1 //  Copyright (c) 2001-2011 Hartmut Kaiser
2 //
3 //  Distributed under the Boost Software License, Version 1.0. (See accompanying
4 //  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5 
6 #include <boost/config/warning_disable.hpp>
7 #include <boost/detail/lightweight_test.hpp>
8 
9 #include <boost/spirit/include/phoenix_limits.hpp>
10 
11 #include <boost/fusion/include/struct.hpp>
12 #include <boost/fusion/include/nview.hpp>
13 
14 #include <boost/spirit/include/karma_char.hpp>
15 #include <boost/spirit/include/karma_string.hpp>
16 #include <boost/spirit/include/karma_numeric.hpp>
17 #include <boost/spirit/include/karma_operator.hpp>
18 #include <boost/spirit/include/karma_nonterminal.hpp>
19 #include <boost/spirit/include/karma_auxiliary.hpp>
20 
21 #include "test.hpp"
22 
23 using namespace spirit_test;
24 
25 ///////////////////////////////////////////////////////////////////////////////
26 struct test_data
27 {
28     std::string s1;
29     std::string s2;
30     int i1;
31     double d1;
32     std::string s3;
33 };
34 
35 BOOST_FUSION_ADAPT_STRUCT(
36     test_data,
37     (int, i1)
38     (std::string, s1)
39     (std::string, s2)
40     (std::string, s3)
41     (double, d1)
42 )
43 
44 ///////////////////////////////////////////////////////////////////////////////
45 // this is just a test structure we need to use in place of an int
46 struct test_int_data1
47 {
48     int i;
49 };
50 
51 // so we provide a custom attribute transformation
52 namespace boost { namespace spirit { namespace traits
53 {
54     template <>
55     struct transform_attribute<test_int_data1 const, int, karma::domain>
56     {
57         typedef int type;
preboost::spirit::traits::transform_attribute58         static int pre(test_int_data1 const& d) { return d.i; }
59     };
60 }}}
61 
62 ///////////////////////////////////////////////////////////////////////////////
63 // this is another test structure we need to use in place of an int, but this
64 // time we use a reference to the embedded element
65 struct test_int_data2
66 {
67     int i;
68 };
69 
70 // so we provide a custom attribute transformation
71 namespace boost { namespace spirit { namespace traits
72 {
73     template <>
74     struct transform_attribute<test_int_data2 const, int, karma::domain>
75     {
76         typedef int const& type;
preboost::spirit::traits::transform_attribute77         static int const& pre(test_int_data2 const& d) { return d.i; }
78     };
79 }}}
80 
81 ///////////////////////////////////////////////////////////////////////////////
main()82 int main()
83 {
84     namespace fusion = boost::fusion;
85     namespace karma = boost::spirit::karma;
86 
87     test_data d1 = { "s11", "s12", 1, 2.5, "s13" };
88     {
89 
90         BOOST_TEST(test("s121",
91             karma::string << karma::int_,
92             fusion::as_nview<2, 0>(d1)));
93 
94         BOOST_TEST(test_delimited("s12 1 ",
95             karma::string << karma::int_,
96             fusion::as_nview<2, 0>(d1), ' '));
97     }
98 
99     {
100         test_data d2 = { "s21", "s22", 2, 3.4, "s23" };
101         typedef fusion::result_of::as_nview<test_data const, 1, 2, 4>::type
102             test_view;
103         std::vector<test_data> v;
104         v.push_back(d1);
105         v.push_back(d2);
106 
107         karma::rule<output_iterator<char>::type, test_view()> r =
108                 karma::string << karma::string << karma::double_;
109 
110         BOOST_TEST(test("s11s122.5\ns21s223.4", r % karma::eol, v));
111         BOOST_TEST(test_delimited("s11s122.5 \n s21s223.4 ",
112             r % karma::eol, v, ' '));
113     }
114 
115     {
116         test_int_data1 d = { 1 };
117         BOOST_TEST(test("1", karma::attr_cast(karma::int_), d));
118         BOOST_TEST(test("1", karma::attr_cast<test_int_data1>(karma::int_), d));
119         BOOST_TEST(test("1", karma::attr_cast<test_int_data1, int>(karma::int_), d));
120     }
121 
122     {
123         test_int_data1 d[] = {{ 1 }, { 2 }};
124         std::vector<test_int_data1> v;
125         v.push_back(d[0]);
126         v.push_back(d[1]);
127 
128         BOOST_TEST(test("1,2", karma::attr_cast(karma::int_) % ',', v));
129         BOOST_TEST(test("1,2"
130           , karma::attr_cast<test_int_data1>(karma::int_) % ',', v));
131         BOOST_TEST(test("1,2"
132           , karma::attr_cast<test_int_data1, int>(karma::int_) % ',', v));
133     }
134 
135     {
136         test_int_data1 d[] = {{ 1 }, { 2 }};
137         std::vector<test_int_data1> v;
138         v.push_back(d[0]);
139         v.push_back(d[1]);
140 
141         karma::rule<output_iterator<char>::type, int()> r = karma::int_;
142         BOOST_TEST(test("1,2", r % ',', v));
143     }
144 
145     {
146         test_int_data1 d[] = {{ 1 }, { 2 }};
147         std::vector<test_int_data1> v;
148         v.push_back(d[0]);
149         v.push_back(d[1] );
150 
151 // this won't compile as there is no defined transformation for
152 // test_int_data1 and double
153 //      BOOST_TEST(test("1.0,2.0", karma::attr_cast(karma::double_) % ',', v));
154 //      BOOST_TEST(test("1.0,2.0"
155 //        , karma::attr_cast<test_int_data1>(karma::double_) % ',', v));
156 
157         BOOST_TEST(test("1.0,2.0"
158           , karma::attr_cast<test_int_data1, int>(karma::double_) % ',', v));
159 
160         karma::rule<output_iterator<char>::type, int()> r = karma::double_;
161         BOOST_TEST(test("1.0,2.0", r % ',', v));
162     }
163 
164     {
165         test_int_data2 d = { 1 };
166         BOOST_TEST(test("1", karma::attr_cast(karma::int_), d));
167         BOOST_TEST(test("1", karma::attr_cast<test_int_data2>(karma::int_), d));
168         BOOST_TEST(test("1", karma::attr_cast<test_int_data2, int>(karma::int_), d));
169     }
170 
171     {
172         test_int_data2 d[] = {{ 1 }, { 2 }};
173         std::vector<test_int_data2> v;
174         v.push_back(d[0]);
175         v.push_back(d[1]);
176 
177         BOOST_TEST(test("1,2", karma::attr_cast(karma::int_) % ',', v));
178         BOOST_TEST(test("1,2"
179           , karma::attr_cast<test_int_data2>(karma::int_) % ',', v));
180         BOOST_TEST(test("1,2"
181           , karma::attr_cast<test_int_data2, int>(karma::int_) % ',', v));
182     }
183 
184     {
185         test_int_data2 d[] = {{ 1 }, { 2 }};
186         std::vector<test_int_data2> v;
187         v.push_back(d[0]);
188         v.push_back(d[1]);
189 
190         karma::rule<output_iterator<char>::type, int()> r = karma::int_;
191         BOOST_TEST(test("1,2", r % ',', v));
192     }
193 
194     {
195         test_int_data2 d[] = {{ 1 }, { 2 }};
196         std::vector<test_int_data2> v;
197         v.push_back(d[0]);
198         v.push_back(d[1] );
199 
200 // this won't compile as there is no defined transformation for
201 // test_int_data2 and double
202 //      BOOST_TEST(test("1.0,2.0", karma::attr_cast(karma::double_) % ',', v));
203 //      BOOST_TEST(test("1.0,2.0"
204 //        , karma::attr_cast<test_int_data2>(karma::double_) % ',', v));
205 
206         BOOST_TEST(test("1.0,2.0"
207           , karma::attr_cast<test_int_data2, int>(karma::double_) % ',', v));
208 
209         karma::rule<output_iterator<char>::type, int()> r = karma::double_;
210         BOOST_TEST(test("1.0,2.0", r % ',', v));
211     }
212 
213     return boost::report_errors();
214 }
215