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