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