forked from bblanchon/ArduinoJson
Merge all visitXxx()
into one overloaded visit()
function
This commit is contained in:
@ -18,7 +18,7 @@ class JsonSerializer : public VariantDataVisitor<size_t> {
|
||||
|
||||
JsonSerializer(TWriter writer) : formatter_(writer) {}
|
||||
|
||||
FORCE_INLINE size_t visitArray(const ArrayData& array) {
|
||||
FORCE_INLINE size_t visit(const ArrayData& array) {
|
||||
write('[');
|
||||
|
||||
auto it = array.createIterator();
|
||||
@ -37,7 +37,7 @@ class JsonSerializer : public VariantDataVisitor<size_t> {
|
||||
return bytesWritten();
|
||||
}
|
||||
|
||||
size_t visitObject(const ObjectData& object) {
|
||||
size_t visit(const ObjectData& object) {
|
||||
write('{');
|
||||
|
||||
auto it = object.createIterator();
|
||||
@ -58,42 +58,42 @@ class JsonSerializer : public VariantDataVisitor<size_t> {
|
||||
return bytesWritten();
|
||||
}
|
||||
|
||||
size_t visitFloat(JsonFloat value) {
|
||||
size_t visit(JsonFloat value) {
|
||||
formatter_.writeFloat(value);
|
||||
return bytesWritten();
|
||||
}
|
||||
|
||||
size_t visitString(const char* value) {
|
||||
size_t visit(const char* value) {
|
||||
formatter_.writeString(value);
|
||||
return bytesWritten();
|
||||
}
|
||||
|
||||
size_t visitString(JsonString value) {
|
||||
size_t visit(JsonString value) {
|
||||
formatter_.writeString(value.c_str(), value.size());
|
||||
return bytesWritten();
|
||||
}
|
||||
|
||||
size_t visitRawString(RawString value) {
|
||||
size_t visit(RawString value) {
|
||||
formatter_.writeRaw(value.data(), value.size());
|
||||
return bytesWritten();
|
||||
}
|
||||
|
||||
size_t visitSignedInteger(JsonInteger value) {
|
||||
size_t visit(JsonInteger value) {
|
||||
formatter_.writeInteger(value);
|
||||
return bytesWritten();
|
||||
}
|
||||
|
||||
size_t visitUnsignedInteger(JsonUInt value) {
|
||||
size_t visit(JsonUInt value) {
|
||||
formatter_.writeInteger(value);
|
||||
return bytesWritten();
|
||||
}
|
||||
|
||||
size_t visitBoolean(bool value) {
|
||||
size_t visit(bool value) {
|
||||
formatter_.writeBoolean(value);
|
||||
return bytesWritten();
|
||||
}
|
||||
|
||||
size_t visitNull(nullptr_t) {
|
||||
size_t visit(nullptr_t) {
|
||||
formatter_.writeRaw("null");
|
||||
return bytesWritten();
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ class PrettyJsonSerializer : public JsonSerializer<TWriter> {
|
||||
public:
|
||||
PrettyJsonSerializer(TWriter writer) : base(writer), nesting_(0) {}
|
||||
|
||||
size_t visitArray(const ArrayData& array) {
|
||||
size_t visit(const ArrayData& array) {
|
||||
auto it = array.createIterator();
|
||||
if (!it.done()) {
|
||||
base::write("[\r\n");
|
||||
@ -39,14 +39,14 @@ class PrettyJsonSerializer : public JsonSerializer<TWriter> {
|
||||
return this->bytesWritten();
|
||||
}
|
||||
|
||||
size_t visitObject(const ObjectData& object) {
|
||||
size_t visit(const ObjectData& object) {
|
||||
auto it = object.createIterator();
|
||||
if (!it.done()) {
|
||||
base::write("{\r\n");
|
||||
nesting_++;
|
||||
while (!it.done()) {
|
||||
indent();
|
||||
base::visitString(it.key());
|
||||
base::visit(it.key());
|
||||
base::write(": ");
|
||||
it->accept(*this);
|
||||
|
||||
@ -62,6 +62,8 @@ class PrettyJsonSerializer : public JsonSerializer<TWriter> {
|
||||
return this->bytesWritten();
|
||||
}
|
||||
|
||||
using base::visit;
|
||||
|
||||
private:
|
||||
void indent() {
|
||||
for (uint8_t i = 0; i < nesting_; i++)
|
||||
|
@ -22,11 +22,13 @@ class MsgPackSerializer : public VariantDataVisitor<size_t> {
|
||||
MsgPackSerializer(TWriter writer) : writer_(writer) {}
|
||||
|
||||
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)) {
|
||||
JsonInteger truncatedValue = JsonInteger(value32);
|
||||
if (value32 == T(truncatedValue))
|
||||
return visitSignedInteger(truncatedValue);
|
||||
return visit(truncatedValue);
|
||||
}
|
||||
writeByte(0xCA);
|
||||
writeInteger(value32);
|
||||
@ -35,16 +37,17 @@ class MsgPackSerializer : public VariantDataVisitor<size_t> {
|
||||
|
||||
template <typename T>
|
||||
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);
|
||||
if (value32 == value64)
|
||||
return visitFloat(value32);
|
||||
return visit(value32);
|
||||
writeByte(0xCB);
|
||||
writeInteger(value64);
|
||||
return bytesWritten();
|
||||
}
|
||||
|
||||
size_t visitArray(const ArrayData& array) {
|
||||
size_t visit(const ArrayData& array) {
|
||||
size_t n = array.size();
|
||||
if (n < 0x10) {
|
||||
writeByte(uint8_t(0x90 + n));
|
||||
@ -61,7 +64,7 @@ class MsgPackSerializer : public VariantDataVisitor<size_t> {
|
||||
return bytesWritten();
|
||||
}
|
||||
|
||||
size_t visitObject(const ObjectData& object) {
|
||||
size_t visit(const ObjectData& object) {
|
||||
size_t n = object.size();
|
||||
if (n < 0x10) {
|
||||
writeByte(uint8_t(0x80 + n));
|
||||
@ -73,17 +76,17 @@ class MsgPackSerializer : public VariantDataVisitor<size_t> {
|
||||
writeInteger(uint32_t(n));
|
||||
}
|
||||
for (auto it = object.createIterator(); !it.done(); it.next()) {
|
||||
visitString(it.key());
|
||||
visit(it.key());
|
||||
it->accept(*this);
|
||||
}
|
||||
return bytesWritten();
|
||||
}
|
||||
|
||||
size_t visitString(const char* value) {
|
||||
return visitString(JsonString(value));
|
||||
size_t visit(const char* value) {
|
||||
return visit(JsonString(value));
|
||||
}
|
||||
|
||||
size_t visitString(JsonString value) {
|
||||
size_t visit(JsonString value) {
|
||||
ARDUINOJSON_ASSERT(value != NULL);
|
||||
|
||||
auto n = value.size();
|
||||
@ -104,14 +107,14 @@ class MsgPackSerializer : public VariantDataVisitor<size_t> {
|
||||
return bytesWritten();
|
||||
}
|
||||
|
||||
size_t visitRawString(RawString value) {
|
||||
size_t visit(RawString value) {
|
||||
writeBytes(reinterpret_cast<const uint8_t*>(value.data()), value.size());
|
||||
return bytesWritten();
|
||||
}
|
||||
|
||||
size_t visitSignedInteger(JsonInteger value) {
|
||||
size_t visit(JsonInteger value) {
|
||||
if (value > 0) {
|
||||
visitUnsignedInteger(static_cast<JsonUInt>(value));
|
||||
visit(static_cast<JsonUInt>(value));
|
||||
} else if (value >= -0x20) {
|
||||
writeInteger(int8_t(value));
|
||||
} else if (value >= -0x80) {
|
||||
@ -139,7 +142,7 @@ class MsgPackSerializer : public VariantDataVisitor<size_t> {
|
||||
return bytesWritten();
|
||||
}
|
||||
|
||||
size_t visitUnsignedInteger(JsonUInt value) {
|
||||
size_t visit(JsonUInt value) {
|
||||
if (value <= 0x7F) {
|
||||
writeInteger(uint8_t(value));
|
||||
} else if (value <= 0xFF) {
|
||||
@ -167,12 +170,12 @@ class MsgPackSerializer : public VariantDataVisitor<size_t> {
|
||||
return bytesWritten();
|
||||
}
|
||||
|
||||
size_t visitBoolean(bool value) {
|
||||
size_t visit(bool value) {
|
||||
writeByte(value ? 0xC3 : 0xC2);
|
||||
return bytesWritten();
|
||||
}
|
||||
|
||||
size_t visitNull(nullptr_t) {
|
||||
size_t visit(nullptr_t) {
|
||||
writeByte(0xC0);
|
||||
return bytesWritten();
|
||||
}
|
||||
|
@ -15,39 +15,8 @@ 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(nullptr_t) {
|
||||
return TResult();
|
||||
}
|
||||
|
||||
TResult visitObject(JsonObjectConst) {
|
||||
return TResult();
|
||||
}
|
||||
|
||||
TResult visitUnsignedInteger(JsonUInt) {
|
||||
return TResult();
|
||||
}
|
||||
|
||||
TResult visitRawString(RawString) {
|
||||
return TResult();
|
||||
}
|
||||
|
||||
TResult visitString(JsonString) {
|
||||
template <typename T>
|
||||
TResult visit(const T&) {
|
||||
return TResult();
|
||||
}
|
||||
};
|
||||
@ -60,40 +29,17 @@ class VisitorAdapter {
|
||||
VisitorAdapter(TVisitor& visitor, const ResourceManager* resources)
|
||||
: visitor_(&visitor), resources_(resources) {}
|
||||
|
||||
result_type visitArray(const ArrayData& array) {
|
||||
return visitor_->visitArray(JsonArrayConst(&array, resources_));
|
||||
result_type visit(const ArrayData& value) {
|
||||
return visitor_->visit(JsonArrayConst(&value, resources_));
|
||||
}
|
||||
|
||||
result_type visitObject(const ObjectData& object) {
|
||||
return visitor_->visitObject(JsonObjectConst(&object, resources_));
|
||||
result_type visit(const ObjectData& value) {
|
||||
return visitor_->visit(JsonObjectConst(&value, resources_));
|
||||
}
|
||||
|
||||
result_type visitFloat(JsonFloat value) {
|
||||
return visitor_->visitFloat(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);
|
||||
template <typename T>
|
||||
result_type visit(const T& value) {
|
||||
return visitor_->visit(value);
|
||||
}
|
||||
|
||||
private:
|
||||
@ -103,12 +49,12 @@ class VisitorAdapter {
|
||||
|
||||
template <typename TVisitor>
|
||||
typename TVisitor::result_type accept(JsonVariantConst variant,
|
||||
TVisitor& visitor) {
|
||||
TVisitor& visit) {
|
||||
auto data = VariantAttorney::getData(variant);
|
||||
if (!data)
|
||||
return visitor.visitNull(nullptr);
|
||||
return visit.visit(nullptr);
|
||||
auto resources = VariantAttorney::getResourceManager(variant);
|
||||
VisitorAdapter<TVisitor> adapter(visitor, resources);
|
||||
VisitorAdapter<TVisitor> adapter(visit, resources);
|
||||
return data->accept(adapter);
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,7 @@ struct Comparer<T, typename enable_if<IsString<T>::value>::type>
|
||||
|
||||
explicit Comparer(T value) : rhs(value) {}
|
||||
|
||||
CompareResult visitString(JsonString lhs) {
|
||||
CompareResult visit(JsonString lhs) {
|
||||
int i = stringCompare(adaptString(rhs), adaptString(lhs));
|
||||
if (i < 0)
|
||||
return COMPARE_RESULT_GREATER;
|
||||
@ -35,12 +35,14 @@ struct Comparer<T, typename enable_if<IsString<T>::value>::type>
|
||||
return COMPARE_RESULT_EQUAL;
|
||||
}
|
||||
|
||||
CompareResult visitNull(nullptr_t) {
|
||||
CompareResult visit(nullptr_t) {
|
||||
if (adaptString(rhs).isNull())
|
||||
return COMPARE_RESULT_EQUAL;
|
||||
else
|
||||
return COMPARE_RESULT_DIFFER;
|
||||
}
|
||||
|
||||
using ComparerBase::visit;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
@ -51,27 +53,31 @@ struct Comparer<T, typename enable_if<is_integral<T>::value ||
|
||||
|
||||
explicit Comparer(T value) : rhs(value) {}
|
||||
|
||||
CompareResult visitFloat(JsonFloat lhs) {
|
||||
CompareResult visit(JsonFloat lhs) {
|
||||
return arithmeticCompare(lhs, rhs);
|
||||
}
|
||||
|
||||
CompareResult visitSignedInteger(JsonInteger lhs) {
|
||||
CompareResult visit(JsonInteger lhs) {
|
||||
return arithmeticCompare(lhs, rhs);
|
||||
}
|
||||
|
||||
CompareResult visitUnsignedInteger(JsonUInt lhs) {
|
||||
CompareResult visit(JsonUInt lhs) {
|
||||
return arithmeticCompare(lhs, rhs);
|
||||
}
|
||||
|
||||
CompareResult visitBoolean(bool lhs) {
|
||||
return visitUnsignedInteger(static_cast<JsonUInt>(lhs));
|
||||
CompareResult visit(bool lhs) {
|
||||
return visit(static_cast<JsonUInt>(lhs));
|
||||
}
|
||||
|
||||
using ComparerBase::visit;
|
||||
};
|
||||
|
||||
struct NullComparer : ComparerBase {
|
||||
CompareResult visitNull(nullptr_t) {
|
||||
CompareResult visit(nullptr_t) {
|
||||
return COMPARE_RESULT_EQUAL;
|
||||
}
|
||||
|
||||
using ComparerBase::visit;
|
||||
};
|
||||
|
||||
template <>
|
||||
@ -84,12 +90,14 @@ struct ArrayComparer : ComparerBase {
|
||||
|
||||
explicit ArrayComparer(JsonArrayConst rhs) : rhs_(rhs) {}
|
||||
|
||||
CompareResult visitArray(JsonArrayConst lhs) {
|
||||
CompareResult visit(JsonArrayConst lhs) {
|
||||
if (rhs_ == lhs)
|
||||
return COMPARE_RESULT_EQUAL;
|
||||
else
|
||||
return COMPARE_RESULT_DIFFER;
|
||||
}
|
||||
|
||||
using ComparerBase::visit;
|
||||
};
|
||||
|
||||
struct ObjectComparer : ComparerBase {
|
||||
@ -97,12 +105,14 @@ struct ObjectComparer : ComparerBase {
|
||||
|
||||
explicit ObjectComparer(JsonObjectConst rhs) : rhs_(rhs) {}
|
||||
|
||||
CompareResult visitObject(JsonObjectConst lhs) {
|
||||
CompareResult visit(JsonObjectConst lhs) {
|
||||
if (lhs == rhs_)
|
||||
return COMPARE_RESULT_EQUAL;
|
||||
else
|
||||
return COMPARE_RESULT_DIFFER;
|
||||
}
|
||||
|
||||
using ComparerBase::visit;
|
||||
};
|
||||
|
||||
struct RawComparer : ComparerBase {
|
||||
@ -110,7 +120,7 @@ struct RawComparer : ComparerBase {
|
||||
|
||||
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();
|
||||
int n = memcmp(lhs.data(), rhs_.data(), size);
|
||||
if (n < 0)
|
||||
@ -120,6 +130,8 @@ struct RawComparer : ComparerBase {
|
||||
else
|
||||
return COMPARE_RESULT_EQUAL;
|
||||
}
|
||||
|
||||
using ComparerBase::visit;
|
||||
};
|
||||
|
||||
struct VariantComparer : ComparerBase {
|
||||
@ -127,47 +139,47 @@ struct VariantComparer : ComparerBase {
|
||||
|
||||
explicit VariantComparer(JsonVariantConst value) : rhs(value) {}
|
||||
|
||||
CompareResult visitArray(JsonArrayConst lhs) {
|
||||
CompareResult visit(JsonArrayConst lhs) {
|
||||
ArrayComparer comparer(lhs);
|
||||
return reverseResult(comparer);
|
||||
}
|
||||
|
||||
CompareResult visitObject(JsonObjectConst lhs) {
|
||||
CompareResult visit(JsonObjectConst lhs) {
|
||||
ObjectComparer comparer(lhs);
|
||||
return reverseResult(comparer);
|
||||
}
|
||||
|
||||
CompareResult visitFloat(JsonFloat lhs) {
|
||||
CompareResult visit(JsonFloat lhs) {
|
||||
Comparer<JsonFloat> comparer(lhs);
|
||||
return reverseResult(comparer);
|
||||
}
|
||||
|
||||
CompareResult visitString(JsonString lhs) {
|
||||
CompareResult visit(JsonString lhs) {
|
||||
Comparer<JsonString> comparer(lhs);
|
||||
return reverseResult(comparer);
|
||||
}
|
||||
|
||||
CompareResult visitRawString(RawString value) {
|
||||
CompareResult visit(RawString value) {
|
||||
RawComparer comparer(value);
|
||||
return reverseResult(comparer);
|
||||
}
|
||||
|
||||
CompareResult visitSignedInteger(JsonInteger lhs) {
|
||||
CompareResult visit(JsonInteger lhs) {
|
||||
Comparer<JsonInteger> comparer(lhs);
|
||||
return reverseResult(comparer);
|
||||
}
|
||||
|
||||
CompareResult visitUnsignedInteger(JsonUInt lhs) {
|
||||
CompareResult visit(JsonUInt lhs) {
|
||||
Comparer<JsonUInt> comparer(lhs);
|
||||
return reverseResult(comparer);
|
||||
}
|
||||
|
||||
CompareResult visitBoolean(bool lhs) {
|
||||
CompareResult visit(bool lhs) {
|
||||
Comparer<bool> comparer(lhs);
|
||||
return reverseResult(comparer);
|
||||
}
|
||||
|
||||
CompareResult visitNull(nullptr_t) {
|
||||
CompareResult visit(nullptr_t) {
|
||||
NullComparer comparer;
|
||||
return reverseResult(comparer);
|
||||
}
|
||||
|
@ -25,50 +25,50 @@ class VariantData {
|
||||
VariantData() : flags_(VALUE_IS_NULL) {}
|
||||
|
||||
template <typename TVisitor>
|
||||
typename TVisitor::result_type accept(TVisitor& visitor) const {
|
||||
typename TVisitor::result_type accept(TVisitor& visit) const {
|
||||
switch (type()) {
|
||||
case VALUE_IS_FLOAT:
|
||||
return visitor.visitFloat(content_.asFloat);
|
||||
return visit.visit(content_.asFloat);
|
||||
|
||||
case VALUE_IS_ARRAY:
|
||||
return visitor.visitArray(content_.asArray);
|
||||
return visit.visit(content_.asArray);
|
||||
|
||||
case VALUE_IS_OBJECT:
|
||||
return visitor.visitObject(content_.asObject);
|
||||
return visit.visit(content_.asObject);
|
||||
|
||||
case VALUE_IS_LINKED_STRING:
|
||||
return visitor.visitString(JsonString(content_.asLinkedString));
|
||||
return visit.visit(JsonString(content_.asLinkedString));
|
||||
|
||||
case VALUE_IS_OWNED_STRING:
|
||||
return visitor.visitString(JsonString(content_.asOwnedString->data,
|
||||
content_.asOwnedString->length,
|
||||
JsonString::Copied));
|
||||
return visit.visit(JsonString(content_.asOwnedString->data,
|
||||
content_.asOwnedString->length,
|
||||
JsonString::Copied));
|
||||
|
||||
case VALUE_IS_RAW_STRING:
|
||||
return visitor.visitRawString(RawString(
|
||||
content_.asOwnedString->data, content_.asOwnedString->length));
|
||||
return visit.visit(RawString(content_.asOwnedString->data,
|
||||
content_.asOwnedString->length));
|
||||
|
||||
case VALUE_IS_SIGNED_INTEGER:
|
||||
return visitor.visitSignedInteger(content_.asSignedInteger);
|
||||
return visit.visit(content_.asSignedInteger);
|
||||
|
||||
case VALUE_IS_UNSIGNED_INTEGER:
|
||||
return visitor.visitUnsignedInteger(content_.asUnsignedInteger);
|
||||
return visit.visit(content_.asUnsignedInteger);
|
||||
|
||||
case VALUE_IS_BOOLEAN:
|
||||
return visitor.visitBoolean(content_.asBoolean != 0);
|
||||
return visit.visit(content_.asBoolean != 0);
|
||||
|
||||
default:
|
||||
return visitor.visitNull(nullptr);
|
||||
return visit.visit(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename TVisitor>
|
||||
static typename TVisitor::result_type accept(const VariantData* var,
|
||||
TVisitor& visitor) {
|
||||
TVisitor& visit) {
|
||||
if (var != 0)
|
||||
return var->accept(visitor);
|
||||
return var->accept(visit);
|
||||
else
|
||||
return visitor.visitNull(nullptr);
|
||||
return visit.visit(nullptr);
|
||||
}
|
||||
|
||||
VariantData* addElement(ResourceManager* resources) {
|
||||
|
@ -15,39 +15,8 @@ template <typename TResult>
|
||||
struct VariantDataVisitor {
|
||||
typedef TResult result_type;
|
||||
|
||||
TResult visitArray(const ArrayData&) {
|
||||
return TResult();
|
||||
}
|
||||
|
||||
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) {
|
||||
template <typename T>
|
||||
TResult visit(const T&) {
|
||||
return TResult();
|
||||
}
|
||||
};
|
||||
|
Reference in New Issue
Block a user