utree.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501
  1. /*=============================================================================
  2. Copyright (c) 2001-2011 Joel de Guzman
  3. Copyright (c) 2001-2011 Hartmut Kaiser
  4. Copyright (c) 2010 Bryce Lelbach
  5. Distributed under the Boost Software License, Version 1.0. (See accompanying
  6. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  7. =============================================================================*/
  8. #include <boost/config/warning_disable.hpp>
  9. #include <boost/detail/lightweight_test.hpp>
  10. #include <boost/functional/hash.hpp>
  11. #include <boost/spirit/include/support_utree.hpp>
  12. #include <iostream>
  13. #include <sstream>
  14. #include <cstdlib>
  15. inline bool check(boost::spirit::utree const& val, std::string expected)
  16. {
  17. std::stringstream s;
  18. s << val;
  19. if (s.str() == expected + " ")
  20. return true;
  21. std::cerr << "got result: " << s.str()
  22. << ", expected: " << expected << std::endl;
  23. return false;
  24. }
  25. struct one_two_three
  26. {
  27. boost::spirit::utree operator()(boost::spirit::utree) const
  28. {
  29. return boost::spirit::utree(123);
  30. }
  31. };
  32. struct this_
  33. {
  34. boost::spirit::utree operator()(boost::spirit::utree) const
  35. {
  36. return boost::spirit::utree(static_cast<int>(boost::hash_value(this)));
  37. }
  38. };
  39. int main()
  40. {
  41. using boost::spirit::utree;
  42. using boost::spirit::get;
  43. using boost::spirit::utf8_symbol_type;
  44. using boost::spirit::binary_string_type;
  45. {
  46. // test the size
  47. std::cout << "size of utree is: "
  48. << sizeof(utree) << " bytes" << std::endl;
  49. BOOST_TEST_EQ(sizeof(utree), sizeof(void*[4]));
  50. }
  51. {
  52. using boost::spirit::nil;
  53. utree val(nil);
  54. BOOST_TEST(check(val, "<nil>"));
  55. }
  56. {
  57. using boost::spirit::empty_list;
  58. utree val(empty_list);
  59. BOOST_TEST(check(val, "( )"));
  60. }
  61. {
  62. utree val(true);
  63. BOOST_TEST(check(val, "true"));
  64. }
  65. {
  66. utree val(123);
  67. BOOST_TEST(check(val, "123"));
  68. }
  69. {
  70. // single element string
  71. utree val('x');
  72. BOOST_TEST(check(val, "\"x\""));
  73. // empty string
  74. utree val1("");
  75. BOOST_TEST(check(val1, "\"\""));
  76. }
  77. {
  78. utree val(123.456);
  79. BOOST_TEST(check(val, "123.456"));
  80. }
  81. { // strings
  82. utree val("Hello, World");
  83. BOOST_TEST(check(val, "\"Hello, World\""));
  84. utree val2;
  85. val2 = val;
  86. BOOST_TEST(check(val2, "\"Hello, World\""));
  87. utree val3("Hello, World. Chuckie is back!!!");
  88. val = val3;
  89. BOOST_TEST(check(val, "\"Hello, World. Chuckie is back!!!\""));
  90. utree val4("Apple");
  91. utree val5("Apple");
  92. BOOST_TEST_EQ(val4, val5);
  93. utree val6("ApplePie");
  94. BOOST_TEST(val4 < val6);
  95. }
  96. { // symbols
  97. utree val(utf8_symbol_type("Hello, World"));
  98. BOOST_TEST(check(val, "Hello, World"));
  99. utree val2;
  100. val2 = val;
  101. BOOST_TEST(check(val2, "Hello, World"));
  102. utree val3(utf8_symbol_type("Hello, World. Chuckie is back!!!"));
  103. val = val3;
  104. BOOST_TEST(check(val, "Hello, World. Chuckie is back!!!"));
  105. utree val4(utf8_symbol_type("Apple"));
  106. utree val5(utf8_symbol_type("Apple"));
  107. BOOST_TEST_EQ(val4, val5);
  108. utree val6(utf8_symbol_type("ApplePie"));
  109. BOOST_TEST(val4 < val6);
  110. }
  111. { // binary_strings
  112. utree val(binary_string_type("\xDE#\xAD"));
  113. BOOST_TEST(check(val, "#de23ad#" /* FIXME?: "#\xDE#\xAD#" */));
  114. utree val2;
  115. val2 = val;
  116. BOOST_TEST(check(val2, "#de23ad#" /* FIXME?: "#\xDE#\xAD#" */));
  117. utree val3(binary_string_type("\xDE\xAD\xBE\xEF"));
  118. val = val3;
  119. BOOST_TEST(check(val, "#deadbeef#" /* FIXME?: "#\xDE\xAD\xBE\xEF#" */));
  120. utree val4(binary_string_type("\x01"));
  121. utree val5(binary_string_type("\x01"));
  122. BOOST_TEST_EQ(val4, val5);
  123. utree val6(binary_string_type("\x01\x02"));
  124. BOOST_TEST(val4 < val6);
  125. }
  126. {
  127. using boost::spirit::nil;
  128. utree val;
  129. val.push_back(123);
  130. val.push_back("Chuckie");
  131. BOOST_TEST_EQ(val.size(), 2U);
  132. utree val2;
  133. val2.push_back(123.456);
  134. val2.push_back("Mah Doggie");
  135. val.push_back(val2);
  136. BOOST_TEST_EQ(val.size(), 3U);
  137. BOOST_TEST(check(val, "( 123 \"Chuckie\" ( 123.456 \"Mah Doggie\" ) )"));
  138. BOOST_TEST(check(val.front(), "123"));
  139. utree val3(nil);
  140. val3.swap(val);
  141. BOOST_TEST_EQ(val3.size(), 3U);
  142. BOOST_TEST(check(val, "<nil>"));
  143. val3.swap(val);
  144. BOOST_TEST(check(val, "( 123 \"Chuckie\" ( 123.456 \"Mah Doggie\" ) )"));
  145. val.push_back("another string");
  146. BOOST_TEST_EQ(val.size(), 4U);
  147. BOOST_TEST(check(val, "( 123 \"Chuckie\" ( 123.456 \"Mah Doggie\" ) \"another string\" )"));
  148. val.pop_front();
  149. BOOST_TEST(check(val, "( \"Chuckie\" ( 123.456 \"Mah Doggie\" ) \"another string\" )"));
  150. utree::iterator i = val.begin();
  151. ++++i;
  152. val.insert(i, "Right in the middle");
  153. BOOST_TEST_EQ(val.size(), 4U);
  154. BOOST_TEST(check(val, "( \"Chuckie\" ( 123.456 \"Mah Doggie\" ) \"Right in the middle\" \"another string\" )"));
  155. val.pop_back();
  156. BOOST_TEST(check(val, "( \"Chuckie\" ( 123.456 \"Mah Doggie\" ) \"Right in the middle\" )"));
  157. BOOST_TEST_EQ(val.size(), 3U);
  158. utree::iterator it = val.end(); --it;
  159. val.erase(it);
  160. BOOST_TEST(check(val, "( \"Chuckie\" ( 123.456 \"Mah Doggie\" ) )"));
  161. BOOST_TEST_EQ(val.size(), 2U);
  162. val.insert(val.begin(), val2.begin(), val2.end());
  163. BOOST_TEST(check(val, "( 123.456 \"Mah Doggie\" \"Chuckie\" ( 123.456 \"Mah Doggie\" ) )"));
  164. BOOST_TEST_EQ(val.size(), 4U);
  165. // Regeression Ticket #6714
  166. it = val.insert(val.end(), 111);
  167. BOOST_TEST(it != val.begin());
  168. BOOST_TEST(it == --val.end());
  169. BOOST_TEST(*it == 111);
  170. val.clear();
  171. it = val.insert(val.begin(), 222);
  172. BOOST_TEST(it == val.begin());
  173. BOOST_TEST(it == --val.end());
  174. BOOST_TEST(*it == 222);
  175. // Regeression Ticket #6714
  176. }
  177. {
  178. utree val;
  179. val.insert(val.end(), 123);
  180. val.insert(val.end(), "Mia");
  181. val.insert(val.end(), "Chuckie");
  182. val.insert(val.end(), "Poly");
  183. val.insert(val.end(), "Mochi");
  184. BOOST_TEST(check(val, "( 123 \"Mia\" \"Chuckie\" \"Poly\" \"Mochi\" )"));
  185. }
  186. {
  187. using boost::spirit::nil;
  188. using boost::spirit::invalid;
  189. utree a(nil), b(nil);
  190. BOOST_TEST_EQ(a, b);
  191. a = 123;
  192. BOOST_TEST(a != b);
  193. b = 123;
  194. BOOST_TEST_EQ(a, b);
  195. a = 100.00;
  196. BOOST_TEST(a < b);
  197. b = a = utree(invalid);
  198. BOOST_TEST_EQ(a, b);
  199. a.push_back(1);
  200. a.push_back("two");
  201. a.push_back(3.0);
  202. b.push_back(1);
  203. b.push_back("two");
  204. b.push_back(3.0);
  205. BOOST_TEST_EQ(a, b);
  206. b.push_back(4);
  207. BOOST_TEST(a != b);
  208. BOOST_TEST(a < b);
  209. }
  210. {
  211. using boost::spirit::empty_list;
  212. utree a(empty_list);
  213. a.push_back(0);
  214. a.push_back(0);
  215. a.push_back(0);
  216. a.push_back(0);
  217. a.push_back(0);
  218. a.push_back(0);
  219. a.push_back(0);
  220. a.push_back(0);
  221. a.push_back(0);
  222. a.push_back(0);
  223. a.push_back(0);
  224. a.push_back(0);
  225. for (utree::size_type i = 0; i < a.size(); ++i)
  226. get(a, i) = int(i + 1);
  227. BOOST_TEST_EQ(get(a, 0), utree(1));
  228. BOOST_TEST_EQ(get(a, 1), utree(2));
  229. BOOST_TEST_EQ(get(a, 2), utree(3));
  230. BOOST_TEST_EQ(get(a, 3), utree(4));
  231. BOOST_TEST_EQ(get(a, 4), utree(5));
  232. BOOST_TEST_EQ(get(a, 5), utree(6));
  233. BOOST_TEST_EQ(get(a, 6), utree(7));
  234. BOOST_TEST_EQ(get(a, 7), utree(8));
  235. BOOST_TEST_EQ(get(a, 8), utree(9));
  236. BOOST_TEST_EQ(get(a, 9), utree(10));
  237. BOOST_TEST_EQ(get(a, 10), utree(11));
  238. BOOST_TEST_EQ(get(a, 11), utree(12));
  239. }
  240. {
  241. // test empty list
  242. utree a;
  243. a.push_back(1);
  244. a.pop_front();
  245. BOOST_TEST(check(a, "( )"));
  246. // the other way around
  247. utree b;
  248. b.push_front(1);
  249. b.pop_back();
  250. BOOST_TEST(check(b, "( )"));
  251. }
  252. { // test references
  253. utree val(123);
  254. utree ref(boost::ref(val));
  255. BOOST_TEST(check(ref, "123"));
  256. BOOST_TEST_EQ(ref, utree(123));
  257. val.clear();
  258. val.push_back(1);
  259. val.push_back(2);
  260. val.push_back(3);
  261. val.push_back(4);
  262. BOOST_TEST(check(ref, "( 1 2 3 4 )"));
  263. BOOST_TEST_EQ(get(ref, 0), utree(1));
  264. BOOST_TEST_EQ(get(ref, 1), utree(2));
  265. BOOST_TEST_EQ(get(ref, 2), utree(3));
  266. BOOST_TEST_EQ(get(ref, 3), utree(4));
  267. }
  268. { // put it in an array
  269. utree vals[] = {
  270. utree(123),
  271. utree("Hello, World"),
  272. utree(123.456)
  273. };
  274. BOOST_TEST(check(vals[0], "123"));
  275. BOOST_TEST(check(vals[1], "\"Hello, World\""));
  276. BOOST_TEST(check(vals[2], "123.456"));
  277. }
  278. { // operators
  279. BOOST_TEST((utree(false) && utree(false)) == utree(false));
  280. BOOST_TEST((utree(false) && utree(true)) == utree(false));
  281. BOOST_TEST((utree(true) && utree(false)) == utree(false));
  282. BOOST_TEST((utree(true) && utree(true)) == utree(true));
  283. BOOST_TEST((utree(0) && utree(0)) == utree(false));
  284. BOOST_TEST((utree(0) && utree(1)) == utree(false));
  285. BOOST_TEST((utree(1) && utree(0)) == utree(false));
  286. BOOST_TEST((utree(1) && utree(1)) == utree(true));
  287. BOOST_TEST((utree(false) || utree(false)) == utree(false));
  288. BOOST_TEST((utree(false) || utree(true)) == utree(true));
  289. BOOST_TEST((utree(true) || utree(false)) == utree(true));
  290. BOOST_TEST((utree(true) || utree(true)) == utree(true));
  291. BOOST_TEST((utree(0) || utree(0)) == utree(false));
  292. BOOST_TEST((utree(0) || utree(1)) == utree(true));
  293. BOOST_TEST((utree(1) || utree(0)) == utree(true));
  294. BOOST_TEST((utree(1) || utree(1)) == utree(true));
  295. BOOST_TEST((!utree(true)) == utree(false));
  296. BOOST_TEST((!utree(false)) == utree(true));
  297. BOOST_TEST((!utree(1)) == utree(false));
  298. BOOST_TEST((!utree(0)) == utree(true));
  299. BOOST_TEST((utree(456) + utree(123)) == utree(456 + 123));
  300. BOOST_TEST((utree(456) + utree(123.456)) == utree(456 + 123.456));
  301. BOOST_TEST((utree(456) - utree(123)) == utree(456 - 123));
  302. BOOST_TEST((utree(456) - utree(123.456)) == utree(456 - 123.456));
  303. BOOST_TEST((utree(456) * utree(123)) == utree(456 * 123));
  304. BOOST_TEST((utree(456) * utree(123.456)) == utree(456 * 123.456));
  305. BOOST_TEST((utree(456) / utree(123)) == utree(456 / 123));
  306. BOOST_TEST((utree(456) / utree(123.456)) == utree(456 / 123.456));
  307. BOOST_TEST((utree(456) % utree(123)) == utree(456 % 123));
  308. BOOST_TEST(-utree(456) == utree(-456));
  309. BOOST_TEST((utree(456) & utree(123)) == utree(456 & 123));
  310. BOOST_TEST((utree(456) | utree(123)) == utree(456 | 123));
  311. BOOST_TEST((utree(456) ^ utree(123)) == utree(456 ^ 123));
  312. BOOST_TEST((utree(456) << utree(3)) == utree(456 << 3));
  313. BOOST_TEST((utree(456) >> utree(2)) == utree(456 >> 2));
  314. BOOST_TEST(~utree(456) == utree(~456));
  315. }
  316. { // test reference iterator
  317. utree val;
  318. val.push_back(1);
  319. val.push_back(2);
  320. val.push_back(3);
  321. val.push_back(4);
  322. BOOST_TEST(check(val, "( 1 2 3 4 )"));
  323. utree::ref_iterator b = val.ref_begin();
  324. utree::ref_iterator e = val.ref_end();
  325. utree ref(boost::make_iterator_range(b, e));
  326. BOOST_TEST_EQ(get(ref, 0), utree(1));
  327. BOOST_TEST_EQ(get(ref, 1), utree(2));
  328. BOOST_TEST_EQ(get(ref, 2), utree(3));
  329. BOOST_TEST_EQ(get(ref, 3), utree(4));
  330. BOOST_TEST(check(ref, "( 1 2 3 4 )"));
  331. }
  332. {
  333. // check the tag
  334. // TODO: test tags on all utree types
  335. utree x;
  336. x.tag(123);
  337. BOOST_TEST_EQ(x.tag(), 123);
  338. x = "hello world! my name is bob the builder";
  339. x.tag(123);
  340. BOOST_TEST_EQ(x.tag(), 123);
  341. x.tag(456);
  342. BOOST_TEST_EQ(x.tag(), 456);
  343. BOOST_TEST_EQ(x.size(), 39U);
  344. BOOST_TEST(check(x, "\"hello world! my name is bob the builder\""));
  345. x = "hello";
  346. x.tag(456);
  347. BOOST_TEST_EQ(x.tag(), 456);
  348. x.tag(789);
  349. BOOST_TEST_EQ(x.tag(), 789);
  350. BOOST_TEST_EQ(x.size(), 5U);
  351. BOOST_TEST(check(x, "\"hello\""));
  352. }
  353. {
  354. // test functions
  355. using boost::spirit::stored_function;
  356. utree f = stored_function<one_two_three>();
  357. f.eval(utree());
  358. }
  359. {
  360. // test referenced functions
  361. using boost::spirit::referenced_function;
  362. one_two_three f;
  363. utree ff = referenced_function<one_two_three>(f);
  364. BOOST_TEST_EQ(ff.eval(utree()), f(utree()));
  365. }
  366. {
  367. // shallow ranges
  368. using boost::spirit::shallow;
  369. utree val;
  370. val.push_back(1);
  371. val.push_back(2);
  372. val.push_back(3);
  373. val.push_back(4);
  374. utree::iterator i = val.begin(); ++i;
  375. utree alias(utree::range(i, val.end()), shallow);
  376. BOOST_TEST(check(alias, "( 2 3 4 )"));
  377. BOOST_TEST_EQ(alias.size(), 3U);
  378. BOOST_TEST_EQ(alias.front(), 2);
  379. BOOST_TEST_EQ(alias.back(), 4);
  380. BOOST_TEST(!alias.empty());
  381. BOOST_TEST_EQ(get(alias, 1), 3);
  382. }
  383. {
  384. // shallow string ranges
  385. using boost::spirit::utf8_string_range_type;
  386. using boost::spirit::shallow;
  387. char const* s = "Hello, World";
  388. utree val(utf8_string_range_type(s, s + strlen(s)), shallow);
  389. BOOST_TEST(check(val, "\"Hello, World\""));
  390. utf8_string_range_type r = val.get<utf8_string_range_type>();
  391. utf8_string_range_type pf(r.begin()+1, r.end()-1);
  392. val = utree(pf, shallow);
  393. BOOST_TEST(check(val, "\"ello, Worl\""));
  394. }
  395. {
  396. // any pointer
  397. using boost::spirit::any_ptr;
  398. int n = 123;
  399. utree up = any_ptr(&n);
  400. BOOST_TEST(*up.get<int*>() == 123);
  401. }
  402. // tags
  403. {
  404. short min = (std::numeric_limits<short>::min)();
  405. short max = (std::numeric_limits<short>::max)();
  406. utree::list_type u;
  407. utree u2;
  408. bool ok = true;
  409. for (int t = min ; ok && t <= max ; ++t) {
  410. u.tag(t);
  411. u2 = u;
  412. BOOST_TEST_EQ(t, u.tag());
  413. BOOST_TEST_EQ(t, u2.tag());
  414. ok = t == u.tag() && t == u2.tag();
  415. u2 = utree("12");
  416. }
  417. }
  418. return boost::report_errors();
  419. }