Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
6554 serge 1
// Copyright (C) 1997-2015 Free Software Foundation, Inc.
2
//
3
// This file is part of the GNU ISO C++ Library.  This library is free
4
// software; you can redistribute it and/or modify it under the
5
// terms of the GNU General Public License as published by the
6
// Free Software Foundation; either version 3, or (at your option)
7
// any later version.
8
 
9
// This library is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13
 
14
// Under Section 7 of GPL version 3, you are granted additional
15
// permissions described in the GCC Runtime Library Exception, version
16
// 3.1, as published by the Free Software Foundation.
17
 
18
// You should have received a copy of the GNU General Public License and
19
// a copy of the GCC Runtime Library Exception along with this program;
20
// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
21
// .
22
 
23
#define _GLIBCXX_USE_CXX11_ABI 1
24
#include 
25
#include 
26
#include      // For getenv
27
#include 
28
#include      // For towupper, etc.
29
#include 
30
#include 
31
 
32
namespace
33
{
34
  __gnu_cxx::__mutex&
35
  get_locale_cache_mutex()
36
  {
37
    static __gnu_cxx::__mutex locale_cache_mutex;
38
    return locale_cache_mutex;
39
  }
40
} // anonymous namespace
41
 
42
// XXX GLIBCXX_ABI Deprecated
43
#ifdef _GLIBCXX_LONG_DOUBLE_COMPAT
44
# define _GLIBCXX_LOC_ID(mangled) extern std::locale::id mangled
45
_GLIBCXX_LOC_ID (_ZNSt7num_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE2idE);
46
_GLIBCXX_LOC_ID (_ZNSt7num_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE2idE);
47
_GLIBCXX_LOC_ID (_ZNSt9money_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE2idE);
48
_GLIBCXX_LOC_ID (_ZNSt9money_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE2idE);
49
# ifdef _GLIBCXX_USE_WCHAR_T
50
_GLIBCXX_LOC_ID (_ZNSt7num_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE2idE);
51
_GLIBCXX_LOC_ID (_ZNSt7num_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE2idE);
52
_GLIBCXX_LOC_ID (_ZNSt9money_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE2idE);
53
_GLIBCXX_LOC_ID (_ZNSt9money_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE2idE);
54
# endif
55
#endif
56
 
57
namespace std _GLIBCXX_VISIBILITY(default)
58
{
59
_GLIBCXX_BEGIN_NAMESPACE_VERSION
60
 
61
  // Definitions for static const data members of locale.
62
  const locale::category 	locale::none;
63
  const locale::category 	locale::ctype;
64
  const locale::category 	locale::numeric;
65
  const locale::category 	locale::collate;
66
  const locale::category 	locale::time;
67
  const locale::category 	locale::monetary;
68
  const locale::category 	locale::messages;
69
  const locale::category 	locale::all;
70
 
71
  // These are no longer exported.
72
  locale::_Impl*                locale::_S_classic;
73
  locale::_Impl* 		locale::_S_global;
74
 
75
#ifdef __GTHREADS
76
  __gthread_once_t 		locale::_S_once = __GTHREAD_ONCE_INIT;
77
#endif
78
 
79
  locale::locale(const locale& __other) throw()
80
  : _M_impl(__other._M_impl)
81
  { _M_impl->_M_add_reference(); }
82
 
83
  // This is used to initialize global and classic locales, and
84
  // assumes that the _Impl objects are constructed correctly.
85
  // The lack of a reference increment is intentional.
86
  locale::locale(_Impl* __ip) throw() : _M_impl(__ip)
87
  { }
88
 
89
  locale::~locale() throw()
90
  { _M_impl->_M_remove_reference(); }
91
 
92
  bool
93
  locale::operator==(const locale& __rhs) const throw()
94
  {
95
    // Deal first with the common cases, fast to process: refcopies,
96
    // unnamed (i.e., !_M_names[0]), "simple" (!_M_names[1] => all the
97
    // categories same name, i.e., _M_names[0]). Otherwise fall back
98
    // to the general locale::name().
99
    bool __ret;
100
    if (_M_impl == __rhs._M_impl)
101
      __ret = true;
102
    else if (!_M_impl->_M_names[0] || !__rhs._M_impl->_M_names[0]
103
	     || std::strcmp(_M_impl->_M_names[0],
104
			    __rhs._M_impl->_M_names[0]) != 0)
105
      __ret = false;
106
    else if (!_M_impl->_M_names[1] && !__rhs._M_impl->_M_names[1])
107
      __ret = true;
108
    else
109
      __ret = this->name() == __rhs.name();
110
    return __ret;
111
  }
112
 
113
  const locale&
114
  locale::operator=(const locale& __other) throw()
115
  {
116
    __other._M_impl->_M_add_reference();
117
    _M_impl->_M_remove_reference();
118
    _M_impl = __other._M_impl;
119
    return *this;
120
  }
121
 
122
  _GLIBCXX_DEFAULT_ABI_TAG
123
  string
124
  locale::name() const
125
  {
126
    string __ret;
127
    if (!_M_impl->_M_names[0])
128
      __ret = '*';
129
    else if (_M_impl->_M_check_same_name())
130
      __ret = _M_impl->_M_names[0];
131
    else
132
      {
133
	__ret.reserve(128);
134
	__ret += _S_categories[0];
135
	__ret += '=';
136
	__ret += _M_impl->_M_names[0];
137
	for (size_t __i = 1; __i < _S_categories_size; ++__i)
138
	  {
139
	    __ret += ';';
140
	    __ret += _S_categories[__i];
141
	    __ret += '=';
142
	    __ret += _M_impl->_M_names[__i];
143
	  }
144
      }
145
    return __ret;
146
  }
147
 
148
  locale::category
149
  locale::_S_normalize_category(category __cat)
150
  {
151
    int __ret = 0;
152
    if (__cat == none || ((__cat & all) && !(__cat & ~all)))
153
      __ret = __cat;
154
    else
155
      {
156
	// NB: May be a C-style "LC_ALL" category; convert.
157
	switch (__cat)
158
	  {
159
	  case LC_COLLATE:
160
	    __ret = collate;
161
	    break;
162
	  case LC_CTYPE:
163
	    __ret = ctype;
164
	    break;
165
	  case LC_MONETARY:
166
	    __ret = monetary;
167
	    break;
168
	  case LC_NUMERIC:
169
	    __ret = numeric;
170
	    break;
171
	  case LC_TIME:
172
	    __ret = time;
173
	    break;
174
#ifdef _GLIBCXX_HAVE_LC_MESSAGES
175
	  case LC_MESSAGES:
176
	    __ret = messages;
177
	    break;
178
#endif
179
	  case LC_ALL:
180
	    __ret = all;
181
	    break;
182
	  default:
183
	    __throw_runtime_error(__N("locale::_S_normalize_category "
184
				  "category not found"));
185
	  }
186
      }
187
    return __ret;
188
  }
189
 
190
  // locale::facet
191
  __c_locale locale::facet::_S_c_locale;
192
 
193
  const char locale::facet::_S_c_name[2] = "C";
194
 
195
#ifdef __GTHREADS
196
  __gthread_once_t locale::facet::_S_once = __GTHREAD_ONCE_INIT;
197
#endif
198
 
199
  void
200
  locale::facet::_S_initialize_once()
201
  {
202
    // Initialize the underlying locale model.
203
    _S_create_c_locale(_S_c_locale, _S_c_name);
204
  }
205
 
206
  __c_locale
207
  locale::facet::_S_get_c_locale()
208
  {
209
#ifdef __GTHREADS
210
    if (__gthread_active_p())
211
      __gthread_once(&_S_once, _S_initialize_once);
212
    else
213
#endif
214
      {
215
	if (!_S_c_locale)
216
	  _S_initialize_once();
217
      }
218
    return _S_c_locale;
219
  }
220
 
221
  const char*
222
  locale::facet::_S_get_c_name() throw()
223
  { return _S_c_name; }
224
 
225
  locale::facet::
226
  ~facet() { }
227
 
228
  // locale::_Impl
229
  locale::_Impl::
230
  ~_Impl() throw()
231
  {
232
    if (_M_facets)
233
      for (size_t __i = 0; __i < _M_facets_size; ++__i)
234
	if (_M_facets[__i])
235
	  _M_facets[__i]->_M_remove_reference();
236
    delete [] _M_facets;
237
 
238
    if (_M_caches)
239
      for (size_t __i = 0; __i < _M_facets_size; ++__i)
240
	if (_M_caches[__i])
241
	  _M_caches[__i]->_M_remove_reference();
242
    delete [] _M_caches;
243
 
244
    if (_M_names)
245
      for (size_t __i = 0; __i < _S_categories_size; ++__i)
246
	delete [] _M_names[__i];
247
    delete [] _M_names;
248
  }
249
 
250
  // Clone existing _Impl object.
251
  locale::_Impl::
252
  _Impl(const _Impl& __imp, size_t __refs)
253
  : _M_refcount(__refs), _M_facets(0), _M_facets_size(__imp._M_facets_size),
254
  _M_caches(0), _M_names(0)
255
  {
256
    __try
257
      {
258
	_M_facets = new const facet*[_M_facets_size];
259
	for (size_t __i = 0; __i < _M_facets_size; ++__i)
260
	  {
261
	    _M_facets[__i] = __imp._M_facets[__i];
262
	    if (_M_facets[__i])
263
	      _M_facets[__i]->_M_add_reference();
264
	  }
265
	_M_caches = new const facet*[_M_facets_size];
266
	for (size_t __j = 0; __j < _M_facets_size; ++__j)
267
	  {
268
	    _M_caches[__j] = __imp._M_caches[__j];
269
	    if (_M_caches[__j])
270
	      _M_caches[__j]->_M_add_reference();
271
	  }
272
	_M_names = new char*[_S_categories_size];
273
	for (size_t __k = 0; __k < _S_categories_size; ++__k)
274
	  _M_names[__k] = 0;
275
 
276
	// Name the categories.
277
	for (size_t __l = 0; (__l < _S_categories_size
278
			      && __imp._M_names[__l]); ++__l)
279
	  {
280
	    const size_t __len = std::strlen(__imp._M_names[__l]) + 1;
281
	    _M_names[__l] = new char[__len];
282
	    std::memcpy(_M_names[__l], __imp._M_names[__l], __len);
283
	  }
284
      }
285
    __catch(...)
286
      {
287
	this->~_Impl();
288
	__throw_exception_again;
289
      }
290
  }
291
 
292
  void
293
  locale::_Impl::
294
  _M_replace_category(const _Impl* __imp,
295
		      const locale::id* const* __idpp)
296
  {
297
    for (; *__idpp; ++__idpp)
298
      _M_replace_facet(__imp, *__idpp);
299
  }
300
 
301
  void
302
  locale::_Impl::
303
  _M_replace_facet(const _Impl* __imp, const locale::id* __idp)
304
  {
305
    size_t __index = __idp->_M_id();
306
    if ((__index > (__imp->_M_facets_size - 1))
307
	|| !__imp->_M_facets[__index])
308
      __throw_runtime_error(__N("locale::_Impl::_M_replace_facet"));
309
    _M_install_facet(__idp, __imp->_M_facets[__index]);
310
  }
311
 
312
  void
313
  locale::_Impl::
314
  _M_install_facet(const locale::id* __idp, const facet* __fp)
315
  {
316
    if (__fp)
317
      {
318
	size_t __index = __idp->_M_id();
319
 
320
	// Check size of facet vector to ensure adequate room.
321
	if (__index > _M_facets_size - 1)
322
	  {
323
	    const size_t __new_size = __index + 4;
324
 
325
	    // New facet array.
326
	    const facet** __oldf = _M_facets;
327
	    const facet** __newf;
328
	    __newf = new const facet*[__new_size];
329
	    for (size_t __i = 0; __i < _M_facets_size; ++__i)
330
	      __newf[__i] = _M_facets[__i];
331
	    for (size_t __l = _M_facets_size; __l < __new_size; ++__l)
332
	      __newf[__l] = 0;
333
 
334
	    // New cache array.
335
	    const facet** __oldc = _M_caches;
336
	    const facet** __newc;
337
	    __try
338
	      {
339
		__newc = new const facet*[__new_size];
340
	      }
341
	    __catch(...)
342
	      {
343
		delete [] __newf;
344
		__throw_exception_again;
345
	      }
346
	    for (size_t __j = 0; __j < _M_facets_size; ++__j)
347
	      __newc[__j] = _M_caches[__j];
348
	    for (size_t __k = _M_facets_size; __k < __new_size; ++__k)
349
	      __newc[__k] = 0;
350
 
351
	    _M_facets_size = __new_size;
352
	    _M_facets = __newf;
353
	    _M_caches = __newc;
354
	    delete [] __oldf;
355
	    delete [] __oldc;
356
	  }
357
 
358
	__fp->_M_add_reference();
359
	const facet*& __fpr = _M_facets[__index];
360
	if (__fpr)
361
	  {
362
#if _GLIBCXX_USE_DUAL_ABI
363
            // If this is a twinned facet replace its twin with a shim.
364
            for (const id* const* p = _S_twinned_facets; *p != 0; p += 2)
365
              {
366
                if (p[0]->_M_id() == __index)
367
                  {
368
                    // replacing the old ABI facet, also replace new ABI twin
369
                    const facet*& __fpr2 = _M_facets[p[1]->_M_id()];
370
                    if (__fpr2)
371
                      {
372
                        const facet* __fp2 = __fp->_M_sso_shim(p[1]);
373
                        __fp2->_M_add_reference();
374
                        __fpr2->_M_remove_reference();
375
                        __fpr2 = __fp2;
376
                      }
377
                    break;
378
                  }
379
                else if (p[1]->_M_id() == __index)
380
                  {
381
                    // replacing the new ABI facet, also replace old ABI twin
382
                    const facet*& __fpr2 = _M_facets[p[0]->_M_id()];
383
                    if (__fpr2)
384
                      {
385
                        const facet* __fp2 = __fp->_M_cow_shim(p[0]);
386
                        __fp2->_M_add_reference();
387
                        __fpr2->_M_remove_reference();
388
                        __fpr2 = __fp2;
389
                      }
390
                    break;
391
                  }
392
              }
393
#endif
394
	    // Replacing an existing facet. Order matters.
395
	    __fpr->_M_remove_reference();
396
	    __fpr = __fp;
397
	  }
398
	else
399
	  {
400
	    // Installing a newly created facet into an empty
401
	    // _M_facets container, say a newly-constructed,
402
	    // swanky-fresh _Impl.
403
	    _M_facets[__index] = __fp;
404
	  }
405
 
406
	// Ideally, it would be nice to only remove the caches that
407
	// are now incorrect. However, some of the caches depend on
408
	// multiple facets, and we only know about one facet
409
	// here. It's no great loss: the first use of the new facet
410
	// will create a new, correctly cached facet anyway.
411
	for (size_t __i = 0; __i < _M_facets_size; ++__i)
412
	  {
413
	    const facet* __cpr = _M_caches[__i];
414
	    if (__cpr)
415
	      {
416
		__cpr->_M_remove_reference();
417
		_M_caches[__i] = 0;
418
	      }
419
	  }
420
      }
421
  }
422
 
423
  void
424
  locale::_Impl::
425
  _M_install_cache(const facet* __cache, size_t __index)
426
  {
427
    __gnu_cxx::__scoped_lock sentry(get_locale_cache_mutex());
428
#if _GLIBCXX_USE_DUAL_ABI
429
    // If this cache is for one of the facets that is instantiated twice,
430
    // for old and new std::string ABI, install it in both slots.
431
    size_t __index2 = -1;
432
    for (const id* const* p = _S_twinned_facets; *p != 0; p += 2)
433
      {
434
        if (p[0]->_M_id() == __index)
435
          {
436
            __index2 = p[1]->_M_id();
437
            break;
438
          }
439
        else if (p[1]->_M_id() == __index)
440
          {
441
            __index2 = __index;
442
            __index = p[0]->_M_id();
443
            break;
444
          }
445
      }
446
#endif
447
    if (_M_caches[__index] != 0)
448
      {
449
	// Some other thread got in first.
450
	delete __cache;
451
      }
452
    else
453
      {
454
	__cache->_M_add_reference();
455
	_M_caches[__index] = __cache;
456
#if _GLIBCXX_USE_DUAL_ABI
457
        if (__index2 != size_t(-1))
458
          {
459
            __cache->_M_add_reference();
460
            _M_caches[__index2] = __cache;
461
          }
462
#endif
463
      }
464
  }
465
 
466
  // locale::id
467
  // Definitions for static const data members of locale::id
468
  _Atomic_word locale::id::_S_refcount;  // init'd to 0 by linker
469
 
470
  size_t
471
  locale::id::_M_id() const throw()
472
  {
473
    if (!_M_index)
474
      {
475
	// XXX GLIBCXX_ABI Deprecated
476
#ifdef _GLIBCXX_LONG_DOUBLE_COMPAT
477
	locale::id *f = 0;
478
# define _GLIBCXX_SYNC_ID(facet, mangled) \
479
	if (this == &::mangled)				\
480
	  f = &facet::id
481
	_GLIBCXX_SYNC_ID (num_get, _ZNSt7num_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE2idE);
482
	_GLIBCXX_SYNC_ID (num_put, _ZNSt7num_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE2idE);
483
	_GLIBCXX_SYNC_ID (money_get, _ZNSt9money_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE2idE);
484
	_GLIBCXX_SYNC_ID (money_put, _ZNSt9money_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE2idE);
485
# ifdef _GLIBCXX_USE_WCHAR_T
486
	_GLIBCXX_SYNC_ID (num_get, _ZNSt7num_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE2idE);
487
	_GLIBCXX_SYNC_ID (num_put, _ZNSt7num_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE2idE);
488
	_GLIBCXX_SYNC_ID (money_get, _ZNSt9money_getIwSt19istreambuf_iteratorIwSt11char_traitsIwEEE2idE);
489
	_GLIBCXX_SYNC_ID (money_put, _ZNSt9money_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE2idE);
490
# endif
491
	if (f)
492
	  _M_index = 1 + f->_M_id();
493
	else
494
#endif
495
	  _M_index = 1 + __gnu_cxx::__exchange_and_add_dispatch(&_S_refcount,
496
								1);
497
      }
498
    return _M_index - 1;
499
  }
500
 
501
_GLIBCXX_END_NAMESPACE_VERSION
502
} // namespace