16#ifndef RAPIDJSON_ALLOCATORS_H_
17#define RAPIDJSON_ALLOCATORS_H_
20#include "internal/meta.h"
25#if RAPIDJSON_HAS_CXX11
72#ifndef RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY
73#define RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY (64 * 1024)
86 static const bool kNeedFree =
true;
87 void* Malloc(
size_t size) {
93 void* Realloc(
void* originalPtr,
size_t originalSize,
size_t newSize) {
101 static void Free(
void *ptr) RAPIDJSON_NOEXCEPT {
RAPIDJSON_FREE(ptr); }
103 bool operator==(
const CrtAllocator&)
const RAPIDJSON_NOEXCEPT {
106 bool operator!=(
const CrtAllocator&)
const RAPIDJSON_NOEXCEPT {
130template <
typename BaseAllocator = CrtAllocator>
153 return reinterpret_cast<ChunkHeader*
>(
reinterpret_cast<uint8_t*
>(shared) + SIZEOF_SHARED_DATA);
155 static inline uint8_t *GetChunkBuffer(SharedData *shared)
157 return reinterpret_cast<uint8_t*
>(shared->chunkHead) + SIZEOF_CHUNK_HEADER;
185 shared_->chunkHead->capacity = 0;
209 shared_->chunkHead->capacity = size - SIZEOF_SHARED_DATA - SIZEOF_CHUNK_HEADER;
228 ++rhs.shared_->refcount;
236#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
270 BaseAllocator *a =
shared_->ownBaseAllocator;
298 capacity += c->capacity;
305 size_t Size() const RAPIDJSON_NOEXCEPT {
332 void *buffer = GetChunkBuffer(
shared_) +
shared_->chunkHead->size;
333 shared_->chunkHead->size += size;
338 void*
Realloc(
void* originalPtr,
size_t originalSize,
size_t newSize) {
339 if (originalPtr == 0)
350 if (originalSize >= newSize)
354 if (originalPtr == GetChunkBuffer(
shared_) +
shared_->chunkHead->size - originalSize) {
355 size_t increment =
static_cast<size_t>(newSize - originalSize);
356 if (
shared_->chunkHead->size + increment <= shared_->chunkHead->capacity) {
357 shared_->chunkHead->size += increment;
363 if (
void* newBuffer =
Malloc(newSize)) {
365 std::memcpy(newBuffer, originalPtr, originalSize);
373 static void Free(
void *ptr) RAPIDJSON_NOEXCEPT { (void)ptr; }
395 chunk->capacity = capacity;
397 chunk->next =
shared_->chunkHead;
405 static inline void* AlignBuffer(
void* buf,
size_t &size)
408 const uintptr_t mask =
sizeof(
void*) - 1;
409 const uintptr_t ubuf =
reinterpret_cast<uintptr_t
>(buf);
411 const uintptr_t abuf = (ubuf + mask) & ~mask;
413 buf =
reinterpret_cast<void*
>(abuf);
425 template<
typename,
typename =
void>
435template<
typename T,
typename A>
436inline T* Realloc(A& a, T* old_p,
size_t old_n,
size_t new_n)
438 RAPIDJSON_NOEXCEPT_ASSERT(old_n <= (std::numeric_limits<size_t>::max)() /
sizeof(T) && new_n <= (std::numeric_limits<size_t>::max)() /
sizeof(T));
439 return static_cast<T*
>(a.Realloc(old_p, old_n *
sizeof(T), new_n *
sizeof(T)));
442template<
typename T,
typename A>
443inline T *Malloc(A& a,
size_t n = 1)
445 return Realloc<T, A>(a, NULL, 0, n);
448template<
typename T,
typename A>
449inline void Free(A& a, T *p,
size_t n = 1)
451 static_cast<void>(Realloc<T, A>(a, p, n, 0));
456RAPIDJSON_DIAG_OFF(effc++)
459template <
typename T,
typename BaseAllocator = CrtAllocator>
461 public std::allocator<T>
463 typedef std::allocator<T> allocator_type;
464#if RAPIDJSON_HAS_CXX11
465 typedef std::allocator_traits<allocator_type> traits_type;
467 typedef allocator_type traits_type;
471 typedef BaseAllocator BaseAllocatorType;
473 StdAllocator() RAPIDJSON_NOEXCEPT :
478 StdAllocator(
const StdAllocator& rhs) RAPIDJSON_NOEXCEPT :
480 baseAllocator_(rhs.baseAllocator_)
484 StdAllocator(
const StdAllocator<U, BaseAllocator>& rhs) RAPIDJSON_NOEXCEPT :
486 baseAllocator_(rhs.baseAllocator_)
489#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
490 StdAllocator(StdAllocator&& rhs) RAPIDJSON_NOEXCEPT :
491 allocator_type(std::move(rhs)),
492 baseAllocator_(std::move(rhs.baseAllocator_))
495#if RAPIDJSON_HAS_CXX11
496 using propagate_on_container_move_assignment = std::true_type;
497 using propagate_on_container_swap = std::true_type;
501 StdAllocator(
const BaseAllocator& baseAllocator) RAPIDJSON_NOEXCEPT :
503 baseAllocator_(baseAllocator)
506 ~StdAllocator() RAPIDJSON_NOEXCEPT
511 typedef StdAllocator<U, BaseAllocator> other;
514 typedef typename traits_type::size_type size_type;
515 typedef typename traits_type::difference_type difference_type;
517 typedef typename traits_type::value_type value_type;
518 typedef typename traits_type::pointer pointer;
519 typedef typename traits_type::const_pointer const_pointer;
521#if RAPIDJSON_HAS_CXX11
523 typedef typename std::add_lvalue_reference<value_type>::type &reference;
524 typedef typename std::add_lvalue_reference<typename std::add_const<value_type>::type>::type &const_reference;
526 pointer address(reference r)
const RAPIDJSON_NOEXCEPT
528 return std::addressof(r);
530 const_pointer address(const_reference r)
const RAPIDJSON_NOEXCEPT
532 return std::addressof(r);
535 size_type max_size() const RAPIDJSON_NOEXCEPT
537 return traits_type::max_size(*
this);
540 template <
typename ...Args>
541 void construct(pointer p, Args&&... args)
543 traits_type::construct(*
this, p, std::forward<Args>(args)...);
545 void destroy(pointer p)
547 traits_type::destroy(*
this, p);
552 typedef typename allocator_type::reference reference;
553 typedef typename allocator_type::const_reference const_reference;
555 pointer address(reference r)
const RAPIDJSON_NOEXCEPT
557 return allocator_type::address(r);
559 const_pointer address(const_reference r)
const RAPIDJSON_NOEXCEPT
561 return allocator_type::address(r);
564 size_type max_size() const RAPIDJSON_NOEXCEPT
566 return allocator_type::max_size();
569 void construct(pointer p, const_reference r)
571 allocator_type::construct(p, r);
573 void destroy(pointer p)
575 allocator_type::destroy(p);
580 template <
typename U>
581 U* allocate(size_type n = 1,
const void* = 0)
583 return RAPIDJSON_NAMESPACE::Malloc<U>(baseAllocator_, n);
585 template <
typename U>
586 void deallocate(U* p, size_type n = 1)
588 RAPIDJSON_NAMESPACE::Free<U>(baseAllocator_, p, n);
591 pointer allocate(size_type n = 1,
const void* = 0)
593 return allocate<value_type>(n);
595 void deallocate(pointer p, size_type n = 1)
597 deallocate<value_type>(p, n);
600#if RAPIDJSON_HAS_CXX11
601 using is_always_equal = std::is_empty<BaseAllocator>;
605 bool operator==(
const StdAllocator<U, BaseAllocator>& rhs)
const RAPIDJSON_NOEXCEPT
607 return baseAllocator_ == rhs.baseAllocator_;
610 bool operator!=(
const StdAllocator<U, BaseAllocator>& rhs)
const RAPIDJSON_NOEXCEPT
612 return !operator==(rhs);
618 void* Malloc(
size_t size)
620 return baseAllocator_.Malloc(size);
622 void* Realloc(
void* originalPtr,
size_t originalSize,
size_t newSize)
624 return baseAllocator_.Realloc(originalPtr, originalSize, newSize);
626 static void Free(
void *ptr) RAPIDJSON_NOEXCEPT
628 BaseAllocator::Free(ptr);
632 template <
typename,
typename>
633 friend class StdAllocator;
635 BaseAllocator baseAllocator_;
638#if !RAPIDJSON_HAS_CXX17
639template <
typename BaseAllocator>
640class StdAllocator<void, BaseAllocator> :
641 public std::allocator<void>
643 typedef std::allocator<void> allocator_type;
646 typedef BaseAllocator BaseAllocatorType;
648 StdAllocator() RAPIDJSON_NOEXCEPT :
653 StdAllocator(
const StdAllocator& rhs) RAPIDJSON_NOEXCEPT :
655 baseAllocator_(rhs.baseAllocator_)
659 StdAllocator(
const StdAllocator<U, BaseAllocator>& rhs) RAPIDJSON_NOEXCEPT :
661 baseAllocator_(rhs.baseAllocator_)
665 StdAllocator(
const BaseAllocator& baseAllocator) RAPIDJSON_NOEXCEPT :
667 baseAllocator_(baseAllocator)
670 ~StdAllocator() RAPIDJSON_NOEXCEPT
675 typedef StdAllocator<U, BaseAllocator> other;
678 typedef typename allocator_type::value_type value_type;
681 template <
typename,
typename>
682 friend class StdAllocator;
684 BaseAllocator baseAllocator_;
C-runtime library allocator.
Default memory allocator used by the parser and DOM.
SharedData * shared_
The shared data of the allocator.
MemoryPoolAllocator(void *buffer, size_t size, size_t chunkSize=kDefaultChunkCapacity, BaseAllocator *baseAllocator=0)
Constructor with user-supplied buffer.
static const bool kRefCounted
Tell users that this allocator is reference counted on copy.
bool AddChunk(size_t capacity)
Creates a new chunk.
size_t Size() const RAPIDJSON_NOEXCEPT
Computes the memory blocks allocated.
size_t Capacity() const RAPIDJSON_NOEXCEPT
Computes the total capacity of allocated memory chunks.
BaseAllocator * baseAllocator_
base allocator for allocating memory chunks.
size_t chunk_capacity_
The minimum capacity of chunk when they are allocated.
void Clear() RAPIDJSON_NOEXCEPT
Deallocates all memory chunks, excluding the first/user one.
void * Realloc(void *originalPtr, size_t originalSize, size_t newSize)
Resizes a memory block (concept Allocator)
void * Malloc(size_t size)
Allocates a memory block. (concept Allocator)
static const size_t kDefaultChunkCapacity
Default chunk capacity.
bool operator==(const MemoryPoolAllocator &rhs) const RAPIDJSON_NOEXCEPT
Compare (equality) with another MemoryPoolAllocator.
static void Free(void *ptr) RAPIDJSON_NOEXCEPT
Frees a memory block (concept Allocator)
static const bool kNeedFree
Tell users that no need to call Free() with this allocator. (concept Allocator)
bool operator!=(const MemoryPoolAllocator &rhs) const RAPIDJSON_NOEXCEPT
Compare (inequality) with another MemoryPoolAllocator.
bool Shared() const RAPIDJSON_NOEXCEPT
Whether the allocator is shared.
MemoryPoolAllocator(size_t chunkSize=kDefaultChunkCapacity, BaseAllocator *baseAllocator=0)
Constructor with chunkSize.
~MemoryPoolAllocator() RAPIDJSON_NOEXCEPT
Destructor.
static const bool kNeedFree
#define RAPIDJSON_NOEXCEPT_ASSERT(x)
Assertion (in non-throwing contexts).
#define RAPIDJSON_ALIGN(x)
Data alignment of the machine.
#define RAPIDJSON_UNLIKELY(x)
Compiler branching hint for expression with low probability to be true.
#define RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY
User-defined kDefaultChunkCapacity definition.
#define RAPIDJSON_ASSERT(x)
Assertion.
#define RAPIDJSON_NAMESPACE_BEGIN
provide custom rapidjson namespace (opening expression)
#define RAPIDJSON_NAMESPACE_END
provide custom rapidjson namespace (closing expression)
common definitions and configuration
#define RAPIDJSON_MALLOC(size)
! customization point for global malloc
#define RAPIDJSON_DELETE(x)
! customization point for global delete
#define RAPIDJSON_REALLOC(ptr, new_size)
! customization point for global realloc
#define RAPIDJSON_FREE(ptr)
! customization point for global free
#define RAPIDJSON_NEW(TypeName)
! customization point for global new
ChunkHeader * chunkHead
Head of the chunk linked-list. Only the head chunk serves allocation.
BaseAllocator * ownBaseAllocator
base allocator created by this object.