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.
Files changed (30) hide show
  1. checksums.yaml +4 -4
  2. data/ext/rj_schema/rapidjson/CMakeLists.txt +23 -1
  3. data/ext/rj_schema/rapidjson/appveyor.yml +49 -1
  4. data/ext/rj_schema/rapidjson/bin/types/alotofkeys.json +502 -0
  5. data/ext/rj_schema/rapidjson/bin/unittestschema/idandref.json +69 -0
  6. data/ext/rj_schema/rapidjson/doc/stream.md +7 -7
  7. data/ext/rj_schema/rapidjson/doc/stream.zh-cn.md +1 -1
  8. data/ext/rj_schema/rapidjson/doc/tutorial.md +15 -15
  9. data/ext/rj_schema/rapidjson/example/schemavalidator/schemavalidator.cpp +2 -0
  10. data/ext/rj_schema/rapidjson/example/traverseaspointer.cpp +39 -0
  11. data/ext/rj_schema/rapidjson/include/rapidjson/allocators.h +460 -52
  12. data/ext/rj_schema/rapidjson/include/rapidjson/document.h +350 -60
  13. data/ext/rj_schema/rapidjson/include/rapidjson/internal/strfunc.h +14 -0
  14. data/ext/rj_schema/rapidjson/include/rapidjson/pointer.h +68 -1
  15. data/ext/rj_schema/rapidjson/include/rapidjson/rapidjson.h +60 -11
  16. data/ext/rj_schema/rapidjson/include/rapidjson/schema.h +249 -102
  17. data/ext/rj_schema/rapidjson/include/rapidjson/uri.h +466 -0
  18. data/ext/rj_schema/rapidjson/test/perftest/perftest.h +5 -4
  19. data/ext/rj_schema/rapidjson/test/perftest/rapidjsontest.cpp +20 -2
  20. data/ext/rj_schema/rapidjson/test/unittest/CMakeLists.txt +2 -0
  21. data/ext/rj_schema/rapidjson/test/unittest/allocatorstest.cpp +193 -1
  22. data/ext/rj_schema/rapidjson/test/unittest/documenttest.cpp +2 -0
  23. data/ext/rj_schema/rapidjson/test/unittest/platformtest.cpp +40 -0
  24. data/ext/rj_schema/rapidjson/test/unittest/pointertest.cpp +62 -2
  25. data/ext/rj_schema/rapidjson/test/unittest/schematest.cpp +372 -7
  26. data/ext/rj_schema/rapidjson/test/unittest/uritest.cpp +718 -0
  27. data/ext/rj_schema/rapidjson/test/unittest/valuetest.cpp +12 -2
  28. data/ext/rj_schema/rj_schema.cpp +3 -10
  29. data/lib/rj_schema.rb +1 -1
  30. metadata +9 -3
@@ -0,0 +1,466 @@
1
+ // Tencent is pleased to support the open source community by making RapidJSON available.
2
+ //
3
+ // (C) Copyright IBM Corporation 2021
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
+ #ifndef RAPIDJSON_URI_H_
16
+ #define RAPIDJSON_URI_H_
17
+
18
+ #include "internal/strfunc.h"
19
+
20
+ #if defined(__clang__)
21
+ RAPIDJSON_DIAG_PUSH
22
+ RAPIDJSON_DIAG_OFF(c++98-compat)
23
+ #elif defined(_MSC_VER)
24
+ RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
25
+ #endif
26
+
27
+ RAPIDJSON_NAMESPACE_BEGIN
28
+
29
+ ///////////////////////////////////////////////////////////////////////////////
30
+ // GenericUri
31
+
32
+ template <typename ValueType, typename Allocator=CrtAllocator>
33
+ class GenericUri {
34
+ public:
35
+ typedef typename ValueType::Ch Ch;
36
+ #if RAPIDJSON_HAS_STDSTRING
37
+ typedef std::basic_string<Ch> String;
38
+ #endif
39
+
40
+ //! Constructors
41
+ GenericUri(Allocator* allocator = 0) : uri_(), base_(), scheme_(), auth_(), path_(), query_(), frag_(), allocator_(allocator), ownAllocator_() {
42
+ }
43
+
44
+ GenericUri(const Ch* uri, SizeType len, Allocator* allocator = 0) : uri_(), base_(), scheme_(), auth_(), path_(), query_(), frag_(), allocator_(allocator), ownAllocator_() {
45
+ Parse(uri, len);
46
+ }
47
+
48
+ GenericUri(const Ch* uri, Allocator* allocator = 0) : uri_(), base_(), scheme_(), auth_(), path_(), query_(), frag_(), allocator_(allocator), ownAllocator_() {
49
+ Parse(uri, internal::StrLen<Ch>(uri));
50
+ }
51
+
52
+ // Use with specializations of GenericValue
53
+ template<typename T> GenericUri(const T& uri, Allocator* allocator = 0) : uri_(), base_(), scheme_(), auth_(), path_(), query_(), frag_(), allocator_(allocator), ownAllocator_() {
54
+ const Ch* u = uri.template Get<const Ch*>(); // TypeHelper from document.h
55
+ Parse(u, internal::StrLen<Ch>(u));
56
+ }
57
+
58
+ #if RAPIDJSON_HAS_STDSTRING
59
+ GenericUri(const String& uri, Allocator* allocator = 0) : uri_(), base_(), scheme_(), auth_(), path_(), query_(), frag_(), allocator_(allocator), ownAllocator_() {
60
+ Parse(uri.c_str(), internal::StrLen<Ch>(uri.c_str()));
61
+ }
62
+ #endif
63
+
64
+ //! Copy constructor
65
+ GenericUri(const GenericUri& rhs) : uri_(), base_(), scheme_(), auth_(), path_(), query_(), frag_(), allocator_(), ownAllocator_() {
66
+ *this = rhs;
67
+ }
68
+
69
+ //! Copy constructor
70
+ GenericUri(const GenericUri& rhs, Allocator* allocator) : uri_(), base_(), scheme_(), auth_(), path_(), query_(), frag_(), allocator_(allocator), ownAllocator_() {
71
+ *this = rhs;
72
+ }
73
+
74
+ //! Destructor.
75
+ ~GenericUri() {
76
+ Free();
77
+ RAPIDJSON_DELETE(ownAllocator_);
78
+ }
79
+
80
+ //! Assignment operator
81
+ GenericUri& operator=(const GenericUri& rhs) {
82
+ if (this != &rhs) {
83
+ // Do not delete ownAllocator
84
+ Free();
85
+ Allocate(rhs.GetStringLength());
86
+ auth_ = CopyPart(scheme_, rhs.scheme_, rhs.GetSchemeStringLength());
87
+ path_ = CopyPart(auth_, rhs.auth_, rhs.GetAuthStringLength());
88
+ query_ = CopyPart(path_, rhs.path_, rhs.GetPathStringLength());
89
+ frag_ = CopyPart(query_, rhs.query_, rhs.GetQueryStringLength());
90
+ base_ = CopyPart(frag_, rhs.frag_, rhs.GetFragStringLength());
91
+ uri_ = CopyPart(base_, rhs.base_, rhs.GetBaseStringLength());
92
+ CopyPart(uri_, rhs.uri_, rhs.GetStringLength());
93
+ }
94
+ return *this;
95
+ }
96
+
97
+ //! Getters
98
+ // Use with specializations of GenericValue
99
+ template<typename T> void Get(T& uri, Allocator& allocator) {
100
+ uri.template Set<const Ch*>(this->GetString(), allocator); // TypeHelper from document.h
101
+ }
102
+
103
+ const Ch* GetString() const { return uri_; }
104
+ SizeType GetStringLength() const { return uri_ == 0 ? 0 : internal::StrLen<Ch>(uri_); }
105
+ const Ch* GetBaseString() const { return base_; }
106
+ SizeType GetBaseStringLength() const { return base_ == 0 ? 0 : internal::StrLen<Ch>(base_); }
107
+ const Ch* GetSchemeString() const { return scheme_; }
108
+ SizeType GetSchemeStringLength() const { return scheme_ == 0 ? 0 : internal::StrLen<Ch>(scheme_); }
109
+ const Ch* GetAuthString() const { return auth_; }
110
+ SizeType GetAuthStringLength() const { return auth_ == 0 ? 0 : internal::StrLen<Ch>(auth_); }
111
+ const Ch* GetPathString() const { return path_; }
112
+ SizeType GetPathStringLength() const { return path_ == 0 ? 0 : internal::StrLen<Ch>(path_); }
113
+ const Ch* GetQueryString() const { return query_; }
114
+ SizeType GetQueryStringLength() const { return query_ == 0 ? 0 : internal::StrLen<Ch>(query_); }
115
+ const Ch* GetFragString() const { return frag_; }
116
+ SizeType GetFragStringLength() const { return frag_ == 0 ? 0 : internal::StrLen<Ch>(frag_); }
117
+
118
+ #if RAPIDJSON_HAS_STDSTRING
119
+ static String Get(const GenericUri& uri) { return String(uri.GetString(), uri.GetStringLength()); }
120
+ static String GetBase(const GenericUri& uri) { return String(uri.GetBaseString(), uri.GetBaseStringLength()); }
121
+ static String GetScheme(const GenericUri& uri) { return String(uri.GetSchemeString(), uri.GetSchemeStringLength()); }
122
+ static String GetAuth(const GenericUri& uri) { return String(uri.GetAuthString(), uri.GetAuthStringLength()); }
123
+ static String GetPath(const GenericUri& uri) { return String(uri.GetPathString(), uri.GetPathStringLength()); }
124
+ static String GetQuery(const GenericUri& uri) { return String(uri.GetQueryString(), uri.GetQueryStringLength()); }
125
+ static String GetFrag(const GenericUri& uri) { return String(uri.GetFragString(), uri.GetFragStringLength()); }
126
+ #endif
127
+
128
+ //! Equality operators
129
+ bool operator==(const GenericUri& rhs) const {
130
+ return Match(rhs, true);
131
+ }
132
+
133
+ bool operator!=(const GenericUri& rhs) const {
134
+ return !Match(rhs, true);
135
+ }
136
+
137
+ bool Match(const GenericUri& uri, bool full = true) const {
138
+ Ch* s1;
139
+ Ch* s2;
140
+ if (full) {
141
+ s1 = uri_;
142
+ s2 = uri.uri_;
143
+ } else {
144
+ s1 = base_;
145
+ s2 = uri.base_;
146
+ }
147
+ if (s1 == s2) return true;
148
+ if (s1 == 0 || s2 == 0) return false;
149
+ return internal::StrCmp<Ch>(s1, s2) == 0;
150
+ }
151
+
152
+ //! Resolve this URI against another (base) URI in accordance with URI resolution rules.
153
+ // See https://tools.ietf.org/html/rfc3986
154
+ // Use for resolving an id or $ref with an in-scope id.
155
+ // Returns a new GenericUri for the resolved URI.
156
+ GenericUri Resolve(const GenericUri& baseuri, Allocator* allocator = 0) {
157
+ GenericUri resuri;
158
+ resuri.allocator_ = allocator;
159
+ // Ensure enough space for combining paths
160
+ resuri.Allocate(GetStringLength() + baseuri.GetStringLength() + 1); // + 1 for joining slash
161
+
162
+ if (!(GetSchemeStringLength() == 0)) {
163
+ // Use all of this URI
164
+ resuri.auth_ = CopyPart(resuri.scheme_, scheme_, GetSchemeStringLength());
165
+ resuri.path_ = CopyPart(resuri.auth_, auth_, GetAuthStringLength());
166
+ resuri.query_ = CopyPart(resuri.path_, path_, GetPathStringLength());
167
+ resuri.frag_ = CopyPart(resuri.query_, query_, GetQueryStringLength());
168
+ resuri.RemoveDotSegments();
169
+ } else {
170
+ // Use the base scheme
171
+ resuri.auth_ = CopyPart(resuri.scheme_, baseuri.scheme_, baseuri.GetSchemeStringLength());
172
+ if (!(GetAuthStringLength() == 0)) {
173
+ // Use this auth, path, query
174
+ resuri.path_ = CopyPart(resuri.auth_, auth_, GetAuthStringLength());
175
+ resuri.query_ = CopyPart(resuri.path_, path_, GetPathStringLength());
176
+ resuri.frag_ = CopyPart(resuri.query_, query_, GetQueryStringLength());
177
+ resuri.RemoveDotSegments();
178
+ } else {
179
+ // Use the base auth
180
+ resuri.path_ = CopyPart(resuri.auth_, baseuri.auth_, baseuri.GetAuthStringLength());
181
+ if (GetPathStringLength() == 0) {
182
+ // Use the base path
183
+ resuri.query_ = CopyPart(resuri.path_, baseuri.path_, baseuri.GetPathStringLength());
184
+ if (GetQueryStringLength() == 0) {
185
+ // Use the base query
186
+ resuri.frag_ = CopyPart(resuri.query_, baseuri.query_, baseuri.GetQueryStringLength());
187
+ } else {
188
+ // Use this query
189
+ resuri.frag_ = CopyPart(resuri.query_, query_, GetQueryStringLength());
190
+ }
191
+ } else {
192
+ if (path_[0] == '/') {
193
+ // Absolute path - use all of this path
194
+ resuri.query_ = CopyPart(resuri.path_, path_, GetPathStringLength());
195
+ resuri.RemoveDotSegments();
196
+ } else {
197
+ // Relative path - append this path to base path after base path's last slash
198
+ size_t pos = 0;
199
+ if (!(baseuri.GetAuthStringLength() == 0) && baseuri.GetPathStringLength() == 0) {
200
+ resuri.path_[pos] = '/';
201
+ pos++;
202
+ }
203
+ size_t lastslashpos = baseuri.GetPathStringLength();
204
+ while (lastslashpos > 0) {
205
+ if (baseuri.path_[lastslashpos - 1] == '/') break;
206
+ lastslashpos--;
207
+ }
208
+ std::memcpy(&resuri.path_[pos], baseuri.path_, lastslashpos * sizeof(Ch));
209
+ pos += lastslashpos;
210
+ resuri.query_ = CopyPart(&resuri.path_[pos], path_, GetPathStringLength());
211
+ resuri.RemoveDotSegments();
212
+ }
213
+ // Use this query
214
+ resuri.frag_ = CopyPart(resuri.query_, query_, GetQueryStringLength());
215
+ }
216
+ }
217
+ }
218
+ // Always use this frag
219
+ resuri.base_ = CopyPart(resuri.frag_, frag_, GetFragStringLength());
220
+
221
+ // Re-constitute base_ and uri_
222
+ resuri.SetBase();
223
+ resuri.uri_ = resuri.base_ + resuri.GetBaseStringLength() + 1;
224
+ resuri.SetUri();
225
+ return resuri;
226
+ }
227
+
228
+ //! Get the allocator of this GenericUri.
229
+ Allocator& GetAllocator() { return *allocator_; }
230
+
231
+ private:
232
+ // Allocate memory for a URI
233
+ // Returns total amount allocated
234
+ std::size_t Allocate(std::size_t len) {
235
+ // Create own allocator if user did not supply.
236
+ if (!allocator_)
237
+ ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();
238
+
239
+ // Allocate one block containing each part of the URI (5) plus base plus full URI, all null terminated.
240
+ // Order: scheme, auth, path, query, frag, base, uri
241
+ size_t total = (3 * len + 7) * sizeof(Ch);
242
+ scheme_ = static_cast<Ch*>(allocator_->Malloc(total));
243
+ *scheme_ = '\0';
244
+ auth_ = scheme_ + 1;
245
+ *auth_ = '\0';
246
+ path_ = auth_ + 1;
247
+ *path_ = '\0';
248
+ query_ = path_ + 1;
249
+ *query_ = '\0';
250
+ frag_ = query_ + 1;
251
+ *frag_ = '\0';
252
+ base_ = frag_ + 1;
253
+ *base_ = '\0';
254
+ uri_ = base_ + 1;
255
+ *uri_ = '\0';
256
+ return total;
257
+ }
258
+
259
+ // Free memory for a URI
260
+ void Free() {
261
+ if (scheme_) {
262
+ Allocator::Free(scheme_);
263
+ scheme_ = 0;
264
+ }
265
+ }
266
+
267
+ // Parse a URI into constituent scheme, authority, path, query, & fragment parts
268
+ // Supports URIs that match regex ^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))? as per
269
+ // https://tools.ietf.org/html/rfc3986
270
+ void Parse(const Ch* uri, std::size_t len) {
271
+ std::size_t start = 0, pos1 = 0, pos2 = 0;
272
+ Allocate(len);
273
+
274
+ // Look for scheme ([^:/?#]+):)?
275
+ if (start < len) {
276
+ while (pos1 < len) {
277
+ if (uri[pos1] == ':') break;
278
+ pos1++;
279
+ }
280
+ if (pos1 != len) {
281
+ while (pos2 < len) {
282
+ if (uri[pos2] == '/') break;
283
+ if (uri[pos2] == '?') break;
284
+ if (uri[pos2] == '#') break;
285
+ pos2++;
286
+ }
287
+ if (pos1 < pos2) {
288
+ pos1++;
289
+ std::memcpy(scheme_, &uri[start], pos1 * sizeof(Ch));
290
+ scheme_[pos1] = '\0';
291
+ start = pos1;
292
+ }
293
+ }
294
+ }
295
+ // Look for auth (//([^/?#]*))?
296
+ auth_ = scheme_ + GetSchemeStringLength() + 1;
297
+ *auth_ = '\0';
298
+ if (start < len - 1 && uri[start] == '/' && uri[start + 1] == '/') {
299
+ pos2 = start + 2;
300
+ while (pos2 < len) {
301
+ if (uri[pos2] == '/') break;
302
+ if (uri[pos2] == '?') break;
303
+ if (uri[pos2] == '#') break;
304
+ pos2++;
305
+ }
306
+ std::memcpy(auth_, &uri[start], (pos2 - start) * sizeof(Ch));
307
+ auth_[pos2 - start] = '\0';
308
+ start = pos2;
309
+ }
310
+ // Look for path ([^?#]*)
311
+ path_ = auth_ + GetAuthStringLength() + 1;
312
+ *path_ = '\0';
313
+ if (start < len) {
314
+ pos2 = start;
315
+ while (pos2 < len) {
316
+ if (uri[pos2] == '?') break;
317
+ if (uri[pos2] == '#') break;
318
+ pos2++;
319
+ }
320
+ if (start != pos2) {
321
+ std::memcpy(path_, &uri[start], (pos2 - start) * sizeof(Ch));
322
+ path_[pos2 - start] = '\0';
323
+ if (path_[0] == '/')
324
+ RemoveDotSegments(); // absolute path - normalize
325
+ start = pos2;
326
+ }
327
+ }
328
+ // Look for query (\?([^#]*))?
329
+ query_ = path_ + GetPathStringLength() + 1;
330
+ *query_ = '\0';
331
+ if (start < len && uri[start] == '?') {
332
+ pos2 = start + 1;
333
+ while (pos2 < len) {
334
+ if (uri[pos2] == '#') break;
335
+ pos2++;
336
+ }
337
+ if (start != pos2) {
338
+ std::memcpy(query_, &uri[start], (pos2 - start) * sizeof(Ch));
339
+ query_[pos2 - start] = '\0';
340
+ start = pos2;
341
+ }
342
+ }
343
+ // Look for fragment (#(.*))?
344
+ frag_ = query_ + GetQueryStringLength() + 1;
345
+ *frag_ = '\0';
346
+ if (start < len && uri[start] == '#') {
347
+ std::memcpy(frag_, &uri[start], (len - start) * sizeof(Ch));
348
+ frag_[len - start] = '\0';
349
+ }
350
+
351
+ // Re-constitute base_ and uri_
352
+ base_ = frag_ + GetFragStringLength() + 1;
353
+ SetBase();
354
+ uri_ = base_ + GetBaseStringLength() + 1;
355
+ SetUri();
356
+ }
357
+
358
+ // Reconstitute base
359
+ void SetBase() {
360
+ Ch* next = base_;
361
+ std::memcpy(next, scheme_, GetSchemeStringLength() * sizeof(Ch));
362
+ next+= GetSchemeStringLength();
363
+ std::memcpy(next, auth_, GetAuthStringLength() * sizeof(Ch));
364
+ next+= GetAuthStringLength();
365
+ std::memcpy(next, path_, GetPathStringLength() * sizeof(Ch));
366
+ next+= GetPathStringLength();
367
+ std::memcpy(next, query_, GetQueryStringLength() * sizeof(Ch));
368
+ next+= GetQueryStringLength();
369
+ *next = '\0';
370
+ }
371
+
372
+ // Reconstitute uri
373
+ void SetUri() {
374
+ Ch* next = uri_;
375
+ std::memcpy(next, base_, GetBaseStringLength() * sizeof(Ch));
376
+ next+= GetBaseStringLength();
377
+ std::memcpy(next, frag_, GetFragStringLength() * sizeof(Ch));
378
+ next+= GetFragStringLength();
379
+ *next = '\0';
380
+ }
381
+
382
+ // Copy a part from one GenericUri to another
383
+ // Return the pointer to the next part to be copied to
384
+ Ch* CopyPart(Ch* to, Ch* from, std::size_t len) {
385
+ RAPIDJSON_ASSERT(to != 0);
386
+ RAPIDJSON_ASSERT(from != 0);
387
+ std::memcpy(to, from, len * sizeof(Ch));
388
+ to[len] = '\0';
389
+ Ch* next = to + len + 1;
390
+ return next;
391
+ }
392
+
393
+ // Remove . and .. segments from the path_ member.
394
+ // https://tools.ietf.org/html/rfc3986
395
+ // This is done in place as we are only removing segments.
396
+ void RemoveDotSegments() {
397
+ std::size_t pathlen = GetPathStringLength();
398
+ std::size_t pathpos = 0; // Position in path_
399
+ std::size_t newpos = 0; // Position in new path_
400
+
401
+ // Loop through each segment in original path_
402
+ while (pathpos < pathlen) {
403
+ // Get next segment, bounded by '/' or end
404
+ size_t slashpos = 0;
405
+ while ((pathpos + slashpos) < pathlen) {
406
+ if (path_[pathpos + slashpos] == '/') break;
407
+ slashpos++;
408
+ }
409
+ // Check for .. and . segments
410
+ if (slashpos == 2 && path_[pathpos] == '.' && path_[pathpos + 1] == '.') {
411
+ // Backup a .. segment in the new path_
412
+ // We expect to find a previously added slash at the end or nothing
413
+ RAPIDJSON_ASSERT(newpos == 0 || path_[newpos - 1] == '/');
414
+ size_t lastslashpos = newpos;
415
+ // Make sure we don't go beyond the start segment
416
+ if (lastslashpos > 1) {
417
+ // Find the next to last slash and back up to it
418
+ lastslashpos--;
419
+ while (lastslashpos > 0) {
420
+ if (path_[lastslashpos - 1] == '/') break;
421
+ lastslashpos--;
422
+ }
423
+ // Set the new path_ position
424
+ newpos = lastslashpos;
425
+ }
426
+ } else if (slashpos == 1 && path_[pathpos] == '.') {
427
+ // Discard . segment, leaves new path_ unchanged
428
+ } else {
429
+ // Move any other kind of segment to the new path_
430
+ RAPIDJSON_ASSERT(newpos <= pathpos);
431
+ std::memmove(&path_[newpos], &path_[pathpos], slashpos * sizeof(Ch));
432
+ newpos += slashpos;
433
+ // Add slash if not at end
434
+ if ((pathpos + slashpos) < pathlen) {
435
+ path_[newpos] = '/';
436
+ newpos++;
437
+ }
438
+ }
439
+ // Move to next segment
440
+ pathpos += slashpos + 1;
441
+ }
442
+ path_[newpos] = '\0';
443
+ }
444
+
445
+ Ch* uri_; // Everything
446
+ Ch* base_; // Everything except fragment
447
+ Ch* scheme_; // Includes the :
448
+ Ch* auth_; // Includes the //
449
+ Ch* path_; // Absolute if starts with /
450
+ Ch* query_; // Includes the ?
451
+ Ch* frag_; // Includes the #
452
+
453
+ Allocator* allocator_; //!< The current allocator. It is either user-supplied or equal to ownAllocator_.
454
+ Allocator* ownAllocator_; //!< Allocator owned by this Uri.
455
+ };
456
+
457
+ //! GenericUri for Value (UTF-8, default allocator).
458
+ typedef GenericUri<Value> Uri;
459
+
460
+ RAPIDJSON_NAMESPACE_END
461
+
462
+ #if defined(__clang__)
463
+ RAPIDJSON_DIAG_POP
464
+ #endif
465
+
466
+ #endif // RAPIDJSON_URI_H_
@@ -130,7 +130,8 @@ public:
130
130
  "integers.json",
131
131
  "mixed.json",
132
132
  "nulls.json",
133
- "paragraphs.json"
133
+ "paragraphs.json",
134
+ "alotofkeys.json"
134
135
  };
135
136
 
136
137
  for (size_t j = 0; j < sizeof(typesfilenames) / sizeof(typesfilenames[0]); j++) {
@@ -158,7 +159,7 @@ public:
158
159
  free(whitespace_);
159
160
  json_ = 0;
160
161
  whitespace_ = 0;
161
- for (size_t i = 0; i < 7; i++) {
162
+ for (size_t i = 0; i < 8; i++) {
162
163
  free(types_[i]);
163
164
  types_[i] = 0;
164
165
  }
@@ -174,8 +175,8 @@ protected:
174
175
  size_t length_;
175
176
  char *whitespace_;
176
177
  size_t whitespace_length_;
177
- char *types_[7];
178
- size_t typesLength_[7];
178
+ char *types_[8];
179
+ size_t typesLength_[8];
179
180
 
180
181
  static const size_t kTrialCount = 1000;
181
182
  };
@@ -26,6 +26,7 @@
26
26
  #include "rapidjson/memorystream.h"
27
27
 
28
28
  #include <fstream>
29
+ #include <vector>
29
30
 
30
31
  #ifdef RAPIDJSON_SSE2
31
32
  #define SIMD_SUFFIX(name) name##_SSE2
@@ -52,7 +53,7 @@ public:
52
53
  // Parse as a document
53
54
  EXPECT_FALSE(doc_.Parse(json_).HasParseError());
54
55
 
55
- for (size_t i = 0; i < 7; i++)
56
+ for (size_t i = 0; i < 8; i++)
56
57
  EXPECT_FALSE(typesDoc_[i].Parse(types_[i]).HasParseError());
57
58
  }
58
59
 
@@ -68,7 +69,7 @@ private:
68
69
  protected:
69
70
  char *temp_;
70
71
  Document doc_;
71
- Document typesDoc_[7];
72
+ Document typesDoc_[8];
72
73
  };
73
74
 
74
75
  TEST_F(RapidJson, SIMD_SUFFIX(ReaderParseInsitu_DummyHandler)) {
@@ -335,6 +336,23 @@ TEST_F(RapidJson, DocumentAccept) {
335
336
  }
336
337
  }
337
338
 
339
+ TEST_F(RapidJson, DocumentFind) {
340
+ typedef Document::ValueType ValueType;
341
+ typedef ValueType::ConstMemberIterator ConstMemberIterator;
342
+ const Document &doc = typesDoc_[7]; // alotofkeys.json
343
+ if (doc.IsObject()) {
344
+ std::vector<const ValueType*> keys;
345
+ for (ConstMemberIterator it = doc.MemberBegin(); it != doc.MemberEnd(); ++it) {
346
+ keys.push_back(&it->name);
347
+ }
348
+ for (size_t i = 0; i < kTrialCount; i++) {
349
+ for (size_t j = 0; j < keys.size(); j++) {
350
+ EXPECT_TRUE(doc.FindMember(*keys[j]) != doc.MemberEnd());
351
+ }
352
+ }
353
+ }
354
+ }
355
+
338
356
  struct NullStream {
339
357
  typedef char Ch;
340
358
 
@@ -16,6 +16,7 @@ set(UNITTEST_SOURCES
16
16
  jsoncheckertest.cpp
17
17
  namespacetest.cpp
18
18
  pointertest.cpp
19
+ platformtest.cpp
19
20
  prettywritertest.cpp
20
21
  ostreamwrappertest.cpp
21
22
  readertest.cpp
@@ -26,6 +27,7 @@ set(UNITTEST_SOURCES
26
27
  stringbuffertest.cpp
27
28
  strtodtest.cpp
28
29
  unittest.cpp
30
+ uritest.cpp
29
31
  valuetest.cpp
30
32
  writertest.cpp)
31
33