diff --git a/include/ArduinoJson/DynamicJsonBuffer.hpp b/include/ArduinoJson/DynamicJsonBuffer.hpp index 5fb33440..81d195be 100644 --- a/include/ArduinoJson/DynamicJsonBuffer.hpp +++ b/include/ArduinoJson/DynamicJsonBuffer.hpp @@ -15,29 +15,47 @@ namespace ArduinoJson { // more suitable for embedded systems. class DynamicJsonBuffer : public JsonBuffer { public: - explicit DynamicJsonBuffer() : _size(0) {} + explicit DynamicJsonBuffer() : _next(NULL), _size(0) {} size_t size() const { return _size; } - size_t blockCount() const { return 1; } + size_t blockCount() const { return _next ? _next->blockCount() + 1 : 1; } static const size_t BLOCK_CAPACITY = 32; protected: virtual void* alloc(size_t bytes) { - if (bytes > BLOCK_CAPACITY) return NULL; + if (canAllocInThisBlock(bytes)) + return allocInThisBlock(bytes); + else if (canAllocInOtherBlocks(bytes)) + return allocInOtherBlocks(bytes); + else + return NULL; + } + + private: + bool canAllocInThisBlock(size_t bytes) const { + return _size + bytes <= BLOCK_CAPACITY; + } + + void* allocInThisBlock(size_t bytes) { void* p = _buffer + _size; _size += bytes; return p; } - - bool canStore(size_t bytes) { + bool canAllocInOtherBlocks(size_t bytes) const { // by design a DynamicJsonBuffer can't alloc a block bigger than // BLOCK_CAPACITY return bytes < BLOCK_CAPACITY; } + void* allocInOtherBlocks(size_t bytes) { + if (!_next) _next = new DynamicJsonBuffer(); + return _next->alloc(bytes); + } + size_t _size; uint8_t _buffer[BLOCK_CAPACITY]; + DynamicJsonBuffer* _next; }; } diff --git a/test/DynamicJsonBuffer_Basic_Tests.cpp b/test/DynamicJsonBuffer_Basic_Tests.cpp index cc8d97ed..83c949a9 100644 --- a/test/DynamicJsonBuffer_Basic_Tests.cpp +++ b/test/DynamicJsonBuffer_Basic_Tests.cpp @@ -24,13 +24,24 @@ TEST_F(DynamicJsonBuffer_Basic_Tests, InitialBlockCountIsOne) { ASSERT_EQ(1, buffer.blockCount()); } -TEST_F(DynamicJsonBuffer_Basic_Tests, GrowsAfterAlloc) { +TEST_F(DynamicJsonBuffer_Basic_Tests, SizeIncreasesAfterAlloc) { buffer.alloc(1); ASSERT_EQ(1, buffer.size()); buffer.alloc(1); ASSERT_EQ(2, buffer.size()); } +TEST_F(DynamicJsonBuffer_Basic_Tests, BlockCountDoesntChangeWhenNotFull) { + buffer.alloc(DynamicJsonBuffer::BLOCK_CAPACITY); + ASSERT_EQ(1, buffer.blockCount()); +} + +TEST_F(DynamicJsonBuffer_Basic_Tests, BlockCountChangesWhenFull) { + buffer.alloc(DynamicJsonBuffer::BLOCK_CAPACITY); + buffer.alloc(1); + ASSERT_EQ(2, buffer.blockCount()); +} + TEST_F(DynamicJsonBuffer_Basic_Tests, CanAllocLessThanBlockCapacity) { void* p = buffer.alloc(DynamicJsonBuffer::BLOCK_CAPACITY); ASSERT_TRUE(p);