mirror of
https://github.com/bblanchon/ArduinoJson.git
synced 2025-07-30 10:47:34 +02:00
Add JsonVariantVisitor
and use it for comparisons
This commit is contained in:
115
src/ArduinoJson/Variant/JsonVariantVisitor.hpp
Normal file
115
src/ArduinoJson/Variant/JsonVariantVisitor.hpp
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
// ArduinoJson - https://arduinojson.org
|
||||||
|
// Copyright © 2014-2023, Benoit BLANCHON
|
||||||
|
// MIT License
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <ArduinoJson/Array/JsonArray.hpp>
|
||||||
|
#include <ArduinoJson/Object/JsonObject.hpp>
|
||||||
|
#include <ArduinoJson/Variant/JsonVariant.hpp>
|
||||||
|
#include <ArduinoJson/Variant/VariantDataVisitor.hpp>
|
||||||
|
|
||||||
|
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
||||||
|
|
||||||
|
template <typename TResult>
|
||||||
|
struct JsonVariantVisitor {
|
||||||
|
typedef TResult result_type;
|
||||||
|
|
||||||
|
TResult visitArray(JsonArrayConst) {
|
||||||
|
return TResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
TResult visitBoolean(bool) {
|
||||||
|
return TResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
TResult visitFloat(JsonFloat) {
|
||||||
|
return TResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
TResult visitSignedInteger(JsonInteger) {
|
||||||
|
return TResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
TResult visitNull() {
|
||||||
|
return TResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
TResult visitObject(JsonObjectConst) {
|
||||||
|
return TResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
TResult visitUnsignedInteger(JsonUInt) {
|
||||||
|
return TResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
TResult visitRawString(const char*, size_t) {
|
||||||
|
return TResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
TResult visitString(const char*, size_t) {
|
||||||
|
return TResult();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename TVisitor>
|
||||||
|
class VisitorAdapter {
|
||||||
|
public:
|
||||||
|
using result_type = typename TVisitor::result_type;
|
||||||
|
|
||||||
|
VisitorAdapter(TVisitor& visitor, const ResourceManager* resources)
|
||||||
|
: visitor_(&visitor), resources_(resources) {}
|
||||||
|
|
||||||
|
result_type visitArray(const ArrayData& array) {
|
||||||
|
return visitor_->visitArray(JsonArrayConst(&array, resources_));
|
||||||
|
}
|
||||||
|
|
||||||
|
result_type visitObject(const ObjectData& object) {
|
||||||
|
return visitor_->visitObject(JsonObjectConst(&object, resources_));
|
||||||
|
}
|
||||||
|
|
||||||
|
result_type visitFloat(JsonFloat value) {
|
||||||
|
return visitor_->visitFloat(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
result_type visitString(const char* s, size_t n) {
|
||||||
|
return visitor_->visitString(s, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
result_type visitRawString(const char* p, size_t n) {
|
||||||
|
return visitor_->visitRawString(p, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
result_type visitSignedInteger(JsonInteger value) {
|
||||||
|
return visitor_->visitSignedInteger(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
result_type visitUnsignedInteger(JsonUInt value) {
|
||||||
|
return visitor_->visitUnsignedInteger(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
result_type visitBoolean(bool value) {
|
||||||
|
return visitor_->visitBoolean(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
result_type visitNull() {
|
||||||
|
return visitor_->visitNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
TVisitor* visitor_;
|
||||||
|
const ResourceManager* resources_;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename TVisitor>
|
||||||
|
typename TVisitor::result_type accept(JsonVariantConst variant,
|
||||||
|
TVisitor& visitor) {
|
||||||
|
auto data = VariantAttorney::getData(variant);
|
||||||
|
if (!data)
|
||||||
|
return visitor.visitNull();
|
||||||
|
auto resources = VariantAttorney::getResourceManager(variant);
|
||||||
|
VisitorAdapter<TVisitor> adapter(visitor, resources);
|
||||||
|
return data->accept(adapter);
|
||||||
|
}
|
||||||
|
|
||||||
|
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
@ -8,11 +8,11 @@
|
|||||||
#include <ArduinoJson/Numbers/arithmeticCompare.hpp>
|
#include <ArduinoJson/Numbers/arithmeticCompare.hpp>
|
||||||
#include <ArduinoJson/Polyfills/type_traits.hpp>
|
#include <ArduinoJson/Polyfills/type_traits.hpp>
|
||||||
#include <ArduinoJson/Strings/StringAdapters.hpp>
|
#include <ArduinoJson/Strings/StringAdapters.hpp>
|
||||||
#include <ArduinoJson/Variant/VariantDataVisitor.hpp>
|
#include <ArduinoJson/Variant/JsonVariantVisitor.hpp>
|
||||||
|
|
||||||
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
||||||
|
|
||||||
struct ComparerBase : VariantDataVisitor<CompareResult> {};
|
struct ComparerBase : JsonVariantVisitor<CompareResult> {};
|
||||||
|
|
||||||
template <typename T, typename Enable = void>
|
template <typename T, typename Enable = void>
|
||||||
struct Comparer;
|
struct Comparer;
|
||||||
@ -79,12 +79,12 @@ struct Comparer<decltype(nullptr), void> : NullComparer {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct ArrayComparer : ComparerBase {
|
struct ArrayComparer : ComparerBase {
|
||||||
const ArrayData* rhs_;
|
JsonArrayConst rhs_;
|
||||||
|
|
||||||
explicit ArrayComparer(const ArrayData& rhs) : rhs_(&rhs) {}
|
explicit ArrayComparer(JsonArrayConst rhs) : rhs_(rhs) {}
|
||||||
|
|
||||||
CompareResult visitArray(const ArrayData& lhs) {
|
CompareResult visitArray(JsonArrayConst lhs) {
|
||||||
if (JsonArrayConst(&lhs, nullptr) == JsonArrayConst(rhs_, nullptr))
|
if (rhs_ == lhs)
|
||||||
return COMPARE_RESULT_EQUAL;
|
return COMPARE_RESULT_EQUAL;
|
||||||
else
|
else
|
||||||
return COMPARE_RESULT_DIFFER;
|
return COMPARE_RESULT_DIFFER;
|
||||||
@ -92,12 +92,12 @@ struct ArrayComparer : ComparerBase {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct ObjectComparer : ComparerBase {
|
struct ObjectComparer : ComparerBase {
|
||||||
const ObjectData* rhs_;
|
JsonObjectConst rhs_;
|
||||||
|
|
||||||
explicit ObjectComparer(const ObjectData& rhs) : rhs_(&rhs) {}
|
explicit ObjectComparer(JsonObjectConst rhs) : rhs_(rhs) {}
|
||||||
|
|
||||||
CompareResult visitObject(const ObjectData& lhs) {
|
CompareResult visitObject(JsonObjectConst lhs) {
|
||||||
if (JsonObjectConst(&lhs, nullptr) == JsonObjectConst(rhs_, nullptr))
|
if (lhs == rhs_)
|
||||||
return COMPARE_RESULT_EQUAL;
|
return COMPARE_RESULT_EQUAL;
|
||||||
else
|
else
|
||||||
return COMPARE_RESULT_DIFFER;
|
return COMPARE_RESULT_DIFFER;
|
||||||
@ -124,59 +124,59 @@ struct RawComparer : ComparerBase {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct VariantComparer : ComparerBase {
|
struct VariantComparer : ComparerBase {
|
||||||
const VariantData* rhs;
|
JsonVariantConst rhs;
|
||||||
|
|
||||||
explicit VariantComparer(const VariantData* value) : rhs(value) {}
|
explicit VariantComparer(JsonVariantConst value) : rhs(value) {}
|
||||||
|
|
||||||
CompareResult visitArray(const ArrayData& lhs) {
|
CompareResult visitArray(JsonArrayConst lhs) {
|
||||||
ArrayComparer comparer(lhs);
|
ArrayComparer comparer(lhs);
|
||||||
return accept(comparer);
|
return reverseResult(comparer);
|
||||||
}
|
}
|
||||||
|
|
||||||
CompareResult visitObject(const ObjectData& lhs) {
|
CompareResult visitObject(JsonObjectConst lhs) {
|
||||||
ObjectComparer comparer(lhs);
|
ObjectComparer comparer(lhs);
|
||||||
return accept(comparer);
|
return reverseResult(comparer);
|
||||||
}
|
}
|
||||||
|
|
||||||
CompareResult visitFloat(JsonFloat lhs) {
|
CompareResult visitFloat(JsonFloat lhs) {
|
||||||
Comparer<JsonFloat> comparer(lhs);
|
Comparer<JsonFloat> comparer(lhs);
|
||||||
return accept(comparer);
|
return reverseResult(comparer);
|
||||||
}
|
}
|
||||||
|
|
||||||
CompareResult visitString(const char* lhs, size_t) {
|
CompareResult visitString(const char* lhs, size_t) {
|
||||||
Comparer<const char*> comparer(lhs);
|
Comparer<const char*> comparer(lhs);
|
||||||
return accept(comparer);
|
return reverseResult(comparer);
|
||||||
}
|
}
|
||||||
|
|
||||||
CompareResult visitRawString(const char* lhsData, size_t lhsSize) {
|
CompareResult visitRawString(const char* lhsData, size_t lhsSize) {
|
||||||
RawComparer comparer(lhsData, lhsSize);
|
RawComparer comparer(lhsData, lhsSize);
|
||||||
return accept(comparer);
|
return reverseResult(comparer);
|
||||||
}
|
}
|
||||||
|
|
||||||
CompareResult visitSignedInteger(JsonInteger lhs) {
|
CompareResult visitSignedInteger(JsonInteger lhs) {
|
||||||
Comparer<JsonInteger> comparer(lhs);
|
Comparer<JsonInteger> comparer(lhs);
|
||||||
return accept(comparer);
|
return reverseResult(comparer);
|
||||||
}
|
}
|
||||||
|
|
||||||
CompareResult visitUnsignedInteger(JsonUInt lhs) {
|
CompareResult visitUnsignedInteger(JsonUInt lhs) {
|
||||||
Comparer<JsonUInt> comparer(lhs);
|
Comparer<JsonUInt> comparer(lhs);
|
||||||
return accept(comparer);
|
return reverseResult(comparer);
|
||||||
}
|
}
|
||||||
|
|
||||||
CompareResult visitBoolean(bool lhs) {
|
CompareResult visitBoolean(bool lhs) {
|
||||||
Comparer<bool> comparer(lhs);
|
Comparer<bool> comparer(lhs);
|
||||||
return accept(comparer);
|
return reverseResult(comparer);
|
||||||
}
|
}
|
||||||
|
|
||||||
CompareResult visitNull() {
|
CompareResult visitNull() {
|
||||||
NullComparer comparer;
|
NullComparer comparer;
|
||||||
return accept(comparer);
|
return reverseResult(comparer);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template <typename TComparer>
|
template <typename TComparer>
|
||||||
CompareResult accept(TComparer& comparer) {
|
CompareResult reverseResult(TComparer& comparer) {
|
||||||
CompareResult reversedResult = VariantData::accept(rhs, comparer);
|
CompareResult reversedResult = accept(rhs, comparer);
|
||||||
switch (reversedResult) {
|
switch (reversedResult) {
|
||||||
case COMPARE_RESULT_GREATER:
|
case COMPARE_RESULT_GREATER:
|
||||||
return COMPARE_RESULT_LESS;
|
return COMPARE_RESULT_LESS;
|
||||||
@ -193,18 +193,13 @@ struct Comparer<T, typename enable_if<is_convertible<
|
|||||||
T, ArduinoJson::JsonVariantConst>::value>::type>
|
T, ArduinoJson::JsonVariantConst>::value>::type>
|
||||||
: VariantComparer {
|
: VariantComparer {
|
||||||
explicit Comparer(const T& value)
|
explicit Comparer(const T& value)
|
||||||
: VariantComparer(VariantAttorney::getData(value)) {}
|
: VariantComparer(static_cast<JsonVariantConst>(value)) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
CompareResult compare(ArduinoJson::JsonVariantConst lhs, const T& rhs) {
|
CompareResult compare(ArduinoJson::JsonVariantConst lhs, const T& rhs) {
|
||||||
Comparer<T> comparer(rhs);
|
Comparer<T> comparer(rhs);
|
||||||
return VariantData::accept(VariantAttorney::getData(lhs), comparer);
|
return accept(lhs, comparer);
|
||||||
}
|
|
||||||
|
|
||||||
inline CompareResult compare(const VariantData* lhs, const VariantData* rhs) {
|
|
||||||
VariantComparer comparer(rhs);
|
|
||||||
return VariantData::accept(lhs, comparer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
||||||
|
Reference in New Issue
Block a user