rj_schema 1.0.0 → 1.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/ext/rj_schema/rapidjson/CMakeLists.txt +23 -1
- data/ext/rj_schema/rapidjson/appveyor.yml +49 -1
- data/ext/rj_schema/rapidjson/bin/types/alotofkeys.json +502 -0
- data/ext/rj_schema/rapidjson/bin/unittestschema/idandref.json +69 -0
- data/ext/rj_schema/rapidjson/doc/stream.md +7 -7
- data/ext/rj_schema/rapidjson/doc/stream.zh-cn.md +1 -1
- data/ext/rj_schema/rapidjson/doc/tutorial.md +15 -15
- data/ext/rj_schema/rapidjson/example/schemavalidator/schemavalidator.cpp +2 -0
- data/ext/rj_schema/rapidjson/example/traverseaspointer.cpp +39 -0
- data/ext/rj_schema/rapidjson/include/rapidjson/allocators.h +460 -52
- data/ext/rj_schema/rapidjson/include/rapidjson/document.h +350 -60
- data/ext/rj_schema/rapidjson/include/rapidjson/internal/strfunc.h +14 -0
- data/ext/rj_schema/rapidjson/include/rapidjson/pointer.h +68 -1
- data/ext/rj_schema/rapidjson/include/rapidjson/rapidjson.h +60 -11
- data/ext/rj_schema/rapidjson/include/rapidjson/schema.h +249 -102
- data/ext/rj_schema/rapidjson/include/rapidjson/uri.h +466 -0
- data/ext/rj_schema/rapidjson/test/perftest/perftest.h +5 -4
- data/ext/rj_schema/rapidjson/test/perftest/rapidjsontest.cpp +20 -2
- data/ext/rj_schema/rapidjson/test/unittest/CMakeLists.txt +2 -0
- data/ext/rj_schema/rapidjson/test/unittest/allocatorstest.cpp +193 -1
- data/ext/rj_schema/rapidjson/test/unittest/documenttest.cpp +2 -0
- data/ext/rj_schema/rapidjson/test/unittest/platformtest.cpp +40 -0
- data/ext/rj_schema/rapidjson/test/unittest/pointertest.cpp +62 -2
- data/ext/rj_schema/rapidjson/test/unittest/schematest.cpp +372 -7
- data/ext/rj_schema/rapidjson/test/unittest/uritest.cpp +718 -0
- data/ext/rj_schema/rapidjson/test/unittest/valuetest.cpp +12 -2
- data/ext/rj_schema/rj_schema.cpp +3 -10
- data/lib/rj_schema.rb +1 -1
- metadata +9 -3
@@ -0,0 +1,69 @@
|
|
1
|
+
{
|
2
|
+
"id": "http://example.com/root.json",
|
3
|
+
"definitions": {
|
4
|
+
"A": {
|
5
|
+
"id": "#foo",
|
6
|
+
"type": "integer"
|
7
|
+
},
|
8
|
+
"B": {
|
9
|
+
"id": "other.json",
|
10
|
+
"definitions": {
|
11
|
+
"X": {
|
12
|
+
"id": "#bar",
|
13
|
+
"type": "boolean"
|
14
|
+
},
|
15
|
+
"Y": {
|
16
|
+
"$ref": "#/definitions/X"
|
17
|
+
},
|
18
|
+
"W": {
|
19
|
+
"$ref": "#/definitions/Y"
|
20
|
+
},
|
21
|
+
"Z": {
|
22
|
+
"$ref": "#bar"
|
23
|
+
},
|
24
|
+
"N": {
|
25
|
+
"properties": {
|
26
|
+
"NX": {
|
27
|
+
"$ref": "#/definitions/X"
|
28
|
+
}
|
29
|
+
}
|
30
|
+
}
|
31
|
+
}
|
32
|
+
}
|
33
|
+
},
|
34
|
+
"properties": {
|
35
|
+
"PA1": {
|
36
|
+
"$ref": "http://example.com/root.json#/definitions/A"
|
37
|
+
},
|
38
|
+
"PA2": {
|
39
|
+
"$ref": "#/definitions/A"
|
40
|
+
},
|
41
|
+
"PA3": {
|
42
|
+
"$ref": "#foo"
|
43
|
+
},
|
44
|
+
"PX1": {
|
45
|
+
"$ref": "#/definitions/B/definitions/X"
|
46
|
+
},
|
47
|
+
"PX2Y": {
|
48
|
+
"$ref": "#/definitions/B/definitions/Y"
|
49
|
+
},
|
50
|
+
"PX3Z": {
|
51
|
+
"$ref": "#/definitions/B/definitions/Z"
|
52
|
+
},
|
53
|
+
"PX4": {
|
54
|
+
"$ref": "http://example.com/other.json#/definitions/X"
|
55
|
+
},
|
56
|
+
"PX5": {
|
57
|
+
"$ref": "other.json#/definitions/X"
|
58
|
+
},
|
59
|
+
"PX6": {
|
60
|
+
"$ref": "other.json#bar"
|
61
|
+
},
|
62
|
+
"PX7W": {
|
63
|
+
"$ref": "#/definitions/B/definitions/W"
|
64
|
+
},
|
65
|
+
"PX8N": {
|
66
|
+
"$ref": "#/definitions/B/definitions/N"
|
67
|
+
}
|
68
|
+
}
|
69
|
+
}
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# Stream
|
2
2
|
|
3
|
-
In RapidJSON, `rapidjson::Stream` is a concept for reading/writing JSON. Here we first show how to use streams
|
3
|
+
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.
|
4
4
|
|
5
5
|
[TOC]
|
6
6
|
|
@@ -51,7 +51,7 @@ d.Accept(writer);
|
|
51
51
|
const char* output = buffer.GetString();
|
52
52
|
~~~~~~~~~~
|
53
53
|
|
54
|
-
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
|
54
|
+
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.
|
55
55
|
|
56
56
|
~~~~~~~~~~cpp
|
57
57
|
StringBuffer buffer1(0, 1024); // Use its allocator, initial size = 1024
|
@@ -89,7 +89,7 @@ d.ParseStream(is);
|
|
89
89
|
fclose(fp);
|
90
90
|
~~~~~~~~~~
|
91
91
|
|
92
|
-
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`.
|
92
|
+
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.
|
93
93
|
|
94
94
|
Apart from reading file, user can also use `FileReadStream` to read `stdin`.
|
95
95
|
|
@@ -119,11 +119,11 @@ d.Accept(writer);
|
|
119
119
|
fclose(fp);
|
120
120
|
~~~~~~~~~~
|
121
121
|
|
122
|
-
It can also
|
122
|
+
It can also redirect the output to `stdout`.
|
123
123
|
|
124
124
|
# iostream Wrapper {#iostreamWrapper}
|
125
125
|
|
126
|
-
Due to users' requests, RapidJSON
|
126
|
+
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.
|
127
127
|
|
128
128
|
## IStreamWrapper {#IStreamWrapper}
|
129
129
|
|
@@ -181,7 +181,7 @@ As mentioned above, UTF-8 byte streams can be read directly. However, UTF-16 and
|
|
181
181
|
|
182
182
|
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.
|
183
183
|
|
184
|
-
If the encoding of stream is known
|
184
|
+
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`.
|
185
185
|
|
186
186
|
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.
|
187
187
|
|
@@ -231,7 +231,7 @@ FileWriteStream bos(fp, writeBuffer, sizeof(writeBuffer));
|
|
231
231
|
typedef EncodedOutputStream<UTF32LE<>, FileWriteStream> OutputStream;
|
232
232
|
OutputStream eos(bos, true); // Write BOM
|
233
233
|
|
234
|
-
Writer<OutputStream,
|
234
|
+
Writer<OutputStream, UTF8<>, UTF32LE<>> writer(eos);
|
235
235
|
d.Accept(writer); // This generates UTF32-LE file from UTF-8 in memory
|
236
236
|
|
237
237
|
fclose(fp);
|
@@ -231,7 +231,7 @@ FileWriteStream bos(fp, writeBuffer, sizeof(writeBuffer));
|
|
231
231
|
typedef EncodedOutputStream<UTF32LE<>, FileWriteStream> OutputStream;
|
232
232
|
OutputStream eos(bos, true); // 写入 BOM
|
233
233
|
|
234
|
-
Writer<OutputStream,
|
234
|
+
Writer<OutputStream, UTF8<>, UTF32LE<>> writer(eos);
|
235
235
|
d.Accept(writer); // 这里从内存的 UTF-8 生成 UTF32-LE 文件
|
236
236
|
|
237
237
|
fclose(fp);
|
@@ -12,7 +12,7 @@ Each JSON value is stored in a type called `Value`. A `Document`, representing t
|
|
12
12
|
|
13
13
|
# Query Value {#QueryValue}
|
14
14
|
|
15
|
-
In this section, we will use excerpt
|
15
|
+
In this section, we will use excerpt from `example/tutorial/tutorial.cpp`.
|
16
16
|
|
17
17
|
Assume we have the following JSON stored in a C string (`const char* json`):
|
18
18
|
~~~~~~~~~~js
|
@@ -85,7 +85,7 @@ assert(document["i"].IsNumber());
|
|
85
85
|
// In this case, IsUint()/IsInt64()/IsUint64() also return true.
|
86
86
|
assert(document["i"].IsInt());
|
87
87
|
printf("i = %d\n", document["i"].GetInt());
|
88
|
-
//
|
88
|
+
// Alternatively (int)document["i"]
|
89
89
|
|
90
90
|
assert(document["pi"].IsNumber());
|
91
91
|
assert(document["pi"].IsDouble());
|
@@ -113,7 +113,7 @@ a[2] = 3
|
|
113
113
|
a[3] = 4
|
114
114
|
~~~~~~~~~~
|
115
115
|
|
116
|
-
Note that, RapidJSON does not automatically convert values between JSON types.
|
116
|
+
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.
|
117
117
|
|
118
118
|
In the following sections we discuss details about querying individual types.
|
119
119
|
|
@@ -168,9 +168,9 @@ Type of member pi is Number
|
|
168
168
|
Type of member a is Array
|
169
169
|
~~~~~~~~~~
|
170
170
|
|
171
|
-
Note that, when `operator[](const char*)` cannot find the member, it will fail
|
171
|
+
Note that, when `operator[](const char*)` cannot find the member, it will fail on assertion.
|
172
172
|
|
173
|
-
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:
|
173
|
+
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:
|
174
174
|
|
175
175
|
~~~~~~~~~~cpp
|
176
176
|
Value::ConstMemberIterator itr = document.FindMember("hello");
|
@@ -221,18 +221,18 @@ When obtaining the numeric values, `GetDouble()` will convert internal integer r
|
|
221
221
|
|
222
222
|
## Query String {#QueryString}
|
223
223
|
|
224
|
-
In addition to `GetString()`, the `Value` class also contains `GetStringLength()`. Here explains why
|
224
|
+
In addition to `GetString()`, the `Value` class also contains `GetStringLength()`. Here explains why:
|
225
225
|
|
226
|
-
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
|
226
|
+
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.
|
227
227
|
|
228
|
-
To conform RFC 4627, RapidJSON supports string containing `U+0000
|
228
|
+
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.
|
229
229
|
|
230
|
-
For example, after parsing
|
230
|
+
For example, after parsing the following JSON to `Document d`:
|
231
231
|
|
232
232
|
~~~~~~~~~~js
|
233
233
|
{ "s" : "a\u0000b" }
|
234
234
|
~~~~~~~~~~
|
235
|
-
The correct length of the
|
235
|
+
The correct length of the string `"a\u0000b"` is 3, as returned by `GetStringLength()`. But `strlen()` returns 1.
|
236
236
|
|
237
237
|
`GetStringLength()` can also improve performance, as user may often need to call `strlen()` for allocating buffer.
|
238
238
|
|
@@ -246,7 +246,7 @@ which accepts the length of string as parameter. This constructor supports stori
|
|
246
246
|
|
247
247
|
## Comparing values
|
248
248
|
|
249
|
-
You can use `==` and `!=` to compare values. Two values are equal if and only if they
|
249
|
+
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:
|
250
250
|
|
251
251
|
~~~~~~~~~~cpp
|
252
252
|
if (document["hello"] == document["n"]) /*...*/; // Compare values
|
@@ -264,7 +264,7 @@ Note that, currently if an object contains duplicated named member, comparing eq
|
|
264
264
|
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`.
|
265
265
|
|
266
266
|
## Change Value Type {#ChangeValueType}
|
267
|
-
When creating a Value or Document by default constructor, its type is Null. To change its type, call `SetXXX()` or assignment operator, for example:
|
267
|
+
When creating a `Value` or `Document` by default constructor, its type is Null. To change its type, call `SetXXX()` or assignment operator, for example:
|
268
268
|
|
269
269
|
~~~~~~~~~~cpp
|
270
270
|
Document d; // Null
|
@@ -285,7 +285,7 @@ Value u(123u); // calls Value(unsigned)
|
|
285
285
|
Value d(1.5); // calls Value(double)
|
286
286
|
~~~~~~~~~~
|
287
287
|
|
288
|
-
To create empty object or array, you may use `SetObject()`/`SetArray()` after default constructor, or using the `Value(Type)` in one
|
288
|
+
To create empty object or array, you may use `SetObject()`/`SetArray()` after default constructor, or using the `Value(Type)` in one call:
|
289
289
|
|
290
290
|
~~~~~~~~~~cpp
|
291
291
|
Value o(kObjectType);
|
@@ -299,7 +299,7 @@ A very special decision during design of RapidJSON is that, assignment of value
|
|
299
299
|
~~~~~~~~~~cpp
|
300
300
|
Value a(123);
|
301
301
|
Value b(456);
|
302
|
-
|
302
|
+
a = b; // b becomes a Null value, a becomes number 456.
|
303
303
|
~~~~~~~~~~
|
304
304
|
|
305
305
|
![Assignment with move semantics.](diagram/move1.png)
|
@@ -367,7 +367,7 @@ RapidJSON provides two strategies for storing string.
|
|
367
367
|
|
368
368
|
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.
|
369
369
|
|
370
|
-
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
|
370
|
+
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.
|
371
371
|
|
372
372
|
Therefore, when we assign a copy-string, we call this overloaded `SetString()` with allocator:
|
373
373
|
|
@@ -0,0 +1,39 @@
|
|
1
|
+
#include "rapidjson/document.h"
|
2
|
+
#include "rapidjson/filereadstream.h"
|
3
|
+
#include "rapidjson/pointer.h"
|
4
|
+
#include "rapidjson/stringbuffer.h"
|
5
|
+
#include <iostream>
|
6
|
+
|
7
|
+
using namespace rapidjson;
|
8
|
+
|
9
|
+
void traverse(const Value& v, const Pointer& p) {
|
10
|
+
StringBuffer sb;
|
11
|
+
p.Stringify(sb);
|
12
|
+
std::cout << sb.GetString() << std::endl;
|
13
|
+
|
14
|
+
switch (v.GetType()) {
|
15
|
+
case kArrayType:
|
16
|
+
for (SizeType i = 0; i != v.Size(); ++i)
|
17
|
+
traverse(v[i], p.Append(i));
|
18
|
+
break;
|
19
|
+
case kObjectType:
|
20
|
+
for (Value::ConstMemberIterator m = v.MemberBegin(); m != v.MemberEnd(); ++m)
|
21
|
+
traverse(m->value, p.Append(m->name.GetString(), m->name.GetStringLength()));
|
22
|
+
break;
|
23
|
+
default:
|
24
|
+
break;
|
25
|
+
}
|
26
|
+
}
|
27
|
+
|
28
|
+
int main(int, char*[]) {
|
29
|
+
char readBuffer[65536];
|
30
|
+
FileReadStream is(stdin, readBuffer, sizeof(readBuffer));
|
31
|
+
|
32
|
+
Document d;
|
33
|
+
d.ParseStream(is);
|
34
|
+
|
35
|
+
Pointer root;
|
36
|
+
traverse(d, root);
|
37
|
+
|
38
|
+
return 0;
|
39
|
+
}
|