Minh Nguyen / ArduinoJson
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers VariantCompare.hpp Source File

VariantCompare.hpp

00001 // ArduinoJson - arduinojson.org
00002 // Copyright Benoit Blanchon 2014-2021
00003 // MIT License
00004 
00005 #pragma once
00006 
00007 #include <ArduinoJson/Configuration.hpp>
00008 #include <ArduinoJson/Misc/Visitable.hpp>
00009 #include <ArduinoJson/Numbers/arithmeticCompare.hpp>
00010 #include <ArduinoJson/Polyfills/type_traits.hpp>
00011 #include <ArduinoJson/Strings/IsString.hpp>
00012 
00013 namespace ARDUINOJSON_NAMESPACE {
00014 
00015 class CollectionData;
00016 
00017 struct ComparerBase : Visitor<CompareResult> {
00018   CompareResult visitArray(const CollectionData &) {
00019     return COMPARE_RESULT_DIFFER;
00020   }
00021   CompareResult visitBoolean(bool) {
00022     return COMPARE_RESULT_DIFFER;
00023   }
00024   CompareResult visitFloat(Float) {
00025     return COMPARE_RESULT_DIFFER;
00026   }
00027   CompareResult visitNegativeInteger(UInt) {
00028     return COMPARE_RESULT_DIFFER;
00029   }
00030   CompareResult visitNull() {
00031     return COMPARE_RESULT_DIFFER;
00032   }
00033   CompareResult visitObject(const CollectionData &) {
00034     return COMPARE_RESULT_DIFFER;
00035   }
00036   CompareResult visitPositiveInteger(UInt) {
00037     return COMPARE_RESULT_DIFFER;
00038   }
00039   CompareResult visitRawJson(const char *, size_t) {
00040     return COMPARE_RESULT_DIFFER;
00041   }
00042   CompareResult visitString(const char *) {
00043     return COMPARE_RESULT_DIFFER;
00044   }
00045 };
00046 
00047 template <typename T, typename Enable = void>
00048 struct Comparer;
00049 
00050 template <typename T>
00051 struct Comparer<T, typename enable_if<IsString<T>::value>::type>
00052     : ComparerBase {
00053   T rhs;
00054 
00055   explicit Comparer(T value) : rhs(value) {}
00056 
00057   CompareResult visitString(const char *lhs) {
00058     int i = adaptString(rhs).compare(lhs);
00059     if (i < 0)
00060       return COMPARE_RESULT_GREATER;
00061     else if (i > 0)
00062       return COMPARE_RESULT_LESS;
00063     else
00064       return COMPARE_RESULT_EQUAL;
00065   }
00066 
00067   CompareResult visitNull() {
00068     if (adaptString(rhs).isNull())
00069       return COMPARE_RESULT_EQUAL;
00070     else
00071       return COMPARE_RESULT_DIFFER;
00072   }
00073 };
00074 
00075 template <typename T>
00076 struct Comparer<T, typename enable_if<is_integral<T>::value ||
00077                                       is_floating_point<T>::value>::type>
00078     : ComparerBase {
00079   T rhs;
00080 
00081   explicit Comparer(T value) : rhs(value) {}
00082 
00083   CompareResult visitFloat(Float lhs) {
00084     return arithmeticCompare(lhs, rhs);
00085   }
00086 
00087   CompareResult visitNegativeInteger(UInt lhs) {
00088     return arithmeticCompareNegateLeft(lhs, rhs);
00089   }
00090 
00091   CompareResult visitPositiveInteger(UInt lhs) {
00092     return arithmeticCompare(lhs, rhs);
00093   }
00094 
00095   CompareResult visitBoolean(bool lhs) {
00096     return visitPositiveInteger(static_cast<UInt>(lhs));
00097   }
00098 };
00099 
00100 struct NullComparer : ComparerBase {
00101   CompareResult visitNull() {
00102     return COMPARE_RESULT_EQUAL;
00103   }
00104 };
00105 
00106 #if ARDUINOJSON_HAS_NULLPTR
00107 template <>
00108 struct Comparer<decltype(nullptr), void> : NullComparer {
00109   explicit Comparer(decltype(nullptr)) : NullComparer() {}
00110 };
00111 #endif
00112 
00113 struct ArrayComparer : ComparerBase {
00114   const CollectionData *_rhs;
00115 
00116   explicit ArrayComparer(const CollectionData &rhs) : _rhs(&rhs) {}
00117 
00118   CompareResult visitArray(const CollectionData &lhs) {
00119     if (lhs.equalsArray(*_rhs))
00120       return COMPARE_RESULT_EQUAL;
00121     else
00122       return COMPARE_RESULT_DIFFER;
00123   }
00124 };
00125 
00126 struct NegativeIntegerComparer : ComparerBase {
00127   UInt _rhs;
00128 
00129   explicit NegativeIntegerComparer(UInt rhs) : _rhs(rhs) {}
00130 
00131   CompareResult visitFloat(Float lhs) {
00132     return arithmeticCompareNegateRight(lhs, _rhs);
00133   }
00134 
00135   CompareResult visitNegativeInteger(UInt lhs) {
00136     return arithmeticCompare(_rhs, lhs);
00137   }
00138 
00139   CompareResult visitPositiveInteger(UInt) {
00140     return COMPARE_RESULT_GREATER;
00141   }
00142 
00143   CompareResult visitBoolean(bool) {
00144     return COMPARE_RESULT_GREATER;
00145   }
00146 };
00147 
00148 struct ObjectComparer : ComparerBase {
00149   const CollectionData *_rhs;
00150 
00151   explicit ObjectComparer(const CollectionData &rhs) : _rhs(&rhs) {}
00152 
00153   CompareResult visitObject(const CollectionData &lhs) {
00154     if (lhs.equalsObject(*_rhs))
00155       return COMPARE_RESULT_EQUAL;
00156     else
00157       return COMPARE_RESULT_DIFFER;
00158   }
00159 };
00160 
00161 struct RawComparer : ComparerBase {
00162   const char *_rhsData;
00163   size_t _rhsSize;
00164 
00165   explicit RawComparer(const char *rhsData, size_t rhsSize)
00166       : _rhsData(rhsData), _rhsSize(rhsSize) {}
00167 
00168   CompareResult visitRawJson(const char *lhsData, size_t lhsSize) {
00169     size_t size = _rhsSize < lhsSize ? _rhsSize : lhsSize;
00170     int n = memcmp(lhsData, _rhsData, size);
00171     if (n < 0)
00172       return COMPARE_RESULT_LESS;
00173     else if (n > 0)
00174       return COMPARE_RESULT_GREATER;
00175     else
00176       return COMPARE_RESULT_EQUAL;
00177   }
00178 };
00179 
00180 template <typename T>
00181 struct Comparer<T, typename enable_if<IsVisitable<T>::value>::type>
00182     : ComparerBase {
00183   T rhs;
00184 
00185   explicit Comparer(T value) : rhs(value) {}
00186 
00187   CompareResult visitArray(const CollectionData &lhs) {
00188     ArrayComparer comparer(lhs);
00189     return accept(comparer);
00190   }
00191 
00192   CompareResult visitObject(const CollectionData &lhs) {
00193     ObjectComparer comparer(lhs);
00194     return accept(comparer);
00195   }
00196 
00197   CompareResult visitFloat(Float lhs) {
00198     Comparer<Float> comparer(lhs);
00199     return accept(comparer);
00200   }
00201 
00202   CompareResult visitString(const char *lhs) {
00203     Comparer<const char *> comparer(lhs);
00204     return accept(comparer);
00205   }
00206 
00207   CompareResult visitRawJson(const char *lhsData, size_t lhsSize) {
00208     RawComparer comparer(lhsData, lhsSize);
00209     return accept(comparer);
00210   }
00211 
00212   CompareResult visitNegativeInteger(UInt lhs) {
00213     NegativeIntegerComparer comparer(lhs);
00214     return accept(comparer);
00215   }
00216 
00217   CompareResult visitPositiveInteger(UInt lhs) {
00218     Comparer<UInt> comparer(lhs);
00219     return accept(comparer);
00220   }
00221 
00222   CompareResult visitBoolean(bool lhs) {
00223     Comparer<bool> comparer(lhs);
00224     return accept(comparer);
00225   }
00226 
00227   CompareResult visitNull() {
00228     NullComparer comparer;
00229     return accept(comparer);
00230   }
00231 
00232  private:
00233   template <typename TComparer>
00234   CompareResult accept(TComparer &comparer) {
00235     CompareResult reversedResult = rhs.accept(comparer);
00236     switch (reversedResult) {
00237       case COMPARE_RESULT_GREATER:
00238         return COMPARE_RESULT_LESS;
00239       case COMPARE_RESULT_LESS:
00240         return COMPARE_RESULT_GREATER;
00241       default:
00242         return reversedResult;
00243     }
00244   }
00245 };
00246 
00247 template <typename T1, typename T2>
00248 CompareResult compare(const T1 &lhs, const T2 &rhs) {
00249   Comparer<T2> comparer(rhs);
00250   return lhs.accept(comparer);
00251 }
00252 
00253 inline int variantCompare(const VariantData *a, const VariantData *b) {
00254   return compare(VariantConstRef(a), VariantConstRef(b));
00255 }
00256 
00257 }  // namespace ARDUINOJSON_NAMESPACE