manip.hpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  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(int xalloc())
  33. {
  34. // each Tag will have a unique index
  35. static int const index = 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>(stream.xalloc)) = ar.data.back();
  60. }
  61. static T const* get(Stream& stream)
  62. {
  63. return (T const*)stream.pword(get_xalloc_index<Tag>(stream.xalloc));
  64. }
  65. };
  66. #ifdef _MSC_VER
  67. # pragma warning(push)
  68. # pragma warning(disable: 4512) // assignment operator could not be generated.
  69. #endif
  70. template <typename Tag, typename Stream>
  71. class string_ios_manip
  72. {
  73. public:
  74. typedef FUSION_STRING_OF_STREAM(Stream) string_type;
  75. typedef stream_data<Stream, Tag, string_type> stream_data_t;
  76. string_ios_manip(Stream& str_)
  77. : stream(str_)
  78. {}
  79. void
  80. set(string_type const& s)
  81. {
  82. stream_data_t::attach(stream, s);
  83. }
  84. void
  85. print(char const* default_) const
  86. {
  87. // print a delimiter
  88. string_type const* p = stream_data_t::get(stream);
  89. if (p)
  90. stream << *p;
  91. else
  92. stream << default_;
  93. }
  94. void
  95. read(char const* default_) const
  96. {
  97. // read a delimiter
  98. string_type const* p = stream_data_t::get(stream);
  99. if (p)
  100. {
  101. typedef typename string_type::const_iterator iterator;
  102. for (iterator i = p->begin(); i != p->end(); ++i)
  103. check_delim(*i);
  104. }
  105. else
  106. {
  107. while (*default_)
  108. check_delim(*default_++);
  109. }
  110. }
  111. private:
  112. template <typename Char>
  113. void
  114. check_delim(Char c) const
  115. {
  116. using namespace std;
  117. if (!isspace(c))
  118. {
  119. if (stream.get() != c)
  120. {
  121. stream.unget();
  122. stream.setstate(Stream::failbit);
  123. }
  124. }
  125. }
  126. Stream& stream;
  127. };
  128. #ifdef _MSC_VER
  129. # pragma warning(pop)
  130. #endif
  131. } // detail
  132. #if defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
  133. #define STD_TUPLE_DEFINE_MANIPULATOR_FUNCTIONS(name) \
  134. template <typename Char, typename Traits> \
  135. inline detail::name##_type<Char, Traits> \
  136. name(const std::basic_string<Char, Traits>& s) \
  137. { \
  138. return detail::name##_type<Char, Traits>(s); \
  139. } \
  140. \
  141. inline detail::name##_type<char> \
  142. name(char const* s) \
  143. { \
  144. return detail::name##_type<char>(std::basic_string<char>(s)); \
  145. } \
  146. \
  147. inline detail::name##_type<wchar_t> \
  148. name(wchar_t const* s) \
  149. { \
  150. return detail::name##_type<wchar_t>(std::basic_string<wchar_t>(s)); \
  151. } \
  152. \
  153. inline detail::name##_type<char> \
  154. name(char c) \
  155. { \
  156. return detail::name##_type<char>(std::basic_string<char>(1, c)); \
  157. } \
  158. \
  159. inline detail::name##_type<wchar_t> \
  160. name(wchar_t c) \
  161. { \
  162. return detail::name##_type<wchar_t>(std::basic_string<wchar_t>(1, c)); \
  163. }
  164. #else // defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
  165. #define STD_TUPLE_DEFINE_MANIPULATOR_FUNCTIONS(name) \
  166. template <typename Char, typename Traits> \
  167. inline detail::name##_type<Char, Traits> \
  168. name(const std::basic_string<Char, Traits>& s) \
  169. { \
  170. return detail::name##_type<Char, Traits>(s); \
  171. } \
  172. \
  173. template <typename Char> \
  174. inline detail::name##_type<Char> \
  175. name(Char s[]) \
  176. { \
  177. return detail::name##_type<Char>(std::basic_string<Char>(s)); \
  178. } \
  179. \
  180. template <typename Char> \
  181. inline detail::name##_type<Char> \
  182. name(Char const s[]) \
  183. { \
  184. return detail::name##_type<Char>(std::basic_string<Char>(s)); \
  185. } \
  186. \
  187. template <typename Char> \
  188. inline detail::name##_type<Char> \
  189. name(Char c) \
  190. { \
  191. return detail::name##_type<Char>(std::basic_string<Char>(1, c)); \
  192. }
  193. #endif
  194. #define STD_TUPLE_DEFINE_MANIPULATOR(name) \
  195. namespace detail \
  196. { \
  197. struct name##_tag; \
  198. \
  199. template <typename Char, typename Traits = std::char_traits<Char> > \
  200. struct name##_type \
  201. { \
  202. typedef std::basic_string<Char, Traits> string_type; \
  203. string_type data; \
  204. name##_type(const string_type& d): data(d) {} \
  205. }; \
  206. \
  207. template <typename Stream, typename Char, typename Traits> \
  208. Stream& operator>>(Stream& s, const name##_type<Char,Traits>& m) \
  209. { \
  210. string_ios_manip<name##_tag, Stream> manip(s); \
  211. manip.set(m.data); \
  212. return s; \
  213. } \
  214. \
  215. template <typename Stream, typename Char, typename Traits> \
  216. Stream& operator<<(Stream& s, const name##_type<Char,Traits>& m) \
  217. { \
  218. string_ios_manip<name##_tag, Stream> manip(s); \
  219. manip.set(m.data); \
  220. return s; \
  221. } \
  222. } \
  223. STD_TUPLE_DEFINE_MANIPULATOR(tuple_open)
  224. STD_TUPLE_DEFINE_MANIPULATOR(tuple_close)
  225. STD_TUPLE_DEFINE_MANIPULATOR(tuple_delimiter)
  226. STD_TUPLE_DEFINE_MANIPULATOR_FUNCTIONS(tuple_open)
  227. STD_TUPLE_DEFINE_MANIPULATOR_FUNCTIONS(tuple_close)
  228. STD_TUPLE_DEFINE_MANIPULATOR_FUNCTIONS(tuple_delimiter)
  229. #undef STD_TUPLE_DEFINE_MANIPULATOR
  230. #undef STD_TUPLE_DEFINE_MANIPULATOR_FUNCTIONS
  231. #undef FUSION_STRING_OF_STREAM
  232. #undef FUSION_GET_CHAR_TYPE
  233. #undef FUSION_GET_TRAITS_TYPE
  234. }}
  235. #endif