blob: 72b4729bae41c2d0ca8cd5b58f32c59d80c1bd5d [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 Hinnantff926772012-11-06 21:08:48 +0000695_LIBCPP_EXTERN_TEMPLATE(struct __num_get<char>)
696_LIBCPP_EXTERN_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
Howard Hinnantff926772012-11-06 21:08:48 +00001317_LIBCPP_EXTERN_TEMPLATE(class num_get<char>)
1318_LIBCPP_EXTERN_TEMPLATE(class num_get<wchar_t>)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001319
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 Hinnantff926772012-11-06 21:08:48 +00001467_LIBCPP_EXTERN_TEMPLATE(struct __num_put<char>)
1468_LIBCPP_EXTERN_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
Howard Hinnanta585de62012-09-19 19:14:15 +00001590template <class _CharT, class _Traits>
1591_LIBCPP_HIDDEN
1592ostreambuf_iterator<_CharT, _Traits>
1593__pad_and_output(ostreambuf_iterator<_CharT, _Traits> __s,
1594 const _CharT* __ob, const _CharT* __op, const _CharT* __oe,
1595 ios_base& __iob, _CharT __fl)
1596{
1597 if (__s.__sbuf_ == nullptr)
1598 return __s;
1599 streamsize __sz = __oe - __ob;
1600 streamsize __ns = __iob.width();
1601 if (__ns > __sz)
1602 __ns -= __sz;
1603 else
1604 __ns = 0;
1605 streamsize __np = __op - __ob;
1606 if (__np > 0)
1607 {
1608 if (__s.__sbuf_->sputn(__ob, __np) != __np)
1609 {
1610 __s.__sbuf_ = nullptr;
1611 return __s;
1612 }
1613 }
1614 if (__ns > 0)
1615 {
1616 basic_string<_CharT, _Traits> __sp(__ns, __fl);
1617 if (__s.__sbuf_->sputn(__sp.data(), __ns) != __ns)
1618 {
1619 __s.__sbuf_ = nullptr;
1620 return __s;
1621 }
1622 }
1623 __np = __oe - __op;
1624 if (__np > 0)
1625 {
1626 if (__s.__sbuf_->sputn(__op, __np) != __np)
1627 {
1628 __s.__sbuf_ = nullptr;
1629 return __s;
1630 }
1631 }
1632 __iob.width(0);
1633 return __s;
1634}
1635
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001636template <class _CharT, class _OutputIterator>
1637_OutputIterator
1638num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1639 char_type __fl, bool __v) const
1640{
1641 if ((__iob.flags() & ios_base::boolalpha) == 0)
1642 return do_put(__s, __iob, __fl, (unsigned long)__v);
1643 const numpunct<char_type>& __np = use_facet<numpunct<char_type> >(__iob.getloc());
1644 typedef typename numpunct<char_type>::string_type string_type;
1645 string_type __nm = __v ? __np.truename() : __np.falsename();
1646 for (typename string_type::iterator __i = __nm.begin(); __i != __nm.end(); ++__i, ++__s)
1647 *__s = *__i;
1648 return __s;
1649}
1650
1651template <class _CharT, class _OutputIterator>
1652_OutputIterator
1653num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1654 char_type __fl, long __v) const
1655{
1656 // Stage 1 - Get number in narrow char
1657 char __fmt[6] = {'%', 0};
1658 const char* __len = "l";
1659 this->__format_int(__fmt+1, __len, true, __iob.flags());
1660 const unsigned __nbuf = (numeric_limits<long>::digits / 3)
1661 + ((numeric_limits<long>::digits % 3) != 0)
1662 + 1;
1663 char __nar[__nbuf];
Howard Hinnant866569b2011-09-28 23:39:33 +00001664#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001665 int __nc = sprintf_l(__nar, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001666#else
1667 int __nc = __sprintf_l(__nar, __cloc(), __fmt, __v);
1668#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001669 char* __ne = __nar + __nc;
1670 char* __np = this->__identify_padding(__nar, __ne, __iob);
1671 // Stage 2 - Widen __nar while adding thousands separators
1672 char_type __o[2*(__nbuf-1) - 1];
1673 char_type* __op; // pad here
1674 char_type* __oe; // end of output
1675 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1676 // [__o, __oe) contains thousands_sep'd wide number
1677 // Stage 3 & 4
1678 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1679}
1680
1681template <class _CharT, class _OutputIterator>
1682_OutputIterator
1683num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1684 char_type __fl, long long __v) const
1685{
1686 // Stage 1 - Get number in narrow char
1687 char __fmt[8] = {'%', 0};
1688 const char* __len = "ll";
1689 this->__format_int(__fmt+1, __len, true, __iob.flags());
1690 const unsigned __nbuf = (numeric_limits<long long>::digits / 3)
1691 + ((numeric_limits<long long>::digits % 3) != 0)
1692 + 1;
1693 char __nar[__nbuf];
Howard Hinnant866569b2011-09-28 23:39:33 +00001694#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001695 int __nc = sprintf_l(__nar, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001696#else
1697 int __nc = __sprintf_l(__nar, __cloc(), __fmt, __v);
1698#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001699 char* __ne = __nar + __nc;
1700 char* __np = this->__identify_padding(__nar, __ne, __iob);
1701 // Stage 2 - Widen __nar while adding thousands separators
1702 char_type __o[2*(__nbuf-1) - 1];
1703 char_type* __op; // pad here
1704 char_type* __oe; // end of output
1705 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1706 // [__o, __oe) contains thousands_sep'd wide number
1707 // Stage 3 & 4
1708 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1709}
1710
1711template <class _CharT, class _OutputIterator>
1712_OutputIterator
1713num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1714 char_type __fl, unsigned long __v) const
1715{
1716 // Stage 1 - Get number in narrow char
1717 char __fmt[6] = {'%', 0};
1718 const char* __len = "l";
1719 this->__format_int(__fmt+1, __len, false, __iob.flags());
1720 const unsigned __nbuf = (numeric_limits<unsigned long>::digits / 3)
1721 + ((numeric_limits<unsigned long>::digits % 3) != 0)
1722 + 1;
1723 char __nar[__nbuf];
Howard Hinnant866569b2011-09-28 23:39:33 +00001724#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001725 int __nc = sprintf_l(__nar, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001726#else
1727 int __nc = __sprintf_l(__nar, __cloc(), __fmt, __v);
1728#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001729 char* __ne = __nar + __nc;
1730 char* __np = this->__identify_padding(__nar, __ne, __iob);
1731 // Stage 2 - Widen __nar while adding thousands separators
1732 char_type __o[2*(__nbuf-1) - 1];
1733 char_type* __op; // pad here
1734 char_type* __oe; // end of output
1735 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1736 // [__o, __oe) contains thousands_sep'd wide number
1737 // Stage 3 & 4
1738 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1739}
1740
1741template <class _CharT, class _OutputIterator>
1742_OutputIterator
1743num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1744 char_type __fl, unsigned long long __v) const
1745{
1746 // Stage 1 - Get number in narrow char
1747 char __fmt[8] = {'%', 0};
1748 const char* __len = "ll";
1749 this->__format_int(__fmt+1, __len, false, __iob.flags());
1750 const unsigned __nbuf = (numeric_limits<unsigned long long>::digits / 3)
1751 + ((numeric_limits<unsigned long long>::digits % 3) != 0)
1752 + 1;
1753 char __nar[__nbuf];
Howard Hinnant866569b2011-09-28 23:39:33 +00001754#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001755 int __nc = sprintf_l(__nar, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001756#else
1757 int __nc = __sprintf_l(__nar, __cloc(), __fmt, __v);
1758#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001759 char* __ne = __nar + __nc;
1760 char* __np = this->__identify_padding(__nar, __ne, __iob);
1761 // Stage 2 - Widen __nar while adding thousands separators
1762 char_type __o[2*(__nbuf-1) - 1];
1763 char_type* __op; // pad here
1764 char_type* __oe; // end of output
1765 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1766 // [__o, __oe) contains thousands_sep'd wide number
1767 // Stage 3 & 4
1768 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1769}
1770
1771template <class _CharT, class _OutputIterator>
1772_OutputIterator
1773num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1774 char_type __fl, double __v) const
1775{
1776 // Stage 1 - Get number in narrow char
1777 char __fmt[8] = {'%', 0};
1778 const char* __len = "";
1779 bool __specify_precision = this->__format_float(__fmt+1, __len, __iob.flags());
1780 const unsigned __nbuf = 30;
1781 char __nar[__nbuf];
1782 char* __nb = __nar;
1783 int __nc;
1784 if (__specify_precision)
Howard Hinnant866569b2011-09-28 23:39:33 +00001785#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001786 __nc = snprintf_l(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt,
Howard Hinnantadff4892010-05-24 17:49:41 +00001787 (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001788#else
1789 __nc = __snprintf_l(__nb, __nbuf, __cloc(), __fmt,
1790 (int)__iob.precision(), __v);
1791#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001792 else
Howard Hinnant866569b2011-09-28 23:39:33 +00001793#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001794 __nc = snprintf_l(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001795#else
1796 __nc = __snprintf_l(__nb, __nbuf, __cloc(), __fmt, __v);
1797#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001798 unique_ptr<char, void(*)(void*)> __nbh(0, free);
1799 if (__nc > static_cast<int>(__nbuf-1))
1800 {
1801 if (__specify_precision)
Howard Hinnant866569b2011-09-28 23:39:33 +00001802#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001803 __nc = asprintf_l(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001804#else
1805 __nc = __asprintf_l(&__nb, __cloc(), __fmt,
David Chisnallc512df12011-09-21 08:39:44 +00001806 (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001807#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001808 else
Howard Hinnant866569b2011-09-28 23:39:33 +00001809#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001810 __nc = asprintf_l(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001811#else
David Chisnallc512df12011-09-21 08:39:44 +00001812 __nc = __asprintf_l(&__nb, __cloc(), __fmt, (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001813#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001814 if (__nb == 0)
1815 __throw_bad_alloc();
1816 __nbh.reset(__nb);
1817 }
1818 char* __ne = __nb + __nc;
1819 char* __np = this->__identify_padding(__nb, __ne, __iob);
1820 // Stage 2 - Widen __nar while adding thousands separators
1821 char_type __o[2*(__nbuf-1) - 1];
1822 char_type* __ob = __o;
1823 unique_ptr<char_type, void(*)(void*)> __obh(0, free);
1824 if (__nb != __nar)
1825 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00001826 __ob = (char_type*)malloc(2*static_cast<size_t>(__nc)*sizeof(char_type));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001827 if (__ob == 0)
1828 __throw_bad_alloc();
1829 __obh.reset(__ob);
1830 }
1831 char_type* __op; // pad here
1832 char_type* __oe; // end of output
1833 this->__widen_and_group_float(__nb, __np, __ne, __ob, __op, __oe, __iob.getloc());
1834 // [__o, __oe) contains thousands_sep'd wide number
1835 // Stage 3 & 4
1836 __s = __pad_and_output(__s, __ob, __op, __oe, __iob, __fl);
1837 return __s;
1838}
1839
1840template <class _CharT, class _OutputIterator>
1841_OutputIterator
1842num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1843 char_type __fl, long double __v) const
1844{
1845 // Stage 1 - Get number in narrow char
1846 char __fmt[8] = {'%', 0};
1847 const char* __len = "L";
1848 bool __specify_precision = this->__format_float(__fmt+1, __len, __iob.flags());
1849 const unsigned __nbuf = 30;
1850 char __nar[__nbuf];
1851 char* __nb = __nar;
1852 int __nc;
1853 if (__specify_precision)
Howard Hinnant866569b2011-09-28 23:39:33 +00001854#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001855 __nc = snprintf_l(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt,
Howard Hinnantadff4892010-05-24 17:49:41 +00001856 (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001857#else
1858 __nc = __snprintf_l(__nb, __nbuf, __cloc(), __fmt,
1859 (int)__iob.precision(), __v);
1860#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001861 else
Howard Hinnant866569b2011-09-28 23:39:33 +00001862#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001863 __nc = snprintf_l(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001864#else
1865 __nc = __snprintf_l(__nb, __nbuf, __cloc(), __fmt, __v);
1866#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001867 unique_ptr<char, void(*)(void*)> __nbh(0, free);
1868 if (__nc > static_cast<int>(__nbuf-1))
1869 {
1870 if (__specify_precision)
Howard Hinnant866569b2011-09-28 23:39:33 +00001871#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001872 __nc = asprintf_l(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001873#else
1874 __nc = __asprintf_l(&__nb, __cloc(), __fmt,
David Chisnallc512df12011-09-21 08:39:44 +00001875 (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001876#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001877 else
Howard Hinnant866569b2011-09-28 23:39:33 +00001878#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001879 __nc = asprintf_l(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001880#else
David Chisnallc512df12011-09-21 08:39:44 +00001881 __nc = __asprintf_l(&__nb, __cloc(), __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001882#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001883 if (__nb == 0)
1884 __throw_bad_alloc();
1885 __nbh.reset(__nb);
1886 }
1887 char* __ne = __nb + __nc;
1888 char* __np = this->__identify_padding(__nb, __ne, __iob);
1889 // Stage 2 - Widen __nar while adding thousands separators
1890 char_type __o[2*(__nbuf-1) - 1];
1891 char_type* __ob = __o;
1892 unique_ptr<char_type, void(*)(void*)> __obh(0, free);
1893 if (__nb != __nar)
1894 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00001895 __ob = (char_type*)malloc(2*static_cast<size_t>(__nc)*sizeof(char_type));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001896 if (__ob == 0)
1897 __throw_bad_alloc();
1898 __obh.reset(__ob);
1899 }
1900 char_type* __op; // pad here
1901 char_type* __oe; // end of output
1902 this->__widen_and_group_float(__nb, __np, __ne, __ob, __op, __oe, __iob.getloc());
1903 // [__o, __oe) contains thousands_sep'd wide number
1904 // Stage 3 & 4
1905 __s = __pad_and_output(__s, __ob, __op, __oe, __iob, __fl);
1906 return __s;
1907}
1908
1909template <class _CharT, class _OutputIterator>
1910_OutputIterator
1911num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1912 char_type __fl, const void* __v) const
1913{
1914 // Stage 1 - Get pointer in narrow char
1915 char __fmt[6] = "%p";
1916 const unsigned __nbuf = 20;
1917 char __nar[__nbuf];
Howard Hinnant866569b2011-09-28 23:39:33 +00001918#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001919 int __nc = sprintf_l(__nar, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001920#else
1921 int __nc = __sprintf_l(__nar, __cloc(), __fmt, __v);
1922#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001923 char* __ne = __nar + __nc;
1924 char* __np = this->__identify_padding(__nar, __ne, __iob);
1925 // Stage 2 - Widen __nar
1926 char_type __o[2*(__nbuf-1) - 1];
1927 char_type* __op; // pad here
1928 char_type* __oe; // end of output
1929 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
1930 __ct.widen(__nar, __ne, __o);
1931 __oe = __o + (__ne - __nar);
1932 if (__np == __ne)
1933 __op = __oe;
1934 else
1935 __op = __o + (__np - __nar);
1936 // [__o, __oe) contains wide number
1937 // Stage 3 & 4
1938 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1939}
1940
Howard Hinnantff926772012-11-06 21:08:48 +00001941_LIBCPP_EXTERN_TEMPLATE(class num_put<char>)
1942_LIBCPP_EXTERN_TEMPLATE(class num_put<wchar_t>)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001943
1944template <class _CharT, class _InputIterator>
1945_LIBCPP_HIDDEN
1946int
1947__get_up_to_n_digits(_InputIterator& __b, _InputIterator __e,
1948 ios_base::iostate& __err, const ctype<_CharT>& __ct, int __n)
1949{
1950 // Precondition: __n >= 1
1951 if (__b == __e)
1952 {
1953 __err |= ios_base::eofbit | ios_base::failbit;
1954 return 0;
1955 }
1956 // get first digit
1957 _CharT __c = *__b;
1958 if (!__ct.is(ctype_base::digit, __c))
1959 {
1960 __err |= ios_base::failbit;
1961 return 0;
1962 }
1963 int __r = __ct.narrow(__c, 0) - '0';
1964 for (++__b, --__n; __b != __e && __n > 0; ++__b, --__n)
1965 {
1966 // get next digit
1967 __c = *__b;
1968 if (!__ct.is(ctype_base::digit, __c))
1969 return __r;
1970 __r = __r * 10 + __ct.narrow(__c, 0) - '0';
1971 }
1972 if (__b == __e)
1973 __err |= ios_base::eofbit;
1974 return __r;
1975}
1976
Howard Hinnant82894812010-09-22 16:48:34 +00001977class _LIBCPP_VISIBLE time_base
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001978{
1979public:
1980 enum dateorder {no_order, dmy, mdy, ymd, ydm};
1981};
1982
1983template <class _CharT>
Howard Hinnant2d72b1e2010-12-17 14:46:43 +00001984class __time_get_c_storage // purposefully not decorated
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001985{
1986protected:
1987 typedef basic_string<_CharT> string_type;
1988
1989 virtual const string_type* __weeks() const;
1990 virtual const string_type* __months() const;
1991 virtual const string_type* __am_pm() const;
1992 virtual const string_type& __c() const;
1993 virtual const string_type& __r() const;
1994 virtual const string_type& __x() const;
1995 virtual const string_type& __X() const;
1996};
1997
1998template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00001999class _LIBCPP_VISIBLE time_get
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002000 : public locale::facet,
2001 public time_base,
2002 private __time_get_c_storage<_CharT>
2003{
2004public:
2005 typedef _CharT char_type;
2006 typedef _InputIterator iter_type;
2007 typedef time_base::dateorder dateorder;
2008 typedef basic_string<char_type> string_type;
2009
2010 _LIBCPP_ALWAYS_INLINE
2011 explicit time_get(size_t __refs = 0)
2012 : locale::facet(__refs) {}
2013
2014 _LIBCPP_ALWAYS_INLINE
2015 dateorder date_order() const
2016 {
2017 return this->do_date_order();
2018 }
2019
2020 _LIBCPP_ALWAYS_INLINE
2021 iter_type get_time(iter_type __b, iter_type __e, ios_base& __iob,
2022 ios_base::iostate& __err, tm* __tm) const
2023 {
2024 return do_get_time(__b, __e, __iob, __err, __tm);
2025 }
2026
2027 _LIBCPP_ALWAYS_INLINE
2028 iter_type get_date(iter_type __b, iter_type __e, ios_base& __iob,
2029 ios_base::iostate& __err, tm* __tm) const
2030 {
2031 return do_get_date(__b, __e, __iob, __err, __tm);
2032 }
2033
2034 _LIBCPP_ALWAYS_INLINE
2035 iter_type get_weekday(iter_type __b, iter_type __e, ios_base& __iob,
2036 ios_base::iostate& __err, tm* __tm) const
2037 {
2038 return do_get_weekday(__b, __e, __iob, __err, __tm);
2039 }
2040
2041 _LIBCPP_ALWAYS_INLINE
2042 iter_type get_monthname(iter_type __b, iter_type __e, ios_base& __iob,
2043 ios_base::iostate& __err, tm* __tm) const
2044 {
2045 return do_get_monthname(__b, __e, __iob, __err, __tm);
2046 }
2047
2048 _LIBCPP_ALWAYS_INLINE
2049 iter_type get_year(iter_type __b, iter_type __e, ios_base& __iob,
2050 ios_base::iostate& __err, tm* __tm) const
2051 {
2052 return do_get_year(__b, __e, __iob, __err, __tm);
2053 }
2054
2055 _LIBCPP_ALWAYS_INLINE
2056 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
2057 ios_base::iostate& __err, tm *__tm,
2058 char __fmt, char __mod = 0) const
2059 {
2060 return do_get(__b, __e, __iob, __err, __tm, __fmt, __mod);
2061 }
2062
2063 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
2064 ios_base::iostate& __err, tm* __tm,
2065 const char_type* __fmtb, const char_type* __fmte) const;
2066
2067 static locale::id id;
2068
2069protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002070 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002071 ~time_get() {}
2072
2073 virtual dateorder do_date_order() const;
2074 virtual iter_type do_get_time(iter_type __b, iter_type __e, ios_base& __iob,
2075 ios_base::iostate& __err, tm* __tm) const;
2076 virtual iter_type do_get_date(iter_type __b, iter_type __e, ios_base& __iob,
2077 ios_base::iostate& __err, tm* __tm) const;
2078 virtual iter_type do_get_weekday(iter_type __b, iter_type __e, ios_base& __iob,
2079 ios_base::iostate& __err, tm* __tm) const;
2080 virtual iter_type do_get_monthname(iter_type __b, iter_type __e, ios_base& __iob,
2081 ios_base::iostate& __err, tm* __tm) const;
2082 virtual iter_type do_get_year(iter_type __b, iter_type __e, ios_base& __iob,
2083 ios_base::iostate& __err, tm* __tm) const;
2084 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
2085 ios_base::iostate& __err, tm* __tm,
2086 char __fmt, char __mod) const;
2087private:
2088 void __get_white_space(iter_type& __b, iter_type __e,
2089 ios_base::iostate& __err, const ctype<char_type>& __ct) const;
2090 void __get_percent(iter_type& __b, iter_type __e, ios_base::iostate& __err,
2091 const ctype<char_type>& __ct) const;
2092
2093 void __get_weekdayname(int& __m,
2094 iter_type& __b, iter_type __e,
2095 ios_base::iostate& __err,
2096 const ctype<char_type>& __ct) const;
2097 void __get_monthname(int& __m,
2098 iter_type& __b, iter_type __e,
2099 ios_base::iostate& __err,
2100 const ctype<char_type>& __ct) const;
2101 void __get_day(int& __d,
2102 iter_type& __b, iter_type __e,
2103 ios_base::iostate& __err,
2104 const ctype<char_type>& __ct) const;
2105 void __get_month(int& __m,
2106 iter_type& __b, iter_type __e,
2107 ios_base::iostate& __err,
2108 const ctype<char_type>& __ct) const;
2109 void __get_year(int& __y,
2110 iter_type& __b, iter_type __e,
2111 ios_base::iostate& __err,
2112 const ctype<char_type>& __ct) const;
2113 void __get_year4(int& __y,
2114 iter_type& __b, iter_type __e,
2115 ios_base::iostate& __err,
2116 const ctype<char_type>& __ct) const;
2117 void __get_hour(int& __d,
2118 iter_type& __b, iter_type __e,
2119 ios_base::iostate& __err,
2120 const ctype<char_type>& __ct) const;
2121 void __get_12_hour(int& __h,
2122 iter_type& __b, iter_type __e,
2123 ios_base::iostate& __err,
2124 const ctype<char_type>& __ct) const;
2125 void __get_am_pm(int& __h,
2126 iter_type& __b, iter_type __e,
2127 ios_base::iostate& __err,
2128 const ctype<char_type>& __ct) const;
2129 void __get_minute(int& __m,
2130 iter_type& __b, iter_type __e,
2131 ios_base::iostate& __err,
2132 const ctype<char_type>& __ct) const;
2133 void __get_second(int& __s,
2134 iter_type& __b, iter_type __e,
2135 ios_base::iostate& __err,
2136 const ctype<char_type>& __ct) const;
2137 void __get_weekday(int& __w,
2138 iter_type& __b, iter_type __e,
2139 ios_base::iostate& __err,
2140 const ctype<char_type>& __ct) const;
2141 void __get_day_year_num(int& __w,
2142 iter_type& __b, iter_type __e,
2143 ios_base::iostate& __err,
2144 const ctype<char_type>& __ct) const;
2145};
2146
2147template <class _CharT, class _InputIterator>
2148locale::id
2149time_get<_CharT, _InputIterator>::id;
2150
2151// time_get primatives
2152
2153template <class _CharT, class _InputIterator>
2154void
2155time_get<_CharT, _InputIterator>::__get_weekdayname(int& __w,
2156 iter_type& __b, iter_type __e,
2157 ios_base::iostate& __err,
2158 const ctype<char_type>& __ct) const
2159{
2160 // Note: ignoring case comes from the POSIX strptime spec
2161 const string_type* __wk = this->__weeks();
Howard Hinnantec3773c2011-12-01 20:21:04 +00002162 ptrdiff_t __i = __scan_keyword(__b, __e, __wk, __wk+14, __ct, __err, false) - __wk;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002163 if (__i < 14)
2164 __w = __i % 7;
2165}
2166
2167template <class _CharT, class _InputIterator>
2168void
2169time_get<_CharT, _InputIterator>::__get_monthname(int& __m,
2170 iter_type& __b, iter_type __e,
2171 ios_base::iostate& __err,
2172 const ctype<char_type>& __ct) const
2173{
2174 // Note: ignoring case comes from the POSIX strptime spec
2175 const string_type* __month = this->__months();
Howard Hinnantec3773c2011-12-01 20:21:04 +00002176 ptrdiff_t __i = __scan_keyword(__b, __e, __month, __month+24, __ct, __err, false) - __month;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002177 if (__i < 24)
2178 __m = __i % 12;
2179}
2180
2181template <class _CharT, class _InputIterator>
2182void
2183time_get<_CharT, _InputIterator>::__get_day(int& __d,
2184 iter_type& __b, iter_type __e,
2185 ios_base::iostate& __err,
2186 const ctype<char_type>& __ct) const
2187{
2188 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2189 if (!(__err & ios_base::failbit) && 1 <= __t && __t <= 31)
2190 __d = __t;
2191 else
2192 __err |= ios_base::failbit;
2193}
2194
2195template <class _CharT, class _InputIterator>
2196void
2197time_get<_CharT, _InputIterator>::__get_month(int& __m,
2198 iter_type& __b, iter_type __e,
2199 ios_base::iostate& __err,
2200 const ctype<char_type>& __ct) const
2201{
2202 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2) - 1;
2203 if (!(__err & ios_base::failbit) && __t <= 11)
2204 __m = __t;
2205 else
2206 __err |= ios_base::failbit;
2207}
2208
2209template <class _CharT, class _InputIterator>
2210void
2211time_get<_CharT, _InputIterator>::__get_year(int& __y,
2212 iter_type& __b, iter_type __e,
2213 ios_base::iostate& __err,
2214 const ctype<char_type>& __ct) const
2215{
2216 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 4);
2217 if (!(__err & ios_base::failbit))
2218 {
2219 if (__t < 69)
2220 __t += 2000;
2221 else if (69 <= __t && __t <= 99)
2222 __t += 1900;
2223 __y = __t - 1900;
2224 }
2225}
2226
2227template <class _CharT, class _InputIterator>
2228void
2229time_get<_CharT, _InputIterator>::__get_year4(int& __y,
2230 iter_type& __b, iter_type __e,
2231 ios_base::iostate& __err,
2232 const ctype<char_type>& __ct) const
2233{
2234 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 4);
2235 if (!(__err & ios_base::failbit))
2236 __y = __t - 1900;
2237}
2238
2239template <class _CharT, class _InputIterator>
2240void
2241time_get<_CharT, _InputIterator>::__get_hour(int& __h,
2242 iter_type& __b, iter_type __e,
2243 ios_base::iostate& __err,
2244 const ctype<char_type>& __ct) const
2245{
2246 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2247 if (!(__err & ios_base::failbit) && __t <= 23)
2248 __h = __t;
2249 else
2250 __err |= ios_base::failbit;
2251}
2252
2253template <class _CharT, class _InputIterator>
2254void
2255time_get<_CharT, _InputIterator>::__get_12_hour(int& __h,
2256 iter_type& __b, iter_type __e,
2257 ios_base::iostate& __err,
2258 const ctype<char_type>& __ct) const
2259{
2260 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2261 if (!(__err & ios_base::failbit) && 1 <= __t && __t <= 12)
2262 __h = __t;
2263 else
2264 __err |= ios_base::failbit;
2265}
2266
2267template <class _CharT, class _InputIterator>
2268void
2269time_get<_CharT, _InputIterator>::__get_minute(int& __m,
2270 iter_type& __b, iter_type __e,
2271 ios_base::iostate& __err,
2272 const ctype<char_type>& __ct) const
2273{
2274 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2275 if (!(__err & ios_base::failbit) && __t <= 59)
2276 __m = __t;
2277 else
2278 __err |= ios_base::failbit;
2279}
2280
2281template <class _CharT, class _InputIterator>
2282void
2283time_get<_CharT, _InputIterator>::__get_second(int& __s,
2284 iter_type& __b, iter_type __e,
2285 ios_base::iostate& __err,
2286 const ctype<char_type>& __ct) const
2287{
2288 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2289 if (!(__err & ios_base::failbit) && __t <= 60)
2290 __s = __t;
2291 else
2292 __err |= ios_base::failbit;
2293}
2294
2295template <class _CharT, class _InputIterator>
2296void
2297time_get<_CharT, _InputIterator>::__get_weekday(int& __w,
2298 iter_type& __b, iter_type __e,
2299 ios_base::iostate& __err,
2300 const ctype<char_type>& __ct) const
2301{
2302 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 1);
2303 if (!(__err & ios_base::failbit) && __t <= 6)
2304 __w = __t;
2305 else
2306 __err |= ios_base::failbit;
2307}
2308
2309template <class _CharT, class _InputIterator>
2310void
2311time_get<_CharT, _InputIterator>::__get_day_year_num(int& __d,
2312 iter_type& __b, iter_type __e,
2313 ios_base::iostate& __err,
2314 const ctype<char_type>& __ct) const
2315{
2316 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 3);
2317 if (!(__err & ios_base::failbit) && __t <= 365)
2318 __d = __t;
2319 else
2320 __err |= ios_base::failbit;
2321}
2322
2323template <class _CharT, class _InputIterator>
2324void
2325time_get<_CharT, _InputIterator>::__get_white_space(iter_type& __b, iter_type __e,
2326 ios_base::iostate& __err,
2327 const ctype<char_type>& __ct) const
2328{
2329 for (; __b != __e && __ct.is(ctype_base::space, *__b); ++__b)
2330 ;
2331 if (__b == __e)
2332 __err |= ios_base::eofbit;
2333}
2334
2335template <class _CharT, class _InputIterator>
2336void
2337time_get<_CharT, _InputIterator>::__get_am_pm(int& __h,
2338 iter_type& __b, iter_type __e,
2339 ios_base::iostate& __err,
2340 const ctype<char_type>& __ct) const
2341{
2342 const string_type* __ap = this->__am_pm();
2343 if (__ap[0].size() + __ap[1].size() == 0)
2344 {
2345 __err |= ios_base::failbit;
2346 return;
2347 }
Howard Hinnantec3773c2011-12-01 20:21:04 +00002348 ptrdiff_t __i = __scan_keyword(__b, __e, __ap, __ap+2, __ct, __err, false) - __ap;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002349 if (__i == 0 && __h == 12)
2350 __h = 0;
2351 else if (__i == 1 && __h < 12)
2352 __h += 12;
2353}
2354
2355template <class _CharT, class _InputIterator>
2356void
2357time_get<_CharT, _InputIterator>::__get_percent(iter_type& __b, iter_type __e,
2358 ios_base::iostate& __err,
2359 const ctype<char_type>& __ct) const
2360{
2361 if (__b == __e)
2362 {
2363 __err |= ios_base::eofbit | ios_base::failbit;
2364 return;
2365 }
2366 if (__ct.narrow(*__b, 0) != '%')
2367 __err |= ios_base::failbit;
2368 else if(++__b == __e)
2369 __err |= ios_base::eofbit;
2370}
2371
2372// time_get end primatives
2373
2374template <class _CharT, class _InputIterator>
2375_InputIterator
2376time_get<_CharT, _InputIterator>::get(iter_type __b, iter_type __e,
2377 ios_base& __iob,
2378 ios_base::iostate& __err, tm* __tm,
2379 const char_type* __fmtb, const char_type* __fmte) const
2380{
2381 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2382 __err = ios_base::goodbit;
2383 while (__fmtb != __fmte && __err == ios_base::goodbit)
2384 {
2385 if (__b == __e)
2386 {
2387 __err = ios_base::failbit;
2388 break;
2389 }
2390 if (__ct.narrow(*__fmtb, 0) == '%')
2391 {
2392 if (++__fmtb == __fmte)
2393 {
2394 __err = ios_base::failbit;
2395 break;
2396 }
2397 char __cmd = __ct.narrow(*__fmtb, 0);
2398 char __opt = '\0';
2399 if (__cmd == 'E' || __cmd == '0')
2400 {
2401 if (++__fmtb == __fmte)
2402 {
2403 __err = ios_base::failbit;
2404 break;
2405 }
2406 __opt = __cmd;
2407 __cmd = __ct.narrow(*__fmtb, 0);
2408 }
2409 __b = do_get(__b, __e, __iob, __err, __tm, __cmd, __opt);
2410 ++__fmtb;
2411 }
2412 else if (__ct.is(ctype_base::space, *__fmtb))
2413 {
2414 for (++__fmtb; __fmtb != __fmte && __ct.is(ctype_base::space, *__fmtb); ++__fmtb)
2415 ;
2416 for ( ; __b != __e && __ct.is(ctype_base::space, *__b); ++__b)
2417 ;
2418 }
2419 else if (__ct.toupper(*__b) == __ct.toupper(*__fmtb))
2420 {
2421 ++__b;
2422 ++__fmtb;
2423 }
2424 else
2425 __err = ios_base::failbit;
2426 }
2427 if (__b == __e)
2428 __err |= ios_base::eofbit;
2429 return __b;
2430}
2431
2432template <class _CharT, class _InputIterator>
2433typename time_get<_CharT, _InputIterator>::dateorder
2434time_get<_CharT, _InputIterator>::do_date_order() const
2435{
2436 return mdy;
2437}
2438
2439template <class _CharT, class _InputIterator>
2440_InputIterator
2441time_get<_CharT, _InputIterator>::do_get_time(iter_type __b, iter_type __e,
2442 ios_base& __iob,
2443 ios_base::iostate& __err,
2444 tm* __tm) const
2445{
2446 const char_type __fmt[] = {'%', 'H', ':', '%', 'M', ':', '%', 'S'};
2447 return get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2448}
2449
2450template <class _CharT, class _InputIterator>
2451_InputIterator
2452time_get<_CharT, _InputIterator>::do_get_date(iter_type __b, iter_type __e,
2453 ios_base& __iob,
2454 ios_base::iostate& __err,
2455 tm* __tm) const
2456{
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002457 const string_type& __fmt = this->__x();
2458 return get(__b, __e, __iob, __err, __tm, __fmt.data(), __fmt.data() + __fmt.size());
2459}
2460
2461template <class _CharT, class _InputIterator>
2462_InputIterator
2463time_get<_CharT, _InputIterator>::do_get_weekday(iter_type __b, iter_type __e,
2464 ios_base& __iob,
2465 ios_base::iostate& __err,
2466 tm* __tm) const
2467{
2468 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2469 __get_weekdayname(__tm->tm_wday, __b, __e, __err, __ct);
2470 return __b;
2471}
2472
2473template <class _CharT, class _InputIterator>
2474_InputIterator
2475time_get<_CharT, _InputIterator>::do_get_monthname(iter_type __b, iter_type __e,
2476 ios_base& __iob,
2477 ios_base::iostate& __err,
2478 tm* __tm) const
2479{
2480 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2481 __get_monthname(__tm->tm_mon, __b, __e, __err, __ct);
2482 return __b;
2483}
2484
2485template <class _CharT, class _InputIterator>
2486_InputIterator
2487time_get<_CharT, _InputIterator>::do_get_year(iter_type __b, iter_type __e,
2488 ios_base& __iob,
2489 ios_base::iostate& __err,
2490 tm* __tm) const
2491{
2492 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2493 __get_year(__tm->tm_year, __b, __e, __err, __ct);
2494 return __b;
2495}
2496
2497template <class _CharT, class _InputIterator>
2498_InputIterator
2499time_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
2500 ios_base& __iob,
2501 ios_base::iostate& __err, tm* __tm,
2502 char __fmt, char) const
2503{
2504 __err = ios_base::goodbit;
2505 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2506 switch (__fmt)
2507 {
2508 case 'a':
2509 case 'A':
2510 __get_weekdayname(__tm->tm_wday, __b, __e, __err, __ct);
2511 break;
2512 case 'b':
2513 case 'B':
2514 case 'h':
2515 __get_monthname(__tm->tm_mon, __b, __e, __err, __ct);
2516 break;
2517 case 'c':
2518 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002519 const string_type& __fm = this->__c();
2520 __b = get(__b, __e, __iob, __err, __tm, __fm.data(), __fm.data() + __fm.size());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002521 }
2522 break;
2523 case 'd':
2524 case 'e':
2525 __get_day(__tm->tm_mday, __b, __e, __err, __ct);
2526 break;
2527 case 'D':
2528 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002529 const char_type __fm[] = {'%', 'm', '/', '%', 'd', '/', '%', 'y'};
2530 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm)/sizeof(__fm[0]));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002531 }
2532 break;
Howard Hinnant506b3642011-04-10 17:54:14 +00002533 case 'F':
2534 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002535 const char_type __fm[] = {'%', 'Y', '-', '%', 'm', '-', '%', 'd'};
2536 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm)/sizeof(__fm[0]));
Howard Hinnant506b3642011-04-10 17:54:14 +00002537 }
2538 break;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002539 case 'H':
2540 __get_hour(__tm->tm_hour, __b, __e, __err, __ct);
2541 break;
2542 case 'I':
2543 __get_12_hour(__tm->tm_hour, __b, __e, __err, __ct);
2544 break;
2545 case 'j':
2546 __get_day_year_num(__tm->tm_yday, __b, __e, __err, __ct);
2547 break;
2548 case 'm':
2549 __get_month(__tm->tm_mon, __b, __e, __err, __ct);
2550 break;
2551 case 'M':
2552 __get_minute(__tm->tm_min, __b, __e, __err, __ct);
2553 break;
2554 case 'n':
2555 case 't':
2556 __get_white_space(__b, __e, __err, __ct);
2557 break;
2558 case 'p':
2559 __get_am_pm(__tm->tm_hour, __b, __e, __err, __ct);
2560 break;
2561 case 'r':
2562 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002563 const char_type __fm[] = {'%', 'I', ':', '%', 'M', ':', '%', 'S', ' ', '%', 'p'};
2564 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm)/sizeof(__fm[0]));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002565 }
2566 break;
2567 case 'R':
2568 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002569 const char_type __fm[] = {'%', 'H', ':', '%', 'M'};
2570 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm)/sizeof(__fm[0]));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002571 }
2572 break;
2573 case 'S':
2574 __get_second(__tm->tm_sec, __b, __e, __err, __ct);
2575 break;
2576 case 'T':
2577 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002578 const char_type __fm[] = {'%', 'H', ':', '%', 'M', ':', '%', 'S'};
2579 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm)/sizeof(__fm[0]));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002580 }
2581 break;
2582 case 'w':
2583 __get_weekday(__tm->tm_wday, __b, __e, __err, __ct);
2584 break;
2585 case 'x':
2586 return do_get_date(__b, __e, __iob, __err, __tm);
2587 case 'X':
2588 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002589 const string_type& __fm = this->__X();
2590 __b = get(__b, __e, __iob, __err, __tm, __fm.data(), __fm.data() + __fm.size());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002591 }
2592 break;
2593 case 'y':
2594 __get_year(__tm->tm_year, __b, __e, __err, __ct);
2595 break;
2596 case 'Y':
2597 __get_year4(__tm->tm_year, __b, __e, __err, __ct);
2598 break;
2599 case '%':
2600 __get_percent(__b, __e, __err, __ct);
2601 break;
2602 default:
2603 __err |= ios_base::failbit;
2604 }
2605 return __b;
2606}
2607
Howard Hinnantff926772012-11-06 21:08:48 +00002608_LIBCPP_EXTERN_TEMPLATE(class time_get<char>)
2609_LIBCPP_EXTERN_TEMPLATE(class time_get<wchar_t>)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002610
2611class __time_get
2612{
2613protected:
2614 locale_t __loc_;
2615
2616 __time_get(const char* __nm);
2617 __time_get(const string& __nm);
2618 ~__time_get();
2619};
2620
2621template <class _CharT>
2622class __time_get_storage
2623 : public __time_get
2624{
2625protected:
2626 typedef basic_string<_CharT> string_type;
2627
2628 string_type __weeks_[14];
2629 string_type __months_[24];
2630 string_type __am_pm_[2];
2631 string_type __c_;
2632 string_type __r_;
2633 string_type __x_;
2634 string_type __X_;
2635
2636 explicit __time_get_storage(const char* __nm);
2637 explicit __time_get_storage(const string& __nm);
2638
2639 _LIBCPP_ALWAYS_INLINE ~__time_get_storage() {}
2640
2641 time_base::dateorder __do_date_order() const;
2642
2643private:
2644 void init(const ctype<_CharT>&);
2645 string_type __analyze(char __fmt, const ctype<_CharT>&);
2646};
2647
2648template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00002649class _LIBCPP_VISIBLE time_get_byname
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002650 : public time_get<_CharT, _InputIterator>,
2651 private __time_get_storage<_CharT>
2652{
2653public:
2654 typedef time_base::dateorder dateorder;
2655 typedef _InputIterator iter_type;
2656 typedef _CharT char_type;
2657 typedef basic_string<char_type> string_type;
2658
Howard Hinnant82894812010-09-22 16:48:34 +00002659 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002660 explicit time_get_byname(const char* __nm, size_t __refs = 0)
2661 : time_get<_CharT, _InputIterator>(__refs),
2662 __time_get_storage<_CharT>(__nm) {}
Howard Hinnant82894812010-09-22 16:48:34 +00002663 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002664 explicit time_get_byname(const string& __nm, size_t __refs = 0)
2665 : time_get<_CharT, _InputIterator>(__refs),
2666 __time_get_storage<_CharT>(__nm) {}
2667
2668protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002669 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002670 ~time_get_byname() {}
2671
Howard Hinnant82894812010-09-22 16:48:34 +00002672 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002673 virtual dateorder do_date_order() const {return this->__do_date_order();}
2674private:
Howard Hinnant82894812010-09-22 16:48:34 +00002675 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002676 virtual const string_type* __weeks() const {return this->__weeks_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002677 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002678 virtual const string_type* __months() const {return this->__months_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002679 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002680 virtual const string_type* __am_pm() const {return this->__am_pm_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002681 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002682 virtual const string_type& __c() const {return this->__c_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002683 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002684 virtual const string_type& __r() const {return this->__r_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002685 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002686 virtual const string_type& __x() const {return this->__x_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002687 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002688 virtual const string_type& __X() const {return this->__X_;}
2689};
2690
Howard Hinnantff926772012-11-06 21:08:48 +00002691_LIBCPP_EXTERN_TEMPLATE(class time_get_byname<char>)
2692_LIBCPP_EXTERN_TEMPLATE(class time_get_byname<wchar_t>)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002693
2694class __time_put
2695{
2696 locale_t __loc_;
2697protected:
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00002698 _LIBCPP_ALWAYS_INLINE __time_put() : __loc_(_LIBCPP_GET_C_LOCALE) {}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002699 __time_put(const char* __nm);
2700 __time_put(const string& __nm);
2701 ~__time_put();
2702 void __do_put(char* __nb, char*& __ne, const tm* __tm,
2703 char __fmt, char __mod) const;
2704 void __do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
2705 char __fmt, char __mod) const;
2706};
2707
2708template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00002709class _LIBCPP_VISIBLE time_put
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002710 : public locale::facet,
2711 private __time_put
2712{
2713public:
2714 typedef _CharT char_type;
2715 typedef _OutputIterator iter_type;
2716
2717 _LIBCPP_ALWAYS_INLINE
2718 explicit time_put(size_t __refs = 0)
2719 : locale::facet(__refs) {}
2720
2721 iter_type put(iter_type __s, ios_base& __iob, char_type __fl, const tm* __tm,
2722 const char_type* __pb, const char_type* __pe) const;
2723
2724 _LIBCPP_ALWAYS_INLINE
2725 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
2726 const tm* __tm, char __fmt, char __mod = 0) const
2727 {
2728 return do_put(__s, __iob, __fl, __tm, __fmt, __mod);
2729 }
2730
2731 static locale::id id;
2732
2733protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002734 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002735 ~time_put() {}
2736 virtual iter_type do_put(iter_type __s, ios_base&, char_type, const tm* __tm,
2737 char __fmt, char __mod) const;
2738
Howard Hinnant82894812010-09-22 16:48:34 +00002739 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002740 explicit time_put(const char* __nm, size_t __refs)
2741 : locale::facet(__refs),
2742 __time_put(__nm) {}
Howard Hinnant82894812010-09-22 16:48:34 +00002743 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002744 explicit time_put(const string& __nm, size_t __refs)
2745 : locale::facet(__refs),
2746 __time_put(__nm) {}
2747};
2748
2749template <class _CharT, class _OutputIterator>
2750locale::id
2751time_put<_CharT, _OutputIterator>::id;
2752
2753template <class _CharT, class _OutputIterator>
2754_OutputIterator
2755time_put<_CharT, _OutputIterator>::put(iter_type __s, ios_base& __iob,
2756 char_type __fl, const tm* __tm,
2757 const char_type* __pb,
2758 const char_type* __pe) const
2759{
2760 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2761 for (; __pb != __pe; ++__pb)
2762 {
2763 if (__ct.narrow(*__pb, 0) == '%')
2764 {
2765 if (++__pb == __pe)
2766 {
2767 *__s++ = __pb[-1];
2768 break;
2769 }
2770 char __mod = 0;
2771 char __fmt = __ct.narrow(*__pb, 0);
2772 if (__fmt == 'E' || __fmt == 'O')
2773 {
2774 if (++__pb == __pe)
2775 {
2776 *__s++ = __pb[-2];
2777 *__s++ = __pb[-1];
2778 break;
2779 }
2780 __mod = __fmt;
2781 __fmt = __ct.narrow(*__pb, 0);
2782 }
2783 __s = do_put(__s, __iob, __fl, __tm, __fmt, __mod);
2784 }
2785 else
2786 *__s++ = *__pb;
2787 }
2788 return __s;
2789}
2790
2791template <class _CharT, class _OutputIterator>
2792_OutputIterator
Howard Hinnantec3773c2011-12-01 20:21:04 +00002793time_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002794 char_type, const tm* __tm,
2795 char __fmt, char __mod) const
2796{
2797 char_type __nar[100];
2798 char_type* __nb = __nar;
2799 char_type* __ne = __nb + 100;
2800 __do_put(__nb, __ne, __tm, __fmt, __mod);
Howard Hinnant0949eed2011-06-30 21:18:19 +00002801 return _VSTD::copy(__nb, __ne, __s);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002802}
2803
Howard Hinnantff926772012-11-06 21:08:48 +00002804_LIBCPP_EXTERN_TEMPLATE(class time_put<char>)
2805_LIBCPP_EXTERN_TEMPLATE(class time_put<wchar_t>)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002806
2807template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00002808class _LIBCPP_VISIBLE time_put_byname
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002809 : public time_put<_CharT, _OutputIterator>
2810{
2811public:
2812 _LIBCPP_ALWAYS_INLINE
2813 explicit time_put_byname(const char* __nm, size_t __refs = 0)
2814 : time_put<_CharT, _OutputIterator>(__nm, __refs) {}
2815
2816 _LIBCPP_ALWAYS_INLINE
2817 explicit time_put_byname(const string& __nm, size_t __refs = 0)
2818 : time_put<_CharT, _OutputIterator>(__nm, __refs) {}
2819
2820protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002821 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002822 ~time_put_byname() {}
2823};
2824
Howard Hinnantff926772012-11-06 21:08:48 +00002825_LIBCPP_EXTERN_TEMPLATE(class time_put_byname<char>)
2826_LIBCPP_EXTERN_TEMPLATE(class time_put_byname<wchar_t>)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002827
2828// money_base
2829
Howard Hinnant82894812010-09-22 16:48:34 +00002830class _LIBCPP_VISIBLE money_base
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002831{
2832public:
2833 enum part {none, space, symbol, sign, value};
2834 struct pattern {char field[4];};
2835
2836 _LIBCPP_ALWAYS_INLINE money_base() {}
2837};
2838
2839// moneypunct
2840
2841template <class _CharT, bool _International = false>
Howard Hinnant82894812010-09-22 16:48:34 +00002842class _LIBCPP_VISIBLE moneypunct
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002843 : public locale::facet,
2844 public money_base
2845{
2846public:
2847 typedef _CharT char_type;
2848 typedef basic_string<char_type> string_type;
2849
Howard Hinnant82894812010-09-22 16:48:34 +00002850 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002851 explicit moneypunct(size_t __refs = 0)
2852 : locale::facet(__refs) {}
2853
2854 _LIBCPP_ALWAYS_INLINE char_type decimal_point() const {return do_decimal_point();}
2855 _LIBCPP_ALWAYS_INLINE char_type thousands_sep() const {return do_thousands_sep();}
2856 _LIBCPP_ALWAYS_INLINE string grouping() const {return do_grouping();}
2857 _LIBCPP_ALWAYS_INLINE string_type curr_symbol() const {return do_curr_symbol();}
2858 _LIBCPP_ALWAYS_INLINE string_type positive_sign() const {return do_positive_sign();}
2859 _LIBCPP_ALWAYS_INLINE string_type negative_sign() const {return do_negative_sign();}
2860 _LIBCPP_ALWAYS_INLINE int frac_digits() const {return do_frac_digits();}
2861 _LIBCPP_ALWAYS_INLINE pattern pos_format() const {return do_pos_format();}
2862 _LIBCPP_ALWAYS_INLINE pattern neg_format() const {return do_neg_format();}
2863
2864 static locale::id id;
2865 static const bool intl = _International;
2866
2867protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002868 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002869 ~moneypunct() {}
2870
2871 virtual char_type do_decimal_point() const {return numeric_limits<char_type>::max();}
2872 virtual char_type do_thousands_sep() const {return numeric_limits<char_type>::max();}
2873 virtual string do_grouping() const {return string();}
2874 virtual string_type do_curr_symbol() const {return string_type();}
2875 virtual string_type do_positive_sign() const {return string_type();}
2876 virtual string_type do_negative_sign() const {return string_type(1, '-');}
2877 virtual int do_frac_digits() const {return 0;}
2878 virtual pattern do_pos_format() const
2879 {pattern __p = {symbol, sign, none, value}; return __p;}
2880 virtual pattern do_neg_format() const
2881 {pattern __p = {symbol, sign, none, value}; return __p;}
2882};
2883
2884template <class _CharT, bool _International>
2885locale::id
2886moneypunct<_CharT, _International>::id;
2887
Howard Hinnantff926772012-11-06 21:08:48 +00002888_LIBCPP_EXTERN_TEMPLATE(class moneypunct<char, false>)
2889_LIBCPP_EXTERN_TEMPLATE(class moneypunct<char, true>)
2890_LIBCPP_EXTERN_TEMPLATE(class moneypunct<wchar_t, false>)
2891_LIBCPP_EXTERN_TEMPLATE(class moneypunct<wchar_t, true>)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002892
2893// moneypunct_byname
2894
2895template <class _CharT, bool _International = false>
Howard Hinnant82894812010-09-22 16:48:34 +00002896class _LIBCPP_VISIBLE moneypunct_byname
2897 : public moneypunct<_CharT, _International>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002898{
2899public:
2900 typedef money_base::pattern pattern;
2901 typedef _CharT char_type;
2902 typedef basic_string<char_type> string_type;
2903
2904 _LIBCPP_ALWAYS_INLINE
2905 explicit moneypunct_byname(const char* __nm, size_t __refs = 0)
2906 : moneypunct<_CharT, _International>(__refs) {init(__nm);}
2907
2908 _LIBCPP_ALWAYS_INLINE
2909 explicit moneypunct_byname(const string& __nm, size_t __refs = 0)
2910 : moneypunct<_CharT, _International>(__refs) {init(__nm.c_str());}
2911
2912protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002913 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002914 ~moneypunct_byname() {}
2915
2916 virtual char_type do_decimal_point() const {return __decimal_point_;}
2917 virtual char_type do_thousands_sep() const {return __thousands_sep_;}
2918 virtual string do_grouping() const {return __grouping_;}
2919 virtual string_type do_curr_symbol() const {return __curr_symbol_;}
2920 virtual string_type do_positive_sign() const {return __positive_sign_;}
2921 virtual string_type do_negative_sign() const {return __negative_sign_;}
2922 virtual int do_frac_digits() const {return __frac_digits_;}
2923 virtual pattern do_pos_format() const {return __pos_format_;}
2924 virtual pattern do_neg_format() const {return __neg_format_;}
2925
2926private:
2927 char_type __decimal_point_;
2928 char_type __thousands_sep_;
2929 string __grouping_;
2930 string_type __curr_symbol_;
2931 string_type __positive_sign_;
2932 string_type __negative_sign_;
2933 int __frac_digits_;
2934 pattern __pos_format_;
2935 pattern __neg_format_;
2936
2937 void init(const char*);
2938};
2939
2940template<> void moneypunct_byname<char, false>::init(const char*);
2941template<> void moneypunct_byname<char, true>::init(const char*);
2942template<> void moneypunct_byname<wchar_t, false>::init(const char*);
2943template<> void moneypunct_byname<wchar_t, true>::init(const char*);
2944
Howard Hinnantff926772012-11-06 21:08:48 +00002945_LIBCPP_EXTERN_TEMPLATE(class moneypunct_byname<char, false>)
2946_LIBCPP_EXTERN_TEMPLATE(class moneypunct_byname<char, true>)
2947_LIBCPP_EXTERN_TEMPLATE(class moneypunct_byname<wchar_t, false>)
2948_LIBCPP_EXTERN_TEMPLATE(class moneypunct_byname<wchar_t, true>)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002949
2950// money_get
2951
2952template <class _CharT>
2953class __money_get
2954{
2955protected:
2956 typedef _CharT char_type;
2957 typedef basic_string<char_type> string_type;
2958
2959 _LIBCPP_ALWAYS_INLINE __money_get() {}
2960
2961 static void __gather_info(bool __intl, const locale& __loc,
2962 money_base::pattern& __pat, char_type& __dp,
2963 char_type& __ts, string& __grp,
2964 string_type& __sym, string_type& __psn,
2965 string_type& __nsn, int& __fd);
2966};
2967
2968template <class _CharT>
2969void
2970__money_get<_CharT>::__gather_info(bool __intl, const locale& __loc,
2971 money_base::pattern& __pat, char_type& __dp,
2972 char_type& __ts, string& __grp,
2973 string_type& __sym, string_type& __psn,
2974 string_type& __nsn, int& __fd)
2975{
2976 if (__intl)
2977 {
2978 const moneypunct<char_type, true>& __mp =
2979 use_facet<moneypunct<char_type, true> >(__loc);
2980 __pat = __mp.neg_format();
2981 __nsn = __mp.negative_sign();
2982 __psn = __mp.positive_sign();
2983 __dp = __mp.decimal_point();
2984 __ts = __mp.thousands_sep();
2985 __grp = __mp.grouping();
2986 __sym = __mp.curr_symbol();
2987 __fd = __mp.frac_digits();
2988 }
2989 else
2990 {
2991 const moneypunct<char_type, false>& __mp =
2992 use_facet<moneypunct<char_type, false> >(__loc);
2993 __pat = __mp.neg_format();
2994 __nsn = __mp.negative_sign();
2995 __psn = __mp.positive_sign();
2996 __dp = __mp.decimal_point();
2997 __ts = __mp.thousands_sep();
2998 __grp = __mp.grouping();
2999 __sym = __mp.curr_symbol();
3000 __fd = __mp.frac_digits();
3001 }
3002}
3003
Howard Hinnantff926772012-11-06 21:08:48 +00003004_LIBCPP_EXTERN_TEMPLATE(class __money_get<char>)
3005_LIBCPP_EXTERN_TEMPLATE(class __money_get<wchar_t>)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003006
3007template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00003008class _LIBCPP_VISIBLE money_get
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003009 : public locale::facet,
3010 private __money_get<_CharT>
3011{
3012public:
3013 typedef _CharT char_type;
3014 typedef _InputIterator iter_type;
3015 typedef basic_string<char_type> string_type;
3016
3017 _LIBCPP_ALWAYS_INLINE
3018 explicit money_get(size_t __refs = 0)
3019 : locale::facet(__refs) {}
3020
3021 _LIBCPP_ALWAYS_INLINE
3022 iter_type get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob,
3023 ios_base::iostate& __err, long double& __v) const
3024 {
3025 return do_get(__b, __e, __intl, __iob, __err, __v);
3026 }
3027
3028 _LIBCPP_ALWAYS_INLINE
3029 iter_type get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob,
3030 ios_base::iostate& __err, string_type& __v) const
3031 {
3032 return do_get(__b, __e, __intl, __iob, __err, __v);
3033 }
3034
3035 static locale::id id;
3036
3037protected:
3038
Howard Hinnant82894812010-09-22 16:48:34 +00003039 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003040 ~money_get() {}
Howard Hinnant324bb032010-08-22 00:02:43 +00003041
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003042 virtual iter_type do_get(iter_type __b, iter_type __e, bool __intl,
3043 ios_base& __iob, ios_base::iostate& __err,
3044 long double& __v) const;
3045 virtual iter_type do_get(iter_type __b, iter_type __e, bool __intl,
3046 ios_base& __iob, ios_base::iostate& __err,
3047 string_type& __v) const;
3048
3049private:
3050 static bool __do_get(iter_type& __b, iter_type __e,
3051 bool __intl, const locale& __loc,
3052 ios_base::fmtflags __flags, ios_base::iostate& __err,
3053 bool& __neg, const ctype<char_type>& __ct,
3054 unique_ptr<char_type, void(*)(void*)>& __wb,
3055 char_type*& __wn, char_type* __we);
3056};
3057
3058template <class _CharT, class _InputIterator>
3059locale::id
3060money_get<_CharT, _InputIterator>::id;
3061
3062void __do_nothing(void*);
3063
3064template <class _Tp>
3065_LIBCPP_HIDDEN
3066void
3067__double_or_nothing(unique_ptr<_Tp, void(*)(void*)>& __b, _Tp*& __n, _Tp*& __e)
3068{
3069 bool __owns = __b.get_deleter() != __do_nothing;
Howard Hinnantec3773c2011-12-01 20:21:04 +00003070 size_t __cur_cap = static_cast<size_t>(__e-__b.get()) * sizeof(_Tp);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003071 size_t __new_cap = __cur_cap < numeric_limits<size_t>::max() / 2 ?
3072 2 * __cur_cap : numeric_limits<size_t>::max();
Howard Hinnantec3773c2011-12-01 20:21:04 +00003073 size_t __n_off = static_cast<size_t>(__n - __b.get());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003074 _Tp* __t = (_Tp*)realloc(__owns ? __b.get() : 0, __new_cap);
3075 if (__t == 0)
3076 __throw_bad_alloc();
3077 if (__owns)
3078 __b.release();
3079 __b = unique_ptr<_Tp, void(*)(void*)>(__t, free);
3080 __new_cap /= sizeof(_Tp);
3081 __n = __b.get() + __n_off;
3082 __e = __b.get() + __new_cap;
3083}
3084
3085// true == success
3086template <class _CharT, class _InputIterator>
3087bool
3088money_get<_CharT, _InputIterator>::__do_get(iter_type& __b, iter_type __e,
3089 bool __intl, const locale& __loc,
3090 ios_base::fmtflags __flags,
3091 ios_base::iostate& __err,
3092 bool& __neg,
3093 const ctype<char_type>& __ct,
3094 unique_ptr<char_type, void(*)(void*)>& __wb,
3095 char_type*& __wn, char_type* __we)
3096{
3097 const unsigned __bz = 100;
3098 unsigned __gbuf[__bz];
3099 unique_ptr<unsigned, void(*)(void*)> __gb(__gbuf, __do_nothing);
3100 unsigned* __gn = __gb.get();
3101 unsigned* __ge = __gn + __bz;
3102 money_base::pattern __pat;
3103 char_type __dp;
3104 char_type __ts;
3105 string __grp;
3106 string_type __sym;
3107 string_type __psn;
3108 string_type __nsn;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00003109 // Capture the spaces read into money_base::{space,none} so they
3110 // can be compared to initial spaces in __sym.
3111 string_type __spaces;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003112 int __fd;
3113 __money_get<_CharT>::__gather_info(__intl, __loc, __pat, __dp, __ts, __grp,
3114 __sym, __psn, __nsn, __fd);
3115 const string_type* __trailing_sign = 0;
3116 __wn = __wb.get();
3117 for (unsigned __p = 0; __p < 4 && __b != __e; ++__p)
3118 {
3119 switch (__pat.field[__p])
3120 {
3121 case money_base::space:
3122 if (__p != 3)
3123 {
3124 if (__ct.is(ctype_base::space, *__b))
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00003125 __spaces.push_back(*__b++);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003126 else
3127 {
3128 __err |= ios_base::failbit;
3129 return false;
3130 }
3131 }
Howard Hinnant324bb032010-08-22 00:02:43 +00003132 // drop through
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003133 case money_base::none:
3134 if (__p != 3)
3135 {
3136 while (__b != __e && __ct.is(ctype_base::space, *__b))
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00003137 __spaces.push_back(*__b++);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003138 }
3139 break;
3140 case money_base::sign:
3141 if (__psn.size() + __nsn.size() > 0)
3142 {
3143 if (__psn.size() == 0 || __nsn.size() == 0)
3144 { // sign is optional
3145 if (__psn.size() > 0)
3146 { // __nsn.size() == 0
3147 if (*__b == __psn[0])
3148 {
3149 ++__b;
3150 if (__psn.size() > 1)
3151 __trailing_sign = &__psn;
3152 }
3153 else
3154 __neg = true;
3155 }
3156 else if (*__b == __nsn[0]) // __nsn.size() > 0 && __psn.size() == 0
3157 {
3158 ++__b;
3159 __neg = true;
3160 if (__nsn.size() > 1)
3161 __trailing_sign = &__nsn;
3162 }
3163 }
3164 else // sign is required
3165 {
3166 if (*__b == __psn[0])
3167 {
3168 ++__b;
3169 if (__psn.size() > 1)
3170 __trailing_sign = &__psn;
3171 }
3172 else if (*__b == __nsn[0])
3173 {
3174 ++__b;
3175 __neg = true;
3176 if (__nsn.size() > 1)
3177 __trailing_sign = &__nsn;
3178 }
3179 else
3180 {
3181 __err |= ios_base::failbit;
3182 return false;
3183 }
3184 }
3185 }
3186 break;
3187 case money_base::symbol:
3188 {
3189 bool __more_needed = __trailing_sign ||
3190 (__p < 2) ||
3191 (__p == 2 && __pat.field[3] != static_cast<char>(money_base::none));
3192 bool __sb = __flags & ios_base::showbase;
3193 if (__sb || __more_needed)
3194 {
3195 ios_base::iostate __et = ios_base::goodbit;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00003196 typename string_type::const_iterator __sym_space_end = __sym.begin();
3197 if (__p > 0 && (__pat.field[__p - 1] == money_base::none ||
3198 __pat.field[__p - 1] == money_base::space)) {
3199 // Match spaces we've already read against spaces at
3200 // the beginning of __sym.
3201 while (__sym_space_end != __sym.end() &&
3202 __ct.is(ctype_base::space, *__sym_space_end))
3203 ++__sym_space_end;
3204 const size_t __num_spaces = __sym_space_end - __sym.begin();
3205 if (__num_spaces > __spaces.size() ||
3206 !equal(__spaces.end() - __num_spaces, __spaces.end(),
3207 __sym.begin())) {
3208 // No match. Put __sym_space_end back at the
3209 // beginning of __sym, which will prevent a
3210 // match in the next loop.
3211 __sym_space_end = __sym.begin();
3212 }
3213 }
3214 typename string_type::const_iterator __sym_curr_char = __sym_space_end;
3215 while (__sym_curr_char != __sym.end() && __b != __e &&
3216 *__b == *__sym_curr_char) {
3217 ++__b;
3218 ++__sym_curr_char;
3219 }
3220 if (__sb && __sym_curr_char != __sym.end())
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003221 {
3222 __err |= ios_base::failbit;
3223 return false;
3224 }
3225 }
3226 }
3227 break;
3228 case money_base::value:
3229 {
3230 unsigned __ng = 0;
3231 for (; __b != __e; ++__b)
3232 {
3233 char_type __c = *__b;
3234 if (__ct.is(ctype_base::digit, __c))
3235 {
3236 if (__wn == __we)
3237 __double_or_nothing(__wb, __wn, __we);
3238 *__wn++ = __c;
3239 ++__ng;
3240 }
3241 else if (__grp.size() > 0 && __ng > 0 && __c == __ts)
3242 {
3243 if (__gn == __ge)
3244 __double_or_nothing(__gb, __gn, __ge);
3245 *__gn++ = __ng;
3246 __ng = 0;
3247 }
3248 else
3249 break;
3250 }
3251 if (__gb.get() != __gn && __ng > 0)
3252 {
3253 if (__gn == __ge)
3254 __double_or_nothing(__gb, __gn, __ge);
3255 *__gn++ = __ng;
3256 }
3257 if (__fd > 0)
3258 {
3259 if (__b == __e || *__b != __dp)
3260 {
3261 __err |= ios_base::failbit;
3262 return false;
3263 }
3264 for (++__b; __fd > 0; --__fd, ++__b)
3265 {
3266 if (__b == __e || !__ct.is(ctype_base::digit, *__b))
3267 {
3268 __err |= ios_base::failbit;
3269 return false;
3270 }
3271 if (__wn == __we)
3272 __double_or_nothing(__wb, __wn, __we);
3273 *__wn++ = *__b;
3274 }
3275 }
3276 if (__wn == __wb.get())
3277 {
3278 __err |= ios_base::failbit;
3279 return false;
3280 }
3281 }
3282 break;
3283 }
3284 }
3285 if (__trailing_sign)
3286 {
3287 for (unsigned __i = 1; __i < __trailing_sign->size(); ++__i, ++__b)
3288 {
3289 if (__b == __e || *__b != (*__trailing_sign)[__i])
3290 {
3291 __err |= ios_base::failbit;
3292 return false;
3293 }
3294 }
3295 }
3296 if (__gb.get() != __gn)
3297 {
3298 ios_base::iostate __et = ios_base::goodbit;
3299 __check_grouping(__grp, __gb.get(), __gn, __et);
3300 if (__et)
3301 {
3302 __err |= ios_base::failbit;
3303 return false;
3304 }
3305 }
3306 return true;
3307}
3308
3309template <class _CharT, class _InputIterator>
3310_InputIterator
3311money_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
3312 bool __intl, ios_base& __iob,
3313 ios_base::iostate& __err,
3314 long double& __v) const
3315{
Howard Hinnantec3773c2011-12-01 20:21:04 +00003316 const int __bz = 100;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003317 char_type __wbuf[__bz];
3318 unique_ptr<char_type, void(*)(void*)> __wb(__wbuf, __do_nothing);
3319 char_type* __wn;
3320 char_type* __we = __wbuf + __bz;
3321 locale __loc = __iob.getloc();
3322 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3323 bool __neg = false;
3324 if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct,
3325 __wb, __wn, __we))
3326 {
3327 const char __src[] = "0123456789";
3328 char_type __atoms[sizeof(__src)-1];
3329 __ct.widen(__src, __src + (sizeof(__src)-1), __atoms);
3330 char __nbuf[__bz];
3331 char* __nc = __nbuf;
3332 unique_ptr<char, void(*)(void*)> __h(0, free);
3333 if (__wn - __wb.get() > __bz-2)
3334 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00003335 __h.reset((char*)malloc(static_cast<size_t>(__wn - __wb.get() + 2)));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003336 if (__h.get() == 0)
3337 __throw_bad_alloc();
3338 __nc = __h.get();
3339 }
3340 if (__neg)
3341 *__nc++ = '-';
3342 for (const char_type* __w = __wb.get(); __w < __wn; ++__w, ++__nc)
3343 *__nc = __src[find(__atoms, __atoms+sizeof(__atoms), *__w) - __atoms];
3344 *__nc = char();
3345 if (sscanf(__nbuf, "%Lf", &__v) != 1)
3346 __throw_runtime_error("money_get error");
3347 }
3348 if (__b == __e)
3349 __err |= ios_base::eofbit;
3350 return __b;
3351}
3352
3353template <class _CharT, class _InputIterator>
3354_InputIterator
3355money_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
3356 bool __intl, ios_base& __iob,
3357 ios_base::iostate& __err,
3358 string_type& __v) const
3359{
Howard Hinnantec3773c2011-12-01 20:21:04 +00003360 const int __bz = 100;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003361 char_type __wbuf[__bz];
3362 unique_ptr<char_type, void(*)(void*)> __wb(__wbuf, __do_nothing);
3363 char_type* __wn;
3364 char_type* __we = __wbuf + __bz;
3365 locale __loc = __iob.getloc();
3366 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3367 bool __neg = false;
3368 if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct,
3369 __wb, __wn, __we))
3370 {
3371 __v.clear();
3372 if (__neg)
3373 __v.push_back(__ct.widen('-'));
3374 char_type __z = __ct.widen('0');
3375 char_type* __w;
3376 for (__w = __wb.get(); __w < __wn-1; ++__w)
3377 if (*__w != __z)
3378 break;
3379 __v.append(__w, __wn);
3380 }
3381 if (__b == __e)
3382 __err |= ios_base::eofbit;
3383 return __b;
3384}
3385
Howard Hinnantff926772012-11-06 21:08:48 +00003386_LIBCPP_EXTERN_TEMPLATE(class money_get<char>)
3387_LIBCPP_EXTERN_TEMPLATE(class money_get<wchar_t>)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003388
3389// money_put
3390
3391template <class _CharT>
3392class __money_put
3393{
3394protected:
3395 typedef _CharT char_type;
3396 typedef basic_string<char_type> string_type;
3397
3398 _LIBCPP_ALWAYS_INLINE __money_put() {}
3399
3400 static void __gather_info(bool __intl, bool __neg, const locale& __loc,
3401 money_base::pattern& __pat, char_type& __dp,
3402 char_type& __ts, string& __grp,
3403 string_type& __sym, string_type& __sn,
3404 int& __fd);
3405 static void __format(char_type* __mb, char_type*& __mi, char_type*& __me,
3406 ios_base::fmtflags __flags,
3407 const char_type* __db, const char_type* __de,
3408 const ctype<char_type>& __ct, bool __neg,
3409 const money_base::pattern& __pat, char_type __dp,
3410 char_type __ts, const string& __grp,
3411 const string_type& __sym, const string_type& __sn,
3412 int __fd);
3413};
3414
3415template <class _CharT>
3416void
3417__money_put<_CharT>::__gather_info(bool __intl, bool __neg, const locale& __loc,
3418 money_base::pattern& __pat, char_type& __dp,
3419 char_type& __ts, string& __grp,
3420 string_type& __sym, string_type& __sn,
3421 int& __fd)
3422{
3423 if (__intl)
3424 {
3425 const moneypunct<char_type, true>& __mp =
3426 use_facet<moneypunct<char_type, true> >(__loc);
3427 if (__neg)
3428 {
3429 __pat = __mp.neg_format();
3430 __sn = __mp.negative_sign();
3431 }
3432 else
3433 {
3434 __pat = __mp.pos_format();
3435 __sn = __mp.positive_sign();
3436 }
3437 __dp = __mp.decimal_point();
3438 __ts = __mp.thousands_sep();
3439 __grp = __mp.grouping();
3440 __sym = __mp.curr_symbol();
3441 __fd = __mp.frac_digits();
3442 }
3443 else
3444 {
3445 const moneypunct<char_type, false>& __mp =
3446 use_facet<moneypunct<char_type, false> >(__loc);
3447 if (__neg)
3448 {
3449 __pat = __mp.neg_format();
3450 __sn = __mp.negative_sign();
3451 }
3452 else
3453 {
3454 __pat = __mp.pos_format();
3455 __sn = __mp.positive_sign();
3456 }
3457 __dp = __mp.decimal_point();
3458 __ts = __mp.thousands_sep();
3459 __grp = __mp.grouping();
3460 __sym = __mp.curr_symbol();
3461 __fd = __mp.frac_digits();
3462 }
3463}
3464
3465template <class _CharT>
3466void
3467__money_put<_CharT>::__format(char_type* __mb, char_type*& __mi, char_type*& __me,
3468 ios_base::fmtflags __flags,
3469 const char_type* __db, const char_type* __de,
3470 const ctype<char_type>& __ct, bool __neg,
3471 const money_base::pattern& __pat, char_type __dp,
3472 char_type __ts, const string& __grp,
3473 const string_type& __sym, const string_type& __sn,
3474 int __fd)
3475{
3476 __me = __mb;
3477 for (unsigned __p = 0; __p < 4; ++__p)
3478 {
3479 switch (__pat.field[__p])
3480 {
3481 case money_base::none:
3482 __mi = __me;
3483 break;
3484 case money_base::space:
3485 __mi = __me;
3486 *__me++ = __ct.widen(' ');
3487 break;
3488 case money_base::sign:
3489 if (!__sn.empty())
3490 *__me++ = __sn[0];
3491 break;
3492 case money_base::symbol:
3493 if (!__sym.empty() && (__flags & ios_base::showbase))
Howard Hinnant0949eed2011-06-30 21:18:19 +00003494 __me = _VSTD::copy(__sym.begin(), __sym.end(), __me);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003495 break;
3496 case money_base::value:
3497 {
3498 // remember start of value so we can reverse it
3499 char_type* __t = __me;
3500 // find beginning of digits
3501 if (__neg)
3502 ++__db;
3503 // find end of digits
3504 const char_type* __d;
3505 for (__d = __db; __d < __de; ++__d)
3506 if (!__ct.is(ctype_base::digit, *__d))
3507 break;
3508 // print fractional part
3509 if (__fd > 0)
3510 {
3511 int __f;
3512 for (__f = __fd; __d > __db && __f > 0; --__f)
3513 *__me++ = *--__d;
3514 char_type __z = __f > 0 ? __ct.widen('0') : char_type();
3515 for (; __f > 0; --__f)
3516 *__me++ = __z;
3517 *__me++ = __dp;
3518 }
3519 // print units part
3520 if (__d == __db)
3521 {
3522 *__me++ = __ct.widen('0');
3523 }
3524 else
3525 {
3526 unsigned __ng = 0;
3527 unsigned __ig = 0;
3528 unsigned __gl = __grp.empty() ? numeric_limits<unsigned>::max()
3529 : static_cast<unsigned>(__grp[__ig]);
3530 while (__d != __db)
3531 {
3532 if (__ng == __gl)
3533 {
3534 *__me++ = __ts;
3535 __ng = 0;
3536 if (++__ig < __grp.size())
3537 __gl = __grp[__ig] == numeric_limits<char>::max() ?
3538 numeric_limits<unsigned>::max() :
3539 static_cast<unsigned>(__grp[__ig]);
3540 }
3541 *__me++ = *--__d;
3542 ++__ng;
3543 }
3544 }
3545 // reverse it
3546 reverse(__t, __me);
3547 }
3548 break;
3549 }
3550 }
3551 // print rest of sign, if any
3552 if (__sn.size() > 1)
Howard Hinnant0949eed2011-06-30 21:18:19 +00003553 __me = _VSTD::copy(__sn.begin()+1, __sn.end(), __me);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003554 // set alignment
3555 if ((__flags & ios_base::adjustfield) == ios_base::left)
3556 __mi = __me;
3557 else if ((__flags & ios_base::adjustfield) != ios_base::internal)
3558 __mi = __mb;
3559}
3560
Howard Hinnantff926772012-11-06 21:08:48 +00003561_LIBCPP_EXTERN_TEMPLATE(class __money_put<char>)
3562_LIBCPP_EXTERN_TEMPLATE(class __money_put<wchar_t>)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003563
3564template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00003565class _LIBCPP_VISIBLE money_put
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003566 : public locale::facet,
3567 private __money_put<_CharT>
3568{
3569public:
3570 typedef _CharT char_type;
3571 typedef _OutputIterator iter_type;
3572 typedef basic_string<char_type> string_type;
3573
3574 _LIBCPP_ALWAYS_INLINE
3575 explicit money_put(size_t __refs = 0)
3576 : locale::facet(__refs) {}
3577
3578 _LIBCPP_ALWAYS_INLINE
3579 iter_type put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl,
3580 long double __units) const
3581 {
3582 return do_put(__s, __intl, __iob, __fl, __units);
3583 }
3584
3585 _LIBCPP_ALWAYS_INLINE
3586 iter_type put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl,
3587 const string_type& __digits) const
3588 {
3589 return do_put(__s, __intl, __iob, __fl, __digits);
3590 }
3591
3592 static locale::id id;
3593
3594protected:
Howard Hinnant82894812010-09-22 16:48:34 +00003595 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003596 ~money_put() {}
3597
3598 virtual iter_type do_put(iter_type __s, bool __intl, ios_base& __iob,
3599 char_type __fl, long double __units) const;
3600 virtual iter_type do_put(iter_type __s, bool __intl, ios_base& __iob,
3601 char_type __fl, const string_type& __digits) const;
3602};
3603
3604template <class _CharT, class _OutputIterator>
3605locale::id
3606money_put<_CharT, _OutputIterator>::id;
3607
3608template <class _CharT, class _OutputIterator>
3609_OutputIterator
3610money_put<_CharT, _OutputIterator>::do_put(iter_type __s, bool __intl,
3611 ios_base& __iob, char_type __fl,
3612 long double __units) const
3613{
3614 // convert to char
3615 const size_t __bs = 100;
3616 char __buf[__bs];
3617 char* __bb = __buf;
3618 char_type __digits[__bs];
3619 char_type* __db = __digits;
Howard Hinnantec3773c2011-12-01 20:21:04 +00003620 size_t __n = static_cast<size_t>(snprintf(__bb, __bs, "%.0Lf", __units));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003621 unique_ptr<char, void(*)(void*)> __hn(0, free);
3622 unique_ptr<char_type, void(*)(void*)> __hd(0, free);
3623 // secure memory for digit storage
3624 if (__n > __bs-1)
3625 {
Howard Hinnant866569b2011-09-28 23:39:33 +00003626#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00003627 __n = static_cast<size_t>(asprintf_l(&__bb, _LIBCPP_GET_C_LOCALE, "%.0Lf", __units));
Sean Huntf3907e62011-07-15 05:40:33 +00003628#else
3629 __n = __asprintf_l(&__bb, __cloc(), "%.0Lf", __units);
3630#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003631 if (__bb == 0)
3632 __throw_bad_alloc();
3633 __hn.reset(__bb);
3634 __hd.reset((char_type*)malloc(__n * sizeof(char_type)));
Howard Hinnant05b57d52012-03-07 20:37:43 +00003635 if (__hd == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003636 __throw_bad_alloc();
3637 __db = __hd.get();
3638 }
3639 // gather info
3640 locale __loc = __iob.getloc();
3641 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3642 __ct.widen(__bb, __bb + __n, __db);
3643 bool __neg = __n > 0 && __bb[0] == '-';
3644 money_base::pattern __pat;
3645 char_type __dp;
3646 char_type __ts;
3647 string __grp;
3648 string_type __sym;
3649 string_type __sn;
3650 int __fd;
3651 this->__gather_info(__intl, __neg, __loc, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3652 // secure memory for formatting
3653 char_type __mbuf[__bs];
3654 char_type* __mb = __mbuf;
3655 unique_ptr<char_type, void(*)(void*)> __hw(0, free);
3656 size_t __exn = static_cast<int>(__n) > __fd ?
Howard Hinnantec3773c2011-12-01 20:21:04 +00003657 (__n - static_cast<size_t>(__fd)) * 2 + __sn.size() +
3658 __sym.size() + static_cast<size_t>(__fd) + 1
3659 : __sn.size() + __sym.size() + static_cast<size_t>(__fd) + 2;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003660 if (__exn > __bs)
3661 {
3662 __hw.reset((char_type*)malloc(__exn * sizeof(char_type)));
3663 __mb = __hw.get();
3664 if (__mb == 0)
3665 __throw_bad_alloc();
3666 }
3667 // format
3668 char_type* __mi;
3669 char_type* __me;
3670 this->__format(__mb, __mi, __me, __iob.flags(),
3671 __db, __db + __n, __ct,
3672 __neg, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3673 return __pad_and_output(__s, __mb, __mi, __me, __iob, __fl);
3674}
3675
3676template <class _CharT, class _OutputIterator>
3677_OutputIterator
3678money_put<_CharT, _OutputIterator>::do_put(iter_type __s, bool __intl,
3679 ios_base& __iob, char_type __fl,
3680 const string_type& __digits) const
3681{
3682 // gather info
3683 locale __loc = __iob.getloc();
3684 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3685 bool __neg = __digits.size() > 0 && __digits[0] == __ct.widen('-');
3686 money_base::pattern __pat;
3687 char_type __dp;
3688 char_type __ts;
3689 string __grp;
3690 string_type __sym;
3691 string_type __sn;
3692 int __fd;
3693 this->__gather_info(__intl, __neg, __loc, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3694 // secure memory for formatting
3695 char_type __mbuf[100];
3696 char_type* __mb = __mbuf;
3697 unique_ptr<char_type, void(*)(void*)> __h(0, free);
Howard Hinnantec3773c2011-12-01 20:21:04 +00003698 size_t __exn = static_cast<int>(__digits.size()) > __fd ?
3699 (__digits.size() - static_cast<size_t>(__fd)) * 2 +
3700 __sn.size() + __sym.size() + static_cast<size_t>(__fd) + 1
3701 : __sn.size() + __sym.size() + static_cast<size_t>(__fd) + 2;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003702 if (__exn > 100)
3703 {
3704 __h.reset((char_type*)malloc(__exn * sizeof(char_type)));
3705 __mb = __h.get();
3706 if (__mb == 0)
3707 __throw_bad_alloc();
3708 }
3709 // format
3710 char_type* __mi;
3711 char_type* __me;
3712 this->__format(__mb, __mi, __me, __iob.flags(),
3713 __digits.data(), __digits.data() + __digits.size(), __ct,
3714 __neg, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3715 return __pad_and_output(__s, __mb, __mi, __me, __iob, __fl);
3716}
3717
Howard Hinnantff926772012-11-06 21:08:48 +00003718_LIBCPP_EXTERN_TEMPLATE(class money_put<char>)
3719_LIBCPP_EXTERN_TEMPLATE(class money_put<wchar_t>)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003720
3721// messages
3722
Howard Hinnant82894812010-09-22 16:48:34 +00003723class _LIBCPP_VISIBLE messages_base
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003724{
3725public:
Howard Hinnantb2080c72011-02-25 00:51:08 +00003726 typedef ptrdiff_t catalog;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003727
3728 _LIBCPP_ALWAYS_INLINE messages_base() {}
3729};
3730
3731template <class _CharT>
Howard Hinnant82894812010-09-22 16:48:34 +00003732class _LIBCPP_VISIBLE messages
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003733 : public locale::facet,
3734 public messages_base
3735{
3736public:
3737 typedef _CharT char_type;
3738 typedef basic_string<_CharT> string_type;
3739
3740 _LIBCPP_ALWAYS_INLINE
3741 explicit messages(size_t __refs = 0)
3742 : locale::facet(__refs) {}
3743
3744 _LIBCPP_ALWAYS_INLINE
3745 catalog open(const basic_string<char>& __nm, const locale& __loc) const
3746 {
3747 return do_open(__nm, __loc);
3748 }
3749
3750 _LIBCPP_ALWAYS_INLINE
3751 string_type get(catalog __c, int __set, int __msgid,
3752 const string_type& __dflt) const
3753 {
3754 return do_get(__c, __set, __msgid, __dflt);
3755 }
3756
3757 _LIBCPP_ALWAYS_INLINE
3758 void close(catalog __c) const
3759 {
3760 do_close(__c);
3761 }
3762
3763 static locale::id id;
3764
3765protected:
Howard Hinnant82894812010-09-22 16:48:34 +00003766 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003767 ~messages() {}
3768
3769 virtual catalog do_open(const basic_string<char>&, const locale&) const;
3770 virtual string_type do_get(catalog, int __set, int __msgid,
3771 const string_type& __dflt) const;
3772 virtual void do_close(catalog) const;
3773};
3774
3775template <class _CharT>
3776locale::id
3777messages<_CharT>::id;
3778
3779template <class _CharT>
3780typename messages<_CharT>::catalog
3781messages<_CharT>::do_open(const basic_string<char>& __nm, const locale&) const
3782{
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00003783#if _WIN32
3784 return -1;
3785#else // _WIN32
Howard Hinnant11624452011-10-11 16:00:46 +00003786 catalog __cat = (catalog)catopen(__nm.c_str(), NL_CAT_LOCALE);
Howard Hinnantb2080c72011-02-25 00:51:08 +00003787 if (__cat != -1)
3788 __cat = static_cast<catalog>((static_cast<size_t>(__cat) >> 1));
3789 return __cat;
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00003790#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003791}
3792
3793template <class _CharT>
3794typename messages<_CharT>::string_type
3795messages<_CharT>::do_get(catalog __c, int __set, int __msgid,
3796 const string_type& __dflt) const
3797{
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00003798#if _WIN32
3799 return __dflt;
3800#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003801 string __ndflt;
3802 __narrow_to_utf8<sizeof(char_type)*__CHAR_BIT__>()(back_inserter(__ndflt),
3803 __dflt.c_str(),
3804 __dflt.c_str() + __dflt.size());
Howard Hinnantb2080c72011-02-25 00:51:08 +00003805 if (__c != -1)
3806 __c <<= 1;
Howard Hinnant11624452011-10-11 16:00:46 +00003807 nl_catd __cat = (nl_catd)__c;
Howard Hinnantb2080c72011-02-25 00:51:08 +00003808 char* __n = catgets(__cat, __set, __msgid, __ndflt.c_str());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003809 string_type __w;
3810 __widen_from_utf8<sizeof(char_type)*__CHAR_BIT__>()(back_inserter(__w),
3811 __n, __n + strlen(__n));
3812 return __w;
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00003813#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003814}
3815
3816template <class _CharT>
3817void
3818messages<_CharT>::do_close(catalog __c) const
3819{
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00003820#if !_WIN32
Howard Hinnantb2080c72011-02-25 00:51:08 +00003821 if (__c != -1)
3822 __c <<= 1;
Howard Hinnant11624452011-10-11 16:00:46 +00003823 nl_catd __cat = (nl_catd)__c;
Howard Hinnantb2080c72011-02-25 00:51:08 +00003824 catclose(__cat);
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00003825#endif // !_WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003826}
3827
Howard Hinnantff926772012-11-06 21:08:48 +00003828_LIBCPP_EXTERN_TEMPLATE(class messages<char>)
3829_LIBCPP_EXTERN_TEMPLATE(class messages<wchar_t>)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003830
3831template <class _CharT>
Howard Hinnant82894812010-09-22 16:48:34 +00003832class _LIBCPP_VISIBLE messages_byname
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003833 : public messages<_CharT>
3834{
3835public:
3836 typedef messages_base::catalog catalog;
3837 typedef basic_string<_CharT> string_type;
3838
3839 _LIBCPP_ALWAYS_INLINE
3840 explicit messages_byname(const char*, size_t __refs = 0)
3841 : messages<_CharT>(__refs) {}
3842
3843 _LIBCPP_ALWAYS_INLINE
3844 explicit messages_byname(const string&, size_t __refs = 0)
3845 : messages<_CharT>(__refs) {}
3846
3847protected:
Howard Hinnant82894812010-09-22 16:48:34 +00003848 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003849 ~messages_byname() {}
3850};
3851
Howard Hinnantff926772012-11-06 21:08:48 +00003852_LIBCPP_EXTERN_TEMPLATE(class messages_byname<char>)
3853_LIBCPP_EXTERN_TEMPLATE(class messages_byname<wchar_t>)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003854
Howard Hinnantd23b4642010-05-31 20:58:54 +00003855template<class _Codecvt, class _Elem = wchar_t,
3856 class _Wide_alloc = allocator<_Elem>,
3857 class _Byte_alloc = allocator<char> >
Howard Hinnant82894812010-09-22 16:48:34 +00003858class _LIBCPP_VISIBLE wstring_convert
Howard Hinnantd23b4642010-05-31 20:58:54 +00003859{
3860public:
3861 typedef basic_string<char, char_traits<char>, _Byte_alloc> byte_string;
3862 typedef basic_string<_Elem, char_traits<_Elem>, _Wide_alloc> wide_string;
3863 typedef typename _Codecvt::state_type state_type;
3864 typedef typename wide_string::traits_type::int_type int_type;
3865
3866private:
3867 byte_string __byte_err_string_;
3868 wide_string __wide_err_string_;
3869 _Codecvt* __cvtptr_;
3870 state_type __cvtstate_;
3871 size_t __cvtcount_;
3872
3873 wstring_convert(const wstring_convert& __wc);
3874 wstring_convert& operator=(const wstring_convert& __wc);
3875public:
3876 wstring_convert(_Codecvt* __pcvt = new _Codecvt);
3877 wstring_convert(_Codecvt* __pcvt, state_type __state);
3878 wstring_convert(const byte_string& __byte_err,
3879 const wide_string& __wide_err = wide_string());
Howard Hinnant73d21a42010-09-04 23:28:19 +00003880#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantd23b4642010-05-31 20:58:54 +00003881 wstring_convert(wstring_convert&& __wc);
3882#endif
3883 ~wstring_convert();
3884
Howard Hinnant82894812010-09-22 16:48:34 +00003885 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003886 wide_string from_bytes(char __byte)
3887 {return from_bytes(&__byte, &__byte+1);}
Howard Hinnant82894812010-09-22 16:48:34 +00003888 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003889 wide_string from_bytes(const char* __ptr)
3890 {return from_bytes(__ptr, __ptr + char_traits<char>::length(__ptr));}
Howard Hinnant82894812010-09-22 16:48:34 +00003891 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003892 wide_string from_bytes(const byte_string& __str)
3893 {return from_bytes(__str.data(), __str.data() + __str.size());}
3894 wide_string from_bytes(const char* __first, const char* __last);
3895
Howard Hinnant82894812010-09-22 16:48:34 +00003896 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003897 byte_string to_bytes(_Elem __wchar)
3898 {return to_bytes(&__wchar, &__wchar+1);}
Howard Hinnant82894812010-09-22 16:48:34 +00003899 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003900 byte_string to_bytes(const _Elem* __wptr)
3901 {return to_bytes(__wptr, __wptr + char_traits<_Elem>::length(__wptr));}
Howard Hinnant82894812010-09-22 16:48:34 +00003902 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003903 byte_string to_bytes(const wide_string& __wstr)
3904 {return to_bytes(__wstr.data(), __wstr.data() + __wstr.size());}
3905 byte_string to_bytes(const _Elem* __first, const _Elem* __last);
3906
Howard Hinnant82894812010-09-22 16:48:34 +00003907 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003908 size_t converted() const {return __cvtcount_;}
Howard Hinnant82894812010-09-22 16:48:34 +00003909 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003910 state_type state() const {return __cvtstate_;}
3911};
3912
3913template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Howard Hinnant82894812010-09-22 16:48:34 +00003914inline _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003915wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3916 wstring_convert(_Codecvt* __pcvt)
3917 : __cvtptr_(__pcvt), __cvtstate_(), __cvtcount_(0)
3918{
3919}
3920
3921template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Howard Hinnant82894812010-09-22 16:48:34 +00003922inline _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003923wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3924 wstring_convert(_Codecvt* __pcvt, state_type __state)
3925 : __cvtptr_(__pcvt), __cvtstate_(__state), __cvtcount_(0)
3926{
3927}
3928
3929template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3930wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3931 wstring_convert(const byte_string& __byte_err, const wide_string& __wide_err)
3932 : __byte_err_string_(__byte_err), __wide_err_string_(__wide_err),
3933 __cvtstate_(), __cvtcount_(0)
3934{
3935 __cvtptr_ = new _Codecvt;
3936}
3937
Howard Hinnant73d21a42010-09-04 23:28:19 +00003938#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantd23b4642010-05-31 20:58:54 +00003939
3940template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Howard Hinnant82894812010-09-22 16:48:34 +00003941inline _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003942wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3943 wstring_convert(wstring_convert&& __wc)
Howard Hinnant0949eed2011-06-30 21:18:19 +00003944 : __byte_err_string_(_VSTD::move(__wc.__byte_err_string_)),
3945 __wide_err_string_(_VSTD::move(__wc.__wide_err_string_)),
Howard Hinnantd23b4642010-05-31 20:58:54 +00003946 __cvtptr_(__wc.__cvtptr_),
3947 __cvtstate_(__wc.__cvtstate_), __cvtcount_(__wc.__cvtstate_)
3948{
3949 __wc.__cvtptr_ = nullptr;
3950}
3951
Howard Hinnantbfd55302010-09-04 23:46:48 +00003952#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantd23b4642010-05-31 20:58:54 +00003953
3954template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3955wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::~wstring_convert()
3956{
3957 delete __cvtptr_;
3958}
3959
3960template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3961typename wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::wide_string
3962wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3963 from_bytes(const char* __frm, const char* __frm_end)
3964{
3965 __cvtcount_ = 0;
3966 if (__cvtptr_ != nullptr)
3967 {
3968 wide_string __ws(2*(__frm_end - __frm), _Elem());
Howard Hinnant1ca23672012-07-12 18:07:41 +00003969 if (__frm != __frm_end)
3970 __ws.resize(__ws.capacity());
Howard Hinnantd23b4642010-05-31 20:58:54 +00003971 codecvt_base::result __r = codecvt_base::ok;
3972 state_type __st = __cvtstate_;
3973 if (__frm != __frm_end)
3974 {
3975 _Elem* __to = &__ws[0];
3976 _Elem* __to_end = __to + __ws.size();
3977 const char* __frm_nxt;
3978 do
3979 {
3980 _Elem* __to_nxt;
3981 __r = __cvtptr_->in(__st, __frm, __frm_end, __frm_nxt,
3982 __to, __to_end, __to_nxt);
3983 __cvtcount_ += __frm_nxt - __frm;
3984 if (__frm_nxt == __frm)
3985 {
3986 __r = codecvt_base::error;
3987 }
3988 else if (__r == codecvt_base::noconv)
3989 {
3990 __ws.resize(__to - &__ws[0]);
3991 // This only gets executed if _Elem is char
3992 __ws.append((const _Elem*)__frm, (const _Elem*)__frm_end);
3993 __frm = __frm_nxt;
3994 __r = codecvt_base::ok;
3995 }
3996 else if (__r == codecvt_base::ok)
3997 {
3998 __ws.resize(__to_nxt - &__ws[0]);
3999 __frm = __frm_nxt;
4000 }
4001 else if (__r == codecvt_base::partial)
4002 {
4003 ptrdiff_t __s = __to_nxt - &__ws[0];
4004 __ws.resize(2 * __s);
4005 __to = &__ws[0] + __s;
4006 __to_end = &__ws[0] + __ws.size();
4007 __frm = __frm_nxt;
4008 }
4009 } while (__r == codecvt_base::partial && __frm_nxt < __frm_end);
4010 }
4011 if (__r == codecvt_base::ok)
4012 return __ws;
4013 }
Howard Hinnantd4444702010-08-11 17:04:31 +00004014#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00004015 if (__wide_err_string_.empty())
4016 throw range_error("wstring_convert: from_bytes error");
Howard Hinnant324bb032010-08-22 00:02:43 +00004017#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00004018 return __wide_err_string_;
4019}
4020
4021template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
4022typename wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::byte_string
4023wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
4024 to_bytes(const _Elem* __frm, const _Elem* __frm_end)
4025{
4026 __cvtcount_ = 0;
4027 if (__cvtptr_ != nullptr)
4028 {
4029 byte_string __bs(2*(__frm_end - __frm), char());
Howard Hinnant1ca23672012-07-12 18:07:41 +00004030 if (__frm != __frm_end)
4031 __bs.resize(__bs.capacity());
Howard Hinnantd23b4642010-05-31 20:58:54 +00004032 codecvt_base::result __r = codecvt_base::ok;
4033 state_type __st = __cvtstate_;
4034 if (__frm != __frm_end)
4035 {
4036 char* __to = &__bs[0];
4037 char* __to_end = __to + __bs.size();
4038 const _Elem* __frm_nxt;
4039 do
4040 {
4041 char* __to_nxt;
4042 __r = __cvtptr_->out(__st, __frm, __frm_end, __frm_nxt,
4043 __to, __to_end, __to_nxt);
4044 __cvtcount_ += __frm_nxt - __frm;
4045 if (__frm_nxt == __frm)
4046 {
4047 __r = codecvt_base::error;
4048 }
4049 else if (__r == codecvt_base::noconv)
4050 {
4051 __bs.resize(__to - &__bs[0]);
4052 // This only gets executed if _Elem is char
4053 __bs.append((const char*)__frm, (const char*)__frm_end);
4054 __frm = __frm_nxt;
4055 __r = codecvt_base::ok;
4056 }
4057 else if (__r == codecvt_base::ok)
4058 {
4059 __bs.resize(__to_nxt - &__bs[0]);
4060 __frm = __frm_nxt;
4061 }
4062 else if (__r == codecvt_base::partial)
4063 {
4064 ptrdiff_t __s = __to_nxt - &__bs[0];
4065 __bs.resize(2 * __s);
4066 __to = &__bs[0] + __s;
4067 __to_end = &__bs[0] + __bs.size();
4068 __frm = __frm_nxt;
4069 }
4070 } while (__r == codecvt_base::partial && __frm_nxt < __frm_end);
4071 }
4072 if (__r == codecvt_base::ok)
4073 {
4074 size_t __s = __bs.size();
4075 __bs.resize(__bs.capacity());
4076 char* __to = &__bs[0] + __s;
4077 char* __to_end = __to + __bs.size();
4078 do
4079 {
4080 char* __to_nxt;
4081 __r = __cvtptr_->unshift(__st, __to, __to_end, __to_nxt);
4082 if (__r == codecvt_base::noconv)
4083 {
4084 __bs.resize(__to - &__bs[0]);
4085 __r = codecvt_base::ok;
4086 }
4087 else if (__r == codecvt_base::ok)
4088 {
4089 __bs.resize(__to_nxt - &__bs[0]);
4090 }
4091 else if (__r == codecvt_base::partial)
4092 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00004093 ptrdiff_t __sp = __to_nxt - &__bs[0];
4094 __bs.resize(2 * __sp);
4095 __to = &__bs[0] + __sp;
Howard Hinnantd23b4642010-05-31 20:58:54 +00004096 __to_end = &__bs[0] + __bs.size();
4097 }
4098 } while (__r == codecvt_base::partial);
4099 if (__r == codecvt_base::ok)
4100 return __bs;
4101 }
4102 }
Howard Hinnantd4444702010-08-11 17:04:31 +00004103#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00004104 if (__byte_err_string_.empty())
4105 throw range_error("wstring_convert: to_bytes error");
Howard Hinnant324bb032010-08-22 00:02:43 +00004106#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00004107 return __byte_err_string_;
4108}
4109
4110template <class _Codecvt, class _Elem = wchar_t, class _Tr = char_traits<_Elem> >
Howard Hinnant82894812010-09-22 16:48:34 +00004111class _LIBCPP_VISIBLE wbuffer_convert
Howard Hinnantd23b4642010-05-31 20:58:54 +00004112 : public basic_streambuf<_Elem, _Tr>
4113{
4114public:
4115 // types:
4116 typedef _Elem char_type;
4117 typedef _Tr traits_type;
4118 typedef typename traits_type::int_type int_type;
4119 typedef typename traits_type::pos_type pos_type;
4120 typedef typename traits_type::off_type off_type;
4121 typedef typename _Codecvt::state_type state_type;
4122
4123private:
Howard Hinnant4b53f502010-06-01 20:09:18 +00004124 char* __extbuf_;
4125 const char* __extbufnext_;
4126 const char* __extbufend_;
4127 char __extbuf_min_[8];
4128 size_t __ebs_;
4129 char_type* __intbuf_;
4130 size_t __ibs_;
Howard Hinnantd23b4642010-05-31 20:58:54 +00004131 streambuf* __bufptr_;
Howard Hinnant4b53f502010-06-01 20:09:18 +00004132 _Codecvt* __cv_;
4133 state_type __st_;
4134 ios_base::openmode __cm_;
4135 bool __owns_eb_;
4136 bool __owns_ib_;
4137 bool __always_noconv_;
Howard Hinnantd23b4642010-05-31 20:58:54 +00004138
Howard Hinnant4b53f502010-06-01 20:09:18 +00004139 wbuffer_convert(const wbuffer_convert&);
4140 wbuffer_convert& operator=(const wbuffer_convert&);
Howard Hinnantd23b4642010-05-31 20:58:54 +00004141public:
4142 wbuffer_convert(streambuf* __bytebuf = 0, _Codecvt* __pcvt = new _Codecvt,
Howard Hinnant4b53f502010-06-01 20:09:18 +00004143 state_type __state = state_type());
4144 ~wbuffer_convert();
Howard Hinnantd23b4642010-05-31 20:58:54 +00004145
Howard Hinnant82894812010-09-22 16:48:34 +00004146 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantd23b4642010-05-31 20:58:54 +00004147 streambuf* rdbuf() const {return __bufptr_;}
Howard Hinnant82894812010-09-22 16:48:34 +00004148 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantd23b4642010-05-31 20:58:54 +00004149 streambuf* rdbuf(streambuf* __bytebuf)
4150 {
4151 streambuf* __r = __bufptr_;
4152 __bufptr_ = __bytebuf;
4153 return __r;
4154 }
4155
Howard Hinnant82894812010-09-22 16:48:34 +00004156 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant4b53f502010-06-01 20:09:18 +00004157 state_type state() const {return __st_;}
Howard Hinnantd23b4642010-05-31 20:58:54 +00004158
4159protected:
Howard Hinnant4b53f502010-06-01 20:09:18 +00004160 virtual int_type underflow();
4161 virtual int_type pbackfail(int_type __c = traits_type::eof());
Howard Hinnantd23b4642010-05-31 20:58:54 +00004162 virtual int_type overflow (int_type __c = traits_type::eof());
Howard Hinnant4b53f502010-06-01 20:09:18 +00004163 virtual basic_streambuf<char_type, traits_type>* setbuf(char_type* __s,
4164 streamsize __n);
4165 virtual pos_type seekoff(off_type __off, ios_base::seekdir __way,
4166 ios_base::openmode __wch = ios_base::in | ios_base::out);
4167 virtual pos_type seekpos(pos_type __sp,
4168 ios_base::openmode __wch = ios_base::in | ios_base::out);
4169 virtual int sync();
4170
4171private:
4172 bool __read_mode();
4173 void __write_mode();
4174 wbuffer_convert* __close();
Howard Hinnantd23b4642010-05-31 20:58:54 +00004175};
4176
4177template <class _Codecvt, class _Elem, class _Tr>
Howard Hinnant4b53f502010-06-01 20:09:18 +00004178wbuffer_convert<_Codecvt, _Elem, _Tr>::
4179 wbuffer_convert(streambuf* __bytebuf, _Codecvt* __pcvt, state_type __state)
4180 : __extbuf_(0),
4181 __extbufnext_(0),
4182 __extbufend_(0),
4183 __ebs_(0),
4184 __intbuf_(0),
4185 __ibs_(0),
4186 __bufptr_(__bytebuf),
4187 __cv_(__pcvt),
4188 __st_(__state),
4189 __cm_(0),
4190 __owns_eb_(false),
4191 __owns_ib_(false),
4192 __always_noconv_(__cv_ ? __cv_->always_noconv() : false)
4193{
4194 setbuf(0, 4096);
4195}
4196
4197template <class _Codecvt, class _Elem, class _Tr>
4198wbuffer_convert<_Codecvt, _Elem, _Tr>::~wbuffer_convert()
4199{
4200 __close();
4201 delete __cv_;
4202 if (__owns_eb_)
4203 delete [] __extbuf_;
4204 if (__owns_ib_)
4205 delete [] __intbuf_;
4206}
4207
4208template <class _Codecvt, class _Elem, class _Tr>
4209typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
4210wbuffer_convert<_Codecvt, _Elem, _Tr>::underflow()
4211{
4212 if (__cv_ == 0 || __bufptr_ == 0)
4213 return traits_type::eof();
4214 bool __initial = __read_mode();
4215 char_type __1buf;
4216 if (this->gptr() == 0)
4217 this->setg(&__1buf, &__1buf+1, &__1buf+1);
4218 const size_t __unget_sz = __initial ? 0 : min<size_t>((this->egptr() - this->eback()) / 2, 4);
4219 int_type __c = traits_type::eof();
4220 if (this->gptr() == this->egptr())
4221 {
4222 memmove(this->eback(), this->egptr() - __unget_sz, __unget_sz * sizeof(char_type));
4223 if (__always_noconv_)
4224 {
4225 streamsize __nmemb = static_cast<streamsize>(this->egptr() - this->eback() - __unget_sz);
4226 __nmemb = __bufptr_->sgetn((char*)this->eback() + __unget_sz, __nmemb);
4227 if (__nmemb != 0)
4228 {
4229 this->setg(this->eback(),
4230 this->eback() + __unget_sz,
4231 this->eback() + __unget_sz + __nmemb);
4232 __c = *this->gptr();
4233 }
4234 }
4235 else
4236 {
4237 memmove(__extbuf_, __extbufnext_, __extbufend_ - __extbufnext_);
4238 __extbufnext_ = __extbuf_ + (__extbufend_ - __extbufnext_);
4239 __extbufend_ = __extbuf_ + (__extbuf_ == __extbuf_min_ ? sizeof(__extbuf_min_) : __ebs_);
Howard Hinnant0949eed2011-06-30 21:18:19 +00004240 streamsize __nmemb = _VSTD::min(static_cast<streamsize>(this->egptr() - this->eback() - __unget_sz),
Howard Hinnant4b53f502010-06-01 20:09:18 +00004241 static_cast<streamsize>(__extbufend_ - __extbufnext_));
4242 codecvt_base::result __r;
4243 state_type __svs = __st_;
4244 streamsize __nr = __bufptr_->sgetn(const_cast<char*>(__extbufnext_), __nmemb);
4245 if (__nr != 0)
4246 {
4247 __extbufend_ = __extbufnext_ + __nr;
4248 char_type* __inext;
4249 __r = __cv_->in(__st_, __extbuf_, __extbufend_, __extbufnext_,
4250 this->eback() + __unget_sz,
4251 this->egptr(), __inext);
4252 if (__r == codecvt_base::noconv)
4253 {
4254 this->setg((char_type*)__extbuf_, (char_type*)__extbuf_, (char_type*)__extbufend_);
4255 __c = *this->gptr();
4256 }
4257 else if (__inext != this->eback() + __unget_sz)
4258 {
4259 this->setg(this->eback(), this->eback() + __unget_sz, __inext);
4260 __c = *this->gptr();
4261 }
4262 }
4263 }
4264 }
4265 else
4266 __c = *this->gptr();
4267 if (this->eback() == &__1buf)
4268 this->setg(0, 0, 0);
4269 return __c;
4270}
4271
4272template <class _Codecvt, class _Elem, class _Tr>
4273typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
4274wbuffer_convert<_Codecvt, _Elem, _Tr>::pbackfail(int_type __c)
4275{
4276 if (__cv_ != 0 && __bufptr_ != 0 && this->eback() < this->gptr())
4277 {
4278 if (traits_type::eq_int_type(__c, traits_type::eof()))
4279 {
4280 this->gbump(-1);
4281 return traits_type::not_eof(__c);
4282 }
4283 if (traits_type::eq(traits_type::to_char_type(__c), this->gptr()[-1]))
4284 {
4285 this->gbump(-1);
4286 *this->gptr() = traits_type::to_char_type(__c);
4287 return __c;
4288 }
4289 }
4290 return traits_type::eof();
4291}
4292
4293template <class _Codecvt, class _Elem, class _Tr>
Howard Hinnantd23b4642010-05-31 20:58:54 +00004294typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
4295wbuffer_convert<_Codecvt, _Elem, _Tr>::overflow(int_type __c)
4296{
Howard Hinnant4b53f502010-06-01 20:09:18 +00004297 if (__cv_ == 0 || __bufptr_ == 0)
4298 return traits_type::eof();
4299 __write_mode();
4300 char_type __1buf;
4301 char_type* __pb_save = this->pbase();
4302 char_type* __epb_save = this->epptr();
4303 if (!traits_type::eq_int_type(__c, traits_type::eof()))
4304 {
4305 if (this->pptr() == 0)
4306 this->setp(&__1buf, &__1buf+1);
4307 *this->pptr() = traits_type::to_char_type(__c);
4308 this->pbump(1);
4309 }
4310 if (this->pptr() != this->pbase())
4311 {
4312 if (__always_noconv_)
4313 {
4314 streamsize __nmemb = static_cast<streamsize>(this->pptr() - this->pbase());
4315 if (__bufptr_->sputn((const char*)this->pbase(), __nmemb) != __nmemb)
4316 return traits_type::eof();
4317 }
4318 else
4319 {
4320 char* __extbe = __extbuf_;
4321 codecvt_base::result __r;
4322 do
4323 {
4324 const char_type* __e;
4325 __r = __cv_->out(__st_, this->pbase(), this->pptr(), __e,
4326 __extbuf_, __extbuf_ + __ebs_, __extbe);
4327 if (__e == this->pbase())
4328 return traits_type::eof();
4329 if (__r == codecvt_base::noconv)
4330 {
4331 streamsize __nmemb = static_cast<size_t>(this->pptr() - this->pbase());
4332 if (__bufptr_->sputn((const char*)this->pbase(), __nmemb) != __nmemb)
4333 return traits_type::eof();
4334 }
4335 else if (__r == codecvt_base::ok || __r == codecvt_base::partial)
4336 {
4337 streamsize __nmemb = static_cast<size_t>(__extbe - __extbuf_);
4338 if (__bufptr_->sputn(__extbuf_, __nmemb) != __nmemb)
4339 return traits_type::eof();
4340 if (__r == codecvt_base::partial)
4341 {
4342 this->setp((char_type*)__e, this->pptr());
4343 this->pbump(this->epptr() - this->pbase());
4344 }
4345 }
4346 else
4347 return traits_type::eof();
4348 } while (__r == codecvt_base::partial);
4349 }
4350 this->setp(__pb_save, __epb_save);
4351 }
4352 return traits_type::not_eof(__c);
4353}
4354
4355template <class _Codecvt, class _Elem, class _Tr>
4356basic_streambuf<_Elem, _Tr>*
4357wbuffer_convert<_Codecvt, _Elem, _Tr>::setbuf(char_type* __s, streamsize __n)
4358{
4359 this->setg(0, 0, 0);
4360 this->setp(0, 0);
4361 if (__owns_eb_)
4362 delete [] __extbuf_;
4363 if (__owns_ib_)
4364 delete [] __intbuf_;
4365 __ebs_ = __n;
4366 if (__ebs_ > sizeof(__extbuf_min_))
4367 {
4368 if (__always_noconv_ && __s)
4369 {
4370 __extbuf_ = (char*)__s;
4371 __owns_eb_ = false;
4372 }
4373 else
4374 {
4375 __extbuf_ = new char[__ebs_];
4376 __owns_eb_ = true;
4377 }
4378 }
4379 else
4380 {
4381 __extbuf_ = __extbuf_min_;
4382 __ebs_ = sizeof(__extbuf_min_);
4383 __owns_eb_ = false;
4384 }
4385 if (!__always_noconv_)
4386 {
4387 __ibs_ = max<streamsize>(__n, sizeof(__extbuf_min_));
4388 if (__s && __ibs_ >= sizeof(__extbuf_min_))
4389 {
4390 __intbuf_ = __s;
4391 __owns_ib_ = false;
4392 }
4393 else
4394 {
4395 __intbuf_ = new char_type[__ibs_];
4396 __owns_ib_ = true;
4397 }
4398 }
4399 else
4400 {
4401 __ibs_ = 0;
4402 __intbuf_ = 0;
4403 __owns_ib_ = false;
4404 }
4405 return this;
4406}
4407
4408template <class _Codecvt, class _Elem, class _Tr>
4409typename wbuffer_convert<_Codecvt, _Elem, _Tr>::pos_type
4410wbuffer_convert<_Codecvt, _Elem, _Tr>::seekoff(off_type __off, ios_base::seekdir __way,
4411 ios_base::openmode __om)
4412{
4413 int __width = __cv_->encoding();
4414 if (__cv_ == 0 || __bufptr_ == 0 || (__width <= 0 && __off != 0) || sync())
4415 return pos_type(off_type(-1));
4416 // __width > 0 || __off == 0
4417 switch (__way)
4418 {
4419 case ios_base::beg:
4420 break;
4421 case ios_base::cur:
4422 break;
4423 case ios_base::end:
4424 break;
4425 default:
4426 return pos_type(off_type(-1));
4427 }
4428 pos_type __r = __bufptr_->pubseekoff(__width * __off, __way, __om);
4429 __r.state(__st_);
4430 return __r;
4431}
4432
4433template <class _Codecvt, class _Elem, class _Tr>
4434typename wbuffer_convert<_Codecvt, _Elem, _Tr>::pos_type
4435wbuffer_convert<_Codecvt, _Elem, _Tr>::seekpos(pos_type __sp, ios_base::openmode __wch)
4436{
4437 if (__cv_ == 0 || __bufptr_ == 0 || sync())
4438 return pos_type(off_type(-1));
4439 if (__bufptr_->pubseekpos(__sp, __wch) == pos_type(off_type(-1)))
4440 return pos_type(off_type(-1));
4441 return __sp;
4442}
4443
4444template <class _Codecvt, class _Elem, class _Tr>
4445int
4446wbuffer_convert<_Codecvt, _Elem, _Tr>::sync()
4447{
4448 if (__cv_ == 0 || __bufptr_ == 0)
4449 return 0;
4450 if (__cm_ & ios_base::out)
4451 {
4452 if (this->pptr() != this->pbase())
4453 if (overflow() == traits_type::eof())
4454 return -1;
4455 codecvt_base::result __r;
4456 do
4457 {
4458 char* __extbe;
4459 __r = __cv_->unshift(__st_, __extbuf_, __extbuf_ + __ebs_, __extbe);
4460 streamsize __nmemb = static_cast<streamsize>(__extbe - __extbuf_);
4461 if (__bufptr_->sputn(__extbuf_, __nmemb) != __nmemb)
4462 return -1;
4463 } while (__r == codecvt_base::partial);
4464 if (__r == codecvt_base::error)
4465 return -1;
4466 if (__bufptr_->pubsync())
4467 return -1;
4468 }
4469 else if (__cm_ & ios_base::in)
4470 {
4471 off_type __c;
4472 if (__always_noconv_)
4473 __c = this->egptr() - this->gptr();
4474 else
4475 {
4476 int __width = __cv_->encoding();
4477 __c = __extbufend_ - __extbufnext_;
4478 if (__width > 0)
4479 __c += __width * (this->egptr() - this->gptr());
4480 else
4481 {
4482 if (this->gptr() != this->egptr())
4483 {
4484 reverse(this->gptr(), this->egptr());
4485 codecvt_base::result __r;
4486 const char_type* __e = this->gptr();
4487 char* __extbe;
4488 do
4489 {
4490 __r = __cv_->out(__st_, __e, this->egptr(), __e,
4491 __extbuf_, __extbuf_ + __ebs_, __extbe);
4492 switch (__r)
4493 {
4494 case codecvt_base::noconv:
4495 __c += this->egptr() - this->gptr();
4496 break;
4497 case codecvt_base::ok:
4498 case codecvt_base::partial:
4499 __c += __extbe - __extbuf_;
4500 break;
4501 default:
4502 return -1;
4503 }
4504 } while (__r == codecvt_base::partial);
4505 }
4506 }
4507 }
4508 if (__bufptr_->pubseekoff(-__c, ios_base::cur, __cm_) == pos_type(off_type(-1)))
4509 return -1;
4510 this->setg(0, 0, 0);
4511 __cm_ = 0;
4512 }
4513 return 0;
4514}
4515
4516template <class _Codecvt, class _Elem, class _Tr>
4517bool
4518wbuffer_convert<_Codecvt, _Elem, _Tr>::__read_mode()
4519{
4520 if (!(__cm_ & ios_base::in))
4521 {
4522 this->setp(0, 0);
4523 if (__always_noconv_)
4524 this->setg((char_type*)__extbuf_,
4525 (char_type*)__extbuf_ + __ebs_,
4526 (char_type*)__extbuf_ + __ebs_);
4527 else
4528 this->setg(__intbuf_, __intbuf_ + __ibs_, __intbuf_ + __ibs_);
4529 __cm_ = ios_base::in;
4530 return true;
4531 }
4532 return false;
4533}
4534
4535template <class _Codecvt, class _Elem, class _Tr>
4536void
4537wbuffer_convert<_Codecvt, _Elem, _Tr>::__write_mode()
4538{
4539 if (!(__cm_ & ios_base::out))
4540 {
4541 this->setg(0, 0, 0);
4542 if (__ebs_ > sizeof(__extbuf_min_))
4543 {
4544 if (__always_noconv_)
4545 this->setp((char_type*)__extbuf_,
4546 (char_type*)__extbuf_ + (__ebs_ - 1));
4547 else
4548 this->setp(__intbuf_, __intbuf_ + (__ibs_ - 1));
4549 }
4550 else
4551 this->setp(0, 0);
4552 __cm_ = ios_base::out;
4553 }
4554}
4555
4556template <class _Codecvt, class _Elem, class _Tr>
4557wbuffer_convert<_Codecvt, _Elem, _Tr>*
4558wbuffer_convert<_Codecvt, _Elem, _Tr>::__close()
4559{
4560 wbuffer_convert* __rt = 0;
4561 if (__cv_ != 0 && __bufptr_ != 0)
4562 {
4563 __rt = this;
4564 if ((__cm_ & ios_base::out) && sync())
4565 __rt = 0;
4566 }
4567 return __rt;
Howard Hinnantd23b4642010-05-31 20:58:54 +00004568}
4569
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004570_LIBCPP_END_NAMESPACE_STD
4571
4572#endif // _LIBCPP_LOCALE