975 lines
		
	
	
		
			46 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			975 lines
		
	
	
		
			46 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
// Protocol Buffers - Google's data interchange format
 | 
						|
// Copyright 2008 Google Inc.  All rights reserved.
 | 
						|
// https://developers.google.com/protocol-buffers/
 | 
						|
//
 | 
						|
// Redistribution and use in source and binary forms, with or without
 | 
						|
// modification, are permitted provided that the following conditions are
 | 
						|
// met:
 | 
						|
//
 | 
						|
//     * Redistributions of source code must retain the above copyright
 | 
						|
// notice, this list of conditions and the following disclaimer.
 | 
						|
//     * Redistributions in binary form must reproduce the above
 | 
						|
// copyright notice, this list of conditions and the following disclaimer
 | 
						|
// in the documentation and/or other materials provided with the
 | 
						|
// distribution.
 | 
						|
//     * Neither the name of Google Inc. nor the names of its
 | 
						|
// contributors may be used to endorse or promote products derived from
 | 
						|
// this software without specific prior written permission.
 | 
						|
//
 | 
						|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
						|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
						|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | 
						|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | 
						|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
						|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
						|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | 
						|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | 
						|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
						|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | 
						|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
						|
 | 
						|
// Author: jschorr@google.com (Joseph Schorr)
 | 
						|
//  Based on original Protocol Buffers design by
 | 
						|
//  Sanjay Ghemawat, Jeff Dean, and others.
 | 
						|
//
 | 
						|
// This file defines static methods and classes for comparing Protocol
 | 
						|
// Messages.
 | 
						|
//
 | 
						|
// Aug. 2008: Added Unknown Fields Comparison for messages.
 | 
						|
// Aug. 2009: Added different options to compare repeated fields.
 | 
						|
// Apr. 2010: Moved field comparison to FieldComparator
 | 
						|
// Sep. 2020: Added option to output map keys in path
 | 
						|
 | 
						|
#ifndef GOOGLE_PROTOBUF_UTIL_MESSAGE_DIFFERENCER_H__
 | 
						|
#define GOOGLE_PROTOBUF_UTIL_MESSAGE_DIFFERENCER_H__
 | 
						|
 | 
						|
#include <functional>
 | 
						|
#include <map>
 | 
						|
#include <memory>
 | 
						|
#include <set>
 | 
						|
#include <string>
 | 
						|
#include <vector>
 | 
						|
 | 
						|
#include <google/protobuf/descriptor.h>  // FieldDescriptor
 | 
						|
#include <google/protobuf/message.h>     // Message
 | 
						|
#include <google/protobuf/unknown_field_set.h>
 | 
						|
#include <google/protobuf/util/field_comparator.h>
 | 
						|
 | 
						|
// Always include as last one, otherwise it can break compilation
 | 
						|
#include <google/protobuf/port_def.inc>
 | 
						|
 | 
						|
namespace google {
 | 
						|
namespace protobuf {
 | 
						|
 | 
						|
class DynamicMessageFactory;
 | 
						|
class FieldDescriptor;
 | 
						|
 | 
						|
namespace io {
 | 
						|
class ZeroCopyOutputStream;
 | 
						|
class Printer;
 | 
						|
}  // namespace io
 | 
						|
 | 
						|
namespace util {
 | 
						|
 | 
						|
class DefaultFieldComparator;
 | 
						|
class FieldContext;  // declared below MessageDifferencer
 | 
						|
 | 
						|
// Defines a collection of field descriptors.
 | 
						|
// In case of internal google codebase we are using absl::FixedArray instead
 | 
						|
// of vector. It significantly speeds up proto comparison (by ~30%) by
 | 
						|
// reducing the number of malloc/free operations
 | 
						|
typedef std::vector<const FieldDescriptor*> FieldDescriptorArray;
 | 
						|
 | 
						|
// A basic differencer that can be used to determine
 | 
						|
// the differences between two specified Protocol Messages. If any differences
 | 
						|
// are found, the Compare method will return false, and any differencer reporter
 | 
						|
// specified via ReportDifferencesTo will have its reporting methods called (see
 | 
						|
// below for implementation of the report). Based off of the original
 | 
						|
// ProtocolDifferencer implementation in //net/proto/protocol-differencer.h
 | 
						|
// (Thanks Todd!).
 | 
						|
//
 | 
						|
// MessageDifferencer REQUIRES that compared messages be the same type, defined
 | 
						|
// as messages that share the same descriptor.  If not, the behavior of this
 | 
						|
// class is undefined.
 | 
						|
//
 | 
						|
// People disagree on what MessageDifferencer should do when asked to compare
 | 
						|
// messages with different descriptors.  Some people think it should always
 | 
						|
// return false.  Others expect it to try to look for similar fields and
 | 
						|
// compare them anyway -- especially if the descriptors happen to be identical.
 | 
						|
// If we chose either of these behaviors, some set of people would find it
 | 
						|
// surprising, and could end up writing code expecting the other behavior
 | 
						|
// without realizing their error.  Therefore, we forbid that usage.
 | 
						|
//
 | 
						|
// This class is implemented based on the proto2 reflection. The performance
 | 
						|
// should be good enough for normal usages. However, for places where the
 | 
						|
// performance is extremely sensitive, there are several alternatives:
 | 
						|
// - Comparing serialized string
 | 
						|
// Downside: false negatives (there are messages that are the same but their
 | 
						|
// serialized strings are different).
 | 
						|
// - Equals code generator by compiler plugin (net/proto2/contrib/equals_plugin)
 | 
						|
// Downside: more generated code; maintenance overhead for the additional rule
 | 
						|
// (must be in sync with the original proto_library).
 | 
						|
//
 | 
						|
// Note on handling of google.protobuf.Any: MessageDifferencer automatically
 | 
						|
// unpacks Any::value into a Message and compares its individual fields.
 | 
						|
// Messages encoded in a repeated Any cannot be compared using TreatAsMap.
 | 
						|
//
 | 
						|
// Note on thread-safety: MessageDifferencer is *not* thread-safe. You need to
 | 
						|
// guard it with a lock to use the same MessageDifferencer instance from
 | 
						|
// multiple threads. Note that it's fine to call static comparison methods
 | 
						|
// (like MessageDifferencer::Equals) concurrently, but it's not recommended for
 | 
						|
// performance critical code as it leads to extra allocations.
 | 
						|
class PROTOBUF_EXPORT MessageDifferencer {
 | 
						|
 public:
 | 
						|
  // Determines whether the supplied messages are equal. Equality is defined as
 | 
						|
  // all fields within the two messages being set to the same value. Primitive
 | 
						|
  // fields and strings are compared by value while embedded messages/groups
 | 
						|
  // are compared as if via a recursive call. Use Compare() with IgnoreField()
 | 
						|
  // if some fields should be ignored in the comparison. Use Compare() with
 | 
						|
  // TreatAsSet() if there are repeated fields where ordering does not matter.
 | 
						|
  //
 | 
						|
  // This method REQUIRES that the two messages have the same
 | 
						|
  // Descriptor (message1.GetDescriptor() == message2.GetDescriptor()).
 | 
						|
  static bool Equals(const Message& message1, const Message& message2);
 | 
						|
 | 
						|
  // Determines whether the supplied messages are equivalent. Equivalency is
 | 
						|
  // defined as all fields within the two messages having the same value. This
 | 
						|
  // differs from the Equals method above in that fields with default values
 | 
						|
  // are considered set to said value automatically. For details on how default
 | 
						|
  // values are defined for each field type, see:
 | 
						|
  // https://developers.google.com/protocol-buffers/docs/proto?csw=1#optional.
 | 
						|
  // Also, Equivalent() ignores unknown fields. Use IgnoreField() and Compare()
 | 
						|
  // if some fields should be ignored in the comparison.
 | 
						|
  //
 | 
						|
  // This method REQUIRES that the two messages have the same
 | 
						|
  // Descriptor (message1.GetDescriptor() == message2.GetDescriptor()).
 | 
						|
  static bool Equivalent(const Message& message1, const Message& message2);
 | 
						|
 | 
						|
  // Determines whether the supplied messages are approximately equal.
 | 
						|
  // Approximate equality is defined as all fields within the two messages
 | 
						|
  // being approximately equal.  Primitive (non-float) fields and strings are
 | 
						|
  // compared by value, floats are compared using MathUtil::AlmostEquals() and
 | 
						|
  // embedded messages/groups are compared as if via a recursive call. Use
 | 
						|
  // IgnoreField() and Compare() if some fields should be ignored in the
 | 
						|
  // comparison.
 | 
						|
  //
 | 
						|
  // This method REQUIRES that the two messages have the same
 | 
						|
  // Descriptor (message1.GetDescriptor() == message2.GetDescriptor()).
 | 
						|
  static bool ApproximatelyEquals(const Message& message1,
 | 
						|
                                  const Message& message2);
 | 
						|
 | 
						|
  // Determines whether the supplied messages are approximately equivalent.
 | 
						|
  // Approximate equivalency is defined as all fields within the two messages
 | 
						|
  // being approximately equivalent. As in
 | 
						|
  // MessageDifferencer::ApproximatelyEquals, primitive (non-float) fields and
 | 
						|
  // strings are compared by value, floats are compared using
 | 
						|
  // MathUtil::AlmostEquals() and embedded messages/groups are compared as if
 | 
						|
  // via a recursive call. However, fields with default values are considered
 | 
						|
  // set to said value, as per MessageDiffencer::Equivalent. Use IgnoreField()
 | 
						|
  // and Compare() if some fields should be ignored in the comparison.
 | 
						|
  //
 | 
						|
  // This method REQUIRES that the two messages have the same
 | 
						|
  // Descriptor (message1.GetDescriptor() == message2.GetDescriptor()).
 | 
						|
  static bool ApproximatelyEquivalent(const Message& message1,
 | 
						|
                                      const Message& message2);
 | 
						|
 | 
						|
  // Identifies an individual field in a message instance.  Used for field_path,
 | 
						|
  // below.
 | 
						|
  struct SpecificField {
 | 
						|
    // For known fields, "field" is filled in and "unknown_field_number" is -1.
 | 
						|
    // For unknown fields, "field" is NULL, "unknown_field_number" is the field
 | 
						|
    // number, and "unknown_field_type" is its type.
 | 
						|
    const FieldDescriptor* field = nullptr;
 | 
						|
    int unknown_field_number = -1;
 | 
						|
    UnknownField::Type unknown_field_type = UnknownField::Type::TYPE_VARINT;
 | 
						|
 | 
						|
    // If this a repeated field, "index" is the index within it.  For unknown
 | 
						|
    // fields, this is the index of the field among all unknown fields of the
 | 
						|
    // same field number and type.
 | 
						|
    int index = -1;
 | 
						|
 | 
						|
    // If "field" is a repeated field which is being treated as a map or
 | 
						|
    // a set (see TreatAsMap() and TreatAsSet(), below), new_index indicates
 | 
						|
    // the index the position to which the element has moved.  If the element
 | 
						|
    // has not moved, "new_index" will have the same value as "index".
 | 
						|
    int new_index = -1;
 | 
						|
 | 
						|
    // If "field" is a map field, point to the map entry.
 | 
						|
    const Message* map_entry1 = nullptr;
 | 
						|
    const Message* map_entry2 = nullptr;
 | 
						|
 | 
						|
    // For unknown fields, these are the pointers to the UnknownFieldSet
 | 
						|
    // containing the unknown fields. In certain cases (e.g. proto1's
 | 
						|
    // MessageSet, or nested groups of unknown fields), these may differ from
 | 
						|
    // the messages' internal UnknownFieldSets.
 | 
						|
    const UnknownFieldSet* unknown_field_set1 = nullptr;
 | 
						|
    const UnknownFieldSet* unknown_field_set2 = nullptr;
 | 
						|
 | 
						|
    // For unknown fields, these are the index of the field within the
 | 
						|
    // UnknownFieldSets. One or the other will be -1 when
 | 
						|
    // reporting an addition or deletion.
 | 
						|
    int unknown_field_index1 = -1;
 | 
						|
    int unknown_field_index2 = -1;
 | 
						|
  };
 | 
						|
 | 
						|
  // Class for processing Any deserialization.  This logic is used by both the
 | 
						|
  // MessageDifferencer and StreamReporter classes.
 | 
						|
  class UnpackAnyField {
 | 
						|
   private:
 | 
						|
    std::unique_ptr<DynamicMessageFactory> dynamic_message_factory_;
 | 
						|
 | 
						|
   public:
 | 
						|
    UnpackAnyField() = default;
 | 
						|
    ~UnpackAnyField() = default;
 | 
						|
    // If "any" is of type google.protobuf.Any, extract its payload using
 | 
						|
    // DynamicMessageFactory and store in "data".
 | 
						|
    bool UnpackAny(const Message& any, std::unique_ptr<Message>* data);
 | 
						|
  };
 | 
						|
 | 
						|
  // Abstract base class from which all MessageDifferencer
 | 
						|
  // reporters derive. The five Report* methods below will be called when
 | 
						|
  // a field has been added, deleted, modified, moved, or matched. The third
 | 
						|
  // argument is a vector of FieldDescriptor pointers which describes the chain
 | 
						|
  // of fields that was taken to find the current field. For example, for a
 | 
						|
  // field found in an embedded message, the vector will contain two
 | 
						|
  // FieldDescriptors. The first will be the field of the embedded message
 | 
						|
  // itself and the second will be the actual field in the embedded message
 | 
						|
  // that was added/deleted/modified.
 | 
						|
  // Fields will be reported in PostTraversalOrder.
 | 
						|
  // For example, given following proto, if both baz and quux are changed.
 | 
						|
  // foo {
 | 
						|
  //   bar {
 | 
						|
  //     baz: 1
 | 
						|
  //     quux: 2
 | 
						|
  //   }
 | 
						|
  // }
 | 
						|
  // ReportModified will be invoked with following order:
 | 
						|
  // 1. foo.bar.baz or foo.bar.quux
 | 
						|
  // 2. foo.bar.quux or foo.bar.baz
 | 
						|
  // 2. foo.bar
 | 
						|
  // 3. foo
 | 
						|
  class PROTOBUF_EXPORT Reporter {
 | 
						|
   public:
 | 
						|
    Reporter();
 | 
						|
    virtual ~Reporter();
 | 
						|
 | 
						|
    // Reports that a field has been added into Message2.
 | 
						|
    virtual void ReportAdded(const Message& message1, const Message& message2,
 | 
						|
                             const std::vector<SpecificField>& field_path) = 0;
 | 
						|
 | 
						|
    // Reports that a field has been deleted from Message1.
 | 
						|
    virtual void ReportDeleted(
 | 
						|
        const Message& message1, const Message& message2,
 | 
						|
        const std::vector<SpecificField>& field_path) = 0;
 | 
						|
 | 
						|
    // Reports that the value of a field has been modified.
 | 
						|
    virtual void ReportModified(
 | 
						|
        const Message& message1, const Message& message2,
 | 
						|
        const std::vector<SpecificField>& field_path) = 0;
 | 
						|
 | 
						|
    // Reports that a repeated field has been moved to another location.  This
 | 
						|
    // only applies when using TreatAsSet or TreatAsMap()  -- see below. Also
 | 
						|
    // note that for any given field, ReportModified and ReportMoved are
 | 
						|
    // mutually exclusive. If a field has been both moved and modified, then
 | 
						|
    // only ReportModified will be called.
 | 
						|
    virtual void ReportMoved(
 | 
						|
        const Message& /* message1 */, const Message& /* message2 */,
 | 
						|
        const std::vector<SpecificField>& /* field_path */) {}
 | 
						|
 | 
						|
    // Reports that two fields match. Useful for doing side-by-side diffs.
 | 
						|
    // This function is mutually exclusive with ReportModified and ReportMoved.
 | 
						|
    // Note that you must call set_report_matches(true) before calling Compare
 | 
						|
    // to make use of this function.
 | 
						|
    virtual void ReportMatched(
 | 
						|
        const Message& /* message1 */, const Message& /* message2 */,
 | 
						|
        const std::vector<SpecificField>& /* field_path */) {}
 | 
						|
 | 
						|
    // Reports that two fields would have been compared, but the
 | 
						|
    // comparison has been skipped because the field was marked as
 | 
						|
    // 'ignored' using IgnoreField().  This function is mutually
 | 
						|
    // exclusive with all the other Report() functions.
 | 
						|
    //
 | 
						|
    // The contract of ReportIgnored is slightly different than the
 | 
						|
    // other Report() functions, in that |field_path.back().index| is
 | 
						|
    // always equal to -1, even if the last field is repeated. This is
 | 
						|
    // because while the other Report() functions indicate where in a
 | 
						|
    // repeated field the action (Addition, Deletion, etc...)
 | 
						|
    // happened, when a repeated field is 'ignored', the differencer
 | 
						|
    // simply calls ReportIgnored on the repeated field as a whole and
 | 
						|
    // moves on without looking at its individual elements.
 | 
						|
    //
 | 
						|
    // Furthermore, ReportIgnored() does not indicate whether the
 | 
						|
    // fields were in fact equal or not, as Compare() does not inspect
 | 
						|
    // these fields at all. It is up to the Reporter to decide whether
 | 
						|
    // the fields are equal or not (perhaps with a second call to
 | 
						|
    // Compare()), if it cares.
 | 
						|
    virtual void ReportIgnored(
 | 
						|
        const Message& /* message1 */, const Message& /* message2 */,
 | 
						|
        const std::vector<SpecificField>& /* field_path */) {}
 | 
						|
 | 
						|
    // Report that an unknown field is ignored. (see comment above).
 | 
						|
    // Note this is a different function since the last SpecificField in field
 | 
						|
    // path has a null field.  This could break existing Reporter.
 | 
						|
    virtual void ReportUnknownFieldIgnored(
 | 
						|
        const Message& /* message1 */, const Message& /* message2 */,
 | 
						|
        const std::vector<SpecificField>& /* field_path */) {}
 | 
						|
 | 
						|
   private:
 | 
						|
    GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Reporter);
 | 
						|
  };
 | 
						|
 | 
						|
  // MapKeyComparator is used to determine if two elements have the same key
 | 
						|
  // when comparing elements of a repeated field as a map.
 | 
						|
  class PROTOBUF_EXPORT MapKeyComparator {
 | 
						|
   public:
 | 
						|
    MapKeyComparator();
 | 
						|
    virtual ~MapKeyComparator();
 | 
						|
 | 
						|
    virtual bool IsMatch(
 | 
						|
        const Message& /* message1 */, const Message& /* message2 */,
 | 
						|
        const std::vector<SpecificField>& /* parent_fields */) const {
 | 
						|
      GOOGLE_CHECK(false) << "IsMatch() is not implemented.";
 | 
						|
      return false;
 | 
						|
    }
 | 
						|
 | 
						|
   private:
 | 
						|
    GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapKeyComparator);
 | 
						|
  };
 | 
						|
 | 
						|
  // Abstract base class from which all IgnoreCriteria derive.
 | 
						|
  // By adding IgnoreCriteria more complex ignore logic can be implemented.
 | 
						|
  // IgnoreCriteria are registered with AddIgnoreCriteria. For each compared
 | 
						|
  // field IsIgnored is called on each added IgnoreCriteria until one returns
 | 
						|
  // true or all return false.
 | 
						|
  // IsIgnored is called for fields where at least one side has a value.
 | 
						|
  class PROTOBUF_EXPORT IgnoreCriteria {
 | 
						|
   public:
 | 
						|
    IgnoreCriteria();
 | 
						|
    virtual ~IgnoreCriteria();
 | 
						|
 | 
						|
    // Returns true if the field should be ignored.
 | 
						|
    virtual bool IsIgnored(
 | 
						|
        const Message& /* message1 */, const Message& /* message2 */,
 | 
						|
        const FieldDescriptor* /* field */,
 | 
						|
        const std::vector<SpecificField>& /* parent_fields */) = 0;
 | 
						|
 | 
						|
    // Returns true if the unknown field should be ignored.
 | 
						|
    // Note: This will be called for unknown fields as well in which case
 | 
						|
    //       field.field will be null.
 | 
						|
    virtual bool IsUnknownFieldIgnored(
 | 
						|
        const Message& /* message1 */, const Message& /* message2 */,
 | 
						|
        const SpecificField& /* field */,
 | 
						|
        const std::vector<SpecificField>& /* parent_fields */) {
 | 
						|
      return false;
 | 
						|
    }
 | 
						|
  };
 | 
						|
 | 
						|
  // To add a Reporter, construct default here, then use ReportDifferencesTo or
 | 
						|
  // ReportDifferencesToString.
 | 
						|
  explicit MessageDifferencer();
 | 
						|
 | 
						|
  ~MessageDifferencer();
 | 
						|
 | 
						|
  enum MessageFieldComparison {
 | 
						|
    EQUAL,       // Fields must be present in both messages
 | 
						|
                 // for the messages to be considered the same.
 | 
						|
    EQUIVALENT,  // Fields with default values are considered set
 | 
						|
                 // for comparison purposes even if not explicitly
 | 
						|
                 // set in the messages themselves.  Unknown fields
 | 
						|
                 // are ignored.
 | 
						|
  };
 | 
						|
 | 
						|
  enum Scope {
 | 
						|
    FULL,    // All fields of both messages are considered in the comparison.
 | 
						|
    PARTIAL  // Only fields present in the first message are considered; fields
 | 
						|
             // set only in the second message will be skipped during
 | 
						|
             // comparison.
 | 
						|
  };
 | 
						|
 | 
						|
  // DEPRECATED. Use FieldComparator::FloatComparison instead.
 | 
						|
  enum FloatComparison {
 | 
						|
    EXACT,       // Floats and doubles are compared exactly.
 | 
						|
    APPROXIMATE  // Floats and doubles are compared using the
 | 
						|
                 // MathUtil::AlmostEquals method.
 | 
						|
  };
 | 
						|
 | 
						|
  enum RepeatedFieldComparison {
 | 
						|
    AS_LIST,  // Repeated fields are compared in order.  Differing values at
 | 
						|
              // the same index are reported using ReportModified().  If the
 | 
						|
              // repeated fields have different numbers of elements, the
 | 
						|
              // unpaired elements are reported using ReportAdded() or
 | 
						|
              // ReportDeleted().
 | 
						|
    AS_SET,   // Treat all the repeated fields as sets.
 | 
						|
              // See TreatAsSet(), as below.
 | 
						|
    AS_SMART_LIST,  // Similar to AS_SET, but preserve the order and find the
 | 
						|
                    // longest matching sequence from the first matching
 | 
						|
                    // element. To use an optimal solution, call
 | 
						|
                    // SetMatchIndicesForSmartListCallback() to pass it in.
 | 
						|
    AS_SMART_SET,   // Similar to AS_SET, but match elements with fewest diffs.
 | 
						|
  };
 | 
						|
 | 
						|
  // The elements of the given repeated field will be treated as a set for
 | 
						|
  // diffing purposes, so different orderings of the same elements will be
 | 
						|
  // considered equal.  Elements which are present on both sides of the
 | 
						|
  // comparison but which have changed position will be reported with
 | 
						|
  // ReportMoved().  Elements which only exist on one side or the other are
 | 
						|
  // reported with ReportAdded() and ReportDeleted() regardless of their
 | 
						|
  // positions.  ReportModified() is never used for this repeated field.  If
 | 
						|
  // the only differences between the compared messages is that some fields
 | 
						|
  // have been moved, then the comparison returns true.
 | 
						|
  //
 | 
						|
  // Note that despite the name of this method, this is really
 | 
						|
  // comparison as multisets: if one side of the comparison has a duplicate
 | 
						|
  // in the repeated field but the other side doesn't, this will count as
 | 
						|
  // a mismatch.
 | 
						|
  //
 | 
						|
  // If the scope of comparison is set to PARTIAL, then in addition to what's
 | 
						|
  // above, extra values added to repeated fields of the second message will
 | 
						|
  // not cause the comparison to fail.
 | 
						|
  //
 | 
						|
  // Note that set comparison is currently O(k * n^2) (where n is the total
 | 
						|
  // number of elements, and k is the average size of each element). In theory
 | 
						|
  // it could be made O(n * k) with a more complex hashing implementation. Feel
 | 
						|
  // free to contribute one if the current implementation is too slow for you.
 | 
						|
  // If partial matching is also enabled, the time complexity will be O(k * n^2
 | 
						|
  // + n^3) in which n^3 is the time complexity of the maximum matching
 | 
						|
  // algorithm.
 | 
						|
  //
 | 
						|
  // REQUIRES: field->is_repeated() and field not registered with TreatAsMap*
 | 
						|
  void TreatAsSet(const FieldDescriptor* field);
 | 
						|
  void TreatAsSmartSet(const FieldDescriptor* field);
 | 
						|
 | 
						|
  // The elements of the given repeated field will be treated as a list for
 | 
						|
  // diffing purposes, so different orderings of the same elements will NOT be
 | 
						|
  // considered equal.
 | 
						|
  //
 | 
						|
  // REQUIRES: field->is_repeated() and field not registered with TreatAsMap*
 | 
						|
  void TreatAsList(const FieldDescriptor* field);
 | 
						|
  // Note that the complexity is similar to treating as SET.
 | 
						|
  void TreatAsSmartList(const FieldDescriptor* field);
 | 
						|
 | 
						|
  // The elements of the given repeated field will be treated as a map for
 | 
						|
  // diffing purposes, with |key| being the map key.  Thus, elements with the
 | 
						|
  // same key will be compared even if they do not appear at the same index.
 | 
						|
  // Differences are reported similarly to TreatAsSet(), except that
 | 
						|
  // ReportModified() is used to report elements with the same key but
 | 
						|
  // different values.  Note that if an element is both moved and modified,
 | 
						|
  // only ReportModified() will be called.  As with TreatAsSet, if the only
 | 
						|
  // differences between the compared messages is that some fields have been
 | 
						|
  // moved, then the comparison returns true. See TreatAsSet for notes on
 | 
						|
  // performance.
 | 
						|
  //
 | 
						|
  // REQUIRES:  field->is_repeated()
 | 
						|
  // REQUIRES:  field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE
 | 
						|
  // REQUIRES:  key->containing_type() == field->message_type()
 | 
						|
  void TreatAsMap(const FieldDescriptor* field, const FieldDescriptor* key);
 | 
						|
  // Same as TreatAsMap except that this method will use multiple fields as
 | 
						|
  // the key in comparison. All specified fields in 'key_fields' should be
 | 
						|
  // present in the compared elements. Two elements will be treated as having
 | 
						|
  // the same key iff they have the same value for every specified field. There
 | 
						|
  // are two steps in the comparison process. The first one is key matching.
 | 
						|
  // Every element from one message will be compared to every element from
 | 
						|
  // the other message. Only fields in 'key_fields' are compared in this step
 | 
						|
  // to decide if two elements have the same key. The second step is value
 | 
						|
  // comparison. Those pairs of elements with the same key (with equal value
 | 
						|
  // for every field in 'key_fields') will be compared in this step.
 | 
						|
  // Time complexity of the first step is O(s * m * n ^ 2) where s is the
 | 
						|
  // average size of the fields specified in 'key_fields', m is the number of
 | 
						|
  // fields in 'key_fields' and n is the number of elements. If partial
 | 
						|
  // matching is enabled, an extra O(n^3) will be incured by the maximum
 | 
						|
  // matching algorithm. The second step is O(k * n) where k is the average
 | 
						|
  // size of each element.
 | 
						|
  void TreatAsMapWithMultipleFieldsAsKey(
 | 
						|
      const FieldDescriptor* field,
 | 
						|
      const std::vector<const FieldDescriptor*>& key_fields);
 | 
						|
  // Same as TreatAsMapWithMultipleFieldsAsKey, except that each of the field
 | 
						|
  // do not necessarily need to be a direct subfield. Each element in
 | 
						|
  // key_field_paths indicate a path from the message being compared, listing
 | 
						|
  // successive subfield to reach the key field.
 | 
						|
  //
 | 
						|
  // REQUIRES:
 | 
						|
  //   for key_field_path in key_field_paths:
 | 
						|
  //     key_field_path[0]->containing_type() == field->message_type()
 | 
						|
  //     for i in [0, key_field_path.size() - 1):
 | 
						|
  //       key_field_path[i+1]->containing_type() ==
 | 
						|
  //           key_field_path[i]->message_type()
 | 
						|
  //       key_field_path[i]->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE
 | 
						|
  //       !key_field_path[i]->is_repeated()
 | 
						|
  void TreatAsMapWithMultipleFieldPathsAsKey(
 | 
						|
      const FieldDescriptor* field,
 | 
						|
      const std::vector<std::vector<const FieldDescriptor*> >& key_field_paths);
 | 
						|
 | 
						|
  // Uses a custom MapKeyComparator to determine if two elements have the same
 | 
						|
  // key when comparing a repeated field as a map.
 | 
						|
  // The caller is responsible to delete the key_comparator.
 | 
						|
  // This method varies from TreatAsMapWithMultipleFieldsAsKey only in the
 | 
						|
  // first key matching step. Rather than comparing some specified fields, it
 | 
						|
  // will invoke the IsMatch method of the given 'key_comparator' to decide if
 | 
						|
  // two elements have the same key.
 | 
						|
  void TreatAsMapUsingKeyComparator(const FieldDescriptor* field,
 | 
						|
                                    const MapKeyComparator* key_comparator);
 | 
						|
 | 
						|
  // Initiates and returns a new instance of MultipleFieldsMapKeyComparator.
 | 
						|
  MapKeyComparator* CreateMultipleFieldsMapKeyComparator(
 | 
						|
      const std::vector<std::vector<const FieldDescriptor*> >& key_field_paths);
 | 
						|
 | 
						|
  // Add a custom ignore criteria that is evaluated in addition to the
 | 
						|
  // ignored fields added with IgnoreField.
 | 
						|
  // Takes ownership of ignore_criteria.
 | 
						|
  void AddIgnoreCriteria(IgnoreCriteria* ignore_criteria);
 | 
						|
 | 
						|
  // Indicates that any field with the given descriptor should be
 | 
						|
  // ignored for the purposes of comparing two messages. This applies
 | 
						|
  // to fields nested in the message structure as well as top level
 | 
						|
  // ones. When the MessageDifferencer encounters an ignored field,
 | 
						|
  // ReportIgnored is called on the reporter, if one is specified.
 | 
						|
  //
 | 
						|
  // The only place where the field's 'ignored' status is not applied is when
 | 
						|
  // it is being used as a key in a field passed to TreatAsMap or is one of
 | 
						|
  // the fields passed to TreatAsMapWithMultipleFieldsAsKey.
 | 
						|
  // In this case it is compared in key matching but after that it's ignored
 | 
						|
  // in value comparison.
 | 
						|
  void IgnoreField(const FieldDescriptor* field);
 | 
						|
 | 
						|
  // Sets the field comparator used to determine differences between protocol
 | 
						|
  // buffer fields. By default it's set to a DefaultFieldComparator instance.
 | 
						|
  // MessageDifferencer doesn't take ownership over the passed object.
 | 
						|
  // Note that this method must be called before Compare for the comparator to
 | 
						|
  // be used.
 | 
						|
  void set_field_comparator(FieldComparator* comparator);
 | 
						|
#ifdef PROTOBUF_FUTURE_BREAKING_CHANGES
 | 
						|
  void set_field_comparator(DefaultFieldComparator* comparator);
 | 
						|
#endif  // PROTOBUF_FUTURE_BREAKING_CHANGES
 | 
						|
 | 
						|
  // DEPRECATED. Pass a DefaultFieldComparator instance instead.
 | 
						|
  // Sets the fraction and margin for the float comparison of a given field.
 | 
						|
  // Uses MathUtil::WithinFractionOrMargin to compare the values.
 | 
						|
  // NOTE: this method does nothing if differencer's field comparator has been
 | 
						|
  //       set to a custom object.
 | 
						|
  //
 | 
						|
  // REQUIRES: field->cpp_type == FieldDescriptor::CPPTYPE_DOUBLE or
 | 
						|
  //           field->cpp_type == FieldDescriptor::CPPTYPE_FLOAT
 | 
						|
  // REQUIRES: float_comparison_ == APPROXIMATE
 | 
						|
  void SetFractionAndMargin(const FieldDescriptor* field, double fraction,
 | 
						|
                            double margin);
 | 
						|
 | 
						|
  // Sets the type of comparison (as defined in the MessageFieldComparison
 | 
						|
  // enumeration above) that is used by this differencer when determining how
 | 
						|
  // to compare fields in messages.
 | 
						|
  void set_message_field_comparison(MessageFieldComparison comparison);
 | 
						|
 | 
						|
  // Tells the differencer whether or not to report matches. This method must
 | 
						|
  // be called before Compare. The default for a new differencer is false.
 | 
						|
  void set_report_matches(bool report_matches) {
 | 
						|
    report_matches_ = report_matches;
 | 
						|
  }
 | 
						|
 | 
						|
  // Tells the differencer whether or not to report moves (in a set or map
 | 
						|
  // repeated field). This method must be called before Compare. The default for
 | 
						|
  // a new differencer is true.
 | 
						|
  void set_report_moves(bool report_moves) { report_moves_ = report_moves; }
 | 
						|
 | 
						|
  // Tells the differencer whether or not to report ignored values. This method
 | 
						|
  // must be called before Compare. The default for a new differencer is true.
 | 
						|
  void set_report_ignores(bool report_ignores) {
 | 
						|
    report_ignores_ = report_ignores;
 | 
						|
  }
 | 
						|
 | 
						|
  // Sets the scope of the comparison (as defined in the Scope enumeration
 | 
						|
  // above) that is used by this differencer when determining which fields to
 | 
						|
  // compare between the messages.
 | 
						|
  void set_scope(Scope scope);
 | 
						|
 | 
						|
  // Returns the current scope used by this differencer.
 | 
						|
  Scope scope();
 | 
						|
 | 
						|
  // DEPRECATED. Pass a DefaultFieldComparator instance instead.
 | 
						|
  // Sets the type of comparison (as defined in the FloatComparison enumeration
 | 
						|
  // above) that is used by this differencer when comparing float (and double)
 | 
						|
  // fields in messages.
 | 
						|
  // NOTE: this method does nothing if differencer's field comparator has been
 | 
						|
  //       set to a custom object.
 | 
						|
  void set_float_comparison(FloatComparison comparison);
 | 
						|
 | 
						|
  // Sets the type of comparison for repeated field (as defined in the
 | 
						|
  // RepeatedFieldComparison enumeration above) that is used by this
 | 
						|
  // differencer when compare repeated fields in messages.
 | 
						|
  void set_repeated_field_comparison(RepeatedFieldComparison comparison);
 | 
						|
 | 
						|
  // Returns the current repeated field comparison used by this differencer.
 | 
						|
  RepeatedFieldComparison repeated_field_comparison();
 | 
						|
 | 
						|
  // Compares the two specified messages, returning true if they are the same,
 | 
						|
  // false otherwise. If this method returns false, any changes between the
 | 
						|
  // two messages will be reported if a Reporter was specified via
 | 
						|
  // ReportDifferencesTo (see also ReportDifferencesToString).
 | 
						|
  //
 | 
						|
  // This method REQUIRES that the two messages have the same
 | 
						|
  // Descriptor (message1.GetDescriptor() == message2.GetDescriptor()).
 | 
						|
  bool Compare(const Message& message1, const Message& message2);
 | 
						|
 | 
						|
  // Same as above, except comparing only the list of fields specified by the
 | 
						|
  // two vectors of FieldDescriptors.
 | 
						|
  bool CompareWithFields(
 | 
						|
      const Message& message1, const Message& message2,
 | 
						|
      const std::vector<const FieldDescriptor*>& message1_fields,
 | 
						|
      const std::vector<const FieldDescriptor*>& message2_fields);
 | 
						|
 | 
						|
  // Automatically creates a reporter that will output the differences
 | 
						|
  // found (if any) to the specified output string pointer. Note that this
 | 
						|
  // method must be called before Compare.
 | 
						|
  void ReportDifferencesToString(std::string* output);
 | 
						|
 | 
						|
  // Tells the MessageDifferencer to report differences via the specified
 | 
						|
  // reporter. Note that this method must be called before Compare for
 | 
						|
  // the reporter to be used. It is the responsibility of the caller to delete
 | 
						|
  // this object.
 | 
						|
  // If the provided pointer equals NULL, the MessageDifferencer stops reporting
 | 
						|
  // differences to any previously set reporters or output strings.
 | 
						|
  void ReportDifferencesTo(Reporter* reporter);
 | 
						|
 | 
						|
  // An implementation of the MessageDifferencer Reporter that outputs
 | 
						|
  // any differences found in human-readable form to the supplied
 | 
						|
  // ZeroCopyOutputStream or Printer. If a printer is used, the delimiter
 | 
						|
  // *must* be '$'.
 | 
						|
  //
 | 
						|
  // WARNING: this reporter does not necessarily flush its output until it is
 | 
						|
  // destroyed. As a result, it is not safe to assume the output is valid or
 | 
						|
  // complete until after you destroy the reporter. For example, if you use a
 | 
						|
  // StreamReporter to write to a StringOutputStream, the target string may
 | 
						|
  // contain uninitialized data until the reporter is destroyed.
 | 
						|
  class PROTOBUF_EXPORT StreamReporter : public Reporter {
 | 
						|
   public:
 | 
						|
    explicit StreamReporter(io::ZeroCopyOutputStream* output);
 | 
						|
    explicit StreamReporter(io::Printer* printer);  // delimiter '$'
 | 
						|
    ~StreamReporter() override;
 | 
						|
 | 
						|
    // When set to true, the stream reporter will also output aggregates nodes
 | 
						|
    // (i.e. messages and groups) whose subfields have been modified. When
 | 
						|
    // false, will only report the individual subfields. Defaults to false.
 | 
						|
    void set_report_modified_aggregates(bool report) {
 | 
						|
      report_modified_aggregates_ = report;
 | 
						|
    }
 | 
						|
 | 
						|
    // The following are implementations of the methods described above.
 | 
						|
 | 
						|
    void ReportAdded(const Message& message1, const Message& message2,
 | 
						|
                     const std::vector<SpecificField>& field_path) override;
 | 
						|
 | 
						|
    void ReportDeleted(const Message& message1, const Message& message2,
 | 
						|
                       const std::vector<SpecificField>& field_path) override;
 | 
						|
 | 
						|
    void ReportModified(const Message& message1, const Message& message2,
 | 
						|
                        const std::vector<SpecificField>& field_path) override;
 | 
						|
 | 
						|
    void ReportMoved(const Message& message1, const Message& message2,
 | 
						|
                     const std::vector<SpecificField>& field_path) override;
 | 
						|
 | 
						|
    void ReportMatched(const Message& message1, const Message& message2,
 | 
						|
                       const std::vector<SpecificField>& field_path) override;
 | 
						|
 | 
						|
    void ReportIgnored(const Message& message1, const Message& message2,
 | 
						|
                       const std::vector<SpecificField>& field_path) override;
 | 
						|
 | 
						|
    void ReportUnknownFieldIgnored(
 | 
						|
        const Message& message1, const Message& message2,
 | 
						|
        const std::vector<SpecificField>& field_path) override;
 | 
						|
 | 
						|
    // Messages that are being compared must be provided to StreamReporter prior
 | 
						|
    // to processing
 | 
						|
    void SetMessages(const Message& message1, const Message& message2);
 | 
						|
 | 
						|
   protected:
 | 
						|
    // Prints the specified path of fields to the buffer.
 | 
						|
    virtual void PrintPath(const std::vector<SpecificField>& field_path,
 | 
						|
                           bool left_side);
 | 
						|
 | 
						|
    // Prints the value of fields to the buffer.  left_side is true if the
 | 
						|
    // given message is from the left side of the comparison, false if it
 | 
						|
    // was the right.  This is relevant only to decide whether to follow
 | 
						|
    // unknown_field_index1 or unknown_field_index2 when an unknown field
 | 
						|
    // is encountered in field_path.
 | 
						|
    virtual void PrintValue(const Message& message,
 | 
						|
                            const std::vector<SpecificField>& field_path,
 | 
						|
                            bool left_side);
 | 
						|
 | 
						|
    // Prints the specified path of unknown fields to the buffer.
 | 
						|
    virtual void PrintUnknownFieldValue(const UnknownField* unknown_field);
 | 
						|
 | 
						|
    // Just print a string
 | 
						|
    void Print(const std::string& str);
 | 
						|
 | 
						|
   private:
 | 
						|
    // helper function for PrintPath that contains logic for printing maps
 | 
						|
    void PrintMapKey(bool left_side, const SpecificField& specific_field);
 | 
						|
 | 
						|
    io::Printer* printer_;
 | 
						|
    bool delete_printer_;
 | 
						|
    bool report_modified_aggregates_;
 | 
						|
    const Message* message1_;
 | 
						|
    const Message* message2_;
 | 
						|
    MessageDifferencer::UnpackAnyField unpack_any_field_;
 | 
						|
    GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StreamReporter);
 | 
						|
  };
 | 
						|
 | 
						|
 private:
 | 
						|
  friend class SimpleFieldComparator;
 | 
						|
 | 
						|
  // A MapKeyComparator to be used in TreatAsMapUsingKeyComparator.
 | 
						|
  // Implementation of this class needs to do field value comparison which
 | 
						|
  // relies on some private methods of MessageDifferencer. That's why this
 | 
						|
  // class is declared as a nested class of MessageDifferencer.
 | 
						|
  class MultipleFieldsMapKeyComparator;
 | 
						|
 | 
						|
  // A MapKeyComparator for use with map_entries.
 | 
						|
  class PROTOBUF_EXPORT MapEntryKeyComparator : public MapKeyComparator {
 | 
						|
   public:
 | 
						|
    explicit MapEntryKeyComparator(MessageDifferencer* message_differencer);
 | 
						|
    bool IsMatch(
 | 
						|
        const Message& message1, const Message& message2,
 | 
						|
        const std::vector<SpecificField>& parent_fields) const override;
 | 
						|
 | 
						|
   private:
 | 
						|
    MessageDifferencer* message_differencer_;
 | 
						|
  };
 | 
						|
 | 
						|
  // Returns true if field1's number() is less than field2's.
 | 
						|
  static bool FieldBefore(const FieldDescriptor* field1,
 | 
						|
                          const FieldDescriptor* field2);
 | 
						|
 | 
						|
  // Retrieve all the set fields, including extensions.
 | 
						|
  FieldDescriptorArray RetrieveFields(const Message& message,
 | 
						|
                                      bool base_message);
 | 
						|
 | 
						|
  // Combine the two lists of fields into the combined_fields output vector.
 | 
						|
  // All fields present in both lists will always be included in the combined
 | 
						|
  // list.  Fields only present in one of the lists will only appear in the
 | 
						|
  // combined list if the corresponding fields_scope option is set to FULL.
 | 
						|
  FieldDescriptorArray CombineFields(const FieldDescriptorArray& fields1,
 | 
						|
                                     Scope fields1_scope,
 | 
						|
                                     const FieldDescriptorArray& fields2,
 | 
						|
                                     Scope fields2_scope);
 | 
						|
 | 
						|
  // Internal version of the Compare method which performs the actual
 | 
						|
  // comparison. The parent_fields vector is a vector containing field
 | 
						|
  // descriptors of all fields accessed to get to this comparison operation
 | 
						|
  // (i.e. if the current message is an embedded message, the parent_fields
 | 
						|
  // vector will contain the field that has this embedded message).
 | 
						|
  bool Compare(const Message& message1, const Message& message2,
 | 
						|
               std::vector<SpecificField>* parent_fields);
 | 
						|
 | 
						|
  // Compares all the unknown fields in two messages.
 | 
						|
  bool CompareUnknownFields(const Message& message1, const Message& message2,
 | 
						|
                            const UnknownFieldSet&, const UnknownFieldSet&,
 | 
						|
                            std::vector<SpecificField>* parent_fields);
 | 
						|
 | 
						|
  // Compares the specified messages for the requested field lists. The field
 | 
						|
  // lists are modified depending on comparison settings, and then passed to
 | 
						|
  // CompareWithFieldsInternal.
 | 
						|
  bool CompareRequestedFieldsUsingSettings(
 | 
						|
      const Message& message1, const Message& message2,
 | 
						|
      const FieldDescriptorArray& message1_fields,
 | 
						|
      const FieldDescriptorArray& message2_fields,
 | 
						|
      std::vector<SpecificField>* parent_fields);
 | 
						|
 | 
						|
  // Compares the specified messages with the specified field lists.
 | 
						|
  bool CompareWithFieldsInternal(const Message& message1,
 | 
						|
                                 const Message& message2,
 | 
						|
                                 const FieldDescriptorArray& message1_fields,
 | 
						|
                                 const FieldDescriptorArray& message2_fields,
 | 
						|
                                 std::vector<SpecificField>* parent_fields);
 | 
						|
 | 
						|
  // Compares the repeated fields, and report the error.
 | 
						|
  bool CompareRepeatedField(const Message& message1, const Message& message2,
 | 
						|
                            const FieldDescriptor* field,
 | 
						|
                            std::vector<SpecificField>* parent_fields);
 | 
						|
 | 
						|
  // Compares map fields, and report the error.
 | 
						|
  bool CompareMapField(const Message& message1, const Message& message2,
 | 
						|
                       const FieldDescriptor* field,
 | 
						|
                       std::vector<SpecificField>* parent_fields);
 | 
						|
 | 
						|
  // Helper for CompareRepeatedField and CompareMapField: compares and reports
 | 
						|
  // differences element-wise. This is the implementation for non-map fields,
 | 
						|
  // and can also compare map fields by using the underlying representation.
 | 
						|
  bool CompareRepeatedRep(const Message& message1, const Message& message2,
 | 
						|
                          const FieldDescriptor* field,
 | 
						|
                          std::vector<SpecificField>* parent_fields);
 | 
						|
 | 
						|
  // Helper for CompareMapField: compare the map fields using map reflection
 | 
						|
  // instead of sync to repeated.
 | 
						|
  bool CompareMapFieldByMapReflection(const Message& message1,
 | 
						|
                                      const Message& message2,
 | 
						|
                                      const FieldDescriptor* field,
 | 
						|
                                      std::vector<SpecificField>* parent_fields,
 | 
						|
                                      DefaultFieldComparator* comparator);
 | 
						|
 | 
						|
  // Shorthand for CompareFieldValueUsingParentFields with NULL parent_fields.
 | 
						|
  bool CompareFieldValue(const Message& message1, const Message& message2,
 | 
						|
                         const FieldDescriptor* field, int index1, int index2);
 | 
						|
 | 
						|
  // Compares the specified field on the two messages, returning
 | 
						|
  // true if they are the same, false otherwise. For repeated fields,
 | 
						|
  // this method only compares the value in the specified index. This method
 | 
						|
  // uses Compare functions to recurse into submessages.
 | 
						|
  // The parent_fields vector is used in calls to a Reporter instance calls.
 | 
						|
  // It can be NULL, in which case the MessageDifferencer will create new
 | 
						|
  // list of parent messages if it needs to recursively compare the given field.
 | 
						|
  // To avoid confusing users you should not set it to NULL unless you modified
 | 
						|
  // Reporter to handle the change of parent_fields correctly.
 | 
						|
  bool CompareFieldValueUsingParentFields(
 | 
						|
      const Message& message1, const Message& message2,
 | 
						|
      const FieldDescriptor* field, int index1, int index2,
 | 
						|
      std::vector<SpecificField>* parent_fields);
 | 
						|
 | 
						|
  // Compares the specified field on the two messages, returning comparison
 | 
						|
  // result, as returned by appropriate FieldComparator.
 | 
						|
  FieldComparator::ComparisonResult GetFieldComparisonResult(
 | 
						|
      const Message& message1, const Message& message2,
 | 
						|
      const FieldDescriptor* field, int index1, int index2,
 | 
						|
      const FieldContext* field_context);
 | 
						|
 | 
						|
  // Check if the two elements in the repeated field are match to each other.
 | 
						|
  // if the key_comprator is NULL, this function returns true when the two
 | 
						|
  // elements are equal.
 | 
						|
  bool IsMatch(const FieldDescriptor* repeated_field,
 | 
						|
               const MapKeyComparator* key_comparator, const Message* message1,
 | 
						|
               const Message* message2,
 | 
						|
               const std::vector<SpecificField>& parent_fields,
 | 
						|
               Reporter* reporter, int index1, int index2);
 | 
						|
 | 
						|
  // Returns true when this repeated field has been configured to be treated
 | 
						|
  // as a Set / SmartSet / SmartList.
 | 
						|
  bool IsTreatedAsSet(const FieldDescriptor* field);
 | 
						|
  bool IsTreatedAsSmartSet(const FieldDescriptor* field);
 | 
						|
 | 
						|
  bool IsTreatedAsSmartList(const FieldDescriptor* field);
 | 
						|
  // When treating as SMART_LIST, it uses MatchIndicesPostProcessorForSmartList
 | 
						|
  // by default to find the longest matching sequence from the first matching
 | 
						|
  // element. The callback takes two vectors showing the matching indices from
 | 
						|
  // the other vector, where -1 means an unmatch.
 | 
						|
  void SetMatchIndicesForSmartListCallback(
 | 
						|
      std::function<void(std::vector<int>*, std::vector<int>*)> callback);
 | 
						|
 | 
						|
  // Returns true when this repeated field is to be compared as a subset, ie.
 | 
						|
  // has been configured to be treated as a set or map and scope is set to
 | 
						|
  // PARTIAL.
 | 
						|
  bool IsTreatedAsSubset(const FieldDescriptor* field);
 | 
						|
 | 
						|
  // Returns true if this field is to be ignored when this
 | 
						|
  // MessageDifferencer compares messages.
 | 
						|
  bool IsIgnored(const Message& message1, const Message& message2,
 | 
						|
                 const FieldDescriptor* field,
 | 
						|
                 const std::vector<SpecificField>& parent_fields);
 | 
						|
 | 
						|
  // Returns true if this unknown field is to be ignored when this
 | 
						|
  // MessageDifferencer compares messages.
 | 
						|
  bool IsUnknownFieldIgnored(const Message& message1, const Message& message2,
 | 
						|
                             const SpecificField& field,
 | 
						|
                             const std::vector<SpecificField>& parent_fields);
 | 
						|
 | 
						|
  // Returns MapKeyComparator* when this field has been configured to be treated
 | 
						|
  // as a map or its is_map() return true.  If not, returns NULL.
 | 
						|
  const MapKeyComparator* GetMapKeyComparator(
 | 
						|
      const FieldDescriptor* field) const;
 | 
						|
 | 
						|
  // Attempts to match indices of a repeated field, so that the contained values
 | 
						|
  // match. Clears output vectors and sets their values to indices of paired
 | 
						|
  // messages, ie. if message1[0] matches message2[1], then match_list1[0] == 1
 | 
						|
  // and match_list2[1] == 0. The unmatched indices are indicated by -1.
 | 
						|
  // Assumes the repeated field is not treated as a simple list.
 | 
						|
  // This method returns false if the match failed. However, it doesn't mean
 | 
						|
  // that the comparison succeeds when this method returns true (you need to
 | 
						|
  // double-check in this case).
 | 
						|
  bool MatchRepeatedFieldIndices(
 | 
						|
      const Message& message1, const Message& message2,
 | 
						|
      const FieldDescriptor* repeated_field,
 | 
						|
      const MapKeyComparator* key_comparator,
 | 
						|
      const std::vector<SpecificField>& parent_fields,
 | 
						|
      std::vector<int>* match_list1, std::vector<int>* match_list2);
 | 
						|
 | 
						|
  // Checks if index is equal to new_index in all the specific fields.
 | 
						|
  static bool CheckPathChanged(const std::vector<SpecificField>& parent_fields);
 | 
						|
 | 
						|
  // CHECKs that the given repeated field can be compared according to
 | 
						|
  // new_comparison.
 | 
						|
  void CheckRepeatedFieldComparisons(
 | 
						|
      const FieldDescriptor* field,
 | 
						|
      const RepeatedFieldComparison& new_comparison);
 | 
						|
 | 
						|
  // Defines a map between field descriptors and their MapKeyComparators.
 | 
						|
  // Used for repeated fields when they are configured as TreatAsMap.
 | 
						|
  typedef std::map<const FieldDescriptor*, const MapKeyComparator*>
 | 
						|
      FieldKeyComparatorMap;
 | 
						|
 | 
						|
  // Defines a set to store field descriptors.  Used for repeated fields when
 | 
						|
  // they are configured as TreatAsSet.
 | 
						|
  typedef std::set<const FieldDescriptor*> FieldSet;
 | 
						|
  typedef std::map<const FieldDescriptor*, RepeatedFieldComparison> FieldMap;
 | 
						|
 | 
						|
  Reporter* reporter_;
 | 
						|
  DefaultFieldComparator default_field_comparator_;
 | 
						|
  MessageFieldComparison message_field_comparison_;
 | 
						|
  Scope scope_;
 | 
						|
  RepeatedFieldComparison repeated_field_comparison_;
 | 
						|
 | 
						|
  FieldMap repeated_field_comparisons_;
 | 
						|
  // Keeps track of MapKeyComparators that are created within
 | 
						|
  // MessageDifferencer. These MapKeyComparators should be deleted
 | 
						|
  // before MessageDifferencer is destroyed.
 | 
						|
  // When TreatAsMap or TreatAsMapWithMultipleFieldsAsKey is called, we don't
 | 
						|
  // store the supplied FieldDescriptors directly. Instead, a new
 | 
						|
  // MapKeyComparator is created for comparison purpose.
 | 
						|
  std::vector<MapKeyComparator*> owned_key_comparators_;
 | 
						|
  FieldKeyComparatorMap map_field_key_comparator_;
 | 
						|
  MapEntryKeyComparator map_entry_key_comparator_;
 | 
						|
  std::vector<IgnoreCriteria*> ignore_criteria_;
 | 
						|
  // Reused multiple times in RetrieveFields to avoid extra allocations
 | 
						|
  std::vector<const FieldDescriptor*> tmp_message_fields_;
 | 
						|
 | 
						|
  FieldSet ignored_fields_;
 | 
						|
 | 
						|
  union {
 | 
						|
    DefaultFieldComparator* default_impl;
 | 
						|
    FieldComparator* base;
 | 
						|
  } field_comparator_ = {&default_field_comparator_};
 | 
						|
  enum { kFCDefault, kFCBase } field_comparator_kind_ = kFCDefault;
 | 
						|
 | 
						|
  bool report_matches_;
 | 
						|
  bool report_moves_;
 | 
						|
  bool report_ignores_;
 | 
						|
 | 
						|
  std::string* output_string_;
 | 
						|
 | 
						|
  // Callback to post-process the matched indices to support SMART_LIST.
 | 
						|
  std::function<void(std::vector<int>*, std::vector<int>*)>
 | 
						|
      match_indices_for_smart_list_callback_;
 | 
						|
 | 
						|
  MessageDifferencer::UnpackAnyField unpack_any_field_;
 | 
						|
  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageDifferencer);
 | 
						|
};
 | 
						|
 | 
						|
// This class provides extra information to the FieldComparator::Compare
 | 
						|
// function.
 | 
						|
class PROTOBUF_EXPORT FieldContext {
 | 
						|
 public:
 | 
						|
  explicit FieldContext(
 | 
						|
      std::vector<MessageDifferencer::SpecificField>* parent_fields)
 | 
						|
      : parent_fields_(parent_fields) {}
 | 
						|
 | 
						|
  std::vector<MessageDifferencer::SpecificField>* parent_fields() const {
 | 
						|
    return parent_fields_;
 | 
						|
  }
 | 
						|
 | 
						|
 private:
 | 
						|
  std::vector<MessageDifferencer::SpecificField>* parent_fields_;
 | 
						|
};
 | 
						|
 | 
						|
}  // namespace util
 | 
						|
}  // namespace protobuf
 | 
						|
}  // namespace google
 | 
						|
 | 
						|
#include <google/protobuf/port_undef.inc>
 | 
						|
 | 
						|
#endif  // GOOGLE_PROTOBUF_UTIL_MESSAGE_DIFFERENCER_H__
 |