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