File indexing completed on 2025-01-19 09:47:36
0001
0002
0003
0004
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
0040
0041
0042
0043 template <>
0044 struct use_directive<karma::domain, tag::center>
0045 : mpl::true_ {};
0046
0047
0048
0049 template <typename T>
0050 struct use_directive<karma::domain
0051 , terminal_ex<tag::center, fusion::vector1<T> > >
0052 : mpl::true_ {};
0053
0054
0055 template <>
0056 struct use_lazy_directive<karma::domain, tag::center, 1>
0057 : mpl::true_ {};
0058
0059
0060
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
0067
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
0086
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;
0097 #endif
0098
0099 detail::enable_buffering<OutputIterator> buffering(sink, width);
0100 bool r = false;
0101
0102
0103 {
0104 detail::disable_counting<OutputIterator> nocounting(sink);
0105 r = e.generate(sink, ctx, d, attr);
0106 }
0107
0108 buffering.disable();
0109
0110
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
0119 buffering.buffer_copy();
0120
0121
0122 while (r && counting.count() < width)
0123 r = p.generate(sink, ctx, unused, unused);
0124 }
0125 return r;
0126 }
0127 }
0128
0129
0130
0131
0132
0133
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
0174
0175
0176
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
0222
0223
0224
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
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
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
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 }}}
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