OSDN Git Service

2001-07-02 Benjamin Kosnik <bkoz@redhat.com>
[pf3gnuchains/gcc-fork.git] / libstdc++-v3 / include / bits / locale_facets.tcc
1 // Locale support -*- C++ -*-
2
3 // Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
4 //
5 // This file is part of the GNU ISO C++ Library.  This library is free
6 // software; you can redistribute it and/or modify it under the
7 // terms of the GNU General Public License as published by the
8 // Free Software Foundation; either version 2, or (at your option)
9 // any later version.
10
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 // GNU General Public License for more details.
15
16 // You should have received a copy of the GNU General Public License along
17 // with this library; see the file COPYING.  If not, write to the Free
18 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
19 // USA.
20
21 // As a special exception, you may use this file as part of a free software
22 // library without restriction.  Specifically, if other files instantiate
23 // templates or use macros or inline functions from this file, or you compile
24 // this file and link it with other files to produce an executable, this
25 // file does not by itself cause the resulting executable to be covered by
26 // the GNU General Public License.  This exception does not however
27 // invalidate any other reasons why the executable file might be covered by
28 // the GNU General Public License.
29
30 // Warning: this file is not meant for user inclusion.  Use <locale>.
31
32 #ifndef _CPP_BITS_LOCFACETS_TCC
33 #define _CPP_BITS_LOCFACETS_TCC 1
34
35 #include <bits/std_cerrno.h>
36 #include <bits/std_clocale.h>   // For localeconv
37 #include <bits/std_cstdlib.h>   // For strof, strtold
38 #include <bits/std_limits.h>    // For numeric_limits
39 #include <bits/std_memory.h>    // For auto_ptr
40 #include <bits/streambuf_iterator.h>     // For streambuf_iterators
41 #include <bits/std_cctype.h>    // For isspace
42 #include <typeinfo>             // For bad_cast
43 #include <bits/std_vector.h>    
44
45 namespace std
46 {
47   template<typename _Facet>
48     locale
49     locale::combine(const locale& __other)
50     {
51       _Impl* __tmp = new _Impl(*_M_impl, 0);
52       __tmp->_M_replace_facet(__other._M_impl, &_Facet::id);
53       return locale(__tmp);
54     }
55
56   template<typename _CharT, typename _Traits, typename _Alloc>
57     bool
58     locale::operator()(const basic_string<_CharT, _Traits, _Alloc>& __s1,
59                        const basic_string<_CharT, _Traits, _Alloc>& __s2) const
60     {
61       typedef std::collate<_CharT> __collate_type;
62       const __collate_type* __fcoll = &use_facet<__collate_type>(*this);
63       return (__fcoll->compare(__s1.data(), __s1.data() + __s1.length(),
64                                __s2.data(), __s2.data() + __s2.length()) < 0);
65     }
66
67   template<typename _Facet>
68     const _Facet&
69     use_facet(const locale& __loc)
70     {
71       typedef locale::_Impl::__vec_facet        __vec_facet;
72       size_t __i = _Facet::id._M_index;
73       __vec_facet* __facet = __loc._M_impl->_M_facets;
74       const locale::facet* __fp = (*__facet)[__i]; 
75       if (__fp == 0 || __i >= __facet->size())
76         __throw_bad_cast();
77       return static_cast<const _Facet&>(*__fp);
78     }
79
80   template<typename _Facet>
81     bool
82     has_facet(const locale& __loc) throw()
83     {
84       typedef locale::_Impl::__vec_facet        __vec_facet;
85       size_t __i = _Facet::id._M_index;
86       __vec_facet* __facet = __loc._M_impl->_M_facets;
87       return (__i < __facet->size() && (*__facet)[__i] != 0);
88     }
89
90   // __match_parallel
91   // matches input __s against a set of __ntargs strings in __targets,
92   // placing in __matches a vector of indices into __targets which
93   // match, and in __remain the number of such matches. If it hits
94   // end of sequence before it minimizes the set, sets __eof.
95   // Empty strings are never matched.
96   template<typename _InIter, typename _CharT>
97     _InIter
98     __match_parallel(_InIter __s, _InIter __end, int __ntargs,
99                      const basic_string<_CharT>* __targets,
100                      int* __matches, int& __remain, bool& __eof)
101     {
102       typedef basic_string<_CharT> __string_type;
103       __eof = false;
104       for (int __ti = 0; __ti < __ntargs; ++__ti)
105         __matches[__ti] = __ti;
106       __remain = __ntargs;
107       size_t __pos = 0;
108       do
109         {
110           int __ti = 0;
111           while (__ti < __remain && __pos == __targets[__matches[__ti]].size())
112             ++__ti;
113           if (__ti == __remain)
114             {
115               if (__pos == 0) __remain = 0;
116               return __s;
117             }
118           if (__s == __end)
119             __eof = true;
120           bool __matched = false;
121           for (int __ti2 = 0; __ti2 < __remain; )
122             {
123               const __string_type& __target = __targets[__matches[__ti2]];
124               if (__pos < __target.size())
125                 {
126                   if (__eof || __target[__pos] != *__s)
127                     {
128                       __matches[__ti2] = __matches[--__remain];
129                       continue;
130                     }
131                   __matched = true;
132                 }
133               ++__ti2;
134             }
135           if (__matched)
136             {
137               ++__s;
138               ++__pos;
139             }
140           for (int __ti3 = 0; __ti3 < __remain;)
141             {
142               if (__pos > __targets[__matches[__ti3]].size())
143                 {
144                   __matches[__ti3] = __matches[--__remain];
145                   continue;
146                 }
147               ++__ti3;
148             }
149         }
150       while (__remain);
151       return __s;
152     }
153
154   template<typename _CharT>
155     _Format_cache<_CharT>::_Format_cache()
156     : _M_valid(true), _M_use_grouping(false)
157     { }
158
159   template<>
160     _Format_cache<char>::_Format_cache();
161
162   template<>
163     _Format_cache<wchar_t>::_Format_cache();
164
165   template<typename _CharT>
166     void
167     _Format_cache<_CharT>::_M_populate(ios_base& __io)
168     {
169       locale __loc = __io.getloc ();
170       numpunct<_CharT> const& __np = use_facet<numpunct<_CharT> >(__loc);
171       _M_truename = __np.truename();
172       _M_falsename = __np.falsename();
173       _M_thousands_sep = __np.thousands_sep();
174       _M_decimal_point = __np.decimal_point();
175       _M_grouping = __np.grouping();
176       _M_use_grouping = _M_grouping.size() != 0 && _M_grouping.data()[0] != 0;
177       _M_valid = true;
178     }
179
180   // This function is always called via a pointer installed in
181   // an ios_base by ios_base::register_callback.
182   template<typename _CharT>
183     void
184     _Format_cache<_CharT>::
185     _S_callback(ios_base::event __ev, ios_base& __ios, int __ix) throw()
186     {
187       void*& __p = __ios.pword(__ix);
188       switch (__ev)
189         {
190         case ios_base::erase_event:
191           delete static_cast<_Format_cache<_CharT>*>(__p);
192           __p = 0;
193           break;
194         case ios_base::copyfmt_event:
195           // If just stored zero, the callback would get registered again.
196           try 
197             { __p = new _Format_cache<_CharT>; }
198           catch(...) 
199             { }
200           break;
201         case ios_base::imbue_event:
202           static_cast<_Format_cache<_CharT>*>(__p)->_M_valid = false;
203           break;
204         }
205     }
206
207   template<typename _CharT>
208     _Format_cache<_CharT>*
209     _Format_cache<_CharT>::_S_get(ios_base& __ios)
210     {
211       if (!_S_pword_ix)
212         _S_pword_ix = ios_base::xalloc();  // XXX MT
213       void*& __p = __ios.pword(_S_pword_ix);
214
215       // XXX What if pword fails? must check failbit, throw.
216       if (__p == 0)  // XXX MT?  maybe sentry takes care of it
217         {
218           auto_ptr<_Format_cache<_CharT> > __ap(new _Format_cache<_CharT>);
219           __ios.register_callback(&_Format_cache<_CharT>::_S_callback,
220                                   _S_pword_ix);
221           __p = __ap.release();
222         }
223       _Format_cache<_CharT>* __ncp = static_cast<_Format_cache<_CharT>*>(__p);
224       if (!__ncp->_M_valid)
225         __ncp->_M_populate(__ios);
226
227       return __ncp;
228     }
229
230   // This member function takes an (w)istreambuf_iterator object and
231   // parses it into a generic char array suitable for parsing with
232   // strto[l,ll,f,d]. The thought was to encapsulate the conversion
233   // into this one function, and thus the num_get::do_get member
234   // functions can just adjust for the type of the overloaded
235   // argument and process the char array returned from _M_extract.
236   // Other things were also considered, including a fused
237   // multiply-add loop that would obviate the need for any call to
238   // strto... at all: however, it would b e a bit of a pain, because
239   // you'd have to be able to return either floating or integral
240   // types, etc etc. The current approach seems to be smack dab in
241   // the middle between an unoptimized approach using sscanf, and
242   // some kind of hyper-optimized approach alluded to above.
243
244   // XXX
245   // Need to do partial specialization to account for differences
246   // between character sets. For char, this is pretty
247   // straightforward, but for wchar_t, the conversion to a plain-jane
248   // char type is a bit more involved.
249   template<typename _CharT, typename _InIter>
250     void
251     num_get<_CharT, _InIter>::
252     _M_extract(_InIter /*__beg*/, _InIter /*__end*/, ios_base& /*__io*/,
253                ios_base::iostate& /*__err*/, char* /*__xtrc*/,
254                int& /*__base*/, bool /*__fp*/) const
255     {
256       // XXX Not currently done: need to expand upon char version below.
257     }
258
259   template<>
260     void
261     num_get<char, istreambuf_iterator<char> >::
262     _M_extract(istreambuf_iterator<char> __beg, 
263                istreambuf_iterator<char> __end, ios_base& __io, 
264                ios_base::iostate& __err, char* __xtrc, int& __base, 
265                bool __fp) const;
266
267 #ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
268   // NB: This is an unresolved library defect #17
269   template<typename _CharT, typename _InIter>
270     _InIter
271     num_get<_CharT, _InIter>::
272     do_get(iter_type __beg, iter_type __end, ios_base& __io,
273            ios_base::iostate& __err, bool& __v) const
274     {
275       // Parse bool values as long
276       if (!(__io.flags() & ios_base::boolalpha))
277         {
278           // NB: We can't just call do_get(long) here, as it might
279           // refer to a derived class.
280
281           // Stage 1: extract and determine the conversion specifier.
282           // Assuming leading zeros eliminated, thus the size of 32 for
283           // integral types.
284           char __xtrc[32] = {'\0'};
285           int __base;
286           _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
287
288           // Stage 2: convert and store results.
289           char* __sanity;
290           errno = 0;
291           long __l = strtol(__xtrc, &__sanity, __base);
292           if (!(__err & ios_base::failbit)
293               && __l <= 1
294               && __sanity != __xtrc && *__sanity == '\0' && errno == 0)
295             __v = __l;
296           else
297             __err |= ios_base::failbit;
298         }
299
300       // Parse bool values as alphanumeric
301       else
302         {
303           typedef _Format_cache<char_type> __fcache_type;
304           __fcache_type* __fmt = __fcache_type::_S_get(__io);
305           const char_type* __true = __fmt->_M_truename.c_str();
306           const char_type* __false = __fmt->_M_falsename.c_str();
307           const size_t __truelen =  __traits_type::length(__true) - 1;
308           const size_t __falselen =  __traits_type::length(__false) - 1;
309
310           for (size_t __pos = 0; __beg != __end; ++__pos)
311             {
312               char_type __c = *__beg++;
313               bool __testf = __c == __false[__pos];
314               bool __testt = __c == __true[__pos];
315               if (!(__testf || __testt))
316                 {
317                   __err |= ios_base::failbit;
318                   break;
319                 }
320               else if (__testf && __pos == __falselen)
321                 {
322                   __v = 0;
323                   break;
324                 }
325               else if (__testt && __pos == __truelen)
326                 {
327                   __v = 1;
328                   break;
329                 }
330             }
331           if (__beg == __end)
332             __err |= ios_base::eofbit;
333         }
334
335       return __beg;
336     }
337 #endif
338
339 #ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
340   template<typename _CharT, typename _InIter>
341     _InIter
342     num_get<_CharT, _InIter>::
343     do_get(iter_type __beg, iter_type __end, ios_base& __io,
344            ios_base::iostate& __err, short& __v) const
345     {
346       // Stage 1: extract and determine the conversion specifier.
347       // Assuming leading zeros eliminated, thus the size of 32 for
348       // integral types.
349       char __xtrc[32]= {'\0'};
350       int __base;
351       _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
352
353       // Stage 2: convert and store results.
354       char* __sanity;
355       errno = 0;
356       long __l = strtol(__xtrc, &__sanity, __base);
357       if (!(__err & ios_base::failbit)
358           && __sanity != __xtrc && *__sanity == '\0' && errno == 0
359           && __l >= SHRT_MIN && __l <= SHRT_MAX)
360         __v = static_cast<short>(__l);
361       else
362         __err |= ios_base::failbit;
363
364       return __beg;
365     }
366
367   template<typename _CharT, typename _InIter>
368     _InIter
369     num_get<_CharT, _InIter>::
370     do_get(iter_type __beg, iter_type __end, ios_base& __io,
371            ios_base::iostate& __err, int& __v) const
372     {
373       // Stage 1: extract and determine the conversion specifier.
374       // Assuming leading zeros eliminated, thus the size of 32 for
375       // integral types.
376       char __xtrc[32] = {'\0'};
377       int __base;
378       _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
379
380       // Stage 2: convert and store results.
381       char* __sanity;
382       errno = 0;
383       long __l = strtol(__xtrc, &__sanity, __base);
384       if (!(__err & ios_base::failbit)
385           && __sanity != __xtrc && *__sanity == '\0' && errno == 0
386           && __l >= INT_MIN && __l <= INT_MAX)
387         __v = static_cast<int>(__l);
388       else
389         __err |= ios_base::failbit;
390
391       return __beg;
392     }
393 #endif
394
395   template<typename _CharT, typename _InIter>
396     _InIter
397     num_get<_CharT, _InIter>::
398     do_get(iter_type __beg, iter_type __end, ios_base& __io,
399            ios_base::iostate& __err, long& __v) const
400     {
401       // Stage 1: extract and determine the conversion specifier.
402       // Assuming leading zeros eliminated, thus the size of 32 for
403       // integral types.
404       char __xtrc[32]= {'\0'};
405       int __base;
406       _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
407
408       // Stage 2: convert and store results.
409       char* __sanity;
410       errno = 0;
411       long __l = strtol(__xtrc, &__sanity, __base);
412       if (!(__err & ios_base::failbit)
413           && __sanity != __xtrc && *__sanity == '\0' && errno == 0)
414         __v = __l;
415       else
416         __err |= ios_base::failbit;
417
418       return __beg;
419     }
420
421 #ifdef _GLIBCPP_USE_LONG_LONG
422   template<typename _CharT, typename _InIter>
423     _InIter
424     num_get<_CharT, _InIter>::
425     do_get(iter_type __beg, iter_type __end, ios_base& __io,
426            ios_base::iostate& __err, long long& __v) const
427     {
428       // Stage 1: extract and determine the conversion specifier.
429       // Assuming leading zeros eliminated, thus the size of 32 for
430       // integral types.
431       char __xtrc[32]= {'\0'};
432       int __base;
433       _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
434
435       // Stage 2: convert and store results.
436       char* __sanity;
437       errno = 0;
438       long long __ll = strtoll(__xtrc, &__sanity, __base);
439       if (!(__err & ios_base::failbit)
440           && __sanity != __xtrc && *__sanity == '\0' && errno == 0)
441         __v = __ll;
442       else
443         __err |= ios_base::failbit;
444
445       return __beg;
446     }
447 #endif
448
449   template<typename _CharT, typename _InIter>
450     _InIter
451     num_get<_CharT, _InIter>::
452     do_get(iter_type __beg, iter_type __end, ios_base& __io,
453            ios_base::iostate& __err, unsigned short& __v) const
454     {
455       // Stage 1: extract and determine the conversion specifier.
456       // Assuming leading zeros eliminated, thus the size of 32 for
457       // integral types.
458       char __xtrc[32]= {'\0'};
459       int __base;
460       _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
461
462       // Stage 2: convert and store results.
463       char* __sanity;
464       errno = 0;
465       unsigned long __ul = strtoul(__xtrc, &__sanity, __base);
466       if (!(__err & ios_base::failbit)
467           && __sanity != __xtrc && *__sanity == '\0' && errno == 0
468           && __ul <= USHRT_MAX)
469         __v = static_cast<unsigned short>(__ul);
470       else
471         __err |= ios_base::failbit;
472
473       return __beg;
474     }
475
476   template<typename _CharT, typename _InIter>
477     _InIter
478     num_get<_CharT, _InIter>::
479     do_get(iter_type __beg, iter_type __end, ios_base& __io,
480            ios_base::iostate& __err, unsigned int& __v) const
481     {
482       // Stage 1: extract and determine the conversion specifier.
483       // Assuming leading zeros eliminated, thus the size of 32 for
484       // integral types.
485       char __xtrc[32]= {'\0'};
486       int __base;
487       _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
488
489       // Stage 2: convert and store results.
490       char* __sanity;
491       errno = 0;
492       unsigned long __ul = strtoul(__xtrc, &__sanity, __base);
493       if (!(__err & ios_base::failbit)
494           && __sanity != __xtrc && *__sanity == '\0' && errno == 0
495           && __ul <= UINT_MAX)
496         __v = static_cast<unsigned int>(__ul);
497       else
498         __err |= ios_base::failbit;
499
500       return __beg;
501     }
502
503   template<typename _CharT, typename _InIter>
504     _InIter
505     num_get<_CharT, _InIter>::
506     do_get(iter_type __beg, iter_type __end, ios_base& __io,
507            ios_base::iostate& __err, unsigned long& __v) const
508     {
509       // Stage 1: extract and determine the conversion specifier.
510       // Assuming leading zeros eliminated, thus the size of 32 for
511       // integral types.
512       char __xtrc[32] = {'\0'};
513       int __base;
514       _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
515
516       // Stage 2: convert and store results.
517       char* __sanity;
518       errno = 0;
519       unsigned long __ul = strtoul(__xtrc, &__sanity, __base);
520       if (!(__err & ios_base::failbit)
521           && __sanity != __xtrc && *__sanity == '\0' && errno == 0)
522         __v = __ul;
523       else
524         __err |= ios_base::failbit;
525
526       return __beg;
527     }
528
529 #ifdef _GLIBCPP_USE_LONG_LONG
530   template<typename _CharT, typename _InIter>
531     _InIter
532     num_get<_CharT, _InIter>::
533     do_get(iter_type __beg, iter_type __end, ios_base& __io,
534            ios_base::iostate& __err, unsigned long long& __v) const
535     {
536       // Stage 1: extract and determine the conversion specifier.
537       // Assuming leading zeros eliminated, thus the size of 32 for
538       // integral types.
539       char __xtrc[32]= {'\0'};
540       int __base;
541       _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
542
543       // Stage 2: convert and store results.
544       char* __sanity;
545       errno = 0;
546       unsigned long long __ull = strtoull(__xtrc, &__sanity, __base);
547       if (!(__err & ios_base::failbit)
548           && __sanity != __xtrc && *__sanity == '\0' && errno == 0)
549         __v = __ull;
550       else
551         __err |= ios_base::failbit;
552
553       return __beg;
554     }
555 #endif
556
557   template<typename _CharT, typename _InIter>
558     _InIter
559     num_get<_CharT, _InIter>::
560     do_get(iter_type __beg, iter_type __end, ios_base& __io,
561            ios_base::iostate& __err, float& __v) const
562     {
563       // Stage 1: extract and determine the conversion specifier.
564       // Assuming leading zeros eliminated, thus the size of 256 for
565       // floating-point types.
566       char __xtrc[32]= {'\0'};
567       int __base;
568       _M_extract(__beg, __end, __io, __err, __xtrc, __base, true);
569
570       // Stage 2: convert and store results.
571       char* __sanity;
572       errno = 0;
573 #ifdef _GLIBCPP_USE_C99
574       float __f = strtof(__xtrc, &__sanity);
575 #else
576       float __f = static_cast<float>(strtod(__xtrc, &__sanity));
577 #endif
578       if (!(__err & ios_base::failbit)
579           && __sanity != __xtrc && *__sanity == '\0' && errno == 0)
580         __v = __f;
581       else
582         __err |= ios_base::failbit;
583
584       return __beg;
585     }
586
587   template<typename _CharT, typename _InIter>
588     _InIter
589     num_get<_CharT, _InIter>::
590     do_get(iter_type __beg, iter_type __end, ios_base& __io,
591            ios_base::iostate& __err, double& __v) const
592     {
593       // Stage 1: extract and determine the conversion specifier.
594       // Assuming leading zeros eliminated, thus the size of 256 for
595       // floating-point types.
596       char __xtrc[32]= {'\0'};
597       int __base;
598       _M_extract(__beg, __end, __io, __err, __xtrc, __base, true);
599
600       // Stage 2: convert and store results.
601       char* __sanity;
602       errno = 0;
603       double __d = strtod(__xtrc, &__sanity);
604       if (!(__err & ios_base::failbit)
605           && __sanity != __xtrc && *__sanity == '\0' && errno == 0)
606         __v = __d;
607       else
608         __err |= ios_base::failbit;
609
610       return __beg;
611     }
612
613 #if defined(_GLIBCPP_USE_C99) && !defined(__hpux)
614   template<typename _CharT, typename _InIter>
615     _InIter
616     num_get<_CharT, _InIter>::
617     do_get(iter_type __beg, iter_type __end, ios_base& __io,
618            ios_base::iostate& __err, long double& __v) const
619     {
620       // Stage 1: extract and determine the conversion specifier.
621       // Assuming leading zeros eliminated, thus the size of 256 for
622       // floating-point types.
623       char __xtrc[32]= {'\0'};
624       int __base;
625       _M_extract(__beg, __end, __io, __err, __xtrc, __base, true);
626
627       // Stage 2: convert and store results.
628       char* __sanity;
629       errno = 0;
630       long double __ld = strtold(__xtrc, &__sanity);
631       if (!(__err & ios_base::failbit)
632           && __sanity != __xtrc && *__sanity == '\0' && errno == 0)
633         __v = __ld;
634       else
635         __err |= ios_base::failbit;
636
637       return __beg;
638     }
639 #else
640   template<typename _CharT, typename _InIter>
641     _InIter
642     num_get<_CharT, _InIter>::
643     do_get(iter_type __beg, iter_type __end, ios_base& __io,
644            ios_base::iostate& __err, long double& __v) const
645     {
646       // Stage 1: extract
647       char __xtrc[32]= {'\0'};
648       int __base;
649       _M_extract(__beg, __end, __io, __err, __xtrc, __base, true);
650
651       // Stage 2: determine a conversion specifier.
652       ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield;
653       const char* __conv;
654       if (__basefield == ios_base::oct)
655         __conv = "%Lo";
656       else if (__basefield == ios_base::hex)
657         __conv = "%LX";
658       else if (__basefield == 0)
659         __conv = "%Li";
660       else
661         __conv = "%Lg";
662
663       // Stage 3: store results.
664       long double __ld;
665       int __p = sscanf(__xtrc, __conv, &__ld);
666       if (__p
667           && static_cast<typename __traits_type::int_type>(__p)
668         != __traits_type::eof())
669         __v = __ld;
670       else
671         __err |= ios_base::failbit;
672
673       return __beg;
674     }
675 #endif
676
677   template<typename _CharT, typename _InIter>
678     _InIter
679     num_get<_CharT, _InIter>::
680     do_get(iter_type __beg, iter_type __end, ios_base& __io,
681            ios_base::iostate& __err, void*& __v) const
682     {
683       // Prepare for hex formatted input
684       typedef ios_base::fmtflags        fmtflags;
685       fmtflags __fmt = __io.flags();
686       fmtflags __fmtmask = ~(ios_base::showpos | ios_base::basefield
687                              | ios_base::uppercase | ios_base::internal);
688       __io.flags(__fmt & __fmtmask | (ios_base::hex | ios_base::showbase));
689
690       // Stage 1: extract and determine the conversion specifier.
691       // Assuming leading zeros eliminated, thus the size of 32 for
692       // integral types.
693       char __xtrc[32]= {'\0'};
694       int __base;
695       _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
696
697       // Stage 2: convert and store results.
698       char* __sanity;
699       errno = 0;
700       void* __vp = reinterpret_cast<void*>(strtoul(__xtrc, &__sanity, __base));
701       if (!(__err & ios_base::failbit)
702           && __sanity != __xtrc && *__sanity == '\0' && errno == 0)
703         __v = __vp;
704       else
705         __err |= ios_base::failbit;
706
707       // Reset from hex formatted input
708       __io.flags(__fmt);
709       return __beg;
710     }
711
712   // __pad is specialized for ostreambuf_iterator, random access iterator.
713   template <typename _CharT, typename _OutIter>
714     inline _OutIter
715     __pad(_OutIter __s, _CharT __fill, int __padding);
716
717   template <typename _CharT, typename _RaIter>
718     _RaIter
719     __pad(_RaIter __s, _CharT __fill, int __padding, 
720           random_access_iterator_tag)
721     {
722       fill_n(__s, __fill);
723       return __s + __padding;
724     }
725
726   template <typename _CharT, typename _OutIter, typename _Tag>
727     _OutIter
728     __pad(_OutIter __s, _CharT __fill, int __padding, _Tag)
729     {
730       while (--__padding >= 0) { *__s = __fill; ++__s; }
731       return __s;
732     }
733
734   template <typename _CharT, typename _OutIter>
735     inline _OutIter
736     __pad(_OutIter __s, _CharT __fill, int __padding)
737     {
738       return __pad(__s, __fill, __padding, 
739                    typename iterator_traits<_OutIter>::iterator_category());
740     }
741
742   template <typename _CharT, typename _OutIter>
743     _OutIter
744     __pad_numeric(_OutIter __s, ios_base::fmtflags /*__flags*/,
745                   _CharT /*__fill*/, int /*__width*/, 
746                   _CharT const* /*__first*/, _CharT const* /*__middle*/, 
747                   _CharT const* /*__last*/)
748   {
749       // XXX Not currently done: non streambuf_iterator
750       return __s;
751     }
752
753   // Partial specialization for ostreambuf_iterator.
754   template <typename _CharT>   
755     ostreambuf_iterator<_CharT>
756     __pad_numeric(ostreambuf_iterator<_CharT> __s, ios_base::fmtflags __flags,
757                   _CharT __fill, int __width, _CharT const* __first,
758                   _CharT const* __middle, _CharT const* __last)
759     {
760       typedef ostreambuf_iterator<_CharT>       __out_iter;
761       int __padding = __width - (__last - __first);
762       if (__padding < 0)
763         __padding = 0;
764       ios_base::fmtflags __aflags = __flags & ios_base::adjustfield;
765       bool __testfield = __padding == 0 || __aflags == ios_base::left
766                          || __aflags == ios_base::internal;
767
768       // This was needlessly complicated.
769       if (__first != __middle)
770         {
771           if (!__testfield)
772             {
773               __pad(__s, __fill, __padding);
774               __padding = 0;
775             }
776           copy(__first, __middle, __s);
777         }
778       __out_iter __s2 = __s;
779
780       if (__padding && __aflags != ios_base::left)
781         {
782           __pad(__s2, __fill, __padding);
783           __padding = 0;
784         }
785       __out_iter __s3 = copy(__middle, __last, __s2);
786       if (__padding)
787         __pad(__s3, __fill, __padding);
788       return __s3;
789     }
790
791   template <typename _CharT, typename _OutIter>
792     _OutIter
793     num_put<_CharT, _OutIter>::
794     do_put(iter_type __s, ios_base& __io, char_type __fill, bool __v) const
795     {
796       const _Format_cache<_CharT>* __fmt = _Format_cache<_CharT>::_S_get(__io);
797       ios_base::fmtflags __flags = __io.flags();
798
799       if ((__flags & ios_base::boolalpha) == 0)
800         {
801           unsigned long __uv = __v;
802           return __output_integer(__s, __io, __fill, false, __uv);
803         }
804       else
805         {
806           const char_type* __first;
807           const char_type* __last;
808           if (__v)
809             {
810               __first = __fmt->_M_truename.data();
811               __last = __first + __fmt->_M_truename.size();
812             }
813           else
814             {
815               __first = __fmt->_M_falsename.data();
816               __last = __first + __fmt->_M_falsename.size();
817             }
818           copy(__first, __last, __s);
819         }
820       return __s;
821     }
822
823   // __group_digits inserts "group separator" characters into an array
824   // of characters.  It's recursive, one iteration per group.  It moves
825   // the characters in the buffer this way: "xxxx12345" -> "12,345xxx".
826   // Call this only with __grouping != __grend.
827   template <typename _CharT>
828     _CharT*
829     __group_digits(_CharT* __s, _CharT __grsep,  char const* __grouping,
830                     char const* __grend, _CharT const* __first,
831                     _CharT const* __last)
832     {
833       if (__last - __first > *__grouping)
834         {
835           __s = __group_digits(__s,  __grsep,
836               (__grouping + 1 == __grend ? __grouping : __grouping + 1),
837               __grend, __first, __last - *__grouping);
838           __first = __last - *__grouping;
839           *__s++ = __grsep;
840         }
841       do
842         {
843           *__s++ = *__first++;
844         }
845       while (__first != __last);
846       return __s;
847     }
848
849   template <typename _CharT, typename _OutIter, typename _ValueT>
850     _OutIter
851     __output_integer(_OutIter __s, ios_base& __io, _CharT __fill, bool __neg,
852               _ValueT __v)
853     {
854       // Leave room for "+/-," "0x," and commas.
855       const long _M_room = numeric_limits<_ValueT>::digits10 * 2 + 4;
856       _CharT __digits[_M_room];
857       _CharT* __front = __digits + _M_room;
858       ios_base::fmtflags __flags = __io.flags();
859       const _Format_cache<_CharT>* __fmt = _Format_cache<_CharT>::_S_get(__io);
860       char const* __table = __fmt->_S_literals + __fmt->_S_digits;
861
862       ios_base::fmtflags __basefield = (__flags & __io.basefield);
863       _CharT* __sign_end = __front;
864       if (__basefield == ios_base::hex)
865         {
866           if (__flags & ios_base::uppercase)
867             __table += 16;  // use ABCDEF
868           do
869             *--__front = __table[__v & 15];
870           while ((__v >>= 4) != 0);
871           __sign_end = __front;
872           if (__flags & ios_base::showbase)
873             {
874               *--__front = __fmt->_S_literals[__fmt->_S_x +
875                        ((__flags & ios_base::uppercase) ? 1 : 0)];
876               *--__front = __table[0];
877             }
878         }
879       else if (__basefield == ios_base::oct)
880         {
881           do
882             *--__front = __table[__v & 7];
883           while ((__v >>= 3) != 0);
884           if (__flags & ios_base::showbase
885               && static_cast<char>(*__front) != __table[0])
886             *--__front = __table[0];
887           __sign_end = __front;
888         }
889       else
890         {
891           // NB: This is _lots_ faster than using ldiv.
892           do
893             *--__front = __table[__v % 10];
894           while ((__v /= 10) != 0);
895           __sign_end = __front;
896           // NB: ios_base:hex || ios_base::oct assumed to be unsigned.
897           if (__neg || (__flags & ios_base::showpos))
898             *--__front = __fmt->_S_literals[__fmt->_S_plus - __neg];
899         }
900
901       // XXX should specialize!
902       if (!__fmt->_M_use_grouping && !__io.width())
903         return copy(__front, __digits + _M_room, __s);
904
905       if (!__fmt->_M_use_grouping)
906         return __pad_numeric(__s, __flags, __fill, __io.width(0),
907                              __front, __sign_end, __digits + _M_room);
908
909       _CharT* __p = __digits;
910       while (__front < __sign_end)
911         *__p++ = *__front++;
912       const char* __gr = __fmt->_M_grouping.data();
913       __front = __group_digits(__p, __fmt->_M_thousands_sep, __gr,
914         __gr + __fmt->_M_grouping.size(), __sign_end, __digits + _M_room);
915       return __pad_numeric(__s, __flags, __fill, __io.width(0),
916                            __digits, __p, __front);
917     }
918
919   template <typename _CharT, typename _OutIter>
920     _OutIter
921     num_put<_CharT, _OutIter>::
922     do_put(iter_type __s, ios_base& __io, char_type __fill, long __v) const
923     {
924       unsigned long __uv = __v;
925       bool __neg = false;
926       if (__v < 0)
927         {
928           __neg = true;
929           __uv = -__uv;
930         }
931       return __output_integer(__s, __io, __fill, __neg, __uv);
932     }
933
934   template <typename _CharT, typename _OutIter>
935     _OutIter
936     num_put<_CharT, _OutIter>::
937     do_put(iter_type __s, ios_base& __io, char_type __fill,
938            unsigned long __v) const
939     { return __output_integer(__s, __io, __fill, false, __v); }
940
941 #ifdef _GLIBCPP_USE_LONG_LONG
942   template <typename _CharT, typename _OutIter>
943     _OutIter
944     num_put<_CharT, _OutIter>::
945     do_put(iter_type __s, ios_base& __b, char_type __fill, long long __v) const
946     {
947       unsigned long long __uv = __v;
948       bool __neg = false;
949       if (__v < 0)
950         {
951           __neg = true;
952           __uv = -__uv;
953         }
954       return __output_integer(__s, __b, __fill, __neg, __uv);
955     }
956
957   template <typename _CharT, typename _OutIter>
958     _OutIter
959     num_put<_CharT, _OutIter>::
960     do_put(iter_type __s, ios_base& __io, char_type __fill,
961            unsigned long long __v) const
962     { return __output_integer(__s, __io, __fill, false, __v); }
963 #endif
964
965   // Generic helper function
966   template<typename _CharT, typename _Traits, typename _OutIter>
967     _OutIter
968     __output_float(_OutIter __s, ios_base& __io, _CharT __fill,
969                     const char* __sptr, size_t __slen)
970     {
971       // XXX Not currently done: non streambuf_iterator
972       return __s;
973     }
974
975   // Partial specialization for ostreambuf_iterator.
976   template<typename _CharT, typename _Traits>
977     ostreambuf_iterator<_CharT, _Traits>
978     __output_float(ostreambuf_iterator<_CharT, _Traits> __s, ios_base& __io, 
979                    _CharT __fill, const char* __sptr, size_t __slen)
980     {
981       size_t __padding = __io.width() > streamsize(__slen) ?
982                          __io.width() -__slen : 0;
983       locale __loc = __io.getloc();
984       ctype<_CharT> const& __ct = use_facet<ctype<_CharT> >(__loc);
985       ios_base::fmtflags __adjfield = __io.flags() & ios_base::adjustfield;
986       const char* const __eptr = __sptr + __slen;
987       // [22.2.2.2.2.19] Table 61
988       if (__adjfield == ios_base::internal)
989        {
990          // [22.2.2.2.2.14]; widen()
991          if (__sptr < __eptr && (*__sptr == '+' || *__sptr == '-'))
992            {
993              __s = __ct.widen(*__sptr);
994              ++__s;
995              ++__sptr;
996            }
997          __s = __pad(__s, __fill, __padding);
998          __padding = 0;
999        }
1000       else if (__adjfield != ios_base::left)
1001         {
1002           __s = __pad(__s, __fill, __padding);
1003           __padding = 0;
1004         }
1005       // the "C" locale decimal character
1006       char __decimal_point = *(localeconv()->decimal_point);
1007       const _Format_cache<_CharT>* __fmt = _Format_cache<_CharT>::_S_get(__io);
1008       for (; __sptr != __eptr; ++__s, ++__sptr)
1009        {
1010          // [22.2.2.2.2.17]; decimal point conversion
1011          if (*__sptr == __decimal_point)
1012            __s = __fmt->_M_decimal_point;
1013          // [22.2.2.2.2.14]; widen()
1014          else
1015            __s = __ct.widen(*__sptr);
1016        }
1017       // [22.2.2.2.2.19] Table 61
1018       if (__padding)
1019         __pad(__s, __fill, __padding);
1020       __io.width(0);
1021       return __s;
1022     }
1023
1024   bool
1025   __build_float_format(ios_base& __io, char* __fptr, char __modifier,
1026                        streamsize __prec);
1027
1028   template <typename _CharT, typename _OutIter>
1029     _OutIter
1030     num_put<_CharT, _OutIter>::
1031     do_put(iter_type __s, ios_base& __io, char_type __fill, double __v) const
1032     {
1033       const streamsize __max_prec = numeric_limits<double>::digits10 + 3;
1034       streamsize __prec = __io.precision();
1035       // Protect against sprintf() buffer overflows.
1036       if (__prec > __max_prec)
1037         __prec = __max_prec;
1038       // The *2 provides for signs, exp, 'E', and pad.
1039       char __sbuf[__max_prec * 2];
1040       size_t __slen;
1041       // Long enough for the max format spec.
1042       char __fbuf[16];
1043       if (__build_float_format(__io, __fbuf, 0, __prec))
1044         __slen = sprintf(__sbuf, __fbuf, __prec, __v);
1045       else
1046         __slen = sprintf(__sbuf, __fbuf, __v);
1047       // [22.2.2.2.2] Stages 2-4.
1048       return __output_float(__s, __io, __fill, __sbuf, __slen);
1049     }
1050
1051   template <typename _CharT, typename _OutIter>
1052     _OutIter
1053     num_put<_CharT, _OutIter>::
1054     do_put(iter_type __s, ios_base& __io, char_type __fill,
1055            long double __v) const
1056     {
1057       const streamsize __max_prec = numeric_limits<long double>::digits10 + 3;
1058       streamsize __prec = __io.precision();
1059       // Protect against sprintf() buffer overflows.
1060       if (__prec > __max_prec)
1061         __prec = __max_prec;
1062       // The *2 provides for signs, exp, 'E', and pad.
1063       char __sbuf[__max_prec * 2];
1064       size_t __slen;
1065       // Long enough for the max format spec.
1066       char __fbuf[16];
1067       // 'L' as per [22.2.2.2.2] Table 59
1068       if (__build_float_format(__io, __fbuf, 'L', __prec))
1069         __slen = sprintf(__sbuf, __fbuf, __prec, __v);
1070       else
1071         __slen = sprintf(__sbuf, __fbuf, __v);
1072       // [22.2.2.2.2] Stages 2-4
1073       return __output_float(__s, __io, __fill, __sbuf, __slen);
1074     }
1075
1076   template <typename _CharT, typename _OutIter>
1077     _OutIter
1078     num_put<_CharT, _OutIter>::
1079     do_put(iter_type __s, ios_base& __io, char_type __fill,
1080            const void* __v) const
1081     {
1082       typedef ios_base::fmtflags        fmtflags;
1083       fmtflags __fmt = __io.flags();
1084       fmtflags __fmtmask = ~(ios_base::showpos | ios_base::basefield
1085                              | ios_base::uppercase | ios_base::internal);
1086       __io.flags(__fmt & __fmtmask | (ios_base::hex | ios_base::showbase));
1087       try {
1088         _OutIter __s2 = __output_integer(__s, __io, __fill, false,
1089                                   reinterpret_cast<unsigned long>(__v));
1090         __io.flags(__fmt);
1091         return __s2;
1092       }
1093       catch (...) {
1094         __io.flags(__fmt);
1095         __throw_exception_again;
1096       }
1097     }
1098
1099   // Support for time_get:
1100   // Note that these partial specializations could, and maybe should,
1101   // be changed to full specializations (by eliminating the _Dummy
1102   // argument) and moved to a .cc file.
1103   template<typename _CharT, typename _Dummy = int>
1104     struct _Weekdaynames;
1105
1106   template<typename _Dummy>
1107     struct _Weekdaynames<char, _Dummy>
1108     { static const char* const _S_names[14]; };
1109
1110   template<typename _Dummy>
1111     const char* const
1112     _Weekdaynames<char, _Dummy>::_S_names[14] =
1113     {
1114       "Sun", "Sunday",
1115       "Mon", "Monday",   "Tue", "Tuesday", "Wed", "Wednesday",
1116       "Thu", "Thursday", "Fri", "Friday",  "Sat", "Saturday"
1117     };
1118
1119 #ifdef _GLIBCPP_USE_WCHAR_T
1120   template<typename _Dummy>
1121     struct _Weekdaynames<wchar_t, _Dummy>
1122     { static const wchar_t* const _S_names[14]; };
1123
1124   template<typename _Dummy>
1125     const wchar_t* const
1126     _Weekdaynames<wchar_t, _Dummy>::_S_names[14] =
1127     {
1128       L"Sun", L"Sunday",
1129       L"Mon", L"Monday",   L"Tue", L"Tuesday", L"Wed", L"Wednesday",
1130       L"Thu", L"Thursday", L"Fri", L"Friday",  L"Sat", L"Saturday"
1131     };
1132 #endif
1133
1134   template<typename _CharT, typename _Dummy = int>
1135     struct _Monthnames;
1136
1137   template<typename _Dummy>
1138     struct _Monthnames<char,_Dummy>
1139     { static const char* const _S_names[24]; };
1140
1141   template<typename _Dummy>
1142     const char* const
1143     _Monthnames<char,_Dummy>::_S_names[24] =
1144     {
1145       "Jan", "January", "Feb", "February", "Mar", "March",
1146       "Apr", "April",   "May", "May",      "Jun", "June",
1147       "Jul", "July",    "Aug", "August",   "Sep", "September",
1148       "Oct", "October", "Nov", "November", "Dec", "December"
1149     };
1150
1151 #ifdef _GLIBCPP_USE_WCHAR_T
1152   template<typename _Dummy>
1153     struct _Monthnames<wchar_t, _Dummy>
1154     { static const wchar_t* const _S_names[24]; };
1155
1156   template<typename _Dummy>
1157     const wchar_t* const
1158     _Monthnames<wchar_t,_Dummy>::_S_names[24] =
1159     {
1160       L"Jan", L"January", L"Feb", L"February", L"Mar", L"March",
1161       L"Apr", L"April",   L"May", L"May",      L"Jun", L"June",
1162       L"Jul", L"July",    L"Aug", L"August",   L"Sep", L"September",
1163       L"Oct", L"October", L"Nov", L"November", L"Dec", L"December"
1164     };
1165 #endif
1166
1167   template<typename _CharT, typename _InIter>
1168     _InIter
1169     time_get<_CharT, _InIter>::
1170     do_get_weekday(iter_type __s, iter_type __end,
1171                    ios_base& __io, ios_base::iostate& __err, tm* __t) const
1172     {
1173       if (!_M_daynames)
1174         {
1175           _M_daynames = new basic_string<_CharT>[14];
1176           for (int __i = 0; __i < 14; ++__i)
1177             _M_daynames[__i] = _Weekdaynames<_CharT>::_S_names[__i];
1178         }
1179       bool __at_eof = false;
1180       int __remain = 0;
1181       int __matches[14];
1182       iter_type __out = __match_parallel(__s, __end, 14, _M_daynames,
1183                                          __matches, __remain, __at_eof);
1184       __err = ios_base::iostate(0);
1185       if (__at_eof) __err |= __io.eofbit;
1186       if (__remain == 1 ||
1187           __remain == 2 && (__matches[0]>>1) == (__matches[1]>>1))
1188         __t->tm_wday = (__matches[0]>>1);
1189       else
1190         __err |= __io.failbit;
1191       return __out;
1192     }
1193
1194   template<typename _CharT, typename _InIter>
1195     _InIter
1196     time_get<_CharT, _InIter>::
1197     do_get_monthname(iter_type __s, iter_type __end,
1198                      ios_base& __io, ios_base::iostate& __err, tm* __t) const
1199     {
1200       if (!_M_monthnames)
1201         {
1202           _M_monthnames = new basic_string<_CharT>[24];
1203           for (int __i = 0; __i < 24; ++__i)
1204             _M_monthnames[__i] = _Monthnames<_CharT>::_S_names[__i];
1205         }
1206       bool __at_eof = false;
1207       int __remain = 0;
1208       int __matches[24];
1209       iter_type __out = __match_parallel( __s, __end, 24, _M_monthnames,
1210                                           __matches, __remain, __at_eof);
1211       __err = ios_base::iostate(0);
1212       if (__at_eof) __err |= __io.eofbit;
1213       if (__remain == 1 ||
1214           __remain == 2 && (__matches[0]>>1) == (__matches[1]>>1))
1215         __t->tm_mon = (__matches[0]>>1);
1216       else
1217         __err |= __io.failbit;
1218       return __out;
1219     }
1220 } // std::
1221
1222 #endif /* _CPP_BITS_LOCFACETS_TCC */
1223
1224 // Local Variables:
1225 // mode:c++
1226 // End: