pointertest.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562
  1. // Copyright (C) 2011 Milo Yip
  2. //
  3. // Permission is hereby granted, free of charge, to any person obtaining a copy
  4. // of this software and associated documentation files (the "Software"), to deal
  5. // in the Software without restriction, including without limitation the rights
  6. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  7. // copies of the Software, and to permit persons to whom the Software is
  8. // furnished to do so, subject to the following conditions:
  9. //
  10. // The above copyright notice and this permission notice shall be included in
  11. // all copies or substantial portions of the Software.
  12. //
  13. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  14. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  16. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  17. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  18. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  19. // THE SOFTWARE.
  20. #include "unittest.h"
  21. #include "rapidjson/pointer.h"
  22. #include "rapidjson/stringbuffer.h"
  23. #include <sstream>
  24. using namespace rapidjson;
  25. static const char kJson[] = "{\n"
  26. " \"foo\":[\"bar\", \"baz\"],\n"
  27. " \"\" : 0,\n"
  28. " \"a/b\" : 1,\n"
  29. " \"c%d\" : 2,\n"
  30. " \"e^f\" : 3,\n"
  31. " \"g|h\" : 4,\n"
  32. " \"i\\\\j\" : 5,\n"
  33. " \"k\\\"l\" : 6,\n"
  34. " \" \" : 7,\n"
  35. " \"m~n\" : 8\n"
  36. "}";
  37. TEST(Pointer, Parse) {
  38. {
  39. Pointer p("");
  40. EXPECT_TRUE(p.IsValid());
  41. EXPECT_EQ(0u, p.GetTokenCount());
  42. }
  43. {
  44. Pointer p("/foo");
  45. EXPECT_TRUE(p.IsValid());
  46. EXPECT_EQ(1u, p.GetTokenCount());
  47. EXPECT_EQ(3u, p.GetTokens()[0].length);
  48. EXPECT_STREQ("foo", p.GetTokens()[0].name);
  49. }
  50. {
  51. Pointer p("/foo/0");
  52. EXPECT_TRUE(p.IsValid());
  53. EXPECT_EQ(2u, p.GetTokenCount());
  54. EXPECT_EQ(3u, p.GetTokens()[0].length);
  55. EXPECT_STREQ("foo", p.GetTokens()[0].name);
  56. EXPECT_EQ(1u, p.GetTokens()[1].length);
  57. EXPECT_STREQ("0", p.GetTokens()[1].name);
  58. EXPECT_EQ(0u, p.GetTokens()[1].index);
  59. }
  60. {
  61. // Unescape ~1
  62. Pointer p("/a~1b");
  63. EXPECT_TRUE(p.IsValid());
  64. EXPECT_EQ(1u, p.GetTokenCount());
  65. EXPECT_EQ(3u, p.GetTokens()[0].length);
  66. EXPECT_STREQ("a/b", p.GetTokens()[0].name);
  67. }
  68. {
  69. // Unescape ~0
  70. Pointer p("/m~0n");
  71. EXPECT_TRUE(p.IsValid());
  72. EXPECT_EQ(1u, p.GetTokenCount());
  73. EXPECT_EQ(3u, p.GetTokens()[0].length);
  74. EXPECT_STREQ("m~n", p.GetTokens()[0].name);
  75. }
  76. {
  77. // empty name
  78. Pointer p("/");
  79. EXPECT_TRUE(p.IsValid());
  80. EXPECT_EQ(1u, p.GetTokenCount());
  81. EXPECT_EQ(0u, p.GetTokens()[0].length);
  82. EXPECT_STREQ("", p.GetTokens()[0].name);
  83. }
  84. {
  85. // empty and non-empty name
  86. Pointer p("//a");
  87. EXPECT_TRUE(p.IsValid());
  88. EXPECT_EQ(2u, p.GetTokenCount());
  89. EXPECT_EQ(0u, p.GetTokens()[0].length);
  90. EXPECT_STREQ("", p.GetTokens()[0].name);
  91. EXPECT_EQ(1u, p.GetTokens()[1].length);
  92. EXPECT_STREQ("a", p.GetTokens()[1].name);
  93. }
  94. {
  95. // Null characters
  96. Pointer p("/\0\0", 3);
  97. EXPECT_TRUE(p.IsValid());
  98. EXPECT_EQ(1u, p.GetTokenCount());
  99. EXPECT_EQ(2u, p.GetTokens()[0].length);
  100. EXPECT_EQ('\0', p.GetTokens()[0].name[0]);
  101. EXPECT_EQ('\0', p.GetTokens()[0].name[1]);
  102. EXPECT_EQ('\0', p.GetTokens()[0].name[2]);
  103. }
  104. {
  105. // Valid index
  106. Pointer p("/123");
  107. EXPECT_TRUE(p.IsValid());
  108. EXPECT_EQ(1u, p.GetTokenCount());
  109. EXPECT_STREQ("123", p.GetTokens()[0].name);
  110. EXPECT_EQ(123u, p.GetTokens()[0].index);
  111. }
  112. {
  113. // Invalid index (with leading zero)
  114. Pointer p("/01");
  115. EXPECT_TRUE(p.IsValid());
  116. EXPECT_EQ(1u, p.GetTokenCount());
  117. EXPECT_STREQ("01", p.GetTokens()[0].name);
  118. EXPECT_EQ(kPointerInvalidIndex, p.GetTokens()[0].index);
  119. }
  120. if (sizeof(SizeType) == 4) {
  121. // Invalid index (overflow)
  122. Pointer p("/4294967296");
  123. EXPECT_TRUE(p.IsValid());
  124. EXPECT_EQ(1u, p.GetTokenCount());
  125. EXPECT_STREQ("4294967296", p.GetTokens()[0].name);
  126. EXPECT_EQ(kPointerInvalidIndex, p.GetTokens()[0].index);
  127. }
  128. {
  129. // kPointerParseErrorTokenMustBeginWithSolidus
  130. Pointer p(" ");
  131. EXPECT_FALSE(p.IsValid());
  132. EXPECT_EQ(kPointerParseErrorTokenMustBeginWithSolidus, p.GetParseErrorCode());
  133. EXPECT_EQ(0u, p.GetParseErrorOffset());
  134. }
  135. {
  136. // kPointerParseErrorInvalidEscape
  137. Pointer p("/~");
  138. EXPECT_FALSE(p.IsValid());
  139. EXPECT_EQ(kPointerParseErrorInvalidEscape, p.GetParseErrorCode());
  140. EXPECT_EQ(2u, p.GetParseErrorOffset());
  141. }
  142. {
  143. // kPointerParseErrorInvalidEscape
  144. Pointer p("/~2");
  145. EXPECT_FALSE(p.IsValid());
  146. EXPECT_EQ(kPointerParseErrorInvalidEscape, p.GetParseErrorCode());
  147. EXPECT_EQ(2u, p.GetParseErrorOffset());
  148. }
  149. }
  150. TEST(Pointer, Stringify) {
  151. // Test by roundtrip
  152. const char* sources[] = {
  153. "",
  154. "/foo",
  155. "/foo/0",
  156. "/",
  157. "/a~1b",
  158. "/c%d",
  159. "/e^f",
  160. "/g|h",
  161. "/i\\j",
  162. "/k\"l",
  163. "/ ",
  164. "/m~0n"
  165. };
  166. for (size_t i = 0; i < sizeof(sources) / sizeof(sources[0]); i++) {
  167. Pointer p(sources[i]);
  168. StringBuffer s;
  169. p.Stringify(s);
  170. EXPECT_STREQ(sources[i], s.GetString());
  171. }
  172. }
  173. // Construct a Pointer with static tokens, no dynamic allocation involved.
  174. #define NAME(s) { s, sizeof(s) / sizeof(s[0]) - 1, kPointerInvalidIndex }
  175. #define INDEX(i) { #i, sizeof(#i) - 1, i }
  176. static const Pointer::Token kTokens[] = { NAME("foo"), INDEX(0) }; // equivalent to "/foo/0"
  177. #undef NAME
  178. #undef INDEX
  179. TEST(Pointer, ConstructorWithToken) {
  180. Pointer p(kTokens, sizeof(kTokens) / sizeof(kTokens[0]));
  181. EXPECT_TRUE(p.IsValid());
  182. EXPECT_EQ(2u, p.GetTokenCount());
  183. EXPECT_EQ(3u, p.GetTokens()[0].length);
  184. EXPECT_STREQ("foo", p.GetTokens()[0].name);
  185. EXPECT_EQ(1u, p.GetTokens()[1].length);
  186. EXPECT_STREQ("0", p.GetTokens()[1].name);
  187. EXPECT_EQ(0u, p.GetTokens()[1].index);
  188. }
  189. TEST(Pointer, CopyConstructor) {
  190. {
  191. Pointer p("/foo/0");
  192. Pointer q(p);
  193. EXPECT_TRUE(q.IsValid());
  194. EXPECT_EQ(2u, q.GetTokenCount());
  195. EXPECT_EQ(3u, q.GetTokens()[0].length);
  196. EXPECT_STREQ("foo", q.GetTokens()[0].name);
  197. EXPECT_EQ(1u, q.GetTokens()[1].length);
  198. EXPECT_STREQ("0", q.GetTokens()[1].name);
  199. EXPECT_EQ(0u, q.GetTokens()[1].index);
  200. }
  201. // Static tokens
  202. {
  203. Pointer p(kTokens, sizeof(kTokens) / sizeof(kTokens[0]));
  204. Pointer q(p);
  205. EXPECT_TRUE(q.IsValid());
  206. EXPECT_EQ(2u, q.GetTokenCount());
  207. EXPECT_EQ(3u, q.GetTokens()[0].length);
  208. EXPECT_STREQ("foo", q.GetTokens()[0].name);
  209. EXPECT_EQ(1u, q.GetTokens()[1].length);
  210. EXPECT_STREQ("0", q.GetTokens()[1].name);
  211. EXPECT_EQ(0u, q.GetTokens()[1].index);
  212. }
  213. }
  214. TEST(Pointer, Assignment) {
  215. {
  216. Pointer p("/foo/0");
  217. Pointer q;
  218. q = p;
  219. EXPECT_TRUE(q.IsValid());
  220. EXPECT_EQ(2u, q.GetTokenCount());
  221. EXPECT_EQ(3u, q.GetTokens()[0].length);
  222. EXPECT_STREQ("foo", q.GetTokens()[0].name);
  223. EXPECT_EQ(1u, q.GetTokens()[1].length);
  224. EXPECT_STREQ("0", q.GetTokens()[1].name);
  225. EXPECT_EQ(0u, q.GetTokens()[1].index);
  226. }
  227. // Static tokens
  228. {
  229. Pointer p(kTokens, sizeof(kTokens) / sizeof(kTokens[0]));
  230. Pointer q;
  231. q = p;
  232. EXPECT_TRUE(q.IsValid());
  233. EXPECT_EQ(2u, q.GetTokenCount());
  234. EXPECT_EQ(3u, q.GetTokens()[0].length);
  235. EXPECT_STREQ("foo", q.GetTokens()[0].name);
  236. EXPECT_EQ(1u, q.GetTokens()[1].length);
  237. EXPECT_STREQ("0", q.GetTokens()[1].name);
  238. EXPECT_EQ(0u, q.GetTokens()[1].index);
  239. }
  240. }
  241. TEST(Pointer, Create) {
  242. Document d;
  243. {
  244. Value* v = &Pointer("").Create(d, d.GetAllocator());
  245. EXPECT_EQ(&d, v);
  246. }
  247. {
  248. Value* v = &Pointer("/foo").Create(d, d.GetAllocator());
  249. EXPECT_EQ(&d["foo"], v);
  250. }
  251. {
  252. Value* v = &Pointer("/foo/0").Create(d, d.GetAllocator());
  253. EXPECT_EQ(&d["foo"][0], v);
  254. }
  255. {
  256. Value* v = &Pointer("/foo/-").Create(d, d.GetAllocator());
  257. EXPECT_EQ(&d["foo"][1], v);
  258. }
  259. {
  260. Value* v = &Pointer("/foo/-/-").Create(d, d.GetAllocator());
  261. EXPECT_EQ(&d["foo"][2][0], v);
  262. }
  263. }
  264. TEST(Pointer, Get) {
  265. Document d;
  266. d.Parse(kJson);
  267. EXPECT_EQ(&d, Pointer("").Get(d));
  268. EXPECT_EQ(&d["foo"], Pointer("/foo").Get(d));
  269. EXPECT_EQ(&d["foo"][0], Pointer("/foo/0").Get(d));
  270. EXPECT_EQ(&d[""], Pointer("/").Get(d));
  271. EXPECT_EQ(&d["a/b"], Pointer("/a~1b").Get(d));
  272. EXPECT_EQ(&d["c%d"], Pointer("/c%d").Get(d));
  273. EXPECT_EQ(&d["e^f"], Pointer("/e^f").Get(d));
  274. EXPECT_EQ(&d["g|h"], Pointer("/g|h").Get(d));
  275. EXPECT_EQ(&d["i\\j"], Pointer("/i\\j").Get(d));
  276. EXPECT_EQ(&d["k\"l"], Pointer("/k\"l").Get(d));
  277. EXPECT_EQ(&d[" "], Pointer("/ ").Get(d));
  278. EXPECT_EQ(&d["m~n"], Pointer("/m~0n").Get(d));
  279. EXPECT_TRUE(Pointer("/abc").Get(d) == 0);
  280. }
  281. TEST(Pointer, GetWithDefault) {
  282. Document d;
  283. d.Parse(kJson);
  284. // Value version
  285. Document::AllocatorType& a = d.GetAllocator();
  286. const Value v("qux");
  287. EXPECT_TRUE(Value("bar") == Pointer("/foo/0").GetWithDefault(d, v, a));
  288. EXPECT_TRUE(Value("baz") == Pointer("/foo/1").GetWithDefault(d, v, a));
  289. EXPECT_TRUE(Value("qux") == Pointer("/foo/2").GetWithDefault(d, v, a));
  290. EXPECT_TRUE(Value("last") == Pointer("/foo/-").GetWithDefault(d, Value("last").Move(), a));
  291. EXPECT_STREQ("last", d["foo"][3].GetString());
  292. EXPECT_TRUE(Pointer("/foo/null").GetWithDefault(d, Value().Move(), a).IsNull());
  293. EXPECT_TRUE(Pointer("/foo/null").GetWithDefault(d, "x", a).IsNull());
  294. // Generic version
  295. EXPECT_EQ(-1, Pointer("/foo/int").GetWithDefault(d, -1, a).GetInt());
  296. EXPECT_EQ(-1, Pointer("/foo/int").GetWithDefault(d, -2, a).GetInt());
  297. EXPECT_EQ(0x87654321, Pointer("/foo/uint").GetWithDefault(d, 0x87654321, a).GetUint());
  298. EXPECT_EQ(0x87654321, Pointer("/foo/uint").GetWithDefault(d, 0x12345678, a).GetUint());
  299. const int64_t i64 = static_cast<int64_t>(RAPIDJSON_UINT64_C2(0x80000000, 0));
  300. EXPECT_EQ(i64, Pointer("/foo/int64").GetWithDefault(d, i64, a).GetInt64());
  301. EXPECT_EQ(i64, Pointer("/foo/int64").GetWithDefault(d, i64 + 1, a).GetInt64());
  302. const uint64_t u64 = RAPIDJSON_UINT64_C2(0xFFFFFFFFF, 0xFFFFFFFFF);
  303. EXPECT_EQ(u64, Pointer("/foo/uint64").GetWithDefault(d, u64, a).GetUint64());
  304. EXPECT_EQ(u64, Pointer("/foo/uint64").GetWithDefault(d, u64 - 1, a).GetUint64());
  305. EXPECT_TRUE(Pointer("/foo/true").GetWithDefault(d, true, a).IsTrue());
  306. EXPECT_TRUE(Pointer("/foo/true").GetWithDefault(d, false, a).IsTrue());
  307. EXPECT_TRUE(Pointer("/foo/false").GetWithDefault(d, false, a).IsFalse());
  308. EXPECT_TRUE(Pointer("/foo/false").GetWithDefault(d, true, a).IsFalse());
  309. // StringRef version
  310. EXPECT_STREQ("Hello", Pointer("/foo/hello").GetWithDefault(d, "Hello", a).GetString());
  311. // Copy string version
  312. {
  313. char buffer[256];
  314. strcpy(buffer, "World");
  315. EXPECT_STREQ("World", Pointer("/foo/world").GetWithDefault(d, buffer, a).GetString());
  316. memset(buffer, 0, sizeof(buffer));
  317. }
  318. EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString());
  319. }
  320. TEST(Pointer, Set) {
  321. Document d;
  322. d.Parse(kJson);
  323. Document::AllocatorType& a = d.GetAllocator();
  324. // Value version
  325. Pointer("/foo/0").Set(d, Value(123).Move(), a);
  326. EXPECT_EQ(123, d["foo"][0].GetInt());
  327. Pointer("/foo/-").Set(d, Value(456).Move(), a);
  328. EXPECT_EQ(456, d["foo"][2].GetInt());
  329. Pointer("/foo/null").Set(d, Value().Move(), a);
  330. EXPECT_TRUE(GetValueByPointer(d, "/foo/null")->IsNull());
  331. // Generic version
  332. Pointer("/foo/int").Set(d, -1, a);
  333. EXPECT_EQ(-1, GetValueByPointer(d, "/foo/int")->GetInt());
  334. Pointer("/foo/uint").Set(d, 0x87654321, a);
  335. EXPECT_EQ(0x87654321, GetValueByPointer(d, "/foo/uint")->GetUint());
  336. const int64_t i64 = static_cast<int64_t>(RAPIDJSON_UINT64_C2(0x80000000, 0));
  337. Pointer("/foo/int64").Set(d, i64, a);
  338. EXPECT_EQ(i64, GetValueByPointer(d, "/foo/int64")->GetInt64());
  339. const uint64_t u64 = RAPIDJSON_UINT64_C2(0xFFFFFFFFF, 0xFFFFFFFFF);
  340. Pointer("/foo/uint64").Set(d, u64, a);
  341. EXPECT_EQ(u64, GetValueByPointer(d, "/foo/uint64")->GetUint64());
  342. Pointer("/foo/true").Set(d, true, a);
  343. EXPECT_TRUE(GetValueByPointer(d, "/foo/true")->IsTrue());
  344. Pointer("/foo/false").Set(d, false, a);
  345. EXPECT_TRUE(GetValueByPointer(d, "/foo/false")->IsFalse());
  346. // StringRef version
  347. Pointer("/foo/hello").Set(d, "Hello", a);
  348. EXPECT_STREQ("Hello", GetValueByPointer(d, "/foo/hello")->GetString());
  349. // Copy string version
  350. {
  351. char buffer[256];
  352. strcpy(buffer, "World");
  353. Pointer("/foo/world").Set(d, buffer, a);
  354. memset(buffer, 0, sizeof(buffer));
  355. }
  356. EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString());
  357. }
  358. TEST(Pointer, Swap) {
  359. Document d;
  360. d.Parse(kJson);
  361. Document::AllocatorType& a = d.GetAllocator();
  362. Pointer("/foo/0").Swap(d, *Pointer("/foo/1").Get(d), a);
  363. EXPECT_STREQ("baz", d["foo"][0].GetString());
  364. EXPECT_STREQ("bar", d["foo"][1].GetString());
  365. }
  366. TEST(Pointer, CreateValueByPointer) {
  367. Document d;
  368. Document::AllocatorType& a = d.GetAllocator();
  369. {
  370. Value& v = CreateValueByPointer(d, Pointer("/foo/0"), a);
  371. EXPECT_EQ(&d["foo"][0], &v);
  372. }
  373. {
  374. Value& v = CreateValueByPointer(d, "/foo/1", a);
  375. EXPECT_EQ(&d["foo"][1], &v);
  376. }
  377. }
  378. TEST(Pointer, GetValueByPointer) {
  379. Document d;
  380. d.Parse(kJson);
  381. EXPECT_EQ(&d["foo"][0], GetValueByPointer(d, Pointer("/foo/0")));
  382. EXPECT_EQ(&d["foo"][0], GetValueByPointer(d, "/foo/0"));
  383. // const version
  384. const Value& v = d;
  385. EXPECT_EQ(&d["foo"][0], GetValueByPointer(v, Pointer("/foo/0")));
  386. EXPECT_EQ(&d["foo"][0], GetValueByPointer(v, "/foo/0"));
  387. }
  388. TEST(Pointer, GetValueByPointerWithDefault) {
  389. Document d;
  390. d.Parse(kJson);
  391. Document::AllocatorType& a = d.GetAllocator();
  392. const Value v("qux");
  393. EXPECT_TRUE(Value("bar") == GetValueByPointerWithDefault(d, Pointer("/foo/0"), v, a));
  394. EXPECT_TRUE(Value("baz") == GetValueByPointerWithDefault(d, "/foo/1", v, a));
  395. }
  396. TEST(Pointer, SetValueByPointer_Pointer) {
  397. Document d;
  398. d.Parse(kJson);
  399. Document::AllocatorType& a = d.GetAllocator();
  400. // Value version
  401. SetValueByPointer(d, Pointer("/foo/0"), Value(123).Move(), a);
  402. EXPECT_EQ(123, d["foo"][0].GetInt());
  403. SetValueByPointer(d, Pointer("/foo/null"), Value().Move(), a);
  404. EXPECT_TRUE(GetValueByPointer(d, "/foo/null")->IsNull());
  405. // Generic version
  406. SetValueByPointer(d, Pointer("/foo/int"), -1, a);
  407. EXPECT_EQ(-1, GetValueByPointer(d, "/foo/int")->GetInt());
  408. SetValueByPointer(d, Pointer("/foo/uint"), 0x87654321, a);
  409. EXPECT_EQ(0x87654321, GetValueByPointer(d, "/foo/uint")->GetUint());
  410. const int64_t i64 = static_cast<int64_t>(RAPIDJSON_UINT64_C2(0x80000000, 0));
  411. SetValueByPointer(d, Pointer("/foo/int64"), i64, a);
  412. EXPECT_EQ(i64, GetValueByPointer(d, "/foo/int64")->GetInt64());
  413. const uint64_t u64 = RAPIDJSON_UINT64_C2(0xFFFFFFFFF, 0xFFFFFFFFF);
  414. SetValueByPointer(d, Pointer("/foo/uint64"), u64, a);
  415. EXPECT_EQ(u64, GetValueByPointer(d, "/foo/uint64")->GetUint64());
  416. SetValueByPointer(d, Pointer("/foo/true"), true, a);
  417. EXPECT_TRUE(GetValueByPointer(d, "/foo/true")->IsTrue());
  418. SetValueByPointer(d, Pointer("/foo/false"), false, a);
  419. EXPECT_TRUE(GetValueByPointer(d, "/foo/false")->IsFalse());
  420. // StringRef version
  421. SetValueByPointer(d, Pointer("/foo/hello"), "Hello", a);
  422. EXPECT_STREQ("Hello", GetValueByPointer(d, "/foo/hello")->GetString());
  423. // Copy string version
  424. {
  425. char buffer[256];
  426. strcpy(buffer, "World");
  427. SetValueByPointer(d, Pointer("/foo/world"), buffer, a);
  428. memset(buffer, 0, sizeof(buffer));
  429. }
  430. EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString());
  431. }
  432. TEST(Pointer, SetValueByPointer_String) {
  433. Document d;
  434. d.Parse(kJson);
  435. Document::AllocatorType& a = d.GetAllocator();
  436. // Value version
  437. SetValueByPointer(d, "/foo/0", Value(123).Move(), a);
  438. EXPECT_EQ(123, d["foo"][0].GetInt());
  439. SetValueByPointer(d, "/foo/null", Value().Move(), a);
  440. EXPECT_TRUE(GetValueByPointer(d, "/foo/null")->IsNull());
  441. // Generic version
  442. SetValueByPointer(d, "/foo/int", -1, a);
  443. EXPECT_EQ(-1, GetValueByPointer(d, "/foo/int")->GetInt());
  444. SetValueByPointer(d, "/foo/uint", 0x87654321, a);
  445. EXPECT_EQ(0x87654321, GetValueByPointer(d, "/foo/uint")->GetUint());
  446. const int64_t i64 = static_cast<int64_t>(RAPIDJSON_UINT64_C2(0x80000000, 0));
  447. SetValueByPointer(d, "/foo/int64", i64, a);
  448. EXPECT_EQ(i64, GetValueByPointer(d, "/foo/int64")->GetInt64());
  449. const uint64_t u64 = RAPIDJSON_UINT64_C2(0xFFFFFFFFF, 0xFFFFFFFFF);
  450. SetValueByPointer(d, "/foo/uint64", u64, a);
  451. EXPECT_EQ(u64, GetValueByPointer(d, "/foo/uint64")->GetUint64());
  452. SetValueByPointer(d, "/foo/true", true, a);
  453. EXPECT_TRUE(GetValueByPointer(d, "/foo/true")->IsTrue());
  454. SetValueByPointer(d, "/foo/false", false, a);
  455. EXPECT_TRUE(GetValueByPointer(d, "/foo/false")->IsFalse());
  456. // StringRef version
  457. SetValueByPointer(d, "/foo/hello", "Hello", a);
  458. EXPECT_STREQ("Hello", GetValueByPointer(d, "/foo/hello")->GetString());
  459. // Copy string version
  460. {
  461. char buffer[256];
  462. strcpy(buffer, "World");
  463. SetValueByPointer(d, "/foo/world", buffer, a);
  464. memset(buffer, 0, sizeof(buffer));
  465. }
  466. EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString());
  467. }
  468. TEST(Pointer, SwapValueByPointer) {
  469. Document d;
  470. d.Parse(kJson);
  471. Document::AllocatorType& a = d.GetAllocator();
  472. SwapValueByPointer(d, Pointer("/foo/0"), *GetValueByPointer(d, "/foo/1"), a);
  473. EXPECT_STREQ("baz", d["foo"][0].GetString());
  474. EXPECT_STREQ("bar", d["foo"][1].GetString());
  475. SwapValueByPointer(d, "/foo/0", *GetValueByPointer(d, "/foo/1"), a);
  476. EXPECT_STREQ("bar", d["foo"][0].GetString());
  477. EXPECT_STREQ("baz", d["foo"][1].GetString());
  478. }