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/streambuf_iterator.h> // For streambuf_iterators
41 #include <bits/std_cctype.h> // For isspace
42 #include <typeinfo> // For bad_cast
43 #include <bits/std_vector.h>
47 template<typename _Facet>
49 locale::combine(const locale& __other)
51 _Impl* __tmp = new _Impl(*_M_impl, 0);
52 __tmp->_M_replace_facet(__other._M_impl, &_Facet::id);
56 template<typename _CharT, typename _Traits, typename _Alloc>
58 locale::operator()(const basic_string<_CharT, _Traits, _Alloc>& __s1,
59 const basic_string<_CharT, _Traits, _Alloc>& __s2) const
61 typedef std::collate<_CharT> __collate_type;
62 const __collate_type* __fcoll = &use_facet<__collate_type>(*this);
63 return (__fcoll->compare(__s1.data(), __s1.data() + __s1.length(),
64 __s2.data(), __s2.data() + __s2.length()) < 0);
67 template<typename _Facet>
69 use_facet(const locale& __loc)
71 typedef locale::_Impl::__vec_facet __vec_facet;
72 size_t __i = _Facet::id._M_index;
73 __vec_facet* __facet = __loc._M_impl->_M_facets;
74 const locale::facet* __fp = (*__facet)[__i];
75 if (__fp == 0 || __i >= __facet->size())
77 return static_cast<const _Facet&>(*__fp);
80 template<typename _Facet>
82 has_facet(const locale& __loc) throw()
84 typedef locale::_Impl::__vec_facet __vec_facet;
85 size_t __i = _Facet::id._M_index;
86 __vec_facet* __facet = __loc._M_impl->_M_facets;
87 return (__i < __facet->size() && (*__facet)[__i] != 0);
91 // matches input __s against a set of __ntargs strings in __targets,
92 // placing in __matches a vector of indices into __targets which
93 // match, and in __remain the number of such matches. If it hits
94 // end of sequence before it minimizes the set, sets __eof.
95 // Empty strings are never matched.
96 template<typename _InIter, typename _CharT>
98 __match_parallel(_InIter __s, _InIter __end, int __ntargs,
99 const basic_string<_CharT>* __targets,
100 int* __matches, int& __remain, bool& __eof)
102 typedef basic_string<_CharT> __string_type;
104 for (int __ti = 0; __ti < __ntargs; ++__ti)
105 __matches[__ti] = __ti;
111 while (__ti < __remain && __pos == __targets[__matches[__ti]].size())
113 if (__ti == __remain)
115 if (__pos == 0) __remain = 0;
120 bool __matched = false;
121 for (int __ti2 = 0; __ti2 < __remain; )
123 const __string_type& __target = __targets[__matches[__ti2]];
124 if (__pos < __target.size())
126 if (__eof || __target[__pos] != *__s)
128 __matches[__ti2] = __matches[--__remain];
140 for (int __ti3 = 0; __ti3 < __remain;)
142 if (__pos > __targets[__matches[__ti3]].size())
144 __matches[__ti3] = __matches[--__remain];
154 template<typename _CharT>
155 _Format_cache<_CharT>::_Format_cache()
156 : _M_valid(true), _M_use_grouping(false)
160 _Format_cache<char>::_Format_cache();
163 _Format_cache<wchar_t>::_Format_cache();
165 template<typename _CharT>
167 _Format_cache<_CharT>::_M_populate(ios_base& __io)
169 locale __loc = __io.getloc ();
170 numpunct<_CharT> const& __np = use_facet<numpunct<_CharT> >(__loc);
171 _M_truename = __np.truename();
172 _M_falsename = __np.falsename();
173 _M_thousands_sep = __np.thousands_sep();
174 _M_decimal_point = __np.decimal_point();
175 _M_grouping = __np.grouping();
176 _M_use_grouping = _M_grouping.size() != 0 && _M_grouping.data()[0] != 0;
180 // This function is always called via a pointer installed in
181 // an ios_base by ios_base::register_callback.
182 template<typename _CharT>
184 _Format_cache<_CharT>::
185 _S_callback(ios_base::event __ev, ios_base& __ios, int __ix) throw()
187 void*& __p = __ios.pword(__ix);
190 case ios_base::erase_event:
191 delete static_cast<_Format_cache<_CharT>*>(__p);
194 case ios_base::copyfmt_event:
195 // If just stored zero, the callback would get registered again.
197 { __p = new _Format_cache<_CharT>; }
201 case ios_base::imbue_event:
202 static_cast<_Format_cache<_CharT>*>(__p)->_M_valid = false;
207 template<typename _CharT>
208 _Format_cache<_CharT>*
209 _Format_cache<_CharT>::_S_get(ios_base& __ios)
212 _S_pword_ix = ios_base::xalloc(); // XXX MT
213 void*& __p = __ios.pword(_S_pword_ix);
215 // XXX What if pword fails? must check failbit, throw.
216 if (__p == 0) // XXX MT? maybe sentry takes care of it
218 auto_ptr<_Format_cache<_CharT> > __ap(new _Format_cache<_CharT>);
219 __ios.register_callback(&_Format_cache<_CharT>::_S_callback,
221 __p = __ap.release();
223 _Format_cache<_CharT>* __ncp = static_cast<_Format_cache<_CharT>*>(__p);
224 if (!__ncp->_M_valid)
225 __ncp->_M_populate(__ios);
230 // This member function takes an (w)istreambuf_iterator object and
231 // parses it into a generic char array suitable for parsing with
232 // strto[l,ll,f,d]. The thought was to encapsulate the conversion
233 // into this one function, and thus the num_get::do_get member
234 // functions can just adjust for the type of the overloaded
235 // argument and process the char array returned from _M_extract.
236 // Other things were also considered, including a fused
237 // multiply-add loop that would obviate the need for any call to
238 // strto... at all: however, it would b e a bit of a pain, because
239 // you'd have to be able to return either floating or integral
240 // types, etc etc. The current approach seems to be smack dab in
241 // the middle between an unoptimized approach using sscanf, and
242 // some kind of hyper-optimized approach alluded to above.
245 // Need to do partial specialization to account for differences
246 // between character sets. For char, this is pretty
247 // straightforward, but for wchar_t, the conversion to a plain-jane
248 // char type is a bit more involved.
249 template<typename _CharT, typename _InIter>
251 num_get<_CharT, _InIter>::
252 _M_extract(_InIter /*__beg*/, _InIter /*__end*/, ios_base& /*__io*/,
253 ios_base::iostate& /*__err*/, char* /*__xtrc*/,
254 int& /*__base*/, bool /*__fp*/) const
256 // XXX Not currently done: need to expand upon char version below.
261 num_get<char, istreambuf_iterator<char> >::
262 _M_extract(istreambuf_iterator<char> __beg,
263 istreambuf_iterator<char> __end, ios_base& __io,
264 ios_base::iostate& __err, char* __xtrc, int& __base,
267 #ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
268 // NB: This is an unresolved library defect #17
269 template<typename _CharT, typename _InIter>
271 num_get<_CharT, _InIter>::
272 do_get(iter_type __beg, iter_type __end, ios_base& __io,
273 ios_base::iostate& __err, bool& __v) const
275 // Parse bool values as long
276 if (!(__io.flags() & ios_base::boolalpha))
278 // NB: We can't just call do_get(long) here, as it might
279 // refer to a derived class.
281 // Stage 1: extract and determine the conversion specifier.
282 // Assuming leading zeros eliminated, thus the size of 32 for
284 char __xtrc[32] = {'\0'};
286 _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
288 // Stage 2: convert and store results.
291 long __l = strtol(__xtrc, &__sanity, __base);
292 if (!(__err & ios_base::failbit)
294 && __sanity != __xtrc && *__sanity == '\0' && errno == 0)
297 __err |= ios_base::failbit;
300 // Parse bool values as alphanumeric
303 typedef _Format_cache<char_type> __fcache_type;
304 __fcache_type* __fmt = __fcache_type::_S_get(__io);
305 const char_type* __true = __fmt->_M_truename.c_str();
306 const char_type* __false = __fmt->_M_falsename.c_str();
307 const size_t __truelen = __traits_type::length(__true) - 1;
308 const size_t __falselen = __traits_type::length(__false) - 1;
310 for (size_t __pos = 0; __beg != __end; ++__pos)
312 char_type __c = *__beg++;
313 bool __testf = __c == __false[__pos];
314 bool __testt = __c == __true[__pos];
315 if (!(__testf || __testt))
317 __err |= ios_base::failbit;
320 else if (__testf && __pos == __falselen)
325 else if (__testt && __pos == __truelen)
332 __err |= ios_base::eofbit;
339 #ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
340 template<typename _CharT, typename _InIter>
342 num_get<_CharT, _InIter>::
343 do_get(iter_type __beg, iter_type __end, ios_base& __io,
344 ios_base::iostate& __err, short& __v) const
346 // Stage 1: extract and determine the conversion specifier.
347 // Assuming leading zeros eliminated, thus the size of 32 for
349 char __xtrc[32]= {'\0'};
351 _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
353 // Stage 2: convert and store results.
356 long __l = strtol(__xtrc, &__sanity, __base);
357 if (!(__err & ios_base::failbit)
358 && __sanity != __xtrc && *__sanity == '\0' && errno == 0
359 && __l >= SHRT_MIN && __l <= SHRT_MAX)
360 __v = static_cast<short>(__l);
362 __err |= ios_base::failbit;
367 template<typename _CharT, typename _InIter>
369 num_get<_CharT, _InIter>::
370 do_get(iter_type __beg, iter_type __end, ios_base& __io,
371 ios_base::iostate& __err, int& __v) const
373 // Stage 1: extract and determine the conversion specifier.
374 // Assuming leading zeros eliminated, thus the size of 32 for
376 char __xtrc[32] = {'\0'};
378 _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
380 // Stage 2: convert and store results.
383 long __l = strtol(__xtrc, &__sanity, __base);
384 if (!(__err & ios_base::failbit)
385 && __sanity != __xtrc && *__sanity == '\0' && errno == 0
386 && __l >= INT_MIN && __l <= INT_MAX)
387 __v = static_cast<int>(__l);
389 __err |= ios_base::failbit;
395 template<typename _CharT, typename _InIter>
397 num_get<_CharT, _InIter>::
398 do_get(iter_type __beg, iter_type __end, ios_base& __io,
399 ios_base::iostate& __err, long& __v) const
401 // Stage 1: extract and determine the conversion specifier.
402 // Assuming leading zeros eliminated, thus the size of 32 for
404 char __xtrc[32]= {'\0'};
406 _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
408 // Stage 2: convert and store results.
411 long __l = strtol(__xtrc, &__sanity, __base);
412 if (!(__err & ios_base::failbit)
413 && __sanity != __xtrc && *__sanity == '\0' && errno == 0)
416 __err |= ios_base::failbit;
421 #ifdef _GLIBCPP_USE_LONG_LONG
422 template<typename _CharT, typename _InIter>
424 num_get<_CharT, _InIter>::
425 do_get(iter_type __beg, iter_type __end, ios_base& __io,
426 ios_base::iostate& __err, long long& __v) const
428 // Stage 1: extract and determine the conversion specifier.
429 // Assuming leading zeros eliminated, thus the size of 32 for
431 char __xtrc[32]= {'\0'};
433 _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
435 // Stage 2: convert and store results.
438 long long __ll = strtoll(__xtrc, &__sanity, __base);
439 if (!(__err & ios_base::failbit)
440 && __sanity != __xtrc && *__sanity == '\0' && errno == 0)
443 __err |= ios_base::failbit;
449 template<typename _CharT, typename _InIter>
451 num_get<_CharT, _InIter>::
452 do_get(iter_type __beg, iter_type __end, ios_base& __io,
453 ios_base::iostate& __err, unsigned short& __v) const
455 // Stage 1: extract and determine the conversion specifier.
456 // Assuming leading zeros eliminated, thus the size of 32 for
458 char __xtrc[32]= {'\0'};
460 _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
462 // Stage 2: convert and store results.
465 unsigned long __ul = strtoul(__xtrc, &__sanity, __base);
466 if (!(__err & ios_base::failbit)
467 && __sanity != __xtrc && *__sanity == '\0' && errno == 0
468 && __ul <= USHRT_MAX)
469 __v = static_cast<unsigned short>(__ul);
471 __err |= ios_base::failbit;
476 template<typename _CharT, typename _InIter>
478 num_get<_CharT, _InIter>::
479 do_get(iter_type __beg, iter_type __end, ios_base& __io,
480 ios_base::iostate& __err, unsigned int& __v) const
482 // Stage 1: extract and determine the conversion specifier.
483 // Assuming leading zeros eliminated, thus the size of 32 for
485 char __xtrc[32]= {'\0'};
487 _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
489 // Stage 2: convert and store results.
492 unsigned long __ul = strtoul(__xtrc, &__sanity, __base);
493 if (!(__err & ios_base::failbit)
494 && __sanity != __xtrc && *__sanity == '\0' && errno == 0
496 __v = static_cast<unsigned int>(__ul);
498 __err |= ios_base::failbit;
503 template<typename _CharT, typename _InIter>
505 num_get<_CharT, _InIter>::
506 do_get(iter_type __beg, iter_type __end, ios_base& __io,
507 ios_base::iostate& __err, unsigned long& __v) const
509 // Stage 1: extract and determine the conversion specifier.
510 // Assuming leading zeros eliminated, thus the size of 32 for
512 char __xtrc[32] = {'\0'};
514 _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
516 // Stage 2: convert and store results.
519 unsigned long __ul = strtoul(__xtrc, &__sanity, __base);
520 if (!(__err & ios_base::failbit)
521 && __sanity != __xtrc && *__sanity == '\0' && errno == 0)
524 __err |= ios_base::failbit;
529 #ifdef _GLIBCPP_USE_LONG_LONG
530 template<typename _CharT, typename _InIter>
532 num_get<_CharT, _InIter>::
533 do_get(iter_type __beg, iter_type __end, ios_base& __io,
534 ios_base::iostate& __err, unsigned long long& __v) const
536 // Stage 1: extract and determine the conversion specifier.
537 // Assuming leading zeros eliminated, thus the size of 32 for
539 char __xtrc[32]= {'\0'};
541 _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
543 // Stage 2: convert and store results.
546 unsigned long long __ull = strtoull(__xtrc, &__sanity, __base);
547 if (!(__err & ios_base::failbit)
548 && __sanity != __xtrc && *__sanity == '\0' && errno == 0)
551 __err |= ios_base::failbit;
557 template<typename _CharT, typename _InIter>
559 num_get<_CharT, _InIter>::
560 do_get(iter_type __beg, iter_type __end, ios_base& __io,
561 ios_base::iostate& __err, float& __v) const
563 // Stage 1: extract and determine the conversion specifier.
564 // Assuming leading zeros eliminated, thus the size of 256 for
565 // floating-point types.
566 char __xtrc[32]= {'\0'};
568 _M_extract(__beg, __end, __io, __err, __xtrc, __base, true);
570 // Stage 2: convert and store results.
573 #ifdef _GLIBCPP_USE_C99
574 float __f = strtof(__xtrc, &__sanity);
576 float __f = static_cast<float>(strtod(__xtrc, &__sanity));
578 if (!(__err & ios_base::failbit)
579 && __sanity != __xtrc && *__sanity == '\0' && errno == 0)
582 __err |= ios_base::failbit;
587 template<typename _CharT, typename _InIter>
589 num_get<_CharT, _InIter>::
590 do_get(iter_type __beg, iter_type __end, ios_base& __io,
591 ios_base::iostate& __err, double& __v) const
593 // Stage 1: extract and determine the conversion specifier.
594 // Assuming leading zeros eliminated, thus the size of 256 for
595 // floating-point types.
596 char __xtrc[32]= {'\0'};
598 _M_extract(__beg, __end, __io, __err, __xtrc, __base, true);
600 // Stage 2: convert and store results.
603 double __d = strtod(__xtrc, &__sanity);
604 if (!(__err & ios_base::failbit)
605 && __sanity != __xtrc && *__sanity == '\0' && errno == 0)
608 __err |= ios_base::failbit;
613 #if defined(_GLIBCPP_USE_C99) && !defined(__hpux)
614 template<typename _CharT, typename _InIter>
616 num_get<_CharT, _InIter>::
617 do_get(iter_type __beg, iter_type __end, ios_base& __io,
618 ios_base::iostate& __err, long double& __v) const
620 // Stage 1: extract and determine the conversion specifier.
621 // Assuming leading zeros eliminated, thus the size of 256 for
622 // floating-point types.
623 char __xtrc[32]= {'\0'};
625 _M_extract(__beg, __end, __io, __err, __xtrc, __base, true);
627 // Stage 2: convert and store results.
630 long double __ld = strtold(__xtrc, &__sanity);
631 if (!(__err & ios_base::failbit)
632 && __sanity != __xtrc && *__sanity == '\0' && errno == 0)
635 __err |= ios_base::failbit;
640 template<typename _CharT, typename _InIter>
642 num_get<_CharT, _InIter>::
643 do_get(iter_type __beg, iter_type __end, ios_base& __io,
644 ios_base::iostate& __err, long double& __v) const
647 char __xtrc[32]= {'\0'};
649 _M_extract(__beg, __end, __io, __err, __xtrc, __base, true);
651 // Stage 2: determine a conversion specifier.
652 ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield;
654 if (__basefield == ios_base::oct)
656 else if (__basefield == ios_base::hex)
658 else if (__basefield == 0)
663 // Stage 3: store results.
665 int __p = sscanf(__xtrc, __conv, &__ld);
667 && static_cast<typename __traits_type::int_type>(__p)
668 != __traits_type::eof())
671 __err |= ios_base::failbit;
677 template<typename _CharT, typename _InIter>
679 num_get<_CharT, _InIter>::
680 do_get(iter_type __beg, iter_type __end, ios_base& __io,
681 ios_base::iostate& __err, void*& __v) const
683 // Prepare for hex formatted input
684 typedef ios_base::fmtflags fmtflags;
685 fmtflags __fmt = __io.flags();
686 fmtflags __fmtmask = ~(ios_base::showpos | ios_base::basefield
687 | ios_base::uppercase | ios_base::internal);
688 __io.flags(__fmt & __fmtmask | (ios_base::hex | ios_base::showbase));
690 // Stage 1: extract and determine the conversion specifier.
691 // Assuming leading zeros eliminated, thus the size of 32 for
693 char __xtrc[32]= {'\0'};
695 _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
697 // Stage 2: convert and store results.
700 void* __vp = reinterpret_cast<void*>(strtoul(__xtrc, &__sanity, __base));
701 if (!(__err & ios_base::failbit)
702 && __sanity != __xtrc && *__sanity == '\0' && errno == 0)
705 __err |= ios_base::failbit;
707 // Reset from hex formatted input
712 // __pad is specialized for ostreambuf_iterator, random access iterator.
713 template <typename _CharT, typename _OutIter>
715 __pad(_OutIter __s, _CharT __fill, int __padding);
717 template <typename _CharT, typename _RaIter>
719 __pad(_RaIter __s, _CharT __fill, int __padding,
720 random_access_iterator_tag)
723 return __s + __padding;
726 template <typename _CharT, typename _OutIter, typename _Tag>
728 __pad(_OutIter __s, _CharT __fill, int __padding, _Tag)
730 while (--__padding >= 0) { *__s = __fill; ++__s; }
734 template <typename _CharT, typename _OutIter>
736 __pad(_OutIter __s, _CharT __fill, int __padding)
738 return __pad(__s, __fill, __padding,
739 typename iterator_traits<_OutIter>::iterator_category());
742 template <typename _CharT, typename _OutIter>
744 __pad_numeric(_OutIter __s, ios_base::fmtflags /*__flags*/,
745 _CharT /*__fill*/, int /*__width*/,
746 _CharT const* /*__first*/, _CharT const* /*__middle*/,
747 _CharT const* /*__last*/)
749 // XXX Not currently done: non streambuf_iterator
753 // Partial specialization for ostreambuf_iterator.
754 template <typename _CharT>
755 ostreambuf_iterator<_CharT>
756 __pad_numeric(ostreambuf_iterator<_CharT> __s, ios_base::fmtflags __flags,
757 _CharT __fill, int __width, _CharT const* __first,
758 _CharT const* __middle, _CharT const* __last)
760 typedef ostreambuf_iterator<_CharT> __out_iter;
761 int __padding = __width - (__last - __first);
764 ios_base::fmtflags __aflags = __flags & ios_base::adjustfield;
765 bool __testfield = __padding == 0 || __aflags == ios_base::left
766 || __aflags == ios_base::internal;
768 // This was needlessly complicated.
769 if (__first != __middle)
773 __pad(__s, __fill, __padding);
776 copy(__first, __middle, __s);
778 __out_iter __s2 = __s;
780 if (__padding && __aflags != ios_base::left)
782 __pad(__s2, __fill, __padding);
785 __out_iter __s3 = copy(__middle, __last, __s2);
787 __pad(__s3, __fill, __padding);
791 template <typename _CharT, typename _OutIter>
793 num_put<_CharT, _OutIter>::
794 do_put(iter_type __s, ios_base& __io, char_type __fill, bool __v) const
796 const _Format_cache<_CharT>* __fmt = _Format_cache<_CharT>::_S_get(__io);
797 ios_base::fmtflags __flags = __io.flags();
799 if ((__flags & ios_base::boolalpha) == 0)
801 unsigned long __uv = __v;
802 return __output_integer(__s, __io, __fill, false, __uv);
806 const char_type* __first;
807 const char_type* __last;
810 __first = __fmt->_M_truename.data();
811 __last = __first + __fmt->_M_truename.size();
815 __first = __fmt->_M_falsename.data();
816 __last = __first + __fmt->_M_falsename.size();
818 copy(__first, __last, __s);
823 // __group_digits inserts "group separator" characters into an array
824 // of characters. It's recursive, one iteration per group. It moves
825 // the characters in the buffer this way: "xxxx12345" -> "12,345xxx".
826 // Call this only with __grouping != __grend.
827 template <typename _CharT>
829 __group_digits(_CharT* __s, _CharT __grsep, char const* __grouping,
830 char const* __grend, _CharT const* __first,
831 _CharT const* __last)
833 if (__last - __first > *__grouping)
835 __s = __group_digits(__s, __grsep,
836 (__grouping + 1 == __grend ? __grouping : __grouping + 1),
837 __grend, __first, __last - *__grouping);
838 __first = __last - *__grouping;
845 while (__first != __last);
849 template <typename _CharT, typename _OutIter, typename _ValueT>
851 __output_integer(_OutIter __s, ios_base& __io, _CharT __fill, bool __neg,
854 // Leave room for "+/-," "0x," and commas.
855 const long _M_room = numeric_limits<_ValueT>::digits10 * 2 + 4;
856 _CharT __digits[_M_room];
857 _CharT* __front = __digits + _M_room;
858 ios_base::fmtflags __flags = __io.flags();
859 const _Format_cache<_CharT>* __fmt = _Format_cache<_CharT>::_S_get(__io);
860 char const* __table = __fmt->_S_literals + __fmt->_S_digits;
862 ios_base::fmtflags __basefield = (__flags & __io.basefield);
863 _CharT* __sign_end = __front;
864 if (__basefield == ios_base::hex)
866 if (__flags & ios_base::uppercase)
867 __table += 16; // use ABCDEF
869 *--__front = __table[__v & 15];
870 while ((__v >>= 4) != 0);
871 __sign_end = __front;
872 if (__flags & ios_base::showbase)
874 *--__front = __fmt->_S_literals[__fmt->_S_x +
875 ((__flags & ios_base::uppercase) ? 1 : 0)];
876 *--__front = __table[0];
879 else if (__basefield == ios_base::oct)
882 *--__front = __table[__v & 7];
883 while ((__v >>= 3) != 0);
884 if (__flags & ios_base::showbase
885 && static_cast<char>(*__front) != __table[0])
886 *--__front = __table[0];
887 __sign_end = __front;
891 // NB: This is _lots_ faster than using ldiv.
893 *--__front = __table[__v % 10];
894 while ((__v /= 10) != 0);
895 __sign_end = __front;
896 // NB: ios_base:hex || ios_base::oct assumed to be unsigned.
897 if (__neg || (__flags & ios_base::showpos))
898 *--__front = __fmt->_S_literals[__fmt->_S_plus - __neg];
901 // XXX should specialize!
902 if (!__fmt->_M_use_grouping && !__io.width())
903 return copy(__front, __digits + _M_room, __s);
905 if (!__fmt->_M_use_grouping)
906 return __pad_numeric(__s, __flags, __fill, __io.width(0),
907 __front, __sign_end, __digits + _M_room);
909 _CharT* __p = __digits;
910 while (__front < __sign_end)
912 const char* __gr = __fmt->_M_grouping.data();
913 __front = __group_digits(__p, __fmt->_M_thousands_sep, __gr,
914 __gr + __fmt->_M_grouping.size(), __sign_end, __digits + _M_room);
915 return __pad_numeric(__s, __flags, __fill, __io.width(0),
916 __digits, __p, __front);
919 template <typename _CharT, typename _OutIter>
921 num_put<_CharT, _OutIter>::
922 do_put(iter_type __s, ios_base& __io, char_type __fill, long __v) const
924 unsigned long __uv = __v;
931 return __output_integer(__s, __io, __fill, __neg, __uv);
934 template <typename _CharT, typename _OutIter>
936 num_put<_CharT, _OutIter>::
937 do_put(iter_type __s, ios_base& __io, char_type __fill,
938 unsigned long __v) const
939 { return __output_integer(__s, __io, __fill, false, __v); }
941 #ifdef _GLIBCPP_USE_LONG_LONG
942 template <typename _CharT, typename _OutIter>
944 num_put<_CharT, _OutIter>::
945 do_put(iter_type __s, ios_base& __b, char_type __fill, long long __v) const
947 unsigned long long __uv = __v;
954 return __output_integer(__s, __b, __fill, __neg, __uv);
957 template <typename _CharT, typename _OutIter>
959 num_put<_CharT, _OutIter>::
960 do_put(iter_type __s, ios_base& __io, char_type __fill,
961 unsigned long long __v) const
962 { return __output_integer(__s, __io, __fill, false, __v); }
965 // Generic helper function
966 template<typename _CharT, typename _Traits, typename _OutIter>
968 __output_float(_OutIter __s, ios_base& __io, _CharT __fill,
969 const char* __sptr, size_t __slen)
971 // XXX Not currently done: non streambuf_iterator
975 // Partial specialization for ostreambuf_iterator.
976 template<typename _CharT, typename _Traits>
977 ostreambuf_iterator<_CharT, _Traits>
978 __output_float(ostreambuf_iterator<_CharT, _Traits> __s, ios_base& __io,
979 _CharT __fill, const char* __sptr, size_t __slen)
981 size_t __padding = __io.width() > streamsize(__slen) ?
982 __io.width() -__slen : 0;
983 locale __loc = __io.getloc();
984 ctype<_CharT> const& __ct = use_facet<ctype<_CharT> >(__loc);
985 ios_base::fmtflags __adjfield = __io.flags() & ios_base::adjustfield;
986 const char* const __eptr = __sptr + __slen;
987 // [22.2.2.2.2.19] Table 61
988 if (__adjfield == ios_base::internal)
990 // [22.2.2.2.2.14]; widen()
991 if (__sptr < __eptr && (*__sptr == '+' || *__sptr == '-'))
993 __s = __ct.widen(*__sptr);
997 __s = __pad(__s, __fill, __padding);
1000 else if (__adjfield != ios_base::left)
1002 __s = __pad(__s, __fill, __padding);
1005 // the "C" locale decimal character
1006 char __decimal_point = *(localeconv()->decimal_point);
1007 const _Format_cache<_CharT>* __fmt = _Format_cache<_CharT>::_S_get(__io);
1008 for (; __sptr != __eptr; ++__s, ++__sptr)
1010 // [22.2.2.2.2.17]; decimal point conversion
1011 if (*__sptr == __decimal_point)
1012 __s = __fmt->_M_decimal_point;
1013 // [22.2.2.2.2.14]; widen()
1015 __s = __ct.widen(*__sptr);
1017 // [22.2.2.2.2.19] Table 61
1019 __pad(__s, __fill, __padding);
1025 __build_float_format(ios_base& __io, char* __fptr, char __modifier,
1028 template <typename _CharT, typename _OutIter>
1030 num_put<_CharT, _OutIter>::
1031 do_put(iter_type __s, ios_base& __io, char_type __fill, double __v) const
1033 const streamsize __max_prec = numeric_limits<double>::digits10 + 3;
1034 streamsize __prec = __io.precision();
1035 // Protect against sprintf() buffer overflows.
1036 if (__prec > __max_prec)
1037 __prec = __max_prec;
1038 // The *2 provides for signs, exp, 'E', and pad.
1039 char __sbuf[__max_prec * 2];
1041 // Long enough for the max format spec.
1043 if (__build_float_format(__io, __fbuf, 0, __prec))
1044 __slen = sprintf(__sbuf, __fbuf, __prec, __v);
1046 __slen = sprintf(__sbuf, __fbuf, __v);
1047 // [22.2.2.2.2] Stages 2-4.
1048 return __output_float(__s, __io, __fill, __sbuf, __slen);
1051 template <typename _CharT, typename _OutIter>
1053 num_put<_CharT, _OutIter>::
1054 do_put(iter_type __s, ios_base& __io, char_type __fill,
1055 long double __v) const
1057 const streamsize __max_prec = numeric_limits<long double>::digits10 + 3;
1058 streamsize __prec = __io.precision();
1059 // Protect against sprintf() buffer overflows.
1060 if (__prec > __max_prec)
1061 __prec = __max_prec;
1062 // The *2 provides for signs, exp, 'E', and pad.
1063 char __sbuf[__max_prec * 2];
1065 // Long enough for the max format spec.
1067 // 'L' as per [22.2.2.2.2] Table 59
1068 if (__build_float_format(__io, __fbuf, 'L', __prec))
1069 __slen = sprintf(__sbuf, __fbuf, __prec, __v);
1071 __slen = sprintf(__sbuf, __fbuf, __v);
1072 // [22.2.2.2.2] Stages 2-4
1073 return __output_float(__s, __io, __fill, __sbuf, __slen);
1076 template <typename _CharT, typename _OutIter>
1078 num_put<_CharT, _OutIter>::
1079 do_put(iter_type __s, ios_base& __io, char_type __fill,
1080 const void* __v) const
1082 typedef ios_base::fmtflags fmtflags;
1083 fmtflags __fmt = __io.flags();
1084 fmtflags __fmtmask = ~(ios_base::showpos | ios_base::basefield
1085 | ios_base::uppercase | ios_base::internal);
1086 __io.flags(__fmt & __fmtmask | (ios_base::hex | ios_base::showbase));
1088 _OutIter __s2 = __output_integer(__s, __io, __fill, false,
1089 reinterpret_cast<unsigned long>(__v));
1095 __throw_exception_again;
1099 // Support for time_get:
1100 // Note that these partial specializations could, and maybe should,
1101 // be changed to full specializations (by eliminating the _Dummy
1102 // argument) and moved to a .cc file.
1103 template<typename _CharT, typename _Dummy = int>
1104 struct _Weekdaynames;
1106 template<typename _Dummy>
1107 struct _Weekdaynames<char, _Dummy>
1108 { static const char* const _S_names[14]; };
1110 template<typename _Dummy>
1112 _Weekdaynames<char, _Dummy>::_S_names[14] =
1115 "Mon", "Monday", "Tue", "Tuesday", "Wed", "Wednesday",
1116 "Thu", "Thursday", "Fri", "Friday", "Sat", "Saturday"
1119 #ifdef _GLIBCPP_USE_WCHAR_T
1120 template<typename _Dummy>
1121 struct _Weekdaynames<wchar_t, _Dummy>
1122 { static const wchar_t* const _S_names[14]; };
1124 template<typename _Dummy>
1125 const wchar_t* const
1126 _Weekdaynames<wchar_t, _Dummy>::_S_names[14] =
1129 L"Mon", L"Monday", L"Tue", L"Tuesday", L"Wed", L"Wednesday",
1130 L"Thu", L"Thursday", L"Fri", L"Friday", L"Sat", L"Saturday"
1134 template<typename _CharT, typename _Dummy = int>
1137 template<typename _Dummy>
1138 struct _Monthnames<char,_Dummy>
1139 { static const char* const _S_names[24]; };
1141 template<typename _Dummy>
1143 _Monthnames<char,_Dummy>::_S_names[24] =
1145 "Jan", "January", "Feb", "February", "Mar", "March",
1146 "Apr", "April", "May", "May", "Jun", "June",
1147 "Jul", "July", "Aug", "August", "Sep", "September",
1148 "Oct", "October", "Nov", "November", "Dec", "December"
1151 #ifdef _GLIBCPP_USE_WCHAR_T
1152 template<typename _Dummy>
1153 struct _Monthnames<wchar_t, _Dummy>
1154 { static const wchar_t* const _S_names[24]; };
1156 template<typename _Dummy>
1157 const wchar_t* const
1158 _Monthnames<wchar_t,_Dummy>::_S_names[24] =
1160 L"Jan", L"January", L"Feb", L"February", L"Mar", L"March",
1161 L"Apr", L"April", L"May", L"May", L"Jun", L"June",
1162 L"Jul", L"July", L"Aug", L"August", L"Sep", L"September",
1163 L"Oct", L"October", L"Nov", L"November", L"Dec", L"December"
1167 template<typename _CharT, typename _InIter>
1169 time_get<_CharT, _InIter>::
1170 do_get_weekday(iter_type __s, iter_type __end,
1171 ios_base& __io, ios_base::iostate& __err, tm* __t) const
1175 _M_daynames = new basic_string<_CharT>[14];
1176 for (int __i = 0; __i < 14; ++__i)
1177 _M_daynames[__i] = _Weekdaynames<_CharT>::_S_names[__i];
1179 bool __at_eof = false;
1182 iter_type __out = __match_parallel(__s, __end, 14, _M_daynames,
1183 __matches, __remain, __at_eof);
1184 __err = ios_base::iostate(0);
1185 if (__at_eof) __err |= __io.eofbit;
1186 if (__remain == 1 ||
1187 __remain == 2 && (__matches[0]>>1) == (__matches[1]>>1))
1188 __t->tm_wday = (__matches[0]>>1);
1190 __err |= __io.failbit;
1194 template<typename _CharT, typename _InIter>
1196 time_get<_CharT, _InIter>::
1197 do_get_monthname(iter_type __s, iter_type __end,
1198 ios_base& __io, ios_base::iostate& __err, tm* __t) const
1202 _M_monthnames = new basic_string<_CharT>[24];
1203 for (int __i = 0; __i < 24; ++__i)
1204 _M_monthnames[__i] = _Monthnames<_CharT>::_S_names[__i];
1206 bool __at_eof = false;
1209 iter_type __out = __match_parallel( __s, __end, 24, _M_monthnames,
1210 __matches, __remain, __at_eof);
1211 __err = ios_base::iostate(0);
1212 if (__at_eof) __err |= __io.eofbit;
1213 if (__remain == 1 ||
1214 __remain == 2 && (__matches[0]>>1) == (__matches[1]>>1))
1215 __t->tm_mon = (__matches[0]>>1);
1217 __err |= __io.failbit;
1222 #endif /* _CPP_BITS_LOCFACETS_TCC */