libstdc++
locale_facets_nonio.tcc
Go to the documentation of this file.
1// Locale support -*- C++ -*-
2
3// Copyright (C) 2007-2025 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 _InIter
1045 _M_extract_via_format(iter_type __beg, iter_type __end, ios_base& __io,
1046 ios_base::iostate& __err, tm* __tm,
1047 const _CharT* __format) const
1048 {
1049 __time_get_state __state = __time_get_state();
1050 return _M_extract_via_format(__beg, __end, __io, __err, __tm,
1051 __format, __state);
1052 }
1053
1054 template<typename _CharT, typename _InIter>
1055 _InIter
1057 _M_extract_num(iter_type __beg, iter_type __end, int& __member,
1058 int __min, int __max, size_t __len,
1059 ios_base& __io, ios_base::iostate& __err) const
1060 {
1061 const locale& __loc = __io._M_getloc();
1062 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1063
1064 size_t __i = 0;
1065 int __value = 0;
1066 for (; __beg != __end && __i < __len; ++__beg, (void)++__i)
1067 {
1068 const char __c = __ctype.narrow(*__beg, '*');
1069 if (__c >= '0' && __c <= '9')
1070 {
1071 __value = __value * 10 + (__c - '0');
1072 if (__value > __max)
1073 break;
1074 }
1075 else
1076 break;
1077 }
1078 if (__i && __value >= __min && __value <= __max)
1079 __member = __value;
1080 else
1081 __err |= ios_base::failbit;
1082
1083 return __beg;
1084 }
1085
1086 // Assumptions:
1087 // All elements in __names are unique, except if __indexlen is
1088 // even __names in the first half could be the same as corresponding
1089 // __names in the second half (May is abbreviated as May). Some __names
1090 // elements could be prefixes of other __names elements.
1091 template<typename _CharT, typename _InIter>
1092 _InIter
1094 _M_extract_name(iter_type __beg, iter_type __end, int& __member,
1095 const _CharT** __names, size_t __indexlen,
1096 ios_base& __io, ios_base::iostate& __err) const
1097 {
1098 typedef char_traits<_CharT> __traits_type;
1099 const locale& __loc = __io._M_getloc();
1100 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1101
1102 size_t* __matches
1103 = static_cast<size_t*>(__builtin_alloca(2 * sizeof(size_t)
1104 * __indexlen));
1105 size_t* __lengths = __matches + __indexlen;
1106 size_t __nmatches = 0;
1107 size_t __pos = 0;
1108 bool __testvalid = true;
1109 const char_type* __name;
1110 bool __begupdated = false;
1111
1112 // Look for initial matches.
1113 if (__beg != __end)
1114 {
1115 const char_type __c = *__beg;
1116 // TODO real case-insensitive comparison
1117 const char_type __cl = __ctype.tolower(__c);
1118 const char_type __cu = __ctype.toupper(__c);
1119 for (size_t __i1 = 0; __i1 < __indexlen; ++__i1)
1120 if (__cl == __ctype.tolower(__names[__i1][0])
1121 || __cu == __ctype.toupper(__names[__i1][0]))
1122 {
1123 __lengths[__nmatches]
1124 = __traits_type::length(__names[__i1]);
1125 __matches[__nmatches++] = __i1;
1126 }
1127 }
1128
1129 while (__nmatches > 1)
1130 {
1131 // Find smallest matching string.
1132 size_t __minlen = __lengths[0];
1133 for (size_t __i2 = 1; __i2 < __nmatches; ++__i2)
1134 __minlen = std::min(__minlen, __lengths[__i2]);
1135 ++__pos;
1136 ++__beg;
1137 if (__pos == __minlen)
1138 {
1139 // If some match has remaining length of 0,
1140 // need to decide if any match with remaining
1141 // length non-zero matches the next character.
1142 // If so, remove all matches with remaining length
1143 // 0 from consideration, otherwise keep only matches
1144 // with remaining length 0.
1145 bool __match_longer = false;
1146
1147 if (__beg != __end)
1148 {
1149 // TODO real case-insensitive comparison
1150 const char_type __cl = __ctype.tolower(*__beg);
1151 const char_type __cu = __ctype.toupper(*__beg);
1152 for (size_t __i3 = 0; __i3 < __nmatches; ++__i3)
1153 {
1154 __name = __names[__matches[__i3]];
1155 if (__lengths[__i3] > __pos
1156 && (__ctype.tolower(__name[__pos]) == __cl
1157 || __ctype.toupper(__name[__pos]) == __cu))
1158 {
1159 __match_longer = true;
1160 break;
1161 }
1162 }
1163 }
1164 for (size_t __i4 = 0; __i4 < __nmatches;)
1165 if (__match_longer == (__lengths[__i4] == __pos))
1166 {
1167 __matches[__i4] = __matches[--__nmatches];
1168 __lengths[__i4] = __lengths[__nmatches];
1169 }
1170 else
1171 ++__i4;
1172 if (__match_longer)
1173 {
1174 __minlen = __lengths[0];
1175 for (size_t __i5 = 1; __i5 < __nmatches; ++__i5)
1176 __minlen = std::min(__minlen, __lengths[__i5]);
1177 }
1178 else
1179 {
1180 // Deal with May being full as well as abbreviated month
1181 // name. Pick the smaller index.
1182 if (__nmatches == 2 && (__indexlen & 1) == 0)
1183 {
1184 if (__matches[0] < __indexlen / 2)
1185 {
1186 if (__matches[1] == __matches[0] + __indexlen / 2)
1187 __nmatches = 1;
1188 }
1189 else if (__matches[1] == __matches[0] - __indexlen / 2)
1190 {
1191 __matches[0] = __matches[1];
1192 __lengths[0] = __lengths[1];
1193 __nmatches = 1;
1194 }
1195 }
1196 __begupdated = true;
1197 break;
1198 }
1199 }
1200 if (__pos < __minlen && __beg != __end)
1201 {
1202 // TODO real case-insensitive comparison
1203 const char_type __cl = __ctype.tolower(*__beg);
1204 const char_type __cu = __ctype.toupper(*__beg);
1205 for (size_t __i6 = 0; __i6 < __nmatches;)
1206 {
1207 __name = __names[__matches[__i6]];
1208 if (__ctype.tolower(__name[__pos]) != __cl
1209 && __ctype.toupper(__name[__pos]) != __cu)
1210 {
1211 __matches[__i6] = __matches[--__nmatches];
1212 __lengths[__i6] = __lengths[__nmatches];
1213 }
1214 else
1215 ++__i6;
1216 }
1217 }
1218 else
1219 break;
1220 }
1221
1222 if (__nmatches == 1)
1223 {
1224 // Make sure found name is completely extracted.
1225 if (!__begupdated)
1226 {
1227 ++__beg;
1228 ++__pos;
1229 }
1230 __name = __names[__matches[0]];
1231 const size_t __len = __lengths[0];
1232 while (__pos < __len
1233 && __beg != __end
1234 // TODO real case-insensitive comparison
1235 && (__ctype.tolower(__name[__pos]) == __ctype.tolower(*__beg)
1236 || (__ctype.toupper(__name[__pos])
1237 == __ctype.toupper(*__beg))))
1238 ++__beg, (void)++__pos;
1239
1240 if (__len == __pos)
1241 __member = __matches[0];
1242 else
1243 __testvalid = false;
1244 }
1245 else
1246 __testvalid = false;
1247 if (!__testvalid)
1248 __err |= ios_base::failbit;
1249
1250 return __beg;
1251 }
1252
1253 template<typename _CharT, typename _InIter>
1254 _InIter
1256 _M_extract_wday_or_month(iter_type __beg, iter_type __end, int& __member,
1257 const _CharT** __names, size_t __indexlen,
1258 ios_base& __io, ios_base::iostate& __err) const
1259 {
1260 typedef char_traits<_CharT> __traits_type;
1261 const locale& __loc = __io._M_getloc();
1262 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1263
1264 int* __matches = static_cast<int*>(__builtin_alloca(2 * sizeof(int)
1265 * __indexlen));
1266 size_t __nmatches = 0;
1267 size_t* __matches_lengths = 0;
1268 size_t __pos = 0;
1269
1270 if (__beg != __end)
1271 {
1272 const char_type __c = *__beg;
1273 for (size_t __i = 0; __i < 2 * __indexlen; ++__i)
1274 if (__c == __names[__i][0]
1275 || __c == __ctype.toupper(__names[__i][0]))
1276 __matches[__nmatches++] = __i;
1277 }
1278
1279 if (__nmatches)
1280 {
1281 ++__beg;
1282 ++__pos;
1283
1284 __matches_lengths
1285 = static_cast<size_t*>(__builtin_alloca(sizeof(size_t)
1286 * __nmatches));
1287 for (size_t __i = 0; __i < __nmatches; ++__i)
1288 __matches_lengths[__i]
1289 = __traits_type::length(__names[__matches[__i]]);
1290 }
1291
1292 for (; __beg != __end; ++__beg, (void)++__pos)
1293 {
1294 size_t __nskipped = 0;
1295 const char_type __c = *__beg;
1296 for (size_t __i = 0; __i < __nmatches;)
1297 {
1298 const char_type* __name = __names[__matches[__i]];
1299 if (__pos >= __matches_lengths[__i])
1300 ++__nskipped, ++__i;
1301 else if (!(__name[__pos] == __c))
1302 {
1303 --__nmatches;
1304 __matches[__i] = __matches[__nmatches];
1305 __matches_lengths[__i] = __matches_lengths[__nmatches];
1306 }
1307 else
1308 ++__i;
1309 }
1310 if (__nskipped == __nmatches)
1311 break;
1312 }
1313
1314 if ((__nmatches == 1 && __matches_lengths[0] == __pos)
1315 || (__nmatches == 2 && (__matches_lengths[0] == __pos
1316 || __matches_lengths[1] == __pos)))
1317 __member = (__matches[0] >= (int)__indexlen
1318 ? __matches[0] - (int)__indexlen : __matches[0]);
1319 else
1320 __err |= ios_base::failbit;
1321
1322 return __beg;
1323 }
1324
1325 template<typename _CharT, typename _InIter>
1326 _InIter
1328 do_get_time(iter_type __beg, iter_type __end, ios_base& __io,
1329 ios_base::iostate& __err, tm* __tm) const
1330 {
1331 const locale& __loc = __io._M_getloc();
1332 const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
1333 const char_type* __times[2];
1334 __tp._M_time_formats(__times);
1335 __time_get_state __state = __time_get_state();
1336 __beg = _M_extract_via_format(__beg, __end, __io, __err,
1337 __tm, __times[0], __state);
1338 __state._M_finalize_state(__tm);
1339 if (__beg == __end)
1340 __err |= ios_base::eofbit;
1341 return __beg;
1342 }
1343
1344 template<typename _CharT, typename _InIter>
1345 _InIter
1347 do_get_date(iter_type __beg, iter_type __end, ios_base& __io,
1348 ios_base::iostate& __err, tm* __tm) const
1349 {
1350 const locale& __loc = __io._M_getloc();
1351 const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
1352 const char_type* __dates[2];
1353 __tp._M_date_formats(__dates);
1354 __time_get_state __state = __time_get_state();
1355 __beg = _M_extract_via_format(__beg, __end, __io, __err,
1356 __tm, __dates[0], __state);
1357 __state._M_finalize_state(__tm);
1358 if (__beg == __end)
1359 __err |= ios_base::eofbit;
1360 return __beg;
1361 }
1362
1363 template<typename _CharT, typename _InIter>
1364 _InIter
1366 do_get_weekday(iter_type __beg, iter_type __end, ios_base& __io,
1367 ios_base::iostate& __err, tm* __tm) const
1368 {
1369 const locale& __loc = __io._M_getloc();
1370 const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
1371 const char_type* __days[14];
1372 __tp._M_days_abbreviated(__days);
1373 __tp._M_days(__days + 7);
1374 int __tmpwday;
1376
1377 __beg = _M_extract_wday_or_month(__beg, __end, __tmpwday, __days, 7,
1378 __io, __tmperr);
1379 if (!__tmperr)
1380 __tm->tm_wday = __tmpwday;
1381 else
1382 __err |= ios_base::failbit;
1383
1384 if (__beg == __end)
1385 __err |= ios_base::eofbit;
1386 return __beg;
1387 }
1388
1389 template<typename _CharT, typename _InIter>
1390 _InIter
1393 ios_base& __io, ios_base::iostate& __err, tm* __tm) const
1394 {
1395 const locale& __loc = __io._M_getloc();
1396 const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
1397 const char_type* __months[24];
1398 __tp._M_months_abbreviated(__months);
1399 __tp._M_months(__months + 12);
1400 int __tmpmon;
1402
1403 __beg = _M_extract_wday_or_month(__beg, __end, __tmpmon, __months, 12,
1404 __io, __tmperr);
1405 if (!__tmperr)
1406 __tm->tm_mon = __tmpmon;
1407 else
1408 __err |= ios_base::failbit;
1409
1410 if (__beg == __end)
1411 __err |= ios_base::eofbit;
1412 return __beg;
1413 }
1414
1415 template<typename _CharT, typename _InIter>
1416 _InIter
1418 do_get_year(iter_type __beg, iter_type __end, ios_base& __io,
1419 ios_base::iostate& __err, tm* __tm) const
1420 {
1421 int __tmpyear;
1423 const locale& __loc = __io._M_getloc();
1424 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1425
1426 __beg = _M_extract_num(__beg, __end, __tmpyear, 0, 99, 2,
1427 __io, __tmperr);
1428 if (!__tmperr)
1429 {
1430 char __c = 0;
1431 if (__beg != __end)
1432 __c = __ctype.narrow(*__beg, '*');
1433 // For 1-2 digit year, assume 69-99 is 1969-1999, 0-68 is 2000-2068.
1434 // For 3-4 digit year, use it as year.
1435 // __tm->tm_year needs year - 1900 though.
1436 if (__c >= '0' && __c <= '9')
1437 {
1438 ++__beg;
1439 __tmpyear = __tmpyear * 10 + (__c - '0');
1440 if (__beg != __end)
1441 {
1442 __c = __ctype.narrow(*__beg, '*');
1443 if (__c >= '0' && __c <= '9')
1444 {
1445 ++__beg;
1446 __tmpyear = __tmpyear * 10 + (__c - '0');
1447 }
1448 }
1449 __tmpyear -= 1900;
1450 }
1451 else if (__tmpyear < 69)
1452 __tmpyear += 100;
1453 __tm->tm_year = __tmpyear;
1454 }
1455 else
1456 __err |= ios_base::failbit;
1457
1458 if (__beg == __end)
1459 __err |= ios_base::eofbit;
1460 return __beg;
1461 }
1462
1463#if __cplusplus >= 201103L
1464 template<typename _CharT, typename _InIter>
1465 inline
1466 _InIter
1468 get(iter_type __s, iter_type __end, ios_base& __io,
1469 ios_base::iostate& __err, tm* __tm, const char_type* __fmt,
1470 const char_type* __fmtend) const
1471 {
1472 const locale& __loc = __io._M_getloc();
1473 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
1474 __err = ios_base::goodbit;
1475 bool __use_state = false;
1476#if __GNUC__ >= 5 && !defined(_GLIBCXX_CLANG)
1477#pragma GCC diagnostic push
1478#pragma GCC diagnostic ignored "-Wpmf-conversions"
1479 // Nasty hack. The C++ standard mandates that get invokes the do_get
1480 // virtual method, but unfortunately at least without an ABI change
1481 // for the facets we can't keep state across the different do_get
1482 // calls. So e.g. if __fmt is "%p %I:%M:%S", we can't handle it
1483 // properly, because we first handle the %p am/pm specifier and only
1484 // later the 12-hour format specifier.
1485 if ((void*)(this->*(&time_get::do_get)) == (void*)(&time_get::do_get))
1486 __use_state = true;
1487#pragma GCC diagnostic pop
1488#endif
1489 __time_get_state __state = __time_get_state();
1490 while (__fmt != __fmtend &&
1491 __err == ios_base::goodbit)
1492 {
1493 if (__s == __end)
1494 {
1496 break;
1497 }
1498 else if (__ctype.narrow(*__fmt, 0) == '%')
1499 {
1500 const char_type* __fmt_start = __fmt;
1501 char __format;
1502 char __mod = 0;
1503 if (++__fmt == __fmtend)
1504 {
1505 __err = ios_base::failbit;
1506 break;
1507 }
1508 const char __c = __ctype.narrow(*__fmt, 0);
1509 if (__c != 'E' && __c != 'O')
1510 __format = __c;
1511 else if (++__fmt != __fmtend)
1512 {
1513 __mod = __c;
1514 __format = __ctype.narrow(*__fmt, 0);
1515 }
1516 else
1517 {
1518 __err = ios_base::failbit;
1519 break;
1520 }
1521 if (__use_state)
1522 {
1523 char_type __new_fmt[4];
1524 __new_fmt[0] = __fmt_start[0];
1525 __new_fmt[1] = __fmt_start[1];
1526 if (__mod)
1527 {
1528 __new_fmt[2] = __fmt_start[2];
1529 __new_fmt[3] = char_type();
1530 }
1531 else
1532 __new_fmt[2] = char_type();
1533 __s = _M_extract_via_format(__s, __end, __io, __err, __tm,
1534 __new_fmt, __state);
1535 if (__s == __end)
1536 __err |= ios_base::eofbit;
1537 }
1538 else
1539 __s = this->do_get(__s, __end, __io, __err, __tm, __format,
1540 __mod);
1541 ++__fmt;
1542 }
1543 else if (__ctype.is(ctype_base::space, *__fmt))
1544 {
1545 ++__fmt;
1546 while (__fmt != __fmtend &&
1547 __ctype.is(ctype_base::space, *__fmt))
1548 ++__fmt;
1549
1550 while (__s != __end &&
1551 __ctype.is(ctype_base::space, *__s))
1552 ++__s;
1553 }
1554 // TODO real case-insensitive comparison
1555 else if (__ctype.tolower(*__s) == __ctype.tolower(*__fmt) ||
1556 __ctype.toupper(*__s) == __ctype.toupper(*__fmt))
1557 {
1558 ++__s;
1559 ++__fmt;
1560 }
1561 else
1562 {
1563 __err = ios_base::failbit;
1564 break;
1565 }
1566 }
1567 if (__use_state)
1568 __state._M_finalize_state(__tm);
1569 return __s;
1570 }
1571
1572 template<typename _CharT, typename _InIter>
1573 inline
1574 _InIter
1576 do_get(iter_type __beg, iter_type __end, ios_base& __io,
1577 ios_base::iostate& __err, tm* __tm,
1578 char __format, char __mod) const
1579 {
1580 const locale& __loc = __io._M_getloc();
1581 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
1582 __err = ios_base::goodbit;
1583
1584 char_type __fmt[4];
1585 __fmt[0] = __ctype.widen('%');
1586 if (!__mod)
1587 {
1588 __fmt[1] = __format;
1589 __fmt[2] = char_type();
1590 }
1591 else
1592 {
1593 __fmt[1] = __mod;
1594 __fmt[2] = __format;
1595 __fmt[3] = char_type();
1596 }
1597
1598 __time_get_state __state = __time_get_state();
1599 __beg = _M_extract_via_format(__beg, __end, __io, __err, __tm, __fmt,
1600 __state);
1601 __state._M_finalize_state(__tm);
1602 if (__beg == __end)
1603 __err |= ios_base::eofbit;
1604 return __beg;
1605 }
1606
1607#endif // __cplusplus >= 201103L
1608
1609 template<typename _CharT, typename _OutIter>
1610 _OutIter
1612 put(iter_type __s, ios_base& __io, char_type __fill, const tm* __tm,
1613 const _CharT* __beg, const _CharT* __end) const
1614 {
1615 const locale& __loc = __io._M_getloc();
1616 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
1617 for (; __beg != __end; ++__beg)
1618 if (__ctype.narrow(*__beg, 0) != '%')
1619 {
1620 *__s = *__beg;
1621 ++__s;
1622 }
1623 else if (++__beg != __end)
1624 {
1625 char __format;
1626 char __mod = 0;
1627 const char __c = __ctype.narrow(*__beg, 0);
1628 if (__c != 'E' && __c != 'O')
1629 __format = __c;
1630 else if (++__beg != __end)
1631 {
1632 __mod = __c;
1633 __format = __ctype.narrow(*__beg, 0);
1634 }
1635 else
1636 break;
1637 __s = this->do_put(__s, __io, __fill, __tm, __format, __mod);
1638 }
1639 else
1640 break;
1641 return __s;
1642 }
1643
1644 template<typename _CharT, typename _OutIter>
1645 _OutIter
1647 do_put(iter_type __s, ios_base& __io, char_type, const tm* __tm,
1648 char __format, char __mod) const
1649 {
1650 const locale& __loc = __io._M_getloc();
1651 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
1652 __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc);
1653
1654 // NB: This size is arbitrary. Should this be a data member,
1655 // initialized at construction?
1656 const size_t __maxlen = 128;
1657 char_type __res[__maxlen];
1658
1659 // NB: In IEEE 1003.1-200x, and perhaps other locale models, it
1660 // is possible that the format character will be longer than one
1661 // character. Possibilities include 'E' or 'O' followed by a
1662 // format character: if __mod is not the default argument, assume
1663 // it's a valid modifier.
1664 char_type __fmt[4];
1665 __fmt[0] = __ctype.widen('%');
1666 if (!__mod)
1667 {
1668 __fmt[1] = __format;
1669 __fmt[2] = char_type();
1670 }
1671 else
1672 {
1673 __fmt[1] = __mod;
1674 __fmt[2] = __format;
1675 __fmt[3] = char_type();
1676 }
1677
1678 __tp._M_put(__res, __maxlen, __fmt, __tm);
1679
1680 // Write resulting, fully-formatted string to output iterator.
1681 return std::__write(__s, __res, char_traits<char_type>::length(__res));
1682 }
1683
1684
1685 // Inhibit implicit instantiations for required instantiations,
1686 // which are defined via explicit instantiations elsewhere.
1687#if _GLIBCXX_EXTERN_TEMPLATE
1688#pragma GCC diagnostic push
1689#pragma GCC diagnostic ignored "-Wc++11-extensions" // extern template
1690#pragma GCC diagnostic ignored "-Wlong-long"
1691 extern template class moneypunct<char, false>;
1692 extern template class moneypunct<char, true>;
1693 extern template class moneypunct_byname<char, false>;
1694 extern template class moneypunct_byname<char, true>;
1695 extern template class _GLIBCXX_NAMESPACE_LDBL_OR_CXX11 money_get<char>;
1696 extern template class _GLIBCXX_NAMESPACE_LDBL_OR_CXX11 money_put<char>;
1697 extern template class __timepunct<char>;
1698 extern template class time_put<char>;
1699 extern template class time_put_byname<char>;
1700 extern template class time_get<char>;
1701 extern template class time_get_byname<char>;
1702 extern template class messages<char>;
1703 extern template class messages_byname<char>;
1704
1705 extern template
1707 __try_use_facet<moneypunct<char, true> >(const locale&) _GLIBCXX_NOTHROW;
1708
1709 extern template
1711 __try_use_facet<moneypunct<char, false> >(const locale&) _GLIBCXX_NOTHROW;
1712
1713 extern template
1714 const money_put<char>*
1715 __try_use_facet<money_put<char> >(const locale&) _GLIBCXX_NOTHROW;
1716
1717 extern template
1718 const money_get<char>*
1719 __try_use_facet<money_get<char> >(const locale&) _GLIBCXX_NOTHROW;
1720
1721 extern template
1722 const __timepunct<char>*
1723 __try_use_facet<__timepunct<char> >(const locale&) _GLIBCXX_NOTHROW;
1724
1725 extern template
1726 const time_put<char>*
1727 __try_use_facet<time_put<char> >(const locale&) _GLIBCXX_NOTHROW;
1728
1729 extern template
1730 const time_get<char>*
1731 __try_use_facet<time_get<char> >(const locale&) _GLIBCXX_NOTHROW;
1732
1733 extern template
1734 const messages<char>*
1735 __try_use_facet<messages<char> >(const locale&) _GLIBCXX_NOTHROW;
1736
1737 extern template
1740
1741 extern template
1744
1745 extern template
1746 const money_put<char>&
1748
1749 extern template
1750 const money_get<char>&
1752
1753 extern template
1754 const __timepunct<char>&
1756
1757 extern template
1758 const time_put<char>&
1760
1761 extern template
1762 const time_get<char>&
1764
1765 extern template
1766 const messages<char>&
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 extern template
1790 bool
1792
1793 extern template
1794 bool
1796
1797#ifdef _GLIBCXX_USE_WCHAR_T
1798 extern template class moneypunct<wchar_t, false>;
1799 extern template class moneypunct<wchar_t, true>;
1800 extern template class moneypunct_byname<wchar_t, false>;
1801 extern template class moneypunct_byname<wchar_t, true>;
1802 extern template class _GLIBCXX_NAMESPACE_LDBL_OR_CXX11 money_get<wchar_t>;
1803 extern template class _GLIBCXX_NAMESPACE_LDBL_OR_CXX11 money_put<wchar_t>;
1804 extern template class __timepunct<wchar_t>;
1805 extern template class time_put<wchar_t>;
1806 extern template class time_put_byname<wchar_t>;
1807 extern template class time_get<wchar_t>;
1808 extern template class time_get_byname<wchar_t>;
1809 extern template class messages<wchar_t>;
1810 extern template class messages_byname<wchar_t>;
1811
1812 extern template
1814 __try_use_facet<moneypunct<wchar_t, true> >(const locale&) _GLIBCXX_NOTHROW;
1815
1816 extern template
1818 __try_use_facet<moneypunct<wchar_t, false> >(const locale&) _GLIBCXX_NOTHROW;
1819
1820 extern template
1821 const money_put<wchar_t>*
1822 __try_use_facet<money_put<wchar_t> >(const locale&) _GLIBCXX_NOTHROW;
1823
1824 extern template
1825 const money_get<wchar_t>*
1826 __try_use_facet<money_get<wchar_t> >(const locale&) _GLIBCXX_NOTHROW;
1827
1828 extern template
1829 const __timepunct<wchar_t>*
1830 __try_use_facet<__timepunct<wchar_t> >(const locale&) _GLIBCXX_NOTHROW;
1831
1832 extern template
1833 const time_put<wchar_t>*
1834 __try_use_facet<time_put<wchar_t> >(const locale&) _GLIBCXX_NOTHROW;
1835
1836 extern template
1837 const time_get<wchar_t>*
1838 __try_use_facet<time_get<wchar_t> >(const locale&) _GLIBCXX_NOTHROW;
1839
1840 extern template
1841 const messages<wchar_t>*
1842 __try_use_facet<messages<wchar_t> >(const locale&) _GLIBCXX_NOTHROW;
1843
1844 extern template
1847
1848 extern template
1851
1852 extern template
1853 const money_put<wchar_t>&
1855
1856 extern template
1857 const money_get<wchar_t>&
1859
1860 extern template
1861 const __timepunct<wchar_t>&
1863
1864 extern template
1865 const time_put<wchar_t>&
1867
1868 extern template
1869 const time_get<wchar_t>&
1871
1872 extern template
1873 const messages<wchar_t>&
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
1896 extern template
1897 bool
1899
1900 extern template
1901 bool
1903#endif
1904#pragma GCC diagnostic pop
1905#endif
1906
1907_GLIBCXX_END_NAMESPACE_VERSION
1908} // namespace std
1909
1910#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:292
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 auto size(const _Container &__cont) noexcept(noexcept(__cont.size())) -> decltype(__cont.size())
Return the size of a container.
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_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].