blob: 0f879dc72be18d3b3895319ecd162997f5f98419 [file] [log] [blame]
Brian Silverman9c614bc2016-02-15 20:20:02 -05001// Protocol Buffers - Google's data interchange format
2// Copyright 2008 Google Inc. All rights reserved.
3// https://developers.google.com/protocol-buffers/
4//
5// Redistribution and use in source and binary forms, with or without
6// modification, are permitted provided that the following conditions are
7// met:
8//
9// * Redistributions of source code must retain the above copyright
10// notice, this list of conditions and the following disclaimer.
11// * Redistributions in binary form must reproduce the above
12// copyright notice, this list of conditions and the following disclaimer
13// in the documentation and/or other materials provided with the
14// distribution.
15// * Neither the name of Google Inc. nor the names of its
16// contributors may be used to endorse or promote products derived from
17// this software without specific prior written permission.
18//
19// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31// Author: jschorr@google.com (Joseph Schorr)
32// Based on original Protocol Buffers design by
33// Sanjay Ghemawat, Jeff Dean, and others.
34//
35// This file defines static methods and classes for comparing Protocol
36// Messages (see //google/protobuf/util/message_differencer.h for more
37// information).
38
39#include <google/protobuf/util/message_differencer.h>
40
41#include <algorithm>
42#include <memory>
43#ifndef _SHARED_PTR_H
44#include <google/protobuf/stubs/shared_ptr.h>
45#endif
46#include <utility>
47
48#include <google/protobuf/stubs/callback.h>
49#include <google/protobuf/stubs/common.h>
50#include <google/protobuf/stubs/stringprintf.h>
51#include <google/protobuf/any.h>
52#include <google/protobuf/io/printer.h>
53#include <google/protobuf/io/zero_copy_stream.h>
54#include <google/protobuf/io/zero_copy_stream_impl.h>
55#include <google/protobuf/dynamic_message.h>
56#include <google/protobuf/text_format.h>
57#include <google/protobuf/util/field_comparator.h>
58#include <google/protobuf/stubs/strutil.h>
59
60namespace google {
61namespace protobuf {
62
63namespace util {
64
65// When comparing a repeated field as map, MultipleFieldMapKeyComparator can
66// be used to specify multiple fields as key for key comparison.
67// Two elements of a repeated field will be regarded as having the same key
68// iff they have the same value for every specified key field.
69// Note that you can also specify only one field as key.
70class MessageDifferencer::MultipleFieldsMapKeyComparator
71 : public MessageDifferencer::MapKeyComparator {
72 public:
73 MultipleFieldsMapKeyComparator(
74 MessageDifferencer* message_differencer,
75 const vector<vector<const FieldDescriptor*> >& key_field_paths)
76 : message_differencer_(message_differencer),
77 key_field_paths_(key_field_paths) {
78 GOOGLE_CHECK(!key_field_paths_.empty());
79 for (int i = 0; i < key_field_paths_.size(); ++i) {
80 GOOGLE_CHECK(!key_field_paths_[i].empty());
81 }
82 }
83 MultipleFieldsMapKeyComparator(
84 MessageDifferencer* message_differencer,
85 const FieldDescriptor* key)
86 : message_differencer_(message_differencer) {
87 vector<const FieldDescriptor*> key_field_path;
88 key_field_path.push_back(key);
89 key_field_paths_.push_back(key_field_path);
90 }
91 virtual bool IsMatch(
92 const Message& message1,
93 const Message& message2,
94 const vector<SpecificField>& parent_fields) const {
95 for (int i = 0; i < key_field_paths_.size(); ++i) {
96 if (!IsMatchInternal(message1, message2, parent_fields,
97 key_field_paths_[i], 0)) {
98 return false;
99 }
100 }
101 return true;
102 }
103 private:
104 bool IsMatchInternal(
105 const Message& message1,
106 const Message& message2,
107 const vector<SpecificField>& parent_fields,
108 const vector<const FieldDescriptor*>& key_field_path,
109 int path_index) const {
110 const FieldDescriptor* field = key_field_path[path_index];
111 vector<SpecificField> current_parent_fields(parent_fields);
112 if (path_index == key_field_path.size() - 1) {
113 if (field->is_repeated()) {
114 if (!message_differencer_->CompareRepeatedField(
115 message1, message2, field, &current_parent_fields)) {
116 return false;
117 }
118 } else {
119 if (!message_differencer_->CompareFieldValueUsingParentFields(
120 message1, message2, field, -1, -1, &current_parent_fields)) {
121 return false;
122 }
123 }
124 return true;
125 } else {
126 const Reflection* reflection1 = message1.GetReflection();
127 const Reflection* reflection2 = message2.GetReflection();
128 bool has_field1 = reflection1->HasField(message1, field);
129 bool has_field2 = reflection2->HasField(message2, field);
130 if (!has_field1 && !has_field2) {
131 return true;
132 }
133 if (has_field1 != has_field2) {
134 return false;
135 }
136 SpecificField specific_field;
137 specific_field.field = field;
138 current_parent_fields.push_back(specific_field);
139 return IsMatchInternal(
140 reflection1->GetMessage(message1, field),
141 reflection2->GetMessage(message2, field),
142 current_parent_fields,
143 key_field_path,
144 path_index + 1);
145 }
146 }
147 MessageDifferencer* message_differencer_;
148 vector<vector<const FieldDescriptor*> > key_field_paths_;
149 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MultipleFieldsMapKeyComparator);
150};
151
152bool MessageDifferencer::Equals(const Message& message1,
153 const Message& message2) {
154 MessageDifferencer differencer;
155
156 return differencer.Compare(message1, message2);
157}
158
159bool MessageDifferencer::Equivalent(const Message& message1,
160 const Message& message2) {
161 MessageDifferencer differencer;
162 differencer.set_message_field_comparison(MessageDifferencer::EQUIVALENT);
163
164 return differencer.Compare(message1, message2);
165}
166
167bool MessageDifferencer::ApproximatelyEquals(const Message& message1,
168 const Message& message2) {
169 MessageDifferencer differencer;
170 differencer.set_float_comparison(
171 MessageDifferencer::APPROXIMATE);
172
173 return differencer.Compare(message1, message2);
174}
175
176bool MessageDifferencer::ApproximatelyEquivalent(const Message& message1,
177 const Message& message2) {
178 MessageDifferencer differencer;
179 differencer.set_message_field_comparison(MessageDifferencer::EQUIVALENT);
180 differencer.set_float_comparison(MessageDifferencer::APPROXIMATE);
181
182 return differencer.Compare(message1, message2);
183}
184
185// ===========================================================================
186
187MessageDifferencer::MessageDifferencer()
188 : reporter_(NULL),
189 field_comparator_(NULL),
190 message_field_comparison_(EQUAL),
191 scope_(FULL),
192 repeated_field_comparison_(AS_LIST),
193 report_matches_(false),
194 output_string_(NULL) { }
195
196MessageDifferencer::~MessageDifferencer() {
197 for (int i = 0; i < owned_key_comparators_.size(); ++i) {
198 delete owned_key_comparators_[i];
199 }
200 for (int i = 0; i < ignore_criteria_.size(); ++i) {
201 delete ignore_criteria_[i];
202 }
203}
204
205void MessageDifferencer::set_field_comparator(FieldComparator* comparator) {
206 GOOGLE_CHECK(comparator) << "Field comparator can't be NULL.";
207 field_comparator_ = comparator;
208}
209
210void MessageDifferencer::set_message_field_comparison(
211 MessageFieldComparison comparison) {
212 message_field_comparison_ = comparison;
213}
214
215void MessageDifferencer::set_scope(Scope scope) {
216 scope_ = scope;
217}
218
219MessageDifferencer::Scope MessageDifferencer::scope() {
220 return scope_;
221}
222
223void MessageDifferencer::set_float_comparison(FloatComparison comparison) {
224 default_field_comparator_.set_float_comparison(
225 comparison == EXACT ?
226 DefaultFieldComparator::EXACT : DefaultFieldComparator::APPROXIMATE);
227}
228
229void MessageDifferencer::set_repeated_field_comparison(
230 RepeatedFieldComparison comparison) {
231 repeated_field_comparison_ = comparison;
232}
233
234void MessageDifferencer::TreatAsSet(const FieldDescriptor* field) {
235 GOOGLE_CHECK(field->is_repeated()) << "Field must be repeated: "
236 << field->full_name();
237 const MapKeyComparator* key_comparator = GetMapKeyComparator(field);
238 GOOGLE_CHECK(key_comparator == NULL)
239 << "Cannot treat this repeated field as both Map and Set for"
240 << " comparison. Field name is: " << field->full_name();
241 GOOGLE_CHECK(list_fields_.find(field) == list_fields_.end())
242 << "Cannot treat the same field as both SET and LIST. Field name is: "
243 << field->full_name();
244 set_fields_.insert(field);
245}
246
247void MessageDifferencer::TreatAsList(const FieldDescriptor* field) {
248 GOOGLE_CHECK(field->is_repeated()) << "Field must be repeated: "
249 << field->full_name();
250 const MapKeyComparator* key_comparator = GetMapKeyComparator(field);
251 GOOGLE_CHECK(key_comparator == NULL)
252 << "Cannot treat this repeated field as both Map and Set for"
253 << " comparison. Field name is: " << field->full_name();
254 GOOGLE_CHECK(set_fields_.find(field) == set_fields_.end())
255 << "Cannot treat the same field as both SET and LIST. Field name is: "
256 << field->full_name();
257 list_fields_.insert(field);
258}
259
260void MessageDifferencer::TreatAsMap(const FieldDescriptor* field,
261 const FieldDescriptor* key) {
262 GOOGLE_CHECK(field->is_repeated()) << "Field must be repeated: "
263 << field->full_name();
264 GOOGLE_CHECK_EQ(FieldDescriptor::CPPTYPE_MESSAGE, field->cpp_type())
265 << "Field has to be message type. Field name is: "
266 << field->full_name();
267 GOOGLE_CHECK(key->containing_type() == field->message_type())
268 << key->full_name()
269 << " must be a direct subfield within the repeated field "
270 << field->full_name() << ", not " << key->containing_type()->full_name();
271 GOOGLE_CHECK(set_fields_.find(field) == set_fields_.end())
272 << "Cannot treat this repeated field as both Map and Set for "
273 << "comparison.";
274 GOOGLE_CHECK(list_fields_.find(field) == list_fields_.end())
275 << "Cannot treat this repeated field as both Map and List for "
276 << "comparison.";
277 MapKeyComparator* key_comparator =
278 new MultipleFieldsMapKeyComparator(this, key);
279 owned_key_comparators_.push_back(key_comparator);
280 map_field_key_comparator_[field] = key_comparator;
281}
282
283void MessageDifferencer::TreatAsMapWithMultipleFieldsAsKey(
284 const FieldDescriptor* field,
285 const vector<const FieldDescriptor*>& key_fields) {
286 vector<vector<const FieldDescriptor*> > key_field_paths;
287 for (int i = 0; i < key_fields.size(); ++i) {
288 vector<const FieldDescriptor*> key_field_path;
289 key_field_path.push_back(key_fields[i]);
290 key_field_paths.push_back(key_field_path);
291 }
292 TreatAsMapWithMultipleFieldPathsAsKey(field, key_field_paths);
293}
294
295void MessageDifferencer::TreatAsMapWithMultipleFieldPathsAsKey(
296 const FieldDescriptor* field,
297 const vector<vector<const FieldDescriptor*> >& key_field_paths) {
298 GOOGLE_CHECK(field->is_repeated()) << "Field must be repeated: "
299 << field->full_name();
300 GOOGLE_CHECK_EQ(FieldDescriptor::CPPTYPE_MESSAGE, field->cpp_type())
301 << "Field has to be message type. Field name is: "
302 << field->full_name();
303 for (int i = 0; i < key_field_paths.size(); ++i) {
304 const vector<const FieldDescriptor*>& key_field_path = key_field_paths[i];
305 for (int j = 0; j < key_field_path.size(); ++j) {
306 const FieldDescriptor* parent_field =
307 j == 0 ? field : key_field_path[j - 1];
308 const FieldDescriptor* child_field = key_field_path[j];
309 GOOGLE_CHECK(child_field->containing_type() == parent_field->message_type())
310 << child_field->full_name()
311 << " must be a direct subfield within the field: "
312 << parent_field->full_name();
313 if (j != 0) {
314 GOOGLE_CHECK_EQ(FieldDescriptor::CPPTYPE_MESSAGE, parent_field->cpp_type())
315 << parent_field->full_name() << " has to be of type message.";
316 GOOGLE_CHECK(!parent_field->is_repeated())
317 << parent_field->full_name() << " cannot be a repeated field.";
318 }
319 }
320 }
321 GOOGLE_CHECK(set_fields_.find(field) == set_fields_.end())
322 << "Cannot treat this repeated field as both Map and Set for "
323 << "comparison.";
324 MapKeyComparator* key_comparator =
325 new MultipleFieldsMapKeyComparator(this, key_field_paths);
326 owned_key_comparators_.push_back(key_comparator);
327 map_field_key_comparator_[field] = key_comparator;
328}
329
330void MessageDifferencer::TreatAsMapUsingKeyComparator(
331 const FieldDescriptor* field,
332 const MapKeyComparator* key_comparator) {
333 GOOGLE_CHECK(field->is_repeated()) << "Field must be repeated: "
334 << field->full_name();
335 GOOGLE_CHECK_EQ(FieldDescriptor::CPPTYPE_MESSAGE, field->cpp_type())
336 << "Field has to be message type. Field name is: "
337 << field->full_name();
338 GOOGLE_CHECK(set_fields_.find(field) == set_fields_.end())
339 << "Cannot treat this repeated field as both Map and Set for "
340 << "comparison.";
341 map_field_key_comparator_[field] = key_comparator;
342}
343
344void MessageDifferencer::AddIgnoreCriteria(IgnoreCriteria* ignore_criteria) {
345 ignore_criteria_.push_back(ignore_criteria);
346}
347
348void MessageDifferencer::IgnoreField(const FieldDescriptor* field) {
349 ignored_fields_.insert(field);
350}
351
352void MessageDifferencer::SetFractionAndMargin(const FieldDescriptor* field,
353 double fraction, double margin) {
354 default_field_comparator_.SetFractionAndMargin(field, fraction, margin);
355}
356
357void MessageDifferencer::ReportDifferencesToString(string* output) {
358 GOOGLE_DCHECK(output) << "Specified output string was NULL";
359
360 output_string_ = output;
361 output_string_->clear();
362}
363
364void MessageDifferencer::ReportDifferencesTo(Reporter* reporter) {
365 // If an output string is set, clear it to prevent
366 // it superceding the specified reporter.
367 if (output_string_) {
368 output_string_ = NULL;
369 }
370
371 reporter_ = reporter;
372}
373
374bool MessageDifferencer::FieldBefore(const FieldDescriptor* field1,
375 const FieldDescriptor* field2) {
376 // Handle sentinel values (i.e. make sure NULLs are always ordered
377 // at the end of the list).
378 if (field1 == NULL) {
379 return false;
380 }
381
382 if (field2 == NULL) {
383 return true;
384 }
385
386 // Always order fields by their tag number
387 return (field1->number() < field2->number());
388}
389
390bool MessageDifferencer::Compare(const Message& message1,
391 const Message& message2) {
392 vector<SpecificField> parent_fields;
393
394 bool result = false;
395
396 // Setup the internal reporter if need be.
397 if (output_string_) {
398 io::StringOutputStream output_stream(output_string_);
399 StreamReporter reporter(&output_stream);
400 reporter_ = &reporter;
401 result = Compare(message1, message2, &parent_fields);
402 reporter_ = NULL;
403 } else {
404 result = Compare(message1, message2, &parent_fields);
405 }
406
407 return result;
408}
409
410bool MessageDifferencer::CompareWithFields(
411 const Message& message1,
412 const Message& message2,
413 const vector<const FieldDescriptor*>& message1_fields_arg,
414 const vector<const FieldDescriptor*>& message2_fields_arg) {
415 if (message1.GetDescriptor() != message2.GetDescriptor()) {
416 GOOGLE_LOG(DFATAL) << "Comparison between two messages with different "
417 << "descriptors.";
418 return false;
419 }
420
421 vector<SpecificField> parent_fields;
422
423 bool result = false;
424
425 vector<const FieldDescriptor*> message1_fields(message1_fields_arg);
426 vector<const FieldDescriptor*> message2_fields(message2_fields_arg);
427
428 std::sort(message1_fields.begin(), message1_fields.end(), FieldBefore);
429 std::sort(message2_fields.begin(), message2_fields.end(), FieldBefore);
430 // Append NULL sentinel values.
431 message1_fields.push_back(NULL);
432 message2_fields.push_back(NULL);
433
434 // Setup the internal reporter if need be.
435 if (output_string_) {
436 io::StringOutputStream output_stream(output_string_);
437 StreamReporter reporter(&output_stream);
438 reporter_ = &reporter;
439 result = CompareRequestedFieldsUsingSettings(
440 message1, message2, message1_fields, message2_fields, &parent_fields);
441 reporter_ = NULL;
442 } else {
443 result = CompareRequestedFieldsUsingSettings(
444 message1, message2, message1_fields, message2_fields, &parent_fields);
445 }
446
447 return result;
448}
449
450bool MessageDifferencer::Compare(
451 const Message& message1,
452 const Message& message2,
453 vector<SpecificField>* parent_fields) {
454 const Descriptor* descriptor1 = message1.GetDescriptor();
455 const Descriptor* descriptor2 = message2.GetDescriptor();
456 if (descriptor1 != descriptor2) {
457 GOOGLE_LOG(DFATAL) << "Comparison between two messages with different "
458 << "descriptors.";
459 return false;
460 }
461 // Expand google.protobuf.Any payload if possible.
462 if (descriptor1->full_name() == internal::kAnyFullTypeName) {
463 google::protobuf::scoped_ptr<Message> data1;
464 google::protobuf::scoped_ptr<Message> data2;
465 if (UnpackAny(message1, &data1) && UnpackAny(message2, &data2)) {
466 return Compare(*data1, *data2, parent_fields);
467 }
468 }
469 const Reflection* reflection1 = message1.GetReflection();
470 const Reflection* reflection2 = message2.GetReflection();
471
472 // Retrieve all the set fields, including extensions.
473 vector<const FieldDescriptor*> message1_fields;
474 vector<const FieldDescriptor*> message2_fields;
475
476 reflection1->ListFields(message1, &message1_fields);
477 reflection2->ListFields(message2, &message2_fields);
478
479 // Add sentinel values to deal with the
480 // case where the number of the fields in
481 // each list are different.
482 message1_fields.push_back(NULL);
483 message2_fields.push_back(NULL);
484
485 bool unknown_compare_result = true;
486 // Ignore unknown fields in EQUIVALENT mode
487 if (message_field_comparison_ != EQUIVALENT) {
488 const google::protobuf::UnknownFieldSet* unknown_field_set1 =
489 &reflection1->GetUnknownFields(message1);
490 const google::protobuf::UnknownFieldSet* unknown_field_set2 =
491 &reflection2->GetUnknownFields(message2);
492 if (!CompareUnknownFields(message1, message2,
493 *unknown_field_set1, *unknown_field_set2,
494 parent_fields)) {
495 if (reporter_ == NULL) {
496 return false;
497 };
498 unknown_compare_result = false;
499 }
500 }
501
502 return CompareRequestedFieldsUsingSettings(
503 message1, message2,
504 message1_fields, message2_fields,
505 parent_fields) && unknown_compare_result;
506}
507
508bool MessageDifferencer::CompareRequestedFieldsUsingSettings(
509 const Message& message1,
510 const Message& message2,
511 const vector<const FieldDescriptor*>& message1_fields,
512 const vector<const FieldDescriptor*>& message2_fields,
513 vector<SpecificField>* parent_fields) {
514 if (scope_ == FULL) {
515 if (message_field_comparison_ == EQUIVALENT) {
516 // We need to merge the field lists of both messages (i.e.
517 // we are merely checking for a difference in field values,
518 // rather than the addition or deletion of fields).
519 vector<const FieldDescriptor*> fields_union;
520 CombineFields(message1_fields, FULL, message2_fields, FULL,
521 &fields_union);
522 return CompareWithFieldsInternal(message1, message2, fields_union,
523 fields_union, parent_fields);
524 } else {
525 // Simple equality comparison, use the unaltered field lists.
526 return CompareWithFieldsInternal(message1, message2, message1_fields,
527 message2_fields, parent_fields);
528 }
529 } else {
530 if (message_field_comparison_ == EQUIVALENT) {
531 // We use the list of fields for message1 for both messages when
532 // comparing. This way, extra fields in message2 are ignored,
533 // and missing fields in message2 use their default value.
534 return CompareWithFieldsInternal(message1, message2, message1_fields,
535 message1_fields, parent_fields);
536 } else {
537 // We need to consider the full list of fields for message1
538 // but only the intersection for message2. This way, any fields
539 // only present in message2 will be ignored, but any fields only
540 // present in message1 will be marked as a difference.
541 vector<const FieldDescriptor*> fields_intersection;
542 CombineFields(message1_fields, PARTIAL, message2_fields, PARTIAL,
543 &fields_intersection);
544 return CompareWithFieldsInternal(message1, message2, message1_fields,
545 fields_intersection, parent_fields);
546 }
547 }
548}
549
550void MessageDifferencer::CombineFields(
551 const vector<const FieldDescriptor*>& fields1,
552 Scope fields1_scope,
553 const vector<const FieldDescriptor*>& fields2,
554 Scope fields2_scope,
555 vector<const FieldDescriptor*>* combined_fields) {
556
557 int index1 = 0;
558 int index2 = 0;
559
560 while (index1 < fields1.size() && index2 < fields2.size()) {
561 const FieldDescriptor* field1 = fields1[index1];
562 const FieldDescriptor* field2 = fields2[index2];
563
564 if (FieldBefore(field1, field2)) {
565 if (fields1_scope == FULL) {
566 combined_fields->push_back(fields1[index1]);
567 }
568 ++index1;
569 } else if (FieldBefore(field2, field1)) {
570 if (fields2_scope == FULL) {
571 combined_fields->push_back(fields2[index2]);
572 }
573 ++index2;
574 } else {
575 combined_fields->push_back(fields1[index1]);
576 ++index1;
577 ++index2;
578 }
579 }
580}
581
582bool MessageDifferencer::CompareWithFieldsInternal(
583 const Message& message1,
584 const Message& message2,
585 const vector<const FieldDescriptor*>& message1_fields,
586 const vector<const FieldDescriptor*>& message2_fields,
587 vector<SpecificField>* parent_fields) {
588 bool isDifferent = false;
589 int field_index1 = 0;
590 int field_index2 = 0;
591
592 const Reflection* reflection1 = message1.GetReflection();
593 const Reflection* reflection2 = message2.GetReflection();
594
595 while (true) {
596 const FieldDescriptor* field1 = message1_fields[field_index1];
597 const FieldDescriptor* field2 = message2_fields[field_index2];
598
599 // Once we have reached sentinel values, we are done the comparison.
600 if (field1 == NULL && field2 == NULL) {
601 break;
602 }
603
604 // Check for differences in the field itself.
605 if (FieldBefore(field1, field2)) {
606 // Field 1 is not in the field list for message 2.
607 if (IsIgnored(message1, message2, field1, *parent_fields)) {
608 // We are ignoring field1. Report the ignore and move on to
609 // the next field in message1_fields.
610 if (reporter_ != NULL) {
611 SpecificField specific_field;
612 specific_field.field = field1;
613
614 parent_fields->push_back(specific_field);
615 reporter_->ReportIgnored(message1, message2, *parent_fields);
616 parent_fields->pop_back();
617 }
618 ++field_index1;
619 continue;
620 }
621
622 if (reporter_ != NULL) {
623 int count = field1->is_repeated() ?
624 reflection1->FieldSize(message1, field1) : 1;
625
626 for (int i = 0; i < count; ++i) {
627 SpecificField specific_field;
628 specific_field.field = field1;
629 specific_field.index = field1->is_repeated() ? i : -1;
630
631 parent_fields->push_back(specific_field);
632 reporter_->ReportDeleted(message1, message2, *parent_fields);
633 parent_fields->pop_back();
634 }
635
636 isDifferent = true;
637 } else {
638 return false;
639 }
640
641 ++field_index1;
642 continue;
643 } else if (FieldBefore(field2, field1)) {
644 // Field 2 is not in the field list for message 1.
645 if (IsIgnored(message1, message2, field2, *parent_fields)) {
646 // We are ignoring field2. Report the ignore and move on to
647 // the next field in message2_fields.
648 if (reporter_ != NULL) {
649 SpecificField specific_field;
650 specific_field.field = field2;
651
652 parent_fields->push_back(specific_field);
653 reporter_->ReportIgnored(message1, message2, *parent_fields);
654 parent_fields->pop_back();
655 }
656 ++field_index2;
657 continue;
658 }
659
660 if (reporter_ != NULL) {
661 int count = field2->is_repeated() ?
662 reflection2->FieldSize(message2, field2) : 1;
663
664 for (int i = 0; i < count; ++i) {
665 SpecificField specific_field;
666 specific_field.field = field2;
667 specific_field.index = field2->is_repeated() ? i : -1;
668 specific_field.new_index = specific_field.index;
669
670 parent_fields->push_back(specific_field);
671 reporter_->ReportAdded(message1, message2, *parent_fields);
672 parent_fields->pop_back();
673 }
674
675 isDifferent = true;
676 } else {
677 return false;
678 }
679
680 ++field_index2;
681 continue;
682 }
683
684 // By this point, field1 and field2 are guarenteed to point to the same
685 // field, so we can now compare the values.
686 if (IsIgnored(message1, message2, field1, *parent_fields)) {
687 // Ignore this field. Report and move on.
688 if (reporter_ != NULL) {
689 SpecificField specific_field;
690 specific_field.field = field1;
691
692 parent_fields->push_back(specific_field);
693 reporter_->ReportIgnored(message1, message2, *parent_fields);
694 parent_fields->pop_back();
695 }
696
697 ++field_index1;
698 ++field_index2;
699 continue;
700 }
701
702 bool fieldDifferent = false;
703 if (field1->is_repeated()) {
704 fieldDifferent = !CompareRepeatedField(message1, message2, field1,
705 parent_fields);
706 if (fieldDifferent) {
707 if (reporter_ == NULL) return false;
708 isDifferent = true;
709 }
710 } else {
711 fieldDifferent = !CompareFieldValueUsingParentFields(
712 message1, message2, field1, -1, -1, parent_fields);
713
714 // If we have found differences, either report them or terminate if
715 // no reporter is present.
716 if (fieldDifferent && reporter_ == NULL) {
717 return false;
718 }
719
720 if (reporter_ != NULL) {
721 SpecificField specific_field;
722 specific_field.field = field1;
723 parent_fields->push_back(specific_field);
724 if (fieldDifferent) {
725 reporter_->ReportModified(message1, message2, *parent_fields);
726 isDifferent = true;
727 } else if (report_matches_) {
728 reporter_->ReportMatched(message1, message2, *parent_fields);
729 }
730 parent_fields->pop_back();
731 }
732 }
733 // Increment the field indicies.
734 ++field_index1;
735 ++field_index2;
736 }
737
738 return !isDifferent;
739}
740
741bool MessageDifferencer::IsMatch(const FieldDescriptor* repeated_field,
742 const MapKeyComparator* key_comparator,
743 const Message* message1,
744 const Message* message2,
745 const vector<SpecificField>& parent_fields,
746 int index1, int index2) {
747 vector<SpecificField> current_parent_fields(parent_fields);
748 if (repeated_field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) {
749 return CompareFieldValueUsingParentFields(
750 *message1, *message2, repeated_field, index1, index2,
751 &current_parent_fields);
752 }
753 // Back up the Reporter and output_string_. They will be reset in the
754 // following code.
755 Reporter* backup_reporter = reporter_;
756 string* output_string = output_string_;
757 reporter_ = NULL;
758 output_string_ = NULL;
759 bool match;
760
761 if (key_comparator == NULL) {
762 match = CompareFieldValueUsingParentFields(
763 *message1, *message2, repeated_field, index1, index2,
764 &current_parent_fields);
765 } else {
766 const Reflection* reflection1 = message1->GetReflection();
767 const Reflection* reflection2 = message2->GetReflection();
768 const Message& m1 =
769 reflection1->GetRepeatedMessage(*message1, repeated_field, index1);
770 const Message& m2 =
771 reflection2->GetRepeatedMessage(*message2, repeated_field, index2);
772 SpecificField specific_field;
773 specific_field.field = repeated_field;
774 current_parent_fields.push_back(specific_field);
775 match = key_comparator->IsMatch(m1, m2, current_parent_fields);
776 }
777
778 reporter_ = backup_reporter;
779 output_string_ = output_string;
780 return match;
781}
782
783bool MessageDifferencer::CompareRepeatedField(
784 const Message& message1,
785 const Message& message2,
786 const FieldDescriptor* repeated_field,
787 vector<SpecificField>* parent_fields) {
788 // the input FieldDescriptor is guaranteed to be repeated field.
789 const Reflection* reflection1 = message1.GetReflection();
790 const Reflection* reflection2 = message2.GetReflection();
791 const int count1 = reflection1->FieldSize(message1, repeated_field);
792 const int count2 = reflection2->FieldSize(message2, repeated_field);
793 const bool treated_as_subset = IsTreatedAsSubset(repeated_field);
794
795 // If the field is not treated as subset and no detailed reports is needed,
796 // we do a quick check on the number of the elements to avoid unnecessary
797 // comparison.
798 if (count1 != count2 && reporter_ == NULL && !treated_as_subset) {
799 return false;
800 }
801 // A match can never be found if message1 has more items than message2.
802 if (count1 > count2 && reporter_ == NULL) {
803 return false;
804 }
805
806 // These two list are used for store the index of the correspondent
807 // element in peer repeated field.
808 vector<int> match_list1;
809 vector<int> match_list2;
810
811 // Try to match indices of the repeated fields. Return false if match fails
812 // and there's no detailed report needed.
813 if (!MatchRepeatedFieldIndices(message1, message2, repeated_field,
814 *parent_fields, &match_list1, &match_list2) &&
815 reporter_ == NULL) {
816 return false;
817 }
818
819 bool fieldDifferent = false;
820 SpecificField specific_field;
821 specific_field.field = repeated_field;
822
823 // At this point, we have already matched pairs of fields (with the reporting
824 // to be done later). Now to check if the paired elements are different.
825 for (int i = 0; i < count1; i++) {
826 if (match_list1[i] == -1) continue;
827 specific_field.index = i;
828 specific_field.new_index = match_list1[i];
829
830 const bool result = CompareFieldValueUsingParentFields(
831 message1, message2, repeated_field, i, specific_field.new_index,
832 parent_fields);
833
834 // If we have found differences, either report them or terminate if
835 // no reporter is present. Note that ReportModified, ReportMoved, and
836 // ReportMatched are all mutually exclusive.
837 if (!result) {
838 if (reporter_ == NULL) return false;
839 parent_fields->push_back(specific_field);
840 reporter_->ReportModified(message1, message2, *parent_fields);
841 parent_fields->pop_back();
842 fieldDifferent = true;
843 } else if (reporter_ != NULL &&
844 specific_field.index != specific_field.new_index) {
845 parent_fields->push_back(specific_field);
846 reporter_->ReportMoved(message1, message2, *parent_fields);
847 parent_fields->pop_back();
848 } else if (report_matches_ && reporter_ != NULL) {
849 parent_fields->push_back(specific_field);
850 reporter_->ReportMatched(message1, message2, *parent_fields);
851 parent_fields->pop_back();
852 }
853 }
854
855 // Report any remaining additions or deletions.
856 for (int i = 0; i < count2; ++i) {
857 if (match_list2[i] != -1) continue;
858 if (!treated_as_subset) {
859 fieldDifferent = true;
860 }
861
862 if (reporter_ == NULL) continue;
863 specific_field.index = i;
864 specific_field.new_index = i;
865 parent_fields->push_back(specific_field);
866 reporter_->ReportAdded(message1, message2, *parent_fields);
867 parent_fields->pop_back();
868 }
869
870 for (int i = 0; i < count1; ++i) {
871 if (match_list1[i] != -1) continue;
872 specific_field.index = i;
873 parent_fields->push_back(specific_field);
874 reporter_->ReportDeleted(message1, message2, *parent_fields);
875 parent_fields->pop_back();
876 fieldDifferent = true;
877 }
878 return !fieldDifferent;
879}
880
881bool MessageDifferencer::CompareFieldValue(const Message& message1,
882 const Message& message2,
883 const FieldDescriptor* field,
884 int index1,
885 int index2) {
886 return CompareFieldValueUsingParentFields(message1, message2, field, index1,
887 index2, NULL);
888}
889
890bool MessageDifferencer::CompareFieldValueUsingParentFields(
891 const Message& message1, const Message& message2,
892 const FieldDescriptor* field, int index1, int index2,
893 vector<SpecificField>* parent_fields) {
894 FieldContext field_context(parent_fields);
895 FieldComparator::ComparisonResult result = GetFieldComparisonResult(
896 message1, message2, field, index1, index2, &field_context);
897
898 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
899 result == FieldComparator::RECURSE) {
900 // Get the nested messages and compare them using one of the Compare
901 // methods.
902 const Reflection* reflection1 = message1.GetReflection();
903 const Reflection* reflection2 = message2.GetReflection();
904 const Message& m1 = field->is_repeated() ?
905 reflection1->GetRepeatedMessage(message1, field, index1) :
906 reflection1->GetMessage(message1, field);
907 const Message& m2 = field->is_repeated() ?
908 reflection2->GetRepeatedMessage(message2, field, index2) :
909 reflection2->GetMessage(message2, field);
910
911 // parent_fields is used in calls to Reporter methods.
912 if (parent_fields != NULL) {
913 // Append currently compared field to the end of parent_fields.
914 SpecificField specific_field;
915 specific_field.field = field;
916 specific_field.index = index1;
917 specific_field.new_index = index2;
918 parent_fields->push_back(specific_field);
919 const bool compare_result = Compare(m1, m2, parent_fields);
920 parent_fields->pop_back();
921 return compare_result;
922 } else {
923 // Recreates parent_fields as if m1 and m2 had no parents.
924 return Compare(m1, m2);
925 }
926 } else {
927 return (result == FieldComparator::SAME);
928 }
929}
930
931bool MessageDifferencer::CheckPathChanged(
932 const vector<SpecificField>& field_path) {
933 for (int i = 0; i < field_path.size(); ++i) {
934 if (field_path[i].index != field_path[i].new_index) return true;
935 }
936 return false;
937}
938
939bool MessageDifferencer::IsTreatedAsSet(const FieldDescriptor* field) {
940 if (!field->is_repeated()) return false;
941 if (field->is_map()) return true;
942 if (repeated_field_comparison_ == AS_SET)
943 return list_fields_.find(field) == list_fields_.end();
944 return (set_fields_.find(field) != set_fields_.end());
945}
946
947bool MessageDifferencer::IsTreatedAsSubset(const FieldDescriptor* field) {
948 return scope_ == PARTIAL &&
949 (IsTreatedAsSet(field) || GetMapKeyComparator(field) != NULL);
950}
951
952bool MessageDifferencer::IsIgnored(
953 const Message& message1,
954 const Message& message2,
955 const FieldDescriptor* field,
956 const vector<SpecificField>& parent_fields) {
957 if (ignored_fields_.find(field) != ignored_fields_.end()) {
958 return true;
959 }
960 for (int i = 0; i < ignore_criteria_.size(); ++i) {
961 if (ignore_criteria_[i]->IsIgnored(message1, message2, field,
962 parent_fields)) {
963 return true;
964 }
965 }
966 return false;
967}
968
969bool MessageDifferencer::IsUnknownFieldIgnored(
970 const Message& message1, const Message& message2,
971 const SpecificField& field, const vector<SpecificField>& parent_fields) {
972 for (int i = 0; i < ignore_criteria_.size(); ++i) {
973 if (ignore_criteria_[i]->IsUnknownFieldIgnored(message1, message2, field,
974 parent_fields)) {
975 return true;
976 }
977 }
978 return false;
979}
980
981const MessageDifferencer::MapKeyComparator* MessageDifferencer
982 ::GetMapKeyComparator(const FieldDescriptor* field) {
983 if (!field->is_repeated()) return NULL;
984 if (map_field_key_comparator_.find(field) !=
985 map_field_key_comparator_.end()) {
986 return map_field_key_comparator_[field];
987 }
988 return NULL;
989}
990
991namespace {
992
993typedef pair<int, const UnknownField*> IndexUnknownFieldPair;
994
995struct UnknownFieldOrdering {
996 inline bool operator()(const IndexUnknownFieldPair& a,
997 const IndexUnknownFieldPair& b) const {
998 if (a.second->number() < b.second->number()) return true;
999 if (a.second->number() > b.second->number()) return false;
1000 return a.second->type() < b.second->type();
1001 }
1002};
1003
1004} // namespace
1005
1006bool MessageDifferencer::UnpackAny(const Message& any,
1007 google::protobuf::scoped_ptr<Message>* data) {
1008 const Reflection* reflection = any.GetReflection();
1009 const FieldDescriptor* type_url_field;
1010 const FieldDescriptor* value_field;
1011 if (!internal::GetAnyFieldDescriptors(any, &type_url_field, &value_field)) {
1012 return false;
1013 }
1014 const string& type_url = reflection->GetString(any, type_url_field);
1015 string full_type_name;
1016 if (!internal::ParseAnyTypeUrl(type_url, &full_type_name)) {
1017 return false;
1018 }
1019
1020 const google::protobuf::Descriptor* desc =
1021 any.GetDescriptor()->file()->pool()->FindMessageTypeByName(
1022 full_type_name);
1023 if (desc == NULL) {
1024 GOOGLE_LOG(ERROR) << "Proto type '" << full_type_name << "' not found";
1025 return false;
1026 }
1027
1028 if (dynamic_message_factory_ == NULL) {
1029 dynamic_message_factory_.reset(new DynamicMessageFactory());
1030 }
1031 data->reset(dynamic_message_factory_->GetPrototype(desc)->New());
1032 string serialized_value = reflection->GetString(any, value_field);
1033 if (!(*data)->ParseFromString(serialized_value)) {
1034 GOOGLE_LOG(ERROR) << "Failed to parse value for " << full_type_name;
1035 return false;
1036 }
1037 return true;
1038}
1039
1040bool MessageDifferencer::CompareUnknownFields(
1041 const Message& message1, const Message& message2,
1042 const google::protobuf::UnknownFieldSet& unknown_field_set1,
1043 const google::protobuf::UnknownFieldSet& unknown_field_set2,
1044 vector<SpecificField>* parent_field) {
1045 // Ignore unknown fields in EQUIVALENT mode.
1046 if (message_field_comparison_ == EQUIVALENT) return true;
1047
1048 if (unknown_field_set1.empty() && unknown_field_set2.empty()) {
1049 return true;
1050 }
1051
1052 bool is_different = false;
1053
1054 // We first sort the unknown fields by field number and type (in other words,
1055 // in tag order), making sure to preserve ordering of values with the same
1056 // tag. This allows us to report only meaningful differences between the
1057 // two sets -- that is, differing values for the same tag. We use
1058 // IndexUnknownFieldPairs to keep track of the field's original index for
1059 // reporting purposes.
1060 vector<IndexUnknownFieldPair> fields1; // unknown_field_set1, sorted
1061 vector<IndexUnknownFieldPair> fields2; // unknown_field_set2, sorted
1062 fields1.reserve(unknown_field_set1.field_count());
1063 fields2.reserve(unknown_field_set2.field_count());
1064
1065 for (int i = 0; i < unknown_field_set1.field_count(); i++) {
1066 fields1.push_back(std::make_pair(i, &unknown_field_set1.field(i)));
1067 }
1068 for (int i = 0; i < unknown_field_set2.field_count(); i++) {
1069 fields2.push_back(std::make_pair(i, &unknown_field_set2.field(i)));
1070 }
1071
1072 UnknownFieldOrdering is_before;
1073 std::stable_sort(fields1.begin(), fields1.end(), is_before);
1074 std::stable_sort(fields2.begin(), fields2.end(), is_before);
1075
1076 // In order to fill in SpecificField::index, we have to keep track of how
1077 // many values we've seen with the same field number and type.
1078 // current_repeated points at the first field in this range, and
1079 // current_repeated_start{1,2} are the indexes of the first field in the
1080 // range within fields1 and fields2.
1081 const UnknownField* current_repeated = NULL;
1082 int current_repeated_start1 = 0;
1083 int current_repeated_start2 = 0;
1084
1085 // Now that we have two sorted lists, we can detect fields which appear only
1086 // in one list or the other by traversing them simultaneously.
1087 int index1 = 0;
1088 int index2 = 0;
1089 while (index1 < fields1.size() || index2 < fields2.size()) {
1090 enum { ADDITION, DELETION, MODIFICATION, COMPARE_GROUPS,
1091 NO_CHANGE } change_type;
1092
1093 // focus_field is the field we're currently reporting on. (In the case
1094 // of a modification, it's the field on the left side.)
1095 const UnknownField* focus_field;
1096 bool match = false;
1097
1098 if (index2 == fields2.size() ||
1099 (index1 < fields1.size() &&
1100 is_before(fields1[index1], fields2[index2]))) {
1101 // fields1[index1] is not present in fields2.
1102 change_type = DELETION;
1103 focus_field = fields1[index1].second;
1104 } else if (index1 == fields1.size() ||
1105 is_before(fields2[index2], fields1[index1])) {
1106 // fields2[index2] is not present in fields1.
1107 if (scope_ == PARTIAL) {
1108 // Ignore.
1109 ++index2;
1110 continue;
1111 }
1112 change_type = ADDITION;
1113 focus_field = fields2[index2].second;
1114 } else {
1115 // Field type and number are the same. See if the values differ.
1116 change_type = MODIFICATION;
1117 focus_field = fields1[index1].second;
1118
1119 switch (focus_field->type()) {
1120 case UnknownField::TYPE_VARINT:
1121 match = fields1[index1].second->varint() ==
1122 fields2[index2].second->varint();
1123 break;
1124 case UnknownField::TYPE_FIXED32:
1125 match = fields1[index1].second->fixed32() ==
1126 fields2[index2].second->fixed32();
1127 break;
1128 case UnknownField::TYPE_FIXED64:
1129 match = fields1[index1].second->fixed64() ==
1130 fields2[index2].second->fixed64();
1131 break;
1132 case UnknownField::TYPE_LENGTH_DELIMITED:
1133 match = fields1[index1].second->length_delimited() ==
1134 fields2[index2].second->length_delimited();
1135 break;
1136 case UnknownField::TYPE_GROUP:
1137 // We must deal with this later, after building the SpecificField.
1138 change_type = COMPARE_GROUPS;
1139 break;
1140 }
1141 if (match && change_type != COMPARE_GROUPS) {
1142 change_type = NO_CHANGE;
1143 }
1144 }
1145
1146 if (current_repeated == NULL ||
1147 focus_field->number() != current_repeated->number() ||
1148 focus_field->type() != current_repeated->type()) {
1149 // We've started a new repeated field.
1150 current_repeated = focus_field;
1151 current_repeated_start1 = index1;
1152 current_repeated_start2 = index2;
1153 }
1154
1155 if (change_type == NO_CHANGE && reporter_ == NULL) {
1156 // Fields were already compared and matched and we have no reporter.
1157 ++index1;
1158 ++index2;
1159 continue;
1160 }
1161
1162 // Build the SpecificField. This is slightly complicated.
1163 SpecificField specific_field;
1164 specific_field.unknown_field_number = focus_field->number();
1165 specific_field.unknown_field_type = focus_field->type();
1166
1167 specific_field.unknown_field_set1 = &unknown_field_set1;
1168 specific_field.unknown_field_set2 = &unknown_field_set2;
1169
1170 if (change_type != ADDITION) {
1171 specific_field.unknown_field_index1 = fields1[index1].first;
1172 }
1173 if (change_type != DELETION) {
1174 specific_field.unknown_field_index2 = fields2[index2].first;
1175 }
1176
1177 // Calculate the field index.
1178 if (change_type == ADDITION) {
1179 specific_field.index = index2 - current_repeated_start2;
1180 specific_field.new_index = index2 - current_repeated_start2;
1181 } else {
1182 specific_field.index = index1 - current_repeated_start1;
1183 specific_field.new_index = index2 - current_repeated_start2;
1184 }
1185
1186 if (IsUnknownFieldIgnored(message1, message2, specific_field,
1187 *parent_field)) {
1188 if (reporter_ != NULL) {
1189 parent_field->push_back(specific_field);
1190 reporter_->ReportUnknownFieldIgnored(message1, message2, *parent_field);
1191 parent_field->pop_back();
1192 }
1193 return true;
1194 }
1195
1196 if (change_type == ADDITION || change_type == DELETION ||
1197 change_type == MODIFICATION) {
1198 if (reporter_ == NULL) {
1199 // We found a difference and we have no reproter.
1200 return false;
1201 }
1202 is_different = true;
1203 }
1204
1205 parent_field->push_back(specific_field);
1206
1207 switch (change_type) {
1208 case ADDITION:
1209 reporter_->ReportAdded(message1, message2, *parent_field);
1210 ++index2;
1211 break;
1212 case DELETION:
1213 reporter_->ReportDeleted(message1, message2, *parent_field);
1214 ++index1;
1215 break;
1216 case MODIFICATION:
1217 reporter_->ReportModified(message1, message2, *parent_field);
1218 ++index1;
1219 ++index2;
1220 break;
1221 case COMPARE_GROUPS:
1222 if (!CompareUnknownFields(message1, message2,
1223 fields1[index1].second->group(),
1224 fields2[index2].second->group(),
1225 parent_field)) {
1226 if (reporter_ == NULL) return false;
1227 is_different = true;
1228 reporter_->ReportModified(message1, message2, *parent_field);
1229 }
1230 ++index1;
1231 ++index2;
1232 break;
1233 case NO_CHANGE:
1234 ++index1;
1235 ++index2;
1236 if (report_matches_) {
1237 reporter_->ReportMatched(message1, message2, *parent_field);
1238 }
1239 }
1240
1241 parent_field->pop_back();
1242 }
1243
1244 return !is_different;
1245}
1246
1247namespace {
1248
1249// Find maximum bipartite matching using the argumenting path algorithm.
1250class MaximumMatcher {
1251 public:
1252 typedef ResultCallback2<bool, int, int> NodeMatchCallback;
1253 // MaximumMatcher takes ownership of the passed in callback and uses it to
1254 // determine whether a node on the left side of the bipartial graph matches
1255 // a node on the right side. count1 is the number of nodes on the left side
1256 // of the graph and count2 to is the number of nodes on the right side.
1257 // Every node is referred to using 0-based indices.
1258 // If a maximum match is found, the result will be stored in match_list1 and
1259 // match_list2. match_list1[i] == j means the i-th node on the left side is
1260 // matched to the j-th node on the right side and match_list2[x] == y means
1261 // the x-th node on the right side is matched to y-th node on the left side.
1262 // match_list1[i] == -1 means the node is not matched. Same with match_list2.
1263 MaximumMatcher(int count1, int count2, NodeMatchCallback* callback,
1264 vector<int>* match_list1, vector<int>* match_list2);
1265 // Find a maximum match and return the number of matched node pairs.
1266 // If early_return is true, this method will return 0 immediately when it
1267 // finds that not all nodes on the left side can be matched.
1268 int FindMaximumMatch(bool early_return);
1269 private:
1270 // Determines whether the node on the left side of the bipartial graph
1271 // matches the one on the right side.
1272 bool Match(int left, int right);
1273 // Find an argumenting path starting from the node v on the left side. If a
1274 // path can be found, update match_list2_ to reflect the path and return
1275 // true.
1276 bool FindArgumentPathDFS(int v, vector<bool>* visited);
1277
1278 int count1_;
1279 int count2_;
1280 google::protobuf::scoped_ptr<NodeMatchCallback> match_callback_;
1281 map<pair<int, int>, bool> cached_match_results_;
1282 vector<int>* match_list1_;
1283 vector<int>* match_list2_;
1284 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MaximumMatcher);
1285};
1286
1287MaximumMatcher::MaximumMatcher(int count1, int count2,
1288 NodeMatchCallback* callback,
1289 vector<int>* match_list1,
1290 vector<int>* match_list2)
1291 : count1_(count1), count2_(count2), match_callback_(callback),
1292 match_list1_(match_list1), match_list2_(match_list2) {
1293 match_list1_->assign(count1, -1);
1294 match_list2_->assign(count2, -1);
1295}
1296
1297int MaximumMatcher::FindMaximumMatch(bool early_return) {
1298 int result = 0;
1299 for (int i = 0; i < count1_; ++i) {
1300 vector<bool> visited(count1_);
1301 if (FindArgumentPathDFS(i, &visited)) {
1302 ++result;
1303 } else if (early_return) {
1304 return 0;
1305 }
1306 }
1307 // Backfill match_list1_ as we only filled match_list2_ when finding
1308 // argumenting pathes.
1309 for (int i = 0; i < count2_; ++i) {
1310 if ((*match_list2_)[i] != -1) {
1311 (*match_list1_)[(*match_list2_)[i]] = i;
1312 }
1313 }
1314 return result;
1315}
1316
1317bool MaximumMatcher::Match(int left, int right) {
1318 pair<int, int> p(left, right);
1319 map<pair<int, int>, bool>::iterator it = cached_match_results_.find(p);
1320 if (it != cached_match_results_.end()) {
1321 return it->second;
1322 }
1323 cached_match_results_[p] = match_callback_->Run(left, right);
1324 return cached_match_results_[p];
1325}
1326
1327bool MaximumMatcher::FindArgumentPathDFS(int v, vector<bool>* visited) {
1328 (*visited)[v] = true;
1329 // We try to match those un-matched nodes on the right side first. This is
1330 // the step that the navie greedy matching algorithm uses. In the best cases
1331 // where the greedy algorithm can find a maximum matching, we will always
1332 // find a match in this step and the performance will be identical to the
1333 // greedy algorithm.
1334 for (int i = 0; i < count2_; ++i) {
1335 int matched = (*match_list2_)[i];
1336 if (matched == -1 && Match(v, i)) {
1337 (*match_list2_)[i] = v;
1338 return true;
1339 }
1340 }
1341 // Then we try those already matched nodes and see if we can find an
1342 // alternaive match for the node matched to them.
1343 // The greedy algorithm will stop before this and fail to produce the
1344 // correct result.
1345 for (int i = 0; i < count2_; ++i) {
1346 int matched = (*match_list2_)[i];
1347 if (matched != -1 && Match(v, i)) {
1348 if (!(*visited)[matched] && FindArgumentPathDFS(matched, visited)) {
1349 (*match_list2_)[i] = v;
1350 return true;
1351 }
1352 }
1353 }
1354 return false;
1355}
1356
1357} // namespace
1358
1359bool MessageDifferencer::MatchRepeatedFieldIndices(
1360 const Message& message1,
1361 const Message& message2,
1362 const FieldDescriptor* repeated_field,
1363 const vector<SpecificField>& parent_fields,
1364 vector<int>* match_list1,
1365 vector<int>* match_list2) {
1366 const int count1 =
1367 message1.GetReflection()->FieldSize(message1, repeated_field);
1368 const int count2 =
1369 message2.GetReflection()->FieldSize(message2, repeated_field);
1370 const MapKeyComparator* key_comparator = GetMapKeyComparator(repeated_field);
1371
1372 match_list1->assign(count1, -1);
1373 match_list2->assign(count2, -1);
1374
1375 SpecificField specific_field;
1376 specific_field.field = repeated_field;
1377
1378 bool success = true;
1379 // Find potential match if this is a special repeated field.
1380 if (key_comparator != NULL || IsTreatedAsSet(repeated_field)) {
1381 if (scope_ == PARTIAL) {
1382 // When partial matching is enabled, Compare(a, b) && Compare(a, c)
1383 // doesn't neccessarily imply Compare(b, c). Therefore a naive greedy
1384 // algorithm will fail to find a maximum matching.
1385 // Here we use the argumenting path algorithm.
1386 MaximumMatcher::NodeMatchCallback* callback =
1387 google::protobuf::internal::NewPermanentCallback(
1388 this, &MessageDifferencer::IsMatch,
1389 repeated_field, key_comparator,
1390 &message1, &message2, parent_fields);
1391 MaximumMatcher matcher(count1, count2, callback, match_list1,
1392 match_list2);
1393 // If diff info is not needed, we should end the matching process as
1394 // soon as possible if not all items can be matched.
1395 bool early_return = (reporter_ == NULL);
1396 int match_count = matcher.FindMaximumMatch(early_return);
1397 if (match_count != count1 && reporter_ == NULL) return false;
1398 success = success && (match_count == count1);
1399 } else {
1400 for (int i = 0; i < count1; ++i) {
1401 // Indicates any matched elements for this repeated field.
1402 bool match = false;
1403
1404 specific_field.index = i;
1405 specific_field.new_index = i;
1406
1407 for (int j = 0; j < count2; j++) {
1408 if (match_list2->at(j) != -1) continue;
1409 specific_field.index = i;
1410 specific_field.new_index = j;
1411
1412 match = IsMatch(repeated_field, key_comparator,
1413 &message1, &message2, parent_fields, i, j);
1414
1415 if (match) {
1416 match_list1->at(specific_field.index) = specific_field.new_index;
1417 match_list2->at(specific_field.new_index) = specific_field.index;
1418 break;
1419 }
1420 }
1421 if (!match && reporter_ == NULL) return false;
1422 success = success && match;
1423 }
1424 }
1425 } else {
1426 // If this field should be treated as list, just label the match_list.
1427 for (int i = 0; i < count1 && i < count2; i++) {
1428 match_list1->at(i) = i;
1429 match_list2->at(i) = i;
1430 }
1431 }
1432
1433 return success;
1434}
1435
1436FieldComparator::ComparisonResult MessageDifferencer::GetFieldComparisonResult(
1437 const Message& message1, const Message& message2,
1438 const FieldDescriptor* field, int index1, int index2,
1439 const FieldContext* field_context) {
1440 FieldComparator* comparator = field_comparator_ != NULL ?
1441 field_comparator_ : &default_field_comparator_;
1442 return comparator->Compare(message1, message2, field,
1443 index1, index2, field_context);
1444}
1445
1446// ===========================================================================
1447
1448MessageDifferencer::Reporter::Reporter() { }
1449MessageDifferencer::Reporter::~Reporter() {}
1450
1451// ===========================================================================
1452
1453MessageDifferencer::MapKeyComparator::MapKeyComparator() {}
1454MessageDifferencer::MapKeyComparator::~MapKeyComparator() {}
1455
1456// ===========================================================================
1457
1458MessageDifferencer::IgnoreCriteria::IgnoreCriteria() {}
1459MessageDifferencer::IgnoreCriteria::~IgnoreCriteria() {}
1460
1461// ===========================================================================
1462
1463// Note that the printer's delimiter is not used, because if we are given a
1464// printer, we don't know its delimiter.
1465MessageDifferencer::StreamReporter::StreamReporter(
1466 io::ZeroCopyOutputStream* output) : printer_(new io::Printer(output, '$')),
1467 delete_printer_(true),
1468 report_modified_aggregates_(false) { }
1469
1470MessageDifferencer::StreamReporter::StreamReporter(
1471 io::Printer* printer) : printer_(printer),
1472 delete_printer_(false),
1473 report_modified_aggregates_(false) { }
1474
1475MessageDifferencer::StreamReporter::~StreamReporter() {
1476 if (delete_printer_) delete printer_;
1477}
1478
1479void MessageDifferencer::StreamReporter::PrintPath(
1480 const vector<SpecificField>& field_path, bool left_side) {
1481 for (int i = 0; i < field_path.size(); ++i) {
1482 if (i > 0) {
1483 printer_->Print(".");
1484 }
1485
1486 SpecificField specific_field = field_path[i];
1487
1488 if (specific_field.field != NULL) {
1489 if (specific_field.field->is_extension()) {
1490 printer_->Print("($name$)", "name",
1491 specific_field.field->full_name());
1492 } else {
1493 printer_->PrintRaw(specific_field.field->name());
1494 }
1495 } else {
1496 printer_->PrintRaw(SimpleItoa(specific_field.unknown_field_number));
1497 }
1498 if (left_side && specific_field.index >= 0) {
1499 printer_->Print("[$name$]", "name", SimpleItoa(specific_field.index));
1500 }
1501 if (!left_side && specific_field.new_index >= 0) {
1502 printer_->Print("[$name$]", "name", SimpleItoa(specific_field.new_index));
1503 }
1504 }
1505}
1506
1507void MessageDifferencer::
1508StreamReporter::PrintValue(const Message& message,
1509 const vector<SpecificField>& field_path,
1510 bool left_side) {
1511 const SpecificField& specific_field = field_path.back();
1512 const FieldDescriptor* field = specific_field.field;
1513 if (field != NULL) {
1514 string output;
1515 int index = left_side ? specific_field.index : specific_field.new_index;
1516 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
1517 const Reflection* reflection = message.GetReflection();
1518 const Message& field_message = field->is_repeated() ?
1519 reflection->GetRepeatedMessage(message, field, index) :
1520 reflection->GetMessage(message, field);
1521 output = field_message.ShortDebugString();
1522 if (output.empty()) {
1523 printer_->Print("{ }");
1524 } else {
1525 printer_->Print("{ $name$ }", "name", output);
1526 }
1527 } else {
1528 TextFormat::PrintFieldValueToString(message, field, index, &output);
1529 printer_->PrintRaw(output);
1530 }
1531 } else {
1532 const UnknownFieldSet* unknown_fields =
1533 (left_side ?
1534 specific_field.unknown_field_set1 :
1535 specific_field.unknown_field_set2);
1536 const UnknownField* unknown_field = &unknown_fields->field(
1537 left_side ?
1538 specific_field.unknown_field_index1 :
1539 specific_field.unknown_field_index2);
1540 PrintUnknownFieldValue(unknown_field);
1541 }
1542}
1543
1544void MessageDifferencer::
1545StreamReporter::PrintUnknownFieldValue(const UnknownField* unknown_field) {
1546 GOOGLE_CHECK(unknown_field != NULL) << " Cannot print NULL unknown_field.";
1547
1548 string output;
1549 switch (unknown_field->type()) {
1550 case UnknownField::TYPE_VARINT:
1551 output = SimpleItoa(unknown_field->varint());
1552 break;
1553 case UnknownField::TYPE_FIXED32:
1554 output = StrCat("0x", strings::Hex(unknown_field->fixed32(),
1555 strings::ZERO_PAD_8));
1556 break;
1557 case UnknownField::TYPE_FIXED64:
1558 output = StrCat("0x", strings::Hex(unknown_field->fixed64(),
1559 strings::ZERO_PAD_16));
1560 break;
1561 case UnknownField::TYPE_LENGTH_DELIMITED:
1562 output = StringPrintf("\"%s\"",
1563 CEscape(unknown_field->length_delimited()).c_str());
1564 break;
1565 case UnknownField::TYPE_GROUP:
1566 // TODO(kenton): Print the contents of the group like we do for
1567 // messages. Requires an equivalent of ShortDebugString() for
1568 // UnknownFieldSet.
1569 output = "{ ... }";
1570 break;
1571 }
1572 printer_->PrintRaw(output);
1573}
1574
1575void MessageDifferencer::StreamReporter::Print(const string& str) {
1576 printer_->Print(str.c_str());
1577}
1578
1579void MessageDifferencer::StreamReporter::ReportAdded(
1580 const Message& message1,
1581 const Message& message2,
1582 const vector<SpecificField>& field_path) {
1583 printer_->Print("added: ");
1584 PrintPath(field_path, false);
1585 printer_->Print(": ");
1586 PrintValue(message2, field_path, false);
1587 printer_->Print("\n"); // Print for newlines.
1588}
1589
1590void MessageDifferencer::StreamReporter::ReportDeleted(
1591 const Message& message1,
1592 const Message& message2,
1593 const vector<SpecificField>& field_path) {
1594 printer_->Print("deleted: ");
1595 PrintPath(field_path, true);
1596 printer_->Print(": ");
1597 PrintValue(message1, field_path, true);
1598 printer_->Print("\n"); // Print for newlines
1599}
1600
1601void MessageDifferencer::StreamReporter::ReportModified(
1602 const Message& message1,
1603 const Message& message2,
1604 const vector<SpecificField>& field_path) {
1605 if (!report_modified_aggregates_ && field_path.back().field == NULL) {
1606 if (field_path.back().unknown_field_type == UnknownField::TYPE_GROUP) {
1607 // Any changes to the subfields have already been printed.
1608 return;
1609 }
1610 } else if (!report_modified_aggregates_) {
1611 if (field_path.back().field->cpp_type() ==
1612 FieldDescriptor::CPPTYPE_MESSAGE) {
1613 // Any changes to the subfields have already been printed.
1614 return;
1615 }
1616 }
1617
1618 printer_->Print("modified: ");
1619 PrintPath(field_path, true);
1620 if (CheckPathChanged(field_path)) {
1621 printer_->Print(" -> ");
1622 PrintPath(field_path, false);
1623 }
1624 printer_->Print(": ");
1625 PrintValue(message1, field_path, true);
1626 printer_->Print(" -> ");
1627 PrintValue(message2, field_path, false);
1628 printer_->Print("\n"); // Print for newlines.
1629}
1630
1631void MessageDifferencer::StreamReporter::ReportMoved(
1632 const Message& message1,
1633 const Message& message2,
1634 const vector<SpecificField>& field_path) {
1635 printer_->Print("moved: ");
1636 PrintPath(field_path, true);
1637 printer_->Print(" -> ");
1638 PrintPath(field_path, false);
1639 printer_->Print(" : ");
1640 PrintValue(message1, field_path, true);
1641 printer_->Print("\n"); // Print for newlines.
1642}
1643
1644void MessageDifferencer::StreamReporter::ReportMatched(
1645 const Message& message1,
1646 const Message& message2,
1647 const vector<SpecificField>& field_path) {
1648 printer_->Print("matched: ");
1649 PrintPath(field_path, true);
1650 if (CheckPathChanged(field_path)) {
1651 printer_->Print(" -> ");
1652 PrintPath(field_path, false);
1653 }
1654 printer_->Print(" : ");
1655 PrintValue(message1, field_path, true);
1656 printer_->Print("\n"); // Print for newlines.
1657}
1658
1659void MessageDifferencer::StreamReporter::ReportIgnored(
1660 const Message& message1,
1661 const Message& message2,
1662 const vector<SpecificField>& field_path) {
1663 printer_->Print("ignored: ");
1664 PrintPath(field_path, true);
1665 if (CheckPathChanged(field_path)) {
1666 printer_->Print(" -> ");
1667 PrintPath(field_path, false);
1668 }
1669 printer_->Print("\n"); // Print for newlines.
1670}
1671
1672void MessageDifferencer::StreamReporter::ReportUnknownFieldIgnored(
1673 const Message& message1, const Message& message2,
1674 const vector<SpecificField>& field_path) {
1675 printer_->Print("ignored: ");
1676 PrintPath(field_path, true);
1677 if (CheckPathChanged(field_path)) {
1678 printer_->Print(" -> ");
1679 PrintPath(field_path, false);
1680 }
1681 printer_->Print("\n"); // Print for newlines.
1682}
1683
1684} // namespace util
1685} // namespace protobuf
1686} // namespace google