Whole document tree locale.ccGo to the documentation of this file.00001 // Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. 00002 // 00003 // This file is part of the GNU ISO C++ Library. This library is free 00004 // software; you can redistribute it and/or modify it under the 00005 // terms of the GNU General Public License as published by the 00006 // Free Software Foundation; either version 2, or (at your option) 00007 // any later version. 00008 00009 // This library is distributed in the hope that it will be useful, 00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 // GNU General Public License for more details. 00013 00014 // You should have received a copy of the GNU General Public License along 00015 // with this library; see the file COPYING. If not, write to the Free 00016 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, 00017 // USA. 00018 00019 // As a special exception, you may use this file as part of a free software 00020 // library without restriction. Specifically, if other files instantiate 00021 // templates or use macros or inline functions from this file, or you compile 00022 // this file and link it with other files to produce an executable, this 00023 // file does not by itself cause the resulting executable to be covered by 00024 // the GNU General Public License. This exception does not however 00025 // invalidate any other reasons why the executable file might be covered by 00026 // the GNU General Public License. 00027 00028 #include <bits/std_clocale.h> 00029 #include <bits/std_cstring.h> 00030 #include <bits/std_cassert.h> 00031 #include <bits/std_cctype.h> 00032 #include <bits/std_limits.h> 00033 #include <exception> 00034 #include <bits/std_stdexcept.h> 00035 #include <bits/std_locale.h> 00036 #include <bits/std_istream.h> 00037 #include <bits/std_ostream.h> 00038 #include <bits/std_vector.h> 00039 #include <bits/std_memory.h> // for auto_ptr 00040 #ifdef _GLIBCPP_USE_WCHAR_T 00041 # include <bits/std_cwctype.h> // for towupper, etc. 00042 #endif 00043 00044 namespace std 00045 { 00046 // Definitions for static const data members of locale. 00047 const locale::category locale::none; 00048 const locale::category locale::ctype; 00049 const locale::category locale::numeric; 00050 const locale::category locale::collate; 00051 const locale::category locale::time; 00052 const locale::category locale::monetary; 00053 const locale::category locale::messages; 00054 const locale::category locale::all; 00055 00056 locale::_Impl* locale::_S_classic; 00057 locale::_Impl* locale::_S_global; 00058 const size_t locale::_S_num_categories; 00059 const size_t locale::_S_num_facets; 00060 00061 // Definitions for locale::id of standard facets. 00062 locale::id ctype<char>::id; 00063 locale::id codecvt<char, char, mbstate_t>::id; 00064 00065 #ifdef _GLIBCPP_USE_WCHAR_T 00066 locale::id ctype<wchar_t>::id; 00067 locale::id codecvt<wchar_t, char, mbstate_t>::id; 00068 #endif 00069 00070 // Definitions for static const data members of locale::id 00071 size_t locale::id::_S_highwater; // init'd to 0 by linker 00072 00073 // Definitions for static const data members of locale::_Impl 00074 const locale::id* const 00075 locale::_Impl::_S_id_ctype[] = 00076 { 00077 &std::ctype<char>::id, 00078 &codecvt<char, char, mbstate_t>::id, 00079 #ifdef _GLIBCPP_USE_WCHAR_T 00080 &std::ctype<wchar_t>::id, 00081 &codecvt<wchar_t, char, mbstate_t>::id, 00082 #endif 00083 0 00084 }; 00085 00086 const locale::id* const 00087 locale::_Impl::_S_id_numeric[] = 00088 { 00089 &num_get<char>::id, 00090 &num_put<char>::id, 00091 &numpunct<char>::id, 00092 #ifdef _GLIBCPP_USE_WCHAR_T 00093 &num_get<wchar_t>::id, 00094 &num_put<wchar_t>::id, 00095 &numpunct<wchar_t>::id, 00096 #endif 00097 0 00098 }; 00099 00100 const locale::id* const 00101 locale::_Impl::_S_id_collate[] = 00102 { 00103 &std::collate<char>::id, 00104 #ifdef _GLIBCPP_USE_WCHAR_T 00105 &std::collate<wchar_t>::id, 00106 #endif 00107 0 00108 }; 00109 00110 const locale::id* const 00111 locale::_Impl::_S_id_time[] = 00112 { 00113 &time_get<char>::id, 00114 &time_put<char>::id, 00115 #ifdef _GLIBCPP_USE_WCHAR_T 00116 &time_get<wchar_t>::id, 00117 &time_put<wchar_t>::id, 00118 #endif 00119 0 00120 }; 00121 00122 const locale::id* const 00123 locale::_Impl::_S_id_monetary[] = 00124 { 00125 &money_get<char>::id, 00126 &money_put<char>::id, 00127 &moneypunct<char, false>::id, 00128 &moneypunct<char, true >::id, 00129 #ifdef _GLIBCPP_USE_WCHAR_T 00130 &money_get<wchar_t>::id, 00131 &money_put<wchar_t>::id, 00132 &moneypunct<wchar_t, false>::id, 00133 &moneypunct<wchar_t, true >::id, 00134 #endif 00135 0 00136 }; 00137 00138 const locale::id* const 00139 locale::_Impl::_S_id_messages[] = 00140 { 00141 &std::messages<char>::id, 00142 #ifdef _GLIBCPP_USE_WCHAR_T 00143 &std::messages<wchar_t>::id, 00144 #endif 00145 0 00146 }; 00147 00148 const locale::id* const* const 00149 locale::_Impl::_S_facet_categories[] = 00150 { 00151 // Order must match the decl order in class locale. 00152 locale::_Impl::_S_id_ctype, 00153 locale::_Impl::_S_id_numeric, 00154 locale::_Impl::_S_id_collate, 00155 locale::_Impl::_S_id_time, 00156 locale::_Impl::_S_id_monetary, 00157 locale::_Impl::_S_id_messages, 00158 0 00159 }; 00160 00161 // Construct and return valid pattern consisting of some combination of: 00162 // space none symbol sign value 00163 money_base::pattern 00164 money_base::_S_construct_pattern(char __preceeds, char __space, char __posn) 00165 { 00166 pattern __ret; 00167 00168 // This insanely complicated routine attempts to construct a valid 00169 // pattern for use with monyepunct. A couple of invariants: 00170 00171 // if (__preceeds) symbol -> value 00172 // else value -> symbol 00173 00174 // if (__space) space 00175 // else none 00176 00177 // none == never first 00178 // space never first or last 00179 00180 // Any elegant implementations of this are welcome. 00181 switch (__posn) 00182 { 00183 case 1: 00184 // 1 The sign precedes the value and symbol. 00185 if (__space) 00186 { 00187 // Pattern starts with sign. 00188 if (__preceeds) 00189 { 00190 __ret.field[1] = symbol; 00191 __ret.field[2] = space; 00192 __ret.field[3] = value; 00193 } 00194 else 00195 { 00196 __ret.field[1] = value; 00197 __ret.field[2] = space; 00198 __ret.field[3] = symbol; 00199 } 00200 __ret.field[0] = sign; 00201 } 00202 else 00203 { 00204 // Pattern starts with sign and ends with none. 00205 if (__preceeds) 00206 { 00207 __ret.field[1] = symbol; 00208 __ret.field[2] = value; 00209 } 00210 else 00211 { 00212 __ret.field[1] = value; 00213 __ret.field[2] = symbol; 00214 } 00215 __ret.field[0] = sign; 00216 __ret.field[3] = none; 00217 } 00218 break; 00219 case 2: 00220 // 2 The sign follows the value and symbol. 00221 if (__space) 00222 { 00223 // Pattern either ends with sign. 00224 if (__preceeds) 00225 { 00226 __ret.field[0] = symbol; 00227 __ret.field[1] = space; 00228 __ret.field[2] = value; 00229 } 00230 else 00231 { 00232 __ret.field[0] = value; 00233 __ret.field[1] = space; 00234 __ret.field[2] = symbol; 00235 } 00236 __ret.field[3] = sign; 00237 } 00238 else 00239 { 00240 // Pattern ends with sign then none. 00241 if (__preceeds) 00242 { 00243 __ret.field[0] = symbol; 00244 __ret.field[1] = value; 00245 } 00246 else 00247 { 00248 __ret.field[0] = value; 00249 __ret.field[1] = symbol; 00250 } 00251 __ret.field[2] = sign; 00252 __ret.field[3] = none; 00253 } 00254 break; 00255 case 3: 00256 // 3 The sign immediately precedes the symbol. 00257 if (__space) 00258 { 00259 // Have space. 00260 if (__preceeds) 00261 { 00262 __ret.field[0] = sign; 00263 __ret.field[1] = symbol; 00264 __ret.field[2] = space; 00265 __ret.field[3] = value; 00266 } 00267 else 00268 { 00269 __ret.field[0] = value; 00270 __ret.field[1] = space; 00271 __ret.field[2] = sign; 00272 __ret.field[3] = symbol; 00273 } 00274 } 00275 else 00276 { 00277 // Have none. 00278 if (__preceeds) 00279 { 00280 __ret.field[0] = sign; 00281 __ret.field[1] = symbol; 00282 __ret.field[2] = value; 00283 } 00284 else 00285 { 00286 __ret.field[0] = value; 00287 __ret.field[1] = sign; 00288 __ret.field[2] = symbol; 00289 } 00290 __ret.field[3] = none; 00291 } 00292 break; 00293 case 4: 00294 // 4 The sign immediately follows the symbol. 00295 if (__space) 00296 { 00297 // Have space. 00298 if (__preceeds) 00299 { 00300 __ret.field[0] = symbol; 00301 __ret.field[1] = sign; 00302 __ret.field[2] = space; 00303 __ret.field[3] = value; 00304 } 00305 else 00306 { 00307 __ret.field[0] = value; 00308 __ret.field[1] = space; 00309 __ret.field[2] = symbol; 00310 __ret.field[3] = sign; 00311 } 00312 } 00313 else 00314 { 00315 // Have none. 00316 if (__preceeds) 00317 { 00318 __ret.field[0] = symbol; 00319 __ret.field[1] = sign; 00320 __ret.field[2] = value; 00321 } 00322 else 00323 { 00324 __ret.field[0] = value; 00325 __ret.field[1] = symbol; 00326 __ret.field[2] = sign; 00327 } 00328 __ret.field[3] = none; 00329 } 00330 break; 00331 default: 00332 ; 00333 } 00334 return __ret; 00335 } 00336 00337 locale::~locale() throw() 00338 { _M_impl->_M_remove_reference(); } 00339 00340 void 00341 locale::_M_coalesce(const locale& __base, const locale& __add, 00342 category __cat) 00343 { 00344 __cat = _S_normalize_category(__cat); 00345 _M_impl = new _Impl(*__base._M_impl, 1); 00346 00347 try 00348 { _M_impl->_M_replace_categories(__add._M_impl, __cat); } 00349 catch (...) 00350 { 00351 _M_impl->_M_remove_reference(); 00352 __throw_exception_again; 00353 } 00354 } 00355 00356 locale::locale() throw() 00357 { 00358 _S_initialize(); 00359 (_M_impl = _S_global)->_M_add_reference(); 00360 } // XXX MT 00361 00362 locale::locale(const locale& __other) throw() 00363 { (_M_impl = __other._M_impl)->_M_add_reference(); } 00364 00365 locale::locale(_Impl* __ip) throw() 00366 : _M_impl(__ip) 00367 { __ip->_M_add_reference(); } 00368 00369 locale::locale(const char* __s) 00370 { 00371 if (__s) 00372 { 00373 if (strcmp(__s, "C") == 0 || strcmp(__s, "POSIX") == 0) 00374 (_M_impl = _S_classic)->_M_add_reference(); 00375 else 00376 _M_impl = new _Impl(__s, 1); 00377 } 00378 else 00379 __throw_runtime_error("attempt to create locale from NULL name"); 00380 } 00381 00382 locale::locale(const locale& __base, const char* __s, category __cat) 00383 { 00384 // NB: There are complicated, yet more efficient ways to do 00385 // this. Building up locales on a per-category way is tedious, so 00386 // let's do it this way until people complain. 00387 locale __add(__s); 00388 _M_coalesce(__base, __add, __cat); 00389 } 00390 00391 locale::locale(const locale& __base, const locale& __add, category __cat) 00392 { _M_coalesce(__base, __add, __cat); } 00393 00394 bool 00395 locale::operator==(const locale& __rhs) const throw() 00396 { 00397 string __name = this->name(); 00398 return (_M_impl == __rhs._M_impl 00399 || (__name != "*" && __name == __rhs.name())); 00400 } 00401 00402 const locale& 00403 locale::operator=(const locale& __other) throw() 00404 { 00405 __other._M_impl->_M_add_reference(); 00406 _M_impl->_M_remove_reference(); 00407 _M_impl = __other._M_impl; 00408 return *this; 00409 } 00410 00411 locale 00412 locale::global(const locale& __other) 00413 { 00414 // XXX MT 00415 _S_initialize(); 00416 locale __old(_S_global); 00417 __other._M_impl->_M_add_reference(); 00418 _S_global->_M_remove_reference(); 00419 _S_global = __other._M_impl; 00420 if (_S_global->_M_check_same_name() && _S_global->_M_names[0] != "*") 00421 setlocale(LC_ALL, __other.name().c_str()); 00422 return __old; 00423 } 00424 00425 string 00426 locale::name() const 00427 { 00428 string __ret; 00429 // Need some kind of separator character. This one was pretty much 00430 // arbitrarily chosen as to not conflict with glibc locales: the 00431 // exact formatting is not set in stone. 00432 const char __separator = '|'; 00433 00434 if (_M_impl->_M_check_same_name()) 00435 __ret = _M_impl->_M_names[0]; 00436 else 00437 { 00438 for (size_t i = 0; i < _S_num_categories; ++i) 00439 __ret += __separator + _M_impl->_M_names[i]; 00440 } 00441 return __ret; 00442 } 00443 00444 locale const& 00445 locale::classic() 00446 { 00447 static locale* __classic_locale; 00448 // XXX MT 00449 if (!_S_classic) 00450 { 00451 try 00452 { 00453 // 26 Standard facets, 2 references. 00454 // One reference for _M_classic, one for _M_global 00455 _S_classic = new _Impl("C", 2); 00456 _S_global = _S_classic; 00457 00458 // Finesse static init order hassles 00459 __classic_locale = new locale(_S_classic); 00460 } 00461 catch(...) 00462 { 00463 delete __classic_locale; 00464 if (_S_classic) 00465 { 00466 _S_classic->_M_remove_reference(); 00467 _S_global->_M_remove_reference(); 00468 } 00469 _S_classic = _S_global = 0; 00470 // XXX MT 00471 __throw_exception_again; 00472 } 00473 } 00474 return *__classic_locale; 00475 } 00476 00477 locale::category 00478 locale::_S_normalize_category(category __cat) 00479 { 00480 int __ret = 0; 00481 if (__cat == none || (__cat & all) && !(__cat & ~all)) 00482 __ret = __cat; 00483 else 00484 { 00485 // NB: May be a C-style "LC_ALL" category; convert. 00486 switch (__cat) 00487 { 00488 case LC_COLLATE: 00489 __ret = collate; 00490 break; 00491 case LC_CTYPE: 00492 __ret = ctype; 00493 break; 00494 case LC_MONETARY: 00495 __ret = monetary; 00496 break; 00497 case LC_NUMERIC: 00498 __ret = numeric; 00499 break; 00500 case LC_TIME: 00501 __ret = time; 00502 break; 00503 #ifdef _GLIBCPP_HAVE_LC_MESSAGES 00504 case LC_MESSAGES: 00505 __ret = messages; 00506 break; 00507 #endif 00508 case LC_ALL: 00509 __ret = all; 00510 break; 00511 default: 00512 __throw_runtime_error("bad locale category"); 00513 } 00514 } 00515 return __ret; 00516 } 00517 00518 locale::facet:: 00519 facet(size_t __refs) throw() 00520 : _M_references(__refs) 00521 { } 00522 00523 void 00524 locale::facet:: 00525 _M_add_reference() throw() 00526 { ++_M_references; } // XXX MT 00527 00528 void 00529 locale::facet:: 00530 _M_remove_reference() throw() 00531 { 00532 if (_M_references) 00533 --_M_references; 00534 else 00535 { 00536 try 00537 { delete this; } // XXX MT 00538 catch (...) 00539 { } 00540 } 00541 } 00542 00543 // Definitions for static const data members of ctype_base. 00544 const ctype_base::mask ctype_base::space; 00545 const ctype_base::mask ctype_base::print; 00546 const ctype_base::mask ctype_base::cntrl; 00547 const ctype_base::mask ctype_base::upper; 00548 const ctype_base::mask ctype_base::lower; 00549 const ctype_base::mask ctype_base::alpha; 00550 const ctype_base::mask ctype_base::digit; 00551 const ctype_base::mask ctype_base::punct; 00552 const ctype_base::mask ctype_base::xdigit; 00553 const ctype_base::mask ctype_base::alnum; 00554 const ctype_base::mask ctype_base::graph; 00555 00556 // Platform-specific initialization code for ctype tables. 00557 #include <bits/ctype_noninline.h> 00558 00559 const size_t ctype<char>::table_size; 00560 00561 ctype<char>::~ctype() 00562 { if (_M_del) delete[] this->table(); } 00563 00564 // These are dummy placeholders as these virtual functions are never called. 00565 bool 00566 ctype<char>::do_is(mask, char_type) const 00567 { return false; } 00568 00569 const char* 00570 ctype<char>::do_is(const char_type* __c, const char_type*, mask*) const 00571 { return __c; } 00572 00573 const char* 00574 ctype<char>::do_scan_is(mask, const char_type* __c, const char_type*) const 00575 { return __c; } 00576 00577 const char* 00578 ctype<char>::do_scan_not(mask, const char_type* __c, const char_type*) const 00579 { return __c; } 00580 00581 char 00582 ctype<char>::do_widen(char __c) const 00583 { return __c; } 00584 00585 const char* 00586 ctype<char>::do_widen(const char* __lo, const char* __hi, char* __dest) const 00587 { 00588 memcpy(__dest, __lo, __hi - __lo); 00589 return __hi; 00590 } 00591 00592 char 00593 ctype<char>::do_narrow(char __c, char /*__dfault*/) const 00594 { return __c; } 00595 00596 const char* 00597 ctype<char>::do_narrow(const char* __lo, const char* __hi, 00598 char /*__dfault*/, char* __dest) const 00599 { 00600 memcpy(__dest, __lo, __hi - __lo); 00601 return __hi; 00602 } 00603 00604 template<> 00605 ctype_byname<char>::ctype_byname(const char* /*__s*/, size_t __refs) 00606 : ctype<char>(new mask[table_size], true, __refs) 00607 { } 00608 00609 // Definitions for static const data members of money_base 00610 const money_base::pattern 00611 money_base::_S_default_pattern = {{symbol, sign, none, value}}; 00612 00613 template<> 00614 _Format_cache<char>::_Format_cache() 00615 : _M_valid(true), 00616 _M_decimal_point('.'), _M_thousands_sep(','), 00617 _M_truename("true"), _M_falsename("false"), _M_use_grouping(false) 00618 { } 00619 00620 #ifdef _GLIBCPP_USE_WCHAR_T 00621 template<> 00622 _Format_cache<wchar_t>::_Format_cache() 00623 : _M_valid(true), 00624 _M_decimal_point(L'.'), _M_thousands_sep(L','), 00625 _M_truename(L"true"), _M_falsename(L"false"), _M_use_grouping(false) 00626 { } 00627 #endif 00628 00629 template<> 00630 const ctype<char>& 00631 use_facet<ctype<char> >(const locale& __loc) 00632 { 00633 size_t __i = ctype<char>::id._M_index; 00634 const locale::_Impl* __tmp = __loc._M_impl; 00635 return static_cast<const ctype<char>&>(* (*(__tmp->_M_facets))[__i]); 00636 } 00637 00638 #ifdef _GLIBCPP_USE_WCHAR_T 00639 template<> 00640 const ctype<wchar_t>& 00641 use_facet<ctype<wchar_t> >(const locale& __loc) 00642 { 00643 size_t __i = ctype<wchar_t>::id._M_index; 00644 const locale::_Impl* __tmp = __loc._M_impl; 00645 return static_cast<const ctype<wchar_t>&>(* (*(__tmp->_M_facets))[__i]); 00646 } 00647 #endif 00648 00649 // This interface passes a fixed size buffer. The function cannot handle 00650 // input longer than the buffer and sets failbit in that case. This is 00651 // not strictly compliant since the input may be valid, but we are stuck 00652 // with this ABI on the 3.0 branch. Since leading zeros are discarded all 00653 // valid integer input should be OK, only floating point input can exceed 00654 // the buffer. 00655 template<> 00656 void 00657 num_get<char, istreambuf_iterator<char> >:: 00658 _M_extract(istreambuf_iterator<char> __beg, 00659 istreambuf_iterator<char> __end, ios_base& __io, 00660 ios_base::iostate& __err, char* __xtrc, int& __base, 00661 bool __fp) const 00662 { 00663 typedef _Format_cache<char> __cache_type; 00664 00665 // Prepare for possible failure 00666 __xtrc[0] = '\0'; 00667 00668 // Stage 1: determine a conversion specifier. 00669 ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield; 00670 if (__basefield == ios_base::dec) 00671 __base = 10; 00672 else if (__basefield == ios_base::oct) 00673 __base = 8; 00674 else if (__basefield == ios_base::hex) 00675 __base = 16; 00676 else 00677 __base = 0; 00678 // As far as I can tell, bases other than 10 are not available for 00679 // floating point types 00680 if (__fp) 00681 __base = 10; 00682 00683 // Stage 2: extract characters. 00684 __cache_type const* __fmt = __cache_type::_S_get(__io); 00685 00686 // Fail quickly if !__valid 00687 if (__beg == __end) 00688 { 00689 __err |= (ios_base::eofbit | ios_base::failbit); 00690 return; 00691 } 00692 00693 // Acceptable formats for numbers here are based on 22.2.3.1 00694 string __grp; 00695 int __sep_pos = 0; 00696 int __pos = 0; 00697 const char* __lits = __fmt->_S_literals; 00698 char __c = *__beg; 00699 00700 // Check first for sign 00701 bool __testsign = false; 00702 if ((__c == __lits[__cache_type::_S_minus]) 00703 || (__c == __lits[__cache_type::_S_plus])) 00704 { 00705 __testsign = true; 00706 __xtrc[__pos++] = __c; 00707 ++__beg; 00708 __c = * __beg; 00709 00710 // Whitespace may follow a sign 00711 while ((__beg != __end) && (isspace(__c))) 00712 { 00713 ++__beg; 00714 __c = *__beg; 00715 } 00716 00717 // There had better be more to come... 00718 if (__beg == __end) 00719 { 00720 __xtrc[__pos] = '\0'; 00721 __err |= (ios_base::eofbit | ios_base::failbit); 00722 return; 00723 } 00724 } 00725 00726 // Now check if first character is a zero. 00727 bool __testzero = false; 00728 if (__c == __lits[__cache_type::_S_digits]) 00729 { 00730 __testzero = true; 00731 ++__beg; 00732 __c = *__beg; 00733 00734 // We have to check for __beg == __end here. If so, 00735 // a plain '0' (possibly with a sign) can be got rid of now 00736 if (__beg == __end) 00737 { 00738 __xtrc[__pos++] = __lits[__cache_type::_S_digits]; 00739 __xtrc[__pos] = '\0'; 00740 __err |= ios_base::eofbit; 00741 return; 00742 } 00743 00744 // Figure out base for integer types only 00745 // Based on Table 55 of 22.2.2.1.2 00746 if (!__fp && __base != 10 && __base != 8) 00747 { 00748 // Here, __base == 0 or 16 00749 if ((__c == __lits[__cache_type::_S_x]) 00750 || (__c == __lits[__cache_type::_S_X])) 00751 { 00752 ++__beg; 00753 __c = *__beg; 00754 __base = 16; 00755 __testzero = false; // "0x" is not a leading zero 00756 } 00757 else if (__base == 0) 00758 __base = 8; 00759 } 00760 00761 // Remove any more leading zeros 00762 while (__beg != __end) 00763 { 00764 if (__c == __lits[__cache_type::_S_digits]) 00765 { 00766 ++__beg; 00767 __c = *__beg; 00768 __testzero = true; 00769 } 00770 else 00771 break; 00772 } 00773 } 00774 else if (__base == 0) // 1st character is not zero 00775 __base = 10; 00776 00777 // We now seek "units", i.e. digits and thousands separators. 00778 // We may need to know if anything is found here. A leading zero 00779 // (removed by now) would count. 00780 bool __testunits = __testzero; 00781 while (__beg != __end) 00782 { 00783 const char* __p = strchr(__lits, __c); 00784 00785 // NB: strchr returns true for __c == 0x0 00786 if (__p && __c 00787 &&((__p >= &__lits[__cache_type::_S_digits] 00788 && __p < &__lits[__cache_type::_S_digits + __base]) 00789 || (__p >= &__lits[__cache_type::_S_udigits] 00790 && __p < &__lits[__cache_type::_S_udigits + __base]))) 00791 { 00792 // Try first for acceptable digit; record it if found. 00793 __xtrc[__pos++] = __c; 00794 if (__pos == _M_extract_buffer_length) 00795 { 00796 // XXX This is non-compliant, but our fixed-size 00797 // buffer is full. 00798 __xtrc[_M_extract_buffer_length-1] = '\0'; 00799 __err |= ios_base::failbit; 00800 return; 00801 } 00802 ++__sep_pos; 00803 __testunits = true; 00804 ++__beg; 00805 __c = *__beg; 00806 } 00807 else if (__c == __fmt->_M_thousands_sep && __fmt->_M_use_grouping) 00808 { 00809 // NB: Thousands separator at the beginning of a string 00810 // is a no-no, as is two consecutive thousands 00811 // separators. 00812 if (__sep_pos) 00813 { 00814 __grp += static_cast<char>(__sep_pos); 00815 __sep_pos = 0; 00816 ++__beg; 00817 __c = *__beg; 00818 } 00819 else 00820 { 00821 __err |= ios_base::failbit; 00822 break; 00823 } 00824 } 00825 else 00826 // Not a valid input item. 00827 break; 00828 } 00829 00830 // Digit grouping is checked. If _M_groupings() doesn't 00831 // match, then get very very upset, and set failbit. 00832 if (__fmt->_M_use_grouping && !__grp.empty()) 00833 { 00834 // Add the ending grouping 00835 __grp += static_cast<char>(__sep_pos); 00836 00837 // __grp is parsed L to R 00838 // 1,222,444 == __grp of "/1/3/3" 00839 // __fmt->_M_grouping is parsed R to L 00840 // 1,222,444 == __fmt->_M_grouping of "/3" == "/3/3/3" 00841 int __i = 0; 00842 int __j = 0; 00843 const int __len = __fmt->_M_grouping.size(); 00844 int __n = __grp.size(); 00845 bool __test = true; 00846 00847 // Parsed number groupings have to match the 00848 // numpunct::grouping string exactly, starting at the 00849 // right-most point of the parsed sequence of elements ... 00850 while (__test && __i < __n - 1) 00851 for (__j = 0; __test && __j < __len && __i < __n - 1; ++__j,++__i) 00852 __test &= __fmt->_M_grouping[__j] == __grp[__n - __i - 1]; 00853 // ... but the last parsed grouping can be <= numpunct 00854 // grouping. 00855 __j == __len ? __j = 0 : __j; 00856 __test &= __fmt->_M_grouping[__j] >= __grp[__n - __i - 1]; 00857 00858 if (!__test) 00859 { 00860 __err |= ios_base::failbit; 00861 __xtrc[__pos] = '\0'; 00862 if (__beg == __end) 00863 __err |= ios_base::eofbit; 00864 return; 00865 } 00866 } 00867 00868 // If there was nothing but zeros, put one in the output string 00869 if (__testzero && (__pos == 0 || (__pos == 1 && __testsign))) 00870 __xtrc[__pos++] = __lits[__cache_type::_S_digits]; 00871 00872 // That's it for integer types. Remaining code is for floating point 00873 if (__fp && __beg != __end) 00874 { 00875 // Check first for decimal point. There MUST be one if 00876 // __testunits is false. 00877 bool __testdec = false; // Is there a decimal point 00878 // with digits following it? 00879 if (__c == __fmt->_M_decimal_point) 00880 { 00881 __xtrc[__pos++] = '.'; 00882 if (__pos == _M_extract_buffer_length) 00883 { 00884 // XXX This is non-compliant, but our fixed-size 00885 // buffer is full. 00886 __xtrc[_M_extract_buffer_length-1] = '\0'; 00887 __err |= ios_base::failbit; 00888 return; 00889 } 00890 ++__beg; 00891 __c = *__beg; 00892 00893 // Now we get any digits after the decimal point 00894 // There MUST be some if __testunits is false. 00895 while (__beg != __end) 00896 { 00897 const char* __p = strchr(__lits, __c); 00898 if ((__p >= &__lits[__cache_type::_S_digits] 00899 && __p < &__lits[__cache_type::_S_digits + __base]) 00900 || (__p >= &__lits[__cache_type::_S_udigits] 00901 && __p < &__lits[__cache_type::_S_udigits + __base])) 00902 { 00903 __xtrc[__pos++] = __c; 00904 if (__pos == _M_extract_buffer_length) 00905 { 00906 // XXX This is non-compliant, but our fixed-size 00907 // buffer is full. 00908 __xtrc[_M_extract_buffer_length-1] = '\0'; 00909 __err |= ios_base::failbit; 00910 return; 00911 } 00912 ++__beg; 00913 __c = *__beg; 00914 __testdec = true; 00915 } 00916 else 00917 break; 00918 } 00919 } 00920 if (!__testunits && !__testdec) // Ill formed 00921 { 00922 __err |= ios_base::failbit; 00923 __xtrc[__pos] = '\0'; 00924 if (__beg == __end) 00925 __err |= ios_base::eofbit; 00926 return; 00927 } 00928 00929 // Now we may find an exponent 00930 if (__beg != __end) 00931 { 00932 if ((__c == __lits[__cache_type::_S_ee]) 00933 || (__c == __lits[__cache_type::_S_Ee])) 00934 { 00935 __xtrc[__pos++] = __c; 00936 if (__pos == _M_extract_buffer_length) 00937 { 00938 // XXX This is non-compliant, but our fixed-size 00939 // buffer is full. 00940 __xtrc[_M_extract_buffer_length-1] = '\0'; 00941 __err |= ios_base::failbit; 00942 return; 00943 } 00944 ++__beg; 00945 __c = *__beg; 00946 00947 // Now there may be a sign 00948 if (__beg != __end) 00949 { 00950 if ((__c == __lits[__cache_type::_S_minus]) 00951 || (__c == __lits[__cache_type::_S_plus])) 00952 { 00953 __xtrc[__pos++] = __c; 00954 if (__pos == _M_extract_buffer_length) 00955 { 00956 // XXX This is non-compliant, but our fixed-size 00957 // buffer is full. 00958 __xtrc[_M_extract_buffer_length-1] = '\0'; 00959 __err |= ios_base::failbit; 00960 return; 00961 } 00962 ++__beg; 00963 __c = *__beg; 00964 // whitespace may follow a sign 00965 while ((__beg != __end) && (isspace(__c))) 00966 { 00967 ++__beg; 00968 __c = *__beg; 00969 } 00970 } 00971 } 00972 // And now there must be some digits 00973 if (__beg == __end) 00974 { 00975 __xtrc[__pos] = '\0'; 00976 __err |= (ios_base::eofbit | ios_base::failbit); 00977 return; 00978 } 00979 while (__beg != __end) 00980 { 00981 const char* __p = strchr(__lits, __c); 00982 if ((__p >= &__lits[__cache_type::_S_digits] 00983 && __p < &__lits[__cache_type::_S_digits + __base]) 00984 || (__p >= &__lits[__cache_type::_S_udigits] 00985 && __p < &__lits[__cache_type::_S_udigits + __base])) 00986 { 00987 __xtrc[__pos++] = __c; 00988 if (__pos == _M_extract_buffer_length) 00989 { 00990 // XXX This is non-compliant, but our fixed-size 00991 // buffer is full. 00992 __xtrc[_M_extract_buffer_length-1] = '\0'; 00993 __err |= ios_base::failbit; 00994 return; 00995 } 00996 ++__beg; 00997 __c = *__beg; 00998 } 00999 else 01000 break; 01001 } 01002 } 01003 } 01004 // Finally, that's it for floating point 01005 } 01006 01007 // Finish up 01008 __xtrc[__pos] = '\0'; 01009 if (__beg == __end) 01010 __err |= ios_base::eofbit; 01011 } 01012 01013 // The following code uses sprintf() to convert floating point 01014 // values for insertion into a stream. The current implementation 01015 // replicates the code in _S_pad_numeric() (in _S_output_float()) in 01016 // order to prevent having to create a "wide" buffer in addition to 01017 // the "narrow" buffer passed to sprintf(). An optimization would be 01018 // to replace sprintf() with code that works directly on a wide 01019 // buffer and then use _S_pad_numeric() to do the padding. It would 01020 // be good to replace sprintf() anyway to avoid accidental buffer 01021 // overruns and to gain back the efficiency that C++ provides by 01022 // knowing up front the type of the values to insert. This 01023 // implementation follows the C++ standard fairly directly as 01024 // outlined in 22.2.2.2 [lib.locale.num.put] 01025 bool 01026 __build_float_format(ios_base& __io, char* __fptr, char __modifier, 01027 streamsize __prec) 01028 { 01029 bool __incl_prec = false; 01030 ios_base::fmtflags __flags = __io.flags(); 01031 *__fptr++ = '%'; 01032 // [22.2.2.2.2] Table 60 01033 if (__flags & ios_base::showpos) 01034 *__fptr++ = '+'; 01035 if (__flags & ios_base::showpoint) 01036 *__fptr++ = '#'; 01037 // As per [22.2.2.2.2.11] 01038 if (__flags & ios_base::fixed || __prec > 0) 01039 { 01040 *__fptr++ = '.'; 01041 *__fptr++ = '*'; 01042 __incl_prec = true; 01043 } 01044 if (__modifier) 01045 *__fptr++ = __modifier; 01046 ios_base::fmtflags __fltfield = __flags & ios_base::floatfield; 01047 // [22.2.2.2.2] Table 58 01048 if (__fltfield == ios_base::fixed) 01049 *__fptr++ = 'f'; 01050 else if (__fltfield == ios_base::scientific) 01051 *__fptr++ = (__flags & ios_base::uppercase) ? 'E' : 'e'; 01052 else 01053 *__fptr++ = (__flags & ios_base::uppercase) ? 'G' : 'g'; 01054 *__fptr = '\0'; 01055 return __incl_prec; 01056 } 01057 01058 template <> 01059 collate<char>::collate(size_t __refs) 01060 : locale::facet(__refs) { } 01061 01062 template<> 01063 collate<char>::~collate() { } 01064 01065 template<> 01066 int 01067 collate<char>::do_compare(const char* __lo1, const char* __hi1, 01068 const char* __lo2, const char* __hi2) const 01069 { 01070 for (; __lo1 < __hi1 && __lo2 < __hi2; ++__lo1, ++__lo2) 01071 if (*__lo1 != *__lo2) 01072 return (*__lo1 < *__lo2) ? -1 : 1; 01073 if (__lo1 < __hi1) 01074 return 1; 01075 else if (__lo2 < __hi2) 01076 return -1; 01077 else 01078 return 0; 01079 } 01080 01081 template<> 01082 string 01083 collate<char>:: 01084 do_transform(const char* __lo, const char* __hi) const 01085 { return string(__lo, __hi - __lo); } 01086 01087 template<> 01088 long 01089 collate<char>:: 01090 do_hash(const char* __lo, const char* __hi) const 01091 { 01092 unsigned long __val = 0xdeadbeef; 01093 for (; __lo < __hi; ++__lo) 01094 __val = *__lo ^ ((__val << 7) & 01095 (__val >> (numeric_limits<unsigned long>::digits - 1))); 01096 return __val; 01097 } 01098 01099 template<> 01100 collate_byname<char>::collate_byname(const char* /*__s*/, size_t __refs) 01101 : collate<char>(__refs) { } 01102 01103 template<> 01104 moneypunct_byname<char, false>::moneypunct_byname(const char* /*__s*/, 01105 size_t __refs) 01106 : moneypunct<char, false>(__refs) { } 01107 01108 template<> 01109 moneypunct_byname<char, true>::moneypunct_byname(const char* /*__s*/, 01110 size_t __refs) 01111 : moneypunct<char, true>(__refs) { } 01112 01113 template<> 01114 messages_byname<char>:: 01115 messages_byname(const char* /*__s*/, size_t __refs) 01116 : messages<char>(__refs) { } 01117 01118 #ifdef _GLIBCPP_USE_WCHAR_T 01119 ctype<wchar_t>::__wmask_type 01120 ctype<wchar_t>::_M_convert_to_wmask(const mask __m) const 01121 { 01122 __wmask_type __ret; 01123 switch (__m) 01124 { 01125 case space: 01126 __ret = wctype("space"); 01127 break; 01128 case print: 01129 __ret = wctype("print"); 01130 break; 01131 case cntrl: 01132 __ret = wctype("cntrl"); 01133 break; 01134 case upper: 01135 __ret = wctype("upper"); 01136 break; 01137 case lower: 01138 __ret = wctype("lower"); 01139 break; 01140 case alpha: 01141 __ret = wctype("alpha"); 01142 break; 01143 case digit: 01144 __ret = wctype("digit"); 01145 break; 01146 case punct: 01147 __ret = wctype("punct"); 01148 break; 01149 case xdigit: 01150 __ret = wctype("xdigit"); 01151 break; 01152 case alnum: 01153 __ret = wctype("alnum"); 01154 break; 01155 case graph: 01156 __ret = wctype("graph"); 01157 break; 01158 default: 01159 __ret = 0; 01160 } 01161 return __ret; 01162 }; 01163 01164 ctype<wchar_t>::~ctype() { } 01165 01166 // NB: These ctype<wchar_t> methods are not configuration-specific, 01167 // unlike the ctype<char> bits. 01168 ctype<wchar_t>::ctype(size_t __refs) : __ctype_abstract_base<wchar_t>(__refs) 01169 { } 01170 01171 wchar_t 01172 ctype<wchar_t>::do_toupper(wchar_t __c) const 01173 { return towupper(__c); } 01174 01175 const wchar_t* 01176 ctype<wchar_t>::do_toupper(wchar_t* __lo, const wchar_t* __hi) const 01177 { 01178 while (__lo < __hi) 01179 { 01180 *__lo = towupper(*__lo); 01181 ++__lo; 01182 } 01183 return __hi; 01184 } 01185 01186 wchar_t 01187 ctype<wchar_t>::do_tolower(wchar_t __c) const 01188 { return towlower(__c); } 01189 01190 const wchar_t* 01191 ctype<wchar_t>::do_tolower(wchar_t* __lo, const wchar_t* __hi) const 01192 { 01193 while (__lo < __hi) 01194 { 01195 *__lo = towlower(*__lo); 01196 ++__lo; 01197 } 01198 return __hi; 01199 } 01200 01201 bool 01202 ctype<wchar_t>:: 01203 do_is(mask __m, char_type __c) const 01204 { return static_cast<bool>(iswctype(__c, _M_convert_to_wmask(__m))); } 01205 01206 const wchar_t* 01207 ctype<wchar_t>:: 01208 do_is(const wchar_t* __lo, const wchar_t* __hi, mask* __m) const 01209 { 01210 while (__lo < __hi && !this->is(*__m, *__lo)) 01211 ++__lo; 01212 return __lo; 01213 } 01214 01215 const wchar_t* 01216 ctype<wchar_t>:: 01217 do_scan_is(mask __m, const wchar_t* __lo, const wchar_t* __hi) const 01218 { 01219 while (__lo < __hi && !this->is(__m, *__lo)) 01220 ++__lo; 01221 return __lo; 01222 } 01223 01224 const wchar_t* 01225 ctype<wchar_t>:: 01226 do_scan_not(mask __m, const char_type* __lo, const char_type* __hi) const 01227 { 01228 while (__lo < __hi && this->is(__m, *__lo) != 0) 01229 ++__lo; 01230 return __lo; 01231 } 01232 01233 wchar_t 01234 ctype<wchar_t>:: 01235 do_widen(char __c) const 01236 { return btowc(__c); } 01237 01238 const char* 01239 ctype<wchar_t>:: 01240 do_widen(const char* __lo, const char* __hi, wchar_t* __dest) const 01241 { 01242 mbstate_t __state; 01243 memset(static_cast<void*>(&__state), 0, sizeof(mbstate_t)); 01244 mbsrtowcs(__dest, &__lo, __hi - __lo, &__state); 01245 return __hi; 01246 } 01247 01248 char 01249 ctype<wchar_t>:: 01250 do_narrow(wchar_t __wc, char __dfault) const 01251 { 01252 int __c = wctob(__wc); 01253 return (__c == EOF ? __dfault : static_cast<char>(__c)); 01254 } 01255 01256 const wchar_t* 01257 ctype<wchar_t>:: 01258 do_narrow(const wchar_t* __lo, const wchar_t* __hi, char __dfault, 01259 char* __dest) const 01260 { 01261 mbstate_t __state; 01262 memset(static_cast<void*>(&__state), 0, sizeof(mbstate_t)); 01263 size_t __len = __hi - __lo; 01264 size_t __conv = wcsrtombs(__dest, &__lo, __len, &__state); 01265 if (__conv == __len) 01266 *__dest = __dfault; 01267 return __hi; 01268 } 01269 01270 template<> 01271 ctype_byname<wchar_t>:: 01272 ctype_byname(const char* /*__s*/, size_t __refs) 01273 : ctype<wchar_t>(__refs) { } 01274 01275 template<> 01276 collate<wchar_t>:: 01277 collate(size_t __refs): locale::facet(__refs) { } 01278 01279 template<> 01280 collate<wchar_t>:: 01281 ~collate() { } 01282 01283 template<> 01284 int 01285 collate<wchar_t>:: 01286 do_compare(const wchar_t* /*__lo1*/, const wchar_t* /*__hi1*/, 01287 const wchar_t* /*__lo2*/, const wchar_t* /*__hi2*/) const 01288 { 01289 return 0; // XXX not done 01290 } 01291 01292 template<> 01293 wstring collate<wchar_t>:: 01294 do_transform(const wchar_t* /*__lo*/, const wchar_t* /*__hi*/) const 01295 { 01296 return wstring(); // XXX not done 01297 } 01298 01299 template<> 01300 long collate<wchar_t>:: 01301 do_hash(const wchar_t* /*__lo*/, const wchar_t* /*__hi*/) const 01302 { 01303 return 0; // XXX not done 01304 } 01305 01306 template<> 01307 collate_byname<wchar_t>:: 01308 collate_byname(const char* /*__s*/, size_t __refs) 01309 : collate<wchar_t> (__refs) { } 01310 01311 template<> 01312 messages_byname<wchar_t>:: 01313 messages_byname(const char* /*__s*/, size_t __refs) 01314 : messages<wchar_t> (__refs) { } 01315 #endif // _GLIBCPP_USE_WCHAR_T 01316 } // namespace std 01317 Generated on Mon Apr 8 03:11:28 2002 for libstdc++-v3 Source by ![]() |