format_manip.hpp 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  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(BOOST_SPIRIT_KARMA_FORMAT_MANIP_MAY_03_2007_1424PM)
  6. #define BOOST_SPIRIT_KARMA_FORMAT_MANIP_MAY_03_2007_1424PM
  7. #if defined(_MSC_VER)
  8. #pragma once
  9. #endif
  10. #include <iterator>
  11. #include <string>
  12. #include <boost/spirit/home/karma/generate.hpp>
  13. #include <boost/spirit/home/support/iterators/ostream_iterator.hpp>
  14. #include <boost/mpl/bool.hpp>
  15. ///////////////////////////////////////////////////////////////////////////////
  16. namespace boost { namespace spirit { namespace karma { namespace detail
  17. {
  18. ///////////////////////////////////////////////////////////////////////////
  19. template <typename Expr
  20. , typename CopyExpr = mpl::false_, typename CopyAttr = mpl::false_
  21. , typename Delimiter = unused_type, typename Attribute = unused_type>
  22. struct format_manip
  23. {
  24. // This assertion makes sure we don't hit the only code path which is
  25. // not implemented (because it isn't needed), where both, the
  26. // expression and the attribute need to be held as a copy.
  27. BOOST_SPIRIT_ASSERT_MSG(!CopyExpr::value || !CopyAttr::value
  28. , error_invalid_should_not_happen, ());
  29. format_manip(Expr const& xpr, Delimiter const& d, Attribute const& a)
  30. : expr(xpr), delim(d), pre(delimit_flag::dont_predelimit), attr(a) {}
  31. format_manip(Expr const& xpr, Delimiter const& d
  32. , BOOST_SCOPED_ENUM(delimit_flag) pre_delimit, Attribute const& a)
  33. : expr(xpr), delim(d), pre(pre_delimit), attr(a) {}
  34. Expr const& expr;
  35. Delimiter const& delim;
  36. BOOST_SCOPED_ENUM(delimit_flag) const pre;
  37. Attribute const& attr;
  38. // silence MSVC warning C4512: assignment operator could not be generated
  39. BOOST_DELETED_FUNCTION(format_manip& operator= (format_manip const&))
  40. };
  41. template <typename Expr, typename Delimiter, typename Attribute>
  42. struct format_manip<Expr, mpl::false_, mpl::true_, Delimiter, Attribute>
  43. {
  44. format_manip(Expr const& xpr, Delimiter const& d, Attribute const& a)
  45. : expr(xpr), delim(d), pre(delimit_flag::dont_predelimit), attr(a) {}
  46. format_manip(Expr const& xpr, Delimiter const& d
  47. , BOOST_SCOPED_ENUM(delimit_flag) pre_delimit, Attribute const& a)
  48. : expr(xpr), delim(d), pre(pre_delimit), attr(a) {}
  49. Expr const& expr;
  50. Delimiter const& delim;
  51. BOOST_SCOPED_ENUM(delimit_flag) const pre;
  52. Attribute attr;
  53. // silence MSVC warning C4512: assignment operator could not be generated
  54. BOOST_DELETED_FUNCTION(format_manip& operator= (format_manip const&))
  55. };
  56. template <typename Expr, typename Delimiter, typename Attribute>
  57. struct format_manip<Expr, mpl::true_, mpl::false_, Delimiter, Attribute>
  58. {
  59. format_manip(Expr const& xpr, Delimiter const& d, Attribute const& a)
  60. : expr(xpr), delim(d), pre(delimit_flag::dont_predelimit), attr(a) {}
  61. format_manip(Expr const& xpr, Delimiter const& d
  62. , BOOST_SCOPED_ENUM(delimit_flag) pre_delimit, Attribute const& a)
  63. : expr(xpr), delim(d), pre(pre_delimit), attr(a) {}
  64. Expr expr;
  65. Delimiter const& delim;
  66. BOOST_SCOPED_ENUM(delimit_flag) const pre;
  67. Attribute const& attr;
  68. // silence MSVC warning C4512: assignment operator could not be generated
  69. BOOST_DELETED_FUNCTION(format_manip& operator= (format_manip const&))
  70. };
  71. ///////////////////////////////////////////////////////////////////////////
  72. template <typename Expr, typename Enable = void>
  73. struct format
  74. {
  75. // Report invalid expression error as early as possible.
  76. // If you got an error_invalid_expression error message here,
  77. // then the expression (Expr) is not a valid spirit karma expression.
  78. // Did you intend to use the auto_ facilities while forgetting to
  79. // #include <boost/spirit/include/karma_format_auto.hpp>?
  80. BOOST_SPIRIT_ASSERT_MATCH(karma::domain, Expr);
  81. };
  82. template <typename Expr>
  83. struct format<Expr
  84. , typename enable_if<traits::matches<karma::domain, Expr> >::type>
  85. {
  86. typedef format_manip<Expr> type;
  87. static type call(Expr const& expr)
  88. {
  89. return type(expr, unused, unused);
  90. }
  91. };
  92. ///////////////////////////////////////////////////////////////////////////
  93. template <typename Expr, typename Delimiter, typename Enable = void>
  94. struct format_delimited
  95. {
  96. // Report invalid expression error as early as possible.
  97. // If you got an error_invalid_expression error message here,
  98. // then the expression (Expr) is not a valid spirit karma expression.
  99. // Did you intend to use the auto_ facilities while forgetting to
  100. // #include <boost/spirit/include/karma_format_auto.hpp>?
  101. BOOST_SPIRIT_ASSERT_MATCH(karma::domain, Expr);
  102. };
  103. template <typename Expr, typename Delimiter>
  104. struct format_delimited<Expr, Delimiter
  105. , typename enable_if<traits::matches<karma::domain, Expr> >::type>
  106. {
  107. typedef format_manip<Expr, mpl::false_, mpl::false_, Delimiter> type;
  108. static type call(
  109. Expr const& expr
  110. , Delimiter const& delimiter
  111. , BOOST_SCOPED_ENUM(delimit_flag) pre_delimit)
  112. {
  113. // Report invalid expression error as early as possible.
  114. // If you got an error_invalid_expression error message here,
  115. // then the delimiter is not a valid spirit karma expression.
  116. BOOST_SPIRIT_ASSERT_MATCH(karma::domain, Delimiter);
  117. return type(expr, delimiter, pre_delimit, unused);
  118. }
  119. };
  120. ///////////////////////////////////////////////////////////////////////////
  121. template<typename Char, typename Traits, typename Expr
  122. , typename CopyExpr, typename CopyAttr>
  123. inline std::basic_ostream<Char, Traits> &
  124. operator<< (std::basic_ostream<Char, Traits> &os
  125. , format_manip<Expr, CopyExpr, CopyAttr> const& fm)
  126. {
  127. karma::ostream_iterator<Char, Char, Traits> sink(os);
  128. if (!karma::generate (sink, fm.expr))
  129. {
  130. os.setstate(std::ios_base::failbit);
  131. }
  132. return os;
  133. }
  134. ///////////////////////////////////////////////////////////////////////////
  135. template<typename Char, typename Traits, typename Expr
  136. , typename CopyExpr, typename CopyAttr, typename Attribute>
  137. inline std::basic_ostream<Char, Traits> &
  138. operator<< (std::basic_ostream<Char, Traits> &os
  139. , format_manip<Expr, CopyExpr, CopyAttr, unused_type, Attribute> const& fm)
  140. {
  141. karma::ostream_iterator<Char, Char, Traits> sink(os);
  142. if (!karma::generate(sink, fm.expr, fm.attr))
  143. {
  144. os.setstate(std::ios_base::failbit);
  145. }
  146. return os;
  147. }
  148. template<typename Char, typename Traits, typename Expr
  149. , typename CopyExpr, typename CopyAttr, typename Delimiter>
  150. inline std::basic_ostream<Char, Traits> &
  151. operator<< (std::basic_ostream<Char, Traits> &os
  152. , format_manip<Expr, CopyExpr, CopyAttr, Delimiter> const& fm)
  153. {
  154. karma::ostream_iterator<Char, Char, Traits> sink(os);
  155. if (!karma::generate_delimited(sink, fm.expr, fm.delim, fm.pre))
  156. {
  157. os.setstate(std::ios_base::failbit);
  158. }
  159. return os;
  160. }
  161. ///////////////////////////////////////////////////////////////////////////
  162. template<typename Char, typename Traits, typename Expr
  163. , typename CopyExpr, typename CopyAttr, typename Delimiter
  164. , typename Attribute>
  165. inline std::basic_ostream<Char, Traits> &
  166. operator<< (std::basic_ostream<Char, Traits> &os
  167. , format_manip<Expr, CopyExpr, CopyAttr, Delimiter, Attribute> const& fm)
  168. {
  169. karma::ostream_iterator<Char, Char, Traits> sink(os);
  170. if (!karma::generate_delimited(sink, fm.expr, fm.delim, fm.pre, fm.attr))
  171. {
  172. os.setstate(std::ios_base::failbit);
  173. }
  174. return os;
  175. }
  176. }}}}
  177. #endif