]>
Commit | Line | Data |
---|---|---|
725dc051 BK |
1 | // Locale support -*- C++ -*- |
2 | ||
7adcbafe | 3 | // Copyright (C) 1997-2022 Free Software Foundation, Inc. |
725dc051 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) |
725dc051 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/>. | |
725dc051 | 24 | |
f910786b | 25 | /** @file bits/locale_facets.tcc |
0aa06b18 | 26 | * This is an internal header file, included by other library headers. |
f910786b | 27 | * Do not attempt to use it directly. @headername{locale} |
0aa06b18 | 28 | */ |
725dc051 | 29 | |
3d7c150e BK |
30 | #ifndef _LOCALE_FACETS_TCC |
31 | #define _LOCALE_FACETS_TCC 1 | |
725dc051 | 32 | |
3b794528 BK |
33 | #pragma GCC system_header |
34 | ||
12ffa228 BK |
35 | namespace std _GLIBCXX_VISIBILITY(default) |
36 | { | |
37 | _GLIBCXX_BEGIN_NAMESPACE_VERSION | |
3cbc7af0 | 38 | |
215f9e28 BK |
39 | // Routine to access a cache for the facet. If the cache didn't |
40 | // exist before, it gets constructed on the fly. | |
41 | template<typename _Facet> | |
cde63840 BK |
42 | struct __use_cache |
43 | { | |
44 | const _Facet* | |
45 | operator() (const locale& __loc) const; | |
46 | }; | |
215f9e28 | 47 | |
586b5f20 | 48 | // Specializations. |
cde63840 BK |
49 | template<typename _CharT> |
50 | struct __use_cache<__numpunct_cache<_CharT> > | |
51 | { | |
52 | const __numpunct_cache<_CharT>* | |
53 | operator() (const locale& __loc) const | |
54 | { | |
905df1fb | 55 | const size_t __i = numpunct<_CharT>::id._M_id(); |
cde63840 BK |
56 | const locale::facet** __caches = __loc._M_impl->_M_caches; |
57 | if (!__caches[__i]) | |
58 | { | |
8fc81078 | 59 | __numpunct_cache<_CharT>* __tmp = 0; |
bc2631e0 | 60 | __try |
cde63840 BK |
61 | { |
62 | __tmp = new __numpunct_cache<_CharT>; | |
63 | __tmp->_M_cache(__loc); | |
64 | } | |
bc2631e0 | 65 | __catch(...) |
cde63840 BK |
66 | { |
67 | delete __tmp; | |
68 | __throw_exception_again; | |
69 | } | |
70 | __loc._M_impl->_M_install_cache(__tmp, __i); | |
71 | } | |
72 | return static_cast<const __numpunct_cache<_CharT>*>(__caches[__i]); | |
73 | } | |
74 | }; | |
725dc051 | 75 | |
586b5f20 BK |
76 | template<typename _CharT> |
77 | void | |
78 | __numpunct_cache<_CharT>::_M_cache(const locale& __loc) | |
79 | { | |
586b5f20 BK |
80 | const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); |
81 | ||
af90c8c9 PC |
82 | char* __grouping = 0; |
83 | _CharT* __truename = 0; | |
84 | _CharT* __falsename = 0; | |
85 | __try | |
86 | { | |
d6f64424 JW |
87 | const string& __g = __np.grouping(); |
88 | _M_grouping_size = __g.size(); | |
af90c8c9 | 89 | __grouping = new char[_M_grouping_size]; |
d6f64424 | 90 | __g.copy(__grouping, _M_grouping_size); |
af90c8c9 | 91 | _M_use_grouping = (_M_grouping_size |
d6f64424 JW |
92 | && static_cast<signed char>(__grouping[0]) > 0 |
93 | && (__grouping[0] | |
af90c8c9 PC |
94 | != __gnu_cxx::__numeric_traits<char>::__max)); |
95 | ||
d6f64424 JW |
96 | const basic_string<_CharT>& __tn = __np.truename(); |
97 | _M_truename_size = __tn.size(); | |
af90c8c9 | 98 | __truename = new _CharT[_M_truename_size]; |
d6f64424 | 99 | __tn.copy(__truename, _M_truename_size); |
af90c8c9 | 100 | |
d6f64424 JW |
101 | const basic_string<_CharT>& __fn = __np.falsename(); |
102 | _M_falsename_size = __fn.size(); | |
af90c8c9 | 103 | __falsename = new _CharT[_M_falsename_size]; |
d6f64424 | 104 | __fn.copy(__falsename, _M_falsename_size); |
af90c8c9 PC |
105 | |
106 | _M_decimal_point = __np.decimal_point(); | |
107 | _M_thousands_sep = __np.thousands_sep(); | |
108 | ||
109 | const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__loc); | |
110 | __ct.widen(__num_base::_S_atoms_out, | |
111 | __num_base::_S_atoms_out | |
112 | + __num_base::_S_oend, _M_atoms_out); | |
113 | __ct.widen(__num_base::_S_atoms_in, | |
114 | __num_base::_S_atoms_in | |
115 | + __num_base::_S_iend, _M_atoms_in); | |
d6f64424 JW |
116 | |
117 | _M_grouping = __grouping; | |
118 | _M_truename = __truename; | |
119 | _M_falsename = __falsename; | |
120 | _M_allocated = true; | |
af90c8c9 PC |
121 | } |
122 | __catch(...) | |
123 | { | |
124 | delete [] __grouping; | |
125 | delete [] __truename; | |
126 | delete [] __falsename; | |
127 | __throw_exception_again; | |
128 | } | |
586b5f20 BK |
129 | } |
130 | ||
47f62b27 PC |
131 | // Used by both numeric and monetary facets. |
132 | // Check to make sure that the __grouping_tmp string constructed in | |
133 | // money_get or num_get matches the canonical grouping for a given | |
134 | // locale. | |
135 | // __grouping_tmp is parsed L to R | |
136 | // 1,222,444 == __grouping_tmp of "\1\3\3" | |
137 | // __grouping is parsed R to L | |
138 | // 1,222,444 == __grouping of "\3" == "\3\3\3" | |
50a681c4 | 139 | _GLIBCXX_PURE bool |
47f62b27 | 140 | __verify_grouping(const char* __grouping, size_t __grouping_size, |
50a681c4 | 141 | const string& __grouping_tmp) throw (); |
47f62b27 | 142 | |
12ffa228 | 143 | _GLIBCXX_BEGIN_NAMESPACE_LDBL |
6defecc2 | 144 | |
1ab65677 | 145 | template<typename _CharT, typename _InIter> |
34a2b755 | 146 | _GLIBCXX_DEFAULT_ABI_TAG |
631ba05e | 147 | _InIter |
1ab65677 | 148 | num_get<_CharT, _InIter>:: |
86ade44c | 149 | _M_extract_float(_InIter __beg, _InIter __end, ios_base& __io, |
823b4f7d | 150 | ios_base::iostate& __err, string& __xtrc) const |
725dc051 | 151 | { |
7942afdc | 152 | typedef char_traits<_CharT> __traits_type; |
a70c902e | 153 | typedef __numpunct_cache<_CharT> __cache_type; |
7942afdc BK |
154 | __use_cache<__cache_type> __uc; |
155 | const locale& __loc = __io._M_getloc(); | |
156 | const __cache_type* __lc = __uc(__loc); | |
157 | const _CharT* __lit = __lc->_M_atoms_in; | |
8dc5fa32 | 158 | char_type __c = char_type(); |
86ade44c | 159 | |
8dc5fa32 PC |
160 | // True if __beg becomes equal to __end. |
161 | bool __testeof = __beg == __end; | |
a827daa0 | 162 | |
4b9aaf63 | 163 | // First check for sign. |
8dc5fa32 | 164 | if (!__testeof) |
86ade44c | 165 | { |
8dc5fa32 | 166 | __c = *__beg; |
586b5f20 BK |
167 | const bool __plus = __c == __lit[__num_base::_S_iplus]; |
168 | if ((__plus || __c == __lit[__num_base::_S_iminus]) | |
ce345590 PC |
169 | && !(__lc->_M_use_grouping && __c == __lc->_M_thousands_sep) |
170 | && !(__c == __lc->_M_decimal_point)) | |
f20d2b78 | 171 | { |
0e1b98cc | 172 | __xtrc += __plus ? '+' : '-'; |
8dc5fa32 PC |
173 | if (++__beg != __end) |
174 | __c = *__beg; | |
175 | else | |
176 | __testeof = true; | |
f20d2b78 | 177 | } |
86ade44c | 178 | } |
ed6814f7 | 179 | |
a827daa0 | 180 | // Next, look for leading zeros. |
e597a4d3 | 181 | bool __found_mantissa = false; |
d04e9b7f | 182 | int __sep_pos = 0; |
8dc5fa32 | 183 | while (!__testeof) |
823b4f7d | 184 | { |
2a67bec2 | 185 | if ((__lc->_M_use_grouping && __c == __lc->_M_thousands_sep) |
ce345590 | 186 | || __c == __lc->_M_decimal_point) |
a827daa0 | 187 | break; |
586b5f20 | 188 | else if (__c == __lit[__num_base::_S_izero]) |
a827daa0 PC |
189 | { |
190 | if (!__found_mantissa) | |
191 | { | |
0e1b98cc | 192 | __xtrc += '0'; |
a827daa0 PC |
193 | __found_mantissa = true; |
194 | } | |
d04e9b7f PC |
195 | ++__sep_pos; |
196 | ||
8dc5fa32 PC |
197 | if (++__beg != __end) |
198 | __c = *__beg; | |
199 | else | |
200 | __testeof = true; | |
a827daa0 PC |
201 | } |
202 | else | |
203 | break; | |
823b4f7d | 204 | } |
86ade44c BK |
205 | |
206 | // Only need acceptable digits for floating point numbers. | |
86ade44c BK |
207 | bool __found_dec = false; |
208 | bool __found_sci = false; | |
86ade44c | 209 | string __found_grouping; |
a8ea7389 PC |
210 | if (__lc->_M_use_grouping) |
211 | __found_grouping.reserve(32); | |
586b5f20 | 212 | const char_type* __lit_zero = __lit + __num_base::_S_izero; |
8dc5fa32 | 213 | |
bfdb907c PC |
214 | if (!__lc->_M_allocated) |
215 | // "C" locale | |
216 | while (!__testeof) | |
217 | { | |
218 | const int __digit = _M_find(__lit_zero, 10, __c); | |
219 | if (__digit != -1) | |
220 | { | |
221 | __xtrc += '0' + __digit; | |
222 | __found_mantissa = true; | |
223 | } | |
224 | else if (__c == __lc->_M_decimal_point | |
225 | && !__found_dec && !__found_sci) | |
226 | { | |
227 | __xtrc += '.'; | |
228 | __found_dec = true; | |
229 | } | |
230 | else if ((__c == __lit[__num_base::_S_ie] | |
231 | || __c == __lit[__num_base::_S_iE]) | |
232 | && !__found_sci && __found_mantissa) | |
233 | { | |
234 | // Scientific notation. | |
235 | __xtrc += 'e'; | |
236 | __found_sci = true; | |
237 | ||
238 | // Remove optional plus or minus sign, if they exist. | |
239 | if (++__beg != __end) | |
240 | { | |
241 | __c = *__beg; | |
242 | const bool __plus = __c == __lit[__num_base::_S_iplus]; | |
243 | if (__plus || __c == __lit[__num_base::_S_iminus]) | |
244 | __xtrc += __plus ? '+' : '-'; | |
245 | else | |
246 | continue; | |
247 | } | |
248 | else | |
249 | { | |
250 | __testeof = true; | |
251 | break; | |
252 | } | |
253 | } | |
254 | else | |
255 | break; | |
8dc5fa32 | 256 | |
bfdb907c PC |
257 | if (++__beg != __end) |
258 | __c = *__beg; | |
259 | else | |
260 | __testeof = true; | |
261 | } | |
262 | else | |
263 | while (!__testeof) | |
264 | { | |
265 | // According to 22.2.2.1.2, p8-9, first look for thousands_sep | |
266 | // and decimal_point. | |
267 | if (__lc->_M_use_grouping && __c == __lc->_M_thousands_sep) | |
268 | { | |
269 | if (!__found_dec && !__found_sci) | |
270 | { | |
271 | // NB: Thousands separator at the beginning of a string | |
272 | // is a no-no, as is two consecutive thousands separators. | |
273 | if (__sep_pos) | |
274 | { | |
275 | __found_grouping += static_cast<char>(__sep_pos); | |
276 | __sep_pos = 0; | |
277 | } | |
278 | else | |
279 | { | |
280 | // NB: __convert_to_v will not assign __v and will | |
281 | // set the failbit. | |
282 | __xtrc.clear(); | |
283 | break; | |
284 | } | |
285 | } | |
286 | else | |
287 | break; | |
288 | } | |
289 | else if (__c == __lc->_M_decimal_point) | |
290 | { | |
291 | if (!__found_dec && !__found_sci) | |
292 | { | |
293 | // If no grouping chars are seen, no grouping check | |
294 | // is applied. Therefore __found_grouping is adjusted | |
295 | // only if decimal_point comes after some thousands_sep. | |
296 | if (__found_grouping.size()) | |
297 | __found_grouping += static_cast<char>(__sep_pos); | |
298 | __xtrc += '.'; | |
299 | __found_dec = true; | |
300 | } | |
301 | else | |
302 | break; | |
303 | } | |
304 | else | |
305 | { | |
306 | const char_type* __q = | |
307 | __traits_type::find(__lit_zero, 10, __c); | |
308 | if (__q) | |
309 | { | |
310 | __xtrc += '0' + (__q - __lit_zero); | |
311 | __found_mantissa = true; | |
312 | ++__sep_pos; | |
313 | } | |
314 | else if ((__c == __lit[__num_base::_S_ie] | |
315 | || __c == __lit[__num_base::_S_iE]) | |
316 | && !__found_sci && __found_mantissa) | |
317 | { | |
318 | // Scientific notation. | |
319 | if (__found_grouping.size() && !__found_dec) | |
320 | __found_grouping += static_cast<char>(__sep_pos); | |
321 | __xtrc += 'e'; | |
322 | __found_sci = true; | |
323 | ||
324 | // Remove optional plus or minus sign, if they exist. | |
325 | if (++__beg != __end) | |
326 | { | |
327 | __c = *__beg; | |
328 | const bool __plus = __c == __lit[__num_base::_S_iplus]; | |
329 | if ((__plus || __c == __lit[__num_base::_S_iminus]) | |
330 | && !(__lc->_M_use_grouping | |
331 | && __c == __lc->_M_thousands_sep) | |
332 | && !(__c == __lc->_M_decimal_point)) | |
333 | __xtrc += __plus ? '+' : '-'; | |
334 | else | |
335 | continue; | |
336 | } | |
337 | else | |
338 | { | |
339 | __testeof = true; | |
340 | break; | |
341 | } | |
342 | } | |
343 | else | |
344 | break; | |
345 | } | |
346 | ||
347 | if (++__beg != __end) | |
348 | __c = *__beg; | |
349 | else | |
350 | __testeof = true; | |
351 | } | |
86ade44c BK |
352 | |
353 | // Digit grouping is checked. If grouping and found_grouping don't | |
354 | // match, then get very very upset, and set failbit. | |
6d4925e3 | 355 | if (__found_grouping.size()) |
86ade44c | 356 | { |
0e1b98cc PC |
357 | // Add the ending grouping if a decimal or 'e'/'E' wasn't found. |
358 | if (!__found_dec && !__found_sci) | |
86ade44c | 359 | __found_grouping += static_cast<char>(__sep_pos); |
7942afdc | 360 | |
586b5f20 BK |
361 | if (!std::__verify_grouping(__lc->_M_grouping, |
362 | __lc->_M_grouping_size, | |
47f62b27 | 363 | __found_grouping)) |
5ef46f95 | 364 | __err = ios_base::failbit; |
86ade44c BK |
365 | } |
366 | ||
631ba05e | 367 | return __beg; |
725dc051 BK |
368 | } |
369 | ||
86ade44c | 370 | template<typename _CharT, typename _InIter> |
ed6814f7 | 371 | template<typename _ValueT> |
34a2b755 | 372 | _GLIBCXX_DEFAULT_ABI_TAG |
0fa96a60 PC |
373 | _InIter |
374 | num_get<_CharT, _InIter>:: | |
375 | _M_extract_int(_InIter __beg, _InIter __end, ios_base& __io, | |
376 | ios_base::iostate& __err, _ValueT& __v) const | |
377 | { | |
5383998a | 378 | typedef char_traits<_CharT> __traits_type; |
105c6331 | 379 | using __gnu_cxx::__add_unsigned; |
5383998a XR |
380 | typedef typename __add_unsigned<_ValueT>::__type __unsigned_type; |
381 | typedef __numpunct_cache<_CharT> __cache_type; | |
0fa96a60 PC |
382 | __use_cache<__cache_type> __uc; |
383 | const locale& __loc = __io._M_getloc(); | |
384 | const __cache_type* __lc = __uc(__loc); | |
385 | const _CharT* __lit = __lc->_M_atoms_in; | |
e597a4d3 | 386 | char_type __c = char_type(); |
86ade44c | 387 | |
0fa96a60 | 388 | // NB: Iff __basefield == 0, __base can change based on contents. |
a8ea7389 PC |
389 | const ios_base::fmtflags __basefield = __io.flags() |
390 | & ios_base::basefield; | |
0fa96a60 PC |
391 | const bool __oct = __basefield == ios_base::oct; |
392 | int __base = __oct ? 8 : (__basefield == ios_base::hex ? 16 : 10); | |
86ade44c | 393 | |
e597a4d3 PC |
394 | // True if __beg becomes equal to __end. |
395 | bool __testeof = __beg == __end; | |
0fa96a60 PC |
396 | |
397 | // First check for sign. | |
398 | bool __negative = false; | |
e597a4d3 | 399 | if (!__testeof) |
ed6814f7 | 400 | { |
e597a4d3 | 401 | __c = *__beg; |
2daad65e | 402 | __negative = __c == __lit[__num_base::_S_iminus]; |
586b5f20 | 403 | if ((__negative || __c == __lit[__num_base::_S_iplus]) |
ce345590 PC |
404 | && !(__lc->_M_use_grouping && __c == __lc->_M_thousands_sep) |
405 | && !(__c == __lc->_M_decimal_point)) | |
e597a4d3 PC |
406 | { |
407 | if (++__beg != __end) | |
408 | __c = *__beg; | |
409 | else | |
410 | __testeof = true; | |
411 | } | |
0fa96a60 | 412 | } |
86ade44c | 413 | |
0fa96a60 PC |
414 | // Next, look for leading zeros and check required digits |
415 | // for base formats. | |
e597a4d3 | 416 | bool __found_zero = false; |
d04e9b7f | 417 | int __sep_pos = 0; |
e597a4d3 | 418 | while (!__testeof) |
0fa96a60 | 419 | { |
2a67bec2 | 420 | if ((__lc->_M_use_grouping && __c == __lc->_M_thousands_sep) |
ce345590 | 421 | || __c == __lc->_M_decimal_point) |
a827daa0 | 422 | break; |
586b5f20 | 423 | else if (__c == __lit[__num_base::_S_izero] |
e597a4d3 | 424 | && (!__found_zero || __base == 10)) |
0fa96a60 | 425 | { |
d04e9b7f PC |
426 | __found_zero = true; |
427 | ++__sep_pos; | |
428 | if (__basefield == 0) | |
429 | __base = 8; | |
430 | if (__base == 8) | |
431 | __sep_pos = 0; | |
432 | } | |
433 | else if (__found_zero | |
434 | && (__c == __lit[__num_base::_S_ix] | |
435 | || __c == __lit[__num_base::_S_iX])) | |
436 | { | |
437 | if (__basefield == 0) | |
438 | __base = 16; | |
439 | if (__base == 16) | |
0fa96a60 | 440 | { |
d04e9b7f PC |
441 | __found_zero = false; |
442 | __sep_pos = 0; | |
e597a4d3 PC |
443 | } |
444 | else | |
d04e9b7f | 445 | break; |
0fa96a60 | 446 | } |
a827daa0 PC |
447 | else |
448 | break; | |
86ade44c | 449 | |
e597a4d3 PC |
450 | if (++__beg != __end) |
451 | { | |
452 | __c = *__beg; | |
453 | if (!__found_zero) | |
454 | break; | |
455 | } | |
456 | else | |
457 | __testeof = true; | |
458 | } | |
459 | ||
0fa96a60 PC |
460 | // At this point, base is determined. If not hex, only allow |
461 | // base digits as valid input. | |
fea6ecb7 PC |
462 | const size_t __len = (__base == 16 ? __num_base::_S_iend |
463 | - __num_base::_S_izero : __base); | |
0fa96a60 PC |
464 | |
465 | // Extract. | |
5383998a | 466 | typedef __gnu_cxx::__numeric_traits<_ValueT> __num_traits; |
0fa96a60 | 467 | string __found_grouping; |
a8ea7389 PC |
468 | if (__lc->_M_use_grouping) |
469 | __found_grouping.reserve(32); | |
d04e9b7f | 470 | bool __testfail = false; |
5ef46f95 | 471 | bool __testoverflow = false; |
2daad65e | 472 | const __unsigned_type __max = |
5383998a XR |
473 | (__negative && __num_traits::__is_signed) |
474 | ? -static_cast<__unsigned_type>(__num_traits::__min) | |
475 | : __num_traits::__max; | |
44ecf603 PC |
476 | const __unsigned_type __smax = __max / __base; |
477 | __unsigned_type __result = 0; | |
bfdb907c | 478 | int __digit = 0; |
586b5f20 | 479 | const char_type* __lit_zero = __lit + __num_base::_S_izero; |
86ade44c | 480 | |
bfdb907c PC |
481 | if (!__lc->_M_allocated) |
482 | // "C" locale | |
483 | while (!__testeof) | |
484 | { | |
485 | __digit = _M_find(__lit_zero, __len, __c); | |
486 | if (__digit == -1) | |
487 | break; | |
488 | ||
489 | if (__result > __smax) | |
5ef46f95 | 490 | __testoverflow = true; |
bfdb907c PC |
491 | else |
492 | { | |
493 | __result *= __base; | |
5ef46f95 | 494 | __testoverflow |= __result > __max - __digit; |
bfdb907c PC |
495 | __result += __digit; |
496 | ++__sep_pos; | |
497 | } | |
498 | ||
499 | if (++__beg != __end) | |
500 | __c = *__beg; | |
501 | else | |
502 | __testeof = true; | |
503 | } | |
504 | else | |
505 | while (!__testeof) | |
506 | { | |
507 | // According to 22.2.2.1.2, p8-9, first look for thousands_sep | |
508 | // and decimal_point. | |
509 | if (__lc->_M_use_grouping && __c == __lc->_M_thousands_sep) | |
510 | { | |
511 | // NB: Thousands separator at the beginning of a string | |
512 | // is a no-no, as is two consecutive thousands separators. | |
513 | if (__sep_pos) | |
514 | { | |
515 | __found_grouping += static_cast<char>(__sep_pos); | |
516 | __sep_pos = 0; | |
517 | } | |
518 | else | |
519 | { | |
520 | __testfail = true; | |
521 | break; | |
522 | } | |
523 | } | |
524 | else if (__c == __lc->_M_decimal_point) | |
525 | break; | |
526 | else | |
527 | { | |
528 | const char_type* __q = | |
529 | __traits_type::find(__lit_zero, __len, __c); | |
530 | if (!__q) | |
531 | break; | |
532 | ||
533 | __digit = __q - __lit_zero; | |
534 | if (__digit > 15) | |
535 | __digit -= 6; | |
536 | if (__result > __smax) | |
5ef46f95 | 537 | __testoverflow = true; |
bfdb907c PC |
538 | else |
539 | { | |
540 | __result *= __base; | |
5ef46f95 | 541 | __testoverflow |= __result > __max - __digit; |
bfdb907c PC |
542 | __result += __digit; |
543 | ++__sep_pos; | |
544 | } | |
545 | } | |
546 | ||
547 | if (++__beg != __end) | |
548 | __c = *__beg; | |
549 | else | |
550 | __testeof = true; | |
551 | } | |
552 | ||
0fa96a60 PC |
553 | // Digit grouping is checked. If grouping and found_grouping don't |
554 | // match, then get very very upset, and set failbit. | |
6d4925e3 | 555 | if (__found_grouping.size()) |
0fa96a60 PC |
556 | { |
557 | // Add the ending grouping. | |
558 | __found_grouping += static_cast<char>(__sep_pos); | |
ed6814f7 | 559 | |
a8ea7389 PC |
560 | if (!std::__verify_grouping(__lc->_M_grouping, |
561 | __lc->_M_grouping_size, | |
47f62b27 | 562 | __found_grouping)) |
5ef46f95 | 563 | __err = ios_base::failbit; |
0fa96a60 | 564 | } |
7942afdc | 565 | |
5ef46f95 PC |
566 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
567 | // 23. Num_get overflow result. | |
568 | if ((!__sep_pos && !__found_zero && !__found_grouping.size()) | |
569 | || __testfail) | |
570 | { | |
571 | __v = 0; | |
572 | __err = ios_base::failbit; | |
573 | } | |
574 | else if (__testoverflow) | |
575 | { | |
5383998a XR |
576 | if (__negative && __num_traits::__is_signed) |
577 | __v = __num_traits::__min; | |
5ef46f95 | 578 | else |
5383998a | 579 | __v = __num_traits::__max; |
5ef46f95 PC |
580 | __err = ios_base::failbit; |
581 | } | |
0fa96a60 | 582 | else |
5ef46f95 | 583 | __v = __negative ? -__result : __result; |
86ade44c | 584 | |
e597a4d3 | 585 | if (__testeof) |
0fa96a60 PC |
586 | __err |= ios_base::eofbit; |
587 | return __beg; | |
588 | } | |
1ab65677 | 589 | |
f5677b15 PC |
590 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
591 | // 17. Bad bool parsing | |
1ab65677 BK |
592 | template<typename _CharT, typename _InIter> |
593 | _InIter | |
594 | num_get<_CharT, _InIter>:: | |
595 | do_get(iter_type __beg, iter_type __end, ios_base& __io, | |
596 | ios_base::iostate& __err, bool& __v) const | |
725dc051 | 597 | { |
1ab65677 | 598 | if (!(__io.flags() & ios_base::boolalpha)) |
725dc051 | 599 | { |
0fa96a60 | 600 | // Parse bool values as long. |
1ab65677 BK |
601 | // NB: We can't just call do_get(long) here, as it might |
602 | // refer to a derived class. | |
0fa96a60 PC |
603 | long __l = -1; |
604 | __beg = _M_extract_int(__beg, __end, __io, __err, __l); | |
605 | if (__l == 0 || __l == 1) | |
226a2e08 | 606 | __v = bool(__l); |
0fa96a60 | 607 | else |
5ef46f95 PC |
608 | { |
609 | // _GLIBCXX_RESOLVE_LIB_DEFECTS | |
610 | // 23. Num_get overflow result. | |
611 | __v = true; | |
612 | __err = ios_base::failbit; | |
613 | if (__beg == __end) | |
614 | __err |= ios_base::eofbit; | |
615 | } | |
1ab65677 | 616 | } |
1ab65677 | 617 | else |
725dc051 | 618 | { |
7942afdc | 619 | // Parse bool values as alphanumeric. |
894e47e7 | 620 | typedef __numpunct_cache<_CharT> __cache_type; |
7942afdc BK |
621 | __use_cache<__cache_type> __uc; |
622 | const locale& __loc = __io._M_getloc(); | |
623 | const __cache_type* __lc = __uc(__loc); | |
86ade44c | 624 | |
fa4262a4 PC |
625 | bool __testf = true; |
626 | bool __testt = true; | |
7ea6fdf5 PC |
627 | bool __donef = __lc->_M_falsename_size == 0; |
628 | bool __donet = __lc->_M_truename_size == 0; | |
fa4262a4 | 629 | bool __testeof = false; |
7ea6fdf5 PC |
630 | size_t __n = 0; |
631 | while (!__donef || !__donet) | |
fa4262a4 PC |
632 | { |
633 | if (__beg == __end) | |
894e47e7 | 634 | { |
fa4262a4 PC |
635 | __testeof = true; |
636 | break; | |
9e0b7527 | 637 | } |
7942afdc | 638 | |
fa4262a4 | 639 | const char_type __c = *__beg; |
7942afdc | 640 | |
7ea6fdf5 | 641 | if (!__donef) |
fa4262a4 PC |
642 | __testf = __c == __lc->_M_falsename[__n]; |
643 | ||
2a81fe20 PC |
644 | if (!__testf && __donet) |
645 | break; | |
646 | ||
7ea6fdf5 | 647 | if (!__donet) |
fa4262a4 PC |
648 | __testt = __c == __lc->_M_truename[__n]; |
649 | ||
2a81fe20 | 650 | if (!__testt && __donef) |
ed6814f7 | 651 | break; |
fa4262a4 | 652 | |
2a81fe20 | 653 | if (!__testt && !__testf) |
fa4262a4 | 654 | break; |
7ea6fdf5 PC |
655 | |
656 | ++__n; | |
657 | ++__beg; | |
658 | ||
659 | __donef = !__testf || __n >= __lc->_M_falsename_size; | |
660 | __donet = !__testt || __n >= __lc->_M_truename_size; | |
fa4262a4 PC |
661 | } |
662 | if (__testf && __n == __lc->_M_falsename_size && __n) | |
894e47e7 PC |
663 | { |
664 | __v = false; | |
665 | if (__testt && __n == __lc->_M_truename_size) | |
666 | __err = ios_base::failbit; | |
667 | else | |
fa4262a4 | 668 | __err = __testeof ? ios_base::eofbit : ios_base::goodbit; |
894e47e7 | 669 | } |
fa4262a4 | 670 | else if (__testt && __n == __lc->_M_truename_size && __n) |
894e47e7 PC |
671 | { |
672 | __v = true; | |
fa4262a4 | 673 | __err = __testeof ? ios_base::eofbit : ios_base::goodbit; |
894e47e7 | 674 | } |
ca13fb7f | 675 | else |
5ef46f95 PC |
676 | { |
677 | // _GLIBCXX_RESOLVE_LIB_DEFECTS | |
678 | // 23. Num_get overflow result. | |
679 | __v = false; | |
680 | __err = ios_base::failbit; | |
fa4262a4 | 681 | if (__testeof) |
894e47e7 | 682 | __err |= ios_base::eofbit; |
5ef46f95 | 683 | } |
fa4262a4 | 684 | } |
1ab65677 | 685 | return __beg; |
725dc051 BK |
686 | } |
687 | ||
725dc051 | 688 | template<typename _CharT, typename _InIter> |
1ab65677 | 689 | _InIter |
725dc051 | 690 | num_get<_CharT, _InIter>:: |
ed6814f7 | 691 | do_get(iter_type __beg, iter_type __end, ios_base& __io, |
86ade44c | 692 | ios_base::iostate& __err, float& __v) const |
725dc051 | 693 | { |
823b4f7d BK |
694 | string __xtrc; |
695 | __xtrc.reserve(32); | |
631ba05e | 696 | __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc); |
0fa96a60 | 697 | std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_get_c_locale()); |
5ef46f95 PC |
698 | if (__beg == __end) |
699 | __err |= ios_base::eofbit; | |
1ab65677 BK |
700 | return __beg; |
701 | } | |
725dc051 | 702 | |
725dc051 BK |
703 | template<typename _CharT, typename _InIter> |
704 | _InIter | |
705 | num_get<_CharT, _InIter>:: | |
706 | do_get(iter_type __beg, iter_type __end, ios_base& __io, | |
1ab65677 | 707 | ios_base::iostate& __err, double& __v) const |
725dc051 | 708 | { |
823b4f7d BK |
709 | string __xtrc; |
710 | __xtrc.reserve(32); | |
631ba05e | 711 | __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc); |
8ae81136 | 712 | std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_get_c_locale()); |
5ef46f95 PC |
713 | if (__beg == __end) |
714 | __err |= ios_base::eofbit; | |
725dc051 BK |
715 | return __beg; |
716 | } | |
717 | ||
6defecc2 JJ |
718 | #if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__ |
719 | template<typename _CharT, typename _InIter> | |
720 | _InIter | |
721 | num_get<_CharT, _InIter>:: | |
722 | __do_get(iter_type __beg, iter_type __end, ios_base& __io, | |
723 | ios_base::iostate& __err, double& __v) const | |
724 | { | |
725 | string __xtrc; | |
726 | __xtrc.reserve(32); | |
727 | __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc); | |
728 | std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_get_c_locale()); | |
5ef46f95 PC |
729 | if (__beg == __end) |
730 | __err |= ios_base::eofbit; | |
6defecc2 JJ |
731 | return __beg; |
732 | } | |
733 | #endif | |
734 | ||
725dc051 BK |
735 | template<typename _CharT, typename _InIter> |
736 | _InIter | |
737 | num_get<_CharT, _InIter>:: | |
738 | do_get(iter_type __beg, iter_type __end, ios_base& __io, | |
1ab65677 | 739 | ios_base::iostate& __err, long double& __v) const |
725dc051 | 740 | { |
823b4f7d BK |
741 | string __xtrc; |
742 | __xtrc.reserve(32); | |
631ba05e | 743 | __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc); |
8ae81136 | 744 | std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_get_c_locale()); |
5ef46f95 PC |
745 | if (__beg == __end) |
746 | __err |= ios_base::eofbit; | |
725dc051 BK |
747 | return __beg; |
748 | } | |
749 | ||
725dc051 BK |
750 | template<typename _CharT, typename _InIter> |
751 | _InIter | |
752 | num_get<_CharT, _InIter>:: | |
753 | do_get(iter_type __beg, iter_type __end, ios_base& __io, | |
1ab65677 | 754 | ios_base::iostate& __err, void*& __v) const |
725dc051 | 755 | { |
7942afdc | 756 | // Prepare for hex formatted input. |
1ab65677 | 757 | typedef ios_base::fmtflags fmtflags; |
905df1fb | 758 | const fmtflags __fmt = __io.flags(); |
2a67bec2 | 759 | __io.flags((__fmt & ~ios_base::basefield) | ios_base::hex); |
1ab65677 | 760 | |
90737ab7 PC |
761 | typedef __gnu_cxx::__conditional_type<(sizeof(void*) |
762 | <= sizeof(unsigned long)), | |
763 | unsigned long, unsigned long long>::__type _UIntPtrType; | |
764 | ||
765 | _UIntPtrType __ul; | |
0fa96a60 | 766 | __beg = _M_extract_int(__beg, __end, __io, __err, __ul); |
725dc051 | 767 | |
7942afdc | 768 | // Reset from hex formatted input. |
1ab65677 | 769 | __io.flags(__fmt); |
4b9aaf63 | 770 | |
5ef46f95 | 771 | __v = reinterpret_cast<void*>(__ul); |
725dc051 BK |
772 | return __beg; |
773 | } | |
725dc051 | 774 | |
7c1e7eed JW |
775 | #if defined _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT \ |
776 | && defined __LONG_DOUBLE_IEEE128__ | |
777 | template<typename _CharT, typename _InIter> | |
778 | _InIter | |
779 | num_get<_CharT, _InIter>:: | |
780 | __do_get(iter_type __beg, iter_type __end, ios_base& __io, | |
781 | ios_base::iostate& __err, __ibm128& __v) const | |
782 | { | |
783 | string __xtrc; | |
784 | __xtrc.reserve(32); | |
785 | __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc); | |
786 | std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_get_c_locale()); | |
787 | if (__beg == __end) | |
788 | __err |= ios_base::eofbit; | |
789 | return __beg; | |
790 | } | |
791 | #endif | |
792 | ||
ce3039af JQ |
793 | // For use by integer and floating-point types after they have been |
794 | // converted into a char_type string. | |
795 | template<typename _CharT, typename _OutIter> | |
796 | void | |
797 | num_put<_CharT, _OutIter>:: | |
ed6814f7 | 798 | _M_pad(_CharT __fill, streamsize __w, ios_base& __io, |
ce3039af JQ |
799 | _CharT* __new, const _CharT* __cs, int& __len) const |
800 | { | |
801 | // [22.2.2.2.2] Stage 3. | |
802 | // If necessary, pad. | |
11202768 PC |
803 | __pad<_CharT, char_traits<_CharT> >::_S_pad(__io, __fill, __new, |
804 | __cs, __w, __len); | |
ce3039af JQ |
805 | __len = static_cast<int>(__w); |
806 | } | |
807 | ||
12ffa228 | 808 | _GLIBCXX_END_NAMESPACE_LDBL |
6defecc2 | 809 | |
ce3039af JQ |
810 | template<typename _CharT, typename _ValueT> |
811 | int | |
3c21d6e0 | 812 | __int_to_char(_CharT* __bufend, _ValueT __v, const _CharT* __lit, |
5c171a74 | 813 | ios_base::fmtflags __flags, bool __dec) |
ce3039af | 814 | { |
101c5bc5 | 815 | _CharT* __buf = __bufend; |
5c171a74 | 816 | if (__builtin_expect(__dec, true)) |
d542f114 BK |
817 | { |
818 | // Decimal. | |
ed6814f7 | 819 | do |
d542f114 | 820 | { |
101c5bc5 | 821 | *--__buf = __lit[(__v % 10) + __num_base::_S_odigits]; |
d542f114 | 822 | __v /= 10; |
ed6814f7 | 823 | } |
d542f114 | 824 | while (__v != 0); |
d542f114 | 825 | } |
5c171a74 | 826 | else if ((__flags & ios_base::basefield) == ios_base::oct) |
ce3039af JQ |
827 | { |
828 | // Octal. | |
ed6814f7 | 829 | do |
ce3039af | 830 | { |
101c5bc5 | 831 | *--__buf = __lit[(__v & 0x7) + __num_base::_S_odigits]; |
ce3039af | 832 | __v >>= 3; |
ed6814f7 | 833 | } |
ce3039af | 834 | while (__v != 0); |
ce3039af | 835 | } |
d542f114 | 836 | else |
ce3039af JQ |
837 | { |
838 | // Hex. | |
839 | const bool __uppercase = __flags & ios_base::uppercase; | |
ed6814f7 | 840 | const int __case_offset = __uppercase ? __num_base::_S_oudigits |
905df1fb | 841 | : __num_base::_S_odigits; |
ed6814f7 | 842 | do |
ce3039af | 843 | { |
101c5bc5 | 844 | *--__buf = __lit[(__v & 0xf) + __case_offset]; |
ce3039af | 845 | __v >>= 4; |
ed6814f7 | 846 | } |
ce3039af | 847 | while (__v != 0); |
ce3039af | 848 | } |
101c5bc5 | 849 | return __bufend - __buf; |
ce3039af JQ |
850 | } |
851 | ||
12ffa228 | 852 | _GLIBCXX_BEGIN_NAMESPACE_LDBL |
6defecc2 | 853 | |
ce3039af JQ |
854 | template<typename _CharT, typename _OutIter> |
855 | void | |
856 | num_put<_CharT, _OutIter>:: | |
47f62b27 | 857 | _M_group_int(const char* __grouping, size_t __grouping_size, _CharT __sep, |
101c5bc5 | 858 | ios_base&, _CharT* __new, _CharT* __cs, int& __len) const |
ce3039af | 859 | { |
101c5bc5 PC |
860 | _CharT* __p = std::__add_grouping(__new, __sep, __grouping, |
861 | __grouping_size, __cs, __cs + __len); | |
ce3039af JQ |
862 | __len = __p - __new; |
863 | } | |
101c5bc5 | 864 | |
ce3039af JQ |
865 | template<typename _CharT, typename _OutIter> |
866 | template<typename _ValueT> | |
867 | _OutIter | |
868 | num_put<_CharT, _OutIter>:: | |
ed6814f7 | 869 | _M_insert_int(_OutIter __s, ios_base& __io, _CharT __fill, |
0fa96a60 | 870 | _ValueT __v) const |
ce3039af | 871 | { |
105c6331 BK |
872 | using __gnu_cxx::__add_unsigned; |
873 | typedef typename __add_unsigned<_ValueT>::__type __unsigned_type; | |
5c171a74 | 874 | typedef __numpunct_cache<_CharT> __cache_type; |
cde63840 | 875 | __use_cache<__cache_type> __uc; |
215f9e28 | 876 | const locale& __loc = __io._M_getloc(); |
cde63840 BK |
877 | const __cache_type* __lc = __uc(__loc); |
878 | const _CharT* __lit = __lc->_M_atoms_out; | |
101c5bc5 | 879 | const ios_base::fmtflags __flags = __io.flags(); |
ce3039af | 880 | |
ed6814f7 | 881 | // Long enough to hold hex, dec, and octal representations. |
101c5bc5 | 882 | const int __ilen = 5 * sizeof(_ValueT); |
ed6814f7 | 883 | _CharT* __cs = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) |
ce3039af | 884 | * __ilen)); |
a761195b | 885 | |
ce3039af JQ |
886 | // [22.2.2.2.2] Stage 1, numeric conversion to character. |
887 | // Result is returned right-justified in the buffer. | |
5c171a74 PC |
888 | const ios_base::fmtflags __basefield = __flags & ios_base::basefield; |
889 | const bool __dec = (__basefield != ios_base::oct | |
890 | && __basefield != ios_base::hex); | |
226a2e08 PC |
891 | const __unsigned_type __u = ((__v > 0 || !__dec) |
892 | ? __unsigned_type(__v) | |
893 | : -__unsigned_type(__v)); | |
5c171a74 | 894 | int __len = __int_to_char(__cs + __ilen, __u, __lit, __flags, __dec); |
a761195b | 895 | __cs += __ilen - __len; |
ed6814f7 BI |
896 | |
897 | // Add grouping, if necessary. | |
cde63840 | 898 | if (__lc->_M_use_grouping) |
ce3039af | 899 | { |
101c5bc5 PC |
900 | // Grouping can add (almost) as many separators as the number |
901 | // of digits + space is reserved for numeric base or sign. | |
ed6814f7 | 902 | _CharT* __cs2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) |
101c5bc5 PC |
903 | * (__len + 1) |
904 | * 2)); | |
47f62b27 | 905 | _M_group_int(__lc->_M_grouping, __lc->_M_grouping_size, |
101c5bc5 PC |
906 | __lc->_M_thousands_sep, __io, __cs2 + 2, __cs, __len); |
907 | __cs = __cs2 + 2; | |
908 | } | |
909 | ||
910 | // Complete Stage 1, prepend numeric base or sign. | |
5c171a74 | 911 | if (__builtin_expect(__dec, true)) |
101c5bc5 PC |
912 | { |
913 | // Decimal. | |
cded5e6b | 914 | if (__v >= 0) |
101c5bc5 | 915 | { |
7f786096 | 916 | if (bool(__flags & ios_base::showpos) |
6725add5 | 917 | && __gnu_cxx::__numeric_traits<_ValueT>::__is_signed) |
101c5bc5 PC |
918 | *--__cs = __lit[__num_base::_S_oplus], ++__len; |
919 | } | |
cded5e6b | 920 | else |
101c5bc5 PC |
921 | *--__cs = __lit[__num_base::_S_ominus], ++__len; |
922 | } | |
7f786096 | 923 | else if (bool(__flags & ios_base::showbase) && __v) |
101c5bc5 | 924 | { |
8637038a | 925 | if (__basefield == ios_base::oct) |
101c5bc5 | 926 | *--__cs = __lit[__num_base::_S_odigits], ++__len; |
8637038a | 927 | else |
101c5bc5 PC |
928 | { |
929 | // 'x' or 'X' | |
930 | const bool __uppercase = __flags & ios_base::uppercase; | |
931 | *--__cs = __lit[__num_base::_S_ox + __uppercase]; | |
932 | // '0' | |
933 | *--__cs = __lit[__num_base::_S_odigits]; | |
934 | __len += 2; | |
935 | } | |
ce3039af | 936 | } |
ed6814f7 | 937 | |
ce3039af | 938 | // Pad. |
905df1fb | 939 | const streamsize __w = __io.width(); |
ce3039af JQ |
940 | if (__w > static_cast<streamsize>(__len)) |
941 | { | |
ed6814f7 | 942 | _CharT* __cs3 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) |
f6a7db9e | 943 | * __w)); |
ce3039af JQ |
944 | _M_pad(__fill, __w, __io, __cs3, __cs, __len); |
945 | __cs = __cs3; | |
946 | } | |
947 | __io.width(0); | |
948 | ||
949 | // [22.2.2.2.2] Stage 4. | |
950 | // Write resulting, fully-formatted string to output iterator. | |
391cfc46 | 951 | return std::__write(__s, __cs, __len); |
ed6814f7 | 952 | } |
ce3039af JQ |
953 | |
954 | template<typename _CharT, typename _OutIter> | |
955 | void | |
956 | num_put<_CharT, _OutIter>:: | |
a8ea7389 PC |
957 | _M_group_float(const char* __grouping, size_t __grouping_size, |
958 | _CharT __sep, const _CharT* __p, _CharT* __new, | |
959 | _CharT* __cs, int& __len) const | |
ce3039af | 960 | { |
f5677b15 PC |
961 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
962 | // 282. What types does numpunct grouping refer to? | |
ed6814f7 | 963 | // Add grouping, if necessary. |
a761195b | 964 | const int __declen = __p ? __p - __cs : __len; |
23d4fa49 PC |
965 | _CharT* __p2 = std::__add_grouping(__new, __sep, __grouping, |
966 | __grouping_size, | |
967 | __cs, __cs + __declen); | |
ed6814f7 | 968 | |
ce3039af JQ |
969 | // Tack on decimal part. |
970 | int __newlen = __p2 - __new; | |
971 | if (__p) | |
972 | { | |
973 | char_traits<_CharT>::copy(__p2, __p, __len - __declen); | |
974 | __newlen += __len - __declen; | |
ed6814f7 | 975 | } |
ce3039af | 976 | __len = __newlen; |
ce3039af JQ |
977 | } |
978 | ||
964c5329 | 979 | // The following code uses vsnprintf (or vsprintf(), when |
23c64853 JY |
980 | // _GLIBCXX_USE_C99_STDIO is not defined) to convert floating point |
981 | // values for insertion into a stream. An optimization would be to | |
982 | // replace them with code that works directly on a wide buffer and | |
983 | // then use __pad to do the padding. It would be good to replace | |
984 | // them anyway to gain back the efficiency that C++ provides by | |
985 | // knowing up front the type of the values to insert. Also, sprintf | |
986 | // is dangerous since may lead to accidental buffer overruns. This | |
ce3039af | 987 | // implementation follows the C++ standard fairly directly as |
6d8e16a4 | 988 | // outlined in 22.2.2.2 [lib.locale.num.put] |
1ab65677 | 989 | template<typename _CharT, typename _OutIter> |
86ade44c BK |
990 | template<typename _ValueT> |
991 | _OutIter | |
992 | num_put<_CharT, _OutIter>:: | |
7942afdc | 993 | _M_insert_float(_OutIter __s, ios_base& __io, _CharT __fill, char __mod, |
86ade44c BK |
994 | _ValueT __v) const |
995 | { | |
a70c902e | 996 | typedef __numpunct_cache<_CharT> __cache_type; |
7942afdc BK |
997 | __use_cache<__cache_type> __uc; |
998 | const locale& __loc = __io._M_getloc(); | |
999 | const __cache_type* __lc = __uc(__loc); | |
1000 | ||
ce3039af | 1001 | // Use default precision if out of range. |
caade192 | 1002 | const streamsize __prec = __io.precision() < 0 ? 6 : __io.precision(); |
86ade44c | 1003 | |
6725add5 PC |
1004 | const int __max_digits = |
1005 | __gnu_cxx::__numeric_traits<_ValueT>::__digits10; | |
7c9b102e | 1006 | |
ce3039af JQ |
1007 | // [22.2.2.2.2] Stage 1, numeric conversion to character. |
1008 | int __len; | |
86ade44c BK |
1009 | // Long enough for the max format spec. |
1010 | char __fbuf[16]; | |
caade192 | 1011 | __num_base::_S_format_float(__io, __fbuf, __mod); |
0228de0c | 1012 | |
c98f2551 | 1013 | #if _GLIBCXX_USE_C99_STDIO && !_GLIBCXX_HAVE_BROKEN_VSNPRINTF |
9d07d890 JW |
1014 | // Precision is always used except for hexfloat format. |
1015 | const bool __use_prec = | |
1016 | (__io.flags() & ios_base::floatfield) != ios_base::floatfield; | |
1017 | ||
7c9b102e | 1018 | // First try a buffer perhaps big enough (most probably sufficient |
ce3039af | 1019 | // for non-ios_base::fixed outputs) |
6d8e16a4 PC |
1020 | int __cs_size = __max_digits * 3; |
1021 | char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); | |
9d07d890 JW |
1022 | if (__use_prec) |
1023 | __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size, | |
1024 | __fbuf, __prec, __v); | |
1025 | else | |
1026 | __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size, | |
1027 | __fbuf, __v); | |
6d8e16a4 PC |
1028 | |
1029 | // If the buffer was not large enough, try again with the correct size. | |
1030 | if (__len >= __cs_size) | |
1031 | { | |
ed6814f7 | 1032 | __cs_size = __len + 1; |
6d8e16a4 | 1033 | __cs = static_cast<char*>(__builtin_alloca(__cs_size)); |
9d07d890 JW |
1034 | if (__use_prec) |
1035 | __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size, | |
1036 | __fbuf, __prec, __v); | |
1037 | else | |
1038 | __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size, | |
1039 | __fbuf, __v); | |
6d8e16a4 PC |
1040 | } |
1041 | #else | |
0228de0c BK |
1042 | // Consider the possibility of long ios_base::fixed outputs |
1043 | const bool __fixed = __io.flags() & ios_base::fixed; | |
6725add5 PC |
1044 | const int __max_exp = |
1045 | __gnu_cxx::__numeric_traits<_ValueT>::__max_exponent10; | |
ce3039af | 1046 | |
7942afdc | 1047 | // The size of the output string is computed as follows. |
7c9b102e PC |
1048 | // ios_base::fixed outputs may need up to __max_exp + 1 chars |
1049 | // for the integer part + __prec chars for the fractional part | |
1050 | // + 3 chars for sign, decimal point, '\0'. On the other hand, | |
1051 | // for non-fixed outputs __max_digits * 2 + __prec chars are | |
1052 | // largely sufficient. | |
1053 | const int __cs_size = __fixed ? __max_exp + __prec + 4 | |
1054 | : __max_digits * 2 + __prec; | |
0228de0c | 1055 | char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); |
964c5329 PC |
1056 | __len = std::__convert_from_v(_S_get_c_locale(), __cs, 0, __fbuf, |
1057 | __prec, __v); | |
6d8e16a4 | 1058 | #endif |
725dc051 | 1059 | |
101c5bc5 PC |
1060 | // [22.2.2.2.2] Stage 2, convert to char_type, using correct |
1061 | // numpunct.decimal_point() values for '.' and adding grouping. | |
1062 | const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); | |
1063 | ||
1064 | _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) | |
1065 | * __len)); | |
1066 | __ctype.widen(__cs, __cs + __len, __ws); | |
1067 | ||
1068 | // Replace decimal point. | |
caade192 PC |
1069 | _CharT* __wp = 0; |
1070 | const char* __p = char_traits<char>::find(__cs, __len, '.'); | |
101c5bc5 | 1071 | if (__p) |
caade192 PC |
1072 | { |
1073 | __wp = __ws + (__p - __cs); | |
1074 | *__wp = __lc->_M_decimal_point; | |
1075 | } | |
101c5bc5 PC |
1076 | |
1077 | // Add grouping, if necessary. | |
1078 | // N.B. Make sure to not group things like 2e20, i.e., no decimal | |
1079 | // point, scientific notation. | |
1080 | if (__lc->_M_use_grouping | |
caade192 PC |
1081 | && (__wp || __len < 3 || (__cs[1] <= '9' && __cs[2] <= '9' |
1082 | && __cs[1] >= '0' && __cs[2] >= '0'))) | |
101c5bc5 PC |
1083 | { |
1084 | // Grouping can add (almost) as many separators as the | |
1085 | // number of digits, but no more. | |
1086 | _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) | |
1087 | * __len * 2)); | |
1088 | ||
1089 | streamsize __off = 0; | |
1090 | if (__cs[0] == '-' || __cs[0] == '+') | |
1091 | { | |
1092 | __off = 1; | |
1093 | __ws2[0] = __ws[0]; | |
1094 | __len -= 1; | |
1095 | } | |
1096 | ||
1097 | _M_group_float(__lc->_M_grouping, __lc->_M_grouping_size, | |
caade192 | 1098 | __lc->_M_thousands_sep, __wp, __ws2 + __off, |
101c5bc5 PC |
1099 | __ws + __off, __len); |
1100 | __len += __off; | |
1101 | ||
1102 | __ws = __ws2; | |
1103 | } | |
ed6814f7 | 1104 | |
101c5bc5 PC |
1105 | // Pad. |
1106 | const streamsize __w = __io.width(); | |
1107 | if (__w > static_cast<streamsize>(__len)) | |
1108 | { | |
1109 | _CharT* __ws3 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) | |
1110 | * __w)); | |
1111 | _M_pad(__fill, __w, __io, __ws3, __ws, __len); | |
1112 | __ws = __ws3; | |
1113 | } | |
1114 | __io.width(0); | |
1115 | ||
1116 | // [22.2.2.2.2] Stage 4. | |
1117 | // Write resulting, fully-formatted string to output iterator. | |
1118 | return std::__write(__s, __ws, __len); | |
ce3039af | 1119 | } |
101c5bc5 | 1120 | |
fb678854 | 1121 | template<typename _CharT, typename _OutIter> |
725dc051 BK |
1122 | _OutIter |
1123 | num_put<_CharT, _OutIter>:: | |
1124 | do_put(iter_type __s, ios_base& __io, char_type __fill, bool __v) const | |
1125 | { | |
905df1fb | 1126 | const ios_base::fmtflags __flags = __io.flags(); |
725dc051 BK |
1127 | if ((__flags & ios_base::boolalpha) == 0) |
1128 | { | |
44e91562 PC |
1129 | const long __l = __v; |
1130 | __s = _M_insert_int(__s, __io, __fill, __l); | |
725dc051 BK |
1131 | } |
1132 | else | |
1133 | { | |
a70c902e | 1134 | typedef __numpunct_cache<_CharT> __cache_type; |
cde63840 | 1135 | __use_cache<__cache_type> __uc; |
215f9e28 | 1136 | const locale& __loc = __io._M_getloc(); |
cde63840 | 1137 | const __cache_type* __lc = __uc(__loc); |
215f9e28 | 1138 | |
ed6814f7 | 1139 | const _CharT* __name = __v ? __lc->_M_truename |
6c39c207 | 1140 | : __lc->_M_falsename; |
47f62b27 PC |
1141 | int __len = __v ? __lc->_M_truename_size |
1142 | : __lc->_M_falsename_size; | |
ce3039af | 1143 | |
905df1fb | 1144 | const streamsize __w = __io.width(); |
ce3039af JQ |
1145 | if (__w > static_cast<streamsize>(__len)) |
1146 | { | |
7391b597 PC |
1147 | const streamsize __plen = __w - __len; |
1148 | _CharT* __ps | |
a8ea7389 | 1149 | = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) |
7391b597 PC |
1150 | * __plen)); |
1151 | ||
1152 | char_traits<_CharT>::assign(__ps, __plen, __fill); | |
1153 | __io.width(0); | |
1154 | ||
1155 | if ((__flags & ios_base::adjustfield) == ios_base::left) | |
1156 | { | |
1157 | __s = std::__write(__s, __name, __len); | |
1158 | __s = std::__write(__s, __ps, __plen); | |
1159 | } | |
1160 | else | |
1161 | { | |
1162 | __s = std::__write(__s, __ps, __plen); | |
1163 | __s = std::__write(__s, __name, __len); | |
1164 | } | |
1165 | return __s; | |
ce3039af JQ |
1166 | } |
1167 | __io.width(0); | |
7942afdc | 1168 | __s = std::__write(__s, __name, __len); |
86ade44c BK |
1169 | } |
1170 | return __s; | |
1ab65677 BK |
1171 | } |
1172 | ||
1173 | template<typename _CharT, typename _OutIter> | |
1ab65677 BK |
1174 | _OutIter |
1175 | num_put<_CharT, _OutIter>:: | |
1176 | do_put(iter_type __s, ios_base& __io, char_type __fill, double __v) const | |
7942afdc | 1177 | { return _M_insert_float(__s, __io, __fill, char(), __v); } |
1ab65677 | 1178 | |
6defecc2 JJ |
1179 | #if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__ |
1180 | template<typename _CharT, typename _OutIter> | |
1181 | _OutIter | |
1182 | num_put<_CharT, _OutIter>:: | |
1183 | __do_put(iter_type __s, ios_base& __io, char_type __fill, double __v) const | |
1184 | { return _M_insert_float(__s, __io, __fill, char(), __v); } | |
1185 | #endif | |
1186 | ||
1ab65677 BK |
1187 | template<typename _CharT, typename _OutIter> |
1188 | _OutIter | |
1189 | num_put<_CharT, _OutIter>:: | |
ed6814f7 | 1190 | do_put(iter_type __s, ios_base& __io, char_type __fill, |
86ade44c | 1191 | long double __v) const |
7942afdc | 1192 | { return _M_insert_float(__s, __io, __fill, 'L', __v); } |
1ab65677 BK |
1193 | |
1194 | template<typename _CharT, typename _OutIter> | |
1195 | _OutIter | |
1196 | num_put<_CharT, _OutIter>:: | |
1197 | do_put(iter_type __s, ios_base& __io, char_type __fill, | |
1198 | const void* __v) const | |
1199 | { | |
905df1fb | 1200 | const ios_base::fmtflags __flags = __io.flags(); |
44e91562 | 1201 | const ios_base::fmtflags __fmt = ~(ios_base::basefield |
d2f6b13b | 1202 | | ios_base::uppercase); |
2a67bec2 | 1203 | __io.flags((__flags & __fmt) | (ios_base::hex | ios_base::showbase)); |
ed6814f7 | 1204 | |
5b3f6d1a PC |
1205 | typedef __gnu_cxx::__conditional_type<(sizeof(const void*) |
1206 | <= sizeof(unsigned long)), | |
1207 | unsigned long, unsigned long long>::__type _UIntPtrType; | |
1208 | ||
ed6814f7 | 1209 | __s = _M_insert_int(__s, __io, __fill, |
5b3f6d1a | 1210 | reinterpret_cast<_UIntPtrType>(__v)); |
e8c5fc66 | 1211 | __io.flags(__flags); |
86ade44c | 1212 | return __s; |
1ab65677 BK |
1213 | } |
1214 | ||
7c1e7eed JW |
1215 | #if defined _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT \ |
1216 | && defined __LONG_DOUBLE_IEEE128__ | |
1217 | template<typename _CharT, typename _OutIter> | |
1218 | _OutIter | |
1219 | num_put<_CharT, _OutIter>:: | |
1220 | __do_put(iter_type __s, ios_base& __io, char_type __fill, | |
1221 | __ibm128 __v) const | |
1222 | { return _M_insert_float(__s, __io, __fill, 'L', __v); } | |
1223 | #endif | |
12ffa228 | 1224 | _GLIBCXX_END_NAMESPACE_LDBL |
586b5f20 | 1225 | |
86ade44c | 1226 | // Construct correctly padded string, as per 22.2.2.2.2 |
ed6814f7 | 1227 | // Assumes |
86ade44c BK |
1228 | // __newlen > __oldlen |
1229 | // __news is allocated for __newlen size | |
f13a69ec BK |
1230 | |
1231 | // NB: Of the two parameters, _CharT can be deduced from the | |
1232 | // function arguments. The other (_Traits) has to be explicitly specified. | |
f13a69ec | 1233 | template<typename _CharT, typename _Traits> |
ed6814f7 BI |
1234 | void |
1235 | __pad<_CharT, _Traits>::_S_pad(ios_base& __io, _CharT __fill, | |
1236 | _CharT* __news, const _CharT* __olds, | |
4a2095e2 | 1237 | streamsize __newlen, streamsize __oldlen) |
f13a69ec | 1238 | { |
e4f7d0a1 PC |
1239 | const size_t __plen = static_cast<size_t>(__newlen - __oldlen); |
1240 | const ios_base::fmtflags __adjust = __io.flags() & ios_base::adjustfield; | |
86ade44c | 1241 | |
e4f7d0a1 | 1242 | // Padding last. |
86ade44c BK |
1243 | if (__adjust == ios_base::left) |
1244 | { | |
a576fe88 | 1245 | _Traits::copy(__news, __olds, __oldlen); |
e4f7d0a1 PC |
1246 | _Traits::assign(__news + __oldlen, __plen, __fill); |
1247 | return; | |
86ade44c | 1248 | } |
e4f7d0a1 PC |
1249 | |
1250 | size_t __mod = 0; | |
11202768 | 1251 | if (__adjust == ios_base::internal) |
86ade44c BK |
1252 | { |
1253 | // Pad after the sign, if there is one. | |
1254 | // Pad after 0[xX], if there is one. | |
1255 | // Who came up with these rules, anyway? Jeeze. | |
7942afdc | 1256 | const locale& __loc = __io._M_getloc(); |
ed6814f7 | 1257 | const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); |
230377dc | 1258 | |
a576fe88 PC |
1259 | if (__ctype.widen('-') == __olds[0] |
1260 | || __ctype.widen('+') == __olds[0]) | |
86ade44c | 1261 | { |
ed6814f7 | 1262 | __news[0] = __olds[0]; |
a576fe88 PC |
1263 | __mod = 1; |
1264 | ++__news; | |
86ade44c | 1265 | } |
a576fe88 PC |
1266 | else if (__ctype.widen('0') == __olds[0] |
1267 | && __oldlen > 1 | |
1268 | && (__ctype.widen('x') == __olds[1] | |
1269 | || __ctype.widen('X') == __olds[1])) | |
86ade44c | 1270 | { |
a3aff86a | 1271 | __news[0] = __olds[0]; |
a576fe88 PC |
1272 | __news[1] = __olds[1]; |
1273 | __mod = 2; | |
1274 | __news += 2; | |
86ade44c | 1275 | } |
5b577977 | 1276 | // else Padding first. |
86ade44c | 1277 | } |
e4f7d0a1 | 1278 | _Traits::assign(__news, __plen, __fill); |
a576fe88 | 1279 | _Traits::copy(__news + __plen, __olds + __mod, __oldlen - __mod); |
86ade44c BK |
1280 | } |
1281 | ||
1ab65677 BK |
1282 | template<typename _CharT> |
1283 | _CharT* | |
47f62b27 PC |
1284 | __add_grouping(_CharT* __s, _CharT __sep, |
1285 | const char* __gbeg, size_t __gsize, | |
1ab65677 | 1286 | const _CharT* __first, const _CharT* __last) |
bf058d22 | 1287 | { |
a484326f PC |
1288 | size_t __idx = 0; |
1289 | size_t __ctr = 0; | |
1290 | ||
1291 | while (__last - __first > __gbeg[__idx] | |
bbcac3be PC |
1292 | && static_cast<signed char>(__gbeg[__idx]) > 0 |
1293 | && __gbeg[__idx] != __gnu_cxx::__numeric_traits<char>::__max) | |
bf058d22 | 1294 | { |
a484326f PC |
1295 | __last -= __gbeg[__idx]; |
1296 | __idx < __gsize - 1 ? ++__idx : ++__ctr; | |
bf058d22 | 1297 | } |
a484326f PC |
1298 | |
1299 | while (__first != __last) | |
bf058d22 | 1300 | *__s++ = *__first++; |
a484326f PC |
1301 | |
1302 | while (__ctr--) | |
1303 | { | |
1304 | *__s++ = __sep; | |
1305 | for (char __i = __gbeg[__idx]; __i > 0; --__i) | |
1306 | *__s++ = *__first++; | |
1307 | } | |
1308 | ||
1309 | while (__idx--) | |
1310 | { | |
1311 | *__s++ = __sep; | |
1312 | for (char __i = __gbeg[__idx]; __i > 0; --__i) | |
1313 | *__s++ = *__first++; | |
1314 | } | |
1315 | ||
bf058d22 PC |
1316 | return __s; |
1317 | } | |
a32e3c09 BK |
1318 | |
1319 | // Inhibit implicit instantiations for required instantiations, | |
ed6814f7 | 1320 | // which are defined via explicit instantiations elsewhere. |
3d7c150e | 1321 | #if _GLIBCXX_EXTERN_TEMPLATE |
34a2b755 JW |
1322 | extern template class _GLIBCXX_NAMESPACE_CXX11 numpunct<char>; |
1323 | extern template class _GLIBCXX_NAMESPACE_CXX11 numpunct_byname<char>; | |
12ffa228 BK |
1324 | extern template class _GLIBCXX_NAMESPACE_LDBL num_get<char>; |
1325 | extern template class _GLIBCXX_NAMESPACE_LDBL num_put<char>; | |
a32e3c09 | 1326 | extern template class ctype_byname<char>; |
41b4d44b | 1327 | |
08376e28 PC |
1328 | extern template |
1329 | const ctype<char>& | |
1330 | use_facet<ctype<char> >(const locale&); | |
1331 | ||
41b4d44b | 1332 | extern template |
ed6814f7 | 1333 | const numpunct<char>& |
41b4d44b BK |
1334 | use_facet<numpunct<char> >(const locale&); |
1335 | ||
ed6814f7 BI |
1336 | extern template |
1337 | const num_put<char>& | |
41b4d44b BK |
1338 | use_facet<num_put<char> >(const locale&); |
1339 | ||
ed6814f7 BI |
1340 | extern template |
1341 | const num_get<char>& | |
41b4d44b BK |
1342 | use_facet<num_get<char> >(const locale&); |
1343 | ||
ed6814f7 | 1344 | extern template |
41b4d44b BK |
1345 | bool |
1346 | has_facet<ctype<char> >(const locale&); | |
1347 | ||
ed6814f7 | 1348 | extern template |
41b4d44b BK |
1349 | bool |
1350 | has_facet<numpunct<char> >(const locale&); | |
a32e3c09 | 1351 | |
ed6814f7 | 1352 | extern template |
41b4d44b BK |
1353 | bool |
1354 | has_facet<num_put<char> >(const locale&); | |
a32e3c09 | 1355 | |
ed6814f7 | 1356 | extern template |
41b4d44b BK |
1357 | bool |
1358 | has_facet<num_get<char> >(const locale&); | |
a32e3c09 | 1359 | |
3d7c150e | 1360 | #ifdef _GLIBCXX_USE_WCHAR_T |
34a2b755 JW |
1361 | extern template class _GLIBCXX_NAMESPACE_CXX11 numpunct<wchar_t>; |
1362 | extern template class _GLIBCXX_NAMESPACE_CXX11 numpunct_byname<wchar_t>; | |
12ffa228 BK |
1363 | extern template class _GLIBCXX_NAMESPACE_LDBL num_get<wchar_t>; |
1364 | extern template class _GLIBCXX_NAMESPACE_LDBL num_put<wchar_t>; | |
5112ae3a | 1365 | extern template class ctype_byname<wchar_t>; |
5112ae3a | 1366 | |
08376e28 PC |
1367 | extern template |
1368 | const ctype<wchar_t>& | |
1369 | use_facet<ctype<wchar_t> >(const locale&); | |
1370 | ||
5112ae3a | 1371 | extern template |
ed6814f7 | 1372 | const numpunct<wchar_t>& |
5112ae3a BK |
1373 | use_facet<numpunct<wchar_t> >(const locale&); |
1374 | ||
ed6814f7 BI |
1375 | extern template |
1376 | const num_put<wchar_t>& | |
5112ae3a BK |
1377 | use_facet<num_put<wchar_t> >(const locale&); |
1378 | ||
ed6814f7 BI |
1379 | extern template |
1380 | const num_get<wchar_t>& | |
5112ae3a BK |
1381 | use_facet<num_get<wchar_t> >(const locale&); |
1382 | ||
ed6814f7 | 1383 | extern template |
41b4d44b BK |
1384 | bool |
1385 | has_facet<ctype<wchar_t> >(const locale&); | |
1386 | ||
ed6814f7 | 1387 | extern template |
41b4d44b BK |
1388 | bool |
1389 | has_facet<numpunct<wchar_t> >(const locale&); | |
1390 | ||
ed6814f7 | 1391 | extern template |
41b4d44b BK |
1392 | bool |
1393 | has_facet<num_put<wchar_t> >(const locale&); | |
1394 | ||
ed6814f7 | 1395 | extern template |
41b4d44b BK |
1396 | bool |
1397 | has_facet<num_get<wchar_t> >(const locale&); | |
5112ae3a | 1398 | #endif |
1bc8b0ad | 1399 | #endif |
3cbc7af0 | 1400 | |
12ffa228 BK |
1401 | _GLIBCXX_END_NAMESPACE_VERSION |
1402 | } // namespace | |
41b4d44b BK |
1403 | |
1404 | #endif |