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