blob: bec27f6d9eb28b76ddf3fc21b5b6b4dd86ed8ba9 [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;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00003063 // Capture the spaces read into money_base::{space,none} so they
3064 // can be compared to initial spaces in __sym.
3065 string_type __spaces;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003066 int __fd;
3067 __money_get<_CharT>::__gather_info(__intl, __loc, __pat, __dp, __ts, __grp,
3068 __sym, __psn, __nsn, __fd);
3069 const string_type* __trailing_sign = 0;
3070 __wn = __wb.get();
3071 for (unsigned __p = 0; __p < 4 && __b != __e; ++__p)
3072 {
3073 switch (__pat.field[__p])
3074 {
3075 case money_base::space:
3076 if (__p != 3)
3077 {
3078 if (__ct.is(ctype_base::space, *__b))
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00003079 __spaces.push_back(*__b++);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003080 else
3081 {
3082 __err |= ios_base::failbit;
3083 return false;
3084 }
3085 }
Howard Hinnant324bb032010-08-22 00:02:43 +00003086 // drop through
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003087 case money_base::none:
3088 if (__p != 3)
3089 {
3090 while (__b != __e && __ct.is(ctype_base::space, *__b))
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00003091 __spaces.push_back(*__b++);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003092 }
3093 break;
3094 case money_base::sign:
3095 if (__psn.size() + __nsn.size() > 0)
3096 {
3097 if (__psn.size() == 0 || __nsn.size() == 0)
3098 { // sign is optional
3099 if (__psn.size() > 0)
3100 { // __nsn.size() == 0
3101 if (*__b == __psn[0])
3102 {
3103 ++__b;
3104 if (__psn.size() > 1)
3105 __trailing_sign = &__psn;
3106 }
3107 else
3108 __neg = true;
3109 }
3110 else if (*__b == __nsn[0]) // __nsn.size() > 0 && __psn.size() == 0
3111 {
3112 ++__b;
3113 __neg = true;
3114 if (__nsn.size() > 1)
3115 __trailing_sign = &__nsn;
3116 }
3117 }
3118 else // sign is required
3119 {
3120 if (*__b == __psn[0])
3121 {
3122 ++__b;
3123 if (__psn.size() > 1)
3124 __trailing_sign = &__psn;
3125 }
3126 else if (*__b == __nsn[0])
3127 {
3128 ++__b;
3129 __neg = true;
3130 if (__nsn.size() > 1)
3131 __trailing_sign = &__nsn;
3132 }
3133 else
3134 {
3135 __err |= ios_base::failbit;
3136 return false;
3137 }
3138 }
3139 }
3140 break;
3141 case money_base::symbol:
3142 {
3143 bool __more_needed = __trailing_sign ||
3144 (__p < 2) ||
3145 (__p == 2 && __pat.field[3] != static_cast<char>(money_base::none));
3146 bool __sb = __flags & ios_base::showbase;
3147 if (__sb || __more_needed)
3148 {
3149 ios_base::iostate __et = ios_base::goodbit;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00003150 typename string_type::const_iterator __sym_space_end = __sym.begin();
3151 if (__p > 0 && (__pat.field[__p - 1] == money_base::none ||
3152 __pat.field[__p - 1] == money_base::space)) {
3153 // Match spaces we've already read against spaces at
3154 // the beginning of __sym.
3155 while (__sym_space_end != __sym.end() &&
3156 __ct.is(ctype_base::space, *__sym_space_end))
3157 ++__sym_space_end;
3158 const size_t __num_spaces = __sym_space_end - __sym.begin();
3159 if (__num_spaces > __spaces.size() ||
3160 !equal(__spaces.end() - __num_spaces, __spaces.end(),
3161 __sym.begin())) {
3162 // No match. Put __sym_space_end back at the
3163 // beginning of __sym, which will prevent a
3164 // match in the next loop.
3165 __sym_space_end = __sym.begin();
3166 }
3167 }
3168 typename string_type::const_iterator __sym_curr_char = __sym_space_end;
3169 while (__sym_curr_char != __sym.end() && __b != __e &&
3170 *__b == *__sym_curr_char) {
3171 ++__b;
3172 ++__sym_curr_char;
3173 }
3174 if (__sb && __sym_curr_char != __sym.end())
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003175 {
3176 __err |= ios_base::failbit;
3177 return false;
3178 }
3179 }
3180 }
3181 break;
3182 case money_base::value:
3183 {
3184 unsigned __ng = 0;
3185 for (; __b != __e; ++__b)
3186 {
3187 char_type __c = *__b;
3188 if (__ct.is(ctype_base::digit, __c))
3189 {
3190 if (__wn == __we)
3191 __double_or_nothing(__wb, __wn, __we);
3192 *__wn++ = __c;
3193 ++__ng;
3194 }
3195 else if (__grp.size() > 0 && __ng > 0 && __c == __ts)
3196 {
3197 if (__gn == __ge)
3198 __double_or_nothing(__gb, __gn, __ge);
3199 *__gn++ = __ng;
3200 __ng = 0;
3201 }
3202 else
3203 break;
3204 }
3205 if (__gb.get() != __gn && __ng > 0)
3206 {
3207 if (__gn == __ge)
3208 __double_or_nothing(__gb, __gn, __ge);
3209 *__gn++ = __ng;
3210 }
3211 if (__fd > 0)
3212 {
3213 if (__b == __e || *__b != __dp)
3214 {
3215 __err |= ios_base::failbit;
3216 return false;
3217 }
3218 for (++__b; __fd > 0; --__fd, ++__b)
3219 {
3220 if (__b == __e || !__ct.is(ctype_base::digit, *__b))
3221 {
3222 __err |= ios_base::failbit;
3223 return false;
3224 }
3225 if (__wn == __we)
3226 __double_or_nothing(__wb, __wn, __we);
3227 *__wn++ = *__b;
3228 }
3229 }
3230 if (__wn == __wb.get())
3231 {
3232 __err |= ios_base::failbit;
3233 return false;
3234 }
3235 }
3236 break;
3237 }
3238 }
3239 if (__trailing_sign)
3240 {
3241 for (unsigned __i = 1; __i < __trailing_sign->size(); ++__i, ++__b)
3242 {
3243 if (__b == __e || *__b != (*__trailing_sign)[__i])
3244 {
3245 __err |= ios_base::failbit;
3246 return false;
3247 }
3248 }
3249 }
3250 if (__gb.get() != __gn)
3251 {
3252 ios_base::iostate __et = ios_base::goodbit;
3253 __check_grouping(__grp, __gb.get(), __gn, __et);
3254 if (__et)
3255 {
3256 __err |= ios_base::failbit;
3257 return false;
3258 }
3259 }
3260 return true;
3261}
3262
3263template <class _CharT, class _InputIterator>
3264_InputIterator
3265money_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
3266 bool __intl, ios_base& __iob,
3267 ios_base::iostate& __err,
3268 long double& __v) const
3269{
Howard Hinnantec3773c2011-12-01 20:21:04 +00003270 const int __bz = 100;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003271 char_type __wbuf[__bz];
3272 unique_ptr<char_type, void(*)(void*)> __wb(__wbuf, __do_nothing);
3273 char_type* __wn;
3274 char_type* __we = __wbuf + __bz;
3275 locale __loc = __iob.getloc();
3276 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3277 bool __neg = false;
3278 if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct,
3279 __wb, __wn, __we))
3280 {
3281 const char __src[] = "0123456789";
3282 char_type __atoms[sizeof(__src)-1];
3283 __ct.widen(__src, __src + (sizeof(__src)-1), __atoms);
3284 char __nbuf[__bz];
3285 char* __nc = __nbuf;
3286 unique_ptr<char, void(*)(void*)> __h(0, free);
3287 if (__wn - __wb.get() > __bz-2)
3288 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00003289 __h.reset((char*)malloc(static_cast<size_t>(__wn - __wb.get() + 2)));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003290 if (__h.get() == 0)
3291 __throw_bad_alloc();
3292 __nc = __h.get();
3293 }
3294 if (__neg)
3295 *__nc++ = '-';
3296 for (const char_type* __w = __wb.get(); __w < __wn; ++__w, ++__nc)
3297 *__nc = __src[find(__atoms, __atoms+sizeof(__atoms), *__w) - __atoms];
3298 *__nc = char();
3299 if (sscanf(__nbuf, "%Lf", &__v) != 1)
3300 __throw_runtime_error("money_get error");
3301 }
3302 if (__b == __e)
3303 __err |= ios_base::eofbit;
3304 return __b;
3305}
3306
3307template <class _CharT, class _InputIterator>
3308_InputIterator
3309money_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
3310 bool __intl, ios_base& __iob,
3311 ios_base::iostate& __err,
3312 string_type& __v) const
3313{
Howard Hinnantec3773c2011-12-01 20:21:04 +00003314 const int __bz = 100;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003315 char_type __wbuf[__bz];
3316 unique_ptr<char_type, void(*)(void*)> __wb(__wbuf, __do_nothing);
3317 char_type* __wn;
3318 char_type* __we = __wbuf + __bz;
3319 locale __loc = __iob.getloc();
3320 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3321 bool __neg = false;
3322 if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct,
3323 __wb, __wn, __we))
3324 {
3325 __v.clear();
3326 if (__neg)
3327 __v.push_back(__ct.widen('-'));
3328 char_type __z = __ct.widen('0');
3329 char_type* __w;
3330 for (__w = __wb.get(); __w < __wn-1; ++__w)
3331 if (*__w != __z)
3332 break;
3333 __v.append(__w, __wn);
3334 }
3335 if (__b == __e)
3336 __err |= ios_base::eofbit;
3337 return __b;
3338}
3339
3340extern template class money_get<char>;
3341extern template class money_get<wchar_t>;
3342
3343// money_put
3344
3345template <class _CharT>
3346class __money_put
3347{
3348protected:
3349 typedef _CharT char_type;
3350 typedef basic_string<char_type> string_type;
3351
3352 _LIBCPP_ALWAYS_INLINE __money_put() {}
3353
3354 static void __gather_info(bool __intl, bool __neg, const locale& __loc,
3355 money_base::pattern& __pat, char_type& __dp,
3356 char_type& __ts, string& __grp,
3357 string_type& __sym, string_type& __sn,
3358 int& __fd);
3359 static void __format(char_type* __mb, char_type*& __mi, char_type*& __me,
3360 ios_base::fmtflags __flags,
3361 const char_type* __db, const char_type* __de,
3362 const ctype<char_type>& __ct, bool __neg,
3363 const money_base::pattern& __pat, char_type __dp,
3364 char_type __ts, const string& __grp,
3365 const string_type& __sym, const string_type& __sn,
3366 int __fd);
3367};
3368
3369template <class _CharT>
3370void
3371__money_put<_CharT>::__gather_info(bool __intl, bool __neg, const locale& __loc,
3372 money_base::pattern& __pat, char_type& __dp,
3373 char_type& __ts, string& __grp,
3374 string_type& __sym, string_type& __sn,
3375 int& __fd)
3376{
3377 if (__intl)
3378 {
3379 const moneypunct<char_type, true>& __mp =
3380 use_facet<moneypunct<char_type, true> >(__loc);
3381 if (__neg)
3382 {
3383 __pat = __mp.neg_format();
3384 __sn = __mp.negative_sign();
3385 }
3386 else
3387 {
3388 __pat = __mp.pos_format();
3389 __sn = __mp.positive_sign();
3390 }
3391 __dp = __mp.decimal_point();
3392 __ts = __mp.thousands_sep();
3393 __grp = __mp.grouping();
3394 __sym = __mp.curr_symbol();
3395 __fd = __mp.frac_digits();
3396 }
3397 else
3398 {
3399 const moneypunct<char_type, false>& __mp =
3400 use_facet<moneypunct<char_type, false> >(__loc);
3401 if (__neg)
3402 {
3403 __pat = __mp.neg_format();
3404 __sn = __mp.negative_sign();
3405 }
3406 else
3407 {
3408 __pat = __mp.pos_format();
3409 __sn = __mp.positive_sign();
3410 }
3411 __dp = __mp.decimal_point();
3412 __ts = __mp.thousands_sep();
3413 __grp = __mp.grouping();
3414 __sym = __mp.curr_symbol();
3415 __fd = __mp.frac_digits();
3416 }
3417}
3418
3419template <class _CharT>
3420void
3421__money_put<_CharT>::__format(char_type* __mb, char_type*& __mi, char_type*& __me,
3422 ios_base::fmtflags __flags,
3423 const char_type* __db, const char_type* __de,
3424 const ctype<char_type>& __ct, bool __neg,
3425 const money_base::pattern& __pat, char_type __dp,
3426 char_type __ts, const string& __grp,
3427 const string_type& __sym, const string_type& __sn,
3428 int __fd)
3429{
3430 __me = __mb;
3431 for (unsigned __p = 0; __p < 4; ++__p)
3432 {
3433 switch (__pat.field[__p])
3434 {
3435 case money_base::none:
3436 __mi = __me;
3437 break;
3438 case money_base::space:
3439 __mi = __me;
3440 *__me++ = __ct.widen(' ');
3441 break;
3442 case money_base::sign:
3443 if (!__sn.empty())
3444 *__me++ = __sn[0];
3445 break;
3446 case money_base::symbol:
3447 if (!__sym.empty() && (__flags & ios_base::showbase))
Howard Hinnant0949eed2011-06-30 21:18:19 +00003448 __me = _VSTD::copy(__sym.begin(), __sym.end(), __me);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003449 break;
3450 case money_base::value:
3451 {
3452 // remember start of value so we can reverse it
3453 char_type* __t = __me;
3454 // find beginning of digits
3455 if (__neg)
3456 ++__db;
3457 // find end of digits
3458 const char_type* __d;
3459 for (__d = __db; __d < __de; ++__d)
3460 if (!__ct.is(ctype_base::digit, *__d))
3461 break;
3462 // print fractional part
3463 if (__fd > 0)
3464 {
3465 int __f;
3466 for (__f = __fd; __d > __db && __f > 0; --__f)
3467 *__me++ = *--__d;
3468 char_type __z = __f > 0 ? __ct.widen('0') : char_type();
3469 for (; __f > 0; --__f)
3470 *__me++ = __z;
3471 *__me++ = __dp;
3472 }
3473 // print units part
3474 if (__d == __db)
3475 {
3476 *__me++ = __ct.widen('0');
3477 }
3478 else
3479 {
3480 unsigned __ng = 0;
3481 unsigned __ig = 0;
3482 unsigned __gl = __grp.empty() ? numeric_limits<unsigned>::max()
3483 : static_cast<unsigned>(__grp[__ig]);
3484 while (__d != __db)
3485 {
3486 if (__ng == __gl)
3487 {
3488 *__me++ = __ts;
3489 __ng = 0;
3490 if (++__ig < __grp.size())
3491 __gl = __grp[__ig] == numeric_limits<char>::max() ?
3492 numeric_limits<unsigned>::max() :
3493 static_cast<unsigned>(__grp[__ig]);
3494 }
3495 *__me++ = *--__d;
3496 ++__ng;
3497 }
3498 }
3499 // reverse it
3500 reverse(__t, __me);
3501 }
3502 break;
3503 }
3504 }
3505 // print rest of sign, if any
3506 if (__sn.size() > 1)
Howard Hinnant0949eed2011-06-30 21:18:19 +00003507 __me = _VSTD::copy(__sn.begin()+1, __sn.end(), __me);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003508 // set alignment
3509 if ((__flags & ios_base::adjustfield) == ios_base::left)
3510 __mi = __me;
3511 else if ((__flags & ios_base::adjustfield) != ios_base::internal)
3512 __mi = __mb;
3513}
3514
3515extern template class __money_put<char>;
3516extern template class __money_put<wchar_t>;
3517
3518template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00003519class _LIBCPP_VISIBLE money_put
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003520 : public locale::facet,
3521 private __money_put<_CharT>
3522{
3523public:
3524 typedef _CharT char_type;
3525 typedef _OutputIterator iter_type;
3526 typedef basic_string<char_type> string_type;
3527
3528 _LIBCPP_ALWAYS_INLINE
3529 explicit money_put(size_t __refs = 0)
3530 : locale::facet(__refs) {}
3531
3532 _LIBCPP_ALWAYS_INLINE
3533 iter_type put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl,
3534 long double __units) const
3535 {
3536 return do_put(__s, __intl, __iob, __fl, __units);
3537 }
3538
3539 _LIBCPP_ALWAYS_INLINE
3540 iter_type put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl,
3541 const string_type& __digits) const
3542 {
3543 return do_put(__s, __intl, __iob, __fl, __digits);
3544 }
3545
3546 static locale::id id;
3547
3548protected:
Howard Hinnant82894812010-09-22 16:48:34 +00003549 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003550 ~money_put() {}
3551
3552 virtual iter_type do_put(iter_type __s, bool __intl, ios_base& __iob,
3553 char_type __fl, long double __units) const;
3554 virtual iter_type do_put(iter_type __s, bool __intl, ios_base& __iob,
3555 char_type __fl, const string_type& __digits) const;
3556};
3557
3558template <class _CharT, class _OutputIterator>
3559locale::id
3560money_put<_CharT, _OutputIterator>::id;
3561
3562template <class _CharT, class _OutputIterator>
3563_OutputIterator
3564money_put<_CharT, _OutputIterator>::do_put(iter_type __s, bool __intl,
3565 ios_base& __iob, char_type __fl,
3566 long double __units) const
3567{
3568 // convert to char
3569 const size_t __bs = 100;
3570 char __buf[__bs];
3571 char* __bb = __buf;
3572 char_type __digits[__bs];
3573 char_type* __db = __digits;
Howard Hinnantec3773c2011-12-01 20:21:04 +00003574 size_t __n = static_cast<size_t>(snprintf(__bb, __bs, "%.0Lf", __units));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003575 unique_ptr<char, void(*)(void*)> __hn(0, free);
3576 unique_ptr<char_type, void(*)(void*)> __hd(0, free);
3577 // secure memory for digit storage
3578 if (__n > __bs-1)
3579 {
Howard Hinnant866569b2011-09-28 23:39:33 +00003580#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00003581 __n = static_cast<size_t>(asprintf_l(&__bb, _LIBCPP_GET_C_LOCALE, "%.0Lf", __units));
Sean Huntf3907e62011-07-15 05:40:33 +00003582#else
3583 __n = __asprintf_l(&__bb, __cloc(), "%.0Lf", __units);
3584#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003585 if (__bb == 0)
3586 __throw_bad_alloc();
3587 __hn.reset(__bb);
3588 __hd.reset((char_type*)malloc(__n * sizeof(char_type)));
Howard Hinnant05b57d52012-03-07 20:37:43 +00003589 if (__hd == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003590 __throw_bad_alloc();
3591 __db = __hd.get();
3592 }
3593 // gather info
3594 locale __loc = __iob.getloc();
3595 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3596 __ct.widen(__bb, __bb + __n, __db);
3597 bool __neg = __n > 0 && __bb[0] == '-';
3598 money_base::pattern __pat;
3599 char_type __dp;
3600 char_type __ts;
3601 string __grp;
3602 string_type __sym;
3603 string_type __sn;
3604 int __fd;
3605 this->__gather_info(__intl, __neg, __loc, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3606 // secure memory for formatting
3607 char_type __mbuf[__bs];
3608 char_type* __mb = __mbuf;
3609 unique_ptr<char_type, void(*)(void*)> __hw(0, free);
3610 size_t __exn = static_cast<int>(__n) > __fd ?
Howard Hinnantec3773c2011-12-01 20:21:04 +00003611 (__n - static_cast<size_t>(__fd)) * 2 + __sn.size() +
3612 __sym.size() + static_cast<size_t>(__fd) + 1
3613 : __sn.size() + __sym.size() + static_cast<size_t>(__fd) + 2;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003614 if (__exn > __bs)
3615 {
3616 __hw.reset((char_type*)malloc(__exn * sizeof(char_type)));
3617 __mb = __hw.get();
3618 if (__mb == 0)
3619 __throw_bad_alloc();
3620 }
3621 // format
3622 char_type* __mi;
3623 char_type* __me;
3624 this->__format(__mb, __mi, __me, __iob.flags(),
3625 __db, __db + __n, __ct,
3626 __neg, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3627 return __pad_and_output(__s, __mb, __mi, __me, __iob, __fl);
3628}
3629
3630template <class _CharT, class _OutputIterator>
3631_OutputIterator
3632money_put<_CharT, _OutputIterator>::do_put(iter_type __s, bool __intl,
3633 ios_base& __iob, char_type __fl,
3634 const string_type& __digits) const
3635{
3636 // gather info
3637 locale __loc = __iob.getloc();
3638 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3639 bool __neg = __digits.size() > 0 && __digits[0] == __ct.widen('-');
3640 money_base::pattern __pat;
3641 char_type __dp;
3642 char_type __ts;
3643 string __grp;
3644 string_type __sym;
3645 string_type __sn;
3646 int __fd;
3647 this->__gather_info(__intl, __neg, __loc, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3648 // secure memory for formatting
3649 char_type __mbuf[100];
3650 char_type* __mb = __mbuf;
3651 unique_ptr<char_type, void(*)(void*)> __h(0, free);
Howard Hinnantec3773c2011-12-01 20:21:04 +00003652 size_t __exn = static_cast<int>(__digits.size()) > __fd ?
3653 (__digits.size() - static_cast<size_t>(__fd)) * 2 +
3654 __sn.size() + __sym.size() + static_cast<size_t>(__fd) + 1
3655 : __sn.size() + __sym.size() + static_cast<size_t>(__fd) + 2;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003656 if (__exn > 100)
3657 {
3658 __h.reset((char_type*)malloc(__exn * sizeof(char_type)));
3659 __mb = __h.get();
3660 if (__mb == 0)
3661 __throw_bad_alloc();
3662 }
3663 // format
3664 char_type* __mi;
3665 char_type* __me;
3666 this->__format(__mb, __mi, __me, __iob.flags(),
3667 __digits.data(), __digits.data() + __digits.size(), __ct,
3668 __neg, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3669 return __pad_and_output(__s, __mb, __mi, __me, __iob, __fl);
3670}
3671
3672extern template class money_put<char>;
3673extern template class money_put<wchar_t>;
3674
3675// messages
3676
Howard Hinnant82894812010-09-22 16:48:34 +00003677class _LIBCPP_VISIBLE messages_base
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003678{
3679public:
Howard Hinnantb2080c72011-02-25 00:51:08 +00003680 typedef ptrdiff_t catalog;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003681
3682 _LIBCPP_ALWAYS_INLINE messages_base() {}
3683};
3684
3685template <class _CharT>
Howard Hinnant82894812010-09-22 16:48:34 +00003686class _LIBCPP_VISIBLE messages
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003687 : public locale::facet,
3688 public messages_base
3689{
3690public:
3691 typedef _CharT char_type;
3692 typedef basic_string<_CharT> string_type;
3693
3694 _LIBCPP_ALWAYS_INLINE
3695 explicit messages(size_t __refs = 0)
3696 : locale::facet(__refs) {}
3697
3698 _LIBCPP_ALWAYS_INLINE
3699 catalog open(const basic_string<char>& __nm, const locale& __loc) const
3700 {
3701 return do_open(__nm, __loc);
3702 }
3703
3704 _LIBCPP_ALWAYS_INLINE
3705 string_type get(catalog __c, int __set, int __msgid,
3706 const string_type& __dflt) const
3707 {
3708 return do_get(__c, __set, __msgid, __dflt);
3709 }
3710
3711 _LIBCPP_ALWAYS_INLINE
3712 void close(catalog __c) const
3713 {
3714 do_close(__c);
3715 }
3716
3717 static locale::id id;
3718
3719protected:
Howard Hinnant82894812010-09-22 16:48:34 +00003720 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003721 ~messages() {}
3722
3723 virtual catalog do_open(const basic_string<char>&, const locale&) const;
3724 virtual string_type do_get(catalog, int __set, int __msgid,
3725 const string_type& __dflt) const;
3726 virtual void do_close(catalog) const;
3727};
3728
3729template <class _CharT>
3730locale::id
3731messages<_CharT>::id;
3732
3733template <class _CharT>
3734typename messages<_CharT>::catalog
3735messages<_CharT>::do_open(const basic_string<char>& __nm, const locale&) const
3736{
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00003737#if _WIN32
3738 return -1;
3739#else // _WIN32
Howard Hinnant11624452011-10-11 16:00:46 +00003740 catalog __cat = (catalog)catopen(__nm.c_str(), NL_CAT_LOCALE);
Howard Hinnantb2080c72011-02-25 00:51:08 +00003741 if (__cat != -1)
3742 __cat = static_cast<catalog>((static_cast<size_t>(__cat) >> 1));
3743 return __cat;
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00003744#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003745}
3746
3747template <class _CharT>
3748typename messages<_CharT>::string_type
3749messages<_CharT>::do_get(catalog __c, int __set, int __msgid,
3750 const string_type& __dflt) const
3751{
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00003752#if _WIN32
3753 return __dflt;
3754#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003755 string __ndflt;
3756 __narrow_to_utf8<sizeof(char_type)*__CHAR_BIT__>()(back_inserter(__ndflt),
3757 __dflt.c_str(),
3758 __dflt.c_str() + __dflt.size());
Howard Hinnantb2080c72011-02-25 00:51:08 +00003759 if (__c != -1)
3760 __c <<= 1;
Howard Hinnant11624452011-10-11 16:00:46 +00003761 nl_catd __cat = (nl_catd)__c;
Howard Hinnantb2080c72011-02-25 00:51:08 +00003762 char* __n = catgets(__cat, __set, __msgid, __ndflt.c_str());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003763 string_type __w;
3764 __widen_from_utf8<sizeof(char_type)*__CHAR_BIT__>()(back_inserter(__w),
3765 __n, __n + strlen(__n));
3766 return __w;
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00003767#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003768}
3769
3770template <class _CharT>
3771void
3772messages<_CharT>::do_close(catalog __c) const
3773{
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00003774#if !_WIN32
Howard Hinnantb2080c72011-02-25 00:51:08 +00003775 if (__c != -1)
3776 __c <<= 1;
Howard Hinnant11624452011-10-11 16:00:46 +00003777 nl_catd __cat = (nl_catd)__c;
Howard Hinnantb2080c72011-02-25 00:51:08 +00003778 catclose(__cat);
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00003779#endif // !_WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003780}
3781
3782extern template class messages<char>;
3783extern template class messages<wchar_t>;
3784
3785template <class _CharT>
Howard Hinnant82894812010-09-22 16:48:34 +00003786class _LIBCPP_VISIBLE messages_byname
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003787 : public messages<_CharT>
3788{
3789public:
3790 typedef messages_base::catalog catalog;
3791 typedef basic_string<_CharT> string_type;
3792
3793 _LIBCPP_ALWAYS_INLINE
3794 explicit messages_byname(const char*, size_t __refs = 0)
3795 : messages<_CharT>(__refs) {}
3796
3797 _LIBCPP_ALWAYS_INLINE
3798 explicit messages_byname(const string&, size_t __refs = 0)
3799 : messages<_CharT>(__refs) {}
3800
3801protected:
Howard Hinnant82894812010-09-22 16:48:34 +00003802 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003803 ~messages_byname() {}
3804};
3805
3806extern template class messages_byname<char>;
3807extern template class messages_byname<wchar_t>;
3808
Howard Hinnantd23b4642010-05-31 20:58:54 +00003809template<class _Codecvt, class _Elem = wchar_t,
3810 class _Wide_alloc = allocator<_Elem>,
3811 class _Byte_alloc = allocator<char> >
Howard Hinnant82894812010-09-22 16:48:34 +00003812class _LIBCPP_VISIBLE wstring_convert
Howard Hinnantd23b4642010-05-31 20:58:54 +00003813{
3814public:
3815 typedef basic_string<char, char_traits<char>, _Byte_alloc> byte_string;
3816 typedef basic_string<_Elem, char_traits<_Elem>, _Wide_alloc> wide_string;
3817 typedef typename _Codecvt::state_type state_type;
3818 typedef typename wide_string::traits_type::int_type int_type;
3819
3820private:
3821 byte_string __byte_err_string_;
3822 wide_string __wide_err_string_;
3823 _Codecvt* __cvtptr_;
3824 state_type __cvtstate_;
3825 size_t __cvtcount_;
3826
3827 wstring_convert(const wstring_convert& __wc);
3828 wstring_convert& operator=(const wstring_convert& __wc);
3829public:
3830 wstring_convert(_Codecvt* __pcvt = new _Codecvt);
3831 wstring_convert(_Codecvt* __pcvt, state_type __state);
3832 wstring_convert(const byte_string& __byte_err,
3833 const wide_string& __wide_err = wide_string());
Howard Hinnant73d21a42010-09-04 23:28:19 +00003834#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantd23b4642010-05-31 20:58:54 +00003835 wstring_convert(wstring_convert&& __wc);
3836#endif
3837 ~wstring_convert();
3838
Howard Hinnant82894812010-09-22 16:48:34 +00003839 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003840 wide_string from_bytes(char __byte)
3841 {return from_bytes(&__byte, &__byte+1);}
Howard Hinnant82894812010-09-22 16:48:34 +00003842 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003843 wide_string from_bytes(const char* __ptr)
3844 {return from_bytes(__ptr, __ptr + char_traits<char>::length(__ptr));}
Howard Hinnant82894812010-09-22 16:48:34 +00003845 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003846 wide_string from_bytes(const byte_string& __str)
3847 {return from_bytes(__str.data(), __str.data() + __str.size());}
3848 wide_string from_bytes(const char* __first, const char* __last);
3849
Howard Hinnant82894812010-09-22 16:48:34 +00003850 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003851 byte_string to_bytes(_Elem __wchar)
3852 {return to_bytes(&__wchar, &__wchar+1);}
Howard Hinnant82894812010-09-22 16:48:34 +00003853 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003854 byte_string to_bytes(const _Elem* __wptr)
3855 {return to_bytes(__wptr, __wptr + char_traits<_Elem>::length(__wptr));}
Howard Hinnant82894812010-09-22 16:48:34 +00003856 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003857 byte_string to_bytes(const wide_string& __wstr)
3858 {return to_bytes(__wstr.data(), __wstr.data() + __wstr.size());}
3859 byte_string to_bytes(const _Elem* __first, const _Elem* __last);
3860
Howard Hinnant82894812010-09-22 16:48:34 +00003861 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003862 size_t converted() const {return __cvtcount_;}
Howard Hinnant82894812010-09-22 16:48:34 +00003863 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003864 state_type state() const {return __cvtstate_;}
3865};
3866
3867template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Howard Hinnant82894812010-09-22 16:48:34 +00003868inline _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003869wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3870 wstring_convert(_Codecvt* __pcvt)
3871 : __cvtptr_(__pcvt), __cvtstate_(), __cvtcount_(0)
3872{
3873}
3874
3875template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Howard Hinnant82894812010-09-22 16:48:34 +00003876inline _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003877wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3878 wstring_convert(_Codecvt* __pcvt, state_type __state)
3879 : __cvtptr_(__pcvt), __cvtstate_(__state), __cvtcount_(0)
3880{
3881}
3882
3883template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3884wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3885 wstring_convert(const byte_string& __byte_err, const wide_string& __wide_err)
3886 : __byte_err_string_(__byte_err), __wide_err_string_(__wide_err),
3887 __cvtstate_(), __cvtcount_(0)
3888{
3889 __cvtptr_ = new _Codecvt;
3890}
3891
Howard Hinnant73d21a42010-09-04 23:28:19 +00003892#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantd23b4642010-05-31 20:58:54 +00003893
3894template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Howard Hinnant82894812010-09-22 16:48:34 +00003895inline _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003896wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3897 wstring_convert(wstring_convert&& __wc)
Howard Hinnant0949eed2011-06-30 21:18:19 +00003898 : __byte_err_string_(_VSTD::move(__wc.__byte_err_string_)),
3899 __wide_err_string_(_VSTD::move(__wc.__wide_err_string_)),
Howard Hinnantd23b4642010-05-31 20:58:54 +00003900 __cvtptr_(__wc.__cvtptr_),
3901 __cvtstate_(__wc.__cvtstate_), __cvtcount_(__wc.__cvtstate_)
3902{
3903 __wc.__cvtptr_ = nullptr;
3904}
3905
Howard Hinnantbfd55302010-09-04 23:46:48 +00003906#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantd23b4642010-05-31 20:58:54 +00003907
3908template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3909wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::~wstring_convert()
3910{
3911 delete __cvtptr_;
3912}
3913
3914template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3915typename wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::wide_string
3916wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3917 from_bytes(const char* __frm, const char* __frm_end)
3918{
3919 __cvtcount_ = 0;
3920 if (__cvtptr_ != nullptr)
3921 {
3922 wide_string __ws(2*(__frm_end - __frm), _Elem());
3923 __ws.resize(__ws.capacity());
3924 codecvt_base::result __r = codecvt_base::ok;
3925 state_type __st = __cvtstate_;
3926 if (__frm != __frm_end)
3927 {
3928 _Elem* __to = &__ws[0];
3929 _Elem* __to_end = __to + __ws.size();
3930 const char* __frm_nxt;
3931 do
3932 {
3933 _Elem* __to_nxt;
3934 __r = __cvtptr_->in(__st, __frm, __frm_end, __frm_nxt,
3935 __to, __to_end, __to_nxt);
3936 __cvtcount_ += __frm_nxt - __frm;
3937 if (__frm_nxt == __frm)
3938 {
3939 __r = codecvt_base::error;
3940 }
3941 else if (__r == codecvt_base::noconv)
3942 {
3943 __ws.resize(__to - &__ws[0]);
3944 // This only gets executed if _Elem is char
3945 __ws.append((const _Elem*)__frm, (const _Elem*)__frm_end);
3946 __frm = __frm_nxt;
3947 __r = codecvt_base::ok;
3948 }
3949 else if (__r == codecvt_base::ok)
3950 {
3951 __ws.resize(__to_nxt - &__ws[0]);
3952 __frm = __frm_nxt;
3953 }
3954 else if (__r == codecvt_base::partial)
3955 {
3956 ptrdiff_t __s = __to_nxt - &__ws[0];
3957 __ws.resize(2 * __s);
3958 __to = &__ws[0] + __s;
3959 __to_end = &__ws[0] + __ws.size();
3960 __frm = __frm_nxt;
3961 }
3962 } while (__r == codecvt_base::partial && __frm_nxt < __frm_end);
3963 }
3964 if (__r == codecvt_base::ok)
3965 return __ws;
3966 }
Howard Hinnantd4444702010-08-11 17:04:31 +00003967#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00003968 if (__wide_err_string_.empty())
3969 throw range_error("wstring_convert: from_bytes error");
Howard Hinnant324bb032010-08-22 00:02:43 +00003970#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00003971 return __wide_err_string_;
3972}
3973
3974template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3975typename wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::byte_string
3976wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3977 to_bytes(const _Elem* __frm, const _Elem* __frm_end)
3978{
3979 __cvtcount_ = 0;
3980 if (__cvtptr_ != nullptr)
3981 {
3982 byte_string __bs(2*(__frm_end - __frm), char());
3983 __bs.resize(__bs.capacity());
3984 codecvt_base::result __r = codecvt_base::ok;
3985 state_type __st = __cvtstate_;
3986 if (__frm != __frm_end)
3987 {
3988 char* __to = &__bs[0];
3989 char* __to_end = __to + __bs.size();
3990 const _Elem* __frm_nxt;
3991 do
3992 {
3993 char* __to_nxt;
3994 __r = __cvtptr_->out(__st, __frm, __frm_end, __frm_nxt,
3995 __to, __to_end, __to_nxt);
3996 __cvtcount_ += __frm_nxt - __frm;
3997 if (__frm_nxt == __frm)
3998 {
3999 __r = codecvt_base::error;
4000 }
4001 else if (__r == codecvt_base::noconv)
4002 {
4003 __bs.resize(__to - &__bs[0]);
4004 // This only gets executed if _Elem is char
4005 __bs.append((const char*)__frm, (const char*)__frm_end);
4006 __frm = __frm_nxt;
4007 __r = codecvt_base::ok;
4008 }
4009 else if (__r == codecvt_base::ok)
4010 {
4011 __bs.resize(__to_nxt - &__bs[0]);
4012 __frm = __frm_nxt;
4013 }
4014 else if (__r == codecvt_base::partial)
4015 {
4016 ptrdiff_t __s = __to_nxt - &__bs[0];
4017 __bs.resize(2 * __s);
4018 __to = &__bs[0] + __s;
4019 __to_end = &__bs[0] + __bs.size();
4020 __frm = __frm_nxt;
4021 }
4022 } while (__r == codecvt_base::partial && __frm_nxt < __frm_end);
4023 }
4024 if (__r == codecvt_base::ok)
4025 {
4026 size_t __s = __bs.size();
4027 __bs.resize(__bs.capacity());
4028 char* __to = &__bs[0] + __s;
4029 char* __to_end = __to + __bs.size();
4030 do
4031 {
4032 char* __to_nxt;
4033 __r = __cvtptr_->unshift(__st, __to, __to_end, __to_nxt);
4034 if (__r == codecvt_base::noconv)
4035 {
4036 __bs.resize(__to - &__bs[0]);
4037 __r = codecvt_base::ok;
4038 }
4039 else if (__r == codecvt_base::ok)
4040 {
4041 __bs.resize(__to_nxt - &__bs[0]);
4042 }
4043 else if (__r == codecvt_base::partial)
4044 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00004045 ptrdiff_t __sp = __to_nxt - &__bs[0];
4046 __bs.resize(2 * __sp);
4047 __to = &__bs[0] + __sp;
Howard Hinnantd23b4642010-05-31 20:58:54 +00004048 __to_end = &__bs[0] + __bs.size();
4049 }
4050 } while (__r == codecvt_base::partial);
4051 if (__r == codecvt_base::ok)
4052 return __bs;
4053 }
4054 }
Howard Hinnantd4444702010-08-11 17:04:31 +00004055#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00004056 if (__byte_err_string_.empty())
4057 throw range_error("wstring_convert: to_bytes error");
Howard Hinnant324bb032010-08-22 00:02:43 +00004058#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00004059 return __byte_err_string_;
4060}
4061
4062template <class _Codecvt, class _Elem = wchar_t, class _Tr = char_traits<_Elem> >
Howard Hinnant82894812010-09-22 16:48:34 +00004063class _LIBCPP_VISIBLE wbuffer_convert
Howard Hinnantd23b4642010-05-31 20:58:54 +00004064 : public basic_streambuf<_Elem, _Tr>
4065{
4066public:
4067 // types:
4068 typedef _Elem char_type;
4069 typedef _Tr traits_type;
4070 typedef typename traits_type::int_type int_type;
4071 typedef typename traits_type::pos_type pos_type;
4072 typedef typename traits_type::off_type off_type;
4073 typedef typename _Codecvt::state_type state_type;
4074
4075private:
Howard Hinnant4b53f502010-06-01 20:09:18 +00004076 char* __extbuf_;
4077 const char* __extbufnext_;
4078 const char* __extbufend_;
4079 char __extbuf_min_[8];
4080 size_t __ebs_;
4081 char_type* __intbuf_;
4082 size_t __ibs_;
Howard Hinnantd23b4642010-05-31 20:58:54 +00004083 streambuf* __bufptr_;
Howard Hinnant4b53f502010-06-01 20:09:18 +00004084 _Codecvt* __cv_;
4085 state_type __st_;
4086 ios_base::openmode __cm_;
4087 bool __owns_eb_;
4088 bool __owns_ib_;
4089 bool __always_noconv_;
Howard Hinnantd23b4642010-05-31 20:58:54 +00004090
Howard Hinnant4b53f502010-06-01 20:09:18 +00004091 wbuffer_convert(const wbuffer_convert&);
4092 wbuffer_convert& operator=(const wbuffer_convert&);
Howard Hinnantd23b4642010-05-31 20:58:54 +00004093public:
4094 wbuffer_convert(streambuf* __bytebuf = 0, _Codecvt* __pcvt = new _Codecvt,
Howard Hinnant4b53f502010-06-01 20:09:18 +00004095 state_type __state = state_type());
4096 ~wbuffer_convert();
Howard Hinnantd23b4642010-05-31 20:58:54 +00004097
Howard Hinnant82894812010-09-22 16:48:34 +00004098 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantd23b4642010-05-31 20:58:54 +00004099 streambuf* rdbuf() const {return __bufptr_;}
Howard Hinnant82894812010-09-22 16:48:34 +00004100 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantd23b4642010-05-31 20:58:54 +00004101 streambuf* rdbuf(streambuf* __bytebuf)
4102 {
4103 streambuf* __r = __bufptr_;
4104 __bufptr_ = __bytebuf;
4105 return __r;
4106 }
4107
Howard Hinnant82894812010-09-22 16:48:34 +00004108 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant4b53f502010-06-01 20:09:18 +00004109 state_type state() const {return __st_;}
Howard Hinnantd23b4642010-05-31 20:58:54 +00004110
4111protected:
Howard Hinnant4b53f502010-06-01 20:09:18 +00004112 virtual int_type underflow();
4113 virtual int_type pbackfail(int_type __c = traits_type::eof());
Howard Hinnantd23b4642010-05-31 20:58:54 +00004114 virtual int_type overflow (int_type __c = traits_type::eof());
Howard Hinnant4b53f502010-06-01 20:09:18 +00004115 virtual basic_streambuf<char_type, traits_type>* setbuf(char_type* __s,
4116 streamsize __n);
4117 virtual pos_type seekoff(off_type __off, ios_base::seekdir __way,
4118 ios_base::openmode __wch = ios_base::in | ios_base::out);
4119 virtual pos_type seekpos(pos_type __sp,
4120 ios_base::openmode __wch = ios_base::in | ios_base::out);
4121 virtual int sync();
4122
4123private:
4124 bool __read_mode();
4125 void __write_mode();
4126 wbuffer_convert* __close();
Howard Hinnantd23b4642010-05-31 20:58:54 +00004127};
4128
4129template <class _Codecvt, class _Elem, class _Tr>
Howard Hinnant4b53f502010-06-01 20:09:18 +00004130wbuffer_convert<_Codecvt, _Elem, _Tr>::
4131 wbuffer_convert(streambuf* __bytebuf, _Codecvt* __pcvt, state_type __state)
4132 : __extbuf_(0),
4133 __extbufnext_(0),
4134 __extbufend_(0),
4135 __ebs_(0),
4136 __intbuf_(0),
4137 __ibs_(0),
4138 __bufptr_(__bytebuf),
4139 __cv_(__pcvt),
4140 __st_(__state),
4141 __cm_(0),
4142 __owns_eb_(false),
4143 __owns_ib_(false),
4144 __always_noconv_(__cv_ ? __cv_->always_noconv() : false)
4145{
4146 setbuf(0, 4096);
4147}
4148
4149template <class _Codecvt, class _Elem, class _Tr>
4150wbuffer_convert<_Codecvt, _Elem, _Tr>::~wbuffer_convert()
4151{
4152 __close();
4153 delete __cv_;
4154 if (__owns_eb_)
4155 delete [] __extbuf_;
4156 if (__owns_ib_)
4157 delete [] __intbuf_;
4158}
4159
4160template <class _Codecvt, class _Elem, class _Tr>
4161typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
4162wbuffer_convert<_Codecvt, _Elem, _Tr>::underflow()
4163{
4164 if (__cv_ == 0 || __bufptr_ == 0)
4165 return traits_type::eof();
4166 bool __initial = __read_mode();
4167 char_type __1buf;
4168 if (this->gptr() == 0)
4169 this->setg(&__1buf, &__1buf+1, &__1buf+1);
4170 const size_t __unget_sz = __initial ? 0 : min<size_t>((this->egptr() - this->eback()) / 2, 4);
4171 int_type __c = traits_type::eof();
4172 if (this->gptr() == this->egptr())
4173 {
4174 memmove(this->eback(), this->egptr() - __unget_sz, __unget_sz * sizeof(char_type));
4175 if (__always_noconv_)
4176 {
4177 streamsize __nmemb = static_cast<streamsize>(this->egptr() - this->eback() - __unget_sz);
4178 __nmemb = __bufptr_->sgetn((char*)this->eback() + __unget_sz, __nmemb);
4179 if (__nmemb != 0)
4180 {
4181 this->setg(this->eback(),
4182 this->eback() + __unget_sz,
4183 this->eback() + __unget_sz + __nmemb);
4184 __c = *this->gptr();
4185 }
4186 }
4187 else
4188 {
4189 memmove(__extbuf_, __extbufnext_, __extbufend_ - __extbufnext_);
4190 __extbufnext_ = __extbuf_ + (__extbufend_ - __extbufnext_);
4191 __extbufend_ = __extbuf_ + (__extbuf_ == __extbuf_min_ ? sizeof(__extbuf_min_) : __ebs_);
Howard Hinnant0949eed2011-06-30 21:18:19 +00004192 streamsize __nmemb = _VSTD::min(static_cast<streamsize>(this->egptr() - this->eback() - __unget_sz),
Howard Hinnant4b53f502010-06-01 20:09:18 +00004193 static_cast<streamsize>(__extbufend_ - __extbufnext_));
4194 codecvt_base::result __r;
4195 state_type __svs = __st_;
4196 streamsize __nr = __bufptr_->sgetn(const_cast<char*>(__extbufnext_), __nmemb);
4197 if (__nr != 0)
4198 {
4199 __extbufend_ = __extbufnext_ + __nr;
4200 char_type* __inext;
4201 __r = __cv_->in(__st_, __extbuf_, __extbufend_, __extbufnext_,
4202 this->eback() + __unget_sz,
4203 this->egptr(), __inext);
4204 if (__r == codecvt_base::noconv)
4205 {
4206 this->setg((char_type*)__extbuf_, (char_type*)__extbuf_, (char_type*)__extbufend_);
4207 __c = *this->gptr();
4208 }
4209 else if (__inext != this->eback() + __unget_sz)
4210 {
4211 this->setg(this->eback(), this->eback() + __unget_sz, __inext);
4212 __c = *this->gptr();
4213 }
4214 }
4215 }
4216 }
4217 else
4218 __c = *this->gptr();
4219 if (this->eback() == &__1buf)
4220 this->setg(0, 0, 0);
4221 return __c;
4222}
4223
4224template <class _Codecvt, class _Elem, class _Tr>
4225typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
4226wbuffer_convert<_Codecvt, _Elem, _Tr>::pbackfail(int_type __c)
4227{
4228 if (__cv_ != 0 && __bufptr_ != 0 && this->eback() < this->gptr())
4229 {
4230 if (traits_type::eq_int_type(__c, traits_type::eof()))
4231 {
4232 this->gbump(-1);
4233 return traits_type::not_eof(__c);
4234 }
4235 if (traits_type::eq(traits_type::to_char_type(__c), this->gptr()[-1]))
4236 {
4237 this->gbump(-1);
4238 *this->gptr() = traits_type::to_char_type(__c);
4239 return __c;
4240 }
4241 }
4242 return traits_type::eof();
4243}
4244
4245template <class _Codecvt, class _Elem, class _Tr>
Howard Hinnantd23b4642010-05-31 20:58:54 +00004246typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
4247wbuffer_convert<_Codecvt, _Elem, _Tr>::overflow(int_type __c)
4248{
Howard Hinnant4b53f502010-06-01 20:09:18 +00004249 if (__cv_ == 0 || __bufptr_ == 0)
4250 return traits_type::eof();
4251 __write_mode();
4252 char_type __1buf;
4253 char_type* __pb_save = this->pbase();
4254 char_type* __epb_save = this->epptr();
4255 if (!traits_type::eq_int_type(__c, traits_type::eof()))
4256 {
4257 if (this->pptr() == 0)
4258 this->setp(&__1buf, &__1buf+1);
4259 *this->pptr() = traits_type::to_char_type(__c);
4260 this->pbump(1);
4261 }
4262 if (this->pptr() != this->pbase())
4263 {
4264 if (__always_noconv_)
4265 {
4266 streamsize __nmemb = static_cast<streamsize>(this->pptr() - this->pbase());
4267 if (__bufptr_->sputn((const char*)this->pbase(), __nmemb) != __nmemb)
4268 return traits_type::eof();
4269 }
4270 else
4271 {
4272 char* __extbe = __extbuf_;
4273 codecvt_base::result __r;
4274 do
4275 {
4276 const char_type* __e;
4277 __r = __cv_->out(__st_, this->pbase(), this->pptr(), __e,
4278 __extbuf_, __extbuf_ + __ebs_, __extbe);
4279 if (__e == this->pbase())
4280 return traits_type::eof();
4281 if (__r == codecvt_base::noconv)
4282 {
4283 streamsize __nmemb = static_cast<size_t>(this->pptr() - this->pbase());
4284 if (__bufptr_->sputn((const char*)this->pbase(), __nmemb) != __nmemb)
4285 return traits_type::eof();
4286 }
4287 else if (__r == codecvt_base::ok || __r == codecvt_base::partial)
4288 {
4289 streamsize __nmemb = static_cast<size_t>(__extbe - __extbuf_);
4290 if (__bufptr_->sputn(__extbuf_, __nmemb) != __nmemb)
4291 return traits_type::eof();
4292 if (__r == codecvt_base::partial)
4293 {
4294 this->setp((char_type*)__e, this->pptr());
4295 this->pbump(this->epptr() - this->pbase());
4296 }
4297 }
4298 else
4299 return traits_type::eof();
4300 } while (__r == codecvt_base::partial);
4301 }
4302 this->setp(__pb_save, __epb_save);
4303 }
4304 return traits_type::not_eof(__c);
4305}
4306
4307template <class _Codecvt, class _Elem, class _Tr>
4308basic_streambuf<_Elem, _Tr>*
4309wbuffer_convert<_Codecvt, _Elem, _Tr>::setbuf(char_type* __s, streamsize __n)
4310{
4311 this->setg(0, 0, 0);
4312 this->setp(0, 0);
4313 if (__owns_eb_)
4314 delete [] __extbuf_;
4315 if (__owns_ib_)
4316 delete [] __intbuf_;
4317 __ebs_ = __n;
4318 if (__ebs_ > sizeof(__extbuf_min_))
4319 {
4320 if (__always_noconv_ && __s)
4321 {
4322 __extbuf_ = (char*)__s;
4323 __owns_eb_ = false;
4324 }
4325 else
4326 {
4327 __extbuf_ = new char[__ebs_];
4328 __owns_eb_ = true;
4329 }
4330 }
4331 else
4332 {
4333 __extbuf_ = __extbuf_min_;
4334 __ebs_ = sizeof(__extbuf_min_);
4335 __owns_eb_ = false;
4336 }
4337 if (!__always_noconv_)
4338 {
4339 __ibs_ = max<streamsize>(__n, sizeof(__extbuf_min_));
4340 if (__s && __ibs_ >= sizeof(__extbuf_min_))
4341 {
4342 __intbuf_ = __s;
4343 __owns_ib_ = false;
4344 }
4345 else
4346 {
4347 __intbuf_ = new char_type[__ibs_];
4348 __owns_ib_ = true;
4349 }
4350 }
4351 else
4352 {
4353 __ibs_ = 0;
4354 __intbuf_ = 0;
4355 __owns_ib_ = false;
4356 }
4357 return this;
4358}
4359
4360template <class _Codecvt, class _Elem, class _Tr>
4361typename wbuffer_convert<_Codecvt, _Elem, _Tr>::pos_type
4362wbuffer_convert<_Codecvt, _Elem, _Tr>::seekoff(off_type __off, ios_base::seekdir __way,
4363 ios_base::openmode __om)
4364{
4365 int __width = __cv_->encoding();
4366 if (__cv_ == 0 || __bufptr_ == 0 || (__width <= 0 && __off != 0) || sync())
4367 return pos_type(off_type(-1));
4368 // __width > 0 || __off == 0
4369 switch (__way)
4370 {
4371 case ios_base::beg:
4372 break;
4373 case ios_base::cur:
4374 break;
4375 case ios_base::end:
4376 break;
4377 default:
4378 return pos_type(off_type(-1));
4379 }
4380 pos_type __r = __bufptr_->pubseekoff(__width * __off, __way, __om);
4381 __r.state(__st_);
4382 return __r;
4383}
4384
4385template <class _Codecvt, class _Elem, class _Tr>
4386typename wbuffer_convert<_Codecvt, _Elem, _Tr>::pos_type
4387wbuffer_convert<_Codecvt, _Elem, _Tr>::seekpos(pos_type __sp, ios_base::openmode __wch)
4388{
4389 if (__cv_ == 0 || __bufptr_ == 0 || sync())
4390 return pos_type(off_type(-1));
4391 if (__bufptr_->pubseekpos(__sp, __wch) == pos_type(off_type(-1)))
4392 return pos_type(off_type(-1));
4393 return __sp;
4394}
4395
4396template <class _Codecvt, class _Elem, class _Tr>
4397int
4398wbuffer_convert<_Codecvt, _Elem, _Tr>::sync()
4399{
4400 if (__cv_ == 0 || __bufptr_ == 0)
4401 return 0;
4402 if (__cm_ & ios_base::out)
4403 {
4404 if (this->pptr() != this->pbase())
4405 if (overflow() == traits_type::eof())
4406 return -1;
4407 codecvt_base::result __r;
4408 do
4409 {
4410 char* __extbe;
4411 __r = __cv_->unshift(__st_, __extbuf_, __extbuf_ + __ebs_, __extbe);
4412 streamsize __nmemb = static_cast<streamsize>(__extbe - __extbuf_);
4413 if (__bufptr_->sputn(__extbuf_, __nmemb) != __nmemb)
4414 return -1;
4415 } while (__r == codecvt_base::partial);
4416 if (__r == codecvt_base::error)
4417 return -1;
4418 if (__bufptr_->pubsync())
4419 return -1;
4420 }
4421 else if (__cm_ & ios_base::in)
4422 {
4423 off_type __c;
4424 if (__always_noconv_)
4425 __c = this->egptr() - this->gptr();
4426 else
4427 {
4428 int __width = __cv_->encoding();
4429 __c = __extbufend_ - __extbufnext_;
4430 if (__width > 0)
4431 __c += __width * (this->egptr() - this->gptr());
4432 else
4433 {
4434 if (this->gptr() != this->egptr())
4435 {
4436 reverse(this->gptr(), this->egptr());
4437 codecvt_base::result __r;
4438 const char_type* __e = this->gptr();
4439 char* __extbe;
4440 do
4441 {
4442 __r = __cv_->out(__st_, __e, this->egptr(), __e,
4443 __extbuf_, __extbuf_ + __ebs_, __extbe);
4444 switch (__r)
4445 {
4446 case codecvt_base::noconv:
4447 __c += this->egptr() - this->gptr();
4448 break;
4449 case codecvt_base::ok:
4450 case codecvt_base::partial:
4451 __c += __extbe - __extbuf_;
4452 break;
4453 default:
4454 return -1;
4455 }
4456 } while (__r == codecvt_base::partial);
4457 }
4458 }
4459 }
4460 if (__bufptr_->pubseekoff(-__c, ios_base::cur, __cm_) == pos_type(off_type(-1)))
4461 return -1;
4462 this->setg(0, 0, 0);
4463 __cm_ = 0;
4464 }
4465 return 0;
4466}
4467
4468template <class _Codecvt, class _Elem, class _Tr>
4469bool
4470wbuffer_convert<_Codecvt, _Elem, _Tr>::__read_mode()
4471{
4472 if (!(__cm_ & ios_base::in))
4473 {
4474 this->setp(0, 0);
4475 if (__always_noconv_)
4476 this->setg((char_type*)__extbuf_,
4477 (char_type*)__extbuf_ + __ebs_,
4478 (char_type*)__extbuf_ + __ebs_);
4479 else
4480 this->setg(__intbuf_, __intbuf_ + __ibs_, __intbuf_ + __ibs_);
4481 __cm_ = ios_base::in;
4482 return true;
4483 }
4484 return false;
4485}
4486
4487template <class _Codecvt, class _Elem, class _Tr>
4488void
4489wbuffer_convert<_Codecvt, _Elem, _Tr>::__write_mode()
4490{
4491 if (!(__cm_ & ios_base::out))
4492 {
4493 this->setg(0, 0, 0);
4494 if (__ebs_ > sizeof(__extbuf_min_))
4495 {
4496 if (__always_noconv_)
4497 this->setp((char_type*)__extbuf_,
4498 (char_type*)__extbuf_ + (__ebs_ - 1));
4499 else
4500 this->setp(__intbuf_, __intbuf_ + (__ibs_ - 1));
4501 }
4502 else
4503 this->setp(0, 0);
4504 __cm_ = ios_base::out;
4505 }
4506}
4507
4508template <class _Codecvt, class _Elem, class _Tr>
4509wbuffer_convert<_Codecvt, _Elem, _Tr>*
4510wbuffer_convert<_Codecvt, _Elem, _Tr>::__close()
4511{
4512 wbuffer_convert* __rt = 0;
4513 if (__cv_ != 0 && __bufptr_ != 0)
4514 {
4515 __rt = this;
4516 if ((__cm_ & ios_base::out) && sync())
4517 __rt = 0;
4518 }
4519 return __rt;
Howard Hinnantd23b4642010-05-31 20:58:54 +00004520}
4521
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004522_LIBCPP_END_NAMESPACE_STD
4523
4524#endif // _LIBCPP_LOCALE