diff --git a/.travis.yml b/.travis.yml index df821a7..783c052 100644 --- a/.travis.yml +++ b/.travis.yml @@ -20,7 +20,7 @@ env: before_install: - sudo apt-add-repository -y ppa:ubuntu-toolchain-r/test - sudo apt-get update -qq - - sudo apt-get install -y cmake valgrind g++-multilib libc6-dbg:i386 + - sudo apt-get install -y cmake valgrind g++-multilib libc6-dbg:i386 --allow-unauthenticated matrix: include: diff --git a/doc/internals.md b/doc/internals.md index 706f98c..81fe9c1 100644 --- a/doc/internals.md +++ b/doc/internals.md @@ -79,7 +79,7 @@ The following tables show the data layout of each type. The 32-bit/64-bit column | `unsigned u` | 32-bit unsigned integer |4 |4 | | (zero padding) | 0 |4 |4 | | (unused) | |4 |8 | -| `unsigned flags_` | `kNumberType kNumberFlag kUIntFlag kUInt64Flag ...` |4 |4 | +| `unsigned flags_` | `kNumberType kNumberFlag kUintFlag kUint64Flag ...` |4 |4 | | Number (Int64) | |32-bit|64-bit| |---------------------|-------------------------------------|:----:|:----:| diff --git a/doc/internals.zh-cn.md b/doc/internals.zh-cn.md index ca3d297..d414fc1 100644 --- a/doc/internals.zh-cn.md +++ b/doc/internals.zh-cn.md @@ -79,7 +79,7 @@ SAX 和 DOM API 都依赖于3个额外的概念:`Allocator`、`Encoding` 和 ` | `unsigned u` | 32位无符号整数 |4 |4 | | (零填充) | 0 |4 |4 | | (未使用) | |4 |8 | -| `unsigned flags_` | `kNumberType kNumberFlag kUIntFlag kUInt64Flag ...` |4 |4 | +| `unsigned flags_` | `kNumberType kNumberFlag kUintFlag kUint64Flag ...` |4 |4 | | Number (Int64) | | 32位 | 64位 | |---------------------|-------------------------------------|:----:|:----:| @@ -248,7 +248,7 @@ void SkipWhitespace(InputStream& is) { ## 整数到字符串的转换 {#itoa} -整数到字符串转换的朴素算法需要对每一个十进制位进行一次处罚。我们实现了若干版本并在 [itoa-benchmark](https://github.com/miloyip/itoa-benchmark) 中对它们进行了评估。 +整数到字符串转换的朴素算法需要对每一个十进制位进行一次除法。我们实现了若干版本并在 [itoa-benchmark](https://github.com/miloyip/itoa-benchmark) 中对它们进行了评估。 虽然 SSE2 版本是最快的,但它和第二快的 `branchlut` 差距不大。而且 `branchlut` 是纯C++实现,所以我们在 RapidJSON 中使用了 `branchlut`。 diff --git a/doc/sax.md b/doc/sax.md index 874361f..d42d043 100644 --- a/doc/sax.md +++ b/doc/sax.md @@ -37,7 +37,7 @@ Bool(false) Key("n", 1, true) Null() Key("i") -UInt(123) +Uint(123) Key("pi") Double(3.1416) Key("a") diff --git a/doc/sax.zh-cn.md b/doc/sax.zh-cn.md index 740c339..9b11e76 100644 --- a/doc/sax.zh-cn.md +++ b/doc/sax.zh-cn.md @@ -37,7 +37,7 @@ Bool(false) Key("n", 1, true) Null() Key("i") -UInt(123) +Uint(123) Key("pi") Double(3.1416) Key("a") @@ -91,7 +91,7 @@ void main() { } ~~~~~~~~~~ -注意 RapidJSON 使用模板去静态挷定 `Reader` 类型及处理器的类形,而不是使用含虚函数的类。这个范式可以通过把函数内联而改善性能。 +注意 RapidJSON 使用模板去静态挷定 `Reader` 类型及处理器的类型,而不是使用含虚函数的类。这个范式可以通过把函数内联而改善性能。 ## 处理器 {#Handler} diff --git a/doc/tutorial.md b/doc/tutorial.md index 3fa63c9..4bde2fa 100644 --- a/doc/tutorial.md +++ b/doc/tutorial.md @@ -82,7 +82,7 @@ JSON number type represents all numeric values. However, C++ needs more specific ~~~~~~~~~~cpp assert(document["i"].IsNumber()); -// In this case, IsUint()/IsInt64()/IsUInt64() also return true. +// In this case, IsUint()/IsInt64()/IsUint64() also return true. assert(document["i"].IsInt()); printf("i = %d\n", document["i"].GetInt()); // Alternative (int)document["i"] diff --git a/doc/tutorial.zh-cn.md b/doc/tutorial.zh-cn.md index 3bacfb0..8b24ff1 100644 --- a/doc/tutorial.zh-cn.md +++ b/doc/tutorial.zh-cn.md @@ -82,7 +82,7 @@ JSON Number 类型表示所有数值。然而,C++ 需要使用更专门的类 ~~~~~~~~~~cpp assert(document["i"].IsNumber()); -// 在此情况下,IsUint()/IsInt64()/IsUInt64() 也会返回 true +// 在此情况下,IsUint()/IsInt64()/IsUint64() 也会返回 true assert(document["i"].IsInt()); printf("i = %d\n", document["i"].GetInt()); // 另一种用法: (int)document["i"] @@ -447,7 +447,7 @@ contact.PushBack(val, document.GetAllocator()); ~~~~~~~~~~ ## 修改 Object {#ModifyObject} -Object 是键值对的集合。每个键必须为 String。要修改 Object,方法是增加或移除成员。以下的 API 用来增加城员: +Object 是键值对的集合。每个键必须为 String。要修改 Object,方法是增加或移除成员。以下的 API 用来增加成员: * `Value& AddMember(Value&, Value&, Allocator& allocator)` * `Value& AddMember(StringRefType, Value&, Allocator&)` diff --git a/example/tutorial/tutorial.cpp b/example/tutorial/tutorial.cpp index c8bfcc1..d6021c6 100644 --- a/example/tutorial/tutorial.cpp +++ b/example/tutorial/tutorial.cpp @@ -57,7 +57,7 @@ int main(int, char*[]) { printf("n = %s\n", document["n"].IsNull() ? "null" : "?"); assert(document["i"].IsNumber()); // Number is a JSON type, but C++ needs more specific type. - assert(document["i"].IsInt()); // In this case, IsUint()/IsInt64()/IsUInt64() also return true. + assert(document["i"].IsInt()); // In this case, IsUint()/IsInt64()/IsUint64() also return true. printf("i = %d\n", document["i"].GetInt()); // Alternative (int)document["i"] assert(document["pi"].IsNumber()); diff --git a/include/rapidjson/document.h b/include/rapidjson/document.h index 9783fe4..f070234 100644 --- a/include/rapidjson/document.h +++ b/include/rapidjson/document.h @@ -63,15 +63,45 @@ class GenericDocument; https://code.google.com/p/rapidjson/issues/detail?id=64 */ template -struct GenericMember { +class GenericMember { +public: GenericValue name; //!< name of member (must be a string) GenericValue value; //!< value of member. +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + //! Move constructor in C++11 + GenericMember(GenericMember&& rhs) RAPIDJSON_NOEXCEPT + : name(std::move(rhs.name)), + value(std::move(rhs.value)) + { + } + + //! Move assignment in C++11 + GenericMember& operator=(GenericMember&& rhs) RAPIDJSON_NOEXCEPT { + return *this = static_cast(rhs); + } +#endif + + //! Assignment with move semantics. + /*! \param rhs Source of the assignment. Its name and value will become a null value after assignment. + */ + GenericMember& operator=(GenericMember& rhs) RAPIDJSON_NOEXCEPT { + if (RAPIDJSON_LIKELY(this != &rhs)) { + name = rhs.name; + value = rhs.value; + } + return *this; + } + // swap() for std::sort() and other potential use in STL. friend inline void swap(GenericMember& a, GenericMember& b) RAPIDJSON_NOEXCEPT { a.name.Swap(b.name); a.value.Swap(b.value); } + +private: + //! Copy constructor is not permitted. + GenericMember(const GenericMember& rhs); }; /////////////////////////////////////////////////////////////////////////////// diff --git a/include/rapidjson/fwd.h b/include/rapidjson/fwd.h index e8104e8..b74a2b8 100644 --- a/include/rapidjson/fwd.h +++ b/include/rapidjson/fwd.h @@ -102,7 +102,7 @@ class PrettyWriter; // document.h template -struct GenericMember; +class GenericMember; template class GenericMemberIterator; diff --git a/include/rapidjson/internal/regex.h b/include/rapidjson/internal/regex.h index 16e3559..af7e06d 100644 --- a/include/rapidjson/internal/regex.h +++ b/include/rapidjson/internal/regex.h @@ -23,7 +23,6 @@ RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_OFF(padded) RAPIDJSON_DIAG_OFF(switch-enum) -RAPIDJSON_DIAG_OFF(implicit-fallthrough) #elif defined(_MSC_VER) RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated @@ -32,9 +31,6 @@ RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated #ifdef __GNUC__ RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_OFF(effc++) -#if __GNUC__ >= 7 -RAPIDJSON_DIAG_OFF(implicit-fallthrough) -#endif #endif #ifndef RAPIDJSON_REGEX_VERBOSE @@ -291,6 +287,7 @@ private: if (!CharacterEscape(ds, &codepoint)) return; // Unsupported escape character // fall through to default + RAPIDJSON_DELIBERATE_FALLTHROUGH; default: // Pattern character PushOperand(operandStack, codepoint); @@ -520,6 +517,7 @@ private: else if (!CharacterEscape(ds, &codepoint)) return false; // fall through to default + RAPIDJSON_DELIBERATE_FALLTHROUGH; default: switch (step) { @@ -529,6 +527,7 @@ private: break; } // fall through to step 0 for other characters + RAPIDJSON_DELIBERATE_FALLTHROUGH; case 0: { diff --git a/include/rapidjson/pointer.h b/include/rapidjson/pointer.h index 063abab..b8143b6 100644 --- a/include/rapidjson/pointer.h +++ b/include/rapidjson/pointer.h @@ -488,10 +488,11 @@ public: v = &((*v)[t->index]); } else { - typename ValueType::MemberIterator m = v->FindMember(GenericStringRef(t->name, t->length)); + typename ValueType::MemberIterator m = v->FindMember(GenericValue(GenericStringRef(t->name, t->length))); if (m == v->MemberEnd()) { v->AddMember(ValueType(t->name, t->length, allocator).Move(), ValueType().Move(), allocator); - v = &(--v->MemberEnd())->value; // Assumes AddMember() appends at the end + m = v->MemberEnd(); + v = &(--m)->value; // Assumes AddMember() appends at the end exist = false; } else @@ -543,7 +544,7 @@ public: switch (v->GetType()) { case kObjectType: { - typename ValueType::MemberIterator m = v->FindMember(GenericStringRef(t->name, t->length)); + typename ValueType::MemberIterator m = v->FindMember(GenericValue(GenericStringRef(t->name, t->length))); if (m == v->MemberEnd()) break; v = &m->value; @@ -779,7 +780,7 @@ public: switch (v->GetType()) { case kObjectType: { - typename ValueType::MemberIterator m = v->FindMember(GenericStringRef(t->name, t->length)); + typename ValueType::MemberIterator m = v->FindMember(GenericValue(GenericStringRef(t->name, t->length))); if (m == v->MemberEnd()) return false; v = &m->value; diff --git a/include/rapidjson/rapidjson.h b/include/rapidjson/rapidjson.h index 62b079f..b71ea79 100644 --- a/include/rapidjson/rapidjson.h +++ b/include/rapidjson/rapidjson.h @@ -597,6 +597,19 @@ RAPIDJSON_NAMESPACE_END #endif #endif // RAPIDJSON_HAS_CXX11_RANGE_FOR +/////////////////////////////////////////////////////////////////////////////// +// C++17 features + +#if defined(__has_cpp_attribute) +# if __has_cpp_attribute(fallthrough) +# define RAPIDJSON_DELIBERATE_FALLTHROUGH [[fallthrough]] +# else +# define RAPIDJSON_DELIBERATE_FALLTHROUGH +# endif +#else +# define RAPIDJSON_DELIBERATE_FALLTHROUGH +#endif + //!@endcond //! Assertion (in non-throwing contexts). diff --git a/include/rapidjson/schema.h b/include/rapidjson/schema.h index 26ae947..1ff8883 100644 --- a/include/rapidjson/schema.h +++ b/include/rapidjson/schema.h @@ -899,7 +899,7 @@ public: } } - SizeType index; + SizeType index = 0; if (FindPropertyIndex(ValueType(str, len).Move(), &index)) { if (context.patternPropertiesSchemaCount > 0) { context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = properties_[index].schema; diff --git a/test/unittest/pointertest.cpp b/test/unittest/pointertest.cpp index 858fd2a..4629f76 100644 --- a/test/unittest/pointertest.cpp +++ b/test/unittest/pointertest.cpp @@ -674,6 +674,9 @@ TEST(Pointer, Get) { EXPECT_EQ(2u, unresolvedTokenIndex); EXPECT_TRUE(Pointer("/foo/0/a").Get(d, &unresolvedTokenIndex) == 0); // "/foo/0" is an string, cannot further query EXPECT_EQ(2u, unresolvedTokenIndex); + + Pointer::Token tokens[] = { { "foo ...", 3, kPointerInvalidIndex } }; + EXPECT_EQ(&d["foo"], Pointer(tokens, 1).Get(d)); } TEST(Pointer, GetWithDefault) { diff --git a/travis-doxygen.sh b/travis-doxygen.sh index 38e4eb6..cf18dc3 100755 --- a/travis-doxygen.sh +++ b/travis-doxygen.sh @@ -4,9 +4,8 @@ set -e -DOXYGEN_VER=doxygen-1.8.15 -DOXYGEN_TAR=${DOXYGEN_VER}.linux.bin.tar.gz -DOXYGEN_URL="http://doxygen.nl/files/${DOXYGEN_TAR}" +DOXYGEN_VER=1_8_16 +DOXYGEN_URL="https://codeload.github.com/doxygen/doxygen/tar.gz/Release_${DOXYGEN_VER}" : ${GITHUB_REPO:="Tencent/rapidjson"} GITHUB_HOST="github.com" @@ -47,9 +46,17 @@ abort() { # install doxygen binary distribution doxygen_install() { - wget -O - "${DOXYGEN_URL}" | \ - tar xz -C ${TMPDIR-/tmp} ${DOXYGEN_VER}/bin/doxygen - export PATH="${TMPDIR-/tmp}/${DOXYGEN_VER}/bin:$PATH" + cd ${TMPDIR-/tmp} + curl ${DOXYGEN_URL} -o doxygen.tar.gz + tar zxvf doxygen.tar.gz + mkdir doxygen_build + cd doxygen_build + cmake ../doxygen-Release_${DOXYGEN_VER}/ + make + + export PATH="${TMPDIR-/tmp}/doxygen_build/bin:$PATH" + + cd ../../ } doxygen_run()