Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-31 10:12:04

0001 // Protocol Buffers - Google's data interchange format
0002 // Copyright 2008 Google Inc.  All rights reserved.
0003 //
0004 // Use of this source code is governed by a BSD-style
0005 // license that can be found in the LICENSE file or at
0006 // https://developers.google.com/open-source/licenses/bsd
0007 
0008 // Defines classes for field comparison.
0009 
0010 #ifndef GOOGLE_PROTOBUF_UTIL_FIELD_COMPARATOR_H__
0011 #define GOOGLE_PROTOBUF_UTIL_FIELD_COMPARATOR_H__
0012 
0013 #include <cstdint>
0014 #include <string>
0015 #include <vector>
0016 
0017 #include "google/protobuf/stubs/common.h"
0018 #include "absl/container/flat_hash_map.h"
0019 #include "google/protobuf/port.h"
0020 
0021 // Must be included last.
0022 #include "google/protobuf/port_def.inc"
0023 
0024 namespace google {
0025 namespace protobuf {
0026 
0027 class Message;
0028 class EnumValueDescriptor;
0029 class FieldDescriptor;
0030 
0031 namespace util {
0032 
0033 class FieldContext;
0034 class MessageDifferencer;
0035 
0036 // Base class specifying the interface for comparing protocol buffer fields.
0037 // Regular users should consider using or subclassing DefaultFieldComparator
0038 // rather than this interface.
0039 // Currently, this does not support comparing unknown fields.
0040 class PROTOBUF_EXPORT FieldComparator {
0041  public:
0042   FieldComparator();
0043   FieldComparator(const FieldComparator&) = delete;
0044   FieldComparator& operator=(const FieldComparator&) = delete;
0045   virtual ~FieldComparator();
0046 
0047   enum ComparisonResult {
0048     SAME,       // Compared fields are equal. In case of comparing submessages,
0049                 // user should not recursively compare their contents.
0050     DIFFERENT,  // Compared fields are different. In case of comparing
0051                 // submessages, user should not recursively compare their
0052                 // contents.
0053     RECURSE,    // Compared submessages need to be compared recursively.
0054                 // FieldComparator does not specify the semantics of recursive
0055                 // comparison. This value should not be returned for simple
0056                 // values.
0057   };
0058 
0059   // Compares the values of a field in two protocol buffer messages.
0060   // Returns SAME or DIFFERENT for simple values, and SAME, DIFFERENT or RECURSE
0061   // for submessages. Returning RECURSE for fields not being submessages is
0062   // illegal.
0063   // In case the given FieldDescriptor points to a repeated field, the indices
0064   // need to be valid. Otherwise they should be ignored.
0065   //
0066   // FieldContext contains information about the specific instances of the
0067   // fields being compared, versus FieldDescriptor which only contains general
0068   // type information about the fields.
0069   virtual ComparisonResult Compare(const Message& message_1,
0070                                    const Message& message_2,
0071                                    const FieldDescriptor* field, int index_1,
0072                                    int index_2,
0073                                    const util::FieldContext* field_context) = 0;
0074 };
0075 
0076 // Basic implementation of FieldComparator.  Supports three modes of floating
0077 // point value comparison: exact, approximate using MathUtil::AlmostEqual
0078 // method, and arbitrarily precise using MathUtil::WithinFractionOrMargin.
0079 class PROTOBUF_EXPORT SimpleFieldComparator : public FieldComparator {
0080  public:
0081   enum FloatComparison {
0082     EXACT,        // Floats and doubles are compared exactly.
0083     APPROXIMATE,  // Floats and doubles are compared using the
0084                   // MathUtil::AlmostEqual method or
0085                   // MathUtil::WithinFractionOrMargin method.
0086     // TODO: Introduce third value to differentiate uses of AlmostEqual
0087     //               and WithinFractionOrMargin.
0088   };
0089 
0090   // Creates new comparator with float comparison set to EXACT.
0091   SimpleFieldComparator();
0092   SimpleFieldComparator(const SimpleFieldComparator&) = delete;
0093   SimpleFieldComparator& operator=(const SimpleFieldComparator&) = delete;
0094 
0095   ~SimpleFieldComparator() override;
0096 
0097   void set_float_comparison(FloatComparison float_comparison) {
0098     float_comparison_ = float_comparison;
0099   }
0100 
0101   FloatComparison float_comparison() const { return float_comparison_; }
0102 
0103   // Set whether the FieldComparator shall treat floats or doubles that are both
0104   // NaN as equal (treat_nan_as_equal = true) or as different
0105   // (treat_nan_as_equal = false). Default is treating NaNs always as different.
0106   void set_treat_nan_as_equal(bool treat_nan_as_equal) {
0107     treat_nan_as_equal_ = treat_nan_as_equal;
0108   }
0109 
0110   bool treat_nan_as_equal() const { return treat_nan_as_equal_; }
0111 
0112   // Sets the fraction and margin for the float comparison of a given field.
0113   // Uses MathUtil::WithinFractionOrMargin to compare the values.
0114   //
0115   // REQUIRES: field->cpp_type == FieldDescriptor::CPPTYPE_DOUBLE or
0116   //           field->cpp_type == FieldDescriptor::CPPTYPE_FLOAT
0117   // REQUIRES: float_comparison_ == APPROXIMATE
0118   void SetFractionAndMargin(const FieldDescriptor* field, double fraction,
0119                             double margin);
0120 
0121   // Sets the fraction and margin for the float comparison of all float and
0122   // double fields, unless a field has been given a specific setting via
0123   // SetFractionAndMargin() above.
0124   // Uses MathUtil::WithinFractionOrMargin to compare the values.
0125   //
0126   // REQUIRES: float_comparison_ == APPROXIMATE
0127   void SetDefaultFractionAndMargin(double fraction, double margin);
0128 
0129  protected:
0130   // Returns the comparison result for the given field in two messages.
0131   //
0132   // This function is called directly by DefaultFieldComparator::Compare.
0133   // Subclasses can call this function to compare fields they do not need to
0134   // handle specially.
0135   ComparisonResult SimpleCompare(const Message& message_1,
0136                                  const Message& message_2,
0137                                  const FieldDescriptor* field, int index_1,
0138                                  int index_2,
0139                                  const util::FieldContext* field_context);
0140 
0141   // Compare using the provided message_differencer. For example, a subclass can
0142   // use this method to compare some field in a certain way using the same
0143   // message_differencer instance and the field context.
0144   bool CompareWithDifferencer(MessageDifferencer* differencer,
0145                               const Message& message1, const Message& message2,
0146                               const util::FieldContext* field_context);
0147 
0148   // Returns FieldComparator::SAME if boolean_result is true and
0149   // FieldComparator::DIFFERENT otherwise.
0150   ComparisonResult ResultFromBoolean(bool boolean_result) const;
0151 
0152  private:
0153   // Defines the tolerance for floating point comparison (fraction and margin).
0154   struct Tolerance {
0155     double fraction;
0156     double margin;
0157     Tolerance() : fraction(0.0), margin(0.0) {}
0158     Tolerance(double f, double m) : fraction(f), margin(m) {}
0159   };
0160 
0161   friend class MessageDifferencer;
0162   // The following methods get executed when CompareFields is called for the
0163   // basic types (instead of submessages). They return true on success. One
0164   // can use ResultFromBoolean() to convert that boolean to a ComparisonResult
0165   // value.
0166   bool CompareBool(const FieldDescriptor& /* unused */, bool value_1,
0167                    bool value_2) {
0168     return value_1 == value_2;
0169   }
0170 
0171   // Uses CompareDoubleOrFloat, a helper function used by both CompareDouble and
0172   // CompareFloat.
0173   bool CompareDouble(const FieldDescriptor& field, double value_1,
0174                      double value_2);
0175 
0176   bool CompareEnum(const FieldDescriptor& field,
0177                    const EnumValueDescriptor* value_1,
0178                    const EnumValueDescriptor* value_2);
0179 
0180   // Uses CompareDoubleOrFloat, a helper function used by both CompareDouble and
0181   // CompareFloat.
0182   bool CompareFloat(const FieldDescriptor& field, float value_1, float value_2);
0183 
0184   bool CompareInt32(const FieldDescriptor& /* unused */, int32_t value_1,
0185                     int32_t value_2) {
0186     return value_1 == value_2;
0187   }
0188 
0189   bool CompareInt64(const FieldDescriptor& /* unused */, int64_t value_1,
0190                     int64_t value_2) {
0191     return value_1 == value_2;
0192   }
0193 
0194   bool CompareString(const FieldDescriptor& /* unused */,
0195                      const std::string& value_1, const std::string& value_2) {
0196     return value_1 == value_2;
0197   }
0198 
0199   bool CompareUInt32(const FieldDescriptor& /* unused */, uint32_t value_1,
0200                      uint32_t value_2) {
0201     return value_1 == value_2;
0202   }
0203 
0204   bool CompareUInt64(const FieldDescriptor& /* unused */, uint64_t value_1,
0205                      uint64_t value_2) {
0206     return value_1 == value_2;
0207   }
0208 
0209   // This function is used by CompareDouble and CompareFloat to avoid code
0210   // duplication. There are no checks done against types of the values passed,
0211   // but it's likely to fail if passed non-numeric arguments.
0212   template <typename T>
0213   bool CompareDoubleOrFloat(const FieldDescriptor& field, T value_1, T value_2);
0214 
0215   FloatComparison float_comparison_;
0216 
0217   // If true, floats and doubles that are both NaN are considered to be
0218   // equal. Otherwise, two floats or doubles that are NaN are considered to be
0219   // different.
0220   bool treat_nan_as_equal_;
0221 
0222   // True iff default_tolerance_ has been explicitly set.
0223   //
0224   // If false, then the default tolerance for floats and doubles is that which
0225   // is used by MathUtil::AlmostEquals().
0226   bool has_default_tolerance_;
0227 
0228   // Default float/double tolerance. Only meaningful if
0229   // has_default_tolerance_ == true.
0230   Tolerance default_tolerance_;
0231 
0232   // Field-specific float/double tolerances, which override any default for
0233   // those particular fields.
0234   absl::flat_hash_map<const FieldDescriptor*, Tolerance> map_tolerance_;
0235 };
0236 
0237 // Default field comparison: use the basic implementation of FieldComparator.
0238 class PROTOBUF_EXPORT DefaultFieldComparator final
0239     : public SimpleFieldComparator {
0240  public:
0241   ComparisonResult Compare(const Message& message_1, const Message& message_2,
0242                            const FieldDescriptor* field, int index_1,
0243                            int index_2,
0244                            const util::FieldContext* field_context) override {
0245     return SimpleCompare(message_1, message_2, field, index_1, index_2,
0246                          field_context);
0247   }
0248 };
0249 
0250 }  // namespace util
0251 }  // namespace protobuf
0252 }  // namespace google
0253 
0254 #include "google/protobuf/port_undef.inc"
0255 
0256 #endif  // GOOGLE_PROTOBUF_UTIL_FIELD_COMPARATOR_H__