Просмотр исходного кода

Merged the two StringBuilder classes into one

Benoit Blanchon 7 лет назад
Родитель
Сommit
ae089dcff7

+ 18 - 36
src/ArduinoJson/Memory/DynamicMemoryPool.hpp

@@ -6,6 +6,7 @@
 
 
 #include "../Strings/StringInMemoryPool.hpp"
 #include "../Strings/StringInMemoryPool.hpp"
 #include "MemoryPool.hpp"
 #include "MemoryPool.hpp"
+#include "StringBuilder.hpp"
 
 
 #include <stdlib.h>  // malloc, free
 #include <stdlib.h>  // malloc, free
 
 
@@ -39,7 +40,7 @@ class DynamicMemoryPoolBase : public MemoryPool {
     size_t size;
     size_t size;
   };
   };
   struct Block : EmptyBlock {
   struct Block : EmptyBlock {
-    uint8_t data[1];
+    char data[1];
   };
   };
 
 
  public:
  public:
@@ -64,11 +65,23 @@ class DynamicMemoryPoolBase : public MemoryPool {
   }
   }
 
 
   // Allocates the specified amount of bytes in the memoryPool
   // Allocates the specified amount of bytes in the memoryPool
-  virtual void* alloc(size_t bytes) {
+  virtual char* alloc(size_t bytes) {
     alignNextAlloc();
     alignNextAlloc();
     return canAllocInHead(bytes) ? allocInHead(bytes) : allocInNewBlock(bytes);
     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.
   // Resets the memoryPool.
   // USE WITH CAUTION: this invalidates all previously allocated data
   // USE WITH CAUTION: this invalidates all previously allocated data
   void clear() {
   void clear() {
@@ -82,37 +95,6 @@ class DynamicMemoryPoolBase : public MemoryPool {
     _head = 0;
     _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() {
   StringBuilder startString() {
     return StringBuilder(this);
     return StringBuilder(this);
   }
   }
@@ -126,13 +108,13 @@ class DynamicMemoryPoolBase : public MemoryPool {
     return _head != NULL && _head->size + bytes <= _head->capacity;
     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;
     _head->size += bytes;
     return p;
     return p;
   }
   }
 
 
-  void* allocInNewBlock(size_t bytes) {
+  char* allocInNewBlock(size_t bytes) {
     size_t capacity = _nextBlockCapacity;
     size_t capacity = _nextBlockCapacity;
     if (bytes > capacity) capacity = bytes;
     if (bytes > capacity) capacity = bytes;
     if (!addNewBlock(capacity)) return NULL;
     if (!addNewBlock(capacity)) return NULL;

+ 3 - 1
src/ArduinoJson/Memory/MemoryPool.hpp

@@ -19,7 +19,9 @@ class MemoryPool {
  public:
  public:
   // Allocates n bytes in the MemoryPool.
   // Allocates n bytes in the MemoryPool.
   // Return a pointer to the allocated memory or NULL if allocation fails.
   // 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:
  protected:
   // CAUTION: NO VIRTUAL DESTRUCTOR!
   // CAUTION: NO VIRTUAL DESTRUCTOR!

+ 11 - 31
src/ArduinoJson/Memory/StaticMemoryPool.hpp

@@ -7,39 +7,12 @@
 #include "../Polyfills/mpl/max.hpp"
 #include "../Polyfills/mpl/max.hpp"
 #include "../Strings/StringInMemoryPool.hpp"
 #include "../Strings/StringInMemoryPool.hpp"
 #include "MemoryPool.hpp"
 #include "MemoryPool.hpp"
+#include "StringBuilder.hpp"
 
 
 namespace ARDUINOJSON_NAMESPACE {
 namespace ARDUINOJSON_NAMESPACE {
 
 
 class StaticMemoryPoolBase : public MemoryPool {
 class StaticMemoryPoolBase : public MemoryPool {
  public:
  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
   // Gets the capacity of the memoryPool in bytes
   size_t capacity() const {
   size_t capacity() const {
     return _capacity;
     return _capacity;
@@ -51,12 +24,19 @@ class StaticMemoryPoolBase : public MemoryPool {
   }
   }
 
 
   // Allocates the specified amount of bytes in the memoryPool
   // Allocates the specified amount of bytes in the memoryPool
-  virtual void* alloc(size_t bytes) {
+  virtual char* alloc(size_t bytes) {
     alignNextAlloc();
     alignNextAlloc();
     if (!canAlloc(bytes)) return NULL;
     if (!canAlloc(bytes)) return NULL;
     return doAlloc(bytes);
     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.
   // Resets the memoryPool.
   // USE WITH CAUTION: this invalidates all previously allocated data
   // USE WITH CAUTION: this invalidates all previously allocated data
   void clear() {
   void clear() {
@@ -82,8 +62,8 @@ class StaticMemoryPoolBase : public MemoryPool {
     return _size + bytes <= _capacity;
     return _size + bytes <= _capacity;
   }
   }
 
 
-  void* doAlloc(size_t bytes) {
-    void* p = &_buffer[_size];
+  char* doAlloc(size_t bytes) {
+    char* p = &_buffer[_size];
     _size += bytes;
     _size += bytes;
     return p;
     return p;
   }
   }

+ 35 - 0
src/ArduinoJson/Memory/StringBuilder.hpp

@@ -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

+ 7 - 5
src/ArduinoJson/StringStorage/StringCopier.hpp

@@ -4,20 +4,22 @@
 
 
 #pragma once
 #pragma once
 
 
+#include "../Memory/MemoryPool.hpp"
+#include "../Memory/StringBuilder.hpp"
+
 namespace ARDUINOJSON_NAMESPACE {
 namespace ARDUINOJSON_NAMESPACE {
 
 
-template <typename TMemoryPool>
 class StringCopier {
 class StringCopier {
  public:
  public:
-  StringCopier(TMemoryPool& memoryPool) : _memoryPool(&memoryPool) {}
+  typedef ARDUINOJSON_NAMESPACE::StringBuilder StringBuilder;
 
 
-  typedef typename TMemoryPool::StringBuilder StringBuilder;
+  StringCopier(MemoryPool* memoryPool) : _memoryPool(memoryPool) {}
 
 
   StringBuilder startString() {
   StringBuilder startString() {
-    return _memoryPool->startString();
+    return StringBuilder(_memoryPool);
   }
   }
 
 
  private:
  private:
-  TMemoryPool* _memoryPool;
+  MemoryPool* _memoryPool;
 };
 };
 }  // namespace ARDUINOJSON_NAMESPACE
 }  // namespace ARDUINOJSON_NAMESPACE

+ 15 - 15
src/ArduinoJson/StringStorage/StringStorage.hpp

@@ -9,34 +9,34 @@
 
 
 namespace ARDUINOJSON_NAMESPACE {
 namespace ARDUINOJSON_NAMESPACE {
 
 
-template <typename TMemoryPool, typename TInput, typename Enable = void>
+template <typename TInput, typename Enable = void>
 struct StringStorage {
 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> {
                      typename enable_if<!is_const<TChar>::value>::type> {
   typedef StringMover<TChar> type;
   typedef StringMover<TChar> type;
 
 
-  static type create(TMemoryPool&, TChar* input) {
+  static type create(MemoryPool&, TChar* input) {
     return type(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
 }  // namespace ARDUINOJSON_NAMESPACE

+ 0 - 2
test/DynamicMemoryPool/no_memory.cpp

@@ -17,8 +17,6 @@ struct NoMemoryAllocator {
 TEST_CASE("DynamicMemoryPool no memory") {
 TEST_CASE("DynamicMemoryPool no memory") {
   DynamicMemoryPoolBase<NoMemoryAllocator> _memoryPool;
   DynamicMemoryPoolBase<NoMemoryAllocator> _memoryPool;
 
 
-  typedef DynamicMemoryPoolBase<NoMemoryAllocator>::StringBuilder StringBuilder;
-
   SECTION("FixCodeCoverage") {
   SECTION("FixCodeCoverage") {
     // call this function to fix code coverage
     // call this function to fix code coverage
     NoMemoryAllocator().deallocate(NULL);
     NoMemoryAllocator().deallocate(NULL);

+ 1 - 6
test/DynamicMemoryPool/startString.cpp

@@ -7,8 +7,6 @@
 
 
 using namespace ARDUINOJSON_NAMESPACE;
 using namespace ARDUINOJSON_NAMESPACE;
 
 
-typedef DynamicMemoryPool::StringBuilder StringBuilder;
-
 TEST_CASE("DynamicMemoryPool::startString()") {
 TEST_CASE("DynamicMemoryPool::startString()") {
   SECTION("WorksWhenBufferIsBigEnough") {
   SECTION("WorksWhenBufferIsBigEnough") {
     DynamicMemoryPool memoryPool(6);
     DynamicMemoryPool memoryPool(6);
@@ -40,12 +38,9 @@ TEST_CASE("DynamicMemoryPool::startString()") {
     DynamicMemoryPool memoryPool(5);
     DynamicMemoryPool memoryPool(5);
 
 
     StringBuilder str = memoryPool.startString();
     StringBuilder str = memoryPool.startString();
-    REQUIRE(0 == memoryPool.size());
-
     str.append('h');
     str.append('h');
-    REQUIRE(1 == memoryPool.size());
-
     str.complete();
     str.complete();
+
     REQUIRE(2 == memoryPool.size());
     REQUIRE(2 == memoryPool.size());
   }
   }
 }
 }

+ 1 - 6
test/StaticMemoryPool/startString.cpp

@@ -8,8 +8,6 @@
 using namespace ARDUINOJSON_NAMESPACE;
 using namespace ARDUINOJSON_NAMESPACE;
 
 
 TEST_CASE("StaticMemoryPool::startString()") {
 TEST_CASE("StaticMemoryPool::startString()") {
-  typedef StaticMemoryPoolBase::StringBuilder StringBuilder;
-
   SECTION("WorksWhenBufferIsBigEnough") {
   SECTION("WorksWhenBufferIsBigEnough") {
     StaticMemoryPool<6> memoryPool;
     StaticMemoryPool<6> memoryPool;
 
 
@@ -40,12 +38,9 @@ TEST_CASE("StaticMemoryPool::startString()") {
     StaticMemoryPool<5> memoryPool;
     StaticMemoryPool<5> memoryPool;
 
 
     StringBuilder str = memoryPool.startString();
     StringBuilder str = memoryPool.startString();
-    REQUIRE(0 == memoryPool.size());
-
     str.append('h');
     str.append('h');
-    REQUIRE(1 == memoryPool.size());
-
     str.complete();
     str.complete();
+
     REQUIRE(2 == memoryPool.size());
     REQUIRE(2 == memoryPool.size());
   }
   }
 }
 }