OSDN Git Service

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