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