]> git.ipfire.org Git - thirdparty/gcc.git/blame - libstdc++-v3/config/locale/gnu/numeric_members.cc
Update copyright years.
[thirdparty/gcc.git] / libstdc++-v3 / config / locale / gnu / numeric_members.cc
CommitLineData
72e2386f 1// std::numpunct implementation details, GNU version -*- C++ -*-
ea0c0b6e 2
83ffe9cd 3// Copyright (C) 2001-2023 Free Software Foundation, Inc.
ea0c0b6e
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)
ea0c0b6e
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.
19
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/>.
ea0c0b6e
BK
24
25//
72e2386f 26// ISO C++ 14882: 22.2.3.1.2 numpunct virtual functions
ea0c0b6e
BK
27//
28
29// Written by Benjamin Kosnik <bkoz@redhat.com>
30
31#include <locale>
6aa43d99 32#include <bits/c++locale_internal.h>
c0ace69e 33#include <iconv.h>
ea0c0b6e 34
12ffa228
BK
35namespace std _GLIBCXX_VISIBILITY(default)
36{
37_GLIBCXX_BEGIN_NAMESPACE_VERSION
3cbc7af0 38
c0ace69e
JW
39 extern char __narrow_multibyte_chars(const char* s, __locale_t cloc);
40
41// This file might be compiled twice, but we only want to define this once.
42#if ! _GLIBCXX_USE_CXX11_ABI
43 char
44 __narrow_multibyte_chars(const char* s, __locale_t cloc)
45 {
46 const char* codeset = __nl_langinfo_l(CODESET, cloc);
47 if (!strcmp(codeset, "UTF-8"))
48 {
49 // optimize for some known cases
50 if (!strcmp(s, "\u202F")) // NARROW NO-BREAK SPACE
51 return ' ';
52 if (!strcmp(s, "\u2019")) // RIGHT SINGLE QUOTATION MARK
53 return '\'';
54 if (!strcmp(s, "\u066C")) // ARABIC THOUSANDS SEPARATOR
55 return '\'';
56 }
57
58 iconv_t cd = iconv_open("ASCII//TRANSLIT", codeset);
59 if (cd != (iconv_t)-1)
60 {
61 char c1;
62 size_t inbytesleft = strlen(s);
63 size_t outbytesleft = 1;
64 char* inbuf = const_cast<char*>(s);
65 char* outbuf = &c1;
66 size_t n = iconv(cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
67 iconv_close(cd);
68 if (n != (size_t)-1)
69 {
70 cd = iconv_open(codeset, "ASCII");
71 if (cd != (iconv_t)-1)
72 {
73 char c2;
74 inbuf = &c1;
75 inbytesleft = 1;
76 outbuf = &c2;
77 outbytesleft = 1;
78 n = iconv(cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
79 iconv_close(cd);
80 if (n != (size_t)-1)
81 return c2;
82 }
83 }
84 }
85 return '\0';
86 }
87#endif
88
f92ab29f 89 template<>
72e2386f
BK
90 void
91 numpunct<char>::_M_initialize_numpunct(__c_locale __cloc)
ea0c0b6e 92 {
215f9e28
BK
93 if (!_M_data)
94 _M_data = new __numpunct_cache<char>;
95
aa53f832 96 if (!__cloc)
72e2386f
BK
97 {
98 // "C" locale
215f9e28 99 _M_data->_M_grouping = "";
fe932e50 100 _M_data->_M_grouping_size = 0;
215f9e28
BK
101 _M_data->_M_use_grouping = false;
102
103 _M_data->_M_decimal_point = '.';
104 _M_data->_M_thousands_sep = ',';
105
17fa5560
PC
106 for (size_t __i = 0; __i < __num_base::_S_oend; ++__i)
107 _M_data->_M_atoms_out[__i] = __num_base::_S_atoms_out[__i];
215f9e28 108
95b147fe
SM
109 for (size_t __j = 0; __j < __num_base::_S_iend; ++__j)
110 _M_data->_M_atoms_in[__j] = __num_base::_S_atoms_in[__j];
72e2386f 111 }
ea0c0b6e 112 else
72e2386f
BK
113 {
114 // Named locale.
f92ab29f 115 _M_data->_M_decimal_point = *(__nl_langinfo_l(DECIMAL_POINT,
95b147fe 116 __cloc));
c0ace69e
JW
117 const char* thousands_sep = __nl_langinfo_l(THOUSANDS_SEP, __cloc);
118
119 if (thousands_sep[0] != '\0' && thousands_sep[1] != '\0')
120 _M_data->_M_thousands_sep = __narrow_multibyte_chars(thousands_sep,
121 __cloc);
122 else
123 _M_data->_M_thousands_sep = *thousands_sep;
215f9e28
BK
124
125 // Check for NULL, which implies no grouping.
126 if (_M_data->_M_thousands_sep == '\0')
1d9aba81
PC
127 {
128 // Like in "C" locale.
129 _M_data->_M_grouping = "";
130 _M_data->_M_grouping_size = 0;
131 _M_data->_M_use_grouping = false;
132 _M_data->_M_thousands_sep = ',';
133 }
f2e7381d 134 else
1d9aba81 135 {
af90c8c9
PC
136 const char* __src = __nl_langinfo_l(GROUPING, __cloc);
137 const size_t __len = strlen(__src);
138 if (__len)
139 {
140 __try
141 {
142 char* __dst = new char[__len + 1];
143 memcpy(__dst, __src, __len + 1);
144 _M_data->_M_grouping = __dst;
145 }
146 __catch(...)
147 {
148 delete _M_data;
149 _M_data = 0;
150 __throw_exception_again;
151 }
152 }
153 else
154 {
155 _M_data->_M_grouping = "";
156 _M_data->_M_use_grouping = false;
157 }
158 _M_data->_M_grouping_size = __len;
1d9aba81 159 }
72e2386f 160 }
47f62b27 161
72e2386f
BK
162 // NB: There is no way to extact this info from posix locales.
163 // _M_truename = __nl_langinfo_l(YESSTR, __cloc);
215f9e28 164 _M_data->_M_truename = "true";
af55af57 165 _M_data->_M_truename_size = 4;
72e2386f 166 // _M_falsename = __nl_langinfo_l(NOSTR, __cloc);
215f9e28 167 _M_data->_M_falsename = "false";
af55af57 168 _M_data->_M_falsename_size = 5;
ea0c0b6e 169 }
f92ab29f
CG
170
171 template<>
d3a193e3 172 numpunct<char>::~numpunct()
af90c8c9
PC
173 {
174 if (_M_data->_M_grouping_size)
175 delete [] _M_data->_M_grouping;
176 delete _M_data;
177 }
f92ab29f 178
3d7c150e 179#ifdef _GLIBCXX_USE_WCHAR_T
f92ab29f 180 template<>
72e2386f
BK
181 void
182 numpunct<wchar_t>::_M_initialize_numpunct(__c_locale __cloc)
ea0c0b6e 183 {
215f9e28
BK
184 if (!_M_data)
185 _M_data = new __numpunct_cache<wchar_t>;
186
aa53f832 187 if (!__cloc)
72e2386f
BK
188 {
189 // "C" locale
215f9e28 190 _M_data->_M_grouping = "";
fe932e50 191 _M_data->_M_grouping_size = 0;
215f9e28
BK
192 _M_data->_M_use_grouping = false;
193
194 _M_data->_M_decimal_point = L'.';
195 _M_data->_M_thousands_sep = L',';
196
215f9e28 197 // Use ctype::widen code without the facet...
17fa5560 198 for (size_t __i = 0; __i < __num_base::_S_oend; ++__i)
af55af57
PC
199 _M_data->_M_atoms_out[__i] =
200 static_cast<wchar_t>(__num_base::_S_atoms_out[__i]);
215f9e28 201
95b147fe
SM
202 for (size_t __j = 0; __j < __num_base::_S_iend; ++__j)
203 _M_data->_M_atoms_in[__j] =
204 static_cast<wchar_t>(__num_base::_S_atoms_in[__j]);
72e2386f 205 }
ea0c0b6e 206 else
72e2386f
BK
207 {
208 // Named locale.
a80e0e83
PC
209 // NB: In the GNU model wchar_t is always 32 bit wide.
210 union { char *__s; wchar_t __w; } __u;
43be7fe7 211 __u.__s = __nl_langinfo_l(_NL_NUMERIC_DECIMAL_POINT_WC, __cloc);
a80e0e83 212 _M_data->_M_decimal_point = __u.__w;
43be7fe7
MM
213
214 __u.__s = __nl_langinfo_l(_NL_NUMERIC_THOUSANDS_SEP_WC, __cloc);
a80e0e83 215 _M_data->_M_thousands_sep = __u.__w;
215f9e28 216
1d9aba81 217 // Check for NULL, which implies no grouping.
215f9e28 218 if (_M_data->_M_thousands_sep == L'\0')
1d9aba81
PC
219 {
220 // Like in "C" locale.
221 _M_data->_M_grouping = "";
222 _M_data->_M_grouping_size = 0;
223 _M_data->_M_use_grouping = false;
224 _M_data->_M_thousands_sep = L',';
225 }
f2e7381d 226 else
1d9aba81 227 {
af90c8c9
PC
228 const char* __src = __nl_langinfo_l(GROUPING, __cloc);
229 const size_t __len = strlen(__src);
230 if (__len)
231 {
232 __try
233 {
234 char* __dst = new char[__len + 1];
235 memcpy(__dst, __src, __len + 1);
236 _M_data->_M_grouping = __dst;
237 }
238 __catch(...)
239 {
240 delete _M_data;
241 _M_data = 0;
242 __throw_exception_again;
243 }
244 }
245 else
246 {
247 _M_data->_M_grouping = "";
248 _M_data->_M_use_grouping = false;
249 }
250 _M_data->_M_grouping_size = __len;
1d9aba81 251 }
72e2386f 252 }
47f62b27 253
72e2386f
BK
254 // NB: There is no way to extact this info from posix locales.
255 // _M_truename = __nl_langinfo_l(YESSTR, __cloc);
215f9e28 256 _M_data->_M_truename = L"true";
af55af57 257 _M_data->_M_truename_size = 4;
72e2386f 258 // _M_falsename = __nl_langinfo_l(NOSTR, __cloc);
215f9e28 259 _M_data->_M_falsename = L"false";
af55af57 260 _M_data->_M_falsename_size = 5;
ea0c0b6e 261 }
d3a193e3 262
f92ab29f 263 template<>
d3a193e3 264 numpunct<wchar_t>::~numpunct()
af90c8c9
PC
265 {
266 if (_M_data->_M_grouping_size)
267 delete [] _M_data->_M_grouping;
268 delete _M_data;
269 }
a0080f02 270#endif
3cbc7af0 271
12ffa228
BK
272_GLIBCXX_END_NAMESPACE_VERSION
273} // namespace