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

@ -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_;
@ -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);
@ -407,24 +421,31 @@ private:
namespace internal { namespace internal {
template<typename, typename = void> template<typename, typename = void>
struct IsRefCounted : public FalseType {}; struct IsRefCounted :
public FalseType
{ };
template<typename T> template<typename T>
struct IsRefCounted<T, typename internal::EnableIfCond<T::kRefCounted>::Type> : public TrueType {}; 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,10 +496,13 @@ 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 {
@ -487,22 +521,27 @@ public:
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);
} }
@ -552,24 +600,29 @@ public:
#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,27 +635,38 @@ 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 {

View File

@ -40,7 +40,8 @@ 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() {
@ -48,8 +49,7 @@ public:
if(ch == '\n') { if(ch == '\n') {
line_ ++; line_ ++;
col_ = 0; col_ = 0;
} } else {
else {
col_ ++; col_ ++;
} }
return ch; return ch;

View File

@ -126,7 +126,8 @@ public:
//! Move constructor in C++11 //! Move constructor in C++11
GenericMember(GenericMember&& rhs) RAPIDJSON_NOEXCEPT GenericMember(GenericMember&& rhs) RAPIDJSON_NOEXCEPT
: name(std::move(rhs.name)), : name(std::move(rhs.name)),
value(std::move(rhs.value)) { value(std::move(rhs.value))
{
} }
//! Move assignment in C++11 //! Move assignment in C++11
@ -185,8 +186,7 @@ template <bool Const, typename Encoding, typename Allocator>
class GenericMemberIterator { class GenericMemberIterator {
friend class GenericValue<Encoding,Allocator>; friend class GenericValue<Encoding,Allocator>;
template <bool, typename, typename> template <bool, typename, typename> friend class GenericMemberIterator;
friend class GenericMemberIterator;
typedef GenericMember<Encoding,Allocator> PlainType; typedef GenericMember<Encoding,Allocator> PlainType;
typedef typename internal::MaybeAddConst<Const,PlainType>::Type ValueType; typedef typename internal::MaybeAddConst<Const,PlainType>::Type ValueType;
@ -238,31 +238,14 @@ public:
Otherwise, the copy constructor is implicitly defined. Otherwise, the copy constructor is implicitly defined.
*/ */
GenericMemberIterator(const NonConstIterator & it) : ptr_(it.ptr_) {} GenericMemberIterator(const NonConstIterator & it) : ptr_(it.ptr_) {}
Iterator& operator=(const NonConstIterator& it) { Iterator& operator=(const NonConstIterator & it) { ptr_ = it.ptr_; return *this; }
ptr_ = it.ptr_;
return *this;
}
//! @name stepping //! @name stepping
//@{ //@{
Iterator& operator++() { Iterator& operator++(){ ++ptr_; return *this; }
++ptr_; Iterator& operator--(){ --ptr_; return *this; }
return *this; Iterator operator++(int){ Iterator old(*this); ++ptr_; return old; }
} Iterator operator--(int){ Iterator old(*this); --ptr_; return old; }
Iterator& operator--() {
--ptr_;
return *this;
}
Iterator operator++(int) {
Iterator old(*this);
++ptr_;
return old;
}
Iterator operator--(int) {
Iterator old(*this);
--ptr_;
return old;
}
//@} //@}
//! @name increment/decrement //! @name increment/decrement
@ -270,34 +253,21 @@ public:
Iterator operator+(DifferenceType n) const { return Iterator(ptr_+n); } Iterator operator+(DifferenceType n) const { return Iterator(ptr_+n); }
Iterator operator-(DifferenceType n) const { return Iterator(ptr_-n); } Iterator operator-(DifferenceType n) const { return Iterator(ptr_-n); }
Iterator& operator+=(DifferenceType n) { Iterator& operator+=(DifferenceType n) { ptr_+=n; return *this; }
ptr_ += n; Iterator& operator-=(DifferenceType n) { ptr_-=n; return *this; }
return *this;
}
Iterator& operator-=(DifferenceType n) {
ptr_ -= n;
return *this;
}
//@} //@}
//! @name relations //! @name relations
//@{ //@{
template <bool Const_> template <bool Const_> bool operator==(const GenericMemberIterator<Const_, Encoding, Allocator>& that) const { return ptr_ == that.ptr_; }
bool operator==(const GenericMemberIterator<Const_, Encoding, Allocator>& that) const { return ptr_ == that.ptr_; } template <bool Const_> bool operator!=(const GenericMemberIterator<Const_, Encoding, Allocator>& that) const { return ptr_ != that.ptr_; }
template <bool Const_> template <bool Const_> bool operator<=(const GenericMemberIterator<Const_, Encoding, Allocator>& that) const { return ptr_ <= that.ptr_; }
bool operator!=(const GenericMemberIterator<Const_, Encoding, Allocator>& that) const { return ptr_ != that.ptr_; } template <bool Const_> bool operator>=(const GenericMemberIterator<Const_, Encoding, Allocator>& that) const { return ptr_ >= that.ptr_; }
template <bool Const_> template <bool Const_> bool operator< (const GenericMemberIterator<Const_, Encoding, Allocator>& that) const { return ptr_ < that.ptr_; }
bool operator<=(const GenericMemberIterator<Const_, Encoding, Allocator>& that) const { return ptr_ <= that.ptr_; } template <bool Const_> bool operator> (const GenericMemberIterator<Const_, Encoding, Allocator>& that) const { return ptr_ > that.ptr_; }
template <bool Const_>
bool operator>=(const GenericMemberIterator<Const_, Encoding, Allocator>& that) const { return ptr_ >= that.ptr_; }
template <bool Const_>
bool operator<(const GenericMemberIterator<Const_, Encoding, Allocator>& that) const { return ptr_ < that.ptr_; }
template <bool Const_>
bool operator>(const GenericMemberIterator<Const_, Encoding, Allocator>& that) const { return ptr_ > that.ptr_; }
#ifdef __cpp_lib_three_way_comparison #ifdef __cpp_lib_three_way_comparison
template <bool Const_> template <bool Const_> std::strong_ordering operator<=>(const GenericMemberIterator<Const_, Encoding, Allocator>& that) const { return ptr_ <=> that.ptr_; }
std::strong_ordering operator<=>(const GenericMemberIterator<Const_, Encoding, Allocator>& that) const { return ptr_ <=> that.ptr_; }
#endif #endif
//@} //@}
@ -403,8 +373,7 @@ struct GenericStringRef {
#endif #endif
template<SizeType N> template<SizeType N>
GenericStringRef(const CharType (&str)[N]) RAPIDJSON_NOEXCEPT GenericStringRef(const CharType (&str)[N]) RAPIDJSON_NOEXCEPT
: s(str), : s(str), length(N-1) {}
length(N - 1) {}
//! Explicitly create string reference from \c const character pointer //! Explicitly create string reference from \c const character pointer
#ifndef __clang__ // -Wdocumentation #ifndef __clang__ // -Wdocumentation
@ -533,13 +502,11 @@ namespace internal {
struct IsGenericValueImpl : FalseType {}; struct IsGenericValueImpl : FalseType {};
// select candidates according to nested encoding and allocator types // select candidates according to nested encoding and allocator types
template <typename T> template <typename T> struct IsGenericValueImpl<T, typename Void<typename T::EncodingType>::Type, typename Void<typename T::AllocatorType>::Type>
struct IsGenericValueImpl<T, typename Void<typename T::EncodingType>::Type, typename Void<typename T::AllocatorType>::Type>
: IsBaseOf<GenericValue<typename T::EncodingType, typename T::AllocatorType>, T>::Type {}; : IsBaseOf<GenericValue<typename T::EncodingType, typename T::AllocatorType>, T>::Type {};
// helper to match arbitrary GenericValue instantiations, including derived classes // helper to match arbitrary GenericValue instantiations, including derived classes
template <typename T> template <typename T> struct IsGenericValue : IsGenericValueImpl<T>::Type {};
struct IsGenericValue : IsGenericValueImpl<T>::Type {};
} // namespace internal } // namespace internal
@ -681,10 +648,8 @@ namespace internal {
} // namespace internal } // namespace internal
// Forward declarations // Forward declarations
template <bool, typename> template <bool, typename> class GenericArray;
class GenericArray; template <bool, typename> class GenericObject;
template <bool, typename>
class GenericObject;
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// GenericValue // GenericValue
@ -746,6 +711,7 @@ private:
#endif #endif
public: public:
//! Constructor with JSON value type. //! Constructor with JSON value type.
/*! This creates a Value of specified type with default content. /*! This creates a Value of specified type with default content.
\param type Type of the value. \param type Type of the value.
@ -787,7 +753,8 @@ public:
data_.f.flags = kArrayFlag; data_.f.flags = kArrayFlag;
data_.a.size = data_.a.capacity = count; data_.a.size = data_.a.capacity = count;
SetElementsPointer(le); SetElementsPointer(le);
} break; }
break;
case kStringType: case kStringType:
if (rhs.data_.f.flags == kConstStringFlag && !copyConstStrings) { if (rhs.data_.f.flags == kConstStringFlag && !copyConstStrings) {
data_.f.flags = rhs.data_.f.flags; data_.f.flags = rhs.data_.f.flags;
@ -861,16 +828,10 @@ public:
} }
//! Constructor for double value. //! Constructor for double value.
explicit GenericValue(double d) RAPIDJSON_NOEXCEPT : data_() { explicit GenericValue(double d) RAPIDJSON_NOEXCEPT : data_() { data_.n.d = d; data_.f.flags = kNumberDoubleFlag; }
data_.n.d = d;
data_.f.flags = kNumberDoubleFlag;
}
//! Constructor for float value. //! Constructor for float value.
explicit GenericValue(float f) RAPIDJSON_NOEXCEPT : data_() { explicit GenericValue(float f) RAPIDJSON_NOEXCEPT : data_() { data_.n.d = static_cast<double>(f); data_.f.flags = kNumberDoubleFlag; }
data_.n.d = static_cast<double>(f);
data_.f.flags = kNumberDoubleFlag;
}
//! Constructor for constant string (i.e. do not make a copy of string) //! Constructor for constant string (i.e. do not make a copy of string)
GenericValue(const Ch* s, SizeType length) RAPIDJSON_NOEXCEPT : data_() { SetStringRaw(StringRef(s, length)); } GenericValue(const Ch* s, SizeType length) RAPIDJSON_NOEXCEPT : data_() { SetStringRaw(StringRef(s, length)); }
@ -922,14 +883,16 @@ public:
if (Allocator::kNeedFree || (RAPIDJSON_USE_MEMBERSMAP+0 && if (Allocator::kNeedFree || (RAPIDJSON_USE_MEMBERSMAP+0 &&
internal::IsRefCounted<Allocator>::Value)) { internal::IsRefCounted<Allocator>::Value)) {
switch(data_.f.flags) { switch(data_.f.flags) {
case kArrayFlag: { case kArrayFlag:
{
GenericValue* e = GetElementsPointer(); GenericValue* e = GetElementsPointer();
for (GenericValue* v = e; v != e + data_.a.size; ++v) for (GenericValue* v = e; v != e + data_.a.size; ++v)
v->~GenericValue(); v->~GenericValue();
if (Allocator::kNeedFree) { // Shortcut by Allocator's trait if (Allocator::kNeedFree) { // Shortcut by Allocator's trait
Allocator::Free(e); Allocator::Free(e);
} }
} break; }
break;
case kObjectFlag: case kObjectFlag:
DoFreeMembers(); DoFreeMembers();
@ -1113,9 +1076,7 @@ public:
//! Equal-to operator with primitive types //! Equal-to operator with primitive types
/*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c double, \c true, \c false /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c double, \c true, \c false
*/ */
template <typename T> template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>,internal::IsGenericValue<T> >), (bool)) operator==(const T& rhs) const { return *this == GenericValue(rhs); }
RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T>>), (bool))
operator==(const T& rhs) const { return *this == GenericValue(rhs); }
//! Not-equal-to operator //! Not-equal-to operator
/*! \return !(*this == rhs) /*! \return !(*this == rhs)
@ -1129,22 +1090,18 @@ public:
//! Not-equal-to operator with arbitrary types //! Not-equal-to operator with arbitrary types
/*! \return !(*this == rhs) /*! \return !(*this == rhs)
*/ */
template <typename T> template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue<T>), (bool)) operator!=(const T& rhs) const { return !(*this == rhs); }
RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue<T>), (bool))
operator!=(const T& rhs) const { return !(*this == rhs); }
#ifndef __cpp_lib_three_way_comparison #ifndef __cpp_lib_three_way_comparison
//! Equal-to operator with arbitrary types (symmetric version) //! Equal-to operator with arbitrary types (symmetric version)
/*! \return (rhs == lhs) /*! \return (rhs == lhs)
*/ */
template <typename T> template <typename T> friend RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue<T>), (bool)) operator==(const T& lhs, const GenericValue& rhs) { return rhs == lhs; }
friend RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue<T>), (bool)) operator==(const T& lhs, const GenericValue& rhs) { return rhs == lhs; }
//! Not-Equal-to operator with arbitrary types (symmetric version) //! Not-Equal-to operator with arbitrary types (symmetric version)
/*! \return !(rhs == lhs) /*! \return !(rhs == lhs)
*/ */
template <typename T> template <typename T> friend RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue<T>), (bool)) operator!=(const T& lhs, const GenericValue& rhs) { return !(rhs == lhs); }
friend RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue<T>), (bool)) operator!=(const T& lhs, const GenericValue& rhs) { return !(rhs == lhs); }
//@} //@}
#endif #endif
@ -1172,12 +1129,16 @@ public:
if (IsUint64()) { if (IsUint64()) {
uint64_t u = GetUint64(); uint64_t u = GetUint64();
volatile double d = static_cast<double>(u); volatile double d = static_cast<double>(u);
return (d >= 0.0) && (d < static_cast<double>((std::numeric_limits<uint64_t>::max)())) && (u == static_cast<uint64_t>(d)); return (d >= 0.0)
&& (d < static_cast<double>((std::numeric_limits<uint64_t>::max)()))
&& (u == static_cast<uint64_t>(d));
} }
if (IsInt64()) { if (IsInt64()) {
int64_t i = GetInt64(); int64_t i = GetInt64();
volatile double d = static_cast<double>(i); volatile double d = static_cast<double>(i);
return (d >= static_cast<double>((std::numeric_limits<int64_t>::min)())) && (d < static_cast<double>((std::numeric_limits<int64_t>::max)())) && (i == static_cast<int64_t>(d)); return (d >= static_cast<double>((std::numeric_limits<int64_t>::min)()))
&& (d < static_cast<double>((std::numeric_limits<int64_t>::max)()))
&& (i == static_cast<int64_t>(d));
} }
return true; // double, int, uint are always lossless return true; // double, int, uint are always lossless
} }
@ -1193,7 +1154,8 @@ public:
bool IsLosslessFloat() const { bool IsLosslessFloat() const {
if (!IsNumber()) return false; if (!IsNumber()) return false;
double a = GetDouble(); double a = GetDouble();
if (a < static_cast<double>(-(std::numeric_limits<float>::max)()) || a > static_cast<double>((std::numeric_limits<float>::max)())) if (a < static_cast<double>(-(std::numeric_limits<float>::max)())
|| a > static_cast<double>((std::numeric_limits<float>::max)()))
return false; return false;
double b = static_cast<double>(static_cast<float>(a)); double b = static_cast<double>(static_cast<float>(a));
return a >= b && a <= b; // Prevent -Wfloat-equal return a >= b && a <= b; // Prevent -Wfloat-equal
@ -1204,28 +1166,17 @@ public:
//!@name Null //!@name Null
//@{ //@{
GenericValue& SetNull() { GenericValue& SetNull() { this->~GenericValue(); new (this) GenericValue(); return *this; }
this->~GenericValue();
new (this) GenericValue();
return *this;
}
//@} //@}
//!@name Bool //!@name Bool
//@{ //@{
bool GetBool() const { bool GetBool() const { RAPIDJSON_ASSERT(IsBool()); return data_.f.flags == kTrueFlag; }
RAPIDJSON_ASSERT(IsBool());
return data_.f.flags == kTrueFlag;
}
//!< Set boolean value //!< Set boolean value
/*! \post IsBool() == true */ /*! \post IsBool() == true */
GenericValue& SetBool(bool b) { GenericValue& SetBool(bool b) { this->~GenericValue(); new (this) GenericValue(b); return *this; }
this->~GenericValue();
new (this) GenericValue(b);
return *this;
}
//@} //@}
@ -1234,29 +1185,16 @@ public:
//! Set this value as an empty object. //! Set this value as an empty object.
/*! \post IsObject() == true */ /*! \post IsObject() == true */
GenericValue& SetObject() { GenericValue& SetObject() { this->~GenericValue(); new (this) GenericValue(kObjectType); return *this; }
this->~GenericValue();
new (this) GenericValue(kObjectType);
return *this;
}
//! Get the number of members in the object. //! Get the number of members in the object.
SizeType MemberCount() const { SizeType MemberCount() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.size; }
RAPIDJSON_ASSERT(IsObject());
return data_.o.size;
}
//! Get the capacity of object. //! Get the capacity of object.
SizeType MemberCapacity() const { SizeType MemberCapacity() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.capacity; }
RAPIDJSON_ASSERT(IsObject());
return data_.o.capacity;
}
//! Check whether the object is empty. //! Check whether the object is empty.
bool ObjectEmpty() const { bool ObjectEmpty() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.size == 0; }
RAPIDJSON_ASSERT(IsObject());
return data_.o.size == 0;
}
//! Get a value from an object associated with the name. //! Get a value from an object associated with the name.
/*! \pre IsObject() == true /*! \pre IsObject() == true
@ -1268,14 +1206,12 @@ public:
\note Linear time complexity. \note Linear time complexity.
*/ */
template <typename T> template <typename T>
RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr<internal::IsSame<typename internal::RemoveConst<T>::Type, Ch>>), (GenericValue&)) RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr<internal::IsSame<typename internal::RemoveConst<T>::Type, Ch> >),(GenericValue&)) operator[](T* name) {
operator[](T* name) {
GenericValue n(StringRef(name)); GenericValue n(StringRef(name));
return (*this)[n]; return (*this)[n];
} }
template <typename T> template <typename T>
RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr<internal::IsSame<typename internal::RemoveConst<T>::Type, Ch>>), (const GenericValue&)) RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr<internal::IsSame<typename internal::RemoveConst<T>::Type, Ch> >),(const GenericValue&)) operator[](T* name) const { return const_cast<GenericValue&>(*this)[name]; }
operator[](T* name) const { return const_cast<GenericValue&>(*this)[name]; }
//! Get a value from an object associated with the name. //! Get a value from an object associated with the name.
/*! \pre IsObject() == true /*! \pre IsObject() == true
@ -1314,28 +1250,16 @@ public:
//! Const member iterator //! Const member iterator
/*! \pre IsObject() == true */ /*! \pre IsObject() == true */
ConstMemberIterator MemberBegin() const { ConstMemberIterator MemberBegin() const { RAPIDJSON_ASSERT(IsObject()); return ConstMemberIterator(GetMembersPointer()); }
RAPIDJSON_ASSERT(IsObject());
return ConstMemberIterator(GetMembersPointer());
}
//! Const \em past-the-end member iterator //! Const \em past-the-end member iterator
/*! \pre IsObject() == true */ /*! \pre IsObject() == true */
ConstMemberIterator MemberEnd() const { ConstMemberIterator MemberEnd() const { RAPIDJSON_ASSERT(IsObject()); return ConstMemberIterator(GetMembersPointer() + data_.o.size); }
RAPIDJSON_ASSERT(IsObject());
return ConstMemberIterator(GetMembersPointer() + data_.o.size);
}
//! Member iterator //! Member iterator
/*! \pre IsObject() == true */ /*! \pre IsObject() == true */
MemberIterator MemberBegin() { MemberIterator MemberBegin() { RAPIDJSON_ASSERT(IsObject()); return MemberIterator(GetMembersPointer()); }
RAPIDJSON_ASSERT(IsObject());
return MemberIterator(GetMembersPointer());
}
//! \em Past-the-end member iterator //! \em Past-the-end member iterator
/*! \pre IsObject() == true */ /*! \pre IsObject() == true */
MemberIterator MemberEnd() { MemberIterator MemberEnd() { RAPIDJSON_ASSERT(IsObject()); return MemberIterator(GetMembersPointer() + data_.o.size); }
RAPIDJSON_ASSERT(IsObject());
return MemberIterator(GetMembersPointer() + data_.o.size);
}
//! Request the object to have enough capacity to store members. //! Request the object to have enough capacity to store members.
/*! \param newCapacity The capacity that the object at least need to have. /*! \param newCapacity The capacity that the object at least need to have.
@ -1421,8 +1345,7 @@ public:
RAPIDJSON_ASSERT(name.IsString()); RAPIDJSON_ASSERT(name.IsString());
return DoFindMember(name); return DoFindMember(name);
} }
template <typename SourceAllocator> template <typename SourceAllocator> ConstMemberIterator FindMember(const GenericValue<Encoding, SourceAllocator>& name) const { return const_cast<GenericValue&>(*this).FindMember(name); }
ConstMemberIterator FindMember(const GenericValue<Encoding, SourceAllocator>& name) const { return const_cast<GenericValue&>(*this).FindMember(name); }
#if RAPIDJSON_HAS_STDSTRING #if RAPIDJSON_HAS_STDSTRING
//! Find member by string object name. //! Find member by string object name.
@ -1687,22 +1610,10 @@ public:
return false; return false;
} }
Object GetObject() { Object GetObject() { RAPIDJSON_ASSERT(IsObject()); return Object(*this); }
RAPIDJSON_ASSERT(IsObject()); Object GetObj() { RAPIDJSON_ASSERT(IsObject()); return Object(*this); }
return Object(*this); ConstObject GetObject() const { RAPIDJSON_ASSERT(IsObject()); return ConstObject(*this); }
} ConstObject GetObj() const { RAPIDJSON_ASSERT(IsObject()); return ConstObject(*this); }
Object GetObj() {
RAPIDJSON_ASSERT(IsObject());
return Object(*this);
}
ConstObject GetObject() const {
RAPIDJSON_ASSERT(IsObject());
return ConstObject(*this);
}
ConstObject GetObj() const {
RAPIDJSON_ASSERT(IsObject());
return ConstObject(*this);
}
//@} //@}
@ -1711,29 +1622,16 @@ public:
//! Set this value as an empty array. //! Set this value as an empty array.
/*! \post IsArray == true */ /*! \post IsArray == true */
GenericValue& SetArray() { GenericValue& SetArray() { this->~GenericValue(); new (this) GenericValue(kArrayType); return *this; }
this->~GenericValue();
new (this) GenericValue(kArrayType);
return *this;
}
//! Get the number of elements in array. //! Get the number of elements in array.
SizeType Size() const { SizeType Size() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size; }
RAPIDJSON_ASSERT(IsArray());
return data_.a.size;
}
//! Get the capacity of array. //! Get the capacity of array.
SizeType Capacity() const { SizeType Capacity() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.capacity; }
RAPIDJSON_ASSERT(IsArray());
return data_.a.capacity;
}
//! Check whether the array is empty. //! Check whether the array is empty.
bool Empty() const { bool Empty() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size == 0; }
RAPIDJSON_ASSERT(IsArray());
return data_.a.size == 0;
}
//! Remove all elements in the array. //! Remove all elements in the array.
/*! This function do not deallocate memory in the array, i.e. the capacity is unchanged. /*! This function do not deallocate memory in the array, i.e. the capacity is unchanged.
@ -1761,16 +1659,10 @@ public:
//! Element iterator //! Element iterator
/*! \pre IsArray() == true */ /*! \pre IsArray() == true */
ValueIterator Begin() { ValueIterator Begin() { RAPIDJSON_ASSERT(IsArray()); return GetElementsPointer(); }
RAPIDJSON_ASSERT(IsArray());
return GetElementsPointer();
}
//! \em Past-the-end element iterator //! \em Past-the-end element iterator
/*! \pre IsArray() == true */ /*! \pre IsArray() == true */
ValueIterator End() { ValueIterator End() { RAPIDJSON_ASSERT(IsArray()); return GetElementsPointer() + data_.a.size; }
RAPIDJSON_ASSERT(IsArray());
return GetElementsPointer() + data_.a.size;
}
//! Constant element iterator //! Constant element iterator
/*! \pre IsArray() == true */ /*! \pre IsArray() == true */
ConstValueIterator Begin() const { return const_cast<GenericValue&>(*this).Begin(); } ConstValueIterator Begin() const { return const_cast<GenericValue&>(*this).Begin(); }
@ -1899,36 +1791,18 @@ public:
return pos; return pos;
} }
Array GetArray() { Array GetArray() { RAPIDJSON_ASSERT(IsArray()); return Array(*this); }
RAPIDJSON_ASSERT(IsArray()); ConstArray GetArray() const { RAPIDJSON_ASSERT(IsArray()); return ConstArray(*this); }
return Array(*this);
}
ConstArray GetArray() const {
RAPIDJSON_ASSERT(IsArray());
return ConstArray(*this);
}
//@} //@}
//!@name Number //!@name Number
//@{ //@{
int GetInt() const { int GetInt() const { RAPIDJSON_ASSERT(data_.f.flags & kIntFlag); return data_.n.i.i; }
RAPIDJSON_ASSERT(data_.f.flags & kIntFlag); unsigned GetUint() const { RAPIDJSON_ASSERT(data_.f.flags & kUintFlag); return data_.n.u.u; }
return data_.n.i.i; int64_t GetInt64() const { RAPIDJSON_ASSERT(data_.f.flags & kInt64Flag); return data_.n.i64; }
} uint64_t GetUint64() const { RAPIDJSON_ASSERT(data_.f.flags & kUint64Flag); return data_.n.u64; }
unsigned GetUint() const {
RAPIDJSON_ASSERT(data_.f.flags & kUintFlag);
return data_.n.u.u;
}
int64_t GetInt64() const {
RAPIDJSON_ASSERT(data_.f.flags & kInt64Flag);
return data_.n.i64;
}
uint64_t GetUint64() const {
RAPIDJSON_ASSERT(data_.f.flags & kUint64Flag);
return data_.n.u64;
}
//! Get the value as double type. //! Get the value as double type.
/*! \note If the value is 64-bit integer type, it may lose precision. Use \c IsLosslessDouble() to check whether the converison is lossless. /*! \note If the value is 64-bit integer type, it may lose precision. Use \c IsLosslessDouble() to check whether the converison is lossless.
@ -1939,8 +1813,7 @@ public:
if ((data_.f.flags & kIntFlag) != 0) return data_.n.i.i; // int -> double if ((data_.f.flags & kIntFlag) != 0) return data_.n.i.i; // int -> double
if ((data_.f.flags & kUintFlag) != 0) return data_.n.u.u; // unsigned -> double if ((data_.f.flags & kUintFlag) != 0) return data_.n.u.u; // unsigned -> double
if ((data_.f.flags & kInt64Flag) != 0) return static_cast<double>(data_.n.i64); // int64_t -> double (may lose precision) if ((data_.f.flags & kInt64Flag) != 0) return static_cast<double>(data_.n.i64); // int64_t -> double (may lose precision)
RAPIDJSON_ASSERT((data_.f.flags & kUint64Flag) != 0); RAPIDJSON_ASSERT((data_.f.flags & kUint64Flag) != 0); return static_cast<double>(data_.n.u64); // uint64_t -> double (may lose precision)
return static_cast<double>(data_.n.u64); // uint64_t -> double (may lose precision)
} }
//! Get the value as float type. //! Get the value as float type.
@ -1950,54 +1823,24 @@ public:
return static_cast<float>(GetDouble()); return static_cast<float>(GetDouble());
} }
GenericValue& SetInt(int i) { GenericValue& SetInt(int i) { this->~GenericValue(); new (this) GenericValue(i); return *this; }
this->~GenericValue(); GenericValue& SetUint(unsigned u) { this->~GenericValue(); new (this) GenericValue(u); return *this; }
new (this) GenericValue(i); GenericValue& SetInt64(int64_t i64) { this->~GenericValue(); new (this) GenericValue(i64); return *this; }
return *this; GenericValue& SetUint64(uint64_t u64) { this->~GenericValue(); new (this) GenericValue(u64); return *this; }
} GenericValue& SetDouble(double d) { this->~GenericValue(); new (this) GenericValue(d); return *this; }
GenericValue& SetUint(unsigned u) { GenericValue& SetFloat(float f) { this->~GenericValue(); new (this) GenericValue(static_cast<double>(f)); return *this; }
this->~GenericValue();
new (this) GenericValue(u);
return *this;
}
GenericValue& SetInt64(int64_t i64) {
this->~GenericValue();
new (this) GenericValue(i64);
return *this;
}
GenericValue& SetUint64(uint64_t u64) {
this->~GenericValue();
new (this) GenericValue(u64);
return *this;
}
GenericValue& SetDouble(double d) {
this->~GenericValue();
new (this) GenericValue(d);
return *this;
}
GenericValue& SetFloat(float f) {
this->~GenericValue();
new (this) GenericValue(static_cast<double>(f));
return *this;
}
//@} //@}
//!@name String //!@name String
//@{ //@{
const Ch* GetString() const { const Ch* GetString() const { RAPIDJSON_ASSERT(IsString()); return DataString(data_); }
RAPIDJSON_ASSERT(IsString());
return DataString(data_);
}
//! Get the length of string. //! Get the length of string.
/*! Since rapidjson permits "\\u0000" in the json string, strlen(v.GetString()) may not equal to v.GetStringLength(). /*! Since rapidjson permits "\\u0000" in the json string, strlen(v.GetString()) may not equal to v.GetStringLength().
*/ */
SizeType GetStringLength() const { SizeType GetStringLength() const { RAPIDJSON_ASSERT(IsString()); return DataStringLength(data_); }
RAPIDJSON_ASSERT(IsString());
return DataStringLength(data_);
}
//! Set this value as a string without copying source string. //! Set this value as a string without copying source string.
/*! This version has better performance with supplied length, and also support string containing null character. /*! This version has better performance with supplied length, and also support string containing null character.
@ -2014,11 +1857,7 @@ public:
\return The value itself for fluent API. \return The value itself for fluent API.
\post IsString() == true && GetString() == s && GetStringLength() == s.length \post IsString() == true && GetString() == s && GetStringLength() == s.length
*/ */
GenericValue& SetString(StringRefType s) { GenericValue& SetString(StringRefType s) { this->~GenericValue(); SetStringRaw(s); return *this; }
this->~GenericValue();
SetStringRaw(s);
return *this;
}
//! Set this value as a string by copying from source string. //! Set this value as a string by copying from source string.
/*! This version has better performance with supplied length, and also support string containing null character. /*! This version has better performance with supplied length, and also support string containing null character.
@ -2044,11 +1883,7 @@ public:
\return The value itself for fluent API. \return The value itself for fluent API.
\post IsString() == true && GetString() != s.s && strcmp(GetString(),s) == 0 && GetStringLength() == length \post IsString() == true && GetString() != s.s && strcmp(GetString(),s) == 0 && GetStringLength() == length
*/ */
GenericValue& SetString(StringRefType s, Allocator& allocator) { GenericValue& SetString(StringRefType s, Allocator& allocator) { this->~GenericValue(); SetStringRaw(s, allocator); return *this; }
this->~GenericValue();
SetStringRaw(s, allocator);
return *this;
}
#if RAPIDJSON_HAS_STDSTRING #if RAPIDJSON_HAS_STDSTRING
//! Set this value as a string by copying from source string. //! Set this value as a string by copying from source string.
@ -2097,12 +1932,9 @@ public:
template <typename Handler> template <typename Handler>
bool Accept(Handler& handler) const { bool Accept(Handler& handler) const {
switch(GetType()) { switch(GetType()) {
case kNullType: case kNullType: return handler.Null();
return handler.Null(); case kFalseType: return handler.Bool(false);
case kFalseType: case kTrueType: return handler.Bool(true);
return handler.Bool(false);
case kTrueType:
return handler.Bool(true);
case kObjectType: case kObjectType:
if (RAPIDJSON_UNLIKELY(!handler.StartObject())) if (RAPIDJSON_UNLIKELY(!handler.StartObject()))
@ -2129,24 +1961,17 @@ public:
default: default:
RAPIDJSON_ASSERT(GetType() == kNumberType); RAPIDJSON_ASSERT(GetType() == kNumberType);
if (IsDouble()) if (IsDouble()) return handler.Double(data_.n.d);
return handler.Double(data_.n.d); else if (IsInt()) return handler.Int(data_.n.i.i);
else if (IsInt()) else if (IsUint()) return handler.Uint(data_.n.u.u);
return handler.Int(data_.n.i.i); else if (IsInt64()) return handler.Int64(data_.n.i64);
else if (IsUint()) else return handler.Uint64(data_.n.u64);
return handler.Uint(data_.n.u.u);
else if (IsInt64())
return handler.Int64(data_.n.i64);
else
return handler.Uint64(data_.n.u64);
} }
} }
private: private:
template <typename, typename> template <typename, typename> friend class GenericValue;
friend class GenericValue; template <typename, typename, typename> friend class GenericDocument;
template <typename, typename, typename>
friend class GenericDocument;
enum { enum {
kBoolFlag = 0x0008, kBoolFlag = 0x0008,
@ -2209,9 +2034,7 @@ private:
// This allows to store 13-chars strings in 32-bit mode, 21-chars strings in 64-bit mode, // This allows to store 13-chars strings in 32-bit mode, 21-chars strings in 64-bit mode,
// 13-chars strings for RAPIDJSON_48BITPOINTER_OPTIMIZATION=1 inline (for `UTF8`-encoded strings). // 13-chars strings for RAPIDJSON_48BITPOINTER_OPTIMIZATION=1 inline (for `UTF8`-encoded strings).
struct ShortString { struct ShortString {
enum { MaxChars = sizeof(static_cast<Flag*>(0)->payload) / sizeof(Ch), enum { MaxChars = sizeof(static_cast<Flag*>(0)->payload) / sizeof(Ch), MaxSize = MaxChars - 1, LenPos = MaxSize };
MaxSize = MaxChars - 1,
LenPos = MaxSize };
Ch str[MaxChars]; Ch str[MaxChars];
inline static bool Usable(SizeType len) { return (MaxSize >= len); } inline static bool Usable(SizeType len) { return (MaxSize >= len); }
@ -2607,8 +2430,7 @@ private:
data_.f.flags = kShortStringFlag; data_.f.flags = kShortStringFlag;
data_.ss.SetLength(s.length); data_.ss.SetLength(s.length);
str = data_.ss.str; str = data_.ss.str;
} } else {
else {
data_.f.flags = kCopyStringFlag; data_.f.flags = kCopyStringFlag;
data_.s.length = s.length; data_.s.length = s.length;
str = static_cast<Ch *>(allocator.Malloc((s.length + 1) * sizeof(Ch))); str = static_cast<Ch *>(allocator.Malloc((s.length + 1) * sizeof(Ch)));
@ -2672,7 +2494,9 @@ public:
\param stackCapacity Optional initial capacity of stack in bytes. \param stackCapacity Optional initial capacity of stack in bytes.
\param stackAllocator Optional allocator for allocating memory for stack. \param stackAllocator Optional allocator for allocating memory for stack.
*/ */
explicit GenericDocument(Type type, Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity, StackAllocator* stackAllocator = 0) : GenericValue<Encoding, Allocator>(type), allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, stackCapacity), parseResult_() { explicit GenericDocument(Type type, Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity, StackAllocator* stackAllocator = 0) :
GenericValue<Encoding, Allocator>(type), allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, stackCapacity), parseResult_()
{
if (!allocator_) if (!allocator_)
ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)(); ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();
} }
@ -2683,7 +2507,9 @@ public:
\param stackCapacity Optional initial capacity of stack in bytes. \param stackCapacity Optional initial capacity of stack in bytes.
\param stackAllocator Optional allocator for allocating memory for stack. \param stackAllocator Optional allocator for allocating memory for stack.
*/ */
GenericDocument(Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity, StackAllocator* stackAllocator = 0) : allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, stackCapacity), parseResult_() { GenericDocument(Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity, StackAllocator* stackAllocator = 0) :
allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, stackCapacity), parseResult_()
{
if (!allocator_) if (!allocator_)
ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)(); ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();
} }
@ -2695,7 +2521,8 @@ public:
allocator_(rhs.allocator_), allocator_(rhs.allocator_),
ownAllocator_(rhs.ownAllocator_), ownAllocator_(rhs.ownAllocator_),
stack_(std::move(rhs.stack_)), stack_(std::move(rhs.stack_)),
parseResult_(rhs.parseResult_) { parseResult_(rhs.parseResult_)
{
rhs.allocator_ = 0; rhs.allocator_ = 0;
rhs.ownAllocator_ = 0; rhs.ownAllocator_ = 0;
rhs.parseResult_ = ParseResult(); rhs.parseResult_ = ParseResult();
@ -2715,7 +2542,8 @@ public:
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS #if RAPIDJSON_HAS_CXX11_RVALUE_REFS
//! Move assignment in C++11 //! Move assignment in C++11
GenericDocument& operator=(GenericDocument&& rhs) RAPIDJSON_NOEXCEPT { GenericDocument& operator=(GenericDocument&& rhs) RAPIDJSON_NOEXCEPT
{
// The cast to ValueType is necessary here, because otherwise it would // The cast to ValueType is necessary here, because otherwise it would
// attempt to call GenericValue's templated assignment operator. // attempt to call GenericValue's templated assignment operator.
ValueType::operator=(std::forward<ValueType>(rhs)); ValueType::operator=(std::forward<ValueType>(rhs));
@ -2961,7 +2789,6 @@ private:
struct ClearStackOnExit { struct ClearStackOnExit {
explicit ClearStackOnExit(GenericDocument& d) : d_(d) {} explicit ClearStackOnExit(GenericDocument& d) : d_(d) {}
~ClearStackOnExit() { d_.ClearStack(); } ~ClearStackOnExit() { d_.ClearStack(); }
private: private:
ClearStackOnExit(const ClearStackOnExit&); ClearStackOnExit(const ClearStackOnExit&);
ClearStackOnExit& operator=(const ClearStackOnExit&); ClearStackOnExit& operator=(const ClearStackOnExit&);
@ -2970,39 +2797,17 @@ private:
// callers of the following private Handler functions // callers of the following private Handler functions
// template <typename,typename,typename> friend class GenericReader; // for parsing // template <typename,typename,typename> friend class GenericReader; // for parsing
template <typename, typename> template <typename, typename> friend class GenericValue; // for deep copying
friend class GenericValue; // for deep copying
public: public:
// Implementation of Handler // Implementation of Handler
bool Null() { bool Null() { new (stack_.template Push<ValueType>()) ValueType(); return true; }
new (stack_.template Push<ValueType>()) ValueType(); bool Bool(bool b) { new (stack_.template Push<ValueType>()) ValueType(b); return true; }
return true; bool Int(int i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; }
} bool Uint(unsigned i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; }
bool Bool(bool b) { bool Int64(int64_t i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; }
new (stack_.template Push<ValueType>()) ValueType(b); bool Uint64(uint64_t i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; }
return true; bool Double(double d) { new (stack_.template Push<ValueType>()) ValueType(d); return true; }
}
bool Int(int i) {
new (stack_.template Push<ValueType>()) ValueType(i);
return true;
}
bool Uint(unsigned i) {
new (stack_.template Push<ValueType>()) ValueType(i);
return true;
}
bool Int64(int64_t i) {
new (stack_.template Push<ValueType>()) ValueType(i);
return true;
}
bool Uint64(uint64_t i) {
new (stack_.template Push<ValueType>()) ValueType(i);
return true;
}
bool Double(double d) {
new (stack_.template Push<ValueType>()) ValueType(d);
return true;
}
bool RawNumber(const Ch* str, SizeType length, bool copy) { bool RawNumber(const Ch* str, SizeType length, bool copy) {
if (copy) if (copy)
@ -3020,10 +2825,7 @@ public:
return true; return true;
} }
bool StartObject() { bool StartObject() { new (stack_.template Push<ValueType>()) ValueType(kObjectType); return true; }
new (stack_.template Push<ValueType>()) ValueType(kObjectType);
return true;
}
bool Key(const Ch* str, SizeType length, bool copy) { return String(str, length, copy); } bool Key(const Ch* str, SizeType length, bool copy) { return String(str, length, copy); }
@ -3033,10 +2835,7 @@ public:
return true; return true;
} }
bool StartArray() { bool StartArray() { new (stack_.template Push<ValueType>()) ValueType(kArrayType); return true; }
new (stack_.template Push<ValueType>()) ValueType(kArrayType);
return true;
}
bool EndArray(SizeType elementCount) { bool EndArray(SizeType elementCount) {
ValueType* elements = stack_.template Pop<ValueType>(elementCount); ValueType* elements = stack_.template Pop<ValueType>(elementCount);
@ -3095,10 +2894,7 @@ public:
friend class GenericValue; friend class GenericValue;
GenericArray(const GenericArray& rhs) : value_(rhs.value_) {} GenericArray(const GenericArray& rhs) : value_(rhs.value_) {}
GenericArray& operator=(const GenericArray& rhs) { GenericArray& operator=(const GenericArray& rhs) { value_ = rhs.value_; return *this; }
value_ = rhs.value_;
return *this;
}
~GenericArray() {} ~GenericArray() {}
operator ValueType&() const { return value_; } operator ValueType&() const { return value_; }
@ -3109,34 +2905,14 @@ public:
ValueType& operator[](SizeType index) const { return value_[index]; } ValueType& operator[](SizeType index) const { return value_[index]; }
ValueIterator Begin() const { return value_.Begin(); } ValueIterator Begin() const { return value_.Begin(); }
ValueIterator End() const { return value_.End(); } ValueIterator End() const { return value_.End(); }
GenericArray Reserve(SizeType newCapacity, AllocatorType& allocator) const { GenericArray Reserve(SizeType newCapacity, AllocatorType &allocator) const { value_.Reserve(newCapacity, allocator); return *this; }
value_.Reserve(newCapacity, allocator); GenericArray PushBack(ValueType& value, AllocatorType& allocator) const { value_.PushBack(value, allocator); return *this; }
return *this;
}
GenericArray PushBack(ValueType& value, AllocatorType& allocator) const {
value_.PushBack(value, allocator);
return *this;
}
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS #if RAPIDJSON_HAS_CXX11_RVALUE_REFS
GenericArray PushBack(ValueType&& value, AllocatorType& allocator) const { GenericArray PushBack(ValueType&& value, AllocatorType& allocator) const { value_.PushBack(value, allocator); return *this; }
value_.PushBack(value, allocator);
return *this;
}
#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS #endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
GenericArray PushBack(StringRefType value, AllocatorType& allocator) const { GenericArray PushBack(StringRefType value, AllocatorType& allocator) const { value_.PushBack(value, allocator); return *this; }
value_.PushBack(value, allocator); template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (const GenericArray&)) PushBack(T value, AllocatorType& allocator) const { value_.PushBack(value, allocator); return *this; }
return *this; GenericArray PopBack() const { value_.PopBack(); return *this; }
}
template <typename T>
RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T>>), (const GenericArray&))
PushBack(T value, AllocatorType& allocator) const {
value_.PushBack(value, allocator);
return *this;
}
GenericArray PopBack() const {
value_.PopBack();
return *this;
}
ValueIterator Erase(ConstValueIterator pos) const { return value_.Erase(pos); } ValueIterator Erase(ConstValueIterator pos) const { return value_.Erase(pos); }
ValueIterator Erase(ConstValueIterator first, ConstValueIterator last) const { return value_.Erase(first, last); } ValueIterator Erase(ConstValueIterator first, ConstValueIterator last) const { return value_.Erase(first, last); }
@ -3174,100 +2950,52 @@ public:
friend class GenericValue; friend class GenericValue;
GenericObject(const GenericObject& rhs) : value_(rhs.value_) {} GenericObject(const GenericObject& rhs) : value_(rhs.value_) {}
GenericObject& operator=(const GenericObject& rhs) { GenericObject& operator=(const GenericObject& rhs) { value_ = rhs.value_; return *this; }
value_ = rhs.value_;
return *this;
}
~GenericObject() {} ~GenericObject() {}
operator ValueType&() const { return value_; } operator ValueType&() const { return value_; }
SizeType MemberCount() const { return value_.MemberCount(); } SizeType MemberCount() const { return value_.MemberCount(); }
SizeType MemberCapacity() const { return value_.MemberCapacity(); } SizeType MemberCapacity() const { return value_.MemberCapacity(); }
bool ObjectEmpty() const { return value_.ObjectEmpty(); } bool ObjectEmpty() const { return value_.ObjectEmpty(); }
template <typename T> template <typename T> ValueType& operator[](T* name) const { return value_[name]; }
ValueType& operator[](T* name) const { return value_[name]; } template <typename SourceAllocator> ValueType& operator[](const GenericValue<EncodingType, SourceAllocator>& name) const { return value_[name]; }
template <typename SourceAllocator>
ValueType& operator[](const GenericValue<EncodingType, SourceAllocator>& name) const { return value_[name]; }
#if RAPIDJSON_HAS_STDSTRING #if RAPIDJSON_HAS_STDSTRING
ValueType& operator[](const std::basic_string<Ch>& name) const { return value_[name]; } ValueType& operator[](const std::basic_string<Ch>& name) const { return value_[name]; }
#endif #endif
MemberIterator MemberBegin() const { return value_.MemberBegin(); } MemberIterator MemberBegin() const { return value_.MemberBegin(); }
MemberIterator MemberEnd() const { return value_.MemberEnd(); } MemberIterator MemberEnd() const { return value_.MemberEnd(); }
GenericObject MemberReserve(SizeType newCapacity, AllocatorType& allocator) const { GenericObject MemberReserve(SizeType newCapacity, AllocatorType &allocator) const { value_.MemberReserve(newCapacity, allocator); return *this; }
value_.MemberReserve(newCapacity, allocator);
return *this;
}
bool HasMember(const Ch* name) const { return value_.HasMember(name); } bool HasMember(const Ch* name) const { return value_.HasMember(name); }
#if RAPIDJSON_HAS_STDSTRING #if RAPIDJSON_HAS_STDSTRING
bool HasMember(const std::basic_string<Ch>& name) const { return value_.HasMember(name); } bool HasMember(const std::basic_string<Ch>& name) const { return value_.HasMember(name); }
#endif #endif
template <typename SourceAllocator> template <typename SourceAllocator> bool HasMember(const GenericValue<EncodingType, SourceAllocator>& name) const { return value_.HasMember(name); }
bool HasMember(const GenericValue<EncodingType, SourceAllocator>& name) const { return value_.HasMember(name); }
MemberIterator FindMember(const Ch* name) const { return value_.FindMember(name); } MemberIterator FindMember(const Ch* name) const { return value_.FindMember(name); }
template <typename SourceAllocator> template <typename SourceAllocator> MemberIterator FindMember(const GenericValue<EncodingType, SourceAllocator>& name) const { return value_.FindMember(name); }
MemberIterator FindMember(const GenericValue<EncodingType, SourceAllocator>& name) const { return value_.FindMember(name); }
#if RAPIDJSON_HAS_STDSTRING #if RAPIDJSON_HAS_STDSTRING
MemberIterator FindMember(const std::basic_string<Ch>& name) const { return value_.FindMember(name); } MemberIterator FindMember(const std::basic_string<Ch>& name) const { return value_.FindMember(name); }
#endif #endif
GenericObject AddMember(ValueType& name, ValueType& value, AllocatorType& allocator) const { GenericObject AddMember(ValueType& name, ValueType& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
value_.AddMember(name, value, allocator); GenericObject AddMember(ValueType& name, StringRefType value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
return *this;
}
GenericObject AddMember(ValueType& name, StringRefType value, AllocatorType& allocator) const {
value_.AddMember(name, value, allocator);
return *this;
}
#if RAPIDJSON_HAS_STDSTRING #if RAPIDJSON_HAS_STDSTRING
GenericObject AddMember(ValueType& name, std::basic_string<Ch>& value, AllocatorType& allocator) const { GenericObject AddMember(ValueType& name, std::basic_string<Ch>& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
value_.AddMember(name, value, allocator);
return *this;
}
#endif #endif
template <typename T> template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&)) AddMember(ValueType& name, T value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T>>), (ValueType&))
AddMember(ValueType& name, T value, AllocatorType& allocator) const {
value_.AddMember(name, value, allocator);
return *this;
}
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS #if RAPIDJSON_HAS_CXX11_RVALUE_REFS
GenericObject AddMember(ValueType&& name, ValueType&& value, AllocatorType& allocator) const { GenericObject AddMember(ValueType&& name, ValueType&& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
value_.AddMember(name, value, allocator); GenericObject AddMember(ValueType&& name, ValueType& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
return *this; GenericObject AddMember(ValueType& name, ValueType&& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
} GenericObject AddMember(StringRefType name, ValueType&& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
GenericObject AddMember(ValueType&& name, ValueType& value, AllocatorType& allocator) const {
value_.AddMember(name, value, allocator);
return *this;
}
GenericObject AddMember(ValueType& name, ValueType&& value, AllocatorType& allocator) const {
value_.AddMember(name, value, allocator);
return *this;
}
GenericObject AddMember(StringRefType name, ValueType&& value, AllocatorType& allocator) const {
value_.AddMember(name, value, allocator);
return *this;
}
#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS #endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
GenericObject AddMember(StringRefType name, ValueType& value, AllocatorType& allocator) const { GenericObject AddMember(StringRefType name, ValueType& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
value_.AddMember(name, value, allocator); GenericObject AddMember(StringRefType name, StringRefType value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
return *this; template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (GenericObject)) AddMember(StringRefType name, T value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
}
GenericObject AddMember(StringRefType name, StringRefType value, AllocatorType& allocator) const {
value_.AddMember(name, value, allocator);
return *this;
}
template <typename T>
RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T>>), (GenericObject))
AddMember(StringRefType name, T value, AllocatorType& allocator) const {
value_.AddMember(name, value, allocator);
return *this;
}
void RemoveAllMembers() { value_.RemoveAllMembers(); } void RemoveAllMembers() { value_.RemoveAllMembers(); }
bool RemoveMember(const Ch* name) const { return value_.RemoveMember(name); } bool RemoveMember(const Ch* name) const { return value_.RemoveMember(name); }
#if RAPIDJSON_HAS_STDSTRING #if RAPIDJSON_HAS_STDSTRING
bool RemoveMember(const std::basic_string<Ch>& name) const { return value_.RemoveMember(name); } bool RemoveMember(const std::basic_string<Ch>& name) const { return value_.RemoveMember(name); }
#endif #endif
template <typename SourceAllocator> template <typename SourceAllocator> bool RemoveMember(const GenericValue<EncodingType, SourceAllocator>& name) const { return value_.RemoveMember(name); }
bool RemoveMember(const GenericValue<EncodingType, SourceAllocator>& name) const { return value_.RemoveMember(name); }
MemberIterator RemoveMember(MemberIterator m) const { return value_.RemoveMember(m); } MemberIterator RemoveMember(MemberIterator m) const { return value_.RemoveMember(m); }
MemberIterator EraseMember(ConstMemberIterator pos) const { return value_.EraseMember(pos); } MemberIterator EraseMember(ConstMemberIterator pos) const { return value_.EraseMember(pos); }
MemberIterator EraseMember(ConstMemberIterator first, ConstMemberIterator last) const { return value_.EraseMember(first, last); } MemberIterator EraseMember(ConstMemberIterator first, ConstMemberIterator last) const { return value_.EraseMember(first, last); }
@ -3275,8 +3003,7 @@ public:
#if RAPIDJSON_HAS_STDSTRING #if RAPIDJSON_HAS_STDSTRING
bool EraseMember(const std::basic_string<Ch>& name) const { return EraseMember(ValueType(StringRef(name))); } bool EraseMember(const std::basic_string<Ch>& name) const { return EraseMember(ValueType(StringRef(name))); }
#endif #endif
template <typename SourceAllocator> template <typename SourceAllocator> bool EraseMember(const GenericValue<EncodingType, SourceAllocator>& name) const { return value_.EraseMember(name); }
bool EraseMember(const GenericValue<EncodingType, SourceAllocator>& name) const { return value_.EraseMember(name); }
#if RAPIDJSON_HAS_CXX11_RANGE_FOR #if RAPIDJSON_HAS_CXX11_RANGE_FOR
MemberIterator begin() const { return value_.MemberBegin(); } MemberIterator begin() const { return value_.MemberBegin(); }

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&);
@ -220,41 +182,11 @@ private:
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

@ -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];
} }

View File

@ -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) {}
@ -134,10 +133,7 @@ public:
//! 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

@ -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 {

View File

@ -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.

View File

@ -21,24 +21,15 @@ 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;

View File

@ -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,10 +217,7 @@ 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:

View File

@ -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;
} }

View File

@ -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)

View File

@ -36,14 +36,12 @@ 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;
}; };
@ -55,88 +53,58 @@ namespace internal {
// 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);
@ -155,8 +123,7 @@ 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
@ -165,17 +132,11 @@ namespace internal {
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
// 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> {};
@ -185,26 +146,29 @@ namespace internal {
// 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

@ -111,18 +111,20 @@ namespace internal {
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_);
} }
@ -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;
@ -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
} }
@ -613,8 +608,10 @@ namespace internal {
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)();
@ -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;

View File

@ -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_;
@ -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;
} }

View File

@ -70,24 +70,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 {

View File

@ -46,16 +46,10 @@ struct MemoryStream {
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

@ -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

@ -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

@ -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;
} }
} }
@ -541,7 +542,8 @@ public:
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;
@ -776,12 +778,14 @@ public:
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;
@ -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;
@ -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_;
}; };

View File

@ -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

@ -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
@ -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__)
@ -519,8 +515,7 @@ 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) \
@ -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)

View File

@ -347,8 +347,7 @@ inline const char* SkipWhitespace_SIMD(const char* p) {
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
@ -384,8 +383,7 @@ inline const char* SkipWhitespace_SIMD(const char* p, const char* end) {
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
@ -455,8 +453,7 @@ 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);
} }
@ -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,7 +701,6 @@ 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&);
@ -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) {
@ -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,7 +1059,9 @@ 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);
} }
} }
@ -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;
@ -1345,8 +1339,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;
@ -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;
@ -1440,7 +1432,6 @@ private:
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_) {}
@ -1467,7 +1458,6 @@ private:
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) {}
@ -1478,10 +1468,11 @@ private:
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());
} }
} }
@ -1757,27 +1749,16 @@ private:
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':
ParseFalse<parseFlags>(is, handler);
break;
case '"':
ParseString<parseFlags>(is, handler);
break;
case '{':
ParseObject<parseFlags>(is, handler);
break;
case '[':
ParseArray<parseFlags>(is, handler);
break;
default : default :
ParseNumber<parseFlags>(is, handler); ParseNumber<parseFlags>(is, handler);
break; break;
} }
} }
@ -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;
} }
} }

View File

@ -251,36 +251,14 @@ namespace internal {
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);
} }
@ -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() {
@ -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;
@ -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) {
@ -1072,64 +1054,38 @@ 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();
} }
} }
@ -1294,20 +1250,13 @@ namespace internal {
#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);
} }
@ -1655,13 +1602,15 @@ 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)();
@ -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;
@ -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
{ {
} }
@ -2281,8 +2233,10 @@ public:
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

@ -160,16 +160,10 @@ struct GenericStringStream {
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.
@ -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_;

View File

@ -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;
} }
@ -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;
@ -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,14 +559,8 @@ 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;
} }
@ -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;

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

@ -9,7 +9,8 @@
#include <sys/un.h> #include <sys/un.h>
#include <unistd.h> #include <unistd.h>
int GetProcessId() { int GetProcessId()
{
return ::getpid(); return ::getpid();
} }
@ -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,7 +7,8 @@
#include <assert.h> #include <assert.h>
#include <windows.h> #include <windows.h>
int GetProcessId() { int GetProcessId()
{
return (int)::GetCurrentProcessId(); return (int)::GetCurrentProcessId();
} }
@ -17,17 +18,20 @@ struct BaseConnectionWin : public BaseConnection {
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';
@ -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

@ -23,7 +23,8 @@ 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);
@ -84,7 +85,8 @@ private:
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};
@ -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()) {
@ -119,7 +122,8 @@ public:
#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()};
} }
@ -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.
@ -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

@ -15,7 +15,8 @@ class MsgQueue {
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

@ -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()) {