| 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 |