]>
Commit | Line | Data |
---|---|---|
0214010c BK |
1 | // Wrapper for underlying C-language localization -*- C++ -*- |
2 | ||
8d9254fc | 3 | // Copyright (C) 2001-2020 Free Software Foundation, Inc. |
0214010c BK |
4 | // |
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 | |
748086b7 | 8 | // Free Software Foundation; either version 3, or (at your option) |
0214010c BK |
9 | // any later version. |
10 | ||
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. | |
15 | ||
748086b7 JJ |
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. | |
0214010c | 19 | |
748086b7 JJ |
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/>. | |
0214010c BK |
24 | |
25 | // | |
26 | // ISO C++ 14882: 22.8 Standard locale categories. | |
27 | // | |
28 | ||
29 | // Written by Benjamin Kosnik <bkoz@redhat.com> | |
30 | ||
31 | #include <locale> | |
32 | #include <stdexcept> | |
5ef46f95 | 33 | #include <limits> |
9702ee6a | 34 | #include <algorithm> |
0214010c | 35 | #include <langinfo.h> |
6aa43d99 | 36 | #include <bits/c++locale_internal.h> |
0214010c | 37 | |
9702ee6a FD |
38 | #include <backward/auto_ptr.h> |
39 | ||
12ffa228 BK |
40 | namespace std _GLIBCXX_VISIBILITY(default) |
41 | { | |
42 | _GLIBCXX_BEGIN_NAMESPACE_VERSION | |
3cbc7af0 | 43 | |
4b9aaf63 BK |
44 | template<> |
45 | void | |
f92ab29f | 46 | __convert_to_v(const char* __s, float& __v, ios_base::iostate& __err, |
32ade559 | 47 | const __c_locale& __cloc) throw() |
4b9aaf63 | 48 | { |
d04e9b7f | 49 | char* __sanity; |
5ef46f95 PC |
50 | __v = __strtof_l(__s, &__sanity, __cloc); |
51 | ||
52 | // _GLIBCXX_RESOLVE_LIB_DEFECTS | |
53 | // 23. Num_get overflow result. | |
54 | if (__sanity == __s || *__sanity != '\0') | |
55 | { | |
56 | __v = 0.0f; | |
57 | __err = ios_base::failbit; | |
58 | } | |
59 | else if (__v == numeric_limits<float>::infinity()) | |
60 | { | |
61 | __v = numeric_limits<float>::max(); | |
62 | __err = ios_base::failbit; | |
63 | } | |
64 | else if (__v == -numeric_limits<float>::infinity()) | |
65 | { | |
66 | __v = -numeric_limits<float>::max(); | |
67 | __err = ios_base::failbit; | |
68 | } | |
4b9aaf63 BK |
69 | } |
70 | ||
71 | template<> | |
72 | void | |
f92ab29f | 73 | __convert_to_v(const char* __s, double& __v, ios_base::iostate& __err, |
32ade559 | 74 | const __c_locale& __cloc) throw() |
4b9aaf63 | 75 | { |
d04e9b7f | 76 | char* __sanity; |
5ef46f95 PC |
77 | __v = __strtod_l(__s, &__sanity, __cloc); |
78 | ||
79 | // _GLIBCXX_RESOLVE_LIB_DEFECTS | |
80 | // 23. Num_get overflow result. | |
81 | if (__sanity == __s || *__sanity != '\0') | |
82 | { | |
83 | __v = 0.0; | |
84 | __err = ios_base::failbit; | |
85 | } | |
86 | else if (__v == numeric_limits<double>::infinity()) | |
87 | { | |
88 | __v = numeric_limits<double>::max(); | |
89 | __err = ios_base::failbit; | |
90 | } | |
91 | else if (__v == -numeric_limits<double>::infinity()) | |
92 | { | |
93 | __v = -numeric_limits<double>::max(); | |
94 | __err = ios_base::failbit; | |
95 | } | |
4b9aaf63 BK |
96 | } |
97 | ||
98 | template<> | |
99 | void | |
100 | __convert_to_v(const char* __s, long double& __v, ios_base::iostate& __err, | |
32ade559 | 101 | const __c_locale& __cloc) throw() |
4b9aaf63 | 102 | { |
d04e9b7f | 103 | char* __sanity; |
29520adf JJ |
104 | #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) |
105 | // Prefer strtold_l, as __strtold_l isn't prototyped in more recent | |
106 | // glibc versions. | |
5ef46f95 | 107 | __v = strtold_l(__s, &__sanity, __cloc); |
29520adf | 108 | #else |
5ef46f95 | 109 | __v = __strtold_l(__s, &__sanity, __cloc); |
29520adf | 110 | #endif |
5ef46f95 PC |
111 | |
112 | // _GLIBCXX_RESOLVE_LIB_DEFECTS | |
113 | // 23. Num_get overflow result. | |
114 | if (__sanity == __s || *__sanity != '\0') | |
115 | { | |
116 | __v = 0.0l; | |
117 | __err = ios_base::failbit; | |
118 | } | |
119 | else if (__v == numeric_limits<long double>::infinity()) | |
120 | { | |
121 | __v = numeric_limits<long double>::max(); | |
122 | __err = ios_base::failbit; | |
123 | } | |
124 | else if (__v == -numeric_limits<long double>::infinity()) | |
125 | { | |
126 | __v = -numeric_limits<long double>::max(); | |
127 | __err = ios_base::failbit; | |
128 | } | |
4b9aaf63 BK |
129 | } |
130 | ||
0214010c | 131 | void |
f92ab29f | 132 | locale::facet::_S_create_c_locale(__c_locale& __cloc, const char* __s, |
d3a193e3 | 133 | __c_locale __old) |
0214010c | 134 | { |
d3a193e3 | 135 | __cloc = __newlocale(1 << LC_ALL, __s, __old); |
0214010c BK |
136 | if (!__cloc) |
137 | { | |
138 | // This named locale is not supported by the underlying OS. | |
ba9119ec | 139 | __throw_runtime_error(__N("locale::facet::_S_create_c_locale " |
c8036448 | 140 | "name not valid")); |
0214010c BK |
141 | } |
142 | } | |
c8036448 | 143 | |
0214010c BK |
144 | void |
145 | locale::facet::_S_destroy_c_locale(__c_locale& __cloc) | |
aa53f832 | 146 | { |
cd6dba21 | 147 | if (__cloc && _S_get_c_locale() != __cloc) |
f92ab29f | 148 | __freelocale(__cloc); |
aa53f832 | 149 | } |
0214010c | 150 | |
33590f13 | 151 | __c_locale |
32ade559 | 152 | locale::facet::_S_clone_c_locale(__c_locale& __cloc) throw() |
33590f13 | 153 | { return __duplocale(__cloc); } |
aa53f832 | 154 | |
c8036448 PC |
155 | __c_locale |
156 | locale::facet::_S_lc_ctype_c_locale(__c_locale __cloc, const char* __s) | |
157 | { | |
158 | __c_locale __dup = __duplocale(__cloc); | |
159 | if (__dup == __c_locale(0)) | |
160 | __throw_runtime_error(__N("locale::facet::_S_lc_ctype_c_locale " | |
161 | "duplocale error")); | |
0dca2153 | 162 | #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) |
c8036448 | 163 | __c_locale __changed = __newlocale(LC_CTYPE_MASK, __s, __dup); |
0dca2153 PC |
164 | #else |
165 | __c_locale __changed = __newlocale(1 << LC_CTYPE, __s, __dup); | |
166 | #endif | |
c8036448 PC |
167 | if (__changed == __c_locale(0)) |
168 | { | |
169 | __freelocale(__dup); | |
170 | __throw_runtime_error(__N("locale::facet::_S_lc_ctype_c_locale " | |
171 | "newlocale error")); | |
172 | } | |
173 | return __changed; | |
174 | } | |
175 | ||
9702ee6a FD |
176 | struct _CatalogIdComp |
177 | { | |
178 | bool | |
179 | operator()(messages_base::catalog __cat, const Catalog_info* __info) const | |
180 | { return __cat < __info->_M_id; } | |
181 | ||
182 | bool | |
183 | operator()(const Catalog_info* __info, messages_base::catalog __cat) const | |
184 | { return __info->_M_id < __cat; } | |
185 | }; | |
186 | ||
187 | Catalogs::~Catalogs() | |
188 | { | |
189 | for (vector<Catalog_info*>::iterator __it = _M_infos.begin(); | |
190 | __it != _M_infos.end(); ++__it) | |
191 | delete *__it; | |
192 | } | |
193 | ||
194 | messages_base::catalog | |
195 | Catalogs::_M_add(const char* __domain, locale __l) | |
196 | { | |
197 | __gnu_cxx::__scoped_lock lock(_M_mutex); | |
198 | ||
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 | |
201 | // moment. | |
202 | if (_M_catalog_counter == numeric_limits<messages_base::catalog>::max()) | |
203 | return -1; | |
204 | ||
205 | auto_ptr<Catalog_info> info(new Catalog_info(_M_catalog_counter++, | |
206 | __domain, __l)); | |
207 | ||
208 | // Check if we managed to allocate memory for domain. | |
209 | if (!info->_M_domain) | |
210 | return -1; | |
211 | ||
212 | _M_infos.push_back(info.get()); | |
213 | return info.release()->_M_id; | |
214 | } | |
215 | ||
216 | void | |
217 | Catalogs::_M_erase(messages_base::catalog __c) | |
218 | { | |
219 | __gnu_cxx::__scoped_lock lock(_M_mutex); | |
220 | ||
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) | |
224 | return; | |
225 | ||
226 | delete *__res; | |
227 | _M_infos.erase(__res); | |
228 | ||
229 | // Just in case closed catalog was the last open. | |
230 | if (__c == _M_catalog_counter - 1) | |
231 | --_M_catalog_counter; | |
232 | } | |
233 | ||
234 | const Catalog_info* | |
235 | Catalogs::_M_get(messages_base::catalog __c) const | |
236 | { | |
237 | __gnu_cxx::__scoped_lock lock(_M_mutex); | |
238 | ||
239 | vector<Catalog_info*>::const_iterator __res = | |
240 | lower_bound(_M_infos.begin(), _M_infos.end(), __c, _CatalogIdComp()); | |
241 | ||
242 | if (__res != _M_infos.end() && (*__res)->_M_id == __c) | |
243 | return *__res; | |
244 | ||
245 | return 0; | |
246 | } | |
247 | ||
248 | Catalogs& | |
249 | get_catalogs() | |
250 | { | |
251 | static Catalogs __catalogs; | |
252 | return __catalogs; | |
253 | } | |
254 | ||
12ffa228 BK |
255 | _GLIBCXX_END_NAMESPACE_VERSION |
256 | } // namespace | |
3cbc7af0 | 257 | |
12ffa228 BK |
258 | namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) |
259 | { | |
260 | _GLIBCXX_BEGIN_NAMESPACE_VERSION | |
3cbc7af0 | 261 | |
8ae81136 | 262 | const char* const category_names[6 + _GLIBCXX_NUM_CATEGORIES] = |
aa53f832 | 263 | { |
f92ab29f | 264 | "LC_CTYPE", |
0e9501e6 | 265 | "LC_NUMERIC", |
f92ab29f CG |
266 | "LC_TIME", |
267 | "LC_COLLATE", | |
aa53f832 | 268 | "LC_MONETARY", |
f92ab29f CG |
269 | "LC_MESSAGES", |
270 | "LC_PAPER", | |
271 | "LC_NAME", | |
aa53f832 | 272 | "LC_ADDRESS", |
f92ab29f CG |
273 | "LC_TELEPHONE", |
274 | "LC_MEASUREMENT", | |
275 | "LC_IDENTIFICATION" | |
aa53f832 | 276 | }; |
73c4dcc6 | 277 | |
12ffa228 BK |
278 | _GLIBCXX_END_NAMESPACE_VERSION |
279 | } // namespace | |
3cbc7af0 | 280 | |
12ffa228 BK |
281 | namespace std _GLIBCXX_VISIBILITY(default) |
282 | { | |
283 | _GLIBCXX_BEGIN_NAMESPACE_VERSION | |
3cbc7af0 | 284 | |
8ae81136 | 285 | const char* const* const locale::_S_categories = __gnu_cxx::category_names; |
3cbc7af0 | 286 | |
12ffa228 BK |
287 | _GLIBCXX_END_NAMESPACE_VERSION |
288 | } // namespace | |
6defecc2 JJ |
289 | |
290 | // XXX GLIBCXX_ABI Deprecated | |
291 | #ifdef _GLIBCXX_LONG_DOUBLE_COMPAT | |
d56a3683 | 292 | #pragma GCC diagnostic ignored "-Wattribute-alias" |
6defecc2 JJ |
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 |