forked from bblanchon/ArduinoJson
Added support for custom reader classes
This commit is contained in:
@ -4,7 +4,7 @@ ArduinoJson: change log
|
|||||||
HEAD
|
HEAD
|
||||||
----
|
----
|
||||||
|
|
||||||
* Added support for custom writer classes (issue #1088)
|
* Added support for custom writer/reader classes (issue #1088)
|
||||||
* Added conversion from `JsonArray` and `JsonObject` to `bool`, to be consistent with `JsonVariant`
|
* Added conversion from `JsonArray` and `JsonObject` to `bool`, to be consistent with `JsonVariant`
|
||||||
* Fixed `deserializeJson()` when input contains duplicate keys (issue #1095)
|
* Fixed `deserializeJson()` when input contains duplicate keys (issue #1095)
|
||||||
* Improved `deserializeMsgPack()` speed by reading several bytes at once
|
* Improved `deserializeMsgPack()` speed by reading several bytes at once
|
||||||
|
@ -72,6 +72,7 @@ if(MSVC)
|
|||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
include_directories(Helpers)
|
||||||
add_subdirectory(ElementProxy)
|
add_subdirectory(ElementProxy)
|
||||||
add_subdirectory(IntegrationTests)
|
add_subdirectory(IntegrationTests)
|
||||||
add_subdirectory(JsonArray)
|
add_subdirectory(JsonArray)
|
||||||
|
26
extras/tests/Helpers/CustomReader.hpp
Normal file
26
extras/tests/Helpers/CustomReader.hpp
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
// ArduinoJson - arduinojson.org
|
||||||
|
// Copyright Benoit Blanchon 2014-2019
|
||||||
|
// MIT License
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
class CustomReader {
|
||||||
|
std::stringstream _stream;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CustomReader(const char* input) : _stream(input) {}
|
||||||
|
|
||||||
|
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:
|
||||||
|
CustomReader(const CustomReader&);
|
||||||
|
};
|
@ -6,6 +6,8 @@
|
|||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
|
#include "CustomReader.hpp"
|
||||||
|
|
||||||
TEST_CASE("deserializeJson(const std::string&)") {
|
TEST_CASE("deserializeJson(const std::string&)") {
|
||||||
DynamicJsonDocument doc(4096);
|
DynamicJsonDocument doc(4096);
|
||||||
|
|
||||||
@ -113,3 +115,14 @@ TEST_CASE("deserializeJson(VLA)") {
|
|||||||
REQUIRE(err == DeserializationError::Ok);
|
REQUIRE(err == DeserializationError::Ok);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
TEST_CASE("deserializeJson(CustomReader)") {
|
||||||
|
DynamicJsonDocument doc(4096);
|
||||||
|
CustomReader reader("[4,2]");
|
||||||
|
DeserializationError err = deserializeJson(doc, reader);
|
||||||
|
|
||||||
|
REQUIRE(err == DeserializationError::Ok);
|
||||||
|
REQUIRE(doc.size() == 2);
|
||||||
|
REQUIRE(doc[0] == 4);
|
||||||
|
REQUIRE(doc[1] == 2);
|
||||||
|
}
|
||||||
|
@ -2,15 +2,15 @@
|
|||||||
// Copyright Benoit Blanchon 2014-2019
|
// Copyright Benoit Blanchon 2014-2019
|
||||||
// MIT License
|
// MIT License
|
||||||
|
|
||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson/Deserialization/Reader.hpp>
|
||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
|
|
||||||
using namespace ARDUINOJSON_NAMESPACE;
|
using namespace ARDUINOJSON_NAMESPACE;
|
||||||
|
|
||||||
TEST_CASE("StdStreamReader") {
|
TEST_CASE("Reader<std::istringstream>") {
|
||||||
SECTION("read()") {
|
SECTION("read()") {
|
||||||
std::istringstream src("\x01\xFF");
|
std::istringstream src("\x01\xFF");
|
||||||
StdStreamReader reader(src);
|
Reader<std::istringstream> reader(src);
|
||||||
|
|
||||||
REQUIRE(reader.read() == 0x01);
|
REQUIRE(reader.read() == 0x01);
|
||||||
REQUIRE(reader.read() == 0xFF);
|
REQUIRE(reader.read() == 0xFF);
|
||||||
@ -19,7 +19,7 @@ TEST_CASE("StdStreamReader") {
|
|||||||
|
|
||||||
SECTION("readBytes() all at once") {
|
SECTION("readBytes() all at once") {
|
||||||
std::istringstream src("ABC");
|
std::istringstream src("ABC");
|
||||||
StdStreamReader reader(src);
|
Reader<std::istringstream> reader(src);
|
||||||
|
|
||||||
char buffer[8] = "abcd";
|
char buffer[8] = "abcd";
|
||||||
REQUIRE(reader.readBytes(buffer, 4) == 3);
|
REQUIRE(reader.readBytes(buffer, 4) == 3);
|
||||||
@ -32,7 +32,7 @@ TEST_CASE("StdStreamReader") {
|
|||||||
|
|
||||||
SECTION("readBytes() in two parts") {
|
SECTION("readBytes() in two parts") {
|
||||||
std::istringstream src("ABCDEF");
|
std::istringstream src("ABCDEF");
|
||||||
StdStreamReader reader(src);
|
Reader<std::istringstream> reader(src);
|
||||||
|
|
||||||
char buffer[12] = "abcdefg";
|
char buffer[12] = "abcdefg";
|
||||||
REQUIRE(reader.readBytes(buffer, 4) == 4);
|
REQUIRE(reader.readBytes(buffer, 4) == 4);
|
||||||
@ -48,9 +48,9 @@ TEST_CASE("StdStreamReader") {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("SafeCharPointerReader") {
|
TEST_CASE("BoundedReader<const char*>") {
|
||||||
SECTION("read") {
|
SECTION("read") {
|
||||||
SafeCharPointerReader reader("\x01\xFF", 2);
|
BoundedReader<const char*> reader("\x01\xFF", 2);
|
||||||
REQUIRE(reader.read() == 0x01);
|
REQUIRE(reader.read() == 0x01);
|
||||||
REQUIRE(reader.read() == 0xFF);
|
REQUIRE(reader.read() == 0xFF);
|
||||||
REQUIRE(reader.read() == -1);
|
REQUIRE(reader.read() == -1);
|
||||||
@ -58,7 +58,7 @@ TEST_CASE("SafeCharPointerReader") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SECTION("readBytes() all at once") {
|
SECTION("readBytes() all at once") {
|
||||||
SafeCharPointerReader reader("ABCD", 3);
|
BoundedReader<const char*> reader("ABCD", 3);
|
||||||
|
|
||||||
char buffer[8] = "abcd";
|
char buffer[8] = "abcd";
|
||||||
REQUIRE(reader.readBytes(buffer, 4) == 3);
|
REQUIRE(reader.readBytes(buffer, 4) == 3);
|
||||||
@ -70,7 +70,7 @@ TEST_CASE("SafeCharPointerReader") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SECTION("readBytes() in two parts") {
|
SECTION("readBytes() in two parts") {
|
||||||
SafeCharPointerReader reader("ABCDEF", 6);
|
BoundedReader<const char*> reader("ABCDEF", 6);
|
||||||
|
|
||||||
char buffer[8] = "abcdefg";
|
char buffer[8] = "abcdefg";
|
||||||
REQUIRE(reader.readBytes(buffer, 4) == 4);
|
REQUIRE(reader.readBytes(buffer, 4) == 4);
|
||||||
@ -86,9 +86,9 @@ TEST_CASE("SafeCharPointerReader") {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("UnsafeCharPointerReader") {
|
TEST_CASE("Reader<const char*>") {
|
||||||
SECTION("read()") {
|
SECTION("read()") {
|
||||||
UnsafeCharPointerReader reader("\x01\xFF\x00\x12");
|
Reader<const char*> reader("\x01\xFF\x00\x12");
|
||||||
REQUIRE(reader.read() == 0x01);
|
REQUIRE(reader.read() == 0x01);
|
||||||
REQUIRE(reader.read() == 0xFF);
|
REQUIRE(reader.read() == 0xFF);
|
||||||
REQUIRE(reader.read() == 0);
|
REQUIRE(reader.read() == 0);
|
||||||
@ -96,7 +96,7 @@ TEST_CASE("UnsafeCharPointerReader") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SECTION("readBytes() all at once") {
|
SECTION("readBytes() all at once") {
|
||||||
UnsafeCharPointerReader reader("ABCD");
|
Reader<const char*> reader("ABCD");
|
||||||
|
|
||||||
char buffer[8] = "abcd";
|
char buffer[8] = "abcd";
|
||||||
REQUIRE(reader.readBytes(buffer, 3) == 3);
|
REQUIRE(reader.readBytes(buffer, 3) == 3);
|
||||||
@ -108,7 +108,7 @@ TEST_CASE("UnsafeCharPointerReader") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SECTION("readBytes() in two parts") {
|
SECTION("readBytes() in two parts") {
|
||||||
UnsafeCharPointerReader reader("ABCDEF");
|
Reader<const char*> reader("ABCDEF");
|
||||||
|
|
||||||
char buffer[8] = "abcdefg";
|
char buffer[8] = "abcdefg";
|
||||||
REQUIRE(reader.readBytes(buffer, 4) == 4);
|
REQUIRE(reader.readBytes(buffer, 4) == 4);
|
||||||
|
@ -86,11 +86,11 @@ TEST_CASE("memcpy_P") {
|
|||||||
CHECK(dst[3] == 0);
|
CHECK(dst[3] == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("SafeCharPointerReader") {
|
TEST_CASE("BoundedReader<const __FlashStringHelper*>") {
|
||||||
using ARDUINOJSON_NAMESPACE::SafeFlashStringReader;
|
using namespace ARDUINOJSON_NAMESPACE;
|
||||||
|
|
||||||
SECTION("read") {
|
SECTION("read") {
|
||||||
SafeFlashStringReader reader(F("\x01\xFF"), 2);
|
BoundedReader<const __FlashStringHelper*> reader(F("\x01\xFF"), 2);
|
||||||
REQUIRE(reader.read() == 0x01);
|
REQUIRE(reader.read() == 0x01);
|
||||||
REQUIRE(reader.read() == 0xFF);
|
REQUIRE(reader.read() == 0xFF);
|
||||||
REQUIRE(reader.read() == -1);
|
REQUIRE(reader.read() == -1);
|
||||||
@ -98,7 +98,7 @@ TEST_CASE("SafeCharPointerReader") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SECTION("readBytes() all at once") {
|
SECTION("readBytes() all at once") {
|
||||||
SafeFlashStringReader reader(F("ABCD"), 3);
|
BoundedReader<const __FlashStringHelper*> reader(F("ABCD"), 3);
|
||||||
|
|
||||||
char buffer[8] = "abcd";
|
char buffer[8] = "abcd";
|
||||||
REQUIRE(reader.readBytes(buffer, 4) == 3);
|
REQUIRE(reader.readBytes(buffer, 4) == 3);
|
||||||
@ -110,7 +110,7 @@ TEST_CASE("SafeCharPointerReader") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SECTION("readBytes() in two parts") {
|
SECTION("readBytes() in two parts") {
|
||||||
SafeFlashStringReader reader(F("ABCDEF"), 6);
|
BoundedReader<const __FlashStringHelper*> reader(F("ABCDEF"), 6);
|
||||||
|
|
||||||
char buffer[8] = "abcdefg";
|
char buffer[8] = "abcdefg";
|
||||||
REQUIRE(reader.readBytes(buffer, 4) == 4);
|
REQUIRE(reader.readBytes(buffer, 4) == 4);
|
||||||
@ -126,11 +126,11 @@ TEST_CASE("SafeCharPointerReader") {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("UnsafeFlashStringReader") {
|
TEST_CASE("Reader<const __FlashStringHelper*>") {
|
||||||
using ARDUINOJSON_NAMESPACE::UnsafeFlashStringReader;
|
using namespace ARDUINOJSON_NAMESPACE;
|
||||||
|
|
||||||
SECTION("read()") {
|
SECTION("read()") {
|
||||||
UnsafeFlashStringReader reader(F("\x01\xFF\x00\x12"));
|
Reader<const __FlashStringHelper*> reader(F("\x01\xFF\x00\x12"));
|
||||||
REQUIRE(reader.read() == 0x01);
|
REQUIRE(reader.read() == 0x01);
|
||||||
REQUIRE(reader.read() == 0xFF);
|
REQUIRE(reader.read() == 0xFF);
|
||||||
REQUIRE(reader.read() == 0);
|
REQUIRE(reader.read() == 0);
|
||||||
@ -138,7 +138,7 @@ TEST_CASE("UnsafeFlashStringReader") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SECTION("readBytes() all at once") {
|
SECTION("readBytes() all at once") {
|
||||||
UnsafeFlashStringReader reader(F("ABCD"));
|
Reader<const __FlashStringHelper*> reader(F("ABCD"));
|
||||||
|
|
||||||
char buffer[8] = "abcd";
|
char buffer[8] = "abcd";
|
||||||
REQUIRE(reader.readBytes(buffer, 3) == 3);
|
REQUIRE(reader.readBytes(buffer, 3) == 3);
|
||||||
@ -150,7 +150,7 @@ TEST_CASE("UnsafeFlashStringReader") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SECTION("readBytes() in two parts") {
|
SECTION("readBytes() in two parts") {
|
||||||
UnsafeFlashStringReader reader(F("ABCDEF"));
|
Reader<const __FlashStringHelper*> reader(F("ABCDEF"));
|
||||||
|
|
||||||
char buffer[8] = "abcdefg";
|
char buffer[8] = "abcdefg";
|
||||||
REQUIRE(reader.readBytes(buffer, 4) == 4);
|
REQUIRE(reader.readBytes(buffer, 4) == 4);
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
|
|
||||||
|
#include "CustomReader.hpp"
|
||||||
|
|
||||||
TEST_CASE("deserializeMsgPack(const std::string&)") {
|
TEST_CASE("deserializeMsgPack(const std::string&)") {
|
||||||
DynamicJsonDocument doc(4096);
|
DynamicJsonDocument doc(4096);
|
||||||
|
|
||||||
@ -80,3 +82,14 @@ TEST_CASE("deserializeMsgPack(VLA)") {
|
|||||||
REQUIRE(err == DeserializationError::Ok);
|
REQUIRE(err == DeserializationError::Ok);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
TEST_CASE("deserializeMsgPack(CustomReader)") {
|
||||||
|
DynamicJsonDocument doc(4096);
|
||||||
|
CustomReader reader("\x92\xA5Hello\xA5world");
|
||||||
|
DeserializationError err = deserializeMsgPack(doc, reader);
|
||||||
|
|
||||||
|
REQUIRE(err == DeserializationError::Ok);
|
||||||
|
REQUIRE(doc.size() == 2);
|
||||||
|
REQUIRE(doc[0] == "Hello");
|
||||||
|
REQUIRE(doc[1] == "world");
|
||||||
|
}
|
||||||
|
@ -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
|
|
55
src/ArduinoJson/Deserialization/Reader.hpp
Normal file
55
src/ArduinoJson/Deserialization/Reader.hpp
Normal 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
|
@ -4,19 +4,17 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <ArduinoJson/Namespace.hpp>
|
|
||||||
|
|
||||||
#if ARDUINOJSON_ENABLE_ARDUINO_STREAM
|
|
||||||
|
|
||||||
#include <Stream.h>
|
#include <Stream.h>
|
||||||
|
|
||||||
namespace ARDUINOJSON_NAMESPACE {
|
namespace ARDUINOJSON_NAMESPACE {
|
||||||
|
|
||||||
struct ArduinoStreamReader {
|
template <typename TSource>
|
||||||
|
struct Reader<TSource,
|
||||||
|
typename enable_if<is_base_of<Stream, TSource>::value>::type> {
|
||||||
Stream& _stream;
|
Stream& _stream;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit ArduinoStreamReader(Stream& stream) : _stream(stream) {}
|
explicit Reader(Stream& stream) : _stream(stream) {}
|
||||||
|
|
||||||
int read() {
|
int read() {
|
||||||
// don't use _stream.read() as it ignores the timeout
|
// 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
|
} // namespace ARDUINOJSON_NAMESPACE
|
||||||
|
|
||||||
#endif
|
|
@ -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
|
@ -4,16 +4,14 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <ArduinoJson/Namespace.hpp>
|
|
||||||
|
|
||||||
#if ARDUINOJSON_ENABLE_PROGMEM
|
|
||||||
|
|
||||||
namespace ARDUINOJSON_NAMESPACE {
|
namespace ARDUINOJSON_NAMESPACE {
|
||||||
class UnsafeFlashStringReader {
|
|
||||||
|
template <>
|
||||||
|
struct Reader<const __FlashStringHelper*, void> {
|
||||||
const char* _ptr;
|
const char* _ptr;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit UnsafeFlashStringReader(const __FlashStringHelper* ptr)
|
explicit Reader(const __FlashStringHelper* ptr)
|
||||||
: _ptr(reinterpret_cast<const char*>(ptr)) {}
|
: _ptr(reinterpret_cast<const char*>(ptr)) {}
|
||||||
|
|
||||||
int read() {
|
int read() {
|
||||||
@ -27,12 +25,13 @@ class UnsafeFlashStringReader {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class SafeFlashStringReader {
|
template <>
|
||||||
|
struct BoundedReader<const __FlashStringHelper*, void> {
|
||||||
const char* _ptr;
|
const char* _ptr;
|
||||||
const char* _end;
|
const char* _end;
|
||||||
|
|
||||||
public:
|
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) {}
|
: _ptr(reinterpret_cast<const char*>(ptr)), _end(_ptr + size) {}
|
||||||
|
|
||||||
int read() {
|
int read() {
|
||||||
@ -50,15 +49,4 @@ class SafeFlashStringReader {
|
|||||||
return length;
|
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
|
} // namespace ARDUINOJSON_NAMESPACE
|
||||||
|
|
||||||
#endif
|
|
@ -4,8 +4,6 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <ArduinoJson/Namespace.hpp>
|
|
||||||
|
|
||||||
namespace ARDUINOJSON_NAMESPACE {
|
namespace ARDUINOJSON_NAMESPACE {
|
||||||
|
|
||||||
template <typename TIterator>
|
template <typename TIterator>
|
||||||
@ -30,10 +28,16 @@ class IteratorReader {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename TInput>
|
template <typename T>
|
||||||
inline IteratorReader<typename TInput::const_iterator> makeReader(
|
struct void_ {
|
||||||
const TInput& input) {
|
typedef void type;
|
||||||
return IteratorReader<typename TInput::const_iterator>(input.begin(),
|
};
|
||||||
input.end());
|
|
||||||
}
|
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
|
} // namespace ARDUINOJSON_NAMESPACE
|
50
src/ArduinoJson/Deserialization/Readers/RamReader.hpp
Normal file
50
src/ArduinoJson/Deserialization/Readers/RamReader.hpp
Normal 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
|
29
src/ArduinoJson/Deserialization/Readers/StdStreamReader.hpp
Normal file
29
src/ArduinoJson/Deserialization/Readers/StdStreamReader.hpp
Normal 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
|
@ -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
|
|
@ -4,13 +4,9 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <ArduinoJson/Deserialization/ArduinoStreamReader.hpp>
|
|
||||||
#include <ArduinoJson/Deserialization/CharPointerReader.hpp>
|
|
||||||
#include <ArduinoJson/Deserialization/DeserializationError.hpp>
|
#include <ArduinoJson/Deserialization/DeserializationError.hpp>
|
||||||
#include <ArduinoJson/Deserialization/FlashStringReader.hpp>
|
|
||||||
#include <ArduinoJson/Deserialization/IteratorReader.hpp>
|
|
||||||
#include <ArduinoJson/Deserialization/NestingLimit.hpp>
|
#include <ArduinoJson/Deserialization/NestingLimit.hpp>
|
||||||
#include <ArduinoJson/Deserialization/StdStreamReader.hpp>
|
#include <ArduinoJson/Deserialization/Reader.hpp>
|
||||||
#include <ArduinoJson/StringStorage/StringStorage.hpp>
|
#include <ArduinoJson/StringStorage/StringStorage.hpp>
|
||||||
|
|
||||||
namespace ARDUINOJSON_NAMESPACE {
|
namespace ARDUINOJSON_NAMESPACE {
|
||||||
@ -25,26 +21,17 @@ TDeserializer<TReader, TWriter> makeDeserializer(MemoryPool &pool,
|
|||||||
|
|
||||||
// deserialize(JsonDocument&, const std::string&);
|
// deserialize(JsonDocument&, const std::string&);
|
||||||
// deserialize(JsonDocument&, const String&);
|
// deserialize(JsonDocument&, const String&);
|
||||||
|
// deserialize(JsonDocument&, char*);
|
||||||
|
// deserialize(JsonDocument&, const char*);
|
||||||
|
// deserialize(JsonDocument&, const __FlashStringHelper*);
|
||||||
template <template <typename, typename> class TDeserializer, typename TString>
|
template <template <typename, typename> class TDeserializer, typename TString>
|
||||||
typename enable_if<!is_array<TString>::value, DeserializationError>::type
|
typename enable_if<!is_array<TString>::value, DeserializationError>::type
|
||||||
deserialize(JsonDocument &doc, const TString &input,
|
deserialize(JsonDocument &doc, const TString &input,
|
||||||
NestingLimit nestingLimit) {
|
NestingLimit nestingLimit) {
|
||||||
|
Reader<TString> reader(input);
|
||||||
doc.clear();
|
doc.clear();
|
||||||
return makeDeserializer<TDeserializer>(
|
return makeDeserializer<TDeserializer>(
|
||||||
doc.memoryPool(), makeReader(input),
|
doc.memoryPool(), reader,
|
||||||
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),
|
|
||||||
makeStringStorage(doc.memoryPool(), input), nestingLimit.value)
|
makeStringStorage(doc.memoryPool(), input), nestingLimit.value)
|
||||||
.parse(doc.data());
|
.parse(doc.data());
|
||||||
}
|
}
|
||||||
@ -55,9 +42,10 @@ DeserializationError deserialize(JsonDocument &doc, TChar *input,
|
|||||||
template <template <typename, typename> class TDeserializer, typename TChar>
|
template <template <typename, typename> class TDeserializer, typename TChar>
|
||||||
DeserializationError deserialize(JsonDocument &doc, TChar *input,
|
DeserializationError deserialize(JsonDocument &doc, TChar *input,
|
||||||
size_t inputSize, NestingLimit nestingLimit) {
|
size_t inputSize, NestingLimit nestingLimit) {
|
||||||
|
BoundedReader<TChar *> reader(input, inputSize);
|
||||||
doc.clear();
|
doc.clear();
|
||||||
return makeDeserializer<TDeserializer>(
|
return makeDeserializer<TDeserializer>(
|
||||||
doc.memoryPool(), makeReader(input, inputSize),
|
doc.memoryPool(), reader,
|
||||||
makeStringStorage(doc.memoryPool(), input), nestingLimit.value)
|
makeStringStorage(doc.memoryPool(), input), nestingLimit.value)
|
||||||
.parse(doc.data());
|
.parse(doc.data());
|
||||||
}
|
}
|
||||||
@ -67,9 +55,10 @@ DeserializationError deserialize(JsonDocument &doc, TChar *input,
|
|||||||
template <template <typename, typename> class TDeserializer, typename TStream>
|
template <template <typename, typename> class TDeserializer, typename TStream>
|
||||||
DeserializationError deserialize(JsonDocument &doc, TStream &input,
|
DeserializationError deserialize(JsonDocument &doc, TStream &input,
|
||||||
NestingLimit nestingLimit) {
|
NestingLimit nestingLimit) {
|
||||||
|
Reader<TStream> reader(input);
|
||||||
doc.clear();
|
doc.clear();
|
||||||
return makeDeserializer<TDeserializer>(
|
return makeDeserializer<TDeserializer>(
|
||||||
doc.memoryPool(), makeReader(input),
|
doc.memoryPool(), reader,
|
||||||
makeStringStorage(doc.memoryPool(), input), nestingLimit.value)
|
makeStringStorage(doc.memoryPool(), input), nestingLimit.value)
|
||||||
.parse(doc.data());
|
.parse(doc.data());
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user