1 // Wrapper for underlying C-language localization -*- C++ -*-
3 // Copyright (C) 2001-2020 Free Software Foundation, Inc.
5 // This file is part of the GNU ISO C++ Library. This library is free
6 // software; you can redistribute it and/or modify it under the
7 // terms of the GNU General Public License as published by the
8 // Free Software Foundation; either version 3, or (at your option)
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // Under Section 7 of GPL version 3, you are granted additional
17 // permissions described in the GCC Runtime Library Exception, version
18 // 3.1, as published by the Free Software Foundation.
20 // You should have received a copy of the GNU General Public License and
21 // a copy of the GCC Runtime Library Exception along with this program;
22 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23 // <http://www.gnu.org/licenses/>.
26 // ISO C++ 14882: 22.8 Standard locale categories.
29 // Written by Benjamin Kosnik <bkoz@redhat.com>
36 #include <bits/c++locale_internal.h>
38 #include <backward/auto_ptr.h>
40 namespace std
_GLIBCXX_VISIBILITY(default)
42 _GLIBCXX_BEGIN_NAMESPACE_VERSION
46 __convert_to_v(const char* __s
, float& __v
, ios_base::iostate
& __err
,
47 const __c_locale
& __cloc
) throw()
50 __v
= __strtof_l(__s
, &__sanity
, __cloc
);
52 // _GLIBCXX_RESOLVE_LIB_DEFECTS
53 // 23. Num_get overflow result.
54 if (__sanity
== __s
|| *__sanity
!= '\0')
57 __err
= ios_base::failbit
;
59 else if (__v
== numeric_limits
<float>::infinity())
61 __v
= numeric_limits
<float>::max();
62 __err
= ios_base::failbit
;
64 else if (__v
== -numeric_limits
<float>::infinity())
66 __v
= -numeric_limits
<float>::max();
67 __err
= ios_base::failbit
;
73 __convert_to_v(const char* __s
, double& __v
, ios_base::iostate
& __err
,
74 const __c_locale
& __cloc
) throw()
77 __v
= __strtod_l(__s
, &__sanity
, __cloc
);
79 // _GLIBCXX_RESOLVE_LIB_DEFECTS
80 // 23. Num_get overflow result.
81 if (__sanity
== __s
|| *__sanity
!= '\0')
84 __err
= ios_base::failbit
;
86 else if (__v
== numeric_limits
<double>::infinity())
88 __v
= numeric_limits
<double>::max();
89 __err
= ios_base::failbit
;
91 else if (__v
== -numeric_limits
<double>::infinity())
93 __v
= -numeric_limits
<double>::max();
94 __err
= ios_base::failbit
;
100 __convert_to_v(const char* __s
, long double& __v
, ios_base::iostate
& __err
,
101 const __c_locale
& __cloc
) throw()
104 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
105 // Prefer strtold_l, as __strtold_l isn't prototyped in more recent
107 __v
= strtold_l(__s
, &__sanity
, __cloc
);
109 __v
= __strtold_l(__s
, &__sanity
, __cloc
);
112 // _GLIBCXX_RESOLVE_LIB_DEFECTS
113 // 23. Num_get overflow result.
114 if (__sanity
== __s
|| *__sanity
!= '\0')
117 __err
= ios_base::failbit
;
119 else if (__v
== numeric_limits
<long double>::infinity())
121 __v
= numeric_limits
<long double>::max();
122 __err
= ios_base::failbit
;
124 else if (__v
== -numeric_limits
<long double>::infinity())
126 __v
= -numeric_limits
<long double>::max();
127 __err
= ios_base::failbit
;
132 locale::facet::_S_create_c_locale(__c_locale
& __cloc
, const char* __s
,
135 __cloc
= __newlocale(1 << LC_ALL
, __s
, __old
);
138 // This named locale is not supported by the underlying OS.
139 __throw_runtime_error(__N("locale::facet::_S_create_c_locale "
145 locale::facet::_S_destroy_c_locale(__c_locale
& __cloc
)
147 if (__cloc
&& _S_get_c_locale() != __cloc
)
148 __freelocale(__cloc
);
152 locale::facet::_S_clone_c_locale(__c_locale
& __cloc
) throw()
153 { return __duplocale(__cloc
); }
156 locale::facet::_S_lc_ctype_c_locale(__c_locale __cloc
, const char* __s
)
158 __c_locale __dup
= __duplocale(__cloc
);
159 if (__dup
== __c_locale(0))
160 __throw_runtime_error(__N("locale::facet::_S_lc_ctype_c_locale "
162 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
163 __c_locale __changed
= __newlocale(LC_CTYPE_MASK
, __s
, __dup
);
165 __c_locale __changed
= __newlocale(1 << LC_CTYPE
, __s
, __dup
);
167 if (__changed
== __c_locale(0))
170 __throw_runtime_error(__N("locale::facet::_S_lc_ctype_c_locale "
176 struct _CatalogIdComp
179 operator()(messages_base::catalog __cat
, const Catalog_info
* __info
) const
180 { return __cat
< __info
->_M_id
; }
183 operator()(const Catalog_info
* __info
, messages_base::catalog __cat
) const
184 { return __info
->_M_id
< __cat
; }
187 Catalogs::~Catalogs()
189 for (vector
<Catalog_info
*>::iterator __it
= _M_infos
.begin();
190 __it
!= _M_infos
.end(); ++__it
)
194 messages_base::catalog
195 Catalogs::_M_add(const char* __domain
, locale __l
)
197 __gnu_cxx::__scoped_lock
lock(_M_mutex
);
199 // The counter is not likely to roll unless catalogs keep on being
200 // opened/closed which is consider as an application mistake for the
202 if (_M_catalog_counter
== numeric_limits
<messages_base::catalog
>::max())
205 auto_ptr
<Catalog_info
> info(new Catalog_info(_M_catalog_counter
++,
208 // Check if we managed to allocate memory for domain.
209 if (!info
->_M_domain
)
212 _M_infos
.push_back(info
.get());
213 return info
.release()->_M_id
;
217 Catalogs::_M_erase(messages_base::catalog __c
)
219 __gnu_cxx::__scoped_lock
lock(_M_mutex
);
221 vector
<Catalog_info
*>::iterator __res
=
222 lower_bound(_M_infos
.begin(), _M_infos
.end(), __c
, _CatalogIdComp());
223 if (__res
== _M_infos
.end() || (*__res
)->_M_id
!= __c
)
227 _M_infos
.erase(__res
);
229 // Just in case closed catalog was the last open.
230 if (__c
== _M_catalog_counter
- 1)
231 --_M_catalog_counter
;
235 Catalogs::_M_get(messages_base::catalog __c
) const
237 __gnu_cxx::__scoped_lock
lock(_M_mutex
);
239 vector
<Catalog_info
*>::const_iterator __res
=
240 lower_bound(_M_infos
.begin(), _M_infos
.end(), __c
, _CatalogIdComp());
242 if (__res
!= _M_infos
.end() && (*__res
)->_M_id
== __c
)
251 static Catalogs __catalogs
;
255 _GLIBCXX_END_NAMESPACE_VERSION
258 namespace __gnu_cxx
_GLIBCXX_VISIBILITY(default)
260 _GLIBCXX_BEGIN_NAMESPACE_VERSION
262 const char* const category_names
[6 + _GLIBCXX_NUM_CATEGORIES
] =
278 _GLIBCXX_END_NAMESPACE_VERSION
281 namespace std
_GLIBCXX_VISIBILITY(default)
283 _GLIBCXX_BEGIN_NAMESPACE_VERSION
285 const char* const* const locale::_S_categories
= __gnu_cxx::category_names
;
287 _GLIBCXX_END_NAMESPACE_VERSION
290 // XXX GLIBCXX_ABI Deprecated
291 #ifdef _GLIBCXX_LONG_DOUBLE_COMPAT
292 #pragma GCC diagnostic ignored "-Wattribute-alias"
293 #define _GLIBCXX_LDBL_COMPAT(dbl, ldbl) \
294 extern "C" void ldbl (void) __attribute__ ((alias (#dbl)))
295 _GLIBCXX_LDBL_COMPAT(_ZSt14__convert_to_vIdEvPKcRT_RSt12_Ios_IostateRKP15__locale_struct
, _ZSt14__convert_to_vIeEvPKcRT_RSt12_Ios_IostateRKP15__locale_struct
);
296 #endif // _GLIBCXX_LONG_DOUBLE_COMPAT