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