9
3

buffer.hpp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  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(SPIRIT_KARMA_BUFFER_AUG_03_2009_0949AM)
  6. #define SPIRIT_KARMA_BUFFER_AUG_03_2009_0949AM
  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/support/unused.hpp>
  15. #include <boost/spirit/home/support/info.hpp>
  16. #include <boost/spirit/home/support/common_terminals.hpp>
  17. #include <boost/spirit/home/support/has_semantic_action.hpp>
  18. #include <boost/spirit/home/support/handles_container.hpp>
  19. #include <boost/spirit/home/karma/detail/attributes.hpp>
  20. namespace boost { namespace spirit
  21. {
  22. ///////////////////////////////////////////////////////////////////////////
  23. // Enablers
  24. ///////////////////////////////////////////////////////////////////////////
  25. template <>
  26. struct use_directive<karma::domain, tag::buffer> // enables buffer
  27. : mpl::true_ {};
  28. }}
  29. namespace boost { namespace spirit { namespace karma
  30. {
  31. #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
  32. using spirit::buffer;
  33. #endif
  34. using spirit::buffer_type;
  35. ///////////////////////////////////////////////////////////////////////////
  36. // buffer_directive buffers all generated output of the embedded generator
  37. // and flushes it only if the whole embedded generator succeeds
  38. ///////////////////////////////////////////////////////////////////////////
  39. template <typename Subject>
  40. struct buffer_directive : unary_generator<buffer_directive<Subject> >
  41. {
  42. typedef Subject subject_type;
  43. typedef mpl::int_<
  44. subject_type::properties::value |
  45. generator_properties::countingbuffer
  46. > properties;
  47. buffer_directive(Subject const& subject)
  48. : subject(subject) {}
  49. template <typename Context, typename Iterator>
  50. struct attribute
  51. : traits::attribute_of<subject_type, Context, Iterator>
  52. {};
  53. template <typename OutputIterator, typename Context, typename Delimiter
  54. , typename Attribute>
  55. bool generate(OutputIterator& sink, Context& ctx, Delimiter const& d
  56. , Attribute const& attr) const
  57. {
  58. // wrap the given output iterator to avoid output as long as the
  59. // embedded generator (subject) fails
  60. detail::enable_buffering<OutputIterator> buffering(sink);
  61. bool r = false;
  62. {
  63. detail::disable_counting<OutputIterator> nocounting(sink);
  64. r = subject.generate(sink, ctx, d, attr);
  65. }
  66. if (r)
  67. buffering.buffer_copy();
  68. return r;
  69. }
  70. template <typename Context>
  71. info what(Context& context) const
  72. {
  73. return info("buffer", subject.what(context));
  74. }
  75. Subject subject;
  76. };
  77. ///////////////////////////////////////////////////////////////////////////
  78. // Generator generators: make_xxx function (objects)
  79. ///////////////////////////////////////////////////////////////////////////
  80. template <typename Subject, typename Modifiers>
  81. struct make_directive<tag::buffer, Subject, Modifiers>
  82. {
  83. typedef buffer_directive<Subject> result_type;
  84. result_type operator()(unused_type, Subject const& subject
  85. , unused_type) const
  86. {
  87. return result_type(subject);
  88. }
  89. };
  90. // make sure buffer[buffer[...]] does not result in double buffering
  91. template <typename Subject, typename Modifiers>
  92. struct make_directive<tag::buffer, buffer_directive<Subject>, Modifiers>
  93. {
  94. typedef buffer_directive<Subject> result_type;
  95. result_type operator()(unused_type
  96. , buffer_directive<Subject> const& subject, unused_type) const
  97. {
  98. return subject;
  99. }
  100. };
  101. }}}
  102. namespace boost { namespace spirit { namespace traits
  103. {
  104. ///////////////////////////////////////////////////////////////////////////
  105. template <typename Subject>
  106. struct has_semantic_action<karma::buffer_directive<Subject> >
  107. : unary_has_semantic_action<Subject> {};
  108. ///////////////////////////////////////////////////////////////////////////
  109. template <typename Subject, typename Attribute, typename Context
  110. , typename Iterator>
  111. struct handles_container<karma::buffer_directive<Subject>, Attribute
  112. , Context, Iterator>
  113. : unary_handles_container<Subject, Attribute, Context, Iterator> {};
  114. }}}
  115. #endif