1 // Locale support -*- C++ -*-
3 // Copyright (C) 1997, 1998, 1999, 2000 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 <bits/std_vector.h>
46 template<typename _Facet>
48 locale::combine(const locale& __other)
51 __copy._M_impl->_M_replace_facet(__other._M_impl, &_Facet::id);
52 __copy._M_impl->_M_has_name = false;
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 // 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);
69 template<typename _Facet>
71 use_facet(const locale& __loc)
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);
83 template<typename _Facet>
85 has_facet(const locale& __loc) throw()
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);
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>
102 __match_parallel(_InIter __s, _InIter __end, int __ntargs,
103 const basic_string<_CharT>* __targets,
104 int* __matches, int& __remain, bool& __eof)
106 typedef basic_string<_CharT> __string_type;
108 for (int __ti = 0; __ti < __ntargs; ++__ti)
109 __matches[__ti] = __ti;
116 for (;__ti < __remain &&
117 __pos == __targets[__matches[__ti]].size(); ++__ti)
119 if (__ti == __remain)
121 if (__pos == 0) __remain = 0;
127 bool __matched = false;
128 for (int __ti = 0; __ti < __remain; )
130 const __string_type& __target = __targets[__matches[__ti]];
131 if (__pos < __target.size())
133 if (__eof || __target[__pos] != *__s)
135 __matches[__ti] = __matches[--__remain];
147 for (int __ti = 0; __ti < __remain;)
149 if (__pos > __targets[__matches[__ti]].size())
151 __matches[__ti] = __matches[--__remain];
161 template<typename _CharT>
162 locale::id ctype<_CharT>::id;
164 template<typename _CharT>
165 int _Format_cache<_CharT>::_S_pword_ix;
167 template<typename _CharT>
168 const char _Format_cache<_CharT>::
169 _S_literals[] = "-+xX0123456789abcdef0123456789ABCDEF";
171 template<typename _CharT>
172 _Format_cache<_CharT>::_Format_cache()
173 : _M_valid(true), _M_use_grouping(false)
177 _Format_cache<char>::_Format_cache();
180 _Format_cache<wchar_t>::_Format_cache();
182 template<typename _CharT>
184 _Format_cache<_CharT>::_M_populate(ios_base& __io)
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;
197 // This function is always called via a pointer installed in
198 // an ios_base by ios_base::register_callback.
199 template<typename _CharT>
201 _Format_cache<_CharT>::
202 _S_callback(ios_base::event __ev, ios_base& __ios, int __ix) throw()
204 void*& __p = __ios.pword(__ix);
207 case ios_base::erase_event:
208 delete static_cast<_Format_cache<_CharT>*> (__p); __p = 0;
210 case ios_base::copyfmt_event:
211 // If just stored zero, the callback would get registered again.
213 __p = new _Format_cache<_CharT>;
218 case ios_base::imbue_event:
219 static_cast<_Format_cache<_CharT>*>(__p)->_M_valid = false;
224 template<typename _CharT>
225 _Format_cache<_CharT>*
226 _Format_cache<_CharT>::_S_get(ios_base& __ios)
229 _S_pword_ix = ios_base::xalloc(); // XXX MT
230 void*& __p = __ios.pword(_S_pword_ix);
232 // XXX What if pword fails? must check failbit, throw.
233 if (__p == 0) // XXX MT? maybe sentry takes care of it
235 auto_ptr<_Format_cache<_CharT> > __ap(new _Format_cache<_CharT>);
236 __ios.register_callback(&_Format_cache<_CharT>::_S_callback,
238 __p = __ap.release();
240 _Format_cache<_CharT>* __ncp = static_cast<_Format_cache<_CharT>*>(__p);
241 if (!__ncp->_M_valid)
242 __ncp->_M_populate(__ios);
247 template<typename _CharT, typename _InIter>
248 locale::id num_get<_CharT, _InIter>::id;
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.
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>
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
276 // XXX Not currently done: need to expand upon char version below.
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,
287 #ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
288 // NB: This is an unresolved library defect #17
289 template<typename _CharT, typename _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
295 // Parse bool values as long
296 if (!(__io.flags() & ios_base::boolalpha))
298 // NB: We can't just call do_get(long) here, as it might
299 // refer to a derived class.
301 // Stage 1: extract and determine the conversion specifier.
302 // Assuming leading zeros eliminated, thus the size of 32 for
304 char __xtrc[32] = {'\0'};
306 _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
308 // Stage 2: convert and store results.
311 long __l = strtol(__xtrc, &__sanity, __base);
312 if (!(__err & ios_base::failbit)
314 && __sanity != __xtrc && *__sanity == '\0' && errno == 0)
317 __err |= ios_base::failbit;
320 // Parse bool values as alphanumeric
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;
330 for (size_t __pos = 0; __beg != __end; ++__pos)
332 char_type __c = *__beg++;
333 bool __testf = __c == __false[__pos];
334 bool __testt = __c == __true[__pos];
335 if (!(__testf || __testt))
337 __err |= ios_base::failbit;
340 else if (__testf && __pos == __falselen)
345 else if (__testt && __pos == __truelen)
352 __err |= ios_base::eofbit;
359 #ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
360 template<typename _CharT, typename _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
366 // Stage 1: extract and determine the conversion specifier.
367 // Assuming leading zeros eliminated, thus the size of 32 for
369 char __xtrc[32]= {'\0'};
371 _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
373 // Stage 2: convert and store results.
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);
382 __err |= ios_base::failbit;
387 template<typename _CharT, typename _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
393 // Stage 1: extract and determine the conversion specifier.
394 // Assuming leading zeros eliminated, thus the size of 32 for
396 char __xtrc[32] = {'\0'};
398 _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
400 // Stage 2: convert and store results.
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);
409 __err |= ios_base::failbit;
415 template<typename _CharT, typename _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
421 // Stage 1: extract and determine the conversion specifier.
422 // Assuming leading zeros eliminated, thus the size of 32 for
424 char __xtrc[32]= {'\0'};
426 _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
428 // Stage 2: convert and store results.
431 long __l = strtol(__xtrc, &__sanity, __base);
432 if (!(__err & ios_base::failbit)
433 && __sanity != __xtrc && *__sanity == '\0' && errno == 0)
436 __err |= ios_base::failbit;
441 #ifdef _GLIBCPP_USE_LONG_LONG
442 template<typename _CharT, typename _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
448 // Stage 1: extract and determine the conversion specifier.
449 // Assuming leading zeros eliminated, thus the size of 32 for
451 char __xtrc[32]= {'\0'};
453 _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
455 // Stage 2: convert and store results.
458 long long __ll = strtoll(__xtrc, &__sanity, __base);
459 if (!(__err & ios_base::failbit)
460 && __sanity != __xtrc && *__sanity == '\0' && errno == 0)
463 __err |= ios_base::failbit;
469 template<typename _CharT, typename _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
475 // Stage 1: extract and determine the conversion specifier.
476 // Assuming leading zeros eliminated, thus the size of 32 for
478 char __xtrc[32]= {'\0'};
480 _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
482 // Stage 2: convert and store results.
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);
491 __err |= ios_base::failbit;
496 template<typename _CharT, typename _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
502 // Stage 1: extract and determine the conversion specifier.
503 // Assuming leading zeros eliminated, thus the size of 32 for
505 char __xtrc[32]= {'\0'};
507 _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
509 // Stage 2: convert and store results.
512 unsigned long __ul = strtoul(__xtrc, &__sanity, __base);
513 if (!(__err & ios_base::failbit)
514 && __sanity != __xtrc && *__sanity == '\0' && errno == 0
516 __v = static_cast<unsigned int>(__ul);
518 __err |= ios_base::failbit;
523 template<typename _CharT, typename _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
529 // Stage 1: extract and determine the conversion specifier.
530 // Assuming leading zeros eliminated, thus the size of 32 for
532 char __xtrc[32] = {'\0'};
534 _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
536 // Stage 2: convert and store results.
539 unsigned long __ul = strtoul(__xtrc, &__sanity, __base);
540 if (!(__err & ios_base::failbit)
541 && __sanity != __xtrc && *__sanity == '\0' && errno == 0)
544 __err |= ios_base::failbit;
549 #ifdef _GLIBCPP_USE_LONG_LONG
550 template<typename _CharT, typename _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
556 // Stage 1: extract and determine the conversion specifier.
557 // Assuming leading zeros eliminated, thus the size of 32 for
559 char __xtrc[32]= {'\0'};
561 _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
563 // Stage 2: convert and store results.
566 unsigned long long __ull = strtoull(__xtrc, &__sanity, __base);
567 if (!(__err & ios_base::failbit)
568 && __sanity != __xtrc && *__sanity == '\0' && errno == 0)
571 __err |= ios_base::failbit;
577 template<typename _CharT, typename _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
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'};
588 _M_extract(__beg, __end, __io, __err, __xtrc, __base, true);
590 // Stage 2: convert and store results.
593 #ifdef _GLIBCPP_HAVE_STRTOF
594 float __f = strtof(__xtrc, &__sanity);
596 float __f = static_cast<float>(strtod(__xtrc, &__sanity));
598 if (!(__err & ios_base::failbit)
599 && __sanity != __xtrc && *__sanity == '\0' && errno == 0)
602 __err |= ios_base::failbit;
607 template<typename _CharT, typename _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
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'};
618 _M_extract(__beg, __end, __io, __err, __xtrc, __base, true);
620 // Stage 2: convert and store results.
623 double __d = strtod(__xtrc, &__sanity);
624 if (!(__err & ios_base::failbit)
625 && __sanity != __xtrc && *__sanity == '\0' && errno == 0)
628 __err |= ios_base::failbit;
633 #if defined(_GLIBCPP_HAVE_STRTOLD) && !defined(__hpux)
634 template<typename _CharT, typename _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
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'};
645 _M_extract(__beg, __end, __io, __err, __xtrc, __base, true);
647 // Stage 2: convert and store results.
650 long double __ld = strtold(__xtrc, &__sanity);
651 if (!(__err & ios_base::failbit)
652 && __sanity != __xtrc && *__sanity == '\0' && errno == 0)
655 __err |= ios_base::failbit;
660 template<typename _CharT, typename _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
667 char __xtrc[32]= {'\0'};
669 _M_extract(__beg, __end, __io, __err, __xtrc, __base, true);
671 // Stage 2: determine a conversion specifier.
672 ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield;
674 if (__basefield == ios_base::oct)
676 else if (__basefield == ios_base::hex)
678 else if (__basefield == 0)
683 // Stage 3: store results.
685 int __p = sscanf(__xtrc, __conv, &__ld);
687 && static_cast<__traits_type::int_type>(__p) != __traits_type::eof())
690 __err |= ios_base::failbit;
696 template<typename _CharT, typename _InIter>
698 num_get<_CharT, _InIter>::
699 do_get(iter_type __beg, iter_type __end, ios_base& __io,
700 ios_base::iostate& __err, void*& __v) const
702 // Prepare for hex formatted input
703 typedef ios_base::fmtflags fmtflags;
704 fmtflags __fmt = __io.flags();
705 fmtflags __fmtmask = ~(ios_base::showpos | ios_base::basefield
706 | ios_base::uppercase | ios_base::internal);
707 __io.flags(__fmt & __fmtmask | (ios_base::hex | ios_base::showbase));
709 // Stage 1: extract and determine the conversion specifier.
710 // Assuming leading zeros eliminated, thus the size of 32 for
712 char __xtrc[32]= {'\0'};
714 _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
716 // Stage 2: convert and store results.
719 void* __vp = reinterpret_cast<void*>(strtoul(__xtrc, &__sanity, __base));
720 if (!(__err & ios_base::failbit)
721 && __sanity != __xtrc && *__sanity == '\0' && errno == 0)
724 __err |= ios_base::failbit;
726 // Reset from hex formatted input
731 template <typename _CharT, typename _OutIter>
732 locale::id num_put<_CharT, _OutIter>::id;
734 // _S_fill is specialized for ostreambuf_iterator, random access iterator.
735 template <typename _CharT, typename _OutIter>
737 _S_fill(_OutIter __s, _CharT __fill, int __padding);
739 template <typename _CharT, typename _RaIter>
741 _S_fill(_RaIter __s, _CharT __fill, int __padding,
742 random_access_iterator_tag)
745 return __s + __padding;
748 template <typename _CharT, typename _OutIter, typename _Tag>
750 _S_fill(_OutIter __s, _CharT __fill, int __padding, _Tag)
752 while (--__padding >= 0) { *__s = __fill; ++__s; }
756 template <typename _CharT, typename _OutIter>
758 _S_fill(_OutIter __s, _CharT __fill, int __padding)
760 return _S_fill(__s, __fill, __padding,
761 iterator_traits<_OutIter>::iterator_category());
764 template <typename _CharT, typename _OutIter>
766 _S_pad_numeric(_OutIter __s, ios_base::fmtflags /*__flags*/,
767 _CharT /*__fill*/, int /*__width*/,
768 _CharT const* /*__first*/, _CharT const* /*__middle*/,
769 _CharT const* /*__last*/)
771 // XXX Not currently done: non streambuf_iterator
775 // Partial specialization for ostreambuf_iterator.
776 template <typename _CharT>
777 ostreambuf_iterator<_CharT>
778 _S_pad_numeric(ostreambuf_iterator<_CharT> __s, ios_base::fmtflags __flags,
779 _CharT __fill, int __width, _CharT const* __first,
780 _CharT const* __middle, _CharT const* __last)
782 typedef ostreambuf_iterator<_CharT> __out_iter;
783 int __padding = __width - (__last - __first);
786 ios_base::fmtflags __aflags = __flags & ios_base::adjustfield;
787 bool __testfield = __padding == 0 || __aflags == ios_base::left
788 || __aflags == ios_base::internal;
790 // This was needlessly complicated.
791 if (__first != __middle)
795 _S_fill(__s, __fill, __padding);
798 copy(__first, __middle, __s);
800 __out_iter __s2 = __s;
802 if (__padding && __aflags != ios_base::left)
804 _S_fill(__s2, __fill, __padding);
807 __out_iter __s3 = copy(__middle, __last, __s2);
809 _S_fill(__s3, __fill, __padding);
813 template <typename _CharT, typename _OutIter>
815 num_put<_CharT, _OutIter>::
816 do_put(iter_type __s, ios_base& __io, char_type __fill, bool __v) const
818 const _Format_cache<_CharT>* __fmt = _Format_cache<_CharT>::_S_get(__io);
819 ios_base::fmtflags __flags = __io.flags();
821 if ((__flags & ios_base::boolalpha) == 0)
823 unsigned long __uv = __v;
824 return _S_format(__s, __io, __fill, false, __uv);
828 const char_type* __first;
829 const char_type* __last;
832 __first = __fmt->_M_truename.data();
833 __last = __first + __fmt->_M_truename.size();
837 __first = __fmt->_M_falsename.data();
838 __last = __first + __fmt->_M_falsename.size();
840 copy(__first, __last, __s);
845 // _S_group_digits inserts "group separator" characters into an array
846 // of characters. It's recursive, one iteration per group. It moves
847 // the characters in the buffer this way: "xxxx12345" -> "12,345xxx".
848 // Call this only with __grouping != __grend.
849 template <typename _CharT>
851 _S_group_digits(_CharT* __s, _CharT __grsep, char const* __grouping,
852 char const* __grend, _CharT const* __first,
853 _CharT const* __last)
855 if (__last - __first > *__grouping)
857 __s = _S_group_digits(__s, __grsep,
858 (__grouping + 1 == __grend ? __grouping : __grouping + 1),
859 __grend, __first, __last - *__grouping);
860 __first = __last - *__grouping;
867 while (__first != __last);
871 template <typename _CharT, typename _OutIter, typename _ValueT>
873 _S_format(_OutIter __s, ios_base& __io, _CharT __fill, bool __neg,
876 // Leave room for "+/-," "0x," and commas.
877 const long _M_room = numeric_limits<_ValueT>::digits10 * 2 + 4;
878 _CharT __digits[_M_room];
879 _CharT* __front = __digits + _M_room;
880 ios_base::fmtflags __flags = __io.flags();
881 const _Format_cache<_CharT>* __fmt = _Format_cache<_CharT>::_S_get(__io);
882 char const* __table = __fmt->_S_literals + __fmt->_S_digits;
884 ios_base::fmtflags __basefield = (__flags & __io.basefield);
885 _CharT* __sign_end = __front;
886 if (__basefield == ios_base::hex)
888 if (__flags & ios_base::uppercase)
889 __table += 16; // use ABCDEF
891 *--__front = __table[__v & 15];
892 while ((__v >>= 4) != 0);
893 __sign_end = __front;
894 if (__flags & ios_base::showbase)
896 *--__front = __fmt->_S_literals[__fmt->_S_x +
897 ((__flags & ios_base::uppercase) ? 1 : 0)];
898 *--__front = __table[0];
901 else if (__basefield == ios_base::oct)
904 *--__front = __table[__v & 7];
905 while ((__v >>= 3) != 0);
906 if (__flags & ios_base::showbase
907 && static_cast<char>(*__front) != __table[0])
908 *--__front = __table[0];
909 __sign_end = __front;
913 // NB: This is _lots_ faster than using ldiv.
915 *--__front = __table[__v % 10];
916 while ((__v /= 10) != 0);
917 __sign_end = __front;
918 // NB: ios_base:hex || ios_base::oct assumed to be unsigned.
919 if (__neg || (__flags & ios_base::showpos))
920 *--__front = __fmt->_S_literals[__fmt->_S_plus - __neg];
923 // XXX should specialize!
924 if (!__fmt->_M_use_grouping && !__io.width())
925 return copy(__front, __digits + _M_room, __s);
927 if (!__fmt->_M_use_grouping)
928 return _S_pad_numeric(__s, __flags, __fill, __io.width(0),
929 __front, __sign_end, __digits + _M_room);
931 _CharT* __p = __digits;
932 while (__front < __sign_end)
934 const char* __gr = __fmt->_M_grouping.data();
935 __front = _S_group_digits(__p, __fmt->_M_thousands_sep, __gr,
936 __gr + __fmt->_M_grouping.size(), __sign_end, __digits + _M_room);
937 return _S_pad_numeric(__s, __flags, __fill, __io.width(0),
938 __digits, __p, __front);
941 template <typename _CharT, typename _OutIter>
943 num_put<_CharT, _OutIter>::
944 do_put(iter_type __s, ios_base& __io, char_type __fill, long __v) const
946 unsigned long __uv = __v;
953 return _S_format(__s, __io, __fill, __neg, __uv);
956 template <typename _CharT, typename _OutIter>
958 num_put<_CharT, _OutIter>::
959 do_put(iter_type __s, ios_base& __io, char_type __fill,
960 unsigned long __v) const
961 { return _S_format(__s, __io, __fill, false, __v); }
963 #ifdef _GLIBCPP_USE_LONG_LONG
964 template <typename _CharT, typename _OutIter>
966 num_put<_CharT, _OutIter>::
967 do_put(iter_type __s, ios_base& __b, char_type __fill, long long __v) const
969 unsigned long long __uv = __v;
976 return _S_format(__s, __b, __fill, __neg, __uv);
979 template <typename _CharT, typename _OutIter>
981 num_put<_CharT, _OutIter>::
982 do_put(iter_type __s, ios_base& __io, char_type __fill,
983 unsigned long long __v) const
984 { return _S_format(__s, __io, __fill, false, __v); }
987 // Generic helper function
988 template<typename _CharT, typename _OutIter>
990 _S_output_float(_OutIter __s, ios_base& __io, _CharT __fill,
991 const char* __sptr, size_t __slen)
993 // XXX Not currently done: non streambuf_iterator
997 // Partial specialization for ostreambuf_iterator.
998 template<typename _CharT>
999 static ostreambuf_iterator<_CharT>
1000 _S_output_float(ostreambuf_iterator<_CharT> __s, ios_base& __io,
1001 _CharT __fill, const char* __sptr, size_t __slen)
1003 size_t __padding = __io.width() > streamsize(__slen) ?
1004 __io.width() -__slen : 0;
1005 locale __loc = __io.getloc();
1006 ctype<_CharT> const& __ct = use_facet<ctype<_CharT> >(__loc);
1007 ios_base::fmtflags __adjfield = __io.flags() & ios_base::adjustfield;
1008 const char* const __eptr = __sptr + __slen;
1009 // [22.2.2.2.2.19] Table 61
1010 if (__adjfield == ios_base::internal)
1012 // [22.2.2.2.2.14]; widen()
1013 if (__sptr < __eptr && (*__sptr == '+' || *__sptr == '-'))
1015 __s = __ct.widen(*__sptr);
1019 __s = _S_fill(__s, __fill, __padding);
1022 else if (__adjfield != ios_base::left)
1024 __s = _S_fill(__s, __fill, __padding);
1027 // the "C" locale decimal character
1028 char __decimal_point = *(localeconv()->decimal_point);
1029 const _Format_cache<_CharT>* __fmt = _Format_cache<_CharT>::_S_get(__io);
1030 for (; __sptr != __eptr; ++__s, ++__sptr)
1032 // [22.2.2.2.2.17]; decimal point conversion
1033 if (*__sptr == __decimal_point)
1034 __s = __fmt->_M_decimal_point;
1035 // [22.2.2.2.2.14]; widen()
1037 __s = __ct.widen(*__sptr);
1039 // [22.2.2.2.2.19] Table 61
1041 _S_fill(__s, __fill, __padding);
1047 _S_build_float_format(ios_base& __io, char* __fptr, char __modifier,
1050 template <typename _CharT, typename _OutIter>
1052 num_put<_CharT, _OutIter>::
1053 do_put(iter_type __s, ios_base& __io, char_type __fill, double __v) const
1055 const streamsize __max_prec = numeric_limits<double>::digits10 + 3;
1056 streamsize __prec = __io.precision();
1057 // Protect against sprintf() buffer overflows.
1058 if (__prec > __max_prec)
1059 __prec = __max_prec;
1060 // The *2 provides for signs, exp, 'E', and pad.
1061 char __sbuf[__max_prec*2];
1063 // Long enough for the max format spec.
1065 if (_S_build_float_format(__io, __fbuf, 0, __prec))
1066 __slen = sprintf(__sbuf, __fbuf, __prec, __v);
1068 __slen = sprintf(__sbuf, __fbuf, __v);
1069 // [22.2.2.2.2] Stages 2-4.
1070 return _S_output_float(__s, __io, __fill, __sbuf, __slen);
1073 template <typename _CharT, typename _OutIter>
1075 num_put<_CharT, _OutIter>::
1076 do_put(iter_type __s, ios_base& __io, char_type __fill,
1077 long double __v) const
1079 const streamsize __max_prec = numeric_limits<long double>::digits10 + 3;
1080 streamsize __prec = __io.precision();
1081 // Protect against sprintf() buffer overflows.
1082 if (__prec > __max_prec)
1083 __prec = __max_prec;
1084 // The *2 provides for signs, exp, 'E', and pad.
1085 char __sbuf[__max_prec*2];
1087 // Long enough for the max format spec.
1089 // 'L' as per [22.2.2.2.2] Table 59
1090 if ( _S_build_float_format(__io, __fbuf, 'L', __prec))
1091 __slen = sprintf(__sbuf, __fbuf, __prec, __v);
1093 __slen = sprintf(__sbuf, __fbuf, __v);
1094 // [22.2.2.2.2] Stages 2-4
1095 return _S_output_float(__s, __io, __fill, __sbuf, __slen);
1098 template <typename _CharT, typename _OutIter>
1100 num_put<_CharT, _OutIter>::
1101 do_put(iter_type __s, ios_base& __io, char_type __fill,
1102 const void* __v) const
1104 typedef ios_base::fmtflags fmtflags;
1105 fmtflags __fmt = __io.flags();
1106 fmtflags __fmtmask = ~(ios_base::showpos | ios_base::basefield
1107 | ios_base::uppercase | ios_base::internal);
1108 __io.flags(__fmt & __fmtmask | (ios_base::hex | ios_base::showbase));
1110 _OutIter __s2 = _S_format(__s, __io, __fill, false,
1111 reinterpret_cast<unsigned long>(__v));
1121 template<typename _CharT>
1122 locale::id numpunct<_CharT>::id;
1124 template<typename _CharT>
1125 locale::id collate<_CharT>::id;
1127 // Support for time_get:
1128 // Note that these partial specializations could, and maybe should,
1129 // be changed to full specializations (by eliminating the _Dummy
1130 // argument) and moved to a .cc file.
1131 template<typename _CharT, typename _Dummy = int>
1132 struct _Weekdaynames;
1134 template<typename _Dummy>
1135 struct _Weekdaynames<char, _Dummy>
1136 { static const char* const _S_names[14]; };
1138 template<typename _Dummy>
1140 _Weekdaynames<char, _Dummy>::_S_names[14] =
1143 "Mon", "Monday", "Tue", "Tuesday", "Wed", "Wednesday",
1144 "Thu", "Thursday", "Fri", "Friday", "Sat", "Saturday"
1147 #ifdef _GLIBCPP_USE_WCHAR_T
1148 template<typename _Dummy>
1149 struct _Weekdaynames<wchar_t, _Dummy>
1150 { static const wchar_t* const _S_names[14]; };
1152 template<typename _Dummy>
1153 const wchar_t* const
1154 _Weekdaynames<wchar_t, _Dummy>::_S_names[14] =
1157 L"Mon", L"Monday", L"Tue", L"Tuesday", L"Wed", L"Wednesday",
1158 L"Thu", L"Thursday", L"Fri", L"Friday", L"Sat", L"Saturday"
1162 template<typename _CharT, typename _Dummy = int>
1165 template<typename _Dummy>
1166 struct _Monthnames<char,_Dummy>
1167 { static const char* const _S_names[24]; };
1169 template<typename _Dummy>
1171 _Monthnames<char,_Dummy>::_S_names[24] =
1173 "Jan", "January", "Feb", "February", "Mar", "March",
1174 "Apr", "April", "May", "May", "Jun", "June",
1175 "Jul", "July", "Aug", "August", "Sep", "September",
1176 "Oct", "October", "Nov", "November", "Dec", "December"
1179 #ifdef _GLIBCPP_USE_WCHAR_T
1180 template<typename _Dummy>
1181 struct _Monthnames<wchar_t, _Dummy>
1182 { static const wchar_t* const _S_names[24]; };
1184 template<typename _Dummy>
1185 const wchar_t* const
1186 _Monthnames<wchar_t,_Dummy>::_S_names[24] =
1188 L"Jan", L"January", L"Feb", L"February", L"Mar", L"March",
1189 L"Apr", L"April", L"May", L"May", L"Jun", L"June",
1190 L"Jul", L"July", L"Aug", L"August", L"Sep", L"September",
1191 L"Oct", L"October", L"Nov", L"November", L"Dec", L"December"
1195 template<typename _CharT, typename _InIter>
1196 locale::id time_get<_CharT, _InIter>::id;
1198 template<typename _CharT, typename _InIter>
1200 time_get<_CharT, _InIter>::
1201 do_get_weekday(iter_type __s, iter_type __end,
1202 ios_base& __io, ios_base::iostate& __err, tm* __t) const
1206 _M_daynames = new basic_string<_CharT>[14];
1207 for (int __i = 0; __i < 14; ++__i)
1208 _M_daynames[__i] = _Weekdaynames<_CharT>::_S_names[__i];
1210 bool __at_eof = false;
1213 iter_type __out = __match_parallel(__s, __end, 14, _M_daynames,
1214 __matches, __remain, __at_eof);
1215 __err = ios_base::iostate(0);
1216 if (__at_eof) __err |= __io.eofbit;
1217 if (__remain == 1 ||
1218 __remain == 2 && (__matches[0]>>1) == (__matches[1]>>1))
1219 __t->tm_wday = (__matches[0]>>1);
1221 __err |= __io.failbit;
1225 template<typename _CharT, typename _InIter>
1227 time_get<_CharT, _InIter>::
1228 do_get_monthname(iter_type __s, iter_type __end,
1229 ios_base& __io, ios_base::iostate& __err, tm* __t) const
1233 _M_monthnames = new basic_string<_CharT>[24];
1234 for (int __i = 0; __i < 24; ++__i)
1235 _M_monthnames[__i] = _Monthnames<_CharT>::_S_names[__i];
1237 bool __at_eof = false;
1240 iter_type __out = __match_parallel( __s, __end, 24, _M_monthnames,
1241 __matches, __remain, __at_eof);
1242 __err = ios_base::iostate(0);
1243 if (__at_eof) __err |= __io.eofbit;
1244 if (__remain == 1 ||
1245 __remain == 2 && (__matches[0]>>1) == (__matches[1]>>1))
1246 __t->tm_mon = (__matches[0]>>1);
1248 __err |= __io.failbit;
1252 template<typename _CharT, typename _OutIter>
1253 locale::id time_put<_CharT, _OutIter>::id;
1255 template<typename _CharT, typename _InIter>
1256 locale::id money_get<_CharT, _InIter>::id;
1258 template<typename _CharT, typename _OutIter>
1259 locale::id money_put<_CharT, _OutIter>::id;
1261 template<typename _CharT, bool _Intl>
1262 locale::id moneypunct<_CharT, _Intl>::id;
1264 template<typename _CharT, bool _Intl>
1265 const bool moneypunct<_CharT, _Intl>::intl;
1267 template<typename _CharT, bool _Intl>
1268 const bool moneypunct_byname<_CharT, _Intl>::intl;
1270 template<typename _CharT>
1271 locale::id messages<_CharT>::id;
1274 #endif /* _CPP_BITS_LOCFACETS_TCC */