blob: 284184fb17ebb21aaae7cda35f017b91ca16b059 [file] [log] [blame]
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001// -*- C++ -*-
2//===-------------------------- locale ------------------------------------===//
3//
Howard Hinnantf5256e12010-05-11 21:36:01 +00004// The LLVM Compiler Infrastructure
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005//
6// This file is distributed under the University of Illinois Open Source
7// License. See LICENSE.TXT for details.
8//
9//===----------------------------------------------------------------------===//
10
11#ifndef _LIBCPP_LOCALE
12#define _LIBCPP_LOCALE
13
14/*
15 locale synopsis
16
17namespace std
18{
19
20class locale
21{
22public:
23 // types:
24 class facet;
25 class id;
26
27 typedef int category;
28 static const category // values assigned here are for exposition only
29 none = 0x000,
30 collate = 0x010,
31 ctype = 0x020,
32 monetary = 0x040,
33 numeric = 0x080,
34 time = 0x100,
35 messages = 0x200,
36 all = collate | ctype | monetary | numeric | time | messages;
37
38 // construct/copy/destroy:
39 locale() throw();
40 locale(const locale& other) throw();
41 explicit locale(const char* std_name);
42 explicit locale(const string& std_name);
43 locale(const locale& other, const char* std_name, category);
44 locale(const locale& other, const string& std_name, category);
45 template <class Facet> locale(const locale& other, Facet* f);
46 locale(const locale& other, const locale& one, category);
47
48 ~locale() throw(); // not virtual
49
50 const locale& operator=(const locale& other) throw();
51
52 template <class Facet> locale combine(const locale& other) const;
53
54 // locale operations:
55 basic_string<char> name() const;
56 bool operator==(const locale& other) const;
57 bool operator!=(const locale& other) const;
58 template <class charT, class Traits, class Allocator>
59 bool operator()(const basic_string<charT,Traits,Allocator>& s1,
60 const basic_string<charT,Traits,Allocator>& s2) const;
61
62 // global locale objects:
63 static locale global(const locale&);
64 static const locale& classic();
65};
66
67template <class Facet> const Facet& use_facet(const locale&);
68template <class Facet> bool has_facet(const locale&) throw();
69
70// 22.3.3, convenience interfaces:
71template <class charT> bool isspace (charT c, const locale& loc);
72template <class charT> bool isprint (charT c, const locale& loc);
73template <class charT> bool iscntrl (charT c, const locale& loc);
74template <class charT> bool isupper (charT c, const locale& loc);
75template <class charT> bool islower (charT c, const locale& loc);
76template <class charT> bool isalpha (charT c, const locale& loc);
77template <class charT> bool isdigit (charT c, const locale& loc);
78template <class charT> bool ispunct (charT c, const locale& loc);
79template <class charT> bool isxdigit(charT c, const locale& loc);
80template <class charT> bool isalnum (charT c, const locale& loc);
81template <class charT> bool isgraph (charT c, const locale& loc);
82template <class charT> charT toupper(charT c, const locale& loc);
83template <class charT> charT tolower(charT c, const locale& loc);
84template <class Codecvt, class Elem = wchar_t> class wstring_convert;
85template <class Codecvt, class Elem = wchar_t, class Tr = char_traits<Elem>>
86 class wbuffer_convert;
87
88// 22.4.1 and 22.4.1.3, ctype:
89class ctype_base;
90template <class charT> class ctype;
91template <> class ctype<char>; // specialization
92template <class charT> class ctype_byname;
93template <> class ctype_byname<char>; // specialization
94
95class codecvt_base;
96template <class internT, class externT, class stateT> class codecvt;
97template <class internT, class externT, class stateT> class codecvt_byname;
98
99// 22.4.2 and 22.4.3, numeric:
100template <class charT, class InputIterator> class num_get;
101template <class charT, class OutputIterator> class num_put;
102template <class charT> class numpunct;
103template <class charT> class numpunct_byname;
104
105// 22.4.4, col lation:
106template <class charT> class collate;
107template <class charT> class collate_byname;
108
109// 22.4.5, date and time:
110class time_base;
111template <class charT, class InputIterator> class time_get;
112template <class charT, class InputIterator> class time_get_byname;
113template <class charT, class OutputIterator> class time_put;
114template <class charT, class OutputIterator> class time_put_byname;
115
116// 22.4.6, money:
117class money_base;
118template <class charT, class InputIterator> class money_get;
119template <class charT, class OutputIterator> class money_put;
120template <class charT, bool Intl> class moneypunct;
121template <class charT, bool Intl> class moneypunct_byname;
122
123// 22.4.7, message retrieval:
124class messages_base;
125template <class charT> class messages;
126template <class charT> class messages_byname;
127
128} // std
129
130*/
131
132#include <__config>
133#include <__locale>
134#include <algorithm>
135#include <memory>
136#include <ios>
137#include <streambuf>
138#include <iterator>
139#include <limits>
140#include <cstdlib>
141#include <ctime>
142#include <nl_types.h>
143
144#pragma GCC system_header
145
146_LIBCPP_BEGIN_NAMESPACE_STD
147
148// __scan_keyword
149// Scans [__b, __e) until a match is found in the basic_strings range
150// [__kb, __ke) or until it can be shown that there is no match in [__kb, __ke).
151// __b will be incremented (visibly), consuming CharT until a match is found
152// or proved to not exist. A keyword may be "", in which will match anything.
153// If one keyword is a prefix of another, and the next CharT in the input
154// might match another keyword, the algorithm will attempt to find the longest
155// matching keyword. If the longer matching keyword ends up not matching, then
156// no keyword match is found. If no keyword match is found, __ke is returned
157// and failbit is set in __err.
158// Else an iterator pointing to the matching keyword is found. If more than
159// one keyword matches, an iterator to the first matching keyword is returned.
160// If on exit __b == __e, eofbit is set in __err. If __case_senstive is false,
161// __ct is used to force to lower case before comparing characters.
162// Examples:
163// Keywords: "a", "abb"
164// If the input is "a", the first keyword matches and eofbit is set.
165// If the input is "abc", no match is found and "ab" are consumed.
166template <class _InputIterator, class _ForwardIterator, class _Ctype>
167_LIBCPP_HIDDEN
168_ForwardIterator
169__scan_keyword(_InputIterator& __b, _InputIterator __e,
170 _ForwardIterator __kb, _ForwardIterator __ke,
171 const _Ctype& __ct, ios_base::iostate& __err,
172 bool __case_sensitive = true)
173{
174 typedef typename iterator_traits<_InputIterator>::value_type _CharT;
175 size_t __nkw = _STD::distance(__kb, __ke);
176 const unsigned char __doesnt_match = '\0';
177 const unsigned char __might_match = '\1';
178 const unsigned char __does_match = '\2';
179 unsigned char __statbuf[100];
180 unsigned char* __status = __statbuf;
181 unique_ptr<unsigned char, void(*)(void*)> __stat_hold(0, free);
182 if (__nkw > sizeof(__statbuf))
183 {
184 __status = (unsigned char*)malloc(__nkw);
185 if (__status == 0)
186 __throw_bad_alloc();
187 __stat_hold.reset(__status);
188 }
189 size_t __n_might_match = __nkw; // At this point, any keyword might match
190 size_t __n_does_match = 0; // but none of them definitely do
191 // Initialize all statuses to __might_match, except for "" keywords are __does_match
192 unsigned char* __st = __status;
193 for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, ++__st)
194 {
195 if (!__ky->empty())
196 *__st = __might_match;
197 else
198 {
199 *__st = __does_match;
200 --__n_might_match;
201 ++__n_does_match;
202 }
203 }
204 // While there might be a match, test keywords against the next CharT
205 for (size_t __indx = 0; __b != __e && __n_might_match > 0; ++__indx)
206 {
207 // Peek at the next CharT but don't consume it
208 _CharT __c = *__b;
209 if (!__case_sensitive)
210 __c = __ct.toupper(__c);
211 bool __consume = false;
212 // For each keyword which might match, see if the __indx character is __c
213 // If a match if found, consume __c
214 // If a match is found, and that is the last character in the keyword,
215 // then that keyword matches.
216 // If the keyword doesn't match this character, then change the keyword
217 // to doesn't match
218 __st = __status;
219 for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, ++__st)
220 {
221 if (*__st == __might_match)
222 {
223 _CharT __kc = (*__ky)[__indx];
224 if (!__case_sensitive)
225 __kc = __ct.toupper(__kc);
226 if (__c == __kc)
227 {
228 __consume = true;
229 if (__ky->size() == __indx+1)
230 {
231 *__st = __does_match;
232 --__n_might_match;
233 ++__n_does_match;
234 }
235 }
236 else
237 {
238 *__st = __doesnt_match;
239 --__n_might_match;
240 }
241 }
242 }
243 // consume if we matched a character
244 if (__consume)
245 {
246 ++__b;
247 // If we consumed a character and there might be a matched keyword that
248 // was marked matched on a previous iteration, then such keywords
249 // which are now marked as not matching.
250 if (__n_might_match + __n_does_match > 1)
251 {
252 __st = __status;
253 for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, ++__st)
254 {
255 if (*__st == __does_match && __ky->size() != __indx+1)
256 {
257 *__st = __doesnt_match;
258 --__n_does_match;
259 }
260 }
261 }
262 }
263 }
264 // We've exited the loop because we hit eof and/or we have no more "might matches".
265 if (__b == __e)
266 __err |= ios_base::eofbit;
267 // Return the first matching result
268 for (__st = __status; __kb != __ke; ++__kb, ++__st)
269 if (*__st == __does_match)
270 break;
271 if (__kb == __ke)
272 __err |= ios_base::failbit;
273 return __kb;
274}
275
276struct __num_get_base
277{
278 static const int __num_get_buf_sz = 40;
279
280 static int __get_base(ios_base&);
281 static const char __src[33];
282};
283
284void __check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
285 ios_base::iostate& __err);
286
287
288template <class _CharT>
289struct __num_get
290 : protected __num_get_base
291{
292 static string __stage2_int_prep(ios_base& __iob, _CharT* __atoms, _CharT& __thousands_sep);
293 static string __stage2_float_prep(ios_base& __iob, _CharT* __atoms, _CharT& __decimal_point,
294 _CharT& __thousands_sep);
295 static int __stage2_int_loop(_CharT __ct, int __base, char* __a, char*& __a_end,
296 unsigned& __dc, _CharT __thousands_sep, const string& __grouping,
297 unsigned* __g, unsigned*& __g_end, _CharT* __atoms);
298 static int __stage2_float_loop(_CharT __ct, bool& __in_units, char& __exp,
299 char* __a, char*& __a_end,
300 _CharT __decimal_point, _CharT __thousands_sep,
301 const string& __grouping, unsigned* __g,
302 unsigned*& __g_end, unsigned& __dc, _CharT* __atoms);
303};
304
305template <class _CharT>
306string
307__num_get<_CharT>::__stage2_int_prep(ios_base& __iob, _CharT* __atoms, _CharT& __thousands_sep)
308{
309 locale __loc = __iob.getloc();
310 use_facet<ctype<_CharT> >(__loc).widen(__src, __src + 26, __atoms);
311 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
312 __thousands_sep = __np.thousands_sep();
313 return __np.grouping();
314}
315
316template <class _CharT>
317string
318__num_get<_CharT>::__stage2_float_prep(ios_base& __iob, _CharT* __atoms, _CharT& __decimal_point,
319 _CharT& __thousands_sep)
320{
321 locale __loc = __iob.getloc();
322 use_facet<ctype<_CharT> >(__loc).widen(__src, __src + 32, __atoms);
323 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
324 __decimal_point = __np.decimal_point();
325 __thousands_sep = __np.thousands_sep();
326 return __np.grouping();
327}
328
329template <class _CharT>
330int
331__num_get<_CharT>::__stage2_int_loop(_CharT __ct, int __base, char* __a, char*& __a_end,
332 unsigned& __dc, _CharT __thousands_sep, const string& __grouping,
333 unsigned* __g, unsigned*& __g_end, _CharT* __atoms)
334{
335 if (__ct == __thousands_sep && __grouping.size() != 0)
336 {
337 if (__g_end-__g < __num_get_buf_sz)
338 {
339 *__g_end++ = __dc;
340 __dc = 0;
341 }
342 return 0;
343 }
344 ptrdiff_t __f = find(__atoms, __atoms + 26, __ct) - __atoms;
345 if (__f >= 26)
346 return -1;
347 if (__a_end-__a < __num_get_buf_sz - 1)
348 *__a_end++ = __src[__f];
349 switch (__base)
350 {
351 case 8:
352 case 10:
353 if (__f >= __base)
354 return 0;
355 break;
356 default:
357 if (__f >= 22)
358 return 0;
359 break;
360 }
361 ++__dc;
362 return 0;
363}
364
365template <class _CharT>
366int
367__num_get<_CharT>::__stage2_float_loop(_CharT __ct, bool& __in_units, char& __exp, char* __a, char*& __a_end,
368 _CharT __decimal_point, _CharT __thousands_sep, const string& __grouping,
369 unsigned* __g, unsigned*& __g_end, unsigned& __dc, _CharT* __atoms)
370{
371 if (__ct == __decimal_point)
372 {
373 if (!__in_units)
374 return -1;
375 __in_units = false;
376 *__a_end++ = '.';
377 if (__grouping.size() != 0 && __g_end-__g < __num_get_buf_sz)
378 *__g_end++ = __dc;
379 return 0;
380 }
381 if (__ct == __thousands_sep && __grouping.size() != 0)
382 {
383 if (!__in_units)
384 return -1;
385 if (__g_end-__g < __num_get_buf_sz)
386 {
387 *__g_end++ = __dc;
388 __dc = 0;
389 }
390 return 0;
391 }
392 ptrdiff_t __f = find(__atoms, __atoms + 32, __ct) - __atoms;
393 if (__f >= 32)
394 return -1;
395 char __x = __src[__f];
396 if (__a_end-__a < __num_get_buf_sz - 1)
397 *__a_end++ = __x;
398 if (__x == 'x' || __x == 'X')
399 __exp = 'P';
400 else if ((__x & 0xDF) == __exp)
401 {
402 __in_units = false;
403 if (__grouping.size() != 0 && __g_end-__g < __num_get_buf_sz)
404 *__g_end++ = __dc;
405 }
406 if (__f >= 22)
407 return 0;
408 ++__dc;
409 return 0;
410}
411
412extern template class __num_get<char>;
413extern template class __num_get<wchar_t>;
414
415template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
416class num_get
417 : public locale::facet,
418 private __num_get<_CharT>
419{
420public:
421 typedef _CharT char_type;
422 typedef _InputIterator iter_type;
423
424 _LIBCPP_ALWAYS_INLINE
425 explicit num_get(size_t __refs = 0)
426 : locale::facet(__refs) {}
427
428 _LIBCPP_ALWAYS_INLINE
429 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
430 ios_base::iostate& __err, bool& __v) const
431 {
432 return do_get(__b, __e, __iob, __err, __v);
433 }
434
435 _LIBCPP_ALWAYS_INLINE
436 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
437 ios_base::iostate& __err, long& __v) const
438 {
439 return do_get(__b, __e, __iob, __err, __v);
440 }
441
442 _LIBCPP_ALWAYS_INLINE
443 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
444 ios_base::iostate& __err, long long& __v) const
445 {
446 return do_get(__b, __e, __iob, __err, __v);
447 }
448
449 _LIBCPP_ALWAYS_INLINE
450 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
451 ios_base::iostate& __err, unsigned short& __v) const
452 {
453 return do_get(__b, __e, __iob, __err, __v);
454 }
455
456 _LIBCPP_ALWAYS_INLINE
457 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
458 ios_base::iostate& __err, unsigned int& __v) const
459 {
460 return do_get(__b, __e, __iob, __err, __v);
461 }
462
463 _LIBCPP_ALWAYS_INLINE
464 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
465 ios_base::iostate& __err, unsigned long& __v) const
466 {
467 return do_get(__b, __e, __iob, __err, __v);
468 }
469
470 _LIBCPP_ALWAYS_INLINE
471 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
472 ios_base::iostate& __err, unsigned long long& __v) const
473 {
474 return do_get(__b, __e, __iob, __err, __v);
475 }
476
477 _LIBCPP_ALWAYS_INLINE
478 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
479 ios_base::iostate& __err, float& __v) const
480 {
481 return do_get(__b, __e, __iob, __err, __v);
482 }
483
484 _LIBCPP_ALWAYS_INLINE
485 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
486 ios_base::iostate& __err, double& __v) const
487 {
488 return do_get(__b, __e, __iob, __err, __v);
489 }
490
491 _LIBCPP_ALWAYS_INLINE
492 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
493 ios_base::iostate& __err, long double& __v) const
494 {
495 return do_get(__b, __e, __iob, __err, __v);
496 }
497
498 _LIBCPP_ALWAYS_INLINE
499 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
500 ios_base::iostate& __err, void*& __v) const
501 {
502 return do_get(__b, __e, __iob, __err, __v);
503 }
504
505 static locale::id id;
506
507protected:
508 ~num_get() {}
509
510 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
511 ios_base::iostate& __err, bool& __v) const;
512 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
513 ios_base::iostate& __err, long& __v) const;
514 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
515 ios_base::iostate& __err, long long& __v) const;
516 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
517 ios_base::iostate& __err, unsigned short& __v) const;
518 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
519 ios_base::iostate& __err, unsigned int& __v) const;
520 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
521 ios_base::iostate& __err, unsigned long& __v) const;
522 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
523 ios_base::iostate& __err, unsigned long long& __v) const;
524 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
525 ios_base::iostate& __err, float& __v) const;
526 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
527 ios_base::iostate& __err, double& __v) const;
528 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
529 ios_base::iostate& __err, long double& __v) const;
530 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
531 ios_base::iostate& __err, void*& __v) const;
532};
533
534template <class _CharT, class _InputIterator>
535locale::id
536num_get<_CharT, _InputIterator>::id;
537
538template <class _Tp>
539_Tp
540__num_get_signed_integral(const char* __a, const char* __a_end,
541 ios_base::iostate& __err, int __base)
542{
543 if (__a != __a_end)
544 {
545 char *__p2;
546 long long __ll = strtoll_l(__a, &__p2, __base, 0);
547 if (__p2 != __a_end)
548 {
549 __err = ios_base::failbit;
550 return 0;
551 }
552 else if (__ll > numeric_limits<_Tp>::max())
553 {
554 __err = ios_base::failbit;
555 return numeric_limits<_Tp>::max();
556 }
557 else if (__ll < numeric_limits<_Tp>::min())
558 {
559 __err = ios_base::failbit;
560 return numeric_limits<_Tp>::min();
561 }
562 return static_cast<_Tp>(__ll);
563 }
564 __err = ios_base::failbit;
565 return 0;
566}
567
568template <class _Tp>
569_Tp
570__num_get_unsigned_integral(const char* __a, const char* __a_end,
571 ios_base::iostate& __err, int __base)
572{
573 if (__a != __a_end)
574 {
575 char *__p2;
576 unsigned long long __ll = strtoull_l(__a, &__p2, __base, 0);
577 if (__p2 != __a_end)
578 {
579 __err = ios_base::failbit;
580 return 0;
581 }
582 else if (__ll > numeric_limits<_Tp>::max())
583 {
584 __err = ios_base::failbit;
585 return numeric_limits<_Tp>::max();
586 }
587 return static_cast<_Tp>(__ll);
588 }
589 __err = ios_base::failbit;
590 return 0;
591}
592
593template <class _Tp>
594_Tp
595__num_get_float(const char* __a, const char* __a_end, ios_base::iostate& __err)
596{
597 if (__a != __a_end)
598 {
599 char *__p2;
600 long double __ld = strtold_l(__a, &__p2, 0);
601 if (__p2 != __a_end)
602 {
603 __err = ios_base::failbit;
604 return 0;
605 }
606 return static_cast<_Tp>(__ld);
607 }
608 __err = ios_base::failbit;
609 return 0;
610}
611
612template <class _CharT, class _InputIterator>
613_InputIterator
614num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
615 ios_base& __iob,
616 ios_base::iostate& __err,
617 bool& __v) const
618{
619 if ((__iob.flags() & ios_base::boolalpha) == 0)
620 {
621 long __lv = -1;
622 __b = do_get(__b, __e, __iob, __err, __lv);
623 switch (__lv)
624 {
625 case 0:
626 __v = false;
627 break;
628 case 1:
629 __v = true;
630 break;
631 default:
632 __v = true;
633 __err = ios_base::failbit;
634 break;
635 }
636 return __b;
637 }
638 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__iob.getloc());
639 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__iob.getloc());
640 typedef typename numpunct<_CharT>::string_type string_type;
641 const string_type __names[2] = {__np.truename(), __np.falsename()};
642 const string_type* __i = __scan_keyword(__b, __e, __names, __names+2,
643 __ct, __err);
644 __v = __i == __names;
645 return __b;
646}
647
648template <class _CharT, class _InputIterator>
649_InputIterator
650num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
651 ios_base& __iob,
652 ios_base::iostate& __err,
653 long& __v) const
654{
655 // Stage 1
656 int __base = this->__get_base(__iob);
657 // Stage 2
658 char_type __atoms[26];
659 char_type __thousands_sep;
660 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
661 char __a[__num_get_base::__num_get_buf_sz] = {0};
662 char* __a_end = __a;
663 unsigned __g[__num_get_base::__num_get_buf_sz];
664 unsigned* __g_end = __g;
665 unsigned __dc = 0;
666 for (; __b != __e; ++__b)
667 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
668 __thousands_sep, __grouping, __g, __g_end,
669 __atoms))
670 break;
671 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
672 *__g_end++ = __dc;
673 // Stage 3
674 __v = __num_get_signed_integral<long>(__a, __a_end, __err, __base);
675 // Digit grouping checked
676 __check_grouping(__grouping, __g, __g_end, __err);
677 // EOF checked
678 if (__b == __e)
679 __err |= ios_base::eofbit;
680 return __b;
681}
682
683template <class _CharT, class _InputIterator>
684_InputIterator
685num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
686 ios_base& __iob,
687 ios_base::iostate& __err,
688 long long& __v) const
689{
690 // Stage 1
691 int __base = this->__get_base(__iob);
692 // Stage 2
693 char_type __atoms[26];
694 char_type __thousands_sep;
695 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
696 char __a[__num_get_base::__num_get_buf_sz] = {0};
697 char* __a_end = __a;
698 unsigned __g[__num_get_base::__num_get_buf_sz];
699 unsigned* __g_end = __g;
700 unsigned __dc = 0;
701 for (; __b != __e; ++__b)
702 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
703 __thousands_sep, __grouping, __g, __g_end,
704 __atoms))
705 break;
706 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
707 *__g_end++ = __dc;
708 // Stage 3
709 __v = __num_get_signed_integral<long long>(__a, __a_end, __err, __base);
710 // Digit grouping checked
711 __check_grouping(__grouping, __g, __g_end, __err);
712 // EOF checked
713 if (__b == __e)
714 __err |= ios_base::eofbit;
715 return __b;
716}
717
718template <class _CharT, class _InputIterator>
719_InputIterator
720num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
721 ios_base& __iob,
722 ios_base::iostate& __err,
723 unsigned short& __v) const
724{
725 // Stage 1
726 int __base = this->__get_base(__iob);
727 // Stage 2
728 char_type __atoms[26];
729 char_type __thousands_sep;
730 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
731 char __a[__num_get_base::__num_get_buf_sz] = {0};
732 char* __a_end = __a;
733 unsigned __g[__num_get_base::__num_get_buf_sz];
734 unsigned* __g_end = __g;
735 unsigned __dc = 0;
736 for (; __b != __e; ++__b)
737 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
738 __thousands_sep, __grouping, __g, __g_end,
739 __atoms))
740 break;
741 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
742 *__g_end++ = __dc;
743 // Stage 3
744 __v = __num_get_unsigned_integral<unsigned short>(__a, __a_end, __err, __base);
745 // Digit grouping checked
746 __check_grouping(__grouping, __g, __g_end, __err);
747 // EOF checked
748 if (__b == __e)
749 __err |= ios_base::eofbit;
750 return __b;
751}
752
753template <class _CharT, class _InputIterator>
754_InputIterator
755num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
756 ios_base& __iob,
757 ios_base::iostate& __err,
758 unsigned int& __v) const
759{
760 // Stage 1
761 int __base = this->__get_base(__iob);
762 // Stage 2
763 char_type __atoms[26];
764 char_type __thousands_sep;
765 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
766 char __a[__num_get_base::__num_get_buf_sz] = {0};
767 char* __a_end = __a;
768 unsigned __g[__num_get_base::__num_get_buf_sz];
769 unsigned* __g_end = __g;
770 unsigned __dc = 0;
771 for (; __b != __e; ++__b)
772 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
773 __thousands_sep, __grouping, __g, __g_end,
774 __atoms))
775 break;
776 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
777 *__g_end++ = __dc;
778 // Stage 3
779 __v = __num_get_unsigned_integral<unsigned int>(__a, __a_end, __err, __base);
780 // Digit grouping checked
781 __check_grouping(__grouping, __g, __g_end, __err);
782 // EOF checked
783 if (__b == __e)
784 __err |= ios_base::eofbit;
785 return __b;
786}
787
788template <class _CharT, class _InputIterator>
789_InputIterator
790num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
791 ios_base& __iob,
792 ios_base::iostate& __err,
793 unsigned long& __v) const
794{
795 // Stage 1
796 int __base = this->__get_base(__iob);
797 // Stage 2
798 char_type __atoms[26];
799 char_type __thousands_sep;
800 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
801 char __a[__num_get_base::__num_get_buf_sz] = {0};
802 char* __a_end = __a;
803 unsigned __g[__num_get_base::__num_get_buf_sz];
804 unsigned* __g_end = __g;
805 unsigned __dc = 0;
806 for (; __b != __e; ++__b)
807 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
808 __thousands_sep, __grouping, __g, __g_end,
809 __atoms))
810 break;
811 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
812 *__g_end++ = __dc;
813 // Stage 3
814 __v = __num_get_unsigned_integral<unsigned long>(__a, __a_end, __err, __base);
815 // Digit grouping checked
816 __check_grouping(__grouping, __g, __g_end, __err);
817 // EOF checked
818 if (__b == __e)
819 __err |= ios_base::eofbit;
820 return __b;
821}
822
823template <class _CharT, class _InputIterator>
824_InputIterator
825num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
826 ios_base& __iob,
827 ios_base::iostate& __err,
828 unsigned long long& __v) const
829{
830 // Stage 1
831 int __base = this->__get_base(__iob);
832 // Stage 2
833 char_type __atoms[26];
834 char_type __thousands_sep;
835 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
836 char __a[__num_get_base::__num_get_buf_sz] = {0};
837 char* __a_end = __a;
838 unsigned __g[__num_get_base::__num_get_buf_sz];
839 unsigned* __g_end = __g;
840 unsigned __dc = 0;
841 for (; __b != __e; ++__b)
842 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
843 __thousands_sep, __grouping, __g, __g_end,
844 __atoms))
845 break;
846 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
847 *__g_end++ = __dc;
848 // Stage 3
849 __v = __num_get_unsigned_integral<unsigned long long>(__a, __a_end, __err, __base);
850 // Digit grouping checked
851 __check_grouping(__grouping, __g, __g_end, __err);
852 // EOF checked
853 if (__b == __e)
854 __err |= ios_base::eofbit;
855 return __b;
856}
857
858template <class _CharT, class _InputIterator>
859_InputIterator
860num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
861 ios_base& __iob,
862 ios_base::iostate& __err,
863 float& __v) const
864{
865 // Stage 1, nothing to do
866 // Stage 2
867 char_type __atoms[32];
868 char_type __decimal_point;
869 char_type __thousands_sep;
870 string __grouping = this->__stage2_float_prep(__iob, __atoms,
871 __decimal_point,
872 __thousands_sep);
873 char __a[__num_get_base::__num_get_buf_sz] = {0};
874 char* __a_end = __a;
875 unsigned __g[__num_get_base::__num_get_buf_sz];
876 unsigned* __g_end = __g;
877 unsigned __dc = 0;
878 bool __in_units = true;
879 char __exp = 'E';
880 for (; __b != __e; ++__b)
881 if (this->__stage2_float_loop(*__b, __in_units, __exp, __a, __a_end,
882 __decimal_point, __thousands_sep,
883 __grouping, __g, __g_end,
884 __dc, __atoms))
885 break;
886 if (__grouping.size() != 0 && __in_units && __g_end-__g < __num_get_base::__num_get_buf_sz)
887 *__g_end++ = __dc;
888 // Stage 3
889 __v = __num_get_float<float>(__a, __a_end, __err);
890 // Digit grouping checked
891 __check_grouping(__grouping, __g, __g_end, __err);
892 // EOF checked
893 if (__b == __e)
894 __err |= ios_base::eofbit;
895 return __b;
896}
897
898template <class _CharT, class _InputIterator>
899_InputIterator
900num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
901 ios_base& __iob,
902 ios_base::iostate& __err,
903 double& __v) const
904{
905 // Stage 1, nothing to do
906 // Stage 2
907 char_type __atoms[32];
908 char_type __decimal_point;
909 char_type __thousands_sep;
910 string __grouping = this->__stage2_float_prep(__iob, __atoms,
911 __decimal_point,
912 __thousands_sep);
913 char __a[__num_get_base::__num_get_buf_sz] = {0};
914 char* __a_end = __a;
915 unsigned __g[__num_get_base::__num_get_buf_sz];
916 unsigned* __g_end = __g;
917 unsigned __dc = 0;
918 bool __in_units = true;
919 char __exp = 'E';
920 for (; __b != __e; ++__b)
921 if (this->__stage2_float_loop(*__b, __in_units, __exp, __a, __a_end,
922 __decimal_point, __thousands_sep,
923 __grouping, __g, __g_end,
924 __dc, __atoms))
925 break;
926 if (__grouping.size() != 0 && __in_units && __g_end-__g < __num_get_base::__num_get_buf_sz)
927 *__g_end++ = __dc;
928 // Stage 3
929 __v = __num_get_float<double>(__a, __a_end, __err);
930 // Digit grouping checked
931 __check_grouping(__grouping, __g, __g_end, __err);
932 // EOF checked
933 if (__b == __e)
934 __err |= ios_base::eofbit;
935 return __b;
936}
937
938template <class _CharT, class _InputIterator>
939_InputIterator
940num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
941 ios_base& __iob,
942 ios_base::iostate& __err,
943 long double& __v) const
944{
945 // Stage 1, nothing to do
946 // Stage 2
947 char_type __atoms[32];
948 char_type __decimal_point;
949 char_type __thousands_sep;
950 string __grouping = this->__stage2_float_prep(__iob, __atoms,
951 __decimal_point,
952 __thousands_sep);
953 char __a[__num_get_base::__num_get_buf_sz] = {0};
954 char* __a_end = __a;
955 unsigned __g[__num_get_base::__num_get_buf_sz];
956 unsigned* __g_end = __g;
957 unsigned __dc = 0;
958 bool __in_units = true;
959 char __exp = 'E';
960 for (; __b != __e; ++__b)
961 if (this->__stage2_float_loop(*__b, __in_units, __exp, __a, __a_end,
962 __decimal_point, __thousands_sep,
963 __grouping, __g, __g_end,
964 __dc, __atoms))
965 break;
966 if (__grouping.size() != 0 && __in_units && __g_end-__g < __num_get_base::__num_get_buf_sz)
967 *__g_end++ = __dc;
968 // Stage 3
969 __v = __num_get_float<long double>(__a, __a_end, __err);
970 // Digit grouping checked
971 __check_grouping(__grouping, __g, __g_end, __err);
972 // EOF checked
973 if (__b == __e)
974 __err |= ios_base::eofbit;
975 return __b;
976}
977
978template <class _CharT, class _InputIterator>
979_InputIterator
980num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
981 ios_base& __iob,
982 ios_base::iostate& __err,
983 void*& __v) const
984{
985 // Stage 1
986 int __base = 16;
987 // Stage 2
988 char_type __atoms[26];
989 char_type __thousands_sep;
990 string __grouping;
991 use_facet<ctype<_CharT> >(__iob.getloc()).widen(__num_get_base::__src,
992 __num_get_base::__src + 26, __atoms);
993 char __a[__num_get_base::__num_get_buf_sz] = {0};
994 char* __a_end = __a;
995 unsigned __g[__num_get_base::__num_get_buf_sz];
996 unsigned* __g_end = __g;
997 unsigned __dc = 0;
998 for (; __b != __e; ++__b)
999 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
1000 __thousands_sep, __grouping,
1001 __g, __g_end, __atoms))
1002 break;
1003 // Stage 3
1004 __a[sizeof(__a)-1] = 0;
1005 if (sscanf_l(__a, 0, "%p", &__v) != 1)
1006 __err = ios_base::failbit;
1007 // EOF checked
1008 if (__b == __e)
1009 __err |= ios_base::eofbit;
1010 return __b;
1011}
1012
1013extern template class num_get<char>;
1014extern template class num_get<wchar_t>;
1015
1016struct __num_put_base
1017{
1018protected:
1019 static void __format_int(char* __fmt, const char* __len, bool __signd,
1020 ios_base::fmtflags __flags);
1021 static bool __format_float(char* __fmt, const char* __len,
1022 ios_base::fmtflags __flags);
1023 static char* __identify_padding(char* __nb, char* __ne,
1024 const ios_base& __iob);
1025};
1026
1027template <class _CharT>
1028struct __num_put
1029 : protected __num_put_base
1030{
1031 static void __widen_and_group_int(char* __nb, char* __np, char* __ne,
1032 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1033 const locale& __loc);
1034 static void __widen_and_group_float(char* __nb, char* __np, char* __ne,
1035 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1036 const locale& __loc);
1037};
1038
1039template <class _CharT>
1040void
1041__num_put<_CharT>::__widen_and_group_int(char* __nb, char* __np, char* __ne,
1042 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1043 const locale& __loc)
1044{
1045 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> > (__loc);
1046 const numpunct<_CharT>& __npt = use_facet<numpunct<_CharT> >(__loc);
1047 string __grouping = __npt.grouping();
1048 if (__grouping.empty())
1049 {
1050 __ct.widen(__nb, __ne, __ob);
1051 __oe = __ob + (__ne - __nb);
1052 }
1053 else
1054 {
1055 __oe = __ob;
1056 char* __nf = __nb;
1057 if (*__nf == '-' || *__nf == '+')
1058 *__oe++ = __ct.widen(*__nf++);
1059 if (__ne - __nf >= 2 && __nf[0] == '0' && (__nf[1] == 'x' ||
1060 __nf[1] == 'X'))
1061 {
1062 *__oe++ = __ct.widen(*__nf++);
1063 *__oe++ = __ct.widen(*__nf++);
1064 }
1065 reverse(__nf, __ne);
1066 _CharT __thousands_sep = __npt.thousands_sep();
1067 unsigned __dc = 0;
1068 unsigned __dg = 0;
1069 for (char* __p = __nf; __p < __ne; ++__p)
1070 {
1071 if (static_cast<unsigned>(__grouping[__dg]) > 0 &&
1072 __dc == static_cast<unsigned>(__grouping[__dg]))
1073 {
1074 *__oe++ = __thousands_sep;
1075 __dc = 0;
1076 if (__dg < __grouping.size()-1)
1077 ++__dg;
1078 }
1079 *__oe++ = __ct.widen(*__p);
1080 ++__dc;
1081 }
1082 reverse(__ob + (__nf - __nb), __oe);
1083 }
1084 if (__np == __ne)
1085 __op = __oe;
1086 else
1087 __op = __ob + (__np - __nb);
1088}
1089
1090template <class _CharT>
1091void
1092__num_put<_CharT>::__widen_and_group_float(char* __nb, char* __np, char* __ne,
1093 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1094 const locale& __loc)
1095{
1096 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> > (__loc);
1097 const numpunct<_CharT>& __npt = use_facet<numpunct<_CharT> >(__loc);
1098 string __grouping = __npt.grouping();
1099 __oe = __ob;
1100 char* __nf = __nb;
1101 if (*__nf == '-' || *__nf == '+')
1102 *__oe++ = __ct.widen(*__nf++);
1103 char* __ns;
1104 if (__ne - __nf >= 2 && __nf[0] == '0' && (__nf[1] == 'x' ||
1105 __nf[1] == 'X'))
1106 {
1107 *__oe++ = __ct.widen(*__nf++);
1108 *__oe++ = __ct.widen(*__nf++);
1109 for (__ns = __nf; __ns < __ne; ++__ns)
1110 if (!isxdigit_l(*__ns, 0))
1111 break;
1112 }
1113 else
1114 {
1115 for (__ns = __nf; __ns < __ne; ++__ns)
1116 if (!isdigit_l(*__ns, 0))
1117 break;
1118 }
1119 if (__grouping.empty())
1120 {
1121 __ct.widen(__nf, __ns, __oe);
1122 __oe += __ns - __nf;
1123 }
1124 else
1125 {
1126 reverse(__nf, __ns);
1127 _CharT __thousands_sep = __npt.thousands_sep();
1128 unsigned __dc = 0;
1129 unsigned __dg = 0;
1130 for (char* __p = __nf; __p < __ns; ++__p)
1131 {
1132 if (__grouping[__dg] > 0 && __dc == static_cast<unsigned>(__grouping[__dg]))
1133 {
1134 *__oe++ = __thousands_sep;
1135 __dc = 0;
1136 if (__dg < __grouping.size()-1)
1137 ++__dg;
1138 }
1139 *__oe++ = __ct.widen(*__p);
1140 ++__dc;
1141 }
1142 reverse(__ob + (__nf - __nb), __oe);
1143 }
1144 for (__nf = __ns; __nf < __ne; ++__nf)
1145 {
1146 if (*__nf == '.')
1147 {
1148 *__oe++ = __npt.decimal_point();
1149 ++__nf;
1150 break;
1151 }
1152 else
1153 *__oe++ = __ct.widen(*__nf);
1154 }
1155 __ct.widen(__nf, __ne, __oe);
1156 __oe += __ne - __nf;
1157 if (__np == __ne)
1158 __op = __oe;
1159 else
1160 __op = __ob + (__np - __nb);
1161}
1162
1163extern template class __num_put<char>;
1164extern template class __num_put<wchar_t>;
1165
1166template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
1167class num_put
1168 : public locale::facet,
1169 private __num_put<_CharT>
1170{
1171public:
1172 typedef _CharT char_type;
1173 typedef _OutputIterator iter_type;
1174
1175 _LIBCPP_ALWAYS_INLINE
1176 explicit num_put(size_t __refs = 0)
1177 : locale::facet(__refs) {}
1178
1179 _LIBCPP_ALWAYS_INLINE
1180 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1181 bool __v) const
1182 {
1183 return do_put(__s, __iob, __fl, __v);
1184 }
1185
1186 _LIBCPP_ALWAYS_INLINE
1187 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1188 long __v) const
1189 {
1190 return do_put(__s, __iob, __fl, __v);
1191 }
1192
1193 _LIBCPP_ALWAYS_INLINE
1194 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1195 long long __v) const
1196 {
1197 return do_put(__s, __iob, __fl, __v);
1198 }
1199
1200 _LIBCPP_ALWAYS_INLINE
1201 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1202 unsigned long __v) const
1203 {
1204 return do_put(__s, __iob, __fl, __v);
1205 }
1206
1207 _LIBCPP_ALWAYS_INLINE
1208 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1209 unsigned long long __v) const
1210 {
1211 return do_put(__s, __iob, __fl, __v);
1212 }
1213
1214 _LIBCPP_ALWAYS_INLINE
1215 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1216 double __v) const
1217 {
1218 return do_put(__s, __iob, __fl, __v);
1219 }
1220
1221 _LIBCPP_ALWAYS_INLINE
1222 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1223 long double __v) const
1224 {
1225 return do_put(__s, __iob, __fl, __v);
1226 }
1227
1228 _LIBCPP_ALWAYS_INLINE
1229 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1230 const void* __v) const
1231 {
1232 return do_put(__s, __iob, __fl, __v);
1233 }
1234
1235 static locale::id id;
1236
1237protected:
1238 ~num_put() {}
1239
1240 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1241 bool __v) const;
1242 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1243 long __v) const;
1244 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1245 long long __v) const;
1246 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1247 unsigned long) const;
1248 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1249 unsigned long long) const;
1250 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1251 double __v) const;
1252 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1253 long double __v) const;
1254 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1255 const void* __v) const;
1256};
1257
1258template <class _CharT, class _OutputIterator>
1259locale::id
1260num_put<_CharT, _OutputIterator>::id;
1261
1262template <class _CharT, class _OutputIterator>
1263_LIBCPP_HIDDEN
1264_OutputIterator
1265__pad_and_output(_OutputIterator __s,
1266 const _CharT* __ob, const _CharT* __op, const _CharT* __oe,
1267 ios_base& __iob, _CharT __fl)
1268{
1269 streamsize __sz = __oe - __ob;
1270 streamsize __ns = __iob.width();
1271 if (__ns > __sz)
1272 __ns -= __sz;
1273 else
1274 __ns = 0;
1275 for (;__ob < __op; ++__ob, ++__s)
1276 *__s = *__ob;
1277 for (; __ns; --__ns, ++__s)
1278 *__s = __fl;
1279 for (; __ob < __oe; ++__ob, ++__s)
1280 *__s = *__ob;
1281 __iob.width(0);
1282 return __s;
1283}
1284
1285template <class _CharT, class _OutputIterator>
1286_OutputIterator
1287num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1288 char_type __fl, bool __v) const
1289{
1290 if ((__iob.flags() & ios_base::boolalpha) == 0)
1291 return do_put(__s, __iob, __fl, (unsigned long)__v);
1292 const numpunct<char_type>& __np = use_facet<numpunct<char_type> >(__iob.getloc());
1293 typedef typename numpunct<char_type>::string_type string_type;
1294 string_type __nm = __v ? __np.truename() : __np.falsename();
1295 for (typename string_type::iterator __i = __nm.begin(); __i != __nm.end(); ++__i, ++__s)
1296 *__s = *__i;
1297 return __s;
1298}
1299
1300template <class _CharT, class _OutputIterator>
1301_OutputIterator
1302num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1303 char_type __fl, long __v) const
1304{
1305 // Stage 1 - Get number in narrow char
1306 char __fmt[6] = {'%', 0};
1307 const char* __len = "l";
1308 this->__format_int(__fmt+1, __len, true, __iob.flags());
1309 const unsigned __nbuf = (numeric_limits<long>::digits / 3)
1310 + ((numeric_limits<long>::digits % 3) != 0)
1311 + 1;
1312 char __nar[__nbuf];
1313 int __nc = sprintf_l(__nar, 0, __fmt, __v);
1314 char* __ne = __nar + __nc;
1315 char* __np = this->__identify_padding(__nar, __ne, __iob);
1316 // Stage 2 - Widen __nar while adding thousands separators
1317 char_type __o[2*(__nbuf-1) - 1];
1318 char_type* __op; // pad here
1319 char_type* __oe; // end of output
1320 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1321 // [__o, __oe) contains thousands_sep'd wide number
1322 // Stage 3 & 4
1323 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1324}
1325
1326template <class _CharT, class _OutputIterator>
1327_OutputIterator
1328num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1329 char_type __fl, long long __v) const
1330{
1331 // Stage 1 - Get number in narrow char
1332 char __fmt[8] = {'%', 0};
1333 const char* __len = "ll";
1334 this->__format_int(__fmt+1, __len, true, __iob.flags());
1335 const unsigned __nbuf = (numeric_limits<long long>::digits / 3)
1336 + ((numeric_limits<long long>::digits % 3) != 0)
1337 + 1;
1338 char __nar[__nbuf];
1339 int __nc = sprintf_l(__nar, 0, __fmt, __v);
1340 char* __ne = __nar + __nc;
1341 char* __np = this->__identify_padding(__nar, __ne, __iob);
1342 // Stage 2 - Widen __nar while adding thousands separators
1343 char_type __o[2*(__nbuf-1) - 1];
1344 char_type* __op; // pad here
1345 char_type* __oe; // end of output
1346 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1347 // [__o, __oe) contains thousands_sep'd wide number
1348 // Stage 3 & 4
1349 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1350}
1351
1352template <class _CharT, class _OutputIterator>
1353_OutputIterator
1354num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1355 char_type __fl, unsigned long __v) const
1356{
1357 // Stage 1 - Get number in narrow char
1358 char __fmt[6] = {'%', 0};
1359 const char* __len = "l";
1360 this->__format_int(__fmt+1, __len, false, __iob.flags());
1361 const unsigned __nbuf = (numeric_limits<unsigned long>::digits / 3)
1362 + ((numeric_limits<unsigned long>::digits % 3) != 0)
1363 + 1;
1364 char __nar[__nbuf];
1365 int __nc = sprintf_l(__nar, 0, __fmt, __v);
1366 char* __ne = __nar + __nc;
1367 char* __np = this->__identify_padding(__nar, __ne, __iob);
1368 // Stage 2 - Widen __nar while adding thousands separators
1369 char_type __o[2*(__nbuf-1) - 1];
1370 char_type* __op; // pad here
1371 char_type* __oe; // end of output
1372 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1373 // [__o, __oe) contains thousands_sep'd wide number
1374 // Stage 3 & 4
1375 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1376}
1377
1378template <class _CharT, class _OutputIterator>
1379_OutputIterator
1380num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1381 char_type __fl, unsigned long long __v) const
1382{
1383 // Stage 1 - Get number in narrow char
1384 char __fmt[8] = {'%', 0};
1385 const char* __len = "ll";
1386 this->__format_int(__fmt+1, __len, false, __iob.flags());
1387 const unsigned __nbuf = (numeric_limits<unsigned long long>::digits / 3)
1388 + ((numeric_limits<unsigned long long>::digits % 3) != 0)
1389 + 1;
1390 char __nar[__nbuf];
1391 int __nc = sprintf_l(__nar, 0, __fmt, __v);
1392 char* __ne = __nar + __nc;
1393 char* __np = this->__identify_padding(__nar, __ne, __iob);
1394 // Stage 2 - Widen __nar while adding thousands separators
1395 char_type __o[2*(__nbuf-1) - 1];
1396 char_type* __op; // pad here
1397 char_type* __oe; // end of output
1398 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1399 // [__o, __oe) contains thousands_sep'd wide number
1400 // Stage 3 & 4
1401 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1402}
1403
1404template <class _CharT, class _OutputIterator>
1405_OutputIterator
1406num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1407 char_type __fl, double __v) const
1408{
1409 // Stage 1 - Get number in narrow char
1410 char __fmt[8] = {'%', 0};
1411 const char* __len = "";
1412 bool __specify_precision = this->__format_float(__fmt+1, __len, __iob.flags());
1413 const unsigned __nbuf = 30;
1414 char __nar[__nbuf];
1415 char* __nb = __nar;
1416 int __nc;
1417 if (__specify_precision)
1418 __nc = snprintf_l(__nb, __nbuf, 0, __fmt, (int)__iob.precision(), __v);
1419 else
1420 __nc = snprintf_l(__nb, __nbuf, 0, __fmt, __v);
1421 unique_ptr<char, void(*)(void*)> __nbh(0, free);
1422 if (__nc > static_cast<int>(__nbuf-1))
1423 {
1424 if (__specify_precision)
1425 __nc = asprintf_l(&__nb, 0, __fmt, (int)__iob.precision(), __v);
1426 else
1427 __nc = asprintf_l(&__nb, 0, __fmt, __v);
1428 if (__nb == 0)
1429 __throw_bad_alloc();
1430 __nbh.reset(__nb);
1431 }
1432 char* __ne = __nb + __nc;
1433 char* __np = this->__identify_padding(__nb, __ne, __iob);
1434 // Stage 2 - Widen __nar while adding thousands separators
1435 char_type __o[2*(__nbuf-1) - 1];
1436 char_type* __ob = __o;
1437 unique_ptr<char_type, void(*)(void*)> __obh(0, free);
1438 if (__nb != __nar)
1439 {
1440 __ob = (char_type*)malloc((2*__nc)*sizeof(char_type));
1441 if (__ob == 0)
1442 __throw_bad_alloc();
1443 __obh.reset(__ob);
1444 }
1445 char_type* __op; // pad here
1446 char_type* __oe; // end of output
1447 this->__widen_and_group_float(__nb, __np, __ne, __ob, __op, __oe, __iob.getloc());
1448 // [__o, __oe) contains thousands_sep'd wide number
1449 // Stage 3 & 4
1450 __s = __pad_and_output(__s, __ob, __op, __oe, __iob, __fl);
1451 return __s;
1452}
1453
1454template <class _CharT, class _OutputIterator>
1455_OutputIterator
1456num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1457 char_type __fl, long double __v) const
1458{
1459 // Stage 1 - Get number in narrow char
1460 char __fmt[8] = {'%', 0};
1461 const char* __len = "L";
1462 bool __specify_precision = this->__format_float(__fmt+1, __len, __iob.flags());
1463 const unsigned __nbuf = 30;
1464 char __nar[__nbuf];
1465 char* __nb = __nar;
1466 int __nc;
1467 if (__specify_precision)
1468 __nc = snprintf_l(__nb, __nbuf, 0, __fmt, (int)__iob.precision(), __v);
1469 else
1470 __nc = snprintf_l(__nb, __nbuf, 0, __fmt, __v);
1471 unique_ptr<char, void(*)(void*)> __nbh(0, free);
1472 if (__nc > static_cast<int>(__nbuf-1))
1473 {
1474 if (__specify_precision)
1475 __nc = asprintf_l(&__nb, 0, __fmt, (int)__iob.precision(), __v);
1476 else
1477 __nc = asprintf_l(&__nb, 0, __fmt, __v);
1478 if (__nb == 0)
1479 __throw_bad_alloc();
1480 __nbh.reset(__nb);
1481 }
1482 char* __ne = __nb + __nc;
1483 char* __np = this->__identify_padding(__nb, __ne, __iob);
1484 // Stage 2 - Widen __nar while adding thousands separators
1485 char_type __o[2*(__nbuf-1) - 1];
1486 char_type* __ob = __o;
1487 unique_ptr<char_type, void(*)(void*)> __obh(0, free);
1488 if (__nb != __nar)
1489 {
1490 __ob = (char_type*)malloc((2*__nc)*sizeof(char_type));
1491 if (__ob == 0)
1492 __throw_bad_alloc();
1493 __obh.reset(__ob);
1494 }
1495 char_type* __op; // pad here
1496 char_type* __oe; // end of output
1497 this->__widen_and_group_float(__nb, __np, __ne, __ob, __op, __oe, __iob.getloc());
1498 // [__o, __oe) contains thousands_sep'd wide number
1499 // Stage 3 & 4
1500 __s = __pad_and_output(__s, __ob, __op, __oe, __iob, __fl);
1501 return __s;
1502}
1503
1504template <class _CharT, class _OutputIterator>
1505_OutputIterator
1506num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1507 char_type __fl, const void* __v) const
1508{
1509 // Stage 1 - Get pointer in narrow char
1510 char __fmt[6] = "%p";
1511 const unsigned __nbuf = 20;
1512 char __nar[__nbuf];
1513 int __nc = sprintf_l(__nar, 0, __fmt, __v);
1514 char* __ne = __nar + __nc;
1515 char* __np = this->__identify_padding(__nar, __ne, __iob);
1516 // Stage 2 - Widen __nar
1517 char_type __o[2*(__nbuf-1) - 1];
1518 char_type* __op; // pad here
1519 char_type* __oe; // end of output
1520 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
1521 __ct.widen(__nar, __ne, __o);
1522 __oe = __o + (__ne - __nar);
1523 if (__np == __ne)
1524 __op = __oe;
1525 else
1526 __op = __o + (__np - __nar);
1527 // [__o, __oe) contains wide number
1528 // Stage 3 & 4
1529 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1530}
1531
1532extern template class num_put<char>;
1533extern template class num_put<wchar_t>;
1534
1535template <class _CharT, class _InputIterator>
1536_LIBCPP_HIDDEN
1537int
1538__get_up_to_n_digits(_InputIterator& __b, _InputIterator __e,
1539 ios_base::iostate& __err, const ctype<_CharT>& __ct, int __n)
1540{
1541 // Precondition: __n >= 1
1542 if (__b == __e)
1543 {
1544 __err |= ios_base::eofbit | ios_base::failbit;
1545 return 0;
1546 }
1547 // get first digit
1548 _CharT __c = *__b;
1549 if (!__ct.is(ctype_base::digit, __c))
1550 {
1551 __err |= ios_base::failbit;
1552 return 0;
1553 }
1554 int __r = __ct.narrow(__c, 0) - '0';
1555 for (++__b, --__n; __b != __e && __n > 0; ++__b, --__n)
1556 {
1557 // get next digit
1558 __c = *__b;
1559 if (!__ct.is(ctype_base::digit, __c))
1560 return __r;
1561 __r = __r * 10 + __ct.narrow(__c, 0) - '0';
1562 }
1563 if (__b == __e)
1564 __err |= ios_base::eofbit;
1565 return __r;
1566}
1567
1568class time_base
1569{
1570public:
1571 enum dateorder {no_order, dmy, mdy, ymd, ydm};
1572};
1573
1574template <class _CharT>
1575class __time_get_c_storage
1576{
1577protected:
1578 typedef basic_string<_CharT> string_type;
1579
1580 virtual const string_type* __weeks() const;
1581 virtual const string_type* __months() const;
1582 virtual const string_type* __am_pm() const;
1583 virtual const string_type& __c() const;
1584 virtual const string_type& __r() const;
1585 virtual const string_type& __x() const;
1586 virtual const string_type& __X() const;
1587};
1588
1589template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
1590class time_get
1591 : public locale::facet,
1592 public time_base,
1593 private __time_get_c_storage<_CharT>
1594{
1595public:
1596 typedef _CharT char_type;
1597 typedef _InputIterator iter_type;
1598 typedef time_base::dateorder dateorder;
1599 typedef basic_string<char_type> string_type;
1600
1601 _LIBCPP_ALWAYS_INLINE
1602 explicit time_get(size_t __refs = 0)
1603 : locale::facet(__refs) {}
1604
1605 _LIBCPP_ALWAYS_INLINE
1606 dateorder date_order() const
1607 {
1608 return this->do_date_order();
1609 }
1610
1611 _LIBCPP_ALWAYS_INLINE
1612 iter_type get_time(iter_type __b, iter_type __e, ios_base& __iob,
1613 ios_base::iostate& __err, tm* __tm) const
1614 {
1615 return do_get_time(__b, __e, __iob, __err, __tm);
1616 }
1617
1618 _LIBCPP_ALWAYS_INLINE
1619 iter_type get_date(iter_type __b, iter_type __e, ios_base& __iob,
1620 ios_base::iostate& __err, tm* __tm) const
1621 {
1622 return do_get_date(__b, __e, __iob, __err, __tm);
1623 }
1624
1625 _LIBCPP_ALWAYS_INLINE
1626 iter_type get_weekday(iter_type __b, iter_type __e, ios_base& __iob,
1627 ios_base::iostate& __err, tm* __tm) const
1628 {
1629 return do_get_weekday(__b, __e, __iob, __err, __tm);
1630 }
1631
1632 _LIBCPP_ALWAYS_INLINE
1633 iter_type get_monthname(iter_type __b, iter_type __e, ios_base& __iob,
1634 ios_base::iostate& __err, tm* __tm) const
1635 {
1636 return do_get_monthname(__b, __e, __iob, __err, __tm);
1637 }
1638
1639 _LIBCPP_ALWAYS_INLINE
1640 iter_type get_year(iter_type __b, iter_type __e, ios_base& __iob,
1641 ios_base::iostate& __err, tm* __tm) const
1642 {
1643 return do_get_year(__b, __e, __iob, __err, __tm);
1644 }
1645
1646 _LIBCPP_ALWAYS_INLINE
1647 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
1648 ios_base::iostate& __err, tm *__tm,
1649 char __fmt, char __mod = 0) const
1650 {
1651 return do_get(__b, __e, __iob, __err, __tm, __fmt, __mod);
1652 }
1653
1654 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
1655 ios_base::iostate& __err, tm* __tm,
1656 const char_type* __fmtb, const char_type* __fmte) const;
1657
1658 static locale::id id;
1659
1660protected:
1661 ~time_get() {}
1662
1663 virtual dateorder do_date_order() const;
1664 virtual iter_type do_get_time(iter_type __b, iter_type __e, ios_base& __iob,
1665 ios_base::iostate& __err, tm* __tm) const;
1666 virtual iter_type do_get_date(iter_type __b, iter_type __e, ios_base& __iob,
1667 ios_base::iostate& __err, tm* __tm) const;
1668 virtual iter_type do_get_weekday(iter_type __b, iter_type __e, ios_base& __iob,
1669 ios_base::iostate& __err, tm* __tm) const;
1670 virtual iter_type do_get_monthname(iter_type __b, iter_type __e, ios_base& __iob,
1671 ios_base::iostate& __err, tm* __tm) const;
1672 virtual iter_type do_get_year(iter_type __b, iter_type __e, ios_base& __iob,
1673 ios_base::iostate& __err, tm* __tm) const;
1674 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
1675 ios_base::iostate& __err, tm* __tm,
1676 char __fmt, char __mod) const;
1677private:
1678 void __get_white_space(iter_type& __b, iter_type __e,
1679 ios_base::iostate& __err, const ctype<char_type>& __ct) const;
1680 void __get_percent(iter_type& __b, iter_type __e, ios_base::iostate& __err,
1681 const ctype<char_type>& __ct) const;
1682
1683 void __get_weekdayname(int& __m,
1684 iter_type& __b, iter_type __e,
1685 ios_base::iostate& __err,
1686 const ctype<char_type>& __ct) const;
1687 void __get_monthname(int& __m,
1688 iter_type& __b, iter_type __e,
1689 ios_base::iostate& __err,
1690 const ctype<char_type>& __ct) const;
1691 void __get_day(int& __d,
1692 iter_type& __b, iter_type __e,
1693 ios_base::iostate& __err,
1694 const ctype<char_type>& __ct) const;
1695 void __get_month(int& __m,
1696 iter_type& __b, iter_type __e,
1697 ios_base::iostate& __err,
1698 const ctype<char_type>& __ct) const;
1699 void __get_year(int& __y,
1700 iter_type& __b, iter_type __e,
1701 ios_base::iostate& __err,
1702 const ctype<char_type>& __ct) const;
1703 void __get_year4(int& __y,
1704 iter_type& __b, iter_type __e,
1705 ios_base::iostate& __err,
1706 const ctype<char_type>& __ct) const;
1707 void __get_hour(int& __d,
1708 iter_type& __b, iter_type __e,
1709 ios_base::iostate& __err,
1710 const ctype<char_type>& __ct) const;
1711 void __get_12_hour(int& __h,
1712 iter_type& __b, iter_type __e,
1713 ios_base::iostate& __err,
1714 const ctype<char_type>& __ct) const;
1715 void __get_am_pm(int& __h,
1716 iter_type& __b, iter_type __e,
1717 ios_base::iostate& __err,
1718 const ctype<char_type>& __ct) const;
1719 void __get_minute(int& __m,
1720 iter_type& __b, iter_type __e,
1721 ios_base::iostate& __err,
1722 const ctype<char_type>& __ct) const;
1723 void __get_second(int& __s,
1724 iter_type& __b, iter_type __e,
1725 ios_base::iostate& __err,
1726 const ctype<char_type>& __ct) const;
1727 void __get_weekday(int& __w,
1728 iter_type& __b, iter_type __e,
1729 ios_base::iostate& __err,
1730 const ctype<char_type>& __ct) const;
1731 void __get_day_year_num(int& __w,
1732 iter_type& __b, iter_type __e,
1733 ios_base::iostate& __err,
1734 const ctype<char_type>& __ct) const;
1735};
1736
1737template <class _CharT, class _InputIterator>
1738locale::id
1739time_get<_CharT, _InputIterator>::id;
1740
1741// time_get primatives
1742
1743template <class _CharT, class _InputIterator>
1744void
1745time_get<_CharT, _InputIterator>::__get_weekdayname(int& __w,
1746 iter_type& __b, iter_type __e,
1747 ios_base::iostate& __err,
1748 const ctype<char_type>& __ct) const
1749{
1750 // Note: ignoring case comes from the POSIX strptime spec
1751 const string_type* __wk = this->__weeks();
1752 int __i = __scan_keyword(__b, __e, __wk, __wk+14, __ct, __err, false) - __wk;
1753 if (__i < 14)
1754 __w = __i % 7;
1755}
1756
1757template <class _CharT, class _InputIterator>
1758void
1759time_get<_CharT, _InputIterator>::__get_monthname(int& __m,
1760 iter_type& __b, iter_type __e,
1761 ios_base::iostate& __err,
1762 const ctype<char_type>& __ct) const
1763{
1764 // Note: ignoring case comes from the POSIX strptime spec
1765 const string_type* __month = this->__months();
1766 int __i = __scan_keyword(__b, __e, __month, __month+24, __ct, __err, false) - __month;
1767 if (__i < 24)
1768 __m = __i % 12;
1769}
1770
1771template <class _CharT, class _InputIterator>
1772void
1773time_get<_CharT, _InputIterator>::__get_day(int& __d,
1774 iter_type& __b, iter_type __e,
1775 ios_base::iostate& __err,
1776 const ctype<char_type>& __ct) const
1777{
1778 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
1779 if (!(__err & ios_base::failbit) && 1 <= __t && __t <= 31)
1780 __d = __t;
1781 else
1782 __err |= ios_base::failbit;
1783}
1784
1785template <class _CharT, class _InputIterator>
1786void
1787time_get<_CharT, _InputIterator>::__get_month(int& __m,
1788 iter_type& __b, iter_type __e,
1789 ios_base::iostate& __err,
1790 const ctype<char_type>& __ct) const
1791{
1792 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2) - 1;
1793 if (!(__err & ios_base::failbit) && __t <= 11)
1794 __m = __t;
1795 else
1796 __err |= ios_base::failbit;
1797}
1798
1799template <class _CharT, class _InputIterator>
1800void
1801time_get<_CharT, _InputIterator>::__get_year(int& __y,
1802 iter_type& __b, iter_type __e,
1803 ios_base::iostate& __err,
1804 const ctype<char_type>& __ct) const
1805{
1806 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 4);
1807 if (!(__err & ios_base::failbit))
1808 {
1809 if (__t < 69)
1810 __t += 2000;
1811 else if (69 <= __t && __t <= 99)
1812 __t += 1900;
1813 __y = __t - 1900;
1814 }
1815}
1816
1817template <class _CharT, class _InputIterator>
1818void
1819time_get<_CharT, _InputIterator>::__get_year4(int& __y,
1820 iter_type& __b, iter_type __e,
1821 ios_base::iostate& __err,
1822 const ctype<char_type>& __ct) const
1823{
1824 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 4);
1825 if (!(__err & ios_base::failbit))
1826 __y = __t - 1900;
1827}
1828
1829template <class _CharT, class _InputIterator>
1830void
1831time_get<_CharT, _InputIterator>::__get_hour(int& __h,
1832 iter_type& __b, iter_type __e,
1833 ios_base::iostate& __err,
1834 const ctype<char_type>& __ct) const
1835{
1836 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
1837 if (!(__err & ios_base::failbit) && __t <= 23)
1838 __h = __t;
1839 else
1840 __err |= ios_base::failbit;
1841}
1842
1843template <class _CharT, class _InputIterator>
1844void
1845time_get<_CharT, _InputIterator>::__get_12_hour(int& __h,
1846 iter_type& __b, iter_type __e,
1847 ios_base::iostate& __err,
1848 const ctype<char_type>& __ct) const
1849{
1850 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
1851 if (!(__err & ios_base::failbit) && 1 <= __t && __t <= 12)
1852 __h = __t;
1853 else
1854 __err |= ios_base::failbit;
1855}
1856
1857template <class _CharT, class _InputIterator>
1858void
1859time_get<_CharT, _InputIterator>::__get_minute(int& __m,
1860 iter_type& __b, iter_type __e,
1861 ios_base::iostate& __err,
1862 const ctype<char_type>& __ct) const
1863{
1864 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
1865 if (!(__err & ios_base::failbit) && __t <= 59)
1866 __m = __t;
1867 else
1868 __err |= ios_base::failbit;
1869}
1870
1871template <class _CharT, class _InputIterator>
1872void
1873time_get<_CharT, _InputIterator>::__get_second(int& __s,
1874 iter_type& __b, iter_type __e,
1875 ios_base::iostate& __err,
1876 const ctype<char_type>& __ct) const
1877{
1878 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
1879 if (!(__err & ios_base::failbit) && __t <= 60)
1880 __s = __t;
1881 else
1882 __err |= ios_base::failbit;
1883}
1884
1885template <class _CharT, class _InputIterator>
1886void
1887time_get<_CharT, _InputIterator>::__get_weekday(int& __w,
1888 iter_type& __b, iter_type __e,
1889 ios_base::iostate& __err,
1890 const ctype<char_type>& __ct) const
1891{
1892 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 1);
1893 if (!(__err & ios_base::failbit) && __t <= 6)
1894 __w = __t;
1895 else
1896 __err |= ios_base::failbit;
1897}
1898
1899template <class _CharT, class _InputIterator>
1900void
1901time_get<_CharT, _InputIterator>::__get_day_year_num(int& __d,
1902 iter_type& __b, iter_type __e,
1903 ios_base::iostate& __err,
1904 const ctype<char_type>& __ct) const
1905{
1906 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 3);
1907 if (!(__err & ios_base::failbit) && __t <= 365)
1908 __d = __t;
1909 else
1910 __err |= ios_base::failbit;
1911}
1912
1913template <class _CharT, class _InputIterator>
1914void
1915time_get<_CharT, _InputIterator>::__get_white_space(iter_type& __b, iter_type __e,
1916 ios_base::iostate& __err,
1917 const ctype<char_type>& __ct) const
1918{
1919 for (; __b != __e && __ct.is(ctype_base::space, *__b); ++__b)
1920 ;
1921 if (__b == __e)
1922 __err |= ios_base::eofbit;
1923}
1924
1925template <class _CharT, class _InputIterator>
1926void
1927time_get<_CharT, _InputIterator>::__get_am_pm(int& __h,
1928 iter_type& __b, iter_type __e,
1929 ios_base::iostate& __err,
1930 const ctype<char_type>& __ct) const
1931{
1932 const string_type* __ap = this->__am_pm();
1933 if (__ap[0].size() + __ap[1].size() == 0)
1934 {
1935 __err |= ios_base::failbit;
1936 return;
1937 }
1938 int __i = __scan_keyword(__b, __e, __ap, __ap+2, __ct, __err, false) - __ap;
1939 if (__i == 0 && __h == 12)
1940 __h = 0;
1941 else if (__i == 1 && __h < 12)
1942 __h += 12;
1943}
1944
1945template <class _CharT, class _InputIterator>
1946void
1947time_get<_CharT, _InputIterator>::__get_percent(iter_type& __b, iter_type __e,
1948 ios_base::iostate& __err,
1949 const ctype<char_type>& __ct) const
1950{
1951 if (__b == __e)
1952 {
1953 __err |= ios_base::eofbit | ios_base::failbit;
1954 return;
1955 }
1956 if (__ct.narrow(*__b, 0) != '%')
1957 __err |= ios_base::failbit;
1958 else if(++__b == __e)
1959 __err |= ios_base::eofbit;
1960}
1961
1962// time_get end primatives
1963
1964template <class _CharT, class _InputIterator>
1965_InputIterator
1966time_get<_CharT, _InputIterator>::get(iter_type __b, iter_type __e,
1967 ios_base& __iob,
1968 ios_base::iostate& __err, tm* __tm,
1969 const char_type* __fmtb, const char_type* __fmte) const
1970{
1971 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
1972 __err = ios_base::goodbit;
1973 while (__fmtb != __fmte && __err == ios_base::goodbit)
1974 {
1975 if (__b == __e)
1976 {
1977 __err = ios_base::failbit;
1978 break;
1979 }
1980 if (__ct.narrow(*__fmtb, 0) == '%')
1981 {
1982 if (++__fmtb == __fmte)
1983 {
1984 __err = ios_base::failbit;
1985 break;
1986 }
1987 char __cmd = __ct.narrow(*__fmtb, 0);
1988 char __opt = '\0';
1989 if (__cmd == 'E' || __cmd == '0')
1990 {
1991 if (++__fmtb == __fmte)
1992 {
1993 __err = ios_base::failbit;
1994 break;
1995 }
1996 __opt = __cmd;
1997 __cmd = __ct.narrow(*__fmtb, 0);
1998 }
1999 __b = do_get(__b, __e, __iob, __err, __tm, __cmd, __opt);
2000 ++__fmtb;
2001 }
2002 else if (__ct.is(ctype_base::space, *__fmtb))
2003 {
2004 for (++__fmtb; __fmtb != __fmte && __ct.is(ctype_base::space, *__fmtb); ++__fmtb)
2005 ;
2006 for ( ; __b != __e && __ct.is(ctype_base::space, *__b); ++__b)
2007 ;
2008 }
2009 else if (__ct.toupper(*__b) == __ct.toupper(*__fmtb))
2010 {
2011 ++__b;
2012 ++__fmtb;
2013 }
2014 else
2015 __err = ios_base::failbit;
2016 }
2017 if (__b == __e)
2018 __err |= ios_base::eofbit;
2019 return __b;
2020}
2021
2022template <class _CharT, class _InputIterator>
2023typename time_get<_CharT, _InputIterator>::dateorder
2024time_get<_CharT, _InputIterator>::do_date_order() const
2025{
2026 return mdy;
2027}
2028
2029template <class _CharT, class _InputIterator>
2030_InputIterator
2031time_get<_CharT, _InputIterator>::do_get_time(iter_type __b, iter_type __e,
2032 ios_base& __iob,
2033 ios_base::iostate& __err,
2034 tm* __tm) const
2035{
2036 const char_type __fmt[] = {'%', 'H', ':', '%', 'M', ':', '%', 'S'};
2037 return get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2038}
2039
2040template <class _CharT, class _InputIterator>
2041_InputIterator
2042time_get<_CharT, _InputIterator>::do_get_date(iter_type __b, iter_type __e,
2043 ios_base& __iob,
2044 ios_base::iostate& __err,
2045 tm* __tm) const
2046{
2047 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2048 const string_type& __fmt = this->__x();
2049 return get(__b, __e, __iob, __err, __tm, __fmt.data(), __fmt.data() + __fmt.size());
2050}
2051
2052template <class _CharT, class _InputIterator>
2053_InputIterator
2054time_get<_CharT, _InputIterator>::do_get_weekday(iter_type __b, iter_type __e,
2055 ios_base& __iob,
2056 ios_base::iostate& __err,
2057 tm* __tm) const
2058{
2059 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2060 __get_weekdayname(__tm->tm_wday, __b, __e, __err, __ct);
2061 return __b;
2062}
2063
2064template <class _CharT, class _InputIterator>
2065_InputIterator
2066time_get<_CharT, _InputIterator>::do_get_monthname(iter_type __b, iter_type __e,
2067 ios_base& __iob,
2068 ios_base::iostate& __err,
2069 tm* __tm) const
2070{
2071 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2072 __get_monthname(__tm->tm_mon, __b, __e, __err, __ct);
2073 return __b;
2074}
2075
2076template <class _CharT, class _InputIterator>
2077_InputIterator
2078time_get<_CharT, _InputIterator>::do_get_year(iter_type __b, iter_type __e,
2079 ios_base& __iob,
2080 ios_base::iostate& __err,
2081 tm* __tm) const
2082{
2083 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2084 __get_year(__tm->tm_year, __b, __e, __err, __ct);
2085 return __b;
2086}
2087
2088template <class _CharT, class _InputIterator>
2089_InputIterator
2090time_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
2091 ios_base& __iob,
2092 ios_base::iostate& __err, tm* __tm,
2093 char __fmt, char) const
2094{
2095 __err = ios_base::goodbit;
2096 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2097 switch (__fmt)
2098 {
2099 case 'a':
2100 case 'A':
2101 __get_weekdayname(__tm->tm_wday, __b, __e, __err, __ct);
2102 break;
2103 case 'b':
2104 case 'B':
2105 case 'h':
2106 __get_monthname(__tm->tm_mon, __b, __e, __err, __ct);
2107 break;
2108 case 'c':
2109 {
2110 const string_type& __fmt = this->__c();
2111 __b = get(__b, __e, __iob, __err, __tm, __fmt.data(), __fmt.data() + __fmt.size());
2112 }
2113 break;
2114 case 'd':
2115 case 'e':
2116 __get_day(__tm->tm_mday, __b, __e, __err, __ct);
2117 break;
2118 case 'D':
2119 {
2120 const char_type __fmt[] = {'%', 'm', '/', '%', 'd', '/', '%', 'y'};
2121 __b = get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2122 }
2123 break;
2124 case 'H':
2125 __get_hour(__tm->tm_hour, __b, __e, __err, __ct);
2126 break;
2127 case 'I':
2128 __get_12_hour(__tm->tm_hour, __b, __e, __err, __ct);
2129 break;
2130 case 'j':
2131 __get_day_year_num(__tm->tm_yday, __b, __e, __err, __ct);
2132 break;
2133 case 'm':
2134 __get_month(__tm->tm_mon, __b, __e, __err, __ct);
2135 break;
2136 case 'M':
2137 __get_minute(__tm->tm_min, __b, __e, __err, __ct);
2138 break;
2139 case 'n':
2140 case 't':
2141 __get_white_space(__b, __e, __err, __ct);
2142 break;
2143 case 'p':
2144 __get_am_pm(__tm->tm_hour, __b, __e, __err, __ct);
2145 break;
2146 case 'r':
2147 {
2148 const char_type __fmt[] = {'%', 'I', ':', '%', 'M', ':', '%', 'S', ' ', '%', 'p'};
2149 __b = get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2150 }
2151 break;
2152 case 'R':
2153 {
2154 const char_type __fmt[] = {'%', 'H', ':', '%', 'M'};
2155 __b = get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2156 }
2157 break;
2158 case 'S':
2159 __get_second(__tm->tm_sec, __b, __e, __err, __ct);
2160 break;
2161 case 'T':
2162 {
2163 const char_type __fmt[] = {'%', 'H', ':', '%', 'M', ':', '%', 'S'};
2164 __b = get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2165 }
2166 break;
2167 case 'w':
2168 __get_weekday(__tm->tm_wday, __b, __e, __err, __ct);
2169 break;
2170 case 'x':
2171 return do_get_date(__b, __e, __iob, __err, __tm);
2172 case 'X':
2173 {
2174 const string_type& __fmt = this->__X();
2175 __b = get(__b, __e, __iob, __err, __tm, __fmt.data(), __fmt.data() + __fmt.size());
2176 }
2177 break;
2178 case 'y':
2179 __get_year(__tm->tm_year, __b, __e, __err, __ct);
2180 break;
2181 case 'Y':
2182 __get_year4(__tm->tm_year, __b, __e, __err, __ct);
2183 break;
2184 case '%':
2185 __get_percent(__b, __e, __err, __ct);
2186 break;
2187 default:
2188 __err |= ios_base::failbit;
2189 }
2190 return __b;
2191}
2192
2193extern template class time_get<char>;
2194extern template class time_get<wchar_t>;
2195
2196class __time_get
2197{
2198protected:
2199 locale_t __loc_;
2200
2201 __time_get(const char* __nm);
2202 __time_get(const string& __nm);
2203 ~__time_get();
2204};
2205
2206template <class _CharT>
2207class __time_get_storage
2208 : public __time_get
2209{
2210protected:
2211 typedef basic_string<_CharT> string_type;
2212
2213 string_type __weeks_[14];
2214 string_type __months_[24];
2215 string_type __am_pm_[2];
2216 string_type __c_;
2217 string_type __r_;
2218 string_type __x_;
2219 string_type __X_;
2220
2221 explicit __time_get_storage(const char* __nm);
2222 explicit __time_get_storage(const string& __nm);
2223
2224 _LIBCPP_ALWAYS_INLINE ~__time_get_storage() {}
2225
2226 time_base::dateorder __do_date_order() const;
2227
2228private:
2229 void init(const ctype<_CharT>&);
2230 string_type __analyze(char __fmt, const ctype<_CharT>&);
2231};
2232
2233template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
2234class time_get_byname
2235 : public time_get<_CharT, _InputIterator>,
2236 private __time_get_storage<_CharT>
2237{
2238public:
2239 typedef time_base::dateorder dateorder;
2240 typedef _InputIterator iter_type;
2241 typedef _CharT char_type;
2242 typedef basic_string<char_type> string_type;
2243
2244 explicit time_get_byname(const char* __nm, size_t __refs = 0)
2245 : time_get<_CharT, _InputIterator>(__refs),
2246 __time_get_storage<_CharT>(__nm) {}
2247 explicit time_get_byname(const string& __nm, size_t __refs = 0)
2248 : time_get<_CharT, _InputIterator>(__refs),
2249 __time_get_storage<_CharT>(__nm) {}
2250
2251protected:
2252 ~time_get_byname() {}
2253
2254 virtual dateorder do_date_order() const {return this->__do_date_order();}
2255private:
2256 virtual const string_type* __weeks() const {return this->__weeks_;}
2257 virtual const string_type* __months() const {return this->__months_;}
2258 virtual const string_type* __am_pm() const {return this->__am_pm_;}
2259 virtual const string_type& __c() const {return this->__c_;}
2260 virtual const string_type& __r() const {return this->__r_;}
2261 virtual const string_type& __x() const {return this->__x_;}
2262 virtual const string_type& __X() const {return this->__X_;}
2263};
2264
2265extern template class time_get_byname<char>;
2266extern template class time_get_byname<wchar_t>;
2267
2268class __time_put
2269{
2270 locale_t __loc_;
2271protected:
2272 _LIBCPP_ALWAYS_INLINE __time_put() : __loc_(0) {}
2273 __time_put(const char* __nm);
2274 __time_put(const string& __nm);
2275 ~__time_put();
2276 void __do_put(char* __nb, char*& __ne, const tm* __tm,
2277 char __fmt, char __mod) const;
2278 void __do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
2279 char __fmt, char __mod) const;
2280};
2281
2282template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
2283class time_put
2284 : public locale::facet,
2285 private __time_put
2286{
2287public:
2288 typedef _CharT char_type;
2289 typedef _OutputIterator iter_type;
2290
2291 _LIBCPP_ALWAYS_INLINE
2292 explicit time_put(size_t __refs = 0)
2293 : locale::facet(__refs) {}
2294
2295 iter_type put(iter_type __s, ios_base& __iob, char_type __fl, const tm* __tm,
2296 const char_type* __pb, const char_type* __pe) const;
2297
2298 _LIBCPP_ALWAYS_INLINE
2299 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
2300 const tm* __tm, char __fmt, char __mod = 0) const
2301 {
2302 return do_put(__s, __iob, __fl, __tm, __fmt, __mod);
2303 }
2304
2305 static locale::id id;
2306
2307protected:
2308 ~time_put() {}
2309 virtual iter_type do_put(iter_type __s, ios_base&, char_type, const tm* __tm,
2310 char __fmt, char __mod) const;
2311
2312 explicit time_put(const char* __nm, size_t __refs)
2313 : locale::facet(__refs),
2314 __time_put(__nm) {}
2315 explicit time_put(const string& __nm, size_t __refs)
2316 : locale::facet(__refs),
2317 __time_put(__nm) {}
2318};
2319
2320template <class _CharT, class _OutputIterator>
2321locale::id
2322time_put<_CharT, _OutputIterator>::id;
2323
2324template <class _CharT, class _OutputIterator>
2325_OutputIterator
2326time_put<_CharT, _OutputIterator>::put(iter_type __s, ios_base& __iob,
2327 char_type __fl, const tm* __tm,
2328 const char_type* __pb,
2329 const char_type* __pe) const
2330{
2331 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2332 for (; __pb != __pe; ++__pb)
2333 {
2334 if (__ct.narrow(*__pb, 0) == '%')
2335 {
2336 if (++__pb == __pe)
2337 {
2338 *__s++ = __pb[-1];
2339 break;
2340 }
2341 char __mod = 0;
2342 char __fmt = __ct.narrow(*__pb, 0);
2343 if (__fmt == 'E' || __fmt == 'O')
2344 {
2345 if (++__pb == __pe)
2346 {
2347 *__s++ = __pb[-2];
2348 *__s++ = __pb[-1];
2349 break;
2350 }
2351 __mod = __fmt;
2352 __fmt = __ct.narrow(*__pb, 0);
2353 }
2354 __s = do_put(__s, __iob, __fl, __tm, __fmt, __mod);
2355 }
2356 else
2357 *__s++ = *__pb;
2358 }
2359 return __s;
2360}
2361
2362template <class _CharT, class _OutputIterator>
2363_OutputIterator
2364time_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
2365 char_type, const tm* __tm,
2366 char __fmt, char __mod) const
2367{
2368 char_type __nar[100];
2369 char_type* __nb = __nar;
2370 char_type* __ne = __nb + 100;
2371 __do_put(__nb, __ne, __tm, __fmt, __mod);
2372 return copy(__nb, __ne, __s);
2373}
2374
2375extern template class time_put<char>;
2376extern template class time_put<wchar_t>;
2377
2378template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
2379class time_put_byname
2380 : public time_put<_CharT, _OutputIterator>
2381{
2382public:
2383 _LIBCPP_ALWAYS_INLINE
2384 explicit time_put_byname(const char* __nm, size_t __refs = 0)
2385 : time_put<_CharT, _OutputIterator>(__nm, __refs) {}
2386
2387 _LIBCPP_ALWAYS_INLINE
2388 explicit time_put_byname(const string& __nm, size_t __refs = 0)
2389 : time_put<_CharT, _OutputIterator>(__nm, __refs) {}
2390
2391protected:
2392 ~time_put_byname() {}
2393};
2394
2395extern template class time_put_byname<char>;
2396extern template class time_put_byname<wchar_t>;
2397
2398// money_base
2399
2400class money_base
2401{
2402public:
2403 enum part {none, space, symbol, sign, value};
2404 struct pattern {char field[4];};
2405
2406 _LIBCPP_ALWAYS_INLINE money_base() {}
2407};
2408
2409// moneypunct
2410
2411template <class _CharT, bool _International = false>
2412class moneypunct
2413 : public locale::facet,
2414 public money_base
2415{
2416public:
2417 typedef _CharT char_type;
2418 typedef basic_string<char_type> string_type;
2419
2420 explicit moneypunct(size_t __refs = 0)
2421 : locale::facet(__refs) {}
2422
2423 _LIBCPP_ALWAYS_INLINE char_type decimal_point() const {return do_decimal_point();}
2424 _LIBCPP_ALWAYS_INLINE char_type thousands_sep() const {return do_thousands_sep();}
2425 _LIBCPP_ALWAYS_INLINE string grouping() const {return do_grouping();}
2426 _LIBCPP_ALWAYS_INLINE string_type curr_symbol() const {return do_curr_symbol();}
2427 _LIBCPP_ALWAYS_INLINE string_type positive_sign() const {return do_positive_sign();}
2428 _LIBCPP_ALWAYS_INLINE string_type negative_sign() const {return do_negative_sign();}
2429 _LIBCPP_ALWAYS_INLINE int frac_digits() const {return do_frac_digits();}
2430 _LIBCPP_ALWAYS_INLINE pattern pos_format() const {return do_pos_format();}
2431 _LIBCPP_ALWAYS_INLINE pattern neg_format() const {return do_neg_format();}
2432
2433 static locale::id id;
2434 static const bool intl = _International;
2435
2436protected:
2437 ~moneypunct() {}
2438
2439 virtual char_type do_decimal_point() const {return numeric_limits<char_type>::max();}
2440 virtual char_type do_thousands_sep() const {return numeric_limits<char_type>::max();}
2441 virtual string do_grouping() const {return string();}
2442 virtual string_type do_curr_symbol() const {return string_type();}
2443 virtual string_type do_positive_sign() const {return string_type();}
2444 virtual string_type do_negative_sign() const {return string_type(1, '-');}
2445 virtual int do_frac_digits() const {return 0;}
2446 virtual pattern do_pos_format() const
2447 {pattern __p = {symbol, sign, none, value}; return __p;}
2448 virtual pattern do_neg_format() const
2449 {pattern __p = {symbol, sign, none, value}; return __p;}
2450};
2451
2452template <class _CharT, bool _International>
2453locale::id
2454moneypunct<_CharT, _International>::id;
2455
2456extern template class moneypunct<char, false>;
2457extern template class moneypunct<char, true>;
2458extern template class moneypunct<wchar_t, false>;
2459extern template class moneypunct<wchar_t, true>;
2460
2461// moneypunct_byname
2462
2463template <class _CharT, bool _International = false>
2464class moneypunct_byname : public moneypunct<_CharT, _International>
2465{
2466public:
2467 typedef money_base::pattern pattern;
2468 typedef _CharT char_type;
2469 typedef basic_string<char_type> string_type;
2470
2471 _LIBCPP_ALWAYS_INLINE
2472 explicit moneypunct_byname(const char* __nm, size_t __refs = 0)
2473 : moneypunct<_CharT, _International>(__refs) {init(__nm);}
2474
2475 _LIBCPP_ALWAYS_INLINE
2476 explicit moneypunct_byname(const string& __nm, size_t __refs = 0)
2477 : moneypunct<_CharT, _International>(__refs) {init(__nm.c_str());}
2478
2479protected:
2480 ~moneypunct_byname() {}
2481
2482 virtual char_type do_decimal_point() const {return __decimal_point_;}
2483 virtual char_type do_thousands_sep() const {return __thousands_sep_;}
2484 virtual string do_grouping() const {return __grouping_;}
2485 virtual string_type do_curr_symbol() const {return __curr_symbol_;}
2486 virtual string_type do_positive_sign() const {return __positive_sign_;}
2487 virtual string_type do_negative_sign() const {return __negative_sign_;}
2488 virtual int do_frac_digits() const {return __frac_digits_;}
2489 virtual pattern do_pos_format() const {return __pos_format_;}
2490 virtual pattern do_neg_format() const {return __neg_format_;}
2491
2492private:
2493 char_type __decimal_point_;
2494 char_type __thousands_sep_;
2495 string __grouping_;
2496 string_type __curr_symbol_;
2497 string_type __positive_sign_;
2498 string_type __negative_sign_;
2499 int __frac_digits_;
2500 pattern __pos_format_;
2501 pattern __neg_format_;
2502
2503 void init(const char*);
2504};
2505
2506template<> void moneypunct_byname<char, false>::init(const char*);
2507template<> void moneypunct_byname<char, true>::init(const char*);
2508template<> void moneypunct_byname<wchar_t, false>::init(const char*);
2509template<> void moneypunct_byname<wchar_t, true>::init(const char*);
2510
2511extern template class moneypunct_byname<char, false>;
2512extern template class moneypunct_byname<char, true>;
2513extern template class moneypunct_byname<wchar_t, false>;
2514extern template class moneypunct_byname<wchar_t, true>;
2515
2516// money_get
2517
2518template <class _CharT>
2519class __money_get
2520{
2521protected:
2522 typedef _CharT char_type;
2523 typedef basic_string<char_type> string_type;
2524
2525 _LIBCPP_ALWAYS_INLINE __money_get() {}
2526
2527 static void __gather_info(bool __intl, const locale& __loc,
2528 money_base::pattern& __pat, char_type& __dp,
2529 char_type& __ts, string& __grp,
2530 string_type& __sym, string_type& __psn,
2531 string_type& __nsn, int& __fd);
2532};
2533
2534template <class _CharT>
2535void
2536__money_get<_CharT>::__gather_info(bool __intl, const locale& __loc,
2537 money_base::pattern& __pat, char_type& __dp,
2538 char_type& __ts, string& __grp,
2539 string_type& __sym, string_type& __psn,
2540 string_type& __nsn, int& __fd)
2541{
2542 if (__intl)
2543 {
2544 const moneypunct<char_type, true>& __mp =
2545 use_facet<moneypunct<char_type, true> >(__loc);
2546 __pat = __mp.neg_format();
2547 __nsn = __mp.negative_sign();
2548 __psn = __mp.positive_sign();
2549 __dp = __mp.decimal_point();
2550 __ts = __mp.thousands_sep();
2551 __grp = __mp.grouping();
2552 __sym = __mp.curr_symbol();
2553 __fd = __mp.frac_digits();
2554 }
2555 else
2556 {
2557 const moneypunct<char_type, false>& __mp =
2558 use_facet<moneypunct<char_type, false> >(__loc);
2559 __pat = __mp.neg_format();
2560 __nsn = __mp.negative_sign();
2561 __psn = __mp.positive_sign();
2562 __dp = __mp.decimal_point();
2563 __ts = __mp.thousands_sep();
2564 __grp = __mp.grouping();
2565 __sym = __mp.curr_symbol();
2566 __fd = __mp.frac_digits();
2567 }
2568}
2569
2570extern template class __money_get<char>;
2571extern template class __money_get<wchar_t>;
2572
2573template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
2574class money_get
2575 : public locale::facet,
2576 private __money_get<_CharT>
2577{
2578public:
2579 typedef _CharT char_type;
2580 typedef _InputIterator iter_type;
2581 typedef basic_string<char_type> string_type;
2582
2583 _LIBCPP_ALWAYS_INLINE
2584 explicit money_get(size_t __refs = 0)
2585 : locale::facet(__refs) {}
2586
2587 _LIBCPP_ALWAYS_INLINE
2588 iter_type get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob,
2589 ios_base::iostate& __err, long double& __v) const
2590 {
2591 return do_get(__b, __e, __intl, __iob, __err, __v);
2592 }
2593
2594 _LIBCPP_ALWAYS_INLINE
2595 iter_type get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob,
2596 ios_base::iostate& __err, string_type& __v) const
2597 {
2598 return do_get(__b, __e, __intl, __iob, __err, __v);
2599 }
2600
2601 static locale::id id;
2602
2603protected:
2604
2605 ~money_get() {}
2606
2607 virtual iter_type do_get(iter_type __b, iter_type __e, bool __intl,
2608 ios_base& __iob, ios_base::iostate& __err,
2609 long double& __v) const;
2610 virtual iter_type do_get(iter_type __b, iter_type __e, bool __intl,
2611 ios_base& __iob, ios_base::iostate& __err,
2612 string_type& __v) const;
2613
2614private:
2615 static bool __do_get(iter_type& __b, iter_type __e,
2616 bool __intl, const locale& __loc,
2617 ios_base::fmtflags __flags, ios_base::iostate& __err,
2618 bool& __neg, const ctype<char_type>& __ct,
2619 unique_ptr<char_type, void(*)(void*)>& __wb,
2620 char_type*& __wn, char_type* __we);
2621};
2622
2623template <class _CharT, class _InputIterator>
2624locale::id
2625money_get<_CharT, _InputIterator>::id;
2626
2627void __do_nothing(void*);
2628
2629template <class _Tp>
2630_LIBCPP_HIDDEN
2631void
2632__double_or_nothing(unique_ptr<_Tp, void(*)(void*)>& __b, _Tp*& __n, _Tp*& __e)
2633{
2634 bool __owns = __b.get_deleter() != __do_nothing;
2635 size_t __cur_cap = (__e-__b.get()) * sizeof(_Tp);
2636 size_t __new_cap = __cur_cap < numeric_limits<size_t>::max() / 2 ?
2637 2 * __cur_cap : numeric_limits<size_t>::max();
2638 size_t __n_off = __n - __b.get();
2639 _Tp* __t = (_Tp*)realloc(__owns ? __b.get() : 0, __new_cap);
2640 if (__t == 0)
2641 __throw_bad_alloc();
2642 if (__owns)
2643 __b.release();
2644 __b = unique_ptr<_Tp, void(*)(void*)>(__t, free);
2645 __new_cap /= sizeof(_Tp);
2646 __n = __b.get() + __n_off;
2647 __e = __b.get() + __new_cap;
2648}
2649
2650// true == success
2651template <class _CharT, class _InputIterator>
2652bool
2653money_get<_CharT, _InputIterator>::__do_get(iter_type& __b, iter_type __e,
2654 bool __intl, const locale& __loc,
2655 ios_base::fmtflags __flags,
2656 ios_base::iostate& __err,
2657 bool& __neg,
2658 const ctype<char_type>& __ct,
2659 unique_ptr<char_type, void(*)(void*)>& __wb,
2660 char_type*& __wn, char_type* __we)
2661{
2662 const unsigned __bz = 100;
2663 unsigned __gbuf[__bz];
2664 unique_ptr<unsigned, void(*)(void*)> __gb(__gbuf, __do_nothing);
2665 unsigned* __gn = __gb.get();
2666 unsigned* __ge = __gn + __bz;
2667 money_base::pattern __pat;
2668 char_type __dp;
2669 char_type __ts;
2670 string __grp;
2671 string_type __sym;
2672 string_type __psn;
2673 string_type __nsn;
2674 int __fd;
2675 __money_get<_CharT>::__gather_info(__intl, __loc, __pat, __dp, __ts, __grp,
2676 __sym, __psn, __nsn, __fd);
2677 const string_type* __trailing_sign = 0;
2678 __wn = __wb.get();
2679 for (unsigned __p = 0; __p < 4 && __b != __e; ++__p)
2680 {
2681 switch (__pat.field[__p])
2682 {
2683 case money_base::space:
2684 if (__p != 3)
2685 {
2686 if (__ct.is(ctype_base::space, *__b))
2687 ++__b;
2688 else
2689 {
2690 __err |= ios_base::failbit;
2691 return false;
2692 }
2693 }
2694 // drop through
2695 case money_base::none:
2696 if (__p != 3)
2697 {
2698 while (__b != __e && __ct.is(ctype_base::space, *__b))
2699 ++__b;
2700 }
2701 break;
2702 case money_base::sign:
2703 if (__psn.size() + __nsn.size() > 0)
2704 {
2705 if (__psn.size() == 0 || __nsn.size() == 0)
2706 { // sign is optional
2707 if (__psn.size() > 0)
2708 { // __nsn.size() == 0
2709 if (*__b == __psn[0])
2710 {
2711 ++__b;
2712 if (__psn.size() > 1)
2713 __trailing_sign = &__psn;
2714 }
2715 else
2716 __neg = true;
2717 }
2718 else if (*__b == __nsn[0]) // __nsn.size() > 0 && __psn.size() == 0
2719 {
2720 ++__b;
2721 __neg = true;
2722 if (__nsn.size() > 1)
2723 __trailing_sign = &__nsn;
2724 }
2725 }
2726 else // sign is required
2727 {
2728 if (*__b == __psn[0])
2729 {
2730 ++__b;
2731 if (__psn.size() > 1)
2732 __trailing_sign = &__psn;
2733 }
2734 else if (*__b == __nsn[0])
2735 {
2736 ++__b;
2737 __neg = true;
2738 if (__nsn.size() > 1)
2739 __trailing_sign = &__nsn;
2740 }
2741 else
2742 {
2743 __err |= ios_base::failbit;
2744 return false;
2745 }
2746 }
2747 }
2748 break;
2749 case money_base::symbol:
2750 {
2751 bool __more_needed = __trailing_sign ||
2752 (__p < 2) ||
2753 (__p == 2 && __pat.field[3] != static_cast<char>(money_base::none));
2754 bool __sb = __flags & ios_base::showbase;
2755 if (__sb || __more_needed)
2756 {
2757 ios_base::iostate __et = ios_base::goodbit;
2758 string_type* __k = __scan_keyword(__b, __e, &__sym, &__sym+1,
2759 __ct, __et);
2760 if (__sb && __k != &__sym)
2761 {
2762 __err |= ios_base::failbit;
2763 return false;
2764 }
2765 }
2766 }
2767 break;
2768 case money_base::value:
2769 {
2770 unsigned __ng = 0;
2771 for (; __b != __e; ++__b)
2772 {
2773 char_type __c = *__b;
2774 if (__ct.is(ctype_base::digit, __c))
2775 {
2776 if (__wn == __we)
2777 __double_or_nothing(__wb, __wn, __we);
2778 *__wn++ = __c;
2779 ++__ng;
2780 }
2781 else if (__grp.size() > 0 && __ng > 0 && __c == __ts)
2782 {
2783 if (__gn == __ge)
2784 __double_or_nothing(__gb, __gn, __ge);
2785 *__gn++ = __ng;
2786 __ng = 0;
2787 }
2788 else
2789 break;
2790 }
2791 if (__gb.get() != __gn && __ng > 0)
2792 {
2793 if (__gn == __ge)
2794 __double_or_nothing(__gb, __gn, __ge);
2795 *__gn++ = __ng;
2796 }
2797 if (__fd > 0)
2798 {
2799 if (__b == __e || *__b != __dp)
2800 {
2801 __err |= ios_base::failbit;
2802 return false;
2803 }
2804 for (++__b; __fd > 0; --__fd, ++__b)
2805 {
2806 if (__b == __e || !__ct.is(ctype_base::digit, *__b))
2807 {
2808 __err |= ios_base::failbit;
2809 return false;
2810 }
2811 if (__wn == __we)
2812 __double_or_nothing(__wb, __wn, __we);
2813 *__wn++ = *__b;
2814 }
2815 }
2816 if (__wn == __wb.get())
2817 {
2818 __err |= ios_base::failbit;
2819 return false;
2820 }
2821 }
2822 break;
2823 }
2824 }
2825 if (__trailing_sign)
2826 {
2827 for (unsigned __i = 1; __i < __trailing_sign->size(); ++__i, ++__b)
2828 {
2829 if (__b == __e || *__b != (*__trailing_sign)[__i])
2830 {
2831 __err |= ios_base::failbit;
2832 return false;
2833 }
2834 }
2835 }
2836 if (__gb.get() != __gn)
2837 {
2838 ios_base::iostate __et = ios_base::goodbit;
2839 __check_grouping(__grp, __gb.get(), __gn, __et);
2840 if (__et)
2841 {
2842 __err |= ios_base::failbit;
2843 return false;
2844 }
2845 }
2846 return true;
2847}
2848
2849template <class _CharT, class _InputIterator>
2850_InputIterator
2851money_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
2852 bool __intl, ios_base& __iob,
2853 ios_base::iostate& __err,
2854 long double& __v) const
2855{
2856 const unsigned __bz = 100;
2857 char_type __wbuf[__bz];
2858 unique_ptr<char_type, void(*)(void*)> __wb(__wbuf, __do_nothing);
2859 char_type* __wn;
2860 char_type* __we = __wbuf + __bz;
2861 locale __loc = __iob.getloc();
2862 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
2863 bool __neg = false;
2864 if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct,
2865 __wb, __wn, __we))
2866 {
2867 const char __src[] = "0123456789";
2868 char_type __atoms[sizeof(__src)-1];
2869 __ct.widen(__src, __src + (sizeof(__src)-1), __atoms);
2870 char __nbuf[__bz];
2871 char* __nc = __nbuf;
2872 unique_ptr<char, void(*)(void*)> __h(0, free);
2873 if (__wn - __wb.get() > __bz-2)
2874 {
2875 __h.reset((char*)malloc(__wn - __wb.get() + 2));
2876 if (__h.get() == 0)
2877 __throw_bad_alloc();
2878 __nc = __h.get();
2879 }
2880 if (__neg)
2881 *__nc++ = '-';
2882 for (const char_type* __w = __wb.get(); __w < __wn; ++__w, ++__nc)
2883 *__nc = __src[find(__atoms, __atoms+sizeof(__atoms), *__w) - __atoms];
2884 *__nc = char();
2885 if (sscanf(__nbuf, "%Lf", &__v) != 1)
2886 __throw_runtime_error("money_get error");
2887 }
2888 if (__b == __e)
2889 __err |= ios_base::eofbit;
2890 return __b;
2891}
2892
2893template <class _CharT, class _InputIterator>
2894_InputIterator
2895money_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
2896 bool __intl, ios_base& __iob,
2897 ios_base::iostate& __err,
2898 string_type& __v) const
2899{
2900 const unsigned __bz = 100;
2901 char_type __wbuf[__bz];
2902 unique_ptr<char_type, void(*)(void*)> __wb(__wbuf, __do_nothing);
2903 char_type* __wn;
2904 char_type* __we = __wbuf + __bz;
2905 locale __loc = __iob.getloc();
2906 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
2907 bool __neg = false;
2908 if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct,
2909 __wb, __wn, __we))
2910 {
2911 __v.clear();
2912 if (__neg)
2913 __v.push_back(__ct.widen('-'));
2914 char_type __z = __ct.widen('0');
2915 char_type* __w;
2916 for (__w = __wb.get(); __w < __wn-1; ++__w)
2917 if (*__w != __z)
2918 break;
2919 __v.append(__w, __wn);
2920 }
2921 if (__b == __e)
2922 __err |= ios_base::eofbit;
2923 return __b;
2924}
2925
2926extern template class money_get<char>;
2927extern template class money_get<wchar_t>;
2928
2929// money_put
2930
2931template <class _CharT>
2932class __money_put
2933{
2934protected:
2935 typedef _CharT char_type;
2936 typedef basic_string<char_type> string_type;
2937
2938 _LIBCPP_ALWAYS_INLINE __money_put() {}
2939
2940 static void __gather_info(bool __intl, bool __neg, const locale& __loc,
2941 money_base::pattern& __pat, char_type& __dp,
2942 char_type& __ts, string& __grp,
2943 string_type& __sym, string_type& __sn,
2944 int& __fd);
2945 static void __format(char_type* __mb, char_type*& __mi, char_type*& __me,
2946 ios_base::fmtflags __flags,
2947 const char_type* __db, const char_type* __de,
2948 const ctype<char_type>& __ct, bool __neg,
2949 const money_base::pattern& __pat, char_type __dp,
2950 char_type __ts, const string& __grp,
2951 const string_type& __sym, const string_type& __sn,
2952 int __fd);
2953};
2954
2955template <class _CharT>
2956void
2957__money_put<_CharT>::__gather_info(bool __intl, bool __neg, const locale& __loc,
2958 money_base::pattern& __pat, char_type& __dp,
2959 char_type& __ts, string& __grp,
2960 string_type& __sym, string_type& __sn,
2961 int& __fd)
2962{
2963 if (__intl)
2964 {
2965 const moneypunct<char_type, true>& __mp =
2966 use_facet<moneypunct<char_type, true> >(__loc);
2967 if (__neg)
2968 {
2969 __pat = __mp.neg_format();
2970 __sn = __mp.negative_sign();
2971 }
2972 else
2973 {
2974 __pat = __mp.pos_format();
2975 __sn = __mp.positive_sign();
2976 }
2977 __dp = __mp.decimal_point();
2978 __ts = __mp.thousands_sep();
2979 __grp = __mp.grouping();
2980 __sym = __mp.curr_symbol();
2981 __fd = __mp.frac_digits();
2982 }
2983 else
2984 {
2985 const moneypunct<char_type, false>& __mp =
2986 use_facet<moneypunct<char_type, false> >(__loc);
2987 if (__neg)
2988 {
2989 __pat = __mp.neg_format();
2990 __sn = __mp.negative_sign();
2991 }
2992 else
2993 {
2994 __pat = __mp.pos_format();
2995 __sn = __mp.positive_sign();
2996 }
2997 __dp = __mp.decimal_point();
2998 __ts = __mp.thousands_sep();
2999 __grp = __mp.grouping();
3000 __sym = __mp.curr_symbol();
3001 __fd = __mp.frac_digits();
3002 }
3003}
3004
3005template <class _CharT>
3006void
3007__money_put<_CharT>::__format(char_type* __mb, char_type*& __mi, char_type*& __me,
3008 ios_base::fmtflags __flags,
3009 const char_type* __db, const char_type* __de,
3010 const ctype<char_type>& __ct, bool __neg,
3011 const money_base::pattern& __pat, char_type __dp,
3012 char_type __ts, const string& __grp,
3013 const string_type& __sym, const string_type& __sn,
3014 int __fd)
3015{
3016 __me = __mb;
3017 for (unsigned __p = 0; __p < 4; ++__p)
3018 {
3019 switch (__pat.field[__p])
3020 {
3021 case money_base::none:
3022 __mi = __me;
3023 break;
3024 case money_base::space:
3025 __mi = __me;
3026 *__me++ = __ct.widen(' ');
3027 break;
3028 case money_base::sign:
3029 if (!__sn.empty())
3030 *__me++ = __sn[0];
3031 break;
3032 case money_base::symbol:
3033 if (!__sym.empty() && (__flags & ios_base::showbase))
3034 __me = copy(__sym.begin(), __sym.end(), __me);
3035 break;
3036 case money_base::value:
3037 {
3038 // remember start of value so we can reverse it
3039 char_type* __t = __me;
3040 // find beginning of digits
3041 if (__neg)
3042 ++__db;
3043 // find end of digits
3044 const char_type* __d;
3045 for (__d = __db; __d < __de; ++__d)
3046 if (!__ct.is(ctype_base::digit, *__d))
3047 break;
3048 // print fractional part
3049 if (__fd > 0)
3050 {
3051 int __f;
3052 for (__f = __fd; __d > __db && __f > 0; --__f)
3053 *__me++ = *--__d;
3054 char_type __z = __f > 0 ? __ct.widen('0') : char_type();
3055 for (; __f > 0; --__f)
3056 *__me++ = __z;
3057 *__me++ = __dp;
3058 }
3059 // print units part
3060 if (__d == __db)
3061 {
3062 *__me++ = __ct.widen('0');
3063 }
3064 else
3065 {
3066 unsigned __ng = 0;
3067 unsigned __ig = 0;
3068 unsigned __gl = __grp.empty() ? numeric_limits<unsigned>::max()
3069 : static_cast<unsigned>(__grp[__ig]);
3070 while (__d != __db)
3071 {
3072 if (__ng == __gl)
3073 {
3074 *__me++ = __ts;
3075 __ng = 0;
3076 if (++__ig < __grp.size())
3077 __gl = __grp[__ig] == numeric_limits<char>::max() ?
3078 numeric_limits<unsigned>::max() :
3079 static_cast<unsigned>(__grp[__ig]);
3080 }
3081 *__me++ = *--__d;
3082 ++__ng;
3083 }
3084 }
3085 // reverse it
3086 reverse(__t, __me);
3087 }
3088 break;
3089 }
3090 }
3091 // print rest of sign, if any
3092 if (__sn.size() > 1)
3093 __me = copy(__sn.begin()+1, __sn.end(), __me);
3094 // set alignment
3095 if ((__flags & ios_base::adjustfield) == ios_base::left)
3096 __mi = __me;
3097 else if ((__flags & ios_base::adjustfield) != ios_base::internal)
3098 __mi = __mb;
3099}
3100
3101extern template class __money_put<char>;
3102extern template class __money_put<wchar_t>;
3103
3104template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
3105class money_put
3106 : public locale::facet,
3107 private __money_put<_CharT>
3108{
3109public:
3110 typedef _CharT char_type;
3111 typedef _OutputIterator iter_type;
3112 typedef basic_string<char_type> string_type;
3113
3114 _LIBCPP_ALWAYS_INLINE
3115 explicit money_put(size_t __refs = 0)
3116 : locale::facet(__refs) {}
3117
3118 _LIBCPP_ALWAYS_INLINE
3119 iter_type put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl,
3120 long double __units) const
3121 {
3122 return do_put(__s, __intl, __iob, __fl, __units);
3123 }
3124
3125 _LIBCPP_ALWAYS_INLINE
3126 iter_type put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl,
3127 const string_type& __digits) const
3128 {
3129 return do_put(__s, __intl, __iob, __fl, __digits);
3130 }
3131
3132 static locale::id id;
3133
3134protected:
3135 ~money_put() {}
3136
3137 virtual iter_type do_put(iter_type __s, bool __intl, ios_base& __iob,
3138 char_type __fl, long double __units) const;
3139 virtual iter_type do_put(iter_type __s, bool __intl, ios_base& __iob,
3140 char_type __fl, const string_type& __digits) const;
3141};
3142
3143template <class _CharT, class _OutputIterator>
3144locale::id
3145money_put<_CharT, _OutputIterator>::id;
3146
3147template <class _CharT, class _OutputIterator>
3148_OutputIterator
3149money_put<_CharT, _OutputIterator>::do_put(iter_type __s, bool __intl,
3150 ios_base& __iob, char_type __fl,
3151 long double __units) const
3152{
3153 // convert to char
3154 const size_t __bs = 100;
3155 char __buf[__bs];
3156 char* __bb = __buf;
3157 char_type __digits[__bs];
3158 char_type* __db = __digits;
3159 size_t __n = snprintf(__bb, __bs, "%.0Lf", __units);
3160 unique_ptr<char, void(*)(void*)> __hn(0, free);
3161 unique_ptr<char_type, void(*)(void*)> __hd(0, free);
3162 // secure memory for digit storage
3163 if (__n > __bs-1)
3164 {
3165 __n = asprintf_l(&__bb, 0, "%.0Lf", __units);
3166 if (__bb == 0)
3167 __throw_bad_alloc();
3168 __hn.reset(__bb);
3169 __hd.reset((char_type*)malloc(__n * sizeof(char_type)));
3170 if (__hd == 0)
3171 __throw_bad_alloc();
3172 __db = __hd.get();
3173 }
3174 // gather info
3175 locale __loc = __iob.getloc();
3176 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3177 __ct.widen(__bb, __bb + __n, __db);
3178 bool __neg = __n > 0 && __bb[0] == '-';
3179 money_base::pattern __pat;
3180 char_type __dp;
3181 char_type __ts;
3182 string __grp;
3183 string_type __sym;
3184 string_type __sn;
3185 int __fd;
3186 this->__gather_info(__intl, __neg, __loc, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3187 // secure memory for formatting
3188 char_type __mbuf[__bs];
3189 char_type* __mb = __mbuf;
3190 unique_ptr<char_type, void(*)(void*)> __hw(0, free);
3191 size_t __exn = static_cast<int>(__n) > __fd ?
3192 (__n - __fd) * 2 + __sn.size() + __sym.size() + __fd + 1
3193 : __sn.size() + __sym.size() + __fd + 2;
3194 if (__exn > __bs)
3195 {
3196 __hw.reset((char_type*)malloc(__exn * sizeof(char_type)));
3197 __mb = __hw.get();
3198 if (__mb == 0)
3199 __throw_bad_alloc();
3200 }
3201 // format
3202 char_type* __mi;
3203 char_type* __me;
3204 this->__format(__mb, __mi, __me, __iob.flags(),
3205 __db, __db + __n, __ct,
3206 __neg, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3207 return __pad_and_output(__s, __mb, __mi, __me, __iob, __fl);
3208}
3209
3210template <class _CharT, class _OutputIterator>
3211_OutputIterator
3212money_put<_CharT, _OutputIterator>::do_put(iter_type __s, bool __intl,
3213 ios_base& __iob, char_type __fl,
3214 const string_type& __digits) const
3215{
3216 // gather info
3217 locale __loc = __iob.getloc();
3218 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3219 bool __neg = __digits.size() > 0 && __digits[0] == __ct.widen('-');
3220 money_base::pattern __pat;
3221 char_type __dp;
3222 char_type __ts;
3223 string __grp;
3224 string_type __sym;
3225 string_type __sn;
3226 int __fd;
3227 this->__gather_info(__intl, __neg, __loc, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3228 // secure memory for formatting
3229 char_type __mbuf[100];
3230 char_type* __mb = __mbuf;
3231 unique_ptr<char_type, void(*)(void*)> __h(0, free);
3232 size_t __exn = __digits.size() > __fd ?
3233 (__digits.size() - __fd) * 2 + __sn.size() + __sym.size() + __fd + 1
3234 : __sn.size() + __sym.size() + __fd + 2;
3235 if (__exn > 100)
3236 {
3237 __h.reset((char_type*)malloc(__exn * sizeof(char_type)));
3238 __mb = __h.get();
3239 if (__mb == 0)
3240 __throw_bad_alloc();
3241 }
3242 // format
3243 char_type* __mi;
3244 char_type* __me;
3245 this->__format(__mb, __mi, __me, __iob.flags(),
3246 __digits.data(), __digits.data() + __digits.size(), __ct,
3247 __neg, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3248 return __pad_and_output(__s, __mb, __mi, __me, __iob, __fl);
3249}
3250
3251extern template class money_put<char>;
3252extern template class money_put<wchar_t>;
3253
3254// messages
3255
3256class messages_base
3257{
3258public:
3259 typedef nl_catd catalog;
3260
3261 _LIBCPP_ALWAYS_INLINE messages_base() {}
3262};
3263
3264template <class _CharT>
3265class messages
3266 : public locale::facet,
3267 public messages_base
3268{
3269public:
3270 typedef _CharT char_type;
3271 typedef basic_string<_CharT> string_type;
3272
3273 _LIBCPP_ALWAYS_INLINE
3274 explicit messages(size_t __refs = 0)
3275 : locale::facet(__refs) {}
3276
3277 _LIBCPP_ALWAYS_INLINE
3278 catalog open(const basic_string<char>& __nm, const locale& __loc) const
3279 {
3280 return do_open(__nm, __loc);
3281 }
3282
3283 _LIBCPP_ALWAYS_INLINE
3284 string_type get(catalog __c, int __set, int __msgid,
3285 const string_type& __dflt) const
3286 {
3287 return do_get(__c, __set, __msgid, __dflt);
3288 }
3289
3290 _LIBCPP_ALWAYS_INLINE
3291 void close(catalog __c) const
3292 {
3293 do_close(__c);
3294 }
3295
3296 static locale::id id;
3297
3298protected:
3299 ~messages() {}
3300
3301 virtual catalog do_open(const basic_string<char>&, const locale&) const;
3302 virtual string_type do_get(catalog, int __set, int __msgid,
3303 const string_type& __dflt) const;
3304 virtual void do_close(catalog) const;
3305};
3306
3307template <class _CharT>
3308locale::id
3309messages<_CharT>::id;
3310
3311template <class _CharT>
3312typename messages<_CharT>::catalog
3313messages<_CharT>::do_open(const basic_string<char>& __nm, const locale&) const
3314{
3315 return catopen(__nm.c_str(), NL_CAT_LOCALE);
3316}
3317
3318template <class _CharT>
3319typename messages<_CharT>::string_type
3320messages<_CharT>::do_get(catalog __c, int __set, int __msgid,
3321 const string_type& __dflt) const
3322{
3323 string __ndflt;
3324 __narrow_to_utf8<sizeof(char_type)*__CHAR_BIT__>()(back_inserter(__ndflt),
3325 __dflt.c_str(),
3326 __dflt.c_str() + __dflt.size());
3327 char* __n = catgets(__c, __set, __msgid, __ndflt.c_str());
3328 string_type __w;
3329 __widen_from_utf8<sizeof(char_type)*__CHAR_BIT__>()(back_inserter(__w),
3330 __n, __n + strlen(__n));
3331 return __w;
3332}
3333
3334template <class _CharT>
3335void
3336messages<_CharT>::do_close(catalog __c) const
3337{
3338 catclose(__c);
3339}
3340
3341extern template class messages<char>;
3342extern template class messages<wchar_t>;
3343
3344template <class _CharT>
3345class messages_byname
3346 : public messages<_CharT>
3347{
3348public:
3349 typedef messages_base::catalog catalog;
3350 typedef basic_string<_CharT> string_type;
3351
3352 _LIBCPP_ALWAYS_INLINE
3353 explicit messages_byname(const char*, size_t __refs = 0)
3354 : messages<_CharT>(__refs) {}
3355
3356 _LIBCPP_ALWAYS_INLINE
3357 explicit messages_byname(const string&, size_t __refs = 0)
3358 : messages<_CharT>(__refs) {}
3359
3360protected:
3361 ~messages_byname() {}
3362};
3363
3364extern template class messages_byname<char>;
3365extern template class messages_byname<wchar_t>;
3366
3367_LIBCPP_END_NAMESPACE_STD
3368
3369#endif // _LIBCPP_LOCALE