mirror of
				https://github.com/eledio-devices/thirdparty-ArduinoJson.git
				synced 2025-10-31 16:14:11 +01:00 
			
		
		
		
	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