502 lines
15 KiB
C++
502 lines
15 KiB
C++
/*=============================================================================
|
|
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 <boost/config/warning_disable.hpp>
|
|
#include <boost/detail/lightweight_test.hpp>
|
|
|
|
#include <boost/functional/hash.hpp>
|
|
#include <boost/spirit/include/support_utree.hpp>
|
|
|
|
#include <iostream>
|
|
#include <sstream>
|
|
#include <cstdlib>
|
|
|
|
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<int>(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, "<nil>"));
|
|
}
|
|
|
|
{
|
|
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, "<nil>"));
|
|
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<one_two_three>();
|
|
f.eval(utree());
|
|
}
|
|
|
|
{
|
|
// test referenced functions
|
|
using boost::spirit::referenced_function;
|
|
|
|
one_two_three f;
|
|
utree ff = referenced_function<one_two_three>(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>();
|
|
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<int*>() == 123);
|
|
}
|
|
|
|
// tags
|
|
{
|
|
short min = (std::numeric_limits<short>::min)();
|
|
short max = (std::numeric_limits<short>::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();
|
|
}
|