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