diff options
Diffstat (limited to 'src/google/protobuf/util/message_differencer.cc')
-rw-r--r-- | src/google/protobuf/util/message_differencer.cc | 31 |
1 files changed, 22 insertions, 9 deletions
diff --git a/src/google/protobuf/util/message_differencer.cc b/src/google/protobuf/util/message_differencer.cc index c32e941c..9842f64c 100644 --- a/src/google/protobuf/util/message_differencer.cc +++ b/src/google/protobuf/util/message_differencer.cc @@ -40,9 +40,6 @@ #include <algorithm> #include <memory> -#ifndef _SHARED_PTR_H -#include <google/protobuf/stubs/shared_ptr.h> -#endif #include <utility> #include <google/protobuf/stubs/callback.h> @@ -490,8 +487,8 @@ bool MessageDifferencer::Compare( } // Expand google.protobuf.Any payload if possible. if (descriptor1->full_name() == internal::kAnyFullTypeName) { - google::protobuf::scoped_ptr<Message> data1; - google::protobuf::scoped_ptr<Message> data2; + std::unique_ptr<Message> data1; + std::unique_ptr<Message> data2; if (UnpackAny(message1, &data1) && UnpackAny(message2, &data2)) { // Avoid DFATAL for different descriptors in google.protobuf.Any payloads. if (data1->GetDescriptor() != data2->GetDescriptor()) { @@ -1068,7 +1065,7 @@ struct UnknownFieldOrdering { } // namespace bool MessageDifferencer::UnpackAny(const Message& any, - google::protobuf::scoped_ptr<Message>* data) { + std::unique_ptr<Message>* data) { const Reflection* reflection = any.GetReflection(); const FieldDescriptor* type_url_field; const FieldDescriptor* value_field; @@ -1341,7 +1338,7 @@ class MaximumMatcher { int count1_; int count2_; - google::protobuf::scoped_ptr<NodeMatchCallback> match_callback_; + std::unique_ptr<NodeMatchCallback> match_callback_; std::map<std::pair<int, int>, bool> cached_match_results_; std::vector<int>* match_list1_; std::vector<int>* match_list2_; @@ -1459,11 +1456,27 @@ bool MessageDifferencer::MatchRepeatedFieldIndices( if (match_count != count1 && reporter_ == NULL) return false; success = success && (match_count == count1); } else { - for (int i = 0; i < count1; ++i) { + int start_offset = 0; + // If the two repeated fields are treated as sets, optimize for the case + // where both start with same items stored in the same order. + if (IsTreatedAsSet(repeated_field)) { + start_offset = std::min(count1, count2); + for (int i = 0; i < count1 && i < count2; i++) { + if (IsMatch(repeated_field, key_comparator, &message1, &message2, + parent_fields, i, i)) { + match_list1->at(i) = i; + match_list2->at(i) = i; + } else { + start_offset = i; + break; + } + } + } + for (int i = start_offset; i < count1; ++i) { // Indicates any matched elements for this repeated field. bool match = false; - for (int j = 0; j < count2; j++) { + for (int j = start_offset; j < count2; j++) { if (match_list2->at(j) != -1) continue; match = IsMatch(repeated_field, key_comparator, |