plus.hpp 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. // Copyright (c) 2001-2011 Joel de Guzman
  2. // Copyright (c) 2001-2011 Hartmut Kaiser
  3. //
  4. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. #if !defined(BOOST_SPIRIT_KARMA_POSITIVE_MAR_03_2007_0945PM)
  7. #define BOOST_SPIRIT_KARMA_POSITIVE_MAR_03_2007_0945PM
  8. #if defined(_MSC_VER)
  9. #pragma once
  10. #endif
  11. #include <boost/spirit/home/karma/domain.hpp>
  12. #include <boost/spirit/home/karma/generator.hpp>
  13. #include <boost/spirit/home/karma/meta_compiler.hpp>
  14. #include <boost/spirit/home/karma/detail/indirect_iterator.hpp>
  15. #include <boost/spirit/home/karma/detail/output_iterator.hpp>
  16. #include <boost/spirit/home/karma/detail/get_stricttag.hpp>
  17. #include <boost/spirit/home/karma/detail/pass_container.hpp>
  18. #include <boost/spirit/home/karma/detail/fail_function.hpp>
  19. #include <boost/spirit/home/support/info.hpp>
  20. #include <boost/spirit/home/support/unused.hpp>
  21. #include <boost/spirit/home/support/container.hpp>
  22. #include <boost/spirit/home/support/has_semantic_action.hpp>
  23. #include <boost/spirit/home/support/handles_container.hpp>
  24. #include <boost/spirit/home/karma/detail/attributes.hpp>
  25. #include <boost/type_traits/add_const.hpp>
  26. namespace boost { namespace spirit
  27. {
  28. ///////////////////////////////////////////////////////////////////////////
  29. // Enablers
  30. ///////////////////////////////////////////////////////////////////////////
  31. template <>
  32. struct use_operator<karma::domain, proto::tag::unary_plus> // enables +g
  33. : mpl::true_ {};
  34. }}
  35. ///////////////////////////////////////////////////////////////////////////////
  36. namespace boost { namespace spirit { namespace karma
  37. {
  38. template <typename Subject, typename Strict, typename Derived>
  39. struct base_plus : unary_generator<Derived>
  40. {
  41. private:
  42. // Ignore return value in relaxed mode (failing subject generators
  43. // are just skipped). This allows to selectively generate items in
  44. // the provided attribute.
  45. template <typename F, typename Attribute>
  46. bool generate_subject(F f, Attribute const&, bool& result, mpl::false_) const
  47. {
  48. bool r = !f(subject);
  49. if (r)
  50. result = true;
  51. else if (!f.is_at_end())
  52. f.next();
  53. return true;
  54. }
  55. template <typename F, typename Attribute>
  56. bool generate_subject(F f, Attribute const&, bool& result, mpl::true_) const
  57. {
  58. bool r = !f(subject);
  59. if (r)
  60. result = true;
  61. return r;
  62. }
  63. // There is no way to distinguish a failed generator from a
  64. // generator to be skipped. We assume the user takes responsibility
  65. // for ending the loop if no attribute is specified.
  66. template <typename F>
  67. bool generate_subject(F f, unused_type, bool& result, mpl::false_) const
  68. {
  69. bool r = f(subject);
  70. if (!r)
  71. result = true;
  72. return !r;
  73. }
  74. // template <typename F>
  75. // bool generate_subject(F f, unused_type, bool& result, mpl::true_) const
  76. // {
  77. // bool r = f(subject);
  78. // if (!r)
  79. // result = true;
  80. // return !r;
  81. // }
  82. public:
  83. typedef Subject subject_type;
  84. typedef typename subject_type::properties properties;
  85. // Build a std::vector from the subjects attribute. Note
  86. // that build_std_vector may return unused_type if the
  87. // subject's attribute is an unused_type.
  88. template <typename Context, typename Iterator>
  89. struct attribute
  90. : traits::build_std_vector<
  91. typename traits::attribute_of<subject_type, Context, Iterator>::type
  92. >
  93. {};
  94. base_plus(Subject const& subject)
  95. : subject(subject) {}
  96. template <
  97. typename OutputIterator, typename Context, typename Delimiter
  98. , typename Attribute>
  99. bool generate(OutputIterator& sink, Context& ctx
  100. , Delimiter const& d, Attribute const& attr) const
  101. {
  102. typedef detail::fail_function<
  103. OutputIterator, Context, Delimiter> fail_function;
  104. typedef typename traits::container_iterator<
  105. typename add_const<Attribute>::type
  106. >::type iterator_type;
  107. typedef
  108. typename traits::make_indirect_iterator<iterator_type>::type
  109. indirect_iterator_type;
  110. typedef detail::pass_container<
  111. fail_function, Attribute, indirect_iterator_type, mpl::false_>
  112. pass_container;
  113. iterator_type it = traits::begin(attr);
  114. iterator_type end = traits::end(attr);
  115. // plus fails if the parameter is empty
  116. if (traits::compare(it, end))
  117. return false;
  118. pass_container pass(fail_function(sink, ctx, d),
  119. indirect_iterator_type(it), indirect_iterator_type(end));
  120. // from now on plus fails if the underlying output fails or overall
  121. // no subject generators succeeded
  122. bool result = false;
  123. while (!pass.is_at_end())
  124. {
  125. if (!generate_subject(pass, attr, result, Strict()))
  126. break;
  127. }
  128. return result && detail::sink_is_good(sink);
  129. }
  130. template <typename Context>
  131. info what(Context& context) const
  132. {
  133. return info("plus", subject.what(context));
  134. }
  135. Subject subject;
  136. };
  137. template <typename Subject>
  138. struct plus
  139. : base_plus<Subject, mpl::false_, plus<Subject> >
  140. {
  141. typedef base_plus<Subject, mpl::false_, plus> base_plus_;
  142. plus(Subject const& subject)
  143. : base_plus_(subject) {}
  144. };
  145. template <typename Subject>
  146. struct strict_plus
  147. : base_plus<Subject, mpl::true_, strict_plus<Subject> >
  148. {
  149. typedef base_plus<Subject, mpl::true_, strict_plus> base_plus_;
  150. strict_plus(Subject const& subject)
  151. : base_plus_(subject) {}
  152. };
  153. ///////////////////////////////////////////////////////////////////////////
  154. // Generator generators: make_xxx function (objects)
  155. ///////////////////////////////////////////////////////////////////////////
  156. namespace detail
  157. {
  158. template <typename Elements, bool strict_mode = false>
  159. struct make_plus
  160. : make_unary_composite<Elements, plus>
  161. {};
  162. template <typename Elements>
  163. struct make_plus<Elements, true>
  164. : make_unary_composite<Elements, strict_plus>
  165. {};
  166. }
  167. template <typename Elements, typename Modifiers>
  168. struct make_composite<proto::tag::unary_plus, Elements, Modifiers>
  169. : detail::make_plus<Elements, detail::get_stricttag<Modifiers>::value>
  170. {};
  171. }}}
  172. namespace boost { namespace spirit { namespace traits
  173. {
  174. ///////////////////////////////////////////////////////////////////////////
  175. template <typename Subject>
  176. struct has_semantic_action<karma::plus<Subject> >
  177. : unary_has_semantic_action<Subject> {};
  178. template <typename Subject>
  179. struct has_semantic_action<karma::strict_plus<Subject> >
  180. : unary_has_semantic_action<Subject> {};
  181. ///////////////////////////////////////////////////////////////////////////
  182. template <typename Subject, typename Attribute, typename Context
  183. , typename Iterator>
  184. struct handles_container<karma::plus<Subject>, Attribute
  185. , Context, Iterator>
  186. : mpl::true_ {};
  187. template <typename Subject, typename Attribute, typename Context
  188. , typename Iterator>
  189. struct handles_container<karma::strict_plus<Subject>, Attribute
  190. , Context, Iterator>
  191. : mpl::true_ {};
  192. }}}
  193. #endif