print_attribute.hpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  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. namespace boost { namespace spirit { namespace x3 { namespace traits
  16. {
  17. template <typename Out, typename T>
  18. void print_attribute(Out& out, T const& val);
  19. template <typename Out>
  20. inline void print_attribute(Out&, unused_type) {}
  21. ///////////////////////////////////////////////////////////////////////////
  22. namespace detail
  23. {
  24. template <typename Out>
  25. struct print_fusion_sequence
  26. {
  27. print_fusion_sequence(Out& out)
  28. : out(out), is_first(true) {}
  29. typedef void result_type;
  30. template <typename T>
  31. void operator()(T const& val) const
  32. {
  33. if (is_first)
  34. is_first = false;
  35. else
  36. out << ", ";
  37. x3::traits::print_attribute(out, val);
  38. }
  39. Out& out;
  40. mutable bool is_first;
  41. };
  42. // print elements in a variant
  43. template <typename Out>
  44. struct print_visitor : static_visitor<>
  45. {
  46. print_visitor(Out& out) : out(out) {}
  47. template <typename T>
  48. void operator()(T const& val) const
  49. {
  50. x3::traits::print_attribute(out, val);
  51. }
  52. Out& out;
  53. };
  54. }
  55. template <typename Out, typename T, typename Enable = void>
  56. struct print_attribute_debug
  57. {
  58. // for plain data types
  59. template <typename T_>
  60. static void call(Out& out, T_ const& val, unused_attribute)
  61. {
  62. out << "unused";
  63. }
  64. // for plain data types
  65. template <typename T_>
  66. static void call(Out& out, T_ const& val, plain_attribute)
  67. {
  68. out << val;
  69. }
  70. // for fusion data types
  71. template <typename T_>
  72. static void call(Out& out, T_ const& val, tuple_attribute)
  73. {
  74. out << '[';
  75. fusion::for_each(val, detail::print_fusion_sequence<Out>(out));
  76. out << ']';
  77. }
  78. // stl container
  79. template <typename T_>
  80. static void call(Out& out, T_ const& val, container_attribute)
  81. {
  82. out << '[';
  83. if (!traits::is_empty(val))
  84. {
  85. bool first = true;
  86. typename container_iterator<T_ const>::type iend = traits::end(val);
  87. for (typename container_iterator<T_ const>::type i = traits::begin(val);
  88. !traits::compare(i, iend); traits::next(i))
  89. {
  90. if (!first)
  91. out << ", ";
  92. first = false;
  93. x3::traits::print_attribute(out, traits::deref(i));
  94. }
  95. }
  96. out << ']';
  97. }
  98. // for variant types
  99. template <typename T_>
  100. static void call(Out& out, T_ const& val, variant_attribute)
  101. {
  102. apply_visitor(detail::print_visitor<Out>(out), val);
  103. }
  104. // for optional types
  105. template <typename T_>
  106. static void call(Out& out, T_ const& val, optional_attribute)
  107. {
  108. if (val)
  109. x3::traits::print_attribute(out, *val);
  110. else
  111. out << "[empty]";
  112. }
  113. // main entry point
  114. static void call(Out& out, T const& val)
  115. {
  116. call(out, val, typename attribute_category<T>::type());
  117. }
  118. };
  119. ///////////////////////////////////////////////////////////////////////////
  120. template <typename Out, typename T>
  121. inline void print_attribute(Out& out, T const& val)
  122. {
  123. print_attribute_debug<Out, T>::call(out, val);
  124. }
  125. }}}}
  126. #endif