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 <sstream>
19
20 using namespace rapidjson;
21
22 static const char kJson[] = "{\n"
23 " \"foo\":[\"bar\", \"baz\"],\n"
24 " \"\" : 0,\n"
25 " \"a/b\" : 1,\n"
26 " \"c%d\" : 2,\n"
27 " \"e^f\" : 3,\n"
28 " \"g|h\" : 4,\n"
29 " \"i\\\\j\" : 5,\n"
30 " \"k\\\"l\" : 6,\n"
31 " \" \" : 7,\n"
32 " \"m~n\" : 8\n"
33 "}";
34
TEST(Pointer,Parse)35 TEST(Pointer, Parse) {
36 {
37 Pointer p("");
38 EXPECT_TRUE(p.IsValid());
39 EXPECT_EQ(0u, p.GetTokenCount());
40 }
41
42 {
43 Pointer p("/");
44 EXPECT_TRUE(p.IsValid());
45 EXPECT_EQ(1u, p.GetTokenCount());
46 EXPECT_EQ(0u, p.GetTokens()[0].length);
47 EXPECT_STREQ("", p.GetTokens()[0].name);
48 EXPECT_EQ(kPointerInvalidIndex, p.GetTokens()[0].index);
49 }
50
51 {
52 Pointer p("/foo");
53 EXPECT_TRUE(p.IsValid());
54 EXPECT_EQ(1u, p.GetTokenCount());
55 EXPECT_EQ(3u, p.GetTokens()[0].length);
56 EXPECT_STREQ("foo", p.GetTokens()[0].name);
57 EXPECT_EQ(kPointerInvalidIndex, p.GetTokens()[0].index);
58 }
59
60 #if RAPIDJSON_HAS_STDSTRING
61 {
62 Pointer p(std::string("/foo"));
63 EXPECT_TRUE(p.IsValid());
64 EXPECT_EQ(1u, p.GetTokenCount());
65 EXPECT_EQ(3u, p.GetTokens()[0].length);
66 EXPECT_STREQ("foo", p.GetTokens()[0].name);
67 EXPECT_EQ(kPointerInvalidIndex, p.GetTokens()[0].index);
68 }
69 #endif
70
71 {
72 Pointer p("/foo/0");
73 EXPECT_TRUE(p.IsValid());
74 EXPECT_EQ(2u, p.GetTokenCount());
75 EXPECT_EQ(3u, p.GetTokens()[0].length);
76 EXPECT_STREQ("foo", p.GetTokens()[0].name);
77 EXPECT_EQ(kPointerInvalidIndex, p.GetTokens()[0].index);
78 EXPECT_EQ(1u, p.GetTokens()[1].length);
79 EXPECT_STREQ("0", p.GetTokens()[1].name);
80 EXPECT_EQ(0u, p.GetTokens()[1].index);
81 }
82
83 {
84 // Unescape ~1
85 Pointer p("/a~1b");
86 EXPECT_TRUE(p.IsValid());
87 EXPECT_EQ(1u, p.GetTokenCount());
88 EXPECT_EQ(3u, p.GetTokens()[0].length);
89 EXPECT_STREQ("a/b", p.GetTokens()[0].name);
90 }
91
92 {
93 // Unescape ~0
94 Pointer p("/m~0n");
95 EXPECT_TRUE(p.IsValid());
96 EXPECT_EQ(1u, p.GetTokenCount());
97 EXPECT_EQ(3u, p.GetTokens()[0].length);
98 EXPECT_STREQ("m~n", p.GetTokens()[0].name);
99 }
100
101 {
102 // empty name
103 Pointer p("/");
104 EXPECT_TRUE(p.IsValid());
105 EXPECT_EQ(1u, p.GetTokenCount());
106 EXPECT_EQ(0u, p.GetTokens()[0].length);
107 EXPECT_STREQ("", p.GetTokens()[0].name);
108 }
109
110 {
111 // empty and non-empty name
112 Pointer p("//a");
113 EXPECT_TRUE(p.IsValid());
114 EXPECT_EQ(2u, p.GetTokenCount());
115 EXPECT_EQ(0u, p.GetTokens()[0].length);
116 EXPECT_STREQ("", p.GetTokens()[0].name);
117 EXPECT_EQ(1u, p.GetTokens()[1].length);
118 EXPECT_STREQ("a", p.GetTokens()[1].name);
119 }
120
121 {
122 // Null characters
123 Pointer p("/\0\0", 3);
124 EXPECT_TRUE(p.IsValid());
125 EXPECT_EQ(1u, p.GetTokenCount());
126 EXPECT_EQ(2u, p.GetTokens()[0].length);
127 EXPECT_EQ('\0', p.GetTokens()[0].name[0]);
128 EXPECT_EQ('\0', p.GetTokens()[0].name[1]);
129 EXPECT_EQ('\0', p.GetTokens()[0].name[2]);
130 }
131
132 {
133 // Valid index
134 Pointer p("/123");
135 EXPECT_TRUE(p.IsValid());
136 EXPECT_EQ(1u, p.GetTokenCount());
137 EXPECT_STREQ("123", p.GetTokens()[0].name);
138 EXPECT_EQ(123u, p.GetTokens()[0].index);
139 }
140
141 {
142 // Invalid index (with leading zero)
143 Pointer p("/01");
144 EXPECT_TRUE(p.IsValid());
145 EXPECT_EQ(1u, p.GetTokenCount());
146 EXPECT_STREQ("01", p.GetTokens()[0].name);
147 EXPECT_EQ(kPointerInvalidIndex, p.GetTokens()[0].index);
148 }
149
150 if (sizeof(SizeType) == 4) {
151 // Invalid index (overflow)
152 Pointer p("/4294967296");
153 EXPECT_TRUE(p.IsValid());
154 EXPECT_EQ(1u, p.GetTokenCount());
155 EXPECT_STREQ("4294967296", p.GetTokens()[0].name);
156 EXPECT_EQ(kPointerInvalidIndex, p.GetTokens()[0].index);
157 }
158
159 {
160 // kPointerParseErrorTokenMustBeginWithSolidus
161 Pointer p(" ");
162 EXPECT_FALSE(p.IsValid());
163 EXPECT_EQ(kPointerParseErrorTokenMustBeginWithSolidus, p.GetParseErrorCode());
164 EXPECT_EQ(0u, p.GetParseErrorOffset());
165 }
166
167 {
168 // kPointerParseErrorInvalidEscape
169 Pointer p("/~");
170 EXPECT_FALSE(p.IsValid());
171 EXPECT_EQ(kPointerParseErrorInvalidEscape, p.GetParseErrorCode());
172 EXPECT_EQ(2u, p.GetParseErrorOffset());
173 }
174
175 {
176 // kPointerParseErrorInvalidEscape
177 Pointer p("/~2");
178 EXPECT_FALSE(p.IsValid());
179 EXPECT_EQ(kPointerParseErrorInvalidEscape, p.GetParseErrorCode());
180 EXPECT_EQ(2u, p.GetParseErrorOffset());
181 }
182 }
183
TEST(Pointer,Parse_URIFragment)184 TEST(Pointer, Parse_URIFragment) {
185 {
186 Pointer p("#");
187 EXPECT_TRUE(p.IsValid());
188 EXPECT_EQ(0u, p.GetTokenCount());
189 }
190
191 {
192 Pointer p("#/foo");
193 EXPECT_TRUE(p.IsValid());
194 EXPECT_EQ(1u, p.GetTokenCount());
195 EXPECT_EQ(3u, p.GetTokens()[0].length);
196 EXPECT_STREQ("foo", p.GetTokens()[0].name);
197 }
198
199 {
200 Pointer p("#/foo/0");
201 EXPECT_TRUE(p.IsValid());
202 EXPECT_EQ(2u, p.GetTokenCount());
203 EXPECT_EQ(3u, p.GetTokens()[0].length);
204 EXPECT_STREQ("foo", p.GetTokens()[0].name);
205 EXPECT_EQ(1u, p.GetTokens()[1].length);
206 EXPECT_STREQ("0", p.GetTokens()[1].name);
207 EXPECT_EQ(0u, p.GetTokens()[1].index);
208 }
209
210 {
211 // Unescape ~1
212 Pointer p("#/a~1b");
213 EXPECT_TRUE(p.IsValid());
214 EXPECT_EQ(1u, p.GetTokenCount());
215 EXPECT_EQ(3u, p.GetTokens()[0].length);
216 EXPECT_STREQ("a/b", p.GetTokens()[0].name);
217 }
218
219 {
220 // Unescape ~0
221 Pointer p("#/m~0n");
222 EXPECT_TRUE(p.IsValid());
223 EXPECT_EQ(1u, p.GetTokenCount());
224 EXPECT_EQ(3u, p.GetTokens()[0].length);
225 EXPECT_STREQ("m~n", p.GetTokens()[0].name);
226 }
227
228 {
229 // empty name
230 Pointer p("#/");
231 EXPECT_TRUE(p.IsValid());
232 EXPECT_EQ(1u, p.GetTokenCount());
233 EXPECT_EQ(0u, p.GetTokens()[0].length);
234 EXPECT_STREQ("", p.GetTokens()[0].name);
235 }
236
237 {
238 // empty and non-empty name
239 Pointer p("#//a");
240 EXPECT_TRUE(p.IsValid());
241 EXPECT_EQ(2u, p.GetTokenCount());
242 EXPECT_EQ(0u, p.GetTokens()[0].length);
243 EXPECT_STREQ("", p.GetTokens()[0].name);
244 EXPECT_EQ(1u, p.GetTokens()[1].length);
245 EXPECT_STREQ("a", p.GetTokens()[1].name);
246 }
247
248 {
249 // Null characters
250 Pointer p("#/%00%00");
251 EXPECT_TRUE(p.IsValid());
252 EXPECT_EQ(1u, p.GetTokenCount());
253 EXPECT_EQ(2u, p.GetTokens()[0].length);
254 EXPECT_EQ('\0', p.GetTokens()[0].name[0]);
255 EXPECT_EQ('\0', p.GetTokens()[0].name[1]);
256 EXPECT_EQ('\0', p.GetTokens()[0].name[2]);
257 }
258
259 {
260 // Percentage Escapes
261 EXPECT_STREQ("c%d", Pointer("#/c%25d").GetTokens()[0].name);
262 EXPECT_STREQ("e^f", Pointer("#/e%5Ef").GetTokens()[0].name);
263 EXPECT_STREQ("g|h", Pointer("#/g%7Ch").GetTokens()[0].name);
264 EXPECT_STREQ("i\\j", Pointer("#/i%5Cj").GetTokens()[0].name);
265 EXPECT_STREQ("k\"l", Pointer("#/k%22l").GetTokens()[0].name);
266 EXPECT_STREQ(" ", Pointer("#/%20").GetTokens()[0].name);
267 }
268
269 {
270 // Valid index
271 Pointer p("#/123");
272 EXPECT_TRUE(p.IsValid());
273 EXPECT_EQ(1u, p.GetTokenCount());
274 EXPECT_STREQ("123", p.GetTokens()[0].name);
275 EXPECT_EQ(123u, p.GetTokens()[0].index);
276 }
277
278 {
279 // Invalid index (with leading zero)
280 Pointer p("#/01");
281 EXPECT_TRUE(p.IsValid());
282 EXPECT_EQ(1u, p.GetTokenCount());
283 EXPECT_STREQ("01", p.GetTokens()[0].name);
284 EXPECT_EQ(kPointerInvalidIndex, p.GetTokens()[0].index);
285 }
286
287 if (sizeof(SizeType) == 4) {
288 // Invalid index (overflow)
289 Pointer p("#/4294967296");
290 EXPECT_TRUE(p.IsValid());
291 EXPECT_EQ(1u, p.GetTokenCount());
292 EXPECT_STREQ("4294967296", p.GetTokens()[0].name);
293 EXPECT_EQ(kPointerInvalidIndex, p.GetTokens()[0].index);
294 }
295
296 {
297 // Decode UTF-8 perecent encoding to UTF-8
298 Pointer p("#/%C2%A2");
299 EXPECT_TRUE(p.IsValid());
300 EXPECT_EQ(1u, p.GetTokenCount());
301 EXPECT_STREQ("\xC2\xA2", p.GetTokens()[0].name);
302 }
303
304 {
305 // Decode UTF-8 perecent encoding to UTF-16
306 GenericPointer<GenericValue<UTF16<> > > p(L"#/%C2%A2");
307 EXPECT_TRUE(p.IsValid());
308 EXPECT_EQ(1u, p.GetTokenCount());
309 EXPECT_EQ(0x00A2, p.GetTokens()[0].name[0]);
310 EXPECT_EQ(1u, p.GetTokens()[0].length);
311 }
312
313 {
314 // Decode UTF-8 perecent encoding to UTF-16
315 GenericPointer<GenericValue<UTF16<> > > p(L"#/%E2%82%AC");
316 EXPECT_TRUE(p.IsValid());
317 EXPECT_EQ(1u, p.GetTokenCount());
318 EXPECT_EQ(0x20AC, p.GetTokens()[0].name[0]);
319 EXPECT_EQ(1u, p.GetTokens()[0].length);
320 }
321
322 {
323 // kPointerParseErrorTokenMustBeginWithSolidus
324 Pointer p("# ");
325 EXPECT_FALSE(p.IsValid());
326 EXPECT_EQ(kPointerParseErrorTokenMustBeginWithSolidus, p.GetParseErrorCode());
327 EXPECT_EQ(1u, p.GetParseErrorOffset());
328 }
329
330 {
331 // kPointerParseErrorInvalidEscape
332 Pointer p("#/~");
333 EXPECT_FALSE(p.IsValid());
334 EXPECT_EQ(kPointerParseErrorInvalidEscape, p.GetParseErrorCode());
335 EXPECT_EQ(3u, p.GetParseErrorOffset());
336 }
337
338 {
339 // kPointerParseErrorInvalidEscape
340 Pointer p("#/~2");
341 EXPECT_FALSE(p.IsValid());
342 EXPECT_EQ(kPointerParseErrorInvalidEscape, p.GetParseErrorCode());
343 EXPECT_EQ(3u, p.GetParseErrorOffset());
344 }
345
346 {
347 // kPointerParseErrorInvalidPercentEncoding
348 Pointer p("#/%");
349 EXPECT_FALSE(p.IsValid());
350 EXPECT_EQ(kPointerParseErrorInvalidPercentEncoding, p.GetParseErrorCode());
351 EXPECT_EQ(2u, p.GetParseErrorOffset());
352 }
353
354 {
355 // kPointerParseErrorInvalidPercentEncoding (invalid hex)
356 Pointer p("#/%g0");
357 EXPECT_FALSE(p.IsValid());
358 EXPECT_EQ(kPointerParseErrorInvalidPercentEncoding, p.GetParseErrorCode());
359 EXPECT_EQ(2u, p.GetParseErrorOffset());
360 }
361
362 {
363 // kPointerParseErrorInvalidPercentEncoding (invalid hex)
364 Pointer p("#/%0g");
365 EXPECT_FALSE(p.IsValid());
366 EXPECT_EQ(kPointerParseErrorInvalidPercentEncoding, p.GetParseErrorCode());
367 EXPECT_EQ(2u, p.GetParseErrorOffset());
368 }
369
370 {
371 // kPointerParseErrorInvalidPercentEncoding (incomplete UTF-8 sequence)
372 Pointer p("#/%C2");
373 EXPECT_FALSE(p.IsValid());
374 EXPECT_EQ(kPointerParseErrorInvalidPercentEncoding, p.GetParseErrorCode());
375 EXPECT_EQ(2u, p.GetParseErrorOffset());
376 }
377
378 {
379 // kPointerParseErrorCharacterMustPercentEncode
380 Pointer p("#/ ");
381 EXPECT_FALSE(p.IsValid());
382 EXPECT_EQ(kPointerParseErrorCharacterMustPercentEncode, p.GetParseErrorCode());
383 EXPECT_EQ(2u, p.GetParseErrorOffset());
384 }
385
386 {
387 // kPointerParseErrorCharacterMustPercentEncode
388 Pointer p("#/\n");
389 EXPECT_FALSE(p.IsValid());
390 EXPECT_EQ(kPointerParseErrorCharacterMustPercentEncode, p.GetParseErrorCode());
391 EXPECT_EQ(2u, p.GetParseErrorOffset());
392 }
393 }
394
TEST(Pointer,Stringify)395 TEST(Pointer, Stringify) {
396 // Test by roundtrip
397 const char* sources[] = {
398 "",
399 "/foo",
400 "/foo/0",
401 "/",
402 "/a~1b",
403 "/c%d",
404 "/e^f",
405 "/g|h",
406 "/i\\j",
407 "/k\"l",
408 "/ ",
409 "/m~0n",
410 "/\xC2\xA2",
411 "/\xE2\x82\xAC",
412 "/\xF0\x9D\x84\x9E"
413 };
414
415 for (size_t i = 0; i < sizeof(sources) / sizeof(sources[0]); i++) {
416 Pointer p(sources[i]);
417 StringBuffer s;
418 EXPECT_TRUE(p.Stringify(s));
419 EXPECT_STREQ(sources[i], s.GetString());
420
421 // Stringify to URI fragment
422 StringBuffer s2;
423 EXPECT_TRUE(p.StringifyUriFragment(s2));
424 Pointer p2(s2.GetString(), s2.GetSize());
425 EXPECT_TRUE(p2.IsValid());
426 EXPECT_TRUE(p == p2);
427 }
428
429 {
430 // Strigify to URI fragment with an invalid UTF-8 sequence
431 Pointer p("/\xC2");
432 StringBuffer s;
433 EXPECT_FALSE(p.StringifyUriFragment(s));
434 }
435 }
436
437 // Construct a Pointer with static tokens, no dynamic allocation involved.
438 #define NAME(s) { s, sizeof(s) / sizeof(s[0]) - 1, kPointerInvalidIndex }
439 #define INDEX(i) { #i, sizeof(#i) - 1, i }
440
441 static const Pointer::Token kTokens[] = { NAME("foo"), INDEX(0) }; // equivalent to "/foo/0"
442
443 #undef NAME
444 #undef INDEX
445
TEST(Pointer,ConstructorWithToken)446 TEST(Pointer, ConstructorWithToken) {
447 Pointer p(kTokens, sizeof(kTokens) / sizeof(kTokens[0]));
448 EXPECT_TRUE(p.IsValid());
449 EXPECT_EQ(2u, p.GetTokenCount());
450 EXPECT_EQ(3u, p.GetTokens()[0].length);
451 EXPECT_STREQ("foo", p.GetTokens()[0].name);
452 EXPECT_EQ(1u, p.GetTokens()[1].length);
453 EXPECT_STREQ("0", p.GetTokens()[1].name);
454 EXPECT_EQ(0u, p.GetTokens()[1].index);
455 }
456
TEST(Pointer,CopyConstructor)457 TEST(Pointer, CopyConstructor) {
458 {
459 Pointer p("/foo/0");
460 Pointer q(p);
461 EXPECT_TRUE(q.IsValid());
462 EXPECT_EQ(2u, q.GetTokenCount());
463 EXPECT_EQ(3u, q.GetTokens()[0].length);
464 EXPECT_STREQ("foo", q.GetTokens()[0].name);
465 EXPECT_EQ(1u, q.GetTokens()[1].length);
466 EXPECT_STREQ("0", q.GetTokens()[1].name);
467 EXPECT_EQ(0u, q.GetTokens()[1].index);
468 }
469
470 // Static tokens
471 {
472 Pointer p(kTokens, sizeof(kTokens) / sizeof(kTokens[0]));
473 Pointer q(p);
474 EXPECT_TRUE(q.IsValid());
475 EXPECT_EQ(2u, q.GetTokenCount());
476 EXPECT_EQ(3u, q.GetTokens()[0].length);
477 EXPECT_STREQ("foo", q.GetTokens()[0].name);
478 EXPECT_EQ(1u, q.GetTokens()[1].length);
479 EXPECT_STREQ("0", q.GetTokens()[1].name);
480 EXPECT_EQ(0u, q.GetTokens()[1].index);
481 }
482 }
483
TEST(Pointer,Assignment)484 TEST(Pointer, Assignment) {
485 {
486 Pointer p("/foo/0");
487 Pointer q;
488 q = p;
489 EXPECT_TRUE(q.IsValid());
490 EXPECT_EQ(2u, q.GetTokenCount());
491 EXPECT_EQ(3u, q.GetTokens()[0].length);
492 EXPECT_STREQ("foo", q.GetTokens()[0].name);
493 EXPECT_EQ(1u, q.GetTokens()[1].length);
494 EXPECT_STREQ("0", q.GetTokens()[1].name);
495 EXPECT_EQ(0u, q.GetTokens()[1].index);
496 q = q;
497 EXPECT_TRUE(q.IsValid());
498 EXPECT_EQ(2u, q.GetTokenCount());
499 EXPECT_EQ(3u, q.GetTokens()[0].length);
500 EXPECT_STREQ("foo", q.GetTokens()[0].name);
501 EXPECT_EQ(1u, q.GetTokens()[1].length);
502 EXPECT_STREQ("0", q.GetTokens()[1].name);
503 EXPECT_EQ(0u, q.GetTokens()[1].index);
504 }
505
506 // Static tokens
507 {
508 Pointer p(kTokens, sizeof(kTokens) / sizeof(kTokens[0]));
509 Pointer q;
510 q = p;
511 EXPECT_TRUE(q.IsValid());
512 EXPECT_EQ(2u, q.GetTokenCount());
513 EXPECT_EQ(3u, q.GetTokens()[0].length);
514 EXPECT_STREQ("foo", q.GetTokens()[0].name);
515 EXPECT_EQ(1u, q.GetTokens()[1].length);
516 EXPECT_STREQ("0", q.GetTokens()[1].name);
517 EXPECT_EQ(0u, q.GetTokens()[1].index);
518 }
519 }
520
TEST(Pointer,Append)521 TEST(Pointer, Append) {
522 {
523 Pointer p;
524 Pointer q = p.Append("foo");
525 EXPECT_TRUE(Pointer("/foo") == q);
526 q = q.Append(1234);
527 EXPECT_TRUE(Pointer("/foo/1234") == q);
528 q = q.Append("");
529 EXPECT_TRUE(Pointer("/foo/1234/") == q);
530 }
531
532 {
533 Pointer p;
534 Pointer q = p.Append(Value("foo").Move());
535 EXPECT_TRUE(Pointer("/foo") == q);
536 q = q.Append(Value(1234).Move());
537 EXPECT_TRUE(Pointer("/foo/1234") == q);
538 q = q.Append(Value(kStringType).Move());
539 EXPECT_TRUE(Pointer("/foo/1234/") == q);
540 }
541
542 #if RAPIDJSON_HAS_STDSTRING
543 {
544 Pointer p;
545 Pointer q = p.Append(std::string("foo"));
546 EXPECT_TRUE(Pointer("/foo") == q);
547 }
548 #endif
549 }
550
TEST(Pointer,Equality)551 TEST(Pointer, Equality) {
552 EXPECT_TRUE(Pointer("/foo/0") == Pointer("/foo/0"));
553 EXPECT_FALSE(Pointer("/foo/0") == Pointer("/foo/1"));
554 EXPECT_FALSE(Pointer("/foo/0") == Pointer("/foo/0/1"));
555 EXPECT_FALSE(Pointer("/foo/0") == Pointer("a"));
556 EXPECT_FALSE(Pointer("a") == Pointer("a")); // Invalid always not equal
557 }
558
TEST(Pointer,Inequality)559 TEST(Pointer, Inequality) {
560 EXPECT_FALSE(Pointer("/foo/0") != Pointer("/foo/0"));
561 EXPECT_TRUE(Pointer("/foo/0") != Pointer("/foo/1"));
562 EXPECT_TRUE(Pointer("/foo/0") != Pointer("/foo/0/1"));
563 EXPECT_TRUE(Pointer("/foo/0") != Pointer("a"));
564 EXPECT_TRUE(Pointer("a") != Pointer("a")); // Invalid always not equal
565 }
566
TEST(Pointer,Create)567 TEST(Pointer, Create) {
568 Document d;
569 {
570 Value* v = &Pointer("").Create(d, d.GetAllocator());
571 EXPECT_EQ(&d, v);
572 }
573 {
574 Value* v = &Pointer("/foo").Create(d, d.GetAllocator());
575 EXPECT_EQ(&d["foo"], v);
576 }
577 {
578 Value* v = &Pointer("/foo/0").Create(d, d.GetAllocator());
579 EXPECT_EQ(&d["foo"][0], v);
580 }
581 {
582 Value* v = &Pointer("/foo/-").Create(d, d.GetAllocator());
583 EXPECT_EQ(&d["foo"][1], v);
584 }
585
586 {
587 Value* v = &Pointer("/foo/-/-").Create(d, d.GetAllocator());
588 // "foo/-" is a newly created null value x.
589 // "foo/-/-" finds that x is not an array, it converts x to empty object
590 // and treats - as "-" member name
591 EXPECT_EQ(&d["foo"][2]["-"], v);
592 }
593
594 {
595 // Document with no allocator
596 Value* v = &Pointer("/foo/-").Create(d);
597 EXPECT_EQ(&d["foo"][3], v);
598 }
599
600 {
601 // Value (not document) must give allocator
602 Value* v = &Pointer("/-").Create(d["foo"], d.GetAllocator());
603 EXPECT_EQ(&d["foo"][4], v);
604 }
605 }
606
TEST(Pointer,Get)607 TEST(Pointer, Get) {
608 Document d;
609 d.Parse(kJson);
610
611 EXPECT_EQ(&d, Pointer("").Get(d));
612 EXPECT_EQ(&d["foo"], Pointer("/foo").Get(d));
613 EXPECT_EQ(&d["foo"][0], Pointer("/foo/0").Get(d));
614 EXPECT_EQ(&d[""], Pointer("/").Get(d));
615 EXPECT_EQ(&d["a/b"], Pointer("/a~1b").Get(d));
616 EXPECT_EQ(&d["c%d"], Pointer("/c%d").Get(d));
617 EXPECT_EQ(&d["e^f"], Pointer("/e^f").Get(d));
618 EXPECT_EQ(&d["g|h"], Pointer("/g|h").Get(d));
619 EXPECT_EQ(&d["i\\j"], Pointer("/i\\j").Get(d));
620 EXPECT_EQ(&d["k\"l"], Pointer("/k\"l").Get(d));
621 EXPECT_EQ(&d[" "], Pointer("/ ").Get(d));
622 EXPECT_EQ(&d["m~n"], Pointer("/m~0n").Get(d));
623 EXPECT_TRUE(Pointer("/abc").Get(d) == 0);
624 EXPECT_TRUE(Pointer("/foo/2").Get(d) == 0); // Out of boundary
625 EXPECT_TRUE(Pointer("/foo/a").Get(d) == 0); // "/foo" is an array, cannot query by "a"
626 EXPECT_TRUE(Pointer("/foo/0/0").Get(d) == 0); // "/foo/0" is an string, cannot further query
627 EXPECT_TRUE(Pointer("/foo/0/a").Get(d) == 0); // "/foo/0" is an string, cannot further query
628 }
629
TEST(Pointer,GetWithDefault)630 TEST(Pointer, GetWithDefault) {
631 Document d;
632 d.Parse(kJson);
633
634 // Value version
635 Document::AllocatorType& a = d.GetAllocator();
636 const Value v("qux");
637 EXPECT_TRUE(Value("bar") == Pointer("/foo/0").GetWithDefault(d, v, a));
638 EXPECT_TRUE(Value("baz") == Pointer("/foo/1").GetWithDefault(d, v, a));
639 EXPECT_TRUE(Value("qux") == Pointer("/foo/2").GetWithDefault(d, v, a));
640 EXPECT_TRUE(Value("last") == Pointer("/foo/-").GetWithDefault(d, Value("last").Move(), a));
641 EXPECT_STREQ("last", d["foo"][3].GetString());
642
643 EXPECT_TRUE(Pointer("/foo/null").GetWithDefault(d, Value().Move(), a).IsNull());
644 EXPECT_TRUE(Pointer("/foo/null").GetWithDefault(d, "x", a).IsNull());
645
646 // Generic version
647 EXPECT_EQ(-1, Pointer("/foo/int").GetWithDefault(d, -1, a).GetInt());
648 EXPECT_EQ(-1, Pointer("/foo/int").GetWithDefault(d, -2, a).GetInt());
649 EXPECT_EQ(0x87654321, Pointer("/foo/uint").GetWithDefault(d, 0x87654321, a).GetUint());
650 EXPECT_EQ(0x87654321, Pointer("/foo/uint").GetWithDefault(d, 0x12345678, a).GetUint());
651
652 const int64_t i64 = static_cast<int64_t>(RAPIDJSON_UINT64_C2(0x80000000, 0));
653 EXPECT_EQ(i64, Pointer("/foo/int64").GetWithDefault(d, i64, a).GetInt64());
654 EXPECT_EQ(i64, Pointer("/foo/int64").GetWithDefault(d, i64 + 1, a).GetInt64());
655
656 const uint64_t u64 = RAPIDJSON_UINT64_C2(0xFFFFFFFFF, 0xFFFFFFFFF);
657 EXPECT_EQ(u64, Pointer("/foo/uint64").GetWithDefault(d, u64, a).GetUint64());
658 EXPECT_EQ(u64, Pointer("/foo/uint64").GetWithDefault(d, u64 - 1, a).GetUint64());
659
660 EXPECT_TRUE(Pointer("/foo/true").GetWithDefault(d, true, a).IsTrue());
661 EXPECT_TRUE(Pointer("/foo/true").GetWithDefault(d, false, a).IsTrue());
662
663 EXPECT_TRUE(Pointer("/foo/false").GetWithDefault(d, false, a).IsFalse());
664 EXPECT_TRUE(Pointer("/foo/false").GetWithDefault(d, true, a).IsFalse());
665
666 // StringRef version
667 EXPECT_STREQ("Hello", Pointer("/foo/hello").GetWithDefault(d, "Hello", a).GetString());
668
669 // Copy string version
670 {
671 char buffer[256];
672 strcpy(buffer, "World");
673 EXPECT_STREQ("World", Pointer("/foo/world").GetWithDefault(d, buffer, a).GetString());
674 memset(buffer, 0, sizeof(buffer));
675 }
676 EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString());
677
678 #if RAPIDJSON_HAS_STDSTRING
679 EXPECT_STREQ("C++", Pointer("/foo/C++").GetWithDefault(d, std::string("C++"), a).GetString());
680 #endif
681 }
682
TEST(Pointer,GetWithDefault_NoAllocator)683 TEST(Pointer, GetWithDefault_NoAllocator) {
684 Document d;
685 d.Parse(kJson);
686
687 // Value version
688 const Value v("qux");
689 EXPECT_TRUE(Value("bar") == Pointer("/foo/0").GetWithDefault(d, v));
690 EXPECT_TRUE(Value("baz") == Pointer("/foo/1").GetWithDefault(d, v));
691 EXPECT_TRUE(Value("qux") == Pointer("/foo/2").GetWithDefault(d, v));
692 EXPECT_TRUE(Value("last") == Pointer("/foo/-").GetWithDefault(d, Value("last").Move()));
693 EXPECT_STREQ("last", d["foo"][3].GetString());
694
695 EXPECT_TRUE(Pointer("/foo/null").GetWithDefault(d, Value().Move()).IsNull());
696 EXPECT_TRUE(Pointer("/foo/null").GetWithDefault(d, "x").IsNull());
697
698 // Generic version
699 EXPECT_EQ(-1, Pointer("/foo/int").GetWithDefault(d, -1).GetInt());
700 EXPECT_EQ(-1, Pointer("/foo/int").GetWithDefault(d, -2).GetInt());
701 EXPECT_EQ(0x87654321, Pointer("/foo/uint").GetWithDefault(d, 0x87654321).GetUint());
702 EXPECT_EQ(0x87654321, Pointer("/foo/uint").GetWithDefault(d, 0x12345678).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).GetInt64());
706 EXPECT_EQ(i64, Pointer("/foo/int64").GetWithDefault(d, i64 + 1).GetInt64());
707
708 const uint64_t u64 = RAPIDJSON_UINT64_C2(0xFFFFFFFFF, 0xFFFFFFFFF);
709 EXPECT_EQ(u64, Pointer("/foo/uint64").GetWithDefault(d, u64).GetUint64());
710 EXPECT_EQ(u64, Pointer("/foo/uint64").GetWithDefault(d, u64 - 1).GetUint64());
711
712 EXPECT_TRUE(Pointer("/foo/true").GetWithDefault(d, true).IsTrue());
713 EXPECT_TRUE(Pointer("/foo/true").GetWithDefault(d, false).IsTrue());
714
715 EXPECT_TRUE(Pointer("/foo/false").GetWithDefault(d, false).IsFalse());
716 EXPECT_TRUE(Pointer("/foo/false").GetWithDefault(d, true).IsFalse());
717
718 // StringRef version
719 EXPECT_STREQ("Hello", Pointer("/foo/hello").GetWithDefault(d, "Hello").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).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++")).GetString());
732 #endif
733 }
734
TEST(Pointer,Set)735 TEST(Pointer, Set) {
736 Document d;
737 d.Parse(kJson);
738 Document::AllocatorType& a = d.GetAllocator();
739
740 // Value version
741 Pointer("/foo/0").Set(d, Value(123).Move(), a);
742 EXPECT_EQ(123, d["foo"][0].GetInt());
743
744 Pointer("/foo/-").Set(d, Value(456).Move(), a);
745 EXPECT_EQ(456, d["foo"][2].GetInt());
746
747 Pointer("/foo/null").Set(d, Value().Move(), a);
748 EXPECT_TRUE(GetValueByPointer(d, "/foo/null")->IsNull());
749
750 // Const Value version
751 const Value foo(d["foo"], a);
752 Pointer("/clone").Set(d, foo, a);
753 EXPECT_EQ(foo, *GetValueByPointer(d, "/clone"));
754
755 // Generic version
756 Pointer("/foo/int").Set(d, -1, a);
757 EXPECT_EQ(-1, GetValueByPointer(d, "/foo/int")->GetInt());
758
759 Pointer("/foo/uint").Set(d, 0x87654321, a);
760 EXPECT_EQ(0x87654321, GetValueByPointer(d, "/foo/uint")->GetUint());
761
762 const int64_t i64 = static_cast<int64_t>(RAPIDJSON_UINT64_C2(0x80000000, 0));
763 Pointer("/foo/int64").Set(d, i64, a);
764 EXPECT_EQ(i64, GetValueByPointer(d, "/foo/int64")->GetInt64());
765
766 const uint64_t u64 = RAPIDJSON_UINT64_C2(0xFFFFFFFFF, 0xFFFFFFFFF);
767 Pointer("/foo/uint64").Set(d, u64, a);
768 EXPECT_EQ(u64, GetValueByPointer(d, "/foo/uint64")->GetUint64());
769
770 Pointer("/foo/true").Set(d, true, a);
771 EXPECT_TRUE(GetValueByPointer(d, "/foo/true")->IsTrue());
772
773 Pointer("/foo/false").Set(d, false, a);
774 EXPECT_TRUE(GetValueByPointer(d, "/foo/false")->IsFalse());
775
776 // StringRef version
777 Pointer("/foo/hello").Set(d, "Hello", a);
778 EXPECT_STREQ("Hello", GetValueByPointer(d, "/foo/hello")->GetString());
779
780 // Copy string version
781 {
782 char buffer[256];
783 strcpy(buffer, "World");
784 Pointer("/foo/world").Set(d, buffer, a);
785 memset(buffer, 0, sizeof(buffer));
786 }
787 EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString());
788
789 #if RAPIDJSON_HAS_STDSTRING
790 Pointer("/foo/c++").Set(d, std::string("C++"), a);
791 EXPECT_STREQ("C++", GetValueByPointer(d, "/foo/c++")->GetString());
792 #endif
793 }
794
TEST(Pointer,Set_NoAllocator)795 TEST(Pointer, Set_NoAllocator) {
796 Document d;
797 d.Parse(kJson);
798
799 // Value version
800 Pointer("/foo/0").Set(d, Value(123).Move());
801 EXPECT_EQ(123, d["foo"][0].GetInt());
802
803 Pointer("/foo/-").Set(d, Value(456).Move());
804 EXPECT_EQ(456, d["foo"][2].GetInt());
805
806 Pointer("/foo/null").Set(d, Value().Move());
807 EXPECT_TRUE(GetValueByPointer(d, "/foo/null")->IsNull());
808
809 // Const Value version
810 const Value foo(d["foo"], d.GetAllocator());
811 Pointer("/clone").Set(d, foo);
812 EXPECT_EQ(foo, *GetValueByPointer(d, "/clone"));
813
814 // Generic version
815 Pointer("/foo/int").Set(d, -1);
816 EXPECT_EQ(-1, GetValueByPointer(d, "/foo/int")->GetInt());
817
818 Pointer("/foo/uint").Set(d, 0x87654321);
819 EXPECT_EQ(0x87654321, GetValueByPointer(d, "/foo/uint")->GetUint());
820
821 const int64_t i64 = static_cast<int64_t>(RAPIDJSON_UINT64_C2(0x80000000, 0));
822 Pointer("/foo/int64").Set(d, i64);
823 EXPECT_EQ(i64, GetValueByPointer(d, "/foo/int64")->GetInt64());
824
825 const uint64_t u64 = RAPIDJSON_UINT64_C2(0xFFFFFFFFF, 0xFFFFFFFFF);
826 Pointer("/foo/uint64").Set(d, u64);
827 EXPECT_EQ(u64, GetValueByPointer(d, "/foo/uint64")->GetUint64());
828
829 Pointer("/foo/true").Set(d, true);
830 EXPECT_TRUE(GetValueByPointer(d, "/foo/true")->IsTrue());
831
832 Pointer("/foo/false").Set(d, false);
833 EXPECT_TRUE(GetValueByPointer(d, "/foo/false")->IsFalse());
834
835 // StringRef version
836 Pointer("/foo/hello").Set(d, "Hello");
837 EXPECT_STREQ("Hello", GetValueByPointer(d, "/foo/hello")->GetString());
838
839 // Copy string version
840 {
841 char buffer[256];
842 strcpy(buffer, "World");
843 Pointer("/foo/world").Set(d, buffer);
844 memset(buffer, 0, sizeof(buffer));
845 }
846 EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString());
847
848 #if RAPIDJSON_HAS_STDSTRING
849 Pointer("/foo/c++").Set(d, std::string("C++"));
850 EXPECT_STREQ("C++", GetValueByPointer(d, "/foo/c++")->GetString());
851 #endif
852 }
853
TEST(Pointer,Swap)854 TEST(Pointer, Swap) {
855 Document d;
856 d.Parse(kJson);
857 Document::AllocatorType& a = d.GetAllocator();
858 Pointer("/foo/0").Swap(d, *Pointer("/foo/1").Get(d), a);
859 EXPECT_STREQ("baz", d["foo"][0].GetString());
860 EXPECT_STREQ("bar", d["foo"][1].GetString());
861 }
862
TEST(Pointer,Swap_NoAllocator)863 TEST(Pointer, Swap_NoAllocator) {
864 Document d;
865 d.Parse(kJson);
866 Pointer("/foo/0").Swap(d, *Pointer("/foo/1").Get(d));
867 EXPECT_STREQ("baz", d["foo"][0].GetString());
868 EXPECT_STREQ("bar", d["foo"][1].GetString());
869 }
870
TEST(Pointer,Erase)871 TEST(Pointer, Erase) {
872 Document d;
873 d.Parse(kJson);
874
875 EXPECT_FALSE(Pointer("").Erase(d));
876 EXPECT_FALSE(Pointer("/nonexist").Erase(d));
877 EXPECT_FALSE(Pointer("/nonexist/nonexist").Erase(d));
878 EXPECT_FALSE(Pointer("/foo/nonexist").Erase(d));
879 EXPECT_FALSE(Pointer("/foo/nonexist/nonexist").Erase(d));
880 EXPECT_FALSE(Pointer("/foo/0/nonexist").Erase(d));
881 EXPECT_FALSE(Pointer("/foo/0/nonexist/nonexist").Erase(d));
882 EXPECT_FALSE(Pointer("/foo/2/nonexist").Erase(d));
883 EXPECT_TRUE(Pointer("/foo/0").Erase(d));
884 EXPECT_EQ(1u, d["foo"].Size());
885 EXPECT_STREQ("baz", d["foo"][0].GetString());
886 EXPECT_TRUE(Pointer("/foo/0").Erase(d));
887 EXPECT_TRUE(d["foo"].Empty());
888 EXPECT_TRUE(Pointer("/foo").Erase(d));
889 EXPECT_TRUE(Pointer("/foo").Get(d) == 0);
890
891 Pointer("/a/0/b/0").Create(d);
892
893 EXPECT_TRUE(Pointer("/a/0/b/0").Get(d) != 0);
894 EXPECT_TRUE(Pointer("/a/0/b/0").Erase(d));
895 EXPECT_TRUE(Pointer("/a/0/b/0").Get(d) == 0);
896
897 EXPECT_TRUE(Pointer("/a/0/b").Get(d) != 0);
898 EXPECT_TRUE(Pointer("/a/0/b").Erase(d));
899 EXPECT_TRUE(Pointer("/a/0/b").Get(d) == 0);
900
901 EXPECT_TRUE(Pointer("/a/0").Get(d) != 0);
902 EXPECT_TRUE(Pointer("/a/0").Erase(d));
903 EXPECT_TRUE(Pointer("/a/0").Get(d) == 0);
904
905 EXPECT_TRUE(Pointer("/a").Get(d) != 0);
906 EXPECT_TRUE(Pointer("/a").Erase(d));
907 EXPECT_TRUE(Pointer("/a").Get(d) == 0);
908 }
909
TEST(Pointer,CreateValueByPointer)910 TEST(Pointer, CreateValueByPointer) {
911 Document d;
912 Document::AllocatorType& a = d.GetAllocator();
913
914 {
915 Value& v = CreateValueByPointer(d, Pointer("/foo/0"), a);
916 EXPECT_EQ(&d["foo"][0], &v);
917 }
918 {
919 Value& v = CreateValueByPointer(d, "/foo/1", a);
920 EXPECT_EQ(&d["foo"][1], &v);
921 }
922 }
923
TEST(Pointer,CreateValueByPointer_NoAllocator)924 TEST(Pointer, CreateValueByPointer_NoAllocator) {
925 Document d;
926
927 {
928 Value& v = CreateValueByPointer(d, Pointer("/foo/0"));
929 EXPECT_EQ(&d["foo"][0], &v);
930 }
931 {
932 Value& v = CreateValueByPointer(d, "/foo/1");
933 EXPECT_EQ(&d["foo"][1], &v);
934 }
935 }
936
TEST(Pointer,GetValueByPointer)937 TEST(Pointer, GetValueByPointer) {
938 Document d;
939 d.Parse(kJson);
940
941 EXPECT_EQ(&d["foo"][0], GetValueByPointer(d, Pointer("/foo/0")));
942 EXPECT_EQ(&d["foo"][0], GetValueByPointer(d, "/foo/0"));
943
944 // const version
945 const Value& v = d;
946 EXPECT_EQ(&d["foo"][0], GetValueByPointer(v, Pointer("/foo/0")));
947 EXPECT_EQ(&d["foo"][0], GetValueByPointer(v, "/foo/0"));
948 }
949
TEST(Pointer,GetValueByPointerWithDefault_Pointer)950 TEST(Pointer, GetValueByPointerWithDefault_Pointer) {
951 Document d;
952 d.Parse(kJson);
953
954 Document::AllocatorType& a = d.GetAllocator();
955 const Value v("qux");
956 EXPECT_TRUE(Value("bar") == GetValueByPointerWithDefault(d, Pointer("/foo/0"), v, a));
957 EXPECT_TRUE(Value("bar") == GetValueByPointerWithDefault(d, Pointer("/foo/0"), v, a));
958 EXPECT_TRUE(Value("baz") == GetValueByPointerWithDefault(d, Pointer("/foo/1"), v, a));
959 EXPECT_TRUE(Value("qux") == GetValueByPointerWithDefault(d, Pointer("/foo/2"), v, a));
960 EXPECT_TRUE(Value("last") == GetValueByPointerWithDefault(d, Pointer("/foo/-"), Value("last").Move(), a));
961 EXPECT_STREQ("last", d["foo"][3].GetString());
962
963 EXPECT_TRUE(GetValueByPointerWithDefault(d, Pointer("/foo/null"), Value().Move(), a).IsNull());
964 EXPECT_TRUE(GetValueByPointerWithDefault(d, Pointer("/foo/null"), "x", a).IsNull());
965
966 // Generic version
967 EXPECT_EQ(-1, GetValueByPointerWithDefault(d, Pointer("/foo/int"), -1, a).GetInt());
968 EXPECT_EQ(-1, GetValueByPointerWithDefault(d, Pointer("/foo/int"), -2, a).GetInt());
969 EXPECT_EQ(0x87654321, GetValueByPointerWithDefault(d, Pointer("/foo/uint"), 0x87654321, a).GetUint());
970 EXPECT_EQ(0x87654321, GetValueByPointerWithDefault(d, Pointer("/foo/uint"), 0x12345678, a).GetUint());
971
972 const int64_t i64 = static_cast<int64_t>(RAPIDJSON_UINT64_C2(0x80000000, 0));
973 EXPECT_EQ(i64, GetValueByPointerWithDefault(d, Pointer("/foo/int64"), i64, a).GetInt64());
974 EXPECT_EQ(i64, GetValueByPointerWithDefault(d, Pointer("/foo/int64"), i64 + 1, a).GetInt64());
975
976 const uint64_t u64 = RAPIDJSON_UINT64_C2(0xFFFFFFFFF, 0xFFFFFFFFF);
977 EXPECT_EQ(u64, GetValueByPointerWithDefault(d, Pointer("/foo/uint64"), u64, a).GetUint64());
978 EXPECT_EQ(u64, GetValueByPointerWithDefault(d, Pointer("/foo/uint64"), u64 - 1, a).GetUint64());
979
980 EXPECT_TRUE(GetValueByPointerWithDefault(d, Pointer("/foo/true"), true, a).IsTrue());
981 EXPECT_TRUE(GetValueByPointerWithDefault(d, Pointer("/foo/true"), false, a).IsTrue());
982
983 EXPECT_TRUE(GetValueByPointerWithDefault(d, Pointer("/foo/false"), false, a).IsFalse());
984 EXPECT_TRUE(GetValueByPointerWithDefault(d, Pointer("/foo/false"), true, a).IsFalse());
985
986 // StringRef version
987 EXPECT_STREQ("Hello", GetValueByPointerWithDefault(d, Pointer("/foo/hello"), "Hello", a).GetString());
988
989 // Copy string version
990 {
991 char buffer[256];
992 strcpy(buffer, "World");
993 EXPECT_STREQ("World", GetValueByPointerWithDefault(d, Pointer("/foo/world"), buffer, a).GetString());
994 memset(buffer, 0, sizeof(buffer));
995 }
996 EXPECT_STREQ("World", GetValueByPointer(d, Pointer("/foo/world"))->GetString());
997
998 #if RAPIDJSON_HAS_STDSTRING
999 EXPECT_STREQ("C++", GetValueByPointerWithDefault(d, Pointer("/foo/C++"), std::string("C++"), a).GetString());
1000 #endif
1001 }
1002
TEST(Pointer,GetValueByPointerWithDefault_String)1003 TEST(Pointer, GetValueByPointerWithDefault_String) {
1004 Document d;
1005 d.Parse(kJson);
1006
1007 Document::AllocatorType& a = d.GetAllocator();
1008 const Value v("qux");
1009 EXPECT_TRUE(Value("bar") == GetValueByPointerWithDefault(d, "/foo/0", v, a));
1010 EXPECT_TRUE(Value("bar") == GetValueByPointerWithDefault(d, "/foo/0", v, a));
1011 EXPECT_TRUE(Value("baz") == GetValueByPointerWithDefault(d, "/foo/1", v, a));
1012 EXPECT_TRUE(Value("qux") == GetValueByPointerWithDefault(d, "/foo/2", v, a));
1013 EXPECT_TRUE(Value("last") == GetValueByPointerWithDefault(d, "/foo/-", Value("last").Move(), a));
1014 EXPECT_STREQ("last", d["foo"][3].GetString());
1015
1016 EXPECT_TRUE(GetValueByPointerWithDefault(d, "/foo/null", Value().Move(), a).IsNull());
1017 EXPECT_TRUE(GetValueByPointerWithDefault(d, "/foo/null", "x", a).IsNull());
1018
1019 // Generic version
1020 EXPECT_EQ(-1, GetValueByPointerWithDefault(d, "/foo/int", -1, a).GetInt());
1021 EXPECT_EQ(-1, GetValueByPointerWithDefault(d, "/foo/int", -2, a).GetInt());
1022 EXPECT_EQ(0x87654321, GetValueByPointerWithDefault(d, "/foo/uint", 0x87654321, a).GetUint());
1023 EXPECT_EQ(0x87654321, GetValueByPointerWithDefault(d, "/foo/uint", 0x12345678, a).GetUint());
1024
1025 const int64_t i64 = static_cast<int64_t>(RAPIDJSON_UINT64_C2(0x80000000, 0));
1026 EXPECT_EQ(i64, GetValueByPointerWithDefault(d, "/foo/int64", i64, a).GetInt64());
1027 EXPECT_EQ(i64, GetValueByPointerWithDefault(d, "/foo/int64", i64 + 1, a).GetInt64());
1028
1029 const uint64_t u64 = RAPIDJSON_UINT64_C2(0xFFFFFFFFF, 0xFFFFFFFFF);
1030 EXPECT_EQ(u64, GetValueByPointerWithDefault(d, "/foo/uint64", u64, a).GetUint64());
1031 EXPECT_EQ(u64, GetValueByPointerWithDefault(d, "/foo/uint64", u64 - 1, a).GetUint64());
1032
1033 EXPECT_TRUE(GetValueByPointerWithDefault(d, "/foo/true", true, a).IsTrue());
1034 EXPECT_TRUE(GetValueByPointerWithDefault(d, "/foo/true", false, a).IsTrue());
1035
1036 EXPECT_TRUE(GetValueByPointerWithDefault(d, "/foo/false", false, a).IsFalse());
1037 EXPECT_TRUE(GetValueByPointerWithDefault(d, "/foo/false", true, a).IsFalse());
1038
1039 // StringRef version
1040 EXPECT_STREQ("Hello", GetValueByPointerWithDefault(d, "/foo/hello", "Hello", a).GetString());
1041
1042 // Copy string version
1043 {
1044 char buffer[256];
1045 strcpy(buffer, "World");
1046 EXPECT_STREQ("World", GetValueByPointerWithDefault(d, "/foo/world", buffer, a).GetString());
1047 memset(buffer, 0, sizeof(buffer));
1048 }
1049 EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString());
1050
1051 #if RAPIDJSON_HAS_STDSTRING
1052 EXPECT_STREQ("C++", GetValueByPointerWithDefault(d, "/foo/C++", std::string("C++"), a).GetString());
1053 #endif
1054 }
1055
TEST(Pointer,GetValueByPointerWithDefault_Pointer_NoAllocator)1056 TEST(Pointer, GetValueByPointerWithDefault_Pointer_NoAllocator) {
1057 Document d;
1058 d.Parse(kJson);
1059
1060 const Value v("qux");
1061 EXPECT_TRUE(Value("bar") == GetValueByPointerWithDefault(d, Pointer("/foo/0"), v));
1062 EXPECT_TRUE(Value("bar") == GetValueByPointerWithDefault(d, Pointer("/foo/0"), v));
1063 EXPECT_TRUE(Value("baz") == GetValueByPointerWithDefault(d, Pointer("/foo/1"), v));
1064 EXPECT_TRUE(Value("qux") == GetValueByPointerWithDefault(d, Pointer("/foo/2"), v));
1065 EXPECT_TRUE(Value("last") == GetValueByPointerWithDefault(d, Pointer("/foo/-"), Value("last").Move()));
1066 EXPECT_STREQ("last", d["foo"][3].GetString());
1067
1068 EXPECT_TRUE(GetValueByPointerWithDefault(d, Pointer("/foo/null"), Value().Move()).IsNull());
1069 EXPECT_TRUE(GetValueByPointerWithDefault(d, Pointer("/foo/null"), "x").IsNull());
1070
1071 // Generic version
1072 EXPECT_EQ(-1, GetValueByPointerWithDefault(d, Pointer("/foo/int"), -1).GetInt());
1073 EXPECT_EQ(-1, GetValueByPointerWithDefault(d, Pointer("/foo/int"), -2).GetInt());
1074 EXPECT_EQ(0x87654321, GetValueByPointerWithDefault(d, Pointer("/foo/uint"), 0x87654321).GetUint());
1075 EXPECT_EQ(0x87654321, GetValueByPointerWithDefault(d, Pointer("/foo/uint"), 0x12345678).GetUint());
1076
1077 const int64_t i64 = static_cast<int64_t>(RAPIDJSON_UINT64_C2(0x80000000, 0));
1078 EXPECT_EQ(i64, GetValueByPointerWithDefault(d, Pointer("/foo/int64"), i64).GetInt64());
1079 EXPECT_EQ(i64, GetValueByPointerWithDefault(d, Pointer("/foo/int64"), i64 + 1).GetInt64());
1080
1081 const uint64_t u64 = RAPIDJSON_UINT64_C2(0xFFFFFFFFF, 0xFFFFFFFFF);
1082 EXPECT_EQ(u64, GetValueByPointerWithDefault(d, Pointer("/foo/uint64"), u64).GetUint64());
1083 EXPECT_EQ(u64, GetValueByPointerWithDefault(d, Pointer("/foo/uint64"), u64 - 1).GetUint64());
1084
1085 EXPECT_TRUE(GetValueByPointerWithDefault(d, Pointer("/foo/true"), true).IsTrue());
1086 EXPECT_TRUE(GetValueByPointerWithDefault(d, Pointer("/foo/true"), false).IsTrue());
1087
1088 EXPECT_TRUE(GetValueByPointerWithDefault(d, Pointer("/foo/false"), false).IsFalse());
1089 EXPECT_TRUE(GetValueByPointerWithDefault(d, Pointer("/foo/false"), true).IsFalse());
1090
1091 // StringRef version
1092 EXPECT_STREQ("Hello", GetValueByPointerWithDefault(d, Pointer("/foo/hello"), "Hello").GetString());
1093
1094 // Copy string version
1095 {
1096 char buffer[256];
1097 strcpy(buffer, "World");
1098 EXPECT_STREQ("World", GetValueByPointerWithDefault(d, Pointer("/foo/world"), buffer).GetString());
1099 memset(buffer, 0, sizeof(buffer));
1100 }
1101 EXPECT_STREQ("World", GetValueByPointer(d, Pointer("/foo/world"))->GetString());
1102
1103 #if RAPIDJSON_HAS_STDSTRING
1104 EXPECT_STREQ("C++", GetValueByPointerWithDefault(d, Pointer("/foo/C++"), std::string("C++")).GetString());
1105 #endif
1106 }
1107
TEST(Pointer,GetValueByPointerWithDefault_String_NoAllocator)1108 TEST(Pointer, GetValueByPointerWithDefault_String_NoAllocator) {
1109 Document d;
1110 d.Parse(kJson);
1111
1112 const Value v("qux");
1113 EXPECT_TRUE(Value("bar") == GetValueByPointerWithDefault(d, "/foo/0", v));
1114 EXPECT_TRUE(Value("bar") == GetValueByPointerWithDefault(d, "/foo/0", v));
1115 EXPECT_TRUE(Value("baz") == GetValueByPointerWithDefault(d, "/foo/1", v));
1116 EXPECT_TRUE(Value("qux") == GetValueByPointerWithDefault(d, "/foo/2", v));
1117 EXPECT_TRUE(Value("last") == GetValueByPointerWithDefault(d, "/foo/-", Value("last").Move()));
1118 EXPECT_STREQ("last", d["foo"][3].GetString());
1119
1120 EXPECT_TRUE(GetValueByPointerWithDefault(d, "/foo/null", Value().Move()).IsNull());
1121 EXPECT_TRUE(GetValueByPointerWithDefault(d, "/foo/null", "x").IsNull());
1122
1123 // Generic version
1124 EXPECT_EQ(-1, GetValueByPointerWithDefault(d, "/foo/int", -1).GetInt());
1125 EXPECT_EQ(-1, GetValueByPointerWithDefault(d, "/foo/int", -2).GetInt());
1126 EXPECT_EQ(0x87654321, GetValueByPointerWithDefault(d, "/foo/uint", 0x87654321).GetUint());
1127 EXPECT_EQ(0x87654321, GetValueByPointerWithDefault(d, "/foo/uint", 0x12345678).GetUint());
1128
1129 const int64_t i64 = static_cast<int64_t>(RAPIDJSON_UINT64_C2(0x80000000, 0));
1130 EXPECT_EQ(i64, GetValueByPointerWithDefault(d, "/foo/int64", i64).GetInt64());
1131 EXPECT_EQ(i64, GetValueByPointerWithDefault(d, "/foo/int64", i64 + 1).GetInt64());
1132
1133 const uint64_t u64 = RAPIDJSON_UINT64_C2(0xFFFFFFFFF, 0xFFFFFFFFF);
1134 EXPECT_EQ(u64, GetValueByPointerWithDefault(d, "/foo/uint64", u64).GetUint64());
1135 EXPECT_EQ(u64, GetValueByPointerWithDefault(d, "/foo/uint64", u64 - 1).GetUint64());
1136
1137 EXPECT_TRUE(GetValueByPointerWithDefault(d, "/foo/true", true).IsTrue());
1138 EXPECT_TRUE(GetValueByPointerWithDefault(d, "/foo/true", false).IsTrue());
1139
1140 EXPECT_TRUE(GetValueByPointerWithDefault(d, "/foo/false", false).IsFalse());
1141 EXPECT_TRUE(GetValueByPointerWithDefault(d, "/foo/false", true).IsFalse());
1142
1143 // StringRef version
1144 EXPECT_STREQ("Hello", GetValueByPointerWithDefault(d, "/foo/hello", "Hello").GetString());
1145
1146 // Copy string version
1147 {
1148 char buffer[256];
1149 strcpy(buffer, "World");
1150 EXPECT_STREQ("World", GetValueByPointerWithDefault(d, "/foo/world", buffer).GetString());
1151 memset(buffer, 0, sizeof(buffer));
1152 }
1153 EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString());
1154
1155 #if RAPIDJSON_HAS_STDSTRING
1156 EXPECT_STREQ("C++", GetValueByPointerWithDefault(d, Pointer("/foo/C++"), std::string("C++")).GetString());
1157 #endif
1158 }
1159
TEST(Pointer,SetValueByPointer_Pointer)1160 TEST(Pointer, SetValueByPointer_Pointer) {
1161 Document d;
1162 d.Parse(kJson);
1163 Document::AllocatorType& a = d.GetAllocator();
1164
1165 // Value version
1166 SetValueByPointer(d, Pointer("/foo/0"), Value(123).Move(), a);
1167 EXPECT_EQ(123, d["foo"][0].GetInt());
1168
1169 SetValueByPointer(d, Pointer("/foo/null"), Value().Move(), a);
1170 EXPECT_TRUE(GetValueByPointer(d, "/foo/null")->IsNull());
1171
1172 // Const Value version
1173 const Value foo(d["foo"], d.GetAllocator());
1174 SetValueByPointer(d, Pointer("/clone"), foo, a);
1175 EXPECT_EQ(foo, *GetValueByPointer(d, "/clone"));
1176
1177 // Generic version
1178 SetValueByPointer(d, Pointer("/foo/int"), -1, a);
1179 EXPECT_EQ(-1, GetValueByPointer(d, "/foo/int")->GetInt());
1180
1181 SetValueByPointer(d, Pointer("/foo/uint"), 0x87654321, a);
1182 EXPECT_EQ(0x87654321, GetValueByPointer(d, "/foo/uint")->GetUint());
1183
1184 const int64_t i64 = static_cast<int64_t>(RAPIDJSON_UINT64_C2(0x80000000, 0));
1185 SetValueByPointer(d, Pointer("/foo/int64"), i64, a);
1186 EXPECT_EQ(i64, GetValueByPointer(d, "/foo/int64")->GetInt64());
1187
1188 const uint64_t u64 = RAPIDJSON_UINT64_C2(0xFFFFFFFFF, 0xFFFFFFFFF);
1189 SetValueByPointer(d, Pointer("/foo/uint64"), u64, a);
1190 EXPECT_EQ(u64, GetValueByPointer(d, "/foo/uint64")->GetUint64());
1191
1192 SetValueByPointer(d, Pointer("/foo/true"), true, a);
1193 EXPECT_TRUE(GetValueByPointer(d, "/foo/true")->IsTrue());
1194
1195 SetValueByPointer(d, Pointer("/foo/false"), false, a);
1196 EXPECT_TRUE(GetValueByPointer(d, "/foo/false")->IsFalse());
1197
1198 // StringRef version
1199 SetValueByPointer(d, Pointer("/foo/hello"), "Hello", a);
1200 EXPECT_STREQ("Hello", GetValueByPointer(d, "/foo/hello")->GetString());
1201
1202 // Copy string version
1203 {
1204 char buffer[256];
1205 strcpy(buffer, "World");
1206 SetValueByPointer(d, Pointer("/foo/world"), buffer, a);
1207 memset(buffer, 0, sizeof(buffer));
1208 }
1209 EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString());
1210
1211 #if RAPIDJSON_HAS_STDSTRING
1212 SetValueByPointer(d, Pointer("/foo/c++"), std::string("C++"), a);
1213 EXPECT_STREQ("C++", GetValueByPointer(d, "/foo/c++")->GetString());
1214 #endif
1215 }
1216
TEST(Pointer,SetValueByPointer_String)1217 TEST(Pointer, SetValueByPointer_String) {
1218 Document d;
1219 d.Parse(kJson);
1220 Document::AllocatorType& a = d.GetAllocator();
1221
1222 // Value version
1223 SetValueByPointer(d, "/foo/0", Value(123).Move(), a);
1224 EXPECT_EQ(123, d["foo"][0].GetInt());
1225
1226 SetValueByPointer(d, "/foo/null", Value().Move(), a);
1227 EXPECT_TRUE(GetValueByPointer(d, "/foo/null")->IsNull());
1228
1229 // Const Value version
1230 const Value foo(d["foo"], d.GetAllocator());
1231 SetValueByPointer(d, "/clone", foo, a);
1232 EXPECT_EQ(foo, *GetValueByPointer(d, "/clone"));
1233
1234 // Generic version
1235 SetValueByPointer(d, "/foo/int", -1, a);
1236 EXPECT_EQ(-1, GetValueByPointer(d, "/foo/int")->GetInt());
1237
1238 SetValueByPointer(d, "/foo/uint", 0x87654321, a);
1239 EXPECT_EQ(0x87654321, GetValueByPointer(d, "/foo/uint")->GetUint());
1240
1241 const int64_t i64 = static_cast<int64_t>(RAPIDJSON_UINT64_C2(0x80000000, 0));
1242 SetValueByPointer(d, "/foo/int64", i64, a);
1243 EXPECT_EQ(i64, GetValueByPointer(d, "/foo/int64")->GetInt64());
1244
1245 const uint64_t u64 = RAPIDJSON_UINT64_C2(0xFFFFFFFFF, 0xFFFFFFFFF);
1246 SetValueByPointer(d, "/foo/uint64", u64, a);
1247 EXPECT_EQ(u64, GetValueByPointer(d, "/foo/uint64")->GetUint64());
1248
1249 SetValueByPointer(d, "/foo/true", true, a);
1250 EXPECT_TRUE(GetValueByPointer(d, "/foo/true")->IsTrue());
1251
1252 SetValueByPointer(d, "/foo/false", false, a);
1253 EXPECT_TRUE(GetValueByPointer(d, "/foo/false")->IsFalse());
1254
1255 // StringRef version
1256 SetValueByPointer(d, "/foo/hello", "Hello", a);
1257 EXPECT_STREQ("Hello", GetValueByPointer(d, "/foo/hello")->GetString());
1258
1259 // Copy string version
1260 {
1261 char buffer[256];
1262 strcpy(buffer, "World");
1263 SetValueByPointer(d, "/foo/world", buffer, a);
1264 memset(buffer, 0, sizeof(buffer));
1265 }
1266 EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString());
1267
1268 #if RAPIDJSON_HAS_STDSTRING
1269 SetValueByPointer(d, "/foo/c++", std::string("C++"), a);
1270 EXPECT_STREQ("C++", GetValueByPointer(d, "/foo/c++")->GetString());
1271 #endif
1272 }
1273
TEST(Pointer,SetValueByPointer_Pointer_NoAllocator)1274 TEST(Pointer, SetValueByPointer_Pointer_NoAllocator) {
1275 Document d;
1276 d.Parse(kJson);
1277
1278 // Value version
1279 SetValueByPointer(d, Pointer("/foo/0"), Value(123).Move());
1280 EXPECT_EQ(123, d["foo"][0].GetInt());
1281
1282 SetValueByPointer(d, Pointer("/foo/null"), Value().Move());
1283 EXPECT_TRUE(GetValueByPointer(d, "/foo/null")->IsNull());
1284
1285 // Const Value version
1286 const Value foo(d["foo"], d.GetAllocator());
1287 SetValueByPointer(d, Pointer("/clone"), foo);
1288 EXPECT_EQ(foo, *GetValueByPointer(d, "/clone"));
1289
1290 // Generic version
1291 SetValueByPointer(d, Pointer("/foo/int"), -1);
1292 EXPECT_EQ(-1, GetValueByPointer(d, "/foo/int")->GetInt());
1293
1294 SetValueByPointer(d, Pointer("/foo/uint"), 0x87654321);
1295 EXPECT_EQ(0x87654321, GetValueByPointer(d, "/foo/uint")->GetUint());
1296
1297 const int64_t i64 = static_cast<int64_t>(RAPIDJSON_UINT64_C2(0x80000000, 0));
1298 SetValueByPointer(d, Pointer("/foo/int64"), i64);
1299 EXPECT_EQ(i64, GetValueByPointer(d, "/foo/int64")->GetInt64());
1300
1301 const uint64_t u64 = RAPIDJSON_UINT64_C2(0xFFFFFFFFF, 0xFFFFFFFFF);
1302 SetValueByPointer(d, Pointer("/foo/uint64"), u64);
1303 EXPECT_EQ(u64, GetValueByPointer(d, "/foo/uint64")->GetUint64());
1304
1305 SetValueByPointer(d, Pointer("/foo/true"), true);
1306 EXPECT_TRUE(GetValueByPointer(d, "/foo/true")->IsTrue());
1307
1308 SetValueByPointer(d, Pointer("/foo/false"), false);
1309 EXPECT_TRUE(GetValueByPointer(d, "/foo/false")->IsFalse());
1310
1311 // StringRef version
1312 SetValueByPointer(d, Pointer("/foo/hello"), "Hello");
1313 EXPECT_STREQ("Hello", GetValueByPointer(d, "/foo/hello")->GetString());
1314
1315 // Copy string version
1316 {
1317 char buffer[256];
1318 strcpy(buffer, "World");
1319 SetValueByPointer(d, Pointer("/foo/world"), buffer);
1320 memset(buffer, 0, sizeof(buffer));
1321 }
1322 EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString());
1323
1324 #if RAPIDJSON_HAS_STDSTRING
1325 SetValueByPointer(d, Pointer("/foo/c++"), std::string("C++"));
1326 EXPECT_STREQ("C++", GetValueByPointer(d, "/foo/c++")->GetString());
1327 #endif
1328 }
1329
TEST(Pointer,SetValueByPointer_String_NoAllocator)1330 TEST(Pointer, SetValueByPointer_String_NoAllocator) {
1331 Document d;
1332 d.Parse(kJson);
1333
1334 // Value version
1335 SetValueByPointer(d, "/foo/0", Value(123).Move());
1336 EXPECT_EQ(123, d["foo"][0].GetInt());
1337
1338 SetValueByPointer(d, "/foo/null", Value().Move());
1339 EXPECT_TRUE(GetValueByPointer(d, "/foo/null")->IsNull());
1340
1341 // Const Value version
1342 const Value foo(d["foo"], d.GetAllocator());
1343 SetValueByPointer(d, "/clone", foo);
1344 EXPECT_EQ(foo, *GetValueByPointer(d, "/clone"));
1345
1346 // Generic version
1347 SetValueByPointer(d, "/foo/int", -1);
1348 EXPECT_EQ(-1, GetValueByPointer(d, "/foo/int")->GetInt());
1349
1350 SetValueByPointer(d, "/foo/uint", 0x87654321);
1351 EXPECT_EQ(0x87654321, GetValueByPointer(d, "/foo/uint")->GetUint());
1352
1353 const int64_t i64 = static_cast<int64_t>(RAPIDJSON_UINT64_C2(0x80000000, 0));
1354 SetValueByPointer(d, "/foo/int64", i64);
1355 EXPECT_EQ(i64, GetValueByPointer(d, "/foo/int64")->GetInt64());
1356
1357 const uint64_t u64 = RAPIDJSON_UINT64_C2(0xFFFFFFFFF, 0xFFFFFFFFF);
1358 SetValueByPointer(d, "/foo/uint64", u64);
1359 EXPECT_EQ(u64, GetValueByPointer(d, "/foo/uint64")->GetUint64());
1360
1361 SetValueByPointer(d, "/foo/true", true);
1362 EXPECT_TRUE(GetValueByPointer(d, "/foo/true")->IsTrue());
1363
1364 SetValueByPointer(d, "/foo/false", false);
1365 EXPECT_TRUE(GetValueByPointer(d, "/foo/false")->IsFalse());
1366
1367 // StringRef version
1368 SetValueByPointer(d, "/foo/hello", "Hello");
1369 EXPECT_STREQ("Hello", GetValueByPointer(d, "/foo/hello")->GetString());
1370
1371 // Copy string version
1372 {
1373 char buffer[256];
1374 strcpy(buffer, "World");
1375 SetValueByPointer(d, "/foo/world", buffer);
1376 memset(buffer, 0, sizeof(buffer));
1377 }
1378 EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString());
1379
1380 #if RAPIDJSON_HAS_STDSTRING
1381 SetValueByPointer(d, "/foo/c++", std::string("C++"));
1382 EXPECT_STREQ("C++", GetValueByPointer(d, "/foo/c++")->GetString());
1383 #endif
1384 }
1385
TEST(Pointer,SwapValueByPointer)1386 TEST(Pointer, SwapValueByPointer) {
1387 Document d;
1388 d.Parse(kJson);
1389 Document::AllocatorType& a = d.GetAllocator();
1390 SwapValueByPointer(d, Pointer("/foo/0"), *GetValueByPointer(d, "/foo/1"), a);
1391 EXPECT_STREQ("baz", d["foo"][0].GetString());
1392 EXPECT_STREQ("bar", d["foo"][1].GetString());
1393
1394 SwapValueByPointer(d, "/foo/0", *GetValueByPointer(d, "/foo/1"), a);
1395 EXPECT_STREQ("bar", d["foo"][0].GetString());
1396 EXPECT_STREQ("baz", d["foo"][1].GetString());
1397 }
1398
TEST(Pointer,SwapValueByPointer_NoAllocator)1399 TEST(Pointer, SwapValueByPointer_NoAllocator) {
1400 Document d;
1401 d.Parse(kJson);
1402 SwapValueByPointer(d, Pointer("/foo/0"), *GetValueByPointer(d, "/foo/1"));
1403 EXPECT_STREQ("baz", d["foo"][0].GetString());
1404 EXPECT_STREQ("bar", d["foo"][1].GetString());
1405
1406 SwapValueByPointer(d, "/foo/0", *GetValueByPointer(d, "/foo/1"));
1407 EXPECT_STREQ("bar", d["foo"][0].GetString());
1408 EXPECT_STREQ("baz", d["foo"][1].GetString());
1409 }
1410
TEST(Pointer,EraseValueByPointer_Pointer)1411 TEST(Pointer, EraseValueByPointer_Pointer) {
1412 Document d;
1413 d.Parse(kJson);
1414
1415 EXPECT_FALSE(EraseValueByPointer(d, Pointer("")));
1416 EXPECT_FALSE(Pointer("/foo/nonexist").Erase(d));
1417 EXPECT_TRUE(EraseValueByPointer(d, Pointer("/foo/0")));
1418 EXPECT_EQ(1u, d["foo"].Size());
1419 EXPECT_STREQ("baz", d["foo"][0].GetString());
1420 EXPECT_TRUE(EraseValueByPointer(d, Pointer("/foo/0")));
1421 EXPECT_TRUE(d["foo"].Empty());
1422 EXPECT_TRUE(EraseValueByPointer(d, Pointer("/foo")));
1423 EXPECT_TRUE(Pointer("/foo").Get(d) == 0);
1424 }
1425
TEST(Pointer,EraseValueByPointer_String)1426 TEST(Pointer, EraseValueByPointer_String) {
1427 Document d;
1428 d.Parse(kJson);
1429
1430 EXPECT_FALSE(EraseValueByPointer(d, ""));
1431 EXPECT_FALSE(Pointer("/foo/nonexist").Erase(d));
1432 EXPECT_TRUE(EraseValueByPointer(d, "/foo/0"));
1433 EXPECT_EQ(1u, d["foo"].Size());
1434 EXPECT_STREQ("baz", d["foo"][0].GetString());
1435 EXPECT_TRUE(EraseValueByPointer(d, "/foo/0"));
1436 EXPECT_TRUE(d["foo"].Empty());
1437 EXPECT_TRUE(EraseValueByPointer(d, "/foo"));
1438 EXPECT_TRUE(Pointer("/foo").Get(d) == 0);
1439 }
1440
TEST(Pointer,Ambiguity)1441 TEST(Pointer, Ambiguity) {
1442 {
1443 Document d;
1444 d.Parse("{\"0\" : [123]}");
1445 EXPECT_EQ(123, Pointer("/0/0").Get(d)->GetInt());
1446 Pointer("/0/a").Set(d, 456); // Change array [123] to object {456}
1447 EXPECT_EQ(456, Pointer("/0/a").Get(d)->GetInt());
1448 }
1449
1450 {
1451 Document d;
1452 EXPECT_FALSE(d.Parse("[{\"0\": 123}]").HasParseError());
1453 EXPECT_EQ(123, Pointer("/0/0").Get(d)->GetInt());
1454 Pointer("/0/1").Set(d, 456); // 1 is treated as "1" to index object
1455 EXPECT_EQ(123, Pointer("/0/0").Get(d)->GetInt());
1456 EXPECT_EQ(456, Pointer("/0/1").Get(d)->GetInt());
1457 }
1458 }
1459