// ArduinoJson - arduinojson.org // Copyright Benoit Blanchon 2014-2021 // MIT License #pragma once #include #include #include namespace ARDUINOJSON_NAMESPACE { template struct Converter { static bool toJson(VariantRef variant, const T& value) { // clang-format off return convertToJson(variant, value); // Error here? See https://arduinojson.org/v6/unsupported-set/ // clang-format on } static T fromJson(VariantConstRef variant) { // clang-format off T value; // Error here? See https://arduinojson.org/v6/non-default-constructible/ convertFromJson(value, variant); // Error here? See https://arduinojson.org/v6/unsupported-as/ // clang-format on return value; } static bool checkJson(VariantConstRef variant) { T dummy; // clang-format off return canConvertFromJson(dummy, variant); // Error here? See https://arduinojson.org/v6/unsupported-is/ // clang-format on } }; template struct Converter< T, typename enable_if::value && !is_same::value && !is_same::value>::type> { static bool toJson(VariantRef variant, T value) { VariantData* data = getData(variant); ARDUINOJSON_ASSERT_INTEGER_TYPE_IS_SUPPORTED(T); if (!data) return false; data->setInteger(value); return true; } static T fromJson(VariantConstRef variant) { ARDUINOJSON_ASSERT_INTEGER_TYPE_IS_SUPPORTED(T); const VariantData* data = getData(variant); return data ? data->asIntegral() : T(); } static bool checkJson(VariantConstRef variant) { const VariantData* data = getData(variant); return data && data->isInteger(); } }; template struct Converter::value>::type> { static bool toJson(VariantRef variant, T value) { return variant.set(static_cast(value)); } static T fromJson(VariantConstRef variant) { const VariantData* data = getData(variant); return data ? static_cast(data->asIntegral()) : T(); } static bool checkJson(VariantConstRef variant) { const VariantData* data = getData(variant); return data && data->isInteger(); } }; template <> struct Converter { static bool toJson(VariantRef variant, bool value) { VariantData* data = getData(variant); if (!data) return false; data->setBoolean(value); return true; } static bool fromJson(VariantConstRef variant) { const VariantData* data = getData(variant); return data ? data->asBoolean() : false; } static bool checkJson(VariantConstRef variant) { const VariantData* data = getData(variant); return data && data->isBoolean(); } }; template struct Converter::value>::type> { static bool toJson(VariantRef variant, T value) { VariantData* data = getData(variant); if (!data) return false; data->setFloat(static_cast(value)); return true; } static T fromJson(VariantConstRef variant) { const VariantData* data = getData(variant); return data ? data->asFloat() : false; } static bool checkJson(VariantConstRef variant) { const VariantData* data = getData(variant); return data && data->isFloat(); } }; template <> struct Converter { static bool toJson(VariantRef variant, const char* value) { // TODO: don't pass pool return variantSetString(getData(variant), adaptString(value), getPool(variant)); } static const char* fromJson(VariantConstRef variant) { const VariantData* data = getData(variant); return data ? data->asString() : 0; } static bool checkJson(VariantConstRef variant) { const VariantData* data = getData(variant); return data && data->isString(); } }; template inline typename enable_if::value, bool>::type convertToJson( VariantRef variant, const T& value) { VariantData* data = getData(variant); MemoryPool* pool = getPool(variant); return variantSetString(data, adaptString(value), pool); } template inline typename enable_if::value>::type convertFromJson( T& value, VariantConstRef variant) { const VariantData* data = getData(variant); const char* cstr = data != 0 ? data->asString() : 0; if (cstr) value = cstr; else serializeJson(variant, value); } template inline typename enable_if::value, bool>::type canConvertFromJson(T&, VariantConstRef variant) { const VariantData* data = getData(variant); return data && data->isString(); } template <> struct Converter > { static bool toJson(VariantRef variant, SerializedValue value) { VariantData* data = getData(variant); if (!data) return false; data->setLinkedRaw(value); return true; } }; // SerializedValue // SerializedValue // SerializedValue template struct Converter, typename enable_if::value>::type> { static bool toJson(VariantRef variant, SerializedValue value) { VariantData* data = getData(variant); MemoryPool* pool = getPool(variant); return data != 0 && data->setOwnedRaw(value, pool); } }; #if ARDUINOJSON_HAS_NULLPTR template <> struct Converter { static bool toJson(VariantRef variant, decltype(nullptr)) { variantSetNull(getData(variant)); return true; } static decltype(nullptr) fromJson(VariantConstRef) { return nullptr; } static bool checkJson(VariantConstRef variant) { const VariantData* data = getData(variant); return data == 0 || data->isNull(); } }; #endif #if ARDUINOJSON_ENABLE_ARDUINO_STREAM class MemoryPoolPrint : public Print { public: MemoryPoolPrint(MemoryPool* pool) : _pool(pool), _size(0) { pool->getFreeZone(&_string, &_capacity); } const char* c_str() { if (_size >= _capacity) return 0; _string[_size++] = 0; // TODO: test overflow return _pool->saveStringFromFreeZone(_size); } size_t write(uint8_t c) { if (_size >= _capacity) return 0; _string[_size++] = char(c); return 1; } size_t write(const uint8_t* buffer, size_t size) { if (_size + size >= _capacity) { _size = _capacity; // mark as overflowed return 0; } memcpy(&_string[_size], buffer, size); _size += size; return size; } bool overflowed() const { return _size >= _capacity; } private: MemoryPool* _pool; size_t _size; char* _string; size_t _capacity; }; inline bool convertToJson(VariantRef variant, const ::Printable& value) { MemoryPool* pool = getPool(variant); VariantData* data = getData(variant); if (!pool || !data) return false; MemoryPoolPrint print(pool); value.printTo(print); if (print.overflowed()) { pool->markAsOverflowed(); data->setNull(); return false; } data->setOwnedString(print.c_str()); return true; } #endif } // namespace ARDUINOJSON_NAMESPACE