]>
Commit | Line | Data |
---|---|---|
725dc051 BK |
1 | // Locale support -*- C++ -*- |
2 | ||
0214010c | 3 | // Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. |
725dc051 BK |
4 | // |
5 | // This file is part of the GNU ISO C++ Library. This library is free | |
6 | // software; you can redistribute it and/or modify it under the | |
7 | // terms of the GNU General Public License as published by the | |
8 | // Free Software Foundation; either version 2, or (at your option) | |
9 | // any later version. | |
10 | ||
11 | // This library is distributed in the hope that it will be useful, | |
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | // GNU General Public License for more details. | |
15 | ||
16 | // You should have received a copy of the GNU General Public License along | |
17 | // with this library; see the file COPYING. If not, write to the Free | |
18 | // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, | |
19 | // USA. | |
20 | ||
21 | // As a special exception, you may use this file as part of a free software | |
22 | // library without restriction. Specifically, if other files instantiate | |
23 | // templates or use macros or inline functions from this file, or you compile | |
24 | // this file and link it with other files to produce an executable, this | |
25 | // file does not by itself cause the resulting executable to be covered by | |
26 | // the GNU General Public License. This exception does not however | |
27 | // invalidate any other reasons why the executable file might be covered by | |
28 | // the GNU General Public License. | |
29 | ||
30 | // Warning: this file is not meant for user inclusion. Use <locale>. | |
31 | ||
32 | #ifndef _CPP_BITS_LOCFACETS_TCC | |
33 | #define _CPP_BITS_LOCFACETS_TCC 1 | |
34 | ||
35 | #include <bits/std_cerrno.h> | |
dfb1d76f | 36 | #include <bits/std_clocale.h> // For localeconv |
725dc051 BK |
37 | #include <bits/std_cstdlib.h> // For strof, strtold |
38 | #include <bits/std_limits.h> // For numeric_limits | |
39 | #include <bits/std_memory.h> // For auto_ptr | |
40 | #include <bits/sbuf_iter.h> // For streambuf_iterators | |
41 | #include <bits/std_cctype.h> // For isspace | |
0214010c | 42 | #include <typeinfo> // For bad_cast |
725dc051 BK |
43 | #include <bits/std_vector.h> |
44 | ||
0214010c | 45 | |
725dc051 BK |
46 | namespace std |
47 | { | |
48 | template<typename _Facet> | |
49 | locale | |
50 | locale::combine(const locale& __other) | |
51 | { | |
52 | locale __copy(*this); | |
53 | __copy._M_impl->_M_replace_facet(__other._M_impl, &_Facet::id); | |
725dc051 BK |
54 | return __copy; |
55 | } | |
56 | ||
57 | template<typename _CharT, typename _Traits, typename _Alloc> | |
58 | bool | |
59 | locale::operator()(const basic_string<_CharT, _Traits, _Alloc>& __s1, | |
60 | const basic_string<_CharT, _Traits, _Alloc>& __s2) const | |
61 | { | |
725dc051 BK |
62 | typedef std::collate<_CharT> __collate_type; |
63 | const __collate_type* __fcoll = &use_facet<__collate_type>(*this); | |
64 | return (__fcoll->compare(__s1.data(), __s1.data() + __s1.length(), | |
65 | __s2.data(), __s2.data() + __s2.length()) < 0); | |
66 | } | |
67 | ||
68 | template<typename _Facet> | |
69 | const _Facet& | |
70 | use_facet(const locale& __loc) | |
71 | { | |
72 | typedef locale::_Impl::__vec_facet __vec_facet; | |
0214010c | 73 | locale::id& __id = _Facet::id; |
725dc051 BK |
74 | size_t __i = __id._M_index; |
75 | __vec_facet* __facet = __loc._M_impl->_M_facets; | |
0214010c BK |
76 | const locale::facet* __fp = (*__facet)[__i]; |
77 | if (__fp == 0 || __i >= __facet->size()) | |
78 | throw bad_cast(); | |
725dc051 BK |
79 | return static_cast<const _Facet&>(*__fp); |
80 | } | |
81 | ||
82 | template<typename _Facet> | |
83 | bool | |
84 | has_facet(const locale& __loc) throw() | |
85 | { | |
86 | typedef locale::_Impl::__vec_facet __vec_facet; | |
0214010c | 87 | locale::id& __id = _Facet::id; |
725dc051 BK |
88 | size_t __i = __id._M_index; |
89 | __vec_facet* __facet = __loc._M_impl->_M_facets; | |
90 | return (__i < __facet->size() && (*__facet)[__i] != 0); | |
91 | } | |
92 | ||
93 | // __match_parallel | |
94 | // matches input __s against a set of __ntargs strings in __targets, | |
95 | // placing in __matches a vector of indices into __targets which | |
96 | // match, and in __remain the number of such matches. If it hits | |
97 | // end of sequence before it minimizes the set, sets __eof. | |
98 | // Empty strings are never matched. | |
99 | template<typename _InIter, typename _CharT> | |
100 | _InIter | |
101 | __match_parallel(_InIter __s, _InIter __end, int __ntargs, | |
102 | const basic_string<_CharT>* __targets, | |
103 | int* __matches, int& __remain, bool& __eof) | |
104 | { | |
105 | typedef basic_string<_CharT> __string_type; | |
106 | __eof = false; | |
107 | for (int __ti = 0; __ti < __ntargs; ++__ti) | |
108 | __matches[__ti] = __ti; | |
109 | __remain = __ntargs; | |
110 | size_t __pos = 0; | |
111 | do | |
112 | { | |
113 | { | |
114 | int __ti = 0; | |
115 | for (;__ti < __remain && | |
116 | __pos == __targets[__matches[__ti]].size(); ++__ti) | |
117 | { } | |
118 | if (__ti == __remain) | |
119 | { | |
120 | if (__pos == 0) __remain = 0; | |
121 | return __s; | |
122 | } | |
123 | } | |
124 | if (__s == __end) | |
125 | __eof = true; | |
126 | bool __matched = false; | |
127 | for (int __ti = 0; __ti < __remain; ) | |
128 | { | |
129 | const __string_type& __target = __targets[__matches[__ti]]; | |
130 | if (__pos < __target.size()) | |
131 | { | |
132 | if (__eof || __target[__pos] != *__s) | |
133 | { | |
134 | __matches[__ti] = __matches[--__remain]; | |
135 | continue; | |
136 | } | |
137 | __matched = true; | |
138 | } | |
139 | ++__ti; | |
140 | } | |
141 | if (__matched) | |
142 | { | |
143 | ++__s; | |
144 | ++__pos; | |
145 | } | |
146 | for (int __ti = 0; __ti < __remain;) | |
147 | { | |
148 | if (__pos > __targets[__matches[__ti]].size()) | |
149 | { | |
150 | __matches[__ti] = __matches[--__remain]; | |
151 | continue; | |
152 | } | |
153 | ++__ti; | |
154 | } | |
155 | } | |
156 | while (__remain); | |
157 | return __s; | |
158 | } | |
159 | ||
725dc051 BK |
160 | template<typename _CharT> |
161 | _Format_cache<_CharT>::_Format_cache() | |
162 | : _M_valid(true), _M_use_grouping(false) | |
163 | { } | |
164 | ||
165 | template<> | |
166 | _Format_cache<char>::_Format_cache(); | |
167 | ||
168 | template<> | |
169 | _Format_cache<wchar_t>::_Format_cache(); | |
170 | ||
171 | template<typename _CharT> | |
172 | void | |
173 | _Format_cache<_CharT>::_M_populate(ios_base& __io) | |
174 | { | |
175 | locale __loc = __io.getloc (); | |
176 | numpunct<_CharT> const& __np = use_facet<numpunct<_CharT> >(__loc); | |
177 | _M_truename = __np.truename(); | |
178 | _M_falsename = __np.falsename(); | |
179 | _M_thousands_sep = __np.thousands_sep(); | |
180 | _M_decimal_point = __np.decimal_point(); | |
181 | _M_grouping = __np.grouping(); | |
182 | _M_use_grouping = _M_grouping.size() != 0 && _M_grouping.data()[0] != 0; | |
183 | _M_valid = true; | |
184 | } | |
185 | ||
186 | // This function is always called via a pointer installed in | |
187 | // an ios_base by ios_base::register_callback. | |
188 | template<typename _CharT> | |
189 | void | |
190 | _Format_cache<_CharT>:: | |
191 | _S_callback(ios_base::event __ev, ios_base& __ios, int __ix) throw() | |
192 | { | |
193 | void*& __p = __ios.pword(__ix); | |
194 | switch (__ev) | |
195 | { | |
196 | case ios_base::erase_event: | |
197 | delete static_cast<_Format_cache<_CharT>*> (__p); __p = 0; | |
198 | break; | |
199 | case ios_base::copyfmt_event: | |
200 | // If just stored zero, the callback would get registered again. | |
201 | try { | |
202 | __p = new _Format_cache<_CharT>; | |
203 | } | |
204 | catch(...) { | |
205 | } | |
206 | break; | |
207 | case ios_base::imbue_event: | |
208 | static_cast<_Format_cache<_CharT>*>(__p)->_M_valid = false; | |
209 | break; | |
210 | } | |
211 | } | |
212 | ||
213 | template<typename _CharT> | |
214 | _Format_cache<_CharT>* | |
215 | _Format_cache<_CharT>::_S_get(ios_base& __ios) | |
216 | { | |
217 | if (!_S_pword_ix) | |
218 | _S_pword_ix = ios_base::xalloc(); // XXX MT | |
219 | void*& __p = __ios.pword(_S_pword_ix); | |
220 | ||
221 | // XXX What if pword fails? must check failbit, throw. | |
222 | if (__p == 0) // XXX MT? maybe sentry takes care of it | |
223 | { | |
224 | auto_ptr<_Format_cache<_CharT> > __ap(new _Format_cache<_CharT>); | |
225 | __ios.register_callback(&_Format_cache<_CharT>::_S_callback, | |
226 | _S_pword_ix); | |
227 | __p = __ap.release(); | |
228 | } | |
229 | _Format_cache<_CharT>* __ncp = static_cast<_Format_cache<_CharT>*>(__p); | |
230 | if (!__ncp->_M_valid) | |
231 | __ncp->_M_populate(__ios); | |
232 | ||
233 | return __ncp; | |
234 | } | |
235 | ||
725dc051 BK |
236 | // This member function takes an (w)istreambuf_iterator object and |
237 | // parses it into a generic char array suitable for parsing with | |
238 | // strto[l,ll,f,d]. The thought was to encapsulate the conversion | |
239 | // into this one function, and thus the num_get::do_get member | |
240 | // functions can just adjust for the type of the overloaded | |
241 | // argument and process the char array returned from _M_extract. | |
242 | // Other things were also considered, including a fused | |
243 | // multiply-add loop that would obviate the need for any call to | |
244 | // strto... at all: however, it would b e a bit of a pain, because | |
245 | // you'd have to be able to return either floating or integral | |
246 | // types, etc etc. The current approach seems to be smack dab in | |
247 | // the middle between an unoptimized approach using sscanf, and | |
248 | // some kind of hyper-optimized approach alluded to above. | |
249 | ||
250 | // XXX | |
251 | // Need to do partial specialization to account for differences | |
252 | // between character sets. For char, this is pretty | |
253 | // straightforward, but for wchar_t, the conversion to a plain-jane | |
254 | // char type is a bit more involved. | |
255 | template<typename _CharT, typename _InIter> | |
256 | void | |
257 | num_get<_CharT, _InIter>:: | |
258 | _M_extract(_InIter /*__beg*/, _InIter /*__end*/, ios_base& /*__io*/, | |
259 | ios_base::iostate& /*__err*/, char* /*__xtrc*/, | |
260 | int& /*__base*/, bool /*__fp*/) const | |
261 | { | |
262 | // XXX Not currently done: need to expand upon char version below. | |
263 | } | |
264 | ||
265 | template<> | |
266 | void | |
267 | num_get<char, istreambuf_iterator<char> >:: | |
268 | _M_extract(istreambuf_iterator<char> __beg, | |
269 | istreambuf_iterator<char> __end, ios_base& __io, | |
270 | ios_base::iostate& __err, char* __xtrc, int& __base, | |
271 | bool __fp) const; | |
272 | ||
273 | #ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS | |
274 | // NB: This is an unresolved library defect #17 | |
275 | template<typename _CharT, typename _InIter> | |
276 | _InIter | |
277 | num_get<_CharT, _InIter>:: | |
278 | do_get(iter_type __beg, iter_type __end, ios_base& __io, | |
279 | ios_base::iostate& __err, bool& __v) const | |
280 | { | |
281 | // Parse bool values as long | |
282 | if (!(__io.flags() & ios_base::boolalpha)) | |
283 | { | |
284 | // NB: We can't just call do_get(long) here, as it might | |
285 | // refer to a derived class. | |
286 | ||
287 | // Stage 1: extract and determine the conversion specifier. | |
288 | // Assuming leading zeros eliminated, thus the size of 32 for | |
289 | // integral types. | |
290 | char __xtrc[32] = {'\0'}; | |
291 | int __base; | |
292 | _M_extract(__beg, __end, __io, __err, __xtrc, __base, false); | |
293 | ||
294 | // Stage 2: convert and store results. | |
295 | char* __sanity; | |
296 | errno = 0; | |
297 | long __l = strtol(__xtrc, &__sanity, __base); | |
298 | if (!(__err & ios_base::failbit) | |
299 | && __l <= 1 | |
300 | && __sanity != __xtrc && *__sanity == '\0' && errno == 0) | |
301 | __v = __l; | |
302 | else | |
303 | __err |= ios_base::failbit; | |
304 | } | |
305 | ||
306 | // Parse bool values as alphanumeric | |
307 | else | |
308 | { | |
309 | typedef _Format_cache<char_type> __fcache_type; | |
310 | __fcache_type* __fmt = __fcache_type::_S_get(__io); | |
311 | const char_type* __true = __fmt->_M_truename.c_str(); | |
312 | const char_type* __false = __fmt->_M_falsename.c_str(); | |
313 | const size_t __truelen = __traits_type::length(__true) - 1; | |
314 | const size_t __falselen = __traits_type::length(__false) - 1; | |
315 | ||
316 | for (size_t __pos = 0; __beg != __end; ++__pos) | |
317 | { | |
318 | char_type __c = *__beg++; | |
319 | bool __testf = __c == __false[__pos]; | |
320 | bool __testt = __c == __true[__pos]; | |
321 | if (!(__testf || __testt)) | |
322 | { | |
323 | __err |= ios_base::failbit; | |
324 | break; | |
325 | } | |
326 | else if (__testf && __pos == __falselen) | |
327 | { | |
328 | __v = 0; | |
329 | break; | |
330 | } | |
331 | else if (__testt && __pos == __truelen) | |
332 | { | |
333 | __v = 1; | |
334 | break; | |
335 | } | |
336 | } | |
337 | if (__beg == __end) | |
338 | __err |= ios_base::eofbit; | |
339 | } | |
340 | ||
341 | return __beg; | |
342 | } | |
343 | #endif | |
344 | ||
345 | #ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS | |
346 | template<typename _CharT, typename _InIter> | |
347 | _InIter | |
348 | num_get<_CharT, _InIter>:: | |
349 | do_get(iter_type __beg, iter_type __end, ios_base& __io, | |
350 | ios_base::iostate& __err, short& __v) const | |
351 | { | |
352 | // Stage 1: extract and determine the conversion specifier. | |
353 | // Assuming leading zeros eliminated, thus the size of 32 for | |
354 | // integral types. | |
355 | char __xtrc[32]= {'\0'}; | |
356 | int __base; | |
357 | _M_extract(__beg, __end, __io, __err, __xtrc, __base, false); | |
358 | ||
359 | // Stage 2: convert and store results. | |
360 | char* __sanity; | |
361 | errno = 0; | |
362 | long __l = strtol(__xtrc, &__sanity, __base); | |
363 | if (!(__err & ios_base::failbit) | |
364 | && __sanity != __xtrc && *__sanity == '\0' && errno == 0 | |
365 | && __l >= SHRT_MIN && __l <= SHRT_MAX) | |
366 | __v = static_cast<short>(__l); | |
367 | else | |
368 | __err |= ios_base::failbit; | |
369 | ||
370 | return __beg; | |
371 | } | |
372 | ||
373 | template<typename _CharT, typename _InIter> | |
374 | _InIter | |
375 | num_get<_CharT, _InIter>:: | |
376 | do_get(iter_type __beg, iter_type __end, ios_base& __io, | |
377 | ios_base::iostate& __err, int& __v) const | |
378 | { | |
379 | // Stage 1: extract and determine the conversion specifier. | |
380 | // Assuming leading zeros eliminated, thus the size of 32 for | |
381 | // integral types. | |
382 | char __xtrc[32] = {'\0'}; | |
383 | int __base; | |
384 | _M_extract(__beg, __end, __io, __err, __xtrc, __base, false); | |
385 | ||
386 | // Stage 2: convert and store results. | |
387 | char* __sanity; | |
388 | errno = 0; | |
389 | long __l = strtol(__xtrc, &__sanity, __base); | |
390 | if (!(__err & ios_base::failbit) | |
391 | && __sanity != __xtrc && *__sanity == '\0' && errno == 0 | |
392 | && __l >= INT_MIN && __l <= INT_MAX) | |
393 | __v = static_cast<int>(__l); | |
394 | else | |
395 | __err |= ios_base::failbit; | |
396 | ||
397 | return __beg; | |
398 | } | |
399 | #endif | |
400 | ||
401 | template<typename _CharT, typename _InIter> | |
402 | _InIter | |
403 | num_get<_CharT, _InIter>:: | |
404 | do_get(iter_type __beg, iter_type __end, ios_base& __io, | |
405 | ios_base::iostate& __err, long& __v) const | |
406 | { | |
407 | // Stage 1: extract and determine the conversion specifier. | |
408 | // Assuming leading zeros eliminated, thus the size of 32 for | |
409 | // integral types. | |
410 | char __xtrc[32]= {'\0'}; | |
411 | int __base; | |
412 | _M_extract(__beg, __end, __io, __err, __xtrc, __base, false); | |
413 | ||
414 | // Stage 2: convert and store results. | |
415 | char* __sanity; | |
416 | errno = 0; | |
417 | long __l = strtol(__xtrc, &__sanity, __base); | |
418 | if (!(__err & ios_base::failbit) | |
419 | && __sanity != __xtrc && *__sanity == '\0' && errno == 0) | |
420 | __v = __l; | |
421 | else | |
422 | __err |= ios_base::failbit; | |
423 | ||
424 | return __beg; | |
425 | } | |
426 | ||
427 | #ifdef _GLIBCPP_USE_LONG_LONG | |
428 | template<typename _CharT, typename _InIter> | |
429 | _InIter | |
430 | num_get<_CharT, _InIter>:: | |
431 | do_get(iter_type __beg, iter_type __end, ios_base& __io, | |
432 | ios_base::iostate& __err, long long& __v) const | |
433 | { | |
434 | // Stage 1: extract and determine the conversion specifier. | |
435 | // Assuming leading zeros eliminated, thus the size of 32 for | |
436 | // integral types. | |
437 | char __xtrc[32]= {'\0'}; | |
438 | int __base; | |
439 | _M_extract(__beg, __end, __io, __err, __xtrc, __base, false); | |
440 | ||
441 | // Stage 2: convert and store results. | |
442 | char* __sanity; | |
443 | errno = 0; | |
444 | long long __ll = strtoll(__xtrc, &__sanity, __base); | |
445 | if (!(__err & ios_base::failbit) | |
446 | && __sanity != __xtrc && *__sanity == '\0' && errno == 0) | |
447 | __v = __ll; | |
448 | else | |
449 | __err |= ios_base::failbit; | |
450 | ||
451 | return __beg; | |
452 | } | |
453 | #endif | |
454 | ||
455 | template<typename _CharT, typename _InIter> | |
456 | _InIter | |
457 | num_get<_CharT, _InIter>:: | |
458 | do_get(iter_type __beg, iter_type __end, ios_base& __io, | |
459 | ios_base::iostate& __err, unsigned short& __v) const | |
460 | { | |
461 | // Stage 1: extract and determine the conversion specifier. | |
462 | // Assuming leading zeros eliminated, thus the size of 32 for | |
463 | // integral types. | |
464 | char __xtrc[32]= {'\0'}; | |
465 | int __base; | |
466 | _M_extract(__beg, __end, __io, __err, __xtrc, __base, false); | |
467 | ||
468 | // Stage 2: convert and store results. | |
469 | char* __sanity; | |
470 | errno = 0; | |
471 | unsigned long __ul = strtoul(__xtrc, &__sanity, __base); | |
472 | if (!(__err & ios_base::failbit) | |
473 | && __sanity != __xtrc && *__sanity == '\0' && errno == 0 | |
474 | && __ul <= USHRT_MAX) | |
475 | __v = static_cast<unsigned short>(__ul); | |
476 | else | |
477 | __err |= ios_base::failbit; | |
478 | ||
479 | return __beg; | |
480 | } | |
481 | ||
482 | template<typename _CharT, typename _InIter> | |
483 | _InIter | |
484 | num_get<_CharT, _InIter>:: | |
485 | do_get(iter_type __beg, iter_type __end, ios_base& __io, | |
486 | ios_base::iostate& __err, unsigned int& __v) const | |
487 | { | |
488 | // Stage 1: extract and determine the conversion specifier. | |
489 | // Assuming leading zeros eliminated, thus the size of 32 for | |
490 | // integral types. | |
491 | char __xtrc[32]= {'\0'}; | |
492 | int __base; | |
493 | _M_extract(__beg, __end, __io, __err, __xtrc, __base, false); | |
494 | ||
495 | // Stage 2: convert and store results. | |
496 | char* __sanity; | |
497 | errno = 0; | |
498 | unsigned long __ul = strtoul(__xtrc, &__sanity, __base); | |
499 | if (!(__err & ios_base::failbit) | |
500 | && __sanity != __xtrc && *__sanity == '\0' && errno == 0 | |
501 | && __ul <= UINT_MAX) | |
502 | __v = static_cast<unsigned int>(__ul); | |
503 | else | |
504 | __err |= ios_base::failbit; | |
505 | ||
506 | return __beg; | |
507 | } | |
508 | ||
509 | template<typename _CharT, typename _InIter> | |
510 | _InIter | |
511 | num_get<_CharT, _InIter>:: | |
512 | do_get(iter_type __beg, iter_type __end, ios_base& __io, | |
513 | ios_base::iostate& __err, unsigned long& __v) const | |
514 | { | |
515 | // Stage 1: extract and determine the conversion specifier. | |
516 | // Assuming leading zeros eliminated, thus the size of 32 for | |
517 | // integral types. | |
518 | char __xtrc[32] = {'\0'}; | |
519 | int __base; | |
520 | _M_extract(__beg, __end, __io, __err, __xtrc, __base, false); | |
521 | ||
522 | // Stage 2: convert and store results. | |
523 | char* __sanity; | |
524 | errno = 0; | |
525 | unsigned long __ul = strtoul(__xtrc, &__sanity, __base); | |
526 | if (!(__err & ios_base::failbit) | |
527 | && __sanity != __xtrc && *__sanity == '\0' && errno == 0) | |
528 | __v = __ul; | |
529 | else | |
530 | __err |= ios_base::failbit; | |
531 | ||
532 | return __beg; | |
533 | } | |
534 | ||
535 | #ifdef _GLIBCPP_USE_LONG_LONG | |
536 | template<typename _CharT, typename _InIter> | |
537 | _InIter | |
538 | num_get<_CharT, _InIter>:: | |
539 | do_get(iter_type __beg, iter_type __end, ios_base& __io, | |
540 | ios_base::iostate& __err, unsigned long long& __v) const | |
541 | { | |
542 | // Stage 1: extract and determine the conversion specifier. | |
543 | // Assuming leading zeros eliminated, thus the size of 32 for | |
544 | // integral types. | |
545 | char __xtrc[32]= {'\0'}; | |
546 | int __base; | |
547 | _M_extract(__beg, __end, __io, __err, __xtrc, __base, false); | |
548 | ||
549 | // Stage 2: convert and store results. | |
550 | char* __sanity; | |
551 | errno = 0; | |
552 | unsigned long long __ull = strtoull(__xtrc, &__sanity, __base); | |
553 | if (!(__err & ios_base::failbit) | |
554 | && __sanity != __xtrc && *__sanity == '\0' && errno == 0) | |
555 | __v = __ull; | |
556 | else | |
557 | __err |= ios_base::failbit; | |
558 | ||
559 | return __beg; | |
560 | } | |
561 | #endif | |
562 | ||
563 | template<typename _CharT, typename _InIter> | |
564 | _InIter | |
565 | num_get<_CharT, _InIter>:: | |
566 | do_get(iter_type __beg, iter_type __end, ios_base& __io, | |
567 | ios_base::iostate& __err, float& __v) const | |
568 | { | |
569 | // Stage 1: extract and determine the conversion specifier. | |
570 | // Assuming leading zeros eliminated, thus the size of 256 for | |
571 | // floating-point types. | |
572 | char __xtrc[32]= {'\0'}; | |
573 | int __base; | |
574 | _M_extract(__beg, __end, __io, __err, __xtrc, __base, true); | |
575 | ||
576 | // Stage 2: convert and store results. | |
577 | char* __sanity; | |
578 | errno = 0; | |
579 | #ifdef _GLIBCPP_HAVE_STRTOF | |
580 | float __f = strtof(__xtrc, &__sanity); | |
581 | #else | |
582 | float __f = static_cast<float>(strtod(__xtrc, &__sanity)); | |
583 | #endif | |
584 | if (!(__err & ios_base::failbit) | |
585 | && __sanity != __xtrc && *__sanity == '\0' && errno == 0) | |
586 | __v = __f; | |
587 | else | |
588 | __err |= ios_base::failbit; | |
589 | ||
590 | return __beg; | |
591 | } | |
592 | ||
593 | template<typename _CharT, typename _InIter> | |
594 | _InIter | |
595 | num_get<_CharT, _InIter>:: | |
596 | do_get(iter_type __beg, iter_type __end, ios_base& __io, | |
597 | ios_base::iostate& __err, double& __v) const | |
598 | { | |
599 | // Stage 1: extract and determine the conversion specifier. | |
600 | // Assuming leading zeros eliminated, thus the size of 256 for | |
601 | // floating-point types. | |
602 | char __xtrc[32]= {'\0'}; | |
603 | int __base; | |
604 | _M_extract(__beg, __end, __io, __err, __xtrc, __base, true); | |
605 | ||
606 | // Stage 2: convert and store results. | |
607 | char* __sanity; | |
608 | errno = 0; | |
609 | double __d = strtod(__xtrc, &__sanity); | |
610 | if (!(__err & ios_base::failbit) | |
611 | && __sanity != __xtrc && *__sanity == '\0' && errno == 0) | |
612 | __v = __d; | |
613 | else | |
614 | __err |= ios_base::failbit; | |
615 | ||
616 | return __beg; | |
617 | } | |
618 | ||
619 | #if defined(_GLIBCPP_HAVE_STRTOLD) && !defined(__hpux) | |
620 | template<typename _CharT, typename _InIter> | |
621 | _InIter | |
622 | num_get<_CharT, _InIter>:: | |
623 | do_get(iter_type __beg, iter_type __end, ios_base& __io, | |
624 | ios_base::iostate& __err, long double& __v) const | |
625 | { | |
626 | // Stage 1: extract and determine the conversion specifier. | |
627 | // Assuming leading zeros eliminated, thus the size of 256 for | |
628 | // floating-point types. | |
629 | char __xtrc[32]= {'\0'}; | |
630 | int __base; | |
631 | _M_extract(__beg, __end, __io, __err, __xtrc, __base, true); | |
632 | ||
633 | // Stage 2: convert and store results. | |
634 | char* __sanity; | |
635 | errno = 0; | |
636 | long double __ld = strtold(__xtrc, &__sanity); | |
637 | if (!(__err & ios_base::failbit) | |
638 | && __sanity != __xtrc && *__sanity == '\0' && errno == 0) | |
639 | __v = __ld; | |
640 | else | |
641 | __err |= ios_base::failbit; | |
642 | ||
643 | return __beg; | |
644 | } | |
645 | #else | |
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, | |
650 | ios_base::iostate& __err, long double& __v) const | |
651 | { | |
652 | // Stage 1: extract | |
653 | char __xtrc[32]= {'\0'}; | |
654 | int __base; | |
655 | _M_extract(__beg, __end, __io, __err, __xtrc, __base, true); | |
656 | ||
657 | // Stage 2: determine a conversion specifier. | |
658 | ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield; | |
659 | const char* __conv; | |
660 | if (__basefield == ios_base::oct) | |
661 | __conv = "%Lo"; | |
662 | else if (__basefield == ios_base::hex) | |
663 | __conv = "%LX"; | |
664 | else if (__basefield == 0) | |
665 | __conv = "%Li"; | |
666 | else | |
667 | __conv = "%Lg"; | |
668 | ||
669 | // Stage 3: store results. | |
670 | long double __ld; | |
671 | int __p = sscanf(__xtrc, __conv, &__ld); | |
672 | if (__p | |
5af655cc LR |
673 | && static_cast<typename __traits_type::int_type>(__p) |
674 | != __traits_type::eof()) | |
725dc051 BK |
675 | __v = __ld; |
676 | else | |
677 | __err |= ios_base::failbit; | |
678 | ||
679 | return __beg; | |
680 | } | |
681 | #endif | |
682 | ||
683 | template<typename _CharT, typename _InIter> | |
684 | _InIter | |
685 | num_get<_CharT, _InIter>:: | |
686 | do_get(iter_type __beg, iter_type __end, ios_base& __io, | |
687 | ios_base::iostate& __err, void*& __v) const | |
688 | { | |
689 | // Prepare for hex formatted input | |
690 | typedef ios_base::fmtflags fmtflags; | |
691 | fmtflags __fmt = __io.flags(); | |
692 | fmtflags __fmtmask = ~(ios_base::showpos | ios_base::basefield | |
693 | | ios_base::uppercase | ios_base::internal); | |
694 | __io.flags(__fmt & __fmtmask | (ios_base::hex | ios_base::showbase)); | |
695 | ||
696 | // Stage 1: extract and determine the conversion specifier. | |
697 | // Assuming leading zeros eliminated, thus the size of 32 for | |
698 | // integral types. | |
699 | char __xtrc[32]= {'\0'}; | |
700 | int __base; | |
701 | _M_extract(__beg, __end, __io, __err, __xtrc, __base, false); | |
702 | ||
703 | // Stage 2: convert and store results. | |
704 | char* __sanity; | |
705 | errno = 0; | |
706 | void* __vp = reinterpret_cast<void*>(strtoul(__xtrc, &__sanity, __base)); | |
707 | if (!(__err & ios_base::failbit) | |
708 | && __sanity != __xtrc && *__sanity == '\0' && errno == 0) | |
709 | __v = __vp; | |
710 | else | |
711 | __err |= ios_base::failbit; | |
712 | ||
713 | // Reset from hex formatted input | |
714 | __io.flags(__fmt); | |
715 | return __beg; | |
716 | } | |
717 | ||
725dc051 BK |
718 | // _S_fill is specialized for ostreambuf_iterator, random access iterator. |
719 | template <typename _CharT, typename _OutIter> | |
720 | inline _OutIter | |
721 | _S_fill(_OutIter __s, _CharT __fill, int __padding); | |
722 | ||
723 | template <typename _CharT, typename _RaIter> | |
724 | _RaIter | |
725 | _S_fill(_RaIter __s, _CharT __fill, int __padding, | |
726 | random_access_iterator_tag) | |
727 | { | |
728 | fill_n(__s, __fill); | |
729 | return __s + __padding; | |
730 | } | |
731 | ||
732 | template <typename _CharT, typename _OutIter, typename _Tag> | |
733 | _OutIter | |
734 | _S_fill(_OutIter __s, _CharT __fill, int __padding, _Tag) | |
735 | { | |
736 | while (--__padding >= 0) { *__s = __fill; ++__s; } | |
737 | return __s; | |
738 | } | |
739 | ||
740 | template <typename _CharT, typename _OutIter> | |
741 | inline _OutIter | |
742 | _S_fill(_OutIter __s, _CharT __fill, int __padding) | |
743 | { | |
744 | return _S_fill(__s, __fill, __padding, | |
745 | iterator_traits<_OutIter>::iterator_category()); | |
746 | } | |
747 | ||
748 | template <typename _CharT, typename _OutIter> | |
749 | _OutIter | |
750 | _S_pad_numeric(_OutIter __s, ios_base::fmtflags /*__flags*/, | |
751 | _CharT /*__fill*/, int /*__width*/, | |
752 | _CharT const* /*__first*/, _CharT const* /*__middle*/, | |
753 | _CharT const* /*__last*/) | |
754 | { | |
755 | // XXX Not currently done: non streambuf_iterator | |
756 | return __s; | |
757 | } | |
758 | ||
759 | // Partial specialization for ostreambuf_iterator. | |
760 | template <typename _CharT> | |
761 | ostreambuf_iterator<_CharT> | |
762 | _S_pad_numeric(ostreambuf_iterator<_CharT> __s, ios_base::fmtflags __flags, | |
763 | _CharT __fill, int __width, _CharT const* __first, | |
764 | _CharT const* __middle, _CharT const* __last) | |
765 | { | |
766 | typedef ostreambuf_iterator<_CharT> __out_iter; | |
767 | int __padding = __width - (__last - __first); | |
768 | if (__padding < 0) | |
769 | __padding = 0; | |
770 | ios_base::fmtflags __aflags = __flags & ios_base::adjustfield; | |
771 | bool __testfield = __padding == 0 || __aflags == ios_base::left | |
772 | || __aflags == ios_base::internal; | |
773 | ||
774 | // This was needlessly complicated. | |
775 | if (__first != __middle) | |
776 | { | |
777 | if (!__testfield) | |
778 | { | |
779 | _S_fill(__s, __fill, __padding); | |
780 | __padding = 0; | |
781 | } | |
782 | copy(__first, __middle, __s); | |
783 | } | |
784 | __out_iter __s2 = __s; | |
785 | ||
786 | if (__padding && __aflags != ios_base::left) | |
787 | { | |
788 | _S_fill(__s2, __fill, __padding); | |
789 | __padding = 0; | |
790 | } | |
791 | __out_iter __s3 = copy(__middle, __last, __s2); | |
792 | if (__padding) | |
793 | _S_fill(__s3, __fill, __padding); | |
794 | return __s3; | |
795 | } | |
796 | ||
797 | template <typename _CharT, typename _OutIter> | |
798 | _OutIter | |
799 | num_put<_CharT, _OutIter>:: | |
800 | do_put(iter_type __s, ios_base& __io, char_type __fill, bool __v) const | |
801 | { | |
802 | const _Format_cache<_CharT>* __fmt = _Format_cache<_CharT>::_S_get(__io); | |
803 | ios_base::fmtflags __flags = __io.flags(); | |
804 | ||
805 | if ((__flags & ios_base::boolalpha) == 0) | |
806 | { | |
807 | unsigned long __uv = __v; | |
808 | return _S_format(__s, __io, __fill, false, __uv); | |
809 | } | |
810 | else | |
811 | { | |
812 | const char_type* __first; | |
813 | const char_type* __last; | |
814 | if (__v) | |
815 | { | |
816 | __first = __fmt->_M_truename.data(); | |
817 | __last = __first + __fmt->_M_truename.size(); | |
818 | } | |
819 | else | |
820 | { | |
821 | __first = __fmt->_M_falsename.data(); | |
822 | __last = __first + __fmt->_M_falsename.size(); | |
823 | } | |
824 | copy(__first, __last, __s); | |
825 | } | |
826 | return __s; | |
827 | } | |
828 | ||
829 | // _S_group_digits inserts "group separator" characters into an array | |
830 | // of characters. It's recursive, one iteration per group. It moves | |
831 | // the characters in the buffer this way: "xxxx12345" -> "12,345xxx". | |
832 | // Call this only with __grouping != __grend. | |
833 | template <typename _CharT> | |
834 | _CharT* | |
835 | _S_group_digits(_CharT* __s, _CharT __grsep, char const* __grouping, | |
836 | char const* __grend, _CharT const* __first, | |
837 | _CharT const* __last) | |
838 | { | |
839 | if (__last - __first > *__grouping) | |
840 | { | |
841 | __s = _S_group_digits(__s, __grsep, | |
842 | (__grouping + 1 == __grend ? __grouping : __grouping + 1), | |
843 | __grend, __first, __last - *__grouping); | |
844 | __first = __last - *__grouping; | |
845 | *__s++ = __grsep; | |
846 | } | |
847 | do | |
848 | { | |
849 | *__s++ = *__first++; | |
850 | } | |
851 | while (__first != __last); | |
852 | return __s; | |
853 | } | |
854 | ||
855 | template <typename _CharT, typename _OutIter, typename _ValueT> | |
856 | _OutIter | |
857 | _S_format(_OutIter __s, ios_base& __io, _CharT __fill, bool __neg, | |
858 | _ValueT __v) | |
859 | { | |
860 | // Leave room for "+/-," "0x," and commas. | |
861 | const long _M_room = numeric_limits<_ValueT>::digits10 * 2 + 4; | |
862 | _CharT __digits[_M_room]; | |
863 | _CharT* __front = __digits + _M_room; | |
864 | ios_base::fmtflags __flags = __io.flags(); | |
865 | const _Format_cache<_CharT>* __fmt = _Format_cache<_CharT>::_S_get(__io); | |
866 | char const* __table = __fmt->_S_literals + __fmt->_S_digits; | |
867 | ||
868 | ios_base::fmtflags __basefield = (__flags & __io.basefield); | |
869 | _CharT* __sign_end = __front; | |
870 | if (__basefield == ios_base::hex) | |
871 | { | |
872 | if (__flags & ios_base::uppercase) | |
873 | __table += 16; // use ABCDEF | |
874 | do | |
875 | *--__front = __table[__v & 15]; | |
876 | while ((__v >>= 4) != 0); | |
877 | __sign_end = __front; | |
878 | if (__flags & ios_base::showbase) | |
879 | { | |
880 | *--__front = __fmt->_S_literals[__fmt->_S_x + | |
881 | ((__flags & ios_base::uppercase) ? 1 : 0)]; | |
882 | *--__front = __table[0]; | |
883 | } | |
884 | } | |
885 | else if (__basefield == ios_base::oct) | |
886 | { | |
887 | do | |
888 | *--__front = __table[__v & 7]; | |
889 | while ((__v >>= 3) != 0); | |
890 | if (__flags & ios_base::showbase | |
891 | && static_cast<char>(*__front) != __table[0]) | |
892 | *--__front = __table[0]; | |
893 | __sign_end = __front; | |
894 | } | |
895 | else | |
896 | { | |
897 | // NB: This is _lots_ faster than using ldiv. | |
898 | do | |
899 | *--__front = __table[__v % 10]; | |
900 | while ((__v /= 10) != 0); | |
901 | __sign_end = __front; | |
902 | // NB: ios_base:hex || ios_base::oct assumed to be unsigned. | |
903 | if (__neg || (__flags & ios_base::showpos)) | |
904 | *--__front = __fmt->_S_literals[__fmt->_S_plus - __neg]; | |
905 | } | |
906 | ||
907 | // XXX should specialize! | |
908 | if (!__fmt->_M_use_grouping && !__io.width()) | |
909 | return copy(__front, __digits + _M_room, __s); | |
910 | ||
911 | if (!__fmt->_M_use_grouping) | |
912 | return _S_pad_numeric(__s, __flags, __fill, __io.width(0), | |
913 | __front, __sign_end, __digits + _M_room); | |
914 | ||
915 | _CharT* __p = __digits; | |
916 | while (__front < __sign_end) | |
917 | *__p++ = *__front++; | |
918 | const char* __gr = __fmt->_M_grouping.data(); | |
919 | __front = _S_group_digits(__p, __fmt->_M_thousands_sep, __gr, | |
920 | __gr + __fmt->_M_grouping.size(), __sign_end, __digits + _M_room); | |
921 | return _S_pad_numeric(__s, __flags, __fill, __io.width(0), | |
922 | __digits, __p, __front); | |
923 | } | |
924 | ||
925 | template <typename _CharT, typename _OutIter> | |
926 | _OutIter | |
927 | num_put<_CharT, _OutIter>:: | |
928 | do_put(iter_type __s, ios_base& __io, char_type __fill, long __v) const | |
929 | { | |
930 | unsigned long __uv = __v; | |
931 | bool __neg = false; | |
932 | if (__v < 0) | |
933 | { | |
934 | __neg = true; | |
935 | __uv = -__uv; | |
936 | } | |
937 | return _S_format(__s, __io, __fill, __neg, __uv); | |
938 | } | |
939 | ||
940 | template <typename _CharT, typename _OutIter> | |
941 | _OutIter | |
942 | num_put<_CharT, _OutIter>:: | |
943 | do_put(iter_type __s, ios_base& __io, char_type __fill, | |
944 | unsigned long __v) const | |
945 | { return _S_format(__s, __io, __fill, false, __v); } | |
946 | ||
947 | #ifdef _GLIBCPP_USE_LONG_LONG | |
948 | template <typename _CharT, typename _OutIter> | |
949 | _OutIter | |
950 | num_put<_CharT, _OutIter>:: | |
951 | do_put(iter_type __s, ios_base& __b, char_type __fill, long long __v) const | |
952 | { | |
953 | unsigned long long __uv = __v; | |
954 | bool __neg = false; | |
955 | if (__v < 0) | |
956 | { | |
957 | __neg = true; | |
958 | __uv = -__uv; | |
959 | } | |
960 | return _S_format(__s, __b, __fill, __neg, __uv); | |
961 | } | |
962 | ||
963 | template <typename _CharT, typename _OutIter> | |
964 | _OutIter | |
965 | num_put<_CharT, _OutIter>:: | |
966 | do_put(iter_type __s, ios_base& __io, char_type __fill, | |
967 | unsigned long long __v) const | |
968 | { return _S_format(__s, __io, __fill, false, __v); } | |
969 | #endif | |
970 | ||
971 | // Generic helper function | |
972 | template<typename _CharT, typename _OutIter> | |
973 | static _OutIter | |
974 | _S_output_float(_OutIter __s, ios_base& __io, _CharT __fill, | |
975 | const char* __sptr, size_t __slen) | |
976 | { | |
977 | // XXX Not currently done: non streambuf_iterator | |
978 | return __s; | |
979 | } | |
980 | ||
981 | // Partial specialization for ostreambuf_iterator. | |
982 | template<typename _CharT> | |
983 | static ostreambuf_iterator<_CharT> | |
984 | _S_output_float(ostreambuf_iterator<_CharT> __s, ios_base& __io, | |
985 | _CharT __fill, const char* __sptr, size_t __slen) | |
986 | { | |
987 | size_t __padding = __io.width() > streamsize(__slen) ? | |
988 | __io.width() -__slen : 0; | |
989 | locale __loc = __io.getloc(); | |
990 | ctype<_CharT> const& __ct = use_facet<ctype<_CharT> >(__loc); | |
991 | ios_base::fmtflags __adjfield = __io.flags() & ios_base::adjustfield; | |
992 | const char* const __eptr = __sptr + __slen; | |
993 | // [22.2.2.2.2.19] Table 61 | |
994 | if (__adjfield == ios_base::internal) | |
995 | { | |
996 | // [22.2.2.2.2.14]; widen() | |
997 | if (__sptr < __eptr && (*__sptr == '+' || *__sptr == '-')) | |
998 | { | |
999 | __s = __ct.widen(*__sptr); | |
1000 | ++__s; | |
1001 | ++__sptr; | |
1002 | } | |
1003 | __s = _S_fill(__s, __fill, __padding); | |
1004 | __padding = 0; | |
1005 | } | |
1006 | else if (__adjfield != ios_base::left) | |
1007 | { | |
1008 | __s = _S_fill(__s, __fill, __padding); | |
1009 | __padding = 0; | |
1010 | } | |
1011 | // the "C" locale decimal character | |
1012 | char __decimal_point = *(localeconv()->decimal_point); | |
1013 | const _Format_cache<_CharT>* __fmt = _Format_cache<_CharT>::_S_get(__io); | |
1014 | for (; __sptr != __eptr; ++__s, ++__sptr) | |
1015 | { | |
1016 | // [22.2.2.2.2.17]; decimal point conversion | |
1017 | if (*__sptr == __decimal_point) | |
1018 | __s = __fmt->_M_decimal_point; | |
1019 | // [22.2.2.2.2.14]; widen() | |
1020 | else | |
1021 | __s = __ct.widen(*__sptr); | |
1022 | } | |
1023 | // [22.2.2.2.2.19] Table 61 | |
1024 | if (__padding) | |
1025 | _S_fill(__s, __fill, __padding); | |
1026 | __io.width(0); | |
1027 | return __s; | |
1028 | } | |
1029 | ||
1030 | bool | |
1031 | _S_build_float_format(ios_base& __io, char* __fptr, char __modifier, | |
1032 | streamsize __prec); | |
1033 | ||
1034 | template <typename _CharT, typename _OutIter> | |
1035 | _OutIter | |
1036 | num_put<_CharT, _OutIter>:: | |
1037 | do_put(iter_type __s, ios_base& __io, char_type __fill, double __v) const | |
1038 | { | |
1039 | const streamsize __max_prec = numeric_limits<double>::digits10 + 3; | |
1040 | streamsize __prec = __io.precision(); | |
1041 | // Protect against sprintf() buffer overflows. | |
1042 | if (__prec > __max_prec) | |
1043 | __prec = __max_prec; | |
1044 | // The *2 provides for signs, exp, 'E', and pad. | |
1045 | char __sbuf[__max_prec*2]; | |
1046 | size_t __slen; | |
1047 | // Long enough for the max format spec. | |
1048 | char __fbuf[16]; | |
1049 | if (_S_build_float_format(__io, __fbuf, 0, __prec)) | |
1050 | __slen = sprintf(__sbuf, __fbuf, __prec, __v); | |
1051 | else | |
1052 | __slen = sprintf(__sbuf, __fbuf, __v); | |
1053 | // [22.2.2.2.2] Stages 2-4. | |
1054 | return _S_output_float(__s, __io, __fill, __sbuf, __slen); | |
1055 | } | |
1056 | ||
1057 | template <typename _CharT, typename _OutIter> | |
1058 | _OutIter | |
1059 | num_put<_CharT, _OutIter>:: | |
1060 | do_put(iter_type __s, ios_base& __io, char_type __fill, | |
1061 | long double __v) const | |
1062 | { | |
1063 | const streamsize __max_prec = numeric_limits<long double>::digits10 + 3; | |
1064 | streamsize __prec = __io.precision(); | |
1065 | // Protect against sprintf() buffer overflows. | |
1066 | if (__prec > __max_prec) | |
1067 | __prec = __max_prec; | |
1068 | // The *2 provides for signs, exp, 'E', and pad. | |
1069 | char __sbuf[__max_prec*2]; | |
1070 | size_t __slen; | |
1071 | // Long enough for the max format spec. | |
1072 | char __fbuf[16]; | |
1073 | // 'L' as per [22.2.2.2.2] Table 59 | |
1074 | if ( _S_build_float_format(__io, __fbuf, 'L', __prec)) | |
1075 | __slen = sprintf(__sbuf, __fbuf, __prec, __v); | |
1076 | else | |
1077 | __slen = sprintf(__sbuf, __fbuf, __v); | |
1078 | // [22.2.2.2.2] Stages 2-4 | |
1079 | return _S_output_float(__s, __io, __fill, __sbuf, __slen); | |
1080 | } | |
1081 | ||
1082 | template <typename _CharT, typename _OutIter> | |
1083 | _OutIter | |
1084 | num_put<_CharT, _OutIter>:: | |
1085 | do_put(iter_type __s, ios_base& __io, char_type __fill, | |
1086 | const void* __v) const | |
1087 | { | |
1088 | typedef ios_base::fmtflags fmtflags; | |
1089 | fmtflags __fmt = __io.flags(); | |
1090 | fmtflags __fmtmask = ~(ios_base::showpos | ios_base::basefield | |
1091 | | ios_base::uppercase | ios_base::internal); | |
1092 | __io.flags(__fmt & __fmtmask | (ios_base::hex | ios_base::showbase)); | |
1093 | try { | |
1094 | _OutIter __s2 = _S_format(__s, __io, __fill, false, | |
1095 | reinterpret_cast<unsigned long>(__v)); | |
1096 | __io.flags(__fmt); | |
1097 | return __s2; | |
1098 | } | |
1099 | catch (...) { | |
1100 | __io.flags(__fmt); | |
1101 | throw; | |
1102 | } | |
1103 | } | |
1104 | ||
725dc051 BK |
1105 | // Support for time_get: |
1106 | // Note that these partial specializations could, and maybe should, | |
1107 | // be changed to full specializations (by eliminating the _Dummy | |
1108 | // argument) and moved to a .cc file. | |
1109 | template<typename _CharT, typename _Dummy = int> | |
1110 | struct _Weekdaynames; | |
1111 | ||
1112 | template<typename _Dummy> | |
1113 | struct _Weekdaynames<char, _Dummy> | |
1114 | { static const char* const _S_names[14]; }; | |
1115 | ||
1116 | template<typename _Dummy> | |
1117 | const char* const | |
1118 | _Weekdaynames<char, _Dummy>::_S_names[14] = | |
1119 | { | |
1120 | "Sun", "Sunday", | |
1121 | "Mon", "Monday", "Tue", "Tuesday", "Wed", "Wednesday", | |
1122 | "Thu", "Thursday", "Fri", "Friday", "Sat", "Saturday" | |
1123 | }; | |
1124 | ||
1125 | #ifdef _GLIBCPP_USE_WCHAR_T | |
1126 | template<typename _Dummy> | |
1127 | struct _Weekdaynames<wchar_t, _Dummy> | |
1128 | { static const wchar_t* const _S_names[14]; }; | |
1129 | ||
1130 | template<typename _Dummy> | |
1131 | const wchar_t* const | |
1132 | _Weekdaynames<wchar_t, _Dummy>::_S_names[14] = | |
1133 | { | |
1134 | L"Sun", L"Sunday", | |
1135 | L"Mon", L"Monday", L"Tue", L"Tuesday", L"Wed", L"Wednesday", | |
1136 | L"Thu", L"Thursday", L"Fri", L"Friday", L"Sat", L"Saturday" | |
1137 | }; | |
1138 | #endif | |
1139 | ||
1140 | template<typename _CharT, typename _Dummy = int> | |
1141 | struct _Monthnames; | |
1142 | ||
1143 | template<typename _Dummy> | |
1144 | struct _Monthnames<char,_Dummy> | |
1145 | { static const char* const _S_names[24]; }; | |
1146 | ||
1147 | template<typename _Dummy> | |
1148 | const char* const | |
1149 | _Monthnames<char,_Dummy>::_S_names[24] = | |
1150 | { | |
1151 | "Jan", "January", "Feb", "February", "Mar", "March", | |
1152 | "Apr", "April", "May", "May", "Jun", "June", | |
1153 | "Jul", "July", "Aug", "August", "Sep", "September", | |
1154 | "Oct", "October", "Nov", "November", "Dec", "December" | |
1155 | }; | |
1156 | ||
1157 | #ifdef _GLIBCPP_USE_WCHAR_T | |
1158 | template<typename _Dummy> | |
1159 | struct _Monthnames<wchar_t, _Dummy> | |
1160 | { static const wchar_t* const _S_names[24]; }; | |
1161 | ||
1162 | template<typename _Dummy> | |
1163 | const wchar_t* const | |
1164 | _Monthnames<wchar_t,_Dummy>::_S_names[24] = | |
1165 | { | |
1166 | L"Jan", L"January", L"Feb", L"February", L"Mar", L"March", | |
1167 | L"Apr", L"April", L"May", L"May", L"Jun", L"June", | |
1168 | L"Jul", L"July", L"Aug", L"August", L"Sep", L"September", | |
1169 | L"Oct", L"October", L"Nov", L"November", L"Dec", L"December" | |
1170 | }; | |
1171 | #endif | |
1172 | ||
725dc051 BK |
1173 | template<typename _CharT, typename _InIter> |
1174 | _InIter | |
1175 | time_get<_CharT, _InIter>:: | |
1176 | do_get_weekday(iter_type __s, iter_type __end, | |
1177 | ios_base& __io, ios_base::iostate& __err, tm* __t) const | |
1178 | { | |
1179 | if (!_M_daynames) | |
1180 | { | |
1181 | _M_daynames = new basic_string<_CharT>[14]; | |
1182 | for (int __i = 0; __i < 14; ++__i) | |
1183 | _M_daynames[__i] = _Weekdaynames<_CharT>::_S_names[__i]; | |
1184 | } | |
1185 | bool __at_eof = false; | |
1186 | int __remain = 0; | |
1187 | int __matches[14]; | |
1188 | iter_type __out = __match_parallel(__s, __end, 14, _M_daynames, | |
1189 | __matches, __remain, __at_eof); | |
1190 | __err = ios_base::iostate(0); | |
1191 | if (__at_eof) __err |= __io.eofbit; | |
1192 | if (__remain == 1 || | |
1193 | __remain == 2 && (__matches[0]>>1) == (__matches[1]>>1)) | |
1194 | __t->tm_wday = (__matches[0]>>1); | |
1195 | else | |
1196 | __err |= __io.failbit; | |
1197 | return __out; | |
1198 | } | |
1199 | ||
1200 | template<typename _CharT, typename _InIter> | |
1201 | _InIter | |
1202 | time_get<_CharT, _InIter>:: | |
1203 | do_get_monthname(iter_type __s, iter_type __end, | |
1204 | ios_base& __io, ios_base::iostate& __err, tm* __t) const | |
1205 | { | |
1206 | if (!_M_monthnames) | |
1207 | { | |
1208 | _M_monthnames = new basic_string<_CharT>[24]; | |
1209 | for (int __i = 0; __i < 24; ++__i) | |
1210 | _M_monthnames[__i] = _Monthnames<_CharT>::_S_names[__i]; | |
1211 | } | |
1212 | bool __at_eof = false; | |
1213 | int __remain = 0; | |
1214 | int __matches[24]; | |
1215 | iter_type __out = __match_parallel( __s, __end, 24, _M_monthnames, | |
1216 | __matches, __remain, __at_eof); | |
1217 | __err = ios_base::iostate(0); | |
1218 | if (__at_eof) __err |= __io.eofbit; | |
1219 | if (__remain == 1 || | |
1220 | __remain == 2 && (__matches[0]>>1) == (__matches[1]>>1)) | |
1221 | __t->tm_mon = (__matches[0]>>1); | |
1222 | else | |
1223 | __err |= __io.failbit; | |
1224 | return __out; | |
1225 | } | |
725dc051 BK |
1226 | } // std:: |
1227 | ||
1228 | #endif /* _CPP_BITS_LOCFACETS_TCC */ | |
1229 | ||
1230 | // Local Variables: | |
1231 | // mode:c++ | |
1232 | // End: |