as.hpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. // Copyright (c) 2001-2011 Hartmut Kaiser
  2. // Copyright (c) 2010 Bryce Lelbach
  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_AS_DEC_18_0510PM)
  7. #define SPIRIT_KARMA_AS_DEC_18_0510PM
  8. #if defined(_MSC_VER)
  9. #pragma once
  10. #endif
  11. #include <boost/spirit/home/karma/meta_compiler.hpp>
  12. #include <boost/spirit/home/karma/generator.hpp>
  13. #include <boost/spirit/home/karma/domain.hpp>
  14. #include <boost/spirit/home/karma/detail/output_iterator.hpp>
  15. #include <boost/spirit/home/karma/detail/as.hpp>
  16. #include <boost/spirit/home/support/unused.hpp>
  17. #include <boost/spirit/home/support/info.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/support/assert_msg.hpp>
  22. #include <boost/spirit/home/support/container.hpp>
  23. #include <boost/spirit/home/karma/detail/attributes.hpp>
  24. namespace boost { namespace spirit { namespace karma
  25. {
  26. template <typename T>
  27. struct as
  28. : stateful_tag_type<T, tag::as>
  29. {
  30. BOOST_SPIRIT_ASSERT_MSG(
  31. (traits::is_container<T>::type::value),
  32. error_type_must_be_a_container,
  33. (T));
  34. };
  35. }}}
  36. namespace boost { namespace spirit
  37. {
  38. ///////////////////////////////////////////////////////////////////////////
  39. // Enablers
  40. ///////////////////////////////////////////////////////////////////////////
  41. // enables as_string[...]
  42. template <>
  43. struct use_directive<karma::domain, tag::as_string>
  44. : mpl::true_ {};
  45. // enables as_wstring[...]
  46. template <>
  47. struct use_directive<karma::domain, tag::as_wstring>
  48. : mpl::true_ {};
  49. // enables as<T>[...]
  50. template <typename T>
  51. struct use_directive<karma::domain, tag::stateful_tag<T, tag::as> >
  52. : mpl::true_
  53. {};
  54. }}
  55. namespace boost { namespace spirit { namespace karma
  56. {
  57. #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
  58. using spirit::as_string;
  59. using spirit::as_wstring;
  60. #endif
  61. using spirit::as_string_type;
  62. using spirit::as_wstring_type;
  63. ///////////////////////////////////////////////////////////////////////////
  64. // as_directive allows to hook custom conversions to string into the
  65. // output generation process
  66. ///////////////////////////////////////////////////////////////////////////
  67. template <typename Subject, typename T>
  68. struct as_directive
  69. : unary_generator<as_directive<Subject, T> >
  70. {
  71. typedef Subject subject_type;
  72. typedef typename subject_type::properties properties;
  73. as_directive(Subject const& subject)
  74. : subject(subject) {}
  75. template <typename Context, typename Iterator>
  76. struct attribute
  77. {
  78. typedef T type;
  79. };
  80. template <typename OutputIterator, typename Context, typename Delimiter
  81. , typename Attribute>
  82. bool generate(OutputIterator& sink, Context& ctx, Delimiter const& d
  83. , Attribute const& attr) const
  84. {
  85. if (!traits::valid_as<T>(attr))
  86. return false;
  87. return subject.generate(sink, ctx, d, traits::as<T>(attr)) &&
  88. karma::delimit_out(sink, d); // always do post-delimiting
  89. }
  90. template <typename Context>
  91. info what(Context& context) const
  92. {
  93. return info("as", subject.what(context));
  94. }
  95. Subject subject;
  96. };
  97. ///////////////////////////////////////////////////////////////////////////
  98. // Generator generators: make_xxx function (objects)
  99. ///////////////////////////////////////////////////////////////////////////
  100. template <typename Subject, typename Modifiers>
  101. struct make_directive<tag::as_string, Subject, Modifiers>
  102. {
  103. typedef as_directive<Subject, std::string> result_type;
  104. result_type operator()(unused_type, Subject const& subject
  105. , unused_type) const
  106. {
  107. return result_type(subject);
  108. }
  109. };
  110. template <typename Subject, typename Modifiers>
  111. struct make_directive<tag::as_wstring, Subject, Modifiers>
  112. {
  113. typedef as_directive<Subject, std::basic_string<wchar_t> > result_type;
  114. result_type operator()(unused_type, Subject const& subject
  115. , unused_type) const
  116. {
  117. return result_type(subject);
  118. }
  119. };
  120. template <typename T, typename Subject, typename Modifiers>
  121. struct make_directive<tag::stateful_tag<T, tag::as>, Subject, Modifiers>
  122. {
  123. typedef as_directive<Subject, T> result_type;
  124. result_type operator()(unused_type, Subject const& subject
  125. , unused_type) const
  126. {
  127. return result_type(subject);
  128. }
  129. };
  130. }}}
  131. namespace boost { namespace spirit { namespace traits
  132. {
  133. ///////////////////////////////////////////////////////////////////////////
  134. template <typename Subject, typename T>
  135. struct has_semantic_action<karma::as_directive<Subject, T> >
  136. : unary_has_semantic_action<Subject> {};
  137. ///////////////////////////////////////////////////////////////////////////
  138. template <typename Subject, typename T, typename Attribute
  139. , typename Context, typename Iterator>
  140. struct handles_container<karma::as_directive<Subject, T>, Attribute
  141. , Context, Iterator>
  142. : mpl::false_ {}; // always dereference attribute if used in sequences
  143. }}}
  144. #endif