blob: 047da71a48cba1a8696c41da3bf05ba365c99fe1 [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
Howard Hinnant324bb032010-08-22 00:02:43 +0000267#else // __APPLE__
Howard Hinnantadff4892010-05-24 17:49:41 +0000268inline 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}
Howard Hinnant324bb032010-08-22 00:02:43 +0000318#endif // __APPLE__
Howard Hinnantadff4892010-05-24 17:49:41 +0000319
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
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000459template <class _CharT>
460struct __num_get
461 : protected __num_get_base
462{
463 static string __stage2_int_prep(ios_base& __iob, _CharT* __atoms, _CharT& __thousands_sep);
464 static string __stage2_float_prep(ios_base& __iob, _CharT* __atoms, _CharT& __decimal_point,
465 _CharT& __thousands_sep);
466 static int __stage2_int_loop(_CharT __ct, int __base, char* __a, char*& __a_end,
467 unsigned& __dc, _CharT __thousands_sep, const string& __grouping,
468 unsigned* __g, unsigned*& __g_end, _CharT* __atoms);
469 static int __stage2_float_loop(_CharT __ct, bool& __in_units, char& __exp,
470 char* __a, char*& __a_end,
471 _CharT __decimal_point, _CharT __thousands_sep,
472 const string& __grouping, unsigned* __g,
473 unsigned*& __g_end, unsigned& __dc, _CharT* __atoms);
474};
475
476template <class _CharT>
477string
478__num_get<_CharT>::__stage2_int_prep(ios_base& __iob, _CharT* __atoms, _CharT& __thousands_sep)
479{
480 locale __loc = __iob.getloc();
481 use_facet<ctype<_CharT> >(__loc).widen(__src, __src + 26, __atoms);
482 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
483 __thousands_sep = __np.thousands_sep();
484 return __np.grouping();
485}
486
487template <class _CharT>
488string
489__num_get<_CharT>::__stage2_float_prep(ios_base& __iob, _CharT* __atoms, _CharT& __decimal_point,
490 _CharT& __thousands_sep)
491{
492 locale __loc = __iob.getloc();
493 use_facet<ctype<_CharT> >(__loc).widen(__src, __src + 32, __atoms);
494 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
495 __decimal_point = __np.decimal_point();
496 __thousands_sep = __np.thousands_sep();
497 return __np.grouping();
498}
499
500template <class _CharT>
501int
502__num_get<_CharT>::__stage2_int_loop(_CharT __ct, int __base, char* __a, char*& __a_end,
503 unsigned& __dc, _CharT __thousands_sep, const string& __grouping,
504 unsigned* __g, unsigned*& __g_end, _CharT* __atoms)
505{
506 if (__ct == __thousands_sep && __grouping.size() != 0)
507 {
508 if (__g_end-__g < __num_get_buf_sz)
509 {
510 *__g_end++ = __dc;
511 __dc = 0;
512 }
513 return 0;
514 }
515 ptrdiff_t __f = find(__atoms, __atoms + 26, __ct) - __atoms;
516 if (__f >= 26)
517 return -1;
518 if (__a_end-__a < __num_get_buf_sz - 1)
519 *__a_end++ = __src[__f];
520 switch (__base)
521 {
522 case 8:
523 case 10:
524 if (__f >= __base)
525 return 0;
526 break;
527 default:
528 if (__f >= 22)
529 return 0;
530 break;
531 }
532 ++__dc;
533 return 0;
534}
535
536template <class _CharT>
537int
538__num_get<_CharT>::__stage2_float_loop(_CharT __ct, bool& __in_units, char& __exp, char* __a, char*& __a_end,
539 _CharT __decimal_point, _CharT __thousands_sep, const string& __grouping,
540 unsigned* __g, unsigned*& __g_end, unsigned& __dc, _CharT* __atoms)
541{
542 if (__ct == __decimal_point)
543 {
544 if (!__in_units)
545 return -1;
546 __in_units = false;
547 *__a_end++ = '.';
548 if (__grouping.size() != 0 && __g_end-__g < __num_get_buf_sz)
549 *__g_end++ = __dc;
550 return 0;
551 }
552 if (__ct == __thousands_sep && __grouping.size() != 0)
553 {
554 if (!__in_units)
555 return -1;
556 if (__g_end-__g < __num_get_buf_sz)
557 {
558 *__g_end++ = __dc;
559 __dc = 0;
560 }
561 return 0;
562 }
563 ptrdiff_t __f = find(__atoms, __atoms + 32, __ct) - __atoms;
564 if (__f >= 32)
565 return -1;
566 char __x = __src[__f];
567 if (__a_end-__a < __num_get_buf_sz - 1)
568 *__a_end++ = __x;
569 if (__x == 'x' || __x == 'X')
570 __exp = 'P';
571 else if ((__x & 0xDF) == __exp)
572 {
573 __in_units = false;
574 if (__grouping.size() != 0 && __g_end-__g < __num_get_buf_sz)
575 *__g_end++ = __dc;
576 }
577 if (__f >= 22)
578 return 0;
579 ++__dc;
580 return 0;
581}
582
583extern template class __num_get<char>;
584extern template class __num_get<wchar_t>;
585
586template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
587class num_get
588 : public locale::facet,
589 private __num_get<_CharT>
590{
591public:
592 typedef _CharT char_type;
593 typedef _InputIterator iter_type;
594
595 _LIBCPP_ALWAYS_INLINE
596 explicit num_get(size_t __refs = 0)
597 : locale::facet(__refs) {}
598
599 _LIBCPP_ALWAYS_INLINE
600 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
601 ios_base::iostate& __err, bool& __v) const
602 {
603 return do_get(__b, __e, __iob, __err, __v);
604 }
605
606 _LIBCPP_ALWAYS_INLINE
607 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
608 ios_base::iostate& __err, long& __v) const
609 {
610 return do_get(__b, __e, __iob, __err, __v);
611 }
612
613 _LIBCPP_ALWAYS_INLINE
614 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
615 ios_base::iostate& __err, long long& __v) const
616 {
617 return do_get(__b, __e, __iob, __err, __v);
618 }
619
620 _LIBCPP_ALWAYS_INLINE
621 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
622 ios_base::iostate& __err, unsigned short& __v) const
623 {
624 return do_get(__b, __e, __iob, __err, __v);
625 }
626
627 _LIBCPP_ALWAYS_INLINE
628 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
629 ios_base::iostate& __err, unsigned int& __v) const
630 {
631 return do_get(__b, __e, __iob, __err, __v);
632 }
633
634 _LIBCPP_ALWAYS_INLINE
635 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
636 ios_base::iostate& __err, unsigned long& __v) const
637 {
638 return do_get(__b, __e, __iob, __err, __v);
639 }
640
641 _LIBCPP_ALWAYS_INLINE
642 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
643 ios_base::iostate& __err, unsigned long long& __v) const
644 {
645 return do_get(__b, __e, __iob, __err, __v);
646 }
647
648 _LIBCPP_ALWAYS_INLINE
649 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
650 ios_base::iostate& __err, float& __v) const
651 {
652 return do_get(__b, __e, __iob, __err, __v);
653 }
654
655 _LIBCPP_ALWAYS_INLINE
656 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
657 ios_base::iostate& __err, double& __v) const
658 {
659 return do_get(__b, __e, __iob, __err, __v);
660 }
661
662 _LIBCPP_ALWAYS_INLINE
663 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
664 ios_base::iostate& __err, long double& __v) const
665 {
666 return do_get(__b, __e, __iob, __err, __v);
667 }
668
669 _LIBCPP_ALWAYS_INLINE
670 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
671 ios_base::iostate& __err, void*& __v) const
672 {
673 return do_get(__b, __e, __iob, __err, __v);
674 }
675
676 static locale::id id;
677
678protected:
679 ~num_get() {}
680
681 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
682 ios_base::iostate& __err, bool& __v) const;
683 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
684 ios_base::iostate& __err, long& __v) const;
685 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
686 ios_base::iostate& __err, long long& __v) const;
687 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
688 ios_base::iostate& __err, unsigned short& __v) const;
689 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
690 ios_base::iostate& __err, unsigned int& __v) const;
691 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
692 ios_base::iostate& __err, unsigned long& __v) const;
693 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
694 ios_base::iostate& __err, unsigned long long& __v) const;
695 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
696 ios_base::iostate& __err, float& __v) const;
697 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
698 ios_base::iostate& __err, double& __v) const;
699 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
700 ios_base::iostate& __err, long double& __v) const;
701 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
702 ios_base::iostate& __err, void*& __v) const;
703};
704
705template <class _CharT, class _InputIterator>
706locale::id
707num_get<_CharT, _InputIterator>::id;
708
709template <class _Tp>
710_Tp
711__num_get_signed_integral(const char* __a, const char* __a_end,
712 ios_base::iostate& __err, int __base)
713{
714 if (__a != __a_end)
715 {
716 char *__p2;
717 long long __ll = strtoll_l(__a, &__p2, __base, 0);
718 if (__p2 != __a_end)
719 {
720 __err = ios_base::failbit;
721 return 0;
722 }
723 else if (__ll > numeric_limits<_Tp>::max())
724 {
725 __err = ios_base::failbit;
726 return numeric_limits<_Tp>::max();
727 }
728 else if (__ll < numeric_limits<_Tp>::min())
729 {
730 __err = ios_base::failbit;
731 return numeric_limits<_Tp>::min();
732 }
733 return static_cast<_Tp>(__ll);
734 }
735 __err = ios_base::failbit;
736 return 0;
737}
738
739template <class _Tp>
740_Tp
741__num_get_unsigned_integral(const char* __a, const char* __a_end,
742 ios_base::iostate& __err, int __base)
743{
744 if (__a != __a_end)
745 {
746 char *__p2;
747 unsigned long long __ll = strtoull_l(__a, &__p2, __base, 0);
748 if (__p2 != __a_end)
749 {
750 __err = ios_base::failbit;
751 return 0;
752 }
753 else if (__ll > numeric_limits<_Tp>::max())
754 {
755 __err = ios_base::failbit;
756 return numeric_limits<_Tp>::max();
757 }
758 return static_cast<_Tp>(__ll);
759 }
760 __err = ios_base::failbit;
761 return 0;
762}
763
764template <class _Tp>
765_Tp
766__num_get_float(const char* __a, const char* __a_end, ios_base::iostate& __err)
767{
768 if (__a != __a_end)
769 {
770 char *__p2;
771 long double __ld = strtold_l(__a, &__p2, 0);
772 if (__p2 != __a_end)
773 {
774 __err = ios_base::failbit;
775 return 0;
776 }
777 return static_cast<_Tp>(__ld);
778 }
779 __err = ios_base::failbit;
780 return 0;
781}
782
783template <class _CharT, class _InputIterator>
784_InputIterator
785num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
786 ios_base& __iob,
787 ios_base::iostate& __err,
788 bool& __v) const
789{
790 if ((__iob.flags() & ios_base::boolalpha) == 0)
791 {
792 long __lv = -1;
793 __b = do_get(__b, __e, __iob, __err, __lv);
794 switch (__lv)
795 {
796 case 0:
797 __v = false;
798 break;
799 case 1:
800 __v = true;
801 break;
802 default:
803 __v = true;
804 __err = ios_base::failbit;
805 break;
806 }
807 return __b;
808 }
809 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__iob.getloc());
810 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__iob.getloc());
811 typedef typename numpunct<_CharT>::string_type string_type;
812 const string_type __names[2] = {__np.truename(), __np.falsename()};
813 const string_type* __i = __scan_keyword(__b, __e, __names, __names+2,
814 __ct, __err);
815 __v = __i == __names;
816 return __b;
817}
818
819template <class _CharT, class _InputIterator>
820_InputIterator
821num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
822 ios_base& __iob,
823 ios_base::iostate& __err,
824 long& __v) const
825{
826 // Stage 1
827 int __base = this->__get_base(__iob);
828 // Stage 2
829 char_type __atoms[26];
830 char_type __thousands_sep;
831 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
832 char __a[__num_get_base::__num_get_buf_sz] = {0};
833 char* __a_end = __a;
834 unsigned __g[__num_get_base::__num_get_buf_sz];
835 unsigned* __g_end = __g;
836 unsigned __dc = 0;
837 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +0000838 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000839 __thousands_sep, __grouping, __g, __g_end,
840 __atoms))
841 break;
842 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
843 *__g_end++ = __dc;
844 // Stage 3
845 __v = __num_get_signed_integral<long>(__a, __a_end, __err, __base);
846 // Digit grouping checked
847 __check_grouping(__grouping, __g, __g_end, __err);
848 // EOF checked
849 if (__b == __e)
850 __err |= ios_base::eofbit;
851 return __b;
852}
853
854template <class _CharT, class _InputIterator>
855_InputIterator
856num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
857 ios_base& __iob,
858 ios_base::iostate& __err,
859 long long& __v) const
860{
861 // Stage 1
862 int __base = this->__get_base(__iob);
863 // Stage 2
864 char_type __atoms[26];
865 char_type __thousands_sep;
866 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
867 char __a[__num_get_base::__num_get_buf_sz] = {0};
868 char* __a_end = __a;
869 unsigned __g[__num_get_base::__num_get_buf_sz];
870 unsigned* __g_end = __g;
871 unsigned __dc = 0;
872 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +0000873 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
874 __thousands_sep, __grouping, __g, __g_end,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000875 __atoms))
876 break;
877 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
878 *__g_end++ = __dc;
879 // Stage 3
880 __v = __num_get_signed_integral<long long>(__a, __a_end, __err, __base);
881 // Digit grouping checked
882 __check_grouping(__grouping, __g, __g_end, __err);
883 // EOF checked
884 if (__b == __e)
885 __err |= ios_base::eofbit;
886 return __b;
887}
888
889template <class _CharT, class _InputIterator>
890_InputIterator
891num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
892 ios_base& __iob,
893 ios_base::iostate& __err,
894 unsigned short& __v) const
895{
896 // Stage 1
897 int __base = this->__get_base(__iob);
898 // Stage 2
899 char_type __atoms[26];
900 char_type __thousands_sep;
901 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
902 char __a[__num_get_base::__num_get_buf_sz] = {0};
903 char* __a_end = __a;
904 unsigned __g[__num_get_base::__num_get_buf_sz];
905 unsigned* __g_end = __g;
906 unsigned __dc = 0;
907 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +0000908 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000909 __thousands_sep, __grouping, __g, __g_end,
910 __atoms))
911 break;
912 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
913 *__g_end++ = __dc;
914 // Stage 3
915 __v = __num_get_unsigned_integral<unsigned short>(__a, __a_end, __err, __base);
916 // Digit grouping checked
917 __check_grouping(__grouping, __g, __g_end, __err);
918 // EOF checked
919 if (__b == __e)
920 __err |= ios_base::eofbit;
921 return __b;
922}
923
924template <class _CharT, class _InputIterator>
925_InputIterator
926num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
927 ios_base& __iob,
928 ios_base::iostate& __err,
929 unsigned int& __v) const
930{
931 // Stage 1
932 int __base = this->__get_base(__iob);
933 // Stage 2
934 char_type __atoms[26];
935 char_type __thousands_sep;
936 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
937 char __a[__num_get_base::__num_get_buf_sz] = {0};
938 char* __a_end = __a;
939 unsigned __g[__num_get_base::__num_get_buf_sz];
940 unsigned* __g_end = __g;
941 unsigned __dc = 0;
942 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +0000943 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000944 __thousands_sep, __grouping, __g, __g_end,
945 __atoms))
946 break;
947 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
948 *__g_end++ = __dc;
949 // Stage 3
950 __v = __num_get_unsigned_integral<unsigned int>(__a, __a_end, __err, __base);
951 // Digit grouping checked
952 __check_grouping(__grouping, __g, __g_end, __err);
953 // EOF checked
954 if (__b == __e)
955 __err |= ios_base::eofbit;
956 return __b;
957}
958
959template <class _CharT, class _InputIterator>
960_InputIterator
961num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
962 ios_base& __iob,
963 ios_base::iostate& __err,
964 unsigned long& __v) const
965{
966 // Stage 1
967 int __base = this->__get_base(__iob);
968 // Stage 2
969 char_type __atoms[26];
970 char_type __thousands_sep;
971 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
972 char __a[__num_get_base::__num_get_buf_sz] = {0};
973 char* __a_end = __a;
974 unsigned __g[__num_get_base::__num_get_buf_sz];
975 unsigned* __g_end = __g;
976 unsigned __dc = 0;
977 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +0000978 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000979 __thousands_sep, __grouping, __g, __g_end,
980 __atoms))
981 break;
982 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
983 *__g_end++ = __dc;
984 // Stage 3
985 __v = __num_get_unsigned_integral<unsigned long>(__a, __a_end, __err, __base);
986 // Digit grouping checked
987 __check_grouping(__grouping, __g, __g_end, __err);
988 // EOF checked
989 if (__b == __e)
990 __err |= ios_base::eofbit;
991 return __b;
992}
993
994template <class _CharT, class _InputIterator>
995_InputIterator
996num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
997 ios_base& __iob,
998 ios_base::iostate& __err,
999 unsigned long long& __v) const
1000{
1001 // Stage 1
1002 int __base = this->__get_base(__iob);
1003 // Stage 2
1004 char_type __atoms[26];
1005 char_type __thousands_sep;
1006 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
1007 char __a[__num_get_base::__num_get_buf_sz] = {0};
1008 char* __a_end = __a;
1009 unsigned __g[__num_get_base::__num_get_buf_sz];
1010 unsigned* __g_end = __g;
1011 unsigned __dc = 0;
1012 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001013 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001014 __thousands_sep, __grouping, __g, __g_end,
1015 __atoms))
1016 break;
1017 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
1018 *__g_end++ = __dc;
1019 // Stage 3
1020 __v = __num_get_unsigned_integral<unsigned long long>(__a, __a_end, __err, __base);
1021 // Digit grouping checked
1022 __check_grouping(__grouping, __g, __g_end, __err);
1023 // EOF checked
1024 if (__b == __e)
1025 __err |= ios_base::eofbit;
1026 return __b;
1027}
1028
1029template <class _CharT, class _InputIterator>
1030_InputIterator
1031num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1032 ios_base& __iob,
1033 ios_base::iostate& __err,
1034 float& __v) const
1035{
1036 // Stage 1, nothing to do
1037 // Stage 2
1038 char_type __atoms[32];
1039 char_type __decimal_point;
1040 char_type __thousands_sep;
Howard Hinnant324bb032010-08-22 00:02:43 +00001041 string __grouping = this->__stage2_float_prep(__iob, __atoms,
1042 __decimal_point,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001043 __thousands_sep);
1044 char __a[__num_get_base::__num_get_buf_sz] = {0};
1045 char* __a_end = __a;
1046 unsigned __g[__num_get_base::__num_get_buf_sz];
1047 unsigned* __g_end = __g;
1048 unsigned __dc = 0;
1049 bool __in_units = true;
1050 char __exp = 'E';
1051 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001052 if (this->__stage2_float_loop(*__b, __in_units, __exp, __a, __a_end,
1053 __decimal_point, __thousands_sep,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001054 __grouping, __g, __g_end,
1055 __dc, __atoms))
1056 break;
1057 if (__grouping.size() != 0 && __in_units && __g_end-__g < __num_get_base::__num_get_buf_sz)
1058 *__g_end++ = __dc;
1059 // Stage 3
1060 __v = __num_get_float<float>(__a, __a_end, __err);
1061 // Digit grouping checked
1062 __check_grouping(__grouping, __g, __g_end, __err);
1063 // EOF checked
1064 if (__b == __e)
1065 __err |= ios_base::eofbit;
1066 return __b;
1067}
1068
1069template <class _CharT, class _InputIterator>
1070_InputIterator
1071num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1072 ios_base& __iob,
1073 ios_base::iostate& __err,
1074 double& __v) const
1075{
1076 // Stage 1, nothing to do
1077 // Stage 2
1078 char_type __atoms[32];
1079 char_type __decimal_point;
1080 char_type __thousands_sep;
Howard Hinnant324bb032010-08-22 00:02:43 +00001081 string __grouping = this->__stage2_float_prep(__iob, __atoms,
1082 __decimal_point,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001083 __thousands_sep);
1084 char __a[__num_get_base::__num_get_buf_sz] = {0};
1085 char* __a_end = __a;
1086 unsigned __g[__num_get_base::__num_get_buf_sz];
1087 unsigned* __g_end = __g;
1088 unsigned __dc = 0;
1089 bool __in_units = true;
1090 char __exp = 'E';
1091 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001092 if (this->__stage2_float_loop(*__b, __in_units, __exp, __a, __a_end,
1093 __decimal_point, __thousands_sep,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001094 __grouping, __g, __g_end,
1095 __dc, __atoms))
1096 break;
1097 if (__grouping.size() != 0 && __in_units && __g_end-__g < __num_get_base::__num_get_buf_sz)
1098 *__g_end++ = __dc;
1099 // Stage 3
1100 __v = __num_get_float<double>(__a, __a_end, __err);
1101 // Digit grouping checked
1102 __check_grouping(__grouping, __g, __g_end, __err);
1103 // EOF checked
1104 if (__b == __e)
1105 __err |= ios_base::eofbit;
1106 return __b;
1107}
1108
1109template <class _CharT, class _InputIterator>
1110_InputIterator
1111num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1112 ios_base& __iob,
1113 ios_base::iostate& __err,
1114 long double& __v) const
1115{
1116 // Stage 1, nothing to do
1117 // Stage 2
1118 char_type __atoms[32];
1119 char_type __decimal_point;
1120 char_type __thousands_sep;
Howard Hinnant324bb032010-08-22 00:02:43 +00001121 string __grouping = this->__stage2_float_prep(__iob, __atoms,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001122 __decimal_point,
1123 __thousands_sep);
1124 char __a[__num_get_base::__num_get_buf_sz] = {0};
1125 char* __a_end = __a;
1126 unsigned __g[__num_get_base::__num_get_buf_sz];
1127 unsigned* __g_end = __g;
1128 unsigned __dc = 0;
1129 bool __in_units = true;
1130 char __exp = 'E';
1131 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001132 if (this->__stage2_float_loop(*__b, __in_units, __exp, __a, __a_end,
1133 __decimal_point, __thousands_sep,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001134 __grouping, __g, __g_end,
1135 __dc, __atoms))
1136 break;
1137 if (__grouping.size() != 0 && __in_units && __g_end-__g < __num_get_base::__num_get_buf_sz)
1138 *__g_end++ = __dc;
1139 // Stage 3
1140 __v = __num_get_float<long double>(__a, __a_end, __err);
1141 // Digit grouping checked
1142 __check_grouping(__grouping, __g, __g_end, __err);
1143 // EOF checked
1144 if (__b == __e)
1145 __err |= ios_base::eofbit;
1146 return __b;
1147}
1148
1149template <class _CharT, class _InputIterator>
1150_InputIterator
1151num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1152 ios_base& __iob,
1153 ios_base::iostate& __err,
1154 void*& __v) const
1155{
1156 // Stage 1
1157 int __base = 16;
1158 // Stage 2
1159 char_type __atoms[26];
1160 char_type __thousands_sep;
1161 string __grouping;
1162 use_facet<ctype<_CharT> >(__iob.getloc()).widen(__num_get_base::__src,
1163 __num_get_base::__src + 26, __atoms);
1164 char __a[__num_get_base::__num_get_buf_sz] = {0};
1165 char* __a_end = __a;
1166 unsigned __g[__num_get_base::__num_get_buf_sz];
1167 unsigned* __g_end = __g;
1168 unsigned __dc = 0;
1169 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001170 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
1171 __thousands_sep, __grouping,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001172 __g, __g_end, __atoms))
1173 break;
1174 // Stage 3
1175 __a[sizeof(__a)-1] = 0;
Howard Hinnantadff4892010-05-24 17:49:41 +00001176 if (__nolocale_sscanf(__a, "%p", &__v) != 1)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001177 __err = ios_base::failbit;
1178 // EOF checked
1179 if (__b == __e)
1180 __err |= ios_base::eofbit;
1181 return __b;
1182}
1183
1184extern template class num_get<char>;
1185extern template class num_get<wchar_t>;
1186
1187struct __num_put_base
1188{
1189protected:
1190 static void __format_int(char* __fmt, const char* __len, bool __signd,
1191 ios_base::fmtflags __flags);
1192 static bool __format_float(char* __fmt, const char* __len,
1193 ios_base::fmtflags __flags);
1194 static char* __identify_padding(char* __nb, char* __ne,
1195 const ios_base& __iob);
1196};
1197
1198template <class _CharT>
1199struct __num_put
1200 : protected __num_put_base
1201{
1202 static void __widen_and_group_int(char* __nb, char* __np, char* __ne,
1203 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1204 const locale& __loc);
1205 static void __widen_and_group_float(char* __nb, char* __np, char* __ne,
1206 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1207 const locale& __loc);
1208};
1209
1210template <class _CharT>
1211void
1212__num_put<_CharT>::__widen_and_group_int(char* __nb, char* __np, char* __ne,
1213 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1214 const locale& __loc)
1215{
1216 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> > (__loc);
1217 const numpunct<_CharT>& __npt = use_facet<numpunct<_CharT> >(__loc);
1218 string __grouping = __npt.grouping();
1219 if (__grouping.empty())
1220 {
1221 __ct.widen(__nb, __ne, __ob);
1222 __oe = __ob + (__ne - __nb);
1223 }
1224 else
1225 {
1226 __oe = __ob;
1227 char* __nf = __nb;
1228 if (*__nf == '-' || *__nf == '+')
1229 *__oe++ = __ct.widen(*__nf++);
1230 if (__ne - __nf >= 2 && __nf[0] == '0' && (__nf[1] == 'x' ||
1231 __nf[1] == 'X'))
1232 {
1233 *__oe++ = __ct.widen(*__nf++);
1234 *__oe++ = __ct.widen(*__nf++);
1235 }
1236 reverse(__nf, __ne);
1237 _CharT __thousands_sep = __npt.thousands_sep();
1238 unsigned __dc = 0;
1239 unsigned __dg = 0;
1240 for (char* __p = __nf; __p < __ne; ++__p)
1241 {
1242 if (static_cast<unsigned>(__grouping[__dg]) > 0 &&
1243 __dc == static_cast<unsigned>(__grouping[__dg]))
1244 {
1245 *__oe++ = __thousands_sep;
1246 __dc = 0;
1247 if (__dg < __grouping.size()-1)
1248 ++__dg;
1249 }
1250 *__oe++ = __ct.widen(*__p);
1251 ++__dc;
1252 }
1253 reverse(__ob + (__nf - __nb), __oe);
1254 }
1255 if (__np == __ne)
1256 __op = __oe;
1257 else
1258 __op = __ob + (__np - __nb);
1259}
1260
1261template <class _CharT>
1262void
1263__num_put<_CharT>::__widen_and_group_float(char* __nb, char* __np, char* __ne,
1264 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1265 const locale& __loc)
1266{
1267 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> > (__loc);
1268 const numpunct<_CharT>& __npt = use_facet<numpunct<_CharT> >(__loc);
1269 string __grouping = __npt.grouping();
1270 __oe = __ob;
1271 char* __nf = __nb;
1272 if (*__nf == '-' || *__nf == '+')
1273 *__oe++ = __ct.widen(*__nf++);
1274 char* __ns;
1275 if (__ne - __nf >= 2 && __nf[0] == '0' && (__nf[1] == 'x' ||
1276 __nf[1] == 'X'))
1277 {
1278 *__oe++ = __ct.widen(*__nf++);
1279 *__oe++ = __ct.widen(*__nf++);
1280 for (__ns = __nf; __ns < __ne; ++__ns)
Howard Hinnantadff4892010-05-24 17:49:41 +00001281 if (!__nolocale_isxdigit(*__ns))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001282 break;
1283 }
1284 else
1285 {
1286 for (__ns = __nf; __ns < __ne; ++__ns)
Howard Hinnantadff4892010-05-24 17:49:41 +00001287 if (!__nolocale_isdigit(*__ns))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001288 break;
1289 }
1290 if (__grouping.empty())
1291 {
1292 __ct.widen(__nf, __ns, __oe);
1293 __oe += __ns - __nf;
1294 }
1295 else
1296 {
1297 reverse(__nf, __ns);
1298 _CharT __thousands_sep = __npt.thousands_sep();
1299 unsigned __dc = 0;
1300 unsigned __dg = 0;
1301 for (char* __p = __nf; __p < __ns; ++__p)
1302 {
1303 if (__grouping[__dg] > 0 && __dc == static_cast<unsigned>(__grouping[__dg]))
1304 {
1305 *__oe++ = __thousands_sep;
1306 __dc = 0;
1307 if (__dg < __grouping.size()-1)
1308 ++__dg;
1309 }
1310 *__oe++ = __ct.widen(*__p);
1311 ++__dc;
1312 }
1313 reverse(__ob + (__nf - __nb), __oe);
1314 }
1315 for (__nf = __ns; __nf < __ne; ++__nf)
1316 {
1317 if (*__nf == '.')
1318 {
1319 *__oe++ = __npt.decimal_point();
1320 ++__nf;
1321 break;
1322 }
1323 else
1324 *__oe++ = __ct.widen(*__nf);
1325 }
1326 __ct.widen(__nf, __ne, __oe);
1327 __oe += __ne - __nf;
1328 if (__np == __ne)
1329 __op = __oe;
1330 else
1331 __op = __ob + (__np - __nb);
1332}
1333
1334extern template class __num_put<char>;
1335extern template class __num_put<wchar_t>;
1336
1337template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
1338class num_put
1339 : public locale::facet,
1340 private __num_put<_CharT>
1341{
1342public:
1343 typedef _CharT char_type;
1344 typedef _OutputIterator iter_type;
1345
1346 _LIBCPP_ALWAYS_INLINE
1347 explicit num_put(size_t __refs = 0)
1348 : locale::facet(__refs) {}
1349
1350 _LIBCPP_ALWAYS_INLINE
1351 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1352 bool __v) const
1353 {
1354 return do_put(__s, __iob, __fl, __v);
1355 }
1356
1357 _LIBCPP_ALWAYS_INLINE
1358 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1359 long __v) const
1360 {
1361 return do_put(__s, __iob, __fl, __v);
1362 }
1363
1364 _LIBCPP_ALWAYS_INLINE
1365 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1366 long long __v) const
1367 {
1368 return do_put(__s, __iob, __fl, __v);
1369 }
1370
1371 _LIBCPP_ALWAYS_INLINE
1372 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1373 unsigned long __v) const
1374 {
1375 return do_put(__s, __iob, __fl, __v);
1376 }
1377
1378 _LIBCPP_ALWAYS_INLINE
1379 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1380 unsigned long long __v) const
1381 {
1382 return do_put(__s, __iob, __fl, __v);
1383 }
1384
1385 _LIBCPP_ALWAYS_INLINE
1386 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1387 double __v) const
1388 {
1389 return do_put(__s, __iob, __fl, __v);
1390 }
1391
1392 _LIBCPP_ALWAYS_INLINE
1393 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1394 long double __v) const
1395 {
1396 return do_put(__s, __iob, __fl, __v);
1397 }
1398
1399 _LIBCPP_ALWAYS_INLINE
1400 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1401 const void* __v) const
1402 {
1403 return do_put(__s, __iob, __fl, __v);
1404 }
1405
1406 static locale::id id;
1407
1408protected:
1409 ~num_put() {}
1410
1411 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1412 bool __v) const;
1413 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1414 long __v) const;
1415 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1416 long long __v) const;
1417 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1418 unsigned long) const;
1419 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1420 unsigned long long) const;
1421 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1422 double __v) const;
1423 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1424 long double __v) const;
1425 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1426 const void* __v) const;
1427};
1428
1429template <class _CharT, class _OutputIterator>
1430locale::id
1431num_put<_CharT, _OutputIterator>::id;
1432
1433template <class _CharT, class _OutputIterator>
1434_LIBCPP_HIDDEN
1435_OutputIterator
1436__pad_and_output(_OutputIterator __s,
1437 const _CharT* __ob, const _CharT* __op, const _CharT* __oe,
1438 ios_base& __iob, _CharT __fl)
1439{
1440 streamsize __sz = __oe - __ob;
1441 streamsize __ns = __iob.width();
1442 if (__ns > __sz)
1443 __ns -= __sz;
1444 else
1445 __ns = 0;
1446 for (;__ob < __op; ++__ob, ++__s)
1447 *__s = *__ob;
1448 for (; __ns; --__ns, ++__s)
1449 *__s = __fl;
1450 for (; __ob < __oe; ++__ob, ++__s)
1451 *__s = *__ob;
1452 __iob.width(0);
1453 return __s;
1454}
1455
1456template <class _CharT, class _OutputIterator>
1457_OutputIterator
1458num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1459 char_type __fl, bool __v) const
1460{
1461 if ((__iob.flags() & ios_base::boolalpha) == 0)
1462 return do_put(__s, __iob, __fl, (unsigned long)__v);
1463 const numpunct<char_type>& __np = use_facet<numpunct<char_type> >(__iob.getloc());
1464 typedef typename numpunct<char_type>::string_type string_type;
1465 string_type __nm = __v ? __np.truename() : __np.falsename();
1466 for (typename string_type::iterator __i = __nm.begin(); __i != __nm.end(); ++__i, ++__s)
1467 *__s = *__i;
1468 return __s;
1469}
1470
1471template <class _CharT, class _OutputIterator>
1472_OutputIterator
1473num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1474 char_type __fl, long __v) const
1475{
1476 // Stage 1 - Get number in narrow char
1477 char __fmt[6] = {'%', 0};
1478 const char* __len = "l";
1479 this->__format_int(__fmt+1, __len, true, __iob.flags());
1480 const unsigned __nbuf = (numeric_limits<long>::digits / 3)
1481 + ((numeric_limits<long>::digits % 3) != 0)
1482 + 1;
1483 char __nar[__nbuf];
Howard Hinnantadff4892010-05-24 17:49:41 +00001484 int __nc = __nolocale_sprintf(__nar, __fmt, __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001485 char* __ne = __nar + __nc;
1486 char* __np = this->__identify_padding(__nar, __ne, __iob);
1487 // Stage 2 - Widen __nar while adding thousands separators
1488 char_type __o[2*(__nbuf-1) - 1];
1489 char_type* __op; // pad here
1490 char_type* __oe; // end of output
1491 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1492 // [__o, __oe) contains thousands_sep'd wide number
1493 // Stage 3 & 4
1494 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1495}
1496
1497template <class _CharT, class _OutputIterator>
1498_OutputIterator
1499num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1500 char_type __fl, long long __v) const
1501{
1502 // Stage 1 - Get number in narrow char
1503 char __fmt[8] = {'%', 0};
1504 const char* __len = "ll";
1505 this->__format_int(__fmt+1, __len, true, __iob.flags());
1506 const unsigned __nbuf = (numeric_limits<long long>::digits / 3)
1507 + ((numeric_limits<long long>::digits % 3) != 0)
1508 + 1;
1509 char __nar[__nbuf];
Howard Hinnantadff4892010-05-24 17:49:41 +00001510 int __nc = __nolocale_sprintf(__nar, __fmt, __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001511 char* __ne = __nar + __nc;
1512 char* __np = this->__identify_padding(__nar, __ne, __iob);
1513 // Stage 2 - Widen __nar while adding thousands separators
1514 char_type __o[2*(__nbuf-1) - 1];
1515 char_type* __op; // pad here
1516 char_type* __oe; // end of output
1517 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1518 // [__o, __oe) contains thousands_sep'd wide number
1519 // Stage 3 & 4
1520 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1521}
1522
1523template <class _CharT, class _OutputIterator>
1524_OutputIterator
1525num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1526 char_type __fl, unsigned long __v) const
1527{
1528 // Stage 1 - Get number in narrow char
1529 char __fmt[6] = {'%', 0};
1530 const char* __len = "l";
1531 this->__format_int(__fmt+1, __len, false, __iob.flags());
1532 const unsigned __nbuf = (numeric_limits<unsigned long>::digits / 3)
1533 + ((numeric_limits<unsigned long>::digits % 3) != 0)
1534 + 1;
1535 char __nar[__nbuf];
Howard Hinnantadff4892010-05-24 17:49:41 +00001536 int __nc = __nolocale_sprintf(__nar, __fmt, __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001537 char* __ne = __nar + __nc;
1538 char* __np = this->__identify_padding(__nar, __ne, __iob);
1539 // Stage 2 - Widen __nar while adding thousands separators
1540 char_type __o[2*(__nbuf-1) - 1];
1541 char_type* __op; // pad here
1542 char_type* __oe; // end of output
1543 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1544 // [__o, __oe) contains thousands_sep'd wide number
1545 // Stage 3 & 4
1546 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1547}
1548
1549template <class _CharT, class _OutputIterator>
1550_OutputIterator
1551num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1552 char_type __fl, unsigned long long __v) const
1553{
1554 // Stage 1 - Get number in narrow char
1555 char __fmt[8] = {'%', 0};
1556 const char* __len = "ll";
1557 this->__format_int(__fmt+1, __len, false, __iob.flags());
1558 const unsigned __nbuf = (numeric_limits<unsigned long long>::digits / 3)
1559 + ((numeric_limits<unsigned long long>::digits % 3) != 0)
1560 + 1;
1561 char __nar[__nbuf];
Howard Hinnantadff4892010-05-24 17:49:41 +00001562 int __nc = __nolocale_sprintf(__nar, __fmt, __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001563 char* __ne = __nar + __nc;
1564 char* __np = this->__identify_padding(__nar, __ne, __iob);
1565 // Stage 2 - Widen __nar while adding thousands separators
1566 char_type __o[2*(__nbuf-1) - 1];
1567 char_type* __op; // pad here
1568 char_type* __oe; // end of output
1569 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1570 // [__o, __oe) contains thousands_sep'd wide number
1571 // Stage 3 & 4
1572 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1573}
1574
1575template <class _CharT, class _OutputIterator>
1576_OutputIterator
1577num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1578 char_type __fl, double __v) const
1579{
1580 // Stage 1 - Get number in narrow char
1581 char __fmt[8] = {'%', 0};
1582 const char* __len = "";
1583 bool __specify_precision = this->__format_float(__fmt+1, __len, __iob.flags());
1584 const unsigned __nbuf = 30;
1585 char __nar[__nbuf];
1586 char* __nb = __nar;
1587 int __nc;
1588 if (__specify_precision)
Howard Hinnantadff4892010-05-24 17:49:41 +00001589 __nc = __nolocale_snprintf(__nb, __nbuf, __fmt,
1590 (int)__iob.precision(), __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001591 else
Howard Hinnantadff4892010-05-24 17:49:41 +00001592 __nc = __nolocale_snprintf(__nb, __nbuf, __fmt, __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001593 unique_ptr<char, void(*)(void*)> __nbh(0, free);
1594 if (__nc > static_cast<int>(__nbuf-1))
1595 {
1596 if (__specify_precision)
Howard Hinnantadff4892010-05-24 17:49:41 +00001597 __nc = __nolocale_asprintf(&__nb, __fmt, (int)__iob.precision(),
1598 __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001599 else
Howard Hinnantadff4892010-05-24 17:49:41 +00001600 __nc = __nolocale_asprintf(&__nb, __fmt, __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001601 if (__nb == 0)
1602 __throw_bad_alloc();
1603 __nbh.reset(__nb);
1604 }
1605 char* __ne = __nb + __nc;
1606 char* __np = this->__identify_padding(__nb, __ne, __iob);
1607 // Stage 2 - Widen __nar while adding thousands separators
1608 char_type __o[2*(__nbuf-1) - 1];
1609 char_type* __ob = __o;
1610 unique_ptr<char_type, void(*)(void*)> __obh(0, free);
1611 if (__nb != __nar)
1612 {
1613 __ob = (char_type*)malloc((2*__nc)*sizeof(char_type));
1614 if (__ob == 0)
1615 __throw_bad_alloc();
1616 __obh.reset(__ob);
1617 }
1618 char_type* __op; // pad here
1619 char_type* __oe; // end of output
1620 this->__widen_and_group_float(__nb, __np, __ne, __ob, __op, __oe, __iob.getloc());
1621 // [__o, __oe) contains thousands_sep'd wide number
1622 // Stage 3 & 4
1623 __s = __pad_and_output(__s, __ob, __op, __oe, __iob, __fl);
1624 return __s;
1625}
1626
1627template <class _CharT, class _OutputIterator>
1628_OutputIterator
1629num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1630 char_type __fl, long double __v) const
1631{
1632 // Stage 1 - Get number in narrow char
1633 char __fmt[8] = {'%', 0};
1634 const char* __len = "L";
1635 bool __specify_precision = this->__format_float(__fmt+1, __len, __iob.flags());
1636 const unsigned __nbuf = 30;
1637 char __nar[__nbuf];
1638 char* __nb = __nar;
1639 int __nc;
1640 if (__specify_precision)
Howard Hinnantadff4892010-05-24 17:49:41 +00001641 __nc = __nolocale_snprintf(__nb, __nbuf, __fmt,
1642 (int)__iob.precision(), __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001643 else
Howard Hinnantadff4892010-05-24 17:49:41 +00001644 __nc = __nolocale_snprintf(__nb, __nbuf, __fmt, __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001645 unique_ptr<char, void(*)(void*)> __nbh(0, free);
1646 if (__nc > static_cast<int>(__nbuf-1))
1647 {
1648 if (__specify_precision)
Howard Hinnantadff4892010-05-24 17:49:41 +00001649 __nc = __nolocale_asprintf(&__nb, __fmt, (int)__iob.precision(),
1650 __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001651 else
Howard Hinnantadff4892010-05-24 17:49:41 +00001652 __nc = __nolocale_asprintf(&__nb, __fmt, __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001653 if (__nb == 0)
1654 __throw_bad_alloc();
1655 __nbh.reset(__nb);
1656 }
1657 char* __ne = __nb + __nc;
1658 char* __np = this->__identify_padding(__nb, __ne, __iob);
1659 // Stage 2 - Widen __nar while adding thousands separators
1660 char_type __o[2*(__nbuf-1) - 1];
1661 char_type* __ob = __o;
1662 unique_ptr<char_type, void(*)(void*)> __obh(0, free);
1663 if (__nb != __nar)
1664 {
1665 __ob = (char_type*)malloc((2*__nc)*sizeof(char_type));
1666 if (__ob == 0)
1667 __throw_bad_alloc();
1668 __obh.reset(__ob);
1669 }
1670 char_type* __op; // pad here
1671 char_type* __oe; // end of output
1672 this->__widen_and_group_float(__nb, __np, __ne, __ob, __op, __oe, __iob.getloc());
1673 // [__o, __oe) contains thousands_sep'd wide number
1674 // Stage 3 & 4
1675 __s = __pad_and_output(__s, __ob, __op, __oe, __iob, __fl);
1676 return __s;
1677}
1678
1679template <class _CharT, class _OutputIterator>
1680_OutputIterator
1681num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1682 char_type __fl, const void* __v) const
1683{
1684 // Stage 1 - Get pointer in narrow char
1685 char __fmt[6] = "%p";
1686 const unsigned __nbuf = 20;
1687 char __nar[__nbuf];
Howard Hinnantadff4892010-05-24 17:49:41 +00001688 int __nc = __nolocale_sprintf(__nar, __fmt, __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001689 char* __ne = __nar + __nc;
1690 char* __np = this->__identify_padding(__nar, __ne, __iob);
1691 // Stage 2 - Widen __nar
1692 char_type __o[2*(__nbuf-1) - 1];
1693 char_type* __op; // pad here
1694 char_type* __oe; // end of output
1695 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
1696 __ct.widen(__nar, __ne, __o);
1697 __oe = __o + (__ne - __nar);
1698 if (__np == __ne)
1699 __op = __oe;
1700 else
1701 __op = __o + (__np - __nar);
1702 // [__o, __oe) contains wide number
1703 // Stage 3 & 4
1704 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1705}
1706
1707extern template class num_put<char>;
1708extern template class num_put<wchar_t>;
1709
1710template <class _CharT, class _InputIterator>
1711_LIBCPP_HIDDEN
1712int
1713__get_up_to_n_digits(_InputIterator& __b, _InputIterator __e,
1714 ios_base::iostate& __err, const ctype<_CharT>& __ct, int __n)
1715{
1716 // Precondition: __n >= 1
1717 if (__b == __e)
1718 {
1719 __err |= ios_base::eofbit | ios_base::failbit;
1720 return 0;
1721 }
1722 // get first digit
1723 _CharT __c = *__b;
1724 if (!__ct.is(ctype_base::digit, __c))
1725 {
1726 __err |= ios_base::failbit;
1727 return 0;
1728 }
1729 int __r = __ct.narrow(__c, 0) - '0';
1730 for (++__b, --__n; __b != __e && __n > 0; ++__b, --__n)
1731 {
1732 // get next digit
1733 __c = *__b;
1734 if (!__ct.is(ctype_base::digit, __c))
1735 return __r;
1736 __r = __r * 10 + __ct.narrow(__c, 0) - '0';
1737 }
1738 if (__b == __e)
1739 __err |= ios_base::eofbit;
1740 return __r;
1741}
1742
1743class time_base
1744{
1745public:
1746 enum dateorder {no_order, dmy, mdy, ymd, ydm};
1747};
1748
1749template <class _CharT>
1750class __time_get_c_storage
1751{
1752protected:
1753 typedef basic_string<_CharT> string_type;
1754
1755 virtual const string_type* __weeks() const;
1756 virtual const string_type* __months() const;
1757 virtual const string_type* __am_pm() const;
1758 virtual const string_type& __c() const;
1759 virtual const string_type& __r() const;
1760 virtual const string_type& __x() const;
1761 virtual const string_type& __X() const;
1762};
1763
1764template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
1765class time_get
1766 : public locale::facet,
1767 public time_base,
1768 private __time_get_c_storage<_CharT>
1769{
1770public:
1771 typedef _CharT char_type;
1772 typedef _InputIterator iter_type;
1773 typedef time_base::dateorder dateorder;
1774 typedef basic_string<char_type> string_type;
1775
1776 _LIBCPP_ALWAYS_INLINE
1777 explicit time_get(size_t __refs = 0)
1778 : locale::facet(__refs) {}
1779
1780 _LIBCPP_ALWAYS_INLINE
1781 dateorder date_order() const
1782 {
1783 return this->do_date_order();
1784 }
1785
1786 _LIBCPP_ALWAYS_INLINE
1787 iter_type get_time(iter_type __b, iter_type __e, ios_base& __iob,
1788 ios_base::iostate& __err, tm* __tm) const
1789 {
1790 return do_get_time(__b, __e, __iob, __err, __tm);
1791 }
1792
1793 _LIBCPP_ALWAYS_INLINE
1794 iter_type get_date(iter_type __b, iter_type __e, ios_base& __iob,
1795 ios_base::iostate& __err, tm* __tm) const
1796 {
1797 return do_get_date(__b, __e, __iob, __err, __tm);
1798 }
1799
1800 _LIBCPP_ALWAYS_INLINE
1801 iter_type get_weekday(iter_type __b, iter_type __e, ios_base& __iob,
1802 ios_base::iostate& __err, tm* __tm) const
1803 {
1804 return do_get_weekday(__b, __e, __iob, __err, __tm);
1805 }
1806
1807 _LIBCPP_ALWAYS_INLINE
1808 iter_type get_monthname(iter_type __b, iter_type __e, ios_base& __iob,
1809 ios_base::iostate& __err, tm* __tm) const
1810 {
1811 return do_get_monthname(__b, __e, __iob, __err, __tm);
1812 }
1813
1814 _LIBCPP_ALWAYS_INLINE
1815 iter_type get_year(iter_type __b, iter_type __e, ios_base& __iob,
1816 ios_base::iostate& __err, tm* __tm) const
1817 {
1818 return do_get_year(__b, __e, __iob, __err, __tm);
1819 }
1820
1821 _LIBCPP_ALWAYS_INLINE
1822 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
1823 ios_base::iostate& __err, tm *__tm,
1824 char __fmt, char __mod = 0) const
1825 {
1826 return do_get(__b, __e, __iob, __err, __tm, __fmt, __mod);
1827 }
1828
1829 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
1830 ios_base::iostate& __err, tm* __tm,
1831 const char_type* __fmtb, const char_type* __fmte) const;
1832
1833 static locale::id id;
1834
1835protected:
1836 ~time_get() {}
1837
1838 virtual dateorder do_date_order() const;
1839 virtual iter_type do_get_time(iter_type __b, iter_type __e, ios_base& __iob,
1840 ios_base::iostate& __err, tm* __tm) const;
1841 virtual iter_type do_get_date(iter_type __b, iter_type __e, ios_base& __iob,
1842 ios_base::iostate& __err, tm* __tm) const;
1843 virtual iter_type do_get_weekday(iter_type __b, iter_type __e, ios_base& __iob,
1844 ios_base::iostate& __err, tm* __tm) const;
1845 virtual iter_type do_get_monthname(iter_type __b, iter_type __e, ios_base& __iob,
1846 ios_base::iostate& __err, tm* __tm) const;
1847 virtual iter_type do_get_year(iter_type __b, iter_type __e, ios_base& __iob,
1848 ios_base::iostate& __err, tm* __tm) const;
1849 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
1850 ios_base::iostate& __err, tm* __tm,
1851 char __fmt, char __mod) const;
1852private:
1853 void __get_white_space(iter_type& __b, iter_type __e,
1854 ios_base::iostate& __err, const ctype<char_type>& __ct) const;
1855 void __get_percent(iter_type& __b, iter_type __e, ios_base::iostate& __err,
1856 const ctype<char_type>& __ct) const;
1857
1858 void __get_weekdayname(int& __m,
1859 iter_type& __b, iter_type __e,
1860 ios_base::iostate& __err,
1861 const ctype<char_type>& __ct) const;
1862 void __get_monthname(int& __m,
1863 iter_type& __b, iter_type __e,
1864 ios_base::iostate& __err,
1865 const ctype<char_type>& __ct) const;
1866 void __get_day(int& __d,
1867 iter_type& __b, iter_type __e,
1868 ios_base::iostate& __err,
1869 const ctype<char_type>& __ct) const;
1870 void __get_month(int& __m,
1871 iter_type& __b, iter_type __e,
1872 ios_base::iostate& __err,
1873 const ctype<char_type>& __ct) const;
1874 void __get_year(int& __y,
1875 iter_type& __b, iter_type __e,
1876 ios_base::iostate& __err,
1877 const ctype<char_type>& __ct) const;
1878 void __get_year4(int& __y,
1879 iter_type& __b, iter_type __e,
1880 ios_base::iostate& __err,
1881 const ctype<char_type>& __ct) const;
1882 void __get_hour(int& __d,
1883 iter_type& __b, iter_type __e,
1884 ios_base::iostate& __err,
1885 const ctype<char_type>& __ct) const;
1886 void __get_12_hour(int& __h,
1887 iter_type& __b, iter_type __e,
1888 ios_base::iostate& __err,
1889 const ctype<char_type>& __ct) const;
1890 void __get_am_pm(int& __h,
1891 iter_type& __b, iter_type __e,
1892 ios_base::iostate& __err,
1893 const ctype<char_type>& __ct) const;
1894 void __get_minute(int& __m,
1895 iter_type& __b, iter_type __e,
1896 ios_base::iostate& __err,
1897 const ctype<char_type>& __ct) const;
1898 void __get_second(int& __s,
1899 iter_type& __b, iter_type __e,
1900 ios_base::iostate& __err,
1901 const ctype<char_type>& __ct) const;
1902 void __get_weekday(int& __w,
1903 iter_type& __b, iter_type __e,
1904 ios_base::iostate& __err,
1905 const ctype<char_type>& __ct) const;
1906 void __get_day_year_num(int& __w,
1907 iter_type& __b, iter_type __e,
1908 ios_base::iostate& __err,
1909 const ctype<char_type>& __ct) const;
1910};
1911
1912template <class _CharT, class _InputIterator>
1913locale::id
1914time_get<_CharT, _InputIterator>::id;
1915
1916// time_get primatives
1917
1918template <class _CharT, class _InputIterator>
1919void
1920time_get<_CharT, _InputIterator>::__get_weekdayname(int& __w,
1921 iter_type& __b, iter_type __e,
1922 ios_base::iostate& __err,
1923 const ctype<char_type>& __ct) const
1924{
1925 // Note: ignoring case comes from the POSIX strptime spec
1926 const string_type* __wk = this->__weeks();
1927 int __i = __scan_keyword(__b, __e, __wk, __wk+14, __ct, __err, false) - __wk;
1928 if (__i < 14)
1929 __w = __i % 7;
1930}
1931
1932template <class _CharT, class _InputIterator>
1933void
1934time_get<_CharT, _InputIterator>::__get_monthname(int& __m,
1935 iter_type& __b, iter_type __e,
1936 ios_base::iostate& __err,
1937 const ctype<char_type>& __ct) const
1938{
1939 // Note: ignoring case comes from the POSIX strptime spec
1940 const string_type* __month = this->__months();
1941 int __i = __scan_keyword(__b, __e, __month, __month+24, __ct, __err, false) - __month;
1942 if (__i < 24)
1943 __m = __i % 12;
1944}
1945
1946template <class _CharT, class _InputIterator>
1947void
1948time_get<_CharT, _InputIterator>::__get_day(int& __d,
1949 iter_type& __b, iter_type __e,
1950 ios_base::iostate& __err,
1951 const ctype<char_type>& __ct) const
1952{
1953 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
1954 if (!(__err & ios_base::failbit) && 1 <= __t && __t <= 31)
1955 __d = __t;
1956 else
1957 __err |= ios_base::failbit;
1958}
1959
1960template <class _CharT, class _InputIterator>
1961void
1962time_get<_CharT, _InputIterator>::__get_month(int& __m,
1963 iter_type& __b, iter_type __e,
1964 ios_base::iostate& __err,
1965 const ctype<char_type>& __ct) const
1966{
1967 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2) - 1;
1968 if (!(__err & ios_base::failbit) && __t <= 11)
1969 __m = __t;
1970 else
1971 __err |= ios_base::failbit;
1972}
1973
1974template <class _CharT, class _InputIterator>
1975void
1976time_get<_CharT, _InputIterator>::__get_year(int& __y,
1977 iter_type& __b, iter_type __e,
1978 ios_base::iostate& __err,
1979 const ctype<char_type>& __ct) const
1980{
1981 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 4);
1982 if (!(__err & ios_base::failbit))
1983 {
1984 if (__t < 69)
1985 __t += 2000;
1986 else if (69 <= __t && __t <= 99)
1987 __t += 1900;
1988 __y = __t - 1900;
1989 }
1990}
1991
1992template <class _CharT, class _InputIterator>
1993void
1994time_get<_CharT, _InputIterator>::__get_year4(int& __y,
1995 iter_type& __b, iter_type __e,
1996 ios_base::iostate& __err,
1997 const ctype<char_type>& __ct) const
1998{
1999 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 4);
2000 if (!(__err & ios_base::failbit))
2001 __y = __t - 1900;
2002}
2003
2004template <class _CharT, class _InputIterator>
2005void
2006time_get<_CharT, _InputIterator>::__get_hour(int& __h,
2007 iter_type& __b, iter_type __e,
2008 ios_base::iostate& __err,
2009 const ctype<char_type>& __ct) const
2010{
2011 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2012 if (!(__err & ios_base::failbit) && __t <= 23)
2013 __h = __t;
2014 else
2015 __err |= ios_base::failbit;
2016}
2017
2018template <class _CharT, class _InputIterator>
2019void
2020time_get<_CharT, _InputIterator>::__get_12_hour(int& __h,
2021 iter_type& __b, iter_type __e,
2022 ios_base::iostate& __err,
2023 const ctype<char_type>& __ct) const
2024{
2025 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2026 if (!(__err & ios_base::failbit) && 1 <= __t && __t <= 12)
2027 __h = __t;
2028 else
2029 __err |= ios_base::failbit;
2030}
2031
2032template <class _CharT, class _InputIterator>
2033void
2034time_get<_CharT, _InputIterator>::__get_minute(int& __m,
2035 iter_type& __b, iter_type __e,
2036 ios_base::iostate& __err,
2037 const ctype<char_type>& __ct) const
2038{
2039 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2040 if (!(__err & ios_base::failbit) && __t <= 59)
2041 __m = __t;
2042 else
2043 __err |= ios_base::failbit;
2044}
2045
2046template <class _CharT, class _InputIterator>
2047void
2048time_get<_CharT, _InputIterator>::__get_second(int& __s,
2049 iter_type& __b, iter_type __e,
2050 ios_base::iostate& __err,
2051 const ctype<char_type>& __ct) const
2052{
2053 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2054 if (!(__err & ios_base::failbit) && __t <= 60)
2055 __s = __t;
2056 else
2057 __err |= ios_base::failbit;
2058}
2059
2060template <class _CharT, class _InputIterator>
2061void
2062time_get<_CharT, _InputIterator>::__get_weekday(int& __w,
2063 iter_type& __b, iter_type __e,
2064 ios_base::iostate& __err,
2065 const ctype<char_type>& __ct) const
2066{
2067 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 1);
2068 if (!(__err & ios_base::failbit) && __t <= 6)
2069 __w = __t;
2070 else
2071 __err |= ios_base::failbit;
2072}
2073
2074template <class _CharT, class _InputIterator>
2075void
2076time_get<_CharT, _InputIterator>::__get_day_year_num(int& __d,
2077 iter_type& __b, iter_type __e,
2078 ios_base::iostate& __err,
2079 const ctype<char_type>& __ct) const
2080{
2081 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 3);
2082 if (!(__err & ios_base::failbit) && __t <= 365)
2083 __d = __t;
2084 else
2085 __err |= ios_base::failbit;
2086}
2087
2088template <class _CharT, class _InputIterator>
2089void
2090time_get<_CharT, _InputIterator>::__get_white_space(iter_type& __b, iter_type __e,
2091 ios_base::iostate& __err,
2092 const ctype<char_type>& __ct) const
2093{
2094 for (; __b != __e && __ct.is(ctype_base::space, *__b); ++__b)
2095 ;
2096 if (__b == __e)
2097 __err |= ios_base::eofbit;
2098}
2099
2100template <class _CharT, class _InputIterator>
2101void
2102time_get<_CharT, _InputIterator>::__get_am_pm(int& __h,
2103 iter_type& __b, iter_type __e,
2104 ios_base::iostate& __err,
2105 const ctype<char_type>& __ct) const
2106{
2107 const string_type* __ap = this->__am_pm();
2108 if (__ap[0].size() + __ap[1].size() == 0)
2109 {
2110 __err |= ios_base::failbit;
2111 return;
2112 }
2113 int __i = __scan_keyword(__b, __e, __ap, __ap+2, __ct, __err, false) - __ap;
2114 if (__i == 0 && __h == 12)
2115 __h = 0;
2116 else if (__i == 1 && __h < 12)
2117 __h += 12;
2118}
2119
2120template <class _CharT, class _InputIterator>
2121void
2122time_get<_CharT, _InputIterator>::__get_percent(iter_type& __b, iter_type __e,
2123 ios_base::iostate& __err,
2124 const ctype<char_type>& __ct) const
2125{
2126 if (__b == __e)
2127 {
2128 __err |= ios_base::eofbit | ios_base::failbit;
2129 return;
2130 }
2131 if (__ct.narrow(*__b, 0) != '%')
2132 __err |= ios_base::failbit;
2133 else if(++__b == __e)
2134 __err |= ios_base::eofbit;
2135}
2136
2137// time_get end primatives
2138
2139template <class _CharT, class _InputIterator>
2140_InputIterator
2141time_get<_CharT, _InputIterator>::get(iter_type __b, iter_type __e,
2142 ios_base& __iob,
2143 ios_base::iostate& __err, tm* __tm,
2144 const char_type* __fmtb, const char_type* __fmte) const
2145{
2146 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2147 __err = ios_base::goodbit;
2148 while (__fmtb != __fmte && __err == ios_base::goodbit)
2149 {
2150 if (__b == __e)
2151 {
2152 __err = ios_base::failbit;
2153 break;
2154 }
2155 if (__ct.narrow(*__fmtb, 0) == '%')
2156 {
2157 if (++__fmtb == __fmte)
2158 {
2159 __err = ios_base::failbit;
2160 break;
2161 }
2162 char __cmd = __ct.narrow(*__fmtb, 0);
2163 char __opt = '\0';
2164 if (__cmd == 'E' || __cmd == '0')
2165 {
2166 if (++__fmtb == __fmte)
2167 {
2168 __err = ios_base::failbit;
2169 break;
2170 }
2171 __opt = __cmd;
2172 __cmd = __ct.narrow(*__fmtb, 0);
2173 }
2174 __b = do_get(__b, __e, __iob, __err, __tm, __cmd, __opt);
2175 ++__fmtb;
2176 }
2177 else if (__ct.is(ctype_base::space, *__fmtb))
2178 {
2179 for (++__fmtb; __fmtb != __fmte && __ct.is(ctype_base::space, *__fmtb); ++__fmtb)
2180 ;
2181 for ( ; __b != __e && __ct.is(ctype_base::space, *__b); ++__b)
2182 ;
2183 }
2184 else if (__ct.toupper(*__b) == __ct.toupper(*__fmtb))
2185 {
2186 ++__b;
2187 ++__fmtb;
2188 }
2189 else
2190 __err = ios_base::failbit;
2191 }
2192 if (__b == __e)
2193 __err |= ios_base::eofbit;
2194 return __b;
2195}
2196
2197template <class _CharT, class _InputIterator>
2198typename time_get<_CharT, _InputIterator>::dateorder
2199time_get<_CharT, _InputIterator>::do_date_order() const
2200{
2201 return mdy;
2202}
2203
2204template <class _CharT, class _InputIterator>
2205_InputIterator
2206time_get<_CharT, _InputIterator>::do_get_time(iter_type __b, iter_type __e,
2207 ios_base& __iob,
2208 ios_base::iostate& __err,
2209 tm* __tm) const
2210{
2211 const char_type __fmt[] = {'%', 'H', ':', '%', 'M', ':', '%', 'S'};
2212 return get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2213}
2214
2215template <class _CharT, class _InputIterator>
2216_InputIterator
2217time_get<_CharT, _InputIterator>::do_get_date(iter_type __b, iter_type __e,
2218 ios_base& __iob,
2219 ios_base::iostate& __err,
2220 tm* __tm) const
2221{
2222 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2223 const string_type& __fmt = this->__x();
2224 return get(__b, __e, __iob, __err, __tm, __fmt.data(), __fmt.data() + __fmt.size());
2225}
2226
2227template <class _CharT, class _InputIterator>
2228_InputIterator
2229time_get<_CharT, _InputIterator>::do_get_weekday(iter_type __b, iter_type __e,
2230 ios_base& __iob,
2231 ios_base::iostate& __err,
2232 tm* __tm) const
2233{
2234 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2235 __get_weekdayname(__tm->tm_wday, __b, __e, __err, __ct);
2236 return __b;
2237}
2238
2239template <class _CharT, class _InputIterator>
2240_InputIterator
2241time_get<_CharT, _InputIterator>::do_get_monthname(iter_type __b, iter_type __e,
2242 ios_base& __iob,
2243 ios_base::iostate& __err,
2244 tm* __tm) const
2245{
2246 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2247 __get_monthname(__tm->tm_mon, __b, __e, __err, __ct);
2248 return __b;
2249}
2250
2251template <class _CharT, class _InputIterator>
2252_InputIterator
2253time_get<_CharT, _InputIterator>::do_get_year(iter_type __b, iter_type __e,
2254 ios_base& __iob,
2255 ios_base::iostate& __err,
2256 tm* __tm) const
2257{
2258 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2259 __get_year(__tm->tm_year, __b, __e, __err, __ct);
2260 return __b;
2261}
2262
2263template <class _CharT, class _InputIterator>
2264_InputIterator
2265time_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
2266 ios_base& __iob,
2267 ios_base::iostate& __err, tm* __tm,
2268 char __fmt, char) const
2269{
2270 __err = ios_base::goodbit;
2271 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2272 switch (__fmt)
2273 {
2274 case 'a':
2275 case 'A':
2276 __get_weekdayname(__tm->tm_wday, __b, __e, __err, __ct);
2277 break;
2278 case 'b':
2279 case 'B':
2280 case 'h':
2281 __get_monthname(__tm->tm_mon, __b, __e, __err, __ct);
2282 break;
2283 case 'c':
2284 {
2285 const string_type& __fmt = this->__c();
2286 __b = get(__b, __e, __iob, __err, __tm, __fmt.data(), __fmt.data() + __fmt.size());
2287 }
2288 break;
2289 case 'd':
2290 case 'e':
2291 __get_day(__tm->tm_mday, __b, __e, __err, __ct);
2292 break;
2293 case 'D':
2294 {
2295 const char_type __fmt[] = {'%', 'm', '/', '%', 'd', '/', '%', 'y'};
2296 __b = get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2297 }
2298 break;
2299 case 'H':
2300 __get_hour(__tm->tm_hour, __b, __e, __err, __ct);
2301 break;
2302 case 'I':
2303 __get_12_hour(__tm->tm_hour, __b, __e, __err, __ct);
2304 break;
2305 case 'j':
2306 __get_day_year_num(__tm->tm_yday, __b, __e, __err, __ct);
2307 break;
2308 case 'm':
2309 __get_month(__tm->tm_mon, __b, __e, __err, __ct);
2310 break;
2311 case 'M':
2312 __get_minute(__tm->tm_min, __b, __e, __err, __ct);
2313 break;
2314 case 'n':
2315 case 't':
2316 __get_white_space(__b, __e, __err, __ct);
2317 break;
2318 case 'p':
2319 __get_am_pm(__tm->tm_hour, __b, __e, __err, __ct);
2320 break;
2321 case 'r':
2322 {
2323 const char_type __fmt[] = {'%', 'I', ':', '%', 'M', ':', '%', 'S', ' ', '%', 'p'};
2324 __b = get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2325 }
2326 break;
2327 case 'R':
2328 {
2329 const char_type __fmt[] = {'%', 'H', ':', '%', 'M'};
2330 __b = get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2331 }
2332 break;
2333 case 'S':
2334 __get_second(__tm->tm_sec, __b, __e, __err, __ct);
2335 break;
2336 case 'T':
2337 {
2338 const char_type __fmt[] = {'%', 'H', ':', '%', 'M', ':', '%', 'S'};
2339 __b = get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2340 }
2341 break;
2342 case 'w':
2343 __get_weekday(__tm->tm_wday, __b, __e, __err, __ct);
2344 break;
2345 case 'x':
2346 return do_get_date(__b, __e, __iob, __err, __tm);
2347 case 'X':
2348 {
2349 const string_type& __fmt = this->__X();
2350 __b = get(__b, __e, __iob, __err, __tm, __fmt.data(), __fmt.data() + __fmt.size());
2351 }
2352 break;
2353 case 'y':
2354 __get_year(__tm->tm_year, __b, __e, __err, __ct);
2355 break;
2356 case 'Y':
2357 __get_year4(__tm->tm_year, __b, __e, __err, __ct);
2358 break;
2359 case '%':
2360 __get_percent(__b, __e, __err, __ct);
2361 break;
2362 default:
2363 __err |= ios_base::failbit;
2364 }
2365 return __b;
2366}
2367
2368extern template class time_get<char>;
2369extern template class time_get<wchar_t>;
2370
2371class __time_get
2372{
2373protected:
2374 locale_t __loc_;
2375
2376 __time_get(const char* __nm);
2377 __time_get(const string& __nm);
2378 ~__time_get();
2379};
2380
2381template <class _CharT>
2382class __time_get_storage
2383 : public __time_get
2384{
2385protected:
2386 typedef basic_string<_CharT> string_type;
2387
2388 string_type __weeks_[14];
2389 string_type __months_[24];
2390 string_type __am_pm_[2];
2391 string_type __c_;
2392 string_type __r_;
2393 string_type __x_;
2394 string_type __X_;
2395
2396 explicit __time_get_storage(const char* __nm);
2397 explicit __time_get_storage(const string& __nm);
2398
2399 _LIBCPP_ALWAYS_INLINE ~__time_get_storage() {}
2400
2401 time_base::dateorder __do_date_order() const;
2402
2403private:
2404 void init(const ctype<_CharT>&);
2405 string_type __analyze(char __fmt, const ctype<_CharT>&);
2406};
2407
2408template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
2409class time_get_byname
2410 : public time_get<_CharT, _InputIterator>,
2411 private __time_get_storage<_CharT>
2412{
2413public:
2414 typedef time_base::dateorder dateorder;
2415 typedef _InputIterator iter_type;
2416 typedef _CharT char_type;
2417 typedef basic_string<char_type> string_type;
2418
2419 explicit time_get_byname(const char* __nm, size_t __refs = 0)
2420 : time_get<_CharT, _InputIterator>(__refs),
2421 __time_get_storage<_CharT>(__nm) {}
2422 explicit time_get_byname(const string& __nm, size_t __refs = 0)
2423 : time_get<_CharT, _InputIterator>(__refs),
2424 __time_get_storage<_CharT>(__nm) {}
2425
2426protected:
2427 ~time_get_byname() {}
2428
2429 virtual dateorder do_date_order() const {return this->__do_date_order();}
2430private:
2431 virtual const string_type* __weeks() const {return this->__weeks_;}
2432 virtual const string_type* __months() const {return this->__months_;}
2433 virtual const string_type* __am_pm() const {return this->__am_pm_;}
2434 virtual const string_type& __c() const {return this->__c_;}
2435 virtual const string_type& __r() const {return this->__r_;}
2436 virtual const string_type& __x() const {return this->__x_;}
2437 virtual const string_type& __X() const {return this->__X_;}
2438};
2439
2440extern template class time_get_byname<char>;
2441extern template class time_get_byname<wchar_t>;
2442
2443class __time_put
2444{
2445 locale_t __loc_;
2446protected:
2447 _LIBCPP_ALWAYS_INLINE __time_put() : __loc_(0) {}
2448 __time_put(const char* __nm);
2449 __time_put(const string& __nm);
2450 ~__time_put();
2451 void __do_put(char* __nb, char*& __ne, const tm* __tm,
2452 char __fmt, char __mod) const;
2453 void __do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
2454 char __fmt, char __mod) const;
2455};
2456
2457template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
2458class time_put
2459 : public locale::facet,
2460 private __time_put
2461{
2462public:
2463 typedef _CharT char_type;
2464 typedef _OutputIterator iter_type;
2465
2466 _LIBCPP_ALWAYS_INLINE
2467 explicit time_put(size_t __refs = 0)
2468 : locale::facet(__refs) {}
2469
2470 iter_type put(iter_type __s, ios_base& __iob, char_type __fl, const tm* __tm,
2471 const char_type* __pb, const char_type* __pe) const;
2472
2473 _LIBCPP_ALWAYS_INLINE
2474 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
2475 const tm* __tm, char __fmt, char __mod = 0) const
2476 {
2477 return do_put(__s, __iob, __fl, __tm, __fmt, __mod);
2478 }
2479
2480 static locale::id id;
2481
2482protected:
2483 ~time_put() {}
2484 virtual iter_type do_put(iter_type __s, ios_base&, char_type, const tm* __tm,
2485 char __fmt, char __mod) const;
2486
2487 explicit time_put(const char* __nm, size_t __refs)
2488 : locale::facet(__refs),
2489 __time_put(__nm) {}
2490 explicit time_put(const string& __nm, size_t __refs)
2491 : locale::facet(__refs),
2492 __time_put(__nm) {}
2493};
2494
2495template <class _CharT, class _OutputIterator>
2496locale::id
2497time_put<_CharT, _OutputIterator>::id;
2498
2499template <class _CharT, class _OutputIterator>
2500_OutputIterator
2501time_put<_CharT, _OutputIterator>::put(iter_type __s, ios_base& __iob,
2502 char_type __fl, const tm* __tm,
2503 const char_type* __pb,
2504 const char_type* __pe) const
2505{
2506 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2507 for (; __pb != __pe; ++__pb)
2508 {
2509 if (__ct.narrow(*__pb, 0) == '%')
2510 {
2511 if (++__pb == __pe)
2512 {
2513 *__s++ = __pb[-1];
2514 break;
2515 }
2516 char __mod = 0;
2517 char __fmt = __ct.narrow(*__pb, 0);
2518 if (__fmt == 'E' || __fmt == 'O')
2519 {
2520 if (++__pb == __pe)
2521 {
2522 *__s++ = __pb[-2];
2523 *__s++ = __pb[-1];
2524 break;
2525 }
2526 __mod = __fmt;
2527 __fmt = __ct.narrow(*__pb, 0);
2528 }
2529 __s = do_put(__s, __iob, __fl, __tm, __fmt, __mod);
2530 }
2531 else
2532 *__s++ = *__pb;
2533 }
2534 return __s;
2535}
2536
2537template <class _CharT, class _OutputIterator>
2538_OutputIterator
2539time_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
2540 char_type, const tm* __tm,
2541 char __fmt, char __mod) const
2542{
2543 char_type __nar[100];
2544 char_type* __nb = __nar;
2545 char_type* __ne = __nb + 100;
2546 __do_put(__nb, __ne, __tm, __fmt, __mod);
2547 return copy(__nb, __ne, __s);
2548}
2549
2550extern template class time_put<char>;
2551extern template class time_put<wchar_t>;
2552
2553template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
2554class time_put_byname
2555 : public time_put<_CharT, _OutputIterator>
2556{
2557public:
2558 _LIBCPP_ALWAYS_INLINE
2559 explicit time_put_byname(const char* __nm, size_t __refs = 0)
2560 : time_put<_CharT, _OutputIterator>(__nm, __refs) {}
2561
2562 _LIBCPP_ALWAYS_INLINE
2563 explicit time_put_byname(const string& __nm, size_t __refs = 0)
2564 : time_put<_CharT, _OutputIterator>(__nm, __refs) {}
2565
2566protected:
2567 ~time_put_byname() {}
2568};
2569
2570extern template class time_put_byname<char>;
2571extern template class time_put_byname<wchar_t>;
2572
2573// money_base
2574
2575class money_base
2576{
2577public:
2578 enum part {none, space, symbol, sign, value};
2579 struct pattern {char field[4];};
2580
2581 _LIBCPP_ALWAYS_INLINE money_base() {}
2582};
2583
2584// moneypunct
2585
2586template <class _CharT, bool _International = false>
2587class moneypunct
2588 : public locale::facet,
2589 public money_base
2590{
2591public:
2592 typedef _CharT char_type;
2593 typedef basic_string<char_type> string_type;
2594
2595 explicit moneypunct(size_t __refs = 0)
2596 : locale::facet(__refs) {}
2597
2598 _LIBCPP_ALWAYS_INLINE char_type decimal_point() const {return do_decimal_point();}
2599 _LIBCPP_ALWAYS_INLINE char_type thousands_sep() const {return do_thousands_sep();}
2600 _LIBCPP_ALWAYS_INLINE string grouping() const {return do_grouping();}
2601 _LIBCPP_ALWAYS_INLINE string_type curr_symbol() const {return do_curr_symbol();}
2602 _LIBCPP_ALWAYS_INLINE string_type positive_sign() const {return do_positive_sign();}
2603 _LIBCPP_ALWAYS_INLINE string_type negative_sign() const {return do_negative_sign();}
2604 _LIBCPP_ALWAYS_INLINE int frac_digits() const {return do_frac_digits();}
2605 _LIBCPP_ALWAYS_INLINE pattern pos_format() const {return do_pos_format();}
2606 _LIBCPP_ALWAYS_INLINE pattern neg_format() const {return do_neg_format();}
2607
2608 static locale::id id;
2609 static const bool intl = _International;
2610
2611protected:
2612 ~moneypunct() {}
2613
2614 virtual char_type do_decimal_point() const {return numeric_limits<char_type>::max();}
2615 virtual char_type do_thousands_sep() const {return numeric_limits<char_type>::max();}
2616 virtual string do_grouping() const {return string();}
2617 virtual string_type do_curr_symbol() const {return string_type();}
2618 virtual string_type do_positive_sign() const {return string_type();}
2619 virtual string_type do_negative_sign() const {return string_type(1, '-');}
2620 virtual int do_frac_digits() const {return 0;}
2621 virtual pattern do_pos_format() const
2622 {pattern __p = {symbol, sign, none, value}; return __p;}
2623 virtual pattern do_neg_format() const
2624 {pattern __p = {symbol, sign, none, value}; return __p;}
2625};
2626
2627template <class _CharT, bool _International>
2628locale::id
2629moneypunct<_CharT, _International>::id;
2630
2631extern template class moneypunct<char, false>;
2632extern template class moneypunct<char, true>;
2633extern template class moneypunct<wchar_t, false>;
2634extern template class moneypunct<wchar_t, true>;
2635
2636// moneypunct_byname
2637
2638template <class _CharT, bool _International = false>
2639class moneypunct_byname : public moneypunct<_CharT, _International>
2640{
2641public:
2642 typedef money_base::pattern pattern;
2643 typedef _CharT char_type;
2644 typedef basic_string<char_type> string_type;
2645
2646 _LIBCPP_ALWAYS_INLINE
2647 explicit moneypunct_byname(const char* __nm, size_t __refs = 0)
2648 : moneypunct<_CharT, _International>(__refs) {init(__nm);}
2649
2650 _LIBCPP_ALWAYS_INLINE
2651 explicit moneypunct_byname(const string& __nm, size_t __refs = 0)
2652 : moneypunct<_CharT, _International>(__refs) {init(__nm.c_str());}
2653
2654protected:
2655 ~moneypunct_byname() {}
2656
2657 virtual char_type do_decimal_point() const {return __decimal_point_;}
2658 virtual char_type do_thousands_sep() const {return __thousands_sep_;}
2659 virtual string do_grouping() const {return __grouping_;}
2660 virtual string_type do_curr_symbol() const {return __curr_symbol_;}
2661 virtual string_type do_positive_sign() const {return __positive_sign_;}
2662 virtual string_type do_negative_sign() const {return __negative_sign_;}
2663 virtual int do_frac_digits() const {return __frac_digits_;}
2664 virtual pattern do_pos_format() const {return __pos_format_;}
2665 virtual pattern do_neg_format() const {return __neg_format_;}
2666
2667private:
2668 char_type __decimal_point_;
2669 char_type __thousands_sep_;
2670 string __grouping_;
2671 string_type __curr_symbol_;
2672 string_type __positive_sign_;
2673 string_type __negative_sign_;
2674 int __frac_digits_;
2675 pattern __pos_format_;
2676 pattern __neg_format_;
2677
2678 void init(const char*);
2679};
2680
2681template<> void moneypunct_byname<char, false>::init(const char*);
2682template<> void moneypunct_byname<char, true>::init(const char*);
2683template<> void moneypunct_byname<wchar_t, false>::init(const char*);
2684template<> void moneypunct_byname<wchar_t, true>::init(const char*);
2685
2686extern template class moneypunct_byname<char, false>;
2687extern template class moneypunct_byname<char, true>;
2688extern template class moneypunct_byname<wchar_t, false>;
2689extern template class moneypunct_byname<wchar_t, true>;
2690
2691// money_get
2692
2693template <class _CharT>
2694class __money_get
2695{
2696protected:
2697 typedef _CharT char_type;
2698 typedef basic_string<char_type> string_type;
2699
2700 _LIBCPP_ALWAYS_INLINE __money_get() {}
2701
2702 static void __gather_info(bool __intl, const locale& __loc,
2703 money_base::pattern& __pat, char_type& __dp,
2704 char_type& __ts, string& __grp,
2705 string_type& __sym, string_type& __psn,
2706 string_type& __nsn, int& __fd);
2707};
2708
2709template <class _CharT>
2710void
2711__money_get<_CharT>::__gather_info(bool __intl, const locale& __loc,
2712 money_base::pattern& __pat, char_type& __dp,
2713 char_type& __ts, string& __grp,
2714 string_type& __sym, string_type& __psn,
2715 string_type& __nsn, int& __fd)
2716{
2717 if (__intl)
2718 {
2719 const moneypunct<char_type, true>& __mp =
2720 use_facet<moneypunct<char_type, true> >(__loc);
2721 __pat = __mp.neg_format();
2722 __nsn = __mp.negative_sign();
2723 __psn = __mp.positive_sign();
2724 __dp = __mp.decimal_point();
2725 __ts = __mp.thousands_sep();
2726 __grp = __mp.grouping();
2727 __sym = __mp.curr_symbol();
2728 __fd = __mp.frac_digits();
2729 }
2730 else
2731 {
2732 const moneypunct<char_type, false>& __mp =
2733 use_facet<moneypunct<char_type, false> >(__loc);
2734 __pat = __mp.neg_format();
2735 __nsn = __mp.negative_sign();
2736 __psn = __mp.positive_sign();
2737 __dp = __mp.decimal_point();
2738 __ts = __mp.thousands_sep();
2739 __grp = __mp.grouping();
2740 __sym = __mp.curr_symbol();
2741 __fd = __mp.frac_digits();
2742 }
2743}
2744
2745extern template class __money_get<char>;
2746extern template class __money_get<wchar_t>;
2747
2748template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
2749class money_get
2750 : public locale::facet,
2751 private __money_get<_CharT>
2752{
2753public:
2754 typedef _CharT char_type;
2755 typedef _InputIterator iter_type;
2756 typedef basic_string<char_type> string_type;
2757
2758 _LIBCPP_ALWAYS_INLINE
2759 explicit money_get(size_t __refs = 0)
2760 : locale::facet(__refs) {}
2761
2762 _LIBCPP_ALWAYS_INLINE
2763 iter_type get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob,
2764 ios_base::iostate& __err, long double& __v) const
2765 {
2766 return do_get(__b, __e, __intl, __iob, __err, __v);
2767 }
2768
2769 _LIBCPP_ALWAYS_INLINE
2770 iter_type get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob,
2771 ios_base::iostate& __err, string_type& __v) const
2772 {
2773 return do_get(__b, __e, __intl, __iob, __err, __v);
2774 }
2775
2776 static locale::id id;
2777
2778protected:
2779
2780 ~money_get() {}
Howard Hinnant324bb032010-08-22 00:02:43 +00002781
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002782 virtual iter_type do_get(iter_type __b, iter_type __e, bool __intl,
2783 ios_base& __iob, ios_base::iostate& __err,
2784 long double& __v) const;
2785 virtual iter_type do_get(iter_type __b, iter_type __e, bool __intl,
2786 ios_base& __iob, ios_base::iostate& __err,
2787 string_type& __v) const;
2788
2789private:
2790 static bool __do_get(iter_type& __b, iter_type __e,
2791 bool __intl, const locale& __loc,
2792 ios_base::fmtflags __flags, ios_base::iostate& __err,
2793 bool& __neg, const ctype<char_type>& __ct,
2794 unique_ptr<char_type, void(*)(void*)>& __wb,
2795 char_type*& __wn, char_type* __we);
2796};
2797
2798template <class _CharT, class _InputIterator>
2799locale::id
2800money_get<_CharT, _InputIterator>::id;
2801
2802void __do_nothing(void*);
2803
2804template <class _Tp>
2805_LIBCPP_HIDDEN
2806void
2807__double_or_nothing(unique_ptr<_Tp, void(*)(void*)>& __b, _Tp*& __n, _Tp*& __e)
2808{
2809 bool __owns = __b.get_deleter() != __do_nothing;
2810 size_t __cur_cap = (__e-__b.get()) * sizeof(_Tp);
2811 size_t __new_cap = __cur_cap < numeric_limits<size_t>::max() / 2 ?
2812 2 * __cur_cap : numeric_limits<size_t>::max();
2813 size_t __n_off = __n - __b.get();
2814 _Tp* __t = (_Tp*)realloc(__owns ? __b.get() : 0, __new_cap);
2815 if (__t == 0)
2816 __throw_bad_alloc();
2817 if (__owns)
2818 __b.release();
2819 __b = unique_ptr<_Tp, void(*)(void*)>(__t, free);
2820 __new_cap /= sizeof(_Tp);
2821 __n = __b.get() + __n_off;
2822 __e = __b.get() + __new_cap;
2823}
2824
2825// true == success
2826template <class _CharT, class _InputIterator>
2827bool
2828money_get<_CharT, _InputIterator>::__do_get(iter_type& __b, iter_type __e,
2829 bool __intl, const locale& __loc,
2830 ios_base::fmtflags __flags,
2831 ios_base::iostate& __err,
2832 bool& __neg,
2833 const ctype<char_type>& __ct,
2834 unique_ptr<char_type, void(*)(void*)>& __wb,
2835 char_type*& __wn, char_type* __we)
2836{
2837 const unsigned __bz = 100;
2838 unsigned __gbuf[__bz];
2839 unique_ptr<unsigned, void(*)(void*)> __gb(__gbuf, __do_nothing);
2840 unsigned* __gn = __gb.get();
2841 unsigned* __ge = __gn + __bz;
2842 money_base::pattern __pat;
2843 char_type __dp;
2844 char_type __ts;
2845 string __grp;
2846 string_type __sym;
2847 string_type __psn;
2848 string_type __nsn;
2849 int __fd;
2850 __money_get<_CharT>::__gather_info(__intl, __loc, __pat, __dp, __ts, __grp,
2851 __sym, __psn, __nsn, __fd);
2852 const string_type* __trailing_sign = 0;
2853 __wn = __wb.get();
2854 for (unsigned __p = 0; __p < 4 && __b != __e; ++__p)
2855 {
2856 switch (__pat.field[__p])
2857 {
2858 case money_base::space:
2859 if (__p != 3)
2860 {
2861 if (__ct.is(ctype_base::space, *__b))
2862 ++__b;
2863 else
2864 {
2865 __err |= ios_base::failbit;
2866 return false;
2867 }
2868 }
Howard Hinnant324bb032010-08-22 00:02:43 +00002869 // drop through
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002870 case money_base::none:
2871 if (__p != 3)
2872 {
2873 while (__b != __e && __ct.is(ctype_base::space, *__b))
2874 ++__b;
2875 }
2876 break;
2877 case money_base::sign:
2878 if (__psn.size() + __nsn.size() > 0)
2879 {
2880 if (__psn.size() == 0 || __nsn.size() == 0)
2881 { // sign is optional
2882 if (__psn.size() > 0)
2883 { // __nsn.size() == 0
2884 if (*__b == __psn[0])
2885 {
2886 ++__b;
2887 if (__psn.size() > 1)
2888 __trailing_sign = &__psn;
2889 }
2890 else
2891 __neg = true;
2892 }
2893 else if (*__b == __nsn[0]) // __nsn.size() > 0 && __psn.size() == 0
2894 {
2895 ++__b;
2896 __neg = true;
2897 if (__nsn.size() > 1)
2898 __trailing_sign = &__nsn;
2899 }
2900 }
2901 else // sign is required
2902 {
2903 if (*__b == __psn[0])
2904 {
2905 ++__b;
2906 if (__psn.size() > 1)
2907 __trailing_sign = &__psn;
2908 }
2909 else if (*__b == __nsn[0])
2910 {
2911 ++__b;
2912 __neg = true;
2913 if (__nsn.size() > 1)
2914 __trailing_sign = &__nsn;
2915 }
2916 else
2917 {
2918 __err |= ios_base::failbit;
2919 return false;
2920 }
2921 }
2922 }
2923 break;
2924 case money_base::symbol:
2925 {
2926 bool __more_needed = __trailing_sign ||
2927 (__p < 2) ||
2928 (__p == 2 && __pat.field[3] != static_cast<char>(money_base::none));
2929 bool __sb = __flags & ios_base::showbase;
2930 if (__sb || __more_needed)
2931 {
2932 ios_base::iostate __et = ios_base::goodbit;
2933 string_type* __k = __scan_keyword(__b, __e, &__sym, &__sym+1,
2934 __ct, __et);
2935 if (__sb && __k != &__sym)
2936 {
2937 __err |= ios_base::failbit;
2938 return false;
2939 }
2940 }
2941 }
2942 break;
2943 case money_base::value:
2944 {
2945 unsigned __ng = 0;
2946 for (; __b != __e; ++__b)
2947 {
2948 char_type __c = *__b;
2949 if (__ct.is(ctype_base::digit, __c))
2950 {
2951 if (__wn == __we)
2952 __double_or_nothing(__wb, __wn, __we);
2953 *__wn++ = __c;
2954 ++__ng;
2955 }
2956 else if (__grp.size() > 0 && __ng > 0 && __c == __ts)
2957 {
2958 if (__gn == __ge)
2959 __double_or_nothing(__gb, __gn, __ge);
2960 *__gn++ = __ng;
2961 __ng = 0;
2962 }
2963 else
2964 break;
2965 }
2966 if (__gb.get() != __gn && __ng > 0)
2967 {
2968 if (__gn == __ge)
2969 __double_or_nothing(__gb, __gn, __ge);
2970 *__gn++ = __ng;
2971 }
2972 if (__fd > 0)
2973 {
2974 if (__b == __e || *__b != __dp)
2975 {
2976 __err |= ios_base::failbit;
2977 return false;
2978 }
2979 for (++__b; __fd > 0; --__fd, ++__b)
2980 {
2981 if (__b == __e || !__ct.is(ctype_base::digit, *__b))
2982 {
2983 __err |= ios_base::failbit;
2984 return false;
2985 }
2986 if (__wn == __we)
2987 __double_or_nothing(__wb, __wn, __we);
2988 *__wn++ = *__b;
2989 }
2990 }
2991 if (__wn == __wb.get())
2992 {
2993 __err |= ios_base::failbit;
2994 return false;
2995 }
2996 }
2997 break;
2998 }
2999 }
3000 if (__trailing_sign)
3001 {
3002 for (unsigned __i = 1; __i < __trailing_sign->size(); ++__i, ++__b)
3003 {
3004 if (__b == __e || *__b != (*__trailing_sign)[__i])
3005 {
3006 __err |= ios_base::failbit;
3007 return false;
3008 }
3009 }
3010 }
3011 if (__gb.get() != __gn)
3012 {
3013 ios_base::iostate __et = ios_base::goodbit;
3014 __check_grouping(__grp, __gb.get(), __gn, __et);
3015 if (__et)
3016 {
3017 __err |= ios_base::failbit;
3018 return false;
3019 }
3020 }
3021 return true;
3022}
3023
3024template <class _CharT, class _InputIterator>
3025_InputIterator
3026money_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
3027 bool __intl, ios_base& __iob,
3028 ios_base::iostate& __err,
3029 long double& __v) const
3030{
3031 const unsigned __bz = 100;
3032 char_type __wbuf[__bz];
3033 unique_ptr<char_type, void(*)(void*)> __wb(__wbuf, __do_nothing);
3034 char_type* __wn;
3035 char_type* __we = __wbuf + __bz;
3036 locale __loc = __iob.getloc();
3037 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3038 bool __neg = false;
3039 if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct,
3040 __wb, __wn, __we))
3041 {
3042 const char __src[] = "0123456789";
3043 char_type __atoms[sizeof(__src)-1];
3044 __ct.widen(__src, __src + (sizeof(__src)-1), __atoms);
3045 char __nbuf[__bz];
3046 char* __nc = __nbuf;
3047 unique_ptr<char, void(*)(void*)> __h(0, free);
3048 if (__wn - __wb.get() > __bz-2)
3049 {
3050 __h.reset((char*)malloc(__wn - __wb.get() + 2));
3051 if (__h.get() == 0)
3052 __throw_bad_alloc();
3053 __nc = __h.get();
3054 }
3055 if (__neg)
3056 *__nc++ = '-';
3057 for (const char_type* __w = __wb.get(); __w < __wn; ++__w, ++__nc)
3058 *__nc = __src[find(__atoms, __atoms+sizeof(__atoms), *__w) - __atoms];
3059 *__nc = char();
3060 if (sscanf(__nbuf, "%Lf", &__v) != 1)
3061 __throw_runtime_error("money_get error");
3062 }
3063 if (__b == __e)
3064 __err |= ios_base::eofbit;
3065 return __b;
3066}
3067
3068template <class _CharT, class _InputIterator>
3069_InputIterator
3070money_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
3071 bool __intl, ios_base& __iob,
3072 ios_base::iostate& __err,
3073 string_type& __v) const
3074{
3075 const unsigned __bz = 100;
3076 char_type __wbuf[__bz];
3077 unique_ptr<char_type, void(*)(void*)> __wb(__wbuf, __do_nothing);
3078 char_type* __wn;
3079 char_type* __we = __wbuf + __bz;
3080 locale __loc = __iob.getloc();
3081 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3082 bool __neg = false;
3083 if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct,
3084 __wb, __wn, __we))
3085 {
3086 __v.clear();
3087 if (__neg)
3088 __v.push_back(__ct.widen('-'));
3089 char_type __z = __ct.widen('0');
3090 char_type* __w;
3091 for (__w = __wb.get(); __w < __wn-1; ++__w)
3092 if (*__w != __z)
3093 break;
3094 __v.append(__w, __wn);
3095 }
3096 if (__b == __e)
3097 __err |= ios_base::eofbit;
3098 return __b;
3099}
3100
3101extern template class money_get<char>;
3102extern template class money_get<wchar_t>;
3103
3104// money_put
3105
3106template <class _CharT>
3107class __money_put
3108{
3109protected:
3110 typedef _CharT char_type;
3111 typedef basic_string<char_type> string_type;
3112
3113 _LIBCPP_ALWAYS_INLINE __money_put() {}
3114
3115 static void __gather_info(bool __intl, bool __neg, const locale& __loc,
3116 money_base::pattern& __pat, char_type& __dp,
3117 char_type& __ts, string& __grp,
3118 string_type& __sym, string_type& __sn,
3119 int& __fd);
3120 static void __format(char_type* __mb, char_type*& __mi, char_type*& __me,
3121 ios_base::fmtflags __flags,
3122 const char_type* __db, const char_type* __de,
3123 const ctype<char_type>& __ct, bool __neg,
3124 const money_base::pattern& __pat, char_type __dp,
3125 char_type __ts, const string& __grp,
3126 const string_type& __sym, const string_type& __sn,
3127 int __fd);
3128};
3129
3130template <class _CharT>
3131void
3132__money_put<_CharT>::__gather_info(bool __intl, bool __neg, const locale& __loc,
3133 money_base::pattern& __pat, char_type& __dp,
3134 char_type& __ts, string& __grp,
3135 string_type& __sym, string_type& __sn,
3136 int& __fd)
3137{
3138 if (__intl)
3139 {
3140 const moneypunct<char_type, true>& __mp =
3141 use_facet<moneypunct<char_type, true> >(__loc);
3142 if (__neg)
3143 {
3144 __pat = __mp.neg_format();
3145 __sn = __mp.negative_sign();
3146 }
3147 else
3148 {
3149 __pat = __mp.pos_format();
3150 __sn = __mp.positive_sign();
3151 }
3152 __dp = __mp.decimal_point();
3153 __ts = __mp.thousands_sep();
3154 __grp = __mp.grouping();
3155 __sym = __mp.curr_symbol();
3156 __fd = __mp.frac_digits();
3157 }
3158 else
3159 {
3160 const moneypunct<char_type, false>& __mp =
3161 use_facet<moneypunct<char_type, false> >(__loc);
3162 if (__neg)
3163 {
3164 __pat = __mp.neg_format();
3165 __sn = __mp.negative_sign();
3166 }
3167 else
3168 {
3169 __pat = __mp.pos_format();
3170 __sn = __mp.positive_sign();
3171 }
3172 __dp = __mp.decimal_point();
3173 __ts = __mp.thousands_sep();
3174 __grp = __mp.grouping();
3175 __sym = __mp.curr_symbol();
3176 __fd = __mp.frac_digits();
3177 }
3178}
3179
3180template <class _CharT>
3181void
3182__money_put<_CharT>::__format(char_type* __mb, char_type*& __mi, char_type*& __me,
3183 ios_base::fmtflags __flags,
3184 const char_type* __db, const char_type* __de,
3185 const ctype<char_type>& __ct, bool __neg,
3186 const money_base::pattern& __pat, char_type __dp,
3187 char_type __ts, const string& __grp,
3188 const string_type& __sym, const string_type& __sn,
3189 int __fd)
3190{
3191 __me = __mb;
3192 for (unsigned __p = 0; __p < 4; ++__p)
3193 {
3194 switch (__pat.field[__p])
3195 {
3196 case money_base::none:
3197 __mi = __me;
3198 break;
3199 case money_base::space:
3200 __mi = __me;
3201 *__me++ = __ct.widen(' ');
3202 break;
3203 case money_base::sign:
3204 if (!__sn.empty())
3205 *__me++ = __sn[0];
3206 break;
3207 case money_base::symbol:
3208 if (!__sym.empty() && (__flags & ios_base::showbase))
3209 __me = copy(__sym.begin(), __sym.end(), __me);
3210 break;
3211 case money_base::value:
3212 {
3213 // remember start of value so we can reverse it
3214 char_type* __t = __me;
3215 // find beginning of digits
3216 if (__neg)
3217 ++__db;
3218 // find end of digits
3219 const char_type* __d;
3220 for (__d = __db; __d < __de; ++__d)
3221 if (!__ct.is(ctype_base::digit, *__d))
3222 break;
3223 // print fractional part
3224 if (__fd > 0)
3225 {
3226 int __f;
3227 for (__f = __fd; __d > __db && __f > 0; --__f)
3228 *__me++ = *--__d;
3229 char_type __z = __f > 0 ? __ct.widen('0') : char_type();
3230 for (; __f > 0; --__f)
3231 *__me++ = __z;
3232 *__me++ = __dp;
3233 }
3234 // print units part
3235 if (__d == __db)
3236 {
3237 *__me++ = __ct.widen('0');
3238 }
3239 else
3240 {
3241 unsigned __ng = 0;
3242 unsigned __ig = 0;
3243 unsigned __gl = __grp.empty() ? numeric_limits<unsigned>::max()
3244 : static_cast<unsigned>(__grp[__ig]);
3245 while (__d != __db)
3246 {
3247 if (__ng == __gl)
3248 {
3249 *__me++ = __ts;
3250 __ng = 0;
3251 if (++__ig < __grp.size())
3252 __gl = __grp[__ig] == numeric_limits<char>::max() ?
3253 numeric_limits<unsigned>::max() :
3254 static_cast<unsigned>(__grp[__ig]);
3255 }
3256 *__me++ = *--__d;
3257 ++__ng;
3258 }
3259 }
3260 // reverse it
3261 reverse(__t, __me);
3262 }
3263 break;
3264 }
3265 }
3266 // print rest of sign, if any
3267 if (__sn.size() > 1)
3268 __me = copy(__sn.begin()+1, __sn.end(), __me);
3269 // set alignment
3270 if ((__flags & ios_base::adjustfield) == ios_base::left)
3271 __mi = __me;
3272 else if ((__flags & ios_base::adjustfield) != ios_base::internal)
3273 __mi = __mb;
3274}
3275
3276extern template class __money_put<char>;
3277extern template class __money_put<wchar_t>;
3278
3279template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
3280class money_put
3281 : public locale::facet,
3282 private __money_put<_CharT>
3283{
3284public:
3285 typedef _CharT char_type;
3286 typedef _OutputIterator iter_type;
3287 typedef basic_string<char_type> string_type;
3288
3289 _LIBCPP_ALWAYS_INLINE
3290 explicit money_put(size_t __refs = 0)
3291 : locale::facet(__refs) {}
3292
3293 _LIBCPP_ALWAYS_INLINE
3294 iter_type put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl,
3295 long double __units) const
3296 {
3297 return do_put(__s, __intl, __iob, __fl, __units);
3298 }
3299
3300 _LIBCPP_ALWAYS_INLINE
3301 iter_type put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl,
3302 const string_type& __digits) const
3303 {
3304 return do_put(__s, __intl, __iob, __fl, __digits);
3305 }
3306
3307 static locale::id id;
3308
3309protected:
3310 ~money_put() {}
3311
3312 virtual iter_type do_put(iter_type __s, bool __intl, ios_base& __iob,
3313 char_type __fl, long double __units) const;
3314 virtual iter_type do_put(iter_type __s, bool __intl, ios_base& __iob,
3315 char_type __fl, const string_type& __digits) const;
3316};
3317
3318template <class _CharT, class _OutputIterator>
3319locale::id
3320money_put<_CharT, _OutputIterator>::id;
3321
3322template <class _CharT, class _OutputIterator>
3323_OutputIterator
3324money_put<_CharT, _OutputIterator>::do_put(iter_type __s, bool __intl,
3325 ios_base& __iob, char_type __fl,
3326 long double __units) const
3327{
3328 // convert to char
3329 const size_t __bs = 100;
3330 char __buf[__bs];
3331 char* __bb = __buf;
3332 char_type __digits[__bs];
3333 char_type* __db = __digits;
3334 size_t __n = snprintf(__bb, __bs, "%.0Lf", __units);
3335 unique_ptr<char, void(*)(void*)> __hn(0, free);
3336 unique_ptr<char_type, void(*)(void*)> __hd(0, free);
3337 // secure memory for digit storage
3338 if (__n > __bs-1)
3339 {
Howard Hinnantadff4892010-05-24 17:49:41 +00003340 __n = __nolocale_asprintf(&__bb, "%.0Lf", __units);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003341 if (__bb == 0)
3342 __throw_bad_alloc();
3343 __hn.reset(__bb);
3344 __hd.reset((char_type*)malloc(__n * sizeof(char_type)));
3345 if (__hd == 0)
3346 __throw_bad_alloc();
3347 __db = __hd.get();
3348 }
3349 // gather info
3350 locale __loc = __iob.getloc();
3351 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3352 __ct.widen(__bb, __bb + __n, __db);
3353 bool __neg = __n > 0 && __bb[0] == '-';
3354 money_base::pattern __pat;
3355 char_type __dp;
3356 char_type __ts;
3357 string __grp;
3358 string_type __sym;
3359 string_type __sn;
3360 int __fd;
3361 this->__gather_info(__intl, __neg, __loc, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3362 // secure memory for formatting
3363 char_type __mbuf[__bs];
3364 char_type* __mb = __mbuf;
3365 unique_ptr<char_type, void(*)(void*)> __hw(0, free);
3366 size_t __exn = static_cast<int>(__n) > __fd ?
3367 (__n - __fd) * 2 + __sn.size() + __sym.size() + __fd + 1
3368 : __sn.size() + __sym.size() + __fd + 2;
3369 if (__exn > __bs)
3370 {
3371 __hw.reset((char_type*)malloc(__exn * sizeof(char_type)));
3372 __mb = __hw.get();
3373 if (__mb == 0)
3374 __throw_bad_alloc();
3375 }
3376 // format
3377 char_type* __mi;
3378 char_type* __me;
3379 this->__format(__mb, __mi, __me, __iob.flags(),
3380 __db, __db + __n, __ct,
3381 __neg, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3382 return __pad_and_output(__s, __mb, __mi, __me, __iob, __fl);
3383}
3384
3385template <class _CharT, class _OutputIterator>
3386_OutputIterator
3387money_put<_CharT, _OutputIterator>::do_put(iter_type __s, bool __intl,
3388 ios_base& __iob, char_type __fl,
3389 const string_type& __digits) const
3390{
3391 // gather info
3392 locale __loc = __iob.getloc();
3393 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3394 bool __neg = __digits.size() > 0 && __digits[0] == __ct.widen('-');
3395 money_base::pattern __pat;
3396 char_type __dp;
3397 char_type __ts;
3398 string __grp;
3399 string_type __sym;
3400 string_type __sn;
3401 int __fd;
3402 this->__gather_info(__intl, __neg, __loc, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3403 // secure memory for formatting
3404 char_type __mbuf[100];
3405 char_type* __mb = __mbuf;
3406 unique_ptr<char_type, void(*)(void*)> __h(0, free);
3407 size_t __exn = __digits.size() > __fd ?
3408 (__digits.size() - __fd) * 2 + __sn.size() + __sym.size() + __fd + 1
3409 : __sn.size() + __sym.size() + __fd + 2;
3410 if (__exn > 100)
3411 {
3412 __h.reset((char_type*)malloc(__exn * sizeof(char_type)));
3413 __mb = __h.get();
3414 if (__mb == 0)
3415 __throw_bad_alloc();
3416 }
3417 // format
3418 char_type* __mi;
3419 char_type* __me;
3420 this->__format(__mb, __mi, __me, __iob.flags(),
3421 __digits.data(), __digits.data() + __digits.size(), __ct,
3422 __neg, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3423 return __pad_and_output(__s, __mb, __mi, __me, __iob, __fl);
3424}
3425
3426extern template class money_put<char>;
3427extern template class money_put<wchar_t>;
3428
3429// messages
3430
3431class messages_base
3432{
3433public:
3434 typedef nl_catd catalog;
3435
3436 _LIBCPP_ALWAYS_INLINE messages_base() {}
3437};
3438
3439template <class _CharT>
3440class messages
3441 : public locale::facet,
3442 public messages_base
3443{
3444public:
3445 typedef _CharT char_type;
3446 typedef basic_string<_CharT> string_type;
3447
3448 _LIBCPP_ALWAYS_INLINE
3449 explicit messages(size_t __refs = 0)
3450 : locale::facet(__refs) {}
3451
3452 _LIBCPP_ALWAYS_INLINE
3453 catalog open(const basic_string<char>& __nm, const locale& __loc) const
3454 {
3455 return do_open(__nm, __loc);
3456 }
3457
3458 _LIBCPP_ALWAYS_INLINE
3459 string_type get(catalog __c, int __set, int __msgid,
3460 const string_type& __dflt) const
3461 {
3462 return do_get(__c, __set, __msgid, __dflt);
3463 }
3464
3465 _LIBCPP_ALWAYS_INLINE
3466 void close(catalog __c) const
3467 {
3468 do_close(__c);
3469 }
3470
3471 static locale::id id;
3472
3473protected:
3474 ~messages() {}
3475
3476 virtual catalog do_open(const basic_string<char>&, const locale&) const;
3477 virtual string_type do_get(catalog, int __set, int __msgid,
3478 const string_type& __dflt) const;
3479 virtual void do_close(catalog) const;
3480};
3481
3482template <class _CharT>
3483locale::id
3484messages<_CharT>::id;
3485
3486template <class _CharT>
3487typename messages<_CharT>::catalog
3488messages<_CharT>::do_open(const basic_string<char>& __nm, const locale&) const
3489{
3490 return catopen(__nm.c_str(), NL_CAT_LOCALE);
3491}
3492
3493template <class _CharT>
3494typename messages<_CharT>::string_type
3495messages<_CharT>::do_get(catalog __c, int __set, int __msgid,
3496 const string_type& __dflt) const
3497{
3498 string __ndflt;
3499 __narrow_to_utf8<sizeof(char_type)*__CHAR_BIT__>()(back_inserter(__ndflt),
3500 __dflt.c_str(),
3501 __dflt.c_str() + __dflt.size());
3502 char* __n = catgets(__c, __set, __msgid, __ndflt.c_str());
3503 string_type __w;
3504 __widen_from_utf8<sizeof(char_type)*__CHAR_BIT__>()(back_inserter(__w),
3505 __n, __n + strlen(__n));
3506 return __w;
3507}
3508
3509template <class _CharT>
3510void
3511messages<_CharT>::do_close(catalog __c) const
3512{
3513 catclose(__c);
3514}
3515
3516extern template class messages<char>;
3517extern template class messages<wchar_t>;
3518
3519template <class _CharT>
3520class messages_byname
3521 : public messages<_CharT>
3522{
3523public:
3524 typedef messages_base::catalog catalog;
3525 typedef basic_string<_CharT> string_type;
3526
3527 _LIBCPP_ALWAYS_INLINE
3528 explicit messages_byname(const char*, size_t __refs = 0)
3529 : messages<_CharT>(__refs) {}
3530
3531 _LIBCPP_ALWAYS_INLINE
3532 explicit messages_byname(const string&, size_t __refs = 0)
3533 : messages<_CharT>(__refs) {}
3534
3535protected:
3536 ~messages_byname() {}
3537};
3538
3539extern template class messages_byname<char>;
3540extern template class messages_byname<wchar_t>;
3541
Howard Hinnantd23b4642010-05-31 20:58:54 +00003542template<class _Codecvt, class _Elem = wchar_t,
3543 class _Wide_alloc = allocator<_Elem>,
3544 class _Byte_alloc = allocator<char> >
3545class wstring_convert
3546{
3547public:
3548 typedef basic_string<char, char_traits<char>, _Byte_alloc> byte_string;
3549 typedef basic_string<_Elem, char_traits<_Elem>, _Wide_alloc> wide_string;
3550 typedef typename _Codecvt::state_type state_type;
3551 typedef typename wide_string::traits_type::int_type int_type;
3552
3553private:
3554 byte_string __byte_err_string_;
3555 wide_string __wide_err_string_;
3556 _Codecvt* __cvtptr_;
3557 state_type __cvtstate_;
3558 size_t __cvtcount_;
3559
3560 wstring_convert(const wstring_convert& __wc);
3561 wstring_convert& operator=(const wstring_convert& __wc);
3562public:
3563 wstring_convert(_Codecvt* __pcvt = new _Codecvt);
3564 wstring_convert(_Codecvt* __pcvt, state_type __state);
3565 wstring_convert(const byte_string& __byte_err,
3566 const wide_string& __wide_err = wide_string());
Howard Hinnant73d21a42010-09-04 23:28:19 +00003567#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantd23b4642010-05-31 20:58:54 +00003568 wstring_convert(wstring_convert&& __wc);
3569#endif
3570 ~wstring_convert();
3571
3572 wide_string from_bytes(char __byte)
3573 {return from_bytes(&__byte, &__byte+1);}
3574 wide_string from_bytes(const char* __ptr)
3575 {return from_bytes(__ptr, __ptr + char_traits<char>::length(__ptr));}
3576 wide_string from_bytes(const byte_string& __str)
3577 {return from_bytes(__str.data(), __str.data() + __str.size());}
3578 wide_string from_bytes(const char* __first, const char* __last);
3579
3580 byte_string to_bytes(_Elem __wchar)
3581 {return to_bytes(&__wchar, &__wchar+1);}
3582 byte_string to_bytes(const _Elem* __wptr)
3583 {return to_bytes(__wptr, __wptr + char_traits<_Elem>::length(__wptr));}
3584 byte_string to_bytes(const wide_string& __wstr)
3585 {return to_bytes(__wstr.data(), __wstr.data() + __wstr.size());}
3586 byte_string to_bytes(const _Elem* __first, const _Elem* __last);
3587
3588 size_t converted() const {return __cvtcount_;}
3589 state_type state() const {return __cvtstate_;}
3590};
3591
3592template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3593inline
3594wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3595 wstring_convert(_Codecvt* __pcvt)
3596 : __cvtptr_(__pcvt), __cvtstate_(), __cvtcount_(0)
3597{
3598}
3599
3600template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3601inline
3602wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3603 wstring_convert(_Codecvt* __pcvt, state_type __state)
3604 : __cvtptr_(__pcvt), __cvtstate_(__state), __cvtcount_(0)
3605{
3606}
3607
3608template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3609wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3610 wstring_convert(const byte_string& __byte_err, const wide_string& __wide_err)
3611 : __byte_err_string_(__byte_err), __wide_err_string_(__wide_err),
3612 __cvtstate_(), __cvtcount_(0)
3613{
3614 __cvtptr_ = new _Codecvt;
3615}
3616
Howard Hinnant73d21a42010-09-04 23:28:19 +00003617#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantd23b4642010-05-31 20:58:54 +00003618
3619template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3620inline
3621wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3622 wstring_convert(wstring_convert&& __wc)
3623 : __byte_err_string_(_STD::move(__wc.__byte_err_string_)),
3624 __wide_err_string_(_STD::move(__wc.__wide_err_string_)),
3625 __cvtptr_(__wc.__cvtptr_),
3626 __cvtstate_(__wc.__cvtstate_), __cvtcount_(__wc.__cvtstate_)
3627{
3628 __wc.__cvtptr_ = nullptr;
3629}
3630
Howard Hinnant73d21a42010-09-04 23:28:19 +00003631#endif // _LIBCPP_HAS_NO_VARIADICS
Howard Hinnantd23b4642010-05-31 20:58:54 +00003632
3633template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3634wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::~wstring_convert()
3635{
3636 delete __cvtptr_;
3637}
3638
3639template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3640typename wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::wide_string
3641wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3642 from_bytes(const char* __frm, const char* __frm_end)
3643{
3644 __cvtcount_ = 0;
3645 if (__cvtptr_ != nullptr)
3646 {
3647 wide_string __ws(2*(__frm_end - __frm), _Elem());
3648 __ws.resize(__ws.capacity());
3649 codecvt_base::result __r = codecvt_base::ok;
3650 state_type __st = __cvtstate_;
3651 if (__frm != __frm_end)
3652 {
3653 _Elem* __to = &__ws[0];
3654 _Elem* __to_end = __to + __ws.size();
3655 const char* __frm_nxt;
3656 do
3657 {
3658 _Elem* __to_nxt;
3659 __r = __cvtptr_->in(__st, __frm, __frm_end, __frm_nxt,
3660 __to, __to_end, __to_nxt);
3661 __cvtcount_ += __frm_nxt - __frm;
3662 if (__frm_nxt == __frm)
3663 {
3664 __r = codecvt_base::error;
3665 }
3666 else if (__r == codecvt_base::noconv)
3667 {
3668 __ws.resize(__to - &__ws[0]);
3669 // This only gets executed if _Elem is char
3670 __ws.append((const _Elem*)__frm, (const _Elem*)__frm_end);
3671 __frm = __frm_nxt;
3672 __r = codecvt_base::ok;
3673 }
3674 else if (__r == codecvt_base::ok)
3675 {
3676 __ws.resize(__to_nxt - &__ws[0]);
3677 __frm = __frm_nxt;
3678 }
3679 else if (__r == codecvt_base::partial)
3680 {
3681 ptrdiff_t __s = __to_nxt - &__ws[0];
3682 __ws.resize(2 * __s);
3683 __to = &__ws[0] + __s;
3684 __to_end = &__ws[0] + __ws.size();
3685 __frm = __frm_nxt;
3686 }
3687 } while (__r == codecvt_base::partial && __frm_nxt < __frm_end);
3688 }
3689 if (__r == codecvt_base::ok)
3690 return __ws;
3691 }
Howard Hinnantd4444702010-08-11 17:04:31 +00003692#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00003693 if (__wide_err_string_.empty())
3694 throw range_error("wstring_convert: from_bytes error");
Howard Hinnant324bb032010-08-22 00:02:43 +00003695#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00003696 return __wide_err_string_;
3697}
3698
3699template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3700typename wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::byte_string
3701wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3702 to_bytes(const _Elem* __frm, const _Elem* __frm_end)
3703{
3704 __cvtcount_ = 0;
3705 if (__cvtptr_ != nullptr)
3706 {
3707 byte_string __bs(2*(__frm_end - __frm), char());
3708 __bs.resize(__bs.capacity());
3709 codecvt_base::result __r = codecvt_base::ok;
3710 state_type __st = __cvtstate_;
3711 if (__frm != __frm_end)
3712 {
3713 char* __to = &__bs[0];
3714 char* __to_end = __to + __bs.size();
3715 const _Elem* __frm_nxt;
3716 do
3717 {
3718 char* __to_nxt;
3719 __r = __cvtptr_->out(__st, __frm, __frm_end, __frm_nxt,
3720 __to, __to_end, __to_nxt);
3721 __cvtcount_ += __frm_nxt - __frm;
3722 if (__frm_nxt == __frm)
3723 {
3724 __r = codecvt_base::error;
3725 }
3726 else if (__r == codecvt_base::noconv)
3727 {
3728 __bs.resize(__to - &__bs[0]);
3729 // This only gets executed if _Elem is char
3730 __bs.append((const char*)__frm, (const char*)__frm_end);
3731 __frm = __frm_nxt;
3732 __r = codecvt_base::ok;
3733 }
3734 else if (__r == codecvt_base::ok)
3735 {
3736 __bs.resize(__to_nxt - &__bs[0]);
3737 __frm = __frm_nxt;
3738 }
3739 else if (__r == codecvt_base::partial)
3740 {
3741 ptrdiff_t __s = __to_nxt - &__bs[0];
3742 __bs.resize(2 * __s);
3743 __to = &__bs[0] + __s;
3744 __to_end = &__bs[0] + __bs.size();
3745 __frm = __frm_nxt;
3746 }
3747 } while (__r == codecvt_base::partial && __frm_nxt < __frm_end);
3748 }
3749 if (__r == codecvt_base::ok)
3750 {
3751 size_t __s = __bs.size();
3752 __bs.resize(__bs.capacity());
3753 char* __to = &__bs[0] + __s;
3754 char* __to_end = __to + __bs.size();
3755 do
3756 {
3757 char* __to_nxt;
3758 __r = __cvtptr_->unshift(__st, __to, __to_end, __to_nxt);
3759 if (__r == codecvt_base::noconv)
3760 {
3761 __bs.resize(__to - &__bs[0]);
3762 __r = codecvt_base::ok;
3763 }
3764 else if (__r == codecvt_base::ok)
3765 {
3766 __bs.resize(__to_nxt - &__bs[0]);
3767 }
3768 else if (__r == codecvt_base::partial)
3769 {
3770 ptrdiff_t __s = __to_nxt - &__bs[0];
3771 __bs.resize(2 * __s);
3772 __to = &__bs[0] + __s;
3773 __to_end = &__bs[0] + __bs.size();
3774 }
3775 } while (__r == codecvt_base::partial);
3776 if (__r == codecvt_base::ok)
3777 return __bs;
3778 }
3779 }
Howard Hinnantd4444702010-08-11 17:04:31 +00003780#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00003781 if (__byte_err_string_.empty())
3782 throw range_error("wstring_convert: to_bytes error");
Howard Hinnant324bb032010-08-22 00:02:43 +00003783#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00003784 return __byte_err_string_;
3785}
3786
3787template <class _Codecvt, class _Elem = wchar_t, class _Tr = char_traits<_Elem> >
3788class wbuffer_convert
3789 : public basic_streambuf<_Elem, _Tr>
3790{
3791public:
3792 // types:
3793 typedef _Elem char_type;
3794 typedef _Tr traits_type;
3795 typedef typename traits_type::int_type int_type;
3796 typedef typename traits_type::pos_type pos_type;
3797 typedef typename traits_type::off_type off_type;
3798 typedef typename _Codecvt::state_type state_type;
3799
3800private:
Howard Hinnant4b53f502010-06-01 20:09:18 +00003801 char* __extbuf_;
3802 const char* __extbufnext_;
3803 const char* __extbufend_;
3804 char __extbuf_min_[8];
3805 size_t __ebs_;
3806 char_type* __intbuf_;
3807 size_t __ibs_;
Howard Hinnantd23b4642010-05-31 20:58:54 +00003808 streambuf* __bufptr_;
Howard Hinnant4b53f502010-06-01 20:09:18 +00003809 _Codecvt* __cv_;
3810 state_type __st_;
3811 ios_base::openmode __cm_;
3812 bool __owns_eb_;
3813 bool __owns_ib_;
3814 bool __always_noconv_;
Howard Hinnantd23b4642010-05-31 20:58:54 +00003815
Howard Hinnant4b53f502010-06-01 20:09:18 +00003816 wbuffer_convert(const wbuffer_convert&);
3817 wbuffer_convert& operator=(const wbuffer_convert&);
Howard Hinnantd23b4642010-05-31 20:58:54 +00003818public:
3819 wbuffer_convert(streambuf* __bytebuf = 0, _Codecvt* __pcvt = new _Codecvt,
Howard Hinnant4b53f502010-06-01 20:09:18 +00003820 state_type __state = state_type());
3821 ~wbuffer_convert();
Howard Hinnantd23b4642010-05-31 20:58:54 +00003822
3823 streambuf* rdbuf() const {return __bufptr_;}
3824 streambuf* rdbuf(streambuf* __bytebuf)
3825 {
3826 streambuf* __r = __bufptr_;
3827 __bufptr_ = __bytebuf;
3828 return __r;
3829 }
3830
Howard Hinnant4b53f502010-06-01 20:09:18 +00003831 state_type state() const {return __st_;}
Howard Hinnantd23b4642010-05-31 20:58:54 +00003832
3833protected:
Howard Hinnant4b53f502010-06-01 20:09:18 +00003834 virtual int_type underflow();
3835 virtual int_type pbackfail(int_type __c = traits_type::eof());
Howard Hinnantd23b4642010-05-31 20:58:54 +00003836 virtual int_type overflow (int_type __c = traits_type::eof());
Howard Hinnant4b53f502010-06-01 20:09:18 +00003837 virtual basic_streambuf<char_type, traits_type>* setbuf(char_type* __s,
3838 streamsize __n);
3839 virtual pos_type seekoff(off_type __off, ios_base::seekdir __way,
3840 ios_base::openmode __wch = ios_base::in | ios_base::out);
3841 virtual pos_type seekpos(pos_type __sp,
3842 ios_base::openmode __wch = ios_base::in | ios_base::out);
3843 virtual int sync();
3844
3845private:
3846 bool __read_mode();
3847 void __write_mode();
3848 wbuffer_convert* __close();
Howard Hinnantd23b4642010-05-31 20:58:54 +00003849};
3850
3851template <class _Codecvt, class _Elem, class _Tr>
Howard Hinnant4b53f502010-06-01 20:09:18 +00003852wbuffer_convert<_Codecvt, _Elem, _Tr>::
3853 wbuffer_convert(streambuf* __bytebuf, _Codecvt* __pcvt, state_type __state)
3854 : __extbuf_(0),
3855 __extbufnext_(0),
3856 __extbufend_(0),
3857 __ebs_(0),
3858 __intbuf_(0),
3859 __ibs_(0),
3860 __bufptr_(__bytebuf),
3861 __cv_(__pcvt),
3862 __st_(__state),
3863 __cm_(0),
3864 __owns_eb_(false),
3865 __owns_ib_(false),
3866 __always_noconv_(__cv_ ? __cv_->always_noconv() : false)
3867{
3868 setbuf(0, 4096);
3869}
3870
3871template <class _Codecvt, class _Elem, class _Tr>
3872wbuffer_convert<_Codecvt, _Elem, _Tr>::~wbuffer_convert()
3873{
3874 __close();
3875 delete __cv_;
3876 if (__owns_eb_)
3877 delete [] __extbuf_;
3878 if (__owns_ib_)
3879 delete [] __intbuf_;
3880}
3881
3882template <class _Codecvt, class _Elem, class _Tr>
3883typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
3884wbuffer_convert<_Codecvt, _Elem, _Tr>::underflow()
3885{
3886 if (__cv_ == 0 || __bufptr_ == 0)
3887 return traits_type::eof();
3888 bool __initial = __read_mode();
3889 char_type __1buf;
3890 if (this->gptr() == 0)
3891 this->setg(&__1buf, &__1buf+1, &__1buf+1);
3892 const size_t __unget_sz = __initial ? 0 : min<size_t>((this->egptr() - this->eback()) / 2, 4);
3893 int_type __c = traits_type::eof();
3894 if (this->gptr() == this->egptr())
3895 {
3896 memmove(this->eback(), this->egptr() - __unget_sz, __unget_sz * sizeof(char_type));
3897 if (__always_noconv_)
3898 {
3899 streamsize __nmemb = static_cast<streamsize>(this->egptr() - this->eback() - __unget_sz);
3900 __nmemb = __bufptr_->sgetn((char*)this->eback() + __unget_sz, __nmemb);
3901 if (__nmemb != 0)
3902 {
3903 this->setg(this->eback(),
3904 this->eback() + __unget_sz,
3905 this->eback() + __unget_sz + __nmemb);
3906 __c = *this->gptr();
3907 }
3908 }
3909 else
3910 {
3911 memmove(__extbuf_, __extbufnext_, __extbufend_ - __extbufnext_);
3912 __extbufnext_ = __extbuf_ + (__extbufend_ - __extbufnext_);
3913 __extbufend_ = __extbuf_ + (__extbuf_ == __extbuf_min_ ? sizeof(__extbuf_min_) : __ebs_);
3914 streamsize __nmemb = min(static_cast<streamsize>(this->egptr() - this->eback() - __unget_sz),
3915 static_cast<streamsize>(__extbufend_ - __extbufnext_));
3916 codecvt_base::result __r;
3917 state_type __svs = __st_;
3918 streamsize __nr = __bufptr_->sgetn(const_cast<char*>(__extbufnext_), __nmemb);
3919 if (__nr != 0)
3920 {
3921 __extbufend_ = __extbufnext_ + __nr;
3922 char_type* __inext;
3923 __r = __cv_->in(__st_, __extbuf_, __extbufend_, __extbufnext_,
3924 this->eback() + __unget_sz,
3925 this->egptr(), __inext);
3926 if (__r == codecvt_base::noconv)
3927 {
3928 this->setg((char_type*)__extbuf_, (char_type*)__extbuf_, (char_type*)__extbufend_);
3929 __c = *this->gptr();
3930 }
3931 else if (__inext != this->eback() + __unget_sz)
3932 {
3933 this->setg(this->eback(), this->eback() + __unget_sz, __inext);
3934 __c = *this->gptr();
3935 }
3936 }
3937 }
3938 }
3939 else
3940 __c = *this->gptr();
3941 if (this->eback() == &__1buf)
3942 this->setg(0, 0, 0);
3943 return __c;
3944}
3945
3946template <class _Codecvt, class _Elem, class _Tr>
3947typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
3948wbuffer_convert<_Codecvt, _Elem, _Tr>::pbackfail(int_type __c)
3949{
3950 if (__cv_ != 0 && __bufptr_ != 0 && this->eback() < this->gptr())
3951 {
3952 if (traits_type::eq_int_type(__c, traits_type::eof()))
3953 {
3954 this->gbump(-1);
3955 return traits_type::not_eof(__c);
3956 }
3957 if (traits_type::eq(traits_type::to_char_type(__c), this->gptr()[-1]))
3958 {
3959 this->gbump(-1);
3960 *this->gptr() = traits_type::to_char_type(__c);
3961 return __c;
3962 }
3963 }
3964 return traits_type::eof();
3965}
3966
3967template <class _Codecvt, class _Elem, class _Tr>
Howard Hinnantd23b4642010-05-31 20:58:54 +00003968typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
3969wbuffer_convert<_Codecvt, _Elem, _Tr>::overflow(int_type __c)
3970{
Howard Hinnant4b53f502010-06-01 20:09:18 +00003971 if (__cv_ == 0 || __bufptr_ == 0)
3972 return traits_type::eof();
3973 __write_mode();
3974 char_type __1buf;
3975 char_type* __pb_save = this->pbase();
3976 char_type* __epb_save = this->epptr();
3977 if (!traits_type::eq_int_type(__c, traits_type::eof()))
3978 {
3979 if (this->pptr() == 0)
3980 this->setp(&__1buf, &__1buf+1);
3981 *this->pptr() = traits_type::to_char_type(__c);
3982 this->pbump(1);
3983 }
3984 if (this->pptr() != this->pbase())
3985 {
3986 if (__always_noconv_)
3987 {
3988 streamsize __nmemb = static_cast<streamsize>(this->pptr() - this->pbase());
3989 if (__bufptr_->sputn((const char*)this->pbase(), __nmemb) != __nmemb)
3990 return traits_type::eof();
3991 }
3992 else
3993 {
3994 char* __extbe = __extbuf_;
3995 codecvt_base::result __r;
3996 do
3997 {
3998 const char_type* __e;
3999 __r = __cv_->out(__st_, this->pbase(), this->pptr(), __e,
4000 __extbuf_, __extbuf_ + __ebs_, __extbe);
4001 if (__e == this->pbase())
4002 return traits_type::eof();
4003 if (__r == codecvt_base::noconv)
4004 {
4005 streamsize __nmemb = static_cast<size_t>(this->pptr() - this->pbase());
4006 if (__bufptr_->sputn((const char*)this->pbase(), __nmemb) != __nmemb)
4007 return traits_type::eof();
4008 }
4009 else if (__r == codecvt_base::ok || __r == codecvt_base::partial)
4010 {
4011 streamsize __nmemb = static_cast<size_t>(__extbe - __extbuf_);
4012 if (__bufptr_->sputn(__extbuf_, __nmemb) != __nmemb)
4013 return traits_type::eof();
4014 if (__r == codecvt_base::partial)
4015 {
4016 this->setp((char_type*)__e, this->pptr());
4017 this->pbump(this->epptr() - this->pbase());
4018 }
4019 }
4020 else
4021 return traits_type::eof();
4022 } while (__r == codecvt_base::partial);
4023 }
4024 this->setp(__pb_save, __epb_save);
4025 }
4026 return traits_type::not_eof(__c);
4027}
4028
4029template <class _Codecvt, class _Elem, class _Tr>
4030basic_streambuf<_Elem, _Tr>*
4031wbuffer_convert<_Codecvt, _Elem, _Tr>::setbuf(char_type* __s, streamsize __n)
4032{
4033 this->setg(0, 0, 0);
4034 this->setp(0, 0);
4035 if (__owns_eb_)
4036 delete [] __extbuf_;
4037 if (__owns_ib_)
4038 delete [] __intbuf_;
4039 __ebs_ = __n;
4040 if (__ebs_ > sizeof(__extbuf_min_))
4041 {
4042 if (__always_noconv_ && __s)
4043 {
4044 __extbuf_ = (char*)__s;
4045 __owns_eb_ = false;
4046 }
4047 else
4048 {
4049 __extbuf_ = new char[__ebs_];
4050 __owns_eb_ = true;
4051 }
4052 }
4053 else
4054 {
4055 __extbuf_ = __extbuf_min_;
4056 __ebs_ = sizeof(__extbuf_min_);
4057 __owns_eb_ = false;
4058 }
4059 if (!__always_noconv_)
4060 {
4061 __ibs_ = max<streamsize>(__n, sizeof(__extbuf_min_));
4062 if (__s && __ibs_ >= sizeof(__extbuf_min_))
4063 {
4064 __intbuf_ = __s;
4065 __owns_ib_ = false;
4066 }
4067 else
4068 {
4069 __intbuf_ = new char_type[__ibs_];
4070 __owns_ib_ = true;
4071 }
4072 }
4073 else
4074 {
4075 __ibs_ = 0;
4076 __intbuf_ = 0;
4077 __owns_ib_ = false;
4078 }
4079 return this;
4080}
4081
4082template <class _Codecvt, class _Elem, class _Tr>
4083typename wbuffer_convert<_Codecvt, _Elem, _Tr>::pos_type
4084wbuffer_convert<_Codecvt, _Elem, _Tr>::seekoff(off_type __off, ios_base::seekdir __way,
4085 ios_base::openmode __om)
4086{
4087 int __width = __cv_->encoding();
4088 if (__cv_ == 0 || __bufptr_ == 0 || (__width <= 0 && __off != 0) || sync())
4089 return pos_type(off_type(-1));
4090 // __width > 0 || __off == 0
4091 switch (__way)
4092 {
4093 case ios_base::beg:
4094 break;
4095 case ios_base::cur:
4096 break;
4097 case ios_base::end:
4098 break;
4099 default:
4100 return pos_type(off_type(-1));
4101 }
4102 pos_type __r = __bufptr_->pubseekoff(__width * __off, __way, __om);
4103 __r.state(__st_);
4104 return __r;
4105}
4106
4107template <class _Codecvt, class _Elem, class _Tr>
4108typename wbuffer_convert<_Codecvt, _Elem, _Tr>::pos_type
4109wbuffer_convert<_Codecvt, _Elem, _Tr>::seekpos(pos_type __sp, ios_base::openmode __wch)
4110{
4111 if (__cv_ == 0 || __bufptr_ == 0 || sync())
4112 return pos_type(off_type(-1));
4113 if (__bufptr_->pubseekpos(__sp, __wch) == pos_type(off_type(-1)))
4114 return pos_type(off_type(-1));
4115 return __sp;
4116}
4117
4118template <class _Codecvt, class _Elem, class _Tr>
4119int
4120wbuffer_convert<_Codecvt, _Elem, _Tr>::sync()
4121{
4122 if (__cv_ == 0 || __bufptr_ == 0)
4123 return 0;
4124 if (__cm_ & ios_base::out)
4125 {
4126 if (this->pptr() != this->pbase())
4127 if (overflow() == traits_type::eof())
4128 return -1;
4129 codecvt_base::result __r;
4130 do
4131 {
4132 char* __extbe;
4133 __r = __cv_->unshift(__st_, __extbuf_, __extbuf_ + __ebs_, __extbe);
4134 streamsize __nmemb = static_cast<streamsize>(__extbe - __extbuf_);
4135 if (__bufptr_->sputn(__extbuf_, __nmemb) != __nmemb)
4136 return -1;
4137 } while (__r == codecvt_base::partial);
4138 if (__r == codecvt_base::error)
4139 return -1;
4140 if (__bufptr_->pubsync())
4141 return -1;
4142 }
4143 else if (__cm_ & ios_base::in)
4144 {
4145 off_type __c;
4146 if (__always_noconv_)
4147 __c = this->egptr() - this->gptr();
4148 else
4149 {
4150 int __width = __cv_->encoding();
4151 __c = __extbufend_ - __extbufnext_;
4152 if (__width > 0)
4153 __c += __width * (this->egptr() - this->gptr());
4154 else
4155 {
4156 if (this->gptr() != this->egptr())
4157 {
4158 reverse(this->gptr(), this->egptr());
4159 codecvt_base::result __r;
4160 const char_type* __e = this->gptr();
4161 char* __extbe;
4162 do
4163 {
4164 __r = __cv_->out(__st_, __e, this->egptr(), __e,
4165 __extbuf_, __extbuf_ + __ebs_, __extbe);
4166 switch (__r)
4167 {
4168 case codecvt_base::noconv:
4169 __c += this->egptr() - this->gptr();
4170 break;
4171 case codecvt_base::ok:
4172 case codecvt_base::partial:
4173 __c += __extbe - __extbuf_;
4174 break;
4175 default:
4176 return -1;
4177 }
4178 } while (__r == codecvt_base::partial);
4179 }
4180 }
4181 }
4182 if (__bufptr_->pubseekoff(-__c, ios_base::cur, __cm_) == pos_type(off_type(-1)))
4183 return -1;
4184 this->setg(0, 0, 0);
4185 __cm_ = 0;
4186 }
4187 return 0;
4188}
4189
4190template <class _Codecvt, class _Elem, class _Tr>
4191bool
4192wbuffer_convert<_Codecvt, _Elem, _Tr>::__read_mode()
4193{
4194 if (!(__cm_ & ios_base::in))
4195 {
4196 this->setp(0, 0);
4197 if (__always_noconv_)
4198 this->setg((char_type*)__extbuf_,
4199 (char_type*)__extbuf_ + __ebs_,
4200 (char_type*)__extbuf_ + __ebs_);
4201 else
4202 this->setg(__intbuf_, __intbuf_ + __ibs_, __intbuf_ + __ibs_);
4203 __cm_ = ios_base::in;
4204 return true;
4205 }
4206 return false;
4207}
4208
4209template <class _Codecvt, class _Elem, class _Tr>
4210void
4211wbuffer_convert<_Codecvt, _Elem, _Tr>::__write_mode()
4212{
4213 if (!(__cm_ & ios_base::out))
4214 {
4215 this->setg(0, 0, 0);
4216 if (__ebs_ > sizeof(__extbuf_min_))
4217 {
4218 if (__always_noconv_)
4219 this->setp((char_type*)__extbuf_,
4220 (char_type*)__extbuf_ + (__ebs_ - 1));
4221 else
4222 this->setp(__intbuf_, __intbuf_ + (__ibs_ - 1));
4223 }
4224 else
4225 this->setp(0, 0);
4226 __cm_ = ios_base::out;
4227 }
4228}
4229
4230template <class _Codecvt, class _Elem, class _Tr>
4231wbuffer_convert<_Codecvt, _Elem, _Tr>*
4232wbuffer_convert<_Codecvt, _Elem, _Tr>::__close()
4233{
4234 wbuffer_convert* __rt = 0;
4235 if (__cv_ != 0 && __bufptr_ != 0)
4236 {
4237 __rt = this;
4238 if ((__cm_ & ios_base::out) && sync())
4239 __rt = 0;
4240 }
4241 return __rt;
Howard Hinnantd23b4642010-05-31 20:58:54 +00004242}
4243
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004244_LIBCPP_END_NAMESPACE_STD
4245
4246#endif // _LIBCPP_LOCALE