Chris@16: // Copyright (c) 2001-2011 Hartmut Kaiser Chris@16: // Chris@16: // Distributed under the Boost Software License, Version 1.0. (See accompanying Chris@16: // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) Chris@16: Chris@16: #if !defined(BOOST_SPIRIT_KARMA_CENTER_ALIGNMENT_FEB_27_2007_1216PM) Chris@16: #define BOOST_SPIRIT_KARMA_CENTER_ALIGNMENT_FEB_27_2007_1216PM Chris@16: Chris@16: #if defined(_MSC_VER) Chris@16: #pragma once Chris@16: #endif Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: namespace boost { namespace spirit Chris@16: { Chris@16: /////////////////////////////////////////////////////////////////////////// Chris@16: // Enablers Chris@16: /////////////////////////////////////////////////////////////////////////// Chris@16: Chris@16: // enables center[] Chris@16: template <> Chris@16: struct use_directive Chris@16: : mpl::true_ {}; Chris@16: Chris@16: // enables center(d)[g] and center(w)[g], where d is a generator Chris@16: // and w is a maximum width Chris@16: template Chris@16: struct use_directive > > Chris@16: : mpl::true_ {}; Chris@16: Chris@16: // enables *lazy* center(d)[g], where d provides a generator Chris@16: template <> Chris@16: struct use_lazy_directive Chris@16: : mpl::true_ {}; Chris@16: Chris@16: // enables center(w, d)[g], where d is a generator and w is a maximum Chris@16: // width Chris@16: template Chris@16: struct use_directive > > Chris@16: : spirit::traits::matches {}; Chris@16: Chris@16: // enables *lazy* center(w, d)[g], where d provides a generator and w is Chris@16: // a maximum width Chris@16: template <> Chris@16: struct use_lazy_directive Chris@16: : mpl::true_ {}; Chris@16: Chris@16: }} Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: namespace boost { namespace spirit { namespace karma Chris@16: { Chris@16: #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS Chris@16: using spirit::center; Chris@16: #endif Chris@16: using spirit::center_type; Chris@16: Chris@16: namespace detail Chris@16: { Chris@16: /////////////////////////////////////////////////////////////////////// Chris@16: // The center_generate template function is used for all the Chris@16: // different flavors of the center[] directive. Chris@16: /////////////////////////////////////////////////////////////////////// Chris@16: template Chris@16: inline static bool Chris@16: center_generate(OutputIterator& sink, Context& ctx, Chris@16: Delimiter const& d, Attribute const& attr, Embedded const& e, Chris@16: unsigned int const width, Padding const& p) Chris@16: { Chris@16: #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600)) Chris@16: e; // suppresses warning: C4100: 'e' : unreferenced formal parameter Chris@16: #endif Chris@16: // wrap the given output iterator to allow left padding Chris@16: detail::enable_buffering buffering(sink, width); Chris@16: bool r = false; Chris@16: Chris@16: // first generate the embedded output Chris@16: { Chris@16: detail::disable_counting nocounting(sink); Chris@16: r = e.generate(sink, ctx, d, attr); Chris@16: } // re-enable counting Chris@16: Chris@16: buffering.disable(); // do not perform buffering any more Chris@16: Chris@16: // generate the left padding Chris@16: detail::enable_counting counting(sink); Chris@16: Chris@16: std::size_t const pre = width - (buffering.buffer_size() + width)/2; Chris@16: while (r && counting.count() < pre) Chris@16: r = p.generate(sink, ctx, unused, unused); Chris@16: Chris@16: if (r) { Chris@16: // copy the embedded output to the target output iterator Chris@16: buffering.buffer_copy(); Chris@16: Chris@16: // generate the right padding Chris@16: while (r && counting.count() < width) Chris@16: r = p.generate(sink, ctx, unused, unused); Chris@16: } Chris@16: return r; Chris@16: } Chris@16: } Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////// Chris@16: // The simple left alignment directive is used for center[...] Chris@16: // generators. It uses default values for the generated width (defined via Chris@16: // the BOOST_KARMA_DEFAULT_FIELD_LENGTH constant) and for the padding Chris@16: // generator (always spaces). Chris@16: /////////////////////////////////////////////////////////////////////////// Chris@16: template Chris@16: struct simple_center_alignment Chris@16: : unary_generator > Chris@16: { Chris@16: typedef Subject subject_type; Chris@16: Chris@16: typedef mpl::int_< Chris@16: generator_properties::countingbuffer | subject_type::properties::value Chris@16: > properties; Chris@16: Chris@16: template Chris@16: struct attribute Chris@16: : traits::attribute_of Chris@16: {}; Chris@16: Chris@16: simple_center_alignment(Subject const& subject, Width width = Width()) Chris@16: : subject(subject), width(width) {} Chris@16: Chris@16: template Chris@16: bool generate(OutputIterator& sink, Context& ctx, Delimiter const& d Chris@16: , Attribute const& attr) const Chris@16: { Chris@16: return detail::center_generate(sink, ctx, d, attr, Chris@16: subject, width, compile(' ')); Chris@16: } Chris@16: Chris@16: template Chris@16: info what(Context& context) const Chris@16: { Chris@16: return info("center", subject.what(context)); Chris@16: } Chris@16: Chris@16: Subject subject; Chris@16: Width width; Chris@16: }; Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////// Chris@16: // The left alignment directive with padding, is used for generators like Chris@16: // center(padding)[...], where padding is a arbitrary generator Chris@16: // expression. It uses a default value for the generated width (defined Chris@16: // via the BOOST_KARMA_DEFAULT_FIELD_LENGTH constant). Chris@16: /////////////////////////////////////////////////////////////////////////// Chris@16: template Chris@16: struct padding_center_alignment Chris@16: : unary_generator > Chris@16: { Chris@16: typedef Subject subject_type; Chris@16: typedef Padding padding_type; Chris@16: Chris@16: typedef mpl::int_< Chris@16: generator_properties::countingbuffer | Chris@16: subject_type::properties::value | padding_type::properties::value Chris@16: > properties; Chris@16: Chris@16: template Chris@16: struct attribute Chris@16: : traits::attribute_of Chris@16: {}; Chris@16: Chris@16: padding_center_alignment(Subject const& subject, Padding const& padding Chris@16: , Width width = Width()) Chris@16: : subject(subject), padding(padding), width(width) {} Chris@16: Chris@16: template Chris@16: bool generate(OutputIterator& sink, Context& ctx, Delimiter const& d Chris@16: , Attribute const& attr) const Chris@16: { Chris@16: return detail::center_generate(sink, ctx, d, attr, Chris@16: subject, width, padding); Chris@16: } Chris@16: Chris@16: template Chris@16: info what(Context& context) const Chris@16: { Chris@16: return info("center", subject.what(context)); Chris@16: } Chris@16: Chris@16: Subject subject; Chris@16: Padding padding; Chris@16: Width width; Chris@16: }; Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////// Chris@16: // Generator generators: make_xxx function (objects) Chris@16: /////////////////////////////////////////////////////////////////////////// Chris@16: Chris@16: // creates center[] directive generator Chris@16: template Chris@16: struct make_directive Chris@16: { Chris@16: typedef simple_center_alignment result_type; Chris@16: result_type operator()(unused_type, Subject const& subject Chris@16: , unused_type) const Chris@16: { Chris@16: return result_type(subject); Chris@16: } Chris@16: }; Chris@16: Chris@16: // creates center(width)[] directive generator Chris@16: template Chris@16: struct make_directive< Chris@16: terminal_ex > Chris@16: , Subject, Modifiers Chris@16: , typename enable_if_c< integer_traits::is_integral >::type> Chris@16: { Chris@16: typedef simple_center_alignment result_type; Chris@16: Chris@16: template Chris@16: result_type operator()(Terminal const& term, Subject const& subject Chris@16: , unused_type) const Chris@16: { Chris@16: return result_type(subject, fusion::at_c<0>(term.args)); Chris@16: } Chris@16: }; Chris@16: Chris@16: // creates center(pad)[] directive generator Chris@16: template Chris@16: struct make_directive< Chris@16: terminal_ex > Chris@16: , Subject, Modifiers Chris@16: , typename enable_if< Chris@16: mpl::and_< Chris@16: spirit::traits::matches, Chris@16: mpl::not_::is_integral> > Chris@16: > Chris@16: >::type> Chris@16: { Chris@16: typedef typename Chris@16: result_of::compile::type Chris@16: padding_type; Chris@16: Chris@16: typedef padding_center_alignment result_type; Chris@16: Chris@16: template Chris@16: result_type operator()(Terminal const& term, Subject const& subject Chris@16: , Modifiers const& modifiers) const Chris@16: { Chris@16: return result_type(subject Chris@16: , compile(fusion::at_c<0>(term.args), modifiers)); Chris@16: } Chris@16: }; Chris@16: Chris@16: // creates center(width, pad)[] directive generator Chris@16: template Chris@16: struct make_directive< Chris@16: terminal_ex > Chris@16: , Subject, Modifiers> Chris@16: { Chris@16: typedef typename Chris@16: result_of::compile::type Chris@16: padding_type; Chris@16: Chris@16: typedef padding_center_alignment result_type; Chris@16: Chris@16: template Chris@16: result_type operator()(Terminal const& term, Subject const& subject Chris@16: , Modifiers const& modifiers) const Chris@16: { Chris@16: return result_type(subject Chris@16: , compile(fusion::at_c<1>(term.args), modifiers) Chris@16: , fusion::at_c<0>(term.args)); Chris@16: } Chris@16: }; Chris@16: Chris@16: }}} // namespace boost::spirit::karma Chris@16: Chris@16: namespace boost { namespace spirit { namespace traits Chris@16: { Chris@16: /////////////////////////////////////////////////////////////////////////// Chris@16: template Chris@16: struct has_semantic_action > Chris@16: : unary_has_semantic_action {}; Chris@16: Chris@16: template Chris@16: struct has_semantic_action< Chris@16: karma::padding_center_alignment > Chris@16: : unary_has_semantic_action {}; Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////// Chris@16: template Chris@16: struct handles_container< Chris@16: karma::simple_center_alignment, Attribute Chris@16: , Context, Iterator> Chris@16: : unary_handles_container {}; Chris@16: Chris@16: template Chris@16: struct handles_container< Chris@16: karma::padding_center_alignment Chris@16: , Attribute, Context, Iterator> Chris@16: : unary_handles_container {}; Chris@16: }}} Chris@16: Chris@16: #endif Chris@16: Chris@16: