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