comparison DEPENDENCIES/generic/include/boost/spirit/home/karma/string/lit.hpp @ 16:2665513ce2d3

Add boost headers
author Chris Cannam
date Tue, 05 Aug 2014 11:11:38 +0100
parents
children
comparison
equal deleted inserted replaced
15:663ca0da4350 16:2665513ce2d3
1 // Copyright (c) 2001-2011 Hartmut Kaiser
2 // Copyright (c) 2010 Bryce Lelbach
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6
7 #if !defined(BOOST_SPIRIT_KARMA_LIT_FEB_22_2007_0534PM)
8 #define BOOST_SPIRIT_KARMA_LIT_FEB_22_2007_0534PM
9
10 #if defined(_MSC_VER)
11 #pragma once
12 #endif
13
14 #include <boost/spirit/home/support/common_terminals.hpp>
15 #include <boost/spirit/home/support/string_traits.hpp>
16 #include <boost/spirit/home/support/info.hpp>
17 #include <boost/spirit/home/support/char_class.hpp>
18 #include <boost/spirit/home/support/container.hpp>
19 #include <boost/spirit/home/support/handles_container.hpp>
20 #include <boost/spirit/home/support/detail/get_encoding.hpp>
21 #include <boost/spirit/home/karma/domain.hpp>
22 #include <boost/spirit/home/karma/meta_compiler.hpp>
23 #include <boost/spirit/home/karma/delimit_out.hpp>
24 #include <boost/spirit/home/karma/auxiliary/lazy.hpp>
25 #include <boost/spirit/home/karma/detail/get_casetag.hpp>
26 #include <boost/spirit/home/karma/detail/extract_from.hpp>
27 #include <boost/spirit/home/karma/detail/string_generate.hpp>
28 #include <boost/spirit/home/karma/detail/string_compare.hpp>
29 #include <boost/spirit/home/karma/detail/enable_lit.hpp>
30 #include <boost/fusion/include/at.hpp>
31 #include <boost/fusion/include/vector.hpp>
32 #include <boost/fusion/include/cons.hpp>
33 #include <boost/mpl/if.hpp>
34 #include <boost/mpl/or.hpp>
35 #include <boost/mpl/assert.hpp>
36 #include <boost/mpl/bool.hpp>
37 #include <boost/utility/enable_if.hpp>
38 #include <string>
39
40 ///////////////////////////////////////////////////////////////////////////////
41 namespace boost { namespace spirit
42 {
43 ///////////////////////////////////////////////////////////////////////////
44 // Enablers
45 ///////////////////////////////////////////////////////////////////////////
46 template <typename CharEncoding>
47 struct use_terminal<karma::domain
48 , tag::char_code<tag::string, CharEncoding> > // enables string
49 : mpl::true_ {};
50
51 template <typename T>
52 struct use_terminal<karma::domain, T
53 , typename enable_if<traits::is_string<T> >::type> // enables string literals
54 : mpl::true_ {};
55
56 template <typename CharEncoding, typename A0>
57 struct use_terminal<karma::domain
58 , terminal_ex<
59 tag::char_code<tag::string, CharEncoding> // enables string(str)
60 , fusion::vector1<A0> >
61 > : traits::is_string<A0> {};
62
63 template <typename CharEncoding> // enables string(f)
64 struct use_lazy_terminal<
65 karma::domain
66 , tag::char_code<tag::string, CharEncoding>
67 , 1 /*arity*/
68 > : mpl::true_ {};
69
70 // enables lit(str)
71 template <typename A0>
72 struct use_terminal<karma::domain
73 , terminal_ex<tag::lit, fusion::vector1<A0> >
74 , typename enable_if<traits::is_string<A0> >::type>
75 : mpl::true_ {};
76 }}
77
78 ///////////////////////////////////////////////////////////////////////////////
79 namespace boost { namespace spirit { namespace karma
80 {
81 #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
82 using spirit::lit;
83 #endif
84 using spirit::lit_type;
85
86 ///////////////////////////////////////////////////////////////////////////
87 // generate literal strings from a given parameter
88 ///////////////////////////////////////////////////////////////////////////
89 template <typename CharEncoding, typename Tag>
90 struct any_string
91 : primitive_generator<any_string<CharEncoding, Tag> >
92 {
93 typedef typename CharEncoding::char_type char_type;
94 typedef CharEncoding char_encoding;
95
96 template <typename Context, typename Unused = unused_type>
97 struct attribute
98 {
99 typedef std::basic_string<char_type> type;
100 };
101
102 // lit has an attached attribute
103 template <typename OutputIterator, typename Context, typename Delimiter
104 , typename Attribute>
105 static bool
106 generate(OutputIterator& sink, Context& context, Delimiter const& d,
107 Attribute const& attr)
108 {
109 if (!traits::has_optional_value(attr))
110 return false;
111
112 typedef typename attribute<Context>::type attribute_type;
113 return
114 karma::detail::string_generate(sink
115 , traits::extract_from<attribute_type>(attr, context)
116 , char_encoding(), Tag()) &&
117 karma::delimit_out(sink, d); // always do post-delimiting
118 }
119
120 // this lit has no attribute attached, it needs to have been
121 // initialized from a direct literal
122 template <typename OutputIterator, typename Context, typename Delimiter>
123 static bool generate(OutputIterator&, Context&, Delimiter const&,
124 unused_type const&)
125 {
126 // It is not possible (doesn't make sense) to use string without
127 // providing any attribute, as the generator doesn't 'know' what
128 // character to output. The following assertion fires if this
129 // situation is detected in your code.
130 BOOST_SPIRIT_ASSERT_FAIL(OutputIterator, string_not_usable_without_attribute, ());
131 return false;
132 }
133
134 template <typename Context>
135 static info what(Context const& /*context*/)
136 {
137 return info("any-string");
138 }
139 };
140
141 ///////////////////////////////////////////////////////////////////////////
142 // generate literal strings
143 ///////////////////////////////////////////////////////////////////////////
144 template <typename String, typename CharEncoding, typename Tag, bool no_attribute>
145 struct literal_string
146 : primitive_generator<literal_string<String, CharEncoding, Tag, no_attribute> >
147 {
148 typedef CharEncoding char_encoding;
149 typedef typename
150 remove_const<typename traits::char_type_of<String>::type>::type
151 char_type;
152 typedef std::basic_string<char_type> string_type;
153
154 template <typename Context, typename Unused = unused_type>
155 struct attribute
156 : mpl::if_c<no_attribute, unused_type, string_type>
157 {};
158
159 literal_string(typename add_reference<String>::type str)
160 : str_(str)
161 {}
162
163 // A string("...") which additionally has an associated attribute emits
164 // its immediate literal only if it matches the attribute, otherwise
165 // it fails.
166 template <
167 typename OutputIterator, typename Context, typename Delimiter
168 , typename Attribute>
169 bool generate(OutputIterator& sink, Context& context
170 , Delimiter const& d, Attribute const& attr) const
171 {
172 if (!traits::has_optional_value(attr))
173 return false;
174
175 // fail if attribute isn't matched by immediate literal
176 typedef typename attribute<Context>::type attribute_type;
177
178 typedef typename spirit::result_of::extract_from<attribute_type, Attribute>::type
179 extracted_string_type;
180
181 using spirit::traits::get_c_string;
182 if (!detail::string_compare(
183 get_c_string(
184 traits::extract_from<attribute_type>(attr, context))
185 , get_c_string(str_), char_encoding(), Tag()))
186 {
187 return false;
188 }
189 return detail::string_generate(sink, str_, char_encoding(), Tag()) &&
190 karma::delimit_out(sink, d); // always do post-delimiting
191 }
192
193 // A string("...") without any associated attribute just emits its
194 // immediate literal
195 template <typename OutputIterator, typename Context, typename Delimiter>
196 bool generate(OutputIterator& sink, Context&, Delimiter const& d
197 , unused_type) const
198 {
199 return detail::string_generate(sink, str_, char_encoding(), Tag()) &&
200 karma::delimit_out(sink, d); // always do post-delimiting
201 }
202
203 template <typename Context>
204 info what(Context const& /*context*/) const
205 {
206 return info("literal-string", str_);
207 }
208
209 string_type str_;
210 };
211
212 ///////////////////////////////////////////////////////////////////////////
213 // Generator generators: make_xxx function (objects)
214 ///////////////////////////////////////////////////////////////////////////
215
216 // string
217 template <typename CharEncoding, typename Modifiers>
218 struct make_primitive<
219 tag::char_code<tag::string, CharEncoding>
220 , Modifiers>
221 {
222 static bool const lower =
223 has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
224 static bool const upper =
225 has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
226
227 typedef any_string<
228 typename spirit::detail::get_encoding_with_case<
229 Modifiers, CharEncoding, lower || upper>::type
230 , typename detail::get_casetag<Modifiers, lower || upper>::type
231 > result_type;
232
233 result_type operator()(unused_type, unused_type) const
234 {
235 return result_type();
236 }
237 };
238
239 // string literal
240 template <typename T, typename Modifiers>
241 struct make_primitive<T, Modifiers
242 , typename enable_if<traits::is_string<T> >::type>
243 {
244 static bool const lower =
245 has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
246
247 static bool const upper =
248 has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
249
250 typedef typename add_const<T>::type const_string;
251 typedef literal_string<
252 const_string
253 , typename spirit::detail::get_encoding_with_case<
254 Modifiers, unused_type, lower || upper>::type
255 , typename detail::get_casetag<Modifiers, lower || upper>::type
256 , true
257 > result_type;
258
259 result_type operator()(
260 typename add_reference<const_string>::type str, unused_type) const
261 {
262 return result_type(str);
263 }
264 };
265
266 ///////////////////////////////////////////////////////////////////////////
267 namespace detail
268 {
269 template <typename CharEncoding, typename Modifiers, typename A0
270 , bool no_attribute>
271 struct make_string_direct
272 {
273 static bool const lower =
274 has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
275 static bool const upper =
276 has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
277
278 typedef typename add_const<A0>::type const_string;
279 typedef literal_string<
280 const_string
281 , typename spirit::detail::get_encoding_with_case<
282 Modifiers, unused_type, lower || upper>::type
283 , typename detail::get_casetag<Modifiers, lower || upper>::type
284 , no_attribute
285 > result_type;
286
287 template <typename Terminal>
288 result_type operator()(Terminal const& term, unused_type) const
289 {
290 return result_type(fusion::at_c<0>(term.args));
291 }
292 };
293 }
294
295 // string("..."), lit("...")
296 template <typename CharEncoding, typename Modifiers, typename A0>
297 struct make_primitive<
298 terminal_ex<
299 tag::char_code<tag::string, CharEncoding>
300 , fusion::vector1<A0> >
301 , Modifiers>
302 : detail::make_string_direct<CharEncoding, Modifiers, A0, false>
303 {};
304
305 template <typename Modifiers, typename A0>
306 struct make_primitive<
307 terminal_ex<tag::lit, fusion::vector1<A0> >
308 , Modifiers
309 , typename enable_if<traits::is_string<A0> >::type>
310 : detail::make_string_direct<
311 typename traits::char_encoding_from_char<
312 typename traits::char_type_of<A0>::type>::type
313 , Modifiers, A0, true>
314 {};
315 }}} // namespace boost::spirit::karma
316
317 namespace boost { namespace spirit { namespace traits
318 {
319 ///////////////////////////////////////////////////////////////////////////
320 template <typename CharEncoding, typename Tag, typename Attribute
321 , typename Context, typename Iterator>
322 struct handles_container<karma::any_string<CharEncoding, Tag>, Attribute
323 , Context, Iterator>
324 : mpl::false_ {};
325
326 template <typename String, typename CharEncoding, typename Tag
327 , bool no_attribute, typename Attribute, typename Context
328 , typename Iterator>
329 struct handles_container<karma::literal_string<String, CharEncoding, Tag
330 , no_attribute>, Attribute, Context, Iterator>
331 : mpl::false_ {};
332 }}}
333
334 #endif