]> git.proxmox.com Git - ceph.git/blob - ceph/src/s3select/rapidjson/test/unittest/pointertest.cpp
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / s3select / rapidjson / test / unittest / pointertest.cpp
1 // Tencent is pleased to support the open source community by making RapidJSON available.
2 //
3 // Copyright (C) 2015 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 #include "rapidjson/pointer.h"
17 #include "rapidjson/stringbuffer.h"
18 #include "rapidjson/ostreamwrapper.h"
19 #include <sstream>
20 #include <map>
21 #include <algorithm>
22
23 using namespace rapidjson;
24
25 static const char kJson[] = "{\n"
26 " \"foo\":[\"bar\", \"baz\"],\n"
27 " \"\" : 0,\n"
28 " \"a/b\" : 1,\n"
29 " \"c%d\" : 2,\n"
30 " \"e^f\" : 3,\n"
31 " \"g|h\" : 4,\n"
32 " \"i\\\\j\" : 5,\n"
33 " \"k\\\"l\" : 6,\n"
34 " \" \" : 7,\n"
35 " \"m~n\" : 8\n"
36 "}";
37
38 TEST(Pointer, DefaultConstructor) {
39 Pointer p;
40 EXPECT_TRUE(p.IsValid());
41 EXPECT_EQ(0u, p.GetTokenCount());
42 }
43
44 TEST(Pointer, Parse) {
45 {
46 Pointer p("");
47 EXPECT_TRUE(p.IsValid());
48 EXPECT_EQ(0u, p.GetTokenCount());
49 }
50
51 {
52 Pointer p("/");
53 EXPECT_TRUE(p.IsValid());
54 EXPECT_EQ(1u, p.GetTokenCount());
55 EXPECT_EQ(0u, p.GetTokens()[0].length);
56 EXPECT_STREQ("", p.GetTokens()[0].name);
57 EXPECT_EQ(kPointerInvalidIndex, p.GetTokens()[0].index);
58 }
59
60 {
61 Pointer p("/foo");
62 EXPECT_TRUE(p.IsValid());
63 EXPECT_EQ(1u, p.GetTokenCount());
64 EXPECT_EQ(3u, p.GetTokens()[0].length);
65 EXPECT_STREQ("foo", p.GetTokens()[0].name);
66 EXPECT_EQ(kPointerInvalidIndex, p.GetTokens()[0].index);
67 }
68
69 #if RAPIDJSON_HAS_STDSTRING
70 {
71 Pointer p(std::string("/foo"));
72 EXPECT_TRUE(p.IsValid());
73 EXPECT_EQ(1u, p.GetTokenCount());
74 EXPECT_EQ(3u, p.GetTokens()[0].length);
75 EXPECT_STREQ("foo", p.GetTokens()[0].name);
76 EXPECT_EQ(kPointerInvalidIndex, p.GetTokens()[0].index);
77 }
78 #endif
79
80 {
81 Pointer p("/foo/0");
82 EXPECT_TRUE(p.IsValid());
83 EXPECT_EQ(2u, p.GetTokenCount());
84 EXPECT_EQ(3u, p.GetTokens()[0].length);
85 EXPECT_STREQ("foo", p.GetTokens()[0].name);
86 EXPECT_EQ(kPointerInvalidIndex, p.GetTokens()[0].index);
87 EXPECT_EQ(1u, p.GetTokens()[1].length);
88 EXPECT_STREQ("0", p.GetTokens()[1].name);
89 EXPECT_EQ(0u, p.GetTokens()[1].index);
90 }
91
92 {
93 // Unescape ~1
94 Pointer p("/a~1b");
95 EXPECT_TRUE(p.IsValid());
96 EXPECT_EQ(1u, p.GetTokenCount());
97 EXPECT_EQ(3u, p.GetTokens()[0].length);
98 EXPECT_STREQ("a/b", p.GetTokens()[0].name);
99 }
100
101 {
102 // Unescape ~0
103 Pointer p("/m~0n");
104 EXPECT_TRUE(p.IsValid());
105 EXPECT_EQ(1u, p.GetTokenCount());
106 EXPECT_EQ(3u, p.GetTokens()[0].length);
107 EXPECT_STREQ("m~n", p.GetTokens()[0].name);
108 }
109
110 {
111 // empty name
112 Pointer p("/");
113 EXPECT_TRUE(p.IsValid());
114 EXPECT_EQ(1u, p.GetTokenCount());
115 EXPECT_EQ(0u, p.GetTokens()[0].length);
116 EXPECT_STREQ("", p.GetTokens()[0].name);
117 }
118
119 {
120 // empty and non-empty name
121 Pointer p("//a");
122 EXPECT_TRUE(p.IsValid());
123 EXPECT_EQ(2u, p.GetTokenCount());
124 EXPECT_EQ(0u, p.GetTokens()[0].length);
125 EXPECT_STREQ("", p.GetTokens()[0].name);
126 EXPECT_EQ(1u, p.GetTokens()[1].length);
127 EXPECT_STREQ("a", p.GetTokens()[1].name);
128 }
129
130 {
131 // Null characters
132 Pointer p("/\0\0", 3);
133 EXPECT_TRUE(p.IsValid());
134 EXPECT_EQ(1u, p.GetTokenCount());
135 EXPECT_EQ(2u, p.GetTokens()[0].length);
136 EXPECT_EQ('\0', p.GetTokens()[0].name[0]);
137 EXPECT_EQ('\0', p.GetTokens()[0].name[1]);
138 EXPECT_EQ('\0', p.GetTokens()[0].name[2]);
139 }
140
141 {
142 // Valid index
143 Pointer p("/123");
144 EXPECT_TRUE(p.IsValid());
145 EXPECT_EQ(1u, p.GetTokenCount());
146 EXPECT_STREQ("123", p.GetTokens()[0].name);
147 EXPECT_EQ(123u, p.GetTokens()[0].index);
148 }
149
150 {
151 // Invalid index (with leading zero)
152 Pointer p("/01");
153 EXPECT_TRUE(p.IsValid());
154 EXPECT_EQ(1u, p.GetTokenCount());
155 EXPECT_STREQ("01", p.GetTokens()[0].name);
156 EXPECT_EQ(kPointerInvalidIndex, p.GetTokens()[0].index);
157 }
158
159 if (sizeof(SizeType) == 4) {
160 // Invalid index (overflow)
161 Pointer p("/4294967296");
162 EXPECT_TRUE(p.IsValid());
163 EXPECT_EQ(1u, p.GetTokenCount());
164 EXPECT_STREQ("4294967296", p.GetTokens()[0].name);
165 EXPECT_EQ(kPointerInvalidIndex, p.GetTokens()[0].index);
166 }
167
168 {
169 // kPointerParseErrorTokenMustBeginWithSolidus
170 Pointer p(" ");
171 EXPECT_FALSE(p.IsValid());
172 EXPECT_EQ(kPointerParseErrorTokenMustBeginWithSolidus, p.GetParseErrorCode());
173 EXPECT_EQ(0u, p.GetParseErrorOffset());
174 }
175
176 {
177 // kPointerParseErrorInvalidEscape
178 Pointer p("/~");
179 EXPECT_FALSE(p.IsValid());
180 EXPECT_EQ(kPointerParseErrorInvalidEscape, p.GetParseErrorCode());
181 EXPECT_EQ(2u, p.GetParseErrorOffset());
182 }
183
184 {
185 // kPointerParseErrorInvalidEscape
186 Pointer p("/~2");
187 EXPECT_FALSE(p.IsValid());
188 EXPECT_EQ(kPointerParseErrorInvalidEscape, p.GetParseErrorCode());
189 EXPECT_EQ(2u, p.GetParseErrorOffset());
190 }
191 }
192
193 TEST(Pointer, Parse_URIFragment) {
194 {
195 Pointer p("#");
196 EXPECT_TRUE(p.IsValid());
197 EXPECT_EQ(0u, p.GetTokenCount());
198 }
199
200 {
201 Pointer p("#/foo");
202 EXPECT_TRUE(p.IsValid());
203 EXPECT_EQ(1u, p.GetTokenCount());
204 EXPECT_EQ(3u, p.GetTokens()[0].length);
205 EXPECT_STREQ("foo", p.GetTokens()[0].name);
206 }
207
208 {
209 Pointer p("#/foo/0");
210 EXPECT_TRUE(p.IsValid());
211 EXPECT_EQ(2u, p.GetTokenCount());
212 EXPECT_EQ(3u, p.GetTokens()[0].length);
213 EXPECT_STREQ("foo", p.GetTokens()[0].name);
214 EXPECT_EQ(1u, p.GetTokens()[1].length);
215 EXPECT_STREQ("0", p.GetTokens()[1].name);
216 EXPECT_EQ(0u, p.GetTokens()[1].index);
217 }
218
219 {
220 // Unescape ~1
221 Pointer p("#/a~1b");
222 EXPECT_TRUE(p.IsValid());
223 EXPECT_EQ(1u, p.GetTokenCount());
224 EXPECT_EQ(3u, p.GetTokens()[0].length);
225 EXPECT_STREQ("a/b", p.GetTokens()[0].name);
226 }
227
228 {
229 // Unescape ~0
230 Pointer p("#/m~0n");
231 EXPECT_TRUE(p.IsValid());
232 EXPECT_EQ(1u, p.GetTokenCount());
233 EXPECT_EQ(3u, p.GetTokens()[0].length);
234 EXPECT_STREQ("m~n", p.GetTokens()[0].name);
235 }
236
237 {
238 // empty name
239 Pointer p("#/");
240 EXPECT_TRUE(p.IsValid());
241 EXPECT_EQ(1u, p.GetTokenCount());
242 EXPECT_EQ(0u, p.GetTokens()[0].length);
243 EXPECT_STREQ("", p.GetTokens()[0].name);
244 }
245
246 {
247 // empty and non-empty name
248 Pointer p("#//a");
249 EXPECT_TRUE(p.IsValid());
250 EXPECT_EQ(2u, p.GetTokenCount());
251 EXPECT_EQ(0u, p.GetTokens()[0].length);
252 EXPECT_STREQ("", p.GetTokens()[0].name);
253 EXPECT_EQ(1u, p.GetTokens()[1].length);
254 EXPECT_STREQ("a", p.GetTokens()[1].name);
255 }
256
257 {
258 // Null characters
259 Pointer p("#/%00%00");
260 EXPECT_TRUE(p.IsValid());
261 EXPECT_EQ(1u, p.GetTokenCount());
262 EXPECT_EQ(2u, p.GetTokens()[0].length);
263 EXPECT_EQ('\0', p.GetTokens()[0].name[0]);
264 EXPECT_EQ('\0', p.GetTokens()[0].name[1]);
265 EXPECT_EQ('\0', p.GetTokens()[0].name[2]);
266 }
267
268 {
269 // Percentage Escapes
270 EXPECT_STREQ("c%d", Pointer("#/c%25d").GetTokens()[0].name);
271 EXPECT_STREQ("e^f", Pointer("#/e%5Ef").GetTokens()[0].name);
272 EXPECT_STREQ("g|h", Pointer("#/g%7Ch").GetTokens()[0].name);
273 EXPECT_STREQ("i\\j", Pointer("#/i%5Cj").GetTokens()[0].name);
274 EXPECT_STREQ("k\"l", Pointer("#/k%22l").GetTokens()[0].name);
275 EXPECT_STREQ(" ", Pointer("#/%20").GetTokens()[0].name);
276 }
277
278 {
279 // Valid index
280 Pointer p("#/123");
281 EXPECT_TRUE(p.IsValid());
282 EXPECT_EQ(1u, p.GetTokenCount());
283 EXPECT_STREQ("123", p.GetTokens()[0].name);
284 EXPECT_EQ(123u, p.GetTokens()[0].index);
285 }
286
287 {
288 // Invalid index (with leading zero)
289 Pointer p("#/01");
290 EXPECT_TRUE(p.IsValid());
291 EXPECT_EQ(1u, p.GetTokenCount());
292 EXPECT_STREQ("01", p.GetTokens()[0].name);
293 EXPECT_EQ(kPointerInvalidIndex, p.GetTokens()[0].index);
294 }
295
296 if (sizeof(SizeType) == 4) {
297 // Invalid index (overflow)
298 Pointer p("#/4294967296");
299 EXPECT_TRUE(p.IsValid());
300 EXPECT_EQ(1u, p.GetTokenCount());
301 EXPECT_STREQ("4294967296", p.GetTokens()[0].name);
302 EXPECT_EQ(kPointerInvalidIndex, p.GetTokens()[0].index);
303 }
304
305 {
306 // Decode UTF-8 perecent encoding to UTF-8
307 Pointer p("#/%C2%A2");
308 EXPECT_TRUE(p.IsValid());
309 EXPECT_EQ(1u, p.GetTokenCount());
310 EXPECT_STREQ("\xC2\xA2", p.GetTokens()[0].name);
311 }
312
313 {
314 // Decode UTF-8 perecent encoding to UTF-16
315 GenericPointer<GenericValue<UTF16<> > > p(L"#/%C2%A2");
316 EXPECT_TRUE(p.IsValid());
317 EXPECT_EQ(1u, p.GetTokenCount());
318 EXPECT_EQ(static_cast<UTF16<>::Ch>(0x00A2), p.GetTokens()[0].name[0]);
319 EXPECT_EQ(1u, p.GetTokens()[0].length);
320 }
321
322 {
323 // Decode UTF-8 perecent encoding to UTF-16
324 GenericPointer<GenericValue<UTF16<> > > p(L"#/%E2%82%AC");
325 EXPECT_TRUE(p.IsValid());
326 EXPECT_EQ(1u, p.GetTokenCount());
327 EXPECT_EQ(static_cast<UTF16<>::Ch>(0x20AC), p.GetTokens()[0].name[0]);
328 EXPECT_EQ(1u, p.GetTokens()[0].length);
329 }
330
331 {
332 // kPointerParseErrorTokenMustBeginWithSolidus
333 Pointer p("# ");
334 EXPECT_FALSE(p.IsValid());
335 EXPECT_EQ(kPointerParseErrorTokenMustBeginWithSolidus, p.GetParseErrorCode());
336 EXPECT_EQ(1u, p.GetParseErrorOffset());
337 }
338
339 {
340 // kPointerParseErrorInvalidEscape
341 Pointer p("#/~");
342 EXPECT_FALSE(p.IsValid());
343 EXPECT_EQ(kPointerParseErrorInvalidEscape, p.GetParseErrorCode());
344 EXPECT_EQ(3u, p.GetParseErrorOffset());
345 }
346
347 {
348 // kPointerParseErrorInvalidEscape
349 Pointer p("#/~2");
350 EXPECT_FALSE(p.IsValid());
351 EXPECT_EQ(kPointerParseErrorInvalidEscape, p.GetParseErrorCode());
352 EXPECT_EQ(3u, p.GetParseErrorOffset());
353 }
354
355 {
356 // kPointerParseErrorInvalidPercentEncoding
357 Pointer p("#/%");
358 EXPECT_FALSE(p.IsValid());
359 EXPECT_EQ(kPointerParseErrorInvalidPercentEncoding, p.GetParseErrorCode());
360 EXPECT_EQ(2u, p.GetParseErrorOffset());
361 }
362
363 {
364 // kPointerParseErrorInvalidPercentEncoding (invalid hex)
365 Pointer p("#/%g0");
366 EXPECT_FALSE(p.IsValid());
367 EXPECT_EQ(kPointerParseErrorInvalidPercentEncoding, p.GetParseErrorCode());
368 EXPECT_EQ(2u, p.GetParseErrorOffset());
369 }
370
371 {
372 // kPointerParseErrorInvalidPercentEncoding (invalid hex)
373 Pointer p("#/%0g");
374 EXPECT_FALSE(p.IsValid());
375 EXPECT_EQ(kPointerParseErrorInvalidPercentEncoding, p.GetParseErrorCode());
376 EXPECT_EQ(2u, p.GetParseErrorOffset());
377 }
378
379 {
380 // kPointerParseErrorInvalidPercentEncoding (incomplete UTF-8 sequence)
381 Pointer p("#/%C2");
382 EXPECT_FALSE(p.IsValid());
383 EXPECT_EQ(kPointerParseErrorInvalidPercentEncoding, p.GetParseErrorCode());
384 EXPECT_EQ(2u, p.GetParseErrorOffset());
385 }
386
387 {
388 // kPointerParseErrorCharacterMustPercentEncode
389 Pointer p("#/ ");
390 EXPECT_FALSE(p.IsValid());
391 EXPECT_EQ(kPointerParseErrorCharacterMustPercentEncode, p.GetParseErrorCode());
392 EXPECT_EQ(2u, p.GetParseErrorOffset());
393 }
394
395 {
396 // kPointerParseErrorCharacterMustPercentEncode
397 Pointer p("#/\n");
398 EXPECT_FALSE(p.IsValid());
399 EXPECT_EQ(kPointerParseErrorCharacterMustPercentEncode, p.GetParseErrorCode());
400 EXPECT_EQ(2u, p.GetParseErrorOffset());
401 }
402 }
403
404 TEST(Pointer, Stringify) {
405 // Test by roundtrip
406 const char* sources[] = {
407 "",
408 "/foo",
409 "/foo/0",
410 "/",
411 "/a~1b",
412 "/c%d",
413 "/e^f",
414 "/g|h",
415 "/i\\j",
416 "/k\"l",
417 "/ ",
418 "/m~0n",
419 "/\xC2\xA2",
420 "/\xE2\x82\xAC",
421 "/\xF0\x9D\x84\x9E"
422 };
423
424 for (size_t i = 0; i < sizeof(sources) / sizeof(sources[0]); i++) {
425 Pointer p(sources[i]);
426 StringBuffer s;
427 EXPECT_TRUE(p.Stringify(s));
428 EXPECT_STREQ(sources[i], s.GetString());
429
430 // Stringify to URI fragment
431 StringBuffer s2;
432 EXPECT_TRUE(p.StringifyUriFragment(s2));
433 Pointer p2(s2.GetString(), s2.GetSize());
434 EXPECT_TRUE(p2.IsValid());
435 EXPECT_TRUE(p == p2);
436 }
437
438 {
439 // Strigify to URI fragment with an invalid UTF-8 sequence
440 Pointer p("/\xC2");
441 StringBuffer s;
442 EXPECT_FALSE(p.StringifyUriFragment(s));
443 }
444 }
445
446 // Construct a Pointer with static tokens, no dynamic allocation involved.
447 #define NAME(s) { s, static_cast<SizeType>(sizeof(s) / sizeof(s[0]) - 1), kPointerInvalidIndex }
448 #define INDEX(i) { #i, static_cast<SizeType>(sizeof(#i) - 1), i }
449
450 static const Pointer::Token kTokens[] = { NAME("foo"), INDEX(0) }; // equivalent to "/foo/0"
451
452 #undef NAME
453 #undef INDEX
454
455 TEST(Pointer, ConstructorWithToken) {
456 Pointer p(kTokens, sizeof(kTokens) / sizeof(kTokens[0]));
457 EXPECT_TRUE(p.IsValid());
458 EXPECT_EQ(2u, p.GetTokenCount());
459 EXPECT_EQ(3u, p.GetTokens()[0].length);
460 EXPECT_STREQ("foo", p.GetTokens()[0].name);
461 EXPECT_EQ(1u, p.GetTokens()[1].length);
462 EXPECT_STREQ("0", p.GetTokens()[1].name);
463 EXPECT_EQ(0u, p.GetTokens()[1].index);
464 }
465
466 TEST(Pointer, CopyConstructor) {
467 {
468 CrtAllocator allocator;
469 Pointer p("/foo/0", &allocator);
470 Pointer q(p);
471 EXPECT_TRUE(q.IsValid());
472 EXPECT_EQ(2u, q.GetTokenCount());
473 EXPECT_EQ(3u, q.GetTokens()[0].length);
474 EXPECT_STREQ("foo", q.GetTokens()[0].name);
475 EXPECT_EQ(1u, q.GetTokens()[1].length);
476 EXPECT_STREQ("0", q.GetTokens()[1].name);
477 EXPECT_EQ(0u, q.GetTokens()[1].index);
478
479 // Copied pointer needs to have its own allocator
480 EXPECT_NE(&p.GetAllocator(), &q.GetAllocator());
481 }
482
483 // Static tokens
484 {
485 Pointer p(kTokens, sizeof(kTokens) / sizeof(kTokens[0]));
486 Pointer q(p);
487 EXPECT_TRUE(q.IsValid());
488 EXPECT_EQ(2u, q.GetTokenCount());
489 EXPECT_EQ(3u, q.GetTokens()[0].length);
490 EXPECT_STREQ("foo", q.GetTokens()[0].name);
491 EXPECT_EQ(1u, q.GetTokens()[1].length);
492 EXPECT_STREQ("0", q.GetTokens()[1].name);
493 EXPECT_EQ(0u, q.GetTokens()[1].index);
494 }
495 }
496
497 TEST(Pointer, Assignment) {
498 {
499 CrtAllocator allocator;
500 Pointer p("/foo/0", &allocator);
501 Pointer q;
502 q = p;
503 EXPECT_TRUE(q.IsValid());
504 EXPECT_EQ(2u, q.GetTokenCount());
505 EXPECT_EQ(3u, q.GetTokens()[0].length);
506 EXPECT_STREQ("foo", q.GetTokens()[0].name);
507 EXPECT_EQ(1u, q.GetTokens()[1].length);
508 EXPECT_STREQ("0", q.GetTokens()[1].name);
509 EXPECT_EQ(0u, q.GetTokens()[1].index);
510 EXPECT_NE(&p.GetAllocator(), &q.GetAllocator());
511 q = static_cast<const Pointer &>(q);
512 EXPECT_TRUE(q.IsValid());
513 EXPECT_EQ(2u, q.GetTokenCount());
514 EXPECT_EQ(3u, q.GetTokens()[0].length);
515 EXPECT_STREQ("foo", q.GetTokens()[0].name);
516 EXPECT_EQ(1u, q.GetTokens()[1].length);
517 EXPECT_STREQ("0", q.GetTokens()[1].name);
518 EXPECT_EQ(0u, q.GetTokens()[1].index);
519 EXPECT_NE(&p.GetAllocator(), &q.GetAllocator());
520 }
521
522 // Static tokens
523 {
524 Pointer p(kTokens, sizeof(kTokens) / sizeof(kTokens[0]));
525 Pointer q;
526 q = p;
527 EXPECT_TRUE(q.IsValid());
528 EXPECT_EQ(2u, q.GetTokenCount());
529 EXPECT_EQ(3u, q.GetTokens()[0].length);
530 EXPECT_STREQ("foo", q.GetTokens()[0].name);
531 EXPECT_EQ(1u, q.GetTokens()[1].length);
532 EXPECT_STREQ("0", q.GetTokens()[1].name);
533 EXPECT_EQ(0u, q.GetTokens()[1].index);
534 }
535 }
536
537 TEST(Pointer, Swap) {
538 Pointer p("/foo/0");
539 Pointer q(&p.GetAllocator());
540
541 q.Swap(p);
542 EXPECT_EQ(&q.GetAllocator(), &p.GetAllocator());
543 EXPECT_TRUE(p.IsValid());
544 EXPECT_TRUE(q.IsValid());
545 EXPECT_EQ(0u, p.GetTokenCount());
546 EXPECT_EQ(2u, q.GetTokenCount());
547 EXPECT_EQ(3u, q.GetTokens()[0].length);
548 EXPECT_STREQ("foo", q.GetTokens()[0].name);
549 EXPECT_EQ(1u, q.GetTokens()[1].length);
550 EXPECT_STREQ("0", q.GetTokens()[1].name);
551 EXPECT_EQ(0u, q.GetTokens()[1].index);
552
553 // std::swap compatibility
554 std::swap(p, q);
555 EXPECT_EQ(&p.GetAllocator(), &q.GetAllocator());
556 EXPECT_TRUE(q.IsValid());
557 EXPECT_TRUE(p.IsValid());
558 EXPECT_EQ(0u, q.GetTokenCount());
559 EXPECT_EQ(2u, p.GetTokenCount());
560 EXPECT_EQ(3u, p.GetTokens()[0].length);
561 EXPECT_STREQ("foo", p.GetTokens()[0].name);
562 EXPECT_EQ(1u, p.GetTokens()[1].length);
563 EXPECT_STREQ("0", p.GetTokens()[1].name);
564 EXPECT_EQ(0u, p.GetTokens()[1].index);
565 }
566
567 TEST(Pointer, Append) {
568 {
569 Pointer p;
570 Pointer q = p.Append("foo");
571 EXPECT_TRUE(Pointer("/foo") == q);
572 q = q.Append(1234);
573 EXPECT_TRUE(Pointer("/foo/1234") == q);
574 q = q.Append("");
575 EXPECT_TRUE(Pointer("/foo/1234/") == q);
576 }
577
578 {
579 Pointer p;
580 Pointer q = p.Append(Value("foo").Move());
581 EXPECT_TRUE(Pointer("/foo") == q);
582 q = q.Append(Value(1234).Move());
583 EXPECT_TRUE(Pointer("/foo/1234") == q);
584 q = q.Append(Value(kStringType).Move());
585 EXPECT_TRUE(Pointer("/foo/1234/") == q);
586 }
587
588 #if RAPIDJSON_HAS_STDSTRING
589 {
590 Pointer p;
591 Pointer q = p.Append(std::string("foo"));
592 EXPECT_TRUE(Pointer("/foo") == q);
593 }
594 #endif
595 }
596
597 TEST(Pointer, Equality) {
598 EXPECT_TRUE(Pointer("/foo/0") == Pointer("/foo/0"));
599 EXPECT_FALSE(Pointer("/foo/0") == Pointer("/foo/1"));
600 EXPECT_FALSE(Pointer("/foo/0") == Pointer("/foo/0/1"));
601 EXPECT_FALSE(Pointer("/foo/0") == Pointer("a"));
602 EXPECT_FALSE(Pointer("a") == Pointer("a")); // Invalid always not equal
603 }
604
605 TEST(Pointer, Inequality) {
606 EXPECT_FALSE(Pointer("/foo/0") != Pointer("/foo/0"));
607 EXPECT_TRUE(Pointer("/foo/0") != Pointer("/foo/1"));
608 EXPECT_TRUE(Pointer("/foo/0") != Pointer("/foo/0/1"));
609 EXPECT_TRUE(Pointer("/foo/0") != Pointer("a"));
610 EXPECT_TRUE(Pointer("a") != Pointer("a")); // Invalid always not equal
611 }
612
613 TEST(Pointer, Create) {
614 Document d;
615 {
616 Value* v = &Pointer("").Create(d, d.GetAllocator());
617 EXPECT_EQ(&d, v);
618 }
619 {
620 Value* v = &Pointer("/foo").Create(d, d.GetAllocator());
621 EXPECT_EQ(&d["foo"], v);
622 }
623 {
624 Value* v = &Pointer("/foo/0").Create(d, d.GetAllocator());
625 EXPECT_EQ(&d["foo"][0], v);
626 }
627 {
628 Value* v = &Pointer("/foo/-").Create(d, d.GetAllocator());
629 EXPECT_EQ(&d["foo"][1], v);
630 }
631
632 {
633 Value* v = &Pointer("/foo/-/-").Create(d, d.GetAllocator());
634 // "foo/-" is a newly created null value x.
635 // "foo/-/-" finds that x is not an array, it converts x to empty object
636 // and treats - as "-" member name
637 EXPECT_EQ(&d["foo"][2]["-"], v);
638 }
639
640 {
641 // Document with no allocator
642 Value* v = &Pointer("/foo/-").Create(d);
643 EXPECT_EQ(&d["foo"][3], v);
644 }
645
646 {
647 // Value (not document) must give allocator
648 Value* v = &Pointer("/-").Create(d["foo"], d.GetAllocator());
649 EXPECT_EQ(&d["foo"][4], v);
650 }
651 }
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
699 TEST(Pointer, Get) {
700 Document d;
701 d.Parse(kJson);
702
703 EXPECT_EQ(&d, Pointer("").Get(d));
704 EXPECT_EQ(&d["foo"], Pointer("/foo").Get(d));
705 EXPECT_EQ(&d["foo"][0], Pointer("/foo/0").Get(d));
706 EXPECT_EQ(&d[""], Pointer("/").Get(d));
707 EXPECT_EQ(&d["a/b"], Pointer("/a~1b").Get(d));
708 EXPECT_EQ(&d["c%d"], Pointer("/c%d").Get(d));
709 EXPECT_EQ(&d["e^f"], Pointer("/e^f").Get(d));
710 EXPECT_EQ(&d["g|h"], Pointer("/g|h").Get(d));
711 EXPECT_EQ(&d["i\\j"], Pointer("/i\\j").Get(d));
712 EXPECT_EQ(&d["k\"l"], Pointer("/k\"l").Get(d));
713 EXPECT_EQ(&d[" "], Pointer("/ ").Get(d));
714 EXPECT_EQ(&d["m~n"], Pointer("/m~0n").Get(d));
715
716 EXPECT_TRUE(Pointer("/abc").Get(d) == 0); // Out of boundary
717 size_t unresolvedTokenIndex;
718 EXPECT_TRUE(Pointer("/foo/2").Get(d, &unresolvedTokenIndex) == 0); // Out of boundary
719 EXPECT_EQ(1u, unresolvedTokenIndex);
720 EXPECT_TRUE(Pointer("/foo/a").Get(d, &unresolvedTokenIndex) == 0); // "/foo" is an array, cannot query by "a"
721 EXPECT_EQ(1u, unresolvedTokenIndex);
722 EXPECT_TRUE(Pointer("/foo/0/0").Get(d, &unresolvedTokenIndex) == 0); // "/foo/0" is an string, cannot further query
723 EXPECT_EQ(2u, unresolvedTokenIndex);
724 EXPECT_TRUE(Pointer("/foo/0/a").Get(d, &unresolvedTokenIndex) == 0); // "/foo/0" is an string, cannot further query
725 EXPECT_EQ(2u, unresolvedTokenIndex);
726
727 Pointer::Token tokens[] = { { "foo ...", 3, kPointerInvalidIndex } };
728 EXPECT_EQ(&d["foo"], Pointer(tokens, 1).Get(d));
729 }
730
731 TEST(Pointer, GetWithDefault) {
732 Document d;
733 d.Parse(kJson);
734
735 // Value version
736 Document::AllocatorType& a = d.GetAllocator();
737 const Value v("qux");
738 EXPECT_TRUE(Value("bar") == Pointer("/foo/0").GetWithDefault(d, v, a));
739 EXPECT_TRUE(Value("baz") == Pointer("/foo/1").GetWithDefault(d, v, a));
740 EXPECT_TRUE(Value("qux") == Pointer("/foo/2").GetWithDefault(d, v, a));
741 EXPECT_TRUE(Value("last") == Pointer("/foo/-").GetWithDefault(d, Value("last").Move(), a));
742 EXPECT_STREQ("last", d["foo"][3].GetString());
743
744 EXPECT_TRUE(Pointer("/foo/null").GetWithDefault(d, Value().Move(), a).IsNull());
745 EXPECT_TRUE(Pointer("/foo/null").GetWithDefault(d, "x", a).IsNull());
746
747 // Generic version
748 EXPECT_EQ(-1, Pointer("/foo/int").GetWithDefault(d, -1, a).GetInt());
749 EXPECT_EQ(-1, Pointer("/foo/int").GetWithDefault(d, -2, a).GetInt());
750 EXPECT_EQ(0x87654321, Pointer("/foo/uint").GetWithDefault(d, 0x87654321, a).GetUint());
751 EXPECT_EQ(0x87654321, Pointer("/foo/uint").GetWithDefault(d, 0x12345678, a).GetUint());
752
753 const int64_t i64 = static_cast<int64_t>(RAPIDJSON_UINT64_C2(0x80000000, 0));
754 EXPECT_EQ(i64, Pointer("/foo/int64").GetWithDefault(d, i64, a).GetInt64());
755 EXPECT_EQ(i64, Pointer("/foo/int64").GetWithDefault(d, i64 + 1, a).GetInt64());
756
757 const uint64_t u64 = RAPIDJSON_UINT64_C2(0xFFFFFFFFF, 0xFFFFFFFFF);
758 EXPECT_EQ(u64, Pointer("/foo/uint64").GetWithDefault(d, u64, a).GetUint64());
759 EXPECT_EQ(u64, Pointer("/foo/uint64").GetWithDefault(d, u64 - 1, a).GetUint64());
760
761 EXPECT_TRUE(Pointer("/foo/true").GetWithDefault(d, true, a).IsTrue());
762 EXPECT_TRUE(Pointer("/foo/true").GetWithDefault(d, false, a).IsTrue());
763
764 EXPECT_TRUE(Pointer("/foo/false").GetWithDefault(d, false, a).IsFalse());
765 EXPECT_TRUE(Pointer("/foo/false").GetWithDefault(d, true, a).IsFalse());
766
767 // StringRef version
768 EXPECT_STREQ("Hello", Pointer("/foo/hello").GetWithDefault(d, "Hello", a).GetString());
769
770 // Copy string version
771 {
772 char buffer[256];
773 strcpy(buffer, "World");
774 EXPECT_STREQ("World", Pointer("/foo/world").GetWithDefault(d, buffer, a).GetString());
775 memset(buffer, 0, sizeof(buffer));
776 }
777 EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString());
778
779 #if RAPIDJSON_HAS_STDSTRING
780 EXPECT_STREQ("C++", Pointer("/foo/C++").GetWithDefault(d, std::string("C++"), a).GetString());
781 #endif
782 }
783
784 TEST(Pointer, GetWithDefault_NoAllocator) {
785 Document d;
786 d.Parse(kJson);
787
788 // Value version
789 const Value v("qux");
790 EXPECT_TRUE(Value("bar") == Pointer("/foo/0").GetWithDefault(d, v));
791 EXPECT_TRUE(Value("baz") == Pointer("/foo/1").GetWithDefault(d, v));
792 EXPECT_TRUE(Value("qux") == Pointer("/foo/2").GetWithDefault(d, v));
793 EXPECT_TRUE(Value("last") == Pointer("/foo/-").GetWithDefault(d, Value("last").Move()));
794 EXPECT_STREQ("last", d["foo"][3].GetString());
795
796 EXPECT_TRUE(Pointer("/foo/null").GetWithDefault(d, Value().Move()).IsNull());
797 EXPECT_TRUE(Pointer("/foo/null").GetWithDefault(d, "x").IsNull());
798
799 // Generic version
800 EXPECT_EQ(-1, Pointer("/foo/int").GetWithDefault(d, -1).GetInt());
801 EXPECT_EQ(-1, Pointer("/foo/int").GetWithDefault(d, -2).GetInt());
802 EXPECT_EQ(0x87654321, Pointer("/foo/uint").GetWithDefault(d, 0x87654321).GetUint());
803 EXPECT_EQ(0x87654321, Pointer("/foo/uint").GetWithDefault(d, 0x12345678).GetUint());
804
805 const int64_t i64 = static_cast<int64_t>(RAPIDJSON_UINT64_C2(0x80000000, 0));
806 EXPECT_EQ(i64, Pointer("/foo/int64").GetWithDefault(d, i64).GetInt64());
807 EXPECT_EQ(i64, Pointer("/foo/int64").GetWithDefault(d, i64 + 1).GetInt64());
808
809 const uint64_t u64 = RAPIDJSON_UINT64_C2(0xFFFFFFFFF, 0xFFFFFFFFF);
810 EXPECT_EQ(u64, Pointer("/foo/uint64").GetWithDefault(d, u64).GetUint64());
811 EXPECT_EQ(u64, Pointer("/foo/uint64").GetWithDefault(d, u64 - 1).GetUint64());
812
813 EXPECT_TRUE(Pointer("/foo/true").GetWithDefault(d, true).IsTrue());
814 EXPECT_TRUE(Pointer("/foo/true").GetWithDefault(d, false).IsTrue());
815
816 EXPECT_TRUE(Pointer("/foo/false").GetWithDefault(d, false).IsFalse());
817 EXPECT_TRUE(Pointer("/foo/false").GetWithDefault(d, true).IsFalse());
818
819 // StringRef version
820 EXPECT_STREQ("Hello", Pointer("/foo/hello").GetWithDefault(d, "Hello").GetString());
821
822 // Copy string version
823 {
824 char buffer[256];
825 strcpy(buffer, "World");
826 EXPECT_STREQ("World", Pointer("/foo/world").GetWithDefault(d, buffer).GetString());
827 memset(buffer, 0, sizeof(buffer));
828 }
829 EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString());
830
831 #if RAPIDJSON_HAS_STDSTRING
832 EXPECT_STREQ("C++", Pointer("/foo/C++").GetWithDefault(d, std::string("C++")).GetString());
833 #endif
834 }
835
836 TEST(Pointer, Set) {
837 Document d;
838 d.Parse(kJson);
839 Document::AllocatorType& a = d.GetAllocator();
840
841 // Value version
842 Pointer("/foo/0").Set(d, Value(123).Move(), a);
843 EXPECT_EQ(123, d["foo"][0].GetInt());
844
845 Pointer("/foo/-").Set(d, Value(456).Move(), a);
846 EXPECT_EQ(456, d["foo"][2].GetInt());
847
848 Pointer("/foo/null").Set(d, Value().Move(), a);
849 EXPECT_TRUE(GetValueByPointer(d, "/foo/null")->IsNull());
850
851 // Const Value version
852 const Value foo(d["foo"], a);
853 Pointer("/clone").Set(d, foo, a);
854 EXPECT_EQ(foo, *GetValueByPointer(d, "/clone"));
855
856 // Generic version
857 Pointer("/foo/int").Set(d, -1, a);
858 EXPECT_EQ(-1, GetValueByPointer(d, "/foo/int")->GetInt());
859
860 Pointer("/foo/uint").Set(d, 0x87654321, a);
861 EXPECT_EQ(0x87654321, GetValueByPointer(d, "/foo/uint")->GetUint());
862
863 const int64_t i64 = static_cast<int64_t>(RAPIDJSON_UINT64_C2(0x80000000, 0));
864 Pointer("/foo/int64").Set(d, i64, a);
865 EXPECT_EQ(i64, GetValueByPointer(d, "/foo/int64")->GetInt64());
866
867 const uint64_t u64 = RAPIDJSON_UINT64_C2(0xFFFFFFFFF, 0xFFFFFFFFF);
868 Pointer("/foo/uint64").Set(d, u64, a);
869 EXPECT_EQ(u64, GetValueByPointer(d, "/foo/uint64")->GetUint64());
870
871 Pointer("/foo/true").Set(d, true, a);
872 EXPECT_TRUE(GetValueByPointer(d, "/foo/true")->IsTrue());
873
874 Pointer("/foo/false").Set(d, false, a);
875 EXPECT_TRUE(GetValueByPointer(d, "/foo/false")->IsFalse());
876
877 // StringRef version
878 Pointer("/foo/hello").Set(d, "Hello", a);
879 EXPECT_STREQ("Hello", GetValueByPointer(d, "/foo/hello")->GetString());
880
881 // Copy string version
882 {
883 char buffer[256];
884 strcpy(buffer, "World");
885 Pointer("/foo/world").Set(d, buffer, a);
886 memset(buffer, 0, sizeof(buffer));
887 }
888 EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString());
889
890 #if RAPIDJSON_HAS_STDSTRING
891 Pointer("/foo/c++").Set(d, std::string("C++"), a);
892 EXPECT_STREQ("C++", GetValueByPointer(d, "/foo/c++")->GetString());
893 #endif
894 }
895
896 TEST(Pointer, Set_NoAllocator) {
897 Document d;
898 d.Parse(kJson);
899
900 // Value version
901 Pointer("/foo/0").Set(d, Value(123).Move());
902 EXPECT_EQ(123, d["foo"][0].GetInt());
903
904 Pointer("/foo/-").Set(d, Value(456).Move());
905 EXPECT_EQ(456, d["foo"][2].GetInt());
906
907 Pointer("/foo/null").Set(d, Value().Move());
908 EXPECT_TRUE(GetValueByPointer(d, "/foo/null")->IsNull());
909
910 // Const Value version
911 const Value foo(d["foo"], d.GetAllocator());
912 Pointer("/clone").Set(d, foo);
913 EXPECT_EQ(foo, *GetValueByPointer(d, "/clone"));
914
915 // Generic version
916 Pointer("/foo/int").Set(d, -1);
917 EXPECT_EQ(-1, GetValueByPointer(d, "/foo/int")->GetInt());
918
919 Pointer("/foo/uint").Set(d, 0x87654321);
920 EXPECT_EQ(0x87654321, GetValueByPointer(d, "/foo/uint")->GetUint());
921
922 const int64_t i64 = static_cast<int64_t>(RAPIDJSON_UINT64_C2(0x80000000, 0));
923 Pointer("/foo/int64").Set(d, i64);
924 EXPECT_EQ(i64, GetValueByPointer(d, "/foo/int64")->GetInt64());
925
926 const uint64_t u64 = RAPIDJSON_UINT64_C2(0xFFFFFFFFF, 0xFFFFFFFFF);
927 Pointer("/foo/uint64").Set(d, u64);
928 EXPECT_EQ(u64, GetValueByPointer(d, "/foo/uint64")->GetUint64());
929
930 Pointer("/foo/true").Set(d, true);
931 EXPECT_TRUE(GetValueByPointer(d, "/foo/true")->IsTrue());
932
933 Pointer("/foo/false").Set(d, false);
934 EXPECT_TRUE(GetValueByPointer(d, "/foo/false")->IsFalse());
935
936 // StringRef version
937 Pointer("/foo/hello").Set(d, "Hello");
938 EXPECT_STREQ("Hello", GetValueByPointer(d, "/foo/hello")->GetString());
939
940 // Copy string version
941 {
942 char buffer[256];
943 strcpy(buffer, "World");
944 Pointer("/foo/world").Set(d, buffer);
945 memset(buffer, 0, sizeof(buffer));
946 }
947 EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString());
948
949 #if RAPIDJSON_HAS_STDSTRING
950 Pointer("/foo/c++").Set(d, std::string("C++"));
951 EXPECT_STREQ("C++", GetValueByPointer(d, "/foo/c++")->GetString());
952 #endif
953 }
954
955 TEST(Pointer, Swap_Value) {
956 Document d;
957 d.Parse(kJson);
958 Document::AllocatorType& a = d.GetAllocator();
959 Pointer("/foo/0").Swap(d, *Pointer("/foo/1").Get(d), a);
960 EXPECT_STREQ("baz", d["foo"][0].GetString());
961 EXPECT_STREQ("bar", d["foo"][1].GetString());
962 }
963
964 TEST(Pointer, Swap_Value_NoAllocator) {
965 Document d;
966 d.Parse(kJson);
967 Pointer("/foo/0").Swap(d, *Pointer("/foo/1").Get(d));
968 EXPECT_STREQ("baz", d["foo"][0].GetString());
969 EXPECT_STREQ("bar", d["foo"][1].GetString());
970 }
971
972 TEST(Pointer, Erase) {
973 Document d;
974 d.Parse(kJson);
975
976 EXPECT_FALSE(Pointer("").Erase(d));
977 EXPECT_FALSE(Pointer("/nonexist").Erase(d));
978 EXPECT_FALSE(Pointer("/nonexist/nonexist").Erase(d));
979 EXPECT_FALSE(Pointer("/foo/nonexist").Erase(d));
980 EXPECT_FALSE(Pointer("/foo/nonexist/nonexist").Erase(d));
981 EXPECT_FALSE(Pointer("/foo/0/nonexist").Erase(d));
982 EXPECT_FALSE(Pointer("/foo/0/nonexist/nonexist").Erase(d));
983 EXPECT_FALSE(Pointer("/foo/2/nonexist").Erase(d));
984 EXPECT_TRUE(Pointer("/foo/0").Erase(d));
985 EXPECT_EQ(1u, d["foo"].Size());
986 EXPECT_STREQ("baz", d["foo"][0].GetString());
987 EXPECT_TRUE(Pointer("/foo/0").Erase(d));
988 EXPECT_TRUE(d["foo"].Empty());
989 EXPECT_TRUE(Pointer("/foo").Erase(d));
990 EXPECT_TRUE(Pointer("/foo").Get(d) == 0);
991
992 Pointer("/a/0/b/0").Create(d);
993
994 EXPECT_TRUE(Pointer("/a/0/b/0").Get(d) != 0);
995 EXPECT_TRUE(Pointer("/a/0/b/0").Erase(d));
996 EXPECT_TRUE(Pointer("/a/0/b/0").Get(d) == 0);
997
998 EXPECT_TRUE(Pointer("/a/0/b").Get(d) != 0);
999 EXPECT_TRUE(Pointer("/a/0/b").Erase(d));
1000 EXPECT_TRUE(Pointer("/a/0/b").Get(d) == 0);
1001
1002 EXPECT_TRUE(Pointer("/a/0").Get(d) != 0);
1003 EXPECT_TRUE(Pointer("/a/0").Erase(d));
1004 EXPECT_TRUE(Pointer("/a/0").Get(d) == 0);
1005
1006 EXPECT_TRUE(Pointer("/a").Get(d) != 0);
1007 EXPECT_TRUE(Pointer("/a").Erase(d));
1008 EXPECT_TRUE(Pointer("/a").Get(d) == 0);
1009 }
1010
1011 TEST(Pointer, CreateValueByPointer) {
1012 Document d;
1013 Document::AllocatorType& a = d.GetAllocator();
1014
1015 {
1016 Value& v = CreateValueByPointer(d, Pointer("/foo/0"), a);
1017 EXPECT_EQ(&d["foo"][0], &v);
1018 }
1019 {
1020 Value& v = CreateValueByPointer(d, "/foo/1", a);
1021 EXPECT_EQ(&d["foo"][1], &v);
1022 }
1023 }
1024
1025 TEST(Pointer, CreateValueByPointer_NoAllocator) {
1026 Document d;
1027
1028 {
1029 Value& v = CreateValueByPointer(d, Pointer("/foo/0"));
1030 EXPECT_EQ(&d["foo"][0], &v);
1031 }
1032 {
1033 Value& v = CreateValueByPointer(d, "/foo/1");
1034 EXPECT_EQ(&d["foo"][1], &v);
1035 }
1036 }
1037
1038 TEST(Pointer, GetValueByPointer) {
1039 Document d;
1040 d.Parse(kJson);
1041
1042 EXPECT_EQ(&d["foo"][0], GetValueByPointer(d, Pointer("/foo/0")));
1043 EXPECT_EQ(&d["foo"][0], GetValueByPointer(d, "/foo/0"));
1044
1045 size_t unresolvedTokenIndex;
1046 EXPECT_TRUE(GetValueByPointer(d, "/foo/2", &unresolvedTokenIndex) == 0); // Out of boundary
1047 EXPECT_EQ(1u, unresolvedTokenIndex);
1048 EXPECT_TRUE(GetValueByPointer(d, "/foo/a", &unresolvedTokenIndex) == 0); // "/foo" is an array, cannot query by "a"
1049 EXPECT_EQ(1u, unresolvedTokenIndex);
1050 EXPECT_TRUE(GetValueByPointer(d, "/foo/0/0", &unresolvedTokenIndex) == 0); // "/foo/0" is an string, cannot further query
1051 EXPECT_EQ(2u, unresolvedTokenIndex);
1052 EXPECT_TRUE(GetValueByPointer(d, "/foo/0/a", &unresolvedTokenIndex) == 0); // "/foo/0" is an string, cannot further query
1053 EXPECT_EQ(2u, unresolvedTokenIndex);
1054
1055 // const version
1056 const Value& v = d;
1057 EXPECT_EQ(&d["foo"][0], GetValueByPointer(v, Pointer("/foo/0")));
1058 EXPECT_EQ(&d["foo"][0], GetValueByPointer(v, "/foo/0"));
1059
1060 EXPECT_TRUE(GetValueByPointer(v, "/foo/2", &unresolvedTokenIndex) == 0); // Out of boundary
1061 EXPECT_EQ(1u, unresolvedTokenIndex);
1062 EXPECT_TRUE(GetValueByPointer(v, "/foo/a", &unresolvedTokenIndex) == 0); // "/foo" is an array, cannot query by "a"
1063 EXPECT_EQ(1u, unresolvedTokenIndex);
1064 EXPECT_TRUE(GetValueByPointer(v, "/foo/0/0", &unresolvedTokenIndex) == 0); // "/foo/0" is an string, cannot further query
1065 EXPECT_EQ(2u, unresolvedTokenIndex);
1066 EXPECT_TRUE(GetValueByPointer(v, "/foo/0/a", &unresolvedTokenIndex) == 0); // "/foo/0" is an string, cannot further query
1067 EXPECT_EQ(2u, unresolvedTokenIndex);
1068
1069 }
1070
1071 TEST(Pointer, GetValueByPointerWithDefault_Pointer) {
1072 Document d;
1073 d.Parse(kJson);
1074
1075 Document::AllocatorType& a = d.GetAllocator();
1076 const Value v("qux");
1077 EXPECT_TRUE(Value("bar") == GetValueByPointerWithDefault(d, Pointer("/foo/0"), v, a));
1078 EXPECT_TRUE(Value("bar") == GetValueByPointerWithDefault(d, Pointer("/foo/0"), v, a));
1079 EXPECT_TRUE(Value("baz") == GetValueByPointerWithDefault(d, Pointer("/foo/1"), v, a));
1080 EXPECT_TRUE(Value("qux") == GetValueByPointerWithDefault(d, Pointer("/foo/2"), v, a));
1081 EXPECT_TRUE(Value("last") == GetValueByPointerWithDefault(d, Pointer("/foo/-"), Value("last").Move(), a));
1082 EXPECT_STREQ("last", d["foo"][3].GetString());
1083
1084 EXPECT_TRUE(GetValueByPointerWithDefault(d, Pointer("/foo/null"), Value().Move(), a).IsNull());
1085 EXPECT_TRUE(GetValueByPointerWithDefault(d, Pointer("/foo/null"), "x", a).IsNull());
1086
1087 // Generic version
1088 EXPECT_EQ(-1, GetValueByPointerWithDefault(d, Pointer("/foo/int"), -1, a).GetInt());
1089 EXPECT_EQ(-1, GetValueByPointerWithDefault(d, Pointer("/foo/int"), -2, a).GetInt());
1090 EXPECT_EQ(0x87654321, GetValueByPointerWithDefault(d, Pointer("/foo/uint"), 0x87654321, a).GetUint());
1091 EXPECT_EQ(0x87654321, GetValueByPointerWithDefault(d, Pointer("/foo/uint"), 0x12345678, a).GetUint());
1092
1093 const int64_t i64 = static_cast<int64_t>(RAPIDJSON_UINT64_C2(0x80000000, 0));
1094 EXPECT_EQ(i64, GetValueByPointerWithDefault(d, Pointer("/foo/int64"), i64, a).GetInt64());
1095 EXPECT_EQ(i64, GetValueByPointerWithDefault(d, Pointer("/foo/int64"), i64 + 1, a).GetInt64());
1096
1097 const uint64_t u64 = RAPIDJSON_UINT64_C2(0xFFFFFFFFF, 0xFFFFFFFFF);
1098 EXPECT_EQ(u64, GetValueByPointerWithDefault(d, Pointer("/foo/uint64"), u64, a).GetUint64());
1099 EXPECT_EQ(u64, GetValueByPointerWithDefault(d, Pointer("/foo/uint64"), u64 - 1, a).GetUint64());
1100
1101 EXPECT_TRUE(GetValueByPointerWithDefault(d, Pointer("/foo/true"), true, a).IsTrue());
1102 EXPECT_TRUE(GetValueByPointerWithDefault(d, Pointer("/foo/true"), false, a).IsTrue());
1103
1104 EXPECT_TRUE(GetValueByPointerWithDefault(d, Pointer("/foo/false"), false, a).IsFalse());
1105 EXPECT_TRUE(GetValueByPointerWithDefault(d, Pointer("/foo/false"), true, a).IsFalse());
1106
1107 // StringRef version
1108 EXPECT_STREQ("Hello", GetValueByPointerWithDefault(d, Pointer("/foo/hello"), "Hello", a).GetString());
1109
1110 // Copy string version
1111 {
1112 char buffer[256];
1113 strcpy(buffer, "World");
1114 EXPECT_STREQ("World", GetValueByPointerWithDefault(d, Pointer("/foo/world"), buffer, a).GetString());
1115 memset(buffer, 0, sizeof(buffer));
1116 }
1117 EXPECT_STREQ("World", GetValueByPointer(d, Pointer("/foo/world"))->GetString());
1118
1119 #if RAPIDJSON_HAS_STDSTRING
1120 EXPECT_STREQ("C++", GetValueByPointerWithDefault(d, Pointer("/foo/C++"), std::string("C++"), a).GetString());
1121 #endif
1122 }
1123
1124 TEST(Pointer, GetValueByPointerWithDefault_String) {
1125 Document d;
1126 d.Parse(kJson);
1127
1128 Document::AllocatorType& a = d.GetAllocator();
1129 const Value v("qux");
1130 EXPECT_TRUE(Value("bar") == GetValueByPointerWithDefault(d, "/foo/0", v, a));
1131 EXPECT_TRUE(Value("bar") == GetValueByPointerWithDefault(d, "/foo/0", v, a));
1132 EXPECT_TRUE(Value("baz") == GetValueByPointerWithDefault(d, "/foo/1", v, a));
1133 EXPECT_TRUE(Value("qux") == GetValueByPointerWithDefault(d, "/foo/2", v, a));
1134 EXPECT_TRUE(Value("last") == GetValueByPointerWithDefault(d, "/foo/-", Value("last").Move(), a));
1135 EXPECT_STREQ("last", d["foo"][3].GetString());
1136
1137 EXPECT_TRUE(GetValueByPointerWithDefault(d, "/foo/null", Value().Move(), a).IsNull());
1138 EXPECT_TRUE(GetValueByPointerWithDefault(d, "/foo/null", "x", a).IsNull());
1139
1140 // Generic version
1141 EXPECT_EQ(-1, GetValueByPointerWithDefault(d, "/foo/int", -1, a).GetInt());
1142 EXPECT_EQ(-1, GetValueByPointerWithDefault(d, "/foo/int", -2, a).GetInt());
1143 EXPECT_EQ(0x87654321, GetValueByPointerWithDefault(d, "/foo/uint", 0x87654321, a).GetUint());
1144 EXPECT_EQ(0x87654321, GetValueByPointerWithDefault(d, "/foo/uint", 0x12345678, a).GetUint());
1145
1146 const int64_t i64 = static_cast<int64_t>(RAPIDJSON_UINT64_C2(0x80000000, 0));
1147 EXPECT_EQ(i64, GetValueByPointerWithDefault(d, "/foo/int64", i64, a).GetInt64());
1148 EXPECT_EQ(i64, GetValueByPointerWithDefault(d, "/foo/int64", i64 + 1, a).GetInt64());
1149
1150 const uint64_t u64 = RAPIDJSON_UINT64_C2(0xFFFFFFFFF, 0xFFFFFFFFF);
1151 EXPECT_EQ(u64, GetValueByPointerWithDefault(d, "/foo/uint64", u64, a).GetUint64());
1152 EXPECT_EQ(u64, GetValueByPointerWithDefault(d, "/foo/uint64", u64 - 1, a).GetUint64());
1153
1154 EXPECT_TRUE(GetValueByPointerWithDefault(d, "/foo/true", true, a).IsTrue());
1155 EXPECT_TRUE(GetValueByPointerWithDefault(d, "/foo/true", false, a).IsTrue());
1156
1157 EXPECT_TRUE(GetValueByPointerWithDefault(d, "/foo/false", false, a).IsFalse());
1158 EXPECT_TRUE(GetValueByPointerWithDefault(d, "/foo/false", true, a).IsFalse());
1159
1160 // StringRef version
1161 EXPECT_STREQ("Hello", GetValueByPointerWithDefault(d, "/foo/hello", "Hello", a).GetString());
1162
1163 // Copy string version
1164 {
1165 char buffer[256];
1166 strcpy(buffer, "World");
1167 EXPECT_STREQ("World", GetValueByPointerWithDefault(d, "/foo/world", buffer, a).GetString());
1168 memset(buffer, 0, sizeof(buffer));
1169 }
1170 EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString());
1171
1172 #if RAPIDJSON_HAS_STDSTRING
1173 EXPECT_STREQ("C++", GetValueByPointerWithDefault(d, "/foo/C++", std::string("C++"), a).GetString());
1174 #endif
1175 }
1176
1177 TEST(Pointer, GetValueByPointerWithDefault_Pointer_NoAllocator) {
1178 Document d;
1179 d.Parse(kJson);
1180
1181 const Value v("qux");
1182 EXPECT_TRUE(Value("bar") == GetValueByPointerWithDefault(d, Pointer("/foo/0"), v));
1183 EXPECT_TRUE(Value("bar") == GetValueByPointerWithDefault(d, Pointer("/foo/0"), v));
1184 EXPECT_TRUE(Value("baz") == GetValueByPointerWithDefault(d, Pointer("/foo/1"), v));
1185 EXPECT_TRUE(Value("qux") == GetValueByPointerWithDefault(d, Pointer("/foo/2"), v));
1186 EXPECT_TRUE(Value("last") == GetValueByPointerWithDefault(d, Pointer("/foo/-"), Value("last").Move()));
1187 EXPECT_STREQ("last", d["foo"][3].GetString());
1188
1189 EXPECT_TRUE(GetValueByPointerWithDefault(d, Pointer("/foo/null"), Value().Move()).IsNull());
1190 EXPECT_TRUE(GetValueByPointerWithDefault(d, Pointer("/foo/null"), "x").IsNull());
1191
1192 // Generic version
1193 EXPECT_EQ(-1, GetValueByPointerWithDefault(d, Pointer("/foo/int"), -1).GetInt());
1194 EXPECT_EQ(-1, GetValueByPointerWithDefault(d, Pointer("/foo/int"), -2).GetInt());
1195 EXPECT_EQ(0x87654321, GetValueByPointerWithDefault(d, Pointer("/foo/uint"), 0x87654321).GetUint());
1196 EXPECT_EQ(0x87654321, GetValueByPointerWithDefault(d, Pointer("/foo/uint"), 0x12345678).GetUint());
1197
1198 const int64_t i64 = static_cast<int64_t>(RAPIDJSON_UINT64_C2(0x80000000, 0));
1199 EXPECT_EQ(i64, GetValueByPointerWithDefault(d, Pointer("/foo/int64"), i64).GetInt64());
1200 EXPECT_EQ(i64, GetValueByPointerWithDefault(d, Pointer("/foo/int64"), i64 + 1).GetInt64());
1201
1202 const uint64_t u64 = RAPIDJSON_UINT64_C2(0xFFFFFFFFF, 0xFFFFFFFFF);
1203 EXPECT_EQ(u64, GetValueByPointerWithDefault(d, Pointer("/foo/uint64"), u64).GetUint64());
1204 EXPECT_EQ(u64, GetValueByPointerWithDefault(d, Pointer("/foo/uint64"), u64 - 1).GetUint64());
1205
1206 EXPECT_TRUE(GetValueByPointerWithDefault(d, Pointer("/foo/true"), true).IsTrue());
1207 EXPECT_TRUE(GetValueByPointerWithDefault(d, Pointer("/foo/true"), false).IsTrue());
1208
1209 EXPECT_TRUE(GetValueByPointerWithDefault(d, Pointer("/foo/false"), false).IsFalse());
1210 EXPECT_TRUE(GetValueByPointerWithDefault(d, Pointer("/foo/false"), true).IsFalse());
1211
1212 // StringRef version
1213 EXPECT_STREQ("Hello", GetValueByPointerWithDefault(d, Pointer("/foo/hello"), "Hello").GetString());
1214
1215 // Copy string version
1216 {
1217 char buffer[256];
1218 strcpy(buffer, "World");
1219 EXPECT_STREQ("World", GetValueByPointerWithDefault(d, Pointer("/foo/world"), buffer).GetString());
1220 memset(buffer, 0, sizeof(buffer));
1221 }
1222 EXPECT_STREQ("World", GetValueByPointer(d, Pointer("/foo/world"))->GetString());
1223
1224 #if RAPIDJSON_HAS_STDSTRING
1225 EXPECT_STREQ("C++", GetValueByPointerWithDefault(d, Pointer("/foo/C++"), std::string("C++")).GetString());
1226 #endif
1227 }
1228
1229 TEST(Pointer, GetValueByPointerWithDefault_String_NoAllocator) {
1230 Document d;
1231 d.Parse(kJson);
1232
1233 const Value v("qux");
1234 EXPECT_TRUE(Value("bar") == GetValueByPointerWithDefault(d, "/foo/0", v));
1235 EXPECT_TRUE(Value("bar") == GetValueByPointerWithDefault(d, "/foo/0", v));
1236 EXPECT_TRUE(Value("baz") == GetValueByPointerWithDefault(d, "/foo/1", v));
1237 EXPECT_TRUE(Value("qux") == GetValueByPointerWithDefault(d, "/foo/2", v));
1238 EXPECT_TRUE(Value("last") == GetValueByPointerWithDefault(d, "/foo/-", Value("last").Move()));
1239 EXPECT_STREQ("last", d["foo"][3].GetString());
1240
1241 EXPECT_TRUE(GetValueByPointerWithDefault(d, "/foo/null", Value().Move()).IsNull());
1242 EXPECT_TRUE(GetValueByPointerWithDefault(d, "/foo/null", "x").IsNull());
1243
1244 // Generic version
1245 EXPECT_EQ(-1, GetValueByPointerWithDefault(d, "/foo/int", -1).GetInt());
1246 EXPECT_EQ(-1, GetValueByPointerWithDefault(d, "/foo/int", -2).GetInt());
1247 EXPECT_EQ(0x87654321, GetValueByPointerWithDefault(d, "/foo/uint", 0x87654321).GetUint());
1248 EXPECT_EQ(0x87654321, GetValueByPointerWithDefault(d, "/foo/uint", 0x12345678).GetUint());
1249
1250 const int64_t i64 = static_cast<int64_t>(RAPIDJSON_UINT64_C2(0x80000000, 0));
1251 EXPECT_EQ(i64, GetValueByPointerWithDefault(d, "/foo/int64", i64).GetInt64());
1252 EXPECT_EQ(i64, GetValueByPointerWithDefault(d, "/foo/int64", i64 + 1).GetInt64());
1253
1254 const uint64_t u64 = RAPIDJSON_UINT64_C2(0xFFFFFFFFF, 0xFFFFFFFFF);
1255 EXPECT_EQ(u64, GetValueByPointerWithDefault(d, "/foo/uint64", u64).GetUint64());
1256 EXPECT_EQ(u64, GetValueByPointerWithDefault(d, "/foo/uint64", u64 - 1).GetUint64());
1257
1258 EXPECT_TRUE(GetValueByPointerWithDefault(d, "/foo/true", true).IsTrue());
1259 EXPECT_TRUE(GetValueByPointerWithDefault(d, "/foo/true", false).IsTrue());
1260
1261 EXPECT_TRUE(GetValueByPointerWithDefault(d, "/foo/false", false).IsFalse());
1262 EXPECT_TRUE(GetValueByPointerWithDefault(d, "/foo/false", true).IsFalse());
1263
1264 // StringRef version
1265 EXPECT_STREQ("Hello", GetValueByPointerWithDefault(d, "/foo/hello", "Hello").GetString());
1266
1267 // Copy string version
1268 {
1269 char buffer[256];
1270 strcpy(buffer, "World");
1271 EXPECT_STREQ("World", GetValueByPointerWithDefault(d, "/foo/world", buffer).GetString());
1272 memset(buffer, 0, sizeof(buffer));
1273 }
1274 EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString());
1275
1276 #if RAPIDJSON_HAS_STDSTRING
1277 EXPECT_STREQ("C++", GetValueByPointerWithDefault(d, Pointer("/foo/C++"), std::string("C++")).GetString());
1278 #endif
1279 }
1280
1281 TEST(Pointer, SetValueByPointer_Pointer) {
1282 Document d;
1283 d.Parse(kJson);
1284 Document::AllocatorType& a = d.GetAllocator();
1285
1286 // Value version
1287 SetValueByPointer(d, Pointer("/foo/0"), Value(123).Move(), a);
1288 EXPECT_EQ(123, d["foo"][0].GetInt());
1289
1290 SetValueByPointer(d, Pointer("/foo/null"), Value().Move(), a);
1291 EXPECT_TRUE(GetValueByPointer(d, "/foo/null")->IsNull());
1292
1293 // Const Value version
1294 const Value foo(d["foo"], d.GetAllocator());
1295 SetValueByPointer(d, Pointer("/clone"), foo, a);
1296 EXPECT_EQ(foo, *GetValueByPointer(d, "/clone"));
1297
1298 // Generic version
1299 SetValueByPointer(d, Pointer("/foo/int"), -1, a);
1300 EXPECT_EQ(-1, GetValueByPointer(d, "/foo/int")->GetInt());
1301
1302 SetValueByPointer(d, Pointer("/foo/uint"), 0x87654321, a);
1303 EXPECT_EQ(0x87654321, GetValueByPointer(d, "/foo/uint")->GetUint());
1304
1305 const int64_t i64 = static_cast<int64_t>(RAPIDJSON_UINT64_C2(0x80000000, 0));
1306 SetValueByPointer(d, Pointer("/foo/int64"), i64, a);
1307 EXPECT_EQ(i64, GetValueByPointer(d, "/foo/int64")->GetInt64());
1308
1309 const uint64_t u64 = RAPIDJSON_UINT64_C2(0xFFFFFFFFF, 0xFFFFFFFFF);
1310 SetValueByPointer(d, Pointer("/foo/uint64"), u64, a);
1311 EXPECT_EQ(u64, GetValueByPointer(d, "/foo/uint64")->GetUint64());
1312
1313 SetValueByPointer(d, Pointer("/foo/true"), true, a);
1314 EXPECT_TRUE(GetValueByPointer(d, "/foo/true")->IsTrue());
1315
1316 SetValueByPointer(d, Pointer("/foo/false"), false, a);
1317 EXPECT_TRUE(GetValueByPointer(d, "/foo/false")->IsFalse());
1318
1319 // StringRef version
1320 SetValueByPointer(d, Pointer("/foo/hello"), "Hello", a);
1321 EXPECT_STREQ("Hello", GetValueByPointer(d, "/foo/hello")->GetString());
1322
1323 // Copy string version
1324 {
1325 char buffer[256];
1326 strcpy(buffer, "World");
1327 SetValueByPointer(d, Pointer("/foo/world"), buffer, a);
1328 memset(buffer, 0, sizeof(buffer));
1329 }
1330 EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString());
1331
1332 #if RAPIDJSON_HAS_STDSTRING
1333 SetValueByPointer(d, Pointer("/foo/c++"), std::string("C++"), a);
1334 EXPECT_STREQ("C++", GetValueByPointer(d, "/foo/c++")->GetString());
1335 #endif
1336 }
1337
1338 TEST(Pointer, SetValueByPointer_String) {
1339 Document d;
1340 d.Parse(kJson);
1341 Document::AllocatorType& a = d.GetAllocator();
1342
1343 // Value version
1344 SetValueByPointer(d, "/foo/0", Value(123).Move(), a);
1345 EXPECT_EQ(123, d["foo"][0].GetInt());
1346
1347 SetValueByPointer(d, "/foo/null", Value().Move(), a);
1348 EXPECT_TRUE(GetValueByPointer(d, "/foo/null")->IsNull());
1349
1350 // Const Value version
1351 const Value foo(d["foo"], d.GetAllocator());
1352 SetValueByPointer(d, "/clone", foo, a);
1353 EXPECT_EQ(foo, *GetValueByPointer(d, "/clone"));
1354
1355 // Generic version
1356 SetValueByPointer(d, "/foo/int", -1, a);
1357 EXPECT_EQ(-1, GetValueByPointer(d, "/foo/int")->GetInt());
1358
1359 SetValueByPointer(d, "/foo/uint", 0x87654321, a);
1360 EXPECT_EQ(0x87654321, GetValueByPointer(d, "/foo/uint")->GetUint());
1361
1362 const int64_t i64 = static_cast<int64_t>(RAPIDJSON_UINT64_C2(0x80000000, 0));
1363 SetValueByPointer(d, "/foo/int64", i64, a);
1364 EXPECT_EQ(i64, GetValueByPointer(d, "/foo/int64")->GetInt64());
1365
1366 const uint64_t u64 = RAPIDJSON_UINT64_C2(0xFFFFFFFFF, 0xFFFFFFFFF);
1367 SetValueByPointer(d, "/foo/uint64", u64, a);
1368 EXPECT_EQ(u64, GetValueByPointer(d, "/foo/uint64")->GetUint64());
1369
1370 SetValueByPointer(d, "/foo/true", true, a);
1371 EXPECT_TRUE(GetValueByPointer(d, "/foo/true")->IsTrue());
1372
1373 SetValueByPointer(d, "/foo/false", false, a);
1374 EXPECT_TRUE(GetValueByPointer(d, "/foo/false")->IsFalse());
1375
1376 // StringRef version
1377 SetValueByPointer(d, "/foo/hello", "Hello", a);
1378 EXPECT_STREQ("Hello", GetValueByPointer(d, "/foo/hello")->GetString());
1379
1380 // Copy string version
1381 {
1382 char buffer[256];
1383 strcpy(buffer, "World");
1384 SetValueByPointer(d, "/foo/world", buffer, a);
1385 memset(buffer, 0, sizeof(buffer));
1386 }
1387 EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString());
1388
1389 #if RAPIDJSON_HAS_STDSTRING
1390 SetValueByPointer(d, "/foo/c++", std::string("C++"), a);
1391 EXPECT_STREQ("C++", GetValueByPointer(d, "/foo/c++")->GetString());
1392 #endif
1393 }
1394
1395 TEST(Pointer, SetValueByPointer_Pointer_NoAllocator) {
1396 Document d;
1397 d.Parse(kJson);
1398
1399 // Value version
1400 SetValueByPointer(d, Pointer("/foo/0"), Value(123).Move());
1401 EXPECT_EQ(123, d["foo"][0].GetInt());
1402
1403 SetValueByPointer(d, Pointer("/foo/null"), Value().Move());
1404 EXPECT_TRUE(GetValueByPointer(d, "/foo/null")->IsNull());
1405
1406 // Const Value version
1407 const Value foo(d["foo"], d.GetAllocator());
1408 SetValueByPointer(d, Pointer("/clone"), foo);
1409 EXPECT_EQ(foo, *GetValueByPointer(d, "/clone"));
1410
1411 // Generic version
1412 SetValueByPointer(d, Pointer("/foo/int"), -1);
1413 EXPECT_EQ(-1, GetValueByPointer(d, "/foo/int")->GetInt());
1414
1415 SetValueByPointer(d, Pointer("/foo/uint"), 0x87654321);
1416 EXPECT_EQ(0x87654321, GetValueByPointer(d, "/foo/uint")->GetUint());
1417
1418 const int64_t i64 = static_cast<int64_t>(RAPIDJSON_UINT64_C2(0x80000000, 0));
1419 SetValueByPointer(d, Pointer("/foo/int64"), i64);
1420 EXPECT_EQ(i64, GetValueByPointer(d, "/foo/int64")->GetInt64());
1421
1422 const uint64_t u64 = RAPIDJSON_UINT64_C2(0xFFFFFFFFF, 0xFFFFFFFFF);
1423 SetValueByPointer(d, Pointer("/foo/uint64"), u64);
1424 EXPECT_EQ(u64, GetValueByPointer(d, "/foo/uint64")->GetUint64());
1425
1426 SetValueByPointer(d, Pointer("/foo/true"), true);
1427 EXPECT_TRUE(GetValueByPointer(d, "/foo/true")->IsTrue());
1428
1429 SetValueByPointer(d, Pointer("/foo/false"), false);
1430 EXPECT_TRUE(GetValueByPointer(d, "/foo/false")->IsFalse());
1431
1432 // StringRef version
1433 SetValueByPointer(d, Pointer("/foo/hello"), "Hello");
1434 EXPECT_STREQ("Hello", GetValueByPointer(d, "/foo/hello")->GetString());
1435
1436 // Copy string version
1437 {
1438 char buffer[256];
1439 strcpy(buffer, "World");
1440 SetValueByPointer(d, Pointer("/foo/world"), buffer);
1441 memset(buffer, 0, sizeof(buffer));
1442 }
1443 EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString());
1444
1445 #if RAPIDJSON_HAS_STDSTRING
1446 SetValueByPointer(d, Pointer("/foo/c++"), std::string("C++"));
1447 EXPECT_STREQ("C++", GetValueByPointer(d, "/foo/c++")->GetString());
1448 #endif
1449 }
1450
1451 TEST(Pointer, SetValueByPointer_String_NoAllocator) {
1452 Document d;
1453 d.Parse(kJson);
1454
1455 // Value version
1456 SetValueByPointer(d, "/foo/0", Value(123).Move());
1457 EXPECT_EQ(123, d["foo"][0].GetInt());
1458
1459 SetValueByPointer(d, "/foo/null", Value().Move());
1460 EXPECT_TRUE(GetValueByPointer(d, "/foo/null")->IsNull());
1461
1462 // Const Value version
1463 const Value foo(d["foo"], d.GetAllocator());
1464 SetValueByPointer(d, "/clone", foo);
1465 EXPECT_EQ(foo, *GetValueByPointer(d, "/clone"));
1466
1467 // Generic version
1468 SetValueByPointer(d, "/foo/int", -1);
1469 EXPECT_EQ(-1, GetValueByPointer(d, "/foo/int")->GetInt());
1470
1471 SetValueByPointer(d, "/foo/uint", 0x87654321);
1472 EXPECT_EQ(0x87654321, GetValueByPointer(d, "/foo/uint")->GetUint());
1473
1474 const int64_t i64 = static_cast<int64_t>(RAPIDJSON_UINT64_C2(0x80000000, 0));
1475 SetValueByPointer(d, "/foo/int64", i64);
1476 EXPECT_EQ(i64, GetValueByPointer(d, "/foo/int64")->GetInt64());
1477
1478 const uint64_t u64 = RAPIDJSON_UINT64_C2(0xFFFFFFFFF, 0xFFFFFFFFF);
1479 SetValueByPointer(d, "/foo/uint64", u64);
1480 EXPECT_EQ(u64, GetValueByPointer(d, "/foo/uint64")->GetUint64());
1481
1482 SetValueByPointer(d, "/foo/true", true);
1483 EXPECT_TRUE(GetValueByPointer(d, "/foo/true")->IsTrue());
1484
1485 SetValueByPointer(d, "/foo/false", false);
1486 EXPECT_TRUE(GetValueByPointer(d, "/foo/false")->IsFalse());
1487
1488 // StringRef version
1489 SetValueByPointer(d, "/foo/hello", "Hello");
1490 EXPECT_STREQ("Hello", GetValueByPointer(d, "/foo/hello")->GetString());
1491
1492 // Copy string version
1493 {
1494 char buffer[256];
1495 strcpy(buffer, "World");
1496 SetValueByPointer(d, "/foo/world", buffer);
1497 memset(buffer, 0, sizeof(buffer));
1498 }
1499 EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString());
1500
1501 #if RAPIDJSON_HAS_STDSTRING
1502 SetValueByPointer(d, "/foo/c++", std::string("C++"));
1503 EXPECT_STREQ("C++", GetValueByPointer(d, "/foo/c++")->GetString());
1504 #endif
1505 }
1506
1507 TEST(Pointer, SwapValueByPointer) {
1508 Document d;
1509 d.Parse(kJson);
1510 Document::AllocatorType& a = d.GetAllocator();
1511 SwapValueByPointer(d, Pointer("/foo/0"), *GetValueByPointer(d, "/foo/1"), a);
1512 EXPECT_STREQ("baz", d["foo"][0].GetString());
1513 EXPECT_STREQ("bar", d["foo"][1].GetString());
1514
1515 SwapValueByPointer(d, "/foo/0", *GetValueByPointer(d, "/foo/1"), a);
1516 EXPECT_STREQ("bar", d["foo"][0].GetString());
1517 EXPECT_STREQ("baz", d["foo"][1].GetString());
1518 }
1519
1520 TEST(Pointer, SwapValueByPointer_NoAllocator) {
1521 Document d;
1522 d.Parse(kJson);
1523 SwapValueByPointer(d, Pointer("/foo/0"), *GetValueByPointer(d, "/foo/1"));
1524 EXPECT_STREQ("baz", d["foo"][0].GetString());
1525 EXPECT_STREQ("bar", d["foo"][1].GetString());
1526
1527 SwapValueByPointer(d, "/foo/0", *GetValueByPointer(d, "/foo/1"));
1528 EXPECT_STREQ("bar", d["foo"][0].GetString());
1529 EXPECT_STREQ("baz", d["foo"][1].GetString());
1530 }
1531
1532 TEST(Pointer, EraseValueByPointer_Pointer) {
1533 Document d;
1534 d.Parse(kJson);
1535
1536 EXPECT_FALSE(EraseValueByPointer(d, Pointer("")));
1537 EXPECT_FALSE(Pointer("/foo/nonexist").Erase(d));
1538 EXPECT_TRUE(EraseValueByPointer(d, Pointer("/foo/0")));
1539 EXPECT_EQ(1u, d["foo"].Size());
1540 EXPECT_STREQ("baz", d["foo"][0].GetString());
1541 EXPECT_TRUE(EraseValueByPointer(d, Pointer("/foo/0")));
1542 EXPECT_TRUE(d["foo"].Empty());
1543 EXPECT_TRUE(EraseValueByPointer(d, Pointer("/foo")));
1544 EXPECT_TRUE(Pointer("/foo").Get(d) == 0);
1545 }
1546
1547 TEST(Pointer, EraseValueByPointer_String) {
1548 Document d;
1549 d.Parse(kJson);
1550
1551 EXPECT_FALSE(EraseValueByPointer(d, ""));
1552 EXPECT_FALSE(Pointer("/foo/nonexist").Erase(d));
1553 EXPECT_TRUE(EraseValueByPointer(d, "/foo/0"));
1554 EXPECT_EQ(1u, d["foo"].Size());
1555 EXPECT_STREQ("baz", d["foo"][0].GetString());
1556 EXPECT_TRUE(EraseValueByPointer(d, "/foo/0"));
1557 EXPECT_TRUE(d["foo"].Empty());
1558 EXPECT_TRUE(EraseValueByPointer(d, "/foo"));
1559 EXPECT_TRUE(Pointer("/foo").Get(d) == 0);
1560 }
1561
1562 TEST(Pointer, Ambiguity) {
1563 {
1564 Document d;
1565 d.Parse("{\"0\" : [123]}");
1566 EXPECT_EQ(123, Pointer("/0/0").Get(d)->GetInt());
1567 Pointer("/0/a").Set(d, 456); // Change array [123] to object {456}
1568 EXPECT_EQ(456, Pointer("/0/a").Get(d)->GetInt());
1569 }
1570
1571 {
1572 Document d;
1573 EXPECT_FALSE(d.Parse("[{\"0\": 123}]").HasParseError());
1574 EXPECT_EQ(123, Pointer("/0/0").Get(d)->GetInt());
1575 Pointer("/0/1").Set(d, 456); // 1 is treated as "1" to index object
1576 EXPECT_EQ(123, Pointer("/0/0").Get(d)->GetInt());
1577 EXPECT_EQ(456, Pointer("/0/1").Get(d)->GetInt());
1578 }
1579 }
1580
1581 TEST(Pointer, ResolveOnObject) {
1582 Document d;
1583 EXPECT_FALSE(d.Parse("{\"a\": 123}").HasParseError());
1584
1585 {
1586 Value::ConstObject o = static_cast<const Document&>(d).GetObject();
1587 EXPECT_EQ(123, Pointer("/a").Get(o)->GetInt());
1588 }
1589
1590 {
1591 Value::Object o = d.GetObject();
1592 Pointer("/a").Set(o, 456, d.GetAllocator());
1593 EXPECT_EQ(456, Pointer("/a").Get(o)->GetInt());
1594 }
1595 }
1596
1597 TEST(Pointer, ResolveOnArray) {
1598 Document d;
1599 EXPECT_FALSE(d.Parse("[1, 2, 3]").HasParseError());
1600
1601 {
1602 Value::ConstArray a = static_cast<const Document&>(d).GetArray();
1603 EXPECT_EQ(2, Pointer("/1").Get(a)->GetInt());
1604 }
1605
1606 {
1607 Value::Array a = d.GetArray();
1608 Pointer("/1").Set(a, 123, d.GetAllocator());
1609 EXPECT_EQ(123, Pointer("/1").Get(a)->GetInt());
1610 }
1611 }
1612
1613 TEST(Pointer, LessThan) {
1614 static const struct {
1615 const char *str;
1616 bool valid;
1617 } pointers[] = {
1618 { "/a/b", true },
1619 { "/a", true },
1620 { "/d/1", true },
1621 { "/d/2/z", true },
1622 { "/d/2/3", true },
1623 { "/d/2", true },
1624 { "/a/c", true },
1625 { "/e/f~g", false },
1626 { "/d/2/zz", true },
1627 { "/d/1", true },
1628 { "/d/2/z", true },
1629 { "/e/f~~g", false },
1630 { "/e/f~0g", true },
1631 { "/e/f~1g", true },
1632 { "/e/f.g", true },
1633 { "", true }
1634 };
1635 static const char *ordered_pointers[] = {
1636 "",
1637 "/a",
1638 "/a/b",
1639 "/a/c",
1640 "/d/1",
1641 "/d/1",
1642 "/d/2",
1643 "/e/f.g",
1644 "/e/f~1g",
1645 "/e/f~0g",
1646 "/d/2/3",
1647 "/d/2/z",
1648 "/d/2/z",
1649 "/d/2/zz",
1650 NULL, // was invalid "/e/f~g"
1651 NULL // was invalid "/e/f~~g"
1652 };
1653 typedef MemoryPoolAllocator<> AllocatorType;
1654 typedef GenericPointer<Value, AllocatorType> PointerType;
1655 typedef std::multimap<PointerType, size_t> PointerMap;
1656 PointerMap map;
1657 PointerMap::iterator it;
1658 AllocatorType allocator;
1659 size_t i;
1660
1661 EXPECT_EQ(sizeof(pointers) / sizeof(pointers[0]),
1662 sizeof(ordered_pointers) / sizeof(ordered_pointers[0]));
1663
1664 for (i = 0; i < sizeof(pointers) / sizeof(pointers[0]); ++i) {
1665 it = map.insert(PointerMap::value_type(PointerType(pointers[i].str, &allocator), i));
1666 if (!it->first.IsValid()) {
1667 EXPECT_EQ(++it, map.end());
1668 }
1669 }
1670
1671 for (i = 0, it = map.begin(); it != map.end(); ++it, ++i) {
1672 EXPECT_TRUE(it->second < sizeof(pointers) / sizeof(pointers[0]));
1673 EXPECT_EQ(it->first.IsValid(), pointers[it->second].valid);
1674 EXPECT_TRUE(i < sizeof(ordered_pointers) / sizeof(ordered_pointers[0]));
1675 EXPECT_EQ(it->first.IsValid(), !!ordered_pointers[i]);
1676 if (it->first.IsValid()) {
1677 std::stringstream ss;
1678 OStreamWrapper os(ss);
1679 EXPECT_TRUE(it->first.Stringify(os));
1680 EXPECT_EQ(ss.str(), pointers[it->second].str);
1681 EXPECT_EQ(ss.str(), ordered_pointers[i]);
1682 }
1683 }
1684 }
1685
1686 // https://github.com/Tencent/rapidjson/issues/483
1687 namespace myjson {
1688
1689 class MyAllocator
1690 {
1691 public:
1692 static const bool kNeedFree = true;
1693 void * Malloc(size_t _size) { return malloc(_size); }
1694 void * Realloc(void *_org_p, size_t _org_size, size_t _new_size) { (void)_org_size; return realloc(_org_p, _new_size); }
1695 static void Free(void *_p) { return free(_p); }
1696 };
1697
1698 typedef rapidjson::GenericDocument<
1699 rapidjson::UTF8<>,
1700 rapidjson::MemoryPoolAllocator< MyAllocator >,
1701 MyAllocator
1702 > Document;
1703
1704 typedef rapidjson::GenericPointer<
1705 ::myjson::Document::ValueType,
1706 MyAllocator
1707 > Pointer;
1708
1709 typedef ::myjson::Document::ValueType Value;
1710
1711 }
1712
1713 TEST(Pointer, Issue483) {
1714 std::string mystr, path;
1715 myjson::Document document;
1716 myjson::Value value(rapidjson::kStringType);
1717 value.SetString(mystr.c_str(), static_cast<SizeType>(mystr.length()), document.GetAllocator());
1718 myjson::Pointer(path.c_str()).Set(document, value, document.GetAllocator());
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 }