From 852c25123c6f8fec619c1c8d49250bd6f698c6b1 Mon Sep 17 00:00:00 2001 From: Milo Yip Date: Fri, 10 Apr 2015 14:54:13 +0800 Subject: [PATCH 001/189] Implement parser/generator for JSON Pointer --- include/rapidjson/pointer.h | 208 ++++++++++++++++++++++++++++++++++ test/unittest/CMakeLists.txt | 1 + test/unittest/pointertest.cpp | 167 +++++++++++++++++++++++++++ 3 files changed, 376 insertions(+) create mode 100644 include/rapidjson/pointer.h create mode 100644 test/unittest/pointertest.cpp diff --git a/include/rapidjson/pointer.h b/include/rapidjson/pointer.h new file mode 100644 index 0000000..28c94ad --- /dev/null +++ b/include/rapidjson/pointer.h @@ -0,0 +1,208 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_POINTER_H_ +#define RAPIDJSON_POINTER_H_ + +#include "document.h" + +RAPIDJSON_NAMESPACE_BEGIN + +template +class GenericPointer { +public: + typedef typename ValueType::EncodingType EncodingType; + typedef typename EncodingType::Ch Ch; + + struct Token { + const typename Ch* name; + SizeType length; + SizeType index; //!< A valid index if not equal to kInvalidIndex. + }; + + GenericPointer(const Ch* source, Allocator* allocator = 0) + : allocator_(allocator), + ownAllocator_(), + nameBuffer_(), + tokens_(), + tokenCount_(), + valid_(true) + { + Parse(source, internal::StrLen(source)); + } + + GenericPointer(const Ch* source, size_t length, Allocator* allocator = 0) + : allocator_(allocator), + ownAllocator_(), + nameBuffer_(), + tokens_(), + tokenCount_(), + valid_(true) + { + Parse(source, length); + } + + GenericPointer(const Token* tokens, size_t tokenCount) : + : allocator_(), + ownAllocator_(), + nameBuffer_(), + tokens_(tokens), + tokenCount_(tokenCount), + valid_(true) + { + } + + ~GenericPointer() { + if (nameBuffer_) { + Allocator::Free(nameBuffer_); + Allocator::Free(tokens_); + } + RAPIDJSON_DELETE(ownAllocator_); + } + + bool IsValid() const { return valid_; } + + const Token* GetTokens() const { return tokens_; } + + size_t GetTokenCount() const { return tokenCount_; } + + template + void Stringify(OutputStream& os) const { + RAPIDJSON_ASSERT(IsValid()); + for (Token *t = tokens_; t != tokens_ + tokenCount_; ++t) { + os.Put('/'); + for (size_t j = 0; j < t->length; j++) { + Ch c = t->name[j]; + if (c == '~') { os.Put('~'); os.Put('0'); } + else if (c == '/') { os.Put('~'); os.Put('1'); } + else os.Put(c); + } + } + } + + ValueType* Get(ValueType& root) const; + const ValueType* Get(const ValueType& root) const { + return Get(const_cast(root)); + } + + ValueType* Get(ValueType& root, const ValueType& defaultValue) const; + const ValueType* Get(const ValueType& root, const ValueType& defaultValue) const; + + // Move semantics, create parents if non-exist + void Set(ValueType& root, ValueType& value) const; + + // Create parents if non-exist + void Swap(ValueType& root, ValueType& value) const; + + static const size_t kDefaultTokenCapacity = 4; + static const SizeType kInvalidIndex = ~SizeType(0); + +private: + void Parse(const Ch* source, size_t length) { + // Create own allocator if user did not supply. + if (!allocator_) + ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator()); + + // Create a buffer as same size of source + RAPIDJSON_ASSERT(nameBuffer_ == 0); + nameBuffer_ = (Ch*)allocator_->Malloc(length); + + RAPIDJSON_ASSERT(tokens_ == 0); + tokens_ = (Token*)allocator_->Malloc(length * sizeof(Token)); // Maximum possible tokens in the source + + tokenCount_ = 0; + Ch* name = nameBuffer_; + + for (size_t i = 0; i < length;) { + if (source[i++] != '/') // Consumes '/' + goto error; + + Token& token = tokens_[tokenCount_++]; + token.name = name; + bool isNumber = true; + + while (i < length && source[i] != '/') { + Ch c = source[i++]; + + // Escaping "~0" -> '~', "~1" -> '/' + if (c == '~') { + if (i < length) { + c = source[i++]; + if (c == '0') c = '~'; + else if (c == '1') c = '/'; + else goto error; + } + else + goto error; + } + + // First check for index: all of characters are digit + if (c < '0' || c > '9') + isNumber = false; + + *name++ = c; + } + token.length = name - token.name; + *name++ = '\0'; // Null terminator + + // Second check for index: more than one digit cannot have leading zero + if (isNumber && token.length > 1 && token.name[0] == '0') + isNumber = false; + + // String to SizeType conversion + SizeType n = 0; + if (isNumber) { + for (size_t j = 0; j < token.length; j++) { + SizeType m = n * 10 + static_cast(token.name[j] - '0'); + if (m < n) { // overflow detection + isNumber = false; + break; + } + n = m; + } + } + + token.index = isNumber ? n : kInvalidIndex; + } + + RAPIDJSON_ASSERT(name <= nameBuffer_ + length); // Should not overflow buffer + tokens_ = (Token*)allocator_->Realloc(tokens_, length * sizeof(Token), tokenCount_ * sizeof(Token)); // Shrink tokens_ + return; + + error: + Allocator::Free(nameBuffer_); + Allocator::Free(tokens_); + nameBuffer_ = 0; + tokens_ = 0; + tokenCount_ = 0; + valid_ = false; + return; + } + + GenericPointer(const GenericPointer& rhs); + GenericPointer& operator=(const GenericPointer& rhs); + + Allocator* allocator_; + Allocator* ownAllocator_; + Ch* nameBuffer_; + Token* tokens_; + size_t tokenCount_; + bool valid_; +}; + +typedef GenericPointer Pointer; + +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_POINTER_H_ diff --git a/test/unittest/CMakeLists.txt b/test/unittest/CMakeLists.txt index 5e4a3e9..6a776ec 100644 --- a/test/unittest/CMakeLists.txt +++ b/test/unittest/CMakeLists.txt @@ -6,6 +6,7 @@ set(UNITTEST_SOURCES filestreamtest.cpp jsoncheckertest.cpp namespacetest.cpp + pointertest.cpp readertest.cpp stringbuffertest.cpp strtodtest.cpp diff --git a/test/unittest/pointertest.cpp b/test/unittest/pointertest.cpp new file mode 100644 index 0000000..28173f9 --- /dev/null +++ b/test/unittest/pointertest.cpp @@ -0,0 +1,167 @@ +// Copyright (C) 2011 Milo Yip +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#include "unittest.h" +#include "rapidjson/pointer.h" +#include "rapidjson/stringbuffer.h" +#include + +using namespace rapidjson; + +static const char cJson[] = "{\n" +" \"foo\":[\"bar\", \"baz\"],\n" +" \"\" : 0,\n" +" \"a/b\" : 1,\n" +" \"c%d\" : 2,\n" +" \"e^f\" : 3,\n" +" \"g|h\" : 4,\n" +" \"i\\\\j\" : 5,\n" +" \"k\\\"l\" : 6,\n" +" \" \" : 7,\n" +" \"m~n\" : 8\n" +"}"; + +TEST(Pointer, Parse) { + { + Pointer p(""); + EXPECT_TRUE(p.IsValid()); + EXPECT_EQ(0, p.GetTokenCount()); + } + + { + Pointer p("/foo"); + EXPECT_TRUE(p.IsValid()); + EXPECT_EQ(1, p.GetTokenCount()); + EXPECT_EQ(3, p.GetTokens()[0].length); + EXPECT_STREQ("foo", p.GetTokens()[0].name); + } + + { + Pointer p("/foo/0"); + EXPECT_TRUE(p.IsValid()); + EXPECT_EQ(2, p.GetTokenCount()); + EXPECT_EQ(3, p.GetTokens()[0].length); + EXPECT_STREQ("foo", p.GetTokens()[0].name); + EXPECT_EQ(1, p.GetTokens()[1].length); + EXPECT_STREQ("0", p.GetTokens()[1].name); + EXPECT_EQ(0, p.GetTokens()[1].index); + } + + { + // Unescape ~1 + Pointer p("/a~1b"); + EXPECT_TRUE(p.IsValid()); + EXPECT_EQ(1, p.GetTokenCount()); + EXPECT_EQ(3, p.GetTokens()[0].length); + EXPECT_STREQ("a/b", p.GetTokens()[0].name); + } + + { + // Unescape ~0 + Pointer p("/m~0n"); + EXPECT_TRUE(p.IsValid()); + EXPECT_EQ(1, p.GetTokenCount()); + EXPECT_EQ(3, p.GetTokens()[0].length); + EXPECT_STREQ("m~n", p.GetTokens()[0].name); + } + + { + // empty name + Pointer p("/"); + EXPECT_TRUE(p.IsValid()); + EXPECT_EQ(1, p.GetTokenCount()); + EXPECT_EQ(0, p.GetTokens()[0].length); + EXPECT_STREQ("", p.GetTokens()[0].name); + } + + { + // empty and non-empty name + Pointer p("//a"); + EXPECT_TRUE(p.IsValid()); + EXPECT_EQ(2, p.GetTokenCount()); + EXPECT_EQ(0, p.GetTokens()[0].length); + EXPECT_STREQ("", p.GetTokens()[0].name); + EXPECT_EQ(1, p.GetTokens()[1].length); + EXPECT_STREQ("a", p.GetTokens()[1].name); + } + + { + // Null characters + Pointer p("/\0\0", 3); + EXPECT_TRUE(p.IsValid()); + EXPECT_EQ(1, p.GetTokenCount()); + EXPECT_EQ(2, p.GetTokens()[0].length); + EXPECT_EQ('\0', p.GetTokens()[0].name[0]); + EXPECT_EQ('\0', p.GetTokens()[0].name[1]); + EXPECT_EQ('\0', p.GetTokens()[0].name[2]); + } + + { + // Valid index + Pointer p("/123"); + EXPECT_TRUE(p.IsValid()); + EXPECT_EQ(1, p.GetTokenCount()); + EXPECT_STREQ("123", p.GetTokens()[0].name); + EXPECT_EQ(123, p.GetTokens()[0].index); + } + + { + // Invalid index (with leading zero) + Pointer p("/01"); + EXPECT_TRUE(p.IsValid()); + EXPECT_EQ(1, p.GetTokenCount()); + EXPECT_STREQ("01", p.GetTokens()[0].name); + EXPECT_EQ(Pointer::kInvalidIndex, p.GetTokens()[0].index); + } + + { + // Invalid index (overflow) + Pointer p("/4294967296"); + EXPECT_TRUE(p.IsValid()); + EXPECT_EQ(1, p.GetTokenCount()); + EXPECT_STREQ("4294967296", p.GetTokens()[0].name); + EXPECT_EQ(Pointer::kInvalidIndex, p.GetTokens()[0].index); + } +} + +TEST(Pointer, Stringify) { + // Test by roundtrip + const char* sources[] = { + "", + "/foo", + "/foo/0", + "/", + "/a~1b", + "/c%d", + "/e^f", + "/g|h", + "/i\\j", + "/k\"l", + "/ ", + "/m~0n" + }; + + for (size_t i = 0; i < sizeof(sources) / sizeof(sources[0]); i++) { + Pointer p(sources[i]); + StringBuffer s; + p.Stringify(s); + EXPECT_STREQ(sources[i], s.GetString()); + } +} From c11547ebfa2304b8afd3fa2cadf5fdfc92c7f353 Mon Sep 17 00:00:00 2001 From: Milo Yip Date: Fri, 10 Apr 2015 17:43:11 +0800 Subject: [PATCH 002/189] Implement Pointer::Create(). Get(). GetWithDefault(). Set(). Swap() --- include/rapidjson/pointer.h | 92 ++++++++++++++++++++++++++++++++--- test/unittest/pointertest.cpp | 61 ++++++++++++++++++++++- 2 files changed, 143 insertions(+), 10 deletions(-) diff --git a/include/rapidjson/pointer.h b/include/rapidjson/pointer.h index 28c94ad..82a4458 100644 --- a/include/rapidjson/pointer.h +++ b/include/rapidjson/pointer.h @@ -31,6 +31,8 @@ public: SizeType index; //!< A valid index if not equal to kInvalidIndex. }; + static const SizeType kInvalidIndex = ~SizeType(0); + GenericPointer(const Ch* source, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), @@ -91,22 +93,96 @@ public: } } - ValueType* Get(ValueType& root) const; + ValueType& Create(ValueType& root, typename ValueType::AllocatorType& allocator, bool* alreadyExist = 0) const { + RAPIDJSON_ASSERT(IsValid()); + ValueType* v = &root; + bool exist = true; + for (Token *t = tokens_; t != tokens_ + tokenCount_; ++t) { + if (v->GetType() != kObjectType && v->GetType() != kArrayType) + if (t->index == kInvalidIndex) + v->SetObject(); + else + v->SetArray(); + + switch (v->GetType()) { + case kObjectType: + { + typename ValueType::MemberIterator m = v->FindMember(GenericStringRef(t->name, t->length)); + if (m == v->MemberEnd()) { + v->AddMember(Value(t->name, t->length, allocator).Move(), Value().Move(), allocator); + v = &(--v->MemberEnd())->value; // Assumes AddMember() appends at the end + exist = false; + } + else + v = &m->value; + } + break; + case kArrayType: + if (t->index == kInvalidIndex) + v->SetArray(); // Change to Array + if (t->index >= v->Size()) { + v->Reserve(t->index - 1, allocator); + while (t->index >= v->Size()) + v->PushBack(Value().Move(), allocator); + exist = false; + } + v = &((*v)[t->index]); + break; + } + } + + if (alreadyExist) + *alreadyExist = exist; + + return *v; + } + + ValueType* Get(ValueType& root) const { + RAPIDJSON_ASSERT(IsValid()); + ValueType* v = &root; + for (Token *t = tokens_; t != tokens_ + tokenCount_; ++t) { + switch (v->GetType()) { + case kObjectType: + { + typename ValueType::MemberIterator m = v->FindMember(GenericStringRef(t->name, t->length)); + if (m == v->MemberEnd()) + return 0; + v = &m->value; + } + break; + case kArrayType: + if (t->index == kInvalidIndex || t->index >= v->Size()) + return 0; + v = &((*v)[t->index]); + break; + default: + return 0; + } + } + return v; + } + const ValueType* Get(const ValueType& root) const { return Get(const_cast(root)); } - ValueType* Get(ValueType& root, const ValueType& defaultValue) const; - const ValueType* Get(const ValueType& root, const ValueType& defaultValue) const; + ValueType& GetWithDefault(ValueType& root, const ValueType& defaultValue, typename ValueType::AllocatorType& allocator) const { + bool alreadyExist; + Value& v = Create(root, allocator, &alreadyExist); + if (!alreadyExist) + v = Value(defaultValue, allocator); + return v; + } // Move semantics, create parents if non-exist - void Set(ValueType& root, ValueType& value) const; + ValueType& Set(ValueType& root, ValueType& value, typename ValueType::AllocatorType& allocator) const { + return Create(root, allocator) = value; + } // Create parents if non-exist - void Swap(ValueType& root, ValueType& value) const; - - static const size_t kDefaultTokenCapacity = 4; - static const SizeType kInvalidIndex = ~SizeType(0); + ValueType& Swap(ValueType& root, ValueType& value, typename ValueType::AllocatorType& allocator) const { + return Create(root, allocator).Swap(value); + } private: void Parse(const Ch* source, size_t length) { diff --git a/test/unittest/pointertest.cpp b/test/unittest/pointertest.cpp index 28173f9..dbe04c0 100644 --- a/test/unittest/pointertest.cpp +++ b/test/unittest/pointertest.cpp @@ -25,7 +25,7 @@ using namespace rapidjson; -static const char cJson[] = "{\n" +static const char kJson[] = "{\n" " \"foo\":[\"bar\", \"baz\"],\n" " \"\" : 0,\n" " \"a/b\" : 1,\n" @@ -131,7 +131,7 @@ TEST(Pointer, Parse) { EXPECT_EQ(Pointer::kInvalidIndex, p.GetTokens()[0].index); } - { + if (sizeof(SizeType) == 4) { // Invalid index (overflow) Pointer p("/4294967296"); EXPECT_TRUE(p.IsValid()); @@ -165,3 +165,60 @@ TEST(Pointer, Stringify) { EXPECT_STREQ(sources[i], s.GetString()); } } + +TEST(Pointer, Create) { + Document d; + EXPECT_EQ(&d, &Pointer("").Create(d, d.GetAllocator())); + EXPECT_EQ(&d["foo"], &Pointer("/foo").Create(d, d.GetAllocator())); + EXPECT_EQ(&d["foo"][0], &Pointer("/foo/0").Create(d, d.GetAllocator())); +} + +TEST(Pointer, Get) { + Document d; + d.Parse(kJson); + + EXPECT_EQ(&d, Pointer("").Get(d)); + EXPECT_EQ(&d["foo"], Pointer("/foo").Get(d)); + EXPECT_EQ(&d["foo"][0], Pointer("/foo/0").Get(d)); + EXPECT_EQ(&d[""], Pointer("/").Get(d)); + EXPECT_EQ(&d["a/b"], Pointer("/a~1b").Get(d)); + EXPECT_EQ(&d["c%d"], Pointer("/c%d").Get(d)); + EXPECT_EQ(&d["e^f"], Pointer("/e^f").Get(d)); + EXPECT_EQ(&d["g|h"], Pointer("/g|h").Get(d)); + EXPECT_EQ(&d["i\\j"], Pointer("/i\\j").Get(d)); + EXPECT_EQ(&d["k\"l"], Pointer("/k\"l").Get(d)); + EXPECT_EQ(&d[" "], Pointer("/ ").Get(d)); + EXPECT_EQ(&d["m~n"], Pointer("/m~0n").Get(d)); +} + +TEST(Pointer, GetWithDefault) { + Document d; + d.Parse(kJson); + + Document::AllocatorType& a = d.GetAllocator(); + const Value v("qux"); + EXPECT_TRUE(Value("bar") == Pointer("/foo/0").GetWithDefault(d, v, a)); + EXPECT_TRUE(Value("baz") == Pointer("/foo/1").GetWithDefault(d, v, a)); + EXPECT_TRUE(Value("qux") == Pointer("/foo/2").GetWithDefault(d, v, a)); +} + +TEST(Pointer, Set) { + Document d; + d.Parse(kJson); + Document::AllocatorType& a = d.GetAllocator(); + + Pointer("/foo/0").Set(d, Value(123).Move(), a); + EXPECT_EQ(123, d["foo"][0].GetInt()); + + Pointer("/foo/2").Set(d, Value(456).Move(), a); + EXPECT_EQ(456, d["foo"][2].GetInt()); +} + +TEST(Pointer, Swap) { + Document d; + d.Parse(kJson); + Document::AllocatorType& a = d.GetAllocator(); + Pointer("/foo/0").Swap(d, *Pointer("/foo/1").Get(d), a); + EXPECT_STREQ("baz", d["foo"][0].GetString()); + EXPECT_STREQ("bar", d["foo"][1].GetString()); +} From cf0ff19cac40a6fea67d76ab5b70d7e907cd889f Mon Sep 17 00:00:00 2001 From: Milo Yip Date: Fri, 10 Apr 2015 18:25:02 +0800 Subject: [PATCH 003/189] Add Pointer default/copy constructor, assignment operator. Test constructor with tokens --- include/rapidjson/pointer.h | 60 ++++++++++++++++++++++++--- test/unittest/pointertest.cpp | 76 +++++++++++++++++++++++++++++++++++ 2 files changed, 130 insertions(+), 6 deletions(-) diff --git a/include/rapidjson/pointer.h b/include/rapidjson/pointer.h index 82a4458..1ec157e 100644 --- a/include/rapidjson/pointer.h +++ b/include/rapidjson/pointer.h @@ -33,6 +33,16 @@ public: static const SizeType kInvalidIndex = ~SizeType(0); + GenericPointer() + : allocator_(), + ownAllocator_(), + nameBuffer_(), + tokens_(), + tokenCount_(), + valid_(true) + { + } + GenericPointer(const Ch* source, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), @@ -55,16 +65,27 @@ public: Parse(source, length); } - GenericPointer(const Token* tokens, size_t tokenCount) : + GenericPointer(const Token* tokens, size_t tokenCount) : allocator_(), ownAllocator_(), nameBuffer_(), - tokens_(tokens), + tokens_(const_cast(tokens)), tokenCount_(tokenCount), valid_(true) { } + GenericPointer(const GenericPointer& rhs) + : allocator_(), + ownAllocator_(), + nameBuffer_(), + tokens_(), + tokenCount_(), + valid_() + { + *this = rhs; + } + ~GenericPointer() { if (nameBuffer_) { Allocator::Free(nameBuffer_); @@ -73,6 +94,36 @@ public: RAPIDJSON_DELETE(ownAllocator_); } + GenericPointer& operator=(const GenericPointer& rhs) { + this->~GenericPointer(); + + tokenCount_ = rhs.tokenCount_; + valid_ = rhs.valid_; + + if (rhs.nameBuffer_) { + if (!allocator_) + ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator()); + + size_t nameBufferSize = tokenCount_; // null terminators + for (Token *t = rhs.tokens_; t != rhs.tokens_ + tokenCount_; ++t) + nameBufferSize += t->length; + nameBuffer_ = (Ch*)allocator_->Malloc(nameBufferSize * sizeof(Ch)); + std::memcpy(nameBuffer_, rhs.nameBuffer_, nameBufferSize); + + tokens_ = (Token*)allocator_->Malloc(tokenCount_ * sizeof(Token)); + std::memcpy(tokens_, rhs.tokens_, tokenCount_ * sizeof(Token)); + + // Adjust pointers to name buffer + std::ptrdiff_t diff = nameBuffer_ - rhs.nameBuffer_; + for (Token *t = rhs.tokens_; t != rhs.tokens_ + tokenCount_; ++t) + t->name += diff; + } + else + tokens_ = rhs.tokens_; + + return *this; + } + bool IsValid() const { return valid_; } const Token* GetTokens() const { return tokens_; } @@ -192,7 +243,7 @@ private: // Create a buffer as same size of source RAPIDJSON_ASSERT(nameBuffer_ == 0); - nameBuffer_ = (Ch*)allocator_->Malloc(length); + nameBuffer_ = (Ch*)allocator_->Malloc(length * sizeof(Ch)); RAPIDJSON_ASSERT(tokens_ == 0); tokens_ = (Token*)allocator_->Malloc(length * sizeof(Token)); // Maximum possible tokens in the source @@ -266,9 +317,6 @@ private: return; } - GenericPointer(const GenericPointer& rhs); - GenericPointer& operator=(const GenericPointer& rhs); - Allocator* allocator_; Allocator* ownAllocator_; Ch* nameBuffer_; diff --git a/test/unittest/pointertest.cpp b/test/unittest/pointertest.cpp index dbe04c0..4d4aece 100644 --- a/test/unittest/pointertest.cpp +++ b/test/unittest/pointertest.cpp @@ -166,6 +166,82 @@ TEST(Pointer, Stringify) { } } +// Construct a Pointer with static tokens, no dynamic allocation involved. +#define NAME(s) { s, sizeof(s) / sizeof(s[0]) - 1, Pointer::kInvalidIndex } +#define INDEX(i) { #i, sizeof(#i) - 1, i } + +static const Pointer::Token kTokens[] = { NAME("foo"), INDEX(0) }; // equivalent to "/foo/0" + +#undef NAME +#undef INDEX + +TEST(Pointer, ConstructorWithToken) { + Pointer p(kTokens, sizeof(kTokens) / sizeof(kTokens[0])); + EXPECT_TRUE(p.IsValid()); + EXPECT_EQ(2, p.GetTokenCount()); + EXPECT_EQ(3, p.GetTokens()[0].length); + EXPECT_STREQ("foo", p.GetTokens()[0].name); + EXPECT_EQ(1, p.GetTokens()[1].length); + EXPECT_STREQ("0", p.GetTokens()[1].name); + EXPECT_EQ(0, p.GetTokens()[1].index); +} + +TEST(Pointer, CopyConstructor) { + { + Pointer p("/foo/0"); + Pointer q(p); + EXPECT_TRUE(q.IsValid()); + EXPECT_EQ(2, q.GetTokenCount()); + EXPECT_EQ(3, q.GetTokens()[0].length); + EXPECT_STREQ("foo", q.GetTokens()[0].name); + EXPECT_EQ(1, q.GetTokens()[1].length); + EXPECT_STREQ("0", q.GetTokens()[1].name); + EXPECT_EQ(0, q.GetTokens()[1].index); + } + + // Static tokens + { + Pointer p(kTokens, sizeof(kTokens) / sizeof(kTokens[0])); + Pointer q(p); + EXPECT_TRUE(q.IsValid()); + EXPECT_EQ(2, q.GetTokenCount()); + EXPECT_EQ(3, q.GetTokens()[0].length); + EXPECT_STREQ("foo", q.GetTokens()[0].name); + EXPECT_EQ(1, q.GetTokens()[1].length); + EXPECT_STREQ("0", q.GetTokens()[1].name); + EXPECT_EQ(0, q.GetTokens()[1].index); + } +} + +TEST(Pointer, Assignment) { + { + Pointer p("/foo/0"); + Pointer q; + q = p; + EXPECT_TRUE(q.IsValid()); + EXPECT_EQ(2, q.GetTokenCount()); + EXPECT_EQ(3, q.GetTokens()[0].length); + EXPECT_STREQ("foo", q.GetTokens()[0].name); + EXPECT_EQ(1, q.GetTokens()[1].length); + EXPECT_STREQ("0", q.GetTokens()[1].name); + EXPECT_EQ(0, q.GetTokens()[1].index); + } + + // Static tokens + { + Pointer p(kTokens, sizeof(kTokens) / sizeof(kTokens[0])); + Pointer q; + q = p; + EXPECT_TRUE(q.IsValid()); + EXPECT_EQ(2, q.GetTokenCount()); + EXPECT_EQ(3, q.GetTokens()[0].length); + EXPECT_STREQ("foo", q.GetTokens()[0].name); + EXPECT_EQ(1, q.GetTokens()[1].length); + EXPECT_STREQ("0", q.GetTokens()[1].name); + EXPECT_EQ(0, q.GetTokens()[1].index); + } +} + TEST(Pointer, Create) { Document d; EXPECT_EQ(&d, &Pointer("").Create(d, d.GetAllocator())); From b2d72ef751afc618ba38a22c29d1b607c23df0a9 Mon Sep 17 00:00:00 2001 From: Milo Yip Date: Fri, 10 Apr 2015 19:28:12 +0800 Subject: [PATCH 004/189] Add XXXByPointer() helper functions --- include/rapidjson/document.h | 2 +- include/rapidjson/pointer.h | 66 +++++++++++++++++++++++++++++ test/unittest/pointertest.cpp | 78 +++++++++++++++++++++++++++++++++-- 3 files changed, 142 insertions(+), 4 deletions(-) diff --git a/include/rapidjson/document.h b/include/rapidjson/document.h index d41a87e..3b7ef2b 100644 --- a/include/rapidjson/document.h +++ b/include/rapidjson/document.h @@ -427,6 +427,7 @@ public: typedef typename GenericMemberIterator::Iterator ConstMemberIterator; //!< Constant member iterator for iterating in object. typedef GenericValue* ValueIterator; //!< Value iterator for iterating in array. typedef const GenericValue* ConstValueIterator; //!< Constant value iterator for iterating in array. + typedef GenericValue ValueType; //!< Value type of itself. //!@name Constructors and destructor. //@{ @@ -1661,7 +1662,6 @@ template , typenam class GenericDocument : public GenericValue { public: typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding. - typedef GenericValue ValueType; //!< Value type of the document. typedef Allocator AllocatorType; //!< Allocator type from template parameter. //! Constructor diff --git a/include/rapidjson/pointer.h b/include/rapidjson/pointer.h index 1ec157e..99a4c1a 100644 --- a/include/rapidjson/pointer.h +++ b/include/rapidjson/pointer.h @@ -325,6 +325,72 @@ private: bool valid_; }; +template +typename T::ValueType& CreateValueByPointer(T& root, const GenericPointer& pointer, typename T::AllocatorType& a) { + return pointer.Create(root, a); +} + +template +typename T::ValueType& CreateValueByPointer(T& root, const CharType(&source)[N], typename T::AllocatorType& a) { + const Pointer pointer(source, N - 1); + return pointer.Create(root, a); +} + +template +typename T::ValueType* GetValueByPointer(T& root, const GenericPointer& pointer) { + return pointer.Get(root); +} + +template +const typename T::ValueType* GetValueByPointer(const T& root, const GenericPointer& pointer) { + return pointer.Get(root); +} + +template +typename T::ValueType* GetValueByPointer(T& root, const CharType (&source)[N]) { + const Pointer pointer(source, N - 1); + return pointer.Get(root); +} + +template +const typename T::ValueType* GetValueByPointer(const T& root, const CharType(&source)[N]) { + const Pointer pointer(source, N - 1); + return pointer.Get(root); +} + +template +typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer& pointer, const typename T::ValueType& defaultValue, typename T::AllocatorType& a) { + return pointer.GetWithDefault(root, defaultValue, a); +} + +template +typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const typename T::ValueType& defaultValue, typename T::AllocatorType& a) { + const Pointer pointer(source, N - 1); + return pointer.GetWithDefault(root, defaultValue, a); +} + +template +typename T::ValueType& SetValueByPointer(T& root, const GenericPointer& pointer, typename T::ValueType& value, typename T::AllocatorType& a) { + return pointer.Set(root, value, a); +} + +template +typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], typename T::ValueType& value, typename T::AllocatorType& a) { + const Pointer pointer(source, N - 1); + return pointer.Set(root, value , a); +} + +template +typename T::ValueType& SwapValueByPointer(T& root, const GenericPointer& pointer, typename T::ValueType& value, typename T::AllocatorType& a) { + return pointer.Swap(root, value, a); +} + +template +typename T::ValueType& SwapValueByPointer(T& root, const CharType(&source)[N], typename T::ValueType& value, typename T::AllocatorType& a) { + const Pointer pointer(source, N - 1); + return pointer.Swap(root, value, a); +} + typedef GenericPointer Pointer; RAPIDJSON_NAMESPACE_END diff --git a/test/unittest/pointertest.cpp b/test/unittest/pointertest.cpp index 4d4aece..245fa44 100644 --- a/test/unittest/pointertest.cpp +++ b/test/unittest/pointertest.cpp @@ -244,9 +244,18 @@ TEST(Pointer, Assignment) { TEST(Pointer, Create) { Document d; - EXPECT_EQ(&d, &Pointer("").Create(d, d.GetAllocator())); - EXPECT_EQ(&d["foo"], &Pointer("/foo").Create(d, d.GetAllocator())); - EXPECT_EQ(&d["foo"][0], &Pointer("/foo/0").Create(d, d.GetAllocator())); + { + Value* v = &Pointer("").Create(d, d.GetAllocator()); + EXPECT_EQ(&d, v); + } + { + Value* v = &Pointer("/foo").Create(d, d.GetAllocator()); + EXPECT_EQ(&d["foo"], v); + } + { + Value* v = &Pointer("/foo/0").Create(d, d.GetAllocator()); + EXPECT_EQ(&d["foo"][0], v); + } } TEST(Pointer, Get) { @@ -265,6 +274,7 @@ TEST(Pointer, Get) { EXPECT_EQ(&d["k\"l"], Pointer("/k\"l").Get(d)); EXPECT_EQ(&d[" "], Pointer("/ ").Get(d)); EXPECT_EQ(&d["m~n"], Pointer("/m~0n").Get(d)); + EXPECT_TRUE(Pointer("/abc").Get(d) == 0); } TEST(Pointer, GetWithDefault) { @@ -298,3 +308,65 @@ TEST(Pointer, Swap) { EXPECT_STREQ("baz", d["foo"][0].GetString()); EXPECT_STREQ("bar", d["foo"][1].GetString()); } + +TEST(Pointer, CreateValueByPointer) { + Document d; + Document::AllocatorType& a = d.GetAllocator(); + + { + Value& v = CreateValueByPointer(d, Pointer("/foo/0"), a); + EXPECT_EQ(&d["foo"][0], &v); + } + { + Value& v = CreateValueByPointer(d, "/foo/1", a); + EXPECT_EQ(&d["foo"][1], &v); + } +} + +TEST(Pointer, GetValueByPointer) { + Document d; + d.Parse(kJson); + + EXPECT_EQ(&d["foo"][0], GetValueByPointer(d, Pointer("/foo/0"))); + EXPECT_EQ(&d["foo"][0], GetValueByPointer(d, "/foo/0")); + + // const version + const Value& v = d; + EXPECT_EQ(&d["foo"][0], GetValueByPointer(v, Pointer("/foo/0"))); + EXPECT_EQ(&d["foo"][0], GetValueByPointer(v, "/foo/0")); +} + +TEST(Pointer, GetValueByPointerWithDefault) { + Document d; + d.Parse(kJson); + + Document::AllocatorType& a = d.GetAllocator(); + const Value v("qux"); + EXPECT_TRUE(Value("bar") == GetValueByPointerWithDefault(d, Pointer("/foo/0"), v, a)); + EXPECT_TRUE(Value("baz") == GetValueByPointerWithDefault(d, "/foo/1", v, a)); +} + +TEST(Pointer, SetValueByPointer) { + Document d; + d.Parse(kJson); + Document::AllocatorType& a = d.GetAllocator(); + + SetValueByPointer(d, Pointer("/foo/0"), Value(123).Move(), a); + EXPECT_EQ(123, d["foo"][0].GetInt()); + + SetValueByPointer(d, "/foo/2", Value(456).Move(), a); + EXPECT_EQ(456, d["foo"][2].GetInt()); +} + +TEST(Pointer, SwapValueByPointer) { + Document d; + d.Parse(kJson); + Document::AllocatorType& a = d.GetAllocator(); + SwapValueByPointer(d, Pointer("/foo/0"), *GetValueByPointer(d, "/foo/1"), a); + EXPECT_STREQ("baz", d["foo"][0].GetString()); + EXPECT_STREQ("bar", d["foo"][1].GetString()); + + SwapValueByPointer(d, "/foo/0", *GetValueByPointer(d, "/foo/1"), a); + EXPECT_STREQ("bar", d["foo"][0].GetString()); + EXPECT_STREQ("baz", d["foo"][1].GetString()); +} From 601a62e5b3a8db89fd5f5c83ed7d9fe5cacfa093 Mon Sep 17 00:00:00 2001 From: Milo Yip Date: Fri, 10 Apr 2015 20:59:39 +0800 Subject: [PATCH 005/189] Try to fix a gcc/clang issue after removing Document::ValueType --- include/rapidjson/document.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/rapidjson/document.h b/include/rapidjson/document.h index 3b7ef2b..e7a707d 100644 --- a/include/rapidjson/document.h +++ b/include/rapidjson/document.h @@ -1662,6 +1662,7 @@ template , typenam class GenericDocument : public GenericValue { public: typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding. + typedef GenericValue ValueType; //!< Value type of the document. typedef Allocator AllocatorType; //!< Allocator type from template parameter. //! Constructor From 1b9cab7f12cff1b820bce66afa6ed887314b788e Mon Sep 17 00:00:00 2001 From: Milo Yip Date: Fri, 10 Apr 2015 21:40:18 +0800 Subject: [PATCH 006/189] Try to fix more gcc/clang compilation errors --- include/rapidjson/pointer.h | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/include/rapidjson/pointer.h b/include/rapidjson/pointer.h index 99a4c1a..2000b21 100644 --- a/include/rapidjson/pointer.h +++ b/include/rapidjson/pointer.h @@ -26,7 +26,7 @@ public: typedef typename EncodingType::Ch Ch; struct Token { - const typename Ch* name; + const Ch* name; SizeType length; SizeType index; //!< A valid index if not equal to kInvalidIndex. }; @@ -149,11 +149,12 @@ public: ValueType* v = &root; bool exist = true; for (Token *t = tokens_; t != tokens_ + tokenCount_; ++t) { - if (v->GetType() != kObjectType && v->GetType() != kArrayType) + if (v->GetType() != kObjectType && v->GetType() != kArrayType) { if (t->index == kInvalidIndex) v->SetObject(); else v->SetArray(); + } switch (v->GetType()) { case kObjectType: @@ -220,8 +221,10 @@ public: ValueType& GetWithDefault(ValueType& root, const ValueType& defaultValue, typename ValueType::AllocatorType& allocator) const { bool alreadyExist; Value& v = Create(root, allocator, &alreadyExist); - if (!alreadyExist) - v = Value(defaultValue, allocator); + if (!alreadyExist) { + Value clone(defaultValue, allocator); + v = clone; + } return v; } @@ -332,7 +335,7 @@ typename T::ValueType& CreateValueByPointer(T& root, const GenericPointer typename T::ValueType& CreateValueByPointer(T& root, const CharType(&source)[N], typename T::AllocatorType& a) { - const Pointer pointer(source, N - 1); + const GenericPointer pointer(source, N - 1); return pointer.Create(root, a); } @@ -348,13 +351,13 @@ const typename T::ValueType* GetValueByPointer(const T& root, const GenericPoint template typename T::ValueType* GetValueByPointer(T& root, const CharType (&source)[N]) { - const Pointer pointer(source, N - 1); + const GenericPointer pointer(source, N - 1); return pointer.Get(root); } template const typename T::ValueType* GetValueByPointer(const T& root, const CharType(&source)[N]) { - const Pointer pointer(source, N - 1); + const GenericPointer pointer(source, N - 1); return pointer.Get(root); } @@ -365,7 +368,7 @@ typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointe template typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const typename T::ValueType& defaultValue, typename T::AllocatorType& a) { - const Pointer pointer(source, N - 1); + const GenericPointer pointer(source, N - 1); return pointer.GetWithDefault(root, defaultValue, a); } @@ -376,7 +379,7 @@ typename T::ValueType& SetValueByPointer(T& root, const GenericPointer typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], typename T::ValueType& value, typename T::AllocatorType& a) { - const Pointer pointer(source, N - 1); + const GenericPointer pointer(source, N - 1); return pointer.Set(root, value , a); } @@ -387,7 +390,7 @@ typename T::ValueType& SwapValueByPointer(T& root, const GenericPointer typename T::ValueType& SwapValueByPointer(T& root, const CharType(&source)[N], typename T::ValueType& value, typename T::AllocatorType& a) { - const Pointer pointer(source, N - 1); + const GenericPointer pointer(source, N - 1); return pointer.Swap(root, value, a); } From dfc864b1d3544c8bbd1f51721ef78a097da97843 Mon Sep 17 00:00:00 2001 From: Milo Yip Date: Fri, 10 Apr 2015 22:06:56 +0800 Subject: [PATCH 007/189] Fix a bug in Pointer::Create() which makes it very slow --- include/rapidjson/pointer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/rapidjson/pointer.h b/include/rapidjson/pointer.h index 2000b21..421a2cb 100644 --- a/include/rapidjson/pointer.h +++ b/include/rapidjson/pointer.h @@ -173,7 +173,7 @@ public: if (t->index == kInvalidIndex) v->SetArray(); // Change to Array if (t->index >= v->Size()) { - v->Reserve(t->index - 1, allocator); + v->Reserve(t->index + 1, allocator); while (t->index >= v->Size()) v->PushBack(Value().Move(), allocator); exist = false; From 26be3be5c795f7bd829078188400df5a072e03a4 Mon Sep 17 00:00:00 2001 From: Milo Yip Date: Fri, 10 Apr 2015 22:12:59 +0800 Subject: [PATCH 008/189] Fix several clang/gcc warnings --- include/rapidjson/pointer.h | 4 ++ test/unittest/pointertest.cpp | 82 +++++++++++++++++------------------ 2 files changed, 45 insertions(+), 41 deletions(-) diff --git a/include/rapidjson/pointer.h b/include/rapidjson/pointer.h index 421a2cb..7954e12 100644 --- a/include/rapidjson/pointer.h +++ b/include/rapidjson/pointer.h @@ -180,6 +180,10 @@ public: } v = &((*v)[t->index]); break; + default: + // Impossible. + RAPIDJSON_ASSERT(false); + break; } } diff --git a/test/unittest/pointertest.cpp b/test/unittest/pointertest.cpp index 245fa44..3147959 100644 --- a/test/unittest/pointertest.cpp +++ b/test/unittest/pointertest.cpp @@ -42,34 +42,34 @@ TEST(Pointer, Parse) { { Pointer p(""); EXPECT_TRUE(p.IsValid()); - EXPECT_EQ(0, p.GetTokenCount()); + EXPECT_EQ(0u, p.GetTokenCount()); } { Pointer p("/foo"); EXPECT_TRUE(p.IsValid()); - EXPECT_EQ(1, p.GetTokenCount()); - EXPECT_EQ(3, p.GetTokens()[0].length); + EXPECT_EQ(1u, p.GetTokenCount()); + EXPECT_EQ(3u, p.GetTokens()[0].length); EXPECT_STREQ("foo", p.GetTokens()[0].name); } { Pointer p("/foo/0"); EXPECT_TRUE(p.IsValid()); - EXPECT_EQ(2, p.GetTokenCount()); - EXPECT_EQ(3, p.GetTokens()[0].length); + EXPECT_EQ(2u, p.GetTokenCount()); + EXPECT_EQ(3u, p.GetTokens()[0].length); EXPECT_STREQ("foo", p.GetTokens()[0].name); - EXPECT_EQ(1, p.GetTokens()[1].length); + EXPECT_EQ(1u, p.GetTokens()[1].length); EXPECT_STREQ("0", p.GetTokens()[1].name); - EXPECT_EQ(0, p.GetTokens()[1].index); + EXPECT_EQ(0u, p.GetTokens()[1].index); } { // Unescape ~1 Pointer p("/a~1b"); EXPECT_TRUE(p.IsValid()); - EXPECT_EQ(1, p.GetTokenCount()); - EXPECT_EQ(3, p.GetTokens()[0].length); + EXPECT_EQ(1u, p.GetTokenCount()); + EXPECT_EQ(3u, p.GetTokens()[0].length); EXPECT_STREQ("a/b", p.GetTokens()[0].name); } @@ -77,8 +77,8 @@ TEST(Pointer, Parse) { // Unescape ~0 Pointer p("/m~0n"); EXPECT_TRUE(p.IsValid()); - EXPECT_EQ(1, p.GetTokenCount()); - EXPECT_EQ(3, p.GetTokens()[0].length); + EXPECT_EQ(1u, p.GetTokenCount()); + EXPECT_EQ(3u, p.GetTokens()[0].length); EXPECT_STREQ("m~n", p.GetTokens()[0].name); } @@ -86,8 +86,8 @@ TEST(Pointer, Parse) { // empty name Pointer p("/"); EXPECT_TRUE(p.IsValid()); - EXPECT_EQ(1, p.GetTokenCount()); - EXPECT_EQ(0, p.GetTokens()[0].length); + EXPECT_EQ(1u, p.GetTokenCount()); + EXPECT_EQ(0u, p.GetTokens()[0].length); EXPECT_STREQ("", p.GetTokens()[0].name); } @@ -95,10 +95,10 @@ TEST(Pointer, Parse) { // empty and non-empty name Pointer p("//a"); EXPECT_TRUE(p.IsValid()); - EXPECT_EQ(2, p.GetTokenCount()); - EXPECT_EQ(0, p.GetTokens()[0].length); + EXPECT_EQ(2u, p.GetTokenCount()); + EXPECT_EQ(0u, p.GetTokens()[0].length); EXPECT_STREQ("", p.GetTokens()[0].name); - EXPECT_EQ(1, p.GetTokens()[1].length); + EXPECT_EQ(1u, p.GetTokens()[1].length); EXPECT_STREQ("a", p.GetTokens()[1].name); } @@ -106,8 +106,8 @@ TEST(Pointer, Parse) { // Null characters Pointer p("/\0\0", 3); EXPECT_TRUE(p.IsValid()); - EXPECT_EQ(1, p.GetTokenCount()); - EXPECT_EQ(2, p.GetTokens()[0].length); + EXPECT_EQ(1u, p.GetTokenCount()); + EXPECT_EQ(2u, p.GetTokens()[0].length); EXPECT_EQ('\0', p.GetTokens()[0].name[0]); EXPECT_EQ('\0', p.GetTokens()[0].name[1]); EXPECT_EQ('\0', p.GetTokens()[0].name[2]); @@ -117,7 +117,7 @@ TEST(Pointer, Parse) { // Valid index Pointer p("/123"); EXPECT_TRUE(p.IsValid()); - EXPECT_EQ(1, p.GetTokenCount()); + EXPECT_EQ(1u, p.GetTokenCount()); EXPECT_STREQ("123", p.GetTokens()[0].name); EXPECT_EQ(123, p.GetTokens()[0].index); } @@ -126,7 +126,7 @@ TEST(Pointer, Parse) { // Invalid index (with leading zero) Pointer p("/01"); EXPECT_TRUE(p.IsValid()); - EXPECT_EQ(1, p.GetTokenCount()); + EXPECT_EQ(1u, p.GetTokenCount()); EXPECT_STREQ("01", p.GetTokens()[0].name); EXPECT_EQ(Pointer::kInvalidIndex, p.GetTokens()[0].index); } @@ -135,7 +135,7 @@ TEST(Pointer, Parse) { // Invalid index (overflow) Pointer p("/4294967296"); EXPECT_TRUE(p.IsValid()); - EXPECT_EQ(1, p.GetTokenCount()); + EXPECT_EQ(1u, p.GetTokenCount()); EXPECT_STREQ("4294967296", p.GetTokens()[0].name); EXPECT_EQ(Pointer::kInvalidIndex, p.GetTokens()[0].index); } @@ -178,12 +178,12 @@ static const Pointer::Token kTokens[] = { NAME("foo"), INDEX(0) }; // equivalent TEST(Pointer, ConstructorWithToken) { Pointer p(kTokens, sizeof(kTokens) / sizeof(kTokens[0])); EXPECT_TRUE(p.IsValid()); - EXPECT_EQ(2, p.GetTokenCount()); - EXPECT_EQ(3, p.GetTokens()[0].length); + EXPECT_EQ(2u, p.GetTokenCount()); + EXPECT_EQ(3u, p.GetTokens()[0].length); EXPECT_STREQ("foo", p.GetTokens()[0].name); - EXPECT_EQ(1, p.GetTokens()[1].length); + EXPECT_EQ(1u, p.GetTokens()[1].length); EXPECT_STREQ("0", p.GetTokens()[1].name); - EXPECT_EQ(0, p.GetTokens()[1].index); + EXPECT_EQ(0u, p.GetTokens()[1].index); } TEST(Pointer, CopyConstructor) { @@ -191,12 +191,12 @@ TEST(Pointer, CopyConstructor) { Pointer p("/foo/0"); Pointer q(p); EXPECT_TRUE(q.IsValid()); - EXPECT_EQ(2, q.GetTokenCount()); - EXPECT_EQ(3, q.GetTokens()[0].length); + EXPECT_EQ(2u, q.GetTokenCount()); + EXPECT_EQ(3u, q.GetTokens()[0].length); EXPECT_STREQ("foo", q.GetTokens()[0].name); - EXPECT_EQ(1, q.GetTokens()[1].length); + EXPECT_EQ(1u, q.GetTokens()[1].length); EXPECT_STREQ("0", q.GetTokens()[1].name); - EXPECT_EQ(0, q.GetTokens()[1].index); + EXPECT_EQ(0u, q.GetTokens()[1].index); } // Static tokens @@ -204,12 +204,12 @@ TEST(Pointer, CopyConstructor) { Pointer p(kTokens, sizeof(kTokens) / sizeof(kTokens[0])); Pointer q(p); EXPECT_TRUE(q.IsValid()); - EXPECT_EQ(2, q.GetTokenCount()); - EXPECT_EQ(3, q.GetTokens()[0].length); + EXPECT_EQ(2u, q.GetTokenCount()); + EXPECT_EQ(3u, q.GetTokens()[0].length); EXPECT_STREQ("foo", q.GetTokens()[0].name); - EXPECT_EQ(1, q.GetTokens()[1].length); + EXPECT_EQ(1u, q.GetTokens()[1].length); EXPECT_STREQ("0", q.GetTokens()[1].name); - EXPECT_EQ(0, q.GetTokens()[1].index); + EXPECT_EQ(0u, q.GetTokens()[1].index); } } @@ -219,12 +219,12 @@ TEST(Pointer, Assignment) { Pointer q; q = p; EXPECT_TRUE(q.IsValid()); - EXPECT_EQ(2, q.GetTokenCount()); - EXPECT_EQ(3, q.GetTokens()[0].length); + EXPECT_EQ(2u, q.GetTokenCount()); + EXPECT_EQ(3u, q.GetTokens()[0].length); EXPECT_STREQ("foo", q.GetTokens()[0].name); - EXPECT_EQ(1, q.GetTokens()[1].length); + EXPECT_EQ(1u, q.GetTokens()[1].length); EXPECT_STREQ("0", q.GetTokens()[1].name); - EXPECT_EQ(0, q.GetTokens()[1].index); + EXPECT_EQ(0u, q.GetTokens()[1].index); } // Static tokens @@ -233,12 +233,12 @@ TEST(Pointer, Assignment) { Pointer q; q = p; EXPECT_TRUE(q.IsValid()); - EXPECT_EQ(2, q.GetTokenCount()); - EXPECT_EQ(3, q.GetTokens()[0].length); + EXPECT_EQ(2u, q.GetTokenCount()); + EXPECT_EQ(3u, q.GetTokens()[0].length); EXPECT_STREQ("foo", q.GetTokens()[0].name); - EXPECT_EQ(1, q.GetTokens()[1].length); + EXPECT_EQ(1u, q.GetTokens()[1].length); EXPECT_STREQ("0", q.GetTokens()[1].name); - EXPECT_EQ(0, q.GetTokens()[1].index); + EXPECT_EQ(0u, q.GetTokens()[1].index); } } From e0743b2fb0ace5d3ceedc11c20f7c3b35df1f1fd Mon Sep 17 00:00:00 2001 From: Milo Yip Date: Fri, 10 Apr 2015 22:43:46 +0800 Subject: [PATCH 009/189] Fix a clang/gcc warning --- test/unittest/pointertest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unittest/pointertest.cpp b/test/unittest/pointertest.cpp index 3147959..c23e9b8 100644 --- a/test/unittest/pointertest.cpp +++ b/test/unittest/pointertest.cpp @@ -119,7 +119,7 @@ TEST(Pointer, Parse) { EXPECT_TRUE(p.IsValid()); EXPECT_EQ(1u, p.GetTokenCount()); EXPECT_STREQ("123", p.GetTokens()[0].name); - EXPECT_EQ(123, p.GetTokens()[0].index); + EXPECT_EQ(123u, p.GetTokens()[0].index); } { From c7bcdb9c0cf0b9e7b9e1b121fdc776030f0af676 Mon Sep 17 00:00:00 2001 From: Milo Yip Date: Fri, 10 Apr 2015 23:06:17 +0800 Subject: [PATCH 010/189] Fix a clang/gcc linker error static const member integer not working --- include/rapidjson/pointer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/rapidjson/pointer.h b/include/rapidjson/pointer.h index 7954e12..4f77ba2 100644 --- a/include/rapidjson/pointer.h +++ b/include/rapidjson/pointer.h @@ -31,7 +31,7 @@ public: SizeType index; //!< A valid index if not equal to kInvalidIndex. }; - static const SizeType kInvalidIndex = ~SizeType(0); + enum { kInvalidIndex = ~SizeType(0) }; GenericPointer() : allocator_(), From bd435f76abc4f8e1f9f8301f510bbf225312ee18 Mon Sep 17 00:00:00 2001 From: Milo Yip Date: Fri, 10 Apr 2015 23:32:28 +0800 Subject: [PATCH 011/189] Another trial to fix the kInvalidIndex problem --- include/rapidjson/pointer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/rapidjson/pointer.h b/include/rapidjson/pointer.h index 4f77ba2..66cbdef 100644 --- a/include/rapidjson/pointer.h +++ b/include/rapidjson/pointer.h @@ -31,7 +31,7 @@ public: SizeType index; //!< A valid index if not equal to kInvalidIndex. }; - enum { kInvalidIndex = ~SizeType(0) }; + static const SizeType kInvalidIndex = -1; GenericPointer() : allocator_(), From 6ee691550f22c419579a457a0d7b1c9bc642f1f2 Mon Sep 17 00:00:00 2001 From: miloyip Date: Sat, 11 Apr 2015 14:48:33 +0800 Subject: [PATCH 012/189] Move GenericPointer::kInvalidIndex to rapidjson::kPointerInvalidIndex It is needed to prevent linking error for gcc/clang --- include/rapidjson/pointer.h | 14 +++++++------- test/unittest/pointertest.cpp | 6 +++--- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/include/rapidjson/pointer.h b/include/rapidjson/pointer.h index 66cbdef..6ee6abc 100644 --- a/include/rapidjson/pointer.h +++ b/include/rapidjson/pointer.h @@ -19,6 +19,8 @@ RAPIDJSON_NAMESPACE_BEGIN +static const SizeType kPointerInvalidIndex = ~SizeType(0); + template class GenericPointer { public: @@ -28,11 +30,9 @@ public: struct Token { const Ch* name; SizeType length; - SizeType index; //!< A valid index if not equal to kInvalidIndex. + SizeType index; //!< A valid index if not equal to kPointerInvalidIndex. }; - static const SizeType kInvalidIndex = -1; - GenericPointer() : allocator_(), ownAllocator_(), @@ -150,7 +150,7 @@ public: bool exist = true; for (Token *t = tokens_; t != tokens_ + tokenCount_; ++t) { if (v->GetType() != kObjectType && v->GetType() != kArrayType) { - if (t->index == kInvalidIndex) + if (t->index == kPointerInvalidIndex) v->SetObject(); else v->SetArray(); @@ -170,7 +170,7 @@ public: } break; case kArrayType: - if (t->index == kInvalidIndex) + if (t->index == kPointerInvalidIndex) v->SetArray(); // Change to Array if (t->index >= v->Size()) { v->Reserve(t->index + 1, allocator); @@ -207,7 +207,7 @@ public: } break; case kArrayType: - if (t->index == kInvalidIndex || t->index >= v->Size()) + if (t->index == kPointerInvalidIndex || t->index >= v->Size()) return 0; v = &((*v)[t->index]); break; @@ -307,7 +307,7 @@ private: } } - token.index = isNumber ? n : kInvalidIndex; + token.index = isNumber ? n : kPointerInvalidIndex; } RAPIDJSON_ASSERT(name <= nameBuffer_ + length); // Should not overflow buffer diff --git a/test/unittest/pointertest.cpp b/test/unittest/pointertest.cpp index c23e9b8..98a006d 100644 --- a/test/unittest/pointertest.cpp +++ b/test/unittest/pointertest.cpp @@ -128,7 +128,7 @@ TEST(Pointer, Parse) { EXPECT_TRUE(p.IsValid()); EXPECT_EQ(1u, p.GetTokenCount()); EXPECT_STREQ("01", p.GetTokens()[0].name); - EXPECT_EQ(Pointer::kInvalidIndex, p.GetTokens()[0].index); + EXPECT_EQ(kPointerInvalidIndex, p.GetTokens()[0].index); } if (sizeof(SizeType) == 4) { @@ -137,7 +137,7 @@ TEST(Pointer, Parse) { EXPECT_TRUE(p.IsValid()); EXPECT_EQ(1u, p.GetTokenCount()); EXPECT_STREQ("4294967296", p.GetTokens()[0].name); - EXPECT_EQ(Pointer::kInvalidIndex, p.GetTokens()[0].index); + EXPECT_EQ(kPointerInvalidIndex, p.GetTokens()[0].index); } } @@ -167,7 +167,7 @@ TEST(Pointer, Stringify) { } // Construct a Pointer with static tokens, no dynamic allocation involved. -#define NAME(s) { s, sizeof(s) / sizeof(s[0]) - 1, Pointer::kInvalidIndex } +#define NAME(s) { s, sizeof(s) / sizeof(s[0]) - 1, kPointerInvalidIndex } #define INDEX(i) { #i, sizeof(#i) - 1, i } static const Pointer::Token kTokens[] = { NAME("foo"), INDEX(0) }; // equivalent to "/foo/0" From a7763cbecac80f9e4cdf8321440614aaf281fb71 Mon Sep 17 00:00:00 2001 From: miloyip Date: Thu, 16 Apr 2015 09:42:22 +0800 Subject: [PATCH 013/189] Fix allocator test --- test/unittest/allocatorstest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unittest/allocatorstest.cpp b/test/unittest/allocatorstest.cpp index 2cf9a2e..774bf9b 100644 --- a/test/unittest/allocatorstest.cpp +++ b/test/unittest/allocatorstest.cpp @@ -57,7 +57,7 @@ TEST(Allocator, MemoryPoolAllocator) { MemoryPoolAllocator<> a; TestAllocator(a); - for (int i = 0; i < 1000; i++) { + for (int i = 1; i < 1000; i++) { EXPECT_TRUE(a.Malloc(i) != 0); EXPECT_LE(a.Size(), a.Capacity()); } From 22021d6622ec6650ba64bccb17fc491af7aeb02f Mon Sep 17 00:00:00 2001 From: miloyip Date: Thu, 16 Apr 2015 10:15:23 +0800 Subject: [PATCH 014/189] Converts tabs to spaces --- include/rapidjson/reader.h | 68 +++++++++++++++++++------------------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/include/rapidjson/reader.h b/include/rapidjson/reader.h index 31a145f..08297a0 100644 --- a/include/rapidjson/reader.h +++ b/include/rapidjson/reader.h @@ -255,23 +255,23 @@ void SkipWhitespace(InputStream& is) { #ifdef RAPIDJSON_SSE42 //! Skip whitespace with SSE 4.2 pcmpistrm instruction, testing 16 8-byte characters at once. inline const char *SkipWhitespace_SIMD(const char* p) { - // Fast return for single non-whitespace - if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t') - ++p; - else - return p; + // Fast return for single non-whitespace + if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t') + ++p; + else + return p; - // 16-byte align to the next boundary - const char* nextAligned = reinterpret_cast((reinterpret_cast(p) + 15) & ~15); - while (p != nextAligned) - if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t') - ++p; - else - return p; + // 16-byte align to the next boundary + const char* nextAligned = reinterpret_cast((reinterpret_cast(p) + 15) & ~15); + while (p != nextAligned) + if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t') + ++p; + else + return p; // The rest of string using SIMD - static const char whitespace[16] = " \n\r\t"; - const __m128i w = _mm_load_si128((const __m128i *)&whitespace[0]); + static const char whitespace[16] = " \n\r\t"; + const __m128i w = _mm_load_si128((const __m128i *)&whitespace[0]); for (;; p += 16) { const __m128i s = _mm_load_si128((const __m128i *)p); @@ -292,31 +292,31 @@ inline const char *SkipWhitespace_SIMD(const char* p) { //! Skip whitespace with SSE2 instructions, testing 16 8-byte characters at once. inline const char *SkipWhitespace_SIMD(const char* p) { - // Fast return for single non-whitespace - if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t') - ++p; - else - return p; + // Fast return for single non-whitespace + if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t') + ++p; + else + return p; // 16-byte align to the next boundary - const char* nextAligned = reinterpret_cast((reinterpret_cast(p) + 15) & ~15); - while (p != nextAligned) - if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t') - ++p; - else - return p; + const char* nextAligned = reinterpret_cast((reinterpret_cast(p) + 15) & ~15); + while (p != nextAligned) + if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t') + ++p; + else + return p; // The rest of string - static const char whitespaces[4][17] = { - " ", - "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n", - "\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r", - "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"}; + static const char whitespaces[4][17] = { + " ", + "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n", + "\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r", + "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"}; - const __m128i w0 = _mm_loadu_si128((const __m128i *)&whitespaces[0][0]); - const __m128i w1 = _mm_loadu_si128((const __m128i *)&whitespaces[1][0]); - const __m128i w2 = _mm_loadu_si128((const __m128i *)&whitespaces[2][0]); - const __m128i w3 = _mm_loadu_si128((const __m128i *)&whitespaces[3][0]); + const __m128i w0 = _mm_loadu_si128((const __m128i *)&whitespaces[0][0]); + const __m128i w1 = _mm_loadu_si128((const __m128i *)&whitespaces[1][0]); + const __m128i w2 = _mm_loadu_si128((const __m128i *)&whitespaces[2][0]); + const __m128i w3 = _mm_loadu_si128((const __m128i *)&whitespaces[3][0]); for (;; p += 16) { const __m128i s = _mm_load_si128((const __m128i *)p); From 556d154bed5329abb479def1a32431ca6721df39 Mon Sep 17 00:00:00 2001 From: miloyip Date: Thu, 16 Apr 2015 10:34:45 +0800 Subject: [PATCH 015/189] Search sample data in more folders for perftest --- test/perftest/perftest.h | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/test/perftest/perftest.h b/test/perftest/perftest.h index 2fca203..4c955a4 100644 --- a/test/perftest/perftest.h +++ b/test/perftest/perftest.h @@ -71,9 +71,20 @@ public: PerfTest() : filename_(), json_(), length_(), whitespace_(), whitespace_length_() {} virtual void SetUp() { - FILE *fp = fopen(filename_ = "data/sample.json", "rb"); - if (!fp) - fp = fopen(filename_ = "../../bin/data/sample.json", "rb"); + + const char *paths[] = { + "data/sample.json", + "bin/data/sample.json", + "../bin/data/sample.json", + "../../bin/data/sample.json", + "../../../bin/data/sample.json" + }; + FILE *fp = 0; + for (size_t i = 0; i < sizeof(paths) / sizeof(paths[0]); i++) { + fp = fopen(paths[i], "rb"); + if (fp) + break; + } ASSERT_TRUE(fp != 0); fseek(fp, 0, SEEK_END); From 30ace6fa95f692743dd0f0e3efff6cafe4168691 Mon Sep 17 00:00:00 2001 From: miloyip Date: Thu, 16 Apr 2015 10:55:42 +0800 Subject: [PATCH 016/189] Fix mistake in perftest --- test/perftest/perftest.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/perftest/perftest.h b/test/perftest/perftest.h index 4c955a4..3198905 100644 --- a/test/perftest/perftest.h +++ b/test/perftest/perftest.h @@ -81,7 +81,7 @@ public: }; FILE *fp = 0; for (size_t i = 0; i < sizeof(paths) / sizeof(paths[0]); i++) { - fp = fopen(paths[i], "rb"); + fp = fopen(filename_ = paths[i], "rb"); if (fp) break; } From 0c5c1538dcfc7f160e5a4aa208ddf092c787be5a Mon Sep 17 00:00:00 2001 From: "Philipp A. Hartmann" Date: Thu, 16 Apr 2015 21:05:08 +0200 Subject: [PATCH 017/189] Avoid calling memcpy with NULL pointers According to the C/C++ standards, calling `memcpy(NULL, NULL, 0)` is undefined behaviour. Recent GCC versions may rely on this by optimizing NULL pointer checks more aggressively, see [1]. This patch tries to avoid calling std::memcpy with zero elements. As a side effect, explicitly return NULL when requesting an empty block from MemoryPoolAllocator::Malloc. This may be related to #301. [1] https://gcc.gnu.org/gcc-4.9/porting_to.html --- include/rapidjson/allocators.h | 7 ++++++- include/rapidjson/document.h | 16 ++++++++++++---- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/include/rapidjson/allocators.h b/include/rapidjson/allocators.h index 7b348b6..d3dcb12 100644 --- a/include/rapidjson/allocators.h +++ b/include/rapidjson/allocators.h @@ -160,6 +160,9 @@ public: //! Allocates a memory block. (concept Allocator) void* Malloc(size_t size) { + if (!size) + return NULL; + size = RAPIDJSON_ALIGN(size); if (chunkHead_ == 0 || chunkHead_->size + size > chunkHead_->capacity) AddChunk(chunk_capacity_ > size ? chunk_capacity_ : size); @@ -191,7 +194,9 @@ public: // Realloc process: allocate and copy memory, do not free original buffer. void* newBuffer = Malloc(newSize); RAPIDJSON_ASSERT(newBuffer != 0); // Do not handle out-of-memory explicitly. - return std::memcpy(newBuffer, originalPtr, originalSize); + if (originalSize) + std::memcpy(newBuffer, originalPtr, originalSize); + return newBuffer; } //! Frees a memory block (concept Allocator) diff --git a/include/rapidjson/document.h b/include/rapidjson/document.h index 204e3bd..3aaef13 100644 --- a/include/rapidjson/document.h +++ b/include/rapidjson/document.h @@ -1582,16 +1582,24 @@ private: // Initialize this value as array with initial data, without calling destructor. void SetArrayRaw(GenericValue* values, SizeType count, Allocator& allocator) { flags_ = kArrayFlag; - data_.a.elements = (GenericValue*)allocator.Malloc(count * sizeof(GenericValue)); - std::memcpy(data_.a.elements, values, count * sizeof(GenericValue)); + if (count) { + data_.a.elements = (GenericValue*)allocator.Malloc(count * sizeof(GenericValue)); + std::memcpy(data_.a.elements, values, count * sizeof(GenericValue)); + } + else + data_.a.elements = NULL; data_.a.size = data_.a.capacity = count; } //! Initialize this value as object with initial data, without calling destructor. void SetObjectRaw(Member* members, SizeType count, Allocator& allocator) { flags_ = kObjectFlag; - data_.o.members = (Member*)allocator.Malloc(count * sizeof(Member)); - std::memcpy(data_.o.members, members, count * sizeof(Member)); + if (count) { + data_.o.members = (Member*)allocator.Malloc(count * sizeof(Member)); + std::memcpy(data_.o.members, members, count * sizeof(Member)); + } + else + data_.o.members = NULL; data_.o.size = data_.o.capacity = count; } From 0e8bbe5e3ef375e7f052f556878be0bd79e9062d Mon Sep 17 00:00:00 2001 From: Milo Yip Date: Fri, 17 Apr 2015 13:01:14 +0800 Subject: [PATCH 018/189] Standardize behavior of CrtAllocator::Malloc() --- include/rapidjson/allocators.h | 7 ++++++- test/unittest/allocatorstest.cpp | 2 ++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/include/rapidjson/allocators.h b/include/rapidjson/allocators.h index d3dcb12..d68b74c 100644 --- a/include/rapidjson/allocators.h +++ b/include/rapidjson/allocators.h @@ -62,7 +62,12 @@ concept Allocator { class CrtAllocator { public: static const bool kNeedFree = true; - void* Malloc(size_t size) { return std::malloc(size); } + void* Malloc(size_t size) { + if (size) // behavior of malloc(0) is implementation defined. + return std::malloc(size); + else + return NULL; // standardize to returning NULL. + } void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) { (void)originalSize; return std::realloc(originalPtr, newSize); } static void Free(void *ptr) { std::free(ptr); } }; diff --git a/test/unittest/allocatorstest.cpp b/test/unittest/allocatorstest.cpp index 774bf9b..1dba812 100644 --- a/test/unittest/allocatorstest.cpp +++ b/test/unittest/allocatorstest.cpp @@ -26,6 +26,8 @@ using namespace rapidjson; template void TestAllocator(Allocator& a) { + EXPECT_TRUE(a.Malloc(0) == 0); + uint8_t* p = (uint8_t*)a.Malloc(100); EXPECT_TRUE(p != 0); for (size_t i = 0; i < 100; i++) From aa61b08d11b84921e595aa51767726c1bd6f8233 Mon Sep 17 00:00:00 2001 From: miloyip Date: Sat, 18 Apr 2015 20:30:40 +0800 Subject: [PATCH 019/189] Fix warnings for misctest --- test/perftest/misctest.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/perftest/misctest.cpp b/test/perftest/misctest.cpp index 3edadda..6b276e4 100644 --- a/test/perftest/misctest.cpp +++ b/test/perftest/misctest.cpp @@ -768,7 +768,7 @@ template void itoa_Writer_StringBufferVerify() { rapidjson::StringBuffer sb; Writer writer(sb); - for (int j = 0; j < randvalCount; j++) { + for (size_t j = 0; j < randvalCount; j++) { char buffer[32]; sprintf(buffer, "%d", randval[j]); writer.WriteInt(randval[j]); @@ -780,7 +780,7 @@ void itoa_Writer_StringBufferVerify() { template void itoa_Writer_InsituStringStreamVerify() { Writer writer; - for (int j = 0; j < randvalCount; j++) { + for (size_t j = 0; j < randvalCount; j++) { char buffer[32]; sprintf(buffer, "%d", randval[j]); char buffer2[32]; From 8d39282af507629575215de919189babd5d35f01 Mon Sep 17 00:00:00 2001 From: miloyip Date: Sat, 18 Apr 2015 21:41:38 +0800 Subject: [PATCH 020/189] Update license headers for tests --- include/rapidjson/rapidjson.h | 3 --- test/perftest/misctest.cpp | 26 ++++++++++---------------- test/perftest/perftest.cpp | 26 ++++++++++---------------- test/perftest/perftest.h | 26 ++++++++++---------------- test/perftest/platformtest.cpp | 26 ++++++++++---------------- test/perftest/rapidjsontest.cpp | 26 ++++++++++---------------- test/unittest/allocatorstest.cpp | 26 ++++++++++---------------- test/unittest/bigintegertest.cpp | 26 ++++++++++---------------- test/unittest/documenttest.cpp | 26 ++++++++++---------------- test/unittest/encodedstreamtest.cpp | 26 ++++++++++---------------- test/unittest/encodingstest.cpp | 26 ++++++++++---------------- test/unittest/filestreamtest.cpp | 26 ++++++++++---------------- test/unittest/itoatest.cpp | 26 ++++++++++---------------- test/unittest/jsoncheckertest.cpp | 26 ++++++++++---------------- test/unittest/namespacetest.cpp | 26 ++++++++++---------------- test/unittest/prettywritertest.cpp | 26 ++++++++++---------------- test/unittest/readertest.cpp | 26 ++++++++++---------------- test/unittest/simdtest.cpp | 26 ++++++++++---------------- test/unittest/stringbuffertest.cpp | 26 ++++++++++---------------- test/unittest/strtodtest.cpp | 26 ++++++++++---------------- test/unittest/unittest.cpp | 26 ++++++++++---------------- test/unittest/unittest.h | 26 ++++++++++---------------- test/unittest/valuetest.cpp | 26 ++++++++++---------------- test/unittest/writertest.cpp | 26 ++++++++++---------------- 24 files changed, 230 insertions(+), 371 deletions(-) diff --git a/include/rapidjson/rapidjson.h b/include/rapidjson/rapidjson.h index 602dabd..4351aea 100644 --- a/include/rapidjson/rapidjson.h +++ b/include/rapidjson/rapidjson.h @@ -15,9 +15,6 @@ #ifndef RAPIDJSON_RAPIDJSON_H_ #define RAPIDJSON_RAPIDJSON_H_ -// Copyright (c) 2011 Milo Yip (miloyip@gmail.com) -// Version 0.1 - /*!\file rapidjson.h \brief common definitions and configuration diff --git a/test/perftest/misctest.cpp b/test/perftest/misctest.cpp index 6b276e4..c6b3353 100644 --- a/test/perftest/misctest.cpp +++ b/test/perftest/misctest.cpp @@ -1,22 +1,16 @@ -// Copyright (C) 2011 Milo Yip +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. // -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at // -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. +// http://opensource.org/licenses/MIT // -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. #include "perftest.h" diff --git a/test/perftest/perftest.cpp b/test/perftest/perftest.cpp index 4366e1c..38ba07e 100644 --- a/test/perftest/perftest.cpp +++ b/test/perftest/perftest.cpp @@ -1,22 +1,16 @@ -// Copyright (C) 2011 Milo Yip +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. // -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at // -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. +// http://opensource.org/licenses/MIT // -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. #include "perftest.h" diff --git a/test/perftest/perftest.h b/test/perftest/perftest.h index 3198905..2b0984c 100644 --- a/test/perftest/perftest.h +++ b/test/perftest/perftest.h @@ -1,22 +1,16 @@ -// Copyright (C) 2011 Milo Yip +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. // -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at // -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. +// http://opensource.org/licenses/MIT // -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. #ifndef PERFTEST_H_ #define PERFTEST_H_ diff --git a/test/perftest/platformtest.cpp b/test/perftest/platformtest.cpp index 30b690c..7ea2a8e 100644 --- a/test/perftest/platformtest.cpp +++ b/test/perftest/platformtest.cpp @@ -1,22 +1,16 @@ -// Copyright (C) 2011 Milo Yip +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. // -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at // -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. +// http://opensource.org/licenses/MIT // -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. #include "perftest.h" diff --git a/test/perftest/rapidjsontest.cpp b/test/perftest/rapidjsontest.cpp index 875c5eb..05ecf6e 100644 --- a/test/perftest/rapidjsontest.cpp +++ b/test/perftest/rapidjsontest.cpp @@ -1,22 +1,16 @@ -// Copyright (C) 2011 Milo Yip +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. // -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at // -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. +// http://opensource.org/licenses/MIT // -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. #include "perftest.h" diff --git a/test/unittest/allocatorstest.cpp b/test/unittest/allocatorstest.cpp index 1dba812..3f33724 100644 --- a/test/unittest/allocatorstest.cpp +++ b/test/unittest/allocatorstest.cpp @@ -1,22 +1,16 @@ -// Copyright (C) 2011 Milo Yip +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. // -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at // -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. +// http://opensource.org/licenses/MIT // -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. #include "unittest.h" diff --git a/test/unittest/bigintegertest.cpp b/test/unittest/bigintegertest.cpp index e7b3b8f..a68e144 100644 --- a/test/unittest/bigintegertest.cpp +++ b/test/unittest/bigintegertest.cpp @@ -1,22 +1,16 @@ -// Copyright (C) 2011 Milo Yip +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. // -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at // -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. +// http://opensource.org/licenses/MIT // -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. #include "unittest.h" diff --git a/test/unittest/documenttest.cpp b/test/unittest/documenttest.cpp index dd4fb13..71cd777 100644 --- a/test/unittest/documenttest.cpp +++ b/test/unittest/documenttest.cpp @@ -1,22 +1,16 @@ -// Copyright (C) 2011 Milo Yip +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. // -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at // -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. +// http://opensource.org/licenses/MIT // -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. #include "unittest.h" #include "rapidjson/document.h" diff --git a/test/unittest/encodedstreamtest.cpp b/test/unittest/encodedstreamtest.cpp index 5affb5d..8cef208 100644 --- a/test/unittest/encodedstreamtest.cpp +++ b/test/unittest/encodedstreamtest.cpp @@ -1,22 +1,16 @@ -// Copyright (C) 2011 Milo Yip +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. // -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at // -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. +// http://opensource.org/licenses/MIT // -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. #include "unittest.h" #include "rapidjson/filereadstream.h" diff --git a/test/unittest/encodingstest.cpp b/test/unittest/encodingstest.cpp index 3beebe6..b697d91 100644 --- a/test/unittest/encodingstest.cpp +++ b/test/unittest/encodingstest.cpp @@ -1,22 +1,16 @@ -// Copyright (C) 2011 Milo Yip +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. // -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at // -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. +// http://opensource.org/licenses/MIT // -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. #include "unittest.h" #include "rapidjson/filereadstream.h" diff --git a/test/unittest/filestreamtest.cpp b/test/unittest/filestreamtest.cpp index 1fd5d19..2850b56 100644 --- a/test/unittest/filestreamtest.cpp +++ b/test/unittest/filestreamtest.cpp @@ -1,22 +1,16 @@ -// Copyright (C) 2011 Milo Yip +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. // -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at // -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. +// http://opensource.org/licenses/MIT // -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. #include "unittest.h" #include "rapidjson/filereadstream.h" diff --git a/test/unittest/itoatest.cpp b/test/unittest/itoatest.cpp index 31a008c..5ceb99f 100644 --- a/test/unittest/itoatest.cpp +++ b/test/unittest/itoatest.cpp @@ -1,22 +1,16 @@ -// Copyright (C) 2011 Milo Yip +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. // -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at // -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. +// http://opensource.org/licenses/MIT // -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. #include "unittest.h" #include "rapidjson/internal/itoa.h" diff --git a/test/unittest/jsoncheckertest.cpp b/test/unittest/jsoncheckertest.cpp index a89b8d2..34f8569 100644 --- a/test/unittest/jsoncheckertest.cpp +++ b/test/unittest/jsoncheckertest.cpp @@ -1,22 +1,16 @@ -// Copyright (C) 2011 Milo Yip +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. // -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at // -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. +// http://opensource.org/licenses/MIT // -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. #include "unittest.h" diff --git a/test/unittest/namespacetest.cpp b/test/unittest/namespacetest.cpp index ed74ae3..5db83cc 100644 --- a/test/unittest/namespacetest.cpp +++ b/test/unittest/namespacetest.cpp @@ -1,22 +1,16 @@ -// Copyright (C) 2011 Milo Yip +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. // -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at // -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. +// http://opensource.org/licenses/MIT // -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. #include "unittest.h" diff --git a/test/unittest/prettywritertest.cpp b/test/unittest/prettywritertest.cpp index 6ae14b9..1a63c82 100644 --- a/test/unittest/prettywritertest.cpp +++ b/test/unittest/prettywritertest.cpp @@ -1,22 +1,16 @@ -// Copyright (C) 2011 Milo Yip +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. // -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at // -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. +// http://opensource.org/licenses/MIT // -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. #include "unittest.h" #include "rapidjson/reader.h" diff --git a/test/unittest/readertest.cpp b/test/unittest/readertest.cpp index 0b4196f..4e8d4e4 100644 --- a/test/unittest/readertest.cpp +++ b/test/unittest/readertest.cpp @@ -1,22 +1,16 @@ -// Copyright (C) 2011 Milo Yip +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. // -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at // -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. +// http://opensource.org/licenses/MIT // -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. #include "unittest.h" diff --git a/test/unittest/simdtest.cpp b/test/unittest/simdtest.cpp index 217db07..c8f4587 100644 --- a/test/unittest/simdtest.cpp +++ b/test/unittest/simdtest.cpp @@ -1,22 +1,16 @@ -// Copyright (C) 2011 Milo Yip +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. // -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at // -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. +// http://opensource.org/licenses/MIT // -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. // Since Travis CI installs old Valgrind 3.7.0, which fails with some SSE4.2 // The unit tests prefix with SIMD should be skipped by Valgrind test diff --git a/test/unittest/stringbuffertest.cpp b/test/unittest/stringbuffertest.cpp index 7cfde4f..fbacf51 100644 --- a/test/unittest/stringbuffertest.cpp +++ b/test/unittest/stringbuffertest.cpp @@ -1,22 +1,16 @@ -// Copyright (C) 2011 Milo Yip +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. // -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at // -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. +// http://opensource.org/licenses/MIT // -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. #include "unittest.h" #include "rapidjson/stringbuffer.h" diff --git a/test/unittest/strtodtest.cpp b/test/unittest/strtodtest.cpp index d8849be..dc2378b 100644 --- a/test/unittest/strtodtest.cpp +++ b/test/unittest/strtodtest.cpp @@ -1,22 +1,16 @@ -// Copyright (C) 2011 Milo Yip +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. // -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at // -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. +// http://opensource.org/licenses/MIT // -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. #include "unittest.h" diff --git a/test/unittest/unittest.cpp b/test/unittest/unittest.cpp index 4604d9d..c475179 100644 --- a/test/unittest/unittest.cpp +++ b/test/unittest/unittest.cpp @@ -1,22 +1,16 @@ -// Copyright (C) 2011 Milo Yip +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. // -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at // -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. +// http://opensource.org/licenses/MIT // -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. #include "unittest.h" diff --git a/test/unittest/unittest.h b/test/unittest/unittest.h index 800fbab..dbba754 100644 --- a/test/unittest/unittest.h +++ b/test/unittest/unittest.h @@ -1,22 +1,16 @@ -// Copyright (C) 2011 Milo Yip +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. // -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at // -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. +// http://opensource.org/licenses/MIT // -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. #ifndef UNITTEST_H_ #define UNITTEST_H_ diff --git a/test/unittest/valuetest.cpp b/test/unittest/valuetest.cpp index fa9547b..1922222 100644 --- a/test/unittest/valuetest.cpp +++ b/test/unittest/valuetest.cpp @@ -1,22 +1,16 @@ -// Copyright (C) 2011 Milo Yip +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. // -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at // -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. +// http://opensource.org/licenses/MIT // -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. #include "unittest.h" #include "rapidjson/document.h" diff --git a/test/unittest/writertest.cpp b/test/unittest/writertest.cpp index 85d533d..2adb551 100644 --- a/test/unittest/writertest.cpp +++ b/test/unittest/writertest.cpp @@ -1,22 +1,16 @@ -// Copyright (C) 2011 Milo Yip +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. // -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at // -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. +// http://opensource.org/licenses/MIT // -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. #include "unittest.h" From 5ab1e9361db34edfb228e6d7df81e1842ef7b4ab Mon Sep 17 00:00:00 2001 From: miloyip Date: Tue, 21 Apr 2015 16:38:49 +0800 Subject: [PATCH 021/189] Add version macros for RapidJSON --- CMakeLists.txt | 4 ++-- include/rapidjson/rapidjson.h | 39 ++++++++++++++++++++++++++++++----- test/unittest/unittest.cpp | 3 +++ 3 files changed, 39 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9c823ac..94919f0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,8 +3,8 @@ SET(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/CMakeModules) PROJECT(RapidJSON CXX) -set(LIB_MAJOR_VERSION "0") -set(LIB_MINOR_VERSION "12") +set(LIB_MAJOR_VERSION "1") +set(LIB_MINOR_VERSION "0") set(LIB_PATCH_VERSION "0") set(LIB_VERSION_STRING "${LIB_MAJOR_VERSION}.${LIB_MINOR_VERSION}.${LIB_PATCH_VERSION}") diff --git a/include/rapidjson/rapidjson.h b/include/rapidjson/rapidjson.h index 4351aea..021468b 100644 --- a/include/rapidjson/rapidjson.h +++ b/include/rapidjson/rapidjson.h @@ -17,7 +17,7 @@ /*!\file rapidjson.h \brief common definitions and configuration - + \see RAPIDJSON_CONFIG */ @@ -39,6 +39,39 @@ #include // malloc(), realloc(), free(), size_t #include // memset(), memcpy(), memmove(), memcmp() +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_VERSION_STRING +// +// ALWAYS synchronize the following 3 macros with corresponding variables in /CMakeLists.txt. +// + +//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN +// token stringification +#define RAPIDJSON_STRINGIFY(x) RAPIDJSON_DO_STRINGIFY(x) +#define RAPIDJSON_DO_STRINGIFY(x) #x +//!@endcond + +/*! \def RAPIDJSON_MAJOR_VERSION + \ingroup RAPIDJSON_CONFIG + \brief Major version of RapidJSON in integer. +*/ +/*! \def RAPIDJSON_MINOR_VERSION + \ingroup RAPIDJSON_CONFIG + \brief Minor version of RapidJSON in integer. +*/ +/*! \def RAPIDJSON_PATCH_VERSION + \ingroup RAPIDJSON_CONFIG + \brief Patch version of RapidJSON in integer. +*/ +/*! \def RAPIDJSON_VERSION_STRING + \ingroup RAPIDJSON_CONFIG + \brief Version of RapidJSON in ".." string format. +*/ +#define RAPIDJSON_MAJOR_VERSION 1 +#define RAPIDJSON_MINOR_VERSION 0 +#define RAPIDJSON_PATCH_VERSION 0 +#define RAPIDJSON_VERSION_STRING RAPIDJSON_STRINGIFY(RAPIDJSON_MAJOR_VERSION) "." RAPIDJSON_STRINGIFY(RAPIDJSON_MINOR_VERSION) "." RAPIDJSON_STRINGIFY(RAPIDJSON_PATCH_VERSION) + /////////////////////////////////////////////////////////////////////////////// // RAPIDJSON_NAMESPACE_(BEGIN|END) /*! \def RAPIDJSON_NAMESPACE @@ -353,10 +386,6 @@ RAPIDJSON_NAMESPACE_END #define RAPIDJSON_VERSION_CODE(x,y,z) \ (((x)*100000) + ((y)*100) + (z)) -// token stringification -#define RAPIDJSON_STRINGIFY(x) RAPIDJSON_DO_STRINGIFY(x) -#define RAPIDJSON_DO_STRINGIFY(x) #x - /////////////////////////////////////////////////////////////////////////////// // RAPIDJSON_DIAG_PUSH/POP, RAPIDJSON_DIAG_OFF diff --git a/test/unittest/unittest.cpp b/test/unittest/unittest.cpp index c475179..4e3bc11 100644 --- a/test/unittest/unittest.cpp +++ b/test/unittest/unittest.cpp @@ -13,10 +13,13 @@ // specific language governing permissions and limitations under the License. #include "unittest.h" +#include "rapidjson/rapidjson.h" int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); + std::cout << "RapidJSON v" << RAPIDJSON_VERSION_STRING << std::endl; + #if _MSC_VER _CrtMemState memoryState = { 0 }; _CrtMemCheckpoint(&memoryState); From 95c6ec97c419da7832db28f5b1a01f6cdc0580ab Mon Sep 17 00:00:00 2001 From: miloyip Date: Tue, 21 Apr 2015 17:28:31 +0800 Subject: [PATCH 022/189] Add release badge to readmes --- readme.md | 3 +++ readme.zh-cn.md | 2 ++ 2 files changed, 5 insertions(+) diff --git a/readme.md b/readme.md index 8a7264f..007596a 100644 --- a/readme.md +++ b/readme.md @@ -1,4 +1,7 @@ ![](doc/logo/rapidjson.png) + +![](https://img.shields.io/badge/release-v1.0.0-blue.png) + ## A fast JSON parser/generator for C++ with both SAX/DOM style API Tencent is pleased to support the open source community by making RapidJSON available. diff --git a/readme.zh-cn.md b/readme.zh-cn.md index 91ab10d..be3849a 100644 --- a/readme.zh-cn.md +++ b/readme.zh-cn.md @@ -1,5 +1,7 @@ ![](doc/logo/rapidjson.png) +![](https://img.shields.io/badge/release-v1.0.0-blue.png) + Tencent is pleased to support the open source community by making RapidJSON available. Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. From 04b673686af52d673185f822812799812dd161a3 Mon Sep 17 00:00:00 2001 From: Andrii Senkovych Date: Tue, 21 Apr 2015 13:10:08 +0300 Subject: [PATCH 023/189] Introduce option to select default gtest installation. Refs #309 This will introduce RAPIDJSON_BUILD_THIRDPARTY_GTEST option. If it is set to TRUE, cmake will look for GTest installation in `thirdparty/gtest` before looking in other places. Current default value (OFF) for RAPIDJSON_BUILD_THIRDPARTY_GTEST represents previous behaviour when system-wide gtest installation is used whenever possible. This commit will as well eliminate problem described in #309 when source directory found is `thirdparty/gtest` while include files are found system-wide. This however won't give the user possibility to select gtest installation to use. --- CMakeLists.txt | 2 ++ CMakeModules/FindGTestSrc.cmake | 8 +++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9c823ac..cf6b46f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,6 +17,8 @@ SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) option(RAPIDJSON_BUILD_DOC "Build rapidjson documentation." ON) option(RAPIDJSON_BUILD_EXAMPLES "Build rapidjson examples." ON) option(RAPIDJSON_BUILD_TESTS "Build rapidjson perftests and unittests." ON) +option(RAPIDJSON_BUILD_THIRDPARTY_GTEST + "Use gtest installation in `thirdparty/gtest` by default if available" OFF) option(RAPIDJSON_HAS_STDSTRING "" OFF) if(RAPIDJSON_HAS_STDSTRING) diff --git a/CMakeModules/FindGTestSrc.cmake b/CMakeModules/FindGTestSrc.cmake index 13b1c7b..b5abc19 100644 --- a/CMakeModules/FindGTestSrc.cmake +++ b/CMakeModules/FindGTestSrc.cmake @@ -1,9 +1,14 @@ + SET(GTEST_SEARCH_PATH "${GTEST_SOURCE_DIR}" "${CMAKE_SOURCE_DIR}/thirdparty/gtest") IF(UNIX) - LIST(INSERT GTEST_SEARCH_PATH 1 "/usr/src/gtest") + IF(RAPIDJSON_BUILD_THIRDPARTY_GTEST) + LIST(APPEND GTEST_SEARCH_PATH "/usr/src/gtest") + ELSE() + LIST(INSERT GTEST_SEARCH_PATH 1 "/usr/src/gtest") + ENDIF() ENDIF() FIND_PATH(GTEST_SOURCE_DIR @@ -15,6 +20,7 @@ FIND_PATH(GTEST_SOURCE_DIR FIND_PATH(GTEST_INCLUDE_DIR NAMES gtest/gtest.h PATH_SUFFIXES include + HINTS ${GTEST_SOURCE_DIR} PATHS ${GTEST_SEARCH_PATH}) INCLUDE(FindPackageHandleStandardArgs) From 5ab3f69910ce33b6aed5d8de5ff56c2c6b277f88 Mon Sep 17 00:00:00 2001 From: miloyip Date: Wed, 22 Apr 2015 09:19:18 +0800 Subject: [PATCH 024/189] Simplify RAPIDJSON_VERSION_STRING --- include/rapidjson/rapidjson.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/rapidjson/rapidjson.h b/include/rapidjson/rapidjson.h index 021468b..938a3ce 100644 --- a/include/rapidjson/rapidjson.h +++ b/include/rapidjson/rapidjson.h @@ -70,7 +70,8 @@ #define RAPIDJSON_MAJOR_VERSION 1 #define RAPIDJSON_MINOR_VERSION 0 #define RAPIDJSON_PATCH_VERSION 0 -#define RAPIDJSON_VERSION_STRING RAPIDJSON_STRINGIFY(RAPIDJSON_MAJOR_VERSION) "." RAPIDJSON_STRINGIFY(RAPIDJSON_MINOR_VERSION) "." RAPIDJSON_STRINGIFY(RAPIDJSON_PATCH_VERSION) +#define RAPIDJSON_VERSION_STRING \ + RAPIDJSON_STRINGIFY(RAPIDJSON_MAJOR_VERSION.RAPIDJSON_MINOR_VERSION.RAPIDJSON_PATCH_VERSION) /////////////////////////////////////////////////////////////////////////////// // RAPIDJSON_NAMESPACE_(BEGIN|END) From b2e53523bf4a12fe120ceaa16e3b5c7da1672f41 Mon Sep 17 00:00:00 2001 From: miloyip Date: Wed, 22 Apr 2015 09:24:56 +0800 Subject: [PATCH 025/189] Change version in appveyor --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index d1a9108..890f9d9 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,4 @@ -version: 0.12.{build} +version: 1.0.0.{build} configuration: - Debug From 93d13ad2acc6a52d58e09d84e76826cd36ee64f0 Mon Sep 17 00:00:00 2001 From: Milo Yip Date: Fri, 24 Apr 2015 21:44:42 +0800 Subject: [PATCH 026/189] Fix #313 Assertion In `Pow10.h` is triggered in Document::Parse --- include/rapidjson/reader.h | 5 +++++ test/unittest/readertest.cpp | 14 +++++++++----- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/include/rapidjson/reader.h b/include/rapidjson/reader.h index 08297a0..320428f 100644 --- a/include/rapidjson/reader.h +++ b/include/rapidjson/reader.h @@ -929,6 +929,11 @@ private: exp = exp * 10 + (s.Take() - '0'); if (exp > 308 && !expMinus) // exp > 308 should be rare, so it should be checked first. RAPIDJSON_PARSE_ERROR(kParseErrorNumberTooBig, s.Tell()); + else if (exp >= 429496729 && expMinus) { // Issue #313: prevent overflow exponent + while (s.Peek() >= '0' && s.Peek() <= '9') // Consume the rest of exponent + s.Take(); + break; + } } } else diff --git a/test/unittest/readertest.cpp b/test/unittest/readertest.cpp index 4e8d4e4..86199fa 100644 --- a/test/unittest/readertest.cpp +++ b/test/unittest/readertest.cpp @@ -219,13 +219,17 @@ static void TestParseDouble() { TEST_DOUBLE(fullPrecision, "2.2250738585072009e-308", 2.2250738585072009e-308); // Max subnormal double TEST_DOUBLE(fullPrecision, "2.2250738585072014e-308", 2.2250738585072014e-308); // Min normal positive double TEST_DOUBLE(fullPrecision, "1.7976931348623157e+308", 1.7976931348623157e+308); // Max double - TEST_DOUBLE(fullPrecision, "1e-10000", 0.0); // must underflow - TEST_DOUBLE(fullPrecision, "18446744073709551616", 18446744073709551616.0); // 2^64 (max of uint64_t + 1, force to use double) - TEST_DOUBLE(fullPrecision, "-9223372036854775809", -9223372036854775809.0); // -2^63 - 1(min of int64_t + 1, force to use double) - TEST_DOUBLE(fullPrecision, "0.9868011474609375", 0.9868011474609375); // https://github.com/miloyip/rapidjson/issues/120 - TEST_DOUBLE(fullPrecision, "123e34", 123e34); // Fast Path Cases In Disguise + TEST_DOUBLE(fullPrecision, "1e-10000", 0.0); // must underflow + TEST_DOUBLE(fullPrecision, "18446744073709551616", 18446744073709551616.0); // 2^64 (max of uint64_t + 1, force to use double) + TEST_DOUBLE(fullPrecision, "-9223372036854775809", -9223372036854775809.0); // -2^63 - 1(min of int64_t + 1, force to use double) + TEST_DOUBLE(fullPrecision, "0.9868011474609375", 0.9868011474609375); // https://github.com/miloyip/rapidjson/issues/120 + TEST_DOUBLE(fullPrecision, "123e34", 123e34); // Fast Path Cases In Disguise TEST_DOUBLE(fullPrecision, "45913141877270640000.0", 45913141877270640000.0); TEST_DOUBLE(fullPrecision, "2.2250738585072011e-308", 2.2250738585072011e-308); // http://www.exploringbinary.com/php-hangs-on-numeric-value-2-2250738585072011e-308/ + TEST_DOUBLE(fullPrecision, "1e-00011111111111", 0.0); // Issue #313 + TEST_DOUBLE(fullPrecision, "-1e-00011111111111", -0.0); + TEST_DOUBLE(fullPrecision, "1e-429496729", 0.0); // Maximum supported negative exponent + // Since // abs((2^-1022 - 2^-1074) - 2.2250738585072012e-308) = 3.109754131239141401123495768877590405345064751974375599... ¡Á 10^-324 From 735354efd328709a8efb6a2a43a584bb85f2de6b Mon Sep 17 00:00:00 2001 From: Milo Yip Date: Fri, 24 Apr 2015 22:50:42 +0800 Subject: [PATCH 027/189] Separate handling for pos/neg exp and improve pos exp overflow --- include/rapidjson/reader.h | 23 +++++++++++++++-------- test/unittest/readertest.cpp | 1 + 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/include/rapidjson/reader.h b/include/rapidjson/reader.h index 320428f..d809d57 100644 --- a/include/rapidjson/reader.h +++ b/include/rapidjson/reader.h @@ -925,14 +925,21 @@ private: if (s.Peek() >= '0' && s.Peek() <= '9') { exp = s.Take() - '0'; - while (s.Peek() >= '0' && s.Peek() <= '9') { - exp = exp * 10 + (s.Take() - '0'); - if (exp > 308 && !expMinus) // exp > 308 should be rare, so it should be checked first. - RAPIDJSON_PARSE_ERROR(kParseErrorNumberTooBig, s.Tell()); - else if (exp >= 429496729 && expMinus) { // Issue #313: prevent overflow exponent - while (s.Peek() >= '0' && s.Peek() <= '9') // Consume the rest of exponent - s.Take(); - break; + if (expMinus) { + while (s.Peek() >= '0' && s.Peek() <= '9') { + exp = exp * 10 + (s.Take() - '0'); + if (exp >= 429496729) { // Issue #313: prevent overflow exponent + while (s.Peek() >= '0' && s.Peek() <= '9') // Consume the rest of exponent + s.Take(); + } + } + } + else { // positive exp + int maxExp = 308 - expFrac; + while (s.Peek() >= '0' && s.Peek() <= '9') { + exp = exp * 10 + (s.Take() - '0'); + if (exp > maxExp) + RAPIDJSON_PARSE_ERROR(kParseErrorNumberTooBig, s.Tell()); } } } diff --git a/test/unittest/readertest.cpp b/test/unittest/readertest.cpp index 86199fa..e55380c 100644 --- a/test/unittest/readertest.cpp +++ b/test/unittest/readertest.cpp @@ -229,6 +229,7 @@ static void TestParseDouble() { TEST_DOUBLE(fullPrecision, "1e-00011111111111", 0.0); // Issue #313 TEST_DOUBLE(fullPrecision, "-1e-00011111111111", -0.0); TEST_DOUBLE(fullPrecision, "1e-429496729", 0.0); // Maximum supported negative exponent + TEST_DOUBLE(fullPrecision, "0.017976931348623157e+310", 1.7976931348623157e+308); // Max double in another form // Since From 7708215b609733bcfa06074b67463920c03782e8 Mon Sep 17 00:00:00 2001 From: Milo Yip Date: Sat, 25 Apr 2015 00:13:09 +0800 Subject: [PATCH 028/189] Try to fix #313 again --- include/rapidjson/reader.h | 2 +- test/unittest/readertest.cpp | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/include/rapidjson/reader.h b/include/rapidjson/reader.h index d809d57..be0d9fb 100644 --- a/include/rapidjson/reader.h +++ b/include/rapidjson/reader.h @@ -928,7 +928,7 @@ private: if (expMinus) { while (s.Peek() >= '0' && s.Peek() <= '9') { exp = exp * 10 + (s.Take() - '0'); - if (exp >= 429496729) { // Issue #313: prevent overflow exponent + if (exp >= 214748364) { // Issue #313: prevent overflow exponent while (s.Peek() >= '0' && s.Peek() <= '9') // Consume the rest of exponent s.Take(); } diff --git a/test/unittest/readertest.cpp b/test/unittest/readertest.cpp index e55380c..bee19a8 100644 --- a/test/unittest/readertest.cpp +++ b/test/unittest/readertest.cpp @@ -228,9 +228,10 @@ static void TestParseDouble() { TEST_DOUBLE(fullPrecision, "2.2250738585072011e-308", 2.2250738585072011e-308); // http://www.exploringbinary.com/php-hangs-on-numeric-value-2-2250738585072011e-308/ TEST_DOUBLE(fullPrecision, "1e-00011111111111", 0.0); // Issue #313 TEST_DOUBLE(fullPrecision, "-1e-00011111111111", -0.0); - TEST_DOUBLE(fullPrecision, "1e-429496729", 0.0); // Maximum supported negative exponent + TEST_DOUBLE(fullPrecision, "1e-214748363", 0.0); // Maximum supported negative exponent + TEST_DOUBLE(fullPrecision, "1e-214748364", 0.0); + TEST_DOUBLE(fullPrecision, "1e-21474836311", 0.0); TEST_DOUBLE(fullPrecision, "0.017976931348623157e+310", 1.7976931348623157e+308); // Max double in another form - // Since // abs((2^-1022 - 2^-1074) - 2.2250738585072012e-308) = 3.109754131239141401123495768877590405345064751974375599... ¡Á 10^-324 From a9250d170dc7474bf4c7441de587b4933515b127 Mon Sep 17 00:00:00 2001 From: Adam Mitz Date: Fri, 24 Apr 2015 13:32:00 -0500 Subject: [PATCH 029/189] Fixed to build on older versions of 32-bit MSVC --- include/rapidjson/internal/diyfp.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/include/rapidjson/internal/diyfp.h b/include/rapidjson/internal/diyfp.h index de3d1f0..033a2a2 100644 --- a/include/rapidjson/internal/diyfp.h +++ b/include/rapidjson/internal/diyfp.h @@ -19,12 +19,10 @@ #ifndef RAPIDJSON_DIYFP_H_ #define RAPIDJSON_DIYFP_H_ -#if defined(_MSC_VER) +#if defined(_MSC_VER) && defined(_M_AMD64) #include -#if defined(_M_AMD64) #pragma intrinsic(_BitScanReverse64) #endif -#endif RAPIDJSON_NAMESPACE_BEGIN namespace internal { From 4f20541339bb5ba251ded2b14cef348e43eb0e7c Mon Sep 17 00:00:00 2001 From: Milo Yip Date: Sat, 25 Apr 2015 09:49:31 +0800 Subject: [PATCH 030/189] Add change log --- CHANGELOG.md | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..3938cbf --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,59 @@ +# Change Log +All notable changes to this project will be documented in this file. +This project adheres to [Semantic Versioning](http://semver.org/). + +## [Unreleased] + +## [1.0.1] - 2015-04-25 + +### Added +* Changelog following [Keep a CHANGELOG](https://github.com/olivierlacan/keep-a-changelog) suggestions. + +### Fixed +* Parsing of some numbers (e.g. "1e-00011111111111") causing assertion (#314). +* Visual C++ 32-bit compilation error in `diyfp.h` (#317). + +## [1.0.0] - 2015-04-22 + +### Added +* 100% [Coverall](https://coveralls.io/r/miloyip/rapidjson?branch=master) coverage. +* Version macros (#311) + +### Fixed +* A bug in trimming long number sequence (4824f12efbf01af72b8cb6fc96fae7b097b73015). +* Double quote in unicode escape (#288). +* Negative zero roundtrip (double only) (#289). +* Standardize behavior of `memcpy()` and `malloc()` (0c5c1538dcfc7f160e5a4aa208ddf092c787be5a, #305, 0e8bbe5e3ef375e7f052f556878be0bd79e9062d). + +### Removed +* Remove an invalid `Document::ParseInsitu()` API (e7f1c6dd08b522cfcf9aed58a333bd9a0c0ccbeb). + +## [1.0 Beta] - 2015-04-8 + +### Added +* RFC 7159 (#101) +* Optional Iterative Parser (#76) +* Deep-copy values (#20) +* Error code and message (#27) +* ASCII Encoding (#70) +* `kParseStopWhenDoneFlag` (#83) +* `kParseFullPrecisionFlag` (881c91d696f06b7f302af6d04ec14dd08db66ceb) +* Add `Key()` to handler concept (#134) +* C++11 compatibility and support (#128) +* Optimized number-to-string and vice versa conversions (#137, #80) +* Short-String Optimization (#131) +* Local stream optimization by traits (#32) +* Travis & Appveyor Continuous Integration, with Valgrind verification (#24, #242) +* Redo all documentation (English, Simplified Chinese) + +### Changed +* Copyright ownership transfered to THL A29 Limited (a Tencent company). +* Migrating from Premake to CMAKE (#192) +* Resolve all warning reports + +### Removed +* Remove other JSON libraries for performance comparison (#180) + +## [0.11] - 2012-11-16 + +## [0.1] - 2011-11-18 From 316292d5189e9e7e3565b6d9423576a6a3cf73f4 Mon Sep 17 00:00:00 2001 From: Milo Yip Date: Sat, 25 Apr 2015 09:52:59 +0800 Subject: [PATCH 031/189] Change version to 1.0.1 --- CMakeLists.txt | 2 +- appveyor.yml | 2 +- include/rapidjson/rapidjson.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 559312b..380bdcd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,7 +5,7 @@ PROJECT(RapidJSON CXX) set(LIB_MAJOR_VERSION "1") set(LIB_MINOR_VERSION "0") -set(LIB_PATCH_VERSION "0") +set(LIB_PATCH_VERSION "1") set(LIB_VERSION_STRING "${LIB_MAJOR_VERSION}.${LIB_MINOR_VERSION}.${LIB_PATCH_VERSION}") # compile in release with debug info mode by default diff --git a/appveyor.yml b/appveyor.yml index 890f9d9..add4017 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,4 @@ -version: 1.0.0.{build} +version: 1.0.1.{build} configuration: - Debug diff --git a/include/rapidjson/rapidjson.h b/include/rapidjson/rapidjson.h index 938a3ce..0c41ab6 100644 --- a/include/rapidjson/rapidjson.h +++ b/include/rapidjson/rapidjson.h @@ -69,7 +69,7 @@ */ #define RAPIDJSON_MAJOR_VERSION 1 #define RAPIDJSON_MINOR_VERSION 0 -#define RAPIDJSON_PATCH_VERSION 0 +#define RAPIDJSON_PATCH_VERSION 1 #define RAPIDJSON_VERSION_STRING \ RAPIDJSON_STRINGIFY(RAPIDJSON_MAJOR_VERSION.RAPIDJSON_MINOR_VERSION.RAPIDJSON_PATCH_VERSION) From 2e913bfea6fd199126a0bb343fb2e86bda2359cf Mon Sep 17 00:00:00 2001 From: Milo Yip Date: Sat, 25 Apr 2015 10:18:30 +0800 Subject: [PATCH 032/189] Update readme badge to version 1.0.1 also --- readme.md | 2 +- readme.zh-cn.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/readme.md b/readme.md index 007596a..98f81a7 100644 --- a/readme.md +++ b/readme.md @@ -1,6 +1,6 @@ ![](doc/logo/rapidjson.png) -![](https://img.shields.io/badge/release-v1.0.0-blue.png) +![](https://img.shields.io/badge/release-v1.0.1-blue.png) ## A fast JSON parser/generator for C++ with both SAX/DOM style API diff --git a/readme.zh-cn.md b/readme.zh-cn.md index be3849a..2dd27cf 100644 --- a/readme.zh-cn.md +++ b/readme.zh-cn.md @@ -1,6 +1,6 @@ ![](doc/logo/rapidjson.png) -![](https://img.shields.io/badge/release-v1.0.0-blue.png) +![](https://img.shields.io/badge/release-v1.0.1-blue.png) Tencent is pleased to support the open source community by making RapidJSON available. From a592e199e7e9ef10a4059f2ec18f59dcd1b7ec3c Mon Sep 17 00:00:00 2001 From: Milo Yip Date: Sat, 25 Apr 2015 15:53:51 +0800 Subject: [PATCH 033/189] Update CHANGELOG.md --- CHANGELOG.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3938cbf..dd0e4ed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] -## [1.0.1] - 2015-04-25 +## [v1.0.1] - 2015-04-25 ### Added * Changelog following [Keep a CHANGELOG](https://github.com/olivierlacan/keep-a-changelog) suggestions. @@ -13,7 +13,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). * Parsing of some numbers (e.g. "1e-00011111111111") causing assertion (#314). * Visual C++ 32-bit compilation error in `diyfp.h` (#317). -## [1.0.0] - 2015-04-22 +## [v1.0.0] - 2015-04-22 ### Added * 100% [Coverall](https://coveralls.io/r/miloyip/rapidjson?branch=master) coverage. @@ -28,7 +28,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). ### Removed * Remove an invalid `Document::ParseInsitu()` API (e7f1c6dd08b522cfcf9aed58a333bd9a0c0ccbeb). -## [1.0 Beta] - 2015-04-8 +## [v1.0 Beta] - 2015-04-8 ### Added * RFC 7159 (#101) @@ -54,6 +54,6 @@ This project adheres to [Semantic Versioning](http://semver.org/). ### Removed * Remove other JSON libraries for performance comparison (#180) -## [0.11] - 2012-11-16 +## 0.11 - 2012-11-16 -## [0.1] - 2011-11-18 +## 0.1 - 2011-11-18 From d2269f65f60d12b96228918619d8df606fc61de2 Mon Sep 17 00:00:00 2001 From: Milo Yip Date: Sat, 25 Apr 2015 16:01:10 +0800 Subject: [PATCH 034/189] Update CHANGELOG.md --- CHANGELOG.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dd0e4ed..07d732b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] -## [v1.0.1] - 2015-04-25 +## [1.0.1] - 2015-04-25 ### Added * Changelog following [Keep a CHANGELOG](https://github.com/olivierlacan/keep-a-changelog) suggestions. @@ -13,7 +13,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). * Parsing of some numbers (e.g. "1e-00011111111111") causing assertion (#314). * Visual C++ 32-bit compilation error in `diyfp.h` (#317). -## [v1.0.0] - 2015-04-22 +## [1.0.0] - 2015-04-22 ### Added * 100% [Coverall](https://coveralls.io/r/miloyip/rapidjson?branch=master) coverage. @@ -28,7 +28,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). ### Removed * Remove an invalid `Document::ParseInsitu()` API (e7f1c6dd08b522cfcf9aed58a333bd9a0c0ccbeb). -## [v1.0 Beta] - 2015-04-8 +## 1.0-beta - 2015-04-8 ### Added * RFC 7159 (#101) @@ -57,3 +57,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). ## 0.11 - 2012-11-16 ## 0.1 - 2011-11-18 + +[Unreleased]: https://github.com/miloyip/rapidjson/compare/v1.0.1...HEAD +[1.0.1]: https://github.com/miloyip/rapidjson/compare/v1.0.0...v1.0.1 +[1.0.0]: https://github.com/miloyip/rapidjson/compare/v1.0-beta...v1.0.0 From 8f891403bc22f691173898c2e7b76574eac2a86b Mon Sep 17 00:00:00 2001 From: Guo Xiao Date: Sun, 26 Apr 2015 20:54:03 +0800 Subject: [PATCH 035/189] Fix warnings when visited via https --- doc/faq.md | 2 +- doc/misc/footer.html | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/faq.md b/doc/faq.md index 85afcd3..b00b4c6 100644 --- a/doc/faq.md +++ b/doc/faq.md @@ -28,7 +28,7 @@ 6. How to install RapidJSON? - Check [Installation section](http://miloyip.github.io/rapidjson/). + Check [Installation section](https://miloyip.github.io/rapidjson/). 7. Can RapidJSON run on my platform? diff --git a/doc/misc/footer.html b/doc/misc/footer.html index edf3e69..843aa11 100644 --- a/doc/misc/footer.html +++ b/doc/misc/footer.html @@ -18,10 +18,10 @@ (document.getElementsByClassName('contents')[0]).appendChild(dt); var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true; - dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js'; + dsq.src = '//' + disqus_shortname + '.disqus.com/embed.js'; (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq); })(); - \ No newline at end of file + From dba6d6f1b51f03016fcd62dd90b480ea50f29dc8 Mon Sep 17 00:00:00 2001 From: miloyip Date: Tue, 28 Apr 2015 10:09:37 +0800 Subject: [PATCH 036/189] Include rapidjson.h in error/error.h and internal/*.h Fixes #321 --- CHANGELOG.md | 2 ++ include/rapidjson/error/error.h | 2 ++ include/rapidjson/internal/diyfp.h | 2 ++ include/rapidjson/internal/meta.h | 4 +--- include/rapidjson/internal/pow10.h | 2 ++ include/rapidjson/internal/stack.h | 2 ++ include/rapidjson/internal/strfunc.h | 2 ++ 7 files changed, 13 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 07d732b..92a4054 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ This project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] +* Include rapidjson.h for all internal/error headers. + ## [1.0.1] - 2015-04-25 ### Added diff --git a/include/rapidjson/error/error.h b/include/rapidjson/error/error.h index aa5700c..f9094fb 100644 --- a/include/rapidjson/error/error.h +++ b/include/rapidjson/error/error.h @@ -15,6 +15,8 @@ #ifndef RAPIDJSON_ERROR_ERROR_H__ #define RAPIDJSON_ERROR_ERROR_H__ +#include "../rapidjson.h" + /*! \file error.h */ /*! \defgroup RAPIDJSON_ERRORS RapidJSON error handling */ diff --git a/include/rapidjson/internal/diyfp.h b/include/rapidjson/internal/diyfp.h index 033a2a2..4ef53d9 100644 --- a/include/rapidjson/internal/diyfp.h +++ b/include/rapidjson/internal/diyfp.h @@ -19,6 +19,8 @@ #ifndef RAPIDJSON_DIYFP_H_ #define RAPIDJSON_DIYFP_H_ +#include "../rapidjson.h" + #if defined(_MSC_VER) && defined(_M_AMD64) #include #pragma intrinsic(_BitScanReverse64) diff --git a/include/rapidjson/internal/meta.h b/include/rapidjson/internal/meta.h index 594e259..2daad96 100644 --- a/include/rapidjson/internal/meta.h +++ b/include/rapidjson/internal/meta.h @@ -15,9 +15,7 @@ #ifndef RAPIDJSON_INTERNAL_META_H_ #define RAPIDJSON_INTERNAL_META_H_ -#ifndef RAPIDJSON_RAPIDJSON_H_ -#error not yet included. Do not include this file directly. -#endif +#include "../rapidjson.h" #ifdef __GNUC__ RAPIDJSON_DIAG_PUSH diff --git a/include/rapidjson/internal/pow10.h b/include/rapidjson/internal/pow10.h index c552d9f..1d2dff0 100644 --- a/include/rapidjson/internal/pow10.h +++ b/include/rapidjson/internal/pow10.h @@ -15,6 +15,8 @@ #ifndef RAPIDJSON_POW10_ #define RAPIDJSON_POW10_ +#include "../rapidjson.h" + RAPIDJSON_NAMESPACE_BEGIN namespace internal { diff --git a/include/rapidjson/internal/stack.h b/include/rapidjson/internal/stack.h index 2f2c76a..bb31cc0 100644 --- a/include/rapidjson/internal/stack.h +++ b/include/rapidjson/internal/stack.h @@ -15,6 +15,8 @@ #ifndef RAPIDJSON_INTERNAL_STACK_H_ #define RAPIDJSON_INTERNAL_STACK_H_ +#include "../rapidjson.h" + RAPIDJSON_NAMESPACE_BEGIN namespace internal { diff --git a/include/rapidjson/internal/strfunc.h b/include/rapidjson/internal/strfunc.h index e6d1c21..f6c99db 100644 --- a/include/rapidjson/internal/strfunc.h +++ b/include/rapidjson/internal/strfunc.h @@ -15,6 +15,8 @@ #ifndef RAPIDJSON_INTERNAL_STRFUNC_H_ #define RAPIDJSON_INTERNAL_STRFUNC_H_ +#include "../rapidjson.h" + RAPIDJSON_NAMESPACE_BEGIN namespace internal { From c1b66cc082b5500f3410be0d367b0044c46e3153 Mon Sep 17 00:00:00 2001 From: miloyip Date: Tue, 28 Apr 2015 22:41:31 +0800 Subject: [PATCH 037/189] Fix incorrect API in tutorial document. --- doc/tutorial.md | 2 +- doc/tutorial.zh-cn.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/tutorial.md b/doc/tutorial.md index 811833d..3508918 100644 --- a/doc/tutorial.md +++ b/doc/tutorial.md @@ -192,7 +192,7 @@ Checking | Obtaining `bool IsNumber()` | N/A `bool IsUint()` | `unsigned GetUint()` `bool IsInt()` | `int GetInt()` -`bool IsUint64()` | `uint64_t GetUint()` +`bool IsUint64()` | `uint64_t GetUint64()` `bool IsInt64()` | `int64_t GetInt64()` `bool IsDouble()` | `double GetDouble()` diff --git a/doc/tutorial.zh-cn.md b/doc/tutorial.zh-cn.md index 24456d5..d1381be 100644 --- a/doc/tutorial.zh-cn.md +++ b/doc/tutorial.zh-cn.md @@ -192,7 +192,7 @@ JSONåªæä¾›ä¸€ç§æ•°å€¼ç±»åž‹â”€â”€Number。数字å¯ä»¥æ˜¯æ•´æ•°æˆ–实数。R `bool IsNumber()` | ä¸é€‚用 `bool IsUint()` | `unsigned GetUint()` `bool IsInt()` | `int GetInt()` -`bool IsUint64()` | `uint64_t GetUint()` +`bool IsUint64()` | `uint64_t GetUint64()` `bool IsInt64()` | `int64_t GetInt64()` `bool IsDouble()` | `double GetDouble()` From ea7b39b960fa1f2baed5d3587dffe1b42f39e3fe Mon Sep 17 00:00:00 2001 From: Milo Yip Date: Fri, 1 May 2015 08:10:21 +0800 Subject: [PATCH 038/189] Update installation section of zh-cn readme --- readme.zh-cn.md | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/readme.zh-cn.md b/readme.zh-cn.md index 2dd27cf..eb6c21d 100644 --- a/readme.zh-cn.md +++ b/readme.zh-cn.md @@ -2,6 +2,8 @@ ![](https://img.shields.io/badge/release-v1.0.1-blue.png) +## 高效的C++ JSONè§£æžï¼ç”Ÿæˆå™¨ï¼Œæä¾›SAXåŠDOM风格API + Tencent is pleased to support the open source community by making RapidJSON available. Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. @@ -60,21 +62,21 @@ RapidJSON是跨平å°çš„。以下是一些曾测试的平å°ï¼ç¼–è¯‘å™¨ç»„åˆ RapidJSONæ˜¯åªæœ‰å¤´æ–‡ä»¶çš„C++库。åªéœ€æŠŠ`include/rapidjson`目录å¤åˆ¶è‡³ç³»ç»Ÿæˆ–项目的include目录中。 +RapidJSONä¾èµ–于以下软件: +* [CMake](http://www.cmake.org) 作为通用生æˆå·¥å…· +* (optional)[Doxygen](http://www.doxygen.org)ç”¨äºŽç”Ÿæˆæ–‡æ¡£ +* (optional)[googletest](https://code.google.com/p/googletest/)用于å•å…ƒåŠæ€§èƒ½æµ‹è¯• + ç”Ÿæˆæµ‹è¯•åŠä¾‹å­çš„æ­¥éª¤ï¼š 1. 执行 `git submodule update --init` åŽ»èŽ·å– thirdparty submodules (google test)。 -2. 下载 [premake4](http://industriousone.com/premake/download)。 -3. å¤åˆ¶ premake4 坿‰§è¡Œæ–‡ä»¶è‡³ `rapidjson/build` (或系统路径)。 -4. 进入`rapidjson/build/`目录,在Windows下执行`premake.bat`,在Linux或其他平å°ä¸‹æ‰§è¡Œ`premake.sh`。 -5. 在Windows上,生æˆä½äºŽ`rapidjson/build/vs2008/`或`/vs2010/`内的项目方案. -6. 在其他平å°ä¸Šï¼Œåœ¨`rapidjson/build/gmake/`目录执行GNU `make`(如 `make -f test.make config=release32`ã€`make -f example.make config=debug32`)。 -7. è‹¥æˆåŠŸï¼Œå¯æ‰§è¡Œæ–‡ä»¶ä¼šç”Ÿæˆåœ¨`rapidjson/bin`目录。 +2. 在rapidjson目渌下,建立一个`build`目录。 +3. 在`build`目录下执行`cmake ..`命令以设置生æˆã€‚Windows用户å¯ä½¿ç”¨cmake-gui应用程åºã€‚ +4. 在Windows下,编译生æˆåœ¨build目录中的solution。在Linux下,于build目录è¿è¡Œ`make`。 -生æˆ[Doxygen](http://doxygen.org)文档的步骤: +æˆåŠŸç”ŸæˆåŽï¼Œä½ ä¼šåœ¨`bin`的目录下找到编译åŽçš„æµ‹è¯•åŠä¾‹å­å¯æ‰§è¡Œæ–‡ä»¶ã€‚而生æˆçš„æ–‡æ¡£å°†ä½äºŽbuild下的`doc/html`ç›®å½•ã€‚è¦æ‰§è¡Œæµ‹è¯•,请在build下执行`make test`或`ctest`。使用`ctest -V`命令å¯èŽ·å–详细的输出。 -1. 下载åŠå®‰è£…[Doxygen](http://doxygen.org/download.html)。 -2. 在顶层目录执行`doxygen build/Doxyfile`。 -3. 在`doc/html`æµè§ˆæ–‡æ¡£ã€‚ +我们也å¯ä»¥æŠŠç¨‹åºåº“安装至全系统中,åªè¦åœ¨å…·ç®¡ç†æ¬Šé™ä¸‹ä»Žbuild目录执行`make install`命令。这样会按系统的å好设置安装所有文件。当安装RapidJSONåŽï¼Œå…¶ä»–çš„CMake项目需è¦ä½¿ç”¨å®ƒæ—¶ï¼Œå¯ä»¥é€šè¿‡åœ¨`CMakeLists.txt`加入一å¥`find_package(RapidJSON)`。 ## 用法一览 From 1ef380586de0d53df768d743e217b1cf3e2738dc Mon Sep 17 00:00:00 2001 From: miloyip Date: Sat, 2 May 2015 20:07:50 +0800 Subject: [PATCH 039/189] Fix a bug in Pointer::Create() and Add different overloads for Set() related implementations --- include/rapidjson/pointer.h | 105 +++++++++++++++++++++------- test/unittest/pointertest.cpp | 127 ++++++++++++++++++++++++++++++++-- 2 files changed, 201 insertions(+), 31 deletions(-) diff --git a/include/rapidjson/pointer.h b/include/rapidjson/pointer.h index 6ee6abc..e470585 100644 --- a/include/rapidjson/pointer.h +++ b/include/rapidjson/pointer.h @@ -43,7 +43,7 @@ public: { } - GenericPointer(const Ch* source, Allocator* allocator = 0) + explicit GenericPointer(const Ch* source, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), @@ -156,22 +156,23 @@ public: v->SetArray(); } - switch (v->GetType()) { - case kObjectType: - { - typename ValueType::MemberIterator m = v->FindMember(GenericStringRef(t->name, t->length)); - if (m == v->MemberEnd()) { - v->AddMember(Value(t->name, t->length, allocator).Move(), Value().Move(), allocator); - v = &(--v->MemberEnd())->value; // Assumes AddMember() appends at the end - exist = false; - } - else - v = &m->value; + if (t->index == kPointerInvalidIndex) { + if (!v->IsObject()) + v->SetObject(); // Change to Object + + typename ValueType::MemberIterator m = v->FindMember(GenericStringRef(t->name, t->length)); + if (m == v->MemberEnd()) { + v->AddMember(Value(t->name, t->length, allocator).Move(), Value().Move(), allocator); + v = &(--v->MemberEnd())->value; // Assumes AddMember() appends at the end + exist = false; } - break; - case kArrayType: - if (t->index == kPointerInvalidIndex) + else + v = &m->value; + } + else { + if (!v->IsArray()) v->SetArray(); // Change to Array + if (t->index >= v->Size()) { v->Reserve(t->index + 1, allocator); while (t->index >= v->Size()) @@ -179,11 +180,6 @@ public: exist = false; } v = &((*v)[t->index]); - break; - default: - // Impossible. - RAPIDJSON_ASSERT(false); - break; } } @@ -237,6 +233,28 @@ public: return Create(root, allocator) = value; } + // Copy semantics, create parents if non-exist + ValueType& Set(ValueType& root, const ValueType& value, typename ValueType::AllocatorType& allocator) const { + return Create(root, allocator).CopyFrom(value, allocator); + } + + ValueType& Set(ValueType& root, GenericStringRef value, typename ValueType::AllocatorType& allocator) const { + ValueType v(value); + return Create(root, allocator) = v; + } + + ValueType& Set(ValueType& root, const Ch* value, typename ValueType::AllocatorType& allocator) const { + ValueType v(value, allocator); + return Create(root, allocator) = v; + } + + template + RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (ValueType&)) + Set(ValueType& root, T value, typename ValueType::AllocatorType& allocator) const { + ValueType v(value); + return Create(root, allocator) = v; + } + // Create parents if non-exist ValueType& Swap(ValueType& root, ValueType& value, typename ValueType::AllocatorType& allocator) const { return Create(root, allocator).Swap(value); @@ -340,7 +358,7 @@ typename T::ValueType& CreateValueByPointer(T& root, const GenericPointer typename T::ValueType& CreateValueByPointer(T& root, const CharType(&source)[N], typename T::AllocatorType& a) { const GenericPointer pointer(source, N - 1); - return pointer.Create(root, a); + return CreateValueByPointer(root, pointer, a); } template @@ -356,13 +374,13 @@ const typename T::ValueType* GetValueByPointer(const T& root, const GenericPoint template typename T::ValueType* GetValueByPointer(T& root, const CharType (&source)[N]) { const GenericPointer pointer(source, N - 1); - return pointer.Get(root); + return GetValueByPointer(root, pointer); } template const typename T::ValueType* GetValueByPointer(const T& root, const CharType(&source)[N]) { const GenericPointer pointer(source, N - 1); - return pointer.Get(root); + return GetValueByPointer(root, pointer); } template @@ -373,7 +391,7 @@ typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointe template typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const typename T::ValueType& defaultValue, typename T::AllocatorType& a) { const GenericPointer pointer(source, N - 1); - return pointer.GetWithDefault(root, defaultValue, a); + return GetValueByPointerWithDefault(root, pointer, defaultValue, a); } template @@ -381,10 +399,45 @@ typename T::ValueType& SetValueByPointer(T& root, const GenericPointer +typename T::ValueType& SetValueByPointer(T& root, const GenericPointer& pointer, GenericStringRef value, typename T::AllocatorType& a) { + return pointer.Set(root, value, a); +} + +template +typename T::ValueType& SetValueByPointer(T& root, const GenericPointer& pointer, const typename T::Ch* value, typename T::AllocatorType& a) { + return pointer.Set(root, value, a); +} + +template +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename T::ValueType&)) +SetValueByPointer(T& root, const GenericPointer& pointer, T2 value, typename T::AllocatorType& a) { + return pointer.Set(root, value, a); +} + template typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], typename T::ValueType& value, typename T::AllocatorType& a) { const GenericPointer pointer(source, N - 1); - return pointer.Set(root, value , a); + return SetValueByPointer(root, pointer, value, a); +} + +template +typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], GenericStringRef value, typename T::AllocatorType& a) { + const GenericPointer pointer(source, N - 1); + return SetValueByPointer(root, pointer, value, a); +} + +template +typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const typename T::Ch* value, typename T::AllocatorType& a) { + const GenericPointer pointer(source, N - 1); + return SetValueByPointer(root, pointer, value, a); +} + +template +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename T::ValueType&)) +SetValueByPointer(T& root, const CharType(&source)[N], T2 value, typename T::AllocatorType& a) { + const GenericPointer pointer(source, N - 1); + return SetValueByPointer(root, pointer, value, a); } template @@ -395,7 +448,7 @@ typename T::ValueType& SwapValueByPointer(T& root, const GenericPointer typename T::ValueType& SwapValueByPointer(T& root, const CharType(&source)[N], typename T::ValueType& value, typename T::AllocatorType& a) { const GenericPointer pointer(source, N - 1); - return pointer.Swap(root, value, a); + return SwapValueByPointer(root, pointer, value, a); } typedef GenericPointer Pointer; diff --git a/test/unittest/pointertest.cpp b/test/unittest/pointertest.cpp index 98a006d..3efa0ec 100644 --- a/test/unittest/pointertest.cpp +++ b/test/unittest/pointertest.cpp @@ -293,11 +293,46 @@ TEST(Pointer, Set) { d.Parse(kJson); Document::AllocatorType& a = d.GetAllocator(); + // Value version Pointer("/foo/0").Set(d, Value(123).Move(), a); EXPECT_EQ(123, d["foo"][0].GetInt()); - Pointer("/foo/2").Set(d, Value(456).Move(), a); - EXPECT_EQ(456, d["foo"][2].GetInt()); + Pointer("/foo/null").Set(d, Value().Move(), a); + EXPECT_TRUE(GetValueByPointer(d, "/foo/null")->IsNull()); + + // Generic version + Pointer("/foo/int").Set(d, -1, a); + EXPECT_EQ(-1, GetValueByPointer(d, "/foo/int")->GetInt()); + + Pointer("/foo/uint").Set(d, 0x87654321, a); + EXPECT_EQ(0x87654321, GetValueByPointer(d, "/foo/uint")->GetUint()); + + const int64_t i64 = static_cast(RAPIDJSON_UINT64_C2(0x80000000, 0)); + Pointer("/foo/int64").Set(d, i64, a); + EXPECT_EQ(i64, GetValueByPointer(d, "/foo/int64")->GetInt64()); + + const uint64_t u64 = RAPIDJSON_UINT64_C2(0xFFFFFFFFF, 0xFFFFFFFFF); + Pointer("/foo/uint64").Set(d, u64, a); + EXPECT_EQ(u64, GetValueByPointer(d, "/foo/uint64")->GetUint64()); + + Pointer("/foo/true").Set(d, true, a); + EXPECT_TRUE(GetValueByPointer(d, "/foo/true")->IsTrue()); + + Pointer("/foo/false").Set(d, false, a); + EXPECT_TRUE(GetValueByPointer(d, "/foo/false")->IsFalse()); + + // StringRef version + Pointer("/foo/hello").Set(d, "Hello", a); + EXPECT_STREQ("Hello", GetValueByPointer(d, "/foo/hello")->GetString()); + + // Copy string version + { + char buffer[256]; + strcpy(buffer, "World"); + Pointer("/foo/world").Set(d, buffer, a); + memset(buffer, 0, sizeof(buffer)); + } + EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString()); } TEST(Pointer, Swap) { @@ -346,16 +381,98 @@ TEST(Pointer, GetValueByPointerWithDefault) { EXPECT_TRUE(Value("baz") == GetValueByPointerWithDefault(d, "/foo/1", v, a)); } -TEST(Pointer, SetValueByPointer) { +TEST(Pointer, SetValueByPointer_Pointer) { Document d; d.Parse(kJson); Document::AllocatorType& a = d.GetAllocator(); + // Value version SetValueByPointer(d, Pointer("/foo/0"), Value(123).Move(), a); EXPECT_EQ(123, d["foo"][0].GetInt()); - SetValueByPointer(d, "/foo/2", Value(456).Move(), a); - EXPECT_EQ(456, d["foo"][2].GetInt()); + SetValueByPointer(d, Pointer("/foo/null"), Value().Move(), a); + EXPECT_TRUE(GetValueByPointer(d, "/foo/null")->IsNull()); + + // Generic version + SetValueByPointer(d, Pointer("/foo/int"), -1, a); + EXPECT_EQ(-1, GetValueByPointer(d, "/foo/int")->GetInt()); + + SetValueByPointer(d, Pointer("/foo/uint"), 0x87654321, a); + EXPECT_EQ(0x87654321, GetValueByPointer(d, "/foo/uint")->GetUint()); + + const int64_t i64 = static_cast(RAPIDJSON_UINT64_C2(0x80000000, 0)); + SetValueByPointer(d, Pointer("/foo/int64"), i64, a); + EXPECT_EQ(i64, GetValueByPointer(d, "/foo/int64")->GetInt64()); + + const uint64_t u64 = RAPIDJSON_UINT64_C2(0xFFFFFFFFF, 0xFFFFFFFFF); + SetValueByPointer(d, Pointer("/foo/uint64"), u64, a); + EXPECT_EQ(u64, GetValueByPointer(d, "/foo/uint64")->GetUint64()); + + SetValueByPointer(d, Pointer("/foo/true"), true, a); + EXPECT_TRUE(GetValueByPointer(d, "/foo/true")->IsTrue()); + + SetValueByPointer(d, Pointer("/foo/false"), false, a); + EXPECT_TRUE(GetValueByPointer(d, "/foo/false")->IsFalse()); + + // StringRef version + SetValueByPointer(d, Pointer("/foo/hello"), "Hello", a); + EXPECT_STREQ("Hello", GetValueByPointer(d, "/foo/hello")->GetString()); + + // Copy string version + { + char buffer[256]; + strcpy(buffer, "World"); + SetValueByPointer(d, Pointer("/foo/world"), buffer, a); + memset(buffer, 0, sizeof(buffer)); + } + EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString()); +} + +TEST(Pointer, SetValueByPointer_String) { + Document d; + d.Parse(kJson); + Document::AllocatorType& a = d.GetAllocator(); + + // Value version + SetValueByPointer(d, "/foo/0", Value(123).Move(), a); + EXPECT_EQ(123, d["foo"][0].GetInt()); + + SetValueByPointer(d, "/foo/null", Value().Move(), a); + EXPECT_TRUE(GetValueByPointer(d, "/foo/null")->IsNull()); + + // Generic version + SetValueByPointer(d, "/foo/int", -1, a); + EXPECT_EQ(-1, GetValueByPointer(d, "/foo/int")->GetInt()); + + SetValueByPointer(d, "/foo/uint", 0x87654321, a); + EXPECT_EQ(0x87654321, GetValueByPointer(d, "/foo/uint")->GetUint()); + + const int64_t i64 = static_cast(RAPIDJSON_UINT64_C2(0x80000000, 0)); + SetValueByPointer(d, "/foo/int64", i64, a); + EXPECT_EQ(i64, GetValueByPointer(d, "/foo/int64")->GetInt64()); + + const uint64_t u64 = RAPIDJSON_UINT64_C2(0xFFFFFFFFF, 0xFFFFFFFFF); + SetValueByPointer(d, "/foo/uint64", u64, a); + EXPECT_EQ(u64, GetValueByPointer(d, "/foo/uint64")->GetUint64()); + + SetValueByPointer(d, "/foo/true", true, a); + EXPECT_TRUE(GetValueByPointer(d, "/foo/true")->IsTrue()); + + SetValueByPointer(d, "/foo/false", false, a); + EXPECT_TRUE(GetValueByPointer(d, "/foo/false")->IsFalse()); + + // StringRef version + SetValueByPointer(d, "/foo/hello", "Hello", a); + EXPECT_STREQ("Hello", GetValueByPointer(d, "/foo/hello")->GetString()); + + // Copy string version + { + char buffer[256]; + strcpy(buffer, "World"); + SetValueByPointer(d, "/foo/world", buffer, a); + memset(buffer, 0, sizeof(buffer)); + } + EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString()); } TEST(Pointer, SwapValueByPointer) { From 2ece55abc7001962870f7ee4effbd1c852ee182e Mon Sep 17 00:00:00 2001 From: miloyip Date: Sat, 2 May 2015 20:44:30 +0800 Subject: [PATCH 040/189] Implement pointer parse error --- include/rapidjson/pointer.h | 114 ++++++++++++++++++++++------------ test/unittest/pointertest.cpp | 24 +++++++ 2 files changed, 97 insertions(+), 41 deletions(-) diff --git a/include/rapidjson/pointer.h b/include/rapidjson/pointer.h index e470585..c0b7ba1 100644 --- a/include/rapidjson/pointer.h +++ b/include/rapidjson/pointer.h @@ -21,6 +21,13 @@ RAPIDJSON_NAMESPACE_BEGIN static const SizeType kPointerInvalidIndex = ~SizeType(0); +enum PointerParseErrorCode { + kPointerParseErrorNone = 0, + + kPointerParseErrorTokenMustBeginWithSolidus, + kPointerParseErrorInvalidEscape +}; + template class GenericPointer { public: @@ -33,55 +40,60 @@ public: SizeType index; //!< A valid index if not equal to kPointerInvalidIndex. }; - GenericPointer() - : allocator_(), + GenericPointer() : + allocator_(), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), - valid_(true) + parseErrorOffset_(), + parseErrorCode_(kPointerParseErrorNone) { } - explicit GenericPointer(const Ch* source, Allocator* allocator = 0) - : allocator_(allocator), - ownAllocator_(), - nameBuffer_(), - tokens_(), - tokenCount_(), - valid_(true) + explicit GenericPointer(const Ch* source, Allocator* allocator = 0) : + allocator_(allocator), + ownAllocator_(), + nameBuffer_(), + tokens_(), + tokenCount_(), + parseErrorOffset_(), + parseErrorCode_(kPointerParseErrorNone) { Parse(source, internal::StrLen(source)); } - GenericPointer(const Ch* source, size_t length, Allocator* allocator = 0) - : allocator_(allocator), - ownAllocator_(), - nameBuffer_(), - tokens_(), - tokenCount_(), - valid_(true) + GenericPointer(const Ch* source, size_t length, Allocator* allocator = 0) : + allocator_(allocator), + ownAllocator_(), + nameBuffer_(), + tokens_(), + tokenCount_(), + parseErrorOffset_(), + parseErrorCode_(kPointerParseErrorNone) { Parse(source, length); } - GenericPointer(const Token* tokens, size_t tokenCount) - : allocator_(), - ownAllocator_(), - nameBuffer_(), - tokens_(const_cast(tokens)), - tokenCount_(tokenCount), - valid_(true) + GenericPointer(const Token* tokens, size_t tokenCount) : + allocator_(), + ownAllocator_(), + nameBuffer_(), + tokens_(const_cast(tokens)), + tokenCount_(tokenCount), + parseErrorOffset_(), + parseErrorCode_(kPointerParseErrorNone) { } - GenericPointer(const GenericPointer& rhs) - : allocator_(), - ownAllocator_(), - nameBuffer_(), - tokens_(), - tokenCount_(), - valid_() + GenericPointer(const GenericPointer& rhs) : + allocator_(), + ownAllocator_(), + nameBuffer_(), + tokens_(), + tokenCount_(), + parseErrorOffset_(), + parseErrorCode_(kPointerParseErrorNone) { *this = rhs; } @@ -98,7 +110,8 @@ public: this->~GenericPointer(); tokenCount_ = rhs.tokenCount_; - valid_ = rhs.valid_; + parseErrorOffset_ = rhs.parseErrorOffset_; + parseErrorCode_ = rhs.parseErrorCode_; if (rhs.nameBuffer_) { if (!allocator_) @@ -124,7 +137,11 @@ public: return *this; } - bool IsValid() const { return valid_; } + bool IsValid() const { return parseErrorCode_ == kPointerParseErrorNone; } + + size_t GetParseErrorOffset() const { return parseErrorOffset_; } + + PointerParseErrorCode GetParseErrorCode() const { return parseErrorCode_; } const Token* GetTokens() const { return tokens_; } @@ -276,9 +293,16 @@ private: tokenCount_ = 0; Ch* name = nameBuffer_; - for (size_t i = 0; i < length;) { - if (source[i++] != '/') // Consumes '/' - goto error; + size_t i = 0; + + if (length != 0 && source[i] != '/') { + parseErrorCode_ = kPointerParseErrorTokenMustBeginWithSolidus; + goto error; + } + + while (i < length) { + RAPIDJSON_ASSERT(source[i] == '/'); + i++; // consumes '/' Token& token = tokens_[tokenCount_++]; token.name = name; @@ -290,13 +314,19 @@ private: // Escaping "~0" -> '~', "~1" -> '/' if (c == '~') { if (i < length) { - c = source[i++]; + c = source[i]; if (c == '0') c = '~'; else if (c == '1') c = '/'; - else goto error; + else { + parseErrorCode_ = kPointerParseErrorInvalidEscape; + goto error; + } + i++; } - else + else { + parseErrorCode_ = kPointerParseErrorInvalidEscape; goto error; + } } // First check for index: all of characters are digit @@ -330,6 +360,7 @@ private: RAPIDJSON_ASSERT(name <= nameBuffer_ + length); // Should not overflow buffer tokens_ = (Token*)allocator_->Realloc(tokens_, length * sizeof(Token), tokenCount_ * sizeof(Token)); // Shrink tokens_ + parseErrorCode_ = kPointerParseErrorNone; return; error: @@ -338,7 +369,7 @@ private: nameBuffer_ = 0; tokens_ = 0; tokenCount_ = 0; - valid_ = false; + parseErrorOffset_ = i; return; } @@ -347,7 +378,8 @@ private: Ch* nameBuffer_; Token* tokens_; size_t tokenCount_; - bool valid_; + size_t parseErrorOffset_; + PointerParseErrorCode parseErrorCode_; }; template diff --git a/test/unittest/pointertest.cpp b/test/unittest/pointertest.cpp index 3efa0ec..c58b858 100644 --- a/test/unittest/pointertest.cpp +++ b/test/unittest/pointertest.cpp @@ -139,6 +139,30 @@ TEST(Pointer, Parse) { EXPECT_STREQ("4294967296", p.GetTokens()[0].name); EXPECT_EQ(kPointerInvalidIndex, p.GetTokens()[0].index); } + + { + // kPointerParseErrorTokenMustBeginWithSolidus + Pointer p(" "); + EXPECT_FALSE(p.IsValid()); + EXPECT_EQ(kPointerParseErrorTokenMustBeginWithSolidus, p.GetParseErrorCode()); + EXPECT_EQ(0u, p.GetParseErrorOffset()); + } + + { + // kPointerParseErrorInvalidEscape + Pointer p("/~"); + EXPECT_FALSE(p.IsValid()); + EXPECT_EQ(kPointerParseErrorInvalidEscape, p.GetParseErrorCode()); + EXPECT_EQ(2u, p.GetParseErrorOffset()); + } + + { + // kPointerParseErrorInvalidEscape + Pointer p("/~2"); + EXPECT_FALSE(p.IsValid()); + EXPECT_EQ(kPointerParseErrorInvalidEscape, p.GetParseErrorCode()); + EXPECT_EQ(2u, p.GetParseErrorOffset()); + } } TEST(Pointer, Stringify) { From 2ddbd09031b90765e31fc31a7607e3e0248a17d1 Mon Sep 17 00:00:00 2001 From: miloyip Date: Sat, 2 May 2015 21:30:40 +0800 Subject: [PATCH 041/189] Add '-' support for Create() and Set() --- include/rapidjson/pointer.h | 39 +++++++++++++++++++---------------- test/unittest/pointertest.cpp | 13 ++++++++++++ 2 files changed, 34 insertions(+), 18 deletions(-) diff --git a/include/rapidjson/pointer.h b/include/rapidjson/pointer.h index c0b7ba1..bc2795f 100644 --- a/include/rapidjson/pointer.h +++ b/include/rapidjson/pointer.h @@ -166,27 +166,30 @@ public: ValueType* v = &root; bool exist = true; for (Token *t = tokens_; t != tokens_ + tokenCount_; ++t) { - if (v->GetType() != kObjectType && v->GetType() != kArrayType) { - if (t->index == kPointerInvalidIndex) - v->SetObject(); - else - v->SetArray(); - } - - if (t->index == kPointerInvalidIndex) { - if (!v->IsObject()) - v->SetObject(); // Change to Object - - typename ValueType::MemberIterator m = v->FindMember(GenericStringRef(t->name, t->length)); - if (m == v->MemberEnd()) { - v->AddMember(Value(t->name, t->length, allocator).Move(), Value().Move(), allocator); - v = &(--v->MemberEnd())->value; // Assumes AddMember() appends at the end + if (t->index == kPointerInvalidIndex) { // object name + // Handling of '-' for last element of array + if (t->name[0] == '-' && t->length == 1) { + if (!v->IsArray()) + v->SetArray(); // Change to Array + v->PushBack(Value().Move(), allocator); + v = &((*v)[v->Size() - 1]); exist = false; } - else - v = &m->value; + else { + if (!v->IsObject()) + v->SetObject(); // Change to Object + + typename ValueType::MemberIterator m = v->FindMember(GenericStringRef(t->name, t->length)); + if (m == v->MemberEnd()) { + v->AddMember(Value(t->name, t->length, allocator).Move(), Value().Move(), allocator); + v = &(--v->MemberEnd())->value; // Assumes AddMember() appends at the end + exist = false; + } + else + v = &m->value; + } } - else { + else { // array index if (!v->IsArray()) v->SetArray(); // Change to Array diff --git a/test/unittest/pointertest.cpp b/test/unittest/pointertest.cpp index c58b858..887a7f8 100644 --- a/test/unittest/pointertest.cpp +++ b/test/unittest/pointertest.cpp @@ -280,6 +280,14 @@ TEST(Pointer, Create) { Value* v = &Pointer("/foo/0").Create(d, d.GetAllocator()); EXPECT_EQ(&d["foo"][0], v); } + { + Value* v = &Pointer("/foo/-").Create(d, d.GetAllocator()); + EXPECT_EQ(&d["foo"][1], v); + } + { + Value* v = &Pointer("/foo/-/-").Create(d, d.GetAllocator()); + EXPECT_EQ(&d["foo"][2][0], v); + } } TEST(Pointer, Get) { @@ -310,6 +318,8 @@ TEST(Pointer, GetWithDefault) { EXPECT_TRUE(Value("bar") == Pointer("/foo/0").GetWithDefault(d, v, a)); EXPECT_TRUE(Value("baz") == Pointer("/foo/1").GetWithDefault(d, v, a)); EXPECT_TRUE(Value("qux") == Pointer("/foo/2").GetWithDefault(d, v, a)); + EXPECT_TRUE(Value("last") == Pointer("/foo/-").GetWithDefault(d, Value("last").Move(), a)); + EXPECT_STREQ("last", d["foo"][3].GetString()); } TEST(Pointer, Set) { @@ -321,6 +331,9 @@ TEST(Pointer, Set) { Pointer("/foo/0").Set(d, Value(123).Move(), a); EXPECT_EQ(123, d["foo"][0].GetInt()); + Pointer("/foo/-").Set(d, Value(456).Move(), a); + EXPECT_EQ(456, d["foo"][2].GetInt()); + Pointer("/foo/null").Set(d, Value().Move(), a); EXPECT_TRUE(GetValueByPointer(d, "/foo/null")->IsNull()); From 32b45f6e6d15b229ea1907e9569e4792bff6e207 Mon Sep 17 00:00:00 2001 From: miloyip Date: Sat, 2 May 2015 21:52:49 +0800 Subject: [PATCH 042/189] Add GetWithDefault() overloads --- include/rapidjson/pointer.h | 22 +++++++++++++++++++++ test/unittest/pointertest.cpp | 36 +++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) diff --git a/include/rapidjson/pointer.h b/include/rapidjson/pointer.h index bc2795f..16d2e60 100644 --- a/include/rapidjson/pointer.h +++ b/include/rapidjson/pointer.h @@ -248,6 +248,28 @@ public: return v; } + ValueType& GetWithDefault(ValueType& root, GenericStringRef defaultValue, typename ValueType::AllocatorType& allocator) const { + ValueType v(defaultValue); + return GetWithDefault(root, v, allocator); + } + + ValueType& GetWithDefault(ValueType& root, const Ch* defaultValue, typename ValueType::AllocatorType& allocator) const { + bool alreadyExist; + Value& v = Create(root, allocator, &alreadyExist); + if (!alreadyExist) { + Value clone(defaultValue, allocator); // This has overhead, so do it inside if. + v = clone; + } + return v; + } + + template + RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (ValueType&)) + GetWithDefault(ValueType& root, T defaultValue, typename ValueType::AllocatorType& allocator) const { + ValueType v(defaultValue); + return GetWithDefault(root, v, allocator); + } + // Move semantics, create parents if non-exist ValueType& Set(ValueType& root, ValueType& value, typename ValueType::AllocatorType& allocator) const { return Create(root, allocator) = value; diff --git a/test/unittest/pointertest.cpp b/test/unittest/pointertest.cpp index 887a7f8..8368d51 100644 --- a/test/unittest/pointertest.cpp +++ b/test/unittest/pointertest.cpp @@ -313,6 +313,7 @@ TEST(Pointer, GetWithDefault) { Document d; d.Parse(kJson); + // Value version Document::AllocatorType& a = d.GetAllocator(); const Value v("qux"); EXPECT_TRUE(Value("bar") == Pointer("/foo/0").GetWithDefault(d, v, a)); @@ -320,6 +321,41 @@ TEST(Pointer, GetWithDefault) { EXPECT_TRUE(Value("qux") == Pointer("/foo/2").GetWithDefault(d, v, a)); EXPECT_TRUE(Value("last") == Pointer("/foo/-").GetWithDefault(d, Value("last").Move(), a)); EXPECT_STREQ("last", d["foo"][3].GetString()); + + EXPECT_TRUE(Pointer("/foo/null").GetWithDefault(d, Value().Move(), a).IsNull()); + EXPECT_TRUE(Pointer("/foo/null").GetWithDefault(d, "x", a).IsNull()); + + // Generic version + EXPECT_EQ(-1, Pointer("/foo/int").GetWithDefault(d, -1, a).GetInt()); + EXPECT_EQ(-1, Pointer("/foo/int").GetWithDefault(d, -2, a).GetInt()); + EXPECT_EQ(0x87654321, Pointer("/foo/uint").GetWithDefault(d, 0x87654321, a).GetUint()); + EXPECT_EQ(0x87654321, Pointer("/foo/uint").GetWithDefault(d, 0x12345678, a).GetUint()); + + const int64_t i64 = static_cast(RAPIDJSON_UINT64_C2(0x80000000, 0)); + EXPECT_EQ(i64, Pointer("/foo/int64").GetWithDefault(d, i64, a).GetInt64()); + EXPECT_EQ(i64, Pointer("/foo/int64").GetWithDefault(d, i64 + 1, a).GetInt64()); + + const uint64_t u64 = RAPIDJSON_UINT64_C2(0xFFFFFFFFF, 0xFFFFFFFFF); + EXPECT_EQ(u64, Pointer("/foo/uint64").GetWithDefault(d, u64, a).GetUint64()); + EXPECT_EQ(u64, Pointer("/foo/uint64").GetWithDefault(d, u64 - 1, a).GetUint64()); + + EXPECT_TRUE(Pointer("/foo/true").GetWithDefault(d, true, a).IsTrue()); + EXPECT_TRUE(Pointer("/foo/true").GetWithDefault(d, false, a).IsTrue()); + + EXPECT_TRUE(Pointer("/foo/false").GetWithDefault(d, false, a).IsFalse()); + EXPECT_TRUE(Pointer("/foo/false").GetWithDefault(d, true, a).IsFalse()); + + // StringRef version + EXPECT_STREQ("Hello", Pointer("/foo/hello").GetWithDefault(d, "Hello", a).GetString()); + + // Copy string version + { + char buffer[256]; + strcpy(buffer, "World"); + EXPECT_STREQ("World", Pointer("/foo/world").GetWithDefault(d, buffer, a).GetString()); + memset(buffer, 0, sizeof(buffer)); + } + EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString()); } TEST(Pointer, Set) { From d0d18847c5f01fb9378777f25761f54b39b5bdc1 Mon Sep 17 00:00:00 2001 From: miloyip Date: Sat, 2 May 2015 22:08:03 +0800 Subject: [PATCH 043/189] Add GetValueByPointerWithDefault() overloads --- include/rapidjson/pointer.h | 35 ++++++++++++++ test/unittest/pointertest.cpp | 90 ++++++++++++++++++++++++++++++++++- 2 files changed, 124 insertions(+), 1 deletion(-) diff --git a/include/rapidjson/pointer.h b/include/rapidjson/pointer.h index 16d2e60..027d68b 100644 --- a/include/rapidjson/pointer.h +++ b/include/rapidjson/pointer.h @@ -445,12 +445,47 @@ typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointe return pointer.GetWithDefault(root, defaultValue, a); } +template +typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer& pointer, GenericStringRef defaultValue, typename T::AllocatorType& a) { + return pointer.GetWithDefault(root, defaultValue, a); +} + +template +typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer& pointer, const typename T::Ch* defaultValue, typename T::AllocatorType& a) { + return pointer.GetWithDefault(root, defaultValue, a); +} + +template +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename T::ValueType&)) +GetValueByPointerWithDefault(T& root, const GenericPointer& pointer, T2 defaultValue, typename T::AllocatorType& a) { + return pointer.GetWithDefault(root, defaultValue, a); +} + template typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const typename T::ValueType& defaultValue, typename T::AllocatorType& a) { const GenericPointer pointer(source, N - 1); return GetValueByPointerWithDefault(root, pointer, defaultValue, a); } +template +typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], GenericStringRef defaultValue, typename T::AllocatorType& a) { + const GenericPointer pointer(source, N - 1); + return GetValueByPointerWithDefault(root, pointer, defaultValue, a); +} + +template +typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const typename T::Ch* defaultValue, typename T::AllocatorType& a) { + const GenericPointer pointer(source, N - 1); + return GetValueByPointerWithDefault(root, pointer, defaultValue, a); +} + +template +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename T::ValueType&)) +GetValueByPointerWithDefault(T& root, const CharType(&source)[N], T2 defaultValue, typename T::AllocatorType& a) { + const GenericPointer pointer(source, N - 1); + return GetValueByPointerWithDefault(root, pointer, defaultValue, a); +} + template typename T::ValueType& SetValueByPointer(T& root, const GenericPointer& pointer, typename T::ValueType& value, typename T::AllocatorType& a) { return pointer.Set(root, value, a); diff --git a/test/unittest/pointertest.cpp b/test/unittest/pointertest.cpp index 8368d51..a18646a 100644 --- a/test/unittest/pointertest.cpp +++ b/test/unittest/pointertest.cpp @@ -444,14 +444,102 @@ TEST(Pointer, GetValueByPointer) { EXPECT_EQ(&d["foo"][0], GetValueByPointer(v, "/foo/0")); } -TEST(Pointer, GetValueByPointerWithDefault) { +TEST(Pointer, GetValueByPointerWithDefault_Pointer) { Document d; d.Parse(kJson); Document::AllocatorType& a = d.GetAllocator(); const Value v("qux"); EXPECT_TRUE(Value("bar") == GetValueByPointerWithDefault(d, Pointer("/foo/0"), v, a)); + EXPECT_TRUE(Value("bar") == GetValueByPointerWithDefault(d, Pointer("/foo/0"), v, a)); + EXPECT_TRUE(Value("baz") == GetValueByPointerWithDefault(d, Pointer("/foo/1"), v, a)); + EXPECT_TRUE(Value("qux") == GetValueByPointerWithDefault(d, Pointer("/foo/2"), v, a)); + EXPECT_TRUE(Value("last") == GetValueByPointerWithDefault(d, Pointer("/foo/-"), Value("last").Move(), a)); + EXPECT_STREQ("last", d["foo"][3].GetString()); + + EXPECT_TRUE(GetValueByPointerWithDefault(d, Pointer("/foo/null"), Value().Move(), a).IsNull()); + EXPECT_TRUE(GetValueByPointerWithDefault(d, Pointer("/foo/null"), "x", a).IsNull()); + + // Generic version + EXPECT_EQ(-1, GetValueByPointerWithDefault(d, Pointer("/foo/int"), -1, a).GetInt()); + EXPECT_EQ(-1, GetValueByPointerWithDefault(d, Pointer("/foo/int"), -2, a).GetInt()); + EXPECT_EQ(0x87654321, GetValueByPointerWithDefault(d, Pointer("/foo/uint"), 0x87654321, a).GetUint()); + EXPECT_EQ(0x87654321, GetValueByPointerWithDefault(d, Pointer("/foo/uint"), 0x12345678, a).GetUint()); + + const int64_t i64 = static_cast(RAPIDJSON_UINT64_C2(0x80000000, 0)); + EXPECT_EQ(i64, GetValueByPointerWithDefault(d, Pointer("/foo/int64"), i64, a).GetInt64()); + EXPECT_EQ(i64, GetValueByPointerWithDefault(d, Pointer("/foo/int64"), i64 + 1, a).GetInt64()); + + const uint64_t u64 = RAPIDJSON_UINT64_C2(0xFFFFFFFFF, 0xFFFFFFFFF); + EXPECT_EQ(u64, GetValueByPointerWithDefault(d, Pointer("/foo/uint64"), u64, a).GetUint64()); + EXPECT_EQ(u64, GetValueByPointerWithDefault(d, Pointer("/foo/uint64"), u64 - 1, a).GetUint64()); + + EXPECT_TRUE(GetValueByPointerWithDefault(d, Pointer("/foo/true"), true, a).IsTrue()); + EXPECT_TRUE(GetValueByPointerWithDefault(d, Pointer("/foo/true"), false, a).IsTrue()); + + EXPECT_TRUE(GetValueByPointerWithDefault(d, Pointer("/foo/false"), false, a).IsFalse()); + EXPECT_TRUE(GetValueByPointerWithDefault(d, Pointer("/foo/false"), true, a).IsFalse()); + + // StringRef version + EXPECT_STREQ("Hello", GetValueByPointerWithDefault(d, Pointer("/foo/hello"), "Hello", a).GetString()); + + // Copy string version + { + char buffer[256]; + strcpy(buffer, "World"); + EXPECT_STREQ("World", GetValueByPointerWithDefault(d, Pointer("/foo/world"), buffer, a).GetString()); + memset(buffer, 0, sizeof(buffer)); + } + EXPECT_STREQ("World", GetValueByPointer(d, Pointer("/foo/world"))->GetString()); +} + +TEST(Pointer, GetValueByPointerWithDefault_String) { + Document d; + d.Parse(kJson); + + Document::AllocatorType& a = d.GetAllocator(); + const Value v("qux"); + EXPECT_TRUE(Value("bar") == GetValueByPointerWithDefault(d, "/foo/0", v, a)); + EXPECT_TRUE(Value("bar") == GetValueByPointerWithDefault(d, "/foo/0", v, a)); EXPECT_TRUE(Value("baz") == GetValueByPointerWithDefault(d, "/foo/1", v, a)); + EXPECT_TRUE(Value("qux") == GetValueByPointerWithDefault(d, "/foo/2", v, a)); + EXPECT_TRUE(Value("last") == GetValueByPointerWithDefault(d, "/foo/-", Value("last").Move(), a)); + EXPECT_STREQ("last", d["foo"][3].GetString()); + + EXPECT_TRUE(GetValueByPointerWithDefault(d, "/foo/null", Value().Move(), a).IsNull()); + EXPECT_TRUE(GetValueByPointerWithDefault(d, "/foo/null", "x", a).IsNull()); + + // Generic version + EXPECT_EQ(-1, GetValueByPointerWithDefault(d, "/foo/int", -1, a).GetInt()); + EXPECT_EQ(-1, GetValueByPointerWithDefault(d, "/foo/int", -2, a).GetInt()); + EXPECT_EQ(0x87654321, GetValueByPointerWithDefault(d, "/foo/uint", 0x87654321, a).GetUint()); + EXPECT_EQ(0x87654321, GetValueByPointerWithDefault(d, "/foo/uint", 0x12345678, a).GetUint()); + + const int64_t i64 = static_cast(RAPIDJSON_UINT64_C2(0x80000000, 0)); + EXPECT_EQ(i64, GetValueByPointerWithDefault(d, "/foo/int64", i64, a).GetInt64()); + EXPECT_EQ(i64, GetValueByPointerWithDefault(d, "/foo/int64", i64 + 1, a).GetInt64()); + + const uint64_t u64 = RAPIDJSON_UINT64_C2(0xFFFFFFFFF, 0xFFFFFFFFF); + EXPECT_EQ(u64, GetValueByPointerWithDefault(d, "/foo/uint64", u64, a).GetUint64()); + EXPECT_EQ(u64, GetValueByPointerWithDefault(d, "/foo/uint64", u64 - 1, a).GetUint64()); + + EXPECT_TRUE(GetValueByPointerWithDefault(d, "/foo/true", true, a).IsTrue()); + EXPECT_TRUE(GetValueByPointerWithDefault(d, "/foo/true", false, a).IsTrue()); + + EXPECT_TRUE(GetValueByPointerWithDefault(d, "/foo/false", false, a).IsFalse()); + EXPECT_TRUE(GetValueByPointerWithDefault(d, "/foo/false", true, a).IsFalse()); + + // StringRef version + EXPECT_STREQ("Hello", GetValueByPointerWithDefault(d, "/foo/hello", "Hello", a).GetString()); + + // Copy string version + { + char buffer[256]; + strcpy(buffer, "World"); + EXPECT_STREQ("World", GetValueByPointerWithDefault(d, "/foo/world", buffer, a).GetString()); + memset(buffer, 0, sizeof(buffer)); + } + EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString()); } TEST(Pointer, SetValueByPointer_Pointer) { From fd9386589fb3ee97aaa349045e2f2c11589e852a Mon Sep 17 00:00:00 2001 From: miloyip Date: Sat, 2 May 2015 22:46:30 +0800 Subject: [PATCH 044/189] Add overloads for document as root, with no allocator parameter. --- include/rapidjson/pointer.h | 174 +++++++++++++++++++ test/unittest/pointertest.cpp | 310 ++++++++++++++++++++++++++++++++++ 2 files changed, 484 insertions(+) diff --git a/include/rapidjson/pointer.h b/include/rapidjson/pointer.h index 027d68b..cd52b43 100644 --- a/include/rapidjson/pointer.h +++ b/include/rapidjson/pointer.h @@ -209,6 +209,11 @@ public: return *v; } + template + ValueType& Create(GenericDocument& root, bool* alreadyExist = 0) const { + return Create(root, root.GetAllocator(), alreadyExist); + } + ValueType* Get(ValueType& root) const { RAPIDJSON_ASSERT(IsValid()); ValueType* v = &root; @@ -270,6 +275,27 @@ public: return GetWithDefault(root, v, allocator); } + template + ValueType& GetWithDefault(GenericDocument& root, const ValueType& defaultValue) const { + return GetWithDefault(root, defaultValue, root.GetAllocator()); + } + + template + ValueType& GetWithDefault(GenericDocument& root, GenericStringRef defaultValue) const { + return GetWithDefault(root, defaultValue, root.GetAllocator()); + } + + template + ValueType& GetWithDefault(GenericDocument& root, const Ch* defaultValue) const { + return GetWithDefault(root, defaultValue, root.GetAllocator()); + } + + template + RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (ValueType&)) + GetWithDefault(GenericDocument& root, T defaultValue) const { + return GetWithDefault(root, defaultValue, root.GetAllocator()); + } + // Move semantics, create parents if non-exist ValueType& Set(ValueType& root, ValueType& value, typename ValueType::AllocatorType& allocator) const { return Create(root, allocator) = value; @@ -297,6 +323,35 @@ public: return Create(root, allocator) = v; } + template + ValueType& Set(GenericDocument& root, ValueType& value) const { + return Create(root) = value; + } + + template + ValueType& Set(GenericDocument& root, const ValueType& value) const { + return Create(root).CopyFrom(value, root.GetAllocator()); + } + + template + ValueType& Set(GenericDocument& root, GenericStringRef value) const { + ValueType v(value); + return Create(root) = v; + } + + template + ValueType& Set(GenericDocument& root, const Ch* value) const { + ValueType v(value, root.GetAllocator()); + return Create(root) = v; + } + + template + RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (ValueType&)) + Set(GenericDocument& root, T value) const { + ValueType v(value); + return Create(root) = v; + } + // Create parents if non-exist ValueType& Swap(ValueType& root, ValueType& value, typename ValueType::AllocatorType& allocator) const { return Create(root, allocator).Swap(value); @@ -407,6 +462,8 @@ private: PointerParseErrorCode parseErrorCode_; }; +////////////////////////////////////////////////////////////////////////////// + template typename T::ValueType& CreateValueByPointer(T& root, const GenericPointer& pointer, typename T::AllocatorType& a) { return pointer.Create(root, a); @@ -418,6 +475,21 @@ typename T::ValueType& CreateValueByPointer(T& root, const CharType(&source)[N], return CreateValueByPointer(root, pointer, a); } +// No allocator parameter + +template +typename T::ValueType& CreateValueByPointer(T& root, const GenericPointer& pointer) { + return pointer.Create(root); +} + +template +typename T::ValueType& CreateValueByPointer(T& root, const CharType(&source)[N]) { + const GenericPointer pointer(source, N - 1); + return CreateValueByPointer(root, pointer); +} + +////////////////////////////////////////////////////////////////////////////// + template typename T::ValueType* GetValueByPointer(T& root, const GenericPointer& pointer) { return pointer.Get(root); @@ -440,6 +512,8 @@ const typename T::ValueType* GetValueByPointer(const T& root, const CharType(&so return GetValueByPointer(root, pointer); } +////////////////////////////////////////////////////////////////////////////// + template typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer& pointer, const typename T::ValueType& defaultValue, typename T::AllocatorType& a) { return pointer.GetWithDefault(root, defaultValue, a); @@ -486,6 +560,56 @@ GetValueByPointerWithDefault(T& root, const CharType(&source)[N], T2 defaultValu return GetValueByPointerWithDefault(root, pointer, defaultValue, a); } +// No allocator parameter + +template +typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer& pointer, const typename T::ValueType& defaultValue) { + return pointer.GetWithDefault(root, defaultValue); +} + +template +typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer& pointer, GenericStringRef defaultValue) { + return pointer.GetWithDefault(root, defaultValue); +} + +template +typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer& pointer, const typename T::Ch* defaultValue) { + return pointer.GetWithDefault(root, defaultValue); +} + +template +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename T::ValueType&)) +GetValueByPointerWithDefault(T& root, const GenericPointer& pointer, T2 defaultValue) { + return pointer.GetWithDefault(root, defaultValue); +} + +template +typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const typename T::ValueType& defaultValue) { + const GenericPointer pointer(source, N - 1); + return GetValueByPointerWithDefault(root, pointer, defaultValue); +} + +template +typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], GenericStringRef defaultValue) { + const GenericPointer pointer(source, N - 1); + return GetValueByPointerWithDefault(root, pointer, defaultValue); +} + +template +typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const typename T::Ch* defaultValue) { + const GenericPointer pointer(source, N - 1); + return GetValueByPointerWithDefault(root, pointer, defaultValue); +} + +template +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename T::ValueType&)) +GetValueByPointerWithDefault(T& root, const CharType(&source)[N], T2 defaultValue) { + const GenericPointer pointer(source, N - 1); + return GetValueByPointerWithDefault(root, pointer, defaultValue); +} + +////////////////////////////////////////////////////////////////////////////// + template typename T::ValueType& SetValueByPointer(T& root, const GenericPointer& pointer, typename T::ValueType& value, typename T::AllocatorType& a) { return pointer.Set(root, value, a); @@ -532,6 +656,56 @@ SetValueByPointer(T& root, const CharType(&source)[N], T2 value, typename T::All return SetValueByPointer(root, pointer, value, a); } +// No allocator parameter + +template +typename T::ValueType& SetValueByPointer(T& root, const GenericPointer& pointer, typename T::ValueType& value) { + return pointer.Set(root, value); +} + +template +typename T::ValueType& SetValueByPointer(T& root, const GenericPointer& pointer, GenericStringRef value) { + return pointer.Set(root, value); +} + +template +typename T::ValueType& SetValueByPointer(T& root, const GenericPointer& pointer, const typename T::Ch* value) { + return pointer.Set(root, value); +} + +template +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename T::ValueType&)) +SetValueByPointer(T& root, const GenericPointer& pointer, T2 value) { + return pointer.Set(root, value); +} + +template +typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], typename T::ValueType& value) { + const GenericPointer pointer(source, N - 1); + return SetValueByPointer(root, pointer, value); +} + +template +typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], GenericStringRef value) { + const GenericPointer pointer(source, N - 1); + return SetValueByPointer(root, pointer, value); +} + +template +typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const typename T::Ch* value) { + const GenericPointer pointer(source, N - 1); + return SetValueByPointer(root, pointer, value); +} + +template +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename T::ValueType&)) +SetValueByPointer(T& root, const CharType(&source)[N], T2 value) { + const GenericPointer pointer(source, N - 1); + return SetValueByPointer(root, pointer, value); +} + +////////////////////////////////////////////////////////////////////////////// + template typename T::ValueType& SwapValueByPointer(T& root, const GenericPointer& pointer, typename T::ValueType& value, typename T::AllocatorType& a) { return pointer.Swap(root, value, a); diff --git a/test/unittest/pointertest.cpp b/test/unittest/pointertest.cpp index a18646a..13015ba 100644 --- a/test/unittest/pointertest.cpp +++ b/test/unittest/pointertest.cpp @@ -288,6 +288,18 @@ TEST(Pointer, Create) { Value* v = &Pointer("/foo/-/-").Create(d, d.GetAllocator()); EXPECT_EQ(&d["foo"][2][0], v); } + + { + // Document with no allocator + Value* v = &Pointer("/foo/-").Create(d); + EXPECT_EQ(&d["foo"][3], v); + } + + { + // Value (not document) must give allocator + Value* v = &Pointer("/-").Create(d["foo"], d.GetAllocator()); + EXPECT_EQ(&d["foo"][4], v); + } } TEST(Pointer, Get) { @@ -358,6 +370,54 @@ TEST(Pointer, GetWithDefault) { EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString()); } +TEST(Pointer, GetWithDefault_NoAllocator) { + Document d; + d.Parse(kJson); + + // Value version + const Value v("qux"); + EXPECT_TRUE(Value("bar") == Pointer("/foo/0").GetWithDefault(d, v)); + EXPECT_TRUE(Value("baz") == Pointer("/foo/1").GetWithDefault(d, v)); + EXPECT_TRUE(Value("qux") == Pointer("/foo/2").GetWithDefault(d, v)); + EXPECT_TRUE(Value("last") == Pointer("/foo/-").GetWithDefault(d, Value("last").Move())); + EXPECT_STREQ("last", d["foo"][3].GetString()); + + EXPECT_TRUE(Pointer("/foo/null").GetWithDefault(d, Value().Move()).IsNull()); + EXPECT_TRUE(Pointer("/foo/null").GetWithDefault(d, "x").IsNull()); + + // Generic version + EXPECT_EQ(-1, Pointer("/foo/int").GetWithDefault(d, -1).GetInt()); + EXPECT_EQ(-1, Pointer("/foo/int").GetWithDefault(d, -2).GetInt()); + EXPECT_EQ(0x87654321, Pointer("/foo/uint").GetWithDefault(d, 0x87654321).GetUint()); + EXPECT_EQ(0x87654321, Pointer("/foo/uint").GetWithDefault(d, 0x12345678).GetUint()); + + const int64_t i64 = static_cast(RAPIDJSON_UINT64_C2(0x80000000, 0)); + EXPECT_EQ(i64, Pointer("/foo/int64").GetWithDefault(d, i64).GetInt64()); + EXPECT_EQ(i64, Pointer("/foo/int64").GetWithDefault(d, i64 + 1).GetInt64()); + + const uint64_t u64 = RAPIDJSON_UINT64_C2(0xFFFFFFFFF, 0xFFFFFFFFF); + EXPECT_EQ(u64, Pointer("/foo/uint64").GetWithDefault(d, u64).GetUint64()); + EXPECT_EQ(u64, Pointer("/foo/uint64").GetWithDefault(d, u64 - 1).GetUint64()); + + EXPECT_TRUE(Pointer("/foo/true").GetWithDefault(d, true).IsTrue()); + EXPECT_TRUE(Pointer("/foo/true").GetWithDefault(d, false).IsTrue()); + + EXPECT_TRUE(Pointer("/foo/false").GetWithDefault(d, false).IsFalse()); + EXPECT_TRUE(Pointer("/foo/false").GetWithDefault(d, true).IsFalse()); + + // StringRef version + EXPECT_STREQ("Hello", Pointer("/foo/hello").GetWithDefault(d, "Hello").GetString()); + + // Copy string version + { + char buffer[256]; + strcpy(buffer, "World"); + EXPECT_STREQ("World", Pointer("/foo/world").GetWithDefault(d, buffer).GetString()); + memset(buffer, 0, sizeof(buffer)); + } + EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString()); +} + TEST(Pointer, Set) { Document d; d.Parse(kJson); @@ -408,6 +468,55 @@ TEST(Pointer, Set) { EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString()); } +TEST(Pointer, Set_NoAllocator) { + Document d; + d.Parse(kJson); + + // Value version + Pointer("/foo/0").Set(d, Value(123).Move()); + EXPECT_EQ(123, d["foo"][0].GetInt()); + + Pointer("/foo/-").Set(d, Value(456).Move()); + EXPECT_EQ(456, d["foo"][2].GetInt()); + + Pointer("/foo/null").Set(d, Value().Move()); + EXPECT_TRUE(GetValueByPointer(d, "/foo/null")->IsNull()); + + // Generic version + Pointer("/foo/int").Set(d, -1); + EXPECT_EQ(-1, GetValueByPointer(d, "/foo/int")->GetInt()); + + Pointer("/foo/uint").Set(d, 0x87654321); + EXPECT_EQ(0x87654321, GetValueByPointer(d, "/foo/uint")->GetUint()); + + const int64_t i64 = static_cast(RAPIDJSON_UINT64_C2(0x80000000, 0)); + Pointer("/foo/int64").Set(d, i64); + EXPECT_EQ(i64, GetValueByPointer(d, "/foo/int64")->GetInt64()); + + const uint64_t u64 = RAPIDJSON_UINT64_C2(0xFFFFFFFFF, 0xFFFFFFFFF); + Pointer("/foo/uint64").Set(d, u64); + EXPECT_EQ(u64, GetValueByPointer(d, "/foo/uint64")->GetUint64()); + + Pointer("/foo/true").Set(d, true); + EXPECT_TRUE(GetValueByPointer(d, "/foo/true")->IsTrue()); + + Pointer("/foo/false").Set(d, false); + EXPECT_TRUE(GetValueByPointer(d, "/foo/false")->IsFalse()); + + // StringRef version + Pointer("/foo/hello").Set(d, "Hello"); + EXPECT_STREQ("Hello", GetValueByPointer(d, "/foo/hello")->GetString()); + + // Copy string version + { + char buffer[256]; + strcpy(buffer, "World"); + Pointer("/foo/world").Set(d, buffer); + memset(buffer, 0, sizeof(buffer)); + } + EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString()); +} + TEST(Pointer, Swap) { Document d; d.Parse(kJson); @@ -431,6 +540,19 @@ TEST(Pointer, CreateValueByPointer) { } } +TEST(Pointer, CreateValueByPointer_NoAllocator) { + Document d; + + { + Value& v = CreateValueByPointer(d, Pointer("/foo/0")); + EXPECT_EQ(&d["foo"][0], &v); + } + { + Value& v = CreateValueByPointer(d, "/foo/1"); + EXPECT_EQ(&d["foo"][1], &v); + } +} + TEST(Pointer, GetValueByPointer) { Document d; d.Parse(kJson); @@ -542,6 +664,102 @@ TEST(Pointer, GetValueByPointerWithDefault_String) { EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString()); } +TEST(Pointer, GetValueByPointerWithDefault_Pointer_NoAllocator) { + Document d; + d.Parse(kJson); + + const Value v("qux"); + EXPECT_TRUE(Value("bar") == GetValueByPointerWithDefault(d, Pointer("/foo/0"), v)); + EXPECT_TRUE(Value("bar") == GetValueByPointerWithDefault(d, Pointer("/foo/0"), v)); + EXPECT_TRUE(Value("baz") == GetValueByPointerWithDefault(d, Pointer("/foo/1"), v)); + EXPECT_TRUE(Value("qux") == GetValueByPointerWithDefault(d, Pointer("/foo/2"), v)); + EXPECT_TRUE(Value("last") == GetValueByPointerWithDefault(d, Pointer("/foo/-"), Value("last").Move())); + EXPECT_STREQ("last", d["foo"][3].GetString()); + + EXPECT_TRUE(GetValueByPointerWithDefault(d, Pointer("/foo/null"), Value().Move()).IsNull()); + EXPECT_TRUE(GetValueByPointerWithDefault(d, Pointer("/foo/null"), "x").IsNull()); + + // Generic version + EXPECT_EQ(-1, GetValueByPointerWithDefault(d, Pointer("/foo/int"), -1).GetInt()); + EXPECT_EQ(-1, GetValueByPointerWithDefault(d, Pointer("/foo/int"), -2).GetInt()); + EXPECT_EQ(0x87654321, GetValueByPointerWithDefault(d, Pointer("/foo/uint"), 0x87654321).GetUint()); + EXPECT_EQ(0x87654321, GetValueByPointerWithDefault(d, Pointer("/foo/uint"), 0x12345678).GetUint()); + + const int64_t i64 = static_cast(RAPIDJSON_UINT64_C2(0x80000000, 0)); + EXPECT_EQ(i64, GetValueByPointerWithDefault(d, Pointer("/foo/int64"), i64).GetInt64()); + EXPECT_EQ(i64, GetValueByPointerWithDefault(d, Pointer("/foo/int64"), i64 + 1).GetInt64()); + + const uint64_t u64 = RAPIDJSON_UINT64_C2(0xFFFFFFFFF, 0xFFFFFFFFF); + EXPECT_EQ(u64, GetValueByPointerWithDefault(d, Pointer("/foo/uint64"), u64).GetUint64()); + EXPECT_EQ(u64, GetValueByPointerWithDefault(d, Pointer("/foo/uint64"), u64 - 1).GetUint64()); + + EXPECT_TRUE(GetValueByPointerWithDefault(d, Pointer("/foo/true"), true).IsTrue()); + EXPECT_TRUE(GetValueByPointerWithDefault(d, Pointer("/foo/true"), false).IsTrue()); + + EXPECT_TRUE(GetValueByPointerWithDefault(d, Pointer("/foo/false"), false).IsFalse()); + EXPECT_TRUE(GetValueByPointerWithDefault(d, Pointer("/foo/false"), true).IsFalse()); + + // StringRef version + EXPECT_STREQ("Hello", GetValueByPointerWithDefault(d, Pointer("/foo/hello"), "Hello").GetString()); + + // Copy string version + { + char buffer[256]; + strcpy(buffer, "World"); + EXPECT_STREQ("World", GetValueByPointerWithDefault(d, Pointer("/foo/world"), buffer).GetString()); + memset(buffer, 0, sizeof(buffer)); + } + EXPECT_STREQ("World", GetValueByPointer(d, Pointer("/foo/world"))->GetString()); +} + +TEST(Pointer, GetValueByPointerWithDefault_String_NoAllocator) { + Document d; + d.Parse(kJson); + + const Value v("qux"); + EXPECT_TRUE(Value("bar") == GetValueByPointerWithDefault(d, "/foo/0", v)); + EXPECT_TRUE(Value("bar") == GetValueByPointerWithDefault(d, "/foo/0", v)); + EXPECT_TRUE(Value("baz") == GetValueByPointerWithDefault(d, "/foo/1", v)); + EXPECT_TRUE(Value("qux") == GetValueByPointerWithDefault(d, "/foo/2", v)); + EXPECT_TRUE(Value("last") == GetValueByPointerWithDefault(d, "/foo/-", Value("last").Move())); + EXPECT_STREQ("last", d["foo"][3].GetString()); + + EXPECT_TRUE(GetValueByPointerWithDefault(d, "/foo/null", Value().Move()).IsNull()); + EXPECT_TRUE(GetValueByPointerWithDefault(d, "/foo/null", "x").IsNull()); + + // Generic version + EXPECT_EQ(-1, GetValueByPointerWithDefault(d, "/foo/int", -1).GetInt()); + EXPECT_EQ(-1, GetValueByPointerWithDefault(d, "/foo/int", -2).GetInt()); + EXPECT_EQ(0x87654321, GetValueByPointerWithDefault(d, "/foo/uint", 0x87654321).GetUint()); + EXPECT_EQ(0x87654321, GetValueByPointerWithDefault(d, "/foo/uint", 0x12345678).GetUint()); + + const int64_t i64 = static_cast(RAPIDJSON_UINT64_C2(0x80000000, 0)); + EXPECT_EQ(i64, GetValueByPointerWithDefault(d, "/foo/int64", i64).GetInt64()); + EXPECT_EQ(i64, GetValueByPointerWithDefault(d, "/foo/int64", i64 + 1).GetInt64()); + + const uint64_t u64 = RAPIDJSON_UINT64_C2(0xFFFFFFFFF, 0xFFFFFFFFF); + EXPECT_EQ(u64, GetValueByPointerWithDefault(d, "/foo/uint64", u64).GetUint64()); + EXPECT_EQ(u64, GetValueByPointerWithDefault(d, "/foo/uint64", u64 - 1).GetUint64()); + + EXPECT_TRUE(GetValueByPointerWithDefault(d, "/foo/true", true).IsTrue()); + EXPECT_TRUE(GetValueByPointerWithDefault(d, "/foo/true", false).IsTrue()); + + EXPECT_TRUE(GetValueByPointerWithDefault(d, "/foo/false", false).IsFalse()); + EXPECT_TRUE(GetValueByPointerWithDefault(d, "/foo/false", true).IsFalse()); + + // StringRef version + EXPECT_STREQ("Hello", GetValueByPointerWithDefault(d, "/foo/hello", "Hello").GetString()); + + // Copy string version + { + char buffer[256]; + strcpy(buffer, "World"); + EXPECT_STREQ("World", GetValueByPointerWithDefault(d, "/foo/world", buffer).GetString()); + memset(buffer, 0, sizeof(buffer)); + } + EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString()); +} + TEST(Pointer, SetValueByPointer_Pointer) { Document d; d.Parse(kJson); @@ -636,6 +854,98 @@ TEST(Pointer, SetValueByPointer_String) { EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString()); } +TEST(Pointer, SetValueByPointer_Pointer_NoAllocator) { + Document d; + d.Parse(kJson); + + // Value version + SetValueByPointer(d, Pointer("/foo/0"), Value(123).Move()); + EXPECT_EQ(123, d["foo"][0].GetInt()); + + SetValueByPointer(d, Pointer("/foo/null"), Value().Move()); + EXPECT_TRUE(GetValueByPointer(d, "/foo/null")->IsNull()); + + // Generic version + SetValueByPointer(d, Pointer("/foo/int"), -1); + EXPECT_EQ(-1, GetValueByPointer(d, "/foo/int")->GetInt()); + + SetValueByPointer(d, Pointer("/foo/uint"), 0x87654321); + EXPECT_EQ(0x87654321, GetValueByPointer(d, "/foo/uint")->GetUint()); + + const int64_t i64 = static_cast(RAPIDJSON_UINT64_C2(0x80000000, 0)); + SetValueByPointer(d, Pointer("/foo/int64"), i64); + EXPECT_EQ(i64, GetValueByPointer(d, "/foo/int64")->GetInt64()); + + const uint64_t u64 = RAPIDJSON_UINT64_C2(0xFFFFFFFFF, 0xFFFFFFFFF); + SetValueByPointer(d, Pointer("/foo/uint64"), u64); + EXPECT_EQ(u64, GetValueByPointer(d, "/foo/uint64")->GetUint64()); + + SetValueByPointer(d, Pointer("/foo/true"), true); + EXPECT_TRUE(GetValueByPointer(d, "/foo/true")->IsTrue()); + + SetValueByPointer(d, Pointer("/foo/false"), false); + EXPECT_TRUE(GetValueByPointer(d, "/foo/false")->IsFalse()); + + // StringRef version + SetValueByPointer(d, Pointer("/foo/hello"), "Hello"); + EXPECT_STREQ("Hello", GetValueByPointer(d, "/foo/hello")->GetString()); + + // Copy string version + { + char buffer[256]; + strcpy(buffer, "World"); + SetValueByPointer(d, Pointer("/foo/world"), buffer); + memset(buffer, 0, sizeof(buffer)); + } + EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString()); +} + +TEST(Pointer, SetValueByPointer_String_NoAllocator) { + Document d; + d.Parse(kJson); + + // Value version + SetValueByPointer(d, "/foo/0", Value(123).Move()); + EXPECT_EQ(123, d["foo"][0].GetInt()); + + SetValueByPointer(d, "/foo/null", Value().Move()); + EXPECT_TRUE(GetValueByPointer(d, "/foo/null")->IsNull()); + + // Generic version + SetValueByPointer(d, "/foo/int", -1); + EXPECT_EQ(-1, GetValueByPointer(d, "/foo/int")->GetInt()); + + SetValueByPointer(d, "/foo/uint", 0x87654321); + EXPECT_EQ(0x87654321, GetValueByPointer(d, "/foo/uint")->GetUint()); + + const int64_t i64 = static_cast(RAPIDJSON_UINT64_C2(0x80000000, 0)); + SetValueByPointer(d, "/foo/int64", i64); + EXPECT_EQ(i64, GetValueByPointer(d, "/foo/int64")->GetInt64()); + + const uint64_t u64 = RAPIDJSON_UINT64_C2(0xFFFFFFFFF, 0xFFFFFFFFF); + SetValueByPointer(d, "/foo/uint64", u64); + EXPECT_EQ(u64, GetValueByPointer(d, "/foo/uint64")->GetUint64()); + + SetValueByPointer(d, "/foo/true", true); + EXPECT_TRUE(GetValueByPointer(d, "/foo/true")->IsTrue()); + + SetValueByPointer(d, "/foo/false", false); + EXPECT_TRUE(GetValueByPointer(d, "/foo/false")->IsFalse()); + + // StringRef version + SetValueByPointer(d, "/foo/hello", "Hello"); + EXPECT_STREQ("Hello", GetValueByPointer(d, "/foo/hello")->GetString()); + + // Copy string version + { + char buffer[256]; + strcpy(buffer, "World"); + SetValueByPointer(d, "/foo/world", buffer); + memset(buffer, 0, sizeof(buffer)); + } + EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString()); +} + TEST(Pointer, SwapValueByPointer) { Document d; d.Parse(kJson); From 2ee15de4a9f5813594820eb510dfcd2090238b18 Mon Sep 17 00:00:00 2001 From: miloyip Date: Sat, 2 May 2015 22:58:41 +0800 Subject: [PATCH 045/189] Add no allocator overloads for Swap --- include/rapidjson/pointer.h | 18 +++++++++++++++++- test/unittest/pointertest.cpp | 20 ++++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/include/rapidjson/pointer.h b/include/rapidjson/pointer.h index cd52b43..c0b2253 100644 --- a/include/rapidjson/pointer.h +++ b/include/rapidjson/pointer.h @@ -357,6 +357,11 @@ public: return Create(root, allocator).Swap(value); } + template + ValueType& Swap(GenericDocument& root, ValueType& value) const { + return Create(root).Swap(value); + } + private: void Parse(const Ch* source, size_t length) { // Create own allocator if user did not supply. @@ -462,6 +467,8 @@ private: PointerParseErrorCode parseErrorCode_; }; +typedef GenericPointer Pointer; + ////////////////////////////////////////////////////////////////////////////// template @@ -717,7 +724,16 @@ typename T::ValueType& SwapValueByPointer(T& root, const CharType(&source)[N], t return SwapValueByPointer(root, pointer, value, a); } -typedef GenericPointer Pointer; +template +typename T::ValueType& SwapValueByPointer(T& root, const GenericPointer& pointer, typename T::ValueType& value) { + return pointer.Swap(root, value); +} + +template +typename T::ValueType& SwapValueByPointer(T& root, const CharType(&source)[N], typename T::ValueType& value) { + const GenericPointer pointer(source, N - 1); + return SwapValueByPointer(root, pointer, value); +} RAPIDJSON_NAMESPACE_END diff --git a/test/unittest/pointertest.cpp b/test/unittest/pointertest.cpp index 13015ba..75ca5a3 100644 --- a/test/unittest/pointertest.cpp +++ b/test/unittest/pointertest.cpp @@ -526,6 +526,14 @@ TEST(Pointer, Swap) { EXPECT_STREQ("bar", d["foo"][1].GetString()); } +TEST(Pointer, Swap_NoAllocator) { + Document d; + d.Parse(kJson); + Pointer("/foo/0").Swap(d, *Pointer("/foo/1").Get(d)); + EXPECT_STREQ("baz", d["foo"][0].GetString()); + EXPECT_STREQ("bar", d["foo"][1].GetString()); +} + TEST(Pointer, CreateValueByPointer) { Document d; Document::AllocatorType& a = d.GetAllocator(); @@ -958,3 +966,15 @@ TEST(Pointer, SwapValueByPointer) { EXPECT_STREQ("bar", d["foo"][0].GetString()); EXPECT_STREQ("baz", d["foo"][1].GetString()); } + +TEST(Pointer, SwapValueByPointer_NoAllocator) { + Document d; + d.Parse(kJson); + SwapValueByPointer(d, Pointer("/foo/0"), *GetValueByPointer(d, "/foo/1")); + EXPECT_STREQ("baz", d["foo"][0].GetString()); + EXPECT_STREQ("bar", d["foo"][1].GetString()); + + SwapValueByPointer(d, "/foo/0", *GetValueByPointer(d, "/foo/1")); + EXPECT_STREQ("bar", d["foo"][0].GetString()); + EXPECT_STREQ("baz", d["foo"][1].GetString()); +} From 28f14bd68f30872417a6c96dc4be1e7195c24f5d Mon Sep 17 00:00:00 2001 From: miloyip Date: Sun, 3 May 2015 09:51:15 +0800 Subject: [PATCH 046/189] Add parsing of URI fragment representation of JSON pointer --- include/rapidjson/pointer.h | 44 ++++++++- test/unittest/pointertest.cpp | 178 ++++++++++++++++++++++++++++++++++ 2 files changed, 220 insertions(+), 2 deletions(-) diff --git a/include/rapidjson/pointer.h b/include/rapidjson/pointer.h index c0b2253..4086751 100644 --- a/include/rapidjson/pointer.h +++ b/include/rapidjson/pointer.h @@ -25,7 +25,9 @@ enum PointerParseErrorCode { kPointerParseErrorNone = 0, kPointerParseErrorTokenMustBeginWithSolidus, - kPointerParseErrorInvalidEscape + kPointerParseErrorInvalidEscape, + kPointerParseErrorInvalidPercentEncoding, + kPointerParseErrorCharacterMustPercentEncode }; template @@ -363,6 +365,12 @@ public: } private: + //! Parse a JSON String or its URI fragment representation into tokens. + /*! + \param source Either a JSON Pointer string, or its URI fragment representation. Not need to be null terminated. + \param length Length of the source string. + \note Source cannot be JSON String Representation of JSON Pointer, e.g. In "/\u0000", \u0000 will not be unescaped. + */ void Parse(const Ch* source, size_t length) { // Create own allocator if user did not supply. if (!allocator_) @@ -380,7 +388,14 @@ private: size_t i = 0; - if (length != 0 && source[i] != '/') { + // Detect if it is a URI fragment + bool uriFragment = false; + if (source[i] == '#') { + uriFragment = true; + i++; + } + + if (i != length && source[i] != '/') { parseErrorCode_ = kPointerParseErrorTokenMustBeginWithSolidus; goto error; } @@ -395,6 +410,31 @@ private: while (i < length && source[i] != '/') { Ch c = source[i++]; + + if (uriFragment) { + // Decoding percent-encoding for URI fragment + if (c == '%') { + c = 0; + for (int j = 0; j < 2; j++) { + c <<= 4; + Ch h = source[i]; + if (h >= '0' && h <= '9') c += h - '0'; + else if (h >= 'A' && h <= 'F') c += h - 'A' + 10; + else if (h >= 'a' && h <= 'f') c += h - 'a' + 10; + else { + parseErrorCode_ = kPointerParseErrorInvalidPercentEncoding; + goto error; + } + i++; + } + } + else if (!((c >= '0' && c <= '9') || (c >= 'A' && c <='Z') || (c >= 'a' && c <= 'z') || c == '-' || c == '.' || c == '_' || c =='~')) { + // RFC 3986 2.3 Unreserved Characters + i--; + parseErrorCode_ = kPointerParseErrorCharacterMustPercentEncode; + goto error; + } + } // Escaping "~0" -> '~', "~1" -> '/' if (c == '~') { diff --git a/test/unittest/pointertest.cpp b/test/unittest/pointertest.cpp index 75ca5a3..32f659b 100644 --- a/test/unittest/pointertest.cpp +++ b/test/unittest/pointertest.cpp @@ -165,6 +165,184 @@ TEST(Pointer, Parse) { } } +TEST(Pointer, Parse_URIFragment) { + { + Pointer p("#"); + EXPECT_TRUE(p.IsValid()); + EXPECT_EQ(0u, p.GetTokenCount()); + } + + { + Pointer p("#/foo"); + EXPECT_TRUE(p.IsValid()); + EXPECT_EQ(1u, p.GetTokenCount()); + EXPECT_EQ(3u, p.GetTokens()[0].length); + EXPECT_STREQ("foo", p.GetTokens()[0].name); + } + + { + Pointer p("#/foo/0"); + EXPECT_TRUE(p.IsValid()); + EXPECT_EQ(2u, p.GetTokenCount()); + EXPECT_EQ(3u, p.GetTokens()[0].length); + EXPECT_STREQ("foo", p.GetTokens()[0].name); + EXPECT_EQ(1u, p.GetTokens()[1].length); + EXPECT_STREQ("0", p.GetTokens()[1].name); + EXPECT_EQ(0u, p.GetTokens()[1].index); + } + + { + // Unescape ~1 + Pointer p("#/a~1b"); + EXPECT_TRUE(p.IsValid()); + EXPECT_EQ(1u, p.GetTokenCount()); + EXPECT_EQ(3u, p.GetTokens()[0].length); + EXPECT_STREQ("a/b", p.GetTokens()[0].name); + } + + { + // Unescape ~0 + Pointer p("#/m~0n"); + EXPECT_TRUE(p.IsValid()); + EXPECT_EQ(1u, p.GetTokenCount()); + EXPECT_EQ(3u, p.GetTokens()[0].length); + EXPECT_STREQ("m~n", p.GetTokens()[0].name); + } + + { + // empty name + Pointer p("#/"); + EXPECT_TRUE(p.IsValid()); + EXPECT_EQ(1u, p.GetTokenCount()); + EXPECT_EQ(0u, p.GetTokens()[0].length); + EXPECT_STREQ("", p.GetTokens()[0].name); + } + + { + // empty and non-empty name + Pointer p("#//a"); + EXPECT_TRUE(p.IsValid()); + EXPECT_EQ(2u, p.GetTokenCount()); + EXPECT_EQ(0u, p.GetTokens()[0].length); + EXPECT_STREQ("", p.GetTokens()[0].name); + EXPECT_EQ(1u, p.GetTokens()[1].length); + EXPECT_STREQ("a", p.GetTokens()[1].name); + } + + { + // Null characters + Pointer p("#/%00%00"); + EXPECT_TRUE(p.IsValid()); + EXPECT_EQ(1u, p.GetTokenCount()); + EXPECT_EQ(2u, p.GetTokens()[0].length); + EXPECT_EQ('\0', p.GetTokens()[0].name[0]); + EXPECT_EQ('\0', p.GetTokens()[0].name[1]); + EXPECT_EQ('\0', p.GetTokens()[0].name[2]); + } + + { + // Percentage Escapes + EXPECT_STREQ("c%d", Pointer("#/c%25d").GetTokens()[0].name); + EXPECT_STREQ("e^f", Pointer("#/e%5Ef").GetTokens()[0].name); + EXPECT_STREQ("g|h", Pointer("#/g%7Ch").GetTokens()[0].name); + EXPECT_STREQ("i\\j", Pointer("#/i%5Cj").GetTokens()[0].name); + EXPECT_STREQ("k\"l", Pointer("#/k%22l").GetTokens()[0].name); + EXPECT_STREQ(" ", Pointer("#/%20").GetTokens()[0].name); + } + + { + // Valid index + Pointer p("#/123"); + EXPECT_TRUE(p.IsValid()); + EXPECT_EQ(1u, p.GetTokenCount()); + EXPECT_STREQ("123", p.GetTokens()[0].name); + EXPECT_EQ(123u, p.GetTokens()[0].index); + } + + { + // Invalid index (with leading zero) + Pointer p("#/01"); + EXPECT_TRUE(p.IsValid()); + EXPECT_EQ(1u, p.GetTokenCount()); + EXPECT_STREQ("01", p.GetTokens()[0].name); + EXPECT_EQ(kPointerInvalidIndex, p.GetTokens()[0].index); + } + + if (sizeof(SizeType) == 4) { + // Invalid index (overflow) + Pointer p("#/4294967296"); + EXPECT_TRUE(p.IsValid()); + EXPECT_EQ(1u, p.GetTokenCount()); + EXPECT_STREQ("4294967296", p.GetTokens()[0].name); + EXPECT_EQ(kPointerInvalidIndex, p.GetTokens()[0].index); + } + + { + // kPointerParseErrorTokenMustBeginWithSolidus + Pointer p("# "); + EXPECT_FALSE(p.IsValid()); + EXPECT_EQ(kPointerParseErrorTokenMustBeginWithSolidus, p.GetParseErrorCode()); + EXPECT_EQ(1u, p.GetParseErrorOffset()); + } + + { + // kPointerParseErrorInvalidEscape + Pointer p("#/~"); + EXPECT_FALSE(p.IsValid()); + EXPECT_EQ(kPointerParseErrorInvalidEscape, p.GetParseErrorCode()); + EXPECT_EQ(3u, p.GetParseErrorOffset()); + } + + { + // kPointerParseErrorInvalidEscape + Pointer p("#/~2"); + EXPECT_FALSE(p.IsValid()); + EXPECT_EQ(kPointerParseErrorInvalidEscape, p.GetParseErrorCode()); + EXPECT_EQ(3u, p.GetParseErrorOffset()); + } + + { + // kPointerParseErrorInvalidPercentEncoding + Pointer p("#/%"); + EXPECT_FALSE(p.IsValid()); + EXPECT_EQ(kPointerParseErrorInvalidPercentEncoding, p.GetParseErrorCode()); + EXPECT_EQ(3u, p.GetParseErrorOffset()); + } + + { + // kPointerParseErrorInvalidPercentEncoding + Pointer p("#/%g0"); + EXPECT_FALSE(p.IsValid()); + EXPECT_EQ(kPointerParseErrorInvalidPercentEncoding, p.GetParseErrorCode()); + EXPECT_EQ(3u, p.GetParseErrorOffset()); + } + + { + // kPointerParseErrorInvalidPercentEncoding + Pointer p("#/%0g"); + EXPECT_FALSE(p.IsValid()); + EXPECT_EQ(kPointerParseErrorInvalidPercentEncoding, p.GetParseErrorCode()); + EXPECT_EQ(4u, p.GetParseErrorOffset()); + } + + { + // kPointerParseErrorCharacterMustPercentEncode + Pointer p("#/ "); + EXPECT_FALSE(p.IsValid()); + EXPECT_EQ(kPointerParseErrorCharacterMustPercentEncode, p.GetParseErrorCode()); + EXPECT_EQ(2u, p.GetParseErrorOffset()); + } + + { + // kPointerParseErrorCharacterMustPercentEncode + Pointer p("#/\\"); + EXPECT_FALSE(p.IsValid()); + EXPECT_EQ(kPointerParseErrorCharacterMustPercentEncode, p.GetParseErrorCode()); + EXPECT_EQ(2u, p.GetParseErrorOffset()); + } + +} + TEST(Pointer, Stringify) { // Test by roundtrip const char* sources[] = { From 0eb6cb8e5f2ce8bce04768c801e569765378bb97 Mon Sep 17 00:00:00 2001 From: miloyip Date: Sun, 3 May 2015 14:14:05 +0800 Subject: [PATCH 047/189] Add equality/inequality operator, URI fragment stringify and UTF-8 Percent Encoding/Decoding --- include/rapidjson/pointer.h | 162 ++++++++++++++++++++++++++++------ test/unittest/pointertest.cpp | 77 ++++++++++++++-- 2 files changed, 207 insertions(+), 32 deletions(-) diff --git a/include/rapidjson/pointer.h b/include/rapidjson/pointer.h index 4086751..2d42412 100644 --- a/include/rapidjson/pointer.h +++ b/include/rapidjson/pointer.h @@ -123,7 +123,7 @@ public: for (Token *t = rhs.tokens_; t != rhs.tokens_ + tokenCount_; ++t) nameBufferSize += t->length; nameBuffer_ = (Ch*)allocator_->Malloc(nameBufferSize * sizeof(Ch)); - std::memcpy(nameBuffer_, rhs.nameBuffer_, nameBufferSize); + std::memcpy(nameBuffer_, rhs.nameBuffer_, nameBufferSize * sizeof(Ch)); tokens_ = (Token*)allocator_->Malloc(tokenCount_ * sizeof(Token)); std::memcpy(tokens_, rhs.tokens_, tokenCount_ * sizeof(Token)); @@ -149,20 +149,34 @@ public: size_t GetTokenCount() const { return tokenCount_; } - template - void Stringify(OutputStream& os) const { - RAPIDJSON_ASSERT(IsValid()); - for (Token *t = tokens_; t != tokens_ + tokenCount_; ++t) { - os.Put('/'); - for (size_t j = 0; j < t->length; j++) { - Ch c = t->name[j]; - if (c == '~') { os.Put('~'); os.Put('0'); } - else if (c == '/') { os.Put('~'); os.Put('1'); } - else os.Put(c); + bool operator==(const GenericPointer& rhs) const { + if (!IsValid() || !rhs.IsValid() || tokenCount_ != rhs.tokenCount_) + return false; + + for (size_t i = 0; i < tokenCount_; i++) { + if (tokens_[i].index != rhs.tokens_[i].index || + tokens_[i].length != rhs.tokens_[i].length || + std::memcmp(tokens_[i].name, rhs.tokens_[i].name, sizeof(Ch) * tokens_[i].length) != 0) + { + return false; } } + + return true; } + bool operator!=(const GenericPointer& rhs) const { return !(*this == rhs); } + + template + bool Stringify(OutputStream& os) const { + return Stringify(os); + } + + template + bool StringifyUriFragment(OutputStream& os) const { + return Stringify(os); + } + ValueType& Create(ValueType& root, typename ValueType::AllocatorType& allocator, bool* alreadyExist = 0) const { RAPIDJSON_ASSERT(IsValid()); ValueType* v = &root; @@ -365,6 +379,11 @@ public: } private: + bool NeedPercentEncode(Ch c) const { + // RFC 3986 2.3 Unreserved Characters + return !((c >= '0' && c <= '9') || (c >= 'A' && c <='Z') || (c >= 'a' && c <= 'z') || c == '-' || c == '.' || c == '_' || c =='~'); + } + //! Parse a JSON String or its URI fragment representation into tokens. /*! \param source Either a JSON Pointer string, or its URI fragment representation. Not need to be null terminated. @@ -409,32 +428,37 @@ private: bool isNumber = true; while (i < length && source[i] != '/') { - Ch c = source[i++]; + Ch c = source[i]; if (uriFragment) { // Decoding percent-encoding for URI fragment if (c == '%') { - c = 0; - for (int j = 0; j < 2; j++) { - c <<= 4; - Ch h = source[i]; - if (h >= '0' && h <= '9') c += h - '0'; - else if (h >= 'A' && h <= 'F') c += h - 'A' + 10; - else if (h >= 'a' && h <= 'f') c += h - 'a' + 10; - else { - parseErrorCode_ = kPointerParseErrorInvalidPercentEncoding; - goto error; - } + PercentDecodeStream is(&source[i]); + GenericInsituStringStream os(name); + Ch* begin = os.PutBegin(); + Transcoder, EncodingType> transcoder; + if (!transcoder.Transcode(is, os) || !is.IsValid()) { + parseErrorCode_ = kPointerParseErrorInvalidPercentEncoding; + goto error; + } + size_t len = os.PutEnd(begin); + i += is.Tell() - 1; + if (len == 1) + c = *name; + else { + name += len; + isNumber = false; i++; + continue; } } - else if (!((c >= '0' && c <= '9') || (c >= 'A' && c <='Z') || (c >= 'a' && c <= 'z') || c == '-' || c == '.' || c == '_' || c =='~')) { - // RFC 3986 2.3 Unreserved Characters - i--; + else if (NeedPercentEncode(c)) { parseErrorCode_ = kPointerParseErrorCharacterMustPercentEncode; goto error; } } + + i++; // Escaping "~0" -> '~', "~1" -> '/' if (c == '~') { @@ -498,6 +522,92 @@ private: return; } + template + bool Stringify(OutputStream& os) const { + RAPIDJSON_ASSERT(IsValid()); + + if (uriFragment) + os.Put('#'); + + for (Token *t = tokens_; t != tokens_ + tokenCount_; ++t) { + os.Put('/'); + for (size_t j = 0; j < t->length; j++) { + Ch c = t->name[j]; + if (c == '~') { + os.Put('~'); + os.Put('0'); + } + else if (c == '/') { + os.Put('~'); + os.Put('1'); + } + else if (uriFragment && NeedPercentEncode(c)) { + // Transcode to UTF8 sequence + GenericStringStream source(&t->name[j]); + PercentEncodeStream target(os); + Transcoder > transcoder; + if (!transcoder.Transcode(source, target)) + return false; + j += source.Tell() - 1; + } + else + os.Put(c); + } + } + return true; + } + + class PercentDecodeStream { + public: + PercentDecodeStream(const Ch* source) : src_(source), head_(source), valid_(true) {} + + Ch Take() { + if (*src_ != '%') { + valid_ = false; + return 0; + } + src_++; + Ch c = 0; + for (int j = 0; j < 2; j++) { + c <<= 4; + Ch h = *src_; + if (h >= '0' && h <= '9') c += h - '0'; + else if (h >= 'A' && h <= 'F') c += h - 'A' + 10; + else if (h >= 'a' && h <= 'f') c += h - 'a' + 10; + else { + valid_ = false; + return 0; + } + src_++; + } + return c; + } + + size_t Tell() const { return src_ - head_; } + + bool IsValid() const { return valid_; } + + private: + const Ch* src_; //!< Current read position. + const Ch* head_; //!< Original head of the string. + bool valid_; + }; + + template + class PercentEncodeStream { + public: + PercentEncodeStream(OutputStream& os) : os_(os) {} + void Put(char c) { // UTF-8 must be byte + unsigned char u = static_cast(c); + static const char hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + os_.Put('%'); + os_.Put(hexDigits[u >> 4]); + os_.Put(hexDigits[u & 15]); + } + private: + OutputStream& os_; + }; + Allocator* allocator_; Allocator* ownAllocator_; Ch* nameBuffer_; diff --git a/test/unittest/pointertest.cpp b/test/unittest/pointertest.cpp index 32f659b..3a6742e 100644 --- a/test/unittest/pointertest.cpp +++ b/test/unittest/pointertest.cpp @@ -277,6 +277,46 @@ TEST(Pointer, Parse_URIFragment) { EXPECT_EQ(kPointerInvalidIndex, p.GetTokens()[0].index); } + { + // Decode UTF-8 perecent encoding to UTF-8 + Pointer p("#/%C2%A2"); + EXPECT_TRUE(p.IsValid()); + EXPECT_EQ(1u, p.GetTokenCount()); + EXPECT_STREQ("\xC2\xA2", p.GetTokens()[0].name); + } + + { + // Decode UTF-8 perecent encoding to UTF-16 + GenericPointer > > p(L"#/%C2%A2"); + EXPECT_TRUE(p.IsValid()); + EXPECT_EQ(1u, p.GetTokenCount()); + EXPECT_STREQ(L"\xA2", p.GetTokens()[0].name); + } + + { + // Decode UTF-8 perecent encoding to UTF-16 + GenericPointer > > p(L"#/%C2%A2"); + EXPECT_TRUE(p.IsValid()); + EXPECT_EQ(1u, p.GetTokenCount()); + EXPECT_STREQ(L"\xA2", p.GetTokens()[0].name); + } + + { + // Decode UTF-8 perecent encoding to UTF-16 + GenericPointer > > p(L"#/%C2%A2"); + EXPECT_TRUE(p.IsValid()); + EXPECT_EQ(1u, p.GetTokenCount()); + EXPECT_STREQ(L"\x00A2", p.GetTokens()[0].name); + } + + { + // Decode UTF-8 perecent encoding to UTF-16 + GenericPointer > > p(L"#/%E2%82%AC"); + EXPECT_TRUE(p.IsValid()); + EXPECT_EQ(1u, p.GetTokenCount()); + EXPECT_STREQ(L"\x20AC", p.GetTokens()[0].name); + } + { // kPointerParseErrorTokenMustBeginWithSolidus Pointer p("# "); @@ -306,7 +346,7 @@ TEST(Pointer, Parse_URIFragment) { Pointer p("#/%"); EXPECT_FALSE(p.IsValid()); EXPECT_EQ(kPointerParseErrorInvalidPercentEncoding, p.GetParseErrorCode()); - EXPECT_EQ(3u, p.GetParseErrorOffset()); + EXPECT_EQ(2u, p.GetParseErrorOffset()); } { @@ -314,7 +354,7 @@ TEST(Pointer, Parse_URIFragment) { Pointer p("#/%g0"); EXPECT_FALSE(p.IsValid()); EXPECT_EQ(kPointerParseErrorInvalidPercentEncoding, p.GetParseErrorCode()); - EXPECT_EQ(3u, p.GetParseErrorOffset()); + EXPECT_EQ(2u, p.GetParseErrorOffset()); } { @@ -322,7 +362,7 @@ TEST(Pointer, Parse_URIFragment) { Pointer p("#/%0g"); EXPECT_FALSE(p.IsValid()); EXPECT_EQ(kPointerParseErrorInvalidPercentEncoding, p.GetParseErrorCode()); - EXPECT_EQ(4u, p.GetParseErrorOffset()); + EXPECT_EQ(2u, p.GetParseErrorOffset()); } { @@ -335,12 +375,11 @@ TEST(Pointer, Parse_URIFragment) { { // kPointerParseErrorCharacterMustPercentEncode - Pointer p("#/\\"); + Pointer p("#/\n"); EXPECT_FALSE(p.IsValid()); EXPECT_EQ(kPointerParseErrorCharacterMustPercentEncode, p.GetParseErrorCode()); EXPECT_EQ(2u, p.GetParseErrorOffset()); } - } TEST(Pointer, Stringify) { @@ -357,7 +396,10 @@ TEST(Pointer, Stringify) { "/i\\j", "/k\"l", "/ ", - "/m~0n" + "/m~0n", + "/\xC2\xA2", + "/\xE2\x82\xAC", + "/\xF0\x9D\x84\x9E" }; for (size_t i = 0; i < sizeof(sources) / sizeof(sources[0]); i++) { @@ -365,6 +407,13 @@ TEST(Pointer, Stringify) { StringBuffer s; p.Stringify(s); EXPECT_STREQ(sources[i], s.GetString()); + + // Stringify to URI fragment + StringBuffer s2; + p.StringifyUriFragment(s2); + Pointer p2(s2.GetString(), s2.GetSize()); + EXPECT_TRUE(p2.IsValid()); + EXPECT_TRUE(p == p2); } } @@ -444,6 +493,22 @@ TEST(Pointer, Assignment) { } } +TEST(Pointer, Equality) { + EXPECT_TRUE(Pointer("/foo/0") == Pointer("/foo/0")); + EXPECT_FALSE(Pointer("/foo/0") == Pointer("/foo/1")); + EXPECT_FALSE(Pointer("/foo/0") == Pointer("/foo/0/1")); + EXPECT_FALSE(Pointer("/foo/0") == Pointer("a")); + EXPECT_FALSE(Pointer("a") == Pointer("a")); // Invalid always not equal +} + +TEST(Pointer, Inequality) { + EXPECT_FALSE(Pointer("/foo/0") != Pointer("/foo/0")); + EXPECT_TRUE(Pointer("/foo/0") != Pointer("/foo/1")); + EXPECT_TRUE(Pointer("/foo/0") != Pointer("/foo/0/1")); + EXPECT_TRUE(Pointer("/foo/0") != Pointer("a")); + EXPECT_TRUE(Pointer("a") != Pointer("a")); // Invalid always not equal +} + TEST(Pointer, Create) { Document d; { From bb0e8289283f61d4ca637ebbd2f5cb7e432f9513 Mon Sep 17 00:00:00 2001 From: miloyip Date: Sun, 3 May 2015 18:55:55 +0800 Subject: [PATCH 048/189] Some std::string overloads for Pointer --- include/rapidjson/pointer.h | 226 +++++++++++++++++++--------------- test/unittest/CMakeLists.txt | 2 + test/unittest/pointertest.cpp | 64 ++++++++++ 3 files changed, 192 insertions(+), 100 deletions(-) diff --git a/include/rapidjson/pointer.h b/include/rapidjson/pointer.h index 2d42412..b60e84b 100644 --- a/include/rapidjson/pointer.h +++ b/include/rapidjson/pointer.h @@ -42,61 +42,25 @@ public: SizeType index; //!< A valid index if not equal to kPointerInvalidIndex. }; - GenericPointer() : - allocator_(), - ownAllocator_(), - nameBuffer_(), - tokens_(), - tokenCount_(), - parseErrorOffset_(), - parseErrorCode_(kPointerParseErrorNone) - { - } + GenericPointer() : allocator_(), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {} - explicit GenericPointer(const Ch* source, Allocator* allocator = 0) : - allocator_(allocator), - ownAllocator_(), - nameBuffer_(), - tokens_(), - tokenCount_(), - parseErrorOffset_(), - parseErrorCode_(kPointerParseErrorNone) - { + explicit GenericPointer(const Ch* source, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) { Parse(source, internal::StrLen(source)); } - GenericPointer(const Ch* source, size_t length, Allocator* allocator = 0) : - allocator_(allocator), - ownAllocator_(), - nameBuffer_(), - tokens_(), - tokenCount_(), - parseErrorOffset_(), - parseErrorCode_(kPointerParseErrorNone) - { +#if RAPIDJSON_HAS_STDSTRING + explicit GenericPointer(const std::basic_string& source, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) { + Parse(source.c_str(), source.size()); + } +#endif + + GenericPointer(const Ch* source, size_t length, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) { Parse(source, length); } - GenericPointer(const Token* tokens, size_t tokenCount) : - allocator_(), - ownAllocator_(), - nameBuffer_(), - tokens_(const_cast(tokens)), - tokenCount_(tokenCount), - parseErrorOffset_(), - parseErrorCode_(kPointerParseErrorNone) - { - } + GenericPointer(const Token* tokens, size_t tokenCount) : allocator_(), ownAllocator_(), nameBuffer_(), tokens_(const_cast(tokens)), tokenCount_(tokenCount), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {} - GenericPointer(const GenericPointer& rhs) : - allocator_(), - ownAllocator_(), - nameBuffer_(), - tokens_(), - tokenCount_(), - parseErrorOffset_(), - parseErrorCode_(kPointerParseErrorNone) - { + GenericPointer(const GenericPointer& rhs) : allocator_(), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) { *this = rhs; } @@ -255,9 +219,7 @@ public: return v; } - const ValueType* Get(const ValueType& root) const { - return Get(const_cast(root)); - } + const ValueType* Get(const ValueType& root) const { return Get(const_cast(root)); } ValueType& GetWithDefault(ValueType& root, const ValueType& defaultValue, typename ValueType::AllocatorType& allocator) const { bool alreadyExist; @@ -284,6 +246,18 @@ public: return v; } +#if RAPIDJSON_HAS_STDSTRING + ValueType& GetWithDefault(ValueType& root, const std::basic_string& defaultValue, typename ValueType::AllocatorType& allocator) const { + bool alreadyExist; + Value& v = Create(root, allocator, &alreadyExist); + if (!alreadyExist) { + Value clone(defaultValue, allocator); // This has overhead, so do it inside if. + v = clone; + } + return v; + } +#endif + template RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (ValueType&)) GetWithDefault(ValueType& root, T defaultValue, typename ValueType::AllocatorType& allocator) const { @@ -306,6 +280,13 @@ public: return GetWithDefault(root, defaultValue, root.GetAllocator()); } +#if RAPIDJSON_HAS_STDSTRING + template + ValueType& GetWithDefault(GenericDocument& root, const std::basic_string& defaultValue) const { + return GetWithDefault(root, defaultValue, root.GetAllocator()); + } +#endif + template RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (ValueType&)) GetWithDefault(GenericDocument& root, T defaultValue) const { @@ -332,6 +313,13 @@ public: return Create(root, allocator) = v; } +#if RAPIDJSON_HAS_STDSTRING + ValueType& Set(ValueType& root, const std::basic_string& value, typename ValueType::AllocatorType& allocator) const { + ValueType v(value, allocator); + return Create(root, allocator) = v; + } +#endif + template RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (ValueType&)) Set(ValueType& root, T value, typename ValueType::AllocatorType& allocator) const { @@ -351,21 +339,25 @@ public: template ValueType& Set(GenericDocument& root, GenericStringRef value) const { - ValueType v(value); - return Create(root) = v; + return Create(root) = value; } template ValueType& Set(GenericDocument& root, const Ch* value) const { - ValueType v(value, root.GetAllocator()); - return Create(root) = v; + return Create(root) = ValueType(value, root.GetAllocator()).Move(); } +#if RAPIDJSON_HAS_STDSTRING + template + ValueType& Set(GenericDocument& root, const std::basic_string& value) const { + return Create(root) = ValueType(value, root.GetAllocator()).Move(); + } +#endif + template RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (ValueType&)) Set(GenericDocument& root, T value) const { - ValueType v(value); - return Create(root) = v; + return Create(root) = value; } // Create parents if non-exist @@ -628,8 +620,7 @@ typename T::ValueType& CreateValueByPointer(T& root, const GenericPointer typename T::ValueType& CreateValueByPointer(T& root, const CharType(&source)[N], typename T::AllocatorType& a) { - const GenericPointer pointer(source, N - 1); - return CreateValueByPointer(root, pointer, a); + return GenericPointer(source, N - 1).Create(root, a); } // No allocator parameter @@ -641,8 +632,7 @@ typename T::ValueType& CreateValueByPointer(T& root, const GenericPointer typename T::ValueType& CreateValueByPointer(T& root, const CharType(&source)[N]) { - const GenericPointer pointer(source, N - 1); - return CreateValueByPointer(root, pointer); + return GenericPointer(source, N - 1).Create(root); } ////////////////////////////////////////////////////////////////////////////// @@ -659,14 +649,12 @@ const typename T::ValueType* GetValueByPointer(const T& root, const GenericPoint template typename T::ValueType* GetValueByPointer(T& root, const CharType (&source)[N]) { - const GenericPointer pointer(source, N - 1); - return GetValueByPointer(root, pointer); + return GenericPointer(source, N - 1).Get(root); } template const typename T::ValueType* GetValueByPointer(const T& root, const CharType(&source)[N]) { - const GenericPointer pointer(source, N - 1); - return GetValueByPointer(root, pointer); + return GenericPointer(source, N - 1).Get(root); } ////////////////////////////////////////////////////////////////////////////// @@ -686,6 +674,13 @@ typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointe return pointer.GetWithDefault(root, defaultValue, a); } +#if RAPIDJSON_HAS_STDSTRING +template +typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer& pointer, const std::basic_string& defaultValue, typename T::AllocatorType& a) { + return pointer.GetWithDefault(root, defaultValue, a); +} +#endif + template RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename T::ValueType&)) GetValueByPointerWithDefault(T& root, const GenericPointer& pointer, T2 defaultValue, typename T::AllocatorType& a) { @@ -694,27 +689,30 @@ GetValueByPointerWithDefault(T& root, const GenericPointer typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const typename T::ValueType& defaultValue, typename T::AllocatorType& a) { - const GenericPointer pointer(source, N - 1); - return GetValueByPointerWithDefault(root, pointer, defaultValue, a); + return GenericPointer(source, N - 1).GetWithDefault(root, defaultValue, a); } template typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], GenericStringRef defaultValue, typename T::AllocatorType& a) { - const GenericPointer pointer(source, N - 1); - return GetValueByPointerWithDefault(root, pointer, defaultValue, a); + return GenericPointer(source, N - 1).GetWithDefault(root, defaultValue, a); } template typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const typename T::Ch* defaultValue, typename T::AllocatorType& a) { - const GenericPointer pointer(source, N - 1); - return GetValueByPointerWithDefault(root, pointer, defaultValue, a); + return GenericPointer(source, N - 1).GetWithDefault(root, defaultValue, a); } +#if RAPIDJSON_HAS_STDSTRING +template +typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const std::basic_string& defaultValue, typename T::AllocatorType& a) { + return GenericPointer(source, N - 1).GetWithDefault(root, defaultValue, a); +} +#endif + template RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename T::ValueType&)) GetValueByPointerWithDefault(T& root, const CharType(&source)[N], T2 defaultValue, typename T::AllocatorType& a) { - const GenericPointer pointer(source, N - 1); - return GetValueByPointerWithDefault(root, pointer, defaultValue, a); + return GenericPointer(source, N - 1).GetWithDefault(root, defaultValue, a); } // No allocator parameter @@ -734,6 +732,13 @@ typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointe return pointer.GetWithDefault(root, defaultValue); } +#if RAPIDJSON_HAS_STDSTRING +template +typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer& pointer, const std::basic_string& defaultValue) { + return pointer.GetWithDefault(root, defaultValue); +} +#endif + template RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename T::ValueType&)) GetValueByPointerWithDefault(T& root, const GenericPointer& pointer, T2 defaultValue) { @@ -742,27 +747,30 @@ GetValueByPointerWithDefault(T& root, const GenericPointer typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const typename T::ValueType& defaultValue) { - const GenericPointer pointer(source, N - 1); - return GetValueByPointerWithDefault(root, pointer, defaultValue); + return GenericPointer(source, N - 1).GetWithDefault(root, defaultValue); } template typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], GenericStringRef defaultValue) { - const GenericPointer pointer(source, N - 1); - return GetValueByPointerWithDefault(root, pointer, defaultValue); + return GenericPointer(source, N - 1).GetWithDefault(root, defaultValue); } template typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const typename T::Ch* defaultValue) { - const GenericPointer pointer(source, N - 1); - return GetValueByPointerWithDefault(root, pointer, defaultValue); + return GenericPointer(source, N - 1).GetWithDefault(root, defaultValue); } +#if RAPIDJSON_HAS_STDSTRING +template +typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const std::basic_string& defaultValue) { + return GenericPointer(source, N - 1).GetWithDefault(root, defaultValue); +} +#endif + template RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename T::ValueType&)) GetValueByPointerWithDefault(T& root, const CharType(&source)[N], T2 defaultValue) { - const GenericPointer pointer(source, N - 1); - return GetValueByPointerWithDefault(root, pointer, defaultValue); + return GenericPointer(source, N - 1).GetWithDefault(root, defaultValue); } ////////////////////////////////////////////////////////////////////////////// @@ -782,6 +790,13 @@ typename T::ValueType& SetValueByPointer(T& root, const GenericPointer +typename T::ValueType& SetValueByPointer(T& root, const GenericPointer& pointer, const std::basic_string& value, typename T::AllocatorType& a) { + return pointer.Set(root, value, a); +} +#endif + template RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename T::ValueType&)) SetValueByPointer(T& root, const GenericPointer& pointer, T2 value, typename T::AllocatorType& a) { @@ -790,27 +805,30 @@ SetValueByPointer(T& root, const GenericPointer& pointer, template typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], typename T::ValueType& value, typename T::AllocatorType& a) { - const GenericPointer pointer(source, N - 1); - return SetValueByPointer(root, pointer, value, a); + return GenericPointer(source, N - 1).Set(root, value, a); } template typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], GenericStringRef value, typename T::AllocatorType& a) { - const GenericPointer pointer(source, N - 1); - return SetValueByPointer(root, pointer, value, a); + return GenericPointer(source, N - 1).Set(root, value, a); } template typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const typename T::Ch* value, typename T::AllocatorType& a) { - const GenericPointer pointer(source, N - 1); - return SetValueByPointer(root, pointer, value, a); + return GenericPointer(source, N - 1).Set(root, value, a); } +#if RAPIDJSON_HAS_STDSTRING +template +typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const std::basic_string& value, typename T::AllocatorType& a) { + return GenericPointer(source, N - 1).Set(root, value, a); +} +#endif + template RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename T::ValueType&)) SetValueByPointer(T& root, const CharType(&source)[N], T2 value, typename T::AllocatorType& a) { - const GenericPointer pointer(source, N - 1); - return SetValueByPointer(root, pointer, value, a); + return GenericPointer(source, N - 1).Set(root, value, a); } // No allocator parameter @@ -830,6 +848,13 @@ typename T::ValueType& SetValueByPointer(T& root, const GenericPointer +typename T::ValueType& SetValueByPointer(T& root, const GenericPointer& pointer, const std::basic_string& value) { + return pointer.Set(root, value); +} +#endif + template RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename T::ValueType&)) SetValueByPointer(T& root, const GenericPointer& pointer, T2 value) { @@ -838,27 +863,30 @@ SetValueByPointer(T& root, const GenericPointer& pointer, template typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], typename T::ValueType& value) { - const GenericPointer pointer(source, N - 1); - return SetValueByPointer(root, pointer, value); + return GenericPointer(source, N - 1).Set(root, value); } template typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], GenericStringRef value) { - const GenericPointer pointer(source, N - 1); - return SetValueByPointer(root, pointer, value); + return GenericPointer(source, N - 1).Set(root, value); } template typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const typename T::Ch* value) { - const GenericPointer pointer(source, N - 1); - return SetValueByPointer(root, pointer, value); + return GenericPointer(source, N - 1).Set(root, value); } +#if RAPIDJSON_HAS_STDSTRING +template +typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const std::basic_string& value) { + return GenericPointer(source, N - 1).Set(root, value); +} +#endif + template RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename T::ValueType&)) SetValueByPointer(T& root, const CharType(&source)[N], T2 value) { - const GenericPointer pointer(source, N - 1); - return SetValueByPointer(root, pointer, value); + return GenericPointer(source, N - 1).Set(root, value); } ////////////////////////////////////////////////////////////////////////////// @@ -870,8 +898,7 @@ typename T::ValueType& SwapValueByPointer(T& root, const GenericPointer typename T::ValueType& SwapValueByPointer(T& root, const CharType(&source)[N], typename T::ValueType& value, typename T::AllocatorType& a) { - const GenericPointer pointer(source, N - 1); - return SwapValueByPointer(root, pointer, value, a); + return GenericPointer(source, N - 1).Swap(root, value, a); } template @@ -881,8 +908,7 @@ typename T::ValueType& SwapValueByPointer(T& root, const GenericPointer typename T::ValueType& SwapValueByPointer(T& root, const CharType(&source)[N], typename T::ValueType& value) { - const GenericPointer pointer(source, N - 1); - return SwapValueByPointer(root, pointer, value); + return GenericPointer(source, N - 1).Swap(root, value); } RAPIDJSON_NAMESPACE_END diff --git a/test/unittest/CMakeLists.txt b/test/unittest/CMakeLists.txt index 6a776ec..1ff88b1 100644 --- a/test/unittest/CMakeLists.txt +++ b/test/unittest/CMakeLists.txt @@ -22,6 +22,8 @@ elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") add_definitions(-D_CRT_SECURE_NO_WARNINGS=1) endif() +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DRAPIDJSON_HAS_STDSTRING=1") + add_library(namespacetest STATIC namespacetest.cpp) add_executable(unittest ${UNITTEST_SOURCES}) diff --git a/test/unittest/pointertest.cpp b/test/unittest/pointertest.cpp index 3a6742e..417893a 100644 --- a/test/unittest/pointertest.cpp +++ b/test/unittest/pointertest.cpp @@ -53,6 +53,16 @@ TEST(Pointer, Parse) { EXPECT_STREQ("foo", p.GetTokens()[0].name); } + #if RAPIDJSON_HAS_STDSTRING + { + Pointer p(std::string("/foo")); + EXPECT_TRUE(p.IsValid()); + EXPECT_EQ(1u, p.GetTokenCount()); + EXPECT_EQ(3u, p.GetTokens()[0].length); + EXPECT_STREQ("foo", p.GetTokens()[0].name); + } + #endif + { Pointer p("/foo/0"); EXPECT_TRUE(p.IsValid()); @@ -611,6 +621,10 @@ TEST(Pointer, GetWithDefault) { memset(buffer, 0, sizeof(buffer)); } EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString()); + +#if RAPIDJSON_HAS_STDSTRING + EXPECT_STREQ("C++", Pointer("/foo/C++").GetWithDefault(d, std::string("C++"), a).GetString()); +#endif } TEST(Pointer, GetWithDefault_NoAllocator) { @@ -659,6 +673,10 @@ TEST(Pointer, GetWithDefault_NoAllocator) { memset(buffer, 0, sizeof(buffer)); } EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString()); + +#if RAPIDJSON_HAS_STDSTRING + EXPECT_STREQ("C++", Pointer("/foo/C++").GetWithDefault(d, std::string("C++")).GetString()); +#endif } TEST(Pointer, Set) { @@ -709,6 +727,11 @@ TEST(Pointer, Set) { memset(buffer, 0, sizeof(buffer)); } EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString()); + +#if RAPIDJSON_HAS_STDSTRING + Pointer("/foo/c++").Set(d, std::string("C++"), a); + EXPECT_STREQ("C++", GetValueByPointer(d, "/foo/c++")->GetString()); +#endif } TEST(Pointer, Set_NoAllocator) { @@ -758,6 +781,11 @@ TEST(Pointer, Set_NoAllocator) { memset(buffer, 0, sizeof(buffer)); } EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString()); + +#if RAPIDJSON_HAS_STDSTRING + Pointer("/foo/c++").Set(d, std::string("C++")); + EXPECT_STREQ("C++", GetValueByPointer(d, "/foo/c++")->GetString()); +#endif } TEST(Pointer, Swap) { @@ -864,6 +892,10 @@ TEST(Pointer, GetValueByPointerWithDefault_Pointer) { memset(buffer, 0, sizeof(buffer)); } EXPECT_STREQ("World", GetValueByPointer(d, Pointer("/foo/world"))->GetString()); + +#if RAPIDJSON_HAS_STDSTRING + EXPECT_STREQ("C++", GetValueByPointerWithDefault(d, Pointer("/foo/C++"), std::string("C++"), a).GetString()); +#endif } TEST(Pointer, GetValueByPointerWithDefault_String) { @@ -913,6 +945,10 @@ TEST(Pointer, GetValueByPointerWithDefault_String) { memset(buffer, 0, sizeof(buffer)); } EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString()); + +#if RAPIDJSON_HAS_STDSTRING + EXPECT_STREQ("C++", GetValueByPointerWithDefault(d, "/foo/C++", std::string("C++"), a).GetString()); +#endif } TEST(Pointer, GetValueByPointerWithDefault_Pointer_NoAllocator) { @@ -961,6 +997,10 @@ TEST(Pointer, GetValueByPointerWithDefault_Pointer_NoAllocator) { memset(buffer, 0, sizeof(buffer)); } EXPECT_STREQ("World", GetValueByPointer(d, Pointer("/foo/world"))->GetString()); + +#if RAPIDJSON_HAS_STDSTRING + EXPECT_STREQ("C++", GetValueByPointerWithDefault(d, Pointer("/foo/C++"), std::string("C++")).GetString()); +#endif } TEST(Pointer, GetValueByPointerWithDefault_String_NoAllocator) { @@ -1009,6 +1049,10 @@ TEST(Pointer, GetValueByPointerWithDefault_String_NoAllocator) { memset(buffer, 0, sizeof(buffer)); } EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString()); + +#if RAPIDJSON_HAS_STDSTRING + EXPECT_STREQ("C++", GetValueByPointerWithDefault(d, Pointer("/foo/C++"), std::string("C++")).GetString()); +#endif } TEST(Pointer, SetValueByPointer_Pointer) { @@ -1056,6 +1100,11 @@ TEST(Pointer, SetValueByPointer_Pointer) { memset(buffer, 0, sizeof(buffer)); } EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString()); + +#if RAPIDJSON_HAS_STDSTRING + SetValueByPointer(d, Pointer("/foo/c++"), std::string("C++"), a); + EXPECT_STREQ("C++", GetValueByPointer(d, "/foo/c++")->GetString()); +#endif } TEST(Pointer, SetValueByPointer_String) { @@ -1103,6 +1152,11 @@ TEST(Pointer, SetValueByPointer_String) { memset(buffer, 0, sizeof(buffer)); } EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString()); + +#if RAPIDJSON_HAS_STDSTRING + SetValueByPointer(d, "/foo/c++", std::string("C++"), a); + EXPECT_STREQ("C++", GetValueByPointer(d, "/foo/c++")->GetString()); +#endif } TEST(Pointer, SetValueByPointer_Pointer_NoAllocator) { @@ -1149,6 +1203,11 @@ TEST(Pointer, SetValueByPointer_Pointer_NoAllocator) { memset(buffer, 0, sizeof(buffer)); } EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString()); + +#if RAPIDJSON_HAS_STDSTRING + SetValueByPointer(d, Pointer("/foo/c++"), std::string("C++")); + EXPECT_STREQ("C++", GetValueByPointer(d, "/foo/c++")->GetString()); +#endif } TEST(Pointer, SetValueByPointer_String_NoAllocator) { @@ -1195,6 +1254,11 @@ TEST(Pointer, SetValueByPointer_String_NoAllocator) { memset(buffer, 0, sizeof(buffer)); } EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString()); + +#if RAPIDJSON_HAS_STDSTRING + SetValueByPointer(d, "/foo/c++", std::string("C++")); + EXPECT_STREQ("C++", GetValueByPointer(d, "/foo/c++")->GetString()); +#endif } TEST(Pointer, SwapValueByPointer) { From 6582160a12717064b943b6903dd309324698e216 Mon Sep 17 00:00:00 2001 From: miloyip Date: Sun, 3 May 2015 19:14:58 +0800 Subject: [PATCH 049/189] Fix out-of-bound access in percent decode --- include/rapidjson/pointer.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/include/rapidjson/pointer.h b/include/rapidjson/pointer.h index b60e84b..cd685f0 100644 --- a/include/rapidjson/pointer.h +++ b/include/rapidjson/pointer.h @@ -425,7 +425,7 @@ private: if (uriFragment) { // Decoding percent-encoding for URI fragment if (c == '%') { - PercentDecodeStream is(&source[i]); + PercentDecodeStream is(&source[i], source + length); GenericInsituStringStream os(name); Ch* begin = os.PutBegin(); Transcoder, EncodingType> transcoder; @@ -551,10 +551,11 @@ private: class PercentDecodeStream { public: - PercentDecodeStream(const Ch* source) : src_(source), head_(source), valid_(true) {} + PercentDecodeStream(const Ch* source, const Ch* end) : src_(source), head_(source), end_(end), valid_(true) {} Ch Take() { - if (*src_ != '%') { + // %XX triplet + if (src_ + 3 > end_ || *src_ != '%') { valid_ = false; return 0; } @@ -582,6 +583,7 @@ private: private: const Ch* src_; //!< Current read position. const Ch* head_; //!< Original head of the string. + const Ch* end_; bool valid_; }; From f55002c9a2be6efdbe09fee9b2a94624f27d03a6 Mon Sep 17 00:00:00 2001 From: miloyip Date: Sun, 3 May 2015 19:27:12 +0800 Subject: [PATCH 050/189] Try to fix valgrind error --- test/unittest/pointertest.cpp | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/test/unittest/pointertest.cpp b/test/unittest/pointertest.cpp index 417893a..b58b346 100644 --- a/test/unittest/pointertest.cpp +++ b/test/unittest/pointertest.cpp @@ -295,22 +295,6 @@ TEST(Pointer, Parse_URIFragment) { EXPECT_STREQ("\xC2\xA2", p.GetTokens()[0].name); } - { - // Decode UTF-8 perecent encoding to UTF-16 - GenericPointer > > p(L"#/%C2%A2"); - EXPECT_TRUE(p.IsValid()); - EXPECT_EQ(1u, p.GetTokenCount()); - EXPECT_STREQ(L"\xA2", p.GetTokens()[0].name); - } - - { - // Decode UTF-8 perecent encoding to UTF-16 - GenericPointer > > p(L"#/%C2%A2"); - EXPECT_TRUE(p.IsValid()); - EXPECT_EQ(1u, p.GetTokenCount()); - EXPECT_STREQ(L"\xA2", p.GetTokens()[0].name); - } - { // Decode UTF-8 perecent encoding to UTF-16 GenericPointer > > p(L"#/%C2%A2"); From b55a9bcacbf0e00ea092c514b74252dc35a46ae3 Mon Sep 17 00:00:00 2001 From: miloyip Date: Sun, 3 May 2015 19:58:25 +0800 Subject: [PATCH 051/189] Try diagnosis Valgrind error --- test/unittest/pointertest.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/unittest/pointertest.cpp b/test/unittest/pointertest.cpp index b58b346..797aa8f 100644 --- a/test/unittest/pointertest.cpp +++ b/test/unittest/pointertest.cpp @@ -300,6 +300,7 @@ TEST(Pointer, Parse_URIFragment) { GenericPointer > > p(L"#/%C2%A2"); EXPECT_TRUE(p.IsValid()); EXPECT_EQ(1u, p.GetTokenCount()); + printf("%x %x %u\n", p.GetTokens()[0].name[0], p.GetTokens()[0].name[1], p.GetTokens()[0].length); EXPECT_STREQ(L"\x00A2", p.GetTokens()[0].name); } @@ -308,6 +309,7 @@ TEST(Pointer, Parse_URIFragment) { GenericPointer > > p(L"#/%E2%82%AC"); EXPECT_TRUE(p.IsValid()); EXPECT_EQ(1u, p.GetTokenCount()); + printf("%x %x %u\n", p.GetTokens()[0].name[0], p.GetTokens()[0].name[1], p.GetTokens()[0].length); EXPECT_STREQ(L"\x20AC", p.GetTokens()[0].name); } From 369cf2a8b7777b436310455e0406732e67482da1 Mon Sep 17 00:00:00 2001 From: miloyip Date: Sun, 3 May 2015 20:11:55 +0800 Subject: [PATCH 052/189] Fix wcscmp() causing false alarm in Valgrind --- test/unittest/pointertest.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/unittest/pointertest.cpp b/test/unittest/pointertest.cpp index 797aa8f..63ec084 100644 --- a/test/unittest/pointertest.cpp +++ b/test/unittest/pointertest.cpp @@ -300,8 +300,8 @@ TEST(Pointer, Parse_URIFragment) { GenericPointer > > p(L"#/%C2%A2"); EXPECT_TRUE(p.IsValid()); EXPECT_EQ(1u, p.GetTokenCount()); - printf("%x %x %u\n", p.GetTokens()[0].name[0], p.GetTokens()[0].name[1], p.GetTokens()[0].length); - EXPECT_STREQ(L"\x00A2", p.GetTokens()[0].name); + EXPECT_EQ(0x00A2, p.GetTokens()[0].name[0]); + EXPECT_EQ(1u, p.GetTokens()[0].length); } { @@ -309,8 +309,8 @@ TEST(Pointer, Parse_URIFragment) { GenericPointer > > p(L"#/%E2%82%AC"); EXPECT_TRUE(p.IsValid()); EXPECT_EQ(1u, p.GetTokenCount()); - printf("%x %x %u\n", p.GetTokens()[0].name[0], p.GetTokens()[0].name[1], p.GetTokens()[0].length); - EXPECT_STREQ(L"\x20AC", p.GetTokens()[0].name); + EXPECT_EQ(0x20AC, p.GetTokens()[0].name[0]); + EXPECT_EQ(1u, p.GetTokens()[0].length); } { From bfd47a70ed691ab5faada47e42e080dd9fce5b66 Mon Sep 17 00:00:00 2001 From: miloyip Date: Sun, 3 May 2015 20:30:46 +0800 Subject: [PATCH 053/189] Fix merge conflict --- test/unittest/CMakeLists.txt | 3 --- 1 file changed, 3 deletions(-) diff --git a/test/unittest/CMakeLists.txt b/test/unittest/CMakeLists.txt index 4ff95d6..fb95b8e 100644 --- a/test/unittest/CMakeLists.txt +++ b/test/unittest/CMakeLists.txt @@ -8,11 +8,8 @@ set(UNITTEST_SOURCES itoatest.cpp jsoncheckertest.cpp namespacetest.cpp -<<<<<<< HEAD pointertest.cpp -======= prettywritertest.cpp ->>>>>>> master readertest.cpp simdtest.cpp stringbuffertest.cpp From 3c73975513f4f3c0276d936e6684686eb2e40b88 Mon Sep 17 00:00:00 2001 From: miloyip Date: Sun, 3 May 2015 20:52:44 +0800 Subject: [PATCH 054/189] Fix 2 FILE* leaks in documenttest.cpp --- test/unittest/documenttest.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/unittest/documenttest.cpp b/test/unittest/documenttest.cpp index 71cd777..7e5d766 100644 --- a/test/unittest/documenttest.cpp +++ b/test/unittest/documenttest.cpp @@ -146,6 +146,7 @@ TEST(Document, ParseStream_EncodedInputStream) { StringBuffer bos2; Writer writer(bos2); reader.Parse(is, writer); + fclose(fp); EXPECT_EQ(bos.GetSize(), bos2.GetSize()); EXPECT_EQ(0, memcmp(bos.GetString(), bos2.GetString(), bos2.GetSize())); @@ -184,6 +185,7 @@ TEST(Document, ParseStream_AutoUTFInputStream) { StringBuffer bos2; Writer writer(bos2); reader.Parse(is, writer); + fclose(fp); EXPECT_EQ(bos.GetSize(), bos2.GetSize()); EXPECT_EQ(0, memcmp(bos.GetString(), bos2.GetString(), bos2.GetSize())); From ae61b7973cff48247ebd1a874e4f47270392e8ca Mon Sep 17 00:00:00 2001 From: miloyip Date: Sun, 3 May 2015 21:02:34 +0800 Subject: [PATCH 055/189] Standardize CrtAllocator::Realloc() for newSize = 0 --- include/rapidjson/allocators.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/include/rapidjson/allocators.h b/include/rapidjson/allocators.h index d68b74c..16bf038 100644 --- a/include/rapidjson/allocators.h +++ b/include/rapidjson/allocators.h @@ -68,7 +68,14 @@ public: else return NULL; // standardize to returning NULL. } - void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) { (void)originalSize; return std::realloc(originalPtr, newSize); } + void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) { + (void)originalSize; + if (newSize == 0) { + std::free(originalPtr); + return NULL; + } + return std::realloc(originalPtr, newSize); + } static void Free(void *ptr) { std::free(ptr); } }; From 1c98609adac2401a5916563fe3bb344913f82732 Mon Sep 17 00:00:00 2001 From: miloyip Date: Sun, 3 May 2015 21:23:13 +0800 Subject: [PATCH 056/189] Standardize MemoryPoolAllocator::Realloc() also, and improve coverage --- include/rapidjson/allocators.h | 3 +++ test/unittest/allocatorstest.cpp | 3 +++ 2 files changed, 6 insertions(+) diff --git a/include/rapidjson/allocators.h b/include/rapidjson/allocators.h index 16bf038..b7042a5 100644 --- a/include/rapidjson/allocators.h +++ b/include/rapidjson/allocators.h @@ -189,6 +189,9 @@ public: if (originalPtr == 0) return Malloc(newSize); + if (newSize == 0) + return NULL; + // Do not shrink if new size is smaller than original if (originalSize >= newSize) return originalPtr; diff --git a/test/unittest/allocatorstest.cpp b/test/unittest/allocatorstest.cpp index 3f33724..7b4deed 100644 --- a/test/unittest/allocatorstest.cpp +++ b/test/unittest/allocatorstest.cpp @@ -42,6 +42,9 @@ void TestAllocator(Allocator& a) { EXPECT_EQ(i, r[i]); Allocator::Free(r); + + // Realloc to zero size + EXPECT_TRUE(a.Realloc(a.Malloc(1), 1, 0) == 0); } TEST(Allocator, CrtAllocator) { From c35d47f83cff9d254d1aefb450c840f957cfad13 Mon Sep 17 00:00:00 2001 From: miloyip Date: Sun, 3 May 2015 21:37:12 +0800 Subject: [PATCH 057/189] Change copyright header of pointer test --- test/unittest/pointertest.cpp | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/test/unittest/pointertest.cpp b/test/unittest/pointertest.cpp index 63ec084..d74d75f 100644 --- a/test/unittest/pointertest.cpp +++ b/test/unittest/pointertest.cpp @@ -1,22 +1,16 @@ -// Copyright (C) 2011 Milo Yip +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. // -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at // -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. +// http://opensource.org/licenses/MIT // -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. #include "unittest.h" #include "rapidjson/pointer.h" From 524974deec46f437a2e46f490be556c802635774 Mon Sep 17 00:00:00 2001 From: miloyip Date: Sun, 3 May 2015 21:58:55 +0800 Subject: [PATCH 058/189] Add Validation of UTF-8 sequence for percent encoding, also improves coverage --- include/rapidjson/pointer.h | 4 ++-- test/unittest/pointertest.cpp | 27 +++++++++++++++++++++++---- 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/include/rapidjson/pointer.h b/include/rapidjson/pointer.h index cd685f0..7ba5174 100644 --- a/include/rapidjson/pointer.h +++ b/include/rapidjson/pointer.h @@ -429,7 +429,7 @@ private: GenericInsituStringStream os(name); Ch* begin = os.PutBegin(); Transcoder, EncodingType> transcoder; - if (!transcoder.Transcode(is, os) || !is.IsValid()) { + if (!transcoder.Validate(is, os) || !is.IsValid()) { parseErrorCode_ = kPointerParseErrorInvalidPercentEncoding; goto error; } @@ -538,7 +538,7 @@ private: GenericStringStream source(&t->name[j]); PercentEncodeStream target(os); Transcoder > transcoder; - if (!transcoder.Transcode(source, target)) + if (!transcoder.Validate(source, target)) return false; j += source.Tell() - 1; } diff --git a/test/unittest/pointertest.cpp b/test/unittest/pointertest.cpp index d74d75f..cc067e7 100644 --- a/test/unittest/pointertest.cpp +++ b/test/unittest/pointertest.cpp @@ -340,7 +340,7 @@ TEST(Pointer, Parse_URIFragment) { } { - // kPointerParseErrorInvalidPercentEncoding + // kPointerParseErrorInvalidPercentEncoding (invalid hex) Pointer p("#/%g0"); EXPECT_FALSE(p.IsValid()); EXPECT_EQ(kPointerParseErrorInvalidPercentEncoding, p.GetParseErrorCode()); @@ -348,13 +348,21 @@ TEST(Pointer, Parse_URIFragment) { } { - // kPointerParseErrorInvalidPercentEncoding + // kPointerParseErrorInvalidPercentEncoding (invalid hex) Pointer p("#/%0g"); EXPECT_FALSE(p.IsValid()); EXPECT_EQ(kPointerParseErrorInvalidPercentEncoding, p.GetParseErrorCode()); EXPECT_EQ(2u, p.GetParseErrorOffset()); } + { + // kPointerParseErrorInvalidPercentEncoding (incomplete UTF-8 sequence) + Pointer p("#/%C2"); + EXPECT_FALSE(p.IsValid()); + EXPECT_EQ(kPointerParseErrorInvalidPercentEncoding, p.GetParseErrorCode()); + EXPECT_EQ(2u, p.GetParseErrorOffset()); + } + { // kPointerParseErrorCharacterMustPercentEncode Pointer p("#/ "); @@ -395,16 +403,23 @@ TEST(Pointer, Stringify) { for (size_t i = 0; i < sizeof(sources) / sizeof(sources[0]); i++) { Pointer p(sources[i]); StringBuffer s; - p.Stringify(s); + EXPECT_TRUE(p.Stringify(s)); EXPECT_STREQ(sources[i], s.GetString()); // Stringify to URI fragment StringBuffer s2; - p.StringifyUriFragment(s2); + EXPECT_TRUE(p.StringifyUriFragment(s2)); Pointer p2(s2.GetString(), s2.GetSize()); EXPECT_TRUE(p2.IsValid()); EXPECT_TRUE(p == p2); } + + { + // Strigify to URI fragment with an invalid UTF-8 sequence + Pointer p("/\xC2"); + StringBuffer s; + EXPECT_FALSE(p.StringifyUriFragment(s)); + } } // Construct a Pointer with static tokens, no dynamic allocation involved. @@ -552,6 +567,10 @@ TEST(Pointer, Get) { EXPECT_EQ(&d[" "], Pointer("/ ").Get(d)); EXPECT_EQ(&d["m~n"], Pointer("/m~0n").Get(d)); EXPECT_TRUE(Pointer("/abc").Get(d) == 0); + EXPECT_TRUE(Pointer("/foo/2").Get(d) == 0); // Out of boundary + EXPECT_TRUE(Pointer("/foo/a").Get(d) == 0); // "/foo" is an array, cannot query by "a" + EXPECT_TRUE(Pointer("/foo/0/0").Get(d) == 0); // "/foo/0" is an string, cannot further query + EXPECT_TRUE(Pointer("/foo/0/a").Get(d) == 0); // "/foo/0" is an string, cannot further query } TEST(Pointer, GetWithDefault) { From 45bed001ee8b56953f4e59f719302d8f2a5d424f Mon Sep 17 00:00:00 2001 From: miloyip Date: Sun, 3 May 2015 23:44:58 +0800 Subject: [PATCH 059/189] Remove unusable StringRef overloads --- include/rapidjson/pointer.h | 60 ------------------------------------- 1 file changed, 60 deletions(-) diff --git a/include/rapidjson/pointer.h b/include/rapidjson/pointer.h index 7ba5174..635601d 100644 --- a/include/rapidjson/pointer.h +++ b/include/rapidjson/pointer.h @@ -231,11 +231,6 @@ public: return v; } - ValueType& GetWithDefault(ValueType& root, GenericStringRef defaultValue, typename ValueType::AllocatorType& allocator) const { - ValueType v(defaultValue); - return GetWithDefault(root, v, allocator); - } - ValueType& GetWithDefault(ValueType& root, const Ch* defaultValue, typename ValueType::AllocatorType& allocator) const { bool alreadyExist; Value& v = Create(root, allocator, &alreadyExist); @@ -270,11 +265,6 @@ public: return GetWithDefault(root, defaultValue, root.GetAllocator()); } - template - ValueType& GetWithDefault(GenericDocument& root, GenericStringRef defaultValue) const { - return GetWithDefault(root, defaultValue, root.GetAllocator()); - } - template ValueType& GetWithDefault(GenericDocument& root, const Ch* defaultValue) const { return GetWithDefault(root, defaultValue, root.GetAllocator()); @@ -303,11 +293,6 @@ public: return Create(root, allocator).CopyFrom(value, allocator); } - ValueType& Set(ValueType& root, GenericStringRef value, typename ValueType::AllocatorType& allocator) const { - ValueType v(value); - return Create(root, allocator) = v; - } - ValueType& Set(ValueType& root, const Ch* value, typename ValueType::AllocatorType& allocator) const { ValueType v(value, allocator); return Create(root, allocator) = v; @@ -337,11 +322,6 @@ public: return Create(root).CopyFrom(value, root.GetAllocator()); } - template - ValueType& Set(GenericDocument& root, GenericStringRef value) const { - return Create(root) = value; - } - template ValueType& Set(GenericDocument& root, const Ch* value) const { return Create(root) = ValueType(value, root.GetAllocator()).Move(); @@ -666,11 +646,6 @@ typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointe return pointer.GetWithDefault(root, defaultValue, a); } -template -typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer& pointer, GenericStringRef defaultValue, typename T::AllocatorType& a) { - return pointer.GetWithDefault(root, defaultValue, a); -} - template typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer& pointer, const typename T::Ch* defaultValue, typename T::AllocatorType& a) { return pointer.GetWithDefault(root, defaultValue, a); @@ -694,11 +669,6 @@ typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&sou return GenericPointer(source, N - 1).GetWithDefault(root, defaultValue, a); } -template -typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], GenericStringRef defaultValue, typename T::AllocatorType& a) { - return GenericPointer(source, N - 1).GetWithDefault(root, defaultValue, a); -} - template typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const typename T::Ch* defaultValue, typename T::AllocatorType& a) { return GenericPointer(source, N - 1).GetWithDefault(root, defaultValue, a); @@ -724,11 +694,6 @@ typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointe return pointer.GetWithDefault(root, defaultValue); } -template -typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer& pointer, GenericStringRef defaultValue) { - return pointer.GetWithDefault(root, defaultValue); -} - template typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer& pointer, const typename T::Ch* defaultValue) { return pointer.GetWithDefault(root, defaultValue); @@ -752,11 +717,6 @@ typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&sou return GenericPointer(source, N - 1).GetWithDefault(root, defaultValue); } -template -typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], GenericStringRef defaultValue) { - return GenericPointer(source, N - 1).GetWithDefault(root, defaultValue); -} - template typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const typename T::Ch* defaultValue) { return GenericPointer(source, N - 1).GetWithDefault(root, defaultValue); @@ -782,11 +742,6 @@ typename T::ValueType& SetValueByPointer(T& root, const GenericPointer -typename T::ValueType& SetValueByPointer(T& root, const GenericPointer& pointer, GenericStringRef value, typename T::AllocatorType& a) { - return pointer.Set(root, value, a); -} - template typename T::ValueType& SetValueByPointer(T& root, const GenericPointer& pointer, const typename T::Ch* value, typename T::AllocatorType& a) { return pointer.Set(root, value, a); @@ -810,11 +765,6 @@ typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], ty return GenericPointer(source, N - 1).Set(root, value, a); } -template -typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], GenericStringRef value, typename T::AllocatorType& a) { - return GenericPointer(source, N - 1).Set(root, value, a); -} - template typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const typename T::Ch* value, typename T::AllocatorType& a) { return GenericPointer(source, N - 1).Set(root, value, a); @@ -840,11 +790,6 @@ typename T::ValueType& SetValueByPointer(T& root, const GenericPointer -typename T::ValueType& SetValueByPointer(T& root, const GenericPointer& pointer, GenericStringRef value) { - return pointer.Set(root, value); -} - template typename T::ValueType& SetValueByPointer(T& root, const GenericPointer& pointer, const typename T::Ch* value) { return pointer.Set(root, value); @@ -868,11 +813,6 @@ typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], ty return GenericPointer(source, N - 1).Set(root, value); } -template -typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], GenericStringRef value) { - return GenericPointer(source, N - 1).Set(root, value); -} - template typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const typename T::Ch* value) { return GenericPointer(source, N - 1).Set(root, value); From fc7b0a04a1703f142bba03090496ea2a8e96bbb2 Mon Sep 17 00:00:00 2001 From: miloyip Date: Mon, 4 May 2015 10:06:31 +0800 Subject: [PATCH 060/189] Add const Value& version of SetValueByPointer() and improve coverage --- include/rapidjson/pointer.h | 20 ++++++++++++++++++++ test/unittest/pointertest.cpp | 30 ++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/include/rapidjson/pointer.h b/include/rapidjson/pointer.h index 635601d..d54676e 100644 --- a/include/rapidjson/pointer.h +++ b/include/rapidjson/pointer.h @@ -742,6 +742,11 @@ typename T::ValueType& SetValueByPointer(T& root, const GenericPointer +typename T::ValueType& SetValueByPointer(T& root, const GenericPointer& pointer, const typename T::ValueType& value, typename T::AllocatorType& a) { + return pointer.Set(root, value, a); +} + template typename T::ValueType& SetValueByPointer(T& root, const GenericPointer& pointer, const typename T::Ch* value, typename T::AllocatorType& a) { return pointer.Set(root, value, a); @@ -765,6 +770,11 @@ typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], ty return GenericPointer(source, N - 1).Set(root, value, a); } +template +typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const typename T::ValueType& value, typename T::AllocatorType& a) { + return GenericPointer(source, N - 1).Set(root, value, a); +} + template typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const typename T::Ch* value, typename T::AllocatorType& a) { return GenericPointer(source, N - 1).Set(root, value, a); @@ -790,6 +800,11 @@ typename T::ValueType& SetValueByPointer(T& root, const GenericPointer +typename T::ValueType& SetValueByPointer(T& root, const GenericPointer& pointer, const typename T::ValueType& value) { + return pointer.Set(root, value); +} + template typename T::ValueType& SetValueByPointer(T& root, const GenericPointer& pointer, const typename T::Ch* value) { return pointer.Set(root, value); @@ -813,6 +828,11 @@ typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], ty return GenericPointer(source, N - 1).Set(root, value); } +template +typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const typename T::ValueType& value) { + return GenericPointer(source, N - 1).Set(root, value); +} + template typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const typename T::Ch* value) { return GenericPointer(source, N - 1).Set(root, value); diff --git a/test/unittest/pointertest.cpp b/test/unittest/pointertest.cpp index cc067e7..004fa22 100644 --- a/test/unittest/pointertest.cpp +++ b/test/unittest/pointertest.cpp @@ -693,6 +693,11 @@ TEST(Pointer, Set) { Pointer("/foo/null").Set(d, Value().Move(), a); EXPECT_TRUE(GetValueByPointer(d, "/foo/null")->IsNull()); + // Const Value version + const Value foo(d["foo"], a); + Pointer("/clone").Set(d, foo, a); + EXPECT_EQ(foo, *GetValueByPointer(d, "/clone")); + // Generic version Pointer("/foo/int").Set(d, -1, a); EXPECT_EQ(-1, GetValueByPointer(d, "/foo/int")->GetInt()); @@ -747,6 +752,11 @@ TEST(Pointer, Set_NoAllocator) { Pointer("/foo/null").Set(d, Value().Move()); EXPECT_TRUE(GetValueByPointer(d, "/foo/null")->IsNull()); + // Const Value version + const Value foo(d["foo"], d.GetAllocator()); + Pointer("/clone").Set(d, foo); + EXPECT_EQ(foo, *GetValueByPointer(d, "/clone")); + // Generic version Pointer("/foo/int").Set(d, -1); EXPECT_EQ(-1, GetValueByPointer(d, "/foo/int")->GetInt()); @@ -1066,6 +1076,11 @@ TEST(Pointer, SetValueByPointer_Pointer) { SetValueByPointer(d, Pointer("/foo/null"), Value().Move(), a); EXPECT_TRUE(GetValueByPointer(d, "/foo/null")->IsNull()); + // Const Value version + const Value foo(d["foo"], d.GetAllocator()); + SetValueByPointer(d, Pointer("/clone"), foo, a); + EXPECT_EQ(foo, *GetValueByPointer(d, "/clone")); + // Generic version SetValueByPointer(d, Pointer("/foo/int"), -1, a); EXPECT_EQ(-1, GetValueByPointer(d, "/foo/int")->GetInt()); @@ -1118,6 +1133,11 @@ TEST(Pointer, SetValueByPointer_String) { SetValueByPointer(d, "/foo/null", Value().Move(), a); EXPECT_TRUE(GetValueByPointer(d, "/foo/null")->IsNull()); + // Const Value version + const Value foo(d["foo"], d.GetAllocator()); + SetValueByPointer(d, "/clone", foo, a); + EXPECT_EQ(foo, *GetValueByPointer(d, "/clone")); + // Generic version SetValueByPointer(d, "/foo/int", -1, a); EXPECT_EQ(-1, GetValueByPointer(d, "/foo/int")->GetInt()); @@ -1169,6 +1189,11 @@ TEST(Pointer, SetValueByPointer_Pointer_NoAllocator) { SetValueByPointer(d, Pointer("/foo/null"), Value().Move()); EXPECT_TRUE(GetValueByPointer(d, "/foo/null")->IsNull()); + // Const Value version + const Value foo(d["foo"], d.GetAllocator()); + SetValueByPointer(d, Pointer("/clone"), foo); + EXPECT_EQ(foo, *GetValueByPointer(d, "/clone")); + // Generic version SetValueByPointer(d, Pointer("/foo/int"), -1); EXPECT_EQ(-1, GetValueByPointer(d, "/foo/int")->GetInt()); @@ -1220,6 +1245,11 @@ TEST(Pointer, SetValueByPointer_String_NoAllocator) { SetValueByPointer(d, "/foo/null", Value().Move()); EXPECT_TRUE(GetValueByPointer(d, "/foo/null")->IsNull()); + // Const Value version + const Value foo(d["foo"], d.GetAllocator()); + SetValueByPointer(d, "/clone", foo); + EXPECT_EQ(foo, *GetValueByPointer(d, "/clone")); + // Generic version SetValueByPointer(d, "/foo/int", -1); EXPECT_EQ(-1, GetValueByPointer(d, "/foo/int")->GetInt()); From 1135ef662274db5598b0b33b168914b4d97b623d Mon Sep 17 00:00:00 2001 From: miloyip Date: Mon, 4 May 2015 10:08:23 +0800 Subject: [PATCH 061/189] Fix VC2013 false alarm warning --- include/rapidjson/pointer.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/include/rapidjson/pointer.h b/include/rapidjson/pointer.h index d54676e..fc65496 100644 --- a/include/rapidjson/pointer.h +++ b/include/rapidjson/pointer.h @@ -408,8 +408,7 @@ private: PercentDecodeStream is(&source[i], source + length); GenericInsituStringStream os(name); Ch* begin = os.PutBegin(); - Transcoder, EncodingType> transcoder; - if (!transcoder.Validate(is, os) || !is.IsValid()) { + if (!Transcoder, EncodingType>().Validate(is, os) || !is.IsValid()) { parseErrorCode_ = kPointerParseErrorInvalidPercentEncoding; goto error; } @@ -517,8 +516,7 @@ private: // Transcode to UTF8 sequence GenericStringStream source(&t->name[j]); PercentEncodeStream target(os); - Transcoder > transcoder; - if (!transcoder.Validate(source, target)) + if (!Transcoder >().Validate(source, target)) return false; j += source.Tell() - 1; } From e7bcedb4f4d3383f29f69a0e711053754338c52c Mon Sep 17 00:00:00 2001 From: miloyip Date: Mon, 4 May 2015 10:21:30 +0800 Subject: [PATCH 062/189] Simplify code --- include/rapidjson/pointer.h | 40 ++++++++++--------------------------- 1 file changed, 11 insertions(+), 29 deletions(-) diff --git a/include/rapidjson/pointer.h b/include/rapidjson/pointer.h index fc65496..fbd70ad 100644 --- a/include/rapidjson/pointer.h +++ b/include/rapidjson/pointer.h @@ -224,40 +224,27 @@ public: ValueType& GetWithDefault(ValueType& root, const ValueType& defaultValue, typename ValueType::AllocatorType& allocator) const { bool alreadyExist; Value& v = Create(root, allocator, &alreadyExist); - if (!alreadyExist) { - Value clone(defaultValue, allocator); - v = clone; - } - return v; + return alreadyExist ? v : v.CopyFrom(defaultValue, allocator); } ValueType& GetWithDefault(ValueType& root, const Ch* defaultValue, typename ValueType::AllocatorType& allocator) const { bool alreadyExist; Value& v = Create(root, allocator, &alreadyExist); - if (!alreadyExist) { - Value clone(defaultValue, allocator); // This has overhead, so do it inside if. - v = clone; - } - return v; + return alreadyExist ? v : v.SetString(defaultValue, allocator); } #if RAPIDJSON_HAS_STDSTRING ValueType& GetWithDefault(ValueType& root, const std::basic_string& defaultValue, typename ValueType::AllocatorType& allocator) const { bool alreadyExist; Value& v = Create(root, allocator, &alreadyExist); - if (!alreadyExist) { - Value clone(defaultValue, allocator); // This has overhead, so do it inside if. - v = clone; - } - return v; + return alreadyExist ? v : v.SetString(defaultValue, allocator); } #endif template RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (ValueType&)) GetWithDefault(ValueType& root, T defaultValue, typename ValueType::AllocatorType& allocator) const { - ValueType v(defaultValue); - return GetWithDefault(root, v, allocator); + return GetWithDefault(root, ValueType(defaultValue).Move(), allocator); } template @@ -294,22 +281,19 @@ public: } ValueType& Set(ValueType& root, const Ch* value, typename ValueType::AllocatorType& allocator) const { - ValueType v(value, allocator); - return Create(root, allocator) = v; + return Create(root, allocator) = ValueType(value, allocator).Move(); } #if RAPIDJSON_HAS_STDSTRING ValueType& Set(ValueType& root, const std::basic_string& value, typename ValueType::AllocatorType& allocator) const { - ValueType v(value, allocator); - return Create(root, allocator) = v; + return Create(root, allocator) = ValueType(value, allocator).Move(); } #endif template RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (ValueType&)) Set(ValueType& root, T value, typename ValueType::AllocatorType& allocator) const { - ValueType v(value); - return Create(root, allocator) = v; + return Create(root, allocator) = ValueType(value).Move(); } template @@ -363,20 +347,19 @@ private: \note Source cannot be JSON String Representation of JSON Pointer, e.g. In "/\u0000", \u0000 will not be unescaped. */ void Parse(const Ch* source, size_t length) { + RAPIDJSON_ASSERT(source != NULL); + RAPIDJSON_ASSERT(nameBuffer_ == 0); + RAPIDJSON_ASSERT(tokens_ == 0); + // Create own allocator if user did not supply. if (!allocator_) ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator()); // Create a buffer as same size of source - RAPIDJSON_ASSERT(nameBuffer_ == 0); nameBuffer_ = (Ch*)allocator_->Malloc(length * sizeof(Ch)); - - RAPIDJSON_ASSERT(tokens_ == 0); tokens_ = (Token*)allocator_->Malloc(length * sizeof(Token)); // Maximum possible tokens in the source - tokenCount_ = 0; Ch* name = nameBuffer_; - size_t i = 0; // Detect if it is a URI fragment @@ -401,7 +384,6 @@ private: while (i < length && source[i] != '/') { Ch c = source[i]; - if (uriFragment) { // Decoding percent-encoding for URI fragment if (c == '%') { From 56568fd73f28fe19ece89daae3883d214d888b5d Mon Sep 17 00:00:00 2001 From: miloyip Date: Mon, 4 May 2015 10:25:31 +0800 Subject: [PATCH 063/189] Add GenericValue::ValueType and fix warning for SetString(std::string, Allocator) --- include/rapidjson/document.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/rapidjson/document.h b/include/rapidjson/document.h index a649768..7386773 100644 --- a/include/rapidjson/document.h +++ b/include/rapidjson/document.h @@ -427,6 +427,7 @@ public: typedef typename GenericMemberIterator::Iterator ConstMemberIterator; //!< Constant member iterator for iterating in object. typedef GenericValue* ValueIterator; //!< Value iterator for iterating in array. typedef const GenericValue* ConstValueIterator; //!< Constant value iterator for iterating in array. + typedef GenericValue ValueType; //!< Value type of itself. //!@name Constructors and destructor. //@{ @@ -1417,7 +1418,7 @@ public: \post IsString() == true && GetString() != s.data() && strcmp(GetString(),s.data() == 0 && GetStringLength() == s.size() \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING. */ - GenericValue& SetString(const std::basic_string& s, Allocator& allocator) { return SetString(s.data(), s.size(), allocator); } + GenericValue& SetString(const std::basic_string& s, Allocator& allocator) { return SetString(s.data(), SizeType(s.size()), allocator); } #endif //@} From b6a54f724480831f397938740d14e5d3d76ad6cb Mon Sep 17 00:00:00 2001 From: miloyip Date: Mon, 4 May 2015 13:32:44 +0800 Subject: [PATCH 064/189] Add API doc for GenericPointer, rename some (template) parameters --- include/rapidjson/pointer.h | 530 +++++++++++++++++++++++++++--------- 1 file changed, 405 insertions(+), 125 deletions(-) diff --git a/include/rapidjson/pointer.h b/include/rapidjson/pointer.h index fbd70ad..3ba9e1c 100644 --- a/include/rapidjson/pointer.h +++ b/include/rapidjson/pointer.h @@ -19,59 +19,155 @@ RAPIDJSON_NAMESPACE_BEGIN -static const SizeType kPointerInvalidIndex = ~SizeType(0); +static const SizeType kPointerInvalidIndex = ~SizeType(0); //!< Represents an invalid index in GenericPointer::Token +//! Error code of parsing. +/*! \ingroup RAPIDJSON_ERRORS + \see GenericPointer::GenericPointer, GenericPointer::GetParseErrorCode +*/ enum PointerParseErrorCode { - kPointerParseErrorNone = 0, + kPointerParseErrorNone = 0, //!< The parse is successful - kPointerParseErrorTokenMustBeginWithSolidus, - kPointerParseErrorInvalidEscape, - kPointerParseErrorInvalidPercentEncoding, - kPointerParseErrorCharacterMustPercentEncode + kPointerParseErrorTokenMustBeginWithSolidus, //!< A token must begin with a '/' + kPointerParseErrorInvalidEscape, //!< Invalid escape + kPointerParseErrorInvalidPercentEncoding, //!< Invalid percent encoding in URI fragment + kPointerParseErrorCharacterMustPercentEncode //!< A character must percent encoded in URI fragment }; +/////////////////////////////////////////////////////////////////////////////// +// GenericPointer + +//! Represents a JSON Pointer. Use Pointer for UTF8 encoding and default allocator. +/*! + This class implements RFC 6901 "JavaScript Object Notation (JSON) Pointer" + (https://tools.ietf.org/html/rfc6901). + + A JSON pointer is for identifying a specific value in a JSON document + (GenericDocument). It can simplify coding of DOM tree manipulation, because it + can access multiple-level depth of DOM tree with single API call. + + After it parses a string representation (e.g. "/foo/0" or URI fragment + representation (e.g. "#/foo/0") into its internal representation (tokens), + it can be used to resolve a specific value in multiple documents, or sub-tree + of documents. + + Contrary to GenericValue, Pointer can be copy constructed and copy assigned. + Apart from assignment, a Pointer cannot be modified after construction. + + Although Pointer is very convenient, please aware that constructing Pointer + involves parsing and dynamic memory allocation. A special constructor with user- + supplied tokens eliminates these. + + GenericPointer depends on GenericDocument and GenericValue. + + \tparam ValueType The value type of the DOM tree. E.g. GenericValue > + \tparam Allocator The allocator type for allocating memory for internal representation. + + \note GenericPointer uses same encoding of ValueType. + However, Allocator of GenericPointer is independent of Allocator of Value. +*/ template class GenericPointer { public: - typedef typename ValueType::EncodingType EncodingType; - typedef typename EncodingType::Ch Ch; + typedef typename ValueType::EncodingType EncodingType; //!< Encoding type from Value + typedef typename EncodingType::Ch Ch; //!< Character type from Value + //! A token is the basic units of internal representation. + /*! + A JSON pointer string representation "/foo/123" is parsed to two tokens: + "foo" and 123. 123 will be represented in both numeric form and string form. + They are resolved according to the actual value type (object or array). + + For token that are not numbers, or the numeric value is out of bound + (greater than limits of SizeType), they are only treated as string form + (i.e. the token's index will be equal to kPointerInvalidIndex). + + This struct is public so that user can create a Pointer without parsing and + allocation, using a special constructor. + */ struct Token { - const Ch* name; - SizeType length; - SizeType index; //!< A valid index if not equal to kPointerInvalidIndex. + const Ch* name; //!< Name of the token. It has null character at the end but it can contain null character. + SizeType length; //!< Length of the name. + SizeType index; //!< A valid array index, if it is not equal to kPointerInvalidIndex. }; + //!@name Constructors and destructor. + //@{ + + //! Default constructor. GenericPointer() : allocator_(), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {} + //! Constructor that parses a string or URI fragment representation. + /*! + \param source A null-terminated, string or URI fragment representation of JSON pointer. + \param allocator User supplied allocator for this pointer. If no allocator is provided, it creates a self-owned one. + */ explicit GenericPointer(const Ch* source, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) { Parse(source, internal::StrLen(source)); } #if RAPIDJSON_HAS_STDSTRING + //! Constructor that parses a string or URI fragment representation. + /*! + \param source A string or URI fragment representation of JSON pointer. + \param allocator User supplied allocator for this pointer. If no allocator is provided, it creates a self-owned one. + \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING. + */ explicit GenericPointer(const std::basic_string& source, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) { Parse(source.c_str(), source.size()); } #endif + //! Constructor that parses a string or URI fragment representation, with length of the source string. + /*! + \param source A string or URI fragment representation of JSON pointer. + \param length Length of source. + \param allocator User supplied allocator for this pointer. If no allocator is provided, it creates a self-owned one. + \note Slightly faster than the overload without length. + */ GenericPointer(const Ch* source, size_t length, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) { Parse(source, length); } + //! Constructor with user-supplied tokens. + /*! + This constructor let user supplies const array of tokens. + This prevents the parsing process and eliminates allocation. + This is preferred for memory constrained environments. + + \param tokens An constant array of tokens representing the JSON pointer. + \param tokenCount Number of tokens. + + \b Example + \code + #define NAME(s) { s, sizeof(s) / sizeof(s[0]) - 1, kPointerInvalidIndex } + #define INDEX(i) { #i, sizeof(#i) - 1, i } + + static const Pointer::Token kTokens[] = { NAME("foo"), INDEX(123) }; + static const Pointer p(kTokens, sizeof(kTokens) / sizeof(kTokens[0])); + // Equivalent to static const Pointer p("/foo/123"); + + #undef NAME + #undef INDEX + \endcode + */ GenericPointer(const Token* tokens, size_t tokenCount) : allocator_(), ownAllocator_(), nameBuffer_(), tokens_(const_cast(tokens)), tokenCount_(tokenCount), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {} + //! Copy constructor. GenericPointer(const GenericPointer& rhs) : allocator_(), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) { *this = rhs; } + //! Destructor. ~GenericPointer() { - if (nameBuffer_) { + if (nameBuffer_) { // If user-supplied tokens constructor is used, nameBuffer_ is nullptr and tokens_ are not deallocated. Allocator::Free(nameBuffer_); Allocator::Free(tokens_); } RAPIDJSON_DELETE(ownAllocator_); } + //! Assignment operator. GenericPointer& operator=(const GenericPointer& rhs) { this->~GenericPointer(); @@ -79,11 +175,11 @@ public: parseErrorOffset_ = rhs.parseErrorOffset_; parseErrorCode_ = rhs.parseErrorCode_; - if (rhs.nameBuffer_) { - if (!allocator_) + if (rhs.nameBuffer_) { // Normally parsed tokens. + if (!allocator_) // allocator is independently owned. ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator()); - size_t nameBufferSize = tokenCount_; // null terminators + size_t nameBufferSize = tokenCount_; // null terminators for tokens for (Token *t = rhs.tokens_; t != rhs.tokens_ + tokenCount_; ++t) nameBufferSize += t->length; nameBuffer_ = (Ch*)allocator_->Malloc(nameBufferSize * sizeof(Ch)); @@ -98,21 +194,45 @@ public: t->name += diff; } else - tokens_ = rhs.tokens_; + tokens_ = rhs.tokens_; // User supplied const tokens. return *this; } + //@} + + //!@name Handling Parse Error + //@{ + + //! Check whether this is a valid pointer. bool IsValid() const { return parseErrorCode_ == kPointerParseErrorNone; } + //! Get the parsing error offset in code unit. size_t GetParseErrorOffset() const { return parseErrorOffset_; } + //! Get the parsing error code. PointerParseErrorCode GetParseErrorCode() const { return parseErrorCode_; } + //@} + + //!@name Tokens + //@{ + + //! Get the token array (const version only). const Token* GetTokens() const { return tokens_; } + //! Get the number of tokens. size_t GetTokenCount() const { return tokenCount_; } + //@} + + //!@name Equality/inequality operators + //@{ + + //! Equality operator. + /*! + \note When any pointers are invalid, always returns false. + */ bool operator==(const GenericPointer& rhs) const { if (!IsValid() || !rhs.IsValid() || tokenCount_ != rhs.tokenCount_) return false; @@ -129,18 +249,57 @@ public: return true; } + //! Inequality operator. + /*! + \note When any pointers are invalid, always returns true. + */ bool operator!=(const GenericPointer& rhs) const { return !(*this == rhs); } + //@} + + //!@name Stringify + //@{ + + //! Stringify the pointer into string representation. + /*! + \tparam OutputStream Type of output stream. + \param os The output stream. + */ template bool Stringify(OutputStream& os) const { return Stringify(os); } + //! Stringify the pointer into URI fragment representation. + /*! + \tparam OutputStream Type of output stream. + \param os The output stream. + */ template bool StringifyUriFragment(OutputStream& os) const { return Stringify(os); } - + + //@} + + //!@name Create value + //@{ + + //! Create a value in a subtree. + /*! + If the value is not exist, it creates all parent values and a JSON Null value. + So it always succeed and return the newly created or existing value. + + Remind that it may change types of parents according to tokens, so it + potentially removes previously stored values. For example, if a document + was an array, and "/foo" is used to create a value, then the document + will be changed to an object, and all existing array elements are lost. + + \param root Root value of a DOM subtree to be resolved. It can be any value other than document root. + \param allocator Allocator for creating the values if the specified value or its parents are not exist. + \param alreadyExist If non-null, it stores whether the resolved value is already exist. + \return The resolved newly created (a JSON Null value), or already exists value. + */ ValueType& Create(ValueType& root, typename ValueType::AllocatorType& allocator, bool* alreadyExist = 0) const { RAPIDJSON_ASSERT(IsValid()); ValueType* v = &root; @@ -189,11 +348,28 @@ public: return *v; } + //! Creates a value in a document. + /*! + \param document A document to be resolved. + \param allocator Allocator for creating the values if the specified value or its parents are not exist. + \param alreadyExist If non-null, it stores whether the resolved value is already exist. + \return The resolved newly created, or already exists value. + */ template - ValueType& Create(GenericDocument& root, bool* alreadyExist = 0) const { - return Create(root, root.GetAllocator(), alreadyExist); + ValueType& Create(GenericDocument& document, bool* alreadyExist = 0) const { + return Create(document, document.GetAllocator(), alreadyExist); } + //@} + + //!@name Query value + //@{ + + //! Query a value in a subtree. + /*! + \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root. + \return Pointer to the value if it can be resolved. Otherwise null. + */ ValueType* Get(ValueType& root) const { RAPIDJSON_ASSERT(IsValid()); ValueType* v = &root; @@ -219,14 +395,35 @@ public: return v; } + //! Query a const value in a const subtree. + /*! + \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root. + \return Pointer to the value if it can be resolved. Otherwise null. + */ const ValueType* Get(const ValueType& root) const { return Get(const_cast(root)); } + //@} + + //!@name Query a value with default + //@{ + + //! Query a value in a subtree with default value. + /*! + Similar to Get(), but if the specified value do not exists, it creates all parents and clone the default value. + So that this function always succeed. + + \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root. + \param defaultValue Default value to be cloned if the value was not exists. + \param allocator Allocator for creating the values if the specified value or its parents are not exist. + \see Create() + */ ValueType& GetWithDefault(ValueType& root, const ValueType& defaultValue, typename ValueType::AllocatorType& allocator) const { bool alreadyExist; Value& v = Create(root, allocator, &alreadyExist); return alreadyExist ? v : v.CopyFrom(defaultValue, allocator); } + //! Query a value in a subtree with default null-terminated string. ValueType& GetWithDefault(ValueType& root, const Ch* defaultValue, typename ValueType::AllocatorType& allocator) const { bool alreadyExist; Value& v = Create(root, allocator, &alreadyExist); @@ -234,6 +431,7 @@ public: } #if RAPIDJSON_HAS_STDSTRING + //! Query a value in a subtree with default std::basic_string. ValueType& GetWithDefault(ValueType& root, const std::basic_string& defaultValue, typename ValueType::AllocatorType& allocator) const { bool alreadyExist; Value& v = Create(root, allocator, &alreadyExist); @@ -241,102 +439,162 @@ public: } #endif + //! Query a value in a subtree with default primitive value. + /*! + \tparam T \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool + */ template RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (ValueType&)) GetWithDefault(ValueType& root, T defaultValue, typename ValueType::AllocatorType& allocator) const { return GetWithDefault(root, ValueType(defaultValue).Move(), allocator); } + //! Query a value in a document with default value. template - ValueType& GetWithDefault(GenericDocument& root, const ValueType& defaultValue) const { - return GetWithDefault(root, defaultValue, root.GetAllocator()); + ValueType& GetWithDefault(GenericDocument& document, const ValueType& defaultValue) const { + return GetWithDefault(document, defaultValue, document.GetAllocator()); } + //! Query a value in a document with default null-terminated string. template - ValueType& GetWithDefault(GenericDocument& root, const Ch* defaultValue) const { - return GetWithDefault(root, defaultValue, root.GetAllocator()); + ValueType& GetWithDefault(GenericDocument& document, const Ch* defaultValue) const { + return GetWithDefault(document, defaultValue, document.GetAllocator()); } #if RAPIDJSON_HAS_STDSTRING + //! Query a value in a document with default std::basic_string. template - ValueType& GetWithDefault(GenericDocument& root, const std::basic_string& defaultValue) const { - return GetWithDefault(root, defaultValue, root.GetAllocator()); + ValueType& GetWithDefault(GenericDocument& document, const std::basic_string& defaultValue) const { + return GetWithDefault(document, defaultValue, document.GetAllocator()); } #endif + //! Query a value in a document with default primitive value. + /*! + \tparam T \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool + */ template RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (ValueType&)) - GetWithDefault(GenericDocument& root, T defaultValue) const { - return GetWithDefault(root, defaultValue, root.GetAllocator()); + GetWithDefault(GenericDocument& document, T defaultValue) const { + return GetWithDefault(document, defaultValue, document.GetAllocator()); } - // Move semantics, create parents if non-exist + //@} + + //!@name Set a value + //@{ + + //! Set a value in a subtree, with move semantics. + /*! + It creates all parents if they are not exist or types are different to the tokens. + So this function always succeeds but potentially remove existing values. + + \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root. + \param value Value to be set. + \param allocator Allocator for creating the values if the specified value or its parents are not exist. + \see Create() + */ ValueType& Set(ValueType& root, ValueType& value, typename ValueType::AllocatorType& allocator) const { return Create(root, allocator) = value; } - // Copy semantics, create parents if non-exist + //! Set a value in a subtree, with copy semantics. ValueType& Set(ValueType& root, const ValueType& value, typename ValueType::AllocatorType& allocator) const { return Create(root, allocator).CopyFrom(value, allocator); } + //! Set a null-terminated string in a subtree. ValueType& Set(ValueType& root, const Ch* value, typename ValueType::AllocatorType& allocator) const { return Create(root, allocator) = ValueType(value, allocator).Move(); } #if RAPIDJSON_HAS_STDSTRING + //! Set a std::basic_string in a subtree. ValueType& Set(ValueType& root, const std::basic_string& value, typename ValueType::AllocatorType& allocator) const { return Create(root, allocator) = ValueType(value, allocator).Move(); } #endif + //! Set a primitive value in a subtree. + /*! + \tparam T \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool + */ template RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (ValueType&)) Set(ValueType& root, T value, typename ValueType::AllocatorType& allocator) const { return Create(root, allocator) = ValueType(value).Move(); } + //! Set a value in a document, with move semantics. template - ValueType& Set(GenericDocument& root, ValueType& value) const { - return Create(root) = value; + ValueType& Set(GenericDocument& document, ValueType& value) const { + return Create(document) = value; } + //! Set a value in a document, with copy semantics. template - ValueType& Set(GenericDocument& root, const ValueType& value) const { - return Create(root).CopyFrom(value, root.GetAllocator()); + ValueType& Set(GenericDocument& document, const ValueType& value) const { + return Create(document).CopyFrom(value, document.GetAllocator()); } + //! Set a null-terminated string in a document. template - ValueType& Set(GenericDocument& root, const Ch* value) const { - return Create(root) = ValueType(value, root.GetAllocator()).Move(); + ValueType& Set(GenericDocument& document, const Ch* value) const { + return Create(document) = ValueType(value, document.GetAllocator()).Move(); } #if RAPIDJSON_HAS_STDSTRING + //! Sets a std::basic_string in a document. template - ValueType& Set(GenericDocument& root, const std::basic_string& value) const { - return Create(root) = ValueType(value, root.GetAllocator()).Move(); + ValueType& Set(GenericDocument& document, const std::basic_string& value) const { + return Create(document) = ValueType(value, document.GetAllocator()).Move(); } #endif + //! Set a primitive value in a document. + /*! + \tparam T \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool + */ template RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (ValueType&)) - Set(GenericDocument& root, T value) const { - return Create(root) = value; + Set(GenericDocument& document, T value) const { + return Create(document) = value; } - // Create parents if non-exist + //@} + + //!@name Swap a value + //@{ + + //! Swap a value with a value in a subtree. + /*! + It creates all parents if they are not exist or types are different to the tokens. + So this function always succeeds but potentially remove existing values. + + \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root. + \param value Value to be swapped. + \param allocator Allocator for creating the values if the specified value or its parents are not exist. + \see Create() + */ ValueType& Swap(ValueType& root, ValueType& value, typename ValueType::AllocatorType& allocator) const { return Create(root, allocator).Swap(value); } + //! Swap a value with a value in a document. template - ValueType& Swap(GenericDocument& root, ValueType& value) const { - return Create(root).Swap(value); + ValueType& Swap(GenericDocument& document, ValueType& value) const { + return Create(document).Swap(value); } + //@} + private: + //! Check whether a character should be percent-encoded. + /*! + According to RFC 3986 2.3 Unreserved Characters. + \param c The character (code unit) to be tested. + */ bool NeedPercentEncode(Ch c) const { - // RFC 3986 2.3 Unreserved Characters return !((c >= '0' && c <= '9') || (c >= 'A' && c <='Z') || (c >= 'a' && c <= 'z') || c == '-' || c == '.' || c == '_' || c =='~'); } @@ -475,6 +733,12 @@ private: return; } + //! Stringify to string or URI fragment representation. + /*! + \tparam uriFragment True for stringifying to URI fragment representation. False for string representation. + \tparam OutputStream type of output stream. + \param os The output stream. + */ template bool Stringify(OutputStream& os) const { RAPIDJSON_ASSERT(IsValid()); @@ -509,13 +773,23 @@ private: return true; } + //! A helper stream for decoding a percent-encoded sequence into code unit. + /*! + This stream decodes %XY triplet into code unit (0-255). + If it encounters invalid characters, it sets output code unit as 0 and + mark invalid, and to be checked by IsValid(). + */ class PercentDecodeStream { public: + //! Constructor + /*! + \param source Start of the stream + \param end Past-the-end of the stream. + */ PercentDecodeStream(const Ch* source, const Ch* end) : src_(source), head_(source), end_(end), valid_(true) {} Ch Take() { - // %XX triplet - if (src_ + 3 > end_ || *src_ != '%') { + if (*src_ != '%' || src_ + 3 > end_) { // %XY triplet valid_ = false; return 0; } @@ -537,16 +811,16 @@ private: } size_t Tell() const { return src_ - head_; } - bool IsValid() const { return valid_; } private: const Ch* src_; //!< Current read position. const Ch* head_; //!< Original head of the string. - const Ch* end_; - bool valid_; + const Ch* end_; //!< Past-the-end position. + bool valid_; //!< Whether the parsing is valid. }; + //! A helper stream to encode character (UTF-8 code unit) into percent-encoded sequence. template class PercentEncodeStream { public: @@ -562,17 +836,21 @@ private: OutputStream& os_; }; - Allocator* allocator_; - Allocator* ownAllocator_; - Ch* nameBuffer_; - Token* tokens_; - size_t tokenCount_; - size_t parseErrorOffset_; - PointerParseErrorCode parseErrorCode_; + Allocator* allocator_; //!< The current allocator. It is either user-supplied or equal to ownAllocator_. + Allocator* ownAllocator_; //!< Allocator owned by this Pointer. + Ch* nameBuffer_; //!< A buffer containing all names in tokens. + Token* tokens_; //!< A list of tokens. + size_t tokenCount_; //!< Number of tokens in tokens_. + size_t parseErrorOffset_; //!< Offset in code unit when parsing fail. + PointerParseErrorCode parseErrorCode_; //!< Parsing error code. }; +//! GenericPointer for Value (UTF-8, default allocator). typedef GenericPointer Pointer; +//!@name Helper functions for GenericPointer +//@{ + ////////////////////////////////////////////////////////////////////////////// template @@ -587,14 +865,14 @@ typename T::ValueType& CreateValueByPointer(T& root, const CharType(&source)[N], // No allocator parameter -template -typename T::ValueType& CreateValueByPointer(T& root, const GenericPointer& pointer) { - return pointer.Create(root); +template +typename DocumentType::ValueType& CreateValueByPointer(DocumentType& document, const GenericPointer& pointer) { + return pointer.Create(document); } -template -typename T::ValueType& CreateValueByPointer(T& root, const CharType(&source)[N]) { - return GenericPointer(source, N - 1).Create(root); +template +typename DocumentType::ValueType& CreateValueByPointer(DocumentType& document, const CharType(&source)[N]) { + return GenericPointer(source, N - 1).Create(document); } ////////////////////////////////////////////////////////////////////////////// @@ -669,50 +947,50 @@ GetValueByPointerWithDefault(T& root, const CharType(&source)[N], T2 defaultValu // No allocator parameter -template -typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer& pointer, const typename T::ValueType& defaultValue) { - return pointer.GetWithDefault(root, defaultValue); +template +typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer& pointer, const typename DocumentType::ValueType& defaultValue) { + return pointer.GetWithDefault(document, defaultValue); } -template -typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer& pointer, const typename T::Ch* defaultValue) { - return pointer.GetWithDefault(root, defaultValue); +template +typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer& pointer, const typename DocumentType::Ch* defaultValue) { + return pointer.GetWithDefault(document, defaultValue); } #if RAPIDJSON_HAS_STDSTRING -template -typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer& pointer, const std::basic_string& defaultValue) { - return pointer.GetWithDefault(root, defaultValue); +template +typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer& pointer, const std::basic_string& defaultValue) { + return pointer.GetWithDefault(document, defaultValue); } #endif -template -RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename T::ValueType&)) -GetValueByPointerWithDefault(T& root, const GenericPointer& pointer, T2 defaultValue) { - return pointer.GetWithDefault(root, defaultValue); +template +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename DocumentType::ValueType&)) +GetValueByPointerWithDefault(DocumentType& document, const GenericPointer& pointer, T2 defaultValue) { + return pointer.GetWithDefault(document, defaultValue); } -template -typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const typename T::ValueType& defaultValue) { - return GenericPointer(source, N - 1).GetWithDefault(root, defaultValue); +template +typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const typename DocumentType::ValueType& defaultValue) { + return GenericPointer(source, N - 1).GetWithDefault(document, defaultValue); } -template -typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const typename T::Ch* defaultValue) { - return GenericPointer(source, N - 1).GetWithDefault(root, defaultValue); +template +typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const typename DocumentType::Ch* defaultValue) { + return GenericPointer(source, N - 1).GetWithDefault(document, defaultValue); } #if RAPIDJSON_HAS_STDSTRING -template -typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const std::basic_string& defaultValue) { - return GenericPointer(source, N - 1).GetWithDefault(root, defaultValue); +template +typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const std::basic_string& defaultValue) { + return GenericPointer(source, N - 1).GetWithDefault(document, defaultValue); } #endif -template -RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename T::ValueType&)) -GetValueByPointerWithDefault(T& root, const CharType(&source)[N], T2 defaultValue) { - return GenericPointer(source, N - 1).GetWithDefault(root, defaultValue); +template +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename DocumentType::ValueType&)) +GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], T2 defaultValue) { + return GenericPointer(source, N - 1).GetWithDefault(document, defaultValue); } ////////////////////////////////////////////////////////////////////////////// @@ -775,60 +1053,60 @@ SetValueByPointer(T& root, const CharType(&source)[N], T2 value, typename T::All // No allocator parameter -template -typename T::ValueType& SetValueByPointer(T& root, const GenericPointer& pointer, typename T::ValueType& value) { - return pointer.Set(root, value); +template +typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer& pointer, typename DocumentType::ValueType& value) { + return pointer.Set(document, value); } -template -typename T::ValueType& SetValueByPointer(T& root, const GenericPointer& pointer, const typename T::ValueType& value) { - return pointer.Set(root, value); +template +typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer& pointer, const typename DocumentType::ValueType& value) { + return pointer.Set(document, value); } -template -typename T::ValueType& SetValueByPointer(T& root, const GenericPointer& pointer, const typename T::Ch* value) { - return pointer.Set(root, value); +template +typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer& pointer, const typename DocumentType::Ch* value) { + return pointer.Set(document, value); } #if RAPIDJSON_HAS_STDSTRING -template -typename T::ValueType& SetValueByPointer(T& root, const GenericPointer& pointer, const std::basic_string& value) { - return pointer.Set(root, value); +template +typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer& pointer, const std::basic_string& value) { + return pointer.Set(document, value); } #endif -template -RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename T::ValueType&)) -SetValueByPointer(T& root, const GenericPointer& pointer, T2 value) { - return pointer.Set(root, value); +template +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename DocumentType::ValueType&)) +SetValueByPointer(DocumentType& document, const GenericPointer& pointer, T2 value) { + return pointer.Set(document, value); } -template -typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], typename T::ValueType& value) { - return GenericPointer(source, N - 1).Set(root, value); +template +typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], typename DocumentType::ValueType& value) { + return GenericPointer(source, N - 1).Set(document, value); } -template -typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const typename T::ValueType& value) { - return GenericPointer(source, N - 1).Set(root, value); +template +typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const typename DocumentType::ValueType& value) { + return GenericPointer(source, N - 1).Set(document, value); } -template -typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const typename T::Ch* value) { - return GenericPointer(source, N - 1).Set(root, value); +template +typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const typename DocumentType::Ch* value) { + return GenericPointer(source, N - 1).Set(document, value); } #if RAPIDJSON_HAS_STDSTRING -template -typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const std::basic_string& value) { - return GenericPointer(source, N - 1).Set(root, value); +template +typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const std::basic_string& value) { + return GenericPointer(source, N - 1).Set(document, value); } #endif -template -RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename T::ValueType&)) -SetValueByPointer(T& root, const CharType(&source)[N], T2 value) { - return GenericPointer(source, N - 1).Set(root, value); +template +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename DocumentType::ValueType&)) +SetValueByPointer(DocumentType& document, const CharType(&source)[N], T2 value) { + return GenericPointer(source, N - 1).Set(document, value); } ////////////////////////////////////////////////////////////////////////////// @@ -843,16 +1121,18 @@ typename T::ValueType& SwapValueByPointer(T& root, const CharType(&source)[N], t return GenericPointer(source, N - 1).Swap(root, value, a); } -template -typename T::ValueType& SwapValueByPointer(T& root, const GenericPointer& pointer, typename T::ValueType& value) { - return pointer.Swap(root, value); +template +typename DocumentType::ValueType& SwapValueByPointer(DocumentType& document, const GenericPointer& pointer, typename DocumentType::ValueType& value) { + return pointer.Swap(document, value); } -template -typename T::ValueType& SwapValueByPointer(T& root, const CharType(&source)[N], typename T::ValueType& value) { - return GenericPointer(source, N - 1).Swap(root, value); +template +typename DocumentType::ValueType& SwapValueByPointer(DocumentType& document, const CharType(&source)[N], typename DocumentType::ValueType& value) { + return GenericPointer(source, N - 1).Swap(document, value); } +//@} + RAPIDJSON_NAMESPACE_END #endif // RAPIDJSON_POINTER_H_ From 436625f83cbeabc8c6c30b7a7a099b7406f1aee8 Mon Sep 17 00:00:00 2001 From: miloyip Date: Mon, 4 May 2015 15:02:43 +0800 Subject: [PATCH 065/189] Fix ambiguous cases in Pointer::Create() --- include/rapidjson/pointer.h | 44 +++++++++++++++++------------------ test/unittest/pointertest.cpp | 25 +++++++++++++++++++- 2 files changed, 46 insertions(+), 23 deletions(-) diff --git a/include/rapidjson/pointer.h b/include/rapidjson/pointer.h index 3ba9e1c..89dfa48 100644 --- a/include/rapidjson/pointer.h +++ b/include/rapidjson/pointer.h @@ -305,19 +305,31 @@ public: ValueType* v = &root; bool exist = true; for (Token *t = tokens_; t != tokens_ + tokenCount_; ++t) { - if (t->index == kPointerInvalidIndex) { // object name - // Handling of '-' for last element of array - if (t->name[0] == '-' && t->length == 1) { - if (!v->IsArray()) - v->SetArray(); // Change to Array - v->PushBack(Value().Move(), allocator); - v = &((*v)[v->Size() - 1]); - exist = false; - } - else { + if (v->IsArray() && t->name[0] == '-' && t->length == 1) { + v->PushBack(Value().Move(), allocator); + v = &((*v)[v->Size() - 1]); + exist = false; + } + else { + if (t->index == kPointerInvalidIndex) { // must be object name if (!v->IsObject()) v->SetObject(); // Change to Object + } + else { // object name or array index + if (!v->IsArray() && !v->IsObject()) + v->SetArray(); // Change to Array + } + if (v->IsArray()) { + if (t->index >= v->Size()) { + v->Reserve(t->index + 1, allocator); + while (t->index >= v->Size()) + v->PushBack(Value().Move(), allocator); + exist = false; + } + v = &((*v)[t->index]); + } + else { typename ValueType::MemberIterator m = v->FindMember(GenericStringRef(t->name, t->length)); if (m == v->MemberEnd()) { v->AddMember(Value(t->name, t->length, allocator).Move(), Value().Move(), allocator); @@ -328,18 +340,6 @@ public: v = &m->value; } } - else { // array index - if (!v->IsArray()) - v->SetArray(); // Change to Array - - if (t->index >= v->Size()) { - v->Reserve(t->index + 1, allocator); - while (t->index >= v->Size()) - v->PushBack(Value().Move(), allocator); - exist = false; - } - v = &((*v)[t->index]); - } } if (alreadyExist) diff --git a/test/unittest/pointertest.cpp b/test/unittest/pointertest.cpp index 004fa22..72bfdbf 100644 --- a/test/unittest/pointertest.cpp +++ b/test/unittest/pointertest.cpp @@ -532,9 +532,13 @@ TEST(Pointer, Create) { Value* v = &Pointer("/foo/-").Create(d, d.GetAllocator()); EXPECT_EQ(&d["foo"][1], v); } + { Value* v = &Pointer("/foo/-/-").Create(d, d.GetAllocator()); - EXPECT_EQ(&d["foo"][2][0], v); + // "foo/-" is a newly created null value x. + // "foo/-/-" finds that x is not an array, it converts x to empty object + // and treats - as "-" member name + EXPECT_EQ(&d["foo"][2]["-"], v); } { @@ -1314,3 +1318,22 @@ TEST(Pointer, SwapValueByPointer_NoAllocator) { EXPECT_STREQ("bar", d["foo"][0].GetString()); EXPECT_STREQ("baz", d["foo"][1].GetString()); } + +TEST(Pointer, Ambiguity) { + { + Document d; + d.Parse("{\"0\" : [123]}"); + EXPECT_EQ(123, Pointer("/0/0").Get(d)->GetInt()); + Pointer("/0/a").Set(d, 456); // Change array [123] to object {456} + EXPECT_EQ(456, Pointer("/0/a").Get(d)->GetInt()); + } + + { + Document d; + EXPECT_FALSE(d.Parse("[{\"0\": 123}]").HasParseError()); + EXPECT_EQ(123, Pointer("/0/0").Get(d)->GetInt()); + Pointer("/0/1").Set(d, 456); // 1 is treated as "1" to index object + EXPECT_EQ(123, Pointer("/0/0").Get(d)->GetInt()); + EXPECT_EQ(456, Pointer("/0/1").Get(d)->GetInt()); + } +} From 5543a090c02c17f1422342d566f2a1fd38d58e60 Mon Sep 17 00:00:00 2001 From: miloyip Date: Mon, 4 May 2015 16:32:02 +0800 Subject: [PATCH 066/189] Draft Pointer guide --- doc/Doxyfile.in | 1 + doc/pointer.md | 218 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 219 insertions(+) create mode 100644 doc/pointer.md diff --git a/doc/Doxyfile.in b/doc/Doxyfile.in index 6920143..b806205 100644 --- a/doc/Doxyfile.in +++ b/doc/Doxyfile.in @@ -769,6 +769,7 @@ INPUT = readme.md \ include/ \ doc/features.md \ doc/tutorial.md \ + doc/pointer.md \ doc/stream.md \ doc/encoding.md \ doc/dom.md \ diff --git a/doc/pointer.md b/doc/pointer.md new file mode 100644 index 0000000..7388097 --- /dev/null +++ b/doc/pointer.md @@ -0,0 +1,218 @@ +# Pointer + +## Status: experimental, shall be included in v1.1 + +JSON Pointer is a standardized ([RFC6901]) way to select a value inside a JSON Document (DOM). This can be analogous to XPath for XML document. However, JSON Pointer is much simpler, and a single JSON Pointer only pointed to a single value. + +Using RapidJSON's implementation of JSON Pointer can simplify some manipulations of the DOM. + +[TOC] + +# JSON Pointer {#JsonPointer} + +A JSON Pointer is a list of zero-to-many tokens, each prefixed by `/`. Each token can be a string or a number. For example, given a JSON: +~~~javascript +{ + "foo" : ["bar", "baz"], + "pi" : 3.1416 +} +~~~ + +The following JSON Pointers resolve this JSON as: + +1. `"/foo"` → `[ "bar", "baz" ]` +2. `"/foo/0` → `"bar"` +3. `"/foo/1` → `"baz"` +4. `"/pi` → 3.1416 + +Note that, an empty JSON Pointer `""` (zero token) resolves to the whole JSON. + +# Basic Usage {#BasicUsage} + +The following example code is self-explanatory. + +~~~cpp +#include "rapidjson/pointer.h" + +// ... +Document d; + +// Create DOM by Set() +Pointer("/project").Set(d, "RapidJSON"); +Pointer("/stars").Set(d, 10); +// { "project" : "RapidJSON", "stars" : 10 } + +// Access DOM by Get(). It return nullptr if the value is not exist. +if (Value* stars = Pointer("/stars").Get(d)) + stars->SetInt(stars->GetInt() + 1); +// { "project" : "RapidJSON", "stars" : 11 } + +// Set() and Create() automatically generate parents if not exist. +Pointer("/a/b/0").Create(d); +// { "project" : "RapidJSON", "stars" : 11, "a" : { "b" : [ null ] } } + +// GetWithDefault() returns reference. And it deep clones the default value. +Value& hello = Pointer("/hello").GetWithDefault(d, "world"); +// { "project" : "RapidJSON", "stars" : 11, "a" : { "b" : [ null ] }, "hello" : "world" } + +// Swap() is similar to Set() +Value x("C++"); +Pointer("/hello").Swap(d, x); +// { "project" : "RapidJSON", "stars" : 11, "a" : { "b" : [ null ] }, "hello" : "C++" } +// x becomes "world" +~~~ + +# Helper Functions {#HelperFunctions} + +Since object-oriented calling convention may be non-intuitive, RapidJSON also provides helper functions, which just wrap the member functions with free-functions. + +The following example does exactly the same as the above one. + +~~~cpp +Document d; + +SetValueByPointer(d, "/project", "RapidJSON"); +SetValueByPointer(d, "/stars", 10); + +if (Value* stars = GetValueByPointer(d, "/stars")) + stars->SetInt(stars->GetInt() + 1); + +CreateValueByPointer(d, "/a/b/0"); + +Value& hello = GetValueByPointerWithDefault(d, "/hello", "world"); + +Value x("C++"); +SwapValueByPointer(d, "/hello", x); +~~~ + +The conventions are shown here for comparison: + +1. `Pointer(source).(root, ...)` +2. `ValueByPointer(root, Pointer(source), ...)` +3. `ValueByPointer(root, source, ...)` + +# Resolving Pointer {#ResolvingPointer} + +`Pointer::Get()` or `GetValueByPointer()` function does not modify the DOM. If the tokens cannot match a value in the DOM, it returns `nullptr`. User can use this to see whether a value is exists. + +Note that, numerical tokens can represent an array index or member name. The resolving process will match the values according to the types of value. + +~~~javascript +{ + "0" : 123, + "1" : [456] +} +~~~ + +1. `"/0"` → `123` +2. `"/1/0"` → `456` + +The token `"0"` is treated as member name in the first pointer. It is treated as an array index in the second pointer. + +The other functions, including `Create()`, `GetWithDefault()`, `Set()` and `Swap()`, will change the DOM. These functions will always succeed. They will create the parent values if they do not exist. If the parent values do not match with the tokens, they will also be forced to change their type. Changing the type also mean fully removal of that DOM subtree. + +Parsing the above JSON into `d`, + +~~~cpp +SetValueByPointer(d, "1/a", 789); // { "0" : 123, "1" : { "a" : 789 } } +~~~ + +## Resolving Minus Sign Token + +Besides, [RFC6901] defines a special token `-` (single minus sign), which means the pass-the-end value of an array. `Get()` only treats this token as a member name '"-"'. Yet the other functions can resolve this for array, equivalent to calling `Value::PushBack()` to the array. + +~~~cpp +Document d; +d.Parse("{\"foo\":[123]}"); +SetValueByPointer(d, "/foo/-", 456); // { "foo" : [123, 456] } +SetValueByPointer(d, "/-", 789); // { "foo" : [123, 456], "-" : 789 } +~~~ + +## Resolving Document and Value + +When using `p.Get(root)` or `GetValueByPointer(root, p)`, `root` is a (const) `Value&`. That means, it can be a subtree of the DOM. + +The other functions have two groups of signature. One group uses `Document& document` as parameter, another one uses `Value& root`. The first group uses `document.GetAllocator()` for creating values. And the second group needs user to supply an allocator, like the functions in DOM. + +All examples above do not require an allocator parameter, because the parameter is a `Document&`. But if you want to resolve a pointer to a subtree. You need to supply it as in the following example: + +~~~cpp +class Person { +public: + Person() { + document_ = new Document(); + // CreateValueByPointer() here no need allocator + SetLocation(CreateValueByPointer(*document_, "/residence"), ...); + SetLocation(CreateValueByPointer(*document_, "/office"), ...); + }; + +private: + void SetLocation(Value& location, const char* country, const char* addresses[2]) { + Value::Allocator& a = document_->GetAllocator(); + // SetValueByPointer() here need allocator + SetValueByPointer(location, "/country", country, a); + SetValueByPointer(location, "/address/0", address[0], a); + SetValueByPointer(location, "/address/1", address[1], a); + } + + // ... + + Document* document_; +}; +~~~ + +# Error Handling {#ErrorHandling} + +A `Pointer` parses a source string in its constructor. If there is parsing error, `Pointer::IsValid()` returns false. And you can use `Pointer::GetParseErrorCode()` and `GetParseErrorOffset()` to retrieve the error information. + +Note that, all resolving functions assumes valid pointer. Resolving with an invalid pointer causes assertion failure. + +# URI Fragment Representation {#URIFragment} + +In addition to the string representation of JSON pointer that we are using till now, [RFC6901] also defines the URI fragment representation of JSON pointer. URI fragment is specified in [RFC3986] "Uniform Resource Identifier (URI): Generic Syntax". + +The main differences are that a the URI fragment always has a `#` (pound sign) in the beginning, and some characters are encoded by percent-encoding in UTF-8 sequence. For example, the following table shows different C/C++ string literals of different representations. + +String Representation | URI Fragment Representation | Pointer Tokens (UTF-8) +----------------------|-----------------------------|------------------------ +`"/foo/0"` | `"#/foo/0"` | `{"foo", 0}` +`"/a~1b"` | `"#/a~1b"` | `{"a/b"}` +`"/m~0n"` | `"#/m~0n"` | `{"m~n"}` +`"/ "` | `"#/%20"` | `{" "}` +`"/\0"` | `"#/%00"` | `{"\0"}` +`"/\xE2\x82\xAC"` | `"#/%E2%82%AC` | `{"\xE2\x82\xAC"}` + +RapidJSON fully support URI fragment representation. It automatically detects the pound sign during parsing. + +# Stringify + +You may also stringify a `Pointer` to a string or other output streams. This can be done by: + +~~~ +Pointer p(...); +StringBuffer sb; +p.Stringify(sb); +std::cout << sb.GetString() << std::endl; +~~~ + +It can also stringify to URI fragment reprsentation by `StringifyUriFragment()`. + +# User-Supplied Tokens {#UserSuppliedTokens} + +If a pointer will be resolved multiple times, it should be construct once, and then apply it to different DOMs or in different times. This reduce time and memory allocation for constructing `Pointer` multiple times. + +We can go one step further, to completely eliminate the parsing process and dynamic memory allocation, we can establish the token array directly: + +~~~cpp +#define NAME(s) { s, sizeof(s) / sizeof(s[0]) - 1, kPointerInvalidIndex } +#define INDEX(i) { #i, sizeof(#i) - 1, i } + +static const Pointer::Token kTokens[] = { NAME("foo"), INDEX(123) }; +static const Pointer p(kTokens, sizeof(kTokens) / sizeof(kTokens[0])); +// Equivalent to static const Pointer p("/foo/123"); +~~~ + +This may be useful for memory constrained systems. + +[RFC3986]: https://tools.ietf.org/html/rfc3986 +[RFC6901]: https://tools.ietf.org/html/rfc6901 From 1086297f134864058fa450f76d7cac30a2372f46 Mon Sep 17 00:00:00 2001 From: miloyip Date: Mon, 4 May 2015 17:05:01 +0800 Subject: [PATCH 067/189] Fix Pointer guide punctuations --- doc/pointer.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/pointer.md b/doc/pointer.md index 7388097..df9e953 100644 --- a/doc/pointer.md +++ b/doc/pointer.md @@ -21,9 +21,9 @@ A JSON Pointer is a list of zero-to-many tokens, each prefixed by `/`. Each toke The following JSON Pointers resolve this JSON as: 1. `"/foo"` → `[ "bar", "baz" ]` -2. `"/foo/0` → `"bar"` -3. `"/foo/1` → `"baz"` -4. `"/pi` → 3.1416 +2. `"/foo/0"` → `"bar"` +3. `"/foo/1"` → `"baz"` +4. `"/pi"` → 3.1416 Note that, an empty JSON Pointer `""` (zero token) resolves to the whole JSON. @@ -180,7 +180,7 @@ String Representation | URI Fragment Representation | Pointer Tokens (UTF-8) `"/m~0n"` | `"#/m~0n"` | `{"m~n"}` `"/ "` | `"#/%20"` | `{" "}` `"/\0"` | `"#/%00"` | `{"\0"}` -`"/\xE2\x82\xAC"` | `"#/%E2%82%AC` | `{"\xE2\x82\xAC"}` +`"/\xE2\x82\xAC"` | `"#/%E2%82%AC"` | `{"\xE2\x82\xAC"}` RapidJSON fully support URI fragment representation. It automatically detects the pound sign during parsing. From 5bec8b99bb8ef8bb2f1563b78d8d82149f3d313a Mon Sep 17 00:00:00 2001 From: miloyip Date: Mon, 4 May 2015 17:28:37 +0800 Subject: [PATCH 068/189] Minor modification to Pointer guide --- doc/pointer.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/doc/pointer.md b/doc/pointer.md index df9e953..01703f0 100644 --- a/doc/pointer.md +++ b/doc/pointer.md @@ -23,7 +23,7 @@ The following JSON Pointers resolve this JSON as: 1. `"/foo"` → `[ "bar", "baz" ]` 2. `"/foo/0"` → `"bar"` 3. `"/foo/1"` → `"baz"` -4. `"/pi"` → 3.1416 +4. `"/pi"` → `3.1416` Note that, an empty JSON Pointer `""` (zero token) resolves to the whole JSON. @@ -40,24 +40,29 @@ Document d; // Create DOM by Set() Pointer("/project").Set(d, "RapidJSON"); Pointer("/stars").Set(d, 10); + // { "project" : "RapidJSON", "stars" : 10 } // Access DOM by Get(). It return nullptr if the value is not exist. if (Value* stars = Pointer("/stars").Get(d)) stars->SetInt(stars->GetInt() + 1); + // { "project" : "RapidJSON", "stars" : 11 } // Set() and Create() automatically generate parents if not exist. Pointer("/a/b/0").Create(d); + // { "project" : "RapidJSON", "stars" : 11, "a" : { "b" : [ null ] } } // GetWithDefault() returns reference. And it deep clones the default value. Value& hello = Pointer("/hello").GetWithDefault(d, "world"); + // { "project" : "RapidJSON", "stars" : 11, "a" : { "b" : [ null ] }, "hello" : "world" } // Swap() is similar to Set() Value x("C++"); Pointer("/hello").Swap(d, x); + // { "project" : "RapidJSON", "stars" : 11, "a" : { "b" : [ null ] }, "hello" : "C++" } // x becomes "world" ~~~ @@ -109,7 +114,7 @@ Note that, numerical tokens can represent an array index or member name. The res The token `"0"` is treated as member name in the first pointer. It is treated as an array index in the second pointer. -The other functions, including `Create()`, `GetWithDefault()`, `Set()` and `Swap()`, will change the DOM. These functions will always succeed. They will create the parent values if they do not exist. If the parent values do not match with the tokens, they will also be forced to change their type. Changing the type also mean fully removal of that DOM subtree. +The other functions, including `Create()`, `GetWithDefault()`, `Set()` and `Swap()`, will change the DOM. These functions will always succeed. They will create the parent values if they do not exist. If the parent values do not match the tokens, they will also be forced to change their type. Changing the type also mean fully removal of that DOM subtree. Parsing the above JSON into `d`, From a3e5fcf490e4d4018ffda536a0b7859e578c850e Mon Sep 17 00:00:00 2001 From: miloyip Date: Mon, 4 May 2015 18:22:40 +0800 Subject: [PATCH 069/189] Minor grammar corrections --- doc/pointer.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/pointer.md b/doc/pointer.md index 01703f0..c75fe0d 100644 --- a/doc/pointer.md +++ b/doc/pointer.md @@ -43,7 +43,7 @@ Pointer("/stars").Set(d, 10); // { "project" : "RapidJSON", "stars" : 10 } -// Access DOM by Get(). It return nullptr if the value is not exist. +// Access DOM by Get(). It return nullptr if the value does not exist. if (Value* stars = Pointer("/stars").Get(d)) stars->SetInt(stars->GetInt() + 1); @@ -98,7 +98,7 @@ The conventions are shown here for comparison: # Resolving Pointer {#ResolvingPointer} -`Pointer::Get()` or `GetValueByPointer()` function does not modify the DOM. If the tokens cannot match a value in the DOM, it returns `nullptr`. User can use this to see whether a value is exists. +`Pointer::Get()` or `GetValueByPointer()` function does not modify the DOM. If the tokens cannot match a value in the DOM, it returns `nullptr`. User can use this to check whether a value exists. Note that, numerical tokens can represent an array index or member name. The resolving process will match the values according to the types of value. @@ -124,7 +124,7 @@ SetValueByPointer(d, "1/a", 789); // { "0" : 123, "1" : { "a" : 789 } } ## Resolving Minus Sign Token -Besides, [RFC6901] defines a special token `-` (single minus sign), which means the pass-the-end value of an array. `Get()` only treats this token as a member name '"-"'. Yet the other functions can resolve this for array, equivalent to calling `Value::PushBack()` to the array. +Besides, [RFC6901] defines a special token `-` (single minus sign), which represents the pass-the-end element of an array. `Get()` only treats this token as a member name '"-"'. Yet the other functions can resolve this for array, equivalent to calling `Value::PushBack()` to the array. ~~~cpp Document d; From 8c01e7e1ce5e39d675170749a3ec297608b27463 Mon Sep 17 00:00:00 2001 From: Milo Yip Date: Mon, 4 May 2015 21:50:26 +0800 Subject: [PATCH 070/189] Add Pointer::Erase() and EraseValueByPointer() --- doc/pointer.md | 11 +++++++ include/rapidjson/pointer.h | 60 +++++++++++++++++++++++++++++++++-- test/unittest/pointertest.cpp | 45 ++++++++++++++++++++++++++ 3 files changed, 114 insertions(+), 2 deletions(-) diff --git a/doc/pointer.md b/doc/pointer.md index c75fe0d..d4d1cf2 100644 --- a/doc/pointer.md +++ b/doc/pointer.md @@ -65,6 +65,12 @@ Pointer("/hello").Swap(d, x); // { "project" : "RapidJSON", "stars" : 11, "a" : { "b" : [ null ] }, "hello" : "C++" } // x becomes "world" + +// Erase a member or element, return true if the value exists +bool success = Pointer("/a").Erase(d); +assert(success); + +// { "project" : "RapidJSON", "stars" : 10 } ~~~ # Helper Functions {#HelperFunctions} @@ -88,6 +94,9 @@ Value& hello = GetValueByPointerWithDefault(d, "/hello", "world"); Value x("C++"); SwapValueByPointer(d, "/hello", x); + +bool success = EraseValueByPointer(d, "/a"); +assert(success); ~~~ The conventions are shown here for comparison: @@ -166,6 +175,8 @@ private: }; ~~~ +`Erase()` or `EraseValueByPointer()` does not need allocator. And they return `true` if the value is erased successfully. + # Error Handling {#ErrorHandling} A `Pointer` parses a source string in its constructor. If there is parsing error, `Pointer::IsValid()` returns false. And you can use `Pointer::GetParseErrorCode()` and `GetParseErrorOffset()` to retrieve the error information. diff --git a/include/rapidjson/pointer.h b/include/rapidjson/pointer.h index 89dfa48..b68829c 100644 --- a/include/rapidjson/pointer.h +++ b/include/rapidjson/pointer.h @@ -304,7 +304,7 @@ public: RAPIDJSON_ASSERT(IsValid()); ValueType* v = &root; bool exist = true; - for (Token *t = tokens_; t != tokens_ + tokenCount_; ++t) { + for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) { if (v->IsArray() && t->name[0] == '-' && t->length == 1) { v->PushBack(Value().Move(), allocator); v = &((*v)[v->Size() - 1]); @@ -373,7 +373,7 @@ public: ValueType* Get(ValueType& root) const { RAPIDJSON_ASSERT(IsValid()); ValueType* v = &root; - for (Token *t = tokens_; t != tokens_ + tokenCount_; ++t) { + for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) { switch (v->GetType()) { case kObjectType: { @@ -588,6 +588,50 @@ public: //@} + //! Erase a value in a subtree. + /*! + \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root. + \return Whether the resolved value is found and erased. + + \note Erasing with an empty pointer \c Pointer(""), i.e. the root, always fail and return false. + */ + bool Erase(ValueType& root) const { + RAPIDJSON_ASSERT(IsValid()); + if (tokenCount_ == 0) // Cannot erase the root + return false; + + ValueType* v = &root; + const Token* last = tokens_ + (tokenCount_ - 1); + for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) { + switch (v->GetType()) { + case kObjectType: + { + typename ValueType::MemberIterator m = v->FindMember(GenericStringRef(t->name, t->length)); + if (m == v->MemberEnd()) + return false; + if (t == last) { + v->EraseMember(m); + return true; + } + v = &m->value; + } + break; + case kArrayType: + if (t->index == kPointerInvalidIndex || t->index >= v->Size()) + return false; + if (t == last) { + v->Erase(v->Begin() + t->index); + return true; + } + v = &((*v)[t->index]); + break; + default: + return false; + } + } + return false; + } + private: //! Check whether a character should be percent-encoded. /*! @@ -1131,6 +1175,18 @@ typename DocumentType::ValueType& SwapValueByPointer(DocumentType& document, con return GenericPointer(source, N - 1).Swap(document, value); } +////////////////////////////////////////////////////////////////////////////// + +template +bool EraseValueByPointer(T& root, const GenericPointer& pointer) { + return pointer.Erase(root); +} + +template +bool EraseValueByPointer(T& root, const CharType(&source)[N]) { + return GenericPointer(source, N - 1).Erase(root); +} + //@} RAPIDJSON_NAMESPACE_END diff --git a/test/unittest/pointertest.cpp b/test/unittest/pointertest.cpp index 72bfdbf..cf2ab72 100644 --- a/test/unittest/pointertest.cpp +++ b/test/unittest/pointertest.cpp @@ -818,6 +818,21 @@ TEST(Pointer, Swap_NoAllocator) { EXPECT_STREQ("bar", d["foo"][1].GetString()); } +TEST(Pointer, Erase) { + Document d; + d.Parse(kJson); + + EXPECT_FALSE(Pointer("").Erase(d)); + EXPECT_FALSE(Pointer("/foo/nonexist").Erase(d)); + EXPECT_TRUE(Pointer("/foo/0").Erase(d)); + EXPECT_EQ(1u, d["foo"].Size()); + EXPECT_STREQ("baz", d["foo"][0].GetString()); + EXPECT_TRUE(Pointer("/foo/0").Erase(d)); + EXPECT_TRUE(d["foo"].Empty()); + EXPECT_TRUE(Pointer("/foo").Erase(d)); + EXPECT_TRUE(Pointer("/foo").Get(d) == 0); +} + TEST(Pointer, CreateValueByPointer) { Document d; Document::AllocatorType& a = d.GetAllocator(); @@ -1319,6 +1334,36 @@ TEST(Pointer, SwapValueByPointer_NoAllocator) { EXPECT_STREQ("baz", d["foo"][1].GetString()); } +TEST(Pointer, EraseValueByPointer_Pointer) { + Document d; + d.Parse(kJson); + + EXPECT_FALSE(EraseValueByPointer(d, Pointer(""))); + EXPECT_FALSE(Pointer("/foo/nonexist").Erase(d)); + EXPECT_TRUE(EraseValueByPointer(d, Pointer("/foo/0"))); + EXPECT_EQ(1u, d["foo"].Size()); + EXPECT_STREQ("baz", d["foo"][0].GetString()); + EXPECT_TRUE(EraseValueByPointer(d, Pointer("/foo/0"))); + EXPECT_TRUE(d["foo"].Empty()); + EXPECT_TRUE(EraseValueByPointer(d, Pointer("/foo"))); + EXPECT_TRUE(Pointer("/foo").Get(d) == 0); +} + +TEST(Pointer, EraseValueByPointer_String) { + Document d; + d.Parse(kJson); + + EXPECT_FALSE(EraseValueByPointer(d, "")); + EXPECT_FALSE(Pointer("/foo/nonexist").Erase(d)); + EXPECT_TRUE(EraseValueByPointer(d, "/foo/0")); + EXPECT_EQ(1u, d["foo"].Size()); + EXPECT_STREQ("baz", d["foo"][0].GetString()); + EXPECT_TRUE(EraseValueByPointer(d, "/foo/0")); + EXPECT_TRUE(d["foo"].Empty()); + EXPECT_TRUE(EraseValueByPointer(d, "/foo")); + EXPECT_TRUE(Pointer("/foo").Get(d) == 0); +} + TEST(Pointer, Ambiguity) { { Document d; From ba7647531b2fbcc6e91dfc5898e15eb0bc0f178b Mon Sep 17 00:00:00 2001 From: Milo Yip Date: Mon, 4 May 2015 22:13:14 +0800 Subject: [PATCH 071/189] Fix incorrect doxygen escapes --- doc/pointer.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/pointer.md b/doc/pointer.md index d4d1cf2..1d75080 100644 --- a/doc/pointer.md +++ b/doc/pointer.md @@ -196,7 +196,7 @@ String Representation | URI Fragment Representation | Pointer Tokens (UTF-8) `"/m~0n"` | `"#/m~0n"` | `{"m~n"}` `"/ "` | `"#/%20"` | `{" "}` `"/\0"` | `"#/%00"` | `{"\0"}` -`"/\xE2\x82\xAC"` | `"#/%E2%82%AC"` | `{"\xE2\x82\xAC"}` +`"/€"` | `"#/%E2%82%AC"` | `{"€"}` RapidJSON fully support URI fragment representation. It automatically detects the pound sign during parsing. From 33b7a4bae03a8b46a7fedcbae5be1a7fc0c86c6b Mon Sep 17 00:00:00 2001 From: Justin Scheiber Date: Tue, 5 May 2015 09:26:22 -0600 Subject: [PATCH 072/189] don't try to use google's servers --- .gitmodules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitmodules b/.gitmodules index 8e9d1f3..b54b211 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ [submodule "thirdparty/gtest"] path = thirdparty/gtest - url = https://chromium.googlesource.com/external/googletest.git + url = ssh://git@git.eyesopen.com/common/rapidjson.git From 1576cde59276c7157ecaebdb24470667bd743271 Mon Sep 17 00:00:00 2001 From: Igor Kostenko Date: Tue, 5 May 2015 17:39:16 +0100 Subject: [PATCH 073/189] Fix alignment of 64bit platforms --- include/rapidjson/rapidjson.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/rapidjson/rapidjson.h b/include/rapidjson/rapidjson.h index 0c41ab6..b06e82b 100644 --- a/include/rapidjson/rapidjson.h +++ b/include/rapidjson/rapidjson.h @@ -241,8 +241,12 @@ alignment. User can customize by defining the RAPIDJSON_ALIGN function macro., */ #ifndef RAPIDJSON_ALIGN +#if RAPIDJSON_64BIT == 1 +#define RAPIDJSON_ALIGN(x) ((x + 7u) & ~7u) +#else #define RAPIDJSON_ALIGN(x) ((x + 3u) & ~3u) #endif +#endif /////////////////////////////////////////////////////////////////////////////// // RAPIDJSON_UINT64_C2 From 97d489c247918fd127fe410a6c39e05bc2b71719 Mon Sep 17 00:00:00 2001 From: Justin Scheiber Date: Tue, 5 May 2015 13:42:06 -0600 Subject: [PATCH 074/189] fix shadow warnings on gcc 4.8 (-Wshadow) --- include/rapidjson/internal/ieee754.h | 30 ++++++++++++++-------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/include/rapidjson/internal/ieee754.h b/include/rapidjson/internal/ieee754.h index 9a82880..e1e1008 100644 --- a/include/rapidjson/internal/ieee754.h +++ b/include/rapidjson/internal/ieee754.h @@ -23,29 +23,29 @@ namespace internal { class Double { public: Double() {} - Double(double d) : d(d) {} - Double(uint64_t u) : u(u) {} + Double(double d) : d_(d) {} + Double(uint64_t u) : u_(u) {} - double Value() const { return d; } - uint64_t Uint64Value() const { return u; } + double Value() const { return d_; } + uint64_t Uint64Value() const { return u_; } double NextPositiveDouble() const { RAPIDJSON_ASSERT(!Sign()); - return Double(u + 1).Value(); + return Double(u_ + 1).Value(); } - bool Sign() const { return (u & kSignMask) != 0; } - uint64_t Significand() const { return u & kSignificandMask; } - int Exponent() const { return ((u & kExponentMask) >> kSignificandSize) - kExponentBias; } + bool Sign() const { return (u_ & kSignMask) != 0; } + uint64_t Significand() const { return u_ & kSignificandMask; } + int Exponent() const { return ((u_ & kExponentMask) >> kSignificandSize) - kExponentBias; } - bool IsNan() const { return (u & kExponentMask) == kExponentMask && Significand() != 0; } - bool IsInf() const { return (u & kExponentMask) == kExponentMask && Significand() == 0; } - bool IsNormal() const { return (u & kExponentMask) != 0 || Significand() == 0; } - bool IsZero() const { return (u & (kExponentMask | kSignificandMask)) == 0; } + bool IsNan() const { return (u_ & kExponentMask) == kExponentMask && Significand() != 0; } + bool IsInf() const { return (u_ & kExponentMask) == kExponentMask && Significand() == 0; } + bool IsNormal() const { return (u_ & kExponentMask) != 0 || Significand() == 0; } + bool IsZero() const { return (u_ & (kExponentMask | kSignificandMask)) == 0; } uint64_t IntegerSignificand() const { return IsNormal() ? Significand() | kHiddenBit : Significand(); } int IntegerExponent() const { return (IsNormal() ? Exponent() : kDenormalExponent) - kSignificandSize; } - uint64_t ToBias() const { return (u & kSignMask) ? ~u + 1 : u | kSignMask; } + uint64_t ToBias() const { return (u_ & kSignMask) ? ~u_ + 1 : u_ | kSignMask; } static unsigned EffectiveSignificandSize(int order) { if (order >= -1021) @@ -66,8 +66,8 @@ private: static const uint64_t kHiddenBit = RAPIDJSON_UINT64_C2(0x00100000, 0x00000000); union { - double d; - uint64_t u; + double d_; + uint64_t u_; }; }; From 050be06e52f6e667ee246698f0e84c077a11f41b Mon Sep 17 00:00:00 2001 From: Justin Scheiber Date: Tue, 5 May 2015 14:37:18 -0600 Subject: [PATCH 075/189] fixing conversion warnings --- include/rapidjson/internal/biginteger.h | 4 ++-- include/rapidjson/internal/diyfp.h | 4 ++-- include/rapidjson/internal/ieee754.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/rapidjson/internal/biginteger.h b/include/rapidjson/internal/biginteger.h index 5baba9b..99a30ac 100755 --- a/include/rapidjson/internal/biginteger.h +++ b/include/rapidjson/internal/biginteger.h @@ -97,7 +97,7 @@ public: if (u == 1) return *this; if (*this == 1) return *this = u; - uint32_t k = 0; + uint64_t k = 0; for (size_t i = 0; i < count_; i++) { const uint64_t c = digits_[i] >> 32; const uint64_t d = digits_[i] & 0xFFFFFFFF; @@ -246,7 +246,7 @@ private: __extension__ typedef unsigned __int128 uint128; uint128 p = static_cast(a) * static_cast(b); p += k; - *outHigh = p >> 64; + *outHigh = static_cast(p >> 64); return static_cast(p); #else const uint64_t a0 = a & 0xFFFFFFFF, a1 = a >> 32, b0 = b & 0xFFFFFFFF, b1 = b >> 32; diff --git a/include/rapidjson/internal/diyfp.h b/include/rapidjson/internal/diyfp.h index 4ef53d9..3b6c423 100644 --- a/include/rapidjson/internal/diyfp.h +++ b/include/rapidjson/internal/diyfp.h @@ -45,7 +45,7 @@ struct DiyFp { uint64_t u64; } u = { d }; - int biased_e = (u.u64 & kDpExponentMask) >> kDpSignificandSize; + int biased_e = static_cast((u.u64 & kDpExponentMask) >> kDpSignificandSize); uint64_t significand = (u.u64 & kDpSignificandMask); if (biased_e != 0) { f = significand + kDpHiddenBit; @@ -71,7 +71,7 @@ struct DiyFp { #elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__) __extension__ typedef unsigned __int128 uint128; uint128 p = static_cast(f) * static_cast(rhs.f); - uint64_t h = p >> 64; + uint64_t h = static_cast(p >> 64); uint64_t l = static_cast(p); if (l & (uint64_t(1) << 63)) // rounding h++; diff --git a/include/rapidjson/internal/ieee754.h b/include/rapidjson/internal/ieee754.h index e1e1008..e3f0336 100644 --- a/include/rapidjson/internal/ieee754.h +++ b/include/rapidjson/internal/ieee754.h @@ -36,7 +36,7 @@ public: bool Sign() const { return (u_ & kSignMask) != 0; } uint64_t Significand() const { return u_ & kSignificandMask; } - int Exponent() const { return ((u_ & kExponentMask) >> kSignificandSize) - kExponentBias; } + int Exponent() const { return static_cast(((u_ & kExponentMask) >> kSignificandSize) - kExponentBias); } bool IsNan() const { return (u_ & kExponentMask) == kExponentMask && Significand() != 0; } bool IsInf() const { return (u_ & kExponentMask) == kExponentMask && Significand() == 0; } From d0c37814563cd842f7ee7638ad07e7c678032113 Mon Sep 17 00:00:00 2001 From: Justin Scheiber Date: Tue, 5 May 2015 15:33:31 -0600 Subject: [PATCH 076/189] add -Werror for clang and gcc --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 380bdcd..bc1c358 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,9 +26,9 @@ if(RAPIDJSON_HAS_STDSTRING) endif() if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native -Wall -Wextra") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native -Wall -Wextra -Werror") elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native -Wall -Wextra") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native -Wall -Wextra -Werror") elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") add_definitions(-D_CRT_SECURE_NO_WARNINGS=1) endif() From f7c184d36a45245942abe06889875ed6a57b7611 Mon Sep 17 00:00:00 2001 From: Justin Scheiber Date: Tue, 5 May 2015 18:02:03 -0600 Subject: [PATCH 077/189] Revert "add -Werror for clang and gcc" This reverts commit d0c37814563cd842f7ee7638ad07e7c678032113. --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index bc1c358..380bdcd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,9 +26,9 @@ if(RAPIDJSON_HAS_STDSTRING) endif() if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native -Wall -Wextra -Werror") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native -Wall -Wextra") elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native -Wall -Wextra -Werror") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native -Wall -Wextra") elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") add_definitions(-D_CRT_SECURE_NO_WARNINGS=1) endif() From a72c35b9fa881a4c3eb8d8a5f9479dd332c44220 Mon Sep 17 00:00:00 2001 From: miloyip Date: Wed, 6 May 2015 10:49:01 +0800 Subject: [PATCH 078/189] Workaround for Valgrind false alarm on wcscmp() --- test/unittest/documenttest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unittest/documenttest.cpp b/test/unittest/documenttest.cpp index 7e5d766..940b295 100644 --- a/test/unittest/documenttest.cpp +++ b/test/unittest/documenttest.cpp @@ -276,7 +276,7 @@ TEST(Document, UTF16_Document) { GenericValue< UTF16<> >& s = v[L"created_at"]; ASSERT_TRUE(s.IsString()); - EXPECT_EQ(0, wcscmp(L"Wed Oct 30 17:13:20 +0000 2012", s.GetString())); + EXPECT_EQ(0, memcmp(L"Wed Oct 30 17:13:20 +0000 2012", s.GetString(), (s.GetStringLength() + 1) * sizeof(wchar_t))); } #if RAPIDJSON_HAS_CXX11_RVALUE_REFS From 5be9b6e584656bbc94d894887ded663442a024fb Mon Sep 17 00:00:00 2001 From: Justin Scheiber Date: Tue, 5 May 2015 22:41:35 -0600 Subject: [PATCH 079/189] update the submodule fore google test --- .gitmodules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitmodules b/.gitmodules index b54b211..25460de 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ [submodule "thirdparty/gtest"] path = thirdparty/gtest - url = ssh://git@git.eyesopen.com/common/rapidjson.git + url = ssh://git@git.eyesopen.com/common/googletest.git From 5dee394004088cbfac1ecc80102a8353c0db8281 Mon Sep 17 00:00:00 2001 From: Milo Yip Date: Fri, 8 May 2015 21:26:56 +0800 Subject: [PATCH 080/189] Add Pointer::Append() and fixed bugs in assignment and Parse() --- include/rapidjson/pointer.h | 153 ++++++++++++++++++++++++++++------ test/unittest/pointertest.cpp | 40 +++++++++ 2 files changed, 168 insertions(+), 25 deletions(-) diff --git a/include/rapidjson/pointer.h b/include/rapidjson/pointer.h index b68829c..adb819e 100644 --- a/include/rapidjson/pointer.h +++ b/include/rapidjson/pointer.h @@ -16,6 +16,7 @@ #define RAPIDJSON_POINTER_H_ #include "document.h" +#include "internal/itoa.h" RAPIDJSON_NAMESPACE_BEGIN @@ -169,38 +170,109 @@ public: //! Assignment operator. GenericPointer& operator=(const GenericPointer& rhs) { - this->~GenericPointer(); + if (this != &rhs) { + // Do not delete ownAllcator + if (nameBuffer_) { + Allocator::Free(nameBuffer_); + Allocator::Free(tokens_); + } - tokenCount_ = rhs.tokenCount_; - parseErrorOffset_ = rhs.parseErrorOffset_; - parseErrorCode_ = rhs.parseErrorCode_; + tokenCount_ = rhs.tokenCount_; + parseErrorOffset_ = rhs.parseErrorOffset_; + parseErrorCode_ = rhs.parseErrorCode_; - if (rhs.nameBuffer_) { // Normally parsed tokens. - if (!allocator_) // allocator is independently owned. - ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator()); - - size_t nameBufferSize = tokenCount_; // null terminators for tokens - for (Token *t = rhs.tokens_; t != rhs.tokens_ + tokenCount_; ++t) - nameBufferSize += t->length; - nameBuffer_ = (Ch*)allocator_->Malloc(nameBufferSize * sizeof(Ch)); - std::memcpy(nameBuffer_, rhs.nameBuffer_, nameBufferSize * sizeof(Ch)); - - tokens_ = (Token*)allocator_->Malloc(tokenCount_ * sizeof(Token)); - std::memcpy(tokens_, rhs.tokens_, tokenCount_ * sizeof(Token)); - - // Adjust pointers to name buffer - std::ptrdiff_t diff = nameBuffer_ - rhs.nameBuffer_; - for (Token *t = rhs.tokens_; t != rhs.tokens_ + tokenCount_; ++t) - t->name += diff; + if (rhs.nameBuffer_) + CopyFromRaw(rhs); // Normally parsed tokens. + else { + tokens_ = rhs.tokens_; // User supplied const tokens. + nameBuffer_ = 0; + } } - else - tokens_ = rhs.tokens_; // User supplied const tokens. - return *this; } //@} + //!@name Append token + //@{ + + //! Append a token and return a new Pointer + /*! + \param token Token to be appended. + \param allocator Allocator for the newly return Pointer. + \return A new Pointer with appended token. + */ + GenericPointer Append(const Token& token, Allocator* allocator = 0) const { + GenericPointer r; + r.allocator_ = allocator; + Ch *p = r.CopyFromRaw(*this, 1, (token.length + 1) * sizeof(Ch)); + std::memcpy(p, token.name, (token.length + 1) * sizeof(Ch)); + r.tokens_[tokenCount_].name = p; + r.tokens_[tokenCount_].length = token.length; + r.tokens_[tokenCount_].index = token.index; + return r; + } + + //! Append a name token with length, and return a new Pointer + /*! + \param name Name to be appended. + \param length Length of name. + \param allocator Allocator for the newly return Pointer. + \return A new Pointer with appended token. + */ + GenericPointer Append(const Ch* name, SizeType length, Allocator* allocator = 0) const { + Token token = { name, length, kPointerInvalidIndex }; + return Append(token, allocator); + } + + //! Append a name token without length, and return a new Pointer + /*! + \param name Name (const Ch*) to be appended. + \param allocator Allocator for the newly return Pointer. + \return A new Pointer with appended token. + */ + template + RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr::Type, Ch> >), (GenericPointer)) + Append(T* name, Allocator* allocator = 0) const { + return Append(name, StrLen(name), allocator); + } + +#if RAPIDJSON_HAS_STDSTRING + //! Append a name token, and return a new Pointer + /*! + \param name Name to be appended. + \param allocator Allocator for the newly return Pointer. + \return A new Pointer with appended token. + */ + GenericPointer Append(const std::basic_string& name, Allocator* allocator = 0) const { + return Append(name.c_str(), static_cast(name.size()), allocator); + } +#endif + + //! Append a index token, and return a new Pointer + /*! + \param index Index to be appended. + \param allocator Allocator for the newly return Pointer. + \return A new Pointer with appended token. + */ + GenericPointer Append(SizeType index, Allocator* allocator = 0) const { + char buffer[21]; + SizeType length = (sizeof(SizeType) == 4 ? internal::u32toa(index, buffer): internal::u64toa(index, buffer)) - buffer; + buffer[length] = '\0'; + + if (sizeof(Ch) == 1) { + Token token = { (Ch*)buffer, length, index }; + return Append(token, allocator); + } + else { + Ch name[21]; + for (size_t i = 0; i <= length; i++) + name[i] = buffer[i]; + Token token = { name, length, index }; + return Append(token, allocator); + } + } + //!@name Handling Parse Error //@{ @@ -240,7 +312,7 @@ public: for (size_t i = 0; i < tokenCount_; i++) { if (tokens_[i].index != rhs.tokens_[i].index || tokens_[i].length != rhs.tokens_[i].length || - 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; } @@ -633,6 +705,35 @@ public: } private: + //! Clone the content from rhs to this. + /*! + \param rhs Source pointer. + \param extraToken Extra tokens to be allocated. + \param extraNameBufferSize Extra name buffer size to be allocated. + \return Start of non-occupied name buffer, for storing extra names. + */ + Ch* CopyFromRaw(const GenericPointer& rhs, size_t extraToken = 0, size_t extraNameBufferSize = 0) { + if (!allocator_) // allocator is independently owned. + ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator()); + + size_t nameBufferSize = rhs.tokenCount_; // null terminators for tokens + for (Token *t = rhs.tokens_; t != rhs.tokens_ + rhs.tokenCount_; ++t) + nameBufferSize += t->length; + nameBuffer_ = (Ch*)allocator_->Malloc(nameBufferSize * sizeof(Ch)+extraNameBufferSize); + std::memcpy(nameBuffer_, rhs.nameBuffer_, nameBufferSize * sizeof(Ch)); + + tokenCount_ = rhs.tokenCount_ + extraToken; + tokens_ = (Token*)allocator_->Malloc(tokenCount_ * sizeof(Token)); + std::memcpy(tokens_, rhs.tokens_, rhs.tokenCount_ * sizeof(Token)); + + // Adjust pointers to name buffer + std::ptrdiff_t diff = nameBuffer_ - rhs.nameBuffer_; + for (Token *t = tokens_; t != tokens_ + rhs.tokenCount_; ++t) + t->name += diff; + + return nameBuffer_ + nameBufferSize * sizeof(Ch); + } + //! Check whether a character should be percent-encoded. /*! According to RFC 3986 2.3 Unreserved Characters. @@ -740,6 +841,8 @@ private: *name++ = c; } token.length = name - token.name; + if (token.length == 0) + isNumber = false; *name++ = '\0'; // Null terminator // Second check for index: more than one digit cannot have leading zero diff --git a/test/unittest/pointertest.cpp b/test/unittest/pointertest.cpp index cf2ab72..cb36330 100644 --- a/test/unittest/pointertest.cpp +++ b/test/unittest/pointertest.cpp @@ -39,12 +39,22 @@ TEST(Pointer, Parse) { EXPECT_EQ(0u, p.GetTokenCount()); } + { + Pointer p("/"); + EXPECT_TRUE(p.IsValid()); + EXPECT_EQ(1u, p.GetTokenCount()); + EXPECT_EQ(0u, p.GetTokens()[0].length); + EXPECT_STREQ("", p.GetTokens()[0].name); + EXPECT_EQ(kPointerInvalidIndex, p.GetTokens()[0].index); + } + { Pointer p("/foo"); EXPECT_TRUE(p.IsValid()); EXPECT_EQ(1u, p.GetTokenCount()); EXPECT_EQ(3u, p.GetTokens()[0].length); EXPECT_STREQ("foo", p.GetTokens()[0].name); + EXPECT_EQ(kPointerInvalidIndex, p.GetTokens()[0].index); } #if RAPIDJSON_HAS_STDSTRING @@ -54,6 +64,7 @@ TEST(Pointer, Parse) { EXPECT_EQ(1u, p.GetTokenCount()); EXPECT_EQ(3u, p.GetTokens()[0].length); EXPECT_STREQ("foo", p.GetTokens()[0].name); + EXPECT_EQ(kPointerInvalidIndex, p.GetTokens()[0].index); } #endif @@ -63,6 +74,7 @@ TEST(Pointer, Parse) { EXPECT_EQ(2u, p.GetTokenCount()); EXPECT_EQ(3u, p.GetTokens()[0].length); EXPECT_STREQ("foo", p.GetTokens()[0].name); + EXPECT_EQ(kPointerInvalidIndex, p.GetTokens()[0].index); EXPECT_EQ(1u, p.GetTokens()[1].length); EXPECT_STREQ("0", p.GetTokens()[1].name); EXPECT_EQ(0u, p.GetTokens()[1].index); @@ -481,6 +493,14 @@ TEST(Pointer, Assignment) { EXPECT_EQ(1u, q.GetTokens()[1].length); EXPECT_STREQ("0", q.GetTokens()[1].name); EXPECT_EQ(0u, q.GetTokens()[1].index); + q = q; + EXPECT_TRUE(q.IsValid()); + EXPECT_EQ(2u, q.GetTokenCount()); + EXPECT_EQ(3u, q.GetTokens()[0].length); + EXPECT_STREQ("foo", q.GetTokens()[0].name); + EXPECT_EQ(1u, q.GetTokens()[1].length); + EXPECT_STREQ("0", q.GetTokens()[1].name); + EXPECT_EQ(0u, q.GetTokens()[1].index); } // Static tokens @@ -498,6 +518,26 @@ TEST(Pointer, Assignment) { } } +TEST(Pointer, Append) { + { + Pointer p; + Pointer q = p.Append("foo"); + EXPECT_TRUE(Pointer("/foo") == q); + q = q.Append(0); + EXPECT_TRUE(Pointer("/foo/0") == q); + q = q.Append(""); + EXPECT_TRUE(Pointer("/foo/0/") == q); + } + +#if RAPIDJSON_HAS_STDSTRING + { + Pointer p; + Pointer q = p.Append(std::string("foo")); + EXPECT_TRUE(Pointer("/foo") == q); + } +#endif +} + TEST(Pointer, Equality) { EXPECT_TRUE(Pointer("/foo/0") == Pointer("/foo/0")); EXPECT_FALSE(Pointer("/foo/0") == Pointer("/foo/1")); From 771fa9879a8c290e34a53bb8e9374119f76e4d2d Mon Sep 17 00:00:00 2001 From: miloyip Date: Fri, 8 May 2015 22:18:46 +0800 Subject: [PATCH 081/189] Add Pointer::Append(Value, Allocator) overload --- include/rapidjson/pointer.h | 15 +++++++++++++++ test/unittest/pointertest.cpp | 16 +++++++++++++--- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/include/rapidjson/pointer.h b/include/rapidjson/pointer.h index adb819e..a8d0094 100644 --- a/include/rapidjson/pointer.h +++ b/include/rapidjson/pointer.h @@ -273,6 +273,21 @@ public: } } + //! Append a token by value, and return a new Pointer + /*! + \param value Value (either Uint or String) to be appended. + \param allocator Allocator for the newly return Pointer. + \return A new Pointer with appended token. + */ + GenericPointer Append(const ValueType& token, Allocator* allocator = 0) const { + if (token.IsString()) + return Append(token.GetString(), token.GetStringLength(), allocator); + else { + RAPIDJSON_ASSERT(token.IsUint64()); + return Append(static_cast(token.GetUint64()), allocator); + } + } + //!@name Handling Parse Error //@{ diff --git a/test/unittest/pointertest.cpp b/test/unittest/pointertest.cpp index cb36330..0e050c0 100644 --- a/test/unittest/pointertest.cpp +++ b/test/unittest/pointertest.cpp @@ -523,10 +523,20 @@ TEST(Pointer, Append) { Pointer p; Pointer q = p.Append("foo"); EXPECT_TRUE(Pointer("/foo") == q); - q = q.Append(0); - EXPECT_TRUE(Pointer("/foo/0") == q); + q = q.Append(1234); + EXPECT_TRUE(Pointer("/foo/1234") == q); q = q.Append(""); - EXPECT_TRUE(Pointer("/foo/0/") == q); + EXPECT_TRUE(Pointer("/foo/1234/") == q); + } + + { + Pointer p; + Pointer q = p.Append(Value("foo").Move()); + EXPECT_TRUE(Pointer("/foo") == q); + q = q.Append(Value(1234).Move()); + EXPECT_TRUE(Pointer("/foo/1234") == q); + q = q.Append(Value(kStringType).Move()); + EXPECT_TRUE(Pointer("/foo/1234/") == q); } #if RAPIDJSON_HAS_STDSTRING From 63a1db0907bdc58e1d942bcd28c89afaa1dd91ba Mon Sep 17 00:00:00 2001 From: miloyip Date: Sat, 9 May 2015 08:38:27 +0800 Subject: [PATCH 082/189] Fix a bug in Pointer --- include/rapidjson/pointer.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/include/rapidjson/pointer.h b/include/rapidjson/pointer.h index a8d0094..8dc69df 100644 --- a/include/rapidjson/pointer.h +++ b/include/rapidjson/pointer.h @@ -205,7 +205,7 @@ public: GenericPointer Append(const Token& token, Allocator* allocator = 0) const { GenericPointer r; r.allocator_ = allocator; - Ch *p = r.CopyFromRaw(*this, 1, (token.length + 1) * sizeof(Ch)); + Ch *p = r.CopyFromRaw(*this, 1, token.length + 1); std::memcpy(p, token.name, (token.length + 1) * sizeof(Ch)); r.tokens_[tokenCount_].name = p; r.tokens_[tokenCount_].length = token.length; @@ -284,6 +284,7 @@ public: return Append(token.GetString(), token.GetStringLength(), allocator); else { RAPIDJSON_ASSERT(token.IsUint64()); + RAPIDJSON_ASSERT(token.GetUint64() <= SizeType(~0)); return Append(static_cast(token.GetUint64()), allocator); } } @@ -724,7 +725,7 @@ private: /*! \param rhs Source pointer. \param extraToken Extra tokens to be allocated. - \param extraNameBufferSize Extra name buffer size to be allocated. + \param extraNameBufferSize Extra name buffer size (in number of Ch) to be allocated. \return Start of non-occupied name buffer, for storing extra names. */ Ch* CopyFromRaw(const GenericPointer& rhs, size_t extraToken = 0, size_t extraNameBufferSize = 0) { @@ -734,7 +735,7 @@ private: size_t nameBufferSize = rhs.tokenCount_; // null terminators for tokens for (Token *t = rhs.tokens_; t != rhs.tokens_ + rhs.tokenCount_; ++t) nameBufferSize += t->length; - nameBuffer_ = (Ch*)allocator_->Malloc(nameBufferSize * sizeof(Ch)+extraNameBufferSize); + nameBuffer_ = (Ch*)allocator_->Malloc((nameBufferSize + extraNameBufferSize) * sizeof(Ch)); std::memcpy(nameBuffer_, rhs.nameBuffer_, nameBufferSize * sizeof(Ch)); tokenCount_ = rhs.tokenCount_ + extraToken; @@ -746,7 +747,7 @@ private: for (Token *t = tokens_; t != tokens_ + rhs.tokenCount_; ++t) t->name += diff; - return nameBuffer_ + nameBufferSize * sizeof(Ch); + return nameBuffer_ + nameBufferSize; } //! Check whether a character should be percent-encoded. From 3dc40a8f3452c8e97790e927e751712c23f115ed Mon Sep 17 00:00:00 2001 From: miloyip Date: Sun, 10 May 2015 22:54:47 +0800 Subject: [PATCH 083/189] Fix MemoryPoolAllocator::Clear() to clear user-buffer --- include/rapidjson/allocators.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/rapidjson/allocators.h b/include/rapidjson/allocators.h index b7042a5..f615ffd 100644 --- a/include/rapidjson/allocators.h +++ b/include/rapidjson/allocators.h @@ -143,11 +143,13 @@ public: //! Deallocates all memory chunks, excluding the user-supplied buffer. void Clear() { - while(chunkHead_ != 0 && chunkHead_ != userBuffer_) { + while (chunkHead_ && chunkHead_ != userBuffer_) { ChunkHeader* next = chunkHead_->next; baseAllocator_->Free(chunkHead_); chunkHead_ = next; } + if (chunkHead_ && chunkHead_ == userBuffer_) + chunkHead_->size = 0; // Clear user buffer } //! Computes the total capacity of allocated memory chunks. From 98b66e3c5ab92fd63ea2663d989dd1a933f587c5 Mon Sep 17 00:00:00 2001 From: miloyip Date: Sun, 10 May 2015 23:26:58 +0800 Subject: [PATCH 084/189] Change Document::ParseStream() to use stack allocator for Reader --- include/rapidjson/document.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/rapidjson/document.h b/include/rapidjson/document.h index 7386773..aab489c 100644 --- a/include/rapidjson/document.h +++ b/include/rapidjson/document.h @@ -1741,7 +1741,7 @@ public: template GenericDocument& ParseStream(InputStream& is) { ValueType::SetNull(); // Remove existing root if exist - GenericReader reader(&GetAllocator()); + GenericReader reader(&stack_.GetAllocator()); ClearStackOnExit scope(*this); parseResult_ = reader.template Parse(is, *this); if (parseResult_) { From 0edd743c83e4e08523bca8a122fddb20ece27721 Mon Sep 17 00:00:00 2001 From: Milo Yip Date: Mon, 11 May 2015 11:03:50 +0800 Subject: [PATCH 085/189] Fix Document.UserBuffer test --- test/unittest/documenttest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unittest/documenttest.cpp b/test/unittest/documenttest.cpp index 940b295..2ee6b10 100644 --- a/test/unittest/documenttest.cpp +++ b/test/unittest/documenttest.cpp @@ -241,7 +241,7 @@ TEST(Document, UserBuffer) { char parseBuffer[1024]; MemoryPoolAllocator<> valueAllocator(valueBuffer, sizeof(valueBuffer)); MemoryPoolAllocator<> parseAllocator(parseBuffer, sizeof(parseBuffer)); - DocumentType doc(&valueAllocator, sizeof(parseBuffer), &parseAllocator); + DocumentType doc(&valueAllocator, sizeof(parseBuffer) / 2, &parseAllocator); doc.Parse(" { \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3, 4] } "); EXPECT_FALSE(doc.HasParseError()); EXPECT_LE(valueAllocator.Size(), sizeof(valueBuffer)); From 7eb117a26ecbd36eb9fa1c83df7d4f58dd5365d6 Mon Sep 17 00:00:00 2001 From: miloyip Date: Mon, 11 May 2015 21:41:26 +0800 Subject: [PATCH 086/189] Reduce Pointer parsing/copying to single allocation --- include/rapidjson/pointer.h | 43 +++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 23 deletions(-) diff --git a/include/rapidjson/pointer.h b/include/rapidjson/pointer.h index 8dc69df..13e688e 100644 --- a/include/rapidjson/pointer.h +++ b/include/rapidjson/pointer.h @@ -161,10 +161,8 @@ public: //! Destructor. ~GenericPointer() { - if (nameBuffer_) { // If user-supplied tokens constructor is used, nameBuffer_ is nullptr and tokens_ are not deallocated. - Allocator::Free(nameBuffer_); + if (nameBuffer_) // If user-supplied tokens constructor is used, nameBuffer_ is nullptr and tokens_ are not deallocated. Allocator::Free(tokens_); - } RAPIDJSON_DELETE(ownAllocator_); } @@ -172,10 +170,8 @@ public: GenericPointer& operator=(const GenericPointer& rhs) { if (this != &rhs) { // Do not delete ownAllcator - if (nameBuffer_) { - Allocator::Free(nameBuffer_); + if (nameBuffer_) Allocator::Free(tokens_); - } tokenCount_ = rhs.tokenCount_; parseErrorOffset_ = rhs.parseErrorOffset_; @@ -735,12 +731,12 @@ private: size_t nameBufferSize = rhs.tokenCount_; // null terminators for tokens for (Token *t = rhs.tokens_; t != rhs.tokens_ + rhs.tokenCount_; ++t) nameBufferSize += t->length; - nameBuffer_ = (Ch*)allocator_->Malloc((nameBufferSize + extraNameBufferSize) * sizeof(Ch)); - std::memcpy(nameBuffer_, rhs.nameBuffer_, nameBufferSize * sizeof(Ch)); tokenCount_ = rhs.tokenCount_ + extraToken; - tokens_ = (Token*)allocator_->Malloc(tokenCount_ * sizeof(Token)); + tokens_ = static_cast(allocator_->Malloc(tokenCount_ * sizeof(Token) + (nameBufferSize + extraNameBufferSize) * sizeof(Ch))); + nameBuffer_ = reinterpret_cast(tokens_ + tokenCount_); std::memcpy(tokens_, rhs.tokens_, rhs.tokenCount_ * sizeof(Token)); + std::memcpy(nameBuffer_, rhs.nameBuffer_, nameBufferSize * sizeof(Ch)); // Adjust pointers to name buffer std::ptrdiff_t diff = nameBuffer_ - rhs.nameBuffer_; @@ -774,11 +770,14 @@ private: if (!allocator_) ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator()); - // Create a buffer as same size of source - nameBuffer_ = (Ch*)allocator_->Malloc(length * sizeof(Ch)); - tokens_ = (Token*)allocator_->Malloc(length * sizeof(Token)); // Maximum possible tokens in the source + // Count number of '/' as tokenCount tokenCount_ = 0; - Ch* name = nameBuffer_; + for (const Ch* s = source; s != source + length; s++) + if (*s == '/') + tokenCount_++; + + Token* token = tokens_ = static_cast(allocator_->Malloc(tokenCount_ * sizeof(Token) + length * sizeof(Ch))); + Ch* name = nameBuffer_ = reinterpret_cast(tokens_ + tokenCount_); size_t i = 0; // Detect if it is a URI fragment @@ -797,8 +796,7 @@ private: RAPIDJSON_ASSERT(source[i] == '/'); i++; // consumes '/' - Token& token = tokens_[tokenCount_++]; - token.name = name; + token->name = name; bool isNumber = true; while (i < length && source[i] != '/') { @@ -856,20 +854,20 @@ private: *name++ = c; } - token.length = name - token.name; - if (token.length == 0) + token->length = name - token->name; + if (token->length == 0) isNumber = false; *name++ = '\0'; // Null terminator // Second check for index: more than one digit cannot have leading zero - if (isNumber && token.length > 1 && token.name[0] == '0') + if (isNumber && token->length > 1 && token->name[0] == '0') isNumber = false; // String to SizeType conversion SizeType n = 0; if (isNumber) { - for (size_t j = 0; j < token.length; j++) { - SizeType m = n * 10 + static_cast(token.name[j] - '0'); + for (size_t j = 0; j < token->length; j++) { + SizeType m = n * 10 + static_cast(token->name[j] - '0'); if (m < n) { // overflow detection isNumber = false; break; @@ -878,16 +876,15 @@ private: } } - token.index = isNumber ? n : kPointerInvalidIndex; + token->index = isNumber ? n : kPointerInvalidIndex; + token++; } RAPIDJSON_ASSERT(name <= nameBuffer_ + length); // Should not overflow buffer - tokens_ = (Token*)allocator_->Realloc(tokens_, length * sizeof(Token), tokenCount_ * sizeof(Token)); // Shrink tokens_ parseErrorCode_ = kPointerParseErrorNone; return; error: - Allocator::Free(nameBuffer_); Allocator::Free(tokens_); nameBuffer_ = 0; tokens_ = 0; From 89ad34cef44d864dbe3960829b6fc7da214a712f Mon Sep 17 00:00:00 2001 From: Phyks Date: Tue, 12 May 2015 00:23:50 +0200 Subject: [PATCH 087/189] Fix CMakeLists for include as a thirdparty in projects --- CMakeLists.txt | 6 +++--- CMakeModules/FindGTestSrc.cmake | 5 +++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 380bdcd..b757753 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) -SET(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/CMakeModules) +SET(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules) PROJECT(RapidJSON CXX) @@ -17,7 +17,7 @@ SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) option(RAPIDJSON_BUILD_DOC "Build rapidjson documentation." ON) option(RAPIDJSON_BUILD_EXAMPLES "Build rapidjson examples." ON) option(RAPIDJSON_BUILD_TESTS "Build rapidjson perftests and unittests." ON) -option(RAPIDJSON_BUILD_THIRDPARTY_GTEST +option(RAPIDJSON_BUILD_THIRDPARTY_GTEST "Use gtest installation in `thirdparty/gtest` by default if available" OFF) option(RAPIDJSON_HAS_STDSTRING "" OFF) @@ -45,7 +45,7 @@ ELSEIF(WIN32) ENDIF() SET(CMAKE_INSTALL_DIR "${_CMAKE_INSTALL_DIR}" CACHE PATH "The directory cmake fiels are installed in") -include_directories(${CMAKE_SOURCE_DIR}/include) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) if(RAPIDJSON_BUILD_DOC) add_subdirectory(doc) diff --git a/CMakeModules/FindGTestSrc.cmake b/CMakeModules/FindGTestSrc.cmake index b5abc19..f942a8d 100644 --- a/CMakeModules/FindGTestSrc.cmake +++ b/CMakeModules/FindGTestSrc.cmake @@ -1,7 +1,7 @@ -SET(GTEST_SEARCH_PATH +SET(GTEST_SEARCH_PATH "${GTEST_SOURCE_DIR}" - "${CMAKE_SOURCE_DIR}/thirdparty/gtest") + "${CMAKE_CURRENT_LIST_DIR}/../thirdparty/gtest") IF(UNIX) IF(RAPIDJSON_BUILD_THIRDPARTY_GTEST) @@ -15,6 +15,7 @@ FIND_PATH(GTEST_SOURCE_DIR NAMES CMakeLists.txt src/gtest_main.cc PATHS ${GTEST_SEARCH_PATH}) + # Debian installs gtest include directory in /usr/include, thus need to look # for include directory separately from source directory. FIND_PATH(GTEST_INCLUDE_DIR From 2786103abd16997af6c27079a8c11b4c430fcc99 Mon Sep 17 00:00:00 2001 From: miloyip Date: Tue, 12 May 2015 22:48:14 +0800 Subject: [PATCH 088/189] Add Value::XXXMember(...) overloads for std::string --- include/rapidjson/document.h | 50 ++++++++++++++++++++++++++++++++++++ test/unittest/valuetest.cpp | 22 ++++++++++++++++ 2 files changed, 72 insertions(+) diff --git a/include/rapidjson/document.h b/include/rapidjson/document.h index aab489c..ca80963 100644 --- a/include/rapidjson/document.h +++ b/include/rapidjson/document.h @@ -844,6 +844,12 @@ public: template const GenericValue& operator[](const GenericValue& name) const { return const_cast(*this)[name]; } +#if RAPIDJSON_HAS_STDSTRING + //! Get a value from an object associated with name (string object). + GenericValue& operator[](const std::basic_string& name) { return (*this)[GenericValue(StringRef(name))]; } + const GenericValue& operator[](const std::basic_string& name) const { return (*this)[GenericValue(StringRef(name))]; } +#endif + //! Const member iterator /*! \pre IsObject() == true */ ConstMemberIterator MemberBegin() const { RAPIDJSON_ASSERT(IsObject()); return ConstMemberIterator(data_.o.members); } @@ -867,6 +873,18 @@ public: */ bool HasMember(const Ch* name) const { return FindMember(name) != MemberEnd(); } +#if RAPIDJSON_HAS_STDSTRING + //! Check whether a member exists in the object with string object. + /*! + \param name Member name to be searched. + \pre IsObject() == true + \return Whether a member with that name exists. + \note It is better to use FindMember() directly if you need the obtain the value as well. + \note Linear time complexity. + */ + bool HasMember(const std::basic_string& name) const { return FindMember(name) != MemberEnd(); } +#endif + //! Check whether a member exists in the object with GenericValue name. /*! This version is faster because it does not need a StrLen(). It can also handle string with null character. @@ -923,6 +941,18 @@ public: } template ConstMemberIterator FindMember(const GenericValue& name) const { return const_cast(*this).FindMember(name); } +#if RAPIDJSON_HAS_STDSTRING + //! Find member by string object name. + /*! + \param name Member name to be searched. + \pre IsObject() == true + \return Iterator to member, if it exists. + Otherwise returns \ref MemberEnd(). + */ + MemberIterator FindMember(const std::basic_string& name) { return FindMember(StringRef(name)); } + ConstMemberIterator FindMember(const std::basic_string& name) const { return FindMember(StringRef(name)); } +#endif + //! Add a member (name-value pair) to the object. /*! \param name A string value as name of member. \param value Value of any type. @@ -969,6 +999,22 @@ public: return AddMember(name, v, allocator); } +#if RAPIDJSON_HAS_STDSTRING + //! Add a string object as member (name-value pair) to the object. + /*! \param name A string value as name of member. + \param value constant string reference as value of member. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \pre IsObject() + \note This overload is needed to avoid clashes with the generic primitive type AddMember(GenericValue&,T,Allocator&) overload below. + \note Amortized Constant time complexity. + */ + GenericValue& AddMember(GenericValue& name, std::basic_string& value, Allocator& allocator) { + GenericValue v(value, allocator); + return AddMember(name, v, allocator); + } +#endif + //! Add any primitive value as member (name-value pair) to the object. /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t \param name A string value as name of member. @@ -1087,6 +1133,10 @@ public: return RemoveMember(n); } +#if RAPIDJSON_HAS_STDSTRING + bool RemoveMember(const std::basic_string& name) { return RemoveMember(GenericValue(StringRef(name))); } +#endif + template bool RemoveMember(const GenericValue& name) { MemberIterator m = FindMember(name); diff --git a/test/unittest/valuetest.cpp b/test/unittest/valuetest.cpp index 1922222..5e142e1 100644 --- a/test/unittest/valuetest.cpp +++ b/test/unittest/valuetest.cpp @@ -957,6 +957,19 @@ TEST(Value, Object) { EXPECT_EQ(2u, o.MemberCount()); } +#if RAPIDJSON_HAS_STDSTRING + { + // AddMember(StringRefType, const std::string&, Allocator) + Value o(kObjectType); + o.AddMember("b", std::string("Banana"), allocator); + EXPECT_STREQ("Banana", o["b"].GetString()); + + // RemoveMember(const std::string&) + o.RemoveMember(std::string("b")); + EXPECT_TRUE(o.ObjectEmpty()); + } +#endif + #if RAPIDJSON_HAS_CXX11_RVALUE_REFS // AddMember(GenericValue&&, ...) variants { @@ -986,6 +999,10 @@ TEST(Value, Object) { EXPECT_TRUE(y.HasMember("A")); EXPECT_TRUE(y.HasMember("B")); +#if RAPIDJSON_HAS_STDSTRING + EXPECT_TRUE(x.HasMember(std::string("A"))); +#endif + name.SetString("C\0D"); EXPECT_TRUE(x.HasMember(name)); EXPECT_TRUE(y.HasMember(name)); @@ -1009,6 +1026,11 @@ TEST(Value, Object) { EXPECT_STREQ("Banana", y["B"].GetString()); EXPECT_STREQ("CherryD", y[C0D].GetString()); +#if RAPIDJSON_HAS_STDSTRING + EXPECT_STREQ("Apple", x["A"].GetString()); + EXPECT_STREQ("Apple", y[std::string("A")].GetString()); +#endif + // member iterator Value::MemberIterator itr = x.MemberBegin(); EXPECT_TRUE(itr != x.MemberEnd()); From 9c008b07ee16500b32c600bf8f428a6c4132b462 Mon Sep 17 00:00:00 2001 From: Phyks Date: Tue, 12 May 2015 20:15:06 +0200 Subject: [PATCH 089/189] Forgot to update the CMakeLists.txt in doc folder --- doc/CMakeLists.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index 4e49c5f..c1f165a 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -3,9 +3,9 @@ find_package(Doxygen) IF(NOT DOXYGEN_FOUND) MESSAGE(STATUS "No Doxygen found. Documentation won't be built") ELSE() - file(GLOB SOURCES ${CMAKE_SOURCE_DIR}/include/*) - file(GLOB MARKDOWN_DOC ${CMAKE_SOURCE_DIR}/doc/*.md) - list(APPEND MARKDOWN_DOC ${CMAKE_SOURCE_DIR}/readme.md) + file(GLOB SOURCES ${CMAKE_CURRENT_LIST_DIR}/../include/*) + file(GLOB MARKDOWN_DOC ${CMAKE_CURRENT_LIST_DIR}/../doc/*.md) + list(APPEND MARKDOWN_DOC ${CMAKE_CURRENT_LIST_DIR}/../readme.md) CONFIGURE_FILE(Doxyfile.in Doxyfile @ONLY) CONFIGURE_FILE(Doxyfile.zh-cn.in Doxyfile.zh-cn @ONLY) @@ -15,7 +15,7 @@ ELSE() COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile.zh-cn COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_BINARY_DIR}/html DEPENDS ${MARKDOWN_DOC} ${SOURCES} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile* - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/../ ) add_custom_target(doc ALL DEPENDS html) From add5a5058178a8c70c205ba89f385e39285ce429 Mon Sep 17 00:00:00 2001 From: Milo Yip Date: Thu, 14 May 2015 12:03:21 +0800 Subject: [PATCH 090/189] Fix some numbers parsed incorrectly Fix #340 --- include/rapidjson/internal/strtod.h | 7 +++++- test/unittest/readertest.cpp | 35 ++++++++++++++++++++++++++--- 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/include/rapidjson/internal/strtod.h b/include/rapidjson/internal/strtod.h index fa85286..ace65f6 100644 --- a/include/rapidjson/internal/strtod.h +++ b/include/rapidjson/internal/strtod.h @@ -191,8 +191,13 @@ inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosit DiyFp rounded(v.f >> precisionSize, v.e + precisionSize); const uint64_t precisionBits = (v.f & ((uint64_t(1) << precisionSize) - 1)) * kUlp; const uint64_t halfWay = (uint64_t(1) << (precisionSize - 1)) * kUlp; - if (precisionBits >= halfWay + error) + if (precisionBits >= halfWay + error) { rounded.f++; + if (rounded.f & (DiyFp::kDpHiddenBit << 1)) { // rounding overflows mantissa (issue #340) + rounded.f >>= 1; + rounded.e++; + } + } *result = rounded.ToDouble(); diff --git a/test/unittest/readertest.cpp b/test/unittest/readertest.cpp index bee19a8..9106063 100644 --- a/test/unittest/readertest.cpp +++ b/test/unittest/readertest.cpp @@ -193,7 +193,7 @@ static void TestParseDouble() { EXPECT_DOUBLE_EQ(x, h.actual_); \ } \ } - + TEST_DOUBLE(fullPrecision, "0.0", 0.0); TEST_DOUBLE(fullPrecision, "-0.0", -0.0); // For checking issue #289 TEST_DOUBLE(fullPrecision, "1.0", 1.0); @@ -327,15 +327,44 @@ static void TestParseDouble() { if (fullPrecision) { EXPECT_EQ(d.Uint64Value(), a.Uint64Value()); if (d.Uint64Value() != a.Uint64Value()) - printf(" String: %sn Actual: %.17gnExpected: %.17gn", buffer, h.actual_, d.Value()); + printf(" String: %s\n Actual: %.17g\nExpected: %.17g\n", buffer, h.actual_, d.Value()); } else { - EXPECT_EQ(d.Sign(), a.Sign()); /* for 0.0 != -0.0 */ + EXPECT_EQ(d.Sign(), a.Sign()); // for 0.0 != -0.0 EXPECT_DOUBLE_EQ(d.Value(), h.actual_); } } } } + + // Issue #340 + TEST_DOUBLE(fullPrecision, "7.450580596923828e-9", 7.450580596923828e-9); + { + internal::Double d(1.0); + for (int i = 0; i < 324; i++) { + char buffer[32]; + *internal::dtoa(d.Value(), buffer) = '\0'; + + StringStream s(buffer); + ParseDoubleHandler h; + Reader reader; + ASSERT_EQ(kParseErrorNone, reader.Parse(s, h).Code()); + EXPECT_EQ(1u, h.step_); + internal::Double a(h.actual_); + if (fullPrecision) { + EXPECT_EQ(d.Uint64Value(), a.Uint64Value()); + if (d.Uint64Value() != a.Uint64Value()) + printf(" String: %s\n Actual: %.17g\nExpected: %.17g\n", buffer, h.actual_, d.Value()); + } + else { + EXPECT_EQ(d.Sign(), a.Sign()); // for 0.0 != -0.0 + EXPECT_DOUBLE_EQ(d.Value(), h.actual_); + } + + + d = d.Value() * 0.5; + } + } #undef TEST_DOUBLE } From 0e9fe888b75a99db99d269eed6aa631073f6a7db Mon Sep 17 00:00:00 2001 From: Milo Yip Date: Thu, 14 May 2015 14:48:10 +0800 Subject: [PATCH 091/189] v1.0.2 release --- CHANGELOG.md | 13 ++++++++++++- CMakeLists.txt | 2 +- appveyor.yml | 2 +- include/rapidjson/rapidjson.h | 2 +- readme.md | 2 +- readme.zh-cn.md | 2 +- 6 files changed, 17 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 92a4054..080694c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,17 @@ This project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] +## [1.0.2] - 2015-05-14 + +### Fixed * Include rapidjson.h for all internal/error headers. +* Parsing some numbers incorrectly in full-precision mode (`kFullPrecisionParseFlag`) (#342) +* Fix alignment of 64bit platforms (#328) +* Fix MemoryPoolAllocator::Clear() to clear user-buffer (0691502573f1afd3341073dd24b12c3db20fbde4) + +### Changed +* CMakeLists for include as a thirdparty in projects (#334, #337) +* Change Document::ParseStream() to use stack allocator for Reader (ffbe38614732af8e0b3abdc8b50071f386a4a685) ## [1.0.1] - 2015-04-25 @@ -60,6 +70,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). ## 0.1 - 2011-11-18 -[Unreleased]: https://github.com/miloyip/rapidjson/compare/v1.0.1...HEAD +[Unreleased]: https://github.com/miloyip/rapidjson/compare/v1.0.2...HEAD +[1.0.2]: https://github.com/miloyip/rapidjson/compare/v1.0.1...v1.0.2 [1.0.1]: https://github.com/miloyip/rapidjson/compare/v1.0.0...v1.0.1 [1.0.0]: https://github.com/miloyip/rapidjson/compare/v1.0-beta...v1.0.0 diff --git a/CMakeLists.txt b/CMakeLists.txt index b757753..68139ba 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,7 +5,7 @@ PROJECT(RapidJSON CXX) set(LIB_MAJOR_VERSION "1") set(LIB_MINOR_VERSION "0") -set(LIB_PATCH_VERSION "1") +set(LIB_PATCH_VERSION "2") set(LIB_VERSION_STRING "${LIB_MAJOR_VERSION}.${LIB_MINOR_VERSION}.${LIB_PATCH_VERSION}") # compile in release with debug info mode by default diff --git a/appveyor.yml b/appveyor.yml index add4017..7d586e8 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,4 @@ -version: 1.0.1.{build} +version: 1.0.2.{build} configuration: - Debug diff --git a/include/rapidjson/rapidjson.h b/include/rapidjson/rapidjson.h index b06e82b..f5d5630 100644 --- a/include/rapidjson/rapidjson.h +++ b/include/rapidjson/rapidjson.h @@ -69,7 +69,7 @@ */ #define RAPIDJSON_MAJOR_VERSION 1 #define RAPIDJSON_MINOR_VERSION 0 -#define RAPIDJSON_PATCH_VERSION 1 +#define RAPIDJSON_PATCH_VERSION 2 #define RAPIDJSON_VERSION_STRING \ RAPIDJSON_STRINGIFY(RAPIDJSON_MAJOR_VERSION.RAPIDJSON_MINOR_VERSION.RAPIDJSON_PATCH_VERSION) diff --git a/readme.md b/readme.md index 98f81a7..19da386 100644 --- a/readme.md +++ b/readme.md @@ -1,6 +1,6 @@ ![](doc/logo/rapidjson.png) -![](https://img.shields.io/badge/release-v1.0.1-blue.png) +![](https://img.shields.io/badge/release-v1.0.2-blue.png) ## A fast JSON parser/generator for C++ with both SAX/DOM style API diff --git a/readme.zh-cn.md b/readme.zh-cn.md index eb6c21d..ec6bd90 100644 --- a/readme.zh-cn.md +++ b/readme.zh-cn.md @@ -1,6 +1,6 @@ ![](doc/logo/rapidjson.png) -![](https://img.shields.io/badge/release-v1.0.1-blue.png) +![](https://img.shields.io/badge/release-v1.0.2-blue.png) ## 高效的C++ JSONè§£æžï¼ç”Ÿæˆå™¨ï¼Œæä¾›SAXåŠDOM风格API From 3e56b0c35da0b6bb42efe88d673674a64d2d5098 Mon Sep 17 00:00:00 2001 From: Milo Yip Date: Thu, 14 May 2015 14:59:26 +0800 Subject: [PATCH 092/189] Add one more commit about std::string from master --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 080694c..8ad9b3c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,9 @@ This project adheres to [Semantic Versioning](http://semver.org/). ## [1.0.2] - 2015-05-14 +### Added +* Add Value::XXXMember(...) overloads for std::string (#335) + ### Fixed * Include rapidjson.h for all internal/error headers. * Parsing some numbers incorrectly in full-precision mode (`kFullPrecisionParseFlag`) (#342) From 302d1b735fb678201f5309c77d2c87477e1bef71 Mon Sep 17 00:00:00 2001 From: Milo Yip Date: Thu, 14 May 2015 16:56:52 +0800 Subject: [PATCH 093/189] Re-generate images in OSX --- doc/diagram/architecture.png | Bin 10989 -> 16569 bytes doc/diagram/insituparsing.png | Bin 24085 -> 37281 bytes .../iterative-parser-states-diagram.png | Bin 73681 -> 92378 bytes doc/diagram/move1.png | Bin 8181 -> 16081 bytes doc/diagram/move2.png | Bin 26753 -> 41517 bytes doc/diagram/move3.png | Bin 22630 -> 36371 bytes doc/diagram/normalparsing.png | Bin 22674 -> 32887 bytes doc/diagram/simpledom.png | Bin 24053 -> 43670 bytes doc/diagram/tutorial.png | Bin 33154 -> 44634 bytes doc/diagram/utilityclass.png | Bin 62311 -> 99993 bytes 10 files changed, 0 insertions(+), 0 deletions(-) diff --git a/doc/diagram/architecture.png b/doc/diagram/architecture.png index 05336df04563de8c57ad4bfda33560052a037519..556c7e729148cc37be23f083292e21954c12dd73 100644 GIT binary patch literal 16569 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 rhzkIC5D!i0-Q}EH2yB>cL$@q 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 QV-%qzuP#?CWAf^M0geNLSpWb4 diff --git a/doc/diagram/insituparsing.png b/doc/diagram/insituparsing.png index 27b2572d95671e2f125ff8eb9e557932e858e2a6..4400c88466a8fb5ec0774b72acd52bf41c670c6e 100644 GIT binary patch literal 37281 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 F0sxnWX08AL literal 24085 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 diff --git a/doc/diagram/iterative-parser-states-diagram.png b/doc/diagram/iterative-parser-states-diagram.png index 656f8e70331b665172261fcf65ff12beba88ead9..f315494db1d7b3a91ffef5eb395c0fc67e462d4c 100644 GIT binary patch literal 92378 zcmZU5by!qg+b@ix3_T#-UD8MiA}QU1bcb|FH_|QAt&~W2hm^D;NP~a^(j_GzXKmm2 zeBX7Q^Vc&E&g|K1?X~XvS8JlwRAjL+$S_b)P_X6Yq%}}bV5TT2cS;cVz+YbQz19Z* zL3PuRl|-o=r`SS45l4}imU!lcx|@T(NN9fb>A)Uu7@sXAl*K_qp-_@eU7@l55X17j z@m1#=`>6N3k`wO+I}7DlG2|Or6fM$jzMuc?I!WIY-4wOX%HSJ0_~VzmIhwI<6u@V_ zk!g2nsP*@9GcW8Z9XvD$iG)dtBM_*xNEVouHmm6^e7@k({r~=r26_W`8TuXCf3N=Y z*5DPqM0_IAjcs-4WB>h!+R!bs|9d6yCvjG!P60vA2UY0b#Y>SFJ5^ny?_^>|zZNO( zeXq3~8TI_`Z>?QvU=wh2`uyY*bzpkKjL|}Q-T0$oy#`yWf;a(Q_wA{gKz;j~usOez zF-88Drw_oTMv-bJ0i!DKi|N7t$iUU=jePg`PtF#c^zUL>4y%`MPgmG|cwXh0!bwo| zL8~k?FYxain`PI{S=Qz82-gTfqpH|t-!*tyY%^J0tXpSQY}n>;)*SuVHV&Ez8WEUA zPpx_3V=(SW8kkOlkSP>*QN0w8=vG`;*NsKi(0PRCWEGAI*F6o$aOD#wZVm zUOhLZh{wYUy@qHS1+rRjsUm4{1s&Fj=ikBXdc}7qJo)>gSSiD-SUJmzu)xrB>Dxo6 z<;7>E8vQ4o)zM?=JiYA~YcbP49^I&D>1TTjS>LoZ$KPz4lu6JcrQn63{fC9N3X(KY zh->iVta?JxwNZPOXX~t0>xP)J;P?9VojNQB5~!WD%XLie;ZVHrm^F>){-Z4mzFqo0 zDy!*)s1sQOxGhfj#(0k1(>OBA$kRvL?+cXT$oLKPC%N9$<2`s9B<5n=%!NLFdvpGM z1a>lG9O$pv=HWp8M7z#v>^F8%x&Qf+=U5~jy;6tIX*qA|jtlG9uQG5|ba60Pm`ZIi z3w$jaC3@=d`J(y8SeA9X=&>Amp4ObflZ%x*CmUH#^XZidVt)qh+m8mcKhg;WRy0i4 z)|gp5eH47@$EjP}$7XAxjIa7sEg(z4!G7AJxO1?(k4?~h`&k)5qr-y0WThS#ccU*_F@1zI2`anZjFE4}*0-{>t@#GK`3$f)1vid9Q43bJA4hLZmA)B^ zx1X&xo%cU6jJoT1wmY{GMr_1Q9e7<6_hbP~;3Qi}v#?XwjmIl|&y5UgqLhq`1EGd4 zFpH~C!7Mg^PI$@;#)ts}OSh$EB?NPnwIth&Lyt9!V{W@I>i*apRWTd2*jCR2$H={7 zMX~Ecsj}VG=?{b{SfLW zD&KO;1=YRnU^FW3^JU+vIAZ#H%AkOV*Fq0t_oQkLGkB0D2=n+uStV~tUO?-dW7{5E ztncy9A?+67{pKIMdIfA0KaVgLlX0J1S7(U%w+e3+zELW88prnAdB0^dv+MTn0^6Iu z_wr!x$#Ft=>$}hIMvEkc=O=Z;JbKWXpE*nXJ^B1(qjABpjx?41^u{*2R(ssBLxGbFTZ@-nOQrB(f`f3Xu*N$-VE!fw^ z316(ddSE|^0qR;(Fjy8A+16tk2x%fzc7+*LtH3B6 z7Dx49lGHjIkB!*kQDW1wkKImcp998Kr@phSB$Xm}mo)h7PiQ{8Hx2lRV6Vl4%w{c! zi#62Q_38%`(W88M%ZaL=1-ZzBDm24;{X@)s#597^%ENPFCz$Yo_N<0fVqWXryBlDSH|i!$`Nt-8&nIYjfA>F6As6VYh@cMe3Oil*_(}{u zZ59PSt&^**tbmXv4`$Bw>Y27MaOyZ6R{mM@iHc9(p&`X)x!t?vRQ)ofmfw5;>tu*I zFPYpm0*8{l|DHu1J~a8Sz%_nm+l@U#NW+4mDldAqTURWbK(#(__3gRw+^MsZj8?S| zHVJn(?@rrhkbVm6`;UP*x2kEVI`hbatv0G!UCa!B7mk9Vb9J^i7EbP{PGW9!Q; z{1>e6T<;wI8mVmCw`CPv_Sva$<=_=$H#H8tac?>O1Fd^Ms0)5~E6YF+mZLia9Yz0n zq3_{$zmqucy@na3CdZ}4GWxc~vgcJ8+Er{?A9Or!(u{mqYfrv*gY7to3ySjPYEcJx zeTau@Rzzdvu-NRw2o-lk$f1v5 zGw(41^za$c4yuJ!+g@Xt+PfDYL+%plocL2In2ZTJ%-4r}!^C-5od|)CK&Z#vQrLw{ z(%>Wf&gQJckHs7>PiKrB;^fjdez1TJTYYzU$*oMgB2(9{qG7b@d%%uS1+*B=BD=|W zvfmUlfLn&+>9oEqEj8{6Xn9?b{tY02_jF6RVi)<|zb9nJAj}cjJ8zxmKN>HxuTz<) z;SXVp2Lz{9>?{Qr~%|x-B73q)7xWwUGw{kIv^Ow|;Zyenf*CP#X}7NM7)Kqb$G!ZGU-= zZDo9zmmCBx1YxzI{a4qv9+EV?2$Rwe>IF|*jsh;%(_}1Vmc4$&Z9sKYmdd-(p$Uve zfaGs+mLsoJI9AP$^HmX>MBwdBlh!P+?mGxWCEWZ-c!DKe+mFDQAvX3?AIH$?@Nr)V zkF*tIGbPJz;LnKZgmxTc6@gmExAZ0hA3rWr|-V% zL(e7mG{c!%OGR?Gr%MAo<^!|tV8R;b?CZv`bThA&b4BMWKe0V;u+`%8`TgP*`RkkW zc{?tk> z;1w^)_4&{c+F<)_INN(8!)mQBO8a$44ONDSXQfs%Rp7PDPNlRdxrj%(_s!{y1NJ8X z4@VkRbbUrziA z6*ohQf0WniaXv4q96?Kr;cOjbH)#H1vX#kim%24slF(olN5Vtrz}NTUv!ol0BKoX8GEm%6x+>I-qrs#O!ntH>_pK$qF6u8C%Y39EL(rDY-MgKZ0||Z5Fu7P z`riE{GH@^5SzLIaAAX(U#qo=Svv~zZ?x$Mq`@PeD%;ghhn!q8Y-6FWO6OG2+L_vgQ zz3N^8z@epO(SOFTH4H1arU}1A;ShlVBtrvOx0%Qf6+cFb9|%C3Y|(w8BK}!z+Pf=OdP=!BtaVGH)t{pC{+*l%12wm5(-*4` z?xP)sBjECVcR;l|5=zJnLq>|ibV~CJoiS6(85L8TpRc#azT*$L_Sy-zAZ=pcG3M&{ zos_|AsgQBH)qMx|;hlR}+~?l|yM!-)z8RY;)pXEiSTx(4Z{X8+Y$+1nt?vDLhWX?1 zl?2O9V{_4x@R&lfFFx{z)Q|Fv|tX_RN(oX8GF4pL$2 z`toE9bfy=nT*i+1g>vpU*p!c^24YR)^vvVl@$DDWms?+p{^#339sDl*EjCn~0Z)8YQr8tzx|l_%dDHoZ zkd8%&<=M4m61Ko>zWtUZliK@l7-3ZsukMwO&80tV9%O)~ zj~umy{)c}6zX*gA8fVR7Fe+sUSQdj1+D}w0HeP=g-vmILCF>_qvI@I>UlD|!Kyd+k z?teZrZ~LGu6z}~$5p4a(htStiTMP&xH>L-CT0CxzTbiKQc|mZ%Xj8Ke5B6FHrHt4z zgos^7%@GHbXdZxS6x$25Yn|GHM#sa5Xx3 zwNJ;**}}R{L`QD^WwUOtk>8QbWR3YJSGRRch4;zT7}YPpDqsY6XXdTP&q|9_hR-)S zITfqsIbOCe@`>vP>(Oz-(B?)n_{Ko%)pJyE>bxv2ng~*m`hObIAdPq`?Ocdc`_a=D zo&x|I8qdtx5_DQ}=zibjXS^ykPcavIe~NibqjE$kZ=M zHm-_72^akxaHG(|_&Hf)dQ{*ruXhFB_2H*EH7JPU1+pqE9H9Qza zH|gr2tBXVU=RWRod8hwX=4*P{*5|Ue-gC8(rD>@%@1OC`d7RchB+j2ma z#tmwa*Kj)@Nt$Q`^3K_^??DFOE9Hxa=wC|ekvv-J_Z6s?0J$F+MYjau^<+(~A;dpy839K5GskUA2O*7tn#>_*K<%{>jPZjh# z12%iE_2{`e>#Wt@hy{BUTeH@6P_3Hwr|1(zzfOJ78tIUS>K_9F)Ian`bD1BIk!&!~ z!Ff(L#`u69;1$ODdu#HOhTipg*KNbqvsu~|LJJ8oKrlAI+OO5-CXj2o28(M0;vOQq z)vq8xxR_PX4scEn@_p@g_>pSQM)?+~=ST@SMEngsxySC~rm_)SbY5;`DQ}MFRA9P6 zYT zD7AhOW0Ejt#6LdM5&8Q~`wjg&n4BIh96uaPZD@|O@^geVC2F+Sk8ye;_MF<@>*ate zhaH^IGgQ}S(Uw=VEXLd`nv=DF)?2M~2MYvnG;o=9R|iQ{xvWJo7duXS0$76&(elt- zFJ(Z>NrNG}ZvgdbqYj^GUTuIWFeW7=G6BtG^eFm?$ImMA@|TGYr}m(Is8Prn#EZ&) zIkc>&+GH8lT0~*@I042H<|<=@`$Yk|HdHS9vTc>0A^I?b!Fa}EsUFX#3evH3)v`;4 z{4ox=v;@GL;?CaP)EXiVJ(B1by=HmJE3Cc!m(%)A8Bh`{HMYSzaFPrb8ujD-m?7Zny z2*VHO4d;)u{2R$p@cxXe>)Nc^N2^SG%w%gGZ1+9t%1^^TfxIRFm^3d$KcIH0ob$+? zZNYE>qS7p&+~WJJ@jK8W(cpsu?T0;>%76)B^OFEfD#iEW3(cz?uIIEnNkV+doPQDd zB_51{;Ch`}`8wk=)#H!BM~xHY9BlXQ85B2f-8^gi<>9$FCA< zyX3Sqw_sy5@-w3kIxRFhOxxhM8{02EO|BYx!@RI7$IDyQvXNPj`bQV7fD*bj0sw*; zw_n=TO45iS{J>%tP{a?5D3@wNUhz9F3X!+Th>O+eXF0Z(`VylU|7vShAu$G+&dD#2jdwn$+tW!hyJ`2+ae3H- zuSZfj_!QGP8v>gt)mIQ-KJBIJC0~K6&HtO8qIU(rb1fah7BS~Y6Fo_}) zb}eiHqD^_vv%!m7uz+~iqk{sX14V)_?cHD}>Vvk^rg2lNc*unhXjx4V+C1R9MSjFS0YF}*&L zMjjDQ_wbG)DMI2hSvKT>(!WRX9t%8*l(z*Apzejjf~z|J46kg6tcKpl7`Dao!LL3y z$A0B){GX>53YNao;EN9En&K$h*W^y^6Hq-&CC2E_uf>8LKQA{04Ou$%aRVfGFwldc z4Ottz5ySArO|CDFQWNYBI?m&}U))lfB~U#c)l_|KS^Ds=VHxB9_uP2lL|jJpc03!y zXhg-U05c3gs&8Yqdip?74b+OLKr0H{GkSW>+0b`SObdBXvyLo%e=qjW!eS!p468t~G1`gk8KI zBK>vzvozKAbG#=2il+m9xeUZ=Mu8JorVxI6AnHAx=0?Nw2fc@eQE3Kp5g27x zKn)fUTzdIN_-CRNmUe;AFqlS1z_F|Vme~?gQFX(IN#>(~xh6!(!~xK}TOUs4{S!~K z;3@WGks`4ZIgYNKPA`*Ey2;;*9|?(ZO1(qp~oq{s%;HDcD&}D$~L9RVr69jn-Tz6y1^E*G_DTi-Qodu)#?ZLX-00IEkxj6qL=uI->3h7mcA6&re zue68Y%^3jf>1kgBVWN0}ae9aB;R}<-MOVd>MYqrWKDj{ALBdkN!YOz4tJeZ6gBnR9 z=GQ!DSJg2J+RC2P&cusjh#CR-(0mDs^gAAtI1TW=&)}(T2p8I_fjJsR((oMu?Vg{7 zRz9_&aejEJ?D=OF0rsKi!5g_R!R#~MV0^g_6AwcCV~MK~)Q#mAs2=3=m4AM3nS1v_ z-q4qL^*g`>>V5*=ei>1r2kLxx7>c8y&JnK2E_dCWRaQ&m_3c_LDIfduSx{s2O!W<( zuf$h?zN9i;4auuaJc~dza|x3=!G}db^qzQw8qVyTEOYUh* zzm$C3@3_>Op{XL=U*4!!>!=8JL2c^CG~)na%7^RI?!Uf#tan&w{4YCeMKJ6*5-*(; zzJ}0^IP&k9;CFk&I53j|^WKmqz%T~exEI0@=JI2Jv_HH>eWDf_`2=jwwZM3ODOxoR zxJiEmUKiMpq@Rw!XVZZNV7*9njy?5e5r{Tp531Vn&r59s{?!riNMKSi;H6g#%EvQm zzr*0I?_Gfd;j6=$qTaPzi!E*g{z=sm)71>wmSgIOWJr_r7X1whIcfq@r^YOdl;1WP z63It1?J6@GwbuInobFhUKe@e@{+6JGHUL~NC+C@W%?eN>xd(1C$t9OxkrpWgYg%-T z!EP)ORb|?mtts&S^)_M@U`MNs(Tq1XO?~Cen#U8e)XJlN{OYuc|GOfBa1ly5kG>I= zh^++Oscq~$=)B4VAiOMojjb?K(8+OH*P4;SRy<`Q|bcGaFz4jeUo4~jo zkjREw47XW0b*gDLZ+^6!#}IL_Kc5E=hHBHs))7o%xg^+2oRAYKDzyT+5WpYg>GN5q z*9ioA8TOqrv1o&@VYAhcW(LDz;2qS`MJ1|00!9m_)j~Dr9w)pf3?;Q3=sj8H@xn|8 z!FXt=^LACbk79}x(>DD57IA`}#|@*_S%2otB0F*?5PuGnB4yA6SCGvgW((g4q3vno|L!mq1|+Op?Q?zCP2frHSW(1-L(vg3%#Ls5dwra)}VhD*(E)< z>rc7KN<$G=lS`?zqeuaVd7YWvET_&47itH{dYlJ!F6QiV@>iJn5MKV&IM`OUH~{x2 zB``YP36e2xH+2yy%S=FC5Q74DYxWlEbH~y_nF;0tu{=OUH+!mmEt)m8&k3Jzbg+YT zL14jc>XpfW_pOD1XVsi7KPH8M$D*tj3V!#i+XCv-oLLM9Z2z(F(hyl{wp&F86C_Iy ziEL)pAP?ceKqSt9l8?b=|5d~*WBZ^=sCQPTwX{}<>I#CHRJXc~@9Zgmff#DqnV;fOjIAho%2 zof=84yVntVj}gJ*P#0oZ+*U$JQwIaO{Cyy3573~AJSAzXApUYdafg#*2QR;Jhly8$ zX&WJA-2=@q$a|-v35y>a4V#SNA?#_sR0NLIF2oAn?}i9xj!A=0h8e!@+4iJC3?P+hxRleyq6cr#JgWX-2h0Z^waL zpwW}x2|fo_asTq?X%?a(=;O0YFWW)o#uHxwds6UFo8NY7kl>`v7?3Y|?uFk{>{iQL z`lC)98A*vvosb?5?sNRWWRC;f^Cp78_sJWPuP2)C?uCh8BZCNU%c?qSb$yPq3}0GF zs~-R}_PZ!(h!dpsPuW0+ehO-`W$06KFdP)rwL~hvLkYLtnom!s<48*Q=elVt(W~JhB8Z?wiq2^!t8$vT;CZ zSb@sj^(P(h6b9)~XdeWZ0IU?ZOR*+&7*8pZ2|Ca0-+q^X%r{6m45;R~7W1ppCNjhF z{Enl%|7?|v@qD6qv-x^{$q8N^jz`X9m;PO@%%66J3%YE-U~Preps>Xt67tnD3lhZU z7lA0c&btPg*8_3nX&wRpI1G@GhxhV4WGk>ZV89q`BL!_x7z}Fc9=Sbo-i68A1PB*d zkZbuiG`Ua+9_bx=_G-t74juxHH}QpRK9{4UETwz0@Q+x&(E)NNdq}6Bo2Y8tW+RUX z2?=XIo411sqK$Pu;J9r!0K2HPJ)TK{G_ONC`4HI^Adm1uUeugTNlwUt!Q+ikl+vTC z{kAGzMmNa^Co0LSkAS*53RG5G;OeJ(%R1n}#DFO`il$bu$Y7ubsYzM^oE^V4?9hdQ z#4rXPt1SdyDm(vdV@zHF0|8r*S61M=pW8_fCfBSEoi$}1FwAm>3ezP5gN`?dY}dEO zrsCwdN2=F8=ZMVw-kIS_$N8rC5wY8OwSVS$IcJ?mxcKxduHSZP$!^Cs00#BC-5G}$ zf3FTk9M%HXJFO+GcK;eVS_2)F6r%O0>4lX~(O*T=q#$awEA%#!HC1>Z@q^YJhn73N zr>DAPrd0D&ED6s$`^OnCq1439_#Mg^42C=?hau78Hs77{wZ+YPvRs#Mvf5PYYGu=E zy3^lxMA04em`pG^pBoDT|I#0VK9DJL&^~E&2l4`LDL+KKLw1t^RYy>_H(LDl)rbTd zrNyn&wojwTTJ*UxV64}d?rVoz>gs`^l>8)nCAsG*OC}M(r^Otx^) zHmr&bj4T6P#1w!%ZI!qEJ%J+}O|!^2Mb4JKPSM)#}yVrK$!Jc=2tsK#L8f=c3Emy+&Yck&gbo&#dyWS6}Z$2phWEsWJ-tgGbM@2hrVLQZ( z8J!B%>=@z+Zp+@AQG`#tE@Jjyvu^;t_f4<#l2XxCDv13MczoRtUwrAN5?3Og4%pWp zZv}f&`^BhXckb|AFPK_;wr|D>T^opQ%$XYlRa$C@^}S4WJal8AN8{lCd8qZ_Sxx18 zC1BtIRds8*qiqSd*;%SJENK6k_NlVKTwmrU&o{R>YY9TpZ>1v0%FPghqO#QkqJX83 zKli^EgyOVcy=IQuOU4>S1=C3aOW5fseBEU`Qp+DmpXDM+zBqw=R-@I!#6-0Qp|jKX zRYfQC`kiI)Z~I4B&o$sXWXmvvBptRZ0K%&c0Hy;H6gL{WzaAVQKEEA0(Y^Y~;c`9r z2mGtB_2_4gvTDOXr8ilMZC6iXlouv!I-Hi(W)S3e)KN@j=Se?bC83W@5tO}nA1T{Q zc8BNveXft#u`Ak9T?p|D^bH+Nh6$M<9eShC3rhJ~`tHXu!*@V>i5FNamUGlx^et?r zI^*40Ub^gti{I6nv-{|u24A^+EtEeyNR+}E664-`%>q%0?U&Yh_5iExX3=602{Ns< zU;My+EhzJ8QAKgFTkZW|p(wzw?4NOTlN>)5;@;x87^ffFP&cikGiRG9pTHZA&jtky zQrr0-Ek1kfdseTYTPY~**`+s*jk>&CBPKccAW8rhif@AbBbcj{0`P1T9N@-Tzh${wEG zZjw7!j9ROwM*Dq$w%&}RY2CekClFYsr@Poud(~bC)x9_ZgXDtfAw_lo zI#|_>2|S2lts~dI>7@);Ou{O7rukUA9ynuFJwBT{{zUO81ay5tM>K27Vl1m4Q+#q? zZMV$^^aOO#d*3Sx>UQy@@vb?UK1!iSQNBxc$LJ9r3!7T>P@}Y3yu4fpLLZ+C9^H{A zj~+8~s&+h=|4@QQLQfDQo1q;M3pCnR<-aF+x9~@UW=?v+I08j=)elUu(q`!iLV(Q7 zYx(;R*+ZC4CP??0BMyQ(BZw8`+mS410Zg72?UfNppYQc!c2@D+{y=?j8T2ry9?=ej zVF4Ch3VWN?sNV{_#~0YeR&2698hDhVN2zK?E1AhKqKP-ZPO2@@Pe@Jpx!^tFD3$jW z)bUEv^hjwVYlyBkNcu?lPVw$4l9)#j5ZIEKr9dLaMTB_GIiGINwTPgtE+P~kRp-bQ zjVlaBq#$l4^uE%tEi;49dYFu;*R71T9}|Ggqepp}ame=ssI^8>3k9*s44nvZ;jg8d z%u@Z)&s=7nDlHWsfa}7c=z__Swv!|c5}wbR4}Y!y{xT}d7I+G&lY0RUmwbZ{Z=`owhy)KLvzA#snC2sRn7s{Gu;ed6ha;b&llUL@-I? z2f|m1*A_MH$z)=EDw1b|t1!aY@9!yHzn;Jf6ZZlQg(%nU?P~<8Dl&*aXT>+U2AFfC zyfn1SOD3xNbULeMF^Sg)jmzet!#;ivNci{-)%zRaFNn|} zYs5b%0QeVNGgPO0knd!NCjvm>SajY1Mq-1nI_q z-16~&K7j1L`3W~G5s23MnWV^BqqIFo^|kcVw(m=1J`>&k<}m!c5DEr;g|vs?o8t6H zST3!&00rlul4LnaSX3z{TNE=46o^{RUl4N7UI8dG*Ck5;d=HWWAiI!Wy~pUN-|^A~ z9Q49SXuu}5YOkp3rD=%ot=PG0aA4Dx9@4pwV}sk1CYM9-u1UO zFb$wh&qLd(_lwf< z(@15Re{q^*I9QI1!G<{)s0Vmn0Kvw!bw4b!drvFmv8yxL=INwaq(FEeq80O27G-1; zbW~FSP1MUT#{LcEAAxw03CyLXMc@S#*P`sz z-l<30!4cEcK;pGoY_7>+MkfQ}hgSJ!`4DMw=33@Tyk-a&gbSHrACfCuZyE!#{)2?ecul47RnDW=yT(|eEVm5lPq{_48 zbAB{_3Ks9FJ`CIW(7z)%~>ZTz5N$a_zt52ZKac3y9F<`VxOmn*lgdq!y4n|!@*jNUzMVX_DE!Ib&UH%_sx^5Y@(+{^&2_S-F2UQ( zbnQIJXjLtCAFsLeYrUd14bm9^Qq@mkU(EX#LaP6py;gkp+5*GZ2*n7o-x7MW*<1u#eimZs_7E=PP!&M`L(XWV%pB4 zhL)86gy24G&$O>fy&$~9DCY!|Xy0wL_KM88vE|9+>ZXC>zJrR$+_dngjgyS|4Ui|c zy^#9I@FOjaf!#CNd>(9*r8YZVL^4IN*@3l2k3s+je-I7c1&~zPby>BmUg3((LZPru z7BY$Pp`A_$3oxlur3tU6i6~+xR(p;v4ALI51=gS=ZAhvZY)th>9wwB!Z}&qz?!74ZtW7J<<0=HUBQ$1c{;e?Q)o@Gu=$Be*ml+V`_9`JR!Eu zaZepngESD@r?P90VLD#bkHpSq&1-`!gFQP=r}-e3(;ovTkAj?FAe{JYJlrowASZwC z)_v9^F4S18>q&7(ixdMa$Ce6M&gECO5!Xl>sg#Sh;5%sZ7O$`4RW_E@bPtpGK_vQ) zZjCfT8V?jNbx}JqH*GjT(1K7V%k6lG`N4bP2YM|B&R^x3b#p(wNBWP0h&dLO=&Y5` zhSAvO#@e5SU(cpD_%-kO4PG2Hl*;z{BNiWIDHLi2r*BKm~>O zs&asWfYb0JUSxa`%!p-SbqgiwwNZ0EtI6_vb$Tg|v1$xIo#xR5p|!|r9GCR*z2k933Y5+jgeX z0Sbjcj6&gzeUIs)0hCiK6=2eT#bHo9V8I39uY4#6Si4&~mVpeCyjvz{U^~?(jn~T? z4jZ6Obt$*9xYQtp)#@j^g?wO?%!k5M4;cS!FA&3NJQe|^f41F6{PMPI0t8k*CoPBT zqW_Sfu)-vf<23GEOdX{=lF$%>k=s`Xa~OPfqVCUn(v+xl4D!IfVd!>z?21CWTuW9F0R?)~Na~`#Qf56o&qlYE&M6v{RQ#(D(Y*ELIp`Tv7#_7{d zx}x3Tl8X|s??*u(>V=I&uJ;BhQ0F((0f`n#W2#R;vXG(b_C$xPVTYmzL(#4Q-%uMR z7fMWRCRlzi6IbWOJOAos&_pe@6RP7TNE0fbqoF&Am2#jL!?!mdv_CtPop8oijie-h z_#%;(RE7?IEh(PL-Ib`-#wY>gCSZ!D6dn}1E3^}Gc2&!Nil^lGas6K{`hMeT3OO$B z1*qOB`XyXp^xgdO*@iqJWj7%ESo`sM>R$ve#zy56Mz8_|6Iey(N%-N;vI-#*D0kNY z@kA8YiTb`x#>V{ugaFRZ^skl-zoE7F`+`2j2TXg1i8y>I&^k-zo-DpG?HG^AeNV^=F24 z?v`K0p*L9m8G_4R1wDVvv`2vq@pG73=2p$E5aWm^QAbicLwOKcFq)7jxxq%EZ1jX> zGVU_}6;AD@1qjmIdlVvsuA7qmysE0joFeR}99K-v5=k4DsWe~(J z|9baCp#EMTz62%8CB3B5AUN{z#%0{%*=qu|*zV^)HyYmU4j-=ey4fb_#jA+(^014x zBa^w3TY#7+Vkg4#Kym$$78OrtE+`zxyBF_R80rebyw3`?3XGlZ#=P~ScLk*p0cmI%o zFfroS1GNDSbkmq!$p~fwRP|>JzxzJ9&tG<;Yc@H7P{{_EeL+YzCuL_p2T^wo%0r|l z<}}40mro}UY~459<;BH?Rn36IIv5LT(PDt;yJlo3>kct4Aj@!yGEC4t;h16cqU|8H zOMFG>s-PfLgmHu9TTk0bZRw^B|ArD~2O?dT3TBBe7Re=$1gKd;op}IH+I+y$03CvW zVn`f2BAdRTIh1{gz2EyY{&i35PlG0dSC9_afx||Ty@@eU4bE((P6!todBR7)^dB^S z1Mp+`(en({s54w$+Q~F zO!+ne<^T6CHy^FwT9QJJ*RD_U3t1?CnGB5m{=Y+dT z0DYO0#U^i-F6ir*R(HEM<8-K-$gmHTiX_wY?6N@3%xK`0c;*9gS334;uGxbA7*EYF zKgvYj4HC$Xm`!3-+~sxOskU13-ptvE87|!t{A3bu_Lpdp(VE zL11E4sm~hARd!(0z?P{DDK4*2qGkz0yBqeEaVr!J9T%&q0mc|ExMt`v*Dsb1ao@6+ zLZ5!X)*Ptq?oOk!V}Q_Eh~-)_*P>kFP|{hv3F8mihzHEX5?j3*;cK%%R+d`SsqFFd z;uZvUikKgWnfYJQlwg{*dZHSS%CeW@A6*XK9uLx{jD>1`R;<_GTnLZou7QBX<$M;9u;TL6gs*QjBW?smHVO(%XU!TDH$vtKKv8|`VWrW5X8+O*V zjo4wOCoM%)x6}DjtiB%7$sZeZ%3@r5XBR${8)O z8H>i6WcTDBlAT?*6j>Y#aVNM$rgB6ql-!Qq0Xlt8&be264 zw3}vk19nl0o4i$T_^5)xy3S`1TIbNOp7+NZ=7~LGcqR(q_Vnr2^1ji)@v~S9az!48 zD;M_E5haXL>YLKB|7LQ8)cHndC?)K%Q#lnDk>cZ751o$TBE~NLgaQG>LrlGfeD<^4 zG0e#XI`|Y#@9yxDM!-kSWmYOOlmraYzwmMkgsgj`JgO8TpoN{-efwbPwEuh0qCwbU z<0?v~2YuF)TG7-zSpimqM^#N7aPc;$&bP}TO}%z8nn=M4#Q!RiB1AB+fk~@BuAFMO zAV0@Nt;pagGQJ8-d52P^>b2uf4gC!x{24J{?xpe)IG^*6H6(B|RoV@oIq#V_uxqom zF+Ctx?7TT9f1u4XI>o#S*BN*J$KMJx!+?s zf5t<8rpA3lz`E8#LCcY2&qu&y_8!VF)G_Aljc>kJFW9~Fx;tPovF}@AOXNzY)NA^( zSPy4e)5kr>;cB))F^Zj!RVsWsTcaM4BbG4pA@-y=`@8f)iRVNvsDv!N9wO7q6Q zE^m`q#Ge{)hCE1%)ky9d;cOdS%N}tto&U6RMX4ZEPcMNvv)L1d>7aqZg`#5;rTend z2BGD>)onYV7)&gA1>c>_)31%|?{I3gTwF6af7WrR;iZ%$6a5VjllMGGBU_Mbv#_yU zB4~DT%I;BK>c}nGv9QJ!Mlg~th;G&6^*Wz46|(trZIlRRoPW(DJg^iy>0?o;s+D?h z1#@5nfBV@?>Q|Y5{cO|MxN=We=rC?v_p5p8!k87GUSsB{H#b07v=?Sn)<6C_U+_wV-KPdb?D8aD0ocrBwF5=AQgk~NcgSR@%F z^GV=8$rX+s^Z+^RJH^J(G-;O7hv|S8mX&hsrFlM_;hcWx}(LjFHH-mvNUoyt! z)$Wn?bnd-3T*Y&dp*18)*C;j|4sUD}-lK9E~)^i0uQ zVM!S`6US7fk%oIGyJGDtU=&eAv^hn*|JK3DHqsp97FXB1hpWr;o2rkqxbDwtD&wm+ z&FVb_iGWef{FS+TKaTHzPW^yr1bI>KK+fjd`Nyj86@?x;8deHa7BPlp+93B-td-%u z(hm6)v`EXStk7}+E%btSDEy`%Iq)nvy14eNK^gHA$^iR)`P%tbHi(>i(E$Gz4}@}L z285_@eG_DHS>OQ3NonCFWL)uKRt`<2%a$-Z4}|@i;&V5emQx5C`HapS6b;)ZNqVUQ zbb?qy{%ns^R(Q08IFD(6eu=qM1j=vB7Vggxjw^T+$RPxn4$n12_>7{I3rTCjMpK^3 z+YQv#i~svu0AW)^`+P4nt;Vx;KkDJwaJ;-aRuCPi~8kc3pKnwf)9iSKXt12JFgrS zc}H$m07=c8ceW?B66E%x{8!ov*21I_ z@Tj20*Ank4I$;v|Zkyv9z`$v&5eR;n-mS8tOc%~%{3r-6skN1?Zidbj5oZX9cp{zV zPSSTVLRK0rf1qwmrXDEFV3MXJGbAB`^P#NB!?o?to^Tq?u%o|G%(;ghRSX^|lTeVt z7Wn*C3@YDGgnRe*lN*lPk3t^~I^|q&usuoKl5-a8`>=?{a*`Z386OnDCN38${sl2e zNeV8K_?OWS~C=svS3oW)D}nf$T@Lw0Hx3 z3|uWDf*2J+0)!{KI}UXn=n8a8x4S&@$uOxlpTQ1%1Dvp&nvN)ZsoRP*l1(s9WG_$4a`+S!fu0I<+5g70?&G51(E{E7D|vn zt5`@c9XE3+NccXX(;>v1Ovt8Pos9SV3_P_=$k+j?#*VLK<^5+RKYj#5E)XzxnsFY+ zU?C2RW4{%HgN++gnyO>fY1-COK_u0{Jk=w10_tnsp3&ABaJ5nd_D`NZN#PC`14n(c zIOIzy%rY1<@VadgjQv2Tv0}kFNXZX1rFOAd>Nc(3KlFq3?Ul4J5=A@4~-MNBZdI_bg5y13s79 zgmG*t?+tfmjt9oTfV0H=?KCz0BsU)aKQFV;7eQPB%BFU;YPR9Y{AcnabG@)dp1{@m zoQu?Re}a@MahDd(p@fg(^fJghnDc-$;$yBtY*(E9%k{PAE8nRkSWIJcTf+!ap-`RD z`To*PmRg@4lUHsU>ifqa&qpk`OQiINLAm{S_<=U*55GZPq8iLkpH_)LCM|$8c zydUTK&0}hyyAAMzqY-?jJ@Bk=O(0aOcNZ>Ll;)zQVr=>+)M#z5>3ic00}*#Eb=%7= z4cC4&!S#!y9~|pmC*of)G)hSE zzrCfuy?vss^An2U8oWxZFheb*P@gpuW?ec3Y*_C@3}nota_IlPW%&I>{a*qMKlS|x zqxYM2)DZnRaqB^SL10}ag`mhY4C9oZ0-EPMrvnAlO3{b4Ep)nhzW|lrZAx9%J1I5q zExGY?V&BPQcV}HPt|I(Y%NH_E;p6MjFE=du><_5@#d-W&O))PxtezM8jfe6wYM+Qg z1Y=2LPT?=X;q;S`{nrqUsxX(n@j&)4cLl153xwp4Pi$^plK-^y{wlC}du zkG%;`X~}U&7QGi+=F1s4Yw5uEYjF?6YHQ#6fMPF@hjvTq zIF^`C$y{WU)Uy~qE-AE=DUhrut}ro-f+Ov<&|!a50R}R}v1ZXjwK% z`OL&ZZ-K|89$6v+n1@3%%3L;1K_Gt3muxpE^Xw>OQ-z@ECKu&lZPqrK+^7&`=k-3e z$a4P`8gRH|}w0@619{EL-zZ^HtOOx0tFrffnCoK1iF9{+3SYq*R zQDjd#k*f1Puy!=Yx9@%t&BoB`fwbf^0|~}%eZkN&@YqOUAdi~@{UQU~Zpi6K%}cz< zylsu2nPEZ#SthR?!O;hA(BkX%G9&jGCQS%`FuDNmNnnUJkGM)YDEW)L0=nX_sD$2n zo+C}8&37@Jkbq_Qe`tE^s3^Se`fUqC-urcq-^KM4l7ssX_}<+K#`^Nxu%rw+?7%g%2+ePr z1p1Or-^M7B}*w~G-dYp1W0)KYdP<8#DoCCuWvJ`EO zW6Vzmf&3p!g>HKN=DpT0CZ|_(f9eJFY>P?ipH7-^(=tnb0Kp5Jit|!c>}{kglL7iM zu&f=Zr~|LWv~mYw6EC_qBNTn3po-*&XzB#0x*>jX30JOtlYm4qhYr>7X#5P;HQyfsE;F0 zvp~5vnzCX!Af%t|1^3l^BE&nP3EzSbY>=&0)nx~fFE5#*6ch^>a6XS4$C<*1f{HLX z$6fD)cJ1f9)W9k8{F|u&j+1AQ#Jfnof_YbKEd}ssXaOo1wmAJ{OK87eE zCts6eglIBiy(8;umy7-OY>ZnI2nW=EWBDs}Phd5IO??&g7|1dWoa81Q3qcOf>Xp0j zZtlGAtY!5x*{@_B@|=6B4l*AZnD-BdG70;jex@5;7`x>@lxc?nw)+|CV{g6>1w00= zo8Kfz2LyH2!$avGt9-{mV3|jjf)9%%KB$fu>I5vT^MWy}zPQk#3efGrun&Q?&bzr8 zddxqqe|;?b??HQlwrg_r^*9eCjl!oY77Z86GNDH+Hxi>RswZ--!7-Cy1ZfpyDcznV z!6;tZRiwzNO**Ul9=IE*Q@n^jOe$td$fIwYjKMwBpnSh9MN`tbPV; z3&=P+Xfl_6B!59_F~51XYeant?yt&E)9}32_`vESgT-%QXVME|AZ<$tX3Qt0`+{Ho zCs6y!oBqiI77lij4;R2)%rL~<5JQS@j7-L5=brEmt42xZHJDm1prna|2@ZkKz5 zJbMqw8jG^?$(%TVygSo70l|E`N%{ruyme(z>P^(E0eToINeGEhi*}D)!D0wJqB94C zLf6@(13wF*yI1gJLkudm`}|iRW5^~Gyl`Crw-`wgUHzxBrcp^Olk(@U7@MPPMd*=J z+yzj`?LaDVmV|%xfVgP!@5!#4jsb^IZl+uAd*@GE;(q?sR7ci{=>`?60{3m91F%U#Kd^g|rHF+^yI z#;l{HCliVbE|G9)UjLnj&k)FEdG zX*33Y|IW9DhfTX)W`}^FxSy; z`I)DcIm@q2KW!n4K`R*K*%oS< z!50}Qi@>vEl8WpJNha8?Nu-!iumIOxuuHomPF5DL1(g4q4Q=-;oZj*X0us^l@#9## zzm+p+C{4;wr|7`7{t(+}HXkzr`T&o%P#{BgoKt?A|BvCo4)sP-YB`>X6kH$oQFgVBojFq{x=L_@^dL1&zqL7jeSy$)|G$=#yE5E*Z?8fkvdbId z*^k*(TKs>r7!*0@snUM$C!;r}(ap)o%5G+Nfu`oGIrb!I-S#fEW-(tNI93rDS6l1o zW}E{&SSRYm(<#$dpl-EZy`}e2BoIwqN)#|*yV8ItCcR8 zM-`Th@dy;T_es((rs9+6z8smkH9L+GvY*qURqCmL5}L=DK}5u7@8)_L03l+zg24IE z`BPLSjl#Afl>!Lw-C3`IZ{|HOD~0`&GDkmnQXUEmWajR+fMum;l=KJqYdXo~e(hLT z0HH82tn#MTh+Ci=o)T-$(|su=+2Riud1-$opBIN6*&dCZ zMyj6E zi=QU}6BIOE_Z_?^p)26h+u77sGZ9}@=T?cI{tI*|fxMlh{wz`mRRk|S-*7(vvw@Y} zG=)da&DK=Cc`uOYfMkwkFi_BU~Mz`-2dK-arONQ>%@7w7WC95-h&_gw1q~x&j zttqs3=C$dRCfwu4P!o9N`D7ydEiiixLxp__Eo35~VVkes#({h?5jTVkX(a{D0pP;r zT}((S|Kj|m#nMB=@V&r&Z`qn=(=CYY7Cn8dYP()8g1}iYC)fogzKJFR+^;r~cbpr| zdpu1$;|+M(rPjJf9!6(=f#&fw2w(TVe<^Sd-ZJbzlqsY4!Lf&EUs|n)*RG>$-mrcT z=P=Gojl%cZjllBy4&|}oEM&$;>|hL8BR@?+;dyo)VfoesrlWPZSZ>`xd;{o-Yrbla z&x4~+zxDUP(}wOG-3n;=3rIuo)IiLm%N8N0YcLA{DhPtlfBE2-(9iESuIRw=_}9Ml z{#jepP9XavEs+R;AB&5lmGtIgm$3L6VWc8Kmo+}nyI&<>BktzHO&C?^2S)+1B29Uh zzU-_O;q=e3jhTi?KRjX8d;sAa&!ih}n^ZQ8vzZt z$9-%=HO18*mguVQCh={m`3gFH-qdt_V}ORQy}o{6-qS1HbJ(@9=PmG1i3%qsc{K0W?3V)r_H~NC8$e6@X7&U zi$sQ({;{~Cbx=i(FZ*hmJ8y=z@Fi;bJRb*Gen9s!7C2u`QXuXkVB+xo`pr3+UyMD# z&TdgM&_)ZY+g_U8ljn1p6#USqw&2QOi6S_t>(>OTQ+R_l4Lr!PNQtn@!zSemG!!oL z!1s#Ndl~Njs|kR zO5YX}1L*|TM9-qkoyFO&QUK_p6m>5$e4gqd_A{8oEKenoiYcIfC=nfeE_Niy+o>>1 zB?n9un2Us`jWPEUe)QCgN}!|Q_{HL3%fA!ieHEICAfV!KaG*d@+8orPJN)f%piNih z7x*;JiIz@zCKCJtsXwvtk+RU!dbBS)fIxUS8$MMKS6y7l3kil#e82k?&A#2EG{@OCGwG*p+dv)(MzG*{uSHhn zUv@f3wUokq{B!6$@HFX8rU|Eb4}qZQH0xpJpA9erDho6*DS#*_M893T6ZvAH|DJAG z=ul}}wwsB=EiYBUcvX%Nd&!f)4YZ3;MzfEV5nwtq$LB!2#!DFlLb#$bjl_%c~fuIXQNa`Df`**8~DE?yca1ROflc4HB)3{2eH{6kqR%H@Z+v!t)V{I$exN_VhGDuqqj`ae(I-0Z?8 zpuEqL?Q40I;~asJ*lSRl&0eQn>7_{B0|le)5^_H=l69>FH#)KyXnKsb{($!-%^2{| z*>ImuKPu?io8-3rO+rwhwnX@7U;Xt^t3HG`+t|c&b&#l0;NwDzrKGV>|!tbIy1j!-}7uHE~$B!k2U0R4n)D<4m2-> zcK0P60-Q{BQnavRM%98~@QR<)-7)~%ou(yBMue z*kcuWy1+dzx}|8}9m#NIgAj#e#CbqU=G_zoAU$cHdsR;zDi~ja(a_OPjIuLfRSN*O za{CryvaZeoC7Bis;NHw-)$H)Gtmo5wjJR8Orkfp3>?dlZj33dZ2WF-qb>is8oV}Nw zVEn*>nRoPD(-$EbJ;xjVLeLyBbiCc3r}mTaGJ%lActK>3MzdS1zc1a$46Qv?HU#`p*`?dy1!$*)FeVsV?d|%&uXSSTj}SXpjbH?#y}|ydh{wc zOCdzs%uABpY37@bAx-O+`t(O`cZD0R&1a~qvAANvM537gX zXb_yWvP*6^pitq9#dpPPQf3CJsVGC7Xoa`HhJDbHsx5iK>^H@bxb{kS4IXD)#YPlzQYKC3&xoTq^K*809rP2PAX0mYL~1<_u{H1ou& zRHtnl*^kRcOKLo)(x5;O(Qi@#BC$EZo}04_{~C1NtMmoM7z%vJozC-zhk^slNn#W! z^7y}})w4mqNkeW4d0$3RHz!-ril(eQ__fe=yI`FBk}?eN53Q1M=zn`(9HDIo*p)bX~NVv@`M~T0L*kjnFT?G&3 z5xAGxm-z~91M&|i3jL=IjqYmV(M{~)o8ci#Hm~+76%n|LZN{s0-==qYW1Z=RlP{Y% z!2SMUs`g9DG!o^LRp7d#!Uo8`c_t+`I8uSKrY2j1wNh(QEt3E53WmsT17RqrL`BL zVxRiw;22xS!}afPvWTFi28Pa`G$@xvWCT`q?TVG6E{qhi^A!;K9nXpE z#x)eaiK?hFjx;Njy--W^R`kafn+>lq;i7n|jEje`_Y#TrK#Kmu{ABWfxJi|*M1#{J ze&-mSdhyj@XUnW|C@GiUe4ksJ-2~hID96S;TfwhbhnMxY zS`?HqBOkJ2@*#~g$`_mm#o%Cgrzh+KCuusz@?#MnosSca4(v}7z#>sEN z|AKBd;F~JpC!a{jKWzH{zBOn0=z=~b<2VmIaO!2V5=0p+ec;9TKpG>G+B0vr#ad}! z1aeY55SS)0YA(9j&~7|STCarIW%!>vx5#JyRgM2)TY7CAgtEN-JimXbIZJ9j`g`vY zjmr}^P!nWIaPnw88*{Chwj&f7btI#e$_v@p>S$+W2Fx@3&sOIXbhDtb(!izs>+b`& zkEQzKPIJSgigQ9Auzq!cUX$#{)UQcu3oth35}61Sk;vl}?@9Uy`>gOv2+6`!#hZ6s z*+ImqPvTH80|fo4V{U<*_VVj9O3iV1gJv_4!m*3zCX7j#>H%(tn|F(4r6!c~BBhs2KW#_t{!{Vf}sUfOrEs3Rzm4>t!M4fhlYF@s}1 zotcWpDJ3|b@XtGJ5oLiG>RZq-w5K=;Tm--3Hm#MGZlen2VE-gXT#Kj@j_xm^q&jR*aC8UbYzIv2*XClvi1>C|!>8B1RPo8n;vYcWZrRSieQEm!2FJd2Z2vA*|5e?qLqcut6Pj zq}dPH%Xq~p!pI&wp2%a;HgZ?Fec62e-54l3X;>7ou`kKoOx8&GCsY397q+xHdJDdX zrT~J>8`I3g_zBDdX7-*$m9d2loJU!L{%g_nv-D-!OzG<+mgxD=|NaFg^%J4RqZiO| zSAuFW>N6@{BYkA9Z3?E}0!q8B9vO}Bz#jm-lHpOYXDChnp3W%21Hn{Z=;eL+ZgW3r z7G_BrP(FAxl)NvB%$D?J)OvZj8R<6XX1mA=Gwy~%IXxn3Koa96^*Ki zRPA>mv44&xEUUR$N zb!y{x?=JQFDnrb^ zN0KZ=31z?l1|xIJmHY}yzG8S3X!Qyn!X9OaQbKLi&O&@xIOm+j^Z&*1nQey%%KUUs zD^E8jlO^c-AELriitjZDC9IuXf}HLlU~2G|NLtuJuXpL059J8Ez-(GvgRRRCwCx-E z`Ww-NS@=HX)r?3eNV#>}`6UI3DjeL@q|OBqxJ}zA^0QP0&&n%StD@xfPCo|}{(z2A z(X9a5NGE(C#p!X+;DEVX@HUXwkXdIAzEh{Lc37mE#Mi=MWt;9ldFF zOg{~ZnSF^(>Y0pOd(so+^x6sr`bPNp0mhYSFS zSgH81j4y5Fr@@$>J0Jfp4o*Ef2PrlA0NR(bCX|l2H|WQ+y{XG55Wxj~C>U(5zKUaF-E2XrL{XH8r z=u{1L28~8MjBhh0`5iG+Cqu9t@&-<_9GR!nq6!~vwD@%OU~ozr93~!HQFe9qNfyPs zRel&j*06qp_K(47yTfTY`4l{++{YqxvG?;g7>abpARPwK)p+7hU~|EDBw3wSj<-aD z?G92k@tVir2ciQXuO^wmJMTlcjpFjQkcfo^CzTfQH@NGsv8FbSOa$}aZfE%G>?;wy zQB3Z^_^;o%pt`4M`E?%u4}o-tRFr+e93Jn0bbJW9k6&*?x*udwD$MEWC2_te z=W*L^ALI#gex7)7Jp%-D_0NNRPrkT15{j$*UOV|jhdghx-P3*PK*qoLRhzOe5+W|u zyYQLGU>;px6-mDjuAB?}=(s;*D{G2m!UA7frBzkO`G{^yl!|#-)u8sYpOczpQB&dc zuoMLf>IR2{RSJ~TmJHi0a}2p8l0zC7r2TKqia`K~?>!|gKuf3 zCIS)yp7eim@Ptt@XfW2eT`V#{3@P(TOK$|Ehb>oW$D7kC0Y*(!-*-HT(DCb3p7d@K zlRFWjg*`CNar@o0TZ2FVeBq7;Frv+5V2&Z(Sbemb)+BC{27Bwolk!Et*NAQv#2ebcwNWzBUyYg7?^EN^4j43Q#;O!_cZQrs@E6)v zV0-ao`-cNr>>mfif~dU`V&WN5Whq#4@g$Gw{l;*`@^BG@uEDk#Taa$^^8+tg30$Ou zFShcO1y95yoOHc){O``L?DZ7Wh3M~MkZm>`d1^q=5uHLJtEjIm8W^Vr@?A)*y@UB^ z7Y<=H-HeihJVeO*R0(`4sv9*t(}c$`K64`70%OX7PC5r(Y&06eYt+9mMiZD`esNnG z&nIymchzc$3a`aW`Acv%nyFI+7+gIY`4>NdHA`(;Jg_7Q8v<+=!GSg!F#aiUf~O+| zxQttb0l}aguB_pTaMUY?fCACv?m6ECMtC|H7P1+|z_=7j+xzWZtlSs#v?n$yKQsOPNx{pf z-0l~bri=B}p5?_ouKk2Bih8m6_WExS#BVylMuju9+WAHXQ0PLBD_0#)*li!*k4UF= zTuoA&ALu%!4M<4sNY8$s(`m4#<07QtGrS_xD)osqgS8 z18qt24(s}uMmquXUNn#pl?z~*vZyCg!c-cNCMl9+$B5tz;wcWBw5?=puH_6x{bVwL zoR@wYrzdD6NOvnrfvuTm*3b*7jkLMe-IT3y#<%2eMu21XzP zMq@PIWjnw0iIS=FcMAZ@SKqC7Vwnx(COB;4?a9}f;GCiPE!)AJL`;+Aw%!nRPL-%N zg?xbqnztI}9F}m7U0g;1Oy>JallJuxn>>#Gc2OfBi6tpa|FY+YlR98n*Z=@{qm zJH4K&HM#O7fP`Doto;4#0Ms#ACS$%ejox&%2e%miT~7!(0-Nwj(9%W|_`=L$=?(m-XDYq!TfjJK9Fl84O23RCq@=&Kj6|8^Ym;A_8_Zu z8PjZL%b}+}!3QFpbm}OM=Y2KOxfVI`fb68bTdmK$@el+LTI>c$0>4L zwGW$_#ZW-HmL!ymLTHqTEU^%EGdoW(6tHOgq~tfaxPV6I3vr6)*u&F<2`Uf|<5rK3 z{oEtpGTbDHtrkfNZi7OZB>sWgtV90Lr=RSx2p zvRQaJo*}ka3o=9av-jZu*GGZWb3!O%h}&p4Js@oDj@t0uNj;mRM8)qF$0%q6$M(eP zM%q~TW9b+ebSXgQUVARY@r{oXO>T;=*&zR6Y`CBBcb5DY0H(s-hKPCpWyuE8RMrCZ zROy;MkKZTuAn-H^y-~k51CFQjld4D>tXd#0kPI*#(<7|EFGD9AuLRrI>?hJ0EMohm z$*VpQ;K^KM)v;k(Dp`=scID!DI|3l{-^@Xw=&!yr)c->M?UjX4rU?|Z4Ja4~g!6KotiJNMhRFUq3Okiv3~6ck zGt~M@W_a-^h$e=&~_}wYzBzW={V^XnbznJ_SB~)Z?iVB$; zBy8kJ6aN>F{1=$9#s7^|bAO0pfX(P;H)HQE`fT(A@WljRCGzSZJO>wGx<1 zrfOA#EYykccrH<~aVR*o8bTc+L~scByuqHbdO?tu)has0n!r^Qa|gS;1lIzA3O)hC z%LYU@X9UP5*<&BK`T`oq_%sCLqra`hKg^S%Mf~}?rS_qiU1OIV{o@9poraCZ=(k$Q zP`2Wj4naf^VDuNutdzO02}wYAI^CS zqQZ}gJpz{F7k+sM35H}B5&%It4t%p?oQ(M(UAhj~l_#$mHF0g4r;rFmZAK720-llp z@T{H~jV`Q>c*6$LHNH68rX?Rm)HJG?w9T znu<_4k|E`V{MNnwhCt{})TpBpExkt;Y32jS)f+(C8x}~_&1EM{t^MUAZ%Vc(?u2=z zMhR?r2@4ALCoH&Z23Nry*Coud9O^5mOxFawn%ViYXoX5!9^6w&>}lvvw2GL#6pU@c z2{^ID1*q*I{ec%RK*{J>SEoQsqwb6Ro!2{6L^x@ox-{=^;hha7Rl3gZ;n)meQ$Nxh>gRMCntWyief9xmVdy5WA} zHP9S+G-^wwhmo4EfIL(f3mVHkpY2R8`mb?_9G` z@nT(5f09?x`EYqsUgLmbHfQ&ru!l*r#B!clmg~pW+{u%FVR=OL1gG8bFNzv zhhBcWEn7t0EOGuWZ;rtB%~HW*X48u`zQ_ml6ZBdjvrM;!r-`I3L)_Bl)4Gla{Kg2p zBEhk^?4eSfgx}WI#D2(?R}q^W?*PsSl<1>?5v6nnn17o1u+!E$0CLud4BfO|mn{?6 zQeH%I5h_EgBA$Lbc6E;mV{5OYh|7Z5d+hX*EwAY<@jEfvARLf#3G{s88$}%p@qOK# z-8qSAAHMt!K;M$F`3Bl@ek1Nq0k4V`9qe!e6>U4=pzP)X$&xj&n%bd;;{wbDO|8Cx z1giqPPAT|l^=8UKRa6q1V&;$+z=-oS4vd$FdSW=VW11zRHQ!x$P?%||nh^WSnUvEA zK>C}PEk`1aQmg3hjp&OasZH=Nsqh-sZo77S(M@0lCKg(jU!17KSMKi6iu*VTFfJR&)*2T;WoFy4W8@_89`D z{N(pSFN(0ipL_y94lJ*x5|`~;lNSk`>7w;GdbfkK7ML=Txoq% zs8;*^3fr6NkTx=jjX=aFXPnL8b#(k4fRK@h`=ud|IIl)WO>4{i%-c_K9Bl6T0i=2| za!dd0QZCb%e4EmT;Z(h$!J{gRvz&U4-%s4AR`iw*AQaQu1;n$?IXt}G@?@JuZ}tfyNL7CBoaOo|8?@tNI|W_ zbM8J`C6C|o1E7mbHDYCk!7PbQJo;jf-dsO znXibvsc{iP!9ihnKc*6KO#-lb7T-ZmQwh3%+h!G6bRW==pN|HuBGM@UuU~FokZxjp z3RMrNZ!?@c7zZS4ayi}1_MT}<*Ugg@!)4QRAl_8SfS{e5N!76S-+(!a0~SbTbeg>~{) z+)`g|q~rb&aS7MF%|?E|UE=NJ1y}|!4n!|Tv5UG{yhdrIxcK}?f(KuIxLJrK3>e?c zIX8*B3c65?q>xSQ3oy^uCHc{x2F^eTt-58jYOsv=BAiZpR$ z+!z9#21_B_m8%i%hbOU55UoYADKl2h{@pSGgDZm$qGKbW$X){0B4RZDYbGi`x)w<( z28ful5ox+o0N60D0(r+|7U89G;509()2mVA{lhh*%rs;aX99lmmRmBXW81arZWZjF zQJqQc$f_o?b-x9`4-)UuOR&)`nozX>!L9?a%zSYj`8EbZI{gRA9Ci~FS;AOPCA}wb zNG9cek?Lag4DM5#z(B=EgfcKWAImVJR@J13j)JYv_9#P5N%01ges?D|Zu9^jgNw^2itE1cN89R>hAdOlCU7nAvupvIfz z7hj@?ot47=n1`mXPQY!=P8=nB2BKoz`ZoI2%2YN}O~w*%6nW&rqJ5!`6XU;&Cy+}Y%#6RDT#s8J7X*V2?5qpz|vb`PCfP5xY+BSelL={f8 zP$I^cjc)!MS&PC)AD0AvtGWLd8zB$Qy=v6zdAFM>CNu(woeUf!88*jozsS!xGBF7P z2~^>SyuNd};zV5)k%{<~KtAjn(eusq+#0fkucBDyGx2phX?03sf)|Akv&7D&TE*wj7Y(CoGoKpS?Q?`O3o#FkzZX{}c{>WGOyg!LgRHDk0`#PAp~CyvaDhS&ZAG8X*mJfDOwb(wSfPrHfa2i zgAtU4u=sl$sg#+}TiopymU5Q{e*YuA)<_k8yaMu$?KXJq0y{{!(gbeg)0wsXQ5=iX zB5TIbh?GR1feRX*XBQJsM)KgUB<2eWYDr!yjA%z2bTsd%GzL?m0gmR${{&zR!^t6+?ODVk}n zV`|3*bK~L(KV`Ht2hV-z#^lwyey3>K^kXF6_m3X8CCv|d*xz40!xOsxt~0_f))rb| zrfi{VCZ!Y@bjWanSTL|f!T9P_F(KPA^`{2``tmsH;$;2}%V>3c1lXORM{ggeNvE=g zY{#`bl>&pJu9(c#L3A$ki@p?dWohP>evYNf+GnX5=LC$e$sW7@jy!X!dC1cqrUd=q zjn0mC{T4xO@Vojr_P|iU`sbdha~TVKjd!-eft{iD8DEBJ`+o*~9;0bKu zY1B8Y4mfhb3LrhkGx!470oFs|AvH&~o6w06oq#9=rl}5nEwnwm)0O&NunP#c0W1GH z85=*JGdqi#7v+j^{5?XI)fFlHS>R)b4wzfHH}+Fm41uje z|3G;z)xXBW7BfA+A5YN<18}zksTf0a%wVMmz-~jD^##cMd=gfM5wIr1y`DRAlF}Ik zaPQN$<0cpq#%PmEg0pW0UU|?wkeyC%zhTlEy>cPwvmKB82BbZk41=8|kiPQS1rGPX zO&hI$;fZym`cJ~hFN(^BYwI?S9S2Q7Ee4w01RO?9dY32dZbwj+#E39(AoP4rtr;Q* zOL3egpKGOGQ~(KL7wkeH!6xHw3oCnYR>pL7CihG6Rwr1g(^Z^=r~Ue8&}YDYb4R() zAd9znu(&dzE&Ifbyv_NmDYPX5&Y`WpsW^>Z{tcq%9@HO*+_X;Joxd43&`5DHDMeMD z2}V5LTYBp@@izRmiZC=E3_trx{TOTMJI#_IoA_43ds|MoR*Uw-78G*qc-}iL>*3<_ zeFGRxeSo_%Gy{LiX_g_$C$%zEpP84Dicyx0{^9n>r7$msi)$pn5NNCjPT!`;rjv|y(pDWCWZRJ97k^L2l- zGAY;TN0q=BiO8U|LAIZnI3DcUK32#hTWEp-Gi6w{^N%k_Jan+JFGhlhs10+X zpUahwC+w0O3nd-3Au!H0i%U24F|$~UtGKIqcMKrxiLldIl`c_kQQ+=VMm)?~PpZX* zOvs=-0M#h)p;PLS#9Z-P(`TAe;2Lrg@H^B9QB85Dx_{u_7LJ|a4nVCJ5E^@vs+O8+hu zd!XgxzsDn4)VQLbi;_P|n<}-wxH4m@au9SsfzDL#H=-Dhr5!4W1m%-$BymdQnWtA9 zNY)NpUF``+%ARDMwr!o{5X(L|o|qqWm|!2jk0;#cZgrMbTJ&u=B8(3(Dg6{~pl z19K2uMyx^pZQu;gt`%>LC}G?M3x1jI?MH1pPQom)qvrdKf&v!q|~gV@CN4~zHUuF7Y&IqOw1??kIL z;L&*Iq+37xmB99Se_A{yi`RG-fvu5G>FbxrIvlBrQ1xmQTKg-sxtxfYbI^4V}UHTT4AK421&i=G>iyWIODs!6R9;$2Wu_)(eZ}NlWUV3+MK3Y8x=r#vXkI5@*ft# zc~UDFz*)7LI-E+a(mcr()lcS&Oiojs`oGB`AD22yL=x}%Z3}a;I{nl2Pa%#WL*#|Y z!JEg(e6O3Zqr`mdo%ksvS~8O*Nx5-v!9?@8m&mK)yW@DYlEE9nAJr*qL0BaV$s6PDimM%3bU+C!8 zobO~!r#;WN@7_mp5D0xNcrYAcJiMy$Sn|z@pSY6A_g`Q#srn-WZWUSrOW)-qwQQsgvg6@f-c|R7Wi|T}fqG#4==2tPwAXxIubm?5fXz#-rBGHuKg* zMvoWkB8iouk3_C*^m9L;(R_Y8{#Q?%MJ+%d;(xo1kbvqB5`WSs=*St>eCXtc-DWAXfEWp2zL9;lAm1@9*ww;O0vb5 zs+UZscwj~w zzHPDnmJdTNF&6`YrgRx+LfqEWh3ScSpDN|q3WTj}|24wfXPy}R%WSk*KCq>oeZE$3 zCk*@wN4OZ;NuVB&eEJfZ|Azyces-y2o8)jsB)*&IcywnB{hy4j-0}p5ZP&WT8*j6v zS$#=St)awEDLcuRCO*PpC31#8}8KJFGl~QLzRmw3%{Oz zlMj12-IaANLv8W2I<%4E)f#b6?sE0~?8!TL(e#BtrU>)d1wjIW zUnAR2O#*?$aTf!g7AJ*|!^xXbgam%x($ZM8$tlow@|6*ud7{Mdvduq`?t+J4Ej9g0 z7_FOMe(O7;xh!)|P6T14?Xg{51a))!>^8nx(Pma>3 zy7Nt<&O|5Fw|MuQ%ej6#s`5{gQVC)h&Io2|?k9y~{#6{%J=y$Av6JcM`?jwCo8T=a z&`jX%l!Xl>o(^gl!79GfHvPQ7L2fthZ(%eR4h5q-8?X0nuk9Gx zRwWasj$2ELEyAptScZP;fguQr{unBG$%uo8FR6_NzD+WGG-&9f`SQ#e6dj;DF78zJ zOVB*32gREIY6>EPq*Bu-G){Yj(kN>0JO??(omDf5=?ly%Pk6gJVf}P!yqsNY?RY~k z$$}q3;J?|N_=+#s_7gp8DKT5J)iwSu^D;=5zAnIB$z$o5Wf_zwu%{XL>^CeB8k$A$g$Lq zLVo-5+=IF6M>wR{lv*f1E`!5cG#T!&To;*KIh z5!hT1#OuZH1F8RV;d+YvUk=QNu(ny*$!uBg{;iXtQ3`bRz{J8N?FM&D?Ul+_qy-z_xra$ za`)!_dOe?ydH6KzeJJo;BL=TeNaK!4^5;P+j3K>1_NB2uY~5aj7CNU~*YYZ3*1ytC zokF&vGY52DOXS{l1Bnbdl=jwd(Fk3z&M9QtmtaF;5&GdH{@@6uS};wMD~7yv*>{Tu zsc+R<5vx^KEgr{0Q{QV@K6?<)mgIF9Mw^hMBtSU}hUCEn4i|}Z>*<*&ByaS;zl-m! z*UYzX0w{AM;aWV>7wor*!nP27Q~m+jf1qm#mHdfhCEWDxd0(x`pQgtpG;z;vfJ~tH z9dNJndXbYQYR`f>e%2y9r}hFhU4m?Vu~gw@#&H8w`0pK=NJc%Yo2S)&UtZdr*!clt zi`0|wWjAi2Mt2@gp+<6!S5CpZU!B7pc7ds$^U^D~k&p4fI5NI8H=ZxYVZrP+!zct> zk=q2+X7m;7-l#|)(LW%sk@XE>X@O8H_u^Z2#pc8~5gEghC!)Y`(gU<*6#zRR4^C>N zxYY%Wd{tiq0hVd`(TUKa8Yo8}oF_=6!#@6@9Ik>J1Th&t^!)C6$uFVAb~_1|3~nV; zV9(donBa>(-T(A?PwpLC|4BBQ(~#!kkbVf0fQylYUglqa z6^chh2*O8vF~UJ00mY~ZDfk3*Jd2+Ni#7SM+=~A-Vqf#dhl)5-&h7?~Js9GR8Df9?=N{9Z zH~j66dsRMYVj5LPwJ5z}+H0%OesB1)BJQ$(%9lH5568^Tw(iyiZSnR(j#hc2!`^8s5vSzWtch=(IyP0!?YFJ_|2Ql^N5a4@R`vL(s8CV2TFt6%mvFBXi{QJQr z)ObP7=xcf7B>xZVP8rHGJ&vKBnQF5ex)U2YS--cGsTx8}hJiF}9494S5@dO|WajSy z&1Jbm)i6rI!DP})znFk||GwV$XuP8yc4YG97rnVsaC)HV+grddVzzl_6KJt==q3Y3 zG%1_6=bG?b9`H&uNxCGdxJ3zQ*5)%wYcG1_|o={rJ26t_LWIi`^EC;&VW_D7p}FT zr^I)0m4pUrjc)C4ud#eJ4aY45du8AlYU`;_L!B~E$84yy!-Qn=+Ux)+Ks-8DzH z-47N)>iWv<=)XmM0uXfre==kF&O7$8YY6+GfcXAVj7*=FU!OWPsk9TQzL=E%`7@LfoZvLzOrbI(X5|RAgQ0n$Y$D5->GQwOFuj$vXn=K;?DxX!S#E=bjYC+Hn*Wm9 zkjf!2_1V?aMYX{n4z#`z?z_4smrBj*a`GOIb!lOrRx%m8xAQ{3^c!YK(DaZT^c-gS z;p7&tFBe^sT$7IAHZ36H|G8rNaJo}-CM@zhy=%+snIfjh6PwzCFqm)3Z#E23>ZRxz_-XU@%5s0Uu;fgwm7eTt4W_{RfipGZ&URwSQ2~)q8%U zq!Ff-l>!~clCr?e<|9M+i=f)D#3FN9W1s^Csme_h`z(TdoDFv=4+#v2=auUWh`boi zKEqAGC^d^{eH+|-0A0Oy>QP?yNJ&7InFp?VuZF6TKFD#aWH4Oz+H(`fP4_V-ePn_k zML$-+-xTS~6-BeZ*m?7VRNal{jwWye#YJmQ9|7h#}=!+mx#MijBXb0Ub*}oUQE?h zBfN712+8`4d-e^jV}*O|0>He@Ph29{CxekeCLg)+GnQTt^{%R)|KG8GY-v4P!7qE9 z+R=;^RSE1`@95YS9b{fTI7->Kks5~tIquVbdom7$OEB>@{o1MO7I&FDTp zzq^XZ7G|``?kG=F+Us-eWsni#5W;!}p|TkBS+Z`y&PrS{!|@2@rHRF>T8&8--Z^&_ zomzf4%O!vQgb-wtmTyxL|Hu^?nMN_c#$`%LiN)EJfb)#-Y;}hc&{sSPTncYKnpB@8ro2?tn1awY1 zA;BMP>_%I-hUQPA4*PFF7k?#v3~>=iZ<5^L*5(Q0FDHpxs3iyubY#m7=9w<-H!R9U zzQ53hxjo}m5KpT|gl_-?f98VeWrcJwCn)A2pE14@6He~SlA*-;Dd!HnnWRAT{~G)w zJzE1vhQyN0ujxF>mbjbh6{u1NL1%$p9i+`8n$~2EBL zHvb9&(_ZSUBoT_(!GLCqw3u6?m|+AUx?ZT3Y1qmp|F=hjlXT}bi%9O@ebsu$x62|!m$?H>|$)-d8fYc zCZWQdZtNi^K#~SV82cN0$3Hm^25Ge=`Ma~);}H5P+sf=a07o8wQxAsEw`!jr(nUT7 zbb&ErpgC#;6 zHk|+Whn&{{<{l$?+JvWwxkd*oQ0iv{CUs(HKtn$#x`9MA9 z-6>>$@nudJ@izsb?K-&g&ex;QN6ZvooU#j{jJ6G+yGi^}_M{HQ{9julLF_9AL7c_` zSfInPu4~U&-E1U3{~iTU&_=~cn^$1oqjT;TivrP_Ljd>X^?RJR@PA2HhtliYicgv( z4_zcYMH^~Hf0621hk)$gb3voG;@V2Rd$JaUsxPM{dxePuAYRiZGz z-ZgtszqZ40XDw50V^ZPX7BTO`u1zJAwKPci^;pI9CK? z1`m?B6t&Wo+tx;z=2hHU5w}DM^~P^kptM+5B^bgk>e$1&b<)rg3p!K|M;z4qTD3w0 zw5c~mbgdXmhk&m}jIqz(;hC&Cc8 z+MtnQHp#eNl?Ie0)%io0u;qlMi<52{a4a@Oc=>cmxm0absE^^!Q$7!!Y~3#{Eh83= z!x_tX-32QNF5$#)lzeRHO=XAc4AVUIuRn2s{hk28I9pPpfF;ug_*HgPNX-0wTXNZW zcYDK(3usv)RF@aguo(IjHDrL=Q#u2&h1w*yKB_qh-@Gn8o);c?a1gIN+3v4f7)3Y!VSgaRJJ;|Qb0qn!_oGO~w>N2ALgw9n_DSk!BCG52lrJH7Qb-*Y{e0TX+9F7=49d1`)2pdIS*uLCxGW z&NyOPijbwQ-bDSq9vGKo=|lXa8lVs_TE_3(0tCM)+_$@0-B>VbD!~W~G|MA70pdLU z0wiicAR?JDn=PiYP+>SGzeirDfTQv5DYYyz_Qin88XL$JIZdd(Vx9HXE^K_VVI+b$ z4dYd@-ullOu-ht*LcQNx0zs0mk=Y40AYACSHI%CDZeqE4`e!}@Lrpyw{MPK06=(_S zKIFbJ=QmBtk+58!Iw|dll6qnWQ47Z+9po~6rJ2595i zG)*&`=lyU~T-7#JF3}y~(31|su3?2CKx@{B*uDuaAx<|3IA;;m-Aqa4htpX3yvzU| z)5fcb+@YY6AQkM%gC}DPyMr3YVsvLYQjb(KD^j{&wFuP3KAo{S*CUdb+y6AZ+R1(! z3K-A;L%%FU>{tB^9!cl|>0M3*xDEl7D7?O)m(C^XVHtRz#ioiXo`y+QF8XWNUGiR+ z+B*V_Kc=fwmx=@+|I&dnzq+9jm>{K%&B#+G9Vs%2oG)p7;bbl0)!#q z?TwZjTQeuJ*H2M{sWbPaX(E4UuG@xa6GUvDp0bJ4W&)PPR*%yF@cLHkTX6Lm#&4`hlf zfe&2i;sP2F85<7T_&NmN!EOqhwAOtVheleIKOE~YrA|yIqn9+j@f32`YNDo_Wcym6 zy!YRahZqZ#&M+8@WFnI|OCC6TBW-VKCKUyEwBR?+LDB}xr24-ufpdW!Zm6aWbn2*5 z{U?!M@EpG(W;PAM&<$UuKBrmkw4kQ^2x8r=YN2zJ-8iB|6;KGfgB`u;#f>IuWIqi6 zDPujg@w(`Fbhr14z;^<@JqCOP*EzcKfDaw^FYI+!2GP=)RK$57*Qr@x6dk+T1@v*r zM^wNOAw#-lA7<()@{T)N8bptY-5u5c+;KaI-(=dVhyPQI( zZx$1hTxZoH$4|irN$jDnnE}eu%il^k$6(yL zyyX4T=G36sEdK#w)F|uHY_cht^iZ8uO$td%z{b>x1=V_)j|M~?Uk25Y_PF;y{N4+4 z=^FAoUp({~xz8`xeM}?zMqq|Z_F~uD$VLO7jtduBZs`#D+Zf%fvqEvh|K42Ai)fEt z8+*|DqPoTQGCg~CvFXz#(Zx?n4&U+RGcb7y8q`(Ff-PZ1_raQtpdDbJ*b4BEmUn`t zup~-M-{Nt`xZ(x`ms%9nzh!EV{Uv8)r%@Ps;nWot@aMAZl=e3>=W+UIO~_~rBCb7vLS`;LaSI}*ncCNS&h){*KjtgCe6u=4m;Qv(Etp z&|nzV4M-`=MK!I>GGWE&^HWrCPR(RU4n65`ulkl8G_QyeJUrGYH!&I@d$$NgS--j*^Dr{QCA!|SX)9R0KRI!3@ zUXa`+FzF$xQt8I#!KqeV-6AzPF1LVAqnU>CsHK}02oklpUu~H5(GDD{kbY*Gxh}?h zg3B`<5+5JaL}PU9(-Ie?Qo1z1bbN=1r+p|?Sn}MpnqG@%v_RbarK=FA307kPS>f4l zZEVhdL|Md*JkgyB5coM3cmgXy2Th(rPFi`wfn@25`p3b8CkXu=jaRK1FrVYrJ~y?W zc1nU9Th$Mt;}vQJTZ^a-{IYZDd^o|j`PI(Li2&4Q!_zU=-sKCj~pgtHo6O>PY=4=#sf2c>iMTtE_6StT0VD&riy?9rlw1ep}29G!6(_}MO7q@-> zcLDWngWy=3EoRCBF9C=0_ojD$zisjrHbbOzi8X8_(JwQUXL^Melcoz8jzlzySWxD)zB@J%tA5FQ~V z*aT$tR`s7(JWZ!e$yHYWqMF6;cE(2O+?!Z;U&a?7Y6I!p5O7VPUNjNY?E88%-NG3~ZNN^{QTNY{BU)st(F!GN#xUnV|l_r!)|fhEr!Y+&2NU? z@4I%WVkr*LI`-xTGY9>S34JZ51GpQH^a4l8wKwix(zHE`e@El@&Br-yUWYVMKWSfr zS3l$RUnif<#+~7?nffu%Ut7{J4rKz3Mfx5EkY?rXm`%OYK248Cvu+9&VklX7dO&{G zEBF|mAH>KOi*y-;f3)Dfh6@Gk1ZbAceDH7BOd z`RVoaONkbf+2^UU*Ibz7!xxc4CL?+pbH~*2y2aK8MJ~t+CU*N?@%5_z^c^`WKv}t? zl5%Xi$4-6|nJBm^i)4XIOO1~-RECM0hmKj5ODes^Q)mi7m7=Wc*`S~FuM zRtF@XrkFmw4UYwWV?-L3prC7F24a&h-Tvz2sI|ge1H3jDGL_DFE*-ClZ5@@XqsgDD z)O>g^^0P2XLs@;-4GrIe3P?zkrR2aL*P6ed*26EGL3emlZEXc_@rVp7JCU<~K)hK) z;GTc1w~?02GiewwX+Ha&6w^26Ft>c*NV6SE7~;$UC@3P|ImAKpp96+TFPFq78d!+D z^ub)AT1o>Ol9|zk%nG&GiWz?*83J(9}CL1_Erhz~3rbVYrY1zsJn0)Tki1R9ks6 z0F7_uyR_6JY9Iuw6z!aDzrx^#!Cnp@g=5L?&sI6=ZoTmwNCMrgSGgcUsD=uIy+@B( zmO%!b90?7KJ-5r&-Lc5WeIg3K!05U3m`ERb1AH+{4nL4a46WdLaL_kz@PaCC zK3;;N@fZD2<+z!rz5ah zcGd~Fc=C11-eiFWX;9~K_T-TO8B&TJv_%M$;2UQu5pL)}BUg+*d}JPr0VXzWZKfiX zVnyABzFTd-#wH`;4f>f1zAR|>(p8_fKwGBZ=6UkrDQTK0^&D6ljW!+}kuCBm^i=F( zK~JV3xQkGoV$XfrA2%^r0#zHV{k^|1;nka&ZJ^F(p{y9WKMgu%;h_(hoz-m@8pi9S%drJdL#x&JOB4ko(IuP2zDJ*`vFY2)8J)q z3+mozN677L4E9)8sF5BY4o)f2q&Y{|JFZBIW5)QUK03LEC0(9mMs~Vi*gg=l!k6+n z6}?q|fM;RN!(>c38o+TpJ5;qCc@@YaEP|IBX*$o?$Yp8|sie2~c01}<(F|3-p2$N_ zCAPu*_=e12gKP}5)hTc>YX_pB>+YuYJNo=9WnlZK?`kH6#_wD-=;v@Dpl1zNR1(Q> zHgr@AKy4r?;679o#Tuh&TJS5?TyKo_$>;xo$^|sKm2bsx3Hj+aBZVe@ZnPURaexB1 zcCymy5;zvfcA0_7Dz*JC3O}YIIUVOAfkI{BKR;f=2Tzr0RscS@98(i??a`$g{XfOW z*&rU!^v*@P*)LB_=K&Nz*~*es^A1Aw17d)`VV9ck3}(Q6>-+T)mbCZ8EHs1}3S$uUuz ziFw-+W8H0!ugqdF;mg9z#7xzZm`1eQ^ai zkaccYB3tYt&LE(*sum$eCJxSvkMurkadp?lZRAjLCvNrpE0zAvqf*0H=)K|#$GV#FY)i@k6|DUE*?u`9V( zA6}?dy`hw(QNh17qk;nVA^t&NdF8bIZ|#rJXbklIXV>!!!}NqO;fzbNQV|TArsf2m zX`bPsUhj#5WqLb*wYS_HsGE$mHGc)Q6JNKI6al(zh|bM_sK>gf=O8D{8c%m8 zE}CFeqk^TJ{jS0Gc!M^Bt|(kk{KZCPYtxcgJjH9!X>I=1Bm%MGV&L#}x(N{O&hXR= z69WjH#uYrmN3c=hKhS29Z5oJ0iqKBIyI2fH{XbkegE9>u?!Q@e<$OLF!|WXi?!45- z`mj;)(rYf@vYcQr8WE;RiuLMGp&gCmPUu3aZD0tiT;3h_i-LJU+dgU;CwWp<2~^V$ zzR*WfAlSw9lLH;(Bq$oJFLwywge{({gKSGL$LUSVSwK>I1~H=OXz$_Wslv0dWC>v@Q{-FikM^HBZa*^e{i+j`ci%|kxCxjv6XWPUAH3C9;EhhPR2EW5 zyO%&rIQp{9M*y2F;?wN9uivn0)9^^eT%vu0?Fnu#{d&&vF{J|aZT3{A?@R%2FxTV4z z@H{Ez%Z&K#m*iNv<6rBO9DvMZ0|dW3rF|Mj*R9XbAMQV9Lf9Id)>Hxx+?rdxr#FSH zRhs^Z46bq+Up~eEUqn@g{e)EHCDaXhYAF2;riB(jm8eLOU+DoscY4gXGSv1m2^Xeh zCN6{Xa1|OuKfEcFGP>28lA-Pq`>nl@QscI;S%m?P@3FhuSSOSEX^X}>CDkeLVGGfI zDgLaY0g2@R?@Vo07yxEho73)dVJzNy|LDhBx-0PyC7f)6GL7-zzQb)aeF8LfT8dL%hQ{fW z9o^I)?dYst0P5x&?QC9gvL2uX*6f=8_!aS*SME_aRK0lK>l+4Gk=-jz=6rr`U~)s& z(Qk^!#)-TvW-@URNEDvVvkgTZ%F$9#=LZ6q@Er%AdGZFfoW&M~Op+KB=OrNJLwB4U zuAZqhhF3BT2__c|SZIMAl6mzaj0evvFJQC~E;CLLzT%c)7*3=W_Z)76>Dr)zi%-t> zV=m}F>Z2mnU{tm{7_qivn5iP1%;9FuUgLQW;Sas*dVT11l-vzb_j8B|A*mkXV7o#) ziRdt3w63Ybgc>=WISYUt~m9k8KBrudk z!gc75@d7Gfm$N~9SBeFsdKXablmCVqiXrLB8B1C$Pjo@bLq-~lBGCWDE>oP?;9>;N zN$X6*KhRtII_8T?Dajfr=`TIggMP%adVz5zSFt2`*1;XPL$HdI7GH5h@H-_4^D?ks zK?qTzj@$I`zRHhyB{m|HF>$R{ z$d^CNW@6nuh8)12N4g^!yca8LZVZ{_?FL*604wBJi?VCr<5@=s#??La+Iau?p zTPFrrJn-6OzEYaAE@PdQAz_*TMxxW>GBe=ZRN5q1Oul!jp{KByPy#B&|7up4MY^e~ zPx0juraBoCJB#Dqh zitB{)794kKIZuit>^R~?5ZH}oXAn18VVo};7o34f!S5$iDEiF{q|2{JT$5v|gwJqd zAo>hx+yk_qV~@U6=tUKd$J;L*X4(*p+zuz^K8uYok;45jX58D0u1@7jbmEU%#vr-E(fC|u9tqR`^3~fzq0z}AUNDq}O zwzVEsdq3x1nmojP$|FNrZ0qsoyd+Jg;W zEe~5?;YbB7qXr+D5UcY8t-j=aFpFf-wIBZ@*5ty?d46%GU+Mxq7zs@SO0SBU^D0i86j$NDhXpFwP(m|0$fKxd!Z z*63|VcOQ;TVErYZt+AUre~(mlvH#D8?jdLRq*yv53(ph)Syi)SJi7ZnnRj4jr0Eds z!G1d3ry?%m@7N}R7=ZJ|D**88iTjN}6?6&)9*%t*Ed+1iV-MX!K#qUxrd#8bRc~X4 zexZ+}L%7NHp0*)Dw@Qp~AjsqU`(N#Dwg2~`F!>k>rjbhEqA~TeuhbGU?A+|c&I4j^ zMYke;8r<@>bvIW8>UKp8XQD;BIE!0=7~;KBf7JyHuUWS5FfhzIg_XNfC!ILUSL1!{z_x)sXOEg+9}hdL`5OXKp+q* zbVpjiD1rX*{ae0;RSRa1)STht@_rgM$lyE*MvTCZ3a7REYc~MsQytgSz!WKReZo^_ zE6pwlye4Gd;SbkDTQ2F?TlWzAwgF3;pOWyYAHAPTnGyS`R=}WjDGsCiPrAO~Ua6G7 zS_+JUvU<361KgRy((ipVal{`e5kX>H&J-8&0`2P_ll9)LG4bUwq zoL)iDG&J{*u`k+a-okTM`~`U^7UM6FNi9SH+eMwO+i?Gj;W??nwnys2|z z+5B}Oz7S8|WK$N*SU2cnbCZ&io?khzN~CG(Gm83l*M8zejeTL~S6-lJi3@lR&SZo7 zz5@A`*SxigI`+weBc2{^7nFZNOkhw*=LIZ9IP|VK5w0$DPU`=vW~%JuF-ZI}Cl(!z z6zIItQw{R^&gZpKKR$z)7Vsjd?Or!aLorrJF^!GB@;C^$ygR=AwWss*MEg}2PTJa9 zX0R>hQL+{5KphA&K`wQV_#Q%Jrz&()Db>2BEJTl$oa8Wy@KB)W>nW}Qfji8k6c!RS zs6(?hB~B_@{pS98nc&?R-1y|s!!kB3+u}t78c4`2fTx7cY2Kw(v%;xRT>6p3AyMsQ zLs+uuHH*s=3fOilC}6WH{jTgh!Z|hPsC4I%Doo&lmJWkHN)m#_if7~F<>EdzJ14;m_46>Y&|YADx}YeYq&9me=;zcs%b0!oL5{rFU<}PFR&2Cf ze^Vr$e1)e|>-Z;tCRehJWwTU@wmy@@jk8Y*%r0rAy^A(X1d0QrxDQS0@l8s45Fk>b zXaMRg`Ii{ZHC=v_a^T}@QKk7oJqe;`5fs$0%oSQiD29$2Ms0*G13@Cw-aHjgL^K3V zk>U0L13rdZ$8^HnVM#S1ZjnuYC04IpQIwH_r1XSPU9rl)>6p(pY&!MyGYgIN1pBMg2E zA;l~htR}`y_L9=fosvwgZ?!?s`cjQnDfPqAx1nMX-!Otk&}ZCix+7gQ{!f2wo0UCa zy

c)NjpL=}yAN7eU*~w?|ey*Of~Ii7AJ&Cn`E!cH)&nh8K^d`~pO3z5xVv{q5h& z;=Y3!sN>VX3v){8CJaLF3#QO9uHi?06k##1pxC0^DPC;* zyF&5rn*{#-zaM~;-{=JHZ~9|4;!UKQJOENCIGLgG85oiqJKnb7q!h`7uqXr9v*r3W zSc=%9(j50}3=Gh-)u6V=SmiZU^F|KI)A829OWBZXEQFkpzE4lRT+H6r#_I2C4_A!k zv+W)j3+-sR@K&p*r8FS7KwrbK*vb`2FDbU@z(iI(44btA_-jFX#!EnPeXD5tx<76R zRzwxOiDy=@GJZXKX=sF##2{G$!005-QiK6--))?;r~Vl7D7;G39s6vs{lwae=i<@N z!DN;X)yKg7x^@Ii`d+UU7Zf(`FgMHq{Kv>E@^B)Ee#El%%JS6mb>XWqe>1=#lMI$U z!wxphxhoQp{bk#1c2S8ewv@l_iV^pou&^6*mC!flwK3Y;wHgw?j&zk;J>%V=@A-1? z*MwUiBgNoXZFSh~lYq@6wu1tI#3eLeW=ysvpJ22zE!8w9BAyoA?*cHcttfe;bt%as z@-3|9Y6%rDW)GgXPoq=dO5V-7^ZxKF97`2WAHZ|s)>8Wmij`cCw_-On>3$0S>||I# zqAMGKy;w>vhvqFC{rHqxn*62WcK)pDMP!S6%-xg>W}%DDhF=P08}AKf`PHjv#Aph9 zzw7j#EgYO^rW%y1u-)QAj|ZcNhprsa6a4)ah0~ zxpZ>tQ+u7IHQCYI-DWVZcuc{8(Ay$P-#)EtD?XO8nBAR?(gGo(f&T!)=U$^&ayVX! zQhw1>y#Rs&>M$h*V-Hh2xhTT?MwZrqoFTovq;n!>JAS8g$=E5=PcC^wcD_}U8I7-+C(d@w6DyHiGGYM;rT?eHtxOcet~^IUe9+C2)& z_oljDwCTuXBM8>{&GiC}EqshJO+$Fjyib=fq{{75ib9ZKuqZ z$iE?zzFwI}21YI*c4w28eDHe-J+)(;?OPHqDG=lTDVBj|?OyKfcVxd-MVOu7#DSQ8 z4Rhp;#hz|eRjTg0?DhOKwuky`W%`Bs@nWZBZ9NZCMCmP_|WN2GtVn5hc#g)Nc2tFsdK`NN9$ zFS3~UeYtJocL=iY>AfPwTZ1H*0X!#x)~{aTn)K@;Om@6ft2k{rYeKwZ!g_5~JgcD= zo-?v#?20#`W$ZY!(b97k7Ynl{i1ePH__l^0-P|XM7r}D$BE&iCx`haP1vnKOAT&T~ zM>}(KR^oe+13No4!O9UBZ43qQHq?K#@S6eGf9c=_!+C)h`&$g}-EUdg3gzcr`@z)v z_@+x5CSGwM*ZXT%RRMESGYM7#(JqBCFIs{7V}SPQVU>kms{rNwo!NP8p2)*quQquH zcsI5})n{5{lLq=v-JU`yQ30wD-2_Grwe#xx_tuScoD0!+seG&5UCu|HtKQY!Or-lf*laZde z!N4Os03En4N`!y;2lTi#^;-4O79zdCb6&mJOo}A5yauIvOU80~9kFzS`Cs;)F=>5J zHQ2Uofm~Cwl*_^d+BZ9cI@A zD0+{$ImFQD{7TX0#0}4*wOPu-MUS%wqK@)qyrfCNA{wnxY`c=r>}tuuO>M)jq88qR zBerSb17h&0^S#m0qumymYoJ5<8{N^5j~8u{jBWl|_BMXBkL&h)b{(R()t=$0}v9eZ1^zm6B_U6^47o!FtiCu=txPvg&kq@4ro z>Gxqy<3t>w)>*Z+1$JTLDEOs96C*bWy^@aF#sT_!9Oat0$*tFTG)aF{Iu$*Hrj>pV zY8y2*irpj$DO!LAswT)7IEjhMIi>ZzLxmtiweaO}mZ(6;!pC-MWv2RO5I2R*e$P{b z2`W9HLzN!)NPP<@+fOXQnG!+~c71`S7vOi8h}*T58O&e=lz54w{FqUuG$^or{a}op z`mOrEh|vcHYLVef3?3QMN^G4@qd|J*|@-FEVD5~sv1rH+hZdK67UkP;QQ&gToqrqZfShq#n{dsHdCk`l2r;!UJXHU=7xQ72fDjH@ zrYz58^j2r;IcsUMQA7O1Q6g;Vm%$rETXyEZQJz3fN>?QI$P(F?{RB9$ zRsb`Qmr-C`9eTni1Pf4$vA?htpY}dn<*E{}uGXRa^Z9n{JN&;$QOR@|=O=jE&pr2@ zdz)88MfO-{YUoqST%>fLr08yyu|eYz<0_a7xNPNLy?LrukVv;F{uAgf7DP{>D9@T= zH2E|CuU#MW3f_;WoD_zaSEWrp1#@pQP@-LWp7RQ!ulMEeV^!GwC5@%mZ1kN1kgROk z43mrEu;`f8k^3CD(VvhNidEhqVg)SM-!5OG^b4qQBafHyeWZfWw^SDq1l*l#b$#0; za15+HC|x@mhGQKkweibQ{e6tEr6%$@W)*>qAg*l6ryhqRjX8Fca$DP^fiSQa6T2KP zM7!b*M9tx>1qXY+39$@3tpYJu6{U+?K*^MmZ=ZWu>~T2A1FE7}ci(K=%Q)hDhgvb@ zEe<3iylLU z;B|qfuU`4idC)a1`vq3 zrzq275|$CAG%l}O>#g)@1Zqrj-23fl;CBkGZ zo+$D+iS~DI0(Gmw$+)E%7+LLu9S-wpQ^@$@vvP_i-Tb8!%PlM}wx`vnS4Z zJIgmf*IJiq6+ex^f;}eo(=*?3&kZ{F(_D^~548R;#B&zo<2d{t$+D+i%194%2Vi;x{C90qB^z<^+HNOC~X&W$XDyAl~1>pkHtdLugpY%_=FX zFFVPcCY*5}Sj=YqCz<_^HPu2Vjc)J3Q2A3ZWv>A6FSkijKmg>uvXOuV^ryIuMCj@y zZCUYs58I%Az{l)<%UP(B$EJpaD4e)~@q+*NMgpRZLb3Zji^&3`qa84^ahRGm7p#ff zsAk({#GV<*o4qHH9V$K)m)KhUH#Y9H+)~XF;B(o&ulp6q+wr`?H;W-q4L)PwR=mU> zk*As7Kby$FJqT7FUI+aH_It&zkXhLz!ZzCO{Mp#+ZOcIk*!zbzSy@cu_J1- z*HMlqiH%K1>$vKfQSE5clB0WPg`p>*3ly`Ls(0Q|3Hwoft)RtP(0z^m7peSFV8LkZ zR;1b2S(R;{L*MDG-x1&yRpInxXIkC}aicQi0s>ASPzrJJg~pN}a~4Ia++-zXx4%W6 z@0gJo_1@DVmDm(Y_Hd_4DYAg7S*oa`fW}#>$gdl7QcrHSo@aP3RNCJka6iP@C`)x8 z-P^vh34D(+U44wj=#^oW9`I0$o6zRp4+8&-d_AzU2X#T=ejYBZPBPo zBNb|>_?x~Gwissm3yX}~y*R7=sd1R;*al-hcPiyn=PJ#Y+_yJvEN8eQuxf24j=1@U zCTsk>pUW6ErnPE3sSiR~71SD!K75XIy@2tb;0T(WhBI!ek8v$YCsNT(IzS@U7l1!> z`qjOupUX3QU~DjYIF~()ZAo78C%Z@>HtBP89?&QvPWNT;@l~HwT&*J`r zj(@XVMqhxLqjk3*QTn7`zC!;Q;TMlN#`?D_0DSMdmgSB|f(=F&pzOS)_a5wZe_`@w(}P6QEadlaeS>1q%L8RZr!7i(HHp9@EyPmZq&X<~|5P;jR5sjk z^hw40FsSOo;#B#$T(~Q$`@Cr?^yJQiQg4V3xymiP8_^(j z;9<&tWSYbLtBMSe@&rDV2Q7ytt{iC=)|8Z4^M;P&=3=?ClXRDT^xfOP)7E3gZjU(c z{|oW?dGK7#>URWF?aPMKPP;)qU**3Lr>jt3)aBHn7L?2C%I&izZ?GvQx=IAG!UWUe zD0PZ)aeI&AA3XrkPt-1YnMVqDX-CVQNXcy^1$j-Zx@hMEEE#=LY=p-WQ0U}T+%eq) z9NdGGRG*J~PZ#b?TuzE-*Jh=Dta$GYGe zFhXTkyubdY(6IHD&NhBq{gWAAk;6YFsy7n$8=p5L4L|(C5Eda0A(;MNx zE<8lqKlgk1zc4`1dm#sRtVol;;?=ADt!QA zYz)|@HOvh2MO&)Bw>r?X=3z ziPX^F!$&(825zT*URYj2loc~1It^*#_TnR$wH9awpKr4S{cZU{*+Qwu zAR+OnENbql=Yh@77UassZ{JOyoTu1Oki)Ws-4lR=!(xkr)%f;TQGSXI!c@M=r6B4D z84j5WW?c7FUq64?6*ANZ?hoN7gCq|^)61=T9Spo~C6|!ow&d>e=U-6`68ky>k zN>|dtGOEB(FS!wb6hcY(iK+AF_9E0s_6xBPmxEX1&l7QdBxU=HIm%xd^h+^F@et`w+7Z()AZ;E7>#1WxJHw8W;`ySA)Ca5uyBcpvj+^4HJyE{hFyuHE6 zMULX`Hg#>|EAwE@Z7O4#Xt{1KrssOBaA}Ew;#h?uY3ah-0o+b9y3xq|xz73s{Zh~o zDLjpoGK`SEtLZk@qZwr2`hNXo60Z3T;m*OmCr|&py+S>u-VdSRMN@q2hp16mSQT9K zHuX#w3K2~t8{Yb=KGrYTNm&!13I5+st}$$VzNy;*HW-mxosh3maJym%5}AH+u8iHK zl7;=&zaa}QL6@amk9H4%YsecQ7d~h>UHx?n*{a-W%<}Z01{w*;Ut(PtCVL@HT*4zF zX6fONDPFW8w8Q&dUiN~J3S-a3i`1u(|0yr}-41$1O*q4AhQnq4M6OjQ4!#*2f<;jc zP-{^kY{!^Z1%9YJmWjsE>a&3V5n!&u#4Z(o;S3>0c3K*&fGe_Wa`WDB3_p6sKz-hL zqyvxAW}1M1-rSIrdsY=q%fk9!M54I>^m(kCyoLy+Hl8ZgYUIVAWju)*ET=gOS%BxD z17YyJ68R;LiSIu+;z!R*<=wlM#b4b&on>UBT8UV(P)GIk%Lz>a3q_)hj{h&Jnk9A~ zeTEn7cpzZ7N~$3%-8%;yGXY%x_fBRba-(2VzthNifr`8rX|nShue>5B`Sn9iYTe;n z+J?knA&ef-cWy#0_=JVF2#3jmAH7;OlUIN(Vj>m8T+b)11kCCSXE;`C?w&Mm6y+ z+U(<8Wug-c*5!p;&@?G(QSXc0<1R{fh(!gzetIHHUY{vLi_!HGDEuMq z(%k;E3gMnCP;}68us$Sv_!0%Io)Lf)x!@Mkdb@GAE6V%L$eXi&XN&({7`jNxc)T{k zBXT)rF#!f|Dz4EwKkV(VLH2k5gp@oey>gE(vUI*W^{+$eTwF`Q?)Cpe({;yF{f2Fh zW1Q@hjI#G$Nn{;+Maa%LNHRi1WMq$&>`f9P%CR!5V`r98RFs*KY#E{VKEL;UKl=1X zIqQ3#@AKUEbzS#$eK7WGyOhZs4=5jfz5BTNWA%T|UXjBNr0q&G(;0gpBs%@>@KaT# zuJDwC)##Ug0v&f7hIsyR7q?C~m^dp<&gYzt@p)s>uk)+h>eL>bU366Zq;y#LYR`c2 zXkFt{QNozh_&d2ANSWyAoO`VDw!eYS9?Wnj7n)A6P&dp1k2uT`*xW7i7jm~#qlA#m zzk>+gn43+UWcgusOnKL8vRX)wTR?YzVQ0eaAxVRis#oe%agPhNYCCGk9quFSc?Wio zY}*FITT4Gld;387N=ih&%E{*Ag(1D|X2yxZ1>POnIaf#xm<1mAQQalbXeVDLYPtPz zZ4y>~bSg>Z+fpXC|F(Vh;0@JH$PsBVN=f-}Tsg;gULu8aJP!xj@UOLt4rGtVb)Qq< zAakeh>Tj@HF)dGEE+k|c^9bPLI;LMKfzE?qT(fY1=L&+!+Agpzu{wF!OXSk!wUp+# zdkzk@I%d=8@6eHLjj4xhh`ubeWG|i>>wadivw~!^PzFC>oDe?6#ndtb1?4q%616@nIJib zc4u2H$>-BQJJwp(#qF7LNj}Rv4?dQE-~7y1lJo4#=H$R@luIO4K@n$q{P*nsuu|Op z6Qdk*sH007;^Jad`Y>VVP54A(^YB@Bp}GEMyDy*2l$^X)AV;J5<&OIzYx*ujrugAu zMb)w}$sfa?v9<#)-Ip}1o;DS3;ZDe^Gp=pl@pvvikyPyubT;yY>3#@>b;Jau5S3i!cVzRq z5(r}t&5EuSbt{?F|Dc35Z}8!){U}`fOKn%=AO7cTj{B?R1I5kG(_1e`73q5E&r&c0 z4>*6eT`I~~S7DlAn13xBck1Gbg5?G@A8F2WQw2T==}OQU5^_@F^(Ph#+p5?p5?)Ug z`GeLebKddN%V)Yw9AvGpPJ6mNJWKRzg5zX^JUllFyx-q{u%gX+*AYvbDNGyXGG}xL z#-QKtc;JxFEHGiW<;EW>jc|WA)*$sw+VB|Y1sWOipx>+Ix9owC!=1Rcpf*w_ibjrT zPFnZyDI4)9+J+BS?vp=NK%DU*E1-oX)}liO?F)Lk6P?^?*TfAv6cUmp|n`Bt1-w-C9jMtoy} z<7%~bwH=9@!Qwp-ofiQwf*2C{)x4W@YBc;!YDjq2&}zOR@nrYYlVo@90qUNPugRi@ zo>v;_F2`}Qtb&1YkN8P1^A5-`7$GR+EpG~E7W2m?a#f>&EU9O$XY)Miu1V2tP7Wbw zvJoR&VyEvO?QhNkRg?KWkNz$W`)xVj8~ss$;nw_}3dUKr-K)-DkJ$kmH4(Thf59(@ zT)=OG)VoGCub-RNxDUAyMQYs5tNxB?3V{jfxv@p)o_h_HFK;(YO8?p0^rBZOq~uo=N?_`+cdOI+QCQ`X_pg4 z(6G65R~5wGvtMNj#?fj}H}SU@{fugRO*zs&8QG?mh=e&#L6&HAdZ3YT3A;W3Xkz4DOs@)l`s@ria+R$9Hspo zp5^wjFr1gS1^j@zM7*i=126fT$Uc{BJVobi*d`(Ha5OVtlP2K?SVS#Ekc^LEE=ghj zNo!3an)AFVcT_0&L@<`OnPC7iajfIIIG%cRSMm#Hh6?A3Ab8ojQ)!)#^UYHDp!~Pe zCfD-*#6vkGK0P+ID6Hc>^)E;|sPr>BoON zk#F^SBv`LO(ERk+)hp@FOY2QBS1;W9Dx*tP0B)r|w9&p5L_f*$B;^9<)td~%TM1>) z?)#U9%r!oAugL7UkZ0}iXmzOUKr#9{m zlJ#UXCZ)5Eqs`*Y?JM4?4mvhsZ7%dv?7g`i5{lH;|n zb|nKQm+2*ToXSr>Os#3lOblvyZTV!_#j_{8fP7bc=NL4(^N7Bzuw5_C5ax{$~)@;ija>6Dw_ z8!o%wX2u*Ms!Llu9j6*bQCEw)w<7w)cQ&Kfil!zaYGavMxv5d~f7xgCNDr0UzI$fI z>bV~~vqyco|9NXH#1l%bBAsZ(hIdPbm}L_0H=IT6q5BTY4=~gi*>41LywriHt-8I7 zB#KOc!H~_ySI;a#IKCo{o-dgEq6eUFDN8f*k*92_I+1az**Z(nf}5PK43_aMj5i3^ z^4GI+uYKEU$LO>J-v{P>8PQ+M?z_Ax^$aaEJwBfQz4uM+mO3wHdJ#IbzhdpdPmHM~ zU;WCAPsW8_C3@PyrGMKfd%Gko*ywspP*FEe(ftxMeh-||T2H;X=&s5&5Vf7BM7GHh z6pf%@)JVBRU;6#aF}MG`_doEqqtMK2b2Y=WcPmFNsEn{s$W|G-<+aO&8%0bwc|~y% z)5p9>ykwcy*Wo_Ze)MW*m8y1!dHWB~gW|8EI-!hw8gBbXZ7R&Km@SEh{bn`7gY$@E zMcM6*U$By~lH{v&Ies>Ne}3Rjww&ASZEh_UBzGKfA9p|J>$$g*Ny!JbaUCy5nfwKI zpNZp|4B-{eX$`?qpSlNP~rPPC{w zI;Ei7Mu3CFu7})Fher00!;Q=w8~U^qpGPV=5q^!Bc!6x1VTtBOkJq;sjYxOiueC;QN@vphiRAkta=+_Fc_|rLEsZ-KW7Re#W6iA&aJ3?{Y(6};P@1w?laltIsf+QNe_Ear3?keH2~sU78c}spD9*< zpp@lljEi&P^yq+C9IW=oOD`||_$F5AE%ouuhOqcu>$kd0;$*FfkAa3XCfM|(pG<^R zhLz=zux(S%os-p|x;<9vYGA*_o`7YjtM=sK=+nB~^>YP@%h9l>;x-JoqGaHYIB?Ft z-Mok=RsYcc!oU5k>W`IEhh1*5>|9Qi{nxrF$O9-8&N_f%+9dhRY$qkQiqwS{G?M zVkL>%QSFR0Mq^=yVk^9QCCEKS)`>4qjNZn2$GVs9&~{XEEEsciKJ)*ZIbK6wUbE+u z(4Lk>3G~RVvJ|yo@p(r zVkITkViOd2ShJ)eGOF(7YdH=JSZ?^NOHmt5s5DE2AzJp4Cd~I-*il&z6MbT4&TmCZ-jE3p-a)B)n_nkD$Sc^ z#)l!2A6Q^#ufoS(_(wD$NLTBvX>}%-GIKJHPdVKlPeP*mjmR~yu z&FI#JZnHj8V`e|CJqlX~k{N8+38hKTfUB6VK3J4@{%y9v)@b&kwym#h+cq*|srGFH z2Km`MIl8hHoYeQ~&$!rL{xahjR!^iRBpT+5WxBvsxwVxcu`NSm_5>RCP&o&|rjE0( z54(H6;Rk(#xaQ@vSIB5RH$fqHCpT92i47Ij;pXBGk){i>7q%Y|2e+I#@3xgwb(mNk zWmXvOElK1#WsM{^PPIWh=y|SdKSXYAHbl%RkQ{Upy&_M0exr&YzOWc5nNt9L^W>L8 z>g(r7_5*fW*cm$L3RX}`i`wM%mM4Ls@+6gEDROuF(P zETRIi$bU%9{`q@gY%*$WbyfcgGyb+vO0uN9koV-~k0pM=`sdyA8$8~pJdbrQv=)hF zf)1!8IC>SL(KG?F)taXGgn288c`^zx3kexXm!uI0^f#fvJx8M@#anVTb#$=ptdoz+ z4X<4zrDTk*{0T* z2PAQ^fI&{$>VurG^6f;9qK$$Yjozp0CXIh;qO0xhfYIbY&ISEeu=Le5$+75?45L7= z$uvInr5@s=XN-z8a9>1wuuzr(kdW0aaDUtw8*PzA?HQ zOI^%FLWc!7DVLzAk%Q3)ZZC@P_mF2P3?u8JwjvsK;b}~9?&XBxUW7I63cGeKd>qn2 z)U&xHfgivDY-z~cp4H&F@xVzY)|5YL1O^vLL&M^JuoSNm2}sJikboZO)or;Dg3H%H zzQRS0M?;n(n*yIe&379hh6IS->->Bv*t!knbW8d~IR7q*oC4?yx?VPX7Y3uZm7|U% zlb=4j+EOYMA?)r?a8C)~gCmp!j)3?gDp*LCyNN<{?Aw)qxCkO)Qs5Qi^lAT#jcuoz8_qMWJ0>2PrG$)xfzR?ph8Q30;{ExY!$3MjajUS#+n% z?Q6PFd+0#b>GpB@u2MfA{pTusm0_4EGg802#5UOd z*5ixxCb(IkX3e04o^gbnwq#biS2N9cq0warzn3bpL4~t1%O8aF-;GxVKEL0igf+Oj z653<&{Uo#R+hKu8rQhe#rSalV>$~eai#8%gA9VFUeg@mND}+hCr0|THJNWeWO-Bag zHt-38ga%{ysXDpYn}L6awso@_M$8&nZnUu%G}4yXYn1UUk?JuztktJ&{OiRxDjqx4 zi!aUDzcY6=vpQ5LSl;_w*V>?5`#n|b|5(1kj>AX0-*fEVN!&3AT**KD^u#y@aVNS> zq;njm$Vz_23p*S7SBJ(*lKpcf>P8GJChbd>rqyD*(Z3h2JmMG;W-W6MJ@aZz;`isO zmjQx*hIFlW-yDAGzxtu<`3s))Pxap!3uY1?`yE5xW*WKcA+4in{irp^yFEf7ab(W< z=*Rgl?H^GhQIxXVgt;RXGO|!-I*X#*?oRWBinAW`9eBhTelBOvjdS_K%jE}ec*Kl^ zAMG9|Rtf(T$P(Q>8hvtNdJw%Zlw(mIq%4t9I?T`EcTX-LdCEWEyOIl|N-EMyHNMJe}HO@qNOya;BGX9+fj+zP4M zEM&p~)$(fOHM24W-YK6o^AxFwXR0j5bidn+|8$QehM#b6sjxUg1ax(mB~^pp=0br2 z_d|nqQ0XT=I?ZTrL2fVY;jXT+-&4VL{dn%$AXqX3^c-jf# z$w})3q@w?2e_|{?j)w$O)Z325V>wN!u&fa@l4Sa15nUKKTtykc(G`Shhdobcc;T`}vNJh`LVr7H(0nRAA>5dWnIqn>M^KPvYefIvGEy z2M0H(nBj+)o|()T-<%JR9g-+i`=2=N>wS`X7$ebz(W)nekGDkrO7j zrPq}+1Gj>Fw4-LQY12()M@~dEi8HhN9nU}!8LP5gPk4)R%owwX#%vhsLp>)-t>`3t z;?cb}ED@rej{fAfD}~iRIT?Av%Oewr(>77d{*Zn~mRsHX5=};U<}$yADIb=Xl#vXIm~<&3u)Ev-na+{Zf|p8CaGU?}@1%jN9l@c+uMV|Wo<>zx!eR?# zxbhT47?hKd&^uxQ9+D1|HBTnYciqnp<-DtrH4}BfBL4H6q$F7IJ76#5DgH;uq*nKS z!g8uIb7~9|;Ix4N+ILrvlD%ifB{tAh^nd<+Q8>L{(f#{hRZySkH_g;v? z-__$)mjIO(-_KSb?tPYK6B4-`P9*AZRH#qP>BUEkmQ2UP-ad~HCn31?M5<%+0i{bmMHR169 zslzEuY}p1!Q}0-)u~2r9l(!ypNc%uYnB}z<t zDsUmfueM_Yv3a*Yxz6tq?q?j~-3_A|H?6#XM@zij zSK~Lxng4oHG9o3eU8?qYFNFwItcQgIdjzZiOe&EG`%{&6L}FKBj8 zb@eq2sjXazPP~#Q$3-wr1MfKLJBA7vn{%rxQYm1ra4z3}LHd+nkGD;sj?Sh*{Hvq|gO`sM7&9?VG4}at22)H+7=drt0A>Kn5>Byq(EZSmZLK zxG%ten}F4YklBkg8&LO2LsUaRi>o`lFWi}n=Xi+G`w2wmOn=sYNQ~R~QfJHQaC(2G zsH8D%9|)W+#B{dgy>{xM0b5Fo`CPBJ$sh*lgY~|Utj(URmo5y&OE7nn&w>eK&192r z|H1a6Gnn6uKu~TVP?8JqZ$2wyLZ4ha1Jw@*mX9D;nJ0KggXcV@s6AL4CKH^Sw7?s( zX z3zS++-uGonJXs69m`}tMO4019HNk}5P$51Fn}Qrt8TZcv|04YkC`g`1@ij;N+&b94 zyeHnWDjf(ndRkG`f~x2lM|r6fPH!x)kR=YgWCAI2Y0_lwES2`oeQ7A$4ps1eA8Eb& zEjK_c-t*VRzv>9yX(;R99D)J1*yw=h+oLi)u5?y+qOIKAqTEWi;? zf23Mx5kegGEDXzZ9eSxWbrod~BMEL*C-Ty3q*VAAH3V$2=BF`5Yrx<_XI~(_{KNd@=wR3Dw6Yd6<$k`yI3Gg|^gCAw za=q~AftL|U=i(*r{F0lHfDdr@G~R_eqSk-uW7`xPwdFc&JA96BP!qM&2Q!SqraE@e z$^-%ikp7_qe4ZB|{M1wxJEbVc6FoL~?EFI~4B4tpG_()*ZR*J7vEMIxDJOk+-)?Lq zgw3*sgTtw&=1{DcWn~%*#m0k1EC7@76&;qLJ0{ZBmThHGT^H&_H4wZ>2x1S@W(e-S zS{B}5t;*@0frA;iE&UG<1cbsbL8wS&Fn&6YL;uD=R&q*hXysx4+o2Mj=PqHtQ^WqD zuy-%L{X3nYf14>BHf-D_4ZXwFSLK^tUO-q0fEHG7JDliWjgD^XF0YZeB5|WX+bIJ@ zzncqFTYCCg*KR}{a}wW2hn=Z}d4dzxydLc{a(qTc*n-sGUvD{a!$=n|CZr0pOer|&07rD3QB6}#+^s|_5#E0+_d!aE!o~v>5 ziw_kRC91uQ?j~|Qwd1;^Am)JLO0Z-$&ogy;#dQxB#dZl8wCJJK^{6fT+7~HqY3dQ3 z0Dxac%Q7FYk#!1rQhE}UJ=nLJawob4*> zgw1Y*sli}xX_&_`=jlxp-a%De&3d(H?1WB0^plK^f0ABz&Q0xi6J&4#?x8quI6`_l zX*c-;1r$bCsIhP?OcJm42*)^HaZB|c44#a(`$32$~&pZ48;VSp;kmy5y~lM3T$%N5=WQkguq z@?xtDsDJ`Iu<*jbpPQ<9DycAY(Ek62m-zveXkRtE0(*5WeW-1TUU~|M35u6*Lj7)5 z?RU|;KiQ~#=!ptPYxZkwXYbl;E66}7yZHVWAw0#oE8+*! zPx4cYmzU{6q}KsFEAyE_;ctJ~-<&fmOMtvX;RVWg{2NZAcJ!3PO7!jO$FPG8(Zd=! z!tF-r$M~jA4*N`}Ns4NZ9Abw$$P;hiqR=K!)uN4_OS=qJ9<{0ooLmYUiQUI0&x08E z%u%53!1Q9tW=$15&u27-f`9)L_ZV&0F%r?hisD;^jbZHx%O6QeWJcVJYub|+s|%e76^(OmiYB;fEi!w{UPjzQ;G&FCqo-%2P)QhJBwb#*&;t{$ zo9k}~MI5SD`0hN+$8ZADk^koW`_GC7Vg1Pk1oO1aG!?K zCx%?cs^_RjytKOsz!2_{Bgm_n2YiXXYFo`3A!70Ba%!i-?@!aM&-g^;dH zf_t_f3Zj?(f7)1TUrQQ%5JT6;8QKTP}agAghi?5YJBX%#oZX2)TC_T#=W*}&fK zZ_kHjlpG^KzkK<26h{;jqArH)&Sn_>_O498W!R}j!=ZkD(TJ_96wv>e{TIGdVqY2e z2?*9QGcr1Qf#-P3`!qn+b>&+_)g*v#dczSCv}sL*k%}bDSyx}I&}iOCy*msJ6ucmR zXV{&{R&j$x=3kK)BCvbaURjcL{1e1(SDc!qP+M^NR6=oc5n zciU_~izte@qXoj66kyWJHyCDA?eY)2&fKqHrc{xcTkJ}KWx9--RzQ~j*qD1VD@Hh% z>0*UPQg}1S-yQ$Cri%Tz`lXgK)OKh6hstav4TrK#(mP2Q3t#TzOi`G%2S2bY&46ld zutZ{{&dGTfrioY>3eo%nfyKzwxiP{Ft2zCK6Ddn4dIMZYoj0c2giD#zzQgxq3(YM0 z)XoZNOpe-e^xGQ3owvpt#!+Xfi`S#=x`sq7o{m`#N0(Yvwm)|VRMJiN*O0=x>91cp z$&n0laV?I#xFwAga7vC5=X#S^y3b|Logr|c&5+UNc^tGGeB5Nm($b>#Mp#0kkqrG} zb!TpzidAQKKsXZ4Vnqy*xQryLq;Uf|e}7>@cwLn0%<%oEznYE!cy}Y`z1#x(s+qpy z2D!c#x7hi%zR1H1Z9c3d@7-ihLP=HjKe$FT4Qte$cm#) zNdY6rYMF;o)5&Q+J`Rdsn)WG9;E%NBB7RJdUu56XkT!1U;Wr$g!U#KT>^|7(dMvRi zbhT8_UR-Xp&WQh2ue2O>B~P(VZiU;Dy`C%v@x@ zn?isLmu@+fHLRdi~Fs3#eTH;u}5zRMHfheJODkPNa7;Yr?K*H<=!x@}LVH3^+zI)NX z^2-#DEuG+qzdCb(K=~F=G;ZmSM=(XGw#MK8Il#x z5gD}ePdhpI0uclT=j)mH=~sty^X_&349|S+`*o~RP5Gpeppu@)Z8$Q`l5mv^<313r{T@eMt^n}jh!adz_}OwJoOs1$_3Z`VaNEzW2v z4?<&T1#6fOPO@}v%?Iy+0jFP?24ngP1kOz$N%9St^nbnf;hm5C$oAFu#7SWfI+a!ct496N@BBAGoETqeJ=q(2` zyq(oASA}?V?$NZZ4Rgk^97W*cop_1SblC)F!du@m;+sQuB#|blNIt5kT!L$yg;(w* znrh*wH1%-o%dHApDK-)&_5A$f!s~=G1RYK|g9z9G+!}T(vVYG;!gnPZRaVF++MVh! zw{TOBf73`;Q4CW&V(x5M3kE5WFiK#NN z9Wp2sVgz6g3Ps+PZmk-~SGZTXxa!%8L{vnzp&>r*T~~knf{hk*49ZEM!fvj#==F>3 zPwu@vXUjW%7jfQYC=DRJ!;q|Sc6)e7mhFZGiY!aL4fi(6dFN@Kof zg;ga~@x_m`=$T7Gu;ZsFf8!_KLjwq&`c=^!5)tm<(P z$uAs|)x{qplZq%D0&fc4{by4$(t#ItuymnqcwLN;j@#qbAU)YZ^qUq(O&ZCyr+Ur3 zVHBb4fl?;}6p~kkObKFUDt1N7LXTr8?+_KAK=Z}w<_RUMaMCXV6$9@eqBV8mC2HYp zAKSow9PS;=@?^{2${~zGPbK)n?+Aqa{gV!lQ#5^YntVTu+GR;YWr80%o*)WN$z8bO z#bAB1w#*RZhzhU!QJ5h!Go;tVntj-+amqMZPi+l+;WS}pfgi{%^Pw`ZUb<>7-sxKb z1j1RDqg>BsT_JmL?*)UCtT`e@ zcZZgLU%5?F&82Q1zDoP7Yl64#wbhjHU_&~(Q{jOKm6){!o?0|a> za0nY!!;M$rgp`RwXI=EN3wNq8{{d974GR;E)A%9tSt?qnU=aF5!Sz3S>rQvq~X1`RXTiM-@pK@0W2t<3E~4du64i=u^5in6%wjNx^9Ht z5Hx+H{f{9g*tp2R($20b%=$a?IXH>DFN8y%-wSoY0u)fbekxz&w<(b3gbk8b@f~t7 zD9iCv+68xW7U}D8oI)3a-+mAMd&?CX(8_Pzc7Qdvem#yWc@N59JAw_I8Kd93qpf}d z_V{r~H%;}MCj+$3aw2g4OkBajmKTx4fSbP>p*qdMl%DjjRN7QxU9xki1sK-yxXyA( zij_ALYSfEIhWVHHqKH~plhX*92&gF+Q|9vLxYRP6CZFYuU2p24!;SMI=9O8)zZ0Jj z1`LYfa+*NeNY7tK3v%2*ij)&piEFiez+X{|=t(@mDn6LMad*4VNk?gT3UeR*b146s zm~)%3mTn#q1Md2reZ{~n-tU%C3Q2Knj8Z&p^}wt%+xiU3Z#?50xG>t5m=xxOr1K$H z;V%!9mnBVxh0pf+VZT4rR09G; zBFv}#azA{cyg+70SfEVoSMTp7D?6MN*e50;i|8?m>QP@Eiq>wX9R-PfB(MP{LAdIN zTBO_;VtPG1bY5zHHvlA(pRm(iw~@SP5H}ctszb*t=tSuk@@j|ayY}9ue3$URLyrEf zKsc5T!|8gR+7;vul4JwMr95;u`KU4^g&md)PzAVTA_gmA2U&y*fZN=N4N}<8*iQSk z+%#NW(<@BJ>5DgMw6c19UW<+XZKWQjmvzC$N(9xIjZfy$z7Al*2)L$Pyqg+Qn?=|o zZ{6iR_7M&3vkcKdJUq=vPc4xYR)qoxQycK^ZjGt81q&0Alyzvb9v=;}MVj6T+EeR~EGl{0-8ME`j$o$X54^S zQGe9&l%eM4aM4HkdDlwodbcGd+M?5V+Hiu9TcWc9nvu8MVH#7g!QLqHv>$ZyiF}Io zH%2+(Kku^_fRDD_2Bmn;^$!KMg_Seu=v+LI9NDHPgA*5Ok+7$oLqYnh-B0l1f_Z?u zPJ0sqxhUj4d35DW-W5L4x6fa}h0;Ssax*Sh!3JiEpY15u8x{~HwiMMvD07B6zu#Ku z*M}K|5XrMNTxPI@002Cu;(DnC&;xfy&xO+OadABxh;&JHQAJ(ETRx)L;7Va59U^2I z-~u^zYnxHZFozw8(6ggr+tZ6%Xv0Fh0uMf2-1cUtASO27+dgH2n zd6X?OU*&$Ns!qLWy!(2H6W&6;m7$yq6)NQKjY~Ab z^d>Ze>!SEhs4jpriI}dV5V|LAp5mjFio9oQ06U`dppKjWL*m_(uv}Cy==KSWPdfXD!Q<;c@^~ z=?OBRYdy0C15no#&fNPn&bG`PUGEMm-nzJ1{+GsBTYWS6a#G?YjRR4)#7E z@?RaA0s;j4P4cOfQ(Xcumeog2X+QlnGoa4Gv`9$m(CJwIQ_>p8@rC2+S2|V{>18XjcyncYZ3oR{!@mLC!ESw*~Wa|J#Z^88Th;1lJ`{DaofWS1p+Ii*$S-S_SM0%npIMV|F70d1a z^RB4j?{55*(Vs&)n$bN$0eg%X6wv29#V?QDqV&9SajQZ7(ev2kdyDy#T=AC11h>Mi zANRnxt30ekIe*y=!+IVU{g~BKec3+}f2wrP-Bp6i+7AbeAwsE<5 zuxv>4a)W(m)idXJU=mR}?j8RiijPV^i7>b!14g&qk2%)cdU|qgW4O(s=w|^h$V1#6 zABH;vcmJ!Lw^4ZVbaTn=ro(zIVTb#Jm8bP4;8K;qKIXHSfA?_rz~^@(p^_xjd03h} z#!EjHlt?_DAP2a@c)|33Jp+)4+^byfn@X^_?i*B3DLYJ%9>6?vZxWY!@V}%czcB1$ zdAyArAH3uP#czDX@RFw>2u^{2MV8~GmwPe#&-mC^S5zdAvZy4~Nj`((NC zENlB8>8r-sQ)kRL+HU952|E}Xx#aRrU{`ZmM#H&6%kAHz}#?a>K4;z5o**xYJ{n+*rNoH zI_<6(FQ5`lAH=O8DX`*&!A_p5jGYwyNnDXrgEdM3Fq}q#T+o7VMQhsY6pB|3&g4Y% zwg}P%KzBdoOZ}r$CIM}o^gGATS!m(`)X#3u@GWiktf{dt?5HelqHOb|vfPSuKc%Qm z3{2ba)Kc>exam)TEqgI^a?R#}OJsDwlmhL0ywlW(efnsPDQID~v|_*LkJA^T zOLNf*q7FcArHNYAEdBQ=!pRGSwO5cu((5?Atltw~I8j+@Sg7Yr#GaG@{=(V~X9jmDHxdsGr2t=ZPdE*(z7O1s1_?=w#qMFqI4 z${m+{g(Co$oq?1BJh1LgzFg>0W3%kNouxbDCQ7#fqwj^&(&VMq)V~R*$EXPA7|M24 ztOo?;(Y|B2cYn4MW%d(Tf~UUbY;q-3@=y1zx{`KNFiC{FG!+U+nHk1M>3WvTmX;mU z4bJJjTh8xb^9_VCNkYe`GtL%FH2oDUMpM_UUkD_b^osr~gN>;V%n?WZmXG&-WCHT1 zvpL%}YCCGk86e&r@MqQPcbapRp;dd~&M5lEm%189G%gAcM!%v!vN#oa>MxO1mtq3$lFY!4s6SBAyLgJ>Y zEFTudz=9;S(hysBdhDfcoj*aVOV~(FUs{_%c_8izQ*LSEwwDG|Rshy$`^*f8?6zt`9DL6CcVFxuW&{^NfQSuXkW#w?*sUFSv*=C@@=qq7PJdJtqJ_TbM zplm3AU$=-71wlRnyuSI0?wCzK{j`9gsV4AX5{*De8cu8qAX7F{RRD619t?c^n+irr>X?5JZ8Jp>vex(7%W6t{~;Pl}Pk!cxj_!qd(p>2oct_H)uXRiX+iNsv-_1aT}xYxr0S$ zE2KfDe!+i$Bdr$lIm(JBEzys(B_;etG_nL*zCDa3?T2HW`E-~_52zdXz#QR%IKGxQ ziIbSD@)XI9dOj-q)_CzCuD0`{Hb!qjNFqTX49vwX(`3S(Db0mNNmfYvQ*-c_igiI4 zVru&}NRTAQ47G@RScY2Z^s{_1>q_32Ylj=KgmTB3I&y1w>h6zdSq4madyP<<=Kecd zkm?*>d&cgbAtmY+A;h5aCL%#_-)IG=!J;oIv0r<2)$_wpb+s6JgNL}16?+D;$u7i; zB_pgHhRtZ|cRYgRfG|?GtV~|B%)Iw!wLG}=tgHufjkK#$1Sy5G&HMXhRu)MQZPtrl z<&Uq$|2b8W$!`e?Ya(|u#ossgmhG$a;!BLLQ04D33QTpN!+v(FZF}V?Unu8^#;32GQBqD}Sr;fCZc_)I;^!nM4j-?K| zSFbWW4F*B9yR)2^b!t3qtp;L;Mlo=LF+MRe6LK>$mFh9#^^46t*`L8)Z^Lf9iFlUT7dUq#3X78XP-_^ zf?$6}bMD?_XVul3&NUrT4#O--)u~Jm1=3RtNg#R>ysz*E9Ut~ma?`07Z7yQj`%$a$ zs#0YNGbMw_elk#$x)4Rgc9!ychhuD`lVwcjnsKLsZwp4~IV?dyb(I^c-Oq*AF`y+= z@hajcXRo;X=-~crWL-slU+bI2)nLC=0xe&w zyGLbL+NHUUKDLX=-gq5JD~BxARKWQ=2+=dj-O4upVIlXmW0PIawz04PJZwY~a(?zO zg19)yQd#>UGZ#$cKQQgw*=AlWRE<6&(oThM3uimgFsBf;?iJPU{>CKw%Qj^9()a%IuiQJqWb$H7VF@xXhw1s(dIo+G0b&mNkFxw+>ZoYs06&IrAgnAs z@xb!W$oj_ln+4BVIm1dWSI9bPoTXvg=1HCjM0?YMj&h0eXTib7wJT*&ECV+IGy61> zcIL#BV!QCl8>f$oSL8873c|l>T-p|N$oX>&QZNW49TUCE5ZyqI8p0e3e8%t>X8I}b zzunX-TA`Twxy*~=)V%~n)QnH@R40^Boma4cOu9v8Oq~>M?j`ZPF@#+)ilxp?7d>;D zZYF(r$)JW|yPRyoL70SuogLL``rXSVfAMBXDf zQKVa}KWB0i55y~XU48JW%TJ*adlb#aB+ST7{0-{cnCUSJ3k@#f3aEw>FpS2@d#hhg z&$w+pr%z)D$G$Y$NLe?-t#{gB4J9x7pSpN+LO1tTGUf<5O?w1~>3QS3NAE4AbpeCm z4vXX)cp!NO7tBe#3Yw3zPn`>1=Mw!yz@23FAo0NegUmOc@O_Hu^Tb2@pa^`hPL{zP z&I?6f0ufCH4v>&*XhVcN8{mNYP%-I5eGdF8j>sYzApHq<93UD`B50XPHFO8v^G}y^)QlX!ifeDhcnu)+X)~%3NEco zMw)Pi6%Km8Ux#i(_|t|RIxZL57s0Y=rWx*|kJZv|8MrRvRVi}+ zzY)tlopKKM&MNW~yP)ta98dm&@bC6(9uFl+XrnZ<-Hu%9`p_{qpcj>(RoY3~`TflT z0w)+s1X{22hlBXSkYEiCcdnT)_Qq8FShW2VKoVTtHN03cf_Ok$Gr2y_Du|h|rDJxy zs##sTXmmr)Z74+2w!>+xuX&layJ!v+m;JE6E&yrcdo(W2Ai2+O0vm6h0M7rnwey)O z^Orf>`3|%Qz~3y>%Ej$k8=d=;4{s!2*@A*Gi694bIR+?jNn(2fiNIb0rn7$MFJwf@ zr4$JUGvlI$B}DU1{YVWv5B+BDTkH^y)~CX>y=Xw0o6iNR@aPwDCIe~uI;lHw`|E+Q zaRIVGjBa;kEh+fbVdJt?ppP<150|oRQ7sE=a$tm}la9dGd__GD2xma!QZZTz=e8ZM zz2BvHCndwiQSI|_sp}hAE3LC^X&47@nGo(i3K~ zUN3q+{K)pr&{uv$cFZFV$&JR?NOqp;)I&xiSNS&@SlZSylt$RwO)Zn(e|yx?v*iK; z;alt0z%MP7WZIczsC+wj7pFRCy^Lj=kU=4H@ZiXKozN#ue_=p-N5Dd79&V^BR&{<~%+5^^Tti0W9&xBB8?}&DGnCsKehSz~2M!Xd@j8-s*Z5an$6maq zdj;0jJ$~1r>-`x9K0gPR|6cz#LE#NGc`-{%z84721+t}`O-{W0U;ny(jmmh2H{>pNe#UAo%XKjWZ_?=c?9)y%7lSdOP=mc+b0ToJK)7y9O;&g*eC zt8P#54?_v^pFW89CK1#Ypy#?1c;$HKAWYhQMXsYM`bR# z&qpXRY0#gUga}kdIa2$WQ&6Zb%Ie?cYEtz7l=bD|RJPsQY}>F=*yb|N!!{F2=6NP_ z<|$JW5i)G^n3*I~8A`-9G)XdNDkUK$Lxv)SRA%40d%yQMe!uT~{&|k$Ii79b`?{}d zU2C1|JkLcTNR)Oa%APmxSOU5jxcIo^ySh#b6YM$0d$Fu@Nzp738?>CSMo?t{lt-1i zWV}M!-EOHok6#-TcD49%89Um*A>8V|QC-#}*6yrri1>={?5;LM{^Zo=ANKkK8A%;4 z`l6qePW6CaBDwY{Xf#Nrdb^w9(X{rs{I#@TQR{# zW@MGmnS=OAuHRJ4K=zp5()C!mo$JU?ywC!j&L)7!6%3v|E4&rinclziUIj~;r@Z_ceMhA1bg=$GZ&;dWT39FZFhy~JQy}or+c#*SPvcb$ z>p3h4cs{g-Oci}zHI&HZsBXf-@OK>F=xXC=dGBi_d9bxD7R4gwvio6C3S*-~l+t?g zl%EjXRD^oEaYK|I-0uZMvJDb?;qNJ{%XoTdei=mRDUe_2&r(xS;s6?Tq2Vl)6#&Rd zpR>Ba0S|^DY=!UgY-?Uwo05y6d)6Sd-wnZRA#K|Q&O!Tf+SyIc7;rfn%(r%|aXq_x z=?Yu+1YDN}&SZ4eUA2u}E$pDj#vVH&0Av8IyS91nBS~=`f%URXEj=y_%5ba%E&JIO zDHbua;}KnL+l${koFprRW3dJN223N%H{9EJDn2YKf|`U#{bR>f#=<=8^T zh;M*eP6T~R+n=TKlr?f3krHN2(Qo`c^(!%)}{~0*ot|-Q7@W4iAVh=m6^}bodkF5EM%e$$V1Xo z<6nz`qL$;@cc~AcVE9^mj(k5S0HDI(q5#=_Zt_S22l1W;jfE!>fZf|*b8VruIB{lq zZ<=}7YijZ7#7-&nf|giIzJdDqn*z1#f5db@rfFQE|%B%ucu!PS>ETe>)d+Ba%rCce8xe5;H0L`u;DAnAdGe33lQG4Lk z$_G!7?^h*8Mo}(|l+7&jF0St*%a+q@TW!d?1K~Hf?PKf5Sbx%Yxz`st$M2eOJ_P}G z733s{X5`?(Ber)^GfcyNd_<6YfK=pz2u_PAafo|28NvjgAiaKJ?xCjkbTuRHY`)i_ z3u35*^qUcx99Tk`L^lJ=fZmhD{nXqw6jbMoPg0-()b-bGk?24Rd5&Kx>^XqEnQZ#| z`lor4YH+;+iqxB;L$a2rAlLnqeAH`3|a^9JtqClD%Biefg%@g_F((d|{Cr5@4x?3bV^X zYTU4#12@HO2<3sVkJcW~bbYtLn0){;rabdhr`G^q1^Io2zr_-M>N`D3*W?O-k2Ma@9+_zOxS)|h%;3qE zQSNV(gD^_n4zb_g*WN&mVZz(+BdhJCV?YRj{I%jy;|tIuWY9nbkYPf6X4VDzciiGE zN1S1ySd!1d@K{Pj{uJlvhL~{)b32>k(ApeAWazq=<||cLW=ExFZe+5Md(i)5akaPs zi|bL1)+r6t65Q$qsB`jsn;DB#1zqbA*L>@?T|$l(L#2`Jc_xYvc&IqSDhs-$km zJGcU>6e3|d`pxf?jl8{fInPS02n$c<>b*9)a~k9t&$s~3tiPwQQ5J*$N7@3^DudK^ z373VpMLw&GHOMg*a)F_m8BckodvEU?hV;<*f{SPy+^&NvLqCW$Fx|)X0ONy-3i>rM z1&s`P+{6vYZ=0t+%~lBzSjStoQ49?*a10B zGLxHN@*hkGCq3V}0=>A&BIYQk?4eFu}==-8o zBGQ;8jQRLxsZgwuQj|&LF`+KHG3P3E>CRn4gj9+V+W|#fwJotXQxz<3D!*9JpgHTV zx305&e4Zwi`7q??=Lhrok7>ZXJc-z+m+LxzQV z`_ge(D=@sE_t|@v3R*IAvE27H=X4UOS$RSe80!GajAovP<{YhxA7r*7FWezh*Z2(` zWo^Jq1=dfBnwG16jkrVJZ-=L*D*A13EfVxu7M4f*%SY7j;LzufGB-<^!gn7E;J5s? zv(2GV{la838LeateQE(it}crXACE_DN};CfNkDPG_SY(kcKc370q^K{W%L8(9vY1( zz3n9Kfxpo87k~UIFb$r`7zptt*yCf7KRzk$0IL3eW*}FPG+GyxsiL`oj1OQWF$ju_*>Ao&I6FR$n@jUeTBe<H;&NWWi zSjwPNg8KE2CnisF8>5BA#k8+?QN@M`FVTJld7skZ_7^&_A}B^JPx6|3KY;$fd7Vw; z70ZsfCtxM@?e#A-23gC%^po@4IK~-((;aq zvk-wgX3z+G3XV3@!quuQyc6;cFMHnRySd0rCI~ibs&g<->#5dxn%+BK05KOLKLC_x z>Wv85-2<<~@W$2ze1n|N7zJaTdf$V;+-yo*#99b*YvqVktS5qN-w=9dDa}-ZVKO1Q zJfESyeyM&oj)pE|%^~=`;pn-^FSi?^Wz>VSi2WRWrZ`mFfDuxRwfJeA32}@SS9f7apnPjbbZw5757~F5@ zIVzz)^s0Uh01zX}5Ot~ca;_2J)KnYzF% zy%&E|A!*V!34g1mS~3=!SQ1W%P$Rx)QInJM+}$z-i?{q z?$8ZFWNb;DX(%u_IZjaZ)ki1FGEMmc<(x4N+JE;Xxe0mR6I*^7jEBMH5)}>_Hk8A} zr%+#e@8RlKM|@vqFPZK|-;UO@T{|LOiM!);&y>50g6B(IR5MZiIi&nTxM~K!8AU7t z?u0$kLp{O*t)FJ`$XitJ6jfEfh}!4^jOH=VlCOiVaIA#V_FJxe!?~^m4XKj#gvz6N z*CN9@WkU;xFIlR|2ntk!hT2STQ z*78HQHXjr}wIc2|+U>CbE`spM`Kl*aX7XxBP5ij}PINQC^)6$V0Z6Cy^qr_fsQ4+U zZ^zGB(o0VKk_^w>Q5%-n|NC}u{%~FK?aJ7Vx39IruUl9-J+|umS{(A~tEDgfLEjIV zHdlIzCFWo0$52KRiRg|c;#%|^8B6Fpk=D-*f58;nBC7CH-TcAR1qxUCfGR9m)hYyk zWyCv&}nF%d3qUx?W}fjiO=+v^&&?(x&AGZU>ap>bQs?;!wyLW|=M z4uYGU2(&ydiu;#m(~<+&b-nx_!EwBGFM35oasfjx&<_XbKt?Dd9({*4ARkLM^iSM` z`*#D40cAmdB5Xhp)$fqT_8u0P51gZImaS=p(2-Udh%3Y0Z-TtXk-?a zZe2QcHi9f)QvP-8ncetfl0fmw2QtO83XSii7#qV5Ip}q;fIp0F{^%mY`hZ}5Ug?U} zC9;2t`->c^pS9$LU;S+Rl`(6Lw5lEyaJ*vieY4VmU4-e;d6v|3r-!j3E}q$2)@Kne z1`vJvL1vdPasP$(%ePs0DPrq7UY7w1v+Tz6bzUI| zK4v%mN}o4EtqY0-UH*j*e9lc)a4t5B!X~Q-t!`X+u2 z2#%eD1!5=Nmtt7=VB}DB#8Dlaq^q@*NPB+#^;K;JECKik(rChoz}+qHRysbC%)i^I z$mb5fEcR!2Thl7CxS^mDW#)@}WWKI+n?3b8x?>-@41Z1yjz?$^38$XE@^$vsMgSMc z1&KfA6ChxZa;tp!usIpoPkiAamP`vj@Odp-Qrcs%636=I@i5bKVgxdDdpn8cA7OJu}4fNDxp?Hs2H-3*;S(K5%5D87}WcFGe^cjV(;buPG2ocU2+2E znni66;&KiQ0=E0)PL2Trmk>@R&Q|)0@)U7bxZkHIW@N|Ngh0WN16CSCP}Op*6H?1vh>b&>2Rd9?4gy(jfVWFx5-LmRP&9W4{1&SOuo( zi4(bsDWAgbP3R`laEb%VArBC=9>a_%kUWQhozVh-B~b4-u~^=H&D{x#(^qce%#A2V zt{6Uw*&TamfXh_zb!I%?&c&}4NIDxXq=iA-V6%%#q91IYv;4_CUl-TZKL@j|Z}nB- zt}A0T)ruUv6C8a+i}aK%1#bil3%M-sThK-9^zm-b?m{JO`4(8?LcQXpds`k`e;?R1 zcFCXQ!=8)Ymw#E}!leaj;qYroP?gOeE z`^0)KHsq~D#a>Gjg-^}EIg_*beJO01Y`|1%>O^+iytjD}IKJl?wJufsi-3P6&Do-y zldn~yIY$%N6a)F%C{x~_T1l5z;ayUE`_y>iHjAL?i?{nHr^!~|Bh|cHUwSssj$|y* zFAI~PL#F63Nm}Wseh{{~fXUZ6>718)k(oU$Yp5Ot~zQ4(%%4(&Zh0WUtKbIMa1xQrT<)+j__O zSaAh^j1W3qE>B3lG906y{U?F$lEahb#FPG}2D(#c!5n~z{IciPZ|2F30eKU??dIEf(uB5GTV zO^LdZ=G;FC$~y={1tDuw!phq`fHXdtk5`^O%OD`un;tTQ@PGPHElDN!L$8njfx&K- z1+lj)xn$Maa)#|+o_}m5o_z{9lnqNhAfugHTVae!MW~e>E}=l+TVcy{#>u;KNREUa zmJh3Tn3V|#Pc`G0sYaOQedcUqP+mPwmTZfh3R2ytsXBww`Co$6;2tOWy(1`VttO%l zcP_{+e-&j|g2q{Gi)1JhVgEYku_CW=1tEVH!Ot&6w^i;QMKk}5#4+2Ww%P7OUH(aB zKGqBZe(s{STAqR=^v!Qk|EQykCO zql@PiL)Xh&|H4(iGQqL`c=i^(9<9VND`nhM^>PCDA8bKsxqH`c$U7tXs%PxuBK!B_ zRc%#|vUf=+&qJPArIX2_?~Q**!vt0!Q<0|TxBWWIlf&0fJh-@?B%KW%&?{C2S4!TM z=z7)%KYkfpsC&{h%2_XAo=M!)vGZi76L%;_xjWaqN+~gp+*jH4gic=CADr_5{V#I< zV?i5m%0y?h;;&LHXSSL~^(51IA0nW%z4-`hsVGIMn@yjjV5lP~U5iX-Iy9Qw=b!4F z*OiD@vA+ewqVAI%mH!O=yzxnO;G~?7#aFvJ61y%}y7}O<#7fQE#jZA#XBjzi@w&U0 zc++ZT(_VcwkhE%sff|}hWrSV_mMpCoCB-1#iVxin-KAC zHhn5zgFbCdI~aMIWcyn#fAKy!&Ll){Iy;}QS!b~^&guxexPy*~n>QvFwMa>MSD-LR zNh4HTvdq-3iyw9@=P^Q*nsDN*;!WkqR?VrmDHkx5PYxw=I41#%9a}n%OVD`x5nL`p zC&rFswu|P5XqZNz1y1$jT_xE53^E@dHy7IQl6Sn#k8?D~k)wc3Lm8iao*a`6)p}@` zAT@nFKd;S`@`!v1Cr3rI?!g2JIV0x}u^yB|`0%%)$9HLnBUtZ<8?E==Il?BAJQlb| zKhbEP5>lT2?FN^bF(*CM;CUq!DTb0^KfjzpHEdM0#zrJILA>beOLRg#w1IC+a?QC( z-xn->bQ`y_=V4*8t(dOUY@g^Pvl_{Bv12oN@icFzxlCQAX*IXa>v4(auF4zV6AW4| z5Zia36LGPnkM*64UF-#41Nr@yxogi!Sq4ur^asRXX;yIs&uKOq@&JQneR4v*It& z|w)iqEn0pvc*qo>PF}SI&+z^0_$6NO|+^=WfoVUnUUBYRU>GU`&J4- z2T!gz$!i2v=RdVsZADX;;>jnMdExcOzS3qt@BQZxI%_ytD6Zbt1CtpK=s^x(J61?> zgS(t<1LM7Wx*eDPWjCE=_q4R)j`vcf(zfe%xh38e&vkrP*(KSFpn*ZhtSLFTMEd?={yXwnOK$YMf>??R+k`V>T(G#c`K9 zqba_H64;Q|g8^GPod<`(W5Q?K_aP!d50;tMSVqj-M(7zX*tE{dKLK~q-|2Ybh&|AN z*OZE0BUI@JUu@yA# zqe#g%N@okBz%1ZvT5n_oV5+tJCvj%#JG*ee-aogIj;}Zs!RE}`jTI^gBNQ_jnR23s z$_Y`OPdT5-$swjNQ)?K(%eWV=N>dpM57KQLCcW@R#HJL^Va<0gM$EZAeWR~-uc8}5IB0ABXE|+43Q}Fvdg|B#SB?UjpC5rk!t3wn;gut((^aw~WniqAV+b1{K z*%o~$KOmyL(UQO(O;AQYUE=QN;fHn(p6&BHTBnF8F_T6_wHC223 z3EkxT&3by;tao-)4l>1^q5Y2q_W zCx$L=oL;)sY5ueOf_9|i0}_>L+KF^^ls0-+C*_#f`bZTJ4K)Rv_kQSpr>u~}ZN_hZ zquie&uz6NF%U38X-^#z(_~Qj;Hi;pY1Q4KPB9t{uthNWHK=SdCYycLKDx_-I=}oi= zzARI6ME90k)p}S{j{icdOH8~Idjh%(mI0Ct$?psrZG4)) zs<&?uMX1+hst=U&fQ5kRMqsu56C?>FYY#z6MARg|)rHrPY}7%= zPaU%d;7y)@ZOHffruZ8aT+i_A#3$%989BEps0|vEh-~7XD&rrV6>Dacr^g3o5cPqG zAuve(gFH5Xkys~BQuAk@^eCh+4y17`$Tm&3qThV~{>OSirQtT%sh8|vJ&PiGuA_+k)TPr|#l z`ln$=m#q9d?Bnu&q(tUn$@-*UMAz8f9#eUckGfi91yF-46%(^Uq{h~kIqscf%3 zJW6WMBB);(uy5$g84XS1Uh>hZ5bNYiR^DP&3MC*@&sLa2_NP7d9@8PT6s6s-6@g$1 zb+dF#>2o8DM^jyETbq6+Pl9?$C6*Cr+5xl7IS>stUMc~-g{GwmfC<=!V-J$L+<-QN zuh3`NrEn_!_URZsjgu{kh;2KrXC<`@$cNv7Gx2_ zf}mKXY&gR)J(&G3^98?-1fo99T!pf3^QXKp#{qQAeQdEY_Sd$)b{fV1IP}gS~n1mm!zYNI&KrJ z(ZV{#g?g@jY`&0*$dn53bv5f}gO<`Mxt@aAG-Bi8Z2M}(LLbHh4qOA~>iw>WSsmJl z7m_a^^2$9ofM$lyif)4GI6#TUh;GGV6038%Q(Ld&3);RW-rI2Q`*ZgJZ2n2w#uTu@ ztf*s^jNuInfPSC_-njDR4h+4jh`_F={w<1;D0OQgk0$#ser~^gV5hhyHy)h#?lJ4g z9w6m^bxw~@)V^>M&9q))0cyS=7!Y!qrbCTVyF}#l#?-50Ml@D}I(|g8<*LwML`iv) zV!asYW64sdI~-AaBPLSW-jFB%G8zJj89A zDvOrA4y0F4|r#4(4Mxr|pU?)%)mj3o^y| zGj+FgrDXgjC50W^LhmbtMH68n;9Lw^XHnV^36^P`%I}!*q&ZjX;Q{>^e}4RQ1;t{_ zY%TDZ1AXN`NZi2UJwkzbZD_VIy5sV=O{;^xK=Kl|$0fwUg7BdVB-@)X>5Ve>qPlQg z?@e`7BSlB59dsxr;ww|$J2?sx%hQ+h55H>eZqLRipl8Vucv7ujPNtn*vm2uNt;T*}uPeAAW z*Hn7r3qEIQ;)t4+gC1JJfA^>I;kKJMnEb!xF9jo2-B@70=ivL!>vm+KX9da9Sj>~w zK0VEia*ZlpVCakYSOx5;A8c`Msf)D%l~UCNUm$t*7)P#Z2L`Aq>KxJgml1O8CjA+Z z;B=$}Y@Z;8x!-1wwc{H2oR0&?V=2I0jBoZNs-FwrGhI~1Vs2p;YcxCC8HYH0dINk; zPz%^X9#X_bfW#x1Z>0p^}awY_TMuuBg9B3KJIACo)DgBU6* zNxd@pjsP5B7ZDc3^*z`et$eU`uEyy_dzIdF?h4B#9%4>fUBwvr%{OL{3GSN^VSa!R z&S3|HuaN+@q5nl$ zP>~@Hud$2zsnP$W&WQY&6^1BAlMiHPdY^~#guisZ zy{yYOdmQ%6Cn*}}nS^E#&8M8*U+*3iNqpj(F1YkmIDKjkXxsWwY*!S_Y5fz|0%7Ai z=TCtcReF3}Bvjp`201VXwNSFOP=zB2+yy94nOf9Zz2YR97t-yhLLPlI#pN-gNtab= z1iwqGDy5ar&(9q6w8_S}M3#VA(I?>6x?I>PfCceGwZz{v%KM$Is*3T7a-B5NQIYzo zjP5^~syVIu)fl2V^jz~LeRrBduoMh2faCS^W-8rbYXz26)NV>xz@J9mCg66qxQ7S) znDqDw#J#2Gif);D9q(cHhQI(rU5Ma$Wh}AJ%-ht6m zHh>p=h14t}d+7Jzf=Y;T^)Ie!i7b-2kO6EpJ7Cxr|3S@w_oR(FY<2@elR2aewD>ZX z{cc#`!)2uD96RX@4DZ0`3m-JF>loO($~Se7$Du#zbHO+v@BJPCrIyF*$y%Ls$EIP# zg}}=3t#cinAB~{n{7+Yb&Qg6+HVHrniEig}4edKWfK@4y6!G^@&RJgKBRY7+M@xCU zJj4@Ne3?xOmVW_8jG9Hc27FG6)xKQN0oY(A0MX_IXSEAwy2kamoMC@cO~wa3;hU9> zF|X1WR%wLJbnSjFNC^U44PyMEKi|j@2G(TcMI_`VC}ZG;E}?^=7fLKhq$0IYf-|p7 z<|>^81v-gw&(k@8HVt2CfMl{{6@6YH29J=y-=r)P^g6sz{YLkC={4}yyD5q?yt-yU z)O$_100tCglFB5oK{K!vnS$CXQhU{IkgtG$iFS?M!~2ofoA_aW(GuHrsSAawf}aNi zu~=#0l3>WvFzek`?7a}6Lx@5CNjX-iXoC%)hc)#tI`$_4jWSgIDfp*@gyxOO@cacA zXbJ~{dmwPR3uS5rW4xdru2s?P3t#*Q`)0ofG515fTq7V^dGv_0vJXs~K(Ihfhpp6G zwsFwGE4$R+!iFTHb<3fN;Pdh`OzILvoa+WUSWSl8mR*7K+XR}(rvR|Os?C#wZNO(Z z%X#!%2s6`r5`uwl2N?>nTU;)^W(*OD2mW|I07xI++&{WisBrlX(rh|?^~d+4&cJxS zSyvR;ENv_heEDdvpu$xe!Rb0P%2hy#R(A}U9*!g{n1_v&urd}1RVsnwCn8QSCOYWJ z(NS{iqkalZHPYKcvT9fM0d3U>tL>I^5%9kRBtzV0LydTX!wQ!74Qw&Ey`I340z$e; zT`W<7Bf&Wan%P?IFtiwH`FnsNVQdh9xyQMV9lweGqyt;~?<>qTu;`_YQ3b-gdYE7~ zdLMXubo!gJ6l@9ssxgz`z1|@*UTZD!@GbFBHoPEyJ~#?Vm^V^0a~S7eu;wZBs-xc! zM{h{g7GdCPKFFl`9rcKQbcnyZ)V?Dytvi<&4H$svkPQ(0Eywn+B!tGo8U{jC!s!f? z!GhND;1}N6_&1%BMg2P2?^{uJ@+m9+n-C&?a&8Dht2 z)E1^WL(CUE!U%=$(HpUd-rv5w17@tef0$2lAXa^9n^zFcstgjW zsINXkY}v8I+bL%O@k62le9n?a&71;r3tKuWMiFYMYF%;J6DURfhT{D z#8yZM`hixBS``dg=%-Vg5_}G6uC;B4exA^6l~-=ai=ha(TB$Mn0S6y>2z^0yXD~q5 zyyNqDxkL#V$+JJ<>CO!$7pYi-z>^QyOtB^D6k;(iLeYxyh=rP|*>{de=msn_4T)2g zd?AKE(+tN;aj5J8ki~6uiCj+5cDVxP6Zq z`I$_km^qrETH5qE5Jj6tBT9I(=C?x-bY!!8c32WKuu=n?8!|305`Gn+6pby?C5IawaGx4Ni5EhC> zECzkZtrUe!pz~#R3scV4=UWrkd;kw;DZ39&zd|0z&!|JjCbIsw6>LB9Q4>HX+W|*4 zB#Lf=OXs~m!yL@3NJ510NXND}{9!#aX;s;zdgwL05`m?h7=DcW58|VMT?gHjtIm~#4keF0B~LTT8t&l{)=)=q^Aao|AxFqXx3{fE_I{Gv>*fHn^i_` zWO>2wbg;f!=-Er8Ns+jNW9+9bY@fp}xLfDG-suBv%Hh(p=aH1hoF?SQr0)(_c$@%?&>OR?q{QMS5k6kgY$ zh{cdJSL^5h&BZ@O$VWrD4u+xe9^{&lm{1M9`_)ergagF2- zev9xwfRmR8N>p9QP1w&-yP;gb4-gTS5#I_peghIw^fTynR`@)p%zS3YOBnJ9Hw%F@}z`3CK)ja zbc0ji@}EaD3Ab=wcO=|GV~KHIshp!MMhI!a;xtqT9_(pyryyJZ9~lZ4@eMk>G_Vye z>_CRk^M`sU1YvYTw@eEcM+MZBn}%h|4$%JPvvvr!>}jIVlZrl!u!VlAc@(YbBjlQv zpmE)ySCm2QHwsi&-`5I4Rv}Godpp=4?#@k6Fw_pC)~yly7X=;29fH1pkcM4Df<_c) zJD^|V5qLb_dIdTmwH|F?(dctmyJf4Q`E93Ey?Glr>V5Wg#5c?(Pi`S6$OcnJ& z6C8frx?Gw(lT9n-7loKsx^%`UC!2Q7sD1z|gk~DoL*|?kP1y;E zZw&tmpcPiPg$dtlwA$rGd>0kJqqJrk-BT632tBL=&_pF2cwH7ck6Fz0v`Ab=ZXckv z51**7Lu6vSK>j>_A#6K@yOIP|*OgO+=`vJp>^k0m?dNmr*{g^fgzpWF2Hk=K=*Hjs zn|#*O+MZxa&cmkqv>0yw*3?NaP?73e2SN>vc=!webY@vPc!l)em4`*Hyv{*=xK7%1 zi9o}rnWQ;^$a|jAHELk3cx;Afjb1>P@>^nJdEGjl@24k?Fhb+(bg+D}DrE%%Y?Ib# zg{B1{ppe{t`Hy4C<##H z8;Xt#lp9Zfyf`|%q5;a@5=aqr_y^m+Hw}$CT>XOS!CYIZxoh!aE{jtf>F%b6RgW~V z0#6ry=P>uWNzi>4F}Tk7W>ruDHZM2%HYF2>;5#2+V@JTor|k~jg}O>&DLVq3I2T~e zERXNZeK`Tf%yy6L!JlKBA0&xb$(!&Cb7PuL!!L}c?Fd`|o)%(0WG)=HRS`={{dU>K zOg-;fgC0<&Egli2)408*>aym#qpa?SCx*fq5(bN|I=7)BcqS!7qLe3eQsDQv>8%}8 z1umL>0~$1E7xYLCPg1+4x=^zigdQ5Ev$~Q0Gr9m<;dL+}?LE`jCo*a1W!b6W@ zkqb-YRb~{0Lgu|+2qRn~*MT=izK^Vyx$i!6rILEo02Qo3y3LC}muV&em;Kr=T{xb=o_$xFP-BJ5KNIBUQ|O5T9?6cpBU3b{P7 z+hD*|TjxCIois~BYCy|2c_7Zhi;J04cGi85CUXXbH&!weKJd$?NdP`TL%$8BEFXlU z!IcWmK5*6&r&ylt4RzkV+!K^8T8hn_;j-5P zy%pMRf@%^^$G-L30*ujX5OvrIm467ixcj_%qS%j<)S$VZ0bG$r@OkX`S zLGAOvx+K%CGzhG*y6JF;dO|^nk%gzh)H%Iy1VA;<(>=gg2a9-+-c{uM_c4wiYJ(ym z>l8elC%qTQPxxkyQ3$0RQ`abJDxsZv^RRU$^E!jLq22ccp;*AOcQ-v%Br7#3j{xW04Y^;9m<{OO@L z=?4e8cQIHzfYj^H$i9gps>tH5)! zWK=)PBJ4f4h7>iA{HISuou1x<8d0c(H?mb7Qz~ixgw~RC7y(ym0E)u}C)Oc(em6R5 zZ%uvxRDwlxV4G_X^pm_Ld+AGAX>?W+yayW50ARjW28B>`=K>mD<4ZwKtVJgc>SSabQDFMZoNtH?AC!-&t%=dfd*5Yt zV00$p&1IQ=sB`@UV{5@MF^kvG-KhiTs^90&ytIa>wm?yNu%K6e{IeDcmb{doNJ{`r z^I)1`FZrPHeN=S)x~$5a+1H1s5N6##HgA$W*l-~8z0^di0@RX|K?5;_*il2|mWF&v zE$6ZktT0wn_}3@uGrP4|J~=%xz6PP&iJ*HJ5)CJZNYQ=XsC#!_98WLsXyoSl6vz_AIRn>B4}>}+dG)w!( z5o*yK#wW915<;C3JD{iHzTh_KsW|%ml*?}v)pJNbcuIl|qf1`Gvux1M2D}LeqCyK zJ+|tGtQX&`FbZT$=QdgZSvj#HUw0O!vSzj&?ylYr@>lFI)>ByHMU$fL+6lwWmJc;* zWr|MX^o@XFSlVa#M$P_M3N)CXkhvBq>cYF%MW^5C>OM_&AyQ0Mv+`Pr0?jIOh^pNK zyvuiZVYK7vekkJrw_E?w{Qk#nHw(bq^gKz~47SWO$FMdZ$EA`^c1?D2+24y#pojDa zjPdgc3m-O&;Usa=;GEABd59MSi0zd7YGdkqWber+CW0(aCRS zNRe%jekbpYQ?lfbC6d4wZ9n&%g0BFZxlra$>CNXOm)?87cDz>d@XxO^cfZXvm;P32 zvVC;dvyYiq)8^DZiqP0b!PPaGCcCOigvu{a1zgacX?K3!bwmaPUXr3(NbO@!yzb88 zdd|Ya-Bl}&2p!9fr=UvYZH7_stFc) zs3knYbqqyIkwL_RQz#fl6H{mwszQS0z}^S-{rZL;;>tI3L)`CM+#lU5{EYlvxdmJ`kY(V9WhfAA zRzsGdoag{Hxs94y%uC8%oma(*??60w5je6NpVGP${HCDG*eoT-WQgnGlXK8w``$-J zVIfPbX`>ZQQb$8fVIhJ7z%Y2j3A7e}m2S-6&O74^w_NF=f_;BA0Fpbd?LDfOU0v0Y z?-hjaEftng|M$J2_n;g65wz&vK>*BQu=(rP8XVn_%>_M^=sXGcAt1;50ojd1#{C&f zvX)PJ;RP;cSp1t9c%>>%pmDqp|);;gh*f} zb?h3yhXW{vo3&2y%YVSp++=wJ3%m|nuFGv`7@i{@BkT3115}6?;eZkT{+zjnGZTmm z>tWDg?A>?4Is*l}35-0prN0bWeNY0SEIr8yG#4!gEM2JIO;!|bvO)}?Fs)y?kWO zaFqChS`;=mZL)X_Xd9-Whhtw~2d`j{+6=$f8oXKuooc`h`2^h~;zS4vsh3%1VBEUvYA50)3+mqzRFKzv2Ja3zp(5kFSOnR&c}EmE+QXp_%^(kjcHRZ@Fm? zkw#Wk`TEwkbIUuhxeH$1lzHhhQNMOgJgg5e(K*!b)v=l{&rHZ+y^h0rDcIj+gvaD2 z#?*mDtsP`w7l9@2EjCuu1P$aXl_#uI5LZBH|5}sPSR%4o_`+xP|p9;WLO(K%~G?GAhqSZ zt}ssf`UwvhG2IM__;z2yTkgzhz=c7i>?Z#5Mq3E{=wD)0?sX@4X(oYXY*Z=@uh+C4 z`O8DM-osyJp@o-|^o?OISJ1={_`wB57erm=VIdsY2catd03vh9p`*rOU~kWw>XAt9 zQEwXa8nj}JBNi7IZNXQ5w0>iMC+PgMkOvRJbbuXKF79q;ctxG-3M!fKhOU_imd6^& zkRO6%_H<@p?52Sa_Uxvy9v@^5!!RNI=VlO;#P=&R^X|X6cd!4)=jXl&2?>AZd#MCB z7lK9g7<|l0mqp3^=6h03g|5$JS`^Kd#gAS%b{@Q6K9&{(5gQDW zD>a9L_06;z8|;A$kne%uS}K3DSE zS2e#+fDM2c#AP4}+QO{l2pS!7bW<@LnxSZ-LWo#s9o0Lq+Z_DUOo?|+XWN(&|HNKC zT~jl=S6s|CG%_NQ??shCCIbg0ng>s@N6-C30}e@l7CtbDk%8d}ZWq#|%TmtKCyy+r zblwzHx%L>BDPM%yqmrawtqY1hsvgE%rtN2f-{iMb-AIq36}pN_eQ_EH8sKRCxhln! zt8K;XP&}X=M^kgru&VowS`0YkKb^|7TfMsB?O~fV0*A5_s~QjHg&(+xh$$-hK}*iQ zeA`_0xof`#Q5%4fFXr1;CK}5A1l5#)LgRo@rCJgGz2@4+P~LFvMo}&V2hBM6$tPy$ zO)wBBlJUkO`byAB8EFZwDUTq1Go(>X6!9GUVHGU=zs3G$BuHf5KpoO|?y#S}65x6~ z(>gthtuV(DcC+p8U^g7>Y+H=3`}440eR&t1yoLD&$M{F{7Oj_HZ8fB*BJVjv`w#%AmN g_y54FdZG_W?!8m#U7i*cB!YkRw2U?D)tzJi4?{YQ3jhEB literal 73681 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

yx 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 HapnI366Pd8 diff --git a/doc/diagram/move1.png b/doc/diagram/move1.png index bf4938dfecb90dede0f42df0c52e87ca7c16a417..ab322d084bd6d819fdb93a014d19e5fbf6e2b2b0 100644 GIT binary patch literal 16081 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 aKn%h5W>`e-p#nYXpQObV#HvLM1OEpM8uU{D literal 8181 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 xQ6QQh diff --git a/doc/diagram/move2.png b/doc/diagram/move2.png index 1d1f0bf532159dfb61bb28b2029de593383bb8f7..8d4fc5bcc2223e127f672666b8eddbce4020e01c 100644 GIT binary patch literal 41517 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 literal 26753 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 V32%I)nT_&*Vrywnzhusc{2!y7PWJ!+ diff --git a/doc/diagram/move3.png b/doc/diagram/move3.png index a52ad46de7ae75df223a7a03ece5a78fa82f6d92..558470f1fab8390faa35fca1ef85c0e7f048d3c4 100644 GIT binary patch literal 36371 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 literal 22630 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 B_q6~3 diff --git a/doc/diagram/normalparsing.png b/doc/diagram/normalparsing.png index 7e9ff7df87d1c183456960f40c43bb5c83273274..702512ca3678f62f4a35100953d2dad02fc84fab 100644 GIT binary patch literal 32887 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 PMX$b!NDG$;>iYgK0)w4D literal 22674 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 Mwuk7&*2fb64>wxxng9R* diff --git a/doc/diagram/simpledom.png b/doc/diagram/simpledom.png index 111aff6c964e83df04f4133b40a5aefead6cea09..38d9c5dc126f9f28e799b877cb4737cdfebd787e 100644 GIT binary patch literal 43670 zcmce;RaBf^v@9A39^5UsySpX0ySux4B@ytXWlab|RD%B#{vC5#GIfha@c}rth=n`o(RMZk2Yp_qk8h-(d6r?pp5bFII!7Bmtj!WlaL#uZm_3yRG@htB3rIl9p zD+{i%543^rF^nMP0^wO8sNy%Evf1?BYy3C(4we260~P8Q&DGcc{si76LJkaVi%GSR zsQ%|AyW|J_|NV468srifytUkHt91DH=6H#nhnF{^x5=zT;O_cBwXLnKSit_WGt+k} zPgv5#ge*HJM}Cx3PUK;qS+|9w9+zq$iCXc`;bG=+b|SOQA?cW`loTqT`ADL;komQ0 zwJ+z55`EUS#xjh}p_P_5r#bGfst!&^ERESj<~&R1i0P>0iFhxP>Zb~(P?x!;EMp

d-WmRivHS`b^sdFqpGs`!Rk@*~d`T6-k9)`sUj$ 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 z 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 bNY2eb)1a^t{00J^Q}CyurmI?}Y!&=Jjhtmx literal 24053 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 JD%5ZP3 diff --git a/doc/diagram/tutorial.png b/doc/diagram/tutorial.png index a2b0b54761d73a34564d8636edfb805b5068b3d6..8a12924acdd72a9c1b99c0a48a201b936f3557f4 100644 GIT binary patch literal 44634 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 literal 33154 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μ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 LMW#U7==Fa9bO-YM diff --git a/doc/diagram/utilityclass.png b/doc/diagram/utilityclass.png index 0088bb15bcef3d9a4b1cdbaa13a52cc2d74aae47..ce029a4d0670e0a358e3bdb8c030083f67b1ffcd 100644 GIT binary patch literal 99993 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 JR@TJ(e*o()o2UQ) literal 62311 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≠7CLtFZXzPR3JT2qZ#d*^AhDE%#Svy531j83mDg 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 From 32295665739115f5149123bc5a4fe1de21786d18 Mon Sep 17 00:00:00 2001 From: Milo Yip Date: Wed, 20 May 2015 13:33:14 +0800 Subject: [PATCH 094/189] Add multiple SkipWhitespace perftest --- test/perftest/rapidjsontest.cpp | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/test/perftest/rapidjsontest.cpp b/test/perftest/rapidjsontest.cpp index 05ecf6e..9be966a 100644 --- a/test/perftest/rapidjsontest.cpp +++ b/test/perftest/rapidjsontest.cpp @@ -298,11 +298,28 @@ TEST_F(RapidJson, internal_Pow10) { EXPECT_GT(sum, 0.0); } -TEST_F(RapidJson, SIMD_SUFFIX(Whitespace)) { +TEST_F(RapidJson, SkipWhitespace_Basic) { for (size_t i = 0; i < kTrialCount; i++) { - Document doc; - ASSERT_TRUE(doc.Parse(whitespace_).IsArray()); - } + rapidjson::StringStream s(whitespace_); + while (s.Peek() == ' ' || s.Peek() == '\n' || s.Peek() == '\r' || s.Peek() == '\t') + s.Take(); + ASSERT_EQ('[', s.Peek()); + } +} + +TEST_F(RapidJson, SIMD_SUFFIX(SkipWhitespace)) { + for (size_t i = 0; i < kTrialCount; i++) { + rapidjson::StringStream s(whitespace_); + rapidjson::SkipWhitespace(s); + ASSERT_EQ('[', s.Peek()); + } +} + +TEST_F(RapidJson, SkipWhitespace_strspn) { + for (size_t i = 0; i < kTrialCount; i++) { + const char* s = whitespace_ + std::strspn(whitespace_, " \t\r\n"); + ASSERT_EQ('[', *s); + } } TEST_F(RapidJson, UTF8_Validate) { From f688b2b15279bc8face7f4d319fd545b129a3315 Mon Sep 17 00:00:00 2001 From: miloyip Date: Thu, 21 May 2015 13:25:37 +0800 Subject: [PATCH 095/189] Improve coverage of Pointer --- test/unittest/pointertest.cpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/test/unittest/pointertest.cpp b/test/unittest/pointertest.cpp index 0e050c0..312683a 100644 --- a/test/unittest/pointertest.cpp +++ b/test/unittest/pointertest.cpp @@ -873,7 +873,9 @@ TEST(Pointer, Erase) { d.Parse(kJson); EXPECT_FALSE(Pointer("").Erase(d)); + EXPECT_FALSE(Pointer("/nonexist").Erase(d)); EXPECT_FALSE(Pointer("/foo/nonexist").Erase(d)); + EXPECT_FALSE(Pointer("/foo/0/nonexist").Erase(d)); EXPECT_TRUE(Pointer("/foo/0").Erase(d)); EXPECT_EQ(1u, d["foo"].Size()); EXPECT_STREQ("baz", d["foo"][0].GetString()); @@ -881,6 +883,24 @@ TEST(Pointer, Erase) { EXPECT_TRUE(d["foo"].Empty()); EXPECT_TRUE(Pointer("/foo").Erase(d)); EXPECT_TRUE(Pointer("/foo").Get(d) == 0); + + Pointer("/a/0/b/0").Create(d); + + EXPECT_TRUE(Pointer("/a/0/b/0").Get(d) != 0); + EXPECT_TRUE(Pointer("/a/0/b/0").Erase(d)); + EXPECT_TRUE(Pointer("/a/0/b/0").Get(d) == 0); + + EXPECT_TRUE(Pointer("/a/0/b").Get(d) != 0); + EXPECT_TRUE(Pointer("/a/0/b").Erase(d)); + EXPECT_TRUE(Pointer("/a/0/b").Get(d) == 0); + + EXPECT_TRUE(Pointer("/a/0").Get(d) != 0); + EXPECT_TRUE(Pointer("/a/0").Erase(d)); + EXPECT_TRUE(Pointer("/a/0").Get(d) == 0); + + EXPECT_TRUE(Pointer("/a").Get(d) != 0); + EXPECT_TRUE(Pointer("/a").Erase(d)); + EXPECT_TRUE(Pointer("/a").Get(d) == 0); } TEST(Pointer, CreateValueByPointer) { From 1a570c342dad0927503b35782263da006ef93351 Mon Sep 17 00:00:00 2001 From: miloyip Date: Thu, 21 May 2015 16:00:32 +0800 Subject: [PATCH 096/189] Fix the undefined behaviour when negating the minimum value integers in Reader --- include/rapidjson/reader.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/rapidjson/reader.h b/include/rapidjson/reader.h index be0d9fb..8989e38 100644 --- a/include/rapidjson/reader.h +++ b/include/rapidjson/reader.h @@ -967,13 +967,13 @@ private: else { if (use64bit) { if (minus) - cont = handler.Int64(-(int64_t)i64); + cont = handler.Int64(static_cast(~i64 + 1)); else cont = handler.Uint64(i64); } else { if (minus) - cont = handler.Int(-(int)i); + cont = handler.Int(static_cast(~i + 1)); else cont = handler.Uint(i); } From 6e1d10ec6b1454737015ca2b018816185092efc4 Mon Sep 17 00:00:00 2001 From: miloyip Date: Thu, 21 May 2015 16:12:33 +0800 Subject: [PATCH 097/189] Add GenericValue::EraseMember(string types) APIs --- include/rapidjson/document.h | 25 +++++++++++++++++++++++++ test/unittest/valuetest.cpp | 18 ++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/include/rapidjson/document.h b/include/rapidjson/document.h index ca80963..889cdfa 100644 --- a/include/rapidjson/document.h +++ b/include/rapidjson/document.h @@ -1213,6 +1213,31 @@ public: return pos; } + //! Erase a member in object by its name. + /*! \param name Name of member to be removed. + \return Whether the member existed. + \note Linear time complexity. + */ + bool EraseMember(const Ch* name) { + GenericValue n(StringRef(name)); + return EraseMember(n); + } + +#if RAPIDJSON_HAS_STDSTRING + bool EraseMember(const std::basic_string& name) { return EraseMember(GenericValue(StringRef(name))); } +#endif + + template + bool EraseMember(const GenericValue& name) { + MemberIterator m = FindMember(name); + if (m != MemberEnd()) { + EraseMember(m); + return true; + } + else + return false; + } + //@} //!@name Array diff --git a/test/unittest/valuetest.cpp b/test/unittest/valuetest.cpp index 5e142e1..f14669a 100644 --- a/test/unittest/valuetest.cpp +++ b/test/unittest/valuetest.cpp @@ -1182,6 +1182,24 @@ TEST(Value, Object) { EXPECT_TRUE(z.IsObject()); } +TEST(Value, EraseMember_String) { + Value::AllocatorType allocator; + Value x(kObjectType); + x.AddMember("A", "Apple", allocator); + x.AddMember("B", "Banana", allocator); + + EXPECT_TRUE(x.EraseMember("B")); + EXPECT_FALSE(x.HasMember("B")); + + EXPECT_FALSE(x.EraseMember("nonexist")); + + GenericValue, CrtAllocator> othername("A"); + EXPECT_TRUE(x.EraseMember(othername)); + EXPECT_FALSE(x.HasMember("A")); + + EXPECT_TRUE(x.MemberBegin() == x.MemberEnd()); +} + TEST(Value, BigNestedArray) { MemoryPoolAllocator<> allocator; Value x(kArrayType); From a2d09f0a03cf58f62f90c0af1416a59b0ca5cf50 Mon Sep 17 00:00:00 2001 From: miloyip Date: Thu, 21 May 2015 16:13:02 +0800 Subject: [PATCH 098/189] Refactor GenericPointer::Erase() --- include/rapidjson/pointer.h | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/include/rapidjson/pointer.h b/include/rapidjson/pointer.h index 13e688e..5d2aa8d 100644 --- a/include/rapidjson/pointer.h +++ b/include/rapidjson/pointer.h @@ -686,34 +686,37 @@ public: ValueType* v = &root; const Token* last = tokens_ + (tokenCount_ - 1); - for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) { + for (const Token *t = tokens_; t != last; ++t) { switch (v->GetType()) { case kObjectType: { typename ValueType::MemberIterator m = v->FindMember(GenericStringRef(t->name, t->length)); if (m == v->MemberEnd()) return false; - if (t == last) { - v->EraseMember(m); - return true; - } v = &m->value; } break; case kArrayType: if (t->index == kPointerInvalidIndex || t->index >= v->Size()) return false; - if (t == last) { - v->Erase(v->Begin() + t->index); - return true; - } v = &((*v)[t->index]); break; default: return false; } } - return false; + + switch (v->GetType()) { + case kObjectType: + return v->EraseMember(GenericStringRef(last->name, last->length)); + case kArrayType: + if (last->index == kPointerInvalidIndex || last->index >= v->Size()) + return false; + v->Erase(v->Begin() + last->index); + return true; + default: + return false; + } } private: From 7ddaa80e461f8069fc80a28254ffe40804d51451 Mon Sep 17 00:00:00 2001 From: miloyip Date: Thu, 21 May 2015 16:45:39 +0800 Subject: [PATCH 099/189] Improve coverage of GenericPointer::Erase() --- test/unittest/pointertest.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/unittest/pointertest.cpp b/test/unittest/pointertest.cpp index 312683a..0f78450 100644 --- a/test/unittest/pointertest.cpp +++ b/test/unittest/pointertest.cpp @@ -875,7 +875,10 @@ TEST(Pointer, Erase) { EXPECT_FALSE(Pointer("").Erase(d)); EXPECT_FALSE(Pointer("/nonexist").Erase(d)); EXPECT_FALSE(Pointer("/foo/nonexist").Erase(d)); + EXPECT_FALSE(Pointer("/foo/nonexist/nonexist").Erase(d)); EXPECT_FALSE(Pointer("/foo/0/nonexist").Erase(d)); + EXPECT_FALSE(Pointer("/foo/0/nonexist/nonexist").Erase(d)); + EXPECT_FALSE(Pointer("/foo/2/nonexist").Erase(d)); EXPECT_TRUE(Pointer("/foo/0").Erase(d)); EXPECT_EQ(1u, d["foo"].Size()); EXPECT_STREQ("baz", d["foo"][0].GetString()); From c8c8ad47c372dc724cbabcbaf5c62aee4618afeb Mon Sep 17 00:00:00 2001 From: miloyip Date: Thu, 21 May 2015 17:02:27 +0800 Subject: [PATCH 100/189] Further improve coverage of GenericPointer::Erase() --- test/unittest/pointertest.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/test/unittest/pointertest.cpp b/test/unittest/pointertest.cpp index 0f78450..7ec3f72 100644 --- a/test/unittest/pointertest.cpp +++ b/test/unittest/pointertest.cpp @@ -874,6 +874,7 @@ TEST(Pointer, Erase) { EXPECT_FALSE(Pointer("").Erase(d)); EXPECT_FALSE(Pointer("/nonexist").Erase(d)); + EXPECT_FALSE(Pointer("/nonexist/nonexist").Erase(d)); EXPECT_FALSE(Pointer("/foo/nonexist").Erase(d)); EXPECT_FALSE(Pointer("/foo/nonexist/nonexist").Erase(d)); EXPECT_FALSE(Pointer("/foo/0/nonexist").Erase(d)); From 013b71b92fdc835b53a61c739d6d57bd6c5627be Mon Sep 17 00:00:00 2001 From: Kal Conley Date: Sun, 31 May 2015 20:35:55 +0200 Subject: [PATCH 101/189] Fix warnings when compiling with clang and -Wimplicit-fallthrough --- include/rapidjson/reader.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/rapidjson/reader.h b/include/rapidjson/reader.h index 8989e38..43b2d9c 100644 --- a/include/rapidjson/reader.h +++ b/include/rapidjson/reader.h @@ -109,7 +109,7 @@ RAPIDJSON_DIAG_OFF(effc++) #define RAPIDJSON_PARSE_ERROR(parseErrorCode, offset) \ RAPIDJSON_MULTILINEMACRO_BEGIN \ RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset); \ - RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; \ + return RAPIDJSON_NOTHING; \ RAPIDJSON_MULTILINEMACRO_END #endif From ce0184e73bd8eb14c3c5c8a894d7b4ee7ea75e37 Mon Sep 17 00:00:00 2001 From: miloyip Date: Wed, 3 Jun 2015 23:53:14 +0800 Subject: [PATCH 102/189] Add and fix -Wimplicit-fallthrough for clang, revert #350 --- include/rapidjson/reader.h | 14 +++++++------- test/unittest/CMakeLists.txt | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/include/rapidjson/reader.h b/include/rapidjson/reader.h index 43b2d9c..18c4ca5 100644 --- a/include/rapidjson/reader.h +++ b/include/rapidjson/reader.h @@ -109,7 +109,7 @@ RAPIDJSON_DIAG_OFF(effc++) #define RAPIDJSON_PARSE_ERROR(parseErrorCode, offset) \ RAPIDJSON_MULTILINEMACRO_BEGIN \ RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset); \ - return RAPIDJSON_NOTHING; \ + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; \ RAPIDJSON_MULTILINEMACRO_END #endif @@ -1387,13 +1387,13 @@ private: } switch (src) { - case IterativeParsingStartState: RAPIDJSON_PARSE_ERROR(kParseErrorDocumentEmpty, is.Tell()); - case IterativeParsingFinishState: RAPIDJSON_PARSE_ERROR(kParseErrorDocumentRootNotSingular, is.Tell()); + case IterativeParsingStartState: RAPIDJSON_PARSE_ERROR(kParseErrorDocumentEmpty, is.Tell()); return; + case IterativeParsingFinishState: RAPIDJSON_PARSE_ERROR(kParseErrorDocumentRootNotSingular, is.Tell()); return; case IterativeParsingObjectInitialState: - case IterativeParsingMemberDelimiterState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissName, is.Tell()); - case IterativeParsingMemberKeyState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissColon, is.Tell()); - case IterativeParsingMemberValueState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell()); - case IterativeParsingElementState: RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell()); + case IterativeParsingMemberDelimiterState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissName, is.Tell()); return; + case IterativeParsingMemberKeyState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissColon, is.Tell()); return; + case IterativeParsingMemberValueState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell()); return; + case IterativeParsingElementState: RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell()); return; default: RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell()); } } diff --git a/test/unittest/CMakeLists.txt b/test/unittest/CMakeLists.txt index fb95b8e..fd2eb4d 100644 --- a/test/unittest/CMakeLists.txt +++ b/test/unittest/CMakeLists.txt @@ -21,7 +21,7 @@ set(UNITTEST_SOURCES if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror -Wall -Wextra -Weffc++ -Wswitch-default -Wfloat-equal") elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror -Wall -Wextra -Weffc++ -Wswitch-default -Wfloat-equal") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror -Wall -Wextra -Weffc++ -Wswitch-default -Wfloat-equal -Wimplicit-fallthrough") elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") add_definitions(-D_CRT_SECURE_NO_WARNINGS=1) endif() From 81678272a234c599e51d08b95caa2c4252958b71 Mon Sep 17 00:00:00 2001 From: Milo Yip Date: Thu, 4 Jun 2015 16:07:43 +0800 Subject: [PATCH 103/189] Fix #349 emscripten alignment issue --- emscripten/a.cpp | 24 ++++++++++++++++++++++++ include/rapidjson/allocators.h | 6 +++--- include/rapidjson/rapidjson.h | 2 +- 3 files changed, 28 insertions(+), 4 deletions(-) create mode 100644 emscripten/a.cpp diff --git a/emscripten/a.cpp b/emscripten/a.cpp new file mode 100644 index 0000000..9114857 --- /dev/null +++ b/emscripten/a.cpp @@ -0,0 +1,24 @@ +#include +#include +#include +#include + +#define private public +#include "rapidjson/document.h" + +int main() { + // std::ifstream in_file("config.json", std::ios::in); + rapidjson::Document json_config_; + // std::string json_string( + // (std::istreambuf_iterator(in_file)), + // std::istreambuf_iterator()); + std::string json_string("{\"float_test\": 75.0}"); + // if (!json_string.empty()) { + json_config_.Parse(json_string.c_str()); + // } + + printf("%p\n", &json_config_); + printf("%p\n", &json_config_.data_.o.members[0].value.data_.n.d); + + std::cout << json_config_["float_test"].GetDouble() << std::endl; +} \ No newline at end of file diff --git a/include/rapidjson/allocators.h b/include/rapidjson/allocators.h index f615ffd..6be2776 100644 --- a/include/rapidjson/allocators.h +++ b/include/rapidjson/allocators.h @@ -181,7 +181,7 @@ public: if (chunkHead_ == 0 || chunkHead_->size + size > chunkHead_->capacity) AddChunk(chunk_capacity_ > size ? chunk_capacity_ : size); - void *buffer = reinterpret_cast(chunkHead_ + 1) + chunkHead_->size; + void *buffer = reinterpret_cast(chunkHead_) + RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + chunkHead_->size; chunkHead_->size += size; return buffer; } @@ -199,7 +199,7 @@ public: return originalPtr; // Simply expand it if it is the last allocation and there is sufficient space - if (originalPtr == (char *)(chunkHead_ + 1) + chunkHead_->size - originalSize) { + if (originalPtr == (char *)(chunkHead_) + RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + chunkHead_->size - originalSize) { size_t increment = static_cast(newSize - originalSize); increment = RAPIDJSON_ALIGN(increment); if (chunkHead_->size + increment <= chunkHead_->capacity) { @@ -231,7 +231,7 @@ private: void AddChunk(size_t capacity) { if (!baseAllocator_) ownBaseAllocator_ = baseAllocator_ = RAPIDJSON_NEW(BaseAllocator()); - ChunkHeader* chunk = reinterpret_cast(baseAllocator_->Malloc(sizeof(ChunkHeader) + capacity)); + ChunkHeader* chunk = reinterpret_cast(baseAllocator_->Malloc(RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + capacity)); chunk->capacity = capacity; chunk->size = 0; chunk->next = chunkHead_; diff --git a/include/rapidjson/rapidjson.h b/include/rapidjson/rapidjson.h index f5d5630..b0dabc7 100644 --- a/include/rapidjson/rapidjson.h +++ b/include/rapidjson/rapidjson.h @@ -223,7 +223,7 @@ //! Whether using 64-bit architecture #ifndef RAPIDJSON_64BIT -#if defined(__LP64__) || defined(_WIN64) +#if defined(__LP64__) || defined(_WIN64) || defined(__EMSCRIPTEN__) #define RAPIDJSON_64BIT 1 #else #define RAPIDJSON_64BIT 0 From 935d0a39445d0f571421a94d92b431795b7142e5 Mon Sep 17 00:00:00 2001 From: Milo Yip Date: Fri, 5 Jun 2015 09:56:25 +0800 Subject: [PATCH 104/189] Remove emscripten test --- emscripten/a.cpp | 24 ------------------------ 1 file changed, 24 deletions(-) delete mode 100644 emscripten/a.cpp diff --git a/emscripten/a.cpp b/emscripten/a.cpp deleted file mode 100644 index 9114857..0000000 --- a/emscripten/a.cpp +++ /dev/null @@ -1,24 +0,0 @@ -#include -#include -#include -#include - -#define private public -#include "rapidjson/document.h" - -int main() { - // std::ifstream in_file("config.json", std::ios::in); - rapidjson::Document json_config_; - // std::string json_string( - // (std::istreambuf_iterator(in_file)), - // std::istreambuf_iterator()); - std::string json_string("{\"float_test\": 75.0}"); - // if (!json_string.empty()) { - json_config_.Parse(json_string.c_str()); - // } - - printf("%p\n", &json_config_); - printf("%p\n", &json_config_.data_.o.members[0].value.data_.n.d); - - std::cout << json_config_["float_test"].GetDouble() << std::endl; -} \ No newline at end of file From 3bc945fdce5badebaf64f383a2aab00dc76806a1 Mon Sep 17 00:00:00 2001 From: Milo Yip Date: Fri, 5 Jun 2015 09:57:11 +0800 Subject: [PATCH 105/189] Change documentation URL to http://www.rapidjson.org --- readme.md | 4 ++-- readme.zh-cn.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/readme.md b/readme.md index 19da386..584e33b 100644 --- a/readme.md +++ b/readme.md @@ -10,8 +10,8 @@ Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights * [RapidJSON GitHub](https://github.com/miloyip/rapidjson/) * RapidJSON Documentation - * [English](http://miloyip.github.io/rapidjson/) - * [简体中文](http://miloyip.github.io/rapidjson/zh-cn/) + * [English](http://www.rapidjson.org/) + * [简体中文](http://www.rapidjson.org/zh-cn/) * [GitBook](https://www.gitbook.com/book/miloyip/rapidjson/) with downloadable PDF/EPUB/MOBI, without API reference. ## Build status diff --git a/readme.zh-cn.md b/readme.zh-cn.md index ec6bd90..ce9456f 100644 --- a/readme.zh-cn.md +++ b/readme.zh-cn.md @@ -10,8 +10,8 @@ Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights * [RapidJSON GitHub](https://github.com/miloyip/rapidjson/) * RapidJSON 文档 - * [English](http://miloyip.github.io/rapidjson/) - * [简体中文](http://miloyip.github.io/rapidjson/zh-cn/) + * [English](http://www.rapidjson.org/) + * [简体中文](http://www.rapidjson.org/zh-cn/) * [GitBook](https://www.gitbook.com/book/miloyip/rapidjson/)å¯ä¸‹è½½PDF/EPUB/MOBI,但ä¸å«APIå‚考手册。 ## Build çŠ¶æ€ From 93bf4ceb32da38a8f3c1d80333b063ee79de6a47 Mon Sep 17 00:00:00 2001 From: miloyip Date: Fri, 5 Jun 2015 14:08:15 +0800 Subject: [PATCH 106/189] Add CMAKE in travis-doxygen --- travis-doxygen.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/travis-doxygen.sh b/travis-doxygen.sh index ad80536..399df05 100755 --- a/travis-doxygen.sh +++ b/travis-doxygen.sh @@ -78,6 +78,7 @@ gh_pages_prepare() gh_pages_commit() { cd "${TRAVIS_BUILD_DIR}/build/doc/html"; + echo "www.rapidjson.org" > CNAME git add --all; git diff-index --quiet HEAD || git commit -m "Automatic doxygen build"; } From 19687067b74c2a23963c99c817a5e07fc47824fa Mon Sep 17 00:00:00 2001 From: miloyip Date: Sat, 6 Jun 2015 21:29:52 +0800 Subject: [PATCH 107/189] Try to remove www --- readme.md | 4 ++-- travis-doxygen.sh | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/readme.md b/readme.md index 584e33b..8682df1 100644 --- a/readme.md +++ b/readme.md @@ -10,8 +10,8 @@ Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights * [RapidJSON GitHub](https://github.com/miloyip/rapidjson/) * RapidJSON Documentation - * [English](http://www.rapidjson.org/) - * [简体中文](http://www.rapidjson.org/zh-cn/) + * [English](http://rapidjson.org/) + * [简体中文](http://rapidjson.org/zh-cn/) * [GitBook](https://www.gitbook.com/book/miloyip/rapidjson/) with downloadable PDF/EPUB/MOBI, without API reference. ## Build status diff --git a/travis-doxygen.sh b/travis-doxygen.sh index 399df05..1023108 100755 --- a/travis-doxygen.sh +++ b/travis-doxygen.sh @@ -78,7 +78,7 @@ gh_pages_prepare() gh_pages_commit() { cd "${TRAVIS_BUILD_DIR}/build/doc/html"; - echo "www.rapidjson.org" > CNAME + echo "rapidjson.org" > CNAME git add --all; git diff-index --quiet HEAD || git commit -m "Automatic doxygen build"; } From 4e8e99c1578a8042565c64d1d481dce15b0da5a7 Mon Sep 17 00:00:00 2001 From: miloyip Date: Sat, 6 Jun 2015 21:41:19 +0800 Subject: [PATCH 108/189] Remove www in readme.zh-cn also --- readme.zh-cn.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/readme.zh-cn.md b/readme.zh-cn.md index ce9456f..5124f8e 100644 --- a/readme.zh-cn.md +++ b/readme.zh-cn.md @@ -10,8 +10,8 @@ Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights * [RapidJSON GitHub](https://github.com/miloyip/rapidjson/) * RapidJSON 文档 - * [English](http://www.rapidjson.org/) - * [简体中文](http://www.rapidjson.org/zh-cn/) + * [English](http://rapidjson.org/) + * [简体中文](http://rapidjson.org/zh-cn/) * [GitBook](https://www.gitbook.com/book/miloyip/rapidjson/)å¯ä¸‹è½½PDF/EPUB/MOBI,但ä¸å«APIå‚考手册。 ## Build çŠ¶æ€ From 134369d990018b3229d163932e42bf4b684aa0b5 Mon Sep 17 00:00:00 2001 From: miloyip Date: Wed, 10 Jun 2015 16:19:24 +0800 Subject: [PATCH 109/189] Add google analytics to documentation --- doc/misc/header.html | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/doc/misc/header.html b/doc/misc/header.html index 2dbe721..d43f2aa 100644 --- a/doc/misc/header.html +++ b/doc/misc/header.html @@ -16,6 +16,15 @@ $mathjax $extrastylesheet +

From a326314a6138b700b9443130ee6b0e76afe011ee Mon Sep 17 00:00:00 2001 From: Milo Yip Date: Thu, 18 Jun 2015 15:40:39 +0800 Subject: [PATCH 110/189] Fix #538 --- include/rapidjson/reader.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/rapidjson/reader.h b/include/rapidjson/reader.h index 18c4ca5..9a17301 100644 --- a/include/rapidjson/reader.h +++ b/include/rapidjson/reader.h @@ -271,7 +271,7 @@ inline const char *SkipWhitespace_SIMD(const char* p) { // The rest of string using SIMD static const char whitespace[16] = " \n\r\t"; - const __m128i w = _mm_load_si128((const __m128i *)&whitespace[0]); + const __m128i w = _mm_loadu_si128((const __m128i *)&whitespace[0]); for (;; p += 16) { const __m128i s = _mm_load_si128((const __m128i *)p); From 74b41c1a430ed9e6b6f3c2e5c6f906f3c4520a63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20=C5=81oskot?= Date: Wed, 24 Jun 2015 17:22:48 +0200 Subject: [PATCH 111/189] Add missing allocator to uses of AddMember AddMember requires allocator, this fix keeps all uses of AddMember consistent across the whole tutorial. --- doc/tutorial.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/doc/tutorial.md b/doc/tutorial.md index 3508918..1211023 100644 --- a/doc/tutorial.md +++ b/doc/tutorial.md @@ -292,12 +292,13 @@ The simple answer is performance. For fixed size JSON types (Number, True, False For example, if normal *copy* semantics was used: ~~~~~~~~~~cpp +Document d; Value o(kObjectType); { Value contacts(kArrayType); // adding elements to contacts array. // ... - o.AddMember("contacts", contacts); // deep clone contacts (may be with lots of allocations) + o.AddMember("contacts", contacts, d.GetAllocator()); // deep clone contacts (may be with lots of allocations) // destruct contacts. } ~~~~~~~~~~ @@ -313,11 +314,12 @@ To make RapidJSON simple and fast, we chose to use *move* semantics for assignme So, with move semantics, the above example becomes: ~~~~~~~~~~cpp +Document d; Value o(kObjectType); { Value contacts(kArrayType); // adding elements to contacts array. - o.AddMember("contacts", contacts); // just memcpy() of contacts itself to the value of new member (16 bytes) + o.AddMember("contacts", contacts, d.GetAllocator()); // just memcpy() of contacts itself to the value of new member (16 bytes) // contacts became Null here. Its destruction is trivial. } ~~~~~~~~~~ From 5d5d90c10079284c15b9a7a6795bdc8608f2be84 Mon Sep 17 00:00:00 2001 From: miloyip Date: Thu, 25 Jun 2015 09:53:31 +0800 Subject: [PATCH 112/189] Applies the same changes for Chinese as #365 --- doc/tutorial.zh-cn.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/tutorial.zh-cn.md b/doc/tutorial.zh-cn.md index d1381be..3ecaec8 100644 --- a/doc/tutorial.zh-cn.md +++ b/doc/tutorial.zh-cn.md @@ -297,7 +297,7 @@ Value o(kObjectType); Value contacts(kArrayType); // 把元素加进contacts数组。 // ... - o.AddMember("contacts", contacts); // 深度å¤åˆ¶contacts (å¯èƒ½æœ‰å¤§é‡å†…存分é…) + o.AddMember("contacts", contacts, d.GetAllocator()); // 深度å¤åˆ¶contacts (å¯èƒ½æœ‰å¤§é‡å†…存分é…) // æžæž„contacts。 } ~~~~~~~~~~ @@ -317,7 +317,7 @@ Value o(kObjectType); { Value contacts(kArrayType); // adding elements to contacts array. - o.AddMember("contacts", contacts); // åªéœ€ memcpy() contacts本身至新æˆå‘˜çš„Value(16字节) + o.AddMember("contacts", contacts, d.GetAllocator()); // åªéœ€ memcpy() contacts本身至新æˆå‘˜çš„Value(16字节) // contactsåœ¨è¿™é‡Œå˜æˆNullã€‚å®ƒçš„æžæž„是平凡的。 } ~~~~~~~~~~ From 413144a8b21270883bfe9d20723441ac12b414dc Mon Sep 17 00:00:00 2001 From: Mateusz Loskot Date: Fri, 26 Jun 2015 16:00:49 +0200 Subject: [PATCH 113/189] Add GenericDocument ctor overload to specify JSON type. It unifies the interfaces with Value where kXXXType can be passed into constructor. It enables shortcut that helps to avoid extra SetXXX() call following construction of a document. --- include/rapidjson/document.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/include/rapidjson/document.h b/include/rapidjson/document.h index 889cdfa..1b3a4f3 100644 --- a/include/rapidjson/document.h +++ b/include/rapidjson/document.h @@ -1748,6 +1748,13 @@ public: typedef GenericValue ValueType; //!< Value type of the document. typedef Allocator AllocatorType; //!< Allocator type from template parameter. + GenericDocument(Type type, Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity, StackAllocator* stackAllocator = 0) : + GenericValue(type), allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, stackCapacity), parseResult_() + { + if (!allocator_) + ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator()); + } + //! Constructor /*! \param allocator Optional allocator for allocating memory. \param stackCapacity Optional initial capacity of stack in bytes. From a0177ca210c2e9e047ec747a71cca7c3d7683ece Mon Sep 17 00:00:00 2001 From: Mateusz Loskot Date: Tue, 30 Jun 2015 10:28:07 +0200 Subject: [PATCH 114/189] Add documentation for new GenericDocument ctor taking object type. Update also documentation of the existing GenericDocument constructor. --- include/rapidjson/document.h | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/include/rapidjson/document.h b/include/rapidjson/document.h index 1b3a4f3..026c2fb 100644 --- a/include/rapidjson/document.h +++ b/include/rapidjson/document.h @@ -1748,6 +1748,13 @@ public: typedef GenericValue ValueType; //!< Value type of the document. typedef Allocator AllocatorType; //!< Allocator type from template parameter. + //! Constructor + /*! Creates an empty document of specified type. + \param type Mandatory type of object to create. + \param allocator Optional allocator for allocating memory. + \param stackCapacity Optional initial capacity of stack in bytes. + \param stackAllocator Optional allocator for allocating memory for stack. + */ GenericDocument(Type type, Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity, StackAllocator* stackAllocator = 0) : GenericValue(type), allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, stackCapacity), parseResult_() { @@ -1756,7 +1763,8 @@ public: } //! Constructor - /*! \param allocator Optional allocator for allocating memory. + /*! Creates an empty document which type is Null. + \param allocator Optional allocator for allocating memory. \param stackCapacity Optional initial capacity of stack in bytes. \param stackAllocator Optional allocator for allocating memory for stack. */ From 3c47ae9fe47b39ea1073b7598c77dbf7abe94fd1 Mon Sep 17 00:00:00 2001 From: Mateusz Loskot Date: Tue, 30 Jun 2015 11:33:44 +0200 Subject: [PATCH 115/189] Add to FAQ: How to clear-and-minimize a document? Closes #368 --- doc/faq.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/doc/faq.md b/doc/faq.md index b00b4c6..093e8e7 100644 --- a/doc/faq.md +++ b/doc/faq.md @@ -102,6 +102,21 @@ Some applications use 64-bit unsigned/signed integers. And these integers cannot be converted into `double` without loss of precision. So the parsers detects whether a JSON number is convertible to different types of integers and/or `double`. +8. How to clear-and-minimize a document or value? + +* Call one of the `SetXXX()` methods - they call destructor which deallocates DOM data: + + ``` + Document d; + ... + d.SetObject(); // clear and minimize + ``` + +* Alternatively, use equivalent of the [C++ swap with temporary idiom](https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Clear-and-minimize): + ``` + d.Swap(Value(kObjectType).Move()) + ``` + ## Document/Value (DOM) 1. What is move semantics? Why? From 8197805208304499487e0719555d084625606850 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20=C5=81oskot?= Date: Wed, 1 Jul 2015 22:36:26 +0200 Subject: [PATCH 116/189] Add explicit specifier to GenericDocument ctor. @pah recommended to mark this constructor as explicit to avoid accidentally creating a temporary GenericDocument from a Type enum value (because all arguments but the first one are optional). --- include/rapidjson/document.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/rapidjson/document.h b/include/rapidjson/document.h index 026c2fb..a20d644 100644 --- a/include/rapidjson/document.h +++ b/include/rapidjson/document.h @@ -1755,7 +1755,7 @@ public: \param stackCapacity Optional initial capacity of stack in bytes. \param stackAllocator Optional allocator for allocating memory for stack. */ - 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(type), allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, stackCapacity), parseResult_() { if (!allocator_) From 50660c093d7a483642fca27e5adfafe74fc601d0 Mon Sep 17 00:00:00 2001 From: Mateusz Loskot Date: Thu, 2 Jul 2015 14:00:52 +0200 Subject: [PATCH 117/189] Add to FAQ: How to insert a document node into another document? Closes #366 --- doc/faq.md | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/doc/faq.md b/doc/faq.md index 093e8e7..da0d39e 100644 --- a/doc/faq.md +++ b/doc/faq.md @@ -117,6 +117,45 @@ d.Swap(Value(kObjectType).Move()) ``` +9. How to insert a document node into another document? + +Let's take the following two DOM trees represented as JSON documents: + ``` + Document person; + person.Parse("{\"person\":{\"name\":{\"first\":\"Adam\",\"last\":\"Thomas\"}}}"); + + Document address; + address.Parse("{\"address\":{\"city\":\"Moscow\",\"street\":\"Quiet\"}}"); + ``` +Let's assume we want to merge them in such way that the whole `address` document becomes a node of the `person`: + ``` + { "person": { + "name": { "first": "Adam", "last": "Thomas" }, + "address": { "city": "Moscow", "street": "Quiet" } + } + } + ``` + +The most important requirement to take care of document and value life-cycle as well as consistent memory managent using the right allocator during the value transfer. + +* Simple yet most efficient way to achieve that is to modify the `address` definition above to initialize it with allocator of the `person` document, then we just add the root nenber of the value: + ``` + Documnet address(person.GetAllocator()); + ... + person["person"].AddMember("address", address["address"], person.GetAllocator()); + ``` +Alternatively, if we don't want to explicitly refer to the root value of `address` by name, we can refer to it via iterator: + ``` + auto addressRoot = address.MemberBegin(); + person["person"].AddMember(addressRoot->name, addressRoot->value, person.GetAllocator()); + ``` + +* Second way is to deep-clone the value from the address document: + ``` + Value addressValue = Value(address["address"], person.GetAllocator()); + person["person"].AddMember("address", addressValue, person.GetAllocator()); + ``` + ## Document/Value (DOM) 1. What is move semantics? Why? From 5ac04cb0123104c3cd5afc0bec6941ae149b2725 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20=C5=81oskot?= Date: Thu, 2 Jul 2015 14:05:30 +0200 Subject: [PATCH 118/189] Correct formatting of FAQ 8 and 9 --- doc/faq.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/doc/faq.md b/doc/faq.md index da0d39e..1ff6e08 100644 --- a/doc/faq.md +++ b/doc/faq.md @@ -104,7 +104,7 @@ 8. How to clear-and-minimize a document or value? -* Call one of the `SetXXX()` methods - they call destructor which deallocates DOM data: + Call one of the `SetXXX()` methods - they call destructor which deallocates DOM data: ``` Document d; @@ -112,14 +112,14 @@ d.SetObject(); // clear and minimize ``` -* Alternatively, use equivalent of the [C++ swap with temporary idiom](https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Clear-and-minimize): + Alternatively, use equivalent of the [C++ swap with temporary idiom](https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Clear-and-minimize): ``` d.Swap(Value(kObjectType).Move()) ``` 9. How to insert a document node into another document? -Let's take the following two DOM trees represented as JSON documents: + Let's take the following two DOM trees represented as JSON documents: ``` Document person; person.Parse("{\"person\":{\"name\":{\"first\":\"Adam\",\"last\":\"Thomas\"}}}"); @@ -127,7 +127,7 @@ Let's take the following two DOM trees represented as JSON documents: Document address; address.Parse("{\"address\":{\"city\":\"Moscow\",\"street\":\"Quiet\"}}"); ``` -Let's assume we want to merge them in such way that the whole `address` document becomes a node of the `person`: + Let's assume we want to merge them in such way that the whole `address` document becomes a node of the `person`: ``` { "person": { "name": { "first": "Adam", "last": "Thomas" }, @@ -136,9 +136,9 @@ Let's assume we want to merge them in such way that the whole `address` document } ``` -The most important requirement to take care of document and value life-cycle as well as consistent memory managent using the right allocator during the value transfer. + The most important requirement to take care of document and value life-cycle as well as consistent memory managent using the right allocator during the value transfer. -* Simple yet most efficient way to achieve that is to modify the `address` definition above to initialize it with allocator of the `person` document, then we just add the root nenber of the value: + Simple yet most efficient way to achieve that is to modify the `address` definition above to initialize it with allocator of the `person` document, then we just add the root nenber of the value: ``` Documnet address(person.GetAllocator()); ... @@ -150,7 +150,7 @@ Alternatively, if we don't want to explicitly refer to the root value of `addres person["person"].AddMember(addressRoot->name, addressRoot->value, person.GetAllocator()); ``` -* Second way is to deep-clone the value from the address document: + Second way is to deep-clone the value from the address document: ``` Value addressValue = Value(address["address"], person.GetAllocator()); person["person"].AddMember("address", addressValue, person.GetAllocator()); From 6610577a3e38814e86abc04818643712f0db544a Mon Sep 17 00:00:00 2001 From: Mateusz Loskot Date: Thu, 2 Jul 2015 14:14:51 +0200 Subject: [PATCH 119/189] Update FAQ 8 with shorter version of clean-and-minimize idiom. Credits to @pah who suggested it in comment to #368. --- doc/faq.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/doc/faq.md b/doc/faq.md index 093e8e7..2e8de47 100644 --- a/doc/faq.md +++ b/doc/faq.md @@ -114,7 +114,11 @@ * Alternatively, use equivalent of the [C++ swap with temporary idiom](https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Clear-and-minimize): ``` - d.Swap(Value(kObjectType).Move()) + Value(kObjectType).Swap(d); + ``` + or equivalent, but sightly longer to type: + ``` + d.Swap(Value(kObjectType).Move()); ``` ## Document/Value (DOM) From dd901f498b858ada40aaea8fc158d5d067701ae8 Mon Sep 17 00:00:00 2001 From: "Philipp A. Hartmann" Date: Sat, 4 Jul 2015 01:57:24 +0200 Subject: [PATCH 120/189] add GenericDocument<>::Swap See #368. --- include/rapidjson/document.h | 16 ++++++++++++++++ include/rapidjson/internal/stack.h | 13 +++++++++++++ test/unittest/documenttest.cpp | 14 +++++++++++++- 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/include/rapidjson/document.h b/include/rapidjson/document.h index 889cdfa..5eeef9c 100644 --- a/include/rapidjson/document.h +++ b/include/rapidjson/document.h @@ -1803,6 +1803,22 @@ public: } #endif + //! Exchange the contents of this document with those of another. + /*! + \param other Another document. + \note Constant complexity. + \see GenericValue::Swap + */ + GenericDocument& Swap(GenericDocument& rhs) RAPIDJSON_NOEXCEPT { + using std::swap; + ValueType::Swap(rhs); + stack_.Swap(rhs.stack_); + swap(allocator_, rhs.allocator_); + swap(ownAllocator_, rhs.ownAllocator_); + swap(parseResult_, rhs.parseResult_); + return *this; + } + //!@name Parse from stream //!@{ diff --git a/include/rapidjson/internal/stack.h b/include/rapidjson/internal/stack.h index bb31cc0..198c866 100644 --- a/include/rapidjson/internal/stack.h +++ b/include/rapidjson/internal/stack.h @@ -15,6 +15,8 @@ #ifndef RAPIDJSON_INTERNAL_STACK_H_ #define RAPIDJSON_INTERNAL_STACK_H_ +#include // std::swap + #include "../rapidjson.h" RAPIDJSON_NAMESPACE_BEGIN @@ -81,6 +83,17 @@ public: } #endif + void Swap(Stack& rhs) RAPIDJSON_NOEXCEPT { + using std::swap; + + swap(allocator_, rhs.allocator_); + swap(ownAllocator_, rhs.ownAllocator_); + swap(stack_, rhs.stack_); + swap(stackTop_, rhs.stackTop_); + swap(stackEnd_, rhs.stackEnd_); + swap(initialCapacity_, rhs.initialCapacity_); + } + void Clear() { stackTop_ = stack_; } void ShrinkToFit() { diff --git a/test/unittest/documenttest.cpp b/test/unittest/documenttest.cpp index 2ee6b10..3db7cd8 100644 --- a/test/unittest/documenttest.cpp +++ b/test/unittest/documenttest.cpp @@ -202,7 +202,8 @@ TEST(Document, Swap) { o.SetObject().AddMember("a", 1, a); // Swap between Document and Value - d1.Swap(o); + // d1.Swap(o); // doesn't compile + o.Swap(d1); EXPECT_TRUE(d1.IsObject()); EXPECT_TRUE(o.IsArray()); @@ -212,8 +213,19 @@ TEST(Document, Swap) { d1.Swap(d2); EXPECT_TRUE(d1.IsArray()); EXPECT_TRUE(d2.IsObject()); + EXPECT_EQ(&d2.GetAllocator(), &a); + + // reset value + Value().Swap(d1); + EXPECT_TRUE(d1.IsNull()); + + // reset document, including allocator + Document().Swap(d2); + EXPECT_TRUE(d2.IsNull()); + EXPECT_NE(&d2.GetAllocator(), &a); } + // This should be slow due to assignment in inner-loop. struct OutputStringStream : public std::ostringstream { typedef char Ch; From 8e61b726780511c71c47109abec75888d74358a2 Mon Sep 17 00:00:00 2001 From: yuzhaol Date: Thu, 9 Jul 2015 22:39:38 +0100 Subject: [PATCH 121/189] Declare intrinsic function to avoid LNK2019 in x64 debug mode Add #pragma intrinsic(_umul128) for MSVS 2005 --- include/rapidjson/internal/biginteger.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/rapidjson/internal/biginteger.h b/include/rapidjson/internal/biginteger.h index 99a30ac..e06e7e0 100755 --- a/include/rapidjson/internal/biginteger.h +++ b/include/rapidjson/internal/biginteger.h @@ -19,6 +19,7 @@ #if defined(_MSC_VER) && defined(_M_AMD64) #include // for _umul128 +#pragma intrinsic(_umul128) #endif RAPIDJSON_NAMESPACE_BEGIN From 7567752710bf4149dd0bb33f3c7f0fd6d1386328 Mon Sep 17 00:00:00 2001 From: yuzhaol Date: Thu, 9 Jul 2015 22:42:24 +0100 Subject: [PATCH 122/189] Declare intrinsic function to avoid LNK2019 in x64 debug mode Add #pragma intrinsic(_umul128) for MSVS 2005 --- include/rapidjson/internal/diyfp.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/rapidjson/internal/diyfp.h b/include/rapidjson/internal/diyfp.h index 3b6c423..d01bbe8 100644 --- a/include/rapidjson/internal/diyfp.h +++ b/include/rapidjson/internal/diyfp.h @@ -24,6 +24,7 @@ #if defined(_MSC_VER) && defined(_M_AMD64) #include #pragma intrinsic(_BitScanReverse64) +#pragma intrinsic(_umul128) #endif RAPIDJSON_NAMESPACE_BEGIN From 0ebe16e1695fd9ed31f933a269d13a05d73eaf2e Mon Sep 17 00:00:00 2001 From: "Philipp A. Hartmann" Date: Fri, 10 Jul 2015 17:06:52 +0200 Subject: [PATCH 123/189] add and use simplified "internal::Swap" This avoids the dependency on the header, as suggested by @miloyip in #376. --- include/rapidjson/document.h | 7 +++--- include/rapidjson/internal/stack.h | 17 ++++++-------- include/rapidjson/internal/swap.h | 37 ++++++++++++++++++++++++++++++ 3 files changed, 47 insertions(+), 14 deletions(-) create mode 100644 include/rapidjson/internal/swap.h diff --git a/include/rapidjson/document.h b/include/rapidjson/document.h index 5eeef9c..3496c2b 100644 --- a/include/rapidjson/document.h +++ b/include/rapidjson/document.h @@ -1810,12 +1810,11 @@ public: \see GenericValue::Swap */ GenericDocument& Swap(GenericDocument& rhs) RAPIDJSON_NOEXCEPT { - using std::swap; ValueType::Swap(rhs); stack_.Swap(rhs.stack_); - swap(allocator_, rhs.allocator_); - swap(ownAllocator_, rhs.ownAllocator_); - swap(parseResult_, rhs.parseResult_); + internal::Swap(allocator_, rhs.allocator_); + internal::Swap(ownAllocator_, rhs.ownAllocator_); + internal::Swap(parseResult_, rhs.parseResult_); return *this; } diff --git a/include/rapidjson/internal/stack.h b/include/rapidjson/internal/stack.h index 198c866..0d4a7f7 100644 --- a/include/rapidjson/internal/stack.h +++ b/include/rapidjson/internal/stack.h @@ -15,9 +15,8 @@ #ifndef RAPIDJSON_INTERNAL_STACK_H_ #define RAPIDJSON_INTERNAL_STACK_H_ -#include // std::swap - #include "../rapidjson.h" +#include "swap.h" RAPIDJSON_NAMESPACE_BEGIN namespace internal { @@ -84,14 +83,12 @@ public: #endif void Swap(Stack& rhs) RAPIDJSON_NOEXCEPT { - using std::swap; - - swap(allocator_, rhs.allocator_); - swap(ownAllocator_, rhs.ownAllocator_); - swap(stack_, rhs.stack_); - swap(stackTop_, rhs.stackTop_); - swap(stackEnd_, rhs.stackEnd_); - swap(initialCapacity_, rhs.initialCapacity_); + internal::Swap(allocator_, rhs.allocator_); + internal::Swap(ownAllocator_, rhs.ownAllocator_); + internal::Swap(stack_, rhs.stack_); + internal::Swap(stackTop_, rhs.stackTop_); + internal::Swap(stackEnd_, rhs.stackEnd_); + internal::Swap(initialCapacity_, rhs.initialCapacity_); } void Clear() { stackTop_ = stack_; } diff --git a/include/rapidjson/internal/swap.h b/include/rapidjson/internal/swap.h new file mode 100644 index 0000000..41e7e20 --- /dev/null +++ b/include/rapidjson/internal/swap.h @@ -0,0 +1,37 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_INTERNAL_SWAP_H_ +#define RAPIDJSON_INTERNAL_SWAP_H_ + +#include "../rapidjson.h" + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +//! Custom swap() to avoid dependency on C++ header +/*! \tparam T Type of the arguments to swap, should be instantiated with primitive C++ types only. + \note This has the same semantics as std::swap(). +*/ +template +inline void Swap(T& a, T& b) RAPIDJSON_NOEXCEPT { + T tmp = a; + a = b; + b = tmp; +} + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_INTERNAL_SWAP_H_ From 46e1696316e2d33c0198af2138ab481d985439f0 Mon Sep 17 00:00:00 2001 From: "Philipp A. Hartmann" Date: Mon, 13 Jul 2015 09:35:15 +0200 Subject: [PATCH 124/189] add free inline `swap` functions --- include/rapidjson/document.h | 4 ++++ test/unittest/documenttest.cpp | 12 ++++++++++++ test/unittest/valuetest.cpp | 6 ++++++ 3 files changed, 22 insertions(+) diff --git a/include/rapidjson/document.h b/include/rapidjson/document.h index 3496c2b..007fa94 100644 --- a/include/rapidjson/document.h +++ b/include/rapidjson/document.h @@ -660,6 +660,8 @@ public: return *this; } + friend inline void swap(GenericValue& a, GenericValue& b) RAPIDJSON_NOEXCEPT { a.Swap(b); } + //! Prepare Value for move semantics /*! \return *this */ GenericValue& Move() RAPIDJSON_NOEXCEPT { return *this; } @@ -1818,6 +1820,8 @@ public: return *this; } + friend inline void swap(GenericDocument& a, GenericDocument& b) RAPIDJSON_NOEXCEPT { a.Swap(b); } + //!@name Parse from stream //!@{ diff --git a/test/unittest/documenttest.cpp b/test/unittest/documenttest.cpp index 3db7cd8..810a99c 100644 --- a/test/unittest/documenttest.cpp +++ b/test/unittest/documenttest.cpp @@ -19,6 +19,7 @@ #include "rapidjson/encodedstream.h" #include "rapidjson/stringbuffer.h" #include +#include using namespace rapidjson; @@ -223,6 +224,17 @@ TEST(Document, Swap) { Document().Swap(d2); EXPECT_TRUE(d2.IsNull()); EXPECT_NE(&d2.GetAllocator(), &a); + + // testing std::swap compatibility + d1.SetBool(true); + using std::swap; + swap(d1, d2); + EXPECT_TRUE(d1.IsNull()); + EXPECT_TRUE(d2.IsTrue()); + + swap(o, d2); + EXPECT_TRUE(o.IsTrue()); + EXPECT_TRUE(d2.IsArray()); } diff --git a/test/unittest/valuetest.cpp b/test/unittest/valuetest.cpp index f14669a..900783c 100644 --- a/test/unittest/valuetest.cpp +++ b/test/unittest/valuetest.cpp @@ -272,6 +272,12 @@ TEST(Value, Swap) { EXPECT_TRUE(v1.IsObject()); EXPECT_TRUE(v2.IsInt()); EXPECT_EQ(1234, v2.GetInt()); + + // testing std::swap compatibility + using std::swap; + swap(v1, v2); + EXPECT_TRUE(v1.IsInt()); + EXPECT_TRUE(v2.IsObject()); } TEST(Value, Null) { From c2b586492724c7bbfa8bf176caee400b19f66681 Mon Sep 17 00:00:00 2001 From: "Philipp A. Hartmann" Date: Mon, 13 Jul 2015 14:38:24 +0200 Subject: [PATCH 125/189] add documentation for 'swap' friend functions --- include/rapidjson/document.h | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/include/rapidjson/document.h b/include/rapidjson/document.h index 007fa94..ae7e829 100644 --- a/include/rapidjson/document.h +++ b/include/rapidjson/document.h @@ -660,6 +660,18 @@ public: return *this; } + //! free-standing swap function helper + /*! + Helper function to enable support for common swap implementation pattern based on \c std::swap: + \code + void swap(MyClass& a, MyClass& b) { + using std::swap; + swap(a.value, b.value); + // ... + } + \endcode + \see Swap() + */ friend inline void swap(GenericValue& a, GenericValue& b) RAPIDJSON_NOEXCEPT { a.Swap(b); } //! Prepare Value for move semantics @@ -1820,6 +1832,18 @@ public: return *this; } + //! free-standing swap function helper + /*! + Helper function to enable support for common swap implementation pattern based on \c std::swap: + \code + void swap(MyClass& a, MyClass& b) { + using std::swap; + swap(a.doc, b.doc); + // ... + } + \endcode + \see Swap() + */ friend inline void swap(GenericDocument& a, GenericDocument& b) RAPIDJSON_NOEXCEPT { a.Swap(b); } //!@name Parse from stream From fec9e8a4f2df708dc98e17e69f98823797f91f33 Mon Sep 17 00:00:00 2001 From: "Philipp A. Hartmann" Date: Fri, 17 Jul 2015 08:24:43 +0200 Subject: [PATCH 126/189] prohibit C++11 move from Document to Value As reported in #387, silently moving a `GenericDocument` to a `GenericValue` can lead to object slicing and premature deletion of the owning allocator of the (surviving) `GenericValue`. To reduce this risk, prohibit move construction of a `GenericValue` from a `GenericDocument`. --- include/rapidjson/document.h | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/include/rapidjson/document.h b/include/rapidjson/document.h index d0f1c8f..f5c1be9 100644 --- a/include/rapidjson/document.h +++ b/include/rapidjson/document.h @@ -69,6 +69,9 @@ RAPIDJSON_NAMESPACE_BEGIN template class GenericValue; +template +class GenericDocument; + //! Name-value pair in a JSON object value. /*! This class was internal to GenericValue. It used to be a inner struct. @@ -446,6 +449,16 @@ private: //! Copy constructor is not permitted. GenericValue(const GenericValue& rhs); +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + //! Moving from a GenericDocument is not permitted. + template + GenericValue(GenericDocument&& rhs); + + //! Move assignment from a GenericDocument is not permitted. + template + GenericValue& operator=(GenericDocument&& rhs); +#endif + public: //! Constructor with JSON value type. @@ -1792,7 +1805,7 @@ public: #if RAPIDJSON_HAS_CXX11_RVALUE_REFS //! Move constructor in C++11 GenericDocument(GenericDocument&& rhs) RAPIDJSON_NOEXCEPT - : ValueType(std::move(rhs)), + : ValueType(std::forward(rhs)), // explicit cast to avoid prohibited move from Document allocator_(rhs.allocator_), ownAllocator_(rhs.ownAllocator_), stack_(std::move(rhs.stack_)), From 8c0e50f5962a3bd672a5fa85ae2ea0e5b8d2cffb Mon Sep 17 00:00:00 2001 From: Milo Yip Date: Mon, 20 Jul 2015 09:29:15 +0800 Subject: [PATCH 127/189] Update dom.md --- doc/dom.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/dom.md b/doc/dom.md index f3e4208..24f1a39 100644 --- a/doc/dom.md +++ b/doc/dom.md @@ -124,7 +124,7 @@ And the `InputStream` is type of input stream. ## Parse Error {#ParseError} -When the parse processing succeeded, the `Document` contains the parse results. When there is an error, the original DOM is *unchanged*. And the error state of parsing can be obtained by `bool HasParseError()`, `ParseErrorCode GetParseError()` and `size_t GetParseOffet()`. +When the parse processing succeeded, the `Document` contains the parse results. When there is an error, the original DOM is *unchanged*. And the error state of parsing can be obtained by `bool HasParseError()`, `ParseErrorCode GetParseError()` and `size_t GetParseOffset()`. Parse Error Code | Description --------------------------------------------|--------------------------------------------------- @@ -159,8 +159,8 @@ Here shows an example of parse error handling. Document d; if (d.Parse(json).HasParseError()) { fprintf(stderr, "\nError(offset %u): %s\n", - (unsigned)reader.GetErrorOffset(), - GetParseError_En(reader.GetParseErrorCode())); + (unsigned)d.GetErrorOffset(), + GetParseError_En(d.GetParseErrorCode())); // ... } ~~~~~~~~~~ From f431aaff9dd9fd2f167b2a68d3a1f2e9666b6265 Mon Sep 17 00:00:00 2001 From: Milo Yip Date: Mon, 20 Jul 2015 09:29:46 +0800 Subject: [PATCH 128/189] Update dom.zh-cn.md --- doc/dom.zh-cn.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/dom.zh-cn.md b/doc/dom.zh-cn.md index c7fcfff..bb4eafb 100644 --- a/doc/dom.zh-cn.md +++ b/doc/dom.zh-cn.md @@ -124,7 +124,7 @@ GenericDocument& GenericDocument::Parse(const Ch* str); ## è§£æžé”™è¯¯ {#ParseError} -当解æžè¿‡ç¨‹é¡ºåˆ©å®Œæˆï¼Œ`Document`ä¾¿ä¼šå«æœ‰è§£æžç»“果。当过程出现错误,原æ¥çš„DOM会*ç»´æŒä¸ä¾¿*。å¯ä½¿ç”¨`bool HasParseError()`ã€`ParseErrorCode GetParseError()`åŠ`size_t GetParseOffet()`获å–è§£æžçš„错误状æ€ã€‚ +当解æžè¿‡ç¨‹é¡ºåˆ©å®Œæˆï¼Œ`Document`ä¾¿ä¼šå«æœ‰è§£æžç»“果。当过程出现错误,原æ¥çš„DOM会*ç»´æŒä¸ä¾¿*。å¯ä½¿ç”¨`bool HasParseError()`ã€`ParseErrorCode GetParseError()`åŠ`size_t GetParseOffset()`获å–è§£æžçš„错误状æ€ã€‚ è§£æžé”™è¯¯ä»£å· | æè¿° --------------------------------------------|--------------------------------------------------- @@ -159,8 +159,8 @@ GenericDocument& GenericDocument::Parse(const Ch* str); Document d; if (d.Parse(json).HasParseError()) { fprintf(stderr, "\nError(offset %u): %s\n", - (unsigned)reader.GetErrorOffset(), - GetParseError_En(reader.GetParseErrorCode())); + (unsigned)d.GetErrorOffset(), + GetParseError_En(d.GetParseErrorCode())); // ... } ~~~~~~~~~~ From b4b1a39937fbd168ef72ea477f90f626773d56fc Mon Sep 17 00:00:00 2001 From: Bas Couwenberg Date: Tue, 21 Jul 2015 08:46:36 +0200 Subject: [PATCH 129/189] Clarify problematic JSON license (#377) --- license.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/license.txt b/license.txt index a1bb283..03e66d6 100644 --- a/license.txt +++ b/license.txt @@ -3,7 +3,7 @@ Tencent is pleased to support the open source community by making RapidJSON avai Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. If you have downloaded a copy of the RapidJSON binary from Tencent, please note that the RapidJSON binary is licensed under the MIT License. -If you have downloaded a copy of the RapidJSON source code from Tencent, please note that RapidJSON source code is licensed under the MIT License, except for the third-party components listed below which are subject to different license terms. Your integration of RapidJSON into your own projects may require compliance with the MIT License, as well as the other licenses applicable to the third-party components included within RapidJSON. +If you have downloaded a copy of the RapidJSON source code from Tencent, please note that RapidJSON source code is licensed under the MIT License, except for the third-party components listed below which are subject to different license terms. Your integration of RapidJSON into your own projects may require compliance with the MIT License, as well as the other licenses applicable to the third-party components included within RapidJSON. To avoid the problematic JSON license in your own projects, it's sufficient to exclude the bin/jsonchecker/ directory, as it's the only code under the JSON license. A copy of the MIT License is included in this file. Other dependencies and licenses: From d26d50092ddf2917a73137ff27c04fdc76271e73 Mon Sep 17 00:00:00 2001 From: scheiber Date: Tue, 21 Jul 2015 15:15:42 -0600 Subject: [PATCH 130/189] fixing sign conversion warnings and loss of precision warnings --- include/rapidjson/encodedstream.h | 2 +- include/rapidjson/internal/biginteger.h | 2 +- include/rapidjson/internal/diyfp.h | 4 ++-- include/rapidjson/internal/dtoa.h | 8 ++++---- include/rapidjson/internal/ieee754.h | 2 +- include/rapidjson/internal/strtod.h | 22 +++++++++++----------- include/rapidjson/writer.h | 10 +++++----- 7 files changed, 25 insertions(+), 25 deletions(-) diff --git a/include/rapidjson/encodedstream.h b/include/rapidjson/encodedstream.h index 9a93b38..7bc6ad3 100644 --- a/include/rapidjson/encodedstream.h +++ b/include/rapidjson/encodedstream.h @@ -146,7 +146,7 @@ private: if (!c) return; - unsigned bom = c[0] | (c[1] << 8) | (c[2] << 16) | (c[3] << 24); + unsigned bom = static_cast(c[0] | (c[1] << 8) | (c[2] << 16) | (c[3] << 24)); hasBOM_ = false; if (bom == 0xFFFE0000) { type_ = kUTF32BE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); } else if (bom == 0x0000FEFF) { type_ = kUTF32LE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); } diff --git a/include/rapidjson/internal/biginteger.h b/include/rapidjson/internal/biginteger.h index 99a30ac..d1732a0 100755 --- a/include/rapidjson/internal/biginteger.h +++ b/include/rapidjson/internal/biginteger.h @@ -230,7 +230,7 @@ private: uint64_t r = 0; for (const char* p = begin; p != end; ++p) { RAPIDJSON_ASSERT(*p >= '0' && *p <= '9'); - r = r * 10 + (*p - '0'); + r = r * 10u + (unsigned)(*p - '0'); } return r; } diff --git a/include/rapidjson/internal/diyfp.h b/include/rapidjson/internal/diyfp.h index 3b6c423..42d8b3b 100644 --- a/include/rapidjson/internal/diyfp.h +++ b/include/rapidjson/internal/diyfp.h @@ -232,8 +232,8 @@ inline DiyFp GetCachedPower(int e, int* K) { } inline DiyFp GetCachedPower10(int exp, int *outExp) { - unsigned index = (exp + 348) / 8; - *outExp = -348 + index * 8; + unsigned index = (static_cast(exp) + 348u) / 8u; + *outExp = -348 + static_cast(index) * 8; return GetCachedPowerByIndex(index); } diff --git a/include/rapidjson/internal/dtoa.h b/include/rapidjson/internal/dtoa.h index 2d8d2e4..3695866 100644 --- a/include/rapidjson/internal/dtoa.h +++ b/include/rapidjson/internal/dtoa.h @@ -62,7 +62,7 @@ inline void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buff const DiyFp wp_w = Mp - W; uint32_t p1 = static_cast(Mp.f >> -one.e); uint64_t p2 = Mp.f & (one.f - 1); - int kappa = CountDecimalDigit32(p1); // kappa in [0, 9] + unsigned kappa = CountDecimalDigit32(p1); // kappa in [0, 9] *len = 0; while (kappa > 0) { @@ -158,14 +158,14 @@ inline char* Prettify(char* buffer, int length, int k) { } else if (0 < kk && kk <= 21) { // 1234e-2 -> 12.34 - std::memmove(&buffer[kk + 1], &buffer[kk], length - kk); + std::memmove(&buffer[kk + 1], &buffer[kk], static_cast(length - kk)); buffer[kk] = '.'; return &buffer[length + 1]; } else if (-6 < kk && kk <= 0) { // 1234e-6 -> 0.001234 const int offset = 2 - kk; - std::memmove(&buffer[offset], &buffer[0], length); + std::memmove(&buffer[offset], &buffer[0], static_cast(length)); buffer[0] = '0'; buffer[1] = '.'; for (int i = 2; i < offset; i++) @@ -179,7 +179,7 @@ inline char* Prettify(char* buffer, int length, int k) { } else { // 1234e30 -> 1.234e33 - std::memmove(&buffer[2], &buffer[1], length - 1); + std::memmove(&buffer[2], &buffer[1], static_cast(length - 1)); buffer[1] = '.'; buffer[length + 1] = 'e'; return WriteExponent(kk - 1, &buffer[0 + length + 2]); diff --git a/include/rapidjson/internal/ieee754.h b/include/rapidjson/internal/ieee754.h index e3f0336..2fdaf54 100644 --- a/include/rapidjson/internal/ieee754.h +++ b/include/rapidjson/internal/ieee754.h @@ -53,7 +53,7 @@ public: else if (order <= -1074) return 0; else - return order + 1074; + return (unsigned)order + 1074; } private: diff --git a/include/rapidjson/internal/strtod.h b/include/rapidjson/internal/strtod.h index ace65f6..a1b8211 100644 --- a/include/rapidjson/internal/strtod.h +++ b/include/rapidjson/internal/strtod.h @@ -95,13 +95,13 @@ inline int CheckWithinHalfULP(double b, const BigInteger& d, int dExp) { hS_Exp2 -= common_Exp2; BigInteger dS = d; - dS.MultiplyPow5(dS_Exp5) <<= dS_Exp2; + dS.MultiplyPow5(static_cast(dS_Exp5)) <<= static_cast(dS_Exp2); BigInteger bS(bInt); - bS.MultiplyPow5(bS_Exp5) <<= bS_Exp2; + bS.MultiplyPow5(static_cast(bS_Exp5)) <<= static_cast(bS_Exp2); BigInteger hS(1); - hS.MultiplyPow5(hS_Exp5) <<= hS_Exp2; + hS.MultiplyPow5(static_cast(hS_Exp5)) <<= static_cast(hS_Exp2); BigInteger delta(0); dS.Difference(bS, &delta); @@ -134,7 +134,7 @@ inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosit if (significand > RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) || (significand == RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) && decimals[i] > '5')) break; - significand = significand * 10 + (decimals[i] - '0'); + significand = significand * 10u + static_cast(decimals[i] - '0'); } if (i < length && decimals[i] >= '5') // Rounding @@ -163,10 +163,10 @@ inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosit DiyFp(RAPIDJSON_UINT64_C2(0xf4240000, 00000000), -44), // 10^6 DiyFp(RAPIDJSON_UINT64_C2(0x98968000, 00000000), -40) // 10^7 }; - int adjustment = dExp - actualExp - 1; + int adjustment = dExp - actualExp - 1; RAPIDJSON_ASSERT(adjustment >= 0 && adjustment < 7); v = v * kPow10[adjustment]; - if (length + adjustment > 19) // has more digits than decimal digits in 64-bit + if (length + static_cast(adjustment)> 19u) // has more digits than decimal digits in 64-bit error += kUlp / 2; } @@ -184,14 +184,14 @@ inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosit unsigned scaleExp = (precisionSize + kUlpShift) - 63; v.f >>= scaleExp; v.e += scaleExp; - error = (error >> scaleExp) + 1 + kUlp; + error = (error >> scaleExp) + 1 + static_cast(kUlp); precisionSize -= scaleExp; } - DiyFp rounded(v.f >> precisionSize, v.e + precisionSize); + DiyFp rounded(v.f >> precisionSize, v.e + static_cast(precisionSize)); const uint64_t precisionBits = (v.f & ((uint64_t(1) << precisionSize) - 1)) * kUlp; const uint64_t halfWay = (uint64_t(1) << (precisionSize - 1)) * kUlp; - if (precisionBits >= halfWay + error) { + if (precisionBits >= halfWay + static_cast(error)) { rounded.f++; if (rounded.f & (DiyFp::kDpHiddenBit << 1)) { // rounding overflows mantissa (issue #340) rounded.f >>= 1; @@ -201,7 +201,7 @@ inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosit *result = rounded.ToDouble(); - return halfWay - error >= precisionBits || precisionBits >= halfWay + error; + return halfWay - static_cast(error) >= precisionBits || precisionBits >= halfWay + static_cast(error); } inline double StrtodBigInteger(double approx, const char* decimals, size_t length, size_t decimalPosition, int exp) { @@ -249,7 +249,7 @@ inline double StrtodFullPrecision(double d, int p, const char* decimals, size_t if ((int)length > kMaxDecimalDigit) { int delta = (int(length) - kMaxDecimalDigit); exp += delta; - decimalPosition -= delta; + decimalPosition -= static_cast(delta); length = kMaxDecimalDigit; } diff --git a/include/rapidjson/writer.h b/include/rapidjson/writer.h index 40cdb35..8fcffbe 100644 --- a/include/rapidjson/writer.h +++ b/include/rapidjson/writer.h @@ -350,7 +350,7 @@ template<> inline bool Writer::WriteInt(int i) { char *buffer = os_->Push(11); const char* end = internal::i32toa(i, buffer); - os_->Pop(11 - (end - buffer)); + os_->Pop(static_cast(11 - (end - buffer))); return true; } @@ -358,7 +358,7 @@ template<> inline bool Writer::WriteUint(unsigned u) { char *buffer = os_->Push(10); const char* end = internal::u32toa(u, buffer); - os_->Pop(10 - (end - buffer)); + os_->Pop(static_cast(10 - (end - buffer))); return true; } @@ -366,7 +366,7 @@ template<> inline bool Writer::WriteInt64(int64_t i64) { char *buffer = os_->Push(21); const char* end = internal::i64toa(i64, buffer); - os_->Pop(21 - (end - buffer)); + os_->Pop(static_cast(21 - (end - buffer))); return true; } @@ -374,7 +374,7 @@ template<> inline bool Writer::WriteUint64(uint64_t u) { char *buffer = os_->Push(20); const char* end = internal::u64toa(u, buffer); - os_->Pop(20 - (end - buffer)); + os_->Pop(static_cast(20 - (end - buffer))); return true; } @@ -382,7 +382,7 @@ template<> inline bool Writer::WriteDouble(double d) { char *buffer = os_->Push(25); char* end = internal::dtoa(d, buffer); - os_->Pop(25 - (end - buffer)); + os_->Pop(static_cast(25 - (end - buffer))); return true; } From f33b6740fcef78e8b3ffffe5f9d6627646c5f27e Mon Sep 17 00:00:00 2001 From: scheiber Date: Tue, 21 Jul 2015 16:39:00 -0600 Subject: [PATCH 131/189] Revert "update the submodule fore google test" This reverts commit 5be9b6e584656bbc94d894887ded663442a024fb. --- .gitmodules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitmodules b/.gitmodules index 25460de..b54b211 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ [submodule "thirdparty/gtest"] path = thirdparty/gtest - url = ssh://git@git.eyesopen.com/common/googletest.git + url = ssh://git@git.eyesopen.com/common/rapidjson.git From a0f730e3d7b49455787e6061ca38fa8d3ec2ceff Mon Sep 17 00:00:00 2001 From: scheiber Date: Tue, 21 Jul 2015 16:42:50 -0600 Subject: [PATCH 132/189] use -Werror --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 68139ba..a6fd165 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,9 +26,9 @@ if(RAPIDJSON_HAS_STDSTRING) endif() if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native -Wall -Wextra") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native -Wall -Wextra -Werror") elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native -Wall -Wextra") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native -Wall -Wextra -Werror") elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") add_definitions(-D_CRT_SECURE_NO_WARNINGS=1) endif() From 73cf03c2bf77c5c610abf39ec7745005364fdc01 Mon Sep 17 00:00:00 2001 From: scheiber Date: Tue, 21 Jul 2015 16:52:16 -0600 Subject: [PATCH 133/189] use google's servers for googletest --- .gitmodules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitmodules b/.gitmodules index b54b211..8e9d1f3 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ [submodule "thirdparty/gtest"] path = thirdparty/gtest - url = ssh://git@git.eyesopen.com/common/rapidjson.git + url = https://chromium.googlesource.com/external/googletest.git From e527a4fe5e299ad928c9a316be14826a2bccbeac Mon Sep 17 00:00:00 2001 From: Justin Scheiber Date: Tue, 21 Jul 2015 17:42:28 -0600 Subject: [PATCH 134/189] adding -Wno-missing-field-initializers to keep the googletest source from erroring out on a warning --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a6fd165..51ee620 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,7 +28,7 @@ endif() if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native -Wall -Wextra -Werror") elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native -Wall -Wextra -Werror") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native -Wall -Wextra -Werror -Wno-missing-field-initializers") elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") add_definitions(-D_CRT_SECURE_NO_WARNINGS=1) endif() From fc50f103a67adeb4963a4fefdcd6c433daf31e23 Mon Sep 17 00:00:00 2001 From: blackball Date: Fri, 24 Jul 2015 16:19:08 +0200 Subject: [PATCH 135/189] Fix the error when compiled using vs2013 The error message for the original codes is: unary minus operator applied to unsigned type, result still unsigned. Added static casting to eliminate this message. --- include/rapidjson/internal/dtoa.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/rapidjson/internal/dtoa.h b/include/rapidjson/internal/dtoa.h index 3695866..d04ae21 100644 --- a/include/rapidjson/internal/dtoa.h +++ b/include/rapidjson/internal/dtoa.h @@ -101,7 +101,7 @@ inline void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buff kappa--; if (p2 < delta) { *K += kappa; - GrisuRound(buffer, *len, delta, p2, one.f, wp_w.f * kPow10[-kappa]); + GrisuRound(buffer, *len, delta, p2, one.f, wp_w.f * kPow10[-static_cast(kappa)]); return; } } From 2a18d306b845fed167446f1c740f70413172433c Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Sat, 1 Aug 2015 13:05:28 +0300 Subject: [PATCH 136/189] @PlatformIO Library Registry manifest file * This library in Web Registry: http://platformio.org/#!/lib/show/438/RapidJSON * Specification: [PlatformIO Library Manager](http://docs.platformio.org/en/latest/librarymanager/index.html) * Integration: [IDE Integration](http://docs.platformio.org/en/latest/ide.html) --- library.json | Bin 0 -> 322 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 library.json diff --git a/library.json b/library.json new file mode 100644 index 0000000000000000000000000000000000000000..429e453ec704dc5b5e6ae4d8528de064291232a7 GIT binary patch literal 322 zcmYjMO>4t2487-92p`)}-*XGwWrM9_z4YqFZsX0igzV6o(*IsN31bHdq4%MudjlYX z@bp`VDMg{W>VX!I?R;%K;qiwTBRLS7`=#DOg(i=nD| zIIEbTTCNKDCxA0Dyll5{wP}PCmUifm@^$|KF=c0<|9V?YZ5Z67=Y;DhxhAcd7KXVg zPi|(cquj{NZXjB4HiXfZlv#A;vwNxXU&=H~E;h}yvYOb{++#` Date: Sat, 1 Aug 2015 13:10:26 +0300 Subject: [PATCH 137/189] Add examples for @PlatformIO Library Registry --- library.json | Bin 322 -> 323 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/library.json b/library.json index 429e453ec704dc5b5e6ae4d8528de064291232a7..3b53db4c122a9255a74dbc4055adfa11290fe08e 100644 GIT binary patch delta 11 ScmX@abeL(vS;pdtXG;Mcu>~#w delta 9 QcmX@ibckuf*@@>$0Tvbny8r+H From 720d1688f14ef43f35ea87ac4878d83951faa9d5 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Mon, 3 Aug 2015 16:30:37 +0300 Subject: [PATCH 138/189] Fix include location --- library.json | Bin 323 -> 313 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/library.json b/library.json index 3b53db4c122a9255a74dbc4055adfa11290fe08e..47fd352ac7efa35c343de9a2d74ee55ff19ba2eb 100644 GIT binary patch delta 9 QcmX@iw3BJVwuuLt0Tpcon*aa+ delta 20 bcmdnVbeL(vHZJ|5#DdI}tm6E Date: Fri, 7 Aug 2015 10:04:45 +0200 Subject: [PATCH 139/189] Implement = operator for BigInteger There's a copy constructor, but no '=' operator implemented. This is dangerous. --- include/rapidjson/internal/biginteger.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/include/rapidjson/internal/biginteger.h b/include/rapidjson/internal/biginteger.h index 512b6f9..f4d6d12 100755 --- a/include/rapidjson/internal/biginteger.h +++ b/include/rapidjson/internal/biginteger.h @@ -51,7 +51,14 @@ public: if (length > 0) AppendDecimal64(decimals + i, decimals + i + length); } - + + BigInteger& operator=(const BigInteger &rhs) + { + count_ = rhs.count_; + std::memcpy(digits_, rhs.digits_, count_ * sizeof(Type)); + return *this; + } + BigInteger& operator=(uint64_t u) { digits_[0] = u; count_ = 1; From 456975290375ef039cc18d15323f79dbe348db4c Mon Sep 17 00:00:00 2001 From: Ziyang LI Date: Mon, 10 Aug 2015 18:11:25 +0800 Subject: [PATCH 140/189] added missing fields of CMakeList.txt this fixed cmake error for me --- example/CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt index 6463212..8063d89 100644 --- a/example/CMakeLists.txt +++ b/example/CMakeLists.txt @@ -1,6 +1,7 @@ # Copyright (c) 2011 Milo Yip (miloyip@gmail.com) # Copyright (c) 2013 Rafal Jeczalik (rjeczalik@gmail.com) # Distributed under the MIT License (see license.txt file) +cmake_minimum_required(VERSION 2.8) set(EXAMPLES capitalize @@ -13,6 +14,8 @@ set(EXAMPLES simplereader simplewriter tutorial) + +include_directories("../include/") if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror -Wall -Wextra -Weffc++ -Wswitch-default") From ffd389befc3d828effcb7b72979546a3f5cd6a26 Mon Sep 17 00:00:00 2001 From: "Force.Charlie-I" Date: Wed, 12 Aug 2015 18:38:13 +0800 Subject: [PATCH 141/189] =?UTF-8?q?=E8=87=AA=E5=AE=9A=E4=B9=89=E6=B5=81?= =?UTF-8?q?=E5=BA=94=E5=BD=93=E4=BD=BF=E7=94=A8=20ParseStream=20=E8=80=8C?= =?UTF-8?q?=E4=B8=8D=E6=98=AF=20Parse?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/stream.zh-cn.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/stream.zh-cn.md b/doc/stream.zh-cn.md index 5ac32f8..0f930a9 100644 --- a/doc/stream.zh-cn.md +++ b/doc/stream.zh-cn.md @@ -320,7 +320,7 @@ std::stringstream ss(json); IStreamWrapper is(ss); Document d; -d.Parse(is); +d.ParseStream(is); ~~~~~~~~~~ ä½†è¦æ³¨æ„,由于标准库的内部开销问,此实现的性能å¯èƒ½ä¸å¦‚RapidJSONçš„å†…å­˜ï¼æ–‡ä»¶æµã€‚ From 3cf7228f4670d9ea3a283bf316c9be5abefa1777 Mon Sep 17 00:00:00 2001 From: Milo Yip Date: Thu, 13 Aug 2015 10:16:19 +0800 Subject: [PATCH 142/189] Port documentation fix from #407 --- doc/stream.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/stream.md b/doc/stream.md index 94bc10d..7b3c5ca 100644 --- a/doc/stream.md +++ b/doc/stream.md @@ -320,7 +320,7 @@ std::stringstream ss(json); IStreamWrapper is(ss); Document d; -d.Parse(is); +d.ParseStream(is); ~~~~~~~~~~ Note that, this implementation may not be as efficient as RapidJSON's memory or file streams, due to internal overheads of the standard library. From afbc0406f0a59fd5423b3127ed23ba3414a0c53f Mon Sep 17 00:00:00 2001 From: "Philipp A. Hartmann" Date: Thu, 13 Aug 2015 23:07:30 +0200 Subject: [PATCH 143/189] BigInteger: guard against self-assignment Related-to: #404. Suggested-by: @cosinekitty --- include/rapidjson/internal/biginteger.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/include/rapidjson/internal/biginteger.h b/include/rapidjson/internal/biginteger.h index f4d6d12..4477cf5 100755 --- a/include/rapidjson/internal/biginteger.h +++ b/include/rapidjson/internal/biginteger.h @@ -54,8 +54,10 @@ public: BigInteger& operator=(const BigInteger &rhs) { - count_ = rhs.count_; - std::memcpy(digits_, rhs.digits_, count_ * sizeof(Type)); + if (this != &rhs) { + count_ = rhs.count_; + std::memcpy(digits_, rhs.digits_, count_ * sizeof(Type)); + } return *this; } From 311b48224ff02466a0464d51db2ed0a3a0d6cc3b Mon Sep 17 00:00:00 2001 From: Milo Yip Date: Tue, 1 Sep 2015 10:05:33 +0800 Subject: [PATCH 144/189] Try to fix incorrect 64-bit alignment Added unit tests for alignment macros. Fixes #418 --- include/rapidjson/rapidjson.h | 6 +++--- test/unittest/allocatorstest.cpp | 20 ++++++++++++++++++++ 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/include/rapidjson/rapidjson.h b/include/rapidjson/rapidjson.h index b0dabc7..4c4d983 100644 --- a/include/rapidjson/rapidjson.h +++ b/include/rapidjson/rapidjson.h @@ -238,13 +238,13 @@ \param x pointer to align Some machines require strict data alignment. Currently the default uses 4 bytes - alignment. User can customize by defining the RAPIDJSON_ALIGN function macro., + alignment. User can customize by defining the RAPIDJSON_ALIGN function macro. */ #ifndef RAPIDJSON_ALIGN #if RAPIDJSON_64BIT == 1 -#define RAPIDJSON_ALIGN(x) ((x + 7u) & ~7u) +#define RAPIDJSON_ALIGN(x) (((x) + static_cast(7u)) & ~static_cast(7u)) #else -#define RAPIDJSON_ALIGN(x) ((x + 3u) & ~3u) +#define RAPIDJSON_ALIGN(x) (((x) + 3u) & ~3u) #endif #endif diff --git a/test/unittest/allocatorstest.cpp b/test/unittest/allocatorstest.cpp index 7b4deed..792a88e 100644 --- a/test/unittest/allocatorstest.cpp +++ b/test/unittest/allocatorstest.cpp @@ -61,3 +61,23 @@ TEST(Allocator, MemoryPoolAllocator) { EXPECT_LE(a.Size(), a.Capacity()); } } + +TEST(Allocator, Alignment) { +#if RAPIDJSON_64BIT == 1 + EXPECT_EQ(RAPIDJSON_UINT64_C2(0x00000000, 0x00000000), RAPIDJSON_ALIGN(0)); + for (uint64_t i = 1; i < 8; i++) { + EXPECT_EQ(RAPIDJSON_UINT64_C2(0x00000000, 0x00000008), RAPIDJSON_ALIGN(i)); + EXPECT_EQ(RAPIDJSON_UINT64_C2(0x00000000, 0x00000010), RAPIDJSON_ALIGN(RAPIDJSON_UINT64_C2(0x00000000, 0x00000008) + i)); + EXPECT_EQ(RAPIDJSON_UINT64_C2(0x00000001, 0x00000000), RAPIDJSON_ALIGN(RAPIDJSON_UINT64_C2(0x00000000, 0xFFFFFFF8) + i)); + EXPECT_EQ(RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0xFFFFFFF8), RAPIDJSON_ALIGN(RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0xFFFFFFF0) + i)); + } +#else + EXPECT_EQ(0u, RAPIDJSON_ALIGN(0u)); + for (uint32_t i = 1; i < 4; i++) { + EXPECT_EQ(4u, RAPIDJSON_ALIGN(i)); + EXPECT_EQ(8u, RAPIDJSON_ALIGN(4u + i)); + EXPECT_EQ(0xFFFFFFF8u, RAPIDJSON_ALIGN(0xFFFFFFF4u + i)); + EXPECT_EQ(0xFFFFFFFCu, RAPIDJSON_ALIGN(0xFFFFFFF8u + i)); + } +#endif +} From 2a267ff15abea98dd63e988999bdfb8f09a85893 Mon Sep 17 00:00:00 2001 From: Kurt Johnson Date: Wed, 2 Sep 2015 09:29:15 -0500 Subject: [PATCH 145/189] check return of fwrite to avoid warn_unused_result build failures --- include/rapidjson/filewritestream.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/include/rapidjson/filewritestream.h b/include/rapidjson/filewritestream.h index 31223b8..55da265 100644 --- a/include/rapidjson/filewritestream.h +++ b/include/rapidjson/filewritestream.h @@ -57,7 +57,11 @@ public: void Flush() { if (current_ != buffer_) { - fwrite(buffer_, 1, static_cast(current_ - buffer_), fp_); + size_t result = fwrite(buffer_, 1, static_cast(current_ - buffer_), fp_); + if (result < static_cast(current_ - buffer_)) { + // failure deliberately ignored at this time + // added to avoid warn_unused_result build errors + } current_ = buffer_; } } From 8604ba0f1cfc1f2cd73a9d98085143614e587888 Mon Sep 17 00:00:00 2001 From: Rodion Malinovsky Date: Wed, 16 Sep 2015 14:53:12 +0300 Subject: [PATCH 146/189] Add asserts to prevent UB --- include/rapidjson/document.h | 5 ++++- include/rapidjson/internal/stack.h | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/include/rapidjson/document.h b/include/rapidjson/document.h index f5c1be9..6275f96 100644 --- a/include/rapidjson/document.h +++ b/include/rapidjson/document.h @@ -1989,7 +1989,10 @@ public: //!@} //! Get the allocator of this document. - Allocator& GetAllocator() { return *allocator_; } + Allocator& GetAllocator() { + RAPIDJSON_ASSERT(allocator_); + return *allocator_; + } //! Get the capacity of stack in bytes. size_t GetStackCapacity() const { return stack_.GetCapacity(); } diff --git a/include/rapidjson/internal/stack.h b/include/rapidjson/internal/stack.h index 0d4a7f7..4b98e38 100644 --- a/include/rapidjson/internal/stack.h +++ b/include/rapidjson/internal/stack.h @@ -134,7 +134,10 @@ public: template T* Bottom() { return (T*)stack_; } - Allocator& GetAllocator() { return *allocator_; } + Allocator& GetAllocator() { + RAPIDJSON_ASSERT(allocator_); + return *allocator_; + } bool Empty() const { return stackTop_ == stack_; } size_t GetSize() const { return static_cast(stackTop_ - stack_); } size_t GetCapacity() const { return static_cast(stackEnd_ - stack_); } From c7433dfc5ede497126ca347af93ce8587beeafb0 Mon Sep 17 00:00:00 2001 From: Rodion Malinovsky Date: Wed, 16 Sep 2015 14:53:51 +0300 Subject: [PATCH 147/189] Add stack::HasAllocator To check is it possible to expose allocator. --- include/rapidjson/internal/stack.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/rapidjson/internal/stack.h b/include/rapidjson/internal/stack.h index 4b98e38..82f23dd 100644 --- a/include/rapidjson/internal/stack.h +++ b/include/rapidjson/internal/stack.h @@ -134,6 +134,10 @@ public: template T* Bottom() { return (T*)stack_; } + bool HasAllocator() const { + return allocator_ != 0; + } + Allocator& GetAllocator() { RAPIDJSON_ASSERT(allocator_); return *allocator_; From 2e11498943153e72afe0af0f64aecf090c0df659 Mon Sep 17 00:00:00 2001 From: Rodion Malinovsky Date: Wed, 16 Sep 2015 14:54:38 +0300 Subject: [PATCH 148/189] Fix the usage of the stack::GetAllocator --- include/rapidjson/document.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/rapidjson/document.h b/include/rapidjson/document.h index 6275f96..0a5a7b2 100644 --- a/include/rapidjson/document.h +++ b/include/rapidjson/document.h @@ -1887,7 +1887,8 @@ public: template GenericDocument& ParseStream(InputStream& is) { ValueType::SetNull(); // Remove existing root if exist - GenericReader reader(&stack_.GetAllocator()); + GenericReader reader( + stack_.HasAllocator() ? &stack_.GetAllocator() : 0); ClearStackOnExit scope(*this); parseResult_ = reader.template Parse(is, *this); if (parseResult_) { From fa123699d32948eb4f539934a4574e3b73ce6c3d Mon Sep 17 00:00:00 2001 From: "Philipp A. Hartmann" Date: Wed, 7 Oct 2015 21:48:39 +0200 Subject: [PATCH 149/189] Keep Document value unchanged on parse error, fixes #437 Keeping the DOM unchanged in case of an error is the intended behaviour according to the [documentation] [1]. Instead of forcing the value to `kNullType` before starting the parsing, store the parsed value upon success via regular move. [1]: https://miloyip.github.io/rapidjson/md_doc_dom.html#ParseError --- include/rapidjson/document.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/include/rapidjson/document.h b/include/rapidjson/document.h index 0a5a7b2..516cb5e 100644 --- a/include/rapidjson/document.h +++ b/include/rapidjson/document.h @@ -1886,14 +1886,13 @@ public: */ template GenericDocument& ParseStream(InputStream& is) { - ValueType::SetNull(); // Remove existing root if exist GenericReader reader( stack_.HasAllocator() ? &stack_.GetAllocator() : 0); ClearStackOnExit scope(*this); parseResult_ = reader.template Parse(is, *this); if (parseResult_) { RAPIDJSON_ASSERT(stack_.GetSize() == sizeof(ValueType)); // Got one and only one root object - this->RawAssign(*stack_.template Pop(1)); // Add this-> to prevent issue 13. + ValueType::operator=(*stack_.template Pop(1));// Move value from stack to document } return *this; } From 41dd68f092d9a90e8cf87ba78a4af7dbccf261d9 Mon Sep 17 00:00:00 2001 From: "Philipp A. Hartmann" Date: Wed, 7 Oct 2015 21:50:14 +0200 Subject: [PATCH 150/189] add simple test for unchanged DOM after parse error --- test/unittest/documenttest.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/test/unittest/documenttest.cpp b/test/unittest/documenttest.cpp index 810a99c..83325a7 100644 --- a/test/unittest/documenttest.cpp +++ b/test/unittest/documenttest.cpp @@ -95,6 +95,21 @@ TEST(Document, Parse) { ParseTest(); } +TEST(Document, UnchangedOnParseError) { + Document doc; + doc.SetArray().PushBack(0, doc.GetAllocator()); + + doc.Parse("{]"); + EXPECT_TRUE(doc.HasParseError()); + EXPECT_TRUE(doc.IsArray()); + EXPECT_EQ(doc.Size(), 1u); + + doc.Parse("{}"); + EXPECT_FALSE(doc.HasParseError()); + EXPECT_TRUE(doc.IsObject()); + EXPECT_EQ(doc.MemberCount(), 0u); +} + static FILE* OpenEncodedFile(const char* filename) { const char *paths[] = { "encodings/%s", From 481ae5b11d72d56d43eed809d37ddafc45cf609f Mon Sep 17 00:00:00 2001 From: Sean Leather Date: Fri, 9 Oct 2015 14:29:30 +0200 Subject: [PATCH 151/189] Highlight main features in bold Might help some people see things better when skimming. --- readme.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/readme.md b/readme.md index 8682df1..fb270fb 100644 --- a/readme.md +++ b/readme.md @@ -31,15 +31,15 @@ Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights RapidJSON is a JSON parser and generator for C++. It was inspired by [RapidXml](http://rapidxml.sourceforge.net/). -* RapidJSON is small but complete. It supports both SAX and DOM style API. The SAX parser is only a half thousand lines of code. +* RapidJSON is **small** but **complete**. It supports both SAX and DOM style API. The SAX parser is only a half thousand lines of code. -* RapidJSON is fast. Its performance can be comparable to `strlen()`. It also optionally supports SSE2/SSE4.2 for acceleration. +* RapidJSON is **fast**. Its performance can be comparable to `strlen()`. It also optionally supports SSE2/SSE4.2 for acceleration. -* RapidJSON is self-contained. It does not depend on external libraries such as BOOST. It even does not depend on STL. +* RapidJSON is **self-contained** and **header-only**. It does not depend on external libraries such as BOOST. It even does not depend on STL. -* RapidJSON is memory friendly. Each JSON value occupies exactly 16/20 bytes for most 32/64-bit machines (excluding text string). By default it uses a fast memory allocator, and the parser allocates memory compactly during parsing. +* RapidJSON is **memory-friendly**. Each JSON value occupies exactly 16/20 bytes for most 32/64-bit machines (excluding text string). By default it uses a fast memory allocator, and the parser allocates memory compactly during parsing. -* RapidJSON is Unicode friendly. It supports UTF-8, UTF-16, UTF-32 (LE & BE), and their detection, validation and transcoding internally. For example, you can read a UTF-8 file and let RapidJSON transcode the JSON strings into UTF-16 in the DOM. It also supports surrogates and "\u0000" (null character). +* RapidJSON is **Unicode-friendly**. It supports UTF-8, UTF-16, UTF-32 (LE & BE), and their detection, validation and transcoding internally. For example, you can read a UTF-8 file and let RapidJSON transcode the JSON strings into UTF-16 in the DOM. It also supports surrogates and "\u0000" (null character). More features can be read [here](doc/features.md). From 1640ce613ca3bd3b9602c0f9e491c016137f5717 Mon Sep 17 00:00:00 2001 From: FrankHB Date: Sat, 10 Oct 2015 11:33:48 +0800 Subject: [PATCH 152/189] Fixed typo should be . --- include/rapidjson/internal/swap.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/rapidjson/internal/swap.h b/include/rapidjson/internal/swap.h index 41e7e20..39bc2e4 100644 --- a/include/rapidjson/internal/swap.h +++ b/include/rapidjson/internal/swap.h @@ -20,7 +20,7 @@ RAPIDJSON_NAMESPACE_BEGIN namespace internal { -//! Custom swap() to avoid dependency on C++ header +//! Custom swap() to avoid dependency on C++ header /*! \tparam T Type of the arguments to swap, should be instantiated with primitive C++ types only. \note This has the same semantics as std::swap(). */ From 5ce78b135d7fd76589973607b707dd7dbcab0792 Mon Sep 17 00:00:00 2001 From: Andrey Date: Sun, 11 Oct 2015 15:01:15 +0300 Subject: [PATCH 153/189] Introduce support of comments. --- include/rapidjson/reader.h | 48 ++++++++++++++++++------- test/unittest/readertest.cpp | 70 ++++++++++++++++++++++++++++++++++++ 2 files changed, 106 insertions(+), 12 deletions(-) diff --git a/include/rapidjson/reader.h b/include/rapidjson/reader.h index 9a17301..2603992 100644 --- a/include/rapidjson/reader.h +++ b/include/rapidjson/reader.h @@ -140,6 +140,7 @@ enum ParseFlag { kParseIterativeFlag = 4, //!< Iterative(constant complexity in terms of function call stack size) parsing. kParseStopWhenDoneFlag = 8, //!< After parsing a complete JSON root from stream, stop further processing the rest of stream. When this flag is used, parser will not generate kParseErrorDocumentRootNotSingular error. kParseFullPrecisionFlag = 16, //!< Parse number in full precision (but slower). + kParseCommentsFlag = 32, //!< Allow one-line (//) and multi-line (/**/) comments. kParseDefaultFlags = RAPIDJSON_PARSE_DEFAULT_FLAGS //!< Default parse flags. Can be customized by defining RAPIDJSON_PARSE_DEFAULT_FLAGS }; @@ -398,7 +399,7 @@ public: ClearStackOnExit scope(*this); - SkipWhitespace(is); + SkipWhitespaceAndComments(is); if (is.Peek() == '\0') { RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorDocumentEmpty, is.Tell()); @@ -409,7 +410,7 @@ public: RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); if (!(parseFlags & kParseStopWhenDoneFlag)) { - SkipWhitespace(is); + SkipWhitespaceAndComments(is); if (is.Peek() != '\0') { RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorDocumentRootNotSingular, is.Tell()); @@ -462,6 +463,29 @@ private: ClearStackOnExit& operator=(const ClearStackOnExit&); }; + template + void SkipWhitespaceAndComments(InputStream& is) { + SkipWhitespace(is); + + if (parseFlags & kParseCommentsFlag) { + while (is.Peek() == '/') { + is.Take(); + + if (is.Peek() == '*') { + is.Take(); + while (is.Take() != '*' || is.Take() != '/') { } + } else if (is.Peek() == '/') { + is.Take(); + while (is.Take() != '\n') { } + } else { + RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell()); + } + + SkipWhitespace(is); + } + } + } + // Parse object: { string : value, ... } template void ParseObject(InputStream& is, Handler& handler) { @@ -471,7 +495,7 @@ private: if (!handler.StartObject()) RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); - SkipWhitespace(is); + SkipWhitespaceAndComments(is); if (is.Peek() == '}') { is.Take(); @@ -487,22 +511,22 @@ private: ParseString(is, handler, true); RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; - SkipWhitespace(is); + SkipWhitespaceAndComments(is); if (is.Take() != ':') RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissColon, is.Tell()); - SkipWhitespace(is); + SkipWhitespaceAndComments(is); ParseValue(is, handler); RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; - SkipWhitespace(is); + SkipWhitespaceAndComments(is); ++memberCount; switch (is.Take()) { - case ',': SkipWhitespace(is); break; + case ',': SkipWhitespaceAndComments(is); break; case '}': if (!handler.EndObject(memberCount)) RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); @@ -521,7 +545,7 @@ private: if (!handler.StartArray()) RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); - SkipWhitespace(is); + SkipWhitespaceAndComments(is); if (is.Peek() == ']') { is.Take(); @@ -535,10 +559,10 @@ private: RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; ++elementCount; - SkipWhitespace(is); + SkipWhitespaceAndComments(is); switch (is.Take()) { - case ',': SkipWhitespace(is); break; + case ',': SkipWhitespaceAndComments(is); break; case ']': if (!handler.EndArray(elementCount)) RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); @@ -1404,7 +1428,7 @@ private: ClearStackOnExit scope(*this); IterativeParsingState state = IterativeParsingStartState; - SkipWhitespace(is); + SkipWhitespaceAndComments(is); while (is.Peek() != '\0') { Token t = Tokenize(is.Peek()); IterativeParsingState n = Predict(state, t); @@ -1421,7 +1445,7 @@ private: if ((parseFlags & kParseStopWhenDoneFlag) && state == IterativeParsingFinishState) break; - SkipWhitespace(is); + SkipWhitespaceAndComments(is); } // Handle the end of file. diff --git a/test/unittest/readertest.cpp b/test/unittest/readertest.cpp index 9106063..010a1a9 100644 --- a/test/unittest/readertest.cpp +++ b/test/unittest/readertest.cpp @@ -1349,6 +1349,76 @@ TEST(Reader, ParseTerminationByHandler) { TEST_TERMINATION(12, "{\"a\":[1]"); // non-empty array } +TEST(Reader, ParseComments) { + const char* json = + "// Here is a one-line comment.\n" + "{// And here's another one\n" + " /*And here's an in-line one.*/\"hello\" : \"world\"," + " \"t\" :/* And one with '*' symbol*/true ," + "/* A multiline comment\n" + " goes here*/" + " \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3]" + "}/*And the last one to be sure */"; + + StringStream s(json); + ParseObjectHandler h; + Reader reader; + EXPECT_TRUE(reader.Parse(s, h)); + EXPECT_EQ(20u, h.step_); +} + +TEST(Reader, ParseEmptyInlineComment) { + const char* json = "{/**/\"hello\" : \"world\", \"t\" : true, \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3] }"; + + StringStream s(json); + ParseObjectHandler h; + Reader reader; + EXPECT_TRUE(reader.Parse(s, h)); + EXPECT_EQ(20u, h.step_); +} + +TEST(Reader, ParseEmptyOnelineComment) { + const char* json = "{//\n\"hello\" : \"world\", \"t\" : true, \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3] }"; + + StringStream s(json); + ParseObjectHandler h; + Reader reader; + EXPECT_TRUE(reader.Parse(s, h)); + EXPECT_EQ(20u, h.step_); +} + +TEST(Reader, InlineCommentsAreDisabledByDefault) { + { + const char* json = "{/* Inline comment. */\"hello\" : \"world\", \"t\" : true, \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3] }"; + + StringStream s(json); + ParseObjectHandler h; + Reader reader; + EXPECT_FALSE(reader.Parse(s, h)); + } + + { + const char* json = + "{\"hello\" : /* Multiline comment starts here\n" + " continues here\n" + " and ends here */\"world\", \"t\" :true , \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3] }"; + + StringStream s(json); + ParseObjectHandler h; + Reader reader; + EXPECT_FALSE(reader.Parse(s, h)); + } +} + +TEST(Reader, OnelineCommentsAreDisabledByDefault) { + const char* json = "{// One-line comment\n\"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3] }"; + + StringStream s(json); + ParseObjectHandler h; + Reader reader; + EXPECT_FALSE(reader.Parse(s, h)); +} + #ifdef __GNUC__ RAPIDJSON_DIAG_POP #endif From f7960ac0e8740f81980e8cd11284cac54f9f44be Mon Sep 17 00:00:00 2001 From: Andrey Date: Tue, 13 Oct 2015 23:57:54 +0300 Subject: [PATCH 154/189] Comments parsing fixes. * Comments parsing function correctly handles EOF. * Since SkipWhitespaceAndComments can generate errors, its calls should be followed by RAPIDJSON_PARSE_ERROR_EARLY_RETURN macro. * Some tests to make the bug never appear again. --- include/rapidjson/reader.h | 35 +++++++++++++++++++++++++++++++---- test/unittest/readertest.cpp | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 4 deletions(-) diff --git a/include/rapidjson/reader.h b/include/rapidjson/reader.h index 2603992..fba9f19 100644 --- a/include/rapidjson/reader.h +++ b/include/rapidjson/reader.h @@ -400,6 +400,7 @@ public: ClearStackOnExit scope(*this); SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); if (is.Peek() == '\0') { RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorDocumentEmpty, is.Tell()); @@ -411,6 +412,7 @@ public: if (!(parseFlags & kParseStopWhenDoneFlag)) { SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); if (is.Peek() != '\0') { RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorDocumentRootNotSingular, is.Tell()); @@ -473,10 +475,21 @@ private: if (is.Peek() == '*') { is.Take(); - while (is.Take() != '*' || is.Take() != '/') { } + while (true) { + if (is.Peek() == '\0') + RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell()); + + if (is.Take() == '*') { + if (is.Peek() == '\0') + RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell()); + + if (is.Take() == '/') + break; + } + } } else if (is.Peek() == '/') { is.Take(); - while (is.Take() != '\n') { } + while (is.Peek() != '\0' && is.Take() != '\n') { } } else { RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell()); } @@ -496,6 +509,7 @@ private: RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; if (is.Peek() == '}') { is.Take(); @@ -512,21 +526,27 @@ private: RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; if (is.Take() != ':') RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissColon, is.Tell()); SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; ParseValue(is, handler); RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; ++memberCount; switch (is.Take()) { - case ',': SkipWhitespaceAndComments(is); break; + case ',': + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + break; case '}': if (!handler.EndObject(memberCount)) RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); @@ -546,6 +566,7 @@ private: RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; if (is.Peek() == ']') { is.Take(); @@ -560,9 +581,13 @@ private: ++elementCount; SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; switch (is.Take()) { - case ',': SkipWhitespaceAndComments(is); break; + case ',': + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + break; case ']': if (!handler.EndArray(elementCount)) RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); @@ -1429,6 +1454,7 @@ private: IterativeParsingState state = IterativeParsingStartState; SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); while (is.Peek() != '\0') { Token t = Tokenize(is.Peek()); IterativeParsingState n = Predict(state, t); @@ -1446,6 +1472,7 @@ private: break; SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); } // Handle the end of file. diff --git a/test/unittest/readertest.cpp b/test/unittest/readertest.cpp index 010a1a9..71d7113 100644 --- a/test/unittest/readertest.cpp +++ b/test/unittest/readertest.cpp @@ -1387,6 +1387,19 @@ TEST(Reader, ParseEmptyOnelineComment) { EXPECT_EQ(20u, h.step_); } +TEST(Reader, ParseMultipleCommentsInARow) { + const char* json = + "{/* first comment *//* second */\n" + "/* third */ /*fourth*/// last one\n" + "\"hello\" : \"world\", \"t\" : true, \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3] }"; + + StringStream s(json); + ParseObjectHandler h; + Reader reader; + EXPECT_TRUE(reader.Parse(s, h)); + EXPECT_EQ(20u, h.step_); +} + TEST(Reader, InlineCommentsAreDisabledByDefault) { { const char* json = "{/* Inline comment. */\"hello\" : \"world\", \"t\" : true, \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3] }"; @@ -1419,6 +1432,26 @@ TEST(Reader, OnelineCommentsAreDisabledByDefault) { EXPECT_FALSE(reader.Parse(s, h)); } +TEST(Reader, EofAfterOneLineComment) { + const char* json = "{\"hello\" : \"world\" // EOF is here -->\0 \n}"; + + StringStream s(json); + ParseObjectHandler h; + Reader reader; + EXPECT_FALSE(reader.Parse(s, h)); + EXPECT_EQ(kParseErrorObjectMissCommaOrCurlyBracket, reader.GetParseErrorCode()); +} + +TEST(Reader, IncompleteMultilineComment) { + const char* json = "{\"hello\" : \"world\" /* EOF is here -->\0 */}"; + + StringStream s(json); + ParseObjectHandler h; + Reader reader; + EXPECT_FALSE(reader.Parse(s, h)); + EXPECT_EQ(kParseErrorUnspecificSyntaxError, reader.GetParseErrorCode()); +} + #ifdef __GNUC__ RAPIDJSON_DIAG_POP #endif From 74a021346d3a97cd112fa528c09ff8823d36145c Mon Sep 17 00:00:00 2001 From: etiennebatise Date: Wed, 14 Oct 2015 15:46:26 +0200 Subject: [PATCH 155/189] Add break at default switch case statements fix issue #444 --- include/rapidjson/document.h | 1 + include/rapidjson/reader.h | 15 +++++++++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/include/rapidjson/document.h b/include/rapidjson/document.h index 516cb5e..8da86ab 100644 --- a/include/rapidjson/document.h +++ b/include/rapidjson/document.h @@ -2101,6 +2101,7 @@ GenericValue::GenericValue(const GenericValue(&rhs.data_); + break; } } diff --git a/include/rapidjson/reader.h b/include/rapidjson/reader.h index fba9f19..b56f3b5 100644 --- a/include/rapidjson/reader.h +++ b/include/rapidjson/reader.h @@ -551,7 +551,9 @@ private: if (!handler.EndObject(memberCount)) RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); return; - default: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell()); + default: + RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell()); + break; } } } @@ -592,7 +594,9 @@ private: if (!handler.EndArray(elementCount)) RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); return; - default: RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell()); + default: + RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell()); + break; } } } @@ -1041,7 +1045,10 @@ private: case '"': ParseString(is, handler); break; case '{': ParseObject(is, handler); break; case '[': ParseArray (is, handler); break; - default : ParseNumber(is, handler); + default : + ParseNumber(is, handler); + break; + } } @@ -1443,7 +1450,7 @@ private: case IterativeParsingMemberKeyState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissColon, is.Tell()); return; case IterativeParsingMemberValueState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell()); return; case IterativeParsingElementState: RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell()); return; - default: RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell()); + default: RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell()); return; } } From edd077f4bff042576736847f049cee9893930b7f Mon Sep 17 00:00:00 2001 From: etiennebatise Date: Thu, 15 Oct 2015 10:11:42 +0200 Subject: [PATCH 156/189] Add missing return statement, fix #448 --- include/rapidjson/encodedstream.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/rapidjson/encodedstream.h b/include/rapidjson/encodedstream.h index 7bc6ad3..13fcb1b 100644 --- a/include/rapidjson/encodedstream.h +++ b/include/rapidjson/encodedstream.h @@ -77,8 +77,8 @@ public: void Flush() { os_.Flush(); } // Not implemented - Ch Peek() const { RAPIDJSON_ASSERT(false); } - Ch Take() { RAPIDJSON_ASSERT(false); } + Ch Peek() const { 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; } @@ -227,8 +227,8 @@ public: void Flush() { os_->Flush(); } // Not implemented - Ch Peek() const { RAPIDJSON_ASSERT(false); } - Ch Take() { RAPIDJSON_ASSERT(false); } + Ch Peek() const { 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; } From 76d729e9c0246bc55c42e1e7ea28412772427633 Mon Sep 17 00:00:00 2001 From: Milo Yip Date: Thu, 22 Oct 2015 10:58:58 +0800 Subject: [PATCH 157/189] Add kParseCommentsFlag documentation --- doc/dom.md | 1 + doc/dom.zh-cn.md | 1 + doc/features.md | 2 ++ doc/features.zh-cn.md | 2 ++ 4 files changed, 6 insertions(+) diff --git a/doc/dom.md b/doc/dom.md index 24f1a39..cb25fc4 100644 --- a/doc/dom.md +++ b/doc/dom.md @@ -115,6 +115,7 @@ Parse flags | Meaning `kParseIterativeFlag` | Iterative(constant complexity in terms of function call stack size) parsing. `kParseStopWhenDoneFlag` | After parsing a complete JSON root from stream, stop further processing the rest of stream. When this flag is used, parser will not generate `kParseErrorDocumentRootNotSingular` error. Using this flag for parsing multiple JSONs in the same stream. `kParseFullPrecisionFlag` | Parse number in full precision (slower). If this flag is not set, the normal precision (faster) is used. Normal precision has maximum 3 [ULP](http://en.wikipedia.org/wiki/Unit_in_the_last_place) error. +`kParseCommentsFlag` | Allow one-line `// ...` and multi-line `/* ... */` comments (relaxed JSON syntax). By using a non-type template parameter, instead of a function parameter, C++ compiler can generate code which is optimized for specified combinations, improving speed, and reducing code size (if only using a single specialization). The downside is the flags needed to be determined in compile-time. diff --git a/doc/dom.zh-cn.md b/doc/dom.zh-cn.md index bb4eafb..2adf343 100644 --- a/doc/dom.zh-cn.md +++ b/doc/dom.zh-cn.md @@ -115,6 +115,7 @@ GenericDocument& GenericDocument::Parse(const Ch* str); `kParseIterativeFlag` | 迭代å¼ï¼ˆè°ƒç”¨å †æ ˆå¤§å°ä¸ºå¸¸æ•°å¤æ‚度)解æžã€‚ `kParseStopWhenDoneFlag` | 当从æµè§£æžäº†ä¸€ä¸ªå®Œæ•´çš„JSON根节点之åŽï¼Œåœæ­¢ç»§ç»­å¤„ç†ä½™ä¸‹çš„æµã€‚å½“ä½¿ç”¨äº†æ­¤æ ‡å¿—ï¼Œè§£æžå™¨ä¾¿ä¸ä¼šäº§ç”Ÿ`kParseErrorDocumentRootNotSingular`错误。å¯ä½¿ç”¨æœ¬æ ‡å¿—去解æžåŒä¸€ä¸ªæµé‡Œçš„多个JSON。 `kParseFullPrecisionFlag` | ä½¿ç”¨å®Œæ•´çš„ç²¾ç¡®åº¦åŽ»è§£æžæ•°å­—(较慢)。如ä¸è®¾ç½®æ­¤æ ‡èŠ‚ï¼Œåˆ™ä¼šä½¿ç”¨æ­£å¸¸çš„ç²¾ç¡®åº¦ï¼ˆè¾ƒå¿«ï¼‰ã€‚æ­£å¸¸ç²¾ç¡®åº¦ä¼šæœ‰æœ€å¤š3个[ULP](http://en.wikipedia.org/wiki/Unit_in_the_last_place)的误差。 +`kParseCommentsFlag` | 容许å•行 `// ...` åŠå¤šè¡Œ `/* ... */` 注释(放宽的JSON语法)。 由于使用了éžç±»åž‹æ¨¡æ¿å‚æ•°ï¼Œè€Œä¸æ˜¯å‡½æ•°å‚数,C++编译器能为个别组åˆç”Ÿæˆä»£ç ï¼Œä»¥æ”¹å–„性能åŠå‡å°‘代ç å°ºå¯¸ï¼ˆå½“åªç”¨å•ç§ç‰¹åŒ–)。缺点是需è¦åœ¨ç¼–译期决定标志。 diff --git a/doc/features.md b/doc/features.md index fc54cd0..6b529a7 100644 --- a/doc/features.md +++ b/doc/features.md @@ -23,6 +23,8 @@ * Support Unicode surrogate. * Support null character (`"\u0000"`) * For example, `["Hello\u0000World"]` can be parsed and handled gracefully. There is API for getting/setting lengths of string. +* Support optional relaxed syntax. + * Single line (`// ...`) and multiple line (`/* ... */`) comments. ## Unicode diff --git a/doc/features.zh-cn.md b/doc/features.zh-cn.md index 3a01a4b..85a7db1 100644 --- a/doc/features.zh-cn.md +++ b/doc/features.zh-cn.md @@ -23,6 +23,8 @@ * 支æŒUnicod代ç†å¯¹ï¼ˆsurrogate pair)。 * 支æŒç©ºå­—符(`"\u0000"`)。 * 例如,å¯ä»¥ä¼˜é›…地解æžåŠå¤„ç†`["Hello\u0000World"]`。å«è¯»å†™å­—符串长度的API。 +* æ”¯æŒæ”¾å®½çš„å¯é€‰è¯­æ³• + * å•行(`// ...`)åŠå¤šè¡Œï¼ˆ`/* ... */`) 注释。 ## Unicode From d5d17b96c2148f68a0c25c74ce63698d46928e3e Mon Sep 17 00:00:00 2001 From: Milo Yip Date: Tue, 27 Oct 2015 11:09:57 -0700 Subject: [PATCH 158/189] Chinese Translation of JSON Pointer guide and minor English version modification. --- doc/pointer.md | 6 +- doc/pointer.zh-cn.md | 234 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 237 insertions(+), 3 deletions(-) create mode 100644 doc/pointer.zh-cn.md diff --git a/doc/pointer.md b/doc/pointer.md index 1d75080..3927a12 100644 --- a/doc/pointer.md +++ b/doc/pointer.md @@ -148,7 +148,7 @@ When using `p.Get(root)` or `GetValueByPointer(root, p)`, `root` is a (const) `V The other functions have two groups of signature. One group uses `Document& document` as parameter, another one uses `Value& root`. The first group uses `document.GetAllocator()` for creating values. And the second group needs user to supply an allocator, like the functions in DOM. -All examples above do not require an allocator parameter, because the parameter is a `Document&`. But if you want to resolve a pointer to a subtree. You need to supply it as in the following example: +All examples above do not require an allocator parameter, because the first parameter is a `Document&`. But if you want to resolve a pointer to a subtree, you need to supply the allocator as in the following example: ~~~cpp class Person { @@ -179,7 +179,7 @@ private: # Error Handling {#ErrorHandling} -A `Pointer` parses a source string in its constructor. If there is parsing error, `Pointer::IsValid()` returns false. And you can use `Pointer::GetParseErrorCode()` and `GetParseErrorOffset()` to retrieve the error information. +A `Pointer` parses a source string in its constructor. If there is parsing error, `Pointer::IsValid()` returns `false`. And you can use `Pointer::GetParseErrorCode()` and `GetParseErrorOffset()` to retrieve the error information. Note that, all resolving functions assumes valid pointer. Resolving with an invalid pointer causes assertion failure. @@ -215,7 +215,7 @@ It can also stringify to URI fragment reprsentation by `StringifyUriFragment()`. # User-Supplied Tokens {#UserSuppliedTokens} -If a pointer will be resolved multiple times, it should be construct once, and then apply it to different DOMs or in different times. This reduce time and memory allocation for constructing `Pointer` multiple times. +If a pointer will be resolved multiple times, it should be constructed once, and then apply it to different DOMs or in different times. This reduce time and memory allocation for constructing `Pointer` multiple times. We can go one step further, to completely eliminate the parsing process and dynamic memory allocation, we can establish the token array directly: diff --git a/doc/pointer.zh-cn.md b/doc/pointer.zh-cn.md new file mode 100644 index 0000000..b6c446f --- /dev/null +++ b/doc/pointer.zh-cn.md @@ -0,0 +1,234 @@ +# Pointer + +## 状æ€: 实验性,应该会åˆè¿› v1.1 + +JSON Pointer 是一个标准化([RFC6901])的方å¼å޻选å–一个 JSON Document(DOM)中的值。这类似于 XML çš„ XPath。然而,JSON Pointer 简å•得多,而且æ¯ä¸ª JSON Pointer 仅指å‘å•个值。 + +使用 RapidJSON 的 JSON Pointer 实现能简化一些 DOM çš„æ“作。 + +[TOC] + +# JSON Pointer {#JsonPointer} + +一个 JSON Pointer 由一串(零至多个)token 所组æˆï¼Œæ¯ä¸ª token 都有 `/` å‰ç¼€ã€‚æ¯ä¸ª token å¯ä»¥æ˜¯ä¸€ä¸ªå­—符串或数字。例如,给定一个 JSON: +~~~javascript +{ + "foo" : ["bar", "baz"], + "pi" : 3.1416 +} +~~~ + +以下的 JSON Pointer è§£æžä¸ºï¼š + +1. `"/foo"` → `[ "bar", "baz" ]` +2. `"/foo/0"` → `"bar"` +3. `"/foo/1"` → `"baz"` +4. `"/pi"` → `3.1416` + +è¦æ³¨æ„,一个空 JSON Pointer `""` (零个token)解æžä¸ºæ•´ä¸ª JSON。 + +# 基本使用方法 {#BasicUsage} + +以下的代ç èŒƒä¾‹ä¸è§£è‡ªæ˜Žã€‚ + +~~~cpp +#include "rapidjson/pointer.h" + +// ... +Document d; + +// 使用 Set() 创建 DOM +Pointer("/project").Set(d, "RapidJSON"); +Pointer("/stars").Set(d, 10); + +// { "project" : "RapidJSON", "stars" : 10 } + +// 使用 Get() 访问 DOM。若该值ä¸å­˜åœ¨åˆ™è¿”回 nullptr。 +if (Value* stars = Pointer("/stars").Get(d)) + stars->SetInt(stars->GetInt() + 1); + +// { "project" : "RapidJSON", "stars" : 11 } + +// Set() å’Œ Create() 自动生æˆçˆ¶å€¼ï¼ˆå¦‚果它们ä¸å­˜åœ¨ï¼‰ã€‚ +Pointer("/a/b/0").Create(d); + +// { "project" : "RapidJSON", "stars" : 11, "a" : { "b" : [ null ] } } + +// GetWithDefault() 返回引用。若该值ä¸å­˜åœ¨åˆ™ä¼šæ·±æ‹·è´ç¼ºçœå€¼ã€‚ +Value& hello = Pointer("/hello").GetWithDefault(d, "world"); + +// { "project" : "RapidJSON", "stars" : 11, "a" : { "b" : [ null ] }, "hello" : "world" } + +// Swap() å’Œ Set() 相似 +Value x("C++"); +Pointer("/hello").Swap(d, x); + +// { "project" : "RapidJSON", "stars" : 11, "a" : { "b" : [ null ] }, "hello" : "C++" } +// x å˜æˆ "world" + +// 删去一个æˆå‘˜æˆ–元素,若值存在返回 true +bool success = Pointer("/a").Erase(d); +assert(success); + +// { "project" : "RapidJSON", "stars" : 10 } +~~~ + +# 辅助函数 {#HelperFunctions} + +由于é¢å‘对象的调用习惯å¯èƒ½ä¸ç¬¦ç›´è§‰ï¼ŒRapidJSON 也æä¾›äº†ä¸€äº›è¾…助函数,它们把æˆå‘˜å‡½æ•°åŒ…装æˆè‡ªç”±å‡½æ•°ã€‚ + +以下的例å­ä¸Žä¸Šé¢ä¾‹å­æ‰€åšçš„事情完全相åŒã€‚ + +~~~cpp +Document d; + +SetValueByPointer(d, "/project", "RapidJSON"); +SetValueByPointer(d, "/stars", 10); + +if (Value* stars = GetValueByPointer(d, "/stars")) + stars->SetInt(stars->GetInt() + 1); + +CreateValueByPointer(d, "/a/b/0"); + +Value& hello = GetValueByPointerWithDefault(d, "/hello", "world"); + +Value x("C++"); +SwapValueByPointer(d, "/hello", x); + +bool success = EraseValueByPointer(d, "/a"); +assert(success); +~~~ + +以下对比 3 ç§è°ƒç”¨æ–¹å¼ï¼š + +1. `Pointer(source).(root, ...)` +2. `ValueByPointer(root, Pointer(source), ...)` +3. `ValueByPointer(root, source, ...)` + +# è§£æž Pointer {#ResolvingPointer} + +`Pointer::Get()` 或 `GetValueByPointer()` 函数并ä¸ä¿®æ”¹ DOM。若那些 token ä¸èƒ½åŒ¹é… DOM 里的值,这些函数便返回 `nullptr`。使用者å¯åˆ©ç”¨è¿™ä¸ªæ–¹æ³•æ¥æ£€æŸ¥ä¸€ä¸ªå€¼æ˜¯å¦å­˜åœ¨ã€‚ + +注æ„,数值 token å¯è¡¨ç¤ºæ•°ç»„索引或æˆå‘˜å字。解æžè¿‡ç¨‹ä¸­ä¼šæŒ‰å€¼çš„类型æ¥åŒ¹é…。 + +~~~javascript +{ + "0" : 123, + "1" : [456] +} +~~~ + +1. `"/0"` → `123` +2. `"/1/0"` → `456` + +Token `"0"` 在第一个 pointer 中被当作æˆå‘˜å字。它在第二个 pointer ä¸­è¢«å½“ä½œæˆæ•°ç»„索引。 + +å…¶ä»–å‡½æ•°ä¼šæ”¹å˜ DOM,包括`Create()`ã€`GetWithDefault()`ã€`Set()`ã€`Swap()`。这些函数总是æˆåŠŸçš„ã€‚è‹¥ä¸€äº›çˆ¶å€¼ä¸å­˜åœ¨ï¼Œå°±ä¼šåˆ›å»ºå®ƒä»¬ã€‚若父值类型ä¸åŒ¹é… token,也会强行改å˜å…¶ç±»åž‹ã€‚改å˜ç±»åž‹ä¹Ÿæ„味ç€å®Œå…¨ç§»é™¤å…¶ DOM å­æ ‘的内容。 + +例如,把上é¢çš„ JSON 解译至 `d` 之åŽï¼Œ + +~~~cpp +SetValueByPointer(d, "1/a", 789); // { "0" : 123, "1" : { "a" : 789 } } +~~~ + +## è§£æžè´Ÿå· token + +å¦å¤–,[RFC6901] 定义了一个特殊 token `-` (å•个负å·ï¼‰ï¼Œç”¨äºŽè¡¨ç¤ºæ•°ç»„最åŽå…ƒç´ çš„下一个元素。 `Get()` åªä¼šæŠŠæ­¤ token 当作æˆå‘˜åå­— '"-"'ã€‚è€Œå…¶ä»–å‡½æ•°åˆ™ä¼šä»¥æ­¤è§£æžæ•°ç»„,等åŒäºŽå¯¹æ•°ç»„调用 `Value::PushBack()` 。 + +~~~cpp +Document d; +d.Parse("{\"foo\":[123]}"); +SetValueByPointer(d, "/foo/-", 456); // { "foo" : [123, 456] } +SetValueByPointer(d, "/-", 789); // { "foo" : [123, 456], "-" : 789 } +~~~ + +## è§£æž Document åŠ Value + +当使用 `p.Get(root)` 或 `GetValueByPointer(root, p)`,`root` 是一个(常数) `Value&`。这æ„味ç€ï¼Œå®ƒä¹Ÿå¯ä»¥æ˜¯ DOM é‡Œçš„ä¸€ä¸ªå­æ ‘。 + +其他函数有两组签å。一组使用 `Document& document`ã€€ä½œä¸ºå‚æ•°ï¼Œå¦ä¸€ç»„使用 `Value& root`。第一组使用 `document.GetAllocator()` 去创建值,而第二组则需è¦ä½¿ç”¨è€…æä¾›ä¸€ä¸ª allocatorï¼Œå¦‚åŒ DOM 里的函数。 + +以上例å­éƒ½ä¸éœ€è¦ allocator 傿•°ï¼Œå› ä¸ºå®ƒçš„ç¬¬ä¸€ä¸ªå‚æ•°æ˜¯ `Document&`。但如果你需è¦å¯¹ä¸€ä¸ªå­æ ‘进行解æžï¼Œå°±éœ€è¦å¦‚下é¢çš„例å­èˆ¬æä¾› allocator: + +~~~cpp +class Person { +public: + Person() { + document_ = new Document(); + // CreateValueByPointer() here no need allocator + SetLocation(CreateValueByPointer(*document_, "/residence"), ...); + SetLocation(CreateValueByPointer(*document_, "/office"), ...); + }; + +private: + void SetLocation(Value& location, const char* country, const char* addresses[2]) { + Value::Allocator& a = document_->GetAllocator(); + // SetValueByPointer() here need allocator + SetValueByPointer(location, "/country", country, a); + SetValueByPointer(location, "/address/0", address[0], a); + SetValueByPointer(location, "/address/1", address[1], a); + } + + // ... + + Document* document_; +}; +~~~ + +`Erase()` 或 `EraseValueByPointer()` ä¸éœ€è¦ allocator。而且它们æˆåŠŸåˆ é™¤å€¼ä¹‹åŽä¼šè¿”回 `true`。 + +# é”™è¯¯å¤„ç† {#ErrorHandling} + +`Pointer` 在其建构函数里会解译æºå­—符串。若有解æžé”™è¯¯ï¼Œ`Pointer::IsValid()` 返回 `false`。你å¯ä½¿ç”¨ `Pointer::GetParseErrorCode()` å’Œ `GetParseErrorOffset()` 去获å–错信æ¯ã€‚ + +è¦æ³¨æ„的是,所有解æžå‡½æ•°éƒ½å‡è®¾ pointer æ˜¯åˆæ³•çš„ã€‚å¯¹ä¸€ä¸ªéžæ³• pointer è§£æžä¼šåšæˆæ–­è¨€å¤±è´¥ã€‚ + +# URI ç‰‡æ®µè¡¨ç¤ºæ–¹å¼ {#URIFragment} + +除了我们一直在使用的字符串方å¼è¡¨ç¤º JSON pointer,[RFC6901]也定义了一个 JSON Pointer çš„ URI 片段(fragment)表示方å¼ã€‚URI 片段是定义于 [RFC3986] "Uniform Resource Identifier (URI): Generic Syntax"。 + +URI 片段的主è¦åˆ†åˆ«æ˜¯å¿…然以 `#` (pound signï¼‰å¼€å¤´ï¼Œè€Œä¸€äº›å­—ç¬¦ä¹Ÿä¼šä»¥ç™¾åˆ†æ¯”ç¼–ç æˆ UTF-8 åºåˆ—。例如,以下的表展示了ä¸åŒè¡¨ç¤ºæ³•下的 C/C++ 字符串常数。 + +å­—ç¬¦ä¸²è¡¨ç¤ºæ–¹å¼ | URI ç‰‡æ®µè¡¨ç¤ºæ–¹å¼ | Pointer Tokens (UTF-8) +----------------------|-----------------------------|------------------------ +`"/foo/0"` | `"#/foo/0"` | `{"foo", 0}` +`"/a~1b"` | `"#/a~1b"` | `{"a/b"}` +`"/m~0n"` | `"#/m~0n"` | `{"m~n"}` +`"/ "` | `"#/%20"` | `{" "}` +`"/\0"` | `"#/%00"` | `{"\0"}` +`"/€"` | `"#/%E2%82%AC"` | `{"€"}` + +RapidJSON å®Œå…¨æ”¯æŒ URI 片段表示方å¼ã€‚它在解译时会自动检测 `#` å·ã€‚ + +# 字符串化 + +你也å¯ä»¥æŠŠä¸€ä¸ª `Pointer` 字符串化,储存于字符串或其他输出æµã€‚例如: + +~~~ +Pointer p(...); +StringBuffer sb; +p.Stringify(sb); +std::cout << sb.GetString() << std::endl; +~~~ + +使用 `StringifyUriFragment()` å¯ä»¥æŠŠ pointer 字符串化为 URI 片段表示法。 + +# 使用者æä¾›çš„ tokens {#UserSuppliedTokens} + +若一个 pointer 会用于多次解æžï¼Œå®ƒåº”该åªè¢«åˆ›å»ºä¸€æ¬¡ï¼Œç„¶åŽå†æ–½äºŽä¸åŒçš„ DOM ,或在ä¸åŒæ—¶é—´åšè§£æžã€‚这样å¯ä»¥é¿å…多次创键 `Pointer`ï¼ŒèŠ‚çœæ—¶é—´å’Œå†…存分é…。 + +我们甚至å¯ä»¥å†æ›´è¿›ä¸€æ­¥ï¼Œå®Œå…¨æ¶ˆåŽ»è§£æžè¿‡ç¨‹åŠåЍæ€å†…存分é…。我们å¯ä»¥ç›´æŽ¥ç”Ÿæˆ token 数组: + +~~~cpp +#define NAME(s) { s, sizeof(s) / sizeof(s[0]) - 1, kPointerInvalidIndex } +#define INDEX(i) { #i, sizeof(#i) - 1, i } + +static const Pointer::Token kTokens[] = { NAME("foo"), INDEX(123) }; +static const Pointer p(kTokens, sizeof(kTokens) / sizeof(kTokens[0])); +// Equivalent to static const Pointer p("/foo/123"); +~~~ + +è¿™ç§å𿳕å¯èƒ½é€‚åˆå†…å­˜å—é™çš„系统。 + +[RFC3986]: https://tools.ietf.org/html/rfc3986 +[RFC6901]: https://tools.ietf.org/html/rfc6901 From 5512ec30f17bf771a442815c21d5e21cdbc6138b Mon Sep 17 00:00:00 2001 From: Milo Yip Date: Tue, 27 Oct 2015 13:36:36 -0700 Subject: [PATCH 159/189] Add Chinese pointer guide to doxygen --- doc/Doxyfile.zh-cn.in | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/doc/Doxyfile.zh-cn.in b/doc/Doxyfile.zh-cn.in index 2f94553..ad73462 100644 --- a/doc/Doxyfile.zh-cn.in +++ b/doc/Doxyfile.zh-cn.in @@ -764,18 +764,19 @@ WARN_LOGFILE = # spaces. # Note: If this tag is empty the current directory is searched. -INPUT = ./readme.zh-cn.md \ - ./include/rapidjson/rapidjson.h \ - ./include/ \ - ./doc/features.zh-cn.md \ - ./doc/tutorial.zh-cn.md \ - ./doc/stream.zh-cn.md \ - ./doc/encoding.zh-cn.md \ - ./doc/dom.zh-cn.md \ - ./doc/sax.zh-cn.md \ - ./doc/performance.zh-cn.md \ - ./doc/internals.md \ - ./doc/faq.zh-cn.md +INPUT = readme.zh-cn.md \ + include/rapidjson/rapidjson.h \ + include/ \ + doc/features.zh-cn.md \ + doc/tutorial.zh-cn.md \ + doc/pointer.md \ + doc/stream.zh-cn.md \ + doc/encoding.zh-cn.md \ + doc/dom.zh-cn.md \ + doc/sax.zh-cn.md \ + doc/performance.zh-cn.md \ + doc/internals.md \ + doc/faq.zh-cn.md # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses From e602aab7f4f00bdf25f9fc681af059b2a1ad3600 Mon Sep 17 00:00:00 2001 From: Milo Yip Date: Tue, 27 Oct 2015 14:34:35 -0700 Subject: [PATCH 160/189] Fix language for pointer --- doc/Doxyfile.zh-cn.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/Doxyfile.zh-cn.in b/doc/Doxyfile.zh-cn.in index ad73462..873022a 100644 --- a/doc/Doxyfile.zh-cn.in +++ b/doc/Doxyfile.zh-cn.in @@ -769,7 +769,7 @@ INPUT = readme.zh-cn.md \ include/ \ doc/features.zh-cn.md \ doc/tutorial.zh-cn.md \ - doc/pointer.md \ + doc/pointer.zh-cn.md \ doc/stream.zh-cn.md \ doc/encoding.zh-cn.md \ doc/dom.zh-cn.md \ From 82329825c3485cf4dd7778047543a784256d9baf Mon Sep 17 00:00:00 2001 From: Milo Yip Date: Wed, 28 Oct 2015 15:57:13 -0700 Subject: [PATCH 161/189] Fixes full-width spaces --- doc/pointer.zh-cn.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/pointer.zh-cn.md b/doc/pointer.zh-cn.md index b6c446f..b340deb 100644 --- a/doc/pointer.zh-cn.md +++ b/doc/pointer.zh-cn.md @@ -4,7 +4,7 @@ JSON Pointer 是一个标准化([RFC6901])的方å¼å޻选å–一个 JSON Document(DOM)中的值。这类似于 XML çš„ XPath。然而,JSON Pointer 简å•得多,而且æ¯ä¸ª JSON Pointer 仅指å‘å•个值。 -使用 RapidJSON 的 JSON Pointer 实现能简化一些 DOM çš„æ“作。 +使用 RapidJSON çš„ JSON Pointer 实现能简化一些 DOM çš„æ“作。 [TOC] @@ -146,7 +146,7 @@ SetValueByPointer(d, "/-", 789); // { "foo" : [123, 456], "-" : 789 } 当使用 `p.Get(root)` 或 `GetValueByPointer(root, p)`,`root` 是一个(常数) `Value&`。这æ„味ç€ï¼Œå®ƒä¹Ÿå¯ä»¥æ˜¯ DOM é‡Œçš„ä¸€ä¸ªå­æ ‘。 -其他函数有两组签å。一组使用 `Document& document`ã€€ä½œä¸ºå‚æ•°ï¼Œå¦ä¸€ç»„使用 `Value& root`。第一组使用 `document.GetAllocator()` 去创建值,而第二组则需è¦ä½¿ç”¨è€…æä¾›ä¸€ä¸ª allocatorï¼Œå¦‚åŒ DOM 里的函数。 +其他函数有两组签å。一组使用 `Document& document` ä½œä¸ºå‚æ•°ï¼Œå¦ä¸€ç»„使用 `Value& root`。第一组使用 `document.GetAllocator()` 去创建值,而第二组则需è¦ä½¿ç”¨è€…æä¾›ä¸€ä¸ª allocatorï¼Œå¦‚åŒ DOM 里的函数。 以上例å­éƒ½ä¸éœ€è¦ allocator 傿•°ï¼Œå› ä¸ºå®ƒçš„ç¬¬ä¸€ä¸ªå‚æ•°æ˜¯ `Document&`。但如果你需è¦å¯¹ä¸€ä¸ªå­æ ‘进行解æžï¼Œå°±éœ€è¦å¦‚下é¢çš„例å­èˆ¬æä¾› allocator: From c6cb74bff8967fcff0f85684d1a56a83ce1e8c1d Mon Sep 17 00:00:00 2001 From: stunney Date: Thu, 29 Oct 2015 11:57:56 -0400 Subject: [PATCH 162/189] Adding coapp definition To create a nupkg, call CoApp's Write-NuGetPackage .\rapidjson.autopkg -defines:MYVERSION=1.0.2 (or whatever version you want to call it) --- .gitignore | 1 + rapidjson.autopkg | 73 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 rapidjson.autopkg diff --git a/.gitignore b/.gitignore index 95acb0c..d97a316 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,4 @@ Testing install_manifest.txt Doxyfile DartConfiguration.tcl +*.nupkg diff --git a/rapidjson.autopkg b/rapidjson.autopkg new file mode 100644 index 0000000..50307cf --- /dev/null +++ b/rapidjson.autopkg @@ -0,0 +1,73 @@ +nuget { + nuspec { + id = rapidjson; + version : ${MYVERSION}; + title: "rapidjson"; + authors: {"https://github.com/miloyip/rapidjson/releases/tag/v1.0.2"}; + owners: {"@lsantos (github)"}; + licenseUrl: "http://www.opensource.org/licenses/mit-license.php"; + projectUrl: "https://github.com/miloyip/rapidjson/"; + iconUrl: "https://cdn1.iconfinder.com/data/icons/fatcow/32x32/json.png"; + requireLicenseAcceptance:false; + summary: @"A fast JSON parser/generator for C++ with both SAX/DOM style API"; + + // if you need to span several lines you can prefix a string with an @ symbol (exactly like c# does). + description: @"Rapidjson is an attempt to create the fastest JSON parser and generator. + + - Small but complete. Supports both SAX and DOM style API. SAX parser only a few hundred lines of code. + - Fast. In the order of magnitude of strlen(). Optionally supports SSE2/SSE4.2 for acceleration. + - Self-contained. Minimal dependency on standard libraries. No BOOST, not even STL. + - Compact. Each JSON value is 16 or 20 bytes for 32 or 64-bit machines respectively (excluding text string storage). With the custom memory allocator, parser allocates memory compactly during parsing. + - Full RFC4627 compliance. Supports UTF-8, UTF-16 and UTF-32. + - Support both in-situ parsing (directly decode strings into the source JSON text) and non-destructive parsing (decode strings into new buffers). + - Parse number to int/unsigned/int64_t/uint64_t/double depending on input + - Support custom memory allocation. Also, the default memory pool allocator can also be supplied with a user buffer (such as a buffer allocated on user's heap or - programme stack) to minimize allocation. + + As the name implies, rapidjson is inspired by rapidxml."; + + releaseNotes: @" +Added + Add Value::XXXMember(...) overloads for std::string (#335) + +Fixed + Include rapidjson.h for all internal/error headers. + Parsing some numbers incorrectly in full-precision mode (kFullPrecisionParseFlag) (#342) + Fix alignment of 64bit platforms (#328) + Fix MemoryPoolAllocator::Clear() to clear user-buffer (0691502) + +Changed + CMakeLists for include as a thirdparty in projects (#334, #337) + Change Document::ParseStream() to use stack allocator for Reader (ffbe386)"; + + copyright: "Copyright 2015"; + tags: { native, coapp, JSON, nativepackage }; + language: en-US; + }; + + dependencies { + packages : { + //TODO: Add dependecies here in [pkg.name]/[version] form per newline + //zlib/[1.2.8], + }; + } + + // the files that go into the content folders + files { + #defines { + SDK_ROOT = .\; + } + + // grab all the files in the include folder + // the folder that contains all the .h files will + // automatically get added to the Includes path. + nestedinclude += { + #destination = ${d_include}rapidjson; + "${SDK_ROOT}include\rapidjson\**\*.h" + }; + }; + + targets { + // We're trying to be standard about these sorts of thing. (Will help with config.h later :D) + //Defines += HAS_EQCORE; + }; +} \ No newline at end of file From d6912d07cd89c02fb59ed315586cae6fbb403c21 Mon Sep 17 00:00:00 2001 From: stunney Date: Thu, 29 Oct 2015 13:53:42 -0400 Subject: [PATCH 163/189] Updating LicenseURL based on @miloyip 's suggestion https://github.com/miloyip/rapidjson/pull/460#issuecomment-152232015 --- rapidjson.autopkg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rapidjson.autopkg b/rapidjson.autopkg index 50307cf..0e5cd32 100644 --- a/rapidjson.autopkg +++ b/rapidjson.autopkg @@ -5,7 +5,7 @@ nuget { title: "rapidjson"; authors: {"https://github.com/miloyip/rapidjson/releases/tag/v1.0.2"}; owners: {"@lsantos (github)"}; - licenseUrl: "http://www.opensource.org/licenses/mit-license.php"; + licenseUrl: "https://github.com/miloyip/rapidjson/blob/master/license.txt"; projectUrl: "https://github.com/miloyip/rapidjson/"; iconUrl: "https://cdn1.iconfinder.com/data/icons/fatcow/32x32/json.png"; requireLicenseAcceptance:false; From dceb7bed940ad14979c97d34fcc1e03a384acb9e Mon Sep 17 00:00:00 2001 From: stunney Date: Thu, 29 Oct 2015 14:02:12 -0400 Subject: [PATCH 164/189] Usage comment Adding usage comment at the top of the file for knowledge sharing --- rapidjson.autopkg | 2 ++ 1 file changed, 2 insertions(+) diff --git a/rapidjson.autopkg b/rapidjson.autopkg index 0e5cd32..d91aaef 100644 --- a/rapidjson.autopkg +++ b/rapidjson.autopkg @@ -1,4 +1,6 @@ nuget { + //Usage: Write-NuGetPackage rapidjson.autopkg -defines:MYVERSION=1.0.2 + //Be sure you are running Powershell 3.0 and have the CoApp powershell extensions installed properly. nuspec { id = rapidjson; version : ${MYVERSION}; From c8d298bc9eb68c281c98914df08fecd191947938 Mon Sep 17 00:00:00 2001 From: "Philipp A. Hartmann" Date: Mon, 16 Nov 2015 21:32:09 +0100 Subject: [PATCH 165/189] documenttest.cpp: EXPECT_THROW when checking empty allocator (closes #469) In the MoveConstructor/MoveAssignment tests, a check for a `NULL` allocator return has been used to check for the correct moved-from state of a Document. After the merge of #426, the GetAllocator call fails with an assertion, if the allocator of a GenericDocument is NULL. Check for the throw, instead of NULL in the move-related tests. Tested with GCC 4.9 on Linux with C++11 enabled. Reported-by: @woldendans --- test/unittest/documenttest.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/unittest/documenttest.cpp b/test/unittest/documenttest.cpp index 83325a7..0d84194 100644 --- a/test/unittest/documenttest.cpp +++ b/test/unittest/documenttest.cpp @@ -381,7 +381,7 @@ TYPED_TEST(DocumentMove, MoveConstructor) { EXPECT_TRUE(a.IsNull()); EXPECT_TRUE(b.IsArray()); EXPECT_EQ(3u, b.Size()); - EXPECT_EQ(&a.GetAllocator(), (void*)0); + EXPECT_THROW(a.GetAllocator(), AssertException); EXPECT_EQ(&b.GetAllocator(), &allocator); b.Parse("{\"Foo\": \"Bar\", \"Baz\": 42}"); @@ -394,7 +394,7 @@ TYPED_TEST(DocumentMove, MoveConstructor) { EXPECT_TRUE(b.IsNull()); EXPECT_TRUE(c.IsObject()); EXPECT_EQ(2u, c.MemberCount()); - EXPECT_EQ(&b.GetAllocator(), (void*)0); + EXPECT_THROW(b.GetAllocator(), AssertException); EXPECT_EQ(&c.GetAllocator(), &allocator); } @@ -475,7 +475,7 @@ TYPED_TEST(DocumentMove, MoveAssignment) { EXPECT_TRUE(a.IsNull()); EXPECT_TRUE(b.IsArray()); EXPECT_EQ(3u, b.Size()); - EXPECT_EQ(&a.GetAllocator(), (void*)0); + EXPECT_THROW(a.GetAllocator(), AssertException); EXPECT_EQ(&b.GetAllocator(), &allocator); b.Parse("{\"Foo\": \"Bar\", \"Baz\": 42}"); @@ -489,7 +489,7 @@ TYPED_TEST(DocumentMove, MoveAssignment) { EXPECT_TRUE(b.IsNull()); EXPECT_TRUE(c.IsObject()); EXPECT_EQ(2u, c.MemberCount()); - EXPECT_EQ(&b.GetAllocator(), (void*)0); + EXPECT_THROW(b.GetAllocator(), AssertException); EXPECT_EQ(&c.GetAllocator(), &allocator); } From 07672da09815eefba4db31c538dc6590672f21f6 Mon Sep 17 00:00:00 2001 From: Michael Haubenwallner Date: Wed, 25 Nov 2015 19:45:47 +0100 Subject: [PATCH 166/189] fix Document::Parse(const Ch*) for transcoding To allow for an UTF16-Document to Parse(UTF8), the Parse() argument has to be UTF8-compatible. --- include/rapidjson/document.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/rapidjson/document.h b/include/rapidjson/document.h index 8da86ab..1ee4fb6 100644 --- a/include/rapidjson/document.h +++ b/include/rapidjson/document.h @@ -1951,7 +1951,7 @@ public: \param str Read-only zero-terminated string to be parsed. */ template - GenericDocument& Parse(const Ch* str) { + GenericDocument& Parse(const typename SourceEncoding::Ch* str) { RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag)); GenericStringStream s(str); return ParseStream(s); From 98959e28207c154713e7691c35245460c4c87bfb Mon Sep 17 00:00:00 2001 From: "Philipp A. Hartmann" Date: Thu, 26 Nov 2015 22:30:59 +0100 Subject: [PATCH 167/189] GenericDocument: add implicit conversion to ParseResult To simplify the error handling, this commit adds an implicit conversion of GenericDocument to ParseResult, allowing code like (already in the documentation): ParseResult ok = doc.Parse(json); if (!ok) // ... --- include/rapidjson/document.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/include/rapidjson/document.h b/include/rapidjson/document.h index 1ee4fb6..b708a5a 100644 --- a/include/rapidjson/document.h +++ b/include/rapidjson/document.h @@ -1986,6 +1986,17 @@ public: //! Get the position of last parsing error in input, 0 otherwise. size_t GetErrorOffset() const { return parseResult_.Offset(); } + //! Implicit conversion to get the last parse result + /*! \return \ref ParseResult of the last parse operation + + \code + Document doc; + ParseResult ok = doc.Parse(json); + if (!ok) + printf( "JSON parse error: %s (%u)\n", GetParseError_En(ok.Code()), ok.Offset()); + \endcode + */ + operator ParseResult() const { return parseResult_; } //!@} //! Get the allocator of this document. From 9378001e355a1f470a5ff8a49a9834545d17c541 Mon Sep 17 00:00:00 2001 From: "Philipp A. Hartmann" Date: Thu, 26 Nov 2015 22:33:14 +0100 Subject: [PATCH 168/189] documenttest.cpp: check/use conversion from Document to ParseResult --- test/unittest/documenttest.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/test/unittest/documenttest.cpp b/test/unittest/documenttest.cpp index 0d84194..e4d1432 100644 --- a/test/unittest/documenttest.cpp +++ b/test/unittest/documenttest.cpp @@ -28,6 +28,7 @@ void ParseCheck(DocumentType& doc) { typedef typename DocumentType::ValueType ValueType; EXPECT_FALSE(doc.HasParseError()); + EXPECT_TRUE((ParseResult)doc); EXPECT_TRUE(doc.IsObject()); @@ -99,13 +100,18 @@ TEST(Document, UnchangedOnParseError) { Document doc; doc.SetArray().PushBack(0, doc.GetAllocator()); - doc.Parse("{]"); + ParseResult err = doc.Parse("{]"); EXPECT_TRUE(doc.HasParseError()); + EXPECT_EQ(err.Code(), doc.GetParseError()); + EXPECT_EQ(err.Offset(), doc.GetErrorOffset()); EXPECT_TRUE(doc.IsArray()); EXPECT_EQ(doc.Size(), 1u); - doc.Parse("{}"); + err = doc.Parse("{}"); EXPECT_FALSE(doc.HasParseError()); + EXPECT_FALSE(err.IsError()); + EXPECT_EQ(err.Code(), doc.GetParseError()); + EXPECT_EQ(err.Offset(), doc.GetErrorOffset()); EXPECT_TRUE(doc.IsObject()); EXPECT_EQ(doc.MemberCount(), 0u); } From fe89676a9e5a3fdc9b66b914a5076217adb523ff Mon Sep 17 00:00:00 2001 From: Wenhao Liu Date: Sat, 28 Nov 2015 22:40:43 +0800 Subject: [PATCH 169/189] fix a compatibility issue with doxygen --- doc/faq.md | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/doc/faq.md b/doc/faq.md index 8f441fe..cbcd4f1 100644 --- a/doc/faq.md +++ b/doc/faq.md @@ -106,59 +106,59 @@ Call one of the `SetXXX()` methods - they call destructor which deallocates DOM data: - ``` + ~~~~~~~~~~cpp Document d; ... d.SetObject(); // clear and minimize - ``` + ~~~~~~~~~~ Alternatively, use equivalent of the [C++ swap with temporary idiom](https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Clear-and-minimize): - ``` + ~~~~~~~~~~cpp Value(kObjectType).Swap(d); - ``` + ~~~~~~~~~~ or equivalent, but sightly longer to type: - ``` + ~~~~~~~~~~cpp d.Swap(Value(kObjectType).Move()); - ``` + ~~~~~~~~~~ 9. How to insert a document node into another document? Let's take the following two DOM trees represented as JSON documents: - ``` + ~~~~~~~~~~cpp Document person; person.Parse("{\"person\":{\"name\":{\"first\":\"Adam\",\"last\":\"Thomas\"}}}"); Document address; address.Parse("{\"address\":{\"city\":\"Moscow\",\"street\":\"Quiet\"}}"); - ``` + ~~~~~~~~~~ Let's assume we want to merge them in such way that the whole `address` document becomes a node of the `person`: - ``` + ~~~~~~~~~~js { "person": { "name": { "first": "Adam", "last": "Thomas" }, "address": { "city": "Moscow", "street": "Quiet" } } } - ``` + ~~~~~~~~~~ The most important requirement to take care of document and value life-cycle as well as consistent memory managent using the right allocator during the value transfer. Simple yet most efficient way to achieve that is to modify the `address` definition above to initialize it with allocator of the `person` document, then we just add the root nenber of the value: - ``` + ~~~~~~~~~~cpp Documnet address(person.GetAllocator()); ... person["person"].AddMember("address", address["address"], person.GetAllocator()); - ``` + ~~~~~~~~~~ Alternatively, if we don't want to explicitly refer to the root value of `address` by name, we can refer to it via iterator: - ``` + ~~~~~~~~~~cpp auto addressRoot = address.MemberBegin(); person["person"].AddMember(addressRoot->name, addressRoot->value, person.GetAllocator()); - ``` + ~~~~~~~~~~ Second way is to deep-clone the value from the address document: - ``` + ~~~~~~~~~~cpp Value addressValue = Value(address["address"], person.GetAllocator()); person["person"].AddMember("address", addressValue, person.GetAllocator()); - ``` + ~~~~~~~~~~ ## Document/Value (DOM) From 06f62e38f7e7fe1a24c90aa34f7e23887d89b634 Mon Sep 17 00:00:00 2001 From: Wenhao Liu Date: Sun, 29 Nov 2015 00:12:29 +0800 Subject: [PATCH 170/189] fix typos and dead links, sync faq.zh-cn.md --- doc/faq.md | 2 +- doc/faq.zh-cn.md | 65 +++++++++++++++++++++++++++++++++++++++++-- doc/sax.zh-cn.md | 12 ++++---- doc/tutorial.zh-cn.md | 6 ++-- 4 files changed, 72 insertions(+), 13 deletions(-) diff --git a/doc/faq.md b/doc/faq.md index cbcd4f1..1b0541c 100644 --- a/doc/faq.md +++ b/doc/faq.md @@ -142,7 +142,7 @@ The most important requirement to take care of document and value life-cycle as well as consistent memory managent using the right allocator during the value transfer. - Simple yet most efficient way to achieve that is to modify the `address` definition above to initialize it with allocator of the `person` document, then we just add the root nenber of the value: + Simple yet most efficient way to achieve that is to modify the `address` definition above to initialize it with allocator of the `person` document, then we just add the root member of the value: ~~~~~~~~~~cpp Documnet address(person.GetAllocator()); ... diff --git a/doc/faq.zh-cn.md b/doc/faq.zh-cn.md index c6e7557..7127283 100644 --- a/doc/faq.zh-cn.md +++ b/doc/faq.zh-cn.md @@ -28,7 +28,7 @@ 6. 怎样安装RapidJSON? - è§[安装一节](readme.zh-cn.md)。 + è§[安装一节](../readme.zh-cn.md#安装)。 7. RapidJSON能å¦è¿è¡ŒäºŽæˆ‘的平å°ï¼Ÿ @@ -52,7 +52,7 @@ 12. 有没有其他替代å“? - 有许多替代å“。例如nativejson-benchmark](https://github.com/miloyip/nativejson-benchmark)列出了一些开æºçš„C/C++ JSON库。[json.org](http://www.json.org/)也有一个列表。 + 有许多替代å“。例如[nativejson-benchmark](https://github.com/miloyip/nativejson-benchmark)列出了一些开æºçš„C/C++ JSON库。[json.org](http://www.json.org/)也有一个列表。 ## JSON @@ -98,10 +98,69 @@ 错误信æ¯å­˜å‚¨åœ¨`ParseResult`,它包å«é”™è¯¯ä»£å·åŠå移值(从JSON开始至错误处的字符数目)。å¯ä»¥æŠŠé”™è¯¯ä»£å·ç¿»è¯‘为人类å¯è¯»çš„错误讯æ¯ã€‚ -7. 为å¯ä¸åªä½¿ç”¨`double`去表示JSON number? +7. 为何ä¸åªä½¿ç”¨`double`去表示JSON number? 一些应用需è¦ä½¿ç”¨64使— å·ï¼æœ‰å·æ•´æ•°ã€‚这些整数ä¸èƒ½æ— æŸåœ°è½¬æ¢æˆ`double`。因此解æžå™¨ä¼šæ£€æµ‹ä¸€ä¸ªJSON number是å¦èƒ½è½¬æ¢è‡³å„ç§æ•´æ•°ç±»åž‹åŠ`double`。 +8. 如何清空并最å°åŒ–`document`或`value`的容é‡ï¼Ÿ + + 调用 `SetXXX()` 方法 - è¿™äº›æ–¹æ³•ä¼šè°ƒç”¨æžæž„函数,并é‡å»ºç©ºçš„Object或Array: + + ~~~~~~~~~~cpp + Document d; + ... + d.SetObject(); // clear and minimize + ~~~~~~~~~~ + + å¦å¤–,也å¯ä»¥å‚考在 [C++ swap with temporary idiom](https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Clear-and-minimize)中的一ç§ç­‰ä»·çš„æ–¹æ³•: + ~~~~~~~~~~cpp + Value(kObjectType).Swap(d); + ~~~~~~~~~~ + 或者,使用这个ç¨å¾®é•¿ä¸€ç‚¹çš„代ç ä¹Ÿèƒ½å®ŒæˆåŒæ ·çš„事情: + ~~~~~~~~~~cpp + d.Swap(Value(kObjectType).Move()); + ~~~~~~~~~~ + +9. 如何将一个`document`节点æ’入到å¦ä¸€ä¸ª`document`中? + + 比如有以下两个document(DOM): + ~~~~~~~~~~cpp + Document person; + person.Parse("{\"person\":{\"name\":{\"first\":\"Adam\",\"last\":\"Thomas\"}}}"); + + Document address; + address.Parse("{\"address\":{\"city\":\"Moscow\",\"street\":\"Quiet\"}}"); + ~~~~~~~~~~ + å‡è®¾æˆ‘们希望将整个 `address` æ’入到`person`中,作为其的一个å­èŠ‚ç‚¹: + ~~~~~~~~~~js + { "person": { + "name": { "first": "Adam", "last": "Thomas" }, + "address": { "city": "Moscow", "street": "Quiet" } + } + } + ~~~~~~~~~~ + + 在æ’å…¥èŠ‚ç‚¹çš„è¿‡ç¨‹ä¸­éœ€è¦æ³¨æ„`document`å’Œ`value`的生命周期并且正确地使用allocator进行内存分é…和管ç†ã€‚ + + ä¸€ä¸ªç®€å•æœ‰æ•ˆçš„æ–¹æ³•就是修改上述`address`å˜é‡çš„定义,让其使用`person`çš„allocatoråˆå§‹åŒ–,然åŽå°†å…¶æ·»åŠ åˆ°æ ¹èŠ‚ç‚¹ã€‚ + + ~~~~~~~~~~cpp + Documnet address(person.GetAllocator()); + ... + person["person"].AddMember("address", address["address"], person.GetAllocator()); + ~~~~~~~~~~ + å½“ç„¶ï¼Œå¦‚æžœä½ ä¸æƒ³é€šè¿‡æ˜¾å¼åœ°å†™å‡º`address`çš„keyæ¥å¾—到其值,å¯ä»¥ä½¿ç”¨è¿­ä»£å™¨æ¥å®žçް: + ~~~~~~~~~~cpp + auto addressRoot = address.MemberBegin(); + person["person"].AddMember(addressRoot->name, addressRoot->value, person.GetAllocator()); + ~~~~~~~~~~ + + 此外,还å¯ä»¥é€šè¿‡æ·±æ‹·è´address documentæ¥å®žçް: + ~~~~~~~~~~cpp + Value addressValue = Value(address["address"], person.GetAllocator()); + person["person"].AddMember("address", addressValue, person.GetAllocator()); + ~~~~~~~~~~ + ## Document/Value (DOM) 1. 什么是转移语æ„?为什么? diff --git a/doc/sax.zh-cn.md b/doc/sax.zh-cn.md index cad5a58..f8dc7b9 100644 --- a/doc/sax.zh-cn.md +++ b/doc/sax.zh-cn.md @@ -175,7 +175,7 @@ bool Parse(InputStream& is, Handler& handler); # Writer {#Writer} -`Reader`把JSON转æ¢ï¼ˆè§£æžï¼‰æˆä¸ºäº‹ä»¶ã€‚`Writer`完全åšç›¸åçš„äº‹æƒ…ã€‚å®ƒæŠŠäº‹ä»¶è½¬æ¢æˆJSON。 +`Reader`把JSON转æ¢ï¼ˆè§£æžï¼‰æˆä¸ºäº‹ä»¶ã€‚`Writer`åšå®Œå…¨ç›¸åçš„äº‹æƒ…ã€‚å®ƒæŠŠäº‹ä»¶è½¬æ¢æˆJSON。 `Writer`是éžå¸¸å®¹æ˜“使用的。若你的应用程åºåªéœ€æŠŠä¸€äº›æ•°æ®è½¬æ¢æˆJSON,å¯èƒ½ç›´æŽ¥ä½¿ç”¨`Writer`,会比建立一个`Document`ç„¶åŽç”¨`Writer`æŠŠå®ƒè½¬æ¢æˆJSON更加方便。 @@ -265,7 +265,7 @@ public: ## PrettyWriter {#PrettyWriter} -`Writer`所输出的是没有空格字符的最紧凑JSON,适åˆç½‘络传输或储存,但就适åˆäººç±»é˜…读。 +`Writer`所输出的是没有空格字符的最紧凑JSON,适åˆç½‘络传输或储存,但ä¸é€‚åˆäººç±»é˜…读。 因此,RapidJSONæä¾›äº†ä¸€ä¸ª`PrettyWriter`ï¼Œå®ƒåœ¨è¾“å‡ºä¸­åŠ å…¥ç¼©è¿›åŠæ¢è¡Œã€‚ @@ -386,13 +386,13 @@ Error: Terminate parsing due to Handler error. at offset 59 near '} }...' ~~~~~~~~~~ -第一个JSON(`json1`)被æˆåŠŸåœ°è§£æžè‡³`MessageMap`。由于`MessageMap`是一个`std::map`ï¼Œåˆ—å°æ¬¡åºæŒ‰é”®å€¼æŽ’åºã€‚此次åºä¸ŽJSON中的次åºä¸åŒã€‚ +第一个JSON(`json1`)被æˆåŠŸåœ°è§£æžè‡³`MessageMap`。由于`MessageMap`是一个`std::map`ï¼Œæ‰“å°æ¬¡åºæŒ‰é”®å€¼æŽ’åºã€‚此次åºä¸ŽJSON中的次åºä¸åŒã€‚ -在第二个JSON(`json2`)中,`foo`的值是一个空object。由于它是一个object,`MessageHandler::StartObject()`会被调用。然而,在`state_ = kExpectValue`的情况下,该函数会返回`false`,并令到解æžè¿‡ç¨‹ç»ˆæ­¢ã€‚é”™è¯¯ä»£ç æ˜¯`kParseErrorTermination`。 +在第二个JSON(`json2`)中,`foo`的值是一个空object。由于它是一个object,`MessageHandler::StartObject()`会被调用。然而,在`state_ = kExpectValue`的情况下,该函数会返回`false`,并导致解æžè¿‡ç¨‹ç»ˆæ­¢ã€‚é”™è¯¯ä»£ç æ˜¯`kParseErrorTermination`。 ## 过滤JSON {#Filtering} -如å‰é¢æåŠè¿‡ï¼Œ`Writer`å¯å¤„ç†`Reader`å‘出的事件。`condense`例å­ç®€å•地设置`Writer`作为一个`Reader`的处ç†å™¨ï¼Œå› æ­¤å®ƒèƒ½ç§»é™¤JSON中的所有空白字符。`pretty`例å­ä½¿ç”¨åŒæ ·çš„å…³ç³»ï¼Œåªæ˜¯ä»¥`PrettyWriter`å–代`Writer`。因此`pretty`èƒ½å¤Ÿé‡æ–°æ ¼å¼åŒ–JSONï¼ŒåŠ å…¥ç¼©è¿›åŠæ¢è¡Œã€‚ +如å‰é¢æåŠè¿‡ï¼Œ`Writer`å¯å¤„ç†`Reader`å‘出的事件。`example/condense/condense.cpp`例å­ç®€å•地设置`Writer`作为一个`Reader`的处ç†å™¨ï¼Œå› æ­¤å®ƒèƒ½ç§»é™¤JSON中的所有空白字符。`example/pretty/pretty.cpp`例å­ä½¿ç”¨åŒæ ·çš„å…³ç³»ï¼Œåªæ˜¯ä»¥`PrettyWriter`å–代`Writer`。因此`pretty`èƒ½å¤Ÿé‡æ–°æ ¼å¼åŒ–JSONï¼ŒåŠ å…¥ç¼©è¿›åŠæ¢è¡Œã€‚ 实际上,我们å¯ä»¥ä½¿ç”¨SAX风格API去加入(多个)中间层去过滤JSON的内容。例如`capitalize`例å­å¯ä»¥æŠŠæ‰€æœ‰JSON string改为大写。 @@ -472,5 +472,5 @@ int main(int, char*[]) { ["HELLO\nWORLD"] ~~~~~~~~~~ -我们还å¯ä»¥å¼€å‘æ›´å¤æ‚的过滤器。然而,由于SAX风格API在æŸä¸€æ—¶é—´ç‚¹åªèƒ½æä¾›å•一事件的信æ¯ï¼Œä½¿ç”¨è€…需è¦è‡ªè¡Œè®°å½•一些上下文信æ¯ï¼ˆä¾‹å¦‚从根节点起的路径ã€å‚¨å­˜å…¶ä»–ç›¸å…³å€¼ï¼‰ã€‚å¯¹äº›ä¸€äº›å¤„ç†æƒ…况,用DOM会比SAX更容易实现。 +我们还å¯ä»¥å¼€å‘æ›´å¤æ‚的过滤器。然而,由于SAX风格API在æŸä¸€æ—¶é—´ç‚¹åªèƒ½æä¾›å•一事件的信æ¯ï¼Œä½¿ç”¨è€…需è¦è‡ªè¡Œè®°å½•一些上下文信æ¯ï¼ˆä¾‹å¦‚从根节点起的路径ã€å‚¨å­˜å…¶ä»–ç›¸å…³å€¼ï¼‰ã€‚å¯¹äºŽå¤„ç†æŸäº›æƒ…况,用DOM会比SAX更容易实现。 diff --git a/doc/tutorial.zh-cn.md b/doc/tutorial.zh-cn.md index 3ecaec8..37808b0 100644 --- a/doc/tutorial.zh-cn.md +++ b/doc/tutorial.zh-cn.md @@ -2,7 +2,7 @@ 本教程简介文件对象模型(Document Object Model, DOM)API。 -如[用法一览](readme.zh-cn.md)中所示,å¯ä»¥è§£æžä¸€ä¸ªJSON至DOM,然åŽå°±å¯ä»¥è½»æ¾æŸ¥è¯¢åŠä¿®æ”¹DOM,并最终转æ¢å›žJSON。 +如[用法一览](../readme.zh-cn.md#用法一览)中所示,å¯ä»¥è§£æžä¸€ä¸ªJSON至DOM,然åŽå°±å¯ä»¥è½»æ¾æŸ¥è¯¢åŠä¿®æ”¹DOM,并最终转æ¢å›žJSON。 [TOC] @@ -123,7 +123,7 @@ a[3] = 4 ä½ å¯ä»¥ç”¨æ•´æ•°å­—é¢é‡è®¿é—®å…ƒç´ ï¼Œå¦‚`a[0]`ã€`a[1]`ã€`a[2]`。 -Array与`std::vector`相似,除了使用索引,也å¯ä½¿ç”¨è¿­å¾…器æ¥è®¿é—®æ‰€æœ‰å…ƒç´ ã€‚ +Array与`std::vector`相似,除了使用索引,也å¯ä½¿ç”¨è¿­ä»£å™¨æ¥è®¿é—®æ‰€æœ‰å…ƒç´ ã€‚ ~~~~~~~~~~cpp for (Value::ConstValueIterator itr = a.Begin(); itr != a.End(); ++itr) printf("%d ", itr->GetInt()); @@ -461,7 +461,7 @@ contact.AddMember(key, val, document.GetAllocator()); * `bool RemoveMember(const Ch* name)`ï¼šä½¿ç”¨é”®åæ¥ç§»é™¤æˆå‘˜ï¼ˆçº¿æ€§æ—¶é—´å¤æ‚度)。 * `bool RemoveMember(const Value& name)`:除了`name`是一个Value,和上一行相åŒã€‚ -* `MemberIterator RemoveMember(MemberIterator)`:使用迭待器移除æˆå‘˜ï¼ˆ_常数_æ—¶é—´å¤æ‚度)。 +* `MemberIterator RemoveMember(MemberIterator)`:使用迭代器移除æˆå‘˜ï¼ˆ_常数_æ—¶é—´å¤æ‚度)。 * `MemberIterator EraseMember(MemberIterator)`ï¼šå’Œä¸Šè¡Œç›¸ä¼¼ä½†ç»´æŒæˆå‘˜æ¬¡åºï¼ˆçº¿æ€§æ—¶é—´å¤æ‚度)。 * `MemberIterator EraseMember(MemberIterator first, MemberIterator last)`:移除一个范围内的æˆå‘˜ï¼Œç»´æŒæ¬¡åºï¼ˆçº¿æ€§æ—¶é—´å¤æ‚度)。 From db0a03a43c9aa8d665b5a950e72b21f36eaff9c4 Mon Sep 17 00:00:00 2001 From: Milo Yip Date: Mon, 30 Nov 2015 17:22:06 +0800 Subject: [PATCH 171/189] Fix #483 by using the correct value type --- include/rapidjson/pointer.h | 6 +++--- test/unittest/pointertest.cpp | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/include/rapidjson/pointer.h b/include/rapidjson/pointer.h index 5d2aa8d..d873163 100644 --- a/include/rapidjson/pointer.h +++ b/include/rapidjson/pointer.h @@ -390,7 +390,7 @@ public: bool exist = true; for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) { if (v->IsArray() && t->name[0] == '-' && t->length == 1) { - v->PushBack(Value().Move(), allocator); + v->PushBack(ValueType().Move(), allocator); v = &((*v)[v->Size() - 1]); exist = false; } @@ -408,7 +408,7 @@ public: if (t->index >= v->Size()) { v->Reserve(t->index + 1, allocator); while (t->index >= v->Size()) - v->PushBack(Value().Move(), allocator); + v->PushBack(ValueType().Move(), allocator); exist = false; } v = &((*v)[t->index]); @@ -416,7 +416,7 @@ public: else { typename ValueType::MemberIterator m = v->FindMember(GenericStringRef(t->name, t->length)); if (m == v->MemberEnd()) { - v->AddMember(Value(t->name, t->length, allocator).Move(), Value().Move(), allocator); + v->AddMember(ValueType(t->name, t->length, allocator).Move(), ValueType().Move(), allocator); v = &(--v->MemberEnd())->value; // Assumes AddMember() appends at the end exist = false; } diff --git a/test/unittest/pointertest.cpp b/test/unittest/pointertest.cpp index 7ec3f72..9ad6b45 100644 --- a/test/unittest/pointertest.cpp +++ b/test/unittest/pointertest.cpp @@ -1456,3 +1456,38 @@ TEST(Pointer, Ambiguity) { EXPECT_EQ(456, Pointer("/0/1").Get(d)->GetInt()); } } + +// https://github.com/miloyip/rapidjson/issues/483 +namespace myjson { + +class MyAllocator +{ +public: + static const bool kNeedFree = true; + void * Malloc(size_t _size) { return malloc(_size); } + void * Realloc(void *_org_p, size_t _org_size, size_t _new_size) { (void)_org_size; return realloc(_org_p, _new_size); } + static void Free(void *_p) { return free(_p); } +}; + +typedef rapidjson::GenericDocument< + rapidjson::UTF8<>, + rapidjson::MemoryPoolAllocator< MyAllocator >, + MyAllocator + > Document; + +typedef rapidjson::GenericPointer< + ::myjson::Document::ValueType, + MyAllocator + > Pointer; + +typedef ::myjson::Document::ValueType Value; + +} + +TEST(Pointer, Issue483) { + std::string mystr, path; + myjson::Document document; + myjson::Value value(rapidjson::kStringType); + value.SetString(mystr.c_str(), mystr.length(), document.GetAllocator()); + myjson::Pointer(path.c_str()).Set(document, value, document.GetAllocator()); +} From 5b268e65080e9595ffc136363d3ecd51f27a5de5 Mon Sep 17 00:00:00 2001 From: Michael Haubenwallner Date: Fri, 27 Nov 2015 16:46:42 +0100 Subject: [PATCH 172/189] use with C++ linkage on Windows ARM Instead of commenting that we should, just do include with C++ linkage when compiling for Windows on ARM. Actually, omitting the C linkage really should be enough here. --- include/rapidjson/msinttypes/stdint.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/rapidjson/msinttypes/stdint.h b/include/rapidjson/msinttypes/stdint.h index a26fff4..3d4477b 100644 --- a/include/rapidjson/msinttypes/stdint.h +++ b/include/rapidjson/msinttypes/stdint.h @@ -89,14 +89,14 @@ #include // For Visual Studio 6 in C++ mode and for many Visual Studio versions when -// compiling for ARM we should wrap include with 'extern "C++" {}' -// or compiler give many errors like this: +// compiling for ARM we have to wrap include with 'extern "C++" {}' +// or compiler would give many errors like this: // error C2733: second C linkage of overloaded function 'wmemchr' not allowed -#ifdef __cplusplus +#if defined(__cplusplus) && !defined(_M_ARM) extern "C" { #endif # include -#ifdef __cplusplus +#if defined(__cplusplus) && !defined(_M_ARM) } #endif From e7063978617e0145f8a58716d02737ba194379af Mon Sep 17 00:00:00 2001 From: Michael Haubenwallner Date: Mon, 30 Nov 2015 17:38:58 +0100 Subject: [PATCH 173/189] detect little endian for Microsoft ARM targets When _MSC_VER and _M_ARM is defined, this is some Windows ARM target using little-endian byte order. --- include/rapidjson/rapidjson.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/rapidjson/rapidjson.h b/include/rapidjson/rapidjson.h index 4c4d983..7034f48 100644 --- a/include/rapidjson/rapidjson.h +++ b/include/rapidjson/rapidjson.h @@ -211,6 +211,8 @@ # define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN # elif defined(__i386__) || defined(__alpha__) || defined(__ia64) || defined(__ia64__) || defined(_M_IX86) || defined(_M_IA64) || defined(_M_ALPHA) || defined(__amd64) || defined(__amd64__) || defined(_M_AMD64) || defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || defined(__bfin__) # define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN +# elif defined(_MSC_VER) && defined(_M_ARM) +# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN # elif defined(RAPIDJSON_DOXYGEN_RUNNING) # define RAPIDJSON_ENDIAN # else From 8b265fe4b6ab7a9910e7a0b342caa8c5b61cdeeb Mon Sep 17 00:00:00 2001 From: miloyip Date: Sun, 6 Dec 2015 11:38:53 +0800 Subject: [PATCH 174/189] Fixes #489 --- test/unittest/pointertest.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/unittest/pointertest.cpp b/test/unittest/pointertest.cpp index 9ad6b45..d36b59d 100644 --- a/test/unittest/pointertest.cpp +++ b/test/unittest/pointertest.cpp @@ -306,7 +306,7 @@ TEST(Pointer, Parse_URIFragment) { GenericPointer > > p(L"#/%C2%A2"); EXPECT_TRUE(p.IsValid()); EXPECT_EQ(1u, p.GetTokenCount()); - EXPECT_EQ(0x00A2, p.GetTokens()[0].name[0]); + EXPECT_EQ((UTF16<>::Ch)0x00A2, p.GetTokens()[0].name[0]); EXPECT_EQ(1u, p.GetTokens()[0].length); } @@ -315,7 +315,7 @@ TEST(Pointer, Parse_URIFragment) { GenericPointer > > p(L"#/%E2%82%AC"); EXPECT_TRUE(p.IsValid()); EXPECT_EQ(1u, p.GetTokenCount()); - EXPECT_EQ(0x20AC, p.GetTokens()[0].name[0]); + EXPECT_EQ((UTF16<>::Ch)0x20AC, p.GetTokens()[0].name[0]); EXPECT_EQ(1u, p.GetTokens()[0].length); } From a1c4f325cab87c0fa2ce5b2737750adbc905b279 Mon Sep 17 00:00:00 2001 From: Milo Yip Date: Sun, 6 Dec 2015 13:44:47 +0800 Subject: [PATCH 175/189] Temporarily remove git clone single-branch https://github.com/travis-ci/travis-ci/issues/5225 --- travis-doxygen.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/travis-doxygen.sh b/travis-doxygen.sh index 1023108..e9eb6b9 100755 --- a/travis-doxygen.sh +++ b/travis-doxygen.sh @@ -66,7 +66,7 @@ gh_pages_prepare() [ ! -d "html" ] || \ abort "Doxygen target directory already exists." git --version - git clone --single-branch -b gh-pages "${GITHUB_CLONE}" html + git clone -b gh-pages "${GITHUB_CLONE}" html cd html # setup git config (with defaults) git config user.name "${GIT_NAME-travis}" From 7899a3c125f9654968de77cdc431f0eb384429c0 Mon Sep 17 00:00:00 2001 From: "Philipp A. Hartmann" Date: Wed, 16 Dec 2015 09:40:39 +0100 Subject: [PATCH 176/189] encodings.h: fix typo in preprocessor condition (closes #494) --- include/rapidjson/encodings.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/rapidjson/encodings.h b/include/rapidjson/encodings.h index bc3cd81..7b740d3 100644 --- a/include/rapidjson/encodings.h +++ b/include/rapidjson/encodings.h @@ -618,7 +618,7 @@ struct Transcoder { RAPIDJSON_NAMESPACE_END -#if defined(__GNUC__) || defined(_MSV_VER) +#if defined(__GNUC__) || defined(_MSC_VER) RAPIDJSON_DIAG_POP #endif From 74c8dcfd5791c4f11e6d52fdc15047b0622dd8af Mon Sep 17 00:00:00 2001 From: Milo Yip Date: Fri, 18 Dec 2015 18:34:04 +0800 Subject: [PATCH 177/189] Fix clang -Weverything --- example/CMakeLists.txt | 2 +- example/capitalize/capitalize.cpp | 4 +- example/condense/condense.cpp | 2 +- example/messagereader/messagereader.cpp | 9 +- example/pretty/pretty.cpp | 2 +- example/prettyauto/prettyauto.cpp | 2 +- example/serialize/serialize.cpp | 8 +- example/tutorial/tutorial.cpp | 8 +- include/rapidjson/allocators.h | 2 +- include/rapidjson/document.h | 102 +++++++++--------- include/rapidjson/encodedstream.h | 15 ++- include/rapidjson/encodings.h | 134 +++++++++++++----------- include/rapidjson/error/en.h | 10 +- include/rapidjson/error/error.h | 17 ++- include/rapidjson/filereadstream.h | 13 ++- include/rapidjson/internal/biginteger.h | 2 +- include/rapidjson/internal/diyfp.h | 10 ++ include/rapidjson/internal/ieee754.h | 2 +- include/rapidjson/internal/stack.h | 4 +- include/rapidjson/internal/strtod.h | 8 +- include/rapidjson/memorystream.h | 4 +- include/rapidjson/pointer.h | 42 +++++--- include/rapidjson/prettywriter.h | 2 +- include/rapidjson/rapidjson.h | 38 +++++++ include/rapidjson/reader.h | 63 +++++++---- include/rapidjson/writer.h | 37 ++++--- test/CMakeLists.txt | 2 +- test/unittest/CMakeLists.txt | 2 +- test/unittest/allocatorstest.cpp | 12 +-- test/unittest/documenttest.cpp | 72 ++++++------- test/unittest/encodedstreamtest.cpp | 19 ++-- test/unittest/encodingstest.cpp | 5 +- test/unittest/filestreamtest.cpp | 7 +- test/unittest/itoatest.cpp | 8 +- test/unittest/jsoncheckertest.cpp | 24 ++--- test/unittest/pointertest.cpp | 6 +- test/unittest/prettywritertest.cpp | 6 +- test/unittest/readertest.cpp | 37 ++++--- test/unittest/simdtest.cpp | 2 +- test/unittest/strtodtest.cpp | 6 +- test/unittest/unittest.cpp | 6 +- test/unittest/unittest.h | 24 ++++- test/unittest/valuetest.cpp | 66 ++++++------ 43 files changed, 504 insertions(+), 342 deletions(-) diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt index 8063d89..127f71e 100644 --- a/example/CMakeLists.txt +++ b/example/CMakeLists.txt @@ -20,7 +20,7 @@ include_directories("../include/") if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror -Wall -Wextra -Weffc++ -Wswitch-default") elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror -Wall -Wextra -Weffc++ -Wswitch-default") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror -Wall -Wextra -Weffc++ -Wswitch-default -Wfloat-equal -Wimplicit-fallthrough -Weverything") elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") add_definitions(-D_CRT_SECURE_NO_WARNINGS=1) endif() diff --git a/example/capitalize/capitalize.cpp b/example/capitalize/capitalize.cpp index a19ed50..adc32b5 100644 --- a/example/capitalize/capitalize.cpp +++ b/example/capitalize/capitalize.cpp @@ -27,7 +27,7 @@ struct CapitalizeFilter { bool String(const char* str, SizeType length, bool) { buffer_.clear(); for (SizeType i = 0; i < length; i++) - buffer_.push_back(std::toupper(str[i])); + buffer_.push_back(static_cast(std::toupper(str[i]))); return out_.String(&buffer_.front(), length, true); // true = output handler need to copy the string } bool StartObject() { return out_.StartObject(); } @@ -58,7 +58,7 @@ int main(int, char*[]) { // JSON reader parse from the input stream and let writer generate the output. CapitalizeFilter > filter(writer); if (!reader.Parse(is, filter)) { - fprintf(stderr, "\nError(%u): %s\n", (unsigned)reader.GetErrorOffset(), GetParseError_En(reader.GetParseErrorCode())); + fprintf(stderr, "\nError(%u): %s\n", static_cast(reader.GetErrorOffset()), GetParseError_En(reader.GetParseErrorCode())); return 1; } diff --git a/example/condense/condense.cpp b/example/condense/condense.cpp index d77f2c7..5c038d0 100644 --- a/example/condense/condense.cpp +++ b/example/condense/condense.cpp @@ -24,7 +24,7 @@ int main(int, char*[]) { // JSON reader parse from the input stream and let writer generate the output. if (!reader.Parse(is, writer)) { - fprintf(stderr, "\nError(%u): %s\n", (unsigned)reader.GetErrorOffset(), GetParseError_En(reader.GetParseErrorCode())); + fprintf(stderr, "\nError(%u): %s\n", static_cast(reader.GetErrorOffset()), GetParseError_En(reader.GetParseErrorCode())); return 1; } diff --git a/example/messagereader/messagereader.cpp b/example/messagereader/messagereader.cpp index 50255b3..d19292b 100644 --- a/example/messagereader/messagereader.cpp +++ b/example/messagereader/messagereader.cpp @@ -26,13 +26,16 @@ struct MessageHandler case kExpectObjectStart: state_ = kExpectNameOrObjectEnd; return true; - default: + case kExpectNameOrObjectEnd: + case kExpectValue: return false; } } bool String(const char* str, SizeType length, bool) { switch (state_) { + case kExpectObjectStart: + return false; case kExpectNameOrObjectEnd: name_ = string(str, length); state_ = kExpectValue; @@ -41,8 +44,6 @@ struct MessageHandler messages_.insert(MessageMap::value_type(name_, string(str, length))); state_ = kExpectNameOrObjectEnd; return true; - default: - return false; } } @@ -63,7 +64,7 @@ struct MessageHandler RAPIDJSON_DIAG_POP #endif -void ParseMessages(const char* json, MessageMap& messages) { +static void ParseMessages(const char* json, MessageMap& messages) { Reader reader; MessageHandler handler; StringStream ss(json); diff --git a/example/pretty/pretty.cpp b/example/pretty/pretty.cpp index 164e388..2185cfe 100644 --- a/example/pretty/pretty.cpp +++ b/example/pretty/pretty.cpp @@ -22,7 +22,7 @@ int main(int, char*[]) { // JSON reader parse from the input stream and let writer generate the output. if (!reader.Parse(is, writer)) { - fprintf(stderr, "\nError(%u): %s\n", (unsigned)reader.GetErrorOffset(), GetParseError_En(reader.GetParseErrorCode())); + fprintf(stderr, "\nError(%u): %s\n", static_cast(reader.GetErrorOffset()), GetParseError_En(reader.GetParseErrorCode())); return 1; } diff --git a/example/prettyauto/prettyauto.cpp b/example/prettyauto/prettyauto.cpp index 0d30968..700dc19 100644 --- a/example/prettyauto/prettyauto.cpp +++ b/example/prettyauto/prettyauto.cpp @@ -48,7 +48,7 @@ int main(int, char*[]) { // JSON reader parse from the input stream and let writer generate the output. //if (!reader.Parse(is, writer)) { if (!reader.Parse(eis, writer)) { // CHANGED - fprintf(stderr, "\nError(%u): %s\n", (unsigned)reader.GetErrorOffset(), GetParseError_En(reader.GetParseErrorCode())); + fprintf(stderr, "\nError(%u): %s\n", static_cast(reader.GetErrorOffset()), GetParseError_En(reader.GetParseErrorCode())); return 1; } diff --git a/example/serialize/serialize.cpp b/example/serialize/serialize.cpp index 7427939..6c5e5c2 100644 --- a/example/serialize/serialize.cpp +++ b/example/serialize/serialize.cpp @@ -18,10 +18,10 @@ protected: void Serialize(Writer& writer) const { // This base class just write out name-value pairs, without wrapping within an object. writer.String("name"); -#ifdef RAPIDJSON_HAS_STDSTRING +#if RAPIDJSON_HAS_STDSTRING writer.String(name_); #else - writer.String(name_.c_str(), (SizeType)name_.length()); // Supplying length of string is faster. + writer.String(name_.c_str(), static_cast(name_.length())); // Supplying length of string is faster. #endif writer.String("age"); writer.Uint(age_); @@ -44,10 +44,10 @@ public: writer.StartObject(); writer.String("school"); -#ifdef RAPIDJSON_HAS_STDSTRING +#if RAPIDJSON_HAS_STDSTRING writer.String(school_); #else - writer.String(school_.c_str(), (SizeType)school_.length()); + writer.String(school_.c_str(), static_cast(school_.length())); #endif writer.String("GPA"); diff --git a/example/tutorial/tutorial.cpp b/example/tutorial/tutorial.cpp index 206fdb9..354057a 100644 --- a/example/tutorial/tutorial.cpp +++ b/example/tutorial/tutorial.cpp @@ -121,17 +121,17 @@ int main(int, char*[]) { // This version of SetString() needs an allocator, which means it will allocate a new buffer and copy the the string into the buffer. Value author; { - char buffer[10]; - int len = sprintf(buffer, "%s %s", "Milo", "Yip"); // synthetic example of dynamically created string. + char buffer2[10]; + int len = sprintf(buffer2, "%s %s", "Milo", "Yip"); // synthetic example of dynamically created string. - author.SetString(buffer, static_cast(len), document.GetAllocator()); + author.SetString(buffer2, static_cast(len), document.GetAllocator()); // Shorter but slower version: // document["hello"].SetString(buffer, document.GetAllocator()); // Constructor version: // Value author(buffer, len, document.GetAllocator()); // Value author(buffer, document.GetAllocator()); - memset(buffer, 0, sizeof(buffer)); // For demonstration purpose. + memset(buffer2, 0, sizeof(buffer2)); // For demonstration purpose. } // Variable 'buffer' is unusable now but 'author' has already made a copy. document.AddMember("author", author, document.GetAllocator()); diff --git a/include/rapidjson/allocators.h b/include/rapidjson/allocators.h index 6be2776..05e3b0c 100644 --- a/include/rapidjson/allocators.h +++ b/include/rapidjson/allocators.h @@ -199,7 +199,7 @@ public: return originalPtr; // Simply expand it if it is the last allocation and there is sufficient space - if (originalPtr == (char *)(chunkHead_) + RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + chunkHead_->size - originalSize) { + if (originalPtr == reinterpret_cast(chunkHead_) + RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + chunkHead_->size - originalSize) { size_t increment = static_cast(newSize - originalSize); increment = RAPIDJSON_ALIGN(increment); if (chunkHead_->size + increment <= chunkHead_->capacity) { diff --git a/include/rapidjson/document.h b/include/rapidjson/document.h index b708a5a..8fde16c 100644 --- a/include/rapidjson/document.h +++ b/include/rapidjson/document.h @@ -25,36 +25,18 @@ #ifdef _MSC_VER RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant -#elif defined(__GNUC__) +#endif + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(padded) +#endif + +#ifdef __GNUC__ RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_OFF(effc++) #endif -/////////////////////////////////////////////////////////////////////////////// -// RAPIDJSON_HAS_STDSTRING - -#ifndef RAPIDJSON_HAS_STDSTRING -#ifdef RAPIDJSON_DOXYGEN_RUNNING -#define RAPIDJSON_HAS_STDSTRING 1 // force generation of documentation -#else -#define RAPIDJSON_HAS_STDSTRING 0 // no std::string support by default -#endif -/*! \def RAPIDJSON_HAS_STDSTRING - \ingroup RAPIDJSON_CONFIG - \brief Enable RapidJSON support for \c std::string - - By defining this preprocessor symbol to \c 1, several convenience functions for using - \ref rapidjson::GenericValue with \c std::string are enabled, especially - for construction and comparison. - - \hideinitializer -*/ -#endif // !defined(RAPIDJSON_HAS_STDSTRING) - -#if RAPIDJSON_HAS_STDSTRING -#include -#endif // RAPIDJSON_HAS_STDSTRING - #ifndef RAPIDJSON_NOMEMBERITERATORCLASS #include // std::iterator, std::random_access_iterator_tag #endif @@ -260,6 +242,7 @@ struct GenericStringRef { typedef CharType Ch; //!< character type of the string //! Create string reference from \c const character array +#ifndef __clang__ // -Wdocumentation /*! This constructor implicitly creates a constant string reference from a \c const character array. It has better performance than @@ -282,11 +265,13 @@ struct GenericStringRef { In such cases, the referenced string should be \b copied to the GenericValue instead. */ +#endif template GenericStringRef(const CharType (&str)[N]) RAPIDJSON_NOEXCEPT : s(str), length(N-1) {} //! Explicitly create string reference from \c const character pointer +#ifndef __clang__ // -Wdocumentation /*! This constructor can be used to \b explicitly create a reference to a constant string pointer. @@ -305,16 +290,19 @@ struct GenericStringRef { In such cases, the referenced string should be \b copied to the GenericValue instead. */ +#endif explicit GenericStringRef(const CharType* str) : s(str), length(internal::StrLen(str)){ RAPIDJSON_ASSERT(s != NULL); } //! Create constant string reference from pointer and length +#ifndef __clang__ // -Wdocumentation /*! \param str constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue \param len length of the string, excluding the trailing NULL terminator \post \ref s == str && \ref length == len \note Constant complexity. */ +#endif GenericStringRef(const CharType* str, SizeType len) : s(str), length(len) { RAPIDJSON_ASSERT(s != NULL); } @@ -654,7 +642,7 @@ public: */ template GenericValue& CopyFrom(const GenericValue& rhs, Allocator& allocator) { - RAPIDJSON_ASSERT((void*)this != (void const*)&rhs); + RAPIDJSON_ASSERT(static_cast(this) != static_cast(&rhs)); this->~GenericValue(); new (this) GenericValue(rhs, allocator); return *this; @@ -736,7 +724,9 @@ public: else return data_.n.u64 == rhs.data_.n.u64; - default: // kTrueType, kFalseType, kNullType + case kNullType: + case kFalseType: + case kTrueType: return true; } } @@ -864,8 +854,14 @@ public: return member->value; else { RAPIDJSON_ASSERT(false); // see above note - static GenericValue NullValue; - return NullValue; + + // This will generate -Wexit-time-destructors in clang + // static GenericValue NullValue; + // return NullValue; + + // Use static buffer and placement-new to prevent destruction + static char buffer[sizeof(GenericValue)]; + return *new (buffer) GenericValue(); } } template @@ -1235,7 +1231,7 @@ public: MemberIterator pos = MemberBegin() + (first - MemberBegin()); for (MemberIterator itr = pos; itr != last; ++itr) itr->~Member(); - std::memmove(&*pos, &*last, (MemberEnd() - last) * sizeof(Member)); + std::memmove(&*pos, &*last, static_cast(MemberEnd() - last) * sizeof(Member)); data_.o.size -= (last - first); return pos; } @@ -1328,7 +1324,7 @@ public: GenericValue& Reserve(SizeType newCapacity, Allocator &allocator) { RAPIDJSON_ASSERT(IsArray()); if (newCapacity > data_.a.capacity) { - data_.a.elements = (GenericValue*)allocator.Realloc(data_.a.elements, data_.a.capacity * sizeof(GenericValue), newCapacity * sizeof(GenericValue)); + data_.a.elements = static_cast(allocator.Realloc(data_.a.elements, data_.a.capacity * sizeof(GenericValue), newCapacity * sizeof(GenericValue))); data_.a.capacity = newCapacity; } return *this; @@ -1435,7 +1431,7 @@ public: ValueIterator pos = Begin() + (first - Begin()); for (ValueIterator itr = pos; itr != last; ++itr) itr->~GenericValue(); - std::memmove(pos, last, (End() - last) * sizeof(GenericValue)); + std::memmove(pos, last, static_cast(End() - last) * sizeof(GenericValue)); data_.a.size -= (last - first); return pos; } @@ -1455,8 +1451,8 @@ public: if ((flags_ & kDoubleFlag) != 0) return data_.n.d; // exact type, no conversion. if ((flags_ & kIntFlag) != 0) return data_.n.i.i; // int -> double if ((flags_ & kUintFlag) != 0) return data_.n.u.u; // unsigned -> double - if ((flags_ & kInt64Flag) != 0) return (double)data_.n.i64; // int64_t -> double (may lose precision) - RAPIDJSON_ASSERT((flags_ & kUint64Flag) != 0); return (double)data_.n.u64; // uint64_t -> double (may lose precision) + if ((flags_ & kInt64Flag) != 0) return static_cast(data_.n.i64); // int64_t -> double (may lose precision) + RAPIDJSON_ASSERT((flags_ & kUint64Flag) != 0); return static_cast(data_.n.u64); // uint64_t -> double (may lose precision) } GenericValue& SetInt(int i) { this->~GenericValue(); new (this) GenericValue(i); return *this; } @@ -1562,8 +1558,7 @@ public: case kStringType: return handler.String(GetString(), GetStringLength(), (flags_ & kCopyFlag) != 0); - default: - RAPIDJSON_ASSERT(GetType() == kNumberType); + case kNumberType: if (IsInt()) return handler.Int(data_.n.i.i); else if (IsUint()) return handler.Uint(data_.n.u.u); else if (IsInt64()) return handler.Int64(data_.n.i64); @@ -1628,9 +1623,9 @@ private: enum { MaxChars = sizeof(String) / sizeof(Ch), MaxSize = MaxChars - 1, LenPos = MaxSize }; Ch str[MaxChars]; - inline static bool Usable(SizeType len) { return (MaxSize >= len); } - inline void SetLength(SizeType len) { str[LenPos] = (Ch)(MaxSize - len); } - inline SizeType GetLength() const { return (SizeType)(MaxSize - str[LenPos]); } + inline static bool Usable(SizeType len) { return (MaxSize >= len); } + inline void SetLength(SizeType len) { str[LenPos] = static_cast(MaxSize - len); } + inline SizeType GetLength() const { return static_cast(MaxSize - str[LenPos]); } }; // at most as many bytes as "String" above => 12 bytes in 32-bit mode, 16 bytes in 64-bit mode // By using proper binary layout, retrieval of different integer types do not need conversions. @@ -1683,7 +1678,7 @@ private: void SetArrayRaw(GenericValue* values, SizeType count, Allocator& allocator) { flags_ = kArrayFlag; if (count) { - data_.a.elements = (GenericValue*)allocator.Malloc(count * sizeof(GenericValue)); + data_.a.elements = static_cast(allocator.Malloc(count * sizeof(GenericValue))); std::memcpy(data_.a.elements, values, count * sizeof(GenericValue)); } else @@ -1695,7 +1690,7 @@ private: void SetObjectRaw(Member* members, SizeType count, Allocator& allocator) { flags_ = kObjectFlag; if (count) { - data_.o.members = (Member*)allocator.Malloc(count * sizeof(Member)); + data_.o.members = static_cast(allocator.Malloc(count * sizeof(Member))); std::memcpy(data_.o.members, members, count * sizeof(Member)); } else @@ -1720,7 +1715,7 @@ private: } else { flags_ = kCopyStringFlag; data_.s.length = s.length; - str = (Ch *)allocator.Malloc((s.length + 1) * sizeof(Ch)); + str = static_cast(allocator.Malloc((s.length + 1) * sizeof(Ch))); data_.s.str = str; } std::memcpy(str, s, s.length * sizeof(Ch)); @@ -1847,7 +1842,7 @@ public: //! Exchange the contents of this document with those of another. /*! - \param other Another document. + \param rhs Another document. \note Constant complexity. \see GenericValue::Swap */ @@ -1987,6 +1982,7 @@ public: size_t GetErrorOffset() const { return parseResult_.Offset(); } //! Implicit conversion to get the last parse result +#ifndef __clang // -Wdocumentation /*! \return \ref ParseResult of the last parse operation \code @@ -1996,6 +1992,7 @@ public: printf( "JSON parse error: %s (%u)\n", GetParseError_En(ok.Code()), ok.Offset()); \endcode */ +#endif operator ParseResult() const { return parseResult_; } //!@} @@ -2046,7 +2043,7 @@ private: bool EndObject(SizeType memberCount) { typename ValueType::Member* members = stack_.template Pop(memberCount); - stack_.template Top()->SetObjectRaw(members, (SizeType)memberCount, GetAllocator()); + stack_.template Top()->SetObjectRaw(members, memberCount, GetAllocator()); return true; } @@ -2109,7 +2106,10 @@ GenericValue::GenericValue(const GenericValue(&rhs.data_); break; @@ -2118,7 +2118,15 @@ GenericValue::GenericValue(const GenericValue class EncodedOutputStream { @@ -142,7 +147,7 @@ private: // FF FE UTF-16LE // EF BB BF UTF-8 - const unsigned char* c = (const unsigned char *)is_->Peek4(); + const unsigned char* c = reinterpret_cast(is_->Peek4()); if (!c) return; @@ -193,7 +198,7 @@ private: //! Output stream wrapper with dynamically bound encoding and automatic encoding detection. /*! \tparam CharType Type of character for writing. - \tparam InputByteStream type of output byte stream to be wrapped. + \tparam OutputByteStream type of output byte stream to be wrapped. */ template class AutoUTFOutputStream { @@ -254,6 +259,10 @@ private: RAPIDJSON_NAMESPACE_END +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif + #ifdef __GNUC__ RAPIDJSON_DIAG_POP #endif diff --git a/include/rapidjson/encodings.h b/include/rapidjson/encodings.h index 7b740d3..f37f9e1 100644 --- a/include/rapidjson/encodings.h +++ b/include/rapidjson/encodings.h @@ -122,17 +122,17 @@ struct UTF8 { template static bool Decode(InputStream& is, unsigned* codepoint) { -#define COPY() c = is.Take(); *codepoint = (*codepoint << 6) | ((unsigned char)c & 0x3Fu) -#define TRANS(mask) result &= ((GetRange((unsigned char)c) & mask) != 0) +#define COPY() c = is.Take(); *codepoint = (*codepoint << 6) | (static_cast(c) & 0x3Fu) +#define TRANS(mask) result &= ((GetRange(static_cast(c)) & mask) != 0) #define TAIL() COPY(); TRANS(0x70) - Ch c = is.Take(); + typename InputStream::Ch c = is.Take(); if (!(c & 0x80)) { - *codepoint = (unsigned char)c; + *codepoint = static_cast(c); return true; } - unsigned char type = GetRange((unsigned char)c); - *codepoint = (0xFF >> type) & (unsigned char)c; + unsigned char type = GetRange(static_cast(c)); + *codepoint = (0xFF >> type) & static_cast(c); bool result = true; switch (type) { case 2: TAIL(); return result; @@ -152,7 +152,7 @@ struct UTF8 { template static bool Validate(InputStream& is, OutputStream& os) { #define COPY() os.Put(c = is.Take()) -#define TRANS(mask) result &= ((GetRange((unsigned char)c) & mask) != 0) +#define TRANS(mask) result &= ((GetRange(static_cast(c)) & mask) != 0) #define TAIL() COPY(); TRANS(0x70) Ch c; COPY(); @@ -160,7 +160,7 @@ struct UTF8 { return true; bool result = true; - switch (GetRange((unsigned char)c)) { + switch (GetRange(static_cast(c))) { case 2: TAIL(); return result; case 3: TAIL(); TAIL(); return result; case 4: COPY(); TRANS(0x50); TAIL(); return result; @@ -196,12 +196,12 @@ struct UTF8 { template static CharType TakeBOM(InputByteStream& is) { RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); - Ch c = Take(is); - if ((unsigned char)c != 0xEFu) return c; + typename InputByteStream::Ch c = Take(is); + if (static_cast(c) != 0xEFu) return c; c = is.Take(); - if ((unsigned char)c != 0xBBu) return c; + if (static_cast(c) != 0xBBu) return c; c = is.Take(); - if ((unsigned char)c != 0xBFu) return c; + if (static_cast(c) != 0xBFu) return c; c = is.Take(); return c; } @@ -209,13 +209,15 @@ struct UTF8 { template static Ch Take(InputByteStream& is) { RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); - return is.Take(); + return static_cast(is.Take()); } template static void PutBOM(OutputByteStream& os) { RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); - os.Put(0xEFu); os.Put(0xBBu); os.Put(0xBFu); + os.Put(static_cast(0xEFu)); + os.Put(static_cast(0xBBu)); + os.Put(static_cast(0xBFu)); } template @@ -262,15 +264,15 @@ struct UTF16 { template static bool Decode(InputStream& is, unsigned* codepoint) { RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 2); - Ch c = is.Take(); + typename InputStream::Ch c = is.Take(); if (c < 0xD800 || c > 0xDFFF) { - *codepoint = c; + *codepoint = static_cast(c); return true; } else if (c <= 0xDBFF) { - *codepoint = (c & 0x3FF) << 10; + *codepoint = (static_cast(c) & 0x3FF) << 10; c = is.Take(); - *codepoint |= (c & 0x3FF); + *codepoint |= (static_cast(c) & 0x3FF); *codepoint += 0x10000; return c >= 0xDC00 && c <= 0xDFFF; } @@ -281,8 +283,8 @@ struct UTF16 { static bool Validate(InputStream& is, OutputStream& os) { RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 2); RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2); - Ch c; - os.Put(c = is.Take()); + typename InputStream::Ch c; + os.Put(static_cast(c = is.Take())); if (c < 0xD800 || c > 0xDFFF) return true; else if (c <= 0xDBFF) { @@ -300,28 +302,29 @@ struct UTF16LE : UTF16 { static CharType TakeBOM(InputByteStream& is) { RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); CharType c = Take(is); - return (unsigned short)c == 0xFEFFu ? Take(is) : c; + return static_cast(c) == 0xFEFFu ? Take(is) : c; } template static CharType Take(InputByteStream& is) { RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); - CharType c = (unsigned char)is.Take(); - c |= (unsigned char)is.Take() << 8; - return c; + unsigned c = static_cast(is.Take()); + c |= static_cast(static_cast(is.Take())) << 8; + return static_cast(c); } template static void PutBOM(OutputByteStream& os) { RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); - os.Put(0xFFu); os.Put(0xFEu); + os.Put(static_cast(0xFFu)); + os.Put(static_cast(0xFEu)); } template static void Put(OutputByteStream& os, CharType c) { RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); - os.Put(c & 0xFFu); - os.Put((c >> 8) & 0xFFu); + os.Put(static_cast(static_cast(c) & 0xFFu)); + os.Put(static_cast((static_cast(c) >> 8) & 0xFFu)); } }; @@ -332,28 +335,29 @@ struct UTF16BE : UTF16 { static CharType TakeBOM(InputByteStream& is) { RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); CharType c = Take(is); - return (unsigned short)c == 0xFEFFu ? Take(is) : c; + return static_cast(c) == 0xFEFFu ? Take(is) : c; } template static CharType Take(InputByteStream& is) { RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); - CharType c = (unsigned char)is.Take() << 8; - c |= (unsigned char)is.Take(); - return c; + unsigned c = static_cast(static_cast(is.Take())) << 8; + c |= static_cast(is.Take()); + return static_cast(c); } template static void PutBOM(OutputByteStream& os) { RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); - os.Put(0xFEu); os.Put(0xFFu); + os.Put(static_cast(0xFEu)); + os.Put(static_cast(0xFFu)); } template static void Put(OutputByteStream& os, CharType c) { RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); - os.Put((c >> 8) & 0xFFu); - os.Put(c & 0xFFu); + os.Put(static_cast((static_cast(c) >> 8) & 0xFFu)); + os.Put(static_cast(static_cast(c) & 0xFFu)); } }; @@ -406,32 +410,35 @@ struct UTF32LE : UTF32 { static CharType TakeBOM(InputByteStream& is) { RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); CharType c = Take(is); - return (unsigned)c == 0x0000FEFFu ? Take(is) : c; + return static_cast(c) == 0x0000FEFFu ? Take(is) : c; } template static CharType Take(InputByteStream& is) { RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); - CharType c = (unsigned char)is.Take(); - c |= (unsigned char)is.Take() << 8; - c |= (unsigned char)is.Take() << 16; - c |= (unsigned char)is.Take() << 24; - return c; + unsigned c = static_cast(is.Take()); + c |= static_cast(static_cast(is.Take())) << 8; + c |= static_cast(static_cast(is.Take())) << 16; + c |= static_cast(static_cast(is.Take())) << 24; + return static_cast(c); } template static void PutBOM(OutputByteStream& os) { RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); - os.Put(0xFFu); os.Put(0xFEu); os.Put(0x00u); os.Put(0x00u); + os.Put(static_cast(0xFFu)); + os.Put(static_cast(0xFEu)); + os.Put(static_cast(0x00u)); + os.Put(static_cast(0x00u)); } template static void Put(OutputByteStream& os, CharType c) { RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); - os.Put(c & 0xFFu); - os.Put((c >> 8) & 0xFFu); - os.Put((c >> 16) & 0xFFu); - os.Put((c >> 24) & 0xFFu); + os.Put(static_cast(c & 0xFFu)); + os.Put(static_cast((c >> 8) & 0xFFu)); + os.Put(static_cast((c >> 16) & 0xFFu)); + os.Put(static_cast((c >> 24) & 0xFFu)); } }; @@ -442,32 +449,35 @@ struct UTF32BE : UTF32 { static CharType TakeBOM(InputByteStream& is) { RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); CharType c = Take(is); - return (unsigned)c == 0x0000FEFFu ? Take(is) : c; + return static_cast(c) == 0x0000FEFFu ? Take(is) : c; } template static CharType Take(InputByteStream& is) { RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); - CharType c = (unsigned char)is.Take() << 24; - c |= (unsigned char)is.Take() << 16; - c |= (unsigned char)is.Take() << 8; - c |= (unsigned char)is.Take(); - return c; + unsigned c = static_cast(static_cast(is.Take())) << 24; + c |= static_cast(static_cast(is.Take())) << 16; + c |= static_cast(static_cast(is.Take())) << 8; + c |= static_cast(static_cast(is.Take())); + return static_cast(c); } template static void PutBOM(OutputByteStream& os) { RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); - os.Put(0x00u); os.Put(0x00u); os.Put(0xFEu); os.Put(0xFFu); + os.Put(static_cast(0x00u)); + os.Put(static_cast(0x00u)); + os.Put(static_cast(0xFEu)); + os.Put(static_cast(0xFFu)); } template static void Put(OutputByteStream& os, CharType c) { RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); - os.Put((c >> 24) & 0xFFu); - os.Put((c >> 16) & 0xFFu); - os.Put((c >> 8) & 0xFFu); - os.Put(c & 0xFFu); + os.Put(static_cast((c >> 24) & 0xFFu)); + os.Put(static_cast((c >> 16) & 0xFFu)); + os.Put(static_cast((c >> 8) & 0xFFu)); + os.Put(static_cast(c & 0xFFu)); } }; @@ -493,29 +503,29 @@ struct ASCII { template static bool Decode(InputStream& is, unsigned* codepoint) { - unsigned char c = static_cast(is.Take()); + uint8_t c = static_cast(is.Take()); *codepoint = c; return c <= 0X7F; } template static bool Validate(InputStream& is, OutputStream& os) { - unsigned char c = is.Take(); - os.Put(c); + uint8_t c = static_cast(is.Take()); + os.Put(static_cast(c)); return c <= 0x7F; } template static CharType TakeBOM(InputByteStream& is) { RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); - Ch c = Take(is); - return c; + uint8_t c = static_cast(Take(is)); + return static_cast(c); } template static Ch Take(InputByteStream& is) { RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); - return is.Take(); + return static_cast(is.Take()); } template diff --git a/include/rapidjson/error/en.h b/include/rapidjson/error/en.h index d5f9caa..81932e2 100644 --- a/include/rapidjson/error/en.h +++ b/include/rapidjson/error/en.h @@ -12,8 +12,8 @@ // CONDITIONS OF ANY KIND, either express or implied. See the License for the // specific language governing permissions and limitations under the License. -#ifndef RAPIDJSON_ERROR_EN_H__ -#define RAPIDJSON_ERROR_EN_H__ +#ifndef RAPIDJSON_ERROR_EN_H_ +#define RAPIDJSON_ERROR_EN_H_ #include "error.h" @@ -54,12 +54,10 @@ inline const RAPIDJSON_ERROR_CHARTYPE* GetParseError_En(ParseErrorCode parseErro case kParseErrorTermination: 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."); } + return RAPIDJSON_ERROR_STRING("Unknown error."); } RAPIDJSON_NAMESPACE_END -#endif // RAPIDJSON_ERROR_EN_H__ +#endif // RAPIDJSON_ERROR_EN_H_ diff --git a/include/rapidjson/error/error.h b/include/rapidjson/error/error.h index f9094fb..95cb31a 100644 --- a/include/rapidjson/error/error.h +++ b/include/rapidjson/error/error.h @@ -12,11 +12,16 @@ // CONDITIONS OF ANY KIND, either express or implied. See the License for the // specific language governing permissions and limitations under the License. -#ifndef RAPIDJSON_ERROR_ERROR_H__ -#define RAPIDJSON_ERROR_ERROR_H__ +#ifndef RAPIDJSON_ERROR_ERROR_H_ +#define RAPIDJSON_ERROR_ERROR_H_ #include "../rapidjson.h" +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(padded) +#endif + /*! \file error.h */ /*! \defgroup RAPIDJSON_ERRORS RapidJSON error handling */ @@ -99,7 +104,7 @@ enum ParseErrorCode { \see GenericReader::Parse, GenericDocument::Parse */ struct ParseResult { - +public: //! Default constructor, no error. ParseResult() : code_(kParseErrorNone), offset_(0) {} //! Constructor to set an error. @@ -143,4 +148,8 @@ typedef const RAPIDJSON_ERROR_CHARTYPE* (*GetParseErrorFunc)(ParseErrorCode); RAPIDJSON_NAMESPACE_END -#endif // RAPIDJSON_ERROR_ERROR_H__ +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_ERROR_ERROR_H_ diff --git a/include/rapidjson/filereadstream.h b/include/rapidjson/filereadstream.h index 78ee403..588f7f1 100644 --- a/include/rapidjson/filereadstream.h +++ b/include/rapidjson/filereadstream.h @@ -18,6 +18,11 @@ #include "rapidjson.h" #include +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(padded) +#endif + RAPIDJSON_NAMESPACE_BEGIN //! File byte stream for input using fread(). @@ -45,8 +50,8 @@ public: size_t Tell() const { return count_ + static_cast(current_ - buffer_); } // Not implemented - void Put(Ch) { RAPIDJSON_ASSERT(false); } - void Flush() { RAPIDJSON_ASSERT(false); } + void Put(Ch) RAPIDJSON_NORETURN_SUFFIX { RAPIDJSON_ASSERT(false); } + void Flush() RAPIDJSON_NORETURN_SUFFIX { RAPIDJSON_ASSERT(false); } Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } @@ -85,4 +90,8 @@ private: RAPIDJSON_NAMESPACE_END +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif + #endif // RAPIDJSON_FILESTREAM_H_ diff --git a/include/rapidjson/internal/biginteger.h b/include/rapidjson/internal/biginteger.h index 4477cf5..9d3e88c 100755 --- a/include/rapidjson/internal/biginteger.h +++ b/include/rapidjson/internal/biginteger.h @@ -240,7 +240,7 @@ private: uint64_t r = 0; for (const char* p = begin; p != end; ++p) { RAPIDJSON_ASSERT(*p >= '0' && *p <= '9'); - r = r * 10u + (unsigned)(*p - '0'); + r = r * 10u + static_cast(*p - '0'); } return r; } diff --git a/include/rapidjson/internal/diyfp.h b/include/rapidjson/internal/diyfp.h index 7a55ee3..9a62c2c 100644 --- a/include/rapidjson/internal/diyfp.h +++ b/include/rapidjson/internal/diyfp.h @@ -35,6 +35,11 @@ RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_OFF(effc++) #endif +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(padded) +#endif + struct DiyFp { DiyFp() {} @@ -242,6 +247,11 @@ inline DiyFp GetCachedPower10(int exp, int *outExp) { RAPIDJSON_DIAG_POP #endif +#ifdef __clang__ +RAPIDJSON_DIAG_POP +RAPIDJSON_DIAG_OFF(padded) +#endif + } // namespace internal RAPIDJSON_NAMESPACE_END diff --git a/include/rapidjson/internal/ieee754.h b/include/rapidjson/internal/ieee754.h index 2fdaf54..6890f89 100644 --- a/include/rapidjson/internal/ieee754.h +++ b/include/rapidjson/internal/ieee754.h @@ -53,7 +53,7 @@ public: else if (order <= -1074) return 0; else - return (unsigned)order + 1074; + return static_cast(order) + 1074; } private: diff --git a/include/rapidjson/internal/stack.h b/include/rapidjson/internal/stack.h index 82f23dd..dcc9757 100644 --- a/include/rapidjson/internal/stack.h +++ b/include/rapidjson/internal/stack.h @@ -132,7 +132,7 @@ public: } template - T* Bottom() { return (T*)stack_; } + T* Bottom() { return reinterpret_cast(stack_); } bool HasAllocator() const { return allocator_ != 0; @@ -168,7 +168,7 @@ private: void Resize(size_t newCapacity) { const size_t size = GetSize(); // Backup the current size - stack_ = (char*)allocator_->Realloc(stack_, GetCapacity(), newCapacity); + stack_ = static_cast(allocator_->Realloc(stack_, GetCapacity(), newCapacity)); stackTop_ = stack_ + size; stackEnd_ = stack_ + newCapacity; } diff --git a/include/rapidjson/internal/strtod.h b/include/rapidjson/internal/strtod.h index a1b8211..89590c4 100644 --- a/include/rapidjson/internal/strtod.h +++ b/include/rapidjson/internal/strtod.h @@ -149,7 +149,7 @@ inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosit v = v.Normalize(); error <<= -v.e; - const int dExp = (int)decimalPosition - (int)i + exp; + const int dExp = static_cast(decimalPosition) - static_cast(i) + exp; int actualExp; DiyFp cachedPower = GetCachedPower10(dExp, &actualExp); @@ -206,7 +206,7 @@ inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosit inline double StrtodBigInteger(double approx, const char* decimals, size_t length, size_t decimalPosition, int exp) { const BigInteger dInt(decimals, length); - const int dExp = (int)decimalPosition - (int)length + exp; + const int dExp = static_cast(decimalPosition) - static_cast(length) + exp; Double a(approx); int cmp = CheckWithinHalfULP(a.Value(), dInt, dExp); if (cmp < 0) @@ -246,8 +246,8 @@ inline double StrtodFullPrecision(double d, int p, const char* decimals, size_t // Trim right-most digits const int kMaxDecimalDigit = 780; - if ((int)length > kMaxDecimalDigit) { - int delta = (int(length) - kMaxDecimalDigit); + if (static_cast(length) > kMaxDecimalDigit) { + int delta = (static_cast(length) - kMaxDecimalDigit); exp += delta; decimalPosition -= static_cast(delta); length = kMaxDecimalDigit; diff --git a/include/rapidjson/memorystream.h b/include/rapidjson/memorystream.h index 99feae5..03c04e8 100644 --- a/include/rapidjson/memorystream.h +++ b/include/rapidjson/memorystream.h @@ -41,8 +41,8 @@ struct MemoryStream { size_t Tell() const { return static_cast(src_ - begin_); } Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } - void Put(Ch) { RAPIDJSON_ASSERT(false); } - void Flush() { RAPIDJSON_ASSERT(false); } + void Put(Ch) RAPIDJSON_NORETURN_SUFFIX { RAPIDJSON_ASSERT(false); } + void Flush() RAPIDJSON_NORETURN_SUFFIX { RAPIDJSON_ASSERT(false); } size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } // For encoding detection only. diff --git a/include/rapidjson/pointer.h b/include/rapidjson/pointer.h index d873163..f58ce35 100644 --- a/include/rapidjson/pointer.h +++ b/include/rapidjson/pointer.h @@ -253,11 +253,12 @@ public: */ GenericPointer Append(SizeType index, Allocator* allocator = 0) const { char buffer[21]; - SizeType length = (sizeof(SizeType) == 4 ? internal::u32toa(index, buffer): internal::u64toa(index, buffer)) - buffer; + char* end = sizeof(SizeType) == 4 ? internal::u32toa(index, buffer) : internal::u64toa(index, buffer); + SizeType length = static_cast(end - buffer); buffer[length] = '\0'; if (sizeof(Ch) == 1) { - Token token = { (Ch*)buffer, length, index }; + Token token = { reinterpret_cast(buffer), length, index }; return Append(token, allocator); } else { @@ -271,7 +272,7 @@ public: //! Append a token by value, and return a new Pointer /*! - \param value Value (either Uint or String) to be appended. + \param token token to be appended. \param allocator Allocator for the newly return Pointer. \return A new Pointer with appended token. */ @@ -435,7 +436,6 @@ public: //! Creates a value in a document. /*! \param document A document to be resolved. - \param allocator Allocator for creating the values if the specified value or its parents are not exist. \param alreadyExist If non-null, it stores whether the resolved value is already exist. \return The resolved newly created, or already exists value. */ @@ -472,7 +472,11 @@ public: return 0; v = &((*v)[t->index]); break; - default: + case kNullType: + case kFalseType: + case kTrueType: + case kStringType: + case kNumberType: return 0; } } @@ -525,7 +529,7 @@ public: //! Query a value in a subtree with default primitive value. /*! - \tparam T \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool + \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool */ template RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (ValueType&)) @@ -555,7 +559,7 @@ public: //! Query a value in a document with default primitive value. /*! - \tparam T \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool + \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool */ template RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (ValueType&)) @@ -601,7 +605,7 @@ public: //! Set a primitive value in a subtree. /*! - \tparam T \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool + \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool */ template RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (ValueType&)) @@ -637,7 +641,7 @@ public: //! Set a primitive value in a document. /*! - \tparam T \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool + \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool */ template RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (ValueType&)) @@ -701,7 +705,11 @@ public: return false; v = &((*v)[t->index]); break; - default: + case kNullType: + case kFalseType: + case kTrueType: + case kStringType: + case kNumberType: return false; } } @@ -714,7 +722,11 @@ public: return false; v->Erase(v->Begin() + last->index); return true; - default: + case kNullType: + case kFalseType: + case kTrueType: + case kStringType: + case kNumberType: return false; } } @@ -759,11 +771,13 @@ private: } //! Parse a JSON String or its URI fragment representation into tokens. +#ifndef __clang__ // -Wdocumentation /*! \param source Either a JSON Pointer string, or its URI fragment representation. Not need to be null terminated. \param length Length of the source string. \note Source cannot be JSON String Representation of JSON Pointer, e.g. In "/\u0000", \u0000 will not be unescaped. */ +#endif void Parse(const Ch* source, size_t length) { RAPIDJSON_ASSERT(source != NULL); RAPIDJSON_ASSERT(nameBuffer_ == 0); @@ -857,7 +871,7 @@ private: *name++ = c; } - token->length = name - token->name; + token->length = static_cast(name - token->name); if (token->length == 0) isNumber = false; *name++ = '\0'; // Null terminator @@ -944,6 +958,8 @@ private: */ class PercentDecodeStream { public: + typedef Ch Ch; + //! Constructor /*! \param source Start of the stream @@ -973,7 +989,7 @@ private: return c; } - size_t Tell() const { return src_ - head_; } + size_t Tell() const { return static_cast(src_ - head_); } bool IsValid() const { return valid_; } private: diff --git a/include/rapidjson/prettywriter.h b/include/rapidjson/prettywriter.h index fff8886..adfff4f 100644 --- a/include/rapidjson/prettywriter.h +++ b/include/rapidjson/prettywriter.h @@ -186,7 +186,7 @@ protected: void WriteIndent() { size_t count = (Base::level_stack_.GetSize() / sizeof(typename Base::Level)) * indentCharCount_; - PutN(*Base::os_, indentChar_, count); + PutN(*Base::os_, static_cast(indentChar_), count); } Ch indentChar_; diff --git a/include/rapidjson/rapidjson.h b/include/rapidjson/rapidjson.h index 7034f48..41790cf 100644 --- a/include/rapidjson/rapidjson.h +++ b/include/rapidjson/rapidjson.h @@ -119,6 +119,31 @@ #define RAPIDJSON_NAMESPACE_END } #endif +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_HAS_STDSTRING + +#ifndef RAPIDJSON_HAS_STDSTRING +#ifdef RAPIDJSON_DOXYGEN_RUNNING +#define RAPIDJSON_HAS_STDSTRING 1 // force generation of documentation +#else +#define RAPIDJSON_HAS_STDSTRING 0 // no std::string support by default +#endif +/*! \def RAPIDJSON_HAS_STDSTRING + \ingroup RAPIDJSON_CONFIG + \brief Enable RapidJSON support for \c std::string + + By defining this preprocessor symbol to \c 1, several convenience functions for using + \ref rapidjson::GenericValue with \c std::string are enabled, especially + for construction and comparison. + + \hideinitializer +*/ +#endif // !defined(RAPIDJSON_HAS_STDSTRING) + +#if RAPIDJSON_HAS_STDSTRING +#include +#endif // RAPIDJSON_HAS_STDSTRING + /////////////////////////////////////////////////////////////////////////////// // RAPIDJSON_NO_INT64DEFINE @@ -351,7 +376,9 @@ RAPIDJSON_NAMESPACE_END // Adopt from boost #ifndef RAPIDJSON_STATIC_ASSERT +#ifndef __clang__ //!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN +#endif RAPIDJSON_NAMESPACE_BEGIN template struct STATIC_ASSERTION_FAILURE; template <> struct STATIC_ASSERTION_FAILURE { enum { value = 1 }; }; @@ -367,7 +394,9 @@ RAPIDJSON_NAMESPACE_END #else #define RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE #endif +#ifndef __clang__ //!@endcond +#endif /*! \def RAPIDJSON_STATIC_ASSERT \brief (Internal) macro to check for conditions at compile-time @@ -435,6 +464,15 @@ RAPIDJSON_NAMESPACE_END #endif // RAPIDJSON_DIAG_* +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_NORETURN_SUFFIX + +#if defined(__clang__) +#define RAPIDJSON_NORETURN_SUFFIX __attribute__ ((noreturn)) +#else +#define RAPIDJSON_NORETURN_SUFFIX +#endif + /////////////////////////////////////////////////////////////////////////////// // C++11 features diff --git a/include/rapidjson/reader.h b/include/rapidjson/reader.h index b56f3b5..4cb7d50 100644 --- a/include/rapidjson/reader.h +++ b/include/rapidjson/reader.h @@ -39,6 +39,11 @@ RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant RAPIDJSON_DIAG_OFF(4702) // unreachable code #endif +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(padded) +#endif + #ifdef __GNUC__ RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_OFF(effc++) @@ -263,7 +268,7 @@ inline const char *SkipWhitespace_SIMD(const char* p) { return p; // 16-byte align to the next boundary - const char* nextAligned = reinterpret_cast((reinterpret_cast(p) + 15) & ~15); + const char* nextAligned = reinterpret_cast((reinterpret_cast(p) + 15) & static_cast(~15)); while (p != nextAligned) if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t') ++p; @@ -272,11 +277,11 @@ inline const char *SkipWhitespace_SIMD(const char* p) { // The rest of string using SIMD static const char whitespace[16] = " \n\r\t"; - const __m128i w = _mm_loadu_si128((const __m128i *)&whitespace[0]); + const __m128i w = _mm_loadu_si128(reinterpret_cast(&whitespace[0])); for (;; p += 16) { - const __m128i s = _mm_load_si128((const __m128i *)p); - const unsigned r = _mm_cvtsi128_si32(_mm_cmpistrm(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_BIT_MASK | _SIDD_NEGATIVE_POLARITY)); + const __m128i s = _mm_load_si128(reinterpret_cast(p)); + const int r = _mm_cvtsi128_si32(_mm_cmpistrm(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_BIT_MASK | _SIDD_NEGATIVE_POLARITY)); if (r != 0) { // some of characters is non-whitespace #ifdef _MSC_VER // Find the index of first non-whitespace unsigned long offset; @@ -698,7 +703,7 @@ private: RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; size_t length = s.PutEnd(head) - 1; RAPIDJSON_ASSERT(length <= 0xFFFFFFFF); - const typename TargetEncoding::Ch* const str = (typename TargetEncoding::Ch*)head; + const typename TargetEncoding::Ch* const str = reinterpret_cast(head); success = (isKey ? handler.Key(str, SizeType(length), false) : handler.String(str, SizeType(length), false)); } else { @@ -737,9 +742,8 @@ private: if (c == '\\') { // Escape is.Take(); Ch e = is.Take(); - if ((sizeof(Ch) == 1 || unsigned(e) < 256) && escape[(unsigned char)e]) { - os.Put(escape[(unsigned char)e]); - } + if ((sizeof(Ch) == 1 || unsigned(e) < 256) && escape[static_cast(e)]) + os.Put(static_cast(escape[static_cast(e)])); else if (e == 'u') { // Unicode unsigned codepoint = ParseHex4(is); RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; @@ -765,7 +769,7 @@ private: } else if (c == '\0') RAPIDJSON_PARSE_ERROR(kParseErrorStringMissQuotationMark, is.Tell() - 1); - else if ((unsigned)c < 0x20) // RFC 4627: unescaped = %x20-21 / %x23-5B / %x5D-10FFFF + else if (static_cast(c) < 0x20) // RFC 4627: unescaped = %x20-21 / %x23-5B / %x5D-10FFFF RAPIDJSON_PARSE_ERROR(kParseErrorStringEscapeInvalid, is.Tell() - 1); else { if (parseFlags & kParseValidateEncodingFlag ? @@ -806,7 +810,7 @@ private: ~NumberStream() {} RAPIDJSON_FORCEINLINE Ch TakePush() { - stackStream.Put((char)Base::is.Peek()); + stackStream.Put(static_cast(Base::is.Peek())); return Base::is.Take(); } @@ -937,10 +941,10 @@ private: } } - d = (double)i64; + d = static_cast(i64); #else // Use double to store significand in 32-bit architecture - d = use64bit ? (double)i64 : (double)i; + d = static_cast(use64bit ? i64 : i); #endif useDouble = true; } @@ -977,10 +981,10 @@ private: } if (s.Peek() >= '0' && s.Peek() <= '9') { - exp = s.Take() - '0'; + exp = static_cast(s.Take() - '0'); if (expMinus) { while (s.Peek() >= '0' && s.Peek() <= '9') { - exp = exp * 10 + (s.Take() - '0'); + exp = exp * 10 + static_cast(s.Take() - '0'); if (exp >= 214748364) { // Issue #313: prevent overflow exponent while (s.Peek() >= '0' && s.Peek() <= '9') // Consume the rest of exponent s.Take(); @@ -990,7 +994,7 @@ private: else { // positive exp int maxExp = 308 - expFrac; while (s.Peek() >= '0' && s.Peek() <= '9') { - exp = exp * 10 + (s.Take() - '0'); + exp = exp * 10 + static_cast(s.Take() - '0'); if (exp > maxExp) RAPIDJSON_PARSE_ERROR(kParseErrorNumberTooBig, s.Tell()); } @@ -1075,11 +1079,11 @@ private: IterativeParsingArrayFinishState, // Single value state - IterativeParsingValueState, - - cIterativeParsingStateCount + IterativeParsingValueState }; + enum { cIterativeParsingStateCount = IterativeParsingValueState + 1 }; + // Tokens enum Token { LeftBracketToken = 0, @@ -1121,8 +1125,8 @@ private: #undef N16 //!@endcond - if (sizeof(Ch) == 1 || unsigned(c) < 256) - return (Token)tokenMap[(unsigned char)c]; + if (sizeof(Ch) == 1 || static_cast(c) < 256) + return static_cast(tokenMap[static_cast(c)]); else return NumberToken; } @@ -1288,7 +1292,7 @@ private: } }; // End of G - return (IterativeParsingState)G[state][token]; + return static_cast(G[state][token]); } // Make an advance in the token stream and state based on the candidate destination state which was returned by Transit(). @@ -1413,7 +1417,9 @@ private: } } - default: + case IterativeParsingStartState: + case IterativeParsingFinishState: + case IterativeParsingValueState: // This branch is for IterativeParsingValueState actually. // Use `default:` rather than // `case IterativeParsingValueState:` is for code coverage. @@ -1450,7 +1456,13 @@ private: case IterativeParsingMemberKeyState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissColon, is.Tell()); return; case IterativeParsingMemberValueState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell()); return; case IterativeParsingElementState: RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell()); return; - default: RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell()); return; + case IterativeParsingErrorState: + case IterativeParsingKeyValueDelimiterState: + case IterativeParsingObjectFinishState: + case IterativeParsingArrayInitialState: + case IterativeParsingElementDelimiterState: + case IterativeParsingArrayFinishState: + case IterativeParsingValueState: RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell()); return; } } @@ -1499,6 +1511,11 @@ typedef GenericReader, UTF8<> > Reader; RAPIDJSON_NAMESPACE_END +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif + + #ifdef __GNUC__ RAPIDJSON_DIAG_POP #endif diff --git a/include/rapidjson/writer.h b/include/rapidjson/writer.h index 8fcffbe..a450456 100644 --- a/include/rapidjson/writer.h +++ b/include/rapidjson/writer.h @@ -23,15 +23,16 @@ #include "stringbuffer.h" #include // placement new -#if RAPIDJSON_HAS_STDSTRING -#include -#endif - #ifdef _MSC_VER RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant #endif +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(padded) +#endif + RAPIDJSON_NAMESPACE_BEGIN //! JSON writer @@ -205,7 +206,7 @@ protected: char buffer[11]; const char* end = internal::i32toa(i, buffer); for (const char* p = buffer; p != end; ++p) - os_->Put(*p); + os_->Put(static_cast(*p)); return true; } @@ -213,7 +214,7 @@ protected: char buffer[10]; const char* end = internal::u32toa(u, buffer); for (const char* p = buffer; p != end; ++p) - os_->Put(*p); + os_->Put(static_cast(*p)); return true; } @@ -221,7 +222,7 @@ protected: char buffer[21]; const char* end = internal::i64toa(i64, buffer); for (const char* p = buffer; p != end; ++p) - os_->Put(*p); + os_->Put(static_cast(*p)); return true; } @@ -229,7 +230,7 @@ protected: char buffer[20]; char* end = internal::u64toa(u64, buffer); for (char* p = buffer; p != end; ++p) - os_->Put(*p); + os_->Put(static_cast(*p)); return true; } @@ -237,12 +238,12 @@ protected: char buffer[25]; char* end = internal::dtoa(d, buffer); for (char* p = buffer; p != end; ++p) - os_->Put(*p); + os_->Put(static_cast(*p)); return true; } bool WriteString(const Ch* str, SizeType length) { - static const char hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + static const typename TargetEncoding::Ch hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; static const char escape[256] = { #define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //0 1 2 3 4 5 6 7 8 9 A B C D E F @@ -259,7 +260,7 @@ protected: GenericStringStream is(str); while (is.Tell() < length) { const Ch c = is.Peek(); - if (!TargetEncoding::supportUnicode && (unsigned)c >= 0x80) { + if (!TargetEncoding::supportUnicode && static_cast(c) >= 0x80) { // Unicode escaping unsigned codepoint; if (!SourceEncoding::Decode(is, &codepoint)) @@ -290,15 +291,15 @@ protected: os_->Put(hexDigits[(trail ) & 15]); } } - else if ((sizeof(Ch) == 1 || (unsigned)c < 256) && escape[(unsigned char)c]) { + else if ((sizeof(Ch) == 1 || static_cast(c) < 256) && escape[static_cast(c)]) { is.Take(); os_->Put('\\'); - os_->Put(escape[(unsigned char)c]); - if (escape[(unsigned char)c] == 'u') { + os_->Put(static_cast(escape[static_cast(c)])); + if (escape[static_cast(c)] == 'u') { os_->Put('0'); os_->Put('0'); - os_->Put(hexDigits[(unsigned char)c >> 4]); - os_->Put(hexDigits[(unsigned char)c & 0xF]); + os_->Put(hexDigits[static_cast(c) >> 4]); + os_->Put(hexDigits[static_cast(c) & 0xF]); } } else @@ -392,4 +393,8 @@ RAPIDJSON_NAMESPACE_END RAPIDJSON_DIAG_POP #endif +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif + #endif // RAPIDJSON_RAPIDJSON_H_ diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index c698af4..11c1b04 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -9,7 +9,7 @@ IF(GTESTSRC_FOUND) endif() add_subdirectory(${GTEST_SOURCE_DIR} ${CMAKE_BINARY_DIR}/googletest) - include_directories(${GTEST_INCLUDE_DIR}) + include_directories(SYSTEM ${GTEST_INCLUDE_DIR}) set(TEST_LIBRARIES gtest gtest_main) diff --git a/test/unittest/CMakeLists.txt b/test/unittest/CMakeLists.txt index fd2eb4d..35b800f 100644 --- a/test/unittest/CMakeLists.txt +++ b/test/unittest/CMakeLists.txt @@ -21,7 +21,7 @@ set(UNITTEST_SOURCES if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror -Wall -Wextra -Weffc++ -Wswitch-default -Wfloat-equal") elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror -Wall -Wextra -Weffc++ -Wswitch-default -Wfloat-equal -Wimplicit-fallthrough") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror -Wall -Wextra -Weffc++ -Wswitch-default -Wfloat-equal -Wimplicit-fallthrough -Weverything") elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") add_definitions(-D_CRT_SECURE_NO_WARNINGS=1) endif() diff --git a/test/unittest/allocatorstest.cpp b/test/unittest/allocatorstest.cpp index 792a88e..f70e672 100644 --- a/test/unittest/allocatorstest.cpp +++ b/test/unittest/allocatorstest.cpp @@ -22,21 +22,21 @@ template void TestAllocator(Allocator& a) { EXPECT_TRUE(a.Malloc(0) == 0); - uint8_t* p = (uint8_t*)a.Malloc(100); + uint8_t* p = static_cast(a.Malloc(100)); EXPECT_TRUE(p != 0); for (size_t i = 0; i < 100; i++) - p[i] = (uint8_t)i; + p[i] = static_cast(i); // Expand - uint8_t* q = (uint8_t*)a.Realloc(p, 100, 200); + uint8_t* q = static_cast(a.Realloc(p, 100, 200)); EXPECT_TRUE(q != 0); for (size_t i = 0; i < 100; i++) EXPECT_EQ(i, q[i]); for (size_t i = 100; i < 200; i++) - q[i] = (uint8_t)i; + q[i] = static_cast(i); // Shrink - uint8_t *r = (uint8_t*)a.Realloc(q, 200, 150); + uint8_t *r = static_cast(a.Realloc(q, 200, 150)); EXPECT_TRUE(r != 0); for (size_t i = 0; i < 150; i++) EXPECT_EQ(i, r[i]); @@ -56,7 +56,7 @@ TEST(Allocator, MemoryPoolAllocator) { MemoryPoolAllocator<> a; TestAllocator(a); - for (int i = 1; i < 1000; i++) { + for (size_t i = 1; i < 1000; i++) { EXPECT_TRUE(a.Malloc(i) != 0); EXPECT_LE(a.Size(), a.Capacity()); } diff --git a/test/unittest/documenttest.cpp b/test/unittest/documenttest.cpp index e4d1432..cdc4c31 100644 --- a/test/unittest/documenttest.cpp +++ b/test/unittest/documenttest.cpp @@ -28,7 +28,7 @@ void ParseCheck(DocumentType& doc) { typedef typename DocumentType::ValueType ValueType; EXPECT_FALSE(doc.HasParseError()); - EXPECT_TRUE((ParseResult)doc); + EXPECT_TRUE(static_cast(doc)); EXPECT_TRUE(doc.IsObject()); @@ -63,8 +63,8 @@ void ParseCheck(DocumentType& doc) { const ValueType& a = doc["a"]; EXPECT_TRUE(a.IsArray()); EXPECT_EQ(4u, a.Size()); - for (SizeType i = 0; i < 4; i++) - EXPECT_EQ(i + 1, a[i].GetUint()); + for (SizeType j = 0; j < 4; j++) + EXPECT_EQ(j + 1, a[j].GetUint()); } template @@ -118,15 +118,15 @@ TEST(Document, UnchangedOnParseError) { static FILE* OpenEncodedFile(const char* filename) { const char *paths[] = { - "encodings/%s", - "bin/encodings/%s", - "../bin/encodings/%s", - "../../bin/encodings/%s", - "../../../bin/encodings/%s" + "encodings", + "bin/encodings", + "../bin/encodings", + "../../bin/encodings", + "../../../bin/encodings" }; char buffer[1024]; for (size_t i = 0; i < sizeof(paths) / sizeof(paths[0]); i++) { - sprintf(buffer, paths[i], filename); + sprintf(buffer, "%s/%s", paths[i], filename); FILE *fp = fopen(buffer, "rb"); if (fp) return fp; @@ -157,22 +157,22 @@ TEST(Document, ParseStream_EncodedInputStream) { StringBuffer bos; typedef EncodedOutputStream, StringBuffer> OutputStream; OutputStream eos(bos, false); // Not writing BOM - Writer, UTF8<> > writer(eos); - d.Accept(writer); - { - // Condense the original file and compare. - FILE *fp = OpenEncodedFile("utf8.json"); - FileReadStream is(fp, buffer, sizeof(buffer)); - Reader reader; - StringBuffer bos2; - Writer writer(bos2); - reader.Parse(is, writer); - fclose(fp); - - EXPECT_EQ(bos.GetSize(), bos2.GetSize()); - EXPECT_EQ(0, memcmp(bos.GetString(), bos2.GetString(), bos2.GetSize())); + Writer, UTF8<> > writer(eos); + d.Accept(writer); } + + // Condense the original file and compare. + fp = OpenEncodedFile("utf8.json"); + FileReadStream is(fp, buffer, sizeof(buffer)); + Reader reader; + StringBuffer bos2; + Writer writer2(bos2); + reader.Parse(is, writer2); + fclose(fp); + + EXPECT_EQ(bos.GetSize(), bos2.GetSize()); + EXPECT_EQ(0, memcmp(bos.GetString(), bos2.GetString(), bos2.GetSize())); } TEST(Document, ParseStream_AutoUTFInputStream) { @@ -199,19 +199,17 @@ TEST(Document, ParseStream_AutoUTFInputStream) { Writer writer(bos); d.Accept(writer); - { - // Condense the original file and compare. - FILE *fp = OpenEncodedFile("utf8.json"); - FileReadStream is(fp, buffer, sizeof(buffer)); - Reader reader; - StringBuffer bos2; - Writer writer(bos2); - reader.Parse(is, writer); - fclose(fp); + // Condense the original file and compare. + fp = OpenEncodedFile("utf8.json"); + FileReadStream is(fp, buffer, sizeof(buffer)); + Reader reader; + StringBuffer bos2; + Writer writer2(bos2); + reader.Parse(is, writer2); + fclose(fp); - EXPECT_EQ(bos.GetSize(), bos2.GetSize()); - EXPECT_EQ(0, memcmp(bos.GetString(), bos2.GetString(), bos2.GetSize())); - } + EXPECT_EQ(bos.GetSize(), bos2.GetSize()); + EXPECT_EQ(0, memcmp(bos.GetString(), bos2.GetString(), bos2.GetSize())); } TEST(Document, Swap) { @@ -263,12 +261,16 @@ TEST(Document, Swap) { struct OutputStringStream : public std::ostringstream { typedef char Ch; + virtual ~OutputStringStream(); + void Put(char c) { put(c); } void Flush() {} }; +OutputStringStream::~OutputStringStream() {} + TEST(Document, AcceptWriter) { Document doc; doc.Parse(" { \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3, 4] } "); diff --git a/test/unittest/encodedstreamtest.cpp b/test/unittest/encodedstreamtest.cpp index 8cef208..f6d6935 100644 --- a/test/unittest/encodedstreamtest.cpp +++ b/test/unittest/encodedstreamtest.cpp @@ -25,6 +25,7 @@ using namespace rapidjson; class EncodedStreamTest : public ::testing::Test { public: EncodedStreamTest() : json_(), length_() {} + virtual ~EncodedStreamTest(); virtual void SetUp() { json_ = ReadFile("utf8.json", true, &length_); @@ -42,15 +43,15 @@ private: protected: static FILE* Open(const char* filename) { const char *paths[] = { - "encodings/%s", - "bin/encodings/%s", - "../bin/encodings/%s", - "../../bin/encodings/%s", - "../../../bin/encodings/%s" + "encodings", + "bin/encodings", + "../bin/encodings", + "../../bin/encodings", + "../../../bin/encodings" }; char buffer[1024]; for (size_t i = 0; i < sizeof(paths) / sizeof(paths[0]); i++) { - sprintf(buffer, paths[i], filename); + sprintf(buffer, "%s/%s", paths[i], filename); FILE *fp = fopen(buffer, "rb"); if (fp) return fp; @@ -67,9 +68,9 @@ protected: } fseek(fp, 0, SEEK_END); - *outLength = (size_t)ftell(fp); + *outLength = static_cast(ftell(fp)); fseek(fp, 0, SEEK_SET); - char* buffer = (char*)malloc(*outLength + 1); + char* buffer = static_cast(malloc(*outLength + 1)); size_t readLength = fread(buffer, 1, *outLength, fp); buffer[readLength] = '\0'; fclose(fp); @@ -248,6 +249,8 @@ protected: size_t length_; }; +EncodedStreamTest::~EncodedStreamTest() {} + TEST_F(EncodedStreamTest, EncodedInputStream) { TestEncodedInputStream, UTF8<> >("utf8.json"); TestEncodedInputStream, UTF8<> >("utf8bom.json"); diff --git a/test/unittest/encodingstest.cpp b/test/unittest/encodingstest.cpp index b697d91..be59cc9 100644 --- a/test/unittest/encodingstest.cpp +++ b/test/unittest/encodingstest.cpp @@ -240,7 +240,6 @@ static const unsigned kCodepointRanges[] = { // See http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ for details. #define UTF8_ACCEPT 0u -#define UTF8_REJECT 12u static const unsigned char utf8d[] = { // The first part of the table maps bytes to character classes that @@ -298,7 +297,7 @@ TEST(EncodingsTest, UTF8) { unsigned decodedCount = 0; for (const char* s = encodedStr; *s; ++s) - if (!decode(&state, &decodedCodepoint, (unsigned char)*s)) { + if (!decode(&state, &decodedCodepoint, static_cast(*s))) { EXPECT_EQ(codepoint, decodedCodepoint); decodedCount++; } @@ -355,7 +354,7 @@ TEST(EncodingsTest, UTF16) { unsigned state = 0; UTF16<>::Ch buffer[3], *p = &buffer[0]; for (const char* s = utf8os.GetString(); *s; ++s) { - if (!decode(&state, &decodedCodepoint, (unsigned char)*s)) + if (!decode(&state, &decodedCodepoint, static_cast(*s))) break; } diff --git a/test/unittest/filestreamtest.cpp b/test/unittest/filestreamtest.cpp index 2850b56..539da70 100644 --- a/test/unittest/filestreamtest.cpp +++ b/test/unittest/filestreamtest.cpp @@ -22,6 +22,7 @@ using namespace rapidjson; class FileStreamTest : public ::testing::Test { public: FileStreamTest() : filename_(), json_(), length_() {} + virtual ~FileStreamTest(); virtual void SetUp() { const char *paths[] = { @@ -42,9 +43,9 @@ public: ASSERT_TRUE(fp != 0); fseek(fp, 0, SEEK_END); - length_ = (size_t)ftell(fp); + length_ = static_cast(ftell(fp)); fseek(fp, 0, SEEK_SET); - json_ = (char*)malloc(length_ + 1); + json_ = static_cast(malloc(length_ + 1)); size_t readLength = fread(json_, 1, length_, fp); json_[readLength] = '\0'; fclose(fp); @@ -65,6 +66,8 @@ protected: size_t length_; }; +FileStreamTest::~FileStreamTest() {} + TEST_F(FileStreamTest, FileReadStream) { FILE *fp = fopen(filename_, "rb"); ASSERT_TRUE(fp != 0); diff --git a/test/unittest/itoatest.cpp b/test/unittest/itoatest.cpp index 5ceb99f..9c3107d 100644 --- a/test/unittest/itoatest.cpp +++ b/test/unittest/itoatest.cpp @@ -30,28 +30,28 @@ template <> struct Traits { enum { kBufferSize = 11 }; enum { kMaxDigit = 10 }; - static uint32_t Negate(uint32_t x) { return x; }; + static uint32_t Negate(uint32_t x) { return x; } }; template <> struct Traits { enum { kBufferSize = 12 }; enum { kMaxDigit = 10 }; - static int32_t Negate(int32_t x) { return -x; }; + static int32_t Negate(int32_t x) { return -x; } }; template <> struct Traits { enum { kBufferSize = 21 }; enum { kMaxDigit = 20 }; - static uint64_t Negate(uint64_t x) { return x; }; + static uint64_t Negate(uint64_t x) { return x; } }; template <> struct Traits { enum { kBufferSize = 22 }; enum { kMaxDigit = 20 }; - static int64_t Negate(int64_t x) { return -x; }; + static int64_t Negate(int64_t x) { return -x; } }; template diff --git a/test/unittest/jsoncheckertest.cpp b/test/unittest/jsoncheckertest.cpp index 34f8569..8991667 100644 --- a/test/unittest/jsoncheckertest.cpp +++ b/test/unittest/jsoncheckertest.cpp @@ -20,16 +20,16 @@ using namespace rapidjson; static char* ReadFile(const char* filename, size_t& length) { const char *paths[] = { - "jsonchecker/%s", - "bin/jsonchecker/%s", - "../bin/jsonchecker/%s", - "../../bin/jsonchecker/%s", - "../../../bin/jsonchecker/%s" + "jsonchecker", + "bin/jsonchecker", + "../bin/jsonchecker", + "../../bin/jsonchecker", + "../../../bin/jsonchecker" }; char buffer[1024]; FILE *fp = 0; for (size_t i = 0; i < sizeof(paths) / sizeof(paths[0]); i++) { - sprintf(buffer, paths[i], filename); + sprintf(buffer, "%s/%s", paths[i], filename); fp = fopen(buffer, "rb"); if (fp) break; @@ -39,9 +39,9 @@ static char* ReadFile(const char* filename, size_t& length) { return 0; fseek(fp, 0, SEEK_END); - length = (size_t)ftell(fp); + length = static_cast(ftell(fp)); fseek(fp, 0, SEEK_SET); - char* json = (char*)malloc(length + 1); + char* json = static_cast(malloc(length + 1)); size_t readLength = fread(json, 1, length, fp); json[readLength] = '\0'; fclose(fp); @@ -68,10 +68,10 @@ TEST(JsonChecker, Reader) { } GenericDocument, CrtAllocator> document; // Use Crt allocator to check exception-safety (no memory leak) - document.Parse((const char*)json); + document.Parse(json); EXPECT_TRUE(document.HasParseError()); - document.Parse((const char*)json); + document.Parse(json); EXPECT_TRUE(document.HasParseError()); free(json); @@ -88,10 +88,10 @@ TEST(JsonChecker, Reader) { } GenericDocument, CrtAllocator> document; // Use Crt allocator to check exception-safety (no memory leak) - document.Parse((const char*)json); + document.Parse(json); EXPECT_FALSE(document.HasParseError()); - document.Parse((const char*)json); + document.Parse(json); EXPECT_FALSE(document.HasParseError()); free(json); diff --git a/test/unittest/pointertest.cpp b/test/unittest/pointertest.cpp index d36b59d..eee9ff7 100644 --- a/test/unittest/pointertest.cpp +++ b/test/unittest/pointertest.cpp @@ -306,7 +306,7 @@ TEST(Pointer, Parse_URIFragment) { GenericPointer > > p(L"#/%C2%A2"); EXPECT_TRUE(p.IsValid()); EXPECT_EQ(1u, p.GetTokenCount()); - EXPECT_EQ((UTF16<>::Ch)0x00A2, p.GetTokens()[0].name[0]); + EXPECT_EQ(static_cast::Ch>(0x00A2), p.GetTokens()[0].name[0]); EXPECT_EQ(1u, p.GetTokens()[0].length); } @@ -315,7 +315,7 @@ TEST(Pointer, Parse_URIFragment) { GenericPointer > > p(L"#/%E2%82%AC"); EXPECT_TRUE(p.IsValid()); EXPECT_EQ(1u, p.GetTokenCount()); - EXPECT_EQ((UTF16<>::Ch)0x20AC, p.GetTokens()[0].name[0]); + EXPECT_EQ(static_cast::Ch>(0x20AC), p.GetTokens()[0].name[0]); EXPECT_EQ(1u, p.GetTokens()[0].length); } @@ -1488,6 +1488,6 @@ TEST(Pointer, Issue483) { std::string mystr, path; myjson::Document document; myjson::Value value(rapidjson::kStringType); - value.SetString(mystr.c_str(), mystr.length(), document.GetAllocator()); + value.SetString(mystr.c_str(), static_cast(mystr.length()), document.GetAllocator()); myjson::Pointer(path.c_str()).Set(document, value, document.GetAllocator()); } diff --git a/test/unittest/prettywritertest.cpp b/test/unittest/prettywritertest.cpp index 1a63c82..d3c69c0 100644 --- a/test/unittest/prettywritertest.cpp +++ b/test/unittest/prettywritertest.cpp @@ -149,13 +149,13 @@ TEST(PrettyWriter, FileWriteStream) { fp = fopen(filename, "rb"); fseek(fp, 0, SEEK_END); - size_t size = (size_t)ftell(fp); + size_t size = static_cast(ftell(fp)); fseek(fp, 0, SEEK_SET); - char* json = (char*)malloc(size + 1); + char* json = static_cast(malloc(size + 1)); size_t readLength = fread(json, 1, size, fp); json[readLength] = '\0'; fclose(fp); remove(filename); EXPECT_STREQ(kPrettyJson, json); free(json); -} \ No newline at end of file +} diff --git a/test/unittest/readertest.cpp b/test/unittest/readertest.cpp index 71d7113..056ccb4 100644 --- a/test/unittest/readertest.cpp +++ b/test/unittest/readertest.cpp @@ -27,6 +27,11 @@ RAPIDJSON_DIAG_OFF(effc++) RAPIDJSON_DIAG_OFF(float-equal) #endif +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(variadic-macros) +#endif + template struct ParseBoolHandler : BaseReaderHandler, ParseBoolHandler > { ParseBoolHandler() : step_(0) {} @@ -159,12 +164,12 @@ TEST(Reader, ParseNumber_Integer) { u.u |= r(); char buffer[32]; - if (u.u >= 4294967296ULL) { + if (u.u > 4294967295) { *internal::u64toa(u.u, buffer) = '\0'; TEST_INTEGER(ParseUint64Handler, buffer, u.u); } - if (u.i <= -2147483649LL) { + if (u.i < -2147483648) { *internal::i64toa(u.i, buffer) = '\0'; TEST_INTEGER(ParseInt64Handler, buffer, u.i); } @@ -456,7 +461,7 @@ struct ParseStringHandler : BaseReaderHandler(malloc((length + 1) * sizeof(typename Encoding::Ch))); memcpy(const_cast(str_), str, (length + 1) * sizeof(typename Encoding::Ch)); } else @@ -639,11 +644,11 @@ TEST(Reader, ParseString_Error) { { char e[] = { '[', '\"', 0, '\"', ']', '\0' }; for (unsigned char c = 0x80u; c <= 0xBFu; c++) { - e[2] = c; + e[2] = static_cast(c); ParseErrorCode error = TestString >(e); EXPECT_EQ(kParseErrorStringInvalidEncoding, error); if (error != kParseErrorStringInvalidEncoding) - std::cout << (unsigned)(unsigned char)c << std::endl; + std::cout << static_cast(c) << std::endl; } } @@ -651,7 +656,7 @@ TEST(Reader, ParseString_Error) { { char e[] = { '[', '\"', 0, ' ', '\"', ']', '\0' }; for (unsigned c = 0xC0u; c <= 0xFFu; c++) { - e[2] = (char)c; + e[2] = static_cast(c); TEST_STRING_ERROR(kParseErrorStringInvalidEncoding, e); } } @@ -771,7 +776,7 @@ struct ParseObjectHandler : BaseReaderHandler, ParseObjectHandler> { default: ADD_FAILURE(); return false; } } - bool Uint(unsigned i) { return Int(i); } + bool Uint(unsigned i) { return Int(static_cast(i)); } bool Double(double d) { EXPECT_EQ(12u, step_); EXPECT_DOUBLE_EQ(3.1416, d); step_++; return true; } bool String(const char* str, size_t, bool) { switch(step_) { @@ -1024,19 +1029,19 @@ public: Ch Peek() const { int c = is_.peek(); - return c == std::char_traits::eof() ? '\0' : (Ch)c; + return c == std::char_traits::eof() ? '\0' : static_cast(c); } Ch Take() { int c = is_.get(); - return c == std::char_traits::eof() ? '\0' : (Ch)c; + return c == std::char_traits::eof() ? '\0' : static_cast(c); } - size_t Tell() const { return (size_t)is_.tellg(); } + size_t Tell() const { return static_cast(is_.tellg()); } Ch* PutBegin() { assert(false); return 0; } - void Put(Ch) { assert(false); } - void Flush() { assert(false); } + void Put(Ch) RAPIDJSON_NORETURN_SUFFIX { assert(false); } + void Flush() RAPIDJSON_NORETURN_SUFFIX { assert(false); } size_t PutEnd(Ch*) { assert(false); return 0; } private: @@ -1143,7 +1148,7 @@ struct IterativeParsingReaderHandler { bool EndObject(SizeType c) { RAPIDJSON_ASSERT(LogCount < LogCapacity); Logs[LogCount++] = LOG_ENDOBJECT; - Logs[LogCount++] = (int)c; + Logs[LogCount++] = static_cast(c); return true; } @@ -1152,7 +1157,7 @@ struct IterativeParsingReaderHandler { bool EndArray(SizeType c) { RAPIDJSON_ASSERT(LogCount < LogCapacity); Logs[LogCount++] = LOG_ENDARRAY; - Logs[LogCount++] = (int)c; + Logs[LogCount++] = static_cast(c); return true; } }; @@ -1455,3 +1460,7 @@ TEST(Reader, IncompleteMultilineComment) { #ifdef __GNUC__ RAPIDJSON_DIAG_POP #endif + +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif diff --git a/test/unittest/simdtest.cpp b/test/unittest/simdtest.cpp index c8f4587..4407c25 100644 --- a/test/unittest/simdtest.cpp +++ b/test/unittest/simdtest.cpp @@ -41,7 +41,7 @@ using namespace rapidjson_simd; template void TestSkipWhitespace() { - for (int step = 1; step < 32; step++) { + for (size_t step = 1; step < 32; step++) { char buffer[1025]; for (size_t i = 0; i < 1024; i++) buffer[i] = " \t\r\n"[i % 4]; diff --git a/test/unittest/strtodtest.cpp b/test/unittest/strtodtest.cpp index dc2378b..1931653 100644 --- a/test/unittest/strtodtest.cpp +++ b/test/unittest/strtodtest.cpp @@ -99,13 +99,13 @@ TEST(Strtod, CheckApproximationCase) { EXPECT_EQ(49, hS_Exp5); BigInteger dS = BIGINTEGER_LITERAL(dInt); - dS.MultiplyPow5(dS_Exp5) <<= dS_Exp2; + dS.MultiplyPow5(static_cast(dS_Exp5)) <<= static_cast(dS_Exp2); BigInteger bS(bInt); - bS.MultiplyPow5(bS_Exp5) <<= bS_Exp2; + bS.MultiplyPow5(static_cast(bS_Exp5)) <<= static_cast(bS_Exp2); BigInteger hS(1); - hS.MultiplyPow5(hS_Exp5) <<= hS_Exp2; + hS.MultiplyPow5(static_cast(hS_Exp5)) <<= static_cast(hS_Exp2); EXPECT_TRUE(BIGINTEGER_LITERAL("203970822259994138521801764465966248930731085529088") == dS); EXPECT_TRUE(BIGINTEGER_LITERAL("203970822259994122305215569213032722473144531250000") == bS); diff --git a/test/unittest/unittest.cpp b/test/unittest/unittest.cpp index 4e3bc11..dd562a2 100644 --- a/test/unittest/unittest.cpp +++ b/test/unittest/unittest.cpp @@ -15,12 +15,14 @@ #include "unittest.h" #include "rapidjson/rapidjson.h" +AssertException::~AssertException() throw() {} + int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); std::cout << "RapidJSON v" << RAPIDJSON_VERSION_STRING << std::endl; -#if _MSC_VER +#ifdef _MSC_VER _CrtMemState memoryState = { 0 }; _CrtMemCheckpoint(&memoryState); //_CrtSetBreakAlloc(X); @@ -29,7 +31,7 @@ int main(int argc, char **argv) { int ret = RUN_ALL_TESTS(); -#if _MSC_VER +#ifdef _MSC_VER // Current gtest constantly leak 2 blocks at exit _CrtMemDumpAllObjectsSince(&memoryState); #endif diff --git a/test/unittest/unittest.h b/test/unittest/unittest.h index dbba754..2aaa8cd 100644 --- a/test/unittest/unittest.h +++ b/test/unittest/unittest.h @@ -15,10 +15,18 @@ #ifndef UNITTEST_H_ #define UNITTEST_H_ - // gtest indirectly included inttypes.h, without __STDC_CONSTANT_MACROS. #ifndef __STDC_CONSTANT_MACROS +#ifdef __clang__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wreserved-id-macro" +#endif + # define __STDC_CONSTANT_MACROS 1 // required by C++ standard + +#ifdef __clang__ +#pragma GCC diagnostic pop +#endif #endif #ifdef _MSC_VER @@ -41,6 +49,11 @@ #pragma GCC diagnostic pop #endif +#ifdef __clang__ +// All TEST() macro generated this warning, disable globally +#pragma GCC diagnostic ignored "-Wglobal-constructors" +#endif + template inline unsigned StrLen(const Ch* s) { const Ch* p = s; @@ -51,19 +64,19 @@ inline unsigned StrLen(const Ch* s) { template inline int StrCmp(const Ch* s1, const Ch* s2) { while(*s1 && (*s1 == *s2)) { s1++; s2++; } - return (unsigned)*s1 < (unsigned)*s2 ? -1 : (unsigned)*s1 > (unsigned)*s2; + return static_cast(*s1) < static_cast(*s2) ? -1 : static_cast(*s1) > static_cast(*s2); } template inline Ch* StrDup(const Ch* str) { size_t bufferSize = sizeof(Ch) * (StrLen(str) + 1); - Ch* buffer = (Ch*)malloc(bufferSize); + Ch* buffer = static_cast(malloc(bufferSize)); memcpy(buffer, str, bufferSize); return buffer; } inline FILE* TempFile(char *filename) { -#if _MSC_VER +#ifdef _MSC_VER filename = tmpnam(filename); // For Visual Studio, tmpnam() adds a backslash in front. Remove it. @@ -80,13 +93,14 @@ inline FILE* TempFile(char *filename) { } // Use exception for catching assert -#if _MSC_VER +#ifdef _MSC_VER #pragma warning(disable : 4127) #endif class AssertException : public std::logic_error { public: AssertException(const char* w) : std::logic_error(w) {} + virtual ~AssertException() throw(); }; #define RAPIDJSON_ASSERT(x) if (!(x)) throw AssertException(RAPIDJSON_STRINGIFY(x)) diff --git a/test/unittest/valuetest.cpp b/test/unittest/valuetest.cpp index 900783c..1ef877e 100644 --- a/test/unittest/valuetest.cpp +++ b/test/unittest/valuetest.cpp @@ -448,7 +448,7 @@ TEST(Value, Uint) { TEST(Value, Int64) { // Constructor with int - Value x(int64_t(1234LL)); + Value x(int64_t(1234)); EXPECT_EQ(kNumberType, x.GetType()); EXPECT_EQ(1234, x.GetInt()); EXPECT_EQ(1234u, x.GetUint()); @@ -469,7 +469,7 @@ TEST(Value, Int64) { EXPECT_FALSE(x.IsObject()); EXPECT_FALSE(x.IsArray()); - Value nx(int64_t(-1234LL)); + Value nx(int64_t(-1234)); EXPECT_EQ(-1234, nx.GetInt()); EXPECT_EQ(-1234, nx.GetInt64()); EXPECT_TRUE(nx.IsInt()); @@ -482,17 +482,17 @@ TEST(Value, Int64) { z.SetInt64(1234); EXPECT_EQ(1234, z.GetInt64()); - z.SetInt64(2147483648LL); // 2^31, cannot cast as int + z.SetInt64(2147483648); // 2^31, cannot cast as int EXPECT_FALSE(z.IsInt()); EXPECT_TRUE(z.IsUint()); EXPECT_NEAR(2147483648.0, z.GetDouble(), 0.0); - z.SetInt64(4294967296LL); // 2^32, cannot cast as uint + z.SetInt64(4294967296); // 2^32, cannot cast as uint EXPECT_FALSE(z.IsInt()); EXPECT_FALSE(z.IsUint()); EXPECT_NEAR(4294967296.0, z.GetDouble(), 0.0); - z.SetInt64(-2147483649LL); // -2^31-1, cannot cast as int + z.SetInt64(int64_t(-2147483648) - 1); // -2^31-1, cannot cast as int EXPECT_FALSE(z.IsInt()); EXPECT_NEAR(-2147483649.0, z.GetDouble(), 0.0); @@ -502,7 +502,7 @@ TEST(Value, Int64) { TEST(Value, Uint64) { // Constructor with int - Value x(uint64_t(1234LL)); + Value x(uint64_t(1234)); EXPECT_EQ(kNumberType, x.GetType()); EXPECT_EQ(1234, x.GetInt()); EXPECT_EQ(1234u, x.GetUint()); @@ -528,19 +528,19 @@ TEST(Value, Uint64) { z.SetUint64(1234); EXPECT_EQ(1234u, z.GetUint64()); - z.SetUint64(2147483648LL); // 2^31, cannot cast as int + z.SetUint64(uint64_t(2147483648)); // 2^31, cannot cast as int EXPECT_FALSE(z.IsInt()); EXPECT_TRUE(z.IsUint()); EXPECT_TRUE(z.IsInt64()); - z.SetUint64(4294967296LL); // 2^32, cannot cast as uint + z.SetUint64(uint64_t(4294967295) + 1); // 2^32, cannot cast as uint EXPECT_FALSE(z.IsInt()); EXPECT_FALSE(z.IsUint()); EXPECT_TRUE(z.IsInt64()); - z.SetUint64(9223372036854775808uLL); // 2^63 cannot cast as int64 + z.SetUint64(RAPIDJSON_UINT64_C2(0x80000000, 0x00000000)); // 2^63 cannot cast as int64 EXPECT_FALSE(z.IsInt64()); - EXPECT_EQ(9223372036854775808uLL, z.GetUint64()); // Issue 48 + EXPECT_EQ(RAPIDJSON_UINT64_C2(0x80000000, 0x00000000), z.GetUint64()); // Issue 48 EXPECT_DOUBLE_EQ(9223372036854775808.0, z.GetDouble()); } @@ -662,7 +662,7 @@ TEST(Value, String) { // SetString() char s[] = "World"; Value w; - w.SetString(s, (SizeType)strlen(s), allocator); + w.SetString(s, static_cast(strlen(s)), allocator); s[0] = '\0'; EXPECT_STREQ("World", w.GetString()); EXPECT_EQ(5u, w.GetStringLength()); @@ -841,23 +841,23 @@ TEST(Value, Array) { EXPECT_EQ(x.Begin(), itr); EXPECT_EQ(9u, x.Size()); for (int i = 0; i < 9; i++) - EXPECT_EQ(i + 1, x[i][0].GetInt()); + EXPECT_EQ(i + 1, x[static_cast(i)][0].GetInt()); // Ease the last itr = x.Erase(x.End() - 1); EXPECT_EQ(x.End(), itr); EXPECT_EQ(8u, x.Size()); for (int i = 0; i < 8; i++) - EXPECT_EQ(i + 1, x[i][0].GetInt()); + EXPECT_EQ(i + 1, x[static_cast(i)][0].GetInt()); // Erase the middle itr = x.Erase(x.Begin() + 4); EXPECT_EQ(x.Begin() + 4, itr); EXPECT_EQ(7u, x.Size()); for (int i = 0; i < 4; i++) - EXPECT_EQ(i + 1, x[i][0].GetInt()); + EXPECT_EQ(i + 1, x[static_cast(i)][0].GetInt()); for (int i = 4; i < 7; i++) - EXPECT_EQ(i + 2, x[i][0].GetInt()); + EXPECT_EQ(i + 2, x[static_cast(i)][0].GetInt()); // Erase(ValueIterator, ValueIterator) // Exhaustive test with all 0 <= first < n, first <= last <= n cases @@ -879,7 +879,7 @@ TEST(Value, Array) { for (unsigned i = 0; i < first; i++) EXPECT_EQ(i, x[i][0].GetUint()); for (unsigned i = first; i < n - removeCount; i++) - EXPECT_EQ(i + removeCount, x[i][0].GetUint()); + EXPECT_EQ(i + removeCount, x[static_cast(i)][0].GetUint()); } } @@ -896,7 +896,7 @@ TEST(Value, Array) { x.Erase(std::remove(x.Begin(), x.End(), null), x.End()); EXPECT_EQ(5u, x.Size()); for (int i = 0; i < 5; i++) - EXPECT_EQ(i * 2, x[i]); + EXPECT_EQ(i * 2, x[static_cast(i)]); // SetArray() Value z; @@ -935,8 +935,8 @@ TEST(Value, Object) { o.AddMember("false", false, allocator); o.AddMember("int", -1, allocator); o.AddMember("uint", 1u, allocator); - o.AddMember("int64", INT64_C(-4294967296), allocator); - o.AddMember("uint64", UINT64_C(4294967296), allocator); + o.AddMember("int64", int64_t(-4294967296), allocator); + o.AddMember("uint64", uint64_t(4294967296), allocator); o.AddMember("double", 3.14, allocator); o.AddMember("string", "Jelly", allocator); @@ -944,8 +944,8 @@ TEST(Value, Object) { EXPECT_FALSE(o["false"].GetBool()); EXPECT_EQ(-1, o["int"].GetInt()); EXPECT_EQ(1u, o["uint"].GetUint()); - EXPECT_EQ(INT64_C(-4294967296), o["int64"].GetInt64()); - EXPECT_EQ(UINT64_C(4294967296), o["uint64"].GetUint64()); + EXPECT_EQ(int64_t(-4294967296), o["int64"].GetInt64()); + EXPECT_EQ(uint64_t(4294967296), o["uint64"].GetUint64()); EXPECT_STREQ("Jelly",o["string"].GetString()); EXPECT_EQ(8u, o.MemberCount()); } @@ -1125,7 +1125,7 @@ TEST(Value, Object) { EXPECT_EQ(x.MemberBegin(), itr); EXPECT_EQ(9u, x.MemberCount()); for (; itr != x.MemberEnd(); ++itr) { - int i = (itr - x.MemberBegin()) + 1; + size_t i = static_cast((itr - x.MemberBegin())) + 1; EXPECT_STREQ(itr->name.GetString(), keys[i]); EXPECT_EQ(i, itr->value[0].GetInt()); } @@ -1136,7 +1136,7 @@ TEST(Value, Object) { EXPECT_EQ(x.MemberEnd(), itr); EXPECT_EQ(8u, x.MemberCount()); for (; itr != x.MemberEnd(); ++itr) { - int i = (itr - x.MemberBegin()) + 1; + size_t i = static_cast(itr - x.MemberBegin()) + 1; EXPECT_STREQ(itr->name.GetString(), keys[i]); EXPECT_EQ(i, itr->value[0].GetInt()); } @@ -1147,8 +1147,8 @@ TEST(Value, Object) { EXPECT_EQ(x.MemberBegin() + 4, itr); EXPECT_EQ(7u, x.MemberCount()); for (; itr != x.MemberEnd(); ++itr) { - int i = (itr - x.MemberBegin()); - i += (i<4) ? 1 : 2; + size_t i = static_cast(itr - x.MemberBegin()); + i += (i < 4) ? 1 : 2; EXPECT_STREQ(itr->name.GetString(), keys[i]); EXPECT_EQ(i, itr->value[0].GetInt()); } @@ -1214,7 +1214,7 @@ TEST(Value, BigNestedArray) { for (SizeType i = 0; i < n; i++) { Value y(kArrayType); for (SizeType j = 0; j < n; j++) { - Value number((int)(i * n + j)); + Value number(static_cast(i * n + j)); y.PushBack(number, allocator); } x.PushBack(y, allocator); @@ -1223,7 +1223,7 @@ TEST(Value, BigNestedArray) { for (SizeType i = 0; i < n; i++) for (SizeType j = 0; j < n; j++) { EXPECT_TRUE(x[i][j].IsInt()); - EXPECT_EQ((int)(i * n + j), x[i][j].GetInt()); + EXPECT_EQ(static_cast(i * n + j), x[i][j].GetInt()); } } @@ -1237,16 +1237,16 @@ TEST(Value, BigNestedObject) { sprintf(name1, "%d", i); // Value name(name1); // should not compile - Value name(name1, (SizeType)strlen(name1), allocator); + Value name(name1, static_cast(strlen(name1)), allocator); Value object(kObjectType); for (SizeType j = 0; j < n; j++) { char name2[10]; sprintf(name2, "%d", j); - Value name(name2, (SizeType)strlen(name2), allocator); - Value number((int)(i * n + j)); - object.AddMember(name, number, allocator); + Value name3(name2, static_cast(strlen(name2)), allocator); + Value number(static_cast(i * n + j)); + object.AddMember(name3, number, allocator); } // x.AddMember(name1, object, allocator); // should not compile @@ -1261,7 +1261,7 @@ TEST(Value, BigNestedObject) { char name2[10]; sprintf(name2, "%d", j); x[name1]; - EXPECT_EQ((int)(i * n + j), x[name1][name2].GetInt()); + EXPECT_EQ(static_cast(i * n + j), x[name1][name2].GetInt()); } } } @@ -1293,7 +1293,7 @@ TEST(Document, CrtAllocator) { } static void TestShortStringOptimization(const char* str) { - const rapidjson::SizeType len = (rapidjson::SizeType)strlen(str); + const rapidjson::SizeType len = static_cast(strlen(str)); rapidjson::Document doc; rapidjson::Value val; From 17f2ca6913c60618196e2e93d36100dc237c60db Mon Sep 17 00:00:00 2001 From: Milo Yip Date: Fri, 18 Dec 2015 19:04:09 +0800 Subject: [PATCH 178/189] Try to fix clang and gcc warnings problems --- include/rapidjson/document.h | 10 +++------- include/rapidjson/reader.h | 13 +++---------- test/unittest/unittest.h | 2 ++ 3 files changed, 8 insertions(+), 17 deletions(-) diff --git a/include/rapidjson/document.h b/include/rapidjson/document.h index 8fde16c..dc40239 100644 --- a/include/rapidjson/document.h +++ b/include/rapidjson/document.h @@ -30,6 +30,7 @@ RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant #ifdef __clang__ RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_OFF(padded) +RAPIDJSON_DIAG_OFF(switch-enum) #endif #ifdef __GNUC__ @@ -724,9 +725,7 @@ public: else return data_.n.u64 == rhs.data_.n.u64; - case kNullType: - case kFalseType: - case kTrueType: + default: return true; } } @@ -2106,10 +2105,7 @@ GenericValue::GenericValue(const GenericValue(&rhs.data_); break; diff --git a/include/rapidjson/reader.h b/include/rapidjson/reader.h index 4cb7d50..b704154 100644 --- a/include/rapidjson/reader.h +++ b/include/rapidjson/reader.h @@ -42,6 +42,7 @@ RAPIDJSON_DIAG_OFF(4702) // unreachable code #ifdef __clang__ RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_OFF(padded) +RAPIDJSON_DIAG_OFF(switch-enum) #endif #ifdef __GNUC__ @@ -1417,9 +1418,7 @@ private: } } - case IterativeParsingStartState: - case IterativeParsingFinishState: - case IterativeParsingValueState: + default: // This branch is for IterativeParsingValueState actually. // Use `default:` rather than // `case IterativeParsingValueState:` is for code coverage. @@ -1456,13 +1455,7 @@ private: case IterativeParsingMemberKeyState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissColon, is.Tell()); return; case IterativeParsingMemberValueState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell()); return; case IterativeParsingElementState: RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell()); return; - case IterativeParsingErrorState: - case IterativeParsingKeyValueDelimiterState: - case IterativeParsingObjectFinishState: - case IterativeParsingArrayInitialState: - case IterativeParsingElementDelimiterState: - case IterativeParsingArrayFinishState: - case IterativeParsingValueState: RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell()); return; + default: RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell()); return; } } diff --git a/test/unittest/unittest.h b/test/unittest/unittest.h index 2aaa8cd..6062410 100644 --- a/test/unittest/unittest.h +++ b/test/unittest/unittest.h @@ -19,8 +19,10 @@ #ifndef __STDC_CONSTANT_MACROS #ifdef __clang__ #pragma GCC diagnostic push +#if __has_warning("-Wreserved-id-macro") #pragma GCC diagnostic ignored "-Wreserved-id-macro" #endif +#endif # define __STDC_CONSTANT_MACROS 1 // required by C++ standard From 9ce381b80165095b79f7ab3475a4a544cde73f4e Mon Sep 17 00:00:00 2001 From: Milo Yip Date: Fri, 18 Dec 2015 19:15:51 +0800 Subject: [PATCH 179/189] Try to fix clang and gcc warnings problems again --- example/messagereader/messagereader.cpp | 16 ++++++++++++---- include/rapidjson/document.h | 3 ++- include/rapidjson/error/en.h | 13 ++++++++++++- include/rapidjson/filereadstream.h | 1 + include/rapidjson/filewritestream.h | 9 +++++++++ 5 files changed, 36 insertions(+), 6 deletions(-) diff --git a/example/messagereader/messagereader.cpp b/example/messagereader/messagereader.cpp index d19292b..3399bc9 100644 --- a/example/messagereader/messagereader.cpp +++ b/example/messagereader/messagereader.cpp @@ -17,6 +17,11 @@ RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_OFF(effc++) #endif +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(switch-enum) +#endif + struct MessageHandler : public BaseReaderHandler, MessageHandler> { MessageHandler() : messages_(), state_(kExpectObjectStart), name_() {} @@ -26,16 +31,13 @@ struct MessageHandler case kExpectObjectStart: state_ = kExpectNameOrObjectEnd; return true; - case kExpectNameOrObjectEnd: - case kExpectValue: + default: return false; } } bool String(const char* str, SizeType length, bool) { switch (state_) { - case kExpectObjectStart: - return false; case kExpectNameOrObjectEnd: name_ = string(str, length); state_ = kExpectValue; @@ -44,6 +46,8 @@ struct MessageHandler messages_.insert(MessageMap::value_type(name_, string(str, length))); state_ = kExpectNameOrObjectEnd; return true; + default: + return false; } } @@ -64,6 +68,10 @@ struct MessageHandler RAPIDJSON_DIAG_POP #endif +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif + static void ParseMessages(const char* json, MessageMap& messages) { Reader reader; MessageHandler handler; diff --git a/include/rapidjson/document.h b/include/rapidjson/document.h index dc40239..3838af9 100644 --- a/include/rapidjson/document.h +++ b/include/rapidjson/document.h @@ -1557,7 +1557,8 @@ public: case kStringType: return handler.String(GetString(), GetStringLength(), (flags_ & kCopyFlag) != 0); - case kNumberType: + default: + RAPIDJSON_ASSERT(GetType() == kNumberType); if (IsInt()) return handler.Int(data_.n.i.i); else if (IsUint()) return handler.Uint(data_.n.u.u); else if (IsInt64()) return handler.Int64(data_.n.i64); diff --git a/include/rapidjson/error/en.h b/include/rapidjson/error/en.h index 81932e2..c2315fd 100644 --- a/include/rapidjson/error/en.h +++ b/include/rapidjson/error/en.h @@ -17,6 +17,12 @@ #include "error.h" +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(switch-enum) +RAPIDJSON_DIAG_OFF(covered-switch-default) +#endif + RAPIDJSON_NAMESPACE_BEGIN //! Maps error code of parsing into error message. @@ -54,10 +60,15 @@ inline const RAPIDJSON_ERROR_CHARTYPE* GetParseError_En(ParseErrorCode parseErro case kParseErrorTermination: 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."); } - return RAPIDJSON_ERROR_STRING("Unknown error."); } RAPIDJSON_NAMESPACE_END +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif + #endif // RAPIDJSON_ERROR_EN_H_ diff --git a/include/rapidjson/filereadstream.h b/include/rapidjson/filereadstream.h index 588f7f1..b6d6524 100644 --- a/include/rapidjson/filereadstream.h +++ b/include/rapidjson/filereadstream.h @@ -21,6 +21,7 @@ #ifdef __clang__ RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_OFF(padded) +RAPIDJSON_DIAG_OFF(unreachable-code) #endif RAPIDJSON_NAMESPACE_BEGIN diff --git a/include/rapidjson/filewritestream.h b/include/rapidjson/filewritestream.h index 55da265..3c38329 100644 --- a/include/rapidjson/filewritestream.h +++ b/include/rapidjson/filewritestream.h @@ -18,6 +18,11 @@ #include "rapidjson.h" #include +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(unreachable-code) +#endif + RAPIDJSON_NAMESPACE_BEGIN //! Wrapper of C file stream for input using fread(). @@ -92,4 +97,8 @@ inline void PutN(FileWriteStream& stream, char c, size_t n) { RAPIDJSON_NAMESPACE_END +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif + #endif // RAPIDJSON_FILESTREAM_H_ From a6a73b51b5753866f513b029fa721081521c1a9e Mon Sep 17 00:00:00 2001 From: Milo Yip Date: Fri, 18 Dec 2015 19:36:51 +0800 Subject: [PATCH 180/189] Try to fix clang and gcc warnings problems againx2 --- include/rapidjson/memorystream.h | 9 +++++++++ include/rapidjson/pointer.h | 31 ++++++++++++++----------------- 2 files changed, 23 insertions(+), 17 deletions(-) diff --git a/include/rapidjson/memorystream.h b/include/rapidjson/memorystream.h index 03c04e8..dfaec37 100644 --- a/include/rapidjson/memorystream.h +++ b/include/rapidjson/memorystream.h @@ -17,6 +17,11 @@ #include "rapidjson.h" +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(unreachable-code) +#endif + RAPIDJSON_NAMESPACE_BEGIN //! Represents an in-memory input byte stream. @@ -58,4 +63,8 @@ struct MemoryStream { RAPIDJSON_NAMESPACE_END +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif + #endif // RAPIDJSON_MEMORYBUFFER_H_ diff --git a/include/rapidjson/pointer.h b/include/rapidjson/pointer.h index f58ce35..7519490 100644 --- a/include/rapidjson/pointer.h +++ b/include/rapidjson/pointer.h @@ -18,6 +18,11 @@ #include "document.h" #include "internal/itoa.h" +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(switch-enum) +#endif + RAPIDJSON_NAMESPACE_BEGIN static const SizeType kPointerInvalidIndex = ~SizeType(0); //!< Represents an invalid index in GenericPointer::Token @@ -71,7 +76,7 @@ template class GenericPointer { public: typedef typename ValueType::EncodingType EncodingType; //!< Encoding type from Value - typedef typename EncodingType::Ch Ch; //!< Character type from Value + typedef typename ValueType::Ch Ch; //!< Character type from Value //! A token is the basic units of internal representation. /*! @@ -472,11 +477,7 @@ public: return 0; v = &((*v)[t->index]); break; - case kNullType: - case kFalseType: - case kTrueType: - case kStringType: - case kNumberType: + default: return 0; } } @@ -705,11 +706,7 @@ public: return false; v = &((*v)[t->index]); break; - case kNullType: - case kFalseType: - case kTrueType: - case kStringType: - case kNumberType: + default: return false; } } @@ -722,11 +719,7 @@ public: return false; v->Erase(v->Begin() + last->index); return true; - case kNullType: - case kFalseType: - case kTrueType: - case kStringType: - case kNumberType: + default: return false; } } @@ -958,7 +951,7 @@ private: */ class PercentDecodeStream { public: - typedef Ch Ch; + typedef typename ValueType::Ch Ch; //! Constructor /*! @@ -1326,4 +1319,8 @@ bool EraseValueByPointer(T& root, const CharType(&source)[N]) { RAPIDJSON_NAMESPACE_END +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif + #endif // RAPIDJSON_POINTER_H_ From 4cb7c88ca901d4cca62675452ca2b1437702e1ec Mon Sep 17 00:00:00 2001 From: Milo Yip Date: Fri, 18 Dec 2015 19:47:11 +0800 Subject: [PATCH 181/189] Try to fix clang and gcc warnings problems again x3 --- test/unittest/readertest.cpp | 4 ++-- test/unittest/strtodtest.cpp | 9 +++++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/test/unittest/readertest.cpp b/test/unittest/readertest.cpp index 056ccb4..6285181 100644 --- a/test/unittest/readertest.cpp +++ b/test/unittest/readertest.cpp @@ -164,12 +164,12 @@ TEST(Reader, ParseNumber_Integer) { u.u |= r(); char buffer[32]; - if (u.u > 4294967295) { + if (u.u > uint64_t(4294967295u)) { *internal::u64toa(u.u, buffer) = '\0'; TEST_INTEGER(ParseUint64Handler, buffer, u.u); } - if (u.i < -2147483648) { + if (u.i < -int64_t(2147483648u)) { *internal::i64toa(u.i, buffer) = '\0'; TEST_INTEGER(ParseInt64Handler, buffer, u.i); } diff --git a/test/unittest/strtodtest.cpp b/test/unittest/strtodtest.cpp index 1931653..a42d96e 100644 --- a/test/unittest/strtodtest.cpp +++ b/test/unittest/strtodtest.cpp @@ -16,6 +16,11 @@ #include "rapidjson/internal/strtod.h" +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(unreachable-code) +#endif + #define BIGINTEGER_LITERAL(s) BigInteger(s, sizeof(s) - 1) using namespace rapidjson::internal; @@ -121,3 +126,7 @@ TEST(Strtod, CheckApproximationCase) { EXPECT_EQ(-1, delta.Compare(hS)); } + +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif From d6478991d078eee2c0a48bca493810e6adf81ab6 Mon Sep 17 00:00:00 2001 From: Milo Yip Date: Fri, 18 Dec 2015 19:54:10 +0800 Subject: [PATCH 182/189] Try to fix clang and gcc warnings problems again x4 --- include/rapidjson/filereadstream.h | 4 ++-- test/unittest/readertest.cpp | 4 ++-- test/unittest/valuetest.cpp | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/include/rapidjson/filereadstream.h b/include/rapidjson/filereadstream.h index b6d6524..a31d7c0 100644 --- a/include/rapidjson/filereadstream.h +++ b/include/rapidjson/filereadstream.h @@ -51,8 +51,8 @@ public: size_t Tell() const { return count_ + static_cast(current_ - buffer_); } // Not implemented - void Put(Ch) RAPIDJSON_NORETURN_SUFFIX { RAPIDJSON_ASSERT(false); } - void Flush() RAPIDJSON_NORETURN_SUFFIX { RAPIDJSON_ASSERT(false); } + void Put(Ch) { RAPIDJSON_ASSERT(false); } + void Flush() { RAPIDJSON_ASSERT(false); } Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } diff --git a/test/unittest/readertest.cpp b/test/unittest/readertest.cpp index 6285181..3248a5d 100644 --- a/test/unittest/readertest.cpp +++ b/test/unittest/readertest.cpp @@ -1040,8 +1040,8 @@ public: size_t Tell() const { return static_cast(is_.tellg()); } Ch* PutBegin() { assert(false); return 0; } - void Put(Ch) RAPIDJSON_NORETURN_SUFFIX { assert(false); } - void Flush() RAPIDJSON_NORETURN_SUFFIX { assert(false); } + void Put(Ch) { assert(false); } + void Flush() { assert(false); } size_t PutEnd(Ch*) { assert(false); return 0; } private: diff --git a/test/unittest/valuetest.cpp b/test/unittest/valuetest.cpp index 1ef877e..cac450c 100644 --- a/test/unittest/valuetest.cpp +++ b/test/unittest/valuetest.cpp @@ -482,12 +482,12 @@ TEST(Value, Int64) { z.SetInt64(1234); EXPECT_EQ(1234, z.GetInt64()); - z.SetInt64(2147483648); // 2^31, cannot cast as int + z.SetInt64(2147483648u); // 2^31, cannot cast as int EXPECT_FALSE(z.IsInt()); EXPECT_TRUE(z.IsUint()); EXPECT_NEAR(2147483648.0, z.GetDouble(), 0.0); - z.SetInt64(4294967296); // 2^32, cannot cast as uint + z.SetInt64(int64_t(4294967298u) + 1); // 2^32, cannot cast as uint EXPECT_FALSE(z.IsInt()); EXPECT_FALSE(z.IsUint()); EXPECT_NEAR(4294967296.0, z.GetDouble(), 0.0); @@ -528,12 +528,12 @@ TEST(Value, Uint64) { z.SetUint64(1234); EXPECT_EQ(1234u, z.GetUint64()); - z.SetUint64(uint64_t(2147483648)); // 2^31, cannot cast as int + z.SetUint64(uint64_t(2147483648u)); // 2^31, cannot cast as int EXPECT_FALSE(z.IsInt()); EXPECT_TRUE(z.IsUint()); EXPECT_TRUE(z.IsInt64()); - z.SetUint64(uint64_t(4294967295) + 1); // 2^32, cannot cast as uint + z.SetUint64(uint64_t(4294967295u) + 1); // 2^32, cannot cast as uint EXPECT_FALSE(z.IsInt()); EXPECT_FALSE(z.IsUint()); EXPECT_TRUE(z.IsInt64()); From 6e08e760fc2ab9a91c2a0e56b49c4fa16b036375 Mon Sep 17 00:00:00 2001 From: Milo Yip Date: Fri, 18 Dec 2015 19:57:43 +0800 Subject: [PATCH 183/189] Try to fix clang and gcc warnings problems again x5 --- include/rapidjson/filereadstream.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/rapidjson/filereadstream.h b/include/rapidjson/filereadstream.h index a31d7c0..b6d6524 100644 --- a/include/rapidjson/filereadstream.h +++ b/include/rapidjson/filereadstream.h @@ -51,8 +51,8 @@ public: size_t Tell() const { return count_ + static_cast(current_ - buffer_); } // Not implemented - void Put(Ch) { RAPIDJSON_ASSERT(false); } - void Flush() { RAPIDJSON_ASSERT(false); } + void Put(Ch) RAPIDJSON_NORETURN_SUFFIX { RAPIDJSON_ASSERT(false); } + void Flush() RAPIDJSON_NORETURN_SUFFIX { RAPIDJSON_ASSERT(false); } Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } From d72039f3ef30ec2e63955d5159d87f5ac255cf21 Mon Sep 17 00:00:00 2001 From: Milo Yip Date: Fri, 18 Dec 2015 20:06:58 +0800 Subject: [PATCH 184/189] Try to fix clang and gcc warnings problems again x6 --- test/unittest/readertest.cpp | 4 ++-- test/unittest/valuetest.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/unittest/readertest.cpp b/test/unittest/readertest.cpp index 3248a5d..6285181 100644 --- a/test/unittest/readertest.cpp +++ b/test/unittest/readertest.cpp @@ -1040,8 +1040,8 @@ public: size_t Tell() const { return static_cast(is_.tellg()); } Ch* PutBegin() { assert(false); return 0; } - void Put(Ch) { assert(false); } - void Flush() { assert(false); } + void Put(Ch) RAPIDJSON_NORETURN_SUFFIX { assert(false); } + void Flush() RAPIDJSON_NORETURN_SUFFIX { assert(false); } size_t PutEnd(Ch*) { assert(false); return 0; } private: diff --git a/test/unittest/valuetest.cpp b/test/unittest/valuetest.cpp index cac450c..4e08e54 100644 --- a/test/unittest/valuetest.cpp +++ b/test/unittest/valuetest.cpp @@ -487,7 +487,7 @@ TEST(Value, Int64) { EXPECT_TRUE(z.IsUint()); EXPECT_NEAR(2147483648.0, z.GetDouble(), 0.0); - z.SetInt64(int64_t(4294967298u) + 1); // 2^32, cannot cast as uint + z.SetInt64(int64_t(4294967295u) + 1); // 2^32, cannot cast as uint EXPECT_FALSE(z.IsInt()); EXPECT_FALSE(z.IsUint()); EXPECT_NEAR(4294967296.0, z.GetDouble(), 0.0); From 6d6381f596f081097d123b24a2091ae4c29bef39 Mon Sep 17 00:00:00 2001 From: Milo Yip Date: Fri, 18 Dec 2015 20:15:11 +0800 Subject: [PATCH 185/189] Try to fix clang and gcc warnings problems again x7 --- include/rapidjson/document.h | 4 ++-- include/rapidjson/rapidjson.h | 2 +- test/unittest/valuetest.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/rapidjson/document.h b/include/rapidjson/document.h index 3838af9..095aa40 100644 --- a/include/rapidjson/document.h +++ b/include/rapidjson/document.h @@ -1231,7 +1231,7 @@ public: for (MemberIterator itr = pos; itr != last; ++itr) itr->~Member(); std::memmove(&*pos, &*last, static_cast(MemberEnd() - last) * sizeof(Member)); - data_.o.size -= (last - first); + data_.o.size -= static_cast(last - first); return pos; } @@ -1431,7 +1431,7 @@ public: for (ValueIterator itr = pos; itr != last; ++itr) itr->~GenericValue(); std::memmove(pos, last, static_cast(End() - last) * sizeof(GenericValue)); - data_.a.size -= (last - first); + data_.a.size -= static_cast(last - first); return pos; } diff --git a/include/rapidjson/rapidjson.h b/include/rapidjson/rapidjson.h index 41790cf..e3560b7 100644 --- a/include/rapidjson/rapidjson.h +++ b/include/rapidjson/rapidjson.h @@ -467,7 +467,7 @@ RAPIDJSON_NAMESPACE_END /////////////////////////////////////////////////////////////////////////////// // RAPIDJSON_NORETURN_SUFFIX -#if defined(__clang__) +#if defined(__clang__) && !defined(NDEBUG) #define RAPIDJSON_NORETURN_SUFFIX __attribute__ ((noreturn)) #else #define RAPIDJSON_NORETURN_SUFFIX diff --git a/test/unittest/valuetest.cpp b/test/unittest/valuetest.cpp index 4e08e54..8d0f762 100644 --- a/test/unittest/valuetest.cpp +++ b/test/unittest/valuetest.cpp @@ -492,7 +492,7 @@ TEST(Value, Int64) { EXPECT_FALSE(z.IsUint()); EXPECT_NEAR(4294967296.0, z.GetDouble(), 0.0); - z.SetInt64(int64_t(-2147483648) - 1); // -2^31-1, cannot cast as int + z.SetInt64(-int64_t(2147483648u) - 1); // -2^31-1, cannot cast as int EXPECT_FALSE(z.IsInt()); EXPECT_NEAR(-2147483649.0, z.GetDouble(), 0.0); From efdbdc601607759702790d1be0a69005eaf5e3b8 Mon Sep 17 00:00:00 2001 From: Milo Yip Date: Fri, 18 Dec 2015 20:26:34 +0800 Subject: [PATCH 186/189] Try to fix clang and gcc warnings problems again x8 --- include/rapidjson/reader.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/rapidjson/reader.h b/include/rapidjson/reader.h index b704154..107f525 100644 --- a/include/rapidjson/reader.h +++ b/include/rapidjson/reader.h @@ -306,7 +306,7 @@ inline const char *SkipWhitespace_SIMD(const char* p) { return p; // 16-byte align to the next boundary - const char* nextAligned = reinterpret_cast((reinterpret_cast(p) + 15) & ~15); + const char* nextAligned = reinterpret_cast((reinterpret_cast(p) + 15) & static_cast(~15)); while (p != nextAligned) if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t') ++p; @@ -320,18 +320,18 @@ inline const char *SkipWhitespace_SIMD(const char* p) { "\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r", "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"}; - const __m128i w0 = _mm_loadu_si128((const __m128i *)&whitespaces[0][0]); + const __m128i w0 = _mm_loadu_si128(reinterpret_cast(&whitespaces[0][0])); const __m128i w1 = _mm_loadu_si128((const __m128i *)&whitespaces[1][0]); const __m128i w2 = _mm_loadu_si128((const __m128i *)&whitespaces[2][0]); const __m128i w3 = _mm_loadu_si128((const __m128i *)&whitespaces[3][0]); for (;; p += 16) { - const __m128i s = _mm_load_si128((const __m128i *)p); + const __m128i s = _mm_load_si128(reinterpret_cast(p)); __m128i x = _mm_cmpeq_epi8(s, w0); x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w1)); x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w2)); x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w3)); - unsigned short r = (unsigned short)~_mm_movemask_epi8(x); + unsigned short r = static_cast(~_mm_movemask_epi8(x)); if (r != 0) { // some of characters may be non-whitespace #ifdef _MSC_VER // Find the index of first non-whitespace unsigned long offset; From 5c003f3ecb8c00d9ed7f8da16469e17cf1d82d8f Mon Sep 17 00:00:00 2001 From: Milo Yip Date: Fri, 18 Dec 2015 20:34:46 +0800 Subject: [PATCH 187/189] Try to fix clang and gcc warnings problems again x9 Abandon RAPIDJSON_NORETURN_SUFFIX --- include/rapidjson/filereadstream.h | 5 +++-- include/rapidjson/memorystream.h | 5 +++-- include/rapidjson/rapidjson.h | 9 --------- test/unittest/readertest.cpp | 5 +++-- 4 files changed, 9 insertions(+), 15 deletions(-) diff --git a/include/rapidjson/filereadstream.h b/include/rapidjson/filereadstream.h index b6d6524..6c8a86c 100644 --- a/include/rapidjson/filereadstream.h +++ b/include/rapidjson/filereadstream.h @@ -22,6 +22,7 @@ RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_OFF(padded) RAPIDJSON_DIAG_OFF(unreachable-code) +RAPIDJSON_DIAG_OFF(missing-noreturn) #endif RAPIDJSON_NAMESPACE_BEGIN @@ -51,8 +52,8 @@ public: size_t Tell() const { return count_ + static_cast(current_ - buffer_); } // Not implemented - void Put(Ch) RAPIDJSON_NORETURN_SUFFIX { RAPIDJSON_ASSERT(false); } - void Flush() RAPIDJSON_NORETURN_SUFFIX { RAPIDJSON_ASSERT(false); } + void Put(Ch) { RAPIDJSON_ASSERT(false); } + void Flush() { RAPIDJSON_ASSERT(false); } Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } diff --git a/include/rapidjson/memorystream.h b/include/rapidjson/memorystream.h index dfaec37..beed1ef 100644 --- a/include/rapidjson/memorystream.h +++ b/include/rapidjson/memorystream.h @@ -20,6 +20,7 @@ #ifdef __clang__ RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_OFF(unreachable-code) +RAPIDJSON_DIAG_OFF(missing-noreturn) #endif RAPIDJSON_NAMESPACE_BEGIN @@ -46,8 +47,8 @@ struct MemoryStream { size_t Tell() const { return static_cast(src_ - begin_); } Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } - void Put(Ch) RAPIDJSON_NORETURN_SUFFIX { RAPIDJSON_ASSERT(false); } - void Flush() RAPIDJSON_NORETURN_SUFFIX { RAPIDJSON_ASSERT(false); } + void Put(Ch) { RAPIDJSON_ASSERT(false); } + void Flush() { RAPIDJSON_ASSERT(false); } size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } // For encoding detection only. diff --git a/include/rapidjson/rapidjson.h b/include/rapidjson/rapidjson.h index e3560b7..d896a14 100644 --- a/include/rapidjson/rapidjson.h +++ b/include/rapidjson/rapidjson.h @@ -464,15 +464,6 @@ RAPIDJSON_NAMESPACE_END #endif // RAPIDJSON_DIAG_* -/////////////////////////////////////////////////////////////////////////////// -// RAPIDJSON_NORETURN_SUFFIX - -#if defined(__clang__) && !defined(NDEBUG) -#define RAPIDJSON_NORETURN_SUFFIX __attribute__ ((noreturn)) -#else -#define RAPIDJSON_NORETURN_SUFFIX -#endif - /////////////////////////////////////////////////////////////////////////////// // C++11 features diff --git a/test/unittest/readertest.cpp b/test/unittest/readertest.cpp index 6285181..f2a0be1 100644 --- a/test/unittest/readertest.cpp +++ b/test/unittest/readertest.cpp @@ -25,6 +25,7 @@ using namespace rapidjson; RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_OFF(effc++) RAPIDJSON_DIAG_OFF(float-equal) +RAPIDJSON_DIAG_OFF(missing-noreturn) #endif #ifdef __clang__ @@ -1040,8 +1041,8 @@ public: size_t Tell() const { return static_cast(is_.tellg()); } Ch* PutBegin() { assert(false); return 0; } - void Put(Ch) RAPIDJSON_NORETURN_SUFFIX { assert(false); } - void Flush() RAPIDJSON_NORETURN_SUFFIX { assert(false); } + void Put(Ch) { assert(false); } + void Flush() { assert(false); } size_t PutEnd(Ch*) { assert(false); return 0; } private: From 81c07721cbace6eee545d35d4bf9da30353092dc Mon Sep 17 00:00:00 2001 From: Milo Yip Date: Fri, 18 Dec 2015 20:38:08 +0800 Subject: [PATCH 188/189] Try to fix clang and gcc warnings problems again x10 --- include/rapidjson/reader.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/rapidjson/reader.h b/include/rapidjson/reader.h index 107f525..8628b53 100644 --- a/include/rapidjson/reader.h +++ b/include/rapidjson/reader.h @@ -321,9 +321,9 @@ inline const char *SkipWhitespace_SIMD(const char* p) { "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"}; const __m128i w0 = _mm_loadu_si128(reinterpret_cast(&whitespaces[0][0])); - const __m128i w1 = _mm_loadu_si128((const __m128i *)&whitespaces[1][0]); - const __m128i w2 = _mm_loadu_si128((const __m128i *)&whitespaces[2][0]); - const __m128i w3 = _mm_loadu_si128((const __m128i *)&whitespaces[3][0]); + const __m128i w1 = _mm_loadu_si128(reinterpret_cast(&whitespaces[1][0])); + const __m128i w2 = _mm_loadu_si128(reinterpret_cast(&whitespaces[2][0])); + const __m128i w3 = _mm_loadu_si128(reinterpret_cast(&whitespaces[3][0])); for (;; p += 16) { const __m128i s = _mm_load_si128(reinterpret_cast(p)); From c6384da75530996d07af6f0896c33e8fd973f319 Mon Sep 17 00:00:00 2001 From: Milo Yip Date: Fri, 18 Dec 2015 20:53:07 +0800 Subject: [PATCH 189/189] Try to fix clang and gcc warnings problems again x11 --- test/unittest/valuetest.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/unittest/valuetest.cpp b/test/unittest/valuetest.cpp index 8d0f762..245ccac 100644 --- a/test/unittest/valuetest.cpp +++ b/test/unittest/valuetest.cpp @@ -1162,11 +1162,11 @@ TEST(Value, Object) { for (unsigned i = 0; i < n; i++) x.AddMember(keys[i], Value(kArrayType).PushBack(i, allocator), allocator); - itr = x.EraseMember(x.MemberBegin() + first, x.MemberBegin() + last); + itr = x.EraseMember(x.MemberBegin() + static_cast(first), x.MemberBegin() + static_cast(last)); if (last == n) EXPECT_EQ(x.MemberEnd(), itr); else - EXPECT_EQ(x.MemberBegin() + first, itr); + EXPECT_EQ(x.MemberBegin() + static_cast(first), itr); size_t removeCount = last - first; EXPECT_EQ(n - removeCount, x.MemberCount());