locale_facets.tcc

00001 // Locale support -*- C++ -*- 00002 00003 // Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 00004 // Free Software Foundation, Inc. 00005 // 00006 // This file is part of the GNU ISO C++ Library. This library is free 00007 // software; you can redistribute it and/or modify it under the 00008 // terms of the GNU General Public License as published by the 00009 // Free Software Foundation; either version 2, or (at your option) 00010 // any later version. 00011 00012 // This library is distributed in the hope that it will be useful, 00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 // GNU General Public License for more details. 00016 00017 // You should have received a copy of the GNU General Public License along 00018 // with this library; see the file COPYING. If not, write to the Free 00019 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, 00020 // USA. 00021 00022 // As a special exception, you may use this file as part of a free software 00023 // library without restriction. Specifically, if other files instantiate 00024 // templates or use macros or inline functions from this file, or you compile 00025 // this file and link it with other files to produce an executable, this 00026 // file does not by itself cause the resulting executable to be covered by 00027 // the GNU General Public License. This exception does not however 00028 // invalidate any other reasons why the executable file might be covered by 00029 // the GNU General Public License. 00030 00031 // Warning: this file is not meant for user inclusion. Use <locale>. 00032 00033 #ifndef _CPP_BITS_LOCFACETS_TCC 00034 #define _CPP_BITS_LOCFACETS_TCC 1 00035 00036 #pragma GCC system_header 00037 00038 #include <cerrno> 00039 #include <clocale> // For localeconv 00040 #include <cstdlib> // For strof, strtold 00041 #include <cmath> // For ceil 00042 #include <cctype> // For isspace 00043 #include <limits> // For numeric_limits 00044 #include <bits/streambuf_iterator.h> 00045 #include <typeinfo> // For bad_cast. 00046 00047 namespace std 00048 { 00049 template<typename _Facet> 00050 locale 00051 locale::combine(const locale& __other) const 00052 { 00053 _Impl* __tmp = new _Impl(*_M_impl, 1); 00054 __tmp->_M_replace_facet(__other._M_impl, &_Facet::id); 00055 return locale(__tmp); 00056 } 00057 00058 template<typename _CharT, typename _Traits, typename _Alloc> 00059 bool 00060 locale::operator()(const basic_string<_CharT, _Traits, _Alloc>& __s1, 00061 const basic_string<_CharT, _Traits, _Alloc>& __s2) const 00062 { 00063 typedef std::collate<_CharT> __collate_type; 00064 const __collate_type& __collate = use_facet<__collate_type>(*this); 00065 return (__collate.compare(__s1.data(), __s1.data() + __s1.length(), 00066 __s2.data(), __s2.data() + __s2.length()) < 0); 00067 } 00068 00069 template<typename _Facet> 00070 const _Facet& 00071 use_facet(const locale& __loc) 00072 { 00073 size_t __i = _Facet::id._M_id(); 00074 locale::facet** __facets = __loc._M_impl->_M_facets; 00075 if (!(__i < __loc._M_impl->_M_facets_size && __facets[__i])) 00076 __throw_bad_cast(); 00077 return static_cast<const _Facet&>(*__facets[__i]); 00078 } 00079 00080 template<typename _Facet> 00081 bool 00082 has_facet(const locale& __loc) throw() 00083 { 00084 size_t __i = _Facet::id._M_id(); 00085 locale::facet** __facets = __loc._M_impl->_M_facets; 00086 return (__i < __loc._M_impl->_M_facets_size && __facets[__i]); 00087 } 00088 00089 00090 // Stage 1: Determine a conversion specifier. 00091 template<typename _CharT, typename _InIter> 00092 _InIter 00093 num_get<_CharT, _InIter>:: 00094 _M_extract_float(_InIter __beg, _InIter __end, ios_base& __io, 00095 ios_base::iostate& __err, string& __xtrc) const 00096 { 00097 typedef char_traits<_CharT> __traits_type; 00098 const locale __loc = __io.getloc(); 00099 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 00100 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); 00101 00102 // First check for sign. 00103 const char_type __plus = __ctype.widen('+'); 00104 const char_type __minus = __ctype.widen('-'); 00105 int __pos = 0; 00106 char_type __c = *__beg; 00107 if ((__traits_type::eq(__c, __plus) || __traits_type::eq(__c, __minus)) 00108 && __beg != __end) 00109 { 00110 __xtrc += __ctype.narrow(__c, char()); 00111 ++__pos; 00112 __c = *(++__beg); 00113 } 00114 00115 // Next, strip leading zeros. 00116 const char_type __zero = __ctype.widen(_S_atoms[_M_zero]); 00117 bool __found_zero = false; 00118 while (__traits_type::eq(__c, __zero) && __beg != __end) 00119 { 00120 __c = *(++__beg); 00121 __found_zero = true; 00122 } 00123 if (__found_zero) 00124 { 00125 __xtrc += _S_atoms[_M_zero]; 00126 ++__pos; 00127 } 00128 00129 // Only need acceptable digits for floating point numbers. 00130 const size_t __len = _M_E - _M_zero + 1; 00131 char_type __watoms[__len]; 00132 __ctype.widen(_S_atoms, _S_atoms + __len, __watoms); 00133 bool __found_dec = false; 00134 bool __found_sci = false; 00135 const char_type __dec = __np.decimal_point(); 00136 00137 string __found_grouping; 00138 const string __grouping = __np.grouping(); 00139 bool __check_grouping = __grouping.size(); 00140 int __sep_pos = 0; 00141 const char_type __sep = __np.thousands_sep(); 00142 00143 while (__beg != __end) 00144 { 00145 // Only look in digits. 00146 const char_type* __p = __traits_type::find(__watoms, 10, __c); 00147 00148 // NB: strchr returns true for __c == 0x0 00149 if (__p && !__traits_type::eq(__c, char_type())) 00150 { 00151 // Try first for acceptable digit; record it if found. 00152 ++__pos; 00153 __xtrc += _S_atoms[__p - __watoms]; 00154 ++__sep_pos; 00155 __c = *(++__beg); 00156 } 00157 else if (__traits_type::eq(__c, __sep) 00158 && __check_grouping && !__found_dec) 00159 { 00160 // NB: Thousands separator at the beginning of a string 00161 // is a no-no, as is two consecutive thousands separators. 00162 if (__sep_pos) 00163 { 00164 __found_grouping += static_cast<char>(__sep_pos); 00165 __sep_pos = 0; 00166 __c = *(++__beg); 00167 } 00168 else 00169 { 00170 __err |= ios_base::failbit; 00171 break; 00172 } 00173 } 00174 else if (__traits_type::eq(__c, __dec) && !__found_dec) 00175 { 00176 // According to the standard, if no grouping chars are seen, 00177 // no grouping check is applied. Therefore __found_grouping 00178 // must be adjusted only if __dec comes after some __sep. 00179 if (__found_grouping.size()) 00180 __found_grouping += static_cast<char>(__sep_pos); 00181 ++__pos; 00182 __xtrc += '.'; 00183 __c = *(++__beg); 00184 __found_dec = true; 00185 } 00186 else if ((__traits_type::eq(__c, __watoms[_M_e]) 00187 || __traits_type::eq(__c, __watoms[_M_E])) 00188 && !__found_sci && __pos) 00189 { 00190 // Scientific notation. 00191 ++__pos; 00192 __xtrc += __ctype.narrow(__c, char()); 00193 __c = *(++__beg); 00194 00195 // Remove optional plus or minus sign, if they exist. 00196 if (__traits_type::eq(__c, __plus) 00197 || __traits_type::eq(__c, __minus)) 00198 { 00199 ++__pos; 00200 __xtrc += __ctype.narrow(__c, char()); 00201 __c = *(++__beg); 00202 } 00203 __found_sci = true; 00204 } 00205 else 00206 // Not a valid input item. 00207 break; 00208 } 00209 00210 // Digit grouping is checked. If grouping and found_grouping don't 00211 // match, then get very very upset, and set failbit. 00212 if (__check_grouping && __found_grouping.size()) 00213 { 00214 // Add the ending grouping if a decimal wasn't found. 00215 if (!__found_dec) 00216 __found_grouping += static_cast<char>(__sep_pos); 00217 if (!__verify_grouping(__grouping, __found_grouping)) 00218 __err |= ios_base::failbit; 00219 } 00220 00221 // Finish up 00222 __xtrc += char(); 00223 if (__beg == __end) 00224 __err |= ios_base::eofbit; 00225 return __beg; 00226 } 00227 00228 // Stage 1: Determine a conversion specifier. 00229 template<typename _CharT, typename _InIter> 00230 _InIter 00231 num_get<_CharT, _InIter>:: 00232 _M_extract_int(_InIter __beg, _InIter __end, ios_base& __io, 00233 ios_base::iostate& __err, string& __xtrc, int& __base) const 00234 { 00235 typedef char_traits<_CharT> __traits_type; 00236 const locale __loc = __io.getloc(); 00237 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 00238 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); 00239 00240 // NB: Iff __basefield == 0, this can change based on contents. 00241 ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield; 00242 if (__basefield == ios_base::oct) 00243 __base = 8; 00244 else if (__basefield == ios_base::hex) 00245 __base = 16; 00246 else 00247 __base = 10; 00248 00249 // First check for sign. 00250 int __pos = 0; 00251 char_type __c = *__beg; 00252 const char_type __plus = __ctype.widen('+'); 00253 const char_type __minus = __ctype.widen('-'); 00254 00255 if ((__traits_type::eq(__c, __plus) || __traits_type::eq(__c, __minus)) 00256 && __beg != __end) 00257 { 00258 __xtrc += __ctype.narrow(__c, char()); 00259 ++__pos; 00260 __c = *(++__beg); 00261 } 00262 00263 // Next, strip leading zeros and check required digits for base formats. 00264 const char_type __zero = __ctype.widen(_S_atoms[_M_zero]); 00265 const char_type __x = __ctype.widen('x'); 00266 const char_type __X = __ctype.widen('X'); 00267 if (__base == 10) 00268 { 00269 bool __found_zero = false; 00270 while (__traits_type::eq(__c, __zero) && __beg != __end) 00271 { 00272 __c = *(++__beg); 00273 __found_zero = true; 00274 } 00275 if (__found_zero) 00276 { 00277 __xtrc += _S_atoms[_M_zero]; 00278 ++__pos; 00279 if (__basefield == 0) 00280 { 00281 if ((__traits_type::eq(__c, __x) 00282 || __traits_type::eq(__c, __X)) 00283 && __beg != __end) 00284 { 00285 __xtrc += __ctype.narrow(__c, char()); 00286 ++__pos; 00287 __c = *(++__beg); 00288 __base = 16; 00289 } 00290 else 00291 __base = 8; 00292 } 00293 } 00294 } 00295 else if (__base == 16) 00296 { 00297 if (__traits_type::eq(__c, __zero) && __beg != __end) 00298 { 00299 __xtrc += _S_atoms[_M_zero]; 00300 ++__pos; 00301 __c = *(++__beg); 00302 if ((__traits_type::eq(__c, __x) || __traits_type::eq(__c, __X)) 00303 && __beg != __end) 00304 { 00305 __xtrc += __ctype.narrow(__c, char()); 00306 ++__pos; 00307 __c = *(++__beg); 00308 } 00309 } 00310 } 00311 00312 // At this point, base is determined. If not hex, only allow 00313 // base digits as valid input. 00314 size_t __len; 00315 if (__base == 16) 00316 __len = _M_size; 00317 else 00318 __len = __base; 00319 00320 // Extract. 00321 char_type __watoms[_M_size]; 00322 __ctype.widen(_S_atoms, _S_atoms + __len, __watoms); 00323 string __found_grouping; 00324 const string __grouping = __np.grouping(); 00325 bool __check_grouping = __grouping.size(); 00326 int __sep_pos = 0; 00327 const char_type __sep = __np.thousands_sep(); 00328 while (__beg != __end) 00329 { 00330 const char_type* __p = __traits_type::find(__watoms, __len, __c); 00331 00332 // NB: strchr returns true for __c == 0x0 00333 if (__p && !__traits_type::eq(__c, char_type())) 00334 { 00335 // Try first for acceptable digit; record it if found. 00336 __xtrc += _S_atoms[__p - __watoms]; 00337 ++__pos; 00338 ++__sep_pos; 00339 __c = *(++__beg); 00340 } 00341 else if (__traits_type::eq(__c, __sep) && __check_grouping) 00342 { 00343 // NB: Thousands separator at the beginning of a string 00344 // is a no-no, as is two consecutive thousands separators. 00345 if (__sep_pos) 00346 { 00347 __found_grouping += static_cast<char>(__sep_pos); 00348 __sep_pos = 0; 00349 __c = *(++__beg); 00350 } 00351 else 00352 { 00353 __err |= ios_base::failbit; 00354 break; 00355 } 00356 } 00357 else 00358 // Not a valid input item. 00359 break; 00360 } 00361 00362 // Digit grouping is checked. If grouping and found_grouping don't 00363 // match, then get very very upset, and set failbit. 00364 if (__check_grouping && __found_grouping.size()) 00365 { 00366 // Add the ending grouping. 00367 __found_grouping += static_cast<char>(__sep_pos); 00368 if (!__verify_grouping(__grouping, __found_grouping)) 00369 __err |= ios_base::failbit; 00370 } 00371 00372 // Finish up. 00373 __xtrc += char(); 00374 if (__beg == __end) 00375 __err |= ios_base::eofbit; 00376 return __beg; 00377 } 00378 00379 #ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS 00380 //17. Bad bool parsing 00381 template<typename _CharT, typename _InIter> 00382 _InIter 00383 num_get<_CharT, _InIter>:: 00384 do_get(iter_type __beg, iter_type __end, ios_base& __io, 00385 ios_base::iostate& __err, bool& __v) const 00386 { 00387 // Parse bool values as unsigned long 00388 if (!(__io.flags() & ios_base::boolalpha)) 00389 { 00390 // NB: We can't just call do_get(long) here, as it might 00391 // refer to a derived class. 00392 string __xtrc; 00393 int __base; 00394 __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base); 00395 00396 unsigned long __ul; 00397 __convert_to_v(__xtrc.c_str(), __ul, __err, _S_c_locale, __base); 00398 if (!(__err & ios_base::failbit) && __ul <= 1) 00399 __v = __ul; 00400 else 00401 __err |= ios_base::failbit; 00402 } 00403 00404 // Parse bool values as alphanumeric 00405 else 00406 { 00407 typedef char_traits<_CharT> __traits_type; 00408 typedef basic_string<_CharT> __string_type; 00409 00410 locale __loc = __io.getloc(); 00411 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); 00412 const __string_type __true = __np.truename(); 00413 const __string_type __false = __np.falsename(); 00414 const char_type* __trues = __true.c_str(); 00415 const char_type* __falses = __false.c_str(); 00416 const size_t __truen = __true.size() - 1; 00417 const size_t __falsen = __false.size() - 1; 00418 00419 for (size_t __n = 0; __beg != __end; ++__n) 00420 { 00421 char_type __c = *__beg++; 00422 bool __testf = __n <= __falsen 00423 ? __traits_type::eq(__c, __falses[__n]) : false; 00424 bool __testt = __n <= __truen 00425 ? __traits_type::eq(__c, __trues[__n]) : false; 00426 if (!(__testf || __testt)) 00427 { 00428 __err |= ios_base::failbit; 00429 break; 00430 } 00431 else if (__testf && __n == __falsen) 00432 { 00433 __v = 0; 00434 break; 00435 } 00436 else if (__testt && __n == __truen) 00437 { 00438 __v = 1; 00439 break; 00440 } 00441 } 00442 if (__beg == __end) 00443 __err |= ios_base::eofbit; 00444 } 00445 return __beg; 00446 } 00447 #endif 00448 00449 template<typename _CharT, typename _InIter> 00450 _InIter 00451 num_get<_CharT, _InIter>:: 00452 do_get(iter_type __beg, iter_type __end, ios_base& __io, 00453 ios_base::iostate& __err, long& __v) const 00454 { 00455 string __xtrc; 00456 int __base; 00457 __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base); 00458 __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale, __base); 00459 return __beg; 00460 } 00461 00462 template<typename _CharT, typename _InIter> 00463 _InIter 00464 num_get<_CharT, _InIter>:: 00465 do_get(iter_type __beg, iter_type __end, ios_base& __io, 00466 ios_base::iostate& __err, unsigned short& __v) const 00467 { 00468 string __xtrc; 00469 int __base; 00470 __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base); 00471 unsigned long __ul; 00472 __convert_to_v(__xtrc.c_str(), __ul, __err, _S_c_locale, __base); 00473 if (!(__err & ios_base::failbit) 00474 && __ul <= numeric_limits<unsigned short>::max()) 00475 __v = static_cast<unsigned short>(__ul); 00476 else 00477 __err |= ios_base::failbit; 00478 return __beg; 00479 } 00480 00481 template<typename _CharT, typename _InIter> 00482 _InIter 00483 num_get<_CharT, _InIter>:: 00484 do_get(iter_type __beg, iter_type __end, ios_base& __io, 00485 ios_base::iostate& __err, unsigned int& __v) const 00486 { 00487 string __xtrc; 00488 int __base; 00489 __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base); 00490 unsigned long __ul; 00491 __convert_to_v(__xtrc.c_str(), __ul, __err, _S_c_locale, __base); 00492 if (!(__err & ios_base::failbit) 00493 && __ul <= numeric_limits<unsigned int>::max()) 00494 __v = static_cast<unsigned int>(__ul); 00495 else 00496 __err |= ios_base::failbit; 00497 return __beg; 00498 } 00499 00500 template<typename _CharT, typename _InIter> 00501 _InIter 00502 num_get<_CharT, _InIter>:: 00503 do_get(iter_type __beg, iter_type __end, ios_base& __io, 00504 ios_base::iostate& __err, unsigned long& __v) const 00505 { 00506 string __xtrc; 00507 int __base; 00508 __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base); 00509 __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale, __base); 00510 return __beg; 00511 } 00512 00513 #ifdef _GLIBCPP_USE_LONG_LONG 00514 template<typename _CharT, typename _InIter> 00515 _InIter 00516 num_get<_CharT, _InIter>:: 00517 do_get(iter_type __beg, iter_type __end, ios_base& __io, 00518 ios_base::iostate& __err, long long& __v) const 00519 { 00520 string __xtrc; 00521 int __base; 00522 __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base); 00523 __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale, __base); 00524 return __beg; 00525 } 00526 00527 template<typename _CharT, typename _InIter> 00528 _InIter 00529 num_get<_CharT, _InIter>:: 00530 do_get(iter_type __beg, iter_type __end, ios_base& __io, 00531 ios_base::iostate& __err, unsigned long long& __v) const 00532 { 00533 string __xtrc; 00534 int __base; 00535 __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base); 00536 __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale, __base); 00537 return __beg; 00538 } 00539 #endif 00540 00541 template<typename _CharT, typename _InIter> 00542 _InIter 00543 num_get<_CharT, _InIter>:: 00544 do_get(iter_type __beg, iter_type __end, ios_base& __io, 00545 ios_base::iostate& __err, float& __v) const 00546 { 00547 string __xtrc; 00548 __xtrc.reserve(32); 00549 __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc); 00550 __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale); 00551 return __beg; 00552 } 00553 00554 template<typename _CharT, typename _InIter> 00555 _InIter 00556 num_get<_CharT, _InIter>:: 00557 do_get(iter_type __beg, iter_type __end, ios_base& __io, 00558 ios_base::iostate& __err, double& __v) const 00559 { 00560 string __xtrc; 00561 __xtrc.reserve(32); 00562 __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc); 00563 __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale); 00564 return __beg; 00565 } 00566 00567 template<typename _CharT, typename _InIter> 00568 _InIter 00569 num_get<_CharT, _InIter>:: 00570 do_get(iter_type __beg, iter_type __end, ios_base& __io, 00571 ios_base::iostate& __err, long double& __v) const 00572 { 00573 string __xtrc; 00574 __xtrc.reserve(32); 00575 __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc); 00576 __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale); 00577 return __beg; 00578 } 00579 00580 template<typename _CharT, typename _InIter> 00581 _InIter 00582 num_get<_CharT, _InIter>:: 00583 do_get(iter_type __beg, iter_type __end, ios_base& __io, 00584 ios_base::iostate& __err, void*& __v) const 00585 { 00586 // Prepare for hex formatted input 00587 typedef ios_base::fmtflags fmtflags; 00588 fmtflags __fmt = __io.flags(); 00589 fmtflags __fmtmask = ~(ios_base::showpos | ios_base::basefield 00590 | ios_base::uppercase | ios_base::internal); 00591 __io.flags(__fmt & __fmtmask | (ios_base::hex | ios_base::showbase)); 00592 00593 string __xtrc; 00594 int __base; 00595 __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base); 00596 00597 // Reset from hex formatted input 00598 __io.flags(__fmt); 00599 00600 unsigned long __ul; 00601 __convert_to_v(__xtrc.c_str(), __ul, __err, _S_c_locale, __base); 00602 if (!(__err & ios_base::failbit)) 00603 __v = reinterpret_cast<void*>(__ul); 00604 else 00605 __err |= ios_base::failbit; 00606 return __beg; 00607 } 00608 00609 // The following code uses snprintf (or sprintf(), when _GLIBCPP_USE_C99 00610 // is not defined) to convert floating point values for insertion into a 00611 // stream. An optimization would be to replace them with code that works 00612 // directly on a wide buffer and then use __pad to do the padding. 00613 // It would be good to replace them anyway to gain back the efficiency 00614 // that C++ provides by knowing up front the type of the values to insert. 00615 // Also, sprintf is dangerous since may lead to accidental buffer overruns. 00616 // This implementation follows the C++ standard fairly directly as 00617 // outlined in 22.2.2.2 [lib.locale.num.put] 00618 template<typename _CharT, typename _OutIter> 00619 template<typename _ValueT> 00620 _OutIter 00621 num_put<_CharT, _OutIter>:: 00622 _M_convert_float(_OutIter __s, ios_base& __io, _CharT __fill, char __mod, 00623 _ValueT __v) const 00624 { 00625 // Note: digits10 is rounded down: we need to add 1 to ensure 00626 // we get the full available precision. 00627 // Then, in general, one more 1 needs to be added since, when the 00628 // %{g,G} conversion specifiers are chosen inside _S_format_float, the 00629 // precision field is "the maximum number of significant digits", *not* 00630 // the "number of digits to appear after the decimal point", as happens 00631 // for %{e,E,f,F} (C99, 7.19.6.1,4). 00632 const int __max_digits = numeric_limits<_ValueT>::digits10 + 2; 00633 streamsize __prec = __io.precision(); 00634 00635 if (__prec > static_cast<streamsize>(__max_digits)) 00636 __prec = static_cast<streamsize>(__max_digits); 00637 00638 // Long enough for the max format spec. 00639 char __fbuf[16]; 00640 00641 // [22.2.2.2.2] Stage 1, numeric conversion to character. 00642 int __len; 00643 #ifdef _GLIBCPP_USE_C99 00644 // First try a buffer perhaps big enough (for sure sufficient for 00645 // non-ios_base::fixed outputs) 00646 int __cs_size = __max_digits * 3; 00647 char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 00648 00649 const bool __fp = _S_format_float(__io, __fbuf, __mod, __prec); 00650 if (__fp) 00651 __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, 00652 _S_c_locale, __prec); 00653 else 00654 __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, _S_c_locale); 00655 00656 // If the buffer was not large enough, try again with the correct size. 00657 if (__len >= __cs_size) 00658 { 00659 __cs_size = __len + 1; 00660 __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 00661 if (__fp) 00662 __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, 00663 _S_c_locale, __prec); 00664 else 00665 __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, 00666 _S_c_locale); 00667 } 00668 #else 00669 // Consider the possibility of long ios_base::fixed outputs 00670 const bool __fixed = __io.flags() & ios_base::fixed; 00671 const int __max_exp = numeric_limits<_ValueT>::max_exponent10; 00672 // ios_base::fixed outputs may need up to __max_exp+1 chars 00673 // for the integer part + up to __max_digits chars for the 00674 // fractional part + 3 chars for sign, decimal point, '\0'. On 00675 // the other hand, for non-fixed outputs __max_digits*3 chars 00676 // are largely sufficient. 00677 const int __cs_size = __fixed ? __max_exp + __max_digits + 4 00678 : __max_digits * 3; 00679 char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 00680 00681 if (_S_format_float(__io, __fbuf, __mod, __prec)) 00682 __len = __convert_from_v(__cs, 0, __fbuf, __v, _S_c_locale, __prec); 00683 else 00684 __len = __convert_from_v(__cs, 0, __fbuf, __v, _S_c_locale); 00685 #endif 00686 return _M_widen_float(__s, __io, __fill, __cs, __len); 00687 } 00688 00689 template<typename _CharT, typename _OutIter> 00690 template<typename _ValueT> 00691 _OutIter 00692 num_put<_CharT, _OutIter>:: 00693 _M_convert_int(_OutIter __s, ios_base& __io, _CharT __fill, char __mod, 00694 char __modl, _ValueT __v) const 00695 { 00696 // [22.2.2.2.2] Stage 1, numeric conversion to character. 00697 00698 // Long enough for the max format spec. 00699 char __fbuf[16]; 00700 _S_format_int(__io, __fbuf, __mod, __modl); 00701 #ifdef _GLIBCPP_USE_C99 00702 // First try a buffer perhaps big enough. 00703 int __cs_size = 64; 00704 char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 00705 int __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, 00706 _S_c_locale); 00707 // If the buffer was not large enough, try again with the correct size. 00708 if (__len >= __cs_size) 00709 { 00710 __cs_size = __len + 1; 00711 __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 00712 __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, 00713 _S_c_locale); 00714 } 00715 #else 00716 // Leave room for "+/-," "0x," and commas. This size is 00717 // arbitrary, but should be largely sufficient. 00718 char __cs[128]; 00719 int __len = __convert_from_v(__cs, 0, __fbuf, __v, _S_c_locale); 00720 #endif 00721 return _M_widen_int(__s, __io, __fill, __cs, __len); 00722 } 00723 00724 template<typename _CharT, typename _OutIter> 00725 _OutIter 00726 num_put<_CharT, _OutIter>:: 00727 _M_widen_float(_OutIter __s, ios_base& __io, _CharT __fill, char* __cs, 00728 int __len) const 00729 { 00730 typedef char_traits<_CharT> __traits_type; 00731 // [22.2.2.2.2] Stage 2, convert to char_type, using correct 00732 // numpunct.decimal_point() values for '.' and adding grouping. 00733 const locale __loc = __io.getloc(); 00734 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 00735 _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 00736 * __len)); 00737 // Grouping can add (almost) as many separators as the number of 00738 // digits, but no more. 00739 _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 00740 * __len * 2)); 00741 __ctype.widen(__cs, __cs + __len, __ws); 00742 00743 // Replace decimal point. 00744 const _CharT* __p; 00745 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); 00746 if (__p = __traits_type::find(__ws, __len, __ctype.widen('.'))) 00747 __ws[__p - __ws] = __np.decimal_point(); 00748 00749 #ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS 00750 //282. What types does numpunct grouping refer to? 00751 // Add grouping, if necessary. 00752 const string __grouping = __np.grouping(); 00753 ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield; 00754 if (__grouping.size()) 00755 { 00756 _CharT* __p2; 00757 int __declen = __p ? __p - __ws : __len; 00758 __p2 = __add_grouping(__ws2, __np.thousands_sep(), 00759 __grouping.c_str(), 00760 __grouping.c_str() + __grouping.size(), 00761 __ws, __ws + __declen); 00762 int __newlen = __p2 - __ws2; 00763 00764 // Tack on decimal part. 00765 if (__p) 00766 { 00767 __traits_type::copy(__p2, __p, __len - __declen); 00768 __newlen += __len - __declen; 00769 } 00770 00771 // Switch strings, establish correct new length. 00772 __ws = __ws2; 00773 __len = __newlen; 00774 } 00775 #endif 00776 return _M_insert(__s, __io, __fill, __ws, __len); 00777 } 00778 00779 template<typename _CharT, typename _OutIter> 00780 _OutIter 00781 num_put<_CharT, _OutIter>:: 00782 _M_widen_int(_OutIter __s, ios_base& __io, _CharT __fill, char* __cs, 00783 int __len) const 00784 { 00785 // [22.2.2.2.2] Stage 2, convert to char_type, using correct 00786 // numpunct.decimal_point() values for '.' and adding grouping. 00787 const locale __loc = __io.getloc(); 00788 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 00789 _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 00790 * __len)); 00791 // Grouping can add (almost) as many separators as the number of 00792 // digits, but no more. 00793 _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 00794 * __len * 2)); 00795 __ctype.widen(__cs, __cs + __len, __ws); 00796 00797 // Add grouping, if necessary. 00798 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); 00799 const string __grouping = __np.grouping(); 00800 const ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield; 00801 if (__grouping.size()) 00802 { 00803 // By itself __add_grouping cannot deal correctly with __ws when 00804 // ios::showbase is set and ios_base::oct || ios_base::hex. 00805 // Therefore we take care "by hand" of the initial 0, 0x or 0X. 00806 // However, remember that the latter do not occur if the number 00807 // printed is '0' (__len == 1). 00808 streamsize __off = 0; 00809 if ((__io.flags() & ios_base::showbase) && __len > 1) 00810 if (__basefield == ios_base::oct) 00811 { 00812 __off = 1; 00813 *__ws2 = *__ws; 00814 } 00815 else if (__basefield == ios_base::hex) 00816 { 00817 __off = 2; 00818 *__ws2 = *__ws; 00819 *(__ws2 + 1) = *(__ws + 1); 00820 } 00821 _CharT* __p; 00822 __p = __add_grouping(__ws2 + __off, __np.thousands_sep(), 00823 __grouping.c_str(), 00824 __grouping.c_str() + __grouping.size(), 00825 __ws + __off, __ws + __len); 00826 __len = __p - __ws2; 00827 // Switch strings. 00828 __ws = __ws2; 00829 } 00830 return _M_insert(__s, __io, __fill, __ws, __len); 00831 } 00832 00833 // For use by integer and floating-point types after they have been 00834 // converted into a char_type string. 00835 template<typename _CharT, typename _OutIter> 00836 _OutIter 00837 num_put<_CharT, _OutIter>:: 00838 _M_insert(_OutIter __s, ios_base& __io, _CharT __fill, const _CharT* __ws, 00839 int __len) const 00840 { 00841 typedef char_traits<_CharT> __traits_type; 00842 // [22.2.2.2.2] Stage 3. 00843 streamsize __w = __io.width(); 00844 _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 00845 * __w)); 00846 if (__w > static_cast<streamsize>(__len)) 00847 { 00848 __pad<_CharT, __traits_type>::_S_pad(__io, __fill, __ws2, __ws, 00849 __w, __len, true); 00850 __len = static_cast<int>(__w); 00851 // Switch strings. 00852 __ws = __ws2; 00853 } 00854 __io.width(0); 00855 00856 // [22.2.2.2.2] Stage 4. 00857 // Write resulting, fully-formatted string to output iterator. 00858 for (int __j = 0; __j < __len; ++__j, ++__s) 00859 *__s = __ws[__j]; 00860 return __s; 00861 } 00862 00863 template<typename _CharT, typename _OutIter> 00864 _OutIter 00865 num_put<_CharT, _OutIter>:: 00866 do_put(iter_type __s, ios_base& __io, char_type __fill, bool __v) const 00867 { 00868 ios_base::fmtflags __flags = __io.flags(); 00869 if ((__flags & ios_base::boolalpha) == 0) 00870 { 00871 unsigned long __uv = __v; 00872 __s = _M_convert_int(__s, __io, __fill, 'u', char(), __uv); 00873 } 00874 else 00875 { 00876 typedef basic_string<_CharT> __string_type; 00877 locale __loc = __io.getloc(); 00878 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); 00879 __string_type __name; 00880 if (__v) 00881 __name = __np.truename(); 00882 else 00883 __name = __np.falsename(); 00884 __s = _M_insert(__s, __io, __fill, __name.c_str(), __name.size()); 00885 } 00886 return __s; 00887 } 00888 00889 template<typename _CharT, typename _OutIter> 00890 _OutIter 00891 num_put<_CharT, _OutIter>:: 00892 do_put(iter_type __s, ios_base& __io, char_type __fill, long __v) const 00893 { return _M_convert_int(__s, __io, __fill, 'd', char(), __v); } 00894 00895 template<typename _CharT, typename _OutIter> 00896 _OutIter 00897 num_put<_CharT, _OutIter>:: 00898 do_put(iter_type __s, ios_base& __io, char_type __fill, 00899 unsigned long __v) const 00900 { return _M_convert_int(__s, __io, __fill, 'u', char(), __v); } 00901 00902 #ifdef _GLIBCPP_USE_LONG_LONG 00903 template<typename _CharT, typename _OutIter> 00904 _OutIter 00905 num_put<_CharT, _OutIter>:: 00906 do_put(iter_type __s, ios_base& __b, char_type __fill, long long __v) const 00907 { return _M_convert_int(__s, __b, __fill, 'd', 'l', __v); } 00908 00909 template<typename _CharT, typename _OutIter> 00910 _OutIter 00911 num_put<_CharT, _OutIter>:: 00912 do_put(iter_type __s, ios_base& __io, char_type __fill, 00913 unsigned long long __v) const 00914 { return _M_convert_int(__s, __io, __fill, 'u', 'l', __v); } 00915 #endif 00916 00917 template<typename _CharT, typename _OutIter> 00918 _OutIter 00919 num_put<_CharT, _OutIter>:: 00920 do_put(iter_type __s, ios_base& __io, char_type __fill, double __v) const 00921 { return _M_convert_float(__s, __io, __fill, char(), __v); } 00922 00923 template<typename _CharT, typename _OutIter> 00924 _OutIter 00925 num_put<_CharT, _OutIter>:: 00926 do_put(iter_type __s, ios_base& __io, char_type __fill, 00927 long double __v) const 00928 { return _M_convert_float(__s, __io, __fill, 'L', __v); } 00929 00930 template<typename _CharT, typename _OutIter> 00931 _OutIter 00932 num_put<_CharT, _OutIter>:: 00933 do_put(iter_type __s, ios_base& __io, char_type __fill, 00934 const void* __v) const 00935 { 00936 ios_base::fmtflags __flags = __io.flags(); 00937 ios_base::fmtflags __fmt = ~(ios_base::showpos | ios_base::basefield 00938 | ios_base::uppercase | ios_base::internal); 00939 __io.flags(__flags & __fmt | (ios_base::hex | ios_base::showbase)); 00940 try 00941 { 00942 __s = _M_convert_int(__s, __io, __fill, 'u', char(), 00943 reinterpret_cast<unsigned long>(__v)); 00944 __io.flags(__flags); 00945 } 00946 catch (...) 00947 { 00948 __io.flags(__flags); 00949 __throw_exception_again; 00950 } 00951 return __s; 00952 } 00953 00954 00955 template<typename _CharT, typename _InIter> 00956 _InIter 00957 money_get<_CharT, _InIter>:: 00958 do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io, 00959 ios_base::iostate& __err, long double& __units) const 00960 { 00961 string_type __str; 00962 __beg = this->do_get(__beg, __end, __intl, __io, __err, __str); 00963 00964 const int __n = numeric_limits<long double>::digits10; 00965 char* __cs = static_cast<char*>(__builtin_alloca(__n)); 00966 const locale __loc = __io.getloc(); 00967 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 00968 const _CharT* __wcs = __str.c_str(); 00969 __ctype.narrow(__wcs, __wcs + __str.size() + 1, char(), __cs); 00970 __convert_to_v(__cs, __units, __err, _S_c_locale); 00971 return __beg; 00972 } 00973 00974 template<typename _CharT, typename _InIter> 00975 _InIter 00976 money_get<_CharT, _InIter>:: 00977 do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io, 00978 ios_base::iostate& __err, string_type& __units) const 00979 { 00980 // These contortions are quite unfortunate. 00981 typedef moneypunct<_CharT, true> __money_true; 00982 typedef moneypunct<_CharT, false> __money_false; 00983 typedef money_base::part part; 00984 typedef typename string_type::size_type size_type; 00985 00986 const locale __loc = __io.getloc(); 00987 const __money_true& __mpt = use_facet<__money_true>(__loc); 00988 const __money_false& __mpf = use_facet<__money_false>(__loc); 00989 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 00990 00991 const money_base::pattern __p = __intl ? __mpt.neg_format() 00992 : __mpf.neg_format(); 00993 00994 const string_type __pos_sign =__intl ? __mpt.positive_sign() 00995 : __mpf.positive_sign(); 00996 const string_type __neg_sign =__intl ? __mpt.negative_sign() 00997 : __mpf.negative_sign(); 00998 const char_type __d = __intl ? __mpt.decimal_point() 00999 : __mpf.decimal_point(); 01000 const char_type __sep = __intl ? __mpt.thousands_sep() 01001 : __mpf.thousands_sep(); 01002 01003 const string __grouping = __intl ? __mpt.grouping() : __mpf.grouping(); 01004 01005 // Set to deduced positive or negative sign, depending. 01006 string_type __sign; 01007 // String of grouping info from thousands_sep plucked from __units. 01008 string __grouping_tmp; 01009 // Marker for thousands_sep position. 01010 int __sep_pos = 0; 01011 // If input iterator is in a valid state. 01012 bool __testvalid = true; 01013 // Flag marking when a decimal point is found. 01014 bool __testdecfound = false; 01015 01016 // The tentative returned string is stored here. 01017 string_type __temp_units; 01018 01019 char_type __c = *__beg; 01020 char_type __eof = static_cast<char_type>(char_traits<char_type>::eof()); 01021 for (int __i = 0; __beg != __end && __i < 4 && __testvalid; ++__i) 01022 { 01023 part __which = static_cast<part>(__p.field[__i]); 01024 switch (__which) 01025 { 01026 case money_base::symbol: 01027 if (__io.flags() & ios_base::showbase 01028 || __i < 2 || __sign.size() > 1 01029 || ((static_cast<part>(__p.field[3]) != money_base::none) 01030 && __i == 2)) 01031 { 01032 // According to 22.2.6.1.2.2, symbol is required 01033 // if (__io.flags() & ios_base::showbase), 01034 // otherwise is optional and consumed only if 01035 // other characters are needed to complete the 01036 // format. 01037 const string_type __symbol = __intl ? __mpt.curr_symbol() 01038 : __mpf.curr_symbol(); 01039 size_type __len = __symbol.size(); 01040 size_type __j = 0; 01041 while (__beg != __end 01042 && __j < __len && __symbol[__j] == __c) 01043 { 01044 __c = *(++__beg); 01045 ++__j; 01046 } 01047 // When (__io.flags() & ios_base::showbase) 01048 // symbol is required. 01049 if (__j != __len && (__io.flags() & ios_base::showbase)) 01050 __testvalid = false; 01051 } 01052 break; 01053 case money_base::sign: 01054 // Sign might not exist, or be more than one character long. 01055 if (__pos_sign.size() && __neg_sign.size()) 01056 { 01057 // Sign is mandatory. 01058 if (__c == __pos_sign[0]) 01059 { 01060 __sign = __pos_sign; 01061 __c = *(++__beg); 01062 } 01063 else if (__c == __neg_sign[0]) 01064 { 01065 __sign = __neg_sign; 01066 __c = *(++__beg); 01067 } 01068 else 01069 __testvalid = false; 01070 } 01071 else if (__pos_sign.size() && __c == __pos_sign[0]) 01072 { 01073 __sign = __pos_sign; 01074 __c = *(++__beg); 01075 } 01076 else if (__neg_sign.size() && __c == __neg_sign[0]) 01077 { 01078 __sign = __neg_sign; 01079 __c = *(++__beg); 01080 } 01081 break; 01082 case money_base::value: 01083 // Extract digits, remove and stash away the 01084 // grouping of found thousands separators. 01085 while (__beg != __end 01086 && (__ctype.is(ctype_base::digit, __c) 01087 || (__c == __d && !__testdecfound) 01088 || __c == __sep)) 01089 { 01090 if (__c == __d) 01091 { 01092 __grouping_tmp += static_cast<char>(__sep_pos); 01093 __sep_pos = 0; 01094 __testdecfound = true; 01095 } 01096 else if (__c == __sep) 01097 { 01098 if (__grouping.size()) 01099 { 01100 // Mark position for later analysis. 01101 __grouping_tmp += static_cast<char>(__sep_pos); 01102 __sep_pos = 0; 01103 } 01104 else 01105 { 01106 __testvalid = false; 01107 break; 01108 } 01109 } 01110 else 01111 { 01112 __temp_units += __c; 01113 ++__sep_pos; 01114 } 01115 __c = *(++__beg); 01116 } 01117 break; 01118 case money_base::space: 01119 case money_base::none: 01120 // Only if not at the end of the pattern. 01121 if (__i != 3) 01122 while (__beg != __end 01123 && __ctype.is(ctype_base::space, __c)) 01124 __c = *(++__beg); 01125 break; 01126 } 01127 } 01128 01129 // Need to get the rest of the sign characters, if they exist. 01130 if (__sign.size() > 1) 01131 { 01132 size_type __len = __sign.size(); 01133 size_type __i = 1; 01134 for (; __c != __eof && __i < __len; ++__i) 01135 while (__beg != __end && __c != __sign[__i]) 01136 __c = *(++__beg); 01137 01138 if (__i != __len) 01139 __testvalid = false; 01140 } 01141 01142 // Strip leading zeros. 01143 while (__temp_units[0] == __ctype.widen('0')) 01144 __temp_units.erase(__temp_units.begin()); 01145 01146 if (__sign.size() && __sign == __neg_sign) 01147 __temp_units.insert(__temp_units.begin(), __ctype.widen('-')); 01148 01149 // Test for grouping fidelity. 01150 if (__grouping.size() && __grouping_tmp.size()) 01151 { 01152 if (!__verify_grouping(__grouping, __grouping_tmp)) 01153 __testvalid = false; 01154 } 01155 01156 // Iff no more characters are available. 01157 if (__c == __eof) 01158 __err |= ios_base::eofbit; 01159 01160 // Iff valid sequence is not recognized. 01161 if (!__testvalid || !__temp_units.size()) 01162 __err |= ios_base::failbit; 01163 else 01164 // Use the "swap trick" to copy __temp_units into __units. 01165 __temp_units.swap(__units); 01166 01167 return __beg; 01168 } 01169 01170 template<typename _CharT, typename _OutIter> 01171 _OutIter 01172 money_put<_CharT, _OutIter>:: 01173 do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill, 01174 long double __units) const 01175 { 01176 const locale __loc = __io.getloc(); 01177 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 01178 #ifdef _GLIBCPP_USE_C99 01179 // First try a buffer perhaps big enough. 01180 int __cs_size = 64; 01181 char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 01182 int __len = __convert_from_v(__cs, __cs_size, "%.01Lf", __units, 01183 _S_c_locale); 01184 // If the buffer was not large enough, try again with the correct size. 01185 if (__len >= __cs_size) 01186 { 01187 __cs_size = __len + 1; 01188 __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 01189 __len = __convert_from_v(__cs, __cs_size, "%.01Lf", __units, 01190 _S_c_locale); 01191 } 01192 #else 01193 // max_exponent10 + 1 for the integer part, + 4 for sign, decimal point, 01194 // decimal digit, '\0'. 01195 const int __cs_size = numeric_limits<long double>::max_exponent10 + 5; 01196 char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 01197 int __len = __convert_from_v(__cs, 0, "%.01Lf", __units, _S_c_locale); 01198 #endif 01199 _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __cs_size)); 01200 __ctype.widen(__cs, __cs + __len, __ws); 01201 string_type __digits(__ws); 01202 return this->do_put(__s, __intl, __io, __fill, __digits); 01203 } 01204 01205 template<typename _CharT, typename _OutIter> 01206 _OutIter 01207 money_put<_CharT, _OutIter>:: 01208 do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill, 01209 const string_type& __digits) const 01210 { 01211 typedef typename string_type::size_type size_type; 01212 typedef money_base::part part; 01213 01214 const locale __loc = __io.getloc(); 01215 const size_type __width = static_cast<size_type>(__io.width()); 01216 01217 // These contortions are quite unfortunate. 01218 typedef moneypunct<_CharT, true> __money_true; 01219 typedef moneypunct<_CharT, false> __money_false; 01220 const __money_true& __mpt = use_facet<__money_true>(__loc); 01221 const __money_false& __mpf = use_facet<__money_false>(__loc); 01222 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 01223 01224 // Determine if negative or positive formats are to be used, and 01225 // discard leading negative_sign if it is present. 01226 const char_type* __beg = __digits.data(); 01227 const char_type* __end = __beg + __digits.size(); 01228 money_base::pattern __p; 01229 string_type __sign; 01230 if (*__beg != __ctype.widen('-')) 01231 { 01232 __p = __intl ? __mpt.pos_format() : __mpf.pos_format(); 01233 __sign =__intl ? __mpt.positive_sign() : __mpf.positive_sign(); 01234 } 01235 else 01236 { 01237 __p = __intl ? __mpt.neg_format() : __mpf.neg_format(); 01238 __sign =__intl ? __mpt.negative_sign() : __mpf.negative_sign(); 01239 ++__beg; 01240 } 01241 01242 // Look for valid numbers in the current ctype facet within input digits. 01243 __end = __ctype.scan_not(ctype_base::digit, __beg, __end); 01244 if (__beg != __end) 01245 { 01246 // Assume valid input, and attempt to format. 01247 // Break down input numbers into base components, as follows: 01248 // final_value = grouped units + (decimal point) + (digits) 01249 string_type __res; 01250 string_type __value; 01251 const string_type __symbol = __intl ? __mpt.curr_symbol() 01252 : __mpf.curr_symbol(); 01253 01254 // Deal with decimal point, decimal digits. 01255 const int __frac = __intl ? __mpt.frac_digits() 01256 : __mpf.frac_digits(); 01257 if (__frac > 0) 01258 { 01259 const char_type __d = __intl ? __mpt.decimal_point() 01260 : __mpf.decimal_point(); 01261 if (__end - __beg >= __frac) 01262 { 01263 __value = string_type(__end - __frac, __end); 01264 __value.insert(__value.begin(), __d); 01265 __end -= __frac; 01266 } 01267 else 01268 { 01269 // Have to pad zeros in the decimal position. 01270 __value = string_type(__beg, __end); 01271 int __paddec = __frac - (__end - __beg); 01272 char_type __zero = __ctype.widen('0'); 01273 __value.insert(__value.begin(), __paddec, __zero); 01274 __value.insert(__value.begin(), __d); 01275 __beg = __end; 01276 } 01277 } 01278 01279 // Add thousands separators to non-decimal digits, per 01280 // grouping rules. 01281 if (__beg != __end) 01282 { 01283 const string __grouping = __intl ? __mpt.grouping() 01284 : __mpf.grouping(); 01285 if (__grouping.size()) 01286 { 01287 const char_type __sep = __intl ? __mpt.thousands_sep() 01288 : __mpf.thousands_sep(); 01289 const char* __gbeg = __grouping.c_str(); 01290 const char* __gend = __gbeg + __grouping.size(); 01291 const int __n = (__end - __beg) * 2; 01292 _CharT* __ws2 = 01293 static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __n)); 01294 _CharT* __ws_end = __add_grouping(__ws2, __sep, __gbeg, 01295 __gend, __beg, __end); 01296 __value.insert(0, __ws2, __ws_end - __ws2); 01297 } 01298 else 01299 __value.insert(0, string_type(__beg, __end)); 01300 } 01301 01302 // Calculate length of resulting string. 01303 ios_base::fmtflags __f = __io.flags() & ios_base::adjustfield; 01304 size_type __len = __value.size() + __sign.size(); 01305 __len += (__io.flags() & ios_base::showbase) ? __symbol.size() : 0; 01306 bool __testipad = __f == ios_base::internal && __len < __width; 01307 01308 // Fit formatted digits into the required pattern. 01309 for (int __i = 0; __i < 4; ++__i) 01310 { 01311 part __which = static_cast<part>(__p.field[__i]); 01312 switch (__which) 01313 { 01314 case money_base::symbol: 01315 if (__io.flags() & ios_base::showbase) 01316 __res += __symbol; 01317 break; 01318 case money_base::sign: 01319 // Sign might not exist, or be more than one 01320 // charater long. In that case, add in the rest 01321 // below. 01322 if (__sign.size()) 01323 __res += __sign[0]; 01324 break; 01325 case money_base::value: 01326 __res += __value; 01327 break; 01328 case money_base::space: 01329 // At least one space is required, but if internal 01330 // formatting is required, an arbitrary number of 01331 // fill spaces will be necessary. 01332 if (__testipad) 01333 __res += string_type(__width - __len, __fill); 01334 else 01335 __res += __ctype.widen(__fill); 01336 break; 01337 case money_base::none: 01338 if (__testipad) 01339 __res += string_type(__width - __len, __fill); 01340 break; 01341 } 01342 } 01343 01344 // Special case of multi-part sign parts. 01345 if (__sign.size() > 1) 01346 __res += string_type(__sign.begin() + 1, __sign.end()); 01347 01348 // Pad, if still necessary. 01349 __len = __res.size(); 01350 if (__width > __len) 01351 { 01352 if (__f == ios_base::left) 01353 // After. 01354 __res.append(__width - __len, __fill); 01355 else 01356 // Before. 01357 __res.insert(0, string_type(__width - __len, __fill)); 01358 __len = __width; 01359 } 01360 01361 // Write resulting, fully-formatted string to output iterator. 01362 for (size_type __j = 0; __j < __len; ++__j, ++__s) 01363 *__s = __res[__j]; 01364 } 01365 __io.width(0); 01366 return __s; 01367 } 01368 01369 01370 // NB: Not especially useful. Without an ios_base object or some 01371 // kind of locale reference, we are left clawing at the air where 01372 // the side of the mountain used to be... 01373 template<typename _CharT, typename _InIter> 01374 time_base::dateorder 01375 time_get<_CharT, _InIter>::do_date_order() const 01376 { return time_base::no_order; } 01377 01378 template<typename _CharT, typename _InIter> 01379 void 01380 time_get<_CharT, _InIter>:: 01381 _M_extract_via_format(iter_type& __beg, iter_type& __end, ios_base& __io, 01382 ios_base::iostate& __err, tm* __tm, 01383 const _CharT* __format) const 01384 { 01385 locale __loc = __io.getloc(); 01386 __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc); 01387 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 01388 size_t __len = char_traits<_CharT>::length(__format); 01389 01390 for (size_t __i = 0; __beg != __end && __i < __len && !__err; ++__i) 01391 { 01392 char __c = __format[__i]; 01393 if (__c == '%') 01394 { 01395 // Verify valid formatting code, attempt to extract. 01396 __c = __format[++__i]; 01397 char __mod = 0; 01398 int __mem = 0; 01399 if (__c == 'E' || __c == 'O') 01400 { 01401 __mod = __c; 01402 __c = __format[++__i]; 01403 } 01404 switch (__c) 01405 { 01406 const char* __cs; 01407 _CharT __wcs[10]; 01408 case 'a': 01409 // Abbreviated weekday name [tm_wday] 01410 const char_type* __days1[7]; 01411 __tp._M_days_abbreviated(__days1); 01412 _M_extract_name(__beg, __end, __tm->tm_wday, __days1, 7, 01413 __err); 01414 break; 01415 case 'A': 01416 // Weekday name [tm_wday]. 01417 const char_type* __days2[7]; 01418 __tp._M_days(__days2); 01419 _M_extract_name(__beg, __end, __tm->tm_wday, __days2, 7, 01420 __err); 01421 break; 01422 case 'h': 01423 case 'b': 01424 // Abbreviated month name [tm_mon] 01425 const char_type* __months1[12]; 01426 __tp._M_months_abbreviated(__months1); 01427 _M_extract_name(__beg, __end, __tm->tm_mon, __months1, 12, 01428 __err); 01429 break; 01430 case 'B': 01431 // Month name [tm_mon]. 01432 const char_type* __months2[12]; 01433 __tp._M_months(__months2); 01434 _M_extract_name(__beg, __end, __tm->tm_mon, __months2, 12, 01435 __err); 01436 break; 01437 case 'c': 01438 // Default time and date representation. 01439 const char_type* __dt[2]; 01440 __tp._M_date_time_formats(__dt); 01441 _M_extract_via_format(__beg, __end, __io, __err, __tm, 01442 __dt[0]); 01443 break; 01444 case 'd': 01445 // Day [01, 31]. [tm_mday] 01446 _M_extract_num(__beg, __end, __tm->tm_mday, 1, 31, 2, 01447 __ctype, __err); 01448 break; 01449 case 'D': 01450 // Equivalent to %m/%d/%y.[tm_mon, tm_mday, tm_year] 01451 __cs = "%m/%d/%y"; 01452 __ctype.widen(__cs, __cs + 9, __wcs); 01453 _M_extract_via_format(__beg, __end, __io, __err, __tm, 01454 __wcs); 01455 break; 01456 case 'H': 01457 // Hour [00, 23]. [tm_hour] 01458 _M_extract_num(__beg, __end, __tm->tm_hour, 0, 23, 2, 01459 __ctype, __err); 01460 break; 01461 case 'I': 01462 // Hour [01, 12]. [tm_hour] 01463 _M_extract_num(__beg, __end, __tm->tm_hour, 1, 12, 2, 01464 __ctype, __err); 01465 break; 01466 case 'm': 01467 // Month [01, 12]. [tm_mon] 01468 _M_extract_num(__beg, __end, __mem, 1, 12, 2, __ctype, 01469 __err); 01470 if (!__err) 01471 __tm->tm_mon = __mem - 1; 01472 break; 01473 case 'M': 01474 // Minute [00, 59]. [tm_min] 01475 _M_extract_num(__beg, __end, __tm->tm_min, 0, 59, 2, 01476 __ctype, __err); 01477 break; 01478 case 'n': 01479 if (__ctype.narrow(*__beg, 0) == '\n') 01480 ++__beg; 01481 else 01482 __err |= ios_base::failbit; 01483 break; 01484 case 'R': 01485 // Equivalent to (%H:%M). 01486 __cs = "%H:%M"; 01487 __ctype.widen(__cs, __cs + 6, __wcs); 01488 _M_extract_via_format(__beg, __end, __io, __err, __tm, 01489 __wcs); 01490 break; 01491 case 'S': 01492 // Seconds. 01493 _M_extract_num(__beg, __end, __tm->tm_sec, 0, 59, 2, 01494 __ctype, __err); 01495 break; 01496 case 't': 01497 if (__ctype.narrow(*__beg, 0) == '\t') 01498 ++__beg; 01499 else 01500 __err |= ios_base::failbit; 01501 break; 01502 case 'T': 01503 // Equivalent to (%H:%M:%S). 01504 __cs = "%H:%M:%S"; 01505 __ctype.widen(__cs, __cs + 9, __wcs); 01506 _M_extract_via_format(__beg, __end, __io, __err, __tm, 01507 __wcs); 01508 break; 01509 case 'x': 01510 // Locale's date. 01511 const char_type* __dates[2]; 01512 __tp._M_date_formats(__dates); 01513 _M_extract_via_format(__beg, __end, __io, __err, __tm, 01514 __dates[0]); 01515 break; 01516 case 'X': 01517 // Locale's time. 01518 const char_type* __times[2]; 01519 __tp._M_time_formats(__times); 01520 _M_extract_via_format(__beg, __end, __io, __err, __tm, 01521 __times[0]); 01522 break; 01523 case 'y': 01524 // Two digit year. [tm_year] 01525 _M_extract_num(__beg, __end, __tm->tm_year, 0, 99, 2, 01526 __ctype, __err); 01527 break; 01528 case 'Y': 01529 // Year [1900). [tm_year] 01530 _M_extract_num(__beg, __end, __mem, 0, 01531 numeric_limits<int>::max(), 4, 01532 __ctype, __err); 01533 if (!__err) 01534 __tm->tm_year = __mem - 1900; 01535 break; 01536 case 'Z': 01537 // Timezone info. 01538 if (__ctype.is(ctype_base::upper, *__beg)) 01539 { 01540 int __tmp; 01541 _M_extract_name(__beg, __end, __tmp, 01542 __timepunct<_CharT>::_S_timezones, 01543 14, __err); 01544 01545 // GMT requires special effort. 01546 char_type __c = *__beg; 01547 if (!__err && __tmp == 0 01548 && (__c == __ctype.widen('-') 01549 || __c == __ctype.widen('+'))) 01550 { 01551 _M_extract_num(__beg, __end, __tmp, 0, 23, 2, 01552 __ctype, __err); 01553 _M_extract_num(__beg, __end, __tmp, 0, 59, 2, 01554 __ctype, __err); 01555 } 01556 } 01557 else 01558 __err |= ios_base::failbit; 01559 break; 01560 default: 01561 // Not recognized. 01562 __err |= ios_base::failbit; 01563 } 01564 } 01565 else 01566 { 01567 // Verify format and input match, extract and discard. 01568 if (__c == __ctype.narrow(*__beg, 0)) 01569 ++__beg; 01570 else 01571 __err |= ios_base::failbit; 01572 } 01573 } 01574 } 01575 01576 template<typename _CharT, typename _InIter> 01577 void 01578 time_get<_CharT, _InIter>:: 01579 _M_extract_num(iter_type& __beg, iter_type& __end, int& __member, 01580 int __min, int __max, size_t __len, 01581 const ctype<_CharT>& __ctype, 01582 ios_base::iostate& __err) const 01583 { 01584 size_t __i = 0; 01585 string __digits; 01586 bool __testvalid = true; 01587 char_type __c = *__beg; 01588 while (__beg != __end && __i < __len 01589 && __ctype.is(ctype_base::digit, __c)) 01590 { 01591 __digits += __ctype.narrow(__c, 0); 01592 __c = *(++__beg); 01593 ++__i; 01594 } 01595 if (__i == __len) 01596 { 01597 int __value = atoi(__digits.c_str()); 01598 if (__min <= __value && __value <= __max) 01599 __member = __value; 01600 else 01601 __testvalid = false; 01602 } 01603 else 01604 __testvalid = false; 01605 if (!__testvalid) 01606 __err |= ios_base::failbit; 01607 } 01608 01609 // Assumptions: 01610 // All elements in __names are unique. 01611 template<typename _CharT, typename _InIter> 01612 void 01613 time_get<_CharT, _InIter>:: 01614 _M_extract_name(iter_type& __beg, iter_type& __end, int& __member, 01615 const _CharT** __names, size_t __indexlen, 01616 ios_base::iostate& __err) const 01617 { 01618 typedef char_traits<_CharT> __traits_type; 01619 int* __matches = static_cast<int*>(__builtin_alloca(sizeof(int) * __indexlen)); 01620 size_t __nmatches = 0; 01621 size_t __pos = 0; 01622 bool __testvalid = true; 01623 const char_type* __name; 01624 01625 char_type __c = *__beg; 01626 // Look for initial matches. 01627 for (size_t __i1 = 0; __i1 < __indexlen; ++__i1) 01628 if (__c == __names[__i1][0]) 01629 __matches[__nmatches++] = __i1; 01630 01631 while(__nmatches > 1) 01632 { 01633 // Find smallest matching string. 01634 size_t __minlen = 10; 01635 for (size_t __i2 = 0; __i2 < __nmatches; ++__i2) 01636 __minlen = min(__minlen, 01637 __traits_type::length(__names[__matches[__i2]])); 01638 01639 if (__pos < __minlen && __beg != __end) 01640 { 01641 ++__pos; 01642 __c = *(++__beg); 01643 for (size_t __i3 = 0; __i3 < __nmatches; ++__i3) 01644 { 01645 __name = __names[__matches[__i3]]; 01646 if (__name[__pos] != __c) 01647 __matches[__i3] = __matches[--__nmatches]; 01648 } 01649 } 01650 else 01651 break; 01652 } 01653 01654 if (__nmatches == 1) 01655 { 01656 // Make sure found name is completely extracted. 01657 __name = __names[__matches[0]]; 01658 const size_t __len = __traits_type::length(__name); 01659 while (__pos < __len && __beg != __end && __name[__pos] == *__beg) 01660 ++__beg, ++__pos; 01661 01662 if (__len == __pos) 01663 __member = __matches[0]; 01664 else 01665 __testvalid = false; 01666 } 01667 else 01668 __testvalid = false; 01669 if (!__testvalid) 01670 __err |= ios_base::failbit; 01671 } 01672 01673 template<typename _CharT, typename _InIter> 01674 _InIter 01675 time_get<_CharT, _InIter>:: 01676 do_get_time(iter_type __beg, iter_type __end, ios_base& __io, 01677 ios_base::iostate& __err, tm* __tm) const 01678 { 01679 _CharT __wcs[3]; 01680 const char* __cs = "%X"; 01681 locale __loc = __io.getloc(); 01682 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc); 01683 __ctype.widen(__cs, __cs + 3, __wcs); 01684 _M_extract_via_format(__beg, __end, __io, __err, __tm, __wcs); 01685 if (__beg == __end) 01686 __err |= ios_base::eofbit; 01687 return __beg; 01688 } 01689 01690 template<typename _CharT, typename _InIter> 01691 _InIter 01692 time_get<_CharT, _InIter>:: 01693 do_get_date(iter_type __beg, iter_type __end, ios_base& __io, 01694 ios_base::iostate& __err, tm* __tm) const 01695 { 01696 _CharT __wcs[3]; 01697 const char* __cs = "%x"; 01698 locale __loc = __io.getloc(); 01699 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc); 01700 __ctype.widen(__cs, __cs + 3, __wcs); 01701 _M_extract_via_format(__beg, __end, __io, __err, __tm, __wcs); 01702 if (__beg == __end) 01703 __err |= ios_base::eofbit; 01704 return __beg; 01705 } 01706 01707 template<typename _CharT, typename _InIter> 01708 _InIter 01709 time_get<_CharT, _InIter>:: 01710 do_get_weekday(iter_type __beg, iter_type __end, ios_base& __io, 01711 ios_base::iostate& __err, tm* __tm) const 01712 { 01713 typedef char_traits<_CharT> __traits_type; 01714 locale __loc = __io.getloc(); 01715 __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc); 01716 const char_type* __days[7]; 01717 __tp._M_days_abbreviated(__days); 01718 int __tmpwday; 01719 _M_extract_name(__beg, __end, __tmpwday, __days, 7, __err); 01720 01721 // Check to see if non-abbreviated name exists, and extract. 01722 // NB: Assumes both _M_days and _M_days_abbreviated organized in 01723 // exact same order, first to last, such that the resulting 01724 // __days array with the same index points to a day, and that 01725 // day's abbreviated form. 01726 // NB: Also assumes that an abbreviated name is a subset of the name. 01727 if (!__err) 01728 { 01729 size_t __pos = __traits_type::length(__days[__tmpwday]); 01730 __tp._M_days(__days); 01731 const char_type* __name = __days[__tmpwday]; 01732 if (__name[__pos] == *__beg) 01733 { 01734 // Extract the rest of it. 01735 const size_t __len = __traits_type::length(__name); 01736 while (__pos < __len && __beg != __end 01737 && __name[__pos] == *__beg) 01738 ++__beg, ++__pos; 01739 if (__len != __pos) 01740 __err |= ios_base::failbit; 01741 } 01742 if (!__err) 01743 __tm->tm_wday = __tmpwday; 01744 } 01745 if (__beg == __end) 01746 __err |= ios_base::eofbit; 01747 return __beg; 01748 } 01749 01750 template<typename _CharT, typename _InIter> 01751 _InIter 01752 time_get<_CharT, _InIter>:: 01753 do_get_monthname(iter_type __beg, iter_type __end, 01754 ios_base& __io, ios_base::iostate& __err, tm* __tm) const 01755 { 01756 typedef char_traits<_CharT> __traits_type; 01757 locale __loc = __io.getloc(); 01758 __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc); 01759 const char_type* __months[12]; 01760 __tp._M_months_abbreviated(__months); 01761 int __tmpmon; 01762 _M_extract_name(__beg, __end, __tmpmon, __months, 12, __err); 01763 01764 // Check to see if non-abbreviated name exists, and extract. 01765 // NB: Assumes both _M_months and _M_months_abbreviated organized in 01766 // exact same order, first to last, such that the resulting 01767 // __months array with the same index points to a month, and that 01768 // month's abbreviated form. 01769 // NB: Also assumes that an abbreviated name is a subset of the name. 01770 if (!__err) 01771 { 01772 size_t __pos = __traits_type::length(__months[__tmpmon]); 01773 __tp._M_months(__months); 01774 const char_type* __name = __months[__tmpmon]; 01775 if (__name[__pos] == *__beg) 01776 { 01777 // Extract the rest of it. 01778 const size_t __len = __traits_type::length(__name); 01779 while (__pos < __len && __beg != __end 01780 && __name[__pos] == *__beg) 01781 ++__beg, ++__pos; 01782 if (__len != __pos) 01783 __err |= ios_base::failbit; 01784 } 01785 if (!__err) 01786 __tm->tm_mon = __tmpmon; 01787 } 01788 01789 if (__beg == __end) 01790 __err |= ios_base::eofbit; 01791 return __beg; 01792 } 01793 01794 template<typename _CharT, typename _InIter> 01795 _InIter 01796 time_get<_CharT, _InIter>:: 01797 do_get_year(iter_type __beg, iter_type __end, ios_base& __io, 01798 ios_base::iostate& __err, tm* __tm) const 01799 { 01800 locale __loc = __io.getloc(); 01801 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 01802 01803 char_type __c = *__beg; 01804 size_t __i = 0; 01805 string __digits; 01806 while (__i < 4 && __beg != __end && __ctype.is(ctype_base::digit, __c)) 01807 { 01808 __digits += __ctype.narrow(__c, 0); 01809 __c = *(++__beg); 01810 ++__i; 01811 } 01812 if (__i == 2 || __i == 4) 01813 { 01814 long __l; 01815 __convert_to_v(__digits.c_str(), __l, __err, _S_c_locale); 01816 if (!(__err & ios_base::failbit) && __l <= INT_MAX) 01817 { 01818 __l = __i == 2 ? __l : __l - 1900; 01819 __tm->tm_year = static_cast<int>(__l); 01820 } 01821 } 01822 else 01823 __err |= ios_base::failbit; 01824 if (__beg == __end) 01825 __err |= ios_base::eofbit; 01826 return __beg; 01827 } 01828 01829 template<typename _CharT, typename _OutIter> 01830 _OutIter 01831 time_put<_CharT, _OutIter>:: 01832 put(iter_type __s, ios_base& __io, char_type, const tm* __tm, 01833 const _CharT* __beg, const _CharT* __end) const 01834 { 01835 locale __loc = __io.getloc(); 01836 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc); 01837 while (__beg != __end) 01838 { 01839 char __c = __ctype.narrow(*__beg, 0); 01840 ++__beg; 01841 if (__c == '%') 01842 { 01843 char __format; 01844 char __mod = 0; 01845 size_t __len = 1; 01846 __c = __ctype.narrow(*__beg, 0); 01847 ++__beg; 01848 if (__c == 'E' || __c == 'O') 01849 { 01850 __mod = __c; 01851 __format = __ctype.narrow(*__beg, 0); 01852 ++__beg; 01853 } 01854 else 01855 __format = __c; 01856 __s = this->do_put(__s, __io, char_type(), __tm, __format, 01857 __mod); 01858 } 01859 else 01860 { 01861 *__s = __c; 01862 ++__s; 01863 } 01864 } 01865 return __s; 01866 } 01867 01868 template<typename _CharT, typename _OutIter> 01869 _OutIter 01870 time_put<_CharT, _OutIter>:: 01871 do_put(iter_type __s, ios_base& __io, char_type, const tm* __tm, 01872 char __format, char __mod) const 01873 { 01874 locale __loc = __io.getloc(); 01875 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc); 01876 __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc); 01877 01878 // NB: This size is arbitrary. Should this be a data member, 01879 // initialized at construction? 01880 const size_t __maxlen = 64; 01881 char_type* __res = 01882 static_cast<char_type*>(__builtin_alloca(sizeof(char_type) * __maxlen)); 01883 01884 // NB: In IEE 1003.1-200x, and perhaps other locale models, it 01885 // is possible that the format character will be longer than one 01886 // character. Possibilities include 'E' or 'O' followed by a 01887 // format character: if __mod is not the default argument, assume 01888 // it's a valid modifier. 01889 char_type __fmt[4]; 01890 __fmt[0] = __ctype.widen('%'); 01891 if (!__mod) 01892 { 01893 __fmt[1] = __format; 01894 __fmt[2] = char_type(); 01895 } 01896 else 01897 { 01898 __fmt[1] = __mod; 01899 __fmt[2] = __format; 01900 __fmt[3] = char_type(); 01901 } 01902 01903 __tp._M_put(__res, __maxlen, __fmt, __tm); 01904 01905 // Write resulting, fully-formatted string to output iterator. 01906 size_t __len = char_traits<char_type>::length(__res); 01907 for (size_t __i = 0; __i < __len; ++__i, ++__s) 01908 *__s = __res[__i]; 01909 return __s; 01910 } 01911 01912 01913 // Generic version does nothing. 01914 template<typename _CharT> 01915 int 01916 collate<_CharT>::_M_compare(const _CharT*, const _CharT*) const 01917 { return 0; } 01918 01919 // Generic version does nothing. 01920 template<typename _CharT> 01921 size_t 01922 collate<_CharT>::_M_transform(_CharT*, const _CharT*, size_t) const 01923 { return 0; } 01924 01925 template<typename _CharT> 01926 int 01927 collate<_CharT>:: 01928 do_compare(const _CharT* __lo1, const _CharT* __hi1, 01929 const _CharT* __lo2, const _CharT* __hi2) const 01930 { 01931 const string_type __one(__lo1, __hi1); 01932 const string_type __two(__lo2, __hi2); 01933 return _M_compare(__one.c_str(), __two.c_str()); 01934 } 01935 01936 template<typename _CharT> 01937 typename collate<_CharT>::string_type 01938 collate<_CharT>:: 01939 do_transform(const _CharT* __lo, const _CharT* __hi) const 01940 { 01941 size_t __len = (__hi - __lo) * 2; 01942 // First try a buffer perhaps big enough. 01943 _CharT* __c = 01944 static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __len)); 01945 size_t __res = _M_transform(__c, __lo, __len); 01946 // If the buffer was not large enough, try again with the correct size. 01947 if (__res >= __len) 01948 { 01949 __c = 01950 static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * (__res + 1))); 01951 _M_transform(__c, __lo, __res + 1); 01952 } 01953 return string_type(__c); 01954 } 01955 01956 template<typename _CharT> 01957 long 01958 collate<_CharT>:: 01959 do_hash(const _CharT* __lo, const _CharT* __hi) const 01960 { 01961 unsigned long __val = 0; 01962 for (; __lo < __hi; ++__lo) 01963 __val = *__lo + ((__val << 7) | 01964 (__val >> (numeric_limits<unsigned long>::digits - 7))); 01965 return static_cast<long>(__val); 01966 } 01967 01968 // Convert string to numeric value of type _Tv and store results. 01969 // NB: This is specialized for all required types, there is no 01970 // generic definition. 01971 template<typename _Tv> 01972 void 01973 __convert_to_v(const char* __in, _Tv& __out, ios_base::iostate& __err, 01974 const __c_locale& __cloc, int __base = 10); 01975 01976 // Convert numeric value of type _Tv to string and return length of string. 01977 // If snprintf is available use it, otherwise fall back to the unsafe sprintf 01978 // which, in general, can be dangerous and should be avoided. 01979 template<typename _Tv> 01980 int 01981 __convert_from_v(char* __out, const int __size, const char* __fmt, 01982 _Tv __v, const __c_locale&, int __prec = -1); 01983 01984 // Construct correctly padded string, as per 22.2.2.2.2 01985 // Assumes 01986 // __newlen > __oldlen 01987 // __news is allocated for __newlen size 01988 // Used by both num_put and ostream inserters: if __num, 01989 // internal-adjusted objects are padded according to the rules below 01990 // concerning 0[xX] and +-, otherwise, exactly as right-adjusted 01991 // ones are. 01992 01993 // NB: Of the two parameters, _CharT can be deduced from the 01994 // function arguments. The other (_Traits) has to be explicitly specified. 01995 template<typename _CharT, typename _Traits> 01996 struct __pad 01997 { 01998 static void 01999 _S_pad(ios_base& __io, _CharT __fill, _CharT* __news, 02000 const _CharT* __olds, const streamsize __newlen, 02001 const streamsize __oldlen, const bool __num); 02002 }; 02003 02004 template<typename _CharT, typename _Traits> 02005 void 02006 __pad<_CharT, _Traits>::_S_pad(ios_base& __io, _CharT __fill, 02007 _CharT* __news, const _CharT* __olds, 02008 const streamsize __newlen, 02009 const streamsize __oldlen, const bool __num) 02010 { 02011 size_t __plen = static_cast<size_t>(__newlen - __oldlen); 02012 _CharT* __pads = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __plen)); 02013 _Traits::assign(__pads, __plen, __fill); 02014 02015 _CharT* __beg; 02016 _CharT* __end; 02017 size_t __mod = 0; 02018 size_t __beglen; //either __plen or __oldlen 02019 ios_base::fmtflags __adjust = __io.flags() & ios_base::adjustfield; 02020 02021 if (__adjust == ios_base::left) 02022 { 02023 // Padding last. 02024 __beg = const_cast<_CharT*>(__olds); 02025 __beglen = __oldlen; 02026 __end = __pads; 02027 } 02028 else if (__adjust == ios_base::internal && __num) 02029 { 02030 // Pad after the sign, if there is one. 02031 // Pad after 0[xX], if there is one. 02032 // Who came up with these rules, anyway? Jeeze. 02033 locale __loc = __io.getloc(); 02034 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 02035 const _CharT __minus = __ctype.widen('-'); 02036 const _CharT __plus = __ctype.widen('+'); 02037 bool __testsign = _Traits::eq(__olds[0], __minus) 02038 || _Traits::eq(__olds[0], __plus); 02039 02040 bool __testhex = _Traits::eq(__ctype.widen('0'), __olds[0]) 02041 && (_Traits::eq(__ctype.widen('x'), __olds[1]) 02042 || _Traits::eq(__ctype.widen('X'), __olds[1])); 02043 if (__testhex) 02044 { 02045 __news[0] = __olds[0]; 02046 __news[1] = __olds[1]; 02047 __mod += 2; 02048 __news += 2; 02049 __beg = __pads; 02050 __beglen = __plen; 02051 __end = const_cast<_CharT*>(__olds + __mod); 02052 } 02053 else if (__testsign) 02054 { 02055 _Traits::eq((__news[0] = __olds[0]), __plus) ? __plus : __minus; 02056 ++__mod; 02057 ++__news; 02058 __beg = __pads; 02059 __beglen = __plen; 02060 __end = const_cast<_CharT*>(__olds + __mod); 02061 } 02062 else 02063 { 02064 // Padding first. 02065 __beg = __pads; 02066 __beglen = __plen; 02067 __end = const_cast<_CharT*>(__olds); 02068 } 02069 } 02070 else 02071 { 02072 // Padding first. 02073 __beg = __pads; 02074 __beglen = __plen; 02075 __end = const_cast<_CharT*>(__olds); 02076 } 02077 _Traits::copy(__news, __beg, __beglen); 02078 _Traits::copy(__news + __beglen, __end, 02079 __newlen - __beglen - __mod); 02080 } 02081 02082 // Used by both numeric and monetary facets. 02083 // Check to make sure that the __grouping_tmp string constructed in 02084 // money_get or num_get matches the canonical grouping for a given 02085 // locale. 02086 // __grouping_tmp is parsed L to R 02087 // 1,222,444 == __grouping_tmp of "/1/3/3" 02088 // __grouping is parsed R to L 02089 // 1,222,444 == __grouping of "/3" == "/3/3/3" 02090 template<typename _CharT> 02091 bool 02092 __verify_grouping(const basic_string<_CharT>& __grouping, 02093 basic_string<_CharT>& __grouping_tmp) 02094 { 02095 int __i = 0; 02096 int __j = 0; 02097 const int __len = __grouping.size(); 02098 const int __n = __grouping_tmp.size(); 02099 bool __test = true; 02100 02101 // Parsed number groupings have to match the 02102 // numpunct::grouping string exactly, starting at the 02103 // right-most point of the parsed sequence of elements ... 02104 while (__test && __i < __n - 1) 02105 for (__j = 0; __test && __j < __len && __i < __n - 1; ++__j,++__i) 02106 __test &= __grouping[__j] == __grouping_tmp[__n - __i - 1]; 02107 // ... but the last parsed grouping can be <= numpunct 02108 // grouping. 02109 __j == __len ? __j = 0 : __j; 02110 __test &= __grouping[__j] >= __grouping_tmp[__n - __i - 1]; 02111 return __test; 02112 } 02113 02114 // Used by both numeric and monetary facets. 02115 // Inserts "group separator" characters into an array of characters. 02116 // It's recursive, one iteration per group. It moves the characters 02117 // in the buffer this way: "xxxx12345" -> "12,345xxx". Call this 02118 // only with __gbeg != __gend. 02119 template<typename _CharT> 02120 _CharT* 02121 __add_grouping(_CharT* __s, _CharT __sep, 02122 const char* __gbeg, const char* __gend, 02123 const _CharT* __first, const _CharT* __last) 02124 { 02125 if (__last - __first > *__gbeg) 02126 { 02127 __s = __add_grouping(__s, __sep, 02128 (__gbeg + 1 == __gend ? __gbeg : __gbeg + 1), 02129 __gend, __first, __last - *__gbeg); 02130 __first = __last - *__gbeg; 02131 *__s++ = __sep; 02132 } 02133 do 02134 *__s++ = *__first++; 02135 while (__first != __last); 02136 return __s; 02137 } 02138 02139 // Inhibit implicit instantiations for required instantiations, 02140 // which are defined via explicit instantiations elsewhere. 02141 // NB: This syntax is a GNU extension. 02142 extern template class moneypunct<char, false>; 02143 extern template class moneypunct<char, true>; 02144 extern template class moneypunct_byname<char, false>; 02145 extern template class moneypunct_byname<char, true>; 02146 extern template class money_get<char>; 02147 extern template class money_put<char>; 02148 extern template class numpunct<char>; 02149 extern template class numpunct_byname<char>; 02150 extern template class num_get<char>; 02151 extern template class num_put<char>; 02152 extern template class __timepunct<char>; 02153 extern template class time_put<char>; 02154 extern template class time_put_byname<char>; 02155 extern template class time_get<char>; 02156 extern template class time_get_byname<char>; 02157 extern template class messages<char>; 02158 extern template class messages_byname<char>; 02159 extern template class ctype_byname<char>; 02160 extern template class codecvt_byname<char, char, mbstate_t>; 02161 extern template class collate<char>; 02162 extern template class collate_byname<char>; 02163 02164 extern template 02165 const codecvt<char, char, mbstate_t>& 02166 use_facet<codecvt<char, char, mbstate_t> >(const locale&); 02167 02168 extern template 02169 const collate<char>& 02170 use_facet<collate<char> >(const locale&); 02171 02172 extern template 02173 const numpunct<char>& 02174 use_facet<numpunct<char> >(const locale&); 02175 02176 extern template 02177 const num_put<char>& 02178 use_facet<num_put<char> >(const locale&); 02179 02180 extern template 02181 const num_get<char>& 02182 use_facet<num_get<char> >(const locale&); 02183 02184 extern template 02185 const moneypunct<char, true>& 02186 use_facet<moneypunct<char, true> >(const locale&); 02187 02188 extern template 02189 const moneypunct<char, false>& 02190 use_facet<moneypunct<char, false> >(const locale&); 02191 02192 extern template 02193 const money_put<char>& 02194 use_facet<money_put<char> >(const locale&); 02195 02196 extern template 02197 const money_get<char>& 02198 use_facet<money_get<char> >(const locale&); 02199 02200 extern template 02201 const __timepunct<char>& 02202 use_facet<__timepunct<char> >(const locale&); 02203 02204 extern template 02205 const time_put<char>& 02206 use_facet<time_put<char> >(const locale&); 02207 02208 extern template 02209 const time_get<char>& 02210 use_facet<time_get<char> >(const locale&); 02211 02212 extern template 02213 const messages<char>& 02214 use_facet<messages<char> >(const locale&); 02215 02216 extern template 02217 bool 02218 has_facet<ctype<char> >(const locale&); 02219 02220 extern template 02221 bool 02222 has_facet<codecvt<char, char, mbstate_t> >(const locale&); 02223 02224 extern template 02225 bool 02226 has_facet<collate<char> >(const locale&); 02227 02228 extern template 02229 bool 02230 has_facet<numpunct<char> >(const locale&); 02231 02232 extern template 02233 bool 02234 has_facet<num_put<char> >(const locale&); 02235 02236 extern template 02237 bool 02238 has_facet<num_get<char> >(const locale&); 02239 02240 extern template 02241 bool 02242 has_facet<moneypunct<char> >(const locale&); 02243 02244 extern template 02245 bool 02246 has_facet<money_put<char> >(const locale&); 02247 02248 extern template 02249 bool 02250 has_facet<money_get<char> >(const locale&); 02251 02252 extern template 02253 bool 02254 has_facet<__timepunct<char> >(const locale&); 02255 02256 extern template 02257 bool 02258 has_facet<time_put<char> >(const locale&); 02259 02260 extern template 02261 bool 02262 has_facet<time_get<char> >(const locale&); 02263 02264 extern template 02265 bool 02266 has_facet<messages<char> >(const locale&); 02267 02268 #ifdef _GLIBCPP_USE_WCHAR_T 02269 extern template class moneypunct<wchar_t, false>; 02270 extern template class moneypunct<wchar_t, true>; 02271 extern template class moneypunct_byname<wchar_t, false>; 02272 extern template class moneypunct_byname<wchar_t, true>; 02273 extern template class money_get<wchar_t>; 02274 extern template class money_put<wchar_t>; 02275 extern template class numpunct<wchar_t>; 02276 extern template class numpunct_byname<wchar_t>; 02277 extern template class num_get<wchar_t>; 02278 extern template class num_put<wchar_t>; 02279 extern template class __timepunct<wchar_t>; 02280 extern template class time_put<wchar_t>; 02281 extern template class time_put_byname<wchar_t>; 02282 extern template class time_get<wchar_t>; 02283 extern template class time_get_byname<wchar_t>; 02284 extern template class messages<wchar_t>; 02285 extern template class messages_byname<wchar_t>; 02286 extern template class ctype_byname<wchar_t>; 02287 extern template class codecvt_byname<wchar_t, char, mbstate_t>; 02288 extern template class collate<wchar_t>; 02289 extern template class collate_byname<wchar_t>; 02290 02291 extern template 02292 const codecvt<wchar_t, char, mbstate_t>& 02293 use_facet<codecvt<wchar_t, char, mbstate_t> >(locale const&); 02294 02295 extern template 02296 const collate<wchar_t>& 02297 use_facet<collate<wchar_t> >(const locale&); 02298 02299 extern template 02300 const numpunct<wchar_t>& 02301 use_facet<numpunct<wchar_t> >(const locale&); 02302 02303 extern template 02304 const num_put<wchar_t>& 02305 use_facet<num_put<wchar_t> >(const locale&); 02306 02307 extern template 02308 const num_get<wchar_t>& 02309 use_facet<num_get<wchar_t> >(const locale&); 02310 02311 extern template 02312 const moneypunct<wchar_t, true>& 02313 use_facet<moneypunct<wchar_t, true> >(const locale&); 02314 02315 extern template 02316 const moneypunct<wchar_t, false>& 02317 use_facet<moneypunct<wchar_t, false> >(const locale&); 02318 02319 extern template 02320 const money_put<wchar_t>& 02321 use_facet<money_put<wchar_t> >(const locale&); 02322 02323 extern template 02324 const money_get<wchar_t>& 02325 use_facet<money_get<wchar_t> >(const locale&); 02326 02327 extern template 02328 const __timepunct<wchar_t>& 02329 use_facet<__timepunct<wchar_t> >(const locale&); 02330 02331 extern template 02332 const time_put<wchar_t>& 02333 use_facet<time_put<wchar_t> >(const locale&); 02334 02335 extern template 02336 const time_get<wchar_t>& 02337 use_facet<time_get<wchar_t> >(const locale&); 02338 02339 extern template 02340 const messages<wchar_t>& 02341 use_facet<messages<wchar_t> >(const locale&); 02342 02343 extern template 02344 bool 02345 has_facet<ctype<wchar_t> >(const locale&); 02346 02347 extern template 02348 bool 02349 has_facet<codecvt<wchar_t, char, mbstate_t> >(const locale&); 02350 02351 extern template 02352 bool 02353 has_facet<collate<wchar_t> >(const locale&); 02354 02355 extern template 02356 bool 02357 has_facet<numpunct<wchar_t> >(const locale&); 02358 02359 extern template 02360 bool 02361 has_facet<num_put<wchar_t> >(const locale&); 02362 02363 extern template 02364 bool 02365 has_facet<num_get<wchar_t> >(const locale&); 02366 02367 extern template 02368 bool 02369 has_facet<moneypunct<wchar_t> >(const locale&); 02370 02371 extern template 02372 bool 02373 has_facet<money_put<wchar_t> >(const locale&); 02374 02375 extern template 02376 bool 02377 has_facet<money_get<wchar_t> >(const locale&); 02378 02379 extern template 02380 bool 02381 has_facet<__timepunct<wchar_t> >(const locale&); 02382 02383 extern template 02384 bool 02385 has_facet<time_put<wchar_t> >(const locale&); 02386 02387 extern template 02388 bool 02389 has_facet<time_get<wchar_t> >(const locale&); 02390 02391 extern template 02392 bool 02393 has_facet<messages<wchar_t> >(const locale&); 02394 #endif 02395 } // namespace std 02396 02397 #endif

Generated on Wed Sep 29 13:54:49 2004 for libstdc++-v3 Source by doxygen 1.3.7