Added support for custom reader classes

This commit is contained in:
Benoit Blanchon
2019-10-25 11:39:04 +02:00
parent d4f819f1f0
commit 3a169df0a5
17 changed files with 261 additions and 189 deletions

View File

@ -1,65 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
#include <ArduinoJson/Deserialization/IteratorReader.hpp>
#include <ArduinoJson/Namespace.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> {};
class UnsafeCharPointerReader {
const char* _ptr;
public:
explicit UnsafeCharPointerReader(const char* ptr)
: _ptr(ptr ? ptr : reinterpret_cast<const char*>("")) {}
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;
}
};
class SafeCharPointerReader : public IteratorReader<const char*> {
public:
explicit SafeCharPointerReader(const char* ptr, size_t len)
: IteratorReader<const char*>(ptr, ptr + len) {}
};
template <typename TChar>
inline typename enable_if<IsCharOrVoid<TChar>::value,
UnsafeCharPointerReader>::type
makeReader(TChar* input) {
return UnsafeCharPointerReader(reinterpret_cast<const char*>(input));
}
template <typename TChar>
inline
typename enable_if<IsCharOrVoid<TChar>::value, SafeCharPointerReader>::type
makeReader(TChar* input, size_t n) {
return SafeCharPointerReader(reinterpret_cast<const char*>(input), n);
}
#if ARDUINOJSON_ENABLE_ARDUINO_STRING
inline SafeCharPointerReader makeReader(const ::String& input) {
return SafeCharPointerReader(input.c_str(), input.length());
}
#endif
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -0,0 +1,55 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// 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>
#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

View File

@ -4,19 +4,17 @@
#pragma once
#include <ArduinoJson/Namespace.hpp>
#if ARDUINOJSON_ENABLE_ARDUINO_STREAM
#include <Stream.h>
namespace ARDUINOJSON_NAMESPACE {
struct ArduinoStreamReader {
template <typename TSource>
struct Reader<TSource,
typename enable_if<is_base_of<Stream, TSource>::value>::type> {
Stream& _stream;
public:
explicit ArduinoStreamReader(Stream& stream) : _stream(stream) {}
explicit Reader(Stream& stream) : _stream(stream) {}
int read() {
// don't use _stream.read() as it ignores the timeout
@ -29,9 +27,4 @@ struct ArduinoStreamReader {
}
};
inline ArduinoStreamReader makeReader(Stream& input) {
return ArduinoStreamReader(input);
}
} // namespace ARDUINOJSON_NAMESPACE
#endif

View File

@ -0,0 +1,17 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// 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

View File

@ -4,16 +4,14 @@
#pragma once
#include <ArduinoJson/Namespace.hpp>
#if ARDUINOJSON_ENABLE_PROGMEM
namespace ARDUINOJSON_NAMESPACE {
class UnsafeFlashStringReader {
template <>
struct Reader<const __FlashStringHelper*, void> {
const char* _ptr;
public:
explicit UnsafeFlashStringReader(const __FlashStringHelper* ptr)
explicit Reader(const __FlashStringHelper* ptr)
: _ptr(reinterpret_cast<const char*>(ptr)) {}
int read() {
@ -27,12 +25,13 @@ class UnsafeFlashStringReader {
}
};
class SafeFlashStringReader {
template <>
struct BoundedReader<const __FlashStringHelper*, void> {
const char* _ptr;
const char* _end;
public:
explicit SafeFlashStringReader(const __FlashStringHelper* ptr, size_t size)
explicit BoundedReader(const __FlashStringHelper* ptr, size_t size)
: _ptr(reinterpret_cast<const char*>(ptr)), _end(_ptr + size) {}
int read() {
@ -50,15 +49,4 @@ class SafeFlashStringReader {
return length;
}
};
inline UnsafeFlashStringReader makeReader(const __FlashStringHelper* input) {
return UnsafeFlashStringReader(input);
}
inline SafeFlashStringReader makeReader(const __FlashStringHelper* input,
size_t size) {
return SafeFlashStringReader(input, size);
}
} // namespace ARDUINOJSON_NAMESPACE
#endif

View File

@ -4,8 +4,6 @@
#pragma once
#include <ArduinoJson/Namespace.hpp>
namespace ARDUINOJSON_NAMESPACE {
template <typename TIterator>
@ -30,10 +28,16 @@ class IteratorReader {
}
};
template <typename TInput>
inline IteratorReader<typename TInput::const_iterator> makeReader(
const TInput& input) {
return IteratorReader<typename TInput::const_iterator>(input.begin(),
input.end());
}
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

View File

@ -0,0 +1,50 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// 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

View File

@ -0,0 +1,29 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// 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

View File

@ -1,41 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
#include <ArduinoJson/Namespace.hpp>
#if ARDUINOJSON_ENABLE_STD_STREAM
#include <istream>
namespace ARDUINOJSON_NAMESPACE {
class StdStreamReader {
std::istream& _stream;
char _current;
public:
explicit StdStreamReader(std::istream& stream)
: _stream(stream), _current(0) {}
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:
StdStreamReader& operator=(const StdStreamReader&); // Visual Studio C4512
};
inline StdStreamReader makeReader(std::istream& input) {
return StdStreamReader(input);
}
} // namespace ARDUINOJSON_NAMESPACE
#endif

View File

@ -4,13 +4,9 @@
#pragma once
#include <ArduinoJson/Deserialization/ArduinoStreamReader.hpp>
#include <ArduinoJson/Deserialization/CharPointerReader.hpp>
#include <ArduinoJson/Deserialization/DeserializationError.hpp>
#include <ArduinoJson/Deserialization/FlashStringReader.hpp>
#include <ArduinoJson/Deserialization/IteratorReader.hpp>
#include <ArduinoJson/Deserialization/NestingLimit.hpp>
#include <ArduinoJson/Deserialization/StdStreamReader.hpp>
#include <ArduinoJson/Deserialization/Reader.hpp>
#include <ArduinoJson/StringStorage/StringStorage.hpp>
namespace ARDUINOJSON_NAMESPACE {
@ -25,26 +21,17 @@ TDeserializer<TReader, TWriter> makeDeserializer(MemoryPool &pool,
// deserialize(JsonDocument&, const std::string&);
// deserialize(JsonDocument&, const String&);
// deserialize(JsonDocument&, char*);
// deserialize(JsonDocument&, const char*);
// deserialize(JsonDocument&, const __FlashStringHelper*);
template <template <typename, typename> class TDeserializer, typename TString>
typename enable_if<!is_array<TString>::value, DeserializationError>::type
deserialize(JsonDocument &doc, const TString &input,
NestingLimit nestingLimit) {
Reader<TString> reader(input);
doc.clear();
return makeDeserializer<TDeserializer>(
doc.memoryPool(), makeReader(input),
makeStringStorage(doc.memoryPool(), input), nestingLimit.value)
.parse(doc.data());
}
//
// deserialize(JsonDocument&, char*);
// deserialize(JsonDocument&, const char*);
// deserialize(JsonDocument&, const __FlashStringHelper*);
template <template <typename, typename> class TDeserializer, typename TChar>
DeserializationError deserialize(JsonDocument &doc, TChar *input,
NestingLimit nestingLimit) {
doc.clear();
return makeDeserializer<TDeserializer>(
doc.memoryPool(), makeReader(input),
doc.memoryPool(), reader,
makeStringStorage(doc.memoryPool(), input), nestingLimit.value)
.parse(doc.data());
}
@ -55,9 +42,10 @@ DeserializationError deserialize(JsonDocument &doc, TChar *input,
template <template <typename, typename> class TDeserializer, typename TChar>
DeserializationError deserialize(JsonDocument &doc, TChar *input,
size_t inputSize, NestingLimit nestingLimit) {
BoundedReader<TChar *> reader(input, inputSize);
doc.clear();
return makeDeserializer<TDeserializer>(
doc.memoryPool(), makeReader(input, inputSize),
doc.memoryPool(), reader,
makeStringStorage(doc.memoryPool(), input), nestingLimit.value)
.parse(doc.data());
}
@ -67,9 +55,10 @@ DeserializationError deserialize(JsonDocument &doc, TChar *input,
template <template <typename, typename> class TDeserializer, typename TStream>
DeserializationError deserialize(JsonDocument &doc, TStream &input,
NestingLimit nestingLimit) {
Reader<TStream> reader(input);
doc.clear();
return makeDeserializer<TDeserializer>(
doc.memoryPool(), makeReader(input),
doc.memoryPool(), reader,
makeStringStorage(doc.memoryPool(), input), nestingLimit.value)
.parse(doc.data());
}