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