| Index: third_party/protobuf/src/google/protobuf/util/message_differencer.h
|
| diff --git a/third_party/protobuf/src/google/protobuf/util/message_differencer.h b/third_party/protobuf/src/google/protobuf/util/message_differencer.h
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..3ea74e673dd70d031160975dafe5202d1e64ad00
|
| --- /dev/null
|
| +++ b/third_party/protobuf/src/google/protobuf/util/message_differencer.h
|
| @@ -0,0 +1,843 @@
|
| +// 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.
|
| +
|
| +#ifndef GOOGLE_PROTOBUF_UTIL_MESSAGE_DIFFERENCER_H__
|
| +#define GOOGLE_PROTOBUF_UTIL_MESSAGE_DIFFERENCER_H__
|
| +
|
| +#include <map>
|
| +#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>
|
| +
|
| +namespace google {
|
| +namespace protobuf {
|
| +
|
| +class DynamicMessageFactory;
|
| +class FieldDescriptor;
|
| +
|
| +namespace io {
|
| +class ZeroCopyOutputStream;
|
| +class Printer;
|
| +}
|
| +
|
| +namespace util {
|
| +
|
| +class FieldContext; // declared below MessageDifferencer
|
| +
|
| +// 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.
|
| +class LIBPROTOBUF_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 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 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 http://shortn/_x2Gv6XFrWt.
|
| + // 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;
|
| + int unknown_field_number;
|
| + UnknownField::Type unknown_field_type;
|
| +
|
| + // 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;
|
| +
|
| + // 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. This only
|
| + // applies to ReportMoved() and (in the case of TreatAsMap())
|
| + // ReportModified(). In all other cases, "new_index" will have the same
|
| + // value as "index".
|
| + int new_index;
|
| +
|
| + // 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;
|
| + const UnknownFieldSet* unknown_field_set2;
|
| +
|
| + // 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;
|
| + int unknown_field_index2;
|
| +
|
| + SpecificField()
|
| + : field(NULL),
|
| + unknown_field_number(-1),
|
| + index(-1),
|
| + new_index(-1),
|
| + unknown_field_set1(NULL),
|
| + unknown_field_set2(NULL),
|
| + unknown_field_index1(-1),
|
| + unknown_field_index2(-1) {}
|
| + };
|
| +
|
| + // 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.
|
| + class LIBPROTOBUF_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 vector<SpecificField>& field_path) = 0;
|
| +
|
| + // Reports that a field has been deleted from Message1.
|
| + virtual void ReportDeleted(
|
| + const Message& message1,
|
| + const Message& message2,
|
| + const 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 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 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 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 vector<SpecificField>& field_path) { }
|
| +
|
| + // Report that an unkown 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 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 LIBPROTOBUF_EXPORT MapKeyComparator {
|
| + public:
|
| + MapKeyComparator();
|
| + virtual ~MapKeyComparator();
|
| +
|
| + virtual bool IsMatch(const Message& message1,
|
| + const Message& message2,
|
| + const 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 registed 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 LIBPROTOBUF_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 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 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 by default.
|
| + // See TreatAsSet(), as below.
|
| + };
|
| +
|
| + // 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.
|
| + //
|
| + // 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 TreatAsList
|
| + void TreatAsSet(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.
|
| + //
|
| + // REQUIRED: field->is_repeated() and field not registered with TreatAsSet
|
| + void TreatAsList(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 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 vector<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);
|
| +
|
| + // 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);
|
| +
|
| + // 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;
|
| + }
|
| +
|
| + // 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);
|
| +
|
| + // 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 vector<const FieldDescriptor*>& message1_fields,
|
| + const 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(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 '$'.
|
| + class LIBPROTOBUF_EXPORT StreamReporter : public Reporter {
|
| + public:
|
| + explicit StreamReporter(io::ZeroCopyOutputStream* output);
|
| + explicit StreamReporter(io::Printer* printer); // delimiter '$'
|
| + virtual ~StreamReporter();
|
| +
|
| + // 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.
|
| + virtual void ReportAdded(const Message& message1, const Message& message2,
|
| + const vector<SpecificField>& field_path);
|
| +
|
| + virtual void ReportDeleted(const Message& message1,
|
| + const Message& message2,
|
| + const vector<SpecificField>& field_path);
|
| +
|
| + virtual void ReportModified(const Message& message1,
|
| + const Message& message2,
|
| + const vector<SpecificField>& field_path);
|
| +
|
| + virtual void ReportMoved(const Message& message1,
|
| + const Message& message2,
|
| + const vector<SpecificField>& field_path);
|
| +
|
| + virtual void ReportMatched(const Message& message1,
|
| + const Message& message2,
|
| + const vector<SpecificField>& field_path);
|
| +
|
| + virtual void ReportIgnored(const Message& message1,
|
| + const Message& message2,
|
| + const vector<SpecificField>& field_path);
|
| +
|
| + virtual void ReportUnknownFieldIgnored(
|
| + const Message& message1, const Message& message2,
|
| + const vector<SpecificField>& field_path);
|
| +
|
| + protected:
|
| + // Prints the specified path of fields to the buffer.
|
| + virtual void PrintPath(const 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 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 string& str);
|
| +
|
| + private:
|
| + io::Printer* printer_;
|
| + bool delete_printer_;
|
| + bool report_modified_aggregates_;
|
| +
|
| + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StreamReporter);
|
| + };
|
| +
|
| + private:
|
| + // 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;
|
| + // Returns true if field1's number() is less than field2's.
|
| + static bool FieldBefore(const FieldDescriptor* field1,
|
| + const FieldDescriptor* field2);
|
| +
|
| + // 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.
|
| + void CombineFields(const vector<const FieldDescriptor*>& fields1,
|
| + Scope fields1_scope,
|
| + const vector<const FieldDescriptor*>& fields2,
|
| + Scope fields2_scope,
|
| + vector<const FieldDescriptor*>* combined_fields);
|
| +
|
| + // 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,
|
| + vector<SpecificField>* parent_fields);
|
| +
|
| + // Compares all the unknown fields in two messages.
|
| + bool CompareUnknownFields(const Message& message1, const Message& message2,
|
| + const google::protobuf::UnknownFieldSet&,
|
| + const google::protobuf::UnknownFieldSet&,
|
| + 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 vector<const FieldDescriptor*>& message1_fields,
|
| + const vector<const FieldDescriptor*>& message2_fields,
|
| + vector<SpecificField>* parent_fields);
|
| +
|
| + // Compares the specified messages with the specified field lists.
|
| + bool CompareWithFieldsInternal(
|
| + const Message& message1, const Message& message2,
|
| + const vector<const FieldDescriptor*>& message1_fields,
|
| + const vector<const FieldDescriptor*>& message2_fields,
|
| + vector<SpecificField>* parent_fields);
|
| +
|
| + // Compares the repeated fields, and report the error.
|
| + bool CompareRepeatedField(const Message& message1, const Message& message2,
|
| + const FieldDescriptor* field,
|
| + vector<SpecificField>* parent_fields);
|
| +
|
| + // 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,
|
| + 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 vector<SpecificField>& parent_fields,
|
| + int index1, int index2);
|
| +
|
| + // Returns true when this repeated field has been configured to be treated
|
| + // as a set.
|
| + bool IsTreatedAsSet(const FieldDescriptor* field);
|
| +
|
| + // 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 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 vector<SpecificField>& parent_fields);
|
| +
|
| + // Returns MapKeyComparator* when this field has been configured to
|
| + // be treated as a map. If not, returns NULL.
|
| + const MapKeyComparator* GetMapKeyComparator(const FieldDescriptor* field);
|
| +
|
| + // 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.
|
| + // 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 vector<SpecificField>& parent_fields,
|
| + vector<int>* match_list1,
|
| + vector<int>* match_list2);
|
| +
|
| + // If "any" is of type google.protobuf.Any, extract its payload using
|
| + // DynamicMessageFactory and store in "data".
|
| + bool UnpackAny(const Message& any, google::protobuf::scoped_ptr<Message>* data);
|
| +
|
| + // Checks if index is equal to new_index in all the specific fields.
|
| + static bool CheckPathChanged(const vector<SpecificField>& parent_fields);
|
| +
|
| + // Defines a map between field descriptors and their MapKeyComparators.
|
| + // Used for repeated fields when they are configured as TreatAsMap.
|
| + typedef map<const FieldDescriptor*,
|
| + const MapKeyComparator*> FieldKeyComparatorMap;
|
| +
|
| + // Defines a set to store field descriptors. Used for repeated fields when
|
| + // they are configured as TreatAsSet.
|
| + typedef set<const FieldDescriptor*> FieldSet;
|
| +
|
| + Reporter* reporter_;
|
| + DefaultFieldComparator default_field_comparator_;
|
| + FieldComparator* field_comparator_;
|
| + MessageFieldComparison message_field_comparison_;
|
| + Scope scope_;
|
| + RepeatedFieldComparison repeated_field_comparison_;
|
| +
|
| + FieldSet set_fields_;
|
| + FieldSet list_fields_;
|
| + // 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.
|
| + vector<MapKeyComparator*> owned_key_comparators_;
|
| + FieldKeyComparatorMap map_field_key_comparator_;
|
| + vector<IgnoreCriteria*> ignore_criteria_;
|
| +
|
| + FieldSet ignored_fields_;
|
| +
|
| + bool compare_unknown_fields_;
|
| + bool report_matches_;
|
| +
|
| + string* output_string_;
|
| +
|
| + google::protobuf::scoped_ptr<DynamicMessageFactory> dynamic_message_factory_;
|
| + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageDifferencer);
|
| +};
|
| +
|
| +// This class provides extra information to the FieldComparator::Compare
|
| +// function.
|
| +class LIBPROTOBUF_EXPORT FieldContext {
|
| + public:
|
| + explicit FieldContext(
|
| + vector<MessageDifferencer::SpecificField>* parent_fields)
|
| + : parent_fields_(parent_fields) {}
|
| +
|
| + vector<MessageDifferencer::SpecificField>* parent_fields() const {
|
| + return parent_fields_;
|
| + }
|
| +
|
| + private:
|
| + vector<MessageDifferencer::SpecificField>* parent_fields_;
|
| +};
|
| +
|
| +}
|
| +}
|
| +
|
| +} // namespace google
|
| +#endif // GOOGLE_PROTOBUF_UTIL_MESSAGE_DIFFERENCER_H__
|
|
|