libstdc++
locale_facets_nonio.tcc
Go to the documentation of this file.
1// Locale support -*- C++ -*-
2
3// Copyright (C) 2007-2024 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 3, 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// Under Section 7 of GPL version 3, you are granted additional
17// permissions described in the GCC Runtime Library Exception, version
18// 3.1, as published by the Free Software Foundation.
19
20// You should have received a copy of the GNU General Public License and
21// a copy of the GCC Runtime Library Exception along with this program;
22// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23// <http://www.gnu.org/licenses/>.
24
25/** @file bits/locale_facets_nonio.tcc
26 * This is an internal header file, included by other library headers.
27 * Do not attempt to use it directly. @headername{locale}
28 */
29
30#ifndef _LOCALE_FACETS_NONIO_TCC
31#define _LOCALE_FACETS_NONIO_TCC 1
32
33#pragma GCC system_header
34
35namespace std _GLIBCXX_VISIBILITY(default)
36{
37_GLIBCXX_BEGIN_NAMESPACE_VERSION
38
39 template<typename _CharT, bool _Intl>
40 struct __use_cache<__moneypunct_cache<_CharT, _Intl> >
41 {
42 const __moneypunct_cache<_CharT, _Intl>*
43 operator() (const locale& __loc) const
44 {
45 const size_t __i = moneypunct<_CharT, _Intl>::id._M_id();
46 const locale::facet** __caches = __loc._M_impl->_M_caches;
47 if (!__caches[__i])
48 {
49 __moneypunct_cache<_CharT, _Intl>* __tmp = 0;
50 __try
51 {
52 __tmp = new __moneypunct_cache<_CharT, _Intl>;
53 __tmp->_M_cache(__loc);
54 }
55 __catch(...)
56 {
57 delete __tmp;
58 __throw_exception_again;
59 }
60 __loc._M_impl->_M_install_cache(__tmp, __i);
61 }
62 return static_cast<
63 const __moneypunct_cache<_CharT, _Intl>*>(__caches[__i]);
64 }
65 };
66
67 template<typename _CharT, bool _Intl>
68 void
69 __moneypunct_cache<_CharT, _Intl>::_M_cache(const locale& __loc)
70 {
71 const moneypunct<_CharT, _Intl>& __mp =
73
74 struct _Scoped_str
75 {
76 size_t _M_len;
77 _CharT* _M_str;
78
79 explicit
80 _Scoped_str(const basic_string<_CharT>& __str)
81 : _M_len(__str.size()), _M_str(new _CharT[_M_len])
82 { __str.copy(_M_str, _M_len); }
83
84 ~_Scoped_str() { delete[] _M_str; }
85
86 void
87 _M_release(const _CharT*& __p, size_t& __n)
88 {
89 __p = _M_str;
90 __n = _M_len;
91 _M_str = 0;
92 }
93 };
94
95 _Scoped_str __curr_symbol(__mp.curr_symbol());
96 _Scoped_str __positive_sign(__mp.positive_sign());
97 _Scoped_str __negative_sign(__mp.negative_sign());
98
99 const string& __g = __mp.grouping();
100 const size_t __g_size = __g.size();
101 char* const __grouping = new char[__g_size];
102 __g.copy(__grouping, __g_size);
103
104 // All allocations succeeded without throwing, OK to modify *this now.
105
106 _M_grouping = __grouping;
107 _M_grouping_size = __g_size;
108 _M_use_grouping = (__g_size
109 && static_cast<signed char>(__grouping[0]) > 0
110 && (__grouping[0]
111 != __gnu_cxx::__numeric_traits<char>::__max));
112
113 _M_decimal_point = __mp.decimal_point();
114 _M_thousands_sep = __mp.thousands_sep();
115
116 __curr_symbol._M_release(_M_curr_symbol, _M_curr_symbol_size);
117 __positive_sign._M_release(_M_positive_sign, _M_positive_sign_size);
118 __negative_sign._M_release(_M_negative_sign, _M_negative_sign_size);
119
120 _M_frac_digits = __mp.frac_digits();
121 _M_pos_format = __mp.pos_format();
122 _M_neg_format = __mp.neg_format();
123
124 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__loc);
125 __ct.widen(money_base::_S_atoms,
126 money_base::_S_atoms + money_base::_S_end, _M_atoms);
127
128 _M_allocated = true;
129 }
130
131_GLIBCXX_BEGIN_NAMESPACE_LDBL_OR_CXX11
132
133 template<typename _CharT, typename _InIter>
134 template<bool _Intl>
135 _InIter
136 money_get<_CharT, _InIter>::
137 _M_extract(iter_type __beg, iter_type __end, ios_base& __io,
138 ios_base::iostate& __err, string& __units) const
139 {
140 typedef char_traits<_CharT> __traits_type;
141 typedef typename string_type::size_type size_type;
142 typedef money_base::part part;
143 typedef __moneypunct_cache<_CharT, _Intl> __cache_type;
144
145 const locale& __loc = __io._M_getloc();
146 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
147
148 __use_cache<__cache_type> __uc;
149 const __cache_type* __lc = __uc(__loc);
150 const char_type* __lit = __lc->_M_atoms;
151
152 // Deduced sign.
153 bool __negative = false;
154 // Sign size.
155 size_type __sign_size = 0;
156 // True if sign is mandatory.
157 const bool __mandatory_sign = (__lc->_M_positive_sign_size
158 && __lc->_M_negative_sign_size);
159 // String of grouping info from thousands_sep plucked from __units.
160 string __grouping_tmp;
161 if (__lc->_M_use_grouping)
162 __grouping_tmp.reserve(32);
163 // Last position before the decimal point.
164 int __last_pos = 0;
165 // Separator positions, then, possibly, fractional digits.
166 int __n = 0;
167 // If input iterator is in a valid state.
168 bool __testvalid = true;
169 // Flag marking when a decimal point is found.
170 bool __testdecfound = false;
171
172 // The tentative returned string is stored here.
173 string __res;
174 __res.reserve(32);
175
176 const char_type* __lit_zero = __lit + money_base::_S_zero;
177 const money_base::pattern __p = __lc->_M_neg_format;
178 for (int __i = 0; __i < 4 && __testvalid; ++__i)
179 {
180 const part __which = static_cast<part>(__p.field[__i]);
181 switch (__which)
182 {
183 case money_base::symbol:
184 // According to 22.2.6.1.2, p2, symbol is required
185 // if (__io.flags() & ios_base::showbase), otherwise
186 // is optional and consumed only if other characters
187 // are needed to complete the format.
188 if (__io.flags() & ios_base::showbase || __sign_size > 1
189 || __i == 0
190 || (__i == 1 && (__mandatory_sign
191 || (static_cast<part>(__p.field[0])
192 == money_base::sign)
193 || (static_cast<part>(__p.field[2])
194 == money_base::space)))
195 || (__i == 2 && ((static_cast<part>(__p.field[3])
196 == money_base::value)
197 || (__mandatory_sign
198 && (static_cast<part>(__p.field[3])
199 == money_base::sign)))))
200 {
201 const size_type __len = __lc->_M_curr_symbol_size;
202 size_type __j = 0;
203 for (; __beg != __end && __j < __len
204 && *__beg == __lc->_M_curr_symbol[__j];
205 ++__beg, (void)++__j);
206 if (__j != __len
207 && (__j || __io.flags() & ios_base::showbase))
208 __testvalid = false;
209 }
210 break;
211 case money_base::sign:
212 // Sign might not exist, or be more than one character long.
213 if (__lc->_M_positive_sign_size && __beg != __end
214 && *__beg == __lc->_M_positive_sign[0])
215 {
216 __sign_size = __lc->_M_positive_sign_size;
217 ++__beg;
218 }
219 else if (__lc->_M_negative_sign_size && __beg != __end
220 && *__beg == __lc->_M_negative_sign[0])
221 {
222 __negative = true;
223 __sign_size = __lc->_M_negative_sign_size;
224 ++__beg;
225 }
226 else if (__lc->_M_positive_sign_size
227 && !__lc->_M_negative_sign_size)
228 // "... if no sign is detected, the result is given the sign
229 // that corresponds to the source of the empty string"
230 __negative = true;
231 else if (__mandatory_sign)
232 __testvalid = false;
233 break;
234 case money_base::value:
235 // Extract digits, remove and stash away the
236 // grouping of found thousands separators.
237 for (; __beg != __end; ++__beg)
238 {
239 const char_type __c = *__beg;
240 const char_type* __q = __traits_type::find(__lit_zero,
241 10, __c);
242 if (__q != 0)
243 {
244 __res += money_base::_S_atoms[__q - __lit];
245 ++__n;
246 }
247 else if (__c == __lc->_M_decimal_point
248 && !__testdecfound)
249 {
250 if (__lc->_M_frac_digits <= 0)
251 break;
252
253 __last_pos = __n;
254 __n = 0;
255 __testdecfound = true;
256 }
257 else if (__lc->_M_use_grouping
258 && __c == __lc->_M_thousands_sep
259 && !__testdecfound)
260 {
261 if (__n)
262 {
263 // Mark position for later analysis.
264 __grouping_tmp += static_cast<char>(__n);
265 __n = 0;
266 }
267 else
268 {
269 __testvalid = false;
270 break;
271 }
272 }
273 else
274 break;
275 }
276 if (__res.empty())
277 __testvalid = false;
278 break;
279 case money_base::space:
280 // At least one space is required.
281 if (__beg != __end && __ctype.is(ctype_base::space, *__beg))
282 ++__beg;
283 else
284 __testvalid = false;
285 // fallthrough
286 case money_base::none:
287 // Only if not at the end of the pattern.
288 if (__i != 3)
289 for (; __beg != __end
290 && __ctype.is(ctype_base::space, *__beg); ++__beg);
291 break;
292 }
293 }
294
295 // Need to get the rest of the sign characters, if they exist.
296 if (__sign_size > 1 && __testvalid)
297 {
298 const char_type* __sign = __negative ? __lc->_M_negative_sign
299 : __lc->_M_positive_sign;
300 size_type __i = 1;
301 for (; __beg != __end && __i < __sign_size
302 && *__beg == __sign[__i]; ++__beg, (void)++__i);
303
304 if (__i != __sign_size)
305 __testvalid = false;
306 }
307
308 if (__testvalid)
309 {
310 // Strip leading zeros.
311 if (__res.size() > 1)
312 {
313 const size_type __first = __res.find_first_not_of('0');
314 const bool __only_zeros = __first == string::npos;
315 if (__first)
316 __res.erase(0, __only_zeros ? __res.size() - 1 : __first);
317 }
318
319 // 22.2.6.1.2, p4
320 if (__negative && __res[0] != '0')
321 __res.insert(__res.begin(), '-');
322
323 // Test for grouping fidelity.
324 if (__grouping_tmp.size())
325 {
326 // Add the ending grouping.
327 __grouping_tmp += static_cast<char>(__testdecfound ? __last_pos
328 : __n);
329 if (!std::__verify_grouping(__lc->_M_grouping,
330 __lc->_M_grouping_size,
331 __grouping_tmp))
332 __err |= ios_base::failbit;
333 }
334
335 // Iff not enough digits were supplied after the decimal-point.
336 if (__testdecfound && __n != __lc->_M_frac_digits)
337 __testvalid = false;
338 }
339
340 // Iff valid sequence is not recognized.
341 if (!__testvalid)
342 __err |= ios_base::failbit;
343 else
344 __units.swap(__res);
345
346 // Iff no more characters are available.
347 if (__beg == __end)
348 __err |= ios_base::eofbit;
349 return __beg;
350 }
351
352#if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__ \
353 && (_GLIBCXX_USE_CXX11_ABI == 0 || defined __LONG_DOUBLE_IEEE128__)
354 template<typename _CharT, typename _InIter>
355 _InIter
356 money_get<_CharT, _InIter>::
357 __do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
358 ios_base::iostate& __err, double& __units) const
359 {
360 string __str;
361 __beg = __intl ? _M_extract<true>(__beg, __end, __io, __err, __str)
362 : _M_extract<false>(__beg, __end, __io, __err, __str);
363 std::__convert_to_v(__str.c_str(), __units, __err, _S_get_c_locale());
364 return __beg;
365 }
366#endif
367
368 template<typename _CharT, typename _InIter>
369 _InIter
371 do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
372 ios_base::iostate& __err, long double& __units) const
373 {
374 string __str;
375 __beg = __intl ? _M_extract<true>(__beg, __end, __io, __err, __str)
376 : _M_extract<false>(__beg, __end, __io, __err, __str);
377 std::__convert_to_v(__str.c_str(), __units, __err, _S_get_c_locale());
378 return __beg;
379 }
380
381 template<typename _CharT, typename _InIter>
382 _InIter
384 do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
385 ios_base::iostate& __err, string_type& __digits) const
386 {
387 typedef typename string::size_type size_type;
388
389 const locale& __loc = __io._M_getloc();
390 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
391
392 string __str;
393 __beg = __intl ? _M_extract<true>(__beg, __end, __io, __err, __str)
394 : _M_extract<false>(__beg, __end, __io, __err, __str);
395 const size_type __len = __str.size();
396 if (__len)
397 {
398 __digits.resize(__len);
399 __ctype.widen(__str.data(), __str.data() + __len, &__digits[0]);
400 }
401 return __beg;
402 }
403
404#if defined _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT \
405 && defined __LONG_DOUBLE_IEEE128__
406 template<typename _CharT, typename _InIter>
407 _InIter
409 __do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
410 ios_base::iostate& __err, __ibm128& __units) const
411 {
412 string __str;
413 __beg = __intl ? _M_extract<true>(__beg, __end, __io, __err, __str)
414 : _M_extract<false>(__beg, __end, __io, __err, __str);
415 std::__convert_to_v(__str.c_str(), __units, __err, _S_get_c_locale());
416 return __beg;
417 }
418#endif
419
420 template<typename _CharT, typename _OutIter>
421 template<bool _Intl>
422 _OutIter
423 money_put<_CharT, _OutIter>::
424 _M_insert(iter_type __s, ios_base& __io, char_type __fill,
425 const string_type& __digits) const
426 {
427 typedef typename string_type::size_type size_type;
428 typedef money_base::part part;
429 typedef __moneypunct_cache<_CharT, _Intl> __cache_type;
430
431 const locale& __loc = __io._M_getloc();
432 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
433
434 __use_cache<__cache_type> __uc;
435 const __cache_type* __lc = __uc(__loc);
436 const char_type* __lit = __lc->_M_atoms;
437
438 // Determine if negative or positive formats are to be used, and
439 // discard leading negative_sign if it is present.
440 const char_type* __beg = __digits.data();
441
442 money_base::pattern __p;
443 const char_type* __sign;
444 size_type __sign_size;
445 if (!(*__beg == __lit[money_base::_S_minus]))
446 {
447 __p = __lc->_M_pos_format;
448 __sign = __lc->_M_positive_sign;
449 __sign_size = __lc->_M_positive_sign_size;
450 }
451 else
452 {
453 __p = __lc->_M_neg_format;
454 __sign = __lc->_M_negative_sign;
455 __sign_size = __lc->_M_negative_sign_size;
456 if (__digits.size())
457 ++__beg;
458 }
459
460 // Look for valid numbers in the ctype facet within input digits.
461 size_type __len = __ctype.scan_not(ctype_base::digit, __beg,
462 __beg + __digits.size()) - __beg;
463 if (__len)
464 {
465 // Assume valid input, and attempt to format.
466 // Break down input numbers into base components, as follows:
467 // final_value = grouped units + (decimal point) + (digits)
468 string_type __value;
469 __value.reserve(2 * __len);
470
471 // Add thousands separators to non-decimal digits, per
472 // grouping rules.
473 long __paddec = __len - __lc->_M_frac_digits;
474 if (__paddec > 0)
475 {
476 if (__lc->_M_frac_digits < 0)
477 __paddec = __len;
478 if (__lc->_M_grouping_size)
479 {
480 __value.assign(2 * __paddec, char_type());
481 _CharT* __vend =
482 std::__add_grouping(&__value[0], __lc->_M_thousands_sep,
483 __lc->_M_grouping,
484 __lc->_M_grouping_size,
485 __beg, __beg + __paddec);
486 __value.erase(__vend - &__value[0]);
487 }
488 else
489 __value.assign(__beg, __paddec);
490 }
491
492 // Deal with decimal point, decimal digits.
493 if (__lc->_M_frac_digits > 0)
494 {
495 __value += __lc->_M_decimal_point;
496 if (__paddec >= 0)
497 __value.append(__beg + __paddec, __lc->_M_frac_digits);
498 else
499 {
500 // Have to pad zeros in the decimal position.
501 __value.append(-__paddec, __lit[money_base::_S_zero]);
502 __value.append(__beg, __len);
503 }
504 }
505
506 // Calculate length of resulting string.
507 const ios_base::fmtflags __f = __io.flags()
509 __len = __value.size() + __sign_size;
510 __len += ((__io.flags() & ios_base::showbase)
511 ? __lc->_M_curr_symbol_size : 0);
512
513 string_type __res;
514 __res.reserve(2 * __len);
515
516 const size_type __width = static_cast<size_type>(__io.width());
517 const bool __testipad = (__f == ios_base::internal
518 && __len < __width);
519 // Fit formatted digits into the required pattern.
520 for (int __i = 0; __i < 4; ++__i)
521 {
522 const part __which = static_cast<part>(__p.field[__i]);
523 switch (__which)
524 {
525 case money_base::symbol:
526 if (__io.flags() & ios_base::showbase)
527 __res.append(__lc->_M_curr_symbol,
528 __lc->_M_curr_symbol_size);
529 break;
530 case money_base::sign:
531 // Sign might not exist, or be more than one
532 // character long. In that case, add in the rest
533 // below.
534 if (__sign_size)
535 __res += __sign[0];
536 break;
537 case money_base::value:
538 __res += __value;
539 break;
540 case money_base::space:
541 // At least one space is required, but if internal
542 // formatting is required, an arbitrary number of
543 // fill spaces will be necessary.
544 if (__testipad)
545 __res.append(__width - __len, __fill);
546 else
547 __res += __fill;
548 break;
549 case money_base::none:
550 if (__testipad)
551 __res.append(__width - __len, __fill);
552 break;
553 }
554 }
555
556 // Special case of multi-part sign parts.
557 if (__sign_size > 1)
558 __res.append(__sign + 1, __sign_size - 1);
559
560 // Pad, if still necessary.
561 __len = __res.size();
562 if (__width > __len)
563 {
564 if (__f == ios_base::left)
565 // After.
566 __res.append(__width - __len, __fill);
567 else
568 // Before.
569 __res.insert(0, __width - __len, __fill);
570 __len = __width;
571 }
572
573 // Write resulting, fully-formatted string to output iterator.
574 __s = std::__write(__s, __res.data(), __len);
575 }
576 __io.width(0);
577 return __s;
578 }
579
580#if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__ \
581 && (_GLIBCXX_USE_CXX11_ABI == 0 || defined __LONG_DOUBLE_IEEE128__)
582 template<typename _CharT, typename _OutIter>
583 _OutIter
584 money_put<_CharT, _OutIter>::
585 __do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
586 double __units) const
587 { return this->do_put(__s, __intl, __io, __fill, (long double) __units); }
588#endif
589
590 template<typename _CharT, typename _OutIter>
591 _OutIter
593 do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
594 long double __units) const
595 {
596 const locale __loc = __io.getloc();
597 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
598#if _GLIBCXX_USE_C99_STDIO
599 // First try a buffer perhaps big enough.
600 int __cs_size = 64;
601 char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
602 // _GLIBCXX_RESOLVE_LIB_DEFECTS
603 // 328. Bad sprintf format modifier in money_put<>::do_put()
604 int __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
605 "%.*Lf", 0, __units);
606 // If the buffer was not large enough, try again with the correct size.
607 if (__len >= __cs_size)
608 {
609 __cs_size = __len + 1;
610 __cs = static_cast<char*>(__builtin_alloca(__cs_size));
611 __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
612 "%.*Lf", 0, __units);
613 }
614#else
615 // max_exponent10 + 1 for the integer part, + 2 for sign and '\0'.
616 const int __cs_size =
617 __gnu_cxx::__numeric_traits<long double>::__max_exponent10 + 3;
618 char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
619 int __len = std::__convert_from_v(_S_get_c_locale(), __cs, 0, "%.*Lf",
620 0, __units);
621#endif
622 string_type __digits(__len, char_type());
623 __ctype.widen(__cs, __cs + __len, &__digits[0]);
624 return __intl ? _M_insert<true>(__s, __io, __fill, __digits)
625 : _M_insert<false>(__s, __io, __fill, __digits);
626 }
627
628 template<typename _CharT, typename _OutIter>
629 _OutIter
631 do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
632 const string_type& __digits) const
633 { return __intl ? _M_insert<true>(__s, __io, __fill, __digits)
634 : _M_insert<false>(__s, __io, __fill, __digits); }
635
636#if defined _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT \
637 && defined __LONG_DOUBLE_IEEE128__
638extern "C"
639__typeof__(__builtin_snprintf) __glibcxx_snprintfibm128 __asm__("snprintf");
640
641 template<typename _CharT, typename _OutIter>
642 _OutIter
644 __do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
645 __ibm128 __units) const
646 {
647 const locale __loc = __io.getloc();
648 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
649 // First try a buffer perhaps big enough.
650 int __cs_size = 64;
651 char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
652 const __c_locale __old = __gnu_cxx::__uselocale(_S_get_c_locale());
653
654 // _GLIBCXX_RESOLVE_LIB_DEFECTS
655 // 328. Bad sprintf format modifier in money_put<>::do_put()
656 int __len = __glibcxx_snprintfibm128(__cs, __cs_size, "%.*Lf", 0,
657 __units);
658 // If the buffer was not large enough, try again with the correct size.
659 if (__len >= __cs_size)
660 {
661 __cs_size = __len + 1;
662 __cs = static_cast<char*>(__builtin_alloca(__cs_size));
663 __len = __glibcxx_snprintfibm128(__cs, __cs_size, "%.*Lf", 0,
664 __units);
665 }
666 __gnu_cxx::__uselocale(__old);
667 string_type __digits(__len, char_type());
668 __ctype.widen(__cs, __cs + __len, &__digits[0]);
669 return __intl ? _M_insert<true>(__s, __io, __fill, __digits)
670 : _M_insert<false>(__s, __io, __fill, __digits);
671 }
672#endif
674_GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11
675
676 // NB: Not especially useful. Without an ios_base object or some
677 // kind of locale reference, we are left clawing at the air where
678 // the side of the mountain used to be...
679 template<typename _CharT, typename _InIter>
680 time_base::dateorder
682 { return time_base::no_order; }
683
684 // Expand a strptime format string and parse it. E.g., do_get_date() may
685 // pass %m/%d/%Y => extracted characters.
686 template<typename _CharT, typename _InIter>
687 _InIter
689 _M_extract_via_format(iter_type __beg, iter_type __end, ios_base& __io,
690 ios_base::iostate& __err, tm* __tm,
691 const _CharT* __format,
692 __time_get_state &__state) const
693 {
694 const locale& __loc = __io._M_getloc();
695 const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
696 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
697 const size_t __len = char_traits<_CharT>::length(__format);
698
699 ios_base::iostate __tmperr = ios_base::goodbit;
700 size_t __i = 0;
701 for (; __beg != __end && __i < __len && !__tmperr; ++__i)
702 {
703 if (__ctype.narrow(__format[__i], 0) == '%')
704 {
705 // Verify valid formatting code, attempt to extract.
706 char __c = __ctype.narrow(__format[++__i], 0);
707 int __mem = 0;
708 if (__c == 'E' || __c == 'O')
709 __c = __ctype.narrow(__format[++__i], 0);
710 switch (__c)
712 const char* __cs;
713 _CharT __wcs[10];
714 case 'a':
715 case 'A':
716 // Weekday name (possibly abbreviated) [tm_wday]
717 const char_type* __days[14];
718 __tp._M_days(&__days[0]);
719 __tp._M_days_abbreviated(&__days[7]);
720 __beg = _M_extract_name(__beg, __end, __mem, __days,
721 14, __io, __tmperr);
722 if (!__tmperr)
723 {
724 __tm->tm_wday = __mem % 7;
725 __state._M_have_wday = 1;
726 }
727 break;
728 case 'h':
729 case 'b':
730 case 'B':
731 // Month name (possibly abbreviated) [tm_mon]
732 const char_type* __months[24];
733 __tp._M_months(&__months[0]);
734 __tp._M_months_abbreviated(&__months[12]);
735 __beg = _M_extract_name(__beg, __end, __mem,
736 __months, 24, __io, __tmperr);
737 if (!__tmperr)
738 {
739 __tm->tm_mon = __mem % 12;
740 __state._M_have_mon = 1;
741 __state._M_want_xday = 1;
742 }
743 break;
744 case 'c':
745 // Default time and date representation.
746 const char_type* __dt[2];
747 __tp._M_date_time_formats(__dt);
748 __beg = _M_extract_via_format(__beg, __end, __io, __tmperr,
749 __tm, __dt[0], __state);
750 if (!__tmperr)
751 __state._M_want_xday = 1;
752 break;
753 case 'C':
754 // Century.
755 __beg = _M_extract_num(__beg, __end, __mem, 0, 99, 2,
756 __io, __tmperr);
757 if (!__tmperr)
758 {
759 __state._M_century = __mem;
760 __state._M_have_century = 1;
761 __state._M_want_xday = 1;
762 }
763 break;
764 case 'd':
765 case 'e':
766 // Day [1, 31]. [tm_mday]
767 if (__ctype.is(ctype_base::space, *__beg))
768 ++__beg;
769 __beg = _M_extract_num(__beg, __end, __mem, 1, 31, 2,
770 __io, __tmperr);
771 if (!__tmperr)
772 {
773 __tm->tm_mday = __mem;
774 __state._M_have_mday = 1;
775 __state._M_want_xday = 1;
776 }
777 break;
778 case 'D':
779 // Equivalent to %m/%d/%y.[tm_mon, tm_mday, tm_year]
780 __cs = "%m/%d/%y";
781 __ctype.widen(__cs, __cs + 9, __wcs);
782 __beg = _M_extract_via_format(__beg, __end, __io, __tmperr,
783 __tm, __wcs, __state);
784 if (!__tmperr)
785 __state._M_want_xday = 1;
786 break;
787 case 'H':
788 // Hour [00, 23]. [tm_hour]
789 __beg = _M_extract_num(__beg, __end, __mem, 0, 23, 2,
790 __io, __tmperr);
791 if (!__tmperr)
792 {
793 __tm->tm_hour = __mem;
794 __state._M_have_I = 0;
795 }
796 break;
797 case 'I':
798 // Hour [01, 12]. [tm_hour]
799 __beg = _M_extract_num(__beg, __end, __mem, 1, 12, 2,
800 __io, __tmperr);
801 if (!__tmperr)
802 {
803 __tm->tm_hour = __mem % 12;
804 __state._M_have_I = 1;
805 }
806 break;
807 case 'j':
808 // Day number of year.
809 __beg = _M_extract_num(__beg, __end, __mem, 1, 366, 3,
810 __io, __tmperr);
811 if (!__tmperr)
812 {
813 __tm->tm_yday = __mem - 1;
814 __state._M_have_yday = 1;
815 }
816 break;
817 case 'm':
818 // Month [01, 12]. [tm_mon]
819 __beg = _M_extract_num(__beg, __end, __mem, 1, 12, 2,
820 __io, __tmperr);
821 if (!__tmperr)
822 {
823 __tm->tm_mon = __mem - 1;
824 __state._M_have_mon = 1;
825 }
826 break;
827 case 'M':
828 // Minute [00, 59]. [tm_min]
829 __beg = _M_extract_num(__beg, __end, __mem, 0, 59, 2,
830 __io, __tmperr);
831 if (!__tmperr)
832 __tm->tm_min = __mem;
833 break;
834 case 'n':
835 case 't':
836 while (__beg != __end
837 && __ctype.is(ctype_base::space, *__beg))
838 ++__beg;
839 break;
840 case 'p':
841 // Locale's a.m. or p.m.
842 const char_type* __ampm[2];
843 __tp._M_am_pm(&__ampm[0]);
844 if (!__ampm[0][0] || !__ampm[1][0])
845 break;
846 __beg = _M_extract_name(__beg, __end, __mem, __ampm,
847 2, __io, __tmperr);
848 if (!__tmperr && __mem)
849 __state._M_is_pm = 1;
850 break;
851 case 'r':
852 // Locale's 12-hour clock time format (in C %I:%M:%S %p).
853 const char_type* __ampm_format;
854 __tp._M_am_pm_format(&__ampm_format);
855 __beg = _M_extract_via_format(__beg, __end, __io, __tmperr,
856 __tm, __ampm_format, __state);
857 break;
858 case 'R':
859 // Equivalent to (%H:%M).
860 __cs = "%H:%M";
861 __ctype.widen(__cs, __cs + 6, __wcs);
862 __beg = _M_extract_via_format(__beg, __end, __io, __tmperr,
863 __tm, __wcs, __state);
864 break;
865 case 'S':
866 // Seconds. [tm_sec]
867 // [00, 60] in C99 (one leap-second), [00, 61] in C89.
868#if _GLIBCXX_USE_C99
869 __beg = _M_extract_num(__beg, __end, __mem, 0, 60, 2,
870#else
871 __beg = _M_extract_num(__beg, __end, __mem, 0, 61, 2,
872#endif
873 __io, __tmperr);
874 if (!__tmperr)
875 __tm->tm_sec = __mem;
876 break;
877 case 'T':
878 // Equivalent to (%H:%M:%S).
879 __cs = "%H:%M:%S";
880 __ctype.widen(__cs, __cs + 9, __wcs);
881 __beg = _M_extract_via_format(__beg, __end, __io, __tmperr,
882 __tm, __wcs, __state);
883 break;
884 case 'U':
885 // Week number of the year (Sunday as first day of week).
886 __beg = _M_extract_num(__beg, __end, __mem, 0, 53, 2,
887 __io, __tmperr);
888 if (!__tmperr)
889 {
890 __state._M_week_no = __mem;
891 __state._M_have_uweek = 1;
892 }
893 break;
894 case 'w':
895 // Weekday [tm_wday]
896 __beg = _M_extract_num(__beg, __end, __mem, 0, 6, 1,
897 __io, __tmperr);
898 if (!__tmperr)
899 {
900 __tm->tm_wday = __mem;
901 __state._M_have_wday = 1;
902 }
903 break;
904 case 'W':
905 // Week number of the year (Monday as first day of week).
906 __beg = _M_extract_num(__beg, __end, __mem, 0, 53, 2,
907 __io, __tmperr);
908 if (!__tmperr)
909 {
910 __state._M_week_no = __mem;
911 __state._M_have_wweek = 1;
912 }
913 break;
914 case 'x':
915 // Locale's date.
916 const char_type* __dates[2];
917 __tp._M_date_formats(__dates);
918 __beg = _M_extract_via_format(__beg, __end, __io, __tmperr,
919 __tm, __dates[0], __state);
920 break;
921 case 'X':
922 // Locale's time.
923 const char_type* __times[2];
924 __tp._M_time_formats(__times);
925 __beg = _M_extract_via_format(__beg, __end, __io, __tmperr,
926 __tm, __times[0], __state);
927 break;
928 case 'y':
929 // The last 2 digits of year.
930 __beg = _M_extract_num(__beg, __end, __mem, 0, 99, 2,
931 __io, __tmperr);
932 if (!__tmperr)
933 {
934 __state._M_want_century = 1;
935 __state._M_want_xday = 1;
936 // As an extension, if the 2 digits are followed by
937 // 1-2 further digits, treat it like %Y.
938 __c = 0;
939 if (__beg != __end)
940 __c = __ctype.narrow(*__beg, '*');
941 if (__c >= '0' && __c <= '9')
942 {
943 ++__beg;
944 __mem = __mem * 10 + (__c - '0');
945 if (__beg != __end)
946 {
947 __c = __ctype.narrow(*__beg, '*');
948 if (__c >= '0' && __c <= '9')
949 {
950 ++__beg;
951 __mem = __mem * 10 + (__c - '0');
952 }
953 }
954 __mem -= 1900;
955 __state._M_want_century = 0;
956 }
957 // Otherwise, as per POSIX 2008, 00-68 is 2000-2068,
958 // while 69-99 is 1969-1999.
959 else if (__mem < 69)
960 __mem += 100;
961 __tm->tm_year = __mem;
962 }
963 break;
964 case 'Y':
965 // Year.
966 __beg = _M_extract_num(__beg, __end, __mem, 0, 9999, 4,
967 __io, __tmperr);
968 if (!__tmperr)
969 {
970 __tm->tm_year = __mem - 1900;
971 __state._M_want_century = 0;
972 __state._M_want_xday = 1;
973 }
974 break;
975 case 'Z':
976 // Timezone info.
977 if (__ctype.is(ctype_base::upper, *__beg))
978 {
979 int __tmp;
980 __beg = _M_extract_name(__beg, __end, __tmp,
981 __timepunct_cache<_CharT>::_S_timezones,
982 14, __io, __tmperr);
983
984 // GMT requires special effort.
985 if (__beg != __end && !__tmperr && __tmp == 0
986 && (*__beg == __ctype.widen('-')
987 || *__beg == __ctype.widen('+')))
988 {
989 __beg = _M_extract_num(__beg, __end, __tmp, 0, 23, 2,
990 __io, __tmperr);
991 __beg = _M_extract_num(__beg, __end, __tmp, 0, 59, 2,
992 __io, __tmperr);
993 }
994 }
995 else
996 __tmperr |= ios_base::failbit;
997 break;
998 case '%':
999 if (*__beg == __ctype.widen('%'))
1000 ++__beg;
1001 else
1002 __tmperr |= ios_base::failbit;
1003 break;
1004 default:
1005 // Not recognized.
1006 __tmperr |= ios_base::failbit;
1007 }
1008 }
1009 else if (__ctype.is(ctype_base::space, __format[__i]))
1010 {
1011 // Skip any whitespace.
1012 while (__beg != __end
1013 && __ctype.is(ctype_base::space, *__beg))
1014 ++__beg;
1015 }
1016 else
1017 {
1018 // Verify format and input match, extract and discard.
1019 // TODO real case-insensitive comparison
1020 if (__ctype.tolower(__format[__i]) == __ctype.tolower(*__beg)
1021 || __ctype.toupper(__format[__i]) == __ctype.toupper(*__beg))
1022 ++__beg;
1023 else
1024 __tmperr |= ios_base::failbit;
1025 }
1026 }
1027
1028 if (__tmperr || __i != __len)
1029 __err |= ios_base::failbit;
1030
1031 return __beg;
1032 }
1033
1034 template<typename _CharT, typename _InIter>
1035 _InIter
1036 time_get<_CharT, _InIter>::
1037 _M_extract_via_format(iter_type __beg, iter_type __end, ios_base& __io,
1038 ios_base::iostate& __err, tm* __tm,
1039 const _CharT* __format) const
1040 {
1041 __time_get_state __state = __time_get_state();
1042 return _M_extract_via_format(__beg, __end, __io, __err, __tm,
1043 __format, __state);
1044 }
1045
1046 template<typename _CharT, typename _InIter>
1047 _InIter
1048 time_get<_CharT, _InIter>::
1049 _M_extract_num(iter_type __beg, iter_type __end, int& __member,
1050 int __min, int __max, size_t __len,
1051 ios_base& __io, ios_base::iostate& __err) const
1052 {
1053 const locale& __loc = __io._M_getloc();
1054 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1055
1056 size_t __i = 0;
1057 int __value = 0;
1058 for (; __beg != __end && __i < __len; ++__beg, (void)++__i)
1059 {
1060 const char __c = __ctype.narrow(*__beg, '*');
1061 if (__c >= '0' && __c <= '9')
1062 {
1063 __value = __value * 10 + (__c - '0');
1064 if (__value > __max)
1065 break;
1066 }
1067 else
1068 break;
1069 }
1070 if (__i && __value >= __min && __value <= __max)
1071 __member = __value;
1072 else
1073 __err |= ios_base::failbit;
1074
1075 return __beg;
1076 }
1077
1078 // Assumptions:
1079 // All elements in __names are unique, except if __indexlen is
1080 // even __names in the first half could be the same as corresponding
1081 // __names in the second half (May is abbreviated as May). Some __names
1082 // elements could be prefixes of other __names elements.
1083 template<typename _CharT, typename _InIter>
1084 _InIter
1085 time_get<_CharT, _InIter>::
1086 _M_extract_name(iter_type __beg, iter_type __end, int& __member,
1087 const _CharT** __names, size_t __indexlen,
1088 ios_base& __io, ios_base::iostate& __err) const
1089 {
1090 typedef char_traits<_CharT> __traits_type;
1091 const locale& __loc = __io._M_getloc();
1092 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1093
1094 size_t* __matches
1095 = static_cast<size_t*>(__builtin_alloca(2 * sizeof(size_t)
1096 * __indexlen));
1097 size_t* __lengths = __matches + __indexlen;
1098 size_t __nmatches = 0;
1099 size_t __pos = 0;
1100 bool __testvalid = true;
1101 const char_type* __name;
1102 bool __begupdated = false;
1103
1104 // Look for initial matches.
1105 if (__beg != __end)
1106 {
1107 const char_type __c = *__beg;
1108 // TODO real case-insensitive comparison
1109 const char_type __cl = __ctype.tolower(__c);
1110 const char_type __cu = __ctype.toupper(__c);
1111 for (size_t __i1 = 0; __i1 < __indexlen; ++__i1)
1112 if (__cl == __ctype.tolower(__names[__i1][0])
1113 || __cu == __ctype.toupper(__names[__i1][0]))
1114 {
1115 __lengths[__nmatches]
1116 = __traits_type::length(__names[__i1]);
1117 __matches[__nmatches++] = __i1;
1118 }
1119 }
1120
1121 while (__nmatches > 1)
1122 {
1123 // Find smallest matching string.
1124 size_t __minlen = __lengths[0];
1125 for (size_t __i2 = 1; __i2 < __nmatches; ++__i2)
1126 __minlen = std::min(__minlen, __lengths[__i2]);
1127 ++__pos;
1128 ++__beg;
1129 if (__pos == __minlen)
1130 {
1131 // If some match has remaining length of 0,
1132 // need to decide if any match with remaining
1133 // length non-zero matches the next character.
1134 // If so, remove all matches with remaining length
1135 // 0 from consideration, otherwise keep only matches
1136 // with remaining length 0.
1137 bool __match_longer = false;
1138
1139 if (__beg != __end)
1140 {
1141 // TODO real case-insensitive comparison
1142 const char_type __cl = __ctype.tolower(*__beg);
1143 const char_type __cu = __ctype.toupper(*__beg);
1144 for (size_t __i3 = 0; __i3 < __nmatches; ++__i3)
1145 {
1146 __name = __names[__matches[__i3]];
1147 if (__lengths[__i3] > __pos
1148 && (__ctype.tolower(__name[__pos]) == __cl
1149 || __ctype.toupper(__name[__pos]) == __cu))
1150 {
1151 __match_longer = true;
1152 break;
1153 }
1154 }
1155 }
1156 for (size_t __i4 = 0; __i4 < __nmatches;)
1157 if (__match_longer == (__lengths[__i4] == __pos))
1158 {
1159 __matches[__i4] = __matches[--__nmatches];
1160 __lengths[__i4] = __lengths[__nmatches];
1161 }
1162 else
1163 ++__i4;
1164 if (__match_longer)
1165 {
1166 __minlen = __lengths[0];
1167 for (size_t __i5 = 1; __i5 < __nmatches; ++__i5)
1168 __minlen = std::min(__minlen, __lengths[__i5]);
1169 }
1170 else
1171 {
1172 // Deal with May being full as well as abbreviated month
1173 // name. Pick the smaller index.
1174 if (__nmatches == 2 && (__indexlen & 1) == 0)
1175 {
1176 if (__matches[0] < __indexlen / 2)
1177 {
1178 if (__matches[1] == __matches[0] + __indexlen / 2)
1179 __nmatches = 1;
1180 }
1181 else if (__matches[1] == __matches[0] - __indexlen / 2)
1182 {
1183 __matches[0] = __matches[1];
1184 __lengths[0] = __lengths[1];
1185 __nmatches = 1;
1186 }
1187 }
1188 __begupdated = true;
1189 break;
1190 }
1191 }
1192 if (__pos < __minlen && __beg != __end)
1193 {
1194 // TODO real case-insensitive comparison
1195 const char_type __cl = __ctype.tolower(*__beg);
1196 const char_type __cu = __ctype.toupper(*__beg);
1197 for (size_t __i6 = 0; __i6 < __nmatches;)
1198 {
1199 __name = __names[__matches[__i6]];
1200 if (__ctype.tolower(__name[__pos]) != __cl
1201 && __ctype.toupper(__name[__pos]) != __cu)
1202 {
1203 __matches[__i6] = __matches[--__nmatches];
1204 __lengths[__i6] = __lengths[__nmatches];
1205 }
1206 else
1207 ++__i6;
1208 }
1209 }
1210 else
1211 break;
1212 }
1213
1214 if (__nmatches == 1)
1215 {
1216 // Make sure found name is completely extracted.
1217 if (!__begupdated)
1218 {
1219 ++__beg;
1220 ++__pos;
1221 }
1222 __name = __names[__matches[0]];
1223 const size_t __len = __lengths[0];
1224 while (__pos < __len
1225 && __beg != __end
1226 // TODO real case-insensitive comparison
1227 && (__ctype.tolower(__name[__pos]) == __ctype.tolower(*__beg)
1228 || (__ctype.toupper(__name[__pos])
1229 == __ctype.toupper(*__beg))))
1230 ++__beg, (void)++__pos;
1231
1232 if (__len == __pos)
1233 __member = __matches[0];
1234 else
1235 __testvalid = false;
1236 }
1237 else
1238 __testvalid = false;
1239 if (!__testvalid)
1240 __err |= ios_base::failbit;
1241
1242 return __beg;
1243 }
1244
1245 template<typename _CharT, typename _InIter>
1246 _InIter
1247 time_get<_CharT, _InIter>::
1248 _M_extract_wday_or_month(iter_type __beg, iter_type __end, int& __member,
1249 const _CharT** __names, size_t __indexlen,
1250 ios_base& __io, ios_base::iostate& __err) const
1251 {
1252 typedef char_traits<_CharT> __traits_type;
1253 const locale& __loc = __io._M_getloc();
1254 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1255
1256 int* __matches = static_cast<int*>(__builtin_alloca(2 * sizeof(int)
1257 * __indexlen));
1258 size_t __nmatches = 0;
1259 size_t* __matches_lengths = 0;
1260 size_t __pos = 0;
1261
1262 if (__beg != __end)
1263 {
1264 const char_type __c = *__beg;
1265 for (size_t __i = 0; __i < 2 * __indexlen; ++__i)
1266 if (__c == __names[__i][0]
1267 || __c == __ctype.toupper(__names[__i][0]))
1268 __matches[__nmatches++] = __i;
1269 }
1270
1271 if (__nmatches)
1272 {
1273 ++__beg;
1274 ++__pos;
1275
1276 __matches_lengths
1277 = static_cast<size_t*>(__builtin_alloca(sizeof(size_t)
1278 * __nmatches));
1279 for (size_t __i = 0; __i < __nmatches; ++__i)
1280 __matches_lengths[__i]
1281 = __traits_type::length(__names[__matches[__i]]);
1282 }
1283
1284 for (; __beg != __end; ++__beg, (void)++__pos)
1285 {
1286 size_t __nskipped = 0;
1287 const char_type __c = *__beg;
1288 for (size_t __i = 0; __i < __nmatches;)
1289 {
1290 const char_type* __name = __names[__matches[__i]];
1291 if (__pos >= __matches_lengths[__i])
1292 ++__nskipped, ++__i;
1293 else if (!(__name[__pos] == __c))
1294 {
1295 --__nmatches;
1296 __matches[__i] = __matches[__nmatches];
1297 __matches_lengths[__i] = __matches_lengths[__nmatches];
1298 }
1299 else
1300 ++__i;
1301 }
1302 if (__nskipped == __nmatches)
1303 break;
1304 }
1305
1306 if ((__nmatches == 1 && __matches_lengths[0] == __pos)
1307 || (__nmatches == 2 && (__matches_lengths[0] == __pos
1308 || __matches_lengths[1] == __pos)))
1309 __member = (__matches[0] >= (int)__indexlen
1310 ? __matches[0] - (int)__indexlen : __matches[0]);
1311 else
1312 __err |= ios_base::failbit;
1313
1314 return __beg;
1315 }
1316
1317 template<typename _CharT, typename _InIter>
1318 _InIter
1320 do_get_time(iter_type __beg, iter_type __end, ios_base& __io,
1321 ios_base::iostate& __err, tm* __tm) const
1322 {
1323 const locale& __loc = __io._M_getloc();
1324 const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
1325 const char_type* __times[2];
1326 __tp._M_time_formats(__times);
1327 __time_get_state __state = __time_get_state();
1328 __beg = _M_extract_via_format(__beg, __end, __io, __err,
1329 __tm, __times[0], __state);
1330 __state._M_finalize_state(__tm);
1331 if (__beg == __end)
1332 __err |= ios_base::eofbit;
1333 return __beg;
1334 }
1335
1336 template<typename _CharT, typename _InIter>
1337 _InIter
1339 do_get_date(iter_type __beg, iter_type __end, ios_base& __io,
1340 ios_base::iostate& __err, tm* __tm) const
1341 {
1342 const locale& __loc = __io._M_getloc();
1343 const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
1344 const char_type* __dates[2];
1345 __tp._M_date_formats(__dates);
1346 __time_get_state __state = __time_get_state();
1347 __beg = _M_extract_via_format(__beg, __end, __io, __err,
1348 __tm, __dates[0], __state);
1349 __state._M_finalize_state(__tm);
1350 if (__beg == __end)
1351 __err |= ios_base::eofbit;
1352 return __beg;
1353 }
1354
1355 template<typename _CharT, typename _InIter>
1356 _InIter
1358 do_get_weekday(iter_type __beg, iter_type __end, ios_base& __io,
1359 ios_base::iostate& __err, tm* __tm) const
1360 {
1361 const locale& __loc = __io._M_getloc();
1362 const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
1363 const char_type* __days[14];
1364 __tp._M_days_abbreviated(__days);
1365 __tp._M_days(__days + 7);
1366 int __tmpwday;
1367 ios_base::iostate __tmperr = ios_base::goodbit;
1368
1369 __beg = _M_extract_wday_or_month(__beg, __end, __tmpwday, __days, 7,
1370 __io, __tmperr);
1371 if (!__tmperr)
1372 __tm->tm_wday = __tmpwday;
1373 else
1374 __err |= ios_base::failbit;
1375
1376 if (__beg == __end)
1377 __err |= ios_base::eofbit;
1378 return __beg;
1379 }
1380
1381 template<typename _CharT, typename _InIter>
1382 _InIter
1385 ios_base& __io, ios_base::iostate& __err, tm* __tm) const
1386 {
1387 const locale& __loc = __io._M_getloc();
1388 const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
1389 const char_type* __months[24];
1390 __tp._M_months_abbreviated(__months);
1391 __tp._M_months(__months + 12);
1392 int __tmpmon;
1393 ios_base::iostate __tmperr = ios_base::goodbit;
1394
1395 __beg = _M_extract_wday_or_month(__beg, __end, __tmpmon, __months, 12,
1396 __io, __tmperr);
1397 if (!__tmperr)
1398 __tm->tm_mon = __tmpmon;
1399 else
1400 __err |= ios_base::failbit;
1401
1402 if (__beg == __end)
1403 __err |= ios_base::eofbit;
1404 return __beg;
1405 }
1406
1407 template<typename _CharT, typename _InIter>
1408 _InIter
1410 do_get_year(iter_type __beg, iter_type __end, ios_base& __io,
1411 ios_base::iostate& __err, tm* __tm) const
1412 {
1413 int __tmpyear;
1414 ios_base::iostate __tmperr = ios_base::goodbit;
1415 const locale& __loc = __io._M_getloc();
1416 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1417
1418 __beg = _M_extract_num(__beg, __end, __tmpyear, 0, 99, 2,
1419 __io, __tmperr);
1420 if (!__tmperr)
1421 {
1422 char __c = 0;
1423 if (__beg != __end)
1424 __c = __ctype.narrow(*__beg, '*');
1425 // For 1-2 digit year, assume 69-99 is 1969-1999, 0-68 is 2000-2068.
1426 // For 3-4 digit year, use it as year.
1427 // __tm->tm_year needs year - 1900 though.
1428 if (__c >= '0' && __c <= '9')
1429 {
1430 ++__beg;
1431 __tmpyear = __tmpyear * 10 + (__c - '0');
1432 if (__beg != __end)
1433 {
1434 __c = __ctype.narrow(*__beg, '*');
1435 if (__c >= '0' && __c <= '9')
1436 {
1437 ++__beg;
1438 __tmpyear = __tmpyear * 10 + (__c - '0');
1439 }
1440 }
1441 __tmpyear -= 1900;
1442 }
1443 else if (__tmpyear < 69)
1444 __tmpyear += 100;
1445 __tm->tm_year = __tmpyear;
1446 }
1447 else
1448 __err |= ios_base::failbit;
1449
1450 if (__beg == __end)
1451 __err |= ios_base::eofbit;
1452 return __beg;
1453 }
1454
1455#if __cplusplus >= 201103L
1456 template<typename _CharT, typename _InIter>
1457 inline
1458 _InIter
1460 get(iter_type __s, iter_type __end, ios_base& __io,
1461 ios_base::iostate& __err, tm* __tm, const char_type* __fmt,
1462 const char_type* __fmtend) const
1463 {
1464 const locale& __loc = __io._M_getloc();
1465 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
1466 __err = ios_base::goodbit;
1467 bool __use_state = false;
1468#if __GNUC__ >= 5 && !defined(__clang__)
1469#pragma GCC diagnostic push
1470#pragma GCC diagnostic ignored "-Wpmf-conversions"
1471 // Nasty hack. The C++ standard mandates that get invokes the do_get
1472 // virtual method, but unfortunately at least without an ABI change
1473 // for the facets we can't keep state across the different do_get
1474 // calls. So e.g. if __fmt is "%p %I:%M:%S", we can't handle it
1475 // properly, because we first handle the %p am/pm specifier and only
1476 // later the 12-hour format specifier.
1477 if ((void*)(this->*(&time_get::do_get)) == (void*)(&time_get::do_get))
1478 __use_state = true;
1479#pragma GCC diagnostic pop
1480#endif
1481 __time_get_state __state = __time_get_state();
1482 while (__fmt != __fmtend &&
1483 __err == ios_base::goodbit)
1484 {
1485 if (__s == __end)
1486 {
1488 break;
1489 }
1490 else if (__ctype.narrow(*__fmt, 0) == '%')
1491 {
1492 const char_type* __fmt_start = __fmt;
1493 char __format;
1494 char __mod = 0;
1495 if (++__fmt == __fmtend)
1496 {
1497 __err = ios_base::failbit;
1498 break;
1499 }
1500 const char __c = __ctype.narrow(*__fmt, 0);
1501 if (__c != 'E' && __c != 'O')
1502 __format = __c;
1503 else if (++__fmt != __fmtend)
1504 {
1505 __mod = __c;
1506 __format = __ctype.narrow(*__fmt, 0);
1507 }
1508 else
1509 {
1510 __err = ios_base::failbit;
1511 break;
1512 }
1513 if (__use_state)
1514 {
1515 char_type __new_fmt[4];
1516 __new_fmt[0] = __fmt_start[0];
1517 __new_fmt[1] = __fmt_start[1];
1518 if (__mod)
1519 {
1520 __new_fmt[2] = __fmt_start[2];
1521 __new_fmt[3] = char_type();
1522 }
1523 else
1524 __new_fmt[2] = char_type();
1525 __s = _M_extract_via_format(__s, __end, __io, __err, __tm,
1526 __new_fmt, __state);
1527 if (__s == __end)
1528 __err |= ios_base::eofbit;
1529 }
1530 else
1531 __s = this->do_get(__s, __end, __io, __err, __tm, __format,
1532 __mod);
1533 ++__fmt;
1534 }
1535 else if (__ctype.is(ctype_base::space, *__fmt))
1536 {
1537 ++__fmt;
1538 while (__fmt != __fmtend &&
1539 __ctype.is(ctype_base::space, *__fmt))
1540 ++__fmt;
1541
1542 while (__s != __end &&
1543 __ctype.is(ctype_base::space, *__s))
1544 ++__s;
1545 }
1546 // TODO real case-insensitive comparison
1547 else if (__ctype.tolower(*__s) == __ctype.tolower(*__fmt) ||
1548 __ctype.toupper(*__s) == __ctype.toupper(*__fmt))
1549 {
1550 ++__s;
1551 ++__fmt;
1552 }
1553 else
1554 {
1555 __err = ios_base::failbit;
1556 break;
1557 }
1558 }
1559 if (__use_state)
1560 __state._M_finalize_state(__tm);
1561 return __s;
1562 }
1563
1564 template<typename _CharT, typename _InIter>
1565 inline
1566 _InIter
1568 do_get(iter_type __beg, iter_type __end, ios_base& __io,
1569 ios_base::iostate& __err, tm* __tm,
1570 char __format, char __mod) const
1571 {
1572 const locale& __loc = __io._M_getloc();
1573 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
1574 __err = ios_base::goodbit;
1575
1576 char_type __fmt[4];
1577 __fmt[0] = __ctype.widen('%');
1578 if (!__mod)
1579 {
1580 __fmt[1] = __format;
1581 __fmt[2] = char_type();
1582 }
1583 else
1584 {
1585 __fmt[1] = __mod;
1586 __fmt[2] = __format;
1587 __fmt[3] = char_type();
1588 }
1589
1590 __time_get_state __state = __time_get_state();
1591 __beg = _M_extract_via_format(__beg, __end, __io, __err, __tm, __fmt,
1592 __state);
1593 __state._M_finalize_state(__tm);
1594 if (__beg == __end)
1595 __err |= ios_base::eofbit;
1596 return __beg;
1597 }
1598
1599#endif // __cplusplus >= 201103L
1600
1601 template<typename _CharT, typename _OutIter>
1602 _OutIter
1604 put(iter_type __s, ios_base& __io, char_type __fill, const tm* __tm,
1605 const _CharT* __beg, const _CharT* __end) const
1606 {
1607 const locale& __loc = __io._M_getloc();
1608 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
1609 for (; __beg != __end; ++__beg)
1610 if (__ctype.narrow(*__beg, 0) != '%')
1611 {
1612 *__s = *__beg;
1613 ++__s;
1614 }
1615 else if (++__beg != __end)
1616 {
1617 char __format;
1618 char __mod = 0;
1619 const char __c = __ctype.narrow(*__beg, 0);
1620 if (__c != 'E' && __c != 'O')
1621 __format = __c;
1622 else if (++__beg != __end)
1623 {
1624 __mod = __c;
1625 __format = __ctype.narrow(*__beg, 0);
1626 }
1627 else
1628 break;
1629 __s = this->do_put(__s, __io, __fill, __tm, __format, __mod);
1630 }
1631 else
1632 break;
1633 return __s;
1634 }
1635
1636 template<typename _CharT, typename _OutIter>
1637 _OutIter
1639 do_put(iter_type __s, ios_base& __io, char_type, const tm* __tm,
1640 char __format, char __mod) const
1641 {
1642 const locale& __loc = __io._M_getloc();
1643 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
1644 __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc);
1645
1646 // NB: This size is arbitrary. Should this be a data member,
1647 // initialized at construction?
1648 const size_t __maxlen = 128;
1649 char_type __res[__maxlen];
1650
1651 // NB: In IEEE 1003.1-200x, and perhaps other locale models, it
1652 // is possible that the format character will be longer than one
1653 // character. Possibilities include 'E' or 'O' followed by a
1654 // format character: if __mod is not the default argument, assume
1655 // it's a valid modifier.
1656 char_type __fmt[4];
1657 __fmt[0] = __ctype.widen('%');
1658 if (!__mod)
1659 {
1660 __fmt[1] = __format;
1661 __fmt[2] = char_type();
1662 }
1663 else
1664 {
1665 __fmt[1] = __mod;
1666 __fmt[2] = __format;
1667 __fmt[3] = char_type();
1668 }
1669
1670 __tp._M_put(__res, __maxlen, __fmt, __tm);
1671
1672 // Write resulting, fully-formatted string to output iterator.
1673 return std::__write(__s, __res, char_traits<char_type>::length(__res));
1674 }
1675
1676
1677 // Inhibit implicit instantiations for required instantiations,
1678 // which are defined via explicit instantiations elsewhere.
1679#if _GLIBCXX_EXTERN_TEMPLATE
1680#pragma GCC diagnostic push
1681#pragma GCC diagnostic ignored "-Wc++11-extensions" // extern template
1682#pragma GCC diagnostic ignored "-Wlong-long"
1683 extern template class moneypunct<char, false>;
1684 extern template class moneypunct<char, true>;
1685 extern template class moneypunct_byname<char, false>;
1686 extern template class moneypunct_byname<char, true>;
1687 extern template class _GLIBCXX_NAMESPACE_LDBL_OR_CXX11 money_get<char>;
1688 extern template class _GLIBCXX_NAMESPACE_LDBL_OR_CXX11 money_put<char>;
1689 extern template class __timepunct<char>;
1690 extern template class time_put<char>;
1691 extern template class time_put_byname<char>;
1692 extern template class time_get<char>;
1693 extern template class time_get_byname<char>;
1694 extern template class messages<char>;
1695 extern template class messages_byname<char>;
1696
1697 extern template
1699 __try_use_facet<moneypunct<char, true> >(const locale&) _GLIBCXX_NOTHROW;
1700
1701 extern template
1703 __try_use_facet<moneypunct<char, false> >(const locale&) _GLIBCXX_NOTHROW;
1704
1705 extern template
1706 const money_put<char>*
1707 __try_use_facet<money_put<char> >(const locale&) _GLIBCXX_NOTHROW;
1708
1709 extern template
1710 const money_get<char>*
1711 __try_use_facet<money_get<char> >(const locale&) _GLIBCXX_NOTHROW;
1712
1713 extern template
1714 const __timepunct<char>*
1715 __try_use_facet<__timepunct<char> >(const locale&) _GLIBCXX_NOTHROW;
1716
1717 extern template
1718 const time_put<char>*
1719 __try_use_facet<time_put<char> >(const locale&) _GLIBCXX_NOTHROW;
1720
1721 extern template
1722 const time_get<char>*
1723 __try_use_facet<time_get<char> >(const locale&) _GLIBCXX_NOTHROW;
1724
1725 extern template
1726 const messages<char>*
1727 __try_use_facet<messages<char> >(const locale&) _GLIBCXX_NOTHROW;
1728
1729 extern template
1732
1733 extern template
1736
1737 extern template
1738 const money_put<char>&
1740
1741 extern template
1742 const money_get<char>&
1744
1745 extern template
1746 const __timepunct<char>&
1748
1749 extern template
1750 const time_put<char>&
1752
1753 extern template
1754 const time_get<char>&
1756
1757 extern template
1758 const messages<char>&
1760
1761 extern template
1762 bool
1764
1765 extern template
1766 bool
1768
1769 extern template
1770 bool
1772
1773 extern template
1774 bool
1776
1777 extern template
1778 bool
1780
1781 extern template
1782 bool
1784
1785 extern template
1786 bool
1788
1789#ifdef _GLIBCXX_USE_WCHAR_T
1790 extern template class moneypunct<wchar_t, false>;
1791 extern template class moneypunct<wchar_t, true>;
1792 extern template class moneypunct_byname<wchar_t, false>;
1793 extern template class moneypunct_byname<wchar_t, true>;
1794 extern template class _GLIBCXX_NAMESPACE_LDBL_OR_CXX11 money_get<wchar_t>;
1795 extern template class _GLIBCXX_NAMESPACE_LDBL_OR_CXX11 money_put<wchar_t>;
1796 extern template class __timepunct<wchar_t>;
1797 extern template class time_put<wchar_t>;
1798 extern template class time_put_byname<wchar_t>;
1799 extern template class time_get<wchar_t>;
1800 extern template class time_get_byname<wchar_t>;
1801 extern template class messages<wchar_t>;
1802 extern template class messages_byname<wchar_t>;
1803
1804 extern template
1806 __try_use_facet<moneypunct<wchar_t, true> >(const locale&) _GLIBCXX_NOTHROW;
1807
1808 extern template
1810 __try_use_facet<moneypunct<wchar_t, false> >(const locale&) _GLIBCXX_NOTHROW;
1811
1812 extern template
1813 const money_put<wchar_t>*
1814 __try_use_facet<money_put<wchar_t> >(const locale&) _GLIBCXX_NOTHROW;
1815
1816 extern template
1817 const money_get<wchar_t>*
1818 __try_use_facet<money_get<wchar_t> >(const locale&) _GLIBCXX_NOTHROW;
1819
1820 extern template
1821 const __timepunct<wchar_t>*
1822 __try_use_facet<__timepunct<wchar_t> >(const locale&) _GLIBCXX_NOTHROW;
1823
1824 extern template
1825 const time_put<wchar_t>*
1826 __try_use_facet<time_put<wchar_t> >(const locale&) _GLIBCXX_NOTHROW;
1827
1828 extern template
1829 const time_get<wchar_t>*
1830 __try_use_facet<time_get<wchar_t> >(const locale&) _GLIBCXX_NOTHROW;
1831
1832 extern template
1833 const messages<wchar_t>*
1834 __try_use_facet<messages<wchar_t> >(const locale&) _GLIBCXX_NOTHROW;
1835
1836 extern template
1839
1840 extern template
1843
1844 extern template
1845 const money_put<wchar_t>&
1847
1848 extern template
1849 const money_get<wchar_t>&
1851
1852 extern template
1853 const __timepunct<wchar_t>&
1855
1856 extern template
1857 const time_put<wchar_t>&
1859
1860 extern template
1861 const time_get<wchar_t>&
1863
1864 extern template
1865 const messages<wchar_t>&
1867
1868 extern template
1869 bool
1871
1872 extern template
1873 bool
1875
1876 extern template
1877 bool
1879
1880 extern template
1881 bool
1883
1884 extern template
1885 bool
1887
1888 extern template
1889 bool
1891
1892 extern template
1893 bool
1895#endif
1896#pragma GCC diagnostic pop
1897#endif
1898
1899_GLIBCXX_END_NAMESPACE_VERSION
1900} // namespace std
1901
1902#endif
constexpr const _Tp & min(const _Tp &, const _Tp &)
This does what you think it does.
class __attribute((__abi_tag__("cxx11"))) failure typedef _Ios_Fmtflags fmtflags
These are thrown to indicate problems with io.
Definition ios_base.h:281
bool has_facet(const locale &__loc)
Test for the presence of a facet.
const _Facet & use_facet(const locale &__loc)
Return a facet.
ISO C++ entities toplevel namespace is std.
constexpr auto size(const _Container &__cont) noexcept(noexcept(__cont.size())) -> decltype(__cont.size())
Return the size of a container.
Provides input iterator semantics for streambufs.
constexpr const _CharT * c_str() const noexcept
Return const pointer to null-terminated contents.
static const size_type npos
Basis for explicit traits specializations.
Definition stringfwd.h:53
The base of the I/O class hierarchy.
Definition ios_base.h:255
static const fmtflags showbase
Generates a prefix indicating the numeric base of generated integer output.
Definition ios_base.h:402
static const fmtflags internal
Adds fill characters at a designated internal point in certain generated output, or identical to righ...
Definition ios_base.h:384
static const iostate eofbit
Indicates that an input operation reached the end of an input sequence.
Definition ios_base.h:449
static const iostate goodbit
Indicates all is well.
Definition ios_base.h:457
const locale & _M_getloc() const
Locale access.
Definition ios_base.h:837
static const fmtflags left
Adds fill characters on the right (final positions) of certain generated output. (I....
Definition ios_base.h:388
_Ios_Iostate iostate
This is a bitmask type.
Definition ios_base.h:442
locale getloc() const
Locale access.
Definition ios_base.h:826
static const iostate failbit
Indicates that an input operation failed to read the expected characters, or that an output operation...
Definition ios_base.h:454
static const fmtflags adjustfield
A mask of left|right|internal. Useful for the 2-arg form of setf.
Definition ios_base.h:422
Container class for localization functionality.
char_type tolower(char_type __c) const
Convert to lowercase.
char_type toupper(char_type __c) const
Convert to uppercase.
char_type widen(char __c) const
Widen char to char_type.
char narrow(char_type __c, char __dfault) const
Narrow char_type to char.
bool is(mask __m, char_type __c) const
Test char_type classification.
Primary class template ctype facet.
Definition localefwd.h:127
Primary class template time_get.
Definition localefwd.h:178
virtual iter_type do_get_year(iter_type __beg, iter_type __end, ios_base &__io, ios_base::iostate &__err, tm *__tm) const
Parse input year string.
virtual iter_type do_get_weekday(iter_type __beg, iter_type __end, ios_base &, ios_base::iostate &__err, tm *__tm) const
Parse input weekday string.
virtual iter_type do_get_monthname(iter_type __beg, iter_type __end, ios_base &, ios_base::iostate &__err, tm *__tm) const
Parse input month string.
iter_type do_get(iter_type __s, iter_type __end, ios_base &__f, ios_base::iostate &__err, tm *__tm, char __format, char __modifier) const
Parse input string according to format.
iter_type get(iter_type __s, iter_type __end, ios_base &__io, ios_base::iostate &__err, tm *__tm, char __format, char __modifier=0) const
Parse input string according to format.
_InIter iter_type
Public typedefs.
virtual dateorder do_date_order() const
Return preferred order of month, day, and year.
virtual iter_type do_get_date(iter_type __beg, iter_type __end, ios_base &__io, ios_base::iostate &__err, tm *__tm) const
Parse input date string.
virtual iter_type do_get_time(iter_type __beg, iter_type __end, ios_base &__io, ios_base::iostate &__err, tm *__tm) const
Parse input time string.
class time_get_byname [22.2.5.2].
Definition localefwd.h:180
Primary class template time_put.
Definition localefwd.h:183
virtual iter_type do_put(iter_type __s, ios_base &__io, char_type __fill, const tm *__tm, char __format, char __mod) const
Format and output a time or date.
iter_type put(iter_type __s, ios_base &__io, char_type __fill, const tm *__tm, const _CharT *__beg, const _CharT *__end) const
Format and output a time or date.
_OutIter iter_type
Public typedefs.
class time_put_byname [22.2.5.4].
Definition localefwd.h:185
Primary class template moneypunct.
Definition localefwd.h:197
static locale::id id
Numpunct facet id.
class moneypunct_byname [22.2.6.4].
Definition localefwd.h:199
Primary class template money_get.
Definition localefwd.h:191
_InIter iter_type
Public typedefs.
virtual iter_type do_get(iter_type __s, iter_type __end, bool __intl, ios_base &__io, ios_base::iostate &__err, long double &__units) const
Read and parse a monetary value.
basic_string< _CharT > string_type
Public typedefs.
Primary class template money_put.
Definition localefwd.h:193
virtual iter_type do_put(iter_type __s, bool __intl, ios_base &__io, char_type __fill, long double __units) const
Format and output a monetary value.
_CharT char_type
Public typedefs.
basic_string< _CharT > string_type
Public typedefs.
_OutIter iter_type
Public typedefs.
Primary class template messages.
Definition localefwd.h:206
class messages_byname [22.2.7.2].
Definition localefwd.h:208