File indexing completed on 2025-01-18 09:52:55
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #ifndef BOOST_TUPLE_IO_HPP
0014 #define BOOST_TUPLE_IO_HPP
0015
0016 #include <istream>
0017 #include <ostream>
0018
0019 #include <sstream>
0020
0021 #include <boost/tuple/tuple.hpp>
0022
0023
0024
0025
0026
0027
0028
0029 #if !defined (BOOST_NO_STD_LOCALE)
0030
0031 #include <locale> // for two-arg isspace
0032
0033 #else
0034
0035 #include <cctype> // for one-arg (old) isspace
0036 #include <ctype.h> // Metrowerks does not find one-arg isspace from cctype
0037
0038 #endif
0039
0040 namespace boost {
0041 namespace tuples {
0042
0043 namespace detail {
0044
0045 class format_info {
0046 public:
0047
0048 enum manipulator_type { open, close, delimiter };
0049 BOOST_STATIC_CONSTANT(int, number_of_manipulators = delimiter + 1);
0050 private:
0051
0052 static int get_stream_index (int m)
0053 {
0054 static const int stream_index[number_of_manipulators]
0055 = { std::ios::xalloc(), std::ios::xalloc(), std::ios::xalloc() };
0056
0057 return stream_index[m];
0058 }
0059
0060 format_info(const format_info&);
0061 format_info();
0062
0063
0064 public:
0065
0066 template<class CharType, class CharTrait>
0067 static CharType get_manipulator(std::basic_ios<CharType, CharTrait>& i,
0068 manipulator_type m) {
0069
0070
0071
0072
0073 CharType c = static_cast<CharType>(i.iword(get_stream_index(m)) );
0074
0075 if (!c) {
0076 switch(m) {
0077 case detail::format_info::open : c = i.widen('('); break;
0078 case detail::format_info::close : c = i.widen(')'); break;
0079 case detail::format_info::delimiter : c = i.widen(' '); break;
0080 }
0081 }
0082 return c;
0083 }
0084
0085
0086 template<class CharType, class CharTrait>
0087 static void set_manipulator(std::basic_ios<CharType, CharTrait>& i,
0088 manipulator_type m, CharType c) {
0089
0090
0091
0092
0093 i.iword(get_stream_index(m)) = static_cast<long>(c);
0094 }
0095 };
0096
0097 }
0098
0099 template<class CharType>
0100 class tuple_manipulator {
0101 const detail::format_info::manipulator_type mt;
0102 CharType f_c;
0103 public:
0104 explicit tuple_manipulator(detail::format_info::manipulator_type m,
0105 CharType c = CharType())
0106 : mt(m), f_c(c) {}
0107
0108 template<class CharTrait>
0109 void set(std::basic_ios<CharType, CharTrait> &io) const {
0110 detail::format_info::set_manipulator(io, mt, f_c);
0111 }
0112 };
0113
0114
0115 template<class CharType, class CharTrait>
0116 inline std::basic_ostream<CharType, CharTrait>&
0117 operator<<(std::basic_ostream<CharType, CharTrait>& o, const tuple_manipulator<CharType>& m) {
0118 m.set(o);
0119 return o;
0120 }
0121
0122 template<class CharType, class CharTrait>
0123 inline std::basic_istream<CharType, CharTrait>&
0124 operator>>(std::basic_istream<CharType, CharTrait>& i, const tuple_manipulator<CharType>& m) {
0125 m.set(i);
0126 return i;
0127 }
0128
0129
0130 template<class CharType>
0131 inline tuple_manipulator<CharType> set_open(const CharType c) {
0132 return tuple_manipulator<CharType>(detail::format_info::open, c);
0133 }
0134
0135 template<class CharType>
0136 inline tuple_manipulator<CharType> set_close(const CharType c) {
0137 return tuple_manipulator<CharType>(detail::format_info::close, c);
0138 }
0139
0140 template<class CharType>
0141 inline tuple_manipulator<CharType> set_delimiter(const CharType c) {
0142 return tuple_manipulator<CharType>(detail::format_info::delimiter, c);
0143 }
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154 namespace detail {
0155
0156
0157
0158
0159
0160 template<class CharType, class CharTrait, class T1>
0161 inline std::basic_ostream<CharType, CharTrait>&
0162 print(std::basic_ostream<CharType, CharTrait>& o, const cons<T1, null_type>& t) {
0163 return o << t.head;
0164 }
0165
0166
0167 template<class CharType, class CharTrait>
0168 inline std::basic_ostream<CharType, CharTrait>&
0169 print(std::basic_ostream<CharType, CharTrait>& o, const null_type&) {
0170 return o;
0171 }
0172
0173 template<class CharType, class CharTrait, class T1, class T2>
0174 inline std::basic_ostream<CharType, CharTrait>&
0175 print(std::basic_ostream<CharType, CharTrait>& o, const cons<T1, T2>& t) {
0176
0177 const CharType d = format_info::get_manipulator(o, format_info::delimiter);
0178
0179 o << t.head;
0180
0181 o << d;
0182
0183 return print(o, t.tail);
0184 }
0185
0186 template<class CharT, class Traits, class T>
0187 inline bool handle_width(std::basic_ostream<CharT, Traits>& o, const T& t) {
0188 std::streamsize width = o.width();
0189 if(width == 0) return false;
0190
0191 std::basic_ostringstream<CharT, Traits> ss;
0192
0193 ss.copyfmt(o);
0194 ss.tie(0);
0195 ss.width(0);
0196
0197 ss << t;
0198 o << ss.str();
0199
0200 return true;
0201 }
0202
0203
0204 }
0205
0206
0207 template<class CharType, class CharTrait>
0208 inline std::basic_ostream<CharType, CharTrait>&
0209 operator<<(std::basic_ostream<CharType, CharTrait>& o,
0210 const null_type& t) {
0211 if (!o.good() ) return o;
0212 if (detail::handle_width(o, t)) return o;
0213
0214 const CharType l =
0215 detail::format_info::get_manipulator(o, detail::format_info::open);
0216 const CharType r =
0217 detail::format_info::get_manipulator(o, detail::format_info::close);
0218
0219 o << l;
0220 o << r;
0221
0222 return o;
0223 }
0224
0225 template<class CharType, class CharTrait, class T1, class T2>
0226 inline std::basic_ostream<CharType, CharTrait>&
0227 operator<<(std::basic_ostream<CharType, CharTrait>& o,
0228 const cons<T1, T2>& t) {
0229 if (!o.good() ) return o;
0230 if (detail::handle_width(o, t)) return o;
0231
0232 const CharType l =
0233 detail::format_info::get_manipulator(o, detail::format_info::open);
0234 const CharType r =
0235 detail::format_info::get_manipulator(o, detail::format_info::close);
0236
0237 o << l;
0238
0239 detail::print(o, t);
0240
0241 o << r;
0242
0243 return o;
0244 }
0245
0246
0247
0248
0249
0250 namespace detail {
0251
0252
0253 template<class CharType, class CharTrait>
0254 inline std::basic_istream<CharType, CharTrait>&
0255 extract_and_check_delimiter(
0256 std::basic_istream<CharType, CharTrait> &is, format_info::manipulator_type del)
0257 {
0258 const CharType d = format_info::get_manipulator(is, del);
0259
0260 #if defined (BOOST_NO_STD_LOCALE)
0261 const bool is_delimiter = !isspace(d);
0262 #elif defined ( BOOST_BORLANDC )
0263 const bool is_delimiter = !std::use_facet< std::ctype< CharType > >
0264 (is.getloc() ).is( std::ctype_base::space, d);
0265 #else
0266 const bool is_delimiter = (!std::isspace(d, is.getloc()) );
0267 #endif
0268
0269 CharType c;
0270 if (is_delimiter) {
0271 is >> c;
0272 if (is.good() && c!=d) {
0273 is.setstate(std::ios::failbit);
0274 }
0275 } else {
0276 is >> std::ws;
0277 }
0278 return is;
0279 }
0280
0281
0282 template<class CharType, class CharTrait, class T1>
0283 inline std::basic_istream<CharType, CharTrait> &
0284 read (std::basic_istream<CharType, CharTrait> &is, cons<T1, null_type>& t1) {
0285
0286 if (!is.good()) return is;
0287
0288 return is >> t1.head;
0289 }
0290
0291 template<class CharType, class CharTrait, class T1, class T2>
0292 inline std::basic_istream<CharType, CharTrait>&
0293 read(std::basic_istream<CharType, CharTrait> &is, cons<T1, T2>& t1) {
0294
0295 if (!is.good()) return is;
0296
0297 is >> t1.head;
0298
0299
0300 extract_and_check_delimiter(is, format_info::delimiter);
0301
0302 return read(is, t1.tail);
0303 }
0304
0305 }
0306
0307
0308 template<class CharType, class CharTrait>
0309 inline std::basic_istream<CharType, CharTrait>&
0310 operator>>(std::basic_istream<CharType, CharTrait> &is, null_type&) {
0311
0312 if (!is.good() ) return is;
0313
0314 detail::extract_and_check_delimiter(is, detail::format_info::open);
0315 detail::extract_and_check_delimiter(is, detail::format_info::close);
0316
0317 return is;
0318 }
0319
0320 template<class CharType, class CharTrait, class T1, class T2>
0321 inline std::basic_istream<CharType, CharTrait>&
0322 operator>>(std::basic_istream<CharType, CharTrait>& is, cons<T1, T2>& t1) {
0323
0324 if (!is.good() ) return is;
0325
0326 detail::extract_and_check_delimiter(is, detail::format_info::open);
0327
0328 detail::read(is, t1);
0329
0330 detail::extract_and_check_delimiter(is, detail::format_info::close);
0331
0332 return is;
0333 }
0334
0335
0336 }
0337 }
0338
0339 #endif