This commit is contained in:
AlexandreRouma 2021-12-24 21:51:18 +01:00
parent 07294034f6
commit db8f736d58
51 changed files with 5608 additions and 6490 deletions

View File

@ -96,7 +96,7 @@ public:
} }
return RAPIDJSON_REALLOC(originalPtr, newSize); return RAPIDJSON_REALLOC(originalPtr, newSize);
} }
static void Free(void* ptr) RAPIDJSON_NOEXCEPT { RAPIDJSON_FREE(ptr); } static void Free(void *ptr) RAPIDJSON_NOEXCEPT { RAPIDJSON_FREE(ptr); }
bool operator==(const CrtAllocator&) const RAPIDJSON_NOEXCEPT { bool operator==(const CrtAllocator&) const RAPIDJSON_NOEXCEPT {
return true; return true;
@ -133,11 +133,11 @@ class MemoryPoolAllocator {
struct ChunkHeader { struct ChunkHeader {
size_t capacity; //!< Capacity of the chunk in bytes (excluding the header itself). size_t capacity; //!< Capacity of the chunk in bytes (excluding the header itself).
size_t size; //!< Current size of allocated memory in bytes. size_t size; //!< Current size of allocated memory in bytes.
ChunkHeader* next; //!< Next chunk in the linked list. ChunkHeader *next; //!< Next chunk in the linked list.
}; };
struct SharedData { struct SharedData {
ChunkHeader* chunkHead; //!< Head of the chunk linked-list. Only the head chunk serves allocation. ChunkHeader *chunkHead; //!< Head of the chunk linked-list. Only the head chunk serves allocation.
BaseAllocator* ownBaseAllocator; //!< base allocator created by this object. BaseAllocator* ownBaseAllocator; //!< base allocator created by this object.
size_t refcount; size_t refcount;
bool ownBuffer; bool ownBuffer;
@ -146,10 +146,12 @@ class MemoryPoolAllocator {
static const size_t SIZEOF_SHARED_DATA = RAPIDJSON_ALIGN(sizeof(SharedData)); static const size_t SIZEOF_SHARED_DATA = RAPIDJSON_ALIGN(sizeof(SharedData));
static const size_t SIZEOF_CHUNK_HEADER = RAPIDJSON_ALIGN(sizeof(ChunkHeader)); static const size_t SIZEOF_CHUNK_HEADER = RAPIDJSON_ALIGN(sizeof(ChunkHeader));
static inline ChunkHeader* GetChunkHead(SharedData* shared) { static inline ChunkHeader *GetChunkHead(SharedData *shared)
{
return reinterpret_cast<ChunkHeader*>(reinterpret_cast<uint8_t*>(shared) + SIZEOF_SHARED_DATA); return reinterpret_cast<ChunkHeader*>(reinterpret_cast<uint8_t*>(shared) + SIZEOF_SHARED_DATA);
} }
static inline uint8_t* GetChunkBuffer(SharedData* shared) { static inline uint8_t *GetChunkBuffer(SharedData *shared)
{
return reinterpret_cast<uint8_t*>(shared->chunkHead) + SIZEOF_CHUNK_HEADER; return reinterpret_cast<uint8_t*>(shared->chunkHead) + SIZEOF_CHUNK_HEADER;
} }
@ -163,9 +165,12 @@ public:
/*! \param chunkSize The size of memory chunk. The default is kDefaultChunkSize. /*! \param chunkSize The size of memory chunk. The default is kDefaultChunkSize.
\param baseAllocator The allocator for allocating memory chunks. \param baseAllocator The allocator for allocating memory chunks.
*/ */
explicit MemoryPoolAllocator(size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) : chunk_capacity_(chunkSize), explicit
MemoryPoolAllocator(size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) :
chunk_capacity_(chunkSize),
baseAllocator_(baseAllocator ? baseAllocator : RAPIDJSON_NEW(BaseAllocator)()), baseAllocator_(baseAllocator ? baseAllocator : RAPIDJSON_NEW(BaseAllocator)()),
shared_(static_cast<SharedData*>(baseAllocator_ ? baseAllocator_->Malloc(SIZEOF_SHARED_DATA + SIZEOF_CHUNK_HEADER) : 0)) { shared_(static_cast<SharedData*>(baseAllocator_ ? baseAllocator_->Malloc(SIZEOF_SHARED_DATA + SIZEOF_CHUNK_HEADER) : 0))
{
RAPIDJSON_ASSERT(baseAllocator_ != 0); RAPIDJSON_ASSERT(baseAllocator_ != 0);
RAPIDJSON_ASSERT(shared_ != 0); RAPIDJSON_ASSERT(shared_ != 0);
if (baseAllocator) { if (baseAllocator) {
@ -192,9 +197,11 @@ public:
\param chunkSize The size of memory chunk. The default is kDefaultChunkSize. \param chunkSize The size of memory chunk. The default is kDefaultChunkSize.
\param baseAllocator The allocator for allocating memory chunks. \param baseAllocator The allocator for allocating memory chunks.
*/ */
MemoryPoolAllocator(void* buffer, size_t size, size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) : chunk_capacity_(chunkSize), MemoryPoolAllocator(void *buffer, size_t size, size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) :
chunk_capacity_(chunkSize),
baseAllocator_(baseAllocator), baseAllocator_(baseAllocator),
shared_(static_cast<SharedData*>(AlignBuffer(buffer, size))) { shared_(static_cast<SharedData*>(AlignBuffer(buffer, size)))
{
RAPIDJSON_ASSERT(size >= SIZEOF_SHARED_DATA + SIZEOF_CHUNK_HEADER); RAPIDJSON_ASSERT(size >= SIZEOF_SHARED_DATA + SIZEOF_CHUNK_HEADER);
shared_->chunkHead = GetChunkHead(shared_); shared_->chunkHead = GetChunkHead(shared_);
shared_->chunkHead->capacity = size - SIZEOF_SHARED_DATA - SIZEOF_CHUNK_HEADER; shared_->chunkHead->capacity = size - SIZEOF_SHARED_DATA - SIZEOF_CHUNK_HEADER;
@ -205,13 +212,16 @@ public:
shared_->refcount = 1; shared_->refcount = 1;
} }
MemoryPoolAllocator(const MemoryPoolAllocator& rhs) RAPIDJSON_NOEXCEPT : chunk_capacity_(rhs.chunk_capacity_), MemoryPoolAllocator(const MemoryPoolAllocator& rhs) RAPIDJSON_NOEXCEPT :
chunk_capacity_(rhs.chunk_capacity_),
baseAllocator_(rhs.baseAllocator_), baseAllocator_(rhs.baseAllocator_),
shared_(rhs.shared_) { shared_(rhs.shared_)
{
RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0); RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0);
++shared_->refcount; ++shared_->refcount;
} }
MemoryPoolAllocator& operator=(const MemoryPoolAllocator& rhs) RAPIDJSON_NOEXCEPT { MemoryPoolAllocator& operator=(const MemoryPoolAllocator& rhs) RAPIDJSON_NOEXCEPT
{
RAPIDJSON_NOEXCEPT_ASSERT(rhs.shared_->refcount > 0); RAPIDJSON_NOEXCEPT_ASSERT(rhs.shared_->refcount > 0);
++rhs.shared_->refcount; ++rhs.shared_->refcount;
this->~MemoryPoolAllocator(); this->~MemoryPoolAllocator();
@ -222,13 +232,16 @@ public:
} }
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS #if RAPIDJSON_HAS_CXX11_RVALUE_REFS
MemoryPoolAllocator(MemoryPoolAllocator&& rhs) RAPIDJSON_NOEXCEPT : chunk_capacity_(rhs.chunk_capacity_), MemoryPoolAllocator(MemoryPoolAllocator&& rhs) RAPIDJSON_NOEXCEPT :
chunk_capacity_(rhs.chunk_capacity_),
baseAllocator_(rhs.baseAllocator_), baseAllocator_(rhs.baseAllocator_),
shared_(rhs.shared_) { shared_(rhs.shared_)
{
RAPIDJSON_NOEXCEPT_ASSERT(rhs.shared_->refcount > 0); RAPIDJSON_NOEXCEPT_ASSERT(rhs.shared_->refcount > 0);
rhs.shared_ = 0; rhs.shared_ = 0;
} }
MemoryPoolAllocator& operator=(MemoryPoolAllocator&& rhs) RAPIDJSON_NOEXCEPT { MemoryPoolAllocator& operator=(MemoryPoolAllocator&& rhs) RAPIDJSON_NOEXCEPT
{
RAPIDJSON_NOEXCEPT_ASSERT(rhs.shared_->refcount > 0); RAPIDJSON_NOEXCEPT_ASSERT(rhs.shared_->refcount > 0);
this->~MemoryPoolAllocator(); this->~MemoryPoolAllocator();
baseAllocator_ = rhs.baseAllocator_; baseAllocator_ = rhs.baseAllocator_;
@ -252,7 +265,7 @@ public:
return; return;
} }
Clear(); Clear();
BaseAllocator* a = shared_->ownBaseAllocator; BaseAllocator *a = shared_->ownBaseAllocator;
if (shared_->ownBuffer) { if (shared_->ownBuffer) {
baseAllocator_->Free(shared_); baseAllocator_->Free(shared_);
} }
@ -314,7 +327,7 @@ public:
if (!AddChunk(chunk_capacity_ > size ? chunk_capacity_ : size)) if (!AddChunk(chunk_capacity_ > size ? chunk_capacity_ : size))
return NULL; return NULL;
void* buffer = GetChunkBuffer(shared_) + shared_->chunkHead->size; void *buffer = GetChunkBuffer(shared_) + shared_->chunkHead->size;
shared_->chunkHead->size += size; shared_->chunkHead->size += size;
return buffer; return buffer;
} }
@ -355,7 +368,7 @@ public:
} }
//! Frees a memory block (concept Allocator) //! Frees a memory block (concept Allocator)
static void Free(void* ptr) RAPIDJSON_NOEXCEPT { (void)ptr; } // Do nothing static void Free(void *ptr) RAPIDJSON_NOEXCEPT { (void)ptr; } // Do nothing
//! Compare (equality) with another MemoryPoolAllocator //! Compare (equality) with another MemoryPoolAllocator
bool operator==(const MemoryPoolAllocator& rhs) const RAPIDJSON_NOEXCEPT { bool operator==(const MemoryPoolAllocator& rhs) const RAPIDJSON_NOEXCEPT {
@ -387,7 +400,8 @@ private:
return false; return false;
} }
static inline void* AlignBuffer(void* buf, size_t& size) { static inline void* AlignBuffer(void* buf, size_t &size)
{
RAPIDJSON_NOEXCEPT_ASSERT(buf != 0); RAPIDJSON_NOEXCEPT_ASSERT(buf != 0);
const uintptr_t mask = sizeof(void*) - 1; const uintptr_t mask = sizeof(void*) - 1;
const uintptr_t ubuf = reinterpret_cast<uintptr_t>(buf); const uintptr_t ubuf = reinterpret_cast<uintptr_t>(buf);
@ -402,29 +416,36 @@ private:
size_t chunk_capacity_; //!< The minimum capacity of chunk when they are allocated. size_t chunk_capacity_; //!< The minimum capacity of chunk when they are allocated.
BaseAllocator* baseAllocator_; //!< base allocator for allocating memory chunks. BaseAllocator* baseAllocator_; //!< base allocator for allocating memory chunks.
SharedData* shared_; //!< The shared data of the allocator SharedData *shared_; //!< The shared data of the allocator
}; };
namespace internal { namespace internal {
template <typename, typename = void> template<typename, typename = void>
struct IsRefCounted : public FalseType {}; struct IsRefCounted :
template <typename T> public FalseType
struct IsRefCounted<T, typename internal::EnableIfCond<T::kRefCounted>::Type> : public TrueType {}; { };
template<typename T>
struct IsRefCounted<T, typename internal::EnableIfCond<T::kRefCounted>::Type> :
public TrueType
{ };
} }
template <typename T, typename A> template<typename T, typename A>
inline T* Realloc(A& a, T* old_p, size_t old_n, size_t new_n) { inline T* Realloc(A& a, T* old_p, size_t old_n, size_t new_n)
{
RAPIDJSON_NOEXCEPT_ASSERT(old_n <= SIZE_MAX / sizeof(T) && new_n <= SIZE_MAX / sizeof(T)); RAPIDJSON_NOEXCEPT_ASSERT(old_n <= SIZE_MAX / sizeof(T) && new_n <= SIZE_MAX / sizeof(T));
return static_cast<T*>(a.Realloc(old_p, old_n * sizeof(T), new_n * sizeof(T))); return static_cast<T*>(a.Realloc(old_p, old_n * sizeof(T), new_n * sizeof(T)));
} }
template <typename T, typename A> template<typename T, typename A>
inline T* Malloc(A& a, size_t n = 1) { inline T *Malloc(A& a, size_t n = 1)
{
return Realloc<T, A>(a, NULL, 0, n); return Realloc<T, A>(a, NULL, 0, n);
} }
template <typename T, typename A> template<typename T, typename A>
inline void Free(A& a, T* p, size_t n = 1) { inline void Free(A& a, T *p, size_t n = 1)
{
static_cast<void>(Realloc<T, A>(a, p, n, 0)); static_cast<void>(Realloc<T, A>(a, p, n, 0));
} }
@ -434,7 +455,9 @@ RAPIDJSON_DIAG_OFF(effc++) // std::allocator can safely be inherited
#endif #endif
template <typename T, typename BaseAllocator = CrtAllocator> template <typename T, typename BaseAllocator = CrtAllocator>
class StdAllocator : public std::allocator<T> { class StdAllocator :
public std::allocator<T>
{
typedef std::allocator<T> allocator_type; typedef std::allocator<T> allocator_type;
#if RAPIDJSON_HAS_CXX11 #if RAPIDJSON_HAS_CXX11
typedef std::allocator_traits<allocator_type> traits_type; typedef std::allocator_traits<allocator_type> traits_type;
@ -445,19 +468,27 @@ class StdAllocator : public std::allocator<T> {
public: public:
typedef BaseAllocator BaseAllocatorType; typedef BaseAllocator BaseAllocatorType;
StdAllocator() RAPIDJSON_NOEXCEPT : allocator_type(), StdAllocator() RAPIDJSON_NOEXCEPT :
baseAllocator_() {} allocator_type(),
baseAllocator_()
{ }
StdAllocator(const StdAllocator& rhs) RAPIDJSON_NOEXCEPT : allocator_type(rhs), StdAllocator(const StdAllocator& rhs) RAPIDJSON_NOEXCEPT :
baseAllocator_(rhs.baseAllocator_) {} allocator_type(rhs),
baseAllocator_(rhs.baseAllocator_)
{ }
template <typename U> template<typename U>
StdAllocator(const StdAllocator<U, BaseAllocator>& rhs) RAPIDJSON_NOEXCEPT : allocator_type(rhs), StdAllocator(const StdAllocator<U, BaseAllocator>& rhs) RAPIDJSON_NOEXCEPT :
baseAllocator_(rhs.baseAllocator_) {} allocator_type(rhs),
baseAllocator_(rhs.baseAllocator_)
{ }
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS #if RAPIDJSON_HAS_CXX11_RVALUE_REFS
StdAllocator(StdAllocator&& rhs) RAPIDJSON_NOEXCEPT : allocator_type(std::move(rhs)), StdAllocator(StdAllocator&& rhs) RAPIDJSON_NOEXCEPT :
baseAllocator_(std::move(rhs.baseAllocator_)) {} allocator_type(std::move(rhs)),
baseAllocator_(std::move(rhs.baseAllocator_))
{ }
#endif #endif
#if RAPIDJSON_HAS_CXX11 #if RAPIDJSON_HAS_CXX11
using propagate_on_container_move_assignment = std::true_type; using propagate_on_container_move_assignment = std::true_type;
@ -465,12 +496,15 @@ public:
#endif #endif
/* implicit */ /* implicit */
StdAllocator(const BaseAllocator& allocator) RAPIDJSON_NOEXCEPT : allocator_type(), StdAllocator(const BaseAllocator& allocator) RAPIDJSON_NOEXCEPT :
baseAllocator_(allocator) {} allocator_type(),
baseAllocator_(allocator)
{ }
~StdAllocator() RAPIDJSON_NOEXCEPT {} ~StdAllocator() RAPIDJSON_NOEXCEPT
{ }
template <typename U> template<typename U>
struct rebind { struct rebind {
typedef StdAllocator<U, BaseAllocator> other; typedef StdAllocator<U, BaseAllocator> other;
}; };
@ -484,25 +518,30 @@ public:
#if RAPIDJSON_HAS_CXX11 #if RAPIDJSON_HAS_CXX11
typedef typename std::add_lvalue_reference<value_type>::type& reference; typedef typename std::add_lvalue_reference<value_type>::type &reference;
typedef typename std::add_lvalue_reference<typename std::add_const<value_type>::type>::type& const_reference; typedef typename std::add_lvalue_reference<typename std::add_const<value_type>::type>::type &const_reference;
pointer address(reference r) const RAPIDJSON_NOEXCEPT { pointer address(reference r) const RAPIDJSON_NOEXCEPT
{
return std::addressof(r); return std::addressof(r);
} }
const_pointer address(const_reference r) const RAPIDJSON_NOEXCEPT { const_pointer address(const_reference r) const RAPIDJSON_NOEXCEPT
{
return std::addressof(r); return std::addressof(r);
} }
size_type max_size() const RAPIDJSON_NOEXCEPT { size_type max_size() const RAPIDJSON_NOEXCEPT
{
return traits_type::max_size(*this); return traits_type::max_size(*this);
} }
template <typename... Args> template <typename ...Args>
void construct(pointer p, Args&&... args) { void construct(pointer p, Args&&... args)
{
traits_type::construct(*this, p, std::forward<Args>(args)...); traits_type::construct(*this, p, std::forward<Args>(args)...);
} }
void destroy(pointer p) { void destroy(pointer p)
{
traits_type::destroy(*this, p); traits_type::destroy(*this, p);
} }
@ -511,39 +550,48 @@ public:
typedef typename allocator_type::reference reference; typedef typename allocator_type::reference reference;
typedef typename allocator_type::const_reference const_reference; typedef typename allocator_type::const_reference const_reference;
pointer address(reference r) const RAPIDJSON_NOEXCEPT { pointer address(reference r) const RAPIDJSON_NOEXCEPT
{
return allocator_type::address(r); return allocator_type::address(r);
} }
const_pointer address(const_reference r) const RAPIDJSON_NOEXCEPT { const_pointer address(const_reference r) const RAPIDJSON_NOEXCEPT
{
return allocator_type::address(r); return allocator_type::address(r);
} }
size_type max_size() const RAPIDJSON_NOEXCEPT { size_type max_size() const RAPIDJSON_NOEXCEPT
{
return allocator_type::max_size(); return allocator_type::max_size();
} }
void construct(pointer p, const_reference r) { void construct(pointer p, const_reference r)
{
allocator_type::construct(p, r); allocator_type::construct(p, r);
} }
void destroy(pointer p) { void destroy(pointer p)
{
allocator_type::destroy(p); allocator_type::destroy(p);
} }
#endif // !RAPIDJSON_HAS_CXX11 #endif // !RAPIDJSON_HAS_CXX11
template <typename U> template <typename U>
U* allocate(size_type n = 1, const void* = 0) { U* allocate(size_type n = 1, const void* = 0)
{
return RAPIDJSON_NAMESPACE::Malloc<U>(baseAllocator_, n); return RAPIDJSON_NAMESPACE::Malloc<U>(baseAllocator_, n);
} }
template <typename U> template <typename U>
void deallocate(U* p, size_type n = 1) { void deallocate(U* p, size_type n = 1)
{
RAPIDJSON_NAMESPACE::Free<U>(baseAllocator_, p, n); RAPIDJSON_NAMESPACE::Free<U>(baseAllocator_, p, n);
} }
pointer allocate(size_type n = 1, const void* = 0) { pointer allocate(size_type n = 1, const void* = 0)
{
return allocate<value_type>(n); return allocate<value_type>(n);
} }
void deallocate(pointer p, size_type n = 1) { void deallocate(pointer p, size_type n = 1)
{
deallocate<value_type>(p, n); deallocate<value_type>(p, n);
} }
@ -551,25 +599,30 @@ public:
using is_always_equal = std::is_empty<BaseAllocator>; using is_always_equal = std::is_empty<BaseAllocator>;
#endif #endif
template <typename U> template<typename U>
bool operator==(const StdAllocator<U, BaseAllocator>& rhs) const RAPIDJSON_NOEXCEPT { bool operator==(const StdAllocator<U, BaseAllocator>& rhs) const RAPIDJSON_NOEXCEPT
{
return baseAllocator_ == rhs.baseAllocator_; return baseAllocator_ == rhs.baseAllocator_;
} }
template <typename U> template<typename U>
bool operator!=(const StdAllocator<U, BaseAllocator>& rhs) const RAPIDJSON_NOEXCEPT { bool operator!=(const StdAllocator<U, BaseAllocator>& rhs) const RAPIDJSON_NOEXCEPT
{
return !operator==(rhs); return !operator==(rhs);
} }
//! rapidjson Allocator concept //! rapidjson Allocator concept
static const bool kNeedFree = BaseAllocator::kNeedFree; static const bool kNeedFree = BaseAllocator::kNeedFree;
static const bool kRefCounted = internal::IsRefCounted<BaseAllocator>::Value; static const bool kRefCounted = internal::IsRefCounted<BaseAllocator>::Value;
void* Malloc(size_t size) { void* Malloc(size_t size)
{
return baseAllocator_.Malloc(size); return baseAllocator_.Malloc(size);
} }
void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) { void* Realloc(void* originalPtr, size_t originalSize, size_t newSize)
{
return baseAllocator_.Realloc(originalPtr, originalSize, newSize); return baseAllocator_.Realloc(originalPtr, originalSize, newSize);
} }
static void Free(void* ptr) RAPIDJSON_NOEXCEPT { static void Free(void *ptr) RAPIDJSON_NOEXCEPT
{
BaseAllocator::Free(ptr); BaseAllocator::Free(ptr);
} }
@ -582,29 +635,40 @@ private:
#if !RAPIDJSON_HAS_CXX17 // std::allocator<void> deprecated in C++17 #if !RAPIDJSON_HAS_CXX17 // std::allocator<void> deprecated in C++17
template <typename BaseAllocator> template <typename BaseAllocator>
class StdAllocator<void, BaseAllocator> : public std::allocator<void> { class StdAllocator<void, BaseAllocator> :
public std::allocator<void>
{
typedef std::allocator<void> allocator_type; typedef std::allocator<void> allocator_type;
public: public:
typedef BaseAllocator BaseAllocatorType; typedef BaseAllocator BaseAllocatorType;
StdAllocator() RAPIDJSON_NOEXCEPT : allocator_type(), StdAllocator() RAPIDJSON_NOEXCEPT :
baseAllocator_() {} allocator_type(),
baseAllocator_()
{ }
StdAllocator(const StdAllocator& rhs) RAPIDJSON_NOEXCEPT : allocator_type(rhs), StdAllocator(const StdAllocator& rhs) RAPIDJSON_NOEXCEPT :
baseAllocator_(rhs.baseAllocator_) {} allocator_type(rhs),
baseAllocator_(rhs.baseAllocator_)
{ }
template <typename U> template<typename U>
StdAllocator(const StdAllocator<U, BaseAllocator>& rhs) RAPIDJSON_NOEXCEPT : allocator_type(rhs), StdAllocator(const StdAllocator<U, BaseAllocator>& rhs) RAPIDJSON_NOEXCEPT :
baseAllocator_(rhs.baseAllocator_) {} allocator_type(rhs),
baseAllocator_(rhs.baseAllocator_)
{ }
/* implicit */ /* implicit */
StdAllocator(const BaseAllocator& allocator) RAPIDJSON_NOEXCEPT : allocator_type(), StdAllocator(const BaseAllocator& allocator) RAPIDJSON_NOEXCEPT :
baseAllocator_(allocator) {} allocator_type(),
baseAllocator_(allocator)
{ }
~StdAllocator() RAPIDJSON_NOEXCEPT {} ~StdAllocator() RAPIDJSON_NOEXCEPT
{ }
template <typename U> template<typename U>
struct rebind { struct rebind {
typedef StdAllocator<U, BaseAllocator> other; typedef StdAllocator<U, BaseAllocator> other;
}; };

View File

@ -35,22 +35,22 @@ RAPIDJSON_NAMESPACE_BEGIN
/*! /*!
\tparam InputStream Any stream that implements Stream Concept \tparam InputStream Any stream that implements Stream Concept
*/ */
template <typename InputStream, typename Encoding = UTF8<>> template <typename InputStream, typename Encoding = UTF8<> >
class CursorStreamWrapper : public GenericStreamWrapper<InputStream, Encoding> { class CursorStreamWrapper : public GenericStreamWrapper<InputStream, Encoding> {
public: public:
typedef typename Encoding::Ch Ch; typedef typename Encoding::Ch Ch;
CursorStreamWrapper(InputStream& is) : GenericStreamWrapper<InputStream, Encoding>(is), line_(1), col_(0) {} CursorStreamWrapper(InputStream& is):
GenericStreamWrapper<InputStream, Encoding>(is), line_(1), col_(0) {}
// counting line and column number // counting line and column number
Ch Take() { Ch Take() {
Ch ch = this->is_.Take(); Ch ch = this->is_.Take();
if (ch == '\n') { if(ch == '\n') {
line_++; line_ ++;
col_ = 0; col_ = 0;
} } else {
else { col_ ++;
col_++;
} }
return ch; return ch;
} }

View File

@ -38,7 +38,6 @@ RAPIDJSON_NAMESPACE_BEGIN
template <typename Encoding, typename InputByteStream> template <typename Encoding, typename InputByteStream>
class EncodedInputStream { class EncodedInputStream {
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
public: public:
typedef typename Encoding::Ch Ch; typedef typename Encoding::Ch Ch;
@ -47,24 +46,14 @@ public:
} }
Ch Peek() const { return current_; } Ch Peek() const { return current_; }
Ch Take() { Ch Take() { Ch c = current_; current_ = Encoding::Take(is_); return c; }
Ch c = current_;
current_ = Encoding::Take(is_);
return c;
}
size_t Tell() const { return is_.Tell(); } size_t Tell() const { return is_.Tell(); }
// Not implemented // Not implemented
void Put(Ch) { RAPIDJSON_ASSERT(false); } void Put(Ch) { RAPIDJSON_ASSERT(false); }
void Flush() { RAPIDJSON_ASSERT(false); } void Flush() { RAPIDJSON_ASSERT(false); }
Ch* PutBegin() { Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
RAPIDJSON_ASSERT(false); size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
return 0;
}
size_t PutEnd(Ch*) {
RAPIDJSON_ASSERT(false);
return 0;
}
private: private:
EncodedInputStream(const EncodedInputStream&); EncodedInputStream(const EncodedInputStream&);
@ -110,7 +99,6 @@ private:
template <typename Encoding, typename OutputByteStream> template <typename Encoding, typename OutputByteStream>
class EncodedOutputStream { class EncodedOutputStream {
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
public: public:
typedef typename Encoding::Ch Ch; typedef typename Encoding::Ch Ch;
@ -123,26 +111,11 @@ public:
void Flush() { os_.Flush(); } void Flush() { os_.Flush(); }
// Not implemented // Not implemented
Ch Peek() const { Ch Peek() const { RAPIDJSON_ASSERT(false); return 0;}
RAPIDJSON_ASSERT(false); Ch Take() { RAPIDJSON_ASSERT(false); return 0;}
return 0; size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; }
} Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
Ch Take() { size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
RAPIDJSON_ASSERT(false);
return 0;
}
size_t Tell() const {
RAPIDJSON_ASSERT(false);
return 0;
}
Ch* PutBegin() {
RAPIDJSON_ASSERT(false);
return 0;
}
size_t PutEnd(Ch*) {
RAPIDJSON_ASSERT(false);
return 0;
}
private: private:
EncodedOutputStream(const EncodedOutputStream&); EncodedOutputStream(const EncodedOutputStream&);
@ -161,7 +134,6 @@ private:
template <typename CharType, typename InputByteStream> template <typename CharType, typename InputByteStream>
class AutoUTFInputStream { class AutoUTFInputStream {
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
public: public:
typedef CharType Ch; typedef CharType Ch;
@ -182,24 +154,14 @@ public:
bool HasBOM() const { return hasBOM_; } bool HasBOM() const { return hasBOM_; }
Ch Peek() const { return current_; } Ch Peek() const { return current_; }
Ch Take() { Ch Take() { Ch c = current_; current_ = takeFunc_(*is_); return c; }
Ch c = current_;
current_ = takeFunc_(*is_);
return c;
}
size_t Tell() const { return is_->Tell(); } size_t Tell() const { return is_->Tell(); }
// Not implemented // Not implemented
void Put(Ch) { RAPIDJSON_ASSERT(false); } void Put(Ch) { RAPIDJSON_ASSERT(false); }
void Flush() { RAPIDJSON_ASSERT(false); } void Flush() { RAPIDJSON_ASSERT(false); }
Ch* PutBegin() { Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
RAPIDJSON_ASSERT(false); size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
return 0;
}
size_t PutEnd(Ch*) {
RAPIDJSON_ASSERT(false);
return 0;
}
private: private:
AutoUTFInputStream(const AutoUTFInputStream&); AutoUTFInputStream(const AutoUTFInputStream&);
@ -214,47 +176,17 @@ private:
// FF FE UTF-16LE // FF FE UTF-16LE
// EF BB BF UTF-8 // EF BB BF UTF-8
const unsigned char* c = reinterpret_cast<const unsigned char*>(is_->Peek4()); const unsigned char* c = reinterpret_cast<const unsigned char *>(is_->Peek4());
if (!c) if (!c)
return; return;
unsigned bom = static_cast<unsigned>(c[0] | (c[1] << 8) | (c[2] << 16) | (c[3] << 24)); unsigned bom = static_cast<unsigned>(c[0] | (c[1] << 8) | (c[2] << 16) | (c[3] << 24));
hasBOM_ = false; hasBOM_ = false;
if (bom == 0xFFFE0000) { if (bom == 0xFFFE0000) { type_ = kUTF32BE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); }
type_ = kUTF32BE; else if (bom == 0x0000FEFF) { type_ = kUTF32LE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); }
hasBOM_ = true; else if ((bom & 0xFFFF) == 0xFFFE) { type_ = kUTF16BE; hasBOM_ = true; is_->Take(); is_->Take(); }
is_->Take(); else if ((bom & 0xFFFF) == 0xFEFF) { type_ = kUTF16LE; hasBOM_ = true; is_->Take(); is_->Take(); }
is_->Take(); else if ((bom & 0xFFFFFF) == 0xBFBBEF) { type_ = kUTF8; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); }
is_->Take();
is_->Take();
}
else if (bom == 0x0000FEFF) {
type_ = kUTF32LE;
hasBOM_ = true;
is_->Take();
is_->Take();
is_->Take();
is_->Take();
}
else if ((bom & 0xFFFF) == 0xFFFE) {
type_ = kUTF16BE;
hasBOM_ = true;
is_->Take();
is_->Take();
}
else if ((bom & 0xFFFF) == 0xFEFF) {
type_ = kUTF16LE;
hasBOM_ = true;
is_->Take();
is_->Take();
}
else if ((bom & 0xFFFFFF) == 0xBFBBEF) {
type_ = kUTF8;
hasBOM_ = true;
is_->Take();
is_->Take();
is_->Take();
}
// RFC 4627: Section 3 // RFC 4627: Section 3
// "Since the first two characters of a JSON text will always be ASCII // "Since the first two characters of a JSON text will always be ASCII
@ -270,23 +202,12 @@ private:
if (!hasBOM_) { if (!hasBOM_) {
int pattern = (c[0] ? 1 : 0) | (c[1] ? 2 : 0) | (c[2] ? 4 : 0) | (c[3] ? 8 : 0); int pattern = (c[0] ? 1 : 0) | (c[1] ? 2 : 0) | (c[2] ? 4 : 0) | (c[3] ? 8 : 0);
switch (pattern) { switch (pattern) {
case 0x08: case 0x08: type_ = kUTF32BE; break;
type_ = kUTF32BE; case 0x0A: type_ = kUTF16BE; break;
break; case 0x01: type_ = kUTF32LE; break;
case 0x0A: case 0x05: type_ = kUTF16LE; break;
type_ = kUTF16BE; case 0x0F: type_ = kUTF8; break;
break; default: break; // Use type defined by user.
case 0x01:
type_ = kUTF32LE;
break;
case 0x05:
type_ = kUTF16LE;
break;
case 0x0F:
type_ = kUTF8;
break;
default:
break; // Use type defined by user.
} }
} }
@ -311,7 +232,6 @@ private:
template <typename CharType, typename OutputByteStream> template <typename CharType, typename OutputByteStream>
class AutoUTFOutputStream { class AutoUTFOutputStream {
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
public: public:
typedef CharType Ch; typedef CharType Ch;
@ -341,26 +261,11 @@ public:
void Flush() { os_->Flush(); } void Flush() { os_->Flush(); }
// Not implemented // Not implemented
Ch Peek() const { Ch Peek() const { RAPIDJSON_ASSERT(false); return 0;}
RAPIDJSON_ASSERT(false); Ch Take() { RAPIDJSON_ASSERT(false); return 0;}
return 0; size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; }
} Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
Ch Take() { size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
RAPIDJSON_ASSERT(false);
return 0;
}
size_t Tell() const {
RAPIDJSON_ASSERT(false);
return 0;
}
Ch* PutBegin() {
RAPIDJSON_ASSERT(false);
return 0;
}
size_t PutEnd(Ch*) {
RAPIDJSON_ASSERT(false);
return 0;
}
private: private:
AutoUTFOutputStream(const AutoUTFOutputStream&); AutoUTFOutputStream(const AutoUTFOutputStream&);

View File

@ -92,13 +92,13 @@ concept Encoding {
\tparam CharType Code unit for storing 8-bit UTF-8 data. Default is char. \tparam CharType Code unit for storing 8-bit UTF-8 data. Default is char.
\note implements Encoding concept \note implements Encoding concept
*/ */
template <typename CharType = char> template<typename CharType = char>
struct UTF8 { struct UTF8 {
typedef CharType Ch; typedef CharType Ch;
enum { supportUnicode = 1 }; enum { supportUnicode = 1 };
template <typename OutputStream> template<typename OutputStream>
static void Encode(OutputStream& os, unsigned codepoint) { static void Encode(OutputStream& os, unsigned codepoint) {
if (codepoint <= 0x7F) if (codepoint <= 0x7F)
os.Put(static_cast<Ch>(codepoint & 0xFF)); os.Put(static_cast<Ch>(codepoint & 0xFF));
@ -120,7 +120,7 @@ struct UTF8 {
} }
} }
template <typename OutputStream> template<typename OutputStream>
static void EncodeUnsafe(OutputStream& os, unsigned codepoint) { static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
if (codepoint <= 0x7F) if (codepoint <= 0x7F)
PutUnsafe(os, static_cast<Ch>(codepoint & 0xFF)); PutUnsafe(os, static_cast<Ch>(codepoint & 0xFF));
@ -144,13 +144,9 @@ struct UTF8 {
template <typename InputStream> template <typename InputStream>
static bool Decode(InputStream& is, unsigned* codepoint) { static bool Decode(InputStream& is, unsigned* codepoint) {
#define RAPIDJSON_COPY() \ #define RAPIDJSON_COPY() c = is.Take(); *codepoint = (*codepoint << 6) | (static_cast<unsigned char>(c) & 0x3Fu)
c = is.Take(); \
*codepoint = (*codepoint << 6) | (static_cast<unsigned char>(c) & 0x3Fu)
#define RAPIDJSON_TRANS(mask) result &= ((GetRange(static_cast<unsigned char>(c)) & mask) != 0) #define RAPIDJSON_TRANS(mask) result &= ((GetRange(static_cast<unsigned char>(c)) & mask) != 0)
#define RAPIDJSON_TAIL() \ #define RAPIDJSON_TAIL() RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x70)
RAPIDJSON_COPY(); \
RAPIDJSON_TRANS(0x70)
typename InputStream::Ch c = is.Take(); typename InputStream::Ch c = is.Take();
if (!(c & 0x80)) { if (!(c & 0x80)) {
*codepoint = static_cast<unsigned char>(c); *codepoint = static_cast<unsigned char>(c);
@ -160,48 +156,19 @@ struct UTF8 {
unsigned char type = GetRange(static_cast<unsigned char>(c)); unsigned char type = GetRange(static_cast<unsigned char>(c));
if (type >= 32) { if (type >= 32) {
*codepoint = 0; *codepoint = 0;
} } else {
else {
*codepoint = (0xFFu >> type) & static_cast<unsigned char>(c); *codepoint = (0xFFu >> type) & static_cast<unsigned char>(c);
} }
bool result = true; bool result = true;
switch (type) { switch (type) {
case 2: case 2: RAPIDJSON_TAIL(); return result;
RAPIDJSON_TAIL(); case 3: RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result;
return result; case 4: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x50); RAPIDJSON_TAIL(); return result;
case 3: case 5: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x10); RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result;
RAPIDJSON_TAIL(); case 6: RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result;
RAPIDJSON_TAIL(); case 10: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x20); RAPIDJSON_TAIL(); return result;
return result; case 11: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x60); RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result;
case 4: default: return false;
RAPIDJSON_COPY();
RAPIDJSON_TRANS(0x50);
RAPIDJSON_TAIL();
return result;
case 5:
RAPIDJSON_COPY();
RAPIDJSON_TRANS(0x10);
RAPIDJSON_TAIL();
RAPIDJSON_TAIL();
return result;
case 6:
RAPIDJSON_TAIL();
RAPIDJSON_TAIL();
RAPIDJSON_TAIL();
return result;
case 10:
RAPIDJSON_COPY();
RAPIDJSON_TRANS(0x20);
RAPIDJSON_TAIL();
return result;
case 11:
RAPIDJSON_COPY();
RAPIDJSON_TRANS(0x60);
RAPIDJSON_TAIL();
RAPIDJSON_TAIL();
return result;
default:
return false;
} }
#undef RAPIDJSON_COPY #undef RAPIDJSON_COPY
#undef RAPIDJSON_TRANS #undef RAPIDJSON_TRANS
@ -212,9 +179,7 @@ struct UTF8 {
static bool Validate(InputStream& is, OutputStream& os) { static bool Validate(InputStream& is, OutputStream& os) {
#define RAPIDJSON_COPY() os.Put(c = is.Take()) #define RAPIDJSON_COPY() os.Put(c = is.Take())
#define RAPIDJSON_TRANS(mask) result &= ((GetRange(static_cast<unsigned char>(c)) & mask) != 0) #define RAPIDJSON_TRANS(mask) result &= ((GetRange(static_cast<unsigned char>(c)) & mask) != 0)
#define RAPIDJSON_TAIL() \ #define RAPIDJSON_TAIL() RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x70)
RAPIDJSON_COPY(); \
RAPIDJSON_TRANS(0x70)
Ch c; Ch c;
RAPIDJSON_COPY(); RAPIDJSON_COPY();
if (!(c & 0x80)) if (!(c & 0x80))
@ -222,42 +187,14 @@ struct UTF8 {
bool result = true; bool result = true;
switch (GetRange(static_cast<unsigned char>(c))) { switch (GetRange(static_cast<unsigned char>(c))) {
case 2: case 2: RAPIDJSON_TAIL(); return result;
RAPIDJSON_TAIL(); case 3: RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result;
return result; case 4: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x50); RAPIDJSON_TAIL(); return result;
case 3: case 5: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x10); RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result;
RAPIDJSON_TAIL(); case 6: RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result;
RAPIDJSON_TAIL(); case 10: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x20); RAPIDJSON_TAIL(); return result;
return result; case 11: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x60); RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result;
case 4: default: return false;
RAPIDJSON_COPY();
RAPIDJSON_TRANS(0x50);
RAPIDJSON_TAIL();
return result;
case 5:
RAPIDJSON_COPY();
RAPIDJSON_TRANS(0x10);
RAPIDJSON_TAIL();
RAPIDJSON_TAIL();
return result;
case 6:
RAPIDJSON_TAIL();
RAPIDJSON_TAIL();
RAPIDJSON_TAIL();
return result;
case 10:
RAPIDJSON_COPY();
RAPIDJSON_TRANS(0x20);
RAPIDJSON_TAIL();
return result;
case 11:
RAPIDJSON_COPY();
RAPIDJSON_TRANS(0x60);
RAPIDJSON_TAIL();
RAPIDJSON_TAIL();
return result;
default:
return false;
} }
#undef RAPIDJSON_COPY #undef RAPIDJSON_COPY
#undef RAPIDJSON_TRANS #undef RAPIDJSON_TRANS
@ -268,262 +205,16 @@ struct UTF8 {
// Referring to DFA of http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ // Referring to DFA of http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
// With new mapping 1 -> 0x10, 7 -> 0x20, 9 -> 0x40, such that AND operation can test multiple types. // With new mapping 1 -> 0x10, 7 -> 0x20, 9 -> 0x40, such that AND operation can test multiple types.
static const unsigned char type[] = { static const unsigned char type[] = {
0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0, 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
0, 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,
0, 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0, 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0, 8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
0, 10,3,3,3,3,3,3,3,3,3,3,3,3,4,3,3, 11,6,6,6,5,8,8,8,8,8,8,8,8,8,8,8,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0x10,
0x10,
0x10,
0x10,
0x10,
0x10,
0x10,
0x10,
0x10,
0x10,
0x10,
0x10,
0x10,
0x10,
0x10,
0x10,
0x40,
0x40,
0x40,
0x40,
0x40,
0x40,
0x40,
0x40,
0x40,
0x40,
0x40,
0x40,
0x40,
0x40,
0x40,
0x40,
0x20,
0x20,
0x20,
0x20,
0x20,
0x20,
0x20,
0x20,
0x20,
0x20,
0x20,
0x20,
0x20,
0x20,
0x20,
0x20,
0x20,
0x20,
0x20,
0x20,
0x20,
0x20,
0x20,
0x20,
0x20,
0x20,
0x20,
0x20,
0x20,
0x20,
0x20,
0x20,
8,
8,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
10,
3,
3,
3,
3,
3,
3,
3,
3,
3,
3,
3,
3,
4,
3,
3,
11,
6,
6,
6,
5,
8,
8,
8,
8,
8,
8,
8,
8,
8,
8,
8,
}; };
return type[c]; return type[c];
} }
@ -574,14 +265,14 @@ struct UTF8 {
\note For in-memory access, no need to concern endianness. The code units and code points are represented by CPU's endianness. \note For in-memory access, no need to concern endianness. The code units and code points are represented by CPU's endianness.
For streaming, use UTF16LE and UTF16BE, which handle endianness. For streaming, use UTF16LE and UTF16BE, which handle endianness.
*/ */
template <typename CharType = wchar_t> template<typename CharType = wchar_t>
struct UTF16 { struct UTF16 {
typedef CharType Ch; typedef CharType Ch;
RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 2); RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 2);
enum { supportUnicode = 1 }; enum { supportUnicode = 1 };
template <typename OutputStream> template<typename OutputStream>
static void Encode(OutputStream& os, unsigned codepoint) { static void Encode(OutputStream& os, unsigned codepoint) {
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2); RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2);
if (codepoint <= 0xFFFF) { if (codepoint <= 0xFFFF) {
@ -597,7 +288,7 @@ struct UTF16 {
} }
template <typename OutputStream> template<typename OutputStream>
static void EncodeUnsafe(OutputStream& os, unsigned codepoint) { static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2); RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2);
if (codepoint <= 0xFFFF) { if (codepoint <= 0xFFFF) {
@ -647,7 +338,7 @@ struct UTF16 {
}; };
//! UTF-16 little endian encoding. //! UTF-16 little endian encoding.
template <typename CharType = wchar_t> template<typename CharType = wchar_t>
struct UTF16LE : UTF16<CharType> { struct UTF16LE : UTF16<CharType> {
template <typename InputByteStream> template <typename InputByteStream>
static CharType TakeBOM(InputByteStream& is) { static CharType TakeBOM(InputByteStream& is) {
@ -680,7 +371,7 @@ struct UTF16LE : UTF16<CharType> {
}; };
//! UTF-16 big endian encoding. //! UTF-16 big endian encoding.
template <typename CharType = wchar_t> template<typename CharType = wchar_t>
struct UTF16BE : UTF16<CharType> { struct UTF16BE : UTF16<CharType> {
template <typename InputByteStream> template <typename InputByteStream>
static CharType TakeBOM(InputByteStream& is) { static CharType TakeBOM(InputByteStream& is) {
@ -723,21 +414,21 @@ struct UTF16BE : UTF16<CharType> {
\note For in-memory access, no need to concern endianness. The code units and code points are represented by CPU's endianness. \note For in-memory access, no need to concern endianness. The code units and code points are represented by CPU's endianness.
For streaming, use UTF32LE and UTF32BE, which handle endianness. For streaming, use UTF32LE and UTF32BE, which handle endianness.
*/ */
template <typename CharType = unsigned> template<typename CharType = unsigned>
struct UTF32 { struct UTF32 {
typedef CharType Ch; typedef CharType Ch;
RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 4); RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 4);
enum { supportUnicode = 1 }; enum { supportUnicode = 1 };
template <typename OutputStream> template<typename OutputStream>
static void Encode(OutputStream& os, unsigned codepoint) { static void Encode(OutputStream& os, unsigned codepoint) {
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 4); RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 4);
RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
os.Put(codepoint); os.Put(codepoint);
} }
template <typename OutputStream> template<typename OutputStream>
static void EncodeUnsafe(OutputStream& os, unsigned codepoint) { static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 4); RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 4);
RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
@ -762,7 +453,7 @@ struct UTF32 {
}; };
//! UTF-32 little endian enocoding. //! UTF-32 little endian enocoding.
template <typename CharType = unsigned> template<typename CharType = unsigned>
struct UTF32LE : UTF32<CharType> { struct UTF32LE : UTF32<CharType> {
template <typename InputByteStream> template <typename InputByteStream>
static CharType TakeBOM(InputByteStream& is) { static CharType TakeBOM(InputByteStream& is) {
@ -801,7 +492,7 @@ struct UTF32LE : UTF32<CharType> {
}; };
//! UTF-32 big endian encoding. //! UTF-32 big endian encoding.
template <typename CharType = unsigned> template<typename CharType = unsigned>
struct UTF32BE : UTF32<CharType> { struct UTF32BE : UTF32<CharType> {
template <typename InputByteStream> template <typename InputByteStream>
static CharType TakeBOM(InputByteStream& is) { static CharType TakeBOM(InputByteStream& is) {
@ -847,19 +538,19 @@ struct UTF32BE : UTF32<CharType> {
\tparam CharType Code unit for storing 7-bit ASCII data. Default is char. \tparam CharType Code unit for storing 7-bit ASCII data. Default is char.
\note implements Encoding concept \note implements Encoding concept
*/ */
template <typename CharType = char> template<typename CharType = char>
struct ASCII { struct ASCII {
typedef CharType Ch; typedef CharType Ch;
enum { supportUnicode = 0 }; enum { supportUnicode = 0 };
template <typename OutputStream> template<typename OutputStream>
static void Encode(OutputStream& os, unsigned codepoint) { static void Encode(OutputStream& os, unsigned codepoint) {
RAPIDJSON_ASSERT(codepoint <= 0x7F); RAPIDJSON_ASSERT(codepoint <= 0x7F);
os.Put(static_cast<Ch>(codepoint & 0xFF)); os.Put(static_cast<Ch>(codepoint & 0xFF));
} }
template <typename OutputStream> template<typename OutputStream>
static void EncodeUnsafe(OutputStream& os, unsigned codepoint) { static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
RAPIDJSON_ASSERT(codepoint <= 0x7F); RAPIDJSON_ASSERT(codepoint <= 0x7F);
PutUnsafe(os, static_cast<Ch>(codepoint & 0xFF)); PutUnsafe(os, static_cast<Ch>(codepoint & 0xFF));
@ -920,7 +611,7 @@ enum UTFType {
//! Dynamically select encoding according to stream's runtime-specified UTF encoding type. //! Dynamically select encoding according to stream's runtime-specified UTF encoding type.
/*! \note This class can be used with AutoUTFInputtStream and AutoUTFOutputStream, which provides GetType(). /*! \note This class can be used with AutoUTFInputtStream and AutoUTFOutputStream, which provides GetType().
*/ */
template <typename CharType> template<typename CharType>
struct AutoUTF { struct AutoUTF {
typedef CharType Ch; typedef CharType Ch;
@ -928,14 +619,14 @@ struct AutoUTF {
#define RAPIDJSON_ENCODINGS_FUNC(x) UTF8<Ch>::x, UTF16LE<Ch>::x, UTF16BE<Ch>::x, UTF32LE<Ch>::x, UTF32BE<Ch>::x #define RAPIDJSON_ENCODINGS_FUNC(x) UTF8<Ch>::x, UTF16LE<Ch>::x, UTF16BE<Ch>::x, UTF32LE<Ch>::x, UTF32BE<Ch>::x
template <typename OutputStream> template<typename OutputStream>
static RAPIDJSON_FORCEINLINE void Encode(OutputStream& os, unsigned codepoint) { static RAPIDJSON_FORCEINLINE void Encode(OutputStream& os, unsigned codepoint) {
typedef void (*EncodeFunc)(OutputStream&, unsigned); typedef void (*EncodeFunc)(OutputStream&, unsigned);
static const EncodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Encode) }; static const EncodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Encode) };
(*f[os.GetType()])(os, codepoint); (*f[os.GetType()])(os, codepoint);
} }
template <typename OutputStream> template<typename OutputStream>
static RAPIDJSON_FORCEINLINE void EncodeUnsafe(OutputStream& os, unsigned codepoint) { static RAPIDJSON_FORCEINLINE void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
typedef void (*EncodeFunc)(OutputStream&, unsigned); typedef void (*EncodeFunc)(OutputStream&, unsigned);
static const EncodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(EncodeUnsafe) }; static const EncodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(EncodeUnsafe) };
@ -963,10 +654,10 @@ struct AutoUTF {
// Transcoder // Transcoder
//! Encoding conversion. //! Encoding conversion.
template <typename SourceEncoding, typename TargetEncoding> template<typename SourceEncoding, typename TargetEncoding>
struct Transcoder { struct Transcoder {
//! Take one Unicode codepoint from source encoding, convert it to target encoding and put it to the output stream. //! Take one Unicode codepoint from source encoding, convert it to target encoding and put it to the output stream.
template <typename InputStream, typename OutputStream> template<typename InputStream, typename OutputStream>
static RAPIDJSON_FORCEINLINE bool Transcode(InputStream& is, OutputStream& os) { static RAPIDJSON_FORCEINLINE bool Transcode(InputStream& is, OutputStream& os) {
unsigned codepoint; unsigned codepoint;
if (!SourceEncoding::Decode(is, &codepoint)) if (!SourceEncoding::Decode(is, &codepoint))
@ -975,7 +666,7 @@ struct Transcoder {
return true; return true;
} }
template <typename InputStream, typename OutputStream> template<typename InputStream, typename OutputStream>
static RAPIDJSON_FORCEINLINE bool TranscodeUnsafe(InputStream& is, OutputStream& os) { static RAPIDJSON_FORCEINLINE bool TranscodeUnsafe(InputStream& is, OutputStream& os) {
unsigned codepoint; unsigned codepoint;
if (!SourceEncoding::Decode(is, &codepoint)) if (!SourceEncoding::Decode(is, &codepoint))
@ -985,32 +676,32 @@ struct Transcoder {
} }
//! Validate one Unicode codepoint from an encoded stream. //! Validate one Unicode codepoint from an encoded stream.
template <typename InputStream, typename OutputStream> template<typename InputStream, typename OutputStream>
static RAPIDJSON_FORCEINLINE bool Validate(InputStream& is, OutputStream& os) { static RAPIDJSON_FORCEINLINE bool Validate(InputStream& is, OutputStream& os) {
return Transcode(is, os); // Since source/target encoding is different, must transcode. return Transcode(is, os); // Since source/target encoding is different, must transcode.
} }
}; };
// Forward declaration. // Forward declaration.
template <typename Stream> template<typename Stream>
inline void PutUnsafe(Stream& stream, typename Stream::Ch c); inline void PutUnsafe(Stream& stream, typename Stream::Ch c);
//! Specialization of Transcoder with same source and target encoding. //! Specialization of Transcoder with same source and target encoding.
template <typename Encoding> template<typename Encoding>
struct Transcoder<Encoding, Encoding> { struct Transcoder<Encoding, Encoding> {
template <typename InputStream, typename OutputStream> template<typename InputStream, typename OutputStream>
static RAPIDJSON_FORCEINLINE bool Transcode(InputStream& is, OutputStream& os) { static RAPIDJSON_FORCEINLINE bool Transcode(InputStream& is, OutputStream& os) {
os.Put(is.Take()); // Just copy one code unit. This semantic is different from primary template class. os.Put(is.Take()); // Just copy one code unit. This semantic is different from primary template class.
return true; return true;
} }
template <typename InputStream, typename OutputStream> template<typename InputStream, typename OutputStream>
static RAPIDJSON_FORCEINLINE bool TranscodeUnsafe(InputStream& is, OutputStream& os) { static RAPIDJSON_FORCEINLINE bool TranscodeUnsafe(InputStream& is, OutputStream& os) {
PutUnsafe(os, is.Take()); // Just copy one code unit. This semantic is different from primary template class. PutUnsafe(os, is.Take()); // Just copy one code unit. This semantic is different from primary template class.
return true; return true;
} }
template <typename InputStream, typename OutputStream> template<typename InputStream, typename OutputStream>
static RAPIDJSON_FORCEINLINE bool Validate(InputStream& is, OutputStream& os) { static RAPIDJSON_FORCEINLINE bool Validate(InputStream& is, OutputStream& os) {
return Encoding::Validate(is, os); // source/target encoding are the same return Encoding::Validate(is, os); // source/target encoding are the same
} }

View File

@ -19,8 +19,8 @@
#ifdef __clang__ #ifdef __clang__
RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(switch - enum) RAPIDJSON_DIAG_OFF(switch-enum)
RAPIDJSON_DIAG_OFF(covered - switch - default) RAPIDJSON_DIAG_OFF(covered-switch-default)
#endif #endif
RAPIDJSON_NAMESPACE_BEGIN RAPIDJSON_NAMESPACE_BEGIN
@ -35,52 +35,33 @@ RAPIDJSON_NAMESPACE_BEGIN
*/ */
inline const RAPIDJSON_ERROR_CHARTYPE* GetParseError_En(ParseErrorCode parseErrorCode) { inline const RAPIDJSON_ERROR_CHARTYPE* GetParseError_En(ParseErrorCode parseErrorCode) {
switch (parseErrorCode) { switch (parseErrorCode) {
case kParseErrorNone: case kParseErrorNone: return RAPIDJSON_ERROR_STRING("No error.");
return RAPIDJSON_ERROR_STRING("No error.");
case kParseErrorDocumentEmpty: case kParseErrorDocumentEmpty: return RAPIDJSON_ERROR_STRING("The document is empty.");
return RAPIDJSON_ERROR_STRING("The document is empty."); case kParseErrorDocumentRootNotSingular: return RAPIDJSON_ERROR_STRING("The document root must not be followed by other values.");
case kParseErrorDocumentRootNotSingular:
return RAPIDJSON_ERROR_STRING("The document root must not be followed by other values.");
case kParseErrorValueInvalid: case kParseErrorValueInvalid: return RAPIDJSON_ERROR_STRING("Invalid value.");
return RAPIDJSON_ERROR_STRING("Invalid value.");
case kParseErrorObjectMissName: case kParseErrorObjectMissName: return RAPIDJSON_ERROR_STRING("Missing a name for object member.");
return RAPIDJSON_ERROR_STRING("Missing a name for object member."); case kParseErrorObjectMissColon: return RAPIDJSON_ERROR_STRING("Missing a colon after a name of object member.");
case kParseErrorObjectMissColon: case kParseErrorObjectMissCommaOrCurlyBracket: return RAPIDJSON_ERROR_STRING("Missing a comma or '}' after an object member.");
return RAPIDJSON_ERROR_STRING("Missing a colon after a name of object member.");
case kParseErrorObjectMissCommaOrCurlyBracket:
return RAPIDJSON_ERROR_STRING("Missing a comma or '}' after an object member.");
case kParseErrorArrayMissCommaOrSquareBracket: case kParseErrorArrayMissCommaOrSquareBracket: return RAPIDJSON_ERROR_STRING("Missing a comma or ']' after an array element.");
return RAPIDJSON_ERROR_STRING("Missing a comma or ']' after an array element.");
case kParseErrorStringUnicodeEscapeInvalidHex: case kParseErrorStringUnicodeEscapeInvalidHex: return RAPIDJSON_ERROR_STRING("Incorrect hex digit after \\u escape in string.");
return RAPIDJSON_ERROR_STRING("Incorrect hex digit after \\u escape in string."); case kParseErrorStringUnicodeSurrogateInvalid: return RAPIDJSON_ERROR_STRING("The surrogate pair in string is invalid.");
case kParseErrorStringUnicodeSurrogateInvalid: case kParseErrorStringEscapeInvalid: return RAPIDJSON_ERROR_STRING("Invalid escape character in string.");
return RAPIDJSON_ERROR_STRING("The surrogate pair in string is invalid."); case kParseErrorStringMissQuotationMark: return RAPIDJSON_ERROR_STRING("Missing a closing quotation mark in string.");
case kParseErrorStringEscapeInvalid: case kParseErrorStringInvalidEncoding: return RAPIDJSON_ERROR_STRING("Invalid encoding in string.");
return RAPIDJSON_ERROR_STRING("Invalid escape character in string.");
case kParseErrorStringMissQuotationMark:
return RAPIDJSON_ERROR_STRING("Missing a closing quotation mark in string.");
case kParseErrorStringInvalidEncoding:
return RAPIDJSON_ERROR_STRING("Invalid encoding in string.");
case kParseErrorNumberTooBig: case kParseErrorNumberTooBig: return RAPIDJSON_ERROR_STRING("Number too big to be stored in double.");
return RAPIDJSON_ERROR_STRING("Number too big to be stored in double."); case kParseErrorNumberMissFraction: return RAPIDJSON_ERROR_STRING("Miss fraction part in number.");
case kParseErrorNumberMissFraction: case kParseErrorNumberMissExponent: return RAPIDJSON_ERROR_STRING("Miss exponent in number.");
return RAPIDJSON_ERROR_STRING("Miss fraction part in number.");
case kParseErrorNumberMissExponent:
return RAPIDJSON_ERROR_STRING("Miss exponent in number.");
case kParseErrorTermination: case kParseErrorTermination: return RAPIDJSON_ERROR_STRING("Terminate parsing due to Handler error.");
return RAPIDJSON_ERROR_STRING("Terminate parsing due to Handler error."); case kParseErrorUnspecificSyntaxError: return RAPIDJSON_ERROR_STRING("Unspecific syntax error.");
case kParseErrorUnspecificSyntaxError:
return RAPIDJSON_ERROR_STRING("Unspecific syntax error.");
default: default: return RAPIDJSON_ERROR_STRING("Unknown error.");
return RAPIDJSON_ERROR_STRING("Unknown error.");
} }
} }
@ -94,69 +75,41 @@ inline const RAPIDJSON_ERROR_CHARTYPE* GetParseError_En(ParseErrorCode parseErro
*/ */
inline const RAPIDJSON_ERROR_CHARTYPE* GetValidateError_En(ValidateErrorCode validateErrorCode) { inline const RAPIDJSON_ERROR_CHARTYPE* GetValidateError_En(ValidateErrorCode validateErrorCode) {
switch (validateErrorCode) { switch (validateErrorCode) {
case kValidateErrors: case kValidateErrors: return RAPIDJSON_ERROR_STRING("One or more validation errors have occurred");
return RAPIDJSON_ERROR_STRING("One or more validation errors have occurred"); case kValidateErrorNone: return RAPIDJSON_ERROR_STRING("No error.");
case kValidateErrorNone:
return RAPIDJSON_ERROR_STRING("No error.");
case kValidateErrorMultipleOf: case kValidateErrorMultipleOf: return RAPIDJSON_ERROR_STRING("Number '%actual' is not a multiple of the 'multipleOf' value '%expected'.");
return RAPIDJSON_ERROR_STRING("Number '%actual' is not a multiple of the 'multipleOf' value '%expected'."); case kValidateErrorMaximum: return RAPIDJSON_ERROR_STRING("Number '%actual' is greater than the 'maximum' value '%expected'.");
case kValidateErrorMaximum: case kValidateErrorExclusiveMaximum: return RAPIDJSON_ERROR_STRING("Number '%actual' is greater than or equal to the 'exclusiveMaximum' value '%expected'.");
return RAPIDJSON_ERROR_STRING("Number '%actual' is greater than the 'maximum' value '%expected'."); case kValidateErrorMinimum: return RAPIDJSON_ERROR_STRING("Number '%actual' is less than the 'minimum' value '%expected'.");
case kValidateErrorExclusiveMaximum: case kValidateErrorExclusiveMinimum: return RAPIDJSON_ERROR_STRING("Number '%actual' is less than or equal to the 'exclusiveMinimum' value '%expected'.");
return RAPIDJSON_ERROR_STRING("Number '%actual' is greater than or equal to the 'exclusiveMaximum' value '%expected'.");
case kValidateErrorMinimum:
return RAPIDJSON_ERROR_STRING("Number '%actual' is less than the 'minimum' value '%expected'.");
case kValidateErrorExclusiveMinimum:
return RAPIDJSON_ERROR_STRING("Number '%actual' is less than or equal to the 'exclusiveMinimum' value '%expected'.");
case kValidateErrorMaxLength: case kValidateErrorMaxLength: return RAPIDJSON_ERROR_STRING("String '%actual' is longer than the 'maxLength' value '%expected'.");
return RAPIDJSON_ERROR_STRING("String '%actual' is longer than the 'maxLength' value '%expected'."); case kValidateErrorMinLength: return RAPIDJSON_ERROR_STRING("String '%actual' is shorter than the 'minLength' value '%expected'.");
case kValidateErrorMinLength: case kValidateErrorPattern: return RAPIDJSON_ERROR_STRING("String '%actual' does not match the 'pattern' regular expression.");
return RAPIDJSON_ERROR_STRING("String '%actual' is shorter than the 'minLength' value '%expected'.");
case kValidateErrorPattern:
return RAPIDJSON_ERROR_STRING("String '%actual' does not match the 'pattern' regular expression.");
case kValidateErrorMaxItems: case kValidateErrorMaxItems: return RAPIDJSON_ERROR_STRING("Array of length '%actual' is longer than the 'maxItems' value '%expected'.");
return RAPIDJSON_ERROR_STRING("Array of length '%actual' is longer than the 'maxItems' value '%expected'."); case kValidateErrorMinItems: return RAPIDJSON_ERROR_STRING("Array of length '%actual' is shorter than the 'minItems' value '%expected'.");
case kValidateErrorMinItems: case kValidateErrorUniqueItems: return RAPIDJSON_ERROR_STRING("Array has duplicate items at indices '%duplicates' but 'uniqueItems' is true.");
return RAPIDJSON_ERROR_STRING("Array of length '%actual' is shorter than the 'minItems' value '%expected'."); case kValidateErrorAdditionalItems: return RAPIDJSON_ERROR_STRING("Array has an additional item at index '%disallowed' that is not allowed by the schema.");
case kValidateErrorUniqueItems:
return RAPIDJSON_ERROR_STRING("Array has duplicate items at indices '%duplicates' but 'uniqueItems' is true.");
case kValidateErrorAdditionalItems:
return RAPIDJSON_ERROR_STRING("Array has an additional item at index '%disallowed' that is not allowed by the schema.");
case kValidateErrorMaxProperties: case kValidateErrorMaxProperties: return RAPIDJSON_ERROR_STRING("Object has '%actual' members which is more than 'maxProperties' value '%expected'.");
return RAPIDJSON_ERROR_STRING("Object has '%actual' members which is more than 'maxProperties' value '%expected'."); case kValidateErrorMinProperties: return RAPIDJSON_ERROR_STRING("Object has '%actual' members which is less than 'minProperties' value '%expected'.");
case kValidateErrorMinProperties: case kValidateErrorRequired: return RAPIDJSON_ERROR_STRING("Object is missing the following members required by the schema: '%missing'.");
return RAPIDJSON_ERROR_STRING("Object has '%actual' members which is less than 'minProperties' value '%expected'."); case kValidateErrorAdditionalProperties: return RAPIDJSON_ERROR_STRING("Object has an additional member '%disallowed' that is not allowed by the schema.");
case kValidateErrorRequired: case kValidateErrorPatternProperties: return RAPIDJSON_ERROR_STRING("Object has 'patternProperties' that are not allowed by the schema.");
return RAPIDJSON_ERROR_STRING("Object is missing the following members required by the schema: '%missing'."); case kValidateErrorDependencies: return RAPIDJSON_ERROR_STRING("Object has missing property or schema dependencies, refer to following errors.");
case kValidateErrorAdditionalProperties:
return RAPIDJSON_ERROR_STRING("Object has an additional member '%disallowed' that is not allowed by the schema.");
case kValidateErrorPatternProperties:
return RAPIDJSON_ERROR_STRING("Object has 'patternProperties' that are not allowed by the schema.");
case kValidateErrorDependencies:
return RAPIDJSON_ERROR_STRING("Object has missing property or schema dependencies, refer to following errors.");
case kValidateErrorEnum: case kValidateErrorEnum: return RAPIDJSON_ERROR_STRING("Property has a value that is not one of its allowed enumerated values.");
return RAPIDJSON_ERROR_STRING("Property has a value that is not one of its allowed enumerated values."); case kValidateErrorType: return RAPIDJSON_ERROR_STRING("Property has a type '%actual' that is not in the following list: '%expected'.");
case kValidateErrorType:
return RAPIDJSON_ERROR_STRING("Property has a type '%actual' that is not in the following list: '%expected'.");
case kValidateErrorOneOf: case kValidateErrorOneOf: return RAPIDJSON_ERROR_STRING("Property did not match any of the sub-schemas specified by 'oneOf', refer to following errors.");
return RAPIDJSON_ERROR_STRING("Property did not match any of the sub-schemas specified by 'oneOf', refer to following errors."); case kValidateErrorOneOfMatch: return RAPIDJSON_ERROR_STRING("Property matched more than one of the sub-schemas specified by 'oneOf'.");
case kValidateErrorOneOfMatch: case kValidateErrorAllOf: return RAPIDJSON_ERROR_STRING("Property did not match all of the sub-schemas specified by 'allOf', refer to following errors.");
return RAPIDJSON_ERROR_STRING("Property matched more than one of the sub-schemas specified by 'oneOf'."); case kValidateErrorAnyOf: return RAPIDJSON_ERROR_STRING("Property did not match any of the sub-schemas specified by 'anyOf', refer to following errors.");
case kValidateErrorAllOf: case kValidateErrorNot: return RAPIDJSON_ERROR_STRING("Property matched the sub-schema specified by 'not'.");
return RAPIDJSON_ERROR_STRING("Property did not match all of the sub-schemas specified by 'allOf', refer to following errors.");
case kValidateErrorAnyOf:
return RAPIDJSON_ERROR_STRING("Property did not match any of the sub-schemas specified by 'anyOf', refer to following errors.");
case kValidateErrorNot:
return RAPIDJSON_ERROR_STRING("Property matched the sub-schema specified by 'not'.");
default: default: return RAPIDJSON_ERROR_STRING("Unknown error.");
return RAPIDJSON_ERROR_STRING("Unknown error.");
} }
} }

View File

@ -106,7 +106,6 @@ enum ParseErrorCode {
struct ParseResult { struct ParseResult {
//!! Unspecified boolean type //!! Unspecified boolean type
typedef bool (ParseResult::*BooleanType)() const; typedef bool (ParseResult::*BooleanType)() const;
public: public:
//! Default constructor, no error. //! Default constructor, no error.
ParseResult() : code_(kParseErrorNone), offset_(0) {} ParseResult() : code_(kParseErrorNone), offset_(0) {}
@ -125,19 +124,16 @@ public:
bool operator==(const ParseResult& that) const { return code_ == that.code_; } bool operator==(const ParseResult& that) const { return code_ == that.code_; }
bool operator==(ParseErrorCode code) const { return code_ == code; } bool operator==(ParseErrorCode code) const { return code_ == code; }
friend bool operator==(ParseErrorCode code, const ParseResult& err) { return code == err.code_; } friend bool operator==(ParseErrorCode code, const ParseResult & err) { return code == err.code_; }
bool operator!=(const ParseResult& that) const { return !(*this == that); } bool operator!=(const ParseResult& that) const { return !(*this == that); }
bool operator!=(ParseErrorCode code) const { return !(*this == code); } bool operator!=(ParseErrorCode code) const { return !(*this == code); }
friend bool operator!=(ParseErrorCode code, const ParseResult& err) { return err != code; } friend bool operator!=(ParseErrorCode code, const ParseResult & err) { return err != code; }
//! Reset error code. //! Reset error code.
void Clear() { Set(kParseErrorNone); } void Clear() { Set(kParseErrorNone); }
//! Update error code and offset. //! Update error code and offset.
void Set(ParseErrorCode code, size_t offset = 0) { void Set(ParseErrorCode code, size_t offset = 0) { code_ = code; offset_ = offset; }
code_ = code;
offset_ = offset;
}
private: private:
ParseErrorCode code_; ParseErrorCode code_;

View File

@ -21,8 +21,8 @@
#ifdef __clang__ #ifdef __clang__
RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(padded) RAPIDJSON_DIAG_OFF(padded)
RAPIDJSON_DIAG_OFF(unreachable - code) RAPIDJSON_DIAG_OFF(unreachable-code)
RAPIDJSON_DIAG_OFF(missing - noreturn) RAPIDJSON_DIAG_OFF(missing-noreturn)
#endif #endif
RAPIDJSON_NAMESPACE_BEGIN RAPIDJSON_NAMESPACE_BEGIN
@ -48,24 +48,14 @@ public:
} }
Ch Peek() const { return *current_; } Ch Peek() const { return *current_; }
Ch Take() { Ch Take() { Ch c = *current_; Read(); return c; }
Ch c = *current_;
Read();
return c;
}
size_t Tell() const { return count_ + static_cast<size_t>(current_ - buffer_); } size_t Tell() const { return count_ + static_cast<size_t>(current_ - buffer_); }
// Not implemented // Not implemented
void Put(Ch) { RAPIDJSON_ASSERT(false); } void Put(Ch) { RAPIDJSON_ASSERT(false); }
void Flush() { RAPIDJSON_ASSERT(false); } void Flush() { RAPIDJSON_ASSERT(false); }
Ch* PutBegin() { Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
RAPIDJSON_ASSERT(false); size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
return 0;
}
size_t PutEnd(Ch*) {
RAPIDJSON_ASSERT(false);
return 0;
}
// For encoding detection only. // For encoding detection only.
const Ch* Peek4() const { const Ch* Peek4() const {
@ -91,10 +81,10 @@ private:
} }
std::FILE* fp_; std::FILE* fp_;
Ch* buffer_; Ch *buffer_;
size_t bufferSize_; size_t bufferSize_;
Ch* bufferLast_; Ch *bufferLast_;
Ch* current_; Ch *current_;
size_t readCount_; size_t readCount_;
size_t count_; //!< Number of characters read size_t count_; //!< Number of characters read
bool eof_; bool eof_;

View File

@ -20,7 +20,7 @@
#ifdef __clang__ #ifdef __clang__
RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(unreachable - code) RAPIDJSON_DIAG_OFF(unreachable-code)
#endif #endif
RAPIDJSON_NAMESPACE_BEGIN RAPIDJSON_NAMESPACE_BEGIN
@ -72,26 +72,11 @@ public:
} }
// Not implemented // Not implemented
char Peek() const { char Peek() const { RAPIDJSON_ASSERT(false); return 0; }
RAPIDJSON_ASSERT(false); char Take() { RAPIDJSON_ASSERT(false); return 0; }
return 0; size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; }
} char* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
char Take() { size_t PutEnd(char*) { RAPIDJSON_ASSERT(false); return 0; }
RAPIDJSON_ASSERT(false);
return 0;
}
size_t Tell() const {
RAPIDJSON_ASSERT(false);
return 0;
}
char* PutBegin() {
RAPIDJSON_ASSERT(false);
return 0;
}
size_t PutEnd(char*) {
RAPIDJSON_ASSERT(false);
return 0;
}
private: private:
// Prohibit copy constructor & assignment operator. // Prohibit copy constructor & assignment operator.
@ -99,13 +84,13 @@ private:
FileWriteStream& operator=(const FileWriteStream&); FileWriteStream& operator=(const FileWriteStream&);
std::FILE* fp_; std::FILE* fp_;
char* buffer_; char *buffer_;
char* bufferEnd_; char *bufferEnd_;
char* current_; char *current_;
}; };
//! Implement specialized version of PutN() with memset() for better performance. //! Implement specialized version of PutN() with memset() for better performance.
template <> template<>
inline void PutN(FileWriteStream& stream, char c, size_t n) { inline void PutN(FileWriteStream& stream, char c, size_t n) {
stream.PutN(c, n); stream.PutN(c, n);
} }

View File

@ -21,26 +21,17 @@ RAPIDJSON_NAMESPACE_BEGIN
// encodings.h // encodings.h
template <typename CharType> template<typename CharType> struct UTF8;
struct UTF8; template<typename CharType> struct UTF16;
template <typename CharType> template<typename CharType> struct UTF16BE;
struct UTF16; template<typename CharType> struct UTF16LE;
template <typename CharType> template<typename CharType> struct UTF32;
struct UTF16BE; template<typename CharType> struct UTF32BE;
template <typename CharType> template<typename CharType> struct UTF32LE;
struct UTF16LE; template<typename CharType> struct ASCII;
template <typename CharType> template<typename CharType> struct AutoUTF;
struct UTF32;
template <typename CharType>
struct UTF32BE;
template <typename CharType>
struct UTF32LE;
template <typename CharType>
struct ASCII;
template <typename CharType>
struct AutoUTF;
template <typename SourceEncoding, typename TargetEncoding> template<typename SourceEncoding, typename TargetEncoding>
struct Transcoder; struct Transcoder;
// allocators.h // allocators.h
@ -55,12 +46,12 @@ class MemoryPoolAllocator;
template <typename Encoding> template <typename Encoding>
struct GenericStringStream; struct GenericStringStream;
typedef GenericStringStream<UTF8<char>> StringStream; typedef GenericStringStream<UTF8<char> > StringStream;
template <typename Encoding> template <typename Encoding>
struct GenericInsituStringStream; struct GenericInsituStringStream;
typedef GenericInsituStringStream<UTF8<char>> InsituStringStream; typedef GenericInsituStringStream<UTF8<char> > InsituStringStream;
// stringbuffer.h // stringbuffer.h
@ -90,7 +81,7 @@ struct MemoryStream;
// reader.h // reader.h
template <typename Encoding, typename Derived> template<typename Encoding, typename Derived>
struct BaseReaderHandler; struct BaseReaderHandler;
template <typename SourceEncoding, typename TargetEncoding, typename StackAllocator> template <typename SourceEncoding, typename TargetEncoding, typename StackAllocator>
@ -100,12 +91,12 @@ typedef GenericReader<UTF8<char>, UTF8<char>, CrtAllocator> Reader;
// writer.h // writer.h
template <typename OutputStream, typename SourceEncoding, typename TargetEncoding, typename StackAllocator, unsigned writeFlags> template<typename OutputStream, typename SourceEncoding, typename TargetEncoding, typename StackAllocator, unsigned writeFlags>
class Writer; class Writer;
// prettywriter.h // prettywriter.h
template <typename OutputStream, typename SourceEncoding, typename TargetEncoding, typename StackAllocator, unsigned writeFlags> template<typename OutputStream, typename SourceEncoding, typename TargetEncoding, typename StackAllocator, unsigned writeFlags>
class PrettyWriter; class PrettyWriter;
// document.h // document.h
@ -116,13 +107,13 @@ class GenericMember;
template <bool Const, typename Encoding, typename Allocator> template <bool Const, typename Encoding, typename Allocator>
class GenericMemberIterator; class GenericMemberIterator;
template <typename CharType> template<typename CharType>
struct GenericStringRef; struct GenericStringRef;
template <typename Encoding, typename Allocator> template <typename Encoding, typename Allocator>
class GenericValue; class GenericValue;
typedef GenericValue<UTF8<char>, MemoryPoolAllocator<CrtAllocator>> Value; typedef GenericValue<UTF8<char>, MemoryPoolAllocator<CrtAllocator> > Value;
template <typename Encoding, typename Allocator, typename StackAllocator> template <typename Encoding, typename Allocator, typename StackAllocator>
class GenericDocument; class GenericDocument;

View File

@ -25,8 +25,8 @@
RAPIDJSON_NAMESPACE_BEGIN RAPIDJSON_NAMESPACE_BEGIN
namespace internal { namespace internal {
class BigInteger { class BigInteger {
public: public:
typedef uint64_t Type; typedef uint64_t Type;
BigInteger(const BigInteger& rhs) : count_(rhs.count_) { BigInteger(const BigInteger& rhs) : count_(rhs.count_) {
@ -52,7 +52,8 @@ namespace internal {
AppendDecimal64(decimals + i, decimals + i + length); AppendDecimal64(decimals + i, decimals + i + length);
} }
BigInteger& operator=(const BigInteger& rhs) { BigInteger& operator=(const BigInteger &rhs)
{
if (this != &rhs) { if (this != &rhs) {
count_ = rhs.count_; count_ = rhs.count_;
std::memcpy(digits_, rhs.digits_, count_ * sizeof(Type)); std::memcpy(digits_, rhs.digits_, count_ * sizeof(Type));
@ -187,16 +188,8 @@ namespace internal {
RAPIDJSON_ASSERT(cmp != 0); RAPIDJSON_ASSERT(cmp != 0);
const BigInteger *a, *b; // Makes a > b const BigInteger *a, *b; // Makes a > b
bool ret; bool ret;
if (cmp < 0) { if (cmp < 0) { a = &rhs; b = this; ret = true; }
a = &rhs; else { a = this; b = &rhs; ret = false; }
b = this;
ret = true;
}
else {
a = this;
b = &rhs;
ret = false;
}
Type borrow = 0; Type borrow = 0;
for (size_t i = 0; i < a->count_; i++) { for (size_t i = 0; i < a->count_; i++) {
@ -224,13 +217,10 @@ namespace internal {
} }
size_t GetCount() const { return count_; } size_t GetCount() const { return count_; }
Type GetDigit(size_t index) const { Type GetDigit(size_t index) const { RAPIDJSON_ASSERT(index < count_); return digits_[index]; }
RAPIDJSON_ASSERT(index < count_);
return digits_[index];
}
bool IsZero() const { return count_ == 1 && digits_[0] == 0; } bool IsZero() const { return count_ == 1 && digits_[0] == 0; }
private: private:
void AppendDecimal64(const char* begin, const char* end) { void AppendDecimal64(const char* begin, const char* end) {
uint64_t u = ParseUint64(begin, end); uint64_t u = ParseUint64(begin, end);
if (IsZero()) if (IsZero())
@ -292,7 +282,7 @@ namespace internal {
Type digits_[kCapacity]; Type digits_[kCapacity];
size_t count_; size_t count_;
}; };
} // namespace internal } // namespace internal
RAPIDJSON_NAMESPACE_END RAPIDJSON_NAMESPACE_END

View File

@ -29,7 +29,7 @@
RAPIDJSON_NAMESPACE_BEGIN RAPIDJSON_NAMESPACE_BEGIN
namespace internal { namespace internal {
inline uint32_t clzll(uint64_t x) { inline uint32_t clzll(uint64_t x) {
// Passing 0 to __builtin_clzll is UB in GCC and results in an // Passing 0 to __builtin_clzll is UB in GCC and results in an
// infinite loop in the software implementation. // infinite loop in the software implementation.
RAPIDJSON_ASSERT(x != 0); RAPIDJSON_ASSERT(x != 0);
@ -61,7 +61,7 @@ namespace internal {
return r; return r;
#endif // _MSC_VER #endif // _MSC_VER
} }
#define RAPIDJSON_CLZLL RAPIDJSON_NAMESPACE::internal::clzll #define RAPIDJSON_CLZLL RAPIDJSON_NAMESPACE::internal::clzll

View File

@ -32,16 +32,16 @@ RAPIDJSON_NAMESPACE_BEGIN
namespace internal { namespace internal {
#ifdef __GNUC__ #ifdef __GNUC__
RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(effc++) RAPIDJSON_DIAG_OFF(effc++)
#endif #endif
#ifdef __clang__ #ifdef __clang__
RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(padded) RAPIDJSON_DIAG_OFF(padded)
#endif #endif
struct DiyFp { struct DiyFp {
DiyFp() : f(), e() {} DiyFp() : f(), e() {}
DiyFp(uint64_t fp, int exp) : f(fp), e(exp) {} DiyFp(uint64_t fp, int exp) : f(fp), e(exp) {}
@ -128,7 +128,7 @@ namespace internal {
union { union {
double d; double d;
uint64_t u64; uint64_t u64;
} u; }u;
RAPIDJSON_ASSERT(f <= kDpHiddenBit + kDpSignificandMask); RAPIDJSON_ASSERT(f <= kDpHiddenBit + kDpSignificandMask);
if (e < kDpDenormalExponent) { if (e < kDpDenormalExponent) {
// Underflow. // Underflow.
@ -138,7 +138,8 @@ namespace internal {
// Overflow. // Overflow.
return std::numeric_limits<double>::infinity(); return std::numeric_limits<double>::infinity();
} }
const uint64_t be = (e == kDpDenormalExponent && (f & kDpHiddenBit) == 0) ? 0 : static_cast<uint64_t>(e + kDpExponentBias); const uint64_t be = (e == kDpDenormalExponent && (f & kDpHiddenBit) == 0) ? 0 :
static_cast<uint64_t>(e + kDpExponentBias);
u.u64 = (f & kDpSignificandMask) | (be << kDpSignificandSize); u.u64 = (f & kDpSignificandMask) | (be << kDpSignificandSize);
return u.d; return u.d;
} }
@ -155,9 +156,9 @@ namespace internal {
uint64_t f; uint64_t f;
int e; int e;
}; };
inline DiyFp GetCachedPowerByIndex(size_t index) { inline DiyFp GetCachedPowerByIndex(size_t index) {
// 10^-348, 10^-340, ..., 10^340 // 10^-348, 10^-340, ..., 10^340
static const uint64_t kCachedPowers_F[] = { static const uint64_t kCachedPowers_F[] = {
RAPIDJSON_UINT64_C2(0xfa8fd5a0, 0x081c0288), RAPIDJSON_UINT64_C2(0xbaaee17f, 0xa23ebf76), RAPIDJSON_UINT64_C2(0xfa8fd5a0, 0x081c0288), RAPIDJSON_UINT64_C2(0xbaaee17f, 0xa23ebf76),
@ -218,9 +219,9 @@ namespace internal {
}; };
RAPIDJSON_ASSERT(index < 87); RAPIDJSON_ASSERT(index < 87);
return DiyFp(kCachedPowers_F[index], kCachedPowers_E[index]); return DiyFp(kCachedPowers_F[index], kCachedPowers_E[index]);
} }
inline DiyFp GetCachedPower(int e, int* K) { inline DiyFp GetCachedPower(int e, int* K) {
//int k = static_cast<int>(ceil((-61 - e) * 0.30102999566398114)) + 374; //int k = static_cast<int>(ceil((-61 - e) * 0.30102999566398114)) + 374;
double dk = (-61 - e) * 0.30102999566398114 + 347; // dk must be positive, so can do ceiling in positive double dk = (-61 - e) * 0.30102999566398114 + 347; // dk must be positive, so can do ceiling in positive
@ -232,22 +233,22 @@ namespace internal {
*K = -(-348 + static_cast<int>(index << 3)); // decimal exponent no need lookup table *K = -(-348 + static_cast<int>(index << 3)); // decimal exponent no need lookup table
return GetCachedPowerByIndex(index); return GetCachedPowerByIndex(index);
} }
inline DiyFp GetCachedPower10(int exp, int* outExp) { inline DiyFp GetCachedPower10(int exp, int *outExp) {
RAPIDJSON_ASSERT(exp >= -348); RAPIDJSON_ASSERT(exp >= -348);
unsigned index = static_cast<unsigned>(exp + 348) / 8u; unsigned index = static_cast<unsigned>(exp + 348) / 8u;
*outExp = -348 + static_cast<int>(index) * 8; *outExp = -348 + static_cast<int>(index) * 8;
return GetCachedPowerByIndex(index); return GetCachedPowerByIndex(index);
} }
#ifdef __GNUC__ #ifdef __GNUC__
RAPIDJSON_DIAG_POP RAPIDJSON_DIAG_POP
#endif #endif
#ifdef __clang__ #ifdef __clang__
RAPIDJSON_DIAG_POP RAPIDJSON_DIAG_POP
RAPIDJSON_DIAG_OFF(padded) RAPIDJSON_DIAG_OFF(padded)
#endif #endif
} // namespace internal } // namespace internal

View File

@ -27,21 +27,21 @@ RAPIDJSON_NAMESPACE_BEGIN
namespace internal { namespace internal {
#ifdef __GNUC__ #ifdef __GNUC__
RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(effc++) RAPIDJSON_DIAG_OFF(effc++)
RAPIDJSON_DIAG_OFF(array - bounds) // some gcc versions generate wrong warnings https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59124 RAPIDJSON_DIAG_OFF(array-bounds) // some gcc versions generate wrong warnings https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59124
#endif #endif
inline void GrisuRound(char* buffer, int len, uint64_t delta, uint64_t rest, uint64_t ten_kappa, uint64_t wp_w) { inline void GrisuRound(char* buffer, int len, uint64_t delta, uint64_t rest, uint64_t ten_kappa, uint64_t wp_w) {
while (rest < wp_w && delta - rest >= ten_kappa && while (rest < wp_w && delta - rest >= ten_kappa &&
(rest + ten_kappa < wp_w || /// closer (rest + ten_kappa < wp_w || /// closer
wp_w - rest > rest + ten_kappa - wp_w)) { wp_w - rest > rest + ten_kappa - wp_w)) {
buffer[len - 1]--; buffer[len - 1]--;
rest += ten_kappa; rest += ten_kappa;
} }
} }
inline int CountDecimalDigit32(uint32_t n) { inline int CountDecimalDigit32(uint32_t n) {
// Simple pure C++ implementation was faster than __builtin_clz version in this situation. // Simple pure C++ implementation was faster than __builtin_clz version in this situation.
if (n < 10) return 1; if (n < 10) return 1;
if (n < 100) return 2; if (n < 100) return 2;
@ -55,9 +55,9 @@ namespace internal {
//if (n < 1000000000) return 9; //if (n < 1000000000) return 9;
//return 10; //return 10;
return 9; return 9;
} }
inline void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buffer, int* len, int* K) { inline void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buffer, int* len, int* K) {
static const uint32_t kPow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 }; static const uint32_t kPow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 };
const DiyFp one(uint64_t(1) << -Mp.e, Mp.e); const DiyFp one(uint64_t(1) << -Mp.e, Mp.e);
const DiyFp wp_w = Mp - W; const DiyFp wp_w = Mp - W;
@ -69,42 +69,15 @@ namespace internal {
while (kappa > 0) { while (kappa > 0) {
uint32_t d = 0; uint32_t d = 0;
switch (kappa) { switch (kappa) {
case 9: case 9: d = p1 / 100000000; p1 %= 100000000; break;
d = p1 / 100000000; case 8: d = p1 / 10000000; p1 %= 10000000; break;
p1 %= 100000000; case 7: d = p1 / 1000000; p1 %= 1000000; break;
break; case 6: d = p1 / 100000; p1 %= 100000; break;
case 8: case 5: d = p1 / 10000; p1 %= 10000; break;
d = p1 / 10000000; case 4: d = p1 / 1000; p1 %= 1000; break;
p1 %= 10000000; case 3: d = p1 / 100; p1 %= 100; break;
break; case 2: d = p1 / 10; p1 %= 10; break;
case 7: case 1: d = p1; p1 = 0; break;
d = p1 / 1000000;
p1 %= 1000000;
break;
case 6:
d = p1 / 100000;
p1 %= 100000;
break;
case 5:
d = p1 / 10000;
p1 %= 10000;
break;
case 4:
d = p1 / 1000;
p1 %= 1000;
break;
case 3:
d = p1 / 100;
p1 %= 100;
break;
case 2:
d = p1 / 10;
p1 %= 10;
break;
case 1:
d = p1;
p1 = 0;
break;
default:; default:;
} }
if (d || *len) if (d || *len)
@ -134,9 +107,9 @@ namespace internal {
return; return;
} }
} }
} }
inline void Grisu2(double value, char* buffer, int* length, int* K) { inline void Grisu2(double value, char* buffer, int* length, int* K) {
const DiyFp v(value); const DiyFp v(value);
DiyFp w_m, w_p; DiyFp w_m, w_p;
v.NormalizedBoundaries(&w_m, &w_p); v.NormalizedBoundaries(&w_m, &w_p);
@ -148,9 +121,9 @@ namespace internal {
Wm.f++; Wm.f++;
Wp.f--; Wp.f--;
DigitGen(W, Wp, Wp.f - Wm.f, buffer, length, K); DigitGen(W, Wp, Wp.f - Wm.f, buffer, length, K);
} }
inline char* WriteExponent(int K, char* buffer) { inline char* WriteExponent(int K, char* buffer) {
if (K < 0) { if (K < 0) {
*buffer++ = '-'; *buffer++ = '-';
K = -K; K = -K;
@ -172,9 +145,9 @@ namespace internal {
*buffer++ = static_cast<char>('0' + static_cast<char>(K)); *buffer++ = static_cast<char>('0' + static_cast<char>(K));
return buffer; return buffer;
} }
inline char* Prettify(char* buffer, int length, int k, int maxDecimalPlaces) { inline char* Prettify(char* buffer, int length, int k, int maxDecimalPlaces) {
const int kk = length + k; // 10^(kk-1) <= v < 10^kk const int kk = length + k; // 10^(kk-1) <= v < 10^kk
if (0 <= k && kk <= 21) { if (0 <= k && kk <= 21) {
@ -238,9 +211,9 @@ namespace internal {
buffer[length + 1] = 'e'; buffer[length + 1] = 'e';
return WriteExponent(kk - 1, &buffer[0 + length + 2]); return WriteExponent(kk - 1, &buffer[0 + length + 2]);
} }
} }
inline char* dtoa(double value, char* buffer, int maxDecimalPlaces = 324) { inline char* dtoa(double value, char* buffer, int maxDecimalPlaces = 324) {
RAPIDJSON_ASSERT(maxDecimalPlaces >= 1); RAPIDJSON_ASSERT(maxDecimalPlaces >= 1);
Double d(value); Double d(value);
if (d.IsZero()) { if (d.IsZero()) {
@ -260,10 +233,10 @@ namespace internal {
Grisu2(value, buffer, &length, &K); Grisu2(value, buffer, &length, &K);
return Prettify(buffer, length, K, maxDecimalPlaces); return Prettify(buffer, length, K, maxDecimalPlaces);
} }
} }
#ifdef __GNUC__ #ifdef __GNUC__
RAPIDJSON_DIAG_POP RAPIDJSON_DIAG_POP
#endif #endif
} // namespace internal } // namespace internal

View File

@ -20,8 +20,8 @@
RAPIDJSON_NAMESPACE_BEGIN RAPIDJSON_NAMESPACE_BEGIN
namespace internal { namespace internal {
class Double { class Double {
public: public:
Double() {} Double() {}
Double(double d) : d_(d) {} Double(double d) : d_(d) {}
Double(uint64_t u) : u_(u) {} Double(uint64_t u) : u_(u) {}
@ -57,7 +57,7 @@ namespace internal {
return order + 1074; return order + 1074;
} }
private: private:
static const int kSignificandSize = 52; static const int kSignificandSize = 52;
static const int kExponentBias = 0x3FF; static const int kExponentBias = 0x3FF;
static const int kDenormalExponent = 1 - kExponentBias; static const int kDenormalExponent = 1 - kExponentBias;
@ -70,7 +70,7 @@ namespace internal {
double d_; double d_;
uint64_t u_; uint64_t u_;
}; };
}; };
} // namespace internal } // namespace internal
RAPIDJSON_NAMESPACE_END RAPIDJSON_NAMESPACE_END

View File

@ -20,23 +20,23 @@
RAPIDJSON_NAMESPACE_BEGIN RAPIDJSON_NAMESPACE_BEGIN
namespace internal { namespace internal {
inline const char* GetDigitsLut() { inline const char* GetDigitsLut() {
static const char cDigitsLut[200] = { static const char cDigitsLut[200] = {
'0', '0', '0', '1', '0', '2', '0', '3', '0', '4', '0', '5', '0', '6', '0', '7', '0', '8', '0', '9', '0','0','0','1','0','2','0','3','0','4','0','5','0','6','0','7','0','8','0','9',
'1', '0', '1', '1', '1', '2', '1', '3', '1', '4', '1', '5', '1', '6', '1', '7', '1', '8', '1', '9', '1','0','1','1','1','2','1','3','1','4','1','5','1','6','1','7','1','8','1','9',
'2', '0', '2', '1', '2', '2', '2', '3', '2', '4', '2', '5', '2', '6', '2', '7', '2', '8', '2', '9', '2','0','2','1','2','2','2','3','2','4','2','5','2','6','2','7','2','8','2','9',
'3', '0', '3', '1', '3', '2', '3', '3', '3', '4', '3', '5', '3', '6', '3', '7', '3', '8', '3', '9', '3','0','3','1','3','2','3','3','3','4','3','5','3','6','3','7','3','8','3','9',
'4', '0', '4', '1', '4', '2', '4', '3', '4', '4', '4', '5', '4', '6', '4', '7', '4', '8', '4', '9', '4','0','4','1','4','2','4','3','4','4','4','5','4','6','4','7','4','8','4','9',
'5', '0', '5', '1', '5', '2', '5', '3', '5', '4', '5', '5', '5', '6', '5', '7', '5', '8', '5', '9', '5','0','5','1','5','2','5','3','5','4','5','5','5','6','5','7','5','8','5','9',
'6', '0', '6', '1', '6', '2', '6', '3', '6', '4', '6', '5', '6', '6', '6', '7', '6', '8', '6', '9', '6','0','6','1','6','2','6','3','6','4','6','5','6','6','6','7','6','8','6','9',
'7', '0', '7', '1', '7', '2', '7', '3', '7', '4', '7', '5', '7', '6', '7', '7', '7', '8', '7', '9', '7','0','7','1','7','2','7','3','7','4','7','5','7','6','7','7','7','8','7','9',
'8', '0', '8', '1', '8', '2', '8', '3', '8', '4', '8', '5', '8', '6', '8', '7', '8', '8', '8', '9', '8','0','8','1','8','2','8','3','8','4','8','5','8','6','8','7','8','8','8','9',
'9', '0', '9', '1', '9', '2', '9', '3', '9', '4', '9', '5', '9', '6', '9', '7', '9', '8', '9', '9' '9','0','9','1','9','2','9','3','9','4','9','5','9','6','9','7','9','8','9','9'
}; };
return cDigitsLut; return cDigitsLut;
} }
inline char* u32toa(uint32_t value, char* buffer) { inline char* u32toa(uint32_t value, char* buffer) {
RAPIDJSON_ASSERT(buffer != 0); RAPIDJSON_ASSERT(buffer != 0);
const char* cDigitsLut = GetDigitsLut(); const char* cDigitsLut = GetDigitsLut();
@ -110,9 +110,9 @@ namespace internal {
*buffer++ = cDigitsLut[d4 + 1]; *buffer++ = cDigitsLut[d4 + 1];
} }
return buffer; return buffer;
} }
inline char* i32toa(int32_t value, char* buffer) { inline char* i32toa(int32_t value, char* buffer) {
RAPIDJSON_ASSERT(buffer != 0); RAPIDJSON_ASSERT(buffer != 0);
uint32_t u = static_cast<uint32_t>(value); uint32_t u = static_cast<uint32_t>(value);
if (value < 0) { if (value < 0) {
@ -121,9 +121,9 @@ namespace internal {
} }
return u32toa(u, buffer); return u32toa(u, buffer);
} }
inline char* u64toa(uint64_t value, char* buffer) { inline char* u64toa(uint64_t value, char* buffer) {
RAPIDJSON_ASSERT(buffer != 0); RAPIDJSON_ASSERT(buffer != 0);
const char* cDigitsLut = GetDigitsLut(); const char* cDigitsLut = GetDigitsLut();
const uint64_t kTen8 = 100000000; const uint64_t kTen8 = 100000000;
@ -289,9 +289,9 @@ namespace internal {
} }
return buffer; return buffer;
} }
inline char* i64toa(int64_t value, char* buffer) { inline char* i64toa(int64_t value, char* buffer) {
RAPIDJSON_ASSERT(buffer != 0); RAPIDJSON_ASSERT(buffer != 0);
uint64_t u = static_cast<uint64_t>(value); uint64_t u = static_cast<uint64_t>(value);
if (value < 0) { if (value < 0) {
@ -300,7 +300,7 @@ namespace internal {
} }
return u64toa(u, buffer); return u64toa(u, buffer);
} }
} // namespace internal } // namespace internal
RAPIDJSON_NAMESPACE_END RAPIDJSON_NAMESPACE_END

View File

@ -35,113 +35,81 @@ RAPIDJSON_DIAG_OFF(6334)
RAPIDJSON_NAMESPACE_BEGIN RAPIDJSON_NAMESPACE_BEGIN
namespace internal { namespace internal {
// Helper to wrap/convert arbitrary types to void, useful for arbitrary type matching // Helper to wrap/convert arbitrary types to void, useful for arbitrary type matching
template <typename T> template <typename T> struct Void { typedef void Type; };
struct Void { typedef void Type; };
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// BoolType, TrueType, FalseType // BoolType, TrueType, FalseType
// //
template <bool Cond> template <bool Cond> struct BoolType {
struct BoolType {
static const bool Value = Cond; static const bool Value = Cond;
typedef BoolType Type; typedef BoolType Type;
}; };
typedef BoolType<true> TrueType; typedef BoolType<true> TrueType;
typedef BoolType<false> FalseType; typedef BoolType<false> FalseType;
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// SelectIf, BoolExpr, NotExpr, AndExpr, OrExpr // SelectIf, BoolExpr, NotExpr, AndExpr, OrExpr
// //
template <bool C> template <bool C> struct SelectIfImpl { template <typename T1, typename T2> struct Apply { typedef T1 Type; }; };
struct SelectIfImpl { template <> struct SelectIfImpl<false> { template <typename T1, typename T2> struct Apply { typedef T2 Type; }; };
template <typename T1, typename T2> template <bool C, typename T1, typename T2> struct SelectIfCond : SelectIfImpl<C>::template Apply<T1,T2> {};
struct Apply { typedef T1 Type; }; template <typename C, typename T1, typename T2> struct SelectIf : SelectIfCond<C::Value, T1, T2> {};
};
template <>
struct SelectIfImpl<false> {
template <typename T1, typename T2>
struct Apply { typedef T2 Type; };
};
template <bool C, typename T1, typename T2>
struct SelectIfCond : SelectIfImpl<C>::template Apply<T1, T2> {};
template <typename C, typename T1, typename T2>
struct SelectIf : SelectIfCond<C::Value, T1, T2> {};
template <bool Cond1, bool Cond2> template <bool Cond1, bool Cond2> struct AndExprCond : FalseType {};
struct AndExprCond : FalseType {}; template <> struct AndExprCond<true, true> : TrueType {};
template <> template <bool Cond1, bool Cond2> struct OrExprCond : TrueType {};
struct AndExprCond<true, true> : TrueType {}; template <> struct OrExprCond<false, false> : FalseType {};
template <bool Cond1, bool Cond2>
struct OrExprCond : TrueType {};
template <>
struct OrExprCond<false, false> : FalseType {};
template <typename C> template <typename C> struct BoolExpr : SelectIf<C,TrueType,FalseType>::Type {};
struct BoolExpr : SelectIf<C, TrueType, FalseType>::Type {}; template <typename C> struct NotExpr : SelectIf<C,FalseType,TrueType>::Type {};
template <typename C> template <typename C1, typename C2> struct AndExpr : AndExprCond<C1::Value, C2::Value>::Type {};
struct NotExpr : SelectIf<C, FalseType, TrueType>::Type {}; template <typename C1, typename C2> struct OrExpr : OrExprCond<C1::Value, C2::Value>::Type {};
template <typename C1, typename C2>
struct AndExpr : AndExprCond<C1::Value, C2::Value>::Type {};
template <typename C1, typename C2>
struct OrExpr : OrExprCond<C1::Value, C2::Value>::Type {};
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// AddConst, MaybeAddConst, RemoveConst // AddConst, MaybeAddConst, RemoveConst
template <typename T> template <typename T> struct AddConst { typedef const T Type; };
struct AddConst { typedef const T Type; }; template <bool Constify, typename T> struct MaybeAddConst : SelectIfCond<Constify, const T, T> {};
template <bool Constify, typename T> template <typename T> struct RemoveConst { typedef T Type; };
struct MaybeAddConst : SelectIfCond<Constify, const T, T> {}; template <typename T> struct RemoveConst<const T> { typedef T Type; };
template <typename T>
struct RemoveConst { typedef T Type; };
template <typename T>
struct RemoveConst<const T> { typedef T Type; };
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// IsSame, IsConst, IsMoreConst, IsPointer // IsSame, IsConst, IsMoreConst, IsPointer
// //
template <typename T, typename U> template <typename T, typename U> struct IsSame : FalseType {};
struct IsSame : FalseType {}; template <typename T> struct IsSame<T, T> : TrueType {};
template <typename T>
struct IsSame<T, T> : TrueType {};
template <typename T> template <typename T> struct IsConst : FalseType {};
struct IsConst : FalseType {}; template <typename T> struct IsConst<const T> : TrueType {};
template <typename T>
struct IsConst<const T> : TrueType {};
template <typename CT, typename T> template <typename CT, typename T>
struct IsMoreConst struct IsMoreConst
: AndExpr<IsSame<typename RemoveConst<CT>::Type, typename RemoveConst<T>::Type>, : AndExpr<IsSame<typename RemoveConst<CT>::Type, typename RemoveConst<T>::Type>,
BoolType<IsConst<CT>::Value >= IsConst<T>::Value>>::Type {}; BoolType<IsConst<CT>::Value >= IsConst<T>::Value> >::Type {};
template <typename T> template <typename T> struct IsPointer : FalseType {};
struct IsPointer : FalseType {}; template <typename T> struct IsPointer<T*> : TrueType {};
template <typename T>
struct IsPointer<T*> : TrueType {};
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// IsBaseOf // IsBaseOf
// //
#if RAPIDJSON_HAS_CXX11_TYPETRAITS #if RAPIDJSON_HAS_CXX11_TYPETRAITS
template <typename B, typename D> template <typename B, typename D> struct IsBaseOf
struct IsBaseOf : BoolType< ::std::is_base_of<B,D>::value> {};
: BoolType<::std::is_base_of<B, D>::value> {};
#else // simplified version adopted from Boost #else // simplified version adopted from Boost
template <typename B, typename D> template<typename B, typename D> struct IsBaseOfImpl {
struct IsBaseOfImpl {
RAPIDJSON_STATIC_ASSERT(sizeof(B) != 0); RAPIDJSON_STATIC_ASSERT(sizeof(B) != 0);
RAPIDJSON_STATIC_ASSERT(sizeof(D) != 0); RAPIDJSON_STATIC_ASSERT(sizeof(D) != 0);
typedef char (&Yes)[1]; typedef char (&Yes)[1];
typedef char (&No)[2]; typedef char (&No) [2];
template <typename T> template <typename T>
static Yes Check(const D*, T); static Yes Check(const D*, T);
@ -153,58 +121,54 @@ namespace internal {
}; };
enum { Value = (sizeof(Check(Host(), 0)) == sizeof(Yes)) }; enum { Value = (sizeof(Check(Host(), 0)) == sizeof(Yes)) };
}; };
template <typename B, typename D> template <typename B, typename D> struct IsBaseOf
struct IsBaseOf : OrExpr<IsSame<B, D>, BoolExpr<IsBaseOfImpl<B, D> > >::Type {};
: OrExpr<IsSame<B, D>, BoolExpr<IsBaseOfImpl<B, D>>>::Type {};
#endif // RAPIDJSON_HAS_CXX11_TYPETRAITS #endif // RAPIDJSON_HAS_CXX11_TYPETRAITS
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
// EnableIf / DisableIf // EnableIf / DisableIf
// //
template <bool Condition, typename T = void> template <bool Condition, typename T = void> struct EnableIfCond { typedef T Type; };
struct EnableIfCond { typedef T Type; }; template <typename T> struct EnableIfCond<false, T> { /* empty */ };
template <typename T>
struct EnableIfCond<false, T> { /* empty */
};
template <bool Condition, typename T = void> template <bool Condition, typename T = void> struct DisableIfCond { typedef T Type; };
struct DisableIfCond { typedef T Type; }; template <typename T> struct DisableIfCond<true, T> { /* empty */ };
template <typename T>
struct DisableIfCond<true, T> { /* empty */
};
template <typename Condition, typename T = void> template <typename Condition, typename T = void>
struct EnableIf : EnableIfCond<Condition::Value, T> {}; struct EnableIf : EnableIfCond<Condition::Value, T> {};
template <typename Condition, typename T = void> template <typename Condition, typename T = void>
struct DisableIf : DisableIfCond<Condition::Value, T> {}; struct DisableIf : DisableIfCond<Condition::Value, T> {};
// SFINAE helpers // SFINAE helpers
struct SfinaeTag {}; struct SfinaeTag {};
template <typename T> template <typename T> struct RemoveSfinaeTag;
struct RemoveSfinaeTag; template <typename T> struct RemoveSfinaeTag<SfinaeTag&(*)(T)> { typedef T Type; };
template <typename T>
struct RemoveSfinaeTag<SfinaeTag& (*)(T)> { typedef T Type; };
#define RAPIDJSON_REMOVEFPTR_(type) \ #define RAPIDJSON_REMOVEFPTR_(type) \
typename ::RAPIDJSON_NAMESPACE::internal::RemoveSfinaeTag<::RAPIDJSON_NAMESPACE::internal::SfinaeTag&(*)type>::Type typename ::RAPIDJSON_NAMESPACE::internal::RemoveSfinaeTag \
< ::RAPIDJSON_NAMESPACE::internal::SfinaeTag&(*) type>::Type
#define RAPIDJSON_ENABLEIF(cond) \ #define RAPIDJSON_ENABLEIF(cond) \
typename ::RAPIDJSON_NAMESPACE::internal::EnableIf<RAPIDJSON_REMOVEFPTR_(cond)>::Type* = NULL typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \
<RAPIDJSON_REMOVEFPTR_(cond)>::Type * = NULL
#define RAPIDJSON_DISABLEIF(cond) \ #define RAPIDJSON_DISABLEIF(cond) \
typename ::RAPIDJSON_NAMESPACE::internal::DisableIf<RAPIDJSON_REMOVEFPTR_(cond)>::Type* = NULL typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \
<RAPIDJSON_REMOVEFPTR_(cond)>::Type * = NULL
#define RAPIDJSON_ENABLEIF_RETURN(cond, returntype) \ #define RAPIDJSON_ENABLEIF_RETURN(cond,returntype) \
typename ::RAPIDJSON_NAMESPACE::internal::EnableIf<RAPIDJSON_REMOVEFPTR_(cond), \ typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \
<RAPIDJSON_REMOVEFPTR_(cond), \
RAPIDJSON_REMOVEFPTR_(returntype)>::Type RAPIDJSON_REMOVEFPTR_(returntype)>::Type
#define RAPIDJSON_DISABLEIF_RETURN(cond, returntype) \ #define RAPIDJSON_DISABLEIF_RETURN(cond,returntype) \
typename ::RAPIDJSON_NAMESPACE::internal::DisableIf<RAPIDJSON_REMOVEFPTR_(cond), \ typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \
<RAPIDJSON_REMOVEFPTR_(cond), \
RAPIDJSON_REMOVEFPTR_(returntype)>::Type RAPIDJSON_REMOVEFPTR_(returntype)>::Type
} // namespace internal } // namespace internal

View File

@ -20,12 +20,12 @@
RAPIDJSON_NAMESPACE_BEGIN RAPIDJSON_NAMESPACE_BEGIN
namespace internal { namespace internal {
//! Computes integer powers of 10 in double (10.0^n). //! Computes integer powers of 10 in double (10.0^n).
/*! This function uses lookup table for fast and accurate results. /*! This function uses lookup table for fast and accurate results.
\param n non-negative exponent. Must <= 308. \param n non-negative exponent. Must <= 308.
\return 10.0^n \return 10.0^n
*/ */
inline double Pow10(int n) { inline double Pow10(int n) {
static const double e[] = { // 1e-0...1e308: 309 * 8 bytes = 2472 bytes static const double e[] = { // 1e-0...1e308: 309 * 8 bytes = 2472 bytes
1e+0, 1e+0,
1e+1, 1e+2, 1e+3, 1e+4, 1e+5, 1e+6, 1e+7, 1e+8, 1e+9, 1e+10, 1e+11, 1e+12, 1e+13, 1e+14, 1e+15, 1e+16, 1e+17, 1e+18, 1e+19, 1e+20, 1e+1, 1e+2, 1e+3, 1e+4, 1e+5, 1e+6, 1e+7, 1e+8, 1e+9, 1e+10, 1e+11, 1e+12, 1e+13, 1e+14, 1e+15, 1e+16, 1e+17, 1e+18, 1e+19, 1e+20,
@ -33,21 +33,21 @@ namespace internal {
1e+41, 1e+42, 1e+43, 1e+44, 1e+45, 1e+46, 1e+47, 1e+48, 1e+49, 1e+50, 1e+51, 1e+52, 1e+53, 1e+54, 1e+55, 1e+56, 1e+57, 1e+58, 1e+59, 1e+60, 1e+41, 1e+42, 1e+43, 1e+44, 1e+45, 1e+46, 1e+47, 1e+48, 1e+49, 1e+50, 1e+51, 1e+52, 1e+53, 1e+54, 1e+55, 1e+56, 1e+57, 1e+58, 1e+59, 1e+60,
1e+61, 1e+62, 1e+63, 1e+64, 1e+65, 1e+66, 1e+67, 1e+68, 1e+69, 1e+70, 1e+71, 1e+72, 1e+73, 1e+74, 1e+75, 1e+76, 1e+77, 1e+78, 1e+79, 1e+80, 1e+61, 1e+62, 1e+63, 1e+64, 1e+65, 1e+66, 1e+67, 1e+68, 1e+69, 1e+70, 1e+71, 1e+72, 1e+73, 1e+74, 1e+75, 1e+76, 1e+77, 1e+78, 1e+79, 1e+80,
1e+81, 1e+82, 1e+83, 1e+84, 1e+85, 1e+86, 1e+87, 1e+88, 1e+89, 1e+90, 1e+91, 1e+92, 1e+93, 1e+94, 1e+95, 1e+96, 1e+97, 1e+98, 1e+99, 1e+100, 1e+81, 1e+82, 1e+83, 1e+84, 1e+85, 1e+86, 1e+87, 1e+88, 1e+89, 1e+90, 1e+91, 1e+92, 1e+93, 1e+94, 1e+95, 1e+96, 1e+97, 1e+98, 1e+99, 1e+100,
1e+101, 1e+102, 1e+103, 1e+104, 1e+105, 1e+106, 1e+107, 1e+108, 1e+109, 1e+110, 1e+111, 1e+112, 1e+113, 1e+114, 1e+115, 1e+116, 1e+117, 1e+118, 1e+119, 1e+120, 1e+101,1e+102,1e+103,1e+104,1e+105,1e+106,1e+107,1e+108,1e+109,1e+110,1e+111,1e+112,1e+113,1e+114,1e+115,1e+116,1e+117,1e+118,1e+119,1e+120,
1e+121, 1e+122, 1e+123, 1e+124, 1e+125, 1e+126, 1e+127, 1e+128, 1e+129, 1e+130, 1e+131, 1e+132, 1e+133, 1e+134, 1e+135, 1e+136, 1e+137, 1e+138, 1e+139, 1e+140, 1e+121,1e+122,1e+123,1e+124,1e+125,1e+126,1e+127,1e+128,1e+129,1e+130,1e+131,1e+132,1e+133,1e+134,1e+135,1e+136,1e+137,1e+138,1e+139,1e+140,
1e+141, 1e+142, 1e+143, 1e+144, 1e+145, 1e+146, 1e+147, 1e+148, 1e+149, 1e+150, 1e+151, 1e+152, 1e+153, 1e+154, 1e+155, 1e+156, 1e+157, 1e+158, 1e+159, 1e+160, 1e+141,1e+142,1e+143,1e+144,1e+145,1e+146,1e+147,1e+148,1e+149,1e+150,1e+151,1e+152,1e+153,1e+154,1e+155,1e+156,1e+157,1e+158,1e+159,1e+160,
1e+161, 1e+162, 1e+163, 1e+164, 1e+165, 1e+166, 1e+167, 1e+168, 1e+169, 1e+170, 1e+171, 1e+172, 1e+173, 1e+174, 1e+175, 1e+176, 1e+177, 1e+178, 1e+179, 1e+180, 1e+161,1e+162,1e+163,1e+164,1e+165,1e+166,1e+167,1e+168,1e+169,1e+170,1e+171,1e+172,1e+173,1e+174,1e+175,1e+176,1e+177,1e+178,1e+179,1e+180,
1e+181, 1e+182, 1e+183, 1e+184, 1e+185, 1e+186, 1e+187, 1e+188, 1e+189, 1e+190, 1e+191, 1e+192, 1e+193, 1e+194, 1e+195, 1e+196, 1e+197, 1e+198, 1e+199, 1e+200, 1e+181,1e+182,1e+183,1e+184,1e+185,1e+186,1e+187,1e+188,1e+189,1e+190,1e+191,1e+192,1e+193,1e+194,1e+195,1e+196,1e+197,1e+198,1e+199,1e+200,
1e+201, 1e+202, 1e+203, 1e+204, 1e+205, 1e+206, 1e+207, 1e+208, 1e+209, 1e+210, 1e+211, 1e+212, 1e+213, 1e+214, 1e+215, 1e+216, 1e+217, 1e+218, 1e+219, 1e+220, 1e+201,1e+202,1e+203,1e+204,1e+205,1e+206,1e+207,1e+208,1e+209,1e+210,1e+211,1e+212,1e+213,1e+214,1e+215,1e+216,1e+217,1e+218,1e+219,1e+220,
1e+221, 1e+222, 1e+223, 1e+224, 1e+225, 1e+226, 1e+227, 1e+228, 1e+229, 1e+230, 1e+231, 1e+232, 1e+233, 1e+234, 1e+235, 1e+236, 1e+237, 1e+238, 1e+239, 1e+240, 1e+221,1e+222,1e+223,1e+224,1e+225,1e+226,1e+227,1e+228,1e+229,1e+230,1e+231,1e+232,1e+233,1e+234,1e+235,1e+236,1e+237,1e+238,1e+239,1e+240,
1e+241, 1e+242, 1e+243, 1e+244, 1e+245, 1e+246, 1e+247, 1e+248, 1e+249, 1e+250, 1e+251, 1e+252, 1e+253, 1e+254, 1e+255, 1e+256, 1e+257, 1e+258, 1e+259, 1e+260, 1e+241,1e+242,1e+243,1e+244,1e+245,1e+246,1e+247,1e+248,1e+249,1e+250,1e+251,1e+252,1e+253,1e+254,1e+255,1e+256,1e+257,1e+258,1e+259,1e+260,
1e+261, 1e+262, 1e+263, 1e+264, 1e+265, 1e+266, 1e+267, 1e+268, 1e+269, 1e+270, 1e+271, 1e+272, 1e+273, 1e+274, 1e+275, 1e+276, 1e+277, 1e+278, 1e+279, 1e+280, 1e+261,1e+262,1e+263,1e+264,1e+265,1e+266,1e+267,1e+268,1e+269,1e+270,1e+271,1e+272,1e+273,1e+274,1e+275,1e+276,1e+277,1e+278,1e+279,1e+280,
1e+281, 1e+282, 1e+283, 1e+284, 1e+285, 1e+286, 1e+287, 1e+288, 1e+289, 1e+290, 1e+291, 1e+292, 1e+293, 1e+294, 1e+295, 1e+296, 1e+297, 1e+298, 1e+299, 1e+300, 1e+281,1e+282,1e+283,1e+284,1e+285,1e+286,1e+287,1e+288,1e+289,1e+290,1e+291,1e+292,1e+293,1e+294,1e+295,1e+296,1e+297,1e+298,1e+299,1e+300,
1e+301, 1e+302, 1e+303, 1e+304, 1e+305, 1e+306, 1e+307, 1e+308 1e+301,1e+302,1e+303,1e+304,1e+305,1e+306,1e+307,1e+308
}; };
RAPIDJSON_ASSERT(n >= 0 && n <= 308); RAPIDJSON_ASSERT(n >= 0 && n <= 308);
return e[n]; return e[n];
} }
} // namespace internal } // namespace internal
RAPIDJSON_NAMESPACE_END RAPIDJSON_NAMESPACE_END

View File

@ -22,7 +22,7 @@
#ifdef __clang__ #ifdef __clang__
RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(padded) RAPIDJSON_DIAG_OFF(padded)
RAPIDJSON_DIAG_OFF(switch - enum) RAPIDJSON_DIAG_OFF(switch-enum)
#elif defined(_MSC_VER) #elif defined(_MSC_VER)
RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
@ -40,12 +40,12 @@ RAPIDJSON_DIAG_OFF(effc++)
RAPIDJSON_NAMESPACE_BEGIN RAPIDJSON_NAMESPACE_BEGIN
namespace internal { namespace internal {
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// DecodedStream // DecodedStream
template <typename SourceStream, typename Encoding> template <typename SourceStream, typename Encoding>
class DecodedStream { class DecodedStream {
public: public:
DecodedStream(SourceStream& ss) : ss_(ss), codepoint_() { Decode(); } DecodedStream(SourceStream& ss) : ss_(ss), codepoint_() { Decode(); }
unsigned Peek() { return codepoint_; } unsigned Peek() { return codepoint_; }
unsigned Take() { unsigned Take() {
@ -55,7 +55,7 @@ namespace internal {
return c; return c;
} }
private: private:
void Decode() { void Decode() {
if (!Encoding::Decode(ss_, &codepoint_)) if (!Encoding::Decode(ss_, &codepoint_))
codepoint_ = 0; codepoint_ = 0;
@ -63,19 +63,19 @@ namespace internal {
SourceStream& ss_; SourceStream& ss_;
unsigned codepoint_; unsigned codepoint_;
}; };
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// GenericRegex // GenericRegex
static const SizeType kRegexInvalidState = ~SizeType(0); //!< Represents an invalid index in GenericRegex::State::out, out1 static const SizeType kRegexInvalidState = ~SizeType(0); //!< Represents an invalid index in GenericRegex::State::out, out1
static const SizeType kRegexInvalidRange = ~SizeType(0); static const SizeType kRegexInvalidRange = ~SizeType(0);
template <typename Encoding, typename Allocator> template <typename Encoding, typename Allocator>
class GenericRegexSearch; class GenericRegexSearch;
//! Regular expression engine with subset of ECMAscript grammar. //! Regular expression engine with subset of ECMAscript grammar.
/*! /*!
Supported regular expression syntax: Supported regular expression syntax:
- \c ab Concatenation - \c ab Concatenation
- \c a|b Alternation - \c a|b Alternation
@ -106,23 +106,25 @@ namespace internal {
Cox, Russ. "Regular Expression Matching Can Be Simple And Fast (but is slow in Java, Perl, PHP, Python, Ruby,...).", Cox, Russ. "Regular Expression Matching Can Be Simple And Fast (but is slow in Java, Perl, PHP, Python, Ruby,...).",
https://swtch.com/~rsc/regexp/regexp1.html https://swtch.com/~rsc/regexp/regexp1.html
*/ */
template <typename Encoding, typename Allocator = CrtAllocator> template <typename Encoding, typename Allocator = CrtAllocator>
class GenericRegex { class GenericRegex {
public: public:
typedef Encoding EncodingType; typedef Encoding EncodingType;
typedef typename Encoding::Ch Ch; typedef typename Encoding::Ch Ch;
template <typename, typename> template <typename, typename> friend class GenericRegexSearch;
friend class GenericRegexSearch;
GenericRegex(const Ch* source, Allocator* allocator = 0) : ownAllocator_(allocator ? 0 : RAPIDJSON_NEW(Allocator)()), allocator_(allocator ? allocator : ownAllocator_), GenericRegex(const Ch* source, Allocator* allocator = 0) :
ownAllocator_(allocator ? 0 : RAPIDJSON_NEW(Allocator)()), allocator_(allocator ? allocator : ownAllocator_),
states_(allocator_, 256), ranges_(allocator_, 256), root_(kRegexInvalidState), stateCount_(), rangeCount_(), states_(allocator_, 256), ranges_(allocator_, 256), root_(kRegexInvalidState), stateCount_(), rangeCount_(),
anchorBegin_(), anchorEnd_() { anchorBegin_(), anchorEnd_()
{
GenericStringStream<Encoding> ss(source); GenericStringStream<Encoding> ss(source);
DecodedStream<GenericStringStream<Encoding>, Encoding> ds(ss); DecodedStream<GenericStringStream<Encoding>, Encoding> ds(ss);
Parse(ds); Parse(ds);
} }
~GenericRegex() { ~GenericRegex()
{
RAPIDJSON_DELETE(ownAllocator_); RAPIDJSON_DELETE(ownAllocator_);
} }
@ -130,7 +132,7 @@ namespace internal {
return root_ != kRegexInvalidState; return root_ != kRegexInvalidState;
} }
private: private:
enum Operator { enum Operator {
kZeroOrOne, kZeroOrOne,
kZeroOrMore, kZeroOrMore,
@ -242,7 +244,8 @@ namespace internal {
return; return;
break; break;
case '{': { case '{':
{
unsigned n, m; unsigned n, m;
if (!ParseUnsigned(ds, &n)) if (!ParseUnsigned(ds, &n))
return; return;
@ -260,14 +263,16 @@ namespace internal {
if (!EvalQuantifier(operandStack, n, m) || ds.Peek() != '}') if (!EvalQuantifier(operandStack, n, m) || ds.Peek() != '}')
return; return;
ds.Take(); ds.Take();
} break; }
break;
case '.': case '.':
PushOperand(operandStack, kAnyCharacterClass); PushOperand(operandStack, kAnyCharacterClass);
ImplicitConcatenation(atomCountStack, operatorStack); ImplicitConcatenation(atomCountStack, operatorStack);
break; break;
case '[': { case '[':
{
SizeType range; SizeType range;
if (!ParseRange(ds, &range)) if (!ParseRange(ds, &range))
return; return;
@ -302,7 +307,7 @@ namespace internal {
#if RAPIDJSON_REGEX_VERBOSE #if RAPIDJSON_REGEX_VERBOSE
printf("root: %d\n", root_); printf("root: %d\n", root_);
for (SizeType i = 0; i < stateCount_; i++) { for (SizeType i = 0; i < stateCount_ ; i++) {
State& s = GetState(i); State& s = GetState(i);
printf("[%2d] out: %2d out1: %2d c: '%c'\n", i, s.out, s.out1, (char)s.codepoint); printf("[%2d] out: %2d out1: %2d c: '%c'\n", i, s.out, s.out1, (char)s.codepoint);
} }
@ -524,7 +529,8 @@ namespace internal {
// fall through to step 0 for other characters // fall through to step 0 for other characters
RAPIDJSON_DELIBERATE_FALLTHROUGH; RAPIDJSON_DELIBERATE_FALLTHROUGH;
case 0: { case 0:
{
SizeType r = NewRange(codepoint); SizeType r = NewRange(codepoint);
if (current != kRegexInvalidRange) if (current != kRegexInvalidRange)
GetRange(current).next = r; GetRange(current).next = r;
@ -570,23 +576,12 @@ namespace internal {
case '{': case '{':
case '}': case '}':
case '\\': case '\\':
*escapedCodepoint = codepoint; *escapedCodepoint = codepoint; return true;
return true; case 'f': *escapedCodepoint = 0x000C; return true;
case 'f': case 'n': *escapedCodepoint = 0x000A; return true;
*escapedCodepoint = 0x000C; case 'r': *escapedCodepoint = 0x000D; return true;
return true; case 't': *escapedCodepoint = 0x0009; return true;
case 'n': case 'v': *escapedCodepoint = 0x000B; return true;
*escapedCodepoint = 0x000A;
return true;
case 'r':
*escapedCodepoint = 0x000D;
return true;
case 't':
*escapedCodepoint = 0x0009;
return true;
case 'v':
*escapedCodepoint = 0x000B;
return true;
default: default:
return false; // Unsupported escape character return false; // Unsupported escape character
} }
@ -605,16 +600,18 @@ namespace internal {
// For SearchWithAnchoring() // For SearchWithAnchoring()
bool anchorBegin_; bool anchorBegin_;
bool anchorEnd_; bool anchorEnd_;
}; };
template <typename RegexType, typename Allocator = CrtAllocator> template <typename RegexType, typename Allocator = CrtAllocator>
class GenericRegexSearch { class GenericRegexSearch {
public: public:
typedef typename RegexType::EncodingType Encoding; typedef typename RegexType::EncodingType Encoding;
typedef typename Encoding::Ch Ch; typedef typename Encoding::Ch Ch;
GenericRegexSearch(const RegexType& regex, Allocator* allocator = 0) : regex_(regex), allocator_(allocator), ownAllocator_(0), GenericRegexSearch(const RegexType& regex, Allocator* allocator = 0) :
state0_(allocator, 0), state1_(allocator, 0), stateSet_() { regex_(regex), allocator_(allocator), ownAllocator_(0),
state0_(allocator, 0), state1_(allocator, 0), stateSet_()
{
RAPIDJSON_ASSERT(regex_.IsValid()); RAPIDJSON_ASSERT(regex_.IsValid());
if (!allocator_) if (!allocator_)
ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)(); ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();
@ -648,7 +645,7 @@ namespace internal {
return Search(is); return Search(is);
} }
private: private:
typedef typename RegexType::State State; typedef typename RegexType::State State;
typedef typename RegexType::Range Range; typedef typename RegexType::Range Range;
@ -657,7 +654,7 @@ namespace internal {
DecodedStream<InputStream, Encoding> ds(is); DecodedStream<InputStream, Encoding> ds(is);
state0_.Clear(); state0_.Clear();
Stack<Allocator>*current = &state0_, *next = &state1_; Stack<Allocator> *current = &state0_, *next = &state1_;
const size_t stateSetSize = GetStateSetSize(); const size_t stateSetSize = GetStateSetSize();
std::memset(stateSet_, 0, stateSetSize); std::memset(stateSet_, 0, stateSetSize);
@ -671,7 +668,8 @@ namespace internal {
const State& sr = regex_.GetState(*s); const State& sr = regex_.GetState(*s);
if (sr.codepoint == codepoint || if (sr.codepoint == codepoint ||
sr.codepoint == RegexType::kAnyCharacterClass || sr.codepoint == RegexType::kAnyCharacterClass ||
(sr.codepoint == RegexType::kRangeCharacterClass && MatchRange(sr.rangeStart, codepoint))) { (sr.codepoint == RegexType::kRangeCharacterClass && MatchRange(sr.rangeStart, codepoint)))
{
matched = AddState(*next, sr.out) || matched; matched = AddState(*next, sr.out) || matched;
if (!anchorEnd && matched) if (!anchorEnd && matched)
return true; return true;
@ -722,10 +720,10 @@ namespace internal {
Stack<Allocator> state0_; Stack<Allocator> state0_;
Stack<Allocator> state1_; Stack<Allocator> state1_;
uint32_t* stateSet_; uint32_t* stateSet_;
}; };
typedef GenericRegex<UTF8<>> Regex; typedef GenericRegex<UTF8<> > Regex;
typedef GenericRegexSearch<Regex> RegexSearch; typedef GenericRegexSearch<Regex> RegexSearch;
} // namespace internal } // namespace internal
RAPIDJSON_NAMESPACE_END RAPIDJSON_NAMESPACE_END

View File

@ -21,21 +21,21 @@
#if defined(__clang__) #if defined(__clang__)
RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(c++ 98 - compat) RAPIDJSON_DIAG_OFF(c++98-compat)
#endif #endif
RAPIDJSON_NAMESPACE_BEGIN RAPIDJSON_NAMESPACE_BEGIN
namespace internal { namespace internal {
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// Stack // Stack
//! A type-unsafe stack for storing different types of data. //! A type-unsafe stack for storing different types of data.
/*! \tparam Allocator Allocator for allocating stack memory. /*! \tparam Allocator Allocator for allocating stack memory.
*/ */
template <typename Allocator> template <typename Allocator>
class Stack { class Stack {
public: public:
// Optimization note: Do not allocate memory for stack_ in constructor. // Optimization note: Do not allocate memory for stack_ in constructor.
// Do it lazily when first Push() -> Expand() -> Resize(). // Do it lazily when first Push() -> Expand() -> Resize().
Stack(Allocator* allocator, size_t stackCapacity) : allocator_(allocator), ownAllocator_(0), stack_(0), stackTop_(0), stackEnd_(0), initialCapacity_(stackCapacity) { Stack(Allocator* allocator, size_t stackCapacity) : allocator_(allocator), ownAllocator_(0), stack_(0), stackTop_(0), stackEnd_(0), initialCapacity_(stackCapacity) {
@ -48,7 +48,8 @@ namespace internal {
stack_(rhs.stack_), stack_(rhs.stack_),
stackTop_(rhs.stackTop_), stackTop_(rhs.stackTop_),
stackEnd_(rhs.stackEnd_), stackEnd_(rhs.stackEnd_),
initialCapacity_(rhs.initialCapacity_) { initialCapacity_(rhs.initialCapacity_)
{
rhs.allocator_ = 0; rhs.allocator_ = 0;
rhs.ownAllocator_ = 0; rhs.ownAllocator_ = 0;
rhs.stack_ = 0; rhs.stack_ = 0;
@ -64,7 +65,8 @@ namespace internal {
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS #if RAPIDJSON_HAS_CXX11_RVALUE_REFS
Stack& operator=(Stack&& rhs) { Stack& operator=(Stack&& rhs) {
if (&rhs != this) { if (&rhs != this)
{
Destroy(); Destroy();
allocator_ = rhs.allocator_; allocator_ = rhs.allocator_;
@ -110,20 +112,20 @@ namespace internal {
// Optimization note: try to minimize the size of this function for force inline. // Optimization note: try to minimize the size of this function for force inline.
// Expansion is run very infrequently, so it is moved to another (probably non-inline) function. // Expansion is run very infrequently, so it is moved to another (probably non-inline) function.
template <typename T> template<typename T>
RAPIDJSON_FORCEINLINE void Reserve(size_t count = 1) { RAPIDJSON_FORCEINLINE void Reserve(size_t count = 1) {
// Expand the stack if needed // Expand the stack if needed
if (RAPIDJSON_UNLIKELY(static_cast<std::ptrdiff_t>(sizeof(T) * count) > (stackEnd_ - stackTop_))) if (RAPIDJSON_UNLIKELY(static_cast<std::ptrdiff_t>(sizeof(T) * count) > (stackEnd_ - stackTop_)))
Expand<T>(count); Expand<T>(count);
} }
template <typename T> template<typename T>
RAPIDJSON_FORCEINLINE T* Push(size_t count = 1) { RAPIDJSON_FORCEINLINE T* Push(size_t count = 1) {
Reserve<T>(count); Reserve<T>(count);
return PushUnsafe<T>(count); return PushUnsafe<T>(count);
} }
template <typename T> template<typename T>
RAPIDJSON_FORCEINLINE T* PushUnsafe(size_t count = 1) { RAPIDJSON_FORCEINLINE T* PushUnsafe(size_t count = 1) {
RAPIDJSON_ASSERT(stackTop_); RAPIDJSON_ASSERT(stackTop_);
RAPIDJSON_ASSERT(static_cast<std::ptrdiff_t>(sizeof(T) * count) <= (stackEnd_ - stackTop_)); RAPIDJSON_ASSERT(static_cast<std::ptrdiff_t>(sizeof(T) * count) <= (stackEnd_ - stackTop_));
@ -132,35 +134,35 @@ namespace internal {
return ret; return ret;
} }
template <typename T> template<typename T>
T* Pop(size_t count) { T* Pop(size_t count) {
RAPIDJSON_ASSERT(GetSize() >= count * sizeof(T)); RAPIDJSON_ASSERT(GetSize() >= count * sizeof(T));
stackTop_ -= count * sizeof(T); stackTop_ -= count * sizeof(T);
return reinterpret_cast<T*>(stackTop_); return reinterpret_cast<T*>(stackTop_);
} }
template <typename T> template<typename T>
T* Top() { T* Top() {
RAPIDJSON_ASSERT(GetSize() >= sizeof(T)); RAPIDJSON_ASSERT(GetSize() >= sizeof(T));
return reinterpret_cast<T*>(stackTop_ - sizeof(T)); return reinterpret_cast<T*>(stackTop_ - sizeof(T));
} }
template <typename T> template<typename T>
const T* Top() const { const T* Top() const {
RAPIDJSON_ASSERT(GetSize() >= sizeof(T)); RAPIDJSON_ASSERT(GetSize() >= sizeof(T));
return reinterpret_cast<T*>(stackTop_ - sizeof(T)); return reinterpret_cast<T*>(stackTop_ - sizeof(T));
} }
template <typename T> template<typename T>
T* End() { return reinterpret_cast<T*>(stackTop_); } T* End() { return reinterpret_cast<T*>(stackTop_); }
template <typename T> template<typename T>
const T* End() const { return reinterpret_cast<T*>(stackTop_); } const T* End() const { return reinterpret_cast<T*>(stackTop_); }
template <typename T> template<typename T>
T* Bottom() { return reinterpret_cast<T*>(stack_); } T* Bottom() { return reinterpret_cast<T*>(stack_); }
template <typename T> template<typename T>
const T* Bottom() const { return reinterpret_cast<T*>(stack_); } const T* Bottom() const { return reinterpret_cast<T*>(stack_); }
bool HasAllocator() const { bool HasAllocator() const {
@ -176,8 +178,8 @@ namespace internal {
size_t GetSize() const { return static_cast<size_t>(stackTop_ - stack_); } size_t GetSize() const { return static_cast<size_t>(stackTop_ - stack_); }
size_t GetCapacity() const { return static_cast<size_t>(stackEnd_ - stack_); } size_t GetCapacity() const { return static_cast<size_t>(stackEnd_ - stack_); }
private: private:
template <typename T> template<typename T>
void Expand(size_t count) { void Expand(size_t count) {
// Only expand the capacity if the current stack exists. Otherwise just create a stack with initial capacity. // Only expand the capacity if the current stack exists. Otherwise just create a stack with initial capacity.
size_t newCapacity; size_t newCapacity;
@ -185,8 +187,7 @@ namespace internal {
if (!allocator_) if (!allocator_)
ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)(); ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();
newCapacity = initialCapacity_; newCapacity = initialCapacity_;
} } else {
else {
newCapacity = GetCapacity(); newCapacity = GetCapacity();
newCapacity += (newCapacity + 1) / 2; newCapacity += (newCapacity + 1) / 2;
} }
@ -215,11 +216,11 @@ namespace internal {
Allocator* allocator_; Allocator* allocator_;
Allocator* ownAllocator_; Allocator* ownAllocator_;
char* stack_; char *stack_;
char* stackTop_; char *stackTop_;
char* stackEnd_; char *stackEnd_;
size_t initialCapacity_; size_t initialCapacity_;
}; };
} // namespace internal } // namespace internal
RAPIDJSON_NAMESPACE_END RAPIDJSON_NAMESPACE_END

View File

@ -21,33 +21,33 @@
RAPIDJSON_NAMESPACE_BEGIN RAPIDJSON_NAMESPACE_BEGIN
namespace internal { namespace internal {
//! Custom strlen() which works on different character types. //! Custom strlen() which works on different character types.
/*! \tparam Ch Character type (e.g. char, wchar_t, short) /*! \tparam Ch Character type (e.g. char, wchar_t, short)
\param s Null-terminated input string. \param s Null-terminated input string.
\return Number of characters in the string. \return Number of characters in the string.
\note This has the same semantics as strlen(), the return value is not number of Unicode codepoints. \note This has the same semantics as strlen(), the return value is not number of Unicode codepoints.
*/ */
template <typename Ch> template <typename Ch>
inline SizeType StrLen(const Ch* s) { inline SizeType StrLen(const Ch* s) {
RAPIDJSON_ASSERT(s != 0); RAPIDJSON_ASSERT(s != 0);
const Ch* p = s; const Ch* p = s;
while (*p) ++p; while (*p) ++p;
return SizeType(p - s); return SizeType(p - s);
} }
template <> template <>
inline SizeType StrLen(const char* s) { inline SizeType StrLen(const char* s) {
return SizeType(std::strlen(s)); return SizeType(std::strlen(s));
} }
template <> template <>
inline SizeType StrLen(const wchar_t* s) { inline SizeType StrLen(const wchar_t* s) {
return SizeType(std::wcslen(s)); return SizeType(std::wcslen(s));
} }
//! Returns number of code points in a encoded string. //! Returns number of code points in a encoded string.
template <typename Encoding> template<typename Encoding>
bool CountStringCodePoint(const typename Encoding::Ch* s, SizeType length, SizeType* outCount) { bool CountStringCodePoint(const typename Encoding::Ch* s, SizeType length, SizeType* outCount) {
RAPIDJSON_ASSERT(s != 0); RAPIDJSON_ASSERT(s != 0);
RAPIDJSON_ASSERT(outCount != 0); RAPIDJSON_ASSERT(outCount != 0);
GenericStringStream<Encoding> is(s); GenericStringStream<Encoding> is(s);
@ -61,7 +61,7 @@ namespace internal {
} }
*outCount = count; *outCount = count;
return true; return true;
} }
} // namespace internal } // namespace internal
RAPIDJSON_NAMESPACE_END RAPIDJSON_NAMESPACE_END

View File

@ -25,16 +25,16 @@
RAPIDJSON_NAMESPACE_BEGIN RAPIDJSON_NAMESPACE_BEGIN
namespace internal { namespace internal {
inline double FastPath(double significand, int exp) { inline double FastPath(double significand, int exp) {
if (exp < -308) if (exp < -308)
return 0.0; return 0.0;
else if (exp >= 0) else if (exp >= 0)
return significand * internal::Pow10(exp); return significand * internal::Pow10(exp);
else else
return significand / internal::Pow10(-exp); return significand / internal::Pow10(-exp);
} }
inline double StrtodNormalPrecision(double d, int p) { inline double StrtodNormalPrecision(double d, int p) {
if (p < -308) { if (p < -308) {
// Prevent expSum < -308, making Pow10(p) = 0 // Prevent expSum < -308, making Pow10(p) = 0
d = FastPath(d, -308); d = FastPath(d, -308);
@ -43,17 +43,17 @@ namespace internal {
else else
d = FastPath(d, p); d = FastPath(d, p);
return d; return d;
} }
template <typename T> template <typename T>
inline T Min3(T a, T b, T c) { inline T Min3(T a, T b, T c) {
T m = a; T m = a;
if (m > b) m = b; if (m > b) m = b;
if (m > c) m = c; if (m > c) m = c;
return m; return m;
} }
inline int CheckWithinHalfULP(double b, const BigInteger& d, int dExp) { inline int CheckWithinHalfULP(double b, const BigInteger& d, int dExp) {
const Double db(b); const Double db(b);
const uint64_t bInt = db.IntegerSignificand(); const uint64_t bInt = db.IntegerSignificand();
const int bExp = db.IntegerExponent(); const int bExp = db.IntegerExponent();
@ -108,9 +108,9 @@ namespace internal {
dS.Difference(bS, &delta); dS.Difference(bS, &delta);
return delta.Compare(hS); return delta.Compare(hS);
} }
inline bool StrtodFast(double d, int p, double* result) { inline bool StrtodFast(double d, int p, double* result) {
// Use fast path for string-to-double conversion if possible // Use fast path for string-to-double conversion if possible
// see http://www.exploringbinary.com/fast-path-decimal-to-floating-point-conversion/ // see http://www.exploringbinary.com/fast-path-decimal-to-floating-point-conversion/
if (p > 22 && p < 22 + 16) { if (p > 22 && p < 22 + 16) {
@ -125,10 +125,10 @@ namespace internal {
} }
else else
return false; return false;
} }
// Compute an approximation and see if it is within 1/2 ULP // Compute an approximation and see if it is within 1/2 ULP
inline bool StrtodDiyFp(const char* decimals, int dLen, int dExp, double* result) { inline bool StrtodDiyFp(const char* decimals, int dLen, int dExp, double* result) {
uint64_t significand = 0; uint64_t significand = 0;
int i = 0; // 2^64 - 1 = 18446744073709551615, 1844674407370955161 = 0x1999999999999999 int i = 0; // 2^64 - 1 = 18446744073709551615, 1844674407370955161 = 0x1999999999999999
for (; i < dLen; i++) { for (; i < dLen; i++) {
@ -203,9 +203,9 @@ namespace internal {
*result = rounded.ToDouble(); *result = rounded.ToDouble();
return halfWay - static_cast<unsigned>(error) >= precisionBits || precisionBits >= halfWay + static_cast<unsigned>(error); return halfWay - static_cast<unsigned>(error) >= precisionBits || precisionBits >= halfWay + static_cast<unsigned>(error);
} }
inline double StrtodBigInteger(double approx, const char* decimals, int dLen, int dExp) { inline double StrtodBigInteger(double approx, const char* decimals, int dLen, int dExp) {
RAPIDJSON_ASSERT(dLen >= 0); RAPIDJSON_ASSERT(dLen >= 0);
const BigInteger dInt(decimals, static_cast<unsigned>(dLen)); const BigInteger dInt(decimals, static_cast<unsigned>(dLen));
Double a(approx); Double a(approx);
@ -221,9 +221,9 @@ namespace internal {
} }
else // adjustment else // adjustment
return a.NextPositiveDouble(); return a.NextPositiveDouble();
} }
inline double StrtodFullPrecision(double d, int p, const char* decimals, size_t length, size_t decimalPosition, int exp) { inline double StrtodFullPrecision(double d, int p, const char* decimals, size_t length, size_t decimalPosition, int exp) {
RAPIDJSON_ASSERT(d >= 0.0); RAPIDJSON_ASSERT(d >= 0.0);
RAPIDJSON_ASSERT(length >= 1); RAPIDJSON_ASSERT(length >= 1);
@ -282,7 +282,7 @@ namespace internal {
// Use approximation from StrtodDiyFp and make adjustment with BigInteger comparison // Use approximation from StrtodDiyFp and make adjustment with BigInteger comparison
return StrtodBigInteger(result, decimals, dLen, dExp); return StrtodBigInteger(result, decimals, dLen, dExp);
} }
} // namespace internal } // namespace internal
RAPIDJSON_NAMESPACE_END RAPIDJSON_NAMESPACE_END

View File

@ -19,22 +19,22 @@
#if defined(__clang__) #if defined(__clang__)
RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(c++ 98 - compat) RAPIDJSON_DIAG_OFF(c++98-compat)
#endif #endif
RAPIDJSON_NAMESPACE_BEGIN RAPIDJSON_NAMESPACE_BEGIN
namespace internal { namespace internal {
//! Custom swap() to avoid dependency on C++ <algorithm> header //! Custom swap() to avoid dependency on C++ <algorithm> header
/*! \tparam T Type of the arguments to swap, should be instantiated with primitive C++ types only. /*! \tparam T Type of the arguments to swap, should be instantiated with primitive C++ types only.
\note This has the same semantics as std::swap(). \note This has the same semantics as std::swap().
*/ */
template <typename T> template <typename T>
inline void Swap(T& a, T& b) RAPIDJSON_NOEXCEPT { inline void Swap(T& a, T& b) RAPIDJSON_NOEXCEPT {
T tmp = a; T tmp = a;
a = b; a = b;
b = tmp; b = tmp;
} }
} // namespace internal } // namespace internal
RAPIDJSON_NAMESPACE_END RAPIDJSON_NAMESPACE_END

View File

@ -54,7 +54,7 @@ public:
/*! /*!
\param stream stream opened for read. \param stream stream opened for read.
*/ */
BasicIStreamWrapper(StreamType& stream) : stream_(stream), buffer_(peekBuffer_), bufferSize_(4), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) { BasicIStreamWrapper(StreamType &stream) : stream_(stream), buffer_(peekBuffer_), bufferSize_(4), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) {
Read(); Read();
} }
@ -64,30 +64,20 @@ public:
\param buffer user-supplied buffer. \param buffer user-supplied buffer.
\param bufferSize size of buffer in bytes. Must >=4 bytes. \param bufferSize size of buffer in bytes. Must >=4 bytes.
*/ */
BasicIStreamWrapper(StreamType& stream, char* buffer, size_t bufferSize) : stream_(stream), buffer_(buffer), bufferSize_(bufferSize), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) { BasicIStreamWrapper(StreamType &stream, char* buffer, size_t bufferSize) : stream_(stream), buffer_(buffer), bufferSize_(bufferSize), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) {
RAPIDJSON_ASSERT(bufferSize >= 4); RAPIDJSON_ASSERT(bufferSize >= 4);
Read(); Read();
} }
Ch Peek() const { return *current_; } Ch Peek() const { return *current_; }
Ch Take() { Ch Take() { Ch c = *current_; Read(); return c; }
Ch c = *current_;
Read();
return c;
}
size_t Tell() const { return count_ + static_cast<size_t>(current_ - buffer_); } size_t Tell() const { return count_ + static_cast<size_t>(current_ - buffer_); }
// Not implemented // Not implemented
void Put(Ch) { RAPIDJSON_ASSERT(false); } void Put(Ch) { RAPIDJSON_ASSERT(false); }
void Flush() { RAPIDJSON_ASSERT(false); } void Flush() { RAPIDJSON_ASSERT(false); }
Ch* PutBegin() { Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
RAPIDJSON_ASSERT(false); size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
return 0;
}
size_t PutEnd(Ch*) {
RAPIDJSON_ASSERT(false);
return 0;
}
// For encoding detection only. // For encoding detection only.
const Ch* Peek4() const { const Ch* Peek4() const {
@ -116,11 +106,11 @@ private:
} }
} }
StreamType& stream_; StreamType &stream_;
Ch peekBuffer_[4], *buffer_; Ch peekBuffer_[4], *buffer_;
size_t bufferSize_; size_t bufferSize_;
Ch* bufferLast_; Ch *bufferLast_;
Ch* current_; Ch *current_;
size_t readCount_; size_t readCount_;
size_t count_; //!< Number of characters read size_t count_; //!< Number of characters read
bool eof_; bool eof_;

View File

@ -60,7 +60,7 @@ struct GenericMemoryBuffer {
typedef GenericMemoryBuffer<> MemoryBuffer; typedef GenericMemoryBuffer<> MemoryBuffer;
//! Implement specialized version of PutN() with memset() for better performance. //! Implement specialized version of PutN() with memset() for better performance.
template <> template<>
inline void PutN(MemoryBuffer& memoryBuffer, char c, size_t n) { inline void PutN(MemoryBuffer& memoryBuffer, char c, size_t n) {
std::memset(memoryBuffer.stack_.Push<char>(n), c, n * sizeof(c)); std::memset(memoryBuffer.stack_.Push<char>(n), c, n * sizeof(c));
} }

View File

@ -19,8 +19,8 @@
#ifdef __clang__ #ifdef __clang__
RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(unreachable - code) RAPIDJSON_DIAG_OFF(unreachable-code)
RAPIDJSON_DIAG_OFF(missing - noreturn) RAPIDJSON_DIAG_OFF(missing-noreturn)
#endif #endif
RAPIDJSON_NAMESPACE_BEGIN RAPIDJSON_NAMESPACE_BEGIN
@ -40,22 +40,16 @@ RAPIDJSON_NAMESPACE_BEGIN
struct MemoryStream { struct MemoryStream {
typedef char Ch; // byte typedef char Ch; // byte
MemoryStream(const Ch* src, size_t size) : src_(src), begin_(src), end_(src + size), size_(size) {} MemoryStream(const Ch *src, size_t size) : src_(src), begin_(src), end_(src + size), size_(size) {}
Ch Peek() const { return RAPIDJSON_UNLIKELY(src_ == end_) ? '\0' : *src_; } Ch Peek() const { return RAPIDJSON_UNLIKELY(src_ == end_) ? '\0' : *src_; }
Ch Take() { return RAPIDJSON_UNLIKELY(src_ == end_) ? '\0' : *src_++; } Ch Take() { return RAPIDJSON_UNLIKELY(src_ == end_) ? '\0' : *src_++; }
size_t Tell() const { return static_cast<size_t>(src_ - begin_); } size_t Tell() const { return static_cast<size_t>(src_ - begin_); }
Ch* PutBegin() { Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
RAPIDJSON_ASSERT(false);
return 0;
}
void Put(Ch) { RAPIDJSON_ASSERT(false); } void Put(Ch) { RAPIDJSON_ASSERT(false); }
void Flush() { RAPIDJSON_ASSERT(false); } void Flush() { RAPIDJSON_ASSERT(false); }
size_t PutEnd(Ch*) { size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
RAPIDJSON_ASSERT(false);
return 0;
}
// For encoding detection only. // For encoding detection only.
const Ch* Peek4() const { const Ch* Peek4() const {

View File

@ -194,11 +194,11 @@ typedef struct {
#define SCNiMAX "I64i" #define SCNiMAX "I64i"
#ifdef _WIN64 // [ #ifdef _WIN64 // [
#define SCNdPTR "I64d" # define SCNdPTR "I64d"
#define SCNiPTR "I64i" # define SCNiPTR "I64i"
#else // _WIN64 ][ #else // _WIN64 ][
#define SCNdPTR "ld" # define SCNdPTR "ld"
#define SCNiPTR "li" # define SCNiPTR "li"
#endif // _WIN64 ] #endif // _WIN64 ]
// The fscanf macros for unsigned integers are: // The fscanf macros for unsigned integers are:
@ -260,15 +260,15 @@ typedef struct {
#define SCNXMAX "I64X" #define SCNXMAX "I64X"
#ifdef _WIN64 // [ #ifdef _WIN64 // [
#define SCNoPTR "I64o" # define SCNoPTR "I64o"
#define SCNuPTR "I64u" # define SCNuPTR "I64u"
#define SCNxPTR "I64x" # define SCNxPTR "I64x"
#define SCNXPTR "I64X" # define SCNXPTR "I64X"
#else // _WIN64 ][ #else // _WIN64 ][
#define SCNoPTR "lo" # define SCNoPTR "lo"
#define SCNuPTR "lu" # define SCNuPTR "lu"
#define SCNxPTR "lx" # define SCNxPTR "lx"
#define SCNXPTR "lX" # define SCNXPTR "lX"
#endif // _WIN64 ] #endif // _WIN64 ]
#endif // __STDC_FORMAT_MACROS ] #endif // __STDC_FORMAT_MACROS ]
@ -287,7 +287,8 @@ static
#else // STATIC_IMAXDIV ][ #else // STATIC_IMAXDIV ][
_inline _inline
#endif // STATIC_IMAXDIV ] #endif // STATIC_IMAXDIV ]
imaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom) { imaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom)
{
imaxdiv_t result; imaxdiv_t result;
result.quot = numer / denom; result.quot = numer / denom;

View File

@ -76,10 +76,10 @@
// These #ifndef's are needed to prevent collisions with <boost/cstdint.hpp>. // These #ifndef's are needed to prevent collisions with <boost/cstdint.hpp>.
// Check out Issue 9 for the details. // Check out Issue 9 for the details.
#ifndef INTMAX_C // [ #ifndef INTMAX_C // [
#define INTMAX_C INT64_C # define INTMAX_C INT64_C
#endif // INTMAX_C ] #endif // INTMAX_C ]
#ifndef UINTMAX_C // [ #ifndef UINTMAX_C // [
#define UINTMAX_C UINT64_C # define UINTMAX_C UINT64_C
#endif // UINTMAX_C ] #endif // UINTMAX_C ]
#endif // __STDC_CONSTANT_MACROS ] #endif // __STDC_CONSTANT_MACROS ]
@ -95,18 +95,18 @@
#if defined(__cplusplus) && !defined(_M_ARM) #if defined(__cplusplus) && !defined(_M_ARM)
extern "C" { extern "C" {
#endif #endif
#include <wchar.h> # include <wchar.h>
#if defined(__cplusplus) && !defined(_M_ARM) #if defined(__cplusplus) && !defined(_M_ARM)
} }
#endif #endif
// Define _W64 macros to mark types changing their size, like intptr_t. // Define _W64 macros to mark types changing their size, like intptr_t.
#ifndef _W64 #ifndef _W64
#if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300 # if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300
#define _W64 __w64 # define _W64 __w64
#else # else
#define _W64 # define _W64
#endif # endif
#endif #endif
@ -118,19 +118,19 @@ extern "C" {
// realize that, e.g. char has the same size as __int8 // realize that, e.g. char has the same size as __int8
// so we give up on __intX for them. // so we give up on __intX for them.
#if (_MSC_VER < 1300) #if (_MSC_VER < 1300)
typedef signed char int8_t; typedef signed char int8_t;
typedef signed short int16_t; typedef signed short int16_t;
typedef signed int int32_t; typedef signed int int32_t;
typedef unsigned char uint8_t; typedef unsigned char uint8_t;
typedef unsigned short uint16_t; typedef unsigned short uint16_t;
typedef unsigned int uint32_t; typedef unsigned int uint32_t;
#else #else
typedef signed __int8 int8_t; typedef signed __int8 int8_t;
typedef signed __int16 int16_t; typedef signed __int16 int16_t;
typedef signed __int32 int32_t; typedef signed __int32 int32_t;
typedef unsigned __int8 uint8_t; typedef unsigned __int8 uint8_t;
typedef unsigned __int16 uint16_t; typedef unsigned __int16 uint16_t;
typedef unsigned __int32 uint32_t; typedef unsigned __int32 uint32_t;
#endif #endif
typedef signed __int64 int64_t; typedef signed __int64 int64_t;
typedef unsigned __int64 uint64_t; typedef unsigned __int64 uint64_t;
@ -158,11 +158,11 @@ typedef uint64_t uint_fast64_t;
// 7.18.1.4 Integer types capable of holding object pointers // 7.18.1.4 Integer types capable of holding object pointers
#ifdef _WIN64 // [ #ifdef _WIN64 // [
typedef signed __int64 intptr_t; typedef signed __int64 intptr_t;
typedef unsigned __int64 uintptr_t; typedef unsigned __int64 uintptr_t;
#else // _WIN64 ][ #else // _WIN64 ][
typedef _W64 signed int intptr_t; typedef _W64 signed int intptr_t;
typedef _W64 unsigned int uintptr_t; typedef _W64 unsigned int uintptr_t;
#endif // _WIN64 ] #endif // _WIN64 ]
// 7.18.1.5 Greatest-width integer types // 7.18.1.5 Greatest-width integer types
@ -218,13 +218,13 @@ typedef uint64_t uintmax_t;
// 7.18.2.4 Limits of integer types capable of holding object pointers // 7.18.2.4 Limits of integer types capable of holding object pointers
#ifdef _WIN64 // [ #ifdef _WIN64 // [
#define INTPTR_MIN INT64_MIN # define INTPTR_MIN INT64_MIN
#define INTPTR_MAX INT64_MAX # define INTPTR_MAX INT64_MAX
#define UINTPTR_MAX UINT64_MAX # define UINTPTR_MAX UINT64_MAX
#else // _WIN64 ][ #else // _WIN64 ][
#define INTPTR_MIN INT32_MIN # define INTPTR_MIN INT32_MIN
#define INTPTR_MAX INT32_MAX # define INTPTR_MAX INT32_MAX
#define UINTPTR_MAX UINT32_MAX # define UINTPTR_MAX UINT32_MAX
#endif // _WIN64 ] #endif // _WIN64 ]
// 7.18.2.5 Limits of greatest-width integer types // 7.18.2.5 Limits of greatest-width integer types
@ -235,30 +235,30 @@ typedef uint64_t uintmax_t;
// 7.18.3 Limits of other integer types // 7.18.3 Limits of other integer types
#ifdef _WIN64 // [ #ifdef _WIN64 // [
#define PTRDIFF_MIN _I64_MIN # define PTRDIFF_MIN _I64_MIN
#define PTRDIFF_MAX _I64_MAX # define PTRDIFF_MAX _I64_MAX
#else // _WIN64 ][ #else // _WIN64 ][
#define PTRDIFF_MIN _I32_MIN # define PTRDIFF_MIN _I32_MIN
#define PTRDIFF_MAX _I32_MAX # define PTRDIFF_MAX _I32_MAX
#endif // _WIN64 ] #endif // _WIN64 ]
#define SIG_ATOMIC_MIN INT_MIN #define SIG_ATOMIC_MIN INT_MIN
#define SIG_ATOMIC_MAX INT_MAX #define SIG_ATOMIC_MAX INT_MAX
#ifndef SIZE_MAX // [ #ifndef SIZE_MAX // [
#ifdef _WIN64 // [ # ifdef _WIN64 // [
#define SIZE_MAX _UI64_MAX # define SIZE_MAX _UI64_MAX
#else // _WIN64 ][ # else // _WIN64 ][
#define SIZE_MAX _UI32_MAX # define SIZE_MAX _UI32_MAX
#endif // _WIN64 ] # endif // _WIN64 ]
#endif // SIZE_MAX ] #endif // SIZE_MAX ]
// WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h> // WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h>
#ifndef WCHAR_MIN // [ #ifndef WCHAR_MIN // [
#define WCHAR_MIN 0 # define WCHAR_MIN 0
#endif // WCHAR_MIN ] #endif // WCHAR_MIN ]
#ifndef WCHAR_MAX // [ #ifndef WCHAR_MAX // [
#define WCHAR_MAX _UI16_MAX # define WCHAR_MAX _UI16_MAX
#endif // WCHAR_MAX ] #endif // WCHAR_MAX ]
#define WINT_MIN 0 #define WINT_MIN 0
@ -287,10 +287,10 @@ typedef uint64_t uintmax_t;
// These #ifndef's are needed to prevent collisions with <boost/cstdint.hpp>. // These #ifndef's are needed to prevent collisions with <boost/cstdint.hpp>.
// Check out Issue 9 for the details. // Check out Issue 9 for the details.
#ifndef INTMAX_C // [ #ifndef INTMAX_C // [
#define INTMAX_C INT64_C # define INTMAX_C INT64_C
#endif // INTMAX_C ] #endif // INTMAX_C ]
#ifndef UINTMAX_C // [ #ifndef UINTMAX_C // [
#define UINTMAX_C UINT64_C # define UINTMAX_C UINT64_C
#endif // UINTMAX_C ] #endif // UINTMAX_C ]
#endif // __STDC_CONSTANT_MACROS ] #endif // __STDC_CONSTANT_MACROS ]

View File

@ -56,26 +56,11 @@ public:
} }
// Not implemented // Not implemented
char Peek() const { char Peek() const { RAPIDJSON_ASSERT(false); return 0; }
RAPIDJSON_ASSERT(false); char Take() { RAPIDJSON_ASSERT(false); return 0; }
return 0; size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; }
} char* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
char Take() { size_t PutEnd(char*) { RAPIDJSON_ASSERT(false); return 0; }
RAPIDJSON_ASSERT(false);
return 0;
}
size_t Tell() const {
RAPIDJSON_ASSERT(false);
return 0;
}
char* PutBegin() {
RAPIDJSON_ASSERT(false);
return 0;
}
size_t PutEnd(char*) {
RAPIDJSON_ASSERT(false);
return 0;
}
private: private:
BasicOStreamWrapper(const BasicOStreamWrapper&); BasicOStreamWrapper(const BasicOStreamWrapper&);

View File

@ -20,7 +20,7 @@
#ifdef __clang__ #ifdef __clang__
RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(switch - enum) RAPIDJSON_DIAG_OFF(switch-enum)
#elif defined(_MSC_VER) #elif defined(_MSC_VER)
RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
@ -244,7 +244,7 @@ public:
GenericPointer Append(const Token& token, Allocator* allocator = 0) const { GenericPointer Append(const Token& token, Allocator* allocator = 0) const {
GenericPointer r; GenericPointer r;
r.allocator_ = allocator; r.allocator_ = allocator;
Ch* p = r.CopyFromRaw(*this, 1, token.length + 1); Ch *p = r.CopyFromRaw(*this, 1, token.length + 1);
std::memcpy(p, token.name, (token.length + 1) * sizeof(Ch)); std::memcpy(p, token.name, (token.length + 1) * sizeof(Ch));
r.tokens_[tokenCount_].name = p; r.tokens_[tokenCount_].name = p;
r.tokens_[tokenCount_].length = token.length; r.tokens_[tokenCount_].length = token.length;
@ -271,7 +271,7 @@ public:
\return A new Pointer with appended token. \return A new Pointer with appended token.
*/ */
template <typename T> template <typename T>
RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr<internal::IsSame<typename internal::RemoveConst<T>::Type, Ch>>), (GenericPointer)) RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr<internal::IsSame<typename internal::RemoveConst<T>::Type, Ch> >), (GenericPointer))
Append(T* name, Allocator* allocator = 0) const { Append(T* name, Allocator* allocator = 0) const {
return Append(name, internal::StrLen(name), allocator); return Append(name, internal::StrLen(name), allocator);
} }
@ -371,7 +371,8 @@ public:
for (size_t i = 0; i < tokenCount_; i++) { for (size_t i = 0; i < tokenCount_; i++) {
if (tokens_[i].index != rhs.tokens_[i].index || if (tokens_[i].index != rhs.tokens_[i].index ||
tokens_[i].length != rhs.tokens_[i].length || tokens_[i].length != rhs.tokens_[i].length ||
(tokens_[i].length != 0 && std::memcmp(tokens_[i].name, rhs.tokens_[i].name, sizeof(Ch) * tokens_[i].length) != 0)) { (tokens_[i].length != 0 && std::memcmp(tokens_[i].name, rhs.tokens_[i].name, sizeof(Ch)* tokens_[i].length) != 0))
{
return false; return false;
} }
} }
@ -422,7 +423,7 @@ public:
\tparam OutputStream Type of output stream. \tparam OutputStream Type of output stream.
\param os The output stream. \param os The output stream.
*/ */
template <typename OutputStream> template<typename OutputStream>
bool Stringify(OutputStream& os) const { bool Stringify(OutputStream& os) const {
return Stringify<false, OutputStream>(os); return Stringify<false, OutputStream>(os);
} }
@ -432,7 +433,7 @@ public:
\tparam OutputStream Type of output stream. \tparam OutputStream Type of output stream.
\param os The output stream. \param os The output stream.
*/ */
template <typename OutputStream> template<typename OutputStream>
bool StringifyUriFragment(OutputStream& os) const { bool StringifyUriFragment(OutputStream& os) const {
return Stringify<true, OutputStream>(os); return Stringify<true, OutputStream>(os);
} }
@ -461,7 +462,7 @@ public:
RAPIDJSON_ASSERT(IsValid()); RAPIDJSON_ASSERT(IsValid());
ValueType* v = &root; ValueType* v = &root;
bool exist = true; bool exist = true;
for (const Token* t = tokens_; t != tokens_ + tokenCount_; ++t) { for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) {
if (v->IsArray() && t->name[0] == '-' && t->length == 1) { if (v->IsArray() && t->name[0] == '-' && t->length == 1) {
v->PushBack(ValueType().Move(), allocator); v->PushBack(ValueType().Move(), allocator);
v = &((*v)[v->Size() - 1]); v = &((*v)[v->Size() - 1]);
@ -539,9 +540,10 @@ public:
ValueType* Get(ValueType& root, size_t* unresolvedTokenIndex = 0) const { ValueType* Get(ValueType& root, size_t* unresolvedTokenIndex = 0) const {
RAPIDJSON_ASSERT(IsValid()); RAPIDJSON_ASSERT(IsValid());
ValueType* v = &root; ValueType* v = &root;
for (const Token* t = tokens_; t != tokens_ + tokenCount_; ++t) { for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) {
switch (v->GetType()) { switch (v->GetType()) {
case kObjectType: { case kObjectType:
{
typename ValueType::MemberIterator m = v->FindMember(GenericValue<EncodingType>(GenericStringRef<Ch>(t->name, t->length))); typename ValueType::MemberIterator m = v->FindMember(GenericValue<EncodingType>(GenericStringRef<Ch>(t->name, t->length)));
if (m == v->MemberEnd()) if (m == v->MemberEnd())
break; break;
@ -616,7 +618,7 @@ public:
\tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool
*/ */
template <typename T> template <typename T>
RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T>>), (ValueType&)) RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))
GetWithDefault(ValueType& root, T defaultValue, typename ValueType::AllocatorType& allocator) const { GetWithDefault(ValueType& root, T defaultValue, typename ValueType::AllocatorType& allocator) const {
return GetWithDefault(root, ValueType(defaultValue).Move(), allocator); return GetWithDefault(root, ValueType(defaultValue).Move(), allocator);
} }
@ -646,7 +648,7 @@ public:
\tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool
*/ */
template <typename T, typename stackAllocator> template <typename T, typename stackAllocator>
RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T>>), (ValueType&)) RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))
GetWithDefault(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, T defaultValue) const { GetWithDefault(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, T defaultValue) const {
return GetWithDefault(document, defaultValue, document.GetAllocator()); return GetWithDefault(document, defaultValue, document.GetAllocator());
} }
@ -692,7 +694,7 @@ public:
\tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool
*/ */
template <typename T> template <typename T>
RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T>>), (ValueType&)) RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))
Set(ValueType& root, T value, typename ValueType::AllocatorType& allocator) const { Set(ValueType& root, T value, typename ValueType::AllocatorType& allocator) const {
return Create(root, allocator) = ValueType(value).Move(); return Create(root, allocator) = ValueType(value).Move();
} }
@ -728,7 +730,7 @@ public:
\tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool
*/ */
template <typename T, typename stackAllocator> template <typename T, typename stackAllocator>
RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T>>), (ValueType&)) RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))
Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, T value) const { Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, T value) const {
return Create(document) = value; return Create(document) = value;
} }
@ -774,14 +776,16 @@ public:
ValueType* v = &root; ValueType* v = &root;
const Token* last = tokens_ + (tokenCount_ - 1); const Token* last = tokens_ + (tokenCount_ - 1);
for (const Token* t = tokens_; t != last; ++t) { for (const Token *t = tokens_; t != last; ++t) {
switch (v->GetType()) { switch (v->GetType()) {
case kObjectType: { case kObjectType:
{
typename ValueType::MemberIterator m = v->FindMember(GenericValue<EncodingType>(GenericStringRef<Ch>(t->name, t->length))); typename ValueType::MemberIterator m = v->FindMember(GenericValue<EncodingType>(GenericStringRef<Ch>(t->name, t->length)));
if (m == v->MemberEnd()) if (m == v->MemberEnd())
return false; return false;
v = &m->value; v = &m->value;
} break; }
break;
case kArrayType: case kArrayType:
if (t->index == kPointerInvalidIndex || t->index >= v->Size()) if (t->index == kPointerInvalidIndex || t->index >= v->Size())
return false; return false;
@ -818,12 +822,12 @@ private:
ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)(); ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();
size_t nameBufferSize = rhs.tokenCount_; // null terminators for tokens size_t nameBufferSize = rhs.tokenCount_; // null terminators for tokens
for (Token* t = rhs.tokens_; t != rhs.tokens_ + rhs.tokenCount_; ++t) for (Token *t = rhs.tokens_; t != rhs.tokens_ + rhs.tokenCount_; ++t)
nameBufferSize += t->length; nameBufferSize += t->length;
tokenCount_ = rhs.tokenCount_ + extraToken; tokenCount_ = rhs.tokenCount_ + extraToken;
tokens_ = static_cast<Token*>(allocator_->Malloc(tokenCount_ * sizeof(Token) + (nameBufferSize + extraNameBufferSize) * sizeof(Ch))); tokens_ = static_cast<Token *>(allocator_->Malloc(tokenCount_ * sizeof(Token) + (nameBufferSize + extraNameBufferSize) * sizeof(Ch)));
nameBuffer_ = reinterpret_cast<Ch*>(tokens_ + tokenCount_); nameBuffer_ = reinterpret_cast<Ch *>(tokens_ + tokenCount_);
if (rhs.tokenCount_ > 0) { if (rhs.tokenCount_ > 0) {
std::memcpy(tokens_, rhs.tokens_, rhs.tokenCount_ * sizeof(Token)); std::memcpy(tokens_, rhs.tokens_, rhs.tokenCount_ * sizeof(Token));
} }
@ -833,7 +837,7 @@ private:
// Adjust pointers to name buffer // Adjust pointers to name buffer
std::ptrdiff_t diff = nameBuffer_ - rhs.nameBuffer_; std::ptrdiff_t diff = nameBuffer_ - rhs.nameBuffer_;
for (Token* t = tokens_; t != tokens_ + rhs.tokenCount_; ++t) for (Token *t = tokens_; t != tokens_ + rhs.tokenCount_; ++t)
t->name += diff; t->name += diff;
return nameBuffer_ + nameBufferSize; return nameBuffer_ + nameBufferSize;
@ -845,7 +849,7 @@ private:
\param c The character (code unit) to be tested. \param c The character (code unit) to be tested.
*/ */
bool NeedPercentEncode(Ch c) const { bool NeedPercentEncode(Ch c) const {
return !((c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || c == '-' || c == '.' || c == '_' || c == '~'); return !((c >= '0' && c <= '9') || (c >= 'A' && c <='Z') || (c >= 'a' && c <= 'z') || c == '-' || c == '.' || c == '_' || c =='~');
} }
//! Parse a JSON String or its URI fragment representation into tokens. //! Parse a JSON String or its URI fragment representation into tokens.
@ -871,8 +875,8 @@ private:
if (*s == '/') if (*s == '/')
tokenCount_++; tokenCount_++;
Token* token = tokens_ = static_cast<Token*>(allocator_->Malloc(tokenCount_ * sizeof(Token) + length * sizeof(Ch))); Token* token = tokens_ = static_cast<Token *>(allocator_->Malloc(tokenCount_ * sizeof(Token) + length * sizeof(Ch)));
Ch* name = nameBuffer_ = reinterpret_cast<Ch*>(tokens_ + tokenCount_); Ch* name = nameBuffer_ = reinterpret_cast<Ch *>(tokens_ + tokenCount_);
size_t i = 0; size_t i = 0;
// Detect if it is a URI fragment // Detect if it is a URI fragment
@ -929,10 +933,8 @@ private:
if (c == '~') { if (c == '~') {
if (i < length) { if (i < length) {
c = source[i]; c = source[i];
if (c == '0') if (c == '0') c = '~';
c = '~'; else if (c == '1') c = '/';
else if (c == '1')
c = '/';
else { else {
parseErrorCode_ = kPointerParseErrorInvalidEscape; parseErrorCode_ = kPointerParseErrorInvalidEscape;
goto error; goto error;
@ -996,14 +998,14 @@ private:
\tparam OutputStream type of output stream. \tparam OutputStream type of output stream.
\param os The output stream. \param os The output stream.
*/ */
template <bool uriFragment, typename OutputStream> template<bool uriFragment, typename OutputStream>
bool Stringify(OutputStream& os) const { bool Stringify(OutputStream& os) const {
RAPIDJSON_ASSERT(IsValid()); RAPIDJSON_ASSERT(IsValid());
if (uriFragment) if (uriFragment)
os.Put('#'); os.Put('#');
for (Token* t = tokens_; t != tokens_ + tokenCount_; ++t) { for (Token *t = tokens_; t != tokens_ + tokenCount_; ++t) {
os.Put('/'); os.Put('/');
for (size_t j = 0; j < t->length; j++) { for (size_t j = 0; j < t->length; j++) {
Ch c = t->name[j]; Ch c = t->name[j];
@ -1019,7 +1021,7 @@ private:
// Transcode to UTF8 sequence // Transcode to UTF8 sequence
GenericStringStream<typename ValueType::EncodingType> source(&t->name[j]); GenericStringStream<typename ValueType::EncodingType> source(&t->name[j]);
PercentEncodeStream<OutputStream> target(os); PercentEncodeStream<OutputStream> target(os);
if (!Transcoder<EncodingType, UTF8<>>().Validate(source, target)) if (!Transcoder<EncodingType, UTF8<> >().Validate(source, target))
return false; return false;
j += source.Tell() - 1; j += source.Tell() - 1;
} }
@ -1057,12 +1059,9 @@ private:
for (int j = 0; j < 2; j++) { for (int j = 0; j < 2; j++) {
c = static_cast<Ch>(c << 4); c = static_cast<Ch>(c << 4);
Ch h = *src_; Ch h = *src_;
if (h >= '0' && h <= '9') if (h >= '0' && h <= '9') c = static_cast<Ch>(c + h - '0');
c = static_cast<Ch>(c + h - '0'); else if (h >= 'A' && h <= 'F') c = static_cast<Ch>(c + h - 'A' + 10);
else if (h >= 'A' && h <= 'F') else if (h >= 'a' && h <= 'f') c = static_cast<Ch>(c + h - 'a' + 10);
c = static_cast<Ch>(c + h - 'A' + 10);
else if (h >= 'a' && h <= 'f')
c = static_cast<Ch>(c + h - 'a' + 10);
else { else {
valid_ = false; valid_ = false;
return 0; return 0;
@ -1094,7 +1093,6 @@ private:
os_.Put(static_cast<typename OutputStream::Ch>(hexDigits[u >> 4])); os_.Put(static_cast<typename OutputStream::Ch>(hexDigits[u >> 4]));
os_.Put(static_cast<typename OutputStream::Ch>(hexDigits[u & 15])); os_.Put(static_cast<typename OutputStream::Ch>(hexDigits[u & 15]));
} }
private: private:
OutputStream& os_; OutputStream& os_;
}; };
@ -1122,7 +1120,7 @@ typename T::ValueType& CreateValueByPointer(T& root, const GenericPointer<typena
} }
template <typename T, typename CharType, size_t N> template <typename T, typename CharType, size_t N>
typename T::ValueType& CreateValueByPointer(T& root, const CharType (&source)[N], typename T::AllocatorType& a) { typename T::ValueType& CreateValueByPointer(T& root, const CharType(&source)[N], typename T::AllocatorType& a) {
return GenericPointer<typename T::ValueType>(source, N - 1).Create(root, a); return GenericPointer<typename T::ValueType>(source, N - 1).Create(root, a);
} }
@ -1134,7 +1132,7 @@ typename DocumentType::ValueType& CreateValueByPointer(DocumentType& document, c
} }
template <typename DocumentType, typename CharType, size_t N> template <typename DocumentType, typename CharType, size_t N>
typename DocumentType::ValueType& CreateValueByPointer(DocumentType& document, const CharType (&source)[N]) { typename DocumentType::ValueType& CreateValueByPointer(DocumentType& document, const CharType(&source)[N]) {
return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Create(document); return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Create(document);
} }
@ -1156,7 +1154,7 @@ typename T::ValueType* GetValueByPointer(T& root, const CharType (&source)[N], s
} }
template <typename T, typename CharType, size_t N> template <typename T, typename CharType, size_t N>
const typename T::ValueType* GetValueByPointer(const T& root, const CharType (&source)[N], size_t* unresolvedTokenIndex = 0) { const typename T::ValueType* GetValueByPointer(const T& root, const CharType(&source)[N], size_t* unresolvedTokenIndex = 0) {
return GenericPointer<typename T::ValueType>(source, N - 1).Get(root, unresolvedTokenIndex); return GenericPointer<typename T::ValueType>(source, N - 1).Get(root, unresolvedTokenIndex);
} }
@ -1180,31 +1178,31 @@ typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointe
#endif #endif
template <typename T, typename T2> template <typename T, typename T2>
RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2>>), (typename T::ValueType&)) RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&))
GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, T2 defaultValue, typename T::AllocatorType& a) { GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, T2 defaultValue, typename T::AllocatorType& a) {
return pointer.GetWithDefault(root, defaultValue, a); return pointer.GetWithDefault(root, defaultValue, a);
} }
template <typename T, typename CharType, size_t N> template <typename T, typename CharType, size_t N>
typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType (&source)[N], const typename T::ValueType& defaultValue, typename T::AllocatorType& a) { typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const typename T::ValueType& defaultValue, typename T::AllocatorType& a) {
return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a); return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a);
} }
template <typename T, typename CharType, size_t N> template <typename T, typename CharType, size_t N>
typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType (&source)[N], const typename T::Ch* defaultValue, typename T::AllocatorType& a) { typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const typename T::Ch* defaultValue, typename T::AllocatorType& a) {
return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a); return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a);
} }
#if RAPIDJSON_HAS_STDSTRING #if RAPIDJSON_HAS_STDSTRING
template <typename T, typename CharType, size_t N> template <typename T, typename CharType, size_t N>
typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType (&source)[N], const std::basic_string<typename T::Ch>& defaultValue, typename T::AllocatorType& a) { typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const std::basic_string<typename T::Ch>& defaultValue, typename T::AllocatorType& a) {
return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a); return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a);
} }
#endif #endif
template <typename T, typename CharType, size_t N, typename T2> template <typename T, typename CharType, size_t N, typename T2>
RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2>>), (typename T::ValueType&)) RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&))
GetValueByPointerWithDefault(T& root, const CharType (&source)[N], T2 defaultValue, typename T::AllocatorType& a) { GetValueByPointerWithDefault(T& root, const CharType(&source)[N], T2 defaultValue, typename T::AllocatorType& a) {
return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a); return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a);
} }
@ -1228,31 +1226,31 @@ typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& doc
#endif #endif
template <typename DocumentType, typename T2> template <typename DocumentType, typename T2>
RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2>>), (typename DocumentType::ValueType&)) RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&))
GetValueByPointerWithDefault(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, T2 defaultValue) { GetValueByPointerWithDefault(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, T2 defaultValue) {
return pointer.GetWithDefault(document, defaultValue); return pointer.GetWithDefault(document, defaultValue);
} }
template <typename DocumentType, typename CharType, size_t N> template <typename DocumentType, typename CharType, size_t N>
typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType (&source)[N], const typename DocumentType::ValueType& defaultValue) { typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const typename DocumentType::ValueType& defaultValue) {
return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue); return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue);
} }
template <typename DocumentType, typename CharType, size_t N> template <typename DocumentType, typename CharType, size_t N>
typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType (&source)[N], const typename DocumentType::Ch* defaultValue) { typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const typename DocumentType::Ch* defaultValue) {
return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue); return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue);
} }
#if RAPIDJSON_HAS_STDSTRING #if RAPIDJSON_HAS_STDSTRING
template <typename DocumentType, typename CharType, size_t N> template <typename DocumentType, typename CharType, size_t N>
typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType (&source)[N], const std::basic_string<typename DocumentType::Ch>& defaultValue) { typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const std::basic_string<typename DocumentType::Ch>& defaultValue) {
return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue); return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue);
} }
#endif #endif
template <typename DocumentType, typename CharType, size_t N, typename T2> template <typename DocumentType, typename CharType, size_t N, typename T2>
RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2>>), (typename DocumentType::ValueType&)) RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&))
GetValueByPointerWithDefault(DocumentType& document, const CharType (&source)[N], T2 defaultValue) { GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], T2 defaultValue) {
return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue); return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue);
} }
@ -1281,36 +1279,36 @@ typename T::ValueType& SetValueByPointer(T& root, const GenericPointer<typename
#endif #endif
template <typename T, typename T2> template <typename T, typename T2>
RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2>>), (typename T::ValueType&)) RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&))
SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, T2 value, typename T::AllocatorType& a) { SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, T2 value, typename T::AllocatorType& a) {
return pointer.Set(root, value, a); return pointer.Set(root, value, a);
} }
template <typename T, typename CharType, size_t N> template <typename T, typename CharType, size_t N>
typename T::ValueType& SetValueByPointer(T& root, const CharType (&source)[N], typename T::ValueType& value, typename T::AllocatorType& a) { typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], typename T::ValueType& value, typename T::AllocatorType& a) {
return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a); return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
} }
template <typename T, typename CharType, size_t N> template <typename T, typename CharType, size_t N>
typename T::ValueType& SetValueByPointer(T& root, const CharType (&source)[N], const typename T::ValueType& value, typename T::AllocatorType& a) { typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const typename T::ValueType& value, typename T::AllocatorType& a) {
return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a); return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
} }
template <typename T, typename CharType, size_t N> template <typename T, typename CharType, size_t N>
typename T::ValueType& SetValueByPointer(T& root, const CharType (&source)[N], const typename T::Ch* value, typename T::AllocatorType& a) { typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const typename T::Ch* value, typename T::AllocatorType& a) {
return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a); return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
} }
#if RAPIDJSON_HAS_STDSTRING #if RAPIDJSON_HAS_STDSTRING
template <typename T, typename CharType, size_t N> template <typename T, typename CharType, size_t N>
typename T::ValueType& SetValueByPointer(T& root, const CharType (&source)[N], const std::basic_string<typename T::Ch>& value, typename T::AllocatorType& a) { typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const std::basic_string<typename T::Ch>& value, typename T::AllocatorType& a) {
return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a); return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
} }
#endif #endif
template <typename T, typename CharType, size_t N, typename T2> template <typename T, typename CharType, size_t N, typename T2>
RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2>>), (typename T::ValueType&)) RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&))
SetValueByPointer(T& root, const CharType (&source)[N], T2 value, typename T::AllocatorType& a) { SetValueByPointer(T& root, const CharType(&source)[N], T2 value, typename T::AllocatorType& a) {
return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a); return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
} }
@ -1339,36 +1337,36 @@ typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, cons
#endif #endif
template <typename DocumentType, typename T2> template <typename DocumentType, typename T2>
RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2>>), (typename DocumentType::ValueType&)) RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&))
SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, T2 value) { SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, T2 value) {
return pointer.Set(document, value); return pointer.Set(document, value);
} }
template <typename DocumentType, typename CharType, size_t N> template <typename DocumentType, typename CharType, size_t N>
typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType (&source)[N], typename DocumentType::ValueType& value) { typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], typename DocumentType::ValueType& value) {
return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value); return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
} }
template <typename DocumentType, typename CharType, size_t N> template <typename DocumentType, typename CharType, size_t N>
typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType (&source)[N], const typename DocumentType::ValueType& value) { typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const typename DocumentType::ValueType& value) {
return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value); return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
} }
template <typename DocumentType, typename CharType, size_t N> template <typename DocumentType, typename CharType, size_t N>
typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType (&source)[N], const typename DocumentType::Ch* value) { typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const typename DocumentType::Ch* value) {
return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value); return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
} }
#if RAPIDJSON_HAS_STDSTRING #if RAPIDJSON_HAS_STDSTRING
template <typename DocumentType, typename CharType, size_t N> template <typename DocumentType, typename CharType, size_t N>
typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType (&source)[N], const std::basic_string<typename DocumentType::Ch>& value) { typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const std::basic_string<typename DocumentType::Ch>& value) {
return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value); return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
} }
#endif #endif
template <typename DocumentType, typename CharType, size_t N, typename T2> template <typename DocumentType, typename CharType, size_t N, typename T2>
RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2>>), (typename DocumentType::ValueType&)) RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&))
SetValueByPointer(DocumentType& document, const CharType (&source)[N], T2 value) { SetValueByPointer(DocumentType& document, const CharType(&source)[N], T2 value) {
return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value); return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
} }
@ -1380,7 +1378,7 @@ typename T::ValueType& SwapValueByPointer(T& root, const GenericPointer<typename
} }
template <typename T, typename CharType, size_t N> template <typename T, typename CharType, size_t N>
typename T::ValueType& SwapValueByPointer(T& root, const CharType (&source)[N], typename T::ValueType& value, typename T::AllocatorType& a) { typename T::ValueType& SwapValueByPointer(T& root, const CharType(&source)[N], typename T::ValueType& value, typename T::AllocatorType& a) {
return GenericPointer<typename T::ValueType>(source, N - 1).Swap(root, value, a); return GenericPointer<typename T::ValueType>(source, N - 1).Swap(root, value, a);
} }
@ -1390,7 +1388,7 @@ typename DocumentType::ValueType& SwapValueByPointer(DocumentType& document, con
} }
template <typename DocumentType, typename CharType, size_t N> template <typename DocumentType, typename CharType, size_t N>
typename DocumentType::ValueType& SwapValueByPointer(DocumentType& document, const CharType (&source)[N], typename DocumentType::ValueType& value) { typename DocumentType::ValueType& SwapValueByPointer(DocumentType& document, const CharType(&source)[N], typename DocumentType::ValueType& value) {
return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Swap(document, value); return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Swap(document, value);
} }
@ -1402,7 +1400,7 @@ bool EraseValueByPointer(T& root, const GenericPointer<typename T::ValueType>& p
} }
template <typename T, typename CharType, size_t N> template <typename T, typename CharType, size_t N>
bool EraseValueByPointer(T& root, const CharType (&source)[N]) { bool EraseValueByPointer(T& root, const CharType(&source)[N]) {
return GenericPointer<typename T::ValueType>(source, N - 1).Erase(root); return GenericPointer<typename T::ValueType>(source, N - 1).Erase(root);
} }

View File

@ -24,7 +24,7 @@ RAPIDJSON_DIAG_OFF(effc++)
#if defined(__clang__) #if defined(__clang__)
RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(c++ 98 - compat) RAPIDJSON_DIAG_OFF(c++98-compat)
#endif #endif
RAPIDJSON_NAMESPACE_BEGIN RAPIDJSON_NAMESPACE_BEGIN
@ -44,7 +44,7 @@ enum PrettyFormatOptions {
\tparam TargetEncoding Encoding of output stream. \tparam TargetEncoding Encoding of output stream.
\tparam StackAllocator Type of allocator for allocating memory of stack. \tparam StackAllocator Type of allocator for allocating memory of stack.
*/ */
template <typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator, unsigned writeFlags = kWriteDefaultFlags> template<typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator, unsigned writeFlags = kWriteDefaultFlags>
class PrettyWriter : public Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator, writeFlags> { class PrettyWriter : public Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator, writeFlags> {
public: public:
typedef Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator, writeFlags> Base; typedef Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator, writeFlags> Base;
@ -55,13 +55,16 @@ public:
\param allocator User supplied allocator. If it is null, it will create a private one. \param allocator User supplied allocator. If it is null, it will create a private one.
\param levelDepth Initial capacity of stack. \param levelDepth Initial capacity of stack.
*/ */
explicit PrettyWriter(OutputStream& os, StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) : Base(os, allocator, levelDepth), indentChar_(' '), indentCharCount_(4), formatOptions_(kFormatDefault) {} explicit PrettyWriter(OutputStream& os, StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) :
Base(os, allocator, levelDepth), indentChar_(' '), indentCharCount_(4), formatOptions_(kFormatDefault) {}
explicit PrettyWriter(StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) : Base(allocator, levelDepth), indentChar_(' '), indentCharCount_(4), formatOptions_(kFormatDefault) {} explicit PrettyWriter(StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) :
Base(allocator, levelDepth), indentChar_(' '), indentCharCount_(4), formatOptions_(kFormatDefault) {}
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS #if RAPIDJSON_HAS_CXX11_RVALUE_REFS
PrettyWriter(PrettyWriter&& rhs) : Base(std::forward<PrettyWriter>(rhs)), indentChar_(rhs.indentChar_), indentCharCount_(rhs.indentCharCount_), formatOptions_(rhs.formatOptions_) {} PrettyWriter(PrettyWriter&& rhs) :
Base(std::forward<PrettyWriter>(rhs)), indentChar_(rhs.indentChar_), indentCharCount_(rhs.indentCharCount_), formatOptions_(rhs.formatOptions_) {}
#endif #endif
//! Set custom indentation. //! Set custom indentation.
@ -89,34 +92,13 @@ public:
*/ */
//@{ //@{
bool Null() { bool Null() { PrettyPrefix(kNullType); return Base::EndValue(Base::WriteNull()); }
PrettyPrefix(kNullType); bool Bool(bool b) { PrettyPrefix(b ? kTrueType : kFalseType); return Base::EndValue(Base::WriteBool(b)); }
return Base::EndValue(Base::WriteNull()); bool Int(int i) { PrettyPrefix(kNumberType); return Base::EndValue(Base::WriteInt(i)); }
} bool Uint(unsigned u) { PrettyPrefix(kNumberType); return Base::EndValue(Base::WriteUint(u)); }
bool Bool(bool b) { bool Int64(int64_t i64) { PrettyPrefix(kNumberType); return Base::EndValue(Base::WriteInt64(i64)); }
PrettyPrefix(b ? kTrueType : kFalseType); bool Uint64(uint64_t u64) { PrettyPrefix(kNumberType); return Base::EndValue(Base::WriteUint64(u64)); }
return Base::EndValue(Base::WriteBool(b)); bool Double(double d) { PrettyPrefix(kNumberType); return Base::EndValue(Base::WriteDouble(d)); }
}
bool Int(int i) {
PrettyPrefix(kNumberType);
return Base::EndValue(Base::WriteInt(i));
}
bool Uint(unsigned u) {
PrettyPrefix(kNumberType);
return Base::EndValue(Base::WriteUint(u));
}
bool Int64(int64_t i64) {
PrettyPrefix(kNumberType);
return Base::EndValue(Base::WriteInt64(i64));
}
bool Uint64(uint64_t u64) {
PrettyPrefix(kNumberType);
return Base::EndValue(Base::WriteUint64(u64));
}
bool Double(double d) {
PrettyPrefix(kNumberType);
return Base::EndValue(Base::WriteDouble(d));
}
bool RawNumber(const Ch* str, SizeType length, bool copy = false) { bool RawNumber(const Ch* str, SizeType length, bool copy = false) {
RAPIDJSON_ASSERT(str != 0); RAPIDJSON_ASSERT(str != 0);

View File

@ -244,41 +244,41 @@
*/ */
#ifndef RAPIDJSON_ENDIAN #ifndef RAPIDJSON_ENDIAN
// Detect with GCC 4.6's macro // Detect with GCC 4.6's macro
#ifdef __BYTE_ORDER__ # ifdef __BYTE_ORDER__
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ # if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
#define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN # define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ # elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
#define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN # define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN
#else # else
#error Unknown machine endianness detected. User needs to define RAPIDJSON_ENDIAN. # error Unknown machine endianness detected. User needs to define RAPIDJSON_ENDIAN.
#endif // __BYTE_ORDER__ # endif // __BYTE_ORDER__
// Detect with GLIBC's endian.h // Detect with GLIBC's endian.h
#elif defined(__GLIBC__) # elif defined(__GLIBC__)
#include <endian.h> # include <endian.h>
#if (__BYTE_ORDER == __LITTLE_ENDIAN) # if (__BYTE_ORDER == __LITTLE_ENDIAN)
#define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN # define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
#elif (__BYTE_ORDER == __BIG_ENDIAN) # elif (__BYTE_ORDER == __BIG_ENDIAN)
#define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN # define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN
#else # else
#error Unknown machine endianness detected. User needs to define RAPIDJSON_ENDIAN. # error Unknown machine endianness detected. User needs to define RAPIDJSON_ENDIAN.
#endif // __GLIBC__ # endif // __GLIBC__
// Detect with _LITTLE_ENDIAN and _BIG_ENDIAN macro // Detect with _LITTLE_ENDIAN and _BIG_ENDIAN macro
#elif defined(_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN) # elif defined(_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN)
#define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN # define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
#elif defined(_BIG_ENDIAN) && !defined(_LITTLE_ENDIAN) # elif defined(_BIG_ENDIAN) && !defined(_LITTLE_ENDIAN)
#define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN # define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN
// Detect with architecture macros // Detect with architecture macros
#elif defined(__sparc) || defined(__sparc__) || defined(_POWER) || defined(__powerpc__) || defined(__ppc__) || defined(__hpux) || defined(__hppa) || defined(_MIPSEB) || defined(_POWER) || defined(__s390__) # elif defined(__sparc) || defined(__sparc__) || defined(_POWER) || defined(__powerpc__) || defined(__ppc__) || defined(__hpux) || defined(__hppa) || defined(_MIPSEB) || defined(_POWER) || defined(__s390__)
#define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN # define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN
#elif defined(__i386__) || defined(__alpha__) || defined(__ia64) || defined(__ia64__) || defined(_M_IX86) || defined(_M_IA64) || defined(_M_ALPHA) || defined(__amd64) || defined(__amd64__) || defined(_M_AMD64) || defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || defined(__bfin__) # elif defined(__i386__) || defined(__alpha__) || defined(__ia64) || defined(__ia64__) || defined(_M_IX86) || defined(_M_IA64) || defined(_M_ALPHA) || defined(__amd64) || defined(__amd64__) || defined(_M_AMD64) || defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || defined(__bfin__)
#define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN # define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
#elif defined(_MSC_VER) && (defined(_M_ARM) || defined(_M_ARM64)) # elif defined(_MSC_VER) && (defined(_M_ARM) || defined(_M_ARM64))
#define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN # define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
#elif defined(RAPIDJSON_DOXYGEN_RUNNING) # elif defined(RAPIDJSON_DOXYGEN_RUNNING)
#define RAPIDJSON_ENDIAN # define RAPIDJSON_ENDIAN
#else # else
#error Unknown machine endianness detected. User needs to define RAPIDJSON_ENDIAN. # error Unknown machine endianness detected. User needs to define RAPIDJSON_ENDIAN.
#endif # endif
#endif // RAPIDJSON_ENDIAN #endif // RAPIDJSON_ENDIAN
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
@ -343,8 +343,8 @@
#if RAPIDJSON_64BIT != 1 #if RAPIDJSON_64BIT != 1
#error RAPIDJSON_48BITPOINTER_OPTIMIZATION can only be set to 1 when RAPIDJSON_64BIT=1 #error RAPIDJSON_48BITPOINTER_OPTIMIZATION can only be set to 1 when RAPIDJSON_64BIT=1
#endif #endif
#define RAPIDJSON_SETPOINTER(type, p, x) (p = reinterpret_cast<type*>((reinterpret_cast<uintptr_t>(p) & static_cast<uintptr_t>(RAPIDJSON_UINT64_C2(0xFFFF0000, 0x00000000))) | reinterpret_cast<uintptr_t>(reinterpret_cast<const void*>(x)))) #define RAPIDJSON_SETPOINTER(type, p, x) (p = reinterpret_cast<type *>((reinterpret_cast<uintptr_t>(p) & static_cast<uintptr_t>(RAPIDJSON_UINT64_C2(0xFFFF0000, 0x00000000))) | reinterpret_cast<uintptr_t>(reinterpret_cast<const void*>(x))))
#define RAPIDJSON_GETPOINTER(type, p) (reinterpret_cast<type*>(reinterpret_cast<uintptr_t>(p) & static_cast<uintptr_t>(RAPIDJSON_UINT64_C2(0x0000FFFF, 0xFFFFFFFF)))) #define RAPIDJSON_GETPOINTER(type, p) (reinterpret_cast<type *>(reinterpret_cast<uintptr_t>(p) & static_cast<uintptr_t>(RAPIDJSON_UINT64_C2(0x0000FFFF, 0xFFFFFFFF))))
#else #else
#define RAPIDJSON_SETPOINTER(type, p, x) (p = (x)) #define RAPIDJSON_SETPOINTER(type, p, x) (p = (x))
#define RAPIDJSON_GETPOINTER(type, p) (p) #define RAPIDJSON_GETPOINTER(type, p) (p)
@ -379,7 +379,8 @@
If any of these symbols is defined, RapidJSON defines the macro If any of these symbols is defined, RapidJSON defines the macro
\c RAPIDJSON_SIMD to indicate the availability of the optimized code. \c RAPIDJSON_SIMD to indicate the availability of the optimized code.
*/ */
#if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42) || defined(RAPIDJSON_NEON) || defined(RAPIDJSON_DOXYGEN_RUNNING) #if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42) \
|| defined(RAPIDJSON_NEON) || defined(RAPIDJSON_DOXYGEN_RUNNING)
#define RAPIDJSON_SIMD #define RAPIDJSON_SIMD
#endif #endif
@ -441,7 +442,7 @@ RAPIDJSON_NAMESPACE_END
// Prefer C++11 static_assert, if available // Prefer C++11 static_assert, if available
#ifndef RAPIDJSON_STATIC_ASSERT #ifndef RAPIDJSON_STATIC_ASSERT
#if RAPIDJSON_CPLUSPLUS >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800) #if RAPIDJSON_CPLUSPLUS >= 201103L || ( defined(_MSC_VER) && _MSC_VER >= 1800 )
#define RAPIDJSON_STATIC_ASSERT(x) \ #define RAPIDJSON_STATIC_ASSERT(x) \
static_assert(x, RAPIDJSON_STRINGIFY(x)) static_assert(x, RAPIDJSON_STRINGIFY(x))
#endif // C++11 #endif // C++11
@ -453,14 +454,9 @@ RAPIDJSON_NAMESPACE_END
//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN //!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
#endif #endif
RAPIDJSON_NAMESPACE_BEGIN RAPIDJSON_NAMESPACE_BEGIN
template <bool x> template <bool x> struct STATIC_ASSERTION_FAILURE;
struct STATIC_ASSERTION_FAILURE; template <> struct STATIC_ASSERTION_FAILURE<true> { enum { value = 1 }; };
template <> template <size_t x> struct StaticAssertTest {};
struct STATIC_ASSERTION_FAILURE<true> {
enum { value = 1 };
};
template <size_t x>
struct StaticAssertTest {};
RAPIDJSON_NAMESPACE_END RAPIDJSON_NAMESPACE_END
#if defined(__GNUC__) || defined(__clang__) #if defined(__GNUC__) || defined(__clang__)
@ -479,7 +475,7 @@ RAPIDJSON_NAMESPACE_END
*/ */
#define RAPIDJSON_STATIC_ASSERT(x) \ #define RAPIDJSON_STATIC_ASSERT(x) \
typedef ::RAPIDJSON_NAMESPACE::StaticAssertTest< \ typedef ::RAPIDJSON_NAMESPACE::StaticAssertTest< \
sizeof(::RAPIDJSON_NAMESPACE::STATIC_ASSERTION_FAILURE<bool(x)>)> \ sizeof(::RAPIDJSON_NAMESPACE::STATIC_ASSERTION_FAILURE<bool(x) >)> \
RAPIDJSON_JOIN(StaticAssertTypedef, __LINE__) RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE RAPIDJSON_JOIN(StaticAssertTypedef, __LINE__) RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE
#endif // RAPIDJSON_STATIC_ASSERT #endif // RAPIDJSON_STATIC_ASSERT
@ -519,11 +515,10 @@ RAPIDJSON_NAMESPACE_END
#define RAPIDJSON_MULTILINEMACRO_BEGIN do { #define RAPIDJSON_MULTILINEMACRO_BEGIN do {
#define RAPIDJSON_MULTILINEMACRO_END \ #define RAPIDJSON_MULTILINEMACRO_END \
} \ } while((void)0, 0)
while ((void)0, 0)
// adopted from Boost // adopted from Boost
#define RAPIDJSON_VERSION_CODE(x, y, z) \ #define RAPIDJSON_VERSION_CODE(x,y,z) \
(((x)*100000) + ((y)*100) + (z)) (((x)*100000) + ((y)*100) + (z))
#if defined(__has_builtin) #if defined(__has_builtin)
@ -537,18 +532,18 @@ RAPIDJSON_NAMESPACE_END
#if defined(__GNUC__) #if defined(__GNUC__)
#define RAPIDJSON_GNUC \ #define RAPIDJSON_GNUC \
RAPIDJSON_VERSION_CODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) RAPIDJSON_VERSION_CODE(__GNUC__,__GNUC_MINOR__,__GNUC_PATCHLEVEL__)
#endif #endif
#if defined(__clang__) || (defined(RAPIDJSON_GNUC) && RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4, 2, 0)) #if defined(__clang__) || (defined(RAPIDJSON_GNUC) && RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,2,0))
#define RAPIDJSON_PRAGMA(x) _Pragma(RAPIDJSON_STRINGIFY(x)) #define RAPIDJSON_PRAGMA(x) _Pragma(RAPIDJSON_STRINGIFY(x))
#define RAPIDJSON_DIAG_PRAGMA(x) RAPIDJSON_PRAGMA(GCC diagnostic x) #define RAPIDJSON_DIAG_PRAGMA(x) RAPIDJSON_PRAGMA(GCC diagnostic x)
#define RAPIDJSON_DIAG_OFF(x) \ #define RAPIDJSON_DIAG_OFF(x) \
RAPIDJSON_DIAG_PRAGMA(ignored RAPIDJSON_STRINGIFY(RAPIDJSON_JOIN(-W, x))) RAPIDJSON_DIAG_PRAGMA(ignored RAPIDJSON_STRINGIFY(RAPIDJSON_JOIN(-W,x)))
// push/pop support in Clang and GCC>=4.6 // push/pop support in Clang and GCC>=4.6
#if defined(__clang__) || (defined(RAPIDJSON_GNUC) && RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4, 6, 0)) #if defined(__clang__) || (defined(RAPIDJSON_GNUC) && RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,6,0))
#define RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PRAGMA(push) #define RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PRAGMA(push)
#define RAPIDJSON_DIAG_POP RAPIDJSON_DIAG_PRAGMA(pop) #define RAPIDJSON_DIAG_POP RAPIDJSON_DIAG_PRAGMA(pop)
#else // GCC >= 4.2, < 4.6 #else // GCC >= 4.2, < 4.6
@ -562,8 +557,7 @@ RAPIDJSON_NAMESPACE_END
#define RAPIDJSON_PRAGMA(x) __pragma(x) #define RAPIDJSON_PRAGMA(x) __pragma(x)
#define RAPIDJSON_DIAG_PRAGMA(x) RAPIDJSON_PRAGMA(warning(x)) #define RAPIDJSON_DIAG_PRAGMA(x) RAPIDJSON_PRAGMA(warning(x))
#define RAPIDJSON_DIAG_OFF(x) RAPIDJSON_DIAG_PRAGMA(disable \ #define RAPIDJSON_DIAG_OFF(x) RAPIDJSON_DIAG_PRAGMA(disable: x)
: x)
#define RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PRAGMA(push) #define RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PRAGMA(push)
#define RAPIDJSON_DIAG_POP RAPIDJSON_DIAG_PRAGMA(pop) #define RAPIDJSON_DIAG_POP RAPIDJSON_DIAG_PRAGMA(pop)
@ -592,7 +586,7 @@ RAPIDJSON_NAMESPACE_END
#else #else
#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 0 #define RAPIDJSON_HAS_CXX11_RVALUE_REFS 0
#endif #endif
#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4, 3, 0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \ #elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,3,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \
(defined(_MSC_VER) && _MSC_VER >= 1600) || \ (defined(_MSC_VER) && _MSC_VER >= 1600) || \
(defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x5140 && defined(__GXX_EXPERIMENTAL_CXX0X__)) (defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x5140 && defined(__GXX_EXPERIMENTAL_CXX0X__))
@ -611,7 +605,7 @@ RAPIDJSON_NAMESPACE_END
#define RAPIDJSON_HAS_CXX11_NOEXCEPT 1 #define RAPIDJSON_HAS_CXX11_NOEXCEPT 1
#elif defined(__clang__) #elif defined(__clang__)
#define RAPIDJSON_HAS_CXX11_NOEXCEPT __has_feature(cxx_noexcept) #define RAPIDJSON_HAS_CXX11_NOEXCEPT __has_feature(cxx_noexcept)
#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4, 6, 0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \ #elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,6,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \
(defined(_MSC_VER) && _MSC_VER >= 1900) || \ (defined(_MSC_VER) && _MSC_VER >= 1900) || \
(defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x5140 && defined(__GXX_EXPERIMENTAL_CXX0X__)) (defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x5140 && defined(__GXX_EXPERIMENTAL_CXX0X__))
#define RAPIDJSON_HAS_CXX11_NOEXCEPT 1 #define RAPIDJSON_HAS_CXX11_NOEXCEPT 1
@ -639,7 +633,7 @@ RAPIDJSON_NAMESPACE_END
#ifndef RAPIDJSON_HAS_CXX11_RANGE_FOR #ifndef RAPIDJSON_HAS_CXX11_RANGE_FOR
#if defined(__clang__) #if defined(__clang__)
#define RAPIDJSON_HAS_CXX11_RANGE_FOR __has_feature(cxx_range_for) #define RAPIDJSON_HAS_CXX11_RANGE_FOR __has_feature(cxx_range_for)
#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4, 6, 0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \ #elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,6,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \
(defined(_MSC_VER) && _MSC_VER >= 1700) || \ (defined(_MSC_VER) && _MSC_VER >= 1700) || \
(defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x5140 && defined(__GXX_EXPERIMENTAL_CXX0X__)) (defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x5140 && defined(__GXX_EXPERIMENTAL_CXX0X__))
#define RAPIDJSON_HAS_CXX11_RANGE_FOR 1 #define RAPIDJSON_HAS_CXX11_RANGE_FOR 1
@ -656,23 +650,23 @@ RAPIDJSON_NAMESPACE_END
#endif #endif
#if RAPIDJSON_HAS_CXX17 #if RAPIDJSON_HAS_CXX17
#define RAPIDJSON_DELIBERATE_FALLTHROUGH [[fallthrough]] # define RAPIDJSON_DELIBERATE_FALLTHROUGH [[fallthrough]]
#elif defined(__has_cpp_attribute) #elif defined(__has_cpp_attribute)
#if __has_cpp_attribute(clang::fallthrough) # if __has_cpp_attribute(clang::fallthrough)
#define RAPIDJSON_DELIBERATE_FALLTHROUGH [[clang::fallthrough]] # define RAPIDJSON_DELIBERATE_FALLTHROUGH [[clang::fallthrough]]
#elif __has_cpp_attribute(fallthrough) # elif __has_cpp_attribute(fallthrough)
#define RAPIDJSON_DELIBERATE_FALLTHROUGH __attribute__((fallthrough)) # define RAPIDJSON_DELIBERATE_FALLTHROUGH __attribute__((fallthrough))
# else
# define RAPIDJSON_DELIBERATE_FALLTHROUGH
# endif
#else #else
#define RAPIDJSON_DELIBERATE_FALLTHROUGH # define RAPIDJSON_DELIBERATE_FALLTHROUGH
#endif
#else
#define RAPIDJSON_DELIBERATE_FALLTHROUGH
#endif #endif
//!@endcond //!@endcond
//! Assertion (in non-throwing contexts). //! Assertion (in non-throwing contexts).
/*! \ingroup RAPIDJSON_CONFIG /*! \ingroup RAPIDJSON_CONFIG
Some functions provide a \c noexcept guarantee, if the compiler supports it. Some functions provide a \c noexcept guarantee, if the compiler supports it.
In these cases, the \ref RAPIDJSON_ASSERT macro cannot be overridden to In these cases, the \ref RAPIDJSON_ASSERT macro cannot be overridden to
throw an exception. This macro adds a separate customization point for throw an exception. This macro adds a separate customization point for

View File

@ -40,9 +40,9 @@
#ifdef __clang__ #ifdef __clang__
RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(old - style - cast) RAPIDJSON_DIAG_OFF(old-style-cast)
RAPIDJSON_DIAG_OFF(padded) RAPIDJSON_DIAG_OFF(padded)
RAPIDJSON_DIAG_OFF(switch - enum) RAPIDJSON_DIAG_OFF(switch-enum)
#elif defined(_MSC_VER) #elif defined(_MSC_VER)
RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
@ -194,7 +194,7 @@ concept Handler {
/*! This can be used as base class of any reader handler. /*! This can be used as base class of any reader handler.
\note implements Handler concept \note implements Handler concept
*/ */
template <typename Encoding = UTF8<>, typename Derived = void> template<typename Encoding = UTF8<>, typename Derived = void>
struct BaseReaderHandler { struct BaseReaderHandler {
typedef typename Encoding::Ch Ch; typedef typename Encoding::Ch Ch;
@ -223,35 +223,35 @@ struct BaseReaderHandler {
namespace internal { namespace internal {
template <typename Stream, int = StreamTraits<Stream>::copyOptimization> template<typename Stream, int = StreamTraits<Stream>::copyOptimization>
class StreamLocalCopy; class StreamLocalCopy;
//! Do copy optimization. //! Do copy optimization.
template <typename Stream> template<typename Stream>
class StreamLocalCopy<Stream, 1> { class StreamLocalCopy<Stream, 1> {
public: public:
StreamLocalCopy(Stream& original) : s(original), original_(original) {} StreamLocalCopy(Stream& original) : s(original), original_(original) {}
~StreamLocalCopy() { original_ = s; } ~StreamLocalCopy() { original_ = s; }
Stream s; Stream s;
private: private:
StreamLocalCopy& operator=(const StreamLocalCopy&) /* = delete */; StreamLocalCopy& operator=(const StreamLocalCopy&) /* = delete */;
Stream& original_; Stream& original_;
}; };
//! Keep reference. //! Keep reference.
template <typename Stream> template<typename Stream>
class StreamLocalCopy<Stream, 0> { class StreamLocalCopy<Stream, 0> {
public: public:
StreamLocalCopy(Stream& original) : s(original) {} StreamLocalCopy(Stream& original) : s(original) {}
Stream& s; Stream& s;
private: private:
StreamLocalCopy& operator=(const StreamLocalCopy&) /* = delete */; StreamLocalCopy& operator=(const StreamLocalCopy&) /* = delete */;
}; };
} // namespace internal } // namespace internal
@ -262,7 +262,7 @@ namespace internal {
/*! \param is A input stream for skipping white spaces. /*! \param is A input stream for skipping white spaces.
\note This function has SSE2/SSE4.2 specialization. \note This function has SSE2/SSE4.2 specialization.
*/ */
template <typename InputStream> template<typename InputStream>
void SkipWhitespace(InputStream& is) { void SkipWhitespace(InputStream& is) {
internal::StreamLocalCopy<InputStream> copy(is); internal::StreamLocalCopy<InputStream> copy(is);
InputStream& s(copy.s); InputStream& s(copy.s);
@ -280,7 +280,7 @@ inline const char* SkipWhitespace(const char* p, const char* end) {
#ifdef RAPIDJSON_SSE42 #ifdef RAPIDJSON_SSE42
//! Skip whitespace with SSE 4.2 pcmpistrm instruction, testing 16 8-byte characters at once. //! Skip whitespace with SSE 4.2 pcmpistrm instruction, testing 16 8-byte characters at once.
inline const char* SkipWhitespace_SIMD(const char* p) { inline const char *SkipWhitespace_SIMD(const char* p) {
// Fast return for single non-whitespace // Fast return for single non-whitespace
if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t') if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
++p; ++p;
@ -297,17 +297,17 @@ inline const char* SkipWhitespace_SIMD(const char* p) {
// The rest of string using SIMD // The rest of string using SIMD
static const char whitespace[16] = " \n\r\t"; static const char whitespace[16] = " \n\r\t";
const __m128i w = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&whitespace[0])); const __m128i w = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespace[0]));
for (;; p += 16) { for (;; p += 16) {
const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i*>(p)); const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
const int r = _mm_cmpistri(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_LEAST_SIGNIFICANT | _SIDD_NEGATIVE_POLARITY); const int r = _mm_cmpistri(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_LEAST_SIGNIFICANT | _SIDD_NEGATIVE_POLARITY);
if (r != 16) // some of characters is non-whitespace if (r != 16) // some of characters is non-whitespace
return p + r; return p + r;
} }
} }
inline const char* SkipWhitespace_SIMD(const char* p, const char* end) { inline const char *SkipWhitespace_SIMD(const char* p, const char* end) {
// Fast return for single non-whitespace // Fast return for single non-whitespace
if (p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')) if (p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t'))
++p; ++p;
@ -316,10 +316,10 @@ inline const char* SkipWhitespace_SIMD(const char* p, const char* end) {
// The middle of string using SIMD // The middle of string using SIMD
static const char whitespace[16] = " \n\r\t"; static const char whitespace[16] = " \n\r\t";
const __m128i w = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&whitespace[0])); const __m128i w = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespace[0]));
for (; p <= end - 16; p += 16) { for (; p <= end - 16; p += 16) {
const __m128i s = _mm_loadu_si128(reinterpret_cast<const __m128i*>(p)); const __m128i s = _mm_loadu_si128(reinterpret_cast<const __m128i *>(p));
const int r = _mm_cmpistri(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_LEAST_SIGNIFICANT | _SIDD_NEGATIVE_POLARITY); const int r = _mm_cmpistri(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_LEAST_SIGNIFICANT | _SIDD_NEGATIVE_POLARITY);
if (r != 16) // some of characters is non-whitespace if (r != 16) // some of characters is non-whitespace
return p + r; return p + r;
@ -331,7 +331,7 @@ inline const char* SkipWhitespace_SIMD(const char* p, const char* end) {
#elif defined(RAPIDJSON_SSE2) #elif defined(RAPIDJSON_SSE2)
//! Skip whitespace with SSE2 instructions, testing 16 8-byte characters at once. //! Skip whitespace with SSE2 instructions, testing 16 8-byte characters at once.
inline const char* SkipWhitespace_SIMD(const char* p) { inline const char *SkipWhitespace_SIMD(const char* p) {
// Fast return for single non-whitespace // Fast return for single non-whitespace
if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t') if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
++p; ++p;
@ -346,19 +346,18 @@ inline const char* SkipWhitespace_SIMD(const char* p) {
else else
return p; return p;
// The rest of string // The rest of string
#define C16(c) \ #define C16(c) { c, c, c, c, c, c, c, c, c, c, c, c, c, c, c, c }
{ c, c, c, c, c, c, c, c, c, c, c, c, c, c, c, c }
static const char whitespaces[4][16] = { C16(' '), C16('\n'), C16('\r'), C16('\t') }; static const char whitespaces[4][16] = { C16(' '), C16('\n'), C16('\r'), C16('\t') };
#undef C16 #undef C16
const __m128i w0 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&whitespaces[0][0])); const __m128i w0 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[0][0]));
const __m128i w1 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&whitespaces[1][0])); const __m128i w1 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[1][0]));
const __m128i w2 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&whitespaces[2][0])); const __m128i w2 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[2][0]));
const __m128i w3 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&whitespaces[3][0])); const __m128i w3 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[3][0]));
for (;; p += 16) { for (;; p += 16) {
const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i*>(p)); const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
__m128i x = _mm_cmpeq_epi8(s, w0); __m128i x = _mm_cmpeq_epi8(s, w0);
x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w1)); x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w1));
x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w2)); x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w2));
@ -376,26 +375,25 @@ inline const char* SkipWhitespace_SIMD(const char* p) {
} }
} }
inline const char* SkipWhitespace_SIMD(const char* p, const char* end) { inline const char *SkipWhitespace_SIMD(const char* p, const char* end) {
// Fast return for single non-whitespace // Fast return for single non-whitespace
if (p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')) if (p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t'))
++p; ++p;
else else
return p; return p;
// The rest of string // The rest of string
#define C16(c) \ #define C16(c) { c, c, c, c, c, c, c, c, c, c, c, c, c, c, c, c }
{ c, c, c, c, c, c, c, c, c, c, c, c, c, c, c, c }
static const char whitespaces[4][16] = { C16(' '), C16('\n'), C16('\r'), C16('\t') }; static const char whitespaces[4][16] = { C16(' '), C16('\n'), C16('\r'), C16('\t') };
#undef C16 #undef C16
const __m128i w0 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&whitespaces[0][0])); const __m128i w0 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[0][0]));
const __m128i w1 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&whitespaces[1][0])); const __m128i w1 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[1][0]));
const __m128i w2 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&whitespaces[2][0])); const __m128i w2 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[2][0]));
const __m128i w3 = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&whitespaces[3][0])); const __m128i w3 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[3][0]));
for (; p <= end - 16; p += 16) { for (; p <= end - 16; p += 16) {
const __m128i s = _mm_loadu_si128(reinterpret_cast<const __m128i*>(p)); const __m128i s = _mm_loadu_si128(reinterpret_cast<const __m128i *>(p));
__m128i x = _mm_cmpeq_epi8(s, w0); __m128i x = _mm_cmpeq_epi8(s, w0);
x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w1)); x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w1));
x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w2)); x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w2));
@ -418,7 +416,7 @@ inline const char* SkipWhitespace_SIMD(const char* p, const char* end) {
#elif defined(RAPIDJSON_NEON) #elif defined(RAPIDJSON_NEON)
//! Skip whitespace with ARM Neon instructions, testing 16 8-byte characters at once. //! Skip whitespace with ARM Neon instructions, testing 16 8-byte characters at once.
inline const char* SkipWhitespace_SIMD(const char* p) { inline const char *SkipWhitespace_SIMD(const char* p) {
// Fast return for single non-whitespace // Fast return for single non-whitespace
if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t') if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
++p; ++p;
@ -439,7 +437,7 @@ inline const char* SkipWhitespace_SIMD(const char* p) {
const uint8x16_t w3 = vmovq_n_u8('\t'); const uint8x16_t w3 = vmovq_n_u8('\t');
for (;; p += 16) { for (;; p += 16) {
const uint8x16_t s = vld1q_u8(reinterpret_cast<const uint8_t*>(p)); const uint8x16_t s = vld1q_u8(reinterpret_cast<const uint8_t *>(p));
uint8x16_t x = vceqq_u8(s, w0); uint8x16_t x = vceqq_u8(s, w0);
x = vorrq_u8(x, vceqq_u8(s, w1)); x = vorrq_u8(x, vceqq_u8(s, w1));
x = vorrq_u8(x, vceqq_u8(s, w2)); x = vorrq_u8(x, vceqq_u8(s, w2));
@ -455,15 +453,14 @@ inline const char* SkipWhitespace_SIMD(const char* p) {
uint32_t lz = internal::clzll(high); uint32_t lz = internal::clzll(high);
return p + 8 + (lz >> 3); return p + 8 + (lz >> 3);
} }
} } else {
else {
uint32_t lz = internal::clzll(low); uint32_t lz = internal::clzll(low);
return p + (lz >> 3); return p + (lz >> 3);
} }
} }
} }
inline const char* SkipWhitespace_SIMD(const char* p, const char* end) { inline const char *SkipWhitespace_SIMD(const char* p, const char* end) {
// Fast return for single non-whitespace // Fast return for single non-whitespace
if (p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')) if (p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t'))
++p; ++p;
@ -476,7 +473,7 @@ inline const char* SkipWhitespace_SIMD(const char* p, const char* end) {
const uint8x16_t w3 = vmovq_n_u8('\t'); const uint8x16_t w3 = vmovq_n_u8('\t');
for (; p <= end - 16; p += 16) { for (; p <= end - 16; p += 16) {
const uint8x16_t s = vld1q_u8(reinterpret_cast<const uint8_t*>(p)); const uint8x16_t s = vld1q_u8(reinterpret_cast<const uint8_t *>(p));
uint8x16_t x = vceqq_u8(s, w0); uint8x16_t x = vceqq_u8(s, w0);
x = vorrq_u8(x, vceqq_u8(s, w1)); x = vorrq_u8(x, vceqq_u8(s, w1));
x = vorrq_u8(x, vceqq_u8(s, w2)); x = vorrq_u8(x, vceqq_u8(s, w2));
@ -492,8 +489,7 @@ inline const char* SkipWhitespace_SIMD(const char* p, const char* end) {
uint32_t lz = internal::clzll(high); uint32_t lz = internal::clzll(high);
return p + 8 + (lz >> 3); return p + 8 + (lz >> 3);
} }
} } else {
else {
uint32_t lz = internal::clzll(low); uint32_t lz = internal::clzll(low);
return p + (lz >> 3); return p + (lz >> 3);
} }
@ -506,19 +502,16 @@ inline const char* SkipWhitespace_SIMD(const char* p, const char* end) {
#ifdef RAPIDJSON_SIMD #ifdef RAPIDJSON_SIMD
//! Template function specialization for InsituStringStream //! Template function specialization for InsituStringStream
template <> template<> inline void SkipWhitespace(InsituStringStream& is) {
inline void SkipWhitespace(InsituStringStream& is) {
is.src_ = const_cast<char*>(SkipWhitespace_SIMD(is.src_)); is.src_ = const_cast<char*>(SkipWhitespace_SIMD(is.src_));
} }
//! Template function specialization for StringStream //! Template function specialization for StringStream
template <> template<> inline void SkipWhitespace(StringStream& is) {
inline void SkipWhitespace(StringStream& is) {
is.src_ = SkipWhitespace_SIMD(is.src_); is.src_ = SkipWhitespace_SIMD(is.src_);
} }
template <> template<> inline void SkipWhitespace(EncodedInputStream<UTF8<>, MemoryStream>& is) {
inline void SkipWhitespace(EncodedInputStream<UTF8<>, MemoryStream>& is) {
is.is_.src_ = SkipWhitespace_SIMD(is.is_.src_, is.is_.end_); is.is_.src_ = SkipWhitespace_SIMD(is.is_.src_, is.is_.end_);
} }
#endif // RAPIDJSON_SIMD #endif // RAPIDJSON_SIMD
@ -551,7 +544,8 @@ public:
/*! \param stackAllocator Optional allocator for allocating stack memory. (Only use for non-destructive parsing) /*! \param stackAllocator Optional allocator for allocating stack memory. (Only use for non-destructive parsing)
\param stackCapacity stack capacity in bytes for storing a single decoded string. (Only use for non-destructive parsing) \param stackCapacity stack capacity in bytes for storing a single decoded string. (Only use for non-destructive parsing)
*/ */
GenericReader(StackAllocator* stackAllocator = 0, size_t stackCapacity = kDefaultStackCapacity) : stack_(stackAllocator, stackCapacity), parseResult_(), state_(IterativeParsingStartState) {} GenericReader(StackAllocator* stackAllocator = 0, size_t stackCapacity = kDefaultStackCapacity) :
stack_(stackAllocator, stackCapacity), parseResult_(), state_(IterativeParsingStartState) {}
//! Parse JSON text. //! Parse JSON text.
/*! \tparam parseFlags Combination of \ref ParseFlag. /*! \tparam parseFlags Combination of \ref ParseFlag.
@ -707,14 +701,13 @@ private:
struct ClearStackOnExit { struct ClearStackOnExit {
explicit ClearStackOnExit(GenericReader& r) : r_(r) {} explicit ClearStackOnExit(GenericReader& r) : r_(r) {}
~ClearStackOnExit() { r_.ClearStack(); } ~ClearStackOnExit() { r_.ClearStack(); }
private: private:
GenericReader& r_; GenericReader& r_;
ClearStackOnExit(const ClearStackOnExit&); ClearStackOnExit(const ClearStackOnExit&);
ClearStackOnExit& operator=(const ClearStackOnExit&); ClearStackOnExit& operator=(const ClearStackOnExit&);
}; };
template <unsigned parseFlags, typename InputStream> template<unsigned parseFlags, typename InputStream>
void SkipWhitespaceAndComments(InputStream& is) { void SkipWhitespaceAndComments(InputStream& is) {
SkipWhitespace(is); SkipWhitespace(is);
@ -743,7 +736,7 @@ private:
} }
// Parse object: { string : value, ... } // Parse object: { string : value, ... }
template <unsigned parseFlags, typename InputStream, typename Handler> template<unsigned parseFlags, typename InputStream, typename Handler>
void ParseObject(InputStream& is, Handler& handler) { void ParseObject(InputStream& is, Handler& handler) {
RAPIDJSON_ASSERT(is.Peek() == '{'); RAPIDJSON_ASSERT(is.Peek() == '{');
is.Take(); // Skip '{' is.Take(); // Skip '{'
@ -796,8 +789,7 @@ private:
RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
return; return;
default: default:
RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell()); RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell()); break; // This useless break is only for making warning and coverage happy
break; // This useless break is only for making warning and coverage happy
} }
if (parseFlags & kParseTrailingCommasFlag) { if (parseFlags & kParseTrailingCommasFlag) {
@ -812,7 +804,7 @@ private:
} }
// Parse array: [ value, ... ] // Parse array: [ value, ... ]
template <unsigned parseFlags, typename InputStream, typename Handler> template<unsigned parseFlags, typename InputStream, typename Handler>
void ParseArray(InputStream& is, Handler& handler) { void ParseArray(InputStream& is, Handler& handler) {
RAPIDJSON_ASSERT(is.Peek() == '['); RAPIDJSON_ASSERT(is.Peek() == '[');
is.Take(); // Skip '[' is.Take(); // Skip '['
@ -860,7 +852,7 @@ private:
} }
} }
template <unsigned parseFlags, typename InputStream, typename Handler> template<unsigned parseFlags, typename InputStream, typename Handler>
void ParseNull(InputStream& is, Handler& handler) { void ParseNull(InputStream& is, Handler& handler) {
RAPIDJSON_ASSERT(is.Peek() == 'n'); RAPIDJSON_ASSERT(is.Peek() == 'n');
is.Take(); is.Take();
@ -873,7 +865,7 @@ private:
RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell()); RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell());
} }
template <unsigned parseFlags, typename InputStream, typename Handler> template<unsigned parseFlags, typename InputStream, typename Handler>
void ParseTrue(InputStream& is, Handler& handler) { void ParseTrue(InputStream& is, Handler& handler) {
RAPIDJSON_ASSERT(is.Peek() == 't'); RAPIDJSON_ASSERT(is.Peek() == 't');
is.Take(); is.Take();
@ -886,7 +878,7 @@ private:
RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell()); RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell());
} }
template <unsigned parseFlags, typename InputStream, typename Handler> template<unsigned parseFlags, typename InputStream, typename Handler>
void ParseFalse(InputStream& is, Handler& handler) { void ParseFalse(InputStream& is, Handler& handler) {
RAPIDJSON_ASSERT(is.Peek() == 'f'); RAPIDJSON_ASSERT(is.Peek() == 'f');
is.Take(); is.Take();
@ -899,7 +891,7 @@ private:
RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell()); RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell());
} }
template <typename InputStream> template<typename InputStream>
RAPIDJSON_FORCEINLINE static bool Consume(InputStream& is, typename InputStream::Ch expect) { RAPIDJSON_FORCEINLINE static bool Consume(InputStream& is, typename InputStream::Ch expect) {
if (RAPIDJSON_LIKELY(is.Peek() == expect)) { if (RAPIDJSON_LIKELY(is.Peek() == expect)) {
is.Take(); is.Take();
@ -910,7 +902,7 @@ private:
} }
// Helper function to parse four hexadecimal digits in \uXXXX in ParseString(). // Helper function to parse four hexadecimal digits in \uXXXX in ParseString().
template <typename InputStream> template<typename InputStream>
unsigned ParseHex4(InputStream& is, size_t escapeOffset) { unsigned ParseHex4(InputStream& is, size_t escapeOffset) {
unsigned codepoint = 0; unsigned codepoint = 0;
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
@ -963,7 +955,7 @@ private:
}; };
// Parse string and generate String event. Different code paths for kParseInsituFlag. // Parse string and generate String event. Different code paths for kParseInsituFlag.
template <unsigned parseFlags, typename InputStream, typename Handler> template<unsigned parseFlags, typename InputStream, typename Handler>
void ParseString(InputStream& is, Handler& handler, bool isKey = false) { void ParseString(InputStream& is, Handler& handler, bool isKey = false) {
internal::StreamLocalCopy<InputStream> copy(is); internal::StreamLocalCopy<InputStream> copy(is);
InputStream& s(copy.s); InputStream& s(copy.s);
@ -973,7 +965,7 @@ private:
bool success = false; bool success = false;
if (parseFlags & kParseInsituFlag) { if (parseFlags & kParseInsituFlag) {
typename InputStream::Ch* head = s.PutBegin(); typename InputStream::Ch *head = s.PutBegin();
ParseStringToStream<parseFlags, SourceEncoding, SourceEncoding>(s, s); ParseStringToStream<parseFlags, SourceEncoding, SourceEncoding>(s, s);
RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
size_t length = s.PutEnd(head) - 1; size_t length = s.PutEnd(head) - 1;
@ -995,19 +987,19 @@ private:
// Parse string to an output is // Parse string to an output is
// This function handles the prefix/suffix double quotes, escaping, and optional encoding validation. // This function handles the prefix/suffix double quotes, escaping, and optional encoding validation.
template <unsigned parseFlags, typename SEncoding, typename TEncoding, typename InputStream, typename OutputStream> template<unsigned parseFlags, typename SEncoding, typename TEncoding, typename InputStream, typename OutputStream>
RAPIDJSON_FORCEINLINE void ParseStringToStream(InputStream& is, OutputStream& os) { RAPIDJSON_FORCEINLINE void ParseStringToStream(InputStream& is, OutputStream& os) {
//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN //!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
#define Z16 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 #define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
static const char escape[256] = { static const char escape[256] = {
Z16, Z16, 0, 0, '\"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '/', Z16, Z16, 0, 0,'\"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '/',
Z16, Z16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '\\', 0, 0, 0, Z16, Z16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0,
0, 0, '\b', 0, 0, 0, '\f', 0, 0, 0, 0, 0, 0, 0, '\n', 0, 0, 0,'\b', 0, 0, 0,'\f', 0, 0, 0, 0, 0, 0, 0,'\n', 0,
0, 0, '\r', 0, '\t', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\r', 0,'\t', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16 Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16
}; };
#undef Z16 #undef Z16
//!@endcond //!@endcond
for (;;) { for (;;) {
// Scan and copy string before "\\\"" or < 0x20. This is an optional optimzation. // Scan and copy string before "\\\"" or < 0x20. This is an optional optimzation.
@ -1044,7 +1036,8 @@ private:
codepoint = (((codepoint - 0xD800) << 10) | (codepoint2 - 0xDC00)) + 0x10000; codepoint = (((codepoint - 0xD800) << 10) | (codepoint2 - 0xDC00)) + 0x10000;
} }
// single low surrogate // single low surrogate
else { else
{
RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, escapeOffset); RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, escapeOffset);
} }
} }
@ -1066,13 +1059,15 @@ private:
} }
else { else {
size_t offset = is.Tell(); size_t offset = is.Tell();
if (RAPIDJSON_UNLIKELY((parseFlags & kParseValidateEncodingFlag ? !Transcoder<SEncoding, TEncoding>::Validate(is, os) : !Transcoder<SEncoding, TEncoding>::Transcode(is, os)))) if (RAPIDJSON_UNLIKELY((parseFlags & kParseValidateEncodingFlag ?
!Transcoder<SEncoding, TEncoding>::Validate(is, os) :
!Transcoder<SEncoding, TEncoding>::Transcode(is, os))))
RAPIDJSON_PARSE_ERROR(kParseErrorStringInvalidEncoding, offset); RAPIDJSON_PARSE_ERROR(kParseErrorStringInvalidEncoding, offset);
} }
} }
} }
template <typename InputStream, typename OutputStream> template<typename InputStream, typename OutputStream>
static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(InputStream&, OutputStream&) { static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(InputStream&, OutputStream&) {
// Do nothing for generic version // Do nothing for generic version
} }
@ -1096,12 +1091,12 @@ private:
static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' }; static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' };
static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' }; static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' };
static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F }; static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F };
const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&dquote[0])); const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0]));
const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&bslash[0])); const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0]));
const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&space[0])); const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0]));
for (;; p += 16) { for (;; p += 16) {
const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i*>(p)); const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
const __m128i t1 = _mm_cmpeq_epi8(s, dq); const __m128i t1 = _mm_cmpeq_epi8(s, dq);
const __m128i t2 = _mm_cmpeq_epi8(s, bs); const __m128i t2 = _mm_cmpeq_epi8(s, bs);
const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F
@ -1109,13 +1104,13 @@ private:
unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x)); unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x));
if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped
SizeType length; SizeType length;
#ifdef _MSC_VER // Find the index of first escaped #ifdef _MSC_VER // Find the index of first escaped
unsigned long offset; unsigned long offset;
_BitScanForward(&offset, r); _BitScanForward(&offset, r);
length = offset; length = offset;
#else #else
length = static_cast<SizeType>(__builtin_ffs(r) - 1); length = static_cast<SizeType>(__builtin_ffs(r) - 1);
#endif #endif
if (length != 0) { if (length != 0) {
char* q = reinterpret_cast<char*>(os.Push(length)); char* q = reinterpret_cast<char*>(os.Push(length));
for (size_t i = 0; i < length; i++) for (size_t i = 0; i < length; i++)
@ -1125,7 +1120,7 @@ private:
} }
break; break;
} }
_mm_storeu_si128(reinterpret_cast<__m128i*>(os.Push(16)), s); _mm_storeu_si128(reinterpret_cast<__m128i *>(os.Push(16)), s);
} }
is.src_ = p; is.src_ = p;
@ -1142,7 +1137,7 @@ private:
} }
char* p = is.src_; char* p = is.src_;
char* q = is.dst_; char *q = is.dst_;
// Scan one by one until alignment (unaligned load may cross page boundary and cause crash) // Scan one by one until alignment (unaligned load may cross page boundary and cause crash)
const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15)); const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
@ -1159,12 +1154,12 @@ private:
static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' }; static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' };
static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' }; static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' };
static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F }; static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F };
const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&dquote[0])); const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0]));
const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&bslash[0])); const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0]));
const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&space[0])); const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0]));
for (;; p += 16, q += 16) { for (;; p += 16, q += 16) {
const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i*>(p)); const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
const __m128i t1 = _mm_cmpeq_epi8(s, dq); const __m128i t1 = _mm_cmpeq_epi8(s, dq);
const __m128i t2 = _mm_cmpeq_epi8(s, bs); const __m128i t2 = _mm_cmpeq_epi8(s, bs);
const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F
@ -1179,11 +1174,11 @@ private:
#else #else
length = static_cast<size_t>(__builtin_ffs(r) - 1); length = static_cast<size_t>(__builtin_ffs(r) - 1);
#endif #endif
for (const char* pend = p + length; p != pend;) for (const char* pend = p + length; p != pend; )
*q++ = *p++; *q++ = *p++;
break; break;
} }
_mm_storeu_si128(reinterpret_cast<__m128i*>(q), s); _mm_storeu_si128(reinterpret_cast<__m128i *>(q), s);
} }
is.src_ = p; is.src_ = p;
@ -1207,12 +1202,12 @@ private:
static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' }; static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' };
static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' }; static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' };
static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F }; static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F };
const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&dquote[0])); const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0]));
const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&bslash[0])); const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0]));
const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&space[0])); const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0]));
for (;; p += 16) { for (;; p += 16) {
const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i*>(p)); const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
const __m128i t1 = _mm_cmpeq_epi8(s, dq); const __m128i t1 = _mm_cmpeq_epi8(s, dq);
const __m128i t2 = _mm_cmpeq_epi8(s, bs); const __m128i t2 = _mm_cmpeq_epi8(s, bs);
const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F
@ -1256,7 +1251,7 @@ private:
const uint8x16_t s3 = vmovq_n_u8(32); const uint8x16_t s3 = vmovq_n_u8(32);
for (;; p += 16) { for (;; p += 16) {
const uint8x16_t s = vld1q_u8(reinterpret_cast<const uint8_t*>(p)); const uint8x16_t s = vld1q_u8(reinterpret_cast<const uint8_t *>(p));
uint8x16_t x = vceqq_u8(s, s0); uint8x16_t x = vceqq_u8(s, s0);
x = vorrq_u8(x, vceqq_u8(s, s1)); x = vorrq_u8(x, vceqq_u8(s, s1));
x = vorrq_u8(x, vceqq_u8(s, s2)); x = vorrq_u8(x, vceqq_u8(s, s2));
@ -1274,8 +1269,7 @@ private:
length = 8 + (lz >> 3); length = 8 + (lz >> 3);
escaped = true; escaped = true;
} }
} } else {
else {
uint32_t lz = internal::clzll(low); uint32_t lz = internal::clzll(low);
length = lz >> 3; length = lz >> 3;
escaped = true; escaped = true;
@ -1290,7 +1284,7 @@ private:
} }
break; break;
} }
vst1q_u8(reinterpret_cast<uint8_t*>(os.Push(16)), s); vst1q_u8(reinterpret_cast<uint8_t *>(os.Push(16)), s);
} }
is.src_ = p; is.src_ = p;
@ -1307,7 +1301,7 @@ private:
} }
char* p = is.src_; char* p = is.src_;
char* q = is.dst_; char *q = is.dst_;
// Scan one by one until alignment (unaligned load may cross page boundary and cause crash) // Scan one by one until alignment (unaligned load may cross page boundary and cause crash)
const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15)); const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
@ -1327,7 +1321,7 @@ private:
const uint8x16_t s3 = vmovq_n_u8(32); const uint8x16_t s3 = vmovq_n_u8(32);
for (;; p += 16, q += 16) { for (;; p += 16, q += 16) {
const uint8x16_t s = vld1q_u8(reinterpret_cast<uint8_t*>(p)); const uint8x16_t s = vld1q_u8(reinterpret_cast<uint8_t *>(p));
uint8x16_t x = vceqq_u8(s, s0); uint8x16_t x = vceqq_u8(s, s0);
x = vorrq_u8(x, vceqq_u8(s, s1)); x = vorrq_u8(x, vceqq_u8(s, s1));
x = vorrq_u8(x, vceqq_u8(s, s2)); x = vorrq_u8(x, vceqq_u8(s, s2));
@ -1345,19 +1339,18 @@ private:
length = 8 + (lz >> 3); length = 8 + (lz >> 3);
escaped = true; escaped = true;
} }
} } else {
else {
uint32_t lz = internal::clzll(low); uint32_t lz = internal::clzll(low);
length = lz >> 3; length = lz >> 3;
escaped = true; escaped = true;
} }
if (RAPIDJSON_UNLIKELY(escaped)) { // some of characters is escaped if (RAPIDJSON_UNLIKELY(escaped)) { // some of characters is escaped
for (const char* pend = p + length; p != pend;) { for (const char* pend = p + length; p != pend; ) {
*q++ = *p++; *q++ = *p++;
} }
break; break;
} }
vst1q_u8(reinterpret_cast<uint8_t*>(q), s); vst1q_u8(reinterpret_cast<uint8_t *>(q), s);
} }
is.src_ = p; is.src_ = p;
@ -1384,7 +1377,7 @@ private:
const uint8x16_t s3 = vmovq_n_u8(32); const uint8x16_t s3 = vmovq_n_u8(32);
for (;; p += 16) { for (;; p += 16) {
const uint8x16_t s = vld1q_u8(reinterpret_cast<uint8_t*>(p)); const uint8x16_t s = vld1q_u8(reinterpret_cast<uint8_t *>(p));
uint8x16_t x = vceqq_u8(s, s0); uint8x16_t x = vceqq_u8(s, s0);
x = vorrq_u8(x, vceqq_u8(s, s1)); x = vorrq_u8(x, vceqq_u8(s, s1));
x = vorrq_u8(x, vceqq_u8(s, s2)); x = vorrq_u8(x, vceqq_u8(s, s2));
@ -1400,8 +1393,7 @@ private:
p += 8 + (lz >> 3); p += 8 + (lz >> 3);
break; break;
} }
} } else {
else {
uint32_t lz = internal::clzll(low); uint32_t lz = internal::clzll(low);
p += lz >> 3; p += lz >> 3;
break; break;
@ -1412,10 +1404,10 @@ private:
} }
#endif // RAPIDJSON_NEON #endif // RAPIDJSON_NEON
template <typename InputStream, bool backup, bool pushOnTake> template<typename InputStream, bool backup, bool pushOnTake>
class NumberStream; class NumberStream;
template <typename InputStream> template<typename InputStream>
class NumberStream<InputStream, false, false> { class NumberStream<InputStream, false, false> {
public: public:
typedef typename InputStream::Ch Ch; typedef typename InputStream::Ch Ch;
@ -1437,10 +1429,9 @@ private:
InputStream& is; InputStream& is;
}; };
template <typename InputStream> template<typename InputStream>
class NumberStream<InputStream, true, false> : public NumberStream<InputStream, false, false> { class NumberStream<InputStream, true, false> : public NumberStream<InputStream, false, false> {
typedef NumberStream<InputStream, false, false> Base; typedef NumberStream<InputStream, false, false> Base;
public: public:
NumberStream(GenericReader& reader, InputStream& is) : Base(reader, is), stackStream(reader.stack_) {} NumberStream(GenericReader& reader, InputStream& is) : Base(reader, is), stackStream(reader.stack_) {}
@ -1464,24 +1455,24 @@ private:
StackStream<char> stackStream; StackStream<char> stackStream;
}; };
template <typename InputStream> template<typename InputStream>
class NumberStream<InputStream, true, true> : public NumberStream<InputStream, true, false> { class NumberStream<InputStream, true, true> : public NumberStream<InputStream, true, false> {
typedef NumberStream<InputStream, true, false> Base; typedef NumberStream<InputStream, true, false> Base;
public: public:
NumberStream(GenericReader& reader, InputStream& is) : Base(reader, is) {} NumberStream(GenericReader& reader, InputStream& is) : Base(reader, is) {}
RAPIDJSON_FORCEINLINE Ch Take() { return Base::TakePush(); } RAPIDJSON_FORCEINLINE Ch Take() { return Base::TakePush(); }
}; };
template <unsigned parseFlags, typename InputStream, typename Handler> template<unsigned parseFlags, typename InputStream, typename Handler>
void ParseNumber(InputStream& is, Handler& handler) { void ParseNumber(InputStream& is, Handler& handler) {
internal::StreamLocalCopy<InputStream> copy(is); internal::StreamLocalCopy<InputStream> copy(is);
NumberStream<InputStream, NumberStream<InputStream,
((parseFlags & kParseNumbersAsStringsFlag) != 0) ? ((parseFlags & kParseInsituFlag) == 0) : ((parseFlags & kParseFullPrecisionFlag) != 0), ((parseFlags & kParseNumbersAsStringsFlag) != 0) ?
((parseFlags & kParseInsituFlag) == 0) :
((parseFlags & kParseFullPrecisionFlag) != 0),
(parseFlags & kParseNumbersAsStringsFlag) != 0 && (parseFlags & kParseNumbersAsStringsFlag) != 0 &&
(parseFlags & kParseInsituFlag) == 0> (parseFlags & kParseInsituFlag) == 0> s(*this, copy.s);
s(*this, copy.s);
size_t startOffset = s.Tell(); size_t startOffset = s.Tell();
double d = 0.0; double d = 0.0;
@ -1540,7 +1531,8 @@ private:
d = (minus ? -std::numeric_limits<double>::infinity() : std::numeric_limits<double>::infinity()); d = (minus ? -std::numeric_limits<double>::infinity() : std::numeric_limits<double>::infinity());
useNanOrInf = true; useNanOrInf = true;
if (RAPIDJSON_UNLIKELY(s.Peek() == 'i' && !(Consume(s, 'i') && Consume(s, 'n') && Consume(s, 'i') && Consume(s, 't') && Consume(s, 'y')))) { if (RAPIDJSON_UNLIKELY(s.Peek() == 'i' && !(Consume(s, 'i') && Consume(s, 'n')
&& Consume(s, 'i') && Consume(s, 't') && Consume(s, 'y')))) {
RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell()); RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell());
} }
} }
@ -1754,30 +1746,19 @@ private:
} }
// Parse any JSON value // Parse any JSON value
template <unsigned parseFlags, typename InputStream, typename Handler> template<unsigned parseFlags, typename InputStream, typename Handler>
void ParseValue(InputStream& is, Handler& handler) { void ParseValue(InputStream& is, Handler& handler) {
switch (is.Peek()) { switch (is.Peek()) {
case 'n': case 'n': ParseNull <parseFlags>(is, handler); break;
ParseNull<parseFlags>(is, handler); case 't': ParseTrue <parseFlags>(is, handler); break;
break; case 'f': ParseFalse <parseFlags>(is, handler); break;
case 't': case '"': ParseString<parseFlags>(is, handler); break;
ParseTrue<parseFlags>(is, handler); case '{': ParseObject<parseFlags>(is, handler); break;
break; case '[': ParseArray <parseFlags>(is, handler); break;
case 'f': default :
ParseFalse<parseFlags>(is, handler);
break;
case '"':
ParseString<parseFlags>(is, handler);
break;
case '{':
ParseObject<parseFlags>(is, handler);
break;
case '[':
ParseArray<parseFlags>(is, handler);
break;
default:
ParseNumber<parseFlags>(is, handler); ParseNumber<parseFlags>(is, handler);
break; break;
} }
} }
@ -1835,7 +1816,7 @@ private:
//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN //!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
#define N NumberToken #define N NumberToken
#define N16 N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N #define N16 N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N
// Maps from ASCII to Token // Maps from ASCII to Token
static const unsigned char tokenMap[256] = { static const unsigned char tokenMap[256] = {
N16, // 00~0F N16, // 00~0F
@ -1850,7 +1831,7 @@ private:
}; };
#undef N #undef N
#undef N16 #undef N16
//!@endcond //!@endcond
if (sizeof(Ch) == 1 || static_cast<unsigned>(c) < 256) if (sizeof(Ch) == 1 || static_cast<unsigned>(c) < 256)
return static_cast<Token>(tokenMap[static_cast<unsigned char>(c)]); return static_cast<Token>(tokenMap[static_cast<unsigned char>(c)]);
@ -1865,12 +1846,14 @@ private:
{ {
IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
IterativeParsingErrorState }, IterativeParsingErrorState
},
// Error(sink state) // Error(sink state)
{ {
IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
IterativeParsingErrorState }, IterativeParsingErrorState
},
// Start // Start
{ {
IterativeParsingArrayInitialState, // Left bracket IterativeParsingArrayInitialState, // Left bracket
@ -1931,7 +1914,8 @@ private:
{ {
IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
IterativeParsingErrorState }, IterativeParsingErrorState
},
// ArrayInitial // ArrayInitial
{ {
IterativeParsingArrayInitialState, // Left bracket(push Element state) IterativeParsingArrayInitialState, // Left bracket(push Element state)
@ -1964,12 +1948,14 @@ private:
{ {
IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
IterativeParsingErrorState }, IterativeParsingErrorState
},
// Single Value (sink state) // Single Value (sink state)
{ {
IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
IterativeParsingErrorState }, IterativeParsingErrorState
},
// ElementDelimiter // ElementDelimiter
{ {
IterativeParsingArrayInitialState, // Left bracket(push Element state) IterativeParsingArrayInitialState, // Left bracket(push Element state)
@ -2028,7 +2014,8 @@ private:
return dst; return dst;
case IterativeParsingObjectInitialState: case IterativeParsingObjectInitialState:
case IterativeParsingArrayInitialState: { case IterativeParsingArrayInitialState:
{
// Push the state(Element or MemeberValue) if we are nested in another array or value of member. // Push the state(Element or MemeberValue) if we are nested in another array or value of member.
// In this way we can get the correct state on ObjectFinish or ArrayFinish by frame pop. // In this way we can get the correct state on ObjectFinish or ArrayFinish by frame pop.
IterativeParsingState n = src; IterativeParsingState n = src;
@ -2088,7 +2075,8 @@ private:
*stack_.template Top<SizeType>() = *stack_.template Top<SizeType>() + 1; *stack_.template Top<SizeType>() = *stack_.template Top<SizeType>() + 1;
return dst; return dst;
case IterativeParsingObjectFinishState: { case IterativeParsingObjectFinishState:
{
// Transit from delimiter is only allowed when trailing commas are enabled // Transit from delimiter is only allowed when trailing commas are enabled
if (!(parseFlags & kParseTrailingCommasFlag) && src == IterativeParsingMemberDelimiterState) { if (!(parseFlags & kParseTrailingCommasFlag) && src == IterativeParsingMemberDelimiterState) {
RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorObjectMissName, is.Tell()); RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorObjectMissName, is.Tell());
@ -2117,7 +2105,8 @@ private:
} }
} }
case IterativeParsingArrayFinishState: { case IterativeParsingArrayFinishState:
{
// Transit from delimiter is only allowed when trailing commas are enabled // Transit from delimiter is only allowed when trailing commas are enabled
if (!(parseFlags & kParseTrailingCommasFlag) && src == IterativeParsingElementDelimiterState) { if (!(parseFlags & kParseTrailingCommasFlag) && src == IterativeParsingElementDelimiterState) {
RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorValueInvalid, is.Tell()); RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorValueInvalid, is.Tell());
@ -2176,31 +2165,16 @@ private:
} }
switch (src) { switch (src) {
case IterativeParsingStartState: case IterativeParsingStartState: RAPIDJSON_PARSE_ERROR(kParseErrorDocumentEmpty, is.Tell()); return;
RAPIDJSON_PARSE_ERROR(kParseErrorDocumentEmpty, is.Tell()); case IterativeParsingFinishState: RAPIDJSON_PARSE_ERROR(kParseErrorDocumentRootNotSingular, is.Tell()); return;
return;
case IterativeParsingFinishState:
RAPIDJSON_PARSE_ERROR(kParseErrorDocumentRootNotSingular, is.Tell());
return;
case IterativeParsingObjectInitialState: case IterativeParsingObjectInitialState:
case IterativeParsingMemberDelimiterState: case IterativeParsingMemberDelimiterState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissName, is.Tell()); return;
RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissName, is.Tell()); case IterativeParsingMemberKeyState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissColon, is.Tell()); return;
return; case IterativeParsingMemberValueState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell()); return;
case IterativeParsingMemberKeyState:
RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissColon, is.Tell());
return;
case IterativeParsingMemberValueState:
RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell());
return;
case IterativeParsingKeyValueDelimiterState: case IterativeParsingKeyValueDelimiterState:
case IterativeParsingArrayInitialState: case IterativeParsingArrayInitialState:
case IterativeParsingElementDelimiterState: case IterativeParsingElementDelimiterState: RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell()); return;
RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell()); default: RAPIDJSON_ASSERT(src == IterativeParsingElementState); RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell()); return;
return;
default:
RAPIDJSON_ASSERT(src == IterativeParsingElementState);
RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell());
return;
} }
} }
@ -2254,7 +2228,7 @@ private:
}; // class GenericReader }; // class GenericReader
//! Reader with UTF8 encoding and default allocator. //! Reader with UTF8 encoding and default allocator.
typedef GenericReader<UTF8<>, UTF8<>> Reader; typedef GenericReader<UTF8<>, UTF8<> > Reader;
RAPIDJSON_NAMESPACE_END RAPIDJSON_NAMESPACE_END

View File

@ -27,7 +27,7 @@
#define RAPIDJSON_SCHEMA_USE_INTERNALREGEX 0 #define RAPIDJSON_SCHEMA_USE_INTERNALREGEX 0
#endif #endif
#if !RAPIDJSON_SCHEMA_USE_INTERNALREGEX && defined(RAPIDJSON_SCHEMA_USE_STDREGEX) && (__cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)) #if !RAPIDJSON_SCHEMA_USE_INTERNALREGEX && defined(RAPIDJSON_SCHEMA_USE_STDREGEX) && (__cplusplus >=201103L || (defined(_MSC_VER) && _MSC_VER >= 1800))
#define RAPIDJSON_SCHEMA_USE_STDREGEX 1 #define RAPIDJSON_SCHEMA_USE_STDREGEX 1
#else #else
#define RAPIDJSON_SCHEMA_USE_STDREGEX 0 #define RAPIDJSON_SCHEMA_USE_STDREGEX 0
@ -60,10 +60,10 @@ RAPIDJSON_DIAG_OFF(effc++)
#endif #endif
#ifdef __clang__ #ifdef __clang__
RAPIDJSON_DIAG_OFF(weak - vtables) RAPIDJSON_DIAG_OFF(weak-vtables)
RAPIDJSON_DIAG_OFF(exit - time - destructors) RAPIDJSON_DIAG_OFF(exit-time-destructors)
RAPIDJSON_DIAG_OFF(c++ 98 - compat - pedantic) RAPIDJSON_DIAG_OFF(c++98-compat-pedantic)
RAPIDJSON_DIAG_OFF(variadic - macros) RAPIDJSON_DIAG_OFF(variadic-macros)
#elif defined(_MSC_VER) #elif defined(_MSC_VER)
RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
#endif #endif
@ -77,29 +77,29 @@ RAPIDJSON_NAMESPACE_BEGIN
namespace internal { namespace internal {
inline void PrintInvalidKeyword(const char* keyword) { inline void PrintInvalidKeyword(const char* keyword) {
printf("Fail keyword: %s\n", keyword); printf("Fail keyword: %s\n", keyword);
} }
inline void PrintInvalidKeyword(const wchar_t* keyword) { inline void PrintInvalidKeyword(const wchar_t* keyword) {
wprintf(L"Fail keyword: %ls\n", keyword); wprintf(L"Fail keyword: %ls\n", keyword);
} }
inline void PrintInvalidDocument(const char* document) { inline void PrintInvalidDocument(const char* document) {
printf("Fail document: %s\n\n", document); printf("Fail document: %s\n\n", document);
} }
inline void PrintInvalidDocument(const wchar_t* document) { inline void PrintInvalidDocument(const wchar_t* document) {
wprintf(L"Fail document: %ls\n\n", document); wprintf(L"Fail document: %ls\n\n", document);
} }
inline void PrintValidatorPointers(unsigned depth, const char* s, const char* d) { inline void PrintValidatorPointers(unsigned depth, const char* s, const char* d) {
printf("S: %*s%s\nD: %*s%s\n\n", depth * 4, " ", s, depth * 4, " ", d); printf("S: %*s%s\nD: %*s%s\n\n", depth * 4, " ", s, depth * 4, " ", d);
} }
inline void PrintValidatorPointers(unsigned depth, const wchar_t* s, const wchar_t* d) { inline void PrintValidatorPointers(unsigned depth, const wchar_t* s, const wchar_t* d) {
wprintf(L"S: %*ls%ls\nD: %*ls%ls\n\n", depth * 4, L" ", s, depth * 4, L" ", d); wprintf(L"S: %*ls%ls\nD: %*ls%ls\n\n", depth * 4, L" ", s, depth * 4, L" ", d);
} }
} // namespace internal } // namespace internal
@ -114,13 +114,13 @@ namespace internal {
#define RAPIDJSON_INVALID_KEYWORD_VERBOSE(keyword) #define RAPIDJSON_INVALID_KEYWORD_VERBOSE(keyword)
#endif #endif
#define RAPIDJSON_INVALID_KEYWORD_RETURN(code) \ #define RAPIDJSON_INVALID_KEYWORD_RETURN(code)\
RAPIDJSON_MULTILINEMACRO_BEGIN \ RAPIDJSON_MULTILINEMACRO_BEGIN\
context.invalidCode = code; \ context.invalidCode = code;\
context.invalidKeyword = SchemaType::GetValidateErrorKeyword(code).GetString(); \ context.invalidKeyword = SchemaType::GetValidateErrorKeyword(code).GetString();\
RAPIDJSON_INVALID_KEYWORD_VERBOSE(context.invalidKeyword); \ RAPIDJSON_INVALID_KEYWORD_VERBOSE(context.invalidKeyword);\
return false; \ return false;\
RAPIDJSON_MULTILINEMACRO_END RAPIDJSON_MULTILINEMACRO_END
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// ValidateFlag // ValidateFlag
@ -152,26 +152,26 @@ class GenericSchemaDocument;
namespace internal { namespace internal {
template <typename SchemaDocumentType> template <typename SchemaDocumentType>
class Schema; class Schema;
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// ISchemaValidator // ISchemaValidator
class ISchemaValidator { class ISchemaValidator {
public: public:
virtual ~ISchemaValidator() {} virtual ~ISchemaValidator() {}
virtual bool IsValid() const = 0; virtual bool IsValid() const = 0;
virtual void SetValidateFlags(unsigned flags) = 0; virtual void SetValidateFlags(unsigned flags) = 0;
virtual unsigned GetValidateFlags() const = 0; virtual unsigned GetValidateFlags() const = 0;
}; };
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// ISchemaStateFactory // ISchemaStateFactory
template <typename SchemaType> template <typename SchemaType>
class ISchemaStateFactory { class ISchemaStateFactory {
public: public:
virtual ~ISchemaStateFactory() {} virtual ~ISchemaStateFactory() {}
virtual ISchemaValidator* CreateSchemaValidator(const SchemaType&, const bool inheritContinueOnErrors) = 0; virtual ISchemaValidator* CreateSchemaValidator(const SchemaType&, const bool inheritContinueOnErrors) = 0;
virtual void DestroySchemaValidator(ISchemaValidator* validator) = 0; virtual void DestroySchemaValidator(ISchemaValidator* validator) = 0;
@ -180,14 +180,14 @@ namespace internal {
virtual void DestroryHasher(void* hasher) = 0; virtual void DestroryHasher(void* hasher) = 0;
virtual void* MallocState(size_t size) = 0; virtual void* MallocState(size_t size) = 0;
virtual void FreeState(void* p) = 0; virtual void FreeState(void* p) = 0;
}; };
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// IValidationErrorHandler // IValidationErrorHandler
template <typename SchemaType> template <typename SchemaType>
class IValidationErrorHandler { class IValidationErrorHandler {
public: public:
typedef typename SchemaType::Ch Ch; typedef typename SchemaType::Ch Ch;
typedef typename SchemaType::SValue SValue; typedef typename SchemaType::SValue SValue;
@ -235,52 +235,30 @@ namespace internal {
virtual void NoneOf(ISchemaValidator** subvalidators, SizeType count) = 0; virtual void NoneOf(ISchemaValidator** subvalidators, SizeType count) = 0;
virtual void NotOneOf(ISchemaValidator** subvalidators, SizeType count, bool matched) = 0; virtual void NotOneOf(ISchemaValidator** subvalidators, SizeType count, bool matched) = 0;
virtual void Disallowed() = 0; virtual void Disallowed() = 0;
}; };
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// Hasher // Hasher
// For comparison of compound value // For comparison of compound value
template <typename Encoding, typename Allocator> template<typename Encoding, typename Allocator>
class Hasher { class Hasher {
public: public:
typedef typename Encoding::Ch Ch; typedef typename Encoding::Ch Ch;
Hasher(Allocator* allocator = 0, size_t stackCapacity = kDefaultSize) : stack_(allocator, stackCapacity) {} Hasher(Allocator* allocator = 0, size_t stackCapacity = kDefaultSize) : stack_(allocator, stackCapacity) {}
bool Null() { return WriteType(kNullType); } bool Null() { return WriteType(kNullType); }
bool Bool(bool b) { return WriteType(b ? kTrueType : kFalseType); } bool Bool(bool b) { return WriteType(b ? kTrueType : kFalseType); }
bool Int(int i) { bool Int(int i) { Number n; n.u.i = i; n.d = static_cast<double>(i); return WriteNumber(n); }
Number n; bool Uint(unsigned u) { Number n; n.u.u = u; n.d = static_cast<double>(u); return WriteNumber(n); }
n.u.i = i; bool Int64(int64_t i) { Number n; n.u.i = i; n.d = static_cast<double>(i); return WriteNumber(n); }
n.d = static_cast<double>(i); bool Uint64(uint64_t u) { Number n; n.u.u = u; n.d = static_cast<double>(u); return WriteNumber(n); }
return WriteNumber(n);
}
bool Uint(unsigned u) {
Number n;
n.u.u = u;
n.d = static_cast<double>(u);
return WriteNumber(n);
}
bool Int64(int64_t i) {
Number n;
n.u.i = i;
n.d = static_cast<double>(i);
return WriteNumber(n);
}
bool Uint64(uint64_t u) {
Number n;
n.u.u = u;
n.d = static_cast<double>(u);
return WriteNumber(n);
}
bool Double(double d) { bool Double(double d) {
Number n; Number n;
if (d < 0) if (d < 0) n.u.i = static_cast<int64_t>(d);
n.u.i = static_cast<int64_t>(d); else n.u.u = static_cast<uint64_t>(d);
else
n.u.u = static_cast<uint64_t>(d);
n.d = d; n.d = d;
return WriteNumber(n); return WriteNumber(n);
} }
@ -323,13 +301,13 @@ namespace internal {
return *stack_.template Top<uint64_t>(); return *stack_.template Top<uint64_t>();
} }
private: private:
static const size_t kDefaultSize = 256; static const size_t kDefaultSize = 256;
struct Number { struct Number {
union U { union U {
uint64_t u; uint64_t u;
int64_t i; int64_t i;
} u; }u;
double d; double d;
}; };
@ -355,13 +333,13 @@ namespace internal {
} }
Stack<Allocator> stack_; Stack<Allocator> stack_;
}; };
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// SchemaValidationContext // SchemaValidationContext
template <typename SchemaDocumentType> template <typename SchemaDocumentType>
struct SchemaValidationContext { struct SchemaValidationContext {
typedef Schema<SchemaDocumentType> SchemaType; typedef Schema<SchemaDocumentType> SchemaType;
typedef ISchemaStateFactory<SchemaType> SchemaValidatorFactoryType; typedef ISchemaStateFactory<SchemaType> SchemaValidatorFactoryType;
typedef IValidationErrorHandler<SchemaType> ErrorHandlerType; typedef IValidationErrorHandler<SchemaType> ErrorHandlerType;
@ -374,7 +352,8 @@ namespace internal {
kPatternValidatorWithAdditionalProperty kPatternValidatorWithAdditionalProperty
}; };
SchemaValidationContext(SchemaValidatorFactoryType& f, ErrorHandlerType& eh, const SchemaType* s) : factory(f), SchemaValidationContext(SchemaValidatorFactoryType& f, ErrorHandlerType& eh, const SchemaType* s) :
factory(f),
error_handler(eh), error_handler(eh),
schema(s), schema(s),
valueSchema(), valueSchema(),
@ -392,7 +371,8 @@ namespace internal {
propertyExist(), propertyExist(),
inArray(false), inArray(false),
valueUniqueness(false), valueUniqueness(false),
arrayUniqueness(false) { arrayUniqueness(false)
{
} }
~SchemaValidationContext() { ~SchemaValidationContext() {
@ -435,14 +415,14 @@ namespace internal {
bool inArray; bool inArray;
bool valueUniqueness; bool valueUniqueness;
bool arrayUniqueness; bool arrayUniqueness;
}; };
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// Schema // Schema
template <typename SchemaDocumentType> template <typename SchemaDocumentType>
class Schema { class Schema {
public: public:
typedef typename SchemaDocumentType::ValueType ValueType; typedef typename SchemaDocumentType::ValueType ValueType;
typedef typename SchemaDocumentType::AllocatorType AllocatorType; typedef typename SchemaDocumentType::AllocatorType AllocatorType;
typedef typename SchemaDocumentType::PointerType PointerType; typedef typename SchemaDocumentType::PointerType PointerType;
@ -454,7 +434,8 @@ namespace internal {
typedef IValidationErrorHandler<Schema> ErrorHandler; typedef IValidationErrorHandler<Schema> ErrorHandler;
friend class GenericSchemaDocument<ValueType, AllocatorType>; friend class GenericSchemaDocument<ValueType, AllocatorType>;
Schema(SchemaDocumentType* schemaDocument, const PointerType& p, const ValueType& value, const ValueType& document, AllocatorType* allocator) : allocator_(allocator), Schema(SchemaDocumentType* schemaDocument, const PointerType& p, const ValueType& value, const ValueType& document, AllocatorType* allocator) :
allocator_(allocator),
uri_(schemaDocument->GetURI(), *allocator), uri_(schemaDocument->GetURI(), *allocator),
pointer_(p, allocator), pointer_(p, allocator),
typeless_(schemaDocument->GetTypeless()), typeless_(schemaDocument->GetTypeless()),
@ -488,7 +469,8 @@ namespace internal {
maxLength_(~SizeType(0)), maxLength_(~SizeType(0)),
exclusiveMinimum_(false), exclusiveMinimum_(false),
exclusiveMaximum_(false), exclusiveMaximum_(false),
defaultValueLength_(0) { defaultValueLength_(0)
{
typedef typename ValueType::ConstValueIterator ConstValueIterator; typedef typename ValueType::ConstValueIterator ConstValueIterator;
typedef typename ValueType::ConstMemberIterator ConstMemberIterator; typedef typename ValueType::ConstMemberIterator ConstMemberIterator;
@ -508,7 +490,7 @@ namespace internal {
if (v->IsArray() && v->Size() > 0) { if (v->IsArray() && v->Size() > 0) {
enum_ = static_cast<uint64_t*>(allocator_->Malloc(sizeof(uint64_t) * v->Size())); enum_ = static_cast<uint64_t*>(allocator_->Malloc(sizeof(uint64_t) * v->Size()));
for (ConstValueIterator itr = v->Begin(); itr != v->End(); ++itr) { for (ConstValueIterator itr = v->Begin(); itr != v->End(); ++itr) {
typedef Hasher<EncodingType, MemoryPoolAllocator<>> EnumHasherType; typedef Hasher<EncodingType, MemoryPoolAllocator<> > EnumHasherType;
char buffer[256u + 24]; char buffer[256u + 24];
MemoryPoolAllocator<> hasherAllocator(buffer, sizeof(buffer)); MemoryPoolAllocator<> hasherAllocator(buffer, sizeof(buffer));
EnumHasherType h(&hasherAllocator, 256); EnumHasherType h(&hasherAllocator, 256);
@ -608,7 +590,7 @@ namespace internal {
if (FindPropertyIndex(itr->name, &sourceIndex)) { if (FindPropertyIndex(itr->name, &sourceIndex)) {
if (itr->value.IsArray()) { if (itr->value.IsArray()) {
properties_[sourceIndex].dependencies = static_cast<bool*>(allocator_->Malloc(sizeof(bool) * propertyCount_)); properties_[sourceIndex].dependencies = static_cast<bool*>(allocator_->Malloc(sizeof(bool) * propertyCount_));
std::memset(properties_[sourceIndex].dependencies, 0, sizeof(bool) * propertyCount_); std::memset(properties_[sourceIndex].dependencies, 0, sizeof(bool)* propertyCount_);
for (ConstValueIterator targetItr = itr->value.Begin(); targetItr != itr->value.End(); ++targetItr) { for (ConstValueIterator targetItr = itr->value.Begin(); targetItr != itr->value.End(); ++targetItr) {
SizeType targetIndex; SizeType targetIndex;
if (FindPropertyIndex(*targetItr, &targetIndex)) if (FindPropertyIndex(*targetItr, &targetIndex))
@ -687,6 +669,7 @@ namespace internal {
if (const ValueType* v = GetMember(value, GetDefaultValueString())) if (const ValueType* v = GetMember(value, GetDefaultValueString()))
if (v->IsString()) if (v->IsString())
defaultValueLength_ = v->GetStringLength(); defaultValueLength_ = v->GetStringLength();
} }
~Schema() { ~Schema() {
@ -818,8 +801,7 @@ namespace internal {
if (oneValid) { if (oneValid) {
context.error_handler.NotOneOf(&context.validators[oneOf_.begin], oneOf_.count, true); context.error_handler.NotOneOf(&context.validators[oneOf_.begin], oneOf_.count, true);
RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorOneOfMatch); RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorOneOfMatch);
} } else
else
oneValid = true; oneValid = true;
} }
if (!oneValid) { if (!oneValid) {
@ -1000,7 +982,7 @@ namespace internal {
context.error_handler.StartMissingProperties(); context.error_handler.StartMissingProperties();
for (SizeType index = 0; index < propertyCount_; index++) for (SizeType index = 0; index < propertyCount_; index++)
if (properties_[index].required && !context.propertyExist[index]) if (properties_[index].required && !context.propertyExist[index])
if (properties_[index].schema->defaultValueLength_ == 0) if (properties_[index].schema->defaultValueLength_ == 0 )
context.error_handler.AddMissingProperty(properties_[index].name); context.error_handler.AddMissingProperty(properties_[index].name);
if (context.error_handler.EndMissingProperties()) if (context.error_handler.EndMissingProperties())
RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorRequired); RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorRequired);
@ -1072,74 +1054,48 @@ namespace internal {
static const ValueType& GetValidateErrorKeyword(ValidateErrorCode validateErrorCode) { static const ValueType& GetValidateErrorKeyword(ValidateErrorCode validateErrorCode) {
switch (validateErrorCode) { switch (validateErrorCode) {
case kValidateErrorMultipleOf: case kValidateErrorMultipleOf: return GetMultipleOfString();
return GetMultipleOfString(); case kValidateErrorMaximum: return GetMaximumString();
case kValidateErrorMaximum: case kValidateErrorExclusiveMaximum: return GetMaximumString(); // Same
return GetMaximumString(); case kValidateErrorMinimum: return GetMinimumString();
case kValidateErrorExclusiveMaximum: case kValidateErrorExclusiveMinimum: return GetMinimumString(); // Same
return GetMaximumString(); // Same
case kValidateErrorMinimum:
return GetMinimumString();
case kValidateErrorExclusiveMinimum:
return GetMinimumString(); // Same
case kValidateErrorMaxLength: case kValidateErrorMaxLength: return GetMaxLengthString();
return GetMaxLengthString(); case kValidateErrorMinLength: return GetMinLengthString();
case kValidateErrorMinLength: case kValidateErrorPattern: return GetPatternString();
return GetMinLengthString();
case kValidateErrorPattern:
return GetPatternString();
case kValidateErrorMaxItems: case kValidateErrorMaxItems: return GetMaxItemsString();
return GetMaxItemsString(); case kValidateErrorMinItems: return GetMinItemsString();
case kValidateErrorMinItems: case kValidateErrorUniqueItems: return GetUniqueItemsString();
return GetMinItemsString(); case kValidateErrorAdditionalItems: return GetAdditionalItemsString();
case kValidateErrorUniqueItems:
return GetUniqueItemsString();
case kValidateErrorAdditionalItems:
return GetAdditionalItemsString();
case kValidateErrorMaxProperties: case kValidateErrorMaxProperties: return GetMaxPropertiesString();
return GetMaxPropertiesString(); case kValidateErrorMinProperties: return GetMinPropertiesString();
case kValidateErrorMinProperties: case kValidateErrorRequired: return GetRequiredString();
return GetMinPropertiesString(); case kValidateErrorAdditionalProperties: return GetAdditionalPropertiesString();
case kValidateErrorRequired: case kValidateErrorPatternProperties: return GetPatternPropertiesString();
return GetRequiredString(); case kValidateErrorDependencies: return GetDependenciesString();
case kValidateErrorAdditionalProperties:
return GetAdditionalPropertiesString();
case kValidateErrorPatternProperties:
return GetPatternPropertiesString();
case kValidateErrorDependencies:
return GetDependenciesString();
case kValidateErrorEnum: case kValidateErrorEnum: return GetEnumString();
return GetEnumString(); case kValidateErrorType: return GetTypeString();
case kValidateErrorType:
return GetTypeString();
case kValidateErrorOneOf: case kValidateErrorOneOf: return GetOneOfString();
return GetOneOfString(); case kValidateErrorOneOfMatch: return GetOneOfString(); // Same
case kValidateErrorOneOfMatch: case kValidateErrorAllOf: return GetAllOfString();
return GetOneOfString(); // Same case kValidateErrorAnyOf: return GetAnyOfString();
case kValidateErrorAllOf: case kValidateErrorNot: return GetNotString();
return GetAllOfString();
case kValidateErrorAnyOf:
return GetAnyOfString();
case kValidateErrorNot:
return GetNotString();
default: default: return GetNullString();
return GetNullString();
} }
} }
// Generate functions for string literal according to Ch // Generate functions for string literal according to Ch
#define RAPIDJSON_STRING_(name, ...) \ #define RAPIDJSON_STRING_(name, ...) \
static const ValueType& Get##name##String() { \ static const ValueType& Get##name##String() {\
static const Ch s[] = { __VA_ARGS__, '\0' }; \ static const Ch s[] = { __VA_ARGS__, '\0' };\
static const ValueType v(s, static_cast<SizeType>(sizeof(s) / sizeof(Ch) - 1)); \ static const ValueType v(s, static_cast<SizeType>(sizeof(s) / sizeof(Ch) - 1));\
return v; \ return v;\
} }
RAPIDJSON_STRING_(Null, 'n', 'u', 'l', 'l') RAPIDJSON_STRING_(Null, 'n', 'u', 'l', 'l')
@ -1179,7 +1135,7 @@ namespace internal {
#undef RAPIDJSON_STRING_ #undef RAPIDJSON_STRING_
private: private:
enum SchemaValueType { enum SchemaValueType {
kNullSchemaType, kNullSchemaType,
kBooleanSchemaType, kBooleanSchemaType,
@ -1239,7 +1195,7 @@ namespace internal {
PointerType q = p.Append(name, allocator_); PointerType q = p.Append(name, allocator_);
out.count = v->Size(); out.count = v->Size();
out.schemas = static_cast<const Schema**>(allocator_->Malloc(out.count * sizeof(const Schema*))); out.schemas = static_cast<const Schema**>(allocator_->Malloc(out.count * sizeof(const Schema*)));
memset(out.schemas, 0, sizeof(Schema*) * out.count); memset(out.schemas, 0, sizeof(Schema*)* out.count);
for (SizeType i = 0; i < out.count; i++) for (SizeType i = 0; i < out.count; i++)
schemaDocument.CreateSchema(&out.schemas[i], q.Append(i, allocator_), (*v)[i], document); schemaDocument.CreateSchema(&out.schemas[i], q.Append(i, allocator_), (*v)[i], document);
out.begin = validatorCount_; out.begin = validatorCount_;
@ -1263,7 +1219,7 @@ namespace internal {
return 0; return 0;
} }
static bool IsPatternMatch(const RegexType* pattern, const Ch* str, SizeType) { static bool IsPatternMatch(const RegexType* pattern, const Ch *str, SizeType) {
GenericRegexSearch<RegexType> rs(*pattern); GenericRegexSearch<RegexType> rs(*pattern);
return rs.Search(str); return rs.Search(str);
} }
@ -1271,7 +1227,7 @@ namespace internal {
template <typename ValueType> template <typename ValueType>
RegexType* CreatePattern(const ValueType& value) { RegexType* CreatePattern(const ValueType& value) {
if (value.IsString()) { if (value.IsString()) {
RegexType* r = static_cast<RegexType*>(allocator_->Malloc(sizeof(RegexType))); RegexType *r = static_cast<RegexType*>(allocator_->Malloc(sizeof(RegexType)));
try { try {
return new (r) RegexType(value.GetString(), std::size_t(value.GetStringLength()), std::regex_constants::ECMAScript); return new (r) RegexType(value.GetString(), std::size_t(value.GetStringLength()), std::regex_constants::ECMAScript);
} }
@ -1282,7 +1238,7 @@ namespace internal {
return 0; return 0;
} }
static bool IsPatternMatch(const RegexType* pattern, const Ch* str, SizeType length) { static bool IsPatternMatch(const RegexType* pattern, const Ch *str, SizeType length) {
std::match_results<const Ch*> r; std::match_results<const Ch*> r;
return std::regex_search(str, str + length, r, *pattern); return std::regex_search(str, str + length, r, *pattern);
} }
@ -1290,24 +1246,17 @@ namespace internal {
template <typename ValueType> template <typename ValueType>
RegexType* CreatePattern(const ValueType&) { return 0; } RegexType* CreatePattern(const ValueType&) { return 0; }
static bool IsPatternMatch(const RegexType*, const Ch*, SizeType) { return true; } static bool IsPatternMatch(const RegexType*, const Ch *, SizeType) { return true; }
#endif // RAPIDJSON_SCHEMA_USE_STDREGEX #endif // RAPIDJSON_SCHEMA_USE_STDREGEX
void AddType(const ValueType& type) { void AddType(const ValueType& type) {
if (type == GetNullString()) if (type == GetNullString() ) type_ |= 1 << kNullSchemaType;
type_ |= 1 << kNullSchemaType; else if (type == GetBooleanString()) type_ |= 1 << kBooleanSchemaType;
else if (type == GetBooleanString()) else if (type == GetObjectString() ) type_ |= 1 << kObjectSchemaType;
type_ |= 1 << kBooleanSchemaType; else if (type == GetArrayString() ) type_ |= 1 << kArraySchemaType;
else if (type == GetObjectString()) else if (type == GetStringString() ) type_ |= 1 << kStringSchemaType;
type_ |= 1 << kObjectSchemaType; else if (type == GetIntegerString()) type_ |= 1 << kIntegerSchemaType;
else if (type == GetArrayString()) else if (type == GetNumberString() ) type_ |= (1 << kNumberSchemaType) | (1 << kIntegerSchemaType);
type_ |= 1 << kArraySchemaType;
else if (type == GetStringString())
type_ |= 1 << kStringSchemaType;
else if (type == GetIntegerString())
type_ |= 1 << kIntegerSchemaType;
else if (type == GetNumberString())
type_ |= (1 << kNumberSchemaType) | (1 << kIntegerSchemaType);
} }
bool CreateParallelValidator(Context& context) const { bool CreateParallelValidator(Context& context) const {
@ -1353,7 +1302,8 @@ namespace internal {
const Ch* str = name.GetString(); const Ch* str = name.GetString();
for (SizeType index = 0; index < propertyCount_; index++) for (SizeType index = 0; index < propertyCount_; index++)
if (properties_[index].name.GetStringLength() == len && if (properties_[index].name.GetStringLength() == len &&
(std::memcmp(properties_[index].name.GetString(), str, sizeof(Ch) * len) == 0)) { (std::memcmp(properties_[index].name.GetString(), str, sizeof(Ch) * len) == 0))
{
*outIndex = index; *outIndex = index;
return true; return true;
} }
@ -1388,8 +1338,7 @@ namespace internal {
RAPIDJSON_INVALID_KEYWORD_RETURN(exclusiveMaximum_ ? kValidateErrorExclusiveMaximum : kValidateErrorMaximum); RAPIDJSON_INVALID_KEYWORD_RETURN(exclusiveMaximum_ ? kValidateErrorExclusiveMaximum : kValidateErrorMaximum);
} }
} }
else if (maximum_.IsUint64()) { else if (maximum_.IsUint64()) { }
}
/* do nothing */ // i <= max(int64_t) < maximum_.GetUint64() /* do nothing */ // i <= max(int64_t) < maximum_.GetUint64()
else if (!CheckDoubleMaximum(context, static_cast<double>(i))) else if (!CheckDoubleMaximum(context, static_cast<double>(i)))
return false; return false;
@ -1494,10 +1443,8 @@ namespace internal {
if (type_ & (1 << kArraySchemaType)) eh.AddExpectedType(GetArrayString()); if (type_ & (1 << kArraySchemaType)) eh.AddExpectedType(GetArrayString());
if (type_ & (1 << kStringSchemaType)) eh.AddExpectedType(GetStringString()); if (type_ & (1 << kStringSchemaType)) eh.AddExpectedType(GetStringString());
if (type_ & (1 << kNumberSchemaType)) if (type_ & (1 << kNumberSchemaType)) eh.AddExpectedType(GetNumberString());
eh.AddExpectedType(GetNumberString()); else if (type_ & (1 << kIntegerSchemaType)) eh.AddExpectedType(GetIntegerString());
else if (type_ & (1 << kIntegerSchemaType))
eh.AddExpectedType(GetIntegerString());
eh.EndDisallowedType(actualType); eh.EndDisallowedType(actualType);
} }
@ -1571,10 +1518,10 @@ namespace internal {
bool exclusiveMaximum_; bool exclusiveMaximum_;
SizeType defaultValueLength_; SizeType defaultValueLength_;
}; };
template <typename Stack, typename Ch> template<typename Stack, typename Ch>
struct TokenHelper { struct TokenHelper {
RAPIDJSON_FORCEINLINE static void AppendIndexToken(Stack& documentStack, SizeType index) { RAPIDJSON_FORCEINLINE static void AppendIndexToken(Stack& documentStack, SizeType index) {
*documentStack.template Push<Ch>() = '/'; *documentStack.template Push<Ch>() = '/';
char buffer[21]; char buffer[21];
@ -1582,26 +1529,26 @@ namespace internal {
for (size_t i = 0; i < length; i++) for (size_t i = 0; i < length; i++)
*documentStack.template Push<Ch>() = static_cast<Ch>(buffer[i]); *documentStack.template Push<Ch>() = static_cast<Ch>(buffer[i]);
} }
}; };
// Partial specialized version for char to prevent buffer copying. // Partial specialized version for char to prevent buffer copying.
template <typename Stack> template <typename Stack>
struct TokenHelper<Stack, char> { struct TokenHelper<Stack, char> {
RAPIDJSON_FORCEINLINE static void AppendIndexToken(Stack& documentStack, SizeType index) { RAPIDJSON_FORCEINLINE static void AppendIndexToken(Stack& documentStack, SizeType index) {
if (sizeof(SizeType) == 4) { if (sizeof(SizeType) == 4) {
char* buffer = documentStack.template Push<char>(1 + 10); // '/' + uint char *buffer = documentStack.template Push<char>(1 + 10); // '/' + uint
*buffer++ = '/'; *buffer++ = '/';
const char* end = internal::u32toa(index, buffer); const char* end = internal::u32toa(index, buffer);
documentStack.template Pop<char>(static_cast<size_t>(10 - (end - buffer))); documentStack.template Pop<char>(static_cast<size_t>(10 - (end - buffer)));
} }
else { else {
char* buffer = documentStack.template Push<char>(1 + 20); // '/' + uint64 char *buffer = documentStack.template Push<char>(1 + 20); // '/' + uint64
*buffer++ = '/'; *buffer++ = '/';
const char* end = internal::u64toa(index, buffer); const char* end = internal::u64toa(index, buffer);
documentStack.template Pop<char>(static_cast<size_t>(20 - (end - buffer))); documentStack.template Pop<char>(static_cast<size_t>(20 - (end - buffer)));
} }
} }
}; };
} // namespace internal } // namespace internal
@ -1655,17 +1602,19 @@ public:
\param allocator An optional allocator instance for allocating memory. Can be null. \param allocator An optional allocator instance for allocating memory. Can be null.
*/ */
explicit GenericSchemaDocument(const ValueType& document, const Ch* uri = 0, SizeType uriLength = 0, explicit GenericSchemaDocument(const ValueType& document, const Ch* uri = 0, SizeType uriLength = 0,
IRemoteSchemaDocumentProviderType* remoteProvider = 0, Allocator* allocator = 0) : remoteProvider_(remoteProvider), IRemoteSchemaDocumentProviderType* remoteProvider = 0, Allocator* allocator = 0) :
remoteProvider_(remoteProvider),
allocator_(allocator), allocator_(allocator),
ownAllocator_(), ownAllocator_(),
root_(), root_(),
typeless_(), typeless_(),
schemaMap_(allocator, kInitialSchemaMapSize), schemaMap_(allocator, kInitialSchemaMapSize),
schemaRef_(allocator, kInitialSchemaRefSize) { schemaRef_(allocator, kInitialSchemaRefSize)
{
if (!allocator_) if (!allocator_)
ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)(); ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();
Ch noUri[1] = { 0 }; Ch noUri[1] = {0};
uri_.SetString(uri ? uri : noUri, uriLength, *allocator_); uri_.SetString(uri ? uri : noUri, uriLength, *allocator_);
typeless_ = static_cast<SchemaType*>(allocator_->Malloc(sizeof(SchemaType))); typeless_ = static_cast<SchemaType*>(allocator_->Malloc(sizeof(SchemaType)));
@ -1700,14 +1649,16 @@ public:
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS #if RAPIDJSON_HAS_CXX11_RVALUE_REFS
//! Move constructor in C++11 //! Move constructor in C++11
GenericSchemaDocument(GenericSchemaDocument&& rhs) RAPIDJSON_NOEXCEPT : remoteProvider_(rhs.remoteProvider_), GenericSchemaDocument(GenericSchemaDocument&& rhs) RAPIDJSON_NOEXCEPT :
remoteProvider_(rhs.remoteProvider_),
allocator_(rhs.allocator_), allocator_(rhs.allocator_),
ownAllocator_(rhs.ownAllocator_), ownAllocator_(rhs.ownAllocator_),
root_(rhs.root_), root_(rhs.root_),
typeless_(rhs.typeless_), typeless_(rhs.typeless_),
schemaMap_(std::move(rhs.schemaMap_)), schemaMap_(std::move(rhs.schemaMap_)),
schemaRef_(std::move(rhs.schemaRef_)), schemaRef_(std::move(rhs.schemaRef_)),
uri_(std::move(rhs.uri_)) { uri_(std::move(rhs.uri_))
{
rhs.remoteProvider_ = 0; rhs.remoteProvider_ = 0;
rhs.allocator_ = 0; rhs.allocator_ = 0;
rhs.ownAllocator_ = 0; rhs.ownAllocator_ = 0;
@ -1740,7 +1691,7 @@ private:
GenericSchemaDocument& operator=(const GenericSchemaDocument&); GenericSchemaDocument& operator=(const GenericSchemaDocument&);
struct SchemaRefEntry { struct SchemaRefEntry {
SchemaRefEntry(const PointerType& s, const PointerType& t, const SchemaType** outSchema, Allocator* allocator) : source(s, allocator), target(t, allocator), schema(outSchema) {} SchemaRefEntry(const PointerType& s, const PointerType& t, const SchemaType** outSchema, Allocator *allocator) : source(s, allocator), target(t, allocator), schema(outSchema) {}
PointerType source; PointerType source;
PointerType target; PointerType target;
const SchemaType** schema; const SchemaType** schema;
@ -1855,8 +1806,8 @@ private:
static const size_t kInitialSchemaRefSize = 64; static const size_t kInitialSchemaRefSize = 64;
IRemoteSchemaDocumentProviderType* remoteProvider_; IRemoteSchemaDocumentProviderType* remoteProvider_;
Allocator* allocator_; Allocator *allocator_;
Allocator* ownAllocator_; Allocator *ownAllocator_;
const SchemaType* root_; //!< Root schema. const SchemaType* root_; //!< Root schema.
SchemaType* typeless_; SchemaType* typeless_;
internal::Stack<Allocator> schemaMap_; // Stores created Pointer -> Schemas internal::Stack<Allocator> schemaMap_; // Stores created Pointer -> Schemas
@ -1888,7 +1839,8 @@ template <
typename SchemaDocumentType, typename SchemaDocumentType,
typename OutputHandler = BaseReaderHandler<typename SchemaDocumentType::SchemaType::EncodingType>, typename OutputHandler = BaseReaderHandler<typename SchemaDocumentType::SchemaType::EncodingType>,
typename StateAllocator = CrtAllocator> typename StateAllocator = CrtAllocator>
class GenericSchemaValidator : public internal::ISchemaStateFactory<typename SchemaDocumentType::SchemaType>, class GenericSchemaValidator :
public internal::ISchemaStateFactory<typename SchemaDocumentType::SchemaType>,
public internal::ISchemaValidator, public internal::ISchemaValidator,
public internal::IValidationErrorHandler<typename SchemaDocumentType::SchemaType> { public internal::IValidationErrorHandler<typename SchemaDocumentType::SchemaType> {
public: public:
@ -1912,7 +1864,8 @@ public:
StateAllocator* allocator = 0, StateAllocator* allocator = 0,
size_t schemaStackCapacity = kDefaultSchemaStackCapacity, size_t schemaStackCapacity = kDefaultSchemaStackCapacity,
size_t documentStackCapacity = kDefaultDocumentStackCapacity) size_t documentStackCapacity = kDefaultDocumentStackCapacity)
: schemaDocument_(&schemaDocument), :
schemaDocument_(&schemaDocument),
root_(schemaDocument.GetRoot()), root_(schemaDocument.GetRoot()),
stateAllocator_(allocator), stateAllocator_(allocator),
ownStateAllocator_(0), ownStateAllocator_(0),
@ -1925,8 +1878,7 @@ public:
valid_(true), valid_(true),
flags_(kValidateDefaultFlags) flags_(kValidateDefaultFlags)
#if RAPIDJSON_SCHEMA_VERBOSE #if RAPIDJSON_SCHEMA_VERBOSE
, , depth_(0)
depth_(0)
#endif #endif
{ {
} }
@ -1944,7 +1896,8 @@ public:
StateAllocator* allocator = 0, StateAllocator* allocator = 0,
size_t schemaStackCapacity = kDefaultSchemaStackCapacity, size_t schemaStackCapacity = kDefaultSchemaStackCapacity,
size_t documentStackCapacity = kDefaultDocumentStackCapacity) size_t documentStackCapacity = kDefaultDocumentStackCapacity)
: schemaDocument_(&schemaDocument), :
schemaDocument_(&schemaDocument),
root_(schemaDocument.GetRoot()), root_(schemaDocument.GetRoot()),
stateAllocator_(allocator), stateAllocator_(allocator),
ownStateAllocator_(0), ownStateAllocator_(0),
@ -1957,8 +1910,7 @@ public:
valid_(true), valid_(true),
flags_(kValidateDefaultFlags) flags_(kValidateDefaultFlags)
#if RAPIDJSON_SCHEMA_VERBOSE #if RAPIDJSON_SCHEMA_VERBOSE
, , depth_(0)
depth_(0)
#endif #endif
{ {
} }
@ -2216,10 +2168,10 @@ public:
} }
#define RAPIDJSON_STRING_(name, ...) \ #define RAPIDJSON_STRING_(name, ...) \
static const StringRefType& Get##name##String() { \ static const StringRefType& Get##name##String() {\
static const Ch s[] = { __VA_ARGS__, '\0' }; \ static const Ch s[] = { __VA_ARGS__, '\0' };\
static const StringRefType v(s, static_cast<SizeType>(sizeof(s) / sizeof(Ch) - 1)); \ static const StringRefType v(s, static_cast<SizeType>(sizeof(s) / sizeof(Ch) - 1)); \
return v; \ return v;\
} }
RAPIDJSON_STRING_(InstanceRef, 'i', 'n', 's', 't', 'a', 'n', 'c', 'e', 'R', 'e', 'f') RAPIDJSON_STRING_(InstanceRef, 'i', 'n', 's', 't', 'a', 'n', 'c', 'e', 'R', 'e', 'f')
@ -2237,52 +2189,54 @@ public:
#if RAPIDJSON_SCHEMA_VERBOSE #if RAPIDJSON_SCHEMA_VERBOSE
#define RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_() \ #define RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_() \
RAPIDJSON_MULTILINEMACRO_BEGIN \ RAPIDJSON_MULTILINEMACRO_BEGIN\
*documentStack_.template Push<Ch>() = '\0'; \ *documentStack_.template Push<Ch>() = '\0';\
documentStack_.template Pop<Ch>(1); \ documentStack_.template Pop<Ch>(1);\
internal::PrintInvalidDocument(documentStack_.template Bottom<Ch>()); \ internal::PrintInvalidDocument(documentStack_.template Bottom<Ch>());\
RAPIDJSON_MULTILINEMACRO_END RAPIDJSON_MULTILINEMACRO_END
#else #else
#define RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_() #define RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_()
#endif #endif
#define RAPIDJSON_SCHEMA_HANDLE_BEGIN_(method, arg1) \ #define RAPIDJSON_SCHEMA_HANDLE_BEGIN_(method, arg1)\
if (!valid_) return false; \ if (!valid_) return false; \
if ((!BeginValue() && !GetContinueOnErrors()) || (!CurrentSchema().method arg1 && !GetContinueOnErrors())) { \ if ((!BeginValue() && !GetContinueOnErrors()) || (!CurrentSchema().method arg1 && !GetContinueOnErrors())) {\
RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_(); \ RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_();\
return valid_ = false; \ return valid_ = false;\
} }
#define RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(method, arg2) \ #define RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(method, arg2)\
for (Context* context = schemaStack_.template Bottom<Context>(); context != schemaStack_.template End<Context>(); context++) { \ for (Context* context = schemaStack_.template Bottom<Context>(); context != schemaStack_.template End<Context>(); context++) {\
if (context->hasher) \ if (context->hasher)\
static_cast<HasherType*>(context->hasher)->method arg2; \ static_cast<HasherType*>(context->hasher)->method arg2;\
if (context->validators) \ if (context->validators)\
for (SizeType i_ = 0; i_ < context->validatorCount; i_++) \ for (SizeType i_ = 0; i_ < context->validatorCount; i_++)\
static_cast<GenericSchemaValidator*>(context->validators[i_])->method arg2; \ static_cast<GenericSchemaValidator*>(context->validators[i_])->method arg2;\
if (context->patternPropertiesValidators) \ if (context->patternPropertiesValidators)\
for (SizeType i_ = 0; i_ < context->patternPropertiesValidatorCount; i_++) \ for (SizeType i_ = 0; i_ < context->patternPropertiesValidatorCount; i_++)\
static_cast<GenericSchemaValidator*>(context->patternPropertiesValidators[i_])->method arg2; \ static_cast<GenericSchemaValidator*>(context->patternPropertiesValidators[i_])->method arg2;\
} }
#define RAPIDJSON_SCHEMA_HANDLE_END_(method, arg2) \ #define RAPIDJSON_SCHEMA_HANDLE_END_(method, arg2)\
valid_ = (EndValue() || GetContinueOnErrors()) && (!outputHandler_ || outputHandler_->method arg2); \ valid_ = (EndValue() || GetContinueOnErrors()) && (!outputHandler_ || outputHandler_->method arg2);\
return valid_; return valid_;
#define RAPIDJSON_SCHEMA_HANDLE_VALUE_(method, arg1, arg2) \ #define RAPIDJSON_SCHEMA_HANDLE_VALUE_(method, arg1, arg2) \
RAPIDJSON_SCHEMA_HANDLE_BEGIN_(method, arg1); \ RAPIDJSON_SCHEMA_HANDLE_BEGIN_ (method, arg1);\
RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(method, arg2); \ RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(method, arg2);\
RAPIDJSON_SCHEMA_HANDLE_END_(method, arg2) RAPIDJSON_SCHEMA_HANDLE_END_ (method, arg2)
bool Null() { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Null, (CurrentContext()), ()); } bool Null() { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Null, (CurrentContext()), ( )); }
bool Bool(bool b) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Bool, (CurrentContext(), b), (b)); } bool Bool(bool b) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Bool, (CurrentContext(), b), (b)); }
bool Int(int i) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Int, (CurrentContext(), i), (i)); } bool Int(int i) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Int, (CurrentContext(), i), (i)); }
bool Uint(unsigned u) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Uint, (CurrentContext(), u), (u)); } bool Uint(unsigned u) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Uint, (CurrentContext(), u), (u)); }
bool Int64(int64_t i) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Int64, (CurrentContext(), i), (i)); } bool Int64(int64_t i) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Int64, (CurrentContext(), i), (i)); }
bool Uint64(uint64_t u) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Uint64, (CurrentContext(), u), (u)); } bool Uint64(uint64_t u) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Uint64, (CurrentContext(), u), (u)); }
bool Double(double d) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Double, (CurrentContext(), d), (d)); } bool Double(double d) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Double, (CurrentContext(), d), (d)); }
bool RawNumber(const Ch* str, SizeType length, bool copy) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(String, (CurrentContext(), str, length, copy), (str, length, copy)); } bool RawNumber(const Ch* str, SizeType length, bool copy)
bool String(const Ch* str, SizeType length, bool copy) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(String, (CurrentContext(), str, length, copy), (str, length, copy)); } { RAPIDJSON_SCHEMA_HANDLE_VALUE_(String, (CurrentContext(), str, length, copy), (str, length, copy)); }
bool String(const Ch* str, SizeType length, bool copy)
{ RAPIDJSON_SCHEMA_HANDLE_VALUE_(String, (CurrentContext(), str, length, copy), (str, length, copy)); }
bool StartObject() { bool StartObject() {
RAPIDJSON_SCHEMA_HANDLE_BEGIN_(StartObject, (CurrentContext())); RAPIDJSON_SCHEMA_HANDLE_BEGIN_(StartObject, (CurrentContext()));
@ -2377,7 +2331,8 @@ private:
StateAllocator* allocator = 0, StateAllocator* allocator = 0,
size_t schemaStackCapacity = kDefaultSchemaStackCapacity, size_t schemaStackCapacity = kDefaultSchemaStackCapacity,
size_t documentStackCapacity = kDefaultDocumentStackCapacity) size_t documentStackCapacity = kDefaultDocumentStackCapacity)
: schemaDocument_(&schemaDocument), :
schemaDocument_(&schemaDocument),
root_(root), root_(root),
stateAllocator_(allocator), stateAllocator_(allocator),
ownStateAllocator_(0), ownStateAllocator_(0),
@ -2390,8 +2345,7 @@ private:
valid_(true), valid_(true),
flags_(kValidateDefaultFlags) flags_(kValidateDefaultFlags)
#if RAPIDJSON_SCHEMA_VERBOSE #if RAPIDJSON_SCHEMA_VERBOSE
, , depth_(depth)
depth_(depth)
#endif #endif
{ {
if (basePath && basePathSize) if (basePath && basePathSize)
@ -2469,8 +2423,7 @@ private:
// Cleanup before returning if continuing // Cleanup before returning if continuing
if (GetContinueOnErrors()) { if (GetContinueOnErrors()) {
a->PushBack(h, GetStateAllocator()); a->PushBack(h, GetStateAllocator());
while (!documentStack_.Empty() && *documentStack_.template Pop<Ch>(1) != '/') while (!documentStack_.Empty() && *documentStack_.template Pop<Ch>(1) != '/');
;
} }
RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorUniqueItems); RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorUniqueItems);
} }
@ -2518,8 +2471,7 @@ private:
PointerType instancePointer = GetInvalidDocumentPointer(); PointerType instancePointer = GetInvalidDocumentPointer();
((parent && instancePointer.GetTokenCount() > 0) ((parent && instancePointer.GetTokenCount() > 0)
? PointerType(instancePointer.GetTokens(), instancePointer.GetTokenCount() - 1) ? PointerType(instancePointer.GetTokens(), instancePointer.GetTokenCount() - 1)
: instancePointer) : instancePointer).StringifyUriFragment(sb);
.StringifyUriFragment(sb);
ValueType instanceRef(sb.GetString(), static_cast<SizeType>(sb.GetSize() / sizeof(Ch)), ValueType instanceRef(sb.GetString(), static_cast<SizeType>(sb.GetSize() / sizeof(Ch)),
GetStateAllocator()); GetStateAllocator());
result.AddMember(GetInstanceRefString(), instanceRef, GetStateAllocator()); result.AddMember(GetInstanceRefString(), instanceRef, GetStateAllocator());
@ -2529,10 +2481,8 @@ private:
GenericStringBuffer<EncodingType> sb; GenericStringBuffer<EncodingType> sb;
SizeType len = CurrentSchema().GetURI().GetStringLength(); SizeType len = CurrentSchema().GetURI().GetStringLength();
if (len) memcpy(sb.Push(len), CurrentSchema().GetURI().GetString(), len * sizeof(Ch)); if (len) memcpy(sb.Push(len), CurrentSchema().GetURI().GetString(), len * sizeof(Ch));
if (schema.GetTokenCount()) if (schema.GetTokenCount()) schema.StringifyUriFragment(sb);
schema.StringifyUriFragment(sb); else GetInvalidSchemaPointer().StringifyUriFragment(sb);
else
GetInvalidSchemaPointer().StringifyUriFragment(sb);
ValueType schemaRef(sb.GetString(), static_cast<SizeType>(sb.GetSize() / sizeof(Ch)), ValueType schemaRef(sb.GetString(), static_cast<SizeType>(sb.GetSize() / sizeof(Ch)),
GetStateAllocator()); GetStateAllocator());
result.AddMember(GetSchemaRefString(), schemaRef, GetStateAllocator()); result.AddMember(GetSchemaRefString(), schemaRef, GetStateAllocator());

View File

@ -69,7 +69,7 @@ concept Stream {
For custom stream, this type can be specialized for other configuration. For custom stream, this type can be specialized for other configuration.
See TEST(Reader, CustomStringStream) in readertest.cpp for example. See TEST(Reader, CustomStringStream) in readertest.cpp for example.
*/ */
template <typename Stream> template<typename Stream>
struct StreamTraits { struct StreamTraits {
//! Whether to make local copy of stream for optimization during parsing. //! Whether to make local copy of stream for optimization during parsing.
/*! /*!
@ -80,20 +80,20 @@ struct StreamTraits {
}; };
//! Reserve n characters for writing to a stream. //! Reserve n characters for writing to a stream.
template <typename Stream> template<typename Stream>
inline void PutReserve(Stream& stream, size_t count) { inline void PutReserve(Stream& stream, size_t count) {
(void)stream; (void)stream;
(void)count; (void)count;
} }
//! Write character to a stream, presuming buffer is reserved. //! Write character to a stream, presuming buffer is reserved.
template <typename Stream> template<typename Stream>
inline void PutUnsafe(Stream& stream, typename Stream::Ch c) { inline void PutUnsafe(Stream& stream, typename Stream::Ch c) {
stream.Put(c); stream.Put(c);
} }
//! Put N copies of a character to a stream. //! Put N copies of a character to a stream.
template <typename Stream, typename Ch> template<typename Stream, typename Ch>
inline void PutN(Stream& stream, Ch c, size_t n) { inline void PutN(Stream& stream, Ch c, size_t n) {
PutReserve(stream, n); PutReserve(stream, n);
for (size_t i = 0; i < n; i++) for (size_t i = 0; i < n; i++)
@ -115,11 +115,11 @@ RAPIDJSON_DIAG_OFF(4702) // unreachable code
RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
#endif #endif
template <typename InputStream, typename Encoding = UTF8<>> template <typename InputStream, typename Encoding = UTF8<> >
class GenericStreamWrapper { class GenericStreamWrapper {
public: public:
typedef typename Encoding::Ch Ch; typedef typename Encoding::Ch Ch;
GenericStreamWrapper(InputStream& is) : is_(is) {} GenericStreamWrapper(InputStream& is): is_(is) {}
Ch Peek() const { return is_.Peek(); } Ch Peek() const { return is_.Peek(); }
Ch Take() { return is_.Take(); } Ch Take() { return is_.Take(); }
@ -154,34 +154,28 @@ template <typename Encoding>
struct GenericStringStream { struct GenericStringStream {
typedef typename Encoding::Ch Ch; typedef typename Encoding::Ch Ch;
GenericStringStream(const Ch* src) : src_(src), head_(src) {} GenericStringStream(const Ch *src) : src_(src), head_(src) {}
Ch Peek() const { return *src_; } Ch Peek() const { return *src_; }
Ch Take() { return *src_++; } Ch Take() { return *src_++; }
size_t Tell() const { return static_cast<size_t>(src_ - head_); } size_t Tell() const { return static_cast<size_t>(src_ - head_); }
Ch* PutBegin() { Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
RAPIDJSON_ASSERT(false);
return 0;
}
void Put(Ch) { RAPIDJSON_ASSERT(false); } void Put(Ch) { RAPIDJSON_ASSERT(false); }
void Flush() { RAPIDJSON_ASSERT(false); } void Flush() { RAPIDJSON_ASSERT(false); }
size_t PutEnd(Ch*) { size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
RAPIDJSON_ASSERT(false);
return 0;
}
const Ch* src_; //!< Current read position. const Ch* src_; //!< Current read position.
const Ch* head_; //!< Original head of the string. const Ch* head_; //!< Original head of the string.
}; };
template <typename Encoding> template <typename Encoding>
struct StreamTraits<GenericStringStream<Encoding>> { struct StreamTraits<GenericStringStream<Encoding> > {
enum { copyOptimization = 1 }; enum { copyOptimization = 1 };
}; };
//! String stream with UTF8 encoding. //! String stream with UTF8 encoding.
typedef GenericStringStream<UTF8<>> StringStream; typedef GenericStringStream<UTF8<> > StringStream;
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// InsituStringStream // InsituStringStream
@ -194,7 +188,7 @@ template <typename Encoding>
struct GenericInsituStringStream { struct GenericInsituStringStream {
typedef typename Encoding::Ch Ch; typedef typename Encoding::Ch Ch;
GenericInsituStringStream(Ch* src) : src_(src), dst_(0), head_(src) {} GenericInsituStringStream(Ch *src) : src_(src), dst_(0), head_(src) {}
// Read // Read
Ch Peek() { return *src_; } Ch Peek() { return *src_; }
@ -202,20 +196,13 @@ struct GenericInsituStringStream {
size_t Tell() { return static_cast<size_t>(src_ - head_); } size_t Tell() { return static_cast<size_t>(src_ - head_); }
// Write // Write
void Put(Ch c) { void Put(Ch c) { RAPIDJSON_ASSERT(dst_ != 0); *dst_++ = c; }
RAPIDJSON_ASSERT(dst_ != 0);
*dst_++ = c;
}
Ch* PutBegin() { return dst_ = src_; } Ch* PutBegin() { return dst_ = src_; }
size_t PutEnd(Ch* begin) { return static_cast<size_t>(dst_ - begin); } size_t PutEnd(Ch* begin) { return static_cast<size_t>(dst_ - begin); }
void Flush() {} void Flush() {}
Ch* Push(size_t count) { Ch* Push(size_t count) { Ch* begin = dst_; dst_ += count; return begin; }
Ch* begin = dst_;
dst_ += count;
return begin;
}
void Pop(size_t count) { dst_ -= count; } void Pop(size_t count) { dst_ -= count; }
Ch* src_; Ch* src_;
@ -224,12 +211,12 @@ struct GenericInsituStringStream {
}; };
template <typename Encoding> template <typename Encoding>
struct StreamTraits<GenericInsituStringStream<Encoding>> { struct StreamTraits<GenericInsituStringStream<Encoding> > {
enum { copyOptimization = 1 }; enum { copyOptimization = 1 };
}; };
//! Insitu string stream with UTF8 encoding. //! Insitu string stream with UTF8 encoding.
typedef GenericInsituStringStream<UTF8<>> InsituStringStream; typedef GenericInsituStringStream<UTF8<> > InsituStringStream;
RAPIDJSON_NAMESPACE_END RAPIDJSON_NAMESPACE_END

View File

@ -26,7 +26,7 @@
#if defined(__clang__) #if defined(__clang__)
RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(c++ 98 - compat) RAPIDJSON_DIAG_OFF(c++98-compat)
#endif #endif
RAPIDJSON_NAMESPACE_BEGIN RAPIDJSON_NAMESPACE_BEGIN
@ -94,21 +94,21 @@ private:
}; };
//! String buffer with UTF8 encoding //! String buffer with UTF8 encoding
typedef GenericStringBuffer<UTF8<>> StringBuffer; typedef GenericStringBuffer<UTF8<> > StringBuffer;
template <typename Encoding, typename Allocator> template<typename Encoding, typename Allocator>
inline void PutReserve(GenericStringBuffer<Encoding, Allocator>& stream, size_t count) { inline void PutReserve(GenericStringBuffer<Encoding, Allocator>& stream, size_t count) {
stream.Reserve(count); stream.Reserve(count);
} }
template <typename Encoding, typename Allocator> template<typename Encoding, typename Allocator>
inline void PutUnsafe(GenericStringBuffer<Encoding, Allocator>& stream, typename Encoding::Ch c) { inline void PutUnsafe(GenericStringBuffer<Encoding, Allocator>& stream, typename Encoding::Ch c) {
stream.PutUnsafe(c); stream.PutUnsafe(c);
} }
//! Implement specialized version of PutN() with memset() for better performance. //! Implement specialized version of PutN() with memset() for better performance.
template <> template<>
inline void PutN(GenericStringBuffer<UTF8<>>& stream, char c, size_t n) { inline void PutN(GenericStringBuffer<UTF8<> >& stream, char c, size_t n) {
std::memset(stream.stack_.Push<char>(n), c, n * sizeof(c)); std::memset(stream.stack_.Push<char>(n), c, n * sizeof(c));
} }

View File

@ -40,8 +40,8 @@
#ifdef __clang__ #ifdef __clang__
RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(padded) RAPIDJSON_DIAG_OFF(padded)
RAPIDJSON_DIAG_OFF(unreachable - code) RAPIDJSON_DIAG_OFF(unreachable-code)
RAPIDJSON_DIAG_OFF(c++ 98 - compat) RAPIDJSON_DIAG_OFF(c++98-compat)
#elif defined(_MSC_VER) #elif defined(_MSC_VER)
RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
@ -86,7 +86,7 @@ enum WriteFlag {
\tparam StackAllocator Type of allocator for allocating memory of stack. \tparam StackAllocator Type of allocator for allocating memory of stack.
\note implements Handler concept \note implements Handler concept
*/ */
template <typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator, unsigned writeFlags = kWriteDefaultFlags> template<typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator, unsigned writeFlags = kWriteDefaultFlags>
class Writer { class Writer {
public: public:
typedef typename SourceEncoding::Ch Ch; typedef typename SourceEncoding::Ch Ch;
@ -98,12 +98,17 @@ public:
\param stackAllocator User supplied allocator. If it is null, it will create a private one. \param stackAllocator User supplied allocator. If it is null, it will create a private one.
\param levelDepth Initial capacity of stack. \param levelDepth Initial capacity of stack.
*/ */
explicit Writer(OutputStream& os, StackAllocator* stackAllocator = 0, size_t levelDepth = kDefaultLevelDepth) : os_(&os), level_stack_(stackAllocator, levelDepth * sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(false) {} explicit
Writer(OutputStream& os, StackAllocator* stackAllocator = 0, size_t levelDepth = kDefaultLevelDepth) :
os_(&os), level_stack_(stackAllocator, levelDepth * sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(false) {}
explicit Writer(StackAllocator* allocator = 0, size_t levelDepth = kDefaultLevelDepth) : os_(0), level_stack_(allocator, levelDepth * sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(false) {} explicit
Writer(StackAllocator* allocator = 0, size_t levelDepth = kDefaultLevelDepth) :
os_(0), level_stack_(allocator, levelDepth * sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(false) {}
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS #if RAPIDJSON_HAS_CXX11_RVALUE_REFS
Writer(Writer&& rhs) : os_(rhs.os_), level_stack_(std::move(rhs.level_stack_)), maxDecimalPlaces_(rhs.maxDecimalPlaces_), hasRoot_(rhs.hasRoot_) { Writer(Writer&& rhs) :
os_(rhs.os_), level_stack_(std::move(rhs.level_stack_)), maxDecimalPlaces_(rhs.maxDecimalPlaces_), hasRoot_(rhs.hasRoot_) {
rhs.os_ = 0; rhs.os_ = 0;
} }
#endif #endif
@ -174,40 +179,19 @@ public:
*/ */
//@{ //@{
bool Null() { bool Null() { Prefix(kNullType); return EndValue(WriteNull()); }
Prefix(kNullType); bool Bool(bool b) { Prefix(b ? kTrueType : kFalseType); return EndValue(WriteBool(b)); }
return EndValue(WriteNull()); bool Int(int i) { Prefix(kNumberType); return EndValue(WriteInt(i)); }
} bool Uint(unsigned u) { Prefix(kNumberType); return EndValue(WriteUint(u)); }
bool Bool(bool b) { bool Int64(int64_t i64) { Prefix(kNumberType); return EndValue(WriteInt64(i64)); }
Prefix(b ? kTrueType : kFalseType); bool Uint64(uint64_t u64) { Prefix(kNumberType); return EndValue(WriteUint64(u64)); }
return EndValue(WriteBool(b));
}
bool Int(int i) {
Prefix(kNumberType);
return EndValue(WriteInt(i));
}
bool Uint(unsigned u) {
Prefix(kNumberType);
return EndValue(WriteUint(u));
}
bool Int64(int64_t i64) {
Prefix(kNumberType);
return EndValue(WriteInt64(i64));
}
bool Uint64(uint64_t u64) {
Prefix(kNumberType);
return EndValue(WriteUint64(u64));
}
//! Writes the given \c double value to the stream //! Writes the given \c double value to the stream
/*! /*!
\param d The value to be written. \param d The value to be written.
\return Whether it is succeed. \return Whether it is succeed.
*/ */
bool Double(double d) { bool Double(double d) { Prefix(kNumberType); return EndValue(WriteDouble(d)); }
Prefix(kNumberType);
return EndValue(WriteDouble(d));
}
bool RawNumber(const Ch* str, SizeType length, bool copy = false) { bool RawNumber(const Ch* str, SizeType length, bool copy = false) {
RAPIDJSON_ASSERT(str != 0); RAPIDJSON_ASSERT(str != 0);
@ -238,7 +222,8 @@ public:
bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); } bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); }
#if RAPIDJSON_HAS_STDSTRING #if RAPIDJSON_HAS_STDSTRING
bool Key(const std::basic_string<Ch>& str) { bool Key(const std::basic_string<Ch>& str)
{
return Key(str.data(), SizeType(str.size())); return Key(str.data(), SizeType(str.size()));
} }
#endif #endif
@ -310,28 +295,17 @@ protected:
bool WriteNull() { bool WriteNull() {
PutReserve(*os_, 4); PutReserve(*os_, 4);
PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'u'); PutUnsafe(*os_, 'l'); PutUnsafe(*os_, 'l'); return true;
PutUnsafe(*os_, 'u');
PutUnsafe(*os_, 'l');
PutUnsafe(*os_, 'l');
return true;
} }
bool WriteBool(bool b) { bool WriteBool(bool b) {
if (b) { if (b) {
PutReserve(*os_, 4); PutReserve(*os_, 4);
PutUnsafe(*os_, 't'); PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'r'); PutUnsafe(*os_, 'u'); PutUnsafe(*os_, 'e');
PutUnsafe(*os_, 'r');
PutUnsafe(*os_, 'u');
PutUnsafe(*os_, 'e');
} }
else { else {
PutReserve(*os_, 5); PutReserve(*os_, 5);
PutUnsafe(*os_, 'f'); PutUnsafe(*os_, 'f'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'l'); PutUnsafe(*os_, 's'); PutUnsafe(*os_, 'e');
PutUnsafe(*os_, 'a');
PutUnsafe(*os_, 'l');
PutUnsafe(*os_, 's');
PutUnsafe(*os_, 'e');
} }
return true; return true;
} }
@ -378,9 +352,7 @@ protected:
return false; return false;
if (internal::Double(d).IsNan()) { if (internal::Double(d).IsNan()) {
PutReserve(*os_, 3); PutReserve(*os_, 3);
PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'N');
PutUnsafe(*os_, 'a');
PutUnsafe(*os_, 'N');
return true; return true;
} }
if (internal::Double(d).Sign()) { if (internal::Double(d).Sign()) {
@ -389,14 +361,8 @@ protected:
} }
else else
PutReserve(*os_, 8); PutReserve(*os_, 8);
PutUnsafe(*os_, 'I'); PutUnsafe(*os_, 'I'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'f');
PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'y');
PutUnsafe(*os_, 'f');
PutUnsafe(*os_, 'i');
PutUnsafe(*os_, 'n');
PutUnsafe(*os_, 'i');
PutUnsafe(*os_, 't');
PutUnsafe(*os_, 'y');
return true; return true;
} }
@ -411,13 +377,13 @@ protected:
bool WriteString(const Ch* str, SizeType length) { bool WriteString(const Ch* str, SizeType length) {
static const typename OutputStream::Ch hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; static const typename OutputStream::Ch hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
static const char escape[256] = { static const char escape[256] = {
#define Z16 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 #define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
//0 1 2 3 4 5 6 7 8 9 A B C D E F //0 1 2 3 4 5 6 7 8 9 A B C D E F
'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'b', 't', 'n', 'u', 'f', 'r', 'u', 'u', // 00 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'b', 't', 'n', 'u', 'f', 'r', 'u', 'u', // 00
'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', // 10 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', // 10
0, 0, '"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20 0, 0, '"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20
Z16, Z16, // 30~4F Z16, Z16, // 30~4F
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '\\', 0, 0, 0, // 50 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0, // 50
Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16 // 60~FF Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16 // 60~FF
#undef Z16 #undef Z16
}; };
@ -442,7 +408,7 @@ protected:
PutUnsafe(*os_, hexDigits[(codepoint >> 12) & 15]); PutUnsafe(*os_, hexDigits[(codepoint >> 12) & 15]);
PutUnsafe(*os_, hexDigits[(codepoint >> 8) & 15]); PutUnsafe(*os_, hexDigits[(codepoint >> 8) & 15]);
PutUnsafe(*os_, hexDigits[(codepoint >> 4) & 15]); PutUnsafe(*os_, hexDigits[(codepoint >> 4) & 15]);
PutUnsafe(*os_, hexDigits[(codepoint)&15]); PutUnsafe(*os_, hexDigits[(codepoint ) & 15]);
} }
else { else {
RAPIDJSON_ASSERT(codepoint >= 0x010000 && codepoint <= 0x10FFFF); RAPIDJSON_ASSERT(codepoint >= 0x010000 && codepoint <= 0x10FFFF);
@ -453,13 +419,13 @@ protected:
PutUnsafe(*os_, hexDigits[(lead >> 12) & 15]); PutUnsafe(*os_, hexDigits[(lead >> 12) & 15]);
PutUnsafe(*os_, hexDigits[(lead >> 8) & 15]); PutUnsafe(*os_, hexDigits[(lead >> 8) & 15]);
PutUnsafe(*os_, hexDigits[(lead >> 4) & 15]); PutUnsafe(*os_, hexDigits[(lead >> 4) & 15]);
PutUnsafe(*os_, hexDigits[(lead)&15]); PutUnsafe(*os_, hexDigits[(lead ) & 15]);
PutUnsafe(*os_, '\\'); PutUnsafe(*os_, '\\');
PutUnsafe(*os_, 'u'); PutUnsafe(*os_, 'u');
PutUnsafe(*os_, hexDigits[(trail >> 12) & 15]); PutUnsafe(*os_, hexDigits[(trail >> 12) & 15]);
PutUnsafe(*os_, hexDigits[(trail >> 8) & 15]); PutUnsafe(*os_, hexDigits[(trail >> 8) & 15]);
PutUnsafe(*os_, hexDigits[(trail >> 4) & 15]); PutUnsafe(*os_, hexDigits[(trail >> 4) & 15]);
PutUnsafe(*os_, hexDigits[(trail)&15]); PutUnsafe(*os_, hexDigits[(trail ) & 15]);
} }
} }
else if ((sizeof(Ch) == 1 || static_cast<unsigned>(c) < 256) && RAPIDJSON_UNLIKELY(escape[static_cast<unsigned char>(c)])) { else if ((sizeof(Ch) == 1 || static_cast<unsigned>(c) < 256) && RAPIDJSON_UNLIKELY(escape[static_cast<unsigned char>(c)])) {
@ -473,7 +439,9 @@ protected:
PutUnsafe(*os_, hexDigits[static_cast<unsigned char>(c) & 0xF]); PutUnsafe(*os_, hexDigits[static_cast<unsigned char>(c) & 0xF]);
} }
} }
else if (RAPIDJSON_UNLIKELY(!(writeFlags & kWriteValidateEncodingFlag ? Transcoder<SourceEncoding, TargetEncoding>::Validate(is, *os_) : Transcoder<SourceEncoding, TargetEncoding>::TranscodeUnsafe(is, *os_)))) else if (RAPIDJSON_UNLIKELY(!(writeFlags & kWriteValidateEncodingFlag ?
Transcoder<SourceEncoding, TargetEncoding>::Validate(is, *os_) :
Transcoder<SourceEncoding, TargetEncoding>::TranscodeUnsafe(is, *os_))))
return false; return false;
} }
PutUnsafe(*os_, '\"'); PutUnsafe(*os_, '\"');
@ -484,29 +452,19 @@ protected:
return RAPIDJSON_LIKELY(is.Tell() < length); return RAPIDJSON_LIKELY(is.Tell() < length);
} }
bool WriteStartObject() { bool WriteStartObject() { os_->Put('{'); return true; }
os_->Put('{'); bool WriteEndObject() { os_->Put('}'); return true; }
return true; bool WriteStartArray() { os_->Put('['); return true; }
} bool WriteEndArray() { os_->Put(']'); return true; }
bool WriteEndObject() {
os_->Put('}');
return true;
}
bool WriteStartArray() {
os_->Put('[');
return true;
}
bool WriteEndArray() {
os_->Put(']');
return true;
}
bool WriteRawValue(const Ch* json, size_t length) { bool WriteRawValue(const Ch* json, size_t length) {
PutReserve(*os_, length); PutReserve(*os_, length);
GenericStringStream<SourceEncoding> is(json); GenericStringStream<SourceEncoding> is(json);
while (RAPIDJSON_LIKELY(is.Tell() < length)) { while (RAPIDJSON_LIKELY(is.Tell() < length)) {
RAPIDJSON_ASSERT(is.Peek() != '\0'); RAPIDJSON_ASSERT(is.Peek() != '\0');
if (RAPIDJSON_UNLIKELY(!(writeFlags & kWriteValidateEncodingFlag ? Transcoder<SourceEncoding, TargetEncoding>::Validate(is, *os_) : Transcoder<SourceEncoding, TargetEncoding>::TranscodeUnsafe(is, *os_)))) if (RAPIDJSON_UNLIKELY(!(writeFlags & kWriteValidateEncodingFlag ?
Transcoder<SourceEncoding, TargetEncoding>::Validate(is, *os_) :
Transcoder<SourceEncoding, TargetEncoding>::TranscodeUnsafe(is, *os_))))
return false; return false;
} }
return true; return true;
@ -552,39 +510,39 @@ private:
// Full specialization for StringStream to prevent memory copying // Full specialization for StringStream to prevent memory copying
template <> template<>
inline bool Writer<StringBuffer>::WriteInt(int i) { inline bool Writer<StringBuffer>::WriteInt(int i) {
char* buffer = os_->Push(11); char *buffer = os_->Push(11);
const char* end = internal::i32toa(i, buffer); const char* end = internal::i32toa(i, buffer);
os_->Pop(static_cast<size_t>(11 - (end - buffer))); os_->Pop(static_cast<size_t>(11 - (end - buffer)));
return true; return true;
} }
template <> template<>
inline bool Writer<StringBuffer>::WriteUint(unsigned u) { inline bool Writer<StringBuffer>::WriteUint(unsigned u) {
char* buffer = os_->Push(10); char *buffer = os_->Push(10);
const char* end = internal::u32toa(u, buffer); const char* end = internal::u32toa(u, buffer);
os_->Pop(static_cast<size_t>(10 - (end - buffer))); os_->Pop(static_cast<size_t>(10 - (end - buffer)));
return true; return true;
} }
template <> template<>
inline bool Writer<StringBuffer>::WriteInt64(int64_t i64) { inline bool Writer<StringBuffer>::WriteInt64(int64_t i64) {
char* buffer = os_->Push(21); char *buffer = os_->Push(21);
const char* end = internal::i64toa(i64, buffer); const char* end = internal::i64toa(i64, buffer);
os_->Pop(static_cast<size_t>(21 - (end - buffer))); os_->Pop(static_cast<size_t>(21 - (end - buffer)));
return true; return true;
} }
template <> template<>
inline bool Writer<StringBuffer>::WriteUint64(uint64_t u) { inline bool Writer<StringBuffer>::WriteUint64(uint64_t u) {
char* buffer = os_->Push(20); char *buffer = os_->Push(20);
const char* end = internal::u64toa(u, buffer); const char* end = internal::u64toa(u, buffer);
os_->Pop(static_cast<size_t>(20 - (end - buffer))); os_->Pop(static_cast<size_t>(20 - (end - buffer)));
return true; return true;
} }
template <> template<>
inline bool Writer<StringBuffer>::WriteDouble(double d) { inline bool Writer<StringBuffer>::WriteDouble(double d) {
if (internal::Double(d).IsNanOrInf()) { if (internal::Double(d).IsNanOrInf()) {
// Note: This code path can only be reached if (RAPIDJSON_WRITE_DEFAULT_FLAGS & kWriteNanAndInfFlag). // Note: This code path can only be reached if (RAPIDJSON_WRITE_DEFAULT_FLAGS & kWriteNanAndInfFlag).
@ -592,9 +550,7 @@ inline bool Writer<StringBuffer>::WriteDouble(double d) {
return false; return false;
if (internal::Double(d).IsNan()) { if (internal::Double(d).IsNan()) {
PutReserve(*os_, 3); PutReserve(*os_, 3);
PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'N');
PutUnsafe(*os_, 'a');
PutUnsafe(*os_, 'N');
return true; return true;
} }
if (internal::Double(d).Sign()) { if (internal::Double(d).Sign()) {
@ -603,25 +559,19 @@ inline bool Writer<StringBuffer>::WriteDouble(double d) {
} }
else else
PutReserve(*os_, 8); PutReserve(*os_, 8);
PutUnsafe(*os_, 'I'); PutUnsafe(*os_, 'I'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'f');
PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'y');
PutUnsafe(*os_, 'f');
PutUnsafe(*os_, 'i');
PutUnsafe(*os_, 'n');
PutUnsafe(*os_, 'i');
PutUnsafe(*os_, 't');
PutUnsafe(*os_, 'y');
return true; return true;
} }
char* buffer = os_->Push(25); char *buffer = os_->Push(25);
char* end = internal::dtoa(d, buffer, maxDecimalPlaces_); char* end = internal::dtoa(d, buffer, maxDecimalPlaces_);
os_->Pop(static_cast<size_t>(25 - (end - buffer))); os_->Pop(static_cast<size_t>(25 - (end - buffer)));
return true; return true;
} }
#if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42) #if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42)
template <> template<>
inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, size_t length) { inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, size_t length) {
if (length < 16) if (length < 16)
return RAPIDJSON_LIKELY(is.Tell() < length); return RAPIDJSON_LIKELY(is.Tell() < length);
@ -648,12 +598,12 @@ inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, siz
static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' }; static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' };
static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' }; static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' };
static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F }; static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F };
const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&dquote[0])); const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0]));
const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&bslash[0])); const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0]));
const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&space[0])); const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0]));
for (; p != endAligned; p += 16) { for (; p != endAligned; p += 16) {
const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i*>(p)); const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
const __m128i t1 = _mm_cmpeq_epi8(s, dq); const __m128i t1 = _mm_cmpeq_epi8(s, dq);
const __m128i t2 = _mm_cmpeq_epi8(s, bs); const __m128i t2 = _mm_cmpeq_epi8(s, bs);
const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F
@ -675,14 +625,14 @@ inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, siz
p += len; p += len;
break; break;
} }
_mm_storeu_si128(reinterpret_cast<__m128i*>(os_->PushUnsafe(16)), s); _mm_storeu_si128(reinterpret_cast<__m128i *>(os_->PushUnsafe(16)), s);
} }
is.src_ = p; is.src_ = p;
return RAPIDJSON_LIKELY(is.Tell() < length); return RAPIDJSON_LIKELY(is.Tell() < length);
} }
#elif defined(RAPIDJSON_NEON) #elif defined(RAPIDJSON_NEON)
template <> template<>
inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, size_t length) { inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, size_t length) {
if (length < 16) if (length < 16)
return RAPIDJSON_LIKELY(is.Tell() < length); return RAPIDJSON_LIKELY(is.Tell() < length);
@ -712,7 +662,7 @@ inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, siz
const uint8x16_t s3 = vmovq_n_u8(32); const uint8x16_t s3 = vmovq_n_u8(32);
for (; p != endAligned; p += 16) { for (; p != endAligned; p += 16) {
const uint8x16_t s = vld1q_u8(reinterpret_cast<const uint8_t*>(p)); const uint8x16_t s = vld1q_u8(reinterpret_cast<const uint8_t *>(p));
uint8x16_t x = vceqq_u8(s, s0); uint8x16_t x = vceqq_u8(s, s0);
x = vorrq_u8(x, vceqq_u8(s, s1)); x = vorrq_u8(x, vceqq_u8(s, s1));
x = vorrq_u8(x, vceqq_u8(s, s2)); x = vorrq_u8(x, vceqq_u8(s, s2));
@ -730,8 +680,7 @@ inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, siz
len = 8 + (lz >> 3); len = 8 + (lz >> 3);
escaped = true; escaped = true;
} }
} } else {
else {
uint32_t lz = internal::clzll(low); uint32_t lz = internal::clzll(low);
len = lz >> 3; len = lz >> 3;
escaped = true; escaped = true;
@ -744,7 +693,7 @@ inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, siz
p += len; p += len;
break; break;
} }
vst1q_u8(reinterpret_cast<uint8_t*>(os_->PushUnsafe(16)), s); vst1q_u8(reinterpret_cast<uint8_t *>(os_->PushUnsafe(16)), s);
} }
is.src_ = p; is.src_ = p;

View File

@ -16,15 +16,22 @@ struct Backoff {
double rand01() { return randDistribution(randGenerator); } double rand01() { return randDistribution(randGenerator); }
Backoff(int64_t min, int64_t max) Backoff(int64_t min, int64_t max)
: minAmount(min), maxAmount(max), current(min), fails(0), randGenerator((uint64_t)time(0)) { : minAmount(min)
, maxAmount(max)
, current(min)
, fails(0)
, randGenerator((uint64_t)time(0))
{
} }
void reset() { void reset()
{
fails = 0; fails = 0;
current = minAmount; current = minAmount;
} }
int64_t nextDelay() { int64_t nextDelay()
{
++fails; ++fails;
int64_t delay = (int64_t)((double)current * 2.0 * rand01()); int64_t delay = (int64_t)((double)current * 2.0 * rand01());
current = std::min(current + delay, maxAmount); current = std::min(current + delay, maxAmount);

View File

@ -11,7 +11,7 @@ int GetProcessId();
struct BaseConnection { struct BaseConnection {
static BaseConnection* Create(); static BaseConnection* Create();
static void Destroy(BaseConnection*&); static void Destroy(BaseConnection*&);
bool isOpen{ false }; bool isOpen{false};
bool Open(); bool Open();
bool Close(); bool Close();
bool Write(const void* data, size_t length); bool Write(const void* data, size_t length);

View File

@ -9,12 +9,13 @@
#include <sys/un.h> #include <sys/un.h>
#include <unistd.h> #include <unistd.h>
int GetProcessId() { int GetProcessId()
{
return ::getpid(); return ::getpid();
} }
struct BaseConnectionUnix : public BaseConnection { struct BaseConnectionUnix : public BaseConnection {
int sock{ -1 }; int sock{-1};
}; };
static BaseConnectionUnix Connection; static BaseConnectionUnix Connection;
@ -25,7 +26,8 @@ static int MsgFlags = MSG_NOSIGNAL;
static int MsgFlags = 0; static int MsgFlags = 0;
#endif #endif
static const char* GetTempPath() { static const char* GetTempPath()
{
const char* temp = getenv("XDG_RUNTIME_DIR"); const char* temp = getenv("XDG_RUNTIME_DIR");
temp = temp ? temp : getenv("TMPDIR"); temp = temp ? temp : getenv("TMPDIR");
temp = temp ? temp : getenv("TMP"); temp = temp ? temp : getenv("TMP");
@ -34,18 +36,21 @@ static const char* GetTempPath() {
return temp; return temp;
} }
/*static*/ BaseConnection* BaseConnection::Create() { /*static*/ BaseConnection* BaseConnection::Create()
{
PipeAddr.sun_family = AF_UNIX; PipeAddr.sun_family = AF_UNIX;
return &Connection; return &Connection;
} }
/*static*/ void BaseConnection::Destroy(BaseConnection*& c) { /*static*/ void BaseConnection::Destroy(BaseConnection*& c)
{
auto self = reinterpret_cast<BaseConnectionUnix*>(c); auto self = reinterpret_cast<BaseConnectionUnix*>(c);
self->Close(); self->Close();
c = nullptr; c = nullptr;
} }
bool BaseConnection::Open() { bool BaseConnection::Open()
{
const char* tempPath = GetTempPath(); const char* tempPath = GetTempPath();
auto self = reinterpret_cast<BaseConnectionUnix*>(this); auto self = reinterpret_cast<BaseConnectionUnix*>(this);
self->sock = socket(AF_UNIX, SOCK_STREAM, 0); self->sock = socket(AF_UNIX, SOCK_STREAM, 0);
@ -71,7 +76,8 @@ bool BaseConnection::Open() {
return false; return false;
} }
bool BaseConnection::Close() { bool BaseConnection::Close()
{
auto self = reinterpret_cast<BaseConnectionUnix*>(this); auto self = reinterpret_cast<BaseConnectionUnix*>(this);
if (self->sock == -1) { if (self->sock == -1) {
return false; return false;
@ -82,7 +88,8 @@ bool BaseConnection::Close() {
return true; return true;
} }
bool BaseConnection::Write(const void* data, size_t length) { bool BaseConnection::Write(const void* data, size_t length)
{
auto self = reinterpret_cast<BaseConnectionUnix*>(this); auto self = reinterpret_cast<BaseConnectionUnix*>(this);
if (self->sock == -1) { if (self->sock == -1) {
@ -96,7 +103,8 @@ bool BaseConnection::Write(const void* data, size_t length) {
return sentBytes == (ssize_t)length; return sentBytes == (ssize_t)length;
} }
bool BaseConnection::Read(void* data, size_t length) { bool BaseConnection::Read(void* data, size_t length)
{
auto self = reinterpret_cast<BaseConnectionUnix*>(this); auto self = reinterpret_cast<BaseConnectionUnix*>(this);
if (self->sock == -1) { if (self->sock == -1) {

View File

@ -7,28 +7,32 @@
#include <assert.h> #include <assert.h>
#include <windows.h> #include <windows.h>
int GetProcessId() { int GetProcessId()
{
return (int)::GetCurrentProcessId(); return (int)::GetCurrentProcessId();
} }
struct BaseConnectionWin : public BaseConnection { struct BaseConnectionWin : public BaseConnection {
HANDLE pipe{ INVALID_HANDLE_VALUE }; HANDLE pipe{INVALID_HANDLE_VALUE};
}; };
static BaseConnectionWin Connection; static BaseConnectionWin Connection;
/*static*/ BaseConnection* BaseConnection::Create() { /*static*/ BaseConnection* BaseConnection::Create()
{
return &Connection; return &Connection;
} }
/*static*/ void BaseConnection::Destroy(BaseConnection*& c) { /*static*/ void BaseConnection::Destroy(BaseConnection*& c)
{
auto self = reinterpret_cast<BaseConnectionWin*>(c); auto self = reinterpret_cast<BaseConnectionWin*>(c);
self->Close(); self->Close();
c = nullptr; c = nullptr;
} }
bool BaseConnection::Open() { bool BaseConnection::Open()
wchar_t pipeName[]{ L"\\\\?\\pipe\\discord-ipc-0" }; {
wchar_t pipeName[]{L"\\\\?\\pipe\\discord-ipc-0"};
const size_t pipeDigit = sizeof(pipeName) / sizeof(wchar_t) - 2; const size_t pipeDigit = sizeof(pipeName) / sizeof(wchar_t) - 2;
pipeName[pipeDigit] = L'0'; pipeName[pipeDigit] = L'0';
auto self = reinterpret_cast<BaseConnectionWin*>(this); auto self = reinterpret_cast<BaseConnectionWin*>(this);
@ -57,7 +61,8 @@ bool BaseConnection::Open() {
} }
} }
bool BaseConnection::Close() { bool BaseConnection::Close()
{
auto self = reinterpret_cast<BaseConnectionWin*>(this); auto self = reinterpret_cast<BaseConnectionWin*>(this);
::CloseHandle(self->pipe); ::CloseHandle(self->pipe);
self->pipe = INVALID_HANDLE_VALUE; self->pipe = INVALID_HANDLE_VALUE;
@ -65,7 +70,8 @@ bool BaseConnection::Close() {
return true; return true;
} }
bool BaseConnection::Write(const void* data, size_t length) { bool BaseConnection::Write(const void* data, size_t length)
{
if (length == 0) { if (length == 0) {
return true; return true;
} }
@ -87,7 +93,8 @@ bool BaseConnection::Write(const void* data, size_t length) {
bytesWritten == bytesLength; bytesWritten == bytesLength;
} }
bool BaseConnection::Read(void* data, size_t length) { bool BaseConnection::Read(void* data, size_t length)
{
assert(data); assert(data);
if (!data) { if (!data) {
return false; return false;

View File

@ -9,7 +9,8 @@
#include <sys/types.h> #include <sys/types.h>
#include <unistd.h> #include <unistd.h>
static bool Mkdir(const char* path) { static bool Mkdir(const char* path)
{
int result = mkdir(path, 0755); int result = mkdir(path, 0755);
if (result == 0) { if (result == 0) {
return true; return true;
@ -21,7 +22,8 @@ static bool Mkdir(const char* path) {
} }
// we want to register games so we can run them from Discord client as discord-<appid>:// // we want to register games so we can run them from Discord client as discord-<appid>://
extern "C" DISCORD_EXPORT void Discord_Register(const char* applicationId, const char* command) { extern "C" DISCORD_EXPORT void Discord_Register(const char* applicationId, const char* command)
{
// Add a desktop file and update some mime handlers so that xdg-open does the right thing. // Add a desktop file and update some mime handlers so that xdg-open does the right thing.
const char* home = getenv("HOME"); const char* home = getenv("HOME");
@ -92,7 +94,8 @@ extern "C" DISCORD_EXPORT void Discord_Register(const char* applicationId, const
} }
extern "C" DISCORD_EXPORT void Discord_RegisterSteamGame(const char* applicationId, extern "C" DISCORD_EXPORT void Discord_RegisterSteamGame(const char* applicationId,
const char* steamId) { const char* steamId)
{
char command[256]; char command[256];
sprintf(command, "xdg-open steam://rungameid/%s", steamId); sprintf(command, "xdg-open steam://rungameid/%s", steamId);
Discord_Register(applicationId, command); Discord_Register(applicationId, command);

View File

@ -21,7 +21,8 @@
#ifdef __MINGW32__ #ifdef __MINGW32__
#include <wchar.h> #include <wchar.h>
/// strsafe.h fixes /// strsafe.h fixes
static HRESULT StringCbPrintfW(LPWSTR pszDest, size_t cbDest, LPCWSTR pszFormat, ...) { static HRESULT StringCbPrintfW(LPWSTR pszDest, size_t cbDest, LPCWSTR pszFormat, ...)
{
HRESULT ret; HRESULT ret;
va_list va; va_list va;
va_start(va, pszFormat); va_start(va, pszFormat);
@ -50,7 +51,8 @@ static LSTATUS regset(HKEY hkey,
LPCWSTR name, LPCWSTR name,
DWORD type, DWORD type,
const void* data, const void* data,
DWORD len) { DWORD len)
{
HKEY htkey = hkey, hsubkey = nullptr; HKEY htkey = hkey, hsubkey = nullptr;
LSTATUS ret; LSTATUS ret;
if (subkey && subkey[0]) { if (subkey && subkey[0]) {
@ -65,7 +67,8 @@ static LSTATUS regset(HKEY hkey,
return ret; return ret;
} }
static void Discord_RegisterW(const wchar_t* applicationId, const wchar_t* command) { static void Discord_RegisterW(const wchar_t* applicationId, const wchar_t* command)
{
// https://msdn.microsoft.com/en-us/library/aa767914(v=vs.85).aspx // https://msdn.microsoft.com/en-us/library/aa767914(v=vs.85).aspx
// we want to register games so we can run them as discord-<appid>:// // we want to register games so we can run them as discord-<appid>://
// Update the HKEY_CURRENT_USER, because it doesn't seem to require special permissions. // Update the HKEY_CURRENT_USER, because it doesn't seem to require special permissions.
@ -128,7 +131,8 @@ static void Discord_RegisterW(const wchar_t* applicationId, const wchar_t* comma
RegCloseKey(key); RegCloseKey(key);
} }
extern "C" DISCORD_EXPORT void Discord_Register(const char* applicationId, const char* command) { extern "C" DISCORD_EXPORT void Discord_Register(const char* applicationId, const char* command)
{
wchar_t appId[32]; wchar_t appId[32];
MultiByteToWideChar(CP_UTF8, 0, applicationId, -1, appId, 32); MultiByteToWideChar(CP_UTF8, 0, applicationId, -1, appId, 32);
@ -144,7 +148,8 @@ extern "C" DISCORD_EXPORT void Discord_Register(const char* applicationId, const
} }
extern "C" DISCORD_EXPORT void Discord_RegisterSteamGame(const char* applicationId, extern "C" DISCORD_EXPORT void Discord_RegisterSteamGame(const char* applicationId,
const char* steamId) { const char* steamId)
{
wchar_t appId[32]; wchar_t appId[32];
MultiByteToWideChar(CP_UTF8, 0, applicationId, -1, appId, 32); MultiByteToWideChar(CP_UTF8, 0, applicationId, -1, appId, 32);

View File

@ -15,15 +15,16 @@
#include <thread> #include <thread>
#endif #endif
constexpr size_t MaxMessageSize{ 16 * 1024 }; constexpr size_t MaxMessageSize{16 * 1024};
constexpr size_t MessageQueueSize{ 8 }; constexpr size_t MessageQueueSize{8};
constexpr size_t JoinQueueSize{ 8 }; constexpr size_t JoinQueueSize{8};
struct QueuedMessage { struct QueuedMessage {
size_t length; size_t length;
char buffer[MaxMessageSize]; char buffer[MaxMessageSize];
void Copy(const QueuedMessage& other) { void Copy(const QueuedMessage& other)
{
length = other.length; length = other.length;
if (length) { if (length) {
memcpy(buffer, other.buffer, length); memcpy(buffer, other.buffer, length);
@ -45,20 +46,20 @@ struct User {
// Rounded way up because I'm paranoid about games breaking from future changes in these sizes // Rounded way up because I'm paranoid about games breaking from future changes in these sizes
}; };
static RpcConnection* Connection{ nullptr }; static RpcConnection* Connection{nullptr};
static DiscordEventHandlers QueuedHandlers{}; static DiscordEventHandlers QueuedHandlers{};
static DiscordEventHandlers Handlers{}; static DiscordEventHandlers Handlers{};
static std::atomic_bool WasJustConnected{ false }; static std::atomic_bool WasJustConnected{false};
static std::atomic_bool WasJustDisconnected{ false }; static std::atomic_bool WasJustDisconnected{false};
static std::atomic_bool GotErrorMessage{ false }; static std::atomic_bool GotErrorMessage{false};
static std::atomic_bool WasJoinGame{ false }; static std::atomic_bool WasJoinGame{false};
static std::atomic_bool WasSpectateGame{ false }; static std::atomic_bool WasSpectateGame{false};
static std::atomic_bool UpdatePresence{ false }; static std::atomic_bool UpdatePresence{false};
static char JoinGameSecret[256]; static char JoinGameSecret[256];
static char SpectateGameSecret[256]; static char SpectateGameSecret[256];
static int LastErrorCode{ 0 }; static int LastErrorCode{0};
static char LastErrorMessage[256]; static char LastErrorMessage[256];
static int LastDisconnectErrorCode{ 0 }; static int LastDisconnectErrorCode{0};
static char LastDisconnectErrorMessage[256]; static char LastDisconnectErrorMessage[256];
static std::mutex PresenceMutex; static std::mutex PresenceMutex;
static std::mutex HandlerMutex; static std::mutex HandlerMutex;
@ -71,23 +72,24 @@ static User connectedUser;
// backoff from 0.5 seconds to 1 minute // backoff from 0.5 seconds to 1 minute
static Backoff ReconnectTimeMs(500, 60 * 1000); static Backoff ReconnectTimeMs(500, 60 * 1000);
static auto NextConnect = std::chrono::system_clock::now(); static auto NextConnect = std::chrono::system_clock::now();
static int Pid{ 0 }; static int Pid{0};
static int Nonce{ 1 }; static int Nonce{1};
#ifndef DISCORD_DISABLE_IO_THREAD #ifndef DISCORD_DISABLE_IO_THREAD
static void Discord_UpdateConnection(void); static void Discord_UpdateConnection(void);
class IoThreadHolder { class IoThreadHolder {
private: private:
std::atomic_bool keepRunning{ true }; std::atomic_bool keepRunning{true};
std::mutex waitForIOMutex; std::mutex waitForIOMutex;
std::condition_variable waitForIOActivity; std::condition_variable waitForIOActivity;
std::thread ioThread; std::thread ioThread;
public: public:
void Start() { void Start()
{
keepRunning.store(true); keepRunning.store(true);
ioThread = std::thread([&]() { ioThread = std::thread([&]() {
const std::chrono::duration<int64_t, std::milli> maxWait{ 500LL }; const std::chrono::duration<int64_t, std::milli> maxWait{500LL};
Discord_UpdateConnection(); Discord_UpdateConnection();
while (keepRunning.load()) { while (keepRunning.load()) {
std::unique_lock<std::mutex> lock(waitForIOMutex); std::unique_lock<std::mutex> lock(waitForIOMutex);
@ -99,7 +101,8 @@ public:
void Notify() { waitForIOActivity.notify_all(); } void Notify() { waitForIOActivity.notify_all(); }
void Stop() { void Stop()
{
keepRunning.exchange(false); keepRunning.exchange(false);
Notify(); Notify();
if (ioThread.joinable()) { if (ioThread.joinable()) {
@ -117,11 +120,12 @@ public:
void Notify() {} void Notify() {}
}; };
#endif // DISCORD_DISABLE_IO_THREAD #endif // DISCORD_DISABLE_IO_THREAD
static IoThreadHolder* IoThread{ nullptr }; static IoThreadHolder* IoThread{nullptr};
static void UpdateReconnectTime() { static void UpdateReconnectTime()
{
NextConnect = std::chrono::system_clock::now() + NextConnect = std::chrono::system_clock::now() +
std::chrono::duration<int64_t, std::milli>{ ReconnectTimeMs.nextDelay() }; std::chrono::duration<int64_t, std::milli>{ReconnectTimeMs.nextDelay()};
} }
#ifdef DISCORD_DISABLE_IO_THREAD #ifdef DISCORD_DISABLE_IO_THREAD
@ -233,13 +237,15 @@ static void Discord_UpdateConnection(void)
} }
} }
static void SignalIOActivity() { static void SignalIOActivity()
{
if (IoThread != nullptr) { if (IoThread != nullptr) {
IoThread->Notify(); IoThread->Notify();
} }
} }
static bool RegisterForEvent(const char* evtName) { static bool RegisterForEvent(const char* evtName)
{
auto qmessage = SendQueue.GetNextAddMessage(); auto qmessage = SendQueue.GetNextAddMessage();
if (qmessage) { if (qmessage) {
qmessage->length = qmessage->length =
@ -251,7 +257,8 @@ static bool RegisterForEvent(const char* evtName) {
return false; return false;
} }
static bool DeregisterForEvent(const char* evtName) { static bool DeregisterForEvent(const char* evtName)
{
auto qmessage = SendQueue.GetNextAddMessage(); auto qmessage = SendQueue.GetNextAddMessage();
if (qmessage) { if (qmessage) {
qmessage->length = qmessage->length =
@ -266,7 +273,8 @@ static bool DeregisterForEvent(const char* evtName) {
extern "C" DISCORD_EXPORT void Discord_Initialize(const char* applicationId, extern "C" DISCORD_EXPORT void Discord_Initialize(const char* applicationId,
DiscordEventHandlers* handlers, DiscordEventHandlers* handlers,
int autoRegister, int autoRegister,
const char* optionalSteamId) { const char* optionalSteamId)
{
IoThread = new (std::nothrow) IoThreadHolder(); IoThread = new (std::nothrow) IoThreadHolder();
if (IoThread == nullptr) { if (IoThread == nullptr) {
return; return;
@ -339,7 +347,8 @@ extern "C" DISCORD_EXPORT void Discord_Initialize(const char* applicationId,
IoThread->Start(); IoThread->Start();
} }
extern "C" DISCORD_EXPORT void Discord_Shutdown(void) { extern "C" DISCORD_EXPORT void Discord_Shutdown(void)
{
if (!Connection) { if (!Connection) {
return; return;
} }
@ -357,7 +366,8 @@ extern "C" DISCORD_EXPORT void Discord_Shutdown(void) {
RpcConnection::Destroy(Connection); RpcConnection::Destroy(Connection);
} }
extern "C" DISCORD_EXPORT void Discord_UpdatePresence(const DiscordRichPresence* presence) { extern "C" DISCORD_EXPORT void Discord_UpdatePresence(const DiscordRichPresence* presence)
{
{ {
std::lock_guard<std::mutex> guard(PresenceMutex); std::lock_guard<std::mutex> guard(PresenceMutex);
QueuedPresence.length = JsonWriteRichPresenceObj( QueuedPresence.length = JsonWriteRichPresenceObj(
@ -367,11 +377,13 @@ extern "C" DISCORD_EXPORT void Discord_UpdatePresence(const DiscordRichPresence*
SignalIOActivity(); SignalIOActivity();
} }
extern "C" DISCORD_EXPORT void Discord_ClearPresence(void) { extern "C" DISCORD_EXPORT void Discord_ClearPresence(void)
{
Discord_UpdatePresence(nullptr); Discord_UpdatePresence(nullptr);
} }
extern "C" DISCORD_EXPORT void Discord_Respond(const char* userId, /* DISCORD_REPLY_ */ int reply) { extern "C" DISCORD_EXPORT void Discord_Respond(const char* userId, /* DISCORD_REPLY_ */ int reply)
{
// if we are not connected, let's not batch up stale messages for later // if we are not connected, let's not batch up stale messages for later
if (!Connection || !Connection->IsOpen()) { if (!Connection || !Connection->IsOpen()) {
return; return;
@ -385,7 +397,8 @@ extern "C" DISCORD_EXPORT void Discord_Respond(const char* userId, /* DISCORD_RE
} }
} }
extern "C" DISCORD_EXPORT void Discord_RunCallbacks(void) { extern "C" DISCORD_EXPORT void Discord_RunCallbacks(void)
{
// Note on some weirdness: internally we might connect, get other signals, disconnect any number // Note on some weirdness: internally we might connect, get other signals, disconnect any number
// of times inbetween calls here. Externally, we want the sequence to seem sane, so any other // of times inbetween calls here. Externally, we want the sequence to seem sane, so any other
// signals are book-ended by calls to ready and disconnect. // signals are book-ended by calls to ready and disconnect.
@ -408,10 +421,10 @@ extern "C" DISCORD_EXPORT void Discord_RunCallbacks(void) {
if (WasJustConnected.exchange(false)) { if (WasJustConnected.exchange(false)) {
std::lock_guard<std::mutex> guard(HandlerMutex); std::lock_guard<std::mutex> guard(HandlerMutex);
if (Handlers.ready) { if (Handlers.ready) {
DiscordUser du{ connectedUser.userId, DiscordUser du{connectedUser.userId,
connectedUser.username, connectedUser.username,
connectedUser.discriminator, connectedUser.discriminator,
connectedUser.avatar }; connectedUser.avatar};
Handlers.ready(&du); Handlers.ready(&du);
} }
} }
@ -447,7 +460,7 @@ extern "C" DISCORD_EXPORT void Discord_RunCallbacks(void) {
{ {
std::lock_guard<std::mutex> guard(HandlerMutex); std::lock_guard<std::mutex> guard(HandlerMutex);
if (Handlers.joinRequest) { if (Handlers.joinRequest) {
DiscordUser du{ req->userId, req->username, req->discriminator, req->avatar }; DiscordUser du{req->userId, req->username, req->discriminator, req->avatar};
Handlers.joinRequest(&du); Handlers.joinRequest(&du);
} }
} }
@ -463,7 +476,8 @@ extern "C" DISCORD_EXPORT void Discord_RunCallbacks(void) {
} }
} }
extern "C" DISCORD_EXPORT void Discord_UpdateHandlers(DiscordEventHandlers* newHandlers) { extern "C" DISCORD_EXPORT void Discord_UpdateHandlers(DiscordEventHandlers* newHandlers)
{
if (newHandlers) { if (newHandlers) {
#define HANDLE_EVENT_REGISTRATION(handler_name, event) \ #define HANDLE_EVENT_REGISTRATION(handler_name, event) \
if (!Handlers.handler_name && newHandlers->handler_name) { \ if (!Handlers.handler_name && newHandlers->handler_name) { \

View File

@ -2,6 +2,7 @@
// outsmart GCC's missing-declarations warning // outsmart GCC's missing-declarations warning
BOOL WINAPI DllMain(HMODULE, DWORD, LPVOID); BOOL WINAPI DllMain(HMODULE, DWORD, LPVOID);
BOOL WINAPI DllMain(HMODULE, DWORD, LPVOID) { BOOL WINAPI DllMain(HMODULE, DWORD, LPVOID)
{
return TRUE; return TRUE;
} }

View File

@ -8,14 +8,15 @@
template <typename ElementType, size_t QueueSize> template <typename ElementType, size_t QueueSize>
class MsgQueue { class MsgQueue {
ElementType queue_[QueueSize]; ElementType queue_[QueueSize];
std::atomic_uint nextAdd_{ 0 }; std::atomic_uint nextAdd_{0};
std::atomic_uint nextSend_{ 0 }; std::atomic_uint nextSend_{0};
std::atomic_uint pendingSends_{ 0 }; std::atomic_uint pendingSends_{0};
public: public:
MsgQueue() {} MsgQueue() {}
ElementType* GetNextAddMessage() { ElementType* GetNextAddMessage()
{
// if we are falling behind, bail // if we are falling behind, bail
if (pendingSends_.load() >= QueueSize) { if (pendingSends_.load() >= QueueSize) {
return nullptr; return nullptr;
@ -26,7 +27,8 @@ public:
void CommitAdd() { ++pendingSends_; } void CommitAdd() { ++pendingSends_; }
bool HavePendingSends() const { return pendingSends_.load() != 0; } bool HavePendingSends() const { return pendingSends_.load() != 0; }
ElementType* GetNextSendMessage() { ElementType* GetNextSendMessage()
{
auto index = (nextSend_++) % QueueSize; auto index = (nextSend_++) % QueueSize;
return &queue_[index]; return &queue_[index];
} }

View File

@ -6,19 +6,22 @@
static const int RpcVersion = 1; static const int RpcVersion = 1;
static RpcConnection Instance; static RpcConnection Instance;
/*static*/ RpcConnection* RpcConnection::Create(const char* applicationId) { /*static*/ RpcConnection* RpcConnection::Create(const char* applicationId)
{
Instance.connection = BaseConnection::Create(); Instance.connection = BaseConnection::Create();
StringCopy(Instance.appId, applicationId); StringCopy(Instance.appId, applicationId);
return &Instance; return &Instance;
} }
/*static*/ void RpcConnection::Destroy(RpcConnection*& c) { /*static*/ void RpcConnection::Destroy(RpcConnection*& c)
{
c->Close(); c->Close();
BaseConnection::Destroy(c->connection); BaseConnection::Destroy(c->connection);
c = nullptr; c = nullptr;
} }
void RpcConnection::Open() { void RpcConnection::Open()
{
if (state == State::Connected) { if (state == State::Connected) {
return; return;
} }
@ -54,7 +57,8 @@ void RpcConnection::Open() {
} }
} }
void RpcConnection::Close() { void RpcConnection::Close()
{
if (onDisconnect && (state == State::Connected || state == State::SentHandshake)) { if (onDisconnect && (state == State::Connected || state == State::SentHandshake)) {
onDisconnect(lastErrorCode, lastErrorMessage); onDisconnect(lastErrorCode, lastErrorMessage);
} }
@ -62,7 +66,8 @@ void RpcConnection::Close() {
state = State::Disconnected; state = State::Disconnected;
} }
bool RpcConnection::Write(const void* data, size_t length) { bool RpcConnection::Write(const void* data, size_t length)
{
sendFrame.opcode = Opcode::Frame; sendFrame.opcode = Opcode::Frame;
memcpy(sendFrame.message, data, length); memcpy(sendFrame.message, data, length);
sendFrame.length = (uint32_t)length; sendFrame.length = (uint32_t)length;
@ -73,7 +78,8 @@ bool RpcConnection::Write(const void* data, size_t length) {
return true; return true;
} }
bool RpcConnection::Read(JsonDocument& message) { bool RpcConnection::Read(JsonDocument& message)
{
if (state != State::Connected && state != State::SentHandshake) { if (state != State::Connected && state != State::SentHandshake) {
return false; return false;
} }

View File

@ -38,12 +38,12 @@ struct RpcConnection {
Connected, Connected,
}; };
BaseConnection* connection{ nullptr }; BaseConnection* connection{nullptr};
State state{ State::Disconnected }; State state{State::Disconnected};
void (*onConnect)(JsonDocument& message){ nullptr }; void (*onConnect)(JsonDocument& message){nullptr};
void (*onDisconnect)(int errorCode, const char* message){ nullptr }; void (*onDisconnect)(int errorCode, const char* message){nullptr};
char appId[64]{}; char appId[64]{};
int lastErrorCode{ 0 }; int lastErrorCode{0};
char lastErrorMessage[256]{}; char lastErrorMessage[256]{};
RpcConnection::MessageFrame sendFrame; RpcConnection::MessageFrame sendFrame;

View File

@ -3,7 +3,8 @@
#include "discord_rpc.h" #include "discord_rpc.h"
template <typename T> template <typename T>
void NumberToString(char* dest, T number) { void NumberToString(char* dest, T number)
{
if (!number) { if (!number) {
*dest++ = '0'; *dest++ = '0';
*dest++ = 0; *dest++ = 0;
@ -28,19 +29,22 @@ void NumberToString(char* dest, T number) {
// it's ever so slightly faster to not have to strlen the key // it's ever so slightly faster to not have to strlen the key
template <typename T> template <typename T>
void WriteKey(JsonWriter& w, T& k) { void WriteKey(JsonWriter& w, T& k)
{
w.Key(k, sizeof(T) - 1); w.Key(k, sizeof(T) - 1);
} }
struct WriteObject { struct WriteObject {
JsonWriter& writer; JsonWriter& writer;
WriteObject(JsonWriter& w) WriteObject(JsonWriter& w)
: writer(w) { : writer(w)
{
writer.StartObject(); writer.StartObject();
} }
template <typename T> template <typename T>
WriteObject(JsonWriter& w, T& name) WriteObject(JsonWriter& w, T& name)
: writer(w) { : writer(w)
{
WriteKey(writer, name); WriteKey(writer, name);
writer.StartObject(); writer.StartObject();
} }
@ -51,7 +55,8 @@ struct WriteArray {
JsonWriter& writer; JsonWriter& writer;
template <typename T> template <typename T>
WriteArray(JsonWriter& w, T& name) WriteArray(JsonWriter& w, T& name)
: writer(w) { : writer(w)
{
WriteKey(writer, name); WriteKey(writer, name);
writer.StartArray(); writer.StartArray();
} }
@ -59,14 +64,16 @@ struct WriteArray {
}; };
template <typename T> template <typename T>
void WriteOptionalString(JsonWriter& w, T& k, const char* value) { void WriteOptionalString(JsonWriter& w, T& k, const char* value)
{
if (value && value[0]) { if (value && value[0]) {
w.Key(k, sizeof(T) - 1); w.Key(k, sizeof(T) - 1);
w.String(value); w.String(value);
} }
} }
static void JsonWriteNonce(JsonWriter& writer, int nonce) { static void JsonWriteNonce(JsonWriter& writer, int nonce)
{
WriteKey(writer, "nonce"); WriteKey(writer, "nonce");
char nonceBuffer[32]; char nonceBuffer[32];
NumberToString(nonceBuffer, nonce); NumberToString(nonceBuffer, nonce);
@ -77,7 +84,8 @@ size_t JsonWriteRichPresenceObj(char* dest,
size_t maxLen, size_t maxLen,
int nonce, int nonce,
int pid, int pid,
const DiscordRichPresence* presence) { const DiscordRichPresence* presence)
{
JsonWriter writer(dest, maxLen); JsonWriter writer(dest, maxLen);
{ {
@ -159,7 +167,8 @@ size_t JsonWriteRichPresenceObj(char* dest,
return writer.Size(); return writer.Size();
} }
size_t JsonWriteHandshakeObj(char* dest, size_t maxLen, int version, const char* applicationId) { size_t JsonWriteHandshakeObj(char* dest, size_t maxLen, int version, const char* applicationId)
{
JsonWriter writer(dest, maxLen); JsonWriter writer(dest, maxLen);
{ {
@ -173,7 +182,8 @@ size_t JsonWriteHandshakeObj(char* dest, size_t maxLen, int version, const char*
return writer.Size(); return writer.Size();
} }
size_t JsonWriteSubscribeCommand(char* dest, size_t maxLen, int nonce, const char* evtName) { size_t JsonWriteSubscribeCommand(char* dest, size_t maxLen, int nonce, const char* evtName)
{
JsonWriter writer(dest, maxLen); JsonWriter writer(dest, maxLen);
{ {
@ -191,7 +201,8 @@ size_t JsonWriteSubscribeCommand(char* dest, size_t maxLen, int nonce, const cha
return writer.Size(); return writer.Size();
} }
size_t JsonWriteUnsubscribeCommand(char* dest, size_t maxLen, int nonce, const char* evtName) { size_t JsonWriteUnsubscribeCommand(char* dest, size_t maxLen, int nonce, const char* evtName)
{
JsonWriter writer(dest, maxLen); JsonWriter writer(dest, maxLen);
{ {
@ -209,7 +220,8 @@ size_t JsonWriteUnsubscribeCommand(char* dest, size_t maxLen, int nonce, const c
return writer.Size(); return writer.Size();
} }
size_t JsonWriteJoinReply(char* dest, size_t maxLen, const char* userId, int reply, int nonce) { size_t JsonWriteJoinReply(char* dest, size_t maxLen, const char* userId, int reply, int nonce)
{
JsonWriter writer(dest, maxLen); JsonWriter writer(dest, maxLen);
{ {

View File

@ -22,7 +22,8 @@
// if only there was a standard library function for this // if only there was a standard library function for this
template <size_t Len> template <size_t Len>
inline size_t StringCopy(char (&dest)[Len], const char* src) { inline size_t StringCopy(char (&dest)[Len], const char* src)
{
if (!src || !Len) { if (!src || !Len) {
return 0; return 0;
} }
@ -57,14 +58,18 @@ class LinearAllocator {
public: public:
char* buffer_; char* buffer_;
char* end_; char* end_;
LinearAllocator() { LinearAllocator()
{
assert(0); // needed for some default case in rapidjson, should not use assert(0); // needed for some default case in rapidjson, should not use
} }
LinearAllocator(char* buffer, size_t size) LinearAllocator(char* buffer, size_t size)
: buffer_(buffer), end_(buffer + size) { : buffer_(buffer)
, end_(buffer + size)
{
} }
static const bool kNeedFree = false; static const bool kNeedFree = false;
void* Malloc(size_t size) { void* Malloc(size_t size)
{
char* res = buffer_; char* res = buffer_;
buffer_ += size; buffer_ += size;
if (buffer_ > end_) { if (buffer_ > end_) {
@ -73,7 +78,8 @@ public:
} }
return res; return res;
} }
void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) { void* Realloc(void* originalPtr, size_t originalSize, size_t newSize)
{
if (newSize == 0) { if (newSize == 0) {
return nullptr; return nullptr;
} }
@ -84,7 +90,8 @@ public:
(void)(originalSize); (void)(originalSize);
return Malloc(newSize); return Malloc(newSize);
} }
static void Free(void* ptr) { static void Free(void* ptr)
{
/* shrug */ /* shrug */
(void)ptr; (void)ptr;
} }
@ -95,7 +102,8 @@ class FixedLinearAllocator : public LinearAllocator {
public: public:
char fixedBuffer_[Size]; char fixedBuffer_[Size];
FixedLinearAllocator() FixedLinearAllocator()
: LinearAllocator(fixedBuffer_, Size) { : LinearAllocator(fixedBuffer_, Size)
{
} }
static const bool kNeedFree = false; static const bool kNeedFree = false;
}; };
@ -109,10 +117,14 @@ public:
char* current_; char* current_;
DirectStringBuffer(char* buffer, size_t maxLen) DirectStringBuffer(char* buffer, size_t maxLen)
: buffer_(buffer), end_(buffer + maxLen), current_(buffer) { : buffer_(buffer)
, end_(buffer + maxLen)
, current_(buffer)
{
} }
void Put(char c) { void Put(char c)
{
if (current_ < end_) { if (current_ < end_) {
*current_++ = c; *current_++ = c;
} }
@ -135,7 +147,10 @@ public:
StackAllocator stackAlloc_; StackAllocator stackAlloc_;
JsonWriter(char* dest, size_t maxLen) JsonWriter(char* dest, size_t maxLen)
: JsonWriterBase(stringBuffer_, &stackAlloc_, WriterNestingLevels), stringBuffer_(dest, maxLen), stackAlloc_() { : JsonWriterBase(stringBuffer_, &stackAlloc_, WriterNestingLevels)
, stringBuffer_(dest, maxLen)
, stackAlloc_()
{
} }
size_t Size() const { return stringBuffer_.GetSize(); } size_t Size() const { return stringBuffer_.GetSize(); }
@ -155,14 +170,17 @@ public:
: JsonDocumentBase(rapidjson::kObjectType, : JsonDocumentBase(rapidjson::kObjectType,
&poolAllocator_, &poolAllocator_,
sizeof(stackAllocator_.fixedBuffer_), sizeof(stackAllocator_.fixedBuffer_),
&stackAllocator_), &stackAllocator_)
poolAllocator_(parseBuffer_, sizeof(parseBuffer_), kDefaultChunkCapacity, &mallocAllocator_), stackAllocator_() { , poolAllocator_(parseBuffer_, sizeof(parseBuffer_), kDefaultChunkCapacity, &mallocAllocator_)
, stackAllocator_()
{
} }
}; };
using JsonValue = rapidjson::GenericValue<UTF8, PoolAllocator>; using JsonValue = rapidjson::GenericValue<UTF8, PoolAllocator>;
inline JsonValue* GetObjMember(JsonValue* obj, const char* name) { inline JsonValue* GetObjMember(JsonValue* obj, const char* name)
{
if (obj) { if (obj) {
auto member = obj->FindMember(name); auto member = obj->FindMember(name);
if (member != obj->MemberEnd() && member->value.IsObject()) { if (member != obj->MemberEnd() && member->value.IsObject()) {
@ -172,7 +190,8 @@ inline JsonValue* GetObjMember(JsonValue* obj, const char* name) {
return nullptr; return nullptr;
} }
inline int GetIntMember(JsonValue* obj, const char* name, int notFoundDefault = 0) { inline int GetIntMember(JsonValue* obj, const char* name, int notFoundDefault = 0)
{
if (obj) { if (obj) {
auto member = obj->FindMember(name); auto member = obj->FindMember(name);
if (member != obj->MemberEnd() && member->value.IsInt()) { if (member != obj->MemberEnd() && member->value.IsInt()) {
@ -184,7 +203,8 @@ inline int GetIntMember(JsonValue* obj, const char* name, int notFoundDefault =
inline const char* GetStrMember(JsonValue* obj, inline const char* GetStrMember(JsonValue* obj,
const char* name, const char* name,
const char* notFoundDefault = nullptr) { const char* notFoundDefault = nullptr)
{
if (obj) { if (obj) {
auto member = obj->FindMember(name); auto member = obj->FindMember(name);
if (member != obj->MemberEnd() && member->value.IsString()) { if (member != obj->MemberEnd() && member->value.IsString()) {