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

source code of boost/libs/spirit/test/support/utree.cpp