Merge all visitXxx() into one overloaded visit() function

This commit is contained in:
Benoit Blanchon
2023-07-10 18:27:30 +02:00
parent 64922343e6
commit 5e3f84c718
7 changed files with 97 additions and 165 deletions

View File

@ -18,7 +18,7 @@ class JsonSerializer : public VariantDataVisitor<size_t> {
JsonSerializer(TWriter writer) : formatter_(writer) {} JsonSerializer(TWriter writer) : formatter_(writer) {}
FORCE_INLINE size_t visitArray(const ArrayData& array) { FORCE_INLINE size_t visit(const ArrayData& array) {
write('['); write('[');
auto it = array.createIterator(); auto it = array.createIterator();
@ -37,7 +37,7 @@ class JsonSerializer : public VariantDataVisitor<size_t> {
return bytesWritten(); return bytesWritten();
} }
size_t visitObject(const ObjectData& object) { size_t visit(const ObjectData& object) {
write('{'); write('{');
auto it = object.createIterator(); auto it = object.createIterator();
@ -58,42 +58,42 @@ class JsonSerializer : public VariantDataVisitor<size_t> {
return bytesWritten(); return bytesWritten();
} }
size_t visitFloat(JsonFloat value) { size_t visit(JsonFloat value) {
formatter_.writeFloat(value); formatter_.writeFloat(value);
return bytesWritten(); return bytesWritten();
} }
size_t visitString(const char* value) { size_t visit(const char* value) {
formatter_.writeString(value); formatter_.writeString(value);
return bytesWritten(); return bytesWritten();
} }
size_t visitString(JsonString value) { size_t visit(JsonString value) {
formatter_.writeString(value.c_str(), value.size()); formatter_.writeString(value.c_str(), value.size());
return bytesWritten(); return bytesWritten();
} }
size_t visitRawString(RawString value) { size_t visit(RawString value) {
formatter_.writeRaw(value.data(), value.size()); formatter_.writeRaw(value.data(), value.size());
return bytesWritten(); return bytesWritten();
} }
size_t visitSignedInteger(JsonInteger value) { size_t visit(JsonInteger value) {
formatter_.writeInteger(value); formatter_.writeInteger(value);
return bytesWritten(); return bytesWritten();
} }
size_t visitUnsignedInteger(JsonUInt value) { size_t visit(JsonUInt value) {
formatter_.writeInteger(value); formatter_.writeInteger(value);
return bytesWritten(); return bytesWritten();
} }
size_t visitBoolean(bool value) { size_t visit(bool value) {
formatter_.writeBoolean(value); formatter_.writeBoolean(value);
return bytesWritten(); return bytesWritten();
} }
size_t visitNull(nullptr_t) { size_t visit(nullptr_t) {
formatter_.writeRaw("null"); formatter_.writeRaw("null");
return bytesWritten(); return bytesWritten();
} }

View File

@ -18,7 +18,7 @@ class PrettyJsonSerializer : public JsonSerializer<TWriter> {
public: public:
PrettyJsonSerializer(TWriter writer) : base(writer), nesting_(0) {} PrettyJsonSerializer(TWriter writer) : base(writer), nesting_(0) {}
size_t visitArray(const ArrayData& array) { size_t visit(const ArrayData& array) {
auto it = array.createIterator(); auto it = array.createIterator();
if (!it.done()) { if (!it.done()) {
base::write("[\r\n"); base::write("[\r\n");
@ -39,14 +39,14 @@ class PrettyJsonSerializer : public JsonSerializer<TWriter> {
return this->bytesWritten(); return this->bytesWritten();
} }
size_t visitObject(const ObjectData& object) { size_t visit(const ObjectData& object) {
auto it = object.createIterator(); auto it = object.createIterator();
if (!it.done()) { if (!it.done()) {
base::write("{\r\n"); base::write("{\r\n");
nesting_++; nesting_++;
while (!it.done()) { while (!it.done()) {
indent(); indent();
base::visitString(it.key()); base::visit(it.key());
base::write(": "); base::write(": ");
it->accept(*this); it->accept(*this);
@ -62,6 +62,8 @@ class PrettyJsonSerializer : public JsonSerializer<TWriter> {
return this->bytesWritten(); return this->bytesWritten();
} }
using base::visit;
private: private:
void indent() { void indent() {
for (uint8_t i = 0; i < nesting_; i++) for (uint8_t i = 0; i < nesting_; i++)

View File

@ -22,11 +22,13 @@ class MsgPackSerializer : public VariantDataVisitor<size_t> {
MsgPackSerializer(TWriter writer) : writer_(writer) {} MsgPackSerializer(TWriter writer) : writer_(writer) {}
template <typename T> template <typename T>
typename enable_if<sizeof(T) == 4, size_t>::type visitFloat(T value32) { typename enable_if<is_floating_point<T>::value && sizeof(T) == 4,
size_t>::type
visit(T value32) {
if (canConvertNumber<JsonInteger>(value32)) { if (canConvertNumber<JsonInteger>(value32)) {
JsonInteger truncatedValue = JsonInteger(value32); JsonInteger truncatedValue = JsonInteger(value32);
if (value32 == T(truncatedValue)) if (value32 == T(truncatedValue))
return visitSignedInteger(truncatedValue); return visit(truncatedValue);
} }
writeByte(0xCA); writeByte(0xCA);
writeInteger(value32); writeInteger(value32);
@ -35,16 +37,17 @@ class MsgPackSerializer : public VariantDataVisitor<size_t> {
template <typename T> template <typename T>
ARDUINOJSON_NO_SANITIZE("float-cast-overflow") ARDUINOJSON_NO_SANITIZE("float-cast-overflow")
typename enable_if<sizeof(T) == 8, size_t>::type visitFloat(T value64) { typename enable_if<is_floating_point<T>::value && sizeof(T) == 8,
size_t>::type visit(T value64) {
float value32 = float(value64); float value32 = float(value64);
if (value32 == value64) if (value32 == value64)
return visitFloat(value32); return visit(value32);
writeByte(0xCB); writeByte(0xCB);
writeInteger(value64); writeInteger(value64);
return bytesWritten(); return bytesWritten();
} }
size_t visitArray(const ArrayData& array) { size_t visit(const ArrayData& array) {
size_t n = array.size(); size_t n = array.size();
if (n < 0x10) { if (n < 0x10) {
writeByte(uint8_t(0x90 + n)); writeByte(uint8_t(0x90 + n));
@ -61,7 +64,7 @@ class MsgPackSerializer : public VariantDataVisitor<size_t> {
return bytesWritten(); return bytesWritten();
} }
size_t visitObject(const ObjectData& object) { size_t visit(const ObjectData& object) {
size_t n = object.size(); size_t n = object.size();
if (n < 0x10) { if (n < 0x10) {
writeByte(uint8_t(0x80 + n)); writeByte(uint8_t(0x80 + n));
@ -73,17 +76,17 @@ class MsgPackSerializer : public VariantDataVisitor<size_t> {
writeInteger(uint32_t(n)); writeInteger(uint32_t(n));
} }
for (auto it = object.createIterator(); !it.done(); it.next()) { for (auto it = object.createIterator(); !it.done(); it.next()) {
visitString(it.key()); visit(it.key());
it->accept(*this); it->accept(*this);
} }
return bytesWritten(); return bytesWritten();
} }
size_t visitString(const char* value) { size_t visit(const char* value) {
return visitString(JsonString(value)); return visit(JsonString(value));
} }
size_t visitString(JsonString value) { size_t visit(JsonString value) {
ARDUINOJSON_ASSERT(value != NULL); ARDUINOJSON_ASSERT(value != NULL);
auto n = value.size(); auto n = value.size();
@ -104,14 +107,14 @@ class MsgPackSerializer : public VariantDataVisitor<size_t> {
return bytesWritten(); return bytesWritten();
} }
size_t visitRawString(RawString value) { size_t visit(RawString value) {
writeBytes(reinterpret_cast<const uint8_t*>(value.data()), value.size()); writeBytes(reinterpret_cast<const uint8_t*>(value.data()), value.size());
return bytesWritten(); return bytesWritten();
} }
size_t visitSignedInteger(JsonInteger value) { size_t visit(JsonInteger value) {
if (value > 0) { if (value > 0) {
visitUnsignedInteger(static_cast<JsonUInt>(value)); visit(static_cast<JsonUInt>(value));
} else if (value >= -0x20) { } else if (value >= -0x20) {
writeInteger(int8_t(value)); writeInteger(int8_t(value));
} else if (value >= -0x80) { } else if (value >= -0x80) {
@ -139,7 +142,7 @@ class MsgPackSerializer : public VariantDataVisitor<size_t> {
return bytesWritten(); return bytesWritten();
} }
size_t visitUnsignedInteger(JsonUInt value) { size_t visit(JsonUInt value) {
if (value <= 0x7F) { if (value <= 0x7F) {
writeInteger(uint8_t(value)); writeInteger(uint8_t(value));
} else if (value <= 0xFF) { } else if (value <= 0xFF) {
@ -167,12 +170,12 @@ class MsgPackSerializer : public VariantDataVisitor<size_t> {
return bytesWritten(); return bytesWritten();
} }
size_t visitBoolean(bool value) { size_t visit(bool value) {
writeByte(value ? 0xC3 : 0xC2); writeByte(value ? 0xC3 : 0xC2);
return bytesWritten(); return bytesWritten();
} }
size_t visitNull(nullptr_t) { size_t visit(nullptr_t) {
writeByte(0xC0); writeByte(0xC0);
return bytesWritten(); return bytesWritten();
} }

View File

@ -15,39 +15,8 @@ template <typename TResult>
struct JsonVariantVisitor { struct JsonVariantVisitor {
typedef TResult result_type; typedef TResult result_type;
TResult visitArray(JsonArrayConst) { template <typename T>
return TResult(); TResult visit(const T&) {
}
TResult visitBoolean(bool) {
return TResult();
}
TResult visitFloat(JsonFloat) {
return TResult();
}
TResult visitSignedInteger(JsonInteger) {
return TResult();
}
TResult visitNull(nullptr_t) {
return TResult();
}
TResult visitObject(JsonObjectConst) {
return TResult();
}
TResult visitUnsignedInteger(JsonUInt) {
return TResult();
}
TResult visitRawString(RawString) {
return TResult();
}
TResult visitString(JsonString) {
return TResult(); return TResult();
} }
}; };
@ -60,40 +29,17 @@ class VisitorAdapter {
VisitorAdapter(TVisitor& visitor, const ResourceManager* resources) VisitorAdapter(TVisitor& visitor, const ResourceManager* resources)
: visitor_(&visitor), resources_(resources) {} : visitor_(&visitor), resources_(resources) {}
result_type visitArray(const ArrayData& array) { result_type visit(const ArrayData& value) {
return visitor_->visitArray(JsonArrayConst(&array, resources_)); return visitor_->visit(JsonArrayConst(&value, resources_));
} }
result_type visitObject(const ObjectData& object) { result_type visit(const ObjectData& value) {
return visitor_->visitObject(JsonObjectConst(&object, resources_)); return visitor_->visit(JsonObjectConst(&value, resources_));
} }
result_type visitFloat(JsonFloat value) { template <typename T>
return visitor_->visitFloat(value); result_type visit(const T& value) {
} return visitor_->visit(value);
result_type visitString(JsonString value) {
return visitor_->visitString(value);
}
result_type visitRawString(RawString value) {
return visitor_->visitRawString(value);
}
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(nullptr_t) {
return visitor_->visitNull(nullptr);
} }
private: private:
@ -103,12 +49,12 @@ class VisitorAdapter {
template <typename TVisitor> template <typename TVisitor>
typename TVisitor::result_type accept(JsonVariantConst variant, typename TVisitor::result_type accept(JsonVariantConst variant,
TVisitor& visitor) { TVisitor& visit) {
auto data = VariantAttorney::getData(variant); auto data = VariantAttorney::getData(variant);
if (!data) if (!data)
return visitor.visitNull(nullptr); return visit.visit(nullptr);
auto resources = VariantAttorney::getResourceManager(variant); auto resources = VariantAttorney::getResourceManager(variant);
VisitorAdapter<TVisitor> adapter(visitor, resources); VisitorAdapter<TVisitor> adapter(visit, resources);
return data->accept(adapter); return data->accept(adapter);
} }

View File

@ -25,7 +25,7 @@ struct Comparer<T, typename enable_if<IsString<T>::value>::type>
explicit Comparer(T value) : rhs(value) {} explicit Comparer(T value) : rhs(value) {}
CompareResult visitString(JsonString lhs) { CompareResult visit(JsonString lhs) {
int i = stringCompare(adaptString(rhs), adaptString(lhs)); int i = stringCompare(adaptString(rhs), adaptString(lhs));
if (i < 0) if (i < 0)
return COMPARE_RESULT_GREATER; return COMPARE_RESULT_GREATER;
@ -35,12 +35,14 @@ struct Comparer<T, typename enable_if<IsString<T>::value>::type>
return COMPARE_RESULT_EQUAL; return COMPARE_RESULT_EQUAL;
} }
CompareResult visitNull(nullptr_t) { CompareResult visit(nullptr_t) {
if (adaptString(rhs).isNull()) if (adaptString(rhs).isNull())
return COMPARE_RESULT_EQUAL; return COMPARE_RESULT_EQUAL;
else else
return COMPARE_RESULT_DIFFER; return COMPARE_RESULT_DIFFER;
} }
using ComparerBase::visit;
}; };
template <typename T> template <typename T>
@ -51,27 +53,31 @@ struct Comparer<T, typename enable_if<is_integral<T>::value ||
explicit Comparer(T value) : rhs(value) {} explicit Comparer(T value) : rhs(value) {}
CompareResult visitFloat(JsonFloat lhs) { CompareResult visit(JsonFloat lhs) {
return arithmeticCompare(lhs, rhs); return arithmeticCompare(lhs, rhs);
} }
CompareResult visitSignedInteger(JsonInteger lhs) { CompareResult visit(JsonInteger lhs) {
return arithmeticCompare(lhs, rhs); return arithmeticCompare(lhs, rhs);
} }
CompareResult visitUnsignedInteger(JsonUInt lhs) { CompareResult visit(JsonUInt lhs) {
return arithmeticCompare(lhs, rhs); return arithmeticCompare(lhs, rhs);
} }
CompareResult visitBoolean(bool lhs) { CompareResult visit(bool lhs) {
return visitUnsignedInteger(static_cast<JsonUInt>(lhs)); return visit(static_cast<JsonUInt>(lhs));
} }
using ComparerBase::visit;
}; };
struct NullComparer : ComparerBase { struct NullComparer : ComparerBase {
CompareResult visitNull(nullptr_t) { CompareResult visit(nullptr_t) {
return COMPARE_RESULT_EQUAL; return COMPARE_RESULT_EQUAL;
} }
using ComparerBase::visit;
}; };
template <> template <>
@ -84,12 +90,14 @@ struct ArrayComparer : ComparerBase {
explicit ArrayComparer(JsonArrayConst rhs) : rhs_(rhs) {} explicit ArrayComparer(JsonArrayConst rhs) : rhs_(rhs) {}
CompareResult visitArray(JsonArrayConst lhs) { CompareResult visit(JsonArrayConst lhs) {
if (rhs_ == lhs) if (rhs_ == lhs)
return COMPARE_RESULT_EQUAL; return COMPARE_RESULT_EQUAL;
else else
return COMPARE_RESULT_DIFFER; return COMPARE_RESULT_DIFFER;
} }
using ComparerBase::visit;
}; };
struct ObjectComparer : ComparerBase { struct ObjectComparer : ComparerBase {
@ -97,12 +105,14 @@ struct ObjectComparer : ComparerBase {
explicit ObjectComparer(JsonObjectConst rhs) : rhs_(rhs) {} explicit ObjectComparer(JsonObjectConst rhs) : rhs_(rhs) {}
CompareResult visitObject(JsonObjectConst lhs) { CompareResult visit(JsonObjectConst lhs) {
if (lhs == rhs_) if (lhs == rhs_)
return COMPARE_RESULT_EQUAL; return COMPARE_RESULT_EQUAL;
else else
return COMPARE_RESULT_DIFFER; return COMPARE_RESULT_DIFFER;
} }
using ComparerBase::visit;
}; };
struct RawComparer : ComparerBase { struct RawComparer : ComparerBase {
@ -110,7 +120,7 @@ struct RawComparer : ComparerBase {
explicit RawComparer(RawString rhs) : rhs_(rhs) {} explicit RawComparer(RawString rhs) : rhs_(rhs) {}
CompareResult visitRawString(RawString lhs) { CompareResult visit(RawString lhs) {
size_t size = rhs_.size() < lhs.size() ? rhs_.size() : lhs.size(); size_t size = rhs_.size() < lhs.size() ? rhs_.size() : lhs.size();
int n = memcmp(lhs.data(), rhs_.data(), size); int n = memcmp(lhs.data(), rhs_.data(), size);
if (n < 0) if (n < 0)
@ -120,6 +130,8 @@ struct RawComparer : ComparerBase {
else else
return COMPARE_RESULT_EQUAL; return COMPARE_RESULT_EQUAL;
} }
using ComparerBase::visit;
}; };
struct VariantComparer : ComparerBase { struct VariantComparer : ComparerBase {
@ -127,47 +139,47 @@ struct VariantComparer : ComparerBase {
explicit VariantComparer(JsonVariantConst value) : rhs(value) {} explicit VariantComparer(JsonVariantConst value) : rhs(value) {}
CompareResult visitArray(JsonArrayConst lhs) { CompareResult visit(JsonArrayConst lhs) {
ArrayComparer comparer(lhs); ArrayComparer comparer(lhs);
return reverseResult(comparer); return reverseResult(comparer);
} }
CompareResult visitObject(JsonObjectConst lhs) { CompareResult visit(JsonObjectConst lhs) {
ObjectComparer comparer(lhs); ObjectComparer comparer(lhs);
return reverseResult(comparer); return reverseResult(comparer);
} }
CompareResult visitFloat(JsonFloat lhs) { CompareResult visit(JsonFloat lhs) {
Comparer<JsonFloat> comparer(lhs); Comparer<JsonFloat> comparer(lhs);
return reverseResult(comparer); return reverseResult(comparer);
} }
CompareResult visitString(JsonString lhs) { CompareResult visit(JsonString lhs) {
Comparer<JsonString> comparer(lhs); Comparer<JsonString> comparer(lhs);
return reverseResult(comparer); return reverseResult(comparer);
} }
CompareResult visitRawString(RawString value) { CompareResult visit(RawString value) {
RawComparer comparer(value); RawComparer comparer(value);
return reverseResult(comparer); return reverseResult(comparer);
} }
CompareResult visitSignedInteger(JsonInteger lhs) { CompareResult visit(JsonInteger lhs) {
Comparer<JsonInteger> comparer(lhs); Comparer<JsonInteger> comparer(lhs);
return reverseResult(comparer); return reverseResult(comparer);
} }
CompareResult visitUnsignedInteger(JsonUInt lhs) { CompareResult visit(JsonUInt lhs) {
Comparer<JsonUInt> comparer(lhs); Comparer<JsonUInt> comparer(lhs);
return reverseResult(comparer); return reverseResult(comparer);
} }
CompareResult visitBoolean(bool lhs) { CompareResult visit(bool lhs) {
Comparer<bool> comparer(lhs); Comparer<bool> comparer(lhs);
return reverseResult(comparer); return reverseResult(comparer);
} }
CompareResult visitNull(nullptr_t) { CompareResult visit(nullptr_t) {
NullComparer comparer; NullComparer comparer;
return reverseResult(comparer); return reverseResult(comparer);
} }

View File

@ -25,50 +25,50 @@ class VariantData {
VariantData() : flags_(VALUE_IS_NULL) {} VariantData() : flags_(VALUE_IS_NULL) {}
template <typename TVisitor> template <typename TVisitor>
typename TVisitor::result_type accept(TVisitor& visitor) const { typename TVisitor::result_type accept(TVisitor& visit) const {
switch (type()) { switch (type()) {
case VALUE_IS_FLOAT: case VALUE_IS_FLOAT:
return visitor.visitFloat(content_.asFloat); return visit.visit(content_.asFloat);
case VALUE_IS_ARRAY: case VALUE_IS_ARRAY:
return visitor.visitArray(content_.asArray); return visit.visit(content_.asArray);
case VALUE_IS_OBJECT: case VALUE_IS_OBJECT:
return visitor.visitObject(content_.asObject); return visit.visit(content_.asObject);
case VALUE_IS_LINKED_STRING: case VALUE_IS_LINKED_STRING:
return visitor.visitString(JsonString(content_.asLinkedString)); return visit.visit(JsonString(content_.asLinkedString));
case VALUE_IS_OWNED_STRING: case VALUE_IS_OWNED_STRING:
return visitor.visitString(JsonString(content_.asOwnedString->data, return visit.visit(JsonString(content_.asOwnedString->data,
content_.asOwnedString->length, content_.asOwnedString->length,
JsonString::Copied)); JsonString::Copied));
case VALUE_IS_RAW_STRING: case VALUE_IS_RAW_STRING:
return visitor.visitRawString(RawString( return visit.visit(RawString(content_.asOwnedString->data,
content_.asOwnedString->data, content_.asOwnedString->length)); content_.asOwnedString->length));
case VALUE_IS_SIGNED_INTEGER: case VALUE_IS_SIGNED_INTEGER:
return visitor.visitSignedInteger(content_.asSignedInteger); return visit.visit(content_.asSignedInteger);
case VALUE_IS_UNSIGNED_INTEGER: case VALUE_IS_UNSIGNED_INTEGER:
return visitor.visitUnsignedInteger(content_.asUnsignedInteger); return visit.visit(content_.asUnsignedInteger);
case VALUE_IS_BOOLEAN: case VALUE_IS_BOOLEAN:
return visitor.visitBoolean(content_.asBoolean != 0); return visit.visit(content_.asBoolean != 0);
default: default:
return visitor.visitNull(nullptr); return visit.visit(nullptr);
} }
} }
template <typename TVisitor> template <typename TVisitor>
static typename TVisitor::result_type accept(const VariantData* var, static typename TVisitor::result_type accept(const VariantData* var,
TVisitor& visitor) { TVisitor& visit) {
if (var != 0) if (var != 0)
return var->accept(visitor); return var->accept(visit);
else else
return visitor.visitNull(nullptr); return visit.visit(nullptr);
} }
VariantData* addElement(ResourceManager* resources) { VariantData* addElement(ResourceManager* resources) {

View File

@ -15,39 +15,8 @@ template <typename TResult>
struct VariantDataVisitor { struct VariantDataVisitor {
typedef TResult result_type; typedef TResult result_type;
TResult visitArray(const ArrayData&) { template <typename T>
return TResult(); TResult visit(const T&) {
}
TResult visitBoolean(bool) {
return TResult();
}
TResult visitFloat(JsonFloat) {
return TResult();
}
TResult visitSignedInteger(JsonInteger) {
return TResult();
}
TResult visitNull(nullptr_t) {
return TResult();
}
TResult visitObject(const ObjectData&) {
return TResult();
}
TResult visitUnsignedInteger(JsonUInt) {
return TResult();
}
TResult visitRawString(RawString) {
return TResult();
}
TResult visitString(JsonString) {
return TResult(); return TResult();
} }
}; };