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_CENTER_ALIGNMENT_FEB_27_2007_1216PM)
0007 #define BOOST_SPIRIT_KARMA_CENTER_ALIGNMENT_FEB_27_2007_1216PM
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/detail/output_iterator.hpp>
0017 #include <boost/spirit/home/karma/detail/default_width.hpp>
0018 #include <boost/spirit/home/karma/delimit_out.hpp>
0019 #include <boost/spirit/home/karma/auxiliary/lazy.hpp>
0020 #include <boost/spirit/home/karma/char/char.hpp>
0021 #include <boost/spirit/home/support/unused.hpp>
0022 #include <boost/spirit/home/support/common_terminals.hpp>
0023 #include <boost/spirit/home/support/has_semantic_action.hpp>
0024 #include <boost/spirit/home/support/handles_container.hpp>
0025 #include <boost/spirit/home/karma/detail/attributes.hpp>
0026 #include <boost/spirit/home/support/info.hpp>
0027 #include <boost/spirit/home/support/unused.hpp>
0028 #include <boost/fusion/include/at.hpp>
0029 #include <boost/fusion/include/vector.hpp>
0030 #include <boost/integer_traits.hpp>
0031 #include <boost/mpl/bool.hpp>
0032 #include <boost/utility/enable_if.hpp>
0033 #include <boost/detail/workaround.hpp>
0034 
0035 ///////////////////////////////////////////////////////////////////////////////
0036 namespace boost { namespace spirit
0037 {
0038     ///////////////////////////////////////////////////////////////////////////
0039     // Enablers
0040     ///////////////////////////////////////////////////////////////////////////
0041 
0042     // enables center[]
0043     template <>
0044     struct use_directive<karma::domain, tag::center>
0045       : mpl::true_ {};
0046 
0047     // enables center(d)[g] and center(w)[g], where d is a generator
0048     // and w is a maximum width
0049     template <typename T>
0050     struct use_directive<karma::domain
0051           , terminal_ex<tag::center, fusion::vector1<T> > >
0052       : mpl::true_ {};
0053 
0054     // enables *lazy* center(d)[g], where d provides a generator
0055     template <>
0056     struct use_lazy_directive<karma::domain, tag::center, 1>
0057       : mpl::true_ {};
0058 
0059     // enables center(w, d)[g], where d is a generator and w is a maximum
0060     // width
0061     template <typename Width, typename Padding>
0062     struct use_directive<karma::domain
0063           , terminal_ex<tag::center, fusion::vector2<Width, Padding> > >
0064       : spirit::traits::matches<karma::domain, Padding> {};
0065 
0066     // enables *lazy* center(w, d)[g], where d provides a generator and w is
0067     // a maximum width
0068     template <>
0069     struct use_lazy_directive<karma::domain, tag::center, 2>
0070       : mpl::true_ {};
0071 
0072 }}
0073 
0074 ///////////////////////////////////////////////////////////////////////////////
0075 namespace boost { namespace spirit { namespace karma
0076 {
0077 #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
0078     using spirit::center;
0079 #endif
0080     using spirit::center_type;
0081 
0082     namespace detail
0083     {
0084         ///////////////////////////////////////////////////////////////////////
0085         //  The center_generate template function is used for all the
0086         //  different flavors of the center[] directive.
0087         ///////////////////////////////////////////////////////////////////////
0088         template <typename OutputIterator, typename Context, typename Delimiter,
0089             typename Attribute, typename Embedded, typename Padding>
0090         inline static bool
0091         center_generate(OutputIterator& sink, Context& ctx,
0092             Delimiter const& d, Attribute const& attr, Embedded const& e,
0093             unsigned int const width, Padding const& p)
0094         {
0095 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
0096             (void)e; // suppresses warning: C4100: 'e' : unreferenced formal parameter
0097 #endif
0098             // wrap the given output iterator to allow left padding
0099             detail::enable_buffering<OutputIterator> buffering(sink, width);
0100             bool r = false;
0101 
0102             // first generate the embedded output
0103             {
0104                 detail::disable_counting<OutputIterator> nocounting(sink);
0105                 r = e.generate(sink, ctx, d, attr);
0106             }   // re-enable counting
0107 
0108             buffering.disable();    // do not perform buffering any more
0109 
0110             // generate the left padding
0111             detail::enable_counting<OutputIterator> counting(sink);
0112 
0113             std::size_t const pre = width - (buffering.buffer_size() + width)/2;
0114             while (r && counting.count() < pre)
0115                 r = p.generate(sink, ctx, unused, unused);
0116 
0117             if (r) {
0118                 // copy the embedded output to the target output iterator
0119                 buffering.buffer_copy();
0120 
0121                 // generate the right padding
0122                 while (r && counting.count() < width)
0123                     r = p.generate(sink, ctx, unused, unused);
0124             }
0125             return r;
0126         }
0127     }
0128 
0129     ///////////////////////////////////////////////////////////////////////////
0130     //  The simple left alignment directive is used for center[...]
0131     //  generators. It uses default values for the generated width (defined via
0132     //  the BOOST_KARMA_DEFAULT_FIELD_LENGTH constant) and for the padding
0133     //  generator (always spaces).
0134     ///////////////////////////////////////////////////////////////////////////
0135     template <typename Subject, typename Width = detail::default_width>
0136     struct simple_center_alignment
0137       : unary_generator<simple_center_alignment<Subject, Width> >
0138     {
0139         typedef Subject subject_type;
0140 
0141         typedef mpl::int_<
0142             generator_properties::countingbuffer | subject_type::properties::value
0143         > properties;
0144 
0145         template <typename Context, typename Iterator>
0146         struct attribute
0147           : traits::attribute_of<subject_type, Context, Iterator>
0148         {};
0149 
0150         simple_center_alignment(Subject const& subject, Width width = Width())
0151           : subject(subject), width(width) {}
0152 
0153         template <typename OutputIterator, typename Context, typename Delimiter
0154           , typename Attribute>
0155         bool generate(OutputIterator& sink, Context& ctx, Delimiter const& d
0156           , Attribute const& attr) const
0157         {
0158             return detail::center_generate(sink, ctx, d, attr,
0159                 subject, width, compile<karma::domain>(' '));
0160         }
0161 
0162         template <typename Context>
0163         info what(Context& context) const
0164         {
0165             return info("center", subject.what(context));
0166         }
0167 
0168         Subject subject;
0169         Width width;
0170     };
0171 
0172     ///////////////////////////////////////////////////////////////////////////
0173     //  The left alignment directive with padding, is used for generators like
0174     //  center(padding)[...], where padding is a arbitrary generator
0175     //  expression. It uses a default value for the generated width (defined
0176     //  via the BOOST_KARMA_DEFAULT_FIELD_LENGTH constant).
0177     ///////////////////////////////////////////////////////////////////////////
0178     template <typename Subject, typename Padding
0179       , typename Width = detail::default_width>
0180     struct padding_center_alignment
0181       : unary_generator<padding_center_alignment<Subject, Padding, Width> >
0182     {
0183         typedef Subject subject_type;
0184         typedef Padding padding_type;
0185 
0186         typedef mpl::int_<
0187             generator_properties::countingbuffer |
0188             subject_type::properties::value | padding_type::properties::value
0189         > properties;
0190 
0191         template <typename Context, typename Iterator>
0192         struct attribute
0193           : traits::attribute_of<Subject, Context, Iterator>
0194         {};
0195 
0196         padding_center_alignment(Subject const& subject, Padding const& padding
0197               , Width width = Width())
0198           : subject(subject), padding(padding), width(width) {}
0199 
0200         template <typename OutputIterator, typename Context, typename Delimiter
0201           , typename Attribute>
0202         bool generate(OutputIterator& sink, Context& ctx, Delimiter const& d
0203           , Attribute const& attr) const
0204         {
0205             return detail::center_generate(sink, ctx, d, attr,
0206                 subject, width, padding);
0207         }
0208 
0209         template <typename Context>
0210         info what(Context& context) const
0211         {
0212             return info("center", subject.what(context));
0213         }
0214 
0215         Subject subject;
0216         Padding padding;
0217         Width width;
0218     };
0219 
0220     ///////////////////////////////////////////////////////////////////////////
0221     // Generator generators: make_xxx function (objects)
0222     ///////////////////////////////////////////////////////////////////////////
0223 
0224     // creates center[] directive generator
0225     template <typename Subject, typename Modifiers>
0226     struct make_directive<tag::center, Subject, Modifiers>
0227     {
0228         typedef simple_center_alignment<Subject> result_type;
0229         result_type operator()(unused_type, Subject const& subject
0230           , unused_type) const
0231         {
0232             return result_type(subject);
0233         }
0234     };
0235 
0236     // creates center(width)[] directive generator
0237     template <typename Width, typename Subject, typename Modifiers>
0238     struct make_directive<
0239         terminal_ex<tag::center, fusion::vector1<Width> >
0240       , Subject, Modifiers
0241       , typename enable_if_c< integer_traits<Width>::is_integral >::type>
0242     {
0243         typedef simple_center_alignment<Subject, Width> result_type;
0244 
0245         template <typename Terminal>
0246         result_type operator()(Terminal const& term, Subject const& subject
0247           , unused_type) const
0248         {
0249             return result_type(subject, fusion::at_c<0>(term.args));
0250         }
0251     };
0252 
0253     // creates center(pad)[] directive generator
0254     template <typename Padding, typename Subject, typename Modifiers>
0255     struct make_directive<
0256         terminal_ex<tag::center, fusion::vector1<Padding> >
0257       , Subject, Modifiers
0258       , typename enable_if<
0259             mpl::and_<
0260                 spirit::traits::matches<karma::domain, Padding>,
0261                 mpl::not_<mpl::bool_<integer_traits<Padding>::is_integral> >
0262             >
0263         >::type>
0264     {
0265         typedef typename
0266             result_of::compile<karma::domain, Padding, Modifiers>::type
0267         padding_type;
0268 
0269         typedef padding_center_alignment<Subject, padding_type> result_type;
0270 
0271         template <typename Terminal>
0272         result_type operator()(Terminal const& term, Subject const& subject
0273           , Modifiers const& modifiers) const
0274         {
0275             return result_type(subject
0276               , compile<karma::domain>(fusion::at_c<0>(term.args), modifiers));
0277         }
0278     };
0279 
0280     // creates center(width, pad)[] directive generator
0281     template <typename Width, typename Padding, typename Subject
0282       , typename Modifiers>
0283     struct make_directive<
0284         terminal_ex<tag::center, fusion::vector2<Width, Padding> >
0285       , Subject, Modifiers>
0286     {
0287         typedef typename
0288             result_of::compile<karma::domain, Padding, Modifiers>::type
0289         padding_type;
0290 
0291         typedef padding_center_alignment<Subject, padding_type, Width> result_type;
0292 
0293         template <typename Terminal>
0294         result_type operator()(Terminal const& term, Subject const& subject
0295           , Modifiers const& modifiers) const
0296         {
0297             return result_type(subject
0298               , compile<karma::domain>(fusion::at_c<1>(term.args), modifiers)
0299               , fusion::at_c<0>(term.args));
0300         }
0301     };
0302 
0303 }}} // namespace boost::spirit::karma
0304 
0305 namespace boost { namespace spirit { namespace traits
0306 {
0307     ///////////////////////////////////////////////////////////////////////////
0308     template <typename Subject, typename Width>
0309     struct has_semantic_action<karma::simple_center_alignment<Subject, Width> >
0310       : unary_has_semantic_action<Subject> {};
0311 
0312     template <typename Subject, typename Padding, typename Width>
0313     struct has_semantic_action<
0314             karma::padding_center_alignment<Subject, Padding, Width> >
0315       : unary_has_semantic_action<Subject> {};
0316 
0317     ///////////////////////////////////////////////////////////////////////////
0318     template <typename Subject, typename Width, typename Attribute
0319       , typename Context, typename Iterator>
0320     struct handles_container<
0321             karma::simple_center_alignment<Subject, Width>, Attribute
0322           , Context, Iterator>
0323       : unary_handles_container<Subject, Attribute, Context, Iterator> {};
0324 
0325     template <typename Subject, typename Padding, typename Width
0326       , typename Attribute, typename Context, typename Iterator>
0327     struct handles_container<
0328             karma::padding_center_alignment<Subject, Padding, Width>
0329           , Attribute, Context, Iterator>
0330       : unary_handles_container<Subject, Attribute, Context, Iterator> {};
0331 }}}
0332 
0333 #endif
0334 
0335