OLD | NEW |
1 // Protocol Buffers - Google's data interchange format | 1 // Protocol Buffers - Google's data interchange format |
2 // Copyright 2008 Google Inc. All rights reserved. | 2 // Copyright 2008 Google Inc. All rights reserved. |
3 // https://developers.google.com/protocol-buffers/ | 3 // https://developers.google.com/protocol-buffers/ |
4 // | 4 // |
5 // Redistribution and use in source and binary forms, with or without | 5 // Redistribution and use in source and binary forms, with or without |
6 // modification, are permitted provided that the following conditions are | 6 // modification, are permitted provided that the following conditions are |
7 // met: | 7 // met: |
8 // | 8 // |
9 // * Redistributions of source code must retain the above copyright | 9 // * Redistributions of source code must retain the above copyright |
10 // notice, this list of conditions and the following disclaimer. | 10 // notice, this list of conditions and the following disclaimer. |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
66 // When comparing a repeated field as map, MultipleFieldMapKeyComparator can | 66 // When comparing a repeated field as map, MultipleFieldMapKeyComparator can |
67 // be used to specify multiple fields as key for key comparison. | 67 // be used to specify multiple fields as key for key comparison. |
68 // Two elements of a repeated field will be regarded as having the same key | 68 // Two elements of a repeated field will be regarded as having the same key |
69 // iff they have the same value for every specified key field. | 69 // iff they have the same value for every specified key field. |
70 // Note that you can also specify only one field as key. | 70 // Note that you can also specify only one field as key. |
71 class MessageDifferencer::MultipleFieldsMapKeyComparator | 71 class MessageDifferencer::MultipleFieldsMapKeyComparator |
72 : public MessageDifferencer::MapKeyComparator { | 72 : public MessageDifferencer::MapKeyComparator { |
73 public: | 73 public: |
74 MultipleFieldsMapKeyComparator( | 74 MultipleFieldsMapKeyComparator( |
75 MessageDifferencer* message_differencer, | 75 MessageDifferencer* message_differencer, |
76 const std::vector<std::vector<const FieldDescriptor*> >& key_field_paths) | 76 const vector<vector<const FieldDescriptor*> >& key_field_paths) |
77 : message_differencer_(message_differencer), | 77 : message_differencer_(message_differencer), |
78 key_field_paths_(key_field_paths) { | 78 key_field_paths_(key_field_paths) { |
79 GOOGLE_CHECK(!key_field_paths_.empty()); | 79 GOOGLE_CHECK(!key_field_paths_.empty()); |
80 for (int i = 0; i < key_field_paths_.size(); ++i) { | 80 for (int i = 0; i < key_field_paths_.size(); ++i) { |
81 GOOGLE_CHECK(!key_field_paths_[i].empty()); | 81 GOOGLE_CHECK(!key_field_paths_[i].empty()); |
82 } | 82 } |
83 } | 83 } |
84 MultipleFieldsMapKeyComparator( | 84 MultipleFieldsMapKeyComparator( |
85 MessageDifferencer* message_differencer, | 85 MessageDifferencer* message_differencer, |
86 const FieldDescriptor* key) | 86 const FieldDescriptor* key) |
87 : message_differencer_(message_differencer) { | 87 : message_differencer_(message_differencer) { |
88 std::vector<const FieldDescriptor*> key_field_path; | 88 vector<const FieldDescriptor*> key_field_path; |
89 key_field_path.push_back(key); | 89 key_field_path.push_back(key); |
90 key_field_paths_.push_back(key_field_path); | 90 key_field_paths_.push_back(key_field_path); |
91 } | 91 } |
92 virtual bool IsMatch( | 92 virtual bool IsMatch( |
93 const Message& message1, | 93 const Message& message1, |
94 const Message& message2, | 94 const Message& message2, |
95 const std::vector<SpecificField>& parent_fields) const { | 95 const vector<SpecificField>& parent_fields) const { |
96 for (int i = 0; i < key_field_paths_.size(); ++i) { | 96 for (int i = 0; i < key_field_paths_.size(); ++i) { |
97 if (!IsMatchInternal(message1, message2, parent_fields, | 97 if (!IsMatchInternal(message1, message2, parent_fields, |
98 key_field_paths_[i], 0)) { | 98 key_field_paths_[i], 0)) { |
99 return false; | 99 return false; |
100 } | 100 } |
101 } | 101 } |
102 return true; | 102 return true; |
103 } | 103 } |
104 private: | 104 private: |
105 bool IsMatchInternal( | 105 bool IsMatchInternal( |
106 const Message& message1, | 106 const Message& message1, |
107 const Message& message2, | 107 const Message& message2, |
108 const std::vector<SpecificField>& parent_fields, | 108 const vector<SpecificField>& parent_fields, |
109 const std::vector<const FieldDescriptor*>& key_field_path, | 109 const vector<const FieldDescriptor*>& key_field_path, |
110 int path_index) const { | 110 int path_index) const { |
111 const FieldDescriptor* field = key_field_path[path_index]; | 111 const FieldDescriptor* field = key_field_path[path_index]; |
112 std::vector<SpecificField> current_parent_fields(parent_fields); | 112 vector<SpecificField> current_parent_fields(parent_fields); |
113 if (path_index == key_field_path.size() - 1) { | 113 if (path_index == key_field_path.size() - 1) { |
114 if (field->is_repeated()) { | 114 if (field->is_repeated()) { |
115 if (!message_differencer_->CompareRepeatedField( | 115 if (!message_differencer_->CompareRepeatedField( |
116 message1, message2, field, ¤t_parent_fields)) { | 116 message1, message2, field, ¤t_parent_fields)) { |
117 return false; | 117 return false; |
118 } | 118 } |
119 } else { | 119 } else { |
120 if (!message_differencer_->CompareFieldValueUsingParentFields( | 120 if (!message_differencer_->CompareFieldValueUsingParentFields( |
121 message1, message2, field, -1, -1, ¤t_parent_fields)) { | 121 message1, message2, field, -1, -1, ¤t_parent_fields)) { |
122 return false; | 122 return false; |
(...skipping 16 matching lines...) Expand all Loading... |
139 current_parent_fields.push_back(specific_field); | 139 current_parent_fields.push_back(specific_field); |
140 return IsMatchInternal( | 140 return IsMatchInternal( |
141 reflection1->GetMessage(message1, field), | 141 reflection1->GetMessage(message1, field), |
142 reflection2->GetMessage(message2, field), | 142 reflection2->GetMessage(message2, field), |
143 current_parent_fields, | 143 current_parent_fields, |
144 key_field_path, | 144 key_field_path, |
145 path_index + 1); | 145 path_index + 1); |
146 } | 146 } |
147 } | 147 } |
148 MessageDifferencer* message_differencer_; | 148 MessageDifferencer* message_differencer_; |
149 std::vector<std::vector<const FieldDescriptor*> > key_field_paths_; | 149 vector<vector<const FieldDescriptor*> > key_field_paths_; |
150 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MultipleFieldsMapKeyComparator); | 150 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MultipleFieldsMapKeyComparator); |
151 }; | 151 }; |
152 | 152 |
153 bool MessageDifferencer::Equals(const Message& message1, | 153 bool MessageDifferencer::Equals(const Message& message1, |
154 const Message& message2) { | 154 const Message& message2) { |
155 MessageDifferencer differencer; | 155 MessageDifferencer differencer; |
156 | 156 |
157 return differencer.Compare(message1, message2); | 157 return differencer.Compare(message1, message2); |
158 } | 158 } |
159 | 159 |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
276 << "Cannot treat this repeated field as both Map and List for " | 276 << "Cannot treat this repeated field as both Map and List for " |
277 << "comparison."; | 277 << "comparison."; |
278 MapKeyComparator* key_comparator = | 278 MapKeyComparator* key_comparator = |
279 new MultipleFieldsMapKeyComparator(this, key); | 279 new MultipleFieldsMapKeyComparator(this, key); |
280 owned_key_comparators_.push_back(key_comparator); | 280 owned_key_comparators_.push_back(key_comparator); |
281 map_field_key_comparator_[field] = key_comparator; | 281 map_field_key_comparator_[field] = key_comparator; |
282 } | 282 } |
283 | 283 |
284 void MessageDifferencer::TreatAsMapWithMultipleFieldsAsKey( | 284 void MessageDifferencer::TreatAsMapWithMultipleFieldsAsKey( |
285 const FieldDescriptor* field, | 285 const FieldDescriptor* field, |
286 const std::vector<const FieldDescriptor*>& key_fields) { | 286 const vector<const FieldDescriptor*>& key_fields) { |
287 std::vector<std::vector<const FieldDescriptor*> > key_field_paths; | 287 vector<vector<const FieldDescriptor*> > key_field_paths; |
288 for (int i = 0; i < key_fields.size(); ++i) { | 288 for (int i = 0; i < key_fields.size(); ++i) { |
289 std::vector<const FieldDescriptor*> key_field_path; | 289 vector<const FieldDescriptor*> key_field_path; |
290 key_field_path.push_back(key_fields[i]); | 290 key_field_path.push_back(key_fields[i]); |
291 key_field_paths.push_back(key_field_path); | 291 key_field_paths.push_back(key_field_path); |
292 } | 292 } |
293 TreatAsMapWithMultipleFieldPathsAsKey(field, key_field_paths); | 293 TreatAsMapWithMultipleFieldPathsAsKey(field, key_field_paths); |
294 } | 294 } |
295 | 295 |
296 void MessageDifferencer::TreatAsMapWithMultipleFieldPathsAsKey( | 296 void MessageDifferencer::TreatAsMapWithMultipleFieldPathsAsKey( |
297 const FieldDescriptor* field, | 297 const FieldDescriptor* field, |
298 const std::vector<std::vector<const FieldDescriptor*> >& key_field_paths) { | 298 const vector<vector<const FieldDescriptor*> >& key_field_paths) { |
299 GOOGLE_CHECK(field->is_repeated()) << "Field must be repeated: " | 299 GOOGLE_CHECK(field->is_repeated()) << "Field must be repeated: " |
300 << field->full_name(); | 300 << field->full_name(); |
301 GOOGLE_CHECK_EQ(FieldDescriptor::CPPTYPE_MESSAGE, field->cpp_type()) | 301 GOOGLE_CHECK_EQ(FieldDescriptor::CPPTYPE_MESSAGE, field->cpp_type()) |
302 << "Field has to be message type. Field name is: " | 302 << "Field has to be message type. Field name is: " |
303 << field->full_name(); | 303 << field->full_name(); |
304 for (int i = 0; i < key_field_paths.size(); ++i) { | 304 for (int i = 0; i < key_field_paths.size(); ++i) { |
305 const std::vector<const FieldDescriptor*>& key_field_path = | 305 const vector<const FieldDescriptor*>& key_field_path = key_field_paths[i]; |
306 key_field_paths[i]; | |
307 for (int j = 0; j < key_field_path.size(); ++j) { | 306 for (int j = 0; j < key_field_path.size(); ++j) { |
308 const FieldDescriptor* parent_field = | 307 const FieldDescriptor* parent_field = |
309 j == 0 ? field : key_field_path[j - 1]; | 308 j == 0 ? field : key_field_path[j - 1]; |
310 const FieldDescriptor* child_field = key_field_path[j]; | 309 const FieldDescriptor* child_field = key_field_path[j]; |
311 GOOGLE_CHECK(child_field->containing_type() == parent_field->message_type(
)) | 310 GOOGLE_CHECK(child_field->containing_type() == parent_field->message_type(
)) |
312 << child_field->full_name() | 311 << child_field->full_name() |
313 << " must be a direct subfield within the field: " | 312 << " must be a direct subfield within the field: " |
314 << parent_field->full_name(); | 313 << parent_field->full_name(); |
315 if (j != 0) { | 314 if (j != 0) { |
316 GOOGLE_CHECK_EQ(FieldDescriptor::CPPTYPE_MESSAGE, parent_field->cpp_type
()) | 315 GOOGLE_CHECK_EQ(FieldDescriptor::CPPTYPE_MESSAGE, parent_field->cpp_type
()) |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
384 if (field2 == NULL) { | 383 if (field2 == NULL) { |
385 return true; | 384 return true; |
386 } | 385 } |
387 | 386 |
388 // Always order fields by their tag number | 387 // Always order fields by their tag number |
389 return (field1->number() < field2->number()); | 388 return (field1->number() < field2->number()); |
390 } | 389 } |
391 | 390 |
392 bool MessageDifferencer::Compare(const Message& message1, | 391 bool MessageDifferencer::Compare(const Message& message1, |
393 const Message& message2) { | 392 const Message& message2) { |
394 std::vector<SpecificField> parent_fields; | 393 vector<SpecificField> parent_fields; |
395 | 394 |
396 bool result = false; | 395 bool result = false; |
397 | 396 |
398 // Setup the internal reporter if need be. | 397 // Setup the internal reporter if need be. |
399 if (output_string_) { | 398 if (output_string_) { |
400 io::StringOutputStream output_stream(output_string_); | 399 io::StringOutputStream output_stream(output_string_); |
401 StreamReporter reporter(&output_stream); | 400 StreamReporter reporter(&output_stream); |
402 reporter_ = &reporter; | 401 reporter_ = &reporter; |
403 result = Compare(message1, message2, &parent_fields); | 402 result = Compare(message1, message2, &parent_fields); |
404 reporter_ = NULL; | 403 reporter_ = NULL; |
405 } else { | 404 } else { |
406 result = Compare(message1, message2, &parent_fields); | 405 result = Compare(message1, message2, &parent_fields); |
407 } | 406 } |
408 | 407 |
409 return result; | 408 return result; |
410 } | 409 } |
411 | 410 |
412 bool MessageDifferencer::CompareWithFields( | 411 bool MessageDifferencer::CompareWithFields( |
413 const Message& message1, | 412 const Message& message1, |
414 const Message& message2, | 413 const Message& message2, |
415 const std::vector<const FieldDescriptor*>& message1_fields_arg, | 414 const vector<const FieldDescriptor*>& message1_fields_arg, |
416 const std::vector<const FieldDescriptor*>& message2_fields_arg) { | 415 const vector<const FieldDescriptor*>& message2_fields_arg) { |
417 if (message1.GetDescriptor() != message2.GetDescriptor()) { | 416 if (message1.GetDescriptor() != message2.GetDescriptor()) { |
418 GOOGLE_LOG(DFATAL) << "Comparison between two messages with different " | 417 GOOGLE_LOG(DFATAL) << "Comparison between two messages with different " |
419 << "descriptors."; | 418 << "descriptors."; |
420 return false; | 419 return false; |
421 } | 420 } |
422 | 421 |
423 std::vector<SpecificField> parent_fields; | 422 vector<SpecificField> parent_fields; |
424 | 423 |
425 bool result = false; | 424 bool result = false; |
426 | 425 |
427 std::vector<const FieldDescriptor*> message1_fields(message1_fields_arg); | 426 vector<const FieldDescriptor*> message1_fields(message1_fields_arg); |
428 std::vector<const FieldDescriptor*> message2_fields(message2_fields_arg); | 427 vector<const FieldDescriptor*> message2_fields(message2_fields_arg); |
429 | 428 |
430 std::sort(message1_fields.begin(), message1_fields.end(), FieldBefore); | 429 std::sort(message1_fields.begin(), message1_fields.end(), FieldBefore); |
431 std::sort(message2_fields.begin(), message2_fields.end(), FieldBefore); | 430 std::sort(message2_fields.begin(), message2_fields.end(), FieldBefore); |
432 // Append NULL sentinel values. | 431 // Append NULL sentinel values. |
433 message1_fields.push_back(NULL); | 432 message1_fields.push_back(NULL); |
434 message2_fields.push_back(NULL); | 433 message2_fields.push_back(NULL); |
435 | 434 |
436 // Setup the internal reporter if need be. | 435 // Setup the internal reporter if need be. |
437 if (output_string_) { | 436 if (output_string_) { |
438 io::StringOutputStream output_stream(output_string_); | 437 io::StringOutputStream output_stream(output_string_); |
439 StreamReporter reporter(&output_stream); | 438 StreamReporter reporter(&output_stream); |
440 reporter_ = &reporter; | 439 reporter_ = &reporter; |
441 result = CompareRequestedFieldsUsingSettings( | 440 result = CompareRequestedFieldsUsingSettings( |
442 message1, message2, message1_fields, message2_fields, &parent_fields); | 441 message1, message2, message1_fields, message2_fields, &parent_fields); |
443 reporter_ = NULL; | 442 reporter_ = NULL; |
444 } else { | 443 } else { |
445 result = CompareRequestedFieldsUsingSettings( | 444 result = CompareRequestedFieldsUsingSettings( |
446 message1, message2, message1_fields, message2_fields, &parent_fields); | 445 message1, message2, message1_fields, message2_fields, &parent_fields); |
447 } | 446 } |
448 | 447 |
449 return result; | 448 return result; |
450 } | 449 } |
451 | 450 |
452 bool MessageDifferencer::Compare( | 451 bool MessageDifferencer::Compare( |
453 const Message& message1, | 452 const Message& message1, |
454 const Message& message2, | 453 const Message& message2, |
455 std::vector<SpecificField>* parent_fields) { | 454 vector<SpecificField>* parent_fields) { |
456 const Descriptor* descriptor1 = message1.GetDescriptor(); | 455 const Descriptor* descriptor1 = message1.GetDescriptor(); |
457 const Descriptor* descriptor2 = message2.GetDescriptor(); | 456 const Descriptor* descriptor2 = message2.GetDescriptor(); |
458 if (descriptor1 != descriptor2) { | 457 if (descriptor1 != descriptor2) { |
459 GOOGLE_LOG(DFATAL) << "Comparison between two messages with different " | 458 GOOGLE_LOG(DFATAL) << "Comparison between two messages with different " |
460 << "descriptors. " | 459 << "descriptors. " |
461 << descriptor1->full_name() << " vs " | 460 << descriptor1->full_name() << " vs " |
462 << descriptor2->full_name(); | 461 << descriptor2->full_name(); |
463 return false; | 462 return false; |
464 } | 463 } |
465 // Expand google.protobuf.Any payload if possible. | 464 // Expand google.protobuf.Any payload if possible. |
466 if (descriptor1->full_name() == internal::kAnyFullTypeName) { | 465 if (descriptor1->full_name() == internal::kAnyFullTypeName) { |
467 google::protobuf::scoped_ptr<Message> data1; | 466 google::protobuf::scoped_ptr<Message> data1; |
468 google::protobuf::scoped_ptr<Message> data2; | 467 google::protobuf::scoped_ptr<Message> data2; |
469 if (UnpackAny(message1, &data1) && UnpackAny(message2, &data2)) { | 468 if (UnpackAny(message1, &data1) && UnpackAny(message2, &data2)) { |
470 return Compare(*data1, *data2, parent_fields); | 469 return Compare(*data1, *data2, parent_fields); |
471 } | 470 } |
472 } | 471 } |
473 const Reflection* reflection1 = message1.GetReflection(); | 472 const Reflection* reflection1 = message1.GetReflection(); |
474 const Reflection* reflection2 = message2.GetReflection(); | 473 const Reflection* reflection2 = message2.GetReflection(); |
475 | 474 |
476 // Retrieve all the set fields, including extensions. | 475 // Retrieve all the set fields, including extensions. |
477 std::vector<const FieldDescriptor*> message1_fields; | 476 vector<const FieldDescriptor*> message1_fields; |
478 message1_fields.reserve(1 + message1.GetDescriptor()->field_count()); | 477 vector<const FieldDescriptor*> message2_fields; |
479 | |
480 std::vector<const FieldDescriptor*> message2_fields; | |
481 message2_fields.reserve(1 + message2.GetDescriptor()->field_count()); | |
482 | 478 |
483 reflection1->ListFields(message1, &message1_fields); | 479 reflection1->ListFields(message1, &message1_fields); |
484 reflection2->ListFields(message2, &message2_fields); | 480 reflection2->ListFields(message2, &message2_fields); |
485 | 481 |
486 // Add sentinel values to deal with the | 482 // Add sentinel values to deal with the |
487 // case where the number of the fields in | 483 // case where the number of the fields in |
488 // each list are different. | 484 // each list are different. |
489 message1_fields.push_back(NULL); | 485 message1_fields.push_back(NULL); |
490 message2_fields.push_back(NULL); | 486 message2_fields.push_back(NULL); |
491 | 487 |
(...skipping 16 matching lines...) Expand all Loading... |
508 | 504 |
509 return CompareRequestedFieldsUsingSettings( | 505 return CompareRequestedFieldsUsingSettings( |
510 message1, message2, | 506 message1, message2, |
511 message1_fields, message2_fields, | 507 message1_fields, message2_fields, |
512 parent_fields) && unknown_compare_result; | 508 parent_fields) && unknown_compare_result; |
513 } | 509 } |
514 | 510 |
515 bool MessageDifferencer::CompareRequestedFieldsUsingSettings( | 511 bool MessageDifferencer::CompareRequestedFieldsUsingSettings( |
516 const Message& message1, | 512 const Message& message1, |
517 const Message& message2, | 513 const Message& message2, |
518 const std::vector<const FieldDescriptor*>& message1_fields, | 514 const vector<const FieldDescriptor*>& message1_fields, |
519 const std::vector<const FieldDescriptor*>& message2_fields, | 515 const vector<const FieldDescriptor*>& message2_fields, |
520 std::vector<SpecificField>* parent_fields) { | 516 vector<SpecificField>* parent_fields) { |
521 if (scope_ == FULL) { | 517 if (scope_ == FULL) { |
522 if (message_field_comparison_ == EQUIVALENT) { | 518 if (message_field_comparison_ == EQUIVALENT) { |
523 // We need to merge the field lists of both messages (i.e. | 519 // We need to merge the field lists of both messages (i.e. |
524 // we are merely checking for a difference in field values, | 520 // we are merely checking for a difference in field values, |
525 // rather than the addition or deletion of fields). | 521 // rather than the addition or deletion of fields). |
526 std::vector<const FieldDescriptor*> fields_union; | 522 vector<const FieldDescriptor*> fields_union; |
527 CombineFields(message1_fields, FULL, message2_fields, FULL, | 523 CombineFields(message1_fields, FULL, message2_fields, FULL, |
528 &fields_union); | 524 &fields_union); |
529 return CompareWithFieldsInternal(message1, message2, fields_union, | 525 return CompareWithFieldsInternal(message1, message2, fields_union, |
530 fields_union, parent_fields); | 526 fields_union, parent_fields); |
531 } else { | 527 } else { |
532 // Simple equality comparison, use the unaltered field lists. | 528 // Simple equality comparison, use the unaltered field lists. |
533 return CompareWithFieldsInternal(message1, message2, message1_fields, | 529 return CompareWithFieldsInternal(message1, message2, message1_fields, |
534 message2_fields, parent_fields); | 530 message2_fields, parent_fields); |
535 } | 531 } |
536 } else { | 532 } else { |
537 if (message_field_comparison_ == EQUIVALENT) { | 533 if (message_field_comparison_ == EQUIVALENT) { |
538 // We use the list of fields for message1 for both messages when | 534 // We use the list of fields for message1 for both messages when |
539 // comparing. This way, extra fields in message2 are ignored, | 535 // comparing. This way, extra fields in message2 are ignored, |
540 // and missing fields in message2 use their default value. | 536 // and missing fields in message2 use their default value. |
541 return CompareWithFieldsInternal(message1, message2, message1_fields, | 537 return CompareWithFieldsInternal(message1, message2, message1_fields, |
542 message1_fields, parent_fields); | 538 message1_fields, parent_fields); |
543 } else { | 539 } else { |
544 // We need to consider the full list of fields for message1 | 540 // We need to consider the full list of fields for message1 |
545 // but only the intersection for message2. This way, any fields | 541 // but only the intersection for message2. This way, any fields |
546 // only present in message2 will be ignored, but any fields only | 542 // only present in message2 will be ignored, but any fields only |
547 // present in message1 will be marked as a difference. | 543 // present in message1 will be marked as a difference. |
548 std::vector<const FieldDescriptor*> fields_intersection; | 544 vector<const FieldDescriptor*> fields_intersection; |
549 CombineFields(message1_fields, PARTIAL, message2_fields, PARTIAL, | 545 CombineFields(message1_fields, PARTIAL, message2_fields, PARTIAL, |
550 &fields_intersection); | 546 &fields_intersection); |
551 return CompareWithFieldsInternal(message1, message2, message1_fields, | 547 return CompareWithFieldsInternal(message1, message2, message1_fields, |
552 fields_intersection, parent_fields); | 548 fields_intersection, parent_fields); |
553 } | 549 } |
554 } | 550 } |
555 } | 551 } |
556 | 552 |
557 void MessageDifferencer::CombineFields( | 553 void MessageDifferencer::CombineFields( |
558 const std::vector<const FieldDescriptor*>& fields1, | 554 const vector<const FieldDescriptor*>& fields1, |
559 Scope fields1_scope, | 555 Scope fields1_scope, |
560 const std::vector<const FieldDescriptor*>& fields2, | 556 const vector<const FieldDescriptor*>& fields2, |
561 Scope fields2_scope, | 557 Scope fields2_scope, |
562 std::vector<const FieldDescriptor*>* combined_fields) { | 558 vector<const FieldDescriptor*>* combined_fields) { |
563 | 559 |
564 int index1 = 0; | 560 int index1 = 0; |
565 int index2 = 0; | 561 int index2 = 0; |
566 | 562 |
567 while (index1 < fields1.size() && index2 < fields2.size()) { | 563 while (index1 < fields1.size() && index2 < fields2.size()) { |
568 const FieldDescriptor* field1 = fields1[index1]; | 564 const FieldDescriptor* field1 = fields1[index1]; |
569 const FieldDescriptor* field2 = fields2[index2]; | 565 const FieldDescriptor* field2 = fields2[index2]; |
570 | 566 |
571 if (FieldBefore(field1, field2)) { | 567 if (FieldBefore(field1, field2)) { |
572 if (fields1_scope == FULL) { | 568 if (fields1_scope == FULL) { |
573 combined_fields->push_back(fields1[index1]); | 569 combined_fields->push_back(fields1[index1]); |
574 } | 570 } |
575 ++index1; | 571 ++index1; |
576 } else if (FieldBefore(field2, field1)) { | 572 } else if (FieldBefore(field2, field1)) { |
577 if (fields2_scope == FULL) { | 573 if (fields2_scope == FULL) { |
578 combined_fields->push_back(fields2[index2]); | 574 combined_fields->push_back(fields2[index2]); |
579 } | 575 } |
580 ++index2; | 576 ++index2; |
581 } else { | 577 } else { |
582 combined_fields->push_back(fields1[index1]); | 578 combined_fields->push_back(fields1[index1]); |
583 ++index1; | 579 ++index1; |
584 ++index2; | 580 ++index2; |
585 } | 581 } |
586 } | 582 } |
587 } | 583 } |
588 | 584 |
589 bool MessageDifferencer::CompareWithFieldsInternal( | 585 bool MessageDifferencer::CompareWithFieldsInternal( |
590 const Message& message1, | 586 const Message& message1, |
591 const Message& message2, | 587 const Message& message2, |
592 const std::vector<const FieldDescriptor*>& message1_fields, | 588 const vector<const FieldDescriptor*>& message1_fields, |
593 const std::vector<const FieldDescriptor*>& message2_fields, | 589 const vector<const FieldDescriptor*>& message2_fields, |
594 std::vector<SpecificField>* parent_fields) { | 590 vector<SpecificField>* parent_fields) { |
595 bool isDifferent = false; | 591 bool isDifferent = false; |
596 int field_index1 = 0; | 592 int field_index1 = 0; |
597 int field_index2 = 0; | 593 int field_index2 = 0; |
598 | 594 |
599 const Reflection* reflection1 = message1.GetReflection(); | 595 const Reflection* reflection1 = message1.GetReflection(); |
600 const Reflection* reflection2 = message2.GetReflection(); | 596 const Reflection* reflection2 = message2.GetReflection(); |
601 | 597 |
602 while (true) { | 598 while (true) { |
603 const FieldDescriptor* field1 = message1_fields[field_index1]; | 599 const FieldDescriptor* field1 = message1_fields[field_index1]; |
604 const FieldDescriptor* field2 = message2_fields[field_index2]; | 600 const FieldDescriptor* field2 = message2_fields[field_index2]; |
(...skipping 15 matching lines...) Expand all Loading... |
620 | 616 |
621 parent_fields->push_back(specific_field); | 617 parent_fields->push_back(specific_field); |
622 reporter_->ReportIgnored(message1, message2, *parent_fields); | 618 reporter_->ReportIgnored(message1, message2, *parent_fields); |
623 parent_fields->pop_back(); | 619 parent_fields->pop_back(); |
624 } | 620 } |
625 ++field_index1; | 621 ++field_index1; |
626 continue; | 622 continue; |
627 } | 623 } |
628 | 624 |
629 if (reporter_ != NULL) { | 625 if (reporter_ != NULL) { |
630 assert(field1 != NULL); | |
631 int count = field1->is_repeated() ? | 626 int count = field1->is_repeated() ? |
632 reflection1->FieldSize(message1, field1) : 1; | 627 reflection1->FieldSize(message1, field1) : 1; |
633 | 628 |
634 for (int i = 0; i < count; ++i) { | 629 for (int i = 0; i < count; ++i) { |
635 SpecificField specific_field; | 630 SpecificField specific_field; |
636 specific_field.field = field1; | 631 specific_field.field = field1; |
637 specific_field.index = field1->is_repeated() ? i : -1; | 632 specific_field.index = field1->is_repeated() ? i : -1; |
638 | 633 |
639 parent_fields->push_back(specific_field); | 634 parent_fields->push_back(specific_field); |
640 reporter_->ReportDeleted(message1, message2, *parent_fields); | 635 reporter_->ReportDeleted(message1, message2, *parent_fields); |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
701 reporter_->ReportIgnored(message1, message2, *parent_fields); | 696 reporter_->ReportIgnored(message1, message2, *parent_fields); |
702 parent_fields->pop_back(); | 697 parent_fields->pop_back(); |
703 } | 698 } |
704 | 699 |
705 ++field_index1; | 700 ++field_index1; |
706 ++field_index2; | 701 ++field_index2; |
707 continue; | 702 continue; |
708 } | 703 } |
709 | 704 |
710 bool fieldDifferent = false; | 705 bool fieldDifferent = false; |
711 assert(field1 != NULL); | |
712 if (field1->is_repeated()) { | 706 if (field1->is_repeated()) { |
713 fieldDifferent = !CompareRepeatedField(message1, message2, field1, | 707 fieldDifferent = !CompareRepeatedField(message1, message2, field1, |
714 parent_fields); | 708 parent_fields); |
715 if (fieldDifferent) { | 709 if (fieldDifferent) { |
716 if (reporter_ == NULL) return false; | 710 if (reporter_ == NULL) return false; |
717 isDifferent = true; | 711 isDifferent = true; |
718 } | 712 } |
719 } else { | 713 } else { |
720 fieldDifferent = !CompareFieldValueUsingParentFields( | 714 fieldDifferent = !CompareFieldValueUsingParentFields( |
721 message1, message2, field1, -1, -1, parent_fields); | 715 message1, message2, field1, -1, -1, parent_fields); |
(...skipping 18 matching lines...) Expand all Loading... |
740 } | 734 } |
741 } | 735 } |
742 // Increment the field indicies. | 736 // Increment the field indicies. |
743 ++field_index1; | 737 ++field_index1; |
744 ++field_index2; | 738 ++field_index2; |
745 } | 739 } |
746 | 740 |
747 return !isDifferent; | 741 return !isDifferent; |
748 } | 742 } |
749 | 743 |
750 bool MessageDifferencer::IsMatch( | 744 bool MessageDifferencer::IsMatch(const FieldDescriptor* repeated_field, |
751 const FieldDescriptor* repeated_field, | 745 const MapKeyComparator* key_comparator, |
752 const MapKeyComparator* key_comparator, const Message* message1, | 746 const Message* message1, |
753 const Message* message2, const std::vector<SpecificField>& parent_fields, | 747 const Message* message2, |
754 int index1, int index2) { | 748 const vector<SpecificField>& parent_fields, |
755 std::vector<SpecificField> current_parent_fields(parent_fields); | 749 int index1, int index2) { |
| 750 vector<SpecificField> current_parent_fields(parent_fields); |
756 if (repeated_field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) { | 751 if (repeated_field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) { |
757 return CompareFieldValueUsingParentFields( | 752 return CompareFieldValueUsingParentFields( |
758 *message1, *message2, repeated_field, index1, index2, | 753 *message1, *message2, repeated_field, index1, index2, |
759 ¤t_parent_fields); | 754 ¤t_parent_fields); |
760 } | 755 } |
761 // Back up the Reporter and output_string_. They will be reset in the | 756 // Back up the Reporter and output_string_. They will be reset in the |
762 // following code. | 757 // following code. |
763 Reporter* backup_reporter = reporter_; | 758 Reporter* backup_reporter = reporter_; |
764 string* output_string = output_string_; | 759 string* output_string = output_string_; |
765 reporter_ = NULL; | 760 reporter_ = NULL; |
(...skipping 19 matching lines...) Expand all Loading... |
785 | 780 |
786 reporter_ = backup_reporter; | 781 reporter_ = backup_reporter; |
787 output_string_ = output_string; | 782 output_string_ = output_string; |
788 return match; | 783 return match; |
789 } | 784 } |
790 | 785 |
791 bool MessageDifferencer::CompareRepeatedField( | 786 bool MessageDifferencer::CompareRepeatedField( |
792 const Message& message1, | 787 const Message& message1, |
793 const Message& message2, | 788 const Message& message2, |
794 const FieldDescriptor* repeated_field, | 789 const FieldDescriptor* repeated_field, |
795 std::vector<SpecificField>* parent_fields) { | 790 vector<SpecificField>* parent_fields) { |
796 // the input FieldDescriptor is guaranteed to be repeated field. | 791 // the input FieldDescriptor is guaranteed to be repeated field. |
797 const Reflection* reflection1 = message1.GetReflection(); | 792 const Reflection* reflection1 = message1.GetReflection(); |
798 const Reflection* reflection2 = message2.GetReflection(); | 793 const Reflection* reflection2 = message2.GetReflection(); |
799 const int count1 = reflection1->FieldSize(message1, repeated_field); | 794 const int count1 = reflection1->FieldSize(message1, repeated_field); |
800 const int count2 = reflection2->FieldSize(message2, repeated_field); | 795 const int count2 = reflection2->FieldSize(message2, repeated_field); |
801 const bool treated_as_subset = IsTreatedAsSubset(repeated_field); | 796 const bool treated_as_subset = IsTreatedAsSubset(repeated_field); |
802 | 797 |
803 // If the field is not treated as subset and no detailed reports is needed, | 798 // If the field is not treated as subset and no detailed reports is needed, |
804 // we do a quick check on the number of the elements to avoid unnecessary | 799 // we do a quick check on the number of the elements to avoid unnecessary |
805 // comparison. | 800 // comparison. |
806 if (count1 != count2 && reporter_ == NULL && !treated_as_subset) { | 801 if (count1 != count2 && reporter_ == NULL && !treated_as_subset) { |
807 return false; | 802 return false; |
808 } | 803 } |
809 // A match can never be found if message1 has more items than message2. | 804 // A match can never be found if message1 has more items than message2. |
810 if (count1 > count2 && reporter_ == NULL) { | 805 if (count1 > count2 && reporter_ == NULL) { |
811 return false; | 806 return false; |
812 } | 807 } |
813 | 808 |
814 // These two list are used for store the index of the correspondent | 809 // These two list are used for store the index of the correspondent |
815 // element in peer repeated field. | 810 // element in peer repeated field. |
816 std::vector<int> match_list1; | 811 vector<int> match_list1; |
817 std::vector<int> match_list2; | 812 vector<int> match_list2; |
818 | 813 |
819 // Try to match indices of the repeated fields. Return false if match fails | 814 // Try to match indices of the repeated fields. Return false if match fails |
820 // and there's no detailed report needed. | 815 // and there's no detailed report needed. |
821 if (!MatchRepeatedFieldIndices(message1, message2, repeated_field, | 816 if (!MatchRepeatedFieldIndices(message1, message2, repeated_field, |
822 *parent_fields, &match_list1, &match_list2) && | 817 *parent_fields, &match_list1, &match_list2) && |
823 reporter_ == NULL) { | 818 reporter_ == NULL) { |
824 return false; | 819 return false; |
825 } | 820 } |
826 | 821 |
827 bool fieldDifferent = false; | 822 bool fieldDifferent = false; |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
870 if (reporter_ == NULL) continue; | 865 if (reporter_ == NULL) continue; |
871 specific_field.index = i; | 866 specific_field.index = i; |
872 specific_field.new_index = i; | 867 specific_field.new_index = i; |
873 parent_fields->push_back(specific_field); | 868 parent_fields->push_back(specific_field); |
874 reporter_->ReportAdded(message1, message2, *parent_fields); | 869 reporter_->ReportAdded(message1, message2, *parent_fields); |
875 parent_fields->pop_back(); | 870 parent_fields->pop_back(); |
876 } | 871 } |
877 | 872 |
878 for (int i = 0; i < count1; ++i) { | 873 for (int i = 0; i < count1; ++i) { |
879 if (match_list1[i] != -1) continue; | 874 if (match_list1[i] != -1) continue; |
880 assert(reporter_ != NULL); | |
881 specific_field.index = i; | 875 specific_field.index = i; |
882 parent_fields->push_back(specific_field); | 876 parent_fields->push_back(specific_field); |
883 reporter_->ReportDeleted(message1, message2, *parent_fields); | 877 reporter_->ReportDeleted(message1, message2, *parent_fields); |
884 parent_fields->pop_back(); | 878 parent_fields->pop_back(); |
885 fieldDifferent = true; | 879 fieldDifferent = true; |
886 } | 880 } |
887 return !fieldDifferent; | 881 return !fieldDifferent; |
888 } | 882 } |
889 | 883 |
890 bool MessageDifferencer::CompareFieldValue(const Message& message1, | 884 bool MessageDifferencer::CompareFieldValue(const Message& message1, |
891 const Message& message2, | 885 const Message& message2, |
892 const FieldDescriptor* field, | 886 const FieldDescriptor* field, |
893 int index1, | 887 int index1, |
894 int index2) { | 888 int index2) { |
895 return CompareFieldValueUsingParentFields(message1, message2, field, index1, | 889 return CompareFieldValueUsingParentFields(message1, message2, field, index1, |
896 index2, NULL); | 890 index2, NULL); |
897 } | 891 } |
898 | 892 |
899 bool MessageDifferencer::CompareFieldValueUsingParentFields( | 893 bool MessageDifferencer::CompareFieldValueUsingParentFields( |
900 const Message& message1, const Message& message2, | 894 const Message& message1, const Message& message2, |
901 const FieldDescriptor* field, int index1, int index2, | 895 const FieldDescriptor* field, int index1, int index2, |
902 std::vector<SpecificField>* parent_fields) { | 896 vector<SpecificField>* parent_fields) { |
903 FieldContext field_context(parent_fields); | 897 FieldContext field_context(parent_fields); |
904 FieldComparator::ComparisonResult result = GetFieldComparisonResult( | 898 FieldComparator::ComparisonResult result = GetFieldComparisonResult( |
905 message1, message2, field, index1, index2, &field_context); | 899 message1, message2, field, index1, index2, &field_context); |
906 | 900 |
907 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && | 901 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && |
908 result == FieldComparator::RECURSE) { | 902 result == FieldComparator::RECURSE) { |
909 // Get the nested messages and compare them using one of the Compare | 903 // Get the nested messages and compare them using one of the Compare |
910 // methods. | 904 // methods. |
911 const Reflection* reflection1 = message1.GetReflection(); | 905 const Reflection* reflection1 = message1.GetReflection(); |
912 const Reflection* reflection2 = message2.GetReflection(); | 906 const Reflection* reflection2 = message2.GetReflection(); |
(...skipping 18 matching lines...) Expand all Loading... |
931 } else { | 925 } else { |
932 // Recreates parent_fields as if m1 and m2 had no parents. | 926 // Recreates parent_fields as if m1 and m2 had no parents. |
933 return Compare(m1, m2); | 927 return Compare(m1, m2); |
934 } | 928 } |
935 } else { | 929 } else { |
936 return (result == FieldComparator::SAME); | 930 return (result == FieldComparator::SAME); |
937 } | 931 } |
938 } | 932 } |
939 | 933 |
940 bool MessageDifferencer::CheckPathChanged( | 934 bool MessageDifferencer::CheckPathChanged( |
941 const std::vector<SpecificField>& field_path) { | 935 const vector<SpecificField>& field_path) { |
942 for (int i = 0; i < field_path.size(); ++i) { | 936 for (int i = 0; i < field_path.size(); ++i) { |
943 if (field_path[i].index != field_path[i].new_index) return true; | 937 if (field_path[i].index != field_path[i].new_index) return true; |
944 } | 938 } |
945 return false; | 939 return false; |
946 } | 940 } |
947 | 941 |
948 bool MessageDifferencer::IsTreatedAsSet(const FieldDescriptor* field) { | 942 bool MessageDifferencer::IsTreatedAsSet(const FieldDescriptor* field) { |
949 if (!field->is_repeated()) return false; | 943 if (!field->is_repeated()) return false; |
950 if (field->is_map()) return true; | 944 if (field->is_map()) return true; |
951 if (repeated_field_comparison_ == AS_SET) | 945 if (repeated_field_comparison_ == AS_SET) |
952 return list_fields_.find(field) == list_fields_.end(); | 946 return list_fields_.find(field) == list_fields_.end(); |
953 return (set_fields_.find(field) != set_fields_.end()); | 947 return (set_fields_.find(field) != set_fields_.end()); |
954 } | 948 } |
955 | 949 |
956 bool MessageDifferencer::IsTreatedAsSubset(const FieldDescriptor* field) { | 950 bool MessageDifferencer::IsTreatedAsSubset(const FieldDescriptor* field) { |
957 return scope_ == PARTIAL && | 951 return scope_ == PARTIAL && |
958 (IsTreatedAsSet(field) || GetMapKeyComparator(field) != NULL); | 952 (IsTreatedAsSet(field) || GetMapKeyComparator(field) != NULL); |
959 } | 953 } |
960 | 954 |
961 bool MessageDifferencer::IsIgnored( | 955 bool MessageDifferencer::IsIgnored( |
962 const Message& message1, | 956 const Message& message1, |
963 const Message& message2, | 957 const Message& message2, |
964 const FieldDescriptor* field, | 958 const FieldDescriptor* field, |
965 const std::vector<SpecificField>& parent_fields) { | 959 const vector<SpecificField>& parent_fields) { |
966 if (ignored_fields_.find(field) != ignored_fields_.end()) { | 960 if (ignored_fields_.find(field) != ignored_fields_.end()) { |
967 return true; | 961 return true; |
968 } | 962 } |
969 for (int i = 0; i < ignore_criteria_.size(); ++i) { | 963 for (int i = 0; i < ignore_criteria_.size(); ++i) { |
970 if (ignore_criteria_[i]->IsIgnored(message1, message2, field, | 964 if (ignore_criteria_[i]->IsIgnored(message1, message2, field, |
971 parent_fields)) { | 965 parent_fields)) { |
972 return true; | 966 return true; |
973 } | 967 } |
974 } | 968 } |
975 return false; | 969 return false; |
976 } | 970 } |
977 | 971 |
978 bool MessageDifferencer::IsUnknownFieldIgnored( | 972 bool MessageDifferencer::IsUnknownFieldIgnored( |
979 const Message& message1, const Message& message2, | 973 const Message& message1, const Message& message2, |
980 const SpecificField& field, | 974 const SpecificField& field, const vector<SpecificField>& parent_fields) { |
981 const std::vector<SpecificField>& parent_fields) { | |
982 for (int i = 0; i < ignore_criteria_.size(); ++i) { | 975 for (int i = 0; i < ignore_criteria_.size(); ++i) { |
983 if (ignore_criteria_[i]->IsUnknownFieldIgnored(message1, message2, field, | 976 if (ignore_criteria_[i]->IsUnknownFieldIgnored(message1, message2, field, |
984 parent_fields)) { | 977 parent_fields)) { |
985 return true; | 978 return true; |
986 } | 979 } |
987 } | 980 } |
988 return false; | 981 return false; |
989 } | 982 } |
990 | 983 |
991 const MessageDifferencer::MapKeyComparator* MessageDifferencer | 984 const MessageDifferencer::MapKeyComparator* MessageDifferencer |
992 ::GetMapKeyComparator(const FieldDescriptor* field) { | 985 ::GetMapKeyComparator(const FieldDescriptor* field) { |
993 if (!field->is_repeated()) return NULL; | 986 if (!field->is_repeated()) return NULL; |
994 if (map_field_key_comparator_.find(field) != | 987 if (map_field_key_comparator_.find(field) != |
995 map_field_key_comparator_.end()) { | 988 map_field_key_comparator_.end()) { |
996 return map_field_key_comparator_[field]; | 989 return map_field_key_comparator_[field]; |
997 } | 990 } |
998 return NULL; | 991 return NULL; |
999 } | 992 } |
1000 | 993 |
1001 namespace { | 994 namespace { |
1002 | 995 |
1003 typedef std::pair<int, const UnknownField*> IndexUnknownFieldPair; | 996 typedef pair<int, const UnknownField*> IndexUnknownFieldPair; |
1004 | 997 |
1005 struct UnknownFieldOrdering { | 998 struct UnknownFieldOrdering { |
1006 inline bool operator()(const IndexUnknownFieldPair& a, | 999 inline bool operator()(const IndexUnknownFieldPair& a, |
1007 const IndexUnknownFieldPair& b) const { | 1000 const IndexUnknownFieldPair& b) const { |
1008 if (a.second->number() < b.second->number()) return true; | 1001 if (a.second->number() < b.second->number()) return true; |
1009 if (a.second->number() > b.second->number()) return false; | 1002 if (a.second->number() > b.second->number()) return false; |
1010 return a.second->type() < b.second->type(); | 1003 return a.second->type() < b.second->type(); |
1011 } | 1004 } |
1012 }; | 1005 }; |
1013 | 1006 |
(...skipping 30 matching lines...) Expand all Loading... |
1044 GOOGLE_DLOG(ERROR) << "Failed to parse value for " << full_type_name; | 1037 GOOGLE_DLOG(ERROR) << "Failed to parse value for " << full_type_name; |
1045 return false; | 1038 return false; |
1046 } | 1039 } |
1047 return true; | 1040 return true; |
1048 } | 1041 } |
1049 | 1042 |
1050 bool MessageDifferencer::CompareUnknownFields( | 1043 bool MessageDifferencer::CompareUnknownFields( |
1051 const Message& message1, const Message& message2, | 1044 const Message& message1, const Message& message2, |
1052 const google::protobuf::UnknownFieldSet& unknown_field_set1, | 1045 const google::protobuf::UnknownFieldSet& unknown_field_set1, |
1053 const google::protobuf::UnknownFieldSet& unknown_field_set2, | 1046 const google::protobuf::UnknownFieldSet& unknown_field_set2, |
1054 std::vector<SpecificField>* parent_field) { | 1047 vector<SpecificField>* parent_field) { |
1055 // Ignore unknown fields in EQUIVALENT mode. | 1048 // Ignore unknown fields in EQUIVALENT mode. |
1056 if (message_field_comparison_ == EQUIVALENT) return true; | 1049 if (message_field_comparison_ == EQUIVALENT) return true; |
1057 | 1050 |
1058 if (unknown_field_set1.empty() && unknown_field_set2.empty()) { | 1051 if (unknown_field_set1.empty() && unknown_field_set2.empty()) { |
1059 return true; | 1052 return true; |
1060 } | 1053 } |
1061 | 1054 |
1062 bool is_different = false; | 1055 bool is_different = false; |
1063 | 1056 |
1064 // We first sort the unknown fields by field number and type (in other words, | 1057 // We first sort the unknown fields by field number and type (in other words, |
1065 // in tag order), making sure to preserve ordering of values with the same | 1058 // in tag order), making sure to preserve ordering of values with the same |
1066 // tag. This allows us to report only meaningful differences between the | 1059 // tag. This allows us to report only meaningful differences between the |
1067 // two sets -- that is, differing values for the same tag. We use | 1060 // two sets -- that is, differing values for the same tag. We use |
1068 // IndexUnknownFieldPairs to keep track of the field's original index for | 1061 // IndexUnknownFieldPairs to keep track of the field's original index for |
1069 // reporting purposes. | 1062 // reporting purposes. |
1070 std::vector<IndexUnknownFieldPair> fields1; // unknown_field_set1, sorted | 1063 vector<IndexUnknownFieldPair> fields1; // unknown_field_set1, sorted |
1071 std::vector<IndexUnknownFieldPair> fields2; // unknown_field_set2, sorted | 1064 vector<IndexUnknownFieldPair> fields2; // unknown_field_set2, sorted |
1072 fields1.reserve(unknown_field_set1.field_count()); | 1065 fields1.reserve(unknown_field_set1.field_count()); |
1073 fields2.reserve(unknown_field_set2.field_count()); | 1066 fields2.reserve(unknown_field_set2.field_count()); |
1074 | 1067 |
1075 for (int i = 0; i < unknown_field_set1.field_count(); i++) { | 1068 for (int i = 0; i < unknown_field_set1.field_count(); i++) { |
1076 fields1.push_back(std::make_pair(i, &unknown_field_set1.field(i))); | 1069 fields1.push_back(std::make_pair(i, &unknown_field_set1.field(i))); |
1077 } | 1070 } |
1078 for (int i = 0; i < unknown_field_set2.field_count(); i++) { | 1071 for (int i = 0; i < unknown_field_set2.field_count(); i++) { |
1079 fields2.push_back(std::make_pair(i, &unknown_field_set2.field(i))); | 1072 fields2.push_back(std::make_pair(i, &unknown_field_set2.field(i))); |
1080 } | 1073 } |
1081 | 1074 |
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1264 // determine whether a node on the left side of the bipartial graph matches | 1257 // determine whether a node on the left side of the bipartial graph matches |
1265 // a node on the right side. count1 is the number of nodes on the left side | 1258 // a node on the right side. count1 is the number of nodes on the left side |
1266 // of the graph and count2 to is the number of nodes on the right side. | 1259 // of the graph and count2 to is the number of nodes on the right side. |
1267 // Every node is referred to using 0-based indices. | 1260 // Every node is referred to using 0-based indices. |
1268 // If a maximum match is found, the result will be stored in match_list1 and | 1261 // If a maximum match is found, the result will be stored in match_list1 and |
1269 // match_list2. match_list1[i] == j means the i-th node on the left side is | 1262 // match_list2. match_list1[i] == j means the i-th node on the left side is |
1270 // matched to the j-th node on the right side and match_list2[x] == y means | 1263 // matched to the j-th node on the right side and match_list2[x] == y means |
1271 // the x-th node on the right side is matched to y-th node on the left side. | 1264 // the x-th node on the right side is matched to y-th node on the left side. |
1272 // match_list1[i] == -1 means the node is not matched. Same with match_list2. | 1265 // match_list1[i] == -1 means the node is not matched. Same with match_list2. |
1273 MaximumMatcher(int count1, int count2, NodeMatchCallback* callback, | 1266 MaximumMatcher(int count1, int count2, NodeMatchCallback* callback, |
1274 std::vector<int>* match_list1, std::vector<int>* match_list2); | 1267 vector<int>* match_list1, vector<int>* match_list2); |
1275 // Find a maximum match and return the number of matched node pairs. | 1268 // Find a maximum match and return the number of matched node pairs. |
1276 // If early_return is true, this method will return 0 immediately when it | 1269 // If early_return is true, this method will return 0 immediately when it |
1277 // finds that not all nodes on the left side can be matched. | 1270 // finds that not all nodes on the left side can be matched. |
1278 int FindMaximumMatch(bool early_return); | 1271 int FindMaximumMatch(bool early_return); |
1279 private: | 1272 private: |
1280 // Determines whether the node on the left side of the bipartial graph | 1273 // Determines whether the node on the left side of the bipartial graph |
1281 // matches the one on the right side. | 1274 // matches the one on the right side. |
1282 bool Match(int left, int right); | 1275 bool Match(int left, int right); |
1283 // Find an argumenting path starting from the node v on the left side. If a | 1276 // Find an argumenting path starting from the node v on the left side. If a |
1284 // path can be found, update match_list2_ to reflect the path and return | 1277 // path can be found, update match_list2_ to reflect the path and return |
1285 // true. | 1278 // true. |
1286 bool FindArgumentPathDFS(int v, std::vector<bool>* visited); | 1279 bool FindArgumentPathDFS(int v, vector<bool>* visited); |
1287 | 1280 |
1288 int count1_; | 1281 int count1_; |
1289 int count2_; | 1282 int count2_; |
1290 google::protobuf::scoped_ptr<NodeMatchCallback> match_callback_; | 1283 google::protobuf::scoped_ptr<NodeMatchCallback> match_callback_; |
1291 std::map<std::pair<int, int>, bool> cached_match_results_; | 1284 map<pair<int, int>, bool> cached_match_results_; |
1292 std::vector<int>* match_list1_; | 1285 vector<int>* match_list1_; |
1293 std::vector<int>* match_list2_; | 1286 vector<int>* match_list2_; |
1294 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MaximumMatcher); | 1287 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MaximumMatcher); |
1295 }; | 1288 }; |
1296 | 1289 |
1297 MaximumMatcher::MaximumMatcher(int count1, int count2, | 1290 MaximumMatcher::MaximumMatcher(int count1, int count2, |
1298 NodeMatchCallback* callback, | 1291 NodeMatchCallback* callback, |
1299 std::vector<int>* match_list1, | 1292 vector<int>* match_list1, |
1300 std::vector<int>* match_list2) | 1293 vector<int>* match_list2) |
1301 : count1_(count1), count2_(count2), match_callback_(callback), | 1294 : count1_(count1), count2_(count2), match_callback_(callback), |
1302 match_list1_(match_list1), match_list2_(match_list2) { | 1295 match_list1_(match_list1), match_list2_(match_list2) { |
1303 match_list1_->assign(count1, -1); | 1296 match_list1_->assign(count1, -1); |
1304 match_list2_->assign(count2, -1); | 1297 match_list2_->assign(count2, -1); |
1305 } | 1298 } |
1306 | 1299 |
1307 int MaximumMatcher::FindMaximumMatch(bool early_return) { | 1300 int MaximumMatcher::FindMaximumMatch(bool early_return) { |
1308 int result = 0; | 1301 int result = 0; |
1309 for (int i = 0; i < count1_; ++i) { | 1302 for (int i = 0; i < count1_; ++i) { |
1310 std::vector<bool> visited(count1_); | 1303 vector<bool> visited(count1_); |
1311 if (FindArgumentPathDFS(i, &visited)) { | 1304 if (FindArgumentPathDFS(i, &visited)) { |
1312 ++result; | 1305 ++result; |
1313 } else if (early_return) { | 1306 } else if (early_return) { |
1314 return 0; | 1307 return 0; |
1315 } | 1308 } |
1316 } | 1309 } |
1317 // Backfill match_list1_ as we only filled match_list2_ when finding | 1310 // Backfill match_list1_ as we only filled match_list2_ when finding |
1318 // argumenting pathes. | 1311 // argumenting pathes. |
1319 for (int i = 0; i < count2_; ++i) { | 1312 for (int i = 0; i < count2_; ++i) { |
1320 if ((*match_list2_)[i] != -1) { | 1313 if ((*match_list2_)[i] != -1) { |
1321 (*match_list1_)[(*match_list2_)[i]] = i; | 1314 (*match_list1_)[(*match_list2_)[i]] = i; |
1322 } | 1315 } |
1323 } | 1316 } |
1324 return result; | 1317 return result; |
1325 } | 1318 } |
1326 | 1319 |
1327 bool MaximumMatcher::Match(int left, int right) { | 1320 bool MaximumMatcher::Match(int left, int right) { |
1328 std::pair<int, int> p(left, right); | 1321 pair<int, int> p(left, right); |
1329 std::map<std::pair<int, int>, bool>::iterator it = | 1322 map<pair<int, int>, bool>::iterator it = cached_match_results_.find(p); |
1330 cached_match_results_.find(p); | |
1331 if (it != cached_match_results_.end()) { | 1323 if (it != cached_match_results_.end()) { |
1332 return it->second; | 1324 return it->second; |
1333 } | 1325 } |
1334 cached_match_results_[p] = match_callback_->Run(left, right); | 1326 cached_match_results_[p] = match_callback_->Run(left, right); |
1335 return cached_match_results_[p]; | 1327 return cached_match_results_[p]; |
1336 } | 1328 } |
1337 | 1329 |
1338 bool MaximumMatcher::FindArgumentPathDFS(int v, std::vector<bool>* visited) { | 1330 bool MaximumMatcher::FindArgumentPathDFS(int v, vector<bool>* visited) { |
1339 (*visited)[v] = true; | 1331 (*visited)[v] = true; |
1340 // We try to match those un-matched nodes on the right side first. This is | 1332 // We try to match those un-matched nodes on the right side first. This is |
1341 // the step that the navie greedy matching algorithm uses. In the best cases | 1333 // the step that the navie greedy matching algorithm uses. In the best cases |
1342 // where the greedy algorithm can find a maximum matching, we will always | 1334 // where the greedy algorithm can find a maximum matching, we will always |
1343 // find a match in this step and the performance will be identical to the | 1335 // find a match in this step and the performance will be identical to the |
1344 // greedy algorithm. | 1336 // greedy algorithm. |
1345 for (int i = 0; i < count2_; ++i) { | 1337 for (int i = 0; i < count2_; ++i) { |
1346 int matched = (*match_list2_)[i]; | 1338 int matched = (*match_list2_)[i]; |
1347 if (matched == -1 && Match(v, i)) { | 1339 if (matched == -1 && Match(v, i)) { |
1348 (*match_list2_)[i] = v; | 1340 (*match_list2_)[i] = v; |
(...skipping 15 matching lines...) Expand all Loading... |
1364 } | 1356 } |
1365 return false; | 1357 return false; |
1366 } | 1358 } |
1367 | 1359 |
1368 } // namespace | 1360 } // namespace |
1369 | 1361 |
1370 bool MessageDifferencer::MatchRepeatedFieldIndices( | 1362 bool MessageDifferencer::MatchRepeatedFieldIndices( |
1371 const Message& message1, | 1363 const Message& message1, |
1372 const Message& message2, | 1364 const Message& message2, |
1373 const FieldDescriptor* repeated_field, | 1365 const FieldDescriptor* repeated_field, |
1374 const std::vector<SpecificField>& parent_fields, | 1366 const vector<SpecificField>& parent_fields, |
1375 std::vector<int>* match_list1, | 1367 vector<int>* match_list1, |
1376 std::vector<int>* match_list2) { | 1368 vector<int>* match_list2) { |
1377 const int count1 = | 1369 const int count1 = |
1378 message1.GetReflection()->FieldSize(message1, repeated_field); | 1370 message1.GetReflection()->FieldSize(message1, repeated_field); |
1379 const int count2 = | 1371 const int count2 = |
1380 message2.GetReflection()->FieldSize(message2, repeated_field); | 1372 message2.GetReflection()->FieldSize(message2, repeated_field); |
1381 const MapKeyComparator* key_comparator = GetMapKeyComparator(repeated_field); | 1373 const MapKeyComparator* key_comparator = GetMapKeyComparator(repeated_field); |
1382 | 1374 |
1383 match_list1->assign(count1, -1); | 1375 match_list1->assign(count1, -1); |
1384 match_list2->assign(count2, -1); | 1376 match_list2->assign(count2, -1); |
1385 | 1377 |
1386 SpecificField specific_field; | 1378 SpecificField specific_field; |
1387 specific_field.field = repeated_field; | 1379 specific_field.field = repeated_field; |
1388 | 1380 |
1389 bool success = true; | 1381 bool success = true; |
1390 // Find potential match if this is a special repeated field. | 1382 // Find potential match if this is a special repeated field. |
1391 if (key_comparator != NULL || IsTreatedAsSet(repeated_field)) { | 1383 if (key_comparator != NULL || IsTreatedAsSet(repeated_field)) { |
1392 if (scope_ == PARTIAL) { | 1384 if (scope_ == PARTIAL) { |
1393 // When partial matching is enabled, Compare(a, b) && Compare(a, c) | 1385 // When partial matching is enabled, Compare(a, b) && Compare(a, c) |
1394 // doesn't necessarily imply Compare(b, c). Therefore a naive greedy | 1386 // doesn't neccessarily imply Compare(b, c). Therefore a naive greedy |
1395 // algorithm will fail to find a maximum matching. | 1387 // algorithm will fail to find a maximum matching. |
1396 // Here we use the argumenting path algorithm. | 1388 // Here we use the argumenting path algorithm. |
1397 MaximumMatcher::NodeMatchCallback* callback = | 1389 MaximumMatcher::NodeMatchCallback* callback = |
1398 NewPermanentCallback( | 1390 ::google::protobuf::internal::NewPermanentCallback( |
1399 this, &MessageDifferencer::IsMatch, | 1391 this, &MessageDifferencer::IsMatch, |
1400 repeated_field, key_comparator, | 1392 repeated_field, key_comparator, |
1401 &message1, &message2, parent_fields); | 1393 &message1, &message2, parent_fields); |
1402 MaximumMatcher matcher(count1, count2, callback, match_list1, | 1394 MaximumMatcher matcher(count1, count2, callback, match_list1, |
1403 match_list2); | 1395 match_list2); |
1404 // If diff info is not needed, we should end the matching process as | 1396 // If diff info is not needed, we should end the matching process as |
1405 // soon as possible if not all items can be matched. | 1397 // soon as possible if not all items can be matched. |
1406 bool early_return = (reporter_ == NULL); | 1398 bool early_return = (reporter_ == NULL); |
1407 int match_count = matcher.FindMaximumMatch(early_return); | 1399 int match_count = matcher.FindMaximumMatch(early_return); |
1408 if (match_count != count1 && reporter_ == NULL) return false; | 1400 if (match_count != count1 && reporter_ == NULL) return false; |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1481 MessageDifferencer::StreamReporter::StreamReporter( | 1473 MessageDifferencer::StreamReporter::StreamReporter( |
1482 io::Printer* printer) : printer_(printer), | 1474 io::Printer* printer) : printer_(printer), |
1483 delete_printer_(false), | 1475 delete_printer_(false), |
1484 report_modified_aggregates_(false) { } | 1476 report_modified_aggregates_(false) { } |
1485 | 1477 |
1486 MessageDifferencer::StreamReporter::~StreamReporter() { | 1478 MessageDifferencer::StreamReporter::~StreamReporter() { |
1487 if (delete_printer_) delete printer_; | 1479 if (delete_printer_) delete printer_; |
1488 } | 1480 } |
1489 | 1481 |
1490 void MessageDifferencer::StreamReporter::PrintPath( | 1482 void MessageDifferencer::StreamReporter::PrintPath( |
1491 const std::vector<SpecificField>& field_path, bool left_side) { | 1483 const vector<SpecificField>& field_path, bool left_side) { |
1492 for (int i = 0; i < field_path.size(); ++i) { | 1484 for (int i = 0; i < field_path.size(); ++i) { |
1493 if (i > 0) { | 1485 if (i > 0) { |
1494 printer_->Print("."); | 1486 printer_->Print("."); |
1495 } | 1487 } |
1496 | 1488 |
1497 SpecificField specific_field = field_path[i]; | 1489 SpecificField specific_field = field_path[i]; |
1498 | 1490 |
1499 if (specific_field.field != NULL) { | 1491 if (specific_field.field != NULL) { |
1500 if (specific_field.field->is_extension()) { | 1492 if (specific_field.field->is_extension()) { |
1501 printer_->Print("($name$)", "name", | 1493 printer_->Print("($name$)", "name", |
1502 specific_field.field->full_name()); | 1494 specific_field.field->full_name()); |
1503 } else { | 1495 } else { |
1504 printer_->PrintRaw(specific_field.field->name()); | 1496 printer_->PrintRaw(specific_field.field->name()); |
1505 } | 1497 } |
1506 } else { | 1498 } else { |
1507 printer_->PrintRaw(SimpleItoa(specific_field.unknown_field_number)); | 1499 printer_->PrintRaw(SimpleItoa(specific_field.unknown_field_number)); |
1508 } | 1500 } |
1509 if (left_side && specific_field.index >= 0) { | 1501 if (left_side && specific_field.index >= 0) { |
1510 printer_->Print("[$name$]", "name", SimpleItoa(specific_field.index)); | 1502 printer_->Print("[$name$]", "name", SimpleItoa(specific_field.index)); |
1511 } | 1503 } |
1512 if (!left_side && specific_field.new_index >= 0) { | 1504 if (!left_side && specific_field.new_index >= 0) { |
1513 printer_->Print("[$name$]", "name", SimpleItoa(specific_field.new_index)); | 1505 printer_->Print("[$name$]", "name", SimpleItoa(specific_field.new_index)); |
1514 } | 1506 } |
1515 } | 1507 } |
1516 } | 1508 } |
1517 | 1509 |
1518 void MessageDifferencer:: | 1510 void MessageDifferencer:: |
1519 StreamReporter::PrintValue(const Message& message, | 1511 StreamReporter::PrintValue(const Message& message, |
1520 const std::vector<SpecificField>& field_path, | 1512 const vector<SpecificField>& field_path, |
1521 bool left_side) { | 1513 bool left_side) { |
1522 const SpecificField& specific_field = field_path.back(); | 1514 const SpecificField& specific_field = field_path.back(); |
1523 const FieldDescriptor* field = specific_field.field; | 1515 const FieldDescriptor* field = specific_field.field; |
1524 if (field != NULL) { | 1516 if (field != NULL) { |
1525 string output; | 1517 string output; |
1526 int index = left_side ? specific_field.index : specific_field.new_index; | 1518 int index = left_side ? specific_field.index : specific_field.new_index; |
1527 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { | 1519 if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { |
1528 const Reflection* reflection = message.GetReflection(); | 1520 const Reflection* reflection = message.GetReflection(); |
1529 const Message& field_message = field->is_repeated() ? | 1521 const Message& field_message = field->is_repeated() ? |
1530 reflection->GetRepeatedMessage(message, field, index) : | 1522 reflection->GetRepeatedMessage(message, field, index) : |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1583 printer_->PrintRaw(output); | 1575 printer_->PrintRaw(output); |
1584 } | 1576 } |
1585 | 1577 |
1586 void MessageDifferencer::StreamReporter::Print(const string& str) { | 1578 void MessageDifferencer::StreamReporter::Print(const string& str) { |
1587 printer_->Print(str.c_str()); | 1579 printer_->Print(str.c_str()); |
1588 } | 1580 } |
1589 | 1581 |
1590 void MessageDifferencer::StreamReporter::ReportAdded( | 1582 void MessageDifferencer::StreamReporter::ReportAdded( |
1591 const Message& message1, | 1583 const Message& message1, |
1592 const Message& message2, | 1584 const Message& message2, |
1593 const std::vector<SpecificField>& field_path) { | 1585 const vector<SpecificField>& field_path) { |
1594 printer_->Print("added: "); | 1586 printer_->Print("added: "); |
1595 PrintPath(field_path, false); | 1587 PrintPath(field_path, false); |
1596 printer_->Print(": "); | 1588 printer_->Print(": "); |
1597 PrintValue(message2, field_path, false); | 1589 PrintValue(message2, field_path, false); |
1598 printer_->Print("\n"); // Print for newlines. | 1590 printer_->Print("\n"); // Print for newlines. |
1599 } | 1591 } |
1600 | 1592 |
1601 void MessageDifferencer::StreamReporter::ReportDeleted( | 1593 void MessageDifferencer::StreamReporter::ReportDeleted( |
1602 const Message& message1, | 1594 const Message& message1, |
1603 const Message& message2, | 1595 const Message& message2, |
1604 const std::vector<SpecificField>& field_path) { | 1596 const vector<SpecificField>& field_path) { |
1605 printer_->Print("deleted: "); | 1597 printer_->Print("deleted: "); |
1606 PrintPath(field_path, true); | 1598 PrintPath(field_path, true); |
1607 printer_->Print(": "); | 1599 printer_->Print(": "); |
1608 PrintValue(message1, field_path, true); | 1600 PrintValue(message1, field_path, true); |
1609 printer_->Print("\n"); // Print for newlines | 1601 printer_->Print("\n"); // Print for newlines |
1610 } | 1602 } |
1611 | 1603 |
1612 void MessageDifferencer::StreamReporter::ReportModified( | 1604 void MessageDifferencer::StreamReporter::ReportModified( |
1613 const Message& message1, | 1605 const Message& message1, |
1614 const Message& message2, | 1606 const Message& message2, |
1615 const std::vector<SpecificField>& field_path) { | 1607 const vector<SpecificField>& field_path) { |
1616 if (!report_modified_aggregates_ && field_path.back().field == NULL) { | 1608 if (!report_modified_aggregates_ && field_path.back().field == NULL) { |
1617 if (field_path.back().unknown_field_type == UnknownField::TYPE_GROUP) { | 1609 if (field_path.back().unknown_field_type == UnknownField::TYPE_GROUP) { |
1618 // Any changes to the subfields have already been printed. | 1610 // Any changes to the subfields have already been printed. |
1619 return; | 1611 return; |
1620 } | 1612 } |
1621 } else if (!report_modified_aggregates_) { | 1613 } else if (!report_modified_aggregates_) { |
1622 if (field_path.back().field->cpp_type() == | 1614 if (field_path.back().field->cpp_type() == |
1623 FieldDescriptor::CPPTYPE_MESSAGE) { | 1615 FieldDescriptor::CPPTYPE_MESSAGE) { |
1624 // Any changes to the subfields have already been printed. | 1616 // Any changes to the subfields have already been printed. |
1625 return; | 1617 return; |
1626 } | 1618 } |
1627 } | 1619 } |
1628 | 1620 |
1629 printer_->Print("modified: "); | 1621 printer_->Print("modified: "); |
1630 PrintPath(field_path, true); | 1622 PrintPath(field_path, true); |
1631 if (CheckPathChanged(field_path)) { | 1623 if (CheckPathChanged(field_path)) { |
1632 printer_->Print(" -> "); | 1624 printer_->Print(" -> "); |
1633 PrintPath(field_path, false); | 1625 PrintPath(field_path, false); |
1634 } | 1626 } |
1635 printer_->Print(": "); | 1627 printer_->Print(": "); |
1636 PrintValue(message1, field_path, true); | 1628 PrintValue(message1, field_path, true); |
1637 printer_->Print(" -> "); | 1629 printer_->Print(" -> "); |
1638 PrintValue(message2, field_path, false); | 1630 PrintValue(message2, field_path, false); |
1639 printer_->Print("\n"); // Print for newlines. | 1631 printer_->Print("\n"); // Print for newlines. |
1640 } | 1632 } |
1641 | 1633 |
1642 void MessageDifferencer::StreamReporter::ReportMoved( | 1634 void MessageDifferencer::StreamReporter::ReportMoved( |
1643 const Message& message1, | 1635 const Message& message1, |
1644 const Message& message2, | 1636 const Message& message2, |
1645 const std::vector<SpecificField>& field_path) { | 1637 const vector<SpecificField>& field_path) { |
1646 printer_->Print("moved: "); | 1638 printer_->Print("moved: "); |
1647 PrintPath(field_path, true); | 1639 PrintPath(field_path, true); |
1648 printer_->Print(" -> "); | 1640 printer_->Print(" -> "); |
1649 PrintPath(field_path, false); | 1641 PrintPath(field_path, false); |
1650 printer_->Print(" : "); | 1642 printer_->Print(" : "); |
1651 PrintValue(message1, field_path, true); | 1643 PrintValue(message1, field_path, true); |
1652 printer_->Print("\n"); // Print for newlines. | 1644 printer_->Print("\n"); // Print for newlines. |
1653 } | 1645 } |
1654 | 1646 |
1655 void MessageDifferencer::StreamReporter::ReportMatched( | 1647 void MessageDifferencer::StreamReporter::ReportMatched( |
1656 const Message& message1, | 1648 const Message& message1, |
1657 const Message& message2, | 1649 const Message& message2, |
1658 const std::vector<SpecificField>& field_path) { | 1650 const vector<SpecificField>& field_path) { |
1659 printer_->Print("matched: "); | 1651 printer_->Print("matched: "); |
1660 PrintPath(field_path, true); | 1652 PrintPath(field_path, true); |
1661 if (CheckPathChanged(field_path)) { | 1653 if (CheckPathChanged(field_path)) { |
1662 printer_->Print(" -> "); | 1654 printer_->Print(" -> "); |
1663 PrintPath(field_path, false); | 1655 PrintPath(field_path, false); |
1664 } | 1656 } |
1665 printer_->Print(" : "); | 1657 printer_->Print(" : "); |
1666 PrintValue(message1, field_path, true); | 1658 PrintValue(message1, field_path, true); |
1667 printer_->Print("\n"); // Print for newlines. | 1659 printer_->Print("\n"); // Print for newlines. |
1668 } | 1660 } |
1669 | 1661 |
1670 void MessageDifferencer::StreamReporter::ReportIgnored( | 1662 void MessageDifferencer::StreamReporter::ReportIgnored( |
1671 const Message& message1, | 1663 const Message& message1, |
1672 const Message& message2, | 1664 const Message& message2, |
1673 const std::vector<SpecificField>& field_path) { | 1665 const vector<SpecificField>& field_path) { |
1674 printer_->Print("ignored: "); | 1666 printer_->Print("ignored: "); |
1675 PrintPath(field_path, true); | 1667 PrintPath(field_path, true); |
1676 if (CheckPathChanged(field_path)) { | 1668 if (CheckPathChanged(field_path)) { |
1677 printer_->Print(" -> "); | 1669 printer_->Print(" -> "); |
1678 PrintPath(field_path, false); | 1670 PrintPath(field_path, false); |
1679 } | 1671 } |
1680 printer_->Print("\n"); // Print for newlines. | 1672 printer_->Print("\n"); // Print for newlines. |
1681 } | 1673 } |
1682 | 1674 |
1683 void MessageDifferencer::StreamReporter::ReportUnknownFieldIgnored( | 1675 void MessageDifferencer::StreamReporter::ReportUnknownFieldIgnored( |
1684 const Message& message1, const Message& message2, | 1676 const Message& message1, const Message& message2, |
1685 const std::vector<SpecificField>& field_path) { | 1677 const vector<SpecificField>& field_path) { |
1686 printer_->Print("ignored: "); | 1678 printer_->Print("ignored: "); |
1687 PrintPath(field_path, true); | 1679 PrintPath(field_path, true); |
1688 if (CheckPathChanged(field_path)) { | 1680 if (CheckPathChanged(field_path)) { |
1689 printer_->Print(" -> "); | 1681 printer_->Print(" -> "); |
1690 PrintPath(field_path, false); | 1682 PrintPath(field_path, false); |
1691 } | 1683 } |
1692 printer_->Print("\n"); // Print for newlines. | 1684 printer_->Print("\n"); // Print for newlines. |
1693 } | 1685 } |
1694 | 1686 |
1695 } // namespace util | 1687 } // namespace util |
1696 } // namespace protobuf | 1688 } // namespace protobuf |
1697 } // namespace google | 1689 } // namespace google |
OLD | NEW |