00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include <clocale>
00030 #include <cstring>
00031 #include <cstdlib>
00032 #include <cctype>
00033 #include <cwctype>
00034 #include <locale>
00035 #include <bits/atomicity.h>
00036
00037 namespace std
00038 {
00039
00040 const locale::category locale::none;
00041 const locale::category locale::ctype;
00042 const locale::category locale::numeric;
00043 const locale::category locale::collate;
00044 const locale::category locale::time;
00045 const locale::category locale::monetary;
00046 const locale::category locale::messages;
00047 const locale::category locale::all;
00048
00049
00050 locale::_Impl* locale::_S_classic;
00051 locale::_Impl* locale::_S_global;
00052 const size_t locale::_S_categories_size;
00053
00054 #ifdef __GTHREADS
00055 __gthread_once_t locale::_S_once = __GTHREAD_ONCE_INIT;
00056 #endif
00057
00058 locale::locale(const locale& __other) throw()
00059 : _M_impl(__other._M_impl)
00060 { _M_impl->_M_add_reference(); }
00061
00062
00063
00064
00065 locale::locale(_Impl* __ip) throw() : _M_impl(__ip)
00066 { }
00067
00068 locale::~locale() throw()
00069 { _M_impl->_M_remove_reference(); }
00070
00071 bool
00072 locale::operator==(const locale& __rhs) const throw()
00073 {
00074 bool __ret = false;
00075 if (_M_impl == __rhs._M_impl)
00076 __ret = true;
00077 else
00078 {
00079 const string __name = this->name();
00080 if (__name != "*" && __name == __rhs.name())
00081 __ret = true;
00082 }
00083 return __ret;
00084 }
00085
00086 const locale&
00087 locale::operator=(const locale& __other) throw()
00088 {
00089 __other._M_impl->_M_add_reference();
00090 _M_impl->_M_remove_reference();
00091 _M_impl = __other._M_impl;
00092 return *this;
00093 }
00094
00095 string
00096 locale::name() const
00097 {
00098 string __ret;
00099 if (_M_impl->_M_check_same_name())
00100 __ret = _M_impl->_M_names[0];
00101 else
00102 {
00103 __ret += _S_categories[0];
00104 __ret += '=';
00105 __ret += _M_impl->_M_names[0];
00106 for (size_t __i = 1; __i < _S_categories_size; ++__i)
00107 {
00108 __ret += ';';
00109 __ret += _S_categories[__i];
00110 __ret += '=';
00111 __ret += _M_impl->_M_names[__i];
00112 }
00113 }
00114 return __ret;
00115 }
00116
00117 locale::category
00118 locale::_S_normalize_category(category __cat)
00119 {
00120 int __ret = 0;
00121 if (__cat == none || (__cat & all) && !(__cat & ~all))
00122 __ret = __cat;
00123 else
00124 {
00125
00126 switch (__cat)
00127 {
00128 case LC_COLLATE:
00129 __ret = collate;
00130 break;
00131 case LC_CTYPE:
00132 __ret = ctype;
00133 break;
00134 case LC_MONETARY:
00135 __ret = monetary;
00136 break;
00137 case LC_NUMERIC:
00138 __ret = numeric;
00139 break;
00140 case LC_TIME:
00141 __ret = time;
00142 break;
00143 #ifdef _GLIBCXX_HAVE_LC_MESSAGES
00144 case LC_MESSAGES:
00145 __ret = messages;
00146 break;
00147 #endif
00148 case LC_ALL:
00149 __ret = all;
00150 break;
00151 default:
00152 __throw_runtime_error(__N("locale::_S_normalize_category "
00153 "category not found"));
00154 }
00155 }
00156 return __ret;
00157 }
00158
00159
00160 __c_locale locale::facet::_S_c_locale;
00161
00162 const char locale::facet::_S_c_name[2] = "C";
00163
00164 #ifdef __GTHREADS
00165 __gthread_once_t locale::facet::_S_once = __GTHREAD_ONCE_INIT;
00166 #endif
00167
00168 void
00169 locale::facet::_S_initialize_once()
00170 {
00171
00172 _S_create_c_locale(_S_c_locale, _S_c_name);
00173 }
00174
00175 __c_locale
00176 locale::facet::_S_get_c_locale()
00177 {
00178 #ifdef __GHTREADS
00179 if (__gthread_active_p())
00180 __gthread_once(&_S_once, _S_initialize_once);
00181 else
00182 #endif
00183 {
00184 if (!_S_c_locale)
00185 _S_initialize_once();
00186 }
00187 return _S_c_locale;
00188 }
00189
00190 const char*
00191 locale::facet::_S_get_c_name()
00192 { return _S_c_name; }
00193
00194 locale::facet::
00195 ~facet() { }
00196
00197
00198 locale::_Impl::
00199 ~_Impl() throw()
00200 {
00201 if (_M_facets)
00202 for (size_t __i = 0; __i < _M_facets_size; ++__i)
00203 if (_M_facets[__i])
00204 _M_facets[__i]->_M_remove_reference();
00205 delete [] _M_facets;
00206
00207 if (_M_caches)
00208 for (size_t __i = 0; __i < _M_facets_size; ++__i)
00209 if (_M_caches[__i])
00210 _M_caches[__i]->_M_remove_reference();
00211 delete [] _M_caches;
00212
00213 if (_M_names)
00214 for (size_t __i = 0; __i < _S_categories_size; ++__i)
00215 delete [] _M_names[__i];
00216 delete [] _M_names;
00217 }
00218
00219
00220 locale::_Impl::
00221 _Impl(const _Impl& __imp, size_t __refs)
00222 : _M_refcount(__refs), _M_facets(0), _M_facets_size(__imp._M_facets_size),
00223 _M_caches(0), _M_names(0)
00224 {
00225 try
00226 {
00227 _M_facets = new const facet*[_M_facets_size];
00228 for (size_t __i = 0; __i < _M_facets_size; ++__i)
00229 {
00230 _M_facets[__i] = __imp._M_facets[__i];
00231 if (_M_facets[__i])
00232 _M_facets[__i]->_M_add_reference();
00233 }
00234 _M_caches = new const facet*[_M_facets_size];
00235 for (size_t __j = 0; __j < _M_facets_size; ++__j)
00236 {
00237 _M_caches[__j] = __imp._M_caches[__j];
00238 if (_M_caches[__j])
00239 _M_caches[__j]->_M_add_reference();
00240 }
00241 _M_names = new char*[_S_categories_size];
00242 for (size_t __k = 0; __k < _S_categories_size; ++__k)
00243 _M_names[__k] = 0;
00244
00245
00246 for (size_t __l = 0; __l < _S_categories_size; ++__l)
00247 {
00248 char* __new = new char[std::strlen(__imp._M_names[__l]) + 1];
00249 std::strcpy(__new, __imp._M_names[__l]);
00250 _M_names[__l] = __new;
00251 }
00252 }
00253 catch(...)
00254 {
00255 this->~_Impl();
00256 __throw_exception_again;
00257 }
00258 }
00259
00260 void
00261 locale::_Impl::
00262 _M_replace_category(const _Impl* __imp,
00263 const locale::id* const* __idpp)
00264 {
00265 for (; *__idpp; ++__idpp)
00266 _M_replace_facet(__imp, *__idpp);
00267 }
00268
00269 void
00270 locale::_Impl::
00271 _M_replace_facet(const _Impl* __imp, const locale::id* __idp)
00272 {
00273 size_t __index = __idp->_M_id();
00274 if ((__index > (__imp->_M_facets_size - 1))
00275 || !__imp->_M_facets[__index])
00276 __throw_runtime_error(__N("locale::_Impl::_M_replace_facet"));
00277 _M_install_facet(__idp, __imp->_M_facets[__index]);
00278 }
00279
00280 void
00281 locale::_Impl::
00282 _M_install_facet(const locale::id* __idp, const facet* __fp)
00283 {
00284 if (__fp)
00285 {
00286 size_t __index = __idp->_M_id();
00287
00288
00289 if (__index > _M_facets_size - 1)
00290 {
00291 const size_t __new_size = __index + 4;
00292
00293
00294 const facet** __oldf = _M_facets;
00295 const facet** __newf;
00296 __newf = new const facet*[__new_size];
00297 for (size_t __i = 0; __i < _M_facets_size; ++__i)
00298 __newf[__i] = _M_facets[__i];
00299 for (size_t __l = _M_facets_size; __l < __new_size; ++__l)
00300 __newf[__l] = 0;
00301
00302
00303 const facet** __oldc = _M_caches;
00304 const facet** __newc;
00305 try
00306 {
00307 __newc = new const facet*[__new_size];
00308 }
00309 catch(...)
00310 {
00311 delete [] __newf;
00312 __throw_exception_again;
00313 }
00314 for (size_t __j = 0; __j < _M_facets_size; ++__j)
00315 __newc[__j] = _M_caches[__j];
00316 for (size_t __k = _M_facets_size; __k < __new_size; ++__k)
00317 __newc[__k] = 0;
00318
00319 _M_facets_size = __new_size;
00320 _M_facets = __newf;
00321 _M_caches = __newc;
00322 delete [] __oldf;
00323 delete [] __oldc;
00324 }
00325
00326 __fp->_M_add_reference();
00327 const facet*& __fpr = _M_facets[__index];
00328 if (__fpr)
00329 {
00330
00331 __fpr->_M_remove_reference();
00332 __fpr = __fp;
00333 }
00334 else
00335 {
00336
00337
00338
00339 _M_facets[__index] = __fp;
00340 }
00341
00342
00343
00344
00345
00346
00347 for (size_t __i = 0; __i < _M_facets_size; ++__i)
00348 {
00349 const facet* __cpr = _M_caches[__i];
00350 if (__cpr)
00351 {
00352 __cpr->_M_remove_reference();
00353 _M_caches[__i] = 0;
00354 }
00355 }
00356 }
00357 }
00358
00359
00360
00361
00362 _Atomic_word locale::id::_S_refcount;
00363
00364 size_t
00365 locale::id::_M_id() const
00366 {
00367 if (!_M_index)
00368 _M_index = 1 + __gnu_cxx::__exchange_and_add(&_S_refcount, 1);
00369 return _M_index - 1;
00370 }
00371 }
00372
00373