protobuf/src/google/protobuf/util/message_differencer.cc
Go to the documentation of this file.
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 // https://developers.google.com/protocol-buffers/
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 // * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 // * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
14 // distribution.
15 // * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 
31 // Author: jschorr@google.com (Joseph Schorr)
32 // Based on original Protocol Buffers design by
33 // Sanjay Ghemawat, Jeff Dean, and others.
34 
35 #include <google/protobuf/util/message_differencer.h>
36 
37 #include <algorithm>
38 #include <cstddef>
39 #include <cstdint>
40 #include <functional>
41 #include <limits>
42 #include <memory>
43 #include <utility>
44 
45 #include <google/protobuf/stubs/logging.h>
46 #include <google/protobuf/stubs/common.h>
47 #include <google/protobuf/stubs/stringprintf.h>
48 #include <google/protobuf/io/printer.h>
49 #include <google/protobuf/io/zero_copy_stream.h>
50 #include <google/protobuf/io/zero_copy_stream_impl.h>
51 #include <google/protobuf/descriptor.pb.h>
52 #include <google/protobuf/descriptor.h>
53 #include <google/protobuf/dynamic_message.h>
54 #include <google/protobuf/generated_enum_reflection.h>
55 #include <google/protobuf/map_field.h>
56 #include <google/protobuf/message.h>
57 #include <google/protobuf/text_format.h>
58 #include <google/protobuf/util/field_comparator.h>
59 #include <google/protobuf/stubs/strutil.h>
60 
61 // Always include as last one, otherwise it can break compilation
62 #include <google/protobuf/port_def.inc>
63 
64 namespace google {
65 namespace protobuf {
66 
67 namespace util {
68 
69 // A reporter to report the total number of diffs.
70 // TODO(ykzhu): we can improve this to take into account the value differencers.
71 class NumDiffsReporter : public google::protobuf::util::MessageDifferencer::Reporter {
72  public:
74 
75  // Returns the total number of diffs.
76  int32_t GetNumDiffs() const { return num_diffs_; }
77  void Reset() { num_diffs_ = 0; }
78 
79  // Report that a field has been added into Message2.
81  const google::protobuf::Message& /* message1 */,
82  const google::protobuf::Message& /* message2 */,
83  const std::vector<google::protobuf::util::MessageDifferencer::SpecificField>&
84  /*field_path*/) override {
85  ++num_diffs_;
86  }
87 
88  // Report that a field has been deleted from Message1.
90  const google::protobuf::Message& /* message1 */,
91  const google::protobuf::Message& /* message2 */,
92  const std::vector<google::protobuf::util::MessageDifferencer::SpecificField>&
93  /*field_path*/) override {
94  ++num_diffs_;
95  }
96 
97  // Report that the value of a field has been modified.
99  const google::protobuf::Message& /* message1 */,
100  const google::protobuf::Message& /* message2 */,
101  const std::vector<google::protobuf::util::MessageDifferencer::SpecificField>&
102  /*field_path*/) override {
103  ++num_diffs_;
104  }
105 
106  private:
108 };
109 
110 // When comparing a repeated field as map, MultipleFieldMapKeyComparator can
111 // be used to specify multiple fields as key for key comparison.
112 // Two elements of a repeated field will be regarded as having the same key
113 // iff they have the same value for every specified key field.
114 // Note that you can also specify only one field as key.
117  public:
119  MessageDifferencer* message_differencer,
120  const std::vector<std::vector<const FieldDescriptor*> >& key_field_paths)
121  : message_differencer_(message_differencer),
122  key_field_paths_(key_field_paths) {
123  GOOGLE_CHECK(!key_field_paths_.empty());
124  for (const auto& path : key_field_paths_) {
125  GOOGLE_CHECK(!path.empty());
126  }
127  }
129  const FieldDescriptor* key)
130  : message_differencer_(message_differencer) {
131  std::vector<const FieldDescriptor*> key_field_path;
132  key_field_path.push_back(key);
133  key_field_paths_.push_back(key_field_path);
134  }
135  bool IsMatch(const Message& message1, const Message& message2,
136  const std::vector<SpecificField>& parent_fields) const override {
137  for (const auto& path : key_field_paths_) {
138  if (!IsMatchInternal(message1, message2, parent_fields, path, 0)) {
139  return false;
140  }
141  }
142  return true;
143  }
144 
145  private:
147  const Message& message1, const Message& message2,
148  const std::vector<SpecificField>& parent_fields,
149  const std::vector<const FieldDescriptor*>& key_field_path,
150  int path_index) const {
151  const FieldDescriptor* field = key_field_path[path_index];
152  std::vector<SpecificField> current_parent_fields(parent_fields);
153  if (path_index == static_cast<int64_t>(key_field_path.size() - 1)) {
154  if (field->is_map()) {
155  return message_differencer_->CompareMapField(message1, message2, field,
156  &current_parent_fields);
157  } else if (field->is_repeated()) {
159  message1, message2, field, &current_parent_fields);
160  } else {
162  message1, message2, field, -1, -1, &current_parent_fields);
163  }
164  } else {
165  const Reflection* reflection1 = message1.GetReflection();
166  const Reflection* reflection2 = message2.GetReflection();
167  bool has_field1 = reflection1->HasField(message1, field);
168  bool has_field2 = reflection2->HasField(message2, field);
169  if (!has_field1 && !has_field2) {
170  return true;
171  }
172  if (has_field1 != has_field2) {
173  return false;
174  }
175  SpecificField specific_field;
176  specific_field.field = field;
177  current_parent_fields.push_back(specific_field);
178  return IsMatchInternal(reflection1->GetMessage(message1, field),
179  reflection2->GetMessage(message2, field),
180  current_parent_fields, key_field_path,
181  path_index + 1);
182  }
183  }
185  std::vector<std::vector<const FieldDescriptor*> > key_field_paths_;
187 };
188 
189 // Preserve the order when treating repeated field as SMART_LIST. The current
190 // implementation is to find the longest matching sequence from the first
191 // element. The optimal solution requires to use //util/diff/lcs.h, which is
192 // not open sourced yet. Overwrite this method if you want to have that.
193 // TODO(ykzhu): change to use LCS once it is open sourced.
194 void MatchIndicesPostProcessorForSmartList(std::vector<int>* match_list1,
195  std::vector<int>* match_list2) {
196  int last_matched_index = -1;
197  for (size_t i = 0; i < match_list1->size(); ++i) {
198  if (match_list1->at(i) < 0) {
199  continue;
200  }
201  if (last_matched_index < 0 || match_list1->at(i) > last_matched_index) {
202  last_matched_index = match_list1->at(i);
203  } else {
204  match_list2->at(match_list1->at(i)) = -1;
205  match_list1->at(i) = -1;
206  }
207  }
208 }
209 
212  const Message& message, const FieldDescriptor* field, int index) {
213  if (field->is_map()) {
214  const Reflection* reflection = message.GetReflection();
215  specific_field->map_entry1 =
216  &reflection->GetRepeatedMessage(message, field, index);
217  }
218  specific_field->index = index;
219 }
220 
223  const Message& message, const FieldDescriptor* field, int index) {
224  if (field->is_map()) {
225  const Reflection* reflection = message.GetReflection();
226  specific_field->map_entry2 =
227  &reflection->GetRepeatedMessage(message, field, index);
228  }
229  specific_field->new_index = index;
230 }
231 
233  MessageDifferencer* message_differencer)
234  : message_differencer_(message_differencer) {}
235 
237  const Message& message1, const Message& message2,
238  const std::vector<SpecificField>& parent_fields) const {
239  // Map entry has its key in the field with tag 1. See the comment for
240  // map_entry in MessageOptions.
241  const FieldDescriptor* key = message1.GetDescriptor()->FindFieldByNumber(1);
242  // If key is not present in message1 and we're doing partial comparison or if
243  // map key is explicitly ignored treat the field as set instead,
244  const bool treat_as_set =
245  (message_differencer_->scope() == PARTIAL &&
246  !message1.GetReflection()->HasField(message1, key)) ||
247  message_differencer_->IsIgnored(message1, message2, key, parent_fields);
248 
249  std::vector<SpecificField> current_parent_fields(parent_fields);
250  if (treat_as_set) {
251  return message_differencer_->Compare(message1, message2,
252  &current_parent_fields);
253  }
254  return message_differencer_->CompareFieldValueUsingParentFields(
255  message1, message2, key, -1, -1, &current_parent_fields);
256 }
257 
258 bool MessageDifferencer::Equals(const Message& message1,
259  const Message& message2) {
260  MessageDifferencer differencer;
261 
262  return differencer.Compare(message1, message2);
263 }
264 
265 bool MessageDifferencer::Equivalent(const Message& message1,
266  const Message& message2) {
267  MessageDifferencer differencer;
268  differencer.set_message_field_comparison(MessageDifferencer::EQUIVALENT);
269 
270  return differencer.Compare(message1, message2);
271 }
272 
273 bool MessageDifferencer::ApproximatelyEquals(const Message& message1,
274  const Message& message2) {
275  MessageDifferencer differencer;
276  differencer.set_float_comparison(MessageDifferencer::APPROXIMATE);
277 
278  return differencer.Compare(message1, message2);
279 }
280 
281 bool MessageDifferencer::ApproximatelyEquivalent(const Message& message1,
282  const Message& message2) {
283  MessageDifferencer differencer;
284  differencer.set_message_field_comparison(MessageDifferencer::EQUIVALENT);
285  differencer.set_float_comparison(MessageDifferencer::APPROXIMATE);
286 
287  return differencer.Compare(message1, message2);
288 }
289 
290 // ===========================================================================
291 
292 MessageDifferencer::MessageDifferencer()
293  : reporter_(NULL),
294  message_field_comparison_(EQUAL),
295  scope_(FULL),
296  repeated_field_comparison_(AS_LIST),
297  map_entry_key_comparator_(this),
298  report_matches_(false),
299  report_moves_(true),
300  report_ignores_(true),
301  output_string_(nullptr),
302  match_indices_for_smart_list_callback_(
304 
305 MessageDifferencer::~MessageDifferencer() {
306  for (MapKeyComparator* comparator : owned_key_comparators_) {
307  delete comparator;
308  }
309  for (IgnoreCriteria* criteria : ignore_criteria_) {
310  delete criteria;
311  }
312 }
313 
314 void MessageDifferencer::set_field_comparator(FieldComparator* comparator) {
315  GOOGLE_CHECK(comparator) << "Field comparator can't be NULL.";
316  field_comparator_kind_ = kFCBase;
317  field_comparator_.base = comparator;
318 }
319 
320 #ifdef PROTOBUF_FUTURE_BREAKING_CHANGES
321 void MessageDifferencer::set_field_comparator(
322  DefaultFieldComparator* comparator) {
323  GOOGLE_CHECK(comparator) << "Field comparator can't be NULL.";
324  field_comparator_kind_ = kFCDefault;
325  field_comparator_.default_impl = comparator;
326 }
327 #endif // PROTOBUF_FUTURE_BREAKING_CHANGES
328 
329 void MessageDifferencer::set_message_field_comparison(
330  MessageFieldComparison comparison) {
331  message_field_comparison_ = comparison;
332 }
333 
334 void MessageDifferencer::set_scope(Scope scope) { scope_ = scope; }
335 
336 MessageDifferencer::Scope MessageDifferencer::scope() { return scope_; }
337 
338 void MessageDifferencer::set_float_comparison(FloatComparison comparison) {
339  default_field_comparator_.set_float_comparison(
340  comparison == EXACT ? DefaultFieldComparator::EXACT
341  : DefaultFieldComparator::APPROXIMATE);
342 }
343 
344 void MessageDifferencer::set_repeated_field_comparison(
345  RepeatedFieldComparison comparison) {
346  repeated_field_comparison_ = comparison;
347 }
348 
349 MessageDifferencer::RepeatedFieldComparison
350 MessageDifferencer::repeated_field_comparison() {
351  return repeated_field_comparison_;
352 }
353 
354 void MessageDifferencer::CheckRepeatedFieldComparisons(
355  const FieldDescriptor* field,
356  const RepeatedFieldComparison& new_comparison) {
358  << "Field must be repeated: " << field->full_name();
359  const MapKeyComparator* key_comparator = GetMapKeyComparator(field);
360  GOOGLE_CHECK(key_comparator == NULL)
361  << "Cannot treat this repeated field as both MAP and " << new_comparison
362  << " for comparison. Field name is: " << field->full_name();
363 }
364 
365 void MessageDifferencer::TreatAsSet(const FieldDescriptor* field) {
366  CheckRepeatedFieldComparisons(field, AS_SET);
367  repeated_field_comparisons_[field] = AS_SET;
368 }
369 
370 void MessageDifferencer::TreatAsSmartSet(const FieldDescriptor* field) {
371  CheckRepeatedFieldComparisons(field, AS_SMART_SET);
372  repeated_field_comparisons_[field] = AS_SMART_SET;
373 }
374 
375 void MessageDifferencer::SetMatchIndicesForSmartListCallback(
376  std::function<void(std::vector<int>*, std::vector<int>*)> callback) {
377  match_indices_for_smart_list_callback_ = callback;
378 }
379 
380 void MessageDifferencer::TreatAsList(const FieldDescriptor* field) {
381  CheckRepeatedFieldComparisons(field, AS_LIST);
382  repeated_field_comparisons_[field] = AS_LIST;
383 }
384 
385 void MessageDifferencer::TreatAsSmartList(const FieldDescriptor* field) {
386  CheckRepeatedFieldComparisons(field, AS_SMART_LIST);
387  repeated_field_comparisons_[field] = AS_SMART_LIST;
388 }
389 
390 void MessageDifferencer::TreatAsMap(const FieldDescriptor* field,
391  const FieldDescriptor* key) {
393  << "Field has to be message type. Field name is: " << field->full_name();
394  GOOGLE_CHECK(key->containing_type() == field->message_type())
395  << key->full_name()
396  << " must be a direct subfield within the repeated field "
397  << field->full_name() << ", not " << key->containing_type()->full_name();
398  GOOGLE_CHECK(repeated_field_comparisons_.find(field) ==
399  repeated_field_comparisons_.end())
400  << "Cannot treat the same field as both "
401  << repeated_field_comparisons_[field]
402  << " and MAP. Field name is: " << field->full_name();
403  MapKeyComparator* key_comparator =
404  new MultipleFieldsMapKeyComparator(this, key);
405  owned_key_comparators_.push_back(key_comparator);
406  map_field_key_comparator_[field] = key_comparator;
407 }
408 
409 void MessageDifferencer::TreatAsMapWithMultipleFieldsAsKey(
410  const FieldDescriptor* field,
411  const std::vector<const FieldDescriptor*>& key_fields) {
412  std::vector<std::vector<const FieldDescriptor*> > key_field_paths;
413  for (const FieldDescriptor* key_filed : key_fields) {
414  std::vector<const FieldDescriptor*> key_field_path;
415  key_field_path.push_back(key_filed);
416  key_field_paths.push_back(key_field_path);
417  }
418  TreatAsMapWithMultipleFieldPathsAsKey(field, key_field_paths);
419 }
420 
421 void MessageDifferencer::TreatAsMapWithMultipleFieldPathsAsKey(
422  const FieldDescriptor* field,
423  const std::vector<std::vector<const FieldDescriptor*> >& key_field_paths) {
425  << "Field must be repeated: " << field->full_name();
427  << "Field has to be message type. Field name is: " << field->full_name();
428  for (const auto& key_field_path : key_field_paths) {
429  for (size_t j = 0; j < key_field_path.size(); ++j) {
430  const FieldDescriptor* parent_field =
431  j == 0 ? field : key_field_path[j - 1];
432  const FieldDescriptor* child_field = key_field_path[j];
433  GOOGLE_CHECK(child_field->containing_type() == parent_field->message_type())
434  << child_field->full_name()
435  << " must be a direct subfield within the field: "
436  << parent_field->full_name();
437  if (j != 0) {
438  GOOGLE_CHECK_EQ(FieldDescriptor::CPPTYPE_MESSAGE, parent_field->cpp_type())
439  << parent_field->full_name() << " has to be of type message.";
440  GOOGLE_CHECK(!parent_field->is_repeated())
441  << parent_field->full_name() << " cannot be a repeated field.";
442  }
443  }
444  }
445  GOOGLE_CHECK(repeated_field_comparisons_.find(field) ==
446  repeated_field_comparisons_.end())
447  << "Cannot treat the same field as both "
448  << repeated_field_comparisons_[field]
449  << " and MAP. Field name is: " << field->full_name();
450  MapKeyComparator* key_comparator =
451  new MultipleFieldsMapKeyComparator(this, key_field_paths);
452  owned_key_comparators_.push_back(key_comparator);
453  map_field_key_comparator_[field] = key_comparator;
454 }
455 
456 void MessageDifferencer::TreatAsMapUsingKeyComparator(
457  const FieldDescriptor* field, const MapKeyComparator* key_comparator) {
459  << "Field must be repeated: " << field->full_name();
460  GOOGLE_CHECK(repeated_field_comparisons_.find(field) ==
461  repeated_field_comparisons_.end())
462  << "Cannot treat the same field as both "
463  << repeated_field_comparisons_[field]
464  << " and MAP. Field name is: " << field->full_name();
465  map_field_key_comparator_[field] = key_comparator;
466 }
467 
468 void MessageDifferencer::AddIgnoreCriteria(IgnoreCriteria* ignore_criteria) {
469  ignore_criteria_.push_back(ignore_criteria);
470 }
471 
472 void MessageDifferencer::IgnoreField(const FieldDescriptor* field) {
473  ignored_fields_.insert(field);
474 }
475 
476 void MessageDifferencer::SetFractionAndMargin(const FieldDescriptor* field,
477  double fraction, double margin) {
478  default_field_comparator_.SetFractionAndMargin(field, fraction, margin);
479 }
480 
481 void MessageDifferencer::ReportDifferencesToString(std::string* output) {
482  GOOGLE_DCHECK(output) << "Specified output string was NULL";
483 
484  output_string_ = output;
485  output_string_->clear();
486 }
487 
488 void MessageDifferencer::ReportDifferencesTo(Reporter* reporter) {
489  // If an output string is set, clear it to prevent
490  // it superseding the specified reporter.
491  if (output_string_) {
492  output_string_ = NULL;
493  }
494 
495  reporter_ = reporter;
496 }
497 
498 bool MessageDifferencer::FieldBefore(const FieldDescriptor* field1,
499  const FieldDescriptor* field2) {
500  // Handle sentinel values (i.e. make sure NULLs are always ordered
501  // at the end of the list).
502  if (field1 == NULL) {
503  return false;
504  }
505 
506  if (field2 == NULL) {
507  return true;
508  }
509 
510  // Always order fields by their tag number
511  return (field1->number() < field2->number());
512 }
513 
514 bool MessageDifferencer::Compare(const Message& message1,
515  const Message& message2) {
516  std::vector<SpecificField> parent_fields;
517 
518  bool result = false;
519  // Setup the internal reporter if need be.
520  if (output_string_) {
521  io::StringOutputStream output_stream(output_string_);
522  StreamReporter reporter(&output_stream);
523  reporter.SetMessages(message1, message2);
524  reporter_ = &reporter;
525  result = Compare(message1, message2, &parent_fields);
526  reporter_ = NULL;
527  } else {
528  result = Compare(message1, message2, &parent_fields);
529  }
530  return result;
531 }
532 
533 bool MessageDifferencer::CompareWithFields(
534  const Message& message1, const Message& message2,
535  const std::vector<const FieldDescriptor*>& message1_fields_arg,
536  const std::vector<const FieldDescriptor*>& message2_fields_arg) {
537  if (message1.GetDescriptor() != message2.GetDescriptor()) {
538  GOOGLE_LOG(DFATAL) << "Comparison between two messages with different "
539  << "descriptors.";
540  return false;
541  }
542 
543  std::vector<SpecificField> parent_fields;
544 
545  bool result = false;
546 
547  FieldDescriptorArray message1_fields(message1_fields_arg.size() + 1);
548  FieldDescriptorArray message2_fields(message2_fields_arg.size() + 1);
549 
550  std::copy(message1_fields_arg.cbegin(), message1_fields_arg.cend(),
551  message1_fields.begin());
552  std::copy(message2_fields_arg.cbegin(), message2_fields_arg.cend(),
553  message2_fields.begin());
554 
555  // Append sentinel values.
556  message1_fields[message1_fields_arg.size()] = nullptr;
557  message2_fields[message2_fields_arg.size()] = nullptr;
558 
559  std::sort(message1_fields.begin(), message1_fields.end(), FieldBefore);
560  std::sort(message2_fields.begin(), message2_fields.end(), FieldBefore);
561 
562  // Setup the internal reporter if need be.
563  if (output_string_) {
564  io::StringOutputStream output_stream(output_string_);
565  StreamReporter reporter(&output_stream);
566  reporter_ = &reporter;
567  result = CompareRequestedFieldsUsingSettings(
568  message1, message2, message1_fields, message2_fields, &parent_fields);
569  reporter_ = NULL;
570  } else {
571  result = CompareRequestedFieldsUsingSettings(
572  message1, message2, message1_fields, message2_fields, &parent_fields);
573  }
574 
575  return result;
576 }
577 
578 bool MessageDifferencer::Compare(const Message& message1,
579  const Message& message2,
580  std::vector<SpecificField>* parent_fields) {
581  const Descriptor* descriptor1 = message1.GetDescriptor();
582  const Descriptor* descriptor2 = message2.GetDescriptor();
583  if (descriptor1 != descriptor2) {
584  GOOGLE_LOG(DFATAL) << "Comparison between two messages with different "
585  << "descriptors. " << descriptor1->full_name() << " vs "
586  << descriptor2->full_name();
587  return false;
588  }
589 
590  // Expand google.protobuf.Any payload if possible.
591  if (descriptor1->full_name() == internal::kAnyFullTypeName) {
592  std::unique_ptr<Message> data1;
593  std::unique_ptr<Message> data2;
594  if (unpack_any_field_.UnpackAny(message1, &data1) &&
595  unpack_any_field_.UnpackAny(message2, &data2)) {
596  // Avoid DFATAL for different descriptors in google.protobuf.Any payloads.
597  if (data1->GetDescriptor() != data2->GetDescriptor()) {
598  return false;
599  }
600  return Compare(*data1, *data2, parent_fields);
601  }
602  }
603  const Reflection* reflection1 = message1.GetReflection();
604  const Reflection* reflection2 = message2.GetReflection();
605 
606  bool unknown_compare_result = true;
607  // Ignore unknown fields in EQUIVALENT mode
608  if (message_field_comparison_ != EQUIVALENT) {
609  const UnknownFieldSet& unknown_field_set1 =
610  reflection1->GetUnknownFields(message1);
611  const UnknownFieldSet& unknown_field_set2 =
612  reflection2->GetUnknownFields(message2);
613  if (!CompareUnknownFields(message1, message2, unknown_field_set1,
614  unknown_field_set2, parent_fields)) {
615  if (reporter_ == NULL) {
616  return false;
617  }
618  unknown_compare_result = false;
619  }
620  }
621 
622  FieldDescriptorArray message1_fields = RetrieveFields(message1, true);
623  FieldDescriptorArray message2_fields = RetrieveFields(message2, false);
624 
625  return CompareRequestedFieldsUsingSettings(message1, message2,
626  message1_fields, message2_fields,
627  parent_fields) &&
628  unknown_compare_result;
629 }
630 
631 FieldDescriptorArray MessageDifferencer::RetrieveFields(const Message& message,
632  bool base_message) {
633  const Descriptor* descriptor = message.GetDescriptor();
634 
635  tmp_message_fields_.clear();
636  tmp_message_fields_.reserve(descriptor->field_count() + 1);
637 
638  const Reflection* reflection = message.GetReflection();
639  if (descriptor->options().map_entry()) {
640  if (this->scope_ == PARTIAL && base_message) {
641  reflection->ListFields(message, &tmp_message_fields_);
642  } else {
643  // Map entry fields are always considered present.
644  for (int i = 0; i < descriptor->field_count(); i++) {
645  tmp_message_fields_.push_back(descriptor->field(i));
646  }
647  }
648  } else {
649  reflection->ListFields(message, &tmp_message_fields_);
650  }
651  // Add sentinel values to deal with the
652  // case where the number of the fields in
653  // each list are different.
654  tmp_message_fields_.push_back(nullptr);
655 
656  FieldDescriptorArray message_fields(tmp_message_fields_.begin(),
657  tmp_message_fields_.end());
658 
659  return message_fields;
660 }
661 
662 bool MessageDifferencer::CompareRequestedFieldsUsingSettings(
663  const Message& message1, const Message& message2,
664  const FieldDescriptorArray& message1_fields,
665  const FieldDescriptorArray& message2_fields,
666  std::vector<SpecificField>* parent_fields) {
667  if (scope_ == FULL) {
668  if (message_field_comparison_ == EQUIVALENT) {
669  // We need to merge the field lists of both messages (i.e.
670  // we are merely checking for a difference in field values,
671  // rather than the addition or deletion of fields).
672  FieldDescriptorArray fields_union =
673  CombineFields(message1_fields, FULL, message2_fields, FULL);
674  return CompareWithFieldsInternal(message1, message2, fields_union,
675  fields_union, parent_fields);
676  } else {
677  // Simple equality comparison, use the unaltered field lists.
678  return CompareWithFieldsInternal(message1, message2, message1_fields,
679  message2_fields, parent_fields);
680  }
681  } else {
682  if (message_field_comparison_ == EQUIVALENT) {
683  // We use the list of fields for message1 for both messages when
684  // comparing. This way, extra fields in message2 are ignored,
685  // and missing fields in message2 use their default value.
686  return CompareWithFieldsInternal(message1, message2, message1_fields,
687  message1_fields, parent_fields);
688  } else {
689  // We need to consider the full list of fields for message1
690  // but only the intersection for message2. This way, any fields
691  // only present in message2 will be ignored, but any fields only
692  // present in message1 will be marked as a difference.
693  FieldDescriptorArray fields_intersection =
694  CombineFields(message1_fields, PARTIAL, message2_fields, PARTIAL);
695  return CompareWithFieldsInternal(message1, message2, message1_fields,
696  fields_intersection, parent_fields);
697  }
698  }
699 }
700 
701 FieldDescriptorArray MessageDifferencer::CombineFields(
702  const FieldDescriptorArray& fields1, Scope fields1_scope,
703  const FieldDescriptorArray& fields2, Scope fields2_scope) {
704  size_t index1 = 0;
705  size_t index2 = 0;
706 
707  tmp_message_fields_.clear();
708 
709  while (index1 < fields1.size() && index2 < fields2.size()) {
710  const FieldDescriptor* field1 = fields1[index1];
711  const FieldDescriptor* field2 = fields2[index2];
712 
713  if (FieldBefore(field1, field2)) {
714  if (fields1_scope == FULL) {
715  tmp_message_fields_.push_back(fields1[index1]);
716  }
717  ++index1;
718  } else if (FieldBefore(field2, field1)) {
719  if (fields2_scope == FULL) {
720  tmp_message_fields_.push_back(fields2[index2]);
721  }
722  ++index2;
723  } else {
724  tmp_message_fields_.push_back(fields1[index1]);
725  ++index1;
726  ++index2;
727  }
728  }
729 
730  tmp_message_fields_.push_back(nullptr);
731 
732  FieldDescriptorArray combined_fields(tmp_message_fields_.begin(),
733  tmp_message_fields_.end());
734 
735  return combined_fields;
736 }
737 
738 bool MessageDifferencer::CompareWithFieldsInternal(
739  const Message& message1, const Message& message2,
740  const FieldDescriptorArray& message1_fields,
741  const FieldDescriptorArray& message2_fields,
742  std::vector<SpecificField>* parent_fields) {
743  bool isDifferent = false;
744  int field_index1 = 0;
745  int field_index2 = 0;
746 
747  const Reflection* reflection1 = message1.GetReflection();
748  const Reflection* reflection2 = message2.GetReflection();
749 
750  while (true) {
751  const FieldDescriptor* field1 = message1_fields[field_index1];
752  const FieldDescriptor* field2 = message2_fields[field_index2];
753 
754  // Once we have reached sentinel values, we are done the comparison.
755  if (field1 == NULL && field2 == NULL) {
756  break;
757  }
758 
759  // Check for differences in the field itself.
760  if (FieldBefore(field1, field2)) {
761  // Field 1 is not in the field list for message 2.
762  if (IsIgnored(message1, message2, field1, *parent_fields)) {
763  // We are ignoring field1. Report the ignore and move on to
764  // the next field in message1_fields.
765  if (reporter_ != NULL) {
766  SpecificField specific_field;
767  specific_field.field = field1;
768  parent_fields->push_back(specific_field);
769  if (report_ignores_) {
770  reporter_->ReportIgnored(message1, message2, *parent_fields);
771  }
772  parent_fields->pop_back();
773  }
774  ++field_index1;
775  continue;
776  }
777 
778  if (reporter_ != NULL) {
779  assert(field1 != NULL);
780  int count = field1->is_repeated()
781  ? reflection1->FieldSize(message1, field1)
782  : 1;
783 
784  for (int i = 0; i < count; ++i) {
785  SpecificField specific_field;
786  specific_field.field = field1;
787  if (field1->is_repeated()) {
788  AddSpecificIndex(&specific_field, message1, field1, i);
789  } else {
790  specific_field.index = -1;
791  }
792 
793  parent_fields->push_back(specific_field);
794  reporter_->ReportDeleted(message1, message2, *parent_fields);
795  parent_fields->pop_back();
796  }
797 
798  isDifferent = true;
799  } else {
800  return false;
801  }
802 
803  ++field_index1;
804  continue;
805  } else if (FieldBefore(field2, field1)) {
806  // Field 2 is not in the field list for message 1.
807  if (IsIgnored(message1, message2, field2, *parent_fields)) {
808  // We are ignoring field2. Report the ignore and move on to
809  // the next field in message2_fields.
810  if (reporter_ != NULL) {
811  SpecificField specific_field;
812  specific_field.field = field2;
813  parent_fields->push_back(specific_field);
814  if (report_ignores_) {
815  reporter_->ReportIgnored(message1, message2, *parent_fields);
816  }
817  parent_fields->pop_back();
818  }
819  ++field_index2;
820  continue;
821  }
822 
823  if (reporter_ != NULL) {
824  int count = field2->is_repeated()
825  ? reflection2->FieldSize(message2, field2)
826  : 1;
827 
828  for (int i = 0; i < count; ++i) {
829  SpecificField specific_field;
830  specific_field.field = field2;
831  if (field2->is_repeated()) {
832  specific_field.index = i;
833  AddSpecificNewIndex(&specific_field, message2, field2, i);
834  } else {
835  specific_field.index = -1;
836  specific_field.new_index = -1;
837  }
838 
839  parent_fields->push_back(specific_field);
840  reporter_->ReportAdded(message1, message2, *parent_fields);
841  parent_fields->pop_back();
842  }
843 
844  isDifferent = true;
845  } else {
846  return false;
847  }
848 
849  ++field_index2;
850  continue;
851  }
852 
853  // By this point, field1 and field2 are guaranteed to point to the same
854  // field, so we can now compare the values.
855  if (IsIgnored(message1, message2, field1, *parent_fields)) {
856  // Ignore this field. Report and move on.
857  if (reporter_ != NULL) {
858  SpecificField specific_field;
859  specific_field.field = field1;
860  parent_fields->push_back(specific_field);
861  if (report_ignores_) {
862  reporter_->ReportIgnored(message1, message2, *parent_fields);
863  }
864  parent_fields->pop_back();
865  }
866 
867  ++field_index1;
868  ++field_index2;
869  continue;
870  }
871 
872  bool fieldDifferent = false;
873  assert(field1 != NULL);
874  if (field1->is_map()) {
875  fieldDifferent =
876  !CompareMapField(message1, message2, field1, parent_fields);
877  } else if (field1->is_repeated()) {
878  fieldDifferent =
879  !CompareRepeatedField(message1, message2, field1, parent_fields);
880  } else {
881  fieldDifferent = !CompareFieldValueUsingParentFields(
882  message1, message2, field1, -1, -1, parent_fields);
883 
884  if (reporter_ != nullptr) {
885  SpecificField specific_field;
886  specific_field.field = field1;
887  parent_fields->push_back(specific_field);
888  if (fieldDifferent) {
889  reporter_->ReportModified(message1, message2, *parent_fields);
890  isDifferent = true;
891  } else if (report_matches_) {
892  reporter_->ReportMatched(message1, message2, *parent_fields);
893  }
894  parent_fields->pop_back();
895  }
896  }
897  if (fieldDifferent) {
898  if (reporter_ == nullptr) return false;
899  isDifferent = true;
900  }
901  // Increment the field indices.
902  ++field_index1;
903  ++field_index2;
904  }
905 
906  return !isDifferent;
907 }
908 
911  const MapKeyComparator* key_comparator, const Message* message1,
912  const Message* message2, const std::vector<SpecificField>& parent_fields,
913  Reporter* reporter, int index1, int index2) {
914  std::vector<SpecificField> current_parent_fields(parent_fields);
916  return CompareFieldValueUsingParentFields(*message1, *message2,
917  repeated_field, index1, index2,
918  &current_parent_fields);
919  }
920  // Back up the Reporter and output_string_. They will be reset in the
921  // following code.
922  Reporter* backup_reporter = reporter_;
923  std::string* output_string = output_string_;
924  reporter_ = reporter;
925  output_string_ = NULL;
926  bool match;
927 
928  if (key_comparator == NULL) {
929  match = CompareFieldValueUsingParentFields(*message1, *message2,
930  repeated_field, index1, index2,
931  &current_parent_fields);
932  } else {
933  const Reflection* reflection1 = message1->GetReflection();
934  const Reflection* reflection2 = message2->GetReflection();
935  const Message& m1 =
936  reflection1->GetRepeatedMessage(*message1, repeated_field, index1);
937  const Message& m2 =
938  reflection2->GetRepeatedMessage(*message2, repeated_field, index2);
939  SpecificField specific_field;
940  specific_field.field = repeated_field;
941  if (repeated_field->is_map()) {
942  specific_field.map_entry1 = &m1;
943  specific_field.map_entry2 = &m2;
944  }
945  specific_field.index = index1;
946  specific_field.new_index = index2;
947  current_parent_fields.push_back(specific_field);
948  match = key_comparator->IsMatch(m1, m2, current_parent_fields);
949  }
950 
951  reporter_ = backup_reporter;
952  output_string_ = output_string;
953  return match;
954 }
955 
956 bool MessageDifferencer::CompareMapFieldByMapReflection(
957  const Message& message1, const Message& message2,
958  const FieldDescriptor* map_field, std::vector<SpecificField>* parent_fields,
959  DefaultFieldComparator* comparator) {
960  GOOGLE_DCHECK_EQ(nullptr, reporter_);
961  GOOGLE_DCHECK(map_field->is_map());
962  GOOGLE_DCHECK(map_field_key_comparator_.find(map_field) ==
963  map_field_key_comparator_.end());
964  GOOGLE_DCHECK_EQ(repeated_field_comparison_, AS_LIST);
965  const Reflection* reflection1 = message1.GetReflection();
966  const Reflection* reflection2 = message2.GetReflection();
967  const int count1 = reflection1->MapSize(message1, map_field);
968  const int count2 = reflection2->MapSize(message2, map_field);
969  const bool treated_as_subset = IsTreatedAsSubset(map_field);
970  if (count1 != count2 && !treated_as_subset) {
971  return false;
972  }
973  if (count1 > count2) {
974  return false;
975  }
976 
977  // First pass: check whether the same keys are present.
978  for (MapIterator it = reflection1->MapBegin(const_cast<Message*>(&message1),
979  map_field),
980  it_end = reflection1->MapEnd(const_cast<Message*>(&message1),
981  map_field);
982  it != it_end; ++it) {
983  if (!reflection2->ContainsMapKey(message2, map_field, it.GetKey())) {
984  return false;
985  }
986  }
987 
988  // Second pass: compare values for matching keys.
989  const FieldDescriptor* val_des = map_field->message_type()->map_value();
990  switch (val_des->cpp_type()) {
991 #define HANDLE_TYPE(CPPTYPE, METHOD, COMPAREMETHOD) \
992  case FieldDescriptor::CPPTYPE_##CPPTYPE: { \
993  for (MapIterator it = reflection1->MapBegin( \
994  const_cast<Message*>(&message1), map_field), \
995  it_end = reflection1->MapEnd( \
996  const_cast<Message*>(&message1), map_field); \
997  it != it_end; ++it) { \
998  MapValueConstRef value2; \
999  reflection2->LookupMapValue(message2, map_field, it.GetKey(), &value2); \
1000  if (!comparator->Compare##COMPAREMETHOD(*val_des, \
1001  it.GetValueRef().Get##METHOD(), \
1002  value2.Get##METHOD())) { \
1003  return false; \
1004  } \
1005  } \
1006  break; \
1007  }
1008  HANDLE_TYPE(INT32, Int32Value, Int32);
1009  HANDLE_TYPE(INT64, Int64Value, Int64);
1010  HANDLE_TYPE(UINT32, UInt32Value, UInt32);
1011  HANDLE_TYPE(UINT64, UInt64Value, UInt64);
1012  HANDLE_TYPE(DOUBLE, DoubleValue, Double);
1013  HANDLE_TYPE(FLOAT, FloatValue, Float);
1015  HANDLE_TYPE(STRING, StringValue, String);
1016  HANDLE_TYPE(ENUM, EnumValue, Int32);
1017 #undef HANDLE_TYPE
1019  for (MapIterator it = reflection1->MapBegin(
1020  const_cast<Message*>(&message1), map_field);
1021  it !=
1022  reflection1->MapEnd(const_cast<Message*>(&message1), map_field);
1023  ++it) {
1024  if (!reflection2->ContainsMapKey(message2, map_field, it.GetKey())) {
1025  return false;
1026  }
1027  bool compare_result;
1028  MapValueConstRef value2;
1029  reflection2->LookupMapValue(message2, map_field, it.GetKey(), &value2);
1030  // Append currently compared field to the end of parent_fields.
1031  SpecificField specific_value_field;
1032  specific_value_field.field = val_des;
1033  parent_fields->push_back(specific_value_field);
1034  compare_result = Compare(it.GetValueRef().GetMessageValue(),
1035  value2.GetMessageValue(), parent_fields);
1036  parent_fields->pop_back();
1037  if (!compare_result) {
1038  return false;
1039  }
1040  }
1041  break;
1042  }
1043  }
1044  return true;
1045 }
1046 
1047 bool MessageDifferencer::CompareMapField(
1048  const Message& message1, const Message& message2,
1050  std::vector<SpecificField>* parent_fields) {
1051  GOOGLE_DCHECK(repeated_field->is_map());
1052 
1053  // the input FieldDescriptor is guaranteed to be repeated field.
1054  const Reflection* reflection1 = message1.GetReflection();
1055  const Reflection* reflection2 = message2.GetReflection();
1056 
1057  // When both map fields are on map, do not sync to repeated field.
1058  if (reflection1->GetMapData(message1, repeated_field)->IsMapValid() &&
1059  reflection2->GetMapData(message2, repeated_field)->IsMapValid() &&
1060  // TODO(jieluo): Add support for reporter
1061  reporter_ == nullptr &&
1062  // Users didn't set custom map field key comparator
1063  map_field_key_comparator_.find(repeated_field) ==
1064  map_field_key_comparator_.end() &&
1065  // Users didn't set repeated field comparison
1066  repeated_field_comparison_ == AS_LIST &&
1067  // Users didn't set their own FieldComparator implementation
1068  field_comparator_kind_ == kFCDefault) {
1069  const FieldDescriptor* key_des = repeated_field->message_type()->map_key();
1070  const FieldDescriptor* val_des =
1071  repeated_field->message_type()->map_value();
1072  std::vector<SpecificField> current_parent_fields(*parent_fields);
1073  SpecificField specific_field;
1074  specific_field.field = repeated_field;
1075  current_parent_fields.push_back(specific_field);
1076  if (!IsIgnored(message1, message2, key_des, current_parent_fields) &&
1077  !IsIgnored(message1, message2, val_des, current_parent_fields)) {
1078  return CompareMapFieldByMapReflection(message1, message2, repeated_field,
1079  &current_parent_fields,
1080  field_comparator_.default_impl);
1081  }
1082  }
1083 
1084  return CompareRepeatedRep(message1, message2, repeated_field, parent_fields);
1085 }
1086 
1087 bool MessageDifferencer::CompareRepeatedField(
1088  const Message& message1, const Message& message2,
1090  std::vector<SpecificField>* parent_fields) {
1091  GOOGLE_DCHECK(!repeated_field->is_map());
1092  return CompareRepeatedRep(message1, message2, repeated_field, parent_fields);
1093 }
1094 
1095 bool MessageDifferencer::CompareRepeatedRep(
1096  const Message& message1, const Message& message2,
1098  std::vector<SpecificField>* parent_fields) {
1099  // the input FieldDescriptor is guaranteed to be repeated field.
1100  GOOGLE_DCHECK(repeated_field->is_repeated());
1101  const Reflection* reflection1 = message1.GetReflection();
1102  const Reflection* reflection2 = message2.GetReflection();
1103 
1104  const int count1 = reflection1->FieldSize(message1, repeated_field);
1105  const int count2 = reflection2->FieldSize(message2, repeated_field);
1106  const bool treated_as_subset = IsTreatedAsSubset(repeated_field);
1107 
1108  // If the field is not treated as subset and no detailed reports is needed,
1109  // we do a quick check on the number of the elements to avoid unnecessary
1110  // comparison.
1111  if (count1 != count2 && reporter_ == NULL && !treated_as_subset) {
1112  return false;
1113  }
1114  // A match can never be found if message1 has more items than message2.
1115  if (count1 > count2 && reporter_ == NULL) {
1116  return false;
1117  }
1118 
1119  // These two list are used for store the index of the correspondent
1120  // element in peer repeated field.
1121  std::vector<int> match_list1;
1122  std::vector<int> match_list2;
1123 
1124  const MapKeyComparator* key_comparator = GetMapKeyComparator(repeated_field);
1125  bool smart_list = IsTreatedAsSmartList(repeated_field);
1126  bool simple_list = key_comparator == nullptr &&
1127  !IsTreatedAsSet(repeated_field) &&
1128  !IsTreatedAsSmartSet(repeated_field) && !smart_list;
1129 
1130  // For simple lists, we avoid matching repeated field indices, saving the
1131  // memory allocations that would otherwise be needed for match_list1 and
1132  // match_list2.
1133  if (!simple_list) {
1134  // Try to match indices of the repeated fields. Return false if match fails.
1135  if (!MatchRepeatedFieldIndices(message1, message2, repeated_field,
1136  key_comparator, *parent_fields, &match_list1,
1137  &match_list2) &&
1138  reporter_ == nullptr) {
1139  return false;
1140  }
1141  }
1142 
1143  bool fieldDifferent = false;
1144  SpecificField specific_field;
1145  specific_field.field = repeated_field;
1146 
1147  // At this point, we have already matched pairs of fields (with the reporting
1148  // to be done later). Now to check if the paired elements are different.
1149  int next_unmatched_index = 0;
1150  for (int i = 0; i < count1; i++) {
1151  if (simple_list && i >= count2) {
1152  break;
1153  }
1154  if (!simple_list && match_list1[i] == -1) {
1155  if (smart_list) {
1156  if (reporter_ == nullptr) return false;
1157  AddSpecificIndex(&specific_field, message1, repeated_field, i);
1158  parent_fields->push_back(specific_field);
1159  reporter_->ReportDeleted(message1, message2, *parent_fields);
1160  parent_fields->pop_back();
1161  fieldDifferent = true;
1162  // Use -2 to mark this element has been reported.
1163  match_list1[i] = -2;
1164  }
1165  continue;
1166  }
1167  if (smart_list) {
1168  for (int j = next_unmatched_index; j < match_list1[i]; ++j) {
1169  GOOGLE_CHECK_LE(0, j);
1170  if (reporter_ == nullptr) return false;
1171  specific_field.index = j;
1172  AddSpecificNewIndex(&specific_field, message2, repeated_field, j);
1173  parent_fields->push_back(specific_field);
1174  reporter_->ReportAdded(message1, message2, *parent_fields);
1175  parent_fields->pop_back();
1176  fieldDifferent = true;
1177  // Use -2 to mark this element has been reported.
1178  match_list2[j] = -2;
1179  }
1180  }
1181  AddSpecificIndex(&specific_field, message1, repeated_field, i);
1182  if (simple_list) {
1183  AddSpecificNewIndex(&specific_field, message2, repeated_field, i);
1184  } else {
1185  AddSpecificNewIndex(&specific_field, message2, repeated_field,
1186  match_list1[i]);
1187  next_unmatched_index = match_list1[i] + 1;
1188  }
1189 
1190  const bool result = CompareFieldValueUsingParentFields(
1191  message1, message2, repeated_field, i, specific_field.new_index,
1192  parent_fields);
1193 
1194  // If we have found differences, either report them or terminate if
1195  // no reporter is present. Note that ReportModified, ReportMoved, and
1196  // ReportMatched are all mutually exclusive.
1197  if (!result) {
1198  if (reporter_ == NULL) return false;
1199  parent_fields->push_back(specific_field);
1200  reporter_->ReportModified(message1, message2, *parent_fields);
1201  parent_fields->pop_back();
1202  fieldDifferent = true;
1203  } else if (reporter_ != NULL &&
1204  specific_field.index != specific_field.new_index &&
1205  !specific_field.field->is_map() && report_moves_) {
1206  parent_fields->push_back(specific_field);
1207  reporter_->ReportMoved(message1, message2, *parent_fields);
1208  parent_fields->pop_back();
1209  } else if (report_matches_ && reporter_ != NULL) {
1210  parent_fields->push_back(specific_field);
1211  reporter_->ReportMatched(message1, message2, *parent_fields);
1212  parent_fields->pop_back();
1213  }
1214  }
1215 
1216  // Report any remaining additions or deletions.
1217  for (int i = 0; i < count2; ++i) {
1218  if (!simple_list && match_list2[i] != -1) continue;
1219  if (simple_list && i < count1) continue;
1220  if (!treated_as_subset) {
1221  fieldDifferent = true;
1222  }
1223 
1224  if (reporter_ == NULL) continue;
1225  specific_field.index = i;
1226  AddSpecificNewIndex(&specific_field, message2, repeated_field, i);
1227  parent_fields->push_back(specific_field);
1228  reporter_->ReportAdded(message1, message2, *parent_fields);
1229  parent_fields->pop_back();
1230  }
1231 
1232  for (int i = 0; i < count1; ++i) {
1233  if (!simple_list && match_list1[i] != -1) continue;
1234  if (simple_list && i < count2) continue;
1235  assert(reporter_ != NULL);
1236  AddSpecificIndex(&specific_field, message1, repeated_field, i);
1237  parent_fields->push_back(specific_field);
1238  reporter_->ReportDeleted(message1, message2, *parent_fields);
1239  parent_fields->pop_back();
1240  fieldDifferent = true;
1241  }
1242  return !fieldDifferent;
1243 }
1244 
1245 bool MessageDifferencer::CompareFieldValue(const Message& message1,
1246  const Message& message2,
1247  const FieldDescriptor* field,
1248  int index1, int index2) {
1249  return CompareFieldValueUsingParentFields(message1, message2, field, index1,
1250  index2, NULL);
1251 }
1252 
1253 bool MessageDifferencer::CompareFieldValueUsingParentFields(
1254  const Message& message1, const Message& message2,
1255  const FieldDescriptor* field, int index1, int index2,
1256  std::vector<SpecificField>* parent_fields) {
1257  FieldContext field_context(parent_fields);
1258  FieldComparator::ComparisonResult result = GetFieldComparisonResult(
1259  message1, message2, field, index1, index2, &field_context);
1260 
1262  result == FieldComparator::RECURSE) {
1263  // Get the nested messages and compare them using one of the Compare
1264  // methods.
1265  const Reflection* reflection1 = message1.GetReflection();
1266  const Reflection* reflection2 = message2.GetReflection();
1267  const Message& m1 =
1268  field->is_repeated()
1269  ? reflection1->GetRepeatedMessage(message1, field, index1)
1270  : reflection1->GetMessage(message1, field);
1271  const Message& m2 =
1272  field->is_repeated()
1273  ? reflection2->GetRepeatedMessage(message2, field, index2)
1274  : reflection2->GetMessage(message2, field);
1275 
1276  // parent_fields is used in calls to Reporter methods.
1277  if (parent_fields != NULL) {
1278  // Append currently compared field to the end of parent_fields.
1279  SpecificField specific_field;
1280  specific_field.field = field;
1281  AddSpecificIndex(&specific_field, message1, field, index1);
1282  AddSpecificNewIndex(&specific_field, message2, field, index2);
1283  parent_fields->push_back(specific_field);
1284  const bool compare_result = Compare(m1, m2, parent_fields);
1285  parent_fields->pop_back();
1286  return compare_result;
1287  } else {
1288  // Recreates parent_fields as if m1 and m2 had no parents.
1289  return Compare(m1, m2);
1290  }
1291  } else {
1292  return (result == FieldComparator::SAME);
1293  }
1294 }
1295 
1296 bool MessageDifferencer::CheckPathChanged(
1297  const std::vector<SpecificField>& field_path) {
1298  for (const SpecificField& specific_field : field_path) {
1299  // Don't check indexes for map entries -- maps are unordered.
1300  if (specific_field.field != nullptr && specific_field.field->is_map())
1301  continue;
1302  if (specific_field.index != specific_field.new_index) return true;
1303  }
1304  return false;
1305 }
1306 
1307 bool MessageDifferencer::IsTreatedAsSet(const FieldDescriptor* field) {
1308  if (!field->is_repeated()) return false;
1309  if (repeated_field_comparisons_.find(field) !=
1310  repeated_field_comparisons_.end()) {
1311  return repeated_field_comparisons_[field] == AS_SET;
1312  }
1313  return GetMapKeyComparator(field) == nullptr &&
1314  repeated_field_comparison_ == AS_SET;
1315 }
1316 
1317 bool MessageDifferencer::IsTreatedAsSmartSet(const FieldDescriptor* field) {
1318  if (!field->is_repeated()) return false;
1319  if (repeated_field_comparisons_.find(field) !=
1320  repeated_field_comparisons_.end()) {
1321  return repeated_field_comparisons_[field] == AS_SMART_SET;
1322  }
1323  return GetMapKeyComparator(field) == nullptr &&
1324  repeated_field_comparison_ == AS_SMART_SET;
1325 }
1326 
1327 bool MessageDifferencer::IsTreatedAsSmartList(const FieldDescriptor* field) {
1328  if (!field->is_repeated()) return false;
1329  if (repeated_field_comparisons_.find(field) !=
1330  repeated_field_comparisons_.end()) {
1331  return repeated_field_comparisons_[field] == AS_SMART_LIST;
1332  }
1333  return GetMapKeyComparator(field) == nullptr &&
1334  repeated_field_comparison_ == AS_SMART_LIST;
1335 }
1336 
1337 bool MessageDifferencer::IsTreatedAsSubset(const FieldDescriptor* field) {
1338  return scope_ == PARTIAL &&
1339  (IsTreatedAsSet(field) || GetMapKeyComparator(field) != NULL);
1340 }
1341 
1342 bool MessageDifferencer::IsIgnored(
1343  const Message& message1, const Message& message2,
1344  const FieldDescriptor* field,
1345  const std::vector<SpecificField>& parent_fields) {
1346  if (ignored_fields_.find(field) != ignored_fields_.end()) {
1347  return true;
1348  }
1349  for (IgnoreCriteria* criteria : ignore_criteria_) {
1350  if (criteria->IsIgnored(message1, message2, field, parent_fields)) {
1351  return true;
1352  }
1353  }
1354  return false;
1355 }
1356 
1357 bool MessageDifferencer::IsUnknownFieldIgnored(
1358  const Message& message1, const Message& message2,
1359  const SpecificField& field,
1360  const std::vector<SpecificField>& parent_fields) {
1361  for (IgnoreCriteria* criteria : ignore_criteria_) {
1362  if (criteria->IsUnknownFieldIgnored(message1, message2, field,
1363  parent_fields)) {
1364  return true;
1365  }
1366  }
1367  return false;
1368 }
1369 
1370 const MessageDifferencer::MapKeyComparator*
1371 MessageDifferencer ::GetMapKeyComparator(const FieldDescriptor* field) const {
1372  if (!field->is_repeated()) return NULL;
1373  FieldKeyComparatorMap::const_iterator it =
1374  map_field_key_comparator_.find(field);
1375  if (it != map_field_key_comparator_.end()) {
1376  return it->second;
1377  }
1378  if (field->is_map()) {
1379  // field cannot already be treated as list or set since TreatAsList() and
1380  // TreatAsSet() call GetMapKeyComparator() and fail if it returns non-NULL.
1381  return &map_entry_key_comparator_;
1382  }
1383  return NULL;
1384 }
1385 
1386 namespace {
1387 
1388 typedef std::pair<int, const UnknownField*> IndexUnknownFieldPair;
1389 
1390 struct UnknownFieldOrdering {
1391  inline bool operator()(const IndexUnknownFieldPair& a,
1392  const IndexUnknownFieldPair& b) const {
1393  if (a.second->number() < b.second->number()) return true;
1394  if (a.second->number() > b.second->number()) return false;
1395  return a.second->type() < b.second->type();
1396  }
1397 };
1398 
1399 } // namespace
1400 
1401 bool MessageDifferencer::UnpackAnyField::UnpackAny(
1402  const Message& any, std::unique_ptr<Message>* data) {
1403  const Reflection* reflection = any.GetReflection();
1404  const FieldDescriptor* type_url_field;
1405  const FieldDescriptor* value_field;
1406  if (!internal::GetAnyFieldDescriptors(any, &type_url_field, &value_field)) {
1407  return false;
1408  }
1409  const std::string& type_url = reflection->GetString(any, type_url_field);
1410  std::string full_type_name;
1411  if (!internal::ParseAnyTypeUrl(type_url, &full_type_name)) {
1412  return false;
1413  }
1414 
1415  const Descriptor* desc =
1417  full_type_name);
1418  if (desc == NULL) {
1419  GOOGLE_LOG(INFO) << "Proto type '" << full_type_name << "' not found";
1420  return false;
1421  }
1422 
1423  if (dynamic_message_factory_ == NULL) {
1424  dynamic_message_factory_.reset(new DynamicMessageFactory());
1425  }
1426  data->reset(dynamic_message_factory_->GetPrototype(desc)->New());
1427  std::string serialized_value = reflection->GetString(any, value_field);
1428  if (!(*data)->ParsePartialFromString(serialized_value)) {
1429  GOOGLE_DLOG(ERROR) << "Failed to parse value for " << full_type_name;
1430  return false;
1431  }
1432  return true;
1433 }
1434 
1435 bool MessageDifferencer::CompareUnknownFields(
1436  const Message& message1, const Message& message2,
1437  const UnknownFieldSet& unknown_field_set1,
1438  const UnknownFieldSet& unknown_field_set2,
1439  std::vector<SpecificField>* parent_field) {
1440  // Ignore unknown fields in EQUIVALENT mode.
1441  if (message_field_comparison_ == EQUIVALENT) return true;
1442 
1443  if (unknown_field_set1.empty() && unknown_field_set2.empty()) {
1444  return true;
1445  }
1446 
1447  bool is_different = false;
1448 
1449  // We first sort the unknown fields by field number and type (in other words,
1450  // in tag order), making sure to preserve ordering of values with the same
1451  // tag. This allows us to report only meaningful differences between the
1452  // two sets -- that is, differing values for the same tag. We use
1453  // IndexUnknownFieldPairs to keep track of the field's original index for
1454  // reporting purposes.
1455  std::vector<IndexUnknownFieldPair> fields1; // unknown_field_set1, sorted
1456  std::vector<IndexUnknownFieldPair> fields2; // unknown_field_set2, sorted
1457  fields1.reserve(unknown_field_set1.field_count());
1458  fields2.reserve(unknown_field_set2.field_count());
1459 
1460  for (int i = 0; i < unknown_field_set1.field_count(); i++) {
1461  fields1.push_back(std::make_pair(i, &unknown_field_set1.field(i)));
1462  }
1463  for (int i = 0; i < unknown_field_set2.field_count(); i++) {
1464  fields2.push_back(std::make_pair(i, &unknown_field_set2.field(i)));
1465  }
1466 
1467  UnknownFieldOrdering is_before;
1468  std::stable_sort(fields1.begin(), fields1.end(), is_before);
1469  std::stable_sort(fields2.begin(), fields2.end(), is_before);
1470 
1471  // In order to fill in SpecificField::index, we have to keep track of how
1472  // many values we've seen with the same field number and type.
1473  // current_repeated points at the first field in this range, and
1474  // current_repeated_start{1,2} are the indexes of the first field in the
1475  // range within fields1 and fields2.
1476  const UnknownField* current_repeated = NULL;
1477  int current_repeated_start1 = 0;
1478  int current_repeated_start2 = 0;
1479 
1480  // Now that we have two sorted lists, we can detect fields which appear only
1481  // in one list or the other by traversing them simultaneously.
1482  size_t index1 = 0;
1483  size_t index2 = 0;
1484  while (index1 < fields1.size() || index2 < fields2.size()) {
1485  enum {
1486  ADDITION,
1487  DELETION,
1488  MODIFICATION,
1489  COMPARE_GROUPS,
1490  NO_CHANGE
1491  } change_type;
1492 
1493  // focus_field is the field we're currently reporting on. (In the case
1494  // of a modification, it's the field on the left side.)
1495  const UnknownField* focus_field;
1496  bool match = false;
1497 
1498  if (index2 == fields2.size() ||
1499  (index1 < fields1.size() &&
1500  is_before(fields1[index1], fields2[index2]))) {
1501  // fields1[index1] is not present in fields2.
1502  change_type = DELETION;
1503  focus_field = fields1[index1].second;
1504  } else if (index1 == fields1.size() ||
1505  is_before(fields2[index2], fields1[index1])) {
1506  // fields2[index2] is not present in fields1.
1507  if (scope_ == PARTIAL) {
1508  // Ignore.
1509  ++index2;
1510  continue;
1511  }
1512  change_type = ADDITION;
1513  focus_field = fields2[index2].second;
1514  } else {
1515  // Field type and number are the same. See if the values differ.
1516  change_type = MODIFICATION;
1517  focus_field = fields1[index1].second;
1518 
1519  switch (focus_field->type()) {
1521  match = fields1[index1].second->varint() ==
1522  fields2[index2].second->varint();
1523  break;
1525  match = fields1[index1].second->fixed32() ==
1526  fields2[index2].second->fixed32();
1527  break;
1529  match = fields1[index1].second->fixed64() ==
1530  fields2[index2].second->fixed64();
1531  break;
1533  match = fields1[index1].second->length_delimited() ==
1534  fields2[index2].second->length_delimited();
1535  break;
1537  // We must deal with this later, after building the SpecificField.
1538  change_type = COMPARE_GROUPS;
1539  break;
1540  }
1541  if (match && change_type != COMPARE_GROUPS) {
1542  change_type = NO_CHANGE;
1543  }
1544  }
1545 
1546  if (current_repeated == NULL ||
1547  focus_field->number() != current_repeated->number() ||
1548  focus_field->type() != current_repeated->type()) {
1549  // We've started a new repeated field.
1550  current_repeated = focus_field;
1551  current_repeated_start1 = index1;
1552  current_repeated_start2 = index2;
1553  }
1554 
1555  if (change_type == NO_CHANGE && reporter_ == NULL) {
1556  // Fields were already compared and matched and we have no reporter.
1557  ++index1;
1558  ++index2;
1559  continue;
1560  }
1561 
1562  // Build the SpecificField. This is slightly complicated.
1563  SpecificField specific_field;
1564  specific_field.unknown_field_number = focus_field->number();
1565  specific_field.unknown_field_type = focus_field->type();
1566 
1567  specific_field.unknown_field_set1 = &unknown_field_set1;
1568  specific_field.unknown_field_set2 = &unknown_field_set2;
1569 
1570  if (change_type != ADDITION) {
1571  specific_field.unknown_field_index1 = fields1[index1].first;
1572  }
1573  if (change_type != DELETION) {
1574  specific_field.unknown_field_index2 = fields2[index2].first;
1575  }
1576 
1577  // Calculate the field index.
1578  if (change_type == ADDITION) {
1579  specific_field.index = index2 - current_repeated_start2;
1580  specific_field.new_index = index2 - current_repeated_start2;
1581  } else {
1582  specific_field.index = index1 - current_repeated_start1;
1583  specific_field.new_index = index2 - current_repeated_start2;
1584  }
1585 
1586  if (IsUnknownFieldIgnored(message1, message2, specific_field,
1587  *parent_field)) {
1588  if (report_ignores_ && reporter_ != NULL) {
1589  parent_field->push_back(specific_field);
1590  reporter_->ReportUnknownFieldIgnored(message1, message2, *parent_field);
1591  parent_field->pop_back();
1592  }
1593  if (change_type != ADDITION) ++index1;
1594  if (change_type != DELETION) ++index2;
1595  continue;
1596  }
1597 
1598  if (change_type == ADDITION || change_type == DELETION ||
1599  change_type == MODIFICATION) {
1600  if (reporter_ == NULL) {
1601  // We found a difference and we have no reporter.
1602  return false;
1603  }
1604  is_different = true;
1605  }
1606 
1607  parent_field->push_back(specific_field);
1608 
1609  switch (change_type) {
1610  case ADDITION:
1611  reporter_->ReportAdded(message1, message2, *parent_field);
1612  ++index2;
1613  break;
1614  case DELETION:
1615  reporter_->ReportDeleted(message1, message2, *parent_field);
1616  ++index1;
1617  break;
1618  case MODIFICATION:
1619  reporter_->ReportModified(message1, message2, *parent_field);
1620  ++index1;
1621  ++index2;
1622  break;
1623  case COMPARE_GROUPS:
1624  if (!CompareUnknownFields(
1625  message1, message2, fields1[index1].second->group(),
1626  fields2[index2].second->group(), parent_field)) {
1627  if (reporter_ == NULL) return false;
1628  is_different = true;
1629  reporter_->ReportModified(message1, message2, *parent_field);
1630  }
1631  ++index1;
1632  ++index2;
1633  break;
1634  case NO_CHANGE:
1635  ++index1;
1636  ++index2;
1637  if (report_matches_) {
1638  reporter_->ReportMatched(message1, message2, *parent_field);
1639  }
1640  }
1641 
1642  parent_field->pop_back();
1643  }
1644 
1645  return !is_different;
1646 }
1647 
1648 namespace {
1649 
1650 // Find maximum bipartite matching using the argumenting path algorithm.
1651 class MaximumMatcher {
1652  public:
1653  typedef std::function<bool(int, int)> NodeMatchCallback;
1654  // MaximumMatcher takes ownership of the passed in callback and uses it to
1655  // determine whether a node on the left side of the bipartial graph matches
1656  // a node on the right side. count1 is the number of nodes on the left side
1657  // of the graph and count2 to is the number of nodes on the right side.
1658  // Every node is referred to using 0-based indices.
1659  // If a maximum match is found, the result will be stored in match_list1 and
1660  // match_list2. match_list1[i] == j means the i-th node on the left side is
1661  // matched to the j-th node on the right side and match_list2[x] == y means
1662  // the x-th node on the right side is matched to y-th node on the left side.
1663  // match_list1[i] == -1 means the node is not matched. Same with match_list2.
1664  MaximumMatcher(int count1, int count2, NodeMatchCallback callback,
1665  std::vector<int>* match_list1, std::vector<int>* match_list2);
1666  // Find a maximum match and return the number of matched node pairs.
1667  // If early_return is true, this method will return 0 immediately when it
1668  // finds that not all nodes on the left side can be matched.
1669  int FindMaximumMatch(bool early_return);
1670 
1671  private:
1672  // Determines whether the node on the left side of the bipartial graph
1673  // matches the one on the right side.
1674  bool Match(int left, int right);
1675  // Find an argumenting path starting from the node v on the left side. If a
1676  // path can be found, update match_list2_ to reflect the path and return
1677  // true.
1678  bool FindArgumentPathDFS(int v, std::vector<bool>* visited);
1679 
1680  int count1_;
1681  int count2_;
1682  NodeMatchCallback match_callback_;
1683  std::map<std::pair<int, int>, bool> cached_match_results_;
1684  std::vector<int>* match_list1_;
1685  std::vector<int>* match_list2_;
1686  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MaximumMatcher);
1687 };
1688 
1689 MaximumMatcher::MaximumMatcher(int count1, int count2,
1690  NodeMatchCallback callback,
1691  std::vector<int>* match_list1,
1692  std::vector<int>* match_list2)
1693  : count1_(count1),
1694  count2_(count2),
1696  match_list1_(match_list1),
1697  match_list2_(match_list2) {
1698  match_list1_->assign(count1, -1);
1699  match_list2_->assign(count2, -1);
1700 }
1701 
1702 int MaximumMatcher::FindMaximumMatch(bool early_return) {
1703  int result = 0;
1704  for (int i = 0; i < count1_; ++i) {
1705  std::vector<bool> visited(count1_);
1706  if (FindArgumentPathDFS(i, &visited)) {
1707  ++result;
1708  } else if (early_return) {
1709  return 0;
1710  }
1711  }
1712  // Backfill match_list1_ as we only filled match_list2_ when finding
1713  // argumenting paths.
1714  for (int i = 0; i < count2_; ++i) {
1715  if ((*match_list2_)[i] != -1) {
1716  (*match_list1_)[(*match_list2_)[i]] = i;
1717  }
1718  }
1719  return result;
1720 }
1721 
1722 bool MaximumMatcher::Match(int left, int right) {
1723  std::pair<int, int> p(left, right);
1724  std::map<std::pair<int, int>, bool>::iterator it =
1725  cached_match_results_.find(p);
1726  if (it != cached_match_results_.end()) {
1727  return it->second;
1728  }
1729  cached_match_results_[p] = match_callback_(left, right);
1730  return cached_match_results_[p];
1731 }
1732 
1733 bool MaximumMatcher::FindArgumentPathDFS(int v, std::vector<bool>* visited) {
1734  (*visited)[v] = true;
1735  // We try to match those un-matched nodes on the right side first. This is
1736  // the step that the naive greedy matching algorithm uses. In the best cases
1737  // where the greedy algorithm can find a maximum matching, we will always
1738  // find a match in this step and the performance will be identical to the
1739  // greedy algorithm.
1740  for (int i = 0; i < count2_; ++i) {
1741  int matched = (*match_list2_)[i];
1742  if (matched == -1 && Match(v, i)) {
1743  (*match_list2_)[i] = v;
1744  return true;
1745  }
1746  }
1747  // Then we try those already matched nodes and see if we can find an
1748  // alternative match for the node matched to them.
1749  // The greedy algorithm will stop before this and fail to produce the
1750  // correct result.
1751  for (int i = 0; i < count2_; ++i) {
1752  int matched = (*match_list2_)[i];
1753  if (matched != -1 && Match(v, i)) {
1754  if (!(*visited)[matched] && FindArgumentPathDFS(matched, visited)) {
1755  (*match_list2_)[i] = v;
1756  return true;
1757  }
1758  }
1759  }
1760  return false;
1761 }
1762 
1763 } // namespace
1764 
1765 bool MessageDifferencer::MatchRepeatedFieldIndices(
1766  const Message& message1, const Message& message2,
1768  const MapKeyComparator* key_comparator,
1769  const std::vector<SpecificField>& parent_fields,
1770  std::vector<int>* match_list1, std::vector<int>* match_list2) {
1771  const int count1 =
1772  message1.GetReflection()->FieldSize(message1, repeated_field);
1773  const int count2 =
1774  message2.GetReflection()->FieldSize(message2, repeated_field);
1775  const bool is_treated_as_smart_set = IsTreatedAsSmartSet(repeated_field);
1776 
1777  match_list1->assign(count1, -1);
1778  match_list2->assign(count2, -1);
1779  // Ensure that we don't report differences during the matching process. Since
1780  // field comparators could potentially use this message differencer object to
1781  // perform further comparisons, turn off reporting here and re-enable it
1782  // before returning.
1783  Reporter* reporter = reporter_;
1784  reporter_ = NULL;
1785  NumDiffsReporter num_diffs_reporter;
1786  std::vector<int32_t> num_diffs_list1;
1787  if (is_treated_as_smart_set) {
1788  num_diffs_list1.assign(count1, std::numeric_limits<int32_t>::max());
1789  }
1790 
1791  bool success = true;
1792  // Find potential match if this is a special repeated field.
1793  if (scope_ == PARTIAL) {
1794  // When partial matching is enabled, Compare(a, b) && Compare(a, c)
1795  // doesn't necessarily imply Compare(b, c). Therefore a naive greedy
1796  // algorithm will fail to find a maximum matching.
1797  // Here we use the augmenting path algorithm.
1798  auto callback = [&](int i1, int i2) {
1799  return IsMatch(repeated_field, key_comparator, &message1, &message2,
1800  parent_fields, nullptr, i1, i2);
1801  };
1802  MaximumMatcher matcher(count1, count2, std::move(callback), match_list1,
1803  match_list2);
1804  // If diff info is not needed, we should end the matching process as
1805  // soon as possible if not all items can be matched.
1806  bool early_return = (reporter == nullptr);
1807  int match_count = matcher.FindMaximumMatch(early_return);
1808  if (match_count != count1 && early_return) return false;
1809  success = success && (match_count == count1);
1810  } else {
1811  int start_offset = 0;
1812  // If the two repeated fields are treated as sets, optimize for the case
1813  // where both start with same items stored in the same order.
1814  if (IsTreatedAsSet(repeated_field) || is_treated_as_smart_set ||
1815  IsTreatedAsSmartList(repeated_field)) {
1816  start_offset = std::min(count1, count2);
1817  for (int i = 0; i < count1 && i < count2; i++) {
1818  if (IsMatch(repeated_field, key_comparator, &message1, &message2,
1819  parent_fields, nullptr, i, i)) {
1820  match_list1->at(i) = i;
1821  match_list2->at(i) = i;
1822  } else {
1823  start_offset = i;
1824  break;
1825  }
1826  }
1827  }
1828  for (int i = start_offset; i < count1; ++i) {
1829  // Indicates any matched elements for this repeated field.
1830  bool match = false;
1831  int matched_j = -1;
1832 
1833  for (int j = start_offset; j < count2; j++) {
1834  if (match_list2->at(j) != -1) {
1835  if (!is_treated_as_smart_set || num_diffs_list1[i] == 0 ||
1836  num_diffs_list1[match_list2->at(j)] == 0) {
1837  continue;
1838  }
1839  }
1840 
1841  if (is_treated_as_smart_set) {
1842  num_diffs_reporter.Reset();
1843  match = IsMatch(repeated_field, key_comparator, &message1, &message2,
1844  parent_fields, &num_diffs_reporter, i, j);
1845  } else {
1846  match = IsMatch(repeated_field, key_comparator, &message1, &message2,
1847  parent_fields, nullptr, i, j);
1848  }
1849 
1850  if (is_treated_as_smart_set) {
1851  if (match) {
1852  num_diffs_list1[i] = 0;
1853  } else if (repeated_field->cpp_type() ==
1854  FieldDescriptor::CPPTYPE_MESSAGE) {
1855  // Replace with the one with fewer diffs.
1856  const int32_t num_diffs = num_diffs_reporter.GetNumDiffs();
1857  if (num_diffs < num_diffs_list1[i]) {
1858  // If j has been already matched to some element, ensure the
1859  // current num_diffs is smaller.
1860  if (match_list2->at(j) == -1 ||
1861  num_diffs < num_diffs_list1[match_list2->at(j)]) {
1862  num_diffs_list1[i] = num_diffs;
1863  match = true;
1864  }
1865  }
1866  }
1867  }
1868 
1869  if (match) {
1870  matched_j = j;
1871  if (!is_treated_as_smart_set || num_diffs_list1[i] == 0) {
1872  break;
1873  }
1874  }
1875  }
1876 
1877  match = (matched_j != -1);
1878  if (match) {
1879  if (is_treated_as_smart_set && match_list2->at(matched_j) != -1) {
1880  // This is to revert the previously matched index in list2.
1881  match_list1->at(match_list2->at(matched_j)) = -1;
1882  match = false;
1883  }
1884  match_list1->at(i) = matched_j;
1885  match_list2->at(matched_j) = i;
1886  }
1887  if (!match && reporter == nullptr) return false;
1888  success = success && match;
1889  }
1890  }
1891 
1892  if (IsTreatedAsSmartList(repeated_field)) {
1893  match_indices_for_smart_list_callback_(match_list1, match_list2);
1894  }
1895 
1896  reporter_ = reporter;
1897 
1898  return success;
1899 }
1900 
1901 FieldComparator::ComparisonResult MessageDifferencer::GetFieldComparisonResult(
1902  const Message& message1, const Message& message2,
1903  const FieldDescriptor* field, int index1, int index2,
1904  const FieldContext* field_context) {
1905  FieldComparator* comparator = field_comparator_kind_ == kFCBase
1906  ? field_comparator_.base
1907  : field_comparator_.default_impl;
1908  return comparator->Compare(message1, message2, field, index1, index2,
1909  field_context);
1910 }
1911 
1912 // ===========================================================================
1913 
1914 MessageDifferencer::Reporter::Reporter() {}
1915 MessageDifferencer::Reporter::~Reporter() {}
1916 
1917 // ===========================================================================
1918 
1919 MessageDifferencer::MapKeyComparator::MapKeyComparator() {}
1920 MessageDifferencer::MapKeyComparator::~MapKeyComparator() {}
1921 
1922 // ===========================================================================
1923 
1924 MessageDifferencer::IgnoreCriteria::IgnoreCriteria() {}
1925 MessageDifferencer::IgnoreCriteria::~IgnoreCriteria() {}
1926 
1927 // ===========================================================================
1928 
1929 // Note that the printer's delimiter is not used, because if we are given a
1930 // printer, we don't know its delimiter.
1931 MessageDifferencer::StreamReporter::StreamReporter(
1933  : printer_(new io::Printer(output, '$')),
1934  delete_printer_(true),
1935  report_modified_aggregates_(false),
1936  message1_(nullptr),
1937  message2_(nullptr) {}
1938 
1939 MessageDifferencer::StreamReporter::StreamReporter(io::Printer* printer)
1940  : printer_(printer),
1941  delete_printer_(false),
1942  report_modified_aggregates_(false),
1943  message1_(nullptr),
1944  message2_(nullptr) {}
1945 
1946 MessageDifferencer::StreamReporter::~StreamReporter() {
1947  if (delete_printer_) delete printer_;
1948 }
1949 
1950 void MessageDifferencer::StreamReporter::PrintPath(
1951  const std::vector<SpecificField>& field_path, bool left_side) {
1952  for (size_t i = 0; i < field_path.size(); ++i) {
1953  SpecificField specific_field = field_path[i];
1954 
1955  if (specific_field.field != nullptr &&
1956  specific_field.field->name() == "value") {
1957  // check to see if this the value label of a map value. If so, skip it
1958  // because it isn't meaningful
1959  if (i > 0 && field_path[i - 1].field->is_map()) {
1960  continue;
1961  }
1962  }
1963  if (i > 0) {
1964  printer_->Print(".");
1965  }
1966  if (specific_field.field != NULL) {
1967  if (specific_field.field->is_extension()) {
1968  printer_->Print("($name$)", "name", specific_field.field->full_name());
1969  } else {
1970  printer_->PrintRaw(specific_field.field->name());
1971  }
1972 
1973  if (specific_field.field->is_map()) {
1974  PrintMapKey(left_side, specific_field);
1975  continue;
1976  }
1977  } else {
1978  printer_->PrintRaw(StrCat(specific_field.unknown_field_number));
1979  }
1980  if (left_side && specific_field.index >= 0) {
1981  printer_->Print("[$name$]", "name", StrCat(specific_field.index));
1982  }
1983  if (!left_side && specific_field.new_index >= 0) {
1984  printer_->Print("[$name$]", "name",
1985  StrCat(specific_field.new_index));
1986  }
1987  }
1988 }
1989 
1990 
1992  const Message& message, const std::vector<SpecificField>& field_path,
1993  bool left_side) {
1994  const SpecificField& specific_field = field_path.back();
1995  const FieldDescriptor* field = specific_field.field;
1996  if (field != NULL) {
1998  int index = left_side ? specific_field.index : specific_field.new_index;
1999  if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
2000  const Reflection* reflection = message.GetReflection();
2001  const Message& field_message =
2002  field->is_repeated()
2003  ? reflection->GetRepeatedMessage(message, field, index)
2004  : reflection->GetMessage(message, field);
2005  const FieldDescriptor* fd = nullptr;
2006 
2007  if (field->is_map() && message1_ != nullptr && message2_ != nullptr) {
2008  fd = field_message.GetDescriptor()->field(1);
2009  if (fd->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
2010  output = field_message.GetReflection()
2011  ->GetMessage(field_message, fd)
2012  .ShortDebugString();
2013  } else {
2014  TextFormat::PrintFieldValueToString(field_message, fd, -1, &output);
2015  }
2016  } else {
2017  output = field_message.ShortDebugString();
2018  }
2019  if (output.empty()) {
2020  printer_->Print("{ }");
2021  } else {
2022  if ((fd != nullptr) &&
2023  (fd->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE)) {
2025  } else {
2026  printer_->Print("{ $name$ }", "name", output);
2027  }
2028  }
2029  } else {
2030  TextFormat::PrintFieldValueToString(message, field, index, &output);
2032  }
2033  } else {
2034  const UnknownFieldSet* unknown_fields =
2035  (left_side ? specific_field.unknown_field_set1
2036  : specific_field.unknown_field_set2);
2037  const UnknownField* unknown_field =
2038  &unknown_fields->field(left_side ? specific_field.unknown_field_index1
2039  : specific_field.unknown_field_index2);
2040  PrintUnknownFieldValue(unknown_field);
2041  }
2042 }
2043 
2044 void MessageDifferencer::StreamReporter::PrintUnknownFieldValue(
2045  const UnknownField* unknown_field) {
2046  GOOGLE_CHECK(unknown_field != NULL) << " Cannot print NULL unknown_field.";
2047 
2049  switch (unknown_field->type()) {
2050  case UnknownField::TYPE_VARINT:
2051  output = StrCat(unknown_field->varint());
2052  break;
2053  case UnknownField::TYPE_FIXED32:
2054  output = StrCat(
2055  "0x", strings::Hex(unknown_field->fixed32(), strings::ZERO_PAD_8));
2056  break;
2057  case UnknownField::TYPE_FIXED64:
2058  output = StrCat(
2059  "0x", strings::Hex(unknown_field->fixed64(), strings::ZERO_PAD_16));
2060  break;
2061  case UnknownField::TYPE_LENGTH_DELIMITED:
2062  output = StringPrintf(
2063  "\"%s\"", CEscape(unknown_field->length_delimited()).c_str());
2064  break;
2065  case UnknownField::TYPE_GROUP:
2066  // TODO(kenton): Print the contents of the group like we do for
2067  // messages. Requires an equivalent of ShortDebugString() for
2068  // UnknownFieldSet.
2069  output = "{ ... }";
2070  break;
2071  }
2073 }
2074 
2076  printer_->Print(str.c_str());
2077 }
2078 
2079 void MessageDifferencer::StreamReporter::PrintMapKey(
2080  bool left_side, const SpecificField& specific_field) {
2081  if (message1_ == nullptr || message2_ == nullptr) {
2082  GOOGLE_LOG(INFO) << "PrintPath cannot log map keys; "
2083  "use SetMessages to provide the messages "
2084  "being compared prior to any processing.";
2085  return;
2086  }
2087 
2088  const Message* found_message =
2089  left_side ? specific_field.map_entry1 : specific_field.map_entry2;
2090  std::string key_string = "";
2091  if (found_message != nullptr) {
2092  // NB: the map key is always the first field
2093  const FieldDescriptor* fd = found_message->GetDescriptor()->field(0);
2094  if (fd->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
2095  // Not using PrintFieldValueToString for strings to avoid extra
2096  // characters
2097  key_string = found_message->GetReflection()->GetString(
2098  *found_message, found_message->GetDescriptor()->field(0));
2099  } else {
2100  TextFormat::PrintFieldValueToString(*found_message, fd, -1, &key_string);
2101  }
2102  if (key_string.empty()) {
2103  key_string = "''";
2104  }
2105  printer_->PrintRaw(StrCat("[", key_string, "]"));
2106  }
2107 }
2108 
2109 void MessageDifferencer::StreamReporter::ReportAdded(
2110  const Message& /*message1*/, const Message& message2,
2111  const std::vector<SpecificField>& field_path) {
2112  printer_->Print("added: ");
2113  PrintPath(field_path, false);
2114  printer_->Print(": ");
2115  PrintValue(message2, field_path, false);
2116  printer_->Print("\n"); // Print for newlines.
2117 }
2118 
2119 void MessageDifferencer::StreamReporter::ReportDeleted(
2120  const Message& message1, const Message& /*message2*/,
2121  const std::vector<SpecificField>& field_path) {
2122  printer_->Print("deleted: ");
2123  PrintPath(field_path, true);
2124  printer_->Print(": ");
2125  PrintValue(message1, field_path, true);
2126  printer_->Print("\n"); // Print for newlines
2127 }
2128 
2129 void MessageDifferencer::StreamReporter::ReportModified(
2130  const Message& message1, const Message& message2,
2131  const std::vector<SpecificField>& field_path) {
2132  if (!report_modified_aggregates_ && field_path.back().field == NULL) {
2133  if (field_path.back().unknown_field_type == UnknownField::TYPE_GROUP) {
2134  // Any changes to the subfields have already been printed.
2135  return;
2136  }
2137  } else if (!report_modified_aggregates_) {
2138  if (field_path.back().field->cpp_type() ==
2139  FieldDescriptor::CPPTYPE_MESSAGE) {
2140  // Any changes to the subfields have already been printed.
2141  return;
2142  }
2143  }
2144 
2145  printer_->Print("modified: ");
2146  PrintPath(field_path, true);
2147  if (CheckPathChanged(field_path)) {
2148  printer_->Print(" -> ");
2149  PrintPath(field_path, false);
2150  }
2151  printer_->Print(": ");
2152  PrintValue(message1, field_path, true);
2153  printer_->Print(" -> ");
2154  PrintValue(message2, field_path, false);
2155  printer_->Print("\n"); // Print for newlines.
2156 }
2157 
2158 void MessageDifferencer::StreamReporter::ReportMoved(
2159  const Message& message1, const Message& /*message2*/,
2160  const std::vector<SpecificField>& field_path) {
2161  printer_->Print("moved: ");
2162  PrintPath(field_path, true);
2163  printer_->Print(" -> ");
2164  PrintPath(field_path, false);
2165  printer_->Print(" : ");
2166  PrintValue(message1, field_path, true);
2167  printer_->Print("\n"); // Print for newlines.
2168 }
2169 
2170 void MessageDifferencer::StreamReporter::ReportMatched(
2171  const Message& message1, const Message& /*message2*/,
2172  const std::vector<SpecificField>& field_path) {
2173  printer_->Print("matched: ");
2174  PrintPath(field_path, true);
2175  if (CheckPathChanged(field_path)) {
2176  printer_->Print(" -> ");
2177  PrintPath(field_path, false);
2178  }
2179  printer_->Print(" : ");
2180  PrintValue(message1, field_path, true);
2181  printer_->Print("\n"); // Print for newlines.
2182 }
2183 
2184 void MessageDifferencer::StreamReporter::ReportIgnored(
2185  const Message& /*message1*/, const Message& /*message2*/,
2186  const std::vector<SpecificField>& field_path) {
2187  printer_->Print("ignored: ");
2188  PrintPath(field_path, true);
2189  if (CheckPathChanged(field_path)) {
2190  printer_->Print(" -> ");
2191  PrintPath(field_path, false);
2192  }
2193  printer_->Print("\n"); // Print for newlines.
2194 }
2195 
2196 void MessageDifferencer::StreamReporter::SetMessages(const Message& message1,
2197  const Message& message2) {
2198  message1_ = &message1;
2199  message2_ = &message2;
2200 }
2201 
2202 void MessageDifferencer::StreamReporter::ReportUnknownFieldIgnored(
2203  const Message& /*message1*/, const Message& /*message2*/,
2204  const std::vector<SpecificField>& field_path) {
2205  printer_->Print("ignored: ");
2206  PrintPath(field_path, true);
2207  if (CheckPathChanged(field_path)) {
2208  printer_->Print(" -> ");
2209  PrintPath(field_path, false);
2210  }
2211  printer_->Print("\n"); // Print for newlines.
2212 }
2213 
2214 MessageDifferencer::MapKeyComparator*
2215 MessageDifferencer::CreateMultipleFieldsMapKeyComparator(
2216  const std::vector<std::vector<const FieldDescriptor*> >& key_field_paths) {
2217  return new MultipleFieldsMapKeyComparator(this, key_field_paths);
2218 }
2219 
2220 } // namespace util
2221 } // namespace protobuf
2222 } // namespace google
xds_interop_client.str
str
Definition: xds_interop_client.py:487
google::protobuf::util::MessageDifferencer::CompareFieldValueUsingParentFields
bool CompareFieldValueUsingParentFields(const Message &message1, const Message &message2, const FieldDescriptor *field, int index1, int index2, std::vector< SpecificField > *parent_fields)
Definition: bloaty/third_party/protobuf/src/google/protobuf/util/message_differencer.cc:1070
google::protobuf::Reflection::GetString
std::string GetString(const Message &message, const FieldDescriptor *field) const
Definition: bloaty/third_party/protobuf/src/google/protobuf/generated_message_reflection.cc:1151
_gevent_test_main.result
result
Definition: _gevent_test_main.py:96
google::protobuf::util::NumDiffsReporter::ReportAdded
void ReportAdded(const google::protobuf::Message &, const google::protobuf::Message &, const std::vector< google::protobuf::util::MessageDifferencer::SpecificField > &) override
Definition: protobuf/src/google/protobuf/util/message_differencer.cc:80
google::protobuf::util::NumDiffsReporter::ReportDeleted
void ReportDeleted(const google::protobuf::Message &, const google::protobuf::Message &, const std::vector< google::protobuf::util::MessageDifferencer::SpecificField > &) override
Definition: protobuf/src/google/protobuf/util/message_differencer.cc:89
DoubleValue
Definition: bloaty/third_party/protobuf/src/google/protobuf/wrappers.pb.h:101
match_callback_
NodeMatchCallback match_callback_
Definition: protobuf/src/google/protobuf/util/message_differencer.cc:1682
regen-readme.it
it
Definition: regen-readme.py:15
re2::IsMatch
static bool IsMatch(Prog *, Prog::Inst *)
Definition: bloaty/third_party/re2/re2/prog.cc:262
google::protobuf::FieldDescriptor
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.h:515
absl::str_format_internal::LengthMod::j
@ j
google::protobuf::util::MessageDifferencer
Definition: bloaty/third_party/protobuf/src/google/protobuf/util/message_differencer.h:120
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS
#define GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TypeName)
Definition: bloaty/third_party/protobuf/src/google/protobuf/stubs/macros.h:40
bool
bool
Definition: setup_once.h:312
testing::internal::Equals
constexpr bool Equals(const char(&a)[N], const char(&b)[M])
Definition: googletest/googlemock/include/gmock/gmock-function-mocker.h:83
absl::StrCat
std::string StrCat(const AlphaNum &a, const AlphaNum &b)
Definition: abseil-cpp/absl/strings/str_cat.cc:98
testing::internal::Int32
TypeWithSize< 4 >::Int Int32
Definition: bloaty/third_party/googletest/googletest/include/gtest/internal/gtest-port.h:2159
Bool
Definition: bloaty/third_party/googletest/googletest/test/gtest_pred_impl_unittest.cc:56
google::protobuf::util::MessageDifferencer::MultipleFieldsMapKeyComparator
Definition: bloaty/third_party/protobuf/src/google/protobuf/util/message_differencer.cc:106
google::protobuf::FieldDescriptor::full_name
const std::string & full_name() const
false
#define false
Definition: setup_once.h:323
google::protobuf::UnknownField::TYPE_GROUP
@ TYPE_GROUP
Definition: bloaty/third_party/protobuf/src/google/protobuf/unknown_field_set.h:223
grpc_generator::Printer::Print
virtual void Print(const std::map< std::string, std::string > &vars, const char *template_string)=0
google::protobuf.internal::ParseAnyTypeUrl
bool ParseAnyTypeUrl(const std::string &type_url, std::string *full_type_name)
Definition: bloaty/third_party/protobuf/src/google/protobuf/any_lite.cc:116
GOOGLE_DCHECK
#define GOOGLE_DCHECK
Definition: bloaty/third_party/protobuf/src/google/protobuf/stubs/logging.h:194
match
unsigned char match[65280+2]
Definition: bloaty/third_party/zlib/examples/gun.c:165
testing::gtest_printers_test::Print
std::string Print(const T &value)
Definition: bloaty/third_party/googletest/googletest/test/googletest-printers-test.cc:233
copy
static int copy(grpc_slice_buffer *input, grpc_slice_buffer *output)
Definition: message_compress.cc:145
google::protobuf::Message::GetReflection
const Reflection * GetReflection() const
Definition: bloaty/third_party/protobuf/src/google/protobuf/message.h:332
UnknownField
Definition: upb/upb/util/compare_test.cc:66
google::protobuf::FieldDescriptor::message_type
const Descriptor * message_type
Definition: protobuf/src/google/protobuf/descriptor.h:936
GOOGLE_CHECK_EQ
#define GOOGLE_CHECK_EQ(A, B)
Definition: bloaty/third_party/protobuf/src/google/protobuf/stubs/logging.h:156
testing::internal::string
::std::string string
Definition: bloaty/third_party/protobuf/third_party/googletest/googletest/include/gtest/internal/gtest-port.h:881
google::protobuf.internal::kAnyFullTypeName
const char kAnyFullTypeName[]
Definition: bloaty/third_party/protobuf/src/google/protobuf/any_lite.cc:52
google::protobuf::util::MessageDifferencer::Reporter
Definition: bloaty/third_party/protobuf/src/google/protobuf/util/message_differencer.h:228
google::protobuf::util::NumDiffsReporter::num_diffs_
int32 num_diffs_
Definition: bloaty/third_party/protobuf/src/google/protobuf/util/message_differencer.cc:98
grpc::protobuf::io::Printer
GRPC_CUSTOM_PRINTER Printer
Definition: src/compiler/config.h:54
testing::internal::UInt64
TypeWithSize< 8 >::UInt UInt64
Definition: bloaty/third_party/googletest/googletest/include/gtest/internal/gtest-port.h:2162
google::protobuf
Definition: bloaty/third_party/protobuf/benchmarks/util/data_proto2_to_proto3_util.h:12
grpc::protobuf::DynamicMessageFactory
GRPC_CUSTOM_DYNAMICMESSAGEFACTORY DynamicMessageFactory
Definition: config_grpc_cli.h:54
visited
bool visited
Definition: abseil-cpp/absl/synchronization/internal/graphcycles.cc:282
count1_
int count1_
Definition: protobuf/src/google/protobuf/util/message_differencer.cc:1680
PrintValue
::std::string PrintValue(const T &value)
Definition: bloaty/third_party/googletest/googletest/test/googletest-param-test-test.cc:69
grpc::protobuf::io::ZeroCopyOutputStream
GRPC_CUSTOM_ZEROCOPYOUTPUTSTREAM ZeroCopyOutputStream
Definition: include/grpcpp/impl/codegen/config_protobuf.h:100
google::protobuf::strings::ZERO_PAD_8
@ ZERO_PAD_8
Definition: bloaty/third_party/protobuf/src/google/protobuf/stubs/strutil.h:583
check_documentation.path
path
Definition: check_documentation.py:57
a
int a
Definition: abseil-cpp/absl/container/internal/hash_policy_traits_test.cc:88
count2_
int count2_
Definition: protobuf/src/google/protobuf/util/message_differencer.cc:1681
absl::CEscape
std::string CEscape(absl::string_view src)
Definition: abseil-cpp/absl/strings/escaping.cc:854
xds_manager.p
p
Definition: xds_manager.py:60
grpc_generator::Printer::PrintRaw
virtual void PrintRaw(const char *string)=0
second
StrT second
Definition: cxa_demangle.cpp:4885
env.new
def new
Definition: env.py:51
testing::internal::UInt32
TypeWithSize< 4 >::UInt UInt32
Definition: bloaty/third_party/googletest/googletest/include/gtest/internal/gtest-port.h:2160
google::protobuf::Reflection
Definition: bloaty/third_party/protobuf/src/google/protobuf/message.h:397
iterator
const typedef MCPhysReg * iterator
Definition: MCRegisterInfo.h:27
google::protobuf::Reflection::HasField
bool HasField(const Message &message, const FieldDescriptor *field) const
Definition: bloaty/third_party/protobuf/src/google/protobuf/generated_message_reflection.cc:728
google::protobuf::Reflection::ContainsMapKey
bool ContainsMapKey(const Message &message, const FieldDescriptor *field, const MapKey &key) const
Definition: bloaty/third_party/protobuf/src/google/protobuf/generated_message_reflection.cc:1762
google::protobuf::HANDLE_TYPE
HANDLE_TYPE(int32, FieldDescriptor::CPPTYPE_INT32, -1)
EnumValue
Definition: bloaty/third_party/protobuf/src/google/protobuf/type.pb.h:1105
google::protobuf::strings::ZERO_PAD_16
@ ZERO_PAD_16
Definition: bloaty/third_party/protobuf/src/google/protobuf/stubs/strutil.h:591
google::protobuf::python::cmessage::UnknownFieldSet
static PyObject * UnknownFieldSet(CMessage *self)
Definition: bloaty/third_party/protobuf/python/google/protobuf/pyext/message.cc:2512
google::protobuf::util::MessageDifferencer::MultipleFieldsMapKeyComparator::GOOGLE_DISALLOW_EVIL_CONSTRUCTORS
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MultipleFieldsMapKeyComparator)
message
char * message
Definition: libuv/docs/code/tty-gravity/main.c:12
google::protobuf::util::MessageDifferencer::CompareMapField
bool CompareMapField(const Message &message1, const Message &message2, const FieldDescriptor *field, std::vector< SpecificField > *parent_fields)
Definition: protobuf/src/google/protobuf/util/message_differencer.cc:1047
google::protobuf::Reflection::MapSize
int MapSize(const Message &message, const FieldDescriptor *field) const
Definition: bloaty/third_party/protobuf/src/google/protobuf/generated_message_reflection.cc:1804
BOOL
int BOOL
Definition: undname.c:46
repeated_field
PHP_PROTO_OBJECT_FREE_END PHP_PROTO_OBJECT_DTOR_END intern repeated_field
Definition: bloaty/third_party/protobuf/php/ext/google/protobuf/array.c:486
Descriptor
Definition: bloaty/third_party/protobuf/ruby/ext/google/protobuf_c/protobuf.h:121
true
#define true
Definition: setup_once.h:324
google::protobuf::UnknownFieldSet::field_count
int field_count() const
Definition: bloaty/third_party/protobuf/src/google/protobuf/unknown_field_set.h:308
grpc::protobuf::io::StringOutputStream
GRPC_CUSTOM_STRINGOUTPUTSTREAM StringOutputStream
Definition: src/compiler/config.h:56
FieldDescriptor
Definition: bloaty/third_party/protobuf/ruby/ext/google/protobuf_c/protobuf.h:133
google::protobuf::Descriptor::field
const FieldDescriptor * field(int index) const
google::protobuf::UnknownField::TYPE_FIXED32
@ TYPE_FIXED32
Definition: bloaty/third_party/protobuf/src/google/protobuf/unknown_field_set.h:220
google::protobuf::util::MessageDifferencer::SpecificField
Definition: bloaty/third_party/protobuf/src/google/protobuf/util/message_differencer.h:176
Int64Value
Definition: bloaty/third_party/protobuf/src/google/protobuf/wrappers.pb.h:403
google::protobuf::util::AddSpecificIndex
void AddSpecificIndex(google::protobuf::util::MessageDifferencer::SpecificField *specific_field, const Message &message, const FieldDescriptor *field, int index)
Definition: protobuf/src/google/protobuf/util/message_differencer.cc:210
i1
int i1
Definition: abseil-cpp/absl/container/btree_test.cc:2772
absl::move
constexpr absl::remove_reference_t< T > && move(T &&t) noexcept
Definition: abseil-cpp/absl/utility/utility.h:221
int64_t
signed __int64 int64_t
Definition: stdint-msvc2008.h:89
max
int max
Definition: bloaty/third_party/zlib/examples/enough.c:170
gmock_output_test.output
output
Definition: bloaty/third_party/googletest/googlemock/test/gmock_output_test.py:175
python_utils.jobset.INFO
INFO
Definition: jobset.py:111
google::protobuf::FileDescriptor::pool
const DescriptorPool * pool() const
setup.v
v
Definition: third_party/bloaty/third_party/capstone/bindings/python/setup.py:42
match_list2_
std::vector< int > * match_list2_
Definition: protobuf/src/google/protobuf/util/message_differencer.cc:1685
google::protobuf::util::MessageDifferencer::MultipleFieldsMapKeyComparator::MultipleFieldsMapKeyComparator
MultipleFieldsMapKeyComparator(MessageDifferencer *message_differencer, const std::vector< std::vector< const FieldDescriptor * > > &key_field_paths)
Definition: protobuf/src/google/protobuf/util/message_differencer.cc:118
testing::internal::Float
FloatingPoint< float > Float
Definition: bloaty/third_party/googletest/googletest/include/gtest/internal/gtest-internal.h:396
printer_
grpc_generator::Printer * printer_
Definition: src/compiler/python_generator.cc:86
google::protobuf::StringPrintf
string StringPrintf(const char *format,...)
Definition: bloaty/third_party/protobuf/src/google/protobuf/stubs/stringprintf.cc:109
google::protobuf.internal::GetAnyFieldDescriptors
bool GetAnyFieldDescriptors(const Message &message, const FieldDescriptor **type_url_field, const FieldDescriptor **value_field)
Definition: bloaty/third_party/protobuf/src/google/protobuf/any.cc:64
FloatValue
Definition: bloaty/third_party/protobuf/src/google/protobuf/wrappers.pb.h:252
StringValue
Definition: bloaty/third_party/protobuf/src/google/protobuf/wrappers.pb.h:1158
google::protobuf::Reflection::MapBegin
MapIterator MapBegin(Message *message, const FieldDescriptor *field) const
Definition: bloaty/third_party/protobuf/src/google/protobuf/generated_message_reflection.cc:1788
io
google::protobuf::util::MessageDifferencer::MultipleFieldsMapKeyComparator::key_field_paths_
std::vector< std::vector< const FieldDescriptor * > > key_field_paths_
Definition: bloaty/third_party/protobuf/src/google/protobuf/util/message_differencer.cc:179
data
char data[kBufferLength]
Definition: abseil-cpp/absl/strings/internal/str_format/float_conversion.cc:1006
callback
static void callback(void *arg, int status, int timeouts, struct hostent *host)
Definition: acountry.c:224
google::protobuf::MapValueConstRef::GetMessageValue
const Message & GetMessageValue() const
Definition: protobuf/src/google/protobuf/map_field.h:733
google::protobuf::util::MessageDifferencer::SpecificField::map_entry1
const Message * map_entry1
Definition: protobuf/src/google/protobuf/util/message_differencer.h:198
google::protobuf::UnknownField::TYPE_VARINT
@ TYPE_VARINT
Definition: bloaty/third_party/protobuf/src/google/protobuf/unknown_field_set.h:219
min
#define min(a, b)
Definition: qsort.h:83
b
uint64_t b
Definition: abseil-cpp/absl/container/internal/layout_test.cc:53
start_offset
uint16_t start_offset
Definition: protobuf/src/google/protobuf/descriptor.cc:946
google::protobuf::Reflection::FieldSize
int FieldSize(const Message &message, const FieldDescriptor *field) const
Definition: bloaty/third_party/protobuf/src/google/protobuf/generated_message_reflection.cc:744
google::protobuf::ERROR
static const LogLevel ERROR
Definition: bloaty/third_party/protobuf/src/google/protobuf/testing/googletest.h:70
google::protobuf::UnknownField::TYPE_LENGTH_DELIMITED
@ TYPE_LENGTH_DELIMITED
Definition: bloaty/third_party/protobuf/src/google/protobuf/unknown_field_set.h:222
google::protobuf::util::MessageDifferencer::MapKeyComparator
Definition: bloaty/third_party/protobuf/src/google/protobuf/util/message_differencer.h:300
Match
static bool Match(const upb_msgdef *m, const char *name, const upb_fielddef **f, const upb_oneofdef **o, const char *prefix, const char *suffix)
Definition: protobuf/ruby/ext/google/protobuf_c/message.c:195
google::protobuf::util::MessageDifferencer::SpecificField::new_index
int new_index
Definition: bloaty/third_party/protobuf/src/google/protobuf/util/message_differencer.h:193
google::protobuf::util::MatchIndicesPostProcessorForSmartList
void MatchIndicesPostProcessorForSmartList(std::vector< int > *match_list1, std::vector< int > *match_list2)
Definition: bloaty/third_party/protobuf/src/google/protobuf/util/message_differencer.cc:188
google::protobuf::UnknownField::TYPE_FIXED64
@ TYPE_FIXED64
Definition: bloaty/third_party/protobuf/src/google/protobuf/unknown_field_set.h:221
google::protobuf::UnknownFieldSet::field
const UnknownField & field(int index) const
Definition: bloaty/third_party/protobuf/src/google/protobuf/unknown_field_set.h:311
google::protobuf::Message
Definition: bloaty/third_party/protobuf/src/google/protobuf/message.h:205
field
const FieldDescriptor * field
Definition: bloaty/third_party/protobuf/src/google/protobuf/compiler/parser_unittest.cc:2692
key
const char * key
Definition: hpack_parser_table.cc:164
google::protobuf::Message::GetDescriptor
const Descriptor * GetDescriptor() const
Definition: bloaty/third_party/protobuf/src/google/protobuf/message.h:323
scope_
UniquePtr< char > scope_
Definition: oauth2_credentials.cc:652
google::protobuf::util::MessageDifferencer::CompareRepeatedField
bool CompareRepeatedField(const Message &message1, const Message &message2, const FieldDescriptor *field, std::vector< SpecificField > *parent_fields)
Definition: bloaty/third_party/protobuf/src/google/protobuf/util/message_differencer.cc:915
match_list1_
std::vector< int > * match_list1_
Definition: protobuf/src/google/protobuf/util/message_differencer.cc:1684
UInt64Value
Definition: bloaty/third_party/protobuf/src/google/protobuf/wrappers.pb.h:554
count
int * count
Definition: bloaty/third_party/googletest/googlemock/test/gmock_stress_test.cc:96
google::protobuf.internal::MapFieldBase::IsMapValid
bool IsMapValid() const
Definition: bloaty/third_party/protobuf/src/google/protobuf/map_field.cc:72
google::protobuf::UnknownFieldSet::empty
bool empty() const
Definition: bloaty/third_party/protobuf/src/google/protobuf/unknown_field_set.h:302
index
int index
Definition: bloaty/third_party/protobuf/php/ext/google/protobuf/protobuf.h:1184
google::protobuf::util::NumDiffsReporter::NumDiffsReporter
NumDiffsReporter()
Definition: protobuf/src/google/protobuf/util/message_differencer.cc:73
std
Definition: grpcpp/impl/codegen/async_unary_call.h:407
google::protobuf::UnknownFieldSet
Definition: bloaty/third_party/protobuf/src/google/protobuf/unknown_field_set.h:81
testing::internal::Double
FloatingPoint< double > Double
Definition: bloaty/third_party/googletest/googletest/include/gtest/internal/gtest-internal.h:397
google::protobuf::util::NumDiffsReporter::num_diffs_
int32_t num_diffs_
Definition: protobuf/src/google/protobuf/util/message_differencer.cc:107
google::protobuf::Descriptor::file
const FileDescriptor * file() const
type_url
string * type_url
Definition: bloaty/third_party/protobuf/conformance/conformance_cpp.cc:72
GOOGLE_CHECK
#define GOOGLE_CHECK(EXPRESSION)
Definition: bloaty/third_party/protobuf/src/google/protobuf/stubs/logging.h:153
google::protobuf::Descriptor
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.h:231
desc
#define desc
Definition: bloaty/third_party/protobuf/src/google/protobuf/extension_set.h:338
GOOGLE_DLOG
#define GOOGLE_DLOG
Definition: bloaty/third_party/protobuf/src/google/protobuf/stubs/logging.h:192
GOOGLE_DCHECK_EQ
#define GOOGLE_DCHECK_EQ
Definition: bloaty/third_party/protobuf/src/google/protobuf/stubs/logging.h:196
google::protobuf::util::MessageDifferencer::MapEntryKeyComparator::MapEntryKeyComparator
MapEntryKeyComparator(MessageDifferencer *message_differencer)
Definition: bloaty/third_party/protobuf/src/google/protobuf/util/message_differencer.cc:204
absl::strings_internal::Compare
int Compare(const BigUnsigned< N > &lhs, const BigUnsigned< M > &rhs)
Definition: abseil-cpp/absl/strings/internal/charconv_bigint.h:353
google::protobuf::util::NumDiffsReporter::ReportModified
void ReportModified(const google::protobuf::Message &, const google::protobuf::Message &, const std::vector< google::protobuf::util::MessageDifferencer::SpecificField > &) override
Definition: protobuf/src/google/protobuf/util/message_differencer.cc:98
UInt32Value
Definition: bloaty/third_party/protobuf/src/google/protobuf/wrappers.pb.h:856
google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE
@ CPPTYPE_MESSAGE
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.h:563
testing::internal::Int64
TypeWithSize< 8 >::Int Int64
Definition: bloaty/third_party/googletest/googletest/include/gtest/internal/gtest-port.h:2161
google::protobuf::Descriptor::map_value
const FieldDescriptor * map_value() const
Definition: protobuf/src/google/protobuf/descriptor.cc:2326
i2
int i2
Definition: abseil-cpp/absl/container/btree_test.cc:2773
google::protobuf::Reflection::GetMapData
const internal::MapFieldBase * GetMapData(const Message &message, const FieldDescriptor *field) const
Definition: bloaty/third_party/protobuf/src/google/protobuf/generated_message_reflection.cc:2219
google::protobuf::util::MessageDifferencer::SpecificField::index
int index
Definition: bloaty/third_party/protobuf/src/google/protobuf/util/message_differencer.h:187
google::protobuf::util::DefaultFieldComparator
Definition: bloaty/third_party/protobuf/src/google/protobuf/util/field_comparator.h:100
function
std::function< bool(GrpcTool *, int, const char **, const CliCredentials &, GrpcToolOutputCallback)> function
Definition: grpc_tool.cc:250
google::protobuf::MapIterator
Definition: bloaty/third_party/protobuf/src/google/protobuf/map_field.h:712
int32_t
signed int int32_t
Definition: stdint-msvc2008.h:77
cached_match_results_
std::map< std::pair< int, int >, bool > cached_match_results_
Definition: protobuf/src/google/protobuf/util/message_differencer.cc:1683
GOOGLE_LOG
#define GOOGLE_LOG(LEVEL)
Definition: bloaty/third_party/protobuf/src/google/protobuf/stubs/logging.h:146
google::protobuf::util::FieldDescriptorArray
std::vector< const FieldDescriptor * > FieldDescriptorArray
Definition: bloaty/third_party/protobuf/src/google/protobuf/util/message_differencer.h:73
google::protobuf::util::MessageDifferencer::MultipleFieldsMapKeyComparator::IsMatch
bool IsMatch(const Message &message1, const Message &message2, const std::vector< SpecificField > &parent_fields) const override
Definition: protobuf/src/google/protobuf/util/message_differencer.cc:135
google::protobuf::util::NumDiffsReporter::Reset
void Reset()
Definition: protobuf/src/google/protobuf/util/message_differencer.cc:77
descriptor
static const char descriptor[1336]
Definition: certs.upbdefs.c:16
google::protobuf::util::MessageDifferencer::MultipleFieldsMapKeyComparator::message_differencer_
MessageDifferencer * message_differencer_
Definition: bloaty/third_party/protobuf/src/google/protobuf/util/message_differencer.cc:178
google::protobuf::FieldDescriptor::is_repeated
bool is_repeated() const
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.h:2067
google::protobuf::FieldDescriptor::cpp_type
CppType cpp_type() const
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.h:2139
google
Definition: bloaty/third_party/protobuf/benchmarks/util/data_proto2_to_proto3_util.h:11
GOOGLE_CHECK_LE
#define GOOGLE_CHECK_LE(A, B)
Definition: bloaty/third_party/protobuf/src/google/protobuf/stubs/logging.h:159
Message
Definition: protobuf/php/ext/google/protobuf/message.c:53
i
uint64_t i
Definition: abseil-cpp/absl/container/btree_benchmark.cc:230
google::protobuf::Reflection::GetRepeatedMessage
const Message & GetRepeatedMessage(const Message &message, const FieldDescriptor *field, int index) const
Definition: bloaty/third_party/protobuf/src/google/protobuf/generated_message_reflection.cc:1596
google::protobuf::util::MessageDifferencer::MultipleFieldsMapKeyComparator::MultipleFieldsMapKeyComparator
MultipleFieldsMapKeyComparator(MessageDifferencer *message_differencer, const FieldDescriptor *key)
Definition: protobuf/src/google/protobuf/util/message_differencer.cc:128
google::protobuf::MapValueConstRef
Definition: protobuf/src/google/protobuf/map_field.h:685
google::protobuf::util::MessageDifferencer::SpecificField::map_entry2
const Message * map_entry2
Definition: protobuf/src/google/protobuf/util/message_differencer.h:199
google::protobuf::util::NumDiffsReporter::GetNumDiffs
int32_t GetNumDiffs() const
Definition: protobuf/src/google/protobuf/util/message_differencer.cc:76
google::protobuf::util::AddSpecificNewIndex
void AddSpecificNewIndex(google::protobuf::util::MessageDifferencer::SpecificField *specific_field, const Message &message, const FieldDescriptor *field, int index)
Definition: protobuf/src/google/protobuf/util/message_differencer.cc:221
google::protobuf::util::MessageDifferencer::SpecificField::field
const FieldDescriptor * field
Definition: bloaty/third_party/protobuf/src/google/protobuf/util/message_differencer.h:180
Int32Value
Definition: bloaty/third_party/protobuf/src/google/protobuf/wrappers.pb.h:705
google::protobuf::util::MessageDifferencer::MultipleFieldsMapKeyComparator::IsMatchInternal
bool IsMatchInternal(const Message &message1, const Message &message2, const std::vector< SpecificField > &parent_fields, const std::vector< const FieldDescriptor * > &key_field_path, int path_index) const
Definition: bloaty/third_party/protobuf/src/google/protobuf/util/message_differencer.cc:138
BoolValue
Definition: bloaty/third_party/protobuf/src/google/protobuf/wrappers.pb.h:1007
google::protobuf::Reflection::GetMessage
const Message & GetMessage(const Message &message, const FieldDescriptor *field, MessageFactory *factory=nullptr) const
Definition: bloaty/third_party/protobuf/src/google/protobuf/generated_message_reflection.cc:1442
google::protobuf::FieldDescriptor::is_map
bool is_map() const
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.h:2075
google::protobuf::Reflection::LookupMapValue
bool LookupMapValue(const Message &message, const FieldDescriptor *field, const MapKey &key, MapValueConstRef *val) const
Definition: protobuf/src/google/protobuf/generated_message_reflection.cc:2333
google::protobuf::Reflection::MapEnd
MapIterator MapEnd(Message *message, const FieldDescriptor *field) const
Definition: bloaty/third_party/protobuf/src/google/protobuf/generated_message_reflection.cc:1796
google::protobuf::DescriptorPool::FindMessageTypeByName
const Descriptor * FindMessageTypeByName(const std::string &name) const
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.cc:1410


grpc
Author(s):
autogenerated on Fri May 16 2025 02:59:25