webkit  2cdf99a9e3038c7e01b3c37e8ad903ecbe5eecf1
https://github.com/WebKit/webkit
message_differencer.h
Go to the documentation of this file.
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
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.
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.
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".
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.
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.
195 
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.
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.
285  const Message& message1, const Message& message2,
286  const vector<SpecificField>& field_path) {}
287 
288  private:
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.
295  public:
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:
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.
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 
344 
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.
363  EXACT, // Floats and doubles are compared exactly.
364  APPROXIMATE // Floats and doubles are compared using the
365  // MathUtil::AlmostEquals method.
366  };
367 
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 '$'.
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 
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.
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,
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 
821 };
822 
823 // This class provides extra information to the FieldComparator::Compare
824 // function.
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__
const FieldDescriptor * field
Definition: message_differencer.h:166
virtual void ReportMatched(const Message &message1, const Message &message2, const vector< SpecificField > &field_path)
Definition: message_differencer.h:252
Definition: message.h:179
Definition: util.py:1
Definition: printer.h:164
RepeatedFieldComparison
Definition: message_differencer.h:368
const FieldDescriptor * field
Definition: parser_unittest.cc:2279
int unknown_field_index2
Definition: message_differencer.h:194
virtual void ReportIgnored(const Message &message1, const Message &message2, const vector< SpecificField > &field_path)
Definition: message_differencer.h:276
hold on if any(s.optbuf~=0) peak_ix
Definition: field_comparator.h:56
int unknown_field_index1
Definition: message_differencer.h:193
SpecificField()
Definition: message_differencer.h:196
#define GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TypeName)
Definition: macros.h:40
typename detail::make_map< Ts... >::type map
Definition: Brigand.h:223
Type
Definition: unknown_field_set.h:170
Scope
Definition: message_differencer.h:354
vector< MessageDifferencer::SpecificField > * parent_fields() const
Definition: message_differencer.h:831
int index
Definition: message_differencer.h:173
void set_report_matches(bool report_matches)
Definition: message_differencer.h:516
Definition: message_differencer.h:216
FloatComparison
Definition: message_differencer.h:362
virtual bool IsUnknownFieldIgnored(const Message &message1, const Message &message2, const SpecificField &field, const vector< SpecificField > &parent_fields)
Definition: message_differencer.h:331
#define output
Definition: wire_format_lite.h:418
Definition: descriptor.h:439
Definition: protobuf.h:85
Definition: message_differencer.h:374
Definition: zero_copy_stream.h:181
const UnknownFieldSet * unknown_field_set1
Definition: message_differencer.h:187
int unknown_field_number
Definition: message_differencer.h:167
ComparisonResult
Definition: field_comparator.h:61
Definition: unknown_field_set.h:168
void set_report_modified_aggregates(bool report)
Definition: message_differencer.h:582
MessageFieldComparison
Definition: message_differencer.h:345
int new_index
Definition: message_differencer.h:181
comparator
Definition: UpdateContents.py:41
Definition: __init__.py:1
FieldContext(vector< MessageDifferencer::SpecificField > *parent_fields)
Definition: message_differencer.h:827
Definition: message_differencer.h:825
EGLSetBlobFuncANDROID set
Definition: eglext.h:426
Definition: unknown_field_set.h:75
Definition: scoped_ptr.h:48
EGLStreamKHR EGLint EGLint EGLint const void * data
Definition: eglext.h:984
str
Definition: make-dist.py:305
Definition: message_differencer.h:363
Definition: message_differencer.h:369
UnknownField::Type unknown_field_type
Definition: message_differencer.h:168
Definition: message_differencer.h:348
#define GOOGLE_CHECK(EXPRESSION)
Definition: logging.h:151
#define NULL
Definition: common_types.h:41
#define LIBPROTOBUF_EXPORT
Definition: port.h:97
Definition: message_differencer.h:108
virtual void ReportUnknownFieldIgnored(const Message &message1, const Message &message2, const vector< SpecificField > &field_path)
Definition: message_differencer.h:284
virtual void ReportMoved(const Message &message1, const Message &message2, const vector< SpecificField > &field_path)
Definition: message_differencer.h:243
Definition: gflags_completions.h:115
Definition: field_comparator.h:97
Definition: message_differencer.h:355
CFArrayRef CFTypeRef key
Definition: AVFoundationCFSoftLinking.h:129
GLuint GLsizei const GLchar * message
Definition: gl2ext.h:137
Definition: message_differencer.h:346
virtual bool IsMatch(const Message &message1, const Message &message2, const vector< SpecificField > &parent_fields) const
Definition: message_differencer.h:299
const UnknownFieldSet * unknown_field_set2
Definition: message_differencer.h:188