OSDN Git Service

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