allocators.h
1 // Tencent is pleased to support the open source community by making RapidJSON available.
2 //
3 // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
4 //
5 // Licensed under the MIT License (the "License"); you may not use this file except
6 // in compliance with the License. You may obtain a copy of the License at
7 //
8 // http://opensource.org/licenses/MIT
9 //
10 // Unless required by applicable law or agreed to in writing, software distributed
11 // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
12 // CONDITIONS OF ANY KIND, either express or implied. See the License for the
13 // specific language governing permissions and limitations under the License.
14 
15 #ifndef RAPIDJSON_ALLOCATORS_H_
16 #define RAPIDJSON_ALLOCATORS_H_
17 
18 #include "rapidjson.h"
19 #include "internal/meta.h"
20 
21 #include <memory>
22 #include <limits>
23 
24 #if RAPIDJSON_HAS_CXX11
25 #include <type_traits>
26 #endif
27 
28 RAPIDJSON_NAMESPACE_BEGIN
29 
30 ///////////////////////////////////////////////////////////////////////////////
31 // Allocator
32 
33 /*! \class rapidjson::Allocator
34  \brief Concept for allocating, resizing and freeing memory block.
35 
36  Note that Malloc() and Realloc() are non-static but Free() is static.
37 
38  So if an allocator need to support Free(), it needs to put its pointer in
39  the header of memory block.
40 
41 \code
42 concept Allocator {
43  static const bool kNeedFree; //!< Whether this allocator needs to call Free().
44 
45  // Allocate a memory block.
46  // \param size of the memory block in bytes.
47  // \returns pointer to the memory block.
48  void* Malloc(size_t size);
49 
50  // Resize a memory block.
51  // \param originalPtr The pointer to current memory block. Null pointer is permitted.
52  // \param originalSize The current size in bytes. (Design issue: since some allocator may not book-keep this, explicitly pass to it can save memory.)
53  // \param newSize the new size in bytes.
54  void* Realloc(void* originalPtr, size_t originalSize, size_t newSize);
55 
56  // Free a memory block.
57  // \param pointer to the memory block. Null pointer is permitted.
58  static void Free(void *ptr);
59 };
60 \endcode
61 */
62 
63 
64 /*! \def RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY
65  \ingroup RAPIDJSON_CONFIG
66  \brief User-defined kDefaultChunkCapacity definition.
67 
68  User can define this as any \c size that is a power of 2.
69 */
70 
71 #ifndef RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY
72 #define RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY (64 * 1024)
73 #endif
74 
75 
76 ///////////////////////////////////////////////////////////////////////////////
77 // CrtAllocator
78 
79 //! C-runtime library allocator.
80 /*! This class is just wrapper for standard C library memory routines.
81  \note implements Allocator concept
82 */
83 class CrtAllocator {
84 public:
85  static const bool kNeedFree = true;
86  void* Malloc(size_t size) {
87  if (size) // behavior of malloc(0) is implementation defined.
88  return RAPIDJSON_MALLOC(size);
89  else
90  return NULL; // standardize to returning NULL.
91  }
92  void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) {
93  (void)originalSize;
94  if (newSize == 0) {
95  RAPIDJSON_FREE(originalPtr);
96  return NULL;
97  }
98  return RAPIDJSON_REALLOC(originalPtr, newSize);
99  }
100  static void Free(void *ptr) RAPIDJSON_NOEXCEPT { RAPIDJSON_FREE(ptr); }
101 
102  bool operator==(const CrtAllocator&) const RAPIDJSON_NOEXCEPT {
103  return true;
104  }
105  bool operator!=(const CrtAllocator&) const RAPIDJSON_NOEXCEPT {
106  return false;
107  }
108 };
109 
110 ///////////////////////////////////////////////////////////////////////////////
111 // MemoryPoolAllocator
112 
113 //! Default memory allocator used by the parser and DOM.
114 /*! This allocator allocate memory blocks from pre-allocated memory chunks.
115 
116  It does not free memory blocks. And Realloc() only allocate new memory.
117 
118  The memory chunks are allocated by BaseAllocator, which is CrtAllocator by default.
119 
120  User may also supply a buffer as the first chunk.
121 
122  If the user-buffer is full then additional chunks are allocated by BaseAllocator.
123 
124  The user-buffer is not deallocated by this allocator.
125 
126  \tparam BaseAllocator the allocator type for allocating memory chunks. Default is CrtAllocator.
127  \note implements Allocator concept
128 */
129 template <typename BaseAllocator = CrtAllocator>
131  //! Chunk header for perpending to each chunk.
132  /*! Chunks are stored as a singly linked list.
133  */
134  struct ChunkHeader {
135  size_t capacity; //!< Capacity of the chunk in bytes (excluding the header itself).
136  size_t size; //!< Current size of allocated memory in bytes.
137  ChunkHeader *next; //!< Next chunk in the linked list.
138  };
139 
140  struct SharedData {
141  ChunkHeader *chunkHead; //!< Head of the chunk linked-list. Only the head chunk serves allocation.
142  BaseAllocator* ownBaseAllocator; //!< base allocator created by this object.
143  size_t refcount;
144  bool ownBuffer;
145  };
146 
147  static const size_t SIZEOF_SHARED_DATA = RAPIDJSON_ALIGN(sizeof(SharedData));
148  static const size_t SIZEOF_CHUNK_HEADER = RAPIDJSON_ALIGN(sizeof(ChunkHeader));
149 
150  static inline ChunkHeader *GetChunkHead(SharedData *shared)
151  {
152  return reinterpret_cast<ChunkHeader*>(reinterpret_cast<uint8_t*>(shared) + SIZEOF_SHARED_DATA);
153  }
154  static inline uint8_t *GetChunkBuffer(SharedData *shared)
155  {
156  return reinterpret_cast<uint8_t*>(shared->chunkHead) + SIZEOF_CHUNK_HEADER;
157  }
158 
159  static const size_t kDefaultChunkCapacity = RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY; //!< Default chunk capacity.
160 
161 public:
162  static const bool kNeedFree = false; //!< Tell users that no need to call Free() with this allocator. (concept Allocator)
163  static const bool kRefCounted = true; //!< Tell users that this allocator is reference counted on copy
164 
165  //! Constructor with chunkSize.
166  /*! \param chunkSize The size of memory chunk. The default is kDefaultChunkSize.
167  \param baseAllocator The allocator for allocating memory chunks.
168  */
169  explicit
170  MemoryPoolAllocator(size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) :
171  chunk_capacity_(chunkSize),
172  baseAllocator_(baseAllocator ? baseAllocator : RAPIDJSON_NEW(BaseAllocator)()),
173  shared_(static_cast<SharedData*>(baseAllocator_ ? baseAllocator_->Malloc(SIZEOF_SHARED_DATA + SIZEOF_CHUNK_HEADER) : 0))
174  {
175  RAPIDJSON_ASSERT(baseAllocator_ != 0);
176  RAPIDJSON_ASSERT(shared_ != 0);
177  if (baseAllocator) {
178  shared_->ownBaseAllocator = 0;
179  }
180  else {
181  shared_->ownBaseAllocator = baseAllocator_;
182  }
183  shared_->chunkHead = GetChunkHead(shared_);
184  shared_->chunkHead->capacity = 0;
185  shared_->chunkHead->size = 0;
186  shared_->chunkHead->next = 0;
187  shared_->ownBuffer = true;
188  shared_->refcount = 1;
189  }
190 
191  //! Constructor with user-supplied buffer.
192  /*! The user buffer will be used firstly. When it is full, memory pool allocates new chunk with chunk size.
193 
194  The user buffer will not be deallocated when this allocator is destructed.
195 
196  \param buffer User supplied buffer.
197  \param size Size of the buffer in bytes. It must at least larger than sizeof(ChunkHeader).
198  \param chunkSize The size of memory chunk. The default is kDefaultChunkSize.
199  \param baseAllocator The allocator for allocating memory chunks.
200  */
201  MemoryPoolAllocator(void *buffer, size_t size, size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) :
202  chunk_capacity_(chunkSize),
203  baseAllocator_(baseAllocator),
204  shared_(static_cast<SharedData*>(AlignBuffer(buffer, size)))
205  {
206  RAPIDJSON_ASSERT(size >= SIZEOF_SHARED_DATA + SIZEOF_CHUNK_HEADER);
207  shared_->chunkHead = GetChunkHead(shared_);
208  shared_->chunkHead->capacity = size - SIZEOF_SHARED_DATA - SIZEOF_CHUNK_HEADER;
209  shared_->chunkHead->size = 0;
210  shared_->chunkHead->next = 0;
211  shared_->ownBaseAllocator = 0;
212  shared_->ownBuffer = false;
213  shared_->refcount = 1;
214  }
215 
216  MemoryPoolAllocator(const MemoryPoolAllocator& rhs) RAPIDJSON_NOEXCEPT :
217  chunk_capacity_(rhs.chunk_capacity_),
218  baseAllocator_(rhs.baseAllocator_),
219  shared_(rhs.shared_)
220  {
221  RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0);
222  ++shared_->refcount;
223  }
224  MemoryPoolAllocator& operator=(const MemoryPoolAllocator& rhs) RAPIDJSON_NOEXCEPT
225  {
226  RAPIDJSON_NOEXCEPT_ASSERT(rhs.shared_->refcount > 0);
227  ++rhs.shared_->refcount;
228  this->~MemoryPoolAllocator();
229  baseAllocator_ = rhs.baseAllocator_;
230  chunk_capacity_ = rhs.chunk_capacity_;
231  shared_ = rhs.shared_;
232  return *this;
233  }
234 
235 #if RAPIDJSON_HAS_CXX11_RVALUE_REFS
236  MemoryPoolAllocator(MemoryPoolAllocator&& rhs) RAPIDJSON_NOEXCEPT :
237  chunk_capacity_(rhs.chunk_capacity_),
238  baseAllocator_(rhs.baseAllocator_),
239  shared_(rhs.shared_)
240  {
241  RAPIDJSON_NOEXCEPT_ASSERT(rhs.shared_->refcount > 0);
242  rhs.shared_ = 0;
243  }
244  MemoryPoolAllocator& operator=(MemoryPoolAllocator&& rhs) RAPIDJSON_NOEXCEPT
245  {
246  RAPIDJSON_NOEXCEPT_ASSERT(rhs.shared_->refcount > 0);
247  this->~MemoryPoolAllocator();
248  baseAllocator_ = rhs.baseAllocator_;
249  chunk_capacity_ = rhs.chunk_capacity_;
250  shared_ = rhs.shared_;
251  rhs.shared_ = 0;
252  return *this;
253  }
254 #endif
255 
256  //! Destructor.
257  /*! This deallocates all memory chunks, excluding the user-supplied buffer.
258  */
259  ~MemoryPoolAllocator() RAPIDJSON_NOEXCEPT {
260  if (!shared_) {
261  // do nothing if moved
262  return;
263  }
264  if (shared_->refcount > 1) {
265  --shared_->refcount;
266  return;
267  }
268  Clear();
269  BaseAllocator *a = shared_->ownBaseAllocator;
270  if (shared_->ownBuffer) {
271  baseAllocator_->Free(shared_);
272  }
273  RAPIDJSON_DELETE(a);
274  }
275 
276  //! Deallocates all memory chunks, excluding the first/user one.
277  void Clear() RAPIDJSON_NOEXCEPT {
278  RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0);
279  for (;;) {
280  ChunkHeader* c = shared_->chunkHead;
281  if (!c->next) {
282  break;
283  }
284  shared_->chunkHead = c->next;
285  baseAllocator_->Free(c);
286  }
287  shared_->chunkHead->size = 0;
288  }
289 
290  //! Computes the total capacity of allocated memory chunks.
291  /*! \return total capacity in bytes.
292  */
293  size_t Capacity() const RAPIDJSON_NOEXCEPT {
294  RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0);
295  size_t capacity = 0;
296  for (ChunkHeader* c = shared_->chunkHead; c != 0; c = c->next)
297  capacity += c->capacity;
298  return capacity;
299  }
300 
301  //! Computes the memory blocks allocated.
302  /*! \return total used bytes.
303  */
304  size_t Size() const RAPIDJSON_NOEXCEPT {
305  RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0);
306  size_t size = 0;
307  for (ChunkHeader* c = shared_->chunkHead; c != 0; c = c->next)
308  size += c->size;
309  return size;
310  }
311 
312  //! Whether the allocator is shared.
313  /*! \return true or false.
314  */
315  bool Shared() const RAPIDJSON_NOEXCEPT {
316  RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0);
317  return shared_->refcount > 1;
318  }
319 
320  //! Allocates a memory block. (concept Allocator)
321  void* Malloc(size_t size) {
322  RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0);
323  if (!size)
324  return NULL;
325 
326  size = RAPIDJSON_ALIGN(size);
327  if (RAPIDJSON_UNLIKELY(shared_->chunkHead->size + size > shared_->chunkHead->capacity))
328  if (!AddChunk(chunk_capacity_ > size ? chunk_capacity_ : size))
329  return NULL;
330 
331  void *buffer = GetChunkBuffer(shared_) + shared_->chunkHead->size;
332  shared_->chunkHead->size += size;
333  return buffer;
334  }
335 
336  //! Resizes a memory block (concept Allocator)
337  void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) {
338  if (originalPtr == 0)
339  return Malloc(newSize);
340 
341  RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0);
342  if (newSize == 0)
343  return NULL;
344 
345  originalSize = RAPIDJSON_ALIGN(originalSize);
346  newSize = RAPIDJSON_ALIGN(newSize);
347 
348  // Do not shrink if new size is smaller than original
349  if (originalSize >= newSize)
350  return originalPtr;
351 
352  // Simply expand it if it is the last allocation and there is sufficient space
353  if (originalPtr == GetChunkBuffer(shared_) + shared_->chunkHead->size - originalSize) {
354  size_t increment = static_cast<size_t>(newSize - originalSize);
355  if (shared_->chunkHead->size + increment <= shared_->chunkHead->capacity) {
356  shared_->chunkHead->size += increment;
357  return originalPtr;
358  }
359  }
360 
361  // Realloc process: allocate and copy memory, do not free original buffer.
362  if (void* newBuffer = Malloc(newSize)) {
363  if (originalSize)
364  std::memcpy(newBuffer, originalPtr, originalSize);
365  return newBuffer;
366  }
367  else
368  return NULL;
369  }
370 
371  //! Frees a memory block (concept Allocator)
372  static void Free(void *ptr) RAPIDJSON_NOEXCEPT { (void)ptr; } // Do nothing
373 
374  //! Compare (equality) with another MemoryPoolAllocator
375  bool operator==(const MemoryPoolAllocator& rhs) const RAPIDJSON_NOEXCEPT {
376  RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0);
377  RAPIDJSON_NOEXCEPT_ASSERT(rhs.shared_->refcount > 0);
378  return shared_ == rhs.shared_;
379  }
380  //! Compare (inequality) with another MemoryPoolAllocator
381  bool operator!=(const MemoryPoolAllocator& rhs) const RAPIDJSON_NOEXCEPT {
382  return !operator==(rhs);
383  }
384 
385 private:
386  //! Creates a new chunk.
387  /*! \param capacity Capacity of the chunk in bytes.
388  \return true if success.
389  */
390  bool AddChunk(size_t capacity) {
391  if (!baseAllocator_)
392  shared_->ownBaseAllocator = baseAllocator_ = RAPIDJSON_NEW(BaseAllocator)();
393  if (ChunkHeader* chunk = static_cast<ChunkHeader*>(baseAllocator_->Malloc(SIZEOF_CHUNK_HEADER + capacity))) {
394  chunk->capacity = capacity;
395  chunk->size = 0;
396  chunk->next = shared_->chunkHead;
397  shared_->chunkHead = chunk;
398  return true;
399  }
400  else
401  return false;
402  }
403 
404  static inline void* AlignBuffer(void* buf, size_t &size)
405  {
406  RAPIDJSON_NOEXCEPT_ASSERT(buf != 0);
407  const uintptr_t mask = sizeof(void*) - 1;
408  const uintptr_t ubuf = reinterpret_cast<uintptr_t>(buf);
409  if (RAPIDJSON_UNLIKELY(ubuf & mask)) {
410  const uintptr_t abuf = (ubuf + mask) & ~mask;
411  RAPIDJSON_ASSERT(size >= abuf - ubuf);
412  buf = reinterpret_cast<void*>(abuf);
413  size -= abuf - ubuf;
414  }
415  return buf;
416  }
417 
418  size_t chunk_capacity_; //!< The minimum capacity of chunk when they are allocated.
419  BaseAllocator* baseAllocator_; //!< base allocator for allocating memory chunks.
420  SharedData *shared_; //!< The shared data of the allocator
421 };
422 
423 namespace internal {
424  template<typename, typename = void>
425  struct IsRefCounted :
426  public FalseType
427  { };
428  template<typename T>
429  struct IsRefCounted<T, typename internal::EnableIfCond<T::kRefCounted>::Type> :
430  public TrueType
431  { };
432 }
433 
434 template<typename T, typename A>
435 inline T* Realloc(A& a, T* old_p, size_t old_n, size_t new_n)
436 {
437  RAPIDJSON_NOEXCEPT_ASSERT(old_n <= (std::numeric_limits<size_t>::max)() / sizeof(T) && new_n <= (std::numeric_limits<size_t>::max)() / sizeof(T));
438  return static_cast<T*>(a.Realloc(old_p, old_n * sizeof(T), new_n * sizeof(T)));
439 }
440 
441 template<typename T, typename A>
442 inline T *Malloc(A& a, size_t n = 1)
443 {
444  return Realloc<T, A>(a, NULL, 0, n);
445 }
446 
447 template<typename T, typename A>
448 inline void Free(A& a, T *p, size_t n = 1)
449 {
450  static_cast<void>(Realloc<T, A>(a, p, n, 0));
451 }
452 
453 #ifdef __GNUC__
454 RAPIDJSON_DIAG_PUSH
455 RAPIDJSON_DIAG_OFF(effc++) // std::allocator can safely be inherited
456 #endif
457 
458 template <typename T, typename BaseAllocator = CrtAllocator>
460  public std::allocator<T>
461 {
462  typedef std::allocator<T> allocator_type;
463 #if RAPIDJSON_HAS_CXX11
464  typedef std::allocator_traits<allocator_type> traits_type;
465 #else
466  typedef allocator_type traits_type;
467 #endif
468 
469 public:
470  typedef BaseAllocator BaseAllocatorType;
471 
472  StdAllocator() RAPIDJSON_NOEXCEPT :
473  allocator_type(),
474  baseAllocator_()
475  { }
476 
477  StdAllocator(const StdAllocator& rhs) RAPIDJSON_NOEXCEPT :
478  allocator_type(rhs),
479  baseAllocator_(rhs.baseAllocator_)
480  { }
481 
482  template<typename U>
483  StdAllocator(const StdAllocator<U, BaseAllocator>& rhs) RAPIDJSON_NOEXCEPT :
484  allocator_type(rhs),
485  baseAllocator_(rhs.baseAllocator_)
486  { }
487 
488 #if RAPIDJSON_HAS_CXX11_RVALUE_REFS
489  StdAllocator(StdAllocator&& rhs) RAPIDJSON_NOEXCEPT :
490  allocator_type(std::move(rhs)),
491  baseAllocator_(std::move(rhs.baseAllocator_))
492  { }
493 #endif
494 #if RAPIDJSON_HAS_CXX11
495  using propagate_on_container_move_assignment = std::true_type;
496  using propagate_on_container_swap = std::true_type;
497 #endif
498 
499  /* implicit */
500  StdAllocator(const BaseAllocator& baseAllocator) RAPIDJSON_NOEXCEPT :
501  allocator_type(),
502  baseAllocator_(baseAllocator)
503  { }
504 
505  ~StdAllocator() RAPIDJSON_NOEXCEPT
506  { }
507 
508  template<typename U>
509  struct rebind {
511  };
512 
513  typedef typename traits_type::size_type size_type;
514  typedef typename traits_type::difference_type difference_type;
515 
516  typedef typename traits_type::value_type value_type;
517  typedef typename traits_type::pointer pointer;
518  typedef typename traits_type::const_pointer const_pointer;
519 
520 #if RAPIDJSON_HAS_CXX11
521 
522  typedef typename std::add_lvalue_reference<value_type>::type &reference;
523  typedef typename std::add_lvalue_reference<typename std::add_const<value_type>::type>::type &const_reference;
524 
525  pointer address(reference r) const RAPIDJSON_NOEXCEPT
526  {
527  return std::addressof(r);
528  }
529  const_pointer address(const_reference r) const RAPIDJSON_NOEXCEPT
530  {
531  return std::addressof(r);
532  }
533 
534  size_type max_size() const RAPIDJSON_NOEXCEPT
535  {
536  return traits_type::max_size(*this);
537  }
538 
539  template <typename ...Args>
540  void construct(pointer p, Args&&... args)
541  {
542  traits_type::construct(*this, p, std::forward<Args>(args)...);
543  }
544  void destroy(pointer p)
545  {
546  traits_type::destroy(*this, p);
547  }
548 
549 #else // !RAPIDJSON_HAS_CXX11
550 
551  typedef typename allocator_type::reference reference;
552  typedef typename allocator_type::const_reference const_reference;
553 
554  pointer address(reference r) const RAPIDJSON_NOEXCEPT
555  {
556  return allocator_type::address(r);
557  }
558  const_pointer address(const_reference r) const RAPIDJSON_NOEXCEPT
559  {
560  return allocator_type::address(r);
561  }
562 
563  size_type max_size() const RAPIDJSON_NOEXCEPT
564  {
565  return allocator_type::max_size();
566  }
567 
568  void construct(pointer p, const_reference r)
569  {
570  allocator_type::construct(p, r);
571  }
572  void destroy(pointer p)
573  {
574  allocator_type::destroy(p);
575  }
576 
577 #endif // !RAPIDJSON_HAS_CXX11
578 
579  template <typename U>
580  U* allocate(size_type n = 1, const void* = 0)
581  {
582  return RAPIDJSON_NAMESPACE::Malloc<U>(baseAllocator_, n);
583  }
584  template <typename U>
585  void deallocate(U* p, size_type n = 1)
586  {
587  RAPIDJSON_NAMESPACE::Free<U>(baseAllocator_, p, n);
588  }
589 
590  pointer allocate(size_type n = 1, const void* = 0)
591  {
592  return allocate<value_type>(n);
593  }
594  void deallocate(pointer p, size_type n = 1)
595  {
596  deallocate<value_type>(p, n);
597  }
598 
599 #if RAPIDJSON_HAS_CXX11
600  using is_always_equal = std::is_empty<BaseAllocator>;
601 #endif
602 
603  template<typename U>
604  bool operator==(const StdAllocator<U, BaseAllocator>& rhs) const RAPIDJSON_NOEXCEPT
605  {
606  return baseAllocator_ == rhs.baseAllocator_;
607  }
608  template<typename U>
609  bool operator!=(const StdAllocator<U, BaseAllocator>& rhs) const RAPIDJSON_NOEXCEPT
610  {
611  return !operator==(rhs);
612  }
613 
614  //! rapidjson Allocator concept
615  static const bool kNeedFree = BaseAllocator::kNeedFree;
616  static const bool kRefCounted = internal::IsRefCounted<BaseAllocator>::Value;
617  void* Malloc(size_t size)
618  {
619  return baseAllocator_.Malloc(size);
620  }
621  void* Realloc(void* originalPtr, size_t originalSize, size_t newSize)
622  {
623  return baseAllocator_.Realloc(originalPtr, originalSize, newSize);
624  }
625  static void Free(void *ptr) RAPIDJSON_NOEXCEPT
626  {
627  BaseAllocator::Free(ptr);
628  }
629 
630 private:
631  template <typename, typename>
632  friend class StdAllocator; // access to StdAllocator<!T>.*
633 
634  BaseAllocator baseAllocator_;
635 };
636 
637 #if !RAPIDJSON_HAS_CXX17 // std::allocator<void> deprecated in C++17
638 template <typename BaseAllocator>
639 class StdAllocator<void, BaseAllocator> :
640  public std::allocator<void>
641 {
642  typedef std::allocator<void> allocator_type;
643 
644 public:
645  typedef BaseAllocator BaseAllocatorType;
646 
647  StdAllocator() RAPIDJSON_NOEXCEPT :
648  allocator_type(),
649  baseAllocator_()
650  { }
651 
652  StdAllocator(const StdAllocator& rhs) RAPIDJSON_NOEXCEPT :
653  allocator_type(rhs),
654  baseAllocator_(rhs.baseAllocator_)
655  { }
656 
657  template<typename U>
658  StdAllocator(const StdAllocator<U, BaseAllocator>& rhs) RAPIDJSON_NOEXCEPT :
659  allocator_type(rhs),
660  baseAllocator_(rhs.baseAllocator_)
661  { }
662 
663  /* implicit */
664  StdAllocator(const BaseAllocator& baseAllocator) RAPIDJSON_NOEXCEPT :
665  allocator_type(),
666  baseAllocator_(baseAllocator)
667  { }
668 
669  ~StdAllocator() RAPIDJSON_NOEXCEPT
670  { }
671 
672  template<typename U>
673  struct rebind {
675  };
676 
677  typedef typename allocator_type::value_type value_type;
678 
679 private:
680  template <typename, typename>
681  friend class StdAllocator; // access to StdAllocator<!T>.*
682 
683  BaseAllocator baseAllocator_;
684 };
685 #endif
686 
687 #ifdef __GNUC__
688 RAPIDJSON_DIAG_POP
689 #endif
690 
691 RAPIDJSON_NAMESPACE_END
692 
693 #endif // RAPIDJSON_ENCODINGS_H_
GenericValue< UTF8<> > Value
GenericValue with UTF8 encoding.
Definition: document.h:2486
void * Realloc(void *originalPtr, size_t originalSize, size_t newSize)
Resizes a memory block (concept Allocator)
Definition: allocators.h:337
MemoryPoolAllocator(void *buffer, size_t size, size_t chunkSize=kDefaultChunkCapacity, BaseAllocator *baseAllocator=0)
Constructor with user-supplied buffer.
Definition: allocators.h:201
bool Shared() const RAPIDJSON_NOEXCEPT
Whether the allocator is shared.
Definition: allocators.h:315
void Clear() RAPIDJSON_NOEXCEPT
Deallocates all memory chunks, excluding the first/user one.
Definition: allocators.h:277
bool operator!=(const MemoryPoolAllocator &rhs) const RAPIDJSON_NOEXCEPT
Compare (inequality) with another MemoryPoolAllocator.
Definition: allocators.h:381
#define RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY
User-defined kDefaultChunkCapacity definition.
Definition: allocators.h:72
~MemoryPoolAllocator() RAPIDJSON_NOEXCEPT
Destructor.
Definition: allocators.h:259
#define RAPIDJSON_REALLOC(ptr, new_size)
! customization point for global realloc
Definition: rapidjson.h:700
MemoryPoolAllocator(size_t chunkSize=kDefaultChunkCapacity, BaseAllocator *baseAllocator=0)
Constructor with chunkSize.
Definition: allocators.h:170
C-runtime library allocator.
Definition: allocators.h:83
#define RAPIDJSON_MALLOC(size)
! customization point for global malloc
Definition: rapidjson.h:696
#define RAPIDJSON_NEW(TypeName)
! customization point for global new
Definition: rapidjson.h:712
#define RAPIDJSON_NOEXCEPT_ASSERT(x)
Assertion (in non-throwing contexts).
Definition: rapidjson.h:687
#define RAPIDJSON_FREE(ptr)
! customization point for global free
Definition: rapidjson.h:704
Type
Type of JSON value.
Definition: rapidjson.h:729
void * Malloc(size_t size)
Allocates a memory block. (concept Allocator)
Definition: allocators.h:321
#define RAPIDJSON_UNLIKELY(x)
Compiler branching hint for expression with low probability to be true.
Definition: rapidjson.h:507
#define RAPIDJSON_ALIGN(x)
Data alignment of the machine.
Definition: rapidjson.h:307
#define RAPIDJSON_DELETE(x)
! customization point for global delete
Definition: rapidjson.h:716
size_t Size() const RAPIDJSON_NOEXCEPT
Computes the memory blocks allocated.
Definition: allocators.h:304
bool operator==(const MemoryPoolAllocator &rhs) const RAPIDJSON_NOEXCEPT
Compare (equality) with another MemoryPoolAllocator.
Definition: allocators.h:375
common definitions and configuration
Definition: allocators.h:459
size_t Capacity() const RAPIDJSON_NOEXCEPT
Computes the total capacity of allocated memory chunks.
Definition: allocators.h:293
Default memory allocator used by the parser and DOM.
Definition: allocators.h:130
#define RAPIDJSON_ASSERT(x)
Assertion.
Definition: rapidjson.h:437
Definition: allocators.h:509
static void Free(void *ptr) RAPIDJSON_NOEXCEPT
Frees a memory block (concept Allocator)
Definition: allocators.h:372