| // 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. | |
| namespace google { | |
| namespace protobuf { | |
| class Message; | |
| class EnumValueDescriptor; | |
| class FieldDescriptor; | |
| namespace util { | |
| class FieldContext; | |
| // 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 LIBPROTOBUF_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 google::protobuf::Message& message_1, | |
| const google::protobuf::Message& message_2, | |
| const google::protobuf::FieldDescriptor* field, | |
| int index_1, int index_2, | |
| const google::protobuf::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 LIBPROTOBUF_EXPORT DefaultFieldComparator : 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 differenciate uses of AlmostEqual | |
| // and WithinFractionOrMargin. | |
| }; | |
| // Creates new comparator with float comparison set to EXACT. | |
| DefaultFieldComparator(); | |
| virtual ~DefaultFieldComparator(); | |
| virtual ComparisonResult Compare( | |
| const google::protobuf::Message& message_1, | |
| const google::protobuf::Message& message_2, | |
| const google::protobuf::FieldDescriptor* field, | |
| int index_1, int index_2, | |
| const google::protobuf::util::FieldContext* field_context); | |
| 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); | |
| 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; | |
| // 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 google::protobuf::FieldDescriptor& field, | |
| 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 google::protobuf::FieldDescriptor& field, | |
| double value_1, double value_2); | |
| bool CompareEnum(const google::protobuf::FieldDescriptor& field, | |
| const EnumValueDescriptor* value_1, | |
| const EnumValueDescriptor* value_2); | |
| // Uses CompareDoubleOrFloat, a helper function used by both CompareDouble and | |
| // CompareFloat. | |
| bool CompareFloat(const google::protobuf::FieldDescriptor& field, | |
| float value_1, float value_2); | |
| bool CompareInt32(const google::protobuf::FieldDescriptor& field, | |
| int32 value_1, int32 value_2) { | |
| return value_1 == value_2; | |
| } | |
| bool CompareInt64(const google::protobuf::FieldDescriptor& field, | |
| int64 value_1, int64 value_2) { | |
| return value_1 == value_2; | |
| } | |
| bool CompareString(const google::protobuf::FieldDescriptor& field, | |
| const string& value_1, const string& value_2) { | |
| return value_1 == value_2; | |
| } | |
| bool CompareUInt32(const google::protobuf::FieldDescriptor& field, | |
| uint32 value_1, uint32 value_2) { | |
| return value_1 == value_2; | |
| } | |
| bool CompareUInt64(const google::protobuf::FieldDescriptor& field, | |
| uint64 value_1, uint64 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 google::protobuf::FieldDescriptor& field, | |
| T value_1, T value_2); | |
| // Returns FieldComparator::SAME if boolean_result is true and | |
| // FieldComparator::DIFFERENT otherwise. | |
| ComparisonResult ResultFromBoolean(bool boolean_result) const; | |
| 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(DefaultFieldComparator); | |
| }; | |
| } // namespace util | |
| } // namespace protobuf | |
| } // namespace google | |