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 _InIter
1044 time_get<_CharT, _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
1056 time_get<_CharT, _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
1093 time_get<_CharT, _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
1255 time_get<_CharT, _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;
1375 ios_base::iostate __tmperr = ios_base::goodbit;
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;
1401 ios_base::iostate __tmperr = ios_base::goodbit;
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;
1422 ios_base::iostate __tmperr = ios_base::goodbit;
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 IEE 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
1739 use_facet<moneypunct<char, true> >(const locale&);
1740
1741 extern template
1743 use_facet<moneypunct<char, false> >(const locale&);
1744
1745 extern template
1746 const money_put<char>&
1747 use_facet<money_put<char> >(const locale&);
1748
1749 extern template
1750 const money_get<char>&
1751 use_facet<money_get<char> >(const locale&);
1752
1753 extern template
1754 const __timepunct<char>&
1755 use_facet<__timepunct<char> >(const locale&);
1756
1757 extern template
1758 const time_put<char>&
1759 use_facet<time_put<char> >(const locale&);
1760
1761 extern template
1762 const time_get<char>&
1763 use_facet<time_get<char> >(const locale&);
1764
1765 extern template
1766 const messages<char>&
1767 use_facet<messages<char> >(const locale&);
1768
1769 extern template
1770 bool
1771 has_facet<moneypunct<char> >(const locale&);
1772
1773 extern template
1774 bool
1775 has_facet<money_put<char> >(const locale&);
1776
1777 extern template
1778 bool
1779 has_facet<money_get<char> >(const locale&);
1780
1781 extern template
1782 bool
1783 has_facet<__timepunct<char> >(const locale&);
1784
1785 extern template
1786 bool
1787 has_facet<time_put<char> >(const locale&);
1788
1789 extern template
1790 bool
1791 has_facet<time_get<char> >(const locale&);
1792
1793 extern template
1794 bool
1795 has_facet<messages<char> >(const locale&);
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
1846 use_facet<moneypunct<wchar_t, true> >(const locale&);
1847
1848 extern template
1850 use_facet<moneypunct<wchar_t, false> >(const locale&);
1851
1852 extern template
1853 const money_put<wchar_t>&
1854 use_facet<money_put<wchar_t> >(const locale&);
1855
1856 extern template
1857 const money_get<wchar_t>&
1858 use_facet<money_get<wchar_t> >(const locale&);
1859
1860 extern template
1861 const __timepunct<wchar_t>&
1862 use_facet<__timepunct<wchar_t> >(const locale&);
1863
1864 extern template
1865 const time_put<wchar_t>&
1866 use_facet<time_put<wchar_t> >(const locale&);
1867
1868 extern template
1869 const time_get<wchar_t>&
1870 use_facet<time_get<wchar_t> >(const locale&);
1871
1872 extern template
1873 const messages<wchar_t>&
1874 use_facet<messages<wchar_t> >(const locale&);
1875
1876 extern template
1877 bool
1878 has_facet<moneypunct<wchar_t> >(const locale&);
1879
1880 extern template
1881 bool
1882 has_facet<money_put<wchar_t> >(const locale&);
1883
1884 extern template
1885 bool
1886 has_facet<money_get<wchar_t> >(const locale&);
1887
1888 extern template
1889 bool
1890 has_facet<__timepunct<wchar_t> >(const locale&);
1891
1892 extern template
1893 bool
1894 has_facet<time_put<wchar_t> >(const locale&);
1895
1896 extern template
1897 bool
1898 has_facet<time_get<wchar_t> >(const locale&);
1899
1900 extern template
1901 bool
1902 has_facet<messages<wchar_t> >(const locale&);
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.
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.
Basis for explicit traits specializations.
void resize(size_type __n, _CharT __c)
Resizes the string to the specified number of characters.
const _CharT * c_str() const noexcept
Return const pointer to null-terminated contents.
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].