1// Locale support -*- C++ -*-
2
3// Copyright (C) 2007-2021 Free Software Foundation, Inc.
4//
5// This file is part of the GNU ISO C++ Library. This library is free
6// software; you can redistribute it and/or modify it under the
7// terms of the GNU General Public License as published by the
8// Free Software Foundation; either version 3, or (at your option)
9// any later version.
10
11// This library is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// Under Section 7 of GPL version 3, you are granted additional
17// permissions described in the GCC Runtime Library Exception, version
18// 3.1, as published by the Free Software Foundation.
19
20// You should have received a copy of the GNU General Public License and
21// a copy of the GCC Runtime Library Exception along with this program;
22// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23// <http://www.gnu.org/licenses/>.
24
25/** @file bits/locale_facets_nonio.tcc
26 * This is an internal header file, included by other library headers.
27 * Do not attempt to use it directly. @headername{locale}
28 */
29
30#ifndef _LOCALE_FACETS_NONIO_TCC
31#define _LOCALE_FACETS_NONIO_TCC 1
32
33#pragma GCC system_header
34
35namespace std _GLIBCXX_VISIBILITY(default)
36{
37_GLIBCXX_BEGIN_NAMESPACE_VERSION
38
39 template<typename _CharT, bool _Intl>
40 struct __use_cache<__moneypunct_cache<_CharT, _Intl> >
41 {
42 const __moneypunct_cache<_CharT, _Intl>*
43 operator() (const locale& __loc) const
44 {
45 const size_t __i = moneypunct<_CharT, _Intl>::id._M_id();
46 const locale::facet** __caches = __loc._M_impl->_M_caches;
47 if (!__caches[__i])
48 {
49 __moneypunct_cache<_CharT, _Intl>* __tmp = 0;
50 __try
51 {
52 __tmp = new __moneypunct_cache<_CharT, _Intl>;
53 __tmp->_M_cache(__loc);
54 }
55 __catch(...)
56 {
57 delete __tmp;
58 __throw_exception_again;
59 }
60 __loc._M_impl->_M_install_cache(__tmp, __i);
61 }
62 return static_cast<
63 const __moneypunct_cache<_CharT, _Intl>*>(__caches[__i]);
64 }
65 };
66
67 template<typename _CharT, bool _Intl>
68 void
69 __moneypunct_cache<_CharT, _Intl>::_M_cache(const locale& __loc)
70 {
71 const moneypunct<_CharT, _Intl>& __mp =
72 use_facet<moneypunct<_CharT, _Intl> >(__loc);
73
74 _M_decimal_point = __mp.decimal_point();
75 _M_thousands_sep = __mp.thousands_sep();
76 _M_frac_digits = __mp.frac_digits();
77
78 char* __grouping = 0;
79 _CharT* __curr_symbol = 0;
80 _CharT* __positive_sign = 0;
81 _CharT* __negative_sign = 0;
82 size_t __sz;
83 __try
84 {
85 const string& __g = __mp.grouping();
86 __sz = _M_grouping_size = __g.size();
87 __grouping = new char[__sz];
88 __g.copy(s: __grouping, n: __sz);
89 _M_use_grouping = (_M_grouping_size
90 && static_cast<signed char>(__grouping[0]) > 0
91 && (__grouping[0]
92 != __gnu_cxx::__numeric_traits<char>::__max));
93
94 const basic_string<_CharT>& __cs = __mp.curr_symbol();
95 __sz = _M_curr_symbol_size = __cs.size();
96 __curr_symbol = new _CharT[__sz];
97 __cs.copy(__curr_symbol, __sz);
98
99 const basic_string<_CharT>& __ps = __mp.positive_sign();
100 __sz = _M_positive_sign_size = __ps.size();
101 __positive_sign = new _CharT[__sz];
102 __ps.copy(__positive_sign, __sz);
103
104 const basic_string<_CharT>& __ns = __mp.negative_sign();
105 __sz = _M_negative_sign_size = __ns.size();
106 __negative_sign = new _CharT[__sz];
107 __ns.copy(__negative_sign, __sz);
108
109 _M_pos_format = __mp.pos_format();
110 _M_neg_format = __mp.neg_format();
111
112 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__loc);
113 __ct.widen(money_base::_S_atoms,
114 money_base::_S_atoms + money_base::_S_end, _M_atoms);
115
116 _M_grouping = __grouping;
117 _M_curr_symbol = __curr_symbol;
118 _M_positive_sign = __positive_sign;
119 _M_negative_sign = __negative_sign;
120 _M_allocated = true;
121 }
122 __catch(...)
123 {
124 delete [] __grouping;
125 delete [] __curr_symbol;
126 delete [] __positive_sign;
127 delete [] __negative_sign;
128 __throw_exception_again;
129 }
130 }
131
132_GLIBCXX_BEGIN_NAMESPACE_LDBL_OR_CXX11
133
134 template<typename _CharT, typename _InIter>
135 template<bool _Intl>
136 _InIter
137 money_get<_CharT, _InIter>::
138 _M_extract(iter_type __beg, iter_type __end, ios_base& __io,
139 ios_base::iostate& __err, string& __units) const
140 {
141 typedef char_traits<_CharT> __traits_type;
142 typedef typename string_type::size_type size_type;
143 typedef money_base::part part;
144 typedef __moneypunct_cache<_CharT, _Intl> __cache_type;
145
146 const locale& __loc = __io._M_getloc();
147 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
148
149 __use_cache<__cache_type> __uc;
150 const __cache_type* __lc = __uc(__loc);
151 const char_type* __lit = __lc->_M_atoms;
152
153 // Deduced sign.
154 bool __negative = false;
155 // Sign size.
156 size_type __sign_size = 0;
157 // True if sign is mandatory.
158 const bool __mandatory_sign = (__lc->_M_positive_sign_size
159 && __lc->_M_negative_sign_size);
160 // String of grouping info from thousands_sep plucked from __units.
161 string __grouping_tmp;
162 if (__lc->_M_use_grouping)
163 __grouping_tmp.reserve(res: 32);
164 // Last position before the decimal point.
165 int __last_pos = 0;
166 // Separator positions, then, possibly, fractional digits.
167 int __n = 0;
168 // If input iterator is in a valid state.
169 bool __testvalid = true;
170 // Flag marking when a decimal point is found.
171 bool __testdecfound = false;
172
173 // The tentative returned string is stored here.
174 string __res;
175 __res.reserve(res: 32);
176
177 const char_type* __lit_zero = __lit + money_base::_S_zero;
178 const money_base::pattern __p = __lc->_M_neg_format;
179 for (int __i = 0; __i < 4 && __testvalid; ++__i)
180 {
181 const part __which = static_cast<part>(__p.field[__i]);
182 switch (__which)
183 {
184 case money_base::symbol:
185 // According to 22.2.6.1.2, p2, symbol is required
186 // if (__io.flags() & ios_base::showbase), otherwise
187 // is optional and consumed only if other characters
188 // are needed to complete the format.
189 if (__io.flags() & ios_base::showbase || __sign_size > 1
190 || __i == 0
191 || (__i == 1 && (__mandatory_sign
192 || (static_cast<part>(__p.field[0])
193 == money_base::sign)
194 || (static_cast<part>(__p.field[2])
195 == money_base::space)))
196 || (__i == 2 && ((static_cast<part>(__p.field[3])
197 == money_base::value)
198 || (__mandatory_sign
199 && (static_cast<part>(__p.field[3])
200 == money_base::sign)))))
201 {
202 const size_type __len = __lc->_M_curr_symbol_size;
203 size_type __j = 0;
204 for (; __beg != __end && __j < __len
205 && *__beg == __lc->_M_curr_symbol[__j];
206 ++__beg, (void)++__j);
207 if (__j != __len
208 && (__j || __io.flags() & ios_base::showbase))
209 __testvalid = false;
210 }
211 break;
212 case money_base::sign:
213 // Sign might not exist, or be more than one character long.
214 if (__lc->_M_positive_sign_size && __beg != __end
215 && *__beg == __lc->_M_positive_sign[0])
216 {
217 __sign_size = __lc->_M_positive_sign_size;
218 ++__beg;
219 }
220 else if (__lc->_M_negative_sign_size && __beg != __end
221 && *__beg == __lc->_M_negative_sign[0])
222 {
223 __negative = true;
224 __sign_size = __lc->_M_negative_sign_size;
225 ++__beg;
226 }
227 else if (__lc->_M_positive_sign_size
228 && !__lc->_M_negative_sign_size)
229 // "... if no sign is detected, the result is given the sign
230 // that corresponds to the source of the empty string"
231 __negative = true;
232 else if (__mandatory_sign)
233 __testvalid = false;
234 break;
235 case money_base::value:
236 // Extract digits, remove and stash away the
237 // grouping of found thousands separators.
238 for (; __beg != __end; ++__beg)
239 {
240 const char_type __c = *__beg;
241 const char_type* __q = __traits_type::find(__lit_zero,
242 10, __c);
243 if (__q != 0)
244 {
245 __res += money_base::_S_atoms[__q - __lit];
246 ++__n;
247 }
248 else if (__c == __lc->_M_decimal_point
249 && !__testdecfound)
250 {
251 if (__lc->_M_frac_digits <= 0)
252 break;
253
254 __last_pos = __n;
255 __n = 0;
256 __testdecfound = true;
257 }
258 else if (__lc->_M_use_grouping
259 && __c == __lc->_M_thousands_sep
260 && !__testdecfound)
261 {
262 if (__n)
263 {
264 // Mark position for later analysis.
265 __grouping_tmp += static_cast<char>(__n);
266 __n = 0;
267 }
268 else
269 {
270 __testvalid = false;
271 break;
272 }
273 }
274 else
275 break;
276 }
277 if (__res.empty())
278 __testvalid = false;
279 break;
280 case money_base::space:
281 // At least one space is required.
282 if (__beg != __end && __ctype.is(ctype_base::space, *__beg))
283 ++__beg;
284 else
285 __testvalid = false;
286 // fallthrough
287 case money_base::none:
288 // Only if not at the end of the pattern.
289 if (__i != 3)
290 for (; __beg != __end
291 && __ctype.is(ctype_base::space, *__beg); ++__beg);
292 break;
293 }
294 }
295
296 // Need to get the rest of the sign characters, if they exist.
297 if (__sign_size > 1 && __testvalid)
298 {
299 const char_type* __sign = __negative ? __lc->_M_negative_sign
300 : __lc->_M_positive_sign;
301 size_type __i = 1;
302 for (; __beg != __end && __i < __sign_size
303 && *__beg == __sign[__i]; ++__beg, (void)++__i);
304
305 if (__i != __sign_size)
306 __testvalid = false;
307 }
308
309 if (__testvalid)
310 {
311 // Strip leading zeros.
312 if (__res.size() > 1)
313 {
314 const size_type __first = __res.find_first_not_of(c: '0');
315 const bool __only_zeros = __first == string::npos;
316 if (__first)
317 __res.erase(0, __only_zeros ? __res.size() - 1 : __first);
318 }
319
320 // 22.2.6.1.2, p4
321 if (__negative && __res[0] != '0')
322 __res.insert(p: __res.begin(), c: '-');
323
324 // Test for grouping fidelity.
325 if (__grouping_tmp.size())
326 {
327 // Add the ending grouping.
328 __grouping_tmp += static_cast<char>(__testdecfound ? __last_pos
329 : __n);
330 if (!std::__verify_grouping(grouping: __lc->_M_grouping,
331 grouping_size: __lc->_M_grouping_size,
332 __grouping_tmp))
333 __err |= ios_base::failbit;
334 }
335
336 // Iff not enough digits were supplied after the decimal-point.
337 if (__testdecfound && __n != __lc->_M_frac_digits)
338 __testvalid = false;
339 }
340
341 // Iff valid sequence is not recognized.
342 if (!__testvalid)
343 __err |= ios_base::failbit;
344 else
345 __units.swap(s&: __res);
346
347 // Iff no more characters are available.
348 if (__beg == __end)
349 __err |= ios_base::eofbit;
350 return __beg;
351 }
352
353#if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__ \
354 && (_GLIBCXX_USE_CXX11_ABI == 0 || defined __LONG_DOUBLE_IEEE128__)
355 template<typename _CharT, typename _InIter>
356 _InIter
357 money_get<_CharT, _InIter>::
358 __do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
359 ios_base::iostate& __err, double& __units) const
360 {
361 string __str;
362 __beg = __intl ? _M_extract<true>(__beg, __end, __io, __err, __str)
363 : _M_extract<false>(__beg, __end, __io, __err, __str);
364 std::__convert_to_v(__str.c_str(), __units, __err, _S_get_c_locale());
365 return __beg;
366 }
367#endif
368
369 template<typename _CharT, typename _InIter>
370 _InIter
371 money_get<_CharT, _InIter>::
372 do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
373 ios_base::iostate& __err, long double& __units) const
374 {
375 string __str;
376 __beg = __intl ? _M_extract<true>(__beg, __end, __io, __err, __str)
377 : _M_extract<false>(__beg, __end, __io, __err, __str);
378 std::__convert_to_v(__str.c_str(), __units, __err, _S_get_c_locale());
379 return __beg;
380 }
381
382 template<typename _CharT, typename _InIter>
383 _InIter
384 money_get<_CharT, _InIter>::
385 do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
386 ios_base::iostate& __err, string_type& __digits) const
387 {
388 typedef typename string::size_type size_type;
389
390 const locale& __loc = __io._M_getloc();
391 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
392
393 string __str;
394 __beg = __intl ? _M_extract<true>(__beg, __end, __io, __err, __str)
395 : _M_extract<false>(__beg, __end, __io, __err, __str);
396 const size_type __len = __str.size();
397 if (__len)
398 {
399 __digits.resize(__len);
400 __ctype.widen(__str.data(), __str.data() + __len, &__digits[0]);
401 }
402 return __beg;
403 }
404
405#if defined _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT \
406 && defined __LONG_DOUBLE_IEEE128__
407 template<typename _CharT, typename _InIter>
408 _InIter
409 money_get<_CharT, _InIter>::
410 __do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
411 ios_base::iostate& __err, __ibm128& __units) const
412 {
413 string __str;
414 __beg = __intl ? _M_extract<true>(__beg, __end, __io, __err, __str)
415 : _M_extract<false>(__beg, __end, __io, __err, __str);
416 std::__convert_to_v(__str.c_str(), __units, __err, _S_get_c_locale());
417 return __beg;
418 }
419#endif
420
421 template<typename _CharT, typename _OutIter>
422 template<bool _Intl>
423 _OutIter
424 money_put<_CharT, _OutIter>::
425 _M_insert(iter_type __s, ios_base& __io, char_type __fill,
426 const string_type& __digits) const
427 {
428 typedef typename string_type::size_type size_type;
429 typedef money_base::part part;
430 typedef __moneypunct_cache<_CharT, _Intl> __cache_type;
431
432 const locale& __loc = __io._M_getloc();
433 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
434
435 __use_cache<__cache_type> __uc;
436 const __cache_type* __lc = __uc(__loc);
437 const char_type* __lit = __lc->_M_atoms;
438
439 // Determine if negative or positive formats are to be used, and
440 // discard leading negative_sign if it is present.
441 const char_type* __beg = __digits.data();
442
443 money_base::pattern __p;
444 const char_type* __sign;
445 size_type __sign_size;
446 if (!(*__beg == __lit[money_base::_S_minus]))
447 {
448 __p = __lc->_M_pos_format;
449 __sign = __lc->_M_positive_sign;
450 __sign_size = __lc->_M_positive_sign_size;
451 }
452 else
453 {
454 __p = __lc->_M_neg_format;
455 __sign = __lc->_M_negative_sign;
456 __sign_size = __lc->_M_negative_sign_size;
457 if (__digits.size())
458 ++__beg;
459 }
460
461 // Look for valid numbers in the ctype facet within input digits.
462 size_type __len = __ctype.scan_not(ctype_base::digit, __beg,
463 __beg + __digits.size()) - __beg;
464 if (__len)
465 {
466 // Assume valid input, and attempt to format.
467 // Break down input numbers into base components, as follows:
468 // final_value = grouped units + (decimal point) + (digits)
469 string_type __value;
470 __value.reserve(2 * __len);
471
472 // Add thousands separators to non-decimal digits, per
473 // grouping rules.
474 long __paddec = __len - __lc->_M_frac_digits;
475 if (__paddec > 0)
476 {
477 if (__lc->_M_frac_digits < 0)
478 __paddec = __len;
479 if (__lc->_M_grouping_size)
480 {
481 __value.assign(2 * __paddec, char_type());
482 _CharT* __vend =
483 std::__add_grouping(&__value[0], __lc->_M_thousands_sep,
484 __lc->_M_grouping,
485 __lc->_M_grouping_size,
486 __beg, __beg + __paddec);
487 __value.erase(__vend - &__value[0]);
488 }
489 else
490 __value.assign(__beg, __paddec);
491 }
492
493 // Deal with decimal point, decimal digits.
494 if (__lc->_M_frac_digits > 0)
495 {
496 __value += __lc->_M_decimal_point;
497 if (__paddec >= 0)
498 __value.append(__beg + __paddec, __lc->_M_frac_digits);
499 else
500 {
501 // Have to pad zeros in the decimal position.
502 __value.append(-__paddec, __lit[money_base::_S_zero]);
503 __value.append(__beg, __len);
504 }
505 }
506
507 // Calculate length of resulting string.
508 const ios_base::fmtflags __f = __io.flags()
509 & ios_base::adjustfield;
510 __len = __value.size() + __sign_size;
511 __len += ((__io.flags() & ios_base::showbase)
512 ? __lc->_M_curr_symbol_size : 0);
513
514 string_type __res;
515 __res.reserve(2 * __len);
516
517 const size_type __width = static_cast<size_type>(__io.width());
518 const bool __testipad = (__f == ios_base::internal
519 && __len < __width);
520 // Fit formatted digits into the required pattern.
521 for (int __i = 0; __i < 4; ++__i)
522 {
523 const part __which = static_cast<part>(__p.field[__i]);
524 switch (__which)
525 {
526 case money_base::symbol:
527 if (__io.flags() & ios_base::showbase)
528 __res.append(__lc->_M_curr_symbol,
529 __lc->_M_curr_symbol_size);
530 break;
531 case money_base::sign:
532 // Sign might not exist, or be more than one
533 // character long. In that case, add in the rest
534 // below.
535 if (__sign_size)
536 __res += __sign[0];
537 break;
538 case money_base::value:
539 __res += __value;
540 break;
541 case money_base::space:
542 // At least one space is required, but if internal
543 // formatting is required, an arbitrary number of
544 // fill spaces will be necessary.
545 if (__testipad)
546 __res.append(__width - __len, __fill);
547 else
548 __res += __fill;
549 break;
550 case money_base::none:
551 if (__testipad)
552 __res.append(__width - __len, __fill);
553 break;
554 }
555 }
556
557 // Special case of multi-part sign parts.
558 if (__sign_size > 1)
559 __res.append(__sign + 1, __sign_size - 1);
560
561 // Pad, if still necessary.
562 __len = __res.size();
563 if (__width > __len)
564 {
565 if (__f == ios_base::left)
566 // After.
567 __res.append(__width - __len, __fill);
568 else
569 // Before.
570 __res.insert(0, __width - __len, __fill);
571 __len = __width;
572 }
573
574 // Write resulting, fully-formatted string to output iterator.
575 __s = std::__write(__s, __res.data(), __len);
576 }
577 __io.width(wide: 0);
578 return __s;
579 }
580
581#if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__ \
582 && (_GLIBCXX_USE_CXX11_ABI == 0 || defined __LONG_DOUBLE_IEEE128__)
583 template<typename _CharT, typename _OutIter>
584 _OutIter
585 money_put<_CharT, _OutIter>::
586 __do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
587 double __units) const
588 { return this->do_put(__s, __intl, __io, __fill, (long double) __units); }
589#endif
590
591 template<typename _CharT, typename _OutIter>
592 _OutIter
593 money_put<_CharT, _OutIter>::
594 do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
595 long double __units) const
596 {
597 const locale __loc = __io.getloc();
598 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
599#if _GLIBCXX_USE_C99_STDIO
600 // First try a buffer perhaps big enough.
601 int __cs_size = 64;
602 char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
603 // _GLIBCXX_RESOLVE_LIB_DEFECTS
604 // 328. Bad sprintf format modifier in money_put<>::do_put()
605 int __len = std::__convert_from_v(cloc: _S_get_c_locale(), out: __cs, size: __cs_size,
606 fmt: "%.*Lf", 0, __units);
607 // If the buffer was not large enough, try again with the correct size.
608 if (__len >= __cs_size)
609 {
610 __cs_size = __len + 1;
611 __cs = static_cast<char*>(__builtin_alloca(__cs_size));
612 __len = std::__convert_from_v(cloc: _S_get_c_locale(), out: __cs, size: __cs_size,
613 fmt: "%.*Lf", 0, __units);
614 }
615#else
616 // max_exponent10 + 1 for the integer part, + 2 for sign and '\0'.
617 const int __cs_size =
618 __gnu_cxx::__numeric_traits<long double>::__max_exponent10 + 3;
619 char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
620 int __len = std::__convert_from_v(_S_get_c_locale(), __cs, 0, "%.*Lf",
621 0, __units);
622#endif
623 string_type __digits(__len, char_type());
624 __ctype.widen(__cs, __cs + __len, &__digits[0]);
625 return __intl ? _M_insert<true>(__s, __io, __fill, __digits)
626 : _M_insert<false>(__s, __io, __fill, __digits);
627 }
628
629 template<typename _CharT, typename _OutIter>
630 _OutIter
631 money_put<_CharT, _OutIter>::
632 do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
633 const string_type& __digits) const
634 { return __intl ? _M_insert<true>(__s, __io, __fill, __digits)
635 : _M_insert<false>(__s, __io, __fill, __digits); }
636
637#if defined _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT \
638 && defined __LONG_DOUBLE_IEEE128__
639 template<typename _CharT, typename _OutIter>
640 _OutIter
641 money_put<_CharT, _OutIter>::
642 __do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
643 __ibm128 __units) const
644 {
645 const locale __loc = __io.getloc();
646 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
647#if _GLIBCXX_USE_C99_STDIO
648 // First try a buffer perhaps big enough.
649 int __cs_size = 64;
650 char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
651 // _GLIBCXX_RESOLVE_LIB_DEFECTS
652 // 328. Bad sprintf format modifier in money_put<>::do_put()
653 int __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
654 "%.*Lf", 0, __units);
655 // If the buffer was not large enough, try again with the correct size.
656 if (__len >= __cs_size)
657 {
658 __cs_size = __len + 1;
659 __cs = static_cast<char*>(__builtin_alloca(__cs_size));
660 __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
661 "%.*Lf", 0, __units);
662 }
663#else
664 // max_exponent10 + 1 for the integer part, + 2 for sign and '\0'.
665 const int __cs_size =
666 __gnu_cxx::__numeric_traits<long double>::__max_exponent10 + 3;
667 char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
668 int __len = std::__convert_from_v(_S_get_c_locale(), __cs, 0, "%.*Lf",
669 0, __units);
670#endif
671 string_type __digits(__len, char_type());
672 __ctype.widen(__cs, __cs + __len, &__digits[0]);
673 return __intl ? _M_insert<true>(__s, __io, __fill, __digits)
674 : _M_insert<false>(__s, __io, __fill, __digits);
675 }
676#endif
677
678_GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11
679
680 // NB: Not especially useful. Without an ios_base object or some
681 // kind of locale reference, we are left clawing at the air where
682 // the side of the mountain used to be...
683 template<typename _CharT, typename _InIter>
684 time_base::dateorder
685 time_get<_CharT, _InIter>::do_date_order() const
686 { return time_base::no_order; }
687
688 // Expand a strftime format string and parse it. E.g., do_get_date() may
689 // pass %m/%d/%Y => extracted characters.
690 template<typename _CharT, typename _InIter>
691 _InIter
692 time_get<_CharT, _InIter>::
693 _M_extract_via_format(iter_type __beg, iter_type __end, ios_base& __io,
694 ios_base::iostate& __err, tm* __tm,
695 const _CharT* __format) const
696 {
697 const locale& __loc = __io._M_getloc();
698 const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
699 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
700 const size_t __len = char_traits<_CharT>::length(__format);
701
702 ios_base::iostate __tmperr = ios_base::goodbit;
703 size_t __i = 0;
704 for (; __beg != __end && __i < __len && !__tmperr; ++__i)
705 {
706 if (__ctype.narrow(__format[__i], 0) == '%')
707 {
708 // Verify valid formatting code, attempt to extract.
709 char __c = __ctype.narrow(__format[++__i], 0);
710 int __mem = 0;
711 if (__c == 'E' || __c == 'O')
712 __c = __ctype.narrow(__format[++__i], 0);
713 switch (__c)
714 {
715 const char* __cs;
716 _CharT __wcs[10];
717 case 'a':
718 // Abbreviated weekday name [tm_wday]
719 const char_type* __days1[7];
720 __tp._M_days_abbreviated(__days1);
721 __beg = _M_extract_name(__beg, __end, member&: __mem, names: __days1,
722 indexlen: 7, __io, err&: __tmperr);
723 if (!__tmperr)
724 __tm->tm_wday = __mem;
725 break;
726 case 'A':
727 // Weekday name [tm_wday].
728 const char_type* __days2[7];
729 __tp._M_days(__days2);
730 __beg = _M_extract_name(__beg, __end, member&: __mem, names: __days2,
731 indexlen: 7, __io, err&: __tmperr);
732 if (!__tmperr)
733 __tm->tm_wday = __mem;
734 break;
735 case 'h':
736 case 'b':
737 // Abbreviated month name [tm_mon]
738 const char_type* __months1[12];
739 __tp._M_months_abbreviated(__months1);
740 __beg = _M_extract_name(__beg, __end, member&: __mem,
741 names: __months1, indexlen: 12, __io, err&: __tmperr);
742 if (!__tmperr)
743 __tm->tm_mon = __mem;
744 break;
745 case 'B':
746 // Month name [tm_mon].
747 const char_type* __months2[12];
748 __tp._M_months(__months2);
749 __beg = _M_extract_name(__beg, __end, member&: __mem,
750 names: __months2, indexlen: 12, __io, err&: __tmperr);
751 if (!__tmperr)
752 __tm->tm_mon = __mem;
753 break;
754 case 'c':
755 // Default time and date representation.
756 const char_type* __dt[2];
757 __tp._M_date_time_formats(__dt);
758 __beg = _M_extract_via_format(__beg, __end, __io, err&: __tmperr,
759 __tm, format: __dt[0]);
760 break;
761 case 'd':
762 // Day [01, 31]. [tm_mday]
763 __beg = _M_extract_num(__beg, __end, member&: __mem, min: 1, max: 31, len: 2,
764 __io, err&: __tmperr);
765 if (!__tmperr)
766 __tm->tm_mday = __mem;
767 break;
768 case 'e':
769 // Day [1, 31], with single digits preceded by
770 // space. [tm_mday]
771 if (__ctype.is(ctype_base::space, *__beg))
772 __beg = _M_extract_num(beg: ++__beg, __end, member&: __mem, min: 1, max: 9,
773 len: 1, __io, err&: __tmperr);
774 else
775 __beg = _M_extract_num(__beg, __end, member&: __mem, min: 10, max: 31,
776 len: 2, __io, err&: __tmperr);
777 if (!__tmperr)
778 __tm->tm_mday = __mem;
779 break;
780 case 'D':
781 // Equivalent to %m/%d/%y.[tm_mon, tm_mday, tm_year]
782 __cs = "%m/%d/%y";
783 __ctype.widen(__cs, __cs + 9, __wcs);
784 __beg = _M_extract_via_format(__beg, __end, __io, err&: __tmperr,
785 __tm, format: __wcs);
786 break;
787 case 'H':
788 // Hour [00, 23]. [tm_hour]
789 __beg = _M_extract_num(__beg, __end, member&: __mem, min: 0, max: 23, len: 2,
790 __io, err&: __tmperr);
791 if (!__tmperr)
792 __tm->tm_hour = __mem;
793 break;
794 case 'I':
795 // Hour [01, 12]. [tm_hour]
796 __beg = _M_extract_num(__beg, __end, member&: __mem, min: 1, max: 12, len: 2,
797 __io, err&: __tmperr);
798 if (!__tmperr)
799 __tm->tm_hour = __mem;
800 break;
801 case 'm':
802 // Month [01, 12]. [tm_mon]
803 __beg = _M_extract_num(__beg, __end, member&: __mem, min: 1, max: 12, len: 2,
804 __io, err&: __tmperr);
805 if (!__tmperr)
806 __tm->tm_mon = __mem - 1;
807 break;
808 case 'M':
809 // Minute [00, 59]. [tm_min]
810 __beg = _M_extract_num(__beg, __end, member&: __mem, min: 0, max: 59, len: 2,
811 __io, err&: __tmperr);
812 if (!__tmperr)
813 __tm->tm_min = __mem;
814 break;
815 case 'n':
816 if (__ctype.narrow(*__beg, 0) == '\n')
817 ++__beg;
818 else
819 __tmperr |= ios_base::failbit;
820 break;
821 case 'R':
822 // Equivalent to (%H:%M).
823 __cs = "%H:%M";
824 __ctype.widen(__cs, __cs + 6, __wcs);
825 __beg = _M_extract_via_format(__beg, __end, __io, err&: __tmperr,
826 __tm, format: __wcs);
827 break;
828 case 'S':
829 // Seconds. [tm_sec]
830 // [00, 60] in C99 (one leap-second), [00, 61] in C89.
831#if _GLIBCXX_USE_C99
832 __beg = _M_extract_num(__beg, __end, member&: __mem, min: 0, max: 60, len: 2,
833#else
834 __beg = _M_extract_num(__beg, __end, __mem, 0, 61, 2,
835#endif
836 __io, err&: __tmperr);
837 if (!__tmperr)
838 __tm->tm_sec = __mem;
839 break;
840 case 't':
841 if (__ctype.narrow(*__beg, 0) == '\t')
842 ++__beg;
843 else
844 __tmperr |= ios_base::failbit;
845 break;
846 case 'T':
847 // Equivalent to (%H:%M:%S).
848 __cs = "%H:%M:%S";
849 __ctype.widen(__cs, __cs + 9, __wcs);
850 __beg = _M_extract_via_format(__beg, __end, __io, err&: __tmperr,
851 __tm, format: __wcs);
852 break;
853 case 'x':
854 // Locale's date.
855 const char_type* __dates[2];
856 __tp._M_date_formats(__dates);
857 __beg = _M_extract_via_format(__beg, __end, __io, err&: __tmperr,
858 __tm, format: __dates[0]);
859 break;
860 case 'X':
861 // Locale's time.
862 const char_type* __times[2];
863 __tp._M_time_formats(__times);
864 __beg = _M_extract_via_format(__beg, __end, __io, err&: __tmperr,
865 __tm, format: __times[0]);
866 break;
867 case 'y':
868 case 'C': // C99
869 // Two digit year.
870 case 'Y':
871 // Year [1900).
872 // NB: We parse either two digits, implicitly years since
873 // 1900, or 4 digits, full year. In both cases we can
874 // reconstruct [tm_year]. See also libstdc++/26701.
875 __beg = _M_extract_num(__beg, __end, member&: __mem, min: 0, max: 9999, len: 4,
876 __io, err&: __tmperr);
877 if (!__tmperr)
878 __tm->tm_year = __mem < 0 ? __mem + 100 : __mem - 1900;
879 break;
880 case 'Z':
881 // Timezone info.
882 if (__ctype.is(ctype_base::upper, *__beg))
883 {
884 int __tmp;
885 __beg = _M_extract_name(__beg, __end, member&: __tmp,
886 names: __timepunct_cache<_CharT>::_S_timezones,
887 indexlen: 14, __io, err&: __tmperr);
888
889 // GMT requires special effort.
890 if (__beg != __end && !__tmperr && __tmp == 0
891 && (*__beg == __ctype.widen('-')
892 || *__beg == __ctype.widen('+')))
893 {
894 __beg = _M_extract_num(__beg, __end, member&: __tmp, min: 0, max: 23, len: 2,
895 __io, err&: __tmperr);
896 __beg = _M_extract_num(__beg, __end, member&: __tmp, min: 0, max: 59, len: 2,
897 __io, err&: __tmperr);
898 }
899 }
900 else
901 __tmperr |= ios_base::failbit;
902 break;
903 default:
904 // Not recognized.
905 __tmperr |= ios_base::failbit;
906 }
907 }
908 else
909 {
910 // Verify format and input match, extract and discard.
911 if (__format[__i] == *__beg)
912 ++__beg;
913 else
914 __tmperr |= ios_base::failbit;
915 }
916 }
917
918 if (__tmperr || __i != __len)
919 __err |= ios_base::failbit;
920
921 return __beg;
922 }
923
924 template<typename _CharT, typename _InIter>
925 _InIter
926 time_get<_CharT, _InIter>::
927 _M_extract_num(iter_type __beg, iter_type __end, int& __member,
928 int __min, int __max, size_t __len,
929 ios_base& __io, ios_base::iostate& __err) const
930 {
931 const locale& __loc = __io._M_getloc();
932 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
933
934 // As-is works for __len = 1, 2, 4, the values actually used.
935 int __mult = __len == 2 ? 10 : (__len == 4 ? 1000 : 1);
936
937 ++__min;
938 size_t __i = 0;
939 int __value = 0;
940 for (; __beg != __end && __i < __len; ++__beg, (void)++__i)
941 {
942 const char __c = __ctype.narrow(*__beg, '*');
943 if (__c >= '0' && __c <= '9')
944 {
945 __value = __value * 10 + (__c - '0');
946 const int __valuec = __value * __mult;
947 if (__valuec > __max || __valuec + __mult < __min)
948 break;
949 __mult /= 10;
950 }
951 else
952 break;
953 }
954 if (__i == __len)
955 __member = __value;
956 // Special encoding for do_get_year, 'y', and 'Y' above.
957 else if (__len == 4 && __i == 2)
958 __member = __value - 100;
959 else
960 __err |= ios_base::failbit;
961
962 return __beg;
963 }
964
965 // Assumptions:
966 // All elements in __names are unique.
967 template<typename _CharT, typename _InIter>
968 _InIter
969 time_get<_CharT, _InIter>::
970 _M_extract_name(iter_type __beg, iter_type __end, int& __member,
971 const _CharT** __names, size_t __indexlen,
972 ios_base& __io, ios_base::iostate& __err) const
973 {
974 typedef char_traits<_CharT> __traits_type;
975 const locale& __loc = __io._M_getloc();
976 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
977
978 int* __matches = static_cast<int*>(__builtin_alloca(sizeof(int)
979 * __indexlen));
980 size_t __nmatches = 0;
981 size_t __pos = 0;
982 bool __testvalid = true;
983 const char_type* __name;
984
985 // Look for initial matches.
986 // NB: Some of the locale data is in the form of all lowercase
987 // names, and some is in the form of initially-capitalized
988 // names. Look for both.
989 if (__beg != __end)
990 {
991 const char_type __c = *__beg;
992 for (size_t __i1 = 0; __i1 < __indexlen; ++__i1)
993 if (__c == __names[__i1][0]
994 || __c == __ctype.toupper(__names[__i1][0]))
995 __matches[__nmatches++] = __i1;
996 }
997
998 while (__nmatches > 1)
999 {
1000 // Find smallest matching string.
1001 size_t __minlen = __traits_type::length(__names[__matches[0]]);
1002 for (size_t __i2 = 1; __i2 < __nmatches; ++__i2)
1003 __minlen = std::min(__minlen,
1004 __traits_type::length(__names[__matches[__i2]]));
1005 ++__beg;
1006 ++__pos;
1007 if (__pos < __minlen && __beg != __end)
1008 for (size_t __i3 = 0; __i3 < __nmatches;)
1009 {
1010 __name = __names[__matches[__i3]];
1011 if (!(__name[__pos] == *__beg))
1012 __matches[__i3] = __matches[--__nmatches];
1013 else
1014 ++__i3;
1015 }
1016 else
1017 break;
1018 }
1019
1020 if (__nmatches == 1)
1021 {
1022 // Make sure found name is completely extracted.
1023 ++__beg;
1024 ++__pos;
1025 __name = __names[__matches[0]];
1026 const size_t __len = __traits_type::length(__name);
1027 while (__pos < __len && __beg != __end && __name[__pos] == *__beg)
1028 ++__beg, (void)++__pos;
1029
1030 if (__len == __pos)
1031 __member = __matches[0];
1032 else
1033 __testvalid = false;
1034 }
1035 else
1036 __testvalid = false;
1037 if (!__testvalid)
1038 __err |= ios_base::failbit;
1039
1040 return __beg;
1041 }
1042
1043 template<typename _CharT, typename _InIter>
1044 _InIter
1045 time_get<_CharT, _InIter>::
1046 _M_extract_wday_or_month(iter_type __beg, iter_type __end, int& __member,
1047 const _CharT** __names, size_t __indexlen,
1048 ios_base& __io, ios_base::iostate& __err) const
1049 {
1050 typedef char_traits<_CharT> __traits_type;
1051 const locale& __loc = __io._M_getloc();
1052 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1053
1054 int* __matches = static_cast<int*>(__builtin_alloca(2 * sizeof(int)
1055 * __indexlen));
1056 size_t __nmatches = 0;
1057 size_t* __matches_lengths = 0;
1058 size_t __pos = 0;
1059
1060 if (__beg != __end)
1061 {
1062 const char_type __c = *__beg;
1063 for (size_t __i = 0; __i < 2 * __indexlen; ++__i)
1064 if (__c == __names[__i][0]
1065 || __c == __ctype.toupper(__names[__i][0]))
1066 __matches[__nmatches++] = __i;
1067 }
1068
1069 if (__nmatches)
1070 {
1071 ++__beg;
1072 ++__pos;
1073
1074 __matches_lengths
1075 = static_cast<size_t*>(__builtin_alloca(sizeof(size_t)
1076 * __nmatches));
1077 for (size_t __i = 0; __i < __nmatches; ++__i)
1078 __matches_lengths[__i]
1079 = __traits_type::length(__names[__matches[__i]]);
1080 }
1081
1082 for (; __beg != __end; ++__beg, (void)++__pos)
1083 {
1084 size_t __nskipped = 0;
1085 const char_type __c = *__beg;
1086 for (size_t __i = 0; __i < __nmatches;)
1087 {
1088 const char_type* __name = __names[__matches[__i]];
1089 if (__pos >= __matches_lengths[__i])
1090 ++__nskipped, ++__i;
1091 else if (!(__name[__pos] == __c))
1092 {
1093 --__nmatches;
1094 __matches[__i] = __matches[__nmatches];
1095 __matches_lengths[__i] = __matches_lengths[__nmatches];
1096 }
1097 else
1098 ++__i;
1099 }
1100 if (__nskipped == __nmatches)
1101 break;
1102 }
1103
1104 if ((__nmatches == 1 && __matches_lengths[0] == __pos)
1105 || (__nmatches == 2 && (__matches_lengths[0] == __pos
1106 || __matches_lengths[1] == __pos)))
1107 __member = (__matches[0] >= (int)__indexlen
1108 ? __matches[0] - (int)__indexlen : __matches[0]);
1109 else
1110 __err |= ios_base::failbit;
1111
1112 return __beg;
1113 }
1114
1115 template<typename _CharT, typename _InIter>
1116 _InIter
1117 time_get<_CharT, _InIter>::
1118 do_get_time(iter_type __beg, iter_type __end, ios_base& __io,
1119 ios_base::iostate& __err, tm* __tm) const
1120 {
1121 const locale& __loc = __io._M_getloc();
1122 const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
1123 const char_type* __times[2];
1124 __tp._M_time_formats(__times);
1125 __beg = _M_extract_via_format(__beg, __end, __io, __err,
1126 __tm, format: __times[0]);
1127 if (__beg == __end)
1128 __err |= ios_base::eofbit;
1129 return __beg;
1130 }
1131
1132 template<typename _CharT, typename _InIter>
1133 _InIter
1134 time_get<_CharT, _InIter>::
1135 do_get_date(iter_type __beg, iter_type __end, ios_base& __io,
1136 ios_base::iostate& __err, tm* __tm) const
1137 {
1138 const locale& __loc = __io._M_getloc();
1139 const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
1140 const char_type* __dates[2];
1141 __tp._M_date_formats(__dates);
1142 __beg = _M_extract_via_format(__beg, __end, __io, __err,
1143 __tm, format: __dates[0]);
1144 if (__beg == __end)
1145 __err |= ios_base::eofbit;
1146 return __beg;
1147 }
1148
1149 template<typename _CharT, typename _InIter>
1150 _InIter
1151 time_get<_CharT, _InIter>::
1152 do_get_weekday(iter_type __beg, iter_type __end, ios_base& __io,
1153 ios_base::iostate& __err, tm* __tm) const
1154 {
1155 const locale& __loc = __io._M_getloc();
1156 const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
1157 const char_type* __days[14];
1158 __tp._M_days_abbreviated(__days);
1159 __tp._M_days(__days + 7);
1160 int __tmpwday;
1161 ios_base::iostate __tmperr = ios_base::goodbit;
1162
1163 __beg = _M_extract_wday_or_month(__beg, __end, member&: __tmpwday, names: __days, indexlen: 7,
1164 __io, err&: __tmperr);
1165 if (!__tmperr)
1166 __tm->tm_wday = __tmpwday;
1167 else
1168 __err |= ios_base::failbit;
1169
1170 if (__beg == __end)
1171 __err |= ios_base::eofbit;
1172 return __beg;
1173 }
1174
1175 template<typename _CharT, typename _InIter>
1176 _InIter
1177 time_get<_CharT, _InIter>::
1178 do_get_monthname(iter_type __beg, iter_type __end,
1179 ios_base& __io, ios_base::iostate& __err, tm* __tm) const
1180 {
1181 const locale& __loc = __io._M_getloc();
1182 const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
1183 const char_type* __months[24];
1184 __tp._M_months_abbreviated(__months);
1185 __tp._M_months(__months + 12);
1186 int __tmpmon;
1187 ios_base::iostate __tmperr = ios_base::goodbit;
1188
1189 __beg = _M_extract_wday_or_month(__beg, __end, member&: __tmpmon, names: __months, indexlen: 12,
1190 __io, err&: __tmperr);
1191 if (!__tmperr)
1192 __tm->tm_mon = __tmpmon;
1193 else
1194 __err |= ios_base::failbit;
1195
1196 if (__beg == __end)
1197 __err |= ios_base::eofbit;
1198 return __beg;
1199 }
1200
1201 template<typename _CharT, typename _InIter>
1202 _InIter
1203 time_get<_CharT, _InIter>::
1204 do_get_year(iter_type __beg, iter_type __end, ios_base& __io,
1205 ios_base::iostate& __err, tm* __tm) const
1206 {
1207 int __tmpyear;
1208 ios_base::iostate __tmperr = ios_base::goodbit;
1209
1210 __beg = _M_extract_num(__beg, __end, member&: __tmpyear, min: 0, max: 9999, len: 4,
1211 __io, err&: __tmperr);
1212 if (!__tmperr)
1213 __tm->tm_year = __tmpyear < 0 ? __tmpyear + 100 : __tmpyear - 1900;
1214 else
1215 __err |= ios_base::failbit;
1216
1217 if (__beg == __end)
1218 __err |= ios_base::eofbit;
1219 return __beg;
1220 }
1221
1222#if __cplusplus >= 201103L
1223 template<typename _CharT, typename _InIter>
1224 inline
1225 _InIter
1226 time_get<_CharT, _InIter>::
1227 get(iter_type __s, iter_type __end, ios_base& __io,
1228 ios_base::iostate& __err, tm* __tm, const char_type* __fmt,
1229 const char_type* __fmtend) const
1230 {
1231 const locale& __loc = __io._M_getloc();
1232 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
1233 __err = ios_base::goodbit;
1234 while (__fmt != __fmtend &&
1235 __err == ios_base::goodbit)
1236 {
1237 if (__s == __end)
1238 {
1239 __err = ios_base::eofbit | ios_base::failbit;
1240 break;
1241 }
1242 else if (__ctype.narrow(*__fmt, 0) == '%')
1243 {
1244 char __format;
1245 char __mod = 0;
1246 if (++__fmt == __fmtend)
1247 {
1248 __err = ios_base::failbit;
1249 break;
1250 }
1251 const char __c = __ctype.narrow(*__fmt, 0);
1252 if (__c != 'E' && __c != 'O')
1253 __format = __c;
1254 else if (++__fmt != __fmtend)
1255 {
1256 __mod = __c;
1257 __format = __ctype.narrow(*__fmt, 0);
1258 }
1259 else
1260 {
1261 __err = ios_base::failbit;
1262 break;
1263 }
1264 __s = this->do_get(__s, __end, __io, __err, __tm, __format,
1265 __mod);
1266 ++__fmt;
1267 }
1268 else if (__ctype.is(ctype_base::space, *__fmt))
1269 {
1270 ++__fmt;
1271 while (__fmt != __fmtend &&
1272 __ctype.is(ctype_base::space, *__fmt))
1273 ++__fmt;
1274
1275 while (__s != __end &&
1276 __ctype.is(ctype_base::space, *__s))
1277 ++__s;
1278 }
1279 // TODO real case-insensitive comparison
1280 else if (__ctype.tolower(*__s) == __ctype.tolower(*__fmt) ||
1281 __ctype.toupper(*__s) == __ctype.toupper(*__fmt))
1282 {
1283 ++__s;
1284 ++__fmt;
1285 }
1286 else
1287 {
1288 __err = ios_base::failbit;
1289 break;
1290 }
1291 }
1292 return __s;
1293 }
1294
1295 template<typename _CharT, typename _InIter>
1296 inline
1297 _InIter
1298 time_get<_CharT, _InIter>::
1299 do_get(iter_type __beg, iter_type __end, ios_base& __io,
1300 ios_base::iostate& __err, tm* __tm,
1301 char __format, char __mod) const
1302 {
1303 const locale& __loc = __io._M_getloc();
1304 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
1305 __err = ios_base::goodbit;
1306
1307 char_type __fmt[4];
1308 __fmt[0] = __ctype.widen('%');
1309 if (!__mod)
1310 {
1311 __fmt[1] = __format;
1312 __fmt[2] = char_type();
1313 }
1314 else
1315 {
1316 __fmt[1] = __mod;
1317 __fmt[2] = __format;
1318 __fmt[3] = char_type();
1319 }
1320
1321 __beg = _M_extract_via_format(__beg, __end, __io, __err, __tm, format: __fmt);
1322 if (__beg == __end)
1323 __err |= ios_base::eofbit;
1324 return __beg;
1325 }
1326
1327#endif // __cplusplus >= 201103L
1328
1329 template<typename _CharT, typename _OutIter>
1330 _OutIter
1331 time_put<_CharT, _OutIter>::
1332 put(iter_type __s, ios_base& __io, char_type __fill, const tm* __tm,
1333 const _CharT* __beg, const _CharT* __end) const
1334 {
1335 const locale& __loc = __io._M_getloc();
1336 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
1337 for (; __beg != __end; ++__beg)
1338 if (__ctype.narrow(*__beg, 0) != '%')
1339 {
1340 *__s = *__beg;
1341 ++__s;
1342 }
1343 else if (++__beg != __end)
1344 {
1345 char __format;
1346 char __mod = 0;
1347 const char __c = __ctype.narrow(*__beg, 0);
1348 if (__c != 'E' && __c != 'O')
1349 __format = __c;
1350 else if (++__beg != __end)
1351 {
1352 __mod = __c;
1353 __format = __ctype.narrow(*__beg, 0);
1354 }
1355 else
1356 break;
1357 __s = this->do_put(__s, __io, __fill, __tm, __format, __mod);
1358 }
1359 else
1360 break;
1361 return __s;
1362 }
1363
1364 template<typename _CharT, typename _OutIter>
1365 _OutIter
1366 time_put<_CharT, _OutIter>::
1367 do_put(iter_type __s, ios_base& __io, char_type, const tm* __tm,
1368 char __format, char __mod) const
1369 {
1370 const locale& __loc = __io._M_getloc();
1371 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
1372 __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc);
1373
1374 // NB: This size is arbitrary. Should this be a data member,
1375 // initialized at construction?
1376 const size_t __maxlen = 128;
1377 char_type __res[__maxlen];
1378
1379 // NB: In IEE 1003.1-200x, and perhaps other locale models, it
1380 // is possible that the format character will be longer than one
1381 // character. Possibilities include 'E' or 'O' followed by a
1382 // format character: if __mod is not the default argument, assume
1383 // it's a valid modifier.
1384 char_type __fmt[4];
1385 __fmt[0] = __ctype.widen('%');
1386 if (!__mod)
1387 {
1388 __fmt[1] = __format;
1389 __fmt[2] = char_type();
1390 }
1391 else
1392 {
1393 __fmt[1] = __mod;
1394 __fmt[2] = __format;
1395 __fmt[3] = char_type();
1396 }
1397
1398 __tp._M_put(__res, __maxlen, __fmt, __tm);
1399
1400 // Write resulting, fully-formatted string to output iterator.
1401 return std::__write(__s, __res, char_traits<char_type>::length(__res));
1402 }
1403
1404
1405 // Inhibit implicit instantiations for required instantiations,
1406 // which are defined via explicit instantiations elsewhere.
1407#if _GLIBCXX_EXTERN_TEMPLATE
1408 extern template class moneypunct<char, false>;
1409 extern template class moneypunct<char, true>;
1410 extern template class moneypunct_byname<char, false>;
1411 extern template class moneypunct_byname<char, true>;
1412 extern template class _GLIBCXX_NAMESPACE_LDBL_OR_CXX11 money_get<char>;
1413 extern template class _GLIBCXX_NAMESPACE_LDBL_OR_CXX11 money_put<char>;
1414 extern template class __timepunct<char>;
1415 extern template class time_put<char>;
1416 extern template class time_put_byname<char>;
1417 extern template class time_get<char>;
1418 extern template class time_get_byname<char>;
1419 extern template class messages<char>;
1420 extern template class messages_byname<char>;
1421
1422 extern template
1423 const moneypunct<char, true>&
1424 use_facet<moneypunct<char, true> >(const locale&);
1425
1426 extern template
1427 const moneypunct<char, false>&
1428 use_facet<moneypunct<char, false> >(const locale&);
1429
1430 extern template
1431 const money_put<char>&
1432 use_facet<money_put<char> >(const locale&);
1433
1434 extern template
1435 const money_get<char>&
1436 use_facet<money_get<char> >(const locale&);
1437
1438 extern template
1439 const __timepunct<char>&
1440 use_facet<__timepunct<char> >(const locale&);
1441
1442 extern template
1443 const time_put<char>&
1444 use_facet<time_put<char> >(const locale&);
1445
1446 extern template
1447 const time_get<char>&
1448 use_facet<time_get<char> >(const locale&);
1449
1450 extern template
1451 const messages<char>&
1452 use_facet<messages<char> >(const locale&);
1453
1454 extern template
1455 bool
1456 has_facet<moneypunct<char> >(const locale&);
1457
1458 extern template
1459 bool
1460 has_facet<money_put<char> >(const locale&);
1461
1462 extern template
1463 bool
1464 has_facet<money_get<char> >(const locale&);
1465
1466 extern template
1467 bool
1468 has_facet<__timepunct<char> >(const locale&);
1469
1470 extern template
1471 bool
1472 has_facet<time_put<char> >(const locale&);
1473
1474 extern template
1475 bool
1476 has_facet<time_get<char> >(const locale&);
1477
1478 extern template
1479 bool
1480 has_facet<messages<char> >(const locale&);
1481
1482#ifdef _GLIBCXX_USE_WCHAR_T
1483 extern template class moneypunct<wchar_t, false>;
1484 extern template class moneypunct<wchar_t, true>;
1485 extern template class moneypunct_byname<wchar_t, false>;
1486 extern template class moneypunct_byname<wchar_t, true>;
1487 extern template class _GLIBCXX_NAMESPACE_LDBL_OR_CXX11 money_get<wchar_t>;
1488 extern template class _GLIBCXX_NAMESPACE_LDBL_OR_CXX11 money_put<wchar_t>;
1489 extern template class __timepunct<wchar_t>;
1490 extern template class time_put<wchar_t>;
1491 extern template class time_put_byname<wchar_t>;
1492 extern template class time_get<wchar_t>;
1493 extern template class time_get_byname<wchar_t>;
1494 extern template class messages<wchar_t>;
1495 extern template class messages_byname<wchar_t>;
1496
1497 extern template
1498 const moneypunct<wchar_t, true>&
1499 use_facet<moneypunct<wchar_t, true> >(const locale&);
1500
1501 extern template
1502 const moneypunct<wchar_t, false>&
1503 use_facet<moneypunct<wchar_t, false> >(const locale&);
1504
1505 extern template
1506 const money_put<wchar_t>&
1507 use_facet<money_put<wchar_t> >(const locale&);
1508
1509 extern template
1510 const money_get<wchar_t>&
1511 use_facet<money_get<wchar_t> >(const locale&);
1512
1513 extern template
1514 const __timepunct<wchar_t>&
1515 use_facet<__timepunct<wchar_t> >(const locale&);
1516
1517 extern template
1518 const time_put<wchar_t>&
1519 use_facet<time_put<wchar_t> >(const locale&);
1520
1521 extern template
1522 const time_get<wchar_t>&
1523 use_facet<time_get<wchar_t> >(const locale&);
1524
1525 extern template
1526 const messages<wchar_t>&
1527 use_facet<messages<wchar_t> >(const locale&);
1528
1529 extern template
1530 bool
1531 has_facet<moneypunct<wchar_t> >(const locale&);
1532
1533 extern template
1534 bool
1535 has_facet<money_put<wchar_t> >(const locale&);
1536
1537 extern template
1538 bool
1539 has_facet<money_get<wchar_t> >(const locale&);
1540
1541 extern template
1542 bool
1543 has_facet<__timepunct<wchar_t> >(const locale&);
1544
1545 extern template
1546 bool
1547 has_facet<time_put<wchar_t> >(const locale&);
1548
1549 extern template
1550 bool
1551 has_facet<time_get<wchar_t> >(const locale&);
1552
1553 extern template
1554 bool
1555 has_facet<messages<wchar_t> >(const locale&);
1556#endif
1557#endif
1558
1559_GLIBCXX_END_NAMESPACE_VERSION
1560} // namespace std
1561
1562#endif
1563

source code of include/c++/11/bits/locale_facets_nonio.tcc