OSDN Git Service

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