Skip to content

Commit

Permalink
Merge 41e5efe into e80257a
Browse files Browse the repository at this point in the history
  • Loading branch information
ylavic committed Apr 11, 2019
2 parents e80257a + 41e5efe commit fc2a001
Show file tree
Hide file tree
Showing 7 changed files with 996 additions and 70 deletions.
502 changes: 502 additions & 0 deletions bin/types/alotofkeys.json

Large diffs are not rendered by default.

169 changes: 165 additions & 4 deletions include/rapidjson/allocators.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,18 @@

#include "rapidjson.h"

#include <memory>
#if RAPIDJSON_HAS_CXX11
#include <type_traits>
#endif

RAPIDJSON_NAMESPACE_BEGIN

RAPIDJSON_DIAG_PUSH
#ifdef __GNUC__
RAPIDJSON_DIAG_OFF(effc++)
#endif

///////////////////////////////////////////////////////////////////////////////
// Allocator

Expand Down Expand Up @@ -64,6 +74,144 @@ concept Allocator {
#define RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY (64 * 1024)
#endif

template <typename ValueType, typename Allocator>
class StdBaseAllocator {
public:
typedef ValueType value_type;

typedef value_type* pointer;
typedef const value_type* const_pointer;

typedef value_type& reference;
typedef const value_type& const_reference;

typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;

template<typename OtherType>
struct rebind {
typedef StdBaseAllocator<OtherType, Allocator> other;
};

StdBaseAllocator(Allocator &allocator) RAPIDJSON_NOEXCEPT :
allocator_(&allocator) {
}

StdBaseAllocator(const StdBaseAllocator& other) RAPIDJSON_NOEXCEPT :
allocator_(other.allocator_) {
}

template<typename OtherType>
StdBaseAllocator(const StdBaseAllocator<OtherType, Allocator>& other) RAPIDJSON_NOEXCEPT :
allocator_(other.allocator_) {
}

#if RAPIDJSON_HAS_CXX11
StdBaseAllocator(StdBaseAllocator&& other) RAPIDJSON_NOEXCEPT :
allocator_(other.allocator_) {
}
using propagate_on_container_move_assignment = std::true_type;
using is_always_equal = std::is_empty<Allocator>;
#endif

size_type max_size() const RAPIDJSON_NOEXCEPT {
return static_cast<size_type>(-1) / sizeof(value_type);
}

pointer address(reference x) const RAPIDJSON_NOEXCEPT {
return &x;
}
const_pointer address(const_reference x) const RAPIDJSON_NOEXCEPT {
return &x;
}

pointer allocate(size_type n = 1, const void* hint = 0) {
static_cast<void>(hint); // unused
return Reallocate(NULL, 0, n);
}

void deallocate(pointer p, size_type n = 1) {
static_cast<void>(Reallocate(p, n, 0));
}
template<typename OtherType>
void deallocate(OtherType* p, size_type n = 1) {
static_cast<void>(Reallocate(p, n, 0));
}

void construct(pointer p, const_reference r) {
::new(static_cast<void*>(p)) value_type(r);
}
#if RAPIDJSON_HAS_CXX11
template<typename OtherType, typename... Args>
void construct(OtherType* p, Args&&... args) {
::new(static_cast<void*>(p)) OtherType(std::forward<Args>(args)...);
}
#endif

void destroy(pointer p) {
p->~value_type();
}
template<typename OtherType>
void destroy(OtherType* p) {
p->~OtherType();
}

// Rapidjson's style
template<typename OtherType>
OtherType* Allocate(size_type n = 1) {
typename rebind<OtherType>::other a(*this);
return a.Reallocate(NULL, 0, n);
}
template<typename OtherType>
OtherType* Reallocate(OtherType* old, size_type old_n, size_type new_n) {
typename rebind<OtherType>::other a(*this);
return a.Reallocate(old, old_n, new_n);
}
pointer Reallocate(pointer old, size_type old_n, size_type new_n) {
RAPIDJSON_ASSERT(sizeof(value_type) == 1 || new_n <= max_size());
return static_cast<pointer>(allocator_->Realloc(old, old_n * sizeof(value_type),
new_n * sizeof(value_type)));
}

#if RAPIDJSON_HAS_CXX11
template<typename OtherType, typename... Args>
OtherType *New(Args&&... args) {
typename rebind<OtherType>::other a(*this);
return a.construct(a.allocate(1), std::forward<Args>(args)...);
}
template<typename OtherType>
void Delete(OtherType *p) {
if (!p)
return;
typename rebind<OtherType>::other a(*this);
a.destroy(p);
a.deallocate(p);
}
#endif

private:
Allocator *allocator_;

StdBaseAllocator() /* = delete */;

// For OtherType::allocator_
template <typename, typename>
friend class StdBaseAllocator;
template<typename T1, typename T2, typename A>
friend bool operator==(const StdBaseAllocator<T1, A>& a1,
const StdBaseAllocator<T2, A>& a2) RAPIDJSON_NOEXCEPT;
};

template<typename T1, typename T2, typename A>
bool operator==(const StdBaseAllocator<T1, A>& a1,
const StdBaseAllocator<T2, A>& a2) RAPIDJSON_NOEXCEPT {
return a1.allocator_ == a2.allocator_;
}
template<typename T1, typename T2, typename A>
bool operator!=(const StdBaseAllocator<T1, A>& a1,
const StdBaseAllocator<T2, A>& a2) RAPIDJSON_NOEXCEPT {
return !(a1 == a2);
}

///////////////////////////////////////////////////////////////////////////////
// CrtAllocator
Expand All @@ -72,9 +220,15 @@ concept Allocator {
/*! This class is just wrapper for standard C library memory routines.
\note implements Allocator concept
*/
class CrtAllocator {
class CrtAllocator : public StdBaseAllocator<unsigned char, CrtAllocator> {
typedef StdBaseAllocator<unsigned char, CrtAllocator> StdBaseAllocatorType;
public:
static const bool kNeedFree = true;

CrtAllocator() RAPIDJSON_NOEXCEPT :
StdBaseAllocatorType(*this) {
}

void* Malloc(size_t size) {
if (size) // behavior of malloc(0) is implementation defined.
return std::malloc(size);
Expand Down Expand Up @@ -112,7 +266,8 @@ class CrtAllocator {
\note implements Allocator concept
*/
template <typename BaseAllocator = CrtAllocator>
class MemoryPoolAllocator {
class MemoryPoolAllocator : public StdBaseAllocator<unsigned char, MemoryPoolAllocator<BaseAllocator> > {
typedef StdBaseAllocator<unsigned char, MemoryPoolAllocator<BaseAllocator> > StdBaseAllocatorType;
public:
static const bool kNeedFree = false; //!< Tell users that no need to call Free() with this allocator. (concept Allocator)

Expand All @@ -121,7 +276,9 @@ class MemoryPoolAllocator {
\param baseAllocator The allocator for allocating memory chunks.
*/
MemoryPoolAllocator(size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) :
chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(0), baseAllocator_(baseAllocator), ownBaseAllocator_(0)
StdBaseAllocatorType(*this),
chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(0),
baseAllocator_(baseAllocator), ownBaseAllocator_(0)
{
}

Expand All @@ -136,7 +293,9 @@ class MemoryPoolAllocator {
\param baseAllocator The allocator for allocating memory chunks.
*/
MemoryPoolAllocator(void *buffer, size_t size, size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) :
chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(buffer), baseAllocator_(baseAllocator), ownBaseAllocator_(0)
StdBaseAllocatorType(*this),
chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(buffer),
baseAllocator_(baseAllocator), ownBaseAllocator_(0)
{
RAPIDJSON_ASSERT(buffer != 0);
RAPIDJSON_ASSERT(size > sizeof(ChunkHeader));
Expand Down Expand Up @@ -279,6 +438,8 @@ class MemoryPoolAllocator {
BaseAllocator* ownBaseAllocator_; //!< base allocator created by this object.
};

RAPIDJSON_DIAG_POP

RAPIDJSON_NAMESPACE_END

#endif // RAPIDJSON_ENCODINGS_H_
Loading

0 comments on commit fc2a001

Please sign in to comment.