diff --git a/src/google/protobuf/BUILD.bazel b/src/google/protobuf/BUILD.bazel index 8212db06e3..373560a501 100644 --- a/src/google/protobuf/BUILD.bazel +++ b/src/google/protobuf/BUILD.bazel @@ -401,6 +401,7 @@ cc_library( "//src/google/protobuf/stubs", "@com_google_absl//absl/base", "@com_google_absl//absl/base:dynamic_annotations", + "@com_google_absl//absl/container:btree", "@com_google_absl//absl/container:flat_hash_map", "@com_google_absl//absl/container:flat_hash_set", "@com_google_absl//absl/hash", @@ -727,6 +728,7 @@ cc_library( ":cc_test_protos", ":lite_test_util", "//src/google/protobuf/testing", + "@com_google_absl//absl/container:flat_hash_map", "@com_google_googletest//:gtest", ], ) @@ -985,6 +987,7 @@ cc_test( ":protobuf", ":test_util", "//src/google/protobuf/stubs", + "@com_google_absl//absl/container:flat_hash_map", "@com_google_absl//absl/strings:str_format", "@com_google_googletest//:gtest", "@com_google_googletest//:gtest_main", @@ -1008,6 +1011,8 @@ cc_test( ":cc_test_protos", ":protobuf", ":test_util", + "@com_google_absl//absl/container:flat_hash_map", + "@com_google_absl//absl/container:flat_hash_set", "@com_google_googletest//:gtest", "@com_google_googletest//:gtest_main", ], diff --git a/src/google/protobuf/descriptor.cc b/src/google/protobuf/descriptor.cc index 1310e2bb70..a90168c2c8 100644 --- a/src/google/protobuf/descriptor.cc +++ b/src/google/protobuf/descriptor.cc @@ -51,6 +51,7 @@ #include "absl/base/call_once.h" #include "absl/base/casts.h" #include "absl/base/dynamic_annotations.h" +#include "absl/container/btree_map.h" #include "absl/container/flat_hash_map.h" #include "absl/container/flat_hash_set.h" #include "absl/hash/hash.h" @@ -1053,7 +1054,7 @@ using EnumValuesByNumberSet = // ordered data structure that implements lower_bound is convenient // for that. using ExtensionsGroupedByDescriptorMap = - std::map, const FieldDescriptor*>; + absl::btree_map, const FieldDescriptor*>; using LocationsByPathMap = absl::flat_hash_map; @@ -1866,7 +1867,7 @@ void DescriptorPool::InternalDontEnforceDependencies() { void DescriptorPool::AddUnusedImportTrackFile(absl::string_view file_name, bool is_error) { - unused_import_track_files_[std::string(file_name)] = is_error; + unused_import_track_files_[file_name] = is_error; } void DescriptorPool::ClearUnusedImportTrackFiles() { @@ -4045,12 +4046,12 @@ class DescriptorBuilder { // This maps the element path of uninterpreted options to the element path // of the resulting interpreted option. This is used to modify a file's // source code info to account for option interpretation. - std::map, std::vector> interpreted_paths_; + absl::flat_hash_map, std::vector> interpreted_paths_; // This maps the path to a repeated option field to the known number of // elements the field contains. This is used to track the compute the // index portion of the element path when interpreting a single option. - std::map, int> repeated_option_counts_; + absl::flat_hash_map, int> repeated_option_counts_; // Factory used to create the dynamic messages we need to parse // any aggregate option values we encounter. @@ -6055,7 +6056,7 @@ void DescriptorBuilder::CheckEnumValueUniqueness( "Enum name %s has the same name as %s if you ignore case and strip " "out the enum name prefix (if any). (If you are using allow_alias, " "please assign the same numeric value to both enums.)", - value->name(), values[stripped]->name()); + value->name(), insert_result.first->second->name()); // There are proto2 enums out there with conflicting names, so to preserve // compatibility we issue only a warning for proto2. if (IsLegacyJsonFieldConflictEnabled(result->options()) && @@ -7111,23 +7112,23 @@ void DescriptorBuilder::ValidateEnumOptions(EnumDescriptor* enm, CheckEnumValueUniqueness(proto, enm); if (!enm->options().has_allow_alias() || !enm->options().allow_alias()) { - std::map used_values; + absl::flat_hash_map used_values; for (int i = 0; i < enm->value_count(); ++i) { const EnumValueDescriptor* enum_value = enm->value(i); - if (used_values.find(enum_value->number()) != used_values.end()) { - std::string error = - "\"" + enum_value->full_name() + - "\" uses the same enum value as \"" + - used_values[enum_value->number()] + + auto insert_result = + used_values.emplace(enum_value->number(), enum_value->full_name()); + bool inserted = insert_result.second; + if (!inserted) { + std::string error = absl::StrCat( + "\"", enum_value->full_name(), "\" uses the same enum value as \"", + insert_result.first->second, "\". If this is intended, set " - "'option allow_alias = true;' to the enum definition."; + "'option allow_alias = true;' to the enum definition."); if (!enm->options().allow_alias()) { // Generate error if duplicated enum values are explicitly disallowed. AddError(enm->full_name(), proto.value(i), DescriptorPool::ErrorCollector::NUMBER, error); } - } else { - used_values[enum_value->number()] = enum_value->full_name(); } } } @@ -7239,18 +7240,18 @@ bool DescriptorBuilder::ValidateMapEntry(FieldDescriptor* field, void DescriptorBuilder::DetectMapConflicts(const Descriptor* message, const DescriptorProto& proto) { - std::map seen_types; + absl::flat_hash_map seen_types; for (int i = 0; i < message->nested_type_count(); ++i) { const Descriptor* nested = message->nested_type(i); - std::pair::iterator, bool> result = - seen_types.insert(std::make_pair(nested->name(), nested)); - if (!result.second) { - if (result.first->second->options().map_entry() || + auto insert_result = seen_types.emplace(nested->name(), nested); + bool inserted = insert_result.second; + if (!inserted) { + if (insert_result.first->second->options().map_entry() || nested->options().map_entry()) { - AddError(message->full_name(), proto, - DescriptorPool::ErrorCollector::NAME, - "Expanded map entry type " + nested->name() + - " conflicts with an existing nested message type."); + AddError( + message->full_name(), proto, DescriptorPool::ErrorCollector::NAME, + absl::StrCat("Expanded map entry type ", nested->name(), + " conflicts with an existing nested message type.")); break; } } @@ -7260,8 +7261,7 @@ void DescriptorBuilder::DetectMapConflicts(const Descriptor* message, // Check for conflicted field names. for (int i = 0; i < message->field_count(); ++i) { const FieldDescriptor* field = message->field(i); - std::map::iterator iter = - seen_types.find(field->name()); + auto iter = seen_types.find(field->name()); if (iter != seen_types.end() && iter->second->options().map_entry()) { AddError(message->full_name(), proto, DescriptorPool::ErrorCollector::NAME, @@ -7272,8 +7272,7 @@ void DescriptorBuilder::DetectMapConflicts(const Descriptor* message, // Check for conflicted enum names. for (int i = 0; i < message->enum_type_count(); ++i) { const EnumDescriptor* enum_desc = message->enum_type(i); - std::map::iterator iter = - seen_types.find(enum_desc->name()); + auto iter = seen_types.find(enum_desc->name()); if (iter != seen_types.end() && iter->second->options().map_entry()) { AddError(message->full_name(), proto, DescriptorPool::ErrorCollector::NAME, @@ -7284,8 +7283,7 @@ void DescriptorBuilder::DetectMapConflicts(const Descriptor* message, // Check for conflicted oneof names. for (int i = 0; i < message->oneof_decl_count(); ++i) { const OneofDescriptor* oneof_desc = message->oneof_decl(i); - std::map::iterator iter = - seen_types.find(oneof_desc->name()); + auto iter = seen_types.find(oneof_desc->name()); if (iter != seen_types.end() && iter->second->options().map_entry()) { AddError(message->full_name(), proto, DescriptorPool::ErrorCollector::NAME, @@ -7683,8 +7681,7 @@ void DescriptorBuilder::OptionInterpreter::UpdateSourceCodeInfo( pathv.push_back(loc->path(j)); } - std::map, std::vector>::iterator entry = - interpreted_paths_.find(pathv); + auto entry = interpreted_paths_.find(pathv); if (entry == interpreted_paths_.end()) { // not a match diff --git a/src/google/protobuf/descriptor.h b/src/google/protobuf/descriptor.h index 9822ca7513..29b071c3c1 100644 --- a/src/google/protobuf/descriptor.h +++ b/src/google/protobuf/descriptor.h @@ -57,7 +57,6 @@ #include #include #include -#include #include #include #include @@ -66,6 +65,7 @@ #include "google/protobuf/stubs/common.h" #include "google/protobuf/port.h" #include "absl/base/call_once.h" +#include "absl/container/flat_hash_map.h" #include "google/protobuf/stubs/logging.h" #include "google/protobuf/stubs/logging.h" #include "absl/strings/string_view.h" @@ -2123,7 +2123,7 @@ class PROTOBUF_EXPORT DescriptorPool { // Set of files to track for unused imports. The bool value when true means // unused imports are treated as errors (and as warnings when false). - std::map unused_import_track_files_; + absl::flat_hash_map unused_import_track_files_; }; diff --git a/src/google/protobuf/descriptor_database.cc b/src/google/protobuf/descriptor_database.cc index ae37a83af0..a809cfb69a 100644 --- a/src/google/protobuf/descriptor_database.cc +++ b/src/google/protobuf/descriptor_database.cc @@ -38,6 +38,7 @@ #include #include +#include "absl/container/btree_set.h" #include "absl/strings/ascii.h" #include "absl/strings/match.h" #include "absl/strings/str_replace.h" @@ -119,7 +120,7 @@ SimpleDescriptorDatabase::~SimpleDescriptorDatabase() {} template bool SimpleDescriptorDatabase::DescriptorIndex::AddFile( const FileDescriptorProto& file, Value value) { - if (!by_name_.insert({file.name(), value}).second) { + if (!by_name_.emplace(file.name(), value).second) { GOOGLE_ABSL_LOG(ERROR) << "File already exists in database: " << file.name(); return false; } @@ -197,7 +198,7 @@ bool IsSubSymbol(absl::string_view sub_symbol, absl::string_view super_symbol) { template bool SimpleDescriptorDatabase::DescriptorIndex::AddSymbol( - const std::string& name, Value value) { + absl::string_view name, Value value) { // We need to make sure not to violate our map invariant. // If the symbol name is invalid it could break our lookup algorithm (which @@ -214,8 +215,7 @@ bool SimpleDescriptorDatabase::DescriptorIndex::AddSymbol( if (iter == by_symbol_.end()) { // Apparently the map is currently empty. Just insert and be done with it. - by_symbol_.insert( - typename std::map::value_type(name, value)); + by_symbol_.try_emplace(name, value); return true; } @@ -246,8 +246,7 @@ bool SimpleDescriptorDatabase::DescriptorIndex::AddSymbol( // Insert the new symbol using the iterator as a hint, the new entry will // appear immediately before the one the iterator is pointing at. - by_symbol_.insert( - iter, typename std::map::value_type(name, value)); + by_symbol_.insert(iter, {std::string(name), value}); return true; } @@ -274,9 +273,9 @@ bool SimpleDescriptorDatabase::DescriptorIndex::AddExtension( // The extension is fully-qualified. We can use it as a lookup key in // the by_symbol_ table. if (!by_extension_ - .insert( - {std::make_pair(field.extendee().substr(1), field.number()), - value}) + .emplace( + std::make_pair(field.extendee().substr(1), field.number()), + value) .second) { GOOGLE_ABSL_LOG(ERROR) << "Extension conflicts with extension already in database: " @@ -322,8 +321,7 @@ Value SimpleDescriptorDatabase::DescriptorIndex::FindExtension( template bool SimpleDescriptorDatabase::DescriptorIndex::FindAllExtensionNumbers( const std::string& containing_type, std::vector* output) { - typename std::map, Value>::const_iterator it = - by_extension_.lower_bound(std::make_pair(containing_type, 0)); + auto it = by_extension_.lower_bound(std::make_pair(containing_type, 0)); bool success = false; for (; it != by_extension_.end() && it->first.first == containing_type; @@ -473,7 +471,7 @@ class EncodedDescriptorDatabase::DescriptorIndex { return a < b.name(index); } }; - std::set by_name_{FileCompare{*this}}; + absl::btree_set by_name_{FileCompare{*this}}; std::vector by_name_flat_; struct SymbolEntry { @@ -530,7 +528,7 @@ class EncodedDescriptorDatabase::DescriptorIndex { return AsString(lhs) < AsString(rhs); } }; - std::set by_symbol_{SymbolCompare{*this}}; + absl::btree_set by_symbol_{SymbolCompare{*this}}; std::vector by_symbol_flat_; struct ExtensionEntry { @@ -557,7 +555,7 @@ class EncodedDescriptorDatabase::DescriptorIndex { return a < std::make_tuple(b.extendee(index), b.extension_number); } }; - std::set by_extension_{ + absl::btree_set by_extension_{ ExtensionCompare{*this}}; std::vector by_extension_flat_; }; @@ -815,7 +813,7 @@ EncodedDescriptorDatabase::DescriptorIndex::FindExtension( } template -static void MergeIntoFlat(std::set* s, std::vector* flat) { +static void MergeIntoFlat(absl::btree_set* s, std::vector* flat) { if (s->empty()) return; std::vector new_flat(s->size() + flat->size()); std::merge(s->begin(), s->end(), flat->begin(), flat->end(), &new_flat[0], diff --git a/src/google/protobuf/descriptor_database.h b/src/google/protobuf/descriptor_database.h index 7a4b0a3cdd..6951bd7ead 100644 --- a/src/google/protobuf/descriptor_database.h +++ b/src/google/protobuf/descriptor_database.h @@ -42,9 +42,11 @@ #include #include +#include "absl/container/btree_map.h" #include "google/protobuf/descriptor.h" #include "google/protobuf/port.h" + // Must be included last. #include "google/protobuf/port_def.inc" @@ -202,7 +204,7 @@ class PROTOBUF_EXPORT SimpleDescriptorDatabase : public DescriptorDatabase { // Helpers to recursively add particular descriptors and all their contents // to the index. bool AddFile(const FileDescriptorProto& file, Value value); - bool AddSymbol(const std::string& name, Value value); + bool AddSymbol(absl::string_view name, Value value); bool AddNestedExtensions(const std::string& filename, const DescriptorProto& message_type, Value value); bool AddExtension(const std::string& filename, @@ -216,9 +218,9 @@ class PROTOBUF_EXPORT SimpleDescriptorDatabase : public DescriptorDatabase { void FindAllFileNames(std::vector* output); private: - std::map by_name_; - std::map by_symbol_; - std::map, Value> by_extension_; + absl::btree_map by_name_; + absl::btree_map by_symbol_; + absl::btree_map, Value> by_extension_; // Invariant: The by_symbol_ map does not contain any symbols which are // prefixes of other symbols in the map. For example, "foo.bar" is a diff --git a/src/google/protobuf/io/printer.cc b/src/google/protobuf/io/printer.cc index f6171f8707..a14220dadf 100644 --- a/src/google/protobuf/io/printer.cc +++ b/src/google/protobuf/io/printer.cc @@ -338,7 +338,7 @@ void Printer::Emit(absl::Span vars, absl::string_view format, absl::optional> Printer::GetSubstitutionRange( absl::string_view varname, PrintOptions opts) { - auto it = substitutions_.find(std::string(varname)); + auto it = substitutions_.find(varname); if (!Validate(it != substitutions_.end(), opts, [varname] { return absl::StrCat("undefined variable in annotation: ", varname); })) { @@ -395,8 +395,9 @@ void Printer::WriteRaw(const char* data, size_t size) { // Fix up empty variables (e.g., "{") that should be annotated as // coming after the indent. for (const std::string& var : line_start_variables_) { - substitutions_[var].first += indent_; - substitutions_[var].second += indent_; + auto& pair = substitutions_[var]; + pair.first += indent_; + pair.second += indent_; } } @@ -747,8 +748,8 @@ void Printer::PrintImpl(absl::string_view format, } if (opts.use_substitution_map) { - auto insertion = substitutions_.emplace( - std::string(var), std::make_pair(range_start, range_end)); + auto insertion = + substitutions_.emplace(var, std::make_pair(range_start, range_end)); if (!insertion.second) { // This variable was used multiple times. diff --git a/src/google/protobuf/io/printer.h b/src/google/protobuf/io/printer.h index 119c35aea5..723ec32112 100644 --- a/src/google/protobuf/io/printer.h +++ b/src/google/protobuf/io/printer.h @@ -40,7 +40,6 @@ #include #include #include -#include #include #include #include @@ -723,7 +722,7 @@ class PROTOBUF_EXPORT Printer { // A map from variable name to [start, end) offsets in the output buffer. // // This stores the data looked up by GetSubstitutionRange(). - std::map> substitutions_; + absl::flat_hash_map> substitutions_; // Keeps track of the keys in `substitutions_` that need to be updated when // indents are inserted. These are keys that refer to the beginning of the // current line. diff --git a/src/google/protobuf/map_field_test.cc b/src/google/protobuf/map_field_test.cc index 1ec6c9bd3a..ee95a41c93 100644 --- a/src/google/protobuf/map_field_test.cc +++ b/src/google/protobuf/map_field_test.cc @@ -143,7 +143,7 @@ class MapFieldBasePrimitiveTest : public testing::TestWithParam { const Descriptor* map_descriptor_; const FieldDescriptor* key_descriptor_; const FieldDescriptor* value_descriptor_; - std::map + absl::flat_hash_map initial_value_map_; // copy of initial values inserted }; diff --git a/src/google/protobuf/map_test.inc b/src/google/protobuf/map_test.inc index bf9d29a52d..67f06a2d92 100644 --- a/src/google/protobuf/map_test.inc +++ b/src/google/protobuf/map_test.inc @@ -37,7 +37,6 @@ #endif // _WIN32 #include -#include #include #include #include @@ -112,12 +111,11 @@ class MapImplTest : public ::testing::Test { ExpectElement(key, value); } - void ExpectElements(const std::map& map) { + void ExpectElements(const absl::flat_hash_map& map) { EXPECT_FALSE(map_.empty()); EXPECT_EQ(map.size(), map_.size()); - for (std::map::const_iterator it = map.begin(); - it != map.end(); ++it) { - ExpectElement(it->first, it->second); + for (const auto& e : map) { + ExpectElement(e.first, e.second); } } @@ -994,14 +992,14 @@ TEST_F(MapImplTest, InsertByIterator) { int32_t value2a = 200; int32_t value2b = 201; - std::map map1; + absl::flat_hash_map map1; map1[key1] = value1a; map1[key2] = value2a; map_.insert(map1.begin(), map1.end()); ExpectElements(map1); - std::map map2; + absl::flat_hash_map map2; map2[key1] = value1b; map2[key2] = value2b; @@ -1103,7 +1101,7 @@ TEST_F(MapImplTest, EraseByIterator) { int32_t value1 = 100; int32_t value2 = 101; - std::map map; + absl::flat_hash_map map; map[key1] = value1; map[key2] = value2; @@ -1139,7 +1137,7 @@ static void CopyConstructorHelper(Arena* arena, Map* m) { int32_t value1 = 100; int32_t value2 = 101; - std::map map; + absl::flat_hash_map map; map[key1] = value1; map[key2] = value2; @@ -1167,7 +1165,7 @@ TEST_F(MapImplTest, IterConstructor) { int32_t value1 = 100; int32_t value2 = 101; - std::map map; + absl::flat_hash_map map; map[key1] = value1; map[key2] = value2; @@ -1184,7 +1182,7 @@ TEST_F(MapImplTest, Assigner) { int32_t value1 = 100; int32_t value2 = 101; - std::map map; + absl::flat_hash_map map; map[key1] = value1; map[key2] = value2; @@ -1212,7 +1210,7 @@ TEST_F(MapImplTest, Assigner) { TEST_F(MapImplTest, Rehash) { const int test_size = 50; - std::map reference_map; + absl::flat_hash_map reference_map; for (int i = 0; i < test_size; i++) { reference_map[i] = i; } @@ -1253,7 +1251,7 @@ TEST_F(MapImplTest, EqualRange) { TEST_F(MapImplTest, ConvertToStdMap) { map_[100] = 101; - std::map std_map(map_.begin(), map_.end()); + absl::flat_hash_map std_map(map_.begin(), map_.end()); EXPECT_EQ(1, std_map.size()); EXPECT_EQ(101, std_map[100]); } @@ -1994,7 +1992,7 @@ TEST_F(MapFieldReflectionTest, RepeatedFieldRefForRegularFields) { { int index = 0; - std::map result; + absl::flat_hash_map result; for (RepeatedFieldRef::iterator it = mf_int32_foreign_message.begin(); it != mf_int32_foreign_message.end(); ++it) { @@ -2008,10 +2006,9 @@ TEST_F(MapFieldReflectionTest, RepeatedFieldRefForRegularFields) { ++index; } EXPECT_EQ(10, index); - for (std::map::const_iterator it = result.begin(); - it != result.end(); ++it) { - EXPECT_EQ(message.map_int32_foreign_message().at(it->first).c(), - it->second.c()); + for (const auto& e : result) { + EXPECT_EQ(message.map_int32_foreign_message().at(e.first).c(), + e.second.c()); } } diff --git a/src/google/protobuf/reflection_tester.cc b/src/google/protobuf/reflection_tester.cc index ca80445014..85c5cce756 100644 --- a/src/google/protobuf/reflection_tester.cc +++ b/src/google/protobuf/reflection_tester.cc @@ -31,6 +31,7 @@ #include "google/protobuf/reflection_tester.h" #include +#include "absl/container/flat_hash_map.h" #include "google/protobuf/map_field.h" #include "google/protobuf/message.h" @@ -888,7 +889,7 @@ void MapReflectionTester::ExpectMapFieldsSetViaReflection( ASSERT_EQ(2, reflection->FieldSize(message, F("map_int32_foreign_message"))); { - std::map map; + absl::flat_hash_map map; map[0] = 0; map[1] = 1; for (int i = 0; i < 2; i++) { @@ -916,7 +917,7 @@ void MapReflectionTester::ExpectMapFieldsSetViaReflection( } } { - std::map map; + absl::flat_hash_map map; map[0] = 0; map[1] = 1; for (int i = 0; i < 2; i++) { @@ -944,7 +945,7 @@ void MapReflectionTester::ExpectMapFieldsSetViaReflection( } } { - std::map map; + absl::flat_hash_map map; map[0] = 0; map[1] = 1; for (int i = 0; i < 2; i++) { @@ -972,7 +973,7 @@ void MapReflectionTester::ExpectMapFieldsSetViaReflection( } } { - std::map map; + absl::flat_hash_map map; map[0] = 0; map[1] = 1; for (int i = 0; i < 2; i++) { @@ -1000,7 +1001,7 @@ void MapReflectionTester::ExpectMapFieldsSetViaReflection( } } { - std::map map; + absl::flat_hash_map map; map[0] = 0; map[1] = 1; for (int i = 0; i < 2; i++) { @@ -1028,7 +1029,7 @@ void MapReflectionTester::ExpectMapFieldsSetViaReflection( } } { - std::map map; + absl::flat_hash_map map; map[0] = 0; map[1] = 1; for (int i = 0; i < 2; i++) { @@ -1056,7 +1057,7 @@ void MapReflectionTester::ExpectMapFieldsSetViaReflection( } } { - std::map map; + absl::flat_hash_map map; map[0] = 0; map[1] = 1; for (int i = 0; i < 2; i++) { @@ -1084,7 +1085,7 @@ void MapReflectionTester::ExpectMapFieldsSetViaReflection( } } { - std::map map; + absl::flat_hash_map map; map[0] = 0; map[1] = 1; for (int i = 0; i < 2; i++) { @@ -1112,7 +1113,7 @@ void MapReflectionTester::ExpectMapFieldsSetViaReflection( } } { - std::map map; + absl::flat_hash_map map; map[0] = 0; map[1] = 1; for (int i = 0; i < 2; i++) { @@ -1141,7 +1142,7 @@ void MapReflectionTester::ExpectMapFieldsSetViaReflection( } } { - std::map map; + absl::flat_hash_map map; map[0] = 0; map[1] = 1; for (int i = 0; i < 2; i++) { @@ -1170,7 +1171,7 @@ void MapReflectionTester::ExpectMapFieldsSetViaReflection( } } { - std::map map; + absl::flat_hash_map map; map[0] = 0.0; map[1] = 1.0; for (int i = 0; i < 2; i++) { @@ -1198,7 +1199,7 @@ void MapReflectionTester::ExpectMapFieldsSetViaReflection( } } { - std::map map; + absl::flat_hash_map map; map[0] = 0.0; map[1] = 1.0; for (int i = 0; i < 2; i++) { @@ -1226,7 +1227,7 @@ void MapReflectionTester::ExpectMapFieldsSetViaReflection( } } { - std::map map; + absl::flat_hash_map map; map[false] = false; map[true] = true; std::vector keys = {false, true}; @@ -1256,7 +1257,7 @@ void MapReflectionTester::ExpectMapFieldsSetViaReflection( } } { - std::map map; + absl::flat_hash_map map; map["0"] = "0"; map["1"] = "1"; std::vector keys = {"0", "1"}; @@ -1286,7 +1287,7 @@ void MapReflectionTester::ExpectMapFieldsSetViaReflection( } } { - std::map map; + absl::flat_hash_map map; map[0] = "0"; map[1] = "1"; for (int i = 0; i < 2; i++) { @@ -1314,7 +1315,7 @@ void MapReflectionTester::ExpectMapFieldsSetViaReflection( } } { - std::map map; + absl::flat_hash_map map; map[0] = map_enum_bar_; map[1] = map_enum_baz_; for (int i = 0; i < 2; i++) { @@ -1342,7 +1343,7 @@ void MapReflectionTester::ExpectMapFieldsSetViaReflection( } } { - std::map map; + absl::flat_hash_map map; map[0] = 0; map[1] = 1; for (int i = 0; i < 2; i++) { @@ -1403,7 +1404,7 @@ void MapReflectionTester::ExpectMapFieldsSetViaReflectionIterator( ASSERT_EQ(2, reflection->FieldSize(*message, F("map_int32_foreign_message"))); { - std::map map; + absl::flat_hash_map map; map[0] = 0; map[1] = 1; int size = 0; @@ -1422,7 +1423,7 @@ void MapReflectionTester::ExpectMapFieldsSetViaReflectionIterator( EXPECT_EQ(size, 2); } { - std::map map; + absl::flat_hash_map map; map[0] = 0; map[1] = 1; for (MapIterator iter = reflection->MapBegin(message, F("map_int64_int64")); @@ -1432,7 +1433,7 @@ void MapReflectionTester::ExpectMapFieldsSetViaReflectionIterator( } } { - std::map map; + absl::flat_hash_map map; map[0] = 0; map[1] = 1; for (MapIterator iter = @@ -1443,7 +1444,7 @@ void MapReflectionTester::ExpectMapFieldsSetViaReflectionIterator( } } { - std::map map; + absl::flat_hash_map map; map[0] = 0; map[1] = 1; for (MapIterator iter = @@ -1454,7 +1455,7 @@ void MapReflectionTester::ExpectMapFieldsSetViaReflectionIterator( } } { - std::map map; + absl::flat_hash_map map; map[0] = 0; map[1] = 1; for (MapIterator iter = @@ -1465,7 +1466,7 @@ void MapReflectionTester::ExpectMapFieldsSetViaReflectionIterator( } } { - std::map map; + absl::flat_hash_map map; map[0] = 0; map[1] = 1; for (MapIterator iter = @@ -1476,7 +1477,7 @@ void MapReflectionTester::ExpectMapFieldsSetViaReflectionIterator( } } { - std::map map; + absl::flat_hash_map map; map[0] = 0; map[1] = 1; for (MapIterator iter = @@ -1488,7 +1489,7 @@ void MapReflectionTester::ExpectMapFieldsSetViaReflectionIterator( } } { - std::map map; + absl::flat_hash_map map; map[0] = 0; map[1] = 1; for (MapIterator iter = @@ -1500,7 +1501,7 @@ void MapReflectionTester::ExpectMapFieldsSetViaReflectionIterator( } } { - std::map map; + absl::flat_hash_map map; map[0] = 0; map[1] = 1; for (MapIterator iter = @@ -1512,7 +1513,7 @@ void MapReflectionTester::ExpectMapFieldsSetViaReflectionIterator( } } { - std::map map; + absl::flat_hash_map map; map[0] = 0.0; map[1] = 1.0; for (MapIterator iter = reflection->MapBegin(message, F("map_int32_float")); @@ -1522,7 +1523,7 @@ void MapReflectionTester::ExpectMapFieldsSetViaReflectionIterator( } } { - std::map map; + absl::flat_hash_map map; map[0] = 0.0; map[1] = 1.0; for (MapIterator iter = @@ -1533,7 +1534,7 @@ void MapReflectionTester::ExpectMapFieldsSetViaReflectionIterator( } } { - std::map map; + absl::flat_hash_map map; map[false] = false; map[true] = true; for (MapIterator iter = reflection->MapBegin(message, F("map_bool_bool")); @@ -1543,7 +1544,7 @@ void MapReflectionTester::ExpectMapFieldsSetViaReflectionIterator( } } { - std::map map; + absl::flat_hash_map map; map["0"] = "0"; map["1"] = "1"; int size = 0; @@ -1563,7 +1564,7 @@ void MapReflectionTester::ExpectMapFieldsSetViaReflectionIterator( EXPECT_EQ(size, 2); } { - std::map map; + absl::flat_hash_map map; map[0] = "0"; map[1] = "1"; for (MapIterator iter = reflection->MapBegin(message, F("map_int32_bytes")); @@ -1573,7 +1574,7 @@ void MapReflectionTester::ExpectMapFieldsSetViaReflectionIterator( } } { - std::map map; + absl::flat_hash_map map; map[0] = map_enum_bar_; map[1] = map_enum_baz_; for (MapIterator iter = reflection->MapBegin(message, F("map_int32_enum")); @@ -1583,7 +1584,7 @@ void MapReflectionTester::ExpectMapFieldsSetViaReflectionIterator( } } { - std::map map; + absl::flat_hash_map map; map[0] = 0; map[1] = 1; int size = 0; diff --git a/src/google/protobuf/testing/BUILD.bazel b/src/google/protobuf/testing/BUILD.bazel index 20e37b6061..399ae0c836 100644 --- a/src/google/protobuf/testing/BUILD.bazel +++ b/src/google/protobuf/testing/BUILD.bazel @@ -1,7 +1,7 @@ # Protobuf testing support. # This package contains testonly utilities used in C++ unit tests. -load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test") +load("@rules_cc//cc:defs.bzl", "cc_library") load("@rules_pkg//:mappings.bzl", "pkg_files", "strip_prefix") load("//build_defs:cpp_opts.bzl", "COPTS", "LINK_OPTS") @@ -25,6 +25,7 @@ cc_library( "//:protobuf_lite", # for ShutdownProtobufLibrary "//src/google/protobuf/io", "//src/google/protobuf/stubs:lite", + "@com_google_absl//absl/container:flat_hash_map", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest", ], diff --git a/src/google/protobuf/testing/googletest.h b/src/google/protobuf/testing/googletest.h index 87c8a4183f..487124b092 100644 --- a/src/google/protobuf/testing/googletest.h +++ b/src/google/protobuf/testing/googletest.h @@ -36,9 +36,9 @@ #include -#include #include +#include "absl/container/flat_hash_map.h" #include "google/protobuf/stubs/common.h" #include "google/protobuf/stubs/logging.h" @@ -92,7 +92,7 @@ class ScopedMemoryLog { const std::vector& GetMessages(LogLevel error); private: - std::map > messages_; + absl::flat_hash_map > messages_; LogHandler* old_handler_; static void HandleLog(LogLevel level, const char* filename, int line, diff --git a/src/google/protobuf/text_format.cc b/src/google/protobuf/text_format.cc index 34f86134fb..951049292b 100644 --- a/src/google/protobuf/text_format.cc +++ b/src/google/protobuf/text_format.cc @@ -2061,7 +2061,7 @@ bool TextFormat::Printer::RegisterFieldValuePrinter( } std::unique_ptr wrapper( new FieldValuePrinterWrapper(nullptr)); - auto pair = custom_printers_.insert(std::make_pair(field, nullptr)); + auto pair = custom_printers_.emplace(field, nullptr); if (pair.second) { wrapper->SetDelegate(printer); pair.first->second = std::move(wrapper); @@ -2076,7 +2076,7 @@ bool TextFormat::Printer::RegisterFieldValuePrinter( if (field == nullptr || printer == nullptr) { return false; } - auto pair = custom_printers_.insert(std::make_pair(field, nullptr)); + auto pair = custom_printers_.emplace(field, nullptr); if (pair.second) { pair.first->second.reset(printer); return true; @@ -2090,8 +2090,7 @@ bool TextFormat::Printer::RegisterMessagePrinter( if (descriptor == nullptr || printer == nullptr) { return false; } - auto pair = - custom_message_printers_.insert(std::make_pair(descriptor, nullptr)); + auto pair = custom_message_printers_.emplace(descriptor, nullptr); if (pair.second) { pair.first->second.reset(printer); return true; diff --git a/src/google/protobuf/text_format.h b/src/google/protobuf/text_format.h index 99bcf2a5c9..4ae9215965 100644 --- a/src/google/protobuf/text_format.h +++ b/src/google/protobuf/text_format.h @@ -39,12 +39,12 @@ #define GOOGLE_PROTOBUF_TEXT_FORMAT_H__ #include -#include #include #include #include #include "google/protobuf/port.h" +#include "absl/container/flat_hash_map.h" #include "absl/strings/string_view.h" #include "google/protobuf/descriptor.h" #include "google/protobuf/message.h" @@ -509,14 +509,13 @@ class PROTOBUF_EXPORT TextFormat { int64_t truncate_string_field_longer_than_; std::unique_ptr default_field_value_printer_; - typedef std::map> - CustomPrinterMap; - CustomPrinterMap custom_printers_; + absl::flat_hash_map> + custom_printers_; - typedef std::map> - CustomMessagePrinterMap; - CustomMessagePrinterMap custom_message_printers_; + absl::flat_hash_map> + custom_message_printers_; const Finder* finder_; }; @@ -610,17 +609,13 @@ class PROTOBUF_EXPORT TextFormat { ParseInfoTree* CreateNested(const FieldDescriptor* field); // Defines the map from the index-th field descriptor to its parse location. - typedef std::map> - LocationMap; - + absl::flat_hash_map> + locations_; // Defines the map from the index-th field descriptor to the nested parse // info tree. - typedef std::map>> - NestedMap; - - LocationMap locations_; - NestedMap nested_; + absl::flat_hash_map>> + nested_; }; // For more control over parsing, use this class. diff --git a/src/google/protobuf/util/BUILD.bazel b/src/google/protobuf/util/BUILD.bazel index 404b346044..1a4dcbad75 100644 --- a/src/google/protobuf/util/BUILD.bazel +++ b/src/google/protobuf/util/BUILD.bazel @@ -50,6 +50,8 @@ cc_library( "//src/google/protobuf", "//src/google/protobuf/io", "//src/google/protobuf/stubs", + "@com_google_absl//absl/container:flat_hash_map", + "@com_google_absl//absl/container:flat_hash_set", ], ) @@ -97,6 +99,8 @@ cc_library( deps = [ "//src/google/protobuf", "//src/google/protobuf/stubs", + "@com_google_absl//absl/container:btree", + "@com_google_absl//absl/memory", ], ) diff --git a/src/google/protobuf/util/field_comparator.h b/src/google/protobuf/util/field_comparator.h index b3479b3c7a..392bc99f74 100644 --- a/src/google/protobuf/util/field_comparator.h +++ b/src/google/protobuf/util/field_comparator.h @@ -34,11 +34,11 @@ #define GOOGLE_PROTOBUF_UTIL_FIELD_COMPARATOR_H__ #include -#include #include #include #include "google/protobuf/stubs/common.h" +#include "absl/container/flat_hash_map.h" #include "google/protobuf/port.h" // Must be included last. @@ -181,9 +181,6 @@ class PROTOBUF_EXPORT SimpleFieldComparator : public FieldComparator { Tolerance(double f, double m) : fraction(f), margin(m) {} }; - // Defines the map to store the tolerances for floating point comparison. - typedef std::map ToleranceMap; - friend class MessageDifferencer; // The following methods get executed when CompareFields is called for the // basic types (instead of submessages). They return true on success. One @@ -257,7 +254,7 @@ class PROTOBUF_EXPORT SimpleFieldComparator : public FieldComparator { // Field-specific float/double tolerances, which override any default for // those particular fields. - ToleranceMap map_tolerance_; + absl::flat_hash_map map_tolerance_; }; // Default field comparison: use the basic implementation of FieldComparator. diff --git a/src/google/protobuf/util/field_mask_util.cc b/src/google/protobuf/util/field_mask_util.cc index c39a053a16..7ec6115a51 100644 --- a/src/google/protobuf/util/field_mask_util.cc +++ b/src/google/protobuf/util/field_mask_util.cc @@ -31,12 +31,14 @@ #include "google/protobuf/util/field_mask_util.h" #include -#include +#include #include #include +#include "absl/container/btree_map.h" #include "google/protobuf/stubs/logging.h" #include "google/protobuf/stubs/logging.h" +#include "absl/memory/memory.h" #include "absl/strings/str_join.h" #include "absl/strings/str_split.h" #include "google/protobuf/message.h" @@ -252,20 +254,17 @@ class FieldMaskTree { private: struct Node { - Node() {} + Node() = default; Node(const Node&) = delete; Node& operator=(const Node&) = delete; ~Node() { ClearChildren(); } void ClearChildren() { - for (auto& p : children) { - delete p.second; - } children.clear(); } - std::map children; + absl::btree_map> children; }; // Merge a sub-tree to mask. This method adds the field paths represented @@ -319,34 +318,33 @@ void FieldMaskTree::MergeToFieldMask(const std::string& prefix, out->add_paths(prefix); return; } - for (std::map::const_iterator it = node->children.begin(); - it != node->children.end(); ++it) { + for (const auto& kv : node->children) { std::string current_path = - prefix.empty() ? it->first : prefix + "." + it->first; - MergeToFieldMask(current_path, it->second, out); + prefix.empty() ? kv.first : absl::StrCat(prefix, ".", kv.first); + MergeToFieldMask(current_path, kv.second.get(), out); } } void FieldMaskTree::AddPath(const std::string& path) { - std::vector parts = absl::StrSplit(path, '.'); + std::vector parts = absl::StrSplit(path, '.'); if (parts.empty()) { return; } bool new_branch = false; Node* node = &root_; - for (const std::string& node_name : parts) { + for (absl::string_view node_name : parts) { if (!new_branch && node != &root_ && node->children.empty()) { // Path matches an existing leaf node. This means the path is already // covered by this tree (for example, adding "foo.bar.baz" to a tree // which already contains "foo.bar"). return; } - Node*& child = node->children[node_name]; + std::unique_ptr& child = node->children[node_name]; if (child == nullptr) { new_branch = true; - child = new Node(); + child = absl::make_unique(); } - node = child; + node = child.get(); } if (!node->children.empty()) { node->ClearChildren(); @@ -361,7 +359,7 @@ void FieldMaskTree::RemovePath(const std::string& path, // code below. return; } - std::vector parts = absl::StrSplit(path, '.'); + std::vector parts = absl::StrSplit(path, '.'); if (parts.empty()) { return; } @@ -389,19 +387,19 @@ void FieldMaskTree::RemovePath(const std::string& path, new_branch_node = node; } for (int j = 0; j < current_descriptor->field_count(); ++j) { - node->children[current_descriptor->field(j)->name()] = new Node(); + node->children[current_descriptor->field(j)->name()] = + absl::make_unique(); } } auto it = node->children.find(parts[i]); if (it == node->children.end()) return; - node = it->second; + node = it->second.get(); if (field_descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { current_descriptor = field_descriptor->message_type(); } } // Remove path. for (int i = parts.size() - 1; i >= 0; i--) { - delete nodes[i]->children[parts[i]]; nodes[i]->children.erase(parts[i]); if (!nodes[i]->children.empty()) { break; @@ -427,7 +425,7 @@ void FieldMaskTree::IntersectPath(const std::string& path, FieldMaskTree* out) { // No intersection found. return; } - node = it->second; + node = it->second.get(); } // Now we found a matching node with the given path. Add all leaf nodes // to out. @@ -439,11 +437,10 @@ void FieldMaskTree::MergeLeafNodesToTree(const std::string& prefix, if (node->children.empty()) { out->AddPath(prefix); } - for (std::map::const_iterator it = node->children.begin(); - it != node->children.end(); ++it) { + for (const auto& kv : node->children) { std::string current_path = - prefix.empty() ? it->first : prefix + "." + it->first; - MergeLeafNodesToTree(current_path, it->second, out); + prefix.empty() ? kv.first : absl::StrCat(prefix, ".", kv.first); + MergeLeafNodesToTree(current_path, kv.second.get(), out); } } @@ -454,10 +451,9 @@ void FieldMaskTree::MergeMessage(const Node* node, const Message& source, const Reflection* source_reflection = source.GetReflection(); const Reflection* destination_reflection = destination->GetReflection(); const Descriptor* descriptor = source.GetDescriptor(); - for (std::map::const_iterator it = node->children.begin(); - it != node->children.end(); ++it) { - const std::string& field_name = it->first; - const Node* child = it->second; + for (const auto& kv : node->children) { + const std::string& field_name = kv.first; + const Node* child = kv.second.get(); const FieldDescriptor* field = descriptor->FindFieldByName(field_name); if (field == nullptr) { GOOGLE_ABSL_LOG(ERROR) << "Cannot find field \"" << field_name @@ -557,10 +553,10 @@ void FieldMaskTree::AddRequiredFieldPath(Node* node, const FieldDescriptor* field = descriptor->field(index); if (field->is_required()) { const std::string& node_name = field->name(); - Node*& child = node->children[node_name]; + std::unique_ptr& child = node->children[node_name]; if (child == nullptr) { // Add required field path to the tree - child = new Node(); + child = absl::make_unique(); } else if (child->children.empty()) { // If the required field is in the tree and does not have any children, // do nothing. @@ -568,15 +564,14 @@ void FieldMaskTree::AddRequiredFieldPath(Node* node, } // Add required field in the children to the tree if the field is message. if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { - AddRequiredFieldPath(child, field->message_type()); + AddRequiredFieldPath(child.get(), field->message_type()); } } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { - std::map::const_iterator it = - node->children.find(field->name()); + auto it = node->children.find(field->name()); if (it != node->children.end()) { // Add required fields in the children to the // tree if the field is a message and present in the tree. - Node* child = it->second; + Node* child = it->second.get(); if (!child->children.empty()) { AddRequiredFieldPath(child, field->message_type()); } @@ -593,8 +588,7 @@ bool FieldMaskTree::TrimMessage(const Node* node, Message* message) { bool modified = false; for (int index = 0; index < field_count; ++index) { const FieldDescriptor* field = descriptor->field(index); - std::map::const_iterator it = - node->children.find(field->name()); + auto it = node->children.find(field->name()); if (it == node->children.end()) { if (field->is_repeated()) { if (reflection->FieldSize(*message, field) != 0) { @@ -608,7 +602,7 @@ bool FieldMaskTree::TrimMessage(const Node* node, Message* message) { reflection->ClearField(message, field); } else { if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { - Node* child = it->second; + Node* child = it->second.get(); if (!child->children.empty() && reflection->HasField(*message, field)) { bool nestedMessageChanged = TrimMessage(child, reflection->MutableMessage(message, field)); diff --git a/src/google/protobuf/util/message_differencer.cc b/src/google/protobuf/util/message_differencer.cc index c8f6cfca47..7aa5eee4c0 100644 --- a/src/google/protobuf/util/message_differencer.cc +++ b/src/google/protobuf/util/message_differencer.cc @@ -50,6 +50,7 @@ #include "google/protobuf/message.h" #include "google/protobuf/text_format.h" #include "absl/container/fixed_array.h" +#include "absl/container/flat_hash_map.h" #include "google/protobuf/stubs/logging.h" #include "google/protobuf/stubs/logging.h" #include "absl/strings/escaping.h" @@ -1449,9 +1450,8 @@ bool MessageDifferencer::IsUnknownFieldIgnored( const MessageDifferencer::MapKeyComparator* MessageDifferencer ::GetMapKeyComparator(const FieldDescriptor* field) const { - if (!field->is_repeated()) return NULL; - FieldKeyComparatorMap::const_iterator it = - map_field_key_comparator_.find(field); + if (!field->is_repeated()) return nullptr; + auto it = map_field_key_comparator_.find(field); if (it != map_field_key_comparator_.end()) { return it->second; } @@ -1460,7 +1460,7 @@ MessageDifferencer ::GetMapKeyComparator(const FieldDescriptor* field) const { // TreatAsSet() call GetMapKeyComparator() and fail if it returns non-NULL. return &map_entry_key_comparator_; } - return NULL; + return nullptr; } namespace { @@ -1764,7 +1764,7 @@ class MaximumMatcher { int count1_; int count2_; NodeMatchCallback match_callback_; - std::map, bool> cached_match_results_; + absl::flat_hash_map, bool> cached_match_results_; std::vector* match_list1_; std::vector* match_list2_; }; @@ -1804,13 +1804,12 @@ int MaximumMatcher::FindMaximumMatch(bool early_return) { bool MaximumMatcher::Match(int left, int right) { std::pair p(left, right); - std::map, bool>::iterator it = - cached_match_results_.find(p); + auto it = cached_match_results_.find(p); if (it != cached_match_results_.end()) { return it->second; } - cached_match_results_[p] = match_callback_(left, right); - return cached_match_results_[p]; + it = cached_match_results_.emplace_hint(it, p, match_callback_(left, right)); + return it->second; } bool MaximumMatcher::FindArgumentPathDFS(int v, std::vector* visited) { diff --git a/src/google/protobuf/util/message_differencer.h b/src/google/protobuf/util/message_differencer.h index bb4d26967d..a3804ade80 100644 --- a/src/google/protobuf/util/message_differencer.h +++ b/src/google/protobuf/util/message_differencer.h @@ -44,9 +44,7 @@ #define GOOGLE_PROTOBUF_UTIL_MESSAGE_DIFFERENCER_H__ #include -#include #include -#include #include #include @@ -55,6 +53,8 @@ #include "google/protobuf/unknown_field_set.h" #include "google/protobuf/stubs/common.h" #include "absl/container/fixed_array.h" +#include "absl/container/flat_hash_map.h" +#include "absl/container/flat_hash_set.h" #include "google/protobuf/stubs/logging.h" #include "google/protobuf/util/field_comparator.h" @@ -934,23 +934,14 @@ class PROTOBUF_EXPORT MessageDifferencer { const FieldDescriptor* field, const RepeatedFieldComparison& new_comparison); - // Defines a map between field descriptors and their MapKeyComparators. - // Used for repeated fields when they are configured as TreatAsMap. - typedef std::map - FieldKeyComparatorMap; - - // Defines a set to store field descriptors. Used for repeated fields when - // they are configured as TreatAsSet. - typedef std::set FieldSet; - typedef std::map FieldMap; - Reporter* reporter_; DefaultFieldComparator default_field_comparator_; MessageFieldComparison message_field_comparison_; Scope scope_; RepeatedFieldComparison repeated_field_comparison_; - FieldMap repeated_field_comparisons_; + absl::flat_hash_map + repeated_field_comparisons_; // Keeps track of MapKeyComparators that are created within // MessageDifferencer. These MapKeyComparators should be deleted // before MessageDifferencer is destroyed. @@ -958,13 +949,14 @@ class PROTOBUF_EXPORT MessageDifferencer { // store the supplied FieldDescriptors directly. Instead, a new // MapKeyComparator is created for comparison purpose. std::vector owned_key_comparators_; - FieldKeyComparatorMap map_field_key_comparator_; + absl::flat_hash_map + map_field_key_comparator_; MapEntryKeyComparator map_entry_key_comparator_; std::vector> ignore_criteria_; // Reused multiple times in RetrieveFields to avoid extra allocations std::vector tmp_message_fields_; - FieldSet ignored_fields_; + absl::flat_hash_set ignored_fields_; union { DefaultFieldComparator* default_impl;