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 
36 
37 #include <algorithm>
38 #include <memory>
39 #include <utility>
40 
45 #include <google/protobuf/any.h>
54 
55 
56 // Always include as last one, otherwise it can break compilation
57 #include <google/protobuf/port_def.inc>
58 
59 namespace google {
60 namespace protobuf {
61 
62 namespace util {
63 
64 // A reporter to report the total number of diffs.
65 // TODO(ykzhu): we can improve this to take into account the value differencers.
67  public:
69 
70  // Returns the total number of diffs.
71  int32 GetNumDiffs() const { return num_diffs_; }
72  void Reset() { num_diffs_ = 0; }
73 
74  // Report that a field has been added into Message2.
76  const google::protobuf::Message& message1, const google::protobuf::Message& message2,
77  const std::vector<google::protobuf::util::MessageDifferencer::SpecificField>&
78  field_path) override {
79  ++num_diffs_;
80  }
81 
82  // Report that a field has been deleted from Message1.
84  const google::protobuf::Message& message1, const google::protobuf::Message& message2,
85  const std::vector<google::protobuf::util::MessageDifferencer::SpecificField>&
86  field_path) override {
87  ++num_diffs_;
88  }
89 
90  // Report that the value of a field has been modified.
92  const google::protobuf::Message& message1, const google::protobuf::Message& message2,
93  const std::vector<google::protobuf::util::MessageDifferencer::SpecificField>&
94  field_path) override {
95  ++num_diffs_;
96  }
97 
98  private:
100 };
101 
102 // When comparing a repeated field as map, MultipleFieldMapKeyComparator can
103 // be used to specify multiple fields as key for key comparison.
104 // Two elements of a repeated field will be regarded as having the same key
105 // iff they have the same value for every specified key field.
106 // Note that you can also specify only one field as key.
109  public:
111  MessageDifferencer* message_differencer,
112  const std::vector<std::vector<const FieldDescriptor*> >& key_field_paths)
113  : message_differencer_(message_differencer),
114  key_field_paths_(key_field_paths) {
115  GOOGLE_CHECK(!key_field_paths_.empty());
116  for (int i = 0; i < key_field_paths_.size(); ++i) {
117  GOOGLE_CHECK(!key_field_paths_[i].empty());
118  }
119  }
121  const FieldDescriptor* key)
122  : message_differencer_(message_differencer) {
123  std::vector<const FieldDescriptor*> key_field_path;
124  key_field_path.push_back(key);
125  key_field_paths_.push_back(key_field_path);
126  }
127  bool IsMatch(const Message& message1, const Message& message2,
128  const std::vector<SpecificField>& parent_fields) const override {
129  for (int i = 0; i < key_field_paths_.size(); ++i) {
130  if (!IsMatchInternal(message1, message2, parent_fields,
131  key_field_paths_[i], 0)) {
132  return false;
133  }
134  }
135  return true;
136  }
137 
138  private:
140  const Message& message1, const Message& message2,
141  const std::vector<SpecificField>& parent_fields,
142  const std::vector<const FieldDescriptor*>& key_field_path,
143  int path_index) const {
144  const FieldDescriptor* field = key_field_path[path_index];
145  std::vector<SpecificField> current_parent_fields(parent_fields);
146  if (path_index == key_field_path.size() - 1) {
147  if (field->is_repeated()) {
149  message1, message2, field, &current_parent_fields)) {
150  return false;
151  }
152  } else {
154  message1, message2, field, -1, -1, &current_parent_fields)) {
155  return false;
156  }
157  }
158  return true;
159  } else {
160  const Reflection* reflection1 = message1.GetReflection();
161  const Reflection* reflection2 = message2.GetReflection();
162  bool has_field1 = reflection1->HasField(message1, field);
163  bool has_field2 = reflection2->HasField(message2, field);
164  if (!has_field1 && !has_field2) {
165  return true;
166  }
167  if (has_field1 != has_field2) {
168  return false;
169  }
170  SpecificField specific_field;
171  specific_field.field = field;
172  current_parent_fields.push_back(specific_field);
173  return IsMatchInternal(reflection1->GetMessage(message1, field),
174  reflection2->GetMessage(message2, field),
175  current_parent_fields, key_field_path,
176  path_index + 1);
177  }
178  }
180  std::vector<std::vector<const FieldDescriptor*> > key_field_paths_;
182 };
183 
184 // Preserve the order when treating repeated field as SMART_LIST. The current
185 // implementation is to find the longest matching sequence from the first
186 // element. The optimal solution requires to use //util/diff/lcs.h, which is
187 // not open sourced yet. Overwrite this method if you want to have that.
188 // TODO(ykzhu): change to use LCS once it is open sourced.
190  std::vector<int>* match_list1, std::vector<int>* match_list2) {
191  int last_matched_index = -1;
192  for (int i = 0; i < match_list1->size(); ++i) {
193  if (match_list1->at(i) < 0) {
194  continue;
195  }
196  if (last_matched_index < 0 || match_list1->at(i) > last_matched_index) {
197  last_matched_index = match_list1->at(i);
198  } else {
199  match_list2->at(match_list1->at(i)) = -1;
200  match_list1->at(i) = -1;
201  }
202  }
203 }
204 
206  MessageDifferencer* message_differencer)
207  : message_differencer_(message_differencer) {}
208 
210  const Message& message1, const Message& message2,
211  const std::vector<SpecificField>& parent_fields) const {
212  // Map entry has its key in the field with tag 1. See the comment for
213  // map_entry in MessageOptions.
214  const FieldDescriptor* key = message1.GetDescriptor()->FindFieldByNumber(1);
215  // If key is not present in message1 and we're doing partial comparison or if
216  // map key is explicitly ignored treat the field as set instead,
217  const bool treat_as_set =
218  (message_differencer_->scope() == PARTIAL &&
219  !message1.GetReflection()->HasField(message1, key)) ||
220  message_differencer_->IsIgnored(message1, message2, key, parent_fields);
221 
222  std::vector<SpecificField> current_parent_fields(parent_fields);
223  if (treat_as_set) {
224  return message_differencer_->Compare(message1, message2,
225  &current_parent_fields);
226  }
227  return message_differencer_->CompareFieldValueUsingParentFields(
228  message1, message2, key, -1, -1, &current_parent_fields);
229 }
230 
231 bool MessageDifferencer::Equals(const Message& message1,
232  const Message& message2) {
233  MessageDifferencer differencer;
234 
235  return differencer.Compare(message1, message2);
236 }
237 
239  const Message& message2) {
240  MessageDifferencer differencer;
242 
243  return differencer.Compare(message1, message2);
244 }
245 
247  const Message& message2) {
248  MessageDifferencer differencer;
250 
251  return differencer.Compare(message1, message2);
252 }
253 
255  const Message& message2) {
256  MessageDifferencer differencer;
259 
260  return differencer.Compare(message1, message2);
261 }
262 
263 // ===========================================================================
264 
266  : reporter_(NULL),
269  scope_(FULL),
275  output_string_(nullptr),
278 
280  for (int i = 0; i < owned_key_comparators_.size(); ++i) {
281  delete owned_key_comparators_[i];
282  }
283  for (int i = 0; i < ignore_criteria_.size(); ++i) {
284  delete ignore_criteria_[i];
285  }
286 }
287 
289  GOOGLE_CHECK(comparator) << "Field comparator can't be NULL.";
290  field_comparator_ = comparator;
291 }
292 
294  MessageFieldComparison comparison) {
295  message_field_comparison_ = comparison;
296 }
297 
299 
301 
304  comparison == EXACT ? DefaultFieldComparator::EXACT
306 }
307 
309  RepeatedFieldComparison comparison) {
310  repeated_field_comparison_ = comparison;
311 }
312 
314  const FieldDescriptor* field,
315  const RepeatedFieldComparison& new_comparison) {
316  GOOGLE_CHECK(field->is_repeated())
317  << "Field must be repeated: " << field->full_name();
318  const MapKeyComparator* key_comparator = GetMapKeyComparator(field);
319  GOOGLE_CHECK(key_comparator == NULL)
320  << "Cannot treat this repeated field as both MAP and " << new_comparison
321  << " for"
322  << " comparison. Field name is: " << field->full_name();
325  repeated_field_comparisons_[field] == new_comparison)
326  << "Cannot treat the same field as both "
327  << repeated_field_comparisons_[field] << " and " << new_comparison
328  << ". Field name is: " << field->full_name();
329 }
330 
334 }
335 
339 }
340 
342  std::function<void(std::vector<int>*, std::vector<int>*)> callback) {
344 }
345 
349 }
350 
354 }
355 
357  const FieldDescriptor* key) {
359  << "Field has to be message type. Field name is: " << field->full_name();
360  GOOGLE_CHECK(key->containing_type() == field->message_type())
361  << key->full_name()
362  << " must be a direct subfield within the repeated field "
363  << field->full_name() << ", not " << key->containing_type()->full_name();
366  << "Cannot treat the same field as both "
368  << " and MAP. Field name is: " << field->full_name();
369  MapKeyComparator* key_comparator =
371  owned_key_comparators_.push_back(key_comparator);
372  map_field_key_comparator_[field] = key_comparator;
373 }
374 
376  const FieldDescriptor* field,
377  const std::vector<const FieldDescriptor*>& key_fields) {
378  std::vector<std::vector<const FieldDescriptor*> > key_field_paths;
379  for (int i = 0; i < key_fields.size(); ++i) {
380  std::vector<const FieldDescriptor*> key_field_path;
381  key_field_path.push_back(key_fields[i]);
382  key_field_paths.push_back(key_field_path);
383  }
385 }
386 
388  const FieldDescriptor* field,
389  const std::vector<std::vector<const FieldDescriptor*> >& key_field_paths) {
390  GOOGLE_CHECK(field->is_repeated())
391  << "Field must be repeated: " << field->full_name();
393  << "Field has to be message type. Field name is: " << field->full_name();
394  for (int i = 0; i < key_field_paths.size(); ++i) {
395  const std::vector<const FieldDescriptor*>& key_field_path =
396  key_field_paths[i];
397  for (int j = 0; j < key_field_path.size(); ++j) {
398  const FieldDescriptor* parent_field =
399  j == 0 ? field : key_field_path[j - 1];
400  const FieldDescriptor* child_field = key_field_path[j];
401  GOOGLE_CHECK(child_field->containing_type() == parent_field->message_type())
402  << child_field->full_name()
403  << " must be a direct subfield within the field: "
404  << parent_field->full_name();
405  if (j != 0) {
407  << parent_field->full_name() << " has to be of type message.";
408  GOOGLE_CHECK(!parent_field->is_repeated())
409  << parent_field->full_name() << " cannot be a repeated field.";
410  }
411  }
412  }
415  << "Cannot treat the same field as both "
417  << " and MAP. Field name is: " << field->full_name();
418  MapKeyComparator* key_comparator =
419  new MultipleFieldsMapKeyComparator(this, key_field_paths);
420  owned_key_comparators_.push_back(key_comparator);
421  map_field_key_comparator_[field] = key_comparator;
422 }
423 
425  const FieldDescriptor* field, const MapKeyComparator* key_comparator) {
426  GOOGLE_CHECK(field->is_repeated())
427  << "Field must be repeated: " << field->full_name();
430  << "Cannot treat the same field as both "
432  << " and MAP. Field name is: " << field->full_name();
433  map_field_key_comparator_[field] = key_comparator;
434 }
435 
437  ignore_criteria_.push_back(ignore_criteria);
438 }
439 
441  ignored_fields_.insert(field);
442 }
443 
445  double fraction, double margin) {
447 }
448 
450  GOOGLE_DCHECK(output) << "Specified output string was NULL";
451 
453  output_string_->clear();
454 }
455 
457  // If an output string is set, clear it to prevent
458  // it superceding the specified reporter.
459  if (output_string_) {
461  }
462 
463  reporter_ = reporter;
464 }
465 
467  const FieldDescriptor* field2) {
468  // Handle sentinel values (i.e. make sure NULLs are always ordered
469  // at the end of the list).
470  if (field1 == NULL) {
471  return false;
472  }
473 
474  if (field2 == NULL) {
475  return true;
476  }
477 
478  // Always order fields by their tag number
479  return (field1->number() < field2->number());
480 }
481 
483  const Message& message2) {
484  std::vector<SpecificField> parent_fields;
485 
486  bool result = false;
487 
488  // Setup the internal reporter if need be.
489  if (output_string_) {
490  io::StringOutputStream output_stream(output_string_);
491  StreamReporter reporter(&output_stream);
492  reporter_ = &reporter;
493  result = Compare(message1, message2, &parent_fields);
494  reporter_ = NULL;
495  } else {
496  result = Compare(message1, message2, &parent_fields);
497  }
498 
499  return result;
500 }
501 
503  const Message& message1, const Message& message2,
504  const std::vector<const FieldDescriptor*>& message1_fields_arg,
505  const std::vector<const FieldDescriptor*>& message2_fields_arg) {
506  if (message1.GetDescriptor() != message2.GetDescriptor()) {
507  GOOGLE_LOG(DFATAL) << "Comparison between two messages with different "
508  << "descriptors.";
509  return false;
510  }
511 
512  std::vector<SpecificField> parent_fields;
513 
514  bool result = false;
515 
516  FieldDescriptorArray message1_fields(message1_fields_arg.size() + 1);
517  FieldDescriptorArray message2_fields(message2_fields_arg.size() + 1);
518 
519  std::copy(message1_fields_arg.cbegin(), message1_fields_arg.cend(),
520  message1_fields.begin());
521  std::copy(message2_fields_arg.cbegin(), message2_fields_arg.cend(),
522  message2_fields.begin());
523 
524  // Append sentinel values.
525  message1_fields[message1_fields_arg.size()] = nullptr;
526  message2_fields[message2_fields_arg.size()] = nullptr;
527 
528  std::sort(message1_fields.begin(), message1_fields.end(), FieldBefore);
529  std::sort(message2_fields.begin(), message2_fields.end(), FieldBefore);
530 
531  // Setup the internal reporter if need be.
532  if (output_string_) {
533  io::StringOutputStream output_stream(output_string_);
534  StreamReporter reporter(&output_stream);
535  reporter_ = &reporter;
537  message1, message2, message1_fields, message2_fields, &parent_fields);
538  reporter_ = NULL;
539  } else {
541  message1, message2, message1_fields, message2_fields, &parent_fields);
542  }
543 
544  return result;
545 }
546 
548  const Message& message2,
549  std::vector<SpecificField>* parent_fields) {
550  const Descriptor* descriptor1 = message1.GetDescriptor();
551  const Descriptor* descriptor2 = message2.GetDescriptor();
552  if (descriptor1 != descriptor2) {
553  GOOGLE_LOG(DFATAL) << "Comparison between two messages with different "
554  << "descriptors. " << descriptor1->full_name() << " vs "
555  << descriptor2->full_name();
556  return false;
557  }
558  // Expand google.protobuf.Any payload if possible.
559  if (descriptor1->full_name() == internal::kAnyFullTypeName) {
560  std::unique_ptr<Message> data1;
561  std::unique_ptr<Message> data2;
562  if (UnpackAny(message1, &data1) && UnpackAny(message2, &data2)) {
563  // Avoid DFATAL for different descriptors in google.protobuf.Any payloads.
564  if (data1->GetDescriptor() != data2->GetDescriptor()) {
565  return false;
566  }
567  return Compare(*data1, *data2, parent_fields);
568  }
569  }
570  const Reflection* reflection1 = message1.GetReflection();
571  const Reflection* reflection2 = message2.GetReflection();
572 
573  bool unknown_compare_result = true;
574  // Ignore unknown fields in EQUIVALENT mode
576  const UnknownFieldSet* unknown_field_set1 =
577  &reflection1->GetUnknownFields(message1);
578  const UnknownFieldSet* unknown_field_set2 =
579  &reflection2->GetUnknownFields(message2);
580  if (!CompareUnknownFields(message1, message2, *unknown_field_set1,
581  *unknown_field_set2, parent_fields)) {
582  if (reporter_ == NULL) {
583  return false;
584  };
585  unknown_compare_result = false;
586  }
587  }
588 
589  FieldDescriptorArray message1_fields = RetrieveFields(message1, true);
590  FieldDescriptorArray message2_fields = RetrieveFields(message2, false);
591 
593  message1, message2,
594  message1_fields, message2_fields,
595  parent_fields) && unknown_compare_result;
596 }
597 
599  bool base_message) {
600  const Descriptor* descriptor = message.GetDescriptor();
601 
602  tmp_message_fields_.clear();
603  tmp_message_fields_.reserve(descriptor->field_count() + 1);
604 
605  const Reflection* reflection = message.GetReflection();
606  if (descriptor->options().map_entry()) {
607  if (this->scope_ == PARTIAL && base_message) {
608  reflection->ListFields(message, &tmp_message_fields_);
609  } else {
610  // Map entry fields are always considered present.
611  for (int i = 0; i < descriptor->field_count(); i++) {
612  tmp_message_fields_.push_back(descriptor->field(i));
613  }
614  }
615  } else {
616  reflection->ListFields(message, &tmp_message_fields_);
617  }
618  // Add sentinel values to deal with the
619  // case where the number of the fields in
620  // each list are different.
621  tmp_message_fields_.push_back(nullptr);
622 
623  FieldDescriptorArray message_fields(tmp_message_fields_.begin(),
624  tmp_message_fields_.end());
625 
626  return message_fields;
627 }
628 
630  const Message& message1, const Message& message2,
631  const FieldDescriptorArray& message1_fields,
632  const FieldDescriptorArray& message2_fields,
633  std::vector<SpecificField>* parent_fields) {
634  if (scope_ == FULL) {
636  // We need to merge the field lists of both messages (i.e.
637  // we are merely checking for a difference in field values,
638  // rather than the addition or deletion of fields).
639  FieldDescriptorArray fields_union =
640  CombineFields(message1_fields, FULL, message2_fields, FULL);
641  return CompareWithFieldsInternal(message1, message2, fields_union,
642  fields_union, parent_fields);
643  } else {
644  // Simple equality comparison, use the unaltered field lists.
645  return CompareWithFieldsInternal(message1, message2, message1_fields,
646  message2_fields, parent_fields);
647  }
648  } else {
650  // We use the list of fields for message1 for both messages when
651  // comparing. This way, extra fields in message2 are ignored,
652  // and missing fields in message2 use their default value.
653  return CompareWithFieldsInternal(message1, message2, message1_fields,
654  message1_fields, parent_fields);
655  } else {
656  // We need to consider the full list of fields for message1
657  // but only the intersection for message2. This way, any fields
658  // only present in message2 will be ignored, but any fields only
659  // present in message1 will be marked as a difference.
660  FieldDescriptorArray fields_intersection =
661  CombineFields(message1_fields, PARTIAL, message2_fields, PARTIAL);
662  return CompareWithFieldsInternal(message1, message2, message1_fields,
663  fields_intersection, parent_fields);
664  }
665  }
666 }
667 
669  const FieldDescriptorArray& fields1, Scope fields1_scope,
670  const FieldDescriptorArray& fields2, Scope fields2_scope) {
671  int index1 = 0;
672  int index2 = 0;
673 
674  tmp_message_fields_.clear();
675 
676  while (index1 < fields1.size() && index2 < fields2.size()) {
677  const FieldDescriptor* field1 = fields1[index1];
678  const FieldDescriptor* field2 = fields2[index2];
679 
680  if (FieldBefore(field1, field2)) {
681  if (fields1_scope == FULL) {
682  tmp_message_fields_.push_back(fields1[index1]);
683  }
684  ++index1;
685  } else if (FieldBefore(field2, field1)) {
686  if (fields2_scope == FULL) {
687  tmp_message_fields_.push_back(fields2[index2]);
688  }
689  ++index2;
690  } else {
691  tmp_message_fields_.push_back(fields1[index1]);
692  ++index1;
693  ++index2;
694  }
695  }
696 
697  tmp_message_fields_.push_back(nullptr);
698 
699  FieldDescriptorArray combined_fields(tmp_message_fields_.begin(),
700  tmp_message_fields_.end());
701 
702  return combined_fields;
703 }
704 
706  const Message& message1, const Message& message2,
707  const FieldDescriptorArray& message1_fields,
708  const FieldDescriptorArray& message2_fields,
709  std::vector<SpecificField>* parent_fields) {
710  bool isDifferent = false;
711  int field_index1 = 0;
712  int field_index2 = 0;
713 
714  const Reflection* reflection1 = message1.GetReflection();
715  const Reflection* reflection2 = message2.GetReflection();
716 
717  while (true) {
718  const FieldDescriptor* field1 = message1_fields[field_index1];
719  const FieldDescriptor* field2 = message2_fields[field_index2];
720 
721  // Once we have reached sentinel values, we are done the comparison.
722  if (field1 == NULL && field2 == NULL) {
723  break;
724  }
725 
726  // Check for differences in the field itself.
727  if (FieldBefore(field1, field2)) {
728  // Field 1 is not in the field list for message 2.
729  if (IsIgnored(message1, message2, field1, *parent_fields)) {
730  // We are ignoring field1. Report the ignore and move on to
731  // the next field in message1_fields.
732  if (reporter_ != NULL) {
733  SpecificField specific_field;
734  specific_field.field = field1;
735 
736  parent_fields->push_back(specific_field);
737  if (report_ignores_) {
738  reporter_->ReportIgnored(message1, message2, *parent_fields);
739  }
740  parent_fields->pop_back();
741  }
742  ++field_index1;
743  continue;
744  }
745 
746  if (reporter_ != NULL) {
747  assert(field1 != NULL);
748  int count = field1->is_repeated()
749  ? reflection1->FieldSize(message1, field1)
750  : 1;
751 
752  for (int i = 0; i < count; ++i) {
753  SpecificField specific_field;
754  specific_field.field = field1;
755  specific_field.index = field1->is_repeated() ? i : -1;
756 
757  parent_fields->push_back(specific_field);
758  reporter_->ReportDeleted(message1, message2, *parent_fields);
759  parent_fields->pop_back();
760  }
761 
762  isDifferent = true;
763  } else {
764  return false;
765  }
766 
767  ++field_index1;
768  continue;
769  } else if (FieldBefore(field2, field1)) {
770  // Field 2 is not in the field list for message 1.
771  if (IsIgnored(message1, message2, field2, *parent_fields)) {
772  // We are ignoring field2. Report the ignore and move on to
773  // the next field in message2_fields.
774  if (reporter_ != NULL) {
775  SpecificField specific_field;
776  specific_field.field = field2;
777 
778  parent_fields->push_back(specific_field);
779  if (report_ignores_) {
780  reporter_->ReportIgnored(message1, message2, *parent_fields);
781  }
782  parent_fields->pop_back();
783  }
784  ++field_index2;
785  continue;
786  }
787 
788  if (reporter_ != NULL) {
789  int count = field2->is_repeated()
790  ? reflection2->FieldSize(message2, field2)
791  : 1;
792 
793  for (int i = 0; i < count; ++i) {
794  SpecificField specific_field;
795  specific_field.field = field2;
796  specific_field.index = field2->is_repeated() ? i : -1;
797  specific_field.new_index = specific_field.index;
798 
799  parent_fields->push_back(specific_field);
800  reporter_->ReportAdded(message1, message2, *parent_fields);
801  parent_fields->pop_back();
802  }
803 
804  isDifferent = true;
805  } else {
806  return false;
807  }
808 
809  ++field_index2;
810  continue;
811  }
812 
813  // By this point, field1 and field2 are guarenteed to point to the same
814  // field, so we can now compare the values.
815  if (IsIgnored(message1, message2, field1, *parent_fields)) {
816  // Ignore this field. Report and move on.
817  if (reporter_ != NULL) {
818  SpecificField specific_field;
819  specific_field.field = field1;
820 
821  parent_fields->push_back(specific_field);
822  if (report_ignores_) {
823  reporter_->ReportIgnored(message1, message2, *parent_fields);
824  }
825  parent_fields->pop_back();
826  }
827 
828  ++field_index1;
829  ++field_index2;
830  continue;
831  }
832 
833  bool fieldDifferent = false;
834  assert(field1 != NULL);
835  if (field1->is_repeated()) {
836  fieldDifferent =
837  !CompareRepeatedField(message1, message2, field1, parent_fields);
838  if (fieldDifferent) {
839  if (reporter_ == NULL) return false;
840  isDifferent = true;
841  }
842  } else {
843  fieldDifferent = !CompareFieldValueUsingParentFields(
844  message1, message2, field1, -1, -1, parent_fields);
845 
846  // If we have found differences, either report them or terminate if
847  // no reporter is present.
848  if (fieldDifferent && reporter_ == NULL) {
849  return false;
850  }
851 
852  if (reporter_ != NULL) {
853  SpecificField specific_field;
854  specific_field.field = field1;
855  parent_fields->push_back(specific_field);
856  if (fieldDifferent) {
857  reporter_->ReportModified(message1, message2, *parent_fields);
858  isDifferent = true;
859  } else if (report_matches_) {
860  reporter_->ReportMatched(message1, message2, *parent_fields);
861  }
862  parent_fields->pop_back();
863  }
864  }
865  // Increment the field indicies.
866  ++field_index1;
867  ++field_index2;
868  }
869 
870  return !isDifferent;
871 }
872 
875  const MapKeyComparator* key_comparator, const Message* message1,
876  const Message* message2, const std::vector<SpecificField>& parent_fields,
877  Reporter* reporter, int index1, int index2) {
878  std::vector<SpecificField> current_parent_fields(parent_fields);
880  return CompareFieldValueUsingParentFields(*message1, *message2,
881  repeated_field, index1, index2,
882  &current_parent_fields);
883  }
884  // Back up the Reporter and output_string_. They will be reset in the
885  // following code.
886  Reporter* backup_reporter = reporter_;
887  std::string* output_string = output_string_;
888  reporter_ = reporter;
890  bool match;
891 
892  if (key_comparator == NULL) {
893  match = CompareFieldValueUsingParentFields(*message1, *message2,
894  repeated_field, index1, index2,
895  &current_parent_fields);
896  } else {
897  const Reflection* reflection1 = message1->GetReflection();
898  const Reflection* reflection2 = message2->GetReflection();
899  const Message& m1 =
900  reflection1->GetRepeatedMessage(*message1, repeated_field, index1);
901  const Message& m2 =
902  reflection2->GetRepeatedMessage(*message2, repeated_field, index2);
903  SpecificField specific_field;
904  specific_field.field = repeated_field;
905  specific_field.index = index1;
906  specific_field.new_index = index2;
907  current_parent_fields.push_back(specific_field);
908  match = key_comparator->IsMatch(m1, m2, current_parent_fields);
909  }
910 
911  reporter_ = backup_reporter;
912  output_string_ = output_string;
913  return match;
914 }
915 
917  const Message& message1, const Message& message2,
919  std::vector<SpecificField>* parent_fields) {
920  // the input FieldDescriptor is guaranteed to be repeated field.
921  const Reflection* reflection1 = message1.GetReflection();
922  const Reflection* reflection2 = message2.GetReflection();
923  const int count1 = reflection1->FieldSize(message1, repeated_field);
924  const int count2 = reflection2->FieldSize(message2, repeated_field);
925  const bool treated_as_subset = IsTreatedAsSubset(repeated_field);
926 
927  // If the field is not treated as subset and no detailed reports is needed,
928  // we do a quick check on the number of the elements to avoid unnecessary
929  // comparison.
930  if (count1 != count2 && reporter_ == NULL && !treated_as_subset) {
931  return false;
932  }
933  // A match can never be found if message1 has more items than message2.
934  if (count1 > count2 && reporter_ == NULL) {
935  return false;
936  }
937 
938  // These two list are used for store the index of the correspondent
939  // element in peer repeated field.
940  std::vector<int> match_list1;
941  std::vector<int> match_list2;
942 
943  const MapKeyComparator* key_comparator = GetMapKeyComparator(repeated_field);
944  bool smart_list = IsTreatedAsSmartList(repeated_field);
945  bool simple_list = key_comparator == nullptr &&
947  !IsTreatedAsSmartSet(repeated_field) && !smart_list;
948 
949  // For simple lists, we avoid matching repeated field indices, saving the
950  // memory allocations that would otherwise be needed for match_list1 and
951  // match_list2.
952  if (!simple_list) {
953  // Try to match indices of the repeated fields. Return false if match fails.
954  if (!MatchRepeatedFieldIndices(message1, message2, repeated_field,
955  key_comparator, *parent_fields, &match_list1,
956  &match_list2) &&
957  reporter_ == nullptr) {
958  return false;
959  }
960  }
961 
962  bool fieldDifferent = false;
963  SpecificField specific_field;
964  specific_field.field = repeated_field;
965 
966  // At this point, we have already matched pairs of fields (with the reporting
967  // to be done later). Now to check if the paired elements are different.
968  int next_unmatched_index = 0;
969  for (int i = 0; i < count1; i++) {
970  if (simple_list && i >= count2) {
971  break;
972  }
973  if (!simple_list && match_list1[i] == -1) {
974  if (smart_list) {
975  if (reporter_ == nullptr) return false;
976  specific_field.index = i;
977  parent_fields->push_back(specific_field);
978  reporter_->ReportDeleted(message1, message2, *parent_fields);
979  parent_fields->pop_back();
980  fieldDifferent = true;
981  // Use -2 to mark this element has been reported.
982  match_list1[i] = -2;
983  }
984  continue;
985  }
986  if (smart_list) {
987  for (int j = next_unmatched_index; j < match_list1[i]; ++j) {
988  GOOGLE_CHECK_LE(0, j);
989  if (reporter_ == nullptr) return false;
990  specific_field.index = j;
991  specific_field.new_index = j;
992  parent_fields->push_back(specific_field);
993  reporter_->ReportAdded(message1, message2, *parent_fields);
994  parent_fields->pop_back();
995  fieldDifferent = true;
996  // Use -2 to mark this element has been reported.
997  match_list2[j] = -2;
998  }
999  }
1000  specific_field.index = i;
1001  if (simple_list) {
1002  specific_field.new_index = i;
1003  } else {
1004  specific_field.new_index = match_list1[i];
1005  next_unmatched_index = match_list1[i] + 1;
1006  }
1007 
1008  const bool result = CompareFieldValueUsingParentFields(
1009  message1, message2, repeated_field, i, specific_field.new_index,
1010  parent_fields);
1011 
1012  // If we have found differences, either report them or terminate if
1013  // no reporter is present. Note that ReportModified, ReportMoved, and
1014  // ReportMatched are all mutually exclusive.
1015  if (!result) {
1016  if (reporter_ == NULL) return false;
1017  parent_fields->push_back(specific_field);
1018  reporter_->ReportModified(message1, message2, *parent_fields);
1019  parent_fields->pop_back();
1020  fieldDifferent = true;
1021  } else if (reporter_ != NULL &&
1022  specific_field.index != specific_field.new_index &&
1023  !specific_field.field->is_map() && report_moves_) {
1024  parent_fields->push_back(specific_field);
1025  reporter_->ReportMoved(message1, message2, *parent_fields);
1026  parent_fields->pop_back();
1027  } else if (report_matches_ && reporter_ != NULL) {
1028  parent_fields->push_back(specific_field);
1029  reporter_->ReportMatched(message1, message2, *parent_fields);
1030  parent_fields->pop_back();
1031  }
1032  }
1033 
1034  // Report any remaining additions or deletions.
1035  for (int i = 0; i < count2; ++i) {
1036  if (!simple_list && match_list2[i] != -1) continue;
1037  if (simple_list && i < count1) continue;
1038  if (!treated_as_subset) {
1039  fieldDifferent = true;
1040  }
1041 
1042  if (reporter_ == NULL) continue;
1043  specific_field.index = i;
1044  specific_field.new_index = i;
1045  parent_fields->push_back(specific_field);
1046  reporter_->ReportAdded(message1, message2, *parent_fields);
1047  parent_fields->pop_back();
1048  }
1049 
1050  for (int i = 0; i < count1; ++i) {
1051  if (!simple_list && match_list1[i] != -1) continue;
1052  if (simple_list && i < count2) continue;
1053  assert(reporter_ != NULL);
1054  specific_field.index = i;
1055  parent_fields->push_back(specific_field);
1056  reporter_->ReportDeleted(message1, message2, *parent_fields);
1057  parent_fields->pop_back();
1058  fieldDifferent = true;
1059  }
1060  return !fieldDifferent;
1061 }
1062 
1064  const Message& message2,
1065  const FieldDescriptor* field,
1066  int index1, int index2) {
1067  return CompareFieldValueUsingParentFields(message1, message2, field, index1,
1068  index2, NULL);
1069 }
1070 
1072  const Message& message1, const Message& message2,
1073  const FieldDescriptor* field, int index1, int index2,
1074  std::vector<SpecificField>* parent_fields) {
1075  FieldContext field_context(parent_fields);
1077  message1, message2, field, index1, index2, &field_context);
1078 
1079  if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
1080  result == FieldComparator::RECURSE) {
1081  // Get the nested messages and compare them using one of the Compare
1082  // methods.
1083  const Reflection* reflection1 = message1.GetReflection();
1084  const Reflection* reflection2 = message2.GetReflection();
1085  const Message& m1 =
1086  field->is_repeated()
1087  ? reflection1->GetRepeatedMessage(message1, field, index1)
1088  : reflection1->GetMessage(message1, field);
1089  const Message& m2 =
1090  field->is_repeated()
1091  ? reflection2->GetRepeatedMessage(message2, field, index2)
1092  : reflection2->GetMessage(message2, field);
1093 
1094  // parent_fields is used in calls to Reporter methods.
1095  if (parent_fields != NULL) {
1096  // Append currently compared field to the end of parent_fields.
1097  SpecificField specific_field;
1098  specific_field.field = field;
1099  specific_field.index = index1;
1100  specific_field.new_index = index2;
1101  parent_fields->push_back(specific_field);
1102  const bool compare_result = Compare(m1, m2, parent_fields);
1103  parent_fields->pop_back();
1104  return compare_result;
1105  } else {
1106  // Recreates parent_fields as if m1 and m2 had no parents.
1107  return Compare(m1, m2);
1108  }
1109  } else {
1110  return (result == FieldComparator::SAME);
1111  }
1112 }
1113 
1115  const std::vector<SpecificField>& field_path) {
1116  for (int i = 0; i < field_path.size(); ++i) {
1117  // Don't check indexes for map entries -- maps are unordered.
1118  if (field_path[i].field != NULL && field_path[i].field->is_map()) continue;
1119  if (field_path[i].index != field_path[i].new_index) return true;
1120  }
1121  return false;
1122 }
1123 
1125  if (!field->is_repeated()) return false;
1126  if (repeated_field_comparisons_.find(field) !=
1129  }
1131 }
1132 
1134  if (!field->is_repeated()) return false;
1135  if (repeated_field_comparisons_.find(field) !=
1138  }
1140 }
1141 
1143  if (!field->is_repeated()) return false;
1144  if (repeated_field_comparisons_.find(field) !=
1147  }
1149 }
1150 
1152  return scope_ == PARTIAL &&
1154 }
1155 
1157  const Message& message1, const Message& message2,
1158  const FieldDescriptor* field,
1159  const std::vector<SpecificField>& parent_fields) {
1160  if (ignored_fields_.find(field) != ignored_fields_.end()) {
1161  return true;
1162  }
1163  for (int i = 0; i < ignore_criteria_.size(); ++i) {
1164  if (ignore_criteria_[i]->IsIgnored(message1, message2, field,
1165  parent_fields)) {
1166  return true;
1167  }
1168  }
1169  return false;
1170 }
1171 
1173  const Message& message1, const Message& message2,
1174  const SpecificField& field,
1175  const std::vector<SpecificField>& parent_fields) {
1176  for (int i = 0; i < ignore_criteria_.size(); ++i) {
1177  if (ignore_criteria_[i]->IsUnknownFieldIgnored(message1, message2, field,
1178  parent_fields)) {
1179  return true;
1180  }
1181  }
1182  return false;
1183 }
1184 
1187  if (!field->is_repeated()) return NULL;
1188  FieldKeyComparatorMap::const_iterator it =
1190  if (it != map_field_key_comparator_.end()) {
1191  return it->second;
1192  }
1193  if (field->is_map()) {
1194  // field cannot already be treated as list or set since TreatAsList() and
1195  // TreatAsSet() call GetMapKeyComparator() and fail if it returns non-NULL.
1196  return &map_entry_key_comparator_;
1197  }
1198  return NULL;
1199 }
1200 
1201 namespace {
1202 
1203 typedef std::pair<int, const UnknownField*> IndexUnknownFieldPair;
1204 
1205 struct UnknownFieldOrdering {
1206  inline bool operator()(const IndexUnknownFieldPair& a,
1207  const IndexUnknownFieldPair& b) const {
1208  if (a.second->number() < b.second->number()) return true;
1209  if (a.second->number() > b.second->number()) return false;
1210  return a.second->type() < b.second->type();
1211  }
1212 };
1213 
1214 } // namespace
1215 
1217  std::unique_ptr<Message>* data) {
1218  const Reflection* reflection = any.GetReflection();
1219  const FieldDescriptor* type_url_field;
1220  const FieldDescriptor* value_field;
1221  if (!internal::GetAnyFieldDescriptors(any, &type_url_field, &value_field)) {
1222  return false;
1223  }
1224  const std::string& type_url = reflection->GetString(any, type_url_field);
1225  std::string full_type_name;
1226  if (!internal::ParseAnyTypeUrl(type_url, &full_type_name)) {
1227  return false;
1228  }
1229 
1230  const Descriptor* desc =
1232  full_type_name);
1233  if (desc == NULL) {
1234  GOOGLE_DLOG(ERROR) << "Proto type '" << full_type_name << "' not found";
1235  return false;
1236  }
1237 
1238  if (dynamic_message_factory_ == NULL) {
1240  }
1241  data->reset(dynamic_message_factory_->GetPrototype(desc)->New());
1242  std::string serialized_value = reflection->GetString(any, value_field);
1243  if (!(*data)->ParseFromString(serialized_value)) {
1244  GOOGLE_DLOG(ERROR) << "Failed to parse value for " << full_type_name;
1245  return false;
1246  }
1247  return true;
1248 }
1249 
1251  const Message& message1, const Message& message2,
1252  const UnknownFieldSet& unknown_field_set1,
1253  const UnknownFieldSet& unknown_field_set2,
1254  std::vector<SpecificField>* parent_field) {
1255  // Ignore unknown fields in EQUIVALENT mode.
1256  if (message_field_comparison_ == EQUIVALENT) return true;
1257 
1258  if (unknown_field_set1.empty() && unknown_field_set2.empty()) {
1259  return true;
1260  }
1261 
1262  bool is_different = false;
1263 
1264  // We first sort the unknown fields by field number and type (in other words,
1265  // in tag order), making sure to preserve ordering of values with the same
1266  // tag. This allows us to report only meaningful differences between the
1267  // two sets -- that is, differing values for the same tag. We use
1268  // IndexUnknownFieldPairs to keep track of the field's original index for
1269  // reporting purposes.
1270  std::vector<IndexUnknownFieldPair> fields1; // unknown_field_set1, sorted
1271  std::vector<IndexUnknownFieldPair> fields2; // unknown_field_set2, sorted
1272  fields1.reserve(unknown_field_set1.field_count());
1273  fields2.reserve(unknown_field_set2.field_count());
1274 
1275  for (int i = 0; i < unknown_field_set1.field_count(); i++) {
1276  fields1.push_back(std::make_pair(i, &unknown_field_set1.field(i)));
1277  }
1278  for (int i = 0; i < unknown_field_set2.field_count(); i++) {
1279  fields2.push_back(std::make_pair(i, &unknown_field_set2.field(i)));
1280  }
1281 
1282  UnknownFieldOrdering is_before;
1283  std::stable_sort(fields1.begin(), fields1.end(), is_before);
1284  std::stable_sort(fields2.begin(), fields2.end(), is_before);
1285 
1286  // In order to fill in SpecificField::index, we have to keep track of how
1287  // many values we've seen with the same field number and type.
1288  // current_repeated points at the first field in this range, and
1289  // current_repeated_start{1,2} are the indexes of the first field in the
1290  // range within fields1 and fields2.
1291  const UnknownField* current_repeated = NULL;
1292  int current_repeated_start1 = 0;
1293  int current_repeated_start2 = 0;
1294 
1295  // Now that we have two sorted lists, we can detect fields which appear only
1296  // in one list or the other by traversing them simultaneously.
1297  int index1 = 0;
1298  int index2 = 0;
1299  while (index1 < fields1.size() || index2 < fields2.size()) {
1300  enum {
1301  ADDITION,
1302  DELETION,
1303  MODIFICATION,
1304  COMPARE_GROUPS,
1305  NO_CHANGE
1306  } change_type;
1307 
1308  // focus_field is the field we're currently reporting on. (In the case
1309  // of a modification, it's the field on the left side.)
1310  const UnknownField* focus_field;
1311  bool match = false;
1312 
1313  if (index2 == fields2.size() ||
1314  (index1 < fields1.size() &&
1315  is_before(fields1[index1], fields2[index2]))) {
1316  // fields1[index1] is not present in fields2.
1317  change_type = DELETION;
1318  focus_field = fields1[index1].second;
1319  } else if (index1 == fields1.size() ||
1320  is_before(fields2[index2], fields1[index1])) {
1321  // fields2[index2] is not present in fields1.
1322  if (scope_ == PARTIAL) {
1323  // Ignore.
1324  ++index2;
1325  continue;
1326  }
1327  change_type = ADDITION;
1328  focus_field = fields2[index2].second;
1329  } else {
1330  // Field type and number are the same. See if the values differ.
1331  change_type = MODIFICATION;
1332  focus_field = fields1[index1].second;
1333 
1334  switch (focus_field->type()) {
1336  match = fields1[index1].second->varint() ==
1337  fields2[index2].second->varint();
1338  break;
1340  match = fields1[index1].second->fixed32() ==
1341  fields2[index2].second->fixed32();
1342  break;
1344  match = fields1[index1].second->fixed64() ==
1345  fields2[index2].second->fixed64();
1346  break;
1348  match = fields1[index1].second->length_delimited() ==
1349  fields2[index2].second->length_delimited();
1350  break;
1352  // We must deal with this later, after building the SpecificField.
1353  change_type = COMPARE_GROUPS;
1354  break;
1355  }
1356  if (match && change_type != COMPARE_GROUPS) {
1357  change_type = NO_CHANGE;
1358  }
1359  }
1360 
1361  if (current_repeated == NULL ||
1362  focus_field->number() != current_repeated->number() ||
1363  focus_field->type() != current_repeated->type()) {
1364  // We've started a new repeated field.
1365  current_repeated = focus_field;
1366  current_repeated_start1 = index1;
1367  current_repeated_start2 = index2;
1368  }
1369 
1370  if (change_type == NO_CHANGE && reporter_ == NULL) {
1371  // Fields were already compared and matched and we have no reporter.
1372  ++index1;
1373  ++index2;
1374  continue;
1375  }
1376 
1377  // Build the SpecificField. This is slightly complicated.
1378  SpecificField specific_field;
1379  specific_field.unknown_field_number = focus_field->number();
1380  specific_field.unknown_field_type = focus_field->type();
1381 
1382  specific_field.unknown_field_set1 = &unknown_field_set1;
1383  specific_field.unknown_field_set2 = &unknown_field_set2;
1384 
1385  if (change_type != ADDITION) {
1386  specific_field.unknown_field_index1 = fields1[index1].first;
1387  }
1388  if (change_type != DELETION) {
1389  specific_field.unknown_field_index2 = fields2[index2].first;
1390  }
1391 
1392  // Calculate the field index.
1393  if (change_type == ADDITION) {
1394  specific_field.index = index2 - current_repeated_start2;
1395  specific_field.new_index = index2 - current_repeated_start2;
1396  } else {
1397  specific_field.index = index1 - current_repeated_start1;
1398  specific_field.new_index = index2 - current_repeated_start2;
1399  }
1400 
1401  if (IsUnknownFieldIgnored(message1, message2, specific_field,
1402  *parent_field)) {
1403  if (reporter_ != NULL) {
1404  parent_field->push_back(specific_field);
1405  reporter_->ReportUnknownFieldIgnored(message1, message2, *parent_field);
1406  parent_field->pop_back();
1407  }
1408  return true;
1409  }
1410 
1411  if (change_type == ADDITION || change_type == DELETION ||
1412  change_type == MODIFICATION) {
1413  if (reporter_ == NULL) {
1414  // We found a difference and we have no reporter.
1415  return false;
1416  }
1417  is_different = true;
1418  }
1419 
1420  parent_field->push_back(specific_field);
1421 
1422  switch (change_type) {
1423  case ADDITION:
1424  reporter_->ReportAdded(message1, message2, *parent_field);
1425  ++index2;
1426  break;
1427  case DELETION:
1428  reporter_->ReportDeleted(message1, message2, *parent_field);
1429  ++index1;
1430  break;
1431  case MODIFICATION:
1432  reporter_->ReportModified(message1, message2, *parent_field);
1433  ++index1;
1434  ++index2;
1435  break;
1436  case COMPARE_GROUPS:
1437  if (!CompareUnknownFields(
1438  message1, message2, fields1[index1].second->group(),
1439  fields2[index2].second->group(), parent_field)) {
1440  if (reporter_ == NULL) return false;
1441  is_different = true;
1442  reporter_->ReportModified(message1, message2, *parent_field);
1443  }
1444  ++index1;
1445  ++index2;
1446  break;
1447  case NO_CHANGE:
1448  ++index1;
1449  ++index2;
1450  if (report_matches_) {
1451  reporter_->ReportMatched(message1, message2, *parent_field);
1452  }
1453  }
1454 
1455  parent_field->pop_back();
1456  }
1457 
1458  return !is_different;
1459 }
1460 
1461 namespace {
1462 
1463 // Find maximum bipartite matching using the argumenting path algorithm.
1464 class MaximumMatcher {
1465  public:
1466  typedef ResultCallback2<bool, int, int> NodeMatchCallback;
1467  // MaximumMatcher takes ownership of the passed in callback and uses it to
1468  // determine whether a node on the left side of the bipartial graph matches
1469  // a node on the right side. count1 is the number of nodes on the left side
1470  // of the graph and count2 to is the number of nodes on the right side.
1471  // Every node is referred to using 0-based indices.
1472  // If a maximum match is found, the result will be stored in match_list1 and
1473  // match_list2. match_list1[i] == j means the i-th node on the left side is
1474  // matched to the j-th node on the right side and match_list2[x] == y means
1475  // the x-th node on the right side is matched to y-th node on the left side.
1476  // match_list1[i] == -1 means the node is not matched. Same with match_list2.
1477  MaximumMatcher(int count1, int count2, NodeMatchCallback* callback,
1478  std::vector<int>* match_list1, std::vector<int>* match_list2);
1479  // Find a maximum match and return the number of matched node pairs.
1480  // If early_return is true, this method will return 0 immediately when it
1481  // finds that not all nodes on the left side can be matched.
1482  int FindMaximumMatch(bool early_return);
1483 
1484  private:
1485  // Determines whether the node on the left side of the bipartial graph
1486  // matches the one on the right side.
1487  bool Match(int left, int right);
1488  // Find an argumenting path starting from the node v on the left side. If a
1489  // path can be found, update match_list2_ to reflect the path and return
1490  // true.
1491  bool FindArgumentPathDFS(int v, std::vector<bool>* visited);
1492 
1493  int count1_;
1494  int count2_;
1495  std::unique_ptr<NodeMatchCallback> match_callback_;
1496  std::map<std::pair<int, int>, bool> cached_match_results_;
1497  std::vector<int>* match_list1_;
1498  std::vector<int>* match_list2_;
1499  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MaximumMatcher);
1500 };
1501 
1502 MaximumMatcher::MaximumMatcher(int count1, int count2,
1503  NodeMatchCallback* callback,
1504  std::vector<int>* match_list1,
1505  std::vector<int>* match_list2)
1506  : count1_(count1), count2_(count2), match_callback_(callback),
1507  match_list1_(match_list1), match_list2_(match_list2) {
1508  match_list1_->assign(count1, -1);
1509  match_list2_->assign(count2, -1);
1510 }
1511 
1512 int MaximumMatcher::FindMaximumMatch(bool early_return) {
1513  int result = 0;
1514  for (int i = 0; i < count1_; ++i) {
1515  std::vector<bool> visited(count1_);
1516  if (FindArgumentPathDFS(i, &visited)) {
1517  ++result;
1518  } else if (early_return) {
1519  return 0;
1520  }
1521  }
1522  // Backfill match_list1_ as we only filled match_list2_ when finding
1523  // argumenting pathes.
1524  for (int i = 0; i < count2_; ++i) {
1525  if ((*match_list2_)[i] != -1) {
1526  (*match_list1_)[(*match_list2_)[i]] = i;
1527  }
1528  }
1529  return result;
1530 }
1531 
1532 bool MaximumMatcher::Match(int left, int right) {
1533  std::pair<int, int> p(left, right);
1534  std::map<std::pair<int, int>, bool>::iterator it =
1535  cached_match_results_.find(p);
1536  if (it != cached_match_results_.end()) {
1537  return it->second;
1538  }
1539  cached_match_results_[p] = match_callback_->Run(left, right);
1540  return cached_match_results_[p];
1541 }
1542 
1543 bool MaximumMatcher::FindArgumentPathDFS(int v, std::vector<bool>* visited) {
1544  (*visited)[v] = true;
1545  // We try to match those un-matched nodes on the right side first. This is
1546  // the step that the navie greedy matching algorithm uses. In the best cases
1547  // where the greedy algorithm can find a maximum matching, we will always
1548  // find a match in this step and the performance will be identical to the
1549  // greedy algorithm.
1550  for (int i = 0; i < count2_; ++i) {
1551  int matched = (*match_list2_)[i];
1552  if (matched == -1 && Match(v, i)) {
1553  (*match_list2_)[i] = v;
1554  return true;
1555  }
1556  }
1557  // Then we try those already matched nodes and see if we can find an
1558  // alternaive match for the node matched to them.
1559  // The greedy algorithm will stop before this and fail to produce the
1560  // correct result.
1561  for (int i = 0; i < count2_; ++i) {
1562  int matched = (*match_list2_)[i];
1563  if (matched != -1 && Match(v, i)) {
1564  if (!(*visited)[matched] && FindArgumentPathDFS(matched, visited)) {
1565  (*match_list2_)[i] = v;
1566  return true;
1567  }
1568  }
1569  }
1570  return false;
1571 }
1572 
1573 } // namespace
1574 
1575 bool MessageDifferencer::MatchRepeatedFieldIndices(
1576  const Message& message1, const Message& message2,
1578  const MapKeyComparator* key_comparator,
1579  const std::vector<SpecificField>& parent_fields,
1580  std::vector<int>* match_list1, std::vector<int>* match_list2) {
1581  const int count1 =
1582  message1.GetReflection()->FieldSize(message1, repeated_field);
1583  const int count2 =
1584  message2.GetReflection()->FieldSize(message2, repeated_field);
1585  const bool is_treated_as_smart_set = IsTreatedAsSmartSet(repeated_field);
1586 
1587  match_list1->assign(count1, -1);
1588  match_list2->assign(count2, -1);
1589  // Ensure that we don't report differences during the matching process. Since
1590  // field comparators could potentially use this message differencer object to
1591  // perform further comparisons, turn off reporting here and re-enable it
1592  // before returning.
1593  Reporter* reporter = reporter_;
1594  reporter_ = NULL;
1595  NumDiffsReporter num_diffs_reporter;
1596  std::vector<int32> num_diffs_list1;
1597  if (is_treated_as_smart_set) {
1598  num_diffs_list1.assign(count1, kint32max);
1599  }
1600 
1601  bool success = true;
1602  // Find potential match if this is a special repeated field.
1603  if (scope_ == PARTIAL) {
1604  // When partial matching is enabled, Compare(a, b) && Compare(a, c)
1605  // doesn't necessarily imply Compare(b, c). Therefore a naive greedy
1606  // algorithm will fail to find a maximum matching.
1607  // Here we use the augmenting path algorithm.
1609  this, &MessageDifferencer::IsMatch, repeated_field, key_comparator,
1610  &message1, &message2, parent_fields, nullptr);
1611  MaximumMatcher matcher(count1, count2, callback, match_list1, match_list2);
1612  // If diff info is not needed, we should end the matching process as
1613  // soon as possible if not all items can be matched.
1614  bool early_return = (reporter == nullptr);
1615  int match_count = matcher.FindMaximumMatch(early_return);
1616  if (match_count != count1 && early_return) return false;
1617  success = success && (match_count == count1);
1618  } else {
1619  int start_offset = 0;
1620  // If the two repeated fields are treated as sets, optimize for the case
1621  // where both start with same items stored in the same order.
1622  if (IsTreatedAsSet(repeated_field) || is_treated_as_smart_set ||
1623  IsTreatedAsSmartList(repeated_field)) {
1624  start_offset = std::min(count1, count2);
1625  for (int i = 0; i < count1 && i < count2; i++) {
1626  if (IsMatch(repeated_field, key_comparator, &message1, &message2,
1627  parent_fields, nullptr, i, i)) {
1628  match_list1->at(i) = i;
1629  match_list2->at(i) = i;
1630  } else {
1631  start_offset = i;
1632  break;
1633  }
1634  }
1635  }
1636  for (int i = start_offset; i < count1; ++i) {
1637  // Indicates any matched elements for this repeated field.
1638  bool match = false;
1639  int matched_j = -1;
1640 
1641  for (int j = start_offset; j < count2; j++) {
1642  if (match_list2->at(j) != -1) {
1643  if (!is_treated_as_smart_set || num_diffs_list1[i] == 0 ||
1644  num_diffs_list1[match_list2->at(j)] == 0) {
1645  continue;
1646  }
1647  }
1648 
1649  if (is_treated_as_smart_set) {
1650  num_diffs_reporter.Reset();
1651  match = IsMatch(repeated_field, key_comparator, &message1, &message2,
1652  parent_fields, &num_diffs_reporter, i, j);
1653  } else {
1654  match = IsMatch(repeated_field, key_comparator, &message1, &message2,
1655  parent_fields, nullptr, i, j);
1656  }
1657 
1658  if (is_treated_as_smart_set) {
1659  if (match) {
1660  num_diffs_list1[i] = 0;
1661  } else if (repeated_field->cpp_type() ==
1662  FieldDescriptor::CPPTYPE_MESSAGE) {
1663  // Replace with the one with fewer diffs.
1664  const int32 num_diffs = num_diffs_reporter.GetNumDiffs();
1665  if (num_diffs < num_diffs_list1[i]) {
1666  // If j has been already matched to some element, ensure the
1667  // current num_diffs is smaller.
1668  if (match_list2->at(j) == -1 ||
1669  num_diffs < num_diffs_list1[match_list2->at(j)]) {
1670  num_diffs_list1[i] = num_diffs;
1671  match = true;
1672  }
1673  }
1674  }
1675  }
1676 
1677  if (match) {
1678  matched_j = j;
1679  if (!is_treated_as_smart_set || num_diffs_list1[i] == 0) {
1680  break;
1681  }
1682  }
1683  }
1684 
1685  match = (matched_j != -1);
1686  if (match) {
1687  if (is_treated_as_smart_set && match_list2->at(matched_j) != -1) {
1688  // This is to revert the previously matched index in list2.
1689  match_list1->at(match_list2->at(matched_j)) = -1;
1690  match = false;
1691  }
1692  match_list1->at(i) = matched_j;
1693  match_list2->at(matched_j) = i;
1694  }
1695  if (!match && reporter == nullptr) return false;
1696  success = success && match;
1697  }
1698  }
1699 
1700  if (IsTreatedAsSmartList(repeated_field)) {
1701  match_indices_for_smart_list_callback_(match_list1, match_list2);
1702  }
1703 
1704  reporter_ = reporter;
1705 
1706  return success;
1707 }
1708 
1709 FieldComparator::ComparisonResult MessageDifferencer::GetFieldComparisonResult(
1710  const Message& message1, const Message& message2,
1711  const FieldDescriptor* field, int index1, int index2,
1712  const FieldContext* field_context) {
1713  FieldComparator* comparator = field_comparator_ != NULL
1714  ? field_comparator_
1715  : &default_field_comparator_;
1716  return comparator->Compare(message1, message2, field, index1, index2,
1717  field_context);
1718 }
1719 
1720 // ===========================================================================
1721 
1722 MessageDifferencer::Reporter::Reporter() {}
1723 MessageDifferencer::Reporter::~Reporter() {}
1724 
1725 // ===========================================================================
1726 
1727 MessageDifferencer::MapKeyComparator::MapKeyComparator() {}
1728 MessageDifferencer::MapKeyComparator::~MapKeyComparator() {}
1729 
1730 // ===========================================================================
1731 
1732 MessageDifferencer::IgnoreCriteria::IgnoreCriteria() {}
1733 MessageDifferencer::IgnoreCriteria::~IgnoreCriteria() {}
1734 
1735 // ===========================================================================
1736 
1737 // Note that the printer's delimiter is not used, because if we are given a
1738 // printer, we don't know its delimiter.
1739 MessageDifferencer::StreamReporter::StreamReporter(
1741  : printer_(new io::Printer(output, '$')),
1742  delete_printer_(true),
1743  report_modified_aggregates_(false) {}
1744 
1746  : printer_(printer),
1747  delete_printer_(false),
1748  report_modified_aggregates_(false) {}
1749 
1751  if (delete_printer_) delete printer_;
1752 }
1753 
1755  const std::vector<SpecificField>& field_path, bool left_side) {
1756  for (int i = 0; i < field_path.size(); ++i) {
1757  if (i > 0) {
1758  printer_->Print(".");
1759  }
1760 
1761  SpecificField specific_field = field_path[i];
1762 
1763  if (specific_field.field != NULL) {
1764  if (specific_field.field->is_extension()) {
1765  printer_->Print("($name$)", "name", specific_field.field->full_name());
1766  } else {
1767  printer_->PrintRaw(specific_field.field->name());
1768  }
1769  if (specific_field.field->is_map()) {
1770  // Don't print index in a map field; they are semantically unordered.
1771  continue;
1772  }
1773  } else {
1774  printer_->PrintRaw(StrCat(specific_field.unknown_field_number));
1775  }
1776  if (left_side && specific_field.index >= 0) {
1777  printer_->Print("[$name$]", "name", StrCat(specific_field.index));
1778  }
1779  if (!left_side && specific_field.new_index >= 0) {
1780  printer_->Print("[$name$]", "name",
1781  StrCat(specific_field.new_index));
1782  }
1783  }
1784 }
1785 
1787  const std::vector<SpecificField>& field_path, bool left_side,
1788  const Message& message) {
1789  PrintPath(field_path, left_side);
1790 }
1791 
1793  const Message& message, const std::vector<SpecificField>& field_path,
1794  bool left_side) {
1795  const SpecificField& specific_field = field_path.back();
1796  const FieldDescriptor* field = specific_field.field;
1797  if (field != NULL) {
1799  int index = left_side ? specific_field.index : specific_field.new_index;
1800  if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
1801  const Reflection* reflection = message.GetReflection();
1802  const Message& field_message =
1803  field->is_repeated()
1804  ? reflection->GetRepeatedMessage(message, field, index)
1805  : reflection->GetMessage(message, field);
1806  output = field_message.ShortDebugString();
1807  if (output.empty()) {
1808  printer_->Print("{ }");
1809  } else {
1810  printer_->Print("{ $name$ }", "name", output);
1811  }
1812  } else {
1814  printer_->PrintRaw(output);
1815  }
1816  } else {
1817  const UnknownFieldSet* unknown_fields =
1818  (left_side ? specific_field.unknown_field_set1
1819  : specific_field.unknown_field_set2);
1820  const UnknownField* unknown_field =
1821  &unknown_fields->field(left_side ? specific_field.unknown_field_index1
1822  : specific_field.unknown_field_index2);
1823  PrintUnknownFieldValue(unknown_field);
1824  }
1825 }
1826 
1828  const UnknownField* unknown_field) {
1829  GOOGLE_CHECK(unknown_field != NULL) << " Cannot print NULL unknown_field.";
1830 
1832  switch (unknown_field->type()) {
1834  output = StrCat(unknown_field->varint());
1835  break;
1837  output = StrCat(
1838  "0x", strings::Hex(unknown_field->fixed32(), strings::ZERO_PAD_8));
1839  break;
1841  output = StrCat(
1842  "0x", strings::Hex(unknown_field->fixed64(), strings::ZERO_PAD_16));
1843  break;
1845  output = StringPrintf(
1846  "\"%s\"", CEscape(unknown_field->length_delimited()).c_str());
1847  break;
1849  // TODO(kenton): Print the contents of the group like we do for
1850  // messages. Requires an equivalent of ShortDebugString() for
1851  // UnknownFieldSet.
1852  output = "{ ... }";
1853  break;
1854  }
1855  printer_->PrintRaw(output);
1856 }
1857 
1859  printer_->Print(str.c_str());
1860 }
1861 
1863  const Message& message1, const Message& message2,
1864  const std::vector<SpecificField>& field_path) {
1865  printer_->Print("added: ");
1866  PrintPath(field_path, false, message2);
1867  printer_->Print(": ");
1868  PrintValue(message2, field_path, false);
1869  printer_->Print("\n"); // Print for newlines.
1870 }
1871 
1873  const Message& message1, const Message& message2,
1874  const std::vector<SpecificField>& field_path) {
1875  printer_->Print("deleted: ");
1876  PrintPath(field_path, true, message1);
1877  printer_->Print(": ");
1878  PrintValue(message1, field_path, true);
1879  printer_->Print("\n"); // Print for newlines
1880 }
1881 
1883  const Message& message1, const Message& message2,
1884  const std::vector<SpecificField>& field_path) {
1885  if (!report_modified_aggregates_ && field_path.back().field == NULL) {
1886  if (field_path.back().unknown_field_type == UnknownField::TYPE_GROUP) {
1887  // Any changes to the subfields have already been printed.
1888  return;
1889  }
1890  } else if (!report_modified_aggregates_) {
1891  if (field_path.back().field->cpp_type() ==
1893  // Any changes to the subfields have already been printed.
1894  return;
1895  }
1896  }
1897 
1898  printer_->Print("modified: ");
1899  PrintPath(field_path, true, message1);
1900  if (CheckPathChanged(field_path)) {
1901  printer_->Print(" -> ");
1902  PrintPath(field_path, false, message2);
1903  }
1904  printer_->Print(": ");
1905  PrintValue(message1, field_path, true);
1906  printer_->Print(" -> ");
1907  PrintValue(message2, field_path, false);
1908  printer_->Print("\n"); // Print for newlines.
1909 }
1910 
1912  const Message& message1, const Message& message2,
1913  const std::vector<SpecificField>& field_path) {
1914  printer_->Print("moved: ");
1915  PrintPath(field_path, true, message1);
1916  printer_->Print(" -> ");
1917  PrintPath(field_path, false, message2);
1918  printer_->Print(" : ");
1919  PrintValue(message1, field_path, true);
1920  printer_->Print("\n"); // Print for newlines.
1921 }
1922 
1924  const Message& message1, const Message& message2,
1925  const std::vector<SpecificField>& field_path) {
1926  printer_->Print("matched: ");
1927  PrintPath(field_path, true, message1);
1928  if (CheckPathChanged(field_path)) {
1929  printer_->Print(" -> ");
1930  PrintPath(field_path, false, message2);
1931  }
1932  printer_->Print(" : ");
1933  PrintValue(message1, field_path, true);
1934  printer_->Print("\n"); // Print for newlines.
1935 }
1936 
1938  const Message& message1, const Message& message2,
1939  const std::vector<SpecificField>& field_path) {
1940  printer_->Print("ignored: ");
1941  PrintPath(field_path, true, message1);
1942  if (CheckPathChanged(field_path)) {
1943  printer_->Print(" -> ");
1944  PrintPath(field_path, false, message2);
1945  }
1946  printer_->Print("\n"); // Print for newlines.
1947 }
1948 
1950  const Message& message1, const Message& message2,
1951  const std::vector<SpecificField>& field_path) {
1952  printer_->Print("ignored: ");
1953  PrintPath(field_path, true, message1);
1954  if (CheckPathChanged(field_path)) {
1955  printer_->Print(" -> ");
1956  PrintPath(field_path, false, message2);
1957  }
1958  printer_->Print("\n"); // Print for newlines.
1959 }
1960 
1963  const std::vector<std::vector<const FieldDescriptor*> >& key_field_paths) {
1964  return new MultipleFieldsMapKeyComparator(this, key_field_paths);
1965 }
1966 
1967 } // namespace util
1968 } // namespace protobuf
1969 } // namespace google
google::protobuf::Descriptor::full_name
const std::string & full_name() const
google::protobuf::strings::ZERO_PAD_16
@ ZERO_PAD_16
Definition: strutil.h:591
zero_copy_stream.h
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: message_differencer.cc:1071
google::protobuf::util::MessageDifferencer::scope_
Scope scope_
Definition: message_differencer.h:865
google::protobuf::util::MessageDifferencer::set_message_field_comparison
void set_message_field_comparison(MessageFieldComparison comparison)
Definition: message_differencer.cc:293
google::protobuf::Reflection::GetString
std::string GetString(const Message &message, const FieldDescriptor *field) const
Definition: generated_message_reflection.cc:1151
GOOGLE_CHECK_EQ
#define GOOGLE_CHECK_EQ(A, B)
Definition: logging.h:156
google::protobuf::util::MessageDifferencer::report_matches_
bool report_matches_
Definition: message_differencer.h:884
google::protobuf::UnknownField::TYPE_FIXED64
@ TYPE_FIXED64
Definition: unknown_field_set.h:228
google::protobuf::util::MessageDifferencer::IsMatch
bool IsMatch(const FieldDescriptor *repeated_field, const MapKeyComparator *key_comparator, const Message *message1, const Message *message2, const std::vector< SpecificField > &parent_fields, Reporter *reporter, int index1, int index2)
Definition: message_differencer.cc:873
google::protobuf::FieldDescriptor
Definition: src/google/protobuf/descriptor.h:515
google::protobuf::util::MessageDifferencer::CheckRepeatedFieldComparisons
void CheckRepeatedFieldComparisons(const FieldDescriptor *field, const RepeatedFieldComparison &new_comparison)
Definition: message_differencer.cc:313
google::protobuf::util::MessageDifferencer
Definition: message_differencer.h:120
google::protobuf::UnknownField::fixed32
uint32 fixed32() const
Definition: unknown_field_set.h:338
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS
#define GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TypeName)
Definition: macros.h:40
google::protobuf::util::MessageDifferencer::map_entry_key_comparator_
MapEntryKeyComparator map_entry_key_comparator_
Definition: message_differencer.h:877
google::protobuf::util::MessageDifferencer::Scope
Scope
Definition: message_differencer.h:359
google::protobuf::util::MessageDifferencer::field_comparator_
FieldComparator * field_comparator_
Definition: message_differencer.h:863
zero_copy_stream_impl.h
google::protobuf::util::MessageDifferencer::IsIgnored
bool IsIgnored(const Message &message1, const Message &message2, const FieldDescriptor *field, const std::vector< SpecificField > &parent_fields)
Definition: message_differencer.cc:1156
google::protobuf::util::NumDiffsReporter::ReportModified
void ReportModified(const google::protobuf::Message &message1, const google::protobuf::Message &message2, const std::vector< google::protobuf::util::MessageDifferencer::SpecificField > &field_path) override
Definition: message_differencer.cc:91
google::protobuf::util::MessageDifferencer::StreamReporter::ReportMatched
void ReportMatched(const Message &message1, const Message &message2, const std::vector< SpecificField > &field_path) override
Definition: message_differencer.cc:1923
google::protobuf::util::MessageDifferencer::FieldBefore
static bool FieldBefore(const FieldDescriptor *field1, const FieldDescriptor *field2)
Definition: message_differencer.cc:466
NULL
NULL
Definition: test_security_zap.cpp:405
google::protobuf::util::MessageDifferencer::GetMapKeyComparator
const MapKeyComparator * GetMapKeyComparator(const FieldDescriptor *field) const
Definition: message_differencer.cc:1186
google::protobuf::util::MessageDifferencer::SetMatchIndicesForSmartListCallback
void SetMatchIndicesForSmartListCallback(std::function< void(std::vector< int > *, std::vector< int > *)> callback)
Definition: message_differencer.cc:341
google::protobuf::FieldDescriptor::is_extension
bool is_extension() const
google::protobuf::util::MessageDifferencer::StreamReporter::PrintUnknownFieldValue
virtual void PrintUnknownFieldValue(const UnknownField *unknown_field)
Definition: message_differencer.cc:1827
google::protobuf::util::MessageDifferencer::MultipleFieldsMapKeyComparator
Definition: message_differencer.cc:107
google::protobuf::FieldDescriptor::full_name
const std::string & full_name() const
google::protobuf::StrCat
string StrCat(const AlphaNum &a, const AlphaNum &b)
Definition: strutil.cc:1480
google::protobuf::util::MessageDifferencer::StreamReporter::ReportDeleted
void ReportDeleted(const Message &message1, const Message &message2, const std::vector< SpecificField > &field_path) override
Definition: message_differencer.cc:1872
google::protobuf::UnknownField::TYPE_FIXED32
@ TYPE_FIXED32
Definition: unknown_field_set.h:227
google::protobuf::util::MessageDifferencer::dynamic_message_factory_
std::unique_ptr< DynamicMessageFactory > dynamic_message_factory_
Definition: message_differencer.h:894
google::protobuf::UnknownField::length_delimited
const std::string & length_delimited() const
Definition: unknown_field_set.h:346
google::protobuf.internal::ParseAnyTypeUrl
bool ParseAnyTypeUrl(const std::string &type_url, std::string *full_type_name)
Definition: any_lite.cc:117
google::protobuf::util::MessageDifferencer::IsTreatedAsSmartList
bool IsTreatedAsSmartList(const FieldDescriptor *field)
Definition: message_differencer.cc:1142
google::protobuf::util::MessageDifferencer::ReportDifferencesTo
void ReportDifferencesTo(Reporter *reporter)
Definition: message_differencer.cc:456
GOOGLE_DCHECK
#define GOOGLE_DCHECK
Definition: logging.h:194
google::protobuf::UnknownField::TYPE_VARINT
@ TYPE_VARINT
Definition: unknown_field_set.h:226
google::protobuf::UnknownField::varint
uint64 varint() const
Definition: unknown_field_set.h:334
google::protobuf::util::MessageDifferencer::StreamReporter::ReportModified
void ReportModified(const Message &message1, const Message &message2, const std::vector< SpecificField > &field_path) override
Definition: message_differencer.cc:1882
google::protobuf::Message::GetReflection
const Reflection * GetReflection() const
Definition: src/google/protobuf/message.h:335
message_differencer.h
google::protobuf::util::MessageDifferencer::Reporter::ReportMatched
virtual void ReportMatched(const Message &, const Message &, const std::vector< SpecificField > &)
Definition: message_differencer.h:260
google::protobuf.internal::kAnyFullTypeName
const char kAnyFullTypeName[]
Definition: any_lite.cc:53
google::protobuf::util::FieldComparator
Definition: field_comparator.h:60
google::protobuf::util::MessageDifferencer::set_float_comparison
void set_float_comparison(FloatComparison comparison)
Definition: message_differencer.cc:302
google::protobuf::util::MessageDifferencer::Reporter
Definition: message_differencer.h:228
google::protobuf::UnknownField
Definition: unknown_field_set.h:223
google::protobuf::Descriptor::FindFieldByNumber
const FieldDescriptor * FindFieldByNumber(int number) const
Definition: src/google/protobuf/descriptor.cc:1584
google::protobuf::FieldDescriptor::containing_type
const Descriptor * containing_type() const
google::protobuf::CEscape
string CEscape(const string &src)
Definition: strutil.cc:615
desc
#define desc
Definition: extension_set.h:342
google::protobuf::util::NumDiffsReporter::num_diffs_
int32 num_diffs_
Definition: message_differencer.cc:99
google::protobuf::util::MessageDifferencer::report_ignores_
bool report_ignores_
Definition: message_differencer.h:886
google::protobuf::util::FieldComparator::RECURSE
@ RECURSE
Definition: field_comparator.h:71
google::protobuf::util::MessageDifferencer::SpecificField::unknown_field_set1
const UnknownFieldSet * unknown_field_set1
Definition: message_differencer.h:199
google::protobuf::util::MessageDifferencer::~MessageDifferencer
~MessageDifferencer()
Definition: message_differencer.cc:279
google::protobuf::Message::ShortDebugString
std::string ShortDebugString() const
Definition: text_format.cc:98
google::protobuf::util::MessageDifferencer::APPROXIMATE
@ APPROXIMATE
Definition: message_differencer.h:369
google::protobuf::util::MessageDifferencer::TreatAsSmartList
void TreatAsSmartList(const FieldDescriptor *field)
Definition: message_differencer.cc:351
left
GLint left
Definition: glcorearb.h:4150
dynamic_message.h
google::protobuf::util::MessageDifferencer::RetrieveFields
FieldDescriptorArray RetrieveFields(const Message &message, bool base_message)
Definition: message_differencer.cc:598
google::protobuf::util::MessageDifferencer::TreatAsMapWithMultipleFieldsAsKey
void TreatAsMapWithMultipleFieldsAsKey(const FieldDescriptor *field, const std::vector< const FieldDescriptor * > &key_fields)
Definition: message_differencer.cc:375
string
GLsizei const GLchar *const * string
Definition: glcorearb.h:3083
google::protobuf::util::MessageDifferencer::MapKeyComparator::IsMatch
virtual bool IsMatch(const Message &, const Message &, const std::vector< SpecificField > &) const
Definition: message_differencer.h:305
google::protobuf::util::MessageDifferencer::StreamReporter::ReportAdded
void ReportAdded(const Message &message1, const Message &message2, const std::vector< SpecificField > &field_path) override
Definition: message_differencer.cc:1862
google::protobuf::util::MessageDifferencer::Reporter::ReportModified
virtual void ReportModified(const Message &message1, const Message &message2, const std::vector< SpecificField > &field_path)=0
google::protobuf::Reflection
Definition: src/google/protobuf/message.h:400
descriptor
Descriptor * descriptor
Definition: php/ext/google/protobuf/protobuf.h:936
google::protobuf::util::MessageDifferencer::match_indices_for_smart_list_callback_
std::function< void(std::vector< int > *, std::vector< int > *)> match_indices_for_smart_list_callback_
Definition: message_differencer.h:892
google::protobuf::Reflection::HasField
bool HasField(const Message &message, const FieldDescriptor *field) const
Definition: generated_message_reflection.cc:728
google::protobuf::ResultCallback2
Definition: callback.h:109
google::protobuf::util::MessageDifferencer::MultipleFieldsMapKeyComparator::GOOGLE_DISALLOW_EVIL_CONSTRUCTORS
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MultipleFieldsMapKeyComparator)
google::protobuf::util::FieldComparator::SAME
@ SAME
Definition: field_comparator.h:66
google::protobuf::UnknownField::type
Type type() const
Definition: unknown_field_set.h:330
callback.h
google::protobuf::util::MessageDifferencer::set_scope
void set_scope(Scope scope)
Definition: message_differencer.cc:298
google::protobuf::util::MessageDifferencer::IsTreatedAsSmartSet
bool IsTreatedAsSmartSet(const FieldDescriptor *field)
Definition: message_differencer.cc:1133
google::protobuf::util::MessageDifferencer::SpecificField::unknown_field_index1
int unknown_field_index1
Definition: message_differencer.h:205
google::protobuf::util::MessageDifferencer::repeated_field_comparison_
RepeatedFieldComparison repeated_field_comparison_
Definition: message_differencer.h:866
google::protobuf::util::MessageDifferencer::set_field_comparator
void set_field_comparator(FieldComparator *comparator)
Definition: message_differencer.cc:288
google::protobuf::util::FieldContext
Definition: message_differencer.h:900
google::protobuf::UnknownFieldSet::field_count
int field_count() const
Definition: unknown_field_set.h:311
google::protobuf::util::MessageDifferencer::EXACT
@ EXACT
Definition: message_differencer.h:368
b
GLboolean GLboolean GLboolean b
Definition: glcorearb.h:3228
google::protobuf::util::MessageDifferencer::StreamReporter::PrintPath
virtual void PrintPath(const std::vector< SpecificField > &field_path, bool left_side, const Message &message)
Definition: message_differencer.cc:1786
google::protobuf::util::MessageDifferencer::ApproximatelyEquals
static bool ApproximatelyEquals(const Message &message1, const Message &message2)
Definition: message_differencer.cc:246
google::protobuf::util::MessageDifferencer::TreatAsSet
void TreatAsSet(const FieldDescriptor *field)
Definition: message_differencer.cc:331
google::protobuf::util::MessageDifferencer::PARTIAL
@ PARTIAL
Definition: message_differencer.h:361
google::protobuf::util::MessageDifferencer::SpecificField
Definition: message_differencer.h:176
google::protobuf::int32
int32_t int32
Definition: protobuf/src/google/protobuf/stubs/port.h:150
google::protobuf::util::DefaultFieldComparator::EXACT
@ EXACT
Definition: field_comparator.h:103
google::protobuf::util::MessageDifferencer::MessageFieldComparison
MessageFieldComparison
Definition: message_differencer.h:350
google::protobuf::util::MessageDifferencer::AS_SMART_LIST
@ AS_SMART_LIST
Definition: message_differencer.h:381
google::protobuf::util::MessageDifferencer::set_repeated_field_comparison
void set_repeated_field_comparison(RepeatedFieldComparison comparison)
Definition: message_differencer.cc:308
google::protobuf::util::DefaultFieldComparator::SetFractionAndMargin
void SetFractionAndMargin(const FieldDescriptor *field, double fraction, double margin)
Definition: field_comparator.cc:144
google::protobuf::util::NumDiffsReporter::GetNumDiffs
int32 GetNumDiffs() const
Definition: message_differencer.cc:71
google::protobuf::util::MessageDifferencer::RepeatedFieldComparison
RepeatedFieldComparison
Definition: message_differencer.h:373
match_list1_
std::vector< int > * match_list1_
Definition: message_differencer.cc:1497
count2_
int count2_
Definition: message_differencer.cc:1494
google::protobuf::util::MessageDifferencer::CheckPathChanged
static bool CheckPathChanged(const std::vector< SpecificField > &parent_fields)
Definition: message_differencer.cc:1114
any.h
google::protobuf::util::MessageDifferencer::MultipleFieldsMapKeyComparator::message_differencer_
MessageDifferencer * message_differencer_
Definition: message_differencer.cc:179
strutil.h
repeated_field
PHP_PROTO_OBJECT_FREE_END PHP_PROTO_OBJECT_DTOR_END intern repeated_field
Definition: array.c:486
google::protobuf::util::NumDiffsReporter::ReportDeleted
void ReportDeleted(const google::protobuf::Message &message1, const google::protobuf::Message &message2, const std::vector< google::protobuf::util::MessageDifferencer::SpecificField > &field_path) override
Definition: message_differencer.cc:83
google::protobuf::FileDescriptor::pool
const DescriptorPool * pool() const
google::protobuf::util::MessageDifferencer::repeated_field_comparisons_
FieldMap repeated_field_comparisons_
Definition: message_differencer.h:868
google::protobuf::util::MessageDifferencer::StreamReporter::PrintValue
virtual void PrintValue(const Message &message, const std::vector< SpecificField > &field_path, bool left_side)
Definition: message_differencer.cc:1792
google::protobuf::util::MessageDifferencer::TreatAsSmartSet
void TreatAsSmartSet(const FieldDescriptor *field)
Definition: message_differencer.cc:336
google::protobuf::util::MessageDifferencer::Compare
bool Compare(const Message &message1, const Message &message2)
Definition: message_differencer.cc:482
google::protobuf::util::MessageDifferencer::MultipleFieldsMapKeyComparator::MultipleFieldsMapKeyComparator
MultipleFieldsMapKeyComparator(MessageDifferencer *message_differencer, const std::vector< std::vector< const FieldDescriptor * > > &key_field_paths)
Definition: message_differencer.cc:110
google::protobuf::util::MessageDifferencer::CreateMultipleFieldsMapKeyComparator
MapKeyComparator * CreateMultipleFieldsMapKeyComparator(const std::vector< std::vector< const FieldDescriptor * > > &key_field_paths)
Definition: message_differencer.cc:1962
google::protobuf::util::MessageDifferencer::MultipleFieldsMapKeyComparator::key_field_paths_
std::vector< std::vector< const FieldDescriptor * > > key_field_paths_
Definition: message_differencer.cc:180
update_failure_list.str
str
Definition: update_failure_list.py:41
google::protobuf::util::MessageDifferencer::AS_SET
@ AS_SET
Definition: message_differencer.h:379
google::protobuf::util::MessageDifferencer::output_string_
std::string * output_string_
Definition: message_differencer.h:888
google::protobuf::util::MessageDifferencer::Equals
static bool Equals(const Message &message1, const Message &message2)
Definition: message_differencer.cc:231
google::protobuf::util::MessageDifferencer::MessageDifferencer
MessageDifferencer()
Definition: message_differencer.cc:265
google::protobuf.internal::GetAnyFieldDescriptors
bool GetAnyFieldDescriptors(const Message &message, const FieldDescriptor **type_url_field, const FieldDescriptor **value_field)
Definition: any.cc:64
google::protobuf::util::MessageDifferencer::CompareUnknownFields
bool CompareUnknownFields(const Message &message1, const Message &message2, const UnknownFieldSet &, const UnknownFieldSet &, std::vector< SpecificField > *parent_fields)
Definition: message_differencer.cc:1250
google::protobuf::Reflection::GetUnknownFields
const UnknownFieldSet & GetUnknownFields(const Message &message) const
Definition: generated_message_reflection.cc:232
printer.h
google::protobuf::util::MessageDifferencer::StreamReporter::ReportUnknownFieldIgnored
void ReportUnknownFieldIgnored(const Message &message1, const Message &message2, const std::vector< SpecificField > &field_path) override
Definition: message_differencer.cc:1949
p
const char * p
Definition: gmock-matchers_test.cc:3863
google::protobuf::FieldDescriptor::number
int number() const
GOOGLE_LOG
#define GOOGLE_LOG(LEVEL)
Definition: logging.h:146
google::protobuf::util::MessageDifferencer::ReportDifferencesToString
void ReportDifferencesToString(std::string *output)
Definition: message_differencer.cc:449
google::protobuf::UnknownField::fixed64
uint64 fixed64() const
Definition: unknown_field_set.h:342
match_list2_
std::vector< int > * match_list2_
Definition: message_differencer.cc:1498
google::protobuf::util::MessageDifferencer::SpecificField::unknown_field_index2
int unknown_field_index2
Definition: message_differencer.h:206
google::protobuf::NewPermanentCallback
Closure * NewPermanentCallback(void(*function)())
Definition: callback.h:420
text_format.h
google::protobuf::util::MessageDifferencer::IsUnknownFieldIgnored
bool IsUnknownFieldIgnored(const Message &message1, const Message &message2, const SpecificField &field, const std::vector< SpecificField > &parent_fields)
Definition: message_differencer.cc:1172
google::protobuf::util::MessageDifferencer::CompareRequestedFieldsUsingSettings
bool CompareRequestedFieldsUsingSettings(const Message &message1, const Message &message2, const FieldDescriptorArray &message1_fields, const FieldDescriptorArray &message2_fields, std::vector< SpecificField > *parent_fields)
Definition: message_differencer.cc:629
google::protobuf::util::MessageDifferencer::IgnoreField
void IgnoreField(const FieldDescriptor *field)
Definition: message_differencer.cc:440
google::protobuf::util::MessageDifferencer::AS_LIST
@ AS_LIST
Definition: message_differencer.h:374
google::protobuf::StringPrintf
string StringPrintf(const char *format,...)
Definition: stringprintf.cc:109
GOOGLE_CHECK_LE
#define GOOGLE_CHECK_LE(A, B)
Definition: logging.h:159
google::protobuf::util::MessageDifferencer::EQUIVALENT
@ EQUIVALENT
Definition: message_differencer.h:353
field
const FieldDescriptor * field
Definition: parser_unittest.cc:2694
google::protobuf::Reflection::FieldSize
int FieldSize(const Message &message, const FieldDescriptor *field) const
Definition: generated_message_reflection.cc:744
google::protobuf::ERROR
static const LogLevel ERROR
Definition: protobuf/src/google/protobuf/testing/googletest.h:70
google::protobuf::util::MessageDifferencer::SpecificField::unknown_field_set2
const UnknownFieldSet * unknown_field_set2
Definition: message_differencer.h:200
key
const SETUP_TEARDOWN_TESTCONTEXT char * key
Definition: test_wss_transport.cpp:10
google::protobuf::util::MessageDifferencer::MapKeyComparator
Definition: message_differencer.h:300
GOOGLE_CHECK
#define GOOGLE_CHECK(EXPRESSION)
Definition: logging.h:153
google::protobuf::io::Printer
Definition: printer.h:181
cached_match_results_
std::map< std::pair< int, int >, bool > cached_match_results_
Definition: message_differencer.cc:1496
google::protobuf::util::MessageDifferencer::TreatAsList
void TreatAsList(const FieldDescriptor *field)
Definition: message_differencer.cc:346
google::protobuf::util::MessageDifferencer::ignore_criteria_
std::vector< IgnoreCriteria * > ignore_criteria_
Definition: message_differencer.h:878
google::protobuf::util::MessageDifferencer::SpecificField::new_index
int new_index
Definition: message_differencer.h:193
google::protobuf::util::MessageDifferencer::FloatComparison
FloatComparison
Definition: message_differencer.h:367
google::protobuf::util::MessageDifferencer::Reporter::ReportUnknownFieldIgnored
virtual void ReportUnknownFieldIgnored(const Message &, const Message &, const std::vector< SpecificField > &)
Definition: message_differencer.h:290
google::protobuf::util::MessageDifferencer::IsTreatedAsSet
bool IsTreatedAsSet(const FieldDescriptor *field)
Definition: message_differencer.cc:1124
i
int i
Definition: gmock-matchers_test.cc:764
google::protobuf::util::MatchIndicesPostProcessorForSmartList
void MatchIndicesPostProcessorForSmartList(std::vector< int > *match_list1, std::vector< int > *match_list2)
Definition: message_differencer.cc:189
google::protobuf::util::MessageDifferencer::MapEntryKeyComparator::IsMatch
bool IsMatch(const Message &message1, const Message &message2, const std::vector< SpecificField > &parent_fields) const override
Definition: message_differencer.cc:209
count1_
int count1_
Definition: message_differencer.cc:1493
google::protobuf::DynamicMessageFactory
Definition: dynamic_message.h:80
google::protobuf::util::MessageDifferencer::TreatAsMapUsingKeyComparator
void TreatAsMapUsingKeyComparator(const FieldDescriptor *field, const MapKeyComparator *key_comparator)
Definition: message_differencer.cc:424
google::protobuf::util::MessageDifferencer::StreamReporter
Definition: message_differencer.h:612
google::protobuf::util::MessageDifferencer::SetFractionAndMargin
void SetFractionAndMargin(const FieldDescriptor *field, double fraction, double margin)
Definition: message_differencer.cc:444
google::protobuf::util::NumDiffsReporter::ReportAdded
void ReportAdded(const google::protobuf::Message &message1, const google::protobuf::Message &message2, const std::vector< google::protobuf::util::MessageDifferencer::SpecificField > &field_path) override
Definition: message_differencer.cc:75
google::protobuf::util::MessageDifferencer::MatchRepeatedFieldIndices
bool MatchRepeatedFieldIndices(const Message &message1, const Message &message2, const FieldDescriptor *repeated_field, const MapKeyComparator *key_comparator, const std::vector< SpecificField > &parent_fields, std::vector< int > *match_list1, std::vector< int > *match_list2)
Definition: message_differencer.cc:1575
google::protobuf::util::MessageDifferencer::StreamReporter::ReportMoved
void ReportMoved(const Message &message1, const Message &message2, const std::vector< SpecificField > &field_path) override
Definition: message_differencer.cc:1911
google::protobuf::UnknownField::TYPE_GROUP
@ TYPE_GROUP
Definition: unknown_field_set.h:230
google::protobuf::util::MessageDifferencer::StreamReporter::~StreamReporter
~StreamReporter() override
Definition: message_differencer.cc:1750
google::protobuf::util::MessageDifferencer::message_field_comparison_
MessageFieldComparison message_field_comparison_
Definition: message_differencer.h:864
google::protobuf::util::MessageDifferencer::StreamReporter::ReportIgnored
void ReportIgnored(const Message &message1, const Message &message2, const std::vector< SpecificField > &field_path) override
Definition: message_differencer.cc:1937
google::protobuf::UnknownFieldSet::field
const UnknownField & field(int index) const
Definition: unknown_field_set.h:314
google::protobuf::Message
Definition: src/google/protobuf/message.h:205
google::protobuf::util::MessageDifferencer::report_moves_
bool report_moves_
Definition: message_differencer.h:885
google::protobuf::Message::GetDescriptor
const Descriptor * GetDescriptor() const
Definition: src/google/protobuf/message.h:326
google::protobuf::io::StringOutputStream
Definition: zero_copy_stream_impl_lite.h:131
google::protobuf::util::MessageDifferencer::reporter_
Reporter * reporter_
Definition: message_differencer.h:861
google::protobuf::util::MessageDifferencer::Reporter::ReportAdded
virtual void ReportAdded(const Message &message1, const Message &message2, const std::vector< SpecificField > &field_path)=0
google::protobuf::util::MessageDifferencer::map_field_key_comparator_
FieldKeyComparatorMap map_field_key_comparator_
Definition: message_differencer.h:876
google::protobuf::util::MessageDifferencer::CompareRepeatedField
bool CompareRepeatedField(const Message &message1, const Message &message2, const FieldDescriptor *field, std::vector< SpecificField > *parent_fields)
Definition: message_differencer.cc:916
google::protobuf::util::MessageDifferencer::SpecificField::unknown_field_number
int unknown_field_number
Definition: message_differencer.h:181
google::protobuf::kint32max
static const int32 kint32max
Definition: protobuf/src/google/protobuf/stubs/port.h:159
google::protobuf::UnknownField::TYPE_LENGTH_DELIMITED
@ TYPE_LENGTH_DELIMITED
Definition: unknown_field_set.h:229
google::protobuf::util::FieldDescriptorArray
std::vector< const FieldDescriptor * > FieldDescriptorArray
Definition: message_differencer.h:73
PrintValue
::std::string PrintValue(const T &value)
Definition: googletest-param-test-test.cc:69
v
const GLdouble * v
Definition: glcorearb.h:3106
google::protobuf::FieldDescriptor::name
const std::string & name() const
google::protobuf::util::MessageDifferencer::AS_SMART_SET
@ AS_SMART_SET
Definition: message_differencer.h:385
common.h
google::protobuf::util::MessageDifferencer::CompareWithFields
bool CompareWithFields(const Message &message1, const Message &message2, const std::vector< const FieldDescriptor * > &message1_fields, const std::vector< const FieldDescriptor * > &message2_fields)
Definition: message_differencer.cc:502
google::protobuf::util::MessageDifferencer::AddIgnoreCriteria
void AddIgnoreCriteria(IgnoreCriteria *ignore_criteria)
Definition: message_differencer.cc:436
google::protobuf::UnknownFieldSet::empty
bool empty() const
Definition: unknown_field_set.h:305
google::protobuf::util::NumDiffsReporter::NumDiffsReporter
NumDiffsReporter()
Definition: message_differencer.cc:68
google::protobuf::util::MessageDifferencer::Reporter::ReportMoved
virtual void ReportMoved(const Message &, const Message &, const std::vector< SpecificField > &)
Definition: message_differencer.h:252
google::protobuf::util::MessageDifferencer::StreamReporter::Print
void Print(const std::string &str)
Definition: message_differencer.cc:1858
field_comparator.h
google::protobuf::UnknownFieldSet
Definition: unknown_field_set.h:86
google::protobuf::io::ZeroCopyOutputStream
Definition: zero_copy_stream.h:183
google::protobuf::util::MessageDifferencer::SpecificField::unknown_field_type
UnknownField::Type unknown_field_type
Definition: message_differencer.h:182
stringprintf.h
google::protobuf::util::MessageDifferencer::IgnoreCriteria
Definition: message_differencer.h:322
logging.h
google::protobuf::Descriptor::file
const FileDescriptor * file() const
google::protobuf::util::MessageDifferencer::Reporter::ReportDeleted
virtual void ReportDeleted(const Message &message1, const Message &message2, const std::vector< SpecificField > &field_path)=0
match_callback_
std::unique_ptr< NodeMatchCallback > match_callback_
Definition: message_differencer.cc:1495
google::protobuf::Descriptor
Definition: src/google/protobuf/descriptor.h:231
google::protobuf::util::MessageDifferencer::CombineFields
FieldDescriptorArray CombineFields(const FieldDescriptorArray &fields1, Scope fields1_scope, const FieldDescriptorArray &fields2, Scope fields2_scope)
Definition: message_differencer.cc:668
google::protobuf::util::MessageDifferencer::CompareWithFieldsInternal
bool CompareWithFieldsInternal(const Message &message1, const Message &message2, const FieldDescriptorArray &message1_fields, const FieldDescriptorArray &message2_fields, std::vector< SpecificField > *parent_fields)
Definition: message_differencer.cc:705
GOOGLE_DLOG
#define GOOGLE_DLOG
Definition: logging.h:192
google::protobuf::util::NumDiffsReporter
Definition: message_differencer.cc:66
google::protobuf::util::MessageDifferencer::default_field_comparator_
DefaultFieldComparator default_field_comparator_
Definition: message_differencer.h:862
google::protobuf::util::MessageDifferencer::Reporter::ReportIgnored
virtual void ReportIgnored(const Message &, const Message &, const std::vector< SpecificField > &)
Definition: message_differencer.h:283
google::protobuf::util::MessageDifferencer::StreamReporter::StreamReporter
StreamReporter(io::ZeroCopyOutputStream *output)
Definition: message_differencer.cc:1739
google::protobuf::util::FieldComparator::Compare
virtual ComparisonResult Compare(const Message &message_1, const Message &message_2, const FieldDescriptor *field, int index_1, int index_2, const util::FieldContext *field_context)=0
google::protobuf::FieldDescriptor::message_type
const Descriptor * message_type() const
Definition: src/google/protobuf/descriptor.cc:7228
google::protobuf::util::MessageDifferencer::MapEntryKeyComparator::MapEntryKeyComparator
MapEntryKeyComparator(MessageDifferencer *message_differencer)
Definition: message_differencer.cc:205
google::protobuf::util::FieldComparator::ComparisonResult
ComparisonResult
Definition: field_comparator.h:65
google::protobuf::util::MessageDifferencer::EQUAL
@ EQUAL
Definition: message_differencer.h:351
data
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: glcorearb.h:2879
google::protobuf::util::DefaultFieldComparator::set_float_comparison
void set_float_comparison(FloatComparison float_comparison)
Definition: field_comparator.h:121
google::protobuf::util::MessageDifferencer::CompareFieldValue
bool CompareFieldValue(const Message &message1, const Message &message2, const FieldDescriptor *field, int index1, int index2)
Definition: message_differencer.cc:1063
true
#define true
Definition: cJSON.c:65
google::protobuf::util::MessageDifferencer::TreatAsMapWithMultipleFieldPathsAsKey
void TreatAsMapWithMultipleFieldPathsAsKey(const FieldDescriptor *field, const std::vector< std::vector< const FieldDescriptor * > > &key_field_paths)
Definition: message_differencer.cc:387
google::protobuf::util::MessageDifferencer::TreatAsMap
void TreatAsMap(const FieldDescriptor *field, const FieldDescriptor *key)
Definition: message_differencer.cc:356
google::protobuf::util::MessageDifferencer::IsTreatedAsSubset
bool IsTreatedAsSubset(const FieldDescriptor *field)
Definition: message_differencer.cc:1151
google::protobuf::util::MessageDifferencer::UnpackAny
bool UnpackAny(const Message &any, std::unique_ptr< Message > *data)
Definition: message_differencer.cc:1216
google::protobuf::util::MessageDifferencer::tmp_message_fields_
std::vector< const FieldDescriptor * > tmp_message_fields_
Definition: message_differencer.h:880
type_url
string * type_url
Definition: conformance_cpp.cc:98
descriptor.pb.h
google::protobuf::util::MessageDifferencer::SpecificField::index
int index
Definition: message_differencer.h:187
google::protobuf::UnknownField::number
int number() const
Definition: unknown_field_set.h:329
google::protobuf::util::MessageDifferencer::owned_key_comparators_
std::vector< MapKeyComparator * > owned_key_comparators_
Definition: message_differencer.h:875
google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE
@ CPPTYPE_MESSAGE
Definition: src/google/protobuf/descriptor.h:563
output
const upb_json_parsermethod const upb_symtab upb_sink * output
Definition: ruby/ext/google/protobuf_c/upb.h:10503
google::protobuf::util::DefaultFieldComparator::APPROXIMATE
@ APPROXIMATE
Definition: field_comparator.h:104
google::protobuf::util::MessageDifferencer::Equivalent
static bool Equivalent(const Message &message1, const Message &message2)
Definition: message_differencer.cc:238
count
GLint GLsizei count
Definition: glcorearb.h:2830
false
#define false
Definition: cJSON.c:70
index
GLuint index
Definition: glcorearb.h:3055
google::protobuf::util::MessageDifferencer::MultipleFieldsMapKeyComparator::IsMatch
bool IsMatch(const Message &message1, const Message &message2, const std::vector< SpecificField > &parent_fields) const override
Definition: message_differencer.cc:127
a
GLboolean GLboolean GLboolean GLboolean a
Definition: glcorearb.h:3228
google::protobuf::util::MessageDifferencer::GetFieldComparisonResult
FieldComparator::ComparisonResult GetFieldComparisonResult(const Message &message1, const Message &message2, const FieldDescriptor *field, int index1, int index2, const FieldContext *field_context)
Definition: message_differencer.cc:1709
google::protobuf::util::NumDiffsReporter::Reset
void Reset()
Definition: message_differencer.cc:72
google::protobuf::Reflection::ListFields
void ListFields(const Message &message, std::vector< const FieldDescriptor * > *output) const
Definition: generated_message_reflection.cc:1029
google::protobuf::FieldDescriptor::is_repeated
bool is_repeated() const
Definition: src/google/protobuf/descriptor.h:2067
google::protobuf::util::MessageDifferencer::ApproximatelyEquivalent
static bool ApproximatelyEquivalent(const Message &message1, const Message &message2)
Definition: message_differencer.cc:254
google::protobuf::FieldDescriptor::cpp_type
CppType cpp_type() const
Definition: src/google/protobuf/descriptor.h:2139
it
MapIter it
Definition: php/ext/google/protobuf/map.c:205
google::protobuf::TextFormat::PrintFieldValueToString
static void PrintFieldValueToString(const Message &message, const FieldDescriptor *field, int index, std::string *output)
Definition: text_format.cc:2408
google
Definition: data_proto2_to_proto3_util.h:11
message
GLenum GLuint GLenum GLsizei const GLchar * message
Definition: glcorearb.h:2695
google::protobuf::util::MessageDifferencer::ignored_fields_
FieldSet ignored_fields_
Definition: message_differencer.h:882
google::protobuf::Reflection::GetRepeatedMessage
const Message & GetRepeatedMessage(const Message &message, const FieldDescriptor *field, int index) const
Definition: generated_message_reflection.cc:1597
google::protobuf::util::MessageDifferencer::scope
Scope scope()
Definition: message_differencer.cc:300
google::protobuf::util::MessageDifferencer::MultipleFieldsMapKeyComparator::MultipleFieldsMapKeyComparator
MultipleFieldsMapKeyComparator(MessageDifferencer *message_differencer, const FieldDescriptor *key)
Definition: message_differencer.cc:120
google::protobuf::util::MessageDifferencer::SpecificField::field
const FieldDescriptor * field
Definition: message_differencer.h:180
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: message_differencer.cc:139
google::protobuf::util::MessageDifferencer::FULL
@ FULL
Definition: message_differencer.h:360
google::protobuf::strings::ZERO_PAD_8
@ ZERO_PAD_8
Definition: strutil.h:583
google::protobuf::Reflection::GetMessage
const Message & GetMessage(const Message &message, const FieldDescriptor *field, MessageFactory *factory=nullptr) const
Definition: generated_message_reflection.cc:1443
google::protobuf::FieldDescriptor::is_map
bool is_map() const
Definition: src/google/protobuf/descriptor.h:2075
google::protobuf::DescriptorPool::FindMessageTypeByName
const Descriptor * FindMessageTypeByName(const std::string &name) const
Definition: src/google/protobuf/descriptor.cc:1430


libaditof
Author(s):
autogenerated on Wed May 21 2025 02:06:56