]> git.lyx.org Git - lyx.git/blob - boost/boost/tuple/tuple_io.hpp
Boost 1.31.0
[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 // This is ugly: one should be using twoargument isspace since whitspace can
40 // be locale dependent, in theory at least.
41 // not all libraries implement have the two-arg version, so we need to 
42 // use the one-arg one, which one should get with <cctype> but there seem
43 // to be exceptions to this.
44
45 #if !defined (BOOST_NO_STD_LOCALE)
46
47 #include <locale> // for two-arg isspace
48
49 #else 
50
51 #include <cctype> // for one-arg (old) isspace 
52 #include <ctype.h> // Metrowerks does not find one-arg isspace from cctype
53
54 #endif
55
56 namespace boost {
57 namespace tuples {
58
59 namespace detail {
60
61 class format_info {
62 public:   
63
64    enum manipulator_type { open, close, delimiter };
65    BOOST_STATIC_CONSTANT(int, number_of_manipulators = delimiter + 1);
66 private:
67    
68    static int get_stream_index (int m)
69    {
70      static const int stream_index[number_of_manipulators]
71         = { std::ios::xalloc(), std::ios::xalloc(), std::ios::xalloc() };
72
73      return stream_index[m];
74    }
75
76    format_info(const format_info&);
77    format_info();   
78
79
80 public:
81
82 #if defined (BOOST_NO_TEMPLATED_STREAMS)
83    static char get_manipulator(std::ios& i, manipulator_type m) {
84      char c = static_cast<char>(i.iword(get_stream_index(m))); 
85      
86      // parentheses and space are the default manipulators
87      if (!c) {
88        switch(m) {
89          case detail::format_info::open : c = '('; break;
90          case detail::format_info::close : c = ')'; break;
91          case detail::format_info::delimiter : c = ' '; break;
92        }
93      }
94      return c;
95    }
96
97    static void set_manipulator(std::ios& i, manipulator_type m, char c) {
98       i.iword(get_stream_index(m)) = static_cast<long>(c);
99    }
100 #else
101    template<class CharType, class CharTrait>
102    static CharType get_manipulator(std::basic_ios<CharType, CharTrait>& i, 
103                                    manipulator_type m) {
104      // The manipulators are stored as long.
105      // A valid instanitation of basic_stream allows CharType to be any POD,
106      // hence, the static_cast may fail (it fails if long is not convertible 
107      // to CharType
108      CharType c = static_cast<CharType>(i.iword(get_stream_index(m)) ); 
109      // parentheses and space are the default manipulators
110      if (!c) {
111        switch(m) {
112          case detail::format_info::open :  c = i.widen('('); break;
113          case detail::format_info::close : c = i.widen(')'); break;
114          case detail::format_info::delimiter : c = i.widen(' '); break;
115        }
116      }
117      return c;
118    }
119
120
121    template<class CharType, class CharTrait>
122    static void set_manipulator(std::basic_ios<CharType, CharTrait>& i, 
123                                manipulator_type m, CharType c) {
124      // The manipulators are stored as long.
125      // A valid instanitation of basic_stream allows CharType to be any POD,
126      // hence, the static_cast may fail (it fails if CharType is not 
127      // convertible long.
128       i.iword(get_stream_index(m)) = static_cast<long>(c);
129    }
130 #endif // BOOST_NO_TEMPLATED_STREAMS
131 };
132
133 } // end of namespace detail
134  
135 template<class CharType>    
136 class tuple_manipulator {
137   const detail::format_info::manipulator_type mt;
138   CharType f_c;
139 public:
140   explicit tuple_manipulator(detail::format_info::manipulator_type m, 
141                              const char c = 0)
142      : mt(m), f_c(c) {}
143   
144 #if defined (BOOST_NO_TEMPLATED_STREAMS)
145   void set(std::ios &io) const {
146      detail::format_info::set_manipulator(io, mt, f_c);
147   }
148 #else
149 #if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
150    template<class CharType2, class CharTrait>
151   void set(std::basic_ios<CharType2, CharTrait> &io) const {
152      detail::format_info::set_manipulator(io, mt, f_c);
153   }
154 #else
155    template<class CharTrait>
156   void set(std::basic_ios<CharType, CharTrait> &io) const {
157      detail::format_info::set_manipulator(io, mt, f_c);
158   }
159 #endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
160 #endif // BOOST_NO_TEMPLATED_STREAMS
161 };
162
163 #if defined (BOOST_NO_TEMPLATED_STREAMS)
164 inline std::ostream&
165 operator<<(std::ostream& o, const tuple_manipulator<char>& m) {
166   m.set(o);
167   return o;
168 }
169
170 inline std::istream&
171 operator>>(std::istream& i, const tuple_manipulator<char>& m) {
172   m.set(i);
173   return i;
174 }
175
176 #else
177
178 template<class CharType, class CharTrait>
179 inline std::basic_ostream<CharType, CharTrait>&
180 operator<<(std::basic_ostream<CharType, CharTrait>& o, const tuple_manipulator<CharType>& m) {
181   m.set(o);
182   return o;
183 }
184
185 template<class CharType, class CharTrait>
186 inline std::basic_istream<CharType, CharTrait>&
187 operator>>(std::basic_istream<CharType, CharTrait>& i, const tuple_manipulator<CharType>& m) {
188   m.set(i);
189   return i;
190 }
191
192 #endif   // BOOST_NO_TEMPLATED_STREAMS
193    
194 template<class CharType>
195 inline tuple_manipulator<CharType> set_open(const CharType c) {
196    return tuple_manipulator<CharType>(detail::format_info::open, c);
197 }
198
199 template<class CharType>
200 inline tuple_manipulator<CharType> set_close(const CharType c) {
201    return tuple_manipulator<CharType>(detail::format_info::close, c);
202 }
203
204 template<class CharType>
205 inline tuple_manipulator<CharType> set_delimiter(const CharType c) {
206    return tuple_manipulator<CharType>(detail::format_info::delimiter, c);
207 }
208
209
210
211    
212    
213 // -------------------------------------------------------------
214 // printing tuples to ostream in format (a b c)
215 // parentheses and space are defaults, but can be overriden with manipulators
216 // set_open, set_close and set_delimiter
217    
218 namespace detail {
219
220 // Note: The order of the print functions is critical 
221 // to let a conforming compiler  find and select the correct one.
222
223 #if defined (BOOST_NO_TEMPLATED_STREAMS)
224
225 #if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
226 template<class T1>
227 inline std::ostream& print(std::ostream& o, const cons<T1, null_type>& t) {
228   return o << t.head;
229 }
230 #endif // BOOST_NO_TEMPLATED_STREAMS
231  
232 inline std::ostream& print(std::ostream& o, const null_type&) { return o; }
233
234 template<class T1, class T2>
235 inline std::ostream& 
236 print(std::ostream& o, const cons<T1, T2>& t) {
237   
238   const char d = format_info::get_manipulator(o, format_info::delimiter);
239    
240   o << t.head;
241
242 #if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
243   if (tuples::length<T2>::value == 0)
244     return o;
245 #endif  // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
246   o << d;
247   
248   return print(o, t.tail );
249
250 }
251
252
253
254 #else
255
256 #if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
257 template<class CharType, class CharTrait, class T1>
258 inline std::basic_ostream<CharType, CharTrait>& 
259 print(std::basic_ostream<CharType, CharTrait>& o, const cons<T1, null_type>& t) {
260   return o << t.head;
261 }
262 #endif  // !BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
263
264  
265 template<class CharType, class CharTrait>
266 inline std::basic_ostream<CharType, CharTrait>& 
267 print(std::basic_ostream<CharType, CharTrait>& o, const null_type&) { 
268   return o; 
269 }
270
271 template<class CharType, class CharTrait, class T1, class T2>
272 inline std::basic_ostream<CharType, CharTrait>& 
273 print(std::basic_ostream<CharType, CharTrait>& o, const cons<T1, T2>& t) {
274   
275   const CharType d = format_info::get_manipulator(o, format_info::delimiter);
276    
277   o << t.head;
278
279 #if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
280   if (tuples::length<T2>::value == 0)
281     return o;
282 #endif  // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
283   o << d;
284
285   return print(o, t.tail);
286 }
287
288 #endif  // BOOST_NO_TEMPLATED_STREAMS
289
290 } // namespace detail
291
292 #if defined (BOOST_NO_TEMPLATED_STREAMS)
293 template<class T1, class T2>
294 inline std::ostream& operator<<(std::ostream& o, const cons<T1, T2>& t) {
295   if (!o.good() ) return o;
296  
297   const char l = 
298     detail::format_info::get_manipulator(o, detail::format_info::open);
299   const char r = 
300     detail::format_info::get_manipulator(o, detail::format_info::close);
301    
302   o << l;
303   
304   detail::print(o, t);  
305
306   o << r;
307
308   return o;
309 }
310
311 #else
312
313 template<class CharType, class CharTrait, class T1, class T2>
314 inline std::basic_ostream<CharType, CharTrait>& 
315 operator<<(std::basic_ostream<CharType, CharTrait>& o, 
316            const cons<T1, T2>& t) {
317   if (!o.good() ) return o;
318  
319   const CharType l = 
320     detail::format_info::get_manipulator(o, detail::format_info::open);
321   const CharType r = 
322     detail::format_info::get_manipulator(o, detail::format_info::close);
323    
324   o << l;   
325
326   detail::print(o, t);  
327
328   o << r;
329
330   return o;
331 }
332 #endif // BOOST_NO_TEMPLATED_STREAMS
333
334    
335 // -------------------------------------------------------------
336 // input stream operators
337
338 namespace detail {
339
340 #if defined (BOOST_NO_TEMPLATED_STREAMS)
341
342 inline std::istream& 
343 extract_and_check_delimiter(
344   std::istream& is, format_info::manipulator_type del)
345 {
346   const char d = format_info::get_manipulator(is, del);
347
348 #if defined (BOOST_NO_STD_LOCALE)
349   const bool is_delimiter = !isspace(d);
350 #else
351   const bool is_delimiter = (!std::isspace(d, is.getloc()) );            
352 #endif
353
354   char c;
355   if (is_delimiter) { 
356     is >> c; 
357     if (c!=d) {
358       is.setstate(std::ios::failbit);
359     } 
360   }
361   return is;
362 }
363
364
365 // Note: The order of the read functions is critical to let a 
366 // (conforming?) compiler find and select the correct one.
367
368 #if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
369 template<class T1>
370 inline  std::istream & 
371 read (std::istream &is, cons<T1, null_type>& t1) {
372
373   if (!is.good()) return is;   
374    
375   return is >> t1.head ;
376 }
377 #else
378 inline std::istream& read(std::istream& i, const null_type&) { return i; }
379 #endif // !BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
380    
381 template<class T1, class T2>
382 inline std::istream& 
383 read(std::istream &is, cons<T1, T2>& t1) {
384
385   if (!is.good()) return is;
386    
387   is >> t1.head;
388
389 #if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
390   if (tuples::length<T2>::value == 0)
391     return is;
392 #endif  // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
393
394   extract_and_check_delimiter(is, format_info::delimiter);
395
396   return read(is, t1.tail);
397 }
398
399 } // end namespace detail
400
401 inline std::istream& 
402 operator>>(std::istream &is, null_type&) {
403
404   if (!is.good() ) return is;
405
406   detail::extract_and_check_delimiter(is, detail::format_info::open);
407   detail::extract_and_check_delimiter(is, detail::format_info::close);
408
409   return is;
410 }
411
412
413 template<class T1, class T2>
414 inline std::istream& 
415 operator>>(std::istream& is, cons<T1, T2>& t1) {
416
417   if (!is.good() ) return is;
418
419   detail::extract_and_check_delimiter(is, detail::format_info::open);
420                       
421   detail::read(is, t1);
422    
423   detail::extract_and_check_delimiter(is, detail::format_info::close);
424
425   return is;
426 }
427
428
429
430 #else
431
432 template<class CharType, class CharTrait>
433 inline std::basic_istream<CharType, CharTrait>& 
434 extract_and_check_delimiter(
435   std::basic_istream<CharType, CharTrait> &is, format_info::manipulator_type del)
436 {
437   const CharType d = format_info::get_manipulator(is, del);
438
439 #if defined (BOOST_NO_STD_LOCALE)
440   const bool is_delimiter = !isspace(d);
441 #elif defined ( __BORLANDC__ )
442   const bool is_delimiter = !std::use_facet< std::ctype< CharType > >
443     (is.getloc() ).is( std::ctype_base::space, d);
444 #else
445   const bool is_delimiter = (!std::isspace(d, is.getloc()) );            
446 #endif
447
448   CharType c;
449   if (is_delimiter) { 
450     is >> c;
451     if (c!=d) { 
452       is.setstate(std::ios::failbit);
453     }
454   }
455   return is;
456 }
457
458    
459 #if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
460 template<class CharType, class CharTrait, class T1>
461 inline  std::basic_istream<CharType, CharTrait> & 
462 read (std::basic_istream<CharType, CharTrait> &is, cons<T1, null_type>& t1) {
463
464   if (!is.good()) return is;   
465    
466   return is >> t1.head; 
467 }
468 #else
469 template<class CharType, class CharTrait>
470 inline std::basic_istream<CharType, CharTrait>& 
471 read(std::basic_istream<CharType, CharTrait>& i, const null_type&) { return i; }
472
473 #endif // !BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
474
475 template<class CharType, class CharTrait, class T1, class T2>
476 inline std::basic_istream<CharType, CharTrait>& 
477 read(std::basic_istream<CharType, CharTrait> &is, cons<T1, T2>& t1) {
478
479   if (!is.good()) return is;
480    
481   is >> t1.head;
482
483 #if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
484   if (tuples::length<T2>::value == 0)
485     return is;
486 #endif  // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
487
488   extract_and_check_delimiter(is, format_info::delimiter);
489
490   return read(is, t1.tail);
491 }
492
493 } // end namespace detail
494
495
496 template<class CharType, class CharTrait>
497 inline std::basic_istream<CharType, CharTrait>& 
498 operator>>(std::basic_istream<CharType, CharTrait> &is, null_type&) {
499
500   if (!is.good() ) return is;
501
502   detail::extract_and_check_delimiter(is, detail::format_info::open);
503   detail::extract_and_check_delimiter(is, detail::format_info::close);
504
505   return is;
506 }
507
508 template<class CharType, class CharTrait, class T1, class T2>
509 inline std::basic_istream<CharType, CharTrait>& 
510 operator>>(std::basic_istream<CharType, CharTrait>& is, cons<T1, T2>& t1) {
511
512   if (!is.good() ) return is;
513
514   detail::extract_and_check_delimiter(is, detail::format_info::open);
515                       
516   detail::read(is, t1);
517    
518   detail::extract_and_check_delimiter(is, detail::format_info::close);
519
520   return is;
521 }
522
523 #endif // BOOST_NO_TEMPLATED_STREAMS
524
525 } // end of namespace tuples
526 } // end of namespace boost
527
528 #endif // BOOST_TUPLE_IO_HPP
529
530