blob: e40a04ce154629715d619eecfb59e18331f6aae2 [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>
189#include <nl_types.h>
190
191#pragma GCC system_header
192
193_LIBCPP_BEGIN_NAMESPACE_STD
194
Sean Hunte59f7242011-07-09 01:09:31 +0000195#ifndef _LIBCPP_STABLE_APPLE_ABI
Sean Hunt62a6ac32011-07-09 00:56:23 +0000196// Get the C locale object
197locale_t __cloc();
Sean Hunte59f7242011-07-09 01:09:31 +0000198#endif
Sean Hunt62a6ac32011-07-09 00:56:23 +0000199
Sean Huntf3907e62011-07-15 05:40:33 +0000200typedef _VSTD::remove_pointer<locale_t>::type __locale_struct;
201typedef _VSTD::unique_ptr<__locale_struct, decltype(&freelocale)> __locale_unique_ptr;
202typedef _VSTD::unique_ptr<__locale_struct, decltype(&uselocale)> __locale_raii;
203
Howard Hinnantadff4892010-05-24 17:49:41 +0000204// OSX has nice foo_l() functions that let you turn off use of the global
205// locale. Linux, not so much. The following functions avoid the locale when
206// that's possible and otherwise do the wrong thing. FIXME.
Howard Hinnantbcbbd4d2011-07-15 14:46:11 +0000207#ifndef _LIBCPP_STABLE_APPLE_ABI
Sean Huntf3907e62011-07-15 05:40:33 +0000208
209#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
210decltype(MB_CUR_MAX_L(_VSTD::declval<locale_t>()))
Howard Hinnant82894812010-09-22 16:48:34 +0000211inline _LIBCPP_INLINE_VISIBILITY
Sean Huntf3907e62011-07-15 05:40:33 +0000212__mb_cur_max_l(locale_t __l)
Howard Hinnantadff4892010-05-24 17:49:41 +0000213{
Sean Huntf3907e62011-07-15 05:40:33 +0000214 return MB_CUR_MAX_L(__l);
215}
216#else // _LIBCPP_LOCALE__L_EXTENSIONS
217_LIBCPP_ALWAYS_INLINE inline
218decltype(MB_CUR_MAX) __mb_cur_max_l(locale_t __l)
219{
220 __locale_raii __current(uselocale(__l), uselocale);
221 return MB_CUR_MAX;
222}
223#endif // _LIBCPP_LOCALE__L_EXTENSIONS
224
225_LIBCPP_ALWAYS_INLINE inline
226wint_t __btowc_l(int __c, locale_t __l)
227{
228#ifdef _LIBCPP_STABLE_APPLE_ABI
229 return btowc_l(__c, __l);
230#else
231 __locale_raii __current(uselocale(__l), uselocale);
232 return btowc(__c);
233#endif
Sean Huntc97da3a2011-07-13 06:40:50 +0000234}
Howard Hinnant8d756322011-07-13 15:48:16 +0000235
Sean Huntf3907e62011-07-15 05:40:33 +0000236_LIBCPP_ALWAYS_INLINE inline
237int __wctob_l(wint_t __c, locale_t __l)
Sean Huntc97da3a2011-07-13 06:40:50 +0000238{
Sean Huntf3907e62011-07-15 05:40:33 +0000239#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
240 return wctob_l(__c, __l);
241#else
242 __locale_raii __current(uselocale(__l), uselocale);
243 return wctob(__c);
244#endif
Sean Huntc97da3a2011-07-13 06:40:50 +0000245}
Sean Huntf3907e62011-07-15 05:40:33 +0000246
247_LIBCPP_ALWAYS_INLINE inline
248size_t __wcsnrtombs_l(char *__dest, const wchar_t **__src, size_t __nwc,
249 size_t __len, mbstate_t *__ps, locale_t __l)
250{
251#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
252 return wcsnrtombs_l(__dest, __src, __nwc, __len, __ps, __l);
253#else
254 __locale_raii __current(uselocale(__l), uselocale);
255 return wcsnrtombs(__dest, __src, __nwc, __len, __ps);
256#endif
257}
258
259_LIBCPP_ALWAYS_INLINE inline
260size_t __wcrtomb_l(char *__s, wchar_t __wc, mbstate_t *__ps, locale_t __l)
261{
262#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
263 return wcrtomb_l(__s, __wc, __ps, __l);
264#else
265 __locale_raii __current(uselocale(__l), uselocale);
266 return wcrtomb(__s, __wc, __ps);
267#endif
268}
269
270_LIBCPP_ALWAYS_INLINE inline
271size_t __mbsnrtowcs_l(wchar_t * __dest, const char **__src, size_t __nms,
272 size_t __len, mbstate_t *__ps, locale_t __l)
273{
274#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
David Chisnallc512df12011-09-21 08:39:44 +0000275 return mbsnrtowcs_l(__dest, __src, __nms, __len, __ps, __l);
Sean Huntf3907e62011-07-15 05:40:33 +0000276#else
277 __locale_raii __current(uselocale(__l), uselocale);
278 return mbsnrtowcs(__dest, __src, __nms, __len, __ps);
279#endif
280}
281
282_LIBCPP_ALWAYS_INLINE inline
283size_t __mbrtowc_l(wchar_t *__pwc, const char *__s, size_t __n,
284 mbstate_t *__ps, locale_t __l)
285{
286#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
287 return mbrtowc_l(__pwc, __s, __n, __ps, __l);
288#else
289 __locale_raii __current(uselocale(__l), uselocale);
290 return mbrtowc(__pwc, __s, __n, __ps);
291#endif
292}
293
294_LIBCPP_ALWAYS_INLINE inline
295int __mbtowc_l(wchar_t *__pwc, const char *__pmb, size_t __max, locale_t __l)
296{
297#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
David Chisnallc512df12011-09-21 08:39:44 +0000298 return mbtowc_l(__pwc, __pmb, __max, __l);
Sean Huntf3907e62011-07-15 05:40:33 +0000299#else
300 __locale_raii __current(uselocale(__l), uselocale);
301 return mbtowc(__pwc, __pmb, __max);
302#endif
303}
304
305_LIBCPP_ALWAYS_INLINE inline
306size_t __mbrlen_l(const char *__s, size_t __n, mbstate_t *__ps, locale_t __l)
307{
308#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
309 return mbrlen_l(__s, __n, __ps, __l);
310#else
311 __locale_raii __current(uselocale(__l), uselocale);
312 return mbrlen(__s, __n, __ps);
313#endif
314}
315
316_LIBCPP_ALWAYS_INLINE inline
317lconv *__localeconv_l(locale_t __l)
318{
319#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
320 return localeconv_l(__l);
321#else
322 __locale_raii __current(uselocale(__l), uselocale);
323 return localeconv();
324#endif
325}
326
327_LIBCPP_ALWAYS_INLINE inline
328size_t __mbsrtowcs_l(wchar_t *__dest, const char **__src, size_t __len,
329 mbstate_t *__ps, locale_t __l)
330{
331#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
332 return mbsrtowcs_l(__dest, __src, __len, __ps, __l);
333#else
334 __locale_raii __current(uselocale(__l), uselocale);
335 return mbsrtowcs(__dest, __src, __len, __ps);
336#endif
337}
338
339_LIBCPP_ALWAYS_INLINE inline
340int __sprintf_l(char *__s, locale_t __l, const char *__format, ...) {
341 va_list __va;
342 va_start(__va, __format);
343#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
344 int __res = vsprintf_l(__s, __l, __format, __va);
345#else
346 __locale_raii __current(uselocale(__l), uselocale);
347 int __res = vsprintf(__s, __format, __va);
348#endif
349 va_end(__va);
350 return __res;
351}
352
353_LIBCPP_ALWAYS_INLINE inline
354int __snprintf_l(char *__s, size_t __n, locale_t __l, const char *__format, ...) {
355 va_list __va;
356 va_start(__va, __format);
357#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
358 int __res = vsnprintf_l(__s, __n, __l, __format, __va);
359#else
360 __locale_raii __current(uselocale(__l), uselocale);
361 int __res = vsnprintf(__s, __n, __format, __va);
362#endif
363 va_end(__va);
364 return __res;
365}
366
367_LIBCPP_ALWAYS_INLINE inline
368int __asprintf_l(char **__s, locale_t __l, const char *__format, ...) {
369 va_list __va;
370 va_start(__va, __format);
371#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
372 int __res = vasprintf_l(__s, __l, __format, __va);
373#else
374 __locale_raii __current(uselocale(__l), uselocale);
375 int __res = vasprintf(__s, __format, __va);
376#endif
377 va_end(__va);
378 return __res;
379}
380
381_LIBCPP_ALWAYS_INLINE inline
382int __sscanf_l(const char *__s, locale_t __l, const char *__format, ...) {
383 va_list __va;
384 va_start(__va, __format);
385#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
386 int __res = vsscanf_l(__s, __l, __format, __va);
387#else
388 __locale_raii __current(uselocale(__l), uselocale);
389 int __res = vsscanf(__s, __format, __va);
390#endif
391 va_end(__va);
392 return __res;
393}
394
395#endif // _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantadff4892010-05-24 17:49:41 +0000396
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000397// __scan_keyword
398// Scans [__b, __e) until a match is found in the basic_strings range
399// [__kb, __ke) or until it can be shown that there is no match in [__kb, __ke).
400// __b will be incremented (visibly), consuming CharT until a match is found
401// or proved to not exist. A keyword may be "", in which will match anything.
402// If one keyword is a prefix of another, and the next CharT in the input
403// might match another keyword, the algorithm will attempt to find the longest
404// matching keyword. If the longer matching keyword ends up not matching, then
405// no keyword match is found. If no keyword match is found, __ke is returned
406// and failbit is set in __err.
407// Else an iterator pointing to the matching keyword is found. If more than
408// one keyword matches, an iterator to the first matching keyword is returned.
409// If on exit __b == __e, eofbit is set in __err. If __case_senstive is false,
410// __ct is used to force to lower case before comparing characters.
411// Examples:
412// Keywords: "a", "abb"
413// If the input is "a", the first keyword matches and eofbit is set.
414// If the input is "abc", no match is found and "ab" are consumed.
415template <class _InputIterator, class _ForwardIterator, class _Ctype>
416_LIBCPP_HIDDEN
417_ForwardIterator
418__scan_keyword(_InputIterator& __b, _InputIterator __e,
419 _ForwardIterator __kb, _ForwardIterator __ke,
420 const _Ctype& __ct, ios_base::iostate& __err,
421 bool __case_sensitive = true)
422{
423 typedef typename iterator_traits<_InputIterator>::value_type _CharT;
Howard Hinnant0949eed2011-06-30 21:18:19 +0000424 size_t __nkw = _VSTD::distance(__kb, __ke);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000425 const unsigned char __doesnt_match = '\0';
426 const unsigned char __might_match = '\1';
427 const unsigned char __does_match = '\2';
428 unsigned char __statbuf[100];
429 unsigned char* __status = __statbuf;
430 unique_ptr<unsigned char, void(*)(void*)> __stat_hold(0, free);
431 if (__nkw > sizeof(__statbuf))
432 {
433 __status = (unsigned char*)malloc(__nkw);
434 if (__status == 0)
435 __throw_bad_alloc();
436 __stat_hold.reset(__status);
437 }
438 size_t __n_might_match = __nkw; // At this point, any keyword might match
439 size_t __n_does_match = 0; // but none of them definitely do
440 // Initialize all statuses to __might_match, except for "" keywords are __does_match
441 unsigned char* __st = __status;
442 for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, ++__st)
443 {
444 if (!__ky->empty())
445 *__st = __might_match;
446 else
447 {
448 *__st = __does_match;
449 --__n_might_match;
450 ++__n_does_match;
451 }
452 }
453 // While there might be a match, test keywords against the next CharT
454 for (size_t __indx = 0; __b != __e && __n_might_match > 0; ++__indx)
455 {
456 // Peek at the next CharT but don't consume it
457 _CharT __c = *__b;
458 if (!__case_sensitive)
459 __c = __ct.toupper(__c);
460 bool __consume = false;
461 // For each keyword which might match, see if the __indx character is __c
462 // If a match if found, consume __c
463 // If a match is found, and that is the last character in the keyword,
464 // then that keyword matches.
465 // If the keyword doesn't match this character, then change the keyword
466 // to doesn't match
467 __st = __status;
468 for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, ++__st)
469 {
470 if (*__st == __might_match)
471 {
472 _CharT __kc = (*__ky)[__indx];
473 if (!__case_sensitive)
474 __kc = __ct.toupper(__kc);
475 if (__c == __kc)
476 {
477 __consume = true;
478 if (__ky->size() == __indx+1)
479 {
480 *__st = __does_match;
481 --__n_might_match;
482 ++__n_does_match;
483 }
484 }
485 else
486 {
487 *__st = __doesnt_match;
488 --__n_might_match;
489 }
490 }
491 }
492 // consume if we matched a character
493 if (__consume)
494 {
495 ++__b;
496 // If we consumed a character and there might be a matched keyword that
497 // was marked matched on a previous iteration, then such keywords
498 // which are now marked as not matching.
499 if (__n_might_match + __n_does_match > 1)
500 {
501 __st = __status;
502 for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, ++__st)
503 {
504 if (*__st == __does_match && __ky->size() != __indx+1)
505 {
506 *__st = __doesnt_match;
507 --__n_does_match;
508 }
509 }
510 }
511 }
512 }
513 // We've exited the loop because we hit eof and/or we have no more "might matches".
514 if (__b == __e)
515 __err |= ios_base::eofbit;
516 // Return the first matching result
517 for (__st = __status; __kb != __ke; ++__kb, ++__st)
518 if (*__st == __does_match)
519 break;
520 if (__kb == __ke)
521 __err |= ios_base::failbit;
522 return __kb;
523}
524
525struct __num_get_base
526{
527 static const int __num_get_buf_sz = 40;
528
529 static int __get_base(ios_base&);
530 static const char __src[33];
531};
532
533void __check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
534 ios_base::iostate& __err);
535
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000536template <class _CharT>
537struct __num_get
538 : protected __num_get_base
539{
540 static string __stage2_int_prep(ios_base& __iob, _CharT* __atoms, _CharT& __thousands_sep);
541 static string __stage2_float_prep(ios_base& __iob, _CharT* __atoms, _CharT& __decimal_point,
542 _CharT& __thousands_sep);
543 static int __stage2_int_loop(_CharT __ct, int __base, char* __a, char*& __a_end,
544 unsigned& __dc, _CharT __thousands_sep, const string& __grouping,
545 unsigned* __g, unsigned*& __g_end, _CharT* __atoms);
546 static int __stage2_float_loop(_CharT __ct, bool& __in_units, char& __exp,
547 char* __a, char*& __a_end,
548 _CharT __decimal_point, _CharT __thousands_sep,
549 const string& __grouping, unsigned* __g,
550 unsigned*& __g_end, unsigned& __dc, _CharT* __atoms);
551};
552
553template <class _CharT>
554string
555__num_get<_CharT>::__stage2_int_prep(ios_base& __iob, _CharT* __atoms, _CharT& __thousands_sep)
556{
557 locale __loc = __iob.getloc();
558 use_facet<ctype<_CharT> >(__loc).widen(__src, __src + 26, __atoms);
559 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
560 __thousands_sep = __np.thousands_sep();
561 return __np.grouping();
562}
563
564template <class _CharT>
565string
566__num_get<_CharT>::__stage2_float_prep(ios_base& __iob, _CharT* __atoms, _CharT& __decimal_point,
567 _CharT& __thousands_sep)
568{
569 locale __loc = __iob.getloc();
570 use_facet<ctype<_CharT> >(__loc).widen(__src, __src + 32, __atoms);
571 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
572 __decimal_point = __np.decimal_point();
573 __thousands_sep = __np.thousands_sep();
574 return __np.grouping();
575}
576
577template <class _CharT>
578int
579__num_get<_CharT>::__stage2_int_loop(_CharT __ct, int __base, char* __a, char*& __a_end,
580 unsigned& __dc, _CharT __thousands_sep, const string& __grouping,
581 unsigned* __g, unsigned*& __g_end, _CharT* __atoms)
582{
Howard Hinnant80586722011-03-09 01:03:19 +0000583 if (__a_end == __a && (__ct == __atoms[24] || __ct == __atoms[25]))
584 {
585 *__a_end++ = __ct == __atoms[24] ? '+' : '-';
586 __dc = 0;
587 return 0;
588 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000589 if (__ct == __thousands_sep && __grouping.size() != 0)
590 {
591 if (__g_end-__g < __num_get_buf_sz)
592 {
593 *__g_end++ = __dc;
594 __dc = 0;
595 }
596 return 0;
597 }
598 ptrdiff_t __f = find(__atoms, __atoms + 26, __ct) - __atoms;
Howard Hinnant80586722011-03-09 01:03:19 +0000599 if (__f >= 24)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000600 return -1;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000601 switch (__base)
602 {
603 case 8:
604 case 10:
605 if (__f >= __base)
Howard Hinnant80586722011-03-09 01:03:19 +0000606 return -1;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000607 break;
Howard Hinnant80586722011-03-09 01:03:19 +0000608 case 16:
609 if (__f < 22)
610 break;
611 if (__a_end != __a && __a_end - __a <= 2 && __a_end[-1] == '0')
612 {
613 __dc = 0;
614 *__a_end++ = __src[__f];
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000615 return 0;
Howard Hinnant80586722011-03-09 01:03:19 +0000616 }
617 return -1;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000618 }
Howard Hinnant80586722011-03-09 01:03:19 +0000619 if (__a_end-__a < __num_get_buf_sz - 1)
620 *__a_end++ = __src[__f];
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000621 ++__dc;
622 return 0;
623}
624
625template <class _CharT>
626int
627__num_get<_CharT>::__stage2_float_loop(_CharT __ct, bool& __in_units, char& __exp, char* __a, char*& __a_end,
628 _CharT __decimal_point, _CharT __thousands_sep, const string& __grouping,
629 unsigned* __g, unsigned*& __g_end, unsigned& __dc, _CharT* __atoms)
630{
631 if (__ct == __decimal_point)
632 {
633 if (!__in_units)
634 return -1;
635 __in_units = false;
636 *__a_end++ = '.';
637 if (__grouping.size() != 0 && __g_end-__g < __num_get_buf_sz)
638 *__g_end++ = __dc;
639 return 0;
640 }
641 if (__ct == __thousands_sep && __grouping.size() != 0)
642 {
643 if (!__in_units)
644 return -1;
645 if (__g_end-__g < __num_get_buf_sz)
646 {
647 *__g_end++ = __dc;
648 __dc = 0;
649 }
650 return 0;
651 }
652 ptrdiff_t __f = find(__atoms, __atoms + 32, __ct) - __atoms;
653 if (__f >= 32)
654 return -1;
655 char __x = __src[__f];
656 if (__a_end-__a < __num_get_buf_sz - 1)
657 *__a_end++ = __x;
658 if (__x == 'x' || __x == 'X')
659 __exp = 'P';
660 else if ((__x & 0xDF) == __exp)
661 {
662 __in_units = false;
663 if (__grouping.size() != 0 && __g_end-__g < __num_get_buf_sz)
664 *__g_end++ = __dc;
665 }
666 if (__f >= 22)
667 return 0;
668 ++__dc;
669 return 0;
670}
671
672extern template class __num_get<char>;
673extern template class __num_get<wchar_t>;
674
675template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +0000676class _LIBCPP_VISIBLE num_get
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000677 : public locale::facet,
678 private __num_get<_CharT>
679{
680public:
681 typedef _CharT char_type;
682 typedef _InputIterator iter_type;
683
684 _LIBCPP_ALWAYS_INLINE
685 explicit num_get(size_t __refs = 0)
686 : locale::facet(__refs) {}
687
688 _LIBCPP_ALWAYS_INLINE
689 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
690 ios_base::iostate& __err, bool& __v) const
691 {
692 return do_get(__b, __e, __iob, __err, __v);
693 }
694
695 _LIBCPP_ALWAYS_INLINE
696 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
697 ios_base::iostate& __err, long& __v) const
698 {
699 return do_get(__b, __e, __iob, __err, __v);
700 }
701
702 _LIBCPP_ALWAYS_INLINE
703 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
704 ios_base::iostate& __err, long long& __v) const
705 {
706 return do_get(__b, __e, __iob, __err, __v);
707 }
708
709 _LIBCPP_ALWAYS_INLINE
710 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
711 ios_base::iostate& __err, unsigned short& __v) const
712 {
713 return do_get(__b, __e, __iob, __err, __v);
714 }
715
716 _LIBCPP_ALWAYS_INLINE
717 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
718 ios_base::iostate& __err, unsigned int& __v) const
719 {
720 return do_get(__b, __e, __iob, __err, __v);
721 }
722
723 _LIBCPP_ALWAYS_INLINE
724 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
725 ios_base::iostate& __err, unsigned long& __v) const
726 {
727 return do_get(__b, __e, __iob, __err, __v);
728 }
729
730 _LIBCPP_ALWAYS_INLINE
731 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
732 ios_base::iostate& __err, unsigned long long& __v) const
733 {
734 return do_get(__b, __e, __iob, __err, __v);
735 }
736
737 _LIBCPP_ALWAYS_INLINE
738 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
739 ios_base::iostate& __err, float& __v) const
740 {
741 return do_get(__b, __e, __iob, __err, __v);
742 }
743
744 _LIBCPP_ALWAYS_INLINE
745 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
746 ios_base::iostate& __err, double& __v) const
747 {
748 return do_get(__b, __e, __iob, __err, __v);
749 }
750
751 _LIBCPP_ALWAYS_INLINE
752 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
753 ios_base::iostate& __err, long double& __v) const
754 {
755 return do_get(__b, __e, __iob, __err, __v);
756 }
757
758 _LIBCPP_ALWAYS_INLINE
759 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
760 ios_base::iostate& __err, void*& __v) const
761 {
762 return do_get(__b, __e, __iob, __err, __v);
763 }
764
765 static locale::id id;
766
767protected:
Howard Hinnant82894812010-09-22 16:48:34 +0000768 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000769 ~num_get() {}
770
771 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
772 ios_base::iostate& __err, bool& __v) const;
773 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
774 ios_base::iostate& __err, long& __v) const;
775 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
776 ios_base::iostate& __err, long long& __v) const;
777 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
778 ios_base::iostate& __err, unsigned short& __v) const;
779 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
780 ios_base::iostate& __err, unsigned int& __v) const;
781 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
782 ios_base::iostate& __err, unsigned long& __v) const;
783 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
784 ios_base::iostate& __err, unsigned long long& __v) const;
785 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
786 ios_base::iostate& __err, float& __v) const;
787 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
788 ios_base::iostate& __err, double& __v) const;
789 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
790 ios_base::iostate& __err, long double& __v) const;
791 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
792 ios_base::iostate& __err, void*& __v) const;
793};
794
795template <class _CharT, class _InputIterator>
796locale::id
797num_get<_CharT, _InputIterator>::id;
798
799template <class _Tp>
800_Tp
801__num_get_signed_integral(const char* __a, const char* __a_end,
802 ios_base::iostate& __err, int __base)
803{
804 if (__a != __a_end)
805 {
Howard Hinnante7c8da62011-02-25 19:52:41 +0000806 int __save_errno = errno;
807 errno = 0;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000808 char *__p2;
Howard Hinnant9a207812011-07-15 14:25:40 +0000809#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000810 long long __ll = strtoll_l(__a, &__p2, __base, 0);
Sean Huntf3907e62011-07-15 05:40:33 +0000811#else
812 long long __ll = strtoll_l(__a, &__p2, __base, __cloc());
813#endif
Howard Hinnante7c8da62011-02-25 19:52:41 +0000814 int __current_errno = errno;
815 if (__current_errno == 0)
816 errno = __save_errno;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000817 if (__p2 != __a_end)
818 {
819 __err = ios_base::failbit;
820 return 0;
821 }
Howard Hinnante7c8da62011-02-25 19:52:41 +0000822 else if (__current_errno == ERANGE ||
823 __ll < numeric_limits<_Tp>::min() ||
824 numeric_limits<_Tp>::max() < __ll)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000825 {
826 __err = ios_base::failbit;
Howard Hinnante7c8da62011-02-25 19:52:41 +0000827 if (__ll > 0)
828 return numeric_limits<_Tp>::max();
829 else
830 return numeric_limits<_Tp>::min();
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000831 }
832 return static_cast<_Tp>(__ll);
833 }
834 __err = ios_base::failbit;
835 return 0;
836}
837
838template <class _Tp>
839_Tp
840__num_get_unsigned_integral(const char* __a, const char* __a_end,
841 ios_base::iostate& __err, int __base)
842{
843 if (__a != __a_end)
844 {
Howard Hinnante7c8da62011-02-25 19:52:41 +0000845 if (*__a == '-')
846 {
847 __err = ios_base::failbit;
848 return 0;
849 }
850 int __save_errno = errno;
851 errno = 0;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000852 char *__p2;
Howard Hinnant9a207812011-07-15 14:25:40 +0000853#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000854 unsigned long long __ll = strtoull_l(__a, &__p2, __base, 0);
Sean Huntf3907e62011-07-15 05:40:33 +0000855#else
856 unsigned long long __ll = strtoull_l(__a, &__p2, __base, __cloc());
857#endif
Howard Hinnante7c8da62011-02-25 19:52:41 +0000858 int __current_errno = errno;
859 if (__current_errno == 0)
860 errno = __save_errno;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000861 if (__p2 != __a_end)
862 {
863 __err = ios_base::failbit;
864 return 0;
865 }
Howard Hinnante7c8da62011-02-25 19:52:41 +0000866 else if (__current_errno == ERANGE ||
867 numeric_limits<_Tp>::max() < __ll)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000868 {
869 __err = ios_base::failbit;
870 return numeric_limits<_Tp>::max();
871 }
872 return static_cast<_Tp>(__ll);
873 }
874 __err = ios_base::failbit;
875 return 0;
876}
877
878template <class _Tp>
879_Tp
880__num_get_float(const char* __a, const char* __a_end, ios_base::iostate& __err)
881{
882 if (__a != __a_end)
883 {
884 char *__p2;
Howard Hinnant9a207812011-07-15 14:25:40 +0000885#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000886 long double __ld = strtold_l(__a, &__p2, 0);
Sean Huntf3907e62011-07-15 05:40:33 +0000887#else
888 long double __ld = strtold_l(__a, &__p2, __cloc());
889#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000890 if (__p2 != __a_end)
891 {
892 __err = ios_base::failbit;
893 return 0;
894 }
895 return static_cast<_Tp>(__ld);
896 }
897 __err = ios_base::failbit;
898 return 0;
899}
900
901template <class _CharT, class _InputIterator>
902_InputIterator
903num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
904 ios_base& __iob,
905 ios_base::iostate& __err,
906 bool& __v) const
907{
908 if ((__iob.flags() & ios_base::boolalpha) == 0)
909 {
910 long __lv = -1;
911 __b = do_get(__b, __e, __iob, __err, __lv);
912 switch (__lv)
913 {
914 case 0:
915 __v = false;
916 break;
917 case 1:
918 __v = true;
919 break;
920 default:
921 __v = true;
922 __err = ios_base::failbit;
923 break;
924 }
925 return __b;
926 }
927 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__iob.getloc());
928 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__iob.getloc());
929 typedef typename numpunct<_CharT>::string_type string_type;
930 const string_type __names[2] = {__np.truename(), __np.falsename()};
931 const string_type* __i = __scan_keyword(__b, __e, __names, __names+2,
932 __ct, __err);
933 __v = __i == __names;
934 return __b;
935}
936
937template <class _CharT, class _InputIterator>
938_InputIterator
939num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
940 ios_base& __iob,
941 ios_base::iostate& __err,
942 long& __v) const
943{
944 // Stage 1
945 int __base = this->__get_base(__iob);
946 // Stage 2
947 char_type __atoms[26];
948 char_type __thousands_sep;
949 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
950 char __a[__num_get_base::__num_get_buf_sz] = {0};
951 char* __a_end = __a;
952 unsigned __g[__num_get_base::__num_get_buf_sz];
953 unsigned* __g_end = __g;
954 unsigned __dc = 0;
955 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +0000956 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000957 __thousands_sep, __grouping, __g, __g_end,
958 __atoms))
959 break;
960 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
961 *__g_end++ = __dc;
962 // Stage 3
963 __v = __num_get_signed_integral<long>(__a, __a_end, __err, __base);
964 // Digit grouping checked
965 __check_grouping(__grouping, __g, __g_end, __err);
966 // EOF checked
967 if (__b == __e)
968 __err |= ios_base::eofbit;
969 return __b;
970}
971
972template <class _CharT, class _InputIterator>
973_InputIterator
974num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
975 ios_base& __iob,
976 ios_base::iostate& __err,
977 long long& __v) const
978{
979 // Stage 1
980 int __base = this->__get_base(__iob);
981 // Stage 2
982 char_type __atoms[26];
983 char_type __thousands_sep;
984 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
985 char __a[__num_get_base::__num_get_buf_sz] = {0};
986 char* __a_end = __a;
987 unsigned __g[__num_get_base::__num_get_buf_sz];
988 unsigned* __g_end = __g;
989 unsigned __dc = 0;
990 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +0000991 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
992 __thousands_sep, __grouping, __g, __g_end,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000993 __atoms))
994 break;
995 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
996 *__g_end++ = __dc;
997 // Stage 3
998 __v = __num_get_signed_integral<long long>(__a, __a_end, __err, __base);
999 // Digit grouping checked
1000 __check_grouping(__grouping, __g, __g_end, __err);
1001 // EOF checked
1002 if (__b == __e)
1003 __err |= ios_base::eofbit;
1004 return __b;
1005}
1006
1007template <class _CharT, class _InputIterator>
1008_InputIterator
1009num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1010 ios_base& __iob,
1011 ios_base::iostate& __err,
1012 unsigned short& __v) const
1013{
1014 // Stage 1
1015 int __base = this->__get_base(__iob);
1016 // Stage 2
1017 char_type __atoms[26];
1018 char_type __thousands_sep;
1019 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
1020 char __a[__num_get_base::__num_get_buf_sz] = {0};
1021 char* __a_end = __a;
1022 unsigned __g[__num_get_base::__num_get_buf_sz];
1023 unsigned* __g_end = __g;
1024 unsigned __dc = 0;
1025 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001026 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001027 __thousands_sep, __grouping, __g, __g_end,
1028 __atoms))
1029 break;
1030 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
1031 *__g_end++ = __dc;
1032 // Stage 3
1033 __v = __num_get_unsigned_integral<unsigned short>(__a, __a_end, __err, __base);
1034 // Digit grouping checked
1035 __check_grouping(__grouping, __g, __g_end, __err);
1036 // EOF checked
1037 if (__b == __e)
1038 __err |= ios_base::eofbit;
1039 return __b;
1040}
1041
1042template <class _CharT, class _InputIterator>
1043_InputIterator
1044num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1045 ios_base& __iob,
1046 ios_base::iostate& __err,
1047 unsigned int& __v) const
1048{
1049 // Stage 1
1050 int __base = this->__get_base(__iob);
1051 // Stage 2
1052 char_type __atoms[26];
1053 char_type __thousands_sep;
1054 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
1055 char __a[__num_get_base::__num_get_buf_sz] = {0};
1056 char* __a_end = __a;
1057 unsigned __g[__num_get_base::__num_get_buf_sz];
1058 unsigned* __g_end = __g;
1059 unsigned __dc = 0;
1060 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001061 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001062 __thousands_sep, __grouping, __g, __g_end,
1063 __atoms))
1064 break;
1065 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
1066 *__g_end++ = __dc;
1067 // Stage 3
1068 __v = __num_get_unsigned_integral<unsigned int>(__a, __a_end, __err, __base);
1069 // Digit grouping checked
1070 __check_grouping(__grouping, __g, __g_end, __err);
1071 // EOF checked
1072 if (__b == __e)
1073 __err |= ios_base::eofbit;
1074 return __b;
1075}
1076
1077template <class _CharT, class _InputIterator>
1078_InputIterator
1079num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1080 ios_base& __iob,
1081 ios_base::iostate& __err,
1082 unsigned long& __v) const
1083{
1084 // Stage 1
1085 int __base = this->__get_base(__iob);
1086 // Stage 2
1087 char_type __atoms[26];
1088 char_type __thousands_sep;
1089 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
1090 char __a[__num_get_base::__num_get_buf_sz] = {0};
1091 char* __a_end = __a;
1092 unsigned __g[__num_get_base::__num_get_buf_sz];
1093 unsigned* __g_end = __g;
1094 unsigned __dc = 0;
1095 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001096 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001097 __thousands_sep, __grouping, __g, __g_end,
1098 __atoms))
1099 break;
1100 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
1101 *__g_end++ = __dc;
1102 // Stage 3
1103 __v = __num_get_unsigned_integral<unsigned long>(__a, __a_end, __err, __base);
1104 // Digit grouping checked
1105 __check_grouping(__grouping, __g, __g_end, __err);
1106 // EOF checked
1107 if (__b == __e)
1108 __err |= ios_base::eofbit;
1109 return __b;
1110}
1111
1112template <class _CharT, class _InputIterator>
1113_InputIterator
1114num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1115 ios_base& __iob,
1116 ios_base::iostate& __err,
1117 unsigned long long& __v) const
1118{
1119 // Stage 1
1120 int __base = this->__get_base(__iob);
1121 // Stage 2
1122 char_type __atoms[26];
1123 char_type __thousands_sep;
1124 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
1125 char __a[__num_get_base::__num_get_buf_sz] = {0};
1126 char* __a_end = __a;
1127 unsigned __g[__num_get_base::__num_get_buf_sz];
1128 unsigned* __g_end = __g;
1129 unsigned __dc = 0;
1130 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001131 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001132 __thousands_sep, __grouping, __g, __g_end,
1133 __atoms))
1134 break;
1135 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
1136 *__g_end++ = __dc;
1137 // Stage 3
1138 __v = __num_get_unsigned_integral<unsigned long long>(__a, __a_end, __err, __base);
1139 // Digit grouping checked
1140 __check_grouping(__grouping, __g, __g_end, __err);
1141 // EOF checked
1142 if (__b == __e)
1143 __err |= ios_base::eofbit;
1144 return __b;
1145}
1146
1147template <class _CharT, class _InputIterator>
1148_InputIterator
1149num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1150 ios_base& __iob,
1151 ios_base::iostate& __err,
1152 float& __v) const
1153{
1154 // Stage 1, nothing to do
1155 // Stage 2
1156 char_type __atoms[32];
1157 char_type __decimal_point;
1158 char_type __thousands_sep;
Howard Hinnant324bb032010-08-22 00:02:43 +00001159 string __grouping = this->__stage2_float_prep(__iob, __atoms,
1160 __decimal_point,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001161 __thousands_sep);
1162 char __a[__num_get_base::__num_get_buf_sz] = {0};
1163 char* __a_end = __a;
1164 unsigned __g[__num_get_base::__num_get_buf_sz];
1165 unsigned* __g_end = __g;
1166 unsigned __dc = 0;
1167 bool __in_units = true;
1168 char __exp = 'E';
1169 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001170 if (this->__stage2_float_loop(*__b, __in_units, __exp, __a, __a_end,
1171 __decimal_point, __thousands_sep,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001172 __grouping, __g, __g_end,
1173 __dc, __atoms))
1174 break;
1175 if (__grouping.size() != 0 && __in_units && __g_end-__g < __num_get_base::__num_get_buf_sz)
1176 *__g_end++ = __dc;
1177 // Stage 3
1178 __v = __num_get_float<float>(__a, __a_end, __err);
1179 // Digit grouping checked
1180 __check_grouping(__grouping, __g, __g_end, __err);
1181 // EOF checked
1182 if (__b == __e)
1183 __err |= ios_base::eofbit;
1184 return __b;
1185}
1186
1187template <class _CharT, class _InputIterator>
1188_InputIterator
1189num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1190 ios_base& __iob,
1191 ios_base::iostate& __err,
1192 double& __v) const
1193{
1194 // Stage 1, nothing to do
1195 // Stage 2
1196 char_type __atoms[32];
1197 char_type __decimal_point;
1198 char_type __thousands_sep;
Howard Hinnant324bb032010-08-22 00:02:43 +00001199 string __grouping = this->__stage2_float_prep(__iob, __atoms,
1200 __decimal_point,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001201 __thousands_sep);
1202 char __a[__num_get_base::__num_get_buf_sz] = {0};
1203 char* __a_end = __a;
1204 unsigned __g[__num_get_base::__num_get_buf_sz];
1205 unsigned* __g_end = __g;
1206 unsigned __dc = 0;
1207 bool __in_units = true;
1208 char __exp = 'E';
1209 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001210 if (this->__stage2_float_loop(*__b, __in_units, __exp, __a, __a_end,
1211 __decimal_point, __thousands_sep,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001212 __grouping, __g, __g_end,
1213 __dc, __atoms))
1214 break;
1215 if (__grouping.size() != 0 && __in_units && __g_end-__g < __num_get_base::__num_get_buf_sz)
1216 *__g_end++ = __dc;
1217 // Stage 3
1218 __v = __num_get_float<double>(__a, __a_end, __err);
1219 // Digit grouping checked
1220 __check_grouping(__grouping, __g, __g_end, __err);
1221 // EOF checked
1222 if (__b == __e)
1223 __err |= ios_base::eofbit;
1224 return __b;
1225}
1226
1227template <class _CharT, class _InputIterator>
1228_InputIterator
1229num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1230 ios_base& __iob,
1231 ios_base::iostate& __err,
1232 long double& __v) const
1233{
1234 // Stage 1, nothing to do
1235 // Stage 2
1236 char_type __atoms[32];
1237 char_type __decimal_point;
1238 char_type __thousands_sep;
Howard Hinnant324bb032010-08-22 00:02:43 +00001239 string __grouping = this->__stage2_float_prep(__iob, __atoms,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001240 __decimal_point,
1241 __thousands_sep);
1242 char __a[__num_get_base::__num_get_buf_sz] = {0};
1243 char* __a_end = __a;
1244 unsigned __g[__num_get_base::__num_get_buf_sz];
1245 unsigned* __g_end = __g;
1246 unsigned __dc = 0;
1247 bool __in_units = true;
1248 char __exp = 'E';
1249 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001250 if (this->__stage2_float_loop(*__b, __in_units, __exp, __a, __a_end,
1251 __decimal_point, __thousands_sep,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001252 __grouping, __g, __g_end,
1253 __dc, __atoms))
1254 break;
1255 if (__grouping.size() != 0 && __in_units && __g_end-__g < __num_get_base::__num_get_buf_sz)
1256 *__g_end++ = __dc;
1257 // Stage 3
1258 __v = __num_get_float<long double>(__a, __a_end, __err);
1259 // Digit grouping checked
1260 __check_grouping(__grouping, __g, __g_end, __err);
1261 // EOF checked
1262 if (__b == __e)
1263 __err |= ios_base::eofbit;
1264 return __b;
1265}
1266
1267template <class _CharT, class _InputIterator>
1268_InputIterator
1269num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1270 ios_base& __iob,
1271 ios_base::iostate& __err,
1272 void*& __v) const
1273{
1274 // Stage 1
1275 int __base = 16;
1276 // Stage 2
1277 char_type __atoms[26];
1278 char_type __thousands_sep;
1279 string __grouping;
1280 use_facet<ctype<_CharT> >(__iob.getloc()).widen(__num_get_base::__src,
1281 __num_get_base::__src + 26, __atoms);
1282 char __a[__num_get_base::__num_get_buf_sz] = {0};
1283 char* __a_end = __a;
1284 unsigned __g[__num_get_base::__num_get_buf_sz];
1285 unsigned* __g_end = __g;
1286 unsigned __dc = 0;
1287 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001288 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
1289 __thousands_sep, __grouping,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001290 __g, __g_end, __atoms))
1291 break;
1292 // Stage 3
1293 __a[sizeof(__a)-1] = 0;
Sean Huntf3907e62011-07-15 05:40:33 +00001294#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantbcbbd4d2011-07-15 14:46:11 +00001295 if (sscanf_l(__a, 0, "%p", &__v) != 1)
Sean Huntf3907e62011-07-15 05:40:33 +00001296#else
1297 if (__sscanf_l(__a, __cloc(), "%p", &__v) != 1)
1298#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001299 __err = ios_base::failbit;
1300 // EOF checked
1301 if (__b == __e)
1302 __err |= ios_base::eofbit;
1303 return __b;
1304}
1305
1306extern template class num_get<char>;
1307extern template class num_get<wchar_t>;
1308
1309struct __num_put_base
1310{
1311protected:
1312 static void __format_int(char* __fmt, const char* __len, bool __signd,
1313 ios_base::fmtflags __flags);
1314 static bool __format_float(char* __fmt, const char* __len,
1315 ios_base::fmtflags __flags);
1316 static char* __identify_padding(char* __nb, char* __ne,
1317 const ios_base& __iob);
1318};
1319
1320template <class _CharT>
1321struct __num_put
1322 : protected __num_put_base
1323{
1324 static void __widen_and_group_int(char* __nb, char* __np, char* __ne,
1325 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1326 const locale& __loc);
1327 static void __widen_and_group_float(char* __nb, char* __np, char* __ne,
1328 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1329 const locale& __loc);
1330};
1331
1332template <class _CharT>
1333void
1334__num_put<_CharT>::__widen_and_group_int(char* __nb, char* __np, char* __ne,
1335 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1336 const locale& __loc)
1337{
1338 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> > (__loc);
1339 const numpunct<_CharT>& __npt = use_facet<numpunct<_CharT> >(__loc);
1340 string __grouping = __npt.grouping();
1341 if (__grouping.empty())
1342 {
1343 __ct.widen(__nb, __ne, __ob);
1344 __oe = __ob + (__ne - __nb);
1345 }
1346 else
1347 {
1348 __oe = __ob;
1349 char* __nf = __nb;
1350 if (*__nf == '-' || *__nf == '+')
1351 *__oe++ = __ct.widen(*__nf++);
1352 if (__ne - __nf >= 2 && __nf[0] == '0' && (__nf[1] == 'x' ||
1353 __nf[1] == 'X'))
1354 {
1355 *__oe++ = __ct.widen(*__nf++);
1356 *__oe++ = __ct.widen(*__nf++);
1357 }
1358 reverse(__nf, __ne);
1359 _CharT __thousands_sep = __npt.thousands_sep();
1360 unsigned __dc = 0;
1361 unsigned __dg = 0;
1362 for (char* __p = __nf; __p < __ne; ++__p)
1363 {
1364 if (static_cast<unsigned>(__grouping[__dg]) > 0 &&
1365 __dc == static_cast<unsigned>(__grouping[__dg]))
1366 {
1367 *__oe++ = __thousands_sep;
1368 __dc = 0;
1369 if (__dg < __grouping.size()-1)
1370 ++__dg;
1371 }
1372 *__oe++ = __ct.widen(*__p);
1373 ++__dc;
1374 }
1375 reverse(__ob + (__nf - __nb), __oe);
1376 }
1377 if (__np == __ne)
1378 __op = __oe;
1379 else
1380 __op = __ob + (__np - __nb);
1381}
1382
1383template <class _CharT>
1384void
1385__num_put<_CharT>::__widen_and_group_float(char* __nb, char* __np, char* __ne,
1386 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1387 const locale& __loc)
1388{
1389 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> > (__loc);
1390 const numpunct<_CharT>& __npt = use_facet<numpunct<_CharT> >(__loc);
1391 string __grouping = __npt.grouping();
1392 __oe = __ob;
1393 char* __nf = __nb;
1394 if (*__nf == '-' || *__nf == '+')
1395 *__oe++ = __ct.widen(*__nf++);
1396 char* __ns;
1397 if (__ne - __nf >= 2 && __nf[0] == '0' && (__nf[1] == 'x' ||
1398 __nf[1] == 'X'))
1399 {
1400 *__oe++ = __ct.widen(*__nf++);
1401 *__oe++ = __ct.widen(*__nf++);
1402 for (__ns = __nf; __ns < __ne; ++__ns)
Sean Huntf3907e62011-07-15 05:40:33 +00001403#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantbcbbd4d2011-07-15 14:46:11 +00001404 if (!isxdigit_l(*__ns, 0))
Sean Huntf3907e62011-07-15 05:40:33 +00001405#else
1406 if (!isxdigit_l(*__ns, __cloc()))
1407#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001408 break;
1409 }
1410 else
1411 {
1412 for (__ns = __nf; __ns < __ne; ++__ns)
Sean Huntf3907e62011-07-15 05:40:33 +00001413#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantbcbbd4d2011-07-15 14:46:11 +00001414 if (!isdigit_l(*__ns, 0))
Sean Huntf3907e62011-07-15 05:40:33 +00001415#else
1416 if (!isdigit_l(*__ns, __cloc()))
1417#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001418 break;
1419 }
1420 if (__grouping.empty())
1421 {
1422 __ct.widen(__nf, __ns, __oe);
1423 __oe += __ns - __nf;
1424 }
1425 else
1426 {
1427 reverse(__nf, __ns);
1428 _CharT __thousands_sep = __npt.thousands_sep();
1429 unsigned __dc = 0;
1430 unsigned __dg = 0;
1431 for (char* __p = __nf; __p < __ns; ++__p)
1432 {
1433 if (__grouping[__dg] > 0 && __dc == static_cast<unsigned>(__grouping[__dg]))
1434 {
1435 *__oe++ = __thousands_sep;
1436 __dc = 0;
1437 if (__dg < __grouping.size()-1)
1438 ++__dg;
1439 }
1440 *__oe++ = __ct.widen(*__p);
1441 ++__dc;
1442 }
1443 reverse(__ob + (__nf - __nb), __oe);
1444 }
1445 for (__nf = __ns; __nf < __ne; ++__nf)
1446 {
1447 if (*__nf == '.')
1448 {
1449 *__oe++ = __npt.decimal_point();
1450 ++__nf;
1451 break;
1452 }
1453 else
1454 *__oe++ = __ct.widen(*__nf);
1455 }
1456 __ct.widen(__nf, __ne, __oe);
1457 __oe += __ne - __nf;
1458 if (__np == __ne)
1459 __op = __oe;
1460 else
1461 __op = __ob + (__np - __nb);
1462}
1463
1464extern template class __num_put<char>;
1465extern template class __num_put<wchar_t>;
1466
1467template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00001468class _LIBCPP_VISIBLE num_put
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001469 : public locale::facet,
1470 private __num_put<_CharT>
1471{
1472public:
1473 typedef _CharT char_type;
1474 typedef _OutputIterator iter_type;
1475
1476 _LIBCPP_ALWAYS_INLINE
1477 explicit num_put(size_t __refs = 0)
1478 : locale::facet(__refs) {}
1479
1480 _LIBCPP_ALWAYS_INLINE
1481 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1482 bool __v) const
1483 {
1484 return do_put(__s, __iob, __fl, __v);
1485 }
1486
1487 _LIBCPP_ALWAYS_INLINE
1488 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1489 long __v) const
1490 {
1491 return do_put(__s, __iob, __fl, __v);
1492 }
1493
1494 _LIBCPP_ALWAYS_INLINE
1495 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1496 long long __v) const
1497 {
1498 return do_put(__s, __iob, __fl, __v);
1499 }
1500
1501 _LIBCPP_ALWAYS_INLINE
1502 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1503 unsigned long __v) const
1504 {
1505 return do_put(__s, __iob, __fl, __v);
1506 }
1507
1508 _LIBCPP_ALWAYS_INLINE
1509 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1510 unsigned long long __v) const
1511 {
1512 return do_put(__s, __iob, __fl, __v);
1513 }
1514
1515 _LIBCPP_ALWAYS_INLINE
1516 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1517 double __v) const
1518 {
1519 return do_put(__s, __iob, __fl, __v);
1520 }
1521
1522 _LIBCPP_ALWAYS_INLINE
1523 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1524 long double __v) const
1525 {
1526 return do_put(__s, __iob, __fl, __v);
1527 }
1528
1529 _LIBCPP_ALWAYS_INLINE
1530 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1531 const void* __v) const
1532 {
1533 return do_put(__s, __iob, __fl, __v);
1534 }
1535
1536 static locale::id id;
1537
1538protected:
Howard Hinnant82894812010-09-22 16:48:34 +00001539 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001540 ~num_put() {}
1541
1542 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1543 bool __v) const;
1544 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1545 long __v) const;
1546 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1547 long long __v) const;
1548 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1549 unsigned long) const;
1550 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1551 unsigned long long) const;
1552 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1553 double __v) const;
1554 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1555 long double __v) const;
1556 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1557 const void* __v) const;
1558};
1559
1560template <class _CharT, class _OutputIterator>
1561locale::id
1562num_put<_CharT, _OutputIterator>::id;
1563
1564template <class _CharT, class _OutputIterator>
1565_LIBCPP_HIDDEN
1566_OutputIterator
1567__pad_and_output(_OutputIterator __s,
1568 const _CharT* __ob, const _CharT* __op, const _CharT* __oe,
1569 ios_base& __iob, _CharT __fl)
1570{
1571 streamsize __sz = __oe - __ob;
1572 streamsize __ns = __iob.width();
1573 if (__ns > __sz)
1574 __ns -= __sz;
1575 else
1576 __ns = 0;
1577 for (;__ob < __op; ++__ob, ++__s)
1578 *__s = *__ob;
1579 for (; __ns; --__ns, ++__s)
1580 *__s = __fl;
1581 for (; __ob < __oe; ++__ob, ++__s)
1582 *__s = *__ob;
1583 __iob.width(0);
1584 return __s;
1585}
1586
1587template <class _CharT, class _OutputIterator>
1588_OutputIterator
1589num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1590 char_type __fl, bool __v) const
1591{
1592 if ((__iob.flags() & ios_base::boolalpha) == 0)
1593 return do_put(__s, __iob, __fl, (unsigned long)__v);
1594 const numpunct<char_type>& __np = use_facet<numpunct<char_type> >(__iob.getloc());
1595 typedef typename numpunct<char_type>::string_type string_type;
1596 string_type __nm = __v ? __np.truename() : __np.falsename();
1597 for (typename string_type::iterator __i = __nm.begin(); __i != __nm.end(); ++__i, ++__s)
1598 *__s = *__i;
1599 return __s;
1600}
1601
1602template <class _CharT, class _OutputIterator>
1603_OutputIterator
1604num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1605 char_type __fl, long __v) const
1606{
1607 // Stage 1 - Get number in narrow char
1608 char __fmt[6] = {'%', 0};
1609 const char* __len = "l";
1610 this->__format_int(__fmt+1, __len, true, __iob.flags());
1611 const unsigned __nbuf = (numeric_limits<long>::digits / 3)
1612 + ((numeric_limits<long>::digits % 3) != 0)
1613 + 1;
1614 char __nar[__nbuf];
Sean Huntf3907e62011-07-15 05:40:33 +00001615#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantbcbbd4d2011-07-15 14:46:11 +00001616 int __nc = sprintf_l(__nar, 0, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001617#else
1618 int __nc = __sprintf_l(__nar, __cloc(), __fmt, __v);
1619#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001620 char* __ne = __nar + __nc;
1621 char* __np = this->__identify_padding(__nar, __ne, __iob);
1622 // Stage 2 - Widen __nar while adding thousands separators
1623 char_type __o[2*(__nbuf-1) - 1];
1624 char_type* __op; // pad here
1625 char_type* __oe; // end of output
1626 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1627 // [__o, __oe) contains thousands_sep'd wide number
1628 // Stage 3 & 4
1629 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1630}
1631
1632template <class _CharT, class _OutputIterator>
1633_OutputIterator
1634num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1635 char_type __fl, long long __v) const
1636{
1637 // Stage 1 - Get number in narrow char
1638 char __fmt[8] = {'%', 0};
1639 const char* __len = "ll";
1640 this->__format_int(__fmt+1, __len, true, __iob.flags());
1641 const unsigned __nbuf = (numeric_limits<long long>::digits / 3)
1642 + ((numeric_limits<long long>::digits % 3) != 0)
1643 + 1;
1644 char __nar[__nbuf];
Sean Huntf3907e62011-07-15 05:40:33 +00001645#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantbcbbd4d2011-07-15 14:46:11 +00001646 int __nc = sprintf_l(__nar, 0, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001647#else
1648 int __nc = __sprintf_l(__nar, __cloc(), __fmt, __v);
1649#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001650 char* __ne = __nar + __nc;
1651 char* __np = this->__identify_padding(__nar, __ne, __iob);
1652 // Stage 2 - Widen __nar while adding thousands separators
1653 char_type __o[2*(__nbuf-1) - 1];
1654 char_type* __op; // pad here
1655 char_type* __oe; // end of output
1656 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1657 // [__o, __oe) contains thousands_sep'd wide number
1658 // Stage 3 & 4
1659 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1660}
1661
1662template <class _CharT, class _OutputIterator>
1663_OutputIterator
1664num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1665 char_type __fl, unsigned long __v) const
1666{
1667 // Stage 1 - Get number in narrow char
1668 char __fmt[6] = {'%', 0};
1669 const char* __len = "l";
1670 this->__format_int(__fmt+1, __len, false, __iob.flags());
1671 const unsigned __nbuf = (numeric_limits<unsigned long>::digits / 3)
1672 + ((numeric_limits<unsigned long>::digits % 3) != 0)
1673 + 1;
1674 char __nar[__nbuf];
Sean Huntf3907e62011-07-15 05:40:33 +00001675#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantbcbbd4d2011-07-15 14:46:11 +00001676 int __nc = sprintf_l(__nar, 0, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001677#else
1678 int __nc = __sprintf_l(__nar, __cloc(), __fmt, __v);
1679#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001680 char* __ne = __nar + __nc;
1681 char* __np = this->__identify_padding(__nar, __ne, __iob);
1682 // Stage 2 - Widen __nar while adding thousands separators
1683 char_type __o[2*(__nbuf-1) - 1];
1684 char_type* __op; // pad here
1685 char_type* __oe; // end of output
1686 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1687 // [__o, __oe) contains thousands_sep'd wide number
1688 // Stage 3 & 4
1689 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1690}
1691
1692template <class _CharT, class _OutputIterator>
1693_OutputIterator
1694num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1695 char_type __fl, unsigned long long __v) const
1696{
1697 // Stage 1 - Get number in narrow char
1698 char __fmt[8] = {'%', 0};
1699 const char* __len = "ll";
1700 this->__format_int(__fmt+1, __len, false, __iob.flags());
1701 const unsigned __nbuf = (numeric_limits<unsigned long long>::digits / 3)
1702 + ((numeric_limits<unsigned long long>::digits % 3) != 0)
1703 + 1;
1704 char __nar[__nbuf];
Sean Huntf3907e62011-07-15 05:40:33 +00001705#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantbcbbd4d2011-07-15 14:46:11 +00001706 int __nc = sprintf_l(__nar, 0, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001707#else
1708 int __nc = __sprintf_l(__nar, __cloc(), __fmt, __v);
1709#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001710 char* __ne = __nar + __nc;
1711 char* __np = this->__identify_padding(__nar, __ne, __iob);
1712 // Stage 2 - Widen __nar while adding thousands separators
1713 char_type __o[2*(__nbuf-1) - 1];
1714 char_type* __op; // pad here
1715 char_type* __oe; // end of output
1716 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1717 // [__o, __oe) contains thousands_sep'd wide number
1718 // Stage 3 & 4
1719 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1720}
1721
1722template <class _CharT, class _OutputIterator>
1723_OutputIterator
1724num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1725 char_type __fl, double __v) const
1726{
1727 // Stage 1 - Get number in narrow char
1728 char __fmt[8] = {'%', 0};
1729 const char* __len = "";
1730 bool __specify_precision = this->__format_float(__fmt+1, __len, __iob.flags());
1731 const unsigned __nbuf = 30;
1732 char __nar[__nbuf];
1733 char* __nb = __nar;
1734 int __nc;
1735 if (__specify_precision)
Sean Huntf3907e62011-07-15 05:40:33 +00001736#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantbcbbd4d2011-07-15 14:46:11 +00001737 __nc = snprintf_l(__nb, __nbuf, 0, __fmt,
Howard Hinnantadff4892010-05-24 17:49:41 +00001738 (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001739#else
1740 __nc = __snprintf_l(__nb, __nbuf, __cloc(), __fmt,
1741 (int)__iob.precision(), __v);
1742#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001743 else
Sean Huntf3907e62011-07-15 05:40:33 +00001744#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantbcbbd4d2011-07-15 14:46:11 +00001745 __nc = snprintf_l(__nb, __nbuf, 0, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001746#else
1747 __nc = __snprintf_l(__nb, __nbuf, __cloc(), __fmt, __v);
1748#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001749 unique_ptr<char, void(*)(void*)> __nbh(0, free);
1750 if (__nc > static_cast<int>(__nbuf-1))
1751 {
1752 if (__specify_precision)
Sean Huntf3907e62011-07-15 05:40:33 +00001753#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantbcbbd4d2011-07-15 14:46:11 +00001754 __nc = asprintf_l(&__nb, 0, __fmt, (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001755#else
1756 __nc = __asprintf_l(&__nb, __cloc(), __fmt,
David Chisnallc512df12011-09-21 08:39:44 +00001757 (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001758#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001759 else
Sean Huntf3907e62011-07-15 05:40:33 +00001760#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantbcbbd4d2011-07-15 14:46:11 +00001761 __nc = asprintf_l(&__nb, 0, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001762#else
David Chisnallc512df12011-09-21 08:39:44 +00001763 __nc = __asprintf_l(&__nb, __cloc(), __fmt, (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001764#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001765 if (__nb == 0)
1766 __throw_bad_alloc();
1767 __nbh.reset(__nb);
1768 }
1769 char* __ne = __nb + __nc;
1770 char* __np = this->__identify_padding(__nb, __ne, __iob);
1771 // Stage 2 - Widen __nar while adding thousands separators
1772 char_type __o[2*(__nbuf-1) - 1];
1773 char_type* __ob = __o;
1774 unique_ptr<char_type, void(*)(void*)> __obh(0, free);
1775 if (__nb != __nar)
1776 {
1777 __ob = (char_type*)malloc((2*__nc)*sizeof(char_type));
1778 if (__ob == 0)
1779 __throw_bad_alloc();
1780 __obh.reset(__ob);
1781 }
1782 char_type* __op; // pad here
1783 char_type* __oe; // end of output
1784 this->__widen_and_group_float(__nb, __np, __ne, __ob, __op, __oe, __iob.getloc());
1785 // [__o, __oe) contains thousands_sep'd wide number
1786 // Stage 3 & 4
1787 __s = __pad_and_output(__s, __ob, __op, __oe, __iob, __fl);
1788 return __s;
1789}
1790
1791template <class _CharT, class _OutputIterator>
1792_OutputIterator
1793num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1794 char_type __fl, long double __v) const
1795{
1796 // Stage 1 - Get number in narrow char
1797 char __fmt[8] = {'%', 0};
1798 const char* __len = "L";
1799 bool __specify_precision = this->__format_float(__fmt+1, __len, __iob.flags());
1800 const unsigned __nbuf = 30;
1801 char __nar[__nbuf];
1802 char* __nb = __nar;
1803 int __nc;
1804 if (__specify_precision)
Sean Huntf3907e62011-07-15 05:40:33 +00001805#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantbcbbd4d2011-07-15 14:46:11 +00001806 __nc = snprintf_l(__nb, __nbuf, 0, __fmt,
Howard Hinnantadff4892010-05-24 17:49:41 +00001807 (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001808#else
1809 __nc = __snprintf_l(__nb, __nbuf, __cloc(), __fmt,
1810 (int)__iob.precision(), __v);
1811#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001812 else
Sean Huntf3907e62011-07-15 05:40:33 +00001813#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantbcbbd4d2011-07-15 14:46:11 +00001814 __nc = snprintf_l(__nb, __nbuf, 0, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001815#else
1816 __nc = __snprintf_l(__nb, __nbuf, __cloc(), __fmt, __v);
1817#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001818 unique_ptr<char, void(*)(void*)> __nbh(0, free);
1819 if (__nc > static_cast<int>(__nbuf-1))
1820 {
1821 if (__specify_precision)
Sean Huntf3907e62011-07-15 05:40:33 +00001822#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantbcbbd4d2011-07-15 14:46:11 +00001823 __nc = asprintf_l(&__nb, 0, __fmt, (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001824#else
1825 __nc = __asprintf_l(&__nb, __cloc(), __fmt,
David Chisnallc512df12011-09-21 08:39:44 +00001826 (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001827#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001828 else
Sean Huntf3907e62011-07-15 05:40:33 +00001829#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantbcbbd4d2011-07-15 14:46:11 +00001830 __nc = asprintf_l(&__nb, 0, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001831#else
David Chisnallc512df12011-09-21 08:39:44 +00001832 __nc = __asprintf_l(&__nb, __cloc(), __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001833#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001834 if (__nb == 0)
1835 __throw_bad_alloc();
1836 __nbh.reset(__nb);
1837 }
1838 char* __ne = __nb + __nc;
1839 char* __np = this->__identify_padding(__nb, __ne, __iob);
1840 // Stage 2 - Widen __nar while adding thousands separators
1841 char_type __o[2*(__nbuf-1) - 1];
1842 char_type* __ob = __o;
1843 unique_ptr<char_type, void(*)(void*)> __obh(0, free);
1844 if (__nb != __nar)
1845 {
1846 __ob = (char_type*)malloc((2*__nc)*sizeof(char_type));
1847 if (__ob == 0)
1848 __throw_bad_alloc();
1849 __obh.reset(__ob);
1850 }
1851 char_type* __op; // pad here
1852 char_type* __oe; // end of output
1853 this->__widen_and_group_float(__nb, __np, __ne, __ob, __op, __oe, __iob.getloc());
1854 // [__o, __oe) contains thousands_sep'd wide number
1855 // Stage 3 & 4
1856 __s = __pad_and_output(__s, __ob, __op, __oe, __iob, __fl);
1857 return __s;
1858}
1859
1860template <class _CharT, class _OutputIterator>
1861_OutputIterator
1862num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1863 char_type __fl, const void* __v) const
1864{
1865 // Stage 1 - Get pointer in narrow char
1866 char __fmt[6] = "%p";
1867 const unsigned __nbuf = 20;
1868 char __nar[__nbuf];
Sean Huntf3907e62011-07-15 05:40:33 +00001869#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantbcbbd4d2011-07-15 14:46:11 +00001870 int __nc = sprintf_l(__nar, 0, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001871#else
1872 int __nc = __sprintf_l(__nar, __cloc(), __fmt, __v);
1873#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001874 char* __ne = __nar + __nc;
1875 char* __np = this->__identify_padding(__nar, __ne, __iob);
1876 // Stage 2 - Widen __nar
1877 char_type __o[2*(__nbuf-1) - 1];
1878 char_type* __op; // pad here
1879 char_type* __oe; // end of output
1880 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
1881 __ct.widen(__nar, __ne, __o);
1882 __oe = __o + (__ne - __nar);
1883 if (__np == __ne)
1884 __op = __oe;
1885 else
1886 __op = __o + (__np - __nar);
1887 // [__o, __oe) contains wide number
1888 // Stage 3 & 4
1889 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1890}
1891
1892extern template class num_put<char>;
1893extern template class num_put<wchar_t>;
1894
1895template <class _CharT, class _InputIterator>
1896_LIBCPP_HIDDEN
1897int
1898__get_up_to_n_digits(_InputIterator& __b, _InputIterator __e,
1899 ios_base::iostate& __err, const ctype<_CharT>& __ct, int __n)
1900{
1901 // Precondition: __n >= 1
1902 if (__b == __e)
1903 {
1904 __err |= ios_base::eofbit | ios_base::failbit;
1905 return 0;
1906 }
1907 // get first digit
1908 _CharT __c = *__b;
1909 if (!__ct.is(ctype_base::digit, __c))
1910 {
1911 __err |= ios_base::failbit;
1912 return 0;
1913 }
1914 int __r = __ct.narrow(__c, 0) - '0';
1915 for (++__b, --__n; __b != __e && __n > 0; ++__b, --__n)
1916 {
1917 // get next digit
1918 __c = *__b;
1919 if (!__ct.is(ctype_base::digit, __c))
1920 return __r;
1921 __r = __r * 10 + __ct.narrow(__c, 0) - '0';
1922 }
1923 if (__b == __e)
1924 __err |= ios_base::eofbit;
1925 return __r;
1926}
1927
Howard Hinnant82894812010-09-22 16:48:34 +00001928class _LIBCPP_VISIBLE time_base
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001929{
1930public:
1931 enum dateorder {no_order, dmy, mdy, ymd, ydm};
1932};
1933
1934template <class _CharT>
Howard Hinnant2d72b1e2010-12-17 14:46:43 +00001935class __time_get_c_storage // purposefully not decorated
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001936{
1937protected:
1938 typedef basic_string<_CharT> string_type;
1939
1940 virtual const string_type* __weeks() const;
1941 virtual const string_type* __months() const;
1942 virtual const string_type* __am_pm() const;
1943 virtual const string_type& __c() const;
1944 virtual const string_type& __r() const;
1945 virtual const string_type& __x() const;
1946 virtual const string_type& __X() const;
1947};
1948
1949template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00001950class _LIBCPP_VISIBLE time_get
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001951 : public locale::facet,
1952 public time_base,
1953 private __time_get_c_storage<_CharT>
1954{
1955public:
1956 typedef _CharT char_type;
1957 typedef _InputIterator iter_type;
1958 typedef time_base::dateorder dateorder;
1959 typedef basic_string<char_type> string_type;
1960
1961 _LIBCPP_ALWAYS_INLINE
1962 explicit time_get(size_t __refs = 0)
1963 : locale::facet(__refs) {}
1964
1965 _LIBCPP_ALWAYS_INLINE
1966 dateorder date_order() const
1967 {
1968 return this->do_date_order();
1969 }
1970
1971 _LIBCPP_ALWAYS_INLINE
1972 iter_type get_time(iter_type __b, iter_type __e, ios_base& __iob,
1973 ios_base::iostate& __err, tm* __tm) const
1974 {
1975 return do_get_time(__b, __e, __iob, __err, __tm);
1976 }
1977
1978 _LIBCPP_ALWAYS_INLINE
1979 iter_type get_date(iter_type __b, iter_type __e, ios_base& __iob,
1980 ios_base::iostate& __err, tm* __tm) const
1981 {
1982 return do_get_date(__b, __e, __iob, __err, __tm);
1983 }
1984
1985 _LIBCPP_ALWAYS_INLINE
1986 iter_type get_weekday(iter_type __b, iter_type __e, ios_base& __iob,
1987 ios_base::iostate& __err, tm* __tm) const
1988 {
1989 return do_get_weekday(__b, __e, __iob, __err, __tm);
1990 }
1991
1992 _LIBCPP_ALWAYS_INLINE
1993 iter_type get_monthname(iter_type __b, iter_type __e, ios_base& __iob,
1994 ios_base::iostate& __err, tm* __tm) const
1995 {
1996 return do_get_monthname(__b, __e, __iob, __err, __tm);
1997 }
1998
1999 _LIBCPP_ALWAYS_INLINE
2000 iter_type get_year(iter_type __b, iter_type __e, ios_base& __iob,
2001 ios_base::iostate& __err, tm* __tm) const
2002 {
2003 return do_get_year(__b, __e, __iob, __err, __tm);
2004 }
2005
2006 _LIBCPP_ALWAYS_INLINE
2007 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
2008 ios_base::iostate& __err, tm *__tm,
2009 char __fmt, char __mod = 0) const
2010 {
2011 return do_get(__b, __e, __iob, __err, __tm, __fmt, __mod);
2012 }
2013
2014 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
2015 ios_base::iostate& __err, tm* __tm,
2016 const char_type* __fmtb, const char_type* __fmte) const;
2017
2018 static locale::id id;
2019
2020protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002021 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002022 ~time_get() {}
2023
2024 virtual dateorder do_date_order() const;
2025 virtual iter_type do_get_time(iter_type __b, iter_type __e, ios_base& __iob,
2026 ios_base::iostate& __err, tm* __tm) const;
2027 virtual iter_type do_get_date(iter_type __b, iter_type __e, ios_base& __iob,
2028 ios_base::iostate& __err, tm* __tm) const;
2029 virtual iter_type do_get_weekday(iter_type __b, iter_type __e, ios_base& __iob,
2030 ios_base::iostate& __err, tm* __tm) const;
2031 virtual iter_type do_get_monthname(iter_type __b, iter_type __e, ios_base& __iob,
2032 ios_base::iostate& __err, tm* __tm) const;
2033 virtual iter_type do_get_year(iter_type __b, iter_type __e, ios_base& __iob,
2034 ios_base::iostate& __err, tm* __tm) const;
2035 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
2036 ios_base::iostate& __err, tm* __tm,
2037 char __fmt, char __mod) const;
2038private:
2039 void __get_white_space(iter_type& __b, iter_type __e,
2040 ios_base::iostate& __err, const ctype<char_type>& __ct) const;
2041 void __get_percent(iter_type& __b, iter_type __e, ios_base::iostate& __err,
2042 const ctype<char_type>& __ct) const;
2043
2044 void __get_weekdayname(int& __m,
2045 iter_type& __b, iter_type __e,
2046 ios_base::iostate& __err,
2047 const ctype<char_type>& __ct) const;
2048 void __get_monthname(int& __m,
2049 iter_type& __b, iter_type __e,
2050 ios_base::iostate& __err,
2051 const ctype<char_type>& __ct) const;
2052 void __get_day(int& __d,
2053 iter_type& __b, iter_type __e,
2054 ios_base::iostate& __err,
2055 const ctype<char_type>& __ct) const;
2056 void __get_month(int& __m,
2057 iter_type& __b, iter_type __e,
2058 ios_base::iostate& __err,
2059 const ctype<char_type>& __ct) const;
2060 void __get_year(int& __y,
2061 iter_type& __b, iter_type __e,
2062 ios_base::iostate& __err,
2063 const ctype<char_type>& __ct) const;
2064 void __get_year4(int& __y,
2065 iter_type& __b, iter_type __e,
2066 ios_base::iostate& __err,
2067 const ctype<char_type>& __ct) const;
2068 void __get_hour(int& __d,
2069 iter_type& __b, iter_type __e,
2070 ios_base::iostate& __err,
2071 const ctype<char_type>& __ct) const;
2072 void __get_12_hour(int& __h,
2073 iter_type& __b, iter_type __e,
2074 ios_base::iostate& __err,
2075 const ctype<char_type>& __ct) const;
2076 void __get_am_pm(int& __h,
2077 iter_type& __b, iter_type __e,
2078 ios_base::iostate& __err,
2079 const ctype<char_type>& __ct) const;
2080 void __get_minute(int& __m,
2081 iter_type& __b, iter_type __e,
2082 ios_base::iostate& __err,
2083 const ctype<char_type>& __ct) const;
2084 void __get_second(int& __s,
2085 iter_type& __b, iter_type __e,
2086 ios_base::iostate& __err,
2087 const ctype<char_type>& __ct) const;
2088 void __get_weekday(int& __w,
2089 iter_type& __b, iter_type __e,
2090 ios_base::iostate& __err,
2091 const ctype<char_type>& __ct) const;
2092 void __get_day_year_num(int& __w,
2093 iter_type& __b, iter_type __e,
2094 ios_base::iostate& __err,
2095 const ctype<char_type>& __ct) const;
2096};
2097
2098template <class _CharT, class _InputIterator>
2099locale::id
2100time_get<_CharT, _InputIterator>::id;
2101
2102// time_get primatives
2103
2104template <class _CharT, class _InputIterator>
2105void
2106time_get<_CharT, _InputIterator>::__get_weekdayname(int& __w,
2107 iter_type& __b, iter_type __e,
2108 ios_base::iostate& __err,
2109 const ctype<char_type>& __ct) const
2110{
2111 // Note: ignoring case comes from the POSIX strptime spec
2112 const string_type* __wk = this->__weeks();
2113 int __i = __scan_keyword(__b, __e, __wk, __wk+14, __ct, __err, false) - __wk;
2114 if (__i < 14)
2115 __w = __i % 7;
2116}
2117
2118template <class _CharT, class _InputIterator>
2119void
2120time_get<_CharT, _InputIterator>::__get_monthname(int& __m,
2121 iter_type& __b, iter_type __e,
2122 ios_base::iostate& __err,
2123 const ctype<char_type>& __ct) const
2124{
2125 // Note: ignoring case comes from the POSIX strptime spec
2126 const string_type* __month = this->__months();
2127 int __i = __scan_keyword(__b, __e, __month, __month+24, __ct, __err, false) - __month;
2128 if (__i < 24)
2129 __m = __i % 12;
2130}
2131
2132template <class _CharT, class _InputIterator>
2133void
2134time_get<_CharT, _InputIterator>::__get_day(int& __d,
2135 iter_type& __b, iter_type __e,
2136 ios_base::iostate& __err,
2137 const ctype<char_type>& __ct) const
2138{
2139 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2140 if (!(__err & ios_base::failbit) && 1 <= __t && __t <= 31)
2141 __d = __t;
2142 else
2143 __err |= ios_base::failbit;
2144}
2145
2146template <class _CharT, class _InputIterator>
2147void
2148time_get<_CharT, _InputIterator>::__get_month(int& __m,
2149 iter_type& __b, iter_type __e,
2150 ios_base::iostate& __err,
2151 const ctype<char_type>& __ct) const
2152{
2153 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2) - 1;
2154 if (!(__err & ios_base::failbit) && __t <= 11)
2155 __m = __t;
2156 else
2157 __err |= ios_base::failbit;
2158}
2159
2160template <class _CharT, class _InputIterator>
2161void
2162time_get<_CharT, _InputIterator>::__get_year(int& __y,
2163 iter_type& __b, iter_type __e,
2164 ios_base::iostate& __err,
2165 const ctype<char_type>& __ct) const
2166{
2167 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 4);
2168 if (!(__err & ios_base::failbit))
2169 {
2170 if (__t < 69)
2171 __t += 2000;
2172 else if (69 <= __t && __t <= 99)
2173 __t += 1900;
2174 __y = __t - 1900;
2175 }
2176}
2177
2178template <class _CharT, class _InputIterator>
2179void
2180time_get<_CharT, _InputIterator>::__get_year4(int& __y,
2181 iter_type& __b, iter_type __e,
2182 ios_base::iostate& __err,
2183 const ctype<char_type>& __ct) const
2184{
2185 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 4);
2186 if (!(__err & ios_base::failbit))
2187 __y = __t - 1900;
2188}
2189
2190template <class _CharT, class _InputIterator>
2191void
2192time_get<_CharT, _InputIterator>::__get_hour(int& __h,
2193 iter_type& __b, iter_type __e,
2194 ios_base::iostate& __err,
2195 const ctype<char_type>& __ct) const
2196{
2197 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2198 if (!(__err & ios_base::failbit) && __t <= 23)
2199 __h = __t;
2200 else
2201 __err |= ios_base::failbit;
2202}
2203
2204template <class _CharT, class _InputIterator>
2205void
2206time_get<_CharT, _InputIterator>::__get_12_hour(int& __h,
2207 iter_type& __b, iter_type __e,
2208 ios_base::iostate& __err,
2209 const ctype<char_type>& __ct) const
2210{
2211 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2212 if (!(__err & ios_base::failbit) && 1 <= __t && __t <= 12)
2213 __h = __t;
2214 else
2215 __err |= ios_base::failbit;
2216}
2217
2218template <class _CharT, class _InputIterator>
2219void
2220time_get<_CharT, _InputIterator>::__get_minute(int& __m,
2221 iter_type& __b, iter_type __e,
2222 ios_base::iostate& __err,
2223 const ctype<char_type>& __ct) const
2224{
2225 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2226 if (!(__err & ios_base::failbit) && __t <= 59)
2227 __m = __t;
2228 else
2229 __err |= ios_base::failbit;
2230}
2231
2232template <class _CharT, class _InputIterator>
2233void
2234time_get<_CharT, _InputIterator>::__get_second(int& __s,
2235 iter_type& __b, iter_type __e,
2236 ios_base::iostate& __err,
2237 const ctype<char_type>& __ct) const
2238{
2239 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2240 if (!(__err & ios_base::failbit) && __t <= 60)
2241 __s = __t;
2242 else
2243 __err |= ios_base::failbit;
2244}
2245
2246template <class _CharT, class _InputIterator>
2247void
2248time_get<_CharT, _InputIterator>::__get_weekday(int& __w,
2249 iter_type& __b, iter_type __e,
2250 ios_base::iostate& __err,
2251 const ctype<char_type>& __ct) const
2252{
2253 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 1);
2254 if (!(__err & ios_base::failbit) && __t <= 6)
2255 __w = __t;
2256 else
2257 __err |= ios_base::failbit;
2258}
2259
2260template <class _CharT, class _InputIterator>
2261void
2262time_get<_CharT, _InputIterator>::__get_day_year_num(int& __d,
2263 iter_type& __b, iter_type __e,
2264 ios_base::iostate& __err,
2265 const ctype<char_type>& __ct) const
2266{
2267 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 3);
2268 if (!(__err & ios_base::failbit) && __t <= 365)
2269 __d = __t;
2270 else
2271 __err |= ios_base::failbit;
2272}
2273
2274template <class _CharT, class _InputIterator>
2275void
2276time_get<_CharT, _InputIterator>::__get_white_space(iter_type& __b, iter_type __e,
2277 ios_base::iostate& __err,
2278 const ctype<char_type>& __ct) const
2279{
2280 for (; __b != __e && __ct.is(ctype_base::space, *__b); ++__b)
2281 ;
2282 if (__b == __e)
2283 __err |= ios_base::eofbit;
2284}
2285
2286template <class _CharT, class _InputIterator>
2287void
2288time_get<_CharT, _InputIterator>::__get_am_pm(int& __h,
2289 iter_type& __b, iter_type __e,
2290 ios_base::iostate& __err,
2291 const ctype<char_type>& __ct) const
2292{
2293 const string_type* __ap = this->__am_pm();
2294 if (__ap[0].size() + __ap[1].size() == 0)
2295 {
2296 __err |= ios_base::failbit;
2297 return;
2298 }
2299 int __i = __scan_keyword(__b, __e, __ap, __ap+2, __ct, __err, false) - __ap;
2300 if (__i == 0 && __h == 12)
2301 __h = 0;
2302 else if (__i == 1 && __h < 12)
2303 __h += 12;
2304}
2305
2306template <class _CharT, class _InputIterator>
2307void
2308time_get<_CharT, _InputIterator>::__get_percent(iter_type& __b, iter_type __e,
2309 ios_base::iostate& __err,
2310 const ctype<char_type>& __ct) const
2311{
2312 if (__b == __e)
2313 {
2314 __err |= ios_base::eofbit | ios_base::failbit;
2315 return;
2316 }
2317 if (__ct.narrow(*__b, 0) != '%')
2318 __err |= ios_base::failbit;
2319 else if(++__b == __e)
2320 __err |= ios_base::eofbit;
2321}
2322
2323// time_get end primatives
2324
2325template <class _CharT, class _InputIterator>
2326_InputIterator
2327time_get<_CharT, _InputIterator>::get(iter_type __b, iter_type __e,
2328 ios_base& __iob,
2329 ios_base::iostate& __err, tm* __tm,
2330 const char_type* __fmtb, const char_type* __fmte) const
2331{
2332 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2333 __err = ios_base::goodbit;
2334 while (__fmtb != __fmte && __err == ios_base::goodbit)
2335 {
2336 if (__b == __e)
2337 {
2338 __err = ios_base::failbit;
2339 break;
2340 }
2341 if (__ct.narrow(*__fmtb, 0) == '%')
2342 {
2343 if (++__fmtb == __fmte)
2344 {
2345 __err = ios_base::failbit;
2346 break;
2347 }
2348 char __cmd = __ct.narrow(*__fmtb, 0);
2349 char __opt = '\0';
2350 if (__cmd == 'E' || __cmd == '0')
2351 {
2352 if (++__fmtb == __fmte)
2353 {
2354 __err = ios_base::failbit;
2355 break;
2356 }
2357 __opt = __cmd;
2358 __cmd = __ct.narrow(*__fmtb, 0);
2359 }
2360 __b = do_get(__b, __e, __iob, __err, __tm, __cmd, __opt);
2361 ++__fmtb;
2362 }
2363 else if (__ct.is(ctype_base::space, *__fmtb))
2364 {
2365 for (++__fmtb; __fmtb != __fmte && __ct.is(ctype_base::space, *__fmtb); ++__fmtb)
2366 ;
2367 for ( ; __b != __e && __ct.is(ctype_base::space, *__b); ++__b)
2368 ;
2369 }
2370 else if (__ct.toupper(*__b) == __ct.toupper(*__fmtb))
2371 {
2372 ++__b;
2373 ++__fmtb;
2374 }
2375 else
2376 __err = ios_base::failbit;
2377 }
2378 if (__b == __e)
2379 __err |= ios_base::eofbit;
2380 return __b;
2381}
2382
2383template <class _CharT, class _InputIterator>
2384typename time_get<_CharT, _InputIterator>::dateorder
2385time_get<_CharT, _InputIterator>::do_date_order() const
2386{
2387 return mdy;
2388}
2389
2390template <class _CharT, class _InputIterator>
2391_InputIterator
2392time_get<_CharT, _InputIterator>::do_get_time(iter_type __b, iter_type __e,
2393 ios_base& __iob,
2394 ios_base::iostate& __err,
2395 tm* __tm) const
2396{
2397 const char_type __fmt[] = {'%', 'H', ':', '%', 'M', ':', '%', 'S'};
2398 return get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2399}
2400
2401template <class _CharT, class _InputIterator>
2402_InputIterator
2403time_get<_CharT, _InputIterator>::do_get_date(iter_type __b, iter_type __e,
2404 ios_base& __iob,
2405 ios_base::iostate& __err,
2406 tm* __tm) const
2407{
2408 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2409 const string_type& __fmt = this->__x();
2410 return get(__b, __e, __iob, __err, __tm, __fmt.data(), __fmt.data() + __fmt.size());
2411}
2412
2413template <class _CharT, class _InputIterator>
2414_InputIterator
2415time_get<_CharT, _InputIterator>::do_get_weekday(iter_type __b, iter_type __e,
2416 ios_base& __iob,
2417 ios_base::iostate& __err,
2418 tm* __tm) const
2419{
2420 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2421 __get_weekdayname(__tm->tm_wday, __b, __e, __err, __ct);
2422 return __b;
2423}
2424
2425template <class _CharT, class _InputIterator>
2426_InputIterator
2427time_get<_CharT, _InputIterator>::do_get_monthname(iter_type __b, iter_type __e,
2428 ios_base& __iob,
2429 ios_base::iostate& __err,
2430 tm* __tm) const
2431{
2432 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2433 __get_monthname(__tm->tm_mon, __b, __e, __err, __ct);
2434 return __b;
2435}
2436
2437template <class _CharT, class _InputIterator>
2438_InputIterator
2439time_get<_CharT, _InputIterator>::do_get_year(iter_type __b, iter_type __e,
2440 ios_base& __iob,
2441 ios_base::iostate& __err,
2442 tm* __tm) const
2443{
2444 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2445 __get_year(__tm->tm_year, __b, __e, __err, __ct);
2446 return __b;
2447}
2448
2449template <class _CharT, class _InputIterator>
2450_InputIterator
2451time_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
2452 ios_base& __iob,
2453 ios_base::iostate& __err, tm* __tm,
2454 char __fmt, char) const
2455{
2456 __err = ios_base::goodbit;
2457 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2458 switch (__fmt)
2459 {
2460 case 'a':
2461 case 'A':
2462 __get_weekdayname(__tm->tm_wday, __b, __e, __err, __ct);
2463 break;
2464 case 'b':
2465 case 'B':
2466 case 'h':
2467 __get_monthname(__tm->tm_mon, __b, __e, __err, __ct);
2468 break;
2469 case 'c':
2470 {
2471 const string_type& __fmt = this->__c();
2472 __b = get(__b, __e, __iob, __err, __tm, __fmt.data(), __fmt.data() + __fmt.size());
2473 }
2474 break;
2475 case 'd':
2476 case 'e':
2477 __get_day(__tm->tm_mday, __b, __e, __err, __ct);
2478 break;
2479 case 'D':
2480 {
2481 const char_type __fmt[] = {'%', 'm', '/', '%', 'd', '/', '%', 'y'};
2482 __b = get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2483 }
2484 break;
Howard Hinnant506b3642011-04-10 17:54:14 +00002485 case 'F':
2486 {
2487 const char_type __fmt[] = {'%', 'Y', '-', '%', 'm', '-', '%', 'd'};
2488 __b = get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2489 }
2490 break;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002491 case 'H':
2492 __get_hour(__tm->tm_hour, __b, __e, __err, __ct);
2493 break;
2494 case 'I':
2495 __get_12_hour(__tm->tm_hour, __b, __e, __err, __ct);
2496 break;
2497 case 'j':
2498 __get_day_year_num(__tm->tm_yday, __b, __e, __err, __ct);
2499 break;
2500 case 'm':
2501 __get_month(__tm->tm_mon, __b, __e, __err, __ct);
2502 break;
2503 case 'M':
2504 __get_minute(__tm->tm_min, __b, __e, __err, __ct);
2505 break;
2506 case 'n':
2507 case 't':
2508 __get_white_space(__b, __e, __err, __ct);
2509 break;
2510 case 'p':
2511 __get_am_pm(__tm->tm_hour, __b, __e, __err, __ct);
2512 break;
2513 case 'r':
2514 {
2515 const char_type __fmt[] = {'%', 'I', ':', '%', 'M', ':', '%', 'S', ' ', '%', 'p'};
2516 __b = get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2517 }
2518 break;
2519 case 'R':
2520 {
2521 const char_type __fmt[] = {'%', 'H', ':', '%', 'M'};
2522 __b = get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2523 }
2524 break;
2525 case 'S':
2526 __get_second(__tm->tm_sec, __b, __e, __err, __ct);
2527 break;
2528 case 'T':
2529 {
2530 const char_type __fmt[] = {'%', 'H', ':', '%', 'M', ':', '%', 'S'};
2531 __b = get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2532 }
2533 break;
2534 case 'w':
2535 __get_weekday(__tm->tm_wday, __b, __e, __err, __ct);
2536 break;
2537 case 'x':
2538 return do_get_date(__b, __e, __iob, __err, __tm);
2539 case 'X':
2540 {
2541 const string_type& __fmt = this->__X();
2542 __b = get(__b, __e, __iob, __err, __tm, __fmt.data(), __fmt.data() + __fmt.size());
2543 }
2544 break;
2545 case 'y':
2546 __get_year(__tm->tm_year, __b, __e, __err, __ct);
2547 break;
2548 case 'Y':
2549 __get_year4(__tm->tm_year, __b, __e, __err, __ct);
2550 break;
2551 case '%':
2552 __get_percent(__b, __e, __err, __ct);
2553 break;
2554 default:
2555 __err |= ios_base::failbit;
2556 }
2557 return __b;
2558}
2559
2560extern template class time_get<char>;
2561extern template class time_get<wchar_t>;
2562
2563class __time_get
2564{
2565protected:
2566 locale_t __loc_;
2567
2568 __time_get(const char* __nm);
2569 __time_get(const string& __nm);
2570 ~__time_get();
2571};
2572
2573template <class _CharT>
2574class __time_get_storage
2575 : public __time_get
2576{
2577protected:
2578 typedef basic_string<_CharT> string_type;
2579
2580 string_type __weeks_[14];
2581 string_type __months_[24];
2582 string_type __am_pm_[2];
2583 string_type __c_;
2584 string_type __r_;
2585 string_type __x_;
2586 string_type __X_;
2587
2588 explicit __time_get_storage(const char* __nm);
2589 explicit __time_get_storage(const string& __nm);
2590
2591 _LIBCPP_ALWAYS_INLINE ~__time_get_storage() {}
2592
2593 time_base::dateorder __do_date_order() const;
2594
2595private:
2596 void init(const ctype<_CharT>&);
2597 string_type __analyze(char __fmt, const ctype<_CharT>&);
2598};
2599
2600template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00002601class _LIBCPP_VISIBLE time_get_byname
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002602 : public time_get<_CharT, _InputIterator>,
2603 private __time_get_storage<_CharT>
2604{
2605public:
2606 typedef time_base::dateorder dateorder;
2607 typedef _InputIterator iter_type;
2608 typedef _CharT char_type;
2609 typedef basic_string<char_type> string_type;
2610
Howard Hinnant82894812010-09-22 16:48:34 +00002611 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002612 explicit time_get_byname(const char* __nm, size_t __refs = 0)
2613 : time_get<_CharT, _InputIterator>(__refs),
2614 __time_get_storage<_CharT>(__nm) {}
Howard Hinnant82894812010-09-22 16:48:34 +00002615 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002616 explicit time_get_byname(const string& __nm, size_t __refs = 0)
2617 : time_get<_CharT, _InputIterator>(__refs),
2618 __time_get_storage<_CharT>(__nm) {}
2619
2620protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002621 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002622 ~time_get_byname() {}
2623
Howard Hinnant82894812010-09-22 16:48:34 +00002624 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002625 virtual dateorder do_date_order() const {return this->__do_date_order();}
2626private:
Howard Hinnant82894812010-09-22 16:48:34 +00002627 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002628 virtual const string_type* __weeks() const {return this->__weeks_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002629 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002630 virtual const string_type* __months() const {return this->__months_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002631 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002632 virtual const string_type* __am_pm() const {return this->__am_pm_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002633 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002634 virtual const string_type& __c() const {return this->__c_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002635 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002636 virtual const string_type& __r() const {return this->__r_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002637 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002638 virtual const string_type& __x() const {return this->__x_;}
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_;}
2641};
2642
2643extern template class time_get_byname<char>;
2644extern template class time_get_byname<wchar_t>;
2645
2646class __time_put
2647{
2648 locale_t __loc_;
2649protected:
Sean Hunt0389c532011-07-12 00:55:04 +00002650#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002651 _LIBCPP_ALWAYS_INLINE __time_put() : __loc_(0) {}
Sean Hunt0389c532011-07-12 00:55:04 +00002652#else // _LIBCPP_STABLE_APPLE_ABI
2653 _LIBCPP_ALWAYS_INLINE __time_put() : __loc_(__cloc()) {}
2654#endif // _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002655 __time_put(const char* __nm);
2656 __time_put(const string& __nm);
2657 ~__time_put();
2658 void __do_put(char* __nb, char*& __ne, const tm* __tm,
2659 char __fmt, char __mod) const;
2660 void __do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
2661 char __fmt, char __mod) const;
2662};
2663
2664template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00002665class _LIBCPP_VISIBLE time_put
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002666 : public locale::facet,
2667 private __time_put
2668{
2669public:
2670 typedef _CharT char_type;
2671 typedef _OutputIterator iter_type;
2672
2673 _LIBCPP_ALWAYS_INLINE
2674 explicit time_put(size_t __refs = 0)
2675 : locale::facet(__refs) {}
2676
2677 iter_type put(iter_type __s, ios_base& __iob, char_type __fl, const tm* __tm,
2678 const char_type* __pb, const char_type* __pe) const;
2679
2680 _LIBCPP_ALWAYS_INLINE
2681 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
2682 const tm* __tm, char __fmt, char __mod = 0) const
2683 {
2684 return do_put(__s, __iob, __fl, __tm, __fmt, __mod);
2685 }
2686
2687 static locale::id id;
2688
2689protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002690 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002691 ~time_put() {}
2692 virtual iter_type do_put(iter_type __s, ios_base&, char_type, const tm* __tm,
2693 char __fmt, char __mod) const;
2694
Howard Hinnant82894812010-09-22 16:48:34 +00002695 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002696 explicit time_put(const char* __nm, size_t __refs)
2697 : locale::facet(__refs),
2698 __time_put(__nm) {}
Howard Hinnant82894812010-09-22 16:48:34 +00002699 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002700 explicit time_put(const string& __nm, size_t __refs)
2701 : locale::facet(__refs),
2702 __time_put(__nm) {}
2703};
2704
2705template <class _CharT, class _OutputIterator>
2706locale::id
2707time_put<_CharT, _OutputIterator>::id;
2708
2709template <class _CharT, class _OutputIterator>
2710_OutputIterator
2711time_put<_CharT, _OutputIterator>::put(iter_type __s, ios_base& __iob,
2712 char_type __fl, const tm* __tm,
2713 const char_type* __pb,
2714 const char_type* __pe) const
2715{
2716 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2717 for (; __pb != __pe; ++__pb)
2718 {
2719 if (__ct.narrow(*__pb, 0) == '%')
2720 {
2721 if (++__pb == __pe)
2722 {
2723 *__s++ = __pb[-1];
2724 break;
2725 }
2726 char __mod = 0;
2727 char __fmt = __ct.narrow(*__pb, 0);
2728 if (__fmt == 'E' || __fmt == 'O')
2729 {
2730 if (++__pb == __pe)
2731 {
2732 *__s++ = __pb[-2];
2733 *__s++ = __pb[-1];
2734 break;
2735 }
2736 __mod = __fmt;
2737 __fmt = __ct.narrow(*__pb, 0);
2738 }
2739 __s = do_put(__s, __iob, __fl, __tm, __fmt, __mod);
2740 }
2741 else
2742 *__s++ = *__pb;
2743 }
2744 return __s;
2745}
2746
2747template <class _CharT, class _OutputIterator>
2748_OutputIterator
2749time_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
2750 char_type, const tm* __tm,
2751 char __fmt, char __mod) const
2752{
2753 char_type __nar[100];
2754 char_type* __nb = __nar;
2755 char_type* __ne = __nb + 100;
2756 __do_put(__nb, __ne, __tm, __fmt, __mod);
Howard Hinnant0949eed2011-06-30 21:18:19 +00002757 return _VSTD::copy(__nb, __ne, __s);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002758}
2759
2760extern template class time_put<char>;
2761extern template class time_put<wchar_t>;
2762
2763template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00002764class _LIBCPP_VISIBLE time_put_byname
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002765 : public time_put<_CharT, _OutputIterator>
2766{
2767public:
2768 _LIBCPP_ALWAYS_INLINE
2769 explicit time_put_byname(const char* __nm, size_t __refs = 0)
2770 : time_put<_CharT, _OutputIterator>(__nm, __refs) {}
2771
2772 _LIBCPP_ALWAYS_INLINE
2773 explicit time_put_byname(const string& __nm, size_t __refs = 0)
2774 : time_put<_CharT, _OutputIterator>(__nm, __refs) {}
2775
2776protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002777 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002778 ~time_put_byname() {}
2779};
2780
2781extern template class time_put_byname<char>;
2782extern template class time_put_byname<wchar_t>;
2783
2784// money_base
2785
Howard Hinnant82894812010-09-22 16:48:34 +00002786class _LIBCPP_VISIBLE money_base
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002787{
2788public:
2789 enum part {none, space, symbol, sign, value};
2790 struct pattern {char field[4];};
2791
2792 _LIBCPP_ALWAYS_INLINE money_base() {}
2793};
2794
2795// moneypunct
2796
2797template <class _CharT, bool _International = false>
Howard Hinnant82894812010-09-22 16:48:34 +00002798class _LIBCPP_VISIBLE moneypunct
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002799 : public locale::facet,
2800 public money_base
2801{
2802public:
2803 typedef _CharT char_type;
2804 typedef basic_string<char_type> string_type;
2805
Howard Hinnant82894812010-09-22 16:48:34 +00002806 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002807 explicit moneypunct(size_t __refs = 0)
2808 : locale::facet(__refs) {}
2809
2810 _LIBCPP_ALWAYS_INLINE char_type decimal_point() const {return do_decimal_point();}
2811 _LIBCPP_ALWAYS_INLINE char_type thousands_sep() const {return do_thousands_sep();}
2812 _LIBCPP_ALWAYS_INLINE string grouping() const {return do_grouping();}
2813 _LIBCPP_ALWAYS_INLINE string_type curr_symbol() const {return do_curr_symbol();}
2814 _LIBCPP_ALWAYS_INLINE string_type positive_sign() const {return do_positive_sign();}
2815 _LIBCPP_ALWAYS_INLINE string_type negative_sign() const {return do_negative_sign();}
2816 _LIBCPP_ALWAYS_INLINE int frac_digits() const {return do_frac_digits();}
2817 _LIBCPP_ALWAYS_INLINE pattern pos_format() const {return do_pos_format();}
2818 _LIBCPP_ALWAYS_INLINE pattern neg_format() const {return do_neg_format();}
2819
2820 static locale::id id;
2821 static const bool intl = _International;
2822
2823protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002824 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002825 ~moneypunct() {}
2826
2827 virtual char_type do_decimal_point() const {return numeric_limits<char_type>::max();}
2828 virtual char_type do_thousands_sep() const {return numeric_limits<char_type>::max();}
2829 virtual string do_grouping() const {return string();}
2830 virtual string_type do_curr_symbol() const {return string_type();}
2831 virtual string_type do_positive_sign() const {return string_type();}
2832 virtual string_type do_negative_sign() const {return string_type(1, '-');}
2833 virtual int do_frac_digits() const {return 0;}
2834 virtual pattern do_pos_format() const
2835 {pattern __p = {symbol, sign, none, value}; return __p;}
2836 virtual pattern do_neg_format() const
2837 {pattern __p = {symbol, sign, none, value}; return __p;}
2838};
2839
2840template <class _CharT, bool _International>
2841locale::id
2842moneypunct<_CharT, _International>::id;
2843
2844extern template class moneypunct<char, false>;
2845extern template class moneypunct<char, true>;
2846extern template class moneypunct<wchar_t, false>;
2847extern template class moneypunct<wchar_t, true>;
2848
2849// moneypunct_byname
2850
2851template <class _CharT, bool _International = false>
Howard Hinnant82894812010-09-22 16:48:34 +00002852class _LIBCPP_VISIBLE moneypunct_byname
2853 : public moneypunct<_CharT, _International>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002854{
2855public:
2856 typedef money_base::pattern pattern;
2857 typedef _CharT char_type;
2858 typedef basic_string<char_type> string_type;
2859
2860 _LIBCPP_ALWAYS_INLINE
2861 explicit moneypunct_byname(const char* __nm, size_t __refs = 0)
2862 : moneypunct<_CharT, _International>(__refs) {init(__nm);}
2863
2864 _LIBCPP_ALWAYS_INLINE
2865 explicit moneypunct_byname(const string& __nm, size_t __refs = 0)
2866 : moneypunct<_CharT, _International>(__refs) {init(__nm.c_str());}
2867
2868protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002869 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002870 ~moneypunct_byname() {}
2871
2872 virtual char_type do_decimal_point() const {return __decimal_point_;}
2873 virtual char_type do_thousands_sep() const {return __thousands_sep_;}
2874 virtual string do_grouping() const {return __grouping_;}
2875 virtual string_type do_curr_symbol() const {return __curr_symbol_;}
2876 virtual string_type do_positive_sign() const {return __positive_sign_;}
2877 virtual string_type do_negative_sign() const {return __negative_sign_;}
2878 virtual int do_frac_digits() const {return __frac_digits_;}
2879 virtual pattern do_pos_format() const {return __pos_format_;}
2880 virtual pattern do_neg_format() const {return __neg_format_;}
2881
2882private:
2883 char_type __decimal_point_;
2884 char_type __thousands_sep_;
2885 string __grouping_;
2886 string_type __curr_symbol_;
2887 string_type __positive_sign_;
2888 string_type __negative_sign_;
2889 int __frac_digits_;
2890 pattern __pos_format_;
2891 pattern __neg_format_;
2892
2893 void init(const char*);
2894};
2895
2896template<> void moneypunct_byname<char, false>::init(const char*);
2897template<> void moneypunct_byname<char, true>::init(const char*);
2898template<> void moneypunct_byname<wchar_t, false>::init(const char*);
2899template<> void moneypunct_byname<wchar_t, true>::init(const char*);
2900
2901extern template class moneypunct_byname<char, false>;
2902extern template class moneypunct_byname<char, true>;
2903extern template class moneypunct_byname<wchar_t, false>;
2904extern template class moneypunct_byname<wchar_t, true>;
2905
2906// money_get
2907
2908template <class _CharT>
2909class __money_get
2910{
2911protected:
2912 typedef _CharT char_type;
2913 typedef basic_string<char_type> string_type;
2914
2915 _LIBCPP_ALWAYS_INLINE __money_get() {}
2916
2917 static void __gather_info(bool __intl, const locale& __loc,
2918 money_base::pattern& __pat, char_type& __dp,
2919 char_type& __ts, string& __grp,
2920 string_type& __sym, string_type& __psn,
2921 string_type& __nsn, int& __fd);
2922};
2923
2924template <class _CharT>
2925void
2926__money_get<_CharT>::__gather_info(bool __intl, const locale& __loc,
2927 money_base::pattern& __pat, char_type& __dp,
2928 char_type& __ts, string& __grp,
2929 string_type& __sym, string_type& __psn,
2930 string_type& __nsn, int& __fd)
2931{
2932 if (__intl)
2933 {
2934 const moneypunct<char_type, true>& __mp =
2935 use_facet<moneypunct<char_type, true> >(__loc);
2936 __pat = __mp.neg_format();
2937 __nsn = __mp.negative_sign();
2938 __psn = __mp.positive_sign();
2939 __dp = __mp.decimal_point();
2940 __ts = __mp.thousands_sep();
2941 __grp = __mp.grouping();
2942 __sym = __mp.curr_symbol();
2943 __fd = __mp.frac_digits();
2944 }
2945 else
2946 {
2947 const moneypunct<char_type, false>& __mp =
2948 use_facet<moneypunct<char_type, false> >(__loc);
2949 __pat = __mp.neg_format();
2950 __nsn = __mp.negative_sign();
2951 __psn = __mp.positive_sign();
2952 __dp = __mp.decimal_point();
2953 __ts = __mp.thousands_sep();
2954 __grp = __mp.grouping();
2955 __sym = __mp.curr_symbol();
2956 __fd = __mp.frac_digits();
2957 }
2958}
2959
2960extern template class __money_get<char>;
2961extern template class __money_get<wchar_t>;
2962
2963template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00002964class _LIBCPP_VISIBLE money_get
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002965 : public locale::facet,
2966 private __money_get<_CharT>
2967{
2968public:
2969 typedef _CharT char_type;
2970 typedef _InputIterator iter_type;
2971 typedef basic_string<char_type> string_type;
2972
2973 _LIBCPP_ALWAYS_INLINE
2974 explicit money_get(size_t __refs = 0)
2975 : locale::facet(__refs) {}
2976
2977 _LIBCPP_ALWAYS_INLINE
2978 iter_type get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob,
2979 ios_base::iostate& __err, long double& __v) const
2980 {
2981 return do_get(__b, __e, __intl, __iob, __err, __v);
2982 }
2983
2984 _LIBCPP_ALWAYS_INLINE
2985 iter_type get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob,
2986 ios_base::iostate& __err, string_type& __v) const
2987 {
2988 return do_get(__b, __e, __intl, __iob, __err, __v);
2989 }
2990
2991 static locale::id id;
2992
2993protected:
2994
Howard Hinnant82894812010-09-22 16:48:34 +00002995 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002996 ~money_get() {}
Howard Hinnant324bb032010-08-22 00:02:43 +00002997
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002998 virtual iter_type do_get(iter_type __b, iter_type __e, bool __intl,
2999 ios_base& __iob, ios_base::iostate& __err,
3000 long double& __v) const;
3001 virtual iter_type do_get(iter_type __b, iter_type __e, bool __intl,
3002 ios_base& __iob, ios_base::iostate& __err,
3003 string_type& __v) const;
3004
3005private:
3006 static bool __do_get(iter_type& __b, iter_type __e,
3007 bool __intl, const locale& __loc,
3008 ios_base::fmtflags __flags, ios_base::iostate& __err,
3009 bool& __neg, const ctype<char_type>& __ct,
3010 unique_ptr<char_type, void(*)(void*)>& __wb,
3011 char_type*& __wn, char_type* __we);
3012};
3013
3014template <class _CharT, class _InputIterator>
3015locale::id
3016money_get<_CharT, _InputIterator>::id;
3017
3018void __do_nothing(void*);
3019
3020template <class _Tp>
3021_LIBCPP_HIDDEN
3022void
3023__double_or_nothing(unique_ptr<_Tp, void(*)(void*)>& __b, _Tp*& __n, _Tp*& __e)
3024{
3025 bool __owns = __b.get_deleter() != __do_nothing;
3026 size_t __cur_cap = (__e-__b.get()) * sizeof(_Tp);
3027 size_t __new_cap = __cur_cap < numeric_limits<size_t>::max() / 2 ?
3028 2 * __cur_cap : numeric_limits<size_t>::max();
3029 size_t __n_off = __n - __b.get();
3030 _Tp* __t = (_Tp*)realloc(__owns ? __b.get() : 0, __new_cap);
3031 if (__t == 0)
3032 __throw_bad_alloc();
3033 if (__owns)
3034 __b.release();
3035 __b = unique_ptr<_Tp, void(*)(void*)>(__t, free);
3036 __new_cap /= sizeof(_Tp);
3037 __n = __b.get() + __n_off;
3038 __e = __b.get() + __new_cap;
3039}
3040
3041// true == success
3042template <class _CharT, class _InputIterator>
3043bool
3044money_get<_CharT, _InputIterator>::__do_get(iter_type& __b, iter_type __e,
3045 bool __intl, const locale& __loc,
3046 ios_base::fmtflags __flags,
3047 ios_base::iostate& __err,
3048 bool& __neg,
3049 const ctype<char_type>& __ct,
3050 unique_ptr<char_type, void(*)(void*)>& __wb,
3051 char_type*& __wn, char_type* __we)
3052{
3053 const unsigned __bz = 100;
3054 unsigned __gbuf[__bz];
3055 unique_ptr<unsigned, void(*)(void*)> __gb(__gbuf, __do_nothing);
3056 unsigned* __gn = __gb.get();
3057 unsigned* __ge = __gn + __bz;
3058 money_base::pattern __pat;
3059 char_type __dp;
3060 char_type __ts;
3061 string __grp;
3062 string_type __sym;
3063 string_type __psn;
3064 string_type __nsn;
3065 int __fd;
3066 __money_get<_CharT>::__gather_info(__intl, __loc, __pat, __dp, __ts, __grp,
3067 __sym, __psn, __nsn, __fd);
3068 const string_type* __trailing_sign = 0;
3069 __wn = __wb.get();
3070 for (unsigned __p = 0; __p < 4 && __b != __e; ++__p)
3071 {
3072 switch (__pat.field[__p])
3073 {
3074 case money_base::space:
3075 if (__p != 3)
3076 {
3077 if (__ct.is(ctype_base::space, *__b))
3078 ++__b;
3079 else
3080 {
3081 __err |= ios_base::failbit;
3082 return false;
3083 }
3084 }
Howard Hinnant324bb032010-08-22 00:02:43 +00003085 // drop through
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003086 case money_base::none:
3087 if (__p != 3)
3088 {
3089 while (__b != __e && __ct.is(ctype_base::space, *__b))
3090 ++__b;
3091 }
3092 break;
3093 case money_base::sign:
3094 if (__psn.size() + __nsn.size() > 0)
3095 {
3096 if (__psn.size() == 0 || __nsn.size() == 0)
3097 { // sign is optional
3098 if (__psn.size() > 0)
3099 { // __nsn.size() == 0
3100 if (*__b == __psn[0])
3101 {
3102 ++__b;
3103 if (__psn.size() > 1)
3104 __trailing_sign = &__psn;
3105 }
3106 else
3107 __neg = true;
3108 }
3109 else if (*__b == __nsn[0]) // __nsn.size() > 0 && __psn.size() == 0
3110 {
3111 ++__b;
3112 __neg = true;
3113 if (__nsn.size() > 1)
3114 __trailing_sign = &__nsn;
3115 }
3116 }
3117 else // sign is required
3118 {
3119 if (*__b == __psn[0])
3120 {
3121 ++__b;
3122 if (__psn.size() > 1)
3123 __trailing_sign = &__psn;
3124 }
3125 else if (*__b == __nsn[0])
3126 {
3127 ++__b;
3128 __neg = true;
3129 if (__nsn.size() > 1)
3130 __trailing_sign = &__nsn;
3131 }
3132 else
3133 {
3134 __err |= ios_base::failbit;
3135 return false;
3136 }
3137 }
3138 }
3139 break;
3140 case money_base::symbol:
3141 {
3142 bool __more_needed = __trailing_sign ||
3143 (__p < 2) ||
3144 (__p == 2 && __pat.field[3] != static_cast<char>(money_base::none));
3145 bool __sb = __flags & ios_base::showbase;
3146 if (__sb || __more_needed)
3147 {
3148 ios_base::iostate __et = ios_base::goodbit;
3149 string_type* __k = __scan_keyword(__b, __e, &__sym, &__sym+1,
3150 __ct, __et);
3151 if (__sb && __k != &__sym)
3152 {
3153 __err |= ios_base::failbit;
3154 return false;
3155 }
3156 }
3157 }
3158 break;
3159 case money_base::value:
3160 {
3161 unsigned __ng = 0;
3162 for (; __b != __e; ++__b)
3163 {
3164 char_type __c = *__b;
3165 if (__ct.is(ctype_base::digit, __c))
3166 {
3167 if (__wn == __we)
3168 __double_or_nothing(__wb, __wn, __we);
3169 *__wn++ = __c;
3170 ++__ng;
3171 }
3172 else if (__grp.size() > 0 && __ng > 0 && __c == __ts)
3173 {
3174 if (__gn == __ge)
3175 __double_or_nothing(__gb, __gn, __ge);
3176 *__gn++ = __ng;
3177 __ng = 0;
3178 }
3179 else
3180 break;
3181 }
3182 if (__gb.get() != __gn && __ng > 0)
3183 {
3184 if (__gn == __ge)
3185 __double_or_nothing(__gb, __gn, __ge);
3186 *__gn++ = __ng;
3187 }
3188 if (__fd > 0)
3189 {
3190 if (__b == __e || *__b != __dp)
3191 {
3192 __err |= ios_base::failbit;
3193 return false;
3194 }
3195 for (++__b; __fd > 0; --__fd, ++__b)
3196 {
3197 if (__b == __e || !__ct.is(ctype_base::digit, *__b))
3198 {
3199 __err |= ios_base::failbit;
3200 return false;
3201 }
3202 if (__wn == __we)
3203 __double_or_nothing(__wb, __wn, __we);
3204 *__wn++ = *__b;
3205 }
3206 }
3207 if (__wn == __wb.get())
3208 {
3209 __err |= ios_base::failbit;
3210 return false;
3211 }
3212 }
3213 break;
3214 }
3215 }
3216 if (__trailing_sign)
3217 {
3218 for (unsigned __i = 1; __i < __trailing_sign->size(); ++__i, ++__b)
3219 {
3220 if (__b == __e || *__b != (*__trailing_sign)[__i])
3221 {
3222 __err |= ios_base::failbit;
3223 return false;
3224 }
3225 }
3226 }
3227 if (__gb.get() != __gn)
3228 {
3229 ios_base::iostate __et = ios_base::goodbit;
3230 __check_grouping(__grp, __gb.get(), __gn, __et);
3231 if (__et)
3232 {
3233 __err |= ios_base::failbit;
3234 return false;
3235 }
3236 }
3237 return true;
3238}
3239
3240template <class _CharT, class _InputIterator>
3241_InputIterator
3242money_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
3243 bool __intl, ios_base& __iob,
3244 ios_base::iostate& __err,
3245 long double& __v) const
3246{
3247 const unsigned __bz = 100;
3248 char_type __wbuf[__bz];
3249 unique_ptr<char_type, void(*)(void*)> __wb(__wbuf, __do_nothing);
3250 char_type* __wn;
3251 char_type* __we = __wbuf + __bz;
3252 locale __loc = __iob.getloc();
3253 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3254 bool __neg = false;
3255 if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct,
3256 __wb, __wn, __we))
3257 {
3258 const char __src[] = "0123456789";
3259 char_type __atoms[sizeof(__src)-1];
3260 __ct.widen(__src, __src + (sizeof(__src)-1), __atoms);
3261 char __nbuf[__bz];
3262 char* __nc = __nbuf;
3263 unique_ptr<char, void(*)(void*)> __h(0, free);
3264 if (__wn - __wb.get() > __bz-2)
3265 {
3266 __h.reset((char*)malloc(__wn - __wb.get() + 2));
3267 if (__h.get() == 0)
3268 __throw_bad_alloc();
3269 __nc = __h.get();
3270 }
3271 if (__neg)
3272 *__nc++ = '-';
3273 for (const char_type* __w = __wb.get(); __w < __wn; ++__w, ++__nc)
3274 *__nc = __src[find(__atoms, __atoms+sizeof(__atoms), *__w) - __atoms];
3275 *__nc = char();
3276 if (sscanf(__nbuf, "%Lf", &__v) != 1)
3277 __throw_runtime_error("money_get error");
3278 }
3279 if (__b == __e)
3280 __err |= ios_base::eofbit;
3281 return __b;
3282}
3283
3284template <class _CharT, class _InputIterator>
3285_InputIterator
3286money_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
3287 bool __intl, ios_base& __iob,
3288 ios_base::iostate& __err,
3289 string_type& __v) const
3290{
3291 const unsigned __bz = 100;
3292 char_type __wbuf[__bz];
3293 unique_ptr<char_type, void(*)(void*)> __wb(__wbuf, __do_nothing);
3294 char_type* __wn;
3295 char_type* __we = __wbuf + __bz;
3296 locale __loc = __iob.getloc();
3297 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3298 bool __neg = false;
3299 if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct,
3300 __wb, __wn, __we))
3301 {
3302 __v.clear();
3303 if (__neg)
3304 __v.push_back(__ct.widen('-'));
3305 char_type __z = __ct.widen('0');
3306 char_type* __w;
3307 for (__w = __wb.get(); __w < __wn-1; ++__w)
3308 if (*__w != __z)
3309 break;
3310 __v.append(__w, __wn);
3311 }
3312 if (__b == __e)
3313 __err |= ios_base::eofbit;
3314 return __b;
3315}
3316
3317extern template class money_get<char>;
3318extern template class money_get<wchar_t>;
3319
3320// money_put
3321
3322template <class _CharT>
3323class __money_put
3324{
3325protected:
3326 typedef _CharT char_type;
3327 typedef basic_string<char_type> string_type;
3328
3329 _LIBCPP_ALWAYS_INLINE __money_put() {}
3330
3331 static void __gather_info(bool __intl, bool __neg, const locale& __loc,
3332 money_base::pattern& __pat, char_type& __dp,
3333 char_type& __ts, string& __grp,
3334 string_type& __sym, string_type& __sn,
3335 int& __fd);
3336 static void __format(char_type* __mb, char_type*& __mi, char_type*& __me,
3337 ios_base::fmtflags __flags,
3338 const char_type* __db, const char_type* __de,
3339 const ctype<char_type>& __ct, bool __neg,
3340 const money_base::pattern& __pat, char_type __dp,
3341 char_type __ts, const string& __grp,
3342 const string_type& __sym, const string_type& __sn,
3343 int __fd);
3344};
3345
3346template <class _CharT>
3347void
3348__money_put<_CharT>::__gather_info(bool __intl, bool __neg, const locale& __loc,
3349 money_base::pattern& __pat, char_type& __dp,
3350 char_type& __ts, string& __grp,
3351 string_type& __sym, string_type& __sn,
3352 int& __fd)
3353{
3354 if (__intl)
3355 {
3356 const moneypunct<char_type, true>& __mp =
3357 use_facet<moneypunct<char_type, true> >(__loc);
3358 if (__neg)
3359 {
3360 __pat = __mp.neg_format();
3361 __sn = __mp.negative_sign();
3362 }
3363 else
3364 {
3365 __pat = __mp.pos_format();
3366 __sn = __mp.positive_sign();
3367 }
3368 __dp = __mp.decimal_point();
3369 __ts = __mp.thousands_sep();
3370 __grp = __mp.grouping();
3371 __sym = __mp.curr_symbol();
3372 __fd = __mp.frac_digits();
3373 }
3374 else
3375 {
3376 const moneypunct<char_type, false>& __mp =
3377 use_facet<moneypunct<char_type, false> >(__loc);
3378 if (__neg)
3379 {
3380 __pat = __mp.neg_format();
3381 __sn = __mp.negative_sign();
3382 }
3383 else
3384 {
3385 __pat = __mp.pos_format();
3386 __sn = __mp.positive_sign();
3387 }
3388 __dp = __mp.decimal_point();
3389 __ts = __mp.thousands_sep();
3390 __grp = __mp.grouping();
3391 __sym = __mp.curr_symbol();
3392 __fd = __mp.frac_digits();
3393 }
3394}
3395
3396template <class _CharT>
3397void
3398__money_put<_CharT>::__format(char_type* __mb, char_type*& __mi, char_type*& __me,
3399 ios_base::fmtflags __flags,
3400 const char_type* __db, const char_type* __de,
3401 const ctype<char_type>& __ct, bool __neg,
3402 const money_base::pattern& __pat, char_type __dp,
3403 char_type __ts, const string& __grp,
3404 const string_type& __sym, const string_type& __sn,
3405 int __fd)
3406{
3407 __me = __mb;
3408 for (unsigned __p = 0; __p < 4; ++__p)
3409 {
3410 switch (__pat.field[__p])
3411 {
3412 case money_base::none:
3413 __mi = __me;
3414 break;
3415 case money_base::space:
3416 __mi = __me;
3417 *__me++ = __ct.widen(' ');
3418 break;
3419 case money_base::sign:
3420 if (!__sn.empty())
3421 *__me++ = __sn[0];
3422 break;
3423 case money_base::symbol:
3424 if (!__sym.empty() && (__flags & ios_base::showbase))
Howard Hinnant0949eed2011-06-30 21:18:19 +00003425 __me = _VSTD::copy(__sym.begin(), __sym.end(), __me);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003426 break;
3427 case money_base::value:
3428 {
3429 // remember start of value so we can reverse it
3430 char_type* __t = __me;
3431 // find beginning of digits
3432 if (__neg)
3433 ++__db;
3434 // find end of digits
3435 const char_type* __d;
3436 for (__d = __db; __d < __de; ++__d)
3437 if (!__ct.is(ctype_base::digit, *__d))
3438 break;
3439 // print fractional part
3440 if (__fd > 0)
3441 {
3442 int __f;
3443 for (__f = __fd; __d > __db && __f > 0; --__f)
3444 *__me++ = *--__d;
3445 char_type __z = __f > 0 ? __ct.widen('0') : char_type();
3446 for (; __f > 0; --__f)
3447 *__me++ = __z;
3448 *__me++ = __dp;
3449 }
3450 // print units part
3451 if (__d == __db)
3452 {
3453 *__me++ = __ct.widen('0');
3454 }
3455 else
3456 {
3457 unsigned __ng = 0;
3458 unsigned __ig = 0;
3459 unsigned __gl = __grp.empty() ? numeric_limits<unsigned>::max()
3460 : static_cast<unsigned>(__grp[__ig]);
3461 while (__d != __db)
3462 {
3463 if (__ng == __gl)
3464 {
3465 *__me++ = __ts;
3466 __ng = 0;
3467 if (++__ig < __grp.size())
3468 __gl = __grp[__ig] == numeric_limits<char>::max() ?
3469 numeric_limits<unsigned>::max() :
3470 static_cast<unsigned>(__grp[__ig]);
3471 }
3472 *__me++ = *--__d;
3473 ++__ng;
3474 }
3475 }
3476 // reverse it
3477 reverse(__t, __me);
3478 }
3479 break;
3480 }
3481 }
3482 // print rest of sign, if any
3483 if (__sn.size() > 1)
Howard Hinnant0949eed2011-06-30 21:18:19 +00003484 __me = _VSTD::copy(__sn.begin()+1, __sn.end(), __me);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003485 // set alignment
3486 if ((__flags & ios_base::adjustfield) == ios_base::left)
3487 __mi = __me;
3488 else if ((__flags & ios_base::adjustfield) != ios_base::internal)
3489 __mi = __mb;
3490}
3491
3492extern template class __money_put<char>;
3493extern template class __money_put<wchar_t>;
3494
3495template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00003496class _LIBCPP_VISIBLE money_put
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003497 : public locale::facet,
3498 private __money_put<_CharT>
3499{
3500public:
3501 typedef _CharT char_type;
3502 typedef _OutputIterator iter_type;
3503 typedef basic_string<char_type> string_type;
3504
3505 _LIBCPP_ALWAYS_INLINE
3506 explicit money_put(size_t __refs = 0)
3507 : locale::facet(__refs) {}
3508
3509 _LIBCPP_ALWAYS_INLINE
3510 iter_type put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl,
3511 long double __units) const
3512 {
3513 return do_put(__s, __intl, __iob, __fl, __units);
3514 }
3515
3516 _LIBCPP_ALWAYS_INLINE
3517 iter_type put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl,
3518 const string_type& __digits) const
3519 {
3520 return do_put(__s, __intl, __iob, __fl, __digits);
3521 }
3522
3523 static locale::id id;
3524
3525protected:
Howard Hinnant82894812010-09-22 16:48:34 +00003526 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003527 ~money_put() {}
3528
3529 virtual iter_type do_put(iter_type __s, bool __intl, ios_base& __iob,
3530 char_type __fl, long double __units) const;
3531 virtual iter_type do_put(iter_type __s, bool __intl, ios_base& __iob,
3532 char_type __fl, const string_type& __digits) const;
3533};
3534
3535template <class _CharT, class _OutputIterator>
3536locale::id
3537money_put<_CharT, _OutputIterator>::id;
3538
3539template <class _CharT, class _OutputIterator>
3540_OutputIterator
3541money_put<_CharT, _OutputIterator>::do_put(iter_type __s, bool __intl,
3542 ios_base& __iob, char_type __fl,
3543 long double __units) const
3544{
3545 // convert to char
3546 const size_t __bs = 100;
3547 char __buf[__bs];
3548 char* __bb = __buf;
3549 char_type __digits[__bs];
3550 char_type* __db = __digits;
3551 size_t __n = snprintf(__bb, __bs, "%.0Lf", __units);
3552 unique_ptr<char, void(*)(void*)> __hn(0, free);
3553 unique_ptr<char_type, void(*)(void*)> __hd(0, free);
3554 // secure memory for digit storage
3555 if (__n > __bs-1)
3556 {
Sean Huntf3907e62011-07-15 05:40:33 +00003557#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantbcbbd4d2011-07-15 14:46:11 +00003558 __n = asprintf_l(&__bb, 0, "%.0Lf", __units);
Sean Huntf3907e62011-07-15 05:40:33 +00003559#else
3560 __n = __asprintf_l(&__bb, __cloc(), "%.0Lf", __units);
3561#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003562 if (__bb == 0)
3563 __throw_bad_alloc();
3564 __hn.reset(__bb);
3565 __hd.reset((char_type*)malloc(__n * sizeof(char_type)));
3566 if (__hd == 0)
3567 __throw_bad_alloc();
3568 __db = __hd.get();
3569 }
3570 // gather info
3571 locale __loc = __iob.getloc();
3572 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3573 __ct.widen(__bb, __bb + __n, __db);
3574 bool __neg = __n > 0 && __bb[0] == '-';
3575 money_base::pattern __pat;
3576 char_type __dp;
3577 char_type __ts;
3578 string __grp;
3579 string_type __sym;
3580 string_type __sn;
3581 int __fd;
3582 this->__gather_info(__intl, __neg, __loc, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3583 // secure memory for formatting
3584 char_type __mbuf[__bs];
3585 char_type* __mb = __mbuf;
3586 unique_ptr<char_type, void(*)(void*)> __hw(0, free);
3587 size_t __exn = static_cast<int>(__n) > __fd ?
3588 (__n - __fd) * 2 + __sn.size() + __sym.size() + __fd + 1
3589 : __sn.size() + __sym.size() + __fd + 2;
3590 if (__exn > __bs)
3591 {
3592 __hw.reset((char_type*)malloc(__exn * sizeof(char_type)));
3593 __mb = __hw.get();
3594 if (__mb == 0)
3595 __throw_bad_alloc();
3596 }
3597 // format
3598 char_type* __mi;
3599 char_type* __me;
3600 this->__format(__mb, __mi, __me, __iob.flags(),
3601 __db, __db + __n, __ct,
3602 __neg, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3603 return __pad_and_output(__s, __mb, __mi, __me, __iob, __fl);
3604}
3605
3606template <class _CharT, class _OutputIterator>
3607_OutputIterator
3608money_put<_CharT, _OutputIterator>::do_put(iter_type __s, bool __intl,
3609 ios_base& __iob, char_type __fl,
3610 const string_type& __digits) const
3611{
3612 // gather info
3613 locale __loc = __iob.getloc();
3614 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3615 bool __neg = __digits.size() > 0 && __digits[0] == __ct.widen('-');
3616 money_base::pattern __pat;
3617 char_type __dp;
3618 char_type __ts;
3619 string __grp;
3620 string_type __sym;
3621 string_type __sn;
3622 int __fd;
3623 this->__gather_info(__intl, __neg, __loc, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3624 // secure memory for formatting
3625 char_type __mbuf[100];
3626 char_type* __mb = __mbuf;
3627 unique_ptr<char_type, void(*)(void*)> __h(0, free);
3628 size_t __exn = __digits.size() > __fd ?
3629 (__digits.size() - __fd) * 2 + __sn.size() + __sym.size() + __fd + 1
3630 : __sn.size() + __sym.size() + __fd + 2;
3631 if (__exn > 100)
3632 {
3633 __h.reset((char_type*)malloc(__exn * sizeof(char_type)));
3634 __mb = __h.get();
3635 if (__mb == 0)
3636 __throw_bad_alloc();
3637 }
3638 // format
3639 char_type* __mi;
3640 char_type* __me;
3641 this->__format(__mb, __mi, __me, __iob.flags(),
3642 __digits.data(), __digits.data() + __digits.size(), __ct,
3643 __neg, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3644 return __pad_and_output(__s, __mb, __mi, __me, __iob, __fl);
3645}
3646
3647extern template class money_put<char>;
3648extern template class money_put<wchar_t>;
3649
3650// messages
3651
Howard Hinnant82894812010-09-22 16:48:34 +00003652class _LIBCPP_VISIBLE messages_base
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003653{
3654public:
Howard Hinnantb2080c72011-02-25 00:51:08 +00003655 typedef ptrdiff_t catalog;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003656
3657 _LIBCPP_ALWAYS_INLINE messages_base() {}
3658};
3659
3660template <class _CharT>
Howard Hinnant82894812010-09-22 16:48:34 +00003661class _LIBCPP_VISIBLE messages
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003662 : public locale::facet,
3663 public messages_base
3664{
3665public:
3666 typedef _CharT char_type;
3667 typedef basic_string<_CharT> string_type;
3668
3669 _LIBCPP_ALWAYS_INLINE
3670 explicit messages(size_t __refs = 0)
3671 : locale::facet(__refs) {}
3672
3673 _LIBCPP_ALWAYS_INLINE
3674 catalog open(const basic_string<char>& __nm, const locale& __loc) const
3675 {
3676 return do_open(__nm, __loc);
3677 }
3678
3679 _LIBCPP_ALWAYS_INLINE
3680 string_type get(catalog __c, int __set, int __msgid,
3681 const string_type& __dflt) const
3682 {
3683 return do_get(__c, __set, __msgid, __dflt);
3684 }
3685
3686 _LIBCPP_ALWAYS_INLINE
3687 void close(catalog __c) const
3688 {
3689 do_close(__c);
3690 }
3691
3692 static locale::id id;
3693
3694protected:
Howard Hinnant82894812010-09-22 16:48:34 +00003695 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003696 ~messages() {}
3697
3698 virtual catalog do_open(const basic_string<char>&, const locale&) const;
3699 virtual string_type do_get(catalog, int __set, int __msgid,
3700 const string_type& __dflt) const;
3701 virtual void do_close(catalog) const;
3702};
3703
3704template <class _CharT>
3705locale::id
3706messages<_CharT>::id;
3707
3708template <class _CharT>
3709typename messages<_CharT>::catalog
3710messages<_CharT>::do_open(const basic_string<char>& __nm, const locale&) const
3711{
Howard Hinnantb2080c72011-02-25 00:51:08 +00003712 catalog __cat = reinterpret_cast<catalog>(catopen(__nm.c_str(), NL_CAT_LOCALE));
3713 if (__cat != -1)
3714 __cat = static_cast<catalog>((static_cast<size_t>(__cat) >> 1));
3715 return __cat;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003716}
3717
3718template <class _CharT>
3719typename messages<_CharT>::string_type
3720messages<_CharT>::do_get(catalog __c, int __set, int __msgid,
3721 const string_type& __dflt) const
3722{
3723 string __ndflt;
3724 __narrow_to_utf8<sizeof(char_type)*__CHAR_BIT__>()(back_inserter(__ndflt),
3725 __dflt.c_str(),
3726 __dflt.c_str() + __dflt.size());
Howard Hinnantb2080c72011-02-25 00:51:08 +00003727 if (__c != -1)
3728 __c <<= 1;
3729 nl_catd __cat = reinterpret_cast<nl_catd>(__c);
3730 char* __n = catgets(__cat, __set, __msgid, __ndflt.c_str());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003731 string_type __w;
3732 __widen_from_utf8<sizeof(char_type)*__CHAR_BIT__>()(back_inserter(__w),
3733 __n, __n + strlen(__n));
3734 return __w;
3735}
3736
3737template <class _CharT>
3738void
3739messages<_CharT>::do_close(catalog __c) const
3740{
Howard Hinnantb2080c72011-02-25 00:51:08 +00003741 if (__c != -1)
3742 __c <<= 1;
3743 nl_catd __cat = reinterpret_cast<nl_catd>(__c);
3744 catclose(__cat);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003745}
3746
3747extern template class messages<char>;
3748extern template class messages<wchar_t>;
3749
3750template <class _CharT>
Howard Hinnant82894812010-09-22 16:48:34 +00003751class _LIBCPP_VISIBLE messages_byname
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003752 : public messages<_CharT>
3753{
3754public:
3755 typedef messages_base::catalog catalog;
3756 typedef basic_string<_CharT> string_type;
3757
3758 _LIBCPP_ALWAYS_INLINE
3759 explicit messages_byname(const char*, size_t __refs = 0)
3760 : messages<_CharT>(__refs) {}
3761
3762 _LIBCPP_ALWAYS_INLINE
3763 explicit messages_byname(const string&, size_t __refs = 0)
3764 : messages<_CharT>(__refs) {}
3765
3766protected:
Howard Hinnant82894812010-09-22 16:48:34 +00003767 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003768 ~messages_byname() {}
3769};
3770
3771extern template class messages_byname<char>;
3772extern template class messages_byname<wchar_t>;
3773
Howard Hinnantd23b4642010-05-31 20:58:54 +00003774template<class _Codecvt, class _Elem = wchar_t,
3775 class _Wide_alloc = allocator<_Elem>,
3776 class _Byte_alloc = allocator<char> >
Howard Hinnant82894812010-09-22 16:48:34 +00003777class _LIBCPP_VISIBLE wstring_convert
Howard Hinnantd23b4642010-05-31 20:58:54 +00003778{
3779public:
3780 typedef basic_string<char, char_traits<char>, _Byte_alloc> byte_string;
3781 typedef basic_string<_Elem, char_traits<_Elem>, _Wide_alloc> wide_string;
3782 typedef typename _Codecvt::state_type state_type;
3783 typedef typename wide_string::traits_type::int_type int_type;
3784
3785private:
3786 byte_string __byte_err_string_;
3787 wide_string __wide_err_string_;
3788 _Codecvt* __cvtptr_;
3789 state_type __cvtstate_;
3790 size_t __cvtcount_;
3791
3792 wstring_convert(const wstring_convert& __wc);
3793 wstring_convert& operator=(const wstring_convert& __wc);
3794public:
3795 wstring_convert(_Codecvt* __pcvt = new _Codecvt);
3796 wstring_convert(_Codecvt* __pcvt, state_type __state);
3797 wstring_convert(const byte_string& __byte_err,
3798 const wide_string& __wide_err = wide_string());
Howard Hinnant73d21a42010-09-04 23:28:19 +00003799#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantd23b4642010-05-31 20:58:54 +00003800 wstring_convert(wstring_convert&& __wc);
3801#endif
3802 ~wstring_convert();
3803
Howard Hinnant82894812010-09-22 16:48:34 +00003804 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003805 wide_string from_bytes(char __byte)
3806 {return from_bytes(&__byte, &__byte+1);}
Howard Hinnant82894812010-09-22 16:48:34 +00003807 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003808 wide_string from_bytes(const char* __ptr)
3809 {return from_bytes(__ptr, __ptr + char_traits<char>::length(__ptr));}
Howard Hinnant82894812010-09-22 16:48:34 +00003810 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003811 wide_string from_bytes(const byte_string& __str)
3812 {return from_bytes(__str.data(), __str.data() + __str.size());}
3813 wide_string from_bytes(const char* __first, const char* __last);
3814
Howard Hinnant82894812010-09-22 16:48:34 +00003815 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003816 byte_string to_bytes(_Elem __wchar)
3817 {return to_bytes(&__wchar, &__wchar+1);}
Howard Hinnant82894812010-09-22 16:48:34 +00003818 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003819 byte_string to_bytes(const _Elem* __wptr)
3820 {return to_bytes(__wptr, __wptr + char_traits<_Elem>::length(__wptr));}
Howard Hinnant82894812010-09-22 16:48:34 +00003821 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003822 byte_string to_bytes(const wide_string& __wstr)
3823 {return to_bytes(__wstr.data(), __wstr.data() + __wstr.size());}
3824 byte_string to_bytes(const _Elem* __first, const _Elem* __last);
3825
Howard Hinnant82894812010-09-22 16:48:34 +00003826 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003827 size_t converted() const {return __cvtcount_;}
Howard Hinnant82894812010-09-22 16:48:34 +00003828 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003829 state_type state() const {return __cvtstate_;}
3830};
3831
3832template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Howard Hinnant82894812010-09-22 16:48:34 +00003833inline _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003834wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3835 wstring_convert(_Codecvt* __pcvt)
3836 : __cvtptr_(__pcvt), __cvtstate_(), __cvtcount_(0)
3837{
3838}
3839
3840template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Howard Hinnant82894812010-09-22 16:48:34 +00003841inline _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003842wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3843 wstring_convert(_Codecvt* __pcvt, state_type __state)
3844 : __cvtptr_(__pcvt), __cvtstate_(__state), __cvtcount_(0)
3845{
3846}
3847
3848template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3849wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3850 wstring_convert(const byte_string& __byte_err, const wide_string& __wide_err)
3851 : __byte_err_string_(__byte_err), __wide_err_string_(__wide_err),
3852 __cvtstate_(), __cvtcount_(0)
3853{
3854 __cvtptr_ = new _Codecvt;
3855}
3856
Howard Hinnant73d21a42010-09-04 23:28:19 +00003857#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantd23b4642010-05-31 20:58:54 +00003858
3859template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Howard Hinnant82894812010-09-22 16:48:34 +00003860inline _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003861wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3862 wstring_convert(wstring_convert&& __wc)
Howard Hinnant0949eed2011-06-30 21:18:19 +00003863 : __byte_err_string_(_VSTD::move(__wc.__byte_err_string_)),
3864 __wide_err_string_(_VSTD::move(__wc.__wide_err_string_)),
Howard Hinnantd23b4642010-05-31 20:58:54 +00003865 __cvtptr_(__wc.__cvtptr_),
3866 __cvtstate_(__wc.__cvtstate_), __cvtcount_(__wc.__cvtstate_)
3867{
3868 __wc.__cvtptr_ = nullptr;
3869}
3870
Howard Hinnantbfd55302010-09-04 23:46:48 +00003871#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantd23b4642010-05-31 20:58:54 +00003872
3873template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3874wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::~wstring_convert()
3875{
3876 delete __cvtptr_;
3877}
3878
3879template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3880typename wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::wide_string
3881wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3882 from_bytes(const char* __frm, const char* __frm_end)
3883{
3884 __cvtcount_ = 0;
3885 if (__cvtptr_ != nullptr)
3886 {
3887 wide_string __ws(2*(__frm_end - __frm), _Elem());
3888 __ws.resize(__ws.capacity());
3889 codecvt_base::result __r = codecvt_base::ok;
3890 state_type __st = __cvtstate_;
3891 if (__frm != __frm_end)
3892 {
3893 _Elem* __to = &__ws[0];
3894 _Elem* __to_end = __to + __ws.size();
3895 const char* __frm_nxt;
3896 do
3897 {
3898 _Elem* __to_nxt;
3899 __r = __cvtptr_->in(__st, __frm, __frm_end, __frm_nxt,
3900 __to, __to_end, __to_nxt);
3901 __cvtcount_ += __frm_nxt - __frm;
3902 if (__frm_nxt == __frm)
3903 {
3904 __r = codecvt_base::error;
3905 }
3906 else if (__r == codecvt_base::noconv)
3907 {
3908 __ws.resize(__to - &__ws[0]);
3909 // This only gets executed if _Elem is char
3910 __ws.append((const _Elem*)__frm, (const _Elem*)__frm_end);
3911 __frm = __frm_nxt;
3912 __r = codecvt_base::ok;
3913 }
3914 else if (__r == codecvt_base::ok)
3915 {
3916 __ws.resize(__to_nxt - &__ws[0]);
3917 __frm = __frm_nxt;
3918 }
3919 else if (__r == codecvt_base::partial)
3920 {
3921 ptrdiff_t __s = __to_nxt - &__ws[0];
3922 __ws.resize(2 * __s);
3923 __to = &__ws[0] + __s;
3924 __to_end = &__ws[0] + __ws.size();
3925 __frm = __frm_nxt;
3926 }
3927 } while (__r == codecvt_base::partial && __frm_nxt < __frm_end);
3928 }
3929 if (__r == codecvt_base::ok)
3930 return __ws;
3931 }
Howard Hinnantd4444702010-08-11 17:04:31 +00003932#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00003933 if (__wide_err_string_.empty())
3934 throw range_error("wstring_convert: from_bytes error");
Howard Hinnant324bb032010-08-22 00:02:43 +00003935#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00003936 return __wide_err_string_;
3937}
3938
3939template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3940typename wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::byte_string
3941wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3942 to_bytes(const _Elem* __frm, const _Elem* __frm_end)
3943{
3944 __cvtcount_ = 0;
3945 if (__cvtptr_ != nullptr)
3946 {
3947 byte_string __bs(2*(__frm_end - __frm), char());
3948 __bs.resize(__bs.capacity());
3949 codecvt_base::result __r = codecvt_base::ok;
3950 state_type __st = __cvtstate_;
3951 if (__frm != __frm_end)
3952 {
3953 char* __to = &__bs[0];
3954 char* __to_end = __to + __bs.size();
3955 const _Elem* __frm_nxt;
3956 do
3957 {
3958 char* __to_nxt;
3959 __r = __cvtptr_->out(__st, __frm, __frm_end, __frm_nxt,
3960 __to, __to_end, __to_nxt);
3961 __cvtcount_ += __frm_nxt - __frm;
3962 if (__frm_nxt == __frm)
3963 {
3964 __r = codecvt_base::error;
3965 }
3966 else if (__r == codecvt_base::noconv)
3967 {
3968 __bs.resize(__to - &__bs[0]);
3969 // This only gets executed if _Elem is char
3970 __bs.append((const char*)__frm, (const char*)__frm_end);
3971 __frm = __frm_nxt;
3972 __r = codecvt_base::ok;
3973 }
3974 else if (__r == codecvt_base::ok)
3975 {
3976 __bs.resize(__to_nxt - &__bs[0]);
3977 __frm = __frm_nxt;
3978 }
3979 else if (__r == codecvt_base::partial)
3980 {
3981 ptrdiff_t __s = __to_nxt - &__bs[0];
3982 __bs.resize(2 * __s);
3983 __to = &__bs[0] + __s;
3984 __to_end = &__bs[0] + __bs.size();
3985 __frm = __frm_nxt;
3986 }
3987 } while (__r == codecvt_base::partial && __frm_nxt < __frm_end);
3988 }
3989 if (__r == codecvt_base::ok)
3990 {
3991 size_t __s = __bs.size();
3992 __bs.resize(__bs.capacity());
3993 char* __to = &__bs[0] + __s;
3994 char* __to_end = __to + __bs.size();
3995 do
3996 {
3997 char* __to_nxt;
3998 __r = __cvtptr_->unshift(__st, __to, __to_end, __to_nxt);
3999 if (__r == codecvt_base::noconv)
4000 {
4001 __bs.resize(__to - &__bs[0]);
4002 __r = codecvt_base::ok;
4003 }
4004 else if (__r == codecvt_base::ok)
4005 {
4006 __bs.resize(__to_nxt - &__bs[0]);
4007 }
4008 else if (__r == codecvt_base::partial)
4009 {
4010 ptrdiff_t __s = __to_nxt - &__bs[0];
4011 __bs.resize(2 * __s);
4012 __to = &__bs[0] + __s;
4013 __to_end = &__bs[0] + __bs.size();
4014 }
4015 } while (__r == codecvt_base::partial);
4016 if (__r == codecvt_base::ok)
4017 return __bs;
4018 }
4019 }
Howard Hinnantd4444702010-08-11 17:04:31 +00004020#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00004021 if (__byte_err_string_.empty())
4022 throw range_error("wstring_convert: to_bytes error");
Howard Hinnant324bb032010-08-22 00:02:43 +00004023#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00004024 return __byte_err_string_;
4025}
4026
4027template <class _Codecvt, class _Elem = wchar_t, class _Tr = char_traits<_Elem> >
Howard Hinnant82894812010-09-22 16:48:34 +00004028class _LIBCPP_VISIBLE wbuffer_convert
Howard Hinnantd23b4642010-05-31 20:58:54 +00004029 : public basic_streambuf<_Elem, _Tr>
4030{
4031public:
4032 // types:
4033 typedef _Elem char_type;
4034 typedef _Tr traits_type;
4035 typedef typename traits_type::int_type int_type;
4036 typedef typename traits_type::pos_type pos_type;
4037 typedef typename traits_type::off_type off_type;
4038 typedef typename _Codecvt::state_type state_type;
4039
4040private:
Howard Hinnant4b53f502010-06-01 20:09:18 +00004041 char* __extbuf_;
4042 const char* __extbufnext_;
4043 const char* __extbufend_;
4044 char __extbuf_min_[8];
4045 size_t __ebs_;
4046 char_type* __intbuf_;
4047 size_t __ibs_;
Howard Hinnantd23b4642010-05-31 20:58:54 +00004048 streambuf* __bufptr_;
Howard Hinnant4b53f502010-06-01 20:09:18 +00004049 _Codecvt* __cv_;
4050 state_type __st_;
4051 ios_base::openmode __cm_;
4052 bool __owns_eb_;
4053 bool __owns_ib_;
4054 bool __always_noconv_;
Howard Hinnantd23b4642010-05-31 20:58:54 +00004055
Howard Hinnant4b53f502010-06-01 20:09:18 +00004056 wbuffer_convert(const wbuffer_convert&);
4057 wbuffer_convert& operator=(const wbuffer_convert&);
Howard Hinnantd23b4642010-05-31 20:58:54 +00004058public:
4059 wbuffer_convert(streambuf* __bytebuf = 0, _Codecvt* __pcvt = new _Codecvt,
Howard Hinnant4b53f502010-06-01 20:09:18 +00004060 state_type __state = state_type());
4061 ~wbuffer_convert();
Howard Hinnantd23b4642010-05-31 20:58:54 +00004062
Howard Hinnant82894812010-09-22 16:48:34 +00004063 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantd23b4642010-05-31 20:58:54 +00004064 streambuf* rdbuf() const {return __bufptr_;}
Howard Hinnant82894812010-09-22 16:48:34 +00004065 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantd23b4642010-05-31 20:58:54 +00004066 streambuf* rdbuf(streambuf* __bytebuf)
4067 {
4068 streambuf* __r = __bufptr_;
4069 __bufptr_ = __bytebuf;
4070 return __r;
4071 }
4072
Howard Hinnant82894812010-09-22 16:48:34 +00004073 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant4b53f502010-06-01 20:09:18 +00004074 state_type state() const {return __st_;}
Howard Hinnantd23b4642010-05-31 20:58:54 +00004075
4076protected:
Howard Hinnant4b53f502010-06-01 20:09:18 +00004077 virtual int_type underflow();
4078 virtual int_type pbackfail(int_type __c = traits_type::eof());
Howard Hinnantd23b4642010-05-31 20:58:54 +00004079 virtual int_type overflow (int_type __c = traits_type::eof());
Howard Hinnant4b53f502010-06-01 20:09:18 +00004080 virtual basic_streambuf<char_type, traits_type>* setbuf(char_type* __s,
4081 streamsize __n);
4082 virtual pos_type seekoff(off_type __off, ios_base::seekdir __way,
4083 ios_base::openmode __wch = ios_base::in | ios_base::out);
4084 virtual pos_type seekpos(pos_type __sp,
4085 ios_base::openmode __wch = ios_base::in | ios_base::out);
4086 virtual int sync();
4087
4088private:
4089 bool __read_mode();
4090 void __write_mode();
4091 wbuffer_convert* __close();
Howard Hinnantd23b4642010-05-31 20:58:54 +00004092};
4093
4094template <class _Codecvt, class _Elem, class _Tr>
Howard Hinnant4b53f502010-06-01 20:09:18 +00004095wbuffer_convert<_Codecvt, _Elem, _Tr>::
4096 wbuffer_convert(streambuf* __bytebuf, _Codecvt* __pcvt, state_type __state)
4097 : __extbuf_(0),
4098 __extbufnext_(0),
4099 __extbufend_(0),
4100 __ebs_(0),
4101 __intbuf_(0),
4102 __ibs_(0),
4103 __bufptr_(__bytebuf),
4104 __cv_(__pcvt),
4105 __st_(__state),
4106 __cm_(0),
4107 __owns_eb_(false),
4108 __owns_ib_(false),
4109 __always_noconv_(__cv_ ? __cv_->always_noconv() : false)
4110{
4111 setbuf(0, 4096);
4112}
4113
4114template <class _Codecvt, class _Elem, class _Tr>
4115wbuffer_convert<_Codecvt, _Elem, _Tr>::~wbuffer_convert()
4116{
4117 __close();
4118 delete __cv_;
4119 if (__owns_eb_)
4120 delete [] __extbuf_;
4121 if (__owns_ib_)
4122 delete [] __intbuf_;
4123}
4124
4125template <class _Codecvt, class _Elem, class _Tr>
4126typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
4127wbuffer_convert<_Codecvt, _Elem, _Tr>::underflow()
4128{
4129 if (__cv_ == 0 || __bufptr_ == 0)
4130 return traits_type::eof();
4131 bool __initial = __read_mode();
4132 char_type __1buf;
4133 if (this->gptr() == 0)
4134 this->setg(&__1buf, &__1buf+1, &__1buf+1);
4135 const size_t __unget_sz = __initial ? 0 : min<size_t>((this->egptr() - this->eback()) / 2, 4);
4136 int_type __c = traits_type::eof();
4137 if (this->gptr() == this->egptr())
4138 {
4139 memmove(this->eback(), this->egptr() - __unget_sz, __unget_sz * sizeof(char_type));
4140 if (__always_noconv_)
4141 {
4142 streamsize __nmemb = static_cast<streamsize>(this->egptr() - this->eback() - __unget_sz);
4143 __nmemb = __bufptr_->sgetn((char*)this->eback() + __unget_sz, __nmemb);
4144 if (__nmemb != 0)
4145 {
4146 this->setg(this->eback(),
4147 this->eback() + __unget_sz,
4148 this->eback() + __unget_sz + __nmemb);
4149 __c = *this->gptr();
4150 }
4151 }
4152 else
4153 {
4154 memmove(__extbuf_, __extbufnext_, __extbufend_ - __extbufnext_);
4155 __extbufnext_ = __extbuf_ + (__extbufend_ - __extbufnext_);
4156 __extbufend_ = __extbuf_ + (__extbuf_ == __extbuf_min_ ? sizeof(__extbuf_min_) : __ebs_);
Howard Hinnant0949eed2011-06-30 21:18:19 +00004157 streamsize __nmemb = _VSTD::min(static_cast<streamsize>(this->egptr() - this->eback() - __unget_sz),
Howard Hinnant4b53f502010-06-01 20:09:18 +00004158 static_cast<streamsize>(__extbufend_ - __extbufnext_));
4159 codecvt_base::result __r;
4160 state_type __svs = __st_;
4161 streamsize __nr = __bufptr_->sgetn(const_cast<char*>(__extbufnext_), __nmemb);
4162 if (__nr != 0)
4163 {
4164 __extbufend_ = __extbufnext_ + __nr;
4165 char_type* __inext;
4166 __r = __cv_->in(__st_, __extbuf_, __extbufend_, __extbufnext_,
4167 this->eback() + __unget_sz,
4168 this->egptr(), __inext);
4169 if (__r == codecvt_base::noconv)
4170 {
4171 this->setg((char_type*)__extbuf_, (char_type*)__extbuf_, (char_type*)__extbufend_);
4172 __c = *this->gptr();
4173 }
4174 else if (__inext != this->eback() + __unget_sz)
4175 {
4176 this->setg(this->eback(), this->eback() + __unget_sz, __inext);
4177 __c = *this->gptr();
4178 }
4179 }
4180 }
4181 }
4182 else
4183 __c = *this->gptr();
4184 if (this->eback() == &__1buf)
4185 this->setg(0, 0, 0);
4186 return __c;
4187}
4188
4189template <class _Codecvt, class _Elem, class _Tr>
4190typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
4191wbuffer_convert<_Codecvt, _Elem, _Tr>::pbackfail(int_type __c)
4192{
4193 if (__cv_ != 0 && __bufptr_ != 0 && this->eback() < this->gptr())
4194 {
4195 if (traits_type::eq_int_type(__c, traits_type::eof()))
4196 {
4197 this->gbump(-1);
4198 return traits_type::not_eof(__c);
4199 }
4200 if (traits_type::eq(traits_type::to_char_type(__c), this->gptr()[-1]))
4201 {
4202 this->gbump(-1);
4203 *this->gptr() = traits_type::to_char_type(__c);
4204 return __c;
4205 }
4206 }
4207 return traits_type::eof();
4208}
4209
4210template <class _Codecvt, class _Elem, class _Tr>
Howard Hinnantd23b4642010-05-31 20:58:54 +00004211typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
4212wbuffer_convert<_Codecvt, _Elem, _Tr>::overflow(int_type __c)
4213{
Howard Hinnant4b53f502010-06-01 20:09:18 +00004214 if (__cv_ == 0 || __bufptr_ == 0)
4215 return traits_type::eof();
4216 __write_mode();
4217 char_type __1buf;
4218 char_type* __pb_save = this->pbase();
4219 char_type* __epb_save = this->epptr();
4220 if (!traits_type::eq_int_type(__c, traits_type::eof()))
4221 {
4222 if (this->pptr() == 0)
4223 this->setp(&__1buf, &__1buf+1);
4224 *this->pptr() = traits_type::to_char_type(__c);
4225 this->pbump(1);
4226 }
4227 if (this->pptr() != this->pbase())
4228 {
4229 if (__always_noconv_)
4230 {
4231 streamsize __nmemb = static_cast<streamsize>(this->pptr() - this->pbase());
4232 if (__bufptr_->sputn((const char*)this->pbase(), __nmemb) != __nmemb)
4233 return traits_type::eof();
4234 }
4235 else
4236 {
4237 char* __extbe = __extbuf_;
4238 codecvt_base::result __r;
4239 do
4240 {
4241 const char_type* __e;
4242 __r = __cv_->out(__st_, this->pbase(), this->pptr(), __e,
4243 __extbuf_, __extbuf_ + __ebs_, __extbe);
4244 if (__e == this->pbase())
4245 return traits_type::eof();
4246 if (__r == codecvt_base::noconv)
4247 {
4248 streamsize __nmemb = static_cast<size_t>(this->pptr() - this->pbase());
4249 if (__bufptr_->sputn((const char*)this->pbase(), __nmemb) != __nmemb)
4250 return traits_type::eof();
4251 }
4252 else if (__r == codecvt_base::ok || __r == codecvt_base::partial)
4253 {
4254 streamsize __nmemb = static_cast<size_t>(__extbe - __extbuf_);
4255 if (__bufptr_->sputn(__extbuf_, __nmemb) != __nmemb)
4256 return traits_type::eof();
4257 if (__r == codecvt_base::partial)
4258 {
4259 this->setp((char_type*)__e, this->pptr());
4260 this->pbump(this->epptr() - this->pbase());
4261 }
4262 }
4263 else
4264 return traits_type::eof();
4265 } while (__r == codecvt_base::partial);
4266 }
4267 this->setp(__pb_save, __epb_save);
4268 }
4269 return traits_type::not_eof(__c);
4270}
4271
4272template <class _Codecvt, class _Elem, class _Tr>
4273basic_streambuf<_Elem, _Tr>*
4274wbuffer_convert<_Codecvt, _Elem, _Tr>::setbuf(char_type* __s, streamsize __n)
4275{
4276 this->setg(0, 0, 0);
4277 this->setp(0, 0);
4278 if (__owns_eb_)
4279 delete [] __extbuf_;
4280 if (__owns_ib_)
4281 delete [] __intbuf_;
4282 __ebs_ = __n;
4283 if (__ebs_ > sizeof(__extbuf_min_))
4284 {
4285 if (__always_noconv_ && __s)
4286 {
4287 __extbuf_ = (char*)__s;
4288 __owns_eb_ = false;
4289 }
4290 else
4291 {
4292 __extbuf_ = new char[__ebs_];
4293 __owns_eb_ = true;
4294 }
4295 }
4296 else
4297 {
4298 __extbuf_ = __extbuf_min_;
4299 __ebs_ = sizeof(__extbuf_min_);
4300 __owns_eb_ = false;
4301 }
4302 if (!__always_noconv_)
4303 {
4304 __ibs_ = max<streamsize>(__n, sizeof(__extbuf_min_));
4305 if (__s && __ibs_ >= sizeof(__extbuf_min_))
4306 {
4307 __intbuf_ = __s;
4308 __owns_ib_ = false;
4309 }
4310 else
4311 {
4312 __intbuf_ = new char_type[__ibs_];
4313 __owns_ib_ = true;
4314 }
4315 }
4316 else
4317 {
4318 __ibs_ = 0;
4319 __intbuf_ = 0;
4320 __owns_ib_ = false;
4321 }
4322 return this;
4323}
4324
4325template <class _Codecvt, class _Elem, class _Tr>
4326typename wbuffer_convert<_Codecvt, _Elem, _Tr>::pos_type
4327wbuffer_convert<_Codecvt, _Elem, _Tr>::seekoff(off_type __off, ios_base::seekdir __way,
4328 ios_base::openmode __om)
4329{
4330 int __width = __cv_->encoding();
4331 if (__cv_ == 0 || __bufptr_ == 0 || (__width <= 0 && __off != 0) || sync())
4332 return pos_type(off_type(-1));
4333 // __width > 0 || __off == 0
4334 switch (__way)
4335 {
4336 case ios_base::beg:
4337 break;
4338 case ios_base::cur:
4339 break;
4340 case ios_base::end:
4341 break;
4342 default:
4343 return pos_type(off_type(-1));
4344 }
4345 pos_type __r = __bufptr_->pubseekoff(__width * __off, __way, __om);
4346 __r.state(__st_);
4347 return __r;
4348}
4349
4350template <class _Codecvt, class _Elem, class _Tr>
4351typename wbuffer_convert<_Codecvt, _Elem, _Tr>::pos_type
4352wbuffer_convert<_Codecvt, _Elem, _Tr>::seekpos(pos_type __sp, ios_base::openmode __wch)
4353{
4354 if (__cv_ == 0 || __bufptr_ == 0 || sync())
4355 return pos_type(off_type(-1));
4356 if (__bufptr_->pubseekpos(__sp, __wch) == pos_type(off_type(-1)))
4357 return pos_type(off_type(-1));
4358 return __sp;
4359}
4360
4361template <class _Codecvt, class _Elem, class _Tr>
4362int
4363wbuffer_convert<_Codecvt, _Elem, _Tr>::sync()
4364{
4365 if (__cv_ == 0 || __bufptr_ == 0)
4366 return 0;
4367 if (__cm_ & ios_base::out)
4368 {
4369 if (this->pptr() != this->pbase())
4370 if (overflow() == traits_type::eof())
4371 return -1;
4372 codecvt_base::result __r;
4373 do
4374 {
4375 char* __extbe;
4376 __r = __cv_->unshift(__st_, __extbuf_, __extbuf_ + __ebs_, __extbe);
4377 streamsize __nmemb = static_cast<streamsize>(__extbe - __extbuf_);
4378 if (__bufptr_->sputn(__extbuf_, __nmemb) != __nmemb)
4379 return -1;
4380 } while (__r == codecvt_base::partial);
4381 if (__r == codecvt_base::error)
4382 return -1;
4383 if (__bufptr_->pubsync())
4384 return -1;
4385 }
4386 else if (__cm_ & ios_base::in)
4387 {
4388 off_type __c;
4389 if (__always_noconv_)
4390 __c = this->egptr() - this->gptr();
4391 else
4392 {
4393 int __width = __cv_->encoding();
4394 __c = __extbufend_ - __extbufnext_;
4395 if (__width > 0)
4396 __c += __width * (this->egptr() - this->gptr());
4397 else
4398 {
4399 if (this->gptr() != this->egptr())
4400 {
4401 reverse(this->gptr(), this->egptr());
4402 codecvt_base::result __r;
4403 const char_type* __e = this->gptr();
4404 char* __extbe;
4405 do
4406 {
4407 __r = __cv_->out(__st_, __e, this->egptr(), __e,
4408 __extbuf_, __extbuf_ + __ebs_, __extbe);
4409 switch (__r)
4410 {
4411 case codecvt_base::noconv:
4412 __c += this->egptr() - this->gptr();
4413 break;
4414 case codecvt_base::ok:
4415 case codecvt_base::partial:
4416 __c += __extbe - __extbuf_;
4417 break;
4418 default:
4419 return -1;
4420 }
4421 } while (__r == codecvt_base::partial);
4422 }
4423 }
4424 }
4425 if (__bufptr_->pubseekoff(-__c, ios_base::cur, __cm_) == pos_type(off_type(-1)))
4426 return -1;
4427 this->setg(0, 0, 0);
4428 __cm_ = 0;
4429 }
4430 return 0;
4431}
4432
4433template <class _Codecvt, class _Elem, class _Tr>
4434bool
4435wbuffer_convert<_Codecvt, _Elem, _Tr>::__read_mode()
4436{
4437 if (!(__cm_ & ios_base::in))
4438 {
4439 this->setp(0, 0);
4440 if (__always_noconv_)
4441 this->setg((char_type*)__extbuf_,
4442 (char_type*)__extbuf_ + __ebs_,
4443 (char_type*)__extbuf_ + __ebs_);
4444 else
4445 this->setg(__intbuf_, __intbuf_ + __ibs_, __intbuf_ + __ibs_);
4446 __cm_ = ios_base::in;
4447 return true;
4448 }
4449 return false;
4450}
4451
4452template <class _Codecvt, class _Elem, class _Tr>
4453void
4454wbuffer_convert<_Codecvt, _Elem, _Tr>::__write_mode()
4455{
4456 if (!(__cm_ & ios_base::out))
4457 {
4458 this->setg(0, 0, 0);
4459 if (__ebs_ > sizeof(__extbuf_min_))
4460 {
4461 if (__always_noconv_)
4462 this->setp((char_type*)__extbuf_,
4463 (char_type*)__extbuf_ + (__ebs_ - 1));
4464 else
4465 this->setp(__intbuf_, __intbuf_ + (__ibs_ - 1));
4466 }
4467 else
4468 this->setp(0, 0);
4469 __cm_ = ios_base::out;
4470 }
4471}
4472
4473template <class _Codecvt, class _Elem, class _Tr>
4474wbuffer_convert<_Codecvt, _Elem, _Tr>*
4475wbuffer_convert<_Codecvt, _Elem, _Tr>::__close()
4476{
4477 wbuffer_convert* __rt = 0;
4478 if (__cv_ != 0 && __bufptr_ != 0)
4479 {
4480 __rt = this;
4481 if ((__cm_ & ios_base::out) && sync())
4482 __rt = 0;
4483 }
4484 return __rt;
Howard Hinnantd23b4642010-05-31 20:58:54 +00004485}
4486
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004487_LIBCPP_END_NAMESPACE_STD
4488
4489#endif // _LIBCPP_LOCALE