maxwidth.hpp 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. // Copyright (c) 2001-2011 Hartmut Kaiser
  2. //
  3. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  4. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. #if !defined(BOOST_SPIRIT_KARMA_MAXWIDTH_MAR_18_2009_0827AM)
  6. #define BOOST_SPIRIT_KARMA_MAXWIDTH_MAR_18_2009_0827AM
  7. #if defined(_MSC_VER)
  8. #pragma once
  9. #endif
  10. #include <boost/spirit/home/karma/meta_compiler.hpp>
  11. #include <boost/spirit/home/karma/generator.hpp>
  12. #include <boost/spirit/home/karma/domain.hpp>
  13. #include <boost/spirit/home/karma/detail/output_iterator.hpp>
  14. #include <boost/spirit/home/karma/detail/default_width.hpp>
  15. #include <boost/spirit/home/karma/delimit_out.hpp>
  16. #include <boost/spirit/home/karma/auxiliary/lazy.hpp>
  17. #include <boost/spirit/home/support/unused.hpp>
  18. #include <boost/spirit/home/support/common_terminals.hpp>
  19. #include <boost/spirit/home/support/has_semantic_action.hpp>
  20. #include <boost/spirit/home/support/handles_container.hpp>
  21. #include <boost/spirit/home/karma/detail/attributes.hpp>
  22. #include <boost/spirit/home/support/info.hpp>
  23. #include <boost/spirit/home/support/unused.hpp>
  24. #include <boost/fusion/include/at.hpp>
  25. #include <boost/fusion/include/vector.hpp>
  26. #include <boost/lexical_cast.hpp>
  27. #include <boost/detail/workaround.hpp>
  28. ///////////////////////////////////////////////////////////////////////////////
  29. namespace boost { namespace spirit
  30. {
  31. ///////////////////////////////////////////////////////////////////////////
  32. // Enablers
  33. ///////////////////////////////////////////////////////////////////////////
  34. // enables maxwidth[]
  35. template <>
  36. struct use_directive<karma::domain, tag::maxwidth>
  37. : mpl::true_ {};
  38. // enables maxwidth(w)[g], where w provides a maxwidth
  39. template <typename T>
  40. struct use_directive<karma::domain
  41. , terminal_ex<tag::maxwidth, fusion::vector1<T> > >
  42. : mpl::true_ {};
  43. // enables *lazy* maxwidth(w)[g], where w provides a maxwidth
  44. template <>
  45. struct use_lazy_directive<karma::domain, tag::maxwidth, 1>
  46. : mpl::true_ {};
  47. // enables maxwidth(w, r)[g], where w provides a maxwidth and r is an output
  48. // iterator used to receive the rest of the output not fitting into the
  49. // maxwidth limit
  50. template <typename T, typename RestIter>
  51. struct use_directive<karma::domain
  52. , terminal_ex<tag::maxwidth, fusion::vector2<T, RestIter> > >
  53. : mpl::true_ {};
  54. // enables *lazy* maxwidth(w, r)[g], where w provides a maxwidth and r is
  55. // an output iterator used to receive the rest of the output not fitting
  56. // into the maxwidth limit
  57. template <>
  58. struct use_lazy_directive<karma::domain, tag::maxwidth, 2>
  59. : mpl::true_ {};
  60. }}
  61. ///////////////////////////////////////////////////////////////////////////////
  62. namespace boost { namespace spirit { namespace karma
  63. {
  64. #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
  65. using spirit::maxwidth;
  66. #endif
  67. using spirit::maxwidth_type;
  68. namespace detail
  69. {
  70. ///////////////////////////////////////////////////////////////////////
  71. template <typename OutputIterator, typename RestIterator>
  72. bool buffer_copy_rest(detail::enable_buffering<OutputIterator>& buff
  73. , std::size_t start_at, RestIterator& dest)
  74. {
  75. return buff.buffer_copy_rest(dest, start_at);
  76. }
  77. template <typename OutputIterator>
  78. bool buffer_copy_rest(detail::enable_buffering<OutputIterator>&
  79. , std::size_t, unused_type)
  80. {
  81. return true;
  82. }
  83. ///////////////////////////////////////////////////////////////////////
  84. // The maxwidth_generate template function is used for all the
  85. // different flavors of the maxwidth[] directive.
  86. ///////////////////////////////////////////////////////////////////////
  87. template <typename OutputIterator, typename Context, typename Delimiter,
  88. typename Attribute, typename Embedded, typename Rest>
  89. inline static bool
  90. maxwidth_generate(OutputIterator& sink, Context& ctx,
  91. Delimiter const& d, Attribute const& attr, Embedded const& e,
  92. unsigned int const maxwidth, Rest& restdest)
  93. {
  94. #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
  95. e; // suppresses warning: C4100: 'e' : unreferenced formal parameter
  96. #endif
  97. // wrap the given output iterator to allow buffering, but disable
  98. // counting
  99. detail::enable_buffering<OutputIterator> buffering(sink);
  100. // generate the underlying output and copy the embedded
  101. // output to the target output iterator applying the given
  102. // maxwidth
  103. bool r = false;
  104. {
  105. detail::disable_counting<OutputIterator> nocounting(sink);
  106. r = e.generate(sink, ctx, d, attr);
  107. } // re-enable counting
  108. return r && buffering.buffer_copy(maxwidth) &&
  109. buffer_copy_rest(buffering, maxwidth, restdest);
  110. }
  111. }
  112. ///////////////////////////////////////////////////////////////////////////
  113. // The maxwidth directive is used for maxwidth[...]
  114. // generators. It uses default values for the generated width (defined via
  115. // the BOOST_KARMA_DEFAULT_FIELD_MAXWIDTH constant).
  116. //
  117. // The maxwidth with width directive, is used for generators
  118. // like maxwidth(width)[...].
  119. ///////////////////////////////////////////////////////////////////////////
  120. template <typename Subject, typename Width = detail::default_max_width
  121. , typename Rest = unused_type>
  122. struct maxwidth_width
  123. : unary_generator<maxwidth_width<Subject, Width, Rest> >
  124. {
  125. typedef Subject subject_type;
  126. typedef mpl::int_<
  127. generator_properties::countingbuffer | subject_type::properties::value
  128. > properties;
  129. template <typename Context, typename Iterator>
  130. struct attribute
  131. : traits::attribute_of<subject_type, Context, Iterator>
  132. {};
  133. maxwidth_width(Subject const& subject, Width const& w = Width()
  134. , Rest const& r = Rest())
  135. : subject(subject), width(w), rest(r) {}
  136. template <typename OutputIterator, typename Context, typename Delimiter
  137. , typename Attribute>
  138. bool generate(OutputIterator& sink, Context& ctx, Delimiter const& d
  139. , Attribute const& attr) const
  140. {
  141. return detail::maxwidth_generate(sink, ctx, d, attr, subject
  142. , width, rest);
  143. }
  144. template <typename Context>
  145. info what(Context& context) const
  146. {
  147. return info("maxwidth", subject.what(context));
  148. }
  149. Subject subject;
  150. Width width;
  151. Rest rest;
  152. };
  153. ///////////////////////////////////////////////////////////////////////////
  154. // Generator generators: make_xxx function (objects)
  155. ///////////////////////////////////////////////////////////////////////////
  156. // creates maxwidth[] directive generator
  157. template <typename Subject, typename Modifiers>
  158. struct make_directive<tag::maxwidth, Subject, Modifiers>
  159. {
  160. typedef maxwidth_width<Subject> result_type;
  161. result_type operator()(unused_type, Subject const& subject
  162. , unused_type) const
  163. {
  164. return result_type(subject);
  165. }
  166. };
  167. // creates maxwidth(width)[] directive generator
  168. template <typename T, typename Subject, typename Modifiers>
  169. struct make_directive<
  170. terminal_ex<tag::maxwidth, fusion::vector1<T> >
  171. , Subject, Modifiers>
  172. {
  173. typedef maxwidth_width<Subject, T> result_type;
  174. template <typename Terminal>
  175. result_type operator()(Terminal const& term, Subject const& subject
  176. , unused_type) const
  177. {
  178. return result_type(subject, fusion::at_c<0>(term.args), unused);
  179. }
  180. };
  181. // creates maxwidth(width, restiter)[] directive generator
  182. template <
  183. typename T, typename RestIter, typename Subject, typename Modifiers>
  184. struct make_directive<
  185. terminal_ex<tag::maxwidth, fusion::vector2<T, RestIter> >
  186. , Subject, Modifiers>
  187. {
  188. typedef maxwidth_width<Subject, T, RestIter> result_type;
  189. template <typename Terminal>
  190. result_type operator()(Terminal const& term, Subject const& subject
  191. , unused_type) const
  192. {
  193. return result_type(subject, fusion::at_c<0>(term.args)
  194. , fusion::at_c<1>(term.args));
  195. }
  196. };
  197. }}} // namespace boost::spirit::karma
  198. namespace boost { namespace spirit { namespace traits
  199. {
  200. ///////////////////////////////////////////////////////////////////////////
  201. template <typename Subject, typename Width, typename Rest>
  202. struct has_semantic_action<karma::maxwidth_width<Subject, Width, Rest> >
  203. : unary_has_semantic_action<Subject> {};
  204. ///////////////////////////////////////////////////////////////////////////
  205. template <typename Subject, typename Attribute, typename Context
  206. , typename Iterator>
  207. struct handles_container<karma::maxwidth_width<Subject>, Attribute
  208. , Context, Iterator>
  209. : unary_handles_container<Subject, Attribute, Context, Iterator> {};
  210. }}}
  211. #endif