info.hpp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. /*=============================================================================
  2. Copyright (c) 2001-2011 Joel de Guzman
  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. ==============================================================================*/
  6. #if !defined(BOOST_SPIRIT_INFO_NOVEMBER_22_2008_1132AM)
  7. #define BOOST_SPIRIT_INFO_NOVEMBER_22_2008_1132AM
  8. #if defined(_MSC_VER)
  9. #pragma once
  10. #endif
  11. #include <boost/variant/variant.hpp>
  12. #include <boost/variant/recursive_variant.hpp>
  13. #include <boost/variant/apply_visitor.hpp>
  14. #include <boost/foreach.hpp>
  15. #include <boost/spirit/home/support/utf8.hpp>
  16. #include <list>
  17. #include <iterator>
  18. #include <utility>
  19. namespace boost { namespace spirit
  20. {
  21. // info provides information about a component. Each component
  22. // has a what member function that returns an info object.
  23. // strings in the info object are assumed to be encoded as UTF8
  24. // for uniformity.
  25. struct info
  26. {
  27. struct nil_ {};
  28. typedef
  29. boost::variant<
  30. nil_
  31. , utf8_string
  32. , recursive_wrapper<info>
  33. , recursive_wrapper<std::pair<info, info> >
  34. , recursive_wrapper<std::list<info> >
  35. >
  36. value_type;
  37. explicit info(utf8_string const& tag_)
  38. : tag(tag_), value(nil_()) {}
  39. template <typename T>
  40. info(utf8_string const& tag_, T const& value_)
  41. : tag(tag_), value(value_) {}
  42. info(utf8_string const& tag_, char value_)
  43. : tag(tag_), value(utf8_string(1, value_)) {}
  44. info(utf8_string const& tag_, wchar_t value_)
  45. : tag(tag_), value(to_utf8(value_)) {}
  46. info(utf8_string const& tag_, ucs4_char value_)
  47. : tag(tag_), value(to_utf8(value_)) {}
  48. template <typename Char>
  49. info(utf8_string const& tag_, Char const* str)
  50. : tag(tag_), value(to_utf8(str)) {}
  51. template <typename Char, typename Traits, typename Allocator>
  52. info(utf8_string const& tag_
  53. , std::basic_string<Char, Traits, Allocator> const& str)
  54. : tag(tag_), value(to_utf8(str)) {}
  55. utf8_string tag;
  56. value_type value;
  57. };
  58. template <typename Callback>
  59. struct basic_info_walker
  60. {
  61. typedef void result_type;
  62. typedef basic_info_walker<Callback> this_type;
  63. basic_info_walker(Callback& callback_, utf8_string const& tag_, int depth_)
  64. : callback(callback_), tag(tag_), depth(depth_) {}
  65. void operator()(info::nil_) const
  66. {
  67. callback.element(tag, "", depth);
  68. }
  69. void operator()(utf8_string const& str) const
  70. {
  71. callback.element(tag, str, depth);
  72. }
  73. void operator()(info const& what) const
  74. {
  75. boost::apply_visitor(
  76. this_type(callback, what.tag, depth+1), what.value);
  77. }
  78. void operator()(std::pair<info, info> const& pair) const
  79. {
  80. callback.element(tag, "", depth);
  81. boost::apply_visitor(
  82. this_type(callback, pair.first.tag, depth+1), pair.first.value);
  83. boost::apply_visitor(
  84. this_type(callback, pair.second.tag, depth+1), pair.second.value);
  85. }
  86. void operator()(std::list<info> const& l) const
  87. {
  88. callback.element(tag, "", depth);
  89. BOOST_FOREACH(info const& what, l)
  90. {
  91. boost::apply_visitor(
  92. this_type(callback, what.tag, depth+1), what.value);
  93. }
  94. }
  95. Callback& callback;
  96. utf8_string const& tag;
  97. int depth;
  98. // silence MSVC warning C4512: assignment operator could not be generated
  99. BOOST_DELETED_FUNCTION(basic_info_walker& operator= (basic_info_walker const&))
  100. };
  101. // bare-bones print support
  102. template <typename Out>
  103. struct simple_printer
  104. {
  105. typedef utf8_string string;
  106. simple_printer(Out& out_)
  107. : out(out_) {}
  108. void element(string const& tag, string const& value, int /*depth*/) const
  109. {
  110. if (value.empty())
  111. out << '<' << tag << '>';
  112. else
  113. out << '"' << value << '"';
  114. }
  115. Out& out;
  116. // silence MSVC warning C4512: assignment operator could not be generated
  117. BOOST_DELETED_FUNCTION(simple_printer& operator= (simple_printer const&))
  118. };
  119. template <typename Out>
  120. Out& operator<<(Out& out, info const& what)
  121. {
  122. simple_printer<Out> pr(out);
  123. basic_info_walker<simple_printer<Out> > walker(pr, what.tag, 0);
  124. boost::apply_visitor(walker, what.value);
  125. return out;
  126. }
  127. }}
  128. #endif