Home | History | Annotate | Download | only in util
      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 (at) 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__
    844