Whole document tree locale_facets.tccGo to the documentation of this file.00001 // Locale support -*- C++ -*- 00002 00003 // Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. 00004 // 00005 // This file is part of the GNU ISO C++ Library. This library is free 00006 // software; you can redistribute it and/or modify it under the 00007 // terms of the GNU General Public License as published by the 00008 // Free Software Foundation; either version 2, or (at your option) 00009 // any later version. 00010 00011 // This library is distributed in the hope that it will be useful, 00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 // GNU General Public License for more details. 00015 00016 // You should have received a copy of the GNU General Public License along 00017 // with this library; see the file COPYING. If not, write to the Free 00018 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, 00019 // USA. 00020 00021 // As a special exception, you may use this file as part of a free software 00022 // library without restriction. Specifically, if other files instantiate 00023 // templates or use macros or inline functions from this file, or you compile 00024 // this file and link it with other files to produce an executable, this 00025 // file does not by itself cause the resulting executable to be covered by 00026 // the GNU General Public License. This exception does not however 00027 // invalidate any other reasons why the executable file might be covered by 00028 // the GNU General Public License. 00029 00030 // Warning: this file is not meant for user inclusion. Use <locale>. 00031 00032 #ifndef _CPP_BITS_LOCFACETS_TCC 00033 #define _CPP_BITS_LOCFACETS_TCC 1 00034 00035 #include <bits/std_cerrno.h> 00036 #include <bits/std_clocale.h> // For localeconv 00037 #include <bits/std_cstdlib.h> // For strof, strtold 00038 #include <bits/std_limits.h> // For numeric_limits 00039 #include <bits/std_memory.h> // For auto_ptr 00040 #include <bits/sbuf_iter.h> // For streambuf_iterators 00041 #include <bits/std_cctype.h> // For isspace 00042 #include <typeinfo> // For bad_cast 00043 #include <bits/std_vector.h> 00044 00045 00046 namespace std 00047 { 00048 template<typename _Facet> 00049 locale 00050 locale::combine(const locale& __other) 00051 { 00052 locale __copy(*this); 00053 __copy._M_impl->_M_replace_facet(__other._M_impl, &_Facet::id); 00054 return __copy; 00055 } 00056 00057 template<typename _CharT, typename _Traits, typename _Alloc> 00058 bool 00059 locale::operator()(const basic_string<_CharT, _Traits, _Alloc>& __s1, 00060 const basic_string<_CharT, _Traits, _Alloc>& __s2) const 00061 { 00062 typedef std::collate<_CharT> __collate_type; 00063 const __collate_type* __fcoll = &use_facet<__collate_type>(*this); 00064 return (__fcoll->compare(__s1.data(), __s1.data() + __s1.length(), 00065 __s2.data(), __s2.data() + __s2.length()) < 0); 00066 } 00067 00068 template<typename _Facet> 00069 const _Facet& 00070 use_facet(const locale& __loc) 00071 { 00072 typedef locale::_Impl::__vec_facet __vec_facet; 00073 size_t __i = _Facet::id._M_index; 00074 __vec_facet* __facet = __loc._M_impl->_M_facets; 00075 const locale::facet* __fp = (*__facet)[__i]; 00076 if (__fp == 0 || __i >= __facet->size()) 00077 __throw_bad_cast(); 00078 return static_cast<const _Facet&>(*__fp); 00079 } 00080 00081 template<typename _Facet> 00082 bool 00083 has_facet(const locale& __loc) throw() 00084 { 00085 typedef locale::_Impl::__vec_facet __vec_facet; 00086 size_t __i = _Facet::id._M_index; 00087 __vec_facet* __facet = __loc._M_impl->_M_facets; 00088 return (__i < __facet->size() && (*__facet)[__i] != 0); 00089 } 00090 00091 // __match_parallel 00092 // matches input __s against a set of __ntargs strings in __targets, 00093 // placing in __matches a vector of indices into __targets which 00094 // match, and in __remain the number of such matches. If it hits 00095 // end of sequence before it minimizes the set, sets __eof. 00096 // Empty strings are never matched. 00097 template<typename _InIter, typename _CharT> 00098 _InIter 00099 __match_parallel(_InIter __s, _InIter __end, int __ntargs, 00100 const basic_string<_CharT>* __targets, 00101 int* __matches, int& __remain, bool& __eof) 00102 { 00103 typedef basic_string<_CharT> __string_type; 00104 __eof = false; 00105 for (int __ti = 0; __ti < __ntargs; ++__ti) 00106 __matches[__ti] = __ti; 00107 __remain = __ntargs; 00108 size_t __pos = 0; 00109 do 00110 { 00111 int __ti = 0; 00112 while (__ti < __remain && __pos == __targets[__matches[__ti]].size()) 00113 ++__ti; 00114 if (__ti == __remain) 00115 { 00116 if (__pos == 0) __remain = 0; 00117 return __s; 00118 } 00119 if (__s == __end) 00120 __eof = true; 00121 bool __matched = false; 00122 for (int __ti2 = 0; __ti2 < __remain; ) 00123 { 00124 const __string_type& __target = __targets[__matches[__ti2]]; 00125 if (__pos < __target.size()) 00126 { 00127 if (__eof || __target[__pos] != *__s) 00128 { 00129 __matches[__ti2] = __matches[--__remain]; 00130 continue; 00131 } 00132 __matched = true; 00133 } 00134 ++__ti2; 00135 } 00136 if (__matched) 00137 { 00138 ++__s; 00139 ++__pos; 00140 } 00141 for (int __ti3 = 0; __ti3 < __remain;) 00142 { 00143 if (__pos > __targets[__matches[__ti3]].size()) 00144 { 00145 __matches[__ti3] = __matches[--__remain]; 00146 continue; 00147 } 00148 ++__ti3; 00149 } 00150 } 00151 while (__remain); 00152 return __s; 00153 } 00154 00155 template<typename _CharT> 00156 _Format_cache<_CharT>::_Format_cache() 00157 : _M_valid(true), _M_use_grouping(false) 00158 { } 00159 00160 template<> 00161 _Format_cache<char>::_Format_cache(); 00162 00163 template<> 00164 _Format_cache<wchar_t>::_Format_cache(); 00165 00166 template<typename _CharT> 00167 void 00168 _Format_cache<_CharT>::_M_populate(ios_base& __io) 00169 { 00170 locale __loc = __io.getloc (); 00171 numpunct<_CharT> const& __np = use_facet<numpunct<_CharT> >(__loc); 00172 _M_truename = __np.truename(); 00173 _M_falsename = __np.falsename(); 00174 _M_thousands_sep = __np.thousands_sep(); 00175 _M_decimal_point = __np.decimal_point(); 00176 _M_grouping = __np.grouping(); 00177 _M_use_grouping = _M_grouping.size() != 0 && _M_grouping.data()[0] != 0; 00178 _M_valid = true; 00179 } 00180 00181 // This function is always called via a pointer installed in 00182 // an ios_base by ios_base::register_callback. 00183 template<typename _CharT> 00184 void 00185 _Format_cache<_CharT>:: 00186 _S_callback(ios_base::event __ev, ios_base& __ios, int __ix) throw() 00187 { 00188 void*& __p = __ios.pword(__ix); 00189 switch (__ev) 00190 { 00191 case ios_base::erase_event: 00192 delete static_cast<_Format_cache<_CharT>*>(__p); 00193 __p = 0; 00194 break; 00195 case ios_base::copyfmt_event: 00196 // If just stored zero, the callback would get registered again. 00197 try 00198 { __p = new _Format_cache<_CharT>; } 00199 catch(...) 00200 { } 00201 break; 00202 case ios_base::imbue_event: 00203 static_cast<_Format_cache<_CharT>*>(__p)->_M_valid = false; 00204 break; 00205 } 00206 } 00207 00208 template<typename _CharT> 00209 _Format_cache<_CharT>* 00210 _Format_cache<_CharT>::_S_get(ios_base& __ios) 00211 { 00212 if (!_S_pword_ix) 00213 _S_pword_ix = ios_base::xalloc(); // XXX MT 00214 void*& __p = __ios.pword(_S_pword_ix); 00215 00216 // XXX What if pword fails? must check failbit, throw. 00217 if (__p == 0) // XXX MT? maybe sentry takes care of it 00218 { 00219 auto_ptr<_Format_cache<_CharT> > __ap(new _Format_cache<_CharT>); 00220 __ios.register_callback(&_Format_cache<_CharT>::_S_callback, 00221 _S_pword_ix); 00222 __p = __ap.release(); 00223 } 00224 _Format_cache<_CharT>* __ncp = static_cast<_Format_cache<_CharT>*>(__p); 00225 if (!__ncp->_M_valid) 00226 __ncp->_M_populate(__ios); 00227 00228 return __ncp; 00229 } 00230 00231 // This member function takes an (w)istreambuf_iterator object and 00232 // parses it into a generic char array suitable for parsing with 00233 // strto[l,ll,f,d]. The thought was to encapsulate the conversion 00234 // into this one function, and thus the num_get::do_get member 00235 // functions can just adjust for the type of the overloaded 00236 // argument and process the char array returned from _M_extract. 00237 // Other things were also considered, including a fused 00238 // multiply-add loop that would obviate the need for any call to 00239 // strto... at all: however, it would b e a bit of a pain, because 00240 // you'd have to be able to return either floating or integral 00241 // types, etc etc. The current approach seems to be smack dab in 00242 // the middle between an unoptimized approach using sscanf, and 00243 // some kind of hyper-optimized approach alluded to above. 00244 00245 // XXX 00246 // Need to do partial specialization to account for differences 00247 // between character sets. For char, this is pretty 00248 // straightforward, but for wchar_t, the conversion to a plain-jane 00249 // char type is a bit more involved. 00250 template<typename _CharT, typename _InIter> 00251 void 00252 num_get<_CharT, _InIter>:: 00253 _M_extract(_InIter /*__beg*/, _InIter /*__end*/, ios_base& /*__io*/, 00254 ios_base::iostate& /*__err*/, char* /*__xtrc*/, 00255 int& /*__base*/, bool /*__fp*/) const 00256 { 00257 // XXX Not currently done: need to expand upon char version below. 00258 } 00259 00260 template<> 00261 void 00262 num_get<char, istreambuf_iterator<char> >:: 00263 _M_extract(istreambuf_iterator<char> __beg, 00264 istreambuf_iterator<char> __end, ios_base& __io, 00265 ios_base::iostate& __err, char* __xtrc, int& __base, 00266 bool __fp) const; 00267 00268 #ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS 00269 // NB: This is an unresolved library defect #17 00270 template<typename _CharT, typename _InIter> 00271 _InIter 00272 num_get<_CharT, _InIter>:: 00273 do_get(iter_type __beg, iter_type __end, ios_base& __io, 00274 ios_base::iostate& __err, bool& __v) const 00275 { 00276 // Parse bool values as long 00277 if (!(__io.flags() & ios_base::boolalpha)) 00278 { 00279 // NB: We can't just call do_get(long) here, as it might 00280 // refer to a derived class. 00281 00282 // Stage 1: extract and determine the conversion specifier. 00283 // Assuming leading zeros eliminated, thus the size of 32 for 00284 // integral types. 00285 char __xtrc[_M_extract_buffer_length] = {'\0'}; 00286 int __base; 00287 _M_extract(__beg, __end, __io, __err, __xtrc, __base, false); 00288 00289 // Stage 2: convert and store results. 00290 char* __sanity; 00291 errno = 0; 00292 long __l = strtol(__xtrc, &__sanity, __base); 00293 if (!(__err & ios_base::failbit) 00294 && __l <= 1 00295 && __sanity != __xtrc && *__sanity == '\0' && errno == 0) 00296 __v = __l; 00297 else 00298 __err |= ios_base::failbit; 00299 } 00300 00301 // Parse bool values as alphanumeric 00302 else 00303 { 00304 typedef _Format_cache<char_type> __fcache_type; 00305 __fcache_type* __fmt = __fcache_type::_S_get(__io); 00306 const char_type* __true = __fmt->_M_truename.c_str(); 00307 const char_type* __false = __fmt->_M_falsename.c_str(); 00308 const size_t __truelen = __traits_type::length(__true) - 1; 00309 const size_t __falselen = __traits_type::length(__false) - 1; 00310 00311 for (size_t __pos = 0; __beg != __end; ++__pos) 00312 { 00313 char_type __c = *__beg++; 00314 bool __testf = __c == __false[__pos]; 00315 bool __testt = __c == __true[__pos]; 00316 if (!(__testf || __testt)) 00317 { 00318 __err |= ios_base::failbit; 00319 break; 00320 } 00321 else if (__testf && __pos == __falselen) 00322 { 00323 __v = 0; 00324 break; 00325 } 00326 else if (__testt && __pos == __truelen) 00327 { 00328 __v = 1; 00329 break; 00330 } 00331 } 00332 if (__beg == __end) 00333 __err |= ios_base::eofbit; 00334 } 00335 00336 return __beg; 00337 } 00338 #endif 00339 00340 #ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS 00341 template<typename _CharT, typename _InIter> 00342 _InIter 00343 num_get<_CharT, _InIter>:: 00344 do_get(iter_type __beg, iter_type __end, ios_base& __io, 00345 ios_base::iostate& __err, short& __v) const 00346 { 00347 // Stage 1: extract and determine the conversion specifier. 00348 // Assuming leading zeros eliminated, thus the size of 32 for 00349 // integral types. 00350 char __xtrc[_M_extract_buffer_length]= {'\0'}; 00351 int __base; 00352 _M_extract(__beg, __end, __io, __err, __xtrc, __base, false); 00353 00354 // Stage 2: convert and store results. 00355 char* __sanity; 00356 errno = 0; 00357 long __l = strtol(__xtrc, &__sanity, __base); 00358 if (!(__err & ios_base::failbit) 00359 && __sanity != __xtrc && *__sanity == '\0' && errno == 0 00360 && __l >= SHRT_MIN && __l <= SHRT_MAX) 00361 __v = static_cast<short>(__l); 00362 else 00363 __err |= ios_base::failbit; 00364 00365 return __beg; 00366 } 00367 00368 template<typename _CharT, typename _InIter> 00369 _InIter 00370 num_get<_CharT, _InIter>:: 00371 do_get(iter_type __beg, iter_type __end, ios_base& __io, 00372 ios_base::iostate& __err, int& __v) const 00373 { 00374 // Stage 1: extract and determine the conversion specifier. 00375 // Assuming leading zeros eliminated, thus the size of 32 for 00376 // integral types. 00377 char __xtrc[_M_extract_buffer_length] = {'\0'}; 00378 int __base; 00379 _M_extract(__beg, __end, __io, __err, __xtrc, __base, false); 00380 00381 // Stage 2: convert and store results. 00382 char* __sanity; 00383 errno = 0; 00384 long __l = strtol(__xtrc, &__sanity, __base); 00385 if (!(__err & ios_base::failbit) 00386 && __sanity != __xtrc && *__sanity == '\0' && errno == 0 00387 && __l >= INT_MIN && __l <= INT_MAX) 00388 __v = static_cast<int>(__l); 00389 else 00390 __err |= ios_base::failbit; 00391 00392 return __beg; 00393 } 00394 #endif 00395 00396 template<typename _CharT, typename _InIter> 00397 _InIter 00398 num_get<_CharT, _InIter>:: 00399 do_get(iter_type __beg, iter_type __end, ios_base& __io, 00400 ios_base::iostate& __err, long& __v) const 00401 { 00402 // Stage 1: extract and determine the conversion specifier. 00403 // Assuming leading zeros eliminated, thus the size of 32 for 00404 // integral types. 00405 char __xtrc[_M_extract_buffer_length]= {'\0'}; 00406 int __base; 00407 _M_extract(__beg, __end, __io, __err, __xtrc, __base, false); 00408 00409 // Stage 2: convert and store results. 00410 char* __sanity; 00411 errno = 0; 00412 long __l = strtol(__xtrc, &__sanity, __base); 00413 if (!(__err & ios_base::failbit) 00414 && __sanity != __xtrc && *__sanity == '\0' && errno == 0) 00415 __v = __l; 00416 else 00417 __err |= ios_base::failbit; 00418 00419 return __beg; 00420 } 00421 00422 #ifdef _GLIBCPP_USE_LONG_LONG 00423 template<typename _CharT, typename _InIter> 00424 _InIter 00425 num_get<_CharT, _InIter>:: 00426 do_get(iter_type __beg, iter_type __end, ios_base& __io, 00427 ios_base::iostate& __err, long long& __v) const 00428 { 00429 // Stage 1: extract and determine the conversion specifier. 00430 // Assuming leading zeros eliminated, thus the size of 32 for 00431 // integral types. 00432 char __xtrc[_M_extract_buffer_length]= {'\0'}; 00433 int __base; 00434 _M_extract(__beg, __end, __io, __err, __xtrc, __base, false); 00435 00436 // Stage 2: convert and store results. 00437 char* __sanity; 00438 errno = 0; 00439 long long __ll = strtoll(__xtrc, &__sanity, __base); 00440 if (!(__err & ios_base::failbit) 00441 && __sanity != __xtrc && *__sanity == '\0' && errno == 0) 00442 __v = __ll; 00443 else 00444 __err |= ios_base::failbit; 00445 00446 return __beg; 00447 } 00448 #endif 00449 00450 template<typename _CharT, typename _InIter> 00451 _InIter 00452 num_get<_CharT, _InIter>:: 00453 do_get(iter_type __beg, iter_type __end, ios_base& __io, 00454 ios_base::iostate& __err, unsigned short& __v) const 00455 { 00456 // Stage 1: extract and determine the conversion specifier. 00457 // Assuming leading zeros eliminated, thus the size of 32 for 00458 // integral types. 00459 char __xtrc[_M_extract_buffer_length]= {'\0'}; 00460 int __base; 00461 _M_extract(__beg, __end, __io, __err, __xtrc, __base, false); 00462 00463 // Stage 2: convert and store results. 00464 char* __sanity; 00465 errno = 0; 00466 unsigned long __ul = strtoul(__xtrc, &__sanity, __base); 00467 if (!(__err & ios_base::failbit) 00468 && __sanity != __xtrc && *__sanity == '\0' && errno == 0 00469 && __ul <= USHRT_MAX) 00470 __v = static_cast<unsigned short>(__ul); 00471 else 00472 __err |= ios_base::failbit; 00473 00474 return __beg; 00475 } 00476 00477 template<typename _CharT, typename _InIter> 00478 _InIter 00479 num_get<_CharT, _InIter>:: 00480 do_get(iter_type __beg, iter_type __end, ios_base& __io, 00481 ios_base::iostate& __err, unsigned int& __v) const 00482 { 00483 // Stage 1: extract and determine the conversion specifier. 00484 // Assuming leading zeros eliminated, thus the size of 32 for 00485 // integral types. 00486 char __xtrc[_M_extract_buffer_length]= {'\0'}; 00487 int __base; 00488 _M_extract(__beg, __end, __io, __err, __xtrc, __base, false); 00489 00490 // Stage 2: convert and store results. 00491 char* __sanity; 00492 errno = 0; 00493 unsigned long __ul = strtoul(__xtrc, &__sanity, __base); 00494 if (!(__err & ios_base::failbit) 00495 && __sanity != __xtrc && *__sanity == '\0' && errno == 0 00496 && __ul <= UINT_MAX) 00497 __v = static_cast<unsigned int>(__ul); 00498 else 00499 __err |= ios_base::failbit; 00500 00501 return __beg; 00502 } 00503 00504 template<typename _CharT, typename _InIter> 00505 _InIter 00506 num_get<_CharT, _InIter>:: 00507 do_get(iter_type __beg, iter_type __end, ios_base& __io, 00508 ios_base::iostate& __err, unsigned long& __v) const 00509 { 00510 // Stage 1: extract and determine the conversion specifier. 00511 // Assuming leading zeros eliminated, thus the size of 32 for 00512 // integral types. 00513 char __xtrc[_M_extract_buffer_length] = {'\0'}; 00514 int __base; 00515 _M_extract(__beg, __end, __io, __err, __xtrc, __base, false); 00516 00517 // Stage 2: convert and store results. 00518 char* __sanity; 00519 errno = 0; 00520 unsigned long __ul = strtoul(__xtrc, &__sanity, __base); 00521 if (!(__err & ios_base::failbit) 00522 && __sanity != __xtrc && *__sanity == '\0' && errno == 0) 00523 __v = __ul; 00524 else 00525 __err |= ios_base::failbit; 00526 00527 return __beg; 00528 } 00529 00530 #ifdef _GLIBCPP_USE_LONG_LONG 00531 template<typename _CharT, typename _InIter> 00532 _InIter 00533 num_get<_CharT, _InIter>:: 00534 do_get(iter_type __beg, iter_type __end, ios_base& __io, 00535 ios_base::iostate& __err, unsigned long long& __v) const 00536 { 00537 // Stage 1: extract and determine the conversion specifier. 00538 // Assuming leading zeros eliminated, thus the size of 32 for 00539 // integral types. 00540 char __xtrc[_M_extract_buffer_length]= {'\0'}; 00541 int __base; 00542 _M_extract(__beg, __end, __io, __err, __xtrc, __base, false); 00543 00544 // Stage 2: convert and store results. 00545 char* __sanity; 00546 errno = 0; 00547 unsigned long long __ull = strtoull(__xtrc, &__sanity, __base); 00548 if (!(__err & ios_base::failbit) 00549 && __sanity != __xtrc && *__sanity == '\0' && errno == 0) 00550 __v = __ull; 00551 else 00552 __err |= ios_base::failbit; 00553 00554 return __beg; 00555 } 00556 #endif 00557 00558 template<typename _CharT, typename _InIter> 00559 _InIter 00560 num_get<_CharT, _InIter>:: 00561 do_get(iter_type __beg, iter_type __end, ios_base& __io, 00562 ios_base::iostate& __err, float& __v) const 00563 { 00564 // Stage 1: extract and determine the conversion specifier. 00565 // Assuming leading zeros eliminated, thus the size of 256 for 00566 // floating-point types. 00567 char __xtrc[_M_extract_buffer_length]= {'\0'}; 00568 int __base; 00569 _M_extract(__beg, __end, __io, __err, __xtrc, __base, true); 00570 00571 // Stage 2: convert and store results. 00572 char* __sanity; 00573 errno = 0; 00574 #ifdef _GLIBCPP_USE_C99 00575 float __f = strtof(__xtrc, &__sanity); 00576 #else 00577 float __f = static_cast<float>(strtod(__xtrc, &__sanity)); 00578 #endif 00579 if (!(__err & ios_base::failbit) 00580 && __sanity != __xtrc && *__sanity == '\0' && errno == 0) 00581 __v = __f; 00582 else 00583 __err |= ios_base::failbit; 00584 00585 return __beg; 00586 } 00587 00588 template<typename _CharT, typename _InIter> 00589 _InIter 00590 num_get<_CharT, _InIter>:: 00591 do_get(iter_type __beg, iter_type __end, ios_base& __io, 00592 ios_base::iostate& __err, double& __v) const 00593 { 00594 // Stage 1: extract and determine the conversion specifier. 00595 // Assuming leading zeros eliminated, thus the size of 256 for 00596 // floating-point types. 00597 char __xtrc[_M_extract_buffer_length]= {'\0'}; 00598 int __base; 00599 _M_extract(__beg, __end, __io, __err, __xtrc, __base, true); 00600 00601 // Stage 2: convert and store results. 00602 char* __sanity; 00603 errno = 0; 00604 double __d = strtod(__xtrc, &__sanity); 00605 if (!(__err & ios_base::failbit) 00606 && __sanity != __xtrc && *__sanity == '\0' && errno == 0) 00607 __v = __d; 00608 else 00609 __err |= ios_base::failbit; 00610 00611 return __beg; 00612 } 00613 00614 #if defined(_GLIBCPP_USE_C99) && !defined(__hpux) 00615 template<typename _CharT, typename _InIter> 00616 _InIter 00617 num_get<_CharT, _InIter>:: 00618 do_get(iter_type __beg, iter_type __end, ios_base& __io, 00619 ios_base::iostate& __err, long double& __v) const 00620 { 00621 // Stage 1: extract and determine the conversion specifier. 00622 // Assuming leading zeros eliminated, thus the size of 256 for 00623 // floating-point types. 00624 char __xtrc[_M_extract_buffer_length]= {'\0'}; 00625 int __base; 00626 _M_extract(__beg, __end, __io, __err, __xtrc, __base, true); 00627 00628 // Stage 2: convert and store results. 00629 char* __sanity; 00630 errno = 0; 00631 long double __ld = strtold(__xtrc, &__sanity); 00632 if (!(__err & ios_base::failbit) 00633 && __sanity != __xtrc && *__sanity == '\0' && errno == 0) 00634 __v = __ld; 00635 else 00636 __err |= ios_base::failbit; 00637 00638 return __beg; 00639 } 00640 #else 00641 template<typename _CharT, typename _InIter> 00642 _InIter 00643 num_get<_CharT, _InIter>:: 00644 do_get(iter_type __beg, iter_type __end, ios_base& __io, 00645 ios_base::iostate& __err, long double& __v) const 00646 { 00647 // Stage 1: extract 00648 char __xtrc[_M_extract_buffer_length]= {'\0'}; 00649 int __base; 00650 _M_extract(__beg, __end, __io, __err, __xtrc, __base, true); 00651 00652 // Stage 2: determine a conversion specifier. 00653 ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield; 00654 const char* __conv; 00655 if (__basefield == ios_base::oct) 00656 __conv = "%Lo"; 00657 else if (__basefield == ios_base::hex) 00658 __conv = "%LX"; 00659 else if (__basefield == 0) 00660 __conv = "%Li"; 00661 else 00662 __conv = "%Lg"; 00663 00664 // Stage 3: store results. 00665 long double __ld; 00666 int __p = sscanf(__xtrc, __conv, &__ld); 00667 if (__p 00668 && static_cast<typename __traits_type::int_type>(__p) 00669 != __traits_type::eof()) 00670 __v = __ld; 00671 else 00672 __err |= ios_base::failbit; 00673 00674 return __beg; 00675 } 00676 #endif 00677 00678 template<typename _CharT, typename _InIter> 00679 _InIter 00680 num_get<_CharT, _InIter>:: 00681 do_get(iter_type __beg, iter_type __end, ios_base& __io, 00682 ios_base::iostate& __err, void*& __v) const 00683 { 00684 // Prepare for hex formatted input 00685 typedef ios_base::fmtflags fmtflags; 00686 fmtflags __fmt = __io.flags(); 00687 fmtflags __fmtmask = ~(ios_base::showpos | ios_base::basefield 00688 | ios_base::uppercase | ios_base::internal); 00689 __io.flags(__fmt & __fmtmask | (ios_base::hex | ios_base::showbase)); 00690 00691 // Stage 1: extract and determine the conversion specifier. 00692 // Assuming leading zeros eliminated, thus the size of 32 for 00693 // integral types. 00694 char __xtrc[_M_extract_buffer_length]= {'\0'}; 00695 int __base; 00696 _M_extract(__beg, __end, __io, __err, __xtrc, __base, false); 00697 00698 // Stage 2: convert and store results. 00699 char* __sanity; 00700 errno = 0; 00701 void* __vp = reinterpret_cast<void*>(strtoul(__xtrc, &__sanity, __base)); 00702 if (!(__err & ios_base::failbit) 00703 && __sanity != __xtrc && *__sanity == '\0' && errno == 0) 00704 __v = __vp; 00705 else 00706 __err |= ios_base::failbit; 00707 00708 // Reset from hex formatted input 00709 __io.flags(__fmt); 00710 return __beg; 00711 } 00712 00713 // __pad is specialized for ostreambuf_iterator, random access iterator. 00714 template <typename _CharT, typename _OutIter> 00715 inline _OutIter 00716 __pad(_OutIter __s, _CharT __fill, int __padding); 00717 00718 template <typename _CharT, typename _RaIter> 00719 _RaIter 00720 __pad(_RaIter __s, _CharT __fill, int __padding, 00721 random_access_iterator_tag) 00722 { 00723 fill_n(__s, __fill); 00724 return __s + __padding; 00725 } 00726 00727 template <typename _CharT, typename _OutIter, typename _Tag> 00728 _OutIter 00729 __pad(_OutIter __s, _CharT __fill, int __padding, _Tag) 00730 { 00731 while (--__padding >= 0) { *__s = __fill; ++__s; } 00732 return __s; 00733 } 00734 00735 template <typename _CharT, typename _OutIter> 00736 inline _OutIter 00737 __pad(_OutIter __s, _CharT __fill, int __padding) 00738 { 00739 return __pad(__s, __fill, __padding, 00740 typename iterator_traits<_OutIter>::iterator_category()); 00741 } 00742 00743 template <typename _CharT, typename _OutIter> 00744 _OutIter 00745 __pad_numeric(_OutIter __s, ios_base::fmtflags /*__flags*/, 00746 _CharT /*__fill*/, int /*__width*/, 00747 _CharT const* /*__first*/, _CharT const* /*__middle*/, 00748 _CharT const* /*__last*/) 00749 { 00750 // XXX Not currently done: non streambuf_iterator 00751 return __s; 00752 } 00753 00754 // Partial specialization for ostreambuf_iterator. 00755 template <typename _CharT> 00756 ostreambuf_iterator<_CharT> 00757 __pad_numeric(ostreambuf_iterator<_CharT> __s, ios_base::fmtflags __flags, 00758 _CharT __fill, int __width, _CharT const* __first, 00759 _CharT const* __middle, _CharT const* __last) 00760 { 00761 typedef ostreambuf_iterator<_CharT> __out_iter; 00762 int __padding = __width - (__last - __first); 00763 if (__padding < 0) 00764 __padding = 0; 00765 ios_base::fmtflags __aflags = __flags & ios_base::adjustfield; 00766 bool __testfield = __padding == 0 || __aflags == ios_base::left 00767 || __aflags == ios_base::internal; 00768 00769 // This was needlessly complicated. 00770 if (__first != __middle) 00771 { 00772 if (!__testfield) 00773 { 00774 __pad(__s, __fill, __padding); 00775 __padding = 0; 00776 } 00777 copy(__first, __middle, __s); 00778 } 00779 __out_iter __s2 = __s; 00780 00781 if (__padding && __aflags != ios_base::left) 00782 { 00783 __pad(__s2, __fill, __padding); 00784 __padding = 0; 00785 } 00786 __out_iter __s3 = copy(__middle, __last, __s2); 00787 if (__padding) 00788 __pad(__s3, __fill, __padding); 00789 return __s3; 00790 } 00791 00792 template <typename _CharT, typename _OutIter> 00793 _OutIter 00794 num_put<_CharT, _OutIter>:: 00795 do_put(iter_type __s, ios_base& __io, char_type __fill, bool __v) const 00796 { 00797 const _Format_cache<_CharT>* __fmt = _Format_cache<_CharT>::_S_get(__io); 00798 ios_base::fmtflags __flags = __io.flags(); 00799 00800 if ((__flags & ios_base::boolalpha) == 0) 00801 { 00802 unsigned long __uv = __v; 00803 return __output_integer(__s, __io, __fill, false, __uv); 00804 } 00805 else 00806 { 00807 const char_type* __first; 00808 const char_type* __last; 00809 if (__v) 00810 { 00811 __first = __fmt->_M_truename.data(); 00812 __last = __first + __fmt->_M_truename.size(); 00813 } 00814 else 00815 { 00816 __first = __fmt->_M_falsename.data(); 00817 __last = __first + __fmt->_M_falsename.size(); 00818 } 00819 copy(__first, __last, __s); 00820 } 00821 return __s; 00822 } 00823 00824 // __group_digits inserts "group separator" characters into an array 00825 // of characters. It's recursive, one iteration per group. It moves 00826 // the characters in the buffer this way: "xxxx12345" -> "12,345xxx". 00827 // Call this only with __grouping != __grend. 00828 template <typename _CharT> 00829 _CharT* 00830 __group_digits(_CharT* __s, _CharT __grsep, char const* __grouping, 00831 char const* __grend, _CharT const* __first, 00832 _CharT const* __last) 00833 { 00834 if (__last - __first > *__grouping) 00835 { 00836 __s = __group_digits(__s, __grsep, 00837 (__grouping + 1 == __grend ? __grouping : __grouping + 1), 00838 __grend, __first, __last - *__grouping); 00839 __first = __last - *__grouping; 00840 *__s++ = __grsep; 00841 } 00842 do 00843 { 00844 *__s++ = *__first++; 00845 } 00846 while (__first != __last); 00847 return __s; 00848 } 00849 00850 template <typename _CharT, typename _OutIter, typename _ValueT> 00851 _OutIter 00852 __output_integer(_OutIter __s, ios_base& __io, _CharT __fill, bool __neg, 00853 _ValueT __v) 00854 { 00855 // Leave room for "+/-," "0x," and commas. 00856 const long _M_room = numeric_limits<_ValueT>::digits10 * 2 + 4; 00857 _CharT __digits[_M_room]; 00858 _CharT* __front = __digits + _M_room; 00859 ios_base::fmtflags __flags = __io.flags(); 00860 const _Format_cache<_CharT>* __fmt = _Format_cache<_CharT>::_S_get(__io); 00861 char const* __table = __fmt->_S_literals + __fmt->_S_digits; 00862 00863 ios_base::fmtflags __basefield = (__flags & __io.basefield); 00864 _CharT* __sign_end = __front; 00865 if (__basefield == ios_base::hex) 00866 { 00867 if (__flags & ios_base::uppercase) 00868 __table += 16; // use ABCDEF 00869 do 00870 *--__front = __table[__v & 15]; 00871 while ((__v >>= 4) != 0); 00872 __sign_end = __front; 00873 if (__flags & ios_base::showbase) 00874 { 00875 *--__front = __fmt->_S_literals[__fmt->_S_x + 00876 ((__flags & ios_base::uppercase) ? 1 : 0)]; 00877 *--__front = __table[0]; 00878 } 00879 } 00880 else if (__basefield == ios_base::oct) 00881 { 00882 do 00883 *--__front = __table[__v & 7]; 00884 while ((__v >>= 3) != 0); 00885 if (__flags & ios_base::showbase 00886 && static_cast<char>(*__front) != __table[0]) 00887 *--__front = __table[0]; 00888 __sign_end = __front; 00889 } 00890 else 00891 { 00892 // NB: This is _lots_ faster than using ldiv. 00893 do 00894 *--__front = __table[__v % 10]; 00895 while ((__v /= 10) != 0); 00896 __sign_end = __front; 00897 // NB: ios_base:hex || ios_base::oct assumed to be unsigned. 00898 if (__neg || (__flags & ios_base::showpos)) 00899 *--__front = __fmt->_S_literals[__fmt->_S_plus - __neg]; 00900 } 00901 00902 // XXX should specialize! 00903 if (!__fmt->_M_use_grouping && !__io.width()) 00904 return copy(__front, __digits + _M_room, __s); 00905 00906 if (!__fmt->_M_use_grouping) 00907 return __pad_numeric(__s, __flags, __fill, __io.width(0), 00908 __front, __sign_end, __digits + _M_room); 00909 00910 _CharT* __p = __digits; 00911 while (__front < __sign_end) 00912 *__p++ = *__front++; 00913 const char* __gr = __fmt->_M_grouping.data(); 00914 __front = __group_digits(__p, __fmt->_M_thousands_sep, __gr, 00915 __gr + __fmt->_M_grouping.size(), __sign_end, __digits + _M_room); 00916 return __pad_numeric(__s, __flags, __fill, __io.width(0), 00917 __digits, __p, __front); 00918 } 00919 00920 template <typename _CharT, typename _OutIter> 00921 _OutIter 00922 num_put<_CharT, _OutIter>:: 00923 do_put(iter_type __s, ios_base& __io, char_type __fill, long __v) const 00924 { 00925 unsigned long __uv = __v; 00926 bool __neg = false; 00927 if (__v < 0) 00928 { 00929 __neg = true; 00930 __uv = -__uv; 00931 } 00932 return __output_integer(__s, __io, __fill, __neg, __uv); 00933 } 00934 00935 template <typename _CharT, typename _OutIter> 00936 _OutIter 00937 num_put<_CharT, _OutIter>:: 00938 do_put(iter_type __s, ios_base& __io, char_type __fill, 00939 unsigned long __v) const 00940 { return __output_integer(__s, __io, __fill, false, __v); } 00941 00942 #ifdef _GLIBCPP_USE_LONG_LONG 00943 template <typename _CharT, typename _OutIter> 00944 _OutIter 00945 num_put<_CharT, _OutIter>:: 00946 do_put(iter_type __s, ios_base& __b, char_type __fill, long long __v) const 00947 { 00948 unsigned long long __uv = __v; 00949 bool __neg = false; 00950 if (__v < 0) 00951 { 00952 __neg = true; 00953 __uv = -__uv; 00954 } 00955 return __output_integer(__s, __b, __fill, __neg, __uv); 00956 } 00957 00958 template <typename _CharT, typename _OutIter> 00959 _OutIter 00960 num_put<_CharT, _OutIter>:: 00961 do_put(iter_type __s, ios_base& __io, char_type __fill, 00962 unsigned long long __v) const 00963 { return __output_integer(__s, __io, __fill, false, __v); } 00964 #endif 00965 00966 // Generic helper function 00967 template<typename _CharT, typename _Traits, typename _OutIter> 00968 _OutIter 00969 __output_float(_OutIter __s, ios_base& __io, _CharT __fill, 00970 const char* __sptr, size_t __slen) 00971 { 00972 // XXX Not currently done: non streambuf_iterator 00973 return __s; 00974 } 00975 00976 // Partial specialization for ostreambuf_iterator. 00977 template<typename _CharT, typename _Traits> 00978 ostreambuf_iterator<_CharT, _Traits> 00979 __output_float(ostreambuf_iterator<_CharT, _Traits> __s, ios_base& __io, 00980 _CharT __fill, const char* __sptr, size_t __slen) 00981 { 00982 size_t __padding = __io.width() > streamsize(__slen) ? 00983 __io.width() -__slen : 0; 00984 locale __loc = __io.getloc(); 00985 ctype<_CharT> const& __ct = use_facet<ctype<_CharT> >(__loc); 00986 ios_base::fmtflags __adjfield = __io.flags() & ios_base::adjustfield; 00987 const char* const __eptr = __sptr + __slen; 00988 // [22.2.2.2.2.19] Table 61 00989 if (__adjfield == ios_base::internal) 00990 { 00991 // [22.2.2.2.2.14]; widen() 00992 if (__sptr < __eptr && (*__sptr == '+' || *__sptr == '-')) 00993 { 00994 __s = __ct.widen(*__sptr); 00995 ++__s; 00996 ++__sptr; 00997 } 00998 __s = __pad(__s, __fill, __padding); 00999 __padding = 0; 01000 } 01001 else if (__adjfield != ios_base::left) 01002 { 01003 __s = __pad(__s, __fill, __padding); 01004 __padding = 0; 01005 } 01006 // the "C" locale decimal character 01007 char __decimal_point = *(localeconv()->decimal_point); 01008 const _Format_cache<_CharT>* __fmt = _Format_cache<_CharT>::_S_get(__io); 01009 for (; __sptr != __eptr; ++__s, ++__sptr) 01010 { 01011 // [22.2.2.2.2.17]; decimal point conversion 01012 if (*__sptr == __decimal_point) 01013 __s = __fmt->_M_decimal_point; 01014 // [22.2.2.2.2.14]; widen() 01015 else 01016 __s = __ct.widen(*__sptr); 01017 } 01018 // [22.2.2.2.2.19] Table 61 01019 if (__padding) 01020 __pad(__s, __fill, __padding); 01021 __io.width(0); 01022 return __s; 01023 } 01024 01025 bool 01026 __build_float_format(ios_base& __io, char* __fptr, char __modifier, 01027 streamsize __prec); 01028 01029 template <typename _CharT, typename _OutIter> 01030 _OutIter 01031 num_put<_CharT, _OutIter>:: 01032 do_put(iter_type __s, ios_base& __io, char_type __fill, double __v) const 01033 { 01034 const streamsize __max_prec = numeric_limits<double>::digits10 + 3; 01035 streamsize __prec = __io.precision(); 01036 // Protect against sprintf() buffer overflows. 01037 if (__prec > __max_prec) 01038 __prec = __max_prec; 01039 // The *2 provides for signs, exp, 'E', and pad. 01040 char __sbuf[__max_prec * 2]; 01041 size_t __slen; 01042 // Long enough for the max format spec. 01043 char __fbuf[16]; 01044 if (__build_float_format(__io, __fbuf, 0, __prec)) 01045 __slen = sprintf(__sbuf, __fbuf, __prec, __v); 01046 else 01047 __slen = sprintf(__sbuf, __fbuf, __v); 01048 // [22.2.2.2.2] Stages 2-4. 01049 return __output_float(__s, __io, __fill, __sbuf, __slen); 01050 } 01051 01052 template <typename _CharT, typename _OutIter> 01053 _OutIter 01054 num_put<_CharT, _OutIter>:: 01055 do_put(iter_type __s, ios_base& __io, char_type __fill, 01056 long double __v) const 01057 { 01058 const streamsize __max_prec = numeric_limits<long double>::digits10 + 3; 01059 streamsize __prec = __io.precision(); 01060 // Protect against sprintf() buffer overflows. 01061 if (__prec > __max_prec) 01062 __prec = __max_prec; 01063 // The *2 provides for signs, exp, 'E', and pad. 01064 char __sbuf[__max_prec * 2]; 01065 size_t __slen; 01066 // Long enough for the max format spec. 01067 char __fbuf[16]; 01068 // 'L' as per [22.2.2.2.2] Table 59 01069 if (__build_float_format(__io, __fbuf, 'L', __prec)) 01070 __slen = sprintf(__sbuf, __fbuf, __prec, __v); 01071 else 01072 __slen = sprintf(__sbuf, __fbuf, __v); 01073 // [22.2.2.2.2] Stages 2-4 01074 return __output_float(__s, __io, __fill, __sbuf, __slen); 01075 } 01076 01077 template <typename _CharT, typename _OutIter> 01078 _OutIter 01079 num_put<_CharT, _OutIter>:: 01080 do_put(iter_type __s, ios_base& __io, char_type __fill, 01081 const void* __v) const 01082 { 01083 typedef ios_base::fmtflags fmtflags; 01084 fmtflags __fmt = __io.flags(); 01085 fmtflags __fmtmask = ~(ios_base::showpos | ios_base::basefield 01086 | ios_base::uppercase | ios_base::internal); 01087 __io.flags(__fmt & __fmtmask | (ios_base::hex | ios_base::showbase)); 01088 try { 01089 _OutIter __s2 = __output_integer(__s, __io, __fill, false, 01090 reinterpret_cast<unsigned long>(__v)); 01091 __io.flags(__fmt); 01092 return __s2; 01093 } 01094 catch (...) { 01095 __io.flags(__fmt); 01096 __throw_exception_again; 01097 } 01098 } 01099 01100 // Support for time_get: 01101 // Note that these partial specializations could, and maybe should, 01102 // be changed to full specializations (by eliminating the _Dummy 01103 // argument) and moved to a .cc file. 01104 template<typename _CharT, typename _Dummy = int> 01105 struct _Weekdaynames; 01106 01107 template<typename _Dummy> 01108 struct _Weekdaynames<char, _Dummy> 01109 { static const char* const _S_names[14]; }; 01110 01111 template<typename _Dummy> 01112 const char* const 01113 _Weekdaynames<char, _Dummy>::_S_names[14] = 01114 { 01115 "Sun", "Sunday", 01116 "Mon", "Monday", "Tue", "Tuesday", "Wed", "Wednesday", 01117 "Thu", "Thursday", "Fri", "Friday", "Sat", "Saturday" 01118 }; 01119 01120 #ifdef _GLIBCPP_USE_WCHAR_T 01121 template<typename _Dummy> 01122 struct _Weekdaynames<wchar_t, _Dummy> 01123 { static const wchar_t* const _S_names[14]; }; 01124 01125 template<typename _Dummy> 01126 const wchar_t* const 01127 _Weekdaynames<wchar_t, _Dummy>::_S_names[14] = 01128 { 01129 L"Sun", L"Sunday", 01130 L"Mon", L"Monday", L"Tue", L"Tuesday", L"Wed", L"Wednesday", 01131 L"Thu", L"Thursday", L"Fri", L"Friday", L"Sat", L"Saturday" 01132 }; 01133 #endif 01134 01135 template<typename _CharT, typename _Dummy = int> 01136 struct _Monthnames; 01137 01138 template<typename _Dummy> 01139 struct _Monthnames<char,_Dummy> 01140 { static const char* const _S_names[24]; }; 01141 01142 template<typename _Dummy> 01143 const char* const 01144 _Monthnames<char,_Dummy>::_S_names[24] = 01145 { 01146 "Jan", "January", "Feb", "February", "Mar", "March", 01147 "Apr", "April", "May", "May", "Jun", "June", 01148 "Jul", "July", "Aug", "August", "Sep", "September", 01149 "Oct", "October", "Nov", "November", "Dec", "December" 01150 }; 01151 01152 #ifdef _GLIBCPP_USE_WCHAR_T 01153 template<typename _Dummy> 01154 struct _Monthnames<wchar_t, _Dummy> 01155 { static const wchar_t* const _S_names[24]; }; 01156 01157 template<typename _Dummy> 01158 const wchar_t* const 01159 _Monthnames<wchar_t,_Dummy>::_S_names[24] = 01160 { 01161 L"Jan", L"January", L"Feb", L"February", L"Mar", L"March", 01162 L"Apr", L"April", L"May", L"May", L"Jun", L"June", 01163 L"Jul", L"July", L"Aug", L"August", L"Sep", L"September", 01164 L"Oct", L"October", L"Nov", L"November", L"Dec", L"December" 01165 }; 01166 #endif 01167 01168 template<typename _CharT, typename _InIter> 01169 _InIter 01170 time_get<_CharT, _InIter>:: 01171 do_get_weekday(iter_type __s, iter_type __end, 01172 ios_base& __io, ios_base::iostate& __err, tm* __t) const 01173 { 01174 if (!_M_daynames) 01175 { 01176 _M_daynames = new basic_string<_CharT>[14]; 01177 for (int __i = 0; __i < 14; ++__i) 01178 _M_daynames[__i] = _Weekdaynames<_CharT>::_S_names[__i]; 01179 } 01180 bool __at_eof = false; 01181 int __remain = 0; 01182 int __matches[14]; 01183 iter_type __out = __match_parallel(__s, __end, 14, _M_daynames, 01184 __matches, __remain, __at_eof); 01185 __err = ios_base::iostate(0); 01186 if (__at_eof) __err |= __io.eofbit; 01187 if (__remain == 1 || 01188 __remain == 2 && (__matches[0]>>1) == (__matches[1]>>1)) 01189 __t->tm_wday = (__matches[0]>>1); 01190 else 01191 __err |= __io.failbit; 01192 return __out; 01193 } 01194 01195 template<typename _CharT, typename _InIter> 01196 _InIter 01197 time_get<_CharT, _InIter>:: 01198 do_get_monthname(iter_type __s, iter_type __end, 01199 ios_base& __io, ios_base::iostate& __err, tm* __t) const 01200 { 01201 if (!_M_monthnames) 01202 { 01203 _M_monthnames = new basic_string<_CharT>[24]; 01204 for (int __i = 0; __i < 24; ++__i) 01205 _M_monthnames[__i] = _Monthnames<_CharT>::_S_names[__i]; 01206 } 01207 bool __at_eof = false; 01208 int __remain = 0; 01209 int __matches[24]; 01210 iter_type __out = __match_parallel( __s, __end, 24, _M_monthnames, 01211 __matches, __remain, __at_eof); 01212 __err = ios_base::iostate(0); 01213 if (__at_eof) __err |= __io.eofbit; 01214 if (__remain == 1 || 01215 __remain == 2 && (__matches[0]>>1) == (__matches[1]>>1)) 01216 __t->tm_mon = (__matches[0]>>1); 01217 else 01218 __err |= __io.failbit; 01219 return __out; 01220 } 01221 } // std:: 01222 01223 #endif /* _CPP_BITS_LOCFACETS_TCC */ 01224 01225 // Local Variables: 01226 // mode:c++ 01227 // End: Generated on Mon Apr 8 03:11:29 2002 for libstdc++-v3 Source by ![]() |