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