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