This commit is contained in:
Charles Milette 2019-10-31 21:10:28 -04:00
commit e54aca7006
No known key found for this signature in database
GPG Key ID: 1A5AE81377AD973A
16 changed files with 81 additions and 28 deletions

View File

@ -20,7 +20,7 @@ env:
before_install: before_install:
- sudo apt-add-repository -y ppa:ubuntu-toolchain-r/test - sudo apt-add-repository -y ppa:ubuntu-toolchain-r/test
- sudo apt-get update -qq - 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: matrix:
include: include:

View File

@ -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 | | `unsigned u` | 32-bit unsigned integer |4 |4 |
| (zero padding) | 0 |4 |4 | | (zero padding) | 0 |4 |4 |
| (unused) | |4 |8 | | (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| | Number (Int64) | |32-bit|64-bit|
|---------------------|-------------------------------------|:----:|:----:| |---------------------|-------------------------------------|:----:|:----:|

View File

@ -79,7 +79,7 @@ SAX 和 DOM API 都依赖于3个额外的概念`Allocator`、`Encoding` 和 `
| `unsigned u` | 32位无符号整数 |4 |4 | | `unsigned u` | 32位无符号整数 |4 |4 |
| (零填充) | 0 |4 |4 | | (零填充) | 0 |4 |4 |
| (未使用) | |4 |8 | | (未使用) | |4 |8 |
| `unsigned flags_` | `kNumberType kNumberFlag kUIntFlag kUInt64Flag ...` |4 |4 | | `unsigned flags_` | `kNumberType kNumberFlag kUintFlag kUint64Flag ...` |4 |4 |
| Number (Int64) | | 32位 | 64位 | | Number (Int64) | | 32位 | 64位 |
|---------------------|-------------------------------------|:----:|:----:| |---------------------|-------------------------------------|:----:|:----:|
@ -248,7 +248,7 @@ void SkipWhitespace(InputStream& is) {
## 整数到字符串的转换 {#itoa} ## 整数到字符串的转换 {#itoa}
整数到字符串转换的朴素算法需要对每一个十进制位进行一次处罚。我们实现了若干版本并在 [itoa-benchmark](https://github.com/miloyip/itoa-benchmark) 中对它们进行了评估。 整数到字符串转换的朴素算法需要对每一个十进制位进行一次除法。我们实现了若干版本并在 [itoa-benchmark](https://github.com/miloyip/itoa-benchmark) 中对它们进行了评估。
虽然 SSE2 版本是最快的,但它和第二快的 `branchlut` 差距不大。而且 `branchlut` 是纯C++实现,所以我们在 RapidJSON 中使用了 `branchlut` 虽然 SSE2 版本是最快的,但它和第二快的 `branchlut` 差距不大。而且 `branchlut` 是纯C++实现,所以我们在 RapidJSON 中使用了 `branchlut`

View File

@ -37,7 +37,7 @@ Bool(false)
Key("n", 1, true) Key("n", 1, true)
Null() Null()
Key("i") Key("i")
UInt(123) Uint(123)
Key("pi") Key("pi")
Double(3.1416) Double(3.1416)
Key("a") Key("a")

View File

@ -37,7 +37,7 @@ Bool(false)
Key("n", 1, true) Key("n", 1, true)
Null() Null()
Key("i") Key("i")
UInt(123) Uint(123)
Key("pi") Key("pi")
Double(3.1416) Double(3.1416)
Key("a") Key("a")
@ -91,7 +91,7 @@ void main() {
} }
~~~~~~~~~~ ~~~~~~~~~~
注意 RapidJSON 使用模板去静态挷定 `Reader` 类型及处理器的类,而不是使用含虚函数的类。这个范式可以通过把函数内联而改善性能。 注意 RapidJSON 使用模板去静态挷定 `Reader` 类型及处理器的类,而不是使用含虚函数的类。这个范式可以通过把函数内联而改善性能。
## 处理器 {#Handler} ## 处理器 {#Handler}

View File

@ -82,7 +82,7 @@ JSON number type represents all numeric values. However, C++ needs more specific
~~~~~~~~~~cpp ~~~~~~~~~~cpp
assert(document["i"].IsNumber()); 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()); assert(document["i"].IsInt());
printf("i = %d\n", document["i"].GetInt()); printf("i = %d\n", document["i"].GetInt());
// Alternative (int)document["i"] // Alternative (int)document["i"]

View File

@ -82,7 +82,7 @@ JSON Number 类型表示所有数值。然而C++ 需要使用更专门的类
~~~~~~~~~~cpp ~~~~~~~~~~cpp
assert(document["i"].IsNumber()); assert(document["i"].IsNumber());
// 在此情况下IsUint()/IsInt64()/IsUInt64() 也会返回 true // 在此情况下IsUint()/IsInt64()/IsUint64() 也会返回 true
assert(document["i"].IsInt()); assert(document["i"].IsInt());
printf("i = %d\n", document["i"].GetInt()); printf("i = %d\n", document["i"].GetInt());
// 另一种用法: (int)document["i"] // 另一种用法: (int)document["i"]
@ -447,7 +447,7 @@ contact.PushBack(val, document.GetAllocator());
~~~~~~~~~~ ~~~~~~~~~~
## 修改 Object {#ModifyObject} ## 修改 Object {#ModifyObject}
Object 是键值对的集合。每个键必须为 String。要修改 Object方法是增加或移除成员。以下的 API 用来增加员: Object 是键值对的集合。每个键必须为 String。要修改 Object方法是增加或移除成员。以下的 API 用来增加员:
* `Value& AddMember(Value&, Value&, Allocator& allocator)` * `Value& AddMember(Value&, Value&, Allocator& allocator)`
* `Value& AddMember(StringRefType, Value&, Allocator&)` * `Value& AddMember(StringRefType, Value&, Allocator&)`

View File

@ -57,7 +57,7 @@ int main(int, char*[]) {
printf("n = %s\n", document["n"].IsNull() ? "null" : "?"); 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"].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"] printf("i = %d\n", document["i"].GetInt()); // Alternative (int)document["i"]
assert(document["pi"].IsNumber()); assert(document["pi"].IsNumber());

View File

@ -63,15 +63,45 @@ class GenericDocument;
https://code.google.com/p/rapidjson/issues/detail?id=64 https://code.google.com/p/rapidjson/issues/detail?id=64
*/ */
template <typename Encoding, typename Allocator> template <typename Encoding, typename Allocator>
struct GenericMember { class GenericMember {
public:
GenericValue<Encoding, Allocator> name; //!< name of member (must be a string) GenericValue<Encoding, Allocator> name; //!< name of member (must be a string)
GenericValue<Encoding, Allocator> value; //!< value of member. GenericValue<Encoding, Allocator> 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<GenericMember&>(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. // swap() for std::sort() and other potential use in STL.
friend inline void swap(GenericMember& a, GenericMember& b) RAPIDJSON_NOEXCEPT { friend inline void swap(GenericMember& a, GenericMember& b) RAPIDJSON_NOEXCEPT {
a.name.Swap(b.name); a.name.Swap(b.name);
a.value.Swap(b.value); a.value.Swap(b.value);
} }
private:
//! Copy constructor is not permitted.
GenericMember(const GenericMember& rhs);
}; };
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////

View File

@ -102,7 +102,7 @@ class PrettyWriter;
// document.h // document.h
template <typename Encoding, typename Allocator> template <typename Encoding, typename Allocator>
struct GenericMember; class GenericMember;
template <bool Const, typename Encoding, typename Allocator> template <bool Const, typename Encoding, typename Allocator>
class GenericMemberIterator; class GenericMemberIterator;

View File

@ -23,7 +23,6 @@
RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(padded) RAPIDJSON_DIAG_OFF(padded)
RAPIDJSON_DIAG_OFF(switch-enum) RAPIDJSON_DIAG_OFF(switch-enum)
RAPIDJSON_DIAG_OFF(implicit-fallthrough)
#elif defined(_MSC_VER) #elif defined(_MSC_VER)
RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
@ -32,9 +31,6 @@ RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
#ifdef __GNUC__ #ifdef __GNUC__
RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(effc++) RAPIDJSON_DIAG_OFF(effc++)
#if __GNUC__ >= 7
RAPIDJSON_DIAG_OFF(implicit-fallthrough)
#endif
#endif #endif
#ifndef RAPIDJSON_REGEX_VERBOSE #ifndef RAPIDJSON_REGEX_VERBOSE
@ -291,6 +287,7 @@ private:
if (!CharacterEscape(ds, &codepoint)) if (!CharacterEscape(ds, &codepoint))
return; // Unsupported escape character return; // Unsupported escape character
// fall through to default // fall through to default
RAPIDJSON_DELIBERATE_FALLTHROUGH;
default: // Pattern character default: // Pattern character
PushOperand(operandStack, codepoint); PushOperand(operandStack, codepoint);
@ -520,6 +517,7 @@ private:
else if (!CharacterEscape(ds, &codepoint)) else if (!CharacterEscape(ds, &codepoint))
return false; return false;
// fall through to default // fall through to default
RAPIDJSON_DELIBERATE_FALLTHROUGH;
default: default:
switch (step) { switch (step) {
@ -529,6 +527,7 @@ private:
break; break;
} }
// fall through to step 0 for other characters // fall through to step 0 for other characters
RAPIDJSON_DELIBERATE_FALLTHROUGH;
case 0: case 0:
{ {

View File

@ -488,10 +488,11 @@ public:
v = &((*v)[t->index]); v = &((*v)[t->index]);
} }
else { else {
typename ValueType::MemberIterator m = v->FindMember(GenericStringRef<Ch>(t->name, t->length)); typename ValueType::MemberIterator m = v->FindMember(GenericValue<EncodingType>(GenericStringRef<Ch>(t->name, t->length)));
if (m == v->MemberEnd()) { if (m == v->MemberEnd()) {
v->AddMember(ValueType(t->name, t->length, allocator).Move(), ValueType().Move(), allocator); 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; exist = false;
} }
else else
@ -543,7 +544,7 @@ public:
switch (v->GetType()) { switch (v->GetType()) {
case kObjectType: case kObjectType:
{ {
typename ValueType::MemberIterator m = v->FindMember(GenericStringRef<Ch>(t->name, t->length)); typename ValueType::MemberIterator m = v->FindMember(GenericValue<EncodingType>(GenericStringRef<Ch>(t->name, t->length)));
if (m == v->MemberEnd()) if (m == v->MemberEnd())
break; break;
v = &m->value; v = &m->value;
@ -779,7 +780,7 @@ public:
switch (v->GetType()) { switch (v->GetType()) {
case kObjectType: case kObjectType:
{ {
typename ValueType::MemberIterator m = v->FindMember(GenericStringRef<Ch>(t->name, t->length)); typename ValueType::MemberIterator m = v->FindMember(GenericValue<EncodingType>(GenericStringRef<Ch>(t->name, t->length)));
if (m == v->MemberEnd()) if (m == v->MemberEnd())
return false; return false;
v = &m->value; v = &m->value;

View File

@ -597,6 +597,19 @@ RAPIDJSON_NAMESPACE_END
#endif #endif
#endif // RAPIDJSON_HAS_CXX11_RANGE_FOR #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 //!@endcond
//! Assertion (in non-throwing contexts). //! Assertion (in non-throwing contexts).

View File

@ -899,7 +899,7 @@ public:
} }
} }
SizeType index; SizeType index = 0;
if (FindPropertyIndex(ValueType(str, len).Move(), &index)) { if (FindPropertyIndex(ValueType(str, len).Move(), &index)) {
if (context.patternPropertiesSchemaCount > 0) { if (context.patternPropertiesSchemaCount > 0) {
context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = properties_[index].schema; context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = properties_[index].schema;

View File

@ -674,6 +674,9 @@ TEST(Pointer, Get) {
EXPECT_EQ(2u, unresolvedTokenIndex); EXPECT_EQ(2u, unresolvedTokenIndex);
EXPECT_TRUE(Pointer("/foo/0/a").Get(d, &unresolvedTokenIndex) == 0); // "/foo/0" is an string, cannot further query EXPECT_TRUE(Pointer("/foo/0/a").Get(d, &unresolvedTokenIndex) == 0); // "/foo/0" is an string, cannot further query
EXPECT_EQ(2u, unresolvedTokenIndex); EXPECT_EQ(2u, unresolvedTokenIndex);
Pointer::Token tokens[] = { { "foo ...", 3, kPointerInvalidIndex } };
EXPECT_EQ(&d["foo"], Pointer(tokens, 1).Get(d));
} }
TEST(Pointer, GetWithDefault) { TEST(Pointer, GetWithDefault) {

View File

@ -4,9 +4,8 @@
set -e set -e
DOXYGEN_VER=doxygen-1.8.15 DOXYGEN_VER=1_8_16
DOXYGEN_TAR=${DOXYGEN_VER}.linux.bin.tar.gz DOXYGEN_URL="https://codeload.github.com/doxygen/doxygen/tar.gz/Release_${DOXYGEN_VER}"
DOXYGEN_URL="http://doxygen.nl/files/${DOXYGEN_TAR}"
: ${GITHUB_REPO:="Tencent/rapidjson"} : ${GITHUB_REPO:="Tencent/rapidjson"}
GITHUB_HOST="github.com" GITHUB_HOST="github.com"
@ -47,9 +46,17 @@ abort() {
# install doxygen binary distribution # install doxygen binary distribution
doxygen_install() doxygen_install()
{ {
wget -O - "${DOXYGEN_URL}" | \ cd ${TMPDIR-/tmp}
tar xz -C ${TMPDIR-/tmp} ${DOXYGEN_VER}/bin/doxygen curl ${DOXYGEN_URL} -o doxygen.tar.gz
export PATH="${TMPDIR-/tmp}/${DOXYGEN_VER}/bin:$PATH" 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() doxygen_run()