-
+
$searchbox
diff --git a/3rdparty/rapidjson/doc/npm.md b/3rdparty/rapidjson/doc/npm.md
index 5efa7682137..6f4e85ad964 100644
--- a/3rdparty/rapidjson/doc/npm.md
+++ b/3rdparty/rapidjson/doc/npm.md
@@ -7,7 +7,7 @@
...
"dependencies": {
...
- "rapidjson": "git@github.com:miloyip/rapidjson.git"
+ "rapidjson": "git@github.com:Tencent/rapidjson.git"
},
...
"gypfile": true
diff --git a/3rdparty/rapidjson/doc/performance.md b/3rdparty/rapidjson/doc/performance.md
index 988e799e97a..6f9e1bf8b12 100644
--- a/3rdparty/rapidjson/doc/performance.md
+++ b/3rdparty/rapidjson/doc/performance.md
@@ -1,6 +1,6 @@
# Performance
-There is a [native JSON benchmark collection] [1] which evaluates speed, memory usage and code size of various operations among 37 JSON libaries.
+There is a [native JSON benchmark collection] [1] which evaluates speed, memory usage and code size of various operations among 37 JSON libraries.
[1]: https://github.com/miloyip/nativejson-benchmark
@@ -15,12 +15,12 @@ Additionally, you may refer to the following third-party benchmarks.
* [json_spirit](https://github.com/cierelabs/json_spirit)
* [jsoncpp](http://jsoncpp.sourceforge.net/)
* [libjson](http://sourceforge.net/projects/libjson/)
- * [rapidjson](https://github.com/miloyip/rapidjson/)
+ * [rapidjson](https://github.com/Tencent/rapidjson/)
* [QJsonDocument](http://qt-project.org/doc/qt-5.0/qtcore/qjsondocument.html)
* [JSON Parser Benchmarking](http://chadaustin.me/2013/01/json-parser-benchmarking/) by Chad Austin (Jan 2013)
* [sajson](https://github.com/chadaustin/sajson)
- * [rapidjson](https://github.com/miloyip/rapidjson/)
+ * [rapidjson](https://github.com/Tencent/rapidjson/)
* [vjson](https://code.google.com/p/vjson/)
* [YAJL](http://lloyd.github.com/yajl/)
* [Jansson](http://www.digip.org/jansson/)
diff --git a/3rdparty/rapidjson/doc/performance.zh-cn.md b/3rdparty/rapidjson/doc/performance.zh-cn.md
index c20c5050fec..2322c9c4903 100644
--- a/3rdparty/rapidjson/doc/performance.zh-cn.md
+++ b/3rdparty/rapidjson/doc/performance.zh-cn.md
@@ -15,12 +15,12 @@ RapidJSON 0.1 版本的性能测试文章位于 [这里](https://code.google.com
* [json_spirit](https://github.com/cierelabs/json_spirit)
* [jsoncpp](http://jsoncpp.sourceforge.net/)
* [libjson](http://sourceforge.net/projects/libjson/)
- * [rapidjson](https://github.com/miloyip/rapidjson/)
+ * [rapidjson](https://github.com/Tencent/rapidjson/)
* [QJsonDocument](http://qt-project.org/doc/qt-5.0/qtcore/qjsondocument.html)
* [JSON Parser Benchmarking](http://chadaustin.me/2013/01/json-parser-benchmarking/) by Chad Austin (Jan 2013)
* [sajson](https://github.com/chadaustin/sajson)
- * [rapidjson](https://github.com/miloyip/rapidjson/)
+ * [rapidjson](https://github.com/Tencent/rapidjson/)
* [vjson](https://code.google.com/p/vjson/)
* [YAJL](http://lloyd.github.com/yajl/)
* [Jansson](http://www.digip.org/jansson/)
diff --git a/3rdparty/rapidjson/doc/pointer.md b/3rdparty/rapidjson/doc/pointer.md
index b343d78ed7c..9a0e5ca03ab 100644
--- a/3rdparty/rapidjson/doc/pointer.md
+++ b/3rdparty/rapidjson/doc/pointer.md
@@ -211,7 +211,7 @@ p.Stringify(sb);
std::cout << sb.GetString() << std::endl;
~~~
-It can also stringify to URI fragment reprsentation by `StringifyUriFragment()`.
+It can also stringify to URI fragment representation by `StringifyUriFragment()`.
# User-Supplied Tokens {#UserSuppliedTokens}
diff --git a/3rdparty/rapidjson/doc/pointer.zh-cn.md b/3rdparty/rapidjson/doc/pointer.zh-cn.md
index f58f55f3d49..239569d4a0b 100644
--- a/3rdparty/rapidjson/doc/pointer.zh-cn.md
+++ b/3rdparty/rapidjson/doc/pointer.zh-cn.md
@@ -181,7 +181,7 @@ private:
`Pointer` 在其建构函数里会解译源字符串。若有解析错误,`Pointer::IsValid()` 返回 `false`。你可使用 `Pointer::GetParseErrorCode()` 和 `GetParseErrorOffset()` 去获取错信息。
-要注意的是,所有解析函数都假设 pointer 是合法的。对一个非法 pointer 解析会做成断言失败。
+要注意的是,所有解析函数都假设 pointer 是合法的。对一个非法 pointer 解析会造成断言失败。
# URI 片段表示方式 {#URIFragment}
diff --git a/3rdparty/rapidjson/doc/sax.md b/3rdparty/rapidjson/doc/sax.md
index 1d4fc2ae59c..d42d0438885 100644
--- a/3rdparty/rapidjson/doc/sax.md
+++ b/3rdparty/rapidjson/doc/sax.md
@@ -8,7 +8,7 @@ In RapidJSON, `Reader` (typedef of `GenericReader<...>`) is the SAX-style parser
# Reader {#Reader}
-`Reader` parses a JSON from a stream. While it reads characters from the stream, it analyze the characters according to the syntax of JSON, and publish events to a handler.
+`Reader` parses a JSON from a stream. While it reads characters from the stream, it analyzes the characters according to the syntax of JSON, and publishes events to a handler.
For example, here is a JSON.
@@ -24,7 +24,7 @@ For example, here is a JSON.
}
~~~~~~~~~~
-While a `Reader` parses this JSON, it publishes the following events to the handler sequentially:
+When a `Reader` parses this JSON, it publishes the following events to the handler sequentially:
~~~~~~~~~~
StartObject()
@@ -37,7 +37,7 @@ Bool(false)
Key("n", 1, true)
Null()
Key("i")
-UInt(123)
+Uint(123)
Key("pi")
Double(3.1416)
Key("a")
@@ -50,7 +50,7 @@ EndArray(4)
EndObject(7)
~~~~~~~~~~
-These events can be easily matched with the JSON, except some event parameters need further explanation. Let's see the `simplereader` example which produces exactly the same output as above:
+These events can be easily matched with the JSON, but some event parameters need further explanation. Let's see the `simplereader` example which produces exactly the same output as above:
~~~~~~~~~~cpp
#include "rapidjson/reader.h"
@@ -91,11 +91,11 @@ void main() {
}
~~~~~~~~~~
-Note that, RapidJSON uses template to statically bind the `Reader` type and the handler type, instead of using class with virtual functions. This paradigm can improve the performance by inlining functions.
+Note that RapidJSON uses templates to statically bind the `Reader` type and the handler type, instead of using classes with virtual functions. This paradigm can improve performance by inlining functions.
## Handler {#Handler}
-As the previous example showed, user needs to implement a handler, which consumes the events (function calls) from `Reader`. The handler must contain the following member functions.
+As shown in the previous example, the user needs to implement a handler which consumes the events (via function calls) from the `Reader`. The handler must contain the following member functions.
~~~~~~~~~~cpp
class Handler {
@@ -122,15 +122,15 @@ class Handler {
When the `Reader` encounters a JSON number, it chooses a suitable C++ type mapping. And then it calls *one* function out of `Int(int)`, `Uint(unsigned)`, `Int64(int64_t)`, `Uint64(uint64_t)` and `Double(double)`. If `kParseNumbersAsStrings` is enabled, `Reader` will always calls `RawNumber()` instead.
-`String(const char* str, SizeType length, bool copy)` is called when the `Reader` encounters a string. The first parameter is pointer to the string. The second parameter is the length of the string (excluding the null terminator). Note that RapidJSON supports null character `'\0'` inside a string. If such situation happens, `strlen(str) < length`. The last `copy` indicates whether the handler needs to make a copy of the string. For normal parsing, `copy = true`. Only when *insitu* parsing is used, `copy = false`. And beware that, the character type depends on the target encoding, which will be explained later.
+`String(const char* str, SizeType length, bool copy)` is called when the `Reader` encounters a string. The first parameter is pointer to the string. The second parameter is the length of the string (excluding the null terminator). Note that RapidJSON supports null character `\0` inside a string. If such situation happens, `strlen(str) < length`. The last `copy` indicates whether the handler needs to make a copy of the string. For normal parsing, `copy = true`. Only when *insitu* parsing is used, `copy = false`. And be aware that the character type depends on the target encoding, which will be explained later.
-When the `Reader` encounters the beginning of an object, it calls `StartObject()`. An object in JSON is a set of name-value pairs. If the object contains members it first calls `Key()` for the name of member, and then calls functions depending on the type of the value. These calls of name-value pairs repeats until calling `EndObject(SizeType memberCount)`. Note that the `memberCount` parameter is just an aid for the handler, user may not need this parameter.
+When the `Reader` encounters the beginning of an object, it calls `StartObject()`. An object in JSON is a set of name-value pairs. If the object contains members it first calls `Key()` for the name of member, and then calls functions depending on the type of the value. These calls of name-value pairs repeat until calling `EndObject(SizeType memberCount)`. Note that the `memberCount` parameter is just an aid for the handler; users who do not need this parameter may ignore it.
-Array is similar to object but simpler. At the beginning of an array, the `Reader` calls `BeginArary()`. If there is elements, it calls functions according to the types of element. Similarly, in the last call `EndArray(SizeType elementCount)`, the parameter `elementCount` is just an aid for the handler.
+Arrays are similar to objects, but simpler. At the beginning of an array, the `Reader` calls `BeginArray()`. If there is elements, it calls functions according to the types of element. Similarly, in the last call `EndArray(SizeType elementCount)`, the parameter `elementCount` is just an aid for the handler.
-Every handler functions returns a `bool`. Normally it should returns `true`. If the handler encounters an error, it can return `false` to notify event publisher to stop further processing.
+Every handler function returns a `bool`. Normally it should return `true`. If the handler encounters an error, it can return `false` to notify the event publisher to stop further processing.
-For example, when we parse a JSON with `Reader` and the handler detected that the JSON does not conform to the required schema, then the handler can return `false` and let the `Reader` stop further parsing. And the `Reader` will be in error state with error code `kParseErrorTermination`.
+For example, when we parse a JSON with `Reader` and the handler detects that the JSON does not conform to the required schema, the handler can return `false` and let the `Reader` stop further parsing. This will place the `Reader` in an error state, with error code `kParseErrorTermination`.
## GenericReader {#GenericReader}
@@ -149,19 +149,19 @@ typedef GenericReader
, UTF8<> > Reader;
} // namespace rapidjson
~~~~~~~~~~
-The `Reader` uses UTF-8 as both source and target encoding. The source encoding means the encoding in the JSON stream. The target encoding means the encoding of the `str` parameter in `String()` calls. For example, to parse a UTF-8 stream and outputs UTF-16 string events, you can define a reader by:
+The `Reader` uses UTF-8 as both source and target encoding. The source encoding means the encoding in the JSON stream. The target encoding means the encoding of the `str` parameter in `String()` calls. For example, to parse a UTF-8 stream and output UTF-16 string events, you can define a reader by:
~~~~~~~~~~cpp
GenericReader, UTF16<> > reader;
~~~~~~~~~~
-Note that, the default character type of `UTF16` is `wchar_t`. So this `reader`needs to call `String(const wchar_t*, SizeType, bool)` of the handler.
+Note that, the default character type of `UTF16` is `wchar_t`. So this `reader` needs to call `String(const wchar_t*, SizeType, bool)` of the handler.
The third template parameter `Allocator` is the allocator type for internal data structure (actually a stack).
## Parsing {#SaxParsing}
-The one and only one function of `Reader` is to parse JSON.
+The main function of `Reader` is used to parse JSON.
~~~~~~~~~~cpp
template
@@ -172,7 +172,30 @@ template
bool Parse(InputStream& is, Handler& handler);
~~~~~~~~~~
-If an error occurs during parsing, it will return `false`. User can also calls `bool HasParseEror()`, `ParseErrorCode GetParseErrorCode()` and `size_t GetErrorOffset()` to obtain the error states. Actually `Document` uses these `Reader` functions to obtain parse errors. Please refer to [DOM](doc/dom.md) for details about parse error.
+If an error occurs during parsing, it will return `false`. User can also call `bool HasParseError()`, `ParseErrorCode GetParseErrorCode()` and `size_t GetErrorOffset()` to obtain the error states. In fact, `Document` uses these `Reader` functions to obtain parse errors. Please refer to [DOM](doc/dom.md) for details about parse errors.
+
+## Token-by-Token Parsing {#TokenByTokenParsing}
+
+Some users may wish to parse a JSON input stream a single token at a time, instead of immediately parsing an entire document without stopping. To parse JSON this way, instead of calling `Parse`, you can use the `IterativeParse` set of functions:
+
+~~~~~~~~~~cpp
+ void IterativeParseInit();
+
+ template
+ bool IterativeParseNext(InputStream& is, Handler& handler);
+
+ bool IterativeParseComplete();
+~~~~~~~~~~
+
+Here is an example of iteratively parsing JSON, token by token:
+
+~~~~~~~~~~cpp
+ reader.IterativeParseInit();
+ while (!reader.IterativeParseComplete()) {
+ reader.IterativeParseNext(is, handler);
+ // Your handler has been called once.
+ }
+~~~~~~~~~~
# Writer {#Writer}
diff --git a/3rdparty/rapidjson/doc/sax.zh-cn.md b/3rdparty/rapidjson/doc/sax.zh-cn.md
index b20286de927..9b11e7683d7 100644
--- a/3rdparty/rapidjson/doc/sax.zh-cn.md
+++ b/3rdparty/rapidjson/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}
@@ -122,7 +122,7 @@ class Handler {
当 `Reader` 遇到 JSON number,它会选择一个合适的 C++ 类型映射,然后调用 `Int(int)`、`Uint(unsigned)`、`Int64(int64_t)`、`Uint64(uint64_t)` 及 `Double(double)` 的 * 其中之一个 *。 若开启了 `kParseNumbersAsStrings` 选项,`Reader` 便会改为调用 `RawNumber()`。
-当 `Reader` 遇到 JSON string,它会调用 `String(const char* str, SizeType length, bool copy)`。第一个参数是字符串的指针。第二个参数是字符串的长度(不包含空终止符号)。注意 RapidJSON 支持字串中含有空字符 `'\0'`。若出现这种情况,便会有 `strlen(str) < length`。最后的 `copy` 参数表示处理器是否需要复制该字符串。在正常解析时,`copy = true`。仅当使用原位解析时,`copy = false`。此外,还要注意字符的类型与目标编码相关,我们稍后会再谈这一点。
+当 `Reader` 遇到 JSON string,它会调用 `String(const char* str, SizeType length, bool copy)`。第一个参数是字符串的指针。第二个参数是字符串的长度(不包含空终止符号)。注意 RapidJSON 支持字串中含有空字符 `\0`。若出现这种情况,便会有 `strlen(str) < length`。最后的 `copy` 参数表示处理器是否需要复制该字符串。在正常解析时,`copy = true`。仅当使用原位解析时,`copy = false`。此外,还要注意字符的类型与目标编码相关,我们稍后会再谈这一点。
当 `Reader` 遇到 JSON object 的开始之时,它会调用 `StartObject()`。JSON 的 object 是一个键值对(成员)的集合。若 object 包含成员,它会先为成员的名字调用 `Key()`,然后再按值的类型调用函数。它不断调用这些键值对,直至最终调用 `EndObject(SizeType memberCount)`。注意 `memberCount` 参数对处理器来说只是协助性质,使用者可能不需要此参数。
diff --git a/3rdparty/rapidjson/doc/schema.md b/3rdparty/rapidjson/doc/schema.md
index a83cebcae7c..4da4474b2e0 100644
--- a/3rdparty/rapidjson/doc/schema.md
+++ b/3rdparty/rapidjson/doc/schema.md
@@ -8,7 +8,7 @@ RapidJSON implemented a JSON Schema validator for [JSON Schema Draft v4](http://
[TOC]
-## Basic Usage
+# Basic Usage {#Basic}
First of all, you need to parse a JSON Schema into `Document`, and then compile the `Document` into a `SchemaDocument`.
@@ -20,15 +20,23 @@ Secondly, construct a `SchemaValidator` with the `SchemaDocument`. It is similar
// ...
Document sd;
-if (!sd.Parse(schemaJson).HasParseError()) {
+if (sd.Parse(schemaJson).HasParseError()) {
// the schema is not a valid JSON.
// ...
}
+
SchemaDocument schema(sd); // Compile a Document to SchemaDocument
+if (!schema.GetError().ObjectEmpty()) {
+ // there was a problem compiling the schema
+ StringBuffer sb;
+ Writer w(sb);
+ schema.GetError().Accept(w);
+ printf("Invalid schema: %s\n", sb.GetString());
+}
// sd is no longer needed here.
Document d;
-if (!d.Parse(inputJson).HasParseError()) {
+if (d.Parse(inputJson).HasParseError()) {
// the input is not a valid JSON.
// ...
}
@@ -49,14 +57,14 @@ if (!d.Accept(validator)) {
Some notes:
-* One `SchemaDocment` can be referenced by multiple `SchemaValidator`s. It will not be modified by `SchemaValidator`s.
+* One `SchemaDocument` can be referenced by multiple `SchemaValidator`s. It will not be modified by `SchemaValidator`s.
* A `SchemaValidator` may be reused to validate multiple documents. To run it for other documents, call `validator.Reset()` first.
-## Validation during parsing/serialization
+# Validation during parsing/serialization {#Fused}
Unlike most JSON Schema validator implementations, RapidJSON provides a SAX-based schema validator. Therefore, you can parse a JSON from a stream while validating it on the fly. If the validator encounters a JSON value that invalidates the supplied schema, the parsing will be terminated immediately. This design is especially useful for parsing large JSON files.
-### DOM parsing
+## DOM parsing {#DOM}
For using DOM in parsing, `Document` needs some preparation and finalizing tasks, in addition to receiving SAX events, thus it needs some work to route the reader, validator and the document. `SchemaValidatingReader` is a helper class that doing such work.
@@ -97,7 +105,7 @@ if (!reader.GetParseResult()) {
}
~~~
-### SAX parsing
+## SAX parsing {#SAX}
For using SAX in parsing, it is much simpler. If it only need to validate the JSON without further processing, it is simply:
@@ -126,7 +134,7 @@ if (!reader.Parse(ss, validator)) {
}
~~~
-### Serialization
+## Serialization {#Serialization}
It is also possible to do validation during serializing. This can ensure the result JSON is valid according to the JSON schema.
@@ -144,7 +152,7 @@ if (!d.Accept(validator)) {
Of course, if your application only needs SAX-style serialization, it can simply send SAX events to `SchemaValidator` instead of `Writer`.
-## Remote Schema
+# Remote Schema {#Remote}
JSON Schema supports [`$ref` keyword](http://spacetelescope.github.io/understanding-json-schema/structuring.html), which is a [JSON pointer](doc/pointer.md) referencing to a local or remote schema. Local pointer is prefixed with `#`, while remote pointer is an relative or absolute URI. For example:
@@ -157,7 +165,7 @@ As `SchemaDocument` does not know how to resolve such URI, it needs a user-provi
~~~
class MyRemoteSchemaDocumentProvider : public IRemoteSchemaDocumentProvider {
public:
- virtual const SchemaDocument* GetRemoteDocument(const char* uri, SizeTyp length) {
+ virtual const SchemaDocument* GetRemoteDocument(const char* uri, SizeType length) {
// Resolve the uri and returns a pointer to that schema.
}
};
@@ -168,7 +176,7 @@ MyRemoteSchemaDocumentProvider provider;
SchemaDocument schema(sd, &provider);
~~~
-## Conformance
+# Conformance {#Conformance}
RapidJSON passed 262 out of 263 tests in [JSON Schema Test Suite](https://github.com/json-schema/JSON-Schema-Test-Suite) (Json Schema draft 4).
@@ -176,7 +184,7 @@ The failed test is "changed scope ref invalid" of "change resolution scope" in `
Besides, the `format` schema keyword for string values is ignored, since it is not required by the specification.
-### Regular Expression
+## Regular Expression {#Regex}
The schema keyword `pattern` and `patternProperties` uses regular expression to match the required pattern.
@@ -185,7 +193,7 @@ RapidJSON implemented a simple NFA regular expression engine, which is used by d
|Syntax|Description|
|------|-----------|
|`ab` | Concatenation |
-|`a|b` | Alternation |
+|a|b
| Alternation |
|`a?` | Zero or one |
|`a*` | Zero or more |
|`a+` | One or more |
@@ -202,7 +210,7 @@ RapidJSON implemented a simple NFA regular expression engine, which is used by d
|`[^abc]` | Negated character classes |
|`[^a-c]` | Negated character class range |
|`[\b]` | Backspace (U+0008) |
-|`\|`, `\\`, ... | Escape characters |
+|\\|
, `\\`, ... | Escape characters |
|`\f` | Form feed (U+000C) |
|`\n` | Line feed (U+000A) |
|`\r` | Carriage return (U+000D) |
@@ -211,7 +219,7 @@ RapidJSON implemented a simple NFA regular expression engine, which is used by d
For C++11 compiler, it is also possible to use the `std::regex` by defining `RAPIDJSON_SCHEMA_USE_INTERNALREGEX=0` and `RAPIDJSON_SCHEMA_USE_STDREGEX=1`. If your schemas do not need `pattern` and `patternProperties`, you can set both macros to zero to disable this feature, which will reduce some code size.
-## Performance
+# Performance {#Performance}
Most C++ JSON libraries do not yet support JSON Schema. So we tried to evaluate the performance of RapidJSON's JSON Schema validator according to [json-schema-benchmark](https://github.com/ebdrup/json-schema-benchmark), which tests 11 JavaScript libraries running on Node.js.
@@ -235,3 +243,271 @@ On a Mac Book Pro (2.8 GHz Intel Core i7), the following results are collected.
|[`jayschema`](https://github.com/natesilva/jayschema)|0.1%|21 (± 1.14%)|
That is, RapidJSON is about 1.5x faster than the fastest JavaScript library (ajv). And 1400x faster than the slowest one.
+
+# Schema violation reporting {#Reporting}
+
+(Unreleased as of 2017-09-20)
+
+When validating an instance against a JSON Schema,
+it is often desirable to report not only whether the instance is valid,
+but also the ways in which it violates the schema.
+
+The `SchemaValidator` class
+collects errors encountered during validation
+into a JSON `Value`.
+This error object can then be accessed as `validator.GetError()`.
+
+The structure of the error object is subject to change
+in future versions of RapidJSON,
+as there is no standard schema for violations.
+The details below this point are provisional only.
+
+## General provisions {#ReportingGeneral}
+
+Validation of an instance value against a schema
+produces an error value.
+The error value is always an object.
+An empty object `{}` indicates the instance is valid.
+
+* The name of each member
+ corresponds to the JSON Schema keyword that is violated.
+* The value is either an object describing a single violation,
+ or an array of such objects.
+
+Each violation object contains two string-valued members
+named `instanceRef` and `schemaRef`.
+`instanceRef` contains the URI fragment serialization
+of a JSON Pointer to the instance subobject
+in which the violation was detected.
+`schemaRef` contains the URI of the schema
+and the fragment serialization of a JSON Pointer
+to the subschema that was violated.
+
+Individual violation objects can contain other keyword-specific members.
+These are detailed further.
+
+For example, validating this instance:
+
+~~~json
+{"numbers": [1, 2, "3", 4, 5]}
+~~~
+
+against this schema:
+
+~~~json
+{
+ "type": "object",
+ "properties": {
+ "numbers": {"$ref": "numbers.schema.json"}
+ }
+}
+~~~
+
+where `numbers.schema.json` refers
+(via a suitable `IRemoteSchemaDocumentProvider`)
+to this schema:
+
+~~~json
+{
+ "type": "array",
+ "items": {"type": "number"}
+}
+~~~
+
+produces the following error object:
+
+~~~json
+{
+ "type": {
+ "instanceRef": "#/numbers/2",
+ "schemaRef": "numbers.schema.json#/items",
+ "expected": ["number"],
+ "actual": "string"
+ }
+}
+~~~
+
+## Validation keywords for numbers {#Numbers}
+
+### multipleOf {#multipleof}
+
+* `expected`: required number strictly greater than 0.
+ The value of the `multipleOf` keyword specified in the schema.
+* `actual`: required number.
+ The instance value.
+
+### maximum {#maximum}
+
+* `expected`: required number.
+ The value of the `maximum` keyword specified in the schema.
+* `exclusiveMaximum`: optional boolean.
+ This will be true if the schema specified `"exclusiveMaximum": true`,
+ and will be omitted otherwise.
+* `actual`: required number.
+ The instance value.
+
+### minimum {#minimum}
+
+* `expected`: required number.
+ The value of the `minimum` keyword specified in the schema.
+* `exclusiveMinimum`: optional boolean.
+ This will be true if the schema specified `"exclusiveMinimum": true`,
+ and will be omitted otherwise.
+* `actual`: required number.
+ The instance value.
+
+## Validation keywords for strings {#Strings}
+
+### maxLength {#maxLength}
+
+* `expected`: required number greater than or equal to 0.
+ The value of the `maxLength` keyword specified in the schema.
+* `actual`: required string.
+ The instance value.
+
+### minLength {#minLength}
+
+* `expected`: required number greater than or equal to 0.
+ The value of the `minLength` keyword specified in the schema.
+* `actual`: required string.
+ The instance value.
+
+### pattern {#pattern}
+
+* `actual`: required string.
+ The instance value.
+
+(The expected pattern is not reported
+because the internal representation in `SchemaDocument`
+does not store the pattern in original string form.)
+
+## Validation keywords for arrays {#Arrays}
+
+### additionalItems {#additionalItems}
+
+This keyword is reported
+when the value of `items` schema keyword is an array,
+the value of `additionalItems` is `false`,
+and the instance is an array
+with more items than specified in the `items` array.
+
+* `disallowed`: required integer greater than or equal to 0.
+ The index of the first item that has no corresponding schema.
+
+### maxItems and minItems {#maxItems-minItems}
+
+* `expected`: required integer greater than or equal to 0.
+ The value of `maxItems` (respectively, `minItems`)
+ specified in the schema.
+* `actual`: required integer greater than or equal to 0.
+ Number of items in the instance array.
+
+### uniqueItems {#uniqueItems}
+
+* `duplicates`: required array
+ whose items are integers greater than or equal to 0.
+ Indices of items of the instance that are equal.
+
+(RapidJSON only reports the first two equal items,
+for performance reasons.)
+
+## Validation keywords for objects
+
+### maxProperties and minProperties {#maxProperties-minProperties}
+
+* `expected`: required integer greater than or equal to 0.
+ The value of `maxProperties` (respectively, `minProperties`)
+ specified in the schema.
+* `actual`: required integer greater than or equal to 0.
+ Number of properties in the instance object.
+
+### required {#required}
+
+* `missing`: required array of one or more unique strings.
+ The names of properties
+ that are listed in the value of the `required` schema keyword
+ but not present in the instance object.
+
+### additionalProperties {#additionalProperties}
+
+This keyword is reported
+when the schema specifies `additionalProperties: false`
+and the name of a property of the instance is
+neither listed in the `properties` keyword
+nor matches any regular expression in the `patternProperties` keyword.
+
+* `disallowed`: required string.
+ Name of the offending property of the instance.
+
+(For performance reasons,
+RapidJSON only reports the first such property encountered.)
+
+### dependencies {#dependencies}
+
+* `errors`: required object with one or more properties.
+ Names and values of its properties are described below.
+
+Recall that JSON Schema Draft 04 supports
+*schema dependencies*,
+where presence of a named *controlling* property
+requires the instance object to be valid against a subschema,
+and *property dependencies*,
+where presence of a controlling property
+requires other *dependent* properties to be also present.
+
+For a violated schema dependency,
+`errors` will contain a property
+with the name of the controlling property
+and its value will be the error object
+produced by validating the instance object
+against the dependent schema.
+
+For a violated property dependency,
+`errors` will contain a property
+with the name of the controlling property
+and its value will be an array of one or more unique strings
+listing the missing dependent properties.
+
+## Validation keywords for any instance type {#AnyTypes}
+
+### enum {#enum}
+
+This keyword has no additional properties
+beyond `instanceRef` and `schemaRef`.
+
+* The allowed values are not listed
+ because `SchemaDocument` does not store them in original form.
+* The violating value is not reported
+ because it might be unwieldy.
+
+If you need to report these details to your users,
+you can access the necessary information
+by following `instanceRef` and `schemaRef`.
+
+### type {#type}
+
+* `expected`: required array of one or more unique strings,
+ each of which is one of the seven primitive types
+ defined by the JSON Schema Draft 04 Core specification.
+ Lists the types allowed by the `type` schema keyword.
+* `actual`: required string, also one of seven primitive types.
+ The primitive type of the instance.
+
+### allOf, anyOf, and oneOf {#allOf-anyOf-oneOf}
+
+* `errors`: required array of at least one object.
+ There will be as many items as there are subschemas
+ in the `allOf`, `anyOf` or `oneOf` schema keyword, respectively.
+ Each item will be the error value
+ produced by validating the instance
+ against the corresponding subschema.
+
+For `allOf`, at least one error value will be non-empty.
+For `anyOf`, all error values will be non-empty.
+For `oneOf`, either all error values will be non-empty,
+or more than one will be empty.
+
+### not {#not}
+
+This keyword has no additional properties
+apart from `instanceRef` and `schemaRef`.
diff --git a/3rdparty/rapidjson/doc/schema.zh-cn.md b/3rdparty/rapidjson/doc/schema.zh-cn.md
index a01c1b10e1d..c85177f9fd0 100644
--- a/3rdparty/rapidjson/doc/schema.zh-cn.md
+++ b/3rdparty/rapidjson/doc/schema.zh-cn.md
@@ -8,7 +8,7 @@ RapidJSON 实现了一个 [JSON Schema Draft v4](http://json-schema.org/document
[TOC]
-## 基本用法
+# 基本用法 {#BasicUsage}
首先,你要把 JSON Schema 解析成 `Document`,再把它编译成一个 `SchemaDocument`。
@@ -20,7 +20,7 @@ RapidJSON 实现了一个 [JSON Schema Draft v4](http://json-schema.org/document
// ...
Document sd;
-if (!sd.Parse(schemaJson).HasParseError()) {
+if (sd.Parse(schemaJson).HasParseError()) {
// 此 schema 不是合法的 JSON
// ...
}
@@ -28,7 +28,7 @@ SchemaDocument schema(sd); // 把一个 Document 编译至 SchemaDocument
// 之后不再需要 sd
Document d;
-if (!d.Parse(inputJson).HasParseError()) {
+if (d.Parse(inputJson).HasParseError()) {
// 输入不是一个合法的 JSON
// ...
}
@@ -52,11 +52,11 @@ if (!d.Accept(validator)) {
* 一个 `SchemaDocment` 能被多个 `SchemaValidator` 引用。它不会被 `SchemaValidator` 修改。
* 可以重复使用一个 `SchemaValidator` 来校验多个文件。在校验其他文件前,须先调用 `validator.Reset()`。
-## 在解析/生成时进行校验
+# 在解析/生成时进行校验 {#ParsingSerialization}
与大部分 JSON Schema 校验器有所不同,RapidJSON 提供了一个基于 SAX 的 schema 校验器实现。因此,你可以在输入流解析 JSON 的同时进行校验。若校验器遇到一个与 schema 不符的值,就会立即终止解析。这设计对于解析大型 JSON 文件时特别有用。
-### DOM 解析
+## DOM 解析 {#DomParsing}
在使用 DOM 进行解析时,`Document` 除了接收 SAX 事件外,还需做一些准备及结束工作,因此,为了连接 `Reader`、`SchemaValidator` 和 `Document` 要做多一点事情。`SchemaValidatingReader` 是一个辅助类去做那些工作。
@@ -97,7 +97,7 @@ if (!reader.GetParseResult()) {
}
~~~
-### SAX 解析
+## SAX 解析 {#SaxParsing}
使用 SAX 解析时,情况就简单得多。若只需要校验 JSON 而无需进一步处理,那么仅需要:
@@ -126,7 +126,7 @@ if (!reader.Parse(ss, validator)) {
}
~~~
-### 生成
+## 生成 {#Serialization}
我们也可以在生成(serialization)的时候进行校验。这能确保输出的 JSON 符合一个 JSON Schema。
@@ -144,7 +144,7 @@ if (!d.Accept(validator)) {
当然,如果你的应用仅需要 SAX 风格的生成,那么只需要把 SAX 事件由原来发送到 `Writer`,改为发送到 `SchemaValidator`。
-## 远程 Schema
+# 远程 Schema {#RemoteSchema}
JSON Schema 支持 [`$ref` 关键字](http://spacetelescope.github.io/understanding-json-schema/structuring.html),它是一个 [JSON pointer](doc/pointer.zh-cn.md) 引用至一个本地(local)或远程(remote) schema。本地指针的首字符是 `#`,而远程指针是一个相对或绝对 URI。例如:
@@ -157,7 +157,7 @@ JSON Schema 支持 [`$ref` 关键字](http://spacetelescope.github.io/understand
~~~
class MyRemoteSchemaDocumentProvider : public IRemoteSchemaDocumentProvider {
public:
- virtual const SchemaDocument* GetRemoteDocument(const char* uri, SizeTyp length) {
+ virtual const SchemaDocument* GetRemoteDocument(const char* uri, SizeType length) {
// Resolve the uri and returns a pointer to that schema.
}
};
@@ -168,7 +168,7 @@ MyRemoteSchemaDocumentProvider provider;
SchemaDocument schema(sd, &provider);
~~~
-## 标准的符合程度
+# 标准的符合程度 {#Conformance}
RapidJSON 通过了 [JSON Schema Test Suite](https://github.com/json-schema/JSON-Schema-Test-Suite) (Json Schema draft 4) 中 263 个测试的 262 个。
@@ -176,7 +176,7 @@ RapidJSON 通过了 [JSON Schema Test Suite](https://github.com/json-schema/JSON
除此以外,关于字符串类型的 `format` schema 关键字也会被忽略,因为标准中并没需求必须实现。
-### 正则表达式
+## 正则表达式 {#RegEx}
`pattern` 及 `patternProperties` 这两个 schema 关键字使用了正则表达式去匹配所需的模式。
@@ -185,7 +185,7 @@ RapidJSON 实现了一个简单的 NFA 正则表达式引擎,并预设使用
|语法|描述|
|------|-----------|
|`ab` | 串联 |
-|`a|b` | 交替 |
+|a|b
| 交替 |
|`a?` | 零或一次 |
|`a*` | 零或多次 |
|`a+` | 一或多次 |
@@ -202,7 +202,7 @@ RapidJSON 实现了一个简单的 NFA 正则表达式引擎,并预设使用
|`[^abc]` | 字符组取反 |
|`[^a-c]` | 字符组范围取反 |
|`[\b]` | 退格符 (U+0008) |
-|`\|`, `\\`, ... | 转义字符 |
+|\\|
, `\\`, ... | 转义字符 |
|`\f` | 馈页 (U+000C) |
|`\n` | 馈行 (U+000A) |
|`\r` | 回车 (U+000D) |
@@ -211,7 +211,7 @@ RapidJSON 实现了一个简单的 NFA 正则表达式引擎,并预设使用
对于使用 C++11 编译器的使用者,也可使用 `std::regex`,只需定义 `RAPIDJSON_SCHEMA_USE_INTERNALREGEX=0` 及 `RAPIDJSON_SCHEMA_USE_STDREGEX=1`。若你的 schema 无需使用 `pattern` 或 `patternProperties`,可以把两个宏都设为零,以禁用此功能,这样做可节省一些代码体积。
-## 性能
+# 性能 {#Performance}
大部分 C++ JSON 库都未支持 JSON Schema。因此我们尝试按照 [json-schema-benchmark](https://github.com/ebdrup/json-schema-benchmark) 去评估 RapidJSON 的 JSON Schema 校验器。该评测测试了 11 个运行在 node.js 上的 JavaScript 库。
diff --git a/3rdparty/rapidjson/doc/stream.md b/3rdparty/rapidjson/doc/stream.md
index b79ce537acd..5d0b0f35ee6 100644
--- a/3rdparty/rapidjson/doc/stream.md
+++ b/3rdparty/rapidjson/doc/stream.md
@@ -1,6 +1,6 @@
# Stream
-In RapidJSON, `rapidjson::Stream` is a concept for reading/writing JSON. Here we first show how to use streams provided. And then see how to create a custom stream.
+In RapidJSON, `rapidjson::Stream` is a concept for reading/writing JSON. Here we'll first show you how to use provided streams. And then see how to create a custom stream.
[TOC]
@@ -42,6 +42,7 @@ Note that, `StringStream` is a typedef of `GenericStringStream >`, user m
~~~~~~~~~~cpp
#include "rapidjson/stringbuffer.h"
+#include
StringBuffer buffer;
Writer writer(buffer);
@@ -50,7 +51,7 @@ d.Accept(writer);
const char* output = buffer.GetString();
~~~~~~~~~~
-When the buffer is full, it will increases the capacity automatically. The default capacity is 256 characters (256 bytes for UTF8, 512 bytes for UTF16, etc.). User can provide an allocator and a initial capacity.
+When the buffer is full, it will increases the capacity automatically. The default capacity is 256 characters (256 bytes for UTF8, 512 bytes for UTF16, etc.). User can provide an allocator and an initial capacity.
~~~~~~~~~~cpp
StringBuffer buffer1(0, 1024); // Use its allocator, initial size = 1024
@@ -88,7 +89,7 @@ d.ParseStream(is);
fclose(fp);
~~~~~~~~~~
-Different from string streams, `FileReadStream` is byte stream. It does not handle encodings. If the file is not UTF-8, the byte stream can be wrapped in a `EncodedInputStream`. It will be discussed very soon.
+Different from string streams, `FileReadStream` is byte stream. It does not handle encodings. If the file is not UTF-8, the byte stream can be wrapped in a `EncodedInputStream`. We will discuss more about this later in this tutorial.
Apart from reading file, user can also use `FileReadStream` to read `stdin`.
@@ -98,6 +99,7 @@ Apart from reading file, user can also use `FileReadStream` to read `stdin`.
~~~~~~~~~~cpp
#include "rapidjson/filewritestream.h"
+#include
#include
using namespace rapidjson;
@@ -117,15 +119,15 @@ d.Accept(writer);
fclose(fp);
~~~~~~~~~~
-It can also directs the output to `stdout`.
+It can also redirect the output to `stdout`.
# iostream Wrapper {#iostreamWrapper}
-Due to users' requests, RapidJSON provided official wrappers for `std::basic_istream` and `std::basic_ostream`. However, please note that the performance will be much lower than the other streams above.
+Due to users' requests, RapidJSON also provides official wrappers for `std::basic_istream` and `std::basic_ostream`. However, please note that the performance will be much lower than the other streams above.
## IStreamWrapper {#IStreamWrapper}
-`IStreamWrapper` wraps any class drived from `std::istream`, such as `std::istringstream`, `std::stringstream`, `std::ifstream`, `std::fstream`, into RapidJSON's input stream.
+`IStreamWrapper` wraps any class derived from `std::istream`, such as `std::istringstream`, `std::stringstream`, `std::ifstream`, `std::fstream`, into RapidJSON's input stream.
~~~cpp
#include
@@ -179,7 +181,7 @@ As mentioned above, UTF-8 byte streams can be read directly. However, UTF-16 and
Besides, it also need to handle [byte order mark (BOM)](http://en.wikipedia.org/wiki/Byte_order_mark). When reading from a byte stream, it is needed to detect or just consume the BOM if exists. When writing to a byte stream, it can optionally write BOM.
-If the encoding of stream is known in compile-time, you may use `EncodedInputStream` and `EncodedOutputStream`. If the stream can be UTF-8, UTF-16LE, UTF-16BE, UTF-32LE, UTF-32BE JSON, and it is only known in runtime, you may use `AutoUTFInputStream` and `AutoUTFOutputStream`. These streams are defined in `rapidjson/encodedstream.h`.
+If the encoding of stream is known during compile-time, you may use `EncodedInputStream` and `EncodedOutputStream`. If the stream can be UTF-8, UTF-16LE, UTF-16BE, UTF-32LE, UTF-32BE JSON, and it is only known in runtime, you may use `AutoUTFInputStream` and `AutoUTFOutputStream`. These streams are defined in `rapidjson/encodedstream.h`.
Note that, these encoded streams can be applied to streams other than file. For example, you may have a file in memory, or a custom byte stream, be wrapped in encoded streams.
@@ -215,6 +217,7 @@ fclose(fp);
~~~~~~~~~~cpp
#include "rapidjson/filewritestream.h" // FileWriteStream
#include "rapidjson/encodedstream.h" // EncodedOutputStream
+#include
#include
Document d; // Document is GenericDocument >
@@ -228,7 +231,7 @@ FileWriteStream bos(fp, writeBuffer, sizeof(writeBuffer));
typedef EncodedOutputStream, FileWriteStream> OutputStream;
OutputStream eos(bos, true); // Write BOM
-Writer, UTF8<>> writer(eos);
+Writer, UTF32LE<>> writer(eos);
d.Accept(writer); // This generates UTF32-LE file from UTF-8 in memory
fclose(fp);
diff --git a/3rdparty/rapidjson/doc/stream.zh-cn.md b/3rdparty/rapidjson/doc/stream.zh-cn.md
index f2c54f798ea..6e379bbd6b5 100644
--- a/3rdparty/rapidjson/doc/stream.zh-cn.md
+++ b/3rdparty/rapidjson/doc/stream.zh-cn.md
@@ -42,6 +42,7 @@ d.Parse(json);
~~~~~~~~~~cpp
#include "rapidjson/stringbuffer.h"
+#include
StringBuffer buffer;
Writer writer(buffer);
@@ -98,6 +99,7 @@ fclose(fp);
~~~~~~~~~~cpp
#include "rapidjson/filewritestream.h"
+#include
#include
using namespace rapidjson;
@@ -215,6 +217,7 @@ fclose(fp);
~~~~~~~~~~cpp
#include "rapidjson/filewritestream.h" // FileWriteStream
#include "rapidjson/encodedstream.h" // EncodedOutputStream
+#include
#include
Document d; // Document 为 GenericDocument >
@@ -228,7 +231,7 @@ FileWriteStream bos(fp, writeBuffer, sizeof(writeBuffer));
typedef EncodedOutputStream, FileWriteStream> OutputStream;
OutputStream eos(bos, true); // 写入 BOM
-Writer, UTF8<>> writer(eos);
+Writer, UTF32LE<>> writer(eos);
d.Accept(writer); // 这里从内存的 UTF-8 生成 UTF32-LE 文件
fclose(fp);
diff --git a/3rdparty/rapidjson/doc/tutorial.md b/3rdparty/rapidjson/doc/tutorial.md
index cb76b4b0b78..a86aafdfc03 100644
--- a/3rdparty/rapidjson/doc/tutorial.md
+++ b/3rdparty/rapidjson/doc/tutorial.md
@@ -2,7 +2,7 @@
This tutorial introduces the basics of the Document Object Model(DOM) API.
-As shown in [Usage at a glance](@ref index), a JSON can be parsed into DOM, and then the DOM can be queried and modified easily, and finally be converted back to JSON.
+As shown in [Usage at a glance](@ref index), JSON can be parsed into a DOM, and then the DOM can be queried and modified easily, and finally be converted back to JSON.
[TOC]
@@ -12,9 +12,9 @@ Each JSON value is stored in a type called `Value`. A `Document`, representing t
# Query Value {#QueryValue}
-In this section, we will use excerpt of `example/tutorial/tutorial.cpp`.
+In this section, we will use excerpt from `example/tutorial/tutorial.cpp`.
-Assumes we have a JSON stored in a C string (`const char* json`):
+Assume we have the following JSON stored in a C string (`const char* json`):
~~~~~~~~~~js
{
"hello": "world",
@@ -55,7 +55,7 @@ printf("hello = %s\n", document["hello"].GetString());
~~~~~~~~~~
~~~~~~~~~~
-world
+hello = world
~~~~~~~~~~
JSON true/false values are represented as `bool`.
@@ -65,16 +65,16 @@ printf("t = %s\n", document["t"].GetBool() ? "true" : "false");
~~~~~~~~~~
~~~~~~~~~~
-true
+t = true
~~~~~~~~~~
-JSON null can be queryed by `IsNull()`.
+JSON null can be queried with `IsNull()`.
~~~~~~~~~~cpp
printf("n = %s\n", document["n"].IsNull() ? "null" : "?");
~~~~~~~~~~
~~~~~~~~~~
-null
+n = null
~~~~~~~~~~
JSON number type represents all numeric values. However, C++ needs more specific type for manipulation.
@@ -82,10 +82,10 @@ 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"]
+// Alternatively (int)document["i"]
assert(document["pi"].IsNumber());
assert(document["pi"].IsDouble());
@@ -113,17 +113,17 @@ a[2] = 3
a[3] = 4
~~~~~~~~~~
-Note that, RapidJSON does not automatically convert values between JSON types. If a value is a string, it is invalid to call `GetInt()`, for example. In debug mode it will fail an assertion. In release mode, the behavior is undefined.
+Note that, RapidJSON does not automatically convert values between JSON types. For example, if a value is a string, it is invalid to call `GetInt()`. In debug mode it will fail on assertion. In release mode, the behavior is undefined.
-In the following, details about querying individual types are discussed.
+In the following sections we discuss details about querying individual types.
## Query Array {#QueryArray}
-By default, `SizeType` is typedef of `unsigned`. In most systems, array is limited to store up to 2^32-1 elements.
+By default, `SizeType` is typedef of `unsigned`. In most systems, an array is limited to store up to 2^32-1 elements.
-You may access the elements in array by integer literal, for example, `a[0]`, `a[1]`, `a[2]`.
+You may access the elements in an array by integer literal, for example, `a[0]`, `a[1]`, `a[2]`.
-Array is similar to `std::vector`, instead of using indices, you may also use iterator to access all the elements.
+Array is similar to `std::vector`: instead of using indices, you may also use iterator to access all the elements.
~~~~~~~~~~cpp
for (Value::ConstValueIterator itr = a.Begin(); itr != a.End(); ++itr)
printf("%d ", itr->GetInt());
@@ -144,7 +144,7 @@ for (auto& v : a.GetArray())
## Query Object {#QueryObject}
-Similar to array, we can access all object members by iterator:
+Similar to Array, we can access all object members by iterator:
~~~~~~~~~~cpp
static const char* kTypeNames[] =
@@ -168,9 +168,9 @@ Type of member pi is Number
Type of member a is Array
~~~~~~~~~~
-Note that, when `operator[](const char*)` cannot find the member, it will fail an assertion.
+Note that, when `operator[](const char*)` cannot find the member, it will fail on assertion.
-If we are unsure whether a member exists, we need to call `HasMember()` before calling `operator[](const char*)`. However, this incurs two lookup. A better way is to call `FindMember()`, which can check the existence of member and obtain its value at once:
+If we are unsure whether a member exists, we need to call `HasMember()` before calling `operator[](const char*)`. However, this incurs two lookup. A better way is to call `FindMember()`, which can check the existence of a member and obtain its value at once:
~~~~~~~~~~cpp
Value::ConstMemberIterator itr = document.FindMember("hello");
@@ -190,11 +190,11 @@ for (auto& m : document.GetObject())
## Querying Number {#QueryNumber}
-JSON provide a single numerical type called Number. Number can be integer or real numbers. RFC 4627 says the range of Number is specified by parser.
+JSON provides a single numerical type called Number. Number can be an integer or a real number. RFC 4627 says the range of Number is specified by the parser implementation.
-As C++ provides several integer and floating point number types, the DOM tries to handle these with widest possible range and good performance.
+As C++ provides several integer and floating point number types, the DOM tries to handle these with the widest possible range and good performance.
-When a Number is parsed, it is stored in the DOM as either one of the following type:
+When a Number is parsed, it is stored in the DOM as one of the following types:
Type | Description
-----------|---------------------------------------
@@ -204,7 +204,7 @@ Type | Description
`int64_t` | 64-bit signed integer
`double` | 64-bit double precision floating point
-When querying a number, you can check whether the number can be obtained as target type:
+When querying a number, you can check whether the number can be obtained as the target type:
Checking | Obtaining
------------------|---------------------
@@ -215,24 +215,24 @@ Checking | Obtaining
`bool IsInt64()` | `int64_t GetInt64()`
`bool IsDouble()` | `double GetDouble()`
-Note that, an integer value may be obtained in various ways without conversion. For example, A value `x` containing 123 will make `x.IsInt() == x.IsUint() == x.IsInt64() == x.IsUint64() == true`. But a value `y` containing -3000000000 will only makes `x.IsInt64() == true`.
+Note that, an integer value may be obtained in various ways without conversion. For example, A value `x` containing 123 will make `x.IsInt() == x.IsUint() == x.IsInt64() == x.IsUint64() == true`. But a value `y` containing -3000000000 will only make `x.IsInt64() == true`.
-When obtaining the numeric values, `GetDouble()` will convert internal integer representation to a `double`. Note that, `int` and `unsigned` can be safely convert to `double`, but `int64_t` and `uint64_t` may lose precision (since mantissa of `double` is only 52-bits).
+When obtaining the numeric values, `GetDouble()` will convert internal integer representation to a `double`. Note that, `int` and `unsigned` can be safely converted to `double`, but `int64_t` and `uint64_t` may lose precision (since mantissa of `double` is only 52-bits).
## Query String {#QueryString}
-In addition to `GetString()`, the `Value` class also contains `GetStringLength()`. Here explains why.
+In addition to `GetString()`, the `Value` class also contains `GetStringLength()`. Here explains why:
-According to RFC 4627, JSON strings can contain Unicode character `U+0000`, which must be escaped as `"\u0000"`. The problem is that, C/C++ often uses null-terminated string, which treats ``\0'` as the terminator symbol.
+According to RFC 4627, JSON strings can contain Unicode character `U+0000`, which must be escaped as `"\u0000"`. The problem is that, C/C++ often uses null-terminated string, which treats `\0` as the terminator symbol.
-To conform RFC 4627, RapidJSON supports string containing `U+0000`. If you need to handle this, you can use `GetStringLength()` API to obtain the correct length of string.
+To conform with RFC 4627, RapidJSON supports string containing `U+0000` character. If you need to handle this, you can use `GetStringLength()` to obtain the correct string length.
-For example, after parsing a the following JSON to `Document d`:
+For example, after parsing the following JSON to `Document d`:
~~~~~~~~~~js
{ "s" : "a\u0000b" }
~~~~~~~~~~
-The correct length of the value `"a\u0000b"` is 3. But `strlen()` returns 1.
+The correct length of the string `"a\u0000b"` is 3, as returned by `GetStringLength()`. But `strlen()` returns 1.
`GetStringLength()` can also improve performance, as user may often need to call `strlen()` for allocating buffer.
@@ -246,7 +246,7 @@ which accepts the length of string as parameter. This constructor supports stori
## Comparing values
-You can use `==` and `!=` to compare values. Two values are equal if and only if they are have same type and contents. You can also compare values with primitive types. Here is an example.
+You can use `==` and `!=` to compare values. Two values are equal if and only if they have same type and contents. You can also compare values with primitive types. Here is an example:
~~~~~~~~~~cpp
if (document["hello"] == document["n"]) /*...*/; // Compare values
@@ -264,7 +264,7 @@ Note that, currently if an object contains duplicated named member, comparing eq
There are several ways to create values. After a DOM tree is created and/or modified, it can be saved as JSON again using `Writer`.
## Change Value Type {#ChangeValueType}
-When creating a Value or Document by default constructor, its type is Null. To change its type, call `SetXXX()` or assignment operator, for example:
+When creating a `Value` or `Document` by default constructor, its type is Null. To change its type, call `SetXXX()` or assignment operator, for example:
~~~~~~~~~~cpp
Document d; // Null
@@ -285,7 +285,7 @@ Value u(123u); // calls Value(unsigned)
Value d(1.5); // calls Value(double)
~~~~~~~~~~
-To create empty object or array, you may use `SetObject()`/`SetArray()` after default constructor, or using the `Value(Type)` in one shot:
+To create empty object or array, you may use `SetObject()`/`SetArray()` after default constructor, or using the `Value(Type)` in one call:
~~~~~~~~~~cpp
Value o(kObjectType);
@@ -299,7 +299,7 @@ A very special decision during design of RapidJSON is that, assignment of value
~~~~~~~~~~cpp
Value a(123);
Value b(456);
-b = a; // a becomes a Null value, b becomes number 123.
+a = b; // b becomes a Null value, a becomes number 456.
~~~~~~~~~~

@@ -360,14 +360,14 @@ a.PushBack(Value(42).Move(), allocator); // same as above
~~~~~~~~~~
## Create String {#CreateString}
-RapidJSON provide two strategies for storing string.
+RapidJSON provides two strategies for storing string.
1. copy-string: allocates a buffer, and then copy the source data into it.
2. const-string: simply store a pointer of string.
-Copy-string is always safe because it owns a copy of the data. Const-string can be used for storing string literal, and in-situ parsing which we will mentioned in Document section.
+Copy-string is always safe because it owns a copy of the data. Const-string can be used for storing a string literal, and for in-situ parsing which will be mentioned in the DOM section.
-To make memory allocation customizable, RapidJSON requires user to pass an instance of allocator, whenever an operation may require allocation. This design is needed to prevent storing a allocator (or Document) pointer per Value.
+To make memory allocation customizable, RapidJSON requires users to pass an instance of allocator, whenever an operation may require allocation. This design is needed to prevent storing an allocator (or Document) pointer per Value.
Therefore, when we assign a copy-string, we call this overloaded `SetString()` with allocator:
@@ -385,7 +385,7 @@ In this example, we get the allocator from a `Document` instance. This is a comm
Besides, the above `SetString()` requires length. This can handle null characters within a string. There is another `SetString()` overloaded function without the length parameter. And it assumes the input is null-terminated and calls a `strlen()`-like function to obtain the length.
-Finally, for string literal or string with safe life-cycle can use const-string version of `SetString()`, which lacks allocator parameter. For string literals (or constant character arrays), simply passing the literal as parameter is safe and efficient:
+Finally, for a string literal or string with a safe life-cycle one can use the const-string version of `SetString()`, which lacks an allocator parameter. For string literals (or constant character arrays), simply passing the literal as parameter is safe and efficient:
~~~~~~~~~~cpp
Value s;
@@ -393,7 +393,7 @@ s.SetString("rapidjson"); // can contain null character, length derived at co
s = "rapidjson"; // shortcut, same as above
~~~~~~~~~~
-For character pointer, the RapidJSON requires to mark it as safe before using it without copying. This can be achieved by using the `StringRef` function:
+For a character pointer, RapidJSON requires it to be marked as safe before using it without copying. This can be achieved by using the `StringRef` function:
~~~~~~~~~cpp
const char * cstr = getenv("USER");
@@ -408,7 +408,7 @@ s = StringRef(cstr,cstr_len); // shortcut, same as above
~~~~~~~~~
## Modify Array {#ModifyArray}
-Value with array type provides similar APIs as `std::vector`.
+Value with array type provides an API similar to `std::vector`.
* `Clear()`
* `Reserve(SizeType, Allocator&)`
@@ -418,7 +418,7 @@ Value with array type provides similar APIs as `std::vector`.
* `ValueIterator Erase(ConstValueIterator pos)`
* `ValueIterator Erase(ConstValueIterator first, ConstValueIterator last)`
-Note that, `Reserve(...)` and `PushBack(...)` may allocate memory for the array elements, therefore require an allocator.
+Note that, `Reserve(...)` and `PushBack(...)` may allocate memory for the array elements, therefore requiring an allocator.
Here is an example of `PushBack()`:
@@ -433,7 +433,7 @@ for (int i = 5; i <= 10; i++)
a.PushBack("Lua", allocator).PushBack("Mio", allocator);
~~~~~~~~~~
-Differs from STL, `PushBack()`/`PopBack()` returns the array reference itself. This is called _fluent interface_.
+This API differs from STL in that `PushBack()`/`PopBack()` return the array reference itself. This is called _fluent interface_.
If you want to add a non-constant string or a string without sufficient lifetime (see [Create String](#CreateString)) to the array, you need to create a string Value by using the copy-string API. To avoid the need for an intermediate variable, you can use a [temporary value](#TemporaryValues) in place:
@@ -448,7 +448,7 @@ contact.PushBack(val, document.GetAllocator());
~~~~~~~~~~
## Modify Object {#ModifyObject}
-Object is a collection of key-value pairs (members). Each key must be a string value. To modify an object, either add or remove members. THe following APIs are for adding members:
+The Object class is a collection of key-value pairs (members). Each key must be a string value. To modify an object, either add or remove members. The following API is for adding members:
* `Value& AddMember(Value&, Value&, Allocator& allocator)`
* `Value& AddMember(StringRefType, Value&, Allocator&)`
@@ -462,7 +462,7 @@ contact.AddMember("name", "Milo", document.GetAllocator());
contact.AddMember("married", true, document.GetAllocator());
~~~~~~~~~~
-The name parameter with `StringRefType` is similar to the interface of `SetString` function for string values. These overloads are used to avoid the need for copying the `name` string, as constant key names are very common in JSON objects.
+The name parameter with `StringRefType` is similar to the interface of the `SetString` function for string values. These overloads are used to avoid the need for copying the `name` string, since constant key names are very common in JSON objects.
If you need to create a name from a non-constant string or a string without sufficient lifetime (see [Create String](#CreateString)), you need to create a string Value by using the copy-string API. To avoid the need for an intermediate variable, you can use a [temporary value](#TemporaryValues) in place:
diff --git a/3rdparty/rapidjson/doc/tutorial.zh-cn.md b/3rdparty/rapidjson/doc/tutorial.zh-cn.md
index 61fb0b24399..8b24ff11f6f 100644
--- a/3rdparty/rapidjson/doc/tutorial.zh-cn.md
+++ b/3rdparty/rapidjson/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"]
@@ -250,7 +250,7 @@ string(const char* s, size_t count);
~~~~~~~~~~cpp
if (document["hello"] == document["n"]) /*...*/; // 比较两个值
-if (document["hello"] == "world") /*...*/; // 与字符串家面量作比较
+if (document["hello"] == "world") /*...*/; // 与字符串字面量作比较
if (document["i"] != 123) /*...*/; // 与整数作比较
if (document["pi"] != 3.14) /*...*/; // 与 double 作比较
~~~~~~~~~~
@@ -292,9 +292,9 @@ Value o(kObjectType);
Value a(kArrayType);
~~~~~~~~~~
-## 转移语意(Move Semantics) {#MoveSemantics}
+## 转移语义(Move Semantics) {#MoveSemantics}
-在设计 RapidJSON 时有一个非常特别的决定,就是 Value 赋值并不是把来源 Value 复制至目的 Value,而是把把来源 Value 转移(move)至目的 Value。例如:
+在设计 RapidJSON 时有一个非常特别的决定,就是 Value 赋值并不是把来源 Value 复制至目的 Value,而是把来源 Value 转移(move)至目的 Value。例如:
~~~~~~~~~~cpp
Value a(123);
@@ -302,13 +302,13 @@ Value b(456);
b = a; // a 变成 Null,b 变成数字 123。
~~~~~~~~~~
-
+
-为什么?此语意有何优点?
+为什么?此语义有何优点?
最简单的答案就是性能。对于固定大小的 JSON 类型(Number、True、False、Null),复制它们是简单快捷。然而,对于可变大小的 JSON 类型(String、Array、Object),复制它们会产生大量开销,而且这些开销常常不被察觉。尤其是当我们需要创建临时 Object,把它复制至另一变量,然后再析构它。
-例如,若使用正常 * 复制 * 语意:
+例如,若使用正常 * 复制 * 语义:
~~~~~~~~~~cpp
Value o(kObjectType);
@@ -321,15 +321,15 @@ Value o(kObjectType);
}
~~~~~~~~~~
-
+
那个 `o` Object 需要分配一个和 contacts 相同大小的缓冲区,对 conacts 做深度复制,并最终要析构 contacts。这样会产生大量无必要的内存分配/释放,以及内存复制。
有一些方案可避免实质地复制这些数据,例如引用计数(reference counting)、垃圾回收(garbage collection, GC)。
-为了使 RapidJSON 简单及快速,我们选择了对赋值采用 * 转移 * 语意。这方法与 `std::auto_ptr` 相似,都是在赋值时转移拥有权。转移快得多简单得多,只需要析构原来的 Value,把来源 `memcpy()` 至目标,最后把来源设置为 Null 类型。
+为了使 RapidJSON 简单及快速,我们选择了对赋值采用 * 转移 * 语义。这方法与 `std::auto_ptr` 相似,都是在赋值时转移拥有权。转移快得多简单得多,只需要析构原来的 Value,把来源 `memcpy()` 至目标,最后把来源设置为 Null 类型。
-因此,使用转移语意后,上面的例子变成:
+因此,使用转移语义后,上面的例子变成:
~~~~~~~~~~cpp
Value o(kObjectType);
@@ -341,11 +341,11 @@ Value o(kObjectType);
}
~~~~~~~~~~
-
+
-在 C++11 中这称为转移赋值操作(move assignment operator)。由于 RapidJSON 支持 C++03,它在赋值操作采用转移语意,其它修改形函数如 `AddMember()`, `PushBack()` 也采用转移语意。
+在 C++11 中这称为转移赋值操作(move assignment operator)。由于 RapidJSON 支持 C++03,它在赋值操作采用转移语义,其它修改型函数如 `AddMember()`, `PushBack()` 也采用转移语义。
-### 转移语意及临时值 {#TemporaryValues}
+### 转移语义及临时值 {#TemporaryValues}
有时候,我们想直接构造一个 Value 并传递给一个“转移”函数(如 `PushBack()`、`AddMember()`)。由于临时对象是不能转换为正常的 Value 引用,我们加入了一个方便的 `Move()` 函数:
@@ -383,11 +383,12 @@ memset(buffer, 0, sizeof(buffer));
另外,上面的 `SetString()` 需要长度参数。这个 API 能处理含有空字符的字符串。另一个 `SetString()` 重载函数没有长度参数,它假设输入是空字符结尾的,并会调用类似 `strlen()` 的函数去获取长度。
-最后,对于字符串字面量或有安全生命周期的字符串,可以使用 const-string 版本的 `SetString()`,它没有 allocator 参数。对于字符串家面量(或字符数组常量),只需简单地传递字面量,又安全又高效:
+最后,对于字符串字面量或有安全生命周期的字符串,可以使用 const-string 版本的 `SetString()`,它没有
+allocator 参数。对于字符串字面量(或字符数组常量),只需简单地传递字面量,又安全又高效:
~~~~~~~~~~cpp
Value s;
-s.SetString("rapidjson"); // 可包含空字符,长度在编译萁推导
+s.SetString("rapidjson"); // 可包含空字符,长度在编译期推导
s = "rapidjson"; // 上行的缩写
~~~~~~~~~~
@@ -446,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/3rdparty/rapidjson/example/CMakeLists.txt b/3rdparty/rapidjson/example/CMakeLists.txt
index 4d448ccc0f4..9f53c9aadc6 100644
--- a/3rdparty/rapidjson/example/CMakeLists.txt
+++ b/3rdparty/rapidjson/example/CMakeLists.txt
@@ -10,6 +10,7 @@ set(EXAMPLES
filterkey
filterkeydom
jsonx
+ lookaheadparser
messagereader
parsebyparts
pretty
@@ -18,19 +19,22 @@ set(EXAMPLES
serialize
simpledom
simplereader
+ simplepullreader
simplewriter
+ sortkeys
tutorial)
include_directories("../include/")
add_definitions(-D__STDC_FORMAT_MACROS)
+set_property(DIRECTORY PROPERTY COMPILE_OPTIONS ${EXTRA_CXX_FLAGS})
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread -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 -Wfloat-equal -Wimplicit-fallthrough -Weverything")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
endif()
+add_executable(archivertest archiver/archiver.cpp archiver/archivertest.cpp)
+
foreach (example ${EXAMPLES})
add_executable(${example} ${example}/${example}.cpp)
endforeach()
diff --git a/3rdparty/rapidjson/example/archiver/archiver.cpp b/3rdparty/rapidjson/example/archiver/archiver.cpp
new file mode 100644
index 00000000000..59ae4c41016
--- /dev/null
+++ b/3rdparty/rapidjson/example/archiver/archiver.cpp
@@ -0,0 +1,292 @@
+#include "archiver.h"
+#include
+#include
+#include "rapidjson/document.h"
+#include "rapidjson/prettywriter.h"
+#include "rapidjson/stringbuffer.h"
+
+using namespace rapidjson;
+
+struct JsonReaderStackItem {
+ enum State {
+ BeforeStart, //!< An object/array is in the stack but it is not yet called by StartObject()/StartArray().
+ Started, //!< An object/array is called by StartObject()/StartArray().
+ Closed //!< An array is closed after read all element, but before EndArray().
+ };
+
+ JsonReaderStackItem(const Value* value, State state) : value(value), state(state), index() {}
+
+ const Value* value;
+ State state;
+ SizeType index; // For array iteration
+};
+
+typedef std::stack JsonReaderStack;
+
+#define DOCUMENT reinterpret_cast(mDocument)
+#define STACK (reinterpret_cast(mStack))
+#define TOP (STACK->top())
+#define CURRENT (*TOP.value)
+
+JsonReader::JsonReader(const char* json) : mDocument(), mStack(), mError(false) {
+ mDocument = new Document;
+ DOCUMENT->Parse(json);
+ if (DOCUMENT->HasParseError())
+ mError = true;
+ else {
+ mStack = new JsonReaderStack;
+ STACK->push(JsonReaderStackItem(DOCUMENT, JsonReaderStackItem::BeforeStart));
+ }
+}
+
+JsonReader::~JsonReader() {
+ delete DOCUMENT;
+ delete STACK;
+}
+
+// Archive concept
+JsonReader& JsonReader::StartObject() {
+ if (!mError) {
+ if (CURRENT.IsObject() && TOP.state == JsonReaderStackItem::BeforeStart)
+ TOP.state = JsonReaderStackItem::Started;
+ else
+ mError = true;
+ }
+ return *this;
+}
+
+JsonReader& JsonReader::EndObject() {
+ if (!mError) {
+ if (CURRENT.IsObject() && TOP.state == JsonReaderStackItem::Started)
+ Next();
+ else
+ mError = true;
+ }
+ return *this;
+}
+
+JsonReader& JsonReader::Member(const char* name) {
+ if (!mError) {
+ if (CURRENT.IsObject() && TOP.state == JsonReaderStackItem::Started) {
+ Value::ConstMemberIterator memberItr = CURRENT.FindMember(name);
+ if (memberItr != CURRENT.MemberEnd())
+ STACK->push(JsonReaderStackItem(&memberItr->value, JsonReaderStackItem::BeforeStart));
+ else
+ mError = true;
+ }
+ else
+ mError = true;
+ }
+ return *this;
+}
+
+bool JsonReader::HasMember(const char* name) const {
+ if (!mError && CURRENT.IsObject() && TOP.state == JsonReaderStackItem::Started)
+ return CURRENT.HasMember(name);
+ return false;
+}
+
+JsonReader& JsonReader::StartArray(size_t* size) {
+ if (!mError) {
+ if (CURRENT.IsArray() && TOP.state == JsonReaderStackItem::BeforeStart) {
+ TOP.state = JsonReaderStackItem::Started;
+ if (size)
+ *size = CURRENT.Size();
+
+ if (!CURRENT.Empty()) {
+ const Value* value = &CURRENT[TOP.index];
+ STACK->push(JsonReaderStackItem(value, JsonReaderStackItem::BeforeStart));
+ }
+ else
+ TOP.state = JsonReaderStackItem::Closed;
+ }
+ else
+ mError = true;
+ }
+ return *this;
+}
+
+JsonReader& JsonReader::EndArray() {
+ if (!mError) {
+ if (CURRENT.IsArray() && TOP.state == JsonReaderStackItem::Closed)
+ Next();
+ else
+ mError = true;
+ }
+ return *this;
+}
+
+JsonReader& JsonReader::operator&(bool& b) {
+ if (!mError) {
+ if (CURRENT.IsBool()) {
+ b = CURRENT.GetBool();
+ Next();
+ }
+ else
+ mError = true;
+ }
+ return *this;
+}
+
+JsonReader& JsonReader::operator&(unsigned& u) {
+ if (!mError) {
+ if (CURRENT.IsUint()) {
+ u = CURRENT.GetUint();
+ Next();
+ }
+ else
+ mError = true;
+ }
+ return *this;
+}
+
+JsonReader& JsonReader::operator&(int& i) {
+ if (!mError) {
+ if (CURRENT.IsInt()) {
+ i = CURRENT.GetInt();
+ Next();
+ }
+ else
+ mError = true;
+ }
+ return *this;
+}
+
+JsonReader& JsonReader::operator&(double& d) {
+ if (!mError) {
+ if (CURRENT.IsNumber()) {
+ d = CURRENT.GetDouble();
+ Next();
+ }
+ else
+ mError = true;
+ }
+ return *this;
+}
+
+JsonReader& JsonReader::operator&(std::string& s) {
+ if (!mError) {
+ if (CURRENT.IsString()) {
+ s = CURRENT.GetString();
+ Next();
+ }
+ else
+ mError = true;
+ }
+ return *this;
+}
+
+JsonReader& JsonReader::SetNull() {
+ // This function is for JsonWriter only.
+ mError = true;
+ return *this;
+}
+
+void JsonReader::Next() {
+ if (!mError) {
+ assert(!STACK->empty());
+ STACK->pop();
+
+ if (!STACK->empty() && CURRENT.IsArray()) {
+ if (TOP.state == JsonReaderStackItem::Started) { // Otherwise means reading array item pass end
+ if (TOP.index < CURRENT.Size() - 1) {
+ const Value* value = &CURRENT[++TOP.index];
+ STACK->push(JsonReaderStackItem(value, JsonReaderStackItem::BeforeStart));
+ }
+ else
+ TOP.state = JsonReaderStackItem::Closed;
+ }
+ else
+ mError = true;
+ }
+ }
+}
+
+#undef DOCUMENT
+#undef STACK
+#undef TOP
+#undef CURRENT
+
+////////////////////////////////////////////////////////////////////////////////
+// JsonWriter
+
+#define WRITER reinterpret_cast*>(mWriter)
+#define STREAM reinterpret_cast(mStream)
+
+JsonWriter::JsonWriter() : mWriter(), mStream() {
+ mStream = new StringBuffer;
+ mWriter = new PrettyWriter(*STREAM);
+}
+
+JsonWriter::~JsonWriter() {
+ delete WRITER;
+ delete STREAM;
+}
+
+const char* JsonWriter::GetString() const {
+ return STREAM->GetString();
+}
+
+JsonWriter& JsonWriter::StartObject() {
+ WRITER->StartObject();
+ return *this;
+}
+
+JsonWriter& JsonWriter::EndObject() {
+ WRITER->EndObject();
+ return *this;
+}
+
+JsonWriter& JsonWriter::Member(const char* name) {
+ WRITER->String(name, static_cast(strlen(name)));
+ return *this;
+}
+
+bool JsonWriter::HasMember(const char*) const {
+ // This function is for JsonReader only.
+ assert(false);
+ return false;
+}
+
+JsonWriter& JsonWriter::StartArray(size_t*) {
+ WRITER->StartArray();
+ return *this;
+}
+
+JsonWriter& JsonWriter::EndArray() {
+ WRITER->EndArray();
+ return *this;
+}
+
+JsonWriter& JsonWriter::operator&(bool& b) {
+ WRITER->Bool(b);
+ return *this;
+}
+
+JsonWriter& JsonWriter::operator&(unsigned& u) {
+ WRITER->Uint(u);
+ return *this;
+}
+
+JsonWriter& JsonWriter::operator&(int& i) {
+ WRITER->Int(i);
+ return *this;
+}
+
+JsonWriter& JsonWriter::operator&(double& d) {
+ WRITER->Double(d);
+ return *this;
+}
+
+JsonWriter& JsonWriter::operator&(std::string& s) {
+ WRITER->String(s.c_str(), static_cast(s.size()));
+ return *this;
+}
+
+JsonWriter& JsonWriter::SetNull() {
+ WRITER->Null();
+ return *this;
+}
+
+#undef STREAM
+#undef WRITER
diff --git a/3rdparty/rapidjson/example/archiver/archiver.h b/3rdparty/rapidjson/example/archiver/archiver.h
new file mode 100644
index 00000000000..285ca73d6ab
--- /dev/null
+++ b/3rdparty/rapidjson/example/archiver/archiver.h
@@ -0,0 +1,145 @@
+#ifndef ARCHIVER_H_
+#define ARCHIVER_H_
+
+#include
+#include
+
+/**
+\class Archiver
+\brief Archiver concept
+
+Archiver can be a reader or writer for serialization or deserialization respectively.
+
+class Archiver {
+public:
+ /// \returns true if the archiver is in normal state. false if it has errors.
+ operator bool() const;
+
+ /// Starts an object
+ Archiver& StartObject();
+
+ /// After calling StartObject(), assign a member with a name
+ Archiver& Member(const char* name);
+
+ /// After calling StartObject(), check if a member presents
+ bool HasMember(const char* name) const;
+
+ /// Ends an object
+ Archiver& EndObject();
+
+ /// Starts an array
+ /// \param size If Archiver::IsReader is true, the size of array is written.
+ Archiver& StartArray(size_t* size = 0);
+
+ /// Ends an array
+ Archiver& EndArray();
+
+ /// Read/Write primitive types.
+ Archiver& operator&(bool& b);
+ Archiver& operator&(unsigned& u);
+ Archiver& operator&(int& i);
+ Archiver& operator&(double& d);
+ Archiver& operator&(std::string& s);
+
+ /// Write primitive types.
+ Archiver& SetNull();
+
+ //! Whether it is a reader.
+ static const bool IsReader;
+
+ //! Whether it is a writer.
+ static const bool IsWriter;
+};
+*/
+
+/// Represents a JSON reader which implements Archiver concept.
+class JsonReader {
+public:
+ /// Constructor.
+ /**
+ \param json A non-const source json string for in-situ parsing.
+ \note in-situ means the source JSON string will be modified after parsing.
+ */
+ JsonReader(const char* json);
+
+ /// Destructor.
+ ~JsonReader();
+
+ // Archive concept
+
+ operator bool() const { return !mError; }
+
+ JsonReader& StartObject();
+ JsonReader& Member(const char* name);
+ bool HasMember(const char* name) const;
+ JsonReader& EndObject();
+
+ JsonReader& StartArray(size_t* size = 0);
+ JsonReader& EndArray();
+
+ JsonReader& operator&(bool& b);
+ JsonReader& operator&(unsigned& u);
+ JsonReader& operator&(int& i);
+ JsonReader& operator&(double& d);
+ JsonReader& operator&(std::string& s);
+
+ JsonReader& SetNull();
+
+ static const bool IsReader = true;
+ static const bool IsWriter = !IsReader;
+
+private:
+ JsonReader(const JsonReader&);
+ JsonReader& operator=(const JsonReader&);
+
+ void Next();
+
+ // PIMPL
+ void* mDocument; ///< DOM result of parsing.
+ void* mStack; ///< Stack for iterating the DOM
+ bool mError; ///< Whether an error has occurred.
+};
+
+class JsonWriter {
+public:
+ /// Constructor.
+ JsonWriter();
+
+ /// Destructor.
+ ~JsonWriter();
+
+ /// Obtains the serialized JSON string.
+ const char* GetString() const;
+
+ // Archive concept
+
+ operator bool() const { return true; }
+
+ JsonWriter& StartObject();
+ JsonWriter& Member(const char* name);
+ bool HasMember(const char* name) const;
+ JsonWriter& EndObject();
+
+ JsonWriter& StartArray(size_t* size = 0);
+ JsonWriter& EndArray();
+
+ JsonWriter& operator&(bool& b);
+ JsonWriter& operator&(unsigned& u);
+ JsonWriter& operator&(int& i);
+ JsonWriter& operator&(double& d);
+ JsonWriter& operator&(std::string& s);
+ JsonWriter& SetNull();
+
+ static const bool IsReader = false;
+ static const bool IsWriter = !IsReader;
+
+private:
+ JsonWriter(const JsonWriter&);
+ JsonWriter& operator=(const JsonWriter&);
+
+ // PIMPL idiom
+ void* mWriter; ///< JSON writer.
+ void* mStream; ///< Stream buffer.
+};
+
+#endif // ARCHIVER_H__
diff --git a/3rdparty/rapidjson/example/archiver/archivertest.cpp b/3rdparty/rapidjson/example/archiver/archivertest.cpp
new file mode 100644
index 00000000000..417a421a318
--- /dev/null
+++ b/3rdparty/rapidjson/example/archiver/archivertest.cpp
@@ -0,0 +1,287 @@
+#include "archiver.h"
+#include
+#include
+
+//////////////////////////////////////////////////////////////////////////////
+// Test1: simple object
+
+struct Student {
+ Student() : name(), age(), height(), canSwim() {}
+ Student(const std::string name, unsigned age, double height, bool canSwim) :
+ name(name), age(age), height(height), canSwim(canSwim)
+ {}
+
+ std::string name;
+ unsigned age;
+ double height;
+ bool canSwim;
+};
+
+template
+Archiver& operator&(Archiver& ar, Student& s) {
+ ar.StartObject();
+ ar.Member("name") & s.name;
+ ar.Member("age") & s.age;
+ ar.Member("height") & s.height;
+ ar.Member("canSwim") & s.canSwim;
+ return ar.EndObject();
+}
+
+std::ostream& operator<<(std::ostream& os, const Student& s) {
+ return os << s.name << " " << s.age << " " << s.height << " " << s.canSwim;
+}
+
+void test1() {
+ std::string json;
+
+ // Serialize
+ {
+ Student s("Lua", 9, 150.5, true);
+
+ JsonWriter writer;
+ writer & s;
+ json = writer.GetString();
+ std::cout << json << std::endl;
+ }
+
+ // Deserialize
+ {
+ Student s;
+ JsonReader reader(json.c_str());
+ reader & s;
+ std::cout << s << std::endl;
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Test2: std::vector <=> JSON array
+//
+// You can map a JSON array to other data structures as well
+
+struct Group {
+ Group() : groupName(), students() {}
+ std::string groupName;
+ std::vector students;
+};
+
+template
+Archiver& operator&(Archiver& ar, Group& g) {
+ ar.StartObject();
+
+ ar.Member("groupName");
+ ar & g.groupName;
+
+ ar.Member("students");
+ size_t studentCount = g.students.size();
+ ar.StartArray(&studentCount);
+ if (ar.IsReader)
+ g.students.resize(studentCount);
+ for (size_t i = 0; i < studentCount; i++)
+ ar & g.students[i];
+ ar.EndArray();
+
+ return ar.EndObject();
+}
+
+std::ostream& operator<<(std::ostream& os, const Group& g) {
+ os << g.groupName << std::endl;
+ for (std::vector::const_iterator itr = g.students.begin(); itr != g.students.end(); ++itr)
+ os << *itr << std::endl;
+ return os;
+}
+
+void test2() {
+ std::string json;
+
+ // Serialize
+ {
+ Group g;
+ g.groupName = "Rainbow";
+
+ Student s1("Lua", 9, 150.5, true);
+ Student s2("Mio", 7, 120.0, false);
+ g.students.push_back(s1);
+ g.students.push_back(s2);
+
+ JsonWriter writer;
+ writer & g;
+ json = writer.GetString();
+ std::cout << json << std::endl;
+ }
+
+ // Deserialize
+ {
+ Group g;
+ JsonReader reader(json.c_str());
+ reader & g;
+ std::cout << g << std::endl;
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Test3: polymorphism & friend
+//
+// Note that friendship is not necessary but make things simpler.
+
+class Shape {
+public:
+ virtual ~Shape() {}
+ virtual const char* GetType() const = 0;
+ virtual void Print(std::ostream& os) const = 0;
+
+protected:
+ Shape() : x_(), y_() {}
+ Shape(double x, double y) : x_(x), y_(y) {}
+
+ template
+ friend Archiver& operator&(Archiver& ar, Shape& s);
+
+ double x_, y_;
+};
+
+template
+Archiver& operator&(Archiver& ar, Shape& s) {
+ ar.Member("x") & s.x_;
+ ar.Member("y") & s.y_;
+ return ar;
+}
+
+class Circle : public Shape {
+public:
+ Circle() : radius_() {}
+ Circle(double x, double y, double radius) : Shape(x, y), radius_(radius) {}
+ ~Circle() {}
+
+ const char* GetType() const { return "Circle"; }
+
+ void Print(std::ostream& os) const {
+ os << "Circle (" << x_ << ", " << y_ << ")" << " radius = " << radius_;
+ }
+
+private:
+ template
+ friend Archiver& operator&(Archiver& ar, Circle& c);
+
+ double radius_;
+};
+
+template
+Archiver& operator&(Archiver& ar, Circle& c) {
+ ar & static_cast(c);
+ ar.Member("radius") & c.radius_;
+ return ar;
+}
+
+class Box : public Shape {
+public:
+ Box() : width_(), height_() {}
+ Box(double x, double y, double width, double height) : Shape(x, y), width_(width), height_(height) {}
+ ~Box() {}
+
+ const char* GetType() const { return "Box"; }
+
+ void Print(std::ostream& os) const {
+ os << "Box (" << x_ << ", " << y_ << ")" << " width = " << width_ << " height = " << height_;
+ }
+
+private:
+ template
+ friend Archiver& operator&(Archiver& ar, Box& b);
+
+ double width_, height_;
+};
+
+template
+Archiver& operator&(Archiver& ar, Box& b) {
+ ar & static_cast(b);
+ ar.Member("width") & b.width_;
+ ar.Member("height") & b.height_;
+ return ar;
+}
+
+class Canvas {
+public:
+ Canvas() : shapes_() {}
+ ~Canvas() { Clear(); }
+
+ void Clear() {
+ for (std::vector::iterator itr = shapes_.begin(); itr != shapes_.end(); ++itr)
+ delete *itr;
+ }
+
+ void AddShape(Shape* shape) { shapes_.push_back(shape); }
+
+ void Print(std::ostream& os) {
+ for (std::vector::iterator itr = shapes_.begin(); itr != shapes_.end(); ++itr) {
+ (*itr)->Print(os);
+ std::cout << std::endl;
+ }
+ }
+
+private:
+ template
+ friend Archiver& operator&(Archiver& ar, Canvas& c);
+
+ std::vector shapes_;
+};
+
+template
+Archiver& operator&(Archiver& ar, Shape*& shape) {
+ std::string type = ar.IsReader ? "" : shape->GetType();
+ ar.StartObject();
+ ar.Member("type") & type;
+ if (type == "Circle") {
+ if (ar.IsReader) shape = new Circle;
+ ar & static_cast(*shape);
+ }
+ else if (type == "Box") {
+ if (ar.IsReader) shape = new Box;
+ ar & static_cast(*shape);
+ }
+ return ar.EndObject();
+}
+
+template
+Archiver& operator&(Archiver& ar, Canvas& c) {
+ size_t shapeCount = c.shapes_.size();
+ ar.StartArray(&shapeCount);
+ if (ar.IsReader) {
+ c.Clear();
+ c.shapes_.resize(shapeCount);
+ }
+ for (size_t i = 0; i < shapeCount; i++)
+ ar & c.shapes_[i];
+ return ar.EndArray();
+}
+
+void test3() {
+ std::string json;
+
+ // Serialize
+ {
+ Canvas c;
+ c.AddShape(new Circle(1.0, 2.0, 3.0));
+ c.AddShape(new Box(4.0, 5.0, 6.0, 7.0));
+
+ JsonWriter writer;
+ writer & c;
+ json = writer.GetString();
+ std::cout << json << std::endl;
+ }
+
+ // Deserialize
+ {
+ Canvas c;
+ JsonReader reader(json.c_str());
+ reader & c;
+ c.Print(std::cout);
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+int main() {
+ test1();
+ test2();
+ test3();
+}
diff --git a/3rdparty/rapidjson/example/jsonx/jsonx.cpp b/3rdparty/rapidjson/example/jsonx/jsonx.cpp
index 1346b578c39..954aa2b9077 100644
--- a/3rdparty/rapidjson/example/jsonx/jsonx.cpp
+++ b/3rdparty/rapidjson/example/jsonx/jsonx.cpp
@@ -1,4 +1,4 @@
-// JSON to JSONx conversion exmaple, using SAX API.
+// JSON to JSONx conversion example, using SAX API.
// JSONx is an IBM standard format to represent JSON as XML.
// https://www-01.ibm.com/support/knowledgecenter/SS9H2Y_7.1.0/com.ibm.dp.doc/json_jsonx.html
// This example parses JSON text from stdin with validation,
diff --git a/3rdparty/rapidjson/example/lookaheadparser/lookaheadparser.cpp b/3rdparty/rapidjson/example/lookaheadparser/lookaheadparser.cpp
new file mode 100644
index 00000000000..f627f4d8636
--- /dev/null
+++ b/3rdparty/rapidjson/example/lookaheadparser/lookaheadparser.cpp
@@ -0,0 +1,350 @@
+#include "rapidjson/reader.h"
+#include "rapidjson/document.h"
+#include
+
+RAPIDJSON_DIAG_PUSH
+#ifdef __GNUC__
+RAPIDJSON_DIAG_OFF(effc++)
+#endif
+
+// This example demonstrates JSON token-by-token parsing with an API that is
+// more direct; you don't need to design your logic around a handler object and
+// callbacks. Instead, you retrieve values from the JSON stream by calling
+// GetInt(), GetDouble(), GetString() and GetBool(), traverse into structures
+// by calling EnterObject() and EnterArray(), and skip over unwanted data by
+// calling SkipValue(). When you know your JSON's structure, this can be quite
+// convenient.
+//
+// If you aren't sure of what's next in the JSON data, you can use PeekType() and
+// PeekValue() to look ahead to the next object before reading it.
+//
+// If you call the wrong retrieval method--e.g. GetInt when the next JSON token is
+// not an int, EnterObject or EnterArray when there isn't actually an object or array
+// to read--the stream parsing will end immediately and no more data will be delivered.
+//
+// After calling EnterObject, you retrieve keys via NextObjectKey() and values via
+// the normal getters. When NextObjectKey() returns null, you have exited the
+// object, or you can call SkipObject() to skip to the end of the object
+// immediately. If you fetch the entire object (i.e. NextObjectKey() returned null),
+// you should not call SkipObject().
+//
+// After calling EnterArray(), you must alternate between calling NextArrayValue()
+// to see if the array has more data, and then retrieving values via the normal
+// getters. You can call SkipArray() to skip to the end of the array immediately.
+// If you fetch the entire array (i.e. NextArrayValue() returned null),
+// you should not call SkipArray().
+//
+// This parser uses in-situ strings, so the JSON buffer will be altered during the
+// parse.
+
+using namespace rapidjson;
+
+
+class LookaheadParserHandler {
+public:
+ bool Null() { st_ = kHasNull; v_.SetNull(); return true; }
+ bool Bool(bool b) { st_ = kHasBool; v_.SetBool(b); return true; }
+ bool Int(int i) { st_ = kHasNumber; v_.SetInt(i); return true; }
+ bool Uint(unsigned u) { st_ = kHasNumber; v_.SetUint(u); return true; }
+ bool Int64(int64_t i) { st_ = kHasNumber; v_.SetInt64(i); return true; }
+ bool Uint64(uint64_t u) { st_ = kHasNumber; v_.SetUint64(u); return true; }
+ bool Double(double d) { st_ = kHasNumber; v_.SetDouble(d); return true; }
+ bool RawNumber(const char*, SizeType, bool) { return false; }
+ bool String(const char* str, SizeType length, bool) { st_ = kHasString; v_.SetString(str, length); return true; }
+ bool StartObject() { st_ = kEnteringObject; return true; }
+ bool Key(const char* str, SizeType length, bool) { st_ = kHasKey; v_.SetString(str, length); return true; }
+ bool EndObject(SizeType) { st_ = kExitingObject; return true; }
+ bool StartArray() { st_ = kEnteringArray; return true; }
+ bool EndArray(SizeType) { st_ = kExitingArray; return true; }
+
+protected:
+ LookaheadParserHandler(char* str);
+ void ParseNext();
+
+protected:
+ enum LookaheadParsingState {
+ kInit,
+ kError,
+ kHasNull,
+ kHasBool,
+ kHasNumber,
+ kHasString,
+ kHasKey,
+ kEnteringObject,
+ kExitingObject,
+ kEnteringArray,
+ kExitingArray
+ };
+
+ Value v_;
+ LookaheadParsingState st_;
+ Reader r_;
+ InsituStringStream ss_;
+
+ static const int parseFlags = kParseDefaultFlags | kParseInsituFlag;
+};
+
+LookaheadParserHandler::LookaheadParserHandler(char* str) : v_(), st_(kInit), r_(), ss_(str) {
+ r_.IterativeParseInit();
+ ParseNext();
+}
+
+void LookaheadParserHandler::ParseNext() {
+ if (r_.HasParseError()) {
+ st_ = kError;
+ return;
+ }
+
+ r_.IterativeParseNext(ss_, *this);
+}
+
+class LookaheadParser : protected LookaheadParserHandler {
+public:
+ LookaheadParser(char* str) : LookaheadParserHandler(str) {}
+
+ bool EnterObject();
+ bool EnterArray();
+ const char* NextObjectKey();
+ bool NextArrayValue();
+ int GetInt();
+ double GetDouble();
+ const char* GetString();
+ bool GetBool();
+ void GetNull();
+
+ void SkipObject();
+ void SkipArray();
+ void SkipValue();
+ Value* PeekValue();
+ int PeekType(); // returns a rapidjson::Type, or -1 for no value (at end of object/array)
+
+ bool IsValid() { return st_ != kError; }
+
+protected:
+ void SkipOut(int depth);
+};
+
+bool LookaheadParser::EnterObject() {
+ if (st_ != kEnteringObject) {
+ st_ = kError;
+ return false;
+ }
+
+ ParseNext();
+ return true;
+}
+
+bool LookaheadParser::EnterArray() {
+ if (st_ != kEnteringArray) {
+ st_ = kError;
+ return false;
+ }
+
+ ParseNext();
+ return true;
+}
+
+const char* LookaheadParser::NextObjectKey() {
+ if (st_ == kHasKey) {
+ const char* result = v_.GetString();
+ ParseNext();
+ return result;
+ }
+
+ if (st_ != kExitingObject) {
+ st_ = kError;
+ return 0;
+ }
+
+ ParseNext();
+ return 0;
+}
+
+bool LookaheadParser::NextArrayValue() {
+ if (st_ == kExitingArray) {
+ ParseNext();
+ return false;
+ }
+
+ if (st_ == kError || st_ == kExitingObject || st_ == kHasKey) {
+ st_ = kError;
+ return false;
+ }
+
+ return true;
+}
+
+int LookaheadParser::GetInt() {
+ if (st_ != kHasNumber || !v_.IsInt()) {
+ st_ = kError;
+ return 0;
+ }
+
+ int result = v_.GetInt();
+ ParseNext();
+ return result;
+}
+
+double LookaheadParser::GetDouble() {
+ if (st_ != kHasNumber) {
+ st_ = kError;
+ return 0.;
+ }
+
+ double result = v_.GetDouble();
+ ParseNext();
+ return result;
+}
+
+bool LookaheadParser::GetBool() {
+ if (st_ != kHasBool) {
+ st_ = kError;
+ return false;
+ }
+
+ bool result = v_.GetBool();
+ ParseNext();
+ return result;
+}
+
+void LookaheadParser::GetNull() {
+ if (st_ != kHasNull) {
+ st_ = kError;
+ return;
+ }
+
+ ParseNext();
+}
+
+const char* LookaheadParser::GetString() {
+ if (st_ != kHasString) {
+ st_ = kError;
+ return 0;
+ }
+
+ const char* result = v_.GetString();
+ ParseNext();
+ return result;
+}
+
+void LookaheadParser::SkipOut(int depth) {
+ do {
+ if (st_ == kEnteringArray || st_ == kEnteringObject) {
+ ++depth;
+ }
+ else if (st_ == kExitingArray || st_ == kExitingObject) {
+ --depth;
+ }
+ else if (st_ == kError) {
+ return;
+ }
+
+ ParseNext();
+ }
+ while (depth > 0);
+}
+
+void LookaheadParser::SkipValue() {
+ SkipOut(0);
+}
+
+void LookaheadParser::SkipArray() {
+ SkipOut(1);
+}
+
+void LookaheadParser::SkipObject() {
+ SkipOut(1);
+}
+
+Value* LookaheadParser::PeekValue() {
+ if (st_ >= kHasNull && st_ <= kHasKey) {
+ return &v_;
+ }
+
+ return 0;
+}
+
+int LookaheadParser::PeekType() {
+ if (st_ >= kHasNull && st_ <= kHasKey) {
+ return v_.GetType();
+ }
+
+ if (st_ == kEnteringArray) {
+ return kArrayType;
+ }
+
+ if (st_ == kEnteringObject) {
+ return kObjectType;
+ }
+
+ return -1;
+}
+
+//-------------------------------------------------------------------------
+
+int main() {
+ using namespace std;
+
+ char json[] = " { \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null,"
+ "\"i\":123, \"pi\": 3.1416, \"a\":[-1, 2, 3, 4, \"array\", []], \"skipArrays\":[1, 2, [[[3]]]], "
+ "\"skipObject\":{ \"i\":0, \"t\":true, \"n\":null, \"d\":123.45 }, "
+ "\"skipNested\":[[[[{\"\":0}, {\"\":[-9.87]}]]], [], []], "
+ "\"skipString\":\"zzz\", \"reachedEnd\":null, \"t\":true }";
+
+ LookaheadParser r(json);
+
+ RAPIDJSON_ASSERT(r.PeekType() == kObjectType);
+
+ r.EnterObject();
+ while (const char* key = r.NextObjectKey()) {
+ if (0 == strcmp(key, "hello")) {
+ RAPIDJSON_ASSERT(r.PeekType() == kStringType);
+ cout << key << ":" << r.GetString() << endl;
+ }
+ else if (0 == strcmp(key, "t") || 0 == strcmp(key, "f")) {
+ RAPIDJSON_ASSERT(r.PeekType() == kTrueType || r.PeekType() == kFalseType);
+ cout << key << ":" << r.GetBool() << endl;
+ continue;
+ }
+ else if (0 == strcmp(key, "n")) {
+ RAPIDJSON_ASSERT(r.PeekType() == kNullType);
+ r.GetNull();
+ cout << key << endl;
+ continue;
+ }
+ else if (0 == strcmp(key, "pi")) {
+ RAPIDJSON_ASSERT(r.PeekType() == kNumberType);
+ cout << key << ":" << r.GetDouble() << endl;
+ continue;
+ }
+ else if (0 == strcmp(key, "a")) {
+ RAPIDJSON_ASSERT(r.PeekType() == kArrayType);
+
+ r.EnterArray();
+
+ cout << key << ":[ ";
+ while (r.NextArrayValue()) {
+ if (r.PeekType() == kNumberType) {
+ cout << r.GetDouble() << " ";
+ }
+ else if (r.PeekType() == kStringType) {
+ cout << r.GetString() << " ";
+ }
+ else {
+ r.SkipArray();
+ break;
+ }
+ }
+
+ cout << "]" << endl;
+ }
+ else {
+ cout << key << ":skipped" << endl;
+ r.SkipValue();
+ }
+ }
+
+ return 0;
+}
+
+RAPIDJSON_DIAG_POP
diff --git a/3rdparty/rapidjson/example/parsebyparts/parsebyparts.cpp b/3rdparty/rapidjson/example/parsebyparts/parsebyparts.cpp
index 57eed005dea..ff735394ec9 100644
--- a/3rdparty/rapidjson/example/parsebyparts/parsebyparts.cpp
+++ b/3rdparty/rapidjson/example/parsebyparts/parsebyparts.cpp
@@ -21,12 +21,15 @@ public:
AsyncDocumentParser(Document& d)
: stream_(*this)
, d_(d)
- , parseThread_(&AsyncDocumentParser::Parse, this)
+ , parseThread_()
, mutex_()
, notEmpty_()
, finish_()
, completed_()
- {}
+ {
+ // Create and execute thread after all member variables are initialized.
+ parseThread_ = std::thread(&AsyncDocumentParser::Parse, this);
+ }
~AsyncDocumentParser() {
if (!parseThread_.joinable())
@@ -140,7 +143,7 @@ int main() {
AsyncDocumentParser<> parser(d);
const char json1[] = " { \"hello\" : \"world\", \"t\" : tr";
- //const char json1[] = " { \"hello\" : \"world\", \"t\" : trX"; // Fot test parsing error
+ //const char json1[] = " { \"hello\" : \"world\", \"t\" : trX"; // For test parsing error
const char json2[] = "ue, \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.14";
const char json3[] = "16, \"a\":[1, 2, 3, 4] } ";
diff --git a/3rdparty/rapidjson/example/schemavalidator/schemavalidator.cpp b/3rdparty/rapidjson/example/schemavalidator/schemavalidator.cpp
index ce36ea95f00..6ce3c39e597 100644
--- a/3rdparty/rapidjson/example/schemavalidator/schemavalidator.cpp
+++ b/3rdparty/rapidjson/example/schemavalidator/schemavalidator.cpp
@@ -2,13 +2,132 @@
// The example validates JSON text from stdin with a JSON schema specified in the argument.
+#define RAPIDJSON_HAS_STDSTRING 1
+
#include "rapidjson/error/en.h"
#include "rapidjson/filereadstream.h"
#include "rapidjson/schema.h"
#include "rapidjson/stringbuffer.h"
+#include "rapidjson/prettywriter.h"
+#include
+#include
+#include
using namespace rapidjson;
+typedef GenericValue, CrtAllocator > ValueType;
+
+// Forward ref
+static void CreateErrorMessages(const ValueType& errors, size_t depth, const char* context);
+
+// Convert GenericValue to std::string
+static std::string GetString(const ValueType& val) {
+ std::ostringstream s;
+ if (val.IsString())
+ s << val.GetString();
+ else if (val.IsDouble())
+ s << val.GetDouble();
+ else if (val.IsUint())
+ s << val.GetUint();
+ else if (val.IsInt())
+ s << val.GetInt();
+ else if (val.IsUint64())
+ s << val.GetUint64();
+ else if (val.IsInt64())
+ s << val.GetInt64();
+ else if (val.IsBool() && val.GetBool())
+ s << "true";
+ else if (val.IsBool())
+ s << "false";
+ else if (val.IsFloat())
+ s << val.GetFloat();
+ return s.str();
+}
+
+// Create the error message for a named error
+// The error object can either be empty or contain at least member properties:
+// {"errorCode": , "instanceRef": "", "schemaRef": "" }
+// Additional properties may be present for use as inserts.
+// An "errors" property may be present if there are child errors.
+static void HandleError(const char* errorName, const ValueType& error, size_t depth, const char* context) {
+ if (!error.ObjectEmpty()) {
+ // Get error code and look up error message text (English)
+ int code = error["errorCode"].GetInt();
+ std::string message(GetValidateError_En(static_cast(code)));
+ // For each member property in the error, see if its name exists as an insert in the error message and if so replace with the stringified property value
+ // So for example - "Number '%actual' is not a multiple of the 'multipleOf' value '%expected'." - we would expect "actual" and "expected" members.
+ for (ValueType::ConstMemberIterator insertsItr = error.MemberBegin();
+ insertsItr != error.MemberEnd(); ++insertsItr) {
+ std::string insertName("%");
+ insertName += insertsItr->name.GetString(); // eg "%actual"
+ size_t insertPos = message.find(insertName);
+ if (insertPos != std::string::npos) {
+ std::string insertString("");
+ const ValueType &insert = insertsItr->value;
+ if (insert.IsArray()) {
+ // Member is an array so create comma-separated list of items for the insert string
+ for (ValueType::ConstValueIterator itemsItr = insert.Begin(); itemsItr != insert.End(); ++itemsItr) {
+ if (itemsItr != insert.Begin()) insertString += ",";
+ insertString += GetString(*itemsItr);
+ }
+ } else {
+ insertString += GetString(insert);
+ }
+ message.replace(insertPos, insertName.length(), insertString);
+ }
+ }
+ // Output error message, references, context
+ std::string indent(depth * 2, ' ');
+ std::cout << indent << "Error Name: " << errorName << std::endl;
+ std::cout << indent << "Message: " << message.c_str() << std::endl;
+ std::cout << indent << "Instance: " << error["instanceRef"].GetString() << std::endl;
+ std::cout << indent << "Schema: " << error["schemaRef"].GetString() << std::endl;
+ if (depth > 0) std::cout << indent << "Context: " << context << std::endl;
+ std::cout << std::endl;
+
+ // If child errors exist, apply the process recursively to each error structure.
+ // This occurs for "oneOf", "allOf", "anyOf" and "dependencies" errors, so pass the error name as context.
+ if (error.HasMember("errors")) {
+ depth++;
+ const ValueType &childErrors = error["errors"];
+ if (childErrors.IsArray()) {
+ // Array - each item is an error structure - example
+ // "anyOf": {"errorCode": ..., "errors":[{"pattern": {"errorCode\": ...\"}}, {"pattern": {"errorCode\": ...}}]
+ for (ValueType::ConstValueIterator errorsItr = childErrors.Begin();
+ errorsItr != childErrors.End(); ++errorsItr) {
+ CreateErrorMessages(*errorsItr, depth, errorName);
+ }
+ } else if (childErrors.IsObject()) {
+ // Object - each member is an error structure - example
+ // "dependencies": {"errorCode": ..., "errors": {"address": {"required": {"errorCode": ...}}, "name": {"required": {"errorCode": ...}}}
+ for (ValueType::ConstMemberIterator propsItr = childErrors.MemberBegin();
+ propsItr != childErrors.MemberEnd(); ++propsItr) {
+ CreateErrorMessages(propsItr->value, depth, errorName);
+ }
+ }
+ }
+ }
+}
+
+// Create error message for all errors in an error structure
+// Context is used to indicate whether the error structure has a parent 'dependencies', 'allOf', 'anyOf' or 'oneOf' error
+static void CreateErrorMessages(const ValueType& errors, size_t depth = 0, const char* context = 0) {
+ // Each member property contains one or more errors of a given type
+ for (ValueType::ConstMemberIterator errorTypeItr = errors.MemberBegin(); errorTypeItr != errors.MemberEnd(); ++errorTypeItr) {
+ const char* errorName = errorTypeItr->name.GetString();
+ const ValueType& errorContent = errorTypeItr->value;
+ if (errorContent.IsArray()) {
+ // Member is an array where each item is an error - eg "type": [{"errorCode": ...}, {"errorCode": ...}]
+ for (ValueType::ConstValueIterator contentItr = errorContent.Begin(); contentItr != errorContent.End(); ++contentItr) {
+ HandleError(errorName, *contentItr, depth, context);
+ }
+ } else if (errorContent.IsObject()) {
+ // Member is an object which is a single error - eg "type": {"errorCode": ... }
+ HandleError(errorName, errorContent, depth, context);
+ }
+ }
+}
+
int main(int argc, char *argv[]) {
if (argc != 2) {
fprintf(stderr, "Usage: schemavalidator schema.json < input.json\n");
@@ -64,9 +183,17 @@ int main(int argc, char *argv[]) {
validator.GetInvalidSchemaPointer().StringifyUriFragment(sb);
fprintf(stderr, "Invalid schema: %s\n", sb.GetString());
fprintf(stderr, "Invalid keyword: %s\n", validator.GetInvalidSchemaKeyword());
+ fprintf(stderr, "Invalid code: %d\n", validator.GetInvalidSchemaCode());
+ fprintf(stderr, "Invalid message: %s\n", GetValidateError_En(validator.GetInvalidSchemaCode()));
sb.Clear();
validator.GetInvalidDocumentPointer().StringifyUriFragment(sb);
fprintf(stderr, "Invalid document: %s\n", sb.GetString());
+ // Detailed violation report is available as a JSON value
+ sb.Clear();
+ PrettyWriter w(sb);
+ validator.GetError().Accept(w);
+ fprintf(stderr, "Error report:\n%s\n", sb.GetString());
+ CreateErrorMessages(validator.GetError());
return EXIT_FAILURE;
}
}
diff --git a/3rdparty/rapidjson/example/simplepullreader/simplepullreader.cpp b/3rdparty/rapidjson/example/simplepullreader/simplepullreader.cpp
new file mode 100644
index 00000000000..a4fb1161a4c
--- /dev/null
+++ b/3rdparty/rapidjson/example/simplepullreader/simplepullreader.cpp
@@ -0,0 +1,53 @@
+#include "rapidjson/reader.h"
+#include
+#include
+
+using namespace rapidjson;
+using namespace std;
+
+// If you can require C++11, you could use std::to_string here
+template std::string stringify(T x) {
+ std::stringstream ss;
+ ss << x;
+ return ss.str();
+}
+
+struct MyHandler {
+ const char* type;
+ std::string data;
+
+ MyHandler() : type(), data() {}
+
+ bool Null() { type = "Null"; data.clear(); return true; }
+ bool Bool(bool b) { type = "Bool:"; data = b? "true": "false"; return true; }
+ bool Int(int i) { type = "Int:"; data = stringify(i); return true; }
+ bool Uint(unsigned u) { type = "Uint:"; data = stringify(u); return true; }
+ bool Int64(int64_t i) { type = "Int64:"; data = stringify(i); return true; }
+ bool Uint64(uint64_t u) { type = "Uint64:"; data = stringify(u); return true; }
+ bool Double(double d) { type = "Double:"; data = stringify(d); return true; }
+ bool RawNumber(const char* str, SizeType length, bool) { type = "Number:"; data = std::string(str, length); return true; }
+ bool String(const char* str, SizeType length, bool) { type = "String:"; data = std::string(str, length); return true; }
+ bool StartObject() { type = "StartObject"; data.clear(); return true; }
+ bool Key(const char* str, SizeType length, bool) { type = "Key:"; data = std::string(str, length); return true; }
+ bool EndObject(SizeType memberCount) { type = "EndObject:"; data = stringify(memberCount); return true; }
+ bool StartArray() { type = "StartArray"; data.clear(); return true; }
+ bool EndArray(SizeType elementCount) { type = "EndArray:"; data = stringify(elementCount); return true; }
+private:
+ MyHandler(const MyHandler& noCopyConstruction);
+ MyHandler& operator=(const MyHandler& noAssignment);
+};
+
+int main() {
+ const char json[] = " { \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3, 4] } ";
+
+ MyHandler handler;
+ Reader reader;
+ StringStream ss(json);
+ reader.IterativeParseInit();
+ while (!reader.IterativeParseComplete()) {
+ reader.IterativeParseNext(ss, handler);
+ cout << handler.type << handler.data << endl;
+ }
+
+ return 0;
+}
diff --git a/3rdparty/rapidjson/example/sortkeys/sortkeys.cpp b/3rdparty/rapidjson/example/sortkeys/sortkeys.cpp
new file mode 100644
index 00000000000..7ede9fb938b
--- /dev/null
+++ b/3rdparty/rapidjson/example/sortkeys/sortkeys.cpp
@@ -0,0 +1,62 @@
+#include "rapidjson/document.h"
+#include "rapidjson/filewritestream.h"
+#include
+
+#include
+#include
+
+using namespace rapidjson;
+using namespace std;
+
+static void printIt(const Value &doc) {
+ char writeBuffer[65536];
+ FileWriteStream os(stdout, writeBuffer, sizeof(writeBuffer));
+ PrettyWriter writer(os);
+ doc.Accept(writer);
+ cout << endl;
+}
+
+struct NameComparator {
+ bool operator()(const Value::Member &lhs, const Value::Member &rhs) const {
+ return (strcmp(lhs.name.GetString(), rhs.name.GetString()) < 0);
+ }
+};
+
+int main() {
+ Document d(kObjectType);
+ Document::AllocatorType &allocator = d.GetAllocator();
+
+ d.AddMember("zeta", Value().SetBool(false), allocator);
+ d.AddMember("gama", Value().SetString("test string", allocator), allocator);
+ d.AddMember("delta", Value().SetInt(123), allocator);
+ d.AddMember("alpha", Value(kArrayType).Move(), allocator);
+
+ printIt(d);
+
+/*
+{
+ "zeta": false,
+ "gama": "test string",
+ "delta": 123,
+ "alpha": []
+}
+*/
+
+// C++11 supports std::move() of Value so it always have no problem for std::sort().
+// Some C++03 implementations of std::sort() requires copy constructor which causes compilation error.
+// Needs a sorting function only depends on std::swap() instead.
+#if __cplusplus >= 201103L || (!defined(__GLIBCXX__) && (!defined(_MSC_VER) || _MSC_VER >= 1900))
+ std::sort(d.MemberBegin(), d.MemberEnd(), NameComparator());
+
+ printIt(d);
+
+/*
+{
+ "alpha": [],
+ "delta": 123,
+ "gama": "test string",
+ "zeta": false
+}
+*/
+#endif
+}
diff --git a/3rdparty/rapidjson/example/traverseaspointer.cpp b/3rdparty/rapidjson/example/traverseaspointer.cpp
new file mode 100644
index 00000000000..7e0c89923e4
--- /dev/null
+++ b/3rdparty/rapidjson/example/traverseaspointer.cpp
@@ -0,0 +1,39 @@
+#include "rapidjson/document.h"
+#include "rapidjson/filereadstream.h"
+#include "rapidjson/pointer.h"
+#include "rapidjson/stringbuffer.h"
+#include
+
+using namespace rapidjson;
+
+void traverse(const Value& v, const Pointer& p) {
+ StringBuffer sb;
+ p.Stringify(sb);
+ std::cout << sb.GetString() << std::endl;
+
+ switch (v.GetType()) {
+ case kArrayType:
+ for (SizeType i = 0; i != v.Size(); ++i)
+ traverse(v[i], p.Append(i));
+ break;
+ case kObjectType:
+ for (Value::ConstMemberIterator m = v.MemberBegin(); m != v.MemberEnd(); ++m)
+ traverse(m->value, p.Append(m->name.GetString(), m->name.GetStringLength()));
+ break;
+ default:
+ break;
+ }
+}
+
+int main(int, char*[]) {
+ char readBuffer[65536];
+ FileReadStream is(stdin, readBuffer, sizeof(readBuffer));
+
+ Document d;
+ d.ParseStream(is);
+
+ Pointer root;
+ traverse(d, root);
+
+ return 0;
+}
diff --git a/3rdparty/rapidjson/example/tutorial/tutorial.cpp b/3rdparty/rapidjson/example/tutorial/tutorial.cpp
index c8bfcc14c18..d6021c66891 100644
--- a/3rdparty/rapidjson/example/tutorial/tutorial.cpp
+++ b/3rdparty/rapidjson/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/3rdparty/rapidjson/include/rapidjson/allocators.h b/3rdparty/rapidjson/include/rapidjson/allocators.h
index 98affe03fbf..ddcf4781bea 100644
--- a/3rdparty/rapidjson/include/rapidjson/allocators.h
+++ b/3rdparty/rapidjson/include/rapidjson/allocators.h
@@ -1,6 +1,6 @@
// 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.
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
//
// 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
@@ -16,6 +16,14 @@
#define RAPIDJSON_ALLOCATORS_H_
#include "rapidjson.h"
+#include "internal/meta.h"
+
+#include
+#include
+
+#if RAPIDJSON_HAS_CXX11
+#include
+#endif
RAPIDJSON_NAMESPACE_BEGIN
@@ -52,6 +60,19 @@ concept Allocator {
\endcode
*/
+
+/*! \def RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY
+ \ingroup RAPIDJSON_CONFIG
+ \brief User-defined kDefaultChunkCapacity definition.
+
+ User can define this as any \c size that is a power of 2.
+*/
+
+#ifndef RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY
+#define RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY (64 * 1024)
+#endif
+
+
///////////////////////////////////////////////////////////////////////////////
// CrtAllocator
@@ -64,19 +85,26 @@ public:
static const bool kNeedFree = true;
void* Malloc(size_t size) {
if (size) // behavior of malloc(0) is implementation defined.
- return std::malloc(size);
+ return RAPIDJSON_MALLOC(size);
else
return NULL; // standardize to returning NULL.
}
void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) {
(void)originalSize;
if (newSize == 0) {
- std::free(originalPtr);
+ RAPIDJSON_FREE(originalPtr);
return NULL;
}
- return std::realloc(originalPtr, newSize);
+ return RAPIDJSON_REALLOC(originalPtr, newSize);
+ }
+ static void Free(void *ptr) RAPIDJSON_NOEXCEPT { RAPIDJSON_FREE(ptr); }
+
+ bool operator==(const CrtAllocator&) const RAPIDJSON_NOEXCEPT {
+ return true;
+ }
+ bool operator!=(const CrtAllocator&) const RAPIDJSON_NOEXCEPT {
+ return false;
}
- static void Free(void *ptr) { std::free(ptr); }
};
///////////////////////////////////////////////////////////////////////////////
@@ -100,16 +128,64 @@ public:
*/
template
class MemoryPoolAllocator {
+ //! Chunk header for perpending to each chunk.
+ /*! Chunks are stored as a singly linked list.
+ */
+ struct ChunkHeader {
+ size_t capacity; //!< Capacity of the chunk in bytes (excluding the header itself).
+ size_t size; //!< Current size of allocated memory in bytes.
+ ChunkHeader *next; //!< Next chunk in the linked list.
+ };
+
+ struct SharedData {
+ ChunkHeader *chunkHead; //!< Head of the chunk linked-list. Only the head chunk serves allocation.
+ BaseAllocator* ownBaseAllocator; //!< base allocator created by this object.
+ size_t refcount;
+ bool ownBuffer;
+ };
+
+ static const size_t SIZEOF_SHARED_DATA = RAPIDJSON_ALIGN(sizeof(SharedData));
+ static const size_t SIZEOF_CHUNK_HEADER = RAPIDJSON_ALIGN(sizeof(ChunkHeader));
+
+ static inline ChunkHeader *GetChunkHead(SharedData *shared)
+ {
+ return reinterpret_cast(reinterpret_cast(shared) + SIZEOF_SHARED_DATA);
+ }
+ static inline uint8_t *GetChunkBuffer(SharedData *shared)
+ {
+ return reinterpret_cast(shared->chunkHead) + SIZEOF_CHUNK_HEADER;
+ }
+
+ static const size_t kDefaultChunkCapacity = RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY; //!< Default chunk capacity.
+
public:
static const bool kNeedFree = false; //!< Tell users that no need to call Free() with this allocator. (concept Allocator)
+ static const bool kRefCounted = true; //!< Tell users that this allocator is reference counted on copy
//! Constructor with chunkSize.
/*! \param chunkSize The size of memory chunk. The default is kDefaultChunkSize.
\param baseAllocator The allocator for allocating memory chunks.
*/
+ explicit
MemoryPoolAllocator(size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) :
- chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(0), baseAllocator_(baseAllocator), ownBaseAllocator_(0)
+ chunk_capacity_(chunkSize),
+ baseAllocator_(baseAllocator ? baseAllocator : RAPIDJSON_NEW(BaseAllocator)()),
+ shared_(static_cast(baseAllocator_ ? baseAllocator_->Malloc(SIZEOF_SHARED_DATA + SIZEOF_CHUNK_HEADER) : 0))
{
+ RAPIDJSON_ASSERT(baseAllocator_ != 0);
+ RAPIDJSON_ASSERT(shared_ != 0);
+ if (baseAllocator) {
+ shared_->ownBaseAllocator = 0;
+ }
+ else {
+ shared_->ownBaseAllocator = baseAllocator_;
+ }
+ shared_->chunkHead = GetChunkHead(shared_);
+ shared_->chunkHead->capacity = 0;
+ shared_->chunkHead->size = 0;
+ shared_->chunkHead->next = 0;
+ shared_->ownBuffer = true;
+ shared_->refcount = 1;
}
//! Constructor with user-supplied buffer.
@@ -123,41 +199,101 @@ public:
\param baseAllocator The allocator for allocating memory chunks.
*/
MemoryPoolAllocator(void *buffer, size_t size, size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) :
- chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(buffer), baseAllocator_(baseAllocator), ownBaseAllocator_(0)
+ chunk_capacity_(chunkSize),
+ baseAllocator_(baseAllocator),
+ shared_(static_cast(AlignBuffer(buffer, size)))
{
- RAPIDJSON_ASSERT(buffer != 0);
- RAPIDJSON_ASSERT(size > sizeof(ChunkHeader));
- chunkHead_ = reinterpret_cast(buffer);
- chunkHead_->capacity = size - sizeof(ChunkHeader);
- chunkHead_->size = 0;
- chunkHead_->next = 0;
+ RAPIDJSON_ASSERT(size >= SIZEOF_SHARED_DATA + SIZEOF_CHUNK_HEADER);
+ shared_->chunkHead = GetChunkHead(shared_);
+ shared_->chunkHead->capacity = size - SIZEOF_SHARED_DATA - SIZEOF_CHUNK_HEADER;
+ shared_->chunkHead->size = 0;
+ shared_->chunkHead->next = 0;
+ shared_->ownBaseAllocator = 0;
+ shared_->ownBuffer = false;
+ shared_->refcount = 1;
}
+ MemoryPoolAllocator(const MemoryPoolAllocator& rhs) RAPIDJSON_NOEXCEPT :
+ chunk_capacity_(rhs.chunk_capacity_),
+ baseAllocator_(rhs.baseAllocator_),
+ shared_(rhs.shared_)
+ {
+ RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0);
+ ++shared_->refcount;
+ }
+ MemoryPoolAllocator& operator=(const MemoryPoolAllocator& rhs) RAPIDJSON_NOEXCEPT
+ {
+ RAPIDJSON_NOEXCEPT_ASSERT(rhs.shared_->refcount > 0);
+ ++rhs.shared_->refcount;
+ this->~MemoryPoolAllocator();
+ baseAllocator_ = rhs.baseAllocator_;
+ chunk_capacity_ = rhs.chunk_capacity_;
+ shared_ = rhs.shared_;
+ return *this;
+ }
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+ MemoryPoolAllocator(MemoryPoolAllocator&& rhs) RAPIDJSON_NOEXCEPT :
+ chunk_capacity_(rhs.chunk_capacity_),
+ baseAllocator_(rhs.baseAllocator_),
+ shared_(rhs.shared_)
+ {
+ RAPIDJSON_NOEXCEPT_ASSERT(rhs.shared_->refcount > 0);
+ rhs.shared_ = 0;
+ }
+ MemoryPoolAllocator& operator=(MemoryPoolAllocator&& rhs) RAPIDJSON_NOEXCEPT
+ {
+ RAPIDJSON_NOEXCEPT_ASSERT(rhs.shared_->refcount > 0);
+ this->~MemoryPoolAllocator();
+ baseAllocator_ = rhs.baseAllocator_;
+ chunk_capacity_ = rhs.chunk_capacity_;
+ shared_ = rhs.shared_;
+ rhs.shared_ = 0;
+ return *this;
+ }
+#endif
+
//! Destructor.
/*! This deallocates all memory chunks, excluding the user-supplied buffer.
*/
- ~MemoryPoolAllocator() {
+ ~MemoryPoolAllocator() RAPIDJSON_NOEXCEPT {
+ if (!shared_) {
+ // do nothing if moved
+ return;
+ }
+ if (shared_->refcount > 1) {
+ --shared_->refcount;
+ return;
+ }
Clear();
- RAPIDJSON_DELETE(ownBaseAllocator_);
+ BaseAllocator *a = shared_->ownBaseAllocator;
+ if (shared_->ownBuffer) {
+ baseAllocator_->Free(shared_);
+ }
+ RAPIDJSON_DELETE(a);
}
- //! Deallocates all memory chunks, excluding the user-supplied buffer.
- void Clear() {
- while (chunkHead_ && chunkHead_ != userBuffer_) {
- ChunkHeader* next = chunkHead_->next;
- baseAllocator_->Free(chunkHead_);
- chunkHead_ = next;
+ //! Deallocates all memory chunks, excluding the first/user one.
+ void Clear() RAPIDJSON_NOEXCEPT {
+ RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0);
+ for (;;) {
+ ChunkHeader* c = shared_->chunkHead;
+ if (!c->next) {
+ break;
+ }
+ shared_->chunkHead = c->next;
+ baseAllocator_->Free(c);
}
- if (chunkHead_ && chunkHead_ == userBuffer_)
- chunkHead_->size = 0; // Clear user buffer
+ shared_->chunkHead->size = 0;
}
//! Computes the total capacity of allocated memory chunks.
/*! \return total capacity in bytes.
*/
- size_t Capacity() const {
+ size_t Capacity() const RAPIDJSON_NOEXCEPT {
+ RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0);
size_t capacity = 0;
- for (ChunkHeader* c = chunkHead_; c != 0; c = c->next)
+ for (ChunkHeader* c = shared_->chunkHead; c != 0; c = c->next)
capacity += c->capacity;
return capacity;
}
@@ -165,25 +301,35 @@ public:
//! Computes the memory blocks allocated.
/*! \return total used bytes.
*/
- size_t Size() const {
+ size_t Size() const RAPIDJSON_NOEXCEPT {
+ RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0);
size_t size = 0;
- for (ChunkHeader* c = chunkHead_; c != 0; c = c->next)
+ for (ChunkHeader* c = shared_->chunkHead; c != 0; c = c->next)
size += c->size;
return size;
}
+ //! Whether the allocator is shared.
+ /*! \return true or false.
+ */
+ bool Shared() const RAPIDJSON_NOEXCEPT {
+ RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0);
+ return shared_->refcount > 1;
+ }
+
//! Allocates a memory block. (concept Allocator)
void* Malloc(size_t size) {
+ RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0);
if (!size)
return NULL;
size = RAPIDJSON_ALIGN(size);
- if (chunkHead_ == 0 || chunkHead_->size + size > chunkHead_->capacity)
+ if (RAPIDJSON_UNLIKELY(shared_->chunkHead->size + size > shared_->chunkHead->capacity))
if (!AddChunk(chunk_capacity_ > size ? chunk_capacity_ : size))
return NULL;
- void *buffer = reinterpret_cast(chunkHead_) + RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + chunkHead_->size;
- chunkHead_->size += size;
+ void *buffer = GetChunkBuffer(shared_) + shared_->chunkHead->size;
+ shared_->chunkHead->size += size;
return buffer;
}
@@ -192,6 +338,7 @@ public:
if (originalPtr == 0)
return Malloc(newSize);
+ RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0);
if (newSize == 0)
return NULL;
@@ -203,10 +350,10 @@ public:
return originalPtr;
// Simply expand it if it is the last allocation and there is sufficient space
- if (originalPtr == reinterpret_cast(chunkHead_) + RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + chunkHead_->size - originalSize) {
+ if (originalPtr == GetChunkBuffer(shared_) + shared_->chunkHead->size - originalSize) {
size_t increment = static_cast(newSize - originalSize);
- if (chunkHead_->size + increment <= chunkHead_->capacity) {
- chunkHead_->size += increment;
+ if (shared_->chunkHead->size + increment <= shared_->chunkHead->capacity) {
+ shared_->chunkHead->size += increment;
return originalPtr;
}
}
@@ -222,50 +369,325 @@ public:
}
//! Frees a memory block (concept Allocator)
- static void Free(void *ptr) { (void)ptr; } // Do nothing
+ static void Free(void *ptr) RAPIDJSON_NOEXCEPT { (void)ptr; } // Do nothing
+
+ //! Compare (equality) with another MemoryPoolAllocator
+ bool operator==(const MemoryPoolAllocator& rhs) const RAPIDJSON_NOEXCEPT {
+ RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0);
+ RAPIDJSON_NOEXCEPT_ASSERT(rhs.shared_->refcount > 0);
+ return shared_ == rhs.shared_;
+ }
+ //! Compare (inequality) with another MemoryPoolAllocator
+ bool operator!=(const MemoryPoolAllocator& rhs) const RAPIDJSON_NOEXCEPT {
+ return !operator==(rhs);
+ }
private:
- //! Copy constructor is not permitted.
- MemoryPoolAllocator(const MemoryPoolAllocator& rhs) /* = delete */;
- //! Copy assignment operator is not permitted.
- MemoryPoolAllocator& operator=(const MemoryPoolAllocator& rhs) /* = delete */;
-
//! Creates a new chunk.
/*! \param capacity Capacity of the chunk in bytes.
\return true if success.
*/
bool AddChunk(size_t capacity) {
if (!baseAllocator_)
- ownBaseAllocator_ = baseAllocator_ = RAPIDJSON_NEW(BaseAllocator());
- if (ChunkHeader* chunk = reinterpret_cast(baseAllocator_->Malloc(RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + capacity))) {
+ shared_->ownBaseAllocator = baseAllocator_ = RAPIDJSON_NEW(BaseAllocator)();
+ if (ChunkHeader* chunk = static_cast(baseAllocator_->Malloc(SIZEOF_CHUNK_HEADER + capacity))) {
chunk->capacity = capacity;
chunk->size = 0;
- chunk->next = chunkHead_;
- chunkHead_ = chunk;
+ chunk->next = shared_->chunkHead;
+ shared_->chunkHead = chunk;
return true;
}
else
return false;
}
- static const int kDefaultChunkCapacity = 64 * 1024; //!< Default chunk capacity.
+ static inline void* AlignBuffer(void* buf, size_t &size)
+ {
+ RAPIDJSON_NOEXCEPT_ASSERT(buf != 0);
+ const uintptr_t mask = sizeof(void*) - 1;
+ const uintptr_t ubuf = reinterpret_cast(buf);
+ if (RAPIDJSON_UNLIKELY(ubuf & mask)) {
+ const uintptr_t abuf = (ubuf + mask) & ~mask;
+ RAPIDJSON_ASSERT(size >= abuf - ubuf);
+ buf = reinterpret_cast(abuf);
+ size -= abuf - ubuf;
+ }
+ return buf;
+ }
- //! Chunk header for perpending to each chunk.
- /*! Chunks are stored as a singly linked list.
- */
- struct ChunkHeader {
- size_t capacity; //!< Capacity of the chunk in bytes (excluding the header itself).
- size_t size; //!< Current size of allocated memory in bytes.
- ChunkHeader *next; //!< Next chunk in the linked list.
+ size_t chunk_capacity_; //!< The minimum capacity of chunk when they are allocated.
+ BaseAllocator* baseAllocator_; //!< base allocator for allocating memory chunks.
+ SharedData *shared_; //!< The shared data of the allocator
+};
+
+namespace internal {
+ template
+ struct IsRefCounted :
+ public FalseType
+ { };
+ template
+ struct IsRefCounted::Type> :
+ public TrueType
+ { };
+}
+
+template
+inline T* Realloc(A& a, T* old_p, size_t old_n, size_t new_n)
+{
+ RAPIDJSON_NOEXCEPT_ASSERT(old_n <= std::numeric_limits::max() / sizeof(T) && new_n <= std::numeric_limits::max() / sizeof(T));
+ return static_cast(a.Realloc(old_p, old_n * sizeof(T), new_n * sizeof(T)));
+}
+
+template
+inline T *Malloc(A& a, size_t n = 1)
+{
+ return Realloc(a, NULL, 0, n);
+}
+
+template
+inline void Free(A& a, T *p, size_t n = 1)
+{
+ static_cast(Realloc(a, p, n, 0));
+}
+
+#ifdef __GNUC__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(effc++) // std::allocator can safely be inherited
+#endif
+
+template
+class StdAllocator :
+ public std::allocator
+{
+ typedef std::allocator allocator_type;
+#if RAPIDJSON_HAS_CXX11
+ typedef std::allocator_traits traits_type;
+#else
+ typedef allocator_type traits_type;
+#endif
+
+public:
+ typedef BaseAllocator BaseAllocatorType;
+
+ StdAllocator() RAPIDJSON_NOEXCEPT :
+ allocator_type(),
+ baseAllocator_()
+ { }
+
+ StdAllocator(const StdAllocator& rhs) RAPIDJSON_NOEXCEPT :
+ allocator_type(rhs),
+ baseAllocator_(rhs.baseAllocator_)
+ { }
+
+ template
+ StdAllocator(const StdAllocator& rhs) RAPIDJSON_NOEXCEPT :
+ allocator_type(rhs),
+ baseAllocator_(rhs.baseAllocator_)
+ { }
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+ StdAllocator(StdAllocator&& rhs) RAPIDJSON_NOEXCEPT :
+ allocator_type(std::move(rhs)),
+ baseAllocator_(std::move(rhs.baseAllocator_))
+ { }
+#endif
+#if RAPIDJSON_HAS_CXX11
+ using propagate_on_container_move_assignment = std::true_type;
+ using propagate_on_container_swap = std::true_type;
+#endif
+
+ /* implicit */
+ StdAllocator(const BaseAllocator& allocator) RAPIDJSON_NOEXCEPT :
+ allocator_type(),
+ baseAllocator_(allocator)
+ { }
+
+ ~StdAllocator() RAPIDJSON_NOEXCEPT
+ { }
+
+ template
+ struct rebind {
+ typedef StdAllocator other;
};
- ChunkHeader *chunkHead_; //!< Head of the chunk linked-list. Only the head chunk serves allocation.
- size_t chunk_capacity_; //!< The minimum capacity of chunk when they are allocated.
- void *userBuffer_; //!< User supplied buffer.
- BaseAllocator* baseAllocator_; //!< base allocator for allocating memory chunks.
- BaseAllocator* ownBaseAllocator_; //!< base allocator created by this object.
+ typedef typename traits_type::size_type size_type;
+ typedef typename traits_type::difference_type difference_type;
+
+ typedef typename traits_type::value_type value_type;
+ typedef typename traits_type::pointer pointer;
+ typedef typename traits_type::const_pointer const_pointer;
+
+#if RAPIDJSON_HAS_CXX11
+
+ typedef typename std::add_lvalue_reference::type &reference;
+ typedef typename std::add_lvalue_reference::type>::type &const_reference;
+
+ pointer address(reference r) const RAPIDJSON_NOEXCEPT
+ {
+ return std::addressof(r);
+ }
+ const_pointer address(const_reference r) const RAPIDJSON_NOEXCEPT
+ {
+ return std::addressof(r);
+ }
+
+ size_type max_size() const RAPIDJSON_NOEXCEPT
+ {
+ return traits_type::max_size(*this);
+ }
+
+ template
+ void construct(pointer p, Args&&... args)
+ {
+ traits_type::construct(*this, p, std::forward(args)...);
+ }
+ void destroy(pointer p)
+ {
+ traits_type::destroy(*this, p);
+ }
+
+#else // !RAPIDJSON_HAS_CXX11
+
+ typedef typename allocator_type::reference reference;
+ typedef typename allocator_type::const_reference const_reference;
+
+ pointer address(reference r) const RAPIDJSON_NOEXCEPT
+ {
+ return allocator_type::address(r);
+ }
+ const_pointer address(const_reference r) const RAPIDJSON_NOEXCEPT
+ {
+ return allocator_type::address(r);
+ }
+
+ size_type max_size() const RAPIDJSON_NOEXCEPT
+ {
+ return allocator_type::max_size();
+ }
+
+ void construct(pointer p, const_reference r)
+ {
+ allocator_type::construct(p, r);
+ }
+ void destroy(pointer p)
+ {
+ allocator_type::destroy(p);
+ }
+
+#endif // !RAPIDJSON_HAS_CXX11
+
+ template
+ U* allocate(size_type n = 1, const void* = 0)
+ {
+ return RAPIDJSON_NAMESPACE::Malloc(baseAllocator_, n);
+ }
+ template
+ void deallocate(U* p, size_type n = 1)
+ {
+ RAPIDJSON_NAMESPACE::Free(baseAllocator_, p, n);
+ }
+
+ pointer allocate(size_type n = 1, const void* = 0)
+ {
+ return allocate(n);
+ }
+ void deallocate(pointer p, size_type n = 1)
+ {
+ deallocate(p, n);
+ }
+
+#if RAPIDJSON_HAS_CXX11
+ using is_always_equal = std::is_empty;
+#endif
+
+ template
+ bool operator==(const StdAllocator& rhs) const RAPIDJSON_NOEXCEPT
+ {
+ return baseAllocator_ == rhs.baseAllocator_;
+ }
+ template
+ bool operator!=(const StdAllocator& rhs) const RAPIDJSON_NOEXCEPT
+ {
+ return !operator==(rhs);
+ }
+
+ //! rapidjson Allocator concept
+ static const bool kNeedFree = BaseAllocator::kNeedFree;
+ static const bool kRefCounted = internal::IsRefCounted::Value;
+ void* Malloc(size_t size)
+ {
+ return baseAllocator_.Malloc(size);
+ }
+ void* Realloc(void* originalPtr, size_t originalSize, size_t newSize)
+ {
+ return baseAllocator_.Realloc(originalPtr, originalSize, newSize);
+ }
+ static void Free(void *ptr) RAPIDJSON_NOEXCEPT
+ {
+ BaseAllocator::Free(ptr);
+ }
+
+private:
+ template
+ friend class StdAllocator; // access to StdAllocator.*
+
+ BaseAllocator baseAllocator_;
};
+#if !RAPIDJSON_HAS_CXX17 // std::allocator deprecated in C++17
+template
+class StdAllocator :
+ public std::allocator
+{
+ typedef std::allocator allocator_type;
+
+public:
+ typedef BaseAllocator BaseAllocatorType;
+
+ StdAllocator() RAPIDJSON_NOEXCEPT :
+ allocator_type(),
+ baseAllocator_()
+ { }
+
+ StdAllocator(const StdAllocator& rhs) RAPIDJSON_NOEXCEPT :
+ allocator_type(rhs),
+ baseAllocator_(rhs.baseAllocator_)
+ { }
+
+ template
+ StdAllocator(const StdAllocator& rhs) RAPIDJSON_NOEXCEPT :
+ allocator_type(rhs),
+ baseAllocator_(rhs.baseAllocator_)
+ { }
+
+ /* implicit */
+ StdAllocator(const BaseAllocator& baseAllocator) RAPIDJSON_NOEXCEPT :
+ allocator_type(),
+ baseAllocator_(baseAllocator)
+ { }
+
+ ~StdAllocator() RAPIDJSON_NOEXCEPT
+ { }
+
+ template
+ struct rebind {
+ typedef StdAllocator other;
+ };
+
+ typedef typename allocator_type::value_type value_type;
+
+private:
+ template
+ friend class StdAllocator; // access to StdAllocator.*
+
+ BaseAllocator baseAllocator_;
+};
+#endif
+
+#ifdef __GNUC__
+RAPIDJSON_DIAG_POP
+#endif
+
RAPIDJSON_NAMESPACE_END
#endif // RAPIDJSON_ENCODINGS_H_
diff --git a/3rdparty/rapidjson/include/rapidjson/cursorstreamwrapper.h b/3rdparty/rapidjson/include/rapidjson/cursorstreamwrapper.h
new file mode 100644
index 00000000000..fd6513db14a
--- /dev/null
+++ b/3rdparty/rapidjson/include/rapidjson/cursorstreamwrapper.h
@@ -0,0 +1,78 @@
+// 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.
+//
+// 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_CURSORSTREAMWRAPPER_H_
+#define RAPIDJSON_CURSORSTREAMWRAPPER_H_
+
+#include "stream.h"
+
+#if defined(__GNUC__)
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(effc++)
+#endif
+
+#if defined(_MSC_VER) && _MSC_VER <= 1800
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(4702) // unreachable code
+RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
+#endif
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+
+//! Cursor stream wrapper for counting line and column number if error exists.
+/*!
+ \tparam InputStream Any stream that implements Stream Concept
+*/
+template >
+class CursorStreamWrapper : public GenericStreamWrapper {
+public:
+ typedef typename Encoding::Ch Ch;
+
+ CursorStreamWrapper(InputStream& is):
+ GenericStreamWrapper(is), line_(1), col_(0) {}
+
+ // counting line and column number
+ Ch Take() {
+ Ch ch = this->is_.Take();
+ if(ch == '\n') {
+ line_ ++;
+ col_ = 0;
+ } else {
+ col_ ++;
+ }
+ return ch;
+ }
+
+ //! Get the error line number, if error exists.
+ size_t GetLine() const { return line_; }
+ //! Get the error column number, if error exists.
+ size_t GetColumn() const { return col_; }
+
+private:
+ size_t line_; //!< Current Line
+ size_t col_; //!< Current Column
+};
+
+#if defined(_MSC_VER) && _MSC_VER <= 1800
+RAPIDJSON_DIAG_POP
+#endif
+
+#if defined(__GNUC__)
+RAPIDJSON_DIAG_POP
+#endif
+
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_CURSORSTREAMWRAPPER_H_
diff --git a/3rdparty/rapidjson/include/rapidjson/document.h b/3rdparty/rapidjson/include/rapidjson/document.h
index 19f5a6a5ff9..2cd9a70a600 100644
--- a/3rdparty/rapidjson/include/rapidjson/document.h
+++ b/3rdparty/rapidjson/include/rapidjson/document.h
@@ -1,6 +1,6 @@
// 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.
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
//
// 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
@@ -24,32 +24,39 @@
#include "encodedstream.h"
#include // placement new
#include
-
-RAPIDJSON_DIAG_PUSH
-#ifdef _MSC_VER
-RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
-RAPIDJSON_DIAG_OFF(4244) // conversion from kXxxFlags to 'uint16_t', possible loss of data
+#ifdef __cpp_lib_three_way_comparison
+#include
#endif
+RAPIDJSON_DIAG_PUSH
#ifdef __clang__
RAPIDJSON_DIAG_OFF(padded)
RAPIDJSON_DIAG_OFF(switch-enum)
RAPIDJSON_DIAG_OFF(c++98-compat)
+#elif defined(_MSC_VER)
+RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
+RAPIDJSON_DIAG_OFF(4244) // conversion from kXxxFlags to 'uint16_t', possible loss of data
#endif
#ifdef __GNUC__
RAPIDJSON_DIAG_OFF(effc++)
-#if __GNUC__ >= 6
-RAPIDJSON_DIAG_OFF(terminate) // ignore throwing RAPIDJSON_ASSERT in RAPIDJSON_NOEXCEPT functions
-#endif
#endif // __GNUC__
-#ifndef RAPIDJSON_NOMEMBERITERATORCLASS
-#include // std::iterator, std::random_access_iterator_tag
+#ifdef GetObject
+// see https://github.com/Tencent/rapidjson/issues/1448
+// a former included windows.h might have defined a macro called GetObject, which affects
+// GetObject defined here. This ensures the macro does not get applied
+#pragma push_macro("GetObject")
+#define RAPIDJSON_WINDOWS_GETOBJECT_WORKAROUND_APPLIED
+#undef GetObject
#endif
-#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
-#include // std::move
+#ifndef RAPIDJSON_NOMEMBERITERATORCLASS
+#include // std::random_access_iterator_tag
+#endif
+
+#if RAPIDJSON_USE_MEMBERSMAP
+#include