]> git.ipfire.org Git - thirdparty/gcc.git/blame - libstdc++-v3/include/bits/locale_facets.tcc
config.gcc (mips64orion-*-elf*, [...]): Delete duplicated line.
[thirdparty/gcc.git] / libstdc++-v3 / include / bits / locale_facets.tcc
CommitLineData
725dc051
BK
1// Locale support -*- C++ -*-
2
47f62b27 3// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
4b9aaf63 4// Free Software Foundation, Inc.
725dc051
BK
5//
6// This file is part of the GNU ISO C++ Library. This library is free
7// software; you can redistribute it and/or modify it under the
8// terms of the GNU General Public License as published by the
9// Free Software Foundation; either version 2, or (at your option)
10// any later version.
11
12// This library is distributed in the hope that it will be useful,
13// but WITHOUT ANY WARRANTY; without even the implied warranty of
14// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15// GNU General Public License for more details.
16
17// You should have received a copy of the GNU General Public License along
18// with this library; see the file COPYING. If not, write to the Free
19// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
20// USA.
21
22// As a special exception, you may use this file as part of a free software
23// library without restriction. Specifically, if other files instantiate
24// templates or use macros or inline functions from this file, or you compile
25// this file and link it with other files to produce an executable, this
26// file does not by itself cause the resulting executable to be covered by
27// the GNU General Public License. This exception does not however
28// invalidate any other reasons why the executable file might be covered by
29// the GNU General Public License.
30
5b1a7610 31// Warning: this file is not meant for user inclusion. Use <locale>.
725dc051 32
3d7c150e
BK
33#ifndef _LOCALE_FACETS_TCC
34#define _LOCALE_FACETS_TCC 1
725dc051 35
3b794528
BK
36#pragma GCC system_header
37
ed6814f7
BI
38#include <limits> // For numeric_limits
39#include <typeinfo> // For bad_cast.
4b9aaf63 40#include <bits/streambuf_iterator.h>
725dc051
BK
41
42namespace std
43{
44 template<typename _Facet>
45 locale
ba317c52 46 locale::combine(const locale& __other) const
725dc051 47 {
1f46fc8e 48 _Impl* __tmp = new _Impl(*_M_impl, 1);
155f6fbb
PC
49 try
50 {
51 __tmp->_M_replace_facet(__other._M_impl, &_Facet::id);
52 }
53 catch(...)
54 {
55 __tmp->_M_remove_reference();
56 __throw_exception_again;
57 }
13f83598 58 return locale(__tmp);
725dc051
BK
59 }
60
61 template<typename _CharT, typename _Traits, typename _Alloc>
62 bool
63 locale::operator()(const basic_string<_CharT, _Traits, _Alloc>& __s1,
64 const basic_string<_CharT, _Traits, _Alloc>& __s2) const
65 {
725dc051 66 typedef std::collate<_CharT> __collate_type;
86ade44c
BK
67 const __collate_type& __collate = use_facet<__collate_type>(*this);
68 return (__collate.compare(__s1.data(), __s1.data() + __s1.length(),
69 __s2.data(), __s2.data() + __s2.length()) < 0);
725dc051
BK
70 }
71
3101fa3c
JQ
72 /**
73 * @brief Test for the presence of a facet.
74 *
75 * has_facet tests the locale argument for the presence of the facet type
76 * provided as the template parameter. Facets derived from the facet
77 * parameter will also return true.
78 *
79 * @param Facet The facet type to test the presence of.
80 * @param locale The locale to test.
81 * @return true if locale contains a facet of type Facet, else false.
82 * @throw std::bad_cast if locale doesn't contain the facet.
83 */
725dc051 84 template<typename _Facet>
0cd1de6f
BK
85 inline bool
86 has_facet(const locale& __loc) throw()
725dc051 87 {
905df1fb 88 const size_t __i = _Facet::id._M_id();
064994a3 89 const locale::facet** __facets = __loc._M_impl->_M_facets;
0cd1de6f 90 return (__i < __loc._M_impl->_M_facets_size && __facets[__i]);
725dc051
BK
91 }
92
3101fa3c
JQ
93 /**
94 * @brief Return a facet.
95 *
96 * use_facet looks for and returns a reference to a facet of type Facet
97 * where Facet is the template parameter. If has_facet(locale) is true,
98 * there is a suitable facet to return. It throws std::bad_cast if the
99 * locale doesn't contain a facet of type Facet.
100 *
101 * @param Facet The facet type to access.
102 * @param locale The locale to use.
103 * @return Reference to facet of type Facet.
104 * @throw std::bad_cast if locale doesn't contain a facet of type Facet.
105 */
725dc051 106 template<typename _Facet>
0cd1de6f
BK
107 inline const _Facet&
108 use_facet(const locale& __loc)
725dc051 109 {
905df1fb 110 const size_t __i = _Facet::id._M_id();
064994a3 111 const locale::facet** __facets = __loc._M_impl->_M_facets;
0cd1de6f
BK
112 if (!(__i < __loc._M_impl->_M_facets_size && __facets[__i]))
113 __throw_bad_cast();
114 return static_cast<const _Facet&>(*__facets[__i]);
725dc051
BK
115 }
116
215f9e28
BK
117 // Routine to access a cache for the facet. If the cache didn't
118 // exist before, it gets constructed on the fly.
119 template<typename _Facet>
cde63840
BK
120 struct __use_cache
121 {
122 const _Facet*
123 operator() (const locale& __loc) const;
124 };
215f9e28 125
cde63840
BK
126 template<typename _CharT>
127 struct __use_cache<__numpunct_cache<_CharT> >
128 {
129 const __numpunct_cache<_CharT>*
130 operator() (const locale& __loc) const
131 {
905df1fb 132 const size_t __i = numpunct<_CharT>::id._M_id();
cde63840
BK
133 const locale::facet** __caches = __loc._M_impl->_M_caches;
134 if (!__caches[__i])
135 {
11f10e6b 136 __numpunct_cache<_CharT>* __tmp = NULL;
cde63840
BK
137 try
138 {
139 __tmp = new __numpunct_cache<_CharT>;
140 __tmp->_M_cache(__loc);
141 }
142 catch(...)
143 {
144 delete __tmp;
145 __throw_exception_again;
146 }
147 __loc._M_impl->_M_install_cache(__tmp, __i);
148 }
149 return static_cast<const __numpunct_cache<_CharT>*>(__caches[__i]);
150 }
151 };
725dc051 152
47f62b27
PC
153 // Used by both numeric and monetary facets.
154 // Check to make sure that the __grouping_tmp string constructed in
155 // money_get or num_get matches the canonical grouping for a given
156 // locale.
157 // __grouping_tmp is parsed L to R
158 // 1,222,444 == __grouping_tmp of "\1\3\3"
159 // __grouping is parsed R to L
160 // 1,222,444 == __grouping of "\3" == "\3\3\3"
161 static bool
162 __verify_grouping(const char* __grouping, size_t __grouping_size,
163 const string& __grouping_tmp);
164
1ab65677 165 template<typename _CharT, typename _InIter>
631ba05e 166 _InIter
1ab65677 167 num_get<_CharT, _InIter>::
86ade44c 168 _M_extract_float(_InIter __beg, _InIter __end, ios_base& __io,
823b4f7d 169 ios_base::iostate& __err, string& __xtrc) const
725dc051 170 {
7942afdc 171 typedef char_traits<_CharT> __traits_type;
ed6814f7 172 typedef typename numpunct<_CharT>::__cache_type __cache_type;
7942afdc
BK
173 __use_cache<__cache_type> __uc;
174 const locale& __loc = __io._M_getloc();
175 const __cache_type* __lc = __uc(__loc);
176 const _CharT* __lit = __lc->_M_atoms_in;
86ade44c 177
a827daa0
PC
178 // True if a mantissa is found.
179 bool __found_mantissa = false;
180
4b9aaf63 181 // First check for sign.
f20d2b78 182 if (__beg != __end)
86ade44c 183 {
f20d2b78
PC
184 const char_type __c = *__beg;
185 const bool __plus = __traits_type::eq(__c, __lit[_S_iplus]);
a827daa0 186 if ((__plus || __traits_type::eq(__c, __lit[_S_iminus]))
a827daa0 187 && (!__lc->_M_use_grouping
08ff96c3
PC
188 || !__traits_type::eq(__c, __lc->_M_thousands_sep))
189 && !__traits_type::eq(__c, __lc->_M_decimal_point))
f20d2b78 190 {
0e1b98cc 191 __xtrc += __plus ? '+' : '-';
f20d2b78
PC
192 ++__beg;
193 }
86ade44c 194 }
ed6814f7 195
a827daa0
PC
196 // Next, look for leading zeros.
197 while (__beg != __end)
823b4f7d 198 {
a827daa0 199 const char_type __c = *__beg;
08ff96c3
PC
200 if (__lc->_M_use_grouping
201 && __traits_type::eq(__c, __lc->_M_thousands_sep)
202 || __traits_type::eq(__c, __lc->_M_decimal_point))
a827daa0
PC
203 break;
204 else if (__traits_type::eq(__c, __lit[_S_izero]))
205 {
206 if (!__found_mantissa)
207 {
0e1b98cc 208 __xtrc += '0';
a827daa0
PC
209 __found_mantissa = true;
210 }
211 ++__beg;
212 }
213 else
214 break;
823b4f7d 215 }
86ade44c
BK
216
217 // Only need acceptable digits for floating point numbers.
86ade44c
BK
218 bool __found_dec = false;
219 bool __found_sci = false;
86ade44c 220 string __found_grouping;
a8ea7389
PC
221 if (__lc->_M_use_grouping)
222 __found_grouping.reserve(32);
86ade44c 223 int __sep_pos = 0;
0e1b98cc 224 const char_type* __lit_zero = __lit + _S_izero;
a8ea7389 225 const char_type* __q;
58c9703f 226 while (__beg != __end)
86ade44c 227 {
4f0c9c8a
PC
228 // According to 22.2.2.1.2, p8-9, first look for thousands_sep
229 // and decimal_point.
f20d2b78 230 const char_type __c = *__beg;
4f0c9c8a
PC
231 if (__lc->_M_use_grouping
232 && __traits_type::eq(__c, __lc->_M_thousands_sep))
86ade44c 233 {
4f0c9c8a 234 if (!__found_dec && !__found_sci)
86ade44c 235 {
4f0c9c8a
PC
236 // NB: Thousands separator at the beginning of a string
237 // is a no-no, as is two consecutive thousands separators.
238 if (__sep_pos)
239 {
240 __found_grouping += static_cast<char>(__sep_pos);
241 __sep_pos = 0;
242 ++__beg;
243 }
244 else
245 {
246 __err |= ios_base::failbit;
247 break;
248 }
86ade44c 249 }
4f0c9c8a
PC
250 else
251 break;
86ade44c 252 }
4f0c9c8a
PC
253 else if (__traits_type::eq(__c, __lc->_M_decimal_point))
254 {
255 if (!__found_dec && !__found_sci)
256 {
257 // If no grouping chars are seen, no grouping check
258 // is applied. Therefore __found_grouping is adjusted
259 // only if decimal_point comes after some thousands_sep.
260 if (__found_grouping.size())
261 __found_grouping += static_cast<char>(__sep_pos);
262 __xtrc += '.';
263 __found_dec = true;
264 ++__beg;
265 }
266 else
267 break;
268 }
0e1b98cc 269 else if (__q = __traits_type::find(__lit_zero, 10, __c))
86ade44c 270 {
a8ea7389 271 __xtrc += _S_atoms_in[__q - __lit];
cc16f8b9
PC
272 __found_mantissa = true;
273 ++__sep_pos;
58c9703f 274 ++__beg;
86ade44c 275 }
08ff96c3 276 else if ((__traits_type::eq(__c, __lit[_S_ie])
ed6814f7 277 || __traits_type::eq(__c, __lit[_S_iE]))
f20d2b78 278 && __found_mantissa && !__found_sci)
86ade44c
BK
279 {
280 // Scientific notation.
0e1b98cc
PC
281 if (__found_grouping.size() && !__found_dec)
282 __found_grouping += static_cast<char>(__sep_pos);
08ff96c3 283 __xtrc += 'e';
58c9703f
PC
284 __found_sci = true;
285
86ade44c 286 // Remove optional plus or minus sign, if they exist.
6bf0b59c 287 if (++__beg != __end)
86ade44c 288 {
a8ea7389
PC
289 const bool __plus = __traits_type::eq(*__beg,
290 __lit[_S_iplus]);
08ff96c3
PC
291 if ((__plus || __traits_type::eq(*__beg, __lit[_S_iminus]))
292 && (!__lc->_M_use_grouping
293 || !__traits_type::eq(*__beg, __lc->_M_thousands_sep))
294 && !__traits_type::eq(*__beg, __lc->_M_decimal_point))
58c9703f 295 {
0e1b98cc 296 __xtrc += __plus ? '+' : '-';
58c9703f
PC
297 ++__beg;
298 }
86ade44c 299 }
86ade44c
BK
300 }
301 else
302 // Not a valid input item.
303 break;
304 }
305
306 // Digit grouping is checked. If grouping and found_grouping don't
307 // match, then get very very upset, and set failbit.
6d4925e3 308 if (__found_grouping.size())
86ade44c 309 {
0e1b98cc
PC
310 // Add the ending grouping if a decimal or 'e'/'E' wasn't found.
311 if (!__found_dec && !__found_sci)
86ade44c 312 __found_grouping += static_cast<char>(__sep_pos);
7942afdc 313
47f62b27
PC
314 if (!std::__verify_grouping(__lc->_M_grouping, __lc->_M_grouping_size,
315 __found_grouping))
823b4f7d 316 __err |= ios_base::failbit;
86ade44c
BK
317 }
318
7942afdc 319 // Finish up.
86ade44c
BK
320 if (__beg == __end)
321 __err |= ios_base::eofbit;
631ba05e 322 return __beg;
725dc051
BK
323 }
324
86ade44c 325 template<typename _CharT, typename _InIter>
ed6814f7 326 template<typename _ValueT>
0fa96a60
PC
327 _InIter
328 num_get<_CharT, _InIter>::
329 _M_extract_int(_InIter __beg, _InIter __end, ios_base& __io,
330 ios_base::iostate& __err, _ValueT& __v) const
331 {
332 typedef char_traits<_CharT> __traits_type;
ed6814f7 333 typedef typename numpunct<_CharT>::__cache_type __cache_type;
0fa96a60
PC
334 __use_cache<__cache_type> __uc;
335 const locale& __loc = __io._M_getloc();
336 const __cache_type* __lc = __uc(__loc);
337 const _CharT* __lit = __lc->_M_atoms_in;
86ade44c 338
0fa96a60 339 // NB: Iff __basefield == 0, __base can change based on contents.
a8ea7389
PC
340 const ios_base::fmtflags __basefield = __io.flags()
341 & ios_base::basefield;
0fa96a60
PC
342 const bool __oct = __basefield == ios_base::oct;
343 int __base = __oct ? 8 : (__basefield == ios_base::hex ? 16 : 10);
86ade44c 344
0fa96a60
PC
345 // True if numeric digits are found.
346 bool __found_num = false;
347
348 // First check for sign.
349 bool __negative = false;
350 if (__beg != __end)
ed6814f7 351 {
a827daa0 352 const char_type __c = *__beg;
1f3adac2 353 if (numeric_limits<_ValueT>::is_signed)
a827daa0
PC
354 __negative = __traits_type::eq(__c, __lit[_S_iminus]);
355 if ((__negative || __traits_type::eq(__c, __lit[_S_iplus]))
a827daa0 356 && (!__lc->_M_use_grouping
08ff96c3
PC
357 || !__traits_type::eq(__c, __lc->_M_thousands_sep))
358 && !__traits_type::eq(__c, __lc->_M_decimal_point))
f20d2b78 359 ++__beg;
0fa96a60 360 }
86ade44c 361
0fa96a60
PC
362 // Next, look for leading zeros and check required digits
363 // for base formats.
a827daa0 364 while (__beg != __end)
0fa96a60 365 {
a827daa0 366 const char_type __c = *__beg;
08ff96c3
PC
367 if (__lc->_M_use_grouping
368 && __traits_type::eq(__c, __lc->_M_thousands_sep)
369 || __traits_type::eq(__c, __lc->_M_decimal_point))
a827daa0
PC
370 break;
371 else if (__traits_type::eq(__c, __lit[_S_izero])
372 && (!__found_num || __base == 10))
0fa96a60 373 {
a827daa0
PC
374 __found_num = true;
375 ++__beg;
0fa96a60 376 }
a827daa0 377 else if (__found_num)
0fa96a60 378 {
a827daa0
PC
379 if (__traits_type::eq(__c, __lit[_S_ix])
380 || __traits_type::eq(__c, __lit[_S_iX]))
0fa96a60 381 {
a827daa0
PC
382 if (__basefield == 0)
383 __base = 16;
384 if (__base == 16)
385 {
386 __found_num = false;
387 ++__beg;
388 }
0fa96a60 389 }
a827daa0
PC
390 else if (__basefield == 0)
391 __base = 8;
392 break;
0fa96a60 393 }
a827daa0
PC
394 else
395 break;
0fa96a60 396 }
86ade44c 397
0fa96a60
PC
398 // At this point, base is determined. If not hex, only allow
399 // base digits as valid input.
212063a8 400 const size_t __len = __base == 16 ? _S_iend - _S_izero : __base;
0fa96a60
PC
401
402 // Extract.
403 string __found_grouping;
a8ea7389
PC
404 if (__lc->_M_use_grouping)
405 __found_grouping.reserve(32);
0fa96a60
PC
406 int __sep_pos = 0;
407 bool __overflow = false;
408 _ValueT __result = 0;
409 const char_type* __lit_zero = __lit + _S_izero;
a8ea7389 410 const char_type* __q;
0fa96a60
PC
411 if (__negative)
412 {
413 const _ValueT __min = numeric_limits<_ValueT>::min() / __base;
414 for (; __beg != __end; ++__beg)
415 {
4f0c9c8a
PC
416 // According to 22.2.2.1.2, p8-9, first look for thousands_sep
417 // and decimal_point.
418 const char_type __c = *__beg;
419 if (__lc->_M_use_grouping
420 && __traits_type::eq(__c, __lc->_M_thousands_sep))
cc16f8b9
PC
421 {
422 // NB: Thousands separator at the beginning of a string
423 // is a no-no, as is two consecutive thousands separators.
424 if (__sep_pos)
425 {
426 __found_grouping += static_cast<char>(__sep_pos);
427 __sep_pos = 0;
428 }
429 else
430 {
431 __err |= ios_base::failbit;
432 break;
433 }
434 }
4f0c9c8a
PC
435 else if (__traits_type::eq(__c, __lc->_M_decimal_point))
436 break;
a8ea7389 437 else if (__q = __traits_type::find(__lit_zero, __len, __c))
0fa96a60 438 {
a8ea7389 439 int __digit = __q - __lit_zero;
0fa96a60
PC
440 if (__digit > 15)
441 __digit -= 6;
442 if (__result < __min)
443 __overflow = true;
444 else
445 {
a8ea7389
PC
446 const _ValueT __new_result = __result * __base
447 - __digit;
1f3adac2 448 __overflow |= __new_result > __result;
0fa96a60
PC
449 __result = __new_result;
450 ++__sep_pos;
451 __found_num = true;
452 }
453 }
cc16f8b9
PC
454 else
455 // Not a valid input item.
456 break;
457 }
458 }
459 else
460 {
461 const _ValueT __max = numeric_limits<_ValueT>::max() / __base;
462 for (; __beg != __end; ++__beg)
463 {
4f0c9c8a
PC
464 const char_type __c = *__beg;
465 if (__lc->_M_use_grouping
466 && __traits_type::eq(__c, __lc->_M_thousands_sep))
0fa96a60 467 {
0fa96a60
PC
468 if (__sep_pos)
469 {
470 __found_grouping += static_cast<char>(__sep_pos);
471 __sep_pos = 0;
472 }
473 else
474 {
475 __err |= ios_base::failbit;
476 break;
477 }
ed6814f7 478 }
4f0c9c8a
PC
479 else if (__traits_type::eq(__c, __lc->_M_decimal_point))
480 break;
a8ea7389 481 else if (__q = __traits_type::find(__lit_zero, __len, __c))
0fa96a60 482 {
a8ea7389 483 int __digit = __q - __lit_zero;
0fa96a60
PC
484 if (__digit > 15)
485 __digit -= 6;
486 if (__result > __max)
487 __overflow = true;
488 else
489 {
a8ea7389
PC
490 const _ValueT __new_result = __result * __base
491 + __digit;
1f3adac2 492 __overflow |= __new_result < __result;
0fa96a60
PC
493 __result = __new_result;
494 ++__sep_pos;
495 __found_num = true;
496 }
497 }
0fa96a60
PC
498 else
499 break;
500 }
501 }
86ade44c 502
0fa96a60
PC
503 // Digit grouping is checked. If grouping and found_grouping don't
504 // match, then get very very upset, and set failbit.
6d4925e3 505 if (__found_grouping.size())
0fa96a60
PC
506 {
507 // Add the ending grouping.
508 __found_grouping += static_cast<char>(__sep_pos);
ed6814f7 509
a8ea7389
PC
510 if (!std::__verify_grouping(__lc->_M_grouping,
511 __lc->_M_grouping_size,
47f62b27 512 __found_grouping))
0fa96a60
PC
513 __err |= ios_base::failbit;
514 }
7942afdc 515
1f3adac2
PC
516 if (!(__err & ios_base::failbit) && !__overflow
517 && __found_num)
0fa96a60
PC
518 __v = __result;
519 else
520 __err |= ios_base::failbit;
86ade44c 521
0fa96a60
PC
522 if (__beg == __end)
523 __err |= ios_base::eofbit;
524 return __beg;
525 }
1ab65677 526
f5677b15
PC
527 // _GLIBCXX_RESOLVE_LIB_DEFECTS
528 // 17. Bad bool parsing
1ab65677
BK
529 template<typename _CharT, typename _InIter>
530 _InIter
531 num_get<_CharT, _InIter>::
532 do_get(iter_type __beg, iter_type __end, ios_base& __io,
533 ios_base::iostate& __err, bool& __v) const
725dc051 534 {
1ab65677 535 if (!(__io.flags() & ios_base::boolalpha))
725dc051 536 {
0fa96a60 537 // Parse bool values as long.
1ab65677
BK
538 // NB: We can't just call do_get(long) here, as it might
539 // refer to a derived class.
0fa96a60
PC
540 long __l = -1;
541 __beg = _M_extract_int(__beg, __end, __io, __err, __l);
542 if (__l == 0 || __l == 1)
543 __v = __l;
544 else
1ab65677
BK
545 __err |= ios_base::failbit;
546 }
1ab65677 547 else
725dc051 548 {
7942afdc 549 // Parse bool values as alphanumeric.
0fa96a60
PC
550 typedef char_traits<_CharT> __traits_type;
551 typedef typename numpunct<_CharT>::__cache_type __cache_type;
7942afdc
BK
552 __use_cache<__cache_type> __uc;
553 const locale& __loc = __io._M_getloc();
554 const __cache_type* __lc = __uc(__loc);
86ade44c 555
ca13fb7f
PC
556 bool __testf = true;
557 bool __testt = true;
558 size_t __n;
559 for (__n = 0; __beg != __end; ++__n, ++__beg)
1ab65677 560 {
ca13fb7f 561 if (__testf)
47f62b27 562 if (__n < __lc->_M_falsename_size)
ca13fb7f
PC
563 __testf = __traits_type::eq(*__beg, __lc->_M_falsename[__n]);
564 else
565 break;
7942afdc 566
ca13fb7f 567 if (__testt)
47f62b27 568 if (__n < __lc->_M_truename_size)
ca13fb7f
PC
569 __testt = __traits_type::eq(*__beg, __lc->_M_truename[__n]);
570 else
571 break;
7942afdc 572
ca13fb7f 573 if (!__testf && !__testt)
ed6814f7 574 break;
1ab65677 575 }
47f62b27 576 if (__testf && __n == __lc->_M_falsename_size)
ca13fb7f 577 __v = 0;
47f62b27 578 else if (__testt && __n == __lc->_M_truename_size)
ca13fb7f
PC
579 __v = 1;
580 else
581 __err |= ios_base::failbit;
582
1ab65677
BK
583 if (__beg == __end)
584 __err |= ios_base::eofbit;
725dc051 585 }
1ab65677 586 return __beg;
725dc051
BK
587 }
588
1ab65677
BK
589 template<typename _CharT, typename _InIter>
590 _InIter
591 num_get<_CharT, _InIter>::
592 do_get(iter_type __beg, iter_type __end, ios_base& __io,
593 ios_base::iostate& __err, long& __v) const
0fa96a60 594 { return _M_extract_int(__beg, __end, __io, __err, __v); }
fb678854 595
1ab65677
BK
596 template<typename _CharT, typename _InIter>
597 _InIter
598 num_get<_CharT, _InIter>::
599 do_get(iter_type __beg, iter_type __end, ios_base& __io,
86ade44c 600 ios_base::iostate& __err, unsigned short& __v) const
ed6814f7 601 { return _M_extract_int(__beg, __end, __io, __err, __v); }
fb678854 602
1ab65677
BK
603 template<typename _CharT, typename _InIter>
604 _InIter
605 num_get<_CharT, _InIter>::
606 do_get(iter_type __beg, iter_type __end, ios_base& __io,
86ade44c 607 ios_base::iostate& __err, unsigned int& __v) const
0fa96a60 608 { return _M_extract_int(__beg, __end, __io, __err, __v); }
fb678854 609
1ab65677
BK
610 template<typename _CharT, typename _InIter>
611 _InIter
612 num_get<_CharT, _InIter>::
613 do_get(iter_type __beg, iter_type __end, ios_base& __io,
86ade44c 614 ios_base::iostate& __err, unsigned long& __v) const
0fa96a60 615 { return _M_extract_int(__beg, __end, __io, __err, __v); }
69971cd8 616
3d7c150e 617#ifdef _GLIBCXX_USE_LONG_LONG
1ab65677
BK
618 template<typename _CharT, typename _InIter>
619 _InIter
620 num_get<_CharT, _InIter>::
621 do_get(iter_type __beg, iter_type __end, ios_base& __io,
86ade44c 622 ios_base::iostate& __err, long long& __v) const
0fa96a60 623 { return _M_extract_int(__beg, __end, __io, __err, __v); }
69971cd8 624
1ab65677
BK
625 template<typename _CharT, typename _InIter>
626 _InIter
627 num_get<_CharT, _InIter>::
628 do_get(iter_type __beg, iter_type __end, ios_base& __io,
629 ios_base::iostate& __err, unsigned long long& __v) const
0fa96a60 630 { return _M_extract_int(__beg, __end, __io, __err, __v); }
1ab65677 631#endif
69971cd8 632
725dc051 633 template<typename _CharT, typename _InIter>
1ab65677 634 _InIter
725dc051 635 num_get<_CharT, _InIter>::
ed6814f7 636 do_get(iter_type __beg, iter_type __end, ios_base& __io,
86ade44c 637 ios_base::iostate& __err, float& __v) const
725dc051 638 {
823b4f7d
BK
639 string __xtrc;
640 __xtrc.reserve(32);
631ba05e 641 __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc);
0fa96a60 642 std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_get_c_locale());
1ab65677
BK
643 return __beg;
644 }
725dc051 645
725dc051
BK
646 template<typename _CharT, typename _InIter>
647 _InIter
648 num_get<_CharT, _InIter>::
649 do_get(iter_type __beg, iter_type __end, ios_base& __io,
1ab65677 650 ios_base::iostate& __err, double& __v) const
725dc051 651 {
823b4f7d
BK
652 string __xtrc;
653 __xtrc.reserve(32);
631ba05e 654 __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc);
8ae81136 655 std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_get_c_locale());
725dc051
BK
656 return __beg;
657 }
658
659 template<typename _CharT, typename _InIter>
660 _InIter
661 num_get<_CharT, _InIter>::
662 do_get(iter_type __beg, iter_type __end, ios_base& __io,
1ab65677 663 ios_base::iostate& __err, long double& __v) const
725dc051 664 {
823b4f7d
BK
665 string __xtrc;
666 __xtrc.reserve(32);
631ba05e 667 __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc);
8ae81136 668 std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_get_c_locale());
725dc051
BK
669 return __beg;
670 }
671
725dc051
BK
672 template<typename _CharT, typename _InIter>
673 _InIter
674 num_get<_CharT, _InIter>::
675 do_get(iter_type __beg, iter_type __end, ios_base& __io,
1ab65677 676 ios_base::iostate& __err, void*& __v) const
725dc051 677 {
7942afdc 678 // Prepare for hex formatted input.
1ab65677 679 typedef ios_base::fmtflags fmtflags;
905df1fb 680 const fmtflags __fmt = __io.flags();
d8ef7dec 681 __io.flags(__fmt & ~ios_base::basefield | ios_base::hex);
1ab65677 682
0fa96a60
PC
683 unsigned long __ul;
684 __beg = _M_extract_int(__beg, __end, __io, __err, __ul);
725dc051 685
7942afdc 686 // Reset from hex formatted input.
1ab65677 687 __io.flags(__fmt);
4b9aaf63 688
4b9aaf63
BK
689 if (!(__err & ios_base::failbit))
690 __v = reinterpret_cast<void*>(__ul);
ed6814f7 691 else
4b9aaf63 692 __err |= ios_base::failbit;
725dc051
BK
693 return __beg;
694 }
725dc051 695
ce3039af
JQ
696 // For use by integer and floating-point types after they have been
697 // converted into a char_type string.
698 template<typename _CharT, typename _OutIter>
699 void
700 num_put<_CharT, _OutIter>::
ed6814f7 701 _M_pad(_CharT __fill, streamsize __w, ios_base& __io,
ce3039af
JQ
702 _CharT* __new, const _CharT* __cs, int& __len) const
703 {
704 // [22.2.2.2.2] Stage 3.
705 // If necessary, pad.
ed6814f7 706 __pad<_CharT, char_traits<_CharT> >::_S_pad(__io, __fill, __new, __cs,
ce3039af
JQ
707 __w, __len, true);
708 __len = static_cast<int>(__w);
709 }
710
711 // Forwarding functions to peel signed from unsigned integer types.
712 template<typename _CharT>
713 inline int
3c21d6e0
PC
714 __int_to_char(_CharT* __bufend, long __v, const _CharT* __lit,
715 ios_base::fmtflags __flags)
ce3039af
JQ
716 {
717 unsigned long __ul = static_cast<unsigned long>(__v);
718 bool __neg = false;
ed6814f7 719 if (__v < 0)
ce3039af
JQ
720 {
721 __ul = -__ul;
722 __neg = true;
723 }
ed6814f7 724 return __int_to_char(__bufend, __ul, __lit, __flags, __neg);
ce3039af
JQ
725 }
726
727 template<typename _CharT>
728 inline int
3c21d6e0
PC
729 __int_to_char(_CharT* __bufend, unsigned long __v, const _CharT* __lit,
730 ios_base::fmtflags __flags)
731 { return __int_to_char(__bufend, __v, __lit, __flags, false); }
ce3039af 732
3d7c150e 733#ifdef _GLIBCXX_USE_LONG_LONG
ce3039af
JQ
734 template<typename _CharT>
735 inline int
3c21d6e0
PC
736 __int_to_char(_CharT* __bufend, long long __v, const _CharT* __lit,
737 ios_base::fmtflags __flags)
ed6814f7 738 {
ce3039af
JQ
739 unsigned long long __ull = static_cast<unsigned long long>(__v);
740 bool __neg = false;
ed6814f7 741 if (__v < 0)
ce3039af
JQ
742 {
743 __ull = -__ull;
744 __neg = true;
745 }
ed6814f7 746 return __int_to_char(__bufend, __ull, __lit, __flags, __neg);
ce3039af
JQ
747 }
748
749 template<typename _CharT>
750 inline int
3c21d6e0
PC
751 __int_to_char(_CharT* __bufend, unsigned long long __v, const _CharT* __lit,
752 ios_base::fmtflags __flags)
753 { return __int_to_char(__bufend, __v, __lit, __flags, false); }
ce3039af 754#endif
ed6814f7 755
ce3039af
JQ
756 template<typename _CharT, typename _ValueT>
757 int
3c21d6e0
PC
758 __int_to_char(_CharT* __bufend, _ValueT __v, const _CharT* __lit,
759 ios_base::fmtflags __flags, bool __neg)
ce3039af
JQ
760 {
761 // Don't write base if already 0.
762 const bool __showbase = (__flags & ios_base::showbase) && __v;
763 const ios_base::fmtflags __basefield = __flags & ios_base::basefield;
a761195b 764 _CharT* __buf = __bufend - 1;
ce3039af 765
d542f114
BK
766 if (__builtin_expect(__basefield != ios_base::oct &&
767 __basefield != ios_base::hex, true))
768 {
769 // Decimal.
ed6814f7 770 do
d542f114
BK
771 {
772 *__buf-- = __lit[(__v % 10) + __num_base::_S_odigits];
773 __v /= 10;
ed6814f7 774 }
d542f114
BK
775 while (__v != 0);
776 if (__neg)
777 *__buf-- = __lit[__num_base::_S_ominus];
778 else if (__flags & ios_base::showpos)
779 *__buf-- = __lit[__num_base::_S_oplus];
780 }
5b577977 781 else if (__basefield == ios_base::oct)
ce3039af
JQ
782 {
783 // Octal.
ed6814f7 784 do
ce3039af 785 {
655d7821 786 *__buf-- = __lit[(__v & 0x7) + __num_base::_S_odigits];
ce3039af 787 __v >>= 3;
ed6814f7 788 }
ce3039af
JQ
789 while (__v != 0);
790 if (__showbase)
655d7821 791 *__buf-- = __lit[__num_base::_S_odigits];
ce3039af 792 }
d542f114 793 else
ce3039af
JQ
794 {
795 // Hex.
796 const bool __uppercase = __flags & ios_base::uppercase;
ed6814f7 797 const int __case_offset = __uppercase ? __num_base::_S_oudigits
905df1fb 798 : __num_base::_S_odigits;
ed6814f7 799 do
ce3039af
JQ
800 {
801 *__buf-- = __lit[(__v & 0xf) + __case_offset];
802 __v >>= 4;
ed6814f7 803 }
ce3039af
JQ
804 while (__v != 0);
805 if (__showbase)
806 {
807 // 'x' or 'X'
655d7821 808 *__buf-- = __lit[__num_base::_S_ox + __uppercase];
ce3039af 809 // '0'
655d7821 810 *__buf-- = __lit[__num_base::_S_odigits];
ce3039af
JQ
811 }
812 }
a761195b 813 return __bufend - __buf - 1;
ce3039af
JQ
814 }
815
816 template<typename _CharT, typename _OutIter>
817 void
818 num_put<_CharT, _OutIter>::
47f62b27
PC
819 _M_group_int(const char* __grouping, size_t __grouping_size, _CharT __sep,
820 ios_base& __io, _CharT* __new, _CharT* __cs, int& __len) const
ce3039af 821 {
c2466393 822 // By itself __add_grouping cannot deal correctly with __cs when
ce3039af
JQ
823 // ios::showbase is set and ios_base::oct || ios_base::hex.
824 // Therefore we take care "by hand" of the initial 0, 0x or 0X.
825 // However, remember that the latter do not occur if the number
826 // printed is '0' (__len == 1).
827 streamsize __off = 0;
ed6814f7 828 const ios_base::fmtflags __basefield = __io.flags()
ce3039af
JQ
829 & ios_base::basefield;
830 if ((__io.flags() & ios_base::showbase) && __len > 1)
831 if (__basefield == ios_base::oct)
832 {
833 __off = 1;
5b577977 834 __new[0] = __cs[0];
ce3039af
JQ
835 }
836 else if (__basefield == ios_base::hex)
837 {
838 __off = 2;
5b577977
PC
839 __new[0] = __cs[0];
840 __new[1] = __cs[1];
ce3039af
JQ
841 }
842 _CharT* __p;
47f62b27
PC
843 __p = std::__add_grouping(__new + __off, __sep, __grouping,
844 __grouping_size, __cs + __off,
845 __cs + __len);
ce3039af
JQ
846 __len = __p - __new;
847 }
848
849 template<typename _CharT, typename _OutIter>
850 template<typename _ValueT>
851 _OutIter
852 num_put<_CharT, _OutIter>::
ed6814f7 853 _M_insert_int(_OutIter __s, ios_base& __io, _CharT __fill,
0fa96a60 854 _ValueT __v) const
ce3039af 855 {
7942afdc 856 typedef typename numpunct<_CharT>::__cache_type __cache_type;
cde63840 857 __use_cache<__cache_type> __uc;
215f9e28 858 const locale& __loc = __io._M_getloc();
cde63840
BK
859 const __cache_type* __lc = __uc(__loc);
860 const _CharT* __lit = __lc->_M_atoms_out;
ce3039af 861
ed6814f7 862 // Long enough to hold hex, dec, and octal representations.
a761195b 863 const int __ilen = 4 * sizeof(_ValueT);
ed6814f7 864 _CharT* __cs = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
ce3039af 865 * __ilen));
a761195b 866
ce3039af
JQ
867 // [22.2.2.2.2] Stage 1, numeric conversion to character.
868 // Result is returned right-justified in the buffer.
869 int __len;
3c21d6e0 870 __len = __int_to_char(__cs + __ilen, __v, __lit, __io.flags());
a761195b 871 __cs += __ilen - __len;
ed6814f7
BI
872
873 // Add grouping, if necessary.
cde63840 874 if (__lc->_M_use_grouping)
ce3039af
JQ
875 {
876 // Grouping can add (almost) as many separators as the
877 // number of digits, but no more.
ed6814f7 878 _CharT* __cs2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
f6a7db9e 879 * __len * 2));
47f62b27
PC
880 _M_group_int(__lc->_M_grouping, __lc->_M_grouping_size,
881 __lc->_M_thousands_sep, __io, __cs2, __cs, __len);
ce3039af
JQ
882 __cs = __cs2;
883 }
ed6814f7 884
ce3039af 885 // Pad.
905df1fb 886 const streamsize __w = __io.width();
ce3039af
JQ
887 if (__w > static_cast<streamsize>(__len))
888 {
ed6814f7 889 _CharT* __cs3 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
f6a7db9e 890 * __w));
ce3039af
JQ
891 _M_pad(__fill, __w, __io, __cs3, __cs, __len);
892 __cs = __cs3;
893 }
894 __io.width(0);
895
896 // [22.2.2.2.2] Stage 4.
897 // Write resulting, fully-formatted string to output iterator.
391cfc46 898 return std::__write(__s, __cs, __len);
ed6814f7 899 }
ce3039af
JQ
900
901 template<typename _CharT, typename _OutIter>
902 void
903 num_put<_CharT, _OutIter>::
a8ea7389
PC
904 _M_group_float(const char* __grouping, size_t __grouping_size,
905 _CharT __sep, const _CharT* __p, _CharT* __new,
906 _CharT* __cs, int& __len) const
ce3039af 907 {
f5677b15
PC
908 // _GLIBCXX_RESOLVE_LIB_DEFECTS
909 // 282. What types does numpunct grouping refer to?
ed6814f7 910 // Add grouping, if necessary.
ce3039af 911 _CharT* __p2;
a761195b 912 const int __declen = __p ? __p - __cs : __len;
47f62b27 913 __p2 = std::__add_grouping(__new, __sep, __grouping, __grouping_size,
391cfc46 914 __cs, __cs + __declen);
ed6814f7 915
ce3039af
JQ
916 // Tack on decimal part.
917 int __newlen = __p2 - __new;
918 if (__p)
919 {
920 char_traits<_CharT>::copy(__p2, __p, __len - __declen);
921 __newlen += __len - __declen;
ed6814f7 922 }
ce3039af 923 __len = __newlen;
ce3039af
JQ
924 }
925
926 // The following code uses snprintf (or sprintf(), when
3d7c150e 927 // _GLIBCXX_USE_C99 is not defined) to convert floating point values
ce3039af
JQ
928 // for insertion into a stream. An optimization would be to replace
929 // them with code that works directly on a wide buffer and then use
930 // __pad to do the padding. It would be good to replace them anyway
931 // to gain back the efficiency that C++ provides by knowing up front
932 // the type of the values to insert. Also, sprintf is dangerous
933 // since may lead to accidental buffer overruns. This
934 // implementation follows the C++ standard fairly directly as
6d8e16a4 935 // outlined in 22.2.2.2 [lib.locale.num.put]
1ab65677 936 template<typename _CharT, typename _OutIter>
86ade44c
BK
937 template<typename _ValueT>
938 _OutIter
939 num_put<_CharT, _OutIter>::
7942afdc 940 _M_insert_float(_OutIter __s, ios_base& __io, _CharT __fill, char __mod,
86ade44c
BK
941 _ValueT __v) const
942 {
7942afdc
BK
943 typedef typename numpunct<_CharT>::__cache_type __cache_type;
944 __use_cache<__cache_type> __uc;
945 const locale& __loc = __io._M_getloc();
946 const __cache_type* __lc = __uc(__loc);
947
ce3039af
JQ
948 // Note: digits10 is rounded down: add 1 to ensure the maximum
949 // available precision. Then, in general, one more 1 needs to
950 // be added since, when the %{g,G} conversion specifiers are
951 // chosen inside _S_format_float, the precision field is "the
952 // maximum number of significant digits", *not* the "number of
953 // digits to appear after the decimal point", as happens for
954 // %{e,E,f,F} (C99, 7.19.6.1,4).
87117aa2 955 const int __max_digits = numeric_limits<_ValueT>::digits10 + 2;
6d8e16a4 956
ce3039af
JQ
957 // Use default precision if out of range.
958 streamsize __prec = __io.precision();
0228de0c
BK
959 if (__prec > static_cast<streamsize>(__max_digits))
960 __prec = static_cast<streamsize>(__max_digits);
5dc91152 961 else if (__prec < static_cast<streamsize>(0))
5dc91152 962 __prec = static_cast<streamsize>(6);
86ade44c 963
ce3039af
JQ
964 // [22.2.2.2.2] Stage 1, numeric conversion to character.
965 int __len;
86ade44c
BK
966 // Long enough for the max format spec.
967 char __fbuf[16];
0228de0c 968
3d7c150e 969#ifdef _GLIBCXX_USE_C99
ce3039af
JQ
970 // First try a buffer perhaps big enough (for sure sufficient
971 // for non-ios_base::fixed outputs)
6d8e16a4
PC
972 int __cs_size = __max_digits * 3;
973 char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
974
5dc91152 975 _S_format_float(__io, __fbuf, __mod);
391cfc46 976 __len = std::__convert_from_v(__cs, __cs_size, __fbuf, __v,
8ae81136 977 _S_get_c_locale(), __prec);
6d8e16a4
PC
978
979 // If the buffer was not large enough, try again with the correct size.
980 if (__len >= __cs_size)
981 {
ed6814f7 982 __cs_size = __len + 1;
6d8e16a4 983 __cs = static_cast<char*>(__builtin_alloca(__cs_size));
391cfc46 984 __len = std::__convert_from_v(__cs, __cs_size, __fbuf, __v,
8ae81136 985 _S_get_c_locale(), __prec);
6d8e16a4
PC
986 }
987#else
0228de0c
BK
988 // Consider the possibility of long ios_base::fixed outputs
989 const bool __fixed = __io.flags() & ios_base::fixed;
990 const int __max_exp = numeric_limits<_ValueT>::max_exponent10;
ce3039af 991
7942afdc 992 // The size of the output string is computed as follows.
46d36062
PC
993 // ios_base::fixed outputs may need up to __max_exp+1 chars
994 // for the integer part + up to __max_digits chars for the
995 // fractional part + 3 chars for sign, decimal point, '\0'. On
996 // the other hand, for non-fixed outputs __max_digits*3 chars
997 // are largely sufficient.
ed6814f7 998 const int __cs_size = __fixed ? __max_exp + __max_digits + 4
46d36062 999 : __max_digits * 3;
0228de0c
BK
1000 char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
1001
5dc91152 1002 _S_format_float(__io, __fbuf, __mod);
ed6814f7 1003 __len = std::__convert_from_v(__cs, 0, __fbuf, __v,
8ae81136 1004 _S_get_c_locale(), __prec);
6d8e16a4 1005#endif
725dc051 1006
86ade44c
BK
1007 // [22.2.2.2.2] Stage 2, convert to char_type, using correct
1008 // numpunct.decimal_point() values for '.' and adding grouping.
86ade44c 1009 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
ce3039af 1010
ed6814f7 1011 _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
0228de0c 1012 * __len));
86ade44c 1013 __ctype.widen(__cs, __cs + __len, __ws);
ed6814f7 1014
86ade44c 1015 // Replace decimal point.
ce3039af 1016 const _CharT __cdec = __ctype.widen('.');
cde63840 1017 const _CharT __dec = __lc->_M_decimal_point;
86ade44c 1018 const _CharT* __p;
ce3039af
JQ
1019 if (__p = char_traits<_CharT>::find(__ws, __len, __cdec))
1020 __ws[__p - __ws] = __dec;
86ade44c 1021
ed6814f7 1022 // Add grouping, if necessary.
cde63840 1023 if (__lc->_M_use_grouping)
86ade44c 1024 {
5b577977
PC
1025 // Grouping can add (almost) as many separators as the
1026 // number of digits, but no more.
ed6814f7 1027 _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
f6a7db9e 1028 * __len * 2));
47f62b27
PC
1029 _M_group_float(__lc->_M_grouping, __lc->_M_grouping_size,
1030 __lc->_M_thousands_sep, __p, __ws2, __ws, __len);
5b577977 1031 __ws = __ws2;
86ade44c 1032 }
725dc051 1033
ce3039af 1034 // Pad.
905df1fb 1035 const streamsize __w = __io.width();
86ade44c
BK
1036 if (__w > static_cast<streamsize>(__len))
1037 {
f6a7db9e
PC
1038 _CharT* __ws3 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
1039 * __w));
ce3039af
JQ
1040 _M_pad(__fill, __w, __io, __ws3, __ws, __len);
1041 __ws = __ws3;
86ade44c
BK
1042 }
1043 __io.width(0);
ed6814f7 1044
86ade44c
BK
1045 // [22.2.2.2.2] Stage 4.
1046 // Write resulting, fully-formatted string to output iterator.
391cfc46 1047 return std::__write(__s, __ws, __len);
ce3039af 1048 }
725dc051 1049
fb678854 1050 template<typename _CharT, typename _OutIter>
725dc051
BK
1051 _OutIter
1052 num_put<_CharT, _OutIter>::
1053 do_put(iter_type __s, ios_base& __io, char_type __fill, bool __v) const
1054 {
905df1fb 1055 const ios_base::fmtflags __flags = __io.flags();
725dc051
BK
1056 if ((__flags & ios_base::boolalpha) == 0)
1057 {
1058 unsigned long __uv = __v;
7942afdc 1059 __s = _M_insert_int(__s, __io, __fill, __uv);
725dc051
BK
1060 }
1061 else
1062 {
7942afdc 1063 typedef typename numpunct<_CharT>::__cache_type __cache_type;
cde63840 1064 __use_cache<__cache_type> __uc;
215f9e28 1065 const locale& __loc = __io._M_getloc();
cde63840 1066 const __cache_type* __lc = __uc(__loc);
215f9e28 1067
ed6814f7 1068 const _CharT* __name = __v ? __lc->_M_truename
6c39c207 1069 : __lc->_M_falsename;
47f62b27
PC
1070 int __len = __v ? __lc->_M_truename_size
1071 : __lc->_M_falsename_size;
ce3039af 1072
905df1fb 1073 const streamsize __w = __io.width();
ce3039af
JQ
1074 if (__w > static_cast<streamsize>(__len))
1075 {
a8ea7389
PC
1076 _CharT* __cs
1077 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
1078 * __w));
7942afdc
BK
1079 _M_pad(__fill, __w, __io, __cs, __name, __len);
1080 __name = __cs;
ce3039af
JQ
1081 }
1082 __io.width(0);
7942afdc 1083 __s = std::__write(__s, __name, __len);
86ade44c
BK
1084 }
1085 return __s;
1ab65677
BK
1086 }
1087
1088 template<typename _CharT, typename _OutIter>
1089 _OutIter
1090 num_put<_CharT, _OutIter>::
1091 do_put(iter_type __s, ios_base& __io, char_type __fill, long __v) const
7942afdc 1092 { return _M_insert_int(__s, __io, __fill, __v); }
1ab65677
BK
1093
1094 template<typename _CharT, typename _OutIter>
1095 _OutIter
1096 num_put<_CharT, _OutIter>::
1097 do_put(iter_type __s, ios_base& __io, char_type __fill,
1098 unsigned long __v) const
7942afdc 1099 { return _M_insert_int(__s, __io, __fill, __v); }
1ab65677 1100
3d7c150e 1101#ifdef _GLIBCXX_USE_LONG_LONG
1ab65677
BK
1102 template<typename _CharT, typename _OutIter>
1103 _OutIter
1104 num_put<_CharT, _OutIter>::
1105 do_put(iter_type __s, ios_base& __b, char_type __fill, long long __v) const
7942afdc 1106 { return _M_insert_int(__s, __b, __fill, __v); }
1ab65677
BK
1107
1108 template<typename _CharT, typename _OutIter>
1109 _OutIter
1110 num_put<_CharT, _OutIter>::
1111 do_put(iter_type __s, ios_base& __io, char_type __fill,
1112 unsigned long long __v) const
7942afdc 1113 { return _M_insert_int(__s, __io, __fill, __v); }
1ab65677
BK
1114#endif
1115
1ab65677
BK
1116 template<typename _CharT, typename _OutIter>
1117 _OutIter
1118 num_put<_CharT, _OutIter>::
1119 do_put(iter_type __s, ios_base& __io, char_type __fill, double __v) const
7942afdc 1120 { return _M_insert_float(__s, __io, __fill, char(), __v); }
1ab65677
BK
1121
1122 template<typename _CharT, typename _OutIter>
1123 _OutIter
1124 num_put<_CharT, _OutIter>::
ed6814f7 1125 do_put(iter_type __s, ios_base& __io, char_type __fill,
86ade44c 1126 long double __v) const
7942afdc 1127 { return _M_insert_float(__s, __io, __fill, 'L', __v); }
1ab65677
BK
1128
1129 template<typename _CharT, typename _OutIter>
1130 _OutIter
1131 num_put<_CharT, _OutIter>::
1132 do_put(iter_type __s, ios_base& __io, char_type __fill,
1133 const void* __v) const
1134 {
905df1fb 1135 const ios_base::fmtflags __flags = __io.flags();
a8ea7389
PC
1136 const ios_base::fmtflags __fmt = ~(ios_base::showpos
1137 | ios_base::basefield
1138 | ios_base::uppercase
1139 | ios_base::internal);
86ade44c 1140 __io.flags(__flags & __fmt | (ios_base::hex | ios_base::showbase));
ed6814f7
BI
1141
1142 __s = _M_insert_int(__s, __io, __fill,
e8c5fc66
PC
1143 reinterpret_cast<unsigned long>(__v));
1144 __io.flags(__flags);
86ade44c 1145 return __s;
1ab65677
BK
1146 }
1147
fe932e50
PC
1148 template<typename _CharT, bool _Intl>
1149 struct __use_cache<__moneypunct_cache<_CharT, _Intl> >
1150 {
1151 const __moneypunct_cache<_CharT, _Intl>*
1152 operator() (const locale& __loc) const
1153 {
1154 const size_t __i = moneypunct<_CharT, _Intl>::id._M_id();
1155 const locale::facet** __caches = __loc._M_impl->_M_caches;
1156 if (!__caches[__i])
1157 {
1158 __moneypunct_cache<_CharT, _Intl>* __tmp = NULL;
1159 try
1160 {
1161 __tmp = new __moneypunct_cache<_CharT, _Intl>;
1162 __tmp->_M_cache(__loc);
1163 }
1164 catch(...)
1165 {
1166 delete __tmp;
1167 __throw_exception_again;
1168 }
1169 __loc._M_impl->_M_install_cache(__tmp, __i);
1170 }
1171 return static_cast<
1172 const __moneypunct_cache<_CharT, _Intl>*>(__caches[__i]);
1173 }
1174 };
1175
1ab65677 1176 template<typename _CharT, typename _InIter>
20da06ef
PC
1177 template<bool _Intl>
1178 _InIter
1179 money_get<_CharT, _InIter>::
1180 _M_extract(iter_type __beg, iter_type __end, ios_base& __io,
f4bdbead 1181 ios_base::iostate& __err, string& __units) const
20da06ef 1182 {
f4bdbead 1183 typedef char_traits<_CharT> __traits_type;
20da06ef
PC
1184 typedef typename string_type::size_type size_type;
1185 typedef money_base::part part;
1186 typedef moneypunct<_CharT, _Intl> __moneypunct_type;
1187 typedef typename __moneypunct_type::__cache_type __cache_type;
1188
1189 const locale& __loc = __io._M_getloc();
1190 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1ab65677 1191
20da06ef
PC
1192 __use_cache<__cache_type> __uc;
1193 const __cache_type* __lc = __uc(__loc);
1194 const char_type* __lit = __lc->_M_atoms;
1ab65677 1195
20da06ef
PC
1196 // Deduced sign.
1197 bool __negative = false;
59564c5e
PC
1198 // Sign size.
1199 size_type __sign_size = 0;
20da06ef
PC
1200 // String of grouping info from thousands_sep plucked from __units.
1201 string __grouping_tmp;
a8ea7389
PC
1202 if (__lc->_M_use_grouping)
1203 __grouping_tmp.reserve(32);
08ff96c3
PC
1204 // Last position before the decimal point.
1205 int __last_pos = 0;
1206 // Separator positions, then, possibly, fractional digits.
1207 int __n = 0;
20da06ef
PC
1208 // If input iterator is in a valid state.
1209 bool __testvalid = true;
1210 // Flag marking when a decimal point is found.
1211 bool __testdecfound = false;
1ab65677 1212
20da06ef 1213 // The tentative returned string is stored here.
f4bdbead
PC
1214 string __res;
1215 __res.reserve(32);
e07554eb 1216
f4bdbead
PC
1217 const char_type* __lit_zero = __lit + _S_zero;
1218 const char_type* __q;
59564c5e
PC
1219 const money_base::pattern __p = __lc->_M_neg_format;
1220 for (int __i = 0; __i < 4 && __testvalid; ++__i)
20da06ef 1221 {
20da06ef
PC
1222 const part __which = static_cast<part>(__p.field[__i]);
1223 switch (__which)
1224 {
1225 case money_base::symbol:
1226 if (__io.flags() & ios_base::showbase
59564c5e 1227 || __i < 2 || __sign_size > 1
20da06ef
PC
1228 || ((static_cast<part>(__p.field[3]) != money_base::none)
1229 && __i == 2))
157f3283 1230 {
20da06ef 1231 // According to 22.2.6.1.2, p2, symbol is required
59564c5e
PC
1232 // if (__io.flags() & ios_base::showbase), otherwise
1233 // is optional and consumed only if other characters
1234 // are needed to complete the format.
20da06ef
PC
1235 const size_type __len = __lc->_M_curr_symbol_size;
1236 size_type __j = 0;
1237 for (; __beg != __end && __j < __len
1238 && *__beg == __lc->_M_curr_symbol[__j];
1239 ++__beg, ++__j);
20da06ef
PC
1240 if (__j != __len && (__io.flags() & ios_base::showbase))
1241 __testvalid = false;
157f3283 1242 }
20da06ef
PC
1243 break;
1244 case money_base::sign:
1245 // Sign might not exist, or be more than one character long.
59564c5e 1246 if (__lc->_M_positive_sign_size && __beg != __end
20da06ef 1247 && *__beg == __lc->_M_positive_sign[0])
157f3283 1248 {
59564c5e 1249 __sign_size = __lc->_M_positive_sign_size;
20da06ef 1250 ++__beg;
157f3283 1251 }
59564c5e 1252 else if (__lc->_M_negative_sign_size && __beg != __end
20da06ef 1253 && *__beg == __lc->_M_negative_sign[0])
157f3283 1254 {
20da06ef 1255 __negative = true;
59564c5e 1256 __sign_size = __lc->_M_negative_sign_size;
20da06ef 1257 ++__beg;
157f3283 1258 }
20da06ef
PC
1259 else if (__lc->_M_positive_sign_size
1260 && !__lc->_M_negative_sign_size)
1261 // "... if no sign is detected, the result is given the sign
1262 // that corresponds to the source of the empty string"
1263 __negative = true;
1264 else if (__lc->_M_positive_sign_size
1265 && __lc->_M_negative_sign_size)
1266 {
1267 // Sign is mandatory.
1268 __testvalid = false;
1269 }
1270 break;
1271 case money_base::value:
1272 // Extract digits, remove and stash away the
1273 // grouping of found thousands separators.
1274 for (; __beg != __end; ++__beg)
f4bdbead 1275 if (__q = __traits_type::find(__lit_zero, 10, *__beg))
20da06ef 1276 {
f4bdbead 1277 __res += _S_atoms[__q - __lit];
08ff96c3 1278 ++__n;
20da06ef 1279 }
f4bdbead 1280 else if (*__beg == __lc->_M_decimal_point && !__testdecfound)
20da06ef 1281 {
08ff96c3
PC
1282 __last_pos = __n;
1283 __n = 0;
20da06ef
PC
1284 __testdecfound = true;
1285 }
a8ea7389 1286 else if (__lc->_M_use_grouping
08ff96c3
PC
1287 && *__beg == __lc->_M_thousands_sep
1288 && !__testdecfound)
20da06ef 1289 {
08ff96c3 1290 if (__n)
20da06ef
PC
1291 {
1292 // Mark position for later analysis.
08ff96c3
PC
1293 __grouping_tmp += static_cast<char>(__n);
1294 __n = 0;
20da06ef
PC
1295 }
1296 else
1297 {
1298 __testvalid = false;
1299 break;
1300 }
1301 }
1302 else
1303 break;
59564c5e
PC
1304 if (__res.empty())
1305 __testvalid = false;
20da06ef
PC
1306 break;
1307 case money_base::space:
1308 case money_base::none:
1309 // Only if not at the end of the pattern.
1310 if (__i != 3)
1311 for (; __beg != __end
1312 && __ctype.is(ctype_base::space, *__beg); ++__beg);
1313 break;
1314 }
1315 }
14628700 1316
20da06ef 1317 // Need to get the rest of the sign characters, if they exist.
59564c5e 1318 if (__sign_size > 1 && __testvalid)
20da06ef
PC
1319 {
1320 const char_type* __sign = __negative ? __lc->_M_negative_sign
1321 : __lc->_M_positive_sign;
20da06ef 1322 size_type __i = 1;
59564c5e 1323 for (; __beg != __end && __i < __sign_size
20da06ef
PC
1324 && *__beg == __sign[__i]; ++__beg, ++__i);
1325
59564c5e 1326 if (__i != __sign_size)
20da06ef
PC
1327 __testvalid = false;
1328 }
87a7c5a1 1329
59564c5e 1330 if (__testvalid)
20da06ef
PC
1331 {
1332 // Strip leading zeros.
1333 if (__res.size() > 1)
1334 {
b19fb27d 1335 const size_type __first = __res.find_first_not_of('0');
98e953f5 1336 const bool __only_zeros = __first == string::npos;
20da06ef
PC
1337 if (__first)
1338 __res.erase(0, __only_zeros ? __res.size() - 1 : __first);
1339 }
e07554eb 1340
20da06ef 1341 // 22.2.6.1.2, p4
b19fb27d
PC
1342 if (__negative && __res[0] != '0')
1343 __res.insert(__res.begin(), '-');
20da06ef
PC
1344
1345 // Test for grouping fidelity.
1346 if (__grouping_tmp.size())
1347 {
08ff96c3
PC
1348 // Add the ending grouping.
1349 __grouping_tmp += static_cast<char>(__testdecfound ? __last_pos
1350 : __n);
20da06ef
PC
1351 if (!std::__verify_grouping(__lc->_M_grouping,
1352 __lc->_M_grouping_size,
1353 __grouping_tmp))
1354 __testvalid = false;
1355 }
1356
1357 // Iff not enough digits were supplied after the decimal-point.
1358 if (__testdecfound && __lc->_M_frac_digits > 0
08ff96c3 1359 && __n != __lc->_M_frac_digits)
20da06ef
PC
1360 __testvalid = false;
1361 }
20da06ef
PC
1362
1363 // Iff no more characters are available.
1364 if (__beg == __end)
1365 __err |= ios_base::eofbit;
1366
1367 // Iff valid sequence is not recognized.
1368 if (!__testvalid)
1369 __err |= ios_base::failbit;
1370 else
f4bdbead 1371 __units.swap(__res);
20da06ef
PC
1372
1373 return __beg;
1374 }
1ab65677 1375
2ddf25f2
PC
1376 template<typename _CharT, typename _InIter>
1377 _InIter
1378 money_get<_CharT, _InIter>::
1379 do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
1380 ios_base::iostate& __err, long double& __units) const
ed6814f7 1381 {
f4bdbead 1382 string __str;
20da06ef
PC
1383 if (__intl)
1384 __beg = _M_extract<true>(__beg, __end, __io, __err, __str);
1385 else
1386 __beg = _M_extract<false>(__beg, __end, __io, __err, __str);
2ddf25f2 1387
f4bdbead
PC
1388 if (__str.size())
1389 std::__convert_to_v(__str.c_str(), __units, __err, _S_get_c_locale());
1390
2ddf25f2 1391 return __beg;
1ab65677
BK
1392 }
1393
2ddf25f2
PC
1394 template<typename _CharT, typename _InIter>
1395 _InIter
1396 money_get<_CharT, _InIter>::
1397 do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
1398 ios_base::iostate& __err, string_type& __units) const
f4bdbead 1399 {
98e953f5 1400 typedef typename string::size_type size_type;
f4bdbead
PC
1401
1402 const locale& __loc = __io._M_getloc();
1403 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1404
1405 string __str;
1406 const iter_type __ret = __intl ? _M_extract<true>(__beg, __end, __io,
1407 __err, __str)
1408 : _M_extract<false>(__beg, __end, __io,
1409 __err, __str);
1410 const size_type __len = __str.size();
1411 if (__len)
1412 {
1413 _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
1414 * __len));
1415 __ctype.widen(__str.data(), __str.data() + __len, __ws);
1416 __units.assign(__ws, __len);
1417 }
1418
1419 return __ret;
1420 }
2ddf25f2 1421
1ab65677 1422 template<typename _CharT, typename _OutIter>
fe932e50
PC
1423 template<bool _Intl>
1424 _OutIter
1425 money_put<_CharT, _OutIter>::
1426 _M_insert(iter_type __s, ios_base& __io, char_type __fill,
1427 const string_type& __digits) const
1428 {
1429 typedef typename string_type::size_type size_type;
1430 typedef money_base::part part;
1431 typedef moneypunct<_CharT, _Intl> __moneypunct_type;
1432 typedef typename __moneypunct_type::__cache_type __cache_type;
2ddf25f2 1433
fe932e50
PC
1434 const locale& __loc = __io._M_getloc();
1435 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1ab65677 1436
fe932e50
PC
1437 __use_cache<__cache_type> __uc;
1438 const __cache_type* __lc = __uc(__loc);
1439 const char_type* __lit = __lc->_M_atoms;
1ab65677 1440
fe932e50
PC
1441 // Determine if negative or positive formats are to be used, and
1442 // discard leading negative_sign if it is present.
1443 const char_type* __beg = __digits.data();
fb678854 1444
fe932e50
PC
1445 money_base::pattern __p;
1446 const char_type* __sign;
1447 size_type __sign_size;
1448 if (*__beg != __lit[_S_minus])
1449 {
1450 __p = __lc->_M_pos_format;
1451 __sign = __lc->_M_positive_sign;
1452 __sign_size = __lc->_M_positive_sign_size;
1453 }
ced3ad4d 1454 else
fe932e50
PC
1455 {
1456 __p = __lc->_M_neg_format;
1457 __sign = __lc->_M_negative_sign;
1458 __sign_size = __lc->_M_negative_sign_size;
ced3ad4d
PC
1459 if (__digits.size())
1460 ++__beg;
fe932e50
PC
1461 }
1462
1463 // Look for valid numbers in the ctype facet within input digits.
039e3c5c
PC
1464 size_type __len = __ctype.scan_not(ctype_base::digit, __beg,
1465 __beg + __digits.size()) - __beg;
1466 if (__len)
fe932e50
PC
1467 {
1468 // Assume valid input, and attempt to format.
1469 // Break down input numbers into base components, as follows:
1470 // final_value = grouped units + (decimal point) + (digits)
fe932e50 1471 string_type __value;
20da06ef
PC
1472 __value.reserve(2 * __len);
1473
1474 // Add thousands separators to non-decimal digits, per
1475 // grouping rules.
039e3c5c
PC
1476 int __paddec = __len - __lc->_M_frac_digits;
1477 if (__paddec > 0)
20da06ef 1478 {
039e3c5c
PC
1479 if (__lc->_M_frac_digits < 0)
1480 __paddec = __len;
20da06ef
PC
1481 if (__lc->_M_grouping_size)
1482 {
1483 _CharT* __ws =
1484 static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
1485 * 2 * __len));
1486 _CharT* __ws_end =
1487 std::__add_grouping(__ws, __lc->_M_thousands_sep,
1488 __lc->_M_grouping,
1489 __lc->_M_grouping_size,
039e3c5c 1490 __beg, __beg + __paddec);
20da06ef
PC
1491 __value.assign(__ws, __ws_end - __ws);
1492 }
1493 else
039e3c5c 1494 __value.assign(__beg, __paddec);
20da06ef
PC
1495 }
1496
fe932e50
PC
1497 // Deal with decimal point, decimal digits.
1498 if (__lc->_M_frac_digits > 0)
1499 {
20da06ef 1500 __value += __lc->_M_decimal_point;
039e3c5c
PC
1501 if (__paddec >= 0)
1502 __value.append(__beg + __paddec, __lc->_M_frac_digits);
fe932e50
PC
1503 else
1504 {
1505 // Have to pad zeros in the decimal position.
039e3c5c 1506 __value.append(-__paddec, __lit[_S_zero]);
20da06ef 1507 __value.append(__beg, __len);
fe932e50 1508 }
20da06ef
PC
1509 }
1510
fe932e50
PC
1511 // Calculate length of resulting string.
1512 const ios_base::fmtflags __f = __io.flags() & ios_base::adjustfield;
20da06ef 1513 __len = __value.size() + __sign_size;
fe932e50
PC
1514 __len += ((__io.flags() & ios_base::showbase)
1515 ? __lc->_M_curr_symbol_size : 0);
20da06ef
PC
1516
1517 string_type __res;
1518 __res.reserve(2 * __len);
fe932e50
PC
1519
1520 const size_type __width = static_cast<size_type>(__io.width());
1521 const bool __testipad = (__f == ios_base::internal
1522 && __len < __width);
1523 // Fit formatted digits into the required pattern.
1524 for (int __i = 0; __i < 4; ++__i)
1525 {
1526 const part __which = static_cast<part>(__p.field[__i]);
1527 switch (__which)
1528 {
1529 case money_base::symbol:
1530 if (__io.flags() & ios_base::showbase)
1531 __res.append(__lc->_M_curr_symbol,
1532 __lc->_M_curr_symbol_size);
1533 break;
1534 case money_base::sign:
1535 // Sign might not exist, or be more than one
1536 // charater long. In that case, add in the rest
1537 // below.
1538 if (__sign_size)
1539 __res += __sign[0];
1540 break;
1541 case money_base::value:
1542 __res += __value;
1543 break;
1544 case money_base::space:
1545 // At least one space is required, but if internal
1546 // formatting is required, an arbitrary number of
1547 // fill spaces will be necessary.
1548 if (__testipad)
031e658e 1549 __res.append(__width - __len, __fill);
fe932e50
PC
1550 else
1551 __res += __fill;
1552 break;
1553 case money_base::none:
1554 if (__testipad)
031e658e 1555 __res.append(__width - __len, __fill);
fe932e50
PC
1556 break;
1557 }
1558 }
1559
1560 // Special case of multi-part sign parts.
1561 if (__sign_size > 1)
1562 __res.append(__sign + 1, __sign_size - 1);
1563
1564 // Pad, if still necessary.
1565 __len = __res.size();
1566 if (__width > __len)
1567 {
1568 if (__f == ios_base::left)
1569 // After.
1570 __res.append(__width - __len, __fill);
1571 else
1572 // Before.
031e658e 1573 __res.insert(0, __width - __len, __fill);
fe932e50
PC
1574 __len = __width;
1575 }
1576
1577 // Write resulting, fully-formatted string to output iterator.
1578 __s = std::__write(__s, __res.data(), __len);
1579 }
1580 __io.width(0);
1581 return __s;
1582 }
1583
2ddf25f2
PC
1584 template<typename _CharT, typename _OutIter>
1585 _OutIter
1586 money_put<_CharT, _OutIter>::
1587 do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
1588 long double __units) const
1589 {
1590 const locale __loc = __io.getloc();
1591 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1592#ifdef _GLIBCXX_USE_C99
1593 // First try a buffer perhaps big enough.
1594 int __cs_size = 64;
1595 char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
1596 // _GLIBCXX_RESOLVE_LIB_DEFECTS
1597 // 328. Bad sprintf format modifier in money_put<>::do_put()
1598 int __len = std::__convert_from_v(__cs, __cs_size, "%.0Lf", __units,
1599 _S_get_c_locale());
1600 // If the buffer was not large enough, try again with the correct size.
1601 if (__len >= __cs_size)
1602 {
1603 __cs_size = __len + 1;
1604 __cs = static_cast<char*>(__builtin_alloca(__cs_size));
1605 __len = std::__convert_from_v(__cs, __cs_size, "%.0Lf", __units,
1606 _S_get_c_locale());
1607 }
1608#else
1609 // max_exponent10 + 1 for the integer part, + 2 for sign and '\0'.
1610 const int __cs_size = numeric_limits<long double>::max_exponent10 + 3;
1611 char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
1612 int __len = std::__convert_from_v(__cs, 0, "%.0Lf", __units,
1613 _S_get_c_locale());
1614#endif
1615 _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
1616 * __cs_size));
1617 __ctype.widen(__cs, __cs + __len, __ws);
1618 const string_type __digits(__ws, __len);
fe932e50
PC
1619 return __intl ? _M_insert<true>(__s, __io, __fill, __digits)
1620 : _M_insert<false>(__s, __io, __fill, __digits);
2ddf25f2
PC
1621 }
1622
1623 template<typename _CharT, typename _OutIter>
1624 _OutIter
1625 money_put<_CharT, _OutIter>::
1626 do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
1627 const string_type& __digits) const
fe932e50
PC
1628 { return __intl ? _M_insert<true>(__s, __io, __fill, __digits)
1629 : _M_insert<false>(__s, __io, __fill, __digits); }
1ab65677
BK
1630
1631 // NB: Not especially useful. Without an ios_base object or some
1632 // kind of locale reference, we are left clawing at the air where
1633 // the side of the mountain used to be...
1634 template<typename _CharT, typename _InIter>
1635 time_base::dateorder
1636 time_get<_CharT, _InIter>::do_date_order() const
1637 { return time_base::no_order; }
1638
9a01c9b0
JQ
1639 // Recursively expand a strftime format string and parse it. Starts w/ %x
1640 // and %X from do_get_time() and do_get_date(), which translate to a more
1641 // specific string, which may contain yet more strings. I.e. %x => %r =>
1642 // %H:%M:%S => extracted characters.
1ab65677
BK
1643 template<typename _CharT, typename _InIter>
1644 void
1645 time_get<_CharT, _InIter>::
da5c0f6e 1646 _M_extract_via_format(iter_type& __beg, iter_type& __end, ios_base& __io,
ed6814f7 1647 ios_base::iostate& __err, tm* __tm,
da5c0f6e 1648 const _CharT* __format) const
ed6814f7 1649 {
905df1fb 1650 const locale __loc = __io.getloc();
e0f05105 1651 const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
ed6814f7 1652 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
905df1fb 1653 const size_t __len = char_traits<_CharT>::length(__format);
da5c0f6e
BK
1654
1655 for (size_t __i = 0; __beg != __end && __i < __len && !__err; ++__i)
1ab65677 1656 {
7e08b3b8 1657 if (__ctype.narrow(__format[__i], 0) == '%')
1ab65677 1658 {
da5c0f6e 1659 // Verify valid formatting code, attempt to extract.
7e08b3b8 1660 char __c = __ctype.narrow(__format[++__i], 0);
ed6814f7 1661 int __mem = 0;
da5c0f6e 1662 if (__c == 'E' || __c == 'O')
7e08b3b8 1663 __c = __ctype.narrow(__format[++__i], 0);
da5c0f6e
BK
1664 switch (__c)
1665 {
1666 const char* __cs;
1667 _CharT __wcs[10];
1668 case 'a':
1669 // Abbreviated weekday name [tm_wday]
1670 const char_type* __days1[7];
1671 __tp._M_days_abbreviated(__days1);
ed6814f7 1672 _M_extract_name(__beg, __end, __tm->tm_wday, __days1, 7,
e0f05105 1673 __ctype, __err);
da5c0f6e
BK
1674 break;
1675 case 'A':
1676 // Weekday name [tm_wday].
1677 const char_type* __days2[7];
1678 __tp._M_days(__days2);
ed6814f7 1679 _M_extract_name(__beg, __end, __tm->tm_wday, __days2, 7,
e0f05105 1680 __ctype, __err);
da5c0f6e
BK
1681 break;
1682 case 'h':
1683 case 'b':
1684 // Abbreviated month name [tm_mon]
1685 const char_type* __months1[12];
1686 __tp._M_months_abbreviated(__months1);
ed6814f7 1687 _M_extract_name(__beg, __end, __tm->tm_mon, __months1, 12,
e0f05105 1688 __ctype, __err);
da5c0f6e
BK
1689 break;
1690 case 'B':
1691 // Month name [tm_mon].
1692 const char_type* __months2[12];
1693 __tp._M_months(__months2);
ed6814f7 1694 _M_extract_name(__beg, __end, __tm->tm_mon, __months2, 12,
e0f05105 1695 __ctype, __err);
da5c0f6e
BK
1696 break;
1697 case 'c':
1698 // Default time and date representation.
1699 const char_type* __dt[2];
1700 __tp._M_date_time_formats(__dt);
ed6814f7 1701 _M_extract_via_format(__beg, __end, __io, __err, __tm,
da5c0f6e
BK
1702 __dt[0]);
1703 break;
1704 case 'd':
1705 // Day [01, 31]. [tm_mday]
ed6814f7 1706 _M_extract_num(__beg, __end, __tm->tm_mday, 1, 31, 2,
da5c0f6e
BK
1707 __ctype, __err);
1708 break;
f20d2b78
PC
1709 case 'e':
1710 // Day [1, 31], with single digits preceded by
1711 // space. [tm_mday]
1712 if (__ctype.is(ctype_base::space, *__beg))
1713 _M_extract_num(++__beg, __end, __tm->tm_mday, 1, 9, 1,
1714 __ctype, __err);
cc27f5a2 1715 else
f20d2b78 1716 _M_extract_num(__beg, __end, __tm->tm_mday, 10, 31, 2,
ed6814f7
BI
1717 __ctype, __err);
1718 break;
da5c0f6e
BK
1719 case 'D':
1720 // Equivalent to %m/%d/%y.[tm_mon, tm_mday, tm_year]
1721 __cs = "%m/%d/%y";
1722 __ctype.widen(__cs, __cs + 9, __wcs);
ed6814f7 1723 _M_extract_via_format(__beg, __end, __io, __err, __tm,
da5c0f6e
BK
1724 __wcs);
1725 break;
1726 case 'H':
1727 // Hour [00, 23]. [tm_hour]
1728 _M_extract_num(__beg, __end, __tm->tm_hour, 0, 23, 2,
1729 __ctype, __err);
1730 break;
1731 case 'I':
1732 // Hour [01, 12]. [tm_hour]
ed6814f7 1733 _M_extract_num(__beg, __end, __tm->tm_hour, 1, 12, 2,
da5c0f6e
BK
1734 __ctype, __err);
1735 break;
1736 case 'm':
1737 // Month [01, 12]. [tm_mon]
ed6814f7 1738 _M_extract_num(__beg, __end, __mem, 1, 12, 2, __ctype,
8f88da40 1739 __err);
da5c0f6e
BK
1740 if (!__err)
1741 __tm->tm_mon = __mem - 1;
1742 break;
1743 case 'M':
1744 // Minute [00, 59]. [tm_min]
1745 _M_extract_num(__beg, __end, __tm->tm_min, 0, 59, 2,
1746 __ctype, __err);
1747 break;
1748 case 'n':
1749 if (__ctype.narrow(*__beg, 0) == '\n')
1750 ++__beg;
1751 else
1752 __err |= ios_base::failbit;
1753 break;
1754 case 'R':
1755 // Equivalent to (%H:%M).
1756 __cs = "%H:%M";
1757 __ctype.widen(__cs, __cs + 6, __wcs);
ed6814f7 1758 _M_extract_via_format(__beg, __end, __io, __err, __tm,
da5c0f6e
BK
1759 __wcs);
1760 break;
1761 case 'S':
1762 // Seconds.
1763 _M_extract_num(__beg, __end, __tm->tm_sec, 0, 59, 2,
1764 __ctype, __err);
1765 break;
1766 case 't':
1767 if (__ctype.narrow(*__beg, 0) == '\t')
1768 ++__beg;
1769 else
f20d2b78 1770 __err |= ios_base::failbit;
da5c0f6e
BK
1771 break;
1772 case 'T':
1773 // Equivalent to (%H:%M:%S).
1774 __cs = "%H:%M:%S";
1775 __ctype.widen(__cs, __cs + 9, __wcs);
ed6814f7 1776 _M_extract_via_format(__beg, __end, __io, __err, __tm,
da5c0f6e
BK
1777 __wcs);
1778 break;
1779 case 'x':
1780 // Locale's date.
1781 const char_type* __dates[2];
1782 __tp._M_date_formats(__dates);
ed6814f7 1783 _M_extract_via_format(__beg, __end, __io, __err, __tm,
da5c0f6e
BK
1784 __dates[0]);
1785 break;
1786 case 'X':
1787 // Locale's time.
1788 const char_type* __times[2];
1789 __tp._M_time_formats(__times);
ed6814f7 1790 _M_extract_via_format(__beg, __end, __io, __err, __tm,
da5c0f6e
BK
1791 __times[0]);
1792 break;
1793 case 'y':
c21dbe85 1794 case 'C': // C99
da5c0f6e 1795 // Two digit year. [tm_year]
ed6814f7 1796 _M_extract_num(__beg, __end, __tm->tm_year, 0, 99, 2,
da5c0f6e
BK
1797 __ctype, __err);
1798 break;
1799 case 'Y':
1800 // Year [1900). [tm_year]
ed6814f7 1801 _M_extract_num(__beg, __end, __mem, 0, 9999, 4,
da5c0f6e
BK
1802 __ctype, __err);
1803 if (!__err)
1804 __tm->tm_year = __mem - 1900;
1805 break;
1806 case 'Z':
1807 // Timezone info.
1808 if (__ctype.is(ctype_base::upper, *__beg))
1809 {
1810 int __tmp;
ed6814f7
BI
1811 _M_extract_name(__beg, __end, __tmp,
1812 __timepunct_cache<_CharT>::_S_timezones,
e0f05105 1813 14, __ctype, __err);
ed6814f7 1814
da5c0f6e 1815 // GMT requires special effort.
f20d2b78 1816 if (__beg != __end && !__err && __tmp == 0
ed6814f7 1817 && (*__beg == __ctype.widen('-')
f20d2b78 1818 || *__beg == __ctype.widen('+')))
da5c0f6e
BK
1819 {
1820 _M_extract_num(__beg, __end, __tmp, 0, 23, 2,
1821 __ctype, __err);
1822 _M_extract_num(__beg, __end, __tmp, 0, 59, 2,
1823 __ctype, __err);
ed6814f7 1824 }
da5c0f6e 1825 }
da5c0f6e
BK
1826 else
1827 __err |= ios_base::failbit;
905df1fb
PC
1828 break;
1829 default:
1830 // Not recognized.
1831 __err |= ios_base::failbit;
da5c0f6e 1832 }
905df1fb
PC
1833 }
1834 else
1835 {
1836 // Verify format and input match, extract and discard.
7e08b3b8 1837 if (__format[__i] == *__beg)
905df1fb
PC
1838 ++__beg;
1839 else
1840 __err |= ios_base::failbit;
1841 }
da5c0f6e
BK
1842 }
1843 }
1844
1845 template<typename _CharT, typename _InIter>
1846 void
1847 time_get<_CharT, _InIter>::
1848 _M_extract_num(iter_type& __beg, iter_type& __end, int& __member,
ed6814f7
BI
1849 int __min, int __max, size_t __len,
1850 const ctype<_CharT>& __ctype,
da5c0f6e
BK
1851 ios_base::iostate& __err) const
1852 {
3259561c
PC
1853 // As-is works for __len = 1, 2, 4, the values actually used.
1854 int __mult = __len == 2 ? 10 : (__len == 4 ? 1000 : 1);
1855
1856 ++__min;
da5c0f6e 1857 size_t __i = 0;
3259561c
PC
1858 int __value = 0;
1859 for (; __beg != __end && __i < __len; ++__beg, ++__i)
da5c0f6e 1860 {
3259561c
PC
1861 const char __c = __ctype.narrow(*__beg, '*');
1862 if (__c >= '0' && __c <= '9')
1863 {
1864 __value = __value * 10 + (__c - '0');
1865 const int __valuec = __value * __mult;
1866 if (__valuec > __max || __valuec + __mult < __min)
1867 break;
1868 __mult /= 10;
1869 }
1ab65677 1870 else
3259561c 1871 break;
da5c0f6e 1872 }
3259561c
PC
1873 if (__i == __len)
1874 __member = __value;
da5c0f6e 1875 else
da5c0f6e 1876 __err |= ios_base::failbit;
725dc051
BK
1877 }
1878
1ab65677
BK
1879 // Assumptions:
1880 // All elements in __names are unique.
1881 template<typename _CharT, typename _InIter>
1882 void
1883 time_get<_CharT, _InIter>::
1884 _M_extract_name(iter_type& __beg, iter_type& __end, int& __member,
ed6814f7
BI
1885 const _CharT** __names, size_t __indexlen,
1886 const ctype<_CharT>& __ctype,
1ab65677 1887 ios_base::iostate& __err) const
725dc051 1888 {
ed6814f7
BI
1889 typedef char_traits<_CharT> __traits_type;
1890 int* __matches = static_cast<int*>(__builtin_alloca(sizeof(int)
2e2a38cd 1891 * __indexlen));
1ab65677
BK
1892 size_t __nmatches = 0;
1893 size_t __pos = 0;
1894 bool __testvalid = true;
1895 const char_type* __name;
725dc051 1896
ed6814f7 1897 // Look for initial matches.
e0f05105
BK
1898 // NB: Some of the locale data is in the form of all lowercase
1899 // names, and some is in the form of initially-capitalized
1900 // names. Look for both.
cc27f5a2
PC
1901 if (__beg != __end)
1902 {
1903 const char_type __c = *__beg;
1904 for (size_t __i1 = 0; __i1 < __indexlen; ++__i1)
ed6814f7 1905 if (__c == __names[__i1][0]
e0f05105 1906 || __c == __ctype.toupper(__names[__i1][0]))
cc27f5a2
PC
1907 __matches[__nmatches++] = __i1;
1908 }
ed6814f7 1909
ce3039af 1910 while (__nmatches > 1)
1ab65677
BK
1911 {
1912 // Find smallest matching string.
1913 size_t __minlen = 10;
1914 for (size_t __i2 = 0; __i2 < __nmatches; ++__i2)
ed6814f7 1915 __minlen = std::min(__minlen,
5b577977 1916 __traits_type::length(__names[__matches[__i2]]));
cc27f5a2 1917 ++__beg;
1ab65677
BK
1918 if (__pos < __minlen && __beg != __end)
1919 {
1920 ++__pos;
1ab65677
BK
1921 for (size_t __i3 = 0; __i3 < __nmatches; ++__i3)
1922 {
1923 __name = __names[__matches[__i3]];
cc27f5a2 1924 if (__name[__pos] != *__beg)
1ab65677
BK
1925 __matches[__i3] = __matches[--__nmatches];
1926 }
1927 }
1928 else
1929 break;
1930 }
725dc051 1931
1ab65677
BK
1932 if (__nmatches == 1)
1933 {
e0f05105
BK
1934 // If there was only one match, the first compare is redundant.
1935 if (__pos == 0)
1936 {
1937 ++__pos;
1938 ++__beg;
1939 }
1940
1ab65677
BK
1941 // Make sure found name is completely extracted.
1942 __name = __names[__matches[0]];
1943 const size_t __len = __traits_type::length(__name);
1944 while (__pos < __len && __beg != __end && __name[__pos] == *__beg)
1945 ++__beg, ++__pos;
1946
1947 if (__len == __pos)
1948 __member = __matches[0];
1949 else
1950 __testvalid = false;
1951 }
1952 else
1953 __testvalid = false;
1954 if (!__testvalid)
1955 __err |= ios_base::failbit;
725dc051
BK
1956 }
1957
1ab65677
BK
1958 template<typename _CharT, typename _InIter>
1959 _InIter
1960 time_get<_CharT, _InIter>::
1961 do_get_time(iter_type __beg, iter_type __end, ios_base& __io,
1962 ios_base::iostate& __err, tm* __tm) const
725dc051 1963 {
da5c0f6e
BK
1964 _CharT __wcs[3];
1965 const char* __cs = "%X";
905df1fb 1966 const locale __loc = __io.getloc();
da5c0f6e
BK
1967 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
1968 __ctype.widen(__cs, __cs + 3, __wcs);
1969 _M_extract_via_format(__beg, __end, __io, __err, __tm, __wcs);
1ab65677
BK
1970 if (__beg == __end)
1971 __err |= ios_base::eofbit;
1972 return __beg;
725dc051
BK
1973 }
1974
1ab65677
BK
1975 template<typename _CharT, typename _InIter>
1976 _InIter
1977 time_get<_CharT, _InIter>::
1978 do_get_date(iter_type __beg, iter_type __end, ios_base& __io,
da5c0f6e 1979 ios_base::iostate& __err, tm* __tm) const
725dc051 1980 {
da5c0f6e
BK
1981 _CharT __wcs[3];
1982 const char* __cs = "%x";
905df1fb 1983 const locale __loc = __io.getloc();
da5c0f6e
BK
1984 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
1985 __ctype.widen(__cs, __cs + 3, __wcs);
1986 _M_extract_via_format(__beg, __end, __io, __err, __tm, __wcs);
1ab65677
BK
1987 if (__beg == __end)
1988 __err |= ios_base::eofbit;
1989 return __beg;
725dc051
BK
1990 }
1991
1ab65677
BK
1992 template<typename _CharT, typename _InIter>
1993 _InIter
1994 time_get<_CharT, _InIter>::
ed6814f7 1995 do_get_weekday(iter_type __beg, iter_type __end, ios_base& __io,
1ab65677 1996 ios_base::iostate& __err, tm* __tm) const
725dc051 1997 {
ed6814f7 1998 typedef char_traits<_CharT> __traits_type;
905df1fb 1999 const locale __loc = __io.getloc();
e0f05105 2000 const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
ed6814f7 2001 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1ab65677
BK
2002 const char_type* __days[7];
2003 __tp._M_days_abbreviated(__days);
2004 int __tmpwday;
e0f05105 2005 _M_extract_name(__beg, __end, __tmpwday, __days, 7, __ctype, __err);
1ab65677
BK
2006
2007 // Check to see if non-abbreviated name exists, and extract.
2008 // NB: Assumes both _M_days and _M_days_abbreviated organized in
2009 // exact same order, first to last, such that the resulting
2010 // __days array with the same index points to a day, and that
2011 // day's abbreviated form.
ed6814f7 2012 // NB: Also assumes that an abbreviated name is a subset of the name.
1ab65677
BK
2013 if (!__err)
2014 {
2015 size_t __pos = __traits_type::length(__days[__tmpwday]);
2016 __tp._M_days(__days);
2017 const char_type* __name = __days[__tmpwday];
2018 if (__name[__pos] == *__beg)
2019 {
2020 // Extract the rest of it.
2021 const size_t __len = __traits_type::length(__name);
ed6814f7 2022 while (__pos < __len && __beg != __end
1ab65677
BK
2023 && __name[__pos] == *__beg)
2024 ++__beg, ++__pos;
2025 if (__len != __pos)
2026 __err |= ios_base::failbit;
2027 }
2028 if (!__err)
2029 __tm->tm_wday = __tmpwday;
2030 }
2031 if (__beg == __end)
2032 __err |= ios_base::eofbit;
2033 return __beg;
2034 }
725dc051 2035
1ab65677
BK
2036 template<typename _CharT, typename _InIter>
2037 _InIter
2038 time_get<_CharT, _InIter>::
2039 do_get_monthname(iter_type __beg, iter_type __end,
2040 ios_base& __io, ios_base::iostate& __err, tm* __tm) const
725dc051 2041 {
ed6814f7 2042 typedef char_traits<_CharT> __traits_type;
905df1fb 2043 const locale __loc = __io.getloc();
e0f05105 2044 const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
ed6814f7 2045 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1ab65677
BK
2046 const char_type* __months[12];
2047 __tp._M_months_abbreviated(__months);
2048 int __tmpmon;
e0f05105 2049 _M_extract_name(__beg, __end, __tmpmon, __months, 12, __ctype, __err);
1ab65677
BK
2050
2051 // Check to see if non-abbreviated name exists, and extract.
2052 // NB: Assumes both _M_months and _M_months_abbreviated organized in
2053 // exact same order, first to last, such that the resulting
2054 // __months array with the same index points to a month, and that
2055 // month's abbreviated form.
ed6814f7 2056 // NB: Also assumes that an abbreviated name is a subset of the name.
1ab65677
BK
2057 if (!__err)
2058 {
2059 size_t __pos = __traits_type::length(__months[__tmpmon]);
2060 __tp._M_months(__months);
2061 const char_type* __name = __months[__tmpmon];
2062 if (__name[__pos] == *__beg)
2063 {
2064 // Extract the rest of it.
2065 const size_t __len = __traits_type::length(__name);
ed6814f7 2066 while (__pos < __len && __beg != __end
1ab65677
BK
2067 && __name[__pos] == *__beg)
2068 ++__beg, ++__pos;
2069 if (__len != __pos)
2070 __err |= ios_base::failbit;
2071 }
2072 if (!__err)
2073 __tm->tm_mon = __tmpmon;
2074 }
ed6814f7 2075
1ab65677
BK
2076 if (__beg == __end)
2077 __err |= ios_base::eofbit;
2078 return __beg;
725dc051
BK
2079 }
2080
1ab65677
BK
2081 template<typename _CharT, typename _InIter>
2082 _InIter
2083 time_get<_CharT, _InIter>::
ed6814f7 2084 do_get_year(iter_type __beg, iter_type __end, ios_base& __io,
1ab65677 2085 ios_base::iostate& __err, tm* __tm) const
725dc051 2086 {
905df1fb 2087 const locale __loc = __io.getloc();
ed6814f7 2088 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1ab65677 2089
1ab65677 2090 size_t __i = 0;
17e15f7f
PC
2091 int __value = 0;
2092 for (; __beg != __end && __i < 4; ++__beg, ++__i)
1ab65677 2093 {
17e15f7f
PC
2094 const char __c = __ctype.narrow(*__beg, '*');
2095 if (__c >= '0' && __c <= '9')
2096 __value = __value * 10 + (__c - '0');
2097 else
2098 break;
1ab65677 2099 }
17e15f7f 2100 if (__i == 2 || __i == 4)
ed6814f7 2101 __tm->tm_year = __i == 2 ? __value : __value - 1900;
725dc051 2102 else
1ab65677
BK
2103 __err |= ios_base::failbit;
2104 if (__beg == __end)
2105 __err |= ios_base::eofbit;
2106 return __beg;
725dc051
BK
2107 }
2108
fb678854 2109 template<typename _CharT, typename _OutIter>
725dc051 2110 _OutIter
1ab65677 2111 time_put<_CharT, _OutIter>::
ed6814f7 2112 put(iter_type __s, ios_base& __io, char_type __fill, const tm* __tm,
1ab65677 2113 const _CharT* __beg, const _CharT* __end) const
e08138aa 2114 {
905df1fb 2115 const locale __loc = __io.getloc();
e08138aa 2116 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
6bf0b59c 2117 for (; __beg != __end; ++__beg)
f1e7988a
PC
2118 if (__ctype.narrow(*__beg, 0) != '%')
2119 {
2120 *__s = *__beg;
2121 ++__s;
2122 }
2123 else if (++__beg != __end)
2124 {
2125 char __format;
2126 char __mod = 0;
2127 const char __c = __ctype.narrow(*__beg, 0);
2128 if (__c != 'E' && __c != 'O')
2129 __format = __c;
2130 else if (++__beg != __end)
2131 {
2132 __mod = __c;
2133 __format = __ctype.narrow(*__beg, 0);
2134 }
2135 else
2136 break;
2137 __s = this->do_put(__s, __io, __fill, __tm,
2138 __format, __mod);
2139 }
2140 else
2141 break;
e08138aa
BK
2142 return __s;
2143 }
2144
2145 template<typename _CharT, typename _OutIter>
1ab65677
BK
2146 _OutIter
2147 time_put<_CharT, _OutIter>::
ed6814f7 2148 do_put(iter_type __s, ios_base& __io, char_type, const tm* __tm,
1ab65677 2149 char __format, char __mod) const
ed6814f7 2150 {
905df1fb 2151 const locale __loc = __io.getloc();
da5c0f6e
BK
2152 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
2153 __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc);
2154
e08138aa
BK
2155 // NB: This size is arbitrary. Should this be a data member,
2156 // initialized at construction?
2157 const size_t __maxlen = 64;
a8ea7389
PC
2158 char_type* __res =
2159 static_cast<char_type*>(__builtin_alloca(sizeof(char_type)
2160 * __maxlen));
e08138aa
BK
2161
2162 // NB: In IEE 1003.1-200x, and perhaps other locale models, it
2163 // is possible that the format character will be longer than one
2164 // character. Possibilities include 'E' or 'O' followed by a
c5504edb 2165 // format character: if __mod is not the default argument, assume
e08138aa 2166 // it's a valid modifier.
da5c0f6e 2167 char_type __fmt[4];
ed6814f7 2168 __fmt[0] = __ctype.widen('%');
e08138aa
BK
2169 if (!__mod)
2170 {
2171 __fmt[1] = __format;
da5c0f6e 2172 __fmt[2] = char_type();
e08138aa
BK
2173 }
2174 else
2175 {
2176 __fmt[1] = __mod;
2177 __fmt[2] = __format;
da5c0f6e 2178 __fmt[3] = char_type();
e08138aa
BK
2179 }
2180
d3a193e3 2181 __tp._M_put(__res, __maxlen, __fmt, __tm);
e08138aa
BK
2182
2183 // Write resulting, fully-formatted string to output iterator.
391cfc46 2184 return std::__write(__s, __res, char_traits<char_type>::length(__res));
e08138aa
BK
2185 }
2186
725dc051 2187
ea0c0b6e
BK
2188 // Generic version does nothing.
2189 template<typename _CharT>
2190 int
d3a193e3 2191 collate<_CharT>::_M_compare(const _CharT*, const _CharT*) const
ea0c0b6e
BK
2192 { return 0; }
2193
2194 // Generic version does nothing.
2195 template<typename _CharT>
2196 size_t
d3a193e3 2197 collate<_CharT>::_M_transform(_CharT*, const _CharT*, size_t) const
ea0c0b6e
BK
2198 { return 0; }
2199
2200 template<typename _CharT>
2201 int
2202 collate<_CharT>::
ed6814f7 2203 do_compare(const _CharT* __lo1, const _CharT* __hi1,
ea0c0b6e 2204 const _CharT* __lo2, const _CharT* __hi2) const
ed6814f7 2205 {
5040d691
PR
2206 // strcoll assumes zero-terminated strings so we make a copy
2207 // and then put a zero at the end.
ea0c0b6e
BK
2208 const string_type __one(__lo1, __hi1);
2209 const string_type __two(__lo2, __hi2);
5040d691
PR
2210
2211 const _CharT* __p = __one.c_str();
761faeec 2212 const _CharT* __pend = __one.data() + __one.length();
5040d691 2213 const _CharT* __q = __two.c_str();
761faeec 2214 const _CharT* __qend = __two.data() + __two.length();
5040d691
PR
2215
2216 // strcoll stops when it sees a nul character so we break
2217 // the strings into zero-terminated substrings and pass those
2218 // to strcoll.
2219 for (;;)
2220 {
905df1fb 2221 const int __res = _M_compare(__p, __q);
5040d691
PR
2222 if (__res)
2223 return __res;
2224
2225 __p += char_traits<_CharT>::length(__p);
2226 __q += char_traits<_CharT>::length(__q);
2227 if (__p == __pend && __q == __qend)
2228 return 0;
2229 else if (__p == __pend)
2230 return -1;
2231 else if (__q == __qend)
2232 return 1;
2233
2234 __p++;
2235 __q++;
2236 }
ea0c0b6e
BK
2237 }
2238
f1e7988a 2239 template<typename _CharT>
b206658a 2240 typename collate<_CharT>::string_type
ea0c0b6e
BK
2241 collate<_CharT>::
2242 do_transform(const _CharT* __lo, const _CharT* __hi) const
2243 {
5040d691
PR
2244 // strxfrm assumes zero-terminated strings so we make a copy
2245 string_type __str(__lo, __hi);
2246
2247 const _CharT* __p = __str.c_str();
761faeec 2248 const _CharT* __pend = __str.data() + __str.length();
5040d691 2249
32c16200 2250 size_t __len = (__hi - __lo) * 2;
5040d691
PR
2251
2252 string_type __ret;
2253
2254 // strxfrm stops when it sees a nul character so we break
2255 // the string into zero-terminated substrings and pass those
2256 // to strxfrm.
2257 for (;;)
ea0c0b6e 2258 {
5040d691
PR
2259 // First try a buffer perhaps big enough.
2260 _CharT* __c =
2261 static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __len));
2262 size_t __res = _M_transform(__c, __p, __len);
2263 // If the buffer was not large enough, try again with the
2264 // correct size.
2265 if (__res >= __len)
2266 {
2267 __len = __res + 1;
ed6814f7 2268 __c = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
5040d691
PR
2269 * __len));
2270 __res = _M_transform(__c, __p, __res + 1);
2271 }
2272
2273 __ret.append(__c, __res);
2274 __p += char_traits<_CharT>::length(__p);
2275 if (__p == __pend)
2276 return __ret;
2277
2278 __p++;
2279 __ret.push_back(_CharT());
ea0c0b6e 2280 }
ea0c0b6e
BK
2281 }
2282
f1e7988a 2283 template<typename _CharT>
ea0c0b6e
BK
2284 long
2285 collate<_CharT>::
2286 do_hash(const _CharT* __lo, const _CharT* __hi) const
ed6814f7 2287 {
ea0c0b6e
BK
2288 unsigned long __val = 0;
2289 for (; __lo < __hi; ++__lo)
ed6814f7 2290 __val = *__lo + ((__val << 7) |
4e2f8bcf 2291 (__val >> (numeric_limits<unsigned long>::digits - 7)));
ea0c0b6e
BK
2292 return static_cast<long>(__val);
2293 }
1ab65677 2294
86ade44c 2295 // Construct correctly padded string, as per 22.2.2.2.2
ed6814f7 2296 // Assumes
86ade44c
BK
2297 // __newlen > __oldlen
2298 // __news is allocated for __newlen size
b3340046
PC
2299 // Used by both num_put and ostream inserters: if __num,
2300 // internal-adjusted objects are padded according to the rules below
2301 // concerning 0[xX] and +-, otherwise, exactly as right-adjusted
2302 // ones are.
f13a69ec
BK
2303
2304 // NB: Of the two parameters, _CharT can be deduced from the
2305 // function arguments. The other (_Traits) has to be explicitly specified.
f13a69ec 2306 template<typename _CharT, typename _Traits>
ed6814f7
BI
2307 void
2308 __pad<_CharT, _Traits>::_S_pad(ios_base& __io, _CharT __fill,
2309 _CharT* __news, const _CharT* __olds,
2310 const streamsize __newlen,
f13a69ec
BK
2311 const streamsize __oldlen, const bool __num)
2312 {
e4f7d0a1
PC
2313 const size_t __plen = static_cast<size_t>(__newlen - __oldlen);
2314 const ios_base::fmtflags __adjust = __io.flags() & ios_base::adjustfield;
86ade44c 2315
e4f7d0a1 2316 // Padding last.
86ade44c
BK
2317 if (__adjust == ios_base::left)
2318 {
e4f7d0a1
PC
2319 _Traits::copy(__news, const_cast<_CharT*>(__olds), __oldlen);
2320 _Traits::assign(__news + __oldlen, __plen, __fill);
2321 return;
86ade44c 2322 }
e4f7d0a1
PC
2323
2324 size_t __mod = 0;
2325 if (__adjust == ios_base::internal && __num)
86ade44c
BK
2326 {
2327 // Pad after the sign, if there is one.
2328 // Pad after 0[xX], if there is one.
2329 // Who came up with these rules, anyway? Jeeze.
7942afdc 2330 const locale& __loc = __io._M_getloc();
ed6814f7 2331 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
230377dc
DA
2332
2333 const bool __testsign = _Traits::eq(__ctype.widen('-'), __olds[0])
2334 || _Traits::eq(__ctype.widen('+'), __olds[0]);
2335 const bool __testhex = (_Traits::eq(__ctype.widen('0'), __olds[0])
2336 && __oldlen > 1
2337 && (_Traits::eq(__ctype.widen('x'), __olds[1])
2338 || _Traits::eq(__ctype.widen('X'),
2339 __olds[1])));
86ade44c
BK
2340 if (__testhex)
2341 {
ed6814f7 2342 __news[0] = __olds[0];
86ade44c 2343 __news[1] = __olds[1];
5b577977 2344 __mod = 2;
86ade44c 2345 __news += 2;
86ade44c
BK
2346 }
2347 else if (__testsign)
2348 {
a3aff86a 2349 __news[0] = __olds[0];
5b577977 2350 __mod = 1;
86ade44c 2351 ++__news;
86ade44c 2352 }
5b577977 2353 // else Padding first.
86ade44c 2354 }
e4f7d0a1
PC
2355 _Traits::assign(__news, __plen, __fill);
2356 _Traits::copy(__news + __plen, const_cast<_CharT*>(__olds + __mod),
2357 __oldlen - __mod);
86ade44c
BK
2358 }
2359
47f62b27
PC
2360 bool
2361 __verify_grouping(const char* __grouping, size_t __grouping_size,
2362 const string& __grouping_tmp)
230377dc
DA
2363 {
2364 const size_t __n = __grouping_tmp.size() - 1;
2365 const size_t __min = std::min(__n, __grouping_size - 1);
2366 size_t __i = __n;
2367 bool __test = true;
2368
2369 // Parsed number groupings have to match the
2370 // numpunct::grouping string exactly, starting at the
2371 // right-most point of the parsed sequence of elements ...
2372 for (size_t __j = 0; __j < __min && __test; --__i, ++__j)
2373 __test = __grouping_tmp[__i] == __grouping[__j];
2374 for (; __i && __test; --__i)
2375 __test = __grouping_tmp[__i] == __grouping[__min];
2376 // ... but the last parsed grouping can be <= numpunct
2377 // grouping.
2378 __test &= __grouping_tmp[0] <= __grouping[__min];
2379 return __test;
2380 }
1ab65677 2381
1ab65677
BK
2382 template<typename _CharT>
2383 _CharT*
47f62b27
PC
2384 __add_grouping(_CharT* __s, _CharT __sep,
2385 const char* __gbeg, size_t __gsize,
1ab65677 2386 const _CharT* __first, const _CharT* __last)
bf058d22
PC
2387 {
2388 if (__last - __first > *__gbeg)
2389 {
47f62b27 2390 const bool __bump = __gsize != 1;
bf058d22 2391 __s = std::__add_grouping(__s, __sep, __gbeg + __bump,
47f62b27
PC
2392 __gsize - __bump, __first,
2393 __last - *__gbeg);
bf058d22
PC
2394 __first = __last - *__gbeg;
2395 *__s++ = __sep;
2396 }
2397 do
2398 *__s++ = *__first++;
2399 while (__first != __last);
2400 return __s;
2401 }
a32e3c09
BK
2402
2403 // Inhibit implicit instantiations for required instantiations,
ed6814f7 2404 // which are defined via explicit instantiations elsewhere.
a32e3c09 2405 // NB: This syntax is a GNU extension.
3d7c150e 2406#if _GLIBCXX_EXTERN_TEMPLATE
a32e3c09
BK
2407 extern template class moneypunct<char, false>;
2408 extern template class moneypunct<char, true>;
2409 extern template class moneypunct_byname<char, false>;
2410 extern template class moneypunct_byname<char, true>;
41b4d44b
BK
2411 extern template class money_get<char>;
2412 extern template class money_put<char>;
a32e3c09
BK
2413 extern template class numpunct<char>;
2414 extern template class numpunct_byname<char>;
41b4d44b 2415 extern template class num_get<char>;
ed6814f7 2416 extern template class num_put<char>;
a32e3c09 2417 extern template class __timepunct<char>;
41b4d44b
BK
2418 extern template class time_put<char>;
2419 extern template class time_put_byname<char>;
2420 extern template class time_get<char>;
2421 extern template class time_get_byname<char>;
a32e3c09
BK
2422 extern template class messages<char>;
2423 extern template class messages_byname<char>;
a32e3c09 2424 extern template class ctype_byname<char>;
a32e3c09 2425 extern template class codecvt_byname<char, char, mbstate_t>;
a32e3c09
BK
2426 extern template class collate<char>;
2427 extern template class collate_byname<char>;
ea0c0b6e 2428
41b4d44b 2429 extern template
ed6814f7 2430 const codecvt<char, char, mbstate_t>&
41b4d44b
BK
2431 use_facet<codecvt<char, char, mbstate_t> >(const locale&);
2432
2433 extern template
ed6814f7 2434 const collate<char>&
41b4d44b
BK
2435 use_facet<collate<char> >(const locale&);
2436
2437 extern template
ed6814f7 2438 const numpunct<char>&
41b4d44b
BK
2439 use_facet<numpunct<char> >(const locale&);
2440
ed6814f7
BI
2441 extern template
2442 const num_put<char>&
41b4d44b
BK
2443 use_facet<num_put<char> >(const locale&);
2444
ed6814f7
BI
2445 extern template
2446 const num_get<char>&
41b4d44b
BK
2447 use_facet<num_get<char> >(const locale&);
2448
2449 extern template
ed6814f7 2450 const moneypunct<char, true>&
41b4d44b
BK
2451 use_facet<moneypunct<char, true> >(const locale&);
2452
2453 extern template
ed6814f7 2454 const moneypunct<char, false>&
41b4d44b
BK
2455 use_facet<moneypunct<char, false> >(const locale&);
2456
ed6814f7
BI
2457 extern template
2458 const money_put<char>&
41b4d44b
BK
2459 use_facet<money_put<char> >(const locale&);
2460
ed6814f7
BI
2461 extern template
2462 const money_get<char>&
41b4d44b
BK
2463 use_facet<money_get<char> >(const locale&);
2464
2465 extern template
ed6814f7 2466 const __timepunct<char>&
41b4d44b
BK
2467 use_facet<__timepunct<char> >(const locale&);
2468
ed6814f7
BI
2469 extern template
2470 const time_put<char>&
41b4d44b
BK
2471 use_facet<time_put<char> >(const locale&);
2472
ed6814f7
BI
2473 extern template
2474 const time_get<char>&
41b4d44b
BK
2475 use_facet<time_get<char> >(const locale&);
2476
ed6814f7
BI
2477 extern template
2478 const messages<char>&
41b4d44b
BK
2479 use_facet<messages<char> >(const locale&);
2480
ed6814f7 2481 extern template
41b4d44b
BK
2482 bool
2483 has_facet<ctype<char> >(const locale&);
2484
ed6814f7 2485 extern template
41b4d44b
BK
2486 bool
2487 has_facet<codecvt<char, char, mbstate_t> >(const locale&);
2488
ed6814f7 2489 extern template
41b4d44b
BK
2490 bool
2491 has_facet<collate<char> >(const locale&);
2492
ed6814f7 2493 extern template
41b4d44b
BK
2494 bool
2495 has_facet<numpunct<char> >(const locale&);
a32e3c09 2496
ed6814f7 2497 extern template
41b4d44b
BK
2498 bool
2499 has_facet<num_put<char> >(const locale&);
a32e3c09 2500
ed6814f7 2501 extern template
41b4d44b
BK
2502 bool
2503 has_facet<num_get<char> >(const locale&);
a32e3c09 2504
ed6814f7 2505 extern template
41b4d44b
BK
2506 bool
2507 has_facet<moneypunct<char> >(const locale&);
2508
ed6814f7 2509 extern template
41b4d44b
BK
2510 bool
2511 has_facet<money_put<char> >(const locale&);
2512
ed6814f7 2513 extern template
41b4d44b
BK
2514 bool
2515 has_facet<money_get<char> >(const locale&);
2516
ed6814f7 2517 extern template
41b4d44b
BK
2518 bool
2519 has_facet<__timepunct<char> >(const locale&);
2520
ed6814f7 2521 extern template
41b4d44b
BK
2522 bool
2523 has_facet<time_put<char> >(const locale&);
2524
ed6814f7 2525 extern template
41b4d44b
BK
2526 bool
2527 has_facet<time_get<char> >(const locale&);
2528
ed6814f7 2529 extern template
41b4d44b
BK
2530 bool
2531 has_facet<messages<char> >(const locale&);
2532
3d7c150e 2533#ifdef _GLIBCXX_USE_WCHAR_T
5112ae3a
BK
2534 extern template class moneypunct<wchar_t, false>;
2535 extern template class moneypunct<wchar_t, true>;
2536 extern template class moneypunct_byname<wchar_t, false>;
2537 extern template class moneypunct_byname<wchar_t, true>;
2538 extern template class money_get<wchar_t>;
2539 extern template class money_put<wchar_t>;
2540 extern template class numpunct<wchar_t>;
2541 extern template class numpunct_byname<wchar_t>;
2542 extern template class num_get<wchar_t>;
2543 extern template class num_put<wchar_t>;
2544 extern template class __timepunct<wchar_t>;
2545 extern template class time_put<wchar_t>;
2546 extern template class time_put_byname<wchar_t>;
2547 extern template class time_get<wchar_t>;
2548 extern template class time_get_byname<wchar_t>;
2549 extern template class messages<wchar_t>;
2550 extern template class messages_byname<wchar_t>;
2551 extern template class ctype_byname<wchar_t>;
2552 extern template class codecvt_byname<wchar_t, char, mbstate_t>;
2553 extern template class collate<wchar_t>;
2554 extern template class collate_byname<wchar_t>;
2555
2556 extern template
ed6814f7 2557 const codecvt<wchar_t, char, mbstate_t>&
5112ae3a
BK
2558 use_facet<codecvt<wchar_t, char, mbstate_t> >(locale const&);
2559
2560 extern template
ed6814f7 2561 const collate<wchar_t>&
5112ae3a
BK
2562 use_facet<collate<wchar_t> >(const locale&);
2563
2564 extern template
ed6814f7 2565 const numpunct<wchar_t>&
5112ae3a
BK
2566 use_facet<numpunct<wchar_t> >(const locale&);
2567
ed6814f7
BI
2568 extern template
2569 const num_put<wchar_t>&
5112ae3a
BK
2570 use_facet<num_put<wchar_t> >(const locale&);
2571
ed6814f7
BI
2572 extern template
2573 const num_get<wchar_t>&
5112ae3a
BK
2574 use_facet<num_get<wchar_t> >(const locale&);
2575
2576 extern template
ed6814f7 2577 const moneypunct<wchar_t, true>&
5112ae3a
BK
2578 use_facet<moneypunct<wchar_t, true> >(const locale&);
2579
2580 extern template
ed6814f7 2581 const moneypunct<wchar_t, false>&
5112ae3a 2582 use_facet<moneypunct<wchar_t, false> >(const locale&);
ed6814f7
BI
2583
2584 extern template
2585 const money_put<wchar_t>&
5112ae3a
BK
2586 use_facet<money_put<wchar_t> >(const locale&);
2587
ed6814f7
BI
2588 extern template
2589 const money_get<wchar_t>&
5112ae3a
BK
2590 use_facet<money_get<wchar_t> >(const locale&);
2591
2592 extern template
ed6814f7 2593 const __timepunct<wchar_t>&
5112ae3a
BK
2594 use_facet<__timepunct<wchar_t> >(const locale&);
2595
ed6814f7
BI
2596 extern template
2597 const time_put<wchar_t>&
5112ae3a
BK
2598 use_facet<time_put<wchar_t> >(const locale&);
2599
ed6814f7
BI
2600 extern template
2601 const time_get<wchar_t>&
5112ae3a
BK
2602 use_facet<time_get<wchar_t> >(const locale&);
2603
ed6814f7
BI
2604 extern template
2605 const messages<wchar_t>&
5112ae3a
BK
2606 use_facet<messages<wchar_t> >(const locale&);
2607
ed6814f7 2608 extern template
41b4d44b
BK
2609 bool
2610 has_facet<ctype<wchar_t> >(const locale&);
2611
ed6814f7 2612 extern template
41b4d44b
BK
2613 bool
2614 has_facet<codecvt<wchar_t, char, mbstate_t> >(const locale&);
2615
ed6814f7 2616 extern template
41b4d44b
BK
2617 bool
2618 has_facet<collate<wchar_t> >(const locale&);
2619
ed6814f7 2620 extern template
41b4d44b
BK
2621 bool
2622 has_facet<numpunct<wchar_t> >(const locale&);
2623
ed6814f7 2624 extern template
41b4d44b
BK
2625 bool
2626 has_facet<num_put<wchar_t> >(const locale&);
2627
ed6814f7 2628 extern template
41b4d44b
BK
2629 bool
2630 has_facet<num_get<wchar_t> >(const locale&);
2631
ed6814f7 2632 extern template
41b4d44b
BK
2633 bool
2634 has_facet<moneypunct<wchar_t> >(const locale&);
2635
ed6814f7 2636 extern template
41b4d44b
BK
2637 bool
2638 has_facet<money_put<wchar_t> >(const locale&);
2639
ed6814f7 2640 extern template
41b4d44b
BK
2641 bool
2642 has_facet<money_get<wchar_t> >(const locale&);
2643
ed6814f7 2644 extern template
41b4d44b
BK
2645 bool
2646 has_facet<__timepunct<wchar_t> >(const locale&);
2647
ed6814f7 2648 extern template
41b4d44b
BK
2649 bool
2650 has_facet<time_put<wchar_t> >(const locale&);
2651
ed6814f7 2652 extern template
41b4d44b
BK
2653 bool
2654 has_facet<time_get<wchar_t> >(const locale&);
2655
ed6814f7 2656 extern template
41b4d44b
BK
2657 bool
2658 has_facet<messages<wchar_t> >(const locale&);
5112ae3a 2659#endif
1bc8b0ad 2660#endif
41b4d44b
BK
2661} // namespace std
2662
2663#endif