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