info.hpp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  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. private:
  99. // silence MSVC warning C4512: assignment operator could not be generated
  100. basic_info_walker& operator= (basic_info_walker const&);
  101. };
  102. // bare-bones print support
  103. template <typename Out>
  104. struct simple_printer
  105. {
  106. typedef utf8_string string;
  107. simple_printer(Out& out_)
  108. : out(out_) {}
  109. void element(string const& tag, string const& value, int /*depth*/) const
  110. {
  111. if (value == "")
  112. out << '<' << tag << '>';
  113. else
  114. out << '"' << value << '"';
  115. }
  116. Out& out;
  117. private:
  118. // silence MSVC warning C4512: assignment operator could not be generated
  119. simple_printer& operator= (simple_printer const&);
  120. };
  121. template <typename Out>
  122. Out& operator<<(Out& out, info const& what)
  123. {
  124. simple_printer<Out> pr(out);
  125. basic_info_walker<simple_printer<Out> > walker(pr, what.tag, 0);
  126. boost::apply_visitor(walker, what.value);
  127. return out;
  128. }
  129. }}
  130. #endif