mirror of
https://github.com/eledio-devices/thirdparty-ArduinoJson.git
synced 2025-11-01 16:14:05 +01:00
160 lines
3.7 KiB
C++
160 lines
3.7 KiB
C++
// Copyright Benoit Blanchon 2014-2016
|
|
// MIT License
|
|
//
|
|
// Arduino JSON library
|
|
// https://github.com/bblanchon/ArduinoJson
|
|
// If you like this project, please add a star!
|
|
|
|
#pragma once
|
|
|
|
#include "JsonBufferBase.hpp"
|
|
|
|
#include <stdlib.h>
|
|
|
|
#if defined(__clang__)
|
|
#pragma clang diagnostic push
|
|
#pragma clang diagnostic ignored "-Wnon-virtual-dtor"
|
|
#elif defined(__GNUC__)
|
|
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
|
|
#pragma GCC diagnostic push
|
|
#endif
|
|
#pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
|
|
#endif
|
|
|
|
namespace ArduinoJson {
|
|
class DefaultAllocator {
|
|
public:
|
|
void* allocate(size_t size) {
|
|
return malloc(size);
|
|
}
|
|
void deallocate(void* pointer) {
|
|
free(pointer);
|
|
}
|
|
};
|
|
|
|
template <typename TAllocator>
|
|
class DynamicJsonBufferBase
|
|
: public JsonBufferBase<DynamicJsonBufferBase<TAllocator> > {
|
|
struct Block;
|
|
struct EmptyBlock {
|
|
Block* next;
|
|
size_t capacity;
|
|
size_t size;
|
|
};
|
|
struct Block : EmptyBlock {
|
|
uint8_t data[1];
|
|
};
|
|
|
|
public:
|
|
DynamicJsonBufferBase(size_t initialSize = 256)
|
|
: _head(NULL), _nextBlockCapacity(initialSize) {}
|
|
|
|
~DynamicJsonBufferBase() {
|
|
Block* currentBlock = _head;
|
|
|
|
while (currentBlock != NULL) {
|
|
Block* nextBlock = currentBlock->next;
|
|
_allocator.deallocate(currentBlock);
|
|
currentBlock = nextBlock;
|
|
}
|
|
}
|
|
|
|
size_t size() const {
|
|
size_t total = 0;
|
|
for (const Block* b = _head; b; b = b->next) total += b->size;
|
|
return total;
|
|
}
|
|
|
|
virtual void* alloc(size_t bytes) {
|
|
alignNextAlloc();
|
|
return canAllocInHead(bytes) ? allocInHead(bytes) : allocInNewBlock(bytes);
|
|
}
|
|
|
|
class String {
|
|
public:
|
|
String(DynamicJsonBufferBase* 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);
|
|
newStart[_length] = c;
|
|
_start = newStart;
|
|
}
|
|
_length++;
|
|
}
|
|
|
|
const char* c_str() {
|
|
append(0);
|
|
return _start;
|
|
}
|
|
|
|
private:
|
|
DynamicJsonBufferBase* _parent;
|
|
char* _start;
|
|
int _length;
|
|
};
|
|
|
|
String startString() {
|
|
return String(this);
|
|
}
|
|
|
|
private:
|
|
void alignNextAlloc() {
|
|
if (_head) _head->size = this->round_size_up(_head->size);
|
|
}
|
|
|
|
bool canAllocInHead(size_t bytes) const {
|
|
return _head != NULL && _head->size + bytes <= _head->capacity;
|
|
}
|
|
|
|
void* allocInHead(size_t bytes) {
|
|
void* p = _head->data + _head->size;
|
|
_head->size += bytes;
|
|
return p;
|
|
}
|
|
|
|
void* allocInNewBlock(size_t bytes) {
|
|
size_t capacity = _nextBlockCapacity;
|
|
if (bytes > capacity) capacity = bytes;
|
|
if (!addNewBlock(capacity)) return NULL;
|
|
_nextBlockCapacity *= 2;
|
|
return allocInHead(bytes);
|
|
}
|
|
|
|
bool addNewBlock(size_t capacity) {
|
|
size_t bytes = sizeof(EmptyBlock) + capacity;
|
|
Block* block = static_cast<Block*>(_allocator.allocate(bytes));
|
|
if (block == NULL) return false;
|
|
block->capacity = capacity;
|
|
block->size = 0;
|
|
block->next = _head;
|
|
_head = block;
|
|
return true;
|
|
}
|
|
|
|
TAllocator _allocator;
|
|
Block* _head;
|
|
size_t _nextBlockCapacity;
|
|
};
|
|
|
|
#if defined(__clang__)
|
|
#pragma clang diagnostic pop
|
|
#elif defined(__GNUC__)
|
|
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
|
|
#pragma GCC diagnostic pop
|
|
#endif
|
|
#endif
|
|
|
|
// Implements a JsonBuffer with dynamic memory allocation.
|
|
// You are strongly encouraged to consider using StaticJsonBuffer which is much
|
|
// more suitable for embedded systems.
|
|
typedef DynamicJsonBufferBase<DefaultAllocator> DynamicJsonBuffer;
|
|
}
|