Home | History | Annotate | Download | only in unittest
      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 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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