]> git.lyx.org Git - lyx.git/blob - boost/boost/tuple/tuple_io.hpp
update from boost cvs
[lyx.git] / boost / boost / tuple / tuple_io.hpp
1 // tuple_io.hpp --------------------------------------------------------------
2
3 // Copyright (C) 2001 Jaakko Järvi (jaakko.jarvi@cs.utu.fi)
4 //               2001 Gary Powell (gary.powell@sierra.com)
5 //
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.
11 //
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 
15
16 // ----------------------------------------------------------------------------
17
18 #ifndef BOOST_TUPLE_IO_HPP
19 #define BOOST_TUPLE_IO_HPP
20
21
22 // add to boost/config.hpp
23 // for now
24 # if defined __GNUC__
25 #   if (__GNUC__ == 2 && __GNUC_MINOR__ <= 97) 
26 #define BOOST_NO_TEMPLATED_STREAMS
27 #endif
28 #endif  // __GNUC__
29
30 #if defined BOOST_NO_TEMPLATED_STREAMS
31 #include <iostream>
32 #else 
33 #include <istream>
34 #include <ostream>
35 #endif  
36
37 #include "boost/tuple/tuple.hpp"
38
39
40                                     
41 namespace boost {
42
43 namespace detail {
44 namespace tuples {
45
46 class format_info {
47 public:   
48    enum manipulator_type { open, close, delimiter };
49    BOOST_STATIC_CONSTANT(int, number_of_manipulators = delimiter + 1);
50 private:
51    
52    static const int stream_index[number_of_manipulators];
53    format_info(const format_info&);
54    format_info();   
55
56
57 public:
58
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])); 
62      
63      // parentheses and space are the default manipulators
64      if (!c) {
65        switch(m) {
66          case open : c = '('; break;                                        
67          case close : c = ')'; break;                                       
68          case delimiter : c = ' '; break;
69        }
70      }
71      return c;
72    }
73
74    static void set_manipulator(std::ios& i, manipulator_type m, char c) {
75       i.iword(stream_index[m]) = static_cast<long>(c);
76    }
77 #else
78    template<class CharType, class CharTrait>
79    static CharType get_manipulator(std::basic_ios<CharType, CharTrait>& i, 
80                                    manipulator_type m) {
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 
84      // to CharType
85      CharType c = static_cast<CharType>(i.iword(stream_index[m]) ); 
86      // parentheses and space are the default manipulators
87      if (!c) {
88        switch(m) {
89          case open :  c = i.widen('('); break;                                      
90          case close : c = i.widen(')'); break;                                      
91          case delimiter : c = i.widen(' '); break;
92        }
93      }
94      return c;
95    }
96
97
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 
104      // convertible long.
105       i.iword(stream_index[m]) = static_cast<long>(c);
106    }
107 #endif  // BOOST_NO_TEMPLATED_STREAMS
108 };
109  
110 template<class CharType>    
111 class tuple_manipulator {
112   const format_info::manipulator_type mt;
113   CharType f_c;
114 public:
115   explicit tuple_manipulator(format_info::manipulator_type m, const char c = 0)
116      : mt(m), f_c(c) {}
117   
118 #if defined (BOOST_NO_TEMPLATED_STREAMS)
119   void set(std::ios &io) const {
120      format_info::set_manipulator(io, mt, f_c);
121   }
122 #else
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);
127   }
128 #else
129    template<class CharTrait>
130   void set(std::basic_ios<CharType, CharTrait> &io) const {
131      format_info::set_manipulator(io, mt, f_c);
132   }
133 #endif  // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
134 #endif  // BOOST_NO_TEMPLATED_STREAMS
135 };
136
137 } // end of namespace tuples
138 } // end of namespace detail
139    
140
141 #if defined (BOOST_NO_TEMPLATED_STREAMS)
142 inline std::ostream&
143 operator<<(std::ostream& o, const detail::tuples::tuple_manipulator<char>& m) {
144   m.set(o);
145   return o;
146 }
147
148 inline std::istream&
149 operator>>(std::istream& i, const detail::tuples::tuple_manipulator<char>& m) {
150   m.set(i);
151   return i;
152 }
153
154 #else
155
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) {
159   m.set(o);
160   return o;
161 }
162
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) {
166   m.set(i);
167   return i;
168 }
169
170 #endif   // BOOST_NO_TEMPLATED_STREAMS
171    
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);
175 }
176
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);
180 }
181
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);
185 }
186
187
188
189    
190    
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
195    
196 namespace detail {
197 namespace tuples {
198
199 // Note: The order of the print functions is critical 
200 // to let a conforming compiler  find and select the correct one.
201
202 #if defined (BOOST_NO_TEMPLATED_STREAMS)
203
204 #if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
205 template<class T1>
206 inline std::ostream& print(std::ostream& o, const cons<T1, null_type>& t) {
207   return o << t.head;
208 }
209 #endif  // BOOST_NO_TEMPLATED_STREAMS
210  
211 inline std::ostream& print(std::ostream& o, const null_type&) { return o; }
212
213 template<class T1, class T2>
214 inline std::ostream& 
215 print(std::ostream& o, const cons<T1, T2>& t) {
216   
217   const char d = format_info::get_manipulator(o, format_info::delimiter);
218    
219   o << t.head;
220
221 #if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
222   if (tuple_length<T2>::value == 0)
223         return o;
224 #endif  // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
225   o << d;
226   
227   return print(o, t.tail );
228
229 }
230
231
232
233 #else
234
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) {
239   return o << t.head;
240 }
241 #endif  // !BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
242
243  
244 template<class CharType, class CharTrait>
245 inline std::basic_ostream<CharType, CharTrait>& 
246 print(std::basic_ostream<CharType, CharTrait>& o, const null_type&) { 
247   return o; 
248 }
249
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) {
253   
254   const CharType d = format_info::get_manipulator(o, format_info::delimiter);
255    
256   o << t.head;
257
258 #if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
259   if (tuple_length<T2>::value == 0)
260         return o;
261 #endif  // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
262   o << d;
263
264   return print(o, t.tail);
265 }
266
267 #endif  // BOOST_NO_TEMPLATED_STREAMS
268
269 } // namespace tuples
270 } // namespace detail
271
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;
276  
277   const char l = 
278     detail::tuples::format_info::get_manipulator(o, detail::tuples::format_info::open);
279   const char r = 
280     detail::tuples::format_info::get_manipulator(o, detail::tuples::format_info::close);
281    
282   o << l;
283   
284   detail::tuples::print(o, t);  
285
286   o << r;
287
288   return o;
289 }
290
291 #else
292
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;
298  
299   const CharType l = 
300     detail::tuples::format_info::get_manipulator(o, detail::tuples::format_info::open);
301   const CharType r = 
302     detail::tuples::format_info::get_manipulator(o, detail::tuples::format_info::close);
303    
304   o << l;   
305
306   detail::tuples::print(o, t);  
307
308   o << r;
309
310   return o;
311 }
312 #endif  // BOOST_NO_TEMPLATED_STREAMS
313
314    
315 // -------------------------------------------------------------
316 // input stream operators
317
318 namespace detail {
319 namespace tuples {
320
321 #if defined (BOOST_NO_TEMPLATED_STREAMS)
322
323 inline std::istream& 
324 extract_and_check_delimiter(
325   std::istream& is, format_info::manipulator_type del)
326 {
327   const char d = format_info::get_manipulator(is, del);
328
329   const bool is_delimiter = (!isspace(d) );      
330
331   char c;
332   if (is_delimiter) { 
333     is >> c; 
334     if (c!=d) {
335       is.setstate(std::ios::failbit);
336     } 
337   }
338   return is;
339 }
340
341
342 // Note: The order of the read functions is critical to let a 
343 // (conforming?) compiler find and select the correct one.
344
345 #if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
346 template<class T1>
347 inline  std::istream & 
348 read (std::istream &is, cons<T1, null_type>& t1) {
349
350   if (!is.good()) return is;   
351    
352   return is >> t1.head ;
353 }
354 #else
355 inline std::istream& read(std::istream& i, const null_type&) { return i; }
356 #endif  // !BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
357    
358 template<class T1, class T2>
359 inline std::istream& 
360 read(std::istream &is, cons<T1, T2>& t1) {
361
362   if (!is.good()) return is;
363    
364   is >> t1.head;
365
366 #if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
367   if (tuple_length<T2>::value == 0)
368         return is;
369 #endif  // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
370
371   extract_and_check_delimiter(is, format_info::delimiter);
372
373   return read(is, t1.tail);
374 }
375
376 } // end namespace tuples
377 } // end namespace detail
378
379 inline std::istream& 
380 operator>>(std::istream &is, null_type&) {
381
382   if (!is.good() ) return is;
383
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);
386
387   return is;
388 }
389
390
391 template<class T1, class T2>
392 inline std::istream& 
393 operator>>(std::istream& is, cons<T1, T2>& t1) {
394
395   if (!is.good() ) return is;
396
397   detail::tuples::extract_and_check_delimiter(is, detail::tuples::format_info::open);
398                       
399   detail::tuples::read(is, t1);
400    
401   detail::tuples::extract_and_check_delimiter(is, detail::tuples::format_info::close);
402
403   return is;
404 }
405
406
407
408 #else
409
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)
414 {
415   const CharType d = format_info::get_manipulator(is, del);
416
417   const bool is_delimiter = (!isspace(d) );      
418
419   CharType c;
420   if (is_delimiter) { 
421     is >> c;
422     if (c!=d) { 
423       is.setstate(std::ios::failbit);
424     }
425   }
426   return is;
427 }
428
429    
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) {
434
435   if (!is.good()) return is;   
436    
437   return is >> t1.head; 
438 }
439 #else
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; }
443
444 #endif  // !BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
445
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) {
449
450   if (!is.good()) return is;
451    
452   is >> t1.head;
453
454 #if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
455   if (tuple_length<T2>::value == 0)
456         return is;
457 #endif  // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
458
459   extract_and_check_delimiter(is, format_info::delimiter);
460
461   return read(is, t1.tail);
462 }
463
464 } // end namespace tuples
465 } // end namespace detail
466
467
468 template<class CharType, class CharTrait>
469 inline std::basic_istream<CharType, CharTrait>& 
470 operator>>(std::basic_istream<CharType, CharTrait> &is, null_type&) {
471
472   if (!is.good() ) return is;
473
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);
476
477   return is;
478 }
479
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) {
483
484   if (!is.good() ) return is;
485
486   detail::tuples::extract_and_check_delimiter(is, detail::tuples::format_info::open);
487                       
488   detail::tuples::read(is, t1);
489    
490   detail::tuples::extract_and_check_delimiter(is, detail::tuples::format_info::close);
491
492   return is;
493 }
494
495 #endif  // BOOST_NO_TEMPLATED_STREAMS
496
497 } // end of namespace boost
498
499 #endif  // BOOST_TUPLE_IO_HPP
500
501