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