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 | |
37 | #include <cstdint> |
38 | #include <map> |
39 | #include <string> |
40 | #include <vector> |
41 | |
42 | #include <google/protobuf/stubs/common.h> |
43 | |
44 | // Must be included last. |
45 | #include <google/protobuf/port_def.inc> |
46 | |
47 | namespace google { |
48 | namespace protobuf { |
49 | |
50 | class Message; |
51 | class EnumValueDescriptor; |
52 | class FieldDescriptor; |
53 | |
54 | namespace util { |
55 | |
56 | class FieldContext; |
57 | class MessageDifferencer; |
58 | |
59 | // Base class specifying the interface for comparing protocol buffer fields. |
60 | // Regular users should consider using or subclassing DefaultFieldComparator |
61 | // rather than this interface. |
62 | // Currently, this does not support comparing unknown fields. |
63 | class PROTOBUF_EXPORT FieldComparator { |
64 | public: |
65 | FieldComparator(); |
66 | virtual ~FieldComparator(); |
67 | |
68 | enum ComparisonResult { |
69 | SAME, // Compared fields are equal. In case of comparing submessages, |
70 | // user should not recursively compare their contents. |
71 | DIFFERENT, // Compared fields are different. In case of comparing |
72 | // submessages, user should not recursively compare their |
73 | // contents. |
74 | RECURSE, // Compared submessages need to be compared recursively. |
75 | // FieldComparator does not specify the semantics of recursive |
76 | // comparison. This value should not be returned for simple |
77 | // values. |
78 | }; |
79 | |
80 | // Compares the values of a field in two protocol buffer messages. |
81 | // Returns SAME or DIFFERENT for simple values, and SAME, DIFFERENT or RECURSE |
82 | // for submessages. Returning RECURSE for fields not being submessages is |
83 | // illegal. |
84 | // In case the given FieldDescriptor points to a repeated field, the indices |
85 | // need to be valid. Otherwise they should be ignored. |
86 | // |
87 | // FieldContext contains information about the specific instances of the |
88 | // fields being compared, versus FieldDescriptor which only contains general |
89 | // type information about the fields. |
90 | virtual ComparisonResult Compare(const Message& message_1, |
91 | const Message& message_2, |
92 | const FieldDescriptor* field, int index_1, |
93 | int index_2, |
94 | const util::FieldContext* field_context) = 0; |
95 | |
96 | private: |
97 | GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldComparator); |
98 | }; |
99 | |
100 | // Basic implementation of FieldComparator. Supports three modes of floating |
101 | // point value comparison: exact, approximate using MathUtil::AlmostEqual |
102 | // method, and arbitrarily precise using MathUtil::WithinFractionOrMargin. |
103 | class PROTOBUF_EXPORT SimpleFieldComparator : public FieldComparator { |
104 | public: |
105 | enum FloatComparison { |
106 | EXACT, // Floats and doubles are compared exactly. |
107 | APPROXIMATE, // Floats and doubles are compared using the |
108 | // MathUtil::AlmostEqual method or |
109 | // MathUtil::WithinFractionOrMargin method. |
110 | // TODO(ksroka): Introduce third value to differentiate uses of AlmostEqual |
111 | // and WithinFractionOrMargin. |
112 | }; |
113 | |
114 | // Creates new comparator with float comparison set to EXACT. |
115 | SimpleFieldComparator(); |
116 | |
117 | ~SimpleFieldComparator() override; |
118 | |
119 | void set_float_comparison(FloatComparison float_comparison) { |
120 | float_comparison_ = float_comparison; |
121 | } |
122 | |
123 | FloatComparison float_comparison() const { return float_comparison_; } |
124 | |
125 | // Set whether the FieldComparator shall treat floats or doubles that are both |
126 | // NaN as equal (treat_nan_as_equal = true) or as different |
127 | // (treat_nan_as_equal = false). Default is treating NaNs always as different. |
128 | void set_treat_nan_as_equal(bool treat_nan_as_equal) { |
129 | treat_nan_as_equal_ = treat_nan_as_equal; |
130 | } |
131 | |
132 | bool treat_nan_as_equal() const { return treat_nan_as_equal_; } |
133 | |
134 | // Sets the fraction and margin for the float comparison of a given field. |
135 | // Uses MathUtil::WithinFractionOrMargin to compare the values. |
136 | // |
137 | // REQUIRES: field->cpp_type == FieldDescriptor::CPPTYPE_DOUBLE or |
138 | // field->cpp_type == FieldDescriptor::CPPTYPE_FLOAT |
139 | // REQUIRES: float_comparison_ == APPROXIMATE |
140 | void SetFractionAndMargin(const FieldDescriptor* field, double fraction, |
141 | double margin); |
142 | |
143 | // Sets the fraction and margin for the float comparison of all float and |
144 | // double fields, unless a field has been given a specific setting via |
145 | // SetFractionAndMargin() above. |
146 | // Uses MathUtil::WithinFractionOrMargin to compare the values. |
147 | // |
148 | // REQUIRES: float_comparison_ == APPROXIMATE |
149 | void SetDefaultFractionAndMargin(double fraction, double margin); |
150 | |
151 | protected: |
152 | // Returns the comparison result for the given field in two messages. |
153 | // |
154 | // This function is called directly by DefaultFieldComparator::Compare. |
155 | // Subclasses can call this function to compare fields they do not need to |
156 | // handle specially. |
157 | ComparisonResult SimpleCompare(const Message& message_1, |
158 | const Message& message_2, |
159 | const FieldDescriptor* field, int index_1, |
160 | int index_2, |
161 | const util::FieldContext* field_context); |
162 | |
163 | // Compare using the provided message_differencer. For example, a subclass can |
164 | // use this method to compare some field in a certain way using the same |
165 | // message_differencer instance and the field context. |
166 | bool CompareWithDifferencer(MessageDifferencer* differencer, |
167 | const Message& message1, const Message& message2, |
168 | const util::FieldContext* field_context); |
169 | |
170 | // Returns FieldComparator::SAME if boolean_result is true and |
171 | // FieldComparator::DIFFERENT otherwise. |
172 | ComparisonResult ResultFromBoolean(bool boolean_result) const; |
173 | |
174 | private: |
175 | // Defines the tolerance for floating point comparison (fraction and margin). |
176 | struct Tolerance { |
177 | double fraction; |
178 | double margin; |
179 | Tolerance() : fraction(0.0), margin(0.0) {} |
180 | Tolerance(double f, double m) : fraction(f), margin(m) {} |
181 | }; |
182 | |
183 | // Defines the map to store the tolerances for floating point comparison. |
184 | typedef std::map<const FieldDescriptor*, Tolerance> ToleranceMap; |
185 | |
186 | friend class MessageDifferencer; |
187 | // The following methods get executed when CompareFields is called for the |
188 | // basic types (instead of submessages). They return true on success. One |
189 | // can use ResultFromBoolean() to convert that boolean to a ComparisonResult |
190 | // value. |
191 | bool CompareBool(const FieldDescriptor& /* unused */, bool value_1, |
192 | bool value_2) { |
193 | return value_1 == value_2; |
194 | } |
195 | |
196 | // Uses CompareDoubleOrFloat, a helper function used by both CompareDouble and |
197 | // CompareFloat. |
198 | bool CompareDouble(const FieldDescriptor& field, double value_1, |
199 | double value_2); |
200 | |
201 | bool CompareEnum(const FieldDescriptor& field, |
202 | const EnumValueDescriptor* value_1, |
203 | const EnumValueDescriptor* value_2); |
204 | |
205 | // Uses CompareDoubleOrFloat, a helper function used by both CompareDouble and |
206 | // CompareFloat. |
207 | bool CompareFloat(const FieldDescriptor& field, float value_1, float value_2); |
208 | |
209 | bool CompareInt32(const FieldDescriptor& /* unused */, int32_t value_1, |
210 | int32_t value_2) { |
211 | return value_1 == value_2; |
212 | } |
213 | |
214 | bool CompareInt64(const FieldDescriptor& /* unused */, int64_t value_1, |
215 | int64_t value_2) { |
216 | return value_1 == value_2; |
217 | } |
218 | |
219 | bool CompareString(const FieldDescriptor& /* unused */, |
220 | const std::string& value_1, const std::string& value_2) { |
221 | return value_1 == value_2; |
222 | } |
223 | |
224 | bool CompareUInt32(const FieldDescriptor& /* unused */, uint32_t value_1, |
225 | uint32_t value_2) { |
226 | return value_1 == value_2; |
227 | } |
228 | |
229 | bool CompareUInt64(const FieldDescriptor& /* unused */, uint64_t value_1, |
230 | uint64_t value_2) { |
231 | return value_1 == value_2; |
232 | } |
233 | |
234 | // This function is used by CompareDouble and CompareFloat to avoid code |
235 | // duplication. There are no checks done against types of the values passed, |
236 | // but it's likely to fail if passed non-numeric arguments. |
237 | template <typename T> |
238 | bool CompareDoubleOrFloat(const FieldDescriptor& field, T value_1, T value_2); |
239 | |
240 | FloatComparison float_comparison_; |
241 | |
242 | // If true, floats and doubles that are both NaN are considered to be |
243 | // equal. Otherwise, two floats or doubles that are NaN are considered to be |
244 | // different. |
245 | bool treat_nan_as_equal_; |
246 | |
247 | // True iff default_tolerance_ has been explicitly set. |
248 | // |
249 | // If false, then the default tolerance for floats and doubles is that which |
250 | // is used by MathUtil::AlmostEquals(). |
251 | bool has_default_tolerance_; |
252 | |
253 | // Default float/double tolerance. Only meaningful if |
254 | // has_default_tolerance_ == true. |
255 | Tolerance default_tolerance_; |
256 | |
257 | // Field-specific float/double tolerances, which override any default for |
258 | // those particular fields. |
259 | ToleranceMap map_tolerance_; |
260 | |
261 | GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SimpleFieldComparator); |
262 | }; |
263 | |
264 | // Default field comparison: use the basic implementation of FieldComparator. |
265 | #ifdef PROTOBUF_FUTURE_BREAKING_CHANGES |
266 | class PROTOBUF_EXPORT DefaultFieldComparator final |
267 | : public SimpleFieldComparator |
268 | #else // PROTOBUF_FUTURE_BREAKING_CHANGES |
269 | class PROTOBUF_EXPORT DefaultFieldComparator : public SimpleFieldComparator |
270 | #endif // PROTOBUF_FUTURE_BREAKING_CHANGES |
271 | { |
272 | public: |
273 | ComparisonResult Compare(const Message& message_1, const Message& message_2, |
274 | const FieldDescriptor* field, int index_1, |
275 | int index_2, |
276 | const util::FieldContext* field_context) override { |
277 | return SimpleCompare(message_1, message_2, field, index_1, index_2, |
278 | field_context); |
279 | } |
280 | }; |
281 | |
282 | } // namespace util |
283 | } // namespace protobuf |
284 | } // namespace google |
285 | |
286 | #include <google/protobuf/port_undef.inc> |
287 | |
288 | #endif // GOOGLE_PROTOBUF_UTIL_FIELD_COMPARATOR_H__ |
289 | |