1 // Locale support -*- C++ -*-
3 // Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
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)
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.
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,
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.
30 // Warning: this file is not meant for user inclusion. Use <locale>.
32 #ifndef _CPP_BITS_LOCFACETS_TCC
33 #define _CPP_BITS_LOCFACETS_TCC 1
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>
48 template<typename _Facet>
50 locale::combine(const locale& __other)
53 __copy._M_impl->_M_replace_facet(__other._M_impl, &_Facet::id);
57 template<typename _CharT, typename _Traits, typename _Alloc>
59 locale::operator()(const basic_string<_CharT, _Traits, _Alloc>& __s1,
60 const basic_string<_CharT, _Traits, _Alloc>& __s2) const
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);
68 template<typename _Facet>
70 use_facet(const locale& __loc)
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())
79 return static_cast<const _Facet&>(*__fp);
82 template<typename _Facet>
84 has_facet(const locale& __loc) throw()
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);
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>
101 __match_parallel(_InIter __s, _InIter __end, int __ntargs,
102 const basic_string<_CharT>* __targets,
103 int* __matches, int& __remain, bool& __eof)
105 typedef basic_string<_CharT> __string_type;
107 for (int __ti = 0; __ti < __ntargs; ++__ti)
108 __matches[__ti] = __ti;
115 for (;__ti < __remain &&
116 __pos == __targets[__matches[__ti]].size(); ++__ti)
118 if (__ti == __remain)
120 if (__pos == 0) __remain = 0;
126 bool __matched = false;
127 for (int __ti = 0; __ti < __remain; )
129 const __string_type& __target = __targets[__matches[__ti]];
130 if (__pos < __target.size())
132 if (__eof || __target[__pos] != *__s)
134 __matches[__ti] = __matches[--__remain];
146 for (int __ti = 0; __ti < __remain;)
148 if (__pos > __targets[__matches[__ti]].size())
150 __matches[__ti] = __matches[--__remain];
160 template<typename _CharT>
161 _Format_cache<_CharT>::_Format_cache()
162 : _M_valid(true), _M_use_grouping(false)
166 _Format_cache<char>::_Format_cache();
169 _Format_cache<wchar_t>::_Format_cache();
171 template<typename _CharT>
173 _Format_cache<_CharT>::_M_populate(ios_base& __io)
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;
186 // This function is always called via a pointer installed in
187 // an ios_base by ios_base::register_callback.
188 template<typename _CharT>
190 _Format_cache<_CharT>::
191 _S_callback(ios_base::event __ev, ios_base& __ios, int __ix) throw()
193 void*& __p = __ios.pword(__ix);
196 case ios_base::erase_event:
197 delete static_cast<_Format_cache<_CharT>*> (__p); __p = 0;
199 case ios_base::copyfmt_event:
200 // If just stored zero, the callback would get registered again.
202 __p = new _Format_cache<_CharT>;
207 case ios_base::imbue_event:
208 static_cast<_Format_cache<_CharT>*>(__p)->_M_valid = false;
213 template<typename _CharT>
214 _Format_cache<_CharT>*
215 _Format_cache<_CharT>::_S_get(ios_base& __ios)
218 _S_pword_ix = ios_base::xalloc(); // XXX MT
219 void*& __p = __ios.pword(_S_pword_ix);
221 // XXX What if pword fails? must check failbit, throw.
222 if (__p == 0) // XXX MT? maybe sentry takes care of it
224 auto_ptr<_Format_cache<_CharT> > __ap(new _Format_cache<_CharT>);
225 __ios.register_callback(&_Format_cache<_CharT>::_S_callback,
227 __p = __ap.release();
229 _Format_cache<_CharT>* __ncp = static_cast<_Format_cache<_CharT>*>(__p);
230 if (!__ncp->_M_valid)
231 __ncp->_M_populate(__ios);
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.
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>
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
262 // XXX Not currently done: need to expand upon char version below.
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,
273 #ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
274 // NB: This is an unresolved library defect #17
275 template<typename _CharT, typename _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
281 // Parse bool values as long
282 if (!(__io.flags() & ios_base::boolalpha))
284 // NB: We can't just call do_get(long) here, as it might
285 // refer to a derived class.
287 // Stage 1: extract and determine the conversion specifier.
288 // Assuming leading zeros eliminated, thus the size of 32 for
290 char __xtrc[32] = {'\0'};
292 _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
294 // Stage 2: convert and store results.
297 long __l = strtol(__xtrc, &__sanity, __base);
298 if (!(__err & ios_base::failbit)
300 && __sanity != __xtrc && *__sanity == '\0' && errno == 0)
303 __err |= ios_base::failbit;
306 // Parse bool values as alphanumeric
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;
316 for (size_t __pos = 0; __beg != __end; ++__pos)
318 char_type __c = *__beg++;
319 bool __testf = __c == __false[__pos];
320 bool __testt = __c == __true[__pos];
321 if (!(__testf || __testt))
323 __err |= ios_base::failbit;
326 else if (__testf && __pos == __falselen)
331 else if (__testt && __pos == __truelen)
338 __err |= ios_base::eofbit;
345 #ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
346 template<typename _CharT, typename _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
352 // Stage 1: extract and determine the conversion specifier.
353 // Assuming leading zeros eliminated, thus the size of 32 for
355 char __xtrc[32]= {'\0'};
357 _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
359 // Stage 2: convert and store results.
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);
368 __err |= ios_base::failbit;
373 template<typename _CharT, typename _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
379 // Stage 1: extract and determine the conversion specifier.
380 // Assuming leading zeros eliminated, thus the size of 32 for
382 char __xtrc[32] = {'\0'};
384 _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
386 // Stage 2: convert and store results.
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);
395 __err |= ios_base::failbit;
401 template<typename _CharT, typename _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
407 // Stage 1: extract and determine the conversion specifier.
408 // Assuming leading zeros eliminated, thus the size of 32 for
410 char __xtrc[32]= {'\0'};
412 _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
414 // Stage 2: convert and store results.
417 long __l = strtol(__xtrc, &__sanity, __base);
418 if (!(__err & ios_base::failbit)
419 && __sanity != __xtrc && *__sanity == '\0' && errno == 0)
422 __err |= ios_base::failbit;
427 #ifdef _GLIBCPP_USE_LONG_LONG
428 template<typename _CharT, typename _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
434 // Stage 1: extract and determine the conversion specifier.
435 // Assuming leading zeros eliminated, thus the size of 32 for
437 char __xtrc[32]= {'\0'};
439 _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
441 // Stage 2: convert and store results.
444 long long __ll = strtoll(__xtrc, &__sanity, __base);
445 if (!(__err & ios_base::failbit)
446 && __sanity != __xtrc && *__sanity == '\0' && errno == 0)
449 __err |= ios_base::failbit;
455 template<typename _CharT, typename _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
461 // Stage 1: extract and determine the conversion specifier.
462 // Assuming leading zeros eliminated, thus the size of 32 for
464 char __xtrc[32]= {'\0'};
466 _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
468 // Stage 2: convert and store results.
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);
477 __err |= ios_base::failbit;
482 template<typename _CharT, typename _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
488 // Stage 1: extract and determine the conversion specifier.
489 // Assuming leading zeros eliminated, thus the size of 32 for
491 char __xtrc[32]= {'\0'};
493 _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
495 // Stage 2: convert and store results.
498 unsigned long __ul = strtoul(__xtrc, &__sanity, __base);
499 if (!(__err & ios_base::failbit)
500 && __sanity != __xtrc && *__sanity == '\0' && errno == 0
502 __v = static_cast<unsigned int>(__ul);
504 __err |= ios_base::failbit;
509 template<typename _CharT, typename _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
515 // Stage 1: extract and determine the conversion specifier.
516 // Assuming leading zeros eliminated, thus the size of 32 for
518 char __xtrc[32] = {'\0'};
520 _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
522 // Stage 2: convert and store results.
525 unsigned long __ul = strtoul(__xtrc, &__sanity, __base);
526 if (!(__err & ios_base::failbit)
527 && __sanity != __xtrc && *__sanity == '\0' && errno == 0)
530 __err |= ios_base::failbit;
535 #ifdef _GLIBCPP_USE_LONG_LONG
536 template<typename _CharT, typename _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
542 // Stage 1: extract and determine the conversion specifier.
543 // Assuming leading zeros eliminated, thus the size of 32 for
545 char __xtrc[32]= {'\0'};
547 _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
549 // Stage 2: convert and store results.
552 unsigned long long __ull = strtoull(__xtrc, &__sanity, __base);
553 if (!(__err & ios_base::failbit)
554 && __sanity != __xtrc && *__sanity == '\0' && errno == 0)
557 __err |= ios_base::failbit;
563 template<typename _CharT, typename _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
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'};
574 _M_extract(__beg, __end, __io, __err, __xtrc, __base, true);
576 // Stage 2: convert and store results.
579 #ifdef _GLIBCPP_HAVE_STRTOF
580 float __f = strtof(__xtrc, &__sanity);
582 float __f = static_cast<float>(strtod(__xtrc, &__sanity));
584 if (!(__err & ios_base::failbit)
585 && __sanity != __xtrc && *__sanity == '\0' && errno == 0)
588 __err |= ios_base::failbit;
593 template<typename _CharT, typename _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
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'};
604 _M_extract(__beg, __end, __io, __err, __xtrc, __base, true);
606 // Stage 2: convert and store results.
609 double __d = strtod(__xtrc, &__sanity);
610 if (!(__err & ios_base::failbit)
611 && __sanity != __xtrc && *__sanity == '\0' && errno == 0)
614 __err |= ios_base::failbit;
619 #if defined(_GLIBCPP_HAVE_STRTOLD) && !defined(__hpux)
620 template<typename _CharT, typename _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
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'};
631 _M_extract(__beg, __end, __io, __err, __xtrc, __base, true);
633 // Stage 2: convert and store results.
636 long double __ld = strtold(__xtrc, &__sanity);
637 if (!(__err & ios_base::failbit)
638 && __sanity != __xtrc && *__sanity == '\0' && errno == 0)
641 __err |= ios_base::failbit;
646 template<typename _CharT, typename _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
653 char __xtrc[32]= {'\0'};
655 _M_extract(__beg, __end, __io, __err, __xtrc, __base, true);
657 // Stage 2: determine a conversion specifier.
658 ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield;
660 if (__basefield == ios_base::oct)
662 else if (__basefield == ios_base::hex)
664 else if (__basefield == 0)
669 // Stage 3: store results.
671 int __p = sscanf(__xtrc, __conv, &__ld);
673 && static_cast<typename __traits_type::int_type>(__p)
674 != __traits_type::eof())
677 __err |= ios_base::failbit;
683 template<typename _CharT, typename _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
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));
696 // Stage 1: extract and determine the conversion specifier.
697 // Assuming leading zeros eliminated, thus the size of 32 for
699 char __xtrc[32]= {'\0'};
701 _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
703 // Stage 2: convert and store results.
706 void* __vp = reinterpret_cast<void*>(strtoul(__xtrc, &__sanity, __base));
707 if (!(__err & ios_base::failbit)
708 && __sanity != __xtrc && *__sanity == '\0' && errno == 0)
711 __err |= ios_base::failbit;
713 // Reset from hex formatted input
718 // _S_fill is specialized for ostreambuf_iterator, random access iterator.
719 template <typename _CharT, typename _OutIter>
721 _S_fill(_OutIter __s, _CharT __fill, int __padding);
723 template <typename _CharT, typename _RaIter>
725 _S_fill(_RaIter __s, _CharT __fill, int __padding,
726 random_access_iterator_tag)
729 return __s + __padding;
732 template <typename _CharT, typename _OutIter, typename _Tag>
734 _S_fill(_OutIter __s, _CharT __fill, int __padding, _Tag)
736 while (--__padding >= 0) { *__s = __fill; ++__s; }
740 template <typename _CharT, typename _OutIter>
742 _S_fill(_OutIter __s, _CharT __fill, int __padding)
744 return _S_fill(__s, __fill, __padding,
745 iterator_traits<_OutIter>::iterator_category());
748 template <typename _CharT, typename _OutIter>
750 _S_pad_numeric(_OutIter __s, ios_base::fmtflags /*__flags*/,
751 _CharT /*__fill*/, int /*__width*/,
752 _CharT const* /*__first*/, _CharT const* /*__middle*/,
753 _CharT const* /*__last*/)
755 // XXX Not currently done: non streambuf_iterator
759 // Partial specialization for ostreambuf_iterator.
760 template <typename _CharT>
761 ostreambuf_iterator<_CharT>
762 _S_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)
766 typedef ostreambuf_iterator<_CharT> __out_iter;
767 int __padding = __width - (__last - __first);
770 ios_base::fmtflags __aflags = __flags & ios_base::adjustfield;
771 bool __testfield = __padding == 0 || __aflags == ios_base::left
772 || __aflags == ios_base::internal;
774 // This was needlessly complicated.
775 if (__first != __middle)
779 _S_fill(__s, __fill, __padding);
782 copy(__first, __middle, __s);
784 __out_iter __s2 = __s;
786 if (__padding && __aflags != ios_base::left)
788 _S_fill(__s2, __fill, __padding);
791 __out_iter __s3 = copy(__middle, __last, __s2);
793 _S_fill(__s3, __fill, __padding);
797 template <typename _CharT, typename _OutIter>
799 num_put<_CharT, _OutIter>::
800 do_put(iter_type __s, ios_base& __io, char_type __fill, bool __v) const
802 const _Format_cache<_CharT>* __fmt = _Format_cache<_CharT>::_S_get(__io);
803 ios_base::fmtflags __flags = __io.flags();
805 if ((__flags & ios_base::boolalpha) == 0)
807 unsigned long __uv = __v;
808 return _S_format(__s, __io, __fill, false, __uv);
812 const char_type* __first;
813 const char_type* __last;
816 __first = __fmt->_M_truename.data();
817 __last = __first + __fmt->_M_truename.size();
821 __first = __fmt->_M_falsename.data();
822 __last = __first + __fmt->_M_falsename.size();
824 copy(__first, __last, __s);
829 // _S_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>
835 _S_group_digits(_CharT* __s, _CharT __grsep, char const* __grouping,
836 char const* __grend, _CharT const* __first,
837 _CharT const* __last)
839 if (__last - __first > *__grouping)
841 __s = _S_group_digits(__s, __grsep,
842 (__grouping + 1 == __grend ? __grouping : __grouping + 1),
843 __grend, __first, __last - *__grouping);
844 __first = __last - *__grouping;
851 while (__first != __last);
855 template <typename _CharT, typename _OutIter, typename _ValueT>
857 _S_format(_OutIter __s, ios_base& __io, _CharT __fill, bool __neg,
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;
868 ios_base::fmtflags __basefield = (__flags & __io.basefield);
869 _CharT* __sign_end = __front;
870 if (__basefield == ios_base::hex)
872 if (__flags & ios_base::uppercase)
873 __table += 16; // use ABCDEF
875 *--__front = __table[__v & 15];
876 while ((__v >>= 4) != 0);
877 __sign_end = __front;
878 if (__flags & ios_base::showbase)
880 *--__front = __fmt->_S_literals[__fmt->_S_x +
881 ((__flags & ios_base::uppercase) ? 1 : 0)];
882 *--__front = __table[0];
885 else if (__basefield == ios_base::oct)
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;
897 // NB: This is _lots_ faster than using ldiv.
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];
907 // XXX should specialize!
908 if (!__fmt->_M_use_grouping && !__io.width())
909 return copy(__front, __digits + _M_room, __s);
911 if (!__fmt->_M_use_grouping)
912 return _S_pad_numeric(__s, __flags, __fill, __io.width(0),
913 __front, __sign_end, __digits + _M_room);
915 _CharT* __p = __digits;
916 while (__front < __sign_end)
918 const char* __gr = __fmt->_M_grouping.data();
919 __front = _S_group_digits(__p, __fmt->_M_thousands_sep, __gr,
920 __gr + __fmt->_M_grouping.size(), __sign_end, __digits + _M_room);
921 return _S_pad_numeric(__s, __flags, __fill, __io.width(0),
922 __digits, __p, __front);
925 template <typename _CharT, typename _OutIter>
927 num_put<_CharT, _OutIter>::
928 do_put(iter_type __s, ios_base& __io, char_type __fill, long __v) const
930 unsigned long __uv = __v;
937 return _S_format(__s, __io, __fill, __neg, __uv);
940 template <typename _CharT, typename _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 _S_format(__s, __io, __fill, false, __v); }
947 #ifdef _GLIBCPP_USE_LONG_LONG
948 template <typename _CharT, typename _OutIter>
950 num_put<_CharT, _OutIter>::
951 do_put(iter_type __s, ios_base& __b, char_type __fill, long long __v) const
953 unsigned long long __uv = __v;
960 return _S_format(__s, __b, __fill, __neg, __uv);
963 template <typename _CharT, typename _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 _S_format(__s, __io, __fill, false, __v); }
971 // Generic helper function
972 template<typename _CharT, typename _OutIter>
974 _S_output_float(_OutIter __s, ios_base& __io, _CharT __fill,
975 const char* __sptr, size_t __slen)
977 // XXX Not currently done: non streambuf_iterator
981 // Partial specialization for ostreambuf_iterator.
982 template<typename _CharT>
983 static ostreambuf_iterator<_CharT>
984 _S_output_float(ostreambuf_iterator<_CharT> __s, ios_base& __io,
985 _CharT __fill, const char* __sptr, size_t __slen)
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)
996 // [22.2.2.2.2.14]; widen()
997 if (__sptr < __eptr && (*__sptr == '+' || *__sptr == '-'))
999 __s = __ct.widen(*__sptr);
1003 __s = _S_fill(__s, __fill, __padding);
1006 else if (__adjfield != ios_base::left)
1008 __s = _S_fill(__s, __fill, __padding);
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)
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()
1021 __s = __ct.widen(*__sptr);
1023 // [22.2.2.2.2.19] Table 61
1025 _S_fill(__s, __fill, __padding);
1031 _S_build_float_format(ios_base& __io, char* __fptr, char __modifier,
1034 template <typename _CharT, typename _OutIter>
1036 num_put<_CharT, _OutIter>::
1037 do_put(iter_type __s, ios_base& __io, char_type __fill, double __v) const
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];
1047 // Long enough for the max format spec.
1049 if (_S_build_float_format(__io, __fbuf, 0, __prec))
1050 __slen = sprintf(__sbuf, __fbuf, __prec, __v);
1052 __slen = sprintf(__sbuf, __fbuf, __v);
1053 // [22.2.2.2.2] Stages 2-4.
1054 return _S_output_float(__s, __io, __fill, __sbuf, __slen);
1057 template <typename _CharT, typename _OutIter>
1059 num_put<_CharT, _OutIter>::
1060 do_put(iter_type __s, ios_base& __io, char_type __fill,
1061 long double __v) const
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];
1071 // Long enough for the max format spec.
1073 // 'L' as per [22.2.2.2.2] Table 59
1074 if ( _S_build_float_format(__io, __fbuf, 'L', __prec))
1075 __slen = sprintf(__sbuf, __fbuf, __prec, __v);
1077 __slen = sprintf(__sbuf, __fbuf, __v);
1078 // [22.2.2.2.2] Stages 2-4
1079 return _S_output_float(__s, __io, __fill, __sbuf, __slen);
1082 template <typename _CharT, typename _OutIter>
1084 num_put<_CharT, _OutIter>::
1085 do_put(iter_type __s, ios_base& __io, char_type __fill,
1086 const void* __v) const
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));
1094 _OutIter __s2 = _S_format(__s, __io, __fill, false,
1095 reinterpret_cast<unsigned long>(__v));
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;
1112 template<typename _Dummy>
1113 struct _Weekdaynames<char, _Dummy>
1114 { static const char* const _S_names[14]; };
1116 template<typename _Dummy>
1118 _Weekdaynames<char, _Dummy>::_S_names[14] =
1121 "Mon", "Monday", "Tue", "Tuesday", "Wed", "Wednesday",
1122 "Thu", "Thursday", "Fri", "Friday", "Sat", "Saturday"
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]; };
1130 template<typename _Dummy>
1131 const wchar_t* const
1132 _Weekdaynames<wchar_t, _Dummy>::_S_names[14] =
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"
1140 template<typename _CharT, typename _Dummy = int>
1143 template<typename _Dummy>
1144 struct _Monthnames<char,_Dummy>
1145 { static const char* const _S_names[24]; };
1147 template<typename _Dummy>
1149 _Monthnames<char,_Dummy>::_S_names[24] =
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"
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]; };
1162 template<typename _Dummy>
1163 const wchar_t* const
1164 _Monthnames<wchar_t,_Dummy>::_S_names[24] =
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"
1173 template<typename _CharT, typename _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
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];
1185 bool __at_eof = false;
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);
1196 __err |= __io.failbit;
1200 template<typename _CharT, typename _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
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];
1212 bool __at_eof = false;
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);
1223 __err |= __io.failbit;
1228 #endif /* _CPP_BITS_LOCFACETS_TCC */