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