simple_columns_directive.hpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. // Copyright (c) 2001-2010 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(COLUMNS_DEC_05_2009_0716PM)
  6. #define COLUMNS_DEC_05_2009_0716PM
  7. #include <boost/spirit/include/karma_generate.hpp>
  8. ///////////////////////////////////////////////////////////////////////////////
  9. // definition the place holder
  10. namespace custom_generator
  11. {
  12. BOOST_SPIRIT_TERMINAL(columns)
  13. }
  14. ///////////////////////////////////////////////////////////////////////////////
  15. // implementation the enabler
  16. namespace boost { namespace spirit
  17. {
  18. // We want custom_generator::columns to be usable as a directive only,
  19. // and only for generator expressions (karma::domain).
  20. template <>
  21. struct use_directive<karma::domain, custom_generator::tag::columns>
  22. : mpl::true_ {};
  23. }}
  24. ///////////////////////////////////////////////////////////////////////////////
  25. // implementation of the generator
  26. namespace custom_generator
  27. {
  28. // special delimiter wrapping the original one while additionally emitting
  29. // the column delimiter after each 5th invocation
  30. template <typename Delimiter>
  31. struct columns_delimiter
  32. {
  33. columns_delimiter(Delimiter const& delim)
  34. : delimiter(delim), count(0) {}
  35. // This function is called during the actual delimiter output
  36. template <typename OutputIterator, typename Context
  37. , typename Delimiter_, typename Attribute>
  38. bool generate(OutputIterator& sink, Context&, Delimiter_ const&
  39. , Attribute const&) const
  40. {
  41. // first invoke the wrapped delimiter
  42. if (!karma::delimit_out(sink, delimiter))
  43. return false;
  44. // now we count the number of invocations and emit the column
  45. // delimiter after each 5th column
  46. if ((++count % 5) == 0)
  47. *sink++ = '\n';
  48. return true;
  49. }
  50. // Generate a final column delimiter if the last invocation didn't
  51. // emit one
  52. template <typename OutputIterator>
  53. bool final_delimit_out(OutputIterator& sink) const
  54. {
  55. if (count % 5)
  56. *sink++ = '\n';
  57. return true;
  58. }
  59. Delimiter const& delimiter; // wrapped delimiter
  60. mutable unsigned int count; // invocation counter
  61. };
  62. // That's the actual columns generator
  63. template <typename Subject>
  64. struct simple_columns_generator
  65. : boost::spirit::karma::unary_generator<
  66. simple_columns_generator<Subject> >
  67. {
  68. // Define required output iterator properties
  69. typedef typename Subject::properties properties;
  70. // Define the attribute type exposed by this parser component
  71. template <typename Context, typename Iterator>
  72. struct attribute
  73. : boost::spirit::traits::attribute_of<Subject, Context, Iterator>
  74. {};
  75. simple_columns_generator(Subject const& s)
  76. : subject(s)
  77. {}
  78. // This function is called during the actual output generation process.
  79. // It dispatches to the embedded generator while supplying a new
  80. // delimiter to use, wrapping the outer delimiter.
  81. template <typename OutputIterator, typename Context
  82. , typename Delimiter, typename Attribute>
  83. bool generate(OutputIterator& sink, Context& ctx
  84. , Delimiter const& delimiter, Attribute const& attr) const
  85. {
  86. columns_delimiter<Delimiter> d(delimiter);
  87. return subject.generate(sink, ctx, d, attr) && d.final_delimit_out(sink);
  88. }
  89. // This function is called during error handling to create
  90. // a human readable string for the error context.
  91. template <typename Context>
  92. boost::spirit::info what(Context& ctx) const
  93. {
  94. return boost::spirit::info("columns", subject.what(ctx));
  95. }
  96. Subject subject;
  97. };
  98. }
  99. ///////////////////////////////////////////////////////////////////////////////
  100. // instantiation of the generator
  101. namespace boost { namespace spirit { namespace karma
  102. {
  103. // This is the factory function object invoked in order to create
  104. // an instance of our simple_columns_generator.
  105. template <typename Subject, typename Modifiers>
  106. struct make_directive<custom_generator::tag::columns, Subject, Modifiers>
  107. {
  108. typedef custom_generator::simple_columns_generator<Subject> result_type;
  109. result_type operator()(unused_type, Subject const& s, unused_type) const
  110. {
  111. return result_type(s);
  112. }
  113. };
  114. }}}
  115. #endif