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