print_attribute.hpp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. /*=============================================================================
  2. Copyright (c) 2001-2014 Joel de Guzman
  3. Copyright (c) 2001-2011 Hartmut Kaiser
  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. ================================================_==============================*/
  7. #if !defined(BOOST_SPIRIT_X3_PRINT_ATTRIBUTE_JANUARY_20_2013_0814AM)
  8. #define BOOST_SPIRIT_X3_PRINT_ATTRIBUTE_JANUARY_20_2013_0814AM
  9. #include <boost/variant.hpp>
  10. #include <boost/optional/optional.hpp>
  11. #include <boost/fusion/include/is_sequence.hpp>
  12. #include <boost/fusion/include/for_each.hpp>
  13. #include <boost/spirit/home/x3/support/traits/attribute_category.hpp>
  14. #include <boost/spirit/home/x3/support/traits/is_variant.hpp>
  15. #ifdef BOOST_SPIRIT_X3_UNICODE
  16. # include <boost/spirit/home/support/char_encoding/unicode.hpp>
  17. #endif
  18. namespace boost { namespace spirit { namespace x3 { namespace traits
  19. {
  20. template <typename Out, typename T>
  21. void print_attribute(Out& out, T const& val);
  22. template <typename Out>
  23. inline void print_attribute(Out&, unused_type) {}
  24. ///////////////////////////////////////////////////////////////////////////
  25. namespace detail
  26. {
  27. template <typename Out>
  28. struct print_fusion_sequence
  29. {
  30. print_fusion_sequence(Out& out)
  31. : out(out), is_first(true) {}
  32. typedef void result_type;
  33. template <typename T>
  34. void operator()(T const& val) const
  35. {
  36. if (is_first)
  37. is_first = false;
  38. else
  39. out << ", ";
  40. x3::traits::print_attribute(out, val);
  41. }
  42. Out& out;
  43. mutable bool is_first;
  44. };
  45. // print elements in a variant
  46. template <typename Out>
  47. struct print_visitor : static_visitor<>
  48. {
  49. print_visitor(Out& out) : out(out) {}
  50. template <typename T>
  51. void operator()(T const& val) const
  52. {
  53. x3::traits::print_attribute(out, val);
  54. }
  55. Out& out;
  56. };
  57. }
  58. template <typename Out, typename T, typename Enable = void>
  59. struct print_attribute_debug
  60. {
  61. // for unused_type
  62. static void call(Out& out, unused_type, unused_attribute)
  63. {
  64. out << "unused";
  65. }
  66. // for plain data types
  67. template <typename T_>
  68. static void call(Out& out, T_ const& val, plain_attribute)
  69. {
  70. out << val;
  71. }
  72. #ifdef BOOST_SPIRIT_X3_UNICODE
  73. static void call(Out& out, char_encoding::unicode::char_type val, plain_attribute)
  74. {
  75. if (val >= 0 && val < 127)
  76. {
  77. if (iscntrl(val))
  78. out << "\\" << std::oct << int(val) << std::dec;
  79. else if (isprint(val))
  80. out << char(val);
  81. else
  82. out << "\\x" << std::hex << int(val) << std::dec;
  83. }
  84. else
  85. out << "\\x" << std::hex << int(val) << std::dec;
  86. }
  87. static void call(Out& out, char val, plain_attribute tag)
  88. {
  89. call(out, static_cast<char_encoding::unicode::char_type>(val), tag);
  90. }
  91. #endif
  92. // for fusion data types
  93. template <typename T_>
  94. static void call(Out& out, T_ const& val, tuple_attribute)
  95. {
  96. out << '[';
  97. fusion::for_each(val, detail::print_fusion_sequence<Out>(out));
  98. out << ']';
  99. }
  100. // stl container
  101. template <typename T_>
  102. static void call(Out& out, T_ const& val, container_attribute)
  103. {
  104. out << '[';
  105. if (!traits::is_empty(val))
  106. {
  107. bool first = true;
  108. typename container_iterator<T_ const>::type iend = traits::end(val);
  109. for (typename container_iterator<T_ const>::type i = traits::begin(val);
  110. !traits::compare(i, iend); traits::next(i))
  111. {
  112. if (!first)
  113. out << ", ";
  114. first = false;
  115. x3::traits::print_attribute(out, traits::deref(i));
  116. }
  117. }
  118. out << ']';
  119. }
  120. // for variant types
  121. template <typename T_>
  122. static void call(Out& out, T_ const& val, variant_attribute)
  123. {
  124. apply_visitor(detail::print_visitor<Out>(out), val);
  125. }
  126. // for optional types
  127. template <typename T_>
  128. static void call(Out& out, T_ const& val, optional_attribute)
  129. {
  130. if (val)
  131. x3::traits::print_attribute(out, *val);
  132. else
  133. out << "[empty]";
  134. }
  135. // main entry point
  136. static void call(Out& out, T const& val)
  137. {
  138. call(out, val, typename attribute_category<T>::type());
  139. }
  140. };
  141. ///////////////////////////////////////////////////////////////////////////
  142. template <typename Out, typename T>
  143. inline void print_attribute(Out& out, T const& val)
  144. {
  145. print_attribute_debug<Out, T>::call(out, val);
  146. }
  147. }}}}
  148. #endif