1 /*=============================================================================
2     Copyright (c) 2001-2011 Hartmut Kaiser
3     Copyright (c) 2001-2011 Joel de Guzman
4 
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 
9 #include <boost/config/warning_disable.hpp>
10 #include <boost/detail/lightweight_test.hpp>
11 
12 #include <boost/spirit/include/karma_string.hpp>
13 #include <boost/spirit/include/karma_numeric.hpp>
14 #include <boost/spirit/include/karma_directive.hpp>
15 #include <boost/spirit/include/karma_operator.hpp>
16 #include <boost/spirit/include/karma_phoenix_attributes.hpp>
17 
18 #include <boost/spirit/include/phoenix_core.hpp>
19 #include <boost/spirit/include/phoenix_operator.hpp>
20 
21 #include "test.hpp"
22 
23 using namespace spirit_test;
24 
25 ///////////////////////////////////////////////////////////////////////////////
26 // special bool output policy allowing to spell false as true backwards (eurt)
27 struct special_bool_policy : boost::spirit::karma::bool_policies<>
28 {
29     template <typename CharEncoding, typename Tag
30       , typename OutputIterator>
generate_falsespecial_bool_policy31     static bool generate_false(OutputIterator& sink, bool)
32     {
33         //  we want to spell the names of true and false backwards
34         return boost::spirit::karma::string_inserter<CharEncoding, Tag>::
35             call(sink, "eurt");
36     }
37 };
38 
39 ///////////////////////////////////////////////////////////////////////////////
40 // special policy allowing to use any type as a boolean
41 struct test_bool_data
42 {
test_bool_datatest_bool_data43     explicit test_bool_data(bool b) : b(b) {}
44 
45     bool b;
46 
47     // we need to provide (safe) convertibility to bool
48 private:
true_test_bool_data::dummy49     struct dummy { void true_() {} };
50     typedef void (dummy::*safe_bool)();
51 
52 public:
operator safe_booltest_bool_data53     operator safe_bool () const { return b ? &dummy::true_ : 0; }
54 };
55 
56 struct test_bool_policy : boost::spirit::karma::bool_policies<>
57 {
58     template <typename Inserter, typename OutputIterator, typename Policies>
59     static bool
calltest_bool_policy60     call (OutputIterator& sink, test_bool_data b, Policies const& p)
61     {
62         //  call the predefined inserter to do the job
63         return Inserter::call_n(sink, bool(b), p);
64     }
65 };
66 
67 
68 ///////////////////////////////////////////////////////////////////////////////
main()69 int main()
70 {
71     using boost::spirit::karma::bool_;
72     using boost::spirit::karma::false_;
73     using boost::spirit::karma::true_;
74     using boost::spirit::karma::lit;
75     using boost::spirit::karma::lower;
76     using boost::spirit::karma::upper;
77 
78     // testing plain bool
79     {
80         BOOST_TEST(test("false", bool_, false));
81         BOOST_TEST(test("true", bool_, true));
82         BOOST_TEST(test("false", false_, false));
83         BOOST_TEST(test("true", true_, true));
84         BOOST_TEST(test("false", bool_(false)));
85         BOOST_TEST(test("true", bool_(true)));
86         BOOST_TEST(test("false", bool_(false), false));
87         BOOST_TEST(test("true", bool_(true), true));
88         BOOST_TEST(!test("", bool_(false), true));
89         BOOST_TEST(!test("", bool_(true), false));
90         BOOST_TEST(test("false", lit(false)));
91         BOOST_TEST(test("true", lit(true)));
92     }
93 
94     // test optional attributes
95     {
96         boost::optional<bool> optbool;
97 
98         BOOST_TEST(!test("", bool_, optbool));
99         BOOST_TEST(test("", -bool_, optbool));
100         optbool = false;
101         BOOST_TEST(test("false", bool_, optbool));
102         BOOST_TEST(test("false", -bool_, optbool));
103         optbool = true;
104         BOOST_TEST(test("true", bool_, optbool));
105         BOOST_TEST(test("true", -bool_, optbool));
106     }
107 
108 // we support Phoenix attributes only starting with V2.2
109 #if SPIRIT_VERSION >= 0x2020
110     // test Phoenix expression attributes (requires to include
111     // karma_phoenix_attributes.hpp)
112     {
113         namespace phoenix = boost::phoenix;
114 
115         BOOST_TEST(test("true", bool_, phoenix::val(true)));
116 
117         bool b = false;
118         BOOST_TEST(test("false", bool_, phoenix::ref(b)));
119         BOOST_TEST(test("true", bool_, !phoenix::ref(b)));
120     }
121 #endif
122 
123     {
124         BOOST_TEST(test("false", lower[bool_], false));
125         BOOST_TEST(test("true", lower[bool_], true));
126         BOOST_TEST(test("false", lower[bool_(false)]));
127         BOOST_TEST(test("true", lower[bool_(true)]));
128         BOOST_TEST(test("false", lower[bool_(false)], false));
129         BOOST_TEST(test("true", lower[bool_(true)], true));
130         BOOST_TEST(!test("", lower[bool_(false)], true));
131         BOOST_TEST(!test("", lower[bool_(true)], false));
132         BOOST_TEST(test("false", lower[lit(false)]));
133         BOOST_TEST(test("true", lower[lit(true)]));
134     }
135 
136     {
137         BOOST_TEST(test("FALSE", upper[bool_], false));
138         BOOST_TEST(test("TRUE", upper[bool_], true));
139         BOOST_TEST(test("FALSE", upper[bool_(false)]));
140         BOOST_TEST(test("TRUE", upper[bool_(true)]));
141         BOOST_TEST(test("FALSE", upper[bool_(false)], false));
142         BOOST_TEST(test("TRUE", upper[bool_(true)], true));
143         BOOST_TEST(!test("", upper[bool_(false)], true));
144         BOOST_TEST(!test("", upper[bool_(true)], false));
145         BOOST_TEST(test("FALSE", upper[lit(false)]));
146         BOOST_TEST(test("TRUE", upper[lit(true)]));
147     }
148 
149     {
150         typedef boost::spirit::karma::bool_generator<bool, special_bool_policy>
151             backwards_bool_type;
152         backwards_bool_type const backwards_bool = backwards_bool_type();
153 
154         BOOST_TEST(test("eurt", backwards_bool, false));
155         BOOST_TEST(test("true", backwards_bool, true));
156         BOOST_TEST(test("eurt", backwards_bool(false)));
157         BOOST_TEST(test("true", backwards_bool(true)));
158         BOOST_TEST(test("eurt", backwards_bool(false), false));
159         BOOST_TEST(test("true", backwards_bool(true), true));
160         BOOST_TEST(!test("", backwards_bool(false), true));
161         BOOST_TEST(!test("", backwards_bool(true), false));
162     }
163 
164     {
165         typedef boost::spirit::karma::bool_generator<
166             test_bool_data, test_bool_policy> test_bool_type;
167         test_bool_type const test_bool = test_bool_type();
168 
169         test_bool_data const test_false = test_bool_data(false);
170         test_bool_data const test_true = test_bool_data(true);
171 
172         BOOST_TEST(test("false", test_bool, test_false));
173         BOOST_TEST(test("true", test_bool, test_true));
174         BOOST_TEST(test("false", test_bool(test_false)));
175         BOOST_TEST(test("true", test_bool(test_true)));
176         BOOST_TEST(test("false", test_bool(test_false), test_false));
177         BOOST_TEST(test("true", test_bool(test_true), test_true));
178         BOOST_TEST(!test("", test_bool(test_false), test_true));
179         BOOST_TEST(!test("", test_bool(test_true), test_false));
180     }
181 
182     return boost::report_errors();
183 }
184 
185