Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-19 09:47:36

0001 //  Copyright (c) 2001-2011 Hartmut Kaiser
0002 //
0003 //  Distributed under the Boost Software License, Version 1.0. (See accompanying
0004 //  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0005 
0006 #if !defined(BOOST_SPIRIT_KARMA_COLUMNS_DEC_03_2009_0736AM)
0007 #define BOOST_SPIRIT_KARMA_COLUMNS_DEC_03_2009_0736AM
0008 
0009 #if defined(_MSC_VER)
0010 #pragma once
0011 #endif
0012 
0013 #include <boost/spirit/home/karma/meta_compiler.hpp>
0014 #include <boost/spirit/home/karma/generator.hpp>
0015 #include <boost/spirit/home/karma/domain.hpp>
0016 #include <boost/spirit/home/karma/delimit_out.hpp>
0017 #include <boost/spirit/home/karma/detail/default_width.hpp>
0018 #include <boost/spirit/home/karma/auxiliary/eol.hpp>
0019 #include <boost/spirit/home/karma/auxiliary/lazy.hpp>
0020 #include <boost/spirit/home/support/unused.hpp>
0021 #include <boost/spirit/home/support/common_terminals.hpp>
0022 #include <boost/spirit/home/support/has_semantic_action.hpp>
0023 #include <boost/spirit/home/support/handles_container.hpp>
0024 #include <boost/spirit/home/karma/detail/attributes.hpp>
0025 #include <boost/spirit/home/support/info.hpp>
0026 #include <boost/fusion/include/at.hpp>
0027 #include <boost/fusion/include/vector.hpp>
0028 #include <boost/integer_traits.hpp>
0029 
0030 namespace boost { namespace spirit
0031 {
0032     ///////////////////////////////////////////////////////////////////////////
0033     // Enablers
0034     ///////////////////////////////////////////////////////////////////////////
0035     template <>
0036     struct use_directive<karma::domain, tag::columns>   // enables columns[]
0037       : mpl::true_ {};
0038 
0039     // enables columns(c)[g], where c provides the number of require columns
0040     template <typename T>
0041     struct use_directive<karma::domain
0042           , terminal_ex<tag::columns, fusion::vector1<T> > > 
0043       : mpl::true_ {};
0044 
0045     // enables *lazy* columns(c)[g]
0046     template <>
0047     struct use_lazy_directive<karma::domain, tag::columns, 1> 
0048       : mpl::true_ {};
0049 
0050     // enables columns(c, d)[g], where c provides the number of require columns
0051     // and d is the custom column-delimiter (default is karma::endl)
0052     template <typename T1, typename T2>
0053     struct use_directive<karma::domain
0054           , terminal_ex<tag::columns, fusion::vector2<T1, T2> > > 
0055       : boost::spirit::traits::matches<karma::domain, T2> {};
0056 
0057     // enables *lazy* columns(c, d)[g]
0058     template <>
0059     struct use_lazy_directive<karma::domain, tag::columns, 2> 
0060       : mpl::true_ {};
0061 
0062 }}
0063 
0064 namespace boost { namespace spirit { namespace karma
0065 {
0066 #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
0067     using spirit::columns;
0068 #endif
0069     using spirit::columns_type;
0070 
0071     namespace detail
0072     {
0073 #ifdef _MSC_VER
0074 #  pragma warning(push)
0075 #  pragma warning(disable: 4512) // assignment operator could not be generated.
0076 #endif
0077         template <typename Delimiter, typename ColumnDelimiter>
0078         struct columns_delimiter 
0079         {
0080             columns_delimiter(Delimiter const& delim
0081                   , ColumnDelimiter const& cdelim, unsigned int const numcols)
0082               : delimiter(delim), column_delimiter(cdelim)
0083               , numcolumns(numcols), count(0) {}
0084 
0085             template <typename OutputIterator, typename Context
0086               , typename Delimiter_, typename Attribute>
0087             bool generate(OutputIterator& sink, Context&, Delimiter_ const&
0088               , Attribute const&) const
0089             {
0090                 // first invoke the embedded delimiter
0091                 if (!karma::delimit_out(sink, delimiter))
0092                     return false;
0093 
0094                 // now we count the number of invocations and emit the column 
0095                 // delimiter if needed
0096                 if ((++count % numcolumns) == 0)
0097                     return karma::delimit_out(sink, column_delimiter);
0098                 return true;
0099             }
0100 
0101             // generate a final column delimiter if the last invocation didn't 
0102             // emit one
0103             template <typename OutputIterator>
0104             bool delimit_out(OutputIterator& sink) const
0105             {
0106                 if (count % numcolumns)
0107                     return karma::delimit_out(sink, column_delimiter);
0108                 return true;
0109             }
0110 
0111             Delimiter const& delimiter;
0112             ColumnDelimiter const& column_delimiter;
0113             unsigned int const numcolumns;
0114             mutable unsigned int count;
0115         };
0116 #ifdef _MSC_VER
0117 #  pragma warning(pop)
0118 #endif
0119     }
0120 
0121     ///////////////////////////////////////////////////////////////////////////
0122     //  The columns_generator is used for columns(c, d)[...] directives.
0123     ///////////////////////////////////////////////////////////////////////////
0124     template <typename Subject, typename NumColumns, typename ColumnsDelimiter>
0125     struct columns_generator 
0126       : unary_generator<columns_generator<Subject, NumColumns, ColumnsDelimiter> >
0127     {
0128         typedef Subject subject_type;
0129         typedef ColumnsDelimiter delimiter_type;
0130 
0131         typedef mpl::int_<
0132             subject_type::properties::value | delimiter_type::properties::value 
0133         > properties;
0134 
0135         template <typename Context, typename Iterator>
0136         struct attribute
0137           : traits::attribute_of<subject_type, Context, Iterator>
0138         {};
0139 
0140         columns_generator(Subject const& subject, NumColumns const& cols
0141               , ColumnsDelimiter const& cdelimiter)
0142           : subject(subject), numcolumns(cols), column_delimiter(cdelimiter) 
0143         {
0144             // having zero number of columns doesn't make any sense
0145             BOOST_ASSERT(numcolumns > 0);
0146         }
0147 
0148         template <typename OutputIterator, typename Context
0149           , typename Delimiter, typename Attribute>
0150         bool generate(OutputIterator& sink, Context& ctx
0151           , Delimiter const& delimiter, Attribute const& attr) const
0152         {
0153             //  The columns generator dispatches to the embedded generator 
0154             //  while supplying a new delimiter to use, wrapping the outer 
0155             //  delimiter.
0156             typedef detail::columns_delimiter<
0157                 Delimiter, ColumnsDelimiter
0158             > columns_delimiter_type;
0159 
0160             columns_delimiter_type d(delimiter, column_delimiter, numcolumns);
0161             return subject.generate(sink, ctx, d, attr) && d.delimit_out(sink);
0162         }
0163 
0164         template <typename Context>
0165         info what(Context& context) const
0166         {
0167             return info("columns", subject.what(context));
0168         }
0169 
0170         Subject subject;
0171         NumColumns numcolumns;
0172         ColumnsDelimiter column_delimiter;
0173     };
0174 
0175     ///////////////////////////////////////////////////////////////////////////
0176     // Generator generators: make_xxx function (objects)
0177     ///////////////////////////////////////////////////////////////////////////
0178 
0179     // creates columns[] directive
0180     template <typename Subject, typename Modifiers>
0181     struct make_directive<tag::columns, Subject, Modifiers>
0182     {
0183         typedef typename
0184             result_of::compile<karma::domain, eol_type, Modifiers>::type
0185         columns_delimiter_type;
0186         typedef columns_generator<
0187             Subject, detail::default_columns, columns_delimiter_type> 
0188         result_type;
0189 
0190         result_type operator()(unused_type, Subject const& subject
0191           , unused_type) const
0192         {
0193 #if defined(BOOST_SPIRIT_NO_PREDEFINED_TERMINALS)
0194             eol_type const eol = eol_type();
0195 #endif
0196             return result_type(subject, detail::default_columns()
0197               , compile<karma::domain>(eol));
0198         }
0199     };
0200 
0201     // creates columns(c)[] directive generator (c is the number of columns)
0202     template <typename T, typename Subject, typename Modifiers>
0203     struct make_directive<
0204         terminal_ex<tag::columns, fusion::vector1<T> >
0205       , Subject, Modifiers
0206       , typename enable_if_c<integer_traits<T>::is_integral>::type>
0207     {
0208         typedef typename
0209             result_of::compile<karma::domain, eol_type, Modifiers>::type
0210         columns_delimiter_type;
0211         typedef columns_generator<
0212             Subject, T, columns_delimiter_type
0213         > result_type;
0214 
0215         template <typename Terminal>
0216         result_type operator()(Terminal const& term, Subject const& subject
0217           , unused_type) const
0218         {
0219 #if defined(BOOST_SPIRIT_NO_PREDEFINED_TERMINALS)
0220             eol_type const eol = eol_type();
0221 #endif
0222             return result_type(subject, fusion::at_c<0>(term.args)
0223               , compile<karma::domain>(eol));
0224         }
0225     };
0226 
0227     // creates columns(d)[] directive generator (d is the column delimiter)
0228     template <typename T, typename Subject, typename Modifiers>
0229     struct make_directive<
0230         terminal_ex<tag::columns, fusion::vector1<T> >
0231       , Subject, Modifiers
0232       , typename enable_if<
0233             mpl::and_<
0234                 spirit::traits::matches<karma::domain, T>,
0235                 mpl::not_<mpl::bool_<integer_traits<T>::is_integral> >
0236             >
0237         >::type>
0238     {
0239         typedef typename
0240             result_of::compile<karma::domain, T, Modifiers>::type
0241         columns_delimiter_type;
0242         typedef columns_generator<
0243             Subject, detail::default_columns, columns_delimiter_type
0244         > result_type;
0245 
0246         template <typename Terminal>
0247         result_type operator()(Terminal const& term, Subject const& subject
0248           , unused_type) const
0249         {
0250             return result_type(subject, detail::default_columns()
0251               , compile<karma::domain>(fusion::at_c<0>(term.args)));
0252         }
0253     };
0254 
0255     // creates columns(c, d)[] directive generator (c is the number of columns
0256     // and d is the column delimiter)
0257     template <typename T1, typename T2, typename Subject, typename Modifiers>
0258     struct make_directive<
0259         terminal_ex<tag::columns, fusion::vector2<T1, T2> >
0260       , Subject, Modifiers>
0261     {
0262         typedef typename
0263             result_of::compile<karma::domain, T2, Modifiers>::type
0264         columns_delimiter_type;
0265         typedef columns_generator<
0266             Subject, T1, columns_delimiter_type
0267         > result_type;
0268 
0269         template <typename Terminal>
0270         result_type operator()(Terminal const& term, Subject const& subject
0271           , unused_type) const
0272         {
0273             return result_type (subject, fusion::at_c<0>(term.args)
0274               , compile<karma::domain>(fusion::at_c<1>(term.args)));
0275         }
0276     };
0277 
0278 }}}
0279 
0280 namespace boost { namespace spirit { namespace traits
0281 {
0282     ///////////////////////////////////////////////////////////////////////////
0283     template <typename Subject, typename T1, typename T2>
0284     struct has_semantic_action<karma::columns_generator<Subject, T1, T2> >
0285       : unary_has_semantic_action<Subject> {};
0286 
0287     ///////////////////////////////////////////////////////////////////////////
0288     template <typename Subject, typename T1, typename T2, typename Attribute
0289       , typename Context, typename Iterator>
0290     struct handles_container<
0291             karma::columns_generator<Subject, T1, T2>, Attribute
0292           , Context, Iterator>
0293       : unary_handles_container<Subject, Attribute, Context, Iterator> {};
0294 }}}
0295 
0296 #endif