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