info.hpp 4.6 KB

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