]> git.ipfire.org Git - thirdparty/gcc.git/blame - libstdc++-v3/include/bits/locale_facets_nonio.tcc
headers.txt (gnu/gcj/jvmti/Breakpoint.h): Add _Jv_RewriteBreakpointInsn friend declar...
[thirdparty/gcc.git] / libstdc++-v3 / include / bits / locale_facets_nonio.tcc
CommitLineData
f749a55b
PC
1// Locale support -*- C++ -*-
2
3// Copyright (C) 2007 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
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/** @file locale_facets_nonio.tcc
31 * This is an internal header file, included by other library headers.
32 * You should not attempt to use it directly.
33 */
34
35#ifndef _LOCALE_FACETS_NONIO_TCC
36#define _LOCALE_FACETS_NONIO_TCC 1
37
38_GLIBCXX_BEGIN_NAMESPACE(std)
39
40 template<typename _CharT, bool _Intl>
41 struct __use_cache<__moneypunct_cache<_CharT, _Intl> >
42 {
43 const __moneypunct_cache<_CharT, _Intl>*
44 operator() (const locale& __loc) const
45 {
46 const size_t __i = moneypunct<_CharT, _Intl>::id._M_id();
47 const locale::facet** __caches = __loc._M_impl->_M_caches;
48 if (!__caches[__i])
49 {
50 __moneypunct_cache<_CharT, _Intl>* __tmp = NULL;
51 try
52 {
53 __tmp = new __moneypunct_cache<_CharT, _Intl>;
54 __tmp->_M_cache(__loc);
55 }
56 catch(...)
57 {
58 delete __tmp;
59 __throw_exception_again;
60 }
61 __loc._M_impl->_M_install_cache(__tmp, __i);
62 }
63 return static_cast<
64 const __moneypunct_cache<_CharT, _Intl>*>(__caches[__i]);
65 }
66 };
67
68 template<typename _CharT, bool _Intl>
69 void
70 __moneypunct_cache<_CharT, _Intl>::_M_cache(const locale& __loc)
71 {
72 _M_allocated = true;
73
74 const moneypunct<_CharT, _Intl>& __mp =
75 use_facet<moneypunct<_CharT, _Intl> >(__loc);
76
77 _M_grouping_size = __mp.grouping().size();
78 char* __grouping = new char[_M_grouping_size];
79 __mp.grouping().copy(__grouping, _M_grouping_size);
80 _M_grouping = __grouping;
81 _M_use_grouping = (_M_grouping_size
82 && static_cast<signed char>(__mp.grouping()[0]) > 0);
83
84 _M_decimal_point = __mp.decimal_point();
85 _M_thousands_sep = __mp.thousands_sep();
86 _M_frac_digits = __mp.frac_digits();
87
88 _M_curr_symbol_size = __mp.curr_symbol().size();
89 _CharT* __curr_symbol = new _CharT[_M_curr_symbol_size];
90 __mp.curr_symbol().copy(__curr_symbol, _M_curr_symbol_size);
91 _M_curr_symbol = __curr_symbol;
92
93 _M_positive_sign_size = __mp.positive_sign().size();
94 _CharT* __positive_sign = new _CharT[_M_positive_sign_size];
95 __mp.positive_sign().copy(__positive_sign, _M_positive_sign_size);
96 _M_positive_sign = __positive_sign;
97
98 _M_negative_sign_size = __mp.negative_sign().size();
99 _CharT* __negative_sign = new _CharT[_M_negative_sign_size];
100 __mp.negative_sign().copy(__negative_sign, _M_negative_sign_size);
101 _M_negative_sign = __negative_sign;
102
103 _M_pos_format = __mp.pos_format();
104 _M_neg_format = __mp.neg_format();
105
106 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__loc);
107 __ct.widen(money_base::_S_atoms,
108 money_base::_S_atoms + money_base::_S_end, _M_atoms);
109 }
110
111_GLIBCXX_BEGIN_LDBL_NAMESPACE
112
113 template<typename _CharT, typename _InIter>
114 template<bool _Intl>
115 _InIter
116 money_get<_CharT, _InIter>::
117 _M_extract(iter_type __beg, iter_type __end, ios_base& __io,
118 ios_base::iostate& __err, string& __units) const
119 {
120 typedef char_traits<_CharT> __traits_type;
121 typedef typename string_type::size_type size_type;
122 typedef money_base::part part;
123 typedef __moneypunct_cache<_CharT, _Intl> __cache_type;
124
125 const locale& __loc = __io._M_getloc();
126 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
127
128 __use_cache<__cache_type> __uc;
129 const __cache_type* __lc = __uc(__loc);
130 const char_type* __lit = __lc->_M_atoms;
131
132 // Deduced sign.
133 bool __negative = false;
134 // Sign size.
135 size_type __sign_size = 0;
136 // True if sign is mandatory.
137 const bool __mandatory_sign = (__lc->_M_positive_sign_size
138 && __lc->_M_negative_sign_size);
139 // String of grouping info from thousands_sep plucked from __units.
140 string __grouping_tmp;
141 if (__lc->_M_use_grouping)
142 __grouping_tmp.reserve(32);
143 // Last position before the decimal point.
144 int __last_pos = 0;
145 // Separator positions, then, possibly, fractional digits.
146 int __n = 0;
147 // If input iterator is in a valid state.
148 bool __testvalid = true;
149 // Flag marking when a decimal point is found.
150 bool __testdecfound = false;
151
152 // The tentative returned string is stored here.
153 string __res;
154 __res.reserve(32);
155
156 const char_type* __lit_zero = __lit + money_base::_S_zero;
157 const money_base::pattern __p = __lc->_M_neg_format;
158 for (int __i = 0; __i < 4 && __testvalid; ++__i)
159 {
160 const part __which = static_cast<part>(__p.field[__i]);
161 switch (__which)
162 {
163 case money_base::symbol:
164 // According to 22.2.6.1.2, p2, symbol is required
165 // if (__io.flags() & ios_base::showbase), otherwise
166 // is optional and consumed only if other characters
167 // are needed to complete the format.
168 if (__io.flags() & ios_base::showbase || __sign_size > 1
169 || __i == 0
170 || (__i == 1 && (__mandatory_sign
171 || (static_cast<part>(__p.field[0])
172 == money_base::sign)
173 || (static_cast<part>(__p.field[2])
174 == money_base::space)))
175 || (__i == 2 && ((static_cast<part>(__p.field[3])
176 == money_base::value)
177 || (__mandatory_sign
178 && (static_cast<part>(__p.field[3])
179 == money_base::sign)))))
180 {
181 const size_type __len = __lc->_M_curr_symbol_size;
182 size_type __j = 0;
183 for (; __beg != __end && __j < __len
184 && *__beg == __lc->_M_curr_symbol[__j];
185 ++__beg, ++__j);
186 if (__j != __len
187 && (__j || __io.flags() & ios_base::showbase))
188 __testvalid = false;
189 }
190 break;
191 case money_base::sign:
192 // Sign might not exist, or be more than one character long.
193 if (__lc->_M_positive_sign_size && __beg != __end
194 && *__beg == __lc->_M_positive_sign[0])
195 {
196 __sign_size = __lc->_M_positive_sign_size;
197 ++__beg;
198 }
199 else if (__lc->_M_negative_sign_size && __beg != __end
200 && *__beg == __lc->_M_negative_sign[0])
201 {
202 __negative = true;
203 __sign_size = __lc->_M_negative_sign_size;
204 ++__beg;
205 }
206 else if (__lc->_M_positive_sign_size
207 && !__lc->_M_negative_sign_size)
208 // "... if no sign is detected, the result is given the sign
209 // that corresponds to the source of the empty string"
210 __negative = true;
211 else if (__mandatory_sign)
212 __testvalid = false;
213 break;
214 case money_base::value:
215 // Extract digits, remove and stash away the
216 // grouping of found thousands separators.
217 for (; __beg != __end; ++__beg)
218 {
219 const char_type __c = *__beg;
220 const char_type* __q = __traits_type::find(__lit_zero,
221 10, __c);
222 if (__q != 0)
223 {
224 __res += money_base::_S_atoms[__q - __lit];
225 ++__n;
226 }
227 else if (__c == __lc->_M_decimal_point
228 && !__testdecfound)
229 {
230 __last_pos = __n;
231 __n = 0;
232 __testdecfound = true;
233 }
234 else if (__lc->_M_use_grouping
235 && __c == __lc->_M_thousands_sep
236 && !__testdecfound)
237 {
238 if (__n)
239 {
240 // Mark position for later analysis.
241 __grouping_tmp += static_cast<char>(__n);
242 __n = 0;
243 }
244 else
245 {
246 __testvalid = false;
247 break;
248 }
249 }
250 else
251 break;
252 }
253 if (__res.empty())
254 __testvalid = false;
255 break;
256 case money_base::space:
257 // At least one space is required.
258 if (__beg != __end && __ctype.is(ctype_base::space, *__beg))
259 ++__beg;
260 else
261 __testvalid = false;
262 case money_base::none:
263 // Only if not at the end of the pattern.
264 if (__i != 3)
265 for (; __beg != __end
266 && __ctype.is(ctype_base::space, *__beg); ++__beg);
267 break;
268 }
269 }
270
271 // Need to get the rest of the sign characters, if they exist.
272 if (__sign_size > 1 && __testvalid)
273 {
274 const char_type* __sign = __negative ? __lc->_M_negative_sign
275 : __lc->_M_positive_sign;
276 size_type __i = 1;
277 for (; __beg != __end && __i < __sign_size
278 && *__beg == __sign[__i]; ++__beg, ++__i);
279
280 if (__i != __sign_size)
281 __testvalid = false;
282 }
283
284 if (__testvalid)
285 {
286 // Strip leading zeros.
287 if (__res.size() > 1)
288 {
289 const size_type __first = __res.find_first_not_of('0');
290 const bool __only_zeros = __first == string::npos;
291 if (__first)
292 __res.erase(0, __only_zeros ? __res.size() - 1 : __first);
293 }
294
295 // 22.2.6.1.2, p4
296 if (__negative && __res[0] != '0')
297 __res.insert(__res.begin(), '-');
298
299 // Test for grouping fidelity.
300 if (__grouping_tmp.size())
301 {
302 // Add the ending grouping.
303 __grouping_tmp += static_cast<char>(__testdecfound ? __last_pos
304 : __n);
305 if (!std::__verify_grouping(__lc->_M_grouping,
306 __lc->_M_grouping_size,
307 __grouping_tmp))
308 __err |= ios_base::failbit;
309 }
310
311 // Iff not enough digits were supplied after the decimal-point.
312 if (__testdecfound && __lc->_M_frac_digits > 0
313 && __n != __lc->_M_frac_digits)
314 __testvalid = false;
315 }
316
317 // Iff valid sequence is not recognized.
318 if (!__testvalid)
319 __err |= ios_base::failbit;
320 else
321 __units.swap(__res);
322
323 // Iff no more characters are available.
324 if (__beg == __end)
325 __err |= ios_base::eofbit;
326 return __beg;
327 }
328
329#if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__
330 template<typename _CharT, typename _InIter>
331 _InIter
332 money_get<_CharT, _InIter>::
333 __do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
334 ios_base::iostate& __err, double& __units) const
335 {
336 string __str;
337 __beg = __intl ? _M_extract<true>(__beg, __end, __io, __err, __str)
338 : _M_extract<false>(__beg, __end, __io, __err, __str);
339 std::__convert_to_v(__str.c_str(), __units, __err, _S_get_c_locale());
340 return __beg;
341 }
342#endif
343
344 template<typename _CharT, typename _InIter>
345 _InIter
346 money_get<_CharT, _InIter>::
347 do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
348 ios_base::iostate& __err, long double& __units) const
349 {
350 string __str;
351 __beg = __intl ? _M_extract<true>(__beg, __end, __io, __err, __str)
352 : _M_extract<false>(__beg, __end, __io, __err, __str);
353 std::__convert_to_v(__str.c_str(), __units, __err, _S_get_c_locale());
354 return __beg;
355 }
356
357 template<typename _CharT, typename _InIter>
358 _InIter
359 money_get<_CharT, _InIter>::
360 do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
361 ios_base::iostate& __err, string_type& __digits) const
362 {
363 typedef typename string::size_type size_type;
364
365 const locale& __loc = __io._M_getloc();
366 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
367
368 string __str;
369 __beg = __intl ? _M_extract<true>(__beg, __end, __io, __err, __str)
370 : _M_extract<false>(__beg, __end, __io, __err, __str);
371 const size_type __len = __str.size();
372 if (__len)
373 {
374 __digits.resize(__len);
375 __ctype.widen(__str.data(), __str.data() + __len, &__digits[0]);
376 }
377 return __beg;
378 }
379
380 template<typename _CharT, typename _OutIter>
381 template<bool _Intl>
382 _OutIter
383 money_put<_CharT, _OutIter>::
384 _M_insert(iter_type __s, ios_base& __io, char_type __fill,
385 const string_type& __digits) const
386 {
387 typedef typename string_type::size_type size_type;
388 typedef money_base::part part;
389 typedef __moneypunct_cache<_CharT, _Intl> __cache_type;
390
391 const locale& __loc = __io._M_getloc();
392 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
393
394 __use_cache<__cache_type> __uc;
395 const __cache_type* __lc = __uc(__loc);
396 const char_type* __lit = __lc->_M_atoms;
397
398 // Determine if negative or positive formats are to be used, and
399 // discard leading negative_sign if it is present.
400 const char_type* __beg = __digits.data();
401
402 money_base::pattern __p;
403 const char_type* __sign;
404 size_type __sign_size;
405 if (!(*__beg == __lit[money_base::_S_minus]))
406 {
407 __p = __lc->_M_pos_format;
408 __sign = __lc->_M_positive_sign;
409 __sign_size = __lc->_M_positive_sign_size;
410 }
411 else
412 {
413 __p = __lc->_M_neg_format;
414 __sign = __lc->_M_negative_sign;
415 __sign_size = __lc->_M_negative_sign_size;
416 if (__digits.size())
417 ++__beg;
418 }
419
420 // Look for valid numbers in the ctype facet within input digits.
421 size_type __len = __ctype.scan_not(ctype_base::digit, __beg,
422 __beg + __digits.size()) - __beg;
423 if (__len)
424 {
425 // Assume valid input, and attempt to format.
426 // Break down input numbers into base components, as follows:
427 // final_value = grouped units + (decimal point) + (digits)
428 string_type __value;
429 __value.reserve(2 * __len);
430
431 // Add thousands separators to non-decimal digits, per
432 // grouping rules.
433 long __paddec = __len - __lc->_M_frac_digits;
434 if (__paddec > 0)
435 {
436 if (__lc->_M_frac_digits < 0)
437 __paddec = __len;
438 if (__lc->_M_grouping_size)
439 {
440 __value.assign(2 * __paddec, char_type());
441 _CharT* __vend =
442 std::__add_grouping(&__value[0], __lc->_M_thousands_sep,
443 __lc->_M_grouping,
444 __lc->_M_grouping_size,
445 __beg, __beg + __paddec);
446 __value.erase(__vend - &__value[0]);
447 }
448 else
449 __value.assign(__beg, __paddec);
450 }
451
452 // Deal with decimal point, decimal digits.
453 if (__lc->_M_frac_digits > 0)
454 {
455 __value += __lc->_M_decimal_point;
456 if (__paddec >= 0)
457 __value.append(__beg + __paddec, __lc->_M_frac_digits);
458 else
459 {
460 // Have to pad zeros in the decimal position.
461 __value.append(-__paddec, __lit[money_base::_S_zero]);
462 __value.append(__beg, __len);
463 }
464 }
465
466 // Calculate length of resulting string.
467 const ios_base::fmtflags __f = __io.flags()
468 & ios_base::adjustfield;
469 __len = __value.size() + __sign_size;
470 __len += ((__io.flags() & ios_base::showbase)
471 ? __lc->_M_curr_symbol_size : 0);
472
473 string_type __res;
474 __res.reserve(2 * __len);
475
476 const size_type __width = static_cast<size_type>(__io.width());
477 const bool __testipad = (__f == ios_base::internal
478 && __len < __width);
479 // Fit formatted digits into the required pattern.
480 for (int __i = 0; __i < 4; ++__i)
481 {
482 const part __which = static_cast<part>(__p.field[__i]);
483 switch (__which)
484 {
485 case money_base::symbol:
486 if (__io.flags() & ios_base::showbase)
487 __res.append(__lc->_M_curr_symbol,
488 __lc->_M_curr_symbol_size);
489 break;
490 case money_base::sign:
491 // Sign might not exist, or be more than one
492 // charater long. In that case, add in the rest
493 // below.
494 if (__sign_size)
495 __res += __sign[0];
496 break;
497 case money_base::value:
498 __res += __value;
499 break;
500 case money_base::space:
501 // At least one space is required, but if internal
502 // formatting is required, an arbitrary number of
503 // fill spaces will be necessary.
504 if (__testipad)
505 __res.append(__width - __len, __fill);
506 else
507 __res += __fill;
508 break;
509 case money_base::none:
510 if (__testipad)
511 __res.append(__width - __len, __fill);
512 break;
513 }
514 }
515
516 // Special case of multi-part sign parts.
517 if (__sign_size > 1)
518 __res.append(__sign + 1, __sign_size - 1);
519
520 // Pad, if still necessary.
521 __len = __res.size();
522 if (__width > __len)
523 {
524 if (__f == ios_base::left)
525 // After.
526 __res.append(__width - __len, __fill);
527 else
528 // Before.
529 __res.insert(0, __width - __len, __fill);
530 __len = __width;
531 }
532
533 // Write resulting, fully-formatted string to output iterator.
534 __s = std::__write(__s, __res.data(), __len);
535 }
536 __io.width(0);
537 return __s;
538 }
539
540#if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__
541 template<typename _CharT, typename _OutIter>
542 _OutIter
543 money_put<_CharT, _OutIter>::
544 __do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
545 double __units) const
546 { return this->do_put(__s, __intl, __io, __fill, (long double) __units); }
547#endif
548
549 template<typename _CharT, typename _OutIter>
550 _OutIter
551 money_put<_CharT, _OutIter>::
552 do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
553 long double __units) const
554 {
555 const locale __loc = __io.getloc();
556 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
557#ifdef _GLIBCXX_USE_C99
558 // First try a buffer perhaps big enough.
559 int __cs_size = 64;
560 char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
561 // _GLIBCXX_RESOLVE_LIB_DEFECTS
562 // 328. Bad sprintf format modifier in money_put<>::do_put()
563 int __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
564 "%.*Lf", 0, __units);
565 // If the buffer was not large enough, try again with the correct size.
566 if (__len >= __cs_size)
567 {
568 __cs_size = __len + 1;
569 __cs = static_cast<char*>(__builtin_alloca(__cs_size));
570 __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
571 "%.*Lf", 0, __units);
572 }
573#else
574 // max_exponent10 + 1 for the integer part, + 2 for sign and '\0'.
575 const int __cs_size =
576 __gnu_cxx::__numeric_traits<long double>::__max_exponent10 + 3;
577 char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
578 int __len = std::__convert_from_v(_S_get_c_locale(), __cs, 0, "%.*Lf",
579 0, __units);
580#endif
581 string_type __digits(__len, char_type());
582 __ctype.widen(__cs, __cs + __len, &__digits[0]);
583 return __intl ? _M_insert<true>(__s, __io, __fill, __digits)
584 : _M_insert<false>(__s, __io, __fill, __digits);
585 }
586
587 template<typename _CharT, typename _OutIter>
588 _OutIter
589 money_put<_CharT, _OutIter>::
590 do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
591 const string_type& __digits) const
592 { return __intl ? _M_insert<true>(__s, __io, __fill, __digits)
593 : _M_insert<false>(__s, __io, __fill, __digits); }
594
595_GLIBCXX_END_LDBL_NAMESPACE
596
597 // NB: Not especially useful. Without an ios_base object or some
598 // kind of locale reference, we are left clawing at the air where
599 // the side of the mountain used to be...
600 template<typename _CharT, typename _InIter>
601 time_base::dateorder
602 time_get<_CharT, _InIter>::do_date_order() const
603 { return time_base::no_order; }
604
605 // Expand a strftime format string and parse it. E.g., do_get_date() may
606 // pass %m/%d/%Y => extracted characters.
607 template<typename _CharT, typename _InIter>
608 _InIter
609 time_get<_CharT, _InIter>::
610 _M_extract_via_format(iter_type __beg, iter_type __end, ios_base& __io,
611 ios_base::iostate& __err, tm* __tm,
612 const _CharT* __format) const
613 {
614 const locale& __loc = __io._M_getloc();
615 const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
616 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
617 const size_t __len = char_traits<_CharT>::length(__format);
618
619 ios_base::iostate __tmperr = ios_base::goodbit;
620 for (size_t __i = 0; __beg != __end && __i < __len && !__tmperr; ++__i)
621 {
622 if (__ctype.narrow(__format[__i], 0) == '%')
623 {
624 // Verify valid formatting code, attempt to extract.
625 char __c = __ctype.narrow(__format[++__i], 0);
626 int __mem = 0;
627 if (__c == 'E' || __c == 'O')
628 __c = __ctype.narrow(__format[++__i], 0);
629 switch (__c)
630 {
631 const char* __cs;
632 _CharT __wcs[10];
633 case 'a':
634 // Abbreviated weekday name [tm_wday]
635 const char_type* __days1[7];
636 __tp._M_days_abbreviated(__days1);
637 __beg = _M_extract_name(__beg, __end, __tm->tm_wday, __days1,
638 7, __io, __tmperr);
639 break;
640 case 'A':
641 // Weekday name [tm_wday].
642 const char_type* __days2[7];
643 __tp._M_days(__days2);
644 __beg = _M_extract_name(__beg, __end, __tm->tm_wday, __days2,
645 7, __io, __tmperr);
646 break;
647 case 'h':
648 case 'b':
649 // Abbreviated month name [tm_mon]
650 const char_type* __months1[12];
651 __tp._M_months_abbreviated(__months1);
652 __beg = _M_extract_name(__beg, __end, __tm->tm_mon,
653 __months1, 12, __io, __tmperr);
654 break;
655 case 'B':
656 // Month name [tm_mon].
657 const char_type* __months2[12];
658 __tp._M_months(__months2);
659 __beg = _M_extract_name(__beg, __end, __tm->tm_mon,
660 __months2, 12, __io, __tmperr);
661 break;
662 case 'c':
663 // Default time and date representation.
664 const char_type* __dt[2];
665 __tp._M_date_time_formats(__dt);
666 __beg = _M_extract_via_format(__beg, __end, __io, __tmperr,
667 __tm, __dt[0]);
668 break;
669 case 'd':
670 // Day [01, 31]. [tm_mday]
671 __beg = _M_extract_num(__beg, __end, __tm->tm_mday, 1, 31, 2,
672 __io, __tmperr);
673 break;
674 case 'e':
675 // Day [1, 31], with single digits preceded by
676 // space. [tm_mday]
677 if (__ctype.is(ctype_base::space, *__beg))
678 __beg = _M_extract_num(++__beg, __end, __tm->tm_mday, 1, 9,
679 1, __io, __tmperr);
680 else
681 __beg = _M_extract_num(__beg, __end, __tm->tm_mday, 10, 31,
682 2, __io, __tmperr);
683 break;
684 case 'D':
685 // Equivalent to %m/%d/%y.[tm_mon, tm_mday, tm_year]
686 __cs = "%m/%d/%y";
687 __ctype.widen(__cs, __cs + 9, __wcs);
688 __beg = _M_extract_via_format(__beg, __end, __io, __tmperr,
689 __tm, __wcs);
690 break;
691 case 'H':
692 // Hour [00, 23]. [tm_hour]
693 __beg = _M_extract_num(__beg, __end, __tm->tm_hour, 0, 23, 2,
694 __io, __tmperr);
695 break;
696 case 'I':
697 // Hour [01, 12]. [tm_hour]
698 __beg = _M_extract_num(__beg, __end, __tm->tm_hour, 1, 12, 2,
699 __io, __tmperr);
700 break;
701 case 'm':
702 // Month [01, 12]. [tm_mon]
703 __beg = _M_extract_num(__beg, __end, __mem, 1, 12, 2,
704 __io, __tmperr);
705 if (!__tmperr)
706 __tm->tm_mon = __mem - 1;
707 break;
708 case 'M':
709 // Minute [00, 59]. [tm_min]
710 __beg = _M_extract_num(__beg, __end, __tm->tm_min, 0, 59, 2,
711 __io, __tmperr);
712 break;
713 case 'n':
714 if (__ctype.narrow(*__beg, 0) == '\n')
715 ++__beg;
716 else
717 __tmperr |= ios_base::failbit;
718 break;
719 case 'R':
720 // Equivalent to (%H:%M).
721 __cs = "%H:%M";
722 __ctype.widen(__cs, __cs + 6, __wcs);
723 __beg = _M_extract_via_format(__beg, __end, __io, __tmperr,
724 __tm, __wcs);
725 break;
726 case 'S':
727 // Seconds. [tm_sec]
728 // [00, 60] in C99 (one leap-second), [00, 61] in C89.
729#ifdef _GLIBCXX_USE_C99
730 __beg = _M_extract_num(__beg, __end, __tm->tm_sec, 0, 60, 2,
731#else
732 __beg = _M_extract_num(__beg, __end, __tm->tm_sec, 0, 61, 2,
733#endif
734 __io, __tmperr);
735 break;
736 case 't':
737 if (__ctype.narrow(*__beg, 0) == '\t')
738 ++__beg;
739 else
740 __tmperr |= ios_base::failbit;
741 break;
742 case 'T':
743 // Equivalent to (%H:%M:%S).
744 __cs = "%H:%M:%S";
745 __ctype.widen(__cs, __cs + 9, __wcs);
746 __beg = _M_extract_via_format(__beg, __end, __io, __tmperr,
747 __tm, __wcs);
748 break;
749 case 'x':
750 // Locale's date.
751 const char_type* __dates[2];
752 __tp._M_date_formats(__dates);
753 __beg = _M_extract_via_format(__beg, __end, __io, __tmperr,
754 __tm, __dates[0]);
755 break;
756 case 'X':
757 // Locale's time.
758 const char_type* __times[2];
759 __tp._M_time_formats(__times);
760 __beg = _M_extract_via_format(__beg, __end, __io, __tmperr,
761 __tm, __times[0]);
762 break;
763 case 'y':
764 case 'C': // C99
765 // Two digit year. [tm_year]
766 __beg = _M_extract_num(__beg, __end, __tm->tm_year, 0, 99, 2,
767 __io, __tmperr);
768 break;
769 case 'Y':
770 // Year [1900). [tm_year]
771 __beg = _M_extract_num(__beg, __end, __mem, 0, 9999, 4,
772 __io, __tmperr);
773 if (!__tmperr)
774 __tm->tm_year = __mem - 1900;
775 break;
776 case 'Z':
777 // Timezone info.
778 if (__ctype.is(ctype_base::upper, *__beg))
779 {
780 int __tmp;
781 __beg = _M_extract_name(__beg, __end, __tmp,
782 __timepunct_cache<_CharT>::_S_timezones,
783 14, __io, __tmperr);
784
785 // GMT requires special effort.
786 if (__beg != __end && !__tmperr && __tmp == 0
787 && (*__beg == __ctype.widen('-')
788 || *__beg == __ctype.widen('+')))
789 {
790 __beg = _M_extract_num(__beg, __end, __tmp, 0, 23, 2,
791 __io, __tmperr);
792 __beg = _M_extract_num(__beg, __end, __tmp, 0, 59, 2,
793 __io, __tmperr);
794 }
795 }
796 else
797 __tmperr |= ios_base::failbit;
798 break;
799 default:
800 // Not recognized.
801 __tmperr |= ios_base::failbit;
802 }
803 }
804 else
805 {
806 // Verify format and input match, extract and discard.
807 if (__format[__i] == *__beg)
808 ++__beg;
809 else
810 __tmperr |= ios_base::failbit;
811 }
812 }
813
814 if (__tmperr)
815 __err |= ios_base::failbit;
816
817 return __beg;
818 }
819
820 template<typename _CharT, typename _InIter>
821 _InIter
822 time_get<_CharT, _InIter>::
823 _M_extract_num(iter_type __beg, iter_type __end, int& __member,
824 int __min, int __max, size_t __len,
825 ios_base& __io, ios_base::iostate& __err) const
826 {
827 const locale& __loc = __io._M_getloc();
828 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
829
830 // As-is works for __len = 1, 2, 4, the values actually used.
831 int __mult = __len == 2 ? 10 : (__len == 4 ? 1000 : 1);
832
833 ++__min;
834 size_t __i = 0;
835 int __value = 0;
836 for (; __beg != __end && __i < __len; ++__beg, ++__i)
837 {
838 const char __c = __ctype.narrow(*__beg, '*');
839 if (__c >= '0' && __c <= '9')
840 {
841 __value = __value * 10 + (__c - '0');
842 const int __valuec = __value * __mult;
843 if (__valuec > __max || __valuec + __mult < __min)
844 break;
845 __mult /= 10;
846 }
847 else
848 break;
849 }
850 if (__i == __len)
851 __member = __value;
852 else
853 __err |= ios_base::failbit;
854
855 return __beg;
856 }
857
858 // Assumptions:
859 // All elements in __names are unique.
860 template<typename _CharT, typename _InIter>
861 _InIter
862 time_get<_CharT, _InIter>::
863 _M_extract_name(iter_type __beg, iter_type __end, int& __member,
864 const _CharT** __names, size_t __indexlen,
865 ios_base& __io, ios_base::iostate& __err) const
866 {
867 typedef char_traits<_CharT> __traits_type;
868 const locale& __loc = __io._M_getloc();
869 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
870
871 int* __matches = static_cast<int*>(__builtin_alloca(sizeof(int)
872 * __indexlen));
873 size_t __nmatches = 0;
874 size_t __pos = 0;
875 bool __testvalid = true;
876 const char_type* __name;
877
878 // Look for initial matches.
879 // NB: Some of the locale data is in the form of all lowercase
880 // names, and some is in the form of initially-capitalized
881 // names. Look for both.
882 if (__beg != __end)
883 {
884 const char_type __c = *__beg;
885 for (size_t __i1 = 0; __i1 < __indexlen; ++__i1)
886 if (__c == __names[__i1][0]
887 || __c == __ctype.toupper(__names[__i1][0]))
888 __matches[__nmatches++] = __i1;
889 }
890
891 while (__nmatches > 1)
892 {
893 // Find smallest matching string.
894 size_t __minlen = __traits_type::length(__names[__matches[0]]);
895 for (size_t __i2 = 1; __i2 < __nmatches; ++__i2)
896 __minlen = std::min(__minlen,
897 __traits_type::length(__names[__matches[__i2]]));
898 ++__beg, ++__pos;
899 if (__pos < __minlen && __beg != __end)
900 for (size_t __i3 = 0; __i3 < __nmatches;)
901 {
902 __name = __names[__matches[__i3]];
903 if (!(__name[__pos] == *__beg))
904 __matches[__i3] = __matches[--__nmatches];
905 else
906 ++__i3;
907 }
908 else
909 break;
910 }
911
912 if (__nmatches == 1)
913 {
914 // Make sure found name is completely extracted.
915 ++__beg, ++__pos;
916 __name = __names[__matches[0]];
917 const size_t __len = __traits_type::length(__name);
918 while (__pos < __len && __beg != __end && __name[__pos] == *__beg)
919 ++__beg, ++__pos;
920
921 if (__len == __pos)
922 __member = __matches[0];
923 else
924 __testvalid = false;
925 }
926 else
927 __testvalid = false;
928 if (!__testvalid)
929 __err |= ios_base::failbit;
930
931 return __beg;
932 }
933
934 template<typename _CharT, typename _InIter>
935 _InIter
936 time_get<_CharT, _InIter>::
937 do_get_time(iter_type __beg, iter_type __end, ios_base& __io,
938 ios_base::iostate& __err, tm* __tm) const
939 {
940 const locale& __loc = __io._M_getloc();
941 const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
942 const char_type* __times[2];
943 __tp._M_time_formats(__times);
944 __beg = _M_extract_via_format(__beg, __end, __io, __err,
945 __tm, __times[0]);
946 if (__beg == __end)
947 __err |= ios_base::eofbit;
948 return __beg;
949 }
950
951 template<typename _CharT, typename _InIter>
952 _InIter
953 time_get<_CharT, _InIter>::
954 do_get_date(iter_type __beg, iter_type __end, ios_base& __io,
955 ios_base::iostate& __err, tm* __tm) const
956 {
957 const locale& __loc = __io._M_getloc();
958 const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
959 const char_type* __dates[2];
960 __tp._M_date_formats(__dates);
961 __beg = _M_extract_via_format(__beg, __end, __io, __err,
962 __tm, __dates[0]);
963 if (__beg == __end)
964 __err |= ios_base::eofbit;
965 return __beg;
966 }
967
968 template<typename _CharT, typename _InIter>
969 _InIter
970 time_get<_CharT, _InIter>::
971 do_get_weekday(iter_type __beg, iter_type __end, ios_base& __io,
972 ios_base::iostate& __err, tm* __tm) const
973 {
974 typedef char_traits<_CharT> __traits_type;
975 const locale& __loc = __io._M_getloc();
976 const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
977 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
978 const char_type* __days[7];
979 __tp._M_days_abbreviated(__days);
980 int __tmpwday;
981 ios_base::iostate __tmperr = ios_base::goodbit;
982 __beg = _M_extract_name(__beg, __end, __tmpwday, __days, 7,
983 __io, __tmperr);
984
985 // Check to see if non-abbreviated name exists, and extract.
986 // NB: Assumes both _M_days and _M_days_abbreviated organized in
987 // exact same order, first to last, such that the resulting
988 // __days array with the same index points to a day, and that
989 // day's abbreviated form.
990 // NB: Also assumes that an abbreviated name is a subset of the name.
991 if (!__tmperr && __beg != __end)
992 {
993 size_t __pos = __traits_type::length(__days[__tmpwday]);
994 __tp._M_days(__days);
995 const char_type* __name = __days[__tmpwday];
996 if (__name[__pos] == *__beg)
997 {
998 // Extract the rest of it.
999 const size_t __len = __traits_type::length(__name);
1000 while (__pos < __len && __beg != __end
1001 && __name[__pos] == *__beg)
1002 ++__beg, ++__pos;
1003 if (__len != __pos)
1004 __tmperr |= ios_base::failbit;
1005 }
1006 }
1007 if (!__tmperr)
1008 __tm->tm_wday = __tmpwday;
1009 else
1010 __err |= ios_base::failbit;
1011
1012 if (__beg == __end)
1013 __err |= ios_base::eofbit;
1014 return __beg;
1015 }
1016
1017 template<typename _CharT, typename _InIter>
1018 _InIter
1019 time_get<_CharT, _InIter>::
1020 do_get_monthname(iter_type __beg, iter_type __end,
1021 ios_base& __io, ios_base::iostate& __err, tm* __tm) const
1022 {
1023 typedef char_traits<_CharT> __traits_type;
1024 const locale& __loc = __io._M_getloc();
1025 const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
1026 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1027 const char_type* __months[12];
1028 __tp._M_months_abbreviated(__months);
1029 int __tmpmon;
1030 ios_base::iostate __tmperr = ios_base::goodbit;
1031 __beg = _M_extract_name(__beg, __end, __tmpmon, __months, 12,
1032 __io, __tmperr);
1033
1034 // Check to see if non-abbreviated name exists, and extract.
1035 // NB: Assumes both _M_months and _M_months_abbreviated organized in
1036 // exact same order, first to last, such that the resulting
1037 // __months array with the same index points to a month, and that
1038 // month's abbreviated form.
1039 // NB: Also assumes that an abbreviated name is a subset of the name.
1040 if (!__tmperr && __beg != __end)
1041 {
1042 size_t __pos = __traits_type::length(__months[__tmpmon]);
1043 __tp._M_months(__months);
1044 const char_type* __name = __months[__tmpmon];
1045 if (__name[__pos] == *__beg)
1046 {
1047 // Extract the rest of it.
1048 const size_t __len = __traits_type::length(__name);
1049 while (__pos < __len && __beg != __end
1050 && __name[__pos] == *__beg)
1051 ++__beg, ++__pos;
1052 if (__len != __pos)
1053 __tmperr |= ios_base::failbit;
1054 }
1055 }
1056 if (!__tmperr)
1057 __tm->tm_mon = __tmpmon;
1058 else
1059 __err |= ios_base::failbit;
1060
1061 if (__beg == __end)
1062 __err |= ios_base::eofbit;
1063 return __beg;
1064 }
1065
1066 template<typename _CharT, typename _InIter>
1067 _InIter
1068 time_get<_CharT, _InIter>::
1069 do_get_year(iter_type __beg, iter_type __end, ios_base& __io,
1070 ios_base::iostate& __err, tm* __tm) const
1071 {
1072 const locale& __loc = __io._M_getloc();
1073 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1074
1075 size_t __i = 0;
1076 int __value = 0;
1077 for (; __beg != __end && __i < 4; ++__beg, ++__i)
1078 {
1079 const char __c = __ctype.narrow(*__beg, '*');
1080 if (__c >= '0' && __c <= '9')
1081 __value = __value * 10 + (__c - '0');
1082 else
1083 break;
1084 }
1085 if (__i == 2 || __i == 4)
1086 __tm->tm_year = __i == 2 ? __value : __value - 1900;
1087 else
1088 __err |= ios_base::failbit;
1089
1090 if (__beg == __end)
1091 __err |= ios_base::eofbit;
1092 return __beg;
1093 }
1094
1095 template<typename _CharT, typename _OutIter>
1096 _OutIter
1097 time_put<_CharT, _OutIter>::
1098 put(iter_type __s, ios_base& __io, char_type __fill, const tm* __tm,
1099 const _CharT* __beg, const _CharT* __end) const
1100 {
1101 const locale& __loc = __io._M_getloc();
1102 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
1103 for (; __beg != __end; ++__beg)
1104 if (__ctype.narrow(*__beg, 0) != '%')
1105 {
1106 *__s = *__beg;
1107 ++__s;
1108 }
1109 else if (++__beg != __end)
1110 {
1111 char __format;
1112 char __mod = 0;
1113 const char __c = __ctype.narrow(*__beg, 0);
1114 if (__c != 'E' && __c != 'O')
1115 __format = __c;
1116 else if (++__beg != __end)
1117 {
1118 __mod = __c;
1119 __format = __ctype.narrow(*__beg, 0);
1120 }
1121 else
1122 break;
1123 __s = this->do_put(__s, __io, __fill, __tm, __format, __mod);
1124 }
1125 else
1126 break;
1127 return __s;
1128 }
1129
1130 template<typename _CharT, typename _OutIter>
1131 _OutIter
1132 time_put<_CharT, _OutIter>::
1133 do_put(iter_type __s, ios_base& __io, char_type, const tm* __tm,
1134 char __format, char __mod) const
1135 {
1136 const locale& __loc = __io._M_getloc();
1137 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
1138 __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc);
1139
1140 // NB: This size is arbitrary. Should this be a data member,
1141 // initialized at construction?
1142 const size_t __maxlen = 128;
1143 char_type* __res =
1144 static_cast<char_type*>(__builtin_alloca(sizeof(char_type) * __maxlen));
1145
1146 // NB: In IEE 1003.1-200x, and perhaps other locale models, it
1147 // is possible that the format character will be longer than one
1148 // character. Possibilities include 'E' or 'O' followed by a
1149 // format character: if __mod is not the default argument, assume
1150 // it's a valid modifier.
1151 char_type __fmt[4];
1152 __fmt[0] = __ctype.widen('%');
1153 if (!__mod)
1154 {
1155 __fmt[1] = __format;
1156 __fmt[2] = char_type();
1157 }
1158 else
1159 {
1160 __fmt[1] = __mod;
1161 __fmt[2] = __format;
1162 __fmt[3] = char_type();
1163 }
1164
1165 __tp._M_put(__res, __maxlen, __fmt, __tm);
1166
1167 // Write resulting, fully-formatted string to output iterator.
1168 return std::__write(__s, __res, char_traits<char_type>::length(__res));
1169 }
1170
1171 // Inhibit implicit instantiations for required instantiations,
1172 // which are defined via explicit instantiations elsewhere.
1173 // NB: This syntax is a GNU extension.
1174#if _GLIBCXX_EXTERN_TEMPLATE
1175 extern template class moneypunct<char, false>;
1176 extern template class moneypunct<char, true>;
1177 extern template class moneypunct_byname<char, false>;
1178 extern template class moneypunct_byname<char, true>;
1179 extern template class _GLIBCXX_LDBL_NAMESPACE money_get<char>;
1180 extern template class _GLIBCXX_LDBL_NAMESPACE money_put<char>;
1181 extern template class __timepunct<char>;
1182 extern template class time_put<char>;
1183 extern template class time_put_byname<char>;
1184 extern template class time_get<char>;
1185 extern template class time_get_byname<char>;
1186 extern template class messages<char>;
1187 extern template class messages_byname<char>;
1188
1189 extern template
1190 const moneypunct<char, true>&
1191 use_facet<moneypunct<char, true> >(const locale&);
1192
1193 extern template
1194 const moneypunct<char, false>&
1195 use_facet<moneypunct<char, false> >(const locale&);
1196
1197 extern template
1198 const money_put<char>&
1199 use_facet<money_put<char> >(const locale&);
1200
1201 extern template
1202 const money_get<char>&
1203 use_facet<money_get<char> >(const locale&);
1204
1205 extern template
1206 const __timepunct<char>&
1207 use_facet<__timepunct<char> >(const locale&);
1208
1209 extern template
1210 const time_put<char>&
1211 use_facet<time_put<char> >(const locale&);
1212
1213 extern template
1214 const time_get<char>&
1215 use_facet<time_get<char> >(const locale&);
1216
1217 extern template
1218 const messages<char>&
1219 use_facet<messages<char> >(const locale&);
1220
1221 extern template
1222 bool
1223 has_facet<moneypunct<char> >(const locale&);
1224
1225 extern template
1226 bool
1227 has_facet<money_put<char> >(const locale&);
1228
1229 extern template
1230 bool
1231 has_facet<money_get<char> >(const locale&);
1232
1233 extern template
1234 bool
1235 has_facet<__timepunct<char> >(const locale&);
1236
1237 extern template
1238 bool
1239 has_facet<time_put<char> >(const locale&);
1240
1241 extern template
1242 bool
1243 has_facet<time_get<char> >(const locale&);
1244
1245 extern template
1246 bool
1247 has_facet<messages<char> >(const locale&);
1248
1249#ifdef _GLIBCXX_USE_WCHAR_T
1250 extern template class moneypunct<wchar_t, false>;
1251 extern template class moneypunct<wchar_t, true>;
1252 extern template class moneypunct_byname<wchar_t, false>;
1253 extern template class moneypunct_byname<wchar_t, true>;
1254 extern template class _GLIBCXX_LDBL_NAMESPACE money_get<wchar_t>;
1255 extern template class _GLIBCXX_LDBL_NAMESPACE money_put<wchar_t>;
1256 extern template class __timepunct<wchar_t>;
1257 extern template class time_put<wchar_t>;
1258 extern template class time_put_byname<wchar_t>;
1259 extern template class time_get<wchar_t>;
1260 extern template class time_get_byname<wchar_t>;
1261 extern template class messages<wchar_t>;
1262 extern template class messages_byname<wchar_t>;
1263
1264 extern template
1265 const moneypunct<wchar_t, true>&
1266 use_facet<moneypunct<wchar_t, true> >(const locale&);
1267
1268 extern template
1269 const moneypunct<wchar_t, false>&
1270 use_facet<moneypunct<wchar_t, false> >(const locale&);
1271
1272 extern template
1273 const money_put<wchar_t>&
1274 use_facet<money_put<wchar_t> >(const locale&);
1275
1276 extern template
1277 const money_get<wchar_t>&
1278 use_facet<money_get<wchar_t> >(const locale&);
1279
1280 extern template
1281 const __timepunct<wchar_t>&
1282 use_facet<__timepunct<wchar_t> >(const locale&);
1283
1284 extern template
1285 const time_put<wchar_t>&
1286 use_facet<time_put<wchar_t> >(const locale&);
1287
1288 extern template
1289 const time_get<wchar_t>&
1290 use_facet<time_get<wchar_t> >(const locale&);
1291
1292 extern template
1293 const messages<wchar_t>&
1294 use_facet<messages<wchar_t> >(const locale&);
1295
1296 extern template
1297 bool
1298 has_facet<moneypunct<wchar_t> >(const locale&);
1299
1300 extern template
1301 bool
1302 has_facet<money_put<wchar_t> >(const locale&);
1303
1304 extern template
1305 bool
1306 has_facet<money_get<wchar_t> >(const locale&);
1307
1308 extern template
1309 bool
1310 has_facet<__timepunct<wchar_t> >(const locale&);
1311
1312 extern template
1313 bool
1314 has_facet<time_put<wchar_t> >(const locale&);
1315
1316 extern template
1317 bool
1318 has_facet<time_get<wchar_t> >(const locale&);
1319
1320 extern template
1321 bool
1322 has_facet<messages<wchar_t> >(const locale&);
1323#endif
1324#endif
1325
1326_GLIBCXX_END_NAMESPACE
1327
1328#endif