diff options
author | Daniel Friesel <daniel.friesel@uos.de> | 2021-05-12 09:12:09 +0200 |
---|---|---|
committer | Daniel Friesel <daniel.friesel@uos.de> | 2021-05-12 09:12:09 +0200 |
commit | 39895a677e5d370824e702cfe90ebc67737b8482 (patch) | |
tree | ff5b4cc9e373d33a795d50d9333e05549bd9f2b8 /include/lib/ArduinoJson/Memory/MemoryPool.hpp | |
parent | 42e7fdf01c3a5701bb51e93ad6c650c3dbbc5450 (diff) |
import ArduinoJson 6.18.0
Diffstat (limited to 'include/lib/ArduinoJson/Memory/MemoryPool.hpp')
-rw-r--r-- | include/lib/ArduinoJson/Memory/MemoryPool.hpp | 212 |
1 files changed, 212 insertions, 0 deletions
diff --git a/include/lib/ArduinoJson/Memory/MemoryPool.hpp b/include/lib/ArduinoJson/Memory/MemoryPool.hpp new file mode 100644 index 0000000..49debf8 --- /dev/null +++ b/include/lib/ArduinoJson/Memory/MemoryPool.hpp @@ -0,0 +1,212 @@ +// ArduinoJson - https://arduinojson.org +// Copyright Benoit Blanchon 2014-2021 +// MIT License + +#pragma once + +#include <ArduinoJson/Memory/Alignment.hpp> +#include <ArduinoJson/Polyfills/assert.hpp> +#include <ArduinoJson/Polyfills/mpl/max.hpp> +#include <ArduinoJson/Variant/VariantSlot.hpp> + +#include <string.h> // memmove + +#define JSON_STRING_SIZE(SIZE) (SIZE + 1) + +namespace ARDUINOJSON_NAMESPACE { + +// _begin _end +// v v +// +-------------+--------------+--------------+ +// | strings... | (free) | ...variants | +// +-------------+--------------+--------------+ +// ^ ^ +// _left _right + +class MemoryPool { + public: + MemoryPool(char* buf, size_t capa) + : _begin(buf), + _left(buf), + _right(buf ? buf + capa : 0), + _end(buf ? buf + capa : 0), + _overflowed(false) { + ARDUINOJSON_ASSERT(isAligned(_begin)); + ARDUINOJSON_ASSERT(isAligned(_right)); + ARDUINOJSON_ASSERT(isAligned(_end)); + } + + void* buffer() { + return _begin; + } + + // Gets the capacity of the memoryPool in bytes + size_t capacity() const { + return size_t(_end - _begin); + } + + size_t size() const { + return size_t(_left - _begin + _end - _right); + } + + bool overflowed() const { + return _overflowed; + } + + VariantSlot* allocVariant() { + return allocRight<VariantSlot>(); + } + + template <typename TAdaptedString> + const char* saveString(const TAdaptedString& str) { + if (str.isNull()) + return 0; + +#if ARDUINOJSON_ENABLE_STRING_DEDUPLICATION + const char* existingCopy = findString(str.begin()); + if (existingCopy) + return existingCopy; +#endif + + size_t n = str.size(); + + char* newCopy = allocString(n + 1); + if (newCopy) { + str.copyTo(newCopy, n); + newCopy[n] = 0; // force null-terminator + } + return newCopy; + } + + void getFreeZone(char** zoneStart, size_t* zoneSize) const { + *zoneStart = _left; + *zoneSize = size_t(_right - _left); + } + + const char* saveStringFromFreeZone(size_t len) { +#if ARDUINOJSON_ENABLE_STRING_DEDUPLICATION + const char* dup = findString(_left); + if (dup) + return dup; +#endif + + const char* str = _left; + _left += len; + checkInvariants(); + return str; + } + + void markAsOverflowed() { + _overflowed = true; + } + + void clear() { + _left = _begin; + _right = _end; + _overflowed = false; + } + + bool canAlloc(size_t bytes) const { + return _left + bytes <= _right; + } + + bool owns(void* p) const { + return _begin <= p && p < _end; + } + + // Workaround for missing placement new + void* operator new(size_t, void* p) { + return p; + } + + // Squash the free space between strings and variants + // + // _begin _end + // v v + // +-------------+--------------+ + // | strings... | ...variants | + // +-------------+--------------+ + // ^ + // _left _right + // + // This funcion is called before a realloc. + ptrdiff_t squash() { + char* new_right = addPadding(_left); + if (new_right >= _right) + return 0; + + size_t right_size = static_cast<size_t>(_end - _right); + memmove(new_right, _right, right_size); + + ptrdiff_t bytes_reclaimed = _right - new_right; + _right = new_right; + _end = new_right + right_size; + return bytes_reclaimed; + } + + // Move all pointers together + // This funcion is called after a realloc. + void movePointers(ptrdiff_t offset) { + _begin += offset; + _left += offset; + _right += offset; + _end += offset; + } + + private: + void checkInvariants() { + ARDUINOJSON_ASSERT(_begin <= _left); + ARDUINOJSON_ASSERT(_left <= _right); + ARDUINOJSON_ASSERT(_right <= _end); + ARDUINOJSON_ASSERT(isAligned(_right)); + } + +#if ARDUINOJSON_ENABLE_STRING_DEDUPLICATION + template <typename TIterator> + const char* findString(TIterator str) { + for (char* next = _begin; next < _left; ++next) { + char* begin = next; + + // try to match + for (TIterator it = str; *it == *next; ++it) { + if (*next++ == 0) + return begin; + } + + // jump to next terminator + while (*next) ++next; + } + return 0; + } +#endif + + char* allocString(size_t n) { + if (!canAlloc(n)) { + _overflowed = true; + return 0; + } + char* s = _left; + _left += n; + checkInvariants(); + return s; + } + + template <typename T> + T* allocRight() { + return reinterpret_cast<T*>(allocRight(sizeof(T))); + } + + void* allocRight(size_t bytes) { + if (!canAlloc(bytes)) { + _overflowed = true; + return 0; + } + _right -= bytes; + return _right; + } + + char *_begin, *_left, *_right, *_end; + bool _overflowed; +}; + +} // namespace ARDUINOJSON_NAMESPACE |