field_comparator.h 10 KB

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