]>
Commit | Line | Data |
---|---|---|
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 |
35 | namespace 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 |