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 <cstdint> 37 #include <map> 38 #include <string> 39 #include <vector> 40 41 #include <google/protobuf/stubs/common.h> 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 SimpleFieldComparator : 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 SimpleFieldComparator(); 113 114 ~SimpleFieldComparator() override; 115 set_float_comparison(FloatComparison float_comparison)116 void set_float_comparison(FloatComparison float_comparison) { 117 float_comparison_ = float_comparison; 118 } 119 float_comparison()120 FloatComparison float_comparison() const { return float_comparison_; } 121 122 // Set whether the FieldComparator shall treat floats or doubles that are both 123 // NaN as equal (treat_nan_as_equal = true) or as different 124 // (treat_nan_as_equal = false). Default is treating NaNs always as different. set_treat_nan_as_equal(bool treat_nan_as_equal)125 void set_treat_nan_as_equal(bool treat_nan_as_equal) { 126 treat_nan_as_equal_ = treat_nan_as_equal; 127 } 128 treat_nan_as_equal()129 bool treat_nan_as_equal() const { return treat_nan_as_equal_; } 130 131 // Sets the fraction and margin for the float comparison of a given field. 132 // Uses MathUtil::WithinFractionOrMargin to compare the values. 133 // 134 // REQUIRES: field->cpp_type == FieldDescriptor::CPPTYPE_DOUBLE or 135 // field->cpp_type == FieldDescriptor::CPPTYPE_FLOAT 136 // REQUIRES: float_comparison_ == APPROXIMATE 137 void SetFractionAndMargin(const FieldDescriptor* field, double fraction, 138 double margin); 139 140 // Sets the fraction and margin for the float comparison of all float and 141 // double fields, unless a field has been given a specific setting via 142 // SetFractionAndMargin() above. 143 // Uses MathUtil::WithinFractionOrMargin to compare the values. 144 // 145 // REQUIRES: float_comparison_ == APPROXIMATE 146 void SetDefaultFractionAndMargin(double fraction, double margin); 147 148 protected: 149 // Returns the comparison result for the given field in two messages. 150 // 151 // This function is called directly by DefaultFieldComparator::Compare. 152 // Subclasses can call this function to compare fields they do not need to 153 // handle specially. 154 ComparisonResult SimpleCompare(const Message& message_1, 155 const Message& message_2, 156 const FieldDescriptor* field, int index_1, 157 int index_2, 158 const util::FieldContext* field_context); 159 160 // Compare using the provided message_differencer. For example, a subclass can 161 // use this method to compare some field in a certain way using the same 162 // message_differencer instance and the field context. 163 bool CompareWithDifferencer(MessageDifferencer* differencer, 164 const Message& message1, const Message& message2, 165 const util::FieldContext* field_context); 166 167 // Returns FieldComparator::SAME if boolean_result is true and 168 // FieldComparator::DIFFERENT otherwise. 169 ComparisonResult ResultFromBoolean(bool boolean_result) const; 170 171 private: 172 // Defines the tolerance for floating point comparison (fraction and margin). 173 struct Tolerance { 174 double fraction; 175 double margin; ToleranceTolerance176 Tolerance() : fraction(0.0), margin(0.0) {} ToleranceTolerance177 Tolerance(double f, double m) : fraction(f), margin(m) {} 178 }; 179 180 // Defines the map to store the tolerances for floating point comparison. 181 typedef std::map<const FieldDescriptor*, Tolerance> ToleranceMap; 182 183 friend class MessageDifferencer; 184 // The following methods get executed when CompareFields is called for the 185 // basic types (instead of submessages). They return true on success. One 186 // can use ResultFromBoolean() to convert that boolean to a ComparisonResult 187 // value. CompareBool(const FieldDescriptor &,bool value_1,bool value_2)188 bool CompareBool(const FieldDescriptor& /* unused */, bool value_1, 189 bool value_2) { 190 return value_1 == value_2; 191 } 192 193 // Uses CompareDoubleOrFloat, a helper function used by both CompareDouble and 194 // CompareFloat. 195 bool CompareDouble(const FieldDescriptor& field, double value_1, 196 double value_2); 197 198 bool CompareEnum(const FieldDescriptor& field, 199 const EnumValueDescriptor* value_1, 200 const EnumValueDescriptor* value_2); 201 202 // Uses CompareDoubleOrFloat, a helper function used by both CompareDouble and 203 // CompareFloat. 204 bool CompareFloat(const FieldDescriptor& field, float value_1, float value_2); 205 CompareInt32(const FieldDescriptor &,int32_t value_1,int32_t value_2)206 bool CompareInt32(const FieldDescriptor& /* unused */, int32_t value_1, 207 int32_t value_2) { 208 return value_1 == value_2; 209 } 210 CompareInt64(const FieldDescriptor &,int64_t value_1,int64_t value_2)211 bool CompareInt64(const FieldDescriptor& /* unused */, int64_t value_1, 212 int64_t value_2) { 213 return value_1 == value_2; 214 } 215 CompareString(const FieldDescriptor &,const std::string & value_1,const std::string & value_2)216 bool CompareString(const FieldDescriptor& /* unused */, 217 const std::string& value_1, const std::string& value_2) { 218 return value_1 == value_2; 219 } 220 CompareUInt32(const FieldDescriptor &,uint32_t value_1,uint32_t value_2)221 bool CompareUInt32(const FieldDescriptor& /* unused */, uint32_t value_1, 222 uint32_t value_2) { 223 return value_1 == value_2; 224 } 225 CompareUInt64(const FieldDescriptor &,uint64_t value_1,uint64_t value_2)226 bool CompareUInt64(const FieldDescriptor& /* unused */, uint64_t value_1, 227 uint64_t value_2) { 228 return value_1 == value_2; 229 } 230 231 // This function is used by CompareDouble and CompareFloat to avoid code 232 // duplication. There are no checks done against types of the values passed, 233 // but it's likely to fail if passed non-numeric arguments. 234 template <typename T> 235 bool CompareDoubleOrFloat(const FieldDescriptor& field, T value_1, T value_2); 236 237 FloatComparison float_comparison_; 238 239 // If true, floats and doubles that are both NaN are considered to be 240 // equal. Otherwise, two floats or doubles that are NaN are considered to be 241 // different. 242 bool treat_nan_as_equal_; 243 244 // True iff default_tolerance_ has been explicitly set. 245 // 246 // If false, then the default tolerance for floats and doubles is that which 247 // is used by MathUtil::AlmostEquals(). 248 bool has_default_tolerance_; 249 250 // Default float/double tolerance. Only meaningful if 251 // has_default_tolerance_ == true. 252 Tolerance default_tolerance_; 253 254 // Field-specific float/double tolerances, which override any default for 255 // those particular fields. 256 ToleranceMap map_tolerance_; 257 258 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SimpleFieldComparator); 259 }; 260 261 // Default field comparison: use the basic implementation of FieldComparator. 262 #ifdef PROTOBUF_FUTURE_BREAKING_CHANGES 263 class PROTOBUF_EXPORT DefaultFieldComparator final 264 : public SimpleFieldComparator 265 #else // PROTOBUF_FUTURE_BREAKING_CHANGES 266 class PROTOBUF_EXPORT DefaultFieldComparator : public SimpleFieldComparator 267 #endif // PROTOBUF_FUTURE_BREAKING_CHANGES 268 { 269 public: Compare(const Message & message_1,const Message & message_2,const FieldDescriptor * field,int index_1,int index_2,const util::FieldContext * field_context)270 ComparisonResult Compare(const Message& message_1, const Message& message_2, 271 const FieldDescriptor* field, int index_1, 272 int index_2, 273 const util::FieldContext* field_context) override { 274 return SimpleCompare(message_1, message_2, field, index_1, index_2, 275 field_context); 276 } 277 }; 278 279 } // namespace util 280 } // namespace protobuf 281 } // namespace google 282 283 #include <google/protobuf/port_undef.inc> 284 285 #endif // GOOGLE_PROTOBUF_UTIL_FIELD_COMPARATOR_H__ 286