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 =
74 use_facet<moneypunct<_CharT, _Intl> >(__loc);
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
138 money_get<_CharT, _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
358 money_get<_CharT, _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
586 money_put<_CharT, _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
707 ios_base::iostate __tmperr = ios_base::goodbit;
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
1045 time_get<_CharT, _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
1058 time_get<_CharT, _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
1096 time_get<_CharT, _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
1258 time_get<_CharT, _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;
1378 ios_base::iostate __tmperr = ios_base::goodbit;
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;
1404 ios_base::iostate __tmperr = ios_base::goodbit;
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;
1425 ios_base::iostate __tmperr = ios_base::goodbit;
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
1742 use_facet<moneypunct<char, true> >(const locale&);
1743
1744 extern template
1746 use_facet<moneypunct<char, false> >(const locale&);
1747
1748 extern template
1749 const money_put<char>&
1750 use_facet<money_put<char> >(const locale&);
1751
1752 extern template
1753 const money_get<char>&
1754 use_facet<money_get<char> >(const locale&);
1755
1756 extern template
1757 const __timepunct<char>&
1758 use_facet<__timepunct<char> >(const locale&);
1759
1760 extern template
1761 const time_put<char>&
1762 use_facet<time_put<char> >(const locale&);
1763
1764 extern template
1765 const time_get<char>&
1766 use_facet<time_get<char> >(const locale&);
1767
1768 extern template
1769 const messages<char>&
1770 use_facet<messages<char> >(const locale&);
1771
1772 extern template
1773 bool
1774 has_facet<moneypunct<char> >(const locale&);
1775
1776 extern template
1777 bool
1778 has_facet<money_put<char> >(const locale&);
1779
1780 extern template
1781 bool
1782 has_facet<money_get<char> >(const locale&);
1783
1784 extern template
1785 bool
1786 has_facet<__timepunct<char> >(const locale&);
1787
1788 extern template
1789 bool
1790 has_facet<time_put<char> >(const locale&);
1791
1792 extern template
1793 bool
1794 has_facet<time_get<char> >(const locale&);
1795
1796 extern template
1797 bool
1798 has_facet<messages<char> >(const locale&);
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
1849 use_facet<moneypunct<wchar_t, true> >(const locale&);
1850
1851 extern template
1853 use_facet<moneypunct<wchar_t, false> >(const locale&);
1854
1855 extern template
1856 const money_put<wchar_t>&
1857 use_facet<money_put<wchar_t> >(const locale&);
1858
1859 extern template
1860 const money_get<wchar_t>&
1861 use_facet<money_get<wchar_t> >(const locale&);
1862
1863 extern template
1864 const __timepunct<wchar_t>&
1865 use_facet<__timepunct<wchar_t> >(const locale&);
1866
1867 extern template
1868 const time_put<wchar_t>&
1869 use_facet<time_put<wchar_t> >(const locale&);
1870
1871 extern template
1872 const time_get<wchar_t>&
1873 use_facet<time_get<wchar_t> >(const locale&);
1874
1875 extern template
1876 const messages<wchar_t>&
1877 use_facet<messages<wchar_t> >(const locale&);
1878
1879 extern template
1880 bool
1881 has_facet<moneypunct<wchar_t> >(const locale&);
1882
1883 extern template
1884 bool
1885 has_facet<money_put<wchar_t> >(const locale&);
1886
1887 extern template
1888 bool
1889 has_facet<money_get<wchar_t> >(const locale&);
1890
1891 extern template
1892 bool
1893 has_facet<__timepunct<wchar_t> >(const locale&);
1894
1895 extern template
1896 bool
1897 has_facet<time_put<wchar_t> >(const locale&);
1898
1899 extern template
1900 bool
1901 has_facet<time_get<wchar_t> >(const locale&);
1902
1903 extern template
1904 bool
1905 has_facet<messages<wchar_t> >(const locale&);
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.
Definition: stl_algobase.h:234
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.
Definition: range_access.h:274
Basis for explicit traits specializations.
Definition: char_traits.h:326
void resize(size_type __n, _CharT __c)
Resizes the string to the specified number of characters.
Definition: cow_string.h:3801
const _CharT * c_str() const noexcept
Return const pointer to null-terminated contents.
Definition: cow_string.h:2376
static const size_type npos
Value returned by various member functions when they fail.
Definition: cow_string.h:322
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.
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.
_OutIter iter_type
Public typedefs.
_CharT char_type
Public typedefs.
Primary class template messages.
class messages_byname [22.2.7.2].