/*============================================================================= Copyright (c) 2001-2011 Joel de Guzman Copyright (c) 2001-2011 Hartmut Kaiser Copyright (c) 2010 Bryce Lelbach Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) =============================================================================*/ #include #include #include #include #include #include #include inline bool check(boost::spirit::utree const& val, std::string expected) { std::stringstream s; s << val; if (s.str() == expected + " ") return true; std::cerr << "got result: " << s.str() << ", expected: " << expected << std::endl; return false; } struct one_two_three { boost::spirit::utree operator()(boost::spirit::utree) const { return boost::spirit::utree(123); } }; struct this_ { boost::spirit::utree operator()(boost::spirit::utree) const { return boost::spirit::utree(static_cast(boost::hash_value(this))); } }; int main() { using boost::spirit::utree; using boost::spirit::get; using boost::spirit::utf8_symbol_type; using boost::spirit::binary_string_type; { // test the size std::cout << "size of utree is: " << sizeof(utree) << " bytes" << std::endl; BOOST_TEST_EQ(sizeof(utree), sizeof(void*[4])); } { using boost::spirit::nil; utree val(nil); BOOST_TEST(check(val, "")); } { using boost::spirit::empty_list; utree val(empty_list); BOOST_TEST(check(val, "( )")); } { utree val(true); BOOST_TEST(check(val, "true")); } { utree val(123); BOOST_TEST(check(val, "123")); } { // single element string utree val('x'); BOOST_TEST(check(val, "\"x\"")); // empty string utree val1(""); BOOST_TEST(check(val1, "\"\"")); } { utree val(123.456); BOOST_TEST(check(val, "123.456")); } { // strings utree val("Hello, World"); BOOST_TEST(check(val, "\"Hello, World\"")); utree val2; val2 = val; BOOST_TEST(check(val2, "\"Hello, World\"")); utree val3("Hello, World. Chuckie is back!!!"); val = val3; BOOST_TEST(check(val, "\"Hello, World. Chuckie is back!!!\"")); utree val4("Apple"); utree val5("Apple"); BOOST_TEST_EQ(val4, val5); utree val6("ApplePie"); BOOST_TEST(val4 < val6); } { // symbols utree val(utf8_symbol_type("Hello, World")); BOOST_TEST(check(val, "Hello, World")); utree val2; val2 = val; BOOST_TEST(check(val2, "Hello, World")); utree val3(utf8_symbol_type("Hello, World. Chuckie is back!!!")); val = val3; BOOST_TEST(check(val, "Hello, World. Chuckie is back!!!")); utree val4(utf8_symbol_type("Apple")); utree val5(utf8_symbol_type("Apple")); BOOST_TEST_EQ(val4, val5); utree val6(utf8_symbol_type("ApplePie")); BOOST_TEST(val4 < val6); } { // binary_strings utree val(binary_string_type("\xDE#\xAD")); BOOST_TEST(check(val, "#de23ad#" /* FIXME?: "#\xDE#\xAD#" */)); utree val2; val2 = val; BOOST_TEST(check(val2, "#de23ad#" /* FIXME?: "#\xDE#\xAD#" */)); utree val3(binary_string_type("\xDE\xAD\xBE\xEF")); val = val3; BOOST_TEST(check(val, "#deadbeef#" /* FIXME?: "#\xDE\xAD\xBE\xEF#" */)); utree val4(binary_string_type("\x01")); utree val5(binary_string_type("\x01")); BOOST_TEST_EQ(val4, val5); utree val6(binary_string_type("\x01\x02")); BOOST_TEST(val4 < val6); } { using boost::spirit::nil; utree val; val.push_back(123); val.push_back("Chuckie"); BOOST_TEST_EQ(val.size(), 2U); utree val2; val2.push_back(123.456); val2.push_back("Mah Doggie"); val.push_back(val2); BOOST_TEST_EQ(val.size(), 3U); BOOST_TEST(check(val, "( 123 \"Chuckie\" ( 123.456 \"Mah Doggie\" ) )")); BOOST_TEST(check(val.front(), "123")); utree val3(nil); val3.swap(val); BOOST_TEST_EQ(val3.size(), 3U); BOOST_TEST(check(val, "")); val3.swap(val); BOOST_TEST(check(val, "( 123 \"Chuckie\" ( 123.456 \"Mah Doggie\" ) )")); val.push_back("another string"); BOOST_TEST_EQ(val.size(), 4U); BOOST_TEST(check(val, "( 123 \"Chuckie\" ( 123.456 \"Mah Doggie\" ) \"another string\" )")); val.pop_front(); BOOST_TEST(check(val, "( \"Chuckie\" ( 123.456 \"Mah Doggie\" ) \"another string\" )")); utree::iterator i = val.begin(); ++++i; val.insert(i, "Right in the middle"); BOOST_TEST_EQ(val.size(), 4U); BOOST_TEST(check(val, "( \"Chuckie\" ( 123.456 \"Mah Doggie\" ) \"Right in the middle\" \"another string\" )")); val.pop_back(); BOOST_TEST(check(val, "( \"Chuckie\" ( 123.456 \"Mah Doggie\" ) \"Right in the middle\" )")); BOOST_TEST_EQ(val.size(), 3U); utree::iterator it = val.end(); --it; val.erase(it); BOOST_TEST(check(val, "( \"Chuckie\" ( 123.456 \"Mah Doggie\" ) )")); BOOST_TEST_EQ(val.size(), 2U); val.insert(val.begin(), val2.begin(), val2.end()); BOOST_TEST(check(val, "( 123.456 \"Mah Doggie\" \"Chuckie\" ( 123.456 \"Mah Doggie\" ) )")); BOOST_TEST_EQ(val.size(), 4U); // Regeression Ticket #6714 it = val.insert(val.end(), 111); BOOST_TEST(it != val.begin()); BOOST_TEST(it == --val.end()); BOOST_TEST(*it == 111); val.clear(); it = val.insert(val.begin(), 222); BOOST_TEST(it == val.begin()); BOOST_TEST(it == --val.end()); BOOST_TEST(*it == 222); // Regeression Ticket #6714 } { utree val; val.insert(val.end(), 123); val.insert(val.end(), "Mia"); val.insert(val.end(), "Chuckie"); val.insert(val.end(), "Poly"); val.insert(val.end(), "Mochi"); BOOST_TEST(check(val, "( 123 \"Mia\" \"Chuckie\" \"Poly\" \"Mochi\" )")); } { using boost::spirit::nil; using boost::spirit::invalid; utree a(nil), b(nil); BOOST_TEST_EQ(a, b); a = 123; BOOST_TEST(a != b); b = 123; BOOST_TEST_EQ(a, b); a = 100.00; BOOST_TEST(a < b); b = a = utree(invalid); BOOST_TEST_EQ(a, b); a.push_back(1); a.push_back("two"); a.push_back(3.0); b.push_back(1); b.push_back("two"); b.push_back(3.0); BOOST_TEST_EQ(a, b); b.push_back(4); BOOST_TEST(a != b); BOOST_TEST(a < b); } { using boost::spirit::empty_list; utree a(empty_list); a.push_back(0); a.push_back(0); a.push_back(0); a.push_back(0); a.push_back(0); a.push_back(0); a.push_back(0); a.push_back(0); a.push_back(0); a.push_back(0); a.push_back(0); a.push_back(0); for (utree::size_type i = 0; i < a.size(); ++i) get(a, i) = int(i + 1); BOOST_TEST_EQ(get(a, 0), utree(1)); BOOST_TEST_EQ(get(a, 1), utree(2)); BOOST_TEST_EQ(get(a, 2), utree(3)); BOOST_TEST_EQ(get(a, 3), utree(4)); BOOST_TEST_EQ(get(a, 4), utree(5)); BOOST_TEST_EQ(get(a, 5), utree(6)); BOOST_TEST_EQ(get(a, 6), utree(7)); BOOST_TEST_EQ(get(a, 7), utree(8)); BOOST_TEST_EQ(get(a, 8), utree(9)); BOOST_TEST_EQ(get(a, 9), utree(10)); BOOST_TEST_EQ(get(a, 10), utree(11)); BOOST_TEST_EQ(get(a, 11), utree(12)); } { // test empty list utree a; a.push_back(1); a.pop_front(); BOOST_TEST(check(a, "( )")); // the other way around utree b; b.push_front(1); b.pop_back(); BOOST_TEST(check(b, "( )")); } { // test references utree val(123); utree ref(boost::ref(val)); BOOST_TEST(check(ref, "123")); BOOST_TEST_EQ(ref, utree(123)); val.clear(); val.push_back(1); val.push_back(2); val.push_back(3); val.push_back(4); BOOST_TEST(check(ref, "( 1 2 3 4 )")); BOOST_TEST_EQ(get(ref, 0), utree(1)); BOOST_TEST_EQ(get(ref, 1), utree(2)); BOOST_TEST_EQ(get(ref, 2), utree(3)); BOOST_TEST_EQ(get(ref, 3), utree(4)); } { // put it in an array utree vals[] = { utree(123), utree("Hello, World"), utree(123.456) }; BOOST_TEST(check(vals[0], "123")); BOOST_TEST(check(vals[1], "\"Hello, World\"")); BOOST_TEST(check(vals[2], "123.456")); } { // operators BOOST_TEST((utree(false) && utree(false)) == utree(false)); BOOST_TEST((utree(false) && utree(true)) == utree(false)); BOOST_TEST((utree(true) && utree(false)) == utree(false)); BOOST_TEST((utree(true) && utree(true)) == utree(true)); BOOST_TEST((utree(0) && utree(0)) == utree(false)); BOOST_TEST((utree(0) && utree(1)) == utree(false)); BOOST_TEST((utree(1) && utree(0)) == utree(false)); BOOST_TEST((utree(1) && utree(1)) == utree(true)); BOOST_TEST((utree(false) || utree(false)) == utree(false)); BOOST_TEST((utree(false) || utree(true)) == utree(true)); BOOST_TEST((utree(true) || utree(false)) == utree(true)); BOOST_TEST((utree(true) || utree(true)) == utree(true)); BOOST_TEST((utree(0) || utree(0)) == utree(false)); BOOST_TEST((utree(0) || utree(1)) == utree(true)); BOOST_TEST((utree(1) || utree(0)) == utree(true)); BOOST_TEST((utree(1) || utree(1)) == utree(true)); BOOST_TEST((!utree(true)) == utree(false)); BOOST_TEST((!utree(false)) == utree(true)); BOOST_TEST((!utree(1)) == utree(false)); BOOST_TEST((!utree(0)) == utree(true)); BOOST_TEST((utree(456) + utree(123)) == utree(456 + 123)); BOOST_TEST((utree(456) + utree(123.456)) == utree(456 + 123.456)); BOOST_TEST((utree(456) - utree(123)) == utree(456 - 123)); BOOST_TEST((utree(456) - utree(123.456)) == utree(456 - 123.456)); BOOST_TEST((utree(456) * utree(123)) == utree(456 * 123)); BOOST_TEST((utree(456) * utree(123.456)) == utree(456 * 123.456)); BOOST_TEST((utree(456) / utree(123)) == utree(456 / 123)); BOOST_TEST((utree(456) / utree(123.456)) == utree(456 / 123.456)); BOOST_TEST((utree(456) % utree(123)) == utree(456 % 123)); BOOST_TEST(-utree(456) == utree(-456)); BOOST_TEST((utree(456) & utree(123)) == utree(456 & 123)); BOOST_TEST((utree(456) | utree(123)) == utree(456 | 123)); BOOST_TEST((utree(456) ^ utree(123)) == utree(456 ^ 123)); BOOST_TEST((utree(456) << utree(3)) == utree(456 << 3)); BOOST_TEST((utree(456) >> utree(2)) == utree(456 >> 2)); BOOST_TEST(~utree(456) == utree(~456)); } { // test reference iterator utree val; val.push_back(1); val.push_back(2); val.push_back(3); val.push_back(4); BOOST_TEST(check(val, "( 1 2 3 4 )")); utree::ref_iterator b = val.ref_begin(); utree::ref_iterator e = val.ref_end(); utree ref(boost::make_iterator_range(b, e)); BOOST_TEST_EQ(get(ref, 0), utree(1)); BOOST_TEST_EQ(get(ref, 1), utree(2)); BOOST_TEST_EQ(get(ref, 2), utree(3)); BOOST_TEST_EQ(get(ref, 3), utree(4)); BOOST_TEST(check(ref, "( 1 2 3 4 )")); } { // check the tag // TODO: test tags on all utree types utree x; x.tag(123); BOOST_TEST_EQ(x.tag(), 123); x = "hello world! my name is bob the builder"; x.tag(123); BOOST_TEST_EQ(x.tag(), 123); x.tag(456); BOOST_TEST_EQ(x.tag(), 456); BOOST_TEST_EQ(x.size(), 39U); BOOST_TEST(check(x, "\"hello world! my name is bob the builder\"")); x = "hello"; x.tag(456); BOOST_TEST_EQ(x.tag(), 456); x.tag(789); BOOST_TEST_EQ(x.tag(), 789); BOOST_TEST_EQ(x.size(), 5U); BOOST_TEST(check(x, "\"hello\"")); } { // test functions using boost::spirit::stored_function; utree f = stored_function(); f.eval(utree()); } { // test referenced functions using boost::spirit::referenced_function; one_two_three f; utree ff = referenced_function(f); BOOST_TEST_EQ(ff.eval(utree()), f(utree())); } { // shallow ranges using boost::spirit::shallow; utree val; val.push_back(1); val.push_back(2); val.push_back(3); val.push_back(4); utree::iterator i = val.begin(); ++i; utree alias(utree::range(i, val.end()), shallow); BOOST_TEST(check(alias, "( 2 3 4 )")); BOOST_TEST_EQ(alias.size(), 3U); BOOST_TEST_EQ(alias.front(), 2); BOOST_TEST_EQ(alias.back(), 4); BOOST_TEST(!alias.empty()); BOOST_TEST_EQ(get(alias, 1), 3); } { // shallow string ranges using boost::spirit::utf8_string_range_type; using boost::spirit::shallow; char const* s = "Hello, World"; utree val(utf8_string_range_type(s, s + strlen(s)), shallow); BOOST_TEST(check(val, "\"Hello, World\"")); utf8_string_range_type r = val.get(); utf8_string_range_type pf(r.begin()+1, r.end()-1); val = utree(pf, shallow); BOOST_TEST(check(val, "\"ello, Worl\"")); } { // any pointer using boost::spirit::any_ptr; int n = 123; utree up = any_ptr(&n); BOOST_TEST(*up.get() == 123); } // tags { short min = (std::numeric_limits::min)(); short max = (std::numeric_limits::max)(); utree::list_type u; utree u2; bool ok = true; for (int t = min ; ok && t <= max ; ++t) { u.tag(t); u2 = u; BOOST_TEST_EQ(t, u.tag()); BOOST_TEST_EQ(t, u2.tag()); ok = t == u.tag() && t == u2.tag(); u2 = utree("12"); } } return boost::report_errors(); }