blob: 2c532a7241c591806b1d8f714098ba638382f6fe [file] [log] [blame]
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001// -*- C++ -*-
2//===-------------------------- locale ------------------------------------===//
3//
Howard Hinnantf5256e12010-05-11 21:36:01 +00004// The LLVM Compiler Infrastructure
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005//
Howard Hinnantb64f8b02010-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 Hinnantbc8d3f92010-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:
Howard Hinnantc9834542011-05-31 15:34:58 +000039 locale() noexcept;
40 locale(const locale& other) noexcept;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000041 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
Howard Hinnantc9834542011-05-31 15:34:58 +000048 ~locale(); // not virtual
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000049
Howard Hinnantc9834542011-05-31 15:34:58 +000050 const locale& operator=(const locale& other) noexcept;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000051
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&);
Howard Hinnantc9834542011-05-31 15:34:58 +000068template <class Facet> bool has_facet(const locale&) noexcept;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000069
70// 22.3.3, convenience interfaces:
71template <class charT> bool isspace (charT c, const locale& loc);
72template <class charT> bool isprint (charT c, const locale& loc);
73template <class charT> bool iscntrl (charT c, const locale& loc);
74template <class charT> bool isupper (charT c, const locale& loc);
75template <class charT> bool islower (charT c, const locale& loc);
76template <class charT> bool isalpha (charT c, const locale& loc);
77template <class charT> bool isdigit (charT c, const locale& loc);
78template <class charT> bool ispunct (charT c, const locale& loc);
79template <class charT> bool isxdigit(charT c, const locale& loc);
80template <class charT> bool isalnum (charT c, const locale& loc);
81template <class charT> bool isgraph (charT c, const locale& loc);
82template <class charT> charT toupper(charT c, const locale& loc);
83template <class charT> charT tolower(charT c, const locale& loc);
Howard Hinnantd23b4642010-05-31 20:58:54 +000084
85template<class Codecvt, class Elem = wchar_t,
86 class Wide_alloc = allocator<Elem>,
87 class Byte_alloc = allocator<char>>
88class wstring_convert
89{
90public:
91 typedef basic_string<char, char_traits<char>, Byte_alloc> byte_string;
92 typedef basic_string<Elem, char_traits<Elem>, Wide_alloc> wide_string;
93 typedef typename Codecvt::state_type state_type;
94 typedef typename wide_string::traits_type::int_type int_type;
95
96 wstring_convert(Codecvt* pcvt = new Codecvt);
97 wstring_convert(Codecvt* pcvt, state_type state);
98 wstring_convert(const byte_string& byte_err,
99 const wide_string& wide_err = wide_string());
100 ~wstring_convert();
101
102 wide_string from_bytes(char byte);
103 wide_string from_bytes(const char* ptr);
104 wide_string from_bytes(const byte_string& str);
105 wide_string from_bytes(const char* first, const char* last);
106
107 byte_string to_bytes(Elem wchar);
108 byte_string to_bytes(const Elem* wptr);
109 byte_string to_bytes(const wide_string& wstr);
110 byte_string to_bytes(const Elem* first, const Elem* last);
111
112 size_t converted() const;
113 state_type state() const;
114};
115
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000116template <class Codecvt, class Elem = wchar_t, class Tr = char_traits<Elem>>
Howard Hinnantd23b4642010-05-31 20:58:54 +0000117class wbuffer_convert
118 : public basic_streambuf<Elem, Tr>
119{
120public:
121 typedef typename Tr::state_type state_type;
122
123 wbuffer_convert(streambuf* bytebuf = 0, Codecvt* pcvt = new Codecvt,
124 state_type state = state_type());
125
126 streambuf* rdbuf() const;
127 streambuf* rdbuf(streambuf* bytebuf);
128
129 state_type state() const;
130};
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000131
132// 22.4.1 and 22.4.1.3, ctype:
133class ctype_base;
134template <class charT> class ctype;
135template <> class ctype<char>; // specialization
136template <class charT> class ctype_byname;
137template <> class ctype_byname<char>; // specialization
138
139class codecvt_base;
140template <class internT, class externT, class stateT> class codecvt;
141template <class internT, class externT, class stateT> class codecvt_byname;
142
143// 22.4.2 and 22.4.3, numeric:
144template <class charT, class InputIterator> class num_get;
145template <class charT, class OutputIterator> class num_put;
146template <class charT> class numpunct;
147template <class charT> class numpunct_byname;
148
149// 22.4.4, col lation:
150template <class charT> class collate;
151template <class charT> class collate_byname;
152
153// 22.4.5, date and time:
154class time_base;
155template <class charT, class InputIterator> class time_get;
156template <class charT, class InputIterator> class time_get_byname;
157template <class charT, class OutputIterator> class time_put;
158template <class charT, class OutputIterator> class time_put_byname;
159
160// 22.4.6, money:
161class money_base;
162template <class charT, class InputIterator> class money_get;
163template <class charT, class OutputIterator> class money_put;
164template <class charT, bool Intl> class moneypunct;
165template <class charT, bool Intl> class moneypunct_byname;
166
167// 22.4.7, message retrieval:
168class messages_base;
169template <class charT> class messages;
170template <class charT> class messages_byname;
171
172} // std
173
174*/
175
176#include <__config>
177#include <__locale>
178#include <algorithm>
179#include <memory>
180#include <ios>
181#include <streambuf>
182#include <iterator>
183#include <limits>
Howard Hinnantadff4892010-05-24 17:49:41 +0000184#if !__APPLE__
185#include <cstdarg>
186#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000187#include <cstdlib>
188#include <ctime>
Howard Hinnant92a07002011-09-22 19:10:18 +0000189#if !_WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000190#include <nl_types.h>
Howard Hinnant92a07002011-09-22 19:10:18 +0000191#endif // !_WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000192
193#pragma GCC system_header
194
195_LIBCPP_BEGIN_NAMESPACE_STD
196
Sean Hunte59f7242011-07-09 01:09:31 +0000197#ifndef _LIBCPP_STABLE_APPLE_ABI
Sean Hunt62a6ac32011-07-09 00:56:23 +0000198// Get the C locale object
199locale_t __cloc();
Sean Hunte59f7242011-07-09 01:09:31 +0000200#endif
Sean Hunt62a6ac32011-07-09 00:56:23 +0000201
Sean Huntf3907e62011-07-15 05:40:33 +0000202typedef _VSTD::remove_pointer<locale_t>::type __locale_struct;
203typedef _VSTD::unique_ptr<__locale_struct, decltype(&freelocale)> __locale_unique_ptr;
204typedef _VSTD::unique_ptr<__locale_struct, decltype(&uselocale)> __locale_raii;
205
Howard Hinnantadff4892010-05-24 17:49:41 +0000206// OSX has nice foo_l() functions that let you turn off use of the global
207// locale. Linux, not so much. The following functions avoid the locale when
208// that's possible and otherwise do the wrong thing. FIXME.
Howard Hinnantbcbbd4d2011-07-15 14:46:11 +0000209#ifndef _LIBCPP_STABLE_APPLE_ABI
Sean Huntf3907e62011-07-15 05:40:33 +0000210
211#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
212decltype(MB_CUR_MAX_L(_VSTD::declval<locale_t>()))
Howard Hinnant82894812010-09-22 16:48:34 +0000213inline _LIBCPP_INLINE_VISIBILITY
Sean Huntf3907e62011-07-15 05:40:33 +0000214__mb_cur_max_l(locale_t __l)
Howard Hinnantadff4892010-05-24 17:49:41 +0000215{
Sean Huntf3907e62011-07-15 05:40:33 +0000216 return MB_CUR_MAX_L(__l);
217}
218#else // _LIBCPP_LOCALE__L_EXTENSIONS
219_LIBCPP_ALWAYS_INLINE inline
220decltype(MB_CUR_MAX) __mb_cur_max_l(locale_t __l)
221{
222 __locale_raii __current(uselocale(__l), uselocale);
223 return MB_CUR_MAX;
224}
225#endif // _LIBCPP_LOCALE__L_EXTENSIONS
226
227_LIBCPP_ALWAYS_INLINE inline
228wint_t __btowc_l(int __c, locale_t __l)
229{
230#ifdef _LIBCPP_STABLE_APPLE_ABI
231 return btowc_l(__c, __l);
232#else
233 __locale_raii __current(uselocale(__l), uselocale);
234 return btowc(__c);
235#endif
Sean Huntc97da3a2011-07-13 06:40:50 +0000236}
Howard Hinnant8d756322011-07-13 15:48:16 +0000237
Sean Huntf3907e62011-07-15 05:40:33 +0000238_LIBCPP_ALWAYS_INLINE inline
239int __wctob_l(wint_t __c, locale_t __l)
Sean Huntc97da3a2011-07-13 06:40:50 +0000240{
Sean Huntf3907e62011-07-15 05:40:33 +0000241#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
242 return wctob_l(__c, __l);
243#else
244 __locale_raii __current(uselocale(__l), uselocale);
245 return wctob(__c);
246#endif
Sean Huntc97da3a2011-07-13 06:40:50 +0000247}
Sean Huntf3907e62011-07-15 05:40:33 +0000248
249_LIBCPP_ALWAYS_INLINE inline
250size_t __wcsnrtombs_l(char *__dest, const wchar_t **__src, size_t __nwc,
251 size_t __len, mbstate_t *__ps, locale_t __l)
252{
253#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
254 return wcsnrtombs_l(__dest, __src, __nwc, __len, __ps, __l);
255#else
256 __locale_raii __current(uselocale(__l), uselocale);
257 return wcsnrtombs(__dest, __src, __nwc, __len, __ps);
258#endif
259}
260
261_LIBCPP_ALWAYS_INLINE inline
262size_t __wcrtomb_l(char *__s, wchar_t __wc, mbstate_t *__ps, locale_t __l)
263{
264#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
265 return wcrtomb_l(__s, __wc, __ps, __l);
266#else
267 __locale_raii __current(uselocale(__l), uselocale);
268 return wcrtomb(__s, __wc, __ps);
269#endif
270}
271
272_LIBCPP_ALWAYS_INLINE inline
273size_t __mbsnrtowcs_l(wchar_t * __dest, const char **__src, size_t __nms,
274 size_t __len, mbstate_t *__ps, locale_t __l)
275{
276#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
David Chisnallc512df12011-09-21 08:39:44 +0000277 return mbsnrtowcs_l(__dest, __src, __nms, __len, __ps, __l);
Sean Huntf3907e62011-07-15 05:40:33 +0000278#else
279 __locale_raii __current(uselocale(__l), uselocale);
280 return mbsnrtowcs(__dest, __src, __nms, __len, __ps);
281#endif
282}
283
284_LIBCPP_ALWAYS_INLINE inline
285size_t __mbrtowc_l(wchar_t *__pwc, const char *__s, size_t __n,
286 mbstate_t *__ps, locale_t __l)
287{
288#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
289 return mbrtowc_l(__pwc, __s, __n, __ps, __l);
290#else
291 __locale_raii __current(uselocale(__l), uselocale);
292 return mbrtowc(__pwc, __s, __n, __ps);
293#endif
294}
295
296_LIBCPP_ALWAYS_INLINE inline
297int __mbtowc_l(wchar_t *__pwc, const char *__pmb, size_t __max, locale_t __l)
298{
299#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
David Chisnallc512df12011-09-21 08:39:44 +0000300 return mbtowc_l(__pwc, __pmb, __max, __l);
Sean Huntf3907e62011-07-15 05:40:33 +0000301#else
302 __locale_raii __current(uselocale(__l), uselocale);
303 return mbtowc(__pwc, __pmb, __max);
304#endif
305}
306
307_LIBCPP_ALWAYS_INLINE inline
308size_t __mbrlen_l(const char *__s, size_t __n, mbstate_t *__ps, locale_t __l)
309{
310#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
311 return mbrlen_l(__s, __n, __ps, __l);
312#else
313 __locale_raii __current(uselocale(__l), uselocale);
314 return mbrlen(__s, __n, __ps);
315#endif
316}
317
318_LIBCPP_ALWAYS_INLINE inline
319lconv *__localeconv_l(locale_t __l)
320{
321#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
322 return localeconv_l(__l);
323#else
324 __locale_raii __current(uselocale(__l), uselocale);
325 return localeconv();
326#endif
327}
328
329_LIBCPP_ALWAYS_INLINE inline
330size_t __mbsrtowcs_l(wchar_t *__dest, const char **__src, size_t __len,
331 mbstate_t *__ps, locale_t __l)
332{
333#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
334 return mbsrtowcs_l(__dest, __src, __len, __ps, __l);
335#else
336 __locale_raii __current(uselocale(__l), uselocale);
337 return mbsrtowcs(__dest, __src, __len, __ps);
338#endif
339}
340
341_LIBCPP_ALWAYS_INLINE inline
342int __sprintf_l(char *__s, locale_t __l, const char *__format, ...) {
343 va_list __va;
344 va_start(__va, __format);
345#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
346 int __res = vsprintf_l(__s, __l, __format, __va);
347#else
348 __locale_raii __current(uselocale(__l), uselocale);
349 int __res = vsprintf(__s, __format, __va);
350#endif
351 va_end(__va);
352 return __res;
353}
354
355_LIBCPP_ALWAYS_INLINE inline
356int __snprintf_l(char *__s, size_t __n, locale_t __l, const char *__format, ...) {
357 va_list __va;
358 va_start(__va, __format);
359#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
360 int __res = vsnprintf_l(__s, __n, __l, __format, __va);
361#else
362 __locale_raii __current(uselocale(__l), uselocale);
363 int __res = vsnprintf(__s, __n, __format, __va);
364#endif
365 va_end(__va);
366 return __res;
367}
368
369_LIBCPP_ALWAYS_INLINE inline
370int __asprintf_l(char **__s, locale_t __l, const char *__format, ...) {
371 va_list __va;
372 va_start(__va, __format);
373#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
374 int __res = vasprintf_l(__s, __l, __format, __va);
375#else
376 __locale_raii __current(uselocale(__l), uselocale);
377 int __res = vasprintf(__s, __format, __va);
378#endif
379 va_end(__va);
380 return __res;
381}
382
383_LIBCPP_ALWAYS_INLINE inline
384int __sscanf_l(const char *__s, locale_t __l, const char *__format, ...) {
385 va_list __va;
386 va_start(__va, __format);
387#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
388 int __res = vsscanf_l(__s, __l, __format, __va);
389#else
390 __locale_raii __current(uselocale(__l), uselocale);
391 int __res = vsscanf(__s, __format, __va);
392#endif
393 va_end(__va);
394 return __res;
395}
396
397#endif // _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantadff4892010-05-24 17:49:41 +0000398
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000399// __scan_keyword
400// Scans [__b, __e) until a match is found in the basic_strings range
401// [__kb, __ke) or until it can be shown that there is no match in [__kb, __ke).
402// __b will be incremented (visibly), consuming CharT until a match is found
403// or proved to not exist. A keyword may be "", in which will match anything.
404// If one keyword is a prefix of another, and the next CharT in the input
405// might match another keyword, the algorithm will attempt to find the longest
406// matching keyword. If the longer matching keyword ends up not matching, then
407// no keyword match is found. If no keyword match is found, __ke is returned
408// and failbit is set in __err.
409// Else an iterator pointing to the matching keyword is found. If more than
410// one keyword matches, an iterator to the first matching keyword is returned.
411// If on exit __b == __e, eofbit is set in __err. If __case_senstive is false,
412// __ct is used to force to lower case before comparing characters.
413// Examples:
414// Keywords: "a", "abb"
415// If the input is "a", the first keyword matches and eofbit is set.
416// If the input is "abc", no match is found and "ab" are consumed.
417template <class _InputIterator, class _ForwardIterator, class _Ctype>
418_LIBCPP_HIDDEN
419_ForwardIterator
420__scan_keyword(_InputIterator& __b, _InputIterator __e,
421 _ForwardIterator __kb, _ForwardIterator __ke,
422 const _Ctype& __ct, ios_base::iostate& __err,
423 bool __case_sensitive = true)
424{
425 typedef typename iterator_traits<_InputIterator>::value_type _CharT;
Howard Hinnant0949eed2011-06-30 21:18:19 +0000426 size_t __nkw = _VSTD::distance(__kb, __ke);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000427 const unsigned char __doesnt_match = '\0';
428 const unsigned char __might_match = '\1';
429 const unsigned char __does_match = '\2';
430 unsigned char __statbuf[100];
431 unsigned char* __status = __statbuf;
432 unique_ptr<unsigned char, void(*)(void*)> __stat_hold(0, free);
433 if (__nkw > sizeof(__statbuf))
434 {
435 __status = (unsigned char*)malloc(__nkw);
436 if (__status == 0)
437 __throw_bad_alloc();
438 __stat_hold.reset(__status);
439 }
440 size_t __n_might_match = __nkw; // At this point, any keyword might match
441 size_t __n_does_match = 0; // but none of them definitely do
442 // Initialize all statuses to __might_match, except for "" keywords are __does_match
443 unsigned char* __st = __status;
444 for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, ++__st)
445 {
446 if (!__ky->empty())
447 *__st = __might_match;
448 else
449 {
450 *__st = __does_match;
451 --__n_might_match;
452 ++__n_does_match;
453 }
454 }
455 // While there might be a match, test keywords against the next CharT
456 for (size_t __indx = 0; __b != __e && __n_might_match > 0; ++__indx)
457 {
458 // Peek at the next CharT but don't consume it
459 _CharT __c = *__b;
460 if (!__case_sensitive)
461 __c = __ct.toupper(__c);
462 bool __consume = false;
463 // For each keyword which might match, see if the __indx character is __c
464 // If a match if found, consume __c
465 // If a match is found, and that is the last character in the keyword,
466 // then that keyword matches.
467 // If the keyword doesn't match this character, then change the keyword
468 // to doesn't match
469 __st = __status;
470 for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, ++__st)
471 {
472 if (*__st == __might_match)
473 {
474 _CharT __kc = (*__ky)[__indx];
475 if (!__case_sensitive)
476 __kc = __ct.toupper(__kc);
477 if (__c == __kc)
478 {
479 __consume = true;
480 if (__ky->size() == __indx+1)
481 {
482 *__st = __does_match;
483 --__n_might_match;
484 ++__n_does_match;
485 }
486 }
487 else
488 {
489 *__st = __doesnt_match;
490 --__n_might_match;
491 }
492 }
493 }
494 // consume if we matched a character
495 if (__consume)
496 {
497 ++__b;
498 // If we consumed a character and there might be a matched keyword that
499 // was marked matched on a previous iteration, then such keywords
500 // which are now marked as not matching.
501 if (__n_might_match + __n_does_match > 1)
502 {
503 __st = __status;
504 for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, ++__st)
505 {
506 if (*__st == __does_match && __ky->size() != __indx+1)
507 {
508 *__st = __doesnt_match;
509 --__n_does_match;
510 }
511 }
512 }
513 }
514 }
515 // We've exited the loop because we hit eof and/or we have no more "might matches".
516 if (__b == __e)
517 __err |= ios_base::eofbit;
518 // Return the first matching result
519 for (__st = __status; __kb != __ke; ++__kb, ++__st)
520 if (*__st == __does_match)
521 break;
522 if (__kb == __ke)
523 __err |= ios_base::failbit;
524 return __kb;
525}
526
527struct __num_get_base
528{
529 static const int __num_get_buf_sz = 40;
530
531 static int __get_base(ios_base&);
532 static const char __src[33];
533};
534
535void __check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
536 ios_base::iostate& __err);
537
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000538template <class _CharT>
539struct __num_get
540 : protected __num_get_base
541{
542 static string __stage2_int_prep(ios_base& __iob, _CharT* __atoms, _CharT& __thousands_sep);
543 static string __stage2_float_prep(ios_base& __iob, _CharT* __atoms, _CharT& __decimal_point,
544 _CharT& __thousands_sep);
545 static int __stage2_int_loop(_CharT __ct, int __base, char* __a, char*& __a_end,
546 unsigned& __dc, _CharT __thousands_sep, const string& __grouping,
547 unsigned* __g, unsigned*& __g_end, _CharT* __atoms);
548 static int __stage2_float_loop(_CharT __ct, bool& __in_units, char& __exp,
549 char* __a, char*& __a_end,
550 _CharT __decimal_point, _CharT __thousands_sep,
551 const string& __grouping, unsigned* __g,
552 unsigned*& __g_end, unsigned& __dc, _CharT* __atoms);
553};
554
555template <class _CharT>
556string
557__num_get<_CharT>::__stage2_int_prep(ios_base& __iob, _CharT* __atoms, _CharT& __thousands_sep)
558{
559 locale __loc = __iob.getloc();
560 use_facet<ctype<_CharT> >(__loc).widen(__src, __src + 26, __atoms);
561 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
562 __thousands_sep = __np.thousands_sep();
563 return __np.grouping();
564}
565
566template <class _CharT>
567string
568__num_get<_CharT>::__stage2_float_prep(ios_base& __iob, _CharT* __atoms, _CharT& __decimal_point,
569 _CharT& __thousands_sep)
570{
571 locale __loc = __iob.getloc();
572 use_facet<ctype<_CharT> >(__loc).widen(__src, __src + 32, __atoms);
573 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
574 __decimal_point = __np.decimal_point();
575 __thousands_sep = __np.thousands_sep();
576 return __np.grouping();
577}
578
579template <class _CharT>
580int
581__num_get<_CharT>::__stage2_int_loop(_CharT __ct, int __base, char* __a, char*& __a_end,
582 unsigned& __dc, _CharT __thousands_sep, const string& __grouping,
583 unsigned* __g, unsigned*& __g_end, _CharT* __atoms)
584{
Howard Hinnant80586722011-03-09 01:03:19 +0000585 if (__a_end == __a && (__ct == __atoms[24] || __ct == __atoms[25]))
586 {
587 *__a_end++ = __ct == __atoms[24] ? '+' : '-';
588 __dc = 0;
589 return 0;
590 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000591 if (__ct == __thousands_sep && __grouping.size() != 0)
592 {
593 if (__g_end-__g < __num_get_buf_sz)
594 {
595 *__g_end++ = __dc;
596 __dc = 0;
597 }
598 return 0;
599 }
600 ptrdiff_t __f = find(__atoms, __atoms + 26, __ct) - __atoms;
Howard Hinnant80586722011-03-09 01:03:19 +0000601 if (__f >= 24)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000602 return -1;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000603 switch (__base)
604 {
605 case 8:
606 case 10:
607 if (__f >= __base)
Howard Hinnant80586722011-03-09 01:03:19 +0000608 return -1;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000609 break;
Howard Hinnant80586722011-03-09 01:03:19 +0000610 case 16:
611 if (__f < 22)
612 break;
613 if (__a_end != __a && __a_end - __a <= 2 && __a_end[-1] == '0')
614 {
615 __dc = 0;
616 *__a_end++ = __src[__f];
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000617 return 0;
Howard Hinnant80586722011-03-09 01:03:19 +0000618 }
619 return -1;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000620 }
Howard Hinnant80586722011-03-09 01:03:19 +0000621 if (__a_end-__a < __num_get_buf_sz - 1)
622 *__a_end++ = __src[__f];
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000623 ++__dc;
624 return 0;
625}
626
627template <class _CharT>
628int
629__num_get<_CharT>::__stage2_float_loop(_CharT __ct, bool& __in_units, char& __exp, char* __a, char*& __a_end,
630 _CharT __decimal_point, _CharT __thousands_sep, const string& __grouping,
631 unsigned* __g, unsigned*& __g_end, unsigned& __dc, _CharT* __atoms)
632{
633 if (__ct == __decimal_point)
634 {
635 if (!__in_units)
636 return -1;
637 __in_units = false;
638 *__a_end++ = '.';
639 if (__grouping.size() != 0 && __g_end-__g < __num_get_buf_sz)
640 *__g_end++ = __dc;
641 return 0;
642 }
643 if (__ct == __thousands_sep && __grouping.size() != 0)
644 {
645 if (!__in_units)
646 return -1;
647 if (__g_end-__g < __num_get_buf_sz)
648 {
649 *__g_end++ = __dc;
650 __dc = 0;
651 }
652 return 0;
653 }
654 ptrdiff_t __f = find(__atoms, __atoms + 32, __ct) - __atoms;
655 if (__f >= 32)
656 return -1;
657 char __x = __src[__f];
658 if (__a_end-__a < __num_get_buf_sz - 1)
659 *__a_end++ = __x;
660 if (__x == 'x' || __x == 'X')
661 __exp = 'P';
662 else if ((__x & 0xDF) == __exp)
663 {
664 __in_units = false;
665 if (__grouping.size() != 0 && __g_end-__g < __num_get_buf_sz)
666 *__g_end++ = __dc;
667 }
668 if (__f >= 22)
669 return 0;
670 ++__dc;
671 return 0;
672}
673
674extern template class __num_get<char>;
675extern template class __num_get<wchar_t>;
676
677template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +0000678class _LIBCPP_VISIBLE num_get
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000679 : public locale::facet,
680 private __num_get<_CharT>
681{
682public:
683 typedef _CharT char_type;
684 typedef _InputIterator iter_type;
685
686 _LIBCPP_ALWAYS_INLINE
687 explicit num_get(size_t __refs = 0)
688 : locale::facet(__refs) {}
689
690 _LIBCPP_ALWAYS_INLINE
691 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
692 ios_base::iostate& __err, bool& __v) const
693 {
694 return do_get(__b, __e, __iob, __err, __v);
695 }
696
697 _LIBCPP_ALWAYS_INLINE
698 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
699 ios_base::iostate& __err, long& __v) const
700 {
701 return do_get(__b, __e, __iob, __err, __v);
702 }
703
704 _LIBCPP_ALWAYS_INLINE
705 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
706 ios_base::iostate& __err, long long& __v) const
707 {
708 return do_get(__b, __e, __iob, __err, __v);
709 }
710
711 _LIBCPP_ALWAYS_INLINE
712 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
713 ios_base::iostate& __err, unsigned short& __v) const
714 {
715 return do_get(__b, __e, __iob, __err, __v);
716 }
717
718 _LIBCPP_ALWAYS_INLINE
719 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
720 ios_base::iostate& __err, unsigned int& __v) const
721 {
722 return do_get(__b, __e, __iob, __err, __v);
723 }
724
725 _LIBCPP_ALWAYS_INLINE
726 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
727 ios_base::iostate& __err, unsigned long& __v) const
728 {
729 return do_get(__b, __e, __iob, __err, __v);
730 }
731
732 _LIBCPP_ALWAYS_INLINE
733 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
734 ios_base::iostate& __err, unsigned long long& __v) const
735 {
736 return do_get(__b, __e, __iob, __err, __v);
737 }
738
739 _LIBCPP_ALWAYS_INLINE
740 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
741 ios_base::iostate& __err, float& __v) const
742 {
743 return do_get(__b, __e, __iob, __err, __v);
744 }
745
746 _LIBCPP_ALWAYS_INLINE
747 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
748 ios_base::iostate& __err, double& __v) const
749 {
750 return do_get(__b, __e, __iob, __err, __v);
751 }
752
753 _LIBCPP_ALWAYS_INLINE
754 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
755 ios_base::iostate& __err, long double& __v) const
756 {
757 return do_get(__b, __e, __iob, __err, __v);
758 }
759
760 _LIBCPP_ALWAYS_INLINE
761 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
762 ios_base::iostate& __err, void*& __v) const
763 {
764 return do_get(__b, __e, __iob, __err, __v);
765 }
766
767 static locale::id id;
768
769protected:
Howard Hinnant82894812010-09-22 16:48:34 +0000770 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000771 ~num_get() {}
772
773 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
774 ios_base::iostate& __err, bool& __v) const;
775 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
776 ios_base::iostate& __err, long& __v) const;
777 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
778 ios_base::iostate& __err, long long& __v) const;
779 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
780 ios_base::iostate& __err, unsigned short& __v) const;
781 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
782 ios_base::iostate& __err, unsigned int& __v) const;
783 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
784 ios_base::iostate& __err, unsigned long& __v) const;
785 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
786 ios_base::iostate& __err, unsigned long long& __v) const;
787 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
788 ios_base::iostate& __err, float& __v) const;
789 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
790 ios_base::iostate& __err, double& __v) const;
791 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
792 ios_base::iostate& __err, long double& __v) const;
793 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
794 ios_base::iostate& __err, void*& __v) const;
795};
796
797template <class _CharT, class _InputIterator>
798locale::id
799num_get<_CharT, _InputIterator>::id;
800
801template <class _Tp>
802_Tp
803__num_get_signed_integral(const char* __a, const char* __a_end,
804 ios_base::iostate& __err, int __base)
805{
806 if (__a != __a_end)
807 {
Howard Hinnante7c8da62011-02-25 19:52:41 +0000808 int __save_errno = errno;
809 errno = 0;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000810 char *__p2;
Howard Hinnant9a207812011-07-15 14:25:40 +0000811#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000812 long long __ll = strtoll_l(__a, &__p2, __base, 0);
Sean Huntf3907e62011-07-15 05:40:33 +0000813#else
814 long long __ll = strtoll_l(__a, &__p2, __base, __cloc());
815#endif
Howard Hinnante7c8da62011-02-25 19:52:41 +0000816 int __current_errno = errno;
817 if (__current_errno == 0)
818 errno = __save_errno;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000819 if (__p2 != __a_end)
820 {
821 __err = ios_base::failbit;
822 return 0;
823 }
Howard Hinnante7c8da62011-02-25 19:52:41 +0000824 else if (__current_errno == ERANGE ||
825 __ll < numeric_limits<_Tp>::min() ||
826 numeric_limits<_Tp>::max() < __ll)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000827 {
828 __err = ios_base::failbit;
Howard Hinnante7c8da62011-02-25 19:52:41 +0000829 if (__ll > 0)
830 return numeric_limits<_Tp>::max();
831 else
832 return numeric_limits<_Tp>::min();
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000833 }
834 return static_cast<_Tp>(__ll);
835 }
836 __err = ios_base::failbit;
837 return 0;
838}
839
840template <class _Tp>
841_Tp
842__num_get_unsigned_integral(const char* __a, const char* __a_end,
843 ios_base::iostate& __err, int __base)
844{
845 if (__a != __a_end)
846 {
Howard Hinnante7c8da62011-02-25 19:52:41 +0000847 if (*__a == '-')
848 {
849 __err = ios_base::failbit;
850 return 0;
851 }
852 int __save_errno = errno;
853 errno = 0;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000854 char *__p2;
Howard Hinnant9a207812011-07-15 14:25:40 +0000855#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000856 unsigned long long __ll = strtoull_l(__a, &__p2, __base, 0);
Sean Huntf3907e62011-07-15 05:40:33 +0000857#else
858 unsigned long long __ll = strtoull_l(__a, &__p2, __base, __cloc());
859#endif
Howard Hinnante7c8da62011-02-25 19:52:41 +0000860 int __current_errno = errno;
861 if (__current_errno == 0)
862 errno = __save_errno;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000863 if (__p2 != __a_end)
864 {
865 __err = ios_base::failbit;
866 return 0;
867 }
Howard Hinnante7c8da62011-02-25 19:52:41 +0000868 else if (__current_errno == ERANGE ||
869 numeric_limits<_Tp>::max() < __ll)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000870 {
871 __err = ios_base::failbit;
872 return numeric_limits<_Tp>::max();
873 }
874 return static_cast<_Tp>(__ll);
875 }
876 __err = ios_base::failbit;
877 return 0;
878}
879
880template <class _Tp>
881_Tp
882__num_get_float(const char* __a, const char* __a_end, ios_base::iostate& __err)
883{
884 if (__a != __a_end)
885 {
886 char *__p2;
Howard Hinnant9a207812011-07-15 14:25:40 +0000887#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000888 long double __ld = strtold_l(__a, &__p2, 0);
Sean Huntf3907e62011-07-15 05:40:33 +0000889#else
890 long double __ld = strtold_l(__a, &__p2, __cloc());
891#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000892 if (__p2 != __a_end)
893 {
894 __err = ios_base::failbit;
895 return 0;
896 }
897 return static_cast<_Tp>(__ld);
898 }
899 __err = ios_base::failbit;
900 return 0;
901}
902
903template <class _CharT, class _InputIterator>
904_InputIterator
905num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
906 ios_base& __iob,
907 ios_base::iostate& __err,
908 bool& __v) const
909{
910 if ((__iob.flags() & ios_base::boolalpha) == 0)
911 {
912 long __lv = -1;
913 __b = do_get(__b, __e, __iob, __err, __lv);
914 switch (__lv)
915 {
916 case 0:
917 __v = false;
918 break;
919 case 1:
920 __v = true;
921 break;
922 default:
923 __v = true;
924 __err = ios_base::failbit;
925 break;
926 }
927 return __b;
928 }
929 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__iob.getloc());
930 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__iob.getloc());
931 typedef typename numpunct<_CharT>::string_type string_type;
932 const string_type __names[2] = {__np.truename(), __np.falsename()};
933 const string_type* __i = __scan_keyword(__b, __e, __names, __names+2,
934 __ct, __err);
935 __v = __i == __names;
936 return __b;
937}
938
939template <class _CharT, class _InputIterator>
940_InputIterator
941num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
942 ios_base& __iob,
943 ios_base::iostate& __err,
944 long& __v) const
945{
946 // Stage 1
947 int __base = this->__get_base(__iob);
948 // Stage 2
949 char_type __atoms[26];
950 char_type __thousands_sep;
951 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
952 char __a[__num_get_base::__num_get_buf_sz] = {0};
953 char* __a_end = __a;
954 unsigned __g[__num_get_base::__num_get_buf_sz];
955 unsigned* __g_end = __g;
956 unsigned __dc = 0;
957 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +0000958 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000959 __thousands_sep, __grouping, __g, __g_end,
960 __atoms))
961 break;
962 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
963 *__g_end++ = __dc;
964 // Stage 3
965 __v = __num_get_signed_integral<long>(__a, __a_end, __err, __base);
966 // Digit grouping checked
967 __check_grouping(__grouping, __g, __g_end, __err);
968 // EOF checked
969 if (__b == __e)
970 __err |= ios_base::eofbit;
971 return __b;
972}
973
974template <class _CharT, class _InputIterator>
975_InputIterator
976num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
977 ios_base& __iob,
978 ios_base::iostate& __err,
979 long long& __v) const
980{
981 // Stage 1
982 int __base = this->__get_base(__iob);
983 // Stage 2
984 char_type __atoms[26];
985 char_type __thousands_sep;
986 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
987 char __a[__num_get_base::__num_get_buf_sz] = {0};
988 char* __a_end = __a;
989 unsigned __g[__num_get_base::__num_get_buf_sz];
990 unsigned* __g_end = __g;
991 unsigned __dc = 0;
992 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +0000993 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
994 __thousands_sep, __grouping, __g, __g_end,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000995 __atoms))
996 break;
997 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
998 *__g_end++ = __dc;
999 // Stage 3
1000 __v = __num_get_signed_integral<long long>(__a, __a_end, __err, __base);
1001 // Digit grouping checked
1002 __check_grouping(__grouping, __g, __g_end, __err);
1003 // EOF checked
1004 if (__b == __e)
1005 __err |= ios_base::eofbit;
1006 return __b;
1007}
1008
1009template <class _CharT, class _InputIterator>
1010_InputIterator
1011num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1012 ios_base& __iob,
1013 ios_base::iostate& __err,
1014 unsigned short& __v) const
1015{
1016 // Stage 1
1017 int __base = this->__get_base(__iob);
1018 // Stage 2
1019 char_type __atoms[26];
1020 char_type __thousands_sep;
1021 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
1022 char __a[__num_get_base::__num_get_buf_sz] = {0};
1023 char* __a_end = __a;
1024 unsigned __g[__num_get_base::__num_get_buf_sz];
1025 unsigned* __g_end = __g;
1026 unsigned __dc = 0;
1027 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001028 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001029 __thousands_sep, __grouping, __g, __g_end,
1030 __atoms))
1031 break;
1032 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
1033 *__g_end++ = __dc;
1034 // Stage 3
1035 __v = __num_get_unsigned_integral<unsigned short>(__a, __a_end, __err, __base);
1036 // Digit grouping checked
1037 __check_grouping(__grouping, __g, __g_end, __err);
1038 // EOF checked
1039 if (__b == __e)
1040 __err |= ios_base::eofbit;
1041 return __b;
1042}
1043
1044template <class _CharT, class _InputIterator>
1045_InputIterator
1046num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1047 ios_base& __iob,
1048 ios_base::iostate& __err,
1049 unsigned int& __v) const
1050{
1051 // Stage 1
1052 int __base = this->__get_base(__iob);
1053 // Stage 2
1054 char_type __atoms[26];
1055 char_type __thousands_sep;
1056 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
1057 char __a[__num_get_base::__num_get_buf_sz] = {0};
1058 char* __a_end = __a;
1059 unsigned __g[__num_get_base::__num_get_buf_sz];
1060 unsigned* __g_end = __g;
1061 unsigned __dc = 0;
1062 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001063 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001064 __thousands_sep, __grouping, __g, __g_end,
1065 __atoms))
1066 break;
1067 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
1068 *__g_end++ = __dc;
1069 // Stage 3
1070 __v = __num_get_unsigned_integral<unsigned int>(__a, __a_end, __err, __base);
1071 // Digit grouping checked
1072 __check_grouping(__grouping, __g, __g_end, __err);
1073 // EOF checked
1074 if (__b == __e)
1075 __err |= ios_base::eofbit;
1076 return __b;
1077}
1078
1079template <class _CharT, class _InputIterator>
1080_InputIterator
1081num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1082 ios_base& __iob,
1083 ios_base::iostate& __err,
1084 unsigned long& __v) const
1085{
1086 // Stage 1
1087 int __base = this->__get_base(__iob);
1088 // Stage 2
1089 char_type __atoms[26];
1090 char_type __thousands_sep;
1091 string __grouping = this->__stage2_int_prep(__iob, __atoms, __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 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001098 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001099 __thousands_sep, __grouping, __g, __g_end,
1100 __atoms))
1101 break;
1102 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
1103 *__g_end++ = __dc;
1104 // Stage 3
1105 __v = __num_get_unsigned_integral<unsigned long>(__a, __a_end, __err, __base);
1106 // Digit grouping checked
1107 __check_grouping(__grouping, __g, __g_end, __err);
1108 // EOF checked
1109 if (__b == __e)
1110 __err |= ios_base::eofbit;
1111 return __b;
1112}
1113
1114template <class _CharT, class _InputIterator>
1115_InputIterator
1116num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1117 ios_base& __iob,
1118 ios_base::iostate& __err,
1119 unsigned long long& __v) const
1120{
1121 // Stage 1
1122 int __base = this->__get_base(__iob);
1123 // Stage 2
1124 char_type __atoms[26];
1125 char_type __thousands_sep;
1126 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
1127 char __a[__num_get_base::__num_get_buf_sz] = {0};
1128 char* __a_end = __a;
1129 unsigned __g[__num_get_base::__num_get_buf_sz];
1130 unsigned* __g_end = __g;
1131 unsigned __dc = 0;
1132 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001133 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001134 __thousands_sep, __grouping, __g, __g_end,
1135 __atoms))
1136 break;
1137 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
1138 *__g_end++ = __dc;
1139 // Stage 3
1140 __v = __num_get_unsigned_integral<unsigned long long>(__a, __a_end, __err, __base);
1141 // Digit grouping checked
1142 __check_grouping(__grouping, __g, __g_end, __err);
1143 // EOF checked
1144 if (__b == __e)
1145 __err |= ios_base::eofbit;
1146 return __b;
1147}
1148
1149template <class _CharT, class _InputIterator>
1150_InputIterator
1151num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1152 ios_base& __iob,
1153 ios_base::iostate& __err,
1154 float& __v) const
1155{
1156 // Stage 1, nothing to do
1157 // Stage 2
1158 char_type __atoms[32];
1159 char_type __decimal_point;
1160 char_type __thousands_sep;
Howard Hinnant324bb032010-08-22 00:02:43 +00001161 string __grouping = this->__stage2_float_prep(__iob, __atoms,
1162 __decimal_point,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001163 __thousands_sep);
1164 char __a[__num_get_base::__num_get_buf_sz] = {0};
1165 char* __a_end = __a;
1166 unsigned __g[__num_get_base::__num_get_buf_sz];
1167 unsigned* __g_end = __g;
1168 unsigned __dc = 0;
1169 bool __in_units = true;
1170 char __exp = 'E';
1171 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001172 if (this->__stage2_float_loop(*__b, __in_units, __exp, __a, __a_end,
1173 __decimal_point, __thousands_sep,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001174 __grouping, __g, __g_end,
1175 __dc, __atoms))
1176 break;
1177 if (__grouping.size() != 0 && __in_units && __g_end-__g < __num_get_base::__num_get_buf_sz)
1178 *__g_end++ = __dc;
1179 // Stage 3
1180 __v = __num_get_float<float>(__a, __a_end, __err);
1181 // Digit grouping checked
1182 __check_grouping(__grouping, __g, __g_end, __err);
1183 // EOF checked
1184 if (__b == __e)
1185 __err |= ios_base::eofbit;
1186 return __b;
1187}
1188
1189template <class _CharT, class _InputIterator>
1190_InputIterator
1191num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1192 ios_base& __iob,
1193 ios_base::iostate& __err,
1194 double& __v) const
1195{
1196 // Stage 1, nothing to do
1197 // Stage 2
1198 char_type __atoms[32];
1199 char_type __decimal_point;
1200 char_type __thousands_sep;
Howard Hinnant324bb032010-08-22 00:02:43 +00001201 string __grouping = this->__stage2_float_prep(__iob, __atoms,
1202 __decimal_point,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001203 __thousands_sep);
1204 char __a[__num_get_base::__num_get_buf_sz] = {0};
1205 char* __a_end = __a;
1206 unsigned __g[__num_get_base::__num_get_buf_sz];
1207 unsigned* __g_end = __g;
1208 unsigned __dc = 0;
1209 bool __in_units = true;
1210 char __exp = 'E';
1211 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001212 if (this->__stage2_float_loop(*__b, __in_units, __exp, __a, __a_end,
1213 __decimal_point, __thousands_sep,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001214 __grouping, __g, __g_end,
1215 __dc, __atoms))
1216 break;
1217 if (__grouping.size() != 0 && __in_units && __g_end-__g < __num_get_base::__num_get_buf_sz)
1218 *__g_end++ = __dc;
1219 // Stage 3
1220 __v = __num_get_float<double>(__a, __a_end, __err);
1221 // Digit grouping checked
1222 __check_grouping(__grouping, __g, __g_end, __err);
1223 // EOF checked
1224 if (__b == __e)
1225 __err |= ios_base::eofbit;
1226 return __b;
1227}
1228
1229template <class _CharT, class _InputIterator>
1230_InputIterator
1231num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1232 ios_base& __iob,
1233 ios_base::iostate& __err,
1234 long double& __v) const
1235{
1236 // Stage 1, nothing to do
1237 // Stage 2
1238 char_type __atoms[32];
1239 char_type __decimal_point;
1240 char_type __thousands_sep;
Howard Hinnant324bb032010-08-22 00:02:43 +00001241 string __grouping = this->__stage2_float_prep(__iob, __atoms,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001242 __decimal_point,
1243 __thousands_sep);
1244 char __a[__num_get_base::__num_get_buf_sz] = {0};
1245 char* __a_end = __a;
1246 unsigned __g[__num_get_base::__num_get_buf_sz];
1247 unsigned* __g_end = __g;
1248 unsigned __dc = 0;
1249 bool __in_units = true;
1250 char __exp = 'E';
1251 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001252 if (this->__stage2_float_loop(*__b, __in_units, __exp, __a, __a_end,
1253 __decimal_point, __thousands_sep,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001254 __grouping, __g, __g_end,
1255 __dc, __atoms))
1256 break;
1257 if (__grouping.size() != 0 && __in_units && __g_end-__g < __num_get_base::__num_get_buf_sz)
1258 *__g_end++ = __dc;
1259 // Stage 3
1260 __v = __num_get_float<long double>(__a, __a_end, __err);
1261 // Digit grouping checked
1262 __check_grouping(__grouping, __g, __g_end, __err);
1263 // EOF checked
1264 if (__b == __e)
1265 __err |= ios_base::eofbit;
1266 return __b;
1267}
1268
1269template <class _CharT, class _InputIterator>
1270_InputIterator
1271num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1272 ios_base& __iob,
1273 ios_base::iostate& __err,
1274 void*& __v) const
1275{
1276 // Stage 1
1277 int __base = 16;
1278 // Stage 2
1279 char_type __atoms[26];
1280 char_type __thousands_sep;
1281 string __grouping;
1282 use_facet<ctype<_CharT> >(__iob.getloc()).widen(__num_get_base::__src,
1283 __num_get_base::__src + 26, __atoms);
1284 char __a[__num_get_base::__num_get_buf_sz] = {0};
1285 char* __a_end = __a;
1286 unsigned __g[__num_get_base::__num_get_buf_sz];
1287 unsigned* __g_end = __g;
1288 unsigned __dc = 0;
1289 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001290 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
1291 __thousands_sep, __grouping,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001292 __g, __g_end, __atoms))
1293 break;
1294 // Stage 3
1295 __a[sizeof(__a)-1] = 0;
Sean Huntf3907e62011-07-15 05:40:33 +00001296#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantbcbbd4d2011-07-15 14:46:11 +00001297 if (sscanf_l(__a, 0, "%p", &__v) != 1)
Sean Huntf3907e62011-07-15 05:40:33 +00001298#else
1299 if (__sscanf_l(__a, __cloc(), "%p", &__v) != 1)
1300#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001301 __err = ios_base::failbit;
1302 // EOF checked
1303 if (__b == __e)
1304 __err |= ios_base::eofbit;
1305 return __b;
1306}
1307
1308extern template class num_get<char>;
1309extern template class num_get<wchar_t>;
1310
1311struct __num_put_base
1312{
1313protected:
1314 static void __format_int(char* __fmt, const char* __len, bool __signd,
1315 ios_base::fmtflags __flags);
1316 static bool __format_float(char* __fmt, const char* __len,
1317 ios_base::fmtflags __flags);
1318 static char* __identify_padding(char* __nb, char* __ne,
1319 const ios_base& __iob);
1320};
1321
1322template <class _CharT>
1323struct __num_put
1324 : protected __num_put_base
1325{
1326 static void __widen_and_group_int(char* __nb, char* __np, char* __ne,
1327 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1328 const locale& __loc);
1329 static void __widen_and_group_float(char* __nb, char* __np, char* __ne,
1330 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1331 const locale& __loc);
1332};
1333
1334template <class _CharT>
1335void
1336__num_put<_CharT>::__widen_and_group_int(char* __nb, char* __np, char* __ne,
1337 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1338 const locale& __loc)
1339{
1340 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> > (__loc);
1341 const numpunct<_CharT>& __npt = use_facet<numpunct<_CharT> >(__loc);
1342 string __grouping = __npt.grouping();
1343 if (__grouping.empty())
1344 {
1345 __ct.widen(__nb, __ne, __ob);
1346 __oe = __ob + (__ne - __nb);
1347 }
1348 else
1349 {
1350 __oe = __ob;
1351 char* __nf = __nb;
1352 if (*__nf == '-' || *__nf == '+')
1353 *__oe++ = __ct.widen(*__nf++);
1354 if (__ne - __nf >= 2 && __nf[0] == '0' && (__nf[1] == 'x' ||
1355 __nf[1] == 'X'))
1356 {
1357 *__oe++ = __ct.widen(*__nf++);
1358 *__oe++ = __ct.widen(*__nf++);
1359 }
1360 reverse(__nf, __ne);
1361 _CharT __thousands_sep = __npt.thousands_sep();
1362 unsigned __dc = 0;
1363 unsigned __dg = 0;
1364 for (char* __p = __nf; __p < __ne; ++__p)
1365 {
1366 if (static_cast<unsigned>(__grouping[__dg]) > 0 &&
1367 __dc == static_cast<unsigned>(__grouping[__dg]))
1368 {
1369 *__oe++ = __thousands_sep;
1370 __dc = 0;
1371 if (__dg < __grouping.size()-1)
1372 ++__dg;
1373 }
1374 *__oe++ = __ct.widen(*__p);
1375 ++__dc;
1376 }
1377 reverse(__ob + (__nf - __nb), __oe);
1378 }
1379 if (__np == __ne)
1380 __op = __oe;
1381 else
1382 __op = __ob + (__np - __nb);
1383}
1384
1385template <class _CharT>
1386void
1387__num_put<_CharT>::__widen_and_group_float(char* __nb, char* __np, char* __ne,
1388 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1389 const locale& __loc)
1390{
1391 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> > (__loc);
1392 const numpunct<_CharT>& __npt = use_facet<numpunct<_CharT> >(__loc);
1393 string __grouping = __npt.grouping();
1394 __oe = __ob;
1395 char* __nf = __nb;
1396 if (*__nf == '-' || *__nf == '+')
1397 *__oe++ = __ct.widen(*__nf++);
1398 char* __ns;
1399 if (__ne - __nf >= 2 && __nf[0] == '0' && (__nf[1] == 'x' ||
1400 __nf[1] == 'X'))
1401 {
1402 *__oe++ = __ct.widen(*__nf++);
1403 *__oe++ = __ct.widen(*__nf++);
1404 for (__ns = __nf; __ns < __ne; ++__ns)
Sean Huntf3907e62011-07-15 05:40:33 +00001405#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantbcbbd4d2011-07-15 14:46:11 +00001406 if (!isxdigit_l(*__ns, 0))
Sean Huntf3907e62011-07-15 05:40:33 +00001407#else
1408 if (!isxdigit_l(*__ns, __cloc()))
1409#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001410 break;
1411 }
1412 else
1413 {
1414 for (__ns = __nf; __ns < __ne; ++__ns)
Sean Huntf3907e62011-07-15 05:40:33 +00001415#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantbcbbd4d2011-07-15 14:46:11 +00001416 if (!isdigit_l(*__ns, 0))
Sean Huntf3907e62011-07-15 05:40:33 +00001417#else
1418 if (!isdigit_l(*__ns, __cloc()))
1419#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001420 break;
1421 }
1422 if (__grouping.empty())
1423 {
1424 __ct.widen(__nf, __ns, __oe);
1425 __oe += __ns - __nf;
1426 }
1427 else
1428 {
1429 reverse(__nf, __ns);
1430 _CharT __thousands_sep = __npt.thousands_sep();
1431 unsigned __dc = 0;
1432 unsigned __dg = 0;
1433 for (char* __p = __nf; __p < __ns; ++__p)
1434 {
1435 if (__grouping[__dg] > 0 && __dc == static_cast<unsigned>(__grouping[__dg]))
1436 {
1437 *__oe++ = __thousands_sep;
1438 __dc = 0;
1439 if (__dg < __grouping.size()-1)
1440 ++__dg;
1441 }
1442 *__oe++ = __ct.widen(*__p);
1443 ++__dc;
1444 }
1445 reverse(__ob + (__nf - __nb), __oe);
1446 }
1447 for (__nf = __ns; __nf < __ne; ++__nf)
1448 {
1449 if (*__nf == '.')
1450 {
1451 *__oe++ = __npt.decimal_point();
1452 ++__nf;
1453 break;
1454 }
1455 else
1456 *__oe++ = __ct.widen(*__nf);
1457 }
1458 __ct.widen(__nf, __ne, __oe);
1459 __oe += __ne - __nf;
1460 if (__np == __ne)
1461 __op = __oe;
1462 else
1463 __op = __ob + (__np - __nb);
1464}
1465
1466extern template class __num_put<char>;
1467extern template class __num_put<wchar_t>;
1468
1469template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00001470class _LIBCPP_VISIBLE num_put
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001471 : public locale::facet,
1472 private __num_put<_CharT>
1473{
1474public:
1475 typedef _CharT char_type;
1476 typedef _OutputIterator iter_type;
1477
1478 _LIBCPP_ALWAYS_INLINE
1479 explicit num_put(size_t __refs = 0)
1480 : locale::facet(__refs) {}
1481
1482 _LIBCPP_ALWAYS_INLINE
1483 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1484 bool __v) const
1485 {
1486 return do_put(__s, __iob, __fl, __v);
1487 }
1488
1489 _LIBCPP_ALWAYS_INLINE
1490 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1491 long __v) const
1492 {
1493 return do_put(__s, __iob, __fl, __v);
1494 }
1495
1496 _LIBCPP_ALWAYS_INLINE
1497 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1498 long long __v) const
1499 {
1500 return do_put(__s, __iob, __fl, __v);
1501 }
1502
1503 _LIBCPP_ALWAYS_INLINE
1504 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1505 unsigned long __v) const
1506 {
1507 return do_put(__s, __iob, __fl, __v);
1508 }
1509
1510 _LIBCPP_ALWAYS_INLINE
1511 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1512 unsigned long long __v) const
1513 {
1514 return do_put(__s, __iob, __fl, __v);
1515 }
1516
1517 _LIBCPP_ALWAYS_INLINE
1518 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1519 double __v) const
1520 {
1521 return do_put(__s, __iob, __fl, __v);
1522 }
1523
1524 _LIBCPP_ALWAYS_INLINE
1525 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1526 long double __v) const
1527 {
1528 return do_put(__s, __iob, __fl, __v);
1529 }
1530
1531 _LIBCPP_ALWAYS_INLINE
1532 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1533 const void* __v) const
1534 {
1535 return do_put(__s, __iob, __fl, __v);
1536 }
1537
1538 static locale::id id;
1539
1540protected:
Howard Hinnant82894812010-09-22 16:48:34 +00001541 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001542 ~num_put() {}
1543
1544 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1545 bool __v) const;
1546 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1547 long __v) const;
1548 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1549 long long __v) const;
1550 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1551 unsigned long) const;
1552 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1553 unsigned long long) const;
1554 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1555 double __v) const;
1556 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1557 long double __v) const;
1558 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1559 const void* __v) const;
1560};
1561
1562template <class _CharT, class _OutputIterator>
1563locale::id
1564num_put<_CharT, _OutputIterator>::id;
1565
1566template <class _CharT, class _OutputIterator>
1567_LIBCPP_HIDDEN
1568_OutputIterator
1569__pad_and_output(_OutputIterator __s,
1570 const _CharT* __ob, const _CharT* __op, const _CharT* __oe,
1571 ios_base& __iob, _CharT __fl)
1572{
1573 streamsize __sz = __oe - __ob;
1574 streamsize __ns = __iob.width();
1575 if (__ns > __sz)
1576 __ns -= __sz;
1577 else
1578 __ns = 0;
1579 for (;__ob < __op; ++__ob, ++__s)
1580 *__s = *__ob;
1581 for (; __ns; --__ns, ++__s)
1582 *__s = __fl;
1583 for (; __ob < __oe; ++__ob, ++__s)
1584 *__s = *__ob;
1585 __iob.width(0);
1586 return __s;
1587}
1588
1589template <class _CharT, class _OutputIterator>
1590_OutputIterator
1591num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1592 char_type __fl, bool __v) const
1593{
1594 if ((__iob.flags() & ios_base::boolalpha) == 0)
1595 return do_put(__s, __iob, __fl, (unsigned long)__v);
1596 const numpunct<char_type>& __np = use_facet<numpunct<char_type> >(__iob.getloc());
1597 typedef typename numpunct<char_type>::string_type string_type;
1598 string_type __nm = __v ? __np.truename() : __np.falsename();
1599 for (typename string_type::iterator __i = __nm.begin(); __i != __nm.end(); ++__i, ++__s)
1600 *__s = *__i;
1601 return __s;
1602}
1603
1604template <class _CharT, class _OutputIterator>
1605_OutputIterator
1606num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1607 char_type __fl, long __v) const
1608{
1609 // Stage 1 - Get number in narrow char
1610 char __fmt[6] = {'%', 0};
1611 const char* __len = "l";
1612 this->__format_int(__fmt+1, __len, true, __iob.flags());
1613 const unsigned __nbuf = (numeric_limits<long>::digits / 3)
1614 + ((numeric_limits<long>::digits % 3) != 0)
1615 + 1;
1616 char __nar[__nbuf];
Sean Huntf3907e62011-07-15 05:40:33 +00001617#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantbcbbd4d2011-07-15 14:46:11 +00001618 int __nc = sprintf_l(__nar, 0, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001619#else
1620 int __nc = __sprintf_l(__nar, __cloc(), __fmt, __v);
1621#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001622 char* __ne = __nar + __nc;
1623 char* __np = this->__identify_padding(__nar, __ne, __iob);
1624 // Stage 2 - Widen __nar while adding thousands separators
1625 char_type __o[2*(__nbuf-1) - 1];
1626 char_type* __op; // pad here
1627 char_type* __oe; // end of output
1628 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1629 // [__o, __oe) contains thousands_sep'd wide number
1630 // Stage 3 & 4
1631 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1632}
1633
1634template <class _CharT, class _OutputIterator>
1635_OutputIterator
1636num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1637 char_type __fl, long long __v) const
1638{
1639 // Stage 1 - Get number in narrow char
1640 char __fmt[8] = {'%', 0};
1641 const char* __len = "ll";
1642 this->__format_int(__fmt+1, __len, true, __iob.flags());
1643 const unsigned __nbuf = (numeric_limits<long long>::digits / 3)
1644 + ((numeric_limits<long long>::digits % 3) != 0)
1645 + 1;
1646 char __nar[__nbuf];
Sean Huntf3907e62011-07-15 05:40:33 +00001647#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantbcbbd4d2011-07-15 14:46:11 +00001648 int __nc = sprintf_l(__nar, 0, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001649#else
1650 int __nc = __sprintf_l(__nar, __cloc(), __fmt, __v);
1651#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001652 char* __ne = __nar + __nc;
1653 char* __np = this->__identify_padding(__nar, __ne, __iob);
1654 // Stage 2 - Widen __nar while adding thousands separators
1655 char_type __o[2*(__nbuf-1) - 1];
1656 char_type* __op; // pad here
1657 char_type* __oe; // end of output
1658 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1659 // [__o, __oe) contains thousands_sep'd wide number
1660 // Stage 3 & 4
1661 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1662}
1663
1664template <class _CharT, class _OutputIterator>
1665_OutputIterator
1666num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1667 char_type __fl, unsigned long __v) const
1668{
1669 // Stage 1 - Get number in narrow char
1670 char __fmt[6] = {'%', 0};
1671 const char* __len = "l";
1672 this->__format_int(__fmt+1, __len, false, __iob.flags());
1673 const unsigned __nbuf = (numeric_limits<unsigned long>::digits / 3)
1674 + ((numeric_limits<unsigned long>::digits % 3) != 0)
1675 + 1;
1676 char __nar[__nbuf];
Sean Huntf3907e62011-07-15 05:40:33 +00001677#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantbcbbd4d2011-07-15 14:46:11 +00001678 int __nc = sprintf_l(__nar, 0, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001679#else
1680 int __nc = __sprintf_l(__nar, __cloc(), __fmt, __v);
1681#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001682 char* __ne = __nar + __nc;
1683 char* __np = this->__identify_padding(__nar, __ne, __iob);
1684 // Stage 2 - Widen __nar while adding thousands separators
1685 char_type __o[2*(__nbuf-1) - 1];
1686 char_type* __op; // pad here
1687 char_type* __oe; // end of output
1688 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1689 // [__o, __oe) contains thousands_sep'd wide number
1690 // Stage 3 & 4
1691 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1692}
1693
1694template <class _CharT, class _OutputIterator>
1695_OutputIterator
1696num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1697 char_type __fl, unsigned long long __v) const
1698{
1699 // Stage 1 - Get number in narrow char
1700 char __fmt[8] = {'%', 0};
1701 const char* __len = "ll";
1702 this->__format_int(__fmt+1, __len, false, __iob.flags());
1703 const unsigned __nbuf = (numeric_limits<unsigned long long>::digits / 3)
1704 + ((numeric_limits<unsigned long long>::digits % 3) != 0)
1705 + 1;
1706 char __nar[__nbuf];
Sean Huntf3907e62011-07-15 05:40:33 +00001707#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantbcbbd4d2011-07-15 14:46:11 +00001708 int __nc = sprintf_l(__nar, 0, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001709#else
1710 int __nc = __sprintf_l(__nar, __cloc(), __fmt, __v);
1711#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001712 char* __ne = __nar + __nc;
1713 char* __np = this->__identify_padding(__nar, __ne, __iob);
1714 // Stage 2 - Widen __nar while adding thousands separators
1715 char_type __o[2*(__nbuf-1) - 1];
1716 char_type* __op; // pad here
1717 char_type* __oe; // end of output
1718 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1719 // [__o, __oe) contains thousands_sep'd wide number
1720 // Stage 3 & 4
1721 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1722}
1723
1724template <class _CharT, class _OutputIterator>
1725_OutputIterator
1726num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1727 char_type __fl, double __v) const
1728{
1729 // Stage 1 - Get number in narrow char
1730 char __fmt[8] = {'%', 0};
1731 const char* __len = "";
1732 bool __specify_precision = this->__format_float(__fmt+1, __len, __iob.flags());
1733 const unsigned __nbuf = 30;
1734 char __nar[__nbuf];
1735 char* __nb = __nar;
1736 int __nc;
1737 if (__specify_precision)
Sean Huntf3907e62011-07-15 05:40:33 +00001738#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantbcbbd4d2011-07-15 14:46:11 +00001739 __nc = snprintf_l(__nb, __nbuf, 0, __fmt,
Howard Hinnantadff4892010-05-24 17:49:41 +00001740 (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001741#else
1742 __nc = __snprintf_l(__nb, __nbuf, __cloc(), __fmt,
1743 (int)__iob.precision(), __v);
1744#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001745 else
Sean Huntf3907e62011-07-15 05:40:33 +00001746#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantbcbbd4d2011-07-15 14:46:11 +00001747 __nc = snprintf_l(__nb, __nbuf, 0, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001748#else
1749 __nc = __snprintf_l(__nb, __nbuf, __cloc(), __fmt, __v);
1750#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001751 unique_ptr<char, void(*)(void*)> __nbh(0, free);
1752 if (__nc > static_cast<int>(__nbuf-1))
1753 {
1754 if (__specify_precision)
Sean Huntf3907e62011-07-15 05:40:33 +00001755#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantbcbbd4d2011-07-15 14:46:11 +00001756 __nc = asprintf_l(&__nb, 0, __fmt, (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001757#else
1758 __nc = __asprintf_l(&__nb, __cloc(), __fmt,
David Chisnallc512df12011-09-21 08:39:44 +00001759 (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001760#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001761 else
Sean Huntf3907e62011-07-15 05:40:33 +00001762#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantbcbbd4d2011-07-15 14:46:11 +00001763 __nc = asprintf_l(&__nb, 0, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001764#else
David Chisnallc512df12011-09-21 08:39:44 +00001765 __nc = __asprintf_l(&__nb, __cloc(), __fmt, (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001766#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001767 if (__nb == 0)
1768 __throw_bad_alloc();
1769 __nbh.reset(__nb);
1770 }
1771 char* __ne = __nb + __nc;
1772 char* __np = this->__identify_padding(__nb, __ne, __iob);
1773 // Stage 2 - Widen __nar while adding thousands separators
1774 char_type __o[2*(__nbuf-1) - 1];
1775 char_type* __ob = __o;
1776 unique_ptr<char_type, void(*)(void*)> __obh(0, free);
1777 if (__nb != __nar)
1778 {
1779 __ob = (char_type*)malloc((2*__nc)*sizeof(char_type));
1780 if (__ob == 0)
1781 __throw_bad_alloc();
1782 __obh.reset(__ob);
1783 }
1784 char_type* __op; // pad here
1785 char_type* __oe; // end of output
1786 this->__widen_and_group_float(__nb, __np, __ne, __ob, __op, __oe, __iob.getloc());
1787 // [__o, __oe) contains thousands_sep'd wide number
1788 // Stage 3 & 4
1789 __s = __pad_and_output(__s, __ob, __op, __oe, __iob, __fl);
1790 return __s;
1791}
1792
1793template <class _CharT, class _OutputIterator>
1794_OutputIterator
1795num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1796 char_type __fl, long double __v) const
1797{
1798 // Stage 1 - Get number in narrow char
1799 char __fmt[8] = {'%', 0};
1800 const char* __len = "L";
1801 bool __specify_precision = this->__format_float(__fmt+1, __len, __iob.flags());
1802 const unsigned __nbuf = 30;
1803 char __nar[__nbuf];
1804 char* __nb = __nar;
1805 int __nc;
1806 if (__specify_precision)
Sean Huntf3907e62011-07-15 05:40:33 +00001807#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantbcbbd4d2011-07-15 14:46:11 +00001808 __nc = snprintf_l(__nb, __nbuf, 0, __fmt,
Howard Hinnantadff4892010-05-24 17:49:41 +00001809 (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001810#else
1811 __nc = __snprintf_l(__nb, __nbuf, __cloc(), __fmt,
1812 (int)__iob.precision(), __v);
1813#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001814 else
Sean Huntf3907e62011-07-15 05:40:33 +00001815#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantbcbbd4d2011-07-15 14:46:11 +00001816 __nc = snprintf_l(__nb, __nbuf, 0, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001817#else
1818 __nc = __snprintf_l(__nb, __nbuf, __cloc(), __fmt, __v);
1819#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001820 unique_ptr<char, void(*)(void*)> __nbh(0, free);
1821 if (__nc > static_cast<int>(__nbuf-1))
1822 {
1823 if (__specify_precision)
Sean Huntf3907e62011-07-15 05:40:33 +00001824#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantbcbbd4d2011-07-15 14:46:11 +00001825 __nc = asprintf_l(&__nb, 0, __fmt, (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001826#else
1827 __nc = __asprintf_l(&__nb, __cloc(), __fmt,
David Chisnallc512df12011-09-21 08:39:44 +00001828 (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001829#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001830 else
Sean Huntf3907e62011-07-15 05:40:33 +00001831#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantbcbbd4d2011-07-15 14:46:11 +00001832 __nc = asprintf_l(&__nb, 0, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001833#else
David Chisnallc512df12011-09-21 08:39:44 +00001834 __nc = __asprintf_l(&__nb, __cloc(), __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001835#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001836 if (__nb == 0)
1837 __throw_bad_alloc();
1838 __nbh.reset(__nb);
1839 }
1840 char* __ne = __nb + __nc;
1841 char* __np = this->__identify_padding(__nb, __ne, __iob);
1842 // Stage 2 - Widen __nar while adding thousands separators
1843 char_type __o[2*(__nbuf-1) - 1];
1844 char_type* __ob = __o;
1845 unique_ptr<char_type, void(*)(void*)> __obh(0, free);
1846 if (__nb != __nar)
1847 {
1848 __ob = (char_type*)malloc((2*__nc)*sizeof(char_type));
1849 if (__ob == 0)
1850 __throw_bad_alloc();
1851 __obh.reset(__ob);
1852 }
1853 char_type* __op; // pad here
1854 char_type* __oe; // end of output
1855 this->__widen_and_group_float(__nb, __np, __ne, __ob, __op, __oe, __iob.getloc());
1856 // [__o, __oe) contains thousands_sep'd wide number
1857 // Stage 3 & 4
1858 __s = __pad_and_output(__s, __ob, __op, __oe, __iob, __fl);
1859 return __s;
1860}
1861
1862template <class _CharT, class _OutputIterator>
1863_OutputIterator
1864num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1865 char_type __fl, const void* __v) const
1866{
1867 // Stage 1 - Get pointer in narrow char
1868 char __fmt[6] = "%p";
1869 const unsigned __nbuf = 20;
1870 char __nar[__nbuf];
Sean Huntf3907e62011-07-15 05:40:33 +00001871#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantbcbbd4d2011-07-15 14:46:11 +00001872 int __nc = sprintf_l(__nar, 0, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001873#else
1874 int __nc = __sprintf_l(__nar, __cloc(), __fmt, __v);
1875#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001876 char* __ne = __nar + __nc;
1877 char* __np = this->__identify_padding(__nar, __ne, __iob);
1878 // Stage 2 - Widen __nar
1879 char_type __o[2*(__nbuf-1) - 1];
1880 char_type* __op; // pad here
1881 char_type* __oe; // end of output
1882 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
1883 __ct.widen(__nar, __ne, __o);
1884 __oe = __o + (__ne - __nar);
1885 if (__np == __ne)
1886 __op = __oe;
1887 else
1888 __op = __o + (__np - __nar);
1889 // [__o, __oe) contains wide number
1890 // Stage 3 & 4
1891 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1892}
1893
1894extern template class num_put<char>;
1895extern template class num_put<wchar_t>;
1896
1897template <class _CharT, class _InputIterator>
1898_LIBCPP_HIDDEN
1899int
1900__get_up_to_n_digits(_InputIterator& __b, _InputIterator __e,
1901 ios_base::iostate& __err, const ctype<_CharT>& __ct, int __n)
1902{
1903 // Precondition: __n >= 1
1904 if (__b == __e)
1905 {
1906 __err |= ios_base::eofbit | ios_base::failbit;
1907 return 0;
1908 }
1909 // get first digit
1910 _CharT __c = *__b;
1911 if (!__ct.is(ctype_base::digit, __c))
1912 {
1913 __err |= ios_base::failbit;
1914 return 0;
1915 }
1916 int __r = __ct.narrow(__c, 0) - '0';
1917 for (++__b, --__n; __b != __e && __n > 0; ++__b, --__n)
1918 {
1919 // get next digit
1920 __c = *__b;
1921 if (!__ct.is(ctype_base::digit, __c))
1922 return __r;
1923 __r = __r * 10 + __ct.narrow(__c, 0) - '0';
1924 }
1925 if (__b == __e)
1926 __err |= ios_base::eofbit;
1927 return __r;
1928}
1929
Howard Hinnant82894812010-09-22 16:48:34 +00001930class _LIBCPP_VISIBLE time_base
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001931{
1932public:
1933 enum dateorder {no_order, dmy, mdy, ymd, ydm};
1934};
1935
1936template <class _CharT>
Howard Hinnant2d72b1e2010-12-17 14:46:43 +00001937class __time_get_c_storage // purposefully not decorated
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001938{
1939protected:
1940 typedef basic_string<_CharT> string_type;
1941
1942 virtual const string_type* __weeks() const;
1943 virtual const string_type* __months() const;
1944 virtual const string_type* __am_pm() const;
1945 virtual const string_type& __c() const;
1946 virtual const string_type& __r() const;
1947 virtual const string_type& __x() const;
1948 virtual const string_type& __X() const;
1949};
1950
1951template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00001952class _LIBCPP_VISIBLE time_get
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001953 : public locale::facet,
1954 public time_base,
1955 private __time_get_c_storage<_CharT>
1956{
1957public:
1958 typedef _CharT char_type;
1959 typedef _InputIterator iter_type;
1960 typedef time_base::dateorder dateorder;
1961 typedef basic_string<char_type> string_type;
1962
1963 _LIBCPP_ALWAYS_INLINE
1964 explicit time_get(size_t __refs = 0)
1965 : locale::facet(__refs) {}
1966
1967 _LIBCPP_ALWAYS_INLINE
1968 dateorder date_order() const
1969 {
1970 return this->do_date_order();
1971 }
1972
1973 _LIBCPP_ALWAYS_INLINE
1974 iter_type get_time(iter_type __b, iter_type __e, ios_base& __iob,
1975 ios_base::iostate& __err, tm* __tm) const
1976 {
1977 return do_get_time(__b, __e, __iob, __err, __tm);
1978 }
1979
1980 _LIBCPP_ALWAYS_INLINE
1981 iter_type get_date(iter_type __b, iter_type __e, ios_base& __iob,
1982 ios_base::iostate& __err, tm* __tm) const
1983 {
1984 return do_get_date(__b, __e, __iob, __err, __tm);
1985 }
1986
1987 _LIBCPP_ALWAYS_INLINE
1988 iter_type get_weekday(iter_type __b, iter_type __e, ios_base& __iob,
1989 ios_base::iostate& __err, tm* __tm) const
1990 {
1991 return do_get_weekday(__b, __e, __iob, __err, __tm);
1992 }
1993
1994 _LIBCPP_ALWAYS_INLINE
1995 iter_type get_monthname(iter_type __b, iter_type __e, ios_base& __iob,
1996 ios_base::iostate& __err, tm* __tm) const
1997 {
1998 return do_get_monthname(__b, __e, __iob, __err, __tm);
1999 }
2000
2001 _LIBCPP_ALWAYS_INLINE
2002 iter_type get_year(iter_type __b, iter_type __e, ios_base& __iob,
2003 ios_base::iostate& __err, tm* __tm) const
2004 {
2005 return do_get_year(__b, __e, __iob, __err, __tm);
2006 }
2007
2008 _LIBCPP_ALWAYS_INLINE
2009 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
2010 ios_base::iostate& __err, tm *__tm,
2011 char __fmt, char __mod = 0) const
2012 {
2013 return do_get(__b, __e, __iob, __err, __tm, __fmt, __mod);
2014 }
2015
2016 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
2017 ios_base::iostate& __err, tm* __tm,
2018 const char_type* __fmtb, const char_type* __fmte) const;
2019
2020 static locale::id id;
2021
2022protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002023 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002024 ~time_get() {}
2025
2026 virtual dateorder do_date_order() const;
2027 virtual iter_type do_get_time(iter_type __b, iter_type __e, ios_base& __iob,
2028 ios_base::iostate& __err, tm* __tm) const;
2029 virtual iter_type do_get_date(iter_type __b, iter_type __e, ios_base& __iob,
2030 ios_base::iostate& __err, tm* __tm) const;
2031 virtual iter_type do_get_weekday(iter_type __b, iter_type __e, ios_base& __iob,
2032 ios_base::iostate& __err, tm* __tm) const;
2033 virtual iter_type do_get_monthname(iter_type __b, iter_type __e, ios_base& __iob,
2034 ios_base::iostate& __err, tm* __tm) const;
2035 virtual iter_type do_get_year(iter_type __b, iter_type __e, ios_base& __iob,
2036 ios_base::iostate& __err, tm* __tm) const;
2037 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
2038 ios_base::iostate& __err, tm* __tm,
2039 char __fmt, char __mod) const;
2040private:
2041 void __get_white_space(iter_type& __b, iter_type __e,
2042 ios_base::iostate& __err, const ctype<char_type>& __ct) const;
2043 void __get_percent(iter_type& __b, iter_type __e, ios_base::iostate& __err,
2044 const ctype<char_type>& __ct) const;
2045
2046 void __get_weekdayname(int& __m,
2047 iter_type& __b, iter_type __e,
2048 ios_base::iostate& __err,
2049 const ctype<char_type>& __ct) const;
2050 void __get_monthname(int& __m,
2051 iter_type& __b, iter_type __e,
2052 ios_base::iostate& __err,
2053 const ctype<char_type>& __ct) const;
2054 void __get_day(int& __d,
2055 iter_type& __b, iter_type __e,
2056 ios_base::iostate& __err,
2057 const ctype<char_type>& __ct) const;
2058 void __get_month(int& __m,
2059 iter_type& __b, iter_type __e,
2060 ios_base::iostate& __err,
2061 const ctype<char_type>& __ct) const;
2062 void __get_year(int& __y,
2063 iter_type& __b, iter_type __e,
2064 ios_base::iostate& __err,
2065 const ctype<char_type>& __ct) const;
2066 void __get_year4(int& __y,
2067 iter_type& __b, iter_type __e,
2068 ios_base::iostate& __err,
2069 const ctype<char_type>& __ct) const;
2070 void __get_hour(int& __d,
2071 iter_type& __b, iter_type __e,
2072 ios_base::iostate& __err,
2073 const ctype<char_type>& __ct) const;
2074 void __get_12_hour(int& __h,
2075 iter_type& __b, iter_type __e,
2076 ios_base::iostate& __err,
2077 const ctype<char_type>& __ct) const;
2078 void __get_am_pm(int& __h,
2079 iter_type& __b, iter_type __e,
2080 ios_base::iostate& __err,
2081 const ctype<char_type>& __ct) const;
2082 void __get_minute(int& __m,
2083 iter_type& __b, iter_type __e,
2084 ios_base::iostate& __err,
2085 const ctype<char_type>& __ct) const;
2086 void __get_second(int& __s,
2087 iter_type& __b, iter_type __e,
2088 ios_base::iostate& __err,
2089 const ctype<char_type>& __ct) const;
2090 void __get_weekday(int& __w,
2091 iter_type& __b, iter_type __e,
2092 ios_base::iostate& __err,
2093 const ctype<char_type>& __ct) const;
2094 void __get_day_year_num(int& __w,
2095 iter_type& __b, iter_type __e,
2096 ios_base::iostate& __err,
2097 const ctype<char_type>& __ct) const;
2098};
2099
2100template <class _CharT, class _InputIterator>
2101locale::id
2102time_get<_CharT, _InputIterator>::id;
2103
2104// time_get primatives
2105
2106template <class _CharT, class _InputIterator>
2107void
2108time_get<_CharT, _InputIterator>::__get_weekdayname(int& __w,
2109 iter_type& __b, iter_type __e,
2110 ios_base::iostate& __err,
2111 const ctype<char_type>& __ct) const
2112{
2113 // Note: ignoring case comes from the POSIX strptime spec
2114 const string_type* __wk = this->__weeks();
2115 int __i = __scan_keyword(__b, __e, __wk, __wk+14, __ct, __err, false) - __wk;
2116 if (__i < 14)
2117 __w = __i % 7;
2118}
2119
2120template <class _CharT, class _InputIterator>
2121void
2122time_get<_CharT, _InputIterator>::__get_monthname(int& __m,
2123 iter_type& __b, iter_type __e,
2124 ios_base::iostate& __err,
2125 const ctype<char_type>& __ct) const
2126{
2127 // Note: ignoring case comes from the POSIX strptime spec
2128 const string_type* __month = this->__months();
2129 int __i = __scan_keyword(__b, __e, __month, __month+24, __ct, __err, false) - __month;
2130 if (__i < 24)
2131 __m = __i % 12;
2132}
2133
2134template <class _CharT, class _InputIterator>
2135void
2136time_get<_CharT, _InputIterator>::__get_day(int& __d,
2137 iter_type& __b, iter_type __e,
2138 ios_base::iostate& __err,
2139 const ctype<char_type>& __ct) const
2140{
2141 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2142 if (!(__err & ios_base::failbit) && 1 <= __t && __t <= 31)
2143 __d = __t;
2144 else
2145 __err |= ios_base::failbit;
2146}
2147
2148template <class _CharT, class _InputIterator>
2149void
2150time_get<_CharT, _InputIterator>::__get_month(int& __m,
2151 iter_type& __b, iter_type __e,
2152 ios_base::iostate& __err,
2153 const ctype<char_type>& __ct) const
2154{
2155 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2) - 1;
2156 if (!(__err & ios_base::failbit) && __t <= 11)
2157 __m = __t;
2158 else
2159 __err |= ios_base::failbit;
2160}
2161
2162template <class _CharT, class _InputIterator>
2163void
2164time_get<_CharT, _InputIterator>::__get_year(int& __y,
2165 iter_type& __b, iter_type __e,
2166 ios_base::iostate& __err,
2167 const ctype<char_type>& __ct) const
2168{
2169 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 4);
2170 if (!(__err & ios_base::failbit))
2171 {
2172 if (__t < 69)
2173 __t += 2000;
2174 else if (69 <= __t && __t <= 99)
2175 __t += 1900;
2176 __y = __t - 1900;
2177 }
2178}
2179
2180template <class _CharT, class _InputIterator>
2181void
2182time_get<_CharT, _InputIterator>::__get_year4(int& __y,
2183 iter_type& __b, iter_type __e,
2184 ios_base::iostate& __err,
2185 const ctype<char_type>& __ct) const
2186{
2187 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 4);
2188 if (!(__err & ios_base::failbit))
2189 __y = __t - 1900;
2190}
2191
2192template <class _CharT, class _InputIterator>
2193void
2194time_get<_CharT, _InputIterator>::__get_hour(int& __h,
2195 iter_type& __b, iter_type __e,
2196 ios_base::iostate& __err,
2197 const ctype<char_type>& __ct) const
2198{
2199 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2200 if (!(__err & ios_base::failbit) && __t <= 23)
2201 __h = __t;
2202 else
2203 __err |= ios_base::failbit;
2204}
2205
2206template <class _CharT, class _InputIterator>
2207void
2208time_get<_CharT, _InputIterator>::__get_12_hour(int& __h,
2209 iter_type& __b, iter_type __e,
2210 ios_base::iostate& __err,
2211 const ctype<char_type>& __ct) const
2212{
2213 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2214 if (!(__err & ios_base::failbit) && 1 <= __t && __t <= 12)
2215 __h = __t;
2216 else
2217 __err |= ios_base::failbit;
2218}
2219
2220template <class _CharT, class _InputIterator>
2221void
2222time_get<_CharT, _InputIterator>::__get_minute(int& __m,
2223 iter_type& __b, iter_type __e,
2224 ios_base::iostate& __err,
2225 const ctype<char_type>& __ct) const
2226{
2227 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2228 if (!(__err & ios_base::failbit) && __t <= 59)
2229 __m = __t;
2230 else
2231 __err |= ios_base::failbit;
2232}
2233
2234template <class _CharT, class _InputIterator>
2235void
2236time_get<_CharT, _InputIterator>::__get_second(int& __s,
2237 iter_type& __b, iter_type __e,
2238 ios_base::iostate& __err,
2239 const ctype<char_type>& __ct) const
2240{
2241 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2242 if (!(__err & ios_base::failbit) && __t <= 60)
2243 __s = __t;
2244 else
2245 __err |= ios_base::failbit;
2246}
2247
2248template <class _CharT, class _InputIterator>
2249void
2250time_get<_CharT, _InputIterator>::__get_weekday(int& __w,
2251 iter_type& __b, iter_type __e,
2252 ios_base::iostate& __err,
2253 const ctype<char_type>& __ct) const
2254{
2255 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 1);
2256 if (!(__err & ios_base::failbit) && __t <= 6)
2257 __w = __t;
2258 else
2259 __err |= ios_base::failbit;
2260}
2261
2262template <class _CharT, class _InputIterator>
2263void
2264time_get<_CharT, _InputIterator>::__get_day_year_num(int& __d,
2265 iter_type& __b, iter_type __e,
2266 ios_base::iostate& __err,
2267 const ctype<char_type>& __ct) const
2268{
2269 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 3);
2270 if (!(__err & ios_base::failbit) && __t <= 365)
2271 __d = __t;
2272 else
2273 __err |= ios_base::failbit;
2274}
2275
2276template <class _CharT, class _InputIterator>
2277void
2278time_get<_CharT, _InputIterator>::__get_white_space(iter_type& __b, iter_type __e,
2279 ios_base::iostate& __err,
2280 const ctype<char_type>& __ct) const
2281{
2282 for (; __b != __e && __ct.is(ctype_base::space, *__b); ++__b)
2283 ;
2284 if (__b == __e)
2285 __err |= ios_base::eofbit;
2286}
2287
2288template <class _CharT, class _InputIterator>
2289void
2290time_get<_CharT, _InputIterator>::__get_am_pm(int& __h,
2291 iter_type& __b, iter_type __e,
2292 ios_base::iostate& __err,
2293 const ctype<char_type>& __ct) const
2294{
2295 const string_type* __ap = this->__am_pm();
2296 if (__ap[0].size() + __ap[1].size() == 0)
2297 {
2298 __err |= ios_base::failbit;
2299 return;
2300 }
2301 int __i = __scan_keyword(__b, __e, __ap, __ap+2, __ct, __err, false) - __ap;
2302 if (__i == 0 && __h == 12)
2303 __h = 0;
2304 else if (__i == 1 && __h < 12)
2305 __h += 12;
2306}
2307
2308template <class _CharT, class _InputIterator>
2309void
2310time_get<_CharT, _InputIterator>::__get_percent(iter_type& __b, iter_type __e,
2311 ios_base::iostate& __err,
2312 const ctype<char_type>& __ct) const
2313{
2314 if (__b == __e)
2315 {
2316 __err |= ios_base::eofbit | ios_base::failbit;
2317 return;
2318 }
2319 if (__ct.narrow(*__b, 0) != '%')
2320 __err |= ios_base::failbit;
2321 else if(++__b == __e)
2322 __err |= ios_base::eofbit;
2323}
2324
2325// time_get end primatives
2326
2327template <class _CharT, class _InputIterator>
2328_InputIterator
2329time_get<_CharT, _InputIterator>::get(iter_type __b, iter_type __e,
2330 ios_base& __iob,
2331 ios_base::iostate& __err, tm* __tm,
2332 const char_type* __fmtb, const char_type* __fmte) const
2333{
2334 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2335 __err = ios_base::goodbit;
2336 while (__fmtb != __fmte && __err == ios_base::goodbit)
2337 {
2338 if (__b == __e)
2339 {
2340 __err = ios_base::failbit;
2341 break;
2342 }
2343 if (__ct.narrow(*__fmtb, 0) == '%')
2344 {
2345 if (++__fmtb == __fmte)
2346 {
2347 __err = ios_base::failbit;
2348 break;
2349 }
2350 char __cmd = __ct.narrow(*__fmtb, 0);
2351 char __opt = '\0';
2352 if (__cmd == 'E' || __cmd == '0')
2353 {
2354 if (++__fmtb == __fmte)
2355 {
2356 __err = ios_base::failbit;
2357 break;
2358 }
2359 __opt = __cmd;
2360 __cmd = __ct.narrow(*__fmtb, 0);
2361 }
2362 __b = do_get(__b, __e, __iob, __err, __tm, __cmd, __opt);
2363 ++__fmtb;
2364 }
2365 else if (__ct.is(ctype_base::space, *__fmtb))
2366 {
2367 for (++__fmtb; __fmtb != __fmte && __ct.is(ctype_base::space, *__fmtb); ++__fmtb)
2368 ;
2369 for ( ; __b != __e && __ct.is(ctype_base::space, *__b); ++__b)
2370 ;
2371 }
2372 else if (__ct.toupper(*__b) == __ct.toupper(*__fmtb))
2373 {
2374 ++__b;
2375 ++__fmtb;
2376 }
2377 else
2378 __err = ios_base::failbit;
2379 }
2380 if (__b == __e)
2381 __err |= ios_base::eofbit;
2382 return __b;
2383}
2384
2385template <class _CharT, class _InputIterator>
2386typename time_get<_CharT, _InputIterator>::dateorder
2387time_get<_CharT, _InputIterator>::do_date_order() const
2388{
2389 return mdy;
2390}
2391
2392template <class _CharT, class _InputIterator>
2393_InputIterator
2394time_get<_CharT, _InputIterator>::do_get_time(iter_type __b, iter_type __e,
2395 ios_base& __iob,
2396 ios_base::iostate& __err,
2397 tm* __tm) const
2398{
2399 const char_type __fmt[] = {'%', 'H', ':', '%', 'M', ':', '%', 'S'};
2400 return get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2401}
2402
2403template <class _CharT, class _InputIterator>
2404_InputIterator
2405time_get<_CharT, _InputIterator>::do_get_date(iter_type __b, iter_type __e,
2406 ios_base& __iob,
2407 ios_base::iostate& __err,
2408 tm* __tm) const
2409{
2410 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2411 const string_type& __fmt = this->__x();
2412 return get(__b, __e, __iob, __err, __tm, __fmt.data(), __fmt.data() + __fmt.size());
2413}
2414
2415template <class _CharT, class _InputIterator>
2416_InputIterator
2417time_get<_CharT, _InputIterator>::do_get_weekday(iter_type __b, iter_type __e,
2418 ios_base& __iob,
2419 ios_base::iostate& __err,
2420 tm* __tm) const
2421{
2422 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2423 __get_weekdayname(__tm->tm_wday, __b, __e, __err, __ct);
2424 return __b;
2425}
2426
2427template <class _CharT, class _InputIterator>
2428_InputIterator
2429time_get<_CharT, _InputIterator>::do_get_monthname(iter_type __b, iter_type __e,
2430 ios_base& __iob,
2431 ios_base::iostate& __err,
2432 tm* __tm) const
2433{
2434 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2435 __get_monthname(__tm->tm_mon, __b, __e, __err, __ct);
2436 return __b;
2437}
2438
2439template <class _CharT, class _InputIterator>
2440_InputIterator
2441time_get<_CharT, _InputIterator>::do_get_year(iter_type __b, iter_type __e,
2442 ios_base& __iob,
2443 ios_base::iostate& __err,
2444 tm* __tm) const
2445{
2446 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2447 __get_year(__tm->tm_year, __b, __e, __err, __ct);
2448 return __b;
2449}
2450
2451template <class _CharT, class _InputIterator>
2452_InputIterator
2453time_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
2454 ios_base& __iob,
2455 ios_base::iostate& __err, tm* __tm,
2456 char __fmt, char) const
2457{
2458 __err = ios_base::goodbit;
2459 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2460 switch (__fmt)
2461 {
2462 case 'a':
2463 case 'A':
2464 __get_weekdayname(__tm->tm_wday, __b, __e, __err, __ct);
2465 break;
2466 case 'b':
2467 case 'B':
2468 case 'h':
2469 __get_monthname(__tm->tm_mon, __b, __e, __err, __ct);
2470 break;
2471 case 'c':
2472 {
2473 const string_type& __fmt = this->__c();
2474 __b = get(__b, __e, __iob, __err, __tm, __fmt.data(), __fmt.data() + __fmt.size());
2475 }
2476 break;
2477 case 'd':
2478 case 'e':
2479 __get_day(__tm->tm_mday, __b, __e, __err, __ct);
2480 break;
2481 case 'D':
2482 {
2483 const char_type __fmt[] = {'%', 'm', '/', '%', 'd', '/', '%', 'y'};
2484 __b = get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2485 }
2486 break;
Howard Hinnant506b3642011-04-10 17:54:14 +00002487 case 'F':
2488 {
2489 const char_type __fmt[] = {'%', 'Y', '-', '%', 'm', '-', '%', 'd'};
2490 __b = get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2491 }
2492 break;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002493 case 'H':
2494 __get_hour(__tm->tm_hour, __b, __e, __err, __ct);
2495 break;
2496 case 'I':
2497 __get_12_hour(__tm->tm_hour, __b, __e, __err, __ct);
2498 break;
2499 case 'j':
2500 __get_day_year_num(__tm->tm_yday, __b, __e, __err, __ct);
2501 break;
2502 case 'm':
2503 __get_month(__tm->tm_mon, __b, __e, __err, __ct);
2504 break;
2505 case 'M':
2506 __get_minute(__tm->tm_min, __b, __e, __err, __ct);
2507 break;
2508 case 'n':
2509 case 't':
2510 __get_white_space(__b, __e, __err, __ct);
2511 break;
2512 case 'p':
2513 __get_am_pm(__tm->tm_hour, __b, __e, __err, __ct);
2514 break;
2515 case 'r':
2516 {
2517 const char_type __fmt[] = {'%', 'I', ':', '%', 'M', ':', '%', 'S', ' ', '%', 'p'};
2518 __b = get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2519 }
2520 break;
2521 case 'R':
2522 {
2523 const char_type __fmt[] = {'%', 'H', ':', '%', 'M'};
2524 __b = get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2525 }
2526 break;
2527 case 'S':
2528 __get_second(__tm->tm_sec, __b, __e, __err, __ct);
2529 break;
2530 case 'T':
2531 {
2532 const char_type __fmt[] = {'%', 'H', ':', '%', 'M', ':', '%', 'S'};
2533 __b = get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2534 }
2535 break;
2536 case 'w':
2537 __get_weekday(__tm->tm_wday, __b, __e, __err, __ct);
2538 break;
2539 case 'x':
2540 return do_get_date(__b, __e, __iob, __err, __tm);
2541 case 'X':
2542 {
2543 const string_type& __fmt = this->__X();
2544 __b = get(__b, __e, __iob, __err, __tm, __fmt.data(), __fmt.data() + __fmt.size());
2545 }
2546 break;
2547 case 'y':
2548 __get_year(__tm->tm_year, __b, __e, __err, __ct);
2549 break;
2550 case 'Y':
2551 __get_year4(__tm->tm_year, __b, __e, __err, __ct);
2552 break;
2553 case '%':
2554 __get_percent(__b, __e, __err, __ct);
2555 break;
2556 default:
2557 __err |= ios_base::failbit;
2558 }
2559 return __b;
2560}
2561
2562extern template class time_get<char>;
2563extern template class time_get<wchar_t>;
2564
2565class __time_get
2566{
2567protected:
2568 locale_t __loc_;
2569
2570 __time_get(const char* __nm);
2571 __time_get(const string& __nm);
2572 ~__time_get();
2573};
2574
2575template <class _CharT>
2576class __time_get_storage
2577 : public __time_get
2578{
2579protected:
2580 typedef basic_string<_CharT> string_type;
2581
2582 string_type __weeks_[14];
2583 string_type __months_[24];
2584 string_type __am_pm_[2];
2585 string_type __c_;
2586 string_type __r_;
2587 string_type __x_;
2588 string_type __X_;
2589
2590 explicit __time_get_storage(const char* __nm);
2591 explicit __time_get_storage(const string& __nm);
2592
2593 _LIBCPP_ALWAYS_INLINE ~__time_get_storage() {}
2594
2595 time_base::dateorder __do_date_order() const;
2596
2597private:
2598 void init(const ctype<_CharT>&);
2599 string_type __analyze(char __fmt, const ctype<_CharT>&);
2600};
2601
2602template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00002603class _LIBCPP_VISIBLE time_get_byname
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002604 : public time_get<_CharT, _InputIterator>,
2605 private __time_get_storage<_CharT>
2606{
2607public:
2608 typedef time_base::dateorder dateorder;
2609 typedef _InputIterator iter_type;
2610 typedef _CharT char_type;
2611 typedef basic_string<char_type> string_type;
2612
Howard Hinnant82894812010-09-22 16:48:34 +00002613 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002614 explicit time_get_byname(const char* __nm, size_t __refs = 0)
2615 : time_get<_CharT, _InputIterator>(__refs),
2616 __time_get_storage<_CharT>(__nm) {}
Howard Hinnant82894812010-09-22 16:48:34 +00002617 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002618 explicit time_get_byname(const string& __nm, size_t __refs = 0)
2619 : time_get<_CharT, _InputIterator>(__refs),
2620 __time_get_storage<_CharT>(__nm) {}
2621
2622protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002623 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002624 ~time_get_byname() {}
2625
Howard Hinnant82894812010-09-22 16:48:34 +00002626 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002627 virtual dateorder do_date_order() const {return this->__do_date_order();}
2628private:
Howard Hinnant82894812010-09-22 16:48:34 +00002629 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002630 virtual const string_type* __weeks() const {return this->__weeks_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002631 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002632 virtual const string_type* __months() const {return this->__months_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002633 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002634 virtual const string_type* __am_pm() const {return this->__am_pm_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002635 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002636 virtual const string_type& __c() const {return this->__c_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002637 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002638 virtual const string_type& __r() const {return this->__r_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002639 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002640 virtual const string_type& __x() const {return this->__x_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002641 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002642 virtual const string_type& __X() const {return this->__X_;}
2643};
2644
2645extern template class time_get_byname<char>;
2646extern template class time_get_byname<wchar_t>;
2647
2648class __time_put
2649{
2650 locale_t __loc_;
2651protected:
Sean Hunt0389c532011-07-12 00:55:04 +00002652#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002653 _LIBCPP_ALWAYS_INLINE __time_put() : __loc_(0) {}
Sean Hunt0389c532011-07-12 00:55:04 +00002654#else // _LIBCPP_STABLE_APPLE_ABI
2655 _LIBCPP_ALWAYS_INLINE __time_put() : __loc_(__cloc()) {}
2656#endif // _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002657 __time_put(const char* __nm);
2658 __time_put(const string& __nm);
2659 ~__time_put();
2660 void __do_put(char* __nb, char*& __ne, const tm* __tm,
2661 char __fmt, char __mod) const;
2662 void __do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
2663 char __fmt, char __mod) const;
2664};
2665
2666template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00002667class _LIBCPP_VISIBLE time_put
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002668 : public locale::facet,
2669 private __time_put
2670{
2671public:
2672 typedef _CharT char_type;
2673 typedef _OutputIterator iter_type;
2674
2675 _LIBCPP_ALWAYS_INLINE
2676 explicit time_put(size_t __refs = 0)
2677 : locale::facet(__refs) {}
2678
2679 iter_type put(iter_type __s, ios_base& __iob, char_type __fl, const tm* __tm,
2680 const char_type* __pb, const char_type* __pe) const;
2681
2682 _LIBCPP_ALWAYS_INLINE
2683 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
2684 const tm* __tm, char __fmt, char __mod = 0) const
2685 {
2686 return do_put(__s, __iob, __fl, __tm, __fmt, __mod);
2687 }
2688
2689 static locale::id id;
2690
2691protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002692 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002693 ~time_put() {}
2694 virtual iter_type do_put(iter_type __s, ios_base&, char_type, const tm* __tm,
2695 char __fmt, char __mod) const;
2696
Howard Hinnant82894812010-09-22 16:48:34 +00002697 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002698 explicit time_put(const char* __nm, size_t __refs)
2699 : locale::facet(__refs),
2700 __time_put(__nm) {}
Howard Hinnant82894812010-09-22 16:48:34 +00002701 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002702 explicit time_put(const string& __nm, size_t __refs)
2703 : locale::facet(__refs),
2704 __time_put(__nm) {}
2705};
2706
2707template <class _CharT, class _OutputIterator>
2708locale::id
2709time_put<_CharT, _OutputIterator>::id;
2710
2711template <class _CharT, class _OutputIterator>
2712_OutputIterator
2713time_put<_CharT, _OutputIterator>::put(iter_type __s, ios_base& __iob,
2714 char_type __fl, const tm* __tm,
2715 const char_type* __pb,
2716 const char_type* __pe) const
2717{
2718 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2719 for (; __pb != __pe; ++__pb)
2720 {
2721 if (__ct.narrow(*__pb, 0) == '%')
2722 {
2723 if (++__pb == __pe)
2724 {
2725 *__s++ = __pb[-1];
2726 break;
2727 }
2728 char __mod = 0;
2729 char __fmt = __ct.narrow(*__pb, 0);
2730 if (__fmt == 'E' || __fmt == 'O')
2731 {
2732 if (++__pb == __pe)
2733 {
2734 *__s++ = __pb[-2];
2735 *__s++ = __pb[-1];
2736 break;
2737 }
2738 __mod = __fmt;
2739 __fmt = __ct.narrow(*__pb, 0);
2740 }
2741 __s = do_put(__s, __iob, __fl, __tm, __fmt, __mod);
2742 }
2743 else
2744 *__s++ = *__pb;
2745 }
2746 return __s;
2747}
2748
2749template <class _CharT, class _OutputIterator>
2750_OutputIterator
2751time_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
2752 char_type, const tm* __tm,
2753 char __fmt, char __mod) const
2754{
2755 char_type __nar[100];
2756 char_type* __nb = __nar;
2757 char_type* __ne = __nb + 100;
2758 __do_put(__nb, __ne, __tm, __fmt, __mod);
Howard Hinnant0949eed2011-06-30 21:18:19 +00002759 return _VSTD::copy(__nb, __ne, __s);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002760}
2761
2762extern template class time_put<char>;
2763extern template class time_put<wchar_t>;
2764
2765template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00002766class _LIBCPP_VISIBLE time_put_byname
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002767 : public time_put<_CharT, _OutputIterator>
2768{
2769public:
2770 _LIBCPP_ALWAYS_INLINE
2771 explicit time_put_byname(const char* __nm, size_t __refs = 0)
2772 : time_put<_CharT, _OutputIterator>(__nm, __refs) {}
2773
2774 _LIBCPP_ALWAYS_INLINE
2775 explicit time_put_byname(const string& __nm, size_t __refs = 0)
2776 : time_put<_CharT, _OutputIterator>(__nm, __refs) {}
2777
2778protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002779 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002780 ~time_put_byname() {}
2781};
2782
2783extern template class time_put_byname<char>;
2784extern template class time_put_byname<wchar_t>;
2785
2786// money_base
2787
Howard Hinnant82894812010-09-22 16:48:34 +00002788class _LIBCPP_VISIBLE money_base
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002789{
2790public:
2791 enum part {none, space, symbol, sign, value};
2792 struct pattern {char field[4];};
2793
2794 _LIBCPP_ALWAYS_INLINE money_base() {}
2795};
2796
2797// moneypunct
2798
2799template <class _CharT, bool _International = false>
Howard Hinnant82894812010-09-22 16:48:34 +00002800class _LIBCPP_VISIBLE moneypunct
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002801 : public locale::facet,
2802 public money_base
2803{
2804public:
2805 typedef _CharT char_type;
2806 typedef basic_string<char_type> string_type;
2807
Howard Hinnant82894812010-09-22 16:48:34 +00002808 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002809 explicit moneypunct(size_t __refs = 0)
2810 : locale::facet(__refs) {}
2811
2812 _LIBCPP_ALWAYS_INLINE char_type decimal_point() const {return do_decimal_point();}
2813 _LIBCPP_ALWAYS_INLINE char_type thousands_sep() const {return do_thousands_sep();}
2814 _LIBCPP_ALWAYS_INLINE string grouping() const {return do_grouping();}
2815 _LIBCPP_ALWAYS_INLINE string_type curr_symbol() const {return do_curr_symbol();}
2816 _LIBCPP_ALWAYS_INLINE string_type positive_sign() const {return do_positive_sign();}
2817 _LIBCPP_ALWAYS_INLINE string_type negative_sign() const {return do_negative_sign();}
2818 _LIBCPP_ALWAYS_INLINE int frac_digits() const {return do_frac_digits();}
2819 _LIBCPP_ALWAYS_INLINE pattern pos_format() const {return do_pos_format();}
2820 _LIBCPP_ALWAYS_INLINE pattern neg_format() const {return do_neg_format();}
2821
2822 static locale::id id;
2823 static const bool intl = _International;
2824
2825protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002826 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002827 ~moneypunct() {}
2828
2829 virtual char_type do_decimal_point() const {return numeric_limits<char_type>::max();}
2830 virtual char_type do_thousands_sep() const {return numeric_limits<char_type>::max();}
2831 virtual string do_grouping() const {return string();}
2832 virtual string_type do_curr_symbol() const {return string_type();}
2833 virtual string_type do_positive_sign() const {return string_type();}
2834 virtual string_type do_negative_sign() const {return string_type(1, '-');}
2835 virtual int do_frac_digits() const {return 0;}
2836 virtual pattern do_pos_format() const
2837 {pattern __p = {symbol, sign, none, value}; return __p;}
2838 virtual pattern do_neg_format() const
2839 {pattern __p = {symbol, sign, none, value}; return __p;}
2840};
2841
2842template <class _CharT, bool _International>
2843locale::id
2844moneypunct<_CharT, _International>::id;
2845
2846extern template class moneypunct<char, false>;
2847extern template class moneypunct<char, true>;
2848extern template class moneypunct<wchar_t, false>;
2849extern template class moneypunct<wchar_t, true>;
2850
2851// moneypunct_byname
2852
2853template <class _CharT, bool _International = false>
Howard Hinnant82894812010-09-22 16:48:34 +00002854class _LIBCPP_VISIBLE moneypunct_byname
2855 : public moneypunct<_CharT, _International>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002856{
2857public:
2858 typedef money_base::pattern pattern;
2859 typedef _CharT char_type;
2860 typedef basic_string<char_type> string_type;
2861
2862 _LIBCPP_ALWAYS_INLINE
2863 explicit moneypunct_byname(const char* __nm, size_t __refs = 0)
2864 : moneypunct<_CharT, _International>(__refs) {init(__nm);}
2865
2866 _LIBCPP_ALWAYS_INLINE
2867 explicit moneypunct_byname(const string& __nm, size_t __refs = 0)
2868 : moneypunct<_CharT, _International>(__refs) {init(__nm.c_str());}
2869
2870protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002871 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002872 ~moneypunct_byname() {}
2873
2874 virtual char_type do_decimal_point() const {return __decimal_point_;}
2875 virtual char_type do_thousands_sep() const {return __thousands_sep_;}
2876 virtual string do_grouping() const {return __grouping_;}
2877 virtual string_type do_curr_symbol() const {return __curr_symbol_;}
2878 virtual string_type do_positive_sign() const {return __positive_sign_;}
2879 virtual string_type do_negative_sign() const {return __negative_sign_;}
2880 virtual int do_frac_digits() const {return __frac_digits_;}
2881 virtual pattern do_pos_format() const {return __pos_format_;}
2882 virtual pattern do_neg_format() const {return __neg_format_;}
2883
2884private:
2885 char_type __decimal_point_;
2886 char_type __thousands_sep_;
2887 string __grouping_;
2888 string_type __curr_symbol_;
2889 string_type __positive_sign_;
2890 string_type __negative_sign_;
2891 int __frac_digits_;
2892 pattern __pos_format_;
2893 pattern __neg_format_;
2894
2895 void init(const char*);
2896};
2897
2898template<> void moneypunct_byname<char, false>::init(const char*);
2899template<> void moneypunct_byname<char, true>::init(const char*);
2900template<> void moneypunct_byname<wchar_t, false>::init(const char*);
2901template<> void moneypunct_byname<wchar_t, true>::init(const char*);
2902
2903extern template class moneypunct_byname<char, false>;
2904extern template class moneypunct_byname<char, true>;
2905extern template class moneypunct_byname<wchar_t, false>;
2906extern template class moneypunct_byname<wchar_t, true>;
2907
2908// money_get
2909
2910template <class _CharT>
2911class __money_get
2912{
2913protected:
2914 typedef _CharT char_type;
2915 typedef basic_string<char_type> string_type;
2916
2917 _LIBCPP_ALWAYS_INLINE __money_get() {}
2918
2919 static void __gather_info(bool __intl, const locale& __loc,
2920 money_base::pattern& __pat, char_type& __dp,
2921 char_type& __ts, string& __grp,
2922 string_type& __sym, string_type& __psn,
2923 string_type& __nsn, int& __fd);
2924};
2925
2926template <class _CharT>
2927void
2928__money_get<_CharT>::__gather_info(bool __intl, const locale& __loc,
2929 money_base::pattern& __pat, char_type& __dp,
2930 char_type& __ts, string& __grp,
2931 string_type& __sym, string_type& __psn,
2932 string_type& __nsn, int& __fd)
2933{
2934 if (__intl)
2935 {
2936 const moneypunct<char_type, true>& __mp =
2937 use_facet<moneypunct<char_type, true> >(__loc);
2938 __pat = __mp.neg_format();
2939 __nsn = __mp.negative_sign();
2940 __psn = __mp.positive_sign();
2941 __dp = __mp.decimal_point();
2942 __ts = __mp.thousands_sep();
2943 __grp = __mp.grouping();
2944 __sym = __mp.curr_symbol();
2945 __fd = __mp.frac_digits();
2946 }
2947 else
2948 {
2949 const moneypunct<char_type, false>& __mp =
2950 use_facet<moneypunct<char_type, false> >(__loc);
2951 __pat = __mp.neg_format();
2952 __nsn = __mp.negative_sign();
2953 __psn = __mp.positive_sign();
2954 __dp = __mp.decimal_point();
2955 __ts = __mp.thousands_sep();
2956 __grp = __mp.grouping();
2957 __sym = __mp.curr_symbol();
2958 __fd = __mp.frac_digits();
2959 }
2960}
2961
2962extern template class __money_get<char>;
2963extern template class __money_get<wchar_t>;
2964
2965template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00002966class _LIBCPP_VISIBLE money_get
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002967 : public locale::facet,
2968 private __money_get<_CharT>
2969{
2970public:
2971 typedef _CharT char_type;
2972 typedef _InputIterator iter_type;
2973 typedef basic_string<char_type> string_type;
2974
2975 _LIBCPP_ALWAYS_INLINE
2976 explicit money_get(size_t __refs = 0)
2977 : locale::facet(__refs) {}
2978
2979 _LIBCPP_ALWAYS_INLINE
2980 iter_type get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob,
2981 ios_base::iostate& __err, long double& __v) const
2982 {
2983 return do_get(__b, __e, __intl, __iob, __err, __v);
2984 }
2985
2986 _LIBCPP_ALWAYS_INLINE
2987 iter_type get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob,
2988 ios_base::iostate& __err, string_type& __v) const
2989 {
2990 return do_get(__b, __e, __intl, __iob, __err, __v);
2991 }
2992
2993 static locale::id id;
2994
2995protected:
2996
Howard Hinnant82894812010-09-22 16:48:34 +00002997 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002998 ~money_get() {}
Howard Hinnant324bb032010-08-22 00:02:43 +00002999
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003000 virtual iter_type do_get(iter_type __b, iter_type __e, bool __intl,
3001 ios_base& __iob, ios_base::iostate& __err,
3002 long double& __v) const;
3003 virtual iter_type do_get(iter_type __b, iter_type __e, bool __intl,
3004 ios_base& __iob, ios_base::iostate& __err,
3005 string_type& __v) const;
3006
3007private:
3008 static bool __do_get(iter_type& __b, iter_type __e,
3009 bool __intl, const locale& __loc,
3010 ios_base::fmtflags __flags, ios_base::iostate& __err,
3011 bool& __neg, const ctype<char_type>& __ct,
3012 unique_ptr<char_type, void(*)(void*)>& __wb,
3013 char_type*& __wn, char_type* __we);
3014};
3015
3016template <class _CharT, class _InputIterator>
3017locale::id
3018money_get<_CharT, _InputIterator>::id;
3019
3020void __do_nothing(void*);
3021
3022template <class _Tp>
3023_LIBCPP_HIDDEN
3024void
3025__double_or_nothing(unique_ptr<_Tp, void(*)(void*)>& __b, _Tp*& __n, _Tp*& __e)
3026{
3027 bool __owns = __b.get_deleter() != __do_nothing;
3028 size_t __cur_cap = (__e-__b.get()) * sizeof(_Tp);
3029 size_t __new_cap = __cur_cap < numeric_limits<size_t>::max() / 2 ?
3030 2 * __cur_cap : numeric_limits<size_t>::max();
3031 size_t __n_off = __n - __b.get();
3032 _Tp* __t = (_Tp*)realloc(__owns ? __b.get() : 0, __new_cap);
3033 if (__t == 0)
3034 __throw_bad_alloc();
3035 if (__owns)
3036 __b.release();
3037 __b = unique_ptr<_Tp, void(*)(void*)>(__t, free);
3038 __new_cap /= sizeof(_Tp);
3039 __n = __b.get() + __n_off;
3040 __e = __b.get() + __new_cap;
3041}
3042
3043// true == success
3044template <class _CharT, class _InputIterator>
3045bool
3046money_get<_CharT, _InputIterator>::__do_get(iter_type& __b, iter_type __e,
3047 bool __intl, const locale& __loc,
3048 ios_base::fmtflags __flags,
3049 ios_base::iostate& __err,
3050 bool& __neg,
3051 const ctype<char_type>& __ct,
3052 unique_ptr<char_type, void(*)(void*)>& __wb,
3053 char_type*& __wn, char_type* __we)
3054{
3055 const unsigned __bz = 100;
3056 unsigned __gbuf[__bz];
3057 unique_ptr<unsigned, void(*)(void*)> __gb(__gbuf, __do_nothing);
3058 unsigned* __gn = __gb.get();
3059 unsigned* __ge = __gn + __bz;
3060 money_base::pattern __pat;
3061 char_type __dp;
3062 char_type __ts;
3063 string __grp;
3064 string_type __sym;
3065 string_type __psn;
3066 string_type __nsn;
3067 int __fd;
3068 __money_get<_CharT>::__gather_info(__intl, __loc, __pat, __dp, __ts, __grp,
3069 __sym, __psn, __nsn, __fd);
3070 const string_type* __trailing_sign = 0;
3071 __wn = __wb.get();
3072 for (unsigned __p = 0; __p < 4 && __b != __e; ++__p)
3073 {
3074 switch (__pat.field[__p])
3075 {
3076 case money_base::space:
3077 if (__p != 3)
3078 {
3079 if (__ct.is(ctype_base::space, *__b))
3080 ++__b;
3081 else
3082 {
3083 __err |= ios_base::failbit;
3084 return false;
3085 }
3086 }
Howard Hinnant324bb032010-08-22 00:02:43 +00003087 // drop through
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003088 case money_base::none:
3089 if (__p != 3)
3090 {
3091 while (__b != __e && __ct.is(ctype_base::space, *__b))
3092 ++__b;
3093 }
3094 break;
3095 case money_base::sign:
3096 if (__psn.size() + __nsn.size() > 0)
3097 {
3098 if (__psn.size() == 0 || __nsn.size() == 0)
3099 { // sign is optional
3100 if (__psn.size() > 0)
3101 { // __nsn.size() == 0
3102 if (*__b == __psn[0])
3103 {
3104 ++__b;
3105 if (__psn.size() > 1)
3106 __trailing_sign = &__psn;
3107 }
3108 else
3109 __neg = true;
3110 }
3111 else if (*__b == __nsn[0]) // __nsn.size() > 0 && __psn.size() == 0
3112 {
3113 ++__b;
3114 __neg = true;
3115 if (__nsn.size() > 1)
3116 __trailing_sign = &__nsn;
3117 }
3118 }
3119 else // sign is required
3120 {
3121 if (*__b == __psn[0])
3122 {
3123 ++__b;
3124 if (__psn.size() > 1)
3125 __trailing_sign = &__psn;
3126 }
3127 else if (*__b == __nsn[0])
3128 {
3129 ++__b;
3130 __neg = true;
3131 if (__nsn.size() > 1)
3132 __trailing_sign = &__nsn;
3133 }
3134 else
3135 {
3136 __err |= ios_base::failbit;
3137 return false;
3138 }
3139 }
3140 }
3141 break;
3142 case money_base::symbol:
3143 {
3144 bool __more_needed = __trailing_sign ||
3145 (__p < 2) ||
3146 (__p == 2 && __pat.field[3] != static_cast<char>(money_base::none));
3147 bool __sb = __flags & ios_base::showbase;
3148 if (__sb || __more_needed)
3149 {
3150 ios_base::iostate __et = ios_base::goodbit;
3151 string_type* __k = __scan_keyword(__b, __e, &__sym, &__sym+1,
3152 __ct, __et);
3153 if (__sb && __k != &__sym)
3154 {
3155 __err |= ios_base::failbit;
3156 return false;
3157 }
3158 }
3159 }
3160 break;
3161 case money_base::value:
3162 {
3163 unsigned __ng = 0;
3164 for (; __b != __e; ++__b)
3165 {
3166 char_type __c = *__b;
3167 if (__ct.is(ctype_base::digit, __c))
3168 {
3169 if (__wn == __we)
3170 __double_or_nothing(__wb, __wn, __we);
3171 *__wn++ = __c;
3172 ++__ng;
3173 }
3174 else if (__grp.size() > 0 && __ng > 0 && __c == __ts)
3175 {
3176 if (__gn == __ge)
3177 __double_or_nothing(__gb, __gn, __ge);
3178 *__gn++ = __ng;
3179 __ng = 0;
3180 }
3181 else
3182 break;
3183 }
3184 if (__gb.get() != __gn && __ng > 0)
3185 {
3186 if (__gn == __ge)
3187 __double_or_nothing(__gb, __gn, __ge);
3188 *__gn++ = __ng;
3189 }
3190 if (__fd > 0)
3191 {
3192 if (__b == __e || *__b != __dp)
3193 {
3194 __err |= ios_base::failbit;
3195 return false;
3196 }
3197 for (++__b; __fd > 0; --__fd, ++__b)
3198 {
3199 if (__b == __e || !__ct.is(ctype_base::digit, *__b))
3200 {
3201 __err |= ios_base::failbit;
3202 return false;
3203 }
3204 if (__wn == __we)
3205 __double_or_nothing(__wb, __wn, __we);
3206 *__wn++ = *__b;
3207 }
3208 }
3209 if (__wn == __wb.get())
3210 {
3211 __err |= ios_base::failbit;
3212 return false;
3213 }
3214 }
3215 break;
3216 }
3217 }
3218 if (__trailing_sign)
3219 {
3220 for (unsigned __i = 1; __i < __trailing_sign->size(); ++__i, ++__b)
3221 {
3222 if (__b == __e || *__b != (*__trailing_sign)[__i])
3223 {
3224 __err |= ios_base::failbit;
3225 return false;
3226 }
3227 }
3228 }
3229 if (__gb.get() != __gn)
3230 {
3231 ios_base::iostate __et = ios_base::goodbit;
3232 __check_grouping(__grp, __gb.get(), __gn, __et);
3233 if (__et)
3234 {
3235 __err |= ios_base::failbit;
3236 return false;
3237 }
3238 }
3239 return true;
3240}
3241
3242template <class _CharT, class _InputIterator>
3243_InputIterator
3244money_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
3245 bool __intl, ios_base& __iob,
3246 ios_base::iostate& __err,
3247 long double& __v) const
3248{
3249 const unsigned __bz = 100;
3250 char_type __wbuf[__bz];
3251 unique_ptr<char_type, void(*)(void*)> __wb(__wbuf, __do_nothing);
3252 char_type* __wn;
3253 char_type* __we = __wbuf + __bz;
3254 locale __loc = __iob.getloc();
3255 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3256 bool __neg = false;
3257 if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct,
3258 __wb, __wn, __we))
3259 {
3260 const char __src[] = "0123456789";
3261 char_type __atoms[sizeof(__src)-1];
3262 __ct.widen(__src, __src + (sizeof(__src)-1), __atoms);
3263 char __nbuf[__bz];
3264 char* __nc = __nbuf;
3265 unique_ptr<char, void(*)(void*)> __h(0, free);
3266 if (__wn - __wb.get() > __bz-2)
3267 {
3268 __h.reset((char*)malloc(__wn - __wb.get() + 2));
3269 if (__h.get() == 0)
3270 __throw_bad_alloc();
3271 __nc = __h.get();
3272 }
3273 if (__neg)
3274 *__nc++ = '-';
3275 for (const char_type* __w = __wb.get(); __w < __wn; ++__w, ++__nc)
3276 *__nc = __src[find(__atoms, __atoms+sizeof(__atoms), *__w) - __atoms];
3277 *__nc = char();
3278 if (sscanf(__nbuf, "%Lf", &__v) != 1)
3279 __throw_runtime_error("money_get error");
3280 }
3281 if (__b == __e)
3282 __err |= ios_base::eofbit;
3283 return __b;
3284}
3285
3286template <class _CharT, class _InputIterator>
3287_InputIterator
3288money_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
3289 bool __intl, ios_base& __iob,
3290 ios_base::iostate& __err,
3291 string_type& __v) const
3292{
3293 const unsigned __bz = 100;
3294 char_type __wbuf[__bz];
3295 unique_ptr<char_type, void(*)(void*)> __wb(__wbuf, __do_nothing);
3296 char_type* __wn;
3297 char_type* __we = __wbuf + __bz;
3298 locale __loc = __iob.getloc();
3299 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3300 bool __neg = false;
3301 if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct,
3302 __wb, __wn, __we))
3303 {
3304 __v.clear();
3305 if (__neg)
3306 __v.push_back(__ct.widen('-'));
3307 char_type __z = __ct.widen('0');
3308 char_type* __w;
3309 for (__w = __wb.get(); __w < __wn-1; ++__w)
3310 if (*__w != __z)
3311 break;
3312 __v.append(__w, __wn);
3313 }
3314 if (__b == __e)
3315 __err |= ios_base::eofbit;
3316 return __b;
3317}
3318
3319extern template class money_get<char>;
3320extern template class money_get<wchar_t>;
3321
3322// money_put
3323
3324template <class _CharT>
3325class __money_put
3326{
3327protected:
3328 typedef _CharT char_type;
3329 typedef basic_string<char_type> string_type;
3330
3331 _LIBCPP_ALWAYS_INLINE __money_put() {}
3332
3333 static void __gather_info(bool __intl, bool __neg, const locale& __loc,
3334 money_base::pattern& __pat, char_type& __dp,
3335 char_type& __ts, string& __grp,
3336 string_type& __sym, string_type& __sn,
3337 int& __fd);
3338 static void __format(char_type* __mb, char_type*& __mi, char_type*& __me,
3339 ios_base::fmtflags __flags,
3340 const char_type* __db, const char_type* __de,
3341 const ctype<char_type>& __ct, bool __neg,
3342 const money_base::pattern& __pat, char_type __dp,
3343 char_type __ts, const string& __grp,
3344 const string_type& __sym, const string_type& __sn,
3345 int __fd);
3346};
3347
3348template <class _CharT>
3349void
3350__money_put<_CharT>::__gather_info(bool __intl, bool __neg, const locale& __loc,
3351 money_base::pattern& __pat, char_type& __dp,
3352 char_type& __ts, string& __grp,
3353 string_type& __sym, string_type& __sn,
3354 int& __fd)
3355{
3356 if (__intl)
3357 {
3358 const moneypunct<char_type, true>& __mp =
3359 use_facet<moneypunct<char_type, true> >(__loc);
3360 if (__neg)
3361 {
3362 __pat = __mp.neg_format();
3363 __sn = __mp.negative_sign();
3364 }
3365 else
3366 {
3367 __pat = __mp.pos_format();
3368 __sn = __mp.positive_sign();
3369 }
3370 __dp = __mp.decimal_point();
3371 __ts = __mp.thousands_sep();
3372 __grp = __mp.grouping();
3373 __sym = __mp.curr_symbol();
3374 __fd = __mp.frac_digits();
3375 }
3376 else
3377 {
3378 const moneypunct<char_type, false>& __mp =
3379 use_facet<moneypunct<char_type, false> >(__loc);
3380 if (__neg)
3381 {
3382 __pat = __mp.neg_format();
3383 __sn = __mp.negative_sign();
3384 }
3385 else
3386 {
3387 __pat = __mp.pos_format();
3388 __sn = __mp.positive_sign();
3389 }
3390 __dp = __mp.decimal_point();
3391 __ts = __mp.thousands_sep();
3392 __grp = __mp.grouping();
3393 __sym = __mp.curr_symbol();
3394 __fd = __mp.frac_digits();
3395 }
3396}
3397
3398template <class _CharT>
3399void
3400__money_put<_CharT>::__format(char_type* __mb, char_type*& __mi, char_type*& __me,
3401 ios_base::fmtflags __flags,
3402 const char_type* __db, const char_type* __de,
3403 const ctype<char_type>& __ct, bool __neg,
3404 const money_base::pattern& __pat, char_type __dp,
3405 char_type __ts, const string& __grp,
3406 const string_type& __sym, const string_type& __sn,
3407 int __fd)
3408{
3409 __me = __mb;
3410 for (unsigned __p = 0; __p < 4; ++__p)
3411 {
3412 switch (__pat.field[__p])
3413 {
3414 case money_base::none:
3415 __mi = __me;
3416 break;
3417 case money_base::space:
3418 __mi = __me;
3419 *__me++ = __ct.widen(' ');
3420 break;
3421 case money_base::sign:
3422 if (!__sn.empty())
3423 *__me++ = __sn[0];
3424 break;
3425 case money_base::symbol:
3426 if (!__sym.empty() && (__flags & ios_base::showbase))
Howard Hinnant0949eed2011-06-30 21:18:19 +00003427 __me = _VSTD::copy(__sym.begin(), __sym.end(), __me);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003428 break;
3429 case money_base::value:
3430 {
3431 // remember start of value so we can reverse it
3432 char_type* __t = __me;
3433 // find beginning of digits
3434 if (__neg)
3435 ++__db;
3436 // find end of digits
3437 const char_type* __d;
3438 for (__d = __db; __d < __de; ++__d)
3439 if (!__ct.is(ctype_base::digit, *__d))
3440 break;
3441 // print fractional part
3442 if (__fd > 0)
3443 {
3444 int __f;
3445 for (__f = __fd; __d > __db && __f > 0; --__f)
3446 *__me++ = *--__d;
3447 char_type __z = __f > 0 ? __ct.widen('0') : char_type();
3448 for (; __f > 0; --__f)
3449 *__me++ = __z;
3450 *__me++ = __dp;
3451 }
3452 // print units part
3453 if (__d == __db)
3454 {
3455 *__me++ = __ct.widen('0');
3456 }
3457 else
3458 {
3459 unsigned __ng = 0;
3460 unsigned __ig = 0;
3461 unsigned __gl = __grp.empty() ? numeric_limits<unsigned>::max()
3462 : static_cast<unsigned>(__grp[__ig]);
3463 while (__d != __db)
3464 {
3465 if (__ng == __gl)
3466 {
3467 *__me++ = __ts;
3468 __ng = 0;
3469 if (++__ig < __grp.size())
3470 __gl = __grp[__ig] == numeric_limits<char>::max() ?
3471 numeric_limits<unsigned>::max() :
3472 static_cast<unsigned>(__grp[__ig]);
3473 }
3474 *__me++ = *--__d;
3475 ++__ng;
3476 }
3477 }
3478 // reverse it
3479 reverse(__t, __me);
3480 }
3481 break;
3482 }
3483 }
3484 // print rest of sign, if any
3485 if (__sn.size() > 1)
Howard Hinnant0949eed2011-06-30 21:18:19 +00003486 __me = _VSTD::copy(__sn.begin()+1, __sn.end(), __me);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003487 // set alignment
3488 if ((__flags & ios_base::adjustfield) == ios_base::left)
3489 __mi = __me;
3490 else if ((__flags & ios_base::adjustfield) != ios_base::internal)
3491 __mi = __mb;
3492}
3493
3494extern template class __money_put<char>;
3495extern template class __money_put<wchar_t>;
3496
3497template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00003498class _LIBCPP_VISIBLE money_put
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003499 : public locale::facet,
3500 private __money_put<_CharT>
3501{
3502public:
3503 typedef _CharT char_type;
3504 typedef _OutputIterator iter_type;
3505 typedef basic_string<char_type> string_type;
3506
3507 _LIBCPP_ALWAYS_INLINE
3508 explicit money_put(size_t __refs = 0)
3509 : locale::facet(__refs) {}
3510
3511 _LIBCPP_ALWAYS_INLINE
3512 iter_type put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl,
3513 long double __units) const
3514 {
3515 return do_put(__s, __intl, __iob, __fl, __units);
3516 }
3517
3518 _LIBCPP_ALWAYS_INLINE
3519 iter_type put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl,
3520 const string_type& __digits) const
3521 {
3522 return do_put(__s, __intl, __iob, __fl, __digits);
3523 }
3524
3525 static locale::id id;
3526
3527protected:
Howard Hinnant82894812010-09-22 16:48:34 +00003528 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003529 ~money_put() {}
3530
3531 virtual iter_type do_put(iter_type __s, bool __intl, ios_base& __iob,
3532 char_type __fl, long double __units) const;
3533 virtual iter_type do_put(iter_type __s, bool __intl, ios_base& __iob,
3534 char_type __fl, const string_type& __digits) const;
3535};
3536
3537template <class _CharT, class _OutputIterator>
3538locale::id
3539money_put<_CharT, _OutputIterator>::id;
3540
3541template <class _CharT, class _OutputIterator>
3542_OutputIterator
3543money_put<_CharT, _OutputIterator>::do_put(iter_type __s, bool __intl,
3544 ios_base& __iob, char_type __fl,
3545 long double __units) const
3546{
3547 // convert to char
3548 const size_t __bs = 100;
3549 char __buf[__bs];
3550 char* __bb = __buf;
3551 char_type __digits[__bs];
3552 char_type* __db = __digits;
3553 size_t __n = snprintf(__bb, __bs, "%.0Lf", __units);
3554 unique_ptr<char, void(*)(void*)> __hn(0, free);
3555 unique_ptr<char_type, void(*)(void*)> __hd(0, free);
3556 // secure memory for digit storage
3557 if (__n > __bs-1)
3558 {
Sean Huntf3907e62011-07-15 05:40:33 +00003559#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantbcbbd4d2011-07-15 14:46:11 +00003560 __n = asprintf_l(&__bb, 0, "%.0Lf", __units);
Sean Huntf3907e62011-07-15 05:40:33 +00003561#else
3562 __n = __asprintf_l(&__bb, __cloc(), "%.0Lf", __units);
3563#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003564 if (__bb == 0)
3565 __throw_bad_alloc();
3566 __hn.reset(__bb);
3567 __hd.reset((char_type*)malloc(__n * sizeof(char_type)));
3568 if (__hd == 0)
3569 __throw_bad_alloc();
3570 __db = __hd.get();
3571 }
3572 // gather info
3573 locale __loc = __iob.getloc();
3574 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3575 __ct.widen(__bb, __bb + __n, __db);
3576 bool __neg = __n > 0 && __bb[0] == '-';
3577 money_base::pattern __pat;
3578 char_type __dp;
3579 char_type __ts;
3580 string __grp;
3581 string_type __sym;
3582 string_type __sn;
3583 int __fd;
3584 this->__gather_info(__intl, __neg, __loc, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3585 // secure memory for formatting
3586 char_type __mbuf[__bs];
3587 char_type* __mb = __mbuf;
3588 unique_ptr<char_type, void(*)(void*)> __hw(0, free);
3589 size_t __exn = static_cast<int>(__n) > __fd ?
3590 (__n - __fd) * 2 + __sn.size() + __sym.size() + __fd + 1
3591 : __sn.size() + __sym.size() + __fd + 2;
3592 if (__exn > __bs)
3593 {
3594 __hw.reset((char_type*)malloc(__exn * sizeof(char_type)));
3595 __mb = __hw.get();
3596 if (__mb == 0)
3597 __throw_bad_alloc();
3598 }
3599 // format
3600 char_type* __mi;
3601 char_type* __me;
3602 this->__format(__mb, __mi, __me, __iob.flags(),
3603 __db, __db + __n, __ct,
3604 __neg, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3605 return __pad_and_output(__s, __mb, __mi, __me, __iob, __fl);
3606}
3607
3608template <class _CharT, class _OutputIterator>
3609_OutputIterator
3610money_put<_CharT, _OutputIterator>::do_put(iter_type __s, bool __intl,
3611 ios_base& __iob, char_type __fl,
3612 const string_type& __digits) const
3613{
3614 // gather info
3615 locale __loc = __iob.getloc();
3616 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3617 bool __neg = __digits.size() > 0 && __digits[0] == __ct.widen('-');
3618 money_base::pattern __pat;
3619 char_type __dp;
3620 char_type __ts;
3621 string __grp;
3622 string_type __sym;
3623 string_type __sn;
3624 int __fd;
3625 this->__gather_info(__intl, __neg, __loc, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3626 // secure memory for formatting
3627 char_type __mbuf[100];
3628 char_type* __mb = __mbuf;
3629 unique_ptr<char_type, void(*)(void*)> __h(0, free);
3630 size_t __exn = __digits.size() > __fd ?
3631 (__digits.size() - __fd) * 2 + __sn.size() + __sym.size() + __fd + 1
3632 : __sn.size() + __sym.size() + __fd + 2;
3633 if (__exn > 100)
3634 {
3635 __h.reset((char_type*)malloc(__exn * sizeof(char_type)));
3636 __mb = __h.get();
3637 if (__mb == 0)
3638 __throw_bad_alloc();
3639 }
3640 // format
3641 char_type* __mi;
3642 char_type* __me;
3643 this->__format(__mb, __mi, __me, __iob.flags(),
3644 __digits.data(), __digits.data() + __digits.size(), __ct,
3645 __neg, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3646 return __pad_and_output(__s, __mb, __mi, __me, __iob, __fl);
3647}
3648
3649extern template class money_put<char>;
3650extern template class money_put<wchar_t>;
3651
3652// messages
3653
Howard Hinnant82894812010-09-22 16:48:34 +00003654class _LIBCPP_VISIBLE messages_base
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003655{
3656public:
Howard Hinnantb2080c72011-02-25 00:51:08 +00003657 typedef ptrdiff_t catalog;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003658
3659 _LIBCPP_ALWAYS_INLINE messages_base() {}
3660};
3661
3662template <class _CharT>
Howard Hinnant82894812010-09-22 16:48:34 +00003663class _LIBCPP_VISIBLE messages
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003664 : public locale::facet,
3665 public messages_base
3666{
3667public:
3668 typedef _CharT char_type;
3669 typedef basic_string<_CharT> string_type;
3670
3671 _LIBCPP_ALWAYS_INLINE
3672 explicit messages(size_t __refs = 0)
3673 : locale::facet(__refs) {}
3674
3675 _LIBCPP_ALWAYS_INLINE
3676 catalog open(const basic_string<char>& __nm, const locale& __loc) const
3677 {
3678 return do_open(__nm, __loc);
3679 }
3680
3681 _LIBCPP_ALWAYS_INLINE
3682 string_type get(catalog __c, int __set, int __msgid,
3683 const string_type& __dflt) const
3684 {
3685 return do_get(__c, __set, __msgid, __dflt);
3686 }
3687
3688 _LIBCPP_ALWAYS_INLINE
3689 void close(catalog __c) const
3690 {
3691 do_close(__c);
3692 }
3693
3694 static locale::id id;
3695
3696protected:
Howard Hinnant82894812010-09-22 16:48:34 +00003697 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003698 ~messages() {}
3699
3700 virtual catalog do_open(const basic_string<char>&, const locale&) const;
3701 virtual string_type do_get(catalog, int __set, int __msgid,
3702 const string_type& __dflt) const;
3703 virtual void do_close(catalog) const;
3704};
3705
3706template <class _CharT>
3707locale::id
3708messages<_CharT>::id;
3709
3710template <class _CharT>
3711typename messages<_CharT>::catalog
3712messages<_CharT>::do_open(const basic_string<char>& __nm, const locale&) const
3713{
Howard Hinnantb2080c72011-02-25 00:51:08 +00003714 catalog __cat = reinterpret_cast<catalog>(catopen(__nm.c_str(), NL_CAT_LOCALE));
3715 if (__cat != -1)
3716 __cat = static_cast<catalog>((static_cast<size_t>(__cat) >> 1));
3717 return __cat;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003718}
3719
3720template <class _CharT>
3721typename messages<_CharT>::string_type
3722messages<_CharT>::do_get(catalog __c, int __set, int __msgid,
3723 const string_type& __dflt) const
3724{
3725 string __ndflt;
3726 __narrow_to_utf8<sizeof(char_type)*__CHAR_BIT__>()(back_inserter(__ndflt),
3727 __dflt.c_str(),
3728 __dflt.c_str() + __dflt.size());
Howard Hinnantb2080c72011-02-25 00:51:08 +00003729 if (__c != -1)
3730 __c <<= 1;
3731 nl_catd __cat = reinterpret_cast<nl_catd>(__c);
3732 char* __n = catgets(__cat, __set, __msgid, __ndflt.c_str());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003733 string_type __w;
3734 __widen_from_utf8<sizeof(char_type)*__CHAR_BIT__>()(back_inserter(__w),
3735 __n, __n + strlen(__n));
3736 return __w;
3737}
3738
3739template <class _CharT>
3740void
3741messages<_CharT>::do_close(catalog __c) const
3742{
Howard Hinnantb2080c72011-02-25 00:51:08 +00003743 if (__c != -1)
3744 __c <<= 1;
3745 nl_catd __cat = reinterpret_cast<nl_catd>(__c);
3746 catclose(__cat);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003747}
3748
3749extern template class messages<char>;
3750extern template class messages<wchar_t>;
3751
3752template <class _CharT>
Howard Hinnant82894812010-09-22 16:48:34 +00003753class _LIBCPP_VISIBLE messages_byname
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003754 : public messages<_CharT>
3755{
3756public:
3757 typedef messages_base::catalog catalog;
3758 typedef basic_string<_CharT> string_type;
3759
3760 _LIBCPP_ALWAYS_INLINE
3761 explicit messages_byname(const char*, size_t __refs = 0)
3762 : messages<_CharT>(__refs) {}
3763
3764 _LIBCPP_ALWAYS_INLINE
3765 explicit messages_byname(const string&, size_t __refs = 0)
3766 : messages<_CharT>(__refs) {}
3767
3768protected:
Howard Hinnant82894812010-09-22 16:48:34 +00003769 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003770 ~messages_byname() {}
3771};
3772
3773extern template class messages_byname<char>;
3774extern template class messages_byname<wchar_t>;
3775
Howard Hinnantd23b4642010-05-31 20:58:54 +00003776template<class _Codecvt, class _Elem = wchar_t,
3777 class _Wide_alloc = allocator<_Elem>,
3778 class _Byte_alloc = allocator<char> >
Howard Hinnant82894812010-09-22 16:48:34 +00003779class _LIBCPP_VISIBLE wstring_convert
Howard Hinnantd23b4642010-05-31 20:58:54 +00003780{
3781public:
3782 typedef basic_string<char, char_traits<char>, _Byte_alloc> byte_string;
3783 typedef basic_string<_Elem, char_traits<_Elem>, _Wide_alloc> wide_string;
3784 typedef typename _Codecvt::state_type state_type;
3785 typedef typename wide_string::traits_type::int_type int_type;
3786
3787private:
3788 byte_string __byte_err_string_;
3789 wide_string __wide_err_string_;
3790 _Codecvt* __cvtptr_;
3791 state_type __cvtstate_;
3792 size_t __cvtcount_;
3793
3794 wstring_convert(const wstring_convert& __wc);
3795 wstring_convert& operator=(const wstring_convert& __wc);
3796public:
3797 wstring_convert(_Codecvt* __pcvt = new _Codecvt);
3798 wstring_convert(_Codecvt* __pcvt, state_type __state);
3799 wstring_convert(const byte_string& __byte_err,
3800 const wide_string& __wide_err = wide_string());
Howard Hinnant73d21a42010-09-04 23:28:19 +00003801#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantd23b4642010-05-31 20:58:54 +00003802 wstring_convert(wstring_convert&& __wc);
3803#endif
3804 ~wstring_convert();
3805
Howard Hinnant82894812010-09-22 16:48:34 +00003806 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003807 wide_string from_bytes(char __byte)
3808 {return from_bytes(&__byte, &__byte+1);}
Howard Hinnant82894812010-09-22 16:48:34 +00003809 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003810 wide_string from_bytes(const char* __ptr)
3811 {return from_bytes(__ptr, __ptr + char_traits<char>::length(__ptr));}
Howard Hinnant82894812010-09-22 16:48:34 +00003812 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003813 wide_string from_bytes(const byte_string& __str)
3814 {return from_bytes(__str.data(), __str.data() + __str.size());}
3815 wide_string from_bytes(const char* __first, const char* __last);
3816
Howard Hinnant82894812010-09-22 16:48:34 +00003817 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003818 byte_string to_bytes(_Elem __wchar)
3819 {return to_bytes(&__wchar, &__wchar+1);}
Howard Hinnant82894812010-09-22 16:48:34 +00003820 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003821 byte_string to_bytes(const _Elem* __wptr)
3822 {return to_bytes(__wptr, __wptr + char_traits<_Elem>::length(__wptr));}
Howard Hinnant82894812010-09-22 16:48:34 +00003823 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003824 byte_string to_bytes(const wide_string& __wstr)
3825 {return to_bytes(__wstr.data(), __wstr.data() + __wstr.size());}
3826 byte_string to_bytes(const _Elem* __first, const _Elem* __last);
3827
Howard Hinnant82894812010-09-22 16:48:34 +00003828 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003829 size_t converted() const {return __cvtcount_;}
Howard Hinnant82894812010-09-22 16:48:34 +00003830 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003831 state_type state() const {return __cvtstate_;}
3832};
3833
3834template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Howard Hinnant82894812010-09-22 16:48:34 +00003835inline _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003836wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3837 wstring_convert(_Codecvt* __pcvt)
3838 : __cvtptr_(__pcvt), __cvtstate_(), __cvtcount_(0)
3839{
3840}
3841
3842template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Howard Hinnant82894812010-09-22 16:48:34 +00003843inline _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003844wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3845 wstring_convert(_Codecvt* __pcvt, state_type __state)
3846 : __cvtptr_(__pcvt), __cvtstate_(__state), __cvtcount_(0)
3847{
3848}
3849
3850template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3851wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3852 wstring_convert(const byte_string& __byte_err, const wide_string& __wide_err)
3853 : __byte_err_string_(__byte_err), __wide_err_string_(__wide_err),
3854 __cvtstate_(), __cvtcount_(0)
3855{
3856 __cvtptr_ = new _Codecvt;
3857}
3858
Howard Hinnant73d21a42010-09-04 23:28:19 +00003859#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantd23b4642010-05-31 20:58:54 +00003860
3861template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Howard Hinnant82894812010-09-22 16:48:34 +00003862inline _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003863wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3864 wstring_convert(wstring_convert&& __wc)
Howard Hinnant0949eed2011-06-30 21:18:19 +00003865 : __byte_err_string_(_VSTD::move(__wc.__byte_err_string_)),
3866 __wide_err_string_(_VSTD::move(__wc.__wide_err_string_)),
Howard Hinnantd23b4642010-05-31 20:58:54 +00003867 __cvtptr_(__wc.__cvtptr_),
3868 __cvtstate_(__wc.__cvtstate_), __cvtcount_(__wc.__cvtstate_)
3869{
3870 __wc.__cvtptr_ = nullptr;
3871}
3872
Howard Hinnantbfd55302010-09-04 23:46:48 +00003873#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantd23b4642010-05-31 20:58:54 +00003874
3875template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3876wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::~wstring_convert()
3877{
3878 delete __cvtptr_;
3879}
3880
3881template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3882typename wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::wide_string
3883wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3884 from_bytes(const char* __frm, const char* __frm_end)
3885{
3886 __cvtcount_ = 0;
3887 if (__cvtptr_ != nullptr)
3888 {
3889 wide_string __ws(2*(__frm_end - __frm), _Elem());
3890 __ws.resize(__ws.capacity());
3891 codecvt_base::result __r = codecvt_base::ok;
3892 state_type __st = __cvtstate_;
3893 if (__frm != __frm_end)
3894 {
3895 _Elem* __to = &__ws[0];
3896 _Elem* __to_end = __to + __ws.size();
3897 const char* __frm_nxt;
3898 do
3899 {
3900 _Elem* __to_nxt;
3901 __r = __cvtptr_->in(__st, __frm, __frm_end, __frm_nxt,
3902 __to, __to_end, __to_nxt);
3903 __cvtcount_ += __frm_nxt - __frm;
3904 if (__frm_nxt == __frm)
3905 {
3906 __r = codecvt_base::error;
3907 }
3908 else if (__r == codecvt_base::noconv)
3909 {
3910 __ws.resize(__to - &__ws[0]);
3911 // This only gets executed if _Elem is char
3912 __ws.append((const _Elem*)__frm, (const _Elem*)__frm_end);
3913 __frm = __frm_nxt;
3914 __r = codecvt_base::ok;
3915 }
3916 else if (__r == codecvt_base::ok)
3917 {
3918 __ws.resize(__to_nxt - &__ws[0]);
3919 __frm = __frm_nxt;
3920 }
3921 else if (__r == codecvt_base::partial)
3922 {
3923 ptrdiff_t __s = __to_nxt - &__ws[0];
3924 __ws.resize(2 * __s);
3925 __to = &__ws[0] + __s;
3926 __to_end = &__ws[0] + __ws.size();
3927 __frm = __frm_nxt;
3928 }
3929 } while (__r == codecvt_base::partial && __frm_nxt < __frm_end);
3930 }
3931 if (__r == codecvt_base::ok)
3932 return __ws;
3933 }
Howard Hinnantd4444702010-08-11 17:04:31 +00003934#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00003935 if (__wide_err_string_.empty())
3936 throw range_error("wstring_convert: from_bytes error");
Howard Hinnant324bb032010-08-22 00:02:43 +00003937#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00003938 return __wide_err_string_;
3939}
3940
3941template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3942typename wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::byte_string
3943wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3944 to_bytes(const _Elem* __frm, const _Elem* __frm_end)
3945{
3946 __cvtcount_ = 0;
3947 if (__cvtptr_ != nullptr)
3948 {
3949 byte_string __bs(2*(__frm_end - __frm), char());
3950 __bs.resize(__bs.capacity());
3951 codecvt_base::result __r = codecvt_base::ok;
3952 state_type __st = __cvtstate_;
3953 if (__frm != __frm_end)
3954 {
3955 char* __to = &__bs[0];
3956 char* __to_end = __to + __bs.size();
3957 const _Elem* __frm_nxt;
3958 do
3959 {
3960 char* __to_nxt;
3961 __r = __cvtptr_->out(__st, __frm, __frm_end, __frm_nxt,
3962 __to, __to_end, __to_nxt);
3963 __cvtcount_ += __frm_nxt - __frm;
3964 if (__frm_nxt == __frm)
3965 {
3966 __r = codecvt_base::error;
3967 }
3968 else if (__r == codecvt_base::noconv)
3969 {
3970 __bs.resize(__to - &__bs[0]);
3971 // This only gets executed if _Elem is char
3972 __bs.append((const char*)__frm, (const char*)__frm_end);
3973 __frm = __frm_nxt;
3974 __r = codecvt_base::ok;
3975 }
3976 else if (__r == codecvt_base::ok)
3977 {
3978 __bs.resize(__to_nxt - &__bs[0]);
3979 __frm = __frm_nxt;
3980 }
3981 else if (__r == codecvt_base::partial)
3982 {
3983 ptrdiff_t __s = __to_nxt - &__bs[0];
3984 __bs.resize(2 * __s);
3985 __to = &__bs[0] + __s;
3986 __to_end = &__bs[0] + __bs.size();
3987 __frm = __frm_nxt;
3988 }
3989 } while (__r == codecvt_base::partial && __frm_nxt < __frm_end);
3990 }
3991 if (__r == codecvt_base::ok)
3992 {
3993 size_t __s = __bs.size();
3994 __bs.resize(__bs.capacity());
3995 char* __to = &__bs[0] + __s;
3996 char* __to_end = __to + __bs.size();
3997 do
3998 {
3999 char* __to_nxt;
4000 __r = __cvtptr_->unshift(__st, __to, __to_end, __to_nxt);
4001 if (__r == codecvt_base::noconv)
4002 {
4003 __bs.resize(__to - &__bs[0]);
4004 __r = codecvt_base::ok;
4005 }
4006 else if (__r == codecvt_base::ok)
4007 {
4008 __bs.resize(__to_nxt - &__bs[0]);
4009 }
4010 else if (__r == codecvt_base::partial)
4011 {
4012 ptrdiff_t __s = __to_nxt - &__bs[0];
4013 __bs.resize(2 * __s);
4014 __to = &__bs[0] + __s;
4015 __to_end = &__bs[0] + __bs.size();
4016 }
4017 } while (__r == codecvt_base::partial);
4018 if (__r == codecvt_base::ok)
4019 return __bs;
4020 }
4021 }
Howard Hinnantd4444702010-08-11 17:04:31 +00004022#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00004023 if (__byte_err_string_.empty())
4024 throw range_error("wstring_convert: to_bytes error");
Howard Hinnant324bb032010-08-22 00:02:43 +00004025#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00004026 return __byte_err_string_;
4027}
4028
4029template <class _Codecvt, class _Elem = wchar_t, class _Tr = char_traits<_Elem> >
Howard Hinnant82894812010-09-22 16:48:34 +00004030class _LIBCPP_VISIBLE wbuffer_convert
Howard Hinnantd23b4642010-05-31 20:58:54 +00004031 : public basic_streambuf<_Elem, _Tr>
4032{
4033public:
4034 // types:
4035 typedef _Elem char_type;
4036 typedef _Tr traits_type;
4037 typedef typename traits_type::int_type int_type;
4038 typedef typename traits_type::pos_type pos_type;
4039 typedef typename traits_type::off_type off_type;
4040 typedef typename _Codecvt::state_type state_type;
4041
4042private:
Howard Hinnant4b53f502010-06-01 20:09:18 +00004043 char* __extbuf_;
4044 const char* __extbufnext_;
4045 const char* __extbufend_;
4046 char __extbuf_min_[8];
4047 size_t __ebs_;
4048 char_type* __intbuf_;
4049 size_t __ibs_;
Howard Hinnantd23b4642010-05-31 20:58:54 +00004050 streambuf* __bufptr_;
Howard Hinnant4b53f502010-06-01 20:09:18 +00004051 _Codecvt* __cv_;
4052 state_type __st_;
4053 ios_base::openmode __cm_;
4054 bool __owns_eb_;
4055 bool __owns_ib_;
4056 bool __always_noconv_;
Howard Hinnantd23b4642010-05-31 20:58:54 +00004057
Howard Hinnant4b53f502010-06-01 20:09:18 +00004058 wbuffer_convert(const wbuffer_convert&);
4059 wbuffer_convert& operator=(const wbuffer_convert&);
Howard Hinnantd23b4642010-05-31 20:58:54 +00004060public:
4061 wbuffer_convert(streambuf* __bytebuf = 0, _Codecvt* __pcvt = new _Codecvt,
Howard Hinnant4b53f502010-06-01 20:09:18 +00004062 state_type __state = state_type());
4063 ~wbuffer_convert();
Howard Hinnantd23b4642010-05-31 20:58:54 +00004064
Howard Hinnant82894812010-09-22 16:48:34 +00004065 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantd23b4642010-05-31 20:58:54 +00004066 streambuf* rdbuf() const {return __bufptr_;}
Howard Hinnant82894812010-09-22 16:48:34 +00004067 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantd23b4642010-05-31 20:58:54 +00004068 streambuf* rdbuf(streambuf* __bytebuf)
4069 {
4070 streambuf* __r = __bufptr_;
4071 __bufptr_ = __bytebuf;
4072 return __r;
4073 }
4074
Howard Hinnant82894812010-09-22 16:48:34 +00004075 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant4b53f502010-06-01 20:09:18 +00004076 state_type state() const {return __st_;}
Howard Hinnantd23b4642010-05-31 20:58:54 +00004077
4078protected:
Howard Hinnant4b53f502010-06-01 20:09:18 +00004079 virtual int_type underflow();
4080 virtual int_type pbackfail(int_type __c = traits_type::eof());
Howard Hinnantd23b4642010-05-31 20:58:54 +00004081 virtual int_type overflow (int_type __c = traits_type::eof());
Howard Hinnant4b53f502010-06-01 20:09:18 +00004082 virtual basic_streambuf<char_type, traits_type>* setbuf(char_type* __s,
4083 streamsize __n);
4084 virtual pos_type seekoff(off_type __off, ios_base::seekdir __way,
4085 ios_base::openmode __wch = ios_base::in | ios_base::out);
4086 virtual pos_type seekpos(pos_type __sp,
4087 ios_base::openmode __wch = ios_base::in | ios_base::out);
4088 virtual int sync();
4089
4090private:
4091 bool __read_mode();
4092 void __write_mode();
4093 wbuffer_convert* __close();
Howard Hinnantd23b4642010-05-31 20:58:54 +00004094};
4095
4096template <class _Codecvt, class _Elem, class _Tr>
Howard Hinnant4b53f502010-06-01 20:09:18 +00004097wbuffer_convert<_Codecvt, _Elem, _Tr>::
4098 wbuffer_convert(streambuf* __bytebuf, _Codecvt* __pcvt, state_type __state)
4099 : __extbuf_(0),
4100 __extbufnext_(0),
4101 __extbufend_(0),
4102 __ebs_(0),
4103 __intbuf_(0),
4104 __ibs_(0),
4105 __bufptr_(__bytebuf),
4106 __cv_(__pcvt),
4107 __st_(__state),
4108 __cm_(0),
4109 __owns_eb_(false),
4110 __owns_ib_(false),
4111 __always_noconv_(__cv_ ? __cv_->always_noconv() : false)
4112{
4113 setbuf(0, 4096);
4114}
4115
4116template <class _Codecvt, class _Elem, class _Tr>
4117wbuffer_convert<_Codecvt, _Elem, _Tr>::~wbuffer_convert()
4118{
4119 __close();
4120 delete __cv_;
4121 if (__owns_eb_)
4122 delete [] __extbuf_;
4123 if (__owns_ib_)
4124 delete [] __intbuf_;
4125}
4126
4127template <class _Codecvt, class _Elem, class _Tr>
4128typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
4129wbuffer_convert<_Codecvt, _Elem, _Tr>::underflow()
4130{
4131 if (__cv_ == 0 || __bufptr_ == 0)
4132 return traits_type::eof();
4133 bool __initial = __read_mode();
4134 char_type __1buf;
4135 if (this->gptr() == 0)
4136 this->setg(&__1buf, &__1buf+1, &__1buf+1);
4137 const size_t __unget_sz = __initial ? 0 : min<size_t>((this->egptr() - this->eback()) / 2, 4);
4138 int_type __c = traits_type::eof();
4139 if (this->gptr() == this->egptr())
4140 {
4141 memmove(this->eback(), this->egptr() - __unget_sz, __unget_sz * sizeof(char_type));
4142 if (__always_noconv_)
4143 {
4144 streamsize __nmemb = static_cast<streamsize>(this->egptr() - this->eback() - __unget_sz);
4145 __nmemb = __bufptr_->sgetn((char*)this->eback() + __unget_sz, __nmemb);
4146 if (__nmemb != 0)
4147 {
4148 this->setg(this->eback(),
4149 this->eback() + __unget_sz,
4150 this->eback() + __unget_sz + __nmemb);
4151 __c = *this->gptr();
4152 }
4153 }
4154 else
4155 {
4156 memmove(__extbuf_, __extbufnext_, __extbufend_ - __extbufnext_);
4157 __extbufnext_ = __extbuf_ + (__extbufend_ - __extbufnext_);
4158 __extbufend_ = __extbuf_ + (__extbuf_ == __extbuf_min_ ? sizeof(__extbuf_min_) : __ebs_);
Howard Hinnant0949eed2011-06-30 21:18:19 +00004159 streamsize __nmemb = _VSTD::min(static_cast<streamsize>(this->egptr() - this->eback() - __unget_sz),
Howard Hinnant4b53f502010-06-01 20:09:18 +00004160 static_cast<streamsize>(__extbufend_ - __extbufnext_));
4161 codecvt_base::result __r;
4162 state_type __svs = __st_;
4163 streamsize __nr = __bufptr_->sgetn(const_cast<char*>(__extbufnext_), __nmemb);
4164 if (__nr != 0)
4165 {
4166 __extbufend_ = __extbufnext_ + __nr;
4167 char_type* __inext;
4168 __r = __cv_->in(__st_, __extbuf_, __extbufend_, __extbufnext_,
4169 this->eback() + __unget_sz,
4170 this->egptr(), __inext);
4171 if (__r == codecvt_base::noconv)
4172 {
4173 this->setg((char_type*)__extbuf_, (char_type*)__extbuf_, (char_type*)__extbufend_);
4174 __c = *this->gptr();
4175 }
4176 else if (__inext != this->eback() + __unget_sz)
4177 {
4178 this->setg(this->eback(), this->eback() + __unget_sz, __inext);
4179 __c = *this->gptr();
4180 }
4181 }
4182 }
4183 }
4184 else
4185 __c = *this->gptr();
4186 if (this->eback() == &__1buf)
4187 this->setg(0, 0, 0);
4188 return __c;
4189}
4190
4191template <class _Codecvt, class _Elem, class _Tr>
4192typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
4193wbuffer_convert<_Codecvt, _Elem, _Tr>::pbackfail(int_type __c)
4194{
4195 if (__cv_ != 0 && __bufptr_ != 0 && this->eback() < this->gptr())
4196 {
4197 if (traits_type::eq_int_type(__c, traits_type::eof()))
4198 {
4199 this->gbump(-1);
4200 return traits_type::not_eof(__c);
4201 }
4202 if (traits_type::eq(traits_type::to_char_type(__c), this->gptr()[-1]))
4203 {
4204 this->gbump(-1);
4205 *this->gptr() = traits_type::to_char_type(__c);
4206 return __c;
4207 }
4208 }
4209 return traits_type::eof();
4210}
4211
4212template <class _Codecvt, class _Elem, class _Tr>
Howard Hinnantd23b4642010-05-31 20:58:54 +00004213typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
4214wbuffer_convert<_Codecvt, _Elem, _Tr>::overflow(int_type __c)
4215{
Howard Hinnant4b53f502010-06-01 20:09:18 +00004216 if (__cv_ == 0 || __bufptr_ == 0)
4217 return traits_type::eof();
4218 __write_mode();
4219 char_type __1buf;
4220 char_type* __pb_save = this->pbase();
4221 char_type* __epb_save = this->epptr();
4222 if (!traits_type::eq_int_type(__c, traits_type::eof()))
4223 {
4224 if (this->pptr() == 0)
4225 this->setp(&__1buf, &__1buf+1);
4226 *this->pptr() = traits_type::to_char_type(__c);
4227 this->pbump(1);
4228 }
4229 if (this->pptr() != this->pbase())
4230 {
4231 if (__always_noconv_)
4232 {
4233 streamsize __nmemb = static_cast<streamsize>(this->pptr() - this->pbase());
4234 if (__bufptr_->sputn((const char*)this->pbase(), __nmemb) != __nmemb)
4235 return traits_type::eof();
4236 }
4237 else
4238 {
4239 char* __extbe = __extbuf_;
4240 codecvt_base::result __r;
4241 do
4242 {
4243 const char_type* __e;
4244 __r = __cv_->out(__st_, this->pbase(), this->pptr(), __e,
4245 __extbuf_, __extbuf_ + __ebs_, __extbe);
4246 if (__e == this->pbase())
4247 return traits_type::eof();
4248 if (__r == codecvt_base::noconv)
4249 {
4250 streamsize __nmemb = static_cast<size_t>(this->pptr() - this->pbase());
4251 if (__bufptr_->sputn((const char*)this->pbase(), __nmemb) != __nmemb)
4252 return traits_type::eof();
4253 }
4254 else if (__r == codecvt_base::ok || __r == codecvt_base::partial)
4255 {
4256 streamsize __nmemb = static_cast<size_t>(__extbe - __extbuf_);
4257 if (__bufptr_->sputn(__extbuf_, __nmemb) != __nmemb)
4258 return traits_type::eof();
4259 if (__r == codecvt_base::partial)
4260 {
4261 this->setp((char_type*)__e, this->pptr());
4262 this->pbump(this->epptr() - this->pbase());
4263 }
4264 }
4265 else
4266 return traits_type::eof();
4267 } while (__r == codecvt_base::partial);
4268 }
4269 this->setp(__pb_save, __epb_save);
4270 }
4271 return traits_type::not_eof(__c);
4272}
4273
4274template <class _Codecvt, class _Elem, class _Tr>
4275basic_streambuf<_Elem, _Tr>*
4276wbuffer_convert<_Codecvt, _Elem, _Tr>::setbuf(char_type* __s, streamsize __n)
4277{
4278 this->setg(0, 0, 0);
4279 this->setp(0, 0);
4280 if (__owns_eb_)
4281 delete [] __extbuf_;
4282 if (__owns_ib_)
4283 delete [] __intbuf_;
4284 __ebs_ = __n;
4285 if (__ebs_ > sizeof(__extbuf_min_))
4286 {
4287 if (__always_noconv_ && __s)
4288 {
4289 __extbuf_ = (char*)__s;
4290 __owns_eb_ = false;
4291 }
4292 else
4293 {
4294 __extbuf_ = new char[__ebs_];
4295 __owns_eb_ = true;
4296 }
4297 }
4298 else
4299 {
4300 __extbuf_ = __extbuf_min_;
4301 __ebs_ = sizeof(__extbuf_min_);
4302 __owns_eb_ = false;
4303 }
4304 if (!__always_noconv_)
4305 {
4306 __ibs_ = max<streamsize>(__n, sizeof(__extbuf_min_));
4307 if (__s && __ibs_ >= sizeof(__extbuf_min_))
4308 {
4309 __intbuf_ = __s;
4310 __owns_ib_ = false;
4311 }
4312 else
4313 {
4314 __intbuf_ = new char_type[__ibs_];
4315 __owns_ib_ = true;
4316 }
4317 }
4318 else
4319 {
4320 __ibs_ = 0;
4321 __intbuf_ = 0;
4322 __owns_ib_ = false;
4323 }
4324 return this;
4325}
4326
4327template <class _Codecvt, class _Elem, class _Tr>
4328typename wbuffer_convert<_Codecvt, _Elem, _Tr>::pos_type
4329wbuffer_convert<_Codecvt, _Elem, _Tr>::seekoff(off_type __off, ios_base::seekdir __way,
4330 ios_base::openmode __om)
4331{
4332 int __width = __cv_->encoding();
4333 if (__cv_ == 0 || __bufptr_ == 0 || (__width <= 0 && __off != 0) || sync())
4334 return pos_type(off_type(-1));
4335 // __width > 0 || __off == 0
4336 switch (__way)
4337 {
4338 case ios_base::beg:
4339 break;
4340 case ios_base::cur:
4341 break;
4342 case ios_base::end:
4343 break;
4344 default:
4345 return pos_type(off_type(-1));
4346 }
4347 pos_type __r = __bufptr_->pubseekoff(__width * __off, __way, __om);
4348 __r.state(__st_);
4349 return __r;
4350}
4351
4352template <class _Codecvt, class _Elem, class _Tr>
4353typename wbuffer_convert<_Codecvt, _Elem, _Tr>::pos_type
4354wbuffer_convert<_Codecvt, _Elem, _Tr>::seekpos(pos_type __sp, ios_base::openmode __wch)
4355{
4356 if (__cv_ == 0 || __bufptr_ == 0 || sync())
4357 return pos_type(off_type(-1));
4358 if (__bufptr_->pubseekpos(__sp, __wch) == pos_type(off_type(-1)))
4359 return pos_type(off_type(-1));
4360 return __sp;
4361}
4362
4363template <class _Codecvt, class _Elem, class _Tr>
4364int
4365wbuffer_convert<_Codecvt, _Elem, _Tr>::sync()
4366{
4367 if (__cv_ == 0 || __bufptr_ == 0)
4368 return 0;
4369 if (__cm_ & ios_base::out)
4370 {
4371 if (this->pptr() != this->pbase())
4372 if (overflow() == traits_type::eof())
4373 return -1;
4374 codecvt_base::result __r;
4375 do
4376 {
4377 char* __extbe;
4378 __r = __cv_->unshift(__st_, __extbuf_, __extbuf_ + __ebs_, __extbe);
4379 streamsize __nmemb = static_cast<streamsize>(__extbe - __extbuf_);
4380 if (__bufptr_->sputn(__extbuf_, __nmemb) != __nmemb)
4381 return -1;
4382 } while (__r == codecvt_base::partial);
4383 if (__r == codecvt_base::error)
4384 return -1;
4385 if (__bufptr_->pubsync())
4386 return -1;
4387 }
4388 else if (__cm_ & ios_base::in)
4389 {
4390 off_type __c;
4391 if (__always_noconv_)
4392 __c = this->egptr() - this->gptr();
4393 else
4394 {
4395 int __width = __cv_->encoding();
4396 __c = __extbufend_ - __extbufnext_;
4397 if (__width > 0)
4398 __c += __width * (this->egptr() - this->gptr());
4399 else
4400 {
4401 if (this->gptr() != this->egptr())
4402 {
4403 reverse(this->gptr(), this->egptr());
4404 codecvt_base::result __r;
4405 const char_type* __e = this->gptr();
4406 char* __extbe;
4407 do
4408 {
4409 __r = __cv_->out(__st_, __e, this->egptr(), __e,
4410 __extbuf_, __extbuf_ + __ebs_, __extbe);
4411 switch (__r)
4412 {
4413 case codecvt_base::noconv:
4414 __c += this->egptr() - this->gptr();
4415 break;
4416 case codecvt_base::ok:
4417 case codecvt_base::partial:
4418 __c += __extbe - __extbuf_;
4419 break;
4420 default:
4421 return -1;
4422 }
4423 } while (__r == codecvt_base::partial);
4424 }
4425 }
4426 }
4427 if (__bufptr_->pubseekoff(-__c, ios_base::cur, __cm_) == pos_type(off_type(-1)))
4428 return -1;
4429 this->setg(0, 0, 0);
4430 __cm_ = 0;
4431 }
4432 return 0;
4433}
4434
4435template <class _Codecvt, class _Elem, class _Tr>
4436bool
4437wbuffer_convert<_Codecvt, _Elem, _Tr>::__read_mode()
4438{
4439 if (!(__cm_ & ios_base::in))
4440 {
4441 this->setp(0, 0);
4442 if (__always_noconv_)
4443 this->setg((char_type*)__extbuf_,
4444 (char_type*)__extbuf_ + __ebs_,
4445 (char_type*)__extbuf_ + __ebs_);
4446 else
4447 this->setg(__intbuf_, __intbuf_ + __ibs_, __intbuf_ + __ibs_);
4448 __cm_ = ios_base::in;
4449 return true;
4450 }
4451 return false;
4452}
4453
4454template <class _Codecvt, class _Elem, class _Tr>
4455void
4456wbuffer_convert<_Codecvt, _Elem, _Tr>::__write_mode()
4457{
4458 if (!(__cm_ & ios_base::out))
4459 {
4460 this->setg(0, 0, 0);
4461 if (__ebs_ > sizeof(__extbuf_min_))
4462 {
4463 if (__always_noconv_)
4464 this->setp((char_type*)__extbuf_,
4465 (char_type*)__extbuf_ + (__ebs_ - 1));
4466 else
4467 this->setp(__intbuf_, __intbuf_ + (__ibs_ - 1));
4468 }
4469 else
4470 this->setp(0, 0);
4471 __cm_ = ios_base::out;
4472 }
4473}
4474
4475template <class _Codecvt, class _Elem, class _Tr>
4476wbuffer_convert<_Codecvt, _Elem, _Tr>*
4477wbuffer_convert<_Codecvt, _Elem, _Tr>::__close()
4478{
4479 wbuffer_convert* __rt = 0;
4480 if (__cv_ != 0 && __bufptr_ != 0)
4481 {
4482 __rt = this;
4483 if ((__cm_ & ios_base::out) && sync())
4484 __rt = 0;
4485 }
4486 return __rt;
Howard Hinnantd23b4642010-05-31 20:58:54 +00004487}
4488
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004489_LIBCPP_END_NAMESPACE_STD
4490
4491#endif // _LIBCPP_LOCALE