]> git.lyx.org Git - lyx.git/blob - boost/boost/tuple/tuple_io.hpp
major boost update
[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 namespace boost {
40 namespace tuples {
41
42 namespace detail {
43
44 class format_info {
45 public:   
46
47    enum manipulator_type { open, close, delimiter };
48    BOOST_STATIC_CONSTANT(int, number_of_manipulators = delimiter + 1);
49 private:
50    
51    static int get_stream_index (int m)
52    {
53      static const int stream_index[number_of_manipulators]
54         = { std::ios::xalloc(), std::ios::xalloc(), std::ios::xalloc() };
55
56      return stream_index[m];
57    }
58
59    format_info(const format_info&);
60    format_info();   
61
62
63 public:
64
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))); 
68      
69      // parentheses and space are the default manipulators
70      if (!c) {
71        switch(m) {
72          case open : c = '('; break;
73          case close : c = ')'; break;
74          case delimiter : c = ' '; break;
75        }
76      }
77      return c;
78    }
79
80    static void set_manipulator(std::ios& i, manipulator_type m, char c) {
81       i.iword(get_stream_index(m)) = static_cast<long>(c);
82    }
83 #else
84    template<class CharType, class CharTrait>
85    static CharType get_manipulator(std::basic_ios<CharType, CharTrait>& i, 
86                                    manipulator_type m) {
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 
90      // to CharType
91      CharType c = static_cast<CharType>(i.iword(get_stream_index(m)) ); 
92      // parentheses and space are the default manipulators
93      if (!c) {
94        switch(m) {
95          case open :  c = i.widen('('); break;
96          case close : c = i.widen(')'); break;
97          case delimiter : c = i.widen(' '); break;
98        }
99      }
100      return c;
101    }
102
103
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 
110      // convertible long.
111       i.iword(get_stream_index(m)) = static_cast<long>(c);
112    }
113 #endif // BOOST_NO_TEMPLATED_STREAMS
114 };
115
116 } // end of namespace detail
117  
118 template<class CharType>    
119 class tuple_manipulator {
120   const detail::format_info::manipulator_type mt;
121   CharType f_c;
122 public:
123   explicit tuple_manipulator(detail::format_info::manipulator_type m, 
124                              const char c = 0)
125      : mt(m), f_c(c) {}
126   
127 #if defined (BOOST_NO_TEMPLATED_STREAMS)
128   void set(std::ios &io) const {
129      detail::format_info::set_manipulator(io, mt, f_c);
130   }
131 #else
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);
136   }
137 #else
138    template<class CharTrait>
139   void set(std::basic_ios<CharType, CharTrait> &io) const {
140      detail::format_info::set_manipulator(io, mt, f_c);
141   }
142 #endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
143 #endif // BOOST_NO_TEMPLATED_STREAMS
144 };
145
146 #if defined (BOOST_NO_TEMPLATED_STREAMS)
147 inline std::ostream&
148 operator<<(std::ostream& o, const tuple_manipulator<char>& m) {
149   m.set(o);
150   return o;
151 }
152
153 inline std::istream&
154 operator>>(std::istream& i, const tuple_manipulator<char>& m) {
155   m.set(i);
156   return i;
157 }
158
159 #else
160
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) {
164   m.set(o);
165   return o;
166 }
167
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) {
171   m.set(i);
172   return i;
173 }
174
175 #endif   // BOOST_NO_TEMPLATED_STREAMS
176    
177 template<class CharType>
178 inline tuple_manipulator<CharType> set_open(const CharType c) {
179    return tuple_manipulator<CharType>(detail::format_info::open, c);
180 }
181
182 template<class CharType>
183 inline tuple_manipulator<CharType> set_close(const CharType c) {
184    return tuple_manipulator<CharType>(detail::format_info::close, c);
185 }
186
187 template<class CharType>
188 inline tuple_manipulator<CharType> set_delimiter(const CharType c) {
189    return tuple_manipulator<CharType>(detail::format_info::delimiter, c);
190 }
191
192
193
194    
195    
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
200    
201 namespace detail {
202
203 // Note: The order of the print functions is critical 
204 // to let a conforming compiler  find and select the correct one.
205
206 #if defined (BOOST_NO_TEMPLATED_STREAMS)
207
208 #if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
209 template<class T1>
210 inline std::ostream& print(std::ostream& o, const cons<T1, null_type>& t) {
211   return o << t.head;
212 }
213 #endif // BOOST_NO_TEMPLATED_STREAMS
214  
215 inline std::ostream& print(std::ostream& o, const null_type&) { return o; }
216
217 template<class T1, class T2>
218 inline std::ostream& 
219 print(std::ostream& o, const cons<T1, T2>& t) {
220   
221   const char d = format_info::get_manipulator(o, format_info::delimiter);
222    
223   o << t.head;
224
225 #if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
226   if (tuples::length<T2>::value == 0)
227     return o;
228 #endif  // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
229   o << d;
230   
231   return print(o, t.tail );
232
233 }
234
235
236
237 #else
238
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) {
243   return o << t.head;
244 }
245 #endif  // !BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
246
247  
248 template<class CharType, class CharTrait>
249 inline std::basic_ostream<CharType, CharTrait>& 
250 print(std::basic_ostream<CharType, CharTrait>& o, const null_type&) { 
251   return o; 
252 }
253
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) {
257   
258   const CharType d = format_info::get_manipulator(o, format_info::delimiter);
259    
260   o << t.head;
261
262 #if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
263   if (tuples::length<T2>::value == 0)
264     return o;
265 #endif  // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
266   o << d;
267
268   return print(o, t.tail);
269 }
270
271 #endif  // BOOST_NO_TEMPLATED_STREAMS
272
273 } // namespace detail
274
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;
279  
280   const char l = 
281     detail::format_info::get_manipulator(o, detail::format_info::open);
282   const char r = 
283     detail::format_info::get_manipulator(o, detail::format_info::close);
284    
285   o << l;
286   
287   detail::print(o, t);  
288
289   o << r;
290
291   return o;
292 }
293
294 #else
295
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;
301  
302   const CharType l = 
303     detail::format_info::get_manipulator(o, detail::format_info::open);
304   const CharType r = 
305     detail::format_info::get_manipulator(o, detail::format_info::close);
306    
307   o << l;   
308
309   detail::print(o, t);  
310
311   o << r;
312
313   return o;
314 }
315 #endif // BOOST_NO_TEMPLATED_STREAMS
316
317    
318 // -------------------------------------------------------------
319 // input stream operators
320
321 namespace detail {
322
323 #if defined (BOOST_NO_TEMPLATED_STREAMS)
324
325 inline std::istream& 
326 extract_and_check_delimiter(
327   std::istream& is, format_info::manipulator_type del)
328 {
329   const char d = format_info::get_manipulator(is, del);
330
331   const bool is_delimiter = (!isspace(d) );      
332
333   char c;
334   if (is_delimiter) { 
335     is >> c; 
336     if (c!=d) {
337       is.setstate(std::ios::failbit);
338     } 
339   }
340   return is;
341 }
342
343
344 // Note: The order of the read functions is critical to let a 
345 // (conforming?) compiler find and select the correct one.
346
347 #if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
348 template<class T1>
349 inline  std::istream & 
350 read (std::istream &is, cons<T1, null_type>& t1) {
351
352   if (!is.good()) return is;   
353    
354   return is >> t1.head ;
355 }
356 #else
357 inline std::istream& read(std::istream& i, const null_type&) { return i; }
358 #endif // !BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
359    
360 template<class T1, class T2>
361 inline std::istream& 
362 read(std::istream &is, cons<T1, T2>& t1) {
363
364   if (!is.good()) return is;
365    
366   is >> t1.head;
367
368 #if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
369   if (tuples::length<T2>::value == 0)
370     return is;
371 #endif  // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
372
373   extract_and_check_delimiter(is, format_info::delimiter);
374
375   return read(is, t1.tail);
376 }
377
378 } // end namespace detail
379
380 inline std::istream& 
381 operator>>(std::istream &is, null_type&) {
382
383   if (!is.good() ) return is;
384
385   detail::extract_and_check_delimiter(is, detail::format_info::open);
386   detail::extract_and_check_delimiter(is, detail::format_info::close);
387
388   return is;
389 }
390
391
392 template<class T1, class T2>
393 inline std::istream& 
394 operator>>(std::istream& is, cons<T1, T2>& t1) {
395
396   if (!is.good() ) return is;
397
398   detail::extract_and_check_delimiter(is, detail::format_info::open);
399                       
400   detail::read(is, t1);
401    
402   detail::extract_and_check_delimiter(is, detail::format_info::close);
403
404   return is;
405 }
406
407
408
409 #else
410
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)
415 {
416   const CharType d = format_info::get_manipulator(is, del);
417
418   const bool is_delimiter = (!isspace(d) );      
419
420   CharType c;
421   if (is_delimiter) { 
422     is >> c;
423     if (c!=d) { 
424       is.setstate(std::ios::failbit);
425     }
426   }
427   return is;
428 }
429
430    
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) {
435
436   if (!is.good()) return is;   
437    
438   return is >> t1.head; 
439 }
440 #else
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; }
444
445 #endif // !BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
446
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) {
450
451   if (!is.good()) return is;
452    
453   is >> t1.head;
454
455 #if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
456   if (tuples::length<T2>::value == 0)
457     return is;
458 #endif  // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
459
460   extract_and_check_delimiter(is, format_info::delimiter);
461
462   return read(is, t1.tail);
463 }
464
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::extract_and_check_delimiter(is, detail::format_info::open);
475   detail::extract_and_check_delimiter(is, detail::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::extract_and_check_delimiter(is, detail::format_info::open);
487                       
488   detail::read(is, t1);
489    
490   detail::extract_and_check_delimiter(is, detail::format_info::close);
491
492   return is;
493 }
494
495 #endif // BOOST_NO_TEMPLATED_STREAMS
496
497 } // end of namespace tuples
498 } // end of namespace boost
499
500 #endif // BOOST_TUPLE_IO_HPP
501
502