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
@@ -16,6 +16,11 @@
|
|
16
16
|
|
17
17
|
#include "rapidjson/allocators.h"
|
18
18
|
|
19
|
+
#include <map>
|
20
|
+
#include <string>
|
21
|
+
#include <utility>
|
22
|
+
#include <functional>
|
23
|
+
|
19
24
|
using namespace rapidjson;
|
20
25
|
|
21
26
|
template <typename Allocator>
|
@@ -47,19 +52,206 @@ void TestAllocator(Allocator& a) {
|
|
47
52
|
EXPECT_TRUE(a.Realloc(a.Malloc(1), 1, 0) == 0);
|
48
53
|
}
|
49
54
|
|
55
|
+
struct TestStdAllocatorData {
|
56
|
+
TestStdAllocatorData(int &constructions, int &destructions) :
|
57
|
+
constructions_(&constructions),
|
58
|
+
destructions_(&destructions)
|
59
|
+
{
|
60
|
+
++*constructions_;
|
61
|
+
}
|
62
|
+
TestStdAllocatorData(const TestStdAllocatorData& rhs) :
|
63
|
+
constructions_(rhs.constructions_),
|
64
|
+
destructions_(rhs.destructions_)
|
65
|
+
{
|
66
|
+
++*constructions_;
|
67
|
+
}
|
68
|
+
TestStdAllocatorData& operator=(const TestStdAllocatorData& rhs)
|
69
|
+
{
|
70
|
+
this->~TestStdAllocatorData();
|
71
|
+
constructions_ = rhs.constructions_;
|
72
|
+
destructions_ = rhs.destructions_;
|
73
|
+
++*constructions_;
|
74
|
+
return *this;
|
75
|
+
}
|
76
|
+
~TestStdAllocatorData()
|
77
|
+
{
|
78
|
+
++*destructions_;
|
79
|
+
}
|
80
|
+
private:
|
81
|
+
TestStdAllocatorData();
|
82
|
+
int *constructions_,
|
83
|
+
*destructions_;
|
84
|
+
};
|
85
|
+
|
86
|
+
template <typename Allocator>
|
87
|
+
void TestStdAllocator(const Allocator& a) {
|
88
|
+
#if RAPIDJSON_HAS_CXX17
|
89
|
+
typedef StdAllocator<bool, Allocator> BoolAllocator;
|
90
|
+
#else
|
91
|
+
typedef StdAllocator<void, Allocator> VoidAllocator;
|
92
|
+
typedef typename VoidAllocator::template rebind<bool>::other BoolAllocator;
|
93
|
+
#endif
|
94
|
+
BoolAllocator ba(a), ba2(a);
|
95
|
+
EXPECT_TRUE(ba == ba2);
|
96
|
+
EXPECT_FALSE(ba!= ba2);
|
97
|
+
ba.deallocate(ba.allocate());
|
98
|
+
EXPECT_TRUE(ba == ba2);
|
99
|
+
EXPECT_FALSE(ba != ba2);
|
100
|
+
|
101
|
+
unsigned long long ll = 0, *llp = ≪
|
102
|
+
const unsigned long long cll = 0, *cllp = &cll;
|
103
|
+
StdAllocator<unsigned long long, Allocator> lla(a);
|
104
|
+
EXPECT_EQ(lla.address(ll), llp);
|
105
|
+
EXPECT_EQ(lla.address(cll), cllp);
|
106
|
+
EXPECT_TRUE(lla.max_size() > 0 && lla.max_size() <= SIZE_MAX / sizeof(unsigned long long));
|
107
|
+
|
108
|
+
int *arr;
|
109
|
+
StdAllocator<int, Allocator> ia(a);
|
110
|
+
arr = ia.allocate(10 * sizeof(int));
|
111
|
+
EXPECT_TRUE(arr != 0);
|
112
|
+
for (int i = 0; i < 10; ++i) {
|
113
|
+
arr[i] = 0x0f0f0f0f;
|
114
|
+
}
|
115
|
+
ia.deallocate(arr, 10);
|
116
|
+
arr = Malloc<int>(ia, 10);
|
117
|
+
EXPECT_TRUE(arr != 0);
|
118
|
+
for (int i = 0; i < 10; ++i) {
|
119
|
+
arr[i] = 0x0f0f0f0f;
|
120
|
+
}
|
121
|
+
arr = Realloc<int>(ia, arr, 10, 20);
|
122
|
+
EXPECT_TRUE(arr != 0);
|
123
|
+
for (int i = 0; i < 10; ++i) {
|
124
|
+
EXPECT_EQ(arr[i], 0x0f0f0f0f);
|
125
|
+
}
|
126
|
+
for (int i = 10; i < 20; i++) {
|
127
|
+
arr[i] = 0x0f0f0f0f;
|
128
|
+
}
|
129
|
+
Free<int>(ia, arr, 20);
|
130
|
+
|
131
|
+
int cons = 0, dest = 0;
|
132
|
+
StdAllocator<TestStdAllocatorData, Allocator> da(a);
|
133
|
+
for (int i = 1; i < 10; i++) {
|
134
|
+
TestStdAllocatorData *d = da.allocate();
|
135
|
+
EXPECT_TRUE(d != 0);
|
136
|
+
|
137
|
+
da.destroy(new(d) TestStdAllocatorData(cons, dest));
|
138
|
+
EXPECT_EQ(cons, i);
|
139
|
+
EXPECT_EQ(dest, i);
|
140
|
+
|
141
|
+
da.deallocate(d);
|
142
|
+
}
|
143
|
+
|
144
|
+
typedef StdAllocator<char, Allocator> CharAllocator;
|
145
|
+
typedef std::basic_string<char, std::char_traits<char>, CharAllocator> String;
|
146
|
+
#if RAPIDJSON_HAS_CXX11
|
147
|
+
String s(CharAllocator{a});
|
148
|
+
#else
|
149
|
+
CharAllocator ca(a);
|
150
|
+
String s(ca);
|
151
|
+
#endif
|
152
|
+
for (int i = 0; i < 26; i++) {
|
153
|
+
s.push_back(static_cast<char>('A' + i));
|
154
|
+
}
|
155
|
+
EXPECT_TRUE(s == "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
|
156
|
+
|
157
|
+
typedef StdAllocator<std::pair<const int, bool>, Allocator> MapAllocator;
|
158
|
+
typedef std::map<int, bool, std::less<int>, MapAllocator> Map;
|
159
|
+
#if RAPIDJSON_HAS_CXX11
|
160
|
+
Map map(std::less<int>(), MapAllocator{a});
|
161
|
+
#else
|
162
|
+
MapAllocator ma(a);
|
163
|
+
Map map(std::less<int>(), ma);
|
164
|
+
#endif
|
165
|
+
for (int i = 0; i < 10; i++) {
|
166
|
+
map.insert(std::make_pair(i, (i % 2) == 0));
|
167
|
+
}
|
168
|
+
EXPECT_TRUE(map.size() == 10);
|
169
|
+
for (int i = 0; i < 10; i++) {
|
170
|
+
typename Map::iterator it = map.find(i);
|
171
|
+
EXPECT_TRUE(it != map.end());
|
172
|
+
EXPECT_TRUE(it->second == ((i % 2) == 0));
|
173
|
+
}
|
174
|
+
}
|
175
|
+
|
50
176
|
TEST(Allocator, CrtAllocator) {
|
51
177
|
CrtAllocator a;
|
178
|
+
|
52
179
|
TestAllocator(a);
|
180
|
+
TestStdAllocator(a);
|
181
|
+
|
182
|
+
CrtAllocator a2;
|
183
|
+
EXPECT_TRUE(a == a2);
|
184
|
+
EXPECT_FALSE(a != a2);
|
185
|
+
a2.Free(a2.Malloc(1));
|
186
|
+
EXPECT_TRUE(a == a2);
|
187
|
+
EXPECT_FALSE(a != a2);
|
53
188
|
}
|
54
189
|
|
55
190
|
TEST(Allocator, MemoryPoolAllocator) {
|
56
|
-
|
191
|
+
const size_t capacity = RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY;
|
192
|
+
MemoryPoolAllocator<> a(capacity);
|
193
|
+
|
194
|
+
a.Clear(); // noop
|
195
|
+
EXPECT_EQ(a.Size(), 0u);
|
196
|
+
EXPECT_EQ(a.Capacity(), 0u);
|
197
|
+
EXPECT_EQ(a.Shared(), false);
|
198
|
+
{
|
199
|
+
MemoryPoolAllocator<> a2(a);
|
200
|
+
EXPECT_EQ(a2.Shared(), true);
|
201
|
+
EXPECT_EQ(a.Shared(), true);
|
202
|
+
EXPECT_TRUE(a == a2);
|
203
|
+
EXPECT_FALSE(a != a2);
|
204
|
+
a2.Free(a2.Malloc(1));
|
205
|
+
EXPECT_TRUE(a == a2);
|
206
|
+
EXPECT_FALSE(a != a2);
|
207
|
+
}
|
208
|
+
EXPECT_EQ(a.Shared(), false);
|
209
|
+
EXPECT_EQ(a.Capacity(), capacity);
|
210
|
+
EXPECT_EQ(a.Size(), 8u); // aligned
|
211
|
+
a.Clear();
|
212
|
+
EXPECT_EQ(a.Capacity(), 0u);
|
213
|
+
EXPECT_EQ(a.Size(), 0u);
|
214
|
+
|
57
215
|
TestAllocator(a);
|
216
|
+
TestStdAllocator(a);
|
58
217
|
|
59
218
|
for (size_t i = 1; i < 1000; i++) {
|
60
219
|
EXPECT_TRUE(a.Malloc(i) != 0);
|
61
220
|
EXPECT_LE(a.Size(), a.Capacity());
|
62
221
|
}
|
222
|
+
|
223
|
+
CrtAllocator baseAllocator;
|
224
|
+
a = MemoryPoolAllocator<>(capacity, &baseAllocator);
|
225
|
+
EXPECT_EQ(a.Capacity(), 0u);
|
226
|
+
EXPECT_EQ(a.Size(), 0u);
|
227
|
+
a.Free(a.Malloc(1));
|
228
|
+
EXPECT_EQ(a.Capacity(), capacity);
|
229
|
+
EXPECT_EQ(a.Size(), 8u); // aligned
|
230
|
+
|
231
|
+
{
|
232
|
+
a.Clear();
|
233
|
+
const size_t bufSize = 1024;
|
234
|
+
char *buffer = (char *)a.Malloc(bufSize);
|
235
|
+
MemoryPoolAllocator<> aligned_a(buffer, bufSize);
|
236
|
+
EXPECT_TRUE(aligned_a.Capacity() > 0 && aligned_a.Capacity() <= bufSize);
|
237
|
+
EXPECT_EQ(aligned_a.Size(), 0u);
|
238
|
+
aligned_a.Free(aligned_a.Malloc(1));
|
239
|
+
EXPECT_TRUE(aligned_a.Capacity() > 0 && aligned_a.Capacity() <= bufSize);
|
240
|
+
EXPECT_EQ(aligned_a.Size(), 8u); // aligned
|
241
|
+
}
|
242
|
+
|
243
|
+
{
|
244
|
+
a.Clear();
|
245
|
+
const size_t bufSize = 1024;
|
246
|
+
char *buffer = (char *)a.Malloc(bufSize);
|
247
|
+
RAPIDJSON_ASSERT(bufSize % sizeof(void*) == 0);
|
248
|
+
MemoryPoolAllocator<> unaligned_a(buffer + 1, bufSize - 1);
|
249
|
+
EXPECT_TRUE(unaligned_a.Capacity() > 0 && unaligned_a.Capacity() <= bufSize - sizeof(void*));
|
250
|
+
EXPECT_EQ(unaligned_a.Size(), 0u);
|
251
|
+
unaligned_a.Free(unaligned_a.Malloc(1));
|
252
|
+
EXPECT_TRUE(unaligned_a.Capacity() > 0 && unaligned_a.Capacity() <= bufSize - sizeof(void*));
|
253
|
+
EXPECT_EQ(unaligned_a.Size(), 8u); // aligned
|
254
|
+
}
|
63
255
|
}
|
64
256
|
|
65
257
|
TEST(Allocator, Alignment) {
|
@@ -325,6 +325,8 @@ TEST(Document, Swap) {
|
|
325
325
|
EXPECT_TRUE(d1.IsNull());
|
326
326
|
|
327
327
|
// reset document, including allocator
|
328
|
+
// so clear o before so that it doesnt contain dangling elements
|
329
|
+
o.Clear();
|
328
330
|
Document().Swap(d2);
|
329
331
|
EXPECT_TRUE(d2.IsNull());
|
330
332
|
EXPECT_NE(&d2.GetAllocator(), &a);
|
@@ -0,0 +1,40 @@
|
|
1
|
+
// Tencent is pleased to support the open source community by making RapidJSON available.
|
2
|
+
//
|
3
|
+
// Copyright (C) 2021 THL A29 Limited, a Tencent company, and Milo Yip.
|
4
|
+
//
|
5
|
+
// Licensed under the MIT License (the "License"); you may not use this file except
|
6
|
+
// in compliance with the License. You may obtain a copy of the License at
|
7
|
+
//
|
8
|
+
// http://opensource.org/licenses/MIT
|
9
|
+
//
|
10
|
+
// Unless required by applicable law or agreed to in writing, software distributed
|
11
|
+
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
12
|
+
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
13
|
+
// specific language governing permissions and limitations under the License.
|
14
|
+
|
15
|
+
#include "unittest.h"
|
16
|
+
|
17
|
+
// see https://github.com/Tencent/rapidjson/issues/1448
|
18
|
+
// including windows.h on purpose to provoke a compile time problem as GetObject is a
|
19
|
+
// macro that gets defined when windows.h is included
|
20
|
+
#ifdef _WIN32
|
21
|
+
#include <windows.h>
|
22
|
+
#endif
|
23
|
+
|
24
|
+
#include "rapidjson/document.h"
|
25
|
+
#undef GetObject
|
26
|
+
|
27
|
+
using namespace rapidjson;
|
28
|
+
|
29
|
+
TEST(Platform, GetObject) {
|
30
|
+
Document doc;
|
31
|
+
doc.Parse(" { \"object\" : { \"pi\": 3.1416} } ");
|
32
|
+
EXPECT_TRUE(doc.IsObject());
|
33
|
+
EXPECT_TRUE(doc.HasMember("object"));
|
34
|
+
const Document::ValueType& o = doc["object"];
|
35
|
+
EXPECT_TRUE(o.IsObject());
|
36
|
+
Value::ConstObject sub = o.GetObject();
|
37
|
+
EXPECT_TRUE(sub.HasMember("pi"));
|
38
|
+
Value::ConstObject sub2 = o.GetObj();
|
39
|
+
EXPECT_TRUE(sub2.HasMember("pi"));
|
40
|
+
}
|
@@ -475,7 +475,9 @@ TEST(Pointer, CopyConstructor) {
|
|
475
475
|
EXPECT_EQ(1u, q.GetTokens()[1].length);
|
476
476
|
EXPECT_STREQ("0", q.GetTokens()[1].name);
|
477
477
|
EXPECT_EQ(0u, q.GetTokens()[1].index);
|
478
|
-
|
478
|
+
|
479
|
+
// Copied pointer needs to have its own allocator
|
480
|
+
EXPECT_NE(&p.GetAllocator(), &q.GetAllocator());
|
479
481
|
}
|
480
482
|
|
481
483
|
// Static tokens
|
@@ -648,6 +650,52 @@ TEST(Pointer, Create) {
|
|
648
650
|
}
|
649
651
|
}
|
650
652
|
|
653
|
+
static const char kJsonIds[] = "{\n"
|
654
|
+
" \"id\": \"/root/\","
|
655
|
+
" \"foo\":[\"bar\", \"baz\", {\"id\": \"inarray\", \"child\": 1}],\n"
|
656
|
+
" \"int\" : 2,\n"
|
657
|
+
" \"str\" : \"val\",\n"
|
658
|
+
" \"obj\": {\"id\": \"inobj\", \"child\": 3},\n"
|
659
|
+
" \"jbo\": {\"id\": true, \"child\": 4}\n"
|
660
|
+
"}";
|
661
|
+
|
662
|
+
|
663
|
+
TEST(Pointer, GetUri) {
|
664
|
+
CrtAllocator allocator;
|
665
|
+
Document d;
|
666
|
+
d.Parse(kJsonIds);
|
667
|
+
Pointer::UriType doc("http://doc");
|
668
|
+
Pointer::UriType root("http://doc/root/");
|
669
|
+
Pointer::UriType empty = Pointer::UriType();
|
670
|
+
|
671
|
+
EXPECT_TRUE(Pointer("").GetUri(d, doc) == doc);
|
672
|
+
EXPECT_TRUE(Pointer("/foo").GetUri(d, doc) == root);
|
673
|
+
EXPECT_TRUE(Pointer("/foo/0").GetUri(d, doc) == root);
|
674
|
+
EXPECT_TRUE(Pointer("/foo/2").GetUri(d, doc) == root);
|
675
|
+
EXPECT_TRUE(Pointer("/foo/2/child").GetUri(d, doc) == Pointer::UriType("http://doc/root/inarray"));
|
676
|
+
EXPECT_TRUE(Pointer("/int").GetUri(d, doc) == root);
|
677
|
+
EXPECT_TRUE(Pointer("/str").GetUri(d, doc) == root);
|
678
|
+
EXPECT_TRUE(Pointer("/obj").GetUri(d, doc) == root);
|
679
|
+
EXPECT_TRUE(Pointer("/obj/child").GetUri(d, doc) == Pointer::UriType("http://doc/root/inobj"));
|
680
|
+
EXPECT_TRUE(Pointer("/jbo").GetUri(d, doc) == root);
|
681
|
+
EXPECT_TRUE(Pointer("/jbo/child").GetUri(d, doc) == root); // id not string
|
682
|
+
|
683
|
+
size_t unresolvedTokenIndex;
|
684
|
+
EXPECT_TRUE(Pointer("/abc").GetUri(d, doc, &unresolvedTokenIndex, &allocator) == empty); // Out of boundary
|
685
|
+
EXPECT_EQ(0u, unresolvedTokenIndex);
|
686
|
+
EXPECT_TRUE(Pointer("/foo/3").GetUri(d, doc, &unresolvedTokenIndex, &allocator) == empty); // Out of boundary
|
687
|
+
EXPECT_EQ(1u, unresolvedTokenIndex);
|
688
|
+
EXPECT_TRUE(Pointer("/foo/a").GetUri(d, doc, &unresolvedTokenIndex, &allocator) == empty); // "/foo" is an array, cannot query by "a"
|
689
|
+
EXPECT_EQ(1u, unresolvedTokenIndex);
|
690
|
+
EXPECT_TRUE(Pointer("/foo/0/0").GetUri(d, doc, &unresolvedTokenIndex, &allocator) == empty); // "/foo/0" is an string, cannot further query
|
691
|
+
EXPECT_EQ(2u, unresolvedTokenIndex);
|
692
|
+
EXPECT_TRUE(Pointer("/foo/0/a").GetUri(d, doc, &unresolvedTokenIndex, &allocator) == empty); // "/foo/0" is an string, cannot further query
|
693
|
+
EXPECT_EQ(2u, unresolvedTokenIndex);
|
694
|
+
|
695
|
+
Pointer::Token tokens[] = { { "foo ...", 3, kPointerInvalidIndex } };
|
696
|
+
EXPECT_TRUE(Pointer(tokens, 1).GetUri(d, doc) == root);
|
697
|
+
}
|
698
|
+
|
651
699
|
TEST(Pointer, Get) {
|
652
700
|
Document d;
|
653
701
|
d.Parse(kJson);
|
@@ -664,7 +712,8 @@ TEST(Pointer, Get) {
|
|
664
712
|
EXPECT_EQ(&d["k\"l"], Pointer("/k\"l").Get(d));
|
665
713
|
EXPECT_EQ(&d[" "], Pointer("/ ").Get(d));
|
666
714
|
EXPECT_EQ(&d["m~n"], Pointer("/m~0n").Get(d));
|
667
|
-
|
715
|
+
|
716
|
+
EXPECT_TRUE(Pointer("/abc").Get(d) == 0); // Out of boundary
|
668
717
|
size_t unresolvedTokenIndex;
|
669
718
|
EXPECT_TRUE(Pointer("/foo/2").Get(d, &unresolvedTokenIndex) == 0); // Out of boundary
|
670
719
|
EXPECT_EQ(1u, unresolvedTokenIndex);
|
@@ -1668,3 +1717,14 @@ TEST(Pointer, Issue483) {
|
|
1668
1717
|
value.SetString(mystr.c_str(), static_cast<SizeType>(mystr.length()), document.GetAllocator());
|
1669
1718
|
myjson::Pointer(path.c_str()).Set(document, value, document.GetAllocator());
|
1670
1719
|
}
|
1720
|
+
|
1721
|
+
TEST(Pointer, Issue1899) {
|
1722
|
+
typedef GenericPointer<Value, MemoryPoolAllocator<> > PointerType;
|
1723
|
+
PointerType p;
|
1724
|
+
PointerType q = p.Append("foo");
|
1725
|
+
EXPECT_TRUE(PointerType("/foo") == q);
|
1726
|
+
q = q.Append(1234);
|
1727
|
+
EXPECT_TRUE(PointerType("/foo/1234") == q);
|
1728
|
+
q = q.Append("");
|
1729
|
+
EXPECT_TRUE(PointerType("/foo/1234/") == q);
|
1730
|
+
}
|