/Src/Dependencies/Boost/boost/spirit/home/karma/detail/alternative_function.hpp

http://hadesmem.googlecode.com/ · C++ Header · 250 lines · 187 code · 28 blank · 35 comment · 6 complexity · f7fbddcdc28b3f32c26a06761b23c731 MD5 · raw file

  1. // Copyright (c) 2001-2011 Hartmut Kaiser
  2. // Copyright (c) 2001-2011 Joel de Guzman
  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(SPIRIT_KARMA_ALTERNATIVE_MAR_01_2007_1124AM)
  7. #define SPIRIT_KARMA_ALTERNATIVE_MAR_01_2007_1124AM
  8. #if defined(_MSC_VER)
  9. #pragma once
  10. #endif
  11. #include <boost/spirit/home/karma/domain.hpp>
  12. #include <boost/spirit/home/karma/directive/buffer.hpp>
  13. #include <boost/spirit/home/support/unused.hpp>
  14. #include <boost/spirit/home/support/utree/utree_traits_fwd.hpp>
  15. #include <boost/spirit/home/karma/detail/attributes.hpp>
  16. #include <boost/spirit/home/support/detail/hold_any.hpp>
  17. #include <boost/spirit/home/karma/detail/output_iterator.hpp>
  18. #include <boost/spirit/home/support/container.hpp>
  19. #include <boost/utility/enable_if.hpp>
  20. #include <boost/variant.hpp>
  21. #include <boost/detail/workaround.hpp>
  22. ///////////////////////////////////////////////////////////////////////////////
  23. namespace boost { namespace spirit { namespace karma { namespace detail
  24. {
  25. ///////////////////////////////////////////////////////////////////////////
  26. // execute a generator if the given Attribute type is compatible
  27. ///////////////////////////////////////////////////////////////////////////
  28. // this gets instantiated if the Attribute type is _not_ compatible with
  29. // the generator
  30. template <typename Component, typename Attribute, typename Expected
  31. , typename Enable = void>
  32. struct alternative_generate
  33. {
  34. template <typename OutputIterator, typename Context, typename Delimiter>
  35. static bool
  36. call(Component const&, OutputIterator&, Context&, Delimiter const&
  37. , Attribute const&, bool& failed)
  38. {
  39. failed = true;
  40. return false;
  41. }
  42. };
  43. template <typename Component>
  44. struct alternative_generate<Component, unused_type, unused_type>
  45. {
  46. template <typename OutputIterator, typename Context, typename Delimiter>
  47. static bool
  48. call(Component const& component, OutputIterator& sink, Context& ctx
  49. , Delimiter const& d, unused_type, bool&)
  50. {
  51. #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
  52. component; // suppresses warning: C4100: 'component' : unreferenced formal parameter
  53. #endif
  54. // return true if any of the generators succeed
  55. return component.generate(sink, ctx, d, unused);
  56. }
  57. };
  58. // this gets instantiated if there is no Attribute given for the
  59. // alternative generator
  60. template <typename Component, typename Expected>
  61. struct alternative_generate<Component, unused_type, Expected>
  62. : alternative_generate<Component, unused_type, unused_type> {};
  63. // this gets instantiated if the generator does not expect to receive an
  64. // Attribute (the generator is self contained).
  65. template <typename Component, typename Attribute>
  66. struct alternative_generate<Component, Attribute, unused_type>
  67. : alternative_generate<Component, unused_type, unused_type> {};
  68. // this gets instantiated if the Attribute type is compatible to the
  69. // generator
  70. template <typename Component, typename Attribute, typename Expected>
  71. struct alternative_generate<Component, Attribute, Expected
  72. , typename enable_if<
  73. traits::compute_compatible_component<Expected, Attribute, karma::domain> >::type>
  74. {
  75. template <typename OutputIterator, typename Context, typename Delimiter>
  76. static bool
  77. call(Component const& component, OutputIterator& sink
  78. , Context& ctx, Delimiter const& d, Attribute const& attr, bool&)
  79. {
  80. #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
  81. component; // suppresses warning: C4100: 'component' : unreferenced formal parameter
  82. #endif
  83. return call(component, sink, ctx, d, attr
  84. , spirit::traits::not_is_variant<Attribute, karma::domain>());
  85. }
  86. template <typename OutputIterator, typename Context, typename Delimiter>
  87. static bool
  88. call(Component const& component, OutputIterator& sink
  89. , Context& ctx, Delimiter const& d, Attribute const& attr, mpl::true_)
  90. {
  91. #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
  92. component; // suppresses warning: C4100: 'component' : unreferenced formal parameter
  93. #endif
  94. return component.generate(sink, ctx, d, attr);
  95. }
  96. template <typename OutputIterator, typename Context, typename Delimiter>
  97. static bool
  98. call(Component const& component, OutputIterator& sink
  99. , Context& ctx, Delimiter const& d, Attribute const& attr, mpl::false_)
  100. {
  101. #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
  102. component; // suppresses warning: C4100: 'component' : unreferenced formal parameter
  103. #endif
  104. typedef
  105. traits::compute_compatible_component<Expected, Attribute, domain>
  106. component_type;
  107. // if we got passed an empty optional, just fail generation
  108. if (!traits::has_optional_value(attr))
  109. return false;
  110. // make sure, the content of the passed variant matches our
  111. // expectations
  112. typename traits::optional_attribute<Attribute>::type attr_ =
  113. traits::optional_value(attr);
  114. if (!component_type::is_compatible(spirit::traits::which(attr_)))
  115. return false;
  116. // returns true if any of the generators succeed
  117. typedef typename component_type::compatible_type compatible_type;
  118. return component.generate(sink, ctx, d
  119. , boost::get<compatible_type>(attr_));
  120. }
  121. };
  122. ///////////////////////////////////////////////////////////////////////////
  123. // alternative_generate_function: a functor supplied to fusion::any which
  124. // will be executed for every generator in a given alternative generator
  125. // expression
  126. ///////////////////////////////////////////////////////////////////////////
  127. template <typename OutputIterator, typename Context, typename Delimiter,
  128. typename Attribute, typename Strict>
  129. struct alternative_generate_function
  130. {
  131. alternative_generate_function(OutputIterator& sink_, Context& ctx_
  132. , Delimiter const& d, Attribute const& attr_)
  133. : sink(sink_), ctx(ctx_), delim(d), attr(attr_) {}
  134. template <typename Component>
  135. bool operator()(Component const& component)
  136. {
  137. typedef
  138. typename traits::attribute_of<Component, Context>::type
  139. expected_type;
  140. typedef
  141. alternative_generate<Component, Attribute, expected_type>
  142. generate;
  143. // wrap the given output iterator avoid output as long as one
  144. // component fails
  145. detail::enable_buffering<OutputIterator> buffering(sink);
  146. bool r = false;
  147. bool failed = false; // will be ignored
  148. {
  149. detail::disable_counting<OutputIterator> nocounting(sink);
  150. r = generate::call(component, sink, ctx, delim, attr, failed);
  151. }
  152. if (r)
  153. buffering.buffer_copy();
  154. return r;
  155. }
  156. // avoid double buffering
  157. template <typename Component>
  158. bool operator()(buffer_directive<Component> const& component)
  159. {
  160. typedef typename
  161. traits::attribute_of<Component, Context>::type
  162. expected_type;
  163. typedef alternative_generate<
  164. buffer_directive<Component>, Attribute, expected_type>
  165. generate;
  166. bool failed = false; // will be ignored
  167. return generate::call(component, sink, ctx, delim, attr, failed);
  168. }
  169. OutputIterator& sink;
  170. Context& ctx;
  171. Delimiter const& delim;
  172. Attribute const& attr;
  173. private:
  174. // silence MSVC warning C4512: assignment operator could not be generated
  175. alternative_generate_function& operator= (alternative_generate_function const&);
  176. };
  177. // specialization for strict alternatives
  178. template <typename OutputIterator, typename Context, typename Delimiter,
  179. typename Attribute>
  180. struct alternative_generate_function<
  181. OutputIterator, Context, Delimiter, Attribute, mpl::true_>
  182. {
  183. alternative_generate_function(OutputIterator& sink_, Context& ctx_
  184. , Delimiter const& d, Attribute const& attr_)
  185. : sink(sink_), ctx(ctx_), delim(d), attr(attr_), failed(false) {}
  186. template <typename Component>
  187. bool operator()(Component const& component)
  188. {
  189. typedef
  190. typename traits::attribute_of<Component, Context>::type
  191. expected_type;
  192. typedef
  193. alternative_generate<Component, Attribute, expected_type>
  194. generate;
  195. if (failed)
  196. return false; // give up when already failed
  197. // wrap the given output iterator avoid output as long as one
  198. // component fails
  199. detail::enable_buffering<OutputIterator> buffering(sink);
  200. bool r = false;
  201. {
  202. detail::disable_counting<OutputIterator> nocounting(sink);
  203. r = generate::call(component, sink, ctx, delim, attr, failed);
  204. }
  205. if (r && !failed)
  206. {
  207. buffering.buffer_copy();
  208. return true;
  209. }
  210. return false;
  211. }
  212. OutputIterator& sink;
  213. Context& ctx;
  214. Delimiter const& delim;
  215. Attribute const& attr;
  216. bool failed;
  217. private:
  218. // silence MSVC warning C4512: assignment operator could not be generated
  219. alternative_generate_function& operator= (alternative_generate_function const&);
  220. };
  221. }}}}
  222. #endif