/Src/Dependencies/Boost/boost/spirit/home/karma/directive/columns.hpp

http://hadesmem.googlecode.com/ · C++ Header · 292 lines · 220 code · 37 blank · 35 comment · 5 complexity · d4235a9beb665057ca5106a48eb4c24b MD5 · raw file

  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_COLUMNS_DEC_03_2009_0736AM)
  6. #define BOOST_SPIRIT_KARMA_COLUMNS_DEC_03_2009_0736AM
  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/delimit_out.hpp>
  14. #include <boost/spirit/home/karma/detail/default_width.hpp>
  15. #include <boost/spirit/home/karma/auxiliary/eol.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/fusion/include/at.hpp>
  24. #include <boost/fusion/include/vector.hpp>
  25. namespace boost { namespace spirit
  26. {
  27. ///////////////////////////////////////////////////////////////////////////
  28. // Enablers
  29. ///////////////////////////////////////////////////////////////////////////
  30. template <>
  31. struct use_directive<karma::domain, tag::columns> // enables columns[]
  32. : mpl::true_ {};
  33. // enables columns(c)[g], where c provides the number of require columns
  34. template <typename T>
  35. struct use_directive<karma::domain
  36. , terminal_ex<tag::columns, fusion::vector1<T> > >
  37. : mpl::true_ {};
  38. // enables *lazy* columns(c)[g]
  39. template <>
  40. struct use_lazy_directive<karma::domain, tag::columns, 1>
  41. : mpl::true_ {};
  42. // enables columns(c, d)[g], where c provides the number of require columns
  43. // and d is the custom column-delimiter (default is karma::endl)
  44. template <typename T1, typename T2>
  45. struct use_directive<karma::domain
  46. , terminal_ex<tag::columns, fusion::vector2<T1, T2> > >
  47. : boost::spirit::traits::matches<karma::domain, T2> {};
  48. // enables *lazy* columns(c, d)[g]
  49. template <>
  50. struct use_lazy_directive<karma::domain, tag::columns, 2>
  51. : mpl::true_ {};
  52. }}
  53. namespace boost { namespace spirit { namespace karma
  54. {
  55. #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
  56. using spirit::columns;
  57. #endif
  58. using spirit::columns_type;
  59. namespace detail
  60. {
  61. template <typename Delimiter, typename ColumnDelimiter>
  62. struct columns_delimiter
  63. {
  64. columns_delimiter(Delimiter const& delim
  65. , ColumnDelimiter const& cdelim, unsigned int const numcols)
  66. : delimiter(delim), column_delimiter(cdelim)
  67. , numcolumns(numcols), count(0) {}
  68. template <typename OutputIterator, typename Context
  69. , typename Delimiter_, typename Attribute>
  70. bool generate(OutputIterator& sink, Context&, Delimiter_ const&
  71. , Attribute const&) const
  72. {
  73. // first invoke the embedded delimiter
  74. if (!karma::delimit_out(sink, delimiter))
  75. return false;
  76. // now we count the number of invocations and emit the column
  77. // delimiter if needed
  78. if ((++count % numcolumns) == 0)
  79. return karma::delimit_out(sink, column_delimiter);
  80. return true;
  81. }
  82. // generate a final column delimiter if the last invocation didn't
  83. // emit one
  84. template <typename OutputIterator>
  85. bool delimit_out(OutputIterator& sink) const
  86. {
  87. if (count % numcolumns)
  88. return karma::delimit_out(sink, column_delimiter);
  89. return true;
  90. }
  91. Delimiter const& delimiter;
  92. ColumnDelimiter const& column_delimiter;
  93. unsigned int const numcolumns;
  94. mutable unsigned int count;
  95. private:
  96. // silence MSVC warning C4512: assignment operator could not be generated
  97. columns_delimiter& operator= (columns_delimiter const&);
  98. };
  99. }
  100. ///////////////////////////////////////////////////////////////////////////
  101. // The columns_generator is used for columns(c, d)[...] directives.
  102. ///////////////////////////////////////////////////////////////////////////
  103. template <typename Subject, typename NumColumns, typename ColumnsDelimiter>
  104. struct columns_generator
  105. : unary_generator<columns_generator<Subject, NumColumns, ColumnsDelimiter> >
  106. {
  107. typedef Subject subject_type;
  108. typedef ColumnsDelimiter delimiter_type;
  109. typedef mpl::int_<
  110. subject_type::properties::value | delimiter_type::properties::value
  111. > properties;
  112. template <typename Context, typename Iterator>
  113. struct attribute
  114. : traits::attribute_of<subject_type, Context, Iterator>
  115. {};
  116. columns_generator(Subject const& subject, NumColumns const& cols
  117. , ColumnsDelimiter const& cdelimiter)
  118. : subject(subject), numcolumns(cols), column_delimiter(cdelimiter)
  119. {
  120. // having zero number of columns doesn't make any sense
  121. BOOST_ASSERT(numcolumns > 0);
  122. }
  123. template <typename OutputIterator, typename Context
  124. , typename Delimiter, typename Attribute>
  125. bool generate(OutputIterator& sink, Context& ctx
  126. , Delimiter const& delimiter, Attribute const& attr) const
  127. {
  128. // The columns generator dispatches to the embedded generator
  129. // while supplying a new delimiter to use, wrapping the outer
  130. // delimiter.
  131. typedef detail::columns_delimiter<
  132. Delimiter, ColumnsDelimiter
  133. > columns_delimiter_type;
  134. columns_delimiter_type d(delimiter, column_delimiter, numcolumns);
  135. return subject.generate(sink, ctx, d, attr) && d.delimit_out(sink);
  136. }
  137. template <typename Context>
  138. info what(Context& context) const
  139. {
  140. return info("columns", subject.what(context));
  141. }
  142. Subject subject;
  143. NumColumns numcolumns;
  144. ColumnsDelimiter column_delimiter;
  145. };
  146. ///////////////////////////////////////////////////////////////////////////
  147. // Generator generators: make_xxx function (objects)
  148. ///////////////////////////////////////////////////////////////////////////
  149. // creates columns[] directive
  150. template <typename Subject, typename Modifiers>
  151. struct make_directive<tag::columns, Subject, Modifiers>
  152. {
  153. typedef typename
  154. result_of::compile<karma::domain, eol_type, Modifiers>::type
  155. columns_delimiter_type;
  156. typedef columns_generator<
  157. Subject, detail::default_columns, columns_delimiter_type>
  158. result_type;
  159. result_type operator()(unused_type, Subject const& subject
  160. , unused_type) const
  161. {
  162. #if defined(BOOST_SPIRIT_NO_PREDEFINED_TERMINALS)
  163. eol_type const eol = eol_type();
  164. #endif
  165. return result_type(subject, detail::default_columns()
  166. , compile<karma::domain>(eol));
  167. }
  168. };
  169. // creates columns(c)[] directive generator (c is the number of columns)
  170. template <typename T, typename Subject, typename Modifiers>
  171. struct make_directive<
  172. terminal_ex<tag::columns, fusion::vector1<T> >
  173. , Subject, Modifiers
  174. , typename enable_if_c<integer_traits<T>::is_integral>::type>
  175. {
  176. typedef typename
  177. result_of::compile<karma::domain, eol_type, Modifiers>::type
  178. columns_delimiter_type;
  179. typedef columns_generator<
  180. Subject, T, columns_delimiter_type
  181. > result_type;
  182. template <typename Terminal>
  183. result_type operator()(Terminal const& term, Subject const& subject
  184. , unused_type) const
  185. {
  186. #if defined(BOOST_SPIRIT_NO_PREDEFINED_TERMINALS)
  187. eol_type const eol = eol_type();
  188. #endif
  189. return result_type(subject, fusion::at_c<0>(term.args)
  190. , compile<karma::domain>(eol));
  191. }
  192. };
  193. // creates columns(d)[] directive generator (d is the column delimiter)
  194. template <typename T, typename Subject, typename Modifiers>
  195. struct make_directive<
  196. terminal_ex<tag::columns, fusion::vector1<T> >
  197. , Subject, Modifiers
  198. , typename enable_if<
  199. mpl::and_<
  200. spirit::traits::matches<karma::domain, T>,
  201. mpl::not_<mpl::bool_<integer_traits<T>::is_integral> >
  202. >
  203. >::type>
  204. {
  205. typedef typename
  206. result_of::compile<karma::domain, T, Modifiers>::type
  207. columns_delimiter_type;
  208. typedef columns_generator<
  209. Subject, detail::default_columns, columns_delimiter_type
  210. > result_type;
  211. template <typename Terminal>
  212. result_type operator()(Terminal const& term, Subject const& subject
  213. , unused_type) const
  214. {
  215. return result_type(subject, detail::default_columns()
  216. , compile<karma::domain>(fusion::at_c<0>(term.args)));
  217. }
  218. };
  219. // creates columns(c, d)[] directive generator (c is the number of columns
  220. // and d is the column delimiter)
  221. template <typename T1, typename T2, typename Subject, typename Modifiers>
  222. struct make_directive<
  223. terminal_ex<tag::columns, fusion::vector2<T1, T2> >
  224. , Subject, Modifiers>
  225. {
  226. typedef typename
  227. result_of::compile<karma::domain, T2, Modifiers>::type
  228. columns_delimiter_type;
  229. typedef columns_generator<
  230. Subject, T1, columns_delimiter_type
  231. > result_type;
  232. template <typename Terminal>
  233. result_type operator()(Terminal const& term, Subject const& subject
  234. , unused_type) const
  235. {
  236. return result_type (subject, fusion::at_c<0>(term.args)
  237. , compile<karma::domain>(fusion::at_c<1>(term.args)));
  238. }
  239. };
  240. }}}
  241. namespace boost { namespace spirit { namespace traits
  242. {
  243. ///////////////////////////////////////////////////////////////////////////
  244. template <typename Subject, typename T1, typename T2>
  245. struct has_semantic_action<karma::columns_generator<Subject, T1, T2> >
  246. : unary_has_semantic_action<Subject> {};
  247. ///////////////////////////////////////////////////////////////////////////
  248. template <typename Subject, typename T1, typename T2, typename Attribute
  249. , typename Context, typename Iterator>
  250. struct handles_container<
  251. karma::columns_generator<Subject, T1, T2>, Attribute
  252. , Context, Iterator>
  253. : unary_handles_container<Subject, Attribute, Context, Iterator> {};
  254. }}}
  255. #endif