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