diff options
Diffstat (limited to 'include/lib/ArduinoJson/Deserialization')
12 files changed, 601 insertions, 0 deletions
diff --git a/include/lib/ArduinoJson/Deserialization/DeserializationError.hpp b/include/lib/ArduinoJson/Deserialization/DeserializationError.hpp new file mode 100644 index 0000000..7b61711 --- /dev/null +++ b/include/lib/ArduinoJson/Deserialization/DeserializationError.hpp @@ -0,0 +1,122 @@ +// ArduinoJson - https://arduinojson.org +// Copyright Benoit Blanchon 2014-2021 +// MIT License + +#pragma once + +#include <ArduinoJson/Namespace.hpp> +#include <ArduinoJson/Polyfills/preprocessor.hpp> +#include <ArduinoJson/Polyfills/static_array.hpp> + +#if ARDUINOJSON_ENABLE_STD_STREAM +#include <ostream> +#endif + +namespace ARDUINOJSON_NAMESPACE { + +class DeserializationError { + // safe bool idiom + typedef void (DeserializationError::*bool_type)() const; + void safeBoolHelper() const {} + + public: + enum Code { + Ok, + EmptyInput, + IncompleteInput, + InvalidInput, + NoMemory, + TooDeep + }; + + DeserializationError() {} + DeserializationError(Code c) : _code(c) {} + + // Compare with DeserializationError + friend bool operator==(const DeserializationError& lhs, + const DeserializationError& rhs) { + return lhs._code == rhs._code; + } + friend bool operator!=(const DeserializationError& lhs, + const DeserializationError& rhs) { + return lhs._code != rhs._code; + } + + // Compare with Code + friend bool operator==(const DeserializationError& lhs, Code rhs) { + return lhs._code == rhs; + } + friend bool operator==(Code lhs, const DeserializationError& rhs) { + return lhs == rhs._code; + } + friend bool operator!=(const DeserializationError& lhs, Code rhs) { + return lhs._code != rhs; + } + friend bool operator!=(Code lhs, const DeserializationError& rhs) { + return lhs != rhs._code; + } + + // Behaves like a bool + operator bool_type() const { + return _code != Ok ? &DeserializationError::safeBoolHelper : 0; + } + friend bool operator==(bool value, const DeserializationError& err) { + return static_cast<bool>(err) == value; + } + friend bool operator==(const DeserializationError& err, bool value) { + return static_cast<bool>(err) == value; + } + friend bool operator!=(bool value, const DeserializationError& err) { + return static_cast<bool>(err) != value; + } + friend bool operator!=(const DeserializationError& err, bool value) { + return static_cast<bool>(err) != value; + } + + // Returns internal enum, useful for switch statement + Code code() const { + return _code; + } + + const char* c_str() const { + static const char* messages[] = { + "Ok", "EmptyInput", "IncompleteInput", + "InvalidInput", "NoMemory", "TooDeep"}; + ARDUINOJSON_ASSERT(static_cast<size_t>(_code) < + sizeof(messages) / sizeof(messages[0])); + return messages[_code]; + } + +#if ARDUINOJSON_ENABLE_PROGMEM + const __FlashStringHelper* f_str() const { + ARDUINOJSON_DEFINE_STATIC_ARRAY(char, s0, "Ok"); + ARDUINOJSON_DEFINE_STATIC_ARRAY(char, s1, "EmptyInput"); + ARDUINOJSON_DEFINE_STATIC_ARRAY(char, s2, "IncompleteInput"); + ARDUINOJSON_DEFINE_STATIC_ARRAY(char, s3, "InvalidInput"); + ARDUINOJSON_DEFINE_STATIC_ARRAY(char, s4, "NoMemory"); + ARDUINOJSON_DEFINE_STATIC_ARRAY(char, s5, "TooDeep"); + ARDUINOJSON_DEFINE_STATIC_ARRAY( + const char*, messages, ARDUINOJSON_EXPAND6({s0, s1, s2, s3, s4, s5})); + return ARDUINOJSON_READ_STATIC_ARRAY(const __FlashStringHelper*, messages, + _code); + } +#endif + + private: + Code _code; +}; + +#if ARDUINOJSON_ENABLE_STD_STREAM +inline std::ostream& operator<<(std::ostream& s, + const DeserializationError& e) { + s << e.c_str(); + return s; +} + +inline std::ostream& operator<<(std::ostream& s, DeserializationError::Code c) { + s << DeserializationError(c).c_str(); + return s; +} +#endif + +} // namespace ARDUINOJSON_NAMESPACE diff --git a/include/lib/ArduinoJson/Deserialization/Filter.hpp b/include/lib/ArduinoJson/Deserialization/Filter.hpp new file mode 100644 index 0000000..7ea3078 --- /dev/null +++ b/include/lib/ArduinoJson/Deserialization/Filter.hpp @@ -0,0 +1,66 @@ +// ArduinoJson - https://arduinojson.org +// Copyright Benoit Blanchon 2014-2021 +// MIT License + +#pragma once + +#include <ArduinoJson/Namespace.hpp> + +namespace ARDUINOJSON_NAMESPACE { + +class Filter { + public: + explicit Filter(VariantConstRef v) : _variant(v) {} + + bool allow() const { + return _variant; + } + + bool allowArray() const { + return _variant == true || _variant.is<ArrayConstRef>(); + } + + bool allowObject() const { + return _variant == true || _variant.is<ObjectConstRef>(); + } + + bool allowValue() const { + return _variant == true; + } + + template <typename TKey> + Filter operator[](const TKey& key) const { + if (_variant == true) // "true" means "allow recursively" + return *this; + else + return Filter(_variant[key] | _variant["*"]); + } + + private: + VariantConstRef _variant; +}; + +struct AllowAllFilter { + bool allow() const { + return true; + } + + bool allowArray() const { + return true; + } + + bool allowObject() const { + return true; + } + + bool allowValue() const { + return true; + } + + template <typename TKey> + AllowAllFilter operator[](const TKey&) const { + return AllowAllFilter(); + } +}; + +} // namespace ARDUINOJSON_NAMESPACE diff --git a/include/lib/ArduinoJson/Deserialization/NestingLimit.hpp b/include/lib/ArduinoJson/Deserialization/NestingLimit.hpp new file mode 100644 index 0000000..06964b4 --- /dev/null +++ b/include/lib/ArduinoJson/Deserialization/NestingLimit.hpp @@ -0,0 +1,29 @@ +// ArduinoJson - https://arduinojson.org +// Copyright Benoit Blanchon 2014-2021 +// MIT License + +#pragma once + +#include <ArduinoJson/Namespace.hpp> +#include <ArduinoJson/Polyfills/assert.hpp> + +namespace ARDUINOJSON_NAMESPACE { + +class NestingLimit { + public: + NestingLimit() : _value(ARDUINOJSON_DEFAULT_NESTING_LIMIT) {} + explicit NestingLimit(uint8_t n) : _value(n) {} + + NestingLimit decrement() const { + ARDUINOJSON_ASSERT(_value > 0); + return NestingLimit(static_cast<uint8_t>(_value - 1)); + } + + bool reached() const { + return _value == 0; + } + + private: + uint8_t _value; +}; +} // namespace ARDUINOJSON_NAMESPACE diff --git a/include/lib/ArduinoJson/Deserialization/Reader.hpp b/include/lib/ArduinoJson/Deserialization/Reader.hpp new file mode 100644 index 0000000..e965c82 --- /dev/null +++ b/include/lib/ArduinoJson/Deserialization/Reader.hpp @@ -0,0 +1,56 @@ +// ArduinoJson - https://arduinojson.org +// Copyright Benoit Blanchon 2014-2021 +// MIT License + +#pragma once + +#include <ArduinoJson/Namespace.hpp> + +#include <stdlib.h> // for size_t + +namespace ARDUINOJSON_NAMESPACE { + +// The default reader is a simple wrapper for Readers that are not copiable +template <typename TSource, typename Enable = void> +struct Reader { + public: + Reader(TSource& source) : _source(&source) {} + + int read() { + return _source->read(); + } + + size_t readBytes(char* buffer, size_t length) { + return _source->readBytes(buffer, length); + } + + private: + TSource* _source; +}; + +template <typename TSource, typename Enable = void> +struct BoundedReader { + // no default implementation because we need to pass the size to the + // constructor +}; +} // namespace ARDUINOJSON_NAMESPACE + +#include <ArduinoJson/Deserialization/Readers/IteratorReader.hpp> +#include <ArduinoJson/Deserialization/Readers/RamReader.hpp> +#include <ArduinoJson/Deserialization/Readers/VariantReader.hpp> + +#if ARDUINOJSON_ENABLE_ARDUINO_STREAM +#include <ArduinoJson/Deserialization/Readers/ArduinoStreamReader.hpp> +#endif + +#if ARDUINOJSON_ENABLE_ARDUINO_STRING +#include <ArduinoJson/Deserialization/Readers/ArduinoStringReader.hpp> +#endif + +#if ARDUINOJSON_ENABLE_PROGMEM +#include <ArduinoJson/Deserialization/Readers/FlashReader.hpp> +#endif + +#if ARDUINOJSON_ENABLE_STD_STREAM +#include <ArduinoJson/Deserialization/Readers/StdStreamReader.hpp> +#endif diff --git a/include/lib/ArduinoJson/Deserialization/Readers/ArduinoStreamReader.hpp b/include/lib/ArduinoJson/Deserialization/Readers/ArduinoStreamReader.hpp new file mode 100644 index 0000000..724638f --- /dev/null +++ b/include/lib/ArduinoJson/Deserialization/Readers/ArduinoStreamReader.hpp @@ -0,0 +1,31 @@ +// ArduinoJson - https://arduinojson.org +// Copyright Benoit Blanchon 2014-2021 +// MIT License + +#pragma once + +#include <Arduino.h> + +namespace ARDUINOJSON_NAMESPACE { + +template <typename TSource> +struct Reader<TSource, + typename enable_if<is_base_of<Stream, TSource>::value>::type> { + public: + explicit Reader(Stream& stream) : _stream(&stream) {} + + int read() { + // don't use _stream.read() as it ignores the timeout + char c; + return _stream->readBytes(&c, 1) ? static_cast<unsigned char>(c) : -1; + } + + size_t readBytes(char* buffer, size_t length) { + return _stream->readBytes(buffer, length); + } + + private: + Stream* _stream; +}; + +} // namespace ARDUINOJSON_NAMESPACE diff --git a/include/lib/ArduinoJson/Deserialization/Readers/ArduinoStringReader.hpp b/include/lib/ArduinoJson/Deserialization/Readers/ArduinoStringReader.hpp new file mode 100644 index 0000000..71571d4 --- /dev/null +++ b/include/lib/ArduinoJson/Deserialization/Readers/ArduinoStringReader.hpp @@ -0,0 +1,17 @@ +// ArduinoJson - https://arduinojson.org +// Copyright Benoit Blanchon 2014-2021 +// MIT License + +#pragma once + +namespace ARDUINOJSON_NAMESPACE { + +template <typename TSource> +struct Reader<TSource, + typename enable_if<is_base_of< ::String, TSource>::value>::type> + : BoundedReader<const char*> { + explicit Reader(const ::String& s) + : BoundedReader<const char*>(s.c_str(), s.length()) {} +}; + +} // namespace ARDUINOJSON_NAMESPACE diff --git a/include/lib/ArduinoJson/Deserialization/Readers/FlashReader.hpp b/include/lib/ArduinoJson/Deserialization/Readers/FlashReader.hpp new file mode 100644 index 0000000..7eca134 --- /dev/null +++ b/include/lib/ArduinoJson/Deserialization/Readers/FlashReader.hpp @@ -0,0 +1,53 @@ +// ArduinoJson - https://arduinojson.org +// Copyright Benoit Blanchon 2014-2021 +// MIT License + +#pragma once + +namespace ARDUINOJSON_NAMESPACE { + +template <> +struct Reader<const __FlashStringHelper*, void> { + const char* _ptr; + + public: + explicit Reader(const __FlashStringHelper* ptr) + : _ptr(reinterpret_cast<const char*>(ptr)) {} + + int read() { + return pgm_read_byte(_ptr++); + } + + size_t readBytes(char* buffer, size_t length) { + memcpy_P(buffer, _ptr, length); + _ptr += length; + return length; + } +}; + +template <> +struct BoundedReader<const __FlashStringHelper*, void> { + const char* _ptr; + const char* _end; + + public: + explicit BoundedReader(const __FlashStringHelper* ptr, size_t size) + : _ptr(reinterpret_cast<const char*>(ptr)), _end(_ptr + size) {} + + int read() { + if (_ptr < _end) + return pgm_read_byte(_ptr++); + else + return -1; + } + + size_t readBytes(char* buffer, size_t length) { + size_t available = static_cast<size_t>(_end - _ptr); + if (available < length) + length = available; + memcpy_P(buffer, _ptr, length); + _ptr += length; + return length; + } +}; +} // namespace ARDUINOJSON_NAMESPACE diff --git a/include/lib/ArduinoJson/Deserialization/Readers/IteratorReader.hpp b/include/lib/ArduinoJson/Deserialization/Readers/IteratorReader.hpp new file mode 100644 index 0000000..37c3c31 --- /dev/null +++ b/include/lib/ArduinoJson/Deserialization/Readers/IteratorReader.hpp @@ -0,0 +1,43 @@ +// ArduinoJson - https://arduinojson.org +// Copyright Benoit Blanchon 2014-2021 +// MIT License + +#pragma once + +namespace ARDUINOJSON_NAMESPACE { + +template <typename TIterator> +class IteratorReader { + TIterator _ptr, _end; + + public: + explicit IteratorReader(TIterator begin, TIterator end) + : _ptr(begin), _end(end) {} + + int read() { + if (_ptr < _end) + return static_cast<unsigned char>(*_ptr++); + else + return -1; + } + + size_t readBytes(char* buffer, size_t length) { + size_t i = 0; + while (i < length && _ptr < _end) buffer[i++] = *_ptr++; + return i; + } +}; + +template <typename T> +struct void_ { + typedef void type; +}; + +template <typename TSource> +struct Reader<TSource, typename void_<typename TSource::const_iterator>::type> + : IteratorReader<typename TSource::const_iterator> { + explicit Reader(const TSource& source) + : IteratorReader<typename TSource::const_iterator>(source.begin(), + source.end()) {} +}; +} // namespace ARDUINOJSON_NAMESPACE diff --git a/include/lib/ArduinoJson/Deserialization/Readers/RamReader.hpp b/include/lib/ArduinoJson/Deserialization/Readers/RamReader.hpp new file mode 100644 index 0000000..67cf682 --- /dev/null +++ b/include/lib/ArduinoJson/Deserialization/Readers/RamReader.hpp @@ -0,0 +1,50 @@ +// ArduinoJson - https://arduinojson.org +// Copyright Benoit Blanchon 2014-2021 +// MIT License + +#pragma once + +#include <ArduinoJson/Polyfills/type_traits.hpp> + +namespace ARDUINOJSON_NAMESPACE { + +template <typename T> +struct IsCharOrVoid { + static const bool value = + is_same<T, void>::value || is_same<T, char>::value || + is_same<T, unsigned char>::value || is_same<T, signed char>::value; +}; + +template <typename T> +struct IsCharOrVoid<const T> : IsCharOrVoid<T> {}; + +template <typename TSource> +struct Reader<TSource*, + typename enable_if<IsCharOrVoid<TSource>::value>::type> { + const char* _ptr; + + public: + explicit Reader(const void* ptr) + : _ptr(ptr ? reinterpret_cast<const char*>(ptr) : "") {} + + int read() { + return static_cast<unsigned char>(*_ptr++); + } + + size_t readBytes(char* buffer, size_t length) { + for (size_t i = 0; i < length; i++) buffer[i] = *_ptr++; + return length; + } +}; + +template <typename TSource> +struct BoundedReader<TSource*, + typename enable_if<IsCharOrVoid<TSource>::value>::type> + : public IteratorReader<const char*> { + public: + explicit BoundedReader(const void* ptr, size_t len) + : IteratorReader<const char*>(reinterpret_cast<const char*>(ptr), + reinterpret_cast<const char*>(ptr) + len) {} +}; + +} // namespace ARDUINOJSON_NAMESPACE diff --git a/include/lib/ArduinoJson/Deserialization/Readers/StdStreamReader.hpp b/include/lib/ArduinoJson/Deserialization/Readers/StdStreamReader.hpp new file mode 100644 index 0000000..eebaa2c --- /dev/null +++ b/include/lib/ArduinoJson/Deserialization/Readers/StdStreamReader.hpp @@ -0,0 +1,29 @@ +// ArduinoJson - https://arduinojson.org +// Copyright Benoit Blanchon 2014-2021 +// MIT License + +#pragma once + +#include <istream> + +namespace ARDUINOJSON_NAMESPACE { + +template <typename TSource> +struct Reader<TSource, typename enable_if< + is_base_of<std::istream, TSource>::value>::type> { + public: + explicit Reader(std::istream& stream) : _stream(&stream) {} + + int read() { + return _stream->get(); + } + + size_t readBytes(char* buffer, size_t length) { + _stream->read(buffer, static_cast<std::streamsize>(length)); + return static_cast<size_t>(_stream->gcount()); + } + + private: + std::istream* _stream; +}; +} // namespace ARDUINOJSON_NAMESPACE diff --git a/include/lib/ArduinoJson/Deserialization/Readers/VariantReader.hpp b/include/lib/ArduinoJson/Deserialization/Readers/VariantReader.hpp new file mode 100644 index 0000000..e56e262 --- /dev/null +++ b/include/lib/ArduinoJson/Deserialization/Readers/VariantReader.hpp @@ -0,0 +1,34 @@ +// ArduinoJson - https://arduinojson.org +// Copyright Benoit Blanchon 2014-2021 +// MIT License + +#pragma once + +#include <ArduinoJson/Object/MemberProxy.hpp> +#include <ArduinoJson/Variant/VariantRef.hpp> + +namespace ARDUINOJSON_NAMESPACE { + +template <typename TArray> +struct Reader<ElementProxy<TArray>, void> : Reader<char*, void> { + explicit Reader(const ElementProxy<TArray>& x) + : Reader<char*, void>(x.template as<const char*>()) {} +}; + +template <typename TObject, typename TStringRef> +struct Reader<MemberProxy<TObject, TStringRef>, void> : Reader<char*, void> { + explicit Reader(const MemberProxy<TObject, TStringRef>& x) + : Reader<char*, void>(x.template as<const char*>()) {} +}; + +template <> +struct Reader<VariantRef, void> : Reader<char*, void> { + explicit Reader(VariantRef x) : Reader<char*, void>(x.as<const char*>()) {} +}; + +template <> +struct Reader<VariantConstRef, void> : Reader<char*, void> { + explicit Reader(VariantConstRef x) + : Reader<char*, void>(x.as<const char*>()) {} +}; +} // namespace ARDUINOJSON_NAMESPACE diff --git a/include/lib/ArduinoJson/Deserialization/deserialize.hpp b/include/lib/ArduinoJson/Deserialization/deserialize.hpp new file mode 100644 index 0000000..2329542 --- /dev/null +++ b/include/lib/ArduinoJson/Deserialization/deserialize.hpp @@ -0,0 +1,71 @@ +// ArduinoJson - https://arduinojson.org +// Copyright Benoit Blanchon 2014-2021 +// MIT License + +#pragma once + +#include <ArduinoJson/Deserialization/DeserializationError.hpp> +#include <ArduinoJson/Deserialization/Filter.hpp> +#include <ArduinoJson/Deserialization/NestingLimit.hpp> +#include <ArduinoJson/Deserialization/Reader.hpp> +#include <ArduinoJson/StringStorage/StringStorage.hpp> + +namespace ARDUINOJSON_NAMESPACE { + +template <template <typename, typename> class TDeserializer, typename TReader, + typename TWriter> +TDeserializer<TReader, TWriter> makeDeserializer(MemoryPool &pool, + TReader reader, + TWriter writer) { + return TDeserializer<TReader, TWriter>(pool, reader, writer); +} + +// deserialize(JsonDocument&, const std::string&, NestingLimit, Filter); +// deserialize(JsonDocument&, const String&, NestingLimit, Filter); +// deserialize(JsonDocument&, char*, NestingLimit, Filter); +// deserialize(JsonDocument&, const char*, NestingLimit, Filter); +// deserialize(JsonDocument&, const __FlashStringHelper*, NestingLimit, Filter); +template <template <typename, typename> class TDeserializer, typename TString, + typename TFilter> +typename enable_if<!is_array<TString>::value, DeserializationError>::type +deserialize(JsonDocument &doc, const TString &input, NestingLimit nestingLimit, + TFilter filter) { + Reader<TString> reader(input); + doc.clear(); + return makeDeserializer<TDeserializer>( + doc.memoryPool(), reader, + makeStringStorage(input, doc.memoryPool())) + .parse(doc.data(), filter, nestingLimit); +} +// +// deserialize(JsonDocument&, char*, size_t, NestingLimit, Filter); +// deserialize(JsonDocument&, const char*, size_t, NestingLimit, Filter); +// deserialize(JsonDocument&, const __FlashStringHelper*, size_t, NL, Filter); +template <template <typename, typename> class TDeserializer, typename TChar, + typename TFilter> +DeserializationError deserialize(JsonDocument &doc, TChar *input, + size_t inputSize, NestingLimit nestingLimit, + TFilter filter) { + BoundedReader<TChar *> reader(input, inputSize); + doc.clear(); + return makeDeserializer<TDeserializer>( + doc.memoryPool(), reader, + makeStringStorage(input, doc.memoryPool())) + .parse(doc.data(), filter, nestingLimit); +} +// +// deserialize(JsonDocument&, std::istream&, NestingLimit, Filter); +// deserialize(JsonDocument&, Stream&, NestingLimit, Filter); +template <template <typename, typename> class TDeserializer, typename TStream, + typename TFilter> +DeserializationError deserialize(JsonDocument &doc, TStream &input, + NestingLimit nestingLimit, TFilter filter) { + Reader<TStream> reader(input); + doc.clear(); + return makeDeserializer<TDeserializer>( + doc.memoryPool(), reader, + makeStringStorage(input, doc.memoryPool())) + .parse(doc.data(), filter, nestingLimit); +} + +} // namespace ARDUINOJSON_NAMESPACE |