mirror of
				https://github.com/eledio-devices/thirdparty-ArduinoJson.git
				synced 2025-10-31 16:14:11 +01:00 
			
		
		
		
	Added BasicJsonDocument to support custom allocator (issue #876)
				
					
				
			This commit is contained in:
		| @@ -8,6 +8,7 @@ HEAD | |||||||
| * Added overflow handling in `JsonVariant::as<T>()` and `JsonVariant::is<T>()`. | * Added overflow handling in `JsonVariant::as<T>()` and `JsonVariant::is<T>()`. | ||||||
|    - `as<T>()` returns `0` if the integer `T` overflows |    - `as<T>()` returns `0` if the integer `T` overflows | ||||||
|    - `is<T>()` returns `false` if the integer `T` overflows |    - `is<T>()` returns `false` if the integer `T` overflows | ||||||
|  | * Added `BasicJsonDocument` to support custom allocator (issue #876) | ||||||
|  |  | ||||||
| v6.9.1 (2019-03-01) | v6.9.1 (2019-03-01) | ||||||
| ------ | ------ | ||||||
|   | |||||||
| @@ -50,6 +50,7 @@ typedef ARDUINOJSON_NAMESPACE::String JsonString; | |||||||
| typedef ARDUINOJSON_NAMESPACE::UInt JsonUInt; | typedef ARDUINOJSON_NAMESPACE::UInt JsonUInt; | ||||||
| typedef ARDUINOJSON_NAMESPACE::VariantConstRef JsonVariantConst; | typedef ARDUINOJSON_NAMESPACE::VariantConstRef JsonVariantConst; | ||||||
| typedef ARDUINOJSON_NAMESPACE::VariantRef JsonVariant; | typedef ARDUINOJSON_NAMESPACE::VariantRef JsonVariant; | ||||||
|  | using ARDUINOJSON_NAMESPACE::BasicJsonDocument; | ||||||
| using ARDUINOJSON_NAMESPACE::copyArray; | using ARDUINOJSON_NAMESPACE::copyArray; | ||||||
| using ARDUINOJSON_NAMESPACE::DeserializationError; | using ARDUINOJSON_NAMESPACE::DeserializationError; | ||||||
| using ARDUINOJSON_NAMESPACE::deserializeJson; | using ARDUINOJSON_NAMESPACE::deserializeJson; | ||||||
|   | |||||||
							
								
								
									
										89
									
								
								src/ArduinoJson/Document/BasicJsonDocument.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								src/ArduinoJson/Document/BasicJsonDocument.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,89 @@ | |||||||
|  | // ArduinoJson - arduinojson.org | ||||||
|  | // Copyright Benoit Blanchon 2014-2019 | ||||||
|  | // MIT License | ||||||
|  |  | ||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include "JsonDocument.hpp" | ||||||
|  |  | ||||||
|  | namespace ARDUINOJSON_NAMESPACE { | ||||||
|  |  | ||||||
|  | template <typename TAllocator> | ||||||
|  | class AllocatorOwner { | ||||||
|  |  protected: | ||||||
|  |   AllocatorOwner() {} | ||||||
|  |   AllocatorOwner(const AllocatorOwner& src) : _allocator(src._allocator) {} | ||||||
|  |   AllocatorOwner(TAllocator allocator) : _allocator(allocator) {} | ||||||
|  |  | ||||||
|  |   void* allocate(size_t n) { | ||||||
|  |     return _allocator.allocate(n); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   void deallocate(void* p) { | ||||||
|  |     _allocator.deallocate(p); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |  private: | ||||||
|  |   TAllocator _allocator; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | template <typename TAllocator> | ||||||
|  | class BasicJsonDocument : AllocatorOwner<TAllocator>, public JsonDocument { | ||||||
|  |  public: | ||||||
|  |   explicit BasicJsonDocument(size_t capa, TAllocator allocator = TAllocator()) | ||||||
|  |       : AllocatorOwner<TAllocator>(allocator), JsonDocument(allocPool(capa)) {} | ||||||
|  |  | ||||||
|  |   BasicJsonDocument(const BasicJsonDocument& src) | ||||||
|  |       : AllocatorOwner<TAllocator>(src), | ||||||
|  |         JsonDocument(allocPool(src.memoryUsage())) { | ||||||
|  |     set(src); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   template <typename T> | ||||||
|  |   BasicJsonDocument(const T& src, | ||||||
|  |                     typename enable_if<IsVisitable<T>::value>::type* = 0) | ||||||
|  |       : JsonDocument(allocPool(src.memoryUsage())) { | ||||||
|  |     set(src); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   // disambiguate | ||||||
|  |   BasicJsonDocument(VariantRef src) | ||||||
|  |       : JsonDocument(allocPool(src.memoryUsage())) { | ||||||
|  |     set(src); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   ~BasicJsonDocument() { | ||||||
|  |     freePool(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   BasicJsonDocument& operator=(const BasicJsonDocument& src) { | ||||||
|  |     reallocPoolIfTooSmall(src.memoryUsage()); | ||||||
|  |     set(src); | ||||||
|  |     return *this; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   template <typename T> | ||||||
|  |   BasicJsonDocument& operator=(const T& src) { | ||||||
|  |     reallocPoolIfTooSmall(src.memoryUsage()); | ||||||
|  |     set(src); | ||||||
|  |     return *this; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |  private: | ||||||
|  |   MemoryPool allocPool(size_t requiredSize) { | ||||||
|  |     size_t capa = addPadding(requiredSize); | ||||||
|  |     return MemoryPool(reinterpret_cast<char*>(this->allocate(capa)), capa); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   void reallocPoolIfTooSmall(size_t requiredSize) { | ||||||
|  |     if (requiredSize <= capacity()) return; | ||||||
|  |     freePool(); | ||||||
|  |     replacePool(allocPool(addPadding(requiredSize))); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   void freePool() { | ||||||
|  |     this->deallocate(memoryPool().buffer()); | ||||||
|  |   } | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | }  // namespace ARDUINOJSON_NAMESPACE | ||||||
| @@ -4,66 +4,22 @@ | |||||||
|  |  | ||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
| #include "JsonDocument.hpp" | #include "BasicJsonDocument.hpp" | ||||||
|  |  | ||||||
| #include <stdlib.h>  // malloc, free | #include <stdlib.h>  // malloc, free | ||||||
|  |  | ||||||
| namespace ARDUINOJSON_NAMESPACE { | namespace ARDUINOJSON_NAMESPACE { | ||||||
|  |  | ||||||
| class DynamicJsonDocument : public JsonDocument { | struct DefaultAllocator { | ||||||
|  public: |   void* allocate(size_t n) { | ||||||
|   explicit DynamicJsonDocument(size_t capa) : JsonDocument(allocPool(capa)) {} |     return malloc(n); | ||||||
|  |  | ||||||
|   DynamicJsonDocument(const DynamicJsonDocument& src) |  | ||||||
|       : JsonDocument(allocPool(src.memoryUsage())) { |  | ||||||
|     set(src); |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   template <typename T> |   void deallocate(void* p) { | ||||||
|   DynamicJsonDocument(const T& src, |     free(p); | ||||||
|                       typename enable_if<IsVisitable<T>::value>::type* = 0) |  | ||||||
|       : JsonDocument(allocPool(src.memoryUsage())) { |  | ||||||
|     set(src); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   // disambiguate |  | ||||||
|   DynamicJsonDocument(VariantRef src) |  | ||||||
|       : JsonDocument(allocPool(src.memoryUsage())) { |  | ||||||
|     set(src); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   ~DynamicJsonDocument() { |  | ||||||
|     freePool(); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   DynamicJsonDocument& operator=(const DynamicJsonDocument& src) { |  | ||||||
|     reallocPoolIfTooSmall(src.memoryUsage()); |  | ||||||
|     set(src); |  | ||||||
|     return *this; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   template <typename T> |  | ||||||
|   DynamicJsonDocument& operator=(const T& src) { |  | ||||||
|     reallocPoolIfTooSmall(src.memoryUsage()); |  | ||||||
|     set(src); |  | ||||||
|     return *this; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|  private: |  | ||||||
|   MemoryPool allocPool(size_t requiredSize) { |  | ||||||
|     size_t capa = addPadding(requiredSize); |  | ||||||
|     return MemoryPool(reinterpret_cast<char*>(malloc(capa)), capa); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   void reallocPoolIfTooSmall(size_t requiredSize) { |  | ||||||
|     if (requiredSize <= capacity()) return; |  | ||||||
|     freePool(); |  | ||||||
|     replacePool(allocPool(addPadding(requiredSize))); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   void freePool() { |  | ||||||
|     free(memoryPool().buffer()); |  | ||||||
|   } |   } | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | typedef BasicJsonDocument<DefaultAllocator> DynamicJsonDocument; | ||||||
|  |  | ||||||
| }  // namespace ARDUINOJSON_NAMESPACE | }  // namespace ARDUINOJSON_NAMESPACE | ||||||
|   | |||||||
							
								
								
									
										49
									
								
								test/JsonDocument/BasicJsonDocument.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								test/JsonDocument/BasicJsonDocument.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,49 @@ | |||||||
|  | // ArduinoJson - arduinojson.org | ||||||
|  | // Copyright Benoit Blanchon 2014-2019 | ||||||
|  | // MIT License | ||||||
|  |  | ||||||
|  | #include <ArduinoJson.h> | ||||||
|  | #include <stdlib.h>  // malloc, free | ||||||
|  | #include <catch.hpp> | ||||||
|  | #include <sstream> | ||||||
|  |  | ||||||
|  | using ARDUINOJSON_NAMESPACE::addPadding; | ||||||
|  |  | ||||||
|  | class SpyingAllocator { | ||||||
|  |  public: | ||||||
|  |   SpyingAllocator(std::ostream& log) : _log(log) {} | ||||||
|  |  | ||||||
|  |   void* allocate(size_t n) { | ||||||
|  |     _log << "A" << n; | ||||||
|  |     return malloc(n); | ||||||
|  |   } | ||||||
|  |   void deallocate(void* p) { | ||||||
|  |     _log << "F"; | ||||||
|  |     free(p); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |  private: | ||||||
|  |   SpyingAllocator& operator=(const SpyingAllocator& src); | ||||||
|  |  | ||||||
|  |   std::ostream& _log; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | typedef BasicJsonDocument<SpyingAllocator> MyJsonDocument; | ||||||
|  |  | ||||||
|  | TEST_CASE("BasicJsonDocument") { | ||||||
|  |   std::stringstream log; | ||||||
|  |  | ||||||
|  |   SECTION("Construct/Destruct") { | ||||||
|  |     { MyJsonDocument doc(4096, log); } | ||||||
|  |     REQUIRE(log.str() == "A4096F"); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("Copy construct") { | ||||||
|  |     { | ||||||
|  |       MyJsonDocument doc1(4096, log); | ||||||
|  |       doc1.set(std::string("The size of this string is 32!!")); | ||||||
|  |       MyJsonDocument doc2(doc1); | ||||||
|  |     } | ||||||
|  |     REQUIRE(log.str() == "A4096A32FF"); | ||||||
|  |   } | ||||||
|  | } | ||||||
| @@ -4,6 +4,7 @@ | |||||||
|  |  | ||||||
| add_executable(JsonDocumentTests | add_executable(JsonDocumentTests | ||||||
| 	add.cpp | 	add.cpp | ||||||
|  | 	BasicJsonDocument.cpp | ||||||
| 	createNested.cpp | 	createNested.cpp | ||||||
| 	DynamicJsonDocument.cpp | 	DynamicJsonDocument.cpp | ||||||
| 	isNull.cpp | 	isNull.cpp | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user