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