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#include <boost/fusion/include/struct.hpp>
9#include <boost/fusion/include/nview.hpp>
10
11#include <boost/spirit/include/qi_char.hpp>
12#include <boost/spirit/include/qi_string.hpp>
13#include <boost/spirit/include/qi_numeric.hpp>
14#include <boost/spirit/include/qi_operator.hpp>
15#include <boost/spirit/include/qi_nonterminal.hpp>
16#include <boost/spirit/include/qi_auxiliary.hpp>
17
18#include <iostream>
19#include <vector>
20#include <string>
21#include "test.hpp"
22
23///////////////////////////////////////////////////////////////////////////////
24struct test_data
25{
26 std::string s1;
27 std::string s2;
28 int i1;
29 double d1;
30 std::string s3;
31};
32
33BOOST_FUSION_ADAPT_STRUCT(
34 test_data,
35 (int, i1)
36 (std::string, s1)
37 (std::string, s2)
38 (std::string, s3)
39 (double, d1)
40)
41
42///////////////////////////////////////////////////////////////////////////////
43struct test_int_data1
44{
45 int i;
46};
47
48// we provide a custom attribute transformation taking copy of the actual
49// attribute value, simulating more complex type transformations
50namespace boost { namespace spirit { namespace traits
51{
52 template <>
53 struct transform_attribute<test_int_data1, int, qi::domain>
54 {
55 typedef int type;
56 static int pre(test_int_data1& d) { return d.i; }
57 static void post(test_int_data1& d, int i) { d.i = i; }
58 static void fail(test_int_data1&) {}
59 };
60}}}
61
62///////////////////////////////////////////////////////////////////////////////
63struct test_int_data2
64{
65 int i;
66};
67
68// we provide a simple custom attribute transformation utilizing passing the
69// actual attribute by reference
70namespace boost { namespace spirit { namespace traits
71{
72 template <>
73 struct transform_attribute<test_int_data2, int, qi::domain>
74 {
75 typedef int& type;
76 static int& pre(test_int_data2& d) { return d.i; }
77 static void post(test_int_data2&, int const&) {}
78 static void fail(test_int_data2&) {}
79 };
80}}}
81
82///////////////////////////////////////////////////////////////////////////////
83int
84main()
85{
86 using spirit_test::test_attr;
87 namespace qi = boost::spirit::qi;
88 namespace fusion = boost::fusion;
89
90 {
91 std::vector<test_int_data1> v;
92 qi::rule<char const*, int()> r = qi::int_;
93
94 BOOST_TEST(test_attr("1,2", r % ',', v));
95 BOOST_TEST(v.size() == 2 && v[0].i == 1 && v[1].i == 2);
96 }
97
98 {
99 std::vector<double> v;
100 qi::rule<char const*, int()> r = qi::int_;
101
102 BOOST_TEST(test_attr("1,2", r % ',', v));
103 BOOST_TEST(v.size() == 2 && v[0] == 1.0 && v[1] == 2.0);
104 }
105
106 {
107 std::vector<test_int_data1> v;
108
109// this won't compile as there is no defined transformation for
110// test_int_data1 and double
111// BOOST_TEST(test_attr("1.0,2.2", qi::attr_cast(qi::double_) % ',', v));
112// BOOST_TEST(test_attr("1.0,2.2"
113// , qi::attr_cast<test_int_data1>(qi::double_) % ',', v));
114
115 BOOST_TEST(test_attr("1.0,2.2"
116 , qi::attr_cast<test_int_data1, int>(qi::double_) % ',', v));
117 BOOST_TEST(v.size() == 2 && v[0].i == 1 && v[1].i == 2);
118
119 qi::rule<char const*, int()> r = qi::double_;
120
121 v.clear();
122 BOOST_TEST(test_attr("1.0,2.0", r % ',', v));
123 BOOST_TEST(v.size() == 2 && v[0].i == 1 && v[1].i == 2);
124 }
125
126 // testing explicit transformation if attribute is taken by reference
127 {
128 test_int_data2 d = { .i: 0 };
129 BOOST_TEST(test_attr("1", qi::attr_cast(qi::int_), d));
130 BOOST_TEST(d.i == 1);
131 BOOST_TEST(test_attr("2", qi::attr_cast<test_int_data2>(qi::int_), d));
132 BOOST_TEST(d.i == 2);
133 BOOST_TEST(test_attr("3", qi::attr_cast<test_int_data2, int>(qi::int_), d));
134 BOOST_TEST(d.i == 3);
135 }
136
137 {
138 std::vector<test_int_data2> v;
139
140 BOOST_TEST(test_attr("1,2", qi::attr_cast(qi::int_) % ',', v));
141 BOOST_TEST(v.size() == 2 && v[0].i == 1 && v[1].i == 2);
142
143 v.clear();
144 BOOST_TEST(test_attr("1,2"
145 , qi::attr_cast<test_int_data2>(qi::int_) % ',', v));
146 BOOST_TEST(v.size() == 2 && v[0].i == 1 && v[1].i == 2);
147
148 v.clear();
149 BOOST_TEST(test_attr("1,2"
150 , qi::attr_cast<test_int_data2, int>(qi::int_) % ',', v));
151 BOOST_TEST(v.size() == 2 && v[0].i == 1 && v[1].i == 2);
152 }
153
154 {
155 std::vector<test_int_data2> v;
156 qi::rule<char const*, int()> r = qi::int_;
157
158 BOOST_TEST(test_attr("1,2", r % ',', v));
159 BOOST_TEST(v.size() == 2 && v[0].i == 1 && v[1].i == 2);
160 }
161
162 {
163 std::vector<test_int_data2> v;
164
165// this won't compile as there is no defined transformation for
166// test_int_data2 and double
167// BOOST_TEST(test_attr("1.0,2.2", qi::attr_cast(qi::double_) % ',', v));
168// BOOST_TEST(test_attr("1.0,2.2"
169// , qi::attr_cast<test_int_data2>(qi::double_) % ',', v));
170
171 BOOST_TEST(test_attr("1.0,2.2"
172 , qi::attr_cast<test_int_data2, int>(qi::double_) % ',', v));
173 BOOST_TEST(v.size() == 2 && v[0].i == 1 && v[1].i == 2);
174
175 qi::rule<char const*, int()> r = qi::double_;
176
177 v.clear();
178 BOOST_TEST(test_attr("1.0,2.0", r % ',', v));
179 BOOST_TEST(v.size() == 2 && v[0].i == 1 && v[1].i == 2);
180 }
181
182 return boost::report_errors();
183}
184

source code of boost/libs/spirit/test/qi/attribute2.cpp