OSDN Git Service

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