Added comparisons between JsonVariants

This commit is contained in:
Benoit Blanchon
2020-07-02 15:28:34 +02:00
parent 0e794a28a1
commit 7e58347fbe
19 changed files with 808 additions and 666 deletions

View File

@ -53,14 +53,6 @@ class ElementProxy : public VariantOperators<ElementProxy<TArray> >,
return *this;
}
FORCE_INLINE bool operator==(VariantConstRef rhs) const {
return static_cast<VariantConstRef>(getUpstreamElement()) == rhs;
}
FORCE_INLINE bool operator!=(VariantConstRef rhs) const {
return static_cast<VariantConstRef>(getUpstreamElement()) != rhs;
}
FORCE_INLINE void clear() const {
getUpstreamElement().clear();
}
@ -79,11 +71,6 @@ class ElementProxy : public VariantOperators<ElementProxy<TArray> >,
return getUpstreamElement();
}
template <typename T>
FORCE_INLINE int compare(const T& rhs) const {
return getUpstreamElement().template compare<T>(rhs);
}
template <typename T>
FORCE_INLINE bool is() const {
return getUpstreamElement().template is<T>();

View File

@ -9,6 +9,10 @@
namespace ARDUINOJSON_NAMESPACE {
inline bool variantEquals(const VariantData* a, const VariantData* b) {
return variantCompare(a, b) == COMPARE_RESULT_EQUAL;
}
inline VariantSlot* CollectionData::addSlot(MemoryPool* pool) {
VariantSlot* slot = pool->allocVariant();
if (!slot)

View File

@ -0,0 +1,121 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020
// MIT License
#pragma once
#include <ArduinoJson/Numbers/Integer.hpp>
#include <ArduinoJson/Polyfills/type_traits.hpp>
namespace ARDUINOJSON_NAMESPACE {
enum CompareResult {
COMPARE_RESULT_DIFFER = 0,
COMPARE_RESULT_EQUAL = 1,
COMPARE_RESULT_GREATER = 2,
COMPARE_RESULT_LESS = 4,
COMPARE_RESULT_GREATER_OR_EQUAL = 3,
COMPARE_RESULT_LESS_OR_EQUAL = 5
};
template <typename T>
CompareResult arithmeticCompare(const T &lhs, const T &rhs) {
if (lhs < rhs)
return COMPARE_RESULT_LESS;
else if (lhs > rhs)
return COMPARE_RESULT_GREATER;
else
return COMPARE_RESULT_EQUAL;
}
template <typename T1, typename T2>
CompareResult arithmeticCompare(
const T1 &lhs, const T2 &rhs,
typename enable_if<is_integral<T1>::value && is_integral<T2>::value &&
sizeof(T1) < sizeof(T2),
int // Using int instead of void to avoid C2572 on
// Visual Studio 2012, 2013, and 2015
>::type * = 0) {
return arithmeticCompare<T2>(static_cast<T2>(lhs), rhs);
}
template <typename T1, typename T2>
CompareResult arithmeticCompare(
const T1 &lhs, const T2 &rhs,
typename enable_if<is_integral<T1>::value && is_integral<T2>::value &&
sizeof(T2) < sizeof(T1)>::type * = 0) {
return arithmeticCompare<T1>(lhs, static_cast<T1>(rhs));
}
template <typename T1, typename T2>
CompareResult arithmeticCompare(
const T1 &lhs, const T2 &rhs,
typename enable_if<is_integral<T1>::value && is_integral<T2>::value &&
is_signed<T1>::value == is_signed<T2>::value &&
sizeof(T2) == sizeof(T1)>::type * = 0) {
return arithmeticCompare<T1>(lhs, static_cast<T1>(rhs));
}
template <typename T1, typename T2>
CompareResult arithmeticCompare(
const T1 &lhs, const T2 &rhs,
typename enable_if<is_integral<T1>::value && is_integral<T2>::value &&
is_unsigned<T1>::value && is_signed<T2>::value &&
sizeof(T2) == sizeof(T1)>::type * = 0) {
if (rhs < 0)
return COMPARE_RESULT_GREATER;
return arithmeticCompare<T1>(lhs, static_cast<T1>(rhs));
}
template <typename T1, typename T2>
CompareResult arithmeticCompare(
const T1 &lhs, const T2 &rhs,
typename enable_if<is_integral<T1>::value && is_integral<T2>::value &&
is_signed<T1>::value && is_unsigned<T2>::value &&
sizeof(T2) == sizeof(T1)>::type * = 0) {
if (lhs < 0)
return COMPARE_RESULT_LESS;
return arithmeticCompare<T2>(static_cast<T2>(lhs), rhs);
}
template <typename T1, typename T2>
CompareResult arithmeticCompare(
const T1 &lhs, const T2 &rhs,
typename enable_if<is_floating_point<T1>::value ||
is_floating_point<T2>::value>::type * = 0) {
return arithmeticCompare<double>(static_cast<double>(lhs),
static_cast<double>(rhs));
}
template <typename T2>
CompareResult arithmeticCompareNegateLeft(
UInt, const T2 &, typename enable_if<is_unsigned<T2>::value>::type * = 0) {
return COMPARE_RESULT_LESS;
}
template <typename T2>
CompareResult arithmeticCompareNegateLeft(
UInt lhs, const T2 &rhs,
typename enable_if<is_signed<T2>::value>::type * = 0) {
if (rhs > 0)
return COMPARE_RESULT_LESS;
return arithmeticCompare(-rhs, static_cast<T2>(lhs));
}
template <typename T1>
CompareResult arithmeticCompareNegateRight(
const T1 &, UInt, typename enable_if<is_unsigned<T1>::value>::type * = 0) {
return COMPARE_RESULT_GREATER;
}
template <typename T1>
CompareResult arithmeticCompareNegateRight(
const T1 &lhs, UInt rhs,
typename enable_if<is_signed<T1>::value>::type * = 0) {
if (lhs > 0)
return COMPARE_RESULT_GREATER;
return arithmeticCompare(static_cast<T1>(rhs), -lhs);
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -56,14 +56,6 @@ class MemberProxy : public VariantOperators<MemberProxy<TObject, TStringRef> >,
return *this;
}
FORCE_INLINE bool operator==(VariantConstRef rhs) const {
return static_cast<VariantConstRef>(getUpstreamMember()) == rhs;
}
FORCE_INLINE bool operator!=(VariantConstRef rhs) const {
return static_cast<VariantConstRef>(getUpstreamMember()) != rhs;
}
FORCE_INLINE void clear() const {
getUpstreamMember().clear();
}
@ -82,11 +74,6 @@ class MemberProxy : public VariantOperators<MemberProxy<TObject, TStringRef> >,
return getUpstreamMember();
}
template <typename T>
FORCE_INLINE int compare(const T &rhs) const {
return getUpstreamMember().template compare<T>(rhs);
}
template <typename TValue>
FORCE_INLINE bool is() const {
return getUpstreamMember().template is<TValue>();

View File

@ -16,8 +16,7 @@ template <typename T>
struct is_enum {
static const bool value = is_convertible<T, int>::value &&
!is_class<T>::value && !is_integral<T>::value &&
!is_floating_point<T>::value &&
!is_same<T, bool>::value;
!is_floating_point<T>::value;
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -25,9 +25,7 @@ struct is_integral {
is_same<T, signed __int64>::value ||
is_same<T, unsigned __int64>::value ||
#endif
is_same<T, char>::value;
// CAUTION: differs from std::is_integral as it doesn't include bool
is_same<T, char>::value || is_same<T, bool>::value;
};
template <typename T>

View File

@ -53,8 +53,9 @@ struct VariantConstAs<ArrayRef> {
// ---
template <typename T>
inline typename enable_if<is_integral<T>::value, T>::type variantAs(
const VariantData* data) {
inline typename enable_if<is_integral<T>::value && !is_same<bool, T>::value,
T>::type
variantAs(const VariantData* data) {
ARDUINOJSON_ASSERT_INTEGER_TYPE_IS_SUPPORTED(T);
return data != 0 ? data->asIntegral<T>() : T(0);
}

View File

@ -6,8 +6,7 @@
#include <ArduinoJson/Configuration.hpp>
#include <ArduinoJson/Misc/Visitable.hpp>
#include <ArduinoJson/Numbers/Float.hpp>
#include <ArduinoJson/Numbers/Integer.hpp>
#include <ArduinoJson/Numbers/arithmeticCompare.hpp>
#include <ArduinoJson/Polyfills/type_traits.hpp>
#include <ArduinoJson/Strings/IsString.hpp>
@ -15,115 +14,228 @@ namespace ARDUINOJSON_NAMESPACE {
class CollectionData;
struct ComparerBase {
CompareResult result;
ComparerBase() : result(COMPARE_RESULT_DIFFER) {}
void visitArray(const CollectionData &) {}
void visitBoolean(bool) {}
void visitFloat(Float) {}
void visitNegativeInteger(UInt) {}
void visitNull() {}
void visitObject(const CollectionData &) {}
void visitPositiveInteger(UInt) {}
void visitRawJson(const char *, size_t) {}
void visitString(const char *) {}
};
template <typename T, typename Enable = void>
struct Comparer;
template <typename T>
struct Comparer<T, typename enable_if<IsString<T>::value>::type> {
struct Comparer<T, typename enable_if<IsString<T>::value>::type>
: ComparerBase {
T rhs;
int result;
explicit Comparer(T value) : rhs(value), result(1) {}
explicit Comparer(T value) : rhs(value) {}
void visitArray(const CollectionData &) {}
void visitObject(const CollectionData &) {}
void visitFloat(Float) {}
void visitString(const char *lhs) {
result = -adaptString(rhs).compare(lhs);
int i = adaptString(rhs).compare(lhs);
if (i < 0)
result = COMPARE_RESULT_GREATER;
else if (i > 0)
result = COMPARE_RESULT_LESS;
else
result = COMPARE_RESULT_EQUAL;
}
void visitRawJson(const char *, size_t) {}
void visitNegativeInteger(UInt) {}
void visitPositiveInteger(UInt) {}
void visitBoolean(bool) {}
void visitNull() {
result = adaptString(rhs).compare(NULL);
if (adaptString(rhs).isNull())
result = COMPARE_RESULT_EQUAL;
}
};
template <typename T>
typename enable_if<is_signed<T>::value, int>::type sign2(const T &value) {
return value < 0 ? -1 : value > 0 ? 1 : 0;
}
template <typename T>
typename enable_if<is_unsigned<T>::value, int>::type sign2(const T &value) {
return value > 0 ? 1 : 0;
}
template <typename T>
struct Comparer<T, typename enable_if<is_integral<T>::value ||
is_floating_point<T>::value>::type> {
is_floating_point<T>::value>::type>
: ComparerBase {
T rhs;
int result;
explicit Comparer(T value) : rhs(value), result(1) {}
explicit Comparer(T value) : rhs(value) {}
void visitArray(const CollectionData &) {}
void visitObject(const CollectionData &) {}
void visitFloat(Float lhs) {
result = sign2(lhs - static_cast<Float>(rhs));
result = arithmeticCompare(lhs, rhs);
}
void visitString(const char *) {}
void visitRawJson(const char *, size_t) {}
void visitNegativeInteger(UInt lhs) {
result = -sign2(static_cast<T>(lhs) + rhs);
result = arithmeticCompareNegateLeft(lhs, rhs);
}
void visitPositiveInteger(UInt lhs) {
result = static_cast<T>(lhs) < rhs ? -1 : static_cast<T>(lhs) > rhs ? 1 : 0;
result = arithmeticCompare(lhs, rhs);
}
void visitBoolean(bool lhs) {
visitPositiveInteger(static_cast<UInt>(lhs));
}
void visitBoolean(bool) {}
void visitNull() {}
};
template <>
struct Comparer<bool, void> {
bool rhs;
int result;
explicit Comparer(bool value) : rhs(value), result(1) {}
void visitArray(const CollectionData &) {}
void visitObject(const CollectionData &) {}
void visitFloat(Float) {}
void visitString(const char *) {}
void visitRawJson(const char *, size_t) {}
void visitNegativeInteger(UInt) {}
void visitPositiveInteger(UInt) {}
void visitBoolean(bool lhs) {
result = static_cast<int>(lhs - rhs);
struct NullComparer : ComparerBase {
void visitNull() {
result = COMPARE_RESULT_EQUAL;
}
void visitNull() {}
};
#if ARDUINOJSON_HAS_NULLPTR
template <>
struct Comparer<decltype(nullptr), void> {
int result;
explicit Comparer(decltype(nullptr)) : result(1) {}
void visitArray(const CollectionData &) {}
void visitObject(const CollectionData &) {}
void visitFloat(Float) {}
void visitString(const char *) {}
void visitRawJson(const char *, size_t) {}
void visitNegativeInteger(UInt) {}
void visitPositiveInteger(UInt) {}
void visitBoolean(bool) {}
void visitNull() {
result = 0;
}
struct Comparer<decltype(nullptr), void> : NullComparer {
explicit Comparer(decltype(nullptr)) : NullComparer() {}
};
#endif
template <typename TData>
struct ArrayComparer : ComparerBase {
const CollectionData *_rhs;
explicit ArrayComparer(const CollectionData &rhs) : _rhs(&rhs) {}
void visitArray(const CollectionData &lhs) {
if (lhs.equalsArray(*_rhs))
result = COMPARE_RESULT_EQUAL;
}
};
struct NegativeIntegerComparer : ComparerBase {
UInt _rhs;
explicit NegativeIntegerComparer(UInt rhs) : _rhs(rhs) {}
void visitFloat(Float lhs) {
result = arithmeticCompareNegateRight(lhs, _rhs);
}
void visitNegativeInteger(UInt lhs) {
result = arithmeticCompare(_rhs, lhs);
}
void visitPositiveInteger(UInt) {
result = COMPARE_RESULT_GREATER;
}
void visitBoolean(bool) {
result = COMPARE_RESULT_GREATER;
}
};
struct ObjectComparer : ComparerBase {
const CollectionData *_rhs;
explicit ObjectComparer(const CollectionData &rhs) : _rhs(&rhs) {}
void visitObject(const CollectionData &lhs) {
if (lhs.equalsObject(*_rhs))
result = COMPARE_RESULT_EQUAL;
}
};
struct RawComparer : ComparerBase {
const char *_rhsData;
size_t _rhsSize;
explicit RawComparer(const char *rhsData, size_t rhsSize)
: _rhsData(rhsData), _rhsSize(rhsSize) {}
void visitRawJson(const char *lhsData, size_t lhsSize) {
size_t size = _rhsSize < lhsSize ? _rhsSize : lhsSize;
int n = memcmp(lhsData, _rhsData, size);
if (n < 0)
result = COMPARE_RESULT_LESS;
else if (n > 0)
result = COMPARE_RESULT_GREATER;
else
result = COMPARE_RESULT_EQUAL;
}
};
template <typename T>
int VariantRefBase<TData>::compare(const T &rhs) const {
Comparer<T> comparer(rhs);
if (_data)
_data->accept(comparer);
else
comparer.visitNull();
struct Comparer<T, typename enable_if<IsVisitable<T>::value>::type>
: ComparerBase {
T rhs;
explicit Comparer(T value) : rhs(value) {}
void visitArray(const CollectionData &lhs) {
ArrayComparer comparer(lhs);
accept(comparer);
}
void visitObject(const CollectionData &lhs) {
ObjectComparer comparer(lhs);
accept(comparer);
}
void visitFloat(Float lhs) {
Comparer<Float> comparer(lhs);
accept(comparer);
}
void visitString(const char *lhs) {
Comparer<const char *> comparer(lhs);
accept(comparer);
}
void visitRawJson(const char *lhsData, size_t lhsSize) {
RawComparer comparer(lhsData, lhsSize);
accept(comparer);
}
void visitNegativeInteger(UInt lhs) {
NegativeIntegerComparer comparer(lhs);
accept(comparer);
}
void visitPositiveInteger(UInt lhs) {
Comparer<UInt> comparer(lhs);
accept(comparer);
}
void visitBoolean(bool lhs) {
Comparer<bool> comparer(lhs);
accept(comparer);
}
void visitNull() {
NullComparer comparer;
accept(comparer);
}
private:
template <typename TComparer>
void accept(TComparer &comparer) {
rhs.accept(comparer);
switch (comparer.result) {
case COMPARE_RESULT_GREATER:
result = COMPARE_RESULT_LESS;
break;
case COMPARE_RESULT_LESS:
result = COMPARE_RESULT_GREATER;
break;
default:
result = comparer.result;
break;
}
}
};
template <typename T1, typename T2>
CompareResult compare(const T1 &lhs, const T2 &rhs) {
Comparer<T2> comparer(rhs);
lhs.accept(comparer);
return comparer.result;
}
inline int variantCompare(const VariantData *a, const VariantData *b) {
return compare(VariantConstRef(a), VariantConstRef(b));
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -111,42 +111,6 @@ class VariantData {
}
}
bool equals(const VariantData &other) const {
// Check that variant have the same type, but ignore string ownership
if ((type() | VALUE_IS_OWNED) != (other.type() | VALUE_IS_OWNED))
return false;
switch (type()) {
case VALUE_IS_LINKED_STRING:
case VALUE_IS_OWNED_STRING:
return !strcmp(_content.asString, other._content.asString);
case VALUE_IS_LINKED_RAW:
case VALUE_IS_OWNED_RAW:
return _content.asRaw.size == other._content.asRaw.size &&
!memcmp(_content.asRaw.data, other._content.asRaw.data,
_content.asRaw.size);
case VALUE_IS_BOOLEAN:
case VALUE_IS_POSITIVE_INTEGER:
case VALUE_IS_NEGATIVE_INTEGER:
return _content.asInteger == other._content.asInteger;
case VALUE_IS_ARRAY:
return _content.asCollection.equalsArray(other._content.asCollection);
case VALUE_IS_OBJECT:
return _content.asCollection.equalsObject(other._content.asCollection);
case VALUE_IS_FLOAT:
return _content.asFloat == other._content.asFloat;
case VALUE_IS_NULL:
default:
return true;
}
}
bool isArray() const {
return (_flags & VALUE_IS_ARRAY) != 0;
}

View File

@ -40,13 +40,7 @@ inline bool variantCopyFrom(VariantData *dst, const VariantData *src,
return dst->copyFrom(*src, pool);
}
inline bool variantEquals(const VariantData *a, const VariantData *b) {
if (a == b)
return true;
if (!a || !b)
return false;
return a->equals(*b);
}
inline int variantCompare(const VariantData *a, const VariantData *b);
inline bool variantIsArray(const VariantData *var) {
return var && var->isArray();

View File

@ -5,12 +5,16 @@
#pragma once
#include <ArduinoJson/Misc/Visitable.hpp>
#include <ArduinoJson/Numbers/arithmeticCompare.hpp>
#include <ArduinoJson/Polyfills/attributes.hpp>
#include <ArduinoJson/Polyfills/type_traits.hpp>
#include <ArduinoJson/Variant/VariantAs.hpp>
namespace ARDUINOJSON_NAMESPACE {
template <typename T1, typename T2>
CompareResult compare(const T1 &lhs, const T2 &rhs); // VariantCompare.cpp
template <typename TVariant>
struct VariantOperators {
// Returns the default value if the VariantRef is undefined of incompatible
@ -33,125 +37,127 @@ struct VariantOperators {
// value == TVariant
template <typename T>
friend bool operator==(T *lhs, TVariant rhs) {
return rhs.compare(lhs) == 0;
return compare(rhs, lhs) == COMPARE_RESULT_EQUAL;
}
template <typename T>
friend typename enable_if<!IsVisitable<T>::value, bool>::type operator==(
const T &lhs, TVariant rhs) {
return rhs.compare(lhs) == 0;
friend bool operator==(const T &lhs, TVariant rhs) {
return compare(rhs, lhs) == COMPARE_RESULT_EQUAL;
}
// TVariant == value
template <typename T>
friend bool operator==(TVariant lhs, T *rhs) {
return lhs.compare(rhs) == 0;
return compare(lhs, rhs) == COMPARE_RESULT_EQUAL;
}
template <typename T>
friend typename enable_if<!IsVisitable<T>::value, bool>::type operator==(
TVariant lhs, const T &rhs) {
return lhs.compare(rhs) == 0;
return compare(lhs, rhs) == COMPARE_RESULT_EQUAL;
}
// value != TVariant
template <typename T>
friend bool operator!=(T *lhs, TVariant rhs) {
return rhs.compare(lhs) != 0;
return compare(rhs, lhs) != COMPARE_RESULT_EQUAL;
}
template <typename T>
friend typename enable_if<!IsVisitable<T>::value, bool>::type operator!=(
const T &lhs, TVariant rhs) {
return rhs.compare(lhs) != 0;
friend bool operator!=(const T &lhs, TVariant rhs) {
return compare(rhs, lhs) != COMPARE_RESULT_EQUAL;
}
// TVariant != value
template <typename T>
friend bool operator!=(TVariant lhs, T *rhs) {
return lhs.compare(rhs) != 0;
return compare(lhs, rhs) != COMPARE_RESULT_EQUAL;
}
template <typename T>
friend typename enable_if<!IsVisitable<T>::value, bool>::type operator!=(
TVariant lhs, const T &rhs) {
return lhs.compare(rhs) != 0;
return compare(lhs, rhs) != COMPARE_RESULT_EQUAL;
}
// value < TVariant
template <typename T>
friend bool operator<(T *lhs, TVariant rhs) {
return rhs.compare(lhs) > 0;
return compare(rhs, lhs) == COMPARE_RESULT_GREATER;
}
template <typename T>
friend bool operator<(const T &lhs, TVariant rhs) {
return rhs.compare(lhs) > 0;
return compare(rhs, lhs) == COMPARE_RESULT_GREATER;
}
// TVariant < value
template <typename T>
friend bool operator<(TVariant lhs, T *rhs) {
return lhs.compare(rhs) < 0;
return compare(lhs, rhs) == COMPARE_RESULT_LESS;
}
template <typename T>
friend bool operator<(TVariant lhs, const T &rhs) {
return lhs.compare(rhs) < 0;
friend typename enable_if<!IsVisitable<T>::value, bool>::type operator<(
TVariant lhs, const T &rhs) {
return compare(lhs, rhs) == COMPARE_RESULT_LESS;
}
// value <= TVariant
template <typename T>
friend bool operator<=(T *lhs, TVariant rhs) {
return rhs.compare(lhs) >= 0;
return (compare(rhs, lhs) & COMPARE_RESULT_GREATER_OR_EQUAL) != 0;
}
template <typename T>
friend bool operator<=(const T &lhs, TVariant rhs) {
return rhs.compare(lhs) >= 0;
return (compare(rhs, lhs) & COMPARE_RESULT_GREATER_OR_EQUAL) != 0;
}
// TVariant <= value
template <typename T>
friend bool operator<=(TVariant lhs, T *rhs) {
return lhs.compare(rhs) <= 0;
return (compare(lhs, rhs) & COMPARE_RESULT_LESS_OR_EQUAL) != 0;
}
template <typename T>
friend bool operator<=(TVariant lhs, const T &rhs) {
return lhs.compare(rhs) <= 0;
friend typename enable_if<!IsVisitable<T>::value, bool>::type operator<=(
TVariant lhs, const T &rhs) {
return (compare(lhs, rhs) & COMPARE_RESULT_LESS_OR_EQUAL) != 0;
}
// value > TVariant
template <typename T>
friend bool operator>(T *lhs, TVariant rhs) {
return rhs.compare(lhs) < 0;
return compare(rhs, lhs) == COMPARE_RESULT_LESS;
}
template <typename T>
friend bool operator>(const T &lhs, TVariant rhs) {
return rhs.compare(lhs) < 0;
return compare(rhs, lhs) == COMPARE_RESULT_LESS;
}
// TVariant > value
template <typename T>
friend bool operator>(TVariant lhs, T *rhs) {
return lhs.compare(rhs) > 0;
return compare(lhs, rhs) == COMPARE_RESULT_GREATER;
}
template <typename T>
friend bool operator>(TVariant lhs, const T &rhs) {
return lhs.compare(rhs) > 0;
friend typename enable_if<!IsVisitable<T>::value, bool>::type operator>(
TVariant lhs, const T &rhs) {
return compare(lhs, rhs) == COMPARE_RESULT_GREATER;
}
// value >= TVariant
template <typename T>
friend bool operator>=(T *lhs, TVariant rhs) {
return rhs.compare(lhs) <= 0;
return (compare(rhs, lhs) & COMPARE_RESULT_LESS_OR_EQUAL) != 0;
}
template <typename T>
friend bool operator>=(const T &lhs, TVariant rhs) {
return rhs.compare(lhs) <= 0;
return (compare(rhs, lhs) & COMPARE_RESULT_LESS_OR_EQUAL) != 0;
}
// TVariant >= value
template <typename T>
friend bool operator>=(TVariant lhs, T *rhs) {
return lhs.compare(rhs) >= 0;
return (compare(lhs, rhs) & COMPARE_RESULT_GREATER_OR_EQUAL) != 0;
}
template <typename T>
friend bool operator>=(TVariant lhs, const T &rhs) {
return lhs.compare(rhs) >= 0;
friend typename enable_if<!IsVisitable<T>::value, bool>::type operator>=(
TVariant lhs, const T &rhs) {
return (compare(lhs, rhs) & COMPARE_RESULT_GREATER_OR_EQUAL) != 0;
}
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -42,8 +42,10 @@ class VariantRefBase {
// bool is<unsigned int>() const;
// bool is<unsigned long>() const;
template <typename T>
FORCE_INLINE typename enable_if<is_integral<T>::value, bool>::type is()
const {
FORCE_INLINE
typename enable_if<is_integral<T>::value && !is_same<bool, T>::value,
bool>::type
is() const {
return variantIsInteger<T>(_data);
}
//
@ -108,9 +110,6 @@ class VariantRefBase {
return variantIsInteger<int>(_data);
}
template <typename T>
int compare(const T &) const; // VariantCompare.cpp
FORCE_INLINE bool isNull() const {
return variantIsNull(_data);
}
@ -188,7 +187,8 @@ class VariantRef : public VariantRefBase<VariantData>,
// set(unsigned long)
template <typename T>
FORCE_INLINE bool set(
T value, typename enable_if<is_integral<T>::value>::type * = 0) const {
T value, typename enable_if<is_integral<T>::value &&
!is_same<bool, T>::value>::type * = 0) const {
return variantSetInteger<T>(_data, value);
}
@ -262,14 +262,6 @@ class VariantRef : public VariantRefBase<VariantData>,
variantAccept(_data, visitor);
}
FORCE_INLINE bool operator==(VariantRef lhs) const {
return variantEquals(_data, lhs._data);
}
FORCE_INLINE bool operator!=(VariantRef lhs) const {
return !variantEquals(_data, lhs._data);
}
// Change the type of the variant
//
// ArrayRef to<ArrayRef>()
@ -407,13 +399,5 @@ class VariantConstRef : public VariantRefBase<const VariantData>,
operator[](TChar *key) const {
return getMember(key);
}
FORCE_INLINE bool operator==(VariantConstRef lhs) const {
return variantEquals(_data, lhs._data);
}
FORCE_INLINE bool operator!=(VariantConstRef lhs) const {
return !variantEquals(_data, lhs._data);
}
};
} // namespace ARDUINOJSON_NAMESPACE