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. All rights reserved.
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
TEST(Pointer,DefaultConstructor)38 TEST(Pointer, DefaultConstructor) {
39 Pointer p;
40 EXPECT_TRUE(p.IsValid());
41 EXPECT_EQ(0u, p.GetTokenCount());
42 }
43
TEST(Pointer,Parse)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
TEST(Pointer,Parse_URIFragment)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
TEST(Pointer,Stringify)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
TEST(Pointer,ConstructorWithToken)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
TEST(Pointer,CopyConstructor)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 EXPECT_EQ(&p.GetAllocator(), &q.GetAllocator());
479 }
480
481 // Static tokens
482 {
483 Pointer p(kTokens, sizeof(kTokens) / sizeof(kTokens[0]));
484 Pointer q(p);
485 EXPECT_TRUE(q.IsValid());
486 EXPECT_EQ(2u, q.GetTokenCount());
487 EXPECT_EQ(3u, q.GetTokens()[0].length);
488 EXPECT_STREQ("foo", q.GetTokens()[0].name);
489 EXPECT_EQ(1u, q.GetTokens()[1].length);
490 EXPECT_STREQ("0", q.GetTokens()[1].name);
491 EXPECT_EQ(0u, q.GetTokens()[1].index);
492 }
493 }
494
TEST(Pointer,Assignment)495 TEST(Pointer, Assignment) {
496 {
497 CrtAllocator allocator;
498 Pointer p("/foo/0", &allocator);
499 Pointer q;
500 q = p;
501 EXPECT_TRUE(q.IsValid());
502 EXPECT_EQ(2u, q.GetTokenCount());
503 EXPECT_EQ(3u, q.GetTokens()[0].length);
504 EXPECT_STREQ("foo", q.GetTokens()[0].name);
505 EXPECT_EQ(1u, q.GetTokens()[1].length);
506 EXPECT_STREQ("0", q.GetTokens()[1].name);
507 EXPECT_EQ(0u, q.GetTokens()[1].index);
508 EXPECT_NE(&p.GetAllocator(), &q.GetAllocator());
509 q = static_cast<const Pointer &>(q);
510 EXPECT_TRUE(q.IsValid());
511 EXPECT_EQ(2u, q.GetTokenCount());
512 EXPECT_EQ(3u, q.GetTokens()[0].length);
513 EXPECT_STREQ("foo", q.GetTokens()[0].name);
514 EXPECT_EQ(1u, q.GetTokens()[1].length);
515 EXPECT_STREQ("0", q.GetTokens()[1].name);
516 EXPECT_EQ(0u, q.GetTokens()[1].index);
517 EXPECT_NE(&p.GetAllocator(), &q.GetAllocator());
518 }
519
520 // Static tokens
521 {
522 Pointer p(kTokens, sizeof(kTokens) / sizeof(kTokens[0]));
523 Pointer q;
524 q = p;
525 EXPECT_TRUE(q.IsValid());
526 EXPECT_EQ(2u, q.GetTokenCount());
527 EXPECT_EQ(3u, q.GetTokens()[0].length);
528 EXPECT_STREQ("foo", q.GetTokens()[0].name);
529 EXPECT_EQ(1u, q.GetTokens()[1].length);
530 EXPECT_STREQ("0", q.GetTokens()[1].name);
531 EXPECT_EQ(0u, q.GetTokens()[1].index);
532 }
533 }
534
TEST(Pointer,Swap)535 TEST(Pointer, Swap) {
536 Pointer p("/foo/0");
537 Pointer q(&p.GetAllocator());
538
539 q.Swap(p);
540 EXPECT_EQ(&q.GetAllocator(), &p.GetAllocator());
541 EXPECT_TRUE(p.IsValid());
542 EXPECT_TRUE(q.IsValid());
543 EXPECT_EQ(0u, p.GetTokenCount());
544 EXPECT_EQ(2u, q.GetTokenCount());
545 EXPECT_EQ(3u, q.GetTokens()[0].length);
546 EXPECT_STREQ("foo", q.GetTokens()[0].name);
547 EXPECT_EQ(1u, q.GetTokens()[1].length);
548 EXPECT_STREQ("0", q.GetTokens()[1].name);
549 EXPECT_EQ(0u, q.GetTokens()[1].index);
550
551 // std::swap compatibility
552 std::swap(p, q);
553 EXPECT_EQ(&p.GetAllocator(), &q.GetAllocator());
554 EXPECT_TRUE(q.IsValid());
555 EXPECT_TRUE(p.IsValid());
556 EXPECT_EQ(0u, q.GetTokenCount());
557 EXPECT_EQ(2u, p.GetTokenCount());
558 EXPECT_EQ(3u, p.GetTokens()[0].length);
559 EXPECT_STREQ("foo", p.GetTokens()[0].name);
560 EXPECT_EQ(1u, p.GetTokens()[1].length);
561 EXPECT_STREQ("0", p.GetTokens()[1].name);
562 EXPECT_EQ(0u, p.GetTokens()[1].index);
563 }
564
TEST(Pointer,Append)565 TEST(Pointer, Append) {
566 {
567 Pointer p;
568 Pointer q = p.Append("foo");
569 EXPECT_TRUE(Pointer("/foo") == q);
570 q = q.Append(1234);
571 EXPECT_TRUE(Pointer("/foo/1234") == q);
572 q = q.Append("");
573 EXPECT_TRUE(Pointer("/foo/1234/") == q);
574 }
575
576 {
577 Pointer p;
578 Pointer q = p.Append(Value("foo").Move());
579 EXPECT_TRUE(Pointer("/foo") == q);
580 q = q.Append(Value(1234).Move());
581 EXPECT_TRUE(Pointer("/foo/1234") == q);
582 q = q.Append(Value(kStringType).Move());
583 EXPECT_TRUE(Pointer("/foo/1234/") == q);
584 }
585
586 #if RAPIDJSON_HAS_STDSTRING
587 {
588 Pointer p;
589 Pointer q = p.Append(std::string("foo"));
590 EXPECT_TRUE(Pointer("/foo") == q);
591 }
592 #endif
593 }
594
TEST(Pointer,Equality)595 TEST(Pointer, Equality) {
596 EXPECT_TRUE(Pointer("/foo/0") == Pointer("/foo/0"));
597 EXPECT_FALSE(Pointer("/foo/0") == Pointer("/foo/1"));
598 EXPECT_FALSE(Pointer("/foo/0") == Pointer("/foo/0/1"));
599 EXPECT_FALSE(Pointer("/foo/0") == Pointer("a"));
600 EXPECT_FALSE(Pointer("a") == Pointer("a")); // Invalid always not equal
601 }
602
TEST(Pointer,Inequality)603 TEST(Pointer, Inequality) {
604 EXPECT_FALSE(Pointer("/foo/0") != Pointer("/foo/0"));
605 EXPECT_TRUE(Pointer("/foo/0") != Pointer("/foo/1"));
606 EXPECT_TRUE(Pointer("/foo/0") != Pointer("/foo/0/1"));
607 EXPECT_TRUE(Pointer("/foo/0") != Pointer("a"));
608 EXPECT_TRUE(Pointer("a") != Pointer("a")); // Invalid always not equal
609 }
610
TEST(Pointer,Create)611 TEST(Pointer, Create) {
612 Document d;
613 {
614 Value* v = &Pointer("").Create(d, d.GetAllocator());
615 EXPECT_EQ(&d, v);
616 }
617 {
618 Value* v = &Pointer("/foo").Create(d, d.GetAllocator());
619 EXPECT_EQ(&d["foo"], v);
620 }
621 {
622 Value* v = &Pointer("/foo/0").Create(d, d.GetAllocator());
623 EXPECT_EQ(&d["foo"][0], v);
624 }
625 {
626 Value* v = &Pointer("/foo/-").Create(d, d.GetAllocator());
627 EXPECT_EQ(&d["foo"][1], v);
628 }
629
630 {
631 Value* v = &Pointer("/foo/-/-").Create(d, d.GetAllocator());
632 // "foo/-" is a newly created null value x.
633 // "foo/-/-" finds that x is not an array, it converts x to empty object
634 // and treats - as "-" member name
635 EXPECT_EQ(&d["foo"][2]["-"], v);
636 }
637
638 {
639 // Document with no allocator
640 Value* v = &Pointer("/foo/-").Create(d);
641 EXPECT_EQ(&d["foo"][3], v);
642 }
643
644 {
645 // Value (not document) must give allocator
646 Value* v = &Pointer("/-").Create(d["foo"], d.GetAllocator());
647 EXPECT_EQ(&d["foo"][4], v);
648 }
649 }
650
TEST(Pointer,Get)651 TEST(Pointer, Get) {
652 Document d;
653 d.Parse(kJson);
654
655 EXPECT_EQ(&d, Pointer("").Get(d));
656 EXPECT_EQ(&d["foo"], Pointer("/foo").Get(d));
657 EXPECT_EQ(&d["foo"][0], Pointer("/foo/0").Get(d));
658 EXPECT_EQ(&d[""], Pointer("/").Get(d));
659 EXPECT_EQ(&d["a/b"], Pointer("/a~1b").Get(d));
660 EXPECT_EQ(&d["c%d"], Pointer("/c%d").Get(d));
661 EXPECT_EQ(&d["e^f"], Pointer("/e^f").Get(d));
662 EXPECT_EQ(&d["g|h"], Pointer("/g|h").Get(d));
663 EXPECT_EQ(&d["i\\j"], Pointer("/i\\j").Get(d));
664 EXPECT_EQ(&d["k\"l"], Pointer("/k\"l").Get(d));
665 EXPECT_EQ(&d[" "], Pointer("/ ").Get(d));
666 EXPECT_EQ(&d["m~n"], Pointer("/m~0n").Get(d));
667 EXPECT_TRUE(Pointer("/abc").Get(d) == 0);
668 size_t unresolvedTokenIndex;
669 EXPECT_TRUE(Pointer("/foo/2").Get(d, &unresolvedTokenIndex) == 0); // Out of boundary
670 EXPECT_EQ(1u, unresolvedTokenIndex);
671 EXPECT_TRUE(Pointer("/foo/a").Get(d, &unresolvedTokenIndex) == 0); // "/foo" is an array, cannot query by "a"
672 EXPECT_EQ(1u, unresolvedTokenIndex);
673 EXPECT_TRUE(Pointer("/foo/0/0").Get(d, &unresolvedTokenIndex) == 0); // "/foo/0" is an string, cannot further query
674 EXPECT_EQ(2u, unresolvedTokenIndex);
675 EXPECT_TRUE(Pointer("/foo/0/a").Get(d, &unresolvedTokenIndex) == 0); // "/foo/0" is an string, cannot further query
676 EXPECT_EQ(2u, unresolvedTokenIndex);
677
678 Pointer::Token tokens[] = { { "foo ...", 3, kPointerInvalidIndex } };
679 EXPECT_EQ(&d["foo"], Pointer(tokens, 1).Get(d));
680 }
681
TEST(Pointer,GetWithDefault)682 TEST(Pointer, GetWithDefault) {
683 Document d;
684 d.Parse(kJson);
685
686 // Value version
687 Document::AllocatorType& a = d.GetAllocator();
688 const Value v("qux");
689 EXPECT_TRUE(Value("bar") == Pointer("/foo/0").GetWithDefault(d, v, a));
690 EXPECT_TRUE(Value("baz") == Pointer("/foo/1").GetWithDefault(d, v, a));
691 EXPECT_TRUE(Value("qux") == Pointer("/foo/2").GetWithDefault(d, v, a));
692 EXPECT_TRUE(Value("last") == Pointer("/foo/-").GetWithDefault(d, Value("last").Move(), a));
693 EXPECT_STREQ("last", d["foo"][3].GetString());
694
695 EXPECT_TRUE(Pointer("/foo/null").GetWithDefault(d, Value().Move(), a).IsNull());
696 EXPECT_TRUE(Pointer("/foo/null").GetWithDefault(d, "x", a).IsNull());
697
698 // Generic version
699 EXPECT_EQ(-1, Pointer("/foo/int").GetWithDefault(d, -1, a).GetInt());
700 EXPECT_EQ(-1, Pointer("/foo/int").GetWithDefault(d, -2, a).GetInt());
701 EXPECT_EQ(0x87654321, Pointer("/foo/uint").GetWithDefault(d, 0x87654321, a).GetUint());
702 EXPECT_EQ(0x87654321, Pointer("/foo/uint").GetWithDefault(d, 0x12345678, a).GetUint());
703
704 const int64_t i64 = static_cast<int64_t>(RAPIDJSON_UINT64_C2(0x80000000, 0));
705 EXPECT_EQ(i64, Pointer("/foo/int64").GetWithDefault(d, i64, a).GetInt64());
706 EXPECT_EQ(i64, Pointer("/foo/int64").GetWithDefault(d, i64 + 1, a).GetInt64());
707
708 const uint64_t u64 = RAPIDJSON_UINT64_C2(0xFFFFFFFFF, 0xFFFFFFFFF);
709 EXPECT_EQ(u64, Pointer("/foo/uint64").GetWithDefault(d, u64, a).GetUint64());
710 EXPECT_EQ(u64, Pointer("/foo/uint64").GetWithDefault(d, u64 - 1, a).GetUint64());
711
712 EXPECT_TRUE(Pointer("/foo/true").GetWithDefault(d, true, a).IsTrue());
713 EXPECT_TRUE(Pointer("/foo/true").GetWithDefault(d, false, a).IsTrue());
714
715 EXPECT_TRUE(Pointer("/foo/false").GetWithDefault(d, false, a).IsFalse());
716 EXPECT_TRUE(Pointer("/foo/false").GetWithDefault(d, true, a).IsFalse());
717
718 // StringRef version
719 EXPECT_STREQ("Hello", Pointer("/foo/hello").GetWithDefault(d, "Hello", a).GetString());
720
721 // Copy string version
722 {
723 char buffer[256];
724 strcpy(buffer, "World");
725 EXPECT_STREQ("World", Pointer("/foo/world").GetWithDefault(d, buffer, a).GetString());
726 memset(buffer, 0, sizeof(buffer));
727 }
728 EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString());
729
730 #if RAPIDJSON_HAS_STDSTRING
731 EXPECT_STREQ("C++", Pointer("/foo/C++").GetWithDefault(d, std::string("C++"), a).GetString());
732 #endif
733 }
734
TEST(Pointer,GetWithDefault_NoAllocator)735 TEST(Pointer, GetWithDefault_NoAllocator) {
736 Document d;
737 d.Parse(kJson);
738
739 // Value version
740 const Value v("qux");
741 EXPECT_TRUE(Value("bar") == Pointer("/foo/0").GetWithDefault(d, v));
742 EXPECT_TRUE(Value("baz") == Pointer("/foo/1").GetWithDefault(d, v));
743 EXPECT_TRUE(Value("qux") == Pointer("/foo/2").GetWithDefault(d, v));
744 EXPECT_TRUE(Value("last") == Pointer("/foo/-").GetWithDefault(d, Value("last").Move()));
745 EXPECT_STREQ("last", d["foo"][3].GetString());
746
747 EXPECT_TRUE(Pointer("/foo/null").GetWithDefault(d, Value().Move()).IsNull());
748 EXPECT_TRUE(Pointer("/foo/null").GetWithDefault(d, "x").IsNull());
749
750 // Generic version
751 EXPECT_EQ(-1, Pointer("/foo/int").GetWithDefault(d, -1).GetInt());
752 EXPECT_EQ(-1, Pointer("/foo/int").GetWithDefault(d, -2).GetInt());
753 EXPECT_EQ(0x87654321, Pointer("/foo/uint").GetWithDefault(d, 0x87654321).GetUint());
754 EXPECT_EQ(0x87654321, Pointer("/foo/uint").GetWithDefault(d, 0x12345678).GetUint());
755
756 const int64_t i64 = static_cast<int64_t>(RAPIDJSON_UINT64_C2(0x80000000, 0));
757 EXPECT_EQ(i64, Pointer("/foo/int64").GetWithDefault(d, i64).GetInt64());
758 EXPECT_EQ(i64, Pointer("/foo/int64").GetWithDefault(d, i64 + 1).GetInt64());
759
760 const uint64_t u64 = RAPIDJSON_UINT64_C2(0xFFFFFFFFF, 0xFFFFFFFFF);
761 EXPECT_EQ(u64, Pointer("/foo/uint64").GetWithDefault(d, u64).GetUint64());
762 EXPECT_EQ(u64, Pointer("/foo/uint64").GetWithDefault(d, u64 - 1).GetUint64());
763
764 EXPECT_TRUE(Pointer("/foo/true").GetWithDefault(d, true).IsTrue());
765 EXPECT_TRUE(Pointer("/foo/true").GetWithDefault(d, false).IsTrue());
766
767 EXPECT_TRUE(Pointer("/foo/false").GetWithDefault(d, false).IsFalse());
768 EXPECT_TRUE(Pointer("/foo/false").GetWithDefault(d, true).IsFalse());
769
770 // StringRef version
771 EXPECT_STREQ("Hello", Pointer("/foo/hello").GetWithDefault(d, "Hello").GetString());
772
773 // Copy string version
774 {
775 char buffer[256];
776 strcpy(buffer, "World");
777 EXPECT_STREQ("World", Pointer("/foo/world").GetWithDefault(d, buffer).GetString());
778 memset(buffer, 0, sizeof(buffer));
779 }
780 EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString());
781
782 #if RAPIDJSON_HAS_STDSTRING
783 EXPECT_STREQ("C++", Pointer("/foo/C++").GetWithDefault(d, std::string("C++")).GetString());
784 #endif
785 }
786
TEST(Pointer,Set)787 TEST(Pointer, Set) {
788 Document d;
789 d.Parse(kJson);
790 Document::AllocatorType& a = d.GetAllocator();
791
792 // Value version
793 Pointer("/foo/0").Set(d, Value(123).Move(), a);
794 EXPECT_EQ(123, d["foo"][0].GetInt());
795
796 Pointer("/foo/-").Set(d, Value(456).Move(), a);
797 EXPECT_EQ(456, d["foo"][2].GetInt());
798
799 Pointer("/foo/null").Set(d, Value().Move(), a);
800 EXPECT_TRUE(GetValueByPointer(d, "/foo/null")->IsNull());
801
802 // Const Value version
803 const Value foo(d["foo"], a);
804 Pointer("/clone").Set(d, foo, a);
805 EXPECT_EQ(foo, *GetValueByPointer(d, "/clone"));
806
807 // Generic version
808 Pointer("/foo/int").Set(d, -1, a);
809 EXPECT_EQ(-1, GetValueByPointer(d, "/foo/int")->GetInt());
810
811 Pointer("/foo/uint").Set(d, 0x87654321, a);
812 EXPECT_EQ(0x87654321, GetValueByPointer(d, "/foo/uint")->GetUint());
813
814 const int64_t i64 = static_cast<int64_t>(RAPIDJSON_UINT64_C2(0x80000000, 0));
815 Pointer("/foo/int64").Set(d, i64, a);
816 EXPECT_EQ(i64, GetValueByPointer(d, "/foo/int64")->GetInt64());
817
818 const uint64_t u64 = RAPIDJSON_UINT64_C2(0xFFFFFFFFF, 0xFFFFFFFFF);
819 Pointer("/foo/uint64").Set(d, u64, a);
820 EXPECT_EQ(u64, GetValueByPointer(d, "/foo/uint64")->GetUint64());
821
822 Pointer("/foo/true").Set(d, true, a);
823 EXPECT_TRUE(GetValueByPointer(d, "/foo/true")->IsTrue());
824
825 Pointer("/foo/false").Set(d, false, a);
826 EXPECT_TRUE(GetValueByPointer(d, "/foo/false")->IsFalse());
827
828 // StringRef version
829 Pointer("/foo/hello").Set(d, "Hello", a);
830 EXPECT_STREQ("Hello", GetValueByPointer(d, "/foo/hello")->GetString());
831
832 // Copy string version
833 {
834 char buffer[256];
835 strcpy(buffer, "World");
836 Pointer("/foo/world").Set(d, buffer, a);
837 memset(buffer, 0, sizeof(buffer));
838 }
839 EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString());
840
841 #if RAPIDJSON_HAS_STDSTRING
842 Pointer("/foo/c++").Set(d, std::string("C++"), a);
843 EXPECT_STREQ("C++", GetValueByPointer(d, "/foo/c++")->GetString());
844 #endif
845 }
846
TEST(Pointer,Set_NoAllocator)847 TEST(Pointer, Set_NoAllocator) {
848 Document d;
849 d.Parse(kJson);
850
851 // Value version
852 Pointer("/foo/0").Set(d, Value(123).Move());
853 EXPECT_EQ(123, d["foo"][0].GetInt());
854
855 Pointer("/foo/-").Set(d, Value(456).Move());
856 EXPECT_EQ(456, d["foo"][2].GetInt());
857
858 Pointer("/foo/null").Set(d, Value().Move());
859 EXPECT_TRUE(GetValueByPointer(d, "/foo/null")->IsNull());
860
861 // Const Value version
862 const Value foo(d["foo"], d.GetAllocator());
863 Pointer("/clone").Set(d, foo);
864 EXPECT_EQ(foo, *GetValueByPointer(d, "/clone"));
865
866 // Generic version
867 Pointer("/foo/int").Set(d, -1);
868 EXPECT_EQ(-1, GetValueByPointer(d, "/foo/int")->GetInt());
869
870 Pointer("/foo/uint").Set(d, 0x87654321);
871 EXPECT_EQ(0x87654321, GetValueByPointer(d, "/foo/uint")->GetUint());
872
873 const int64_t i64 = static_cast<int64_t>(RAPIDJSON_UINT64_C2(0x80000000, 0));
874 Pointer("/foo/int64").Set(d, i64);
875 EXPECT_EQ(i64, GetValueByPointer(d, "/foo/int64")->GetInt64());
876
877 const uint64_t u64 = RAPIDJSON_UINT64_C2(0xFFFFFFFFF, 0xFFFFFFFFF);
878 Pointer("/foo/uint64").Set(d, u64);
879 EXPECT_EQ(u64, GetValueByPointer(d, "/foo/uint64")->GetUint64());
880
881 Pointer("/foo/true").Set(d, true);
882 EXPECT_TRUE(GetValueByPointer(d, "/foo/true")->IsTrue());
883
884 Pointer("/foo/false").Set(d, false);
885 EXPECT_TRUE(GetValueByPointer(d, "/foo/false")->IsFalse());
886
887 // StringRef version
888 Pointer("/foo/hello").Set(d, "Hello");
889 EXPECT_STREQ("Hello", GetValueByPointer(d, "/foo/hello")->GetString());
890
891 // Copy string version
892 {
893 char buffer[256];
894 strcpy(buffer, "World");
895 Pointer("/foo/world").Set(d, buffer);
896 memset(buffer, 0, sizeof(buffer));
897 }
898 EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString());
899
900 #if RAPIDJSON_HAS_STDSTRING
901 Pointer("/foo/c++").Set(d, std::string("C++"));
902 EXPECT_STREQ("C++", GetValueByPointer(d, "/foo/c++")->GetString());
903 #endif
904 }
905
TEST(Pointer,Swap_Value)906 TEST(Pointer, Swap_Value) {
907 Document d;
908 d.Parse(kJson);
909 Document::AllocatorType& a = d.GetAllocator();
910 Pointer("/foo/0").Swap(d, *Pointer("/foo/1").Get(d), a);
911 EXPECT_STREQ("baz", d["foo"][0].GetString());
912 EXPECT_STREQ("bar", d["foo"][1].GetString());
913 }
914
TEST(Pointer,Swap_Value_NoAllocator)915 TEST(Pointer, Swap_Value_NoAllocator) {
916 Document d;
917 d.Parse(kJson);
918 Pointer("/foo/0").Swap(d, *Pointer("/foo/1").Get(d));
919 EXPECT_STREQ("baz", d["foo"][0].GetString());
920 EXPECT_STREQ("bar", d["foo"][1].GetString());
921 }
922
TEST(Pointer,Erase)923 TEST(Pointer, Erase) {
924 Document d;
925 d.Parse(kJson);
926
927 EXPECT_FALSE(Pointer("").Erase(d));
928 EXPECT_FALSE(Pointer("/nonexist").Erase(d));
929 EXPECT_FALSE(Pointer("/nonexist/nonexist").Erase(d));
930 EXPECT_FALSE(Pointer("/foo/nonexist").Erase(d));
931 EXPECT_FALSE(Pointer("/foo/nonexist/nonexist").Erase(d));
932 EXPECT_FALSE(Pointer("/foo/0/nonexist").Erase(d));
933 EXPECT_FALSE(Pointer("/foo/0/nonexist/nonexist").Erase(d));
934 EXPECT_FALSE(Pointer("/foo/2/nonexist").Erase(d));
935 EXPECT_TRUE(Pointer("/foo/0").Erase(d));
936 EXPECT_EQ(1u, d["foo"].Size());
937 EXPECT_STREQ("baz", d["foo"][0].GetString());
938 EXPECT_TRUE(Pointer("/foo/0").Erase(d));
939 EXPECT_TRUE(d["foo"].Empty());
940 EXPECT_TRUE(Pointer("/foo").Erase(d));
941 EXPECT_TRUE(Pointer("/foo").Get(d) == 0);
942
943 Pointer("/a/0/b/0").Create(d);
944
945 EXPECT_TRUE(Pointer("/a/0/b/0").Get(d) != 0);
946 EXPECT_TRUE(Pointer("/a/0/b/0").Erase(d));
947 EXPECT_TRUE(Pointer("/a/0/b/0").Get(d) == 0);
948
949 EXPECT_TRUE(Pointer("/a/0/b").Get(d) != 0);
950 EXPECT_TRUE(Pointer("/a/0/b").Erase(d));
951 EXPECT_TRUE(Pointer("/a/0/b").Get(d) == 0);
952
953 EXPECT_TRUE(Pointer("/a/0").Get(d) != 0);
954 EXPECT_TRUE(Pointer("/a/0").Erase(d));
955 EXPECT_TRUE(Pointer("/a/0").Get(d) == 0);
956
957 EXPECT_TRUE(Pointer("/a").Get(d) != 0);
958 EXPECT_TRUE(Pointer("/a").Erase(d));
959 EXPECT_TRUE(Pointer("/a").Get(d) == 0);
960 }
961
TEST(Pointer,CreateValueByPointer)962 TEST(Pointer, CreateValueByPointer) {
963 Document d;
964 Document::AllocatorType& a = d.GetAllocator();
965
966 {
967 Value& v = CreateValueByPointer(d, Pointer("/foo/0"), a);
968 EXPECT_EQ(&d["foo"][0], &v);
969 }
970 {
971 Value& v = CreateValueByPointer(d, "/foo/1", a);
972 EXPECT_EQ(&d["foo"][1], &v);
973 }
974 }
975
TEST(Pointer,CreateValueByPointer_NoAllocator)976 TEST(Pointer, CreateValueByPointer_NoAllocator) {
977 Document d;
978
979 {
980 Value& v = CreateValueByPointer(d, Pointer("/foo/0"));
981 EXPECT_EQ(&d["foo"][0], &v);
982 }
983 {
984 Value& v = CreateValueByPointer(d, "/foo/1");
985 EXPECT_EQ(&d["foo"][1], &v);
986 }
987 }
988
TEST(Pointer,GetValueByPointer)989 TEST(Pointer, GetValueByPointer) {
990 Document d;
991 d.Parse(kJson);
992
993 EXPECT_EQ(&d["foo"][0], GetValueByPointer(d, Pointer("/foo/0")));
994 EXPECT_EQ(&d["foo"][0], GetValueByPointer(d, "/foo/0"));
995
996 size_t unresolvedTokenIndex;
997 EXPECT_TRUE(GetValueByPointer(d, "/foo/2", &unresolvedTokenIndex) == 0); // Out of boundary
998 EXPECT_EQ(1u, unresolvedTokenIndex);
999 EXPECT_TRUE(GetValueByPointer(d, "/foo/a", &unresolvedTokenIndex) == 0); // "/foo" is an array, cannot query by "a"
1000 EXPECT_EQ(1u, unresolvedTokenIndex);
1001 EXPECT_TRUE(GetValueByPointer(d, "/foo/0/0", &unresolvedTokenIndex) == 0); // "/foo/0" is an string, cannot further query
1002 EXPECT_EQ(2u, unresolvedTokenIndex);
1003 EXPECT_TRUE(GetValueByPointer(d, "/foo/0/a", &unresolvedTokenIndex) == 0); // "/foo/0" is an string, cannot further query
1004 EXPECT_EQ(2u, unresolvedTokenIndex);
1005
1006 // const version
1007 const Value& v = d;
1008 EXPECT_EQ(&d["foo"][0], GetValueByPointer(v, Pointer("/foo/0")));
1009 EXPECT_EQ(&d["foo"][0], GetValueByPointer(v, "/foo/0"));
1010
1011 EXPECT_TRUE(GetValueByPointer(v, "/foo/2", &unresolvedTokenIndex) == 0); // Out of boundary
1012 EXPECT_EQ(1u, unresolvedTokenIndex);
1013 EXPECT_TRUE(GetValueByPointer(v, "/foo/a", &unresolvedTokenIndex) == 0); // "/foo" is an array, cannot query by "a"
1014 EXPECT_EQ(1u, unresolvedTokenIndex);
1015 EXPECT_TRUE(GetValueByPointer(v, "/foo/0/0", &unresolvedTokenIndex) == 0); // "/foo/0" is an string, cannot further query
1016 EXPECT_EQ(2u, unresolvedTokenIndex);
1017 EXPECT_TRUE(GetValueByPointer(v, "/foo/0/a", &unresolvedTokenIndex) == 0); // "/foo/0" is an string, cannot further query
1018 EXPECT_EQ(2u, unresolvedTokenIndex);
1019
1020 }
1021
TEST(Pointer,GetValueByPointerWithDefault_Pointer)1022 TEST(Pointer, GetValueByPointerWithDefault_Pointer) {
1023 Document d;
1024 d.Parse(kJson);
1025
1026 Document::AllocatorType& a = d.GetAllocator();
1027 const Value v("qux");
1028 EXPECT_TRUE(Value("bar") == GetValueByPointerWithDefault(d, Pointer("/foo/0"), v, a));
1029 EXPECT_TRUE(Value("bar") == GetValueByPointerWithDefault(d, Pointer("/foo/0"), v, a));
1030 EXPECT_TRUE(Value("baz") == GetValueByPointerWithDefault(d, Pointer("/foo/1"), v, a));
1031 EXPECT_TRUE(Value("qux") == GetValueByPointerWithDefault(d, Pointer("/foo/2"), v, a));
1032 EXPECT_TRUE(Value("last") == GetValueByPointerWithDefault(d, Pointer("/foo/-"), Value("last").Move(), a));
1033 EXPECT_STREQ("last", d["foo"][3].GetString());
1034
1035 EXPECT_TRUE(GetValueByPointerWithDefault(d, Pointer("/foo/null"), Value().Move(), a).IsNull());
1036 EXPECT_TRUE(GetValueByPointerWithDefault(d, Pointer("/foo/null"), "x", a).IsNull());
1037
1038 // Generic version
1039 EXPECT_EQ(-1, GetValueByPointerWithDefault(d, Pointer("/foo/int"), -1, a).GetInt());
1040 EXPECT_EQ(-1, GetValueByPointerWithDefault(d, Pointer("/foo/int"), -2, a).GetInt());
1041 EXPECT_EQ(0x87654321, GetValueByPointerWithDefault(d, Pointer("/foo/uint"), 0x87654321, a).GetUint());
1042 EXPECT_EQ(0x87654321, GetValueByPointerWithDefault(d, Pointer("/foo/uint"), 0x12345678, a).GetUint());
1043
1044 const int64_t i64 = static_cast<int64_t>(RAPIDJSON_UINT64_C2(0x80000000, 0));
1045 EXPECT_EQ(i64, GetValueByPointerWithDefault(d, Pointer("/foo/int64"), i64, a).GetInt64());
1046 EXPECT_EQ(i64, GetValueByPointerWithDefault(d, Pointer("/foo/int64"), i64 + 1, a).GetInt64());
1047
1048 const uint64_t u64 = RAPIDJSON_UINT64_C2(0xFFFFFFFFF, 0xFFFFFFFFF);
1049 EXPECT_EQ(u64, GetValueByPointerWithDefault(d, Pointer("/foo/uint64"), u64, a).GetUint64());
1050 EXPECT_EQ(u64, GetValueByPointerWithDefault(d, Pointer("/foo/uint64"), u64 - 1, a).GetUint64());
1051
1052 EXPECT_TRUE(GetValueByPointerWithDefault(d, Pointer("/foo/true"), true, a).IsTrue());
1053 EXPECT_TRUE(GetValueByPointerWithDefault(d, Pointer("/foo/true"), false, a).IsTrue());
1054
1055 EXPECT_TRUE(GetValueByPointerWithDefault(d, Pointer("/foo/false"), false, a).IsFalse());
1056 EXPECT_TRUE(GetValueByPointerWithDefault(d, Pointer("/foo/false"), true, a).IsFalse());
1057
1058 // StringRef version
1059 EXPECT_STREQ("Hello", GetValueByPointerWithDefault(d, Pointer("/foo/hello"), "Hello", a).GetString());
1060
1061 // Copy string version
1062 {
1063 char buffer[256];
1064 strcpy(buffer, "World");
1065 EXPECT_STREQ("World", GetValueByPointerWithDefault(d, Pointer("/foo/world"), buffer, a).GetString());
1066 memset(buffer, 0, sizeof(buffer));
1067 }
1068 EXPECT_STREQ("World", GetValueByPointer(d, Pointer("/foo/world"))->GetString());
1069
1070 #if RAPIDJSON_HAS_STDSTRING
1071 EXPECT_STREQ("C++", GetValueByPointerWithDefault(d, Pointer("/foo/C++"), std::string("C++"), a).GetString());
1072 #endif
1073 }
1074
TEST(Pointer,GetValueByPointerWithDefault_String)1075 TEST(Pointer, GetValueByPointerWithDefault_String) {
1076 Document d;
1077 d.Parse(kJson);
1078
1079 Document::AllocatorType& a = d.GetAllocator();
1080 const Value v("qux");
1081 EXPECT_TRUE(Value("bar") == GetValueByPointerWithDefault(d, "/foo/0", v, a));
1082 EXPECT_TRUE(Value("bar") == GetValueByPointerWithDefault(d, "/foo/0", v, a));
1083 EXPECT_TRUE(Value("baz") == GetValueByPointerWithDefault(d, "/foo/1", v, a));
1084 EXPECT_TRUE(Value("qux") == GetValueByPointerWithDefault(d, "/foo/2", v, a));
1085 EXPECT_TRUE(Value("last") == GetValueByPointerWithDefault(d, "/foo/-", Value("last").Move(), a));
1086 EXPECT_STREQ("last", d["foo"][3].GetString());
1087
1088 EXPECT_TRUE(GetValueByPointerWithDefault(d, "/foo/null", Value().Move(), a).IsNull());
1089 EXPECT_TRUE(GetValueByPointerWithDefault(d, "/foo/null", "x", a).IsNull());
1090
1091 // Generic version
1092 EXPECT_EQ(-1, GetValueByPointerWithDefault(d, "/foo/int", -1, a).GetInt());
1093 EXPECT_EQ(-1, GetValueByPointerWithDefault(d, "/foo/int", -2, a).GetInt());
1094 EXPECT_EQ(0x87654321, GetValueByPointerWithDefault(d, "/foo/uint", 0x87654321, a).GetUint());
1095 EXPECT_EQ(0x87654321, GetValueByPointerWithDefault(d, "/foo/uint", 0x12345678, a).GetUint());
1096
1097 const int64_t i64 = static_cast<int64_t>(RAPIDJSON_UINT64_C2(0x80000000, 0));
1098 EXPECT_EQ(i64, GetValueByPointerWithDefault(d, "/foo/int64", i64, a).GetInt64());
1099 EXPECT_EQ(i64, GetValueByPointerWithDefault(d, "/foo/int64", i64 + 1, a).GetInt64());
1100
1101 const uint64_t u64 = RAPIDJSON_UINT64_C2(0xFFFFFFFFF, 0xFFFFFFFFF);
1102 EXPECT_EQ(u64, GetValueByPointerWithDefault(d, "/foo/uint64", u64, a).GetUint64());
1103 EXPECT_EQ(u64, GetValueByPointerWithDefault(d, "/foo/uint64", u64 - 1, a).GetUint64());
1104
1105 EXPECT_TRUE(GetValueByPointerWithDefault(d, "/foo/true", true, a).IsTrue());
1106 EXPECT_TRUE(GetValueByPointerWithDefault(d, "/foo/true", false, a).IsTrue());
1107
1108 EXPECT_TRUE(GetValueByPointerWithDefault(d, "/foo/false", false, a).IsFalse());
1109 EXPECT_TRUE(GetValueByPointerWithDefault(d, "/foo/false", true, a).IsFalse());
1110
1111 // StringRef version
1112 EXPECT_STREQ("Hello", GetValueByPointerWithDefault(d, "/foo/hello", "Hello", a).GetString());
1113
1114 // Copy string version
1115 {
1116 char buffer[256];
1117 strcpy(buffer, "World");
1118 EXPECT_STREQ("World", GetValueByPointerWithDefault(d, "/foo/world", buffer, a).GetString());
1119 memset(buffer, 0, sizeof(buffer));
1120 }
1121 EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString());
1122
1123 #if RAPIDJSON_HAS_STDSTRING
1124 EXPECT_STREQ("C++", GetValueByPointerWithDefault(d, "/foo/C++", std::string("C++"), a).GetString());
1125 #endif
1126 }
1127
TEST(Pointer,GetValueByPointerWithDefault_Pointer_NoAllocator)1128 TEST(Pointer, GetValueByPointerWithDefault_Pointer_NoAllocator) {
1129 Document d;
1130 d.Parse(kJson);
1131
1132 const Value v("qux");
1133 EXPECT_TRUE(Value("bar") == GetValueByPointerWithDefault(d, Pointer("/foo/0"), v));
1134 EXPECT_TRUE(Value("bar") == GetValueByPointerWithDefault(d, Pointer("/foo/0"), v));
1135 EXPECT_TRUE(Value("baz") == GetValueByPointerWithDefault(d, Pointer("/foo/1"), v));
1136 EXPECT_TRUE(Value("qux") == GetValueByPointerWithDefault(d, Pointer("/foo/2"), v));
1137 EXPECT_TRUE(Value("last") == GetValueByPointerWithDefault(d, Pointer("/foo/-"), Value("last").Move()));
1138 EXPECT_STREQ("last", d["foo"][3].GetString());
1139
1140 EXPECT_TRUE(GetValueByPointerWithDefault(d, Pointer("/foo/null"), Value().Move()).IsNull());
1141 EXPECT_TRUE(GetValueByPointerWithDefault(d, Pointer("/foo/null"), "x").IsNull());
1142
1143 // Generic version
1144 EXPECT_EQ(-1, GetValueByPointerWithDefault(d, Pointer("/foo/int"), -1).GetInt());
1145 EXPECT_EQ(-1, GetValueByPointerWithDefault(d, Pointer("/foo/int"), -2).GetInt());
1146 EXPECT_EQ(0x87654321, GetValueByPointerWithDefault(d, Pointer("/foo/uint"), 0x87654321).GetUint());
1147 EXPECT_EQ(0x87654321, GetValueByPointerWithDefault(d, Pointer("/foo/uint"), 0x12345678).GetUint());
1148
1149 const int64_t i64 = static_cast<int64_t>(RAPIDJSON_UINT64_C2(0x80000000, 0));
1150 EXPECT_EQ(i64, GetValueByPointerWithDefault(d, Pointer("/foo/int64"), i64).GetInt64());
1151 EXPECT_EQ(i64, GetValueByPointerWithDefault(d, Pointer("/foo/int64"), i64 + 1).GetInt64());
1152
1153 const uint64_t u64 = RAPIDJSON_UINT64_C2(0xFFFFFFFFF, 0xFFFFFFFFF);
1154 EXPECT_EQ(u64, GetValueByPointerWithDefault(d, Pointer("/foo/uint64"), u64).GetUint64());
1155 EXPECT_EQ(u64, GetValueByPointerWithDefault(d, Pointer("/foo/uint64"), u64 - 1).GetUint64());
1156
1157 EXPECT_TRUE(GetValueByPointerWithDefault(d, Pointer("/foo/true"), true).IsTrue());
1158 EXPECT_TRUE(GetValueByPointerWithDefault(d, Pointer("/foo/true"), false).IsTrue());
1159
1160 EXPECT_TRUE(GetValueByPointerWithDefault(d, Pointer("/foo/false"), false).IsFalse());
1161 EXPECT_TRUE(GetValueByPointerWithDefault(d, Pointer("/foo/false"), true).IsFalse());
1162
1163 // StringRef version
1164 EXPECT_STREQ("Hello", GetValueByPointerWithDefault(d, Pointer("/foo/hello"), "Hello").GetString());
1165
1166 // Copy string version
1167 {
1168 char buffer[256];
1169 strcpy(buffer, "World");
1170 EXPECT_STREQ("World", GetValueByPointerWithDefault(d, Pointer("/foo/world"), buffer).GetString());
1171 memset(buffer, 0, sizeof(buffer));
1172 }
1173 EXPECT_STREQ("World", GetValueByPointer(d, Pointer("/foo/world"))->GetString());
1174
1175 #if RAPIDJSON_HAS_STDSTRING
1176 EXPECT_STREQ("C++", GetValueByPointerWithDefault(d, Pointer("/foo/C++"), std::string("C++")).GetString());
1177 #endif
1178 }
1179
TEST(Pointer,GetValueByPointerWithDefault_String_NoAllocator)1180 TEST(Pointer, GetValueByPointerWithDefault_String_NoAllocator) {
1181 Document d;
1182 d.Parse(kJson);
1183
1184 const Value v("qux");
1185 EXPECT_TRUE(Value("bar") == GetValueByPointerWithDefault(d, "/foo/0", v));
1186 EXPECT_TRUE(Value("bar") == GetValueByPointerWithDefault(d, "/foo/0", v));
1187 EXPECT_TRUE(Value("baz") == GetValueByPointerWithDefault(d, "/foo/1", v));
1188 EXPECT_TRUE(Value("qux") == GetValueByPointerWithDefault(d, "/foo/2", v));
1189 EXPECT_TRUE(Value("last") == GetValueByPointerWithDefault(d, "/foo/-", Value("last").Move()));
1190 EXPECT_STREQ("last", d["foo"][3].GetString());
1191
1192 EXPECT_TRUE(GetValueByPointerWithDefault(d, "/foo/null", Value().Move()).IsNull());
1193 EXPECT_TRUE(GetValueByPointerWithDefault(d, "/foo/null", "x").IsNull());
1194
1195 // Generic version
1196 EXPECT_EQ(-1, GetValueByPointerWithDefault(d, "/foo/int", -1).GetInt());
1197 EXPECT_EQ(-1, GetValueByPointerWithDefault(d, "/foo/int", -2).GetInt());
1198 EXPECT_EQ(0x87654321, GetValueByPointerWithDefault(d, "/foo/uint", 0x87654321).GetUint());
1199 EXPECT_EQ(0x87654321, GetValueByPointerWithDefault(d, "/foo/uint", 0x12345678).GetUint());
1200
1201 const int64_t i64 = static_cast<int64_t>(RAPIDJSON_UINT64_C2(0x80000000, 0));
1202 EXPECT_EQ(i64, GetValueByPointerWithDefault(d, "/foo/int64", i64).GetInt64());
1203 EXPECT_EQ(i64, GetValueByPointerWithDefault(d, "/foo/int64", i64 + 1).GetInt64());
1204
1205 const uint64_t u64 = RAPIDJSON_UINT64_C2(0xFFFFFFFFF, 0xFFFFFFFFF);
1206 EXPECT_EQ(u64, GetValueByPointerWithDefault(d, "/foo/uint64", u64).GetUint64());
1207 EXPECT_EQ(u64, GetValueByPointerWithDefault(d, "/foo/uint64", u64 - 1).GetUint64());
1208
1209 EXPECT_TRUE(GetValueByPointerWithDefault(d, "/foo/true", true).IsTrue());
1210 EXPECT_TRUE(GetValueByPointerWithDefault(d, "/foo/true", false).IsTrue());
1211
1212 EXPECT_TRUE(GetValueByPointerWithDefault(d, "/foo/false", false).IsFalse());
1213 EXPECT_TRUE(GetValueByPointerWithDefault(d, "/foo/false", true).IsFalse());
1214
1215 // StringRef version
1216 EXPECT_STREQ("Hello", GetValueByPointerWithDefault(d, "/foo/hello", "Hello").GetString());
1217
1218 // Copy string version
1219 {
1220 char buffer[256];
1221 strcpy(buffer, "World");
1222 EXPECT_STREQ("World", GetValueByPointerWithDefault(d, "/foo/world", buffer).GetString());
1223 memset(buffer, 0, sizeof(buffer));
1224 }
1225 EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString());
1226
1227 #if RAPIDJSON_HAS_STDSTRING
1228 EXPECT_STREQ("C++", GetValueByPointerWithDefault(d, Pointer("/foo/C++"), std::string("C++")).GetString());
1229 #endif
1230 }
1231
TEST(Pointer,SetValueByPointer_Pointer)1232 TEST(Pointer, SetValueByPointer_Pointer) {
1233 Document d;
1234 d.Parse(kJson);
1235 Document::AllocatorType& a = d.GetAllocator();
1236
1237 // Value version
1238 SetValueByPointer(d, Pointer("/foo/0"), Value(123).Move(), a);
1239 EXPECT_EQ(123, d["foo"][0].GetInt());
1240
1241 SetValueByPointer(d, Pointer("/foo/null"), Value().Move(), a);
1242 EXPECT_TRUE(GetValueByPointer(d, "/foo/null")->IsNull());
1243
1244 // Const Value version
1245 const Value foo(d["foo"], d.GetAllocator());
1246 SetValueByPointer(d, Pointer("/clone"), foo, a);
1247 EXPECT_EQ(foo, *GetValueByPointer(d, "/clone"));
1248
1249 // Generic version
1250 SetValueByPointer(d, Pointer("/foo/int"), -1, a);
1251 EXPECT_EQ(-1, GetValueByPointer(d, "/foo/int")->GetInt());
1252
1253 SetValueByPointer(d, Pointer("/foo/uint"), 0x87654321, a);
1254 EXPECT_EQ(0x87654321, GetValueByPointer(d, "/foo/uint")->GetUint());
1255
1256 const int64_t i64 = static_cast<int64_t>(RAPIDJSON_UINT64_C2(0x80000000, 0));
1257 SetValueByPointer(d, Pointer("/foo/int64"), i64, a);
1258 EXPECT_EQ(i64, GetValueByPointer(d, "/foo/int64")->GetInt64());
1259
1260 const uint64_t u64 = RAPIDJSON_UINT64_C2(0xFFFFFFFFF, 0xFFFFFFFFF);
1261 SetValueByPointer(d, Pointer("/foo/uint64"), u64, a);
1262 EXPECT_EQ(u64, GetValueByPointer(d, "/foo/uint64")->GetUint64());
1263
1264 SetValueByPointer(d, Pointer("/foo/true"), true, a);
1265 EXPECT_TRUE(GetValueByPointer(d, "/foo/true")->IsTrue());
1266
1267 SetValueByPointer(d, Pointer("/foo/false"), false, a);
1268 EXPECT_TRUE(GetValueByPointer(d, "/foo/false")->IsFalse());
1269
1270 // StringRef version
1271 SetValueByPointer(d, Pointer("/foo/hello"), "Hello", a);
1272 EXPECT_STREQ("Hello", GetValueByPointer(d, "/foo/hello")->GetString());
1273
1274 // Copy string version
1275 {
1276 char buffer[256];
1277 strcpy(buffer, "World");
1278 SetValueByPointer(d, Pointer("/foo/world"), buffer, a);
1279 memset(buffer, 0, sizeof(buffer));
1280 }
1281 EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString());
1282
1283 #if RAPIDJSON_HAS_STDSTRING
1284 SetValueByPointer(d, Pointer("/foo/c++"), std::string("C++"), a);
1285 EXPECT_STREQ("C++", GetValueByPointer(d, "/foo/c++")->GetString());
1286 #endif
1287 }
1288
TEST(Pointer,SetValueByPointer_String)1289 TEST(Pointer, SetValueByPointer_String) {
1290 Document d;
1291 d.Parse(kJson);
1292 Document::AllocatorType& a = d.GetAllocator();
1293
1294 // Value version
1295 SetValueByPointer(d, "/foo/0", Value(123).Move(), a);
1296 EXPECT_EQ(123, d["foo"][0].GetInt());
1297
1298 SetValueByPointer(d, "/foo/null", Value().Move(), a);
1299 EXPECT_TRUE(GetValueByPointer(d, "/foo/null")->IsNull());
1300
1301 // Const Value version
1302 const Value foo(d["foo"], d.GetAllocator());
1303 SetValueByPointer(d, "/clone", foo, a);
1304 EXPECT_EQ(foo, *GetValueByPointer(d, "/clone"));
1305
1306 // Generic version
1307 SetValueByPointer(d, "/foo/int", -1, a);
1308 EXPECT_EQ(-1, GetValueByPointer(d, "/foo/int")->GetInt());
1309
1310 SetValueByPointer(d, "/foo/uint", 0x87654321, a);
1311 EXPECT_EQ(0x87654321, GetValueByPointer(d, "/foo/uint")->GetUint());
1312
1313 const int64_t i64 = static_cast<int64_t>(RAPIDJSON_UINT64_C2(0x80000000, 0));
1314 SetValueByPointer(d, "/foo/int64", i64, a);
1315 EXPECT_EQ(i64, GetValueByPointer(d, "/foo/int64")->GetInt64());
1316
1317 const uint64_t u64 = RAPIDJSON_UINT64_C2(0xFFFFFFFFF, 0xFFFFFFFFF);
1318 SetValueByPointer(d, "/foo/uint64", u64, a);
1319 EXPECT_EQ(u64, GetValueByPointer(d, "/foo/uint64")->GetUint64());
1320
1321 SetValueByPointer(d, "/foo/true", true, a);
1322 EXPECT_TRUE(GetValueByPointer(d, "/foo/true")->IsTrue());
1323
1324 SetValueByPointer(d, "/foo/false", false, a);
1325 EXPECT_TRUE(GetValueByPointer(d, "/foo/false")->IsFalse());
1326
1327 // StringRef version
1328 SetValueByPointer(d, "/foo/hello", "Hello", a);
1329 EXPECT_STREQ("Hello", GetValueByPointer(d, "/foo/hello")->GetString());
1330
1331 // Copy string version
1332 {
1333 char buffer[256];
1334 strcpy(buffer, "World");
1335 SetValueByPointer(d, "/foo/world", buffer, a);
1336 memset(buffer, 0, sizeof(buffer));
1337 }
1338 EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString());
1339
1340 #if RAPIDJSON_HAS_STDSTRING
1341 SetValueByPointer(d, "/foo/c++", std::string("C++"), a);
1342 EXPECT_STREQ("C++", GetValueByPointer(d, "/foo/c++")->GetString());
1343 #endif
1344 }
1345
TEST(Pointer,SetValueByPointer_Pointer_NoAllocator)1346 TEST(Pointer, SetValueByPointer_Pointer_NoAllocator) {
1347 Document d;
1348 d.Parse(kJson);
1349
1350 // Value version
1351 SetValueByPointer(d, Pointer("/foo/0"), Value(123).Move());
1352 EXPECT_EQ(123, d["foo"][0].GetInt());
1353
1354 SetValueByPointer(d, Pointer("/foo/null"), Value().Move());
1355 EXPECT_TRUE(GetValueByPointer(d, "/foo/null")->IsNull());
1356
1357 // Const Value version
1358 const Value foo(d["foo"], d.GetAllocator());
1359 SetValueByPointer(d, Pointer("/clone"), foo);
1360 EXPECT_EQ(foo, *GetValueByPointer(d, "/clone"));
1361
1362 // Generic version
1363 SetValueByPointer(d, Pointer("/foo/int"), -1);
1364 EXPECT_EQ(-1, GetValueByPointer(d, "/foo/int")->GetInt());
1365
1366 SetValueByPointer(d, Pointer("/foo/uint"), 0x87654321);
1367 EXPECT_EQ(0x87654321, GetValueByPointer(d, "/foo/uint")->GetUint());
1368
1369 const int64_t i64 = static_cast<int64_t>(RAPIDJSON_UINT64_C2(0x80000000, 0));
1370 SetValueByPointer(d, Pointer("/foo/int64"), i64);
1371 EXPECT_EQ(i64, GetValueByPointer(d, "/foo/int64")->GetInt64());
1372
1373 const uint64_t u64 = RAPIDJSON_UINT64_C2(0xFFFFFFFFF, 0xFFFFFFFFF);
1374 SetValueByPointer(d, Pointer("/foo/uint64"), u64);
1375 EXPECT_EQ(u64, GetValueByPointer(d, "/foo/uint64")->GetUint64());
1376
1377 SetValueByPointer(d, Pointer("/foo/true"), true);
1378 EXPECT_TRUE(GetValueByPointer(d, "/foo/true")->IsTrue());
1379
1380 SetValueByPointer(d, Pointer("/foo/false"), false);
1381 EXPECT_TRUE(GetValueByPointer(d, "/foo/false")->IsFalse());
1382
1383 // StringRef version
1384 SetValueByPointer(d, Pointer("/foo/hello"), "Hello");
1385 EXPECT_STREQ("Hello", GetValueByPointer(d, "/foo/hello")->GetString());
1386
1387 // Copy string version
1388 {
1389 char buffer[256];
1390 strcpy(buffer, "World");
1391 SetValueByPointer(d, Pointer("/foo/world"), buffer);
1392 memset(buffer, 0, sizeof(buffer));
1393 }
1394 EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString());
1395
1396 #if RAPIDJSON_HAS_STDSTRING
1397 SetValueByPointer(d, Pointer("/foo/c++"), std::string("C++"));
1398 EXPECT_STREQ("C++", GetValueByPointer(d, "/foo/c++")->GetString());
1399 #endif
1400 }
1401
TEST(Pointer,SetValueByPointer_String_NoAllocator)1402 TEST(Pointer, SetValueByPointer_String_NoAllocator) {
1403 Document d;
1404 d.Parse(kJson);
1405
1406 // Value version
1407 SetValueByPointer(d, "/foo/0", Value(123).Move());
1408 EXPECT_EQ(123, d["foo"][0].GetInt());
1409
1410 SetValueByPointer(d, "/foo/null", Value().Move());
1411 EXPECT_TRUE(GetValueByPointer(d, "/foo/null")->IsNull());
1412
1413 // Const Value version
1414 const Value foo(d["foo"], d.GetAllocator());
1415 SetValueByPointer(d, "/clone", foo);
1416 EXPECT_EQ(foo, *GetValueByPointer(d, "/clone"));
1417
1418 // Generic version
1419 SetValueByPointer(d, "/foo/int", -1);
1420 EXPECT_EQ(-1, GetValueByPointer(d, "/foo/int")->GetInt());
1421
1422 SetValueByPointer(d, "/foo/uint", 0x87654321);
1423 EXPECT_EQ(0x87654321, GetValueByPointer(d, "/foo/uint")->GetUint());
1424
1425 const int64_t i64 = static_cast<int64_t>(RAPIDJSON_UINT64_C2(0x80000000, 0));
1426 SetValueByPointer(d, "/foo/int64", i64);
1427 EXPECT_EQ(i64, GetValueByPointer(d, "/foo/int64")->GetInt64());
1428
1429 const uint64_t u64 = RAPIDJSON_UINT64_C2(0xFFFFFFFFF, 0xFFFFFFFFF);
1430 SetValueByPointer(d, "/foo/uint64", u64);
1431 EXPECT_EQ(u64, GetValueByPointer(d, "/foo/uint64")->GetUint64());
1432
1433 SetValueByPointer(d, "/foo/true", true);
1434 EXPECT_TRUE(GetValueByPointer(d, "/foo/true")->IsTrue());
1435
1436 SetValueByPointer(d, "/foo/false", false);
1437 EXPECT_TRUE(GetValueByPointer(d, "/foo/false")->IsFalse());
1438
1439 // StringRef version
1440 SetValueByPointer(d, "/foo/hello", "Hello");
1441 EXPECT_STREQ("Hello", GetValueByPointer(d, "/foo/hello")->GetString());
1442
1443 // Copy string version
1444 {
1445 char buffer[256];
1446 strcpy(buffer, "World");
1447 SetValueByPointer(d, "/foo/world", buffer);
1448 memset(buffer, 0, sizeof(buffer));
1449 }
1450 EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString());
1451
1452 #if RAPIDJSON_HAS_STDSTRING
1453 SetValueByPointer(d, "/foo/c++", std::string("C++"));
1454 EXPECT_STREQ("C++", GetValueByPointer(d, "/foo/c++")->GetString());
1455 #endif
1456 }
1457
TEST(Pointer,SwapValueByPointer)1458 TEST(Pointer, SwapValueByPointer) {
1459 Document d;
1460 d.Parse(kJson);
1461 Document::AllocatorType& a = d.GetAllocator();
1462 SwapValueByPointer(d, Pointer("/foo/0"), *GetValueByPointer(d, "/foo/1"), a);
1463 EXPECT_STREQ("baz", d["foo"][0].GetString());
1464 EXPECT_STREQ("bar", d["foo"][1].GetString());
1465
1466 SwapValueByPointer(d, "/foo/0", *GetValueByPointer(d, "/foo/1"), a);
1467 EXPECT_STREQ("bar", d["foo"][0].GetString());
1468 EXPECT_STREQ("baz", d["foo"][1].GetString());
1469 }
1470
TEST(Pointer,SwapValueByPointer_NoAllocator)1471 TEST(Pointer, SwapValueByPointer_NoAllocator) {
1472 Document d;
1473 d.Parse(kJson);
1474 SwapValueByPointer(d, Pointer("/foo/0"), *GetValueByPointer(d, "/foo/1"));
1475 EXPECT_STREQ("baz", d["foo"][0].GetString());
1476 EXPECT_STREQ("bar", d["foo"][1].GetString());
1477
1478 SwapValueByPointer(d, "/foo/0", *GetValueByPointer(d, "/foo/1"));
1479 EXPECT_STREQ("bar", d["foo"][0].GetString());
1480 EXPECT_STREQ("baz", d["foo"][1].GetString());
1481 }
1482
TEST(Pointer,EraseValueByPointer_Pointer)1483 TEST(Pointer, EraseValueByPointer_Pointer) {
1484 Document d;
1485 d.Parse(kJson);
1486
1487 EXPECT_FALSE(EraseValueByPointer(d, Pointer("")));
1488 EXPECT_FALSE(Pointer("/foo/nonexist").Erase(d));
1489 EXPECT_TRUE(EraseValueByPointer(d, Pointer("/foo/0")));
1490 EXPECT_EQ(1u, d["foo"].Size());
1491 EXPECT_STREQ("baz", d["foo"][0].GetString());
1492 EXPECT_TRUE(EraseValueByPointer(d, Pointer("/foo/0")));
1493 EXPECT_TRUE(d["foo"].Empty());
1494 EXPECT_TRUE(EraseValueByPointer(d, Pointer("/foo")));
1495 EXPECT_TRUE(Pointer("/foo").Get(d) == 0);
1496 }
1497
TEST(Pointer,EraseValueByPointer_String)1498 TEST(Pointer, EraseValueByPointer_String) {
1499 Document d;
1500 d.Parse(kJson);
1501
1502 EXPECT_FALSE(EraseValueByPointer(d, ""));
1503 EXPECT_FALSE(Pointer("/foo/nonexist").Erase(d));
1504 EXPECT_TRUE(EraseValueByPointer(d, "/foo/0"));
1505 EXPECT_EQ(1u, d["foo"].Size());
1506 EXPECT_STREQ("baz", d["foo"][0].GetString());
1507 EXPECT_TRUE(EraseValueByPointer(d, "/foo/0"));
1508 EXPECT_TRUE(d["foo"].Empty());
1509 EXPECT_TRUE(EraseValueByPointer(d, "/foo"));
1510 EXPECT_TRUE(Pointer("/foo").Get(d) == 0);
1511 }
1512
TEST(Pointer,Ambiguity)1513 TEST(Pointer, Ambiguity) {
1514 {
1515 Document d;
1516 d.Parse("{\"0\" : [123]}");
1517 EXPECT_EQ(123, Pointer("/0/0").Get(d)->GetInt());
1518 Pointer("/0/a").Set(d, 456); // Change array [123] to object {456}
1519 EXPECT_EQ(456, Pointer("/0/a").Get(d)->GetInt());
1520 }
1521
1522 {
1523 Document d;
1524 EXPECT_FALSE(d.Parse("[{\"0\": 123}]").HasParseError());
1525 EXPECT_EQ(123, Pointer("/0/0").Get(d)->GetInt());
1526 Pointer("/0/1").Set(d, 456); // 1 is treated as "1" to index object
1527 EXPECT_EQ(123, Pointer("/0/0").Get(d)->GetInt());
1528 EXPECT_EQ(456, Pointer("/0/1").Get(d)->GetInt());
1529 }
1530 }
1531
TEST(Pointer,LessThan)1532 TEST(Pointer, LessThan) {
1533 static const struct {
1534 const char *str;
1535 bool valid;
1536 } pointers[] = {
1537 { "/a/b", true },
1538 { "/a", true },
1539 { "/d/1", true },
1540 { "/d/2/z", true },
1541 { "/d/2/3", true },
1542 { "/d/2", true },
1543 { "/a/c", true },
1544 { "/e/f~g", false },
1545 { "/d/2/zz", true },
1546 { "/d/1", true },
1547 { "/d/2/z", true },
1548 { "/e/f~~g", false },
1549 { "/e/f~0g", true },
1550 { "/e/f~1g", true },
1551 { "/e/f.g", true },
1552 { "", true }
1553 };
1554 static const char *ordered_pointers[] = {
1555 "",
1556 "/a",
1557 "/a/b",
1558 "/a/c",
1559 "/d/1",
1560 "/d/1",
1561 "/d/2",
1562 "/e/f.g",
1563 "/e/f~1g",
1564 "/e/f~0g",
1565 "/d/2/3",
1566 "/d/2/z",
1567 "/d/2/z",
1568 "/d/2/zz",
1569 NULL, // was invalid "/e/f~g"
1570 NULL // was invalid "/e/f~~g"
1571 };
1572 typedef MemoryPoolAllocator<> AllocatorType;
1573 typedef GenericPointer<Value, AllocatorType> PointerType;
1574 typedef std::multimap<PointerType, size_t> PointerMap;
1575 PointerMap map;
1576 PointerMap::iterator it;
1577 AllocatorType allocator;
1578 size_t i;
1579
1580 EXPECT_EQ(sizeof(pointers) / sizeof(pointers[0]),
1581 sizeof(ordered_pointers) / sizeof(ordered_pointers[0]));
1582
1583 for (i = 0; i < sizeof(pointers) / sizeof(pointers[0]); ++i) {
1584 it = map.insert(PointerMap::value_type(PointerType(pointers[i].str, &allocator), i));
1585 if (!it->first.IsValid()) {
1586 EXPECT_EQ(++it, map.end());
1587 }
1588 }
1589
1590 for (i = 0, it = map.begin(); it != map.end(); ++it, ++i) {
1591 EXPECT_TRUE(it->second < sizeof(pointers) / sizeof(pointers[0]));
1592 EXPECT_EQ(it->first.IsValid(), pointers[it->second].valid);
1593 EXPECT_TRUE(i < sizeof(ordered_pointers) / sizeof(ordered_pointers[0]));
1594 EXPECT_EQ(it->first.IsValid(), !!ordered_pointers[i]);
1595 if (it->first.IsValid()) {
1596 std::stringstream ss;
1597 OStreamWrapper os(ss);
1598 EXPECT_TRUE(it->first.Stringify(os));
1599 EXPECT_EQ(ss.str(), pointers[it->second].str);
1600 EXPECT_EQ(ss.str(), ordered_pointers[i]);
1601 }
1602 }
1603 }
1604
1605 // https://github.com/Tencent/rapidjson/issues/483
1606 namespace myjson {
1607
1608 class MyAllocator
1609 {
1610 public:
1611 static const bool kNeedFree = true;
Malloc(size_t _size)1612 void * Malloc(size_t _size) { return malloc(_size); }
Realloc(void * _org_p,size_t _org_size,size_t _new_size)1613 void * Realloc(void *_org_p, size_t _org_size, size_t _new_size) { (void)_org_size; return realloc(_org_p, _new_size); }
Free(void * _p)1614 static void Free(void *_p) { return free(_p); }
1615 };
1616
1617 typedef rapidjson::GenericDocument<
1618 rapidjson::UTF8<>,
1619 rapidjson::MemoryPoolAllocator< MyAllocator >,
1620 MyAllocator
1621 > Document;
1622
1623 typedef rapidjson::GenericPointer<
1624 ::myjson::Document::ValueType,
1625 MyAllocator
1626 > Pointer;
1627
1628 typedef ::myjson::Document::ValueType Value;
1629
1630 }
1631
TEST(Pointer,Issue483)1632 TEST(Pointer, Issue483) {
1633 std::string mystr, path;
1634 myjson::Document document;
1635 myjson::Value value(rapidjson::kStringType);
1636 value.SetString(mystr.c_str(), static_cast<SizeType>(mystr.length()), document.GetAllocator());
1637 myjson::Pointer(path.c_str()).Set(document, value, document.GetAllocator());
1638 }
1639