protobuf/src/google/protobuf/util/field_comparator.cc
Go to the documentation of this file.
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 // Author: ksroka@google.com (Krzysztof Sroka)
32 
33 #include <google/protobuf/util/field_comparator.h>
34 
35 #include <limits>
36 #include <string>
37 
38 #include <google/protobuf/descriptor.h>
39 #include <google/protobuf/message.h>
40 #include <google/protobuf/util/message_differencer.h>
41 #include <google/protobuf/stubs/map_util.h>
42 #include <google/protobuf/stubs/mathutil.h>
43 
44 namespace google {
45 namespace protobuf {
46 namespace util {
47 
50 
52  : float_comparison_(EXACT),
53  treat_nan_as_equal_(false),
54  has_default_tolerance_(false) {}
55 
57 
59  const Message& message_1, const Message& message_2,
60  const FieldDescriptor* field, int index_1, int index_2,
61  const util::FieldContext* /*field_context*/) {
62  const Reflection* reflection_1 = message_1.GetReflection();
63  const Reflection* reflection_2 = message_2.GetReflection();
64 
65  switch (field->cpp_type()) {
66 #define COMPARE_FIELD(METHOD) \
67  if (field->is_repeated()) { \
68  return ResultFromBoolean(Compare##METHOD( \
69  *field, reflection_1->GetRepeated##METHOD(message_1, field, index_1), \
70  reflection_2->GetRepeated##METHOD(message_2, field, index_2))); \
71  } else { \
72  return ResultFromBoolean( \
73  Compare##METHOD(*field, reflection_1->Get##METHOD(message_1, field), \
74  reflection_2->Get##METHOD(message_2, field))); \
75  } \
76  break; // Make sure no fall-through is introduced.
77 
91  if (field->is_repeated()) {
92  // Allocate scratch strings to store the result if a conversion is
93  // needed.
94  std::string scratch1;
95  std::string scratch2;
96  return ResultFromBoolean(
98  reflection_1->GetRepeatedStringReference(
99  message_1, field, index_1, &scratch1),
100  reflection_2->GetRepeatedStringReference(
101  message_2, field, index_2, &scratch2)));
102  } else {
103  // Allocate scratch strings to store the result if a conversion is
104  // needed.
105  std::string scratch1;
106  std::string scratch2;
108  *field,
109  reflection_1->GetStringReference(message_1, field, &scratch1),
110  reflection_2->GetStringReference(message_2, field, &scratch2)));
111  }
112  break;
117 
118 #undef COMPARE_FIELD
119 
121  return RECURSE;
122 
123  default:
124  GOOGLE_LOG(FATAL) << "No comparison code for field " << field->full_name()
125  << " of CppType = " << field->cpp_type();
126  return DIFFERENT;
127  }
128 }
129 
131  MessageDifferencer* differencer, const Message& message1,
132  const Message& message2, const util::FieldContext* field_context) {
133  return differencer->Compare(message1, message2,
134  field_context->parent_fields());
135 }
136 
138  double margin) {
139  default_tolerance_ = Tolerance(fraction, margin);
140  has_default_tolerance_ = true;
141 }
142 
144  double fraction,
145  double margin) {
147  FieldDescriptor::CPPTYPE_DOUBLE == field->cpp_type())
148  << "Field has to be float or double type. Field name is: "
149  << field->full_name();
150  map_tolerance_[field] = Tolerance(fraction, margin);
151 }
152 
154  double value_1, double value_2) {
155  return CompareDoubleOrFloat(field, value_1, value_2);
156 }
157 
159  const EnumValueDescriptor* value_1,
160  const EnumValueDescriptor* value_2) {
161  return value_1->number() == value_2->number();
162 }
163 
165  float value_1, float value_2) {
166  return CompareDoubleOrFloat(field, value_1, value_2);
167 }
168 
169 template <typename T>
171  T value_1, T value_2) {
172  if (value_1 == value_2) {
173  // Covers +inf and -inf (which are not within margin or fraction of
174  // themselves), and is a shortcut for finite values.
175  return true;
176  } else if (float_comparison_ == EXACT) {
177  if (treat_nan_as_equal_ && std::isnan(value_1) && std::isnan(value_2)) {
178  return true;
179  }
180  return false;
181  } else {
182  if (treat_nan_as_equal_ && std::isnan(value_1) && std::isnan(value_2)) {
183  return true;
184  }
185  // float_comparison_ == APPROXIMATE covers two use cases.
186  Tolerance* tolerance = FindOrNull(map_tolerance_, &field);
187  if (tolerance == NULL && has_default_tolerance_) {
188  tolerance = &default_tolerance_;
189  }
190  if (tolerance == NULL) {
191  return MathUtil::AlmostEquals(value_1, value_2);
192  } else {
193  // Use user-provided fraction and margin. Since they are stored as
194  // doubles, we explicitly cast them to types of values provided. This
195  // is very likely to fail if provided values are not numeric.
197  value_1, value_2, static_cast<T>(tolerance->fraction),
198  static_cast<T>(tolerance->margin));
199  }
200  }
201 }
202 
204  bool boolean_result) const {
205  return boolean_result ? FieldComparator::SAME : FieldComparator::DIFFERENT;
206 }
207 
208 } // namespace util
209 } // namespace protobuf
210 } // namespace google
google::protobuf::util::SimpleFieldComparator::SimpleCompare
ComparisonResult SimpleCompare(const Message &message_1, const Message &message_2, const FieldDescriptor *field, int index_1, int index_2, const util::FieldContext *field_context)
Definition: protobuf/src/google/protobuf/util/field_comparator.cc:58
google::protobuf::Reflection::GetStringReference
const std::string & GetStringReference(const Message &message, const FieldDescriptor *field, std::string *scratch) const
Definition: bloaty/third_party/protobuf/src/google/protobuf/generated_message_reflection.cc:1171
google::protobuf::util::FieldComparator::RECURSE
@ RECURSE
Definition: bloaty/third_party/protobuf/src/google/protobuf/util/field_comparator.h:71
google::protobuf::FieldDescriptor
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.h:515
google::protobuf::util::MessageDifferencer
Definition: bloaty/third_party/protobuf/src/google/protobuf/util/message_differencer.h:120
google::protobuf::util::SimpleFieldComparator::CompareDouble
bool CompareDouble(const FieldDescriptor &field, double value_1, double value_2)
Definition: protobuf/src/google/protobuf/util/field_comparator.cc:153
testing::internal::Int32
TypeWithSize< 4 >::Int Int32
Definition: bloaty/third_party/googletest/googletest/include/gtest/internal/gtest-port.h:2159
google::protobuf::FieldDescriptor::CPPTYPE_STRING
@ CPPTYPE_STRING
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.h:562
google::protobuf::util::SimpleFieldComparator::SetFractionAndMargin
void SetFractionAndMargin(const FieldDescriptor *field, double fraction, double margin)
Definition: protobuf/src/google/protobuf/util/field_comparator.cc:143
Bool
Definition: bloaty/third_party/googletest/googletest/test/gtest_pred_impl_unittest.cc:56
tests.google.protobuf.internal.message_test.isnan
def isnan(val)
Definition: bloaty/third_party/protobuf/python/compatibility_tests/v2.5.0/tests/google/protobuf/internal/message_test.py:65
false
#define false
Definition: setup_once.h:323
google::protobuf::MathUtil::WithinFractionOrMargin
static bool WithinFractionOrMargin(const T x, const T y, const T fraction, const T margin)
Definition: bloaty/third_party/protobuf/src/google/protobuf/stubs/mathutil.h:115
google::protobuf::util::FieldComparator::~FieldComparator
virtual ~FieldComparator()
Definition: bloaty/third_party/protobuf/src/google/protobuf/util/field_comparator.cc:49
google::protobuf::Reflection::GetRepeatedStringReference
const std::string & GetRepeatedStringReference(const Message &message, const FieldDescriptor *field, int index, std::string *scratch) const
Definition: bloaty/third_party/protobuf/src/google/protobuf/generated_message_reflection.cc:1240
google::protobuf::Message::GetReflection
const Reflection * GetReflection() const
Definition: bloaty/third_party/protobuf/src/google/protobuf/message.h:332
testing::internal::string
::std::string string
Definition: bloaty/third_party/protobuf/third_party/googletest/googletest/include/gtest/internal/gtest-port.h:881
google::protobuf::util::SimpleFieldComparator::treat_nan_as_equal_
bool treat_nan_as_equal_
Definition: protobuf/src/google/protobuf/util/field_comparator.h:242
testing::internal::UInt64
TypeWithSize< 8 >::UInt UInt64
Definition: bloaty/third_party/googletest/googletest/include/gtest/internal/gtest-port.h:2162
google::protobuf
Definition: bloaty/third_party/protobuf/benchmarks/util/data_proto2_to_proto3_util.h:12
google::protobuf::util::SimpleFieldComparator::CompareString
bool CompareString(const FieldDescriptor &, const std::string &value_1, const std::string &value_2)
Definition: protobuf/src/google/protobuf/util/field_comparator.h:216
google::protobuf::util::SimpleFieldComparator::float_comparison_
FloatComparison float_comparison_
Definition: protobuf/src/google/protobuf/util/field_comparator.h:237
testing::internal::UInt32
TypeWithSize< 4 >::UInt UInt32
Definition: bloaty/third_party/googletest/googletest/include/gtest/internal/gtest-port.h:2160
google::protobuf::Reflection
Definition: bloaty/third_party/protobuf/src/google/protobuf/message.h:397
google::protobuf::util::SimpleFieldComparator::CompareFloat
bool CompareFloat(const FieldDescriptor &field, float value_1, float value_2)
Definition: protobuf/src/google/protobuf/util/field_comparator.cc:164
google::protobuf::util::FieldComparator::SAME
@ SAME
Definition: bloaty/third_party/protobuf/src/google/protobuf/util/field_comparator.h:66
T
#define T(upbtypeconst, upbtype, ctype, default_value)
Enum
Definition: bloaty/third_party/protobuf/src/google/protobuf/type.pb.h:867
google::protobuf::util::FieldComparator::DIFFERENT
@ DIFFERENT
Definition: bloaty/third_party/protobuf/src/google/protobuf/util/field_comparator.h:68
google::protobuf::util::FieldContext
Definition: bloaty/third_party/protobuf/src/google/protobuf/util/message_differencer.h:900
google::protobuf::util::SimpleFieldComparator::EXACT
@ EXACT
Definition: protobuf/src/google/protobuf/util/field_comparator.h:103
google::protobuf::util::SimpleFieldComparator::CompareEnum
bool CompareEnum(const FieldDescriptor &field, const EnumValueDescriptor *value_1, const EnumValueDescriptor *value_2)
Definition: protobuf/src/google/protobuf/util/field_comparator.cc:158
google::protobuf::util::SimpleFieldComparator::default_tolerance_
Tolerance default_tolerance_
Definition: protobuf/src/google/protobuf/util/field_comparator.h:252
google::protobuf::util::SimpleFieldComparator::Tolerance::fraction
double fraction
Definition: protobuf/src/google/protobuf/util/field_comparator.h:174
google::protobuf::util::MessageDifferencer::Compare
bool Compare(const Message &message1, const Message &message2)
Definition: bloaty/third_party/protobuf/src/google/protobuf/util/message_differencer.cc:481
testing::internal::Float
FloatingPoint< float > Float
Definition: bloaty/third_party/googletest/googletest/include/gtest/internal/gtest-internal.h:396
google::protobuf::EnumValueDescriptor::number
int number() const
google::protobuf::FieldDescriptor::CPPTYPE_UINT64
@ CPPTYPE_UINT64
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.h:557
google::protobuf::util::FieldContext::parent_fields
std::vector< MessageDifferencer::SpecificField > * parent_fields() const
Definition: bloaty/third_party/protobuf/src/google/protobuf/util/message_differencer.h:906
google::protobuf::util::SimpleFieldComparator::has_default_tolerance_
bool has_default_tolerance_
Definition: protobuf/src/google/protobuf/util/field_comparator.h:248
google::protobuf::util::SimpleFieldComparator::SetDefaultFractionAndMargin
void SetDefaultFractionAndMargin(double fraction, double margin)
Definition: protobuf/src/google/protobuf/util/field_comparator.cc:137
google::protobuf::FieldDescriptor::CPPTYPE_INT64
@ CPPTYPE_INT64
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.h:555
FATAL
#define FATAL(msg)
Definition: task.h:88
google::protobuf::Message
Definition: bloaty/third_party/protobuf/src/google/protobuf/message.h:205
field
const FieldDescriptor * field
Definition: bloaty/third_party/protobuf/src/google/protobuf/compiler/parser_unittest.cc:2692
google::protobuf::util::SimpleFieldComparator::CompareDoubleOrFloat
bool CompareDoubleOrFloat(const FieldDescriptor &field, T value_1, T value_2)
Definition: protobuf/src/google/protobuf/util/field_comparator.cc:170
google::protobuf::FieldDescriptor::CPPTYPE_UINT32
@ CPPTYPE_UINT32
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.h:556
google::protobuf::FieldDescriptor::CPPTYPE_FLOAT
@ CPPTYPE_FLOAT
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.h:559
google::protobuf::util::SimpleFieldComparator::Tolerance::margin
double margin
Definition: protobuf/src/google/protobuf/util/field_comparator.h:175
google::protobuf::MathUtil::AlmostEquals
static bool AlmostEquals(T a, T b)
Definition: bloaty/third_party/protobuf/src/google/protobuf/stubs/mathutil.h:69
google::protobuf::FieldDescriptor::CPPTYPE_BOOL
@ CPPTYPE_BOOL
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.h:560
google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE
@ CPPTYPE_DOUBLE
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.h:558
google::protobuf::util::SimpleFieldComparator::~SimpleFieldComparator
~SimpleFieldComparator() override
Definition: protobuf/src/google/protobuf/util/field_comparator.cc:56
google::protobuf::FieldDescriptor::CPPTYPE_ENUM
@ CPPTYPE_ENUM
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.h:561
testing::internal::Double
FloatingPoint< double > Double
Definition: bloaty/third_party/googletest/googletest/include/gtest/internal/gtest-internal.h:397
google::protobuf::util::SimpleFieldComparator::map_tolerance_
ToleranceMap map_tolerance_
Definition: protobuf/src/google/protobuf/util/field_comparator.h:256
google::protobuf::EnumValueDescriptor
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.h:1075
google::protobuf::util::SimpleFieldComparator::SimpleFieldComparator
SimpleFieldComparator()
Definition: protobuf/src/google/protobuf/util/field_comparator.cc:51
GOOGLE_CHECK
#define GOOGLE_CHECK(EXPRESSION)
Definition: bloaty/third_party/protobuf/src/google/protobuf/stubs/logging.h:153
google::protobuf::util::SimpleFieldComparator::Tolerance
Definition: protobuf/src/google/protobuf/util/field_comparator.h:173
google::protobuf::util::FieldComparator::ComparisonResult
ComparisonResult
Definition: bloaty/third_party/protobuf/src/google/protobuf/util/field_comparator.h:65
google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE
@ CPPTYPE_MESSAGE
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.h:563
testing::internal::Int64
TypeWithSize< 8 >::Int Int64
Definition: bloaty/third_party/googletest/googletest/include/gtest/internal/gtest-port.h:2161
google::protobuf::util::SimpleFieldComparator::CompareWithDifferencer
bool CompareWithDifferencer(MessageDifferencer *differencer, const Message &message1, const Message &message2, const util::FieldContext *field_context)
Definition: protobuf/src/google/protobuf/util/field_comparator.cc:130
google::protobuf::util::FieldComparator::FieldComparator
FieldComparator()
Definition: bloaty/third_party/protobuf/src/google/protobuf/util/field_comparator.cc:48
GOOGLE_LOG
#define GOOGLE_LOG(LEVEL)
Definition: bloaty/third_party/protobuf/src/google/protobuf/stubs/logging.h:146
google::protobuf::util::SimpleFieldComparator::ResultFromBoolean
ComparisonResult ResultFromBoolean(bool boolean_result) const
Definition: protobuf/src/google/protobuf/util/field_comparator.cc:203
google::protobuf::FindOrNull
const Collection::value_type::second_type * FindOrNull(const Collection &collection, const typename Collection::value_type::first_type &key)
Definition: bloaty/third_party/protobuf/src/google/protobuf/stubs/map_util.h:137
google
Definition: bloaty/third_party/protobuf/benchmarks/util/data_proto2_to_proto3_util.h:11
COMPARE_FIELD
#define COMPARE_FIELD(METHOD)
google::protobuf::FieldDescriptor::CPPTYPE_INT32
@ CPPTYPE_INT32
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.h:554


grpc
Author(s):
autogenerated on Fri May 16 2025 02:58:22