1e462795ff5d4c7359f9e8637c10544bb2de70107tturney// Tencent is pleased to support the open source community by making RapidJSON available. 2e462795ff5d4c7359f9e8637c10544bb2de70107tturney// 3e462795ff5d4c7359f9e8637c10544bb2de70107tturney// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4e462795ff5d4c7359f9e8637c10544bb2de70107tturney// 5e462795ff5d4c7359f9e8637c10544bb2de70107tturney// Licensed under the MIT License (the "License"); you may not use this file except 6e462795ff5d4c7359f9e8637c10544bb2de70107tturney// in compliance with the License. You may obtain a copy of the License at 7e462795ff5d4c7359f9e8637c10544bb2de70107tturney// 8e462795ff5d4c7359f9e8637c10544bb2de70107tturney// http://opensource.org/licenses/MIT 9e462795ff5d4c7359f9e8637c10544bb2de70107tturney// 10e462795ff5d4c7359f9e8637c10544bb2de70107tturney// Unless required by applicable law or agreed to in writing, software distributed 11e462795ff5d4c7359f9e8637c10544bb2de70107tturney// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12e462795ff5d4c7359f9e8637c10544bb2de70107tturney// CONDITIONS OF ANY KIND, either express or implied. See the License for the 13e462795ff5d4c7359f9e8637c10544bb2de70107tturney// specific language governing permissions and limitations under the License. 14e462795ff5d4c7359f9e8637c10544bb2de70107tturney 15e462795ff5d4c7359f9e8637c10544bb2de70107tturney#ifndef RAPIDJSON_ALLOCATORS_H_ 16e462795ff5d4c7359f9e8637c10544bb2de70107tturney#define RAPIDJSON_ALLOCATORS_H_ 17e462795ff5d4c7359f9e8637c10544bb2de70107tturney 18e462795ff5d4c7359f9e8637c10544bb2de70107tturney#include "rapidjson.h" 19e462795ff5d4c7359f9e8637c10544bb2de70107tturney 20e462795ff5d4c7359f9e8637c10544bb2de70107tturneyRAPIDJSON_NAMESPACE_BEGIN 21e462795ff5d4c7359f9e8637c10544bb2de70107tturney 22e462795ff5d4c7359f9e8637c10544bb2de70107tturney/////////////////////////////////////////////////////////////////////////////// 23e462795ff5d4c7359f9e8637c10544bb2de70107tturney// Allocator 24e462795ff5d4c7359f9e8637c10544bb2de70107tturney 25e462795ff5d4c7359f9e8637c10544bb2de70107tturney/*! \class rapidjson::Allocator 26e462795ff5d4c7359f9e8637c10544bb2de70107tturney \brief Concept for allocating, resizing and freeing memory block. 27e462795ff5d4c7359f9e8637c10544bb2de70107tturney 28e462795ff5d4c7359f9e8637c10544bb2de70107tturney Note that Malloc() and Realloc() are non-static but Free() is static. 29e462795ff5d4c7359f9e8637c10544bb2de70107tturney 30e462795ff5d4c7359f9e8637c10544bb2de70107tturney So if an allocator need to support Free(), it needs to put its pointer in 31e462795ff5d4c7359f9e8637c10544bb2de70107tturney the header of memory block. 32e462795ff5d4c7359f9e8637c10544bb2de70107tturney 33e462795ff5d4c7359f9e8637c10544bb2de70107tturney\code 34e462795ff5d4c7359f9e8637c10544bb2de70107tturneyconcept Allocator { 35e462795ff5d4c7359f9e8637c10544bb2de70107tturney static const bool kNeedFree; //!< Whether this allocator needs to call Free(). 36e462795ff5d4c7359f9e8637c10544bb2de70107tturney 37e462795ff5d4c7359f9e8637c10544bb2de70107tturney // Allocate a memory block. 38e462795ff5d4c7359f9e8637c10544bb2de70107tturney // \param size of the memory block in bytes. 39e462795ff5d4c7359f9e8637c10544bb2de70107tturney // \returns pointer to the memory block. 40e462795ff5d4c7359f9e8637c10544bb2de70107tturney void* Malloc(size_t size); 41e462795ff5d4c7359f9e8637c10544bb2de70107tturney 42e462795ff5d4c7359f9e8637c10544bb2de70107tturney // Resize a memory block. 43e462795ff5d4c7359f9e8637c10544bb2de70107tturney // \param originalPtr The pointer to current memory block. Null pointer is permitted. 44e462795ff5d4c7359f9e8637c10544bb2de70107tturney // \param originalSize The current size in bytes. (Design issue: since some allocator may not book-keep this, explicitly pass to it can save memory.) 45e462795ff5d4c7359f9e8637c10544bb2de70107tturney // \param newSize the new size in bytes. 46e462795ff5d4c7359f9e8637c10544bb2de70107tturney void* Realloc(void* originalPtr, size_t originalSize, size_t newSize); 47e462795ff5d4c7359f9e8637c10544bb2de70107tturney 48e462795ff5d4c7359f9e8637c10544bb2de70107tturney // Free a memory block. 49e462795ff5d4c7359f9e8637c10544bb2de70107tturney // \param pointer to the memory block. Null pointer is permitted. 50e462795ff5d4c7359f9e8637c10544bb2de70107tturney static void Free(void *ptr); 51e462795ff5d4c7359f9e8637c10544bb2de70107tturney}; 52e462795ff5d4c7359f9e8637c10544bb2de70107tturney\endcode 53e462795ff5d4c7359f9e8637c10544bb2de70107tturney*/ 54e462795ff5d4c7359f9e8637c10544bb2de70107tturney 55e462795ff5d4c7359f9e8637c10544bb2de70107tturney/////////////////////////////////////////////////////////////////////////////// 56e462795ff5d4c7359f9e8637c10544bb2de70107tturney// CrtAllocator 57e462795ff5d4c7359f9e8637c10544bb2de70107tturney 58e462795ff5d4c7359f9e8637c10544bb2de70107tturney//! C-runtime library allocator. 59e462795ff5d4c7359f9e8637c10544bb2de70107tturney/*! This class is just wrapper for standard C library memory routines. 60e462795ff5d4c7359f9e8637c10544bb2de70107tturney \note implements Allocator concept 61e462795ff5d4c7359f9e8637c10544bb2de70107tturney*/ 62e462795ff5d4c7359f9e8637c10544bb2de70107tturneyclass CrtAllocator { 63e462795ff5d4c7359f9e8637c10544bb2de70107tturneypublic: 64e462795ff5d4c7359f9e8637c10544bb2de70107tturney static const bool kNeedFree = true; 65e462795ff5d4c7359f9e8637c10544bb2de70107tturney void* Malloc(size_t size) { 66e462795ff5d4c7359f9e8637c10544bb2de70107tturney if (size) // behavior of malloc(0) is implementation defined. 67e462795ff5d4c7359f9e8637c10544bb2de70107tturney return std::malloc(size); 68e462795ff5d4c7359f9e8637c10544bb2de70107tturney else 69e462795ff5d4c7359f9e8637c10544bb2de70107tturney return NULL; // standardize to returning NULL. 70e462795ff5d4c7359f9e8637c10544bb2de70107tturney } 71e462795ff5d4c7359f9e8637c10544bb2de70107tturney void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) { 72e462795ff5d4c7359f9e8637c10544bb2de70107tturney (void)originalSize; 73e462795ff5d4c7359f9e8637c10544bb2de70107tturney if (newSize == 0) { 74e462795ff5d4c7359f9e8637c10544bb2de70107tturney std::free(originalPtr); 75e462795ff5d4c7359f9e8637c10544bb2de70107tturney return NULL; 76e462795ff5d4c7359f9e8637c10544bb2de70107tturney } 77e462795ff5d4c7359f9e8637c10544bb2de70107tturney return std::realloc(originalPtr, newSize); 78e462795ff5d4c7359f9e8637c10544bb2de70107tturney } 79e462795ff5d4c7359f9e8637c10544bb2de70107tturney static void Free(void *ptr) { std::free(ptr); } 80e462795ff5d4c7359f9e8637c10544bb2de70107tturney}; 81e462795ff5d4c7359f9e8637c10544bb2de70107tturney 82e462795ff5d4c7359f9e8637c10544bb2de70107tturney/////////////////////////////////////////////////////////////////////////////// 83e462795ff5d4c7359f9e8637c10544bb2de70107tturney// MemoryPoolAllocator 84e462795ff5d4c7359f9e8637c10544bb2de70107tturney 85e462795ff5d4c7359f9e8637c10544bb2de70107tturney//! Default memory allocator used by the parser and DOM. 86e462795ff5d4c7359f9e8637c10544bb2de70107tturney/*! This allocator allocate memory blocks from pre-allocated memory chunks. 87e462795ff5d4c7359f9e8637c10544bb2de70107tturney 88e462795ff5d4c7359f9e8637c10544bb2de70107tturney It does not free memory blocks. And Realloc() only allocate new memory. 89e462795ff5d4c7359f9e8637c10544bb2de70107tturney 90e462795ff5d4c7359f9e8637c10544bb2de70107tturney The memory chunks are allocated by BaseAllocator, which is CrtAllocator by default. 91e462795ff5d4c7359f9e8637c10544bb2de70107tturney 92e462795ff5d4c7359f9e8637c10544bb2de70107tturney User may also supply a buffer as the first chunk. 93e462795ff5d4c7359f9e8637c10544bb2de70107tturney 94e462795ff5d4c7359f9e8637c10544bb2de70107tturney If the user-buffer is full then additional chunks are allocated by BaseAllocator. 95e462795ff5d4c7359f9e8637c10544bb2de70107tturney 96e462795ff5d4c7359f9e8637c10544bb2de70107tturney The user-buffer is not deallocated by this allocator. 97e462795ff5d4c7359f9e8637c10544bb2de70107tturney 98e462795ff5d4c7359f9e8637c10544bb2de70107tturney \tparam BaseAllocator the allocator type for allocating memory chunks. Default is CrtAllocator. 99e462795ff5d4c7359f9e8637c10544bb2de70107tturney \note implements Allocator concept 100e462795ff5d4c7359f9e8637c10544bb2de70107tturney*/ 101e462795ff5d4c7359f9e8637c10544bb2de70107tturneytemplate <typename BaseAllocator = CrtAllocator> 102e462795ff5d4c7359f9e8637c10544bb2de70107tturneyclass MemoryPoolAllocator { 103e462795ff5d4c7359f9e8637c10544bb2de70107tturneypublic: 104e462795ff5d4c7359f9e8637c10544bb2de70107tturney static const bool kNeedFree = false; //!< Tell users that no need to call Free() with this allocator. (concept Allocator) 105e462795ff5d4c7359f9e8637c10544bb2de70107tturney 106e462795ff5d4c7359f9e8637c10544bb2de70107tturney //! Constructor with chunkSize. 107e462795ff5d4c7359f9e8637c10544bb2de70107tturney /*! \param chunkSize The size of memory chunk. The default is kDefaultChunkSize. 108e462795ff5d4c7359f9e8637c10544bb2de70107tturney \param baseAllocator The allocator for allocating memory chunks. 109e462795ff5d4c7359f9e8637c10544bb2de70107tturney */ 110e462795ff5d4c7359f9e8637c10544bb2de70107tturney MemoryPoolAllocator(size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) : 111e462795ff5d4c7359f9e8637c10544bb2de70107tturney chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(0), baseAllocator_(baseAllocator), ownBaseAllocator_(0) 112e462795ff5d4c7359f9e8637c10544bb2de70107tturney { 113e462795ff5d4c7359f9e8637c10544bb2de70107tturney } 114e462795ff5d4c7359f9e8637c10544bb2de70107tturney 115e462795ff5d4c7359f9e8637c10544bb2de70107tturney //! Constructor with user-supplied buffer. 116e462795ff5d4c7359f9e8637c10544bb2de70107tturney /*! The user buffer will be used firstly. When it is full, memory pool allocates new chunk with chunk size. 117e462795ff5d4c7359f9e8637c10544bb2de70107tturney 118e462795ff5d4c7359f9e8637c10544bb2de70107tturney The user buffer will not be deallocated when this allocator is destructed. 119e462795ff5d4c7359f9e8637c10544bb2de70107tturney 120e462795ff5d4c7359f9e8637c10544bb2de70107tturney \param buffer User supplied buffer. 121e462795ff5d4c7359f9e8637c10544bb2de70107tturney \param size Size of the buffer in bytes. It must at least larger than sizeof(ChunkHeader). 122e462795ff5d4c7359f9e8637c10544bb2de70107tturney \param chunkSize The size of memory chunk. The default is kDefaultChunkSize. 123e462795ff5d4c7359f9e8637c10544bb2de70107tturney \param baseAllocator The allocator for allocating memory chunks. 124e462795ff5d4c7359f9e8637c10544bb2de70107tturney */ 125e462795ff5d4c7359f9e8637c10544bb2de70107tturney MemoryPoolAllocator(void *buffer, size_t size, size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) : 126e462795ff5d4c7359f9e8637c10544bb2de70107tturney chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(buffer), baseAllocator_(baseAllocator), ownBaseAllocator_(0) 127e462795ff5d4c7359f9e8637c10544bb2de70107tturney { 128e462795ff5d4c7359f9e8637c10544bb2de70107tturney RAPIDJSON_ASSERT(buffer != 0); 129e462795ff5d4c7359f9e8637c10544bb2de70107tturney RAPIDJSON_ASSERT(size > sizeof(ChunkHeader)); 130e462795ff5d4c7359f9e8637c10544bb2de70107tturney chunkHead_ = reinterpret_cast<ChunkHeader*>(buffer); 131e462795ff5d4c7359f9e8637c10544bb2de70107tturney chunkHead_->capacity = size - sizeof(ChunkHeader); 132e462795ff5d4c7359f9e8637c10544bb2de70107tturney chunkHead_->size = 0; 133e462795ff5d4c7359f9e8637c10544bb2de70107tturney chunkHead_->next = 0; 134e462795ff5d4c7359f9e8637c10544bb2de70107tturney } 135e462795ff5d4c7359f9e8637c10544bb2de70107tturney 136e462795ff5d4c7359f9e8637c10544bb2de70107tturney //! Destructor. 137e462795ff5d4c7359f9e8637c10544bb2de70107tturney /*! This deallocates all memory chunks, excluding the user-supplied buffer. 138e462795ff5d4c7359f9e8637c10544bb2de70107tturney */ 139e462795ff5d4c7359f9e8637c10544bb2de70107tturney ~MemoryPoolAllocator() { 140e462795ff5d4c7359f9e8637c10544bb2de70107tturney Clear(); 141e462795ff5d4c7359f9e8637c10544bb2de70107tturney RAPIDJSON_DELETE(ownBaseAllocator_); 142e462795ff5d4c7359f9e8637c10544bb2de70107tturney } 143e462795ff5d4c7359f9e8637c10544bb2de70107tturney 144e462795ff5d4c7359f9e8637c10544bb2de70107tturney //! Deallocates all memory chunks, excluding the user-supplied buffer. 145e462795ff5d4c7359f9e8637c10544bb2de70107tturney void Clear() { 146e462795ff5d4c7359f9e8637c10544bb2de70107tturney while (chunkHead_ && chunkHead_ != userBuffer_) { 147e462795ff5d4c7359f9e8637c10544bb2de70107tturney ChunkHeader* next = chunkHead_->next; 148e462795ff5d4c7359f9e8637c10544bb2de70107tturney baseAllocator_->Free(chunkHead_); 149e462795ff5d4c7359f9e8637c10544bb2de70107tturney chunkHead_ = next; 150e462795ff5d4c7359f9e8637c10544bb2de70107tturney } 151e462795ff5d4c7359f9e8637c10544bb2de70107tturney if (chunkHead_ && chunkHead_ == userBuffer_) 152e462795ff5d4c7359f9e8637c10544bb2de70107tturney chunkHead_->size = 0; // Clear user buffer 153e462795ff5d4c7359f9e8637c10544bb2de70107tturney } 154e462795ff5d4c7359f9e8637c10544bb2de70107tturney 155e462795ff5d4c7359f9e8637c10544bb2de70107tturney //! Computes the total capacity of allocated memory chunks. 156e462795ff5d4c7359f9e8637c10544bb2de70107tturney /*! \return total capacity in bytes. 157e462795ff5d4c7359f9e8637c10544bb2de70107tturney */ 158e462795ff5d4c7359f9e8637c10544bb2de70107tturney size_t Capacity() const { 159e462795ff5d4c7359f9e8637c10544bb2de70107tturney size_t capacity = 0; 160e462795ff5d4c7359f9e8637c10544bb2de70107tturney for (ChunkHeader* c = chunkHead_; c != 0; c = c->next) 161e462795ff5d4c7359f9e8637c10544bb2de70107tturney capacity += c->capacity; 162e462795ff5d4c7359f9e8637c10544bb2de70107tturney return capacity; 163e462795ff5d4c7359f9e8637c10544bb2de70107tturney } 164e462795ff5d4c7359f9e8637c10544bb2de70107tturney 165e462795ff5d4c7359f9e8637c10544bb2de70107tturney //! Computes the memory blocks allocated. 166e462795ff5d4c7359f9e8637c10544bb2de70107tturney /*! \return total used bytes. 167e462795ff5d4c7359f9e8637c10544bb2de70107tturney */ 168e462795ff5d4c7359f9e8637c10544bb2de70107tturney size_t Size() const { 169e462795ff5d4c7359f9e8637c10544bb2de70107tturney size_t size = 0; 170e462795ff5d4c7359f9e8637c10544bb2de70107tturney for (ChunkHeader* c = chunkHead_; c != 0; c = c->next) 171e462795ff5d4c7359f9e8637c10544bb2de70107tturney size += c->size; 172e462795ff5d4c7359f9e8637c10544bb2de70107tturney return size; 173e462795ff5d4c7359f9e8637c10544bb2de70107tturney } 174e462795ff5d4c7359f9e8637c10544bb2de70107tturney 175e462795ff5d4c7359f9e8637c10544bb2de70107tturney //! Allocates a memory block. (concept Allocator) 176e462795ff5d4c7359f9e8637c10544bb2de70107tturney void* Malloc(size_t size) { 177e462795ff5d4c7359f9e8637c10544bb2de70107tturney if (!size) 178e462795ff5d4c7359f9e8637c10544bb2de70107tturney return NULL; 179e462795ff5d4c7359f9e8637c10544bb2de70107tturney 180e462795ff5d4c7359f9e8637c10544bb2de70107tturney size = RAPIDJSON_ALIGN(size); 181e462795ff5d4c7359f9e8637c10544bb2de70107tturney if (chunkHead_ == 0 || chunkHead_->size + size > chunkHead_->capacity) 182e462795ff5d4c7359f9e8637c10544bb2de70107tturney AddChunk(chunk_capacity_ > size ? chunk_capacity_ : size); 183e462795ff5d4c7359f9e8637c10544bb2de70107tturney 184e462795ff5d4c7359f9e8637c10544bb2de70107tturney void *buffer = reinterpret_cast<char *>(chunkHead_) + RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + chunkHead_->size; 185e462795ff5d4c7359f9e8637c10544bb2de70107tturney chunkHead_->size += size; 186e462795ff5d4c7359f9e8637c10544bb2de70107tturney return buffer; 187e462795ff5d4c7359f9e8637c10544bb2de70107tturney } 188e462795ff5d4c7359f9e8637c10544bb2de70107tturney 189e462795ff5d4c7359f9e8637c10544bb2de70107tturney //! Resizes a memory block (concept Allocator) 190e462795ff5d4c7359f9e8637c10544bb2de70107tturney void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) { 191e462795ff5d4c7359f9e8637c10544bb2de70107tturney if (originalPtr == 0) 192e462795ff5d4c7359f9e8637c10544bb2de70107tturney return Malloc(newSize); 193e462795ff5d4c7359f9e8637c10544bb2de70107tturney 194e462795ff5d4c7359f9e8637c10544bb2de70107tturney if (newSize == 0) 195e462795ff5d4c7359f9e8637c10544bb2de70107tturney return NULL; 196e462795ff5d4c7359f9e8637c10544bb2de70107tturney 197e462795ff5d4c7359f9e8637c10544bb2de70107tturney // Do not shrink if new size is smaller than original 198e462795ff5d4c7359f9e8637c10544bb2de70107tturney if (originalSize >= newSize) 199e462795ff5d4c7359f9e8637c10544bb2de70107tturney return originalPtr; 200e462795ff5d4c7359f9e8637c10544bb2de70107tturney 201e462795ff5d4c7359f9e8637c10544bb2de70107tturney // Simply expand it if it is the last allocation and there is sufficient space 202e462795ff5d4c7359f9e8637c10544bb2de70107tturney if (originalPtr == (char *)(chunkHead_) + RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + chunkHead_->size - originalSize) { 203e462795ff5d4c7359f9e8637c10544bb2de70107tturney size_t increment = static_cast<size_t>(newSize - originalSize); 204e462795ff5d4c7359f9e8637c10544bb2de70107tturney increment = RAPIDJSON_ALIGN(increment); 205e462795ff5d4c7359f9e8637c10544bb2de70107tturney if (chunkHead_->size + increment <= chunkHead_->capacity) { 206e462795ff5d4c7359f9e8637c10544bb2de70107tturney chunkHead_->size += increment; 207e462795ff5d4c7359f9e8637c10544bb2de70107tturney return originalPtr; 208e462795ff5d4c7359f9e8637c10544bb2de70107tturney } 209e462795ff5d4c7359f9e8637c10544bb2de70107tturney } 210e462795ff5d4c7359f9e8637c10544bb2de70107tturney 211e462795ff5d4c7359f9e8637c10544bb2de70107tturney // Realloc process: allocate and copy memory, do not free original buffer. 212e462795ff5d4c7359f9e8637c10544bb2de70107tturney void* newBuffer = Malloc(newSize); 213e462795ff5d4c7359f9e8637c10544bb2de70107tturney RAPIDJSON_ASSERT(newBuffer != 0); // Do not handle out-of-memory explicitly. 214e462795ff5d4c7359f9e8637c10544bb2de70107tturney if (originalSize) 215e462795ff5d4c7359f9e8637c10544bb2de70107tturney std::memcpy(newBuffer, originalPtr, originalSize); 216e462795ff5d4c7359f9e8637c10544bb2de70107tturney return newBuffer; 217e462795ff5d4c7359f9e8637c10544bb2de70107tturney } 218e462795ff5d4c7359f9e8637c10544bb2de70107tturney 219e462795ff5d4c7359f9e8637c10544bb2de70107tturney //! Frees a memory block (concept Allocator) 220e462795ff5d4c7359f9e8637c10544bb2de70107tturney static void Free(void *ptr) { (void)ptr; } // Do nothing 221e462795ff5d4c7359f9e8637c10544bb2de70107tturney 222e462795ff5d4c7359f9e8637c10544bb2de70107tturneyprivate: 223e462795ff5d4c7359f9e8637c10544bb2de70107tturney //! Copy constructor is not permitted. 224e462795ff5d4c7359f9e8637c10544bb2de70107tturney MemoryPoolAllocator(const MemoryPoolAllocator& rhs) /* = delete */; 225e462795ff5d4c7359f9e8637c10544bb2de70107tturney //! Copy assignment operator is not permitted. 226e462795ff5d4c7359f9e8637c10544bb2de70107tturney MemoryPoolAllocator& operator=(const MemoryPoolAllocator& rhs) /* = delete */; 227e462795ff5d4c7359f9e8637c10544bb2de70107tturney 228e462795ff5d4c7359f9e8637c10544bb2de70107tturney //! Creates a new chunk. 229e462795ff5d4c7359f9e8637c10544bb2de70107tturney /*! \param capacity Capacity of the chunk in bytes. 230e462795ff5d4c7359f9e8637c10544bb2de70107tturney */ 231e462795ff5d4c7359f9e8637c10544bb2de70107tturney void AddChunk(size_t capacity) { 232e462795ff5d4c7359f9e8637c10544bb2de70107tturney if (!baseAllocator_) 233e462795ff5d4c7359f9e8637c10544bb2de70107tturney ownBaseAllocator_ = baseAllocator_ = RAPIDJSON_NEW(BaseAllocator()); 234e462795ff5d4c7359f9e8637c10544bb2de70107tturney ChunkHeader* chunk = reinterpret_cast<ChunkHeader*>(baseAllocator_->Malloc(RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + capacity)); 235e462795ff5d4c7359f9e8637c10544bb2de70107tturney chunk->capacity = capacity; 236e462795ff5d4c7359f9e8637c10544bb2de70107tturney chunk->size = 0; 237e462795ff5d4c7359f9e8637c10544bb2de70107tturney chunk->next = chunkHead_; 238e462795ff5d4c7359f9e8637c10544bb2de70107tturney chunkHead_ = chunk; 239e462795ff5d4c7359f9e8637c10544bb2de70107tturney } 240e462795ff5d4c7359f9e8637c10544bb2de70107tturney 241e462795ff5d4c7359f9e8637c10544bb2de70107tturney static const int kDefaultChunkCapacity = 64 * 1024; //!< Default chunk capacity. 242e462795ff5d4c7359f9e8637c10544bb2de70107tturney 243e462795ff5d4c7359f9e8637c10544bb2de70107tturney //! Chunk header for perpending to each chunk. 244e462795ff5d4c7359f9e8637c10544bb2de70107tturney /*! Chunks are stored as a singly linked list. 245e462795ff5d4c7359f9e8637c10544bb2de70107tturney */ 246e462795ff5d4c7359f9e8637c10544bb2de70107tturney struct ChunkHeader { 247e462795ff5d4c7359f9e8637c10544bb2de70107tturney size_t capacity; //!< Capacity of the chunk in bytes (excluding the header itself). 248e462795ff5d4c7359f9e8637c10544bb2de70107tturney size_t size; //!< Current size of allocated memory in bytes. 249e462795ff5d4c7359f9e8637c10544bb2de70107tturney ChunkHeader *next; //!< Next chunk in the linked list. 250e462795ff5d4c7359f9e8637c10544bb2de70107tturney }; 251e462795ff5d4c7359f9e8637c10544bb2de70107tturney 252e462795ff5d4c7359f9e8637c10544bb2de70107tturney ChunkHeader *chunkHead_; //!< Head of the chunk linked-list. Only the head chunk serves allocation. 253e462795ff5d4c7359f9e8637c10544bb2de70107tturney size_t chunk_capacity_; //!< The minimum capacity of chunk when they are allocated. 254e462795ff5d4c7359f9e8637c10544bb2de70107tturney void *userBuffer_; //!< User supplied buffer. 255e462795ff5d4c7359f9e8637c10544bb2de70107tturney BaseAllocator* baseAllocator_; //!< base allocator for allocating memory chunks. 256e462795ff5d4c7359f9e8637c10544bb2de70107tturney BaseAllocator* ownBaseAllocator_; //!< base allocator created by this object. 257e462795ff5d4c7359f9e8637c10544bb2de70107tturney}; 258e462795ff5d4c7359f9e8637c10544bb2de70107tturney 259e462795ff5d4c7359f9e8637c10544bb2de70107tturneyRAPIDJSON_NAMESPACE_END 260e462795ff5d4c7359f9e8637c10544bb2de70107tturney 261e462795ff5d4c7359f9e8637c10544bb2de70107tturney#endif // RAPIDJSON_ENCODINGS_H_ 262