manip.hpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  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. private:
  125. // silence MSVC warning C4512: assignment operator could not be generated
  126. string_ios_manip& operator= (string_ios_manip const&);
  127. };
  128. } // detail
  129. #if defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
  130. #define STD_TUPLE_DEFINE_MANIPULATOR_FUNCTIONS(name) \
  131. template <typename Char, typename Traits> \
  132. inline detail::name##_type<Char, Traits> \
  133. name(const std::basic_string<Char, Traits>& s) \
  134. { \
  135. return detail::name##_type<Char, Traits>(s); \
  136. } \
  137. \
  138. inline detail::name##_type<char> \
  139. name(char const* s) \
  140. { \
  141. return detail::name##_type<char>(std::basic_string<char>(s)); \
  142. } \
  143. \
  144. inline detail::name##_type<wchar_t> \
  145. name(wchar_t const* s) \
  146. { \
  147. return detail::name##_type<wchar_t>(std::basic_string<wchar_t>(s)); \
  148. } \
  149. \
  150. inline detail::name##_type<char> \
  151. name(char c) \
  152. { \
  153. return detail::name##_type<char>(std::basic_string<char>(1, c)); \
  154. } \
  155. \
  156. inline detail::name##_type<wchar_t> \
  157. name(wchar_t c) \
  158. { \
  159. return detail::name##_type<wchar_t>(std::basic_string<wchar_t>(1, c)); \
  160. }
  161. #else // defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
  162. #define STD_TUPLE_DEFINE_MANIPULATOR_FUNCTIONS(name) \
  163. template <typename Char, typename Traits> \
  164. inline detail::name##_type<Char, Traits> \
  165. name(const std::basic_string<Char, Traits>& s) \
  166. { \
  167. return detail::name##_type<Char, Traits>(s); \
  168. } \
  169. \
  170. template <typename Char> \
  171. inline detail::name##_type<Char> \
  172. name(Char s[]) \
  173. { \
  174. return detail::name##_type<Char>(std::basic_string<Char>(s)); \
  175. } \
  176. \
  177. template <typename Char> \
  178. inline detail::name##_type<Char> \
  179. name(Char const s[]) \
  180. { \
  181. return detail::name##_type<Char>(std::basic_string<Char>(s)); \
  182. } \
  183. \
  184. template <typename Char> \
  185. inline detail::name##_type<Char> \
  186. name(Char c) \
  187. { \
  188. return detail::name##_type<Char>(std::basic_string<Char>(1, c)); \
  189. }
  190. #endif
  191. #define STD_TUPLE_DEFINE_MANIPULATOR(name) \
  192. namespace detail \
  193. { \
  194. struct name##_tag; \
  195. \
  196. template <typename Char, typename Traits = std::char_traits<Char> > \
  197. struct name##_type \
  198. { \
  199. typedef std::basic_string<Char, Traits> string_type; \
  200. string_type data; \
  201. name##_type(const string_type& d): data(d) {} \
  202. }; \
  203. \
  204. template <typename Stream, typename Char, typename Traits> \
  205. Stream& operator>>(Stream& s, const name##_type<Char,Traits>& m) \
  206. { \
  207. string_ios_manip<name##_tag, Stream> manip(s); \
  208. manip.set(m.data); \
  209. return s; \
  210. } \
  211. \
  212. template <typename Stream, typename Char, typename Traits> \
  213. Stream& operator<<(Stream& s, const name##_type<Char,Traits>& m) \
  214. { \
  215. string_ios_manip<name##_tag, Stream> manip(s); \
  216. manip.set(m.data); \
  217. return s; \
  218. } \
  219. } \
  220. STD_TUPLE_DEFINE_MANIPULATOR(tuple_open)
  221. STD_TUPLE_DEFINE_MANIPULATOR(tuple_close)
  222. STD_TUPLE_DEFINE_MANIPULATOR(tuple_delimiter)
  223. STD_TUPLE_DEFINE_MANIPULATOR_FUNCTIONS(tuple_open)
  224. STD_TUPLE_DEFINE_MANIPULATOR_FUNCTIONS(tuple_close)
  225. STD_TUPLE_DEFINE_MANIPULATOR_FUNCTIONS(tuple_delimiter)
  226. #undef STD_TUPLE_DEFINE_MANIPULATOR
  227. #undef STD_TUPLE_DEFINE_MANIPULATOR_FUNCTIONS
  228. #undef FUSION_STRING_OF_STREAM
  229. #undef FUSION_GET_CHAR_TYPE
  230. #undef FUSION_GET_TRAITS_TYPE
  231. }}
  232. #endif