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"
48 enum manipulator_type { open, close, delimiter };
49 BOOST_STATIC_CONSTANT(int, number_of_manipulators = delimiter + 1);
52 static const int stream_index[number_of_manipulators];
53 format_info(const format_info&);
59 #if defined (BOOST_NO_TEMPLATED_STREAMS)
60 static char get_manipulator(std::ios& i, manipulator_type m) {
61 char c = static_cast<char>(i.iword(stream_index[m]));
63 // parentheses and space are the default manipulators
66 case open : c = '('; break;
67 case close : c = ')'; break;
68 case delimiter : c = ' '; break;
74 static void set_manipulator(std::ios& i, manipulator_type m, char c) {
75 i.iword(stream_index[m]) = static_cast<long>(c);
78 template<class CharType, class CharTrait>
79 static CharType get_manipulator(std::basic_ios<CharType, CharTrait>& i,
81 // The manipulators are stored as long.
82 // A valid instanitation of basic_stream allows CharType to be any POD,
83 // hence, the static_cast may fail (it fails if long is not convertible
85 CharType c = static_cast<CharType>(i.iword(stream_index[m]) );
86 // parentheses and space are the default manipulators
89 case open : c = i.widen('('); break;
90 case close : c = i.widen(')'); break;
91 case delimiter : c = i.widen(' '); break;
98 template<class CharType, class CharTrait>
99 static void set_manipulator(std::basic_ios<CharType, CharTrait>& i,
100 manipulator_type m, CharType c) {
101 // The manipulators are stored as long.
102 // A valid instanitation of basic_stream allows CharType to be any POD,
103 // hence, the static_cast may fail (it fails if CharType is not
105 i.iword(stream_index[m]) = static_cast<long>(c);
107 #endif // BOOST_NO_TEMPLATED_STREAMS
110 template<class CharType>
111 class tuple_manipulator {
112 const format_info::manipulator_type mt;
115 explicit tuple_manipulator(format_info::manipulator_type m, const char c = 0)
118 #if defined (BOOST_NO_TEMPLATED_STREAMS)
119 void set(std::ios &io) const {
120 format_info::set_manipulator(io, mt, f_c);
123 #if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
124 template<class CharType2, class CharTrait>
125 void set(std::basic_ios<CharType2, CharTrait> &io) const {
126 format_info::set_manipulator(io, mt, f_c);
129 template<class CharTrait>
130 void set(std::basic_ios<CharType, CharTrait> &io) const {
131 format_info::set_manipulator(io, mt, f_c);
133 #endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
134 #endif // BOOST_NO_TEMPLATED_STREAMS
137 } // end of namespace tuples
138 } // end of namespace detail
141 #if defined (BOOST_NO_TEMPLATED_STREAMS)
143 operator<<(std::ostream& o, const detail::tuples::tuple_manipulator<char>& m) {
149 operator>>(std::istream& i, const detail::tuples::tuple_manipulator<char>& m) {
156 template<class CharType, class CharTrait>
157 inline std::basic_ostream<CharType, CharTrait>&
158 operator<<(std::basic_ostream<CharType, CharTrait>& o, const detail::tuples::tuple_manipulator<CharType>& m) {
163 template<class CharType, class CharTrait>
164 inline std::basic_istream<CharType, CharTrait>&
165 operator>>(std::basic_istream<CharType, CharTrait>& i, const detail::tuples::tuple_manipulator<CharType>& m) {
170 #endif // BOOST_NO_TEMPLATED_STREAMS
172 template<class CharType>
173 inline detail::tuples::tuple_manipulator<CharType> set_open(const CharType c) {
174 return detail::tuples::tuple_manipulator<CharType>(detail::tuples::format_info::open, c);
177 template<class CharType>
178 inline detail::tuples::tuple_manipulator<CharType> set_close(const CharType c) {
179 return detail::tuples::tuple_manipulator<CharType>(detail::tuples::format_info::close, c);
182 template<class CharType>
183 inline detail::tuples::tuple_manipulator<CharType> set_delimiter(const CharType c) {
184 return detail::tuples::tuple_manipulator<CharType>(detail::tuples::format_info::delimiter, c);
191 // -------------------------------------------------------------
192 // printing tuples to ostream in format (a b c)
193 // parentheses and space are defaults, but can be overriden with manipulators
194 // set_open, set_close and set_delimiter
199 // Note: The order of the print functions is critical
200 // to let a conforming compiler find and select the correct one.
202 #if defined (BOOST_NO_TEMPLATED_STREAMS)
204 #if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
206 inline std::ostream& print(std::ostream& o, const cons<T1, null_type>& t) {
209 #endif // BOOST_NO_TEMPLATED_STREAMS
211 inline std::ostream& print(std::ostream& o, const null_type&) { return o; }
213 template<class T1, class T2>
215 print(std::ostream& o, const cons<T1, T2>& t) {
217 const char d = format_info::get_manipulator(o, format_info::delimiter);
221 #if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
222 if (tuple_length<T2>::value == 0)
224 #endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
227 return print(o, t.tail );
235 #if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
236 template<class CharType, class CharTrait, class T1>
237 inline std::basic_ostream<CharType, CharTrait>&
238 print(std::basic_ostream<CharType, CharTrait>& o, const cons<T1, null_type>& t) {
241 #endif // !BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
244 template<class CharType, class CharTrait>
245 inline std::basic_ostream<CharType, CharTrait>&
246 print(std::basic_ostream<CharType, CharTrait>& o, const null_type&) {
250 template<class CharType, class CharTrait, class T1, class T2>
251 inline std::basic_ostream<CharType, CharTrait>&
252 print(std::basic_ostream<CharType, CharTrait>& o, const cons<T1, T2>& t) {
254 const CharType d = format_info::get_manipulator(o, format_info::delimiter);
258 #if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
259 if (tuple_length<T2>::value == 0)
261 #endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
264 return print(o, t.tail);
267 #endif // BOOST_NO_TEMPLATED_STREAMS
269 } // namespace tuples
270 } // namespace detail
272 #if defined (BOOST_NO_TEMPLATED_STREAMS)
273 template<class T1, class T2>
274 inline std::ostream& operator<<(std::ostream& o, const cons<T1, T2>& t) {
275 if (!o.good() ) return o;
278 detail::tuples::format_info::get_manipulator(o, detail::tuples::format_info::open);
280 detail::tuples::format_info::get_manipulator(o, detail::tuples::format_info::close);
284 detail::tuples::print(o, t);
293 template<class CharType, class CharTrait, class T1, class T2>
294 inline std::basic_ostream<CharType, CharTrait>&
295 operator<<(std::basic_ostream<CharType, CharTrait>& o,
296 const cons<T1, T2>& t) {
297 if (!o.good() ) return o;
300 detail::tuples::format_info::get_manipulator(o, detail::tuples::format_info::open);
302 detail::tuples::format_info::get_manipulator(o, detail::tuples::format_info::close);
306 detail::tuples::print(o, t);
312 #endif // BOOST_NO_TEMPLATED_STREAMS
315 // -------------------------------------------------------------
316 // input stream operators
321 #if defined (BOOST_NO_TEMPLATED_STREAMS)
324 extract_and_check_delimiter(
325 std::istream& is, format_info::manipulator_type del)
327 const char d = format_info::get_manipulator(is, del);
329 const bool is_delimiter = (!isspace(d) );
335 is.setstate(std::ios::failbit);
342 // Note: The order of the read functions is critical to let a
343 // (conforming?) compiler find and select the correct one.
345 #if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
347 inline std::istream &
348 read (std::istream &is, cons<T1, null_type>& t1) {
350 if (!is.good()) return is;
352 return is >> t1.head ;
355 inline std::istream& read(std::istream& i, const null_type&) { return i; }
356 #endif // !BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
358 template<class T1, class T2>
360 read(std::istream &is, cons<T1, T2>& t1) {
362 if (!is.good()) return is;
366 #if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
367 if (tuple_length<T2>::value == 0)
369 #endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
371 extract_and_check_delimiter(is, format_info::delimiter);
373 return read(is, t1.tail);
376 } // end namespace tuples
377 } // end namespace detail
380 operator>>(std::istream &is, null_type&) {
382 if (!is.good() ) return is;
384 detail::tuples::extract_and_check_delimiter(is, detail::tuples::format_info::open);
385 detail::tuples::extract_and_check_delimiter(is, detail::tuples::format_info::close);
391 template<class T1, class T2>
393 operator>>(std::istream& is, cons<T1, T2>& t1) {
395 if (!is.good() ) return is;
397 detail::tuples::extract_and_check_delimiter(is, detail::tuples::format_info::open);
399 detail::tuples::read(is, t1);
401 detail::tuples::extract_and_check_delimiter(is, detail::tuples::format_info::close);
410 template<class CharType, class CharTrait>
411 inline std::basic_istream<CharType, CharTrait>&
412 extract_and_check_delimiter(
413 std::basic_istream<CharType, CharTrait> &is, format_info::manipulator_type del)
415 const CharType d = format_info::get_manipulator(is, del);
417 const bool is_delimiter = (!isspace(d) );
423 is.setstate(std::ios::failbit);
430 #if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
431 template<class CharType, class CharTrait, class T1>
432 inline std::basic_istream<CharType, CharTrait> &
433 read (std::basic_istream<CharType, CharTrait> &is, cons<T1, null_type>& t1) {
435 if (!is.good()) return is;
437 return is >> t1.head;
440 template<class CharType, class CharTrait>
441 inline std::basic_istream<CharType, CharTrait>&
442 read(std::basic_istream<CharType, CharTrait>& i, const null_type&) { return i; }
444 #endif // !BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
446 template<class CharType, class CharTrait, class T1, class T2>
447 inline std::basic_istream<CharType, CharTrait>&
448 read(std::basic_istream<CharType, CharTrait> &is, cons<T1, T2>& t1) {
450 if (!is.good()) return is;
454 #if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
455 if (tuple_length<T2>::value == 0)
457 #endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
459 extract_and_check_delimiter(is, format_info::delimiter);
461 return read(is, t1.tail);
464 } // end namespace tuples
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::tuples::extract_and_check_delimiter(is, detail::tuples::format_info::open);
475 detail::tuples::extract_and_check_delimiter(is, detail::tuples::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::tuples::extract_and_check_delimiter(is, detail::tuples::format_info::open);
488 detail::tuples::read(is, t1);
490 detail::tuples::extract_and_check_delimiter(is, detail::tuples::format_info::close);
495 #endif // BOOST_NO_TEMPLATED_STREAMS
497 } // end of namespace boost
499 #endif // BOOST_TUPLE_IO_HPP