286 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			286 lines
		
	
	
		
			11 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.
 | |
| 
 | |
| // Defines classes for field comparison.
 | |
| 
 | |
| #ifndef GOOGLE_PROTOBUF_UTIL_FIELD_COMPARATOR_H__
 | |
| #define GOOGLE_PROTOBUF_UTIL_FIELD_COMPARATOR_H__
 | |
| 
 | |
| #include <cstdint>
 | |
| #include <map>
 | |
| #include <string>
 | |
| #include <vector>
 | |
| 
 | |
| #include <google/protobuf/stubs/common.h>
 | |
| #include <google/protobuf/port_def.inc>
 | |
| 
 | |
| namespace google {
 | |
| namespace protobuf {
 | |
| 
 | |
| class Message;
 | |
| class EnumValueDescriptor;
 | |
| class FieldDescriptor;
 | |
| 
 | |
| namespace util {
 | |
| 
 | |
| class FieldContext;
 | |
| class MessageDifferencer;
 | |
| 
 | |
| // Base class specifying the interface for comparing protocol buffer fields.
 | |
| // Regular users should consider using or subclassing DefaultFieldComparator
 | |
| // rather than this interface.
 | |
| // Currently, this does not support comparing unknown fields.
 | |
| class PROTOBUF_EXPORT FieldComparator {
 | |
|  public:
 | |
|   FieldComparator();
 | |
|   virtual ~FieldComparator();
 | |
| 
 | |
|   enum ComparisonResult {
 | |
|     SAME,       // Compared fields are equal. In case of comparing submessages,
 | |
|                 // user should not recursively compare their contents.
 | |
|     DIFFERENT,  // Compared fields are different. In case of comparing
 | |
|                 // submessages, user should not recursively compare their
 | |
|                 // contents.
 | |
|     RECURSE,    // Compared submessages need to be compared recursively.
 | |
|                 // FieldComparator does not specify the semantics of recursive
 | |
|                 // comparison. This value should not be returned for simple
 | |
|                 // values.
 | |
|   };
 | |
| 
 | |
|   // Compares the values of a field in two protocol buffer messages.
 | |
|   // Returns SAME or DIFFERENT for simple values, and SAME, DIFFERENT or RECURSE
 | |
|   // for submessages. Returning RECURSE for fields not being submessages is
 | |
|   // illegal.
 | |
|   // In case the given FieldDescriptor points to a repeated field, the indices
 | |
|   // need to be valid. Otherwise they should be ignored.
 | |
|   //
 | |
|   // FieldContext contains information about the specific instances of the
 | |
|   // fields being compared, versus FieldDescriptor which only contains general
 | |
|   // type information about the fields.
 | |
|   virtual ComparisonResult Compare(const Message& message_1,
 | |
|                                    const Message& message_2,
 | |
|                                    const FieldDescriptor* field, int index_1,
 | |
|                                    int index_2,
 | |
|                                    const util::FieldContext* field_context) = 0;
 | |
| 
 | |
|  private:
 | |
|   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldComparator);
 | |
| };
 | |
| 
 | |
| // Basic implementation of FieldComparator.  Supports three modes of floating
 | |
| // point value comparison: exact, approximate using MathUtil::AlmostEqual
 | |
| // method, and arbitrarily precise using MathUtil::WithinFractionOrMargin.
 | |
| class PROTOBUF_EXPORT SimpleFieldComparator : public FieldComparator {
 | |
|  public:
 | |
|   enum FloatComparison {
 | |
|     EXACT,        // Floats and doubles are compared exactly.
 | |
|     APPROXIMATE,  // Floats and doubles are compared using the
 | |
|                   // MathUtil::AlmostEqual method or
 | |
|                   // MathUtil::WithinFractionOrMargin method.
 | |
|     // TODO(ksroka): Introduce third value to differentiate uses of AlmostEqual
 | |
|     //               and WithinFractionOrMargin.
 | |
|   };
 | |
| 
 | |
|   // Creates new comparator with float comparison set to EXACT.
 | |
|   SimpleFieldComparator();
 | |
| 
 | |
|   ~SimpleFieldComparator() override;
 | |
| 
 | |
|   void set_float_comparison(FloatComparison float_comparison) {
 | |
|     float_comparison_ = float_comparison;
 | |
|   }
 | |
| 
 | |
|   FloatComparison float_comparison() const { return float_comparison_; }
 | |
| 
 | |
|   // Set whether the FieldComparator shall treat floats or doubles that are both
 | |
|   // NaN as equal (treat_nan_as_equal = true) or as different
 | |
|   // (treat_nan_as_equal = false). Default is treating NaNs always as different.
 | |
|   void set_treat_nan_as_equal(bool treat_nan_as_equal) {
 | |
|     treat_nan_as_equal_ = treat_nan_as_equal;
 | |
|   }
 | |
| 
 | |
|   bool treat_nan_as_equal() const { return treat_nan_as_equal_; }
 | |
| 
 | |
|   // Sets the fraction and margin for the float comparison of a given field.
 | |
|   // Uses MathUtil::WithinFractionOrMargin to compare the values.
 | |
|   //
 | |
|   // 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 fraction and margin for the float comparison of all float and
 | |
|   // double fields, unless a field has been given a specific setting via
 | |
|   // SetFractionAndMargin() above.
 | |
|   // Uses MathUtil::WithinFractionOrMargin to compare the values.
 | |
|   //
 | |
|   // REQUIRES: float_comparison_ == APPROXIMATE
 | |
|   void SetDefaultFractionAndMargin(double fraction, double margin);
 | |
| 
 | |
|  protected:
 | |
|   // Returns the comparison result for the given field in two messages.
 | |
|   //
 | |
|   // This function is called directly by DefaultFieldComparator::Compare.
 | |
|   // Subclasses can call this function to compare fields they do not need to
 | |
|   // handle specially.
 | |
|   ComparisonResult SimpleCompare(const Message& message_1,
 | |
|                                  const Message& message_2,
 | |
|                                  const FieldDescriptor* field, int index_1,
 | |
|                                  int index_2,
 | |
|                                  const util::FieldContext* field_context);
 | |
| 
 | |
|   // Compare using the provided message_differencer. For example, a subclass can
 | |
|   // use this method to compare some field in a certain way using the same
 | |
|   // message_differencer instance and the field context.
 | |
|   bool CompareWithDifferencer(MessageDifferencer* differencer,
 | |
|                               const Message& message1, const Message& message2,
 | |
|                               const util::FieldContext* field_context);
 | |
| 
 | |
|   // Returns FieldComparator::SAME if boolean_result is true and
 | |
|   // FieldComparator::DIFFERENT otherwise.
 | |
|   ComparisonResult ResultFromBoolean(bool boolean_result) const;
 | |
| 
 | |
|  private:
 | |
|   // Defines the tolerance for floating point comparison (fraction and margin).
 | |
|   struct Tolerance {
 | |
|     double fraction;
 | |
|     double margin;
 | |
|     Tolerance() : fraction(0.0), margin(0.0) {}
 | |
|     Tolerance(double f, double m) : fraction(f), margin(m) {}
 | |
|   };
 | |
| 
 | |
|   // Defines the map to store the tolerances for floating point comparison.
 | |
|   typedef std::map<const FieldDescriptor*, Tolerance> ToleranceMap;
 | |
| 
 | |
|   friend class MessageDifferencer;
 | |
|   // The following methods get executed when CompareFields is called for the
 | |
|   // basic types (instead of submessages). They return true on success. One
 | |
|   // can use ResultFromBoolean() to convert that boolean to a ComparisonResult
 | |
|   // value.
 | |
|   bool CompareBool(const FieldDescriptor& /* unused */, bool value_1,
 | |
|                    bool value_2) {
 | |
|     return value_1 == value_2;
 | |
|   }
 | |
| 
 | |
|   // Uses CompareDoubleOrFloat, a helper function used by both CompareDouble and
 | |
|   // CompareFloat.
 | |
|   bool CompareDouble(const FieldDescriptor& field, double value_1,
 | |
|                      double value_2);
 | |
| 
 | |
|   bool CompareEnum(const FieldDescriptor& field,
 | |
|                    const EnumValueDescriptor* value_1,
 | |
|                    const EnumValueDescriptor* value_2);
 | |
| 
 | |
|   // Uses CompareDoubleOrFloat, a helper function used by both CompareDouble and
 | |
|   // CompareFloat.
 | |
|   bool CompareFloat(const FieldDescriptor& field, float value_1, float value_2);
 | |
| 
 | |
|   bool CompareInt32(const FieldDescriptor& /* unused */, int32_t value_1,
 | |
|                     int32_t value_2) {
 | |
|     return value_1 == value_2;
 | |
|   }
 | |
| 
 | |
|   bool CompareInt64(const FieldDescriptor& /* unused */, int64_t value_1,
 | |
|                     int64_t value_2) {
 | |
|     return value_1 == value_2;
 | |
|   }
 | |
| 
 | |
|   bool CompareString(const FieldDescriptor& /* unused */,
 | |
|                      const std::string& value_1, const std::string& value_2) {
 | |
|     return value_1 == value_2;
 | |
|   }
 | |
| 
 | |
|   bool CompareUInt32(const FieldDescriptor& /* unused */, uint32_t value_1,
 | |
|                      uint32_t value_2) {
 | |
|     return value_1 == value_2;
 | |
|   }
 | |
| 
 | |
|   bool CompareUInt64(const FieldDescriptor& /* unused */, uint64_t value_1,
 | |
|                      uint64_t value_2) {
 | |
|     return value_1 == value_2;
 | |
|   }
 | |
| 
 | |
|   // This function is used by CompareDouble and CompareFloat to avoid code
 | |
|   // duplication. There are no checks done against types of the values passed,
 | |
|   // but it's likely to fail if passed non-numeric arguments.
 | |
|   template <typename T>
 | |
|   bool CompareDoubleOrFloat(const FieldDescriptor& field, T value_1, T value_2);
 | |
| 
 | |
|   FloatComparison float_comparison_;
 | |
| 
 | |
|   // If true, floats and doubles that are both NaN are considered to be
 | |
|   // equal. Otherwise, two floats or doubles that are NaN are considered to be
 | |
|   // different.
 | |
|   bool treat_nan_as_equal_;
 | |
| 
 | |
|   // True iff default_tolerance_ has been explicitly set.
 | |
|   //
 | |
|   // If false, then the default tolerance for floats and doubles is that which
 | |
|   // is used by MathUtil::AlmostEquals().
 | |
|   bool has_default_tolerance_;
 | |
| 
 | |
|   // Default float/double tolerance. Only meaningful if
 | |
|   // has_default_tolerance_ == true.
 | |
|   Tolerance default_tolerance_;
 | |
| 
 | |
|   // Field-specific float/double tolerances, which override any default for
 | |
|   // those particular fields.
 | |
|   ToleranceMap map_tolerance_;
 | |
| 
 | |
|   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SimpleFieldComparator);
 | |
| };
 | |
| 
 | |
| // Default field comparison: use the basic implementation of FieldComparator.
 | |
| #ifdef PROTOBUF_FUTURE_BREAKING_CHANGES
 | |
| class PROTOBUF_EXPORT DefaultFieldComparator final
 | |
|     : public SimpleFieldComparator
 | |
| #else   // PROTOBUF_FUTURE_BREAKING_CHANGES
 | |
| class PROTOBUF_EXPORT DefaultFieldComparator : public SimpleFieldComparator
 | |
| #endif  // PROTOBUF_FUTURE_BREAKING_CHANGES
 | |
| {
 | |
|  public:
 | |
|   ComparisonResult Compare(const Message& message_1, const Message& message_2,
 | |
|                            const FieldDescriptor* field, int index_1,
 | |
|                            int index_2,
 | |
|                            const util::FieldContext* field_context) override {
 | |
|     return SimpleCompare(message_1, message_2, field, index_1, index_2,
 | |
|                          field_context);
 | |
|   }
 | |
| };
 | |
| 
 | |
| }  // namespace util
 | |
| }  // namespace protobuf
 | |
| }  // namespace google
 | |
| 
 | |
| #include <google/protobuf/port_undef.inc>
 | |
| 
 | |
| #endif  // GOOGLE_PROTOBUF_UTIL_FIELD_COMPARATOR_H__
 |