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