1 // tuple_io.hpp --------------------------------------------------------------
3 // Copyright (C) 2001 Jaakko Järvi (jaakko.jarvi@cs.utu.fi)
4 // 2001 Gary Powell (gary.powell@sierra.com)
6 // Permission to copy, use, sell and distribute this software is granted
7 // provided this copyright notice appears in all copies.
8 // Permission to modify the code and to distribute modified code is granted
9 // provided this copyright notice appears in all copies, and a notice
10 // that the code was modified is included with the copyright notice.
12 // This software is provided "as is" without express or implied warranty,
13 // and with no claim as to its suitability for any purpose.
14 // For more information, see http://www.boost.org
16 // ----------------------------------------------------------------------------
18 #ifndef BOOST_TUPLE_IO_HPP
19 #define BOOST_TUPLE_IO_HPP
22 // add to boost/config.hpp
25 # if (__GNUC__ == 2 && __GNUC_MINOR__ <= 97)
26 #define BOOST_NO_TEMPLATED_STREAMS
30 #if defined BOOST_NO_TEMPLATED_STREAMS
37 #include "boost/tuple/tuple.hpp"
47 enum manipulator_type { open, close, delimiter };
48 BOOST_STATIC_CONSTANT(int, number_of_manipulators = delimiter + 1);
51 static int get_stream_index (int m)
53 static const int stream_index[number_of_manipulators]
54 = { std::ios::xalloc(), std::ios::xalloc(), std::ios::xalloc() };
56 return stream_index[m];
59 format_info(const format_info&);
65 #if defined (BOOST_NO_TEMPLATED_STREAMS)
66 static char get_manipulator(std::ios& i, manipulator_type m) {
67 char c = static_cast<char>(i.iword(get_stream_index(m)));
69 // parentheses and space are the default manipulators
72 case open : c = '('; break;
73 case close : c = ')'; break;
74 case delimiter : c = ' '; break;
80 static void set_manipulator(std::ios& i, manipulator_type m, char c) {
81 i.iword(get_stream_index(m)) = static_cast<long>(c);
84 template<class CharType, class CharTrait>
85 static CharType get_manipulator(std::basic_ios<CharType, CharTrait>& i,
87 // The manipulators are stored as long.
88 // A valid instanitation of basic_stream allows CharType to be any POD,
89 // hence, the static_cast may fail (it fails if long is not convertible
91 CharType c = static_cast<CharType>(i.iword(get_stream_index(m)) );
92 // parentheses and space are the default manipulators
95 case open : c = i.widen('('); break;
96 case close : c = i.widen(')'); break;
97 case delimiter : c = i.widen(' '); break;
104 template<class CharType, class CharTrait>
105 static void set_manipulator(std::basic_ios<CharType, CharTrait>& i,
106 manipulator_type m, CharType c) {
107 // The manipulators are stored as long.
108 // A valid instanitation of basic_stream allows CharType to be any POD,
109 // hence, the static_cast may fail (it fails if CharType is not
111 i.iword(get_stream_index(m)) = static_cast<long>(c);
113 #endif // BOOST_NO_TEMPLATED_STREAMS
116 } // end of namespace detail
118 template<class CharType>
119 class tuple_manipulator {
120 const detail::format_info::manipulator_type mt;
123 explicit tuple_manipulator(detail::format_info::manipulator_type m,
127 #if defined (BOOST_NO_TEMPLATED_STREAMS)
128 void set(std::ios &io) const {
129 detail::format_info::set_manipulator(io, mt, f_c);
132 #if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
133 template<class CharType2, class CharTrait>
134 void set(std::basic_ios<CharType2, CharTrait> &io) const {
135 detail::format_info::set_manipulator(io, mt, f_c);
138 template<class CharTrait>
139 void set(std::basic_ios<CharType, CharTrait> &io) const {
140 detail::format_info::set_manipulator(io, mt, f_c);
142 #endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
143 #endif // BOOST_NO_TEMPLATED_STREAMS
146 #if defined (BOOST_NO_TEMPLATED_STREAMS)
148 operator<<(std::ostream& o, const tuple_manipulator<char>& m) {
154 operator>>(std::istream& i, const tuple_manipulator<char>& m) {
161 template<class CharType, class CharTrait>
162 inline std::basic_ostream<CharType, CharTrait>&
163 operator<<(std::basic_ostream<CharType, CharTrait>& o, const tuple_manipulator<CharType>& m) {
168 template<class CharType, class CharTrait>
169 inline std::basic_istream<CharType, CharTrait>&
170 operator>>(std::basic_istream<CharType, CharTrait>& i, const tuple_manipulator<CharType>& m) {
175 #endif // BOOST_NO_TEMPLATED_STREAMS
177 template<class CharType>
178 inline tuple_manipulator<CharType> set_open(const CharType c) {
179 return tuple_manipulator<CharType>(detail::format_info::open, c);
182 template<class CharType>
183 inline tuple_manipulator<CharType> set_close(const CharType c) {
184 return tuple_manipulator<CharType>(detail::format_info::close, c);
187 template<class CharType>
188 inline tuple_manipulator<CharType> set_delimiter(const CharType c) {
189 return tuple_manipulator<CharType>(detail::format_info::delimiter, c);
196 // -------------------------------------------------------------
197 // printing tuples to ostream in format (a b c)
198 // parentheses and space are defaults, but can be overriden with manipulators
199 // set_open, set_close and set_delimiter
203 // Note: The order of the print functions is critical
204 // to let a conforming compiler find and select the correct one.
206 #if defined (BOOST_NO_TEMPLATED_STREAMS)
208 #if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
210 inline std::ostream& print(std::ostream& o, const cons<T1, null_type>& t) {
213 #endif // BOOST_NO_TEMPLATED_STREAMS
215 inline std::ostream& print(std::ostream& o, const null_type&) { return o; }
217 template<class T1, class T2>
219 print(std::ostream& o, const cons<T1, T2>& t) {
221 const char d = format_info::get_manipulator(o, format_info::delimiter);
225 #if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
226 if (tuples::length<T2>::value == 0)
228 #endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
231 return print(o, t.tail );
239 #if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
240 template<class CharType, class CharTrait, class T1>
241 inline std::basic_ostream<CharType, CharTrait>&
242 print(std::basic_ostream<CharType, CharTrait>& o, const cons<T1, null_type>& t) {
245 #endif // !BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
248 template<class CharType, class CharTrait>
249 inline std::basic_ostream<CharType, CharTrait>&
250 print(std::basic_ostream<CharType, CharTrait>& o, const null_type&) {
254 template<class CharType, class CharTrait, class T1, class T2>
255 inline std::basic_ostream<CharType, CharTrait>&
256 print(std::basic_ostream<CharType, CharTrait>& o, const cons<T1, T2>& t) {
258 const CharType d = format_info::get_manipulator(o, format_info::delimiter);
262 #if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
263 if (tuples::length<T2>::value == 0)
265 #endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
268 return print(o, t.tail);
271 #endif // BOOST_NO_TEMPLATED_STREAMS
273 } // namespace detail
275 #if defined (BOOST_NO_TEMPLATED_STREAMS)
276 template<class T1, class T2>
277 inline std::ostream& operator<<(std::ostream& o, const cons<T1, T2>& t) {
278 if (!o.good() ) return o;
281 detail::format_info::get_manipulator(o, detail::format_info::open);
283 detail::format_info::get_manipulator(o, detail::format_info::close);
296 template<class CharType, class CharTrait, class T1, class T2>
297 inline std::basic_ostream<CharType, CharTrait>&
298 operator<<(std::basic_ostream<CharType, CharTrait>& o,
299 const cons<T1, T2>& t) {
300 if (!o.good() ) return o;
303 detail::format_info::get_manipulator(o, detail::format_info::open);
305 detail::format_info::get_manipulator(o, detail::format_info::close);
315 #endif // BOOST_NO_TEMPLATED_STREAMS
318 // -------------------------------------------------------------
319 // input stream operators
323 #if defined (BOOST_NO_TEMPLATED_STREAMS)
326 extract_and_check_delimiter(
327 std::istream& is, format_info::manipulator_type del)
329 const char d = format_info::get_manipulator(is, del);
331 const bool is_delimiter = (!isspace(d) );
337 is.setstate(std::ios::failbit);
344 // Note: The order of the read functions is critical to let a
345 // (conforming?) compiler find and select the correct one.
347 #if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
349 inline std::istream &
350 read (std::istream &is, cons<T1, null_type>& t1) {
352 if (!is.good()) return is;
354 return is >> t1.head ;
357 inline std::istream& read(std::istream& i, const null_type&) { return i; }
358 #endif // !BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
360 template<class T1, class T2>
362 read(std::istream &is, cons<T1, T2>& t1) {
364 if (!is.good()) return is;
368 #if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
369 if (tuples::length<T2>::value == 0)
371 #endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
373 extract_and_check_delimiter(is, format_info::delimiter);
375 return read(is, t1.tail);
378 } // end namespace detail
381 operator>>(std::istream &is, null_type&) {
383 if (!is.good() ) return is;
385 detail::extract_and_check_delimiter(is, detail::format_info::open);
386 detail::extract_and_check_delimiter(is, detail::format_info::close);
392 template<class T1, class T2>
394 operator>>(std::istream& is, cons<T1, T2>& t1) {
396 if (!is.good() ) return is;
398 detail::extract_and_check_delimiter(is, detail::format_info::open);
400 detail::read(is, t1);
402 detail::extract_and_check_delimiter(is, detail::format_info::close);
411 template<class CharType, class CharTrait>
412 inline std::basic_istream<CharType, CharTrait>&
413 extract_and_check_delimiter(
414 std::basic_istream<CharType, CharTrait> &is, format_info::manipulator_type del)
416 const CharType d = format_info::get_manipulator(is, del);
418 const bool is_delimiter = (!isspace(d) );
424 is.setstate(std::ios::failbit);
431 #if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
432 template<class CharType, class CharTrait, class T1>
433 inline std::basic_istream<CharType, CharTrait> &
434 read (std::basic_istream<CharType, CharTrait> &is, cons<T1, null_type>& t1) {
436 if (!is.good()) return is;
438 return is >> t1.head;
441 template<class CharType, class CharTrait>
442 inline std::basic_istream<CharType, CharTrait>&
443 read(std::basic_istream<CharType, CharTrait>& i, const null_type&) { return i; }
445 #endif // !BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
447 template<class CharType, class CharTrait, class T1, class T2>
448 inline std::basic_istream<CharType, CharTrait>&
449 read(std::basic_istream<CharType, CharTrait> &is, cons<T1, T2>& t1) {
451 if (!is.good()) return is;
455 #if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
456 if (tuples::length<T2>::value == 0)
458 #endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
460 extract_and_check_delimiter(is, format_info::delimiter);
462 return read(is, t1.tail);
465 } // end namespace detail
468 template<class CharType, class CharTrait>
469 inline std::basic_istream<CharType, CharTrait>&
470 operator>>(std::basic_istream<CharType, CharTrait> &is, null_type&) {
472 if (!is.good() ) return is;
474 detail::extract_and_check_delimiter(is, detail::format_info::open);
475 detail::extract_and_check_delimiter(is, detail::format_info::close);
480 template<class CharType, class CharTrait, class T1, class T2>
481 inline std::basic_istream<CharType, CharTrait>&
482 operator>>(std::basic_istream<CharType, CharTrait>& is, cons<T1, T2>& t1) {
484 if (!is.good() ) return is;
486 detail::extract_and_check_delimiter(is, detail::format_info::open);
488 detail::read(is, t1);
490 detail::extract_and_check_delimiter(is, detail::format_info::close);
495 #endif // BOOST_NO_TEMPLATED_STREAMS
497 } // end of namespace tuples
498 } // end of namespace boost
500 #endif // BOOST_TUPLE_IO_HPP