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