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