blob: f6d3860798cf073c620effcfae76d56293949e5e [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 Hinnant14fa9f92011-09-29 20:33:10 +0000190#include <support/win32/locale_win32.h>
Howard Hinnant6cd05ee2011-09-23 16:11:27 +0000191#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000192#include <nl_types.h>
Howard Hinnant92a07002011-09-22 19:10:18 +0000193#endif // !_WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000194
Howard Hinnant66c6f972011-11-29 16:45:27 +0000195#include <__undef_min_max>
196
Howard Hinnant08e17472011-10-17 20:05:10 +0000197#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000198#pragma GCC system_header
Howard Hinnant08e17472011-10-17 20:05:10 +0000199#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000200
201_LIBCPP_BEGIN_NAMESPACE_STD
202
Howard Hinnant866569b2011-09-28 23:39:33 +0000203#if __APPLE__ || __FreeBSD__
Howard Hinnant2ea1ca92011-09-28 21:05:01 +0000204# define _LIBCPP_GET_C_LOCALE 0
205#else
206# define _LIBCPP_GET_C_LOCALE __cloc()
Howard Hinnant866569b2011-09-28 23:39:33 +0000207 // Get the C locale object
208 locale_t __cloc();
209#define __cloc_defined
Howard Hinnant2ea1ca92011-09-28 21:05:01 +0000210#endif
211
Sean Huntf3907e62011-07-15 05:40:33 +0000212typedef _VSTD::remove_pointer<locale_t>::type __locale_struct;
213typedef _VSTD::unique_ptr<__locale_struct, decltype(&freelocale)> __locale_unique_ptr;
David Chisnall8fa14e92012-02-29 13:00:07 +0000214#ifndef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +0000215typedef _VSTD::unique_ptr<__locale_struct, decltype(&uselocale)> __locale_raii;
David Chisnall8fa14e92012-02-29 13:00:07 +0000216#endif
Sean Huntf3907e62011-07-15 05:40:33 +0000217
Howard Hinnantadff4892010-05-24 17:49:41 +0000218// OSX has nice foo_l() functions that let you turn off use of the global
219// locale. Linux, not so much. The following functions avoid the locale when
220// that's possible and otherwise do the wrong thing. FIXME.
Howard Hinnant866569b2011-09-28 23:39:33 +0000221#ifdef __linux__
Sean Huntf3907e62011-07-15 05:40:33 +0000222
223#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
224decltype(MB_CUR_MAX_L(_VSTD::declval<locale_t>()))
Howard Hinnant82894812010-09-22 16:48:34 +0000225inline _LIBCPP_INLINE_VISIBILITY
Sean Huntf3907e62011-07-15 05:40:33 +0000226__mb_cur_max_l(locale_t __l)
Howard Hinnantadff4892010-05-24 17:49:41 +0000227{
Sean Huntf3907e62011-07-15 05:40:33 +0000228 return MB_CUR_MAX_L(__l);
229}
230#else // _LIBCPP_LOCALE__L_EXTENSIONS
231_LIBCPP_ALWAYS_INLINE inline
232decltype(MB_CUR_MAX) __mb_cur_max_l(locale_t __l)
233{
234 __locale_raii __current(uselocale(__l), uselocale);
235 return MB_CUR_MAX;
236}
237#endif // _LIBCPP_LOCALE__L_EXTENSIONS
238
239_LIBCPP_ALWAYS_INLINE inline
240wint_t __btowc_l(int __c, locale_t __l)
241{
Howard Hinnant866569b2011-09-28 23:39:33 +0000242#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +0000243 return btowc_l(__c, __l);
244#else
245 __locale_raii __current(uselocale(__l), uselocale);
246 return btowc(__c);
247#endif
Sean Huntc97da3a2011-07-13 06:40:50 +0000248}
Howard Hinnant8d756322011-07-13 15:48:16 +0000249
Sean Huntf3907e62011-07-15 05:40:33 +0000250_LIBCPP_ALWAYS_INLINE inline
251int __wctob_l(wint_t __c, locale_t __l)
Sean Huntc97da3a2011-07-13 06:40:50 +0000252{
Sean Huntf3907e62011-07-15 05:40:33 +0000253#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
254 return wctob_l(__c, __l);
255#else
256 __locale_raii __current(uselocale(__l), uselocale);
257 return wctob(__c);
258#endif
Sean Huntc97da3a2011-07-13 06:40:50 +0000259}
Sean Huntf3907e62011-07-15 05:40:33 +0000260
261_LIBCPP_ALWAYS_INLINE inline
262size_t __wcsnrtombs_l(char *__dest, const wchar_t **__src, size_t __nwc,
263 size_t __len, mbstate_t *__ps, locale_t __l)
264{
265#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
266 return wcsnrtombs_l(__dest, __src, __nwc, __len, __ps, __l);
267#else
268 __locale_raii __current(uselocale(__l), uselocale);
269 return wcsnrtombs(__dest, __src, __nwc, __len, __ps);
270#endif
271}
272
273_LIBCPP_ALWAYS_INLINE inline
274size_t __wcrtomb_l(char *__s, wchar_t __wc, mbstate_t *__ps, locale_t __l)
275{
276#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
277 return wcrtomb_l(__s, __wc, __ps, __l);
278#else
279 __locale_raii __current(uselocale(__l), uselocale);
280 return wcrtomb(__s, __wc, __ps);
281#endif
282}
283
284_LIBCPP_ALWAYS_INLINE inline
285size_t __mbsnrtowcs_l(wchar_t * __dest, const char **__src, size_t __nms,
286 size_t __len, mbstate_t *__ps, locale_t __l)
287{
288#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
David Chisnallc512df12011-09-21 08:39:44 +0000289 return mbsnrtowcs_l(__dest, __src, __nms, __len, __ps, __l);
Sean Huntf3907e62011-07-15 05:40:33 +0000290#else
291 __locale_raii __current(uselocale(__l), uselocale);
292 return mbsnrtowcs(__dest, __src, __nms, __len, __ps);
293#endif
294}
295
296_LIBCPP_ALWAYS_INLINE inline
297size_t __mbrtowc_l(wchar_t *__pwc, const char *__s, size_t __n,
298 mbstate_t *__ps, locale_t __l)
299{
300#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
301 return mbrtowc_l(__pwc, __s, __n, __ps, __l);
302#else
303 __locale_raii __current(uselocale(__l), uselocale);
304 return mbrtowc(__pwc, __s, __n, __ps);
305#endif
306}
307
308_LIBCPP_ALWAYS_INLINE inline
309int __mbtowc_l(wchar_t *__pwc, const char *__pmb, size_t __max, locale_t __l)
310{
311#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
David Chisnallc512df12011-09-21 08:39:44 +0000312 return mbtowc_l(__pwc, __pmb, __max, __l);
Sean Huntf3907e62011-07-15 05:40:33 +0000313#else
314 __locale_raii __current(uselocale(__l), uselocale);
315 return mbtowc(__pwc, __pmb, __max);
316#endif
317}
318
319_LIBCPP_ALWAYS_INLINE inline
320size_t __mbrlen_l(const char *__s, size_t __n, mbstate_t *__ps, locale_t __l)
321{
322#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
323 return mbrlen_l(__s, __n, __ps, __l);
324#else
325 __locale_raii __current(uselocale(__l), uselocale);
326 return mbrlen(__s, __n, __ps);
327#endif
328}
329
330_LIBCPP_ALWAYS_INLINE inline
331lconv *__localeconv_l(locale_t __l)
332{
333#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
334 return localeconv_l(__l);
335#else
336 __locale_raii __current(uselocale(__l), uselocale);
337 return localeconv();
338#endif
339}
340
341_LIBCPP_ALWAYS_INLINE inline
342size_t __mbsrtowcs_l(wchar_t *__dest, const char **__src, size_t __len,
343 mbstate_t *__ps, locale_t __l)
344{
345#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
346 return mbsrtowcs_l(__dest, __src, __len, __ps, __l);
347#else
348 __locale_raii __current(uselocale(__l), uselocale);
349 return mbsrtowcs(__dest, __src, __len, __ps);
350#endif
351}
352
353_LIBCPP_ALWAYS_INLINE inline
354int __sprintf_l(char *__s, locale_t __l, const char *__format, ...) {
355 va_list __va;
356 va_start(__va, __format);
357#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
358 int __res = vsprintf_l(__s, __l, __format, __va);
359#else
360 __locale_raii __current(uselocale(__l), uselocale);
361 int __res = vsprintf(__s, __format, __va);
362#endif
363 va_end(__va);
364 return __res;
365}
366
367_LIBCPP_ALWAYS_INLINE inline
368int __snprintf_l(char *__s, size_t __n, locale_t __l, const char *__format, ...) {
369 va_list __va;
370 va_start(__va, __format);
371#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
372 int __res = vsnprintf_l(__s, __n, __l, __format, __va);
373#else
374 __locale_raii __current(uselocale(__l), uselocale);
375 int __res = vsnprintf(__s, __n, __format, __va);
376#endif
377 va_end(__va);
378 return __res;
379}
380
381_LIBCPP_ALWAYS_INLINE inline
382int __asprintf_l(char **__s, locale_t __l, const char *__format, ...) {
383 va_list __va;
384 va_start(__va, __format);
385#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
386 int __res = vasprintf_l(__s, __l, __format, __va);
387#else
388 __locale_raii __current(uselocale(__l), uselocale);
389 int __res = vasprintf(__s, __format, __va);
390#endif
391 va_end(__va);
392 return __res;
393}
394
395_LIBCPP_ALWAYS_INLINE inline
396int __sscanf_l(const char *__s, locale_t __l, const char *__format, ...) {
397 va_list __va;
398 va_start(__va, __format);
399#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
400 int __res = vsscanf_l(__s, __l, __format, __va);
401#else
402 __locale_raii __current(uselocale(__l), uselocale);
403 int __res = vsscanf(__s, __format, __va);
404#endif
405 va_end(__va);
406 return __res;
407}
408
Howard Hinnant866569b2011-09-28 23:39:33 +0000409#endif // __linux__
Howard Hinnantadff4892010-05-24 17:49:41 +0000410
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000411// __scan_keyword
412// Scans [__b, __e) until a match is found in the basic_strings range
413// [__kb, __ke) or until it can be shown that there is no match in [__kb, __ke).
414// __b will be incremented (visibly), consuming CharT until a match is found
415// or proved to not exist. A keyword may be "", in which will match anything.
416// If one keyword is a prefix of another, and the next CharT in the input
417// might match another keyword, the algorithm will attempt to find the longest
418// matching keyword. If the longer matching keyword ends up not matching, then
419// no keyword match is found. If no keyword match is found, __ke is returned
420// and failbit is set in __err.
421// Else an iterator pointing to the matching keyword is found. If more than
422// one keyword matches, an iterator to the first matching keyword is returned.
423// If on exit __b == __e, eofbit is set in __err. If __case_senstive is false,
424// __ct is used to force to lower case before comparing characters.
425// Examples:
426// Keywords: "a", "abb"
427// If the input is "a", the first keyword matches and eofbit is set.
428// If the input is "abc", no match is found and "ab" are consumed.
429template <class _InputIterator, class _ForwardIterator, class _Ctype>
430_LIBCPP_HIDDEN
431_ForwardIterator
432__scan_keyword(_InputIterator& __b, _InputIterator __e,
433 _ForwardIterator __kb, _ForwardIterator __ke,
434 const _Ctype& __ct, ios_base::iostate& __err,
435 bool __case_sensitive = true)
436{
437 typedef typename iterator_traits<_InputIterator>::value_type _CharT;
Howard Hinnantec3773c2011-12-01 20:21:04 +0000438 size_t __nkw = static_cast<size_t>(_VSTD::distance(__kb, __ke));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000439 const unsigned char __doesnt_match = '\0';
440 const unsigned char __might_match = '\1';
441 const unsigned char __does_match = '\2';
442 unsigned char __statbuf[100];
443 unsigned char* __status = __statbuf;
444 unique_ptr<unsigned char, void(*)(void*)> __stat_hold(0, free);
445 if (__nkw > sizeof(__statbuf))
446 {
447 __status = (unsigned char*)malloc(__nkw);
448 if (__status == 0)
449 __throw_bad_alloc();
450 __stat_hold.reset(__status);
451 }
452 size_t __n_might_match = __nkw; // At this point, any keyword might match
453 size_t __n_does_match = 0; // but none of them definitely do
454 // Initialize all statuses to __might_match, except for "" keywords are __does_match
455 unsigned char* __st = __status;
456 for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, ++__st)
457 {
458 if (!__ky->empty())
459 *__st = __might_match;
460 else
461 {
462 *__st = __does_match;
463 --__n_might_match;
464 ++__n_does_match;
465 }
466 }
467 // While there might be a match, test keywords against the next CharT
468 for (size_t __indx = 0; __b != __e && __n_might_match > 0; ++__indx)
469 {
470 // Peek at the next CharT but don't consume it
471 _CharT __c = *__b;
472 if (!__case_sensitive)
473 __c = __ct.toupper(__c);
474 bool __consume = false;
475 // For each keyword which might match, see if the __indx character is __c
476 // If a match if found, consume __c
477 // If a match is found, and that is the last character in the keyword,
478 // then that keyword matches.
479 // If the keyword doesn't match this character, then change the keyword
480 // to doesn't match
481 __st = __status;
482 for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, ++__st)
483 {
484 if (*__st == __might_match)
485 {
486 _CharT __kc = (*__ky)[__indx];
487 if (!__case_sensitive)
488 __kc = __ct.toupper(__kc);
489 if (__c == __kc)
490 {
491 __consume = true;
492 if (__ky->size() == __indx+1)
493 {
494 *__st = __does_match;
495 --__n_might_match;
496 ++__n_does_match;
497 }
498 }
499 else
500 {
501 *__st = __doesnt_match;
502 --__n_might_match;
503 }
504 }
505 }
506 // consume if we matched a character
507 if (__consume)
508 {
509 ++__b;
510 // If we consumed a character and there might be a matched keyword that
511 // was marked matched on a previous iteration, then such keywords
512 // which are now marked as not matching.
513 if (__n_might_match + __n_does_match > 1)
514 {
515 __st = __status;
516 for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, ++__st)
517 {
518 if (*__st == __does_match && __ky->size() != __indx+1)
519 {
520 *__st = __doesnt_match;
521 --__n_does_match;
522 }
523 }
524 }
525 }
526 }
527 // We've exited the loop because we hit eof and/or we have no more "might matches".
528 if (__b == __e)
529 __err |= ios_base::eofbit;
530 // Return the first matching result
531 for (__st = __status; __kb != __ke; ++__kb, ++__st)
532 if (*__st == __does_match)
533 break;
534 if (__kb == __ke)
535 __err |= ios_base::failbit;
536 return __kb;
537}
538
539struct __num_get_base
540{
541 static const int __num_get_buf_sz = 40;
542
543 static int __get_base(ios_base&);
544 static const char __src[33];
545};
546
547void __check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
548 ios_base::iostate& __err);
549
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000550template <class _CharT>
551struct __num_get
552 : protected __num_get_base
553{
554 static string __stage2_int_prep(ios_base& __iob, _CharT* __atoms, _CharT& __thousands_sep);
555 static string __stage2_float_prep(ios_base& __iob, _CharT* __atoms, _CharT& __decimal_point,
556 _CharT& __thousands_sep);
557 static int __stage2_int_loop(_CharT __ct, int __base, char* __a, char*& __a_end,
558 unsigned& __dc, _CharT __thousands_sep, const string& __grouping,
559 unsigned* __g, unsigned*& __g_end, _CharT* __atoms);
560 static int __stage2_float_loop(_CharT __ct, bool& __in_units, char& __exp,
561 char* __a, char*& __a_end,
562 _CharT __decimal_point, _CharT __thousands_sep,
563 const string& __grouping, unsigned* __g,
564 unsigned*& __g_end, unsigned& __dc, _CharT* __atoms);
565};
566
567template <class _CharT>
568string
569__num_get<_CharT>::__stage2_int_prep(ios_base& __iob, _CharT* __atoms, _CharT& __thousands_sep)
570{
571 locale __loc = __iob.getloc();
572 use_facet<ctype<_CharT> >(__loc).widen(__src, __src + 26, __atoms);
573 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
574 __thousands_sep = __np.thousands_sep();
575 return __np.grouping();
576}
577
578template <class _CharT>
579string
580__num_get<_CharT>::__stage2_float_prep(ios_base& __iob, _CharT* __atoms, _CharT& __decimal_point,
581 _CharT& __thousands_sep)
582{
583 locale __loc = __iob.getloc();
584 use_facet<ctype<_CharT> >(__loc).widen(__src, __src + 32, __atoms);
585 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
586 __decimal_point = __np.decimal_point();
587 __thousands_sep = __np.thousands_sep();
588 return __np.grouping();
589}
590
591template <class _CharT>
592int
593__num_get<_CharT>::__stage2_int_loop(_CharT __ct, int __base, char* __a, char*& __a_end,
594 unsigned& __dc, _CharT __thousands_sep, const string& __grouping,
595 unsigned* __g, unsigned*& __g_end, _CharT* __atoms)
596{
Howard Hinnant80586722011-03-09 01:03:19 +0000597 if (__a_end == __a && (__ct == __atoms[24] || __ct == __atoms[25]))
598 {
599 *__a_end++ = __ct == __atoms[24] ? '+' : '-';
600 __dc = 0;
601 return 0;
602 }
Howard Hinnantec3773c2011-12-01 20:21:04 +0000603 if (__grouping.size() != 0 && __ct == __thousands_sep)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000604 {
605 if (__g_end-__g < __num_get_buf_sz)
606 {
607 *__g_end++ = __dc;
608 __dc = 0;
609 }
610 return 0;
611 }
612 ptrdiff_t __f = find(__atoms, __atoms + 26, __ct) - __atoms;
Howard Hinnant80586722011-03-09 01:03:19 +0000613 if (__f >= 24)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000614 return -1;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000615 switch (__base)
616 {
617 case 8:
618 case 10:
619 if (__f >= __base)
Howard Hinnant80586722011-03-09 01:03:19 +0000620 return -1;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000621 break;
Howard Hinnant80586722011-03-09 01:03:19 +0000622 case 16:
623 if (__f < 22)
624 break;
625 if (__a_end != __a && __a_end - __a <= 2 && __a_end[-1] == '0')
626 {
627 __dc = 0;
628 *__a_end++ = __src[__f];
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000629 return 0;
Howard Hinnant80586722011-03-09 01:03:19 +0000630 }
631 return -1;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000632 }
Howard Hinnant80586722011-03-09 01:03:19 +0000633 if (__a_end-__a < __num_get_buf_sz - 1)
634 *__a_end++ = __src[__f];
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000635 ++__dc;
636 return 0;
637}
638
639template <class _CharT>
640int
641__num_get<_CharT>::__stage2_float_loop(_CharT __ct, bool& __in_units, char& __exp, char* __a, char*& __a_end,
642 _CharT __decimal_point, _CharT __thousands_sep, const string& __grouping,
643 unsigned* __g, unsigned*& __g_end, unsigned& __dc, _CharT* __atoms)
644{
645 if (__ct == __decimal_point)
646 {
647 if (!__in_units)
648 return -1;
649 __in_units = false;
650 *__a_end++ = '.';
651 if (__grouping.size() != 0 && __g_end-__g < __num_get_buf_sz)
652 *__g_end++ = __dc;
653 return 0;
654 }
655 if (__ct == __thousands_sep && __grouping.size() != 0)
656 {
657 if (!__in_units)
658 return -1;
659 if (__g_end-__g < __num_get_buf_sz)
660 {
661 *__g_end++ = __dc;
662 __dc = 0;
663 }
664 return 0;
665 }
666 ptrdiff_t __f = find(__atoms, __atoms + 32, __ct) - __atoms;
667 if (__f >= 32)
668 return -1;
669 char __x = __src[__f];
Howard Hinnantb04ad412012-02-15 19:19:37 +0000670 if (__x == '-' || __x == '+')
671 {
672 if (__a_end == __a || (__a_end[-1] & 0xDF) == __exp)
673 {
674 *__a_end++ = __x;
675 return 0;
676 }
677 return -1;
678 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000679 if (__a_end-__a < __num_get_buf_sz - 1)
680 *__a_end++ = __x;
681 if (__x == 'x' || __x == 'X')
682 __exp = 'P';
683 else if ((__x & 0xDF) == __exp)
684 {
685 __in_units = false;
686 if (__grouping.size() != 0 && __g_end-__g < __num_get_buf_sz)
687 *__g_end++ = __dc;
688 }
689 if (__f >= 22)
690 return 0;
691 ++__dc;
692 return 0;
693}
694
Howard Hinnantec3773c2011-12-01 20:21:04 +0000695extern template struct __num_get<char>;
696extern template struct __num_get<wchar_t>;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000697
698template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +0000699class _LIBCPP_VISIBLE num_get
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000700 : public locale::facet,
701 private __num_get<_CharT>
702{
703public:
704 typedef _CharT char_type;
705 typedef _InputIterator iter_type;
706
707 _LIBCPP_ALWAYS_INLINE
708 explicit num_get(size_t __refs = 0)
709 : locale::facet(__refs) {}
710
711 _LIBCPP_ALWAYS_INLINE
712 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
713 ios_base::iostate& __err, bool& __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, long& __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, long long& __v) const
728 {
729 return do_get(__b, __e, __iob, __err, __v);
730 }
731
732 _LIBCPP_ALWAYS_INLINE
733 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
734 ios_base::iostate& __err, unsigned short& __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 int& __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, unsigned long& __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, unsigned long long& __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, float& __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, double& __v) const
770 {
771 return do_get(__b, __e, __iob, __err, __v);
772 }
773
774 _LIBCPP_ALWAYS_INLINE
775 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
776 ios_base::iostate& __err, long double& __v) const
777 {
778 return do_get(__b, __e, __iob, __err, __v);
779 }
780
781 _LIBCPP_ALWAYS_INLINE
782 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
783 ios_base::iostate& __err, void*& __v) const
784 {
785 return do_get(__b, __e, __iob, __err, __v);
786 }
787
788 static locale::id id;
789
790protected:
Howard Hinnant82894812010-09-22 16:48:34 +0000791 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000792 ~num_get() {}
793
794 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
795 ios_base::iostate& __err, bool& __v) const;
796 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
797 ios_base::iostate& __err, long& __v) const;
798 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
799 ios_base::iostate& __err, long long& __v) const;
800 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
801 ios_base::iostate& __err, unsigned short& __v) const;
802 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
803 ios_base::iostate& __err, unsigned int& __v) const;
804 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
805 ios_base::iostate& __err, unsigned long& __v) const;
806 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
807 ios_base::iostate& __err, unsigned long long& __v) const;
808 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
809 ios_base::iostate& __err, float& __v) const;
810 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
811 ios_base::iostate& __err, double& __v) const;
812 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
813 ios_base::iostate& __err, long double& __v) const;
814 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
815 ios_base::iostate& __err, void*& __v) const;
816};
817
818template <class _CharT, class _InputIterator>
819locale::id
820num_get<_CharT, _InputIterator>::id;
821
822template <class _Tp>
823_Tp
824__num_get_signed_integral(const char* __a, const char* __a_end,
825 ios_base::iostate& __err, int __base)
826{
827 if (__a != __a_end)
828 {
Howard Hinnante7c8da62011-02-25 19:52:41 +0000829 int __save_errno = errno;
830 errno = 0;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000831 char *__p2;
Howard Hinnant2ea1ca92011-09-28 21:05:01 +0000832 long long __ll = strtoll_l(__a, &__p2, __base, _LIBCPP_GET_C_LOCALE);
Howard Hinnante7c8da62011-02-25 19:52:41 +0000833 int __current_errno = errno;
834 if (__current_errno == 0)
835 errno = __save_errno;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000836 if (__p2 != __a_end)
837 {
838 __err = ios_base::failbit;
839 return 0;
840 }
Howard Hinnante7c8da62011-02-25 19:52:41 +0000841 else if (__current_errno == ERANGE ||
842 __ll < numeric_limits<_Tp>::min() ||
843 numeric_limits<_Tp>::max() < __ll)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000844 {
845 __err = ios_base::failbit;
Howard Hinnante7c8da62011-02-25 19:52:41 +0000846 if (__ll > 0)
847 return numeric_limits<_Tp>::max();
848 else
849 return numeric_limits<_Tp>::min();
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000850 }
851 return static_cast<_Tp>(__ll);
852 }
853 __err = ios_base::failbit;
854 return 0;
855}
856
857template <class _Tp>
858_Tp
859__num_get_unsigned_integral(const char* __a, const char* __a_end,
860 ios_base::iostate& __err, int __base)
861{
862 if (__a != __a_end)
863 {
Howard Hinnante7c8da62011-02-25 19:52:41 +0000864 if (*__a == '-')
865 {
866 __err = ios_base::failbit;
867 return 0;
868 }
869 int __save_errno = errno;
870 errno = 0;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000871 char *__p2;
Howard Hinnant2ea1ca92011-09-28 21:05:01 +0000872 unsigned long long __ll = strtoull_l(__a, &__p2, __base, _LIBCPP_GET_C_LOCALE);
Howard Hinnante7c8da62011-02-25 19:52:41 +0000873 int __current_errno = errno;
874 if (__current_errno == 0)
875 errno = __save_errno;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000876 if (__p2 != __a_end)
877 {
878 __err = ios_base::failbit;
879 return 0;
880 }
Howard Hinnante7c8da62011-02-25 19:52:41 +0000881 else if (__current_errno == ERANGE ||
882 numeric_limits<_Tp>::max() < __ll)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000883 {
884 __err = ios_base::failbit;
885 return numeric_limits<_Tp>::max();
886 }
887 return static_cast<_Tp>(__ll);
888 }
889 __err = ios_base::failbit;
890 return 0;
891}
892
893template <class _Tp>
894_Tp
895__num_get_float(const char* __a, const char* __a_end, ios_base::iostate& __err)
896{
897 if (__a != __a_end)
898 {
899 char *__p2;
Howard Hinnant2ea1ca92011-09-28 21:05:01 +0000900 long double __ld = strtold_l(__a, &__p2, _LIBCPP_GET_C_LOCALE);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000901 if (__p2 != __a_end)
902 {
903 __err = ios_base::failbit;
904 return 0;
905 }
906 return static_cast<_Tp>(__ld);
907 }
908 __err = ios_base::failbit;
909 return 0;
910}
911
912template <class _CharT, class _InputIterator>
913_InputIterator
914num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
915 ios_base& __iob,
916 ios_base::iostate& __err,
917 bool& __v) const
918{
919 if ((__iob.flags() & ios_base::boolalpha) == 0)
920 {
921 long __lv = -1;
922 __b = do_get(__b, __e, __iob, __err, __lv);
923 switch (__lv)
924 {
925 case 0:
926 __v = false;
927 break;
928 case 1:
929 __v = true;
930 break;
931 default:
932 __v = true;
933 __err = ios_base::failbit;
934 break;
935 }
936 return __b;
937 }
938 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__iob.getloc());
939 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__iob.getloc());
940 typedef typename numpunct<_CharT>::string_type string_type;
941 const string_type __names[2] = {__np.truename(), __np.falsename()};
942 const string_type* __i = __scan_keyword(__b, __e, __names, __names+2,
943 __ct, __err);
944 __v = __i == __names;
945 return __b;
946}
947
948template <class _CharT, class _InputIterator>
949_InputIterator
950num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
951 ios_base& __iob,
952 ios_base::iostate& __err,
953 long& __v) const
954{
955 // Stage 1
956 int __base = this->__get_base(__iob);
957 // Stage 2
958 char_type __atoms[26];
959 char_type __thousands_sep;
960 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
961 char __a[__num_get_base::__num_get_buf_sz] = {0};
962 char* __a_end = __a;
963 unsigned __g[__num_get_base::__num_get_buf_sz];
964 unsigned* __g_end = __g;
965 unsigned __dc = 0;
966 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +0000967 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000968 __thousands_sep, __grouping, __g, __g_end,
969 __atoms))
970 break;
971 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
972 *__g_end++ = __dc;
973 // Stage 3
974 __v = __num_get_signed_integral<long>(__a, __a_end, __err, __base);
975 // Digit grouping checked
976 __check_grouping(__grouping, __g, __g_end, __err);
977 // EOF checked
978 if (__b == __e)
979 __err |= ios_base::eofbit;
980 return __b;
981}
982
983template <class _CharT, class _InputIterator>
984_InputIterator
985num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
986 ios_base& __iob,
987 ios_base::iostate& __err,
988 long long& __v) const
989{
990 // Stage 1
991 int __base = this->__get_base(__iob);
992 // Stage 2
993 char_type __atoms[26];
994 char_type __thousands_sep;
995 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
996 char __a[__num_get_base::__num_get_buf_sz] = {0};
997 char* __a_end = __a;
998 unsigned __g[__num_get_base::__num_get_buf_sz];
999 unsigned* __g_end = __g;
1000 unsigned __dc = 0;
1001 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001002 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
1003 __thousands_sep, __grouping, __g, __g_end,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001004 __atoms))
1005 break;
1006 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
1007 *__g_end++ = __dc;
1008 // Stage 3
1009 __v = __num_get_signed_integral<long long>(__a, __a_end, __err, __base);
1010 // Digit grouping checked
1011 __check_grouping(__grouping, __g, __g_end, __err);
1012 // EOF checked
1013 if (__b == __e)
1014 __err |= ios_base::eofbit;
1015 return __b;
1016}
1017
1018template <class _CharT, class _InputIterator>
1019_InputIterator
1020num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1021 ios_base& __iob,
1022 ios_base::iostate& __err,
1023 unsigned short& __v) const
1024{
1025 // Stage 1
1026 int __base = this->__get_base(__iob);
1027 // Stage 2
1028 char_type __atoms[26];
1029 char_type __thousands_sep;
1030 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
1031 char __a[__num_get_base::__num_get_buf_sz] = {0};
1032 char* __a_end = __a;
1033 unsigned __g[__num_get_base::__num_get_buf_sz];
1034 unsigned* __g_end = __g;
1035 unsigned __dc = 0;
1036 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001037 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001038 __thousands_sep, __grouping, __g, __g_end,
1039 __atoms))
1040 break;
1041 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
1042 *__g_end++ = __dc;
1043 // Stage 3
1044 __v = __num_get_unsigned_integral<unsigned short>(__a, __a_end, __err, __base);
1045 // Digit grouping checked
1046 __check_grouping(__grouping, __g, __g_end, __err);
1047 // EOF checked
1048 if (__b == __e)
1049 __err |= ios_base::eofbit;
1050 return __b;
1051}
1052
1053template <class _CharT, class _InputIterator>
1054_InputIterator
1055num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1056 ios_base& __iob,
1057 ios_base::iostate& __err,
1058 unsigned int& __v) const
1059{
1060 // Stage 1
1061 int __base = this->__get_base(__iob);
1062 // Stage 2
1063 char_type __atoms[26];
1064 char_type __thousands_sep;
1065 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
1066 char __a[__num_get_base::__num_get_buf_sz] = {0};
1067 char* __a_end = __a;
1068 unsigned __g[__num_get_base::__num_get_buf_sz];
1069 unsigned* __g_end = __g;
1070 unsigned __dc = 0;
1071 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001072 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001073 __thousands_sep, __grouping, __g, __g_end,
1074 __atoms))
1075 break;
1076 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
1077 *__g_end++ = __dc;
1078 // Stage 3
1079 __v = __num_get_unsigned_integral<unsigned int>(__a, __a_end, __err, __base);
1080 // Digit grouping checked
1081 __check_grouping(__grouping, __g, __g_end, __err);
1082 // EOF checked
1083 if (__b == __e)
1084 __err |= ios_base::eofbit;
1085 return __b;
1086}
1087
1088template <class _CharT, class _InputIterator>
1089_InputIterator
1090num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1091 ios_base& __iob,
1092 ios_base::iostate& __err,
1093 unsigned long& __v) const
1094{
1095 // Stage 1
1096 int __base = this->__get_base(__iob);
1097 // Stage 2
1098 char_type __atoms[26];
1099 char_type __thousands_sep;
1100 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
1101 char __a[__num_get_base::__num_get_buf_sz] = {0};
1102 char* __a_end = __a;
1103 unsigned __g[__num_get_base::__num_get_buf_sz];
1104 unsigned* __g_end = __g;
1105 unsigned __dc = 0;
1106 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001107 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001108 __thousands_sep, __grouping, __g, __g_end,
1109 __atoms))
1110 break;
1111 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
1112 *__g_end++ = __dc;
1113 // Stage 3
1114 __v = __num_get_unsigned_integral<unsigned long>(__a, __a_end, __err, __base);
1115 // Digit grouping checked
1116 __check_grouping(__grouping, __g, __g_end, __err);
1117 // EOF checked
1118 if (__b == __e)
1119 __err |= ios_base::eofbit;
1120 return __b;
1121}
1122
1123template <class _CharT, class _InputIterator>
1124_InputIterator
1125num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1126 ios_base& __iob,
1127 ios_base::iostate& __err,
1128 unsigned long long& __v) const
1129{
1130 // Stage 1
1131 int __base = this->__get_base(__iob);
1132 // Stage 2
1133 char_type __atoms[26];
1134 char_type __thousands_sep;
1135 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
1136 char __a[__num_get_base::__num_get_buf_sz] = {0};
1137 char* __a_end = __a;
1138 unsigned __g[__num_get_base::__num_get_buf_sz];
1139 unsigned* __g_end = __g;
1140 unsigned __dc = 0;
1141 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001142 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001143 __thousands_sep, __grouping, __g, __g_end,
1144 __atoms))
1145 break;
1146 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
1147 *__g_end++ = __dc;
1148 // Stage 3
1149 __v = __num_get_unsigned_integral<unsigned long long>(__a, __a_end, __err, __base);
1150 // Digit grouping checked
1151 __check_grouping(__grouping, __g, __g_end, __err);
1152 // EOF checked
1153 if (__b == __e)
1154 __err |= ios_base::eofbit;
1155 return __b;
1156}
1157
1158template <class _CharT, class _InputIterator>
1159_InputIterator
1160num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1161 ios_base& __iob,
1162 ios_base::iostate& __err,
1163 float& __v) const
1164{
1165 // Stage 1, nothing to do
1166 // Stage 2
1167 char_type __atoms[32];
1168 char_type __decimal_point;
1169 char_type __thousands_sep;
Howard Hinnant324bb032010-08-22 00:02:43 +00001170 string __grouping = this->__stage2_float_prep(__iob, __atoms,
1171 __decimal_point,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001172 __thousands_sep);
1173 char __a[__num_get_base::__num_get_buf_sz] = {0};
1174 char* __a_end = __a;
1175 unsigned __g[__num_get_base::__num_get_buf_sz];
1176 unsigned* __g_end = __g;
1177 unsigned __dc = 0;
1178 bool __in_units = true;
1179 char __exp = 'E';
1180 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001181 if (this->__stage2_float_loop(*__b, __in_units, __exp, __a, __a_end,
1182 __decimal_point, __thousands_sep,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001183 __grouping, __g, __g_end,
1184 __dc, __atoms))
1185 break;
1186 if (__grouping.size() != 0 && __in_units && __g_end-__g < __num_get_base::__num_get_buf_sz)
1187 *__g_end++ = __dc;
1188 // Stage 3
1189 __v = __num_get_float<float>(__a, __a_end, __err);
1190 // Digit grouping checked
1191 __check_grouping(__grouping, __g, __g_end, __err);
1192 // EOF checked
1193 if (__b == __e)
1194 __err |= ios_base::eofbit;
1195 return __b;
1196}
1197
1198template <class _CharT, class _InputIterator>
1199_InputIterator
1200num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1201 ios_base& __iob,
1202 ios_base::iostate& __err,
1203 double& __v) const
1204{
1205 // Stage 1, nothing to do
1206 // Stage 2
1207 char_type __atoms[32];
1208 char_type __decimal_point;
1209 char_type __thousands_sep;
Howard Hinnant324bb032010-08-22 00:02:43 +00001210 string __grouping = this->__stage2_float_prep(__iob, __atoms,
1211 __decimal_point,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001212 __thousands_sep);
1213 char __a[__num_get_base::__num_get_buf_sz] = {0};
1214 char* __a_end = __a;
1215 unsigned __g[__num_get_base::__num_get_buf_sz];
1216 unsigned* __g_end = __g;
1217 unsigned __dc = 0;
1218 bool __in_units = true;
1219 char __exp = 'E';
1220 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001221 if (this->__stage2_float_loop(*__b, __in_units, __exp, __a, __a_end,
1222 __decimal_point, __thousands_sep,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001223 __grouping, __g, __g_end,
1224 __dc, __atoms))
1225 break;
1226 if (__grouping.size() != 0 && __in_units && __g_end-__g < __num_get_base::__num_get_buf_sz)
1227 *__g_end++ = __dc;
1228 // Stage 3
1229 __v = __num_get_float<double>(__a, __a_end, __err);
1230 // Digit grouping checked
1231 __check_grouping(__grouping, __g, __g_end, __err);
1232 // EOF checked
1233 if (__b == __e)
1234 __err |= ios_base::eofbit;
1235 return __b;
1236}
1237
1238template <class _CharT, class _InputIterator>
1239_InputIterator
1240num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1241 ios_base& __iob,
1242 ios_base::iostate& __err,
1243 long double& __v) const
1244{
1245 // Stage 1, nothing to do
1246 // Stage 2
1247 char_type __atoms[32];
1248 char_type __decimal_point;
1249 char_type __thousands_sep;
Howard Hinnant324bb032010-08-22 00:02:43 +00001250 string __grouping = this->__stage2_float_prep(__iob, __atoms,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001251 __decimal_point,
1252 __thousands_sep);
1253 char __a[__num_get_base::__num_get_buf_sz] = {0};
1254 char* __a_end = __a;
1255 unsigned __g[__num_get_base::__num_get_buf_sz];
1256 unsigned* __g_end = __g;
1257 unsigned __dc = 0;
1258 bool __in_units = true;
1259 char __exp = 'E';
1260 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001261 if (this->__stage2_float_loop(*__b, __in_units, __exp, __a, __a_end,
1262 __decimal_point, __thousands_sep,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001263 __grouping, __g, __g_end,
1264 __dc, __atoms))
1265 break;
1266 if (__grouping.size() != 0 && __in_units && __g_end-__g < __num_get_base::__num_get_buf_sz)
1267 *__g_end++ = __dc;
1268 // Stage 3
1269 __v = __num_get_float<long double>(__a, __a_end, __err);
1270 // Digit grouping checked
1271 __check_grouping(__grouping, __g, __g_end, __err);
1272 // EOF checked
1273 if (__b == __e)
1274 __err |= ios_base::eofbit;
1275 return __b;
1276}
1277
1278template <class _CharT, class _InputIterator>
1279_InputIterator
1280num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1281 ios_base& __iob,
1282 ios_base::iostate& __err,
1283 void*& __v) const
1284{
1285 // Stage 1
1286 int __base = 16;
1287 // Stage 2
1288 char_type __atoms[26];
Howard Hinnantec3773c2011-12-01 20:21:04 +00001289 char_type __thousands_sep = 0;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001290 string __grouping;
1291 use_facet<ctype<_CharT> >(__iob.getloc()).widen(__num_get_base::__src,
1292 __num_get_base::__src + 26, __atoms);
1293 char __a[__num_get_base::__num_get_buf_sz] = {0};
1294 char* __a_end = __a;
1295 unsigned __g[__num_get_base::__num_get_buf_sz];
1296 unsigned* __g_end = __g;
1297 unsigned __dc = 0;
1298 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001299 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
1300 __thousands_sep, __grouping,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001301 __g, __g_end, __atoms))
1302 break;
1303 // Stage 3
1304 __a[sizeof(__a)-1] = 0;
Howard Hinnant866569b2011-09-28 23:39:33 +00001305#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001306 if (sscanf_l(__a, _LIBCPP_GET_C_LOCALE, "%p", &__v) != 1)
Sean Huntf3907e62011-07-15 05:40:33 +00001307#else
1308 if (__sscanf_l(__a, __cloc(), "%p", &__v) != 1)
1309#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001310 __err = ios_base::failbit;
1311 // EOF checked
1312 if (__b == __e)
1313 __err |= ios_base::eofbit;
1314 return __b;
1315}
1316
1317extern template class num_get<char>;
1318extern template class num_get<wchar_t>;
1319
1320struct __num_put_base
1321{
1322protected:
1323 static void __format_int(char* __fmt, const char* __len, bool __signd,
1324 ios_base::fmtflags __flags);
1325 static bool __format_float(char* __fmt, const char* __len,
1326 ios_base::fmtflags __flags);
1327 static char* __identify_padding(char* __nb, char* __ne,
1328 const ios_base& __iob);
1329};
1330
1331template <class _CharT>
1332struct __num_put
1333 : protected __num_put_base
1334{
1335 static void __widen_and_group_int(char* __nb, char* __np, char* __ne,
1336 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1337 const locale& __loc);
1338 static void __widen_and_group_float(char* __nb, char* __np, char* __ne,
1339 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1340 const locale& __loc);
1341};
1342
1343template <class _CharT>
1344void
1345__num_put<_CharT>::__widen_and_group_int(char* __nb, char* __np, char* __ne,
1346 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1347 const locale& __loc)
1348{
1349 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> > (__loc);
1350 const numpunct<_CharT>& __npt = use_facet<numpunct<_CharT> >(__loc);
1351 string __grouping = __npt.grouping();
1352 if (__grouping.empty())
1353 {
1354 __ct.widen(__nb, __ne, __ob);
1355 __oe = __ob + (__ne - __nb);
1356 }
1357 else
1358 {
1359 __oe = __ob;
1360 char* __nf = __nb;
1361 if (*__nf == '-' || *__nf == '+')
1362 *__oe++ = __ct.widen(*__nf++);
1363 if (__ne - __nf >= 2 && __nf[0] == '0' && (__nf[1] == 'x' ||
1364 __nf[1] == 'X'))
1365 {
1366 *__oe++ = __ct.widen(*__nf++);
1367 *__oe++ = __ct.widen(*__nf++);
1368 }
1369 reverse(__nf, __ne);
1370 _CharT __thousands_sep = __npt.thousands_sep();
1371 unsigned __dc = 0;
1372 unsigned __dg = 0;
1373 for (char* __p = __nf; __p < __ne; ++__p)
1374 {
1375 if (static_cast<unsigned>(__grouping[__dg]) > 0 &&
1376 __dc == static_cast<unsigned>(__grouping[__dg]))
1377 {
1378 *__oe++ = __thousands_sep;
1379 __dc = 0;
1380 if (__dg < __grouping.size()-1)
1381 ++__dg;
1382 }
1383 *__oe++ = __ct.widen(*__p);
1384 ++__dc;
1385 }
1386 reverse(__ob + (__nf - __nb), __oe);
1387 }
1388 if (__np == __ne)
1389 __op = __oe;
1390 else
1391 __op = __ob + (__np - __nb);
1392}
1393
1394template <class _CharT>
1395void
1396__num_put<_CharT>::__widen_and_group_float(char* __nb, char* __np, char* __ne,
1397 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1398 const locale& __loc)
1399{
1400 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> > (__loc);
1401 const numpunct<_CharT>& __npt = use_facet<numpunct<_CharT> >(__loc);
1402 string __grouping = __npt.grouping();
1403 __oe = __ob;
1404 char* __nf = __nb;
1405 if (*__nf == '-' || *__nf == '+')
1406 *__oe++ = __ct.widen(*__nf++);
1407 char* __ns;
1408 if (__ne - __nf >= 2 && __nf[0] == '0' && (__nf[1] == 'x' ||
1409 __nf[1] == 'X'))
1410 {
1411 *__oe++ = __ct.widen(*__nf++);
1412 *__oe++ = __ct.widen(*__nf++);
1413 for (__ns = __nf; __ns < __ne; ++__ns)
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001414 if (!isxdigit_l(*__ns, _LIBCPP_GET_C_LOCALE))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001415 break;
1416 }
1417 else
1418 {
1419 for (__ns = __nf; __ns < __ne; ++__ns)
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001420 if (!isdigit_l(*__ns, _LIBCPP_GET_C_LOCALE))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001421 break;
1422 }
1423 if (__grouping.empty())
1424 {
1425 __ct.widen(__nf, __ns, __oe);
1426 __oe += __ns - __nf;
1427 }
1428 else
1429 {
1430 reverse(__nf, __ns);
1431 _CharT __thousands_sep = __npt.thousands_sep();
1432 unsigned __dc = 0;
1433 unsigned __dg = 0;
1434 for (char* __p = __nf; __p < __ns; ++__p)
1435 {
1436 if (__grouping[__dg] > 0 && __dc == static_cast<unsigned>(__grouping[__dg]))
1437 {
1438 *__oe++ = __thousands_sep;
1439 __dc = 0;
1440 if (__dg < __grouping.size()-1)
1441 ++__dg;
1442 }
1443 *__oe++ = __ct.widen(*__p);
1444 ++__dc;
1445 }
1446 reverse(__ob + (__nf - __nb), __oe);
1447 }
1448 for (__nf = __ns; __nf < __ne; ++__nf)
1449 {
1450 if (*__nf == '.')
1451 {
1452 *__oe++ = __npt.decimal_point();
1453 ++__nf;
1454 break;
1455 }
1456 else
1457 *__oe++ = __ct.widen(*__nf);
1458 }
1459 __ct.widen(__nf, __ne, __oe);
1460 __oe += __ne - __nf;
1461 if (__np == __ne)
1462 __op = __oe;
1463 else
1464 __op = __ob + (__np - __nb);
1465}
1466
Howard Hinnantec3773c2011-12-01 20:21:04 +00001467extern template struct __num_put<char>;
1468extern template struct __num_put<wchar_t>;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001469
1470template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00001471class _LIBCPP_VISIBLE num_put
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001472 : public locale::facet,
1473 private __num_put<_CharT>
1474{
1475public:
1476 typedef _CharT char_type;
1477 typedef _OutputIterator iter_type;
1478
1479 _LIBCPP_ALWAYS_INLINE
1480 explicit num_put(size_t __refs = 0)
1481 : locale::facet(__refs) {}
1482
1483 _LIBCPP_ALWAYS_INLINE
1484 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1485 bool __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 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 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 unsigned long __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 unsigned long long __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 double __v) const
1521 {
1522 return do_put(__s, __iob, __fl, __v);
1523 }
1524
1525 _LIBCPP_ALWAYS_INLINE
1526 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1527 long double __v) const
1528 {
1529 return do_put(__s, __iob, __fl, __v);
1530 }
1531
1532 _LIBCPP_ALWAYS_INLINE
1533 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1534 const void* __v) const
1535 {
1536 return do_put(__s, __iob, __fl, __v);
1537 }
1538
1539 static locale::id id;
1540
1541protected:
Howard Hinnant82894812010-09-22 16:48:34 +00001542 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001543 ~num_put() {}
1544
1545 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1546 bool __v) const;
1547 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1548 long __v) const;
1549 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1550 long long __v) const;
1551 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1552 unsigned long) const;
1553 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1554 unsigned long long) const;
1555 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1556 double __v) const;
1557 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1558 long double __v) const;
1559 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1560 const void* __v) const;
1561};
1562
1563template <class _CharT, class _OutputIterator>
1564locale::id
1565num_put<_CharT, _OutputIterator>::id;
1566
1567template <class _CharT, class _OutputIterator>
1568_LIBCPP_HIDDEN
1569_OutputIterator
1570__pad_and_output(_OutputIterator __s,
1571 const _CharT* __ob, const _CharT* __op, const _CharT* __oe,
1572 ios_base& __iob, _CharT __fl)
1573{
1574 streamsize __sz = __oe - __ob;
1575 streamsize __ns = __iob.width();
1576 if (__ns > __sz)
1577 __ns -= __sz;
1578 else
1579 __ns = 0;
1580 for (;__ob < __op; ++__ob, ++__s)
1581 *__s = *__ob;
1582 for (; __ns; --__ns, ++__s)
1583 *__s = __fl;
1584 for (; __ob < __oe; ++__ob, ++__s)
1585 *__s = *__ob;
1586 __iob.width(0);
1587 return __s;
1588}
1589
1590template <class _CharT, class _OutputIterator>
1591_OutputIterator
1592num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1593 char_type __fl, bool __v) const
1594{
1595 if ((__iob.flags() & ios_base::boolalpha) == 0)
1596 return do_put(__s, __iob, __fl, (unsigned long)__v);
1597 const numpunct<char_type>& __np = use_facet<numpunct<char_type> >(__iob.getloc());
1598 typedef typename numpunct<char_type>::string_type string_type;
1599 string_type __nm = __v ? __np.truename() : __np.falsename();
1600 for (typename string_type::iterator __i = __nm.begin(); __i != __nm.end(); ++__i, ++__s)
1601 *__s = *__i;
1602 return __s;
1603}
1604
1605template <class _CharT, class _OutputIterator>
1606_OutputIterator
1607num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1608 char_type __fl, long __v) const
1609{
1610 // Stage 1 - Get number in narrow char
1611 char __fmt[6] = {'%', 0};
1612 const char* __len = "l";
1613 this->__format_int(__fmt+1, __len, true, __iob.flags());
1614 const unsigned __nbuf = (numeric_limits<long>::digits / 3)
1615 + ((numeric_limits<long>::digits % 3) != 0)
1616 + 1;
1617 char __nar[__nbuf];
Howard Hinnant866569b2011-09-28 23:39:33 +00001618#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001619 int __nc = sprintf_l(__nar, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001620#else
1621 int __nc = __sprintf_l(__nar, __cloc(), __fmt, __v);
1622#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001623 char* __ne = __nar + __nc;
1624 char* __np = this->__identify_padding(__nar, __ne, __iob);
1625 // Stage 2 - Widen __nar while adding thousands separators
1626 char_type __o[2*(__nbuf-1) - 1];
1627 char_type* __op; // pad here
1628 char_type* __oe; // end of output
1629 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1630 // [__o, __oe) contains thousands_sep'd wide number
1631 // Stage 3 & 4
1632 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1633}
1634
1635template <class _CharT, class _OutputIterator>
1636_OutputIterator
1637num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1638 char_type __fl, long long __v) const
1639{
1640 // Stage 1 - Get number in narrow char
1641 char __fmt[8] = {'%', 0};
1642 const char* __len = "ll";
1643 this->__format_int(__fmt+1, __len, true, __iob.flags());
1644 const unsigned __nbuf = (numeric_limits<long long>::digits / 3)
1645 + ((numeric_limits<long long>::digits % 3) != 0)
1646 + 1;
1647 char __nar[__nbuf];
Howard Hinnant866569b2011-09-28 23:39:33 +00001648#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001649 int __nc = sprintf_l(__nar, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001650#else
1651 int __nc = __sprintf_l(__nar, __cloc(), __fmt, __v);
1652#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001653 char* __ne = __nar + __nc;
1654 char* __np = this->__identify_padding(__nar, __ne, __iob);
1655 // Stage 2 - Widen __nar while adding thousands separators
1656 char_type __o[2*(__nbuf-1) - 1];
1657 char_type* __op; // pad here
1658 char_type* __oe; // end of output
1659 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1660 // [__o, __oe) contains thousands_sep'd wide number
1661 // Stage 3 & 4
1662 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1663}
1664
1665template <class _CharT, class _OutputIterator>
1666_OutputIterator
1667num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1668 char_type __fl, unsigned long __v) const
1669{
1670 // Stage 1 - Get number in narrow char
1671 char __fmt[6] = {'%', 0};
1672 const char* __len = "l";
1673 this->__format_int(__fmt+1, __len, false, __iob.flags());
1674 const unsigned __nbuf = (numeric_limits<unsigned long>::digits / 3)
1675 + ((numeric_limits<unsigned long>::digits % 3) != 0)
1676 + 1;
1677 char __nar[__nbuf];
Howard Hinnant866569b2011-09-28 23:39:33 +00001678#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001679 int __nc = sprintf_l(__nar, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001680#else
1681 int __nc = __sprintf_l(__nar, __cloc(), __fmt, __v);
1682#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001683 char* __ne = __nar + __nc;
1684 char* __np = this->__identify_padding(__nar, __ne, __iob);
1685 // Stage 2 - Widen __nar while adding thousands separators
1686 char_type __o[2*(__nbuf-1) - 1];
1687 char_type* __op; // pad here
1688 char_type* __oe; // end of output
1689 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1690 // [__o, __oe) contains thousands_sep'd wide number
1691 // Stage 3 & 4
1692 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1693}
1694
1695template <class _CharT, class _OutputIterator>
1696_OutputIterator
1697num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1698 char_type __fl, unsigned long long __v) const
1699{
1700 // Stage 1 - Get number in narrow char
1701 char __fmt[8] = {'%', 0};
1702 const char* __len = "ll";
1703 this->__format_int(__fmt+1, __len, false, __iob.flags());
1704 const unsigned __nbuf = (numeric_limits<unsigned long long>::digits / 3)
1705 + ((numeric_limits<unsigned long long>::digits % 3) != 0)
1706 + 1;
1707 char __nar[__nbuf];
Howard Hinnant866569b2011-09-28 23:39:33 +00001708#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001709 int __nc = sprintf_l(__nar, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001710#else
1711 int __nc = __sprintf_l(__nar, __cloc(), __fmt, __v);
1712#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001713 char* __ne = __nar + __nc;
1714 char* __np = this->__identify_padding(__nar, __ne, __iob);
1715 // Stage 2 - Widen __nar while adding thousands separators
1716 char_type __o[2*(__nbuf-1) - 1];
1717 char_type* __op; // pad here
1718 char_type* __oe; // end of output
1719 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1720 // [__o, __oe) contains thousands_sep'd wide number
1721 // Stage 3 & 4
1722 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1723}
1724
1725template <class _CharT, class _OutputIterator>
1726_OutputIterator
1727num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1728 char_type __fl, double __v) const
1729{
1730 // Stage 1 - Get number in narrow char
1731 char __fmt[8] = {'%', 0};
1732 const char* __len = "";
1733 bool __specify_precision = this->__format_float(__fmt+1, __len, __iob.flags());
1734 const unsigned __nbuf = 30;
1735 char __nar[__nbuf];
1736 char* __nb = __nar;
1737 int __nc;
1738 if (__specify_precision)
Howard Hinnant866569b2011-09-28 23:39:33 +00001739#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001740 __nc = snprintf_l(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt,
Howard Hinnantadff4892010-05-24 17:49:41 +00001741 (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001742#else
1743 __nc = __snprintf_l(__nb, __nbuf, __cloc(), __fmt,
1744 (int)__iob.precision(), __v);
1745#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001746 else
Howard Hinnant866569b2011-09-28 23:39:33 +00001747#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001748 __nc = snprintf_l(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001749#else
1750 __nc = __snprintf_l(__nb, __nbuf, __cloc(), __fmt, __v);
1751#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001752 unique_ptr<char, void(*)(void*)> __nbh(0, free);
1753 if (__nc > static_cast<int>(__nbuf-1))
1754 {
1755 if (__specify_precision)
Howard Hinnant866569b2011-09-28 23:39:33 +00001756#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001757 __nc = asprintf_l(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001758#else
1759 __nc = __asprintf_l(&__nb, __cloc(), __fmt,
David Chisnallc512df12011-09-21 08:39:44 +00001760 (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001761#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001762 else
Howard Hinnant866569b2011-09-28 23:39:33 +00001763#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001764 __nc = asprintf_l(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001765#else
David Chisnallc512df12011-09-21 08:39:44 +00001766 __nc = __asprintf_l(&__nb, __cloc(), __fmt, (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001767#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001768 if (__nb == 0)
1769 __throw_bad_alloc();
1770 __nbh.reset(__nb);
1771 }
1772 char* __ne = __nb + __nc;
1773 char* __np = this->__identify_padding(__nb, __ne, __iob);
1774 // Stage 2 - Widen __nar while adding thousands separators
1775 char_type __o[2*(__nbuf-1) - 1];
1776 char_type* __ob = __o;
1777 unique_ptr<char_type, void(*)(void*)> __obh(0, free);
1778 if (__nb != __nar)
1779 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00001780 __ob = (char_type*)malloc(2*static_cast<size_t>(__nc)*sizeof(char_type));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001781 if (__ob == 0)
1782 __throw_bad_alloc();
1783 __obh.reset(__ob);
1784 }
1785 char_type* __op; // pad here
1786 char_type* __oe; // end of output
1787 this->__widen_and_group_float(__nb, __np, __ne, __ob, __op, __oe, __iob.getloc());
1788 // [__o, __oe) contains thousands_sep'd wide number
1789 // Stage 3 & 4
1790 __s = __pad_and_output(__s, __ob, __op, __oe, __iob, __fl);
1791 return __s;
1792}
1793
1794template <class _CharT, class _OutputIterator>
1795_OutputIterator
1796num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1797 char_type __fl, long double __v) const
1798{
1799 // Stage 1 - Get number in narrow char
1800 char __fmt[8] = {'%', 0};
1801 const char* __len = "L";
1802 bool __specify_precision = this->__format_float(__fmt+1, __len, __iob.flags());
1803 const unsigned __nbuf = 30;
1804 char __nar[__nbuf];
1805 char* __nb = __nar;
1806 int __nc;
1807 if (__specify_precision)
Howard Hinnant866569b2011-09-28 23:39:33 +00001808#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001809 __nc = snprintf_l(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt,
Howard Hinnantadff4892010-05-24 17:49:41 +00001810 (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001811#else
1812 __nc = __snprintf_l(__nb, __nbuf, __cloc(), __fmt,
1813 (int)__iob.precision(), __v);
1814#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001815 else
Howard Hinnant866569b2011-09-28 23:39:33 +00001816#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001817 __nc = snprintf_l(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001818#else
1819 __nc = __snprintf_l(__nb, __nbuf, __cloc(), __fmt, __v);
1820#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001821 unique_ptr<char, void(*)(void*)> __nbh(0, free);
1822 if (__nc > static_cast<int>(__nbuf-1))
1823 {
1824 if (__specify_precision)
Howard Hinnant866569b2011-09-28 23:39:33 +00001825#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001826 __nc = asprintf_l(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001827#else
1828 __nc = __asprintf_l(&__nb, __cloc(), __fmt,
David Chisnallc512df12011-09-21 08:39:44 +00001829 (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001830#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001831 else
Howard Hinnant866569b2011-09-28 23:39:33 +00001832#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001833 __nc = asprintf_l(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001834#else
David Chisnallc512df12011-09-21 08:39:44 +00001835 __nc = __asprintf_l(&__nb, __cloc(), __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001836#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001837 if (__nb == 0)
1838 __throw_bad_alloc();
1839 __nbh.reset(__nb);
1840 }
1841 char* __ne = __nb + __nc;
1842 char* __np = this->__identify_padding(__nb, __ne, __iob);
1843 // Stage 2 - Widen __nar while adding thousands separators
1844 char_type __o[2*(__nbuf-1) - 1];
1845 char_type* __ob = __o;
1846 unique_ptr<char_type, void(*)(void*)> __obh(0, free);
1847 if (__nb != __nar)
1848 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00001849 __ob = (char_type*)malloc(2*static_cast<size_t>(__nc)*sizeof(char_type));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001850 if (__ob == 0)
1851 __throw_bad_alloc();
1852 __obh.reset(__ob);
1853 }
1854 char_type* __op; // pad here
1855 char_type* __oe; // end of output
1856 this->__widen_and_group_float(__nb, __np, __ne, __ob, __op, __oe, __iob.getloc());
1857 // [__o, __oe) contains thousands_sep'd wide number
1858 // Stage 3 & 4
1859 __s = __pad_and_output(__s, __ob, __op, __oe, __iob, __fl);
1860 return __s;
1861}
1862
1863template <class _CharT, class _OutputIterator>
1864_OutputIterator
1865num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1866 char_type __fl, const void* __v) const
1867{
1868 // Stage 1 - Get pointer in narrow char
1869 char __fmt[6] = "%p";
1870 const unsigned __nbuf = 20;
1871 char __nar[__nbuf];
Howard Hinnant866569b2011-09-28 23:39:33 +00001872#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001873 int __nc = sprintf_l(__nar, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001874#else
1875 int __nc = __sprintf_l(__nar, __cloc(), __fmt, __v);
1876#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001877 char* __ne = __nar + __nc;
1878 char* __np = this->__identify_padding(__nar, __ne, __iob);
1879 // Stage 2 - Widen __nar
1880 char_type __o[2*(__nbuf-1) - 1];
1881 char_type* __op; // pad here
1882 char_type* __oe; // end of output
1883 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
1884 __ct.widen(__nar, __ne, __o);
1885 __oe = __o + (__ne - __nar);
1886 if (__np == __ne)
1887 __op = __oe;
1888 else
1889 __op = __o + (__np - __nar);
1890 // [__o, __oe) contains wide number
1891 // Stage 3 & 4
1892 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1893}
1894
1895extern template class num_put<char>;
1896extern template class num_put<wchar_t>;
1897
1898template <class _CharT, class _InputIterator>
1899_LIBCPP_HIDDEN
1900int
1901__get_up_to_n_digits(_InputIterator& __b, _InputIterator __e,
1902 ios_base::iostate& __err, const ctype<_CharT>& __ct, int __n)
1903{
1904 // Precondition: __n >= 1
1905 if (__b == __e)
1906 {
1907 __err |= ios_base::eofbit | ios_base::failbit;
1908 return 0;
1909 }
1910 // get first digit
1911 _CharT __c = *__b;
1912 if (!__ct.is(ctype_base::digit, __c))
1913 {
1914 __err |= ios_base::failbit;
1915 return 0;
1916 }
1917 int __r = __ct.narrow(__c, 0) - '0';
1918 for (++__b, --__n; __b != __e && __n > 0; ++__b, --__n)
1919 {
1920 // get next digit
1921 __c = *__b;
1922 if (!__ct.is(ctype_base::digit, __c))
1923 return __r;
1924 __r = __r * 10 + __ct.narrow(__c, 0) - '0';
1925 }
1926 if (__b == __e)
1927 __err |= ios_base::eofbit;
1928 return __r;
1929}
1930
Howard Hinnant82894812010-09-22 16:48:34 +00001931class _LIBCPP_VISIBLE time_base
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001932{
1933public:
1934 enum dateorder {no_order, dmy, mdy, ymd, ydm};
1935};
1936
1937template <class _CharT>
Howard Hinnant2d72b1e2010-12-17 14:46:43 +00001938class __time_get_c_storage // purposefully not decorated
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001939{
1940protected:
1941 typedef basic_string<_CharT> string_type;
1942
1943 virtual const string_type* __weeks() const;
1944 virtual const string_type* __months() const;
1945 virtual const string_type* __am_pm() const;
1946 virtual const string_type& __c() const;
1947 virtual const string_type& __r() const;
1948 virtual const string_type& __x() const;
1949 virtual const string_type& __X() const;
1950};
1951
1952template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00001953class _LIBCPP_VISIBLE time_get
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001954 : public locale::facet,
1955 public time_base,
1956 private __time_get_c_storage<_CharT>
1957{
1958public:
1959 typedef _CharT char_type;
1960 typedef _InputIterator iter_type;
1961 typedef time_base::dateorder dateorder;
1962 typedef basic_string<char_type> string_type;
1963
1964 _LIBCPP_ALWAYS_INLINE
1965 explicit time_get(size_t __refs = 0)
1966 : locale::facet(__refs) {}
1967
1968 _LIBCPP_ALWAYS_INLINE
1969 dateorder date_order() const
1970 {
1971 return this->do_date_order();
1972 }
1973
1974 _LIBCPP_ALWAYS_INLINE
1975 iter_type get_time(iter_type __b, iter_type __e, ios_base& __iob,
1976 ios_base::iostate& __err, tm* __tm) const
1977 {
1978 return do_get_time(__b, __e, __iob, __err, __tm);
1979 }
1980
1981 _LIBCPP_ALWAYS_INLINE
1982 iter_type get_date(iter_type __b, iter_type __e, ios_base& __iob,
1983 ios_base::iostate& __err, tm* __tm) const
1984 {
1985 return do_get_date(__b, __e, __iob, __err, __tm);
1986 }
1987
1988 _LIBCPP_ALWAYS_INLINE
1989 iter_type get_weekday(iter_type __b, iter_type __e, ios_base& __iob,
1990 ios_base::iostate& __err, tm* __tm) const
1991 {
1992 return do_get_weekday(__b, __e, __iob, __err, __tm);
1993 }
1994
1995 _LIBCPP_ALWAYS_INLINE
1996 iter_type get_monthname(iter_type __b, iter_type __e, ios_base& __iob,
1997 ios_base::iostate& __err, tm* __tm) const
1998 {
1999 return do_get_monthname(__b, __e, __iob, __err, __tm);
2000 }
2001
2002 _LIBCPP_ALWAYS_INLINE
2003 iter_type get_year(iter_type __b, iter_type __e, ios_base& __iob,
2004 ios_base::iostate& __err, tm* __tm) const
2005 {
2006 return do_get_year(__b, __e, __iob, __err, __tm);
2007 }
2008
2009 _LIBCPP_ALWAYS_INLINE
2010 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
2011 ios_base::iostate& __err, tm *__tm,
2012 char __fmt, char __mod = 0) const
2013 {
2014 return do_get(__b, __e, __iob, __err, __tm, __fmt, __mod);
2015 }
2016
2017 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
2018 ios_base::iostate& __err, tm* __tm,
2019 const char_type* __fmtb, const char_type* __fmte) const;
2020
2021 static locale::id id;
2022
2023protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002024 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002025 ~time_get() {}
2026
2027 virtual dateorder do_date_order() const;
2028 virtual iter_type do_get_time(iter_type __b, iter_type __e, ios_base& __iob,
2029 ios_base::iostate& __err, tm* __tm) const;
2030 virtual iter_type do_get_date(iter_type __b, iter_type __e, ios_base& __iob,
2031 ios_base::iostate& __err, tm* __tm) const;
2032 virtual iter_type do_get_weekday(iter_type __b, iter_type __e, ios_base& __iob,
2033 ios_base::iostate& __err, tm* __tm) const;
2034 virtual iter_type do_get_monthname(iter_type __b, iter_type __e, ios_base& __iob,
2035 ios_base::iostate& __err, tm* __tm) const;
2036 virtual iter_type do_get_year(iter_type __b, iter_type __e, ios_base& __iob,
2037 ios_base::iostate& __err, tm* __tm) const;
2038 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
2039 ios_base::iostate& __err, tm* __tm,
2040 char __fmt, char __mod) const;
2041private:
2042 void __get_white_space(iter_type& __b, iter_type __e,
2043 ios_base::iostate& __err, const ctype<char_type>& __ct) const;
2044 void __get_percent(iter_type& __b, iter_type __e, ios_base::iostate& __err,
2045 const ctype<char_type>& __ct) const;
2046
2047 void __get_weekdayname(int& __m,
2048 iter_type& __b, iter_type __e,
2049 ios_base::iostate& __err,
2050 const ctype<char_type>& __ct) const;
2051 void __get_monthname(int& __m,
2052 iter_type& __b, iter_type __e,
2053 ios_base::iostate& __err,
2054 const ctype<char_type>& __ct) const;
2055 void __get_day(int& __d,
2056 iter_type& __b, iter_type __e,
2057 ios_base::iostate& __err,
2058 const ctype<char_type>& __ct) const;
2059 void __get_month(int& __m,
2060 iter_type& __b, iter_type __e,
2061 ios_base::iostate& __err,
2062 const ctype<char_type>& __ct) const;
2063 void __get_year(int& __y,
2064 iter_type& __b, iter_type __e,
2065 ios_base::iostate& __err,
2066 const ctype<char_type>& __ct) const;
2067 void __get_year4(int& __y,
2068 iter_type& __b, iter_type __e,
2069 ios_base::iostate& __err,
2070 const ctype<char_type>& __ct) const;
2071 void __get_hour(int& __d,
2072 iter_type& __b, iter_type __e,
2073 ios_base::iostate& __err,
2074 const ctype<char_type>& __ct) const;
2075 void __get_12_hour(int& __h,
2076 iter_type& __b, iter_type __e,
2077 ios_base::iostate& __err,
2078 const ctype<char_type>& __ct) const;
2079 void __get_am_pm(int& __h,
2080 iter_type& __b, iter_type __e,
2081 ios_base::iostate& __err,
2082 const ctype<char_type>& __ct) const;
2083 void __get_minute(int& __m,
2084 iter_type& __b, iter_type __e,
2085 ios_base::iostate& __err,
2086 const ctype<char_type>& __ct) const;
2087 void __get_second(int& __s,
2088 iter_type& __b, iter_type __e,
2089 ios_base::iostate& __err,
2090 const ctype<char_type>& __ct) const;
2091 void __get_weekday(int& __w,
2092 iter_type& __b, iter_type __e,
2093 ios_base::iostate& __err,
2094 const ctype<char_type>& __ct) const;
2095 void __get_day_year_num(int& __w,
2096 iter_type& __b, iter_type __e,
2097 ios_base::iostate& __err,
2098 const ctype<char_type>& __ct) const;
2099};
2100
2101template <class _CharT, class _InputIterator>
2102locale::id
2103time_get<_CharT, _InputIterator>::id;
2104
2105// time_get primatives
2106
2107template <class _CharT, class _InputIterator>
2108void
2109time_get<_CharT, _InputIterator>::__get_weekdayname(int& __w,
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* __wk = this->__weeks();
Howard Hinnantec3773c2011-12-01 20:21:04 +00002116 ptrdiff_t __i = __scan_keyword(__b, __e, __wk, __wk+14, __ct, __err, false) - __wk;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002117 if (__i < 14)
2118 __w = __i % 7;
2119}
2120
2121template <class _CharT, class _InputIterator>
2122void
2123time_get<_CharT, _InputIterator>::__get_monthname(int& __m,
2124 iter_type& __b, iter_type __e,
2125 ios_base::iostate& __err,
2126 const ctype<char_type>& __ct) const
2127{
2128 // Note: ignoring case comes from the POSIX strptime spec
2129 const string_type* __month = this->__months();
Howard Hinnantec3773c2011-12-01 20:21:04 +00002130 ptrdiff_t __i = __scan_keyword(__b, __e, __month, __month+24, __ct, __err, false) - __month;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002131 if (__i < 24)
2132 __m = __i % 12;
2133}
2134
2135template <class _CharT, class _InputIterator>
2136void
2137time_get<_CharT, _InputIterator>::__get_day(int& __d,
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);
2143 if (!(__err & ios_base::failbit) && 1 <= __t && __t <= 31)
2144 __d = __t;
2145 else
2146 __err |= ios_base::failbit;
2147}
2148
2149template <class _CharT, class _InputIterator>
2150void
2151time_get<_CharT, _InputIterator>::__get_month(int& __m,
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, 2) - 1;
2157 if (!(__err & ios_base::failbit) && __t <= 11)
2158 __m = __t;
2159 else
2160 __err |= ios_base::failbit;
2161}
2162
2163template <class _CharT, class _InputIterator>
2164void
2165time_get<_CharT, _InputIterator>::__get_year(int& __y,
2166 iter_type& __b, iter_type __e,
2167 ios_base::iostate& __err,
2168 const ctype<char_type>& __ct) const
2169{
2170 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 4);
2171 if (!(__err & ios_base::failbit))
2172 {
2173 if (__t < 69)
2174 __t += 2000;
2175 else if (69 <= __t && __t <= 99)
2176 __t += 1900;
2177 __y = __t - 1900;
2178 }
2179}
2180
2181template <class _CharT, class _InputIterator>
2182void
2183time_get<_CharT, _InputIterator>::__get_year4(int& __y,
2184 iter_type& __b, iter_type __e,
2185 ios_base::iostate& __err,
2186 const ctype<char_type>& __ct) const
2187{
2188 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 4);
2189 if (!(__err & ios_base::failbit))
2190 __y = __t - 1900;
2191}
2192
2193template <class _CharT, class _InputIterator>
2194void
2195time_get<_CharT, _InputIterator>::__get_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) && __t <= 23)
2202 __h = __t;
2203 else
2204 __err |= ios_base::failbit;
2205}
2206
2207template <class _CharT, class _InputIterator>
2208void
2209time_get<_CharT, _InputIterator>::__get_12_hour(int& __h,
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) && 1 <= __t && __t <= 12)
2216 __h = __t;
2217 else
2218 __err |= ios_base::failbit;
2219}
2220
2221template <class _CharT, class _InputIterator>
2222void
2223time_get<_CharT, _InputIterator>::__get_minute(int& __m,
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 <= 59)
2230 __m = __t;
2231 else
2232 __err |= ios_base::failbit;
2233}
2234
2235template <class _CharT, class _InputIterator>
2236void
2237time_get<_CharT, _InputIterator>::__get_second(int& __s,
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, 2);
2243 if (!(__err & ios_base::failbit) && __t <= 60)
2244 __s = __t;
2245 else
2246 __err |= ios_base::failbit;
2247}
2248
2249template <class _CharT, class _InputIterator>
2250void
2251time_get<_CharT, _InputIterator>::__get_weekday(int& __w,
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, 1);
2257 if (!(__err & ios_base::failbit) && __t <= 6)
2258 __w = __t;
2259 else
2260 __err |= ios_base::failbit;
2261}
2262
2263template <class _CharT, class _InputIterator>
2264void
2265time_get<_CharT, _InputIterator>::__get_day_year_num(int& __d,
2266 iter_type& __b, iter_type __e,
2267 ios_base::iostate& __err,
2268 const ctype<char_type>& __ct) const
2269{
2270 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 3);
2271 if (!(__err & ios_base::failbit) && __t <= 365)
2272 __d = __t;
2273 else
2274 __err |= ios_base::failbit;
2275}
2276
2277template <class _CharT, class _InputIterator>
2278void
2279time_get<_CharT, _InputIterator>::__get_white_space(iter_type& __b, iter_type __e,
2280 ios_base::iostate& __err,
2281 const ctype<char_type>& __ct) const
2282{
2283 for (; __b != __e && __ct.is(ctype_base::space, *__b); ++__b)
2284 ;
2285 if (__b == __e)
2286 __err |= ios_base::eofbit;
2287}
2288
2289template <class _CharT, class _InputIterator>
2290void
2291time_get<_CharT, _InputIterator>::__get_am_pm(int& __h,
2292 iter_type& __b, iter_type __e,
2293 ios_base::iostate& __err,
2294 const ctype<char_type>& __ct) const
2295{
2296 const string_type* __ap = this->__am_pm();
2297 if (__ap[0].size() + __ap[1].size() == 0)
2298 {
2299 __err |= ios_base::failbit;
2300 return;
2301 }
Howard Hinnantec3773c2011-12-01 20:21:04 +00002302 ptrdiff_t __i = __scan_keyword(__b, __e, __ap, __ap+2, __ct, __err, false) - __ap;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002303 if (__i == 0 && __h == 12)
2304 __h = 0;
2305 else if (__i == 1 && __h < 12)
2306 __h += 12;
2307}
2308
2309template <class _CharT, class _InputIterator>
2310void
2311time_get<_CharT, _InputIterator>::__get_percent(iter_type& __b, iter_type __e,
2312 ios_base::iostate& __err,
2313 const ctype<char_type>& __ct) const
2314{
2315 if (__b == __e)
2316 {
2317 __err |= ios_base::eofbit | ios_base::failbit;
2318 return;
2319 }
2320 if (__ct.narrow(*__b, 0) != '%')
2321 __err |= ios_base::failbit;
2322 else if(++__b == __e)
2323 __err |= ios_base::eofbit;
2324}
2325
2326// time_get end primatives
2327
2328template <class _CharT, class _InputIterator>
2329_InputIterator
2330time_get<_CharT, _InputIterator>::get(iter_type __b, iter_type __e,
2331 ios_base& __iob,
2332 ios_base::iostate& __err, tm* __tm,
2333 const char_type* __fmtb, const char_type* __fmte) const
2334{
2335 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2336 __err = ios_base::goodbit;
2337 while (__fmtb != __fmte && __err == ios_base::goodbit)
2338 {
2339 if (__b == __e)
2340 {
2341 __err = ios_base::failbit;
2342 break;
2343 }
2344 if (__ct.narrow(*__fmtb, 0) == '%')
2345 {
2346 if (++__fmtb == __fmte)
2347 {
2348 __err = ios_base::failbit;
2349 break;
2350 }
2351 char __cmd = __ct.narrow(*__fmtb, 0);
2352 char __opt = '\0';
2353 if (__cmd == 'E' || __cmd == '0')
2354 {
2355 if (++__fmtb == __fmte)
2356 {
2357 __err = ios_base::failbit;
2358 break;
2359 }
2360 __opt = __cmd;
2361 __cmd = __ct.narrow(*__fmtb, 0);
2362 }
2363 __b = do_get(__b, __e, __iob, __err, __tm, __cmd, __opt);
2364 ++__fmtb;
2365 }
2366 else if (__ct.is(ctype_base::space, *__fmtb))
2367 {
2368 for (++__fmtb; __fmtb != __fmte && __ct.is(ctype_base::space, *__fmtb); ++__fmtb)
2369 ;
2370 for ( ; __b != __e && __ct.is(ctype_base::space, *__b); ++__b)
2371 ;
2372 }
2373 else if (__ct.toupper(*__b) == __ct.toupper(*__fmtb))
2374 {
2375 ++__b;
2376 ++__fmtb;
2377 }
2378 else
2379 __err = ios_base::failbit;
2380 }
2381 if (__b == __e)
2382 __err |= ios_base::eofbit;
2383 return __b;
2384}
2385
2386template <class _CharT, class _InputIterator>
2387typename time_get<_CharT, _InputIterator>::dateorder
2388time_get<_CharT, _InputIterator>::do_date_order() const
2389{
2390 return mdy;
2391}
2392
2393template <class _CharT, class _InputIterator>
2394_InputIterator
2395time_get<_CharT, _InputIterator>::do_get_time(iter_type __b, iter_type __e,
2396 ios_base& __iob,
2397 ios_base::iostate& __err,
2398 tm* __tm) const
2399{
2400 const char_type __fmt[] = {'%', 'H', ':', '%', 'M', ':', '%', 'S'};
2401 return get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2402}
2403
2404template <class _CharT, class _InputIterator>
2405_InputIterator
2406time_get<_CharT, _InputIterator>::do_get_date(iter_type __b, iter_type __e,
2407 ios_base& __iob,
2408 ios_base::iostate& __err,
2409 tm* __tm) const
2410{
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002411 const string_type& __fmt = this->__x();
2412 return get(__b, __e, __iob, __err, __tm, __fmt.data(), __fmt.data() + __fmt.size());
2413}
2414
2415template <class _CharT, class _InputIterator>
2416_InputIterator
2417time_get<_CharT, _InputIterator>::do_get_weekday(iter_type __b, iter_type __e,
2418 ios_base& __iob,
2419 ios_base::iostate& __err,
2420 tm* __tm) const
2421{
2422 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2423 __get_weekdayname(__tm->tm_wday, __b, __e, __err, __ct);
2424 return __b;
2425}
2426
2427template <class _CharT, class _InputIterator>
2428_InputIterator
2429time_get<_CharT, _InputIterator>::do_get_monthname(iter_type __b, iter_type __e,
2430 ios_base& __iob,
2431 ios_base::iostate& __err,
2432 tm* __tm) const
2433{
2434 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2435 __get_monthname(__tm->tm_mon, __b, __e, __err, __ct);
2436 return __b;
2437}
2438
2439template <class _CharT, class _InputIterator>
2440_InputIterator
2441time_get<_CharT, _InputIterator>::do_get_year(iter_type __b, iter_type __e,
2442 ios_base& __iob,
2443 ios_base::iostate& __err,
2444 tm* __tm) const
2445{
2446 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2447 __get_year(__tm->tm_year, __b, __e, __err, __ct);
2448 return __b;
2449}
2450
2451template <class _CharT, class _InputIterator>
2452_InputIterator
2453time_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
2454 ios_base& __iob,
2455 ios_base::iostate& __err, tm* __tm,
2456 char __fmt, char) const
2457{
2458 __err = ios_base::goodbit;
2459 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2460 switch (__fmt)
2461 {
2462 case 'a':
2463 case 'A':
2464 __get_weekdayname(__tm->tm_wday, __b, __e, __err, __ct);
2465 break;
2466 case 'b':
2467 case 'B':
2468 case 'h':
2469 __get_monthname(__tm->tm_mon, __b, __e, __err, __ct);
2470 break;
2471 case 'c':
2472 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002473 const string_type& __fm = this->__c();
2474 __b = get(__b, __e, __iob, __err, __tm, __fm.data(), __fm.data() + __fm.size());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002475 }
2476 break;
2477 case 'd':
2478 case 'e':
2479 __get_day(__tm->tm_mday, __b, __e, __err, __ct);
2480 break;
2481 case 'D':
2482 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002483 const char_type __fm[] = {'%', 'm', '/', '%', 'd', '/', '%', 'y'};
2484 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm)/sizeof(__fm[0]));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002485 }
2486 break;
Howard Hinnant506b3642011-04-10 17:54:14 +00002487 case 'F':
2488 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002489 const char_type __fm[] = {'%', 'Y', '-', '%', 'm', '-', '%', 'd'};
2490 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm)/sizeof(__fm[0]));
Howard Hinnant506b3642011-04-10 17:54:14 +00002491 }
2492 break;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002493 case 'H':
2494 __get_hour(__tm->tm_hour, __b, __e, __err, __ct);
2495 break;
2496 case 'I':
2497 __get_12_hour(__tm->tm_hour, __b, __e, __err, __ct);
2498 break;
2499 case 'j':
2500 __get_day_year_num(__tm->tm_yday, __b, __e, __err, __ct);
2501 break;
2502 case 'm':
2503 __get_month(__tm->tm_mon, __b, __e, __err, __ct);
2504 break;
2505 case 'M':
2506 __get_minute(__tm->tm_min, __b, __e, __err, __ct);
2507 break;
2508 case 'n':
2509 case 't':
2510 __get_white_space(__b, __e, __err, __ct);
2511 break;
2512 case 'p':
2513 __get_am_pm(__tm->tm_hour, __b, __e, __err, __ct);
2514 break;
2515 case 'r':
2516 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002517 const char_type __fm[] = {'%', 'I', ':', '%', 'M', ':', '%', 'S', ' ', '%', 'p'};
2518 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm)/sizeof(__fm[0]));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002519 }
2520 break;
2521 case 'R':
2522 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002523 const char_type __fm[] = {'%', 'H', ':', '%', 'M'};
2524 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm)/sizeof(__fm[0]));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002525 }
2526 break;
2527 case 'S':
2528 __get_second(__tm->tm_sec, __b, __e, __err, __ct);
2529 break;
2530 case 'T':
2531 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002532 const char_type __fm[] = {'%', 'H', ':', '%', 'M', ':', '%', 'S'};
2533 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm)/sizeof(__fm[0]));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002534 }
2535 break;
2536 case 'w':
2537 __get_weekday(__tm->tm_wday, __b, __e, __err, __ct);
2538 break;
2539 case 'x':
2540 return do_get_date(__b, __e, __iob, __err, __tm);
2541 case 'X':
2542 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002543 const string_type& __fm = this->__X();
2544 __b = get(__b, __e, __iob, __err, __tm, __fm.data(), __fm.data() + __fm.size());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002545 }
2546 break;
2547 case 'y':
2548 __get_year(__tm->tm_year, __b, __e, __err, __ct);
2549 break;
2550 case 'Y':
2551 __get_year4(__tm->tm_year, __b, __e, __err, __ct);
2552 break;
2553 case '%':
2554 __get_percent(__b, __e, __err, __ct);
2555 break;
2556 default:
2557 __err |= ios_base::failbit;
2558 }
2559 return __b;
2560}
2561
2562extern template class time_get<char>;
2563extern template class time_get<wchar_t>;
2564
2565class __time_get
2566{
2567protected:
2568 locale_t __loc_;
2569
2570 __time_get(const char* __nm);
2571 __time_get(const string& __nm);
2572 ~__time_get();
2573};
2574
2575template <class _CharT>
2576class __time_get_storage
2577 : public __time_get
2578{
2579protected:
2580 typedef basic_string<_CharT> string_type;
2581
2582 string_type __weeks_[14];
2583 string_type __months_[24];
2584 string_type __am_pm_[2];
2585 string_type __c_;
2586 string_type __r_;
2587 string_type __x_;
2588 string_type __X_;
2589
2590 explicit __time_get_storage(const char* __nm);
2591 explicit __time_get_storage(const string& __nm);
2592
2593 _LIBCPP_ALWAYS_INLINE ~__time_get_storage() {}
2594
2595 time_base::dateorder __do_date_order() const;
2596
2597private:
2598 void init(const ctype<_CharT>&);
2599 string_type __analyze(char __fmt, const ctype<_CharT>&);
2600};
2601
2602template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00002603class _LIBCPP_VISIBLE time_get_byname
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002604 : public time_get<_CharT, _InputIterator>,
2605 private __time_get_storage<_CharT>
2606{
2607public:
2608 typedef time_base::dateorder dateorder;
2609 typedef _InputIterator iter_type;
2610 typedef _CharT char_type;
2611 typedef basic_string<char_type> string_type;
2612
Howard Hinnant82894812010-09-22 16:48:34 +00002613 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002614 explicit time_get_byname(const char* __nm, size_t __refs = 0)
2615 : time_get<_CharT, _InputIterator>(__refs),
2616 __time_get_storage<_CharT>(__nm) {}
Howard Hinnant82894812010-09-22 16:48:34 +00002617 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002618 explicit time_get_byname(const string& __nm, size_t __refs = 0)
2619 : time_get<_CharT, _InputIterator>(__refs),
2620 __time_get_storage<_CharT>(__nm) {}
2621
2622protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002623 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002624 ~time_get_byname() {}
2625
Howard Hinnant82894812010-09-22 16:48:34 +00002626 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002627 virtual dateorder do_date_order() const {return this->__do_date_order();}
2628private:
Howard Hinnant82894812010-09-22 16:48:34 +00002629 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002630 virtual const string_type* __weeks() const {return this->__weeks_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002631 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002632 virtual const string_type* __months() const {return this->__months_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002633 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002634 virtual const string_type* __am_pm() const {return this->__am_pm_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002635 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002636 virtual const string_type& __c() const {return this->__c_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002637 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002638 virtual const string_type& __r() const {return this->__r_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002639 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002640 virtual const string_type& __x() const {return this->__x_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002641 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002642 virtual const string_type& __X() const {return this->__X_;}
2643};
2644
2645extern template class time_get_byname<char>;
2646extern template class time_get_byname<wchar_t>;
2647
2648class __time_put
2649{
2650 locale_t __loc_;
2651protected:
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00002652 _LIBCPP_ALWAYS_INLINE __time_put() : __loc_(_LIBCPP_GET_C_LOCALE) {}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002653 __time_put(const char* __nm);
2654 __time_put(const string& __nm);
2655 ~__time_put();
2656 void __do_put(char* __nb, char*& __ne, const tm* __tm,
2657 char __fmt, char __mod) const;
2658 void __do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
2659 char __fmt, char __mod) const;
2660};
2661
2662template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00002663class _LIBCPP_VISIBLE time_put
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002664 : public locale::facet,
2665 private __time_put
2666{
2667public:
2668 typedef _CharT char_type;
2669 typedef _OutputIterator iter_type;
2670
2671 _LIBCPP_ALWAYS_INLINE
2672 explicit time_put(size_t __refs = 0)
2673 : locale::facet(__refs) {}
2674
2675 iter_type put(iter_type __s, ios_base& __iob, char_type __fl, const tm* __tm,
2676 const char_type* __pb, const char_type* __pe) const;
2677
2678 _LIBCPP_ALWAYS_INLINE
2679 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
2680 const tm* __tm, char __fmt, char __mod = 0) const
2681 {
2682 return do_put(__s, __iob, __fl, __tm, __fmt, __mod);
2683 }
2684
2685 static locale::id id;
2686
2687protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002688 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002689 ~time_put() {}
2690 virtual iter_type do_put(iter_type __s, ios_base&, char_type, const tm* __tm,
2691 char __fmt, char __mod) const;
2692
Howard Hinnant82894812010-09-22 16:48:34 +00002693 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002694 explicit time_put(const char* __nm, size_t __refs)
2695 : locale::facet(__refs),
2696 __time_put(__nm) {}
Howard Hinnant82894812010-09-22 16:48:34 +00002697 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002698 explicit time_put(const string& __nm, size_t __refs)
2699 : locale::facet(__refs),
2700 __time_put(__nm) {}
2701};
2702
2703template <class _CharT, class _OutputIterator>
2704locale::id
2705time_put<_CharT, _OutputIterator>::id;
2706
2707template <class _CharT, class _OutputIterator>
2708_OutputIterator
2709time_put<_CharT, _OutputIterator>::put(iter_type __s, ios_base& __iob,
2710 char_type __fl, const tm* __tm,
2711 const char_type* __pb,
2712 const char_type* __pe) const
2713{
2714 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2715 for (; __pb != __pe; ++__pb)
2716 {
2717 if (__ct.narrow(*__pb, 0) == '%')
2718 {
2719 if (++__pb == __pe)
2720 {
2721 *__s++ = __pb[-1];
2722 break;
2723 }
2724 char __mod = 0;
2725 char __fmt = __ct.narrow(*__pb, 0);
2726 if (__fmt == 'E' || __fmt == 'O')
2727 {
2728 if (++__pb == __pe)
2729 {
2730 *__s++ = __pb[-2];
2731 *__s++ = __pb[-1];
2732 break;
2733 }
2734 __mod = __fmt;
2735 __fmt = __ct.narrow(*__pb, 0);
2736 }
2737 __s = do_put(__s, __iob, __fl, __tm, __fmt, __mod);
2738 }
2739 else
2740 *__s++ = *__pb;
2741 }
2742 return __s;
2743}
2744
2745template <class _CharT, class _OutputIterator>
2746_OutputIterator
Howard Hinnantec3773c2011-12-01 20:21:04 +00002747time_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002748 char_type, const tm* __tm,
2749 char __fmt, char __mod) const
2750{
2751 char_type __nar[100];
2752 char_type* __nb = __nar;
2753 char_type* __ne = __nb + 100;
2754 __do_put(__nb, __ne, __tm, __fmt, __mod);
Howard Hinnant0949eed2011-06-30 21:18:19 +00002755 return _VSTD::copy(__nb, __ne, __s);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002756}
2757
2758extern template class time_put<char>;
2759extern template class time_put<wchar_t>;
2760
2761template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00002762class _LIBCPP_VISIBLE time_put_byname
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002763 : public time_put<_CharT, _OutputIterator>
2764{
2765public:
2766 _LIBCPP_ALWAYS_INLINE
2767 explicit time_put_byname(const char* __nm, size_t __refs = 0)
2768 : time_put<_CharT, _OutputIterator>(__nm, __refs) {}
2769
2770 _LIBCPP_ALWAYS_INLINE
2771 explicit time_put_byname(const string& __nm, size_t __refs = 0)
2772 : time_put<_CharT, _OutputIterator>(__nm, __refs) {}
2773
2774protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002775 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002776 ~time_put_byname() {}
2777};
2778
2779extern template class time_put_byname<char>;
2780extern template class time_put_byname<wchar_t>;
2781
2782// money_base
2783
Howard Hinnant82894812010-09-22 16:48:34 +00002784class _LIBCPP_VISIBLE money_base
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002785{
2786public:
2787 enum part {none, space, symbol, sign, value};
2788 struct pattern {char field[4];};
2789
2790 _LIBCPP_ALWAYS_INLINE money_base() {}
2791};
2792
2793// moneypunct
2794
2795template <class _CharT, bool _International = false>
Howard Hinnant82894812010-09-22 16:48:34 +00002796class _LIBCPP_VISIBLE moneypunct
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002797 : public locale::facet,
2798 public money_base
2799{
2800public:
2801 typedef _CharT char_type;
2802 typedef basic_string<char_type> string_type;
2803
Howard Hinnant82894812010-09-22 16:48:34 +00002804 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002805 explicit moneypunct(size_t __refs = 0)
2806 : locale::facet(__refs) {}
2807
2808 _LIBCPP_ALWAYS_INLINE char_type decimal_point() const {return do_decimal_point();}
2809 _LIBCPP_ALWAYS_INLINE char_type thousands_sep() const {return do_thousands_sep();}
2810 _LIBCPP_ALWAYS_INLINE string grouping() const {return do_grouping();}
2811 _LIBCPP_ALWAYS_INLINE string_type curr_symbol() const {return do_curr_symbol();}
2812 _LIBCPP_ALWAYS_INLINE string_type positive_sign() const {return do_positive_sign();}
2813 _LIBCPP_ALWAYS_INLINE string_type negative_sign() const {return do_negative_sign();}
2814 _LIBCPP_ALWAYS_INLINE int frac_digits() const {return do_frac_digits();}
2815 _LIBCPP_ALWAYS_INLINE pattern pos_format() const {return do_pos_format();}
2816 _LIBCPP_ALWAYS_INLINE pattern neg_format() const {return do_neg_format();}
2817
2818 static locale::id id;
2819 static const bool intl = _International;
2820
2821protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002822 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002823 ~moneypunct() {}
2824
2825 virtual char_type do_decimal_point() const {return numeric_limits<char_type>::max();}
2826 virtual char_type do_thousands_sep() const {return numeric_limits<char_type>::max();}
2827 virtual string do_grouping() const {return string();}
2828 virtual string_type do_curr_symbol() const {return string_type();}
2829 virtual string_type do_positive_sign() const {return string_type();}
2830 virtual string_type do_negative_sign() const {return string_type(1, '-');}
2831 virtual int do_frac_digits() const {return 0;}
2832 virtual pattern do_pos_format() const
2833 {pattern __p = {symbol, sign, none, value}; return __p;}
2834 virtual pattern do_neg_format() const
2835 {pattern __p = {symbol, sign, none, value}; return __p;}
2836};
2837
2838template <class _CharT, bool _International>
2839locale::id
2840moneypunct<_CharT, _International>::id;
2841
2842extern template class moneypunct<char, false>;
2843extern template class moneypunct<char, true>;
2844extern template class moneypunct<wchar_t, false>;
2845extern template class moneypunct<wchar_t, true>;
2846
2847// moneypunct_byname
2848
2849template <class _CharT, bool _International = false>
Howard Hinnant82894812010-09-22 16:48:34 +00002850class _LIBCPP_VISIBLE moneypunct_byname
2851 : public moneypunct<_CharT, _International>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002852{
2853public:
2854 typedef money_base::pattern pattern;
2855 typedef _CharT char_type;
2856 typedef basic_string<char_type> string_type;
2857
2858 _LIBCPP_ALWAYS_INLINE
2859 explicit moneypunct_byname(const char* __nm, size_t __refs = 0)
2860 : moneypunct<_CharT, _International>(__refs) {init(__nm);}
2861
2862 _LIBCPP_ALWAYS_INLINE
2863 explicit moneypunct_byname(const string& __nm, size_t __refs = 0)
2864 : moneypunct<_CharT, _International>(__refs) {init(__nm.c_str());}
2865
2866protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002867 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002868 ~moneypunct_byname() {}
2869
2870 virtual char_type do_decimal_point() const {return __decimal_point_;}
2871 virtual char_type do_thousands_sep() const {return __thousands_sep_;}
2872 virtual string do_grouping() const {return __grouping_;}
2873 virtual string_type do_curr_symbol() const {return __curr_symbol_;}
2874 virtual string_type do_positive_sign() const {return __positive_sign_;}
2875 virtual string_type do_negative_sign() const {return __negative_sign_;}
2876 virtual int do_frac_digits() const {return __frac_digits_;}
2877 virtual pattern do_pos_format() const {return __pos_format_;}
2878 virtual pattern do_neg_format() const {return __neg_format_;}
2879
2880private:
2881 char_type __decimal_point_;
2882 char_type __thousands_sep_;
2883 string __grouping_;
2884 string_type __curr_symbol_;
2885 string_type __positive_sign_;
2886 string_type __negative_sign_;
2887 int __frac_digits_;
2888 pattern __pos_format_;
2889 pattern __neg_format_;
2890
2891 void init(const char*);
2892};
2893
2894template<> void moneypunct_byname<char, false>::init(const char*);
2895template<> void moneypunct_byname<char, true>::init(const char*);
2896template<> void moneypunct_byname<wchar_t, false>::init(const char*);
2897template<> void moneypunct_byname<wchar_t, true>::init(const char*);
2898
2899extern template class moneypunct_byname<char, false>;
2900extern template class moneypunct_byname<char, true>;
2901extern template class moneypunct_byname<wchar_t, false>;
2902extern template class moneypunct_byname<wchar_t, true>;
2903
2904// money_get
2905
2906template <class _CharT>
2907class __money_get
2908{
2909protected:
2910 typedef _CharT char_type;
2911 typedef basic_string<char_type> string_type;
2912
2913 _LIBCPP_ALWAYS_INLINE __money_get() {}
2914
2915 static void __gather_info(bool __intl, const locale& __loc,
2916 money_base::pattern& __pat, char_type& __dp,
2917 char_type& __ts, string& __grp,
2918 string_type& __sym, string_type& __psn,
2919 string_type& __nsn, int& __fd);
2920};
2921
2922template <class _CharT>
2923void
2924__money_get<_CharT>::__gather_info(bool __intl, const locale& __loc,
2925 money_base::pattern& __pat, char_type& __dp,
2926 char_type& __ts, string& __grp,
2927 string_type& __sym, string_type& __psn,
2928 string_type& __nsn, int& __fd)
2929{
2930 if (__intl)
2931 {
2932 const moneypunct<char_type, true>& __mp =
2933 use_facet<moneypunct<char_type, true> >(__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 else
2944 {
2945 const moneypunct<char_type, false>& __mp =
2946 use_facet<moneypunct<char_type, false> >(__loc);
2947 __pat = __mp.neg_format();
2948 __nsn = __mp.negative_sign();
2949 __psn = __mp.positive_sign();
2950 __dp = __mp.decimal_point();
2951 __ts = __mp.thousands_sep();
2952 __grp = __mp.grouping();
2953 __sym = __mp.curr_symbol();
2954 __fd = __mp.frac_digits();
2955 }
2956}
2957
2958extern template class __money_get<char>;
2959extern template class __money_get<wchar_t>;
2960
2961template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00002962class _LIBCPP_VISIBLE money_get
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002963 : public locale::facet,
2964 private __money_get<_CharT>
2965{
2966public:
2967 typedef _CharT char_type;
2968 typedef _InputIterator iter_type;
2969 typedef basic_string<char_type> string_type;
2970
2971 _LIBCPP_ALWAYS_INLINE
2972 explicit money_get(size_t __refs = 0)
2973 : locale::facet(__refs) {}
2974
2975 _LIBCPP_ALWAYS_INLINE
2976 iter_type get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob,
2977 ios_base::iostate& __err, long double& __v) const
2978 {
2979 return do_get(__b, __e, __intl, __iob, __err, __v);
2980 }
2981
2982 _LIBCPP_ALWAYS_INLINE
2983 iter_type get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob,
2984 ios_base::iostate& __err, string_type& __v) const
2985 {
2986 return do_get(__b, __e, __intl, __iob, __err, __v);
2987 }
2988
2989 static locale::id id;
2990
2991protected:
2992
Howard Hinnant82894812010-09-22 16:48:34 +00002993 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002994 ~money_get() {}
Howard Hinnant324bb032010-08-22 00:02:43 +00002995
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002996 virtual iter_type do_get(iter_type __b, iter_type __e, bool __intl,
2997 ios_base& __iob, ios_base::iostate& __err,
2998 long double& __v) const;
2999 virtual iter_type do_get(iter_type __b, iter_type __e, bool __intl,
3000 ios_base& __iob, ios_base::iostate& __err,
3001 string_type& __v) const;
3002
3003private:
3004 static bool __do_get(iter_type& __b, iter_type __e,
3005 bool __intl, const locale& __loc,
3006 ios_base::fmtflags __flags, ios_base::iostate& __err,
3007 bool& __neg, const ctype<char_type>& __ct,
3008 unique_ptr<char_type, void(*)(void*)>& __wb,
3009 char_type*& __wn, char_type* __we);
3010};
3011
3012template <class _CharT, class _InputIterator>
3013locale::id
3014money_get<_CharT, _InputIterator>::id;
3015
3016void __do_nothing(void*);
3017
3018template <class _Tp>
3019_LIBCPP_HIDDEN
3020void
3021__double_or_nothing(unique_ptr<_Tp, void(*)(void*)>& __b, _Tp*& __n, _Tp*& __e)
3022{
3023 bool __owns = __b.get_deleter() != __do_nothing;
Howard Hinnantec3773c2011-12-01 20:21:04 +00003024 size_t __cur_cap = static_cast<size_t>(__e-__b.get()) * sizeof(_Tp);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003025 size_t __new_cap = __cur_cap < numeric_limits<size_t>::max() / 2 ?
3026 2 * __cur_cap : numeric_limits<size_t>::max();
Howard Hinnantec3773c2011-12-01 20:21:04 +00003027 size_t __n_off = static_cast<size_t>(__n - __b.get());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003028 _Tp* __t = (_Tp*)realloc(__owns ? __b.get() : 0, __new_cap);
3029 if (__t == 0)
3030 __throw_bad_alloc();
3031 if (__owns)
3032 __b.release();
3033 __b = unique_ptr<_Tp, void(*)(void*)>(__t, free);
3034 __new_cap /= sizeof(_Tp);
3035 __n = __b.get() + __n_off;
3036 __e = __b.get() + __new_cap;
3037}
3038
3039// true == success
3040template <class _CharT, class _InputIterator>
3041bool
3042money_get<_CharT, _InputIterator>::__do_get(iter_type& __b, iter_type __e,
3043 bool __intl, const locale& __loc,
3044 ios_base::fmtflags __flags,
3045 ios_base::iostate& __err,
3046 bool& __neg,
3047 const ctype<char_type>& __ct,
3048 unique_ptr<char_type, void(*)(void*)>& __wb,
3049 char_type*& __wn, char_type* __we)
3050{
3051 const unsigned __bz = 100;
3052 unsigned __gbuf[__bz];
3053 unique_ptr<unsigned, void(*)(void*)> __gb(__gbuf, __do_nothing);
3054 unsigned* __gn = __gb.get();
3055 unsigned* __ge = __gn + __bz;
3056 money_base::pattern __pat;
3057 char_type __dp;
3058 char_type __ts;
3059 string __grp;
3060 string_type __sym;
3061 string_type __psn;
3062 string_type __nsn;
3063 int __fd;
3064 __money_get<_CharT>::__gather_info(__intl, __loc, __pat, __dp, __ts, __grp,
3065 __sym, __psn, __nsn, __fd);
3066 const string_type* __trailing_sign = 0;
3067 __wn = __wb.get();
3068 for (unsigned __p = 0; __p < 4 && __b != __e; ++__p)
3069 {
3070 switch (__pat.field[__p])
3071 {
3072 case money_base::space:
3073 if (__p != 3)
3074 {
3075 if (__ct.is(ctype_base::space, *__b))
3076 ++__b;
3077 else
3078 {
3079 __err |= ios_base::failbit;
3080 return false;
3081 }
3082 }
Howard Hinnant324bb032010-08-22 00:02:43 +00003083 // drop through
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003084 case money_base::none:
3085 if (__p != 3)
3086 {
3087 while (__b != __e && __ct.is(ctype_base::space, *__b))
3088 ++__b;
3089 }
3090 break;
3091 case money_base::sign:
3092 if (__psn.size() + __nsn.size() > 0)
3093 {
3094 if (__psn.size() == 0 || __nsn.size() == 0)
3095 { // sign is optional
3096 if (__psn.size() > 0)
3097 { // __nsn.size() == 0
3098 if (*__b == __psn[0])
3099 {
3100 ++__b;
3101 if (__psn.size() > 1)
3102 __trailing_sign = &__psn;
3103 }
3104 else
3105 __neg = true;
3106 }
3107 else if (*__b == __nsn[0]) // __nsn.size() > 0 && __psn.size() == 0
3108 {
3109 ++__b;
3110 __neg = true;
3111 if (__nsn.size() > 1)
3112 __trailing_sign = &__nsn;
3113 }
3114 }
3115 else // sign is required
3116 {
3117 if (*__b == __psn[0])
3118 {
3119 ++__b;
3120 if (__psn.size() > 1)
3121 __trailing_sign = &__psn;
3122 }
3123 else if (*__b == __nsn[0])
3124 {
3125 ++__b;
3126 __neg = true;
3127 if (__nsn.size() > 1)
3128 __trailing_sign = &__nsn;
3129 }
3130 else
3131 {
3132 __err |= ios_base::failbit;
3133 return false;
3134 }
3135 }
3136 }
3137 break;
3138 case money_base::symbol:
3139 {
3140 bool __more_needed = __trailing_sign ||
3141 (__p < 2) ||
3142 (__p == 2 && __pat.field[3] != static_cast<char>(money_base::none));
3143 bool __sb = __flags & ios_base::showbase;
3144 if (__sb || __more_needed)
3145 {
3146 ios_base::iostate __et = ios_base::goodbit;
3147 string_type* __k = __scan_keyword(__b, __e, &__sym, &__sym+1,
3148 __ct, __et);
3149 if (__sb && __k != &__sym)
3150 {
3151 __err |= ios_base::failbit;
3152 return false;
3153 }
3154 }
3155 }
3156 break;
3157 case money_base::value:
3158 {
3159 unsigned __ng = 0;
3160 for (; __b != __e; ++__b)
3161 {
3162 char_type __c = *__b;
3163 if (__ct.is(ctype_base::digit, __c))
3164 {
3165 if (__wn == __we)
3166 __double_or_nothing(__wb, __wn, __we);
3167 *__wn++ = __c;
3168 ++__ng;
3169 }
3170 else if (__grp.size() > 0 && __ng > 0 && __c == __ts)
3171 {
3172 if (__gn == __ge)
3173 __double_or_nothing(__gb, __gn, __ge);
3174 *__gn++ = __ng;
3175 __ng = 0;
3176 }
3177 else
3178 break;
3179 }
3180 if (__gb.get() != __gn && __ng > 0)
3181 {
3182 if (__gn == __ge)
3183 __double_or_nothing(__gb, __gn, __ge);
3184 *__gn++ = __ng;
3185 }
3186 if (__fd > 0)
3187 {
3188 if (__b == __e || *__b != __dp)
3189 {
3190 __err |= ios_base::failbit;
3191 return false;
3192 }
3193 for (++__b; __fd > 0; --__fd, ++__b)
3194 {
3195 if (__b == __e || !__ct.is(ctype_base::digit, *__b))
3196 {
3197 __err |= ios_base::failbit;
3198 return false;
3199 }
3200 if (__wn == __we)
3201 __double_or_nothing(__wb, __wn, __we);
3202 *__wn++ = *__b;
3203 }
3204 }
3205 if (__wn == __wb.get())
3206 {
3207 __err |= ios_base::failbit;
3208 return false;
3209 }
3210 }
3211 break;
3212 }
3213 }
3214 if (__trailing_sign)
3215 {
3216 for (unsigned __i = 1; __i < __trailing_sign->size(); ++__i, ++__b)
3217 {
3218 if (__b == __e || *__b != (*__trailing_sign)[__i])
3219 {
3220 __err |= ios_base::failbit;
3221 return false;
3222 }
3223 }
3224 }
3225 if (__gb.get() != __gn)
3226 {
3227 ios_base::iostate __et = ios_base::goodbit;
3228 __check_grouping(__grp, __gb.get(), __gn, __et);
3229 if (__et)
3230 {
3231 __err |= ios_base::failbit;
3232 return false;
3233 }
3234 }
3235 return true;
3236}
3237
3238template <class _CharT, class _InputIterator>
3239_InputIterator
3240money_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
3241 bool __intl, ios_base& __iob,
3242 ios_base::iostate& __err,
3243 long double& __v) const
3244{
Howard Hinnantec3773c2011-12-01 20:21:04 +00003245 const int __bz = 100;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003246 char_type __wbuf[__bz];
3247 unique_ptr<char_type, void(*)(void*)> __wb(__wbuf, __do_nothing);
3248 char_type* __wn;
3249 char_type* __we = __wbuf + __bz;
3250 locale __loc = __iob.getloc();
3251 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3252 bool __neg = false;
3253 if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct,
3254 __wb, __wn, __we))
3255 {
3256 const char __src[] = "0123456789";
3257 char_type __atoms[sizeof(__src)-1];
3258 __ct.widen(__src, __src + (sizeof(__src)-1), __atoms);
3259 char __nbuf[__bz];
3260 char* __nc = __nbuf;
3261 unique_ptr<char, void(*)(void*)> __h(0, free);
3262 if (__wn - __wb.get() > __bz-2)
3263 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00003264 __h.reset((char*)malloc(static_cast<size_t>(__wn - __wb.get() + 2)));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003265 if (__h.get() == 0)
3266 __throw_bad_alloc();
3267 __nc = __h.get();
3268 }
3269 if (__neg)
3270 *__nc++ = '-';
3271 for (const char_type* __w = __wb.get(); __w < __wn; ++__w, ++__nc)
3272 *__nc = __src[find(__atoms, __atoms+sizeof(__atoms), *__w) - __atoms];
3273 *__nc = char();
3274 if (sscanf(__nbuf, "%Lf", &__v) != 1)
3275 __throw_runtime_error("money_get error");
3276 }
3277 if (__b == __e)
3278 __err |= ios_base::eofbit;
3279 return __b;
3280}
3281
3282template <class _CharT, class _InputIterator>
3283_InputIterator
3284money_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
3285 bool __intl, ios_base& __iob,
3286 ios_base::iostate& __err,
3287 string_type& __v) const
3288{
Howard Hinnantec3773c2011-12-01 20:21:04 +00003289 const int __bz = 100;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003290 char_type __wbuf[__bz];
3291 unique_ptr<char_type, void(*)(void*)> __wb(__wbuf, __do_nothing);
3292 char_type* __wn;
3293 char_type* __we = __wbuf + __bz;
3294 locale __loc = __iob.getloc();
3295 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3296 bool __neg = false;
3297 if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct,
3298 __wb, __wn, __we))
3299 {
3300 __v.clear();
3301 if (__neg)
3302 __v.push_back(__ct.widen('-'));
3303 char_type __z = __ct.widen('0');
3304 char_type* __w;
3305 for (__w = __wb.get(); __w < __wn-1; ++__w)
3306 if (*__w != __z)
3307 break;
3308 __v.append(__w, __wn);
3309 }
3310 if (__b == __e)
3311 __err |= ios_base::eofbit;
3312 return __b;
3313}
3314
3315extern template class money_get<char>;
3316extern template class money_get<wchar_t>;
3317
3318// money_put
3319
3320template <class _CharT>
3321class __money_put
3322{
3323protected:
3324 typedef _CharT char_type;
3325 typedef basic_string<char_type> string_type;
3326
3327 _LIBCPP_ALWAYS_INLINE __money_put() {}
3328
3329 static void __gather_info(bool __intl, bool __neg, const locale& __loc,
3330 money_base::pattern& __pat, char_type& __dp,
3331 char_type& __ts, string& __grp,
3332 string_type& __sym, string_type& __sn,
3333 int& __fd);
3334 static void __format(char_type* __mb, char_type*& __mi, char_type*& __me,
3335 ios_base::fmtflags __flags,
3336 const char_type* __db, const char_type* __de,
3337 const ctype<char_type>& __ct, bool __neg,
3338 const money_base::pattern& __pat, char_type __dp,
3339 char_type __ts, const string& __grp,
3340 const string_type& __sym, const string_type& __sn,
3341 int __fd);
3342};
3343
3344template <class _CharT>
3345void
3346__money_put<_CharT>::__gather_info(bool __intl, bool __neg, const locale& __loc,
3347 money_base::pattern& __pat, char_type& __dp,
3348 char_type& __ts, string& __grp,
3349 string_type& __sym, string_type& __sn,
3350 int& __fd)
3351{
3352 if (__intl)
3353 {
3354 const moneypunct<char_type, true>& __mp =
3355 use_facet<moneypunct<char_type, true> >(__loc);
3356 if (__neg)
3357 {
3358 __pat = __mp.neg_format();
3359 __sn = __mp.negative_sign();
3360 }
3361 else
3362 {
3363 __pat = __mp.pos_format();
3364 __sn = __mp.positive_sign();
3365 }
3366 __dp = __mp.decimal_point();
3367 __ts = __mp.thousands_sep();
3368 __grp = __mp.grouping();
3369 __sym = __mp.curr_symbol();
3370 __fd = __mp.frac_digits();
3371 }
3372 else
3373 {
3374 const moneypunct<char_type, false>& __mp =
3375 use_facet<moneypunct<char_type, false> >(__loc);
3376 if (__neg)
3377 {
3378 __pat = __mp.neg_format();
3379 __sn = __mp.negative_sign();
3380 }
3381 else
3382 {
3383 __pat = __mp.pos_format();
3384 __sn = __mp.positive_sign();
3385 }
3386 __dp = __mp.decimal_point();
3387 __ts = __mp.thousands_sep();
3388 __grp = __mp.grouping();
3389 __sym = __mp.curr_symbol();
3390 __fd = __mp.frac_digits();
3391 }
3392}
3393
3394template <class _CharT>
3395void
3396__money_put<_CharT>::__format(char_type* __mb, char_type*& __mi, char_type*& __me,
3397 ios_base::fmtflags __flags,
3398 const char_type* __db, const char_type* __de,
3399 const ctype<char_type>& __ct, bool __neg,
3400 const money_base::pattern& __pat, char_type __dp,
3401 char_type __ts, const string& __grp,
3402 const string_type& __sym, const string_type& __sn,
3403 int __fd)
3404{
3405 __me = __mb;
3406 for (unsigned __p = 0; __p < 4; ++__p)
3407 {
3408 switch (__pat.field[__p])
3409 {
3410 case money_base::none:
3411 __mi = __me;
3412 break;
3413 case money_base::space:
3414 __mi = __me;
3415 *__me++ = __ct.widen(' ');
3416 break;
3417 case money_base::sign:
3418 if (!__sn.empty())
3419 *__me++ = __sn[0];
3420 break;
3421 case money_base::symbol:
3422 if (!__sym.empty() && (__flags & ios_base::showbase))
Howard Hinnant0949eed2011-06-30 21:18:19 +00003423 __me = _VSTD::copy(__sym.begin(), __sym.end(), __me);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003424 break;
3425 case money_base::value:
3426 {
3427 // remember start of value so we can reverse it
3428 char_type* __t = __me;
3429 // find beginning of digits
3430 if (__neg)
3431 ++__db;
3432 // find end of digits
3433 const char_type* __d;
3434 for (__d = __db; __d < __de; ++__d)
3435 if (!__ct.is(ctype_base::digit, *__d))
3436 break;
3437 // print fractional part
3438 if (__fd > 0)
3439 {
3440 int __f;
3441 for (__f = __fd; __d > __db && __f > 0; --__f)
3442 *__me++ = *--__d;
3443 char_type __z = __f > 0 ? __ct.widen('0') : char_type();
3444 for (; __f > 0; --__f)
3445 *__me++ = __z;
3446 *__me++ = __dp;
3447 }
3448 // print units part
3449 if (__d == __db)
3450 {
3451 *__me++ = __ct.widen('0');
3452 }
3453 else
3454 {
3455 unsigned __ng = 0;
3456 unsigned __ig = 0;
3457 unsigned __gl = __grp.empty() ? numeric_limits<unsigned>::max()
3458 : static_cast<unsigned>(__grp[__ig]);
3459 while (__d != __db)
3460 {
3461 if (__ng == __gl)
3462 {
3463 *__me++ = __ts;
3464 __ng = 0;
3465 if (++__ig < __grp.size())
3466 __gl = __grp[__ig] == numeric_limits<char>::max() ?
3467 numeric_limits<unsigned>::max() :
3468 static_cast<unsigned>(__grp[__ig]);
3469 }
3470 *__me++ = *--__d;
3471 ++__ng;
3472 }
3473 }
3474 // reverse it
3475 reverse(__t, __me);
3476 }
3477 break;
3478 }
3479 }
3480 // print rest of sign, if any
3481 if (__sn.size() > 1)
Howard Hinnant0949eed2011-06-30 21:18:19 +00003482 __me = _VSTD::copy(__sn.begin()+1, __sn.end(), __me);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003483 // set alignment
3484 if ((__flags & ios_base::adjustfield) == ios_base::left)
3485 __mi = __me;
3486 else if ((__flags & ios_base::adjustfield) != ios_base::internal)
3487 __mi = __mb;
3488}
3489
3490extern template class __money_put<char>;
3491extern template class __money_put<wchar_t>;
3492
3493template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00003494class _LIBCPP_VISIBLE money_put
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003495 : public locale::facet,
3496 private __money_put<_CharT>
3497{
3498public:
3499 typedef _CharT char_type;
3500 typedef _OutputIterator iter_type;
3501 typedef basic_string<char_type> string_type;
3502
3503 _LIBCPP_ALWAYS_INLINE
3504 explicit money_put(size_t __refs = 0)
3505 : locale::facet(__refs) {}
3506
3507 _LIBCPP_ALWAYS_INLINE
3508 iter_type put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl,
3509 long double __units) const
3510 {
3511 return do_put(__s, __intl, __iob, __fl, __units);
3512 }
3513
3514 _LIBCPP_ALWAYS_INLINE
3515 iter_type put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl,
3516 const string_type& __digits) const
3517 {
3518 return do_put(__s, __intl, __iob, __fl, __digits);
3519 }
3520
3521 static locale::id id;
3522
3523protected:
Howard Hinnant82894812010-09-22 16:48:34 +00003524 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003525 ~money_put() {}
3526
3527 virtual iter_type do_put(iter_type __s, bool __intl, ios_base& __iob,
3528 char_type __fl, long double __units) const;
3529 virtual iter_type do_put(iter_type __s, bool __intl, ios_base& __iob,
3530 char_type __fl, const string_type& __digits) const;
3531};
3532
3533template <class _CharT, class _OutputIterator>
3534locale::id
3535money_put<_CharT, _OutputIterator>::id;
3536
3537template <class _CharT, class _OutputIterator>
3538_OutputIterator
3539money_put<_CharT, _OutputIterator>::do_put(iter_type __s, bool __intl,
3540 ios_base& __iob, char_type __fl,
3541 long double __units) const
3542{
3543 // convert to char
3544 const size_t __bs = 100;
3545 char __buf[__bs];
3546 char* __bb = __buf;
3547 char_type __digits[__bs];
3548 char_type* __db = __digits;
Howard Hinnantec3773c2011-12-01 20:21:04 +00003549 size_t __n = static_cast<size_t>(snprintf(__bb, __bs, "%.0Lf", __units));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003550 unique_ptr<char, void(*)(void*)> __hn(0, free);
3551 unique_ptr<char_type, void(*)(void*)> __hd(0, free);
3552 // secure memory for digit storage
3553 if (__n > __bs-1)
3554 {
Howard Hinnant866569b2011-09-28 23:39:33 +00003555#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00003556 __n = static_cast<size_t>(asprintf_l(&__bb, _LIBCPP_GET_C_LOCALE, "%.0Lf", __units));
Sean Huntf3907e62011-07-15 05:40:33 +00003557#else
3558 __n = __asprintf_l(&__bb, __cloc(), "%.0Lf", __units);
3559#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003560 if (__bb == 0)
3561 __throw_bad_alloc();
3562 __hn.reset(__bb);
3563 __hd.reset((char_type*)malloc(__n * sizeof(char_type)));
Howard Hinnant05b57d52012-03-07 20:37:43 +00003564 if (__hd == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003565 __throw_bad_alloc();
3566 __db = __hd.get();
3567 }
3568 // gather info
3569 locale __loc = __iob.getloc();
3570 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3571 __ct.widen(__bb, __bb + __n, __db);
3572 bool __neg = __n > 0 && __bb[0] == '-';
3573 money_base::pattern __pat;
3574 char_type __dp;
3575 char_type __ts;
3576 string __grp;
3577 string_type __sym;
3578 string_type __sn;
3579 int __fd;
3580 this->__gather_info(__intl, __neg, __loc, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3581 // secure memory for formatting
3582 char_type __mbuf[__bs];
3583 char_type* __mb = __mbuf;
3584 unique_ptr<char_type, void(*)(void*)> __hw(0, free);
3585 size_t __exn = static_cast<int>(__n) > __fd ?
Howard Hinnantec3773c2011-12-01 20:21:04 +00003586 (__n - static_cast<size_t>(__fd)) * 2 + __sn.size() +
3587 __sym.size() + static_cast<size_t>(__fd) + 1
3588 : __sn.size() + __sym.size() + static_cast<size_t>(__fd) + 2;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003589 if (__exn > __bs)
3590 {
3591 __hw.reset((char_type*)malloc(__exn * sizeof(char_type)));
3592 __mb = __hw.get();
3593 if (__mb == 0)
3594 __throw_bad_alloc();
3595 }
3596 // format
3597 char_type* __mi;
3598 char_type* __me;
3599 this->__format(__mb, __mi, __me, __iob.flags(),
3600 __db, __db + __n, __ct,
3601 __neg, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3602 return __pad_and_output(__s, __mb, __mi, __me, __iob, __fl);
3603}
3604
3605template <class _CharT, class _OutputIterator>
3606_OutputIterator
3607money_put<_CharT, _OutputIterator>::do_put(iter_type __s, bool __intl,
3608 ios_base& __iob, char_type __fl,
3609 const string_type& __digits) const
3610{
3611 // gather info
3612 locale __loc = __iob.getloc();
3613 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3614 bool __neg = __digits.size() > 0 && __digits[0] == __ct.widen('-');
3615 money_base::pattern __pat;
3616 char_type __dp;
3617 char_type __ts;
3618 string __grp;
3619 string_type __sym;
3620 string_type __sn;
3621 int __fd;
3622 this->__gather_info(__intl, __neg, __loc, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3623 // secure memory for formatting
3624 char_type __mbuf[100];
3625 char_type* __mb = __mbuf;
3626 unique_ptr<char_type, void(*)(void*)> __h(0, free);
Howard Hinnantec3773c2011-12-01 20:21:04 +00003627 size_t __exn = static_cast<int>(__digits.size()) > __fd ?
3628 (__digits.size() - static_cast<size_t>(__fd)) * 2 +
3629 __sn.size() + __sym.size() + static_cast<size_t>(__fd) + 1
3630 : __sn.size() + __sym.size() + static_cast<size_t>(__fd) + 2;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003631 if (__exn > 100)
3632 {
3633 __h.reset((char_type*)malloc(__exn * sizeof(char_type)));
3634 __mb = __h.get();
3635 if (__mb == 0)
3636 __throw_bad_alloc();
3637 }
3638 // format
3639 char_type* __mi;
3640 char_type* __me;
3641 this->__format(__mb, __mi, __me, __iob.flags(),
3642 __digits.data(), __digits.data() + __digits.size(), __ct,
3643 __neg, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3644 return __pad_and_output(__s, __mb, __mi, __me, __iob, __fl);
3645}
3646
3647extern template class money_put<char>;
3648extern template class money_put<wchar_t>;
3649
3650// messages
3651
Howard Hinnant82894812010-09-22 16:48:34 +00003652class _LIBCPP_VISIBLE messages_base
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003653{
3654public:
Howard Hinnantb2080c72011-02-25 00:51:08 +00003655 typedef ptrdiff_t catalog;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003656
3657 _LIBCPP_ALWAYS_INLINE messages_base() {}
3658};
3659
3660template <class _CharT>
Howard Hinnant82894812010-09-22 16:48:34 +00003661class _LIBCPP_VISIBLE messages
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003662 : public locale::facet,
3663 public messages_base
3664{
3665public:
3666 typedef _CharT char_type;
3667 typedef basic_string<_CharT> string_type;
3668
3669 _LIBCPP_ALWAYS_INLINE
3670 explicit messages(size_t __refs = 0)
3671 : locale::facet(__refs) {}
3672
3673 _LIBCPP_ALWAYS_INLINE
3674 catalog open(const basic_string<char>& __nm, const locale& __loc) const
3675 {
3676 return do_open(__nm, __loc);
3677 }
3678
3679 _LIBCPP_ALWAYS_INLINE
3680 string_type get(catalog __c, int __set, int __msgid,
3681 const string_type& __dflt) const
3682 {
3683 return do_get(__c, __set, __msgid, __dflt);
3684 }
3685
3686 _LIBCPP_ALWAYS_INLINE
3687 void close(catalog __c) const
3688 {
3689 do_close(__c);
3690 }
3691
3692 static locale::id id;
3693
3694protected:
Howard Hinnant82894812010-09-22 16:48:34 +00003695 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003696 ~messages() {}
3697
3698 virtual catalog do_open(const basic_string<char>&, const locale&) const;
3699 virtual string_type do_get(catalog, int __set, int __msgid,
3700 const string_type& __dflt) const;
3701 virtual void do_close(catalog) const;
3702};
3703
3704template <class _CharT>
3705locale::id
3706messages<_CharT>::id;
3707
3708template <class _CharT>
3709typename messages<_CharT>::catalog
3710messages<_CharT>::do_open(const basic_string<char>& __nm, const locale&) const
3711{
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00003712#if _WIN32
3713 return -1;
3714#else // _WIN32
Howard Hinnant11624452011-10-11 16:00:46 +00003715 catalog __cat = (catalog)catopen(__nm.c_str(), NL_CAT_LOCALE);
Howard Hinnantb2080c72011-02-25 00:51:08 +00003716 if (__cat != -1)
3717 __cat = static_cast<catalog>((static_cast<size_t>(__cat) >> 1));
3718 return __cat;
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00003719#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003720}
3721
3722template <class _CharT>
3723typename messages<_CharT>::string_type
3724messages<_CharT>::do_get(catalog __c, int __set, int __msgid,
3725 const string_type& __dflt) const
3726{
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00003727#if _WIN32
3728 return __dflt;
3729#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003730 string __ndflt;
3731 __narrow_to_utf8<sizeof(char_type)*__CHAR_BIT__>()(back_inserter(__ndflt),
3732 __dflt.c_str(),
3733 __dflt.c_str() + __dflt.size());
Howard Hinnantb2080c72011-02-25 00:51:08 +00003734 if (__c != -1)
3735 __c <<= 1;
Howard Hinnant11624452011-10-11 16:00:46 +00003736 nl_catd __cat = (nl_catd)__c;
Howard Hinnantb2080c72011-02-25 00:51:08 +00003737 char* __n = catgets(__cat, __set, __msgid, __ndflt.c_str());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003738 string_type __w;
3739 __widen_from_utf8<sizeof(char_type)*__CHAR_BIT__>()(back_inserter(__w),
3740 __n, __n + strlen(__n));
3741 return __w;
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00003742#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003743}
3744
3745template <class _CharT>
3746void
3747messages<_CharT>::do_close(catalog __c) const
3748{
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00003749#if !_WIN32
Howard Hinnantb2080c72011-02-25 00:51:08 +00003750 if (__c != -1)
3751 __c <<= 1;
Howard Hinnant11624452011-10-11 16:00:46 +00003752 nl_catd __cat = (nl_catd)__c;
Howard Hinnantb2080c72011-02-25 00:51:08 +00003753 catclose(__cat);
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00003754#endif // !_WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003755}
3756
3757extern template class messages<char>;
3758extern template class messages<wchar_t>;
3759
3760template <class _CharT>
Howard Hinnant82894812010-09-22 16:48:34 +00003761class _LIBCPP_VISIBLE messages_byname
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003762 : public messages<_CharT>
3763{
3764public:
3765 typedef messages_base::catalog catalog;
3766 typedef basic_string<_CharT> string_type;
3767
3768 _LIBCPP_ALWAYS_INLINE
3769 explicit messages_byname(const char*, size_t __refs = 0)
3770 : messages<_CharT>(__refs) {}
3771
3772 _LIBCPP_ALWAYS_INLINE
3773 explicit messages_byname(const string&, size_t __refs = 0)
3774 : messages<_CharT>(__refs) {}
3775
3776protected:
Howard Hinnant82894812010-09-22 16:48:34 +00003777 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003778 ~messages_byname() {}
3779};
3780
3781extern template class messages_byname<char>;
3782extern template class messages_byname<wchar_t>;
3783
Howard Hinnantd23b4642010-05-31 20:58:54 +00003784template<class _Codecvt, class _Elem = wchar_t,
3785 class _Wide_alloc = allocator<_Elem>,
3786 class _Byte_alloc = allocator<char> >
Howard Hinnant82894812010-09-22 16:48:34 +00003787class _LIBCPP_VISIBLE wstring_convert
Howard Hinnantd23b4642010-05-31 20:58:54 +00003788{
3789public:
3790 typedef basic_string<char, char_traits<char>, _Byte_alloc> byte_string;
3791 typedef basic_string<_Elem, char_traits<_Elem>, _Wide_alloc> wide_string;
3792 typedef typename _Codecvt::state_type state_type;
3793 typedef typename wide_string::traits_type::int_type int_type;
3794
3795private:
3796 byte_string __byte_err_string_;
3797 wide_string __wide_err_string_;
3798 _Codecvt* __cvtptr_;
3799 state_type __cvtstate_;
3800 size_t __cvtcount_;
3801
3802 wstring_convert(const wstring_convert& __wc);
3803 wstring_convert& operator=(const wstring_convert& __wc);
3804public:
3805 wstring_convert(_Codecvt* __pcvt = new _Codecvt);
3806 wstring_convert(_Codecvt* __pcvt, state_type __state);
3807 wstring_convert(const byte_string& __byte_err,
3808 const wide_string& __wide_err = wide_string());
Howard Hinnant73d21a42010-09-04 23:28:19 +00003809#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantd23b4642010-05-31 20:58:54 +00003810 wstring_convert(wstring_convert&& __wc);
3811#endif
3812 ~wstring_convert();
3813
Howard Hinnant82894812010-09-22 16:48:34 +00003814 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003815 wide_string from_bytes(char __byte)
3816 {return from_bytes(&__byte, &__byte+1);}
Howard Hinnant82894812010-09-22 16:48:34 +00003817 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003818 wide_string from_bytes(const char* __ptr)
3819 {return from_bytes(__ptr, __ptr + char_traits<char>::length(__ptr));}
Howard Hinnant82894812010-09-22 16:48:34 +00003820 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003821 wide_string from_bytes(const byte_string& __str)
3822 {return from_bytes(__str.data(), __str.data() + __str.size());}
3823 wide_string from_bytes(const char* __first, const char* __last);
3824
Howard Hinnant82894812010-09-22 16:48:34 +00003825 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003826 byte_string to_bytes(_Elem __wchar)
3827 {return to_bytes(&__wchar, &__wchar+1);}
Howard Hinnant82894812010-09-22 16:48:34 +00003828 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003829 byte_string to_bytes(const _Elem* __wptr)
3830 {return to_bytes(__wptr, __wptr + char_traits<_Elem>::length(__wptr));}
Howard Hinnant82894812010-09-22 16:48:34 +00003831 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003832 byte_string to_bytes(const wide_string& __wstr)
3833 {return to_bytes(__wstr.data(), __wstr.data() + __wstr.size());}
3834 byte_string to_bytes(const _Elem* __first, const _Elem* __last);
3835
Howard Hinnant82894812010-09-22 16:48:34 +00003836 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003837 size_t converted() const {return __cvtcount_;}
Howard Hinnant82894812010-09-22 16:48:34 +00003838 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003839 state_type state() const {return __cvtstate_;}
3840};
3841
3842template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Howard Hinnant82894812010-09-22 16:48:34 +00003843inline _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003844wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3845 wstring_convert(_Codecvt* __pcvt)
3846 : __cvtptr_(__pcvt), __cvtstate_(), __cvtcount_(0)
3847{
3848}
3849
3850template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Howard Hinnant82894812010-09-22 16:48:34 +00003851inline _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003852wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3853 wstring_convert(_Codecvt* __pcvt, state_type __state)
3854 : __cvtptr_(__pcvt), __cvtstate_(__state), __cvtcount_(0)
3855{
3856}
3857
3858template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3859wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3860 wstring_convert(const byte_string& __byte_err, const wide_string& __wide_err)
3861 : __byte_err_string_(__byte_err), __wide_err_string_(__wide_err),
3862 __cvtstate_(), __cvtcount_(0)
3863{
3864 __cvtptr_ = new _Codecvt;
3865}
3866
Howard Hinnant73d21a42010-09-04 23:28:19 +00003867#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantd23b4642010-05-31 20:58:54 +00003868
3869template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Howard Hinnant82894812010-09-22 16:48:34 +00003870inline _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003871wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3872 wstring_convert(wstring_convert&& __wc)
Howard Hinnant0949eed2011-06-30 21:18:19 +00003873 : __byte_err_string_(_VSTD::move(__wc.__byte_err_string_)),
3874 __wide_err_string_(_VSTD::move(__wc.__wide_err_string_)),
Howard Hinnantd23b4642010-05-31 20:58:54 +00003875 __cvtptr_(__wc.__cvtptr_),
3876 __cvtstate_(__wc.__cvtstate_), __cvtcount_(__wc.__cvtstate_)
3877{
3878 __wc.__cvtptr_ = nullptr;
3879}
3880
Howard Hinnantbfd55302010-09-04 23:46:48 +00003881#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantd23b4642010-05-31 20:58:54 +00003882
3883template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3884wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::~wstring_convert()
3885{
3886 delete __cvtptr_;
3887}
3888
3889template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3890typename wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::wide_string
3891wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3892 from_bytes(const char* __frm, const char* __frm_end)
3893{
3894 __cvtcount_ = 0;
3895 if (__cvtptr_ != nullptr)
3896 {
3897 wide_string __ws(2*(__frm_end - __frm), _Elem());
3898 __ws.resize(__ws.capacity());
3899 codecvt_base::result __r = codecvt_base::ok;
3900 state_type __st = __cvtstate_;
3901 if (__frm != __frm_end)
3902 {
3903 _Elem* __to = &__ws[0];
3904 _Elem* __to_end = __to + __ws.size();
3905 const char* __frm_nxt;
3906 do
3907 {
3908 _Elem* __to_nxt;
3909 __r = __cvtptr_->in(__st, __frm, __frm_end, __frm_nxt,
3910 __to, __to_end, __to_nxt);
3911 __cvtcount_ += __frm_nxt - __frm;
3912 if (__frm_nxt == __frm)
3913 {
3914 __r = codecvt_base::error;
3915 }
3916 else if (__r == codecvt_base::noconv)
3917 {
3918 __ws.resize(__to - &__ws[0]);
3919 // This only gets executed if _Elem is char
3920 __ws.append((const _Elem*)__frm, (const _Elem*)__frm_end);
3921 __frm = __frm_nxt;
3922 __r = codecvt_base::ok;
3923 }
3924 else if (__r == codecvt_base::ok)
3925 {
3926 __ws.resize(__to_nxt - &__ws[0]);
3927 __frm = __frm_nxt;
3928 }
3929 else if (__r == codecvt_base::partial)
3930 {
3931 ptrdiff_t __s = __to_nxt - &__ws[0];
3932 __ws.resize(2 * __s);
3933 __to = &__ws[0] + __s;
3934 __to_end = &__ws[0] + __ws.size();
3935 __frm = __frm_nxt;
3936 }
3937 } while (__r == codecvt_base::partial && __frm_nxt < __frm_end);
3938 }
3939 if (__r == codecvt_base::ok)
3940 return __ws;
3941 }
Howard Hinnantd4444702010-08-11 17:04:31 +00003942#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00003943 if (__wide_err_string_.empty())
3944 throw range_error("wstring_convert: from_bytes error");
Howard Hinnant324bb032010-08-22 00:02:43 +00003945#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00003946 return __wide_err_string_;
3947}
3948
3949template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3950typename wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::byte_string
3951wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3952 to_bytes(const _Elem* __frm, const _Elem* __frm_end)
3953{
3954 __cvtcount_ = 0;
3955 if (__cvtptr_ != nullptr)
3956 {
3957 byte_string __bs(2*(__frm_end - __frm), char());
3958 __bs.resize(__bs.capacity());
3959 codecvt_base::result __r = codecvt_base::ok;
3960 state_type __st = __cvtstate_;
3961 if (__frm != __frm_end)
3962 {
3963 char* __to = &__bs[0];
3964 char* __to_end = __to + __bs.size();
3965 const _Elem* __frm_nxt;
3966 do
3967 {
3968 char* __to_nxt;
3969 __r = __cvtptr_->out(__st, __frm, __frm_end, __frm_nxt,
3970 __to, __to_end, __to_nxt);
3971 __cvtcount_ += __frm_nxt - __frm;
3972 if (__frm_nxt == __frm)
3973 {
3974 __r = codecvt_base::error;
3975 }
3976 else if (__r == codecvt_base::noconv)
3977 {
3978 __bs.resize(__to - &__bs[0]);
3979 // This only gets executed if _Elem is char
3980 __bs.append((const char*)__frm, (const char*)__frm_end);
3981 __frm = __frm_nxt;
3982 __r = codecvt_base::ok;
3983 }
3984 else if (__r == codecvt_base::ok)
3985 {
3986 __bs.resize(__to_nxt - &__bs[0]);
3987 __frm = __frm_nxt;
3988 }
3989 else if (__r == codecvt_base::partial)
3990 {
3991 ptrdiff_t __s = __to_nxt - &__bs[0];
3992 __bs.resize(2 * __s);
3993 __to = &__bs[0] + __s;
3994 __to_end = &__bs[0] + __bs.size();
3995 __frm = __frm_nxt;
3996 }
3997 } while (__r == codecvt_base::partial && __frm_nxt < __frm_end);
3998 }
3999 if (__r == codecvt_base::ok)
4000 {
4001 size_t __s = __bs.size();
4002 __bs.resize(__bs.capacity());
4003 char* __to = &__bs[0] + __s;
4004 char* __to_end = __to + __bs.size();
4005 do
4006 {
4007 char* __to_nxt;
4008 __r = __cvtptr_->unshift(__st, __to, __to_end, __to_nxt);
4009 if (__r == codecvt_base::noconv)
4010 {
4011 __bs.resize(__to - &__bs[0]);
4012 __r = codecvt_base::ok;
4013 }
4014 else if (__r == codecvt_base::ok)
4015 {
4016 __bs.resize(__to_nxt - &__bs[0]);
4017 }
4018 else if (__r == codecvt_base::partial)
4019 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00004020 ptrdiff_t __sp = __to_nxt - &__bs[0];
4021 __bs.resize(2 * __sp);
4022 __to = &__bs[0] + __sp;
Howard Hinnantd23b4642010-05-31 20:58:54 +00004023 __to_end = &__bs[0] + __bs.size();
4024 }
4025 } while (__r == codecvt_base::partial);
4026 if (__r == codecvt_base::ok)
4027 return __bs;
4028 }
4029 }
Howard Hinnantd4444702010-08-11 17:04:31 +00004030#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00004031 if (__byte_err_string_.empty())
4032 throw range_error("wstring_convert: to_bytes error");
Howard Hinnant324bb032010-08-22 00:02:43 +00004033#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00004034 return __byte_err_string_;
4035}
4036
4037template <class _Codecvt, class _Elem = wchar_t, class _Tr = char_traits<_Elem> >
Howard Hinnant82894812010-09-22 16:48:34 +00004038class _LIBCPP_VISIBLE wbuffer_convert
Howard Hinnantd23b4642010-05-31 20:58:54 +00004039 : public basic_streambuf<_Elem, _Tr>
4040{
4041public:
4042 // types:
4043 typedef _Elem char_type;
4044 typedef _Tr traits_type;
4045 typedef typename traits_type::int_type int_type;
4046 typedef typename traits_type::pos_type pos_type;
4047 typedef typename traits_type::off_type off_type;
4048 typedef typename _Codecvt::state_type state_type;
4049
4050private:
Howard Hinnant4b53f502010-06-01 20:09:18 +00004051 char* __extbuf_;
4052 const char* __extbufnext_;
4053 const char* __extbufend_;
4054 char __extbuf_min_[8];
4055 size_t __ebs_;
4056 char_type* __intbuf_;
4057 size_t __ibs_;
Howard Hinnantd23b4642010-05-31 20:58:54 +00004058 streambuf* __bufptr_;
Howard Hinnant4b53f502010-06-01 20:09:18 +00004059 _Codecvt* __cv_;
4060 state_type __st_;
4061 ios_base::openmode __cm_;
4062 bool __owns_eb_;
4063 bool __owns_ib_;
4064 bool __always_noconv_;
Howard Hinnantd23b4642010-05-31 20:58:54 +00004065
Howard Hinnant4b53f502010-06-01 20:09:18 +00004066 wbuffer_convert(const wbuffer_convert&);
4067 wbuffer_convert& operator=(const wbuffer_convert&);
Howard Hinnantd23b4642010-05-31 20:58:54 +00004068public:
4069 wbuffer_convert(streambuf* __bytebuf = 0, _Codecvt* __pcvt = new _Codecvt,
Howard Hinnant4b53f502010-06-01 20:09:18 +00004070 state_type __state = state_type());
4071 ~wbuffer_convert();
Howard Hinnantd23b4642010-05-31 20:58:54 +00004072
Howard Hinnant82894812010-09-22 16:48:34 +00004073 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantd23b4642010-05-31 20:58:54 +00004074 streambuf* rdbuf() const {return __bufptr_;}
Howard Hinnant82894812010-09-22 16:48:34 +00004075 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantd23b4642010-05-31 20:58:54 +00004076 streambuf* rdbuf(streambuf* __bytebuf)
4077 {
4078 streambuf* __r = __bufptr_;
4079 __bufptr_ = __bytebuf;
4080 return __r;
4081 }
4082
Howard Hinnant82894812010-09-22 16:48:34 +00004083 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant4b53f502010-06-01 20:09:18 +00004084 state_type state() const {return __st_;}
Howard Hinnantd23b4642010-05-31 20:58:54 +00004085
4086protected:
Howard Hinnant4b53f502010-06-01 20:09:18 +00004087 virtual int_type underflow();
4088 virtual int_type pbackfail(int_type __c = traits_type::eof());
Howard Hinnantd23b4642010-05-31 20:58:54 +00004089 virtual int_type overflow (int_type __c = traits_type::eof());
Howard Hinnant4b53f502010-06-01 20:09:18 +00004090 virtual basic_streambuf<char_type, traits_type>* setbuf(char_type* __s,
4091 streamsize __n);
4092 virtual pos_type seekoff(off_type __off, ios_base::seekdir __way,
4093 ios_base::openmode __wch = ios_base::in | ios_base::out);
4094 virtual pos_type seekpos(pos_type __sp,
4095 ios_base::openmode __wch = ios_base::in | ios_base::out);
4096 virtual int sync();
4097
4098private:
4099 bool __read_mode();
4100 void __write_mode();
4101 wbuffer_convert* __close();
Howard Hinnantd23b4642010-05-31 20:58:54 +00004102};
4103
4104template <class _Codecvt, class _Elem, class _Tr>
Howard Hinnant4b53f502010-06-01 20:09:18 +00004105wbuffer_convert<_Codecvt, _Elem, _Tr>::
4106 wbuffer_convert(streambuf* __bytebuf, _Codecvt* __pcvt, state_type __state)
4107 : __extbuf_(0),
4108 __extbufnext_(0),
4109 __extbufend_(0),
4110 __ebs_(0),
4111 __intbuf_(0),
4112 __ibs_(0),
4113 __bufptr_(__bytebuf),
4114 __cv_(__pcvt),
4115 __st_(__state),
4116 __cm_(0),
4117 __owns_eb_(false),
4118 __owns_ib_(false),
4119 __always_noconv_(__cv_ ? __cv_->always_noconv() : false)
4120{
4121 setbuf(0, 4096);
4122}
4123
4124template <class _Codecvt, class _Elem, class _Tr>
4125wbuffer_convert<_Codecvt, _Elem, _Tr>::~wbuffer_convert()
4126{
4127 __close();
4128 delete __cv_;
4129 if (__owns_eb_)
4130 delete [] __extbuf_;
4131 if (__owns_ib_)
4132 delete [] __intbuf_;
4133}
4134
4135template <class _Codecvt, class _Elem, class _Tr>
4136typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
4137wbuffer_convert<_Codecvt, _Elem, _Tr>::underflow()
4138{
4139 if (__cv_ == 0 || __bufptr_ == 0)
4140 return traits_type::eof();
4141 bool __initial = __read_mode();
4142 char_type __1buf;
4143 if (this->gptr() == 0)
4144 this->setg(&__1buf, &__1buf+1, &__1buf+1);
4145 const size_t __unget_sz = __initial ? 0 : min<size_t>((this->egptr() - this->eback()) / 2, 4);
4146 int_type __c = traits_type::eof();
4147 if (this->gptr() == this->egptr())
4148 {
4149 memmove(this->eback(), this->egptr() - __unget_sz, __unget_sz * sizeof(char_type));
4150 if (__always_noconv_)
4151 {
4152 streamsize __nmemb = static_cast<streamsize>(this->egptr() - this->eback() - __unget_sz);
4153 __nmemb = __bufptr_->sgetn((char*)this->eback() + __unget_sz, __nmemb);
4154 if (__nmemb != 0)
4155 {
4156 this->setg(this->eback(),
4157 this->eback() + __unget_sz,
4158 this->eback() + __unget_sz + __nmemb);
4159 __c = *this->gptr();
4160 }
4161 }
4162 else
4163 {
4164 memmove(__extbuf_, __extbufnext_, __extbufend_ - __extbufnext_);
4165 __extbufnext_ = __extbuf_ + (__extbufend_ - __extbufnext_);
4166 __extbufend_ = __extbuf_ + (__extbuf_ == __extbuf_min_ ? sizeof(__extbuf_min_) : __ebs_);
Howard Hinnant0949eed2011-06-30 21:18:19 +00004167 streamsize __nmemb = _VSTD::min(static_cast<streamsize>(this->egptr() - this->eback() - __unget_sz),
Howard Hinnant4b53f502010-06-01 20:09:18 +00004168 static_cast<streamsize>(__extbufend_ - __extbufnext_));
4169 codecvt_base::result __r;
4170 state_type __svs = __st_;
4171 streamsize __nr = __bufptr_->sgetn(const_cast<char*>(__extbufnext_), __nmemb);
4172 if (__nr != 0)
4173 {
4174 __extbufend_ = __extbufnext_ + __nr;
4175 char_type* __inext;
4176 __r = __cv_->in(__st_, __extbuf_, __extbufend_, __extbufnext_,
4177 this->eback() + __unget_sz,
4178 this->egptr(), __inext);
4179 if (__r == codecvt_base::noconv)
4180 {
4181 this->setg((char_type*)__extbuf_, (char_type*)__extbuf_, (char_type*)__extbufend_);
4182 __c = *this->gptr();
4183 }
4184 else if (__inext != this->eback() + __unget_sz)
4185 {
4186 this->setg(this->eback(), this->eback() + __unget_sz, __inext);
4187 __c = *this->gptr();
4188 }
4189 }
4190 }
4191 }
4192 else
4193 __c = *this->gptr();
4194 if (this->eback() == &__1buf)
4195 this->setg(0, 0, 0);
4196 return __c;
4197}
4198
4199template <class _Codecvt, class _Elem, class _Tr>
4200typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
4201wbuffer_convert<_Codecvt, _Elem, _Tr>::pbackfail(int_type __c)
4202{
4203 if (__cv_ != 0 && __bufptr_ != 0 && this->eback() < this->gptr())
4204 {
4205 if (traits_type::eq_int_type(__c, traits_type::eof()))
4206 {
4207 this->gbump(-1);
4208 return traits_type::not_eof(__c);
4209 }
4210 if (traits_type::eq(traits_type::to_char_type(__c), this->gptr()[-1]))
4211 {
4212 this->gbump(-1);
4213 *this->gptr() = traits_type::to_char_type(__c);
4214 return __c;
4215 }
4216 }
4217 return traits_type::eof();
4218}
4219
4220template <class _Codecvt, class _Elem, class _Tr>
Howard Hinnantd23b4642010-05-31 20:58:54 +00004221typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
4222wbuffer_convert<_Codecvt, _Elem, _Tr>::overflow(int_type __c)
4223{
Howard Hinnant4b53f502010-06-01 20:09:18 +00004224 if (__cv_ == 0 || __bufptr_ == 0)
4225 return traits_type::eof();
4226 __write_mode();
4227 char_type __1buf;
4228 char_type* __pb_save = this->pbase();
4229 char_type* __epb_save = this->epptr();
4230 if (!traits_type::eq_int_type(__c, traits_type::eof()))
4231 {
4232 if (this->pptr() == 0)
4233 this->setp(&__1buf, &__1buf+1);
4234 *this->pptr() = traits_type::to_char_type(__c);
4235 this->pbump(1);
4236 }
4237 if (this->pptr() != this->pbase())
4238 {
4239 if (__always_noconv_)
4240 {
4241 streamsize __nmemb = static_cast<streamsize>(this->pptr() - this->pbase());
4242 if (__bufptr_->sputn((const char*)this->pbase(), __nmemb) != __nmemb)
4243 return traits_type::eof();
4244 }
4245 else
4246 {
4247 char* __extbe = __extbuf_;
4248 codecvt_base::result __r;
4249 do
4250 {
4251 const char_type* __e;
4252 __r = __cv_->out(__st_, this->pbase(), this->pptr(), __e,
4253 __extbuf_, __extbuf_ + __ebs_, __extbe);
4254 if (__e == this->pbase())
4255 return traits_type::eof();
4256 if (__r == codecvt_base::noconv)
4257 {
4258 streamsize __nmemb = static_cast<size_t>(this->pptr() - this->pbase());
4259 if (__bufptr_->sputn((const char*)this->pbase(), __nmemb) != __nmemb)
4260 return traits_type::eof();
4261 }
4262 else if (__r == codecvt_base::ok || __r == codecvt_base::partial)
4263 {
4264 streamsize __nmemb = static_cast<size_t>(__extbe - __extbuf_);
4265 if (__bufptr_->sputn(__extbuf_, __nmemb) != __nmemb)
4266 return traits_type::eof();
4267 if (__r == codecvt_base::partial)
4268 {
4269 this->setp((char_type*)__e, this->pptr());
4270 this->pbump(this->epptr() - this->pbase());
4271 }
4272 }
4273 else
4274 return traits_type::eof();
4275 } while (__r == codecvt_base::partial);
4276 }
4277 this->setp(__pb_save, __epb_save);
4278 }
4279 return traits_type::not_eof(__c);
4280}
4281
4282template <class _Codecvt, class _Elem, class _Tr>
4283basic_streambuf<_Elem, _Tr>*
4284wbuffer_convert<_Codecvt, _Elem, _Tr>::setbuf(char_type* __s, streamsize __n)
4285{
4286 this->setg(0, 0, 0);
4287 this->setp(0, 0);
4288 if (__owns_eb_)
4289 delete [] __extbuf_;
4290 if (__owns_ib_)
4291 delete [] __intbuf_;
4292 __ebs_ = __n;
4293 if (__ebs_ > sizeof(__extbuf_min_))
4294 {
4295 if (__always_noconv_ && __s)
4296 {
4297 __extbuf_ = (char*)__s;
4298 __owns_eb_ = false;
4299 }
4300 else
4301 {
4302 __extbuf_ = new char[__ebs_];
4303 __owns_eb_ = true;
4304 }
4305 }
4306 else
4307 {
4308 __extbuf_ = __extbuf_min_;
4309 __ebs_ = sizeof(__extbuf_min_);
4310 __owns_eb_ = false;
4311 }
4312 if (!__always_noconv_)
4313 {
4314 __ibs_ = max<streamsize>(__n, sizeof(__extbuf_min_));
4315 if (__s && __ibs_ >= sizeof(__extbuf_min_))
4316 {
4317 __intbuf_ = __s;
4318 __owns_ib_ = false;
4319 }
4320 else
4321 {
4322 __intbuf_ = new char_type[__ibs_];
4323 __owns_ib_ = true;
4324 }
4325 }
4326 else
4327 {
4328 __ibs_ = 0;
4329 __intbuf_ = 0;
4330 __owns_ib_ = false;
4331 }
4332 return this;
4333}
4334
4335template <class _Codecvt, class _Elem, class _Tr>
4336typename wbuffer_convert<_Codecvt, _Elem, _Tr>::pos_type
4337wbuffer_convert<_Codecvt, _Elem, _Tr>::seekoff(off_type __off, ios_base::seekdir __way,
4338 ios_base::openmode __om)
4339{
4340 int __width = __cv_->encoding();
4341 if (__cv_ == 0 || __bufptr_ == 0 || (__width <= 0 && __off != 0) || sync())
4342 return pos_type(off_type(-1));
4343 // __width > 0 || __off == 0
4344 switch (__way)
4345 {
4346 case ios_base::beg:
4347 break;
4348 case ios_base::cur:
4349 break;
4350 case ios_base::end:
4351 break;
4352 default:
4353 return pos_type(off_type(-1));
4354 }
4355 pos_type __r = __bufptr_->pubseekoff(__width * __off, __way, __om);
4356 __r.state(__st_);
4357 return __r;
4358}
4359
4360template <class _Codecvt, class _Elem, class _Tr>
4361typename wbuffer_convert<_Codecvt, _Elem, _Tr>::pos_type
4362wbuffer_convert<_Codecvt, _Elem, _Tr>::seekpos(pos_type __sp, ios_base::openmode __wch)
4363{
4364 if (__cv_ == 0 || __bufptr_ == 0 || sync())
4365 return pos_type(off_type(-1));
4366 if (__bufptr_->pubseekpos(__sp, __wch) == pos_type(off_type(-1)))
4367 return pos_type(off_type(-1));
4368 return __sp;
4369}
4370
4371template <class _Codecvt, class _Elem, class _Tr>
4372int
4373wbuffer_convert<_Codecvt, _Elem, _Tr>::sync()
4374{
4375 if (__cv_ == 0 || __bufptr_ == 0)
4376 return 0;
4377 if (__cm_ & ios_base::out)
4378 {
4379 if (this->pptr() != this->pbase())
4380 if (overflow() == traits_type::eof())
4381 return -1;
4382 codecvt_base::result __r;
4383 do
4384 {
4385 char* __extbe;
4386 __r = __cv_->unshift(__st_, __extbuf_, __extbuf_ + __ebs_, __extbe);
4387 streamsize __nmemb = static_cast<streamsize>(__extbe - __extbuf_);
4388 if (__bufptr_->sputn(__extbuf_, __nmemb) != __nmemb)
4389 return -1;
4390 } while (__r == codecvt_base::partial);
4391 if (__r == codecvt_base::error)
4392 return -1;
4393 if (__bufptr_->pubsync())
4394 return -1;
4395 }
4396 else if (__cm_ & ios_base::in)
4397 {
4398 off_type __c;
4399 if (__always_noconv_)
4400 __c = this->egptr() - this->gptr();
4401 else
4402 {
4403 int __width = __cv_->encoding();
4404 __c = __extbufend_ - __extbufnext_;
4405 if (__width > 0)
4406 __c += __width * (this->egptr() - this->gptr());
4407 else
4408 {
4409 if (this->gptr() != this->egptr())
4410 {
4411 reverse(this->gptr(), this->egptr());
4412 codecvt_base::result __r;
4413 const char_type* __e = this->gptr();
4414 char* __extbe;
4415 do
4416 {
4417 __r = __cv_->out(__st_, __e, this->egptr(), __e,
4418 __extbuf_, __extbuf_ + __ebs_, __extbe);
4419 switch (__r)
4420 {
4421 case codecvt_base::noconv:
4422 __c += this->egptr() - this->gptr();
4423 break;
4424 case codecvt_base::ok:
4425 case codecvt_base::partial:
4426 __c += __extbe - __extbuf_;
4427 break;
4428 default:
4429 return -1;
4430 }
4431 } while (__r == codecvt_base::partial);
4432 }
4433 }
4434 }
4435 if (__bufptr_->pubseekoff(-__c, ios_base::cur, __cm_) == pos_type(off_type(-1)))
4436 return -1;
4437 this->setg(0, 0, 0);
4438 __cm_ = 0;
4439 }
4440 return 0;
4441}
4442
4443template <class _Codecvt, class _Elem, class _Tr>
4444bool
4445wbuffer_convert<_Codecvt, _Elem, _Tr>::__read_mode()
4446{
4447 if (!(__cm_ & ios_base::in))
4448 {
4449 this->setp(0, 0);
4450 if (__always_noconv_)
4451 this->setg((char_type*)__extbuf_,
4452 (char_type*)__extbuf_ + __ebs_,
4453 (char_type*)__extbuf_ + __ebs_);
4454 else
4455 this->setg(__intbuf_, __intbuf_ + __ibs_, __intbuf_ + __ibs_);
4456 __cm_ = ios_base::in;
4457 return true;
4458 }
4459 return false;
4460}
4461
4462template <class _Codecvt, class _Elem, class _Tr>
4463void
4464wbuffer_convert<_Codecvt, _Elem, _Tr>::__write_mode()
4465{
4466 if (!(__cm_ & ios_base::out))
4467 {
4468 this->setg(0, 0, 0);
4469 if (__ebs_ > sizeof(__extbuf_min_))
4470 {
4471 if (__always_noconv_)
4472 this->setp((char_type*)__extbuf_,
4473 (char_type*)__extbuf_ + (__ebs_ - 1));
4474 else
4475 this->setp(__intbuf_, __intbuf_ + (__ibs_ - 1));
4476 }
4477 else
4478 this->setp(0, 0);
4479 __cm_ = ios_base::out;
4480 }
4481}
4482
4483template <class _Codecvt, class _Elem, class _Tr>
4484wbuffer_convert<_Codecvt, _Elem, _Tr>*
4485wbuffer_convert<_Codecvt, _Elem, _Tr>::__close()
4486{
4487 wbuffer_convert* __rt = 0;
4488 if (__cv_ != 0 && __bufptr_ != 0)
4489 {
4490 __rt = this;
4491 if ((__cm_ & ios_base::out) && sync())
4492 __rt = 0;
4493 }
4494 return __rt;
Howard Hinnantd23b4642010-05-31 20:58:54 +00004495}
4496
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004497_LIBCPP_END_NAMESPACE_STD
4498
4499#endif // _LIBCPP_LOCALE