mirror of
				https://github.com/eledio-devices/thirdparty-ArduinoJson.git
				synced 2025-10-31 16:14:11 +01:00 
			
		
		
		
	Merged the two StringBuilder classes into one
This commit is contained in:
		| @@ -6,6 +6,7 @@ | ||||
|  | ||||
| #include "../Strings/StringInMemoryPool.hpp" | ||||
| #include "MemoryPool.hpp" | ||||
| #include "StringBuilder.hpp" | ||||
|  | ||||
| #include <stdlib.h>  // malloc, free | ||||
|  | ||||
| @@ -39,7 +40,7 @@ class DynamicMemoryPoolBase : public MemoryPool { | ||||
|     size_t size; | ||||
|   }; | ||||
|   struct Block : EmptyBlock { | ||||
|     uint8_t data[1]; | ||||
|     char data[1]; | ||||
|   }; | ||||
|  | ||||
|  public: | ||||
| @@ -64,11 +65,23 @@ class DynamicMemoryPoolBase : public MemoryPool { | ||||
|   } | ||||
|  | ||||
|   // Allocates the specified amount of bytes in the memoryPool | ||||
|   virtual void* alloc(size_t bytes) { | ||||
|   virtual char* alloc(size_t bytes) { | ||||
|     alignNextAlloc(); | ||||
|     return canAllocInHead(bytes) ? allocInHead(bytes) : allocInNewBlock(bytes); | ||||
|   } | ||||
|  | ||||
|   virtual char* realloc(char* oldPtr, size_t oldSize, size_t newSize) { | ||||
|     size_t n = newSize - oldSize; | ||||
|     if (canAllocInHead(n)) { | ||||
|       allocInHead(n); | ||||
|       return oldPtr; | ||||
|     } else { | ||||
|       char* newPtr = allocInNewBlock(newSize); | ||||
|       if (oldPtr && newPtr) memcpy(newPtr, oldPtr, oldSize); | ||||
|       return newPtr; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   // Resets the memoryPool. | ||||
|   // USE WITH CAUTION: this invalidates all previously allocated data | ||||
|   void clear() { | ||||
| @@ -82,37 +95,6 @@ class DynamicMemoryPoolBase : public MemoryPool { | ||||
|     _head = 0; | ||||
|   } | ||||
|  | ||||
|   class StringBuilder { | ||||
|    public: | ||||
|     explicit StringBuilder(DynamicMemoryPoolBase* parent) | ||||
|         : _parent(parent), _start(NULL), _length(0) {} | ||||
|  | ||||
|     void append(char c) { | ||||
|       if (_parent->canAllocInHead(1)) { | ||||
|         char* end = static_cast<char*>(_parent->allocInHead(1)); | ||||
|         *end = c; | ||||
|         if (_length == 0) _start = end; | ||||
|       } else { | ||||
|         char* newStart = | ||||
|             static_cast<char*>(_parent->allocInNewBlock(_length + 1)); | ||||
|         if (_start && newStart) memcpy(newStart, _start, _length); | ||||
|         if (newStart) newStart[_length] = c; | ||||
|         _start = newStart; | ||||
|       } | ||||
|       _length++; | ||||
|     } | ||||
|  | ||||
|     StringInMemoryPool complete() { | ||||
|       append(0); | ||||
|       return _start; | ||||
|     } | ||||
|  | ||||
|    private: | ||||
|     DynamicMemoryPoolBase* _parent; | ||||
|     char* _start; | ||||
|     size_t _length; | ||||
|   }; | ||||
|  | ||||
|   StringBuilder startString() { | ||||
|     return StringBuilder(this); | ||||
|   } | ||||
| @@ -126,13 +108,13 @@ class DynamicMemoryPoolBase : public MemoryPool { | ||||
|     return _head != NULL && _head->size + bytes <= _head->capacity; | ||||
|   } | ||||
|  | ||||
|   void* allocInHead(size_t bytes) { | ||||
|     void* p = _head->data + _head->size; | ||||
|   char* allocInHead(size_t bytes) { | ||||
|     char* p = _head->data + _head->size; | ||||
|     _head->size += bytes; | ||||
|     return p; | ||||
|   } | ||||
|  | ||||
|   void* allocInNewBlock(size_t bytes) { | ||||
|   char* allocInNewBlock(size_t bytes) { | ||||
|     size_t capacity = _nextBlockCapacity; | ||||
|     if (bytes > capacity) capacity = bytes; | ||||
|     if (!addNewBlock(capacity)) return NULL; | ||||
|   | ||||
| @@ -19,7 +19,9 @@ class MemoryPool { | ||||
|  public: | ||||
|   // Allocates n bytes in the MemoryPool. | ||||
|   // Return a pointer to the allocated memory or NULL if allocation fails. | ||||
|   virtual void *alloc(size_t size) = 0; | ||||
|   virtual char *alloc(size_t size) = 0; | ||||
|  | ||||
|   virtual char *realloc(char *oldPtr, size_t oldSize, size_t newSize) = 0; | ||||
|  | ||||
|  protected: | ||||
|   // CAUTION: NO VIRTUAL DESTRUCTOR! | ||||
|   | ||||
| @@ -7,39 +7,12 @@ | ||||
| #include "../Polyfills/mpl/max.hpp" | ||||
| #include "../Strings/StringInMemoryPool.hpp" | ||||
| #include "MemoryPool.hpp" | ||||
| #include "StringBuilder.hpp" | ||||
|  | ||||
| namespace ARDUINOJSON_NAMESPACE { | ||||
|  | ||||
| class StaticMemoryPoolBase : public MemoryPool { | ||||
|  public: | ||||
|   class StringBuilder { | ||||
|    public: | ||||
|     explicit StringBuilder(StaticMemoryPoolBase* parent) : _parent(parent) { | ||||
|       _start = parent->_buffer + parent->_size; | ||||
|     } | ||||
|  | ||||
|     void append(char c) { | ||||
|       if (_parent->canAlloc(1)) { | ||||
|         char* last = static_cast<char*>(_parent->doAlloc(1)); | ||||
|         *last = c; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     StringInMemoryPool complete() const { | ||||
|       if (_parent->canAlloc(1)) { | ||||
|         char* last = static_cast<char*>(_parent->doAlloc(1)); | ||||
|         *last = '\0'; | ||||
|         return _start; | ||||
|       } else { | ||||
|         return NULL; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|    private: | ||||
|     StaticMemoryPoolBase* _parent; | ||||
|     char* _start; | ||||
|   }; | ||||
|  | ||||
|   // Gets the capacity of the memoryPool in bytes | ||||
|   size_t capacity() const { | ||||
|     return _capacity; | ||||
| @@ -51,12 +24,19 @@ class StaticMemoryPoolBase : public MemoryPool { | ||||
|   } | ||||
|  | ||||
|   // Allocates the specified amount of bytes in the memoryPool | ||||
|   virtual void* alloc(size_t bytes) { | ||||
|   virtual char* alloc(size_t bytes) { | ||||
|     alignNextAlloc(); | ||||
|     if (!canAlloc(bytes)) return NULL; | ||||
|     return doAlloc(bytes); | ||||
|   } | ||||
|  | ||||
|   virtual char* realloc(char* oldPtr, size_t oldSize, size_t newSize) { | ||||
|     size_t n = newSize - oldSize; | ||||
|     if (!canAlloc(n)) return NULL; | ||||
|     doAlloc(n); | ||||
|     return oldPtr; | ||||
|   } | ||||
|  | ||||
|   // Resets the memoryPool. | ||||
|   // USE WITH CAUTION: this invalidates all previously allocated data | ||||
|   void clear() { | ||||
| @@ -82,8 +62,8 @@ class StaticMemoryPoolBase : public MemoryPool { | ||||
|     return _size + bytes <= _capacity; | ||||
|   } | ||||
|  | ||||
|   void* doAlloc(size_t bytes) { | ||||
|     void* p = &_buffer[_size]; | ||||
|   char* doAlloc(size_t bytes) { | ||||
|     char* p = &_buffer[_size]; | ||||
|     _size += bytes; | ||||
|     return p; | ||||
|   } | ||||
|   | ||||
							
								
								
									
										35
									
								
								src/ArduinoJson/Memory/StringBuilder.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								src/ArduinoJson/Memory/StringBuilder.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,35 @@ | ||||
| // ArduinoJson - arduinojson.org | ||||
| // Copyright Benoit Blanchon 2014-2018 | ||||
| // MIT License | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include "../Strings/StringInMemoryPool.hpp" | ||||
| #include "MemoryPool.hpp" | ||||
|  | ||||
| namespace ARDUINOJSON_NAMESPACE { | ||||
|  | ||||
| class StringBuilder { | ||||
|  public: | ||||
|   explicit StringBuilder(MemoryPool* parent) | ||||
|       : _parent(parent), _start(0), _size(0) { | ||||
|     _start = _parent->alloc(1); | ||||
|   } | ||||
|  | ||||
|   void append(char c) { | ||||
|     _start = _parent->realloc(_start, _size + 1, _size + 2); | ||||
|     if (_start) _start[_size++] = c; | ||||
|   } | ||||
|  | ||||
|   StringInMemoryPool complete() { | ||||
|     if (_start) _start[_size] = 0; | ||||
|     return _start; | ||||
|   } | ||||
|  | ||||
|  private: | ||||
|   MemoryPool* _parent; | ||||
|   char* _start; | ||||
|   size_t _size; | ||||
| }; | ||||
|  | ||||
| }  // namespace ARDUINOJSON_NAMESPACE | ||||
| @@ -4,20 +4,22 @@ | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include "../Memory/MemoryPool.hpp" | ||||
| #include "../Memory/StringBuilder.hpp" | ||||
|  | ||||
| namespace ARDUINOJSON_NAMESPACE { | ||||
|  | ||||
| template <typename TMemoryPool> | ||||
| class StringCopier { | ||||
|  public: | ||||
|   StringCopier(TMemoryPool& memoryPool) : _memoryPool(&memoryPool) {} | ||||
|   typedef ARDUINOJSON_NAMESPACE::StringBuilder StringBuilder; | ||||
|  | ||||
|   typedef typename TMemoryPool::StringBuilder StringBuilder; | ||||
|   StringCopier(MemoryPool* memoryPool) : _memoryPool(memoryPool) {} | ||||
|  | ||||
|   StringBuilder startString() { | ||||
|     return _memoryPool->startString(); | ||||
|     return StringBuilder(_memoryPool); | ||||
|   } | ||||
|  | ||||
|  private: | ||||
|   TMemoryPool* _memoryPool; | ||||
|   MemoryPool* _memoryPool; | ||||
| }; | ||||
| }  // namespace ARDUINOJSON_NAMESPACE | ||||
|   | ||||
| @@ -9,34 +9,34 @@ | ||||
|  | ||||
| namespace ARDUINOJSON_NAMESPACE { | ||||
|  | ||||
| template <typename TMemoryPool, typename TInput, typename Enable = void> | ||||
| template <typename TInput, typename Enable = void> | ||||
| struct StringStorage { | ||||
|   typedef StringCopier<TMemoryPool> type; | ||||
|   typedef StringCopier type; | ||||
|  | ||||
|   static type create(TMemoryPool& jb, TInput&) { | ||||
|     return type(jb); | ||||
|   static type create(MemoryPool& pool, TInput&) { | ||||
|     return type(&pool); | ||||
|   } | ||||
| }; | ||||
|  | ||||
| template <typename TMemoryPool, typename TChar> | ||||
| struct StringStorage<TMemoryPool, TChar*, | ||||
| template <typename TChar> | ||||
| struct StringStorage<TChar*, | ||||
|                      typename enable_if<!is_const<TChar>::value>::type> { | ||||
|   typedef StringMover<TChar> type; | ||||
|  | ||||
|   static type create(TMemoryPool&, TChar* input) { | ||||
|   static type create(MemoryPool&, TChar* input) { | ||||
|     return type(input); | ||||
|   } | ||||
| }; | ||||
|  | ||||
| template <typename TMemoryPool, typename TInput> | ||||
| typename StringStorage<TMemoryPool, TInput>::type makeStringStorage( | ||||
|     TMemoryPool& jb, TInput& input) { | ||||
|   return StringStorage<TMemoryPool, TInput>::create(jb, input); | ||||
| template <typename TInput> | ||||
| typename StringStorage<TInput>::type makeStringStorage(MemoryPool& pool, | ||||
|                                                        TInput& input) { | ||||
|   return StringStorage<TInput>::create(pool, input); | ||||
| } | ||||
|  | ||||
| template <typename TMemoryPool, typename TChar> | ||||
| typename StringStorage<TMemoryPool, TChar*>::type makeStringStorage( | ||||
|     TMemoryPool& jb, TChar* input) { | ||||
|   return StringStorage<TMemoryPool, TChar*>::create(jb, input); | ||||
| template <typename TChar> | ||||
| typename StringStorage<TChar*>::type makeStringStorage(MemoryPool& pool, | ||||
|                                                        TChar* input) { | ||||
|   return StringStorage<TChar*>::create(pool, input); | ||||
| } | ||||
| }  // namespace ARDUINOJSON_NAMESPACE | ||||
|   | ||||
| @@ -17,8 +17,6 @@ struct NoMemoryAllocator { | ||||
| TEST_CASE("DynamicMemoryPool no memory") { | ||||
|   DynamicMemoryPoolBase<NoMemoryAllocator> _memoryPool; | ||||
|  | ||||
|   typedef DynamicMemoryPoolBase<NoMemoryAllocator>::StringBuilder StringBuilder; | ||||
|  | ||||
|   SECTION("FixCodeCoverage") { | ||||
|     // call this function to fix code coverage | ||||
|     NoMemoryAllocator().deallocate(NULL); | ||||
|   | ||||
| @@ -7,8 +7,6 @@ | ||||
|  | ||||
| using namespace ARDUINOJSON_NAMESPACE; | ||||
|  | ||||
| typedef DynamicMemoryPool::StringBuilder StringBuilder; | ||||
|  | ||||
| TEST_CASE("DynamicMemoryPool::startString()") { | ||||
|   SECTION("WorksWhenBufferIsBigEnough") { | ||||
|     DynamicMemoryPool memoryPool(6); | ||||
| @@ -40,12 +38,9 @@ TEST_CASE("DynamicMemoryPool::startString()") { | ||||
|     DynamicMemoryPool memoryPool(5); | ||||
|  | ||||
|     StringBuilder str = memoryPool.startString(); | ||||
|     REQUIRE(0 == memoryPool.size()); | ||||
|  | ||||
|     str.append('h'); | ||||
|     REQUIRE(1 == memoryPool.size()); | ||||
|  | ||||
|     str.complete(); | ||||
|  | ||||
|     REQUIRE(2 == memoryPool.size()); | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -8,8 +8,6 @@ | ||||
| using namespace ARDUINOJSON_NAMESPACE; | ||||
|  | ||||
| TEST_CASE("StaticMemoryPool::startString()") { | ||||
|   typedef StaticMemoryPoolBase::StringBuilder StringBuilder; | ||||
|  | ||||
|   SECTION("WorksWhenBufferIsBigEnough") { | ||||
|     StaticMemoryPool<6> memoryPool; | ||||
|  | ||||
| @@ -40,12 +38,9 @@ TEST_CASE("StaticMemoryPool::startString()") { | ||||
|     StaticMemoryPool<5> memoryPool; | ||||
|  | ||||
|     StringBuilder str = memoryPool.startString(); | ||||
|     REQUIRE(0 == memoryPool.size()); | ||||
|  | ||||
|     str.append('h'); | ||||
|     REQUIRE(1 == memoryPool.size()); | ||||
|  | ||||
|     str.complete(); | ||||
|  | ||||
|     REQUIRE(2 == memoryPool.size()); | ||||
|   } | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user