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