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. 29
      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",
"@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",
],

@ -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<std::pair<const Descriptor*, int>, const FieldDescriptor*>;
absl::btree_map<std::pair<const Descriptor*, int>, const FieldDescriptor*>;
using LocationsByPathMap =
absl::flat_hash_map<std::string, const SourceCodeInfo_Location*>;
@ -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<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
// 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<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
// 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<int, std::string> used_values;
absl::flat_hash_map<int, std::string> 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<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) {
const Descriptor* nested = message->nested_type(i);
std::pair<std::map<std::string, const Descriptor*>::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<std::string, const Descriptor*>::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<std::string, const Descriptor*>::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<std::string, const Descriptor*>::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<int>, std::vector<int>>::iterator entry =
interpreted_paths_.find(pathv);
auto entry = interpreted_paths_.find(pathv);
if (entry == interpreted_paths_.end()) {
// not a match

@ -57,7 +57,6 @@
#include <atomic>
#include <cstdint>
#include <iterator>
#include <map>
#include <memory>
#include <set>
#include <string>
@ -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<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 <utility>
#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 <typename Value>
bool SimpleDescriptorDatabase::DescriptorIndex<Value>::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 <typename Value>
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.
// 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()) {
// Apparently the map is currently empty. Just insert and be done with it.
by_symbol_.insert(
typename std::map<std::string, Value>::value_type(name, value));
by_symbol_.try_emplace(name, value);
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
// appear immediately before the one the iterator is pointing at.
by_symbol_.insert(
iter, typename std::map<std::string, Value>::value_type(name, value));
by_symbol_.insert(iter, {std::string(name), value});
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 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<Value>::FindExtension(
template <typename Value>
bool SimpleDescriptorDatabase::DescriptorIndex<Value>::FindAllExtensionNumbers(
const std::string& containing_type, std::vector<int>* output) {
typename std::map<std::pair<std::string, int>, 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<FileEntry, FileCompare> by_name_{FileCompare{*this}};
absl::btree_set<FileEntry, FileCompare> by_name_{FileCompare{*this}};
std::vector<FileEntry> by_name_flat_;
struct SymbolEntry {
@ -530,7 +528,7 @@ class EncodedDescriptorDatabase::DescriptorIndex {
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_;
struct ExtensionEntry {
@ -557,7 +555,7 @@ class EncodedDescriptorDatabase::DescriptorIndex {
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}};
std::vector<ExtensionEntry> by_extension_flat_;
};
@ -815,7 +813,7 @@ EncodedDescriptorDatabase::DescriptorIndex::FindExtension(
}
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;
std::vector<T> new_flat(s->size() + flat->size());
std::merge(s->begin(), s->end(), flat->begin(), flat->end(), &new_flat[0],

@ -42,9 +42,11 @@
#include <utility>
#include <vector>
#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<std::string>* output);
private:
std::map<std::string, Value> by_name_;
std::map<std::string, Value> by_symbol_;
std::map<std::pair<std::string, int>, Value> by_extension_;
absl::btree_map<std::string, Value> by_name_;
absl::btree_map<std::string, Value> by_symbol_;
absl::btree_map<std::pair<std::string, int>, 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

@ -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::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.

@ -40,7 +40,6 @@
#include <cstddef>
#include <functional>
#include <initializer_list>
#include <map>
#include <string>
#include <type_traits>
#include <utility>
@ -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<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
// indents are inserted. These are keys that refer to the beginning of the
// current line.

@ -143,7 +143,7 @@ class MapFieldBasePrimitiveTest : public testing::TestWithParam<bool> {
const Descriptor* map_descriptor_;
const FieldDescriptor* key_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
};

@ -37,7 +37,6 @@
#endif // _WIN32
#include <algorithm>
#include <map>
#include <memory>
#include <random>
#include <set>
@ -112,12 +111,11 @@ class MapImplTest : public ::testing::Test {
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_EQ(map.size(), map_.size());
for (std::map<int32_t, int32_t>::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<int32_t, int32_t> map1;
absl::flat_hash_map<int32_t, int32_t> map1;
map1[key1] = value1a;
map1[key2] = value2a;
map_.insert(map1.begin(), map1.end());
ExpectElements(map1);
std::map<int32_t, int32_t> map2;
absl::flat_hash_map<int32_t, int32_t> 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<int32_t, int32_t> map;
absl::flat_hash_map<int32_t, int32_t> map;
map[key1] = value1;
map[key2] = value2;
@ -1139,7 +1137,7 @@ static void CopyConstructorHelper(Arena* arena, Map<int32_t, int32_t>* m) {
int32_t value1 = 100;
int32_t value2 = 101;
std::map<int32_t, int32_t> map;
absl::flat_hash_map<int32_t, int32_t> 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<int32_t, int32_t> map;
absl::flat_hash_map<int32_t, int32_t> 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<int32_t, int32_t> map;
absl::flat_hash_map<int32_t, int32_t> 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<int32_t, int32_t> reference_map;
absl::flat_hash_map<int32_t, int32_t> 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<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(101, std_map[100]);
}
@ -1994,7 +1992,7 @@ TEST_F(MapFieldReflectionTest, RepeatedFieldRefForRegularFields) {
{
int index = 0;
std::map<int32_t, ForeignMessage> result;
absl::flat_hash_map<int32_t, ForeignMessage> result;
for (RepeatedFieldRef<Message>::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<int32_t, ForeignMessage>::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());
}
}

@ -31,6 +31,7 @@
#include "google/protobuf/reflection_tester.h"
#include <gtest/gtest.h>
#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<int32_t, int32_t> map;
absl::flat_hash_map<int32_t, int32_t> map;
map[0] = 0;
map[1] = 1;
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[1] = 1;
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[1] = 1;
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[1] = 1;
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[1] = 1;
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[1] = 1;
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[1] = 1;
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[1] = 1;
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[1] = 1;
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[1] = 1;
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[1] = 1.0;
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[1] = 1.0;
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[true] = 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["1"] = "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[1] = "1";
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[1] = map_enum_baz_;
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[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<int32_t, int32_t> map;
absl::flat_hash_map<int32_t, int32_t> map;
map[0] = 0;
map[1] = 1;
int size = 0;
@ -1422,7 +1423,7 @@ void MapReflectionTester::ExpectMapFieldsSetViaReflectionIterator(
EXPECT_EQ(size, 2);
}
{
std::map<int64_t, int64_t> map;
absl::flat_hash_map<int64_t, int64_t> 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<uint32_t, uint32_t> map;
absl::flat_hash_map<uint32_t, uint32_t> map;
map[0] = 0;
map[1] = 1;
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[1] = 1;
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[1] = 1;
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[1] = 1;
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[1] = 1;
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[1] = 1;
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[1] = 1;
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[1] = 1.0;
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[1] = 1.0;
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[true] = true;
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["1"] = "1";
int size = 0;
@ -1563,7 +1564,7 @@ void MapReflectionTester::ExpectMapFieldsSetViaReflectionIterator(
EXPECT_EQ(size, 2);
}
{
std::map<int32_t, std::string> map;
absl::flat_hash_map<int32_t, std::string> 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<int32_t, const EnumValueDescriptor*> map;
absl::flat_hash_map<int32_t, const EnumValueDescriptor*> 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<int32_t, int32_t> map;
absl::flat_hash_map<int32_t, int32_t> map;
map[0] = 0;
map[1] = 1;
int size = 0;

@ -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",
],

@ -36,9 +36,9 @@
#include <gmock/gmock.h>
#include <map>
#include <vector>
#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<std::string>& GetMessages(LogLevel error);
private:
std::map<LogLevel, std::vector<std::string> > messages_;
absl::flat_hash_map<LogLevel, std::vector<std::string> > messages_;
LogHandler* old_handler_;
static void HandleLog(LogLevel level, const char* filename, int line,

@ -2061,7 +2061,7 @@ bool TextFormat::Printer::RegisterFieldValuePrinter(
}
std::unique_ptr<FieldValuePrinterWrapper> 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;

@ -39,12 +39,12 @@
#define GOOGLE_PROTOBUF_TEXT_FORMAT_H__
#include <atomic>
#include <map>
#include <memory>
#include <string>
#include <vector>
#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<const FastFieldValuePrinter> default_field_value_printer_;
typedef std::map<const FieldDescriptor*,
std::unique_ptr<const FastFieldValuePrinter>>
CustomPrinterMap;
CustomPrinterMap custom_printers_;
absl::flat_hash_map<const FieldDescriptor*,
std::unique_ptr<const FastFieldValuePrinter>>
custom_printers_;
typedef std::map<const Descriptor*, std::unique_ptr<const MessagePrinter>>
CustomMessagePrinterMap;
CustomMessagePrinterMap custom_message_printers_;
absl::flat_hash_map<const Descriptor*,
std::unique_ptr<const MessagePrinter>>
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<const FieldDescriptor*, std::vector<ParseLocationRange>>
LocationMap;
absl::flat_hash_map<const FieldDescriptor*, std::vector<ParseLocationRange>>
locations_;
// Defines the map from the index-th field descriptor to the nested parse
// info tree.
typedef std::map<const FieldDescriptor*,
std::vector<std::unique_ptr<ParseInfoTree>>>
NestedMap;
LocationMap locations_;
NestedMap nested_;
absl::flat_hash_map<const FieldDescriptor*,
std::vector<std::unique_ptr<ParseInfoTree>>>
nested_;
};
// For more control over parsing, use this class.

@ -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",
],
)

@ -34,11 +34,11 @@
#define GOOGLE_PROTOBUF_UTIL_FIELD_COMPARATOR_H__
#include <cstdint>
#include <map>
#include <string>
#include <vector>
#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<const FieldDescriptor*, Tolerance> 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<const FieldDescriptor*, Tolerance> map_tolerance_;
};
// Default field comparison: use the basic implementation of FieldComparator.

@ -31,12 +31,14 @@
#include "google/protobuf/util/field_mask_util.h"
#include <cstdint>
#include <map>
#include <memory>
#include <string>
#include <vector>
#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<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
@ -319,34 +318,33 @@ void FieldMaskTree::MergeToFieldMask(const std::string& prefix,
out->add_paths(prefix);
return;
}
for (std::map<std::string, Node*>::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<std::string> parts = absl::StrSplit(path, '.');
std::vector<absl::string_view> 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<Node>& child = node->children[node_name];
if (child == nullptr) {
new_branch = true;
child = new Node();
child = absl::make_unique<Node>();
}
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<std::string> parts = absl::StrSplit(path, '.');
std::vector<absl::string_view> 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<Node>();
}
}
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<std::string, Node*>::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<std::string, Node*>::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<Node>& child = node->children[node_name];
if (child == nullptr) {
// Add required field path to the tree
child = new Node();
child = absl::make_unique<Node>();
} 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<std::string, Node*>::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<std::string, Node*>::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));

@ -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<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_list2_;
};
@ -1804,13 +1804,12 @@ int MaximumMatcher::FindMaximumMatch(bool early_return) {
bool MaximumMatcher::Match(int left, int right) {
std::pair<int, int> p(left, right);
std::map<std::pair<int, int>, 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<bool>* visited) {

@ -44,9 +44,7 @@
#define GOOGLE_PROTOBUF_UTIL_MESSAGE_DIFFERENCER_H__
#include <functional>
#include <map>
#include <memory>
#include <set>
#include <string>
#include <vector>
@ -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<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_;
DefaultFieldComparator default_field_comparator_;
MessageFieldComparison message_field_comparison_;
Scope scope_;
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
// 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<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_;
std::vector<std::unique_ptr<IgnoreCriteria>> ignore_criteria_;
// Reused multiple times in RetrieveFields to avoid extra allocations
std::vector<const FieldDescriptor*> tmp_message_fields_;
FieldSet ignored_fields_;
absl::flat_hash_set<const FieldDescriptor*> ignored_fields_;
union {
DefaultFieldComparator* default_impl;

Loading…
Cancel
Save