]> git.ipfire.org Git - thirdparty/gcc.git/blame - libstdc++-v3/config/locale/gnu/c_locale.cc
Update copyright years.
[thirdparty/gcc.git] / libstdc++-v3 / config / locale / gnu / c_locale.cc
CommitLineData
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
40namespace 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
258namespace __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
281namespace 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