blob: c024e657a518c05e5f93761f9b867ae12782ce4c [file] [log] [blame]
Howard Hinnantc51e1022010-05-11 19:42:16 +00001// -*- C++ -*-
2//===-------------------------- locale ------------------------------------===//
3//
Howard Hinnantc566dc32010-05-11 21:36:01 +00004// The LLVM Compiler Infrastructure
Howard Hinnantc51e1022010-05-11 19:42:16 +00005//
Howard Hinnantee11c312010-11-16 22:09:02 +00006// This file is dual licensed under the MIT and the University of Illinois Open
7// Source Licenses. See LICENSE.TXT for details.
Howard Hinnantc51e1022010-05-11 19:42:16 +00008//
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 Hinnant9dd7e892010-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 Hinnantc51e1022010-05-11 19:42:16 +0000116template <class Codecvt, class Elem = wchar_t, class Tr = char_traits<Elem>>
Howard Hinnant9dd7e892010-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 Hinnantc51e1022010-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 Hinnant155c2af2010-05-24 17:49:41 +0000184#if !__APPLE__
185#include <cstdarg>
186#endif
Howard Hinnantc51e1022010-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 Hinnant155c2af2010-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>
Howard Hinnant756c69b2010-09-22 16:48:34 +0000201inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnant155c2af2010-05-24 17:49:41 +0000202int
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>
Howard Hinnant756c69b2010-09-22 16:48:34 +0000210inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnant155c2af2010-05-24 17:49:41 +0000211int
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>
Howard Hinnant756c69b2010-09-22 16:48:34 +0000219inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnant155c2af2010-05-24 17:49:41 +0000220int
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>
Howard Hinnant756c69b2010-09-22 16:48:34 +0000228inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnant155c2af2010-05-24 17:49:41 +0000229int
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>
Howard Hinnant756c69b2010-09-22 16:48:34 +0000236inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnant155c2af2010-05-24 17:49:41 +0000237int
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>
Howard Hinnant756c69b2010-09-22 16:48:34 +0000245inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnant155c2af2010-05-24 17:49:41 +0000246int
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
Howard Hinnant756c69b2010-09-22 16:48:34 +0000253inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnant155c2af2010-05-24 17:49:41 +0000254int
255__nolocale_isxdigit(int __c)
256{
257 return isxdigit_l(__c, 0);
258}
259
Howard Hinnant756c69b2010-09-22 16:48:34 +0000260inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnant155c2af2010-05-24 17:49:41 +0000261int
262__nolocale_isdigit(int __c)
263{
264 return isdigit_l(__c, 0);
265}
266
Howard Hinnant3b6579a2010-08-22 00:02:43 +0000267#else // __APPLE__
Michael J. Spencer8d8164e2010-12-10 19:47:54 +0000268inline
269#ifndef _LIBCPP_HAS_NO_ALWAYS_INLINE_VARIADICS
270_LIBCPP_INLINE_VISIBILITY
271#endif
Howard Hinnant756c69b2010-09-22 16:48:34 +0000272int
Howard Hinnant155c2af2010-05-24 17:49:41 +0000273__nolocale_sprintf(char* __restrict __str,
274 const char* __restrict __format, ...)
275{
276 va_list __ap;
277 va_start(__ap, __format);
278 int __result = vsprintf(__str, __format, __ap);
279 va_end(__ap);
280 return __result;
281}
Michael J. Spencer8d8164e2010-12-10 19:47:54 +0000282inline
283#ifndef _LIBCPP_HAS_NO_ALWAYS_INLINE_VARIADICS
284_LIBCPP_INLINE_VISIBILITY
285#endif
Howard Hinnant756c69b2010-09-22 16:48:34 +0000286int
Howard Hinnant155c2af2010-05-24 17:49:41 +0000287__nolocale_snprintf(char* __restrict __str, size_t __size,
288 const char* __restrict __format, ...)
289{
290 va_list __ap;
291 va_start(__ap, __format);
292 int __result = vsnprintf(__str, __size, __format, __ap);
293 va_end(__ap);
294 return __result;
295}
Michael J. Spencer8d8164e2010-12-10 19:47:54 +0000296inline
297#ifndef _LIBCPP_HAS_NO_ALWAYS_INLINE_VARIADICS
298_LIBCPP_INLINE_VISIBILITY
299#endif
Howard Hinnant756c69b2010-09-22 16:48:34 +0000300int
Howard Hinnant155c2af2010-05-24 17:49:41 +0000301__nolocale_asprintf(char** __ret,
302 const char* __restrict __format, ...)
303{
304 va_list __ap;
305 va_start(__ap, __format);
306 int __result = vasprintf(__ret, __format, __ap);
307 va_end(__ap);
308 return __result;
309}
Michael J. Spencer8d8164e2010-12-10 19:47:54 +0000310inline
311#ifndef _LIBCPP_HAS_NO_ALWAYS_INLINE_VARIADICS
312_LIBCPP_INLINE_VISIBILITY
313#endif
Howard Hinnant756c69b2010-09-22 16:48:34 +0000314int
Howard Hinnant155c2af2010-05-24 17:49:41 +0000315__nolocale_sscanf(const char* __restrict __str,
316 const char* __restrict __format, ...)
317{
318 va_list __ap;
319 va_start(__ap, __format);
320 int __result = vsscanf(__str, __format, __ap);
321 va_end(__ap);
322 return __result;
323}
Howard Hinnant756c69b2010-09-22 16:48:34 +0000324inline _LIBCPP_INLINE_VISIBILITY
325int
Howard Hinnant155c2af2010-05-24 17:49:41 +0000326__nolocale_isxdigit(int __c)
327{
328 return isxdigit(__c);
329}
Howard Hinnant756c69b2010-09-22 16:48:34 +0000330
331inline _LIBCPP_INLINE_VISIBILITY
332int
Howard Hinnant155c2af2010-05-24 17:49:41 +0000333__nolocale_isdigit(int __c)
334{
335 return isdigit(__c);
336}
Howard Hinnant3b6579a2010-08-22 00:02:43 +0000337#endif // __APPLE__
Howard Hinnant155c2af2010-05-24 17:49:41 +0000338
Howard Hinnantc51e1022010-05-11 19:42:16 +0000339// __scan_keyword
340// Scans [__b, __e) until a match is found in the basic_strings range
341// [__kb, __ke) or until it can be shown that there is no match in [__kb, __ke).
342// __b will be incremented (visibly), consuming CharT until a match is found
343// or proved to not exist. A keyword may be "", in which will match anything.
344// If one keyword is a prefix of another, and the next CharT in the input
345// might match another keyword, the algorithm will attempt to find the longest
346// matching keyword. If the longer matching keyword ends up not matching, then
347// no keyword match is found. If no keyword match is found, __ke is returned
348// and failbit is set in __err.
349// Else an iterator pointing to the matching keyword is found. If more than
350// one keyword matches, an iterator to the first matching keyword is returned.
351// If on exit __b == __e, eofbit is set in __err. If __case_senstive is false,
352// __ct is used to force to lower case before comparing characters.
353// Examples:
354// Keywords: "a", "abb"
355// If the input is "a", the first keyword matches and eofbit is set.
356// If the input is "abc", no match is found and "ab" are consumed.
357template <class _InputIterator, class _ForwardIterator, class _Ctype>
358_LIBCPP_HIDDEN
359_ForwardIterator
360__scan_keyword(_InputIterator& __b, _InputIterator __e,
361 _ForwardIterator __kb, _ForwardIterator __ke,
362 const _Ctype& __ct, ios_base::iostate& __err,
363 bool __case_sensitive = true)
364{
365 typedef typename iterator_traits<_InputIterator>::value_type _CharT;
366 size_t __nkw = _STD::distance(__kb, __ke);
367 const unsigned char __doesnt_match = '\0';
368 const unsigned char __might_match = '\1';
369 const unsigned char __does_match = '\2';
370 unsigned char __statbuf[100];
371 unsigned char* __status = __statbuf;
372 unique_ptr<unsigned char, void(*)(void*)> __stat_hold(0, free);
373 if (__nkw > sizeof(__statbuf))
374 {
375 __status = (unsigned char*)malloc(__nkw);
376 if (__status == 0)
377 __throw_bad_alloc();
378 __stat_hold.reset(__status);
379 }
380 size_t __n_might_match = __nkw; // At this point, any keyword might match
381 size_t __n_does_match = 0; // but none of them definitely do
382 // Initialize all statuses to __might_match, except for "" keywords are __does_match
383 unsigned char* __st = __status;
384 for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, ++__st)
385 {
386 if (!__ky->empty())
387 *__st = __might_match;
388 else
389 {
390 *__st = __does_match;
391 --__n_might_match;
392 ++__n_does_match;
393 }
394 }
395 // While there might be a match, test keywords against the next CharT
396 for (size_t __indx = 0; __b != __e && __n_might_match > 0; ++__indx)
397 {
398 // Peek at the next CharT but don't consume it
399 _CharT __c = *__b;
400 if (!__case_sensitive)
401 __c = __ct.toupper(__c);
402 bool __consume = false;
403 // For each keyword which might match, see if the __indx character is __c
404 // If a match if found, consume __c
405 // If a match is found, and that is the last character in the keyword,
406 // then that keyword matches.
407 // If the keyword doesn't match this character, then change the keyword
408 // to doesn't match
409 __st = __status;
410 for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, ++__st)
411 {
412 if (*__st == __might_match)
413 {
414 _CharT __kc = (*__ky)[__indx];
415 if (!__case_sensitive)
416 __kc = __ct.toupper(__kc);
417 if (__c == __kc)
418 {
419 __consume = true;
420 if (__ky->size() == __indx+1)
421 {
422 *__st = __does_match;
423 --__n_might_match;
424 ++__n_does_match;
425 }
426 }
427 else
428 {
429 *__st = __doesnt_match;
430 --__n_might_match;
431 }
432 }
433 }
434 // consume if we matched a character
435 if (__consume)
436 {
437 ++__b;
438 // If we consumed a character and there might be a matched keyword that
439 // was marked matched on a previous iteration, then such keywords
440 // which are now marked as not matching.
441 if (__n_might_match + __n_does_match > 1)
442 {
443 __st = __status;
444 for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, ++__st)
445 {
446 if (*__st == __does_match && __ky->size() != __indx+1)
447 {
448 *__st = __doesnt_match;
449 --__n_does_match;
450 }
451 }
452 }
453 }
454 }
455 // We've exited the loop because we hit eof and/or we have no more "might matches".
456 if (__b == __e)
457 __err |= ios_base::eofbit;
458 // Return the first matching result
459 for (__st = __status; __kb != __ke; ++__kb, ++__st)
460 if (*__st == __does_match)
461 break;
462 if (__kb == __ke)
463 __err |= ios_base::failbit;
464 return __kb;
465}
466
467struct __num_get_base
468{
469 static const int __num_get_buf_sz = 40;
470
471 static int __get_base(ios_base&);
472 static const char __src[33];
473};
474
475void __check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
476 ios_base::iostate& __err);
477
Howard Hinnantc51e1022010-05-11 19:42:16 +0000478template <class _CharT>
479struct __num_get
480 : protected __num_get_base
481{
482 static string __stage2_int_prep(ios_base& __iob, _CharT* __atoms, _CharT& __thousands_sep);
483 static string __stage2_float_prep(ios_base& __iob, _CharT* __atoms, _CharT& __decimal_point,
484 _CharT& __thousands_sep);
485 static int __stage2_int_loop(_CharT __ct, int __base, char* __a, char*& __a_end,
486 unsigned& __dc, _CharT __thousands_sep, const string& __grouping,
487 unsigned* __g, unsigned*& __g_end, _CharT* __atoms);
488 static int __stage2_float_loop(_CharT __ct, bool& __in_units, char& __exp,
489 char* __a, char*& __a_end,
490 _CharT __decimal_point, _CharT __thousands_sep,
491 const string& __grouping, unsigned* __g,
492 unsigned*& __g_end, unsigned& __dc, _CharT* __atoms);
493};
494
495template <class _CharT>
496string
497__num_get<_CharT>::__stage2_int_prep(ios_base& __iob, _CharT* __atoms, _CharT& __thousands_sep)
498{
499 locale __loc = __iob.getloc();
500 use_facet<ctype<_CharT> >(__loc).widen(__src, __src + 26, __atoms);
501 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
502 __thousands_sep = __np.thousands_sep();
503 return __np.grouping();
504}
505
506template <class _CharT>
507string
508__num_get<_CharT>::__stage2_float_prep(ios_base& __iob, _CharT* __atoms, _CharT& __decimal_point,
509 _CharT& __thousands_sep)
510{
511 locale __loc = __iob.getloc();
512 use_facet<ctype<_CharT> >(__loc).widen(__src, __src + 32, __atoms);
513 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
514 __decimal_point = __np.decimal_point();
515 __thousands_sep = __np.thousands_sep();
516 return __np.grouping();
517}
518
519template <class _CharT>
520int
521__num_get<_CharT>::__stage2_int_loop(_CharT __ct, int __base, char* __a, char*& __a_end,
522 unsigned& __dc, _CharT __thousands_sep, const string& __grouping,
523 unsigned* __g, unsigned*& __g_end, _CharT* __atoms)
524{
525 if (__ct == __thousands_sep && __grouping.size() != 0)
526 {
527 if (__g_end-__g < __num_get_buf_sz)
528 {
529 *__g_end++ = __dc;
530 __dc = 0;
531 }
532 return 0;
533 }
534 ptrdiff_t __f = find(__atoms, __atoms + 26, __ct) - __atoms;
535 if (__f >= 26)
536 return -1;
537 if (__a_end-__a < __num_get_buf_sz - 1)
538 *__a_end++ = __src[__f];
539 switch (__base)
540 {
541 case 8:
542 case 10:
543 if (__f >= __base)
544 return 0;
545 break;
546 default:
547 if (__f >= 22)
548 return 0;
549 break;
550 }
551 ++__dc;
552 return 0;
553}
554
555template <class _CharT>
556int
557__num_get<_CharT>::__stage2_float_loop(_CharT __ct, bool& __in_units, char& __exp, char* __a, char*& __a_end,
558 _CharT __decimal_point, _CharT __thousands_sep, const string& __grouping,
559 unsigned* __g, unsigned*& __g_end, unsigned& __dc, _CharT* __atoms)
560{
561 if (__ct == __decimal_point)
562 {
563 if (!__in_units)
564 return -1;
565 __in_units = false;
566 *__a_end++ = '.';
567 if (__grouping.size() != 0 && __g_end-__g < __num_get_buf_sz)
568 *__g_end++ = __dc;
569 return 0;
570 }
571 if (__ct == __thousands_sep && __grouping.size() != 0)
572 {
573 if (!__in_units)
574 return -1;
575 if (__g_end-__g < __num_get_buf_sz)
576 {
577 *__g_end++ = __dc;
578 __dc = 0;
579 }
580 return 0;
581 }
582 ptrdiff_t __f = find(__atoms, __atoms + 32, __ct) - __atoms;
583 if (__f >= 32)
584 return -1;
585 char __x = __src[__f];
586 if (__a_end-__a < __num_get_buf_sz - 1)
587 *__a_end++ = __x;
588 if (__x == 'x' || __x == 'X')
589 __exp = 'P';
590 else if ((__x & 0xDF) == __exp)
591 {
592 __in_units = false;
593 if (__grouping.size() != 0 && __g_end-__g < __num_get_buf_sz)
594 *__g_end++ = __dc;
595 }
596 if (__f >= 22)
597 return 0;
598 ++__dc;
599 return 0;
600}
601
602extern template class __num_get<char>;
603extern template class __num_get<wchar_t>;
604
605template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnant756c69b2010-09-22 16:48:34 +0000606class _LIBCPP_VISIBLE num_get
Howard Hinnantc51e1022010-05-11 19:42:16 +0000607 : public locale::facet,
608 private __num_get<_CharT>
609{
610public:
611 typedef _CharT char_type;
612 typedef _InputIterator iter_type;
613
614 _LIBCPP_ALWAYS_INLINE
615 explicit num_get(size_t __refs = 0)
616 : locale::facet(__refs) {}
617
618 _LIBCPP_ALWAYS_INLINE
619 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
620 ios_base::iostate& __err, bool& __v) const
621 {
622 return do_get(__b, __e, __iob, __err, __v);
623 }
624
625 _LIBCPP_ALWAYS_INLINE
626 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
627 ios_base::iostate& __err, long& __v) const
628 {
629 return do_get(__b, __e, __iob, __err, __v);
630 }
631
632 _LIBCPP_ALWAYS_INLINE
633 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
634 ios_base::iostate& __err, long long& __v) const
635 {
636 return do_get(__b, __e, __iob, __err, __v);
637 }
638
639 _LIBCPP_ALWAYS_INLINE
640 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
641 ios_base::iostate& __err, unsigned short& __v) const
642 {
643 return do_get(__b, __e, __iob, __err, __v);
644 }
645
646 _LIBCPP_ALWAYS_INLINE
647 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
648 ios_base::iostate& __err, unsigned int& __v) const
649 {
650 return do_get(__b, __e, __iob, __err, __v);
651 }
652
653 _LIBCPP_ALWAYS_INLINE
654 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
655 ios_base::iostate& __err, unsigned long& __v) const
656 {
657 return do_get(__b, __e, __iob, __err, __v);
658 }
659
660 _LIBCPP_ALWAYS_INLINE
661 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
662 ios_base::iostate& __err, unsigned long long& __v) const
663 {
664 return do_get(__b, __e, __iob, __err, __v);
665 }
666
667 _LIBCPP_ALWAYS_INLINE
668 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
669 ios_base::iostate& __err, float& __v) const
670 {
671 return do_get(__b, __e, __iob, __err, __v);
672 }
673
674 _LIBCPP_ALWAYS_INLINE
675 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
676 ios_base::iostate& __err, double& __v) const
677 {
678 return do_get(__b, __e, __iob, __err, __v);
679 }
680
681 _LIBCPP_ALWAYS_INLINE
682 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
683 ios_base::iostate& __err, long double& __v) const
684 {
685 return do_get(__b, __e, __iob, __err, __v);
686 }
687
688 _LIBCPP_ALWAYS_INLINE
689 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
690 ios_base::iostate& __err, void*& __v) const
691 {
692 return do_get(__b, __e, __iob, __err, __v);
693 }
694
695 static locale::id id;
696
697protected:
Howard Hinnant756c69b2010-09-22 16:48:34 +0000698 _LIBCPP_ALWAYS_INLINE
Howard Hinnantc51e1022010-05-11 19:42:16 +0000699 ~num_get() {}
700
701 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
702 ios_base::iostate& __err, bool& __v) const;
703 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
704 ios_base::iostate& __err, long& __v) const;
705 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
706 ios_base::iostate& __err, long long& __v) const;
707 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
708 ios_base::iostate& __err, unsigned short& __v) const;
709 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
710 ios_base::iostate& __err, unsigned int& __v) const;
711 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
712 ios_base::iostate& __err, unsigned long& __v) const;
713 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
714 ios_base::iostate& __err, unsigned long long& __v) const;
715 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
716 ios_base::iostate& __err, float& __v) const;
717 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
718 ios_base::iostate& __err, double& __v) const;
719 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
720 ios_base::iostate& __err, long double& __v) const;
721 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
722 ios_base::iostate& __err, void*& __v) const;
723};
724
725template <class _CharT, class _InputIterator>
726locale::id
727num_get<_CharT, _InputIterator>::id;
728
729template <class _Tp>
730_Tp
731__num_get_signed_integral(const char* __a, const char* __a_end,
732 ios_base::iostate& __err, int __base)
733{
734 if (__a != __a_end)
735 {
Howard Hinnant05c71342011-02-25 19:52:41 +0000736 int __save_errno = errno;
737 errno = 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000738 char *__p2;
739 long long __ll = strtoll_l(__a, &__p2, __base, 0);
Howard Hinnant05c71342011-02-25 19:52:41 +0000740 int __current_errno = errno;
741 if (__current_errno == 0)
742 errno = __save_errno;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000743 if (__p2 != __a_end)
744 {
745 __err = ios_base::failbit;
746 return 0;
747 }
Howard Hinnant05c71342011-02-25 19:52:41 +0000748 else if (__current_errno == ERANGE ||
749 __ll < numeric_limits<_Tp>::min() ||
750 numeric_limits<_Tp>::max() < __ll)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000751 {
752 __err = ios_base::failbit;
Howard Hinnant05c71342011-02-25 19:52:41 +0000753 if (__ll > 0)
754 return numeric_limits<_Tp>::max();
755 else
756 return numeric_limits<_Tp>::min();
Howard Hinnantc51e1022010-05-11 19:42:16 +0000757 }
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_unsigned_integral(const char* __a, const char* __a_end,
767 ios_base::iostate& __err, int __base)
768{
769 if (__a != __a_end)
770 {
Howard Hinnant05c71342011-02-25 19:52:41 +0000771 if (*__a == '-')
772 {
773 __err = ios_base::failbit;
774 return 0;
775 }
776 int __save_errno = errno;
777 errno = 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000778 char *__p2;
779 unsigned long long __ll = strtoull_l(__a, &__p2, __base, 0);
Howard Hinnant05c71342011-02-25 19:52:41 +0000780 int __current_errno = errno;
781 if (__current_errno == 0)
782 errno = __save_errno;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000783 if (__p2 != __a_end)
784 {
785 __err = ios_base::failbit;
786 return 0;
787 }
Howard Hinnant05c71342011-02-25 19:52:41 +0000788 else if (__current_errno == ERANGE ||
789 numeric_limits<_Tp>::max() < __ll)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000790 {
791 __err = ios_base::failbit;
792 return numeric_limits<_Tp>::max();
793 }
794 return static_cast<_Tp>(__ll);
795 }
796 __err = ios_base::failbit;
797 return 0;
798}
799
800template <class _Tp>
801_Tp
802__num_get_float(const char* __a, const char* __a_end, ios_base::iostate& __err)
803{
804 if (__a != __a_end)
805 {
806 char *__p2;
807 long double __ld = strtold_l(__a, &__p2, 0);
808 if (__p2 != __a_end)
809 {
810 __err = ios_base::failbit;
811 return 0;
812 }
813 return static_cast<_Tp>(__ld);
814 }
815 __err = ios_base::failbit;
816 return 0;
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 bool& __v) const
825{
826 if ((__iob.flags() & ios_base::boolalpha) == 0)
827 {
828 long __lv = -1;
829 __b = do_get(__b, __e, __iob, __err, __lv);
830 switch (__lv)
831 {
832 case 0:
833 __v = false;
834 break;
835 case 1:
836 __v = true;
837 break;
838 default:
839 __v = true;
840 __err = ios_base::failbit;
841 break;
842 }
843 return __b;
844 }
845 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__iob.getloc());
846 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__iob.getloc());
847 typedef typename numpunct<_CharT>::string_type string_type;
848 const string_type __names[2] = {__np.truename(), __np.falsename()};
849 const string_type* __i = __scan_keyword(__b, __e, __names, __names+2,
850 __ct, __err);
851 __v = __i == __names;
852 return __b;
853}
854
855template <class _CharT, class _InputIterator>
856_InputIterator
857num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
858 ios_base& __iob,
859 ios_base::iostate& __err,
860 long& __v) const
861{
862 // Stage 1
863 int __base = this->__get_base(__iob);
864 // Stage 2
865 char_type __atoms[26];
866 char_type __thousands_sep;
867 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
868 char __a[__num_get_base::__num_get_buf_sz] = {0};
869 char* __a_end = __a;
870 unsigned __g[__num_get_base::__num_get_buf_sz];
871 unsigned* __g_end = __g;
872 unsigned __dc = 0;
873 for (; __b != __e; ++__b)
Howard Hinnant3b6579a2010-08-22 00:02:43 +0000874 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantc51e1022010-05-11 19:42:16 +0000875 __thousands_sep, __grouping, __g, __g_end,
876 __atoms))
877 break;
878 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
879 *__g_end++ = __dc;
880 // Stage 3
881 __v = __num_get_signed_integral<long>(__a, __a_end, __err, __base);
882 // Digit grouping checked
883 __check_grouping(__grouping, __g, __g_end, __err);
884 // EOF checked
885 if (__b == __e)
886 __err |= ios_base::eofbit;
887 return __b;
888}
889
890template <class _CharT, class _InputIterator>
891_InputIterator
892num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
893 ios_base& __iob,
894 ios_base::iostate& __err,
895 long long& __v) const
896{
897 // Stage 1
898 int __base = this->__get_base(__iob);
899 // Stage 2
900 char_type __atoms[26];
901 char_type __thousands_sep;
902 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
903 char __a[__num_get_base::__num_get_buf_sz] = {0};
904 char* __a_end = __a;
905 unsigned __g[__num_get_base::__num_get_buf_sz];
906 unsigned* __g_end = __g;
907 unsigned __dc = 0;
908 for (; __b != __e; ++__b)
Howard Hinnant3b6579a2010-08-22 00:02:43 +0000909 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
910 __thousands_sep, __grouping, __g, __g_end,
Howard Hinnantc51e1022010-05-11 19:42:16 +0000911 __atoms))
912 break;
913 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
914 *__g_end++ = __dc;
915 // Stage 3
916 __v = __num_get_signed_integral<long long>(__a, __a_end, __err, __base);
917 // Digit grouping checked
918 __check_grouping(__grouping, __g, __g_end, __err);
919 // EOF checked
920 if (__b == __e)
921 __err |= ios_base::eofbit;
922 return __b;
923}
924
925template <class _CharT, class _InputIterator>
926_InputIterator
927num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
928 ios_base& __iob,
929 ios_base::iostate& __err,
930 unsigned short& __v) const
931{
932 // Stage 1
933 int __base = this->__get_base(__iob);
934 // Stage 2
935 char_type __atoms[26];
936 char_type __thousands_sep;
937 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
938 char __a[__num_get_base::__num_get_buf_sz] = {0};
939 char* __a_end = __a;
940 unsigned __g[__num_get_base::__num_get_buf_sz];
941 unsigned* __g_end = __g;
942 unsigned __dc = 0;
943 for (; __b != __e; ++__b)
Howard Hinnant3b6579a2010-08-22 00:02:43 +0000944 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantc51e1022010-05-11 19:42:16 +0000945 __thousands_sep, __grouping, __g, __g_end,
946 __atoms))
947 break;
948 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
949 *__g_end++ = __dc;
950 // Stage 3
951 __v = __num_get_unsigned_integral<unsigned short>(__a, __a_end, __err, __base);
952 // Digit grouping checked
953 __check_grouping(__grouping, __g, __g_end, __err);
954 // EOF checked
955 if (__b == __e)
956 __err |= ios_base::eofbit;
957 return __b;
958}
959
960template <class _CharT, class _InputIterator>
961_InputIterator
962num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
963 ios_base& __iob,
964 ios_base::iostate& __err,
965 unsigned int& __v) const
966{
967 // Stage 1
968 int __base = this->__get_base(__iob);
969 // Stage 2
970 char_type __atoms[26];
971 char_type __thousands_sep;
972 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
973 char __a[__num_get_base::__num_get_buf_sz] = {0};
974 char* __a_end = __a;
975 unsigned __g[__num_get_base::__num_get_buf_sz];
976 unsigned* __g_end = __g;
977 unsigned __dc = 0;
978 for (; __b != __e; ++__b)
Howard Hinnant3b6579a2010-08-22 00:02:43 +0000979 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantc51e1022010-05-11 19:42:16 +0000980 __thousands_sep, __grouping, __g, __g_end,
981 __atoms))
982 break;
983 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
984 *__g_end++ = __dc;
985 // Stage 3
986 __v = __num_get_unsigned_integral<unsigned int>(__a, __a_end, __err, __base);
987 // Digit grouping checked
988 __check_grouping(__grouping, __g, __g_end, __err);
989 // EOF checked
990 if (__b == __e)
991 __err |= ios_base::eofbit;
992 return __b;
993}
994
995template <class _CharT, class _InputIterator>
996_InputIterator
997num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
998 ios_base& __iob,
999 ios_base::iostate& __err,
1000 unsigned long& __v) const
1001{
1002 // Stage 1
1003 int __base = this->__get_base(__iob);
1004 // Stage 2
1005 char_type __atoms[26];
1006 char_type __thousands_sep;
1007 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
1008 char __a[__num_get_base::__num_get_buf_sz] = {0};
1009 char* __a_end = __a;
1010 unsigned __g[__num_get_base::__num_get_buf_sz];
1011 unsigned* __g_end = __g;
1012 unsigned __dc = 0;
1013 for (; __b != __e; ++__b)
Howard Hinnant3b6579a2010-08-22 00:02:43 +00001014 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001015 __thousands_sep, __grouping, __g, __g_end,
1016 __atoms))
1017 break;
1018 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
1019 *__g_end++ = __dc;
1020 // Stage 3
1021 __v = __num_get_unsigned_integral<unsigned long>(__a, __a_end, __err, __base);
1022 // Digit grouping checked
1023 __check_grouping(__grouping, __g, __g_end, __err);
1024 // EOF checked
1025 if (__b == __e)
1026 __err |= ios_base::eofbit;
1027 return __b;
1028}
1029
1030template <class _CharT, class _InputIterator>
1031_InputIterator
1032num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1033 ios_base& __iob,
1034 ios_base::iostate& __err,
1035 unsigned long long& __v) const
1036{
1037 // Stage 1
1038 int __base = this->__get_base(__iob);
1039 // Stage 2
1040 char_type __atoms[26];
1041 char_type __thousands_sep;
1042 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
1043 char __a[__num_get_base::__num_get_buf_sz] = {0};
1044 char* __a_end = __a;
1045 unsigned __g[__num_get_base::__num_get_buf_sz];
1046 unsigned* __g_end = __g;
1047 unsigned __dc = 0;
1048 for (; __b != __e; ++__b)
Howard Hinnant3b6579a2010-08-22 00:02:43 +00001049 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001050 __thousands_sep, __grouping, __g, __g_end,
1051 __atoms))
1052 break;
1053 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
1054 *__g_end++ = __dc;
1055 // Stage 3
1056 __v = __num_get_unsigned_integral<unsigned long long>(__a, __a_end, __err, __base);
1057 // Digit grouping checked
1058 __check_grouping(__grouping, __g, __g_end, __err);
1059 // EOF checked
1060 if (__b == __e)
1061 __err |= ios_base::eofbit;
1062 return __b;
1063}
1064
1065template <class _CharT, class _InputIterator>
1066_InputIterator
1067num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1068 ios_base& __iob,
1069 ios_base::iostate& __err,
1070 float& __v) const
1071{
1072 // Stage 1, nothing to do
1073 // Stage 2
1074 char_type __atoms[32];
1075 char_type __decimal_point;
1076 char_type __thousands_sep;
Howard Hinnant3b6579a2010-08-22 00:02:43 +00001077 string __grouping = this->__stage2_float_prep(__iob, __atoms,
1078 __decimal_point,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001079 __thousands_sep);
1080 char __a[__num_get_base::__num_get_buf_sz] = {0};
1081 char* __a_end = __a;
1082 unsigned __g[__num_get_base::__num_get_buf_sz];
1083 unsigned* __g_end = __g;
1084 unsigned __dc = 0;
1085 bool __in_units = true;
1086 char __exp = 'E';
1087 for (; __b != __e; ++__b)
Howard Hinnant3b6579a2010-08-22 00:02:43 +00001088 if (this->__stage2_float_loop(*__b, __in_units, __exp, __a, __a_end,
1089 __decimal_point, __thousands_sep,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001090 __grouping, __g, __g_end,
1091 __dc, __atoms))
1092 break;
1093 if (__grouping.size() != 0 && __in_units && __g_end-__g < __num_get_base::__num_get_buf_sz)
1094 *__g_end++ = __dc;
1095 // Stage 3
1096 __v = __num_get_float<float>(__a, __a_end, __err);
1097 // Digit grouping checked
1098 __check_grouping(__grouping, __g, __g_end, __err);
1099 // EOF checked
1100 if (__b == __e)
1101 __err |= ios_base::eofbit;
1102 return __b;
1103}
1104
1105template <class _CharT, class _InputIterator>
1106_InputIterator
1107num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1108 ios_base& __iob,
1109 ios_base::iostate& __err,
1110 double& __v) const
1111{
1112 // Stage 1, nothing to do
1113 // Stage 2
1114 char_type __atoms[32];
1115 char_type __decimal_point;
1116 char_type __thousands_sep;
Howard Hinnant3b6579a2010-08-22 00:02:43 +00001117 string __grouping = this->__stage2_float_prep(__iob, __atoms,
1118 __decimal_point,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001119 __thousands_sep);
1120 char __a[__num_get_base::__num_get_buf_sz] = {0};
1121 char* __a_end = __a;
1122 unsigned __g[__num_get_base::__num_get_buf_sz];
1123 unsigned* __g_end = __g;
1124 unsigned __dc = 0;
1125 bool __in_units = true;
1126 char __exp = 'E';
1127 for (; __b != __e; ++__b)
Howard Hinnant3b6579a2010-08-22 00:02:43 +00001128 if (this->__stage2_float_loop(*__b, __in_units, __exp, __a, __a_end,
1129 __decimal_point, __thousands_sep,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001130 __grouping, __g, __g_end,
1131 __dc, __atoms))
1132 break;
1133 if (__grouping.size() != 0 && __in_units && __g_end-__g < __num_get_base::__num_get_buf_sz)
1134 *__g_end++ = __dc;
1135 // Stage 3
1136 __v = __num_get_float<double>(__a, __a_end, __err);
1137 // Digit grouping checked
1138 __check_grouping(__grouping, __g, __g_end, __err);
1139 // EOF checked
1140 if (__b == __e)
1141 __err |= ios_base::eofbit;
1142 return __b;
1143}
1144
1145template <class _CharT, class _InputIterator>
1146_InputIterator
1147num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1148 ios_base& __iob,
1149 ios_base::iostate& __err,
1150 long double& __v) const
1151{
1152 // Stage 1, nothing to do
1153 // Stage 2
1154 char_type __atoms[32];
1155 char_type __decimal_point;
1156 char_type __thousands_sep;
Howard Hinnant3b6579a2010-08-22 00:02:43 +00001157 string __grouping = this->__stage2_float_prep(__iob, __atoms,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001158 __decimal_point,
1159 __thousands_sep);
1160 char __a[__num_get_base::__num_get_buf_sz] = {0};
1161 char* __a_end = __a;
1162 unsigned __g[__num_get_base::__num_get_buf_sz];
1163 unsigned* __g_end = __g;
1164 unsigned __dc = 0;
1165 bool __in_units = true;
1166 char __exp = 'E';
1167 for (; __b != __e; ++__b)
Howard Hinnant3b6579a2010-08-22 00:02:43 +00001168 if (this->__stage2_float_loop(*__b, __in_units, __exp, __a, __a_end,
1169 __decimal_point, __thousands_sep,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001170 __grouping, __g, __g_end,
1171 __dc, __atoms))
1172 break;
1173 if (__grouping.size() != 0 && __in_units && __g_end-__g < __num_get_base::__num_get_buf_sz)
1174 *__g_end++ = __dc;
1175 // Stage 3
1176 __v = __num_get_float<long double>(__a, __a_end, __err);
1177 // Digit grouping checked
1178 __check_grouping(__grouping, __g, __g_end, __err);
1179 // EOF checked
1180 if (__b == __e)
1181 __err |= ios_base::eofbit;
1182 return __b;
1183}
1184
1185template <class _CharT, class _InputIterator>
1186_InputIterator
1187num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1188 ios_base& __iob,
1189 ios_base::iostate& __err,
1190 void*& __v) const
1191{
1192 // Stage 1
1193 int __base = 16;
1194 // Stage 2
1195 char_type __atoms[26];
1196 char_type __thousands_sep;
1197 string __grouping;
1198 use_facet<ctype<_CharT> >(__iob.getloc()).widen(__num_get_base::__src,
1199 __num_get_base::__src + 26, __atoms);
1200 char __a[__num_get_base::__num_get_buf_sz] = {0};
1201 char* __a_end = __a;
1202 unsigned __g[__num_get_base::__num_get_buf_sz];
1203 unsigned* __g_end = __g;
1204 unsigned __dc = 0;
1205 for (; __b != __e; ++__b)
Howard Hinnant3b6579a2010-08-22 00:02:43 +00001206 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
1207 __thousands_sep, __grouping,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001208 __g, __g_end, __atoms))
1209 break;
1210 // Stage 3
1211 __a[sizeof(__a)-1] = 0;
Howard Hinnant155c2af2010-05-24 17:49:41 +00001212 if (__nolocale_sscanf(__a, "%p", &__v) != 1)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001213 __err = ios_base::failbit;
1214 // EOF checked
1215 if (__b == __e)
1216 __err |= ios_base::eofbit;
1217 return __b;
1218}
1219
1220extern template class num_get<char>;
1221extern template class num_get<wchar_t>;
1222
1223struct __num_put_base
1224{
1225protected:
1226 static void __format_int(char* __fmt, const char* __len, bool __signd,
1227 ios_base::fmtflags __flags);
1228 static bool __format_float(char* __fmt, const char* __len,
1229 ios_base::fmtflags __flags);
1230 static char* __identify_padding(char* __nb, char* __ne,
1231 const ios_base& __iob);
1232};
1233
1234template <class _CharT>
1235struct __num_put
1236 : protected __num_put_base
1237{
1238 static void __widen_and_group_int(char* __nb, char* __np, char* __ne,
1239 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1240 const locale& __loc);
1241 static void __widen_and_group_float(char* __nb, char* __np, char* __ne,
1242 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1243 const locale& __loc);
1244};
1245
1246template <class _CharT>
1247void
1248__num_put<_CharT>::__widen_and_group_int(char* __nb, char* __np, char* __ne,
1249 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1250 const locale& __loc)
1251{
1252 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> > (__loc);
1253 const numpunct<_CharT>& __npt = use_facet<numpunct<_CharT> >(__loc);
1254 string __grouping = __npt.grouping();
1255 if (__grouping.empty())
1256 {
1257 __ct.widen(__nb, __ne, __ob);
1258 __oe = __ob + (__ne - __nb);
1259 }
1260 else
1261 {
1262 __oe = __ob;
1263 char* __nf = __nb;
1264 if (*__nf == '-' || *__nf == '+')
1265 *__oe++ = __ct.widen(*__nf++);
1266 if (__ne - __nf >= 2 && __nf[0] == '0' && (__nf[1] == 'x' ||
1267 __nf[1] == 'X'))
1268 {
1269 *__oe++ = __ct.widen(*__nf++);
1270 *__oe++ = __ct.widen(*__nf++);
1271 }
1272 reverse(__nf, __ne);
1273 _CharT __thousands_sep = __npt.thousands_sep();
1274 unsigned __dc = 0;
1275 unsigned __dg = 0;
1276 for (char* __p = __nf; __p < __ne; ++__p)
1277 {
1278 if (static_cast<unsigned>(__grouping[__dg]) > 0 &&
1279 __dc == static_cast<unsigned>(__grouping[__dg]))
1280 {
1281 *__oe++ = __thousands_sep;
1282 __dc = 0;
1283 if (__dg < __grouping.size()-1)
1284 ++__dg;
1285 }
1286 *__oe++ = __ct.widen(*__p);
1287 ++__dc;
1288 }
1289 reverse(__ob + (__nf - __nb), __oe);
1290 }
1291 if (__np == __ne)
1292 __op = __oe;
1293 else
1294 __op = __ob + (__np - __nb);
1295}
1296
1297template <class _CharT>
1298void
1299__num_put<_CharT>::__widen_and_group_float(char* __nb, char* __np, char* __ne,
1300 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1301 const locale& __loc)
1302{
1303 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> > (__loc);
1304 const numpunct<_CharT>& __npt = use_facet<numpunct<_CharT> >(__loc);
1305 string __grouping = __npt.grouping();
1306 __oe = __ob;
1307 char* __nf = __nb;
1308 if (*__nf == '-' || *__nf == '+')
1309 *__oe++ = __ct.widen(*__nf++);
1310 char* __ns;
1311 if (__ne - __nf >= 2 && __nf[0] == '0' && (__nf[1] == 'x' ||
1312 __nf[1] == 'X'))
1313 {
1314 *__oe++ = __ct.widen(*__nf++);
1315 *__oe++ = __ct.widen(*__nf++);
1316 for (__ns = __nf; __ns < __ne; ++__ns)
Howard Hinnant155c2af2010-05-24 17:49:41 +00001317 if (!__nolocale_isxdigit(*__ns))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001318 break;
1319 }
1320 else
1321 {
1322 for (__ns = __nf; __ns < __ne; ++__ns)
Howard Hinnant155c2af2010-05-24 17:49:41 +00001323 if (!__nolocale_isdigit(*__ns))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001324 break;
1325 }
1326 if (__grouping.empty())
1327 {
1328 __ct.widen(__nf, __ns, __oe);
1329 __oe += __ns - __nf;
1330 }
1331 else
1332 {
1333 reverse(__nf, __ns);
1334 _CharT __thousands_sep = __npt.thousands_sep();
1335 unsigned __dc = 0;
1336 unsigned __dg = 0;
1337 for (char* __p = __nf; __p < __ns; ++__p)
1338 {
1339 if (__grouping[__dg] > 0 && __dc == static_cast<unsigned>(__grouping[__dg]))
1340 {
1341 *__oe++ = __thousands_sep;
1342 __dc = 0;
1343 if (__dg < __grouping.size()-1)
1344 ++__dg;
1345 }
1346 *__oe++ = __ct.widen(*__p);
1347 ++__dc;
1348 }
1349 reverse(__ob + (__nf - __nb), __oe);
1350 }
1351 for (__nf = __ns; __nf < __ne; ++__nf)
1352 {
1353 if (*__nf == '.')
1354 {
1355 *__oe++ = __npt.decimal_point();
1356 ++__nf;
1357 break;
1358 }
1359 else
1360 *__oe++ = __ct.widen(*__nf);
1361 }
1362 __ct.widen(__nf, __ne, __oe);
1363 __oe += __ne - __nf;
1364 if (__np == __ne)
1365 __op = __oe;
1366 else
1367 __op = __ob + (__np - __nb);
1368}
1369
1370extern template class __num_put<char>;
1371extern template class __num_put<wchar_t>;
1372
1373template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant756c69b2010-09-22 16:48:34 +00001374class _LIBCPP_VISIBLE num_put
Howard Hinnantc51e1022010-05-11 19:42:16 +00001375 : public locale::facet,
1376 private __num_put<_CharT>
1377{
1378public:
1379 typedef _CharT char_type;
1380 typedef _OutputIterator iter_type;
1381
1382 _LIBCPP_ALWAYS_INLINE
1383 explicit num_put(size_t __refs = 0)
1384 : locale::facet(__refs) {}
1385
1386 _LIBCPP_ALWAYS_INLINE
1387 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1388 bool __v) const
1389 {
1390 return do_put(__s, __iob, __fl, __v);
1391 }
1392
1393 _LIBCPP_ALWAYS_INLINE
1394 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1395 long __v) const
1396 {
1397 return do_put(__s, __iob, __fl, __v);
1398 }
1399
1400 _LIBCPP_ALWAYS_INLINE
1401 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1402 long long __v) const
1403 {
1404 return do_put(__s, __iob, __fl, __v);
1405 }
1406
1407 _LIBCPP_ALWAYS_INLINE
1408 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1409 unsigned long __v) const
1410 {
1411 return do_put(__s, __iob, __fl, __v);
1412 }
1413
1414 _LIBCPP_ALWAYS_INLINE
1415 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1416 unsigned long long __v) const
1417 {
1418 return do_put(__s, __iob, __fl, __v);
1419 }
1420
1421 _LIBCPP_ALWAYS_INLINE
1422 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1423 double __v) const
1424 {
1425 return do_put(__s, __iob, __fl, __v);
1426 }
1427
1428 _LIBCPP_ALWAYS_INLINE
1429 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1430 long double __v) const
1431 {
1432 return do_put(__s, __iob, __fl, __v);
1433 }
1434
1435 _LIBCPP_ALWAYS_INLINE
1436 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1437 const void* __v) const
1438 {
1439 return do_put(__s, __iob, __fl, __v);
1440 }
1441
1442 static locale::id id;
1443
1444protected:
Howard Hinnant756c69b2010-09-22 16:48:34 +00001445 _LIBCPP_ALWAYS_INLINE
Howard Hinnantc51e1022010-05-11 19:42:16 +00001446 ~num_put() {}
1447
1448 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1449 bool __v) const;
1450 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1451 long __v) const;
1452 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1453 long long __v) const;
1454 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1455 unsigned long) const;
1456 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1457 unsigned long long) const;
1458 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1459 double __v) const;
1460 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1461 long double __v) const;
1462 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1463 const void* __v) const;
1464};
1465
1466template <class _CharT, class _OutputIterator>
1467locale::id
1468num_put<_CharT, _OutputIterator>::id;
1469
1470template <class _CharT, class _OutputIterator>
1471_LIBCPP_HIDDEN
1472_OutputIterator
1473__pad_and_output(_OutputIterator __s,
1474 const _CharT* __ob, const _CharT* __op, const _CharT* __oe,
1475 ios_base& __iob, _CharT __fl)
1476{
1477 streamsize __sz = __oe - __ob;
1478 streamsize __ns = __iob.width();
1479 if (__ns > __sz)
1480 __ns -= __sz;
1481 else
1482 __ns = 0;
1483 for (;__ob < __op; ++__ob, ++__s)
1484 *__s = *__ob;
1485 for (; __ns; --__ns, ++__s)
1486 *__s = __fl;
1487 for (; __ob < __oe; ++__ob, ++__s)
1488 *__s = *__ob;
1489 __iob.width(0);
1490 return __s;
1491}
1492
1493template <class _CharT, class _OutputIterator>
1494_OutputIterator
1495num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1496 char_type __fl, bool __v) const
1497{
1498 if ((__iob.flags() & ios_base::boolalpha) == 0)
1499 return do_put(__s, __iob, __fl, (unsigned long)__v);
1500 const numpunct<char_type>& __np = use_facet<numpunct<char_type> >(__iob.getloc());
1501 typedef typename numpunct<char_type>::string_type string_type;
1502 string_type __nm = __v ? __np.truename() : __np.falsename();
1503 for (typename string_type::iterator __i = __nm.begin(); __i != __nm.end(); ++__i, ++__s)
1504 *__s = *__i;
1505 return __s;
1506}
1507
1508template <class _CharT, class _OutputIterator>
1509_OutputIterator
1510num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1511 char_type __fl, long __v) const
1512{
1513 // Stage 1 - Get number in narrow char
1514 char __fmt[6] = {'%', 0};
1515 const char* __len = "l";
1516 this->__format_int(__fmt+1, __len, true, __iob.flags());
1517 const unsigned __nbuf = (numeric_limits<long>::digits / 3)
1518 + ((numeric_limits<long>::digits % 3) != 0)
1519 + 1;
1520 char __nar[__nbuf];
Howard Hinnant155c2af2010-05-24 17:49:41 +00001521 int __nc = __nolocale_sprintf(__nar, __fmt, __v);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001522 char* __ne = __nar + __nc;
1523 char* __np = this->__identify_padding(__nar, __ne, __iob);
1524 // Stage 2 - Widen __nar while adding thousands separators
1525 char_type __o[2*(__nbuf-1) - 1];
1526 char_type* __op; // pad here
1527 char_type* __oe; // end of output
1528 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1529 // [__o, __oe) contains thousands_sep'd wide number
1530 // Stage 3 & 4
1531 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1532}
1533
1534template <class _CharT, class _OutputIterator>
1535_OutputIterator
1536num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1537 char_type __fl, long long __v) const
1538{
1539 // Stage 1 - Get number in narrow char
1540 char __fmt[8] = {'%', 0};
1541 const char* __len = "ll";
1542 this->__format_int(__fmt+1, __len, true, __iob.flags());
1543 const unsigned __nbuf = (numeric_limits<long long>::digits / 3)
1544 + ((numeric_limits<long long>::digits % 3) != 0)
1545 + 1;
1546 char __nar[__nbuf];
Howard Hinnant155c2af2010-05-24 17:49:41 +00001547 int __nc = __nolocale_sprintf(__nar, __fmt, __v);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001548 char* __ne = __nar + __nc;
1549 char* __np = this->__identify_padding(__nar, __ne, __iob);
1550 // Stage 2 - Widen __nar while adding thousands separators
1551 char_type __o[2*(__nbuf-1) - 1];
1552 char_type* __op; // pad here
1553 char_type* __oe; // end of output
1554 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1555 // [__o, __oe) contains thousands_sep'd wide number
1556 // Stage 3 & 4
1557 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1558}
1559
1560template <class _CharT, class _OutputIterator>
1561_OutputIterator
1562num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1563 char_type __fl, unsigned long __v) const
1564{
1565 // Stage 1 - Get number in narrow char
1566 char __fmt[6] = {'%', 0};
1567 const char* __len = "l";
1568 this->__format_int(__fmt+1, __len, false, __iob.flags());
1569 const unsigned __nbuf = (numeric_limits<unsigned long>::digits / 3)
1570 + ((numeric_limits<unsigned long>::digits % 3) != 0)
1571 + 1;
1572 char __nar[__nbuf];
Howard Hinnant155c2af2010-05-24 17:49:41 +00001573 int __nc = __nolocale_sprintf(__nar, __fmt, __v);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001574 char* __ne = __nar + __nc;
1575 char* __np = this->__identify_padding(__nar, __ne, __iob);
1576 // Stage 2 - Widen __nar while adding thousands separators
1577 char_type __o[2*(__nbuf-1) - 1];
1578 char_type* __op; // pad here
1579 char_type* __oe; // end of output
1580 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1581 // [__o, __oe) contains thousands_sep'd wide number
1582 // Stage 3 & 4
1583 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1584}
1585
1586template <class _CharT, class _OutputIterator>
1587_OutputIterator
1588num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1589 char_type __fl, unsigned long long __v) const
1590{
1591 // Stage 1 - Get number in narrow char
1592 char __fmt[8] = {'%', 0};
1593 const char* __len = "ll";
1594 this->__format_int(__fmt+1, __len, false, __iob.flags());
1595 const unsigned __nbuf = (numeric_limits<unsigned long long>::digits / 3)
1596 + ((numeric_limits<unsigned long long>::digits % 3) != 0)
1597 + 1;
1598 char __nar[__nbuf];
Howard Hinnant155c2af2010-05-24 17:49:41 +00001599 int __nc = __nolocale_sprintf(__nar, __fmt, __v);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001600 char* __ne = __nar + __nc;
1601 char* __np = this->__identify_padding(__nar, __ne, __iob);
1602 // Stage 2 - Widen __nar while adding thousands separators
1603 char_type __o[2*(__nbuf-1) - 1];
1604 char_type* __op; // pad here
1605 char_type* __oe; // end of output
1606 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1607 // [__o, __oe) contains thousands_sep'd wide number
1608 // Stage 3 & 4
1609 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1610}
1611
1612template <class _CharT, class _OutputIterator>
1613_OutputIterator
1614num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1615 char_type __fl, double __v) const
1616{
1617 // Stage 1 - Get number in narrow char
1618 char __fmt[8] = {'%', 0};
1619 const char* __len = "";
1620 bool __specify_precision = this->__format_float(__fmt+1, __len, __iob.flags());
1621 const unsigned __nbuf = 30;
1622 char __nar[__nbuf];
1623 char* __nb = __nar;
1624 int __nc;
1625 if (__specify_precision)
Howard Hinnant155c2af2010-05-24 17:49:41 +00001626 __nc = __nolocale_snprintf(__nb, __nbuf, __fmt,
1627 (int)__iob.precision(), __v);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001628 else
Howard Hinnant155c2af2010-05-24 17:49:41 +00001629 __nc = __nolocale_snprintf(__nb, __nbuf, __fmt, __v);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001630 unique_ptr<char, void(*)(void*)> __nbh(0, free);
1631 if (__nc > static_cast<int>(__nbuf-1))
1632 {
1633 if (__specify_precision)
Howard Hinnant155c2af2010-05-24 17:49:41 +00001634 __nc = __nolocale_asprintf(&__nb, __fmt, (int)__iob.precision(),
1635 __v);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001636 else
Howard Hinnant155c2af2010-05-24 17:49:41 +00001637 __nc = __nolocale_asprintf(&__nb, __fmt, __v);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001638 if (__nb == 0)
1639 __throw_bad_alloc();
1640 __nbh.reset(__nb);
1641 }
1642 char* __ne = __nb + __nc;
1643 char* __np = this->__identify_padding(__nb, __ne, __iob);
1644 // Stage 2 - Widen __nar while adding thousands separators
1645 char_type __o[2*(__nbuf-1) - 1];
1646 char_type* __ob = __o;
1647 unique_ptr<char_type, void(*)(void*)> __obh(0, free);
1648 if (__nb != __nar)
1649 {
1650 __ob = (char_type*)malloc((2*__nc)*sizeof(char_type));
1651 if (__ob == 0)
1652 __throw_bad_alloc();
1653 __obh.reset(__ob);
1654 }
1655 char_type* __op; // pad here
1656 char_type* __oe; // end of output
1657 this->__widen_and_group_float(__nb, __np, __ne, __ob, __op, __oe, __iob.getloc());
1658 // [__o, __oe) contains thousands_sep'd wide number
1659 // Stage 3 & 4
1660 __s = __pad_and_output(__s, __ob, __op, __oe, __iob, __fl);
1661 return __s;
1662}
1663
1664template <class _CharT, class _OutputIterator>
1665_OutputIterator
1666num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1667 char_type __fl, long double __v) const
1668{
1669 // Stage 1 - Get number in narrow char
1670 char __fmt[8] = {'%', 0};
1671 const char* __len = "L";
1672 bool __specify_precision = this->__format_float(__fmt+1, __len, __iob.flags());
1673 const unsigned __nbuf = 30;
1674 char __nar[__nbuf];
1675 char* __nb = __nar;
1676 int __nc;
1677 if (__specify_precision)
Howard Hinnant155c2af2010-05-24 17:49:41 +00001678 __nc = __nolocale_snprintf(__nb, __nbuf, __fmt,
1679 (int)__iob.precision(), __v);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001680 else
Howard Hinnant155c2af2010-05-24 17:49:41 +00001681 __nc = __nolocale_snprintf(__nb, __nbuf, __fmt, __v);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001682 unique_ptr<char, void(*)(void*)> __nbh(0, free);
1683 if (__nc > static_cast<int>(__nbuf-1))
1684 {
1685 if (__specify_precision)
Howard Hinnant155c2af2010-05-24 17:49:41 +00001686 __nc = __nolocale_asprintf(&__nb, __fmt, (int)__iob.precision(),
1687 __v);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001688 else
Howard Hinnant155c2af2010-05-24 17:49:41 +00001689 __nc = __nolocale_asprintf(&__nb, __fmt, __v);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001690 if (__nb == 0)
1691 __throw_bad_alloc();
1692 __nbh.reset(__nb);
1693 }
1694 char* __ne = __nb + __nc;
1695 char* __np = this->__identify_padding(__nb, __ne, __iob);
1696 // Stage 2 - Widen __nar while adding thousands separators
1697 char_type __o[2*(__nbuf-1) - 1];
1698 char_type* __ob = __o;
1699 unique_ptr<char_type, void(*)(void*)> __obh(0, free);
1700 if (__nb != __nar)
1701 {
1702 __ob = (char_type*)malloc((2*__nc)*sizeof(char_type));
1703 if (__ob == 0)
1704 __throw_bad_alloc();
1705 __obh.reset(__ob);
1706 }
1707 char_type* __op; // pad here
1708 char_type* __oe; // end of output
1709 this->__widen_and_group_float(__nb, __np, __ne, __ob, __op, __oe, __iob.getloc());
1710 // [__o, __oe) contains thousands_sep'd wide number
1711 // Stage 3 & 4
1712 __s = __pad_and_output(__s, __ob, __op, __oe, __iob, __fl);
1713 return __s;
1714}
1715
1716template <class _CharT, class _OutputIterator>
1717_OutputIterator
1718num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1719 char_type __fl, const void* __v) const
1720{
1721 // Stage 1 - Get pointer in narrow char
1722 char __fmt[6] = "%p";
1723 const unsigned __nbuf = 20;
1724 char __nar[__nbuf];
Howard Hinnant155c2af2010-05-24 17:49:41 +00001725 int __nc = __nolocale_sprintf(__nar, __fmt, __v);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001726 char* __ne = __nar + __nc;
1727 char* __np = this->__identify_padding(__nar, __ne, __iob);
1728 // Stage 2 - Widen __nar
1729 char_type __o[2*(__nbuf-1) - 1];
1730 char_type* __op; // pad here
1731 char_type* __oe; // end of output
1732 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
1733 __ct.widen(__nar, __ne, __o);
1734 __oe = __o + (__ne - __nar);
1735 if (__np == __ne)
1736 __op = __oe;
1737 else
1738 __op = __o + (__np - __nar);
1739 // [__o, __oe) contains wide number
1740 // Stage 3 & 4
1741 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1742}
1743
1744extern template class num_put<char>;
1745extern template class num_put<wchar_t>;
1746
1747template <class _CharT, class _InputIterator>
1748_LIBCPP_HIDDEN
1749int
1750__get_up_to_n_digits(_InputIterator& __b, _InputIterator __e,
1751 ios_base::iostate& __err, const ctype<_CharT>& __ct, int __n)
1752{
1753 // Precondition: __n >= 1
1754 if (__b == __e)
1755 {
1756 __err |= ios_base::eofbit | ios_base::failbit;
1757 return 0;
1758 }
1759 // get first digit
1760 _CharT __c = *__b;
1761 if (!__ct.is(ctype_base::digit, __c))
1762 {
1763 __err |= ios_base::failbit;
1764 return 0;
1765 }
1766 int __r = __ct.narrow(__c, 0) - '0';
1767 for (++__b, --__n; __b != __e && __n > 0; ++__b, --__n)
1768 {
1769 // get next digit
1770 __c = *__b;
1771 if (!__ct.is(ctype_base::digit, __c))
1772 return __r;
1773 __r = __r * 10 + __ct.narrow(__c, 0) - '0';
1774 }
1775 if (__b == __e)
1776 __err |= ios_base::eofbit;
1777 return __r;
1778}
1779
Howard Hinnant756c69b2010-09-22 16:48:34 +00001780class _LIBCPP_VISIBLE time_base
Howard Hinnantc51e1022010-05-11 19:42:16 +00001781{
1782public:
1783 enum dateorder {no_order, dmy, mdy, ymd, ydm};
1784};
1785
1786template <class _CharT>
Howard Hinnantcf823322010-12-17 14:46:43 +00001787class __time_get_c_storage // purposefully not decorated
Howard Hinnantc51e1022010-05-11 19:42:16 +00001788{
1789protected:
1790 typedef basic_string<_CharT> string_type;
1791
1792 virtual const string_type* __weeks() const;
1793 virtual const string_type* __months() const;
1794 virtual const string_type* __am_pm() const;
1795 virtual const string_type& __c() const;
1796 virtual const string_type& __r() const;
1797 virtual const string_type& __x() const;
1798 virtual const string_type& __X() const;
1799};
1800
1801template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnant756c69b2010-09-22 16:48:34 +00001802class _LIBCPP_VISIBLE time_get
Howard Hinnantc51e1022010-05-11 19:42:16 +00001803 : public locale::facet,
1804 public time_base,
1805 private __time_get_c_storage<_CharT>
1806{
1807public:
1808 typedef _CharT char_type;
1809 typedef _InputIterator iter_type;
1810 typedef time_base::dateorder dateorder;
1811 typedef basic_string<char_type> string_type;
1812
1813 _LIBCPP_ALWAYS_INLINE
1814 explicit time_get(size_t __refs = 0)
1815 : locale::facet(__refs) {}
1816
1817 _LIBCPP_ALWAYS_INLINE
1818 dateorder date_order() const
1819 {
1820 return this->do_date_order();
1821 }
1822
1823 _LIBCPP_ALWAYS_INLINE
1824 iter_type get_time(iter_type __b, iter_type __e, ios_base& __iob,
1825 ios_base::iostate& __err, tm* __tm) const
1826 {
1827 return do_get_time(__b, __e, __iob, __err, __tm);
1828 }
1829
1830 _LIBCPP_ALWAYS_INLINE
1831 iter_type get_date(iter_type __b, iter_type __e, ios_base& __iob,
1832 ios_base::iostate& __err, tm* __tm) const
1833 {
1834 return do_get_date(__b, __e, __iob, __err, __tm);
1835 }
1836
1837 _LIBCPP_ALWAYS_INLINE
1838 iter_type get_weekday(iter_type __b, iter_type __e, ios_base& __iob,
1839 ios_base::iostate& __err, tm* __tm) const
1840 {
1841 return do_get_weekday(__b, __e, __iob, __err, __tm);
1842 }
1843
1844 _LIBCPP_ALWAYS_INLINE
1845 iter_type get_monthname(iter_type __b, iter_type __e, ios_base& __iob,
1846 ios_base::iostate& __err, tm* __tm) const
1847 {
1848 return do_get_monthname(__b, __e, __iob, __err, __tm);
1849 }
1850
1851 _LIBCPP_ALWAYS_INLINE
1852 iter_type get_year(iter_type __b, iter_type __e, ios_base& __iob,
1853 ios_base::iostate& __err, tm* __tm) const
1854 {
1855 return do_get_year(__b, __e, __iob, __err, __tm);
1856 }
1857
1858 _LIBCPP_ALWAYS_INLINE
1859 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
1860 ios_base::iostate& __err, tm *__tm,
1861 char __fmt, char __mod = 0) const
1862 {
1863 return do_get(__b, __e, __iob, __err, __tm, __fmt, __mod);
1864 }
1865
1866 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
1867 ios_base::iostate& __err, tm* __tm,
1868 const char_type* __fmtb, const char_type* __fmte) const;
1869
1870 static locale::id id;
1871
1872protected:
Howard Hinnant756c69b2010-09-22 16:48:34 +00001873 _LIBCPP_ALWAYS_INLINE
Howard Hinnantc51e1022010-05-11 19:42:16 +00001874 ~time_get() {}
1875
1876 virtual dateorder do_date_order() const;
1877 virtual iter_type do_get_time(iter_type __b, iter_type __e, ios_base& __iob,
1878 ios_base::iostate& __err, tm* __tm) const;
1879 virtual iter_type do_get_date(iter_type __b, iter_type __e, ios_base& __iob,
1880 ios_base::iostate& __err, tm* __tm) const;
1881 virtual iter_type do_get_weekday(iter_type __b, iter_type __e, ios_base& __iob,
1882 ios_base::iostate& __err, tm* __tm) const;
1883 virtual iter_type do_get_monthname(iter_type __b, iter_type __e, ios_base& __iob,
1884 ios_base::iostate& __err, tm* __tm) const;
1885 virtual iter_type do_get_year(iter_type __b, iter_type __e, ios_base& __iob,
1886 ios_base::iostate& __err, tm* __tm) const;
1887 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
1888 ios_base::iostate& __err, tm* __tm,
1889 char __fmt, char __mod) const;
1890private:
1891 void __get_white_space(iter_type& __b, iter_type __e,
1892 ios_base::iostate& __err, const ctype<char_type>& __ct) const;
1893 void __get_percent(iter_type& __b, iter_type __e, ios_base::iostate& __err,
1894 const ctype<char_type>& __ct) const;
1895
1896 void __get_weekdayname(int& __m,
1897 iter_type& __b, iter_type __e,
1898 ios_base::iostate& __err,
1899 const ctype<char_type>& __ct) const;
1900 void __get_monthname(int& __m,
1901 iter_type& __b, iter_type __e,
1902 ios_base::iostate& __err,
1903 const ctype<char_type>& __ct) const;
1904 void __get_day(int& __d,
1905 iter_type& __b, iter_type __e,
1906 ios_base::iostate& __err,
1907 const ctype<char_type>& __ct) const;
1908 void __get_month(int& __m,
1909 iter_type& __b, iter_type __e,
1910 ios_base::iostate& __err,
1911 const ctype<char_type>& __ct) const;
1912 void __get_year(int& __y,
1913 iter_type& __b, iter_type __e,
1914 ios_base::iostate& __err,
1915 const ctype<char_type>& __ct) const;
1916 void __get_year4(int& __y,
1917 iter_type& __b, iter_type __e,
1918 ios_base::iostate& __err,
1919 const ctype<char_type>& __ct) const;
1920 void __get_hour(int& __d,
1921 iter_type& __b, iter_type __e,
1922 ios_base::iostate& __err,
1923 const ctype<char_type>& __ct) const;
1924 void __get_12_hour(int& __h,
1925 iter_type& __b, iter_type __e,
1926 ios_base::iostate& __err,
1927 const ctype<char_type>& __ct) const;
1928 void __get_am_pm(int& __h,
1929 iter_type& __b, iter_type __e,
1930 ios_base::iostate& __err,
1931 const ctype<char_type>& __ct) const;
1932 void __get_minute(int& __m,
1933 iter_type& __b, iter_type __e,
1934 ios_base::iostate& __err,
1935 const ctype<char_type>& __ct) const;
1936 void __get_second(int& __s,
1937 iter_type& __b, iter_type __e,
1938 ios_base::iostate& __err,
1939 const ctype<char_type>& __ct) const;
1940 void __get_weekday(int& __w,
1941 iter_type& __b, iter_type __e,
1942 ios_base::iostate& __err,
1943 const ctype<char_type>& __ct) const;
1944 void __get_day_year_num(int& __w,
1945 iter_type& __b, iter_type __e,
1946 ios_base::iostate& __err,
1947 const ctype<char_type>& __ct) const;
1948};
1949
1950template <class _CharT, class _InputIterator>
1951locale::id
1952time_get<_CharT, _InputIterator>::id;
1953
1954// time_get primatives
1955
1956template <class _CharT, class _InputIterator>
1957void
1958time_get<_CharT, _InputIterator>::__get_weekdayname(int& __w,
1959 iter_type& __b, iter_type __e,
1960 ios_base::iostate& __err,
1961 const ctype<char_type>& __ct) const
1962{
1963 // Note: ignoring case comes from the POSIX strptime spec
1964 const string_type* __wk = this->__weeks();
1965 int __i = __scan_keyword(__b, __e, __wk, __wk+14, __ct, __err, false) - __wk;
1966 if (__i < 14)
1967 __w = __i % 7;
1968}
1969
1970template <class _CharT, class _InputIterator>
1971void
1972time_get<_CharT, _InputIterator>::__get_monthname(int& __m,
1973 iter_type& __b, iter_type __e,
1974 ios_base::iostate& __err,
1975 const ctype<char_type>& __ct) const
1976{
1977 // Note: ignoring case comes from the POSIX strptime spec
1978 const string_type* __month = this->__months();
1979 int __i = __scan_keyword(__b, __e, __month, __month+24, __ct, __err, false) - __month;
1980 if (__i < 24)
1981 __m = __i % 12;
1982}
1983
1984template <class _CharT, class _InputIterator>
1985void
1986time_get<_CharT, _InputIterator>::__get_day(int& __d,
1987 iter_type& __b, iter_type __e,
1988 ios_base::iostate& __err,
1989 const ctype<char_type>& __ct) const
1990{
1991 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
1992 if (!(__err & ios_base::failbit) && 1 <= __t && __t <= 31)
1993 __d = __t;
1994 else
1995 __err |= ios_base::failbit;
1996}
1997
1998template <class _CharT, class _InputIterator>
1999void
2000time_get<_CharT, _InputIterator>::__get_month(int& __m,
2001 iter_type& __b, iter_type __e,
2002 ios_base::iostate& __err,
2003 const ctype<char_type>& __ct) const
2004{
2005 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2) - 1;
2006 if (!(__err & ios_base::failbit) && __t <= 11)
2007 __m = __t;
2008 else
2009 __err |= ios_base::failbit;
2010}
2011
2012template <class _CharT, class _InputIterator>
2013void
2014time_get<_CharT, _InputIterator>::__get_year(int& __y,
2015 iter_type& __b, iter_type __e,
2016 ios_base::iostate& __err,
2017 const ctype<char_type>& __ct) const
2018{
2019 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 4);
2020 if (!(__err & ios_base::failbit))
2021 {
2022 if (__t < 69)
2023 __t += 2000;
2024 else if (69 <= __t && __t <= 99)
2025 __t += 1900;
2026 __y = __t - 1900;
2027 }
2028}
2029
2030template <class _CharT, class _InputIterator>
2031void
2032time_get<_CharT, _InputIterator>::__get_year4(int& __y,
2033 iter_type& __b, iter_type __e,
2034 ios_base::iostate& __err,
2035 const ctype<char_type>& __ct) const
2036{
2037 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 4);
2038 if (!(__err & ios_base::failbit))
2039 __y = __t - 1900;
2040}
2041
2042template <class _CharT, class _InputIterator>
2043void
2044time_get<_CharT, _InputIterator>::__get_hour(int& __h,
2045 iter_type& __b, iter_type __e,
2046 ios_base::iostate& __err,
2047 const ctype<char_type>& __ct) const
2048{
2049 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2050 if (!(__err & ios_base::failbit) && __t <= 23)
2051 __h = __t;
2052 else
2053 __err |= ios_base::failbit;
2054}
2055
2056template <class _CharT, class _InputIterator>
2057void
2058time_get<_CharT, _InputIterator>::__get_12_hour(int& __h,
2059 iter_type& __b, iter_type __e,
2060 ios_base::iostate& __err,
2061 const ctype<char_type>& __ct) const
2062{
2063 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2064 if (!(__err & ios_base::failbit) && 1 <= __t && __t <= 12)
2065 __h = __t;
2066 else
2067 __err |= ios_base::failbit;
2068}
2069
2070template <class _CharT, class _InputIterator>
2071void
2072time_get<_CharT, _InputIterator>::__get_minute(int& __m,
2073 iter_type& __b, iter_type __e,
2074 ios_base::iostate& __err,
2075 const ctype<char_type>& __ct) const
2076{
2077 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2078 if (!(__err & ios_base::failbit) && __t <= 59)
2079 __m = __t;
2080 else
2081 __err |= ios_base::failbit;
2082}
2083
2084template <class _CharT, class _InputIterator>
2085void
2086time_get<_CharT, _InputIterator>::__get_second(int& __s,
2087 iter_type& __b, iter_type __e,
2088 ios_base::iostate& __err,
2089 const ctype<char_type>& __ct) const
2090{
2091 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2092 if (!(__err & ios_base::failbit) && __t <= 60)
2093 __s = __t;
2094 else
2095 __err |= ios_base::failbit;
2096}
2097
2098template <class _CharT, class _InputIterator>
2099void
2100time_get<_CharT, _InputIterator>::__get_weekday(int& __w,
2101 iter_type& __b, iter_type __e,
2102 ios_base::iostate& __err,
2103 const ctype<char_type>& __ct) const
2104{
2105 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 1);
2106 if (!(__err & ios_base::failbit) && __t <= 6)
2107 __w = __t;
2108 else
2109 __err |= ios_base::failbit;
2110}
2111
2112template <class _CharT, class _InputIterator>
2113void
2114time_get<_CharT, _InputIterator>::__get_day_year_num(int& __d,
2115 iter_type& __b, iter_type __e,
2116 ios_base::iostate& __err,
2117 const ctype<char_type>& __ct) const
2118{
2119 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 3);
2120 if (!(__err & ios_base::failbit) && __t <= 365)
2121 __d = __t;
2122 else
2123 __err |= ios_base::failbit;
2124}
2125
2126template <class _CharT, class _InputIterator>
2127void
2128time_get<_CharT, _InputIterator>::__get_white_space(iter_type& __b, iter_type __e,
2129 ios_base::iostate& __err,
2130 const ctype<char_type>& __ct) const
2131{
2132 for (; __b != __e && __ct.is(ctype_base::space, *__b); ++__b)
2133 ;
2134 if (__b == __e)
2135 __err |= ios_base::eofbit;
2136}
2137
2138template <class _CharT, class _InputIterator>
2139void
2140time_get<_CharT, _InputIterator>::__get_am_pm(int& __h,
2141 iter_type& __b, iter_type __e,
2142 ios_base::iostate& __err,
2143 const ctype<char_type>& __ct) const
2144{
2145 const string_type* __ap = this->__am_pm();
2146 if (__ap[0].size() + __ap[1].size() == 0)
2147 {
2148 __err |= ios_base::failbit;
2149 return;
2150 }
2151 int __i = __scan_keyword(__b, __e, __ap, __ap+2, __ct, __err, false) - __ap;
2152 if (__i == 0 && __h == 12)
2153 __h = 0;
2154 else if (__i == 1 && __h < 12)
2155 __h += 12;
2156}
2157
2158template <class _CharT, class _InputIterator>
2159void
2160time_get<_CharT, _InputIterator>::__get_percent(iter_type& __b, iter_type __e,
2161 ios_base::iostate& __err,
2162 const ctype<char_type>& __ct) const
2163{
2164 if (__b == __e)
2165 {
2166 __err |= ios_base::eofbit | ios_base::failbit;
2167 return;
2168 }
2169 if (__ct.narrow(*__b, 0) != '%')
2170 __err |= ios_base::failbit;
2171 else if(++__b == __e)
2172 __err |= ios_base::eofbit;
2173}
2174
2175// time_get end primatives
2176
2177template <class _CharT, class _InputIterator>
2178_InputIterator
2179time_get<_CharT, _InputIterator>::get(iter_type __b, iter_type __e,
2180 ios_base& __iob,
2181 ios_base::iostate& __err, tm* __tm,
2182 const char_type* __fmtb, const char_type* __fmte) const
2183{
2184 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2185 __err = ios_base::goodbit;
2186 while (__fmtb != __fmte && __err == ios_base::goodbit)
2187 {
2188 if (__b == __e)
2189 {
2190 __err = ios_base::failbit;
2191 break;
2192 }
2193 if (__ct.narrow(*__fmtb, 0) == '%')
2194 {
2195 if (++__fmtb == __fmte)
2196 {
2197 __err = ios_base::failbit;
2198 break;
2199 }
2200 char __cmd = __ct.narrow(*__fmtb, 0);
2201 char __opt = '\0';
2202 if (__cmd == 'E' || __cmd == '0')
2203 {
2204 if (++__fmtb == __fmte)
2205 {
2206 __err = ios_base::failbit;
2207 break;
2208 }
2209 __opt = __cmd;
2210 __cmd = __ct.narrow(*__fmtb, 0);
2211 }
2212 __b = do_get(__b, __e, __iob, __err, __tm, __cmd, __opt);
2213 ++__fmtb;
2214 }
2215 else if (__ct.is(ctype_base::space, *__fmtb))
2216 {
2217 for (++__fmtb; __fmtb != __fmte && __ct.is(ctype_base::space, *__fmtb); ++__fmtb)
2218 ;
2219 for ( ; __b != __e && __ct.is(ctype_base::space, *__b); ++__b)
2220 ;
2221 }
2222 else if (__ct.toupper(*__b) == __ct.toupper(*__fmtb))
2223 {
2224 ++__b;
2225 ++__fmtb;
2226 }
2227 else
2228 __err = ios_base::failbit;
2229 }
2230 if (__b == __e)
2231 __err |= ios_base::eofbit;
2232 return __b;
2233}
2234
2235template <class _CharT, class _InputIterator>
2236typename time_get<_CharT, _InputIterator>::dateorder
2237time_get<_CharT, _InputIterator>::do_date_order() const
2238{
2239 return mdy;
2240}
2241
2242template <class _CharT, class _InputIterator>
2243_InputIterator
2244time_get<_CharT, _InputIterator>::do_get_time(iter_type __b, iter_type __e,
2245 ios_base& __iob,
2246 ios_base::iostate& __err,
2247 tm* __tm) const
2248{
2249 const char_type __fmt[] = {'%', 'H', ':', '%', 'M', ':', '%', 'S'};
2250 return get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2251}
2252
2253template <class _CharT, class _InputIterator>
2254_InputIterator
2255time_get<_CharT, _InputIterator>::do_get_date(iter_type __b, iter_type __e,
2256 ios_base& __iob,
2257 ios_base::iostate& __err,
2258 tm* __tm) const
2259{
2260 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2261 const string_type& __fmt = this->__x();
2262 return get(__b, __e, __iob, __err, __tm, __fmt.data(), __fmt.data() + __fmt.size());
2263}
2264
2265template <class _CharT, class _InputIterator>
2266_InputIterator
2267time_get<_CharT, _InputIterator>::do_get_weekday(iter_type __b, iter_type __e,
2268 ios_base& __iob,
2269 ios_base::iostate& __err,
2270 tm* __tm) const
2271{
2272 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2273 __get_weekdayname(__tm->tm_wday, __b, __e, __err, __ct);
2274 return __b;
2275}
2276
2277template <class _CharT, class _InputIterator>
2278_InputIterator
2279time_get<_CharT, _InputIterator>::do_get_monthname(iter_type __b, iter_type __e,
2280 ios_base& __iob,
2281 ios_base::iostate& __err,
2282 tm* __tm) const
2283{
2284 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2285 __get_monthname(__tm->tm_mon, __b, __e, __err, __ct);
2286 return __b;
2287}
2288
2289template <class _CharT, class _InputIterator>
2290_InputIterator
2291time_get<_CharT, _InputIterator>::do_get_year(iter_type __b, iter_type __e,
2292 ios_base& __iob,
2293 ios_base::iostate& __err,
2294 tm* __tm) const
2295{
2296 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2297 __get_year(__tm->tm_year, __b, __e, __err, __ct);
2298 return __b;
2299}
2300
2301template <class _CharT, class _InputIterator>
2302_InputIterator
2303time_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
2304 ios_base& __iob,
2305 ios_base::iostate& __err, tm* __tm,
2306 char __fmt, char) const
2307{
2308 __err = ios_base::goodbit;
2309 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2310 switch (__fmt)
2311 {
2312 case 'a':
2313 case 'A':
2314 __get_weekdayname(__tm->tm_wday, __b, __e, __err, __ct);
2315 break;
2316 case 'b':
2317 case 'B':
2318 case 'h':
2319 __get_monthname(__tm->tm_mon, __b, __e, __err, __ct);
2320 break;
2321 case 'c':
2322 {
2323 const string_type& __fmt = this->__c();
2324 __b = get(__b, __e, __iob, __err, __tm, __fmt.data(), __fmt.data() + __fmt.size());
2325 }
2326 break;
2327 case 'd':
2328 case 'e':
2329 __get_day(__tm->tm_mday, __b, __e, __err, __ct);
2330 break;
2331 case 'D':
2332 {
2333 const char_type __fmt[] = {'%', 'm', '/', '%', 'd', '/', '%', 'y'};
2334 __b = get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2335 }
2336 break;
2337 case 'H':
2338 __get_hour(__tm->tm_hour, __b, __e, __err, __ct);
2339 break;
2340 case 'I':
2341 __get_12_hour(__tm->tm_hour, __b, __e, __err, __ct);
2342 break;
2343 case 'j':
2344 __get_day_year_num(__tm->tm_yday, __b, __e, __err, __ct);
2345 break;
2346 case 'm':
2347 __get_month(__tm->tm_mon, __b, __e, __err, __ct);
2348 break;
2349 case 'M':
2350 __get_minute(__tm->tm_min, __b, __e, __err, __ct);
2351 break;
2352 case 'n':
2353 case 't':
2354 __get_white_space(__b, __e, __err, __ct);
2355 break;
2356 case 'p':
2357 __get_am_pm(__tm->tm_hour, __b, __e, __err, __ct);
2358 break;
2359 case 'r':
2360 {
2361 const char_type __fmt[] = {'%', 'I', ':', '%', 'M', ':', '%', 'S', ' ', '%', 'p'};
2362 __b = get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2363 }
2364 break;
2365 case 'R':
2366 {
2367 const char_type __fmt[] = {'%', 'H', ':', '%', 'M'};
2368 __b = get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2369 }
2370 break;
2371 case 'S':
2372 __get_second(__tm->tm_sec, __b, __e, __err, __ct);
2373 break;
2374 case 'T':
2375 {
2376 const char_type __fmt[] = {'%', 'H', ':', '%', 'M', ':', '%', 'S'};
2377 __b = get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2378 }
2379 break;
2380 case 'w':
2381 __get_weekday(__tm->tm_wday, __b, __e, __err, __ct);
2382 break;
2383 case 'x':
2384 return do_get_date(__b, __e, __iob, __err, __tm);
2385 case 'X':
2386 {
2387 const string_type& __fmt = this->__X();
2388 __b = get(__b, __e, __iob, __err, __tm, __fmt.data(), __fmt.data() + __fmt.size());
2389 }
2390 break;
2391 case 'y':
2392 __get_year(__tm->tm_year, __b, __e, __err, __ct);
2393 break;
2394 case 'Y':
2395 __get_year4(__tm->tm_year, __b, __e, __err, __ct);
2396 break;
2397 case '%':
2398 __get_percent(__b, __e, __err, __ct);
2399 break;
2400 default:
2401 __err |= ios_base::failbit;
2402 }
2403 return __b;
2404}
2405
2406extern template class time_get<char>;
2407extern template class time_get<wchar_t>;
2408
2409class __time_get
2410{
2411protected:
2412 locale_t __loc_;
2413
2414 __time_get(const char* __nm);
2415 __time_get(const string& __nm);
2416 ~__time_get();
2417};
2418
2419template <class _CharT>
2420class __time_get_storage
2421 : public __time_get
2422{
2423protected:
2424 typedef basic_string<_CharT> string_type;
2425
2426 string_type __weeks_[14];
2427 string_type __months_[24];
2428 string_type __am_pm_[2];
2429 string_type __c_;
2430 string_type __r_;
2431 string_type __x_;
2432 string_type __X_;
2433
2434 explicit __time_get_storage(const char* __nm);
2435 explicit __time_get_storage(const string& __nm);
2436
2437 _LIBCPP_ALWAYS_INLINE ~__time_get_storage() {}
2438
2439 time_base::dateorder __do_date_order() const;
2440
2441private:
2442 void init(const ctype<_CharT>&);
2443 string_type __analyze(char __fmt, const ctype<_CharT>&);
2444};
2445
2446template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnant756c69b2010-09-22 16:48:34 +00002447class _LIBCPP_VISIBLE time_get_byname
Howard Hinnantc51e1022010-05-11 19:42:16 +00002448 : public time_get<_CharT, _InputIterator>,
2449 private __time_get_storage<_CharT>
2450{
2451public:
2452 typedef time_base::dateorder dateorder;
2453 typedef _InputIterator iter_type;
2454 typedef _CharT char_type;
2455 typedef basic_string<char_type> string_type;
2456
Howard Hinnant756c69b2010-09-22 16:48:34 +00002457 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002458 explicit time_get_byname(const char* __nm, size_t __refs = 0)
2459 : time_get<_CharT, _InputIterator>(__refs),
2460 __time_get_storage<_CharT>(__nm) {}
Howard Hinnant756c69b2010-09-22 16:48:34 +00002461 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002462 explicit time_get_byname(const string& __nm, size_t __refs = 0)
2463 : time_get<_CharT, _InputIterator>(__refs),
2464 __time_get_storage<_CharT>(__nm) {}
2465
2466protected:
Howard Hinnant756c69b2010-09-22 16:48:34 +00002467 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002468 ~time_get_byname() {}
2469
Howard Hinnant756c69b2010-09-22 16:48:34 +00002470 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002471 virtual dateorder do_date_order() const {return this->__do_date_order();}
2472private:
Howard Hinnant756c69b2010-09-22 16:48:34 +00002473 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002474 virtual const string_type* __weeks() const {return this->__weeks_;}
Howard Hinnant756c69b2010-09-22 16:48:34 +00002475 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002476 virtual const string_type* __months() const {return this->__months_;}
Howard Hinnant756c69b2010-09-22 16:48:34 +00002477 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002478 virtual const string_type* __am_pm() const {return this->__am_pm_;}
Howard Hinnant756c69b2010-09-22 16:48:34 +00002479 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002480 virtual const string_type& __c() const {return this->__c_;}
Howard Hinnant756c69b2010-09-22 16:48:34 +00002481 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002482 virtual const string_type& __r() const {return this->__r_;}
Howard Hinnant756c69b2010-09-22 16:48:34 +00002483 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002484 virtual const string_type& __x() const {return this->__x_;}
Howard Hinnant756c69b2010-09-22 16:48:34 +00002485 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002486 virtual const string_type& __X() const {return this->__X_;}
2487};
2488
2489extern template class time_get_byname<char>;
2490extern template class time_get_byname<wchar_t>;
2491
2492class __time_put
2493{
2494 locale_t __loc_;
2495protected:
2496 _LIBCPP_ALWAYS_INLINE __time_put() : __loc_(0) {}
2497 __time_put(const char* __nm);
2498 __time_put(const string& __nm);
2499 ~__time_put();
2500 void __do_put(char* __nb, char*& __ne, const tm* __tm,
2501 char __fmt, char __mod) const;
2502 void __do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
2503 char __fmt, char __mod) const;
2504};
2505
2506template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant756c69b2010-09-22 16:48:34 +00002507class _LIBCPP_VISIBLE time_put
Howard Hinnantc51e1022010-05-11 19:42:16 +00002508 : public locale::facet,
2509 private __time_put
2510{
2511public:
2512 typedef _CharT char_type;
2513 typedef _OutputIterator iter_type;
2514
2515 _LIBCPP_ALWAYS_INLINE
2516 explicit time_put(size_t __refs = 0)
2517 : locale::facet(__refs) {}
2518
2519 iter_type put(iter_type __s, ios_base& __iob, char_type __fl, const tm* __tm,
2520 const char_type* __pb, const char_type* __pe) const;
2521
2522 _LIBCPP_ALWAYS_INLINE
2523 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
2524 const tm* __tm, char __fmt, char __mod = 0) const
2525 {
2526 return do_put(__s, __iob, __fl, __tm, __fmt, __mod);
2527 }
2528
2529 static locale::id id;
2530
2531protected:
Howard Hinnant756c69b2010-09-22 16:48:34 +00002532 _LIBCPP_ALWAYS_INLINE
Howard Hinnantc51e1022010-05-11 19:42:16 +00002533 ~time_put() {}
2534 virtual iter_type do_put(iter_type __s, ios_base&, char_type, const tm* __tm,
2535 char __fmt, char __mod) const;
2536
Howard Hinnant756c69b2010-09-22 16:48:34 +00002537 _LIBCPP_ALWAYS_INLINE
Howard Hinnantc51e1022010-05-11 19:42:16 +00002538 explicit time_put(const char* __nm, size_t __refs)
2539 : locale::facet(__refs),
2540 __time_put(__nm) {}
Howard Hinnant756c69b2010-09-22 16:48:34 +00002541 _LIBCPP_ALWAYS_INLINE
Howard Hinnantc51e1022010-05-11 19:42:16 +00002542 explicit time_put(const string& __nm, size_t __refs)
2543 : locale::facet(__refs),
2544 __time_put(__nm) {}
2545};
2546
2547template <class _CharT, class _OutputIterator>
2548locale::id
2549time_put<_CharT, _OutputIterator>::id;
2550
2551template <class _CharT, class _OutputIterator>
2552_OutputIterator
2553time_put<_CharT, _OutputIterator>::put(iter_type __s, ios_base& __iob,
2554 char_type __fl, const tm* __tm,
2555 const char_type* __pb,
2556 const char_type* __pe) const
2557{
2558 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2559 for (; __pb != __pe; ++__pb)
2560 {
2561 if (__ct.narrow(*__pb, 0) == '%')
2562 {
2563 if (++__pb == __pe)
2564 {
2565 *__s++ = __pb[-1];
2566 break;
2567 }
2568 char __mod = 0;
2569 char __fmt = __ct.narrow(*__pb, 0);
2570 if (__fmt == 'E' || __fmt == 'O')
2571 {
2572 if (++__pb == __pe)
2573 {
2574 *__s++ = __pb[-2];
2575 *__s++ = __pb[-1];
2576 break;
2577 }
2578 __mod = __fmt;
2579 __fmt = __ct.narrow(*__pb, 0);
2580 }
2581 __s = do_put(__s, __iob, __fl, __tm, __fmt, __mod);
2582 }
2583 else
2584 *__s++ = *__pb;
2585 }
2586 return __s;
2587}
2588
2589template <class _CharT, class _OutputIterator>
2590_OutputIterator
2591time_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
2592 char_type, const tm* __tm,
2593 char __fmt, char __mod) const
2594{
2595 char_type __nar[100];
2596 char_type* __nb = __nar;
2597 char_type* __ne = __nb + 100;
2598 __do_put(__nb, __ne, __tm, __fmt, __mod);
Howard Hinnant05051da2011-02-14 19:12:38 +00002599 return _STD::copy(__nb, __ne, __s);
Howard Hinnantc51e1022010-05-11 19:42:16 +00002600}
2601
2602extern template class time_put<char>;
2603extern template class time_put<wchar_t>;
2604
2605template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant756c69b2010-09-22 16:48:34 +00002606class _LIBCPP_VISIBLE time_put_byname
Howard Hinnantc51e1022010-05-11 19:42:16 +00002607 : public time_put<_CharT, _OutputIterator>
2608{
2609public:
2610 _LIBCPP_ALWAYS_INLINE
2611 explicit time_put_byname(const char* __nm, size_t __refs = 0)
2612 : time_put<_CharT, _OutputIterator>(__nm, __refs) {}
2613
2614 _LIBCPP_ALWAYS_INLINE
2615 explicit time_put_byname(const string& __nm, size_t __refs = 0)
2616 : time_put<_CharT, _OutputIterator>(__nm, __refs) {}
2617
2618protected:
Howard Hinnant756c69b2010-09-22 16:48:34 +00002619 _LIBCPP_ALWAYS_INLINE
Howard Hinnantc51e1022010-05-11 19:42:16 +00002620 ~time_put_byname() {}
2621};
2622
2623extern template class time_put_byname<char>;
2624extern template class time_put_byname<wchar_t>;
2625
2626// money_base
2627
Howard Hinnant756c69b2010-09-22 16:48:34 +00002628class _LIBCPP_VISIBLE money_base
Howard Hinnantc51e1022010-05-11 19:42:16 +00002629{
2630public:
2631 enum part {none, space, symbol, sign, value};
2632 struct pattern {char field[4];};
2633
2634 _LIBCPP_ALWAYS_INLINE money_base() {}
2635};
2636
2637// moneypunct
2638
2639template <class _CharT, bool _International = false>
Howard Hinnant756c69b2010-09-22 16:48:34 +00002640class _LIBCPP_VISIBLE moneypunct
Howard Hinnantc51e1022010-05-11 19:42:16 +00002641 : public locale::facet,
2642 public money_base
2643{
2644public:
2645 typedef _CharT char_type;
2646 typedef basic_string<char_type> string_type;
2647
Howard Hinnant756c69b2010-09-22 16:48:34 +00002648 _LIBCPP_ALWAYS_INLINE
Howard Hinnantc51e1022010-05-11 19:42:16 +00002649 explicit moneypunct(size_t __refs = 0)
2650 : locale::facet(__refs) {}
2651
2652 _LIBCPP_ALWAYS_INLINE char_type decimal_point() const {return do_decimal_point();}
2653 _LIBCPP_ALWAYS_INLINE char_type thousands_sep() const {return do_thousands_sep();}
2654 _LIBCPP_ALWAYS_INLINE string grouping() const {return do_grouping();}
2655 _LIBCPP_ALWAYS_INLINE string_type curr_symbol() const {return do_curr_symbol();}
2656 _LIBCPP_ALWAYS_INLINE string_type positive_sign() const {return do_positive_sign();}
2657 _LIBCPP_ALWAYS_INLINE string_type negative_sign() const {return do_negative_sign();}
2658 _LIBCPP_ALWAYS_INLINE int frac_digits() const {return do_frac_digits();}
2659 _LIBCPP_ALWAYS_INLINE pattern pos_format() const {return do_pos_format();}
2660 _LIBCPP_ALWAYS_INLINE pattern neg_format() const {return do_neg_format();}
2661
2662 static locale::id id;
2663 static const bool intl = _International;
2664
2665protected:
Howard Hinnant756c69b2010-09-22 16:48:34 +00002666 _LIBCPP_ALWAYS_INLINE
Howard Hinnantc51e1022010-05-11 19:42:16 +00002667 ~moneypunct() {}
2668
2669 virtual char_type do_decimal_point() const {return numeric_limits<char_type>::max();}
2670 virtual char_type do_thousands_sep() const {return numeric_limits<char_type>::max();}
2671 virtual string do_grouping() const {return string();}
2672 virtual string_type do_curr_symbol() const {return string_type();}
2673 virtual string_type do_positive_sign() const {return string_type();}
2674 virtual string_type do_negative_sign() const {return string_type(1, '-');}
2675 virtual int do_frac_digits() const {return 0;}
2676 virtual pattern do_pos_format() const
2677 {pattern __p = {symbol, sign, none, value}; return __p;}
2678 virtual pattern do_neg_format() const
2679 {pattern __p = {symbol, sign, none, value}; return __p;}
2680};
2681
2682template <class _CharT, bool _International>
2683locale::id
2684moneypunct<_CharT, _International>::id;
2685
2686extern template class moneypunct<char, false>;
2687extern template class moneypunct<char, true>;
2688extern template class moneypunct<wchar_t, false>;
2689extern template class moneypunct<wchar_t, true>;
2690
2691// moneypunct_byname
2692
2693template <class _CharT, bool _International = false>
Howard Hinnant756c69b2010-09-22 16:48:34 +00002694class _LIBCPP_VISIBLE moneypunct_byname
2695 : public moneypunct<_CharT, _International>
Howard Hinnantc51e1022010-05-11 19:42:16 +00002696{
2697public:
2698 typedef money_base::pattern pattern;
2699 typedef _CharT char_type;
2700 typedef basic_string<char_type> string_type;
2701
2702 _LIBCPP_ALWAYS_INLINE
2703 explicit moneypunct_byname(const char* __nm, size_t __refs = 0)
2704 : moneypunct<_CharT, _International>(__refs) {init(__nm);}
2705
2706 _LIBCPP_ALWAYS_INLINE
2707 explicit moneypunct_byname(const string& __nm, size_t __refs = 0)
2708 : moneypunct<_CharT, _International>(__refs) {init(__nm.c_str());}
2709
2710protected:
Howard Hinnant756c69b2010-09-22 16:48:34 +00002711 _LIBCPP_ALWAYS_INLINE
Howard Hinnantc51e1022010-05-11 19:42:16 +00002712 ~moneypunct_byname() {}
2713
2714 virtual char_type do_decimal_point() const {return __decimal_point_;}
2715 virtual char_type do_thousands_sep() const {return __thousands_sep_;}
2716 virtual string do_grouping() const {return __grouping_;}
2717 virtual string_type do_curr_symbol() const {return __curr_symbol_;}
2718 virtual string_type do_positive_sign() const {return __positive_sign_;}
2719 virtual string_type do_negative_sign() const {return __negative_sign_;}
2720 virtual int do_frac_digits() const {return __frac_digits_;}
2721 virtual pattern do_pos_format() const {return __pos_format_;}
2722 virtual pattern do_neg_format() const {return __neg_format_;}
2723
2724private:
2725 char_type __decimal_point_;
2726 char_type __thousands_sep_;
2727 string __grouping_;
2728 string_type __curr_symbol_;
2729 string_type __positive_sign_;
2730 string_type __negative_sign_;
2731 int __frac_digits_;
2732 pattern __pos_format_;
2733 pattern __neg_format_;
2734
2735 void init(const char*);
2736};
2737
2738template<> void moneypunct_byname<char, false>::init(const char*);
2739template<> void moneypunct_byname<char, true>::init(const char*);
2740template<> void moneypunct_byname<wchar_t, false>::init(const char*);
2741template<> void moneypunct_byname<wchar_t, true>::init(const char*);
2742
2743extern template class moneypunct_byname<char, false>;
2744extern template class moneypunct_byname<char, true>;
2745extern template class moneypunct_byname<wchar_t, false>;
2746extern template class moneypunct_byname<wchar_t, true>;
2747
2748// money_get
2749
2750template <class _CharT>
2751class __money_get
2752{
2753protected:
2754 typedef _CharT char_type;
2755 typedef basic_string<char_type> string_type;
2756
2757 _LIBCPP_ALWAYS_INLINE __money_get() {}
2758
2759 static void __gather_info(bool __intl, const locale& __loc,
2760 money_base::pattern& __pat, char_type& __dp,
2761 char_type& __ts, string& __grp,
2762 string_type& __sym, string_type& __psn,
2763 string_type& __nsn, int& __fd);
2764};
2765
2766template <class _CharT>
2767void
2768__money_get<_CharT>::__gather_info(bool __intl, const locale& __loc,
2769 money_base::pattern& __pat, char_type& __dp,
2770 char_type& __ts, string& __grp,
2771 string_type& __sym, string_type& __psn,
2772 string_type& __nsn, int& __fd)
2773{
2774 if (__intl)
2775 {
2776 const moneypunct<char_type, true>& __mp =
2777 use_facet<moneypunct<char_type, true> >(__loc);
2778 __pat = __mp.neg_format();
2779 __nsn = __mp.negative_sign();
2780 __psn = __mp.positive_sign();
2781 __dp = __mp.decimal_point();
2782 __ts = __mp.thousands_sep();
2783 __grp = __mp.grouping();
2784 __sym = __mp.curr_symbol();
2785 __fd = __mp.frac_digits();
2786 }
2787 else
2788 {
2789 const moneypunct<char_type, false>& __mp =
2790 use_facet<moneypunct<char_type, false> >(__loc);
2791 __pat = __mp.neg_format();
2792 __nsn = __mp.negative_sign();
2793 __psn = __mp.positive_sign();
2794 __dp = __mp.decimal_point();
2795 __ts = __mp.thousands_sep();
2796 __grp = __mp.grouping();
2797 __sym = __mp.curr_symbol();
2798 __fd = __mp.frac_digits();
2799 }
2800}
2801
2802extern template class __money_get<char>;
2803extern template class __money_get<wchar_t>;
2804
2805template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnant756c69b2010-09-22 16:48:34 +00002806class _LIBCPP_VISIBLE money_get
Howard Hinnantc51e1022010-05-11 19:42:16 +00002807 : public locale::facet,
2808 private __money_get<_CharT>
2809{
2810public:
2811 typedef _CharT char_type;
2812 typedef _InputIterator iter_type;
2813 typedef basic_string<char_type> string_type;
2814
2815 _LIBCPP_ALWAYS_INLINE
2816 explicit money_get(size_t __refs = 0)
2817 : locale::facet(__refs) {}
2818
2819 _LIBCPP_ALWAYS_INLINE
2820 iter_type get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob,
2821 ios_base::iostate& __err, long double& __v) const
2822 {
2823 return do_get(__b, __e, __intl, __iob, __err, __v);
2824 }
2825
2826 _LIBCPP_ALWAYS_INLINE
2827 iter_type get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob,
2828 ios_base::iostate& __err, string_type& __v) const
2829 {
2830 return do_get(__b, __e, __intl, __iob, __err, __v);
2831 }
2832
2833 static locale::id id;
2834
2835protected:
2836
Howard Hinnant756c69b2010-09-22 16:48:34 +00002837 _LIBCPP_ALWAYS_INLINE
Howard Hinnantc51e1022010-05-11 19:42:16 +00002838 ~money_get() {}
Howard Hinnant3b6579a2010-08-22 00:02:43 +00002839
Howard Hinnantc51e1022010-05-11 19:42:16 +00002840 virtual iter_type do_get(iter_type __b, iter_type __e, bool __intl,
2841 ios_base& __iob, ios_base::iostate& __err,
2842 long double& __v) const;
2843 virtual iter_type do_get(iter_type __b, iter_type __e, bool __intl,
2844 ios_base& __iob, ios_base::iostate& __err,
2845 string_type& __v) const;
2846
2847private:
2848 static bool __do_get(iter_type& __b, iter_type __e,
2849 bool __intl, const locale& __loc,
2850 ios_base::fmtflags __flags, ios_base::iostate& __err,
2851 bool& __neg, const ctype<char_type>& __ct,
2852 unique_ptr<char_type, void(*)(void*)>& __wb,
2853 char_type*& __wn, char_type* __we);
2854};
2855
2856template <class _CharT, class _InputIterator>
2857locale::id
2858money_get<_CharT, _InputIterator>::id;
2859
2860void __do_nothing(void*);
2861
2862template <class _Tp>
2863_LIBCPP_HIDDEN
2864void
2865__double_or_nothing(unique_ptr<_Tp, void(*)(void*)>& __b, _Tp*& __n, _Tp*& __e)
2866{
2867 bool __owns = __b.get_deleter() != __do_nothing;
2868 size_t __cur_cap = (__e-__b.get()) * sizeof(_Tp);
2869 size_t __new_cap = __cur_cap < numeric_limits<size_t>::max() / 2 ?
2870 2 * __cur_cap : numeric_limits<size_t>::max();
2871 size_t __n_off = __n - __b.get();
2872 _Tp* __t = (_Tp*)realloc(__owns ? __b.get() : 0, __new_cap);
2873 if (__t == 0)
2874 __throw_bad_alloc();
2875 if (__owns)
2876 __b.release();
2877 __b = unique_ptr<_Tp, void(*)(void*)>(__t, free);
2878 __new_cap /= sizeof(_Tp);
2879 __n = __b.get() + __n_off;
2880 __e = __b.get() + __new_cap;
2881}
2882
2883// true == success
2884template <class _CharT, class _InputIterator>
2885bool
2886money_get<_CharT, _InputIterator>::__do_get(iter_type& __b, iter_type __e,
2887 bool __intl, const locale& __loc,
2888 ios_base::fmtflags __flags,
2889 ios_base::iostate& __err,
2890 bool& __neg,
2891 const ctype<char_type>& __ct,
2892 unique_ptr<char_type, void(*)(void*)>& __wb,
2893 char_type*& __wn, char_type* __we)
2894{
2895 const unsigned __bz = 100;
2896 unsigned __gbuf[__bz];
2897 unique_ptr<unsigned, void(*)(void*)> __gb(__gbuf, __do_nothing);
2898 unsigned* __gn = __gb.get();
2899 unsigned* __ge = __gn + __bz;
2900 money_base::pattern __pat;
2901 char_type __dp;
2902 char_type __ts;
2903 string __grp;
2904 string_type __sym;
2905 string_type __psn;
2906 string_type __nsn;
2907 int __fd;
2908 __money_get<_CharT>::__gather_info(__intl, __loc, __pat, __dp, __ts, __grp,
2909 __sym, __psn, __nsn, __fd);
2910 const string_type* __trailing_sign = 0;
2911 __wn = __wb.get();
2912 for (unsigned __p = 0; __p < 4 && __b != __e; ++__p)
2913 {
2914 switch (__pat.field[__p])
2915 {
2916 case money_base::space:
2917 if (__p != 3)
2918 {
2919 if (__ct.is(ctype_base::space, *__b))
2920 ++__b;
2921 else
2922 {
2923 __err |= ios_base::failbit;
2924 return false;
2925 }
2926 }
Howard Hinnant3b6579a2010-08-22 00:02:43 +00002927 // drop through
Howard Hinnantc51e1022010-05-11 19:42:16 +00002928 case money_base::none:
2929 if (__p != 3)
2930 {
2931 while (__b != __e && __ct.is(ctype_base::space, *__b))
2932 ++__b;
2933 }
2934 break;
2935 case money_base::sign:
2936 if (__psn.size() + __nsn.size() > 0)
2937 {
2938 if (__psn.size() == 0 || __nsn.size() == 0)
2939 { // sign is optional
2940 if (__psn.size() > 0)
2941 { // __nsn.size() == 0
2942 if (*__b == __psn[0])
2943 {
2944 ++__b;
2945 if (__psn.size() > 1)
2946 __trailing_sign = &__psn;
2947 }
2948 else
2949 __neg = true;
2950 }
2951 else if (*__b == __nsn[0]) // __nsn.size() > 0 && __psn.size() == 0
2952 {
2953 ++__b;
2954 __neg = true;
2955 if (__nsn.size() > 1)
2956 __trailing_sign = &__nsn;
2957 }
2958 }
2959 else // sign is required
2960 {
2961 if (*__b == __psn[0])
2962 {
2963 ++__b;
2964 if (__psn.size() > 1)
2965 __trailing_sign = &__psn;
2966 }
2967 else if (*__b == __nsn[0])
2968 {
2969 ++__b;
2970 __neg = true;
2971 if (__nsn.size() > 1)
2972 __trailing_sign = &__nsn;
2973 }
2974 else
2975 {
2976 __err |= ios_base::failbit;
2977 return false;
2978 }
2979 }
2980 }
2981 break;
2982 case money_base::symbol:
2983 {
2984 bool __more_needed = __trailing_sign ||
2985 (__p < 2) ||
2986 (__p == 2 && __pat.field[3] != static_cast<char>(money_base::none));
2987 bool __sb = __flags & ios_base::showbase;
2988 if (__sb || __more_needed)
2989 {
2990 ios_base::iostate __et = ios_base::goodbit;
2991 string_type* __k = __scan_keyword(__b, __e, &__sym, &__sym+1,
2992 __ct, __et);
2993 if (__sb && __k != &__sym)
2994 {
2995 __err |= ios_base::failbit;
2996 return false;
2997 }
2998 }
2999 }
3000 break;
3001 case money_base::value:
3002 {
3003 unsigned __ng = 0;
3004 for (; __b != __e; ++__b)
3005 {
3006 char_type __c = *__b;
3007 if (__ct.is(ctype_base::digit, __c))
3008 {
3009 if (__wn == __we)
3010 __double_or_nothing(__wb, __wn, __we);
3011 *__wn++ = __c;
3012 ++__ng;
3013 }
3014 else if (__grp.size() > 0 && __ng > 0 && __c == __ts)
3015 {
3016 if (__gn == __ge)
3017 __double_or_nothing(__gb, __gn, __ge);
3018 *__gn++ = __ng;
3019 __ng = 0;
3020 }
3021 else
3022 break;
3023 }
3024 if (__gb.get() != __gn && __ng > 0)
3025 {
3026 if (__gn == __ge)
3027 __double_or_nothing(__gb, __gn, __ge);
3028 *__gn++ = __ng;
3029 }
3030 if (__fd > 0)
3031 {
3032 if (__b == __e || *__b != __dp)
3033 {
3034 __err |= ios_base::failbit;
3035 return false;
3036 }
3037 for (++__b; __fd > 0; --__fd, ++__b)
3038 {
3039 if (__b == __e || !__ct.is(ctype_base::digit, *__b))
3040 {
3041 __err |= ios_base::failbit;
3042 return false;
3043 }
3044 if (__wn == __we)
3045 __double_or_nothing(__wb, __wn, __we);
3046 *__wn++ = *__b;
3047 }
3048 }
3049 if (__wn == __wb.get())
3050 {
3051 __err |= ios_base::failbit;
3052 return false;
3053 }
3054 }
3055 break;
3056 }
3057 }
3058 if (__trailing_sign)
3059 {
3060 for (unsigned __i = 1; __i < __trailing_sign->size(); ++__i, ++__b)
3061 {
3062 if (__b == __e || *__b != (*__trailing_sign)[__i])
3063 {
3064 __err |= ios_base::failbit;
3065 return false;
3066 }
3067 }
3068 }
3069 if (__gb.get() != __gn)
3070 {
3071 ios_base::iostate __et = ios_base::goodbit;
3072 __check_grouping(__grp, __gb.get(), __gn, __et);
3073 if (__et)
3074 {
3075 __err |= ios_base::failbit;
3076 return false;
3077 }
3078 }
3079 return true;
3080}
3081
3082template <class _CharT, class _InputIterator>
3083_InputIterator
3084money_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
3085 bool __intl, ios_base& __iob,
3086 ios_base::iostate& __err,
3087 long double& __v) const
3088{
3089 const unsigned __bz = 100;
3090 char_type __wbuf[__bz];
3091 unique_ptr<char_type, void(*)(void*)> __wb(__wbuf, __do_nothing);
3092 char_type* __wn;
3093 char_type* __we = __wbuf + __bz;
3094 locale __loc = __iob.getloc();
3095 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3096 bool __neg = false;
3097 if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct,
3098 __wb, __wn, __we))
3099 {
3100 const char __src[] = "0123456789";
3101 char_type __atoms[sizeof(__src)-1];
3102 __ct.widen(__src, __src + (sizeof(__src)-1), __atoms);
3103 char __nbuf[__bz];
3104 char* __nc = __nbuf;
3105 unique_ptr<char, void(*)(void*)> __h(0, free);
3106 if (__wn - __wb.get() > __bz-2)
3107 {
3108 __h.reset((char*)malloc(__wn - __wb.get() + 2));
3109 if (__h.get() == 0)
3110 __throw_bad_alloc();
3111 __nc = __h.get();
3112 }
3113 if (__neg)
3114 *__nc++ = '-';
3115 for (const char_type* __w = __wb.get(); __w < __wn; ++__w, ++__nc)
3116 *__nc = __src[find(__atoms, __atoms+sizeof(__atoms), *__w) - __atoms];
3117 *__nc = char();
3118 if (sscanf(__nbuf, "%Lf", &__v) != 1)
3119 __throw_runtime_error("money_get error");
3120 }
3121 if (__b == __e)
3122 __err |= ios_base::eofbit;
3123 return __b;
3124}
3125
3126template <class _CharT, class _InputIterator>
3127_InputIterator
3128money_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
3129 bool __intl, ios_base& __iob,
3130 ios_base::iostate& __err,
3131 string_type& __v) const
3132{
3133 const unsigned __bz = 100;
3134 char_type __wbuf[__bz];
3135 unique_ptr<char_type, void(*)(void*)> __wb(__wbuf, __do_nothing);
3136 char_type* __wn;
3137 char_type* __we = __wbuf + __bz;
3138 locale __loc = __iob.getloc();
3139 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3140 bool __neg = false;
3141 if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct,
3142 __wb, __wn, __we))
3143 {
3144 __v.clear();
3145 if (__neg)
3146 __v.push_back(__ct.widen('-'));
3147 char_type __z = __ct.widen('0');
3148 char_type* __w;
3149 for (__w = __wb.get(); __w < __wn-1; ++__w)
3150 if (*__w != __z)
3151 break;
3152 __v.append(__w, __wn);
3153 }
3154 if (__b == __e)
3155 __err |= ios_base::eofbit;
3156 return __b;
3157}
3158
3159extern template class money_get<char>;
3160extern template class money_get<wchar_t>;
3161
3162// money_put
3163
3164template <class _CharT>
3165class __money_put
3166{
3167protected:
3168 typedef _CharT char_type;
3169 typedef basic_string<char_type> string_type;
3170
3171 _LIBCPP_ALWAYS_INLINE __money_put() {}
3172
3173 static void __gather_info(bool __intl, bool __neg, const locale& __loc,
3174 money_base::pattern& __pat, char_type& __dp,
3175 char_type& __ts, string& __grp,
3176 string_type& __sym, string_type& __sn,
3177 int& __fd);
3178 static void __format(char_type* __mb, char_type*& __mi, char_type*& __me,
3179 ios_base::fmtflags __flags,
3180 const char_type* __db, const char_type* __de,
3181 const ctype<char_type>& __ct, bool __neg,
3182 const money_base::pattern& __pat, char_type __dp,
3183 char_type __ts, const string& __grp,
3184 const string_type& __sym, const string_type& __sn,
3185 int __fd);
3186};
3187
3188template <class _CharT>
3189void
3190__money_put<_CharT>::__gather_info(bool __intl, bool __neg, const locale& __loc,
3191 money_base::pattern& __pat, char_type& __dp,
3192 char_type& __ts, string& __grp,
3193 string_type& __sym, string_type& __sn,
3194 int& __fd)
3195{
3196 if (__intl)
3197 {
3198 const moneypunct<char_type, true>& __mp =
3199 use_facet<moneypunct<char_type, true> >(__loc);
3200 if (__neg)
3201 {
3202 __pat = __mp.neg_format();
3203 __sn = __mp.negative_sign();
3204 }
3205 else
3206 {
3207 __pat = __mp.pos_format();
3208 __sn = __mp.positive_sign();
3209 }
3210 __dp = __mp.decimal_point();
3211 __ts = __mp.thousands_sep();
3212 __grp = __mp.grouping();
3213 __sym = __mp.curr_symbol();
3214 __fd = __mp.frac_digits();
3215 }
3216 else
3217 {
3218 const moneypunct<char_type, false>& __mp =
3219 use_facet<moneypunct<char_type, false> >(__loc);
3220 if (__neg)
3221 {
3222 __pat = __mp.neg_format();
3223 __sn = __mp.negative_sign();
3224 }
3225 else
3226 {
3227 __pat = __mp.pos_format();
3228 __sn = __mp.positive_sign();
3229 }
3230 __dp = __mp.decimal_point();
3231 __ts = __mp.thousands_sep();
3232 __grp = __mp.grouping();
3233 __sym = __mp.curr_symbol();
3234 __fd = __mp.frac_digits();
3235 }
3236}
3237
3238template <class _CharT>
3239void
3240__money_put<_CharT>::__format(char_type* __mb, char_type*& __mi, char_type*& __me,
3241 ios_base::fmtflags __flags,
3242 const char_type* __db, const char_type* __de,
3243 const ctype<char_type>& __ct, bool __neg,
3244 const money_base::pattern& __pat, char_type __dp,
3245 char_type __ts, const string& __grp,
3246 const string_type& __sym, const string_type& __sn,
3247 int __fd)
3248{
3249 __me = __mb;
3250 for (unsigned __p = 0; __p < 4; ++__p)
3251 {
3252 switch (__pat.field[__p])
3253 {
3254 case money_base::none:
3255 __mi = __me;
3256 break;
3257 case money_base::space:
3258 __mi = __me;
3259 *__me++ = __ct.widen(' ');
3260 break;
3261 case money_base::sign:
3262 if (!__sn.empty())
3263 *__me++ = __sn[0];
3264 break;
3265 case money_base::symbol:
3266 if (!__sym.empty() && (__flags & ios_base::showbase))
Howard Hinnant05051da2011-02-14 19:12:38 +00003267 __me = _STD::copy(__sym.begin(), __sym.end(), __me);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003268 break;
3269 case money_base::value:
3270 {
3271 // remember start of value so we can reverse it
3272 char_type* __t = __me;
3273 // find beginning of digits
3274 if (__neg)
3275 ++__db;
3276 // find end of digits
3277 const char_type* __d;
3278 for (__d = __db; __d < __de; ++__d)
3279 if (!__ct.is(ctype_base::digit, *__d))
3280 break;
3281 // print fractional part
3282 if (__fd > 0)
3283 {
3284 int __f;
3285 for (__f = __fd; __d > __db && __f > 0; --__f)
3286 *__me++ = *--__d;
3287 char_type __z = __f > 0 ? __ct.widen('0') : char_type();
3288 for (; __f > 0; --__f)
3289 *__me++ = __z;
3290 *__me++ = __dp;
3291 }
3292 // print units part
3293 if (__d == __db)
3294 {
3295 *__me++ = __ct.widen('0');
3296 }
3297 else
3298 {
3299 unsigned __ng = 0;
3300 unsigned __ig = 0;
3301 unsigned __gl = __grp.empty() ? numeric_limits<unsigned>::max()
3302 : static_cast<unsigned>(__grp[__ig]);
3303 while (__d != __db)
3304 {
3305 if (__ng == __gl)
3306 {
3307 *__me++ = __ts;
3308 __ng = 0;
3309 if (++__ig < __grp.size())
3310 __gl = __grp[__ig] == numeric_limits<char>::max() ?
3311 numeric_limits<unsigned>::max() :
3312 static_cast<unsigned>(__grp[__ig]);
3313 }
3314 *__me++ = *--__d;
3315 ++__ng;
3316 }
3317 }
3318 // reverse it
3319 reverse(__t, __me);
3320 }
3321 break;
3322 }
3323 }
3324 // print rest of sign, if any
3325 if (__sn.size() > 1)
Howard Hinnant05051da2011-02-14 19:12:38 +00003326 __me = _STD::copy(__sn.begin()+1, __sn.end(), __me);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003327 // set alignment
3328 if ((__flags & ios_base::adjustfield) == ios_base::left)
3329 __mi = __me;
3330 else if ((__flags & ios_base::adjustfield) != ios_base::internal)
3331 __mi = __mb;
3332}
3333
3334extern template class __money_put<char>;
3335extern template class __money_put<wchar_t>;
3336
3337template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant756c69b2010-09-22 16:48:34 +00003338class _LIBCPP_VISIBLE money_put
Howard Hinnantc51e1022010-05-11 19:42:16 +00003339 : public locale::facet,
3340 private __money_put<_CharT>
3341{
3342public:
3343 typedef _CharT char_type;
3344 typedef _OutputIterator iter_type;
3345 typedef basic_string<char_type> string_type;
3346
3347 _LIBCPP_ALWAYS_INLINE
3348 explicit money_put(size_t __refs = 0)
3349 : locale::facet(__refs) {}
3350
3351 _LIBCPP_ALWAYS_INLINE
3352 iter_type put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl,
3353 long double __units) const
3354 {
3355 return do_put(__s, __intl, __iob, __fl, __units);
3356 }
3357
3358 _LIBCPP_ALWAYS_INLINE
3359 iter_type put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl,
3360 const string_type& __digits) const
3361 {
3362 return do_put(__s, __intl, __iob, __fl, __digits);
3363 }
3364
3365 static locale::id id;
3366
3367protected:
Howard Hinnant756c69b2010-09-22 16:48:34 +00003368 _LIBCPP_ALWAYS_INLINE
Howard Hinnantc51e1022010-05-11 19:42:16 +00003369 ~money_put() {}
3370
3371 virtual iter_type do_put(iter_type __s, bool __intl, ios_base& __iob,
3372 char_type __fl, long double __units) const;
3373 virtual iter_type do_put(iter_type __s, bool __intl, ios_base& __iob,
3374 char_type __fl, const string_type& __digits) const;
3375};
3376
3377template <class _CharT, class _OutputIterator>
3378locale::id
3379money_put<_CharT, _OutputIterator>::id;
3380
3381template <class _CharT, class _OutputIterator>
3382_OutputIterator
3383money_put<_CharT, _OutputIterator>::do_put(iter_type __s, bool __intl,
3384 ios_base& __iob, char_type __fl,
3385 long double __units) const
3386{
3387 // convert to char
3388 const size_t __bs = 100;
3389 char __buf[__bs];
3390 char* __bb = __buf;
3391 char_type __digits[__bs];
3392 char_type* __db = __digits;
3393 size_t __n = snprintf(__bb, __bs, "%.0Lf", __units);
3394 unique_ptr<char, void(*)(void*)> __hn(0, free);
3395 unique_ptr<char_type, void(*)(void*)> __hd(0, free);
3396 // secure memory for digit storage
3397 if (__n > __bs-1)
3398 {
Howard Hinnant155c2af2010-05-24 17:49:41 +00003399 __n = __nolocale_asprintf(&__bb, "%.0Lf", __units);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003400 if (__bb == 0)
3401 __throw_bad_alloc();
3402 __hn.reset(__bb);
3403 __hd.reset((char_type*)malloc(__n * sizeof(char_type)));
3404 if (__hd == 0)
3405 __throw_bad_alloc();
3406 __db = __hd.get();
3407 }
3408 // gather info
3409 locale __loc = __iob.getloc();
3410 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3411 __ct.widen(__bb, __bb + __n, __db);
3412 bool __neg = __n > 0 && __bb[0] == '-';
3413 money_base::pattern __pat;
3414 char_type __dp;
3415 char_type __ts;
3416 string __grp;
3417 string_type __sym;
3418 string_type __sn;
3419 int __fd;
3420 this->__gather_info(__intl, __neg, __loc, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3421 // secure memory for formatting
3422 char_type __mbuf[__bs];
3423 char_type* __mb = __mbuf;
3424 unique_ptr<char_type, void(*)(void*)> __hw(0, free);
3425 size_t __exn = static_cast<int>(__n) > __fd ?
3426 (__n - __fd) * 2 + __sn.size() + __sym.size() + __fd + 1
3427 : __sn.size() + __sym.size() + __fd + 2;
3428 if (__exn > __bs)
3429 {
3430 __hw.reset((char_type*)malloc(__exn * sizeof(char_type)));
3431 __mb = __hw.get();
3432 if (__mb == 0)
3433 __throw_bad_alloc();
3434 }
3435 // format
3436 char_type* __mi;
3437 char_type* __me;
3438 this->__format(__mb, __mi, __me, __iob.flags(),
3439 __db, __db + __n, __ct,
3440 __neg, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3441 return __pad_and_output(__s, __mb, __mi, __me, __iob, __fl);
3442}
3443
3444template <class _CharT, class _OutputIterator>
3445_OutputIterator
3446money_put<_CharT, _OutputIterator>::do_put(iter_type __s, bool __intl,
3447 ios_base& __iob, char_type __fl,
3448 const string_type& __digits) const
3449{
3450 // gather info
3451 locale __loc = __iob.getloc();
3452 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3453 bool __neg = __digits.size() > 0 && __digits[0] == __ct.widen('-');
3454 money_base::pattern __pat;
3455 char_type __dp;
3456 char_type __ts;
3457 string __grp;
3458 string_type __sym;
3459 string_type __sn;
3460 int __fd;
3461 this->__gather_info(__intl, __neg, __loc, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3462 // secure memory for formatting
3463 char_type __mbuf[100];
3464 char_type* __mb = __mbuf;
3465 unique_ptr<char_type, void(*)(void*)> __h(0, free);
3466 size_t __exn = __digits.size() > __fd ?
3467 (__digits.size() - __fd) * 2 + __sn.size() + __sym.size() + __fd + 1
3468 : __sn.size() + __sym.size() + __fd + 2;
3469 if (__exn > 100)
3470 {
3471 __h.reset((char_type*)malloc(__exn * sizeof(char_type)));
3472 __mb = __h.get();
3473 if (__mb == 0)
3474 __throw_bad_alloc();
3475 }
3476 // format
3477 char_type* __mi;
3478 char_type* __me;
3479 this->__format(__mb, __mi, __me, __iob.flags(),
3480 __digits.data(), __digits.data() + __digits.size(), __ct,
3481 __neg, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3482 return __pad_and_output(__s, __mb, __mi, __me, __iob, __fl);
3483}
3484
3485extern template class money_put<char>;
3486extern template class money_put<wchar_t>;
3487
3488// messages
3489
Howard Hinnant756c69b2010-09-22 16:48:34 +00003490class _LIBCPP_VISIBLE messages_base
Howard Hinnantc51e1022010-05-11 19:42:16 +00003491{
3492public:
Howard Hinnant2862aeb2011-02-25 00:51:08 +00003493 typedef ptrdiff_t catalog;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003494
3495 _LIBCPP_ALWAYS_INLINE messages_base() {}
3496};
3497
3498template <class _CharT>
Howard Hinnant756c69b2010-09-22 16:48:34 +00003499class _LIBCPP_VISIBLE messages
Howard Hinnantc51e1022010-05-11 19:42:16 +00003500 : public locale::facet,
3501 public messages_base
3502{
3503public:
3504 typedef _CharT char_type;
3505 typedef basic_string<_CharT> string_type;
3506
3507 _LIBCPP_ALWAYS_INLINE
3508 explicit messages(size_t __refs = 0)
3509 : locale::facet(__refs) {}
3510
3511 _LIBCPP_ALWAYS_INLINE
3512 catalog open(const basic_string<char>& __nm, const locale& __loc) const
3513 {
3514 return do_open(__nm, __loc);
3515 }
3516
3517 _LIBCPP_ALWAYS_INLINE
3518 string_type get(catalog __c, int __set, int __msgid,
3519 const string_type& __dflt) const
3520 {
3521 return do_get(__c, __set, __msgid, __dflt);
3522 }
3523
3524 _LIBCPP_ALWAYS_INLINE
3525 void close(catalog __c) const
3526 {
3527 do_close(__c);
3528 }
3529
3530 static locale::id id;
3531
3532protected:
Howard Hinnant756c69b2010-09-22 16:48:34 +00003533 _LIBCPP_ALWAYS_INLINE
Howard Hinnantc51e1022010-05-11 19:42:16 +00003534 ~messages() {}
3535
3536 virtual catalog do_open(const basic_string<char>&, const locale&) const;
3537 virtual string_type do_get(catalog, int __set, int __msgid,
3538 const string_type& __dflt) const;
3539 virtual void do_close(catalog) const;
3540};
3541
3542template <class _CharT>
3543locale::id
3544messages<_CharT>::id;
3545
3546template <class _CharT>
3547typename messages<_CharT>::catalog
3548messages<_CharT>::do_open(const basic_string<char>& __nm, const locale&) const
3549{
Howard Hinnant2862aeb2011-02-25 00:51:08 +00003550 catalog __cat = reinterpret_cast<catalog>(catopen(__nm.c_str(), NL_CAT_LOCALE));
3551 if (__cat != -1)
3552 __cat = static_cast<catalog>((static_cast<size_t>(__cat) >> 1));
3553 return __cat;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003554}
3555
3556template <class _CharT>
3557typename messages<_CharT>::string_type
3558messages<_CharT>::do_get(catalog __c, int __set, int __msgid,
3559 const string_type& __dflt) const
3560{
3561 string __ndflt;
3562 __narrow_to_utf8<sizeof(char_type)*__CHAR_BIT__>()(back_inserter(__ndflt),
3563 __dflt.c_str(),
3564 __dflt.c_str() + __dflt.size());
Howard Hinnant2862aeb2011-02-25 00:51:08 +00003565 if (__c != -1)
3566 __c <<= 1;
3567 nl_catd __cat = reinterpret_cast<nl_catd>(__c);
3568 char* __n = catgets(__cat, __set, __msgid, __ndflt.c_str());
Howard Hinnantc51e1022010-05-11 19:42:16 +00003569 string_type __w;
3570 __widen_from_utf8<sizeof(char_type)*__CHAR_BIT__>()(back_inserter(__w),
3571 __n, __n + strlen(__n));
3572 return __w;
3573}
3574
3575template <class _CharT>
3576void
3577messages<_CharT>::do_close(catalog __c) const
3578{
Howard Hinnant2862aeb2011-02-25 00:51:08 +00003579 if (__c != -1)
3580 __c <<= 1;
3581 nl_catd __cat = reinterpret_cast<nl_catd>(__c);
3582 catclose(__cat);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003583}
3584
3585extern template class messages<char>;
3586extern template class messages<wchar_t>;
3587
3588template <class _CharT>
Howard Hinnant756c69b2010-09-22 16:48:34 +00003589class _LIBCPP_VISIBLE messages_byname
Howard Hinnantc51e1022010-05-11 19:42:16 +00003590 : public messages<_CharT>
3591{
3592public:
3593 typedef messages_base::catalog catalog;
3594 typedef basic_string<_CharT> string_type;
3595
3596 _LIBCPP_ALWAYS_INLINE
3597 explicit messages_byname(const char*, size_t __refs = 0)
3598 : messages<_CharT>(__refs) {}
3599
3600 _LIBCPP_ALWAYS_INLINE
3601 explicit messages_byname(const string&, size_t __refs = 0)
3602 : messages<_CharT>(__refs) {}
3603
3604protected:
Howard Hinnant756c69b2010-09-22 16:48:34 +00003605 _LIBCPP_ALWAYS_INLINE
Howard Hinnantc51e1022010-05-11 19:42:16 +00003606 ~messages_byname() {}
3607};
3608
3609extern template class messages_byname<char>;
3610extern template class messages_byname<wchar_t>;
3611
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003612template<class _Codecvt, class _Elem = wchar_t,
3613 class _Wide_alloc = allocator<_Elem>,
3614 class _Byte_alloc = allocator<char> >
Howard Hinnant756c69b2010-09-22 16:48:34 +00003615class _LIBCPP_VISIBLE wstring_convert
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003616{
3617public:
3618 typedef basic_string<char, char_traits<char>, _Byte_alloc> byte_string;
3619 typedef basic_string<_Elem, char_traits<_Elem>, _Wide_alloc> wide_string;
3620 typedef typename _Codecvt::state_type state_type;
3621 typedef typename wide_string::traits_type::int_type int_type;
3622
3623private:
3624 byte_string __byte_err_string_;
3625 wide_string __wide_err_string_;
3626 _Codecvt* __cvtptr_;
3627 state_type __cvtstate_;
3628 size_t __cvtcount_;
3629
3630 wstring_convert(const wstring_convert& __wc);
3631 wstring_convert& operator=(const wstring_convert& __wc);
3632public:
3633 wstring_convert(_Codecvt* __pcvt = new _Codecvt);
3634 wstring_convert(_Codecvt* __pcvt, state_type __state);
3635 wstring_convert(const byte_string& __byte_err,
3636 const wide_string& __wide_err = wide_string());
Howard Hinnant74279a52010-09-04 23:28:19 +00003637#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003638 wstring_convert(wstring_convert&& __wc);
3639#endif
3640 ~wstring_convert();
3641
Howard Hinnant756c69b2010-09-22 16:48:34 +00003642 _LIBCPP_ALWAYS_INLINE
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003643 wide_string from_bytes(char __byte)
3644 {return from_bytes(&__byte, &__byte+1);}
Howard Hinnant756c69b2010-09-22 16:48:34 +00003645 _LIBCPP_ALWAYS_INLINE
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003646 wide_string from_bytes(const char* __ptr)
3647 {return from_bytes(__ptr, __ptr + char_traits<char>::length(__ptr));}
Howard Hinnant756c69b2010-09-22 16:48:34 +00003648 _LIBCPP_ALWAYS_INLINE
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003649 wide_string from_bytes(const byte_string& __str)
3650 {return from_bytes(__str.data(), __str.data() + __str.size());}
3651 wide_string from_bytes(const char* __first, const char* __last);
3652
Howard Hinnant756c69b2010-09-22 16:48:34 +00003653 _LIBCPP_ALWAYS_INLINE
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003654 byte_string to_bytes(_Elem __wchar)
3655 {return to_bytes(&__wchar, &__wchar+1);}
Howard Hinnant756c69b2010-09-22 16:48:34 +00003656 _LIBCPP_ALWAYS_INLINE
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003657 byte_string to_bytes(const _Elem* __wptr)
3658 {return to_bytes(__wptr, __wptr + char_traits<_Elem>::length(__wptr));}
Howard Hinnant756c69b2010-09-22 16:48:34 +00003659 _LIBCPP_ALWAYS_INLINE
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003660 byte_string to_bytes(const wide_string& __wstr)
3661 {return to_bytes(__wstr.data(), __wstr.data() + __wstr.size());}
3662 byte_string to_bytes(const _Elem* __first, const _Elem* __last);
3663
Howard Hinnant756c69b2010-09-22 16:48:34 +00003664 _LIBCPP_ALWAYS_INLINE
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003665 size_t converted() const {return __cvtcount_;}
Howard Hinnant756c69b2010-09-22 16:48:34 +00003666 _LIBCPP_ALWAYS_INLINE
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003667 state_type state() const {return __cvtstate_;}
3668};
3669
3670template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Howard Hinnant756c69b2010-09-22 16:48:34 +00003671inline _LIBCPP_ALWAYS_INLINE
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003672wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3673 wstring_convert(_Codecvt* __pcvt)
3674 : __cvtptr_(__pcvt), __cvtstate_(), __cvtcount_(0)
3675{
3676}
3677
3678template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Howard Hinnant756c69b2010-09-22 16:48:34 +00003679inline _LIBCPP_ALWAYS_INLINE
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003680wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3681 wstring_convert(_Codecvt* __pcvt, state_type __state)
3682 : __cvtptr_(__pcvt), __cvtstate_(__state), __cvtcount_(0)
3683{
3684}
3685
3686template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3687wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3688 wstring_convert(const byte_string& __byte_err, const wide_string& __wide_err)
3689 : __byte_err_string_(__byte_err), __wide_err_string_(__wide_err),
3690 __cvtstate_(), __cvtcount_(0)
3691{
3692 __cvtptr_ = new _Codecvt;
3693}
3694
Howard Hinnant74279a52010-09-04 23:28:19 +00003695#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003696
3697template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Howard Hinnant756c69b2010-09-22 16:48:34 +00003698inline _LIBCPP_ALWAYS_INLINE
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003699wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3700 wstring_convert(wstring_convert&& __wc)
3701 : __byte_err_string_(_STD::move(__wc.__byte_err_string_)),
3702 __wide_err_string_(_STD::move(__wc.__wide_err_string_)),
3703 __cvtptr_(__wc.__cvtptr_),
3704 __cvtstate_(__wc.__cvtstate_), __cvtcount_(__wc.__cvtstate_)
3705{
3706 __wc.__cvtptr_ = nullptr;
3707}
3708
Howard Hinnant5dc89112010-09-04 23:46:48 +00003709#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003710
3711template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3712wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::~wstring_convert()
3713{
3714 delete __cvtptr_;
3715}
3716
3717template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3718typename wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::wide_string
3719wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3720 from_bytes(const char* __frm, const char* __frm_end)
3721{
3722 __cvtcount_ = 0;
3723 if (__cvtptr_ != nullptr)
3724 {
3725 wide_string __ws(2*(__frm_end - __frm), _Elem());
3726 __ws.resize(__ws.capacity());
3727 codecvt_base::result __r = codecvt_base::ok;
3728 state_type __st = __cvtstate_;
3729 if (__frm != __frm_end)
3730 {
3731 _Elem* __to = &__ws[0];
3732 _Elem* __to_end = __to + __ws.size();
3733 const char* __frm_nxt;
3734 do
3735 {
3736 _Elem* __to_nxt;
3737 __r = __cvtptr_->in(__st, __frm, __frm_end, __frm_nxt,
3738 __to, __to_end, __to_nxt);
3739 __cvtcount_ += __frm_nxt - __frm;
3740 if (__frm_nxt == __frm)
3741 {
3742 __r = codecvt_base::error;
3743 }
3744 else if (__r == codecvt_base::noconv)
3745 {
3746 __ws.resize(__to - &__ws[0]);
3747 // This only gets executed if _Elem is char
3748 __ws.append((const _Elem*)__frm, (const _Elem*)__frm_end);
3749 __frm = __frm_nxt;
3750 __r = codecvt_base::ok;
3751 }
3752 else if (__r == codecvt_base::ok)
3753 {
3754 __ws.resize(__to_nxt - &__ws[0]);
3755 __frm = __frm_nxt;
3756 }
3757 else if (__r == codecvt_base::partial)
3758 {
3759 ptrdiff_t __s = __to_nxt - &__ws[0];
3760 __ws.resize(2 * __s);
3761 __to = &__ws[0] + __s;
3762 __to_end = &__ws[0] + __ws.size();
3763 __frm = __frm_nxt;
3764 }
3765 } while (__r == codecvt_base::partial && __frm_nxt < __frm_end);
3766 }
3767 if (__r == codecvt_base::ok)
3768 return __ws;
3769 }
Howard Hinnant72f73582010-08-11 17:04:31 +00003770#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003771 if (__wide_err_string_.empty())
3772 throw range_error("wstring_convert: from_bytes error");
Howard Hinnant3b6579a2010-08-22 00:02:43 +00003773#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003774 return __wide_err_string_;
3775}
3776
3777template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3778typename wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::byte_string
3779wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3780 to_bytes(const _Elem* __frm, const _Elem* __frm_end)
3781{
3782 __cvtcount_ = 0;
3783 if (__cvtptr_ != nullptr)
3784 {
3785 byte_string __bs(2*(__frm_end - __frm), char());
3786 __bs.resize(__bs.capacity());
3787 codecvt_base::result __r = codecvt_base::ok;
3788 state_type __st = __cvtstate_;
3789 if (__frm != __frm_end)
3790 {
3791 char* __to = &__bs[0];
3792 char* __to_end = __to + __bs.size();
3793 const _Elem* __frm_nxt;
3794 do
3795 {
3796 char* __to_nxt;
3797 __r = __cvtptr_->out(__st, __frm, __frm_end, __frm_nxt,
3798 __to, __to_end, __to_nxt);
3799 __cvtcount_ += __frm_nxt - __frm;
3800 if (__frm_nxt == __frm)
3801 {
3802 __r = codecvt_base::error;
3803 }
3804 else if (__r == codecvt_base::noconv)
3805 {
3806 __bs.resize(__to - &__bs[0]);
3807 // This only gets executed if _Elem is char
3808 __bs.append((const char*)__frm, (const char*)__frm_end);
3809 __frm = __frm_nxt;
3810 __r = codecvt_base::ok;
3811 }
3812 else if (__r == codecvt_base::ok)
3813 {
3814 __bs.resize(__to_nxt - &__bs[0]);
3815 __frm = __frm_nxt;
3816 }
3817 else if (__r == codecvt_base::partial)
3818 {
3819 ptrdiff_t __s = __to_nxt - &__bs[0];
3820 __bs.resize(2 * __s);
3821 __to = &__bs[0] + __s;
3822 __to_end = &__bs[0] + __bs.size();
3823 __frm = __frm_nxt;
3824 }
3825 } while (__r == codecvt_base::partial && __frm_nxt < __frm_end);
3826 }
3827 if (__r == codecvt_base::ok)
3828 {
3829 size_t __s = __bs.size();
3830 __bs.resize(__bs.capacity());
3831 char* __to = &__bs[0] + __s;
3832 char* __to_end = __to + __bs.size();
3833 do
3834 {
3835 char* __to_nxt;
3836 __r = __cvtptr_->unshift(__st, __to, __to_end, __to_nxt);
3837 if (__r == codecvt_base::noconv)
3838 {
3839 __bs.resize(__to - &__bs[0]);
3840 __r = codecvt_base::ok;
3841 }
3842 else if (__r == codecvt_base::ok)
3843 {
3844 __bs.resize(__to_nxt - &__bs[0]);
3845 }
3846 else if (__r == codecvt_base::partial)
3847 {
3848 ptrdiff_t __s = __to_nxt - &__bs[0];
3849 __bs.resize(2 * __s);
3850 __to = &__bs[0] + __s;
3851 __to_end = &__bs[0] + __bs.size();
3852 }
3853 } while (__r == codecvt_base::partial);
3854 if (__r == codecvt_base::ok)
3855 return __bs;
3856 }
3857 }
Howard Hinnant72f73582010-08-11 17:04:31 +00003858#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003859 if (__byte_err_string_.empty())
3860 throw range_error("wstring_convert: to_bytes error");
Howard Hinnant3b6579a2010-08-22 00:02:43 +00003861#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003862 return __byte_err_string_;
3863}
3864
3865template <class _Codecvt, class _Elem = wchar_t, class _Tr = char_traits<_Elem> >
Howard Hinnant756c69b2010-09-22 16:48:34 +00003866class _LIBCPP_VISIBLE wbuffer_convert
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003867 : public basic_streambuf<_Elem, _Tr>
3868{
3869public:
3870 // types:
3871 typedef _Elem char_type;
3872 typedef _Tr traits_type;
3873 typedef typename traits_type::int_type int_type;
3874 typedef typename traits_type::pos_type pos_type;
3875 typedef typename traits_type::off_type off_type;
3876 typedef typename _Codecvt::state_type state_type;
3877
3878private:
Howard Hinnant0ac182a2010-06-01 20:09:18 +00003879 char* __extbuf_;
3880 const char* __extbufnext_;
3881 const char* __extbufend_;
3882 char __extbuf_min_[8];
3883 size_t __ebs_;
3884 char_type* __intbuf_;
3885 size_t __ibs_;
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003886 streambuf* __bufptr_;
Howard Hinnant0ac182a2010-06-01 20:09:18 +00003887 _Codecvt* __cv_;
3888 state_type __st_;
3889 ios_base::openmode __cm_;
3890 bool __owns_eb_;
3891 bool __owns_ib_;
3892 bool __always_noconv_;
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003893
Howard Hinnant0ac182a2010-06-01 20:09:18 +00003894 wbuffer_convert(const wbuffer_convert&);
3895 wbuffer_convert& operator=(const wbuffer_convert&);
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003896public:
3897 wbuffer_convert(streambuf* __bytebuf = 0, _Codecvt* __pcvt = new _Codecvt,
Howard Hinnant0ac182a2010-06-01 20:09:18 +00003898 state_type __state = state_type());
3899 ~wbuffer_convert();
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003900
Howard Hinnant756c69b2010-09-22 16:48:34 +00003901 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003902 streambuf* rdbuf() const {return __bufptr_;}
Howard Hinnant756c69b2010-09-22 16:48:34 +00003903 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003904 streambuf* rdbuf(streambuf* __bytebuf)
3905 {
3906 streambuf* __r = __bufptr_;
3907 __bufptr_ = __bytebuf;
3908 return __r;
3909 }
3910
Howard Hinnant756c69b2010-09-22 16:48:34 +00003911 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant0ac182a2010-06-01 20:09:18 +00003912 state_type state() const {return __st_;}
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003913
3914protected:
Howard Hinnant0ac182a2010-06-01 20:09:18 +00003915 virtual int_type underflow();
3916 virtual int_type pbackfail(int_type __c = traits_type::eof());
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003917 virtual int_type overflow (int_type __c = traits_type::eof());
Howard Hinnant0ac182a2010-06-01 20:09:18 +00003918 virtual basic_streambuf<char_type, traits_type>* setbuf(char_type* __s,
3919 streamsize __n);
3920 virtual pos_type seekoff(off_type __off, ios_base::seekdir __way,
3921 ios_base::openmode __wch = ios_base::in | ios_base::out);
3922 virtual pos_type seekpos(pos_type __sp,
3923 ios_base::openmode __wch = ios_base::in | ios_base::out);
3924 virtual int sync();
3925
3926private:
3927 bool __read_mode();
3928 void __write_mode();
3929 wbuffer_convert* __close();
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003930};
3931
3932template <class _Codecvt, class _Elem, class _Tr>
Howard Hinnant0ac182a2010-06-01 20:09:18 +00003933wbuffer_convert<_Codecvt, _Elem, _Tr>::
3934 wbuffer_convert(streambuf* __bytebuf, _Codecvt* __pcvt, state_type __state)
3935 : __extbuf_(0),
3936 __extbufnext_(0),
3937 __extbufend_(0),
3938 __ebs_(0),
3939 __intbuf_(0),
3940 __ibs_(0),
3941 __bufptr_(__bytebuf),
3942 __cv_(__pcvt),
3943 __st_(__state),
3944 __cm_(0),
3945 __owns_eb_(false),
3946 __owns_ib_(false),
3947 __always_noconv_(__cv_ ? __cv_->always_noconv() : false)
3948{
3949 setbuf(0, 4096);
3950}
3951
3952template <class _Codecvt, class _Elem, class _Tr>
3953wbuffer_convert<_Codecvt, _Elem, _Tr>::~wbuffer_convert()
3954{
3955 __close();
3956 delete __cv_;
3957 if (__owns_eb_)
3958 delete [] __extbuf_;
3959 if (__owns_ib_)
3960 delete [] __intbuf_;
3961}
3962
3963template <class _Codecvt, class _Elem, class _Tr>
3964typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
3965wbuffer_convert<_Codecvt, _Elem, _Tr>::underflow()
3966{
3967 if (__cv_ == 0 || __bufptr_ == 0)
3968 return traits_type::eof();
3969 bool __initial = __read_mode();
3970 char_type __1buf;
3971 if (this->gptr() == 0)
3972 this->setg(&__1buf, &__1buf+1, &__1buf+1);
3973 const size_t __unget_sz = __initial ? 0 : min<size_t>((this->egptr() - this->eback()) / 2, 4);
3974 int_type __c = traits_type::eof();
3975 if (this->gptr() == this->egptr())
3976 {
3977 memmove(this->eback(), this->egptr() - __unget_sz, __unget_sz * sizeof(char_type));
3978 if (__always_noconv_)
3979 {
3980 streamsize __nmemb = static_cast<streamsize>(this->egptr() - this->eback() - __unget_sz);
3981 __nmemb = __bufptr_->sgetn((char*)this->eback() + __unget_sz, __nmemb);
3982 if (__nmemb != 0)
3983 {
3984 this->setg(this->eback(),
3985 this->eback() + __unget_sz,
3986 this->eback() + __unget_sz + __nmemb);
3987 __c = *this->gptr();
3988 }
3989 }
3990 else
3991 {
3992 memmove(__extbuf_, __extbufnext_, __extbufend_ - __extbufnext_);
3993 __extbufnext_ = __extbuf_ + (__extbufend_ - __extbufnext_);
3994 __extbufend_ = __extbuf_ + (__extbuf_ == __extbuf_min_ ? sizeof(__extbuf_min_) : __ebs_);
Howard Hinnant05051da2011-02-14 19:12:38 +00003995 streamsize __nmemb = _STD::min(static_cast<streamsize>(this->egptr() - this->eback() - __unget_sz),
Howard Hinnant0ac182a2010-06-01 20:09:18 +00003996 static_cast<streamsize>(__extbufend_ - __extbufnext_));
3997 codecvt_base::result __r;
3998 state_type __svs = __st_;
3999 streamsize __nr = __bufptr_->sgetn(const_cast<char*>(__extbufnext_), __nmemb);
4000 if (__nr != 0)
4001 {
4002 __extbufend_ = __extbufnext_ + __nr;
4003 char_type* __inext;
4004 __r = __cv_->in(__st_, __extbuf_, __extbufend_, __extbufnext_,
4005 this->eback() + __unget_sz,
4006 this->egptr(), __inext);
4007 if (__r == codecvt_base::noconv)
4008 {
4009 this->setg((char_type*)__extbuf_, (char_type*)__extbuf_, (char_type*)__extbufend_);
4010 __c = *this->gptr();
4011 }
4012 else if (__inext != this->eback() + __unget_sz)
4013 {
4014 this->setg(this->eback(), this->eback() + __unget_sz, __inext);
4015 __c = *this->gptr();
4016 }
4017 }
4018 }
4019 }
4020 else
4021 __c = *this->gptr();
4022 if (this->eback() == &__1buf)
4023 this->setg(0, 0, 0);
4024 return __c;
4025}
4026
4027template <class _Codecvt, class _Elem, class _Tr>
4028typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
4029wbuffer_convert<_Codecvt, _Elem, _Tr>::pbackfail(int_type __c)
4030{
4031 if (__cv_ != 0 && __bufptr_ != 0 && this->eback() < this->gptr())
4032 {
4033 if (traits_type::eq_int_type(__c, traits_type::eof()))
4034 {
4035 this->gbump(-1);
4036 return traits_type::not_eof(__c);
4037 }
4038 if (traits_type::eq(traits_type::to_char_type(__c), this->gptr()[-1]))
4039 {
4040 this->gbump(-1);
4041 *this->gptr() = traits_type::to_char_type(__c);
4042 return __c;
4043 }
4044 }
4045 return traits_type::eof();
4046}
4047
4048template <class _Codecvt, class _Elem, class _Tr>
Howard Hinnant9dd7e892010-05-31 20:58:54 +00004049typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
4050wbuffer_convert<_Codecvt, _Elem, _Tr>::overflow(int_type __c)
4051{
Howard Hinnant0ac182a2010-06-01 20:09:18 +00004052 if (__cv_ == 0 || __bufptr_ == 0)
4053 return traits_type::eof();
4054 __write_mode();
4055 char_type __1buf;
4056 char_type* __pb_save = this->pbase();
4057 char_type* __epb_save = this->epptr();
4058 if (!traits_type::eq_int_type(__c, traits_type::eof()))
4059 {
4060 if (this->pptr() == 0)
4061 this->setp(&__1buf, &__1buf+1);
4062 *this->pptr() = traits_type::to_char_type(__c);
4063 this->pbump(1);
4064 }
4065 if (this->pptr() != this->pbase())
4066 {
4067 if (__always_noconv_)
4068 {
4069 streamsize __nmemb = static_cast<streamsize>(this->pptr() - this->pbase());
4070 if (__bufptr_->sputn((const char*)this->pbase(), __nmemb) != __nmemb)
4071 return traits_type::eof();
4072 }
4073 else
4074 {
4075 char* __extbe = __extbuf_;
4076 codecvt_base::result __r;
4077 do
4078 {
4079 const char_type* __e;
4080 __r = __cv_->out(__st_, this->pbase(), this->pptr(), __e,
4081 __extbuf_, __extbuf_ + __ebs_, __extbe);
4082 if (__e == this->pbase())
4083 return traits_type::eof();
4084 if (__r == codecvt_base::noconv)
4085 {
4086 streamsize __nmemb = static_cast<size_t>(this->pptr() - this->pbase());
4087 if (__bufptr_->sputn((const char*)this->pbase(), __nmemb) != __nmemb)
4088 return traits_type::eof();
4089 }
4090 else if (__r == codecvt_base::ok || __r == codecvt_base::partial)
4091 {
4092 streamsize __nmemb = static_cast<size_t>(__extbe - __extbuf_);
4093 if (__bufptr_->sputn(__extbuf_, __nmemb) != __nmemb)
4094 return traits_type::eof();
4095 if (__r == codecvt_base::partial)
4096 {
4097 this->setp((char_type*)__e, this->pptr());
4098 this->pbump(this->epptr() - this->pbase());
4099 }
4100 }
4101 else
4102 return traits_type::eof();
4103 } while (__r == codecvt_base::partial);
4104 }
4105 this->setp(__pb_save, __epb_save);
4106 }
4107 return traits_type::not_eof(__c);
4108}
4109
4110template <class _Codecvt, class _Elem, class _Tr>
4111basic_streambuf<_Elem, _Tr>*
4112wbuffer_convert<_Codecvt, _Elem, _Tr>::setbuf(char_type* __s, streamsize __n)
4113{
4114 this->setg(0, 0, 0);
4115 this->setp(0, 0);
4116 if (__owns_eb_)
4117 delete [] __extbuf_;
4118 if (__owns_ib_)
4119 delete [] __intbuf_;
4120 __ebs_ = __n;
4121 if (__ebs_ > sizeof(__extbuf_min_))
4122 {
4123 if (__always_noconv_ && __s)
4124 {
4125 __extbuf_ = (char*)__s;
4126 __owns_eb_ = false;
4127 }
4128 else
4129 {
4130 __extbuf_ = new char[__ebs_];
4131 __owns_eb_ = true;
4132 }
4133 }
4134 else
4135 {
4136 __extbuf_ = __extbuf_min_;
4137 __ebs_ = sizeof(__extbuf_min_);
4138 __owns_eb_ = false;
4139 }
4140 if (!__always_noconv_)
4141 {
4142 __ibs_ = max<streamsize>(__n, sizeof(__extbuf_min_));
4143 if (__s && __ibs_ >= sizeof(__extbuf_min_))
4144 {
4145 __intbuf_ = __s;
4146 __owns_ib_ = false;
4147 }
4148 else
4149 {
4150 __intbuf_ = new char_type[__ibs_];
4151 __owns_ib_ = true;
4152 }
4153 }
4154 else
4155 {
4156 __ibs_ = 0;
4157 __intbuf_ = 0;
4158 __owns_ib_ = false;
4159 }
4160 return this;
4161}
4162
4163template <class _Codecvt, class _Elem, class _Tr>
4164typename wbuffer_convert<_Codecvt, _Elem, _Tr>::pos_type
4165wbuffer_convert<_Codecvt, _Elem, _Tr>::seekoff(off_type __off, ios_base::seekdir __way,
4166 ios_base::openmode __om)
4167{
4168 int __width = __cv_->encoding();
4169 if (__cv_ == 0 || __bufptr_ == 0 || (__width <= 0 && __off != 0) || sync())
4170 return pos_type(off_type(-1));
4171 // __width > 0 || __off == 0
4172 switch (__way)
4173 {
4174 case ios_base::beg:
4175 break;
4176 case ios_base::cur:
4177 break;
4178 case ios_base::end:
4179 break;
4180 default:
4181 return pos_type(off_type(-1));
4182 }
4183 pos_type __r = __bufptr_->pubseekoff(__width * __off, __way, __om);
4184 __r.state(__st_);
4185 return __r;
4186}
4187
4188template <class _Codecvt, class _Elem, class _Tr>
4189typename wbuffer_convert<_Codecvt, _Elem, _Tr>::pos_type
4190wbuffer_convert<_Codecvt, _Elem, _Tr>::seekpos(pos_type __sp, ios_base::openmode __wch)
4191{
4192 if (__cv_ == 0 || __bufptr_ == 0 || sync())
4193 return pos_type(off_type(-1));
4194 if (__bufptr_->pubseekpos(__sp, __wch) == pos_type(off_type(-1)))
4195 return pos_type(off_type(-1));
4196 return __sp;
4197}
4198
4199template <class _Codecvt, class _Elem, class _Tr>
4200int
4201wbuffer_convert<_Codecvt, _Elem, _Tr>::sync()
4202{
4203 if (__cv_ == 0 || __bufptr_ == 0)
4204 return 0;
4205 if (__cm_ & ios_base::out)
4206 {
4207 if (this->pptr() != this->pbase())
4208 if (overflow() == traits_type::eof())
4209 return -1;
4210 codecvt_base::result __r;
4211 do
4212 {
4213 char* __extbe;
4214 __r = __cv_->unshift(__st_, __extbuf_, __extbuf_ + __ebs_, __extbe);
4215 streamsize __nmemb = static_cast<streamsize>(__extbe - __extbuf_);
4216 if (__bufptr_->sputn(__extbuf_, __nmemb) != __nmemb)
4217 return -1;
4218 } while (__r == codecvt_base::partial);
4219 if (__r == codecvt_base::error)
4220 return -1;
4221 if (__bufptr_->pubsync())
4222 return -1;
4223 }
4224 else if (__cm_ & ios_base::in)
4225 {
4226 off_type __c;
4227 if (__always_noconv_)
4228 __c = this->egptr() - this->gptr();
4229 else
4230 {
4231 int __width = __cv_->encoding();
4232 __c = __extbufend_ - __extbufnext_;
4233 if (__width > 0)
4234 __c += __width * (this->egptr() - this->gptr());
4235 else
4236 {
4237 if (this->gptr() != this->egptr())
4238 {
4239 reverse(this->gptr(), this->egptr());
4240 codecvt_base::result __r;
4241 const char_type* __e = this->gptr();
4242 char* __extbe;
4243 do
4244 {
4245 __r = __cv_->out(__st_, __e, this->egptr(), __e,
4246 __extbuf_, __extbuf_ + __ebs_, __extbe);
4247 switch (__r)
4248 {
4249 case codecvt_base::noconv:
4250 __c += this->egptr() - this->gptr();
4251 break;
4252 case codecvt_base::ok:
4253 case codecvt_base::partial:
4254 __c += __extbe - __extbuf_;
4255 break;
4256 default:
4257 return -1;
4258 }
4259 } while (__r == codecvt_base::partial);
4260 }
4261 }
4262 }
4263 if (__bufptr_->pubseekoff(-__c, ios_base::cur, __cm_) == pos_type(off_type(-1)))
4264 return -1;
4265 this->setg(0, 0, 0);
4266 __cm_ = 0;
4267 }
4268 return 0;
4269}
4270
4271template <class _Codecvt, class _Elem, class _Tr>
4272bool
4273wbuffer_convert<_Codecvt, _Elem, _Tr>::__read_mode()
4274{
4275 if (!(__cm_ & ios_base::in))
4276 {
4277 this->setp(0, 0);
4278 if (__always_noconv_)
4279 this->setg((char_type*)__extbuf_,
4280 (char_type*)__extbuf_ + __ebs_,
4281 (char_type*)__extbuf_ + __ebs_);
4282 else
4283 this->setg(__intbuf_, __intbuf_ + __ibs_, __intbuf_ + __ibs_);
4284 __cm_ = ios_base::in;
4285 return true;
4286 }
4287 return false;
4288}
4289
4290template <class _Codecvt, class _Elem, class _Tr>
4291void
4292wbuffer_convert<_Codecvt, _Elem, _Tr>::__write_mode()
4293{
4294 if (!(__cm_ & ios_base::out))
4295 {
4296 this->setg(0, 0, 0);
4297 if (__ebs_ > sizeof(__extbuf_min_))
4298 {
4299 if (__always_noconv_)
4300 this->setp((char_type*)__extbuf_,
4301 (char_type*)__extbuf_ + (__ebs_ - 1));
4302 else
4303 this->setp(__intbuf_, __intbuf_ + (__ibs_ - 1));
4304 }
4305 else
4306 this->setp(0, 0);
4307 __cm_ = ios_base::out;
4308 }
4309}
4310
4311template <class _Codecvt, class _Elem, class _Tr>
4312wbuffer_convert<_Codecvt, _Elem, _Tr>*
4313wbuffer_convert<_Codecvt, _Elem, _Tr>::__close()
4314{
4315 wbuffer_convert* __rt = 0;
4316 if (__cv_ != 0 && __bufptr_ != 0)
4317 {
4318 __rt = this;
4319 if ((__cm_ & ios_base::out) && sync())
4320 __rt = 0;
4321 }
4322 return __rt;
Howard Hinnant9dd7e892010-05-31 20:58:54 +00004323}
4324
Howard Hinnantc51e1022010-05-11 19:42:16 +00004325_LIBCPP_END_NAMESPACE_STD
4326
4327#endif // _LIBCPP_LOCALE