manip.hpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. /*=============================================================================
  2. Copyright (c) 1999-2003 Jeremiah Willcock
  3. Copyright (c) 1999-2003 Jaakko Jarvi
  4. Copyright (c) 2001-2011 Joel de Guzman
  5. Distributed under the Boost Software License, Version 1.0. (See accompanying
  6. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  7. ==============================================================================*/
  8. #if !defined(FUSION_MANIP_05052005_1200)
  9. #define FUSION_MANIP_05052005_1200
  10. #include <boost/fusion/support/config.hpp>
  11. #include <boost/config.hpp>
  12. #include <string>
  13. #include <vector>
  14. #include <cctype>
  15. // Tuple I/O manipulators
  16. #define FUSION_GET_CHAR_TYPE(T) typename T::char_type
  17. #define FUSION_GET_TRAITS_TYPE(T) typename T::traits_type
  18. #define FUSION_STRING_OF_STREAM(Stream) \
  19. std::basic_string< \
  20. FUSION_GET_CHAR_TYPE(Stream) \
  21. , FUSION_GET_TRAITS_TYPE(Stream) \
  22. >
  23. //$$$ these should be part of the public API$$$
  24. //$$$ rename tuple_open, tuple_close and tuple_delimiter to
  25. // open, close and delimeter and add these synonyms to the
  26. // TR1 tuple module.
  27. namespace boost { namespace fusion
  28. {
  29. namespace detail
  30. {
  31. template <typename Tag>
  32. int get_xalloc_index(Tag* = 0)
  33. {
  34. // each Tag will have a unique index
  35. static int index = std::ios::xalloc();
  36. return index;
  37. }
  38. template <typename Stream, typename Tag, typename T>
  39. struct stream_data
  40. {
  41. struct arena
  42. {
  43. ~arena()
  44. {
  45. for (
  46. typename std::vector<T*>::iterator i = data.begin()
  47. ; i != data.end()
  48. ; ++i)
  49. {
  50. delete *i;
  51. }
  52. }
  53. std::vector<T*> data;
  54. };
  55. static void attach(Stream& stream, T const& data)
  56. {
  57. static arena ar; // our arena
  58. ar.data.push_back(new T(data));
  59. stream.pword(get_xalloc_index<Tag>()) = ar.data.back();
  60. }
  61. static T const* get(Stream& stream)
  62. {
  63. return (T const*)stream.pword(get_xalloc_index<Tag>());
  64. }
  65. };
  66. template <typename Tag, typename Stream>
  67. class string_ios_manip
  68. {
  69. public:
  70. typedef FUSION_STRING_OF_STREAM(Stream) string_type;
  71. typedef stream_data<Stream, Tag, string_type> stream_data_t;
  72. string_ios_manip(Stream& str_)
  73. : stream(str_)
  74. {}
  75. void
  76. set(string_type const& s)
  77. {
  78. stream_data_t::attach(stream, s);
  79. }
  80. void
  81. print(char const* default_) const
  82. {
  83. // print a delimiter
  84. string_type const* p = stream_data_t::get(stream);
  85. if (p)
  86. stream << *p;
  87. else
  88. stream << default_;
  89. }
  90. void
  91. read(char const* default_) const
  92. {
  93. // read a delimiter
  94. string_type const* p = stream_data_t::get(stream);
  95. std::ws(stream);
  96. if (p)
  97. {
  98. typedef typename string_type::const_iterator iterator;
  99. for (iterator i = p->begin(); i != p->end(); ++i)
  100. check_delim(*i);
  101. }
  102. else
  103. {
  104. while (*default_)
  105. check_delim(*default_++);
  106. }
  107. }
  108. private:
  109. template <typename Char>
  110. void
  111. check_delim(Char c) const
  112. {
  113. using namespace std;
  114. if (!isspace(c))
  115. {
  116. if (stream.get() != c)
  117. {
  118. stream.unget();
  119. stream.setstate(std::ios::failbit);
  120. }
  121. }
  122. }
  123. Stream& stream;
  124. // silence MSVC warning C4512: assignment operator could not be generated
  125. BOOST_DELETED_FUNCTION(string_ios_manip& operator= (string_ios_manip const&))
  126. };
  127. } // detail
  128. #if defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
  129. #define STD_TUPLE_DEFINE_MANIPULATOR_FUNCTIONS(name) \
  130. template <typename Char, typename Traits> \
  131. inline detail::name##_type<Char, Traits> \
  132. name(const std::basic_string<Char, Traits>& s) \
  133. { \
  134. return detail::name##_type<Char, Traits>(s); \
  135. } \
  136. \
  137. inline detail::name##_type<char> \
  138. name(char const* s) \
  139. { \
  140. return detail::name##_type<char>(std::basic_string<char>(s)); \
  141. } \
  142. \
  143. inline detail::name##_type<wchar_t> \
  144. name(wchar_t const* s) \
  145. { \
  146. return detail::name##_type<wchar_t>(std::basic_string<wchar_t>(s)); \
  147. } \
  148. \
  149. inline detail::name##_type<char> \
  150. name(char c) \
  151. { \
  152. return detail::name##_type<char>(std::basic_string<char>(1, c)); \
  153. } \
  154. \
  155. inline detail::name##_type<wchar_t> \
  156. name(wchar_t c) \
  157. { \
  158. return detail::name##_type<wchar_t>(std::basic_string<wchar_t>(1, c)); \
  159. }
  160. #else // defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
  161. #define STD_TUPLE_DEFINE_MANIPULATOR_FUNCTIONS(name) \
  162. template <typename Char, typename Traits> \
  163. inline detail::name##_type<Char, Traits> \
  164. name(const std::basic_string<Char, Traits>& s) \
  165. { \
  166. return detail::name##_type<Char, Traits>(s); \
  167. } \
  168. \
  169. template <typename Char> \
  170. inline detail::name##_type<Char> \
  171. name(Char s[]) \
  172. { \
  173. return detail::name##_type<Char>(std::basic_string<Char>(s)); \
  174. } \
  175. \
  176. template <typename Char> \
  177. inline detail::name##_type<Char> \
  178. name(Char const s[]) \
  179. { \
  180. return detail::name##_type<Char>(std::basic_string<Char>(s)); \
  181. } \
  182. \
  183. template <typename Char> \
  184. inline detail::name##_type<Char> \
  185. name(Char c) \
  186. { \
  187. return detail::name##_type<Char>(std::basic_string<Char>(1, c)); \
  188. }
  189. #endif
  190. #define STD_TUPLE_DEFINE_MANIPULATOR(name) \
  191. namespace detail \
  192. { \
  193. struct name##_tag; \
  194. \
  195. template <typename Char, typename Traits = std::char_traits<Char> > \
  196. struct name##_type \
  197. { \
  198. typedef std::basic_string<Char, Traits> string_type; \
  199. string_type data; \
  200. name##_type(const string_type& d): data(d) {} \
  201. }; \
  202. \
  203. template <typename Stream, typename Char, typename Traits> \
  204. Stream& operator>>(Stream& s, const name##_type<Char,Traits>& m) \
  205. { \
  206. string_ios_manip<name##_tag, Stream> manip(s); \
  207. manip.set(m.data); \
  208. return s; \
  209. } \
  210. \
  211. template <typename Stream, typename Char, typename Traits> \
  212. Stream& operator<<(Stream& s, const name##_type<Char,Traits>& m) \
  213. { \
  214. string_ios_manip<name##_tag, Stream> manip(s); \
  215. manip.set(m.data); \
  216. return s; \
  217. } \
  218. } \
  219. STD_TUPLE_DEFINE_MANIPULATOR(tuple_open)
  220. STD_TUPLE_DEFINE_MANIPULATOR(tuple_close)
  221. STD_TUPLE_DEFINE_MANIPULATOR(tuple_delimiter)
  222. STD_TUPLE_DEFINE_MANIPULATOR_FUNCTIONS(tuple_open)
  223. STD_TUPLE_DEFINE_MANIPULATOR_FUNCTIONS(tuple_close)
  224. STD_TUPLE_DEFINE_MANIPULATOR_FUNCTIONS(tuple_delimiter)
  225. #undef STD_TUPLE_DEFINE_MANIPULATOR
  226. #undef STD_TUPLE_DEFINE_MANIPULATOR_FUNCTIONS
  227. #undef FUSION_STRING_OF_STREAM
  228. #undef FUSION_GET_CHAR_TYPE
  229. #undef FUSION_GET_TRAITS_TYPE
  230. }}
  231. #endif