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