locale_facets.tcc (num_get<>::_M_extract_float, [...]): If appropriate, call reserve...
[gcc.git] / libstdc++-v3 / include / bits / locale_facets.tcc
1 // Locale support -*- C++ -*-
2
3 // Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
4 // Free Software Foundation, Inc.
5 //
6 // This file is part of the GNU ISO C++ Library. This library is free
7 // software; you can redistribute it and/or modify it under the
8 // terms of the GNU General Public License as published by the
9 // Free Software Foundation; either version 2, or (at your option)
10 // any later version.
11
12 // This library is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
16
17 // You should have received a copy of the GNU General Public License along
18 // with this library; see the file COPYING. If not, write to the Free
19 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
20 // USA.
21
22 // As a special exception, you may use this file as part of a free software
23 // library without restriction. Specifically, if other files instantiate
24 // templates or use macros or inline functions from this file, or you compile
25 // this file and link it with other files to produce an executable, this
26 // file does not by itself cause the resulting executable to be covered by
27 // the GNU General Public License. This exception does not however
28 // invalidate any other reasons why the executable file might be covered by
29 // the GNU General Public License.
30
31 // Warning: this file is not meant for user inclusion. Use <locale>.
32
33 #ifndef _LOCALE_FACETS_TCC
34 #define _LOCALE_FACETS_TCC 1
35
36 #pragma GCC system_header
37
38 #include <limits> // For numeric_limits
39 #include <typeinfo> // For bad_cast.
40 #include <bits/streambuf_iterator.h>
41
42 namespace std
43 {
44 template<typename _Facet>
45 locale
46 locale::combine(const locale& __other) const
47 {
48 _Impl* __tmp = new _Impl(*_M_impl, 1);
49 try
50 {
51 __tmp->_M_replace_facet(__other._M_impl, &_Facet::id);
52 }
53 catch(...)
54 {
55 __tmp->_M_remove_reference();
56 __throw_exception_again;
57 }
58 return locale(__tmp);
59 }
60
61 template<typename _CharT, typename _Traits, typename _Alloc>
62 bool
63 locale::operator()(const basic_string<_CharT, _Traits, _Alloc>& __s1,
64 const basic_string<_CharT, _Traits, _Alloc>& __s2) const
65 {
66 typedef std::collate<_CharT> __collate_type;
67 const __collate_type& __collate = use_facet<__collate_type>(*this);
68 return (__collate.compare(__s1.data(), __s1.data() + __s1.length(),
69 __s2.data(), __s2.data() + __s2.length()) < 0);
70 }
71
72 /**
73 * @brief Test for the presence of a facet.
74 *
75 * has_facet tests the locale argument for the presence of the facet type
76 * provided as the template parameter. Facets derived from the facet
77 * parameter will also return true.
78 *
79 * @param Facet The facet type to test the presence of.
80 * @param locale The locale to test.
81 * @return true if locale contains a facet of type Facet, else false.
82 * @throw std::bad_cast if locale doesn't contain the facet.
83 */
84 template<typename _Facet>
85 inline bool
86 has_facet(const locale& __loc) throw()
87 {
88 const size_t __i = _Facet::id._M_id();
89 const locale::facet** __facets = __loc._M_impl->_M_facets;
90 return (__i < __loc._M_impl->_M_facets_size && __facets[__i]);
91 }
92
93 /**
94 * @brief Return a facet.
95 *
96 * use_facet looks for and returns a reference to a facet of type Facet
97 * where Facet is the template parameter. If has_facet(locale) is true,
98 * there is a suitable facet to return. It throws std::bad_cast if the
99 * locale doesn't contain a facet of type Facet.
100 *
101 * @param Facet The facet type to access.
102 * @param locale The locale to use.
103 * @return Reference to facet of type Facet.
104 * @throw std::bad_cast if locale doesn't contain a facet of type Facet.
105 */
106 template<typename _Facet>
107 inline const _Facet&
108 use_facet(const locale& __loc)
109 {
110 const size_t __i = _Facet::id._M_id();
111 const locale::facet** __facets = __loc._M_impl->_M_facets;
112 if (!(__i < __loc._M_impl->_M_facets_size && __facets[__i]))
113 __throw_bad_cast();
114 return static_cast<const _Facet&>(*__facets[__i]);
115 }
116
117 // Routine to access a cache for the facet. If the cache didn't
118 // exist before, it gets constructed on the fly.
119 template<typename _Facet>
120 struct __use_cache
121 {
122 const _Facet*
123 operator() (const locale& __loc) const;
124 };
125
126 template<typename _CharT>
127 struct __use_cache<__numpunct_cache<_CharT> >
128 {
129 const __numpunct_cache<_CharT>*
130 operator() (const locale& __loc) const
131 {
132 const size_t __i = numpunct<_CharT>::id._M_id();
133 const locale::facet** __caches = __loc._M_impl->_M_caches;
134 if (!__caches[__i])
135 {
136 __numpunct_cache<_CharT>* __tmp = NULL;
137 try
138 {
139 __tmp = new __numpunct_cache<_CharT>;
140 __tmp->_M_cache(__loc);
141 }
142 catch(...)
143 {
144 delete __tmp;
145 __throw_exception_again;
146 }
147 __loc._M_impl->_M_install_cache(__tmp, __i);
148 }
149 return static_cast<const __numpunct_cache<_CharT>*>(__caches[__i]);
150 }
151 };
152
153 // Used by both numeric and monetary facets.
154 // Check to make sure that the __grouping_tmp string constructed in
155 // money_get or num_get matches the canonical grouping for a given
156 // locale.
157 // __grouping_tmp is parsed L to R
158 // 1,222,444 == __grouping_tmp of "\1\3\3"
159 // __grouping is parsed R to L
160 // 1,222,444 == __grouping of "\3" == "\3\3\3"
161 static bool
162 __verify_grouping(const char* __grouping, size_t __grouping_size,
163 const string& __grouping_tmp);
164
165 template<typename _CharT, typename _InIter>
166 _InIter
167 num_get<_CharT, _InIter>::
168 _M_extract_float(_InIter __beg, _InIter __end, ios_base& __io,
169 ios_base::iostate& __err, string& __xtrc) const
170 {
171 typedef char_traits<_CharT> __traits_type;
172 typedef typename numpunct<_CharT>::__cache_type __cache_type;
173 __use_cache<__cache_type> __uc;
174 const locale& __loc = __io._M_getloc();
175 const __cache_type* __lc = __uc(__loc);
176 const _CharT* __lit = __lc->_M_atoms_in;
177
178 // True if a mantissa is found.
179 bool __found_mantissa = false;
180
181 // First check for sign.
182 if (__beg != __end)
183 {
184 const char_type __c = *__beg;
185 const bool __plus = __traits_type::eq(__c, __lit[_S_iplus]);
186 if ((__plus || __traits_type::eq(__c, __lit[_S_iminus]))
187 && !__traits_type::eq(__c, __lc->_M_decimal_point)
188 && (!__lc->_M_use_grouping
189 || !__traits_type::eq(__c, __lc->_M_thousands_sep)))
190 {
191 __xtrc += __plus ? _S_atoms_in[_S_iplus]
192 : _S_atoms_in[_S_iminus];
193 ++__beg;
194 }
195 }
196
197 // Next, look for leading zeros.
198 while (__beg != __end)
199 {
200 const char_type __c = *__beg;
201 if (__traits_type::eq(__c, __lc->_M_decimal_point)
202 || (__lc->_M_use_grouping
203 && __traits_type::eq(__c, __lc->_M_thousands_sep)))
204 break;
205 else if (__traits_type::eq(__c, __lit[_S_izero]))
206 {
207 if (!__found_mantissa)
208 {
209 __xtrc += _S_atoms_in[_S_izero];
210 __found_mantissa = true;
211 }
212 ++__beg;
213 }
214 else
215 break;
216 }
217
218 // Only need acceptable digits for floating point numbers.
219 bool __found_dec = false;
220 bool __found_sci = false;
221 string __found_grouping;
222 if (__lc->_M_use_grouping)
223 __found_grouping.reserve(32);
224 int __sep_pos = 0;
225 bool __e;
226 const char_type* __q;
227 while (__beg != __end)
228 {
229 // According to 22.2.2.1.2, p8-9, first look for thousands_sep
230 // and decimal_point.
231 const char_type __c = *__beg;
232 if (__lc->_M_use_grouping
233 && __traits_type::eq(__c, __lc->_M_thousands_sep))
234 {
235 if (!__found_dec && !__found_sci)
236 {
237 // NB: Thousands separator at the beginning of a string
238 // is a no-no, as is two consecutive thousands separators.
239 if (__sep_pos)
240 {
241 __found_grouping += static_cast<char>(__sep_pos);
242 __sep_pos = 0;
243 ++__beg;
244 }
245 else
246 {
247 __err |= ios_base::failbit;
248 break;
249 }
250 }
251 else
252 break;
253 }
254 else if (__traits_type::eq(__c, __lc->_M_decimal_point))
255 {
256 if (!__found_dec && !__found_sci)
257 {
258 // If no grouping chars are seen, no grouping check
259 // is applied. Therefore __found_grouping is adjusted
260 // only if decimal_point comes after some thousands_sep.
261 if (__found_grouping.size())
262 __found_grouping += static_cast<char>(__sep_pos);
263 __xtrc += '.';
264 __found_dec = true;
265 ++__beg;
266 }
267 else
268 break;
269 }
270 else if (__q = __traits_type::find(__lit + _S_izero, 10, __c))
271 {
272 __xtrc += _S_atoms_in[__q - __lit];
273 __found_mantissa = true;
274 ++__sep_pos;
275 ++__beg;
276 }
277 else if ((__e = __traits_type::eq(__c, __lit[_S_ie])
278 || __traits_type::eq(__c, __lit[_S_iE]))
279 && __found_mantissa && !__found_sci)
280 {
281 // Scientific notation.
282 __xtrc += __e ? _S_atoms_in[_S_ie] : _S_atoms_in[_S_iE];
283 __found_sci = true;
284
285 // Remove optional plus or minus sign, if they exist.
286 if (++__beg != __end)
287 {
288 const bool __plus = __traits_type::eq(*__beg,
289 __lit[_S_iplus]);
290 if (__plus || __traits_type::eq(*__beg, __lit[_S_iminus]))
291 {
292 __xtrc += __plus ? _S_atoms_in[_S_iplus]
293 : _S_atoms_in[_S_iminus];
294 ++__beg;
295 }
296 }
297 }
298 else
299 // Not a valid input item.
300 break;
301 }
302
303 // Digit grouping is checked. If grouping and found_grouping don't
304 // match, then get very very upset, and set failbit.
305 if (__found_grouping.size())
306 {
307 // Add the ending grouping if a decimal wasn't found.
308 if (!__found_dec)
309 __found_grouping += static_cast<char>(__sep_pos);
310
311 if (!std::__verify_grouping(__lc->_M_grouping, __lc->_M_grouping_size,
312 __found_grouping))
313 __err |= ios_base::failbit;
314 }
315
316 // Finish up.
317 if (__beg == __end)
318 __err |= ios_base::eofbit;
319 return __beg;
320 }
321
322 template<typename _CharT, typename _InIter>
323 template<typename _ValueT>
324 _InIter
325 num_get<_CharT, _InIter>::
326 _M_extract_int(_InIter __beg, _InIter __end, ios_base& __io,
327 ios_base::iostate& __err, _ValueT& __v) const
328 {
329 typedef char_traits<_CharT> __traits_type;
330 typedef typename numpunct<_CharT>::__cache_type __cache_type;
331 __use_cache<__cache_type> __uc;
332 const locale& __loc = __io._M_getloc();
333 const __cache_type* __lc = __uc(__loc);
334 const _CharT* __lit = __lc->_M_atoms_in;
335
336 // NB: Iff __basefield == 0, __base can change based on contents.
337 const ios_base::fmtflags __basefield = __io.flags()
338 & ios_base::basefield;
339 const bool __oct = __basefield == ios_base::oct;
340 int __base = __oct ? 8 : (__basefield == ios_base::hex ? 16 : 10);
341
342 // True if numeric digits are found.
343 bool __found_num = false;
344
345 // First check for sign.
346 bool __negative = false;
347 if (__beg != __end)
348 {
349 const char_type __c = *__beg;
350 if (numeric_limits<_ValueT>::is_signed)
351 __negative = __traits_type::eq(__c, __lit[_S_iminus]);
352 if ((__negative || __traits_type::eq(__c, __lit[_S_iplus]))
353 && !__traits_type::eq(__c, __lc->_M_decimal_point)
354 && (!__lc->_M_use_grouping
355 || !__traits_type::eq(__c, __lc->_M_thousands_sep)))
356 ++__beg;
357 }
358
359 // Next, look for leading zeros and check required digits
360 // for base formats.
361 while (__beg != __end)
362 {
363 const char_type __c = *__beg;
364 if (__traits_type::eq(__c, __lc->_M_decimal_point)
365 || (__lc->_M_use_grouping
366 && __traits_type::eq(__c, __lc->_M_thousands_sep)))
367 break;
368 else if (__traits_type::eq(__c, __lit[_S_izero])
369 && (!__found_num || __base == 10))
370 {
371 __found_num = true;
372 ++__beg;
373 }
374 else if (__found_num)
375 {
376 if (__traits_type::eq(__c, __lit[_S_ix])
377 || __traits_type::eq(__c, __lit[_S_iX]))
378 {
379 if (__basefield == 0)
380 __base = 16;
381 if (__base == 16)
382 {
383 __found_num = false;
384 ++__beg;
385 }
386 }
387 else if (__basefield == 0)
388 __base = 8;
389 break;
390 }
391 else
392 break;
393 }
394
395 // At this point, base is determined. If not hex, only allow
396 // base digits as valid input.
397 const size_t __len = __base == 16 ? _S_iend - _S_izero : __base;
398
399 // Extract.
400 string __found_grouping;
401 if (__lc->_M_use_grouping)
402 __found_grouping.reserve(32);
403 int __sep_pos = 0;
404 bool __overflow = false;
405 _ValueT __result = 0;
406 const char_type* __lit_zero = __lit + _S_izero;
407 const char_type* __q;
408 if (__negative)
409 {
410 const _ValueT __min = numeric_limits<_ValueT>::min() / __base;
411 for (; __beg != __end; ++__beg)
412 {
413 // According to 22.2.2.1.2, p8-9, first look for thousands_sep
414 // and decimal_point.
415 const char_type __c = *__beg;
416 if (__lc->_M_use_grouping
417 && __traits_type::eq(__c, __lc->_M_thousands_sep))
418 {
419 // NB: Thousands separator at the beginning of a string
420 // is a no-no, as is two consecutive thousands separators.
421 if (__sep_pos)
422 {
423 __found_grouping += static_cast<char>(__sep_pos);
424 __sep_pos = 0;
425 }
426 else
427 {
428 __err |= ios_base::failbit;
429 break;
430 }
431 }
432 else if (__traits_type::eq(__c, __lc->_M_decimal_point))
433 break;
434 else if (__q = __traits_type::find(__lit_zero, __len, __c))
435 {
436 int __digit = __q - __lit_zero;
437 if (__digit > 15)
438 __digit -= 6;
439 if (__result < __min)
440 __overflow = true;
441 else
442 {
443 const _ValueT __new_result = __result * __base
444 - __digit;
445 __overflow |= __new_result > __result;
446 __result = __new_result;
447 ++__sep_pos;
448 __found_num = true;
449 }
450 }
451 else
452 // Not a valid input item.
453 break;
454 }
455 }
456 else
457 {
458 const _ValueT __max = numeric_limits<_ValueT>::max() / __base;
459 for (; __beg != __end; ++__beg)
460 {
461 const char_type __c = *__beg;
462 if (__lc->_M_use_grouping
463 && __traits_type::eq(__c, __lc->_M_thousands_sep))
464 {
465 if (__sep_pos)
466 {
467 __found_grouping += static_cast<char>(__sep_pos);
468 __sep_pos = 0;
469 }
470 else
471 {
472 __err |= ios_base::failbit;
473 break;
474 }
475 }
476 else if (__traits_type::eq(__c, __lc->_M_decimal_point))
477 break;
478 else if (__q = __traits_type::find(__lit_zero, __len, __c))
479 {
480 int __digit = __q - __lit_zero;
481 if (__digit > 15)
482 __digit -= 6;
483 if (__result > __max)
484 __overflow = true;
485 else
486 {
487 const _ValueT __new_result = __result * __base
488 + __digit;
489 __overflow |= __new_result < __result;
490 __result = __new_result;
491 ++__sep_pos;
492 __found_num = true;
493 }
494 }
495 else
496 break;
497 }
498 }
499
500 // Digit grouping is checked. If grouping and found_grouping don't
501 // match, then get very very upset, and set failbit.
502 if (__found_grouping.size())
503 {
504 // Add the ending grouping.
505 __found_grouping += static_cast<char>(__sep_pos);
506
507 if (!std::__verify_grouping(__lc->_M_grouping,
508 __lc->_M_grouping_size,
509 __found_grouping))
510 __err |= ios_base::failbit;
511 }
512
513 if (!(__err & ios_base::failbit) && !__overflow
514 && __found_num)
515 __v = __result;
516 else
517 __err |= ios_base::failbit;
518
519 if (__beg == __end)
520 __err |= ios_base::eofbit;
521 return __beg;
522 }
523
524 // _GLIBCXX_RESOLVE_LIB_DEFECTS
525 // 17. Bad bool parsing
526 template<typename _CharT, typename _InIter>
527 _InIter
528 num_get<_CharT, _InIter>::
529 do_get(iter_type __beg, iter_type __end, ios_base& __io,
530 ios_base::iostate& __err, bool& __v) const
531 {
532 if (!(__io.flags() & ios_base::boolalpha))
533 {
534 // Parse bool values as long.
535 // NB: We can't just call do_get(long) here, as it might
536 // refer to a derived class.
537 long __l = -1;
538 __beg = _M_extract_int(__beg, __end, __io, __err, __l);
539 if (__l == 0 || __l == 1)
540 __v = __l;
541 else
542 __err |= ios_base::failbit;
543 }
544 else
545 {
546 // Parse bool values as alphanumeric.
547 typedef char_traits<_CharT> __traits_type;
548 typedef typename numpunct<_CharT>::__cache_type __cache_type;
549 __use_cache<__cache_type> __uc;
550 const locale& __loc = __io._M_getloc();
551 const __cache_type* __lc = __uc(__loc);
552
553 bool __testf = true;
554 bool __testt = true;
555 size_t __n;
556 for (__n = 0; __beg != __end; ++__n, ++__beg)
557 {
558 if (__testf)
559 if (__n < __lc->_M_falsename_size)
560 __testf = __traits_type::eq(*__beg, __lc->_M_falsename[__n]);
561 else
562 break;
563
564 if (__testt)
565 if (__n < __lc->_M_truename_size)
566 __testt = __traits_type::eq(*__beg, __lc->_M_truename[__n]);
567 else
568 break;
569
570 if (!__testf && !__testt)
571 break;
572 }
573 if (__testf && __n == __lc->_M_falsename_size)
574 __v = 0;
575 else if (__testt && __n == __lc->_M_truename_size)
576 __v = 1;
577 else
578 __err |= ios_base::failbit;
579
580 if (__beg == __end)
581 __err |= ios_base::eofbit;
582 }
583 return __beg;
584 }
585
586 template<typename _CharT, typename _InIter>
587 _InIter
588 num_get<_CharT, _InIter>::
589 do_get(iter_type __beg, iter_type __end, ios_base& __io,
590 ios_base::iostate& __err, long& __v) const
591 { return _M_extract_int(__beg, __end, __io, __err, __v); }
592
593 template<typename _CharT, typename _InIter>
594 _InIter
595 num_get<_CharT, _InIter>::
596 do_get(iter_type __beg, iter_type __end, ios_base& __io,
597 ios_base::iostate& __err, unsigned short& __v) const
598 { return _M_extract_int(__beg, __end, __io, __err, __v); }
599
600 template<typename _CharT, typename _InIter>
601 _InIter
602 num_get<_CharT, _InIter>::
603 do_get(iter_type __beg, iter_type __end, ios_base& __io,
604 ios_base::iostate& __err, unsigned int& __v) const
605 { return _M_extract_int(__beg, __end, __io, __err, __v); }
606
607 template<typename _CharT, typename _InIter>
608 _InIter
609 num_get<_CharT, _InIter>::
610 do_get(iter_type __beg, iter_type __end, ios_base& __io,
611 ios_base::iostate& __err, unsigned long& __v) const
612 { return _M_extract_int(__beg, __end, __io, __err, __v); }
613
614 #ifdef _GLIBCXX_USE_LONG_LONG
615 template<typename _CharT, typename _InIter>
616 _InIter
617 num_get<_CharT, _InIter>::
618 do_get(iter_type __beg, iter_type __end, ios_base& __io,
619 ios_base::iostate& __err, long long& __v) const
620 { return _M_extract_int(__beg, __end, __io, __err, __v); }
621
622 template<typename _CharT, typename _InIter>
623 _InIter
624 num_get<_CharT, _InIter>::
625 do_get(iter_type __beg, iter_type __end, ios_base& __io,
626 ios_base::iostate& __err, unsigned long long& __v) const
627 { return _M_extract_int(__beg, __end, __io, __err, __v); }
628 #endif
629
630 template<typename _CharT, typename _InIter>
631 _InIter
632 num_get<_CharT, _InIter>::
633 do_get(iter_type __beg, iter_type __end, ios_base& __io,
634 ios_base::iostate& __err, float& __v) const
635 {
636 string __xtrc;
637 __xtrc.reserve(32);
638 __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc);
639 std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_get_c_locale());
640 return __beg;
641 }
642
643 template<typename _CharT, typename _InIter>
644 _InIter
645 num_get<_CharT, _InIter>::
646 do_get(iter_type __beg, iter_type __end, ios_base& __io,
647 ios_base::iostate& __err, double& __v) const
648 {
649 string __xtrc;
650 __xtrc.reserve(32);
651 __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc);
652 std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_get_c_locale());
653 return __beg;
654 }
655
656 template<typename _CharT, typename _InIter>
657 _InIter
658 num_get<_CharT, _InIter>::
659 do_get(iter_type __beg, iter_type __end, ios_base& __io,
660 ios_base::iostate& __err, long double& __v) const
661 {
662 string __xtrc;
663 __xtrc.reserve(32);
664 __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc);
665 std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_get_c_locale());
666 return __beg;
667 }
668
669 template<typename _CharT, typename _InIter>
670 _InIter
671 num_get<_CharT, _InIter>::
672 do_get(iter_type __beg, iter_type __end, ios_base& __io,
673 ios_base::iostate& __err, void*& __v) const
674 {
675 // Prepare for hex formatted input.
676 typedef ios_base::fmtflags fmtflags;
677 const fmtflags __fmt = __io.flags();
678 __io.flags(__fmt & ~ios_base::basefield | ios_base::hex);
679
680 unsigned long __ul;
681 __beg = _M_extract_int(__beg, __end, __io, __err, __ul);
682
683 // Reset from hex formatted input.
684 __io.flags(__fmt);
685
686 if (!(__err & ios_base::failbit))
687 __v = reinterpret_cast<void*>(__ul);
688 else
689 __err |= ios_base::failbit;
690 return __beg;
691 }
692
693 // For use by integer and floating-point types after they have been
694 // converted into a char_type string.
695 template<typename _CharT, typename _OutIter>
696 void
697 num_put<_CharT, _OutIter>::
698 _M_pad(_CharT __fill, streamsize __w, ios_base& __io,
699 _CharT* __new, const _CharT* __cs, int& __len) const
700 {
701 // [22.2.2.2.2] Stage 3.
702 // If necessary, pad.
703 __pad<_CharT, char_traits<_CharT> >::_S_pad(__io, __fill, __new, __cs,
704 __w, __len, true);
705 __len = static_cast<int>(__w);
706 }
707
708 // Forwarding functions to peel signed from unsigned integer types.
709 template<typename _CharT>
710 inline int
711 __int_to_char(_CharT* __bufend, long __v, const _CharT* __lit,
712 ios_base::fmtflags __flags)
713 {
714 unsigned long __ul = static_cast<unsigned long>(__v);
715 bool __neg = false;
716 if (__v < 0)
717 {
718 __ul = -__ul;
719 __neg = true;
720 }
721 return __int_to_char(__bufend, __ul, __lit, __flags, __neg);
722 }
723
724 template<typename _CharT>
725 inline int
726 __int_to_char(_CharT* __bufend, unsigned long __v, const _CharT* __lit,
727 ios_base::fmtflags __flags)
728 { return __int_to_char(__bufend, __v, __lit, __flags, false); }
729
730 #ifdef _GLIBCXX_USE_LONG_LONG
731 template<typename _CharT>
732 inline int
733 __int_to_char(_CharT* __bufend, long long __v, const _CharT* __lit,
734 ios_base::fmtflags __flags)
735 {
736 unsigned long long __ull = static_cast<unsigned long long>(__v);
737 bool __neg = false;
738 if (__v < 0)
739 {
740 __ull = -__ull;
741 __neg = true;
742 }
743 return __int_to_char(__bufend, __ull, __lit, __flags, __neg);
744 }
745
746 template<typename _CharT>
747 inline int
748 __int_to_char(_CharT* __bufend, unsigned long long __v, const _CharT* __lit,
749 ios_base::fmtflags __flags)
750 { return __int_to_char(__bufend, __v, __lit, __flags, false); }
751 #endif
752
753 template<typename _CharT, typename _ValueT>
754 int
755 __int_to_char(_CharT* __bufend, _ValueT __v, const _CharT* __lit,
756 ios_base::fmtflags __flags, bool __neg)
757 {
758 // Don't write base if already 0.
759 const bool __showbase = (__flags & ios_base::showbase) && __v;
760 const ios_base::fmtflags __basefield = __flags & ios_base::basefield;
761 _CharT* __buf = __bufend - 1;
762
763 if (__builtin_expect(__basefield != ios_base::oct &&
764 __basefield != ios_base::hex, true))
765 {
766 // Decimal.
767 do
768 {
769 *__buf-- = __lit[(__v % 10) + __num_base::_S_odigits];
770 __v /= 10;
771 }
772 while (__v != 0);
773 if (__neg)
774 *__buf-- = __lit[__num_base::_S_ominus];
775 else if (__flags & ios_base::showpos)
776 *__buf-- = __lit[__num_base::_S_oplus];
777 }
778 else if (__basefield == ios_base::oct)
779 {
780 // Octal.
781 do
782 {
783 *__buf-- = __lit[(__v & 0x7) + __num_base::_S_odigits];
784 __v >>= 3;
785 }
786 while (__v != 0);
787 if (__showbase)
788 *__buf-- = __lit[__num_base::_S_odigits];
789 }
790 else
791 {
792 // Hex.
793 const bool __uppercase = __flags & ios_base::uppercase;
794 const int __case_offset = __uppercase ? __num_base::_S_oudigits
795 : __num_base::_S_odigits;
796 do
797 {
798 *__buf-- = __lit[(__v & 0xf) + __case_offset];
799 __v >>= 4;
800 }
801 while (__v != 0);
802 if (__showbase)
803 {
804 // 'x' or 'X'
805 *__buf-- = __lit[__num_base::_S_ox + __uppercase];
806 // '0'
807 *__buf-- = __lit[__num_base::_S_odigits];
808 }
809 }
810 return __bufend - __buf - 1;
811 }
812
813 template<typename _CharT, typename _OutIter>
814 void
815 num_put<_CharT, _OutIter>::
816 _M_group_int(const char* __grouping, size_t __grouping_size, _CharT __sep,
817 ios_base& __io, _CharT* __new, _CharT* __cs, int& __len) const
818 {
819 // By itself __add_grouping cannot deal correctly with __cs when
820 // ios::showbase is set and ios_base::oct || ios_base::hex.
821 // Therefore we take care "by hand" of the initial 0, 0x or 0X.
822 // However, remember that the latter do not occur if the number
823 // printed is '0' (__len == 1).
824 streamsize __off = 0;
825 const ios_base::fmtflags __basefield = __io.flags()
826 & ios_base::basefield;
827 if ((__io.flags() & ios_base::showbase) && __len > 1)
828 if (__basefield == ios_base::oct)
829 {
830 __off = 1;
831 __new[0] = __cs[0];
832 }
833 else if (__basefield == ios_base::hex)
834 {
835 __off = 2;
836 __new[0] = __cs[0];
837 __new[1] = __cs[1];
838 }
839 _CharT* __p;
840 __p = std::__add_grouping(__new + __off, __sep, __grouping,
841 __grouping_size, __cs + __off,
842 __cs + __len);
843 __len = __p - __new;
844 }
845
846 template<typename _CharT, typename _OutIter>
847 template<typename _ValueT>
848 _OutIter
849 num_put<_CharT, _OutIter>::
850 _M_insert_int(_OutIter __s, ios_base& __io, _CharT __fill,
851 _ValueT __v) const
852 {
853 typedef typename numpunct<_CharT>::__cache_type __cache_type;
854 __use_cache<__cache_type> __uc;
855 const locale& __loc = __io._M_getloc();
856 const __cache_type* __lc = __uc(__loc);
857 const _CharT* __lit = __lc->_M_atoms_out;
858
859 // Long enough to hold hex, dec, and octal representations.
860 const int __ilen = 4 * sizeof(_ValueT);
861 _CharT* __cs = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
862 * __ilen));
863
864 // [22.2.2.2.2] Stage 1, numeric conversion to character.
865 // Result is returned right-justified in the buffer.
866 int __len;
867 __len = __int_to_char(__cs + __ilen, __v, __lit, __io.flags());
868 __cs += __ilen - __len;
869
870 // Add grouping, if necessary.
871 if (__lc->_M_use_grouping)
872 {
873 // Grouping can add (almost) as many separators as the
874 // number of digits, but no more.
875 _CharT* __cs2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
876 * __len * 2));
877 _M_group_int(__lc->_M_grouping, __lc->_M_grouping_size,
878 __lc->_M_thousands_sep, __io, __cs2, __cs, __len);
879 __cs = __cs2;
880 }
881
882 // Pad.
883 const streamsize __w = __io.width();
884 if (__w > static_cast<streamsize>(__len))
885 {
886 _CharT* __cs3 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
887 * __w));
888 _M_pad(__fill, __w, __io, __cs3, __cs, __len);
889 __cs = __cs3;
890 }
891 __io.width(0);
892
893 // [22.2.2.2.2] Stage 4.
894 // Write resulting, fully-formatted string to output iterator.
895 return std::__write(__s, __cs, __len);
896 }
897
898 template<typename _CharT, typename _OutIter>
899 void
900 num_put<_CharT, _OutIter>::
901 _M_group_float(const char* __grouping, size_t __grouping_size,
902 _CharT __sep, const _CharT* __p, _CharT* __new,
903 _CharT* __cs, int& __len) const
904 {
905 // _GLIBCXX_RESOLVE_LIB_DEFECTS
906 // 282. What types does numpunct grouping refer to?
907 // Add grouping, if necessary.
908 _CharT* __p2;
909 const int __declen = __p ? __p - __cs : __len;
910 __p2 = std::__add_grouping(__new, __sep, __grouping, __grouping_size,
911 __cs, __cs + __declen);
912
913 // Tack on decimal part.
914 int __newlen = __p2 - __new;
915 if (__p)
916 {
917 char_traits<_CharT>::copy(__p2, __p, __len - __declen);
918 __newlen += __len - __declen;
919 }
920 __len = __newlen;
921 }
922
923 // The following code uses snprintf (or sprintf(), when
924 // _GLIBCXX_USE_C99 is not defined) to convert floating point values
925 // for insertion into a stream. An optimization would be to replace
926 // them with code that works directly on a wide buffer and then use
927 // __pad to do the padding. It would be good to replace them anyway
928 // to gain back the efficiency that C++ provides by knowing up front
929 // the type of the values to insert. Also, sprintf is dangerous
930 // since may lead to accidental buffer overruns. This
931 // implementation follows the C++ standard fairly directly as
932 // outlined in 22.2.2.2 [lib.locale.num.put]
933 template<typename _CharT, typename _OutIter>
934 template<typename _ValueT>
935 _OutIter
936 num_put<_CharT, _OutIter>::
937 _M_insert_float(_OutIter __s, ios_base& __io, _CharT __fill, char __mod,
938 _ValueT __v) const
939 {
940 typedef typename numpunct<_CharT>::__cache_type __cache_type;
941 __use_cache<__cache_type> __uc;
942 const locale& __loc = __io._M_getloc();
943 const __cache_type* __lc = __uc(__loc);
944
945 // Note: digits10 is rounded down: add 1 to ensure the maximum
946 // available precision. Then, in general, one more 1 needs to
947 // be added since, when the %{g,G} conversion specifiers are
948 // chosen inside _S_format_float, the precision field is "the
949 // maximum number of significant digits", *not* the "number of
950 // digits to appear after the decimal point", as happens for
951 // %{e,E,f,F} (C99, 7.19.6.1,4).
952 const int __max_digits = numeric_limits<_ValueT>::digits10 + 2;
953
954 // Use default precision if out of range.
955 streamsize __prec = __io.precision();
956 if (__prec > static_cast<streamsize>(__max_digits))
957 __prec = static_cast<streamsize>(__max_digits);
958 else if (__prec < static_cast<streamsize>(0))
959 __prec = static_cast<streamsize>(6);
960
961 // [22.2.2.2.2] Stage 1, numeric conversion to character.
962 int __len;
963 // Long enough for the max format spec.
964 char __fbuf[16];
965
966 #ifdef _GLIBCXX_USE_C99
967 // First try a buffer perhaps big enough (for sure sufficient
968 // for non-ios_base::fixed outputs)
969 int __cs_size = __max_digits * 3;
970 char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
971
972 _S_format_float(__io, __fbuf, __mod);
973 __len = std::__convert_from_v(__cs, __cs_size, __fbuf, __v,
974 _S_get_c_locale(), __prec);
975
976 // If the buffer was not large enough, try again with the correct size.
977 if (__len >= __cs_size)
978 {
979 __cs_size = __len + 1;
980 __cs = static_cast<char*>(__builtin_alloca(__cs_size));
981 __len = std::__convert_from_v(__cs, __cs_size, __fbuf, __v,
982 _S_get_c_locale(), __prec);
983 }
984 #else
985 // Consider the possibility of long ios_base::fixed outputs
986 const bool __fixed = __io.flags() & ios_base::fixed;
987 const int __max_exp = numeric_limits<_ValueT>::max_exponent10;
988
989 // The size of the output string is computed as follows.
990 // ios_base::fixed outputs may need up to __max_exp+1 chars
991 // for the integer part + up to __max_digits chars for the
992 // fractional part + 3 chars for sign, decimal point, '\0'. On
993 // the other hand, for non-fixed outputs __max_digits*3 chars
994 // are largely sufficient.
995 const int __cs_size = __fixed ? __max_exp + __max_digits + 4
996 : __max_digits * 3;
997 char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
998
999 _S_format_float(__io, __fbuf, __mod);
1000 __len = std::__convert_from_v(__cs, 0, __fbuf, __v,
1001 _S_get_c_locale(), __prec);
1002 #endif
1003
1004 // [22.2.2.2.2] Stage 2, convert to char_type, using correct
1005 // numpunct.decimal_point() values for '.' and adding grouping.
1006 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1007
1008 _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
1009 * __len));
1010 __ctype.widen(__cs, __cs + __len, __ws);
1011
1012 // Replace decimal point.
1013 const _CharT __cdec = __ctype.widen('.');
1014 const _CharT __dec = __lc->_M_decimal_point;
1015 const _CharT* __p;
1016 if (__p = char_traits<_CharT>::find(__ws, __len, __cdec))
1017 __ws[__p - __ws] = __dec;
1018
1019 // Add grouping, if necessary.
1020 if (__lc->_M_use_grouping)
1021 {
1022 // Grouping can add (almost) as many separators as the
1023 // number of digits, but no more.
1024 _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
1025 * __len * 2));
1026 _M_group_float(__lc->_M_grouping, __lc->_M_grouping_size,
1027 __lc->_M_thousands_sep, __p, __ws2, __ws, __len);
1028 __ws = __ws2;
1029 }
1030
1031 // Pad.
1032 const streamsize __w = __io.width();
1033 if (__w > static_cast<streamsize>(__len))
1034 {
1035 _CharT* __ws3 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
1036 * __w));
1037 _M_pad(__fill, __w, __io, __ws3, __ws, __len);
1038 __ws = __ws3;
1039 }
1040 __io.width(0);
1041
1042 // [22.2.2.2.2] Stage 4.
1043 // Write resulting, fully-formatted string to output iterator.
1044 return std::__write(__s, __ws, __len);
1045 }
1046
1047 template<typename _CharT, typename _OutIter>
1048 _OutIter
1049 num_put<_CharT, _OutIter>::
1050 do_put(iter_type __s, ios_base& __io, char_type __fill, bool __v) const
1051 {
1052 const ios_base::fmtflags __flags = __io.flags();
1053 if ((__flags & ios_base::boolalpha) == 0)
1054 {
1055 unsigned long __uv = __v;
1056 __s = _M_insert_int(__s, __io, __fill, __uv);
1057 }
1058 else
1059 {
1060 typedef typename numpunct<_CharT>::__cache_type __cache_type;
1061 __use_cache<__cache_type> __uc;
1062 const locale& __loc = __io._M_getloc();
1063 const __cache_type* __lc = __uc(__loc);
1064
1065 const _CharT* __name = __v ? __lc->_M_truename
1066 : __lc->_M_falsename;
1067 int __len = __v ? __lc->_M_truename_size
1068 : __lc->_M_falsename_size;
1069
1070 const streamsize __w = __io.width();
1071 if (__w > static_cast<streamsize>(__len))
1072 {
1073 _CharT* __cs
1074 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
1075 * __w));
1076 _M_pad(__fill, __w, __io, __cs, __name, __len);
1077 __name = __cs;
1078 }
1079 __io.width(0);
1080 __s = std::__write(__s, __name, __len);
1081 }
1082 return __s;
1083 }
1084
1085 template<typename _CharT, typename _OutIter>
1086 _OutIter
1087 num_put<_CharT, _OutIter>::
1088 do_put(iter_type __s, ios_base& __io, char_type __fill, long __v) const
1089 { return _M_insert_int(__s, __io, __fill, __v); }
1090
1091 template<typename _CharT, typename _OutIter>
1092 _OutIter
1093 num_put<_CharT, _OutIter>::
1094 do_put(iter_type __s, ios_base& __io, char_type __fill,
1095 unsigned long __v) const
1096 { return _M_insert_int(__s, __io, __fill, __v); }
1097
1098 #ifdef _GLIBCXX_USE_LONG_LONG
1099 template<typename _CharT, typename _OutIter>
1100 _OutIter
1101 num_put<_CharT, _OutIter>::
1102 do_put(iter_type __s, ios_base& __b, char_type __fill, long long __v) const
1103 { return _M_insert_int(__s, __b, __fill, __v); }
1104
1105 template<typename _CharT, typename _OutIter>
1106 _OutIter
1107 num_put<_CharT, _OutIter>::
1108 do_put(iter_type __s, ios_base& __io, char_type __fill,
1109 unsigned long long __v) const
1110 { return _M_insert_int(__s, __io, __fill, __v); }
1111 #endif
1112
1113 template<typename _CharT, typename _OutIter>
1114 _OutIter
1115 num_put<_CharT, _OutIter>::
1116 do_put(iter_type __s, ios_base& __io, char_type __fill, double __v) const
1117 { return _M_insert_float(__s, __io, __fill, char(), __v); }
1118
1119 template<typename _CharT, typename _OutIter>
1120 _OutIter
1121 num_put<_CharT, _OutIter>::
1122 do_put(iter_type __s, ios_base& __io, char_type __fill,
1123 long double __v) const
1124 { return _M_insert_float(__s, __io, __fill, 'L', __v); }
1125
1126 template<typename _CharT, typename _OutIter>
1127 _OutIter
1128 num_put<_CharT, _OutIter>::
1129 do_put(iter_type __s, ios_base& __io, char_type __fill,
1130 const void* __v) const
1131 {
1132 const ios_base::fmtflags __flags = __io.flags();
1133 const ios_base::fmtflags __fmt = ~(ios_base::showpos
1134 | ios_base::basefield
1135 | ios_base::uppercase
1136 | ios_base::internal);
1137 __io.flags(__flags & __fmt | (ios_base::hex | ios_base::showbase));
1138
1139 __s = _M_insert_int(__s, __io, __fill,
1140 reinterpret_cast<unsigned long>(__v));
1141 __io.flags(__flags);
1142 return __s;
1143 }
1144
1145 template<typename _CharT, bool _Intl>
1146 struct __use_cache<__moneypunct_cache<_CharT, _Intl> >
1147 {
1148 const __moneypunct_cache<_CharT, _Intl>*
1149 operator() (const locale& __loc) const
1150 {
1151 const size_t __i = moneypunct<_CharT, _Intl>::id._M_id();
1152 const locale::facet** __caches = __loc._M_impl->_M_caches;
1153 if (!__caches[__i])
1154 {
1155 __moneypunct_cache<_CharT, _Intl>* __tmp = NULL;
1156 try
1157 {
1158 __tmp = new __moneypunct_cache<_CharT, _Intl>;
1159 __tmp->_M_cache(__loc);
1160 }
1161 catch(...)
1162 {
1163 delete __tmp;
1164 __throw_exception_again;
1165 }
1166 __loc._M_impl->_M_install_cache(__tmp, __i);
1167 }
1168 return static_cast<
1169 const __moneypunct_cache<_CharT, _Intl>*>(__caches[__i]);
1170 }
1171 };
1172
1173 template<typename _CharT, typename _InIter>
1174 template<bool _Intl>
1175 _InIter
1176 money_get<_CharT, _InIter>::
1177 _M_extract(iter_type __beg, iter_type __end, ios_base& __io,
1178 ios_base::iostate& __err, string& __units) const
1179 {
1180 typedef char_traits<_CharT> __traits_type;
1181 typedef typename string_type::size_type size_type;
1182 typedef money_base::part part;
1183 typedef moneypunct<_CharT, _Intl> __moneypunct_type;
1184 typedef typename __moneypunct_type::__cache_type __cache_type;
1185
1186 const locale& __loc = __io._M_getloc();
1187 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1188
1189 __use_cache<__cache_type> __uc;
1190 const __cache_type* __lc = __uc(__loc);
1191 const char_type* __lit = __lc->_M_atoms;
1192
1193 const money_base::pattern __p = __lc->_M_neg_format;
1194
1195 // Deduced sign.
1196 bool __negative = false;
1197 // True for more than one character long sign.
1198 bool __long_sign = false;
1199 // String of grouping info from thousands_sep plucked from __units.
1200 string __grouping_tmp;
1201 if (__lc->_M_use_grouping)
1202 __grouping_tmp.reserve(32);
1203 // Marker for thousands_sep position.
1204 int __sep_pos = 0;
1205 // If input iterator is in a valid state.
1206 bool __testvalid = true;
1207 // Flag marking when a decimal point is found.
1208 bool __testdecfound = false;
1209
1210 // The tentative returned string is stored here.
1211 string __res;
1212 __res.reserve(32);
1213
1214 const char_type* __lit_zero = __lit + _S_zero;
1215 const char_type* __q;
1216 for (int __i = 0; __beg != __end && __i < 4 && __testvalid; ++__i)
1217 {
1218 const part __which = static_cast<part>(__p.field[__i]);
1219 switch (__which)
1220 {
1221 case money_base::symbol:
1222 if (__io.flags() & ios_base::showbase
1223 || __i < 2 || __long_sign
1224 || ((static_cast<part>(__p.field[3]) != money_base::none)
1225 && __i == 2))
1226 {
1227 // According to 22.2.6.1.2, p2, symbol is required
1228 // if (__io.flags() & ios_base::showbase),
1229 // otherwise is optional and consumed only if
1230 // other characters are needed to complete the
1231 // format.
1232 const size_type __len = __lc->_M_curr_symbol_size;
1233 size_type __j = 0;
1234 for (; __beg != __end && __j < __len
1235 && *__beg == __lc->_M_curr_symbol[__j];
1236 ++__beg, ++__j);
1237 // When (__io.flags() & ios_base::showbase)
1238 // symbol is required.
1239 if (__j != __len && (__io.flags() & ios_base::showbase))
1240 __testvalid = false;
1241 }
1242 break;
1243 case money_base::sign:
1244 // Sign might not exist, or be more than one character long.
1245 if (__lc->_M_positive_sign_size
1246 && *__beg == __lc->_M_positive_sign[0])
1247 {
1248 if (__lc->_M_positive_sign_size > 1)
1249 __long_sign = true;
1250 ++__beg;
1251 }
1252 else if (__lc->_M_negative_sign_size
1253 && *__beg == __lc->_M_negative_sign[0])
1254 {
1255 __negative = true;
1256 if (__lc->_M_negative_sign_size > 1)
1257 __long_sign = true;
1258 ++__beg;
1259 }
1260 else if (__lc->_M_positive_sign_size
1261 && !__lc->_M_negative_sign_size)
1262 // "... if no sign is detected, the result is given the sign
1263 // that corresponds to the source of the empty string"
1264 __negative = true;
1265 else if (__lc->_M_positive_sign_size
1266 && __lc->_M_negative_sign_size)
1267 {
1268 // Sign is mandatory.
1269 __testvalid = false;
1270 }
1271 break;
1272 case money_base::value:
1273 // Extract digits, remove and stash away the
1274 // grouping of found thousands separators.
1275 for (; __beg != __end; ++__beg)
1276 if (__q = __traits_type::find(__lit_zero, 10, *__beg))
1277 {
1278 __res += _S_atoms[__q - __lit];
1279 ++__sep_pos;
1280 }
1281 else if (*__beg == __lc->_M_decimal_point && !__testdecfound)
1282 {
1283 // If no grouping chars are seen, no grouping check
1284 // is applied. Therefore __grouping_tmp is adjusted
1285 // only if decimal_point comes after some thousands_sep.
1286 if (__grouping_tmp.size())
1287 __grouping_tmp += static_cast<char>(__sep_pos);
1288 __sep_pos = 0;
1289 __testdecfound = true;
1290 }
1291 else if (__lc->_M_use_grouping
1292 && *__beg == __lc->_M_thousands_sep)
1293 {
1294 if (!__testdecfound)
1295 {
1296 // Mark position for later analysis.
1297 __grouping_tmp += static_cast<char>(__sep_pos);
1298 __sep_pos = 0;
1299 }
1300 else
1301 {
1302 __testvalid = false;
1303 break;
1304 }
1305 }
1306 else
1307 break;
1308 break;
1309 case money_base::space:
1310 case money_base::none:
1311 // Only if not at the end of the pattern.
1312 if (__i != 3)
1313 for (; __beg != __end
1314 && __ctype.is(ctype_base::space, *__beg); ++__beg);
1315 break;
1316 }
1317 }
1318
1319 // Need to get the rest of the sign characters, if they exist.
1320 if (__long_sign)
1321 {
1322 const char_type* __sign = __negative ? __lc->_M_negative_sign
1323 : __lc->_M_positive_sign;
1324 const size_type __len = __negative ? __lc->_M_negative_sign_size
1325 : __lc->_M_positive_sign_size;
1326 size_type __i = 1;
1327 for (; __beg != __end && __i < __len
1328 && *__beg == __sign[__i]; ++__beg, ++__i);
1329
1330 if (__i != __len)
1331 __testvalid = false;
1332 }
1333
1334 if (__testvalid && __res.size())
1335 {
1336 // Strip leading zeros.
1337 if (__res.size() > 1)
1338 {
1339 size_type __first = __res.find_first_not_of(__lit[_S_zero]);
1340 const bool __only_zeros = __first == string_type::npos;
1341 if (__first)
1342 __res.erase(0, __only_zeros ? __res.size() - 1 : __first);
1343 }
1344
1345 // 22.2.6.1.2, p4
1346 if (__negative && __res[0] != __lit[_S_zero])
1347 __res.insert(__res.begin(), __lit[_S_minus]);
1348
1349 // Test for grouping fidelity.
1350 if (__grouping_tmp.size())
1351 {
1352 // Add the ending grouping if a decimal wasn't found.
1353 if (!__testdecfound)
1354 __grouping_tmp += static_cast<char>(__sep_pos);
1355
1356 if (!std::__verify_grouping(__lc->_M_grouping,
1357 __lc->_M_grouping_size,
1358 __grouping_tmp))
1359 __testvalid = false;
1360 }
1361
1362 // Iff not enough digits were supplied after the decimal-point.
1363 if (__testdecfound && __lc->_M_frac_digits > 0
1364 && __sep_pos != __lc->_M_frac_digits)
1365 __testvalid = false;
1366 }
1367 else
1368 __testvalid = false;
1369
1370 // Iff no more characters are available.
1371 if (__beg == __end)
1372 __err |= ios_base::eofbit;
1373
1374 // Iff valid sequence is not recognized.
1375 if (!__testvalid)
1376 __err |= ios_base::failbit;
1377 else
1378 __units.swap(__res);
1379
1380 return __beg;
1381 }
1382
1383 template<typename _CharT, typename _InIter>
1384 _InIter
1385 money_get<_CharT, _InIter>::
1386 do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
1387 ios_base::iostate& __err, long double& __units) const
1388 {
1389 string __str;
1390 if (__intl)
1391 __beg = _M_extract<true>(__beg, __end, __io, __err, __str);
1392 else
1393 __beg = _M_extract<false>(__beg, __end, __io, __err, __str);
1394
1395 if (__str.size())
1396 std::__convert_to_v(__str.c_str(), __units, __err, _S_get_c_locale());
1397
1398 return __beg;
1399 }
1400
1401 template<typename _CharT, typename _InIter>
1402 _InIter
1403 money_get<_CharT, _InIter>::
1404 do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
1405 ios_base::iostate& __err, string_type& __units) const
1406 {
1407 typedef typename string_type::size_type size_type;
1408
1409 const locale& __loc = __io._M_getloc();
1410 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1411
1412 string __str;
1413 const iter_type __ret = __intl ? _M_extract<true>(__beg, __end, __io,
1414 __err, __str)
1415 : _M_extract<false>(__beg, __end, __io,
1416 __err, __str);
1417 const size_type __len = __str.size();
1418 if (__len)
1419 {
1420 _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
1421 * __len));
1422 __ctype.widen(__str.data(), __str.data() + __len, __ws);
1423 __units.assign(__ws, __len);
1424 }
1425
1426 return __ret;
1427 }
1428
1429 template<typename _CharT, typename _OutIter>
1430 template<bool _Intl>
1431 _OutIter
1432 money_put<_CharT, _OutIter>::
1433 _M_insert(iter_type __s, ios_base& __io, char_type __fill,
1434 const string_type& __digits) const
1435 {
1436 typedef typename string_type::size_type size_type;
1437 typedef money_base::part part;
1438 typedef moneypunct<_CharT, _Intl> __moneypunct_type;
1439 typedef typename __moneypunct_type::__cache_type __cache_type;
1440
1441 const locale& __loc = __io._M_getloc();
1442 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1443
1444 __use_cache<__cache_type> __uc;
1445 const __cache_type* __lc = __uc(__loc);
1446 const char_type* __lit = __lc->_M_atoms;
1447
1448 // Determine if negative or positive formats are to be used, and
1449 // discard leading negative_sign if it is present.
1450 const char_type* __beg = __digits.data();
1451 const char_type* __end = __beg + __digits.size();
1452
1453 money_base::pattern __p;
1454 const char_type* __sign;
1455 size_type __sign_size;
1456 if (*__beg != __lit[_S_minus])
1457 {
1458 __p = __lc->_M_pos_format;
1459 __sign = __lc->_M_positive_sign;
1460 __sign_size = __lc->_M_positive_sign_size;
1461 }
1462 else
1463 {
1464 __p = __lc->_M_neg_format;
1465 __sign = __lc->_M_negative_sign;
1466 __sign_size = __lc->_M_negative_sign_size;
1467 ++__beg;
1468 }
1469
1470 // Look for valid numbers in the ctype facet within input digits.
1471 __end = __ctype.scan_not(ctype_base::digit, __beg, __end);
1472 if (__beg != __end)
1473 {
1474 // Assume valid input, and attempt to format.
1475 // Break down input numbers into base components, as follows:
1476 // final_value = grouped units + (decimal point) + (digits)
1477 string_type __value;
1478 size_type __len = __end - __beg;
1479 __value.reserve(2 * __len);
1480
1481 // Add thousands separators to non-decimal digits, per
1482 // grouping rules.
1483 const int __paddec = __lc->_M_frac_digits - __len;
1484 if (__paddec < 0)
1485 {
1486 if (__lc->_M_grouping_size)
1487 {
1488 _CharT* __ws =
1489 static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
1490 * 2 * __len));
1491 _CharT* __ws_end =
1492 std::__add_grouping(__ws, __lc->_M_thousands_sep,
1493 __lc->_M_grouping,
1494 __lc->_M_grouping_size,
1495 __beg, __end - __lc->_M_frac_digits);
1496 __value.assign(__ws, __ws_end - __ws);
1497 }
1498 else
1499 __value.assign(__beg, -__paddec);
1500 }
1501
1502 // Deal with decimal point, decimal digits.
1503 if (__lc->_M_frac_digits > 0)
1504 {
1505 __value += __lc->_M_decimal_point;
1506 if (__paddec <= 0)
1507 __value.append(__end - __lc->_M_frac_digits,
1508 __lc->_M_frac_digits);
1509 else
1510 {
1511 // Have to pad zeros in the decimal position.
1512 __value.append(__paddec, __lit[_S_zero]);
1513 __value.append(__beg, __len);
1514 }
1515 }
1516
1517 // Calculate length of resulting string.
1518 const ios_base::fmtflags __f = __io.flags() & ios_base::adjustfield;
1519 __len = __value.size() + __sign_size;
1520 __len += ((__io.flags() & ios_base::showbase)
1521 ? __lc->_M_curr_symbol_size : 0);
1522
1523 string_type __res;
1524 __res.reserve(2 * __len);
1525
1526 const size_type __width = static_cast<size_type>(__io.width());
1527 const bool __testipad = (__f == ios_base::internal
1528 && __len < __width);
1529 // Fit formatted digits into the required pattern.
1530 for (int __i = 0; __i < 4; ++__i)
1531 {
1532 const part __which = static_cast<part>(__p.field[__i]);
1533 switch (__which)
1534 {
1535 case money_base::symbol:
1536 if (__io.flags() & ios_base::showbase)
1537 __res.append(__lc->_M_curr_symbol,
1538 __lc->_M_curr_symbol_size);
1539 break;
1540 case money_base::sign:
1541 // Sign might not exist, or be more than one
1542 // charater long. In that case, add in the rest
1543 // below.
1544 if (__sign_size)
1545 __res += __sign[0];
1546 break;
1547 case money_base::value:
1548 __res += __value;
1549 break;
1550 case money_base::space:
1551 // At least one space is required, but if internal
1552 // formatting is required, an arbitrary number of
1553 // fill spaces will be necessary.
1554 if (__testipad)
1555 __res.append(__width - __len, __fill);
1556 else
1557 __res += __fill;
1558 break;
1559 case money_base::none:
1560 if (__testipad)
1561 __res.append(__width - __len, __fill);
1562 break;
1563 }
1564 }
1565
1566 // Special case of multi-part sign parts.
1567 if (__sign_size > 1)
1568 __res.append(__sign + 1, __sign_size - 1);
1569
1570 // Pad, if still necessary.
1571 __len = __res.size();
1572 if (__width > __len)
1573 {
1574 if (__f == ios_base::left)
1575 // After.
1576 __res.append(__width - __len, __fill);
1577 else
1578 // Before.
1579 __res.insert(0, __width - __len, __fill);
1580 __len = __width;
1581 }
1582
1583 // Write resulting, fully-formatted string to output iterator.
1584 __s = std::__write(__s, __res.data(), __len);
1585 }
1586 __io.width(0);
1587 return __s;
1588 }
1589
1590 template<typename _CharT, typename _OutIter>
1591 _OutIter
1592 money_put<_CharT, _OutIter>::
1593 do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
1594 long double __units) const
1595 {
1596 const locale __loc = __io.getloc();
1597 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1598 #ifdef _GLIBCXX_USE_C99
1599 // First try a buffer perhaps big enough.
1600 int __cs_size = 64;
1601 char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
1602 // _GLIBCXX_RESOLVE_LIB_DEFECTS
1603 // 328. Bad sprintf format modifier in money_put<>::do_put()
1604 int __len = std::__convert_from_v(__cs, __cs_size, "%.0Lf", __units,
1605 _S_get_c_locale());
1606 // If the buffer was not large enough, try again with the correct size.
1607 if (__len >= __cs_size)
1608 {
1609 __cs_size = __len + 1;
1610 __cs = static_cast<char*>(__builtin_alloca(__cs_size));
1611 __len = std::__convert_from_v(__cs, __cs_size, "%.0Lf", __units,
1612 _S_get_c_locale());
1613 }
1614 #else
1615 // max_exponent10 + 1 for the integer part, + 2 for sign and '\0'.
1616 const int __cs_size = numeric_limits<long double>::max_exponent10 + 3;
1617 char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
1618 int __len = std::__convert_from_v(__cs, 0, "%.0Lf", __units,
1619 _S_get_c_locale());
1620 #endif
1621 _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
1622 * __cs_size));
1623 __ctype.widen(__cs, __cs + __len, __ws);
1624 const string_type __digits(__ws, __len);
1625 return __intl ? _M_insert<true>(__s, __io, __fill, __digits)
1626 : _M_insert<false>(__s, __io, __fill, __digits);
1627 }
1628
1629 template<typename _CharT, typename _OutIter>
1630 _OutIter
1631 money_put<_CharT, _OutIter>::
1632 do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
1633 const string_type& __digits) const
1634 { return __intl ? _M_insert<true>(__s, __io, __fill, __digits)
1635 : _M_insert<false>(__s, __io, __fill, __digits); }
1636
1637 // NB: Not especially useful. Without an ios_base object or some
1638 // kind of locale reference, we are left clawing at the air where
1639 // the side of the mountain used to be...
1640 template<typename _CharT, typename _InIter>
1641 time_base::dateorder
1642 time_get<_CharT, _InIter>::do_date_order() const
1643 { return time_base::no_order; }
1644
1645 // Recursively expand a strftime format string and parse it. Starts w/ %x
1646 // and %X from do_get_time() and do_get_date(), which translate to a more
1647 // specific string, which may contain yet more strings. I.e. %x => %r =>
1648 // %H:%M:%S => extracted characters.
1649 template<typename _CharT, typename _InIter>
1650 void
1651 time_get<_CharT, _InIter>::
1652 _M_extract_via_format(iter_type& __beg, iter_type& __end, ios_base& __io,
1653 ios_base::iostate& __err, tm* __tm,
1654 const _CharT* __format) const
1655 {
1656 const locale __loc = __io.getloc();
1657 const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
1658 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1659 const size_t __len = char_traits<_CharT>::length(__format);
1660
1661 for (size_t __i = 0; __beg != __end && __i < __len && !__err; ++__i)
1662 {
1663 if (__ctype.narrow(__format[__i], 0) == '%')
1664 {
1665 // Verify valid formatting code, attempt to extract.
1666 char __c = __ctype.narrow(__format[++__i], 0);
1667 int __mem = 0;
1668 if (__c == 'E' || __c == 'O')
1669 __c = __ctype.narrow(__format[++__i], 0);
1670 switch (__c)
1671 {
1672 const char* __cs;
1673 _CharT __wcs[10];
1674 case 'a':
1675 // Abbreviated weekday name [tm_wday]
1676 const char_type* __days1[7];
1677 __tp._M_days_abbreviated(__days1);
1678 _M_extract_name(__beg, __end, __tm->tm_wday, __days1, 7,
1679 __ctype, __err);
1680 break;
1681 case 'A':
1682 // Weekday name [tm_wday].
1683 const char_type* __days2[7];
1684 __tp._M_days(__days2);
1685 _M_extract_name(__beg, __end, __tm->tm_wday, __days2, 7,
1686 __ctype, __err);
1687 break;
1688 case 'h':
1689 case 'b':
1690 // Abbreviated month name [tm_mon]
1691 const char_type* __months1[12];
1692 __tp._M_months_abbreviated(__months1);
1693 _M_extract_name(__beg, __end, __tm->tm_mon, __months1, 12,
1694 __ctype, __err);
1695 break;
1696 case 'B':
1697 // Month name [tm_mon].
1698 const char_type* __months2[12];
1699 __tp._M_months(__months2);
1700 _M_extract_name(__beg, __end, __tm->tm_mon, __months2, 12,
1701 __ctype, __err);
1702 break;
1703 case 'c':
1704 // Default time and date representation.
1705 const char_type* __dt[2];
1706 __tp._M_date_time_formats(__dt);
1707 _M_extract_via_format(__beg, __end, __io, __err, __tm,
1708 __dt[0]);
1709 break;
1710 case 'd':
1711 // Day [01, 31]. [tm_mday]
1712 _M_extract_num(__beg, __end, __tm->tm_mday, 1, 31, 2,
1713 __ctype, __err);
1714 break;
1715 case 'e':
1716 // Day [1, 31], with single digits preceded by
1717 // space. [tm_mday]
1718 if (__ctype.is(ctype_base::space, *__beg))
1719 _M_extract_num(++__beg, __end, __tm->tm_mday, 1, 9, 1,
1720 __ctype, __err);
1721 else
1722 _M_extract_num(__beg, __end, __tm->tm_mday, 10, 31, 2,
1723 __ctype, __err);
1724 break;
1725 case 'D':
1726 // Equivalent to %m/%d/%y.[tm_mon, tm_mday, tm_year]
1727 __cs = "%m/%d/%y";
1728 __ctype.widen(__cs, __cs + 9, __wcs);
1729 _M_extract_via_format(__beg, __end, __io, __err, __tm,
1730 __wcs);
1731 break;
1732 case 'H':
1733 // Hour [00, 23]. [tm_hour]
1734 _M_extract_num(__beg, __end, __tm->tm_hour, 0, 23, 2,
1735 __ctype, __err);
1736 break;
1737 case 'I':
1738 // Hour [01, 12]. [tm_hour]
1739 _M_extract_num(__beg, __end, __tm->tm_hour, 1, 12, 2,
1740 __ctype, __err);
1741 break;
1742 case 'm':
1743 // Month [01, 12]. [tm_mon]
1744 _M_extract_num(__beg, __end, __mem, 1, 12, 2, __ctype,
1745 __err);
1746 if (!__err)
1747 __tm->tm_mon = __mem - 1;
1748 break;
1749 case 'M':
1750 // Minute [00, 59]. [tm_min]
1751 _M_extract_num(__beg, __end, __tm->tm_min, 0, 59, 2,
1752 __ctype, __err);
1753 break;
1754 case 'n':
1755 if (__ctype.narrow(*__beg, 0) == '\n')
1756 ++__beg;
1757 else
1758 __err |= ios_base::failbit;
1759 break;
1760 case 'R':
1761 // Equivalent to (%H:%M).
1762 __cs = "%H:%M";
1763 __ctype.widen(__cs, __cs + 6, __wcs);
1764 _M_extract_via_format(__beg, __end, __io, __err, __tm,
1765 __wcs);
1766 break;
1767 case 'S':
1768 // Seconds.
1769 _M_extract_num(__beg, __end, __tm->tm_sec, 0, 59, 2,
1770 __ctype, __err);
1771 break;
1772 case 't':
1773 if (__ctype.narrow(*__beg, 0) == '\t')
1774 ++__beg;
1775 else
1776 __err |= ios_base::failbit;
1777 break;
1778 case 'T':
1779 // Equivalent to (%H:%M:%S).
1780 __cs = "%H:%M:%S";
1781 __ctype.widen(__cs, __cs + 9, __wcs);
1782 _M_extract_via_format(__beg, __end, __io, __err, __tm,
1783 __wcs);
1784 break;
1785 case 'x':
1786 // Locale's date.
1787 const char_type* __dates[2];
1788 __tp._M_date_formats(__dates);
1789 _M_extract_via_format(__beg, __end, __io, __err, __tm,
1790 __dates[0]);
1791 break;
1792 case 'X':
1793 // Locale's time.
1794 const char_type* __times[2];
1795 __tp._M_time_formats(__times);
1796 _M_extract_via_format(__beg, __end, __io, __err, __tm,
1797 __times[0]);
1798 break;
1799 case 'y':
1800 case 'C': // C99
1801 // Two digit year. [tm_year]
1802 _M_extract_num(__beg, __end, __tm->tm_year, 0, 99, 2,
1803 __ctype, __err);
1804 break;
1805 case 'Y':
1806 // Year [1900). [tm_year]
1807 _M_extract_num(__beg, __end, __mem, 0, 9999, 4,
1808 __ctype, __err);
1809 if (!__err)
1810 __tm->tm_year = __mem - 1900;
1811 break;
1812 case 'Z':
1813 // Timezone info.
1814 if (__ctype.is(ctype_base::upper, *__beg))
1815 {
1816 int __tmp;
1817 _M_extract_name(__beg, __end, __tmp,
1818 __timepunct_cache<_CharT>::_S_timezones,
1819 14, __ctype, __err);
1820
1821 // GMT requires special effort.
1822 if (__beg != __end && !__err && __tmp == 0
1823 && (*__beg == __ctype.widen('-')
1824 || *__beg == __ctype.widen('+')))
1825 {
1826 _M_extract_num(__beg, __end, __tmp, 0, 23, 2,
1827 __ctype, __err);
1828 _M_extract_num(__beg, __end, __tmp, 0, 59, 2,
1829 __ctype, __err);
1830 }
1831 }
1832 else
1833 __err |= ios_base::failbit;
1834 break;
1835 default:
1836 // Not recognized.
1837 __err |= ios_base::failbit;
1838 }
1839 }
1840 else
1841 {
1842 // Verify format and input match, extract and discard.
1843 if (__format[__i] == *__beg)
1844 ++__beg;
1845 else
1846 __err |= ios_base::failbit;
1847 }
1848 }
1849 }
1850
1851 template<typename _CharT, typename _InIter>
1852 void
1853 time_get<_CharT, _InIter>::
1854 _M_extract_num(iter_type& __beg, iter_type& __end, int& __member,
1855 int __min, int __max, size_t __len,
1856 const ctype<_CharT>& __ctype,
1857 ios_base::iostate& __err) const
1858 {
1859 // As-is works for __len = 1, 2, 4, the values actually used.
1860 int __mult = __len == 2 ? 10 : (__len == 4 ? 1000 : 1);
1861
1862 ++__min;
1863 size_t __i = 0;
1864 int __value = 0;
1865 for (; __beg != __end && __i < __len; ++__beg, ++__i)
1866 {
1867 const char __c = __ctype.narrow(*__beg, '*');
1868 if (__c >= '0' && __c <= '9')
1869 {
1870 __value = __value * 10 + (__c - '0');
1871 const int __valuec = __value * __mult;
1872 if (__valuec > __max || __valuec + __mult < __min)
1873 break;
1874 __mult /= 10;
1875 }
1876 else
1877 break;
1878 }
1879 if (__i == __len)
1880 __member = __value;
1881 else
1882 __err |= ios_base::failbit;
1883 }
1884
1885 // Assumptions:
1886 // All elements in __names are unique.
1887 template<typename _CharT, typename _InIter>
1888 void
1889 time_get<_CharT, _InIter>::
1890 _M_extract_name(iter_type& __beg, iter_type& __end, int& __member,
1891 const _CharT** __names, size_t __indexlen,
1892 const ctype<_CharT>& __ctype,
1893 ios_base::iostate& __err) const
1894 {
1895 typedef char_traits<_CharT> __traits_type;
1896 int* __matches = static_cast<int*>(__builtin_alloca(sizeof(int)
1897 * __indexlen));
1898 size_t __nmatches = 0;
1899 size_t __pos = 0;
1900 bool __testvalid = true;
1901 const char_type* __name;
1902
1903 // Look for initial matches.
1904 // NB: Some of the locale data is in the form of all lowercase
1905 // names, and some is in the form of initially-capitalized
1906 // names. Look for both.
1907 if (__beg != __end)
1908 {
1909 const char_type __c = *__beg;
1910 for (size_t __i1 = 0; __i1 < __indexlen; ++__i1)
1911 if (__c == __names[__i1][0]
1912 || __c == __ctype.toupper(__names[__i1][0]))
1913 __matches[__nmatches++] = __i1;
1914 }
1915
1916 while (__nmatches > 1)
1917 {
1918 // Find smallest matching string.
1919 size_t __minlen = 10;
1920 for (size_t __i2 = 0; __i2 < __nmatches; ++__i2)
1921 __minlen = std::min(__minlen,
1922 __traits_type::length(__names[__matches[__i2]]));
1923 ++__beg;
1924 if (__pos < __minlen && __beg != __end)
1925 {
1926 ++__pos;
1927 for (size_t __i3 = 0; __i3 < __nmatches; ++__i3)
1928 {
1929 __name = __names[__matches[__i3]];
1930 if (__name[__pos] != *__beg)
1931 __matches[__i3] = __matches[--__nmatches];
1932 }
1933 }
1934 else
1935 break;
1936 }
1937
1938 if (__nmatches == 1)
1939 {
1940 // If there was only one match, the first compare is redundant.
1941 if (__pos == 0)
1942 {
1943 ++__pos;
1944 ++__beg;
1945 }
1946
1947 // Make sure found name is completely extracted.
1948 __name = __names[__matches[0]];
1949 const size_t __len = __traits_type::length(__name);
1950 while (__pos < __len && __beg != __end && __name[__pos] == *__beg)
1951 ++__beg, ++__pos;
1952
1953 if (__len == __pos)
1954 __member = __matches[0];
1955 else
1956 __testvalid = false;
1957 }
1958 else
1959 __testvalid = false;
1960 if (!__testvalid)
1961 __err |= ios_base::failbit;
1962 }
1963
1964 template<typename _CharT, typename _InIter>
1965 _InIter
1966 time_get<_CharT, _InIter>::
1967 do_get_time(iter_type __beg, iter_type __end, ios_base& __io,
1968 ios_base::iostate& __err, tm* __tm) const
1969 {
1970 _CharT __wcs[3];
1971 const char* __cs = "%X";
1972 const locale __loc = __io.getloc();
1973 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
1974 __ctype.widen(__cs, __cs + 3, __wcs);
1975 _M_extract_via_format(__beg, __end, __io, __err, __tm, __wcs);
1976 if (__beg == __end)
1977 __err |= ios_base::eofbit;
1978 return __beg;
1979 }
1980
1981 template<typename _CharT, typename _InIter>
1982 _InIter
1983 time_get<_CharT, _InIter>::
1984 do_get_date(iter_type __beg, iter_type __end, ios_base& __io,
1985 ios_base::iostate& __err, tm* __tm) const
1986 {
1987 _CharT __wcs[3];
1988 const char* __cs = "%x";
1989 const locale __loc = __io.getloc();
1990 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
1991 __ctype.widen(__cs, __cs + 3, __wcs);
1992 _M_extract_via_format(__beg, __end, __io, __err, __tm, __wcs);
1993 if (__beg == __end)
1994 __err |= ios_base::eofbit;
1995 return __beg;
1996 }
1997
1998 template<typename _CharT, typename _InIter>
1999 _InIter
2000 time_get<_CharT, _InIter>::
2001 do_get_weekday(iter_type __beg, iter_type __end, ios_base& __io,
2002 ios_base::iostate& __err, tm* __tm) const
2003 {
2004 typedef char_traits<_CharT> __traits_type;
2005 const locale __loc = __io.getloc();
2006 const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
2007 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
2008 const char_type* __days[7];
2009 __tp._M_days_abbreviated(__days);
2010 int __tmpwday;
2011 _M_extract_name(__beg, __end, __tmpwday, __days, 7, __ctype, __err);
2012
2013 // Check to see if non-abbreviated name exists, and extract.
2014 // NB: Assumes both _M_days and _M_days_abbreviated organized in
2015 // exact same order, first to last, such that the resulting
2016 // __days array with the same index points to a day, and that
2017 // day's abbreviated form.
2018 // NB: Also assumes that an abbreviated name is a subset of the name.
2019 if (!__err)
2020 {
2021 size_t __pos = __traits_type::length(__days[__tmpwday]);
2022 __tp._M_days(__days);
2023 const char_type* __name = __days[__tmpwday];
2024 if (__name[__pos] == *__beg)
2025 {
2026 // Extract the rest of it.
2027 const size_t __len = __traits_type::length(__name);
2028 while (__pos < __len && __beg != __end
2029 && __name[__pos] == *__beg)
2030 ++__beg, ++__pos;
2031 if (__len != __pos)
2032 __err |= ios_base::failbit;
2033 }
2034 if (!__err)
2035 __tm->tm_wday = __tmpwday;
2036 }
2037 if (__beg == __end)
2038 __err |= ios_base::eofbit;
2039 return __beg;
2040 }
2041
2042 template<typename _CharT, typename _InIter>
2043 _InIter
2044 time_get<_CharT, _InIter>::
2045 do_get_monthname(iter_type __beg, iter_type __end,
2046 ios_base& __io, ios_base::iostate& __err, tm* __tm) const
2047 {
2048 typedef char_traits<_CharT> __traits_type;
2049 const locale __loc = __io.getloc();
2050 const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
2051 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
2052 const char_type* __months[12];
2053 __tp._M_months_abbreviated(__months);
2054 int __tmpmon;
2055 _M_extract_name(__beg, __end, __tmpmon, __months, 12, __ctype, __err);
2056
2057 // Check to see if non-abbreviated name exists, and extract.
2058 // NB: Assumes both _M_months and _M_months_abbreviated organized in
2059 // exact same order, first to last, such that the resulting
2060 // __months array with the same index points to a month, and that
2061 // month's abbreviated form.
2062 // NB: Also assumes that an abbreviated name is a subset of the name.
2063 if (!__err)
2064 {
2065 size_t __pos = __traits_type::length(__months[__tmpmon]);
2066 __tp._M_months(__months);
2067 const char_type* __name = __months[__tmpmon];
2068 if (__name[__pos] == *__beg)
2069 {
2070 // Extract the rest of it.
2071 const size_t __len = __traits_type::length(__name);
2072 while (__pos < __len && __beg != __end
2073 && __name[__pos] == *__beg)
2074 ++__beg, ++__pos;
2075 if (__len != __pos)
2076 __err |= ios_base::failbit;
2077 }
2078 if (!__err)
2079 __tm->tm_mon = __tmpmon;
2080 }
2081
2082 if (__beg == __end)
2083 __err |= ios_base::eofbit;
2084 return __beg;
2085 }
2086
2087 template<typename _CharT, typename _InIter>
2088 _InIter
2089 time_get<_CharT, _InIter>::
2090 do_get_year(iter_type __beg, iter_type __end, ios_base& __io,
2091 ios_base::iostate& __err, tm* __tm) const
2092 {
2093 const locale __loc = __io.getloc();
2094 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
2095
2096 size_t __i = 0;
2097 int __value = 0;
2098 for (; __beg != __end && __i < 4; ++__beg, ++__i)
2099 {
2100 const char __c = __ctype.narrow(*__beg, '*');
2101 if (__c >= '0' && __c <= '9')
2102 __value = __value * 10 + (__c - '0');
2103 else
2104 break;
2105 }
2106 if (__i == 2 || __i == 4)
2107 __tm->tm_year = __i == 2 ? __value : __value - 1900;
2108 else
2109 __err |= ios_base::failbit;
2110 if (__beg == __end)
2111 __err |= ios_base::eofbit;
2112 return __beg;
2113 }
2114
2115 template<typename _CharT, typename _OutIter>
2116 _OutIter
2117 time_put<_CharT, _OutIter>::
2118 put(iter_type __s, ios_base& __io, char_type __fill, const tm* __tm,
2119 const _CharT* __beg, const _CharT* __end) const
2120 {
2121 const locale __loc = __io.getloc();
2122 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
2123 for (; __beg != __end; ++__beg)
2124 if (__ctype.narrow(*__beg, 0) != '%')
2125 {
2126 *__s = *__beg;
2127 ++__s;
2128 }
2129 else if (++__beg != __end)
2130 {
2131 char __format;
2132 char __mod = 0;
2133 const char __c = __ctype.narrow(*__beg, 0);
2134 if (__c != 'E' && __c != 'O')
2135 __format = __c;
2136 else if (++__beg != __end)
2137 {
2138 __mod = __c;
2139 __format = __ctype.narrow(*__beg, 0);
2140 }
2141 else
2142 break;
2143 __s = this->do_put(__s, __io, __fill, __tm,
2144 __format, __mod);
2145 }
2146 else
2147 break;
2148 return __s;
2149 }
2150
2151 template<typename _CharT, typename _OutIter>
2152 _OutIter
2153 time_put<_CharT, _OutIter>::
2154 do_put(iter_type __s, ios_base& __io, char_type, const tm* __tm,
2155 char __format, char __mod) const
2156 {
2157 const locale __loc = __io.getloc();
2158 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
2159 __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc);
2160
2161 // NB: This size is arbitrary. Should this be a data member,
2162 // initialized at construction?
2163 const size_t __maxlen = 64;
2164 char_type* __res =
2165 static_cast<char_type*>(__builtin_alloca(sizeof(char_type)
2166 * __maxlen));
2167
2168 // NB: In IEE 1003.1-200x, and perhaps other locale models, it
2169 // is possible that the format character will be longer than one
2170 // character. Possibilities include 'E' or 'O' followed by a
2171 // format character: if __mod is not the default argument, assume
2172 // it's a valid modifier.
2173 char_type __fmt[4];
2174 __fmt[0] = __ctype.widen('%');
2175 if (!__mod)
2176 {
2177 __fmt[1] = __format;
2178 __fmt[2] = char_type();
2179 }
2180 else
2181 {
2182 __fmt[1] = __mod;
2183 __fmt[2] = __format;
2184 __fmt[3] = char_type();
2185 }
2186
2187 __tp._M_put(__res, __maxlen, __fmt, __tm);
2188
2189 // Write resulting, fully-formatted string to output iterator.
2190 return std::__write(__s, __res, char_traits<char_type>::length(__res));
2191 }
2192
2193
2194 // Generic version does nothing.
2195 template<typename _CharT>
2196 int
2197 collate<_CharT>::_M_compare(const _CharT*, const _CharT*) const
2198 { return 0; }
2199
2200 // Generic version does nothing.
2201 template<typename _CharT>
2202 size_t
2203 collate<_CharT>::_M_transform(_CharT*, const _CharT*, size_t) const
2204 { return 0; }
2205
2206 template<typename _CharT>
2207 int
2208 collate<_CharT>::
2209 do_compare(const _CharT* __lo1, const _CharT* __hi1,
2210 const _CharT* __lo2, const _CharT* __hi2) const
2211 {
2212 // strcoll assumes zero-terminated strings so we make a copy
2213 // and then put a zero at the end.
2214 const string_type __one(__lo1, __hi1);
2215 const string_type __two(__lo2, __hi2);
2216
2217 const _CharT* __p = __one.c_str();
2218 const _CharT* __pend = __one.data() + __one.length();
2219 const _CharT* __q = __two.c_str();
2220 const _CharT* __qend = __two.data() + __two.length();
2221
2222 // strcoll stops when it sees a nul character so we break
2223 // the strings into zero-terminated substrings and pass those
2224 // to strcoll.
2225 for (;;)
2226 {
2227 const int __res = _M_compare(__p, __q);
2228 if (__res)
2229 return __res;
2230
2231 __p += char_traits<_CharT>::length(__p);
2232 __q += char_traits<_CharT>::length(__q);
2233 if (__p == __pend && __q == __qend)
2234 return 0;
2235 else if (__p == __pend)
2236 return -1;
2237 else if (__q == __qend)
2238 return 1;
2239
2240 __p++;
2241 __q++;
2242 }
2243 }
2244
2245 template<typename _CharT>
2246 typename collate<_CharT>::string_type
2247 collate<_CharT>::
2248 do_transform(const _CharT* __lo, const _CharT* __hi) const
2249 {
2250 // strxfrm assumes zero-terminated strings so we make a copy
2251 string_type __str(__lo, __hi);
2252
2253 const _CharT* __p = __str.c_str();
2254 const _CharT* __pend = __str.data() + __str.length();
2255
2256 size_t __len = (__hi - __lo) * 2;
2257
2258 string_type __ret;
2259
2260 // strxfrm stops when it sees a nul character so we break
2261 // the string into zero-terminated substrings and pass those
2262 // to strxfrm.
2263 for (;;)
2264 {
2265 // First try a buffer perhaps big enough.
2266 _CharT* __c =
2267 static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __len));
2268 size_t __res = _M_transform(__c, __p, __len);
2269 // If the buffer was not large enough, try again with the
2270 // correct size.
2271 if (__res >= __len)
2272 {
2273 __len = __res + 1;
2274 __c = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
2275 * __len));
2276 __res = _M_transform(__c, __p, __res + 1);
2277 }
2278
2279 __ret.append(__c, __res);
2280 __p += char_traits<_CharT>::length(__p);
2281 if (__p == __pend)
2282 return __ret;
2283
2284 __p++;
2285 __ret.push_back(_CharT());
2286 }
2287 }
2288
2289 template<typename _CharT>
2290 long
2291 collate<_CharT>::
2292 do_hash(const _CharT* __lo, const _CharT* __hi) const
2293 {
2294 unsigned long __val = 0;
2295 for (; __lo < __hi; ++__lo)
2296 __val = *__lo + ((__val << 7) |
2297 (__val >> (numeric_limits<unsigned long>::digits - 7)));
2298 return static_cast<long>(__val);
2299 }
2300
2301 // Construct correctly padded string, as per 22.2.2.2.2
2302 // Assumes
2303 // __newlen > __oldlen
2304 // __news is allocated for __newlen size
2305 // Used by both num_put and ostream inserters: if __num,
2306 // internal-adjusted objects are padded according to the rules below
2307 // concerning 0[xX] and +-, otherwise, exactly as right-adjusted
2308 // ones are.
2309
2310 // NB: Of the two parameters, _CharT can be deduced from the
2311 // function arguments. The other (_Traits) has to be explicitly specified.
2312 template<typename _CharT, typename _Traits>
2313 void
2314 __pad<_CharT, _Traits>::_S_pad(ios_base& __io, _CharT __fill,
2315 _CharT* __news, const _CharT* __olds,
2316 const streamsize __newlen,
2317 const streamsize __oldlen, const bool __num)
2318 {
2319 const size_t __plen = static_cast<size_t>(__newlen - __oldlen);
2320 const ios_base::fmtflags __adjust = __io.flags() & ios_base::adjustfield;
2321
2322 // Padding last.
2323 if (__adjust == ios_base::left)
2324 {
2325 _Traits::copy(__news, const_cast<_CharT*>(__olds), __oldlen);
2326 _Traits::assign(__news + __oldlen, __plen, __fill);
2327 return;
2328 }
2329
2330 size_t __mod = 0;
2331 if (__adjust == ios_base::internal && __num)
2332 {
2333 // Pad after the sign, if there is one.
2334 // Pad after 0[xX], if there is one.
2335 // Who came up with these rules, anyway? Jeeze.
2336 const locale& __loc = __io._M_getloc();
2337 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
2338
2339 const bool __testsign = _Traits::eq(__ctype.widen('-'), __olds[0])
2340 || _Traits::eq(__ctype.widen('+'), __olds[0]);
2341 const bool __testhex = (_Traits::eq(__ctype.widen('0'), __olds[0])
2342 && __oldlen > 1
2343 && (_Traits::eq(__ctype.widen('x'), __olds[1])
2344 || _Traits::eq(__ctype.widen('X'),
2345 __olds[1])));
2346 if (__testhex)
2347 {
2348 __news[0] = __olds[0];
2349 __news[1] = __olds[1];
2350 __mod = 2;
2351 __news += 2;
2352 }
2353 else if (__testsign)
2354 {
2355 __news[0] = __olds[0];
2356 __mod = 1;
2357 ++__news;
2358 }
2359 // else Padding first.
2360 }
2361 _Traits::assign(__news, __plen, __fill);
2362 _Traits::copy(__news + __plen, const_cast<_CharT*>(__olds + __mod),
2363 __oldlen - __mod);
2364 }
2365
2366 bool
2367 __verify_grouping(const char* __grouping, size_t __grouping_size,
2368 const string& __grouping_tmp)
2369 {
2370 const size_t __n = __grouping_tmp.size() - 1;
2371 const size_t __min = std::min(__n, __grouping_size - 1);
2372 size_t __i = __n;
2373 bool __test = true;
2374
2375 // Parsed number groupings have to match the
2376 // numpunct::grouping string exactly, starting at the
2377 // right-most point of the parsed sequence of elements ...
2378 for (size_t __j = 0; __j < __min && __test; --__i, ++__j)
2379 __test = __grouping_tmp[__i] == __grouping[__j];
2380 for (; __i && __test; --__i)
2381 __test = __grouping_tmp[__i] == __grouping[__min];
2382 // ... but the last parsed grouping can be <= numpunct
2383 // grouping.
2384 __test &= __grouping_tmp[0] <= __grouping[__min];
2385 return __test;
2386 }
2387
2388 template<typename _CharT>
2389 _CharT*
2390 __add_grouping(_CharT* __s, _CharT __sep,
2391 const char* __gbeg, size_t __gsize,
2392 const _CharT* __first, const _CharT* __last)
2393 {
2394 if (__last - __first > *__gbeg)
2395 {
2396 const bool __bump = __gsize != 1;
2397 __s = std::__add_grouping(__s, __sep, __gbeg + __bump,
2398 __gsize - __bump, __first,
2399 __last - *__gbeg);
2400 __first = __last - *__gbeg;
2401 *__s++ = __sep;
2402 }
2403 do
2404 *__s++ = *__first++;
2405 while (__first != __last);
2406 return __s;
2407 }
2408
2409 // Inhibit implicit instantiations for required instantiations,
2410 // which are defined via explicit instantiations elsewhere.
2411 // NB: This syntax is a GNU extension.
2412 #if _GLIBCXX_EXTERN_TEMPLATE
2413 extern template class moneypunct<char, false>;
2414 extern template class moneypunct<char, true>;
2415 extern template class moneypunct_byname<char, false>;
2416 extern template class moneypunct_byname<char, true>;
2417 extern template class money_get<char>;
2418 extern template class money_put<char>;
2419 extern template class numpunct<char>;
2420 extern template class numpunct_byname<char>;
2421 extern template class num_get<char>;
2422 extern template class num_put<char>;
2423 extern template class __timepunct<char>;
2424 extern template class time_put<char>;
2425 extern template class time_put_byname<char>;
2426 extern template class time_get<char>;
2427 extern template class time_get_byname<char>;
2428 extern template class messages<char>;
2429 extern template class messages_byname<char>;
2430 extern template class ctype_byname<char>;
2431 extern template class codecvt_byname<char, char, mbstate_t>;
2432 extern template class collate<char>;
2433 extern template class collate_byname<char>;
2434
2435 extern template
2436 const codecvt<char, char, mbstate_t>&
2437 use_facet<codecvt<char, char, mbstate_t> >(const locale&);
2438
2439 extern template
2440 const collate<char>&
2441 use_facet<collate<char> >(const locale&);
2442
2443 extern template
2444 const numpunct<char>&
2445 use_facet<numpunct<char> >(const locale&);
2446
2447 extern template
2448 const num_put<char>&
2449 use_facet<num_put<char> >(const locale&);
2450
2451 extern template
2452 const num_get<char>&
2453 use_facet<num_get<char> >(const locale&);
2454
2455 extern template
2456 const moneypunct<char, true>&
2457 use_facet<moneypunct<char, true> >(const locale&);
2458
2459 extern template
2460 const moneypunct<char, false>&
2461 use_facet<moneypunct<char, false> >(const locale&);
2462
2463 extern template
2464 const money_put<char>&
2465 use_facet<money_put<char> >(const locale&);
2466
2467 extern template
2468 const money_get<char>&
2469 use_facet<money_get<char> >(const locale&);
2470
2471 extern template
2472 const __timepunct<char>&
2473 use_facet<__timepunct<char> >(const locale&);
2474
2475 extern template
2476 const time_put<char>&
2477 use_facet<time_put<char> >(const locale&);
2478
2479 extern template
2480 const time_get<char>&
2481 use_facet<time_get<char> >(const locale&);
2482
2483 extern template
2484 const messages<char>&
2485 use_facet<messages<char> >(const locale&);
2486
2487 extern template
2488 bool
2489 has_facet<ctype<char> >(const locale&);
2490
2491 extern template
2492 bool
2493 has_facet<codecvt<char, char, mbstate_t> >(const locale&);
2494
2495 extern template
2496 bool
2497 has_facet<collate<char> >(const locale&);
2498
2499 extern template
2500 bool
2501 has_facet<numpunct<char> >(const locale&);
2502
2503 extern template
2504 bool
2505 has_facet<num_put<char> >(const locale&);
2506
2507 extern template
2508 bool
2509 has_facet<num_get<char> >(const locale&);
2510
2511 extern template
2512 bool
2513 has_facet<moneypunct<char> >(const locale&);
2514
2515 extern template
2516 bool
2517 has_facet<money_put<char> >(const locale&);
2518
2519 extern template
2520 bool
2521 has_facet<money_get<char> >(const locale&);
2522
2523 extern template
2524 bool
2525 has_facet<__timepunct<char> >(const locale&);
2526
2527 extern template
2528 bool
2529 has_facet<time_put<char> >(const locale&);
2530
2531 extern template
2532 bool
2533 has_facet<time_get<char> >(const locale&);
2534
2535 extern template
2536 bool
2537 has_facet<messages<char> >(const locale&);
2538
2539 #ifdef _GLIBCXX_USE_WCHAR_T
2540 extern template class moneypunct<wchar_t, false>;
2541 extern template class moneypunct<wchar_t, true>;
2542 extern template class moneypunct_byname<wchar_t, false>;
2543 extern template class moneypunct_byname<wchar_t, true>;
2544 extern template class money_get<wchar_t>;
2545 extern template class money_put<wchar_t>;
2546 extern template class numpunct<wchar_t>;
2547 extern template class numpunct_byname<wchar_t>;
2548 extern template class num_get<wchar_t>;
2549 extern template class num_put<wchar_t>;
2550 extern template class __timepunct<wchar_t>;
2551 extern template class time_put<wchar_t>;
2552 extern template class time_put_byname<wchar_t>;
2553 extern template class time_get<wchar_t>;
2554 extern template class time_get_byname<wchar_t>;
2555 extern template class messages<wchar_t>;
2556 extern template class messages_byname<wchar_t>;
2557 extern template class ctype_byname<wchar_t>;
2558 extern template class codecvt_byname<wchar_t, char, mbstate_t>;
2559 extern template class collate<wchar_t>;
2560 extern template class collate_byname<wchar_t>;
2561
2562 extern template
2563 const codecvt<wchar_t, char, mbstate_t>&
2564 use_facet<codecvt<wchar_t, char, mbstate_t> >(locale const&);
2565
2566 extern template
2567 const collate<wchar_t>&
2568 use_facet<collate<wchar_t> >(const locale&);
2569
2570 extern template
2571 const numpunct<wchar_t>&
2572 use_facet<numpunct<wchar_t> >(const locale&);
2573
2574 extern template
2575 const num_put<wchar_t>&
2576 use_facet<num_put<wchar_t> >(const locale&);
2577
2578 extern template
2579 const num_get<wchar_t>&
2580 use_facet<num_get<wchar_t> >(const locale&);
2581
2582 extern template
2583 const moneypunct<wchar_t, true>&
2584 use_facet<moneypunct<wchar_t, true> >(const locale&);
2585
2586 extern template
2587 const moneypunct<wchar_t, false>&
2588 use_facet<moneypunct<wchar_t, false> >(const locale&);
2589
2590 extern template
2591 const money_put<wchar_t>&
2592 use_facet<money_put<wchar_t> >(const locale&);
2593
2594 extern template
2595 const money_get<wchar_t>&
2596 use_facet<money_get<wchar_t> >(const locale&);
2597
2598 extern template
2599 const __timepunct<wchar_t>&
2600 use_facet<__timepunct<wchar_t> >(const locale&);
2601
2602 extern template
2603 const time_put<wchar_t>&
2604 use_facet<time_put<wchar_t> >(const locale&);
2605
2606 extern template
2607 const time_get<wchar_t>&
2608 use_facet<time_get<wchar_t> >(const locale&);
2609
2610 extern template
2611 const messages<wchar_t>&
2612 use_facet<messages<wchar_t> >(const locale&);
2613
2614 extern template
2615 bool
2616 has_facet<ctype<wchar_t> >(const locale&);
2617
2618 extern template
2619 bool
2620 has_facet<codecvt<wchar_t, char, mbstate_t> >(const locale&);
2621
2622 extern template
2623 bool
2624 has_facet<collate<wchar_t> >(const locale&);
2625
2626 extern template
2627 bool
2628 has_facet<numpunct<wchar_t> >(const locale&);
2629
2630 extern template
2631 bool
2632 has_facet<num_put<wchar_t> >(const locale&);
2633
2634 extern template
2635 bool
2636 has_facet<num_get<wchar_t> >(const locale&);
2637
2638 extern template
2639 bool
2640 has_facet<moneypunct<wchar_t> >(const locale&);
2641
2642 extern template
2643 bool
2644 has_facet<money_put<wchar_t> >(const locale&);
2645
2646 extern template
2647 bool
2648 has_facet<money_get<wchar_t> >(const locale&);
2649
2650 extern template
2651 bool
2652 has_facet<__timepunct<wchar_t> >(const locale&);
2653
2654 extern template
2655 bool
2656 has_facet<time_put<wchar_t> >(const locale&);
2657
2658 extern template
2659 bool
2660 has_facet<time_get<wchar_t> >(const locale&);
2661
2662 extern template
2663 bool
2664 has_facet<messages<wchar_t> >(const locale&);
2665 #endif
2666 #endif
2667 } // namespace std
2668
2669 #endif