1 // Protocol Buffers - Google's data interchange format 2 // Copyright 2008 Google Inc. All rights reserved. 3 // https://developers.google.com/protocol-buffers/ 4 // 5 // Redistribution and use in source and binary forms, with or without 6 // modification, are permitted provided that the following conditions are 7 // met: 8 // 9 // * Redistributions of source code must retain the above copyright 10 // notice, this list of conditions and the following disclaimer. 11 // * Redistributions in binary form must reproduce the above 12 // copyright notice, this list of conditions and the following disclaimer 13 // in the documentation and/or other materials provided with the 14 // distribution. 15 // * Neither the name of Google Inc. nor the names of its 16 // contributors may be used to endorse or promote products derived from 17 // this software without specific prior written permission. 18 // 19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 31 // Defines classes for field comparison. 32 33 #ifndef GOOGLE_PROTOBUF_UTIL_FIELD_COMPARATOR_H__ 34 #define GOOGLE_PROTOBUF_UTIL_FIELD_COMPARATOR_H__ 35 36 #include <map> 37 #include <string> 38 #include <vector> 39 40 #include <google/protobuf/stubs/common.h> 41 42 #include <google/protobuf/port_def.inc> 43 44 namespace google { 45 namespace protobuf { 46 47 class Message; 48 class EnumValueDescriptor; 49 class FieldDescriptor; 50 51 namespace util { 52 53 class FieldContext; 54 class MessageDifferencer; 55 56 // Base class specifying the interface for comparing protocol buffer fields. 57 // Regular users should consider using or subclassing DefaultFieldComparator 58 // rather than this interface. 59 // Currently, this does not support comparing unknown fields. 60 class PROTOBUF_EXPORT FieldComparator { 61 public: 62 FieldComparator(); 63 virtual ~FieldComparator(); 64 65 enum ComparisonResult { 66 SAME, // Compared fields are equal. In case of comparing submessages, 67 // user should not recursively compare their contents. 68 DIFFERENT, // Compared fields are different. In case of comparing 69 // submessages, user should not recursively compare their 70 // contents. 71 RECURSE, // Compared submessages need to be compared recursively. 72 // FieldComparator does not specify the semantics of recursive 73 // comparison. This value should not be returned for simple 74 // values. 75 }; 76 77 // Compares the values of a field in two protocol buffer messages. 78 // Returns SAME or DIFFERENT for simple values, and SAME, DIFFERENT or RECURSE 79 // for submessages. Returning RECURSE for fields not being submessages is 80 // illegal. 81 // In case the given FieldDescriptor points to a repeated field, the indices 82 // need to be valid. Otherwise they should be ignored. 83 // 84 // FieldContext contains information about the specific instances of the 85 // fields being compared, versus FieldDescriptor which only contains general 86 // type information about the fields. 87 virtual ComparisonResult Compare(const Message& message_1, 88 const Message& message_2, 89 const FieldDescriptor* field, int index_1, 90 int index_2, 91 const util::FieldContext* field_context) = 0; 92 93 private: 94 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldComparator); 95 }; 96 97 // Basic implementation of FieldComparator. Supports three modes of floating 98 // point value comparison: exact, approximate using MathUtil::AlmostEqual 99 // method, and arbitrarily precise using MathUtil::WithinFractionOrMargin. 100 class PROTOBUF_EXPORT DefaultFieldComparator : public FieldComparator { 101 public: 102 enum FloatComparison { 103 EXACT, // Floats and doubles are compared exactly. 104 APPROXIMATE, // Floats and doubles are compared using the 105 // MathUtil::AlmostEqual method or 106 // MathUtil::WithinFractionOrMargin method. 107 // TODO(ksroka): Introduce third value to differentiate uses of AlmostEqual 108 // and WithinFractionOrMargin. 109 }; 110 111 // Creates new comparator with float comparison set to EXACT. 112 DefaultFieldComparator(); 113 114 ~DefaultFieldComparator() override; 115 116 ComparisonResult Compare(const Message& message_1, const Message& message_2, 117 const FieldDescriptor* field, int index_1, 118 int index_2, 119 const util::FieldContext* field_context) override; 120 set_float_comparison(FloatComparison float_comparison)121 void set_float_comparison(FloatComparison float_comparison) { 122 float_comparison_ = float_comparison; 123 } 124 float_comparison()125 FloatComparison float_comparison() const { return float_comparison_; } 126 127 // Set whether the FieldComparator shall treat floats or doubles that are both 128 // NaN as equal (treat_nan_as_equal = true) or as different 129 // (treat_nan_as_equal = false). Default is treating NaNs always as different. set_treat_nan_as_equal(bool treat_nan_as_equal)130 void set_treat_nan_as_equal(bool treat_nan_as_equal) { 131 treat_nan_as_equal_ = treat_nan_as_equal; 132 } 133 treat_nan_as_equal()134 bool treat_nan_as_equal() const { return treat_nan_as_equal_; } 135 136 // Sets the fraction and margin for the float comparison of a given field. 137 // Uses MathUtil::WithinFractionOrMargin to compare the values. 138 // 139 // REQUIRES: field->cpp_type == FieldDescriptor::CPPTYPE_DOUBLE or 140 // field->cpp_type == FieldDescriptor::CPPTYPE_FLOAT 141 // REQUIRES: float_comparison_ == APPROXIMATE 142 void SetFractionAndMargin(const FieldDescriptor* field, double fraction, 143 double margin); 144 145 // Sets the fraction and margin for the float comparison of all float and 146 // double fields, unless a field has been given a specific setting via 147 // SetFractionAndMargin() above. 148 // Uses MathUtil::WithinFractionOrMargin to compare the values. 149 // 150 // REQUIRES: float_comparison_ == APPROXIMATE 151 void SetDefaultFractionAndMargin(double fraction, double margin); 152 153 protected: 154 // Compare using the provided message_differencer. For example, a subclass can 155 // use this method to compare some field in a certain way using the same 156 // message_differencer instance and the field context. 157 bool Compare(MessageDifferencer* differencer, const Message& message1, 158 const Message& message2, 159 const util::FieldContext* field_context); 160 161 private: 162 // Defines the tolerance for floating point comparison (fraction and margin). 163 struct Tolerance { 164 double fraction; 165 double margin; ToleranceTolerance166 Tolerance() : fraction(0.0), margin(0.0) {} ToleranceTolerance167 Tolerance(double f, double m) : fraction(f), margin(m) {} 168 }; 169 170 // Defines the map to store the tolerances for floating point comparison. 171 typedef std::map<const FieldDescriptor*, Tolerance> ToleranceMap; 172 173 // The following methods get executed when CompareFields is called for the 174 // basic types (instead of submessages). They return true on success. One 175 // can use ResultFromBoolean() to convert that boolean to a ComparisonResult 176 // value. CompareBool(const FieldDescriptor &,bool value_1,bool value_2)177 bool CompareBool(const FieldDescriptor& /* unused */, bool value_1, 178 bool value_2) { 179 return value_1 == value_2; 180 } 181 182 // Uses CompareDoubleOrFloat, a helper function used by both CompareDouble and 183 // CompareFloat. 184 bool CompareDouble(const FieldDescriptor& field, double value_1, 185 double value_2); 186 187 bool CompareEnum(const FieldDescriptor& field, 188 const EnumValueDescriptor* value_1, 189 const EnumValueDescriptor* value_2); 190 191 // Uses CompareDoubleOrFloat, a helper function used by both CompareDouble and 192 // CompareFloat. 193 bool CompareFloat(const FieldDescriptor& field, float value_1, float value_2); 194 CompareInt32(const FieldDescriptor &,int32 value_1,int32 value_2)195 bool CompareInt32(const FieldDescriptor& /* unused */, int32 value_1, 196 int32 value_2) { 197 return value_1 == value_2; 198 } 199 CompareInt64(const FieldDescriptor &,int64 value_1,int64 value_2)200 bool CompareInt64(const FieldDescriptor& /* unused */, int64 value_1, 201 int64 value_2) { 202 return value_1 == value_2; 203 } 204 CompareString(const FieldDescriptor &,const std::string & value_1,const std::string & value_2)205 bool CompareString(const FieldDescriptor& /* unused */, 206 const std::string& value_1, const std::string& value_2) { 207 return value_1 == value_2; 208 } 209 CompareUInt32(const FieldDescriptor &,uint32 value_1,uint32 value_2)210 bool CompareUInt32(const FieldDescriptor& /* unused */, uint32 value_1, 211 uint32 value_2) { 212 return value_1 == value_2; 213 } 214 CompareUInt64(const FieldDescriptor &,uint64 value_1,uint64 value_2)215 bool CompareUInt64(const FieldDescriptor& /* unused */, uint64 value_1, 216 uint64 value_2) { 217 return value_1 == value_2; 218 } 219 220 // This function is used by CompareDouble and CompareFloat to avoid code 221 // duplication. There are no checks done against types of the values passed, 222 // but it's likely to fail if passed non-numeric arguments. 223 template <typename T> 224 bool CompareDoubleOrFloat(const FieldDescriptor& field, T value_1, T value_2); 225 226 // Returns FieldComparator::SAME if boolean_result is true and 227 // FieldComparator::DIFFERENT otherwise. 228 ComparisonResult ResultFromBoolean(bool boolean_result) const; 229 230 FloatComparison float_comparison_; 231 232 // If true, floats and doubles that are both NaN are considered to be 233 // equal. Otherwise, two floats or doubles that are NaN are considered to be 234 // different. 235 bool treat_nan_as_equal_; 236 237 // True iff default_tolerance_ has been explicitly set. 238 // 239 // If false, then the default tolerance for floats and doubles is that which 240 // is used by MathUtil::AlmostEquals(). 241 bool has_default_tolerance_; 242 243 // Default float/double tolerance. Only meaningful if 244 // has_default_tolerance_ == true. 245 Tolerance default_tolerance_; 246 247 // Field-specific float/double tolerances, which override any default for 248 // those particular fields. 249 ToleranceMap map_tolerance_; 250 251 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DefaultFieldComparator); 252 }; 253 254 } // namespace util 255 } // namespace protobuf 256 } // namespace google 257 258 #include <google/protobuf/port_undef.inc> 259 260 #endif // GOOGLE_PROTOBUF_UTIL_FIELD_COMPARATOR_H__ 261