• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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