Migrate more STL tables to Abseil swiss tables

PiperOrigin-RevId: 497063734
pull/11350/head
Mike Kruskal 2 years ago committed by Copybara-Service
parent 84f51356d7
commit 757b7d179f
  1. 5
      src/google/protobuf/BUILD.bazel
  2. 59
      src/google/protobuf/descriptor.cc
  3. 4
      src/google/protobuf/descriptor.h
  4. 28
      src/google/protobuf/descriptor_database.cc
  5. 10
      src/google/protobuf/descriptor_database.h
  6. 11
      src/google/protobuf/io/printer.cc
  7. 3
      src/google/protobuf/io/printer.h
  8. 2
      src/google/protobuf/map_field_test.cc
  9. 33
      src/google/protobuf/map_test.inc
  10. 67
      src/google/protobuf/reflection_tester.cc
  11. 3
      src/google/protobuf/testing/BUILD.bazel
  12. 4
      src/google/protobuf/testing/googletest.h
  13. 7
      src/google/protobuf/text_format.cc
  14. 25
      src/google/protobuf/text_format.h
  15. 4
      src/google/protobuf/util/BUILD.bazel
  16. 7
      src/google/protobuf/util/field_comparator.h
  17. 68
      src/google/protobuf/util/field_mask_util.cc
  18. 17
      src/google/protobuf/util/message_differencer.cc
  19. 22
      src/google/protobuf/util/message_differencer.h

@ -401,6 +401,7 @@ cc_library(
"//src/google/protobuf/stubs", "//src/google/protobuf/stubs",
"@com_google_absl//absl/base", "@com_google_absl//absl/base",
"@com_google_absl//absl/base:dynamic_annotations", "@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_map",
"@com_google_absl//absl/container:flat_hash_set", "@com_google_absl//absl/container:flat_hash_set",
"@com_google_absl//absl/hash", "@com_google_absl//absl/hash",
@ -727,6 +728,7 @@ cc_library(
":cc_test_protos", ":cc_test_protos",
":lite_test_util", ":lite_test_util",
"//src/google/protobuf/testing", "//src/google/protobuf/testing",
"@com_google_absl//absl/container:flat_hash_map",
"@com_google_googletest//:gtest", "@com_google_googletest//:gtest",
], ],
) )
@ -985,6 +987,7 @@ cc_test(
":protobuf", ":protobuf",
":test_util", ":test_util",
"//src/google/protobuf/stubs", "//src/google/protobuf/stubs",
"@com_google_absl//absl/container:flat_hash_map",
"@com_google_absl//absl/strings:str_format", "@com_google_absl//absl/strings:str_format",
"@com_google_googletest//:gtest", "@com_google_googletest//:gtest",
"@com_google_googletest//:gtest_main", "@com_google_googletest//:gtest_main",
@ -1008,6 +1011,8 @@ cc_test(
":cc_test_protos", ":cc_test_protos",
":protobuf", ":protobuf",
":test_util", ":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",
"@com_google_googletest//:gtest_main", "@com_google_googletest//:gtest_main",
], ],

@ -51,6 +51,7 @@
#include "absl/base/call_once.h" #include "absl/base/call_once.h"
#include "absl/base/casts.h" #include "absl/base/casts.h"
#include "absl/base/dynamic_annotations.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_map.h"
#include "absl/container/flat_hash_set.h" #include "absl/container/flat_hash_set.h"
#include "absl/hash/hash.h" #include "absl/hash/hash.h"
@ -1053,7 +1054,7 @@ using EnumValuesByNumberSet =
// ordered data structure that implements lower_bound is convenient // ordered data structure that implements lower_bound is convenient
// for that. // for that.
using ExtensionsGroupedByDescriptorMap = using ExtensionsGroupedByDescriptorMap =
std::map<std::pair<const Descriptor*, int>, const FieldDescriptor*>; absl::btree_map<std::pair<const Descriptor*, int>, const FieldDescriptor*>;
using LocationsByPathMap = using LocationsByPathMap =
absl::flat_hash_map<std::string, const SourceCodeInfo_Location*>; absl::flat_hash_map<std::string, const SourceCodeInfo_Location*>;
@ -1866,7 +1867,7 @@ void DescriptorPool::InternalDontEnforceDependencies() {
void DescriptorPool::AddUnusedImportTrackFile(absl::string_view file_name, void DescriptorPool::AddUnusedImportTrackFile(absl::string_view file_name,
bool is_error) { bool is_error) {
unused_import_track_files_[std::string(file_name)] = is_error; unused_import_track_files_[file_name] = is_error;
} }
void DescriptorPool::ClearUnusedImportTrackFiles() { void DescriptorPool::ClearUnusedImportTrackFiles() {
@ -4045,12 +4046,12 @@ class DescriptorBuilder {
// This maps the element path of uninterpreted options to the element path // 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 // of the resulting interpreted option. This is used to modify a file's
// source code info to account for option interpretation. // source code info to account for option interpretation.
std::map<std::vector<int>, std::vector<int>> interpreted_paths_; absl::flat_hash_map<std::vector<int>, std::vector<int>> interpreted_paths_;
// This maps the path to a repeated option field to the known number of // 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 // elements the field contains. This is used to track the compute the
// index portion of the element path when interpreting a single option. // index portion of the element path when interpreting a single option.
std::map<std::vector<int>, int> repeated_option_counts_; absl::flat_hash_map<std::vector<int>, int> repeated_option_counts_;
// Factory used to create the dynamic messages we need to parse // Factory used to create the dynamic messages we need to parse
// any aggregate option values we encounter. // 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 " "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, " "out the enum name prefix (if any). (If you are using allow_alias, "
"please assign the same numeric value to both enums.)", "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 // There are proto2 enums out there with conflicting names, so to preserve
// compatibility we issue only a warning for proto2. // compatibility we issue only a warning for proto2.
if (IsLegacyJsonFieldConflictEnabled(result->options()) && if (IsLegacyJsonFieldConflictEnabled(result->options()) &&
@ -7111,23 +7112,23 @@ void DescriptorBuilder::ValidateEnumOptions(EnumDescriptor* enm,
CheckEnumValueUniqueness(proto, enm); CheckEnumValueUniqueness(proto, enm);
if (!enm->options().has_allow_alias() || !enm->options().allow_alias()) { if (!enm->options().has_allow_alias() || !enm->options().allow_alias()) {
std::map<int, std::string> used_values; absl::flat_hash_map<int, std::string> used_values;
for (int i = 0; i < enm->value_count(); ++i) { for (int i = 0; i < enm->value_count(); ++i) {
const EnumValueDescriptor* enum_value = enm->value(i); const EnumValueDescriptor* enum_value = enm->value(i);
if (used_values.find(enum_value->number()) != used_values.end()) { auto insert_result =
std::string error = used_values.emplace(enum_value->number(), enum_value->full_name());
"\"" + enum_value->full_name() + bool inserted = insert_result.second;
"\" uses the same enum value as \"" + if (!inserted) {
used_values[enum_value->number()] + std::string error = absl::StrCat(
"\"", enum_value->full_name(), "\" uses the same enum value as \"",
insert_result.first->second,
"\". If this is intended, set " "\". 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()) { if (!enm->options().allow_alias()) {
// Generate error if duplicated enum values are explicitly disallowed. // Generate error if duplicated enum values are explicitly disallowed.
AddError(enm->full_name(), proto.value(i), AddError(enm->full_name(), proto.value(i),
DescriptorPool::ErrorCollector::NUMBER, error); 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, void DescriptorBuilder::DetectMapConflicts(const Descriptor* message,
const DescriptorProto& proto) { const DescriptorProto& proto) {
std::map<std::string, const Descriptor*> seen_types; absl::flat_hash_map<std::string, const Descriptor*> seen_types;
for (int i = 0; i < message->nested_type_count(); ++i) { for (int i = 0; i < message->nested_type_count(); ++i) {
const Descriptor* nested = message->nested_type(i); const Descriptor* nested = message->nested_type(i);
std::pair<std::map<std::string, const Descriptor*>::iterator, bool> result = auto insert_result = seen_types.emplace(nested->name(), nested);
seen_types.insert(std::make_pair(nested->name(), nested)); bool inserted = insert_result.second;
if (!result.second) { if (!inserted) {
if (result.first->second->options().map_entry() || if (insert_result.first->second->options().map_entry() ||
nested->options().map_entry()) { nested->options().map_entry()) {
AddError(message->full_name(), proto, AddError(
DescriptorPool::ErrorCollector::NAME, message->full_name(), proto, DescriptorPool::ErrorCollector::NAME,
"Expanded map entry type " + nested->name() + absl::StrCat("Expanded map entry type ", nested->name(),
" conflicts with an existing nested message type."); " conflicts with an existing nested message type."));
break; break;
} }
} }
@ -7260,8 +7261,7 @@ void DescriptorBuilder::DetectMapConflicts(const Descriptor* message,
// Check for conflicted field names. // Check for conflicted field names.
for (int i = 0; i < message->field_count(); ++i) { for (int i = 0; i < message->field_count(); ++i) {
const FieldDescriptor* field = message->field(i); const FieldDescriptor* field = message->field(i);
std::map<std::string, const Descriptor*>::iterator iter = auto iter = seen_types.find(field->name());
seen_types.find(field->name());
if (iter != seen_types.end() && iter->second->options().map_entry()) { if (iter != seen_types.end() && iter->second->options().map_entry()) {
AddError(message->full_name(), proto, AddError(message->full_name(), proto,
DescriptorPool::ErrorCollector::NAME, DescriptorPool::ErrorCollector::NAME,
@ -7272,8 +7272,7 @@ void DescriptorBuilder::DetectMapConflicts(const Descriptor* message,
// Check for conflicted enum names. // Check for conflicted enum names.
for (int i = 0; i < message->enum_type_count(); ++i) { for (int i = 0; i < message->enum_type_count(); ++i) {
const EnumDescriptor* enum_desc = message->enum_type(i); const EnumDescriptor* enum_desc = message->enum_type(i);
std::map<std::string, const Descriptor*>::iterator iter = auto iter = seen_types.find(enum_desc->name());
seen_types.find(enum_desc->name());
if (iter != seen_types.end() && iter->second->options().map_entry()) { if (iter != seen_types.end() && iter->second->options().map_entry()) {
AddError(message->full_name(), proto, AddError(message->full_name(), proto,
DescriptorPool::ErrorCollector::NAME, DescriptorPool::ErrorCollector::NAME,
@ -7284,8 +7283,7 @@ void DescriptorBuilder::DetectMapConflicts(const Descriptor* message,
// Check for conflicted oneof names. // Check for conflicted oneof names.
for (int i = 0; i < message->oneof_decl_count(); ++i) { for (int i = 0; i < message->oneof_decl_count(); ++i) {
const OneofDescriptor* oneof_desc = message->oneof_decl(i); const OneofDescriptor* oneof_desc = message->oneof_decl(i);
std::map<std::string, const Descriptor*>::iterator iter = auto iter = seen_types.find(oneof_desc->name());
seen_types.find(oneof_desc->name());
if (iter != seen_types.end() && iter->second->options().map_entry()) { if (iter != seen_types.end() && iter->second->options().map_entry()) {
AddError(message->full_name(), proto, AddError(message->full_name(), proto,
DescriptorPool::ErrorCollector::NAME, DescriptorPool::ErrorCollector::NAME,
@ -7683,8 +7681,7 @@ void DescriptorBuilder::OptionInterpreter::UpdateSourceCodeInfo(
pathv.push_back(loc->path(j)); pathv.push_back(loc->path(j));
} }
std::map<std::vector<int>, std::vector<int>>::iterator entry = auto entry = interpreted_paths_.find(pathv);
interpreted_paths_.find(pathv);
if (entry == interpreted_paths_.end()) { if (entry == interpreted_paths_.end()) {
// not a match // not a match

@ -57,7 +57,6 @@
#include <atomic> #include <atomic>
#include <cstdint> #include <cstdint>
#include <iterator> #include <iterator>
#include <map>
#include <memory> #include <memory>
#include <set> #include <set>
#include <string> #include <string>
@ -66,6 +65,7 @@
#include "google/protobuf/stubs/common.h" #include "google/protobuf/stubs/common.h"
#include "google/protobuf/port.h" #include "google/protobuf/port.h"
#include "absl/base/call_once.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 "google/protobuf/stubs/logging.h" #include "google/protobuf/stubs/logging.h"
#include "absl/strings/string_view.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 // 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). // unused imports are treated as errors (and as warnings when false).
std::map<std::string, bool> unused_import_track_files_; absl::flat_hash_map<std::string, bool> unused_import_track_files_;
}; };

@ -38,6 +38,7 @@
#include <set> #include <set>
#include <utility> #include <utility>
#include "absl/container/btree_set.h"
#include "absl/strings/ascii.h" #include "absl/strings/ascii.h"
#include "absl/strings/match.h" #include "absl/strings/match.h"
#include "absl/strings/str_replace.h" #include "absl/strings/str_replace.h"
@ -119,7 +120,7 @@ SimpleDescriptorDatabase::~SimpleDescriptorDatabase() {}
template <typename Value> template <typename Value>
bool SimpleDescriptorDatabase::DescriptorIndex<Value>::AddFile( bool SimpleDescriptorDatabase::DescriptorIndex<Value>::AddFile(
const FileDescriptorProto& file, Value value) { 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(); GOOGLE_ABSL_LOG(ERROR) << "File already exists in database: " << file.name();
return false; return false;
} }
@ -197,7 +198,7 @@ bool IsSubSymbol(absl::string_view sub_symbol, absl::string_view super_symbol) {
template <typename Value> template <typename Value>
bool SimpleDescriptorDatabase::DescriptorIndex<Value>::AddSymbol( bool SimpleDescriptorDatabase::DescriptorIndex<Value>::AddSymbol(
const std::string& name, Value value) { absl::string_view name, Value value) {
// We need to make sure not to violate our map invariant. // We need to make sure not to violate our map invariant.
// If the symbol name is invalid it could break our lookup algorithm (which // If the symbol name is invalid it could break our lookup algorithm (which
@ -214,8 +215,7 @@ bool SimpleDescriptorDatabase::DescriptorIndex<Value>::AddSymbol(
if (iter == by_symbol_.end()) { if (iter == by_symbol_.end()) {
// Apparently the map is currently empty. Just insert and be done with it. // Apparently the map is currently empty. Just insert and be done with it.
by_symbol_.insert( by_symbol_.try_emplace(name, value);
typename std::map<std::string, Value>::value_type(name, value));
return true; return true;
} }
@ -246,8 +246,7 @@ bool SimpleDescriptorDatabase::DescriptorIndex<Value>::AddSymbol(
// Insert the new symbol using the iterator as a hint, the new entry will // Insert the new symbol using the iterator as a hint, the new entry will
// appear immediately before the one the iterator is pointing at. // appear immediately before the one the iterator is pointing at.
by_symbol_.insert( by_symbol_.insert(iter, {std::string(name), value});
iter, typename std::map<std::string, Value>::value_type(name, value));
return true; return true;
} }
@ -274,9 +273,9 @@ bool SimpleDescriptorDatabase::DescriptorIndex<Value>::AddExtension(
// The extension is fully-qualified. We can use it as a lookup key in // The extension is fully-qualified. We can use it as a lookup key in
// the by_symbol_ table. // the by_symbol_ table.
if (!by_extension_ if (!by_extension_
.insert( .emplace(
{std::make_pair(field.extendee().substr(1), field.number()), std::make_pair(field.extendee().substr(1), field.number()),
value}) value)
.second) { .second) {
GOOGLE_ABSL_LOG(ERROR) GOOGLE_ABSL_LOG(ERROR)
<< "Extension conflicts with extension already in database: " << "Extension conflicts with extension already in database: "
@ -322,8 +321,7 @@ Value SimpleDescriptorDatabase::DescriptorIndex<Value>::FindExtension(
template <typename Value> template <typename Value>
bool SimpleDescriptorDatabase::DescriptorIndex<Value>::FindAllExtensionNumbers( bool SimpleDescriptorDatabase::DescriptorIndex<Value>::FindAllExtensionNumbers(
const std::string& containing_type, std::vector<int>* output) { const std::string& containing_type, std::vector<int>* output) {
typename std::map<std::pair<std::string, int>, Value>::const_iterator it = auto it = by_extension_.lower_bound(std::make_pair(containing_type, 0));
by_extension_.lower_bound(std::make_pair(containing_type, 0));
bool success = false; bool success = false;
for (; it != by_extension_.end() && it->first.first == containing_type; for (; it != by_extension_.end() && it->first.first == containing_type;
@ -473,7 +471,7 @@ class EncodedDescriptorDatabase::DescriptorIndex {
return a < b.name(index); return a < b.name(index);
} }
}; };
std::set<FileEntry, FileCompare> by_name_{FileCompare{*this}}; absl::btree_set<FileEntry, FileCompare> by_name_{FileCompare{*this}};
std::vector<FileEntry> by_name_flat_; std::vector<FileEntry> by_name_flat_;
struct SymbolEntry { struct SymbolEntry {
@ -530,7 +528,7 @@ class EncodedDescriptorDatabase::DescriptorIndex {
return AsString(lhs) < AsString(rhs); return AsString(lhs) < AsString(rhs);
} }
}; };
std::set<SymbolEntry, SymbolCompare> by_symbol_{SymbolCompare{*this}}; absl::btree_set<SymbolEntry, SymbolCompare> by_symbol_{SymbolCompare{*this}};
std::vector<SymbolEntry> by_symbol_flat_; std::vector<SymbolEntry> by_symbol_flat_;
struct ExtensionEntry { struct ExtensionEntry {
@ -557,7 +555,7 @@ class EncodedDescriptorDatabase::DescriptorIndex {
return a < std::make_tuple(b.extendee(index), b.extension_number); return a < std::make_tuple(b.extendee(index), b.extension_number);
} }
}; };
std::set<ExtensionEntry, ExtensionCompare> by_extension_{ absl::btree_set<ExtensionEntry, ExtensionCompare> by_extension_{
ExtensionCompare{*this}}; ExtensionCompare{*this}};
std::vector<ExtensionEntry> by_extension_flat_; std::vector<ExtensionEntry> by_extension_flat_;
}; };
@ -815,7 +813,7 @@ EncodedDescriptorDatabase::DescriptorIndex::FindExtension(
} }
template <typename T, typename Less> template <typename T, typename Less>
static void MergeIntoFlat(std::set<T, Less>* s, std::vector<T>* flat) { static void MergeIntoFlat(absl::btree_set<T, Less>* s, std::vector<T>* flat) {
if (s->empty()) return; if (s->empty()) return;
std::vector<T> new_flat(s->size() + flat->size()); std::vector<T> new_flat(s->size() + flat->size());
std::merge(s->begin(), s->end(), flat->begin(), flat->end(), &new_flat[0], std::merge(s->begin(), s->end(), flat->begin(), flat->end(), &new_flat[0],

@ -42,9 +42,11 @@
#include <utility> #include <utility>
#include <vector> #include <vector>
#include "absl/container/btree_map.h"
#include "google/protobuf/descriptor.h" #include "google/protobuf/descriptor.h"
#include "google/protobuf/port.h" #include "google/protobuf/port.h"
// Must be included last. // Must be included last.
#include "google/protobuf/port_def.inc" #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 // Helpers to recursively add particular descriptors and all their contents
// to the index. // to the index.
bool AddFile(const FileDescriptorProto& file, Value value); 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, bool AddNestedExtensions(const std::string& filename,
const DescriptorProto& message_type, Value value); const DescriptorProto& message_type, Value value);
bool AddExtension(const std::string& filename, bool AddExtension(const std::string& filename,
@ -216,9 +218,9 @@ class PROTOBUF_EXPORT SimpleDescriptorDatabase : public DescriptorDatabase {
void FindAllFileNames(std::vector<std::string>* output); void FindAllFileNames(std::vector<std::string>* output);
private: private:
std::map<std::string, Value> by_name_; absl::btree_map<std::string, Value> by_name_;
std::map<std::string, Value> by_symbol_; absl::btree_map<std::string, Value> by_symbol_;
std::map<std::pair<std::string, int>, Value> by_extension_; absl::btree_map<std::pair<std::string, int>, Value> by_extension_;
// Invariant: The by_symbol_ map does not contain any symbols which are // 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 // prefixes of other symbols in the map. For example, "foo.bar" is a

@ -338,7 +338,7 @@ void Printer::Emit(absl::Span<const Sub> vars, absl::string_view format,
absl::optional<std::pair<size_t, size_t>> Printer::GetSubstitutionRange( absl::optional<std::pair<size_t, size_t>> Printer::GetSubstitutionRange(
absl::string_view varname, PrintOptions opts) { 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] { if (!Validate(it != substitutions_.end(), opts, [varname] {
return absl::StrCat("undefined variable in annotation: ", 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 // Fix up empty variables (e.g., "{") that should be annotated as
// coming after the indent. // coming after the indent.
for (const std::string& var : line_start_variables_) { for (const std::string& var : line_start_variables_) {
substitutions_[var].first += indent_; auto& pair = substitutions_[var];
substitutions_[var].second += indent_; pair.first += indent_;
pair.second += indent_;
} }
} }
@ -747,8 +748,8 @@ void Printer::PrintImpl(absl::string_view format,
} }
if (opts.use_substitution_map) { if (opts.use_substitution_map) {
auto insertion = substitutions_.emplace( auto insertion =
std::string(var), std::make_pair(range_start, range_end)); substitutions_.emplace(var, std::make_pair(range_start, range_end));
if (!insertion.second) { if (!insertion.second) {
// This variable was used multiple times. // This variable was used multiple times.

@ -40,7 +40,6 @@
#include <cstddef> #include <cstddef>
#include <functional> #include <functional>
#include <initializer_list> #include <initializer_list>
#include <map>
#include <string> #include <string>
#include <type_traits> #include <type_traits>
#include <utility> #include <utility>
@ -723,7 +722,7 @@ class PROTOBUF_EXPORT Printer {
// A map from variable name to [start, end) offsets in the output buffer. // A map from variable name to [start, end) offsets in the output buffer.
// //
// This stores the data looked up by GetSubstitutionRange(). // This stores the data looked up by GetSubstitutionRange().
std::map<std::string, std::pair<size_t, size_t>> substitutions_; absl::flat_hash_map<std::string, std::pair<size_t, size_t>> substitutions_;
// Keeps track of the keys in `substitutions_` that need to be updated when // 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 // indents are inserted. These are keys that refer to the beginning of the
// current line. // current line.

@ -143,7 +143,7 @@ class MapFieldBasePrimitiveTest : public testing::TestWithParam<bool> {
const Descriptor* map_descriptor_; const Descriptor* map_descriptor_;
const FieldDescriptor* key_descriptor_; const FieldDescriptor* key_descriptor_;
const FieldDescriptor* value_descriptor_; const FieldDescriptor* value_descriptor_;
std::map<int32_t, int32_t> absl::flat_hash_map<int32_t, int32_t>
initial_value_map_; // copy of initial values inserted initial_value_map_; // copy of initial values inserted
}; };

@ -37,7 +37,6 @@
#endif // _WIN32 #endif // _WIN32
#include <algorithm> #include <algorithm>
#include <map>
#include <memory> #include <memory>
#include <random> #include <random>
#include <set> #include <set>
@ -112,12 +111,11 @@ class MapImplTest : public ::testing::Test {
ExpectElement(key, value); ExpectElement(key, value);
} }
void ExpectElements(const std::map<int32_t, int32_t>& map) { void ExpectElements(const absl::flat_hash_map<int32_t, int32_t>& map) {
EXPECT_FALSE(map_.empty()); EXPECT_FALSE(map_.empty());
EXPECT_EQ(map.size(), map_.size()); EXPECT_EQ(map.size(), map_.size());
for (std::map<int32_t, int32_t>::const_iterator it = map.begin(); for (const auto& e : map) {
it != map.end(); ++it) { ExpectElement(e.first, e.second);
ExpectElement(it->first, it->second);
} }
} }
@ -994,14 +992,14 @@ TEST_F(MapImplTest, InsertByIterator) {
int32_t value2a = 200; int32_t value2a = 200;
int32_t value2b = 201; int32_t value2b = 201;
std::map<int32_t, int32_t> map1; absl::flat_hash_map<int32_t, int32_t> map1;
map1[key1] = value1a; map1[key1] = value1a;
map1[key2] = value2a; map1[key2] = value2a;
map_.insert(map1.begin(), map1.end()); map_.insert(map1.begin(), map1.end());
ExpectElements(map1); ExpectElements(map1);
std::map<int32_t, int32_t> map2; absl::flat_hash_map<int32_t, int32_t> map2;
map2[key1] = value1b; map2[key1] = value1b;
map2[key2] = value2b; map2[key2] = value2b;
@ -1103,7 +1101,7 @@ TEST_F(MapImplTest, EraseByIterator) {
int32_t value1 = 100; int32_t value1 = 100;
int32_t value2 = 101; int32_t value2 = 101;
std::map<int32_t, int32_t> map; absl::flat_hash_map<int32_t, int32_t> map;
map[key1] = value1; map[key1] = value1;
map[key2] = value2; map[key2] = value2;
@ -1139,7 +1137,7 @@ static void CopyConstructorHelper(Arena* arena, Map<int32_t, int32_t>* m) {
int32_t value1 = 100; int32_t value1 = 100;
int32_t value2 = 101; int32_t value2 = 101;
std::map<int32_t, int32_t> map; absl::flat_hash_map<int32_t, int32_t> map;
map[key1] = value1; map[key1] = value1;
map[key2] = value2; map[key2] = value2;
@ -1167,7 +1165,7 @@ TEST_F(MapImplTest, IterConstructor) {
int32_t value1 = 100; int32_t value1 = 100;
int32_t value2 = 101; int32_t value2 = 101;
std::map<int32_t, int32_t> map; absl::flat_hash_map<int32_t, int32_t> map;
map[key1] = value1; map[key1] = value1;
map[key2] = value2; map[key2] = value2;
@ -1184,7 +1182,7 @@ TEST_F(MapImplTest, Assigner) {
int32_t value1 = 100; int32_t value1 = 100;
int32_t value2 = 101; int32_t value2 = 101;
std::map<int32_t, int32_t> map; absl::flat_hash_map<int32_t, int32_t> map;
map[key1] = value1; map[key1] = value1;
map[key2] = value2; map[key2] = value2;
@ -1212,7 +1210,7 @@ TEST_F(MapImplTest, Assigner) {
TEST_F(MapImplTest, Rehash) { TEST_F(MapImplTest, Rehash) {
const int test_size = 50; const int test_size = 50;
std::map<int32_t, int32_t> reference_map; absl::flat_hash_map<int32_t, int32_t> reference_map;
for (int i = 0; i < test_size; i++) { for (int i = 0; i < test_size; i++) {
reference_map[i] = i; reference_map[i] = i;
} }
@ -1253,7 +1251,7 @@ TEST_F(MapImplTest, EqualRange) {
TEST_F(MapImplTest, ConvertToStdMap) { TEST_F(MapImplTest, ConvertToStdMap) {
map_[100] = 101; map_[100] = 101;
std::map<int32_t, int32_t> std_map(map_.begin(), map_.end()); absl::flat_hash_map<int32_t, int32_t> std_map(map_.begin(), map_.end());
EXPECT_EQ(1, std_map.size()); EXPECT_EQ(1, std_map.size());
EXPECT_EQ(101, std_map[100]); EXPECT_EQ(101, std_map[100]);
} }
@ -1994,7 +1992,7 @@ TEST_F(MapFieldReflectionTest, RepeatedFieldRefForRegularFields) {
{ {
int index = 0; int index = 0;
std::map<int32_t, ForeignMessage> result; absl::flat_hash_map<int32_t, ForeignMessage> result;
for (RepeatedFieldRef<Message>::iterator it = for (RepeatedFieldRef<Message>::iterator it =
mf_int32_foreign_message.begin(); mf_int32_foreign_message.begin();
it != mf_int32_foreign_message.end(); ++it) { it != mf_int32_foreign_message.end(); ++it) {
@ -2008,10 +2006,9 @@ TEST_F(MapFieldReflectionTest, RepeatedFieldRefForRegularFields) {
++index; ++index;
} }
EXPECT_EQ(10, index); EXPECT_EQ(10, index);
for (std::map<int32_t, ForeignMessage>::const_iterator it = result.begin(); for (const auto& e : result) {
it != result.end(); ++it) { EXPECT_EQ(message.map_int32_foreign_message().at(e.first).c(),
EXPECT_EQ(message.map_int32_foreign_message().at(it->first).c(), e.second.c());
it->second.c());
} }
} }

@ -31,6 +31,7 @@
#include "google/protobuf/reflection_tester.h" #include "google/protobuf/reflection_tester.h"
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include "absl/container/flat_hash_map.h"
#include "google/protobuf/map_field.h" #include "google/protobuf/map_field.h"
#include "google/protobuf/message.h" #include "google/protobuf/message.h"
@ -888,7 +889,7 @@ void MapReflectionTester::ExpectMapFieldsSetViaReflection(
ASSERT_EQ(2, reflection->FieldSize(message, F("map_int32_foreign_message"))); ASSERT_EQ(2, reflection->FieldSize(message, F("map_int32_foreign_message")));
{ {
std::map<int32_t, int32_t> map; absl::flat_hash_map<int32_t, int32_t> map;
map[0] = 0; map[0] = 0;
map[1] = 1; map[1] = 1;
for (int i = 0; i < 2; i++) { for (int i = 0; i < 2; i++) {
@ -916,7 +917,7 @@ void MapReflectionTester::ExpectMapFieldsSetViaReflection(
} }
} }
{ {
std::map<int64_t, int64_t> map; absl::flat_hash_map<int64_t, int64_t> map;
map[0] = 0; map[0] = 0;
map[1] = 1; map[1] = 1;
for (int i = 0; i < 2; i++) { for (int i = 0; i < 2; i++) {
@ -944,7 +945,7 @@ void MapReflectionTester::ExpectMapFieldsSetViaReflection(
} }
} }
{ {
std::map<uint32_t, uint32_t> map; absl::flat_hash_map<uint32_t, uint32_t> map;
map[0] = 0; map[0] = 0;
map[1] = 1; map[1] = 1;
for (int i = 0; i < 2; i++) { for (int i = 0; i < 2; i++) {
@ -972,7 +973,7 @@ void MapReflectionTester::ExpectMapFieldsSetViaReflection(
} }
} }
{ {
std::map<uint64_t, uint64_t> map; absl::flat_hash_map<uint64_t, uint64_t> map;
map[0] = 0; map[0] = 0;
map[1] = 1; map[1] = 1;
for (int i = 0; i < 2; i++) { for (int i = 0; i < 2; i++) {
@ -1000,7 +1001,7 @@ void MapReflectionTester::ExpectMapFieldsSetViaReflection(
} }
} }
{ {
std::map<int32_t, int32_t> map; absl::flat_hash_map<int32_t, int32_t> map;
map[0] = 0; map[0] = 0;
map[1] = 1; map[1] = 1;
for (int i = 0; i < 2; i++) { for (int i = 0; i < 2; i++) {
@ -1028,7 +1029,7 @@ void MapReflectionTester::ExpectMapFieldsSetViaReflection(
} }
} }
{ {
std::map<int64_t, int64_t> map; absl::flat_hash_map<int64_t, int64_t> map;
map[0] = 0; map[0] = 0;
map[1] = 1; map[1] = 1;
for (int i = 0; i < 2; i++) { for (int i = 0; i < 2; i++) {
@ -1056,7 +1057,7 @@ void MapReflectionTester::ExpectMapFieldsSetViaReflection(
} }
} }
{ {
std::map<uint32_t, uint32_t> map; absl::flat_hash_map<uint32_t, uint32_t> map;
map[0] = 0; map[0] = 0;
map[1] = 1; map[1] = 1;
for (int i = 0; i < 2; i++) { for (int i = 0; i < 2; i++) {
@ -1084,7 +1085,7 @@ void MapReflectionTester::ExpectMapFieldsSetViaReflection(
} }
} }
{ {
std::map<uint64_t, uint64_t> map; absl::flat_hash_map<uint64_t, uint64_t> map;
map[0] = 0; map[0] = 0;
map[1] = 1; map[1] = 1;
for (int i = 0; i < 2; i++) { for (int i = 0; i < 2; i++) {
@ -1112,7 +1113,7 @@ void MapReflectionTester::ExpectMapFieldsSetViaReflection(
} }
} }
{ {
std::map<int32_t, int32_t> map; absl::flat_hash_map<int32_t, int32_t> map;
map[0] = 0; map[0] = 0;
map[1] = 1; map[1] = 1;
for (int i = 0; i < 2; i++) { for (int i = 0; i < 2; i++) {
@ -1141,7 +1142,7 @@ void MapReflectionTester::ExpectMapFieldsSetViaReflection(
} }
} }
{ {
std::map<int64_t, int64_t> map; absl::flat_hash_map<int64_t, int64_t> map;
map[0] = 0; map[0] = 0;
map[1] = 1; map[1] = 1;
for (int i = 0; i < 2; i++) { for (int i = 0; i < 2; i++) {
@ -1170,7 +1171,7 @@ void MapReflectionTester::ExpectMapFieldsSetViaReflection(
} }
} }
{ {
std::map<int32_t, float> map; absl::flat_hash_map<int32_t, float> map;
map[0] = 0.0; map[0] = 0.0;
map[1] = 1.0; map[1] = 1.0;
for (int i = 0; i < 2; i++) { for (int i = 0; i < 2; i++) {
@ -1198,7 +1199,7 @@ void MapReflectionTester::ExpectMapFieldsSetViaReflection(
} }
} }
{ {
std::map<int32_t, double> map; absl::flat_hash_map<int32_t, double> map;
map[0] = 0.0; map[0] = 0.0;
map[1] = 1.0; map[1] = 1.0;
for (int i = 0; i < 2; i++) { for (int i = 0; i < 2; i++) {
@ -1226,7 +1227,7 @@ void MapReflectionTester::ExpectMapFieldsSetViaReflection(
} }
} }
{ {
std::map<bool, bool> map; absl::flat_hash_map<bool, bool> map;
map[false] = false; map[false] = false;
map[true] = true; map[true] = true;
std::vector<bool> keys = {false, true}; std::vector<bool> keys = {false, true};
@ -1256,7 +1257,7 @@ void MapReflectionTester::ExpectMapFieldsSetViaReflection(
} }
} }
{ {
std::map<std::string, std::string> map; absl::flat_hash_map<std::string, std::string> map;
map["0"] = "0"; map["0"] = "0";
map["1"] = "1"; map["1"] = "1";
std::vector<std::string> keys = {"0", "1"}; std::vector<std::string> keys = {"0", "1"};
@ -1286,7 +1287,7 @@ void MapReflectionTester::ExpectMapFieldsSetViaReflection(
} }
} }
{ {
std::map<int32_t, std::string> map; absl::flat_hash_map<int32_t, std::string> map;
map[0] = "0"; map[0] = "0";
map[1] = "1"; map[1] = "1";
for (int i = 0; i < 2; i++) { for (int i = 0; i < 2; i++) {
@ -1314,7 +1315,7 @@ void MapReflectionTester::ExpectMapFieldsSetViaReflection(
} }
} }
{ {
std::map<int32_t, const EnumValueDescriptor*> map; absl::flat_hash_map<int32_t, const EnumValueDescriptor*> map;
map[0] = map_enum_bar_; map[0] = map_enum_bar_;
map[1] = map_enum_baz_; map[1] = map_enum_baz_;
for (int i = 0; i < 2; i++) { for (int i = 0; i < 2; i++) {
@ -1342,7 +1343,7 @@ void MapReflectionTester::ExpectMapFieldsSetViaReflection(
} }
} }
{ {
std::map<int32_t, int32_t> map; absl::flat_hash_map<int32_t, int32_t> map;
map[0] = 0; map[0] = 0;
map[1] = 1; map[1] = 1;
for (int i = 0; i < 2; i++) { 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"))); ASSERT_EQ(2, reflection->FieldSize(*message, F("map_int32_foreign_message")));
{ {
std::map<int32_t, int32_t> map; absl::flat_hash_map<int32_t, int32_t> map;
map[0] = 0; map[0] = 0;
map[1] = 1; map[1] = 1;
int size = 0; int size = 0;
@ -1422,7 +1423,7 @@ void MapReflectionTester::ExpectMapFieldsSetViaReflectionIterator(
EXPECT_EQ(size, 2); EXPECT_EQ(size, 2);
} }
{ {
std::map<int64_t, int64_t> map; absl::flat_hash_map<int64_t, int64_t> map;
map[0] = 0; map[0] = 0;
map[1] = 1; map[1] = 1;
for (MapIterator iter = reflection->MapBegin(message, F("map_int64_int64")); for (MapIterator iter = reflection->MapBegin(message, F("map_int64_int64"));
@ -1432,7 +1433,7 @@ void MapReflectionTester::ExpectMapFieldsSetViaReflectionIterator(
} }
} }
{ {
std::map<uint32_t, uint32_t> map; absl::flat_hash_map<uint32_t, uint32_t> map;
map[0] = 0; map[0] = 0;
map[1] = 1; map[1] = 1;
for (MapIterator iter = for (MapIterator iter =
@ -1443,7 +1444,7 @@ void MapReflectionTester::ExpectMapFieldsSetViaReflectionIterator(
} }
} }
{ {
std::map<uint64_t, uint64_t> map; absl::flat_hash_map<uint64_t, uint64_t> map;
map[0] = 0; map[0] = 0;
map[1] = 1; map[1] = 1;
for (MapIterator iter = for (MapIterator iter =
@ -1454,7 +1455,7 @@ void MapReflectionTester::ExpectMapFieldsSetViaReflectionIterator(
} }
} }
{ {
std::map<int32_t, int32_t> map; absl::flat_hash_map<int32_t, int32_t> map;
map[0] = 0; map[0] = 0;
map[1] = 1; map[1] = 1;
for (MapIterator iter = for (MapIterator iter =
@ -1465,7 +1466,7 @@ void MapReflectionTester::ExpectMapFieldsSetViaReflectionIterator(
} }
} }
{ {
std::map<int64_t, int64_t> map; absl::flat_hash_map<int64_t, int64_t> map;
map[0] = 0; map[0] = 0;
map[1] = 1; map[1] = 1;
for (MapIterator iter = for (MapIterator iter =
@ -1476,7 +1477,7 @@ void MapReflectionTester::ExpectMapFieldsSetViaReflectionIterator(
} }
} }
{ {
std::map<uint32_t, uint32_t> map; absl::flat_hash_map<uint32_t, uint32_t> map;
map[0] = 0; map[0] = 0;
map[1] = 1; map[1] = 1;
for (MapIterator iter = for (MapIterator iter =
@ -1488,7 +1489,7 @@ void MapReflectionTester::ExpectMapFieldsSetViaReflectionIterator(
} }
} }
{ {
std::map<uint64_t, uint64_t> map; absl::flat_hash_map<uint64_t, uint64_t> map;
map[0] = 0; map[0] = 0;
map[1] = 1; map[1] = 1;
for (MapIterator iter = for (MapIterator iter =
@ -1500,7 +1501,7 @@ void MapReflectionTester::ExpectMapFieldsSetViaReflectionIterator(
} }
} }
{ {
std::map<int32_t, int32_t> map; absl::flat_hash_map<int32_t, int32_t> map;
map[0] = 0; map[0] = 0;
map[1] = 1; map[1] = 1;
for (MapIterator iter = for (MapIterator iter =
@ -1512,7 +1513,7 @@ void MapReflectionTester::ExpectMapFieldsSetViaReflectionIterator(
} }
} }
{ {
std::map<int32_t, float> map; absl::flat_hash_map<int32_t, float> map;
map[0] = 0.0; map[0] = 0.0;
map[1] = 1.0; map[1] = 1.0;
for (MapIterator iter = reflection->MapBegin(message, F("map_int32_float")); for (MapIterator iter = reflection->MapBegin(message, F("map_int32_float"));
@ -1522,7 +1523,7 @@ void MapReflectionTester::ExpectMapFieldsSetViaReflectionIterator(
} }
} }
{ {
std::map<int32_t, double> map; absl::flat_hash_map<int32_t, double> map;
map[0] = 0.0; map[0] = 0.0;
map[1] = 1.0; map[1] = 1.0;
for (MapIterator iter = for (MapIterator iter =
@ -1533,7 +1534,7 @@ void MapReflectionTester::ExpectMapFieldsSetViaReflectionIterator(
} }
} }
{ {
std::map<bool, bool> map; absl::flat_hash_map<bool, bool> map;
map[false] = false; map[false] = false;
map[true] = true; map[true] = true;
for (MapIterator iter = reflection->MapBegin(message, F("map_bool_bool")); for (MapIterator iter = reflection->MapBegin(message, F("map_bool_bool"));
@ -1543,7 +1544,7 @@ void MapReflectionTester::ExpectMapFieldsSetViaReflectionIterator(
} }
} }
{ {
std::map<std::string, std::string> map; absl::flat_hash_map<std::string, std::string> map;
map["0"] = "0"; map["0"] = "0";
map["1"] = "1"; map["1"] = "1";
int size = 0; int size = 0;
@ -1563,7 +1564,7 @@ void MapReflectionTester::ExpectMapFieldsSetViaReflectionIterator(
EXPECT_EQ(size, 2); EXPECT_EQ(size, 2);
} }
{ {
std::map<int32_t, std::string> map; absl::flat_hash_map<int32_t, std::string> map;
map[0] = "0"; map[0] = "0";
map[1] = "1"; map[1] = "1";
for (MapIterator iter = reflection->MapBegin(message, F("map_int32_bytes")); for (MapIterator iter = reflection->MapBegin(message, F("map_int32_bytes"));
@ -1573,7 +1574,7 @@ void MapReflectionTester::ExpectMapFieldsSetViaReflectionIterator(
} }
} }
{ {
std::map<int32_t, const EnumValueDescriptor*> map; absl::flat_hash_map<int32_t, const EnumValueDescriptor*> map;
map[0] = map_enum_bar_; map[0] = map_enum_bar_;
map[1] = map_enum_baz_; map[1] = map_enum_baz_;
for (MapIterator iter = reflection->MapBegin(message, F("map_int32_enum")); for (MapIterator iter = reflection->MapBegin(message, F("map_int32_enum"));
@ -1583,7 +1584,7 @@ void MapReflectionTester::ExpectMapFieldsSetViaReflectionIterator(
} }
} }
{ {
std::map<int32_t, int32_t> map; absl::flat_hash_map<int32_t, int32_t> map;
map[0] = 0; map[0] = 0;
map[1] = 1; map[1] = 1;
int size = 0; int size = 0;

@ -1,7 +1,7 @@
# Protobuf testing support. # Protobuf testing support.
# This package contains testonly utilities used in C++ unit tests. # 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("@rules_pkg//:mappings.bzl", "pkg_files", "strip_prefix")
load("//build_defs:cpp_opts.bzl", "COPTS", "LINK_OPTS") load("//build_defs:cpp_opts.bzl", "COPTS", "LINK_OPTS")
@ -25,6 +25,7 @@ cc_library(
"//:protobuf_lite", # for ShutdownProtobufLibrary "//:protobuf_lite", # for ShutdownProtobufLibrary
"//src/google/protobuf/io", "//src/google/protobuf/io",
"//src/google/protobuf/stubs:lite", "//src/google/protobuf/stubs:lite",
"@com_google_absl//absl/container:flat_hash_map",
"@com_google_absl//absl/strings", "@com_google_absl//absl/strings",
"@com_google_googletest//:gtest", "@com_google_googletest//:gtest",
], ],

@ -36,9 +36,9 @@
#include <gmock/gmock.h> #include <gmock/gmock.h>
#include <map>
#include <vector> #include <vector>
#include "absl/container/flat_hash_map.h"
#include "google/protobuf/stubs/common.h" #include "google/protobuf/stubs/common.h"
#include "google/protobuf/stubs/logging.h" #include "google/protobuf/stubs/logging.h"
@ -92,7 +92,7 @@ class ScopedMemoryLog {
const std::vector<std::string>& GetMessages(LogLevel error); const std::vector<std::string>& GetMessages(LogLevel error);
private: private:
std::map<LogLevel, std::vector<std::string> > messages_; absl::flat_hash_map<LogLevel, std::vector<std::string> > messages_;
LogHandler* old_handler_; LogHandler* old_handler_;
static void HandleLog(LogLevel level, const char* filename, int line, static void HandleLog(LogLevel level, const char* filename, int line,

@ -2061,7 +2061,7 @@ bool TextFormat::Printer::RegisterFieldValuePrinter(
} }
std::unique_ptr<FieldValuePrinterWrapper> wrapper( std::unique_ptr<FieldValuePrinterWrapper> wrapper(
new FieldValuePrinterWrapper(nullptr)); new FieldValuePrinterWrapper(nullptr));
auto pair = custom_printers_.insert(std::make_pair(field, nullptr)); auto pair = custom_printers_.emplace(field, nullptr);
if (pair.second) { if (pair.second) {
wrapper->SetDelegate(printer); wrapper->SetDelegate(printer);
pair.first->second = std::move(wrapper); pair.first->second = std::move(wrapper);
@ -2076,7 +2076,7 @@ bool TextFormat::Printer::RegisterFieldValuePrinter(
if (field == nullptr || printer == nullptr) { if (field == nullptr || printer == nullptr) {
return false; return false;
} }
auto pair = custom_printers_.insert(std::make_pair(field, nullptr)); auto pair = custom_printers_.emplace(field, nullptr);
if (pair.second) { if (pair.second) {
pair.first->second.reset(printer); pair.first->second.reset(printer);
return true; return true;
@ -2090,8 +2090,7 @@ bool TextFormat::Printer::RegisterMessagePrinter(
if (descriptor == nullptr || printer == nullptr) { if (descriptor == nullptr || printer == nullptr) {
return false; return false;
} }
auto pair = auto pair = custom_message_printers_.emplace(descriptor, nullptr);
custom_message_printers_.insert(std::make_pair(descriptor, nullptr));
if (pair.second) { if (pair.second) {
pair.first->second.reset(printer); pair.first->second.reset(printer);
return true; return true;

@ -39,12 +39,12 @@
#define GOOGLE_PROTOBUF_TEXT_FORMAT_H__ #define GOOGLE_PROTOBUF_TEXT_FORMAT_H__
#include <atomic> #include <atomic>
#include <map>
#include <memory> #include <memory>
#include <string> #include <string>
#include <vector> #include <vector>
#include "google/protobuf/port.h" #include "google/protobuf/port.h"
#include "absl/container/flat_hash_map.h"
#include "absl/strings/string_view.h" #include "absl/strings/string_view.h"
#include "google/protobuf/descriptor.h" #include "google/protobuf/descriptor.h"
#include "google/protobuf/message.h" #include "google/protobuf/message.h"
@ -509,14 +509,13 @@ class PROTOBUF_EXPORT TextFormat {
int64_t truncate_string_field_longer_than_; int64_t truncate_string_field_longer_than_;
std::unique_ptr<const FastFieldValuePrinter> default_field_value_printer_; std::unique_ptr<const FastFieldValuePrinter> default_field_value_printer_;
typedef std::map<const FieldDescriptor*, absl::flat_hash_map<const FieldDescriptor*,
std::unique_ptr<const FastFieldValuePrinter>> std::unique_ptr<const FastFieldValuePrinter>>
CustomPrinterMap; custom_printers_;
CustomPrinterMap custom_printers_;
typedef std::map<const Descriptor*, std::unique_ptr<const MessagePrinter>> absl::flat_hash_map<const Descriptor*,
CustomMessagePrinterMap; std::unique_ptr<const MessagePrinter>>
CustomMessagePrinterMap custom_message_printers_; custom_message_printers_;
const Finder* finder_; const Finder* finder_;
}; };
@ -610,17 +609,13 @@ class PROTOBUF_EXPORT TextFormat {
ParseInfoTree* CreateNested(const FieldDescriptor* field); ParseInfoTree* CreateNested(const FieldDescriptor* field);
// Defines the map from the index-th field descriptor to its parse location. // Defines the map from the index-th field descriptor to its parse location.
typedef std::map<const FieldDescriptor*, std::vector<ParseLocationRange>> absl::flat_hash_map<const FieldDescriptor*, std::vector<ParseLocationRange>>
LocationMap; locations_;
// Defines the map from the index-th field descriptor to the nested parse // Defines the map from the index-th field descriptor to the nested parse
// info tree. // info tree.
typedef std::map<const FieldDescriptor*, absl::flat_hash_map<const FieldDescriptor*,
std::vector<std::unique_ptr<ParseInfoTree>>> std::vector<std::unique_ptr<ParseInfoTree>>>
NestedMap; nested_;
LocationMap locations_;
NestedMap nested_;
}; };
// For more control over parsing, use this class. // For more control over parsing, use this class.

@ -50,6 +50,8 @@ cc_library(
"//src/google/protobuf", "//src/google/protobuf",
"//src/google/protobuf/io", "//src/google/protobuf/io",
"//src/google/protobuf/stubs", "//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 = [ deps = [
"//src/google/protobuf", "//src/google/protobuf",
"//src/google/protobuf/stubs", "//src/google/protobuf/stubs",
"@com_google_absl//absl/container:btree",
"@com_google_absl//absl/memory",
], ],
) )

@ -34,11 +34,11 @@
#define GOOGLE_PROTOBUF_UTIL_FIELD_COMPARATOR_H__ #define GOOGLE_PROTOBUF_UTIL_FIELD_COMPARATOR_H__
#include <cstdint> #include <cstdint>
#include <map>
#include <string> #include <string>
#include <vector> #include <vector>
#include "google/protobuf/stubs/common.h" #include "google/protobuf/stubs/common.h"
#include "absl/container/flat_hash_map.h"
#include "google/protobuf/port.h" #include "google/protobuf/port.h"
// Must be included last. // Must be included last.
@ -181,9 +181,6 @@ class PROTOBUF_EXPORT SimpleFieldComparator : public FieldComparator {
Tolerance(double f, double m) : fraction(f), margin(m) {} Tolerance(double f, double m) : fraction(f), margin(m) {}
}; };
// Defines the map to store the tolerances for floating point comparison.
typedef std::map<const FieldDescriptor*, Tolerance> ToleranceMap;
friend class MessageDifferencer; friend class MessageDifferencer;
// The following methods get executed when CompareFields is called for the // The following methods get executed when CompareFields is called for the
// basic types (instead of submessages). They return true on success. One // 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 // Field-specific float/double tolerances, which override any default for
// those particular fields. // those particular fields.
ToleranceMap map_tolerance_; absl::flat_hash_map<const FieldDescriptor*, Tolerance> map_tolerance_;
}; };
// Default field comparison: use the basic implementation of FieldComparator. // Default field comparison: use the basic implementation of FieldComparator.

@ -31,12 +31,14 @@
#include "google/protobuf/util/field_mask_util.h" #include "google/protobuf/util/field_mask_util.h"
#include <cstdint> #include <cstdint>
#include <map> #include <memory>
#include <string> #include <string>
#include <vector> #include <vector>
#include "absl/container/btree_map.h"
#include "google/protobuf/stubs/logging.h" #include "google/protobuf/stubs/logging.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_join.h"
#include "absl/strings/str_split.h" #include "absl/strings/str_split.h"
#include "google/protobuf/message.h" #include "google/protobuf/message.h"
@ -252,20 +254,17 @@ class FieldMaskTree {
private: private:
struct Node { struct Node {
Node() {} Node() = default;
Node(const Node&) = delete; Node(const Node&) = delete;
Node& operator=(const Node&) = delete; Node& operator=(const Node&) = delete;
~Node() { ClearChildren(); } ~Node() { ClearChildren(); }
void ClearChildren() { void ClearChildren() {
for (auto& p : children) {
delete p.second;
}
children.clear(); children.clear();
} }
std::map<std::string, Node*> children; absl::btree_map<std::string, std::unique_ptr<Node>> children;
}; };
// Merge a sub-tree to mask. This method adds the field paths represented // 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); out->add_paths(prefix);
return; return;
} }
for (std::map<std::string, Node*>::const_iterator it = node->children.begin(); for (const auto& kv : node->children) {
it != node->children.end(); ++it) {
std::string current_path = std::string current_path =
prefix.empty() ? it->first : prefix + "." + it->first; prefix.empty() ? kv.first : absl::StrCat(prefix, ".", kv.first);
MergeToFieldMask(current_path, it->second, out); MergeToFieldMask(current_path, kv.second.get(), out);
} }
} }
void FieldMaskTree::AddPath(const std::string& path) { void FieldMaskTree::AddPath(const std::string& path) {
std::vector<std::string> parts = absl::StrSplit(path, '.'); std::vector<absl::string_view> parts = absl::StrSplit(path, '.');
if (parts.empty()) { if (parts.empty()) {
return; return;
} }
bool new_branch = false; bool new_branch = false;
Node* node = &root_; 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()) { if (!new_branch && node != &root_ && node->children.empty()) {
// Path matches an existing leaf node. This means the path is already // 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 // covered by this tree (for example, adding "foo.bar.baz" to a tree
// which already contains "foo.bar"). // which already contains "foo.bar").
return; return;
} }
Node*& child = node->children[node_name]; std::unique_ptr<Node>& child = node->children[node_name];
if (child == nullptr) { if (child == nullptr) {
new_branch = true; new_branch = true;
child = new Node(); child = absl::make_unique<Node>();
} }
node = child; node = child.get();
} }
if (!node->children.empty()) { if (!node->children.empty()) {
node->ClearChildren(); node->ClearChildren();
@ -361,7 +359,7 @@ void FieldMaskTree::RemovePath(const std::string& path,
// code below. // code below.
return; return;
} }
std::vector<std::string> parts = absl::StrSplit(path, '.'); std::vector<absl::string_view> parts = absl::StrSplit(path, '.');
if (parts.empty()) { if (parts.empty()) {
return; return;
} }
@ -389,19 +387,19 @@ void FieldMaskTree::RemovePath(const std::string& path,
new_branch_node = node; new_branch_node = node;
} }
for (int j = 0; j < current_descriptor->field_count(); ++j) { 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<Node>();
} }
} }
auto it = node->children.find(parts[i]); auto it = node->children.find(parts[i]);
if (it == node->children.end()) return; if (it == node->children.end()) return;
node = it->second; node = it->second.get();
if (field_descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { if (field_descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
current_descriptor = field_descriptor->message_type(); current_descriptor = field_descriptor->message_type();
} }
} }
// Remove path. // Remove path.
for (int i = parts.size() - 1; i >= 0; i--) { for (int i = parts.size() - 1; i >= 0; i--) {
delete nodes[i]->children[parts[i]];
nodes[i]->children.erase(parts[i]); nodes[i]->children.erase(parts[i]);
if (!nodes[i]->children.empty()) { if (!nodes[i]->children.empty()) {
break; break;
@ -427,7 +425,7 @@ void FieldMaskTree::IntersectPath(const std::string& path, FieldMaskTree* out) {
// No intersection found. // No intersection found.
return; return;
} }
node = it->second; node = it->second.get();
} }
// Now we found a matching node with the given path. Add all leaf nodes // Now we found a matching node with the given path. Add all leaf nodes
// to out. // to out.
@ -439,11 +437,10 @@ void FieldMaskTree::MergeLeafNodesToTree(const std::string& prefix,
if (node->children.empty()) { if (node->children.empty()) {
out->AddPath(prefix); out->AddPath(prefix);
} }
for (std::map<std::string, Node*>::const_iterator it = node->children.begin(); for (const auto& kv : node->children) {
it != node->children.end(); ++it) {
std::string current_path = std::string current_path =
prefix.empty() ? it->first : prefix + "." + it->first; prefix.empty() ? kv.first : absl::StrCat(prefix, ".", kv.first);
MergeLeafNodesToTree(current_path, it->second, out); 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* source_reflection = source.GetReflection();
const Reflection* destination_reflection = destination->GetReflection(); const Reflection* destination_reflection = destination->GetReflection();
const Descriptor* descriptor = source.GetDescriptor(); const Descriptor* descriptor = source.GetDescriptor();
for (std::map<std::string, Node*>::const_iterator it = node->children.begin(); for (const auto& kv : node->children) {
it != node->children.end(); ++it) { const std::string& field_name = kv.first;
const std::string& field_name = it->first; const Node* child = kv.second.get();
const Node* child = it->second;
const FieldDescriptor* field = descriptor->FindFieldByName(field_name); const FieldDescriptor* field = descriptor->FindFieldByName(field_name);
if (field == nullptr) { if (field == nullptr) {
GOOGLE_ABSL_LOG(ERROR) << "Cannot find field \"" << field_name GOOGLE_ABSL_LOG(ERROR) << "Cannot find field \"" << field_name
@ -557,10 +553,10 @@ void FieldMaskTree::AddRequiredFieldPath(Node* node,
const FieldDescriptor* field = descriptor->field(index); const FieldDescriptor* field = descriptor->field(index);
if (field->is_required()) { if (field->is_required()) {
const std::string& node_name = field->name(); const std::string& node_name = field->name();
Node*& child = node->children[node_name]; std::unique_ptr<Node>& child = node->children[node_name];
if (child == nullptr) { if (child == nullptr) {
// Add required field path to the tree // Add required field path to the tree
child = new Node(); child = absl::make_unique<Node>();
} else if (child->children.empty()) { } else if (child->children.empty()) {
// If the required field is in the tree and does not have any children, // If the required field is in the tree and does not have any children,
// do nothing. // 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. // Add required field in the children to the tree if the field is message.
if (field->cpp_type() == FieldDescriptor::CPPTYPE_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) { } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
std::map<std::string, Node*>::const_iterator it = auto it = node->children.find(field->name());
node->children.find(field->name());
if (it != node->children.end()) { if (it != node->children.end()) {
// Add required fields in the children to the // Add required fields in the children to the
// tree if the field is a message and present in the tree. // 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()) { if (!child->children.empty()) {
AddRequiredFieldPath(child, field->message_type()); AddRequiredFieldPath(child, field->message_type());
} }
@ -593,8 +588,7 @@ bool FieldMaskTree::TrimMessage(const Node* node, Message* message) {
bool modified = false; bool modified = false;
for (int index = 0; index < field_count; ++index) { for (int index = 0; index < field_count; ++index) {
const FieldDescriptor* field = descriptor->field(index); const FieldDescriptor* field = descriptor->field(index);
std::map<std::string, Node*>::const_iterator it = auto it = node->children.find(field->name());
node->children.find(field->name());
if (it == node->children.end()) { if (it == node->children.end()) {
if (field->is_repeated()) { if (field->is_repeated()) {
if (reflection->FieldSize(*message, field) != 0) { if (reflection->FieldSize(*message, field) != 0) {
@ -608,7 +602,7 @@ bool FieldMaskTree::TrimMessage(const Node* node, Message* message) {
reflection->ClearField(message, field); reflection->ClearField(message, field);
} else { } else {
if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
Node* child = it->second; Node* child = it->second.get();
if (!child->children.empty() && reflection->HasField(*message, field)) { if (!child->children.empty() && reflection->HasField(*message, field)) {
bool nestedMessageChanged = bool nestedMessageChanged =
TrimMessage(child, reflection->MutableMessage(message, field)); TrimMessage(child, reflection->MutableMessage(message, field));

@ -50,6 +50,7 @@
#include "google/protobuf/message.h" #include "google/protobuf/message.h"
#include "google/protobuf/text_format.h" #include "google/protobuf/text_format.h"
#include "absl/container/fixed_array.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 "google/protobuf/stubs/logging.h" #include "google/protobuf/stubs/logging.h"
#include "absl/strings/escaping.h" #include "absl/strings/escaping.h"
@ -1449,9 +1450,8 @@ bool MessageDifferencer::IsUnknownFieldIgnored(
const MessageDifferencer::MapKeyComparator* const MessageDifferencer::MapKeyComparator*
MessageDifferencer ::GetMapKeyComparator(const FieldDescriptor* field) const { MessageDifferencer ::GetMapKeyComparator(const FieldDescriptor* field) const {
if (!field->is_repeated()) return NULL; if (!field->is_repeated()) return nullptr;
FieldKeyComparatorMap::const_iterator it = auto it = map_field_key_comparator_.find(field);
map_field_key_comparator_.find(field);
if (it != map_field_key_comparator_.end()) { if (it != map_field_key_comparator_.end()) {
return it->second; return it->second;
} }
@ -1460,7 +1460,7 @@ MessageDifferencer ::GetMapKeyComparator(const FieldDescriptor* field) const {
// TreatAsSet() call GetMapKeyComparator() and fail if it returns non-NULL. // TreatAsSet() call GetMapKeyComparator() and fail if it returns non-NULL.
return &map_entry_key_comparator_; return &map_entry_key_comparator_;
} }
return NULL; return nullptr;
} }
namespace { namespace {
@ -1764,7 +1764,7 @@ class MaximumMatcher {
int count1_; int count1_;
int count2_; int count2_;
NodeMatchCallback match_callback_; NodeMatchCallback match_callback_;
std::map<std::pair<int, int>, bool> cached_match_results_; absl::flat_hash_map<std::pair<int, int>, bool> cached_match_results_;
std::vector<int>* match_list1_; std::vector<int>* match_list1_;
std::vector<int>* match_list2_; std::vector<int>* match_list2_;
}; };
@ -1804,13 +1804,12 @@ int MaximumMatcher::FindMaximumMatch(bool early_return) {
bool MaximumMatcher::Match(int left, int right) { bool MaximumMatcher::Match(int left, int right) {
std::pair<int, int> p(left, right); std::pair<int, int> p(left, right);
std::map<std::pair<int, int>, bool>::iterator it = auto it = cached_match_results_.find(p);
cached_match_results_.find(p);
if (it != cached_match_results_.end()) { if (it != cached_match_results_.end()) {
return it->second; return it->second;
} }
cached_match_results_[p] = match_callback_(left, right); it = cached_match_results_.emplace_hint(it, p, match_callback_(left, right));
return cached_match_results_[p]; return it->second;
} }
bool MaximumMatcher::FindArgumentPathDFS(int v, std::vector<bool>* visited) { bool MaximumMatcher::FindArgumentPathDFS(int v, std::vector<bool>* visited) {

@ -44,9 +44,7 @@
#define GOOGLE_PROTOBUF_UTIL_MESSAGE_DIFFERENCER_H__ #define GOOGLE_PROTOBUF_UTIL_MESSAGE_DIFFERENCER_H__
#include <functional> #include <functional>
#include <map>
#include <memory> #include <memory>
#include <set>
#include <string> #include <string>
#include <vector> #include <vector>
@ -55,6 +53,8 @@
#include "google/protobuf/unknown_field_set.h" #include "google/protobuf/unknown_field_set.h"
#include "google/protobuf/stubs/common.h" #include "google/protobuf/stubs/common.h"
#include "absl/container/fixed_array.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/stubs/logging.h"
#include "google/protobuf/util/field_comparator.h" #include "google/protobuf/util/field_comparator.h"
@ -934,23 +934,14 @@ class PROTOBUF_EXPORT MessageDifferencer {
const FieldDescriptor* field, const FieldDescriptor* field,
const RepeatedFieldComparison& new_comparison); 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<const FieldDescriptor*, const MapKeyComparator*>
FieldKeyComparatorMap;
// Defines a set to store field descriptors. Used for repeated fields when
// they are configured as TreatAsSet.
typedef std::set<const FieldDescriptor*> FieldSet;
typedef std::map<const FieldDescriptor*, RepeatedFieldComparison> FieldMap;
Reporter* reporter_; Reporter* reporter_;
DefaultFieldComparator default_field_comparator_; DefaultFieldComparator default_field_comparator_;
MessageFieldComparison message_field_comparison_; MessageFieldComparison message_field_comparison_;
Scope scope_; Scope scope_;
RepeatedFieldComparison repeated_field_comparison_; RepeatedFieldComparison repeated_field_comparison_;
FieldMap repeated_field_comparisons_; absl::flat_hash_map<const FieldDescriptor*, RepeatedFieldComparison>
repeated_field_comparisons_;
// Keeps track of MapKeyComparators that are created within // Keeps track of MapKeyComparators that are created within
// MessageDifferencer. These MapKeyComparators should be deleted // MessageDifferencer. These MapKeyComparators should be deleted
// before MessageDifferencer is destroyed. // before MessageDifferencer is destroyed.
@ -958,13 +949,14 @@ class PROTOBUF_EXPORT MessageDifferencer {
// store the supplied FieldDescriptors directly. Instead, a new // store the supplied FieldDescriptors directly. Instead, a new
// MapKeyComparator is created for comparison purpose. // MapKeyComparator is created for comparison purpose.
std::vector<MapKeyComparator*> owned_key_comparators_; std::vector<MapKeyComparator*> owned_key_comparators_;
FieldKeyComparatorMap map_field_key_comparator_; absl::flat_hash_map<const FieldDescriptor*, const MapKeyComparator*>
map_field_key_comparator_;
MapEntryKeyComparator map_entry_key_comparator_; MapEntryKeyComparator map_entry_key_comparator_;
std::vector<std::unique_ptr<IgnoreCriteria>> ignore_criteria_; std::vector<std::unique_ptr<IgnoreCriteria>> ignore_criteria_;
// Reused multiple times in RetrieveFields to avoid extra allocations // Reused multiple times in RetrieveFields to avoid extra allocations
std::vector<const FieldDescriptor*> tmp_message_fields_; std::vector<const FieldDescriptor*> tmp_message_fields_;
FieldSet ignored_fields_; absl::flat_hash_set<const FieldDescriptor*> ignored_fields_;
union { union {
DefaultFieldComparator* default_impl; DefaultFieldComparator* default_impl;

Loading…
Cancel
Save