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