Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(40)

Side by Side Diff: third_party/protobuf/src/google/protobuf/util/message_differencer.h

Issue 1842653006: Update //third_party/protobuf to version 3. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: merge Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 // https://developers.google.com/protocol-buffers/
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 // * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 // * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
14 // distribution.
15 // * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31 // Author: jschorr@google.com (Joseph Schorr)
32 // Based on original Protocol Buffers design by
33 // Sanjay Ghemawat, Jeff Dean, and others.
34 //
35 // This file defines static methods and classes for comparing Protocol
36 // Messages.
37 //
38 // Aug. 2008: Added Unknown Fields Comparison for messages.
39 // Aug. 2009: Added different options to compare repeated fields.
40 // Apr. 2010: Moved field comparison to FieldComparator.
41
42 #ifndef GOOGLE_PROTOBUF_UTIL_MESSAGE_DIFFERENCER_H__
43 #define GOOGLE_PROTOBUF_UTIL_MESSAGE_DIFFERENCER_H__
44
45 #include <map>
46 #include <set>
47 #include <string>
48 #include <vector>
49 #include <google/protobuf/descriptor.h> // FieldDescriptor
50 #include <google/protobuf/message.h> // Message
51 #include <google/protobuf/unknown_field_set.h>
52 #include <google/protobuf/util/field_comparator.h>
53
54 namespace google {
55 namespace protobuf {
56
57 class DynamicMessageFactory;
58 class FieldDescriptor;
59
60 namespace io {
61 class ZeroCopyOutputStream;
62 class Printer;
63 }
64
65 namespace util {
66
67 class FieldContext; // declared below MessageDifferencer
68
69 // A basic differencer that can be used to determine
70 // the differences between two specified Protocol Messages. If any differences
71 // are found, the Compare method will return false, and any differencer reporter
72 // specified via ReportDifferencesTo will have its reporting methods called (see
73 // below for implementation of the report). Based off of the original
74 // ProtocolDifferencer implementation in //net/proto/protocol-differencer.h
75 // (Thanks Todd!).
76 //
77 // MessageDifferencer REQUIRES that compared messages be the same type, defined
78 // as messages that share the same descriptor. If not, the behavior of this
79 // class is undefined.
80 //
81 // People disagree on what MessageDifferencer should do when asked to compare
82 // messages with different descriptors. Some people think it should always
83 // return false. Others expect it to try to look for similar fields and
84 // compare them anyway -- especially if the descriptors happen to be identical.
85 // If we chose either of these behaviors, some set of people would find it
86 // surprising, and could end up writing code expecting the other behavior
87 // without realizing their error. Therefore, we forbid that usage.
88 //
89 // This class is implemented based on the proto2 reflection. The performance
90 // should be good enough for normal usages. However, for places where the
91 // performance is extremely sensitive, there are several alternatives:
92 // - Comparing serialized string
93 // Downside: false negatives (there are messages that are the same but their
94 // serialized strings are different).
95 // - Equals code generator by compiler plugin (net/proto2/contrib/equals_plugin)
96 // Downside: more generated code; maintenance overhead for the additional rule
97 // (must be in sync with the original proto_library).
98 //
99 // Note on handling of google.protobuf.Any: MessageDifferencer automatically
100 // unpacks Any::value into a Message and compares its individual fields.
101 // Messages encoded in a repeated Any cannot be compared using TreatAsMap.
102 //
103 //
104 // Note on thread-safety: MessageDifferencer is *not* thread-safe. You need to
105 // guard it with a lock to use the same MessageDifferencer instance from
106 // multiple threads. Note that it's fine to call static comparison methods
107 // (like MessageDifferencer::Equals) concurrently.
108 class LIBPROTOBUF_EXPORT MessageDifferencer {
109 public:
110 // Determines whether the supplied messages are equal. Equality is defined as
111 // all fields within the two messages being set to the same value. Primitive
112 // fields and strings are compared by value while embedded messages/groups
113 // are compared as if via a recursive call. Use IgnoreField() and Compare()
114 // if some fields should be ignored in the comparison.
115 //
116 // This method REQUIRES that the two messages have the same
117 // Descriptor (message1.GetDescriptor() == message2.GetDescriptor()).
118 static bool Equals(const Message& message1, const Message& message2);
119
120 // Determines whether the supplied messages are equivalent. Equivalency is
121 // defined as all fields within the two messages having the same value. This
122 // differs from the Equals method above in that fields with default values
123 // are considered set to said value automatically. For details on how default
124 // values are defined for each field type, see http://shortn/_x2Gv6XFrWt.
125 // Also, Equivalent() ignores unknown fields. Use IgnoreField() and Compare()
126 // if some fields should be ignored in the comparison.
127 //
128 // This method REQUIRES that the two messages have the same
129 // Descriptor (message1.GetDescriptor() == message2.GetDescriptor()).
130 static bool Equivalent(const Message& message1, const Message& message2);
131
132 // Determines whether the supplied messages are approximately equal.
133 // Approximate equality is defined as all fields within the two messages
134 // being approximately equal. Primitive (non-float) fields and strings are
135 // compared by value, floats are compared using MathUtil::AlmostEquals() and
136 // embedded messages/groups are compared as if via a recursive call. Use
137 // IgnoreField() and Compare() if some fields should be ignored in the
138 // comparison.
139 //
140 // This method REQUIRES that the two messages have the same
141 // Descriptor (message1.GetDescriptor() == message2.GetDescriptor()).
142 static bool ApproximatelyEquals(const Message& message1,
143 const Message& message2);
144
145 // Determines whether the supplied messages are approximately equivalent.
146 // Approximate equivalency is defined as all fields within the two messages
147 // being approximately equivalent. As in
148 // MessageDifferencer::ApproximatelyEquals, primitive (non-float) fields and
149 // strings are compared by value, floats are compared using
150 // MathUtil::AlmostEquals() and embedded messages/groups are compared as if
151 // via a recursive call. However, fields with default values are considered
152 // set to said value, as per MessageDiffencer::Equivalent. Use IgnoreField()
153 // and Compare() if some fields should be ignored in the comparison.
154 //
155 // This method REQUIRES that the two messages have the same
156 // Descriptor (message1.GetDescriptor() == message2.GetDescriptor()).
157 static bool ApproximatelyEquivalent(const Message& message1,
158 const Message& message2);
159
160 // Identifies an individual field in a message instance. Used for field_path,
161 // below.
162 struct SpecificField {
163 // For known fields, "field" is filled in and "unknown_field_number" is -1.
164 // For unknown fields, "field" is NULL, "unknown_field_number" is the field
165 // number, and "unknown_field_type" is its type.
166 const FieldDescriptor* field;
167 int unknown_field_number;
168 UnknownField::Type unknown_field_type;
169
170 // If this a repeated field, "index" is the index within it. For unknown
171 // fields, this is the index of the field among all unknown fields of the
172 // same field number and type.
173 int index;
174
175 // If "field" is a repeated field which is being treated as a map or
176 // a set (see TreatAsMap() and TreatAsSet(), below), new_index indicates
177 // the index the position to which the element has moved. This only
178 // applies to ReportMoved() and (in the case of TreatAsMap())
179 // ReportModified(). In all other cases, "new_index" will have the same
180 // value as "index".
181 int new_index;
182
183 // For unknown fields, these are the pointers to the UnknownFieldSet
184 // containing the unknown fields. In certain cases (e.g. proto1's
185 // MessageSet, or nested groups of unknown fields), these may differ from
186 // the messages' internal UnknownFieldSets.
187 const UnknownFieldSet* unknown_field_set1;
188 const UnknownFieldSet* unknown_field_set2;
189
190 // For unknown fields, these are the index of the field within the
191 // UnknownFieldSets. One or the other will be -1 when
192 // reporting an addition or deletion.
193 int unknown_field_index1;
194 int unknown_field_index2;
195
196 SpecificField()
197 : field(NULL),
198 unknown_field_number(-1),
199 index(-1),
200 new_index(-1),
201 unknown_field_set1(NULL),
202 unknown_field_set2(NULL),
203 unknown_field_index1(-1),
204 unknown_field_index2(-1) {}
205 };
206
207 // Abstract base class from which all MessageDifferencer
208 // reporters derive. The five Report* methods below will be called when
209 // a field has been added, deleted, modified, moved, or matched. The third
210 // argument is a vector of FieldDescriptor pointers which describes the chain
211 // of fields that was taken to find the current field. For example, for a
212 // field found in an embedded message, the vector will contain two
213 // FieldDescriptors. The first will be the field of the embedded message
214 // itself and the second will be the actual field in the embedded message
215 // that was added/deleted/modified.
216 class LIBPROTOBUF_EXPORT Reporter {
217 public:
218 Reporter();
219 virtual ~Reporter();
220
221 // Reports that a field has been added into Message2.
222 virtual void ReportAdded(
223 const Message& message1, const Message& message2,
224 const vector<SpecificField>& field_path) = 0;
225
226 // Reports that a field has been deleted from Message1.
227 virtual void ReportDeleted(
228 const Message& message1,
229 const Message& message2,
230 const vector<SpecificField>& field_path) = 0;
231
232 // Reports that the value of a field has been modified.
233 virtual void ReportModified(
234 const Message& message1,
235 const Message& message2,
236 const vector<SpecificField>& field_path) = 0;
237
238 // Reports that a repeated field has been moved to another location. This
239 // only applies when using TreatAsSet or TreatAsMap() -- see below. Also
240 // note that for any given field, ReportModified and ReportMoved are
241 // mutually exclusive. If a field has been both moved and modified, then
242 // only ReportModified will be called.
243 virtual void ReportMoved(
244 const Message& message1,
245 const Message& message2,
246 const vector<SpecificField>& field_path) { }
247
248 // Reports that two fields match. Useful for doing side-by-side diffs.
249 // This function is mutually exclusive with ReportModified and ReportMoved.
250 // Note that you must call set_report_matches(true) before calling Compare
251 // to make use of this function.
252 virtual void ReportMatched(
253 const Message& message1,
254 const Message& message2,
255 const vector<SpecificField>& field_path) { }
256
257 // Reports that two fields would have been compared, but the
258 // comparison has been skipped because the field was marked as
259 // 'ignored' using IgnoreField(). This function is mutually
260 // exclusive with all the other Report() functions.
261 //
262 // The contract of ReportIgnored is slightly different than the
263 // other Report() functions, in that |field_path.back().index| is
264 // always equal to -1, even if the last field is repeated. This is
265 // because while the other Report() functions indicate where in a
266 // repeated field the action (Addition, Deletion, etc...)
267 // happened, when a repeated field is 'ignored', the differencer
268 // simply calls ReportIgnored on the repeated field as a whole and
269 // moves on without looking at its individual elements.
270 //
271 // Furthermore, ReportIgnored() does not indicate whether the
272 // fields were in fact equal or not, as Compare() does not inspect
273 // these fields at all. It is up to the Reporter to decide whether
274 // the fields are equal or not (perhaps with a second call to
275 // Compare()), if it cares.
276 virtual void ReportIgnored(
277 const Message& message1,
278 const Message& message2,
279 const vector<SpecificField>& field_path) { }
280
281 // Report that an unkown field is ignored. (see comment above).
282 // Note this is a different function since the last SpecificField in field
283 // path has a null field. This could break existing Reporter.
284 virtual void ReportUnknownFieldIgnored(
285 const Message& message1, const Message& message2,
286 const vector<SpecificField>& field_path) {}
287
288 private:
289 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Reporter);
290 };
291
292 // MapKeyComparator is used to determine if two elements have the same key
293 // when comparing elements of a repeated field as a map.
294 class LIBPROTOBUF_EXPORT MapKeyComparator {
295 public:
296 MapKeyComparator();
297 virtual ~MapKeyComparator();
298
299 virtual bool IsMatch(const Message& message1,
300 const Message& message2,
301 const vector<SpecificField>& parent_fields) const {
302 GOOGLE_CHECK(false) << "IsMatch() is not implemented.";
303 return false;
304 }
305
306 private:
307 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapKeyComparator);
308 };
309
310 // Abstract base class from which all IgnoreCriteria derive.
311 // By adding IgnoreCriteria more complex ignore logic can be implemented.
312 // IgnoreCriteria are registed with AddIgnoreCriteria. For each compared
313 // field IsIgnored is called on each added IgnoreCriteria until one returns
314 // true or all return false.
315 // IsIgnored is called for fields where at least one side has a value.
316 class LIBPROTOBUF_EXPORT IgnoreCriteria {
317 public:
318 IgnoreCriteria();
319 virtual ~IgnoreCriteria();
320
321 // Returns true if the field should be ignored.
322 virtual bool IsIgnored(
323 const Message& message1,
324 const Message& message2,
325 const FieldDescriptor* field,
326 const vector<SpecificField>& parent_fields) = 0;
327
328 // Returns true if the unknown field should be ignored.
329 // Note: This will be called for unknown fields as well in which case
330 // field.field will be null.
331 virtual bool IsUnknownFieldIgnored(
332 const Message& message1, const Message& message2,
333 const SpecificField& field,
334 const vector<SpecificField>& parent_fields) {
335 return false;
336 }
337 };
338
339 // To add a Reporter, construct default here, then use ReportDifferencesTo or
340 // ReportDifferencesToString.
341 explicit MessageDifferencer();
342
343 ~MessageDifferencer();
344
345 enum MessageFieldComparison {
346 EQUAL, // Fields must be present in both messages
347 // for the messages to be considered the same.
348 EQUIVALENT, // Fields with default values are considered set
349 // for comparison purposes even if not explicitly
350 // set in the messages themselves. Unknown fields
351 // are ignored.
352 };
353
354 enum Scope {
355 FULL, // All fields of both messages are considered in the comparison.
356 PARTIAL // Only fields present in the first message are considered; fields
357 // set only in the second message will be skipped during
358 // comparison.
359 };
360
361 // DEPRECATED. Use FieldComparator::FloatComparison instead.
362 enum FloatComparison {
363 EXACT, // Floats and doubles are compared exactly.
364 APPROXIMATE // Floats and doubles are compared using the
365 // MathUtil::AlmostEquals method.
366 };
367
368 enum RepeatedFieldComparison {
369 AS_LIST, // Repeated fields are compared in order. Differing values at
370 // the same index are reported using ReportModified(). If the
371 // repeated fields have different numbers of elements, the
372 // unpaired elements are reported using ReportAdded() or
373 // ReportDeleted().
374 AS_SET, // Treat all the repeated fields as sets by default.
375 // See TreatAsSet(), as below.
376 };
377
378 // The elements of the given repeated field will be treated as a set for
379 // diffing purposes, so different orderings of the same elements will be
380 // considered equal. Elements which are present on both sides of the
381 // comparison but which have changed position will be reported with
382 // ReportMoved(). Elements which only exist on one side or the other are
383 // reported with ReportAdded() and ReportDeleted() regardless of their
384 // positions. ReportModified() is never used for this repeated field. If
385 // the only differences between the compared messages is that some fields
386 // have been moved, then the comparison returns true.
387 //
388 // If the scope of comparison is set to PARTIAL, then in addition to what's
389 // above, extra values added to repeated fields of the second message will
390 // not cause the comparison to fail.
391 //
392 // Note that set comparison is currently O(k * n^2) (where n is the total
393 // number of elements, and k is the average size of each element). In theory
394 // it could be made O(n * k) with a more complex hashing implementation. Feel
395 // free to contribute one if the current implementation is too slow for you.
396 // If partial matching is also enabled, the time complexity will be O(k * n^2
397 // + n^3) in which n^3 is the time complexity of the maximum matching
398 // algorithm.
399 //
400 // REQUIRES: field->is_repeated() and field not registered with TreatAsList
401 void TreatAsSet(const FieldDescriptor* field);
402
403 // The elements of the given repeated field will be treated as a list for
404 // diffing purposes, so different orderings of the same elements will NOT be
405 // considered equal.
406 //
407 // REQUIRED: field->is_repeated() and field not registered with TreatAsSet
408 void TreatAsList(const FieldDescriptor* field);
409
410 // The elements of the given repeated field will be treated as a map for
411 // diffing purposes, with |key| being the map key. Thus, elements with the
412 // same key will be compared even if they do not appear at the same index.
413 // Differences are reported similarly to TreatAsSet(), except that
414 // ReportModified() is used to report elements with the same key but
415 // different values. Note that if an element is both moved and modified,
416 // only ReportModified() will be called. As with TreatAsSet, if the only
417 // differences between the compared messages is that some fields have been
418 // moved, then the comparison returns true. See TreatAsSet for notes on
419 // performance.
420 //
421 // REQUIRES: field->is_repeated()
422 // REQUIRES: field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE
423 // REQUIRES: key->containing_type() == field->message_type()
424 void TreatAsMap(const FieldDescriptor* field, const FieldDescriptor* key);
425 // Same as TreatAsMap except that this method will use multiple fields as
426 // the key in comparison. All specified fields in 'key_fields' should be
427 // present in the compared elements. Two elements will be treated as having
428 // the same key iff they have the same value for every specified field. There
429 // are two steps in the comparison process. The first one is key matching.
430 // Every element from one message will be compared to every element from
431 // the other message. Only fields in 'key_fields' are compared in this step
432 // to decide if two elements have the same key. The second step is value
433 // comparison. Those pairs of elements with the same key (with equal value
434 // for every field in 'key_fields') will be compared in this step.
435 // Time complexity of the first step is O(s * m * n ^ 2) where s is the
436 // average size of the fields specified in 'key_fields', m is the number of
437 // fields in 'key_fields' and n is the number of elements. If partial
438 // matching is enabled, an extra O(n^3) will be incured by the maximum
439 // matching algorithm. The second step is O(k * n) where k is the average
440 // size of each element.
441 void TreatAsMapWithMultipleFieldsAsKey(
442 const FieldDescriptor* field,
443 const vector<const FieldDescriptor*>& key_fields);
444 // Same as TreatAsMapWithMultipleFieldsAsKey, except that each of the field
445 // do not necessarily need to be a direct subfield. Each element in
446 // key_field_paths indicate a path from the message being compared, listing
447 // successive subfield to reach the key field.
448 //
449 // REQUIRES:
450 // for key_field_path in key_field_paths:
451 // key_field_path[0]->containing_type() == field->message_type()
452 // for i in [0, key_field_path.size() - 1):
453 // key_field_path[i+1]->containing_type() ==
454 // key_field_path[i]->message_type()
455 // key_field_path[i]->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE
456 // !key_field_path[i]->is_repeated()
457 void TreatAsMapWithMultipleFieldPathsAsKey(
458 const FieldDescriptor* field,
459 const vector<vector<const FieldDescriptor*> >& key_field_paths);
460
461 // Uses a custom MapKeyComparator to determine if two elements have the same
462 // key when comparing a repeated field as a map.
463 // The caller is responsible to delete the key_comparator.
464 // This method varies from TreatAsMapWithMultipleFieldsAsKey only in the
465 // first key matching step. Rather than comparing some specified fields, it
466 // will invoke the IsMatch method of the given 'key_comparator' to decide if
467 // two elements have the same key.
468 void TreatAsMapUsingKeyComparator(
469 const FieldDescriptor* field,
470 const MapKeyComparator* key_comparator);
471
472 // Add a custom ignore criteria that is evaluated in addition to the
473 // ignored fields added with IgnoreField.
474 // Takes ownership of ignore_criteria.
475 void AddIgnoreCriteria(IgnoreCriteria* ignore_criteria);
476
477 // Indicates that any field with the given descriptor should be
478 // ignored for the purposes of comparing two messages. This applies
479 // to fields nested in the message structure as well as top level
480 // ones. When the MessageDifferencer encounters an ignored field,
481 // ReportIgnored is called on the reporter, if one is specified.
482 //
483 // The only place where the field's 'ignored' status is not applied is when
484 // it is being used as a key in a field passed to TreatAsMap or is one of
485 // the fields passed to TreatAsMapWithMultipleFieldsAsKey.
486 // In this case it is compared in key matching but after that it's ignored
487 // in value comparison.
488 void IgnoreField(const FieldDescriptor* field);
489
490 // Sets the field comparator used to determine differences between protocol
491 // buffer fields. By default it's set to a DefaultFieldComparator instance.
492 // MessageDifferencer doesn't take ownership over the passed object.
493 // Note that this method must be called before Compare for the comparator to
494 // be used.
495 void set_field_comparator(FieldComparator* comparator);
496
497 // DEPRECATED. Pass a DefaultFieldComparator instance instead.
498 // Sets the fraction and margin for the float comparison of a given field.
499 // Uses MathUtil::WithinFractionOrMargin to compare the values.
500 // NOTE: this method does nothing if differencer's field comparator has been
501 // set to a custom object.
502 //
503 // REQUIRES: field->cpp_type == FieldDescriptor::CPPTYPE_DOUBLE or
504 // field->cpp_type == FieldDescriptor::CPPTYPE_FLOAT
505 // REQUIRES: float_comparison_ == APPROXIMATE
506 void SetFractionAndMargin(const FieldDescriptor* field, double fraction,
507 double margin);
508
509 // Sets the type of comparison (as defined in the MessageFieldComparison
510 // enumeration above) that is used by this differencer when determining how
511 // to compare fields in messages.
512 void set_message_field_comparison(MessageFieldComparison comparison);
513
514 // Tells the differencer whether or not to report matches. This method must
515 // be called before Compare. The default for a new differencer is false.
516 void set_report_matches(bool report_matches) {
517 report_matches_ = report_matches;
518 }
519
520 // Sets the scope of the comparison (as defined in the Scope enumeration
521 // above) that is used by this differencer when determining which fields to
522 // compare between the messages.
523 void set_scope(Scope scope);
524
525 // Returns the current scope used by this differencer.
526 Scope scope();
527
528 // DEPRECATED. Pass a DefaultFieldComparator instance instead.
529 // Sets the type of comparison (as defined in the FloatComparison enumeration
530 // above) that is used by this differencer when comparing float (and double)
531 // fields in messages.
532 // NOTE: this method does nothing if differencer's field comparator has been
533 // set to a custom object.
534 void set_float_comparison(FloatComparison comparison);
535
536 // Sets the type of comparison for repeated field (as defined in the
537 // RepeatedFieldComparison enumeration above) that is used by this
538 // differencer when compare repeated fields in messages.
539 void set_repeated_field_comparison(RepeatedFieldComparison comparison);
540
541 // Compares the two specified messages, returning true if they are the same,
542 // false otherwise. If this method returns false, any changes between the
543 // two messages will be reported if a Reporter was specified via
544 // ReportDifferencesTo (see also ReportDifferencesToString).
545 //
546 // This method REQUIRES that the two messages have the same
547 // Descriptor (message1.GetDescriptor() == message2.GetDescriptor()).
548 bool Compare(const Message& message1, const Message& message2);
549
550 // Same as above, except comparing only the list of fields specified by the
551 // two vectors of FieldDescriptors.
552 bool CompareWithFields(const Message& message1, const Message& message2,
553 const vector<const FieldDescriptor*>& message1_fields,
554 const vector<const FieldDescriptor*>& message2_fields);
555
556 // Automatically creates a reporter that will output the differences
557 // found (if any) to the specified output string pointer. Note that this
558 // method must be called before Compare.
559 void ReportDifferencesToString(string* output);
560
561 // Tells the MessageDifferencer to report differences via the specified
562 // reporter. Note that this method must be called before Compare for
563 // the reporter to be used. It is the responsibility of the caller to delete
564 // this object.
565 // If the provided pointer equals NULL, the MessageDifferencer stops reporting
566 // differences to any previously set reporters or output strings.
567 void ReportDifferencesTo(Reporter* reporter);
568
569 // An implementation of the MessageDifferencer Reporter that outputs
570 // any differences found in human-readable form to the supplied
571 // ZeroCopyOutputStream or Printer. If a printer is used, the delimiter
572 // *must* be '$'.
573 class LIBPROTOBUF_EXPORT StreamReporter : public Reporter {
574 public:
575 explicit StreamReporter(io::ZeroCopyOutputStream* output);
576 explicit StreamReporter(io::Printer* printer); // delimiter '$'
577 virtual ~StreamReporter();
578
579 // When set to true, the stream reporter will also output aggregates nodes
580 // (i.e. messages and groups) whose subfields have been modified. When
581 // false, will only report the individual subfields. Defaults to false.
582 void set_report_modified_aggregates(bool report) {
583 report_modified_aggregates_ = report;
584 }
585
586 // The following are implementations of the methods described above.
587 virtual void ReportAdded(const Message& message1, const Message& message2,
588 const vector<SpecificField>& field_path);
589
590 virtual void ReportDeleted(const Message& message1,
591 const Message& message2,
592 const vector<SpecificField>& field_path);
593
594 virtual void ReportModified(const Message& message1,
595 const Message& message2,
596 const vector<SpecificField>& field_path);
597
598 virtual void ReportMoved(const Message& message1,
599 const Message& message2,
600 const vector<SpecificField>& field_path);
601
602 virtual void ReportMatched(const Message& message1,
603 const Message& message2,
604 const vector<SpecificField>& field_path);
605
606 virtual void ReportIgnored(const Message& message1,
607 const Message& message2,
608 const vector<SpecificField>& field_path);
609
610 virtual void ReportUnknownFieldIgnored(
611 const Message& message1, const Message& message2,
612 const vector<SpecificField>& field_path);
613
614 protected:
615 // Prints the specified path of fields to the buffer.
616 virtual void PrintPath(const vector<SpecificField>& field_path,
617 bool left_side);
618
619 // Prints the value of fields to the buffer. left_side is true if the
620 // given message is from the left side of the comparison, false if it
621 // was the right. This is relevant only to decide whether to follow
622 // unknown_field_index1 or unknown_field_index2 when an unknown field
623 // is encountered in field_path.
624 virtual void PrintValue(const Message& message,
625 const vector<SpecificField>& field_path,
626 bool left_side);
627
628 // Prints the specified path of unknown fields to the buffer.
629 virtual void PrintUnknownFieldValue(const UnknownField* unknown_field);
630
631 // Just print a string
632 void Print(const string& str);
633
634 private:
635 io::Printer* printer_;
636 bool delete_printer_;
637 bool report_modified_aggregates_;
638
639 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StreamReporter);
640 };
641
642 private:
643 // A MapKeyComparator to be used in TreatAsMapUsingKeyComparator.
644 // Implementation of this class needs to do field value comparison which
645 // relies on some private methods of MessageDifferencer. That's why this
646 // class is declared as a nested class of MessageDifferencer.
647 class MultipleFieldsMapKeyComparator;
648 // Returns true if field1's number() is less than field2's.
649 static bool FieldBefore(const FieldDescriptor* field1,
650 const FieldDescriptor* field2);
651
652 // Combine the two lists of fields into the combined_fields output vector.
653 // All fields present in both lists will always be included in the combined
654 // list. Fields only present in one of the lists will only appear in the
655 // combined list if the corresponding fields_scope option is set to FULL.
656 void CombineFields(const vector<const FieldDescriptor*>& fields1,
657 Scope fields1_scope,
658 const vector<const FieldDescriptor*>& fields2,
659 Scope fields2_scope,
660 vector<const FieldDescriptor*>* combined_fields);
661
662 // Internal version of the Compare method which performs the actual
663 // comparison. The parent_fields vector is a vector containing field
664 // descriptors of all fields accessed to get to this comparison operation
665 // (i.e. if the current message is an embedded message, the parent_fields
666 // vector will contain the field that has this embedded message).
667 bool Compare(const Message& message1, const Message& message2,
668 vector<SpecificField>* parent_fields);
669
670 // Compares all the unknown fields in two messages.
671 bool CompareUnknownFields(const Message& message1, const Message& message2,
672 const google::protobuf::UnknownFieldSet&,
673 const google::protobuf::UnknownFieldSet&,
674 vector<SpecificField>* parent_fields);
675
676 // Compares the specified messages for the requested field lists. The field
677 // lists are modified depending on comparison settings, and then passed to
678 // CompareWithFieldsInternal.
679 bool CompareRequestedFieldsUsingSettings(
680 const Message& message1, const Message& message2,
681 const vector<const FieldDescriptor*>& message1_fields,
682 const vector<const FieldDescriptor*>& message2_fields,
683 vector<SpecificField>* parent_fields);
684
685 // Compares the specified messages with the specified field lists.
686 bool CompareWithFieldsInternal(
687 const Message& message1, const Message& message2,
688 const vector<const FieldDescriptor*>& message1_fields,
689 const vector<const FieldDescriptor*>& message2_fields,
690 vector<SpecificField>* parent_fields);
691
692 // Compares the repeated fields, and report the error.
693 bool CompareRepeatedField(const Message& message1, const Message& message2,
694 const FieldDescriptor* field,
695 vector<SpecificField>* parent_fields);
696
697 // Shorthand for CompareFieldValueUsingParentFields with NULL parent_fields.
698 bool CompareFieldValue(const Message& message1,
699 const Message& message2,
700 const FieldDescriptor* field,
701 int index1,
702 int index2);
703
704 // Compares the specified field on the two messages, returning
705 // true if they are the same, false otherwise. For repeated fields,
706 // this method only compares the value in the specified index. This method
707 // uses Compare functions to recurse into submessages.
708 // The parent_fields vector is used in calls to a Reporter instance calls.
709 // It can be NULL, in which case the MessageDifferencer will create new
710 // list of parent messages if it needs to recursively compare the given field.
711 // To avoid confusing users you should not set it to NULL unless you modified
712 // Reporter to handle the change of parent_fields correctly.
713 bool CompareFieldValueUsingParentFields(const Message& message1,
714 const Message& message2,
715 const FieldDescriptor* field,
716 int index1,
717 int index2,
718 vector<SpecificField>* parent_fields);
719
720 // Compares the specified field on the two messages, returning comparison
721 // result, as returned by appropriate FieldComparator.
722 FieldComparator::ComparisonResult GetFieldComparisonResult(
723 const Message& message1, const Message& message2,
724 const FieldDescriptor* field, int index1, int index2,
725 const FieldContext* field_context);
726
727 // Check if the two elements in the repeated field are match to each other.
728 // if the key_comprator is NULL, this function returns true when the two
729 // elements are equal.
730 bool IsMatch(const FieldDescriptor* repeated_field,
731 const MapKeyComparator* key_comparator,
732 const Message* message1, const Message* message2,
733 const vector<SpecificField>& parent_fields,
734 int index1, int index2);
735
736 // Returns true when this repeated field has been configured to be treated
737 // as a set.
738 bool IsTreatedAsSet(const FieldDescriptor* field);
739
740 // Returns true when this repeated field is to be compared as a subset, ie.
741 // has been configured to be treated as a set or map and scope is set to
742 // PARTIAL.
743 bool IsTreatedAsSubset(const FieldDescriptor* field);
744
745 // Returns true if this field is to be ignored when this
746 // MessageDifferencer compares messages.
747 bool IsIgnored(
748 const Message& message1,
749 const Message& message2,
750 const FieldDescriptor* field,
751 const vector<SpecificField>& parent_fields);
752
753 // Returns true if this unknown field is to be ignored when this
754 // MessageDifferencer compares messages.
755 bool IsUnknownFieldIgnored(const Message& message1, const Message& message2,
756 const SpecificField& field,
757 const vector<SpecificField>& parent_fields);
758
759 // Returns MapKeyComparator* when this field has been configured to
760 // be treated as a map. If not, returns NULL.
761 const MapKeyComparator* GetMapKeyComparator(const FieldDescriptor* field);
762
763 // Attempts to match indices of a repeated field, so that the contained values
764 // match. Clears output vectors and sets their values to indices of paired
765 // messages, ie. if message1[0] matches message2[1], then match_list1[0] == 1
766 // and match_list2[1] == 0. The unmatched indices are indicated by -1.
767 // This method returns false if the match failed. However, it doesn't mean
768 // that the comparison succeeds when this method returns true (you need to
769 // double-check in this case).
770 bool MatchRepeatedFieldIndices(const Message& message1,
771 const Message& message2,
772 const FieldDescriptor* repeated_field,
773 const vector<SpecificField>& parent_fields,
774 vector<int>* match_list1,
775 vector<int>* match_list2);
776
777 // If "any" is of type google.protobuf.Any, extract its payload using
778 // DynamicMessageFactory and store in "data".
779 bool UnpackAny(const Message& any, google::protobuf::scoped_ptr<Message>* data );
780
781 // Checks if index is equal to new_index in all the specific fields.
782 static bool CheckPathChanged(const vector<SpecificField>& parent_fields);
783
784 // Defines a map between field descriptors and their MapKeyComparators.
785 // Used for repeated fields when they are configured as TreatAsMap.
786 typedef map<const FieldDescriptor*,
787 const MapKeyComparator*> FieldKeyComparatorMap;
788
789 // Defines a set to store field descriptors. Used for repeated fields when
790 // they are configured as TreatAsSet.
791 typedef set<const FieldDescriptor*> FieldSet;
792
793 Reporter* reporter_;
794 DefaultFieldComparator default_field_comparator_;
795 FieldComparator* field_comparator_;
796 MessageFieldComparison message_field_comparison_;
797 Scope scope_;
798 RepeatedFieldComparison repeated_field_comparison_;
799
800 FieldSet set_fields_;
801 FieldSet list_fields_;
802 // Keeps track of MapKeyComparators that are created within
803 // MessageDifferencer. These MapKeyComparators should be deleted
804 // before MessageDifferencer is destroyed.
805 // When TreatAsMap or TreatAsMapWithMultipleFieldsAsKey is called, we don't
806 // store the supplied FieldDescriptors directly. Instead, a new
807 // MapKeyComparator is created for comparison purpose.
808 vector<MapKeyComparator*> owned_key_comparators_;
809 FieldKeyComparatorMap map_field_key_comparator_;
810 vector<IgnoreCriteria*> ignore_criteria_;
811
812 FieldSet ignored_fields_;
813
814 bool compare_unknown_fields_;
815 bool report_matches_;
816
817 string* output_string_;
818
819 google::protobuf::scoped_ptr<DynamicMessageFactory> dynamic_message_factory_;
820 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageDifferencer);
821 };
822
823 // This class provides extra information to the FieldComparator::Compare
824 // function.
825 class LIBPROTOBUF_EXPORT FieldContext {
826 public:
827 explicit FieldContext(
828 vector<MessageDifferencer::SpecificField>* parent_fields)
829 : parent_fields_(parent_fields) {}
830
831 vector<MessageDifferencer::SpecificField>* parent_fields() const {
832 return parent_fields_;
833 }
834
835 private:
836 vector<MessageDifferencer::SpecificField>* parent_fields_;
837 };
838
839 }
840 }
841
842 } // namespace google
843 #endif // GOOGLE_PROTOBUF_UTIL_MESSAGE_DIFFERENCER_H__
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698