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/assign/std/vector.hpp>
10
11 #include <boost/spirit/include/karma_char.hpp>
12 #include <boost/spirit/include/karma_string.hpp>
13 #include <boost/spirit/include/karma_numeric.hpp>
14 #include <boost/spirit/include/karma_generate.hpp>
15 #include <boost/spirit/include/karma_operator.hpp>
16 #include <boost/spirit/include/karma_action.hpp>
17 #include <boost/spirit/include/karma_nonterminal.hpp>
18 #include <boost/spirit/include/karma_auxiliary.hpp>
19 #include <boost/spirit/include/karma_directive.hpp>
20 #include <boost/fusion/include/vector.hpp>
21 #include <boost/spirit/include/phoenix_core.hpp>
22 #include <boost/spirit/include/phoenix_operator.hpp>
23 #include <boost/fusion/include/std_pair.hpp>
24
25 #include "test.hpp"
26
27 using namespace spirit_test;
28
29 ///////////////////////////////////////////////////////////////////////////////
30 struct action
31 {
actionaction32 action (std::vector<char>& vec)
33 : vec(vec), it(vec.begin())
34 {}
35
operator ()action36 void operator()(unsigned& value, boost::spirit::unused_type, bool& pass) const
37 {
38 pass = (it != vec.end());
39 if (pass)
40 value = *it++;
41 }
42
43 std::vector<char>& vec;
44 mutable std::vector<char>::iterator it;
45 };
46
47 ///////////////////////////////////////////////////////////////////////////////
main()48 int main()
49 {
50 using namespace boost::spirit;
51 using namespace boost::spirit::ascii;
52 namespace fusion = boost::fusion;
53
54 {
55 std::string s1("aaaa");
56 BOOST_TEST(test("aaaa", +char_, s1));
57 BOOST_TEST(test_delimited("a a a a ", +char_, s1, ' '));
58
59 std::string s2("a");
60 BOOST_TEST(test("a", +char_, s2));
61 BOOST_TEST(test_delimited("a ", +char_, s2, ' '));
62
63 std::string s3("");
64 BOOST_TEST(!test("", +char_, s2));
65 BOOST_TEST(!test_delimited("", +char_, s3, ' '));
66 }
67
68 {
69 std::string s1("aaaaa");
70 BOOST_TEST(test("aaaaa", char_ << +(char_ << char_), s1));
71 BOOST_TEST(test_delimited("a a a a a ",
72 char_ << +(char_ << char_), s1, ' '));
73
74 s1 = "a";
75 BOOST_TEST(!test("", char_ << +(char_ << char_), s1));
76 s1 = "aa";
77 BOOST_TEST(!test("", char_ << +(char_ << char_), s1));
78 s1 = "aaaa";
79 BOOST_TEST(!test("", char_ << +(char_ << char_), s1));
80 }
81
82 {
83 using boost::spirit::karma::strict;
84 using boost::spirit::karma::relaxed;
85 using namespace boost::assign;
86
87 typedef std::pair<char, char> data;
88 std::vector<data> v1;
89 v1 += std::make_pair('a', 'a'),
90 std::make_pair('b', 'b'),
91 std::make_pair('c', 'c'),
92 std::make_pair('d', 'd'),
93 std::make_pair('e', 'e'),
94 std::make_pair('f', 'f'),
95 std::make_pair('g', 'g');
96
97 karma::rule<spirit_test::output_iterator<char>::type, data()> r;
98 r = &char_('a') << char_;
99
100 BOOST_TEST(!test("", r << +(r << r), v1));
101 BOOST_TEST(!test("", relaxed[r << +(r << r)], v1));
102 BOOST_TEST(!test("", strict[r << +(r << r)], v1));
103
104 v1 += std::make_pair('a', 'a');
105
106 BOOST_TEST(!test("", r << *(r << r), v1));
107 BOOST_TEST(!test("", relaxed[r << +(r << r)], v1));
108 BOOST_TEST(!test("", strict[r << +(r << r)], v1));
109
110 v1 += std::make_pair('a', 'a');
111
112 BOOST_TEST(test("aaa", r << +(r << r), v1));
113 BOOST_TEST(test("aaa", relaxed[r << +(r << r)], v1));
114 BOOST_TEST(!test("", strict[r << +(r << r)], v1));
115 }
116
117 {
118 using namespace boost::assign;
119
120 std::vector<char> v;
121 v += 'a', 'b', 'c';
122
123 BOOST_TEST(test("abc", +char_, v));
124 BOOST_TEST(test_delimited("a b c ", +char_, v, ' '));
125 }
126
127 {
128 using namespace boost::assign;
129
130 std::vector<int> v;
131 v += 10, 20, 30;
132
133 BOOST_TEST(test("102030", +int_, v));
134 BOOST_TEST(test_delimited("10, 20, 30, ", +int_, v, lit(", ")));
135
136 BOOST_TEST(test("10,20,30,", +(int_ << ','), v));
137 BOOST_TEST(test_delimited("10 , 20 , 30 , ", +(int_ << ','), v, lit(' ')));
138
139 // leads to infinite loops
140 // fusion::vector<char, char> cc ('a', 'c');
141 // BOOST_TEST(test("ac", char_ << !+(lit(' ') << ',') << char_, cc));
142 // BOOST_TEST(test_delimited("a c ",
143 // char_ << !+(lit(' ') << ',') << char_, cc, " "));
144 }
145
146 { // actions
147 using namespace boost::assign;
148 namespace phx = boost::phoenix;
149
150 std::vector<char> v;
151 v += 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h';
152
153 BOOST_TEST(test("abcdefgh", (+char_)[_1 = phx::ref(v)]));
154 BOOST_TEST(test_delimited("a b c d e f g h ",
155 (+char_ )[_1 = phx::ref(v)], space));
156 }
157
158 // failing sub-generators
159 {
160 using boost::spirit::karma::strict;
161 using boost::spirit::karma::relaxed;
162
163 using namespace boost::assign;
164
165 typedef std::pair<char, char> data;
166 std::vector<data> v2;
167 v2 += std::make_pair('a', 'a'),
168 std::make_pair('b', 'b'),
169 std::make_pair('c', 'c'),
170 std::make_pair('d', 'd'),
171 std::make_pair('e', 'e'),
172 std::make_pair('f', 'f'),
173 std::make_pair('g', 'g');
174
175 karma::rule<spirit_test::output_iterator<char>::type, data()> r;
176
177 r = &char_('d') << char_;
178 BOOST_TEST(test("d", +r, v2));
179 BOOST_TEST(test("d", relaxed[+r], v2));
180 BOOST_TEST(!test("", strict[+r], v2));
181
182 r = &char_('a') << char_;
183 BOOST_TEST(test("a", +r, v2));
184 BOOST_TEST(test("a", relaxed[+r], v2));
185 BOOST_TEST(test("a", strict[+r], v2));
186
187 r = &char_('g') << char_;
188 BOOST_TEST(test("g", +r, v2));
189 BOOST_TEST(test("g", relaxed[+r], v2));
190 BOOST_TEST(!test("", strict[+r], v2));
191
192 r = !char_('d') << char_;
193 BOOST_TEST(test("abcefg", +r, v2));
194 BOOST_TEST(test("abcefg", relaxed[+r], v2));
195 BOOST_TEST(test("abc", strict[+r], v2));
196
197 r = !char_('a') << char_;
198 BOOST_TEST(test("bcdefg", +r, v2));
199 BOOST_TEST(test("bcdefg", relaxed[+r], v2));
200 BOOST_TEST(!test("", strict[+r], v2));
201
202 r = !char_('g') << char_;
203 BOOST_TEST(test("abcdef", +r, v2));
204 BOOST_TEST(test("abcdef", +r, v2));
205 BOOST_TEST(test("abcdef", +r, v2));
206
207 r = &char_('A') << char_;
208 BOOST_TEST(!test("", +r, v2));
209 }
210
211 {
212 // make sure user defined end condition is applied if no attribute
213 // is passed in
214 using namespace boost::assign;
215
216 std::vector<char> v;
217 v += 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h';
218 BOOST_TEST(test("[6162636465666768]", '[' << +hex[action(v)] << ']'));
219 }
220
221 return boost::report_errors();
222 }
223
224