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 | |
parent | 42e7fdf01c3a5701bb51e93ad6c650c3dbbc5450 (diff) |
import ArduinoJson 6.18.0
Diffstat (limited to 'include/lib/ArduinoJson/Memory')
-rw-r--r-- | include/lib/ArduinoJson/Memory/Alignment.hpp | 60 | ||||
-rw-r--r-- | include/lib/ArduinoJson/Memory/MemoryPool.hpp | 212 |
2 files changed, 272 insertions, 0 deletions
diff --git a/include/lib/ArduinoJson/Memory/Alignment.hpp b/include/lib/ArduinoJson/Memory/Alignment.hpp new file mode 100644 index 0000000..bf16798 --- /dev/null +++ b/include/lib/ArduinoJson/Memory/Alignment.hpp @@ -0,0 +1,60 @@ +// ArduinoJson - https://arduinojson.org +// Copyright Benoit Blanchon 2014-2021 +// MIT License + +#pragma once + +#include <ArduinoJson/Namespace.hpp> + +#include <stddef.h> // size_t + +namespace ARDUINOJSON_NAMESPACE { + +#if ARDUINOJSON_ENABLE_ALIGNMENT + +inline bool isAligned(size_t value) { + const size_t mask = sizeof(void *) - 1; + size_t addr = value; + return (addr & mask) == 0; +} + +inline size_t addPadding(size_t bytes) { + const size_t mask = sizeof(void *) - 1; + return (bytes + mask) & ~mask; +} + +template <size_t bytes> +struct AddPadding { + static const size_t mask = sizeof(void *) - 1; + static const size_t value = (bytes + mask) & ~mask; +}; + +#else + +inline bool isAligned(size_t) { + return true; +} + +inline size_t addPadding(size_t bytes) { + return bytes; +} + +template <size_t bytes> +struct AddPadding { + static const size_t value = bytes; +}; + +#endif + +template <typename T> +inline bool isAligned(T *ptr) { + return isAligned(reinterpret_cast<size_t>(ptr)); +} + +template <typename T> +inline T *addPadding(T *p) { + size_t address = addPadding(reinterpret_cast<size_t>(p)); + return reinterpret_cast<T *>(address); +} + +} // namespace ARDUINOJSON_NAMESPACE 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 |