Added preset system for FM IF NR

This commit is contained in:
AlexandreRouma
2021-12-24 21:42:04 +01:00
parent ad2ddc6ad3
commit 07294034f6
53 changed files with 6538 additions and 5603 deletions

View File

@ -13,6 +13,13 @@ enum DeemphasisMode {
_DEEMP_MODE_COUNT _DEEMP_MODE_COUNT
}; };
enum IFNRPreset {
IFNR_PRESET_NOAA_APT,
IFNR_PRESET_VOICE,
IFNR_PRESET_NARROW_BAND,
IFNR_PRESET_BROADCAST
};
namespace demod { namespace demod {
class Demodulator { class Demodulator {
public: public:

View File

@ -22,6 +22,13 @@ std::map<DeemphasisMode, double> deempTaus = {
{ DEEMP_MODE_75US, 75e-6 } { DEEMP_MODE_75US, 75e-6 }
}; };
std::map<IFNRPreset, double> ifnrTaps = {
{ IFNR_PRESET_NOAA_APT, 9},
{ IFNR_PRESET_VOICE, 15 },
{ IFNR_PRESET_NARROW_BAND, 31 },
{ IFNR_PRESET_BROADCAST, 32 }
};
class RadioModule : public ModuleManager::Instance { class RadioModule : public ModuleManager::Instance {
public: public:
RadioModule(std::string name) { RadioModule(std::string name) {
@ -33,6 +40,10 @@ public:
deempModes.define("50us", DEEMP_MODE_50US); deempModes.define("50us", DEEMP_MODE_50US);
deempModes.define("75us", DEEMP_MODE_75US); deempModes.define("75us", DEEMP_MODE_75US);
ifnrPresets.define("NOAA APT", IFNR_PRESET_NOAA_APT);
ifnrPresets.define("Voice", IFNR_PRESET_VOICE);
ifnrPresets.define("Narrow Band", IFNR_PRESET_NARROW_BAND);
// Initialize the config if it doesn't exist // Initialize the config if it doesn't exist
bool created = false; bool created = false;
config.acquire(); config.acquire();
@ -297,6 +308,15 @@ private:
if (ImGui::Checkbox(("IF Noise Reduction##_radio_fmifnr_ena_" + _this->name).c_str(), &_this->FMIFNREnabled)) { if (ImGui::Checkbox(("IF Noise Reduction##_radio_fmifnr_ena_" + _this->name).c_str(), &_this->FMIFNREnabled)) {
_this->setFMIFNREnabled(_this->FMIFNREnabled); _this->setFMIFNREnabled(_this->FMIFNREnabled);
} }
if (_this->selectedDemodID == RADIO_DEMOD_NFM) {
if (!_this->FMIFNREnabled && _this->enabled) { style::beginDisabled(); }
ImGui::SameLine();
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
if (ImGui::Combo(("##_radio_fmifnr_ena_" + _this->name).c_str(), &_this->fmIFPresetId, _this->ifnrPresets.txt)) {
_this->setIFNRPreset(_this->ifnrPresets[_this->fmIFPresetId]);
}
if (!_this->FMIFNREnabled && _this->enabled) { style::endDisabled(); }
}
} }
// Demodulator specific menu // Demodulator specific menu
@ -347,6 +367,7 @@ private:
postProcEnabled = selectedDemod->getPostProcEnabled(); postProcEnabled = selectedDemod->getPostProcEnabled();
FMIFNRAllowed = selectedDemod->getFMIFNRAllowed(); FMIFNRAllowed = selectedDemod->getFMIFNRAllowed();
FMIFNREnabled = false; FMIFNREnabled = false;
fmIFPresetId = ifnrPresets.valueId(IFNR_PRESET_VOICE);
nbAllowed = selectedDemod->getNBAllowed(); nbAllowed = selectedDemod->getNBAllowed();
nbEnabled = false; nbEnabled = false;
nbLevel = 0.0f; nbLevel = 0.0f;
@ -365,7 +386,6 @@ private:
squelchEnabled = config.conf[name][selectedDemod->getName()]["squelchEnabled"]; squelchEnabled = config.conf[name][selectedDemod->getName()]["squelchEnabled"];
} }
if (config.conf[name][selectedDemod->getName()].contains("deempMode")) { if (config.conf[name][selectedDemod->getName()].contains("deempMode")) {
// Upgrade to the text key
if (!config.conf[name][selectedDemod->getName()]["deempMode"].is_string()) { if (!config.conf[name][selectedDemod->getName()]["deempMode"].is_string()) {
config.conf[name][selectedDemod->getName()]["deempMode"] = deempModes.key(deempId); config.conf[name][selectedDemod->getName()]["deempMode"] = deempModes.key(deempId);
} }
@ -378,6 +398,12 @@ private:
if (config.conf[name][selectedDemod->getName()].contains("FMIFNREnabled")) { if (config.conf[name][selectedDemod->getName()].contains("FMIFNREnabled")) {
FMIFNREnabled = config.conf[name][selectedDemod->getName()]["FMIFNREnabled"]; FMIFNREnabled = config.conf[name][selectedDemod->getName()]["FMIFNREnabled"];
} }
if (config.conf[name][selectedDemod->getName()].contains("fmifnrPreset")) {
std::string presetOpt = config.conf[name][selectedDemod->getName()]["fmifnrPreset"];
if (ifnrPresets.keyExists(presetOpt)) {
fmIFPresetId = ifnrPresets.keyId(presetOpt);
}
}
if (config.conf[name][selectedDemod->getName()].contains("noiseBlankerEnabled")) { if (config.conf[name][selectedDemod->getName()].contains("noiseBlankerEnabled")) {
nbEnabled = config.conf[name][selectedDemod->getName()]["noiseBlankerEnabled"]; nbEnabled = config.conf[name][selectedDemod->getName()]["noiseBlankerEnabled"];
} }
@ -401,6 +427,7 @@ private:
setBandwidth(bandwidth); setBandwidth(bandwidth);
// Configure FM IF Noise Reduction // Configure FM IF Noise Reduction
setIFNRPreset((selectedDemodID == RADIO_DEMOD_NFM) ? ifnrPresets[fmIFPresetId] : IFNR_PRESET_BROADCAST);
setFMIFNREnabled(FMIFNRAllowed ? FMIFNREnabled : false); setFMIFNREnabled(FMIFNRAllowed ? FMIFNREnabled : false);
// Configure notch // Configure notch
@ -411,7 +438,6 @@ private:
setSquelchEnabled(squelchEnabled); setSquelchEnabled(squelchEnabled);
// Configure noise blanker // Configure noise blanker
fmnr.block.setTapCount((selectedDemod->getIFSampleRate() < 100000.0f) ? 9 : 32);
nb.block.setLevel(nbLevel); nb.block.setLevel(nbLevel);
setNoiseBlankerEnabled(nbEnabled); setNoiseBlankerEnabled(nbEnabled);
@ -555,6 +581,24 @@ private:
config.release(true); config.release(true);
} }
void setIFNRPreset(IFNRPreset preset) {
// Don't save if in broadcast mode
if (preset == IFNR_PRESET_BROADCAST) {
if (!selectedDemod) { return; }
fmnr.block.setTapCount(ifnrTaps[preset]);
return;
}
fmIFPresetId = ifnrPresets.valueId(preset);
if (!selectedDemod) { return; }
fmnr.block.setTapCount(ifnrTaps[preset]);
// Save config
config.acquire();
config.conf[name][selectedDemod->getName()]["fmifnrPreset"] = ifnrPresets.key(fmIFPresetId);
config.release(true);
}
static void vfoUserChangedBandwidthHandler(double newBw, void* ctx) { static void vfoUserChangedBandwidthHandler(double newBw, void* ctx) {
RadioModule* _this = (RadioModule*)ctx; RadioModule* _this = (RadioModule*)ctx;
_this->setBandwidth(newBw); _this->setBandwidth(newBw);
@ -655,6 +699,7 @@ private:
demod::Demodulator* selectedDemod = NULL; demod::Demodulator* selectedDemod = NULL;
OptionList<std::string, DeemphasisMode> deempModes; OptionList<std::string, DeemphasisMode> deempModes;
OptionList<std::string, IFNRPreset> ifnrPresets;
double audioSampleRate = 48000.0; double audioSampleRate = 48000.0;
float minBandwidth; float minBandwidth;
@ -673,6 +718,7 @@ private:
bool FMIFNRAllowed; bool FMIFNRAllowed;
bool FMIFNREnabled = false; bool FMIFNREnabled = false;
int fmIFPresetId;
bool notchEnabled = false; bool notchEnabled = false;
float notchPos = 0; float notchPos = 0;

View File

@ -146,12 +146,10 @@ 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;
} }
@ -165,12 +163,9 @@ 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 explicit MemoryPoolAllocator(size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) : chunk_capacity_(chunkSize),
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) {
@ -197,11 +192,9 @@ 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) : MemoryPoolAllocator(void* buffer, size_t size, size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) : chunk_capacity_(chunkSize),
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;
@ -212,16 +205,13 @@ public:
shared_->refcount = 1; shared_->refcount = 1;
} }
MemoryPoolAllocator(const MemoryPoolAllocator& rhs) RAPIDJSON_NOEXCEPT : MemoryPoolAllocator(const MemoryPoolAllocator& rhs) RAPIDJSON_NOEXCEPT : chunk_capacity_(rhs.chunk_capacity_),
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();
@ -232,16 +222,13 @@ public:
} }
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS #if RAPIDJSON_HAS_CXX11_RVALUE_REFS
MemoryPoolAllocator(MemoryPoolAllocator&& rhs) RAPIDJSON_NOEXCEPT : MemoryPoolAllocator(MemoryPoolAllocator&& rhs) RAPIDJSON_NOEXCEPT : chunk_capacity_(rhs.chunk_capacity_),
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_;
@ -400,8 +387,7 @@ 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);
@ -421,31 +407,24 @@ private:
namespace internal { namespace internal {
template <typename, typename = void> template <typename, typename = void>
struct IsRefCounted : struct IsRefCounted : public FalseType {};
public FalseType
{ };
template <typename T> template <typename T>
struct IsRefCounted<T, typename internal::EnableIfCond<T::kRefCounted>::Type> : struct IsRefCounted<T, typename internal::EnableIfCond<T::kRefCounted>::Type> : public TrueType {};
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));
} }
@ -455,9 +434,7 @@ 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 : class StdAllocator : public std::allocator<T> {
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;
@ -468,27 +445,19 @@ class StdAllocator :
public: public:
typedef BaseAllocator BaseAllocatorType; typedef BaseAllocator BaseAllocatorType;
StdAllocator() RAPIDJSON_NOEXCEPT : StdAllocator() RAPIDJSON_NOEXCEPT : allocator_type(),
allocator_type(), baseAllocator_() {}
baseAllocator_()
{ }
StdAllocator(const StdAllocator& rhs) RAPIDJSON_NOEXCEPT : StdAllocator(const StdAllocator& rhs) RAPIDJSON_NOEXCEPT : allocator_type(rhs),
allocator_type(rhs), baseAllocator_(rhs.baseAllocator_) {}
baseAllocator_(rhs.baseAllocator_)
{ }
template <typename U> template <typename U>
StdAllocator(const StdAllocator<U, BaseAllocator>& rhs) RAPIDJSON_NOEXCEPT : StdAllocator(const StdAllocator<U, BaseAllocator>& rhs) RAPIDJSON_NOEXCEPT : allocator_type(rhs),
allocator_type(rhs), baseAllocator_(rhs.baseAllocator_) {}
baseAllocator_(rhs.baseAllocator_)
{ }
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS #if RAPIDJSON_HAS_CXX11_RVALUE_REFS
StdAllocator(StdAllocator&& rhs) RAPIDJSON_NOEXCEPT : StdAllocator(StdAllocator&& rhs) RAPIDJSON_NOEXCEPT : allocator_type(std::move(rhs)),
allocator_type(std::move(rhs)), baseAllocator_(std::move(rhs.baseAllocator_)) {}
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;
@ -496,13 +465,10 @@ public:
#endif #endif
/* implicit */ /* implicit */
StdAllocator(const BaseAllocator& allocator) RAPIDJSON_NOEXCEPT : StdAllocator(const BaseAllocator& allocator) RAPIDJSON_NOEXCEPT : allocator_type(),
allocator_type(), baseAllocator_(allocator) {}
baseAllocator_(allocator)
{ }
~StdAllocator() RAPIDJSON_NOEXCEPT ~StdAllocator() RAPIDJSON_NOEXCEPT {}
{ }
template <typename U> template <typename U>
struct rebind { struct rebind {
@ -521,27 +487,22 @@ 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);
} }
@ -550,48 +511,39 @@ 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);
} }
@ -600,29 +552,24 @@ 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);
} }
@ -635,38 +582,27 @@ 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> : class StdAllocator<void, BaseAllocator> : public std::allocator<void> {
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 : StdAllocator() RAPIDJSON_NOEXCEPT : allocator_type(),
allocator_type(), baseAllocator_() {}
baseAllocator_()
{ }
StdAllocator(const StdAllocator& rhs) RAPIDJSON_NOEXCEPT : StdAllocator(const StdAllocator& rhs) RAPIDJSON_NOEXCEPT : allocator_type(rhs),
allocator_type(rhs), baseAllocator_(rhs.baseAllocator_) {}
baseAllocator_(rhs.baseAllocator_)
{ }
template <typename U> template <typename U>
StdAllocator(const StdAllocator<U, BaseAllocator>& rhs) RAPIDJSON_NOEXCEPT : StdAllocator(const StdAllocator<U, BaseAllocator>& rhs) RAPIDJSON_NOEXCEPT : allocator_type(rhs),
allocator_type(rhs), baseAllocator_(rhs.baseAllocator_) {}
baseAllocator_(rhs.baseAllocator_)
{ }
/* implicit */ /* implicit */
StdAllocator(const BaseAllocator& allocator) RAPIDJSON_NOEXCEPT : StdAllocator(const BaseAllocator& allocator) RAPIDJSON_NOEXCEPT : allocator_type(),
allocator_type(), baseAllocator_(allocator) {}
baseAllocator_(allocator)
{ }
~StdAllocator() RAPIDJSON_NOEXCEPT ~StdAllocator() RAPIDJSON_NOEXCEPT {}
{ }
template <typename U> template <typename U>
struct rebind { struct rebind {

View File

@ -40,8 +40,7 @@ class CursorStreamWrapper : public GenericStreamWrapper<InputStream, Encoding> {
public: public:
typedef typename Encoding::Ch Ch; typedef typename Encoding::Ch Ch;
CursorStreamWrapper(InputStream& is): CursorStreamWrapper(InputStream& is) : GenericStreamWrapper<InputStream, Encoding>(is), line_(1), col_(0) {}
GenericStreamWrapper<InputStream, Encoding>(is), line_(1), col_(0) {}
// counting line and column number // counting line and column number
Ch Take() { Ch Take() {
@ -49,7 +48,8 @@ public:
if (ch == '\n') { if (ch == '\n') {
line_++; line_++;
col_ = 0; col_ = 0;
} else { }
else {
col_++; col_++;
} }
return ch; return ch;

View File

@ -126,8 +126,7 @@ 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
@ -186,7 +185,8 @@ 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> friend class GenericMemberIterator; template <bool, typename, typename>
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,14 +238,31 @@ 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) { ptr_ = it.ptr_; return *this; } Iterator& operator=(const NonConstIterator& it) {
ptr_ = it.ptr_;
return *this;
}
//! @name stepping //! @name stepping
//@{ //@{
Iterator& operator++(){ ++ptr_; return *this; } Iterator& operator++() {
Iterator& operator--(){ --ptr_; return *this; } ++ptr_;
Iterator operator++(int){ Iterator old(*this); ++ptr_; return old; } return *this;
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
@ -253,21 +270,34 @@ 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) { ptr_+=n; return *this; } Iterator& operator+=(DifferenceType n) {
Iterator& operator-=(DifferenceType n) { ptr_-=n; return *this; } ptr_ += n;
return *this;
}
Iterator& operator-=(DifferenceType n) {
ptr_ -= n;
return *this;
}
//@} //@}
//! @name relations //! @name relations
//@{ //@{
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_>
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_; }
#ifdef __cpp_lib_three_way_comparison #ifdef __cpp_lib_three_way_comparison
template <bool Const_> std::strong_ordering operator<=>(const GenericMemberIterator<Const_, Encoding, Allocator>& that) const { return ptr_ <=> that.ptr_; } template <bool Const_>
std::strong_ordering operator<=>(const GenericMemberIterator<Const_, Encoding, Allocator>& that) const { return ptr_ <=> that.ptr_; }
#endif #endif
//@} //@}
@ -373,7 +403,8 @@ 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), length(N-1) {} : s(str),
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
@ -502,11 +533,13 @@ template <typename T, typename Encoding = void, typename Allocator = void>
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> struct IsGenericValueImpl<T, typename Void<typename T::EncodingType>::Type, typename Void<typename T::AllocatorType>::Type> template <typename T>
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> struct IsGenericValue : IsGenericValueImpl<T>::Type {}; template <typename T>
struct IsGenericValue : IsGenericValueImpl<T>::Type {};
} // namespace internal } // namespace internal
@ -648,8 +681,10 @@ struct TypeHelper<ValueType, typename ValueType::ConstObject> {
} // namespace internal } // namespace internal
// Forward declarations // Forward declarations
template <bool, typename> class GenericArray; template <bool, typename>
template <bool, typename> class GenericObject; class GenericArray;
template <bool, typename>
class GenericObject;
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// GenericValue // GenericValue
@ -711,7 +746,6 @@ 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.
@ -753,8 +787,7 @@ 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;
@ -828,10 +861,16 @@ public:
} }
//! Constructor for double value. //! Constructor for double value.
explicit GenericValue(double d) RAPIDJSON_NOEXCEPT : data_() { data_.n.d = d; data_.f.flags = kNumberDoubleFlag; } explicit GenericValue(double d) RAPIDJSON_NOEXCEPT : data_() {
data_.n.d = d;
data_.f.flags = kNumberDoubleFlag;
}
//! Constructor for float value. //! Constructor for float value.
explicit GenericValue(float f) RAPIDJSON_NOEXCEPT : data_() { data_.n.d = static_cast<double>(f); data_.f.flags = kNumberDoubleFlag; } explicit GenericValue(float f) RAPIDJSON_NOEXCEPT : data_() {
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)); }
@ -883,16 +922,14 @@ 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();
@ -1076,7 +1113,9 @@ 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> RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>,internal::IsGenericValue<T> >), (bool)) operator==(const T& rhs) const { return *this == GenericValue(rhs); } template <typename T>
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)
@ -1090,18 +1129,22 @@ public:
//! Not-equal-to operator with arbitrary types //! Not-equal-to operator with arbitrary types
/*! \return !(*this == rhs) /*! \return !(*this == rhs)
*/ */
template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue<T>), (bool)) operator!=(const T& rhs) const { return !(*this == rhs); } template <typename T>
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> friend RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue<T>), (bool)) operator==(const T& lhs, const GenericValue& rhs) { return rhs == lhs; } template <typename T>
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> friend RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue<T>), (bool)) operator!=(const T& lhs, const GenericValue& rhs) { return !(rhs == lhs); } template <typename T>
friend RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue<T>), (bool)) operator!=(const T& lhs, const GenericValue& rhs) { return !(rhs == lhs); }
//@} //@}
#endif #endif
@ -1129,16 +1172,12 @@ 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) return (d >= 0.0) && (d < static_cast<double>((std::numeric_limits<uint64_t>::max)())) && (u == static_cast<uint64_t>(d));
&& (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)())) 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));
&& (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
} }
@ -1154,8 +1193,7 @@ 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)()) if (a < static_cast<double>(-(std::numeric_limits<float>::max)()) || 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
@ -1166,17 +1204,28 @@ public:
//!@name Null //!@name Null
//@{ //@{
GenericValue& SetNull() { this->~GenericValue(); new (this) GenericValue(); return *this; } GenericValue& SetNull() {
this->~GenericValue();
new (this) GenericValue();
return *this;
}
//@} //@}
//!@name Bool //!@name Bool
//@{ //@{
bool GetBool() const { RAPIDJSON_ASSERT(IsBool()); return data_.f.flags == kTrueFlag; } bool GetBool() const {
RAPIDJSON_ASSERT(IsBool());
return data_.f.flags == kTrueFlag;
}
//!< Set boolean value //!< Set boolean value
/*! \post IsBool() == true */ /*! \post IsBool() == true */
GenericValue& SetBool(bool b) { this->~GenericValue(); new (this) GenericValue(b); return *this; } GenericValue& SetBool(bool b) {
this->~GenericValue();
new (this) GenericValue(b);
return *this;
}
//@} //@}
@ -1185,16 +1234,29 @@ public:
//! Set this value as an empty object. //! Set this value as an empty object.
/*! \post IsObject() == true */ /*! \post IsObject() == true */
GenericValue& SetObject() { this->~GenericValue(); new (this) GenericValue(kObjectType); return *this; } GenericValue& SetObject() {
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 { RAPIDJSON_ASSERT(IsObject()); return data_.o.size; } SizeType MemberCount() const {
RAPIDJSON_ASSERT(IsObject());
return data_.o.size;
}
//! Get the capacity of object. //! Get the capacity of object.
SizeType MemberCapacity() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.capacity; } SizeType MemberCapacity() const {
RAPIDJSON_ASSERT(IsObject());
return data_.o.capacity;
}
//! Check whether the object is empty. //! Check whether the object is empty.
bool ObjectEmpty() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.size == 0; } bool ObjectEmpty() const {
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
@ -1206,12 +1268,14 @@ 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&)) operator[](T* name) { RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr<internal::IsSame<typename internal::RemoveConst<T>::Type, Ch>>), (GenericValue&))
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&)) operator[](T* name) const { return const_cast<GenericValue&>(*this)[name]; } 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]; }
//! 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
@ -1250,16 +1314,28 @@ public:
//! Const member iterator //! Const member iterator
/*! \pre IsObject() == true */ /*! \pre IsObject() == true */
ConstMemberIterator MemberBegin() const { RAPIDJSON_ASSERT(IsObject()); return ConstMemberIterator(GetMembersPointer()); } ConstMemberIterator MemberBegin() const {
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 { RAPIDJSON_ASSERT(IsObject()); return ConstMemberIterator(GetMembersPointer() + data_.o.size); } ConstMemberIterator MemberEnd() const {
RAPIDJSON_ASSERT(IsObject());
return ConstMemberIterator(GetMembersPointer() + data_.o.size);
}
//! Member iterator //! Member iterator
/*! \pre IsObject() == true */ /*! \pre IsObject() == true */
MemberIterator MemberBegin() { RAPIDJSON_ASSERT(IsObject()); return MemberIterator(GetMembersPointer()); } MemberIterator MemberBegin() {
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() { RAPIDJSON_ASSERT(IsObject()); return MemberIterator(GetMembersPointer() + data_.o.size); } MemberIterator MemberEnd() {
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.
@ -1345,7 +1421,8 @@ public:
RAPIDJSON_ASSERT(name.IsString()); RAPIDJSON_ASSERT(name.IsString());
return DoFindMember(name); return DoFindMember(name);
} }
template <typename SourceAllocator> ConstMemberIterator FindMember(const GenericValue<Encoding, SourceAllocator>& name) const { return const_cast<GenericValue&>(*this).FindMember(name); } template <typename SourceAllocator>
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.
@ -1610,10 +1687,22 @@ public:
return false; return false;
} }
Object GetObject() { RAPIDJSON_ASSERT(IsObject()); return Object(*this); } Object GetObject() {
Object GetObj() { RAPIDJSON_ASSERT(IsObject()); return Object(*this); } RAPIDJSON_ASSERT(IsObject());
ConstObject GetObject() const { RAPIDJSON_ASSERT(IsObject()); return ConstObject(*this); } return Object(*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);
}
//@} //@}
@ -1622,16 +1711,29 @@ public:
//! Set this value as an empty array. //! Set this value as an empty array.
/*! \post IsArray == true */ /*! \post IsArray == true */
GenericValue& SetArray() { this->~GenericValue(); new (this) GenericValue(kArrayType); return *this; } GenericValue& SetArray() {
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 { RAPIDJSON_ASSERT(IsArray()); return data_.a.size; } SizeType Size() const {
RAPIDJSON_ASSERT(IsArray());
return data_.a.size;
}
//! Get the capacity of array. //! Get the capacity of array.
SizeType Capacity() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.capacity; } SizeType Capacity() const {
RAPIDJSON_ASSERT(IsArray());
return data_.a.capacity;
}
//! Check whether the array is empty. //! Check whether the array is empty.
bool Empty() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size == 0; } bool Empty() const {
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.
@ -1659,10 +1761,16 @@ public:
//! Element iterator //! Element iterator
/*! \pre IsArray() == true */ /*! \pre IsArray() == true */
ValueIterator Begin() { RAPIDJSON_ASSERT(IsArray()); return GetElementsPointer(); } ValueIterator Begin() {
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() { RAPIDJSON_ASSERT(IsArray()); return GetElementsPointer() + data_.a.size; } ValueIterator End() {
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(); }
@ -1791,18 +1899,36 @@ public:
return pos; return pos;
} }
Array GetArray() { RAPIDJSON_ASSERT(IsArray()); return Array(*this); } Array GetArray() {
ConstArray GetArray() const { RAPIDJSON_ASSERT(IsArray()); return ConstArray(*this); } RAPIDJSON_ASSERT(IsArray());
return Array(*this);
}
ConstArray GetArray() const {
RAPIDJSON_ASSERT(IsArray());
return ConstArray(*this);
}
//@} //@}
//!@name Number //!@name Number
//@{ //@{
int GetInt() const { RAPIDJSON_ASSERT(data_.f.flags & kIntFlag); return data_.n.i.i; } int GetInt() const {
unsigned GetUint() const { RAPIDJSON_ASSERT(data_.f.flags & kUintFlag); return data_.n.u.u; } RAPIDJSON_ASSERT(data_.f.flags & kIntFlag);
int64_t GetInt64() const { RAPIDJSON_ASSERT(data_.f.flags & kInt64Flag); return data_.n.i64; } return data_.n.i.i;
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.
@ -1813,7 +1939,8 @@ 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); return static_cast<double>(data_.n.u64); // uint64_t -> double (may lose precision) RAPIDJSON_ASSERT((data_.f.flags & kUint64Flag) != 0);
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.
@ -1823,24 +1950,54 @@ public:
return static_cast<float>(GetDouble()); return static_cast<float>(GetDouble());
} }
GenericValue& SetInt(int i) { this->~GenericValue(); new (this) GenericValue(i); return *this; } GenericValue& SetInt(int i) {
GenericValue& SetUint(unsigned u) { this->~GenericValue(); new (this) GenericValue(u); return *this; } this->~GenericValue();
GenericValue& SetInt64(int64_t i64) { this->~GenericValue(); new (this) GenericValue(i64); return *this; } new (this) GenericValue(i);
GenericValue& SetUint64(uint64_t u64) { this->~GenericValue(); new (this) GenericValue(u64); return *this; } 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; } GenericValue& SetUint(unsigned u) {
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 { RAPIDJSON_ASSERT(IsString()); return DataString(data_); } const Ch* GetString() const {
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 { RAPIDJSON_ASSERT(IsString()); return DataStringLength(data_); } SizeType GetStringLength() const {
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.
@ -1857,7 +2014,11 @@ 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) { this->~GenericValue(); SetStringRaw(s); return *this; } GenericValue& SetString(StringRefType s) {
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.
@ -1883,7 +2044,11 @@ 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) { this->~GenericValue(); SetStringRaw(s, allocator); return *this; } GenericValue& SetString(StringRefType s, Allocator& allocator) {
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.
@ -1932,9 +2097,12 @@ public:
template <typename Handler> template <typename Handler>
bool Accept(Handler& handler) const { bool Accept(Handler& handler) const {
switch (GetType()) { switch (GetType()) {
case kNullType: return handler.Null(); case kNullType:
case kFalseType: return handler.Bool(false); return handler.Null();
case kTrueType: return handler.Bool(true); case kFalseType:
return handler.Bool(false);
case kTrueType:
return handler.Bool(true);
case kObjectType: case kObjectType:
if (RAPIDJSON_UNLIKELY(!handler.StartObject())) if (RAPIDJSON_UNLIKELY(!handler.StartObject()))
@ -1961,17 +2129,24 @@ public:
default: default:
RAPIDJSON_ASSERT(GetType() == kNumberType); RAPIDJSON_ASSERT(GetType() == kNumberType);
if (IsDouble()) return handler.Double(data_.n.d); if (IsDouble())
else if (IsInt()) return handler.Int(data_.n.i.i); return handler.Double(data_.n.d);
else if (IsUint()) return handler.Uint(data_.n.u.u); else if (IsInt())
else if (IsInt64()) return handler.Int64(data_.n.i64); return handler.Int(data_.n.i.i);
else return handler.Uint64(data_.n.u64); else if (IsUint())
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> friend class GenericValue; template <typename, typename>
template <typename, typename, typename> friend class GenericDocument; friend class GenericValue;
template <typename, typename, typename>
friend class GenericDocument;
enum { enum {
kBoolFlag = 0x0008, kBoolFlag = 0x0008,
@ -2034,7 +2209,9 @@ 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), MaxSize = MaxChars - 1, LenPos = MaxSize }; enum { MaxChars = sizeof(static_cast<Flag*>(0)->payload) / sizeof(Ch),
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); }
@ -2430,7 +2607,8 @@ 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)));
@ -2494,9 +2672,7 @@ 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) : 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_() {
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)();
} }
@ -2507,9 +2683,7 @@ 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) : GenericDocument(Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity, StackAllocator* stackAllocator = 0) : allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, stackCapacity), parseResult_() {
allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, stackCapacity), parseResult_()
{
if (!allocator_) if (!allocator_)
ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)(); ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();
} }
@ -2521,8 +2695,7 @@ 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();
@ -2542,8 +2715,7 @@ 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));
@ -2789,6 +2961,7 @@ 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&);
@ -2797,17 +2970,39 @@ 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> friend class GenericValue; // for deep copying template <typename, typename>
friend class GenericValue; // for deep copying
public: public:
// Implementation of Handler // Implementation of Handler
bool Null() { new (stack_.template Push<ValueType>()) ValueType(); return true; } bool Null() {
bool Bool(bool b) { new (stack_.template Push<ValueType>()) ValueType(b); return true; } new (stack_.template Push<ValueType>()) ValueType();
bool Int(int i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; } 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 Bool(bool b) {
bool Uint64(uint64_t i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; } new (stack_.template Push<ValueType>()) ValueType(b);
bool Double(double d) { new (stack_.template Push<ValueType>()) ValueType(d); 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 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)
@ -2825,7 +3020,10 @@ public:
return true; return true;
} }
bool StartObject() { new (stack_.template Push<ValueType>()) ValueType(kObjectType); return true; } bool StartObject() {
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); }
@ -2835,7 +3033,10 @@ public:
return true; return true;
} }
bool StartArray() { new (stack_.template Push<ValueType>()) ValueType(kArrayType); return true; } bool StartArray() {
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);
@ -2894,7 +3095,10 @@ 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) { value_ = rhs.value_; return *this; } GenericArray& operator=(const GenericArray& rhs) {
value_ = rhs.value_;
return *this;
}
~GenericArray() {} ~GenericArray() {}
operator ValueType&() const { return value_; } operator ValueType&() const { return value_; }
@ -2905,14 +3109,34 @@ 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 { value_.Reserve(newCapacity, allocator); return *this; } GenericArray Reserve(SizeType newCapacity, AllocatorType& allocator) const {
GenericArray PushBack(ValueType& value, AllocatorType& allocator) const { value_.PushBack(value, allocator); return *this; } value_.Reserve(newCapacity, allocator);
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 { value_.PushBack(value, allocator); return *this; } GenericArray PushBack(ValueType&& value, AllocatorType& allocator) const {
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 { value_.PushBack(value, allocator); return *this; } GenericArray PushBack(StringRefType value, AllocatorType& allocator) const {
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; } value_.PushBack(value, allocator);
GenericArray PopBack() const { value_.PopBack(); return *this; } 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); }
@ -2950,52 +3174,100 @@ 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) { value_ = rhs.value_; return *this; } GenericObject& operator=(const GenericObject& rhs) {
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> ValueType& operator[](T* name) const { return value_[name]; } template <typename T>
template <typename SourceAllocator> ValueType& operator[](const GenericValue<EncodingType, SourceAllocator>& 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]; }
#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 { value_.MemberReserve(newCapacity, allocator); return *this; } GenericObject MemberReserve(SizeType newCapacity, AllocatorType& allocator) const {
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> bool HasMember(const GenericValue<EncodingType, SourceAllocator>& name) const { return value_.HasMember(name); } template <typename SourceAllocator>
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> MemberIterator FindMember(const GenericValue<EncodingType, SourceAllocator>& name) const { return value_.FindMember(name); } template <typename SourceAllocator>
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 { value_.AddMember(name, value, allocator); return *this; } GenericObject AddMember(ValueType& name, ValueType& value, AllocatorType& allocator) const {
GenericObject AddMember(ValueType& name, StringRefType value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } value_.AddMember(name, value, allocator);
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 { value_.AddMember(name, value, allocator); return *this; } GenericObject AddMember(ValueType& name, std::basic_string<Ch>& value, AllocatorType& allocator) const {
value_.AddMember(name, value, allocator);
return *this;
}
#endif #endif
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; } 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;
}
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS #if RAPIDJSON_HAS_CXX11_RVALUE_REFS
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 {
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(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 { value_.AddMember(name, value, allocator); return *this; } GenericObject AddMember(StringRefType name, ValueType& value, AllocatorType& allocator) const {
GenericObject AddMember(StringRefType name, StringRefType value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } value_.AddMember(name, value, allocator);
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; } 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> bool RemoveMember(const GenericValue<EncodingType, SourceAllocator>& name) const { return value_.RemoveMember(name); } template <typename SourceAllocator>
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); }
@ -3003,7 +3275,8 @@ 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> bool EraseMember(const GenericValue<EncodingType, SourceAllocator>& name) const { return value_.EraseMember(name); } template <typename SourceAllocator>
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,6 +38,7 @@ 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;
@ -46,14 +47,24 @@ public:
} }
Ch Peek() const { return current_; } Ch Peek() const { return current_; }
Ch Take() { Ch c = current_; current_ = Encoding::Take(is_); return c; } Ch Take() {
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() { RAPIDJSON_ASSERT(false); return 0; } Ch* PutBegin() {
size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } RAPIDJSON_ASSERT(false);
return 0;
}
size_t PutEnd(Ch*) {
RAPIDJSON_ASSERT(false);
return 0;
}
private: private:
EncodedInputStream(const EncodedInputStream&); EncodedInputStream(const EncodedInputStream&);
@ -99,6 +110,7 @@ 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;
@ -111,11 +123,26 @@ public:
void Flush() { os_.Flush(); } void Flush() { os_.Flush(); }
// Not implemented // Not implemented
Ch Peek() const { RAPIDJSON_ASSERT(false); return 0;} Ch Peek() const {
Ch Take() { RAPIDJSON_ASSERT(false); return 0;} RAPIDJSON_ASSERT(false);
size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; } return 0;
Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } }
size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } Ch Take() {
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&);
@ -134,6 +161,7 @@ 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;
@ -154,14 +182,24 @@ public:
bool HasBOM() const { return hasBOM_; } bool HasBOM() const { return hasBOM_; }
Ch Peek() const { return current_; } Ch Peek() const { return current_; }
Ch Take() { Ch c = current_; current_ = takeFunc_(*is_); return c; } Ch Take() {
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() { RAPIDJSON_ASSERT(false); return 0; } Ch* PutBegin() {
size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } RAPIDJSON_ASSERT(false);
return 0;
}
size_t PutEnd(Ch*) {
RAPIDJSON_ASSERT(false);
return 0;
}
private: private:
AutoUTFInputStream(const AutoUTFInputStream&); AutoUTFInputStream(const AutoUTFInputStream&);
@ -182,11 +220,41 @@ 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) { type_ = kUTF32BE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); } if (bom == 0xFFFE0000) {
else if (bom == 0x0000FEFF) { type_ = kUTF32LE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); } type_ = kUTF32BE;
else if ((bom & 0xFFFF) == 0xFFFE) { type_ = kUTF16BE; hasBOM_ = true; is_->Take(); is_->Take(); } hasBOM_ = true;
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();
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
@ -202,12 +270,23 @@ 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: type_ = kUTF32BE; break; case 0x08:
case 0x0A: type_ = kUTF16BE; break; type_ = kUTF32BE;
case 0x01: type_ = kUTF32LE; break; break;
case 0x05: type_ = kUTF16LE; break; case 0x0A:
case 0x0F: type_ = kUTF8; break; type_ = kUTF16BE;
default: break; // Use type defined by user. break;
case 0x01:
type_ = kUTF32LE;
break;
case 0x05:
type_ = kUTF16LE;
break;
case 0x0F:
type_ = kUTF8;
break;
default:
break; // Use type defined by user.
} }
} }
@ -232,6 +311,7 @@ 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;
@ -261,11 +341,26 @@ public:
void Flush() { os_->Flush(); } void Flush() { os_->Flush(); }
// Not implemented // Not implemented
Ch Peek() const { RAPIDJSON_ASSERT(false); return 0;} Ch Peek() const {
Ch Take() { RAPIDJSON_ASSERT(false); return 0;} RAPIDJSON_ASSERT(false);
size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; } return 0;
Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } }
size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } Ch Take() {
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,9 +144,13 @@ 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() c = is.Take(); *codepoint = (*codepoint << 6) | (static_cast<unsigned char>(c) & 0x3Fu) #define RAPIDJSON_COPY() \
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() RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x70) #define RAPIDJSON_TAIL() \
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);
@ -156,19 +160,48 @@ 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: RAPIDJSON_TAIL(); return result; case 2:
case 3: RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result; RAPIDJSON_TAIL();
case 4: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x50); RAPIDJSON_TAIL(); return result; return result;
case 5: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x10); RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result; case 3:
case 6: RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result; RAPIDJSON_TAIL();
case 10: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x20); RAPIDJSON_TAIL(); return result; RAPIDJSON_TAIL();
case 11: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x60); RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result; return result;
default: return false; case 4:
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
@ -179,7 +212,9 @@ 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() RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x70) #define RAPIDJSON_TAIL() \
RAPIDJSON_COPY(); \
RAPIDJSON_TRANS(0x70)
Ch c; Ch c;
RAPIDJSON_COPY(); RAPIDJSON_COPY();
if (!(c & 0x80)) if (!(c & 0x80))
@ -187,14 +222,42 @@ struct UTF8 {
bool result = true; bool result = true;
switch (GetRange(static_cast<unsigned char>(c))) { switch (GetRange(static_cast<unsigned char>(c))) {
case 2: RAPIDJSON_TAIL(); return result; case 2:
case 3: RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result; RAPIDJSON_TAIL();
case 4: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x50); RAPIDJSON_TAIL(); return result; return result;
case 5: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x10); RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result; case 3:
case 6: RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result; RAPIDJSON_TAIL();
case 10: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x20); RAPIDJSON_TAIL(); return result; RAPIDJSON_TAIL();
case 11: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x60); RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result; return result;
default: return false; case 4:
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
@ -205,16 +268,262 @@ 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,
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,
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,33 +35,52 @@ 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: return RAPIDJSON_ERROR_STRING("No error."); case kParseErrorNone:
return RAPIDJSON_ERROR_STRING("No error.");
case kParseErrorDocumentEmpty: return RAPIDJSON_ERROR_STRING("The document is empty."); case kParseErrorDocumentEmpty:
case kParseErrorDocumentRootNotSingular: return RAPIDJSON_ERROR_STRING("The document root must not be followed by other values."); 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 kParseErrorValueInvalid: return RAPIDJSON_ERROR_STRING("Invalid value."); case kParseErrorValueInvalid:
return RAPIDJSON_ERROR_STRING("Invalid value.");
case kParseErrorObjectMissName: return RAPIDJSON_ERROR_STRING("Missing a name for object member."); case kParseErrorObjectMissName:
case kParseErrorObjectMissColon: return RAPIDJSON_ERROR_STRING("Missing a colon after a name of object member."); return RAPIDJSON_ERROR_STRING("Missing a name for object member.");
case kParseErrorObjectMissCommaOrCurlyBracket: return RAPIDJSON_ERROR_STRING("Missing a comma or '}' after an object member."); case kParseErrorObjectMissColon:
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: return RAPIDJSON_ERROR_STRING("Missing a comma or ']' after an array element."); case kParseErrorArrayMissCommaOrSquareBracket:
return RAPIDJSON_ERROR_STRING("Missing a comma or ']' after an array element.");
case kParseErrorStringUnicodeEscapeInvalidHex: return RAPIDJSON_ERROR_STRING("Incorrect hex digit after \\u escape in string."); case kParseErrorStringUnicodeEscapeInvalidHex:
case kParseErrorStringUnicodeSurrogateInvalid: return RAPIDJSON_ERROR_STRING("The surrogate pair in string is invalid."); return RAPIDJSON_ERROR_STRING("Incorrect hex digit after \\u escape in string.");
case kParseErrorStringEscapeInvalid: return RAPIDJSON_ERROR_STRING("Invalid escape character in string."); case kParseErrorStringUnicodeSurrogateInvalid:
case kParseErrorStringMissQuotationMark: return RAPIDJSON_ERROR_STRING("Missing a closing quotation mark in string."); return RAPIDJSON_ERROR_STRING("The surrogate pair in string is invalid.");
case kParseErrorStringInvalidEncoding: return RAPIDJSON_ERROR_STRING("Invalid encoding in string."); case kParseErrorStringEscapeInvalid:
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: return RAPIDJSON_ERROR_STRING("Number too big to be stored in double."); case kParseErrorNumberTooBig:
case kParseErrorNumberMissFraction: return RAPIDJSON_ERROR_STRING("Miss fraction part in number."); return RAPIDJSON_ERROR_STRING("Number too big to be stored in double.");
case kParseErrorNumberMissExponent: return RAPIDJSON_ERROR_STRING("Miss exponent in number."); case kParseErrorNumberMissFraction:
return RAPIDJSON_ERROR_STRING("Miss fraction part in number.");
case kParseErrorNumberMissExponent:
return RAPIDJSON_ERROR_STRING("Miss exponent in number.");
case kParseErrorTermination: return RAPIDJSON_ERROR_STRING("Terminate parsing due to Handler error."); case kParseErrorTermination:
case kParseErrorUnspecificSyntaxError: return RAPIDJSON_ERROR_STRING("Unspecific syntax error."); return RAPIDJSON_ERROR_STRING("Terminate parsing due to Handler error.");
case kParseErrorUnspecificSyntaxError:
return RAPIDJSON_ERROR_STRING("Unspecific syntax error.");
default: return RAPIDJSON_ERROR_STRING("Unknown error."); default:
return RAPIDJSON_ERROR_STRING("Unknown error.");
} }
} }
@ -75,41 +94,69 @@ 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: return RAPIDJSON_ERROR_STRING("One or more validation errors have occurred"); case kValidateErrors:
case kValidateErrorNone: return RAPIDJSON_ERROR_STRING("No error."); return RAPIDJSON_ERROR_STRING("One or more validation errors have occurred");
case kValidateErrorNone:
return RAPIDJSON_ERROR_STRING("No error.");
case kValidateErrorMultipleOf: return RAPIDJSON_ERROR_STRING("Number '%actual' is not a multiple of the 'multipleOf' value '%expected'."); case kValidateErrorMultipleOf:
case kValidateErrorMaximum: return RAPIDJSON_ERROR_STRING("Number '%actual' is greater than the 'maximum' value '%expected'."); return RAPIDJSON_ERROR_STRING("Number '%actual' is not a multiple of the 'multipleOf' value '%expected'.");
case kValidateErrorExclusiveMaximum: return RAPIDJSON_ERROR_STRING("Number '%actual' is greater than or equal to the 'exclusiveMaximum' value '%expected'."); case kValidateErrorMaximum:
case kValidateErrorMinimum: return RAPIDJSON_ERROR_STRING("Number '%actual' is less than the 'minimum' value '%expected'."); return RAPIDJSON_ERROR_STRING("Number '%actual' is greater than the 'maximum' value '%expected'.");
case kValidateErrorExclusiveMinimum: return RAPIDJSON_ERROR_STRING("Number '%actual' is less than or equal to the 'exclusiveMinimum' value '%expected'."); case kValidateErrorExclusiveMaximum:
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: return RAPIDJSON_ERROR_STRING("String '%actual' is longer than the 'maxLength' value '%expected'."); case kValidateErrorMaxLength:
case kValidateErrorMinLength: return RAPIDJSON_ERROR_STRING("String '%actual' is shorter than the 'minLength' value '%expected'."); return RAPIDJSON_ERROR_STRING("String '%actual' is longer than the 'maxLength' value '%expected'.");
case kValidateErrorPattern: return RAPIDJSON_ERROR_STRING("String '%actual' does not match the 'pattern' regular expression."); case kValidateErrorMinLength:
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: return RAPIDJSON_ERROR_STRING("Array of length '%actual' is longer than the 'maxItems' value '%expected'."); case kValidateErrorMaxItems:
case kValidateErrorMinItems: return RAPIDJSON_ERROR_STRING("Array of length '%actual' is shorter than the 'minItems' value '%expected'."); return RAPIDJSON_ERROR_STRING("Array of length '%actual' is longer than the 'maxItems' value '%expected'.");
case kValidateErrorUniqueItems: return RAPIDJSON_ERROR_STRING("Array has duplicate items at indices '%duplicates' but 'uniqueItems' is true."); case kValidateErrorMinItems:
case kValidateErrorAdditionalItems: return RAPIDJSON_ERROR_STRING("Array has an additional item at index '%disallowed' that is not allowed by the schema."); return RAPIDJSON_ERROR_STRING("Array of length '%actual' is shorter than the 'minItems' value '%expected'.");
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: return RAPIDJSON_ERROR_STRING("Object has '%actual' members which is more than 'maxProperties' value '%expected'."); case kValidateErrorMaxProperties:
case kValidateErrorMinProperties: return RAPIDJSON_ERROR_STRING("Object has '%actual' members which is less than 'minProperties' value '%expected'."); return RAPIDJSON_ERROR_STRING("Object has '%actual' members which is more than 'maxProperties' value '%expected'.");
case kValidateErrorRequired: return RAPIDJSON_ERROR_STRING("Object is missing the following members required by the schema: '%missing'."); case kValidateErrorMinProperties:
case kValidateErrorAdditionalProperties: return RAPIDJSON_ERROR_STRING("Object has an additional member '%disallowed' that is not allowed by the schema."); return RAPIDJSON_ERROR_STRING("Object has '%actual' members which is less than 'minProperties' value '%expected'.");
case kValidateErrorPatternProperties: return RAPIDJSON_ERROR_STRING("Object has 'patternProperties' that are not allowed by the schema."); case kValidateErrorRequired:
case kValidateErrorDependencies: return RAPIDJSON_ERROR_STRING("Object has missing property or schema dependencies, refer to following errors."); return RAPIDJSON_ERROR_STRING("Object is missing the following members required by the schema: '%missing'.");
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: return RAPIDJSON_ERROR_STRING("Property has a value that is not one of its allowed enumerated values."); case kValidateErrorEnum:
case kValidateErrorType: return RAPIDJSON_ERROR_STRING("Property has a type '%actual' that is not in the following list: '%expected'."); 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 kValidateErrorOneOf: return RAPIDJSON_ERROR_STRING("Property did not match any of the sub-schemas specified by 'oneOf', refer to following errors."); case kValidateErrorOneOf:
case kValidateErrorOneOfMatch: return RAPIDJSON_ERROR_STRING("Property matched more than one of the sub-schemas specified by 'oneOf'."); return RAPIDJSON_ERROR_STRING("Property did not match any of the sub-schemas specified by 'oneOf', refer to following errors.");
case kValidateErrorAllOf: return RAPIDJSON_ERROR_STRING("Property did not match all of the sub-schemas specified by 'allOf', refer to following errors."); case kValidateErrorOneOfMatch:
case kValidateErrorAnyOf: return RAPIDJSON_ERROR_STRING("Property did not match any of the sub-schemas specified by 'anyOf', refer to following errors."); return RAPIDJSON_ERROR_STRING("Property matched more than one of the sub-schemas specified by 'oneOf'.");
case kValidateErrorNot: return RAPIDJSON_ERROR_STRING("Property matched the sub-schema specified by 'not'."); case kValidateErrorAllOf:
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: return RAPIDJSON_ERROR_STRING("Unknown error."); default:
return RAPIDJSON_ERROR_STRING("Unknown error.");
} }
} }

View File

@ -106,6 +106,7 @@ 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) {}
@ -133,7 +134,10 @@ 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) { code_ = code; offset_ = offset; } void Set(ParseErrorCode code, size_t offset = 0) {
code_ = code;
offset_ = offset;
}
private: private:
ParseErrorCode code_; ParseErrorCode code_;

View File

@ -48,14 +48,24 @@ public:
} }
Ch Peek() const { return *current_; } Ch Peek() const { return *current_; }
Ch Take() { Ch c = *current_; Read(); return c; } Ch Take() {
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() { RAPIDJSON_ASSERT(false); return 0; } Ch* PutBegin() {
size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } RAPIDJSON_ASSERT(false);
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,11 +72,26 @@ public:
} }
// Not implemented // Not implemented
char Peek() const { RAPIDJSON_ASSERT(false); return 0; } char Peek() const {
char Take() { RAPIDJSON_ASSERT(false); return 0; } RAPIDJSON_ASSERT(false);
size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; } return 0;
char* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } }
size_t PutEnd(char*) { RAPIDJSON_ASSERT(false); return 0; } char Take() {
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,15 +21,24 @@ RAPIDJSON_NAMESPACE_BEGIN
// encodings.h // encodings.h
template<typename CharType> struct UTF8; template <typename CharType>
template<typename CharType> struct UTF16; struct UTF8;
template<typename CharType> struct UTF16BE; template <typename CharType>
template<typename CharType> struct UTF16LE; struct UTF16;
template<typename CharType> struct UTF32; template <typename CharType>
template<typename CharType> struct UTF32BE; struct UTF16BE;
template<typename CharType> struct UTF32LE; template <typename CharType>
template<typename CharType> struct ASCII; struct UTF16LE;
template<typename CharType> struct AutoUTF; template <typename CharType>
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,8 +52,7 @@ public:
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));
@ -188,8 +187,16 @@ public:
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) { a = &rhs; b = this; ret = true; } if (cmp < 0) {
else { a = this; b = &rhs; ret = false; } a = &rhs;
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++) {
@ -217,7 +224,10 @@ public:
} }
size_t GetCount() const { return count_; } size_t GetCount() const { return count_; }
Type GetDigit(size_t index) const { RAPIDJSON_ASSERT(index < count_); return digits_[index]; } Type GetDigit(size_t index) const {
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,8 +138,7 @@ struct DiyFp {
// Overflow. // Overflow.
return std::numeric_limits<double>::infinity(); return std::numeric_limits<double>::infinity();
} }
const uint64_t be = (e == kDpDenormalExponent && (f & kDpHiddenBit) == 0) ? 0 : const uint64_t be = (e == kDpDenormalExponent && (f & kDpHiddenBit) == 0) ? 0 : static_cast<uint64_t>(e + kDpExponentBias);
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,15 +69,42 @@ inline void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buff
while (kappa > 0) { while (kappa > 0) {
uint32_t d = 0; uint32_t d = 0;
switch (kappa) { switch (kappa) {
case 9: d = p1 / 100000000; p1 %= 100000000; break; case 9:
case 8: d = p1 / 10000000; p1 %= 10000000; break; d = p1 / 100000000;
case 7: d = p1 / 1000000; p1 %= 1000000; break; p1 %= 100000000;
case 6: d = p1 / 100000; p1 %= 100000; break; break;
case 5: d = p1 / 10000; p1 %= 10000; break; case 8:
case 4: d = p1 / 1000; p1 %= 1000; break; d = p1 / 10000000;
case 3: d = p1 / 100; p1 %= 100; break; p1 %= 10000000;
case 2: d = p1 / 10; p1 %= 10; break; break;
case 1: d = p1; p1 = 0; break; case 7:
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,12 +36,14 @@ 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> struct Void { typedef void Type; }; template <typename T>
struct Void { typedef void Type; };
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// BoolType, TrueType, FalseType // BoolType, TrueType, FalseType
// //
template <bool Cond> struct BoolType { template <bool Cond>
struct BoolType {
static const bool Value = Cond; static const bool Value = Cond;
typedef BoolType Type; typedef BoolType Type;
}; };
@ -53,58 +55,88 @@ typedef BoolType<false> FalseType;
// SelectIf, BoolExpr, NotExpr, AndExpr, OrExpr // SelectIf, BoolExpr, NotExpr, AndExpr, OrExpr
// //
template <bool C> struct SelectIfImpl { template <typename T1, typename T2> struct Apply { typedef T1 Type; }; }; template <bool C>
template <> struct SelectIfImpl<false> { template <typename T1, typename T2> struct Apply { typedef T2 Type; }; }; struct SelectIfImpl {
template <bool C, typename T1, typename T2> struct SelectIfCond : SelectIfImpl<C>::template Apply<T1,T2> {}; template <typename T1, typename T2>
template <typename C, typename T1, typename T2> struct SelectIf : SelectIfCond<C::Value, T1, T2> {}; struct Apply { typedef T1 Type; };
};
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> struct AndExprCond : FalseType {}; template <bool Cond1, bool Cond2>
template <> struct AndExprCond<true, true> : TrueType {}; struct AndExprCond : FalseType {};
template <bool Cond1, bool Cond2> struct OrExprCond : TrueType {}; template <>
template <> struct OrExprCond<false, false> : FalseType {}; struct AndExprCond<true, true> : TrueType {};
template <bool Cond1, bool Cond2>
struct OrExprCond : TrueType {};
template <>
struct OrExprCond<false, false> : FalseType {};
template <typename C> struct BoolExpr : SelectIf<C,TrueType,FalseType>::Type {}; template <typename C>
template <typename C> struct NotExpr : SelectIf<C,FalseType,TrueType>::Type {}; struct BoolExpr : SelectIf<C, TrueType, FalseType>::Type {};
template <typename C1, typename C2> struct AndExpr : AndExprCond<C1::Value, C2::Value>::Type {}; template <typename C>
template <typename C1, typename C2> struct OrExpr : OrExprCond<C1::Value, C2::Value>::Type {}; struct NotExpr : SelectIf<C, FalseType, TrueType>::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> struct AddConst { typedef const T Type; }; template <typename T>
template <bool Constify, typename T> struct MaybeAddConst : SelectIfCond<Constify, const T, T> {}; struct AddConst { typedef const T Type; };
template <typename T> struct RemoveConst { typedef T Type; }; template <bool Constify, typename T>
template <typename T> struct RemoveConst<const T> { typedef T Type; }; struct MaybeAddConst : SelectIfCond<Constify, const T, T> {};
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> struct IsSame : FalseType {}; template <typename T, typename U>
template <typename T> struct IsSame<T, T> : TrueType {}; struct IsSame : FalseType {};
template <typename T>
struct IsSame<T, T> : TrueType {};
template <typename T> struct IsConst : FalseType {}; template <typename T>
template <typename T> struct IsConst<const T> : TrueType {}; struct IsConst : FalseType {};
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> struct IsPointer : FalseType {}; template <typename T>
template <typename T> struct IsPointer<T*> : TrueType {}; struct IsPointer : FalseType {};
template <typename T>
struct IsPointer<T*> : TrueType {};
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// IsBaseOf // IsBaseOf
// //
#if RAPIDJSON_HAS_CXX11_TYPETRAITS #if RAPIDJSON_HAS_CXX11_TYPETRAITS
template <typename B, typename D> struct IsBaseOf template <typename B, typename D>
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> struct IsBaseOfImpl { template <typename B, typename D>
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);
@ -123,7 +155,8 @@ template<typename B, typename D> struct IsBaseOfImpl {
enum { Value = (sizeof(Check(Host(), 0)) == sizeof(Yes)) }; enum { Value = (sizeof(Check(Host(), 0)) == sizeof(Yes)) };
}; };
template <typename B, typename D> struct IsBaseOf template <typename B, typename D>
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
@ -132,11 +165,17 @@ template <typename B, typename D> struct IsBaseOf
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
// EnableIf / DisableIf // EnableIf / DisableIf
// //
template <bool Condition, typename T = void> struct EnableIfCond { typedef T Type; }; template <bool Condition, typename T = void>
template <typename T> struct EnableIfCond<false, T> { /* empty */ }; struct EnableIfCond { typedef T Type; };
template <typename T>
struct EnableIfCond<false, T> { /* empty */
};
template <bool Condition, typename T = void> struct DisableIfCond { typedef T Type; }; template <bool Condition, typename T = void>
template <typename T> struct DisableIfCond<true, T> { /* empty */ }; struct DisableIfCond { typedef T Type; };
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> {};
@ -146,29 +185,26 @@ struct DisableIf : DisableIfCond<Condition::Value, T> {};
// SFINAE helpers // SFINAE helpers
struct SfinaeTag {}; struct SfinaeTag {};
template <typename T> struct RemoveSfinaeTag; template <typename T>
template <typename T> struct RemoveSfinaeTag<SfinaeTag&(*)(T)> { typedef T Type; }; struct RemoveSfinaeTag;
template <typename T>
struct RemoveSfinaeTag<SfinaeTag& (*)(T)> { typedef T Type; };
#define RAPIDJSON_REMOVEFPTR_(type) \ #define RAPIDJSON_REMOVEFPTR_(type) \
typename ::RAPIDJSON_NAMESPACE::internal::RemoveSfinaeTag \ typename ::RAPIDJSON_NAMESPACE::internal::RemoveSfinaeTag<::RAPIDJSON_NAMESPACE::internal::SfinaeTag&(*)type>::Type
< ::RAPIDJSON_NAMESPACE::internal::SfinaeTag&(*) type>::Type
#define RAPIDJSON_ENABLEIF(cond) \ #define RAPIDJSON_ENABLEIF(cond) \
typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \ typename ::RAPIDJSON_NAMESPACE::internal::EnableIf<RAPIDJSON_REMOVEFPTR_(cond)>::Type* = NULL
<RAPIDJSON_REMOVEFPTR_(cond)>::Type * = NULL
#define RAPIDJSON_DISABLEIF(cond) \ #define RAPIDJSON_DISABLEIF(cond) \
typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \ typename ::RAPIDJSON_NAMESPACE::internal::DisableIf<RAPIDJSON_REMOVEFPTR_(cond)>::Type* = NULL
<RAPIDJSON_REMOVEFPTR_(cond)>::Type * = NULL
#define RAPIDJSON_ENABLEIF_RETURN(cond, returntype) \ #define RAPIDJSON_ENABLEIF_RETURN(cond, returntype) \
typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \ typename ::RAPIDJSON_NAMESPACE::internal::EnableIf<RAPIDJSON_REMOVEFPTR_(cond), \
<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 \ typename ::RAPIDJSON_NAMESPACE::internal::DisableIf<RAPIDJSON_REMOVEFPTR_(cond), \
<RAPIDJSON_REMOVEFPTR_(cond), \
RAPIDJSON_REMOVEFPTR_(returntype)>::Type RAPIDJSON_REMOVEFPTR_(returntype)>::Type
} // namespace internal } // namespace internal

View File

@ -111,20 +111,18 @@ class GenericRegex {
public: public:
typedef Encoding EncodingType; typedef Encoding EncodingType;
typedef typename Encoding::Ch Ch; typedef typename Encoding::Ch Ch;
template <typename, typename> friend class GenericRegexSearch; template <typename, typename>
friend class GenericRegexSearch;
GenericRegex(const Ch* source, Allocator* allocator = 0) : GenericRegex(const Ch* source, Allocator* allocator = 0) : ownAllocator_(allocator ? 0 : RAPIDJSON_NEW(Allocator)()), allocator_(allocator ? allocator : ownAllocator_),
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_);
} }
@ -244,8 +242,7 @@ private:
return; return;
break; break;
case '{': case '{': {
{
unsigned n, m; unsigned n, m;
if (!ParseUnsigned(ds, &n)) if (!ParseUnsigned(ds, &n))
return; return;
@ -263,16 +260,14 @@ private:
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;
@ -529,8 +524,7 @@ private:
// 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;
@ -576,12 +570,23 @@ private:
case '{': case '{':
case '}': case '}':
case '\\': case '\\':
*escapedCodepoint = codepoint; return true; *escapedCodepoint = codepoint;
case 'f': *escapedCodepoint = 0x000C; return true; return true;
case 'n': *escapedCodepoint = 0x000A; return true; case 'f':
case 'r': *escapedCodepoint = 0x000D; return true; *escapedCodepoint = 0x000C;
case 't': *escapedCodepoint = 0x0009; return true; return true;
case 'v': *escapedCodepoint = 0x000B; return true; case 'n':
*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
} }
@ -608,10 +613,8 @@ public:
typedef typename RegexType::EncodingType Encoding; typedef typename RegexType::EncodingType Encoding;
typedef typename Encoding::Ch Ch; typedef typename Encoding::Ch Ch;
GenericRegexSearch(const RegexType& regex, Allocator* allocator = 0) : GenericRegexSearch(const RegexType& regex, Allocator* allocator = 0) : regex_(regex), allocator_(allocator), ownAllocator_(0),
regex_(regex), allocator_(allocator), ownAllocator_(0), state0_(allocator, 0), state1_(allocator, 0), stateSet_() {
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)();
@ -668,8 +671,7 @@ private:
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,8 +48,7 @@ public:
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;
@ -65,8 +64,7 @@ public:
#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_;
@ -187,7 +185,8 @@ private:
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,14 +70,24 @@ public:
} }
Ch Peek() const { return *current_; } Ch Peek() const { return *current_; }
Ch Take() { Ch c = *current_; Read(); return c; } Ch Take() {
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() { RAPIDJSON_ASSERT(false); return 0; } Ch* PutBegin() {
size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } RAPIDJSON_ASSERT(false);
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,10 +46,16 @@ 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() { RAPIDJSON_ASSERT(false); return 0; } Ch* PutBegin() {
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*) { RAPIDJSON_ASSERT(false); 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

@ -287,8 +287,7 @@ 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,11 +56,26 @@ public:
} }
// Not implemented // Not implemented
char Peek() const { RAPIDJSON_ASSERT(false); return 0; } char Peek() const {
char Take() { RAPIDJSON_ASSERT(false); return 0; } RAPIDJSON_ASSERT(false);
size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; } return 0;
char* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } }
size_t PutEnd(char*) { RAPIDJSON_ASSERT(false); return 0; } char Take() {
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,8 +371,7 @@ 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;
} }
} }
@ -542,8 +541,7 @@ 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;
@ -778,14 +776,12 @@ 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;
@ -933,8 +929,10 @@ private:
if (c == '~') { if (c == '~') {
if (i < length) { if (i < length) {
c = source[i]; c = source[i];
if (c == '0') c = '~'; if (c == '0')
else if (c == '1') c = '/'; c = '~';
else if (c == '1')
c = '/';
else { else {
parseErrorCode_ = kPointerParseErrorInvalidEscape; parseErrorCode_ = kPointerParseErrorInvalidEscape;
goto error; goto error;
@ -1059,9 +1057,12 @@ 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') c = static_cast<Ch>(c + h - '0'); if (h >= '0' && h <= '9')
else if (h >= 'A' && h <= 'F') c = static_cast<Ch>(c + h - 'A' + 10); 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')
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;
@ -1093,6 +1094,7 @@ 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,16 +55,13 @@ 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) : explicit PrettyWriter(OutputStream& os, StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) : Base(os, allocator, levelDepth), indentChar_(' '), indentCharCount_(4), formatOptions_(kFormatDefault) {}
Base(os, allocator, levelDepth), indentChar_(' '), indentCharCount_(4), formatOptions_(kFormatDefault) {}
explicit PrettyWriter(StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) : explicit PrettyWriter(StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) : Base(allocator, levelDepth), indentChar_(' '), indentCharCount_(4), formatOptions_(kFormatDefault) {}
Base(allocator, levelDepth), indentChar_(' '), indentCharCount_(4), formatOptions_(kFormatDefault) {}
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS #if RAPIDJSON_HAS_CXX11_RVALUE_REFS
PrettyWriter(PrettyWriter&& rhs) : PrettyWriter(PrettyWriter&& rhs) : Base(std::forward<PrettyWriter>(rhs)), indentChar_(rhs.indentChar_), indentCharCount_(rhs.indentCharCount_), formatOptions_(rhs.formatOptions_) {}
Base(std::forward<PrettyWriter>(rhs)), indentChar_(rhs.indentChar_), indentCharCount_(rhs.indentCharCount_), formatOptions_(rhs.formatOptions_) {}
#endif #endif
//! Set custom indentation. //! Set custom indentation.
@ -92,13 +89,34 @@ public:
*/ */
//@{ //@{
bool Null() { PrettyPrefix(kNullType); return Base::EndValue(Base::WriteNull()); } bool Null() {
bool Bool(bool b) { PrettyPrefix(b ? kTrueType : kFalseType); return Base::EndValue(Base::WriteBool(b)); } PrettyPrefix(kNullType);
bool Int(int i) { PrettyPrefix(kNumberType); return Base::EndValue(Base::WriteInt(i)); } return Base::EndValue(Base::WriteNull());
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 Bool(bool b) {
bool Uint64(uint64_t u64) { PrettyPrefix(kNumberType); return Base::EndValue(Base::WriteUint64(u64)); } PrettyPrefix(b ? kTrueType : kFalseType);
bool Double(double d) { PrettyPrefix(kNumberType); return Base::EndValue(Base::WriteDouble(d)); } return Base::EndValue(Base::WriteBool(b));
}
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,8 +379,7 @@
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) \ #if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42) || defined(RAPIDJSON_NEON) || defined(RAPIDJSON_DOXYGEN_RUNNING)
|| defined(RAPIDJSON_NEON) || defined(RAPIDJSON_DOXYGEN_RUNNING)
#define RAPIDJSON_SIMD #define RAPIDJSON_SIMD
#endif #endif
@ -454,9 +453,14 @@ RAPIDJSON_NAMESPACE_END
//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN //!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
#endif #endif
RAPIDJSON_NAMESPACE_BEGIN RAPIDJSON_NAMESPACE_BEGIN
template <bool x> struct STATIC_ASSERTION_FAILURE; template <bool x>
template <> struct STATIC_ASSERTION_FAILURE<true> { enum { value = 1 }; }; struct STATIC_ASSERTION_FAILURE;
template <size_t x> struct StaticAssertTest {}; template <>
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__)
@ -515,7 +519,8 @@ 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) \
@ -557,7 +562,8 @@ 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: x) #define RAPIDJSON_DIAG_OFF(x) RAPIDJSON_DIAG_PRAGMA(disable \
: 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,7 +347,8 @@ inline const char *SkipWhitespace_SIMD(const char* p) {
return p; return p;
// The rest of string // The rest of string
#define C16(c) { c, c, c, c, c, c, c, c, c, c, c, c, c, c, c, c } #define C16(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
@ -383,7 +384,8 @@ 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) { c, c, c, c, c, c, c, c, c, c, c, c, c, c, c, c } #define C16(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
@ -453,7 +455,8 @@ 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);
} }
@ -489,7 +492,8 @@ 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);
} }
@ -502,16 +506,19 @@ 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<> inline void SkipWhitespace(InsituStringStream& is) { template <>
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<> inline void SkipWhitespace(StringStream& is) { template <>
inline void SkipWhitespace(StringStream& is) {
is.src_ = SkipWhitespace_SIMD(is.src_); is.src_ = SkipWhitespace_SIMD(is.src_);
} }
template<> inline void SkipWhitespace(EncodedInputStream<UTF8<>, MemoryStream>& is) { template <>
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
@ -544,8 +551,7 @@ 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) : GenericReader(StackAllocator* stackAllocator = 0, size_t stackCapacity = kDefaultStackCapacity) : stack_(stackAllocator, stackCapacity), parseResult_(), state_(IterativeParsingStartState) {}
stack_(stackAllocator, stackCapacity), parseResult_(), state_(IterativeParsingStartState) {}
//! Parse JSON text. //! Parse JSON text.
/*! \tparam parseFlags Combination of \ref ParseFlag. /*! \tparam parseFlags Combination of \ref ParseFlag.
@ -701,6 +707,7 @@ 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&);
@ -789,7 +796,8 @@ private:
RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
return; return;
default: default:
RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell()); break; // This useless break is only for making warning and coverage happy RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell());
break; // This useless break is only for making warning and coverage happy
} }
if (parseFlags & kParseTrailingCommasFlag) { if (parseFlags & kParseTrailingCommasFlag) {
@ -1036,8 +1044,7 @@ 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);
} }
} }
@ -1059,9 +1066,7 @@ private:
} }
else { else {
size_t offset = is.Tell(); size_t offset = is.Tell();
if (RAPIDJSON_UNLIKELY((parseFlags & kParseValidateEncodingFlag ? if (RAPIDJSON_UNLIKELY((parseFlags & kParseValidateEncodingFlag ? !Transcoder<SEncoding, TEncoding>::Validate(is, os) : !Transcoder<SEncoding, TEncoding>::Transcode(is, os))))
!Transcoder<SEncoding, TEncoding>::Validate(is, os) :
!Transcoder<SEncoding, TEncoding>::Transcode(is, os))))
RAPIDJSON_PARSE_ERROR(kParseErrorStringInvalidEncoding, offset); RAPIDJSON_PARSE_ERROR(kParseErrorStringInvalidEncoding, offset);
} }
} }
@ -1269,7 +1274,8 @@ 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;
@ -1339,7 +1345,8 @@ 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;
@ -1393,7 +1400,8 @@ 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;
@ -1432,6 +1440,7 @@ 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_) {}
@ -1458,6 +1467,7 @@ 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) {}
@ -1468,11 +1478,10 @@ 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 & kParseNumbersAsStringsFlag) != 0) ? ((parseFlags & kParseInsituFlag) == 0) : ((parseFlags & kParseFullPrecisionFlag) != 0),
((parseFlags & kParseInsituFlag) == 0) :
((parseFlags & kParseFullPrecisionFlag) != 0),
(parseFlags & kParseNumbersAsStringsFlag) != 0 && (parseFlags & kParseNumbersAsStringsFlag) != 0 &&
(parseFlags & kParseInsituFlag) == 0> s(*this, copy.s); (parseFlags & kParseInsituFlag) == 0>
s(*this, copy.s);
size_t startOffset = s.Tell(); size_t startOffset = s.Tell();
double d = 0.0; double d = 0.0;
@ -1531,8 +1540,7 @@ 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') if (RAPIDJSON_UNLIKELY(s.Peek() == 'i' && !(Consume(s, 'i') && Consume(s, 'n') && Consume(s, 'i') && Consume(s, 't') && Consume(s, 'y')))) {
&& Consume(s, 'i') && Consume(s, 't') && Consume(s, 'y')))) {
RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell()); RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell());
} }
} }
@ -1749,16 +1757,27 @@ 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': ParseNull <parseFlags>(is, handler); break; case 'n':
case 't': ParseTrue <parseFlags>(is, handler); break; ParseNull<parseFlags>(is, handler);
case 'f': ParseFalse <parseFlags>(is, handler); break; break;
case '"': ParseString<parseFlags>(is, handler); break; case 't':
case '{': ParseObject<parseFlags>(is, handler); break; ParseTrue<parseFlags>(is, handler);
case '[': ParseArray <parseFlags>(is, handler); break; 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;
} }
} }
@ -1846,14 +1865,12 @@ 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
@ -1914,8 +1931,7 @@ 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)
@ -1948,14 +1964,12 @@ 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)
@ -2014,8 +2028,7 @@ 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;
@ -2075,8 +2088,7 @@ 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());
@ -2105,8 +2117,7 @@ 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());
@ -2165,16 +2176,31 @@ private:
} }
switch (src) { switch (src) {
case IterativeParsingStartState: RAPIDJSON_PARSE_ERROR(kParseErrorDocumentEmpty, is.Tell()); return; case IterativeParsingStartState:
case IterativeParsingFinishState: RAPIDJSON_PARSE_ERROR(kParseErrorDocumentRootNotSingular, is.Tell()); return; RAPIDJSON_PARSE_ERROR(kParseErrorDocumentEmpty, is.Tell());
return;
case IterativeParsingFinishState:
RAPIDJSON_PARSE_ERROR(kParseErrorDocumentRootNotSingular, is.Tell());
return;
case IterativeParsingObjectInitialState: case IterativeParsingObjectInitialState:
case IterativeParsingMemberDelimiterState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissName, is.Tell()); return; case IterativeParsingMemberDelimiterState:
case IterativeParsingMemberKeyState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissColon, is.Tell()); return; RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissName, is.Tell());
case IterativeParsingMemberValueState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell()); return; 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: RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell()); return; case IterativeParsingElementDelimiterState:
default: RAPIDJSON_ASSERT(src == IterativeParsingElementState); RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell()); return; RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell());
return;
default:
RAPIDJSON_ASSERT(src == IterativeParsingElementState);
RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell());
return;
} }
} }

View File

@ -251,14 +251,36 @@ public:
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) { Number n; n.u.i = i; n.d = static_cast<double>(i); return WriteNumber(n); } bool Int(int i) {
bool Uint(unsigned u) { Number n; n.u.u = u; n.d = static_cast<double>(u); return WriteNumber(n); } Number n;
bool Int64(int64_t i) { Number n; n.u.i = i; n.d = static_cast<double>(i); return WriteNumber(n); } n.u.i = i;
bool Uint64(uint64_t u) { Number n; n.u.u = u; n.d = static_cast<double>(u); return WriteNumber(n); } n.d = static_cast<double>(i);
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) n.u.i = static_cast<int64_t>(d); if (d < 0)
else n.u.u = static_cast<uint64_t>(d); n.u.i = static_cast<int64_t>(d);
else
n.u.u = static_cast<uint64_t>(d);
n.d = d; n.d = d;
return WriteNumber(n); return WriteNumber(n);
} }
@ -352,8 +374,7 @@ struct SchemaValidationContext {
kPatternValidatorWithAdditionalProperty kPatternValidatorWithAdditionalProperty
}; };
SchemaValidationContext(SchemaValidatorFactoryType& f, ErrorHandlerType& eh, const SchemaType* s) : SchemaValidationContext(SchemaValidatorFactoryType& f, ErrorHandlerType& eh, const SchemaType* s) : factory(f),
factory(f),
error_handler(eh), error_handler(eh),
schema(s), schema(s),
valueSchema(), valueSchema(),
@ -371,8 +392,7 @@ struct SchemaValidationContext {
propertyExist(), propertyExist(),
inArray(false), inArray(false),
valueUniqueness(false), valueUniqueness(false),
arrayUniqueness(false) arrayUniqueness(false) {
{
} }
~SchemaValidationContext() { ~SchemaValidationContext() {
@ -434,8 +454,7 @@ public:
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) : Schema(SchemaDocumentType* schemaDocument, const PointerType& p, const ValueType& value, const ValueType& document, AllocatorType* allocator) : allocator_(allocator),
allocator_(allocator),
uri_(schemaDocument->GetURI(), *allocator), uri_(schemaDocument->GetURI(), *allocator),
pointer_(p, allocator), pointer_(p, allocator),
typeless_(schemaDocument->GetTypeless()), typeless_(schemaDocument->GetTypeless()),
@ -469,8 +488,7 @@ public:
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;
@ -669,7 +687,6 @@ public:
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() {
@ -801,7 +818,8 @@ public:
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) {
@ -1054,38 +1072,64 @@ public:
static const ValueType& GetValidateErrorKeyword(ValidateErrorCode validateErrorCode) { static const ValueType& GetValidateErrorKeyword(ValidateErrorCode validateErrorCode) {
switch (validateErrorCode) { switch (validateErrorCode) {
case kValidateErrorMultipleOf: return GetMultipleOfString(); case kValidateErrorMultipleOf:
case kValidateErrorMaximum: return GetMaximumString(); return GetMultipleOfString();
case kValidateErrorExclusiveMaximum: return GetMaximumString(); // Same case kValidateErrorMaximum:
case kValidateErrorMinimum: return GetMinimumString(); return GetMaximumString();
case kValidateErrorExclusiveMinimum: return GetMinimumString(); // Same case kValidateErrorExclusiveMaximum:
return GetMaximumString(); // Same
case kValidateErrorMinimum:
return GetMinimumString();
case kValidateErrorExclusiveMinimum:
return GetMinimumString(); // Same
case kValidateErrorMaxLength: return GetMaxLengthString(); case kValidateErrorMaxLength:
case kValidateErrorMinLength: return GetMinLengthString(); return GetMaxLengthString();
case kValidateErrorPattern: return GetPatternString(); case kValidateErrorMinLength:
return GetMinLengthString();
case kValidateErrorPattern:
return GetPatternString();
case kValidateErrorMaxItems: return GetMaxItemsString(); case kValidateErrorMaxItems:
case kValidateErrorMinItems: return GetMinItemsString(); return GetMaxItemsString();
case kValidateErrorUniqueItems: return GetUniqueItemsString(); case kValidateErrorMinItems:
case kValidateErrorAdditionalItems: return GetAdditionalItemsString(); return GetMinItemsString();
case kValidateErrorUniqueItems:
return GetUniqueItemsString();
case kValidateErrorAdditionalItems:
return GetAdditionalItemsString();
case kValidateErrorMaxProperties: return GetMaxPropertiesString(); case kValidateErrorMaxProperties:
case kValidateErrorMinProperties: return GetMinPropertiesString(); return GetMaxPropertiesString();
case kValidateErrorRequired: return GetRequiredString(); case kValidateErrorMinProperties:
case kValidateErrorAdditionalProperties: return GetAdditionalPropertiesString(); return GetMinPropertiesString();
case kValidateErrorPatternProperties: return GetPatternPropertiesString(); case kValidateErrorRequired:
case kValidateErrorDependencies: return GetDependenciesString(); return GetRequiredString();
case kValidateErrorAdditionalProperties:
return GetAdditionalPropertiesString();
case kValidateErrorPatternProperties:
return GetPatternPropertiesString();
case kValidateErrorDependencies:
return GetDependenciesString();
case kValidateErrorEnum: return GetEnumString(); case kValidateErrorEnum:
case kValidateErrorType: return GetTypeString(); return GetEnumString();
case kValidateErrorType:
return GetTypeString();
case kValidateErrorOneOf: return GetOneOfString(); case kValidateErrorOneOf:
case kValidateErrorOneOfMatch: return GetOneOfString(); // Same return GetOneOfString();
case kValidateErrorAllOf: return GetAllOfString(); case kValidateErrorOneOfMatch:
case kValidateErrorAnyOf: return GetAnyOfString(); return GetOneOfString(); // Same
case kValidateErrorNot: return GetNotString(); case kValidateErrorAllOf:
return GetAllOfString();
case kValidateErrorAnyOf:
return GetAnyOfString();
case kValidateErrorNot:
return GetNotString();
default: return GetNullString(); default:
return GetNullString();
} }
} }
@ -1250,13 +1294,20 @@ private:
#endif // RAPIDJSON_SCHEMA_USE_STDREGEX #endif // RAPIDJSON_SCHEMA_USE_STDREGEX
void AddType(const ValueType& type) { void AddType(const ValueType& type) {
if (type == GetNullString() ) type_ |= 1 << kNullSchemaType; if (type == GetNullString())
else if (type == GetBooleanString()) type_ |= 1 << kBooleanSchemaType; type_ |= 1 << kNullSchemaType;
else if (type == GetObjectString() ) type_ |= 1 << kObjectSchemaType; else if (type == GetBooleanString())
else if (type == GetArrayString() ) type_ |= 1 << kArraySchemaType; type_ |= 1 << kBooleanSchemaType;
else if (type == GetStringString() ) type_ |= 1 << kStringSchemaType; else if (type == GetObjectString())
else if (type == GetIntegerString()) type_ |= 1 << kIntegerSchemaType; type_ |= 1 << kObjectSchemaType;
else if (type == GetNumberString() ) type_ |= (1 << kNumberSchemaType) | (1 << kIntegerSchemaType); else if (type == GetArrayString())
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 {
@ -1302,8 +1353,7 @@ private:
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;
} }
@ -1338,7 +1388,8 @@ private:
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;
@ -1443,8 +1494,10 @@ private:
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)) eh.AddExpectedType(GetNumberString()); if (type_ & (1 << kNumberSchemaType))
else if (type_ & (1 << kIntegerSchemaType)) eh.AddExpectedType(GetIntegerString()); eh.AddExpectedType(GetNumberString());
else if (type_ & (1 << kIntegerSchemaType))
eh.AddExpectedType(GetIntegerString());
eh.EndDisallowedType(actualType); eh.EndDisallowedType(actualType);
} }
@ -1602,15 +1655,13 @@ 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) : IRemoteSchemaDocumentProviderType* remoteProvider = 0, Allocator* allocator = 0) : remoteProvider_(remoteProvider),
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)();
@ -1649,16 +1700,14 @@ 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 : GenericSchemaDocument(GenericSchemaDocument&& rhs) RAPIDJSON_NOEXCEPT : remoteProvider_(rhs.remoteProvider_),
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;
@ -1839,8 +1888,7 @@ 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 : class GenericSchemaValidator : public internal::ISchemaStateFactory<typename SchemaDocumentType::SchemaType>,
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:
@ -1864,8 +1912,7 @@ 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),
@ -1878,7 +1925,8 @@ public:
valid_(true), valid_(true),
flags_(kValidateDefaultFlags) flags_(kValidateDefaultFlags)
#if RAPIDJSON_SCHEMA_VERBOSE #if RAPIDJSON_SCHEMA_VERBOSE
, depth_(0) ,
depth_(0)
#endif #endif
{ {
} }
@ -1896,8 +1944,7 @@ 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),
@ -1910,7 +1957,8 @@ public:
valid_(true), valid_(true),
flags_(kValidateDefaultFlags) flags_(kValidateDefaultFlags)
#if RAPIDJSON_SCHEMA_VERBOSE #if RAPIDJSON_SCHEMA_VERBOSE
, depth_(0) ,
depth_(0)
#endif #endif
{ {
} }
@ -2233,10 +2281,8 @@ RAPIDJSON_MULTILINEMACRO_END
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) bool RawNumber(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 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()));
@ -2331,8 +2377,7 @@ 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),
@ -2345,7 +2390,8 @@ 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)
@ -2423,7 +2469,8 @@ 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);
} }
@ -2471,7 +2518,8 @@ 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).StringifyUriFragment(sb); : instancePointer)
.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());
@ -2481,8 +2529,10 @@ 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()) schema.StringifyUriFragment(sb); if (schema.GetTokenCount())
else GetInvalidSchemaPointer().StringifyUriFragment(sb); schema.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,10 +160,16 @@ 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() { RAPIDJSON_ASSERT(false); return 0; } Ch* PutBegin() {
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*) { RAPIDJSON_ASSERT(false); return 0; } size_t PutEnd(Ch*) {
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.
@ -196,13 +202,20 @@ 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) { RAPIDJSON_ASSERT(dst_ != 0); *dst_++ = c; } void Put(Ch 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* begin = dst_; dst_ += count; return begin; } Ch* Push(size_t count) {
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,17 +98,12 @@ 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 explicit Writer(OutputStream& os, StackAllocator* stackAllocator = 0, size_t levelDepth = kDefaultLevelDepth) : os_(&os), level_stack_(stackAllocator, levelDepth * sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(false) {}
Writer(OutputStream& os, StackAllocator* stackAllocator = 0, size_t levelDepth = kDefaultLevelDepth) :
os_(&os), level_stack_(stackAllocator, levelDepth * sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(false) {}
explicit explicit Writer(StackAllocator* allocator = 0, size_t levelDepth = kDefaultLevelDepth) : os_(0), level_stack_(allocator, levelDepth * sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(false) {}
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) : Writer(Writer&& rhs) : os_(rhs.os_), level_stack_(std::move(rhs.level_stack_)), maxDecimalPlaces_(rhs.maxDecimalPlaces_), hasRoot_(rhs.hasRoot_) {
os_(rhs.os_), level_stack_(std::move(rhs.level_stack_)), maxDecimalPlaces_(rhs.maxDecimalPlaces_), hasRoot_(rhs.hasRoot_) {
rhs.os_ = 0; rhs.os_ = 0;
} }
#endif #endif
@ -179,19 +174,40 @@ public:
*/ */
//@{ //@{
bool Null() { Prefix(kNullType); return EndValue(WriteNull()); } bool Null() {
bool Bool(bool b) { Prefix(b ? kTrueType : kFalseType); return EndValue(WriteBool(b)); } Prefix(kNullType);
bool Int(int i) { Prefix(kNumberType); return EndValue(WriteInt(i)); } return EndValue(WriteNull());
bool Uint(unsigned u) { Prefix(kNumberType); return EndValue(WriteUint(u)); } }
bool Int64(int64_t i64) { Prefix(kNumberType); return EndValue(WriteInt64(i64)); } bool Bool(bool b) {
bool Uint64(uint64_t u64) { Prefix(kNumberType); return EndValue(WriteUint64(u64)); } Prefix(b ? kTrueType : kFalseType);
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) { Prefix(kNumberType); return EndValue(WriteDouble(d)); } bool Double(double 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);
@ -222,8 +238,7 @@ 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
@ -295,17 +310,28 @@ protected:
bool WriteNull() { bool WriteNull() {
PutReserve(*os_, 4); PutReserve(*os_, 4);
PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'u'); PutUnsafe(*os_, 'l'); PutUnsafe(*os_, 'l'); return true; PutUnsafe(*os_, 'n');
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_, 'r'); PutUnsafe(*os_, 'u'); PutUnsafe(*os_, 'e'); PutUnsafe(*os_, 't');
PutUnsafe(*os_, 'r');
PutUnsafe(*os_, 'u');
PutUnsafe(*os_, 'e');
} }
else { else {
PutReserve(*os_, 5); PutReserve(*os_, 5);
PutUnsafe(*os_, 'f'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'l'); PutUnsafe(*os_, 's'); PutUnsafe(*os_, 'e'); PutUnsafe(*os_, 'f');
PutUnsafe(*os_, 'a');
PutUnsafe(*os_, 'l');
PutUnsafe(*os_, 's');
PutUnsafe(*os_, 'e');
} }
return true; return true;
} }
@ -352,7 +378,9 @@ 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_, 'a'); PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'N');
PutUnsafe(*os_, 'a');
PutUnsafe(*os_, 'N');
return true; return true;
} }
if (internal::Double(d).Sign()) { if (internal::Double(d).Sign()) {
@ -361,8 +389,14 @@ protected:
} }
else else
PutReserve(*os_, 8); PutReserve(*os_, 8);
PutUnsafe(*os_, 'I'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'f'); PutUnsafe(*os_, 'I');
PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'y'); PutUnsafe(*os_, 'n');
PutUnsafe(*os_, 'f');
PutUnsafe(*os_, 'i');
PutUnsafe(*os_, 'n');
PutUnsafe(*os_, 'i');
PutUnsafe(*os_, 't');
PutUnsafe(*os_, 'y');
return true; return true;
} }
@ -439,9 +473,7 @@ 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 ? else if (RAPIDJSON_UNLIKELY(!(writeFlags & kWriteValidateEncodingFlag ? Transcoder<SourceEncoding, TargetEncoding>::Validate(is, *os_) : Transcoder<SourceEncoding, TargetEncoding>::TranscodeUnsafe(is, *os_))))
Transcoder<SourceEncoding, TargetEncoding>::Validate(is, *os_) :
Transcoder<SourceEncoding, TargetEncoding>::TranscodeUnsafe(is, *os_))))
return false; return false;
} }
PutUnsafe(*os_, '\"'); PutUnsafe(*os_, '\"');
@ -452,19 +484,29 @@ protected:
return RAPIDJSON_LIKELY(is.Tell() < length); return RAPIDJSON_LIKELY(is.Tell() < length);
} }
bool WriteStartObject() { os_->Put('{'); return true; } bool WriteStartObject() {
bool WriteEndObject() { os_->Put('}'); return true; } os_->Put('{');
bool WriteStartArray() { os_->Put('['); return true; } 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 ? if (RAPIDJSON_UNLIKELY(!(writeFlags & kWriteValidateEncodingFlag ? Transcoder<SourceEncoding, TargetEncoding>::Validate(is, *os_) : Transcoder<SourceEncoding, TargetEncoding>::TranscodeUnsafe(is, *os_))))
Transcoder<SourceEncoding, TargetEncoding>::Validate(is, *os_) :
Transcoder<SourceEncoding, TargetEncoding>::TranscodeUnsafe(is, *os_))))
return false; return false;
} }
return true; return true;
@ -550,7 +592,9 @@ 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_, 'a'); PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'N');
PutUnsafe(*os_, 'a');
PutUnsafe(*os_, 'N');
return true; return true;
} }
if (internal::Double(d).Sign()) { if (internal::Double(d).Sign()) {
@ -559,8 +603,14 @@ inline bool Writer<StringBuffer>::WriteDouble(double d) {
} }
else else
PutReserve(*os_, 8); PutReserve(*os_, 8);
PutUnsafe(*os_, 'I'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'f'); PutUnsafe(*os_, 'I');
PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'y'); PutUnsafe(*os_, 'n');
PutUnsafe(*os_, 'f');
PutUnsafe(*os_, 'i');
PutUnsafe(*os_, 'n');
PutUnsafe(*os_, 'i');
PutUnsafe(*os_, 't');
PutUnsafe(*os_, 'y');
return true; return true;
} }
@ -680,7 +730,8 @@ 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,22 +16,15 @@ 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) : minAmount(min), maxAmount(max), current(min), fails(0), randGenerator((uint64_t)time(0)) {
, 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,8 +9,7 @@
#include <sys/un.h> #include <sys/un.h>
#include <unistd.h> #include <unistd.h>
int GetProcessId() int GetProcessId() {
{
return ::getpid(); return ::getpid();
} }
@ -26,8 +25,7 @@ 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");
@ -36,21 +34,18 @@ 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);
@ -76,8 +71,7 @@ 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;
@ -88,8 +82,7 @@ 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) {
@ -103,8 +96,7 @@ 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,8 +7,7 @@
#include <assert.h> #include <assert.h>
#include <windows.h> #include <windows.h>
int GetProcessId() int GetProcessId() {
{
return (int)::GetCurrentProcessId(); return (int)::GetCurrentProcessId();
} }
@ -18,20 +17,17 @@ 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';
@ -61,8 +57,7 @@ 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;
@ -70,8 +65,7 @@ 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;
} }
@ -93,8 +87,7 @@ 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,8 +9,7 @@
#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;
@ -22,8 +21,7 @@ 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");
@ -94,8 +92,7 @@ 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,8 +21,7 @@
#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);
@ -51,8 +50,7 @@ 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]) {
@ -67,8 +65,7 @@ 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.
@ -131,8 +128,7 @@ 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);
@ -148,8 +144,7 @@ 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,8 +23,7 @@ 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);
@ -85,8 +84,7 @@ 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 };
@ -101,8 +99,7 @@ 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()) {
@ -122,8 +119,7 @@ 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() };
} }
@ -237,15 +233,13 @@ 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 =
@ -257,8 +251,7 @@ 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 =
@ -273,8 +266,7 @@ 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;
@ -347,8 +339,7 @@ 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;
} }
@ -366,8 +357,7 @@ 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(
@ -377,13 +367,11 @@ 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;
@ -397,8 +385,7 @@ 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.
@ -476,8 +463,7 @@ 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,7 +2,6 @@
// 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,8 +15,7 @@ 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;
@ -27,8 +26,7 @@ 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,22 +6,19 @@
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;
} }
@ -57,8 +54,7 @@ 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);
} }
@ -66,8 +62,7 @@ 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;
@ -78,8 +73,7 @@ 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,8 +3,7 @@
#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;
@ -29,22 +28,19 @@ 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();
} }
@ -55,8 +51,7 @@ 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();
} }
@ -64,16 +59,14 @@ 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);
@ -84,8 +77,7 @@ 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);
{ {
@ -167,8 +159,7 @@ 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);
{ {
@ -182,8 +173,7 @@ 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);
{ {
@ -201,8 +191,7 @@ 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);
{ {
@ -220,8 +209,7 @@ 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,8 +22,7 @@
// 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;
} }
@ -58,18 +57,14 @@ 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) : buffer_(buffer), end_(buffer + size) {
, 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_) {
@ -78,8 +73,7 @@ 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;
} }
@ -90,8 +84,7 @@ 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;
} }
@ -102,8 +95,7 @@ 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;
}; };
@ -117,14 +109,10 @@ public:
char* current_; char* current_;
DirectStringBuffer(char* buffer, size_t maxLen) DirectStringBuffer(char* buffer, size_t maxLen)
: buffer_(buffer) : buffer_(buffer), end_(buffer + maxLen), current_(buffer) {
, end_(buffer + maxLen)
, current_(buffer)
{
} }
void Put(char c) void Put(char c) {
{
if (current_ < end_) { if (current_ < end_) {
*current_++ = c; *current_++ = c;
} }
@ -147,10 +135,7 @@ public:
StackAllocator stackAlloc_; StackAllocator stackAlloc_;
JsonWriter(char* dest, size_t maxLen) JsonWriter(char* dest, size_t maxLen)
: JsonWriterBase(stringBuffer_, &stackAlloc_, WriterNestingLevels) : JsonWriterBase(stringBuffer_, &stackAlloc_, WriterNestingLevels), stringBuffer_(dest, maxLen), stackAlloc_() {
, stringBuffer_(dest, maxLen)
, stackAlloc_()
{
} }
size_t Size() const { return stringBuffer_.GetSize(); } size_t Size() const { return stringBuffer_.GetSize(); }
@ -170,17 +155,14 @@ public:
: JsonDocumentBase(rapidjson::kObjectType, : JsonDocumentBase(rapidjson::kObjectType,
&poolAllocator_, &poolAllocator_,
sizeof(stackAllocator_.fixedBuffer_), sizeof(stackAllocator_.fixedBuffer_),
&stackAllocator_) &stackAllocator_),
, poolAllocator_(parseBuffer_, sizeof(parseBuffer_), kDefaultChunkCapacity, &mallocAllocator_) poolAllocator_(parseBuffer_, sizeof(parseBuffer_), kDefaultChunkCapacity, &mallocAllocator_), stackAllocator_() {
, 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()) {
@ -190,8 +172,7 @@ 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()) {
@ -203,8 +184,7 @@ 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()) {