PageRenderTime 41ms CodeModel.GetById 13ms app.highlight 23ms RepoModel.GetById 1ms app.codeStats 0ms

/Src/Dependencies/Boost/boost/spirit/home/karma/string/lit.hpp

http://hadesmem.googlecode.com/
C++ Header | 334 lines | 255 code | 41 blank | 38 comment | 11 complexity | 8e69ed380993cb7db463aa7254b635cb MD5 | raw file
  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///////////////////////////////////////////////////////////////////////////////
 41namespace 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///////////////////////////////////////////////////////////////////////////////
 79namespace 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_MSG(false, 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
317namespace 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