OSDN Git Service

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