blob: f04a36b43990bbe3e7254570ebe99ac279856ae3 [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 Hinnant537b2fa2012-11-14 21:17:15 +0000195#if __APPLE__
196#include <Availability.h>
197#endif
198
Howard Hinnant66c6f972011-11-29 16:45:27 +0000199#include <__undef_min_max>
200
Howard Hinnant08e17472011-10-17 20:05:10 +0000201#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000202#pragma GCC system_header
Howard Hinnant08e17472011-10-17 20:05:10 +0000203#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000204
205_LIBCPP_BEGIN_NAMESPACE_STD
206
Howard Hinnant866569b2011-09-28 23:39:33 +0000207#if __APPLE__ || __FreeBSD__
Howard Hinnant2ea1ca92011-09-28 21:05:01 +0000208# define _LIBCPP_GET_C_LOCALE 0
209#else
210# define _LIBCPP_GET_C_LOCALE __cloc()
Howard Hinnant866569b2011-09-28 23:39:33 +0000211 // Get the C locale object
212 locale_t __cloc();
213#define __cloc_defined
Howard Hinnant2ea1ca92011-09-28 21:05:01 +0000214#endif
215
Sean Huntf3907e62011-07-15 05:40:33 +0000216typedef _VSTD::remove_pointer<locale_t>::type __locale_struct;
217typedef _VSTD::unique_ptr<__locale_struct, decltype(&freelocale)> __locale_unique_ptr;
David Chisnall8fa14e92012-02-29 13:00:07 +0000218#ifndef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +0000219typedef _VSTD::unique_ptr<__locale_struct, decltype(&uselocale)> __locale_raii;
David Chisnall8fa14e92012-02-29 13:00:07 +0000220#endif
Sean Huntf3907e62011-07-15 05:40:33 +0000221
Howard Hinnantadff4892010-05-24 17:49:41 +0000222// OSX has nice foo_l() functions that let you turn off use of the global
223// locale. Linux, not so much. The following functions avoid the locale when
224// that's possible and otherwise do the wrong thing. FIXME.
Howard Hinnant866569b2011-09-28 23:39:33 +0000225#ifdef __linux__
Sean Huntf3907e62011-07-15 05:40:33 +0000226
227#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
228decltype(MB_CUR_MAX_L(_VSTD::declval<locale_t>()))
Howard Hinnant82894812010-09-22 16:48:34 +0000229inline _LIBCPP_INLINE_VISIBILITY
Sean Huntf3907e62011-07-15 05:40:33 +0000230__mb_cur_max_l(locale_t __l)
Howard Hinnantadff4892010-05-24 17:49:41 +0000231{
Sean Huntf3907e62011-07-15 05:40:33 +0000232 return MB_CUR_MAX_L(__l);
233}
234#else // _LIBCPP_LOCALE__L_EXTENSIONS
235_LIBCPP_ALWAYS_INLINE inline
236decltype(MB_CUR_MAX) __mb_cur_max_l(locale_t __l)
237{
238 __locale_raii __current(uselocale(__l), uselocale);
239 return MB_CUR_MAX;
240}
241#endif // _LIBCPP_LOCALE__L_EXTENSIONS
242
243_LIBCPP_ALWAYS_INLINE inline
244wint_t __btowc_l(int __c, locale_t __l)
245{
Howard Hinnant866569b2011-09-28 23:39:33 +0000246#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +0000247 return btowc_l(__c, __l);
248#else
249 __locale_raii __current(uselocale(__l), uselocale);
250 return btowc(__c);
251#endif
Sean Huntc97da3a2011-07-13 06:40:50 +0000252}
Howard Hinnant8d756322011-07-13 15:48:16 +0000253
Sean Huntf3907e62011-07-15 05:40:33 +0000254_LIBCPP_ALWAYS_INLINE inline
255int __wctob_l(wint_t __c, locale_t __l)
Sean Huntc97da3a2011-07-13 06:40:50 +0000256{
Sean Huntf3907e62011-07-15 05:40:33 +0000257#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
258 return wctob_l(__c, __l);
259#else
260 __locale_raii __current(uselocale(__l), uselocale);
261 return wctob(__c);
262#endif
Sean Huntc97da3a2011-07-13 06:40:50 +0000263}
Sean Huntf3907e62011-07-15 05:40:33 +0000264
265_LIBCPP_ALWAYS_INLINE inline
266size_t __wcsnrtombs_l(char *__dest, const wchar_t **__src, size_t __nwc,
267 size_t __len, mbstate_t *__ps, locale_t __l)
268{
269#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
270 return wcsnrtombs_l(__dest, __src, __nwc, __len, __ps, __l);
271#else
272 __locale_raii __current(uselocale(__l), uselocale);
273 return wcsnrtombs(__dest, __src, __nwc, __len, __ps);
274#endif
275}
276
277_LIBCPP_ALWAYS_INLINE inline
278size_t __wcrtomb_l(char *__s, wchar_t __wc, mbstate_t *__ps, locale_t __l)
279{
280#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
281 return wcrtomb_l(__s, __wc, __ps, __l);
282#else
283 __locale_raii __current(uselocale(__l), uselocale);
284 return wcrtomb(__s, __wc, __ps);
285#endif
286}
287
288_LIBCPP_ALWAYS_INLINE inline
289size_t __mbsnrtowcs_l(wchar_t * __dest, const char **__src, size_t __nms,
290 size_t __len, mbstate_t *__ps, locale_t __l)
291{
292#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
David Chisnallc512df12011-09-21 08:39:44 +0000293 return mbsnrtowcs_l(__dest, __src, __nms, __len, __ps, __l);
Sean Huntf3907e62011-07-15 05:40:33 +0000294#else
295 __locale_raii __current(uselocale(__l), uselocale);
296 return mbsnrtowcs(__dest, __src, __nms, __len, __ps);
297#endif
298}
299
300_LIBCPP_ALWAYS_INLINE inline
301size_t __mbrtowc_l(wchar_t *__pwc, const char *__s, size_t __n,
302 mbstate_t *__ps, locale_t __l)
303{
304#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
305 return mbrtowc_l(__pwc, __s, __n, __ps, __l);
306#else
307 __locale_raii __current(uselocale(__l), uselocale);
308 return mbrtowc(__pwc, __s, __n, __ps);
309#endif
310}
311
312_LIBCPP_ALWAYS_INLINE inline
313int __mbtowc_l(wchar_t *__pwc, const char *__pmb, size_t __max, locale_t __l)
314{
315#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
David Chisnallc512df12011-09-21 08:39:44 +0000316 return mbtowc_l(__pwc, __pmb, __max, __l);
Sean Huntf3907e62011-07-15 05:40:33 +0000317#else
318 __locale_raii __current(uselocale(__l), uselocale);
319 return mbtowc(__pwc, __pmb, __max);
320#endif
321}
322
323_LIBCPP_ALWAYS_INLINE inline
324size_t __mbrlen_l(const char *__s, size_t __n, mbstate_t *__ps, locale_t __l)
325{
326#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
327 return mbrlen_l(__s, __n, __ps, __l);
328#else
329 __locale_raii __current(uselocale(__l), uselocale);
330 return mbrlen(__s, __n, __ps);
331#endif
332}
333
334_LIBCPP_ALWAYS_INLINE inline
335lconv *__localeconv_l(locale_t __l)
336{
337#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
338 return localeconv_l(__l);
339#else
340 __locale_raii __current(uselocale(__l), uselocale);
341 return localeconv();
342#endif
343}
344
345_LIBCPP_ALWAYS_INLINE inline
346size_t __mbsrtowcs_l(wchar_t *__dest, const char **__src, size_t __len,
347 mbstate_t *__ps, locale_t __l)
348{
349#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
350 return mbsrtowcs_l(__dest, __src, __len, __ps, __l);
351#else
352 __locale_raii __current(uselocale(__l), uselocale);
353 return mbsrtowcs(__dest, __src, __len, __ps);
354#endif
355}
356
357_LIBCPP_ALWAYS_INLINE inline
358int __sprintf_l(char *__s, locale_t __l, const char *__format, ...) {
359 va_list __va;
360 va_start(__va, __format);
361#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
362 int __res = vsprintf_l(__s, __l, __format, __va);
363#else
364 __locale_raii __current(uselocale(__l), uselocale);
365 int __res = vsprintf(__s, __format, __va);
366#endif
367 va_end(__va);
368 return __res;
369}
370
371_LIBCPP_ALWAYS_INLINE inline
372int __snprintf_l(char *__s, size_t __n, locale_t __l, const char *__format, ...) {
373 va_list __va;
374 va_start(__va, __format);
375#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
376 int __res = vsnprintf_l(__s, __n, __l, __format, __va);
377#else
378 __locale_raii __current(uselocale(__l), uselocale);
379 int __res = vsnprintf(__s, __n, __format, __va);
380#endif
381 va_end(__va);
382 return __res;
383}
384
385_LIBCPP_ALWAYS_INLINE inline
386int __asprintf_l(char **__s, locale_t __l, const char *__format, ...) {
387 va_list __va;
388 va_start(__va, __format);
389#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
390 int __res = vasprintf_l(__s, __l, __format, __va);
391#else
392 __locale_raii __current(uselocale(__l), uselocale);
393 int __res = vasprintf(__s, __format, __va);
394#endif
395 va_end(__va);
396 return __res;
397}
398
399_LIBCPP_ALWAYS_INLINE inline
400int __sscanf_l(const char *__s, locale_t __l, const char *__format, ...) {
401 va_list __va;
402 va_start(__va, __format);
403#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
404 int __res = vsscanf_l(__s, __l, __format, __va);
405#else
406 __locale_raii __current(uselocale(__l), uselocale);
407 int __res = vsscanf(__s, __format, __va);
408#endif
409 va_end(__va);
410 return __res;
411}
412
Howard Hinnant866569b2011-09-28 23:39:33 +0000413#endif // __linux__
Howard Hinnantadff4892010-05-24 17:49:41 +0000414
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000415// __scan_keyword
416// Scans [__b, __e) until a match is found in the basic_strings range
417// [__kb, __ke) or until it can be shown that there is no match in [__kb, __ke).
418// __b will be incremented (visibly), consuming CharT until a match is found
419// or proved to not exist. A keyword may be "", in which will match anything.
420// If one keyword is a prefix of another, and the next CharT in the input
421// might match another keyword, the algorithm will attempt to find the longest
422// matching keyword. If the longer matching keyword ends up not matching, then
423// no keyword match is found. If no keyword match is found, __ke is returned
424// and failbit is set in __err.
425// Else an iterator pointing to the matching keyword is found. If more than
426// one keyword matches, an iterator to the first matching keyword is returned.
427// If on exit __b == __e, eofbit is set in __err. If __case_senstive is false,
428// __ct is used to force to lower case before comparing characters.
429// Examples:
430// Keywords: "a", "abb"
431// If the input is "a", the first keyword matches and eofbit is set.
432// If the input is "abc", no match is found and "ab" are consumed.
433template <class _InputIterator, class _ForwardIterator, class _Ctype>
434_LIBCPP_HIDDEN
435_ForwardIterator
436__scan_keyword(_InputIterator& __b, _InputIterator __e,
437 _ForwardIterator __kb, _ForwardIterator __ke,
438 const _Ctype& __ct, ios_base::iostate& __err,
439 bool __case_sensitive = true)
440{
441 typedef typename iterator_traits<_InputIterator>::value_type _CharT;
Howard Hinnantec3773c2011-12-01 20:21:04 +0000442 size_t __nkw = static_cast<size_t>(_VSTD::distance(__kb, __ke));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000443 const unsigned char __doesnt_match = '\0';
444 const unsigned char __might_match = '\1';
445 const unsigned char __does_match = '\2';
446 unsigned char __statbuf[100];
447 unsigned char* __status = __statbuf;
448 unique_ptr<unsigned char, void(*)(void*)> __stat_hold(0, free);
449 if (__nkw > sizeof(__statbuf))
450 {
451 __status = (unsigned char*)malloc(__nkw);
452 if (__status == 0)
453 __throw_bad_alloc();
454 __stat_hold.reset(__status);
455 }
456 size_t __n_might_match = __nkw; // At this point, any keyword might match
457 size_t __n_does_match = 0; // but none of them definitely do
458 // Initialize all statuses to __might_match, except for "" keywords are __does_match
459 unsigned char* __st = __status;
460 for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, ++__st)
461 {
462 if (!__ky->empty())
463 *__st = __might_match;
464 else
465 {
466 *__st = __does_match;
467 --__n_might_match;
468 ++__n_does_match;
469 }
470 }
471 // While there might be a match, test keywords against the next CharT
472 for (size_t __indx = 0; __b != __e && __n_might_match > 0; ++__indx)
473 {
474 // Peek at the next CharT but don't consume it
475 _CharT __c = *__b;
476 if (!__case_sensitive)
477 __c = __ct.toupper(__c);
478 bool __consume = false;
479 // For each keyword which might match, see if the __indx character is __c
480 // If a match if found, consume __c
481 // If a match is found, and that is the last character in the keyword,
482 // then that keyword matches.
483 // If the keyword doesn't match this character, then change the keyword
484 // to doesn't match
485 __st = __status;
486 for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, ++__st)
487 {
488 if (*__st == __might_match)
489 {
490 _CharT __kc = (*__ky)[__indx];
491 if (!__case_sensitive)
492 __kc = __ct.toupper(__kc);
493 if (__c == __kc)
494 {
495 __consume = true;
496 if (__ky->size() == __indx+1)
497 {
498 *__st = __does_match;
499 --__n_might_match;
500 ++__n_does_match;
501 }
502 }
503 else
504 {
505 *__st = __doesnt_match;
506 --__n_might_match;
507 }
508 }
509 }
510 // consume if we matched a character
511 if (__consume)
512 {
513 ++__b;
514 // If we consumed a character and there might be a matched keyword that
515 // was marked matched on a previous iteration, then such keywords
516 // which are now marked as not matching.
517 if (__n_might_match + __n_does_match > 1)
518 {
519 __st = __status;
520 for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, ++__st)
521 {
522 if (*__st == __does_match && __ky->size() != __indx+1)
523 {
524 *__st = __doesnt_match;
525 --__n_does_match;
526 }
527 }
528 }
529 }
530 }
531 // We've exited the loop because we hit eof and/or we have no more "might matches".
532 if (__b == __e)
533 __err |= ios_base::eofbit;
534 // Return the first matching result
535 for (__st = __status; __kb != __ke; ++__kb, ++__st)
536 if (*__st == __does_match)
537 break;
538 if (__kb == __ke)
539 __err |= ios_base::failbit;
540 return __kb;
541}
542
543struct __num_get_base
544{
545 static const int __num_get_buf_sz = 40;
546
547 static int __get_base(ios_base&);
548 static const char __src[33];
549};
550
551void __check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
552 ios_base::iostate& __err);
553
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000554template <class _CharT>
555struct __num_get
556 : protected __num_get_base
557{
558 static string __stage2_int_prep(ios_base& __iob, _CharT* __atoms, _CharT& __thousands_sep);
559 static string __stage2_float_prep(ios_base& __iob, _CharT* __atoms, _CharT& __decimal_point,
560 _CharT& __thousands_sep);
561 static int __stage2_int_loop(_CharT __ct, int __base, char* __a, char*& __a_end,
562 unsigned& __dc, _CharT __thousands_sep, const string& __grouping,
563 unsigned* __g, unsigned*& __g_end, _CharT* __atoms);
564 static int __stage2_float_loop(_CharT __ct, bool& __in_units, char& __exp,
565 char* __a, char*& __a_end,
566 _CharT __decimal_point, _CharT __thousands_sep,
567 const string& __grouping, unsigned* __g,
568 unsigned*& __g_end, unsigned& __dc, _CharT* __atoms);
569};
570
571template <class _CharT>
572string
573__num_get<_CharT>::__stage2_int_prep(ios_base& __iob, _CharT* __atoms, _CharT& __thousands_sep)
574{
575 locale __loc = __iob.getloc();
576 use_facet<ctype<_CharT> >(__loc).widen(__src, __src + 26, __atoms);
577 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
578 __thousands_sep = __np.thousands_sep();
579 return __np.grouping();
580}
581
582template <class _CharT>
583string
584__num_get<_CharT>::__stage2_float_prep(ios_base& __iob, _CharT* __atoms, _CharT& __decimal_point,
585 _CharT& __thousands_sep)
586{
587 locale __loc = __iob.getloc();
588 use_facet<ctype<_CharT> >(__loc).widen(__src, __src + 32, __atoms);
589 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
590 __decimal_point = __np.decimal_point();
591 __thousands_sep = __np.thousands_sep();
592 return __np.grouping();
593}
594
595template <class _CharT>
596int
597__num_get<_CharT>::__stage2_int_loop(_CharT __ct, int __base, char* __a, char*& __a_end,
598 unsigned& __dc, _CharT __thousands_sep, const string& __grouping,
599 unsigned* __g, unsigned*& __g_end, _CharT* __atoms)
600{
Howard Hinnant80586722011-03-09 01:03:19 +0000601 if (__a_end == __a && (__ct == __atoms[24] || __ct == __atoms[25]))
602 {
603 *__a_end++ = __ct == __atoms[24] ? '+' : '-';
604 __dc = 0;
605 return 0;
606 }
Howard Hinnantec3773c2011-12-01 20:21:04 +0000607 if (__grouping.size() != 0 && __ct == __thousands_sep)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000608 {
609 if (__g_end-__g < __num_get_buf_sz)
610 {
611 *__g_end++ = __dc;
612 __dc = 0;
613 }
614 return 0;
615 }
616 ptrdiff_t __f = find(__atoms, __atoms + 26, __ct) - __atoms;
Howard Hinnant80586722011-03-09 01:03:19 +0000617 if (__f >= 24)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000618 return -1;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000619 switch (__base)
620 {
621 case 8:
622 case 10:
623 if (__f >= __base)
Howard Hinnant80586722011-03-09 01:03:19 +0000624 return -1;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000625 break;
Howard Hinnant80586722011-03-09 01:03:19 +0000626 case 16:
627 if (__f < 22)
628 break;
629 if (__a_end != __a && __a_end - __a <= 2 && __a_end[-1] == '0')
630 {
631 __dc = 0;
632 *__a_end++ = __src[__f];
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000633 return 0;
Howard Hinnant80586722011-03-09 01:03:19 +0000634 }
635 return -1;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000636 }
Howard Hinnant80586722011-03-09 01:03:19 +0000637 if (__a_end-__a < __num_get_buf_sz - 1)
638 *__a_end++ = __src[__f];
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000639 ++__dc;
640 return 0;
641}
642
643template <class _CharT>
644int
645__num_get<_CharT>::__stage2_float_loop(_CharT __ct, bool& __in_units, char& __exp, char* __a, char*& __a_end,
646 _CharT __decimal_point, _CharT __thousands_sep, const string& __grouping,
647 unsigned* __g, unsigned*& __g_end, unsigned& __dc, _CharT* __atoms)
648{
649 if (__ct == __decimal_point)
650 {
651 if (!__in_units)
652 return -1;
653 __in_units = false;
654 *__a_end++ = '.';
655 if (__grouping.size() != 0 && __g_end-__g < __num_get_buf_sz)
656 *__g_end++ = __dc;
657 return 0;
658 }
659 if (__ct == __thousands_sep && __grouping.size() != 0)
660 {
661 if (!__in_units)
662 return -1;
663 if (__g_end-__g < __num_get_buf_sz)
664 {
665 *__g_end++ = __dc;
666 __dc = 0;
667 }
668 return 0;
669 }
670 ptrdiff_t __f = find(__atoms, __atoms + 32, __ct) - __atoms;
671 if (__f >= 32)
672 return -1;
673 char __x = __src[__f];
Howard Hinnantb04ad412012-02-15 19:19:37 +0000674 if (__x == '-' || __x == '+')
675 {
676 if (__a_end == __a || (__a_end[-1] & 0xDF) == __exp)
677 {
678 *__a_end++ = __x;
679 return 0;
680 }
681 return -1;
682 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000683 if (__a_end-__a < __num_get_buf_sz - 1)
684 *__a_end++ = __x;
685 if (__x == 'x' || __x == 'X')
686 __exp = 'P';
687 else if ((__x & 0xDF) == __exp)
688 {
689 __in_units = false;
690 if (__grouping.size() != 0 && __g_end-__g < __num_get_buf_sz)
691 *__g_end++ = __dc;
692 }
693 if (__f >= 22)
694 return 0;
695 ++__dc;
696 return 0;
697}
698
Howard Hinnantff926772012-11-06 21:08:48 +0000699_LIBCPP_EXTERN_TEMPLATE(struct __num_get<char>)
700_LIBCPP_EXTERN_TEMPLATE(struct __num_get<wchar_t>)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000701
702template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +0000703class _LIBCPP_VISIBLE num_get
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000704 : public locale::facet,
705 private __num_get<_CharT>
706{
707public:
708 typedef _CharT char_type;
709 typedef _InputIterator iter_type;
710
711 _LIBCPP_ALWAYS_INLINE
712 explicit num_get(size_t __refs = 0)
713 : locale::facet(__refs) {}
714
715 _LIBCPP_ALWAYS_INLINE
716 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
717 ios_base::iostate& __err, bool& __v) const
718 {
719 return do_get(__b, __e, __iob, __err, __v);
720 }
721
722 _LIBCPP_ALWAYS_INLINE
723 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
724 ios_base::iostate& __err, long& __v) const
725 {
726 return do_get(__b, __e, __iob, __err, __v);
727 }
728
729 _LIBCPP_ALWAYS_INLINE
730 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
731 ios_base::iostate& __err, long long& __v) const
732 {
733 return do_get(__b, __e, __iob, __err, __v);
734 }
735
736 _LIBCPP_ALWAYS_INLINE
737 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
738 ios_base::iostate& __err, unsigned short& __v) const
739 {
740 return do_get(__b, __e, __iob, __err, __v);
741 }
742
743 _LIBCPP_ALWAYS_INLINE
744 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
745 ios_base::iostate& __err, unsigned int& __v) const
746 {
747 return do_get(__b, __e, __iob, __err, __v);
748 }
749
750 _LIBCPP_ALWAYS_INLINE
751 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
752 ios_base::iostate& __err, unsigned long& __v) const
753 {
754 return do_get(__b, __e, __iob, __err, __v);
755 }
756
757 _LIBCPP_ALWAYS_INLINE
758 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
759 ios_base::iostate& __err, unsigned long long& __v) const
760 {
761 return do_get(__b, __e, __iob, __err, __v);
762 }
763
764 _LIBCPP_ALWAYS_INLINE
765 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
766 ios_base::iostate& __err, float& __v) const
767 {
768 return do_get(__b, __e, __iob, __err, __v);
769 }
770
771 _LIBCPP_ALWAYS_INLINE
772 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
773 ios_base::iostate& __err, double& __v) const
774 {
775 return do_get(__b, __e, __iob, __err, __v);
776 }
777
778 _LIBCPP_ALWAYS_INLINE
779 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
780 ios_base::iostate& __err, long double& __v) const
781 {
782 return do_get(__b, __e, __iob, __err, __v);
783 }
784
785 _LIBCPP_ALWAYS_INLINE
786 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
787 ios_base::iostate& __err, void*& __v) const
788 {
789 return do_get(__b, __e, __iob, __err, __v);
790 }
791
792 static locale::id id;
793
794protected:
Howard Hinnant82894812010-09-22 16:48:34 +0000795 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000796 ~num_get() {}
797
798 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
799 ios_base::iostate& __err, bool& __v) const;
800 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
801 ios_base::iostate& __err, long& __v) const;
802 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
803 ios_base::iostate& __err, long long& __v) const;
804 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
805 ios_base::iostate& __err, unsigned short& __v) const;
806 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
807 ios_base::iostate& __err, unsigned int& __v) const;
808 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
809 ios_base::iostate& __err, unsigned long& __v) const;
810 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
811 ios_base::iostate& __err, unsigned long long& __v) const;
812 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
813 ios_base::iostate& __err, float& __v) const;
814 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
815 ios_base::iostate& __err, double& __v) const;
816 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
817 ios_base::iostate& __err, long double& __v) const;
818 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
819 ios_base::iostate& __err, void*& __v) const;
820};
821
822template <class _CharT, class _InputIterator>
823locale::id
824num_get<_CharT, _InputIterator>::id;
825
826template <class _Tp>
827_Tp
828__num_get_signed_integral(const char* __a, const char* __a_end,
829 ios_base::iostate& __err, int __base)
830{
831 if (__a != __a_end)
832 {
Howard Hinnante7c8da62011-02-25 19:52:41 +0000833 int __save_errno = errno;
834 errno = 0;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000835 char *__p2;
Howard Hinnant2ea1ca92011-09-28 21:05:01 +0000836 long long __ll = strtoll_l(__a, &__p2, __base, _LIBCPP_GET_C_LOCALE);
Howard Hinnante7c8da62011-02-25 19:52:41 +0000837 int __current_errno = errno;
838 if (__current_errno == 0)
839 errno = __save_errno;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000840 if (__p2 != __a_end)
841 {
842 __err = ios_base::failbit;
843 return 0;
844 }
Howard Hinnante7c8da62011-02-25 19:52:41 +0000845 else if (__current_errno == ERANGE ||
846 __ll < numeric_limits<_Tp>::min() ||
847 numeric_limits<_Tp>::max() < __ll)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000848 {
849 __err = ios_base::failbit;
Howard Hinnante7c8da62011-02-25 19:52:41 +0000850 if (__ll > 0)
851 return numeric_limits<_Tp>::max();
852 else
853 return numeric_limits<_Tp>::min();
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000854 }
855 return static_cast<_Tp>(__ll);
856 }
857 __err = ios_base::failbit;
858 return 0;
859}
860
861template <class _Tp>
862_Tp
863__num_get_unsigned_integral(const char* __a, const char* __a_end,
864 ios_base::iostate& __err, int __base)
865{
866 if (__a != __a_end)
867 {
Howard Hinnante7c8da62011-02-25 19:52:41 +0000868 if (*__a == '-')
869 {
870 __err = ios_base::failbit;
871 return 0;
872 }
873 int __save_errno = errno;
874 errno = 0;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000875 char *__p2;
Howard Hinnant2ea1ca92011-09-28 21:05:01 +0000876 unsigned long long __ll = strtoull_l(__a, &__p2, __base, _LIBCPP_GET_C_LOCALE);
Howard Hinnante7c8da62011-02-25 19:52:41 +0000877 int __current_errno = errno;
878 if (__current_errno == 0)
879 errno = __save_errno;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000880 if (__p2 != __a_end)
881 {
882 __err = ios_base::failbit;
883 return 0;
884 }
Howard Hinnante7c8da62011-02-25 19:52:41 +0000885 else if (__current_errno == ERANGE ||
886 numeric_limits<_Tp>::max() < __ll)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000887 {
888 __err = ios_base::failbit;
889 return numeric_limits<_Tp>::max();
890 }
891 return static_cast<_Tp>(__ll);
892 }
893 __err = ios_base::failbit;
894 return 0;
895}
896
897template <class _Tp>
898_Tp
899__num_get_float(const char* __a, const char* __a_end, ios_base::iostate& __err)
900{
901 if (__a != __a_end)
902 {
903 char *__p2;
Howard Hinnant2ea1ca92011-09-28 21:05:01 +0000904 long double __ld = strtold_l(__a, &__p2, _LIBCPP_GET_C_LOCALE);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000905 if (__p2 != __a_end)
906 {
907 __err = ios_base::failbit;
908 return 0;
909 }
910 return static_cast<_Tp>(__ld);
911 }
912 __err = ios_base::failbit;
913 return 0;
914}
915
916template <class _CharT, class _InputIterator>
917_InputIterator
918num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
919 ios_base& __iob,
920 ios_base::iostate& __err,
921 bool& __v) const
922{
923 if ((__iob.flags() & ios_base::boolalpha) == 0)
924 {
925 long __lv = -1;
926 __b = do_get(__b, __e, __iob, __err, __lv);
927 switch (__lv)
928 {
929 case 0:
930 __v = false;
931 break;
932 case 1:
933 __v = true;
934 break;
935 default:
936 __v = true;
937 __err = ios_base::failbit;
938 break;
939 }
940 return __b;
941 }
942 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__iob.getloc());
943 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__iob.getloc());
944 typedef typename numpunct<_CharT>::string_type string_type;
945 const string_type __names[2] = {__np.truename(), __np.falsename()};
946 const string_type* __i = __scan_keyword(__b, __e, __names, __names+2,
947 __ct, __err);
948 __v = __i == __names;
949 return __b;
950}
951
952template <class _CharT, class _InputIterator>
953_InputIterator
954num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
955 ios_base& __iob,
956 ios_base::iostate& __err,
957 long& __v) const
958{
959 // Stage 1
960 int __base = this->__get_base(__iob);
961 // Stage 2
962 char_type __atoms[26];
963 char_type __thousands_sep;
964 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
965 char __a[__num_get_base::__num_get_buf_sz] = {0};
966 char* __a_end = __a;
967 unsigned __g[__num_get_base::__num_get_buf_sz];
968 unsigned* __g_end = __g;
969 unsigned __dc = 0;
970 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +0000971 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000972 __thousands_sep, __grouping, __g, __g_end,
973 __atoms))
974 break;
975 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
976 *__g_end++ = __dc;
977 // Stage 3
978 __v = __num_get_signed_integral<long>(__a, __a_end, __err, __base);
979 // Digit grouping checked
980 __check_grouping(__grouping, __g, __g_end, __err);
981 // EOF checked
982 if (__b == __e)
983 __err |= ios_base::eofbit;
984 return __b;
985}
986
987template <class _CharT, class _InputIterator>
988_InputIterator
989num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
990 ios_base& __iob,
991 ios_base::iostate& __err,
992 long long& __v) const
993{
994 // Stage 1
995 int __base = this->__get_base(__iob);
996 // Stage 2
997 char_type __atoms[26];
998 char_type __thousands_sep;
999 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
1000 char __a[__num_get_base::__num_get_buf_sz] = {0};
1001 char* __a_end = __a;
1002 unsigned __g[__num_get_base::__num_get_buf_sz];
1003 unsigned* __g_end = __g;
1004 unsigned __dc = 0;
1005 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001006 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
1007 __thousands_sep, __grouping, __g, __g_end,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001008 __atoms))
1009 break;
1010 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
1011 *__g_end++ = __dc;
1012 // Stage 3
1013 __v = __num_get_signed_integral<long long>(__a, __a_end, __err, __base);
1014 // Digit grouping checked
1015 __check_grouping(__grouping, __g, __g_end, __err);
1016 // EOF checked
1017 if (__b == __e)
1018 __err |= ios_base::eofbit;
1019 return __b;
1020}
1021
1022template <class _CharT, class _InputIterator>
1023_InputIterator
1024num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1025 ios_base& __iob,
1026 ios_base::iostate& __err,
1027 unsigned short& __v) const
1028{
1029 // Stage 1
1030 int __base = this->__get_base(__iob);
1031 // Stage 2
1032 char_type __atoms[26];
1033 char_type __thousands_sep;
1034 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
1035 char __a[__num_get_base::__num_get_buf_sz] = {0};
1036 char* __a_end = __a;
1037 unsigned __g[__num_get_base::__num_get_buf_sz];
1038 unsigned* __g_end = __g;
1039 unsigned __dc = 0;
1040 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001041 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001042 __thousands_sep, __grouping, __g, __g_end,
1043 __atoms))
1044 break;
1045 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
1046 *__g_end++ = __dc;
1047 // Stage 3
1048 __v = __num_get_unsigned_integral<unsigned short>(__a, __a_end, __err, __base);
1049 // Digit grouping checked
1050 __check_grouping(__grouping, __g, __g_end, __err);
1051 // EOF checked
1052 if (__b == __e)
1053 __err |= ios_base::eofbit;
1054 return __b;
1055}
1056
1057template <class _CharT, class _InputIterator>
1058_InputIterator
1059num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1060 ios_base& __iob,
1061 ios_base::iostate& __err,
1062 unsigned int& __v) const
1063{
1064 // Stage 1
1065 int __base = this->__get_base(__iob);
1066 // Stage 2
1067 char_type __atoms[26];
1068 char_type __thousands_sep;
1069 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
1070 char __a[__num_get_base::__num_get_buf_sz] = {0};
1071 char* __a_end = __a;
1072 unsigned __g[__num_get_base::__num_get_buf_sz];
1073 unsigned* __g_end = __g;
1074 unsigned __dc = 0;
1075 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001076 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001077 __thousands_sep, __grouping, __g, __g_end,
1078 __atoms))
1079 break;
1080 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
1081 *__g_end++ = __dc;
1082 // Stage 3
1083 __v = __num_get_unsigned_integral<unsigned int>(__a, __a_end, __err, __base);
1084 // Digit grouping checked
1085 __check_grouping(__grouping, __g, __g_end, __err);
1086 // EOF checked
1087 if (__b == __e)
1088 __err |= ios_base::eofbit;
1089 return __b;
1090}
1091
1092template <class _CharT, class _InputIterator>
1093_InputIterator
1094num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1095 ios_base& __iob,
1096 ios_base::iostate& __err,
1097 unsigned long& __v) const
1098{
1099 // Stage 1
1100 int __base = this->__get_base(__iob);
1101 // Stage 2
1102 char_type __atoms[26];
1103 char_type __thousands_sep;
1104 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
1105 char __a[__num_get_base::__num_get_buf_sz] = {0};
1106 char* __a_end = __a;
1107 unsigned __g[__num_get_base::__num_get_buf_sz];
1108 unsigned* __g_end = __g;
1109 unsigned __dc = 0;
1110 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001111 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001112 __thousands_sep, __grouping, __g, __g_end,
1113 __atoms))
1114 break;
1115 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
1116 *__g_end++ = __dc;
1117 // Stage 3
1118 __v = __num_get_unsigned_integral<unsigned long>(__a, __a_end, __err, __base);
1119 // Digit grouping checked
1120 __check_grouping(__grouping, __g, __g_end, __err);
1121 // EOF checked
1122 if (__b == __e)
1123 __err |= ios_base::eofbit;
1124 return __b;
1125}
1126
1127template <class _CharT, class _InputIterator>
1128_InputIterator
1129num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1130 ios_base& __iob,
1131 ios_base::iostate& __err,
1132 unsigned long long& __v) const
1133{
1134 // Stage 1
1135 int __base = this->__get_base(__iob);
1136 // Stage 2
1137 char_type __atoms[26];
1138 char_type __thousands_sep;
1139 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
1140 char __a[__num_get_base::__num_get_buf_sz] = {0};
1141 char* __a_end = __a;
1142 unsigned __g[__num_get_base::__num_get_buf_sz];
1143 unsigned* __g_end = __g;
1144 unsigned __dc = 0;
1145 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001146 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001147 __thousands_sep, __grouping, __g, __g_end,
1148 __atoms))
1149 break;
1150 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
1151 *__g_end++ = __dc;
1152 // Stage 3
1153 __v = __num_get_unsigned_integral<unsigned long long>(__a, __a_end, __err, __base);
1154 // Digit grouping checked
1155 __check_grouping(__grouping, __g, __g_end, __err);
1156 // EOF checked
1157 if (__b == __e)
1158 __err |= ios_base::eofbit;
1159 return __b;
1160}
1161
1162template <class _CharT, class _InputIterator>
1163_InputIterator
1164num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1165 ios_base& __iob,
1166 ios_base::iostate& __err,
1167 float& __v) const
1168{
1169 // Stage 1, nothing to do
1170 // Stage 2
1171 char_type __atoms[32];
1172 char_type __decimal_point;
1173 char_type __thousands_sep;
Howard Hinnant324bb032010-08-22 00:02:43 +00001174 string __grouping = this->__stage2_float_prep(__iob, __atoms,
1175 __decimal_point,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001176 __thousands_sep);
1177 char __a[__num_get_base::__num_get_buf_sz] = {0};
1178 char* __a_end = __a;
1179 unsigned __g[__num_get_base::__num_get_buf_sz];
1180 unsigned* __g_end = __g;
1181 unsigned __dc = 0;
1182 bool __in_units = true;
1183 char __exp = 'E';
1184 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001185 if (this->__stage2_float_loop(*__b, __in_units, __exp, __a, __a_end,
1186 __decimal_point, __thousands_sep,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001187 __grouping, __g, __g_end,
1188 __dc, __atoms))
1189 break;
1190 if (__grouping.size() != 0 && __in_units && __g_end-__g < __num_get_base::__num_get_buf_sz)
1191 *__g_end++ = __dc;
1192 // Stage 3
1193 __v = __num_get_float<float>(__a, __a_end, __err);
1194 // Digit grouping checked
1195 __check_grouping(__grouping, __g, __g_end, __err);
1196 // EOF checked
1197 if (__b == __e)
1198 __err |= ios_base::eofbit;
1199 return __b;
1200}
1201
1202template <class _CharT, class _InputIterator>
1203_InputIterator
1204num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1205 ios_base& __iob,
1206 ios_base::iostate& __err,
1207 double& __v) const
1208{
1209 // Stage 1, nothing to do
1210 // Stage 2
1211 char_type __atoms[32];
1212 char_type __decimal_point;
1213 char_type __thousands_sep;
Howard Hinnant324bb032010-08-22 00:02:43 +00001214 string __grouping = this->__stage2_float_prep(__iob, __atoms,
1215 __decimal_point,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001216 __thousands_sep);
1217 char __a[__num_get_base::__num_get_buf_sz] = {0};
1218 char* __a_end = __a;
1219 unsigned __g[__num_get_base::__num_get_buf_sz];
1220 unsigned* __g_end = __g;
1221 unsigned __dc = 0;
1222 bool __in_units = true;
1223 char __exp = 'E';
1224 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001225 if (this->__stage2_float_loop(*__b, __in_units, __exp, __a, __a_end,
1226 __decimal_point, __thousands_sep,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001227 __grouping, __g, __g_end,
1228 __dc, __atoms))
1229 break;
1230 if (__grouping.size() != 0 && __in_units && __g_end-__g < __num_get_base::__num_get_buf_sz)
1231 *__g_end++ = __dc;
1232 // Stage 3
1233 __v = __num_get_float<double>(__a, __a_end, __err);
1234 // Digit grouping checked
1235 __check_grouping(__grouping, __g, __g_end, __err);
1236 // EOF checked
1237 if (__b == __e)
1238 __err |= ios_base::eofbit;
1239 return __b;
1240}
1241
1242template <class _CharT, class _InputIterator>
1243_InputIterator
1244num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1245 ios_base& __iob,
1246 ios_base::iostate& __err,
1247 long double& __v) const
1248{
1249 // Stage 1, nothing to do
1250 // Stage 2
1251 char_type __atoms[32];
1252 char_type __decimal_point;
1253 char_type __thousands_sep;
Howard Hinnant324bb032010-08-22 00:02:43 +00001254 string __grouping = this->__stage2_float_prep(__iob, __atoms,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001255 __decimal_point,
1256 __thousands_sep);
1257 char __a[__num_get_base::__num_get_buf_sz] = {0};
1258 char* __a_end = __a;
1259 unsigned __g[__num_get_base::__num_get_buf_sz];
1260 unsigned* __g_end = __g;
1261 unsigned __dc = 0;
1262 bool __in_units = true;
1263 char __exp = 'E';
1264 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001265 if (this->__stage2_float_loop(*__b, __in_units, __exp, __a, __a_end,
1266 __decimal_point, __thousands_sep,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001267 __grouping, __g, __g_end,
1268 __dc, __atoms))
1269 break;
1270 if (__grouping.size() != 0 && __in_units && __g_end-__g < __num_get_base::__num_get_buf_sz)
1271 *__g_end++ = __dc;
1272 // Stage 3
1273 __v = __num_get_float<long double>(__a, __a_end, __err);
1274 // Digit grouping checked
1275 __check_grouping(__grouping, __g, __g_end, __err);
1276 // EOF checked
1277 if (__b == __e)
1278 __err |= ios_base::eofbit;
1279 return __b;
1280}
1281
1282template <class _CharT, class _InputIterator>
1283_InputIterator
1284num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1285 ios_base& __iob,
1286 ios_base::iostate& __err,
1287 void*& __v) const
1288{
1289 // Stage 1
1290 int __base = 16;
1291 // Stage 2
1292 char_type __atoms[26];
Howard Hinnantec3773c2011-12-01 20:21:04 +00001293 char_type __thousands_sep = 0;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001294 string __grouping;
1295 use_facet<ctype<_CharT> >(__iob.getloc()).widen(__num_get_base::__src,
1296 __num_get_base::__src + 26, __atoms);
1297 char __a[__num_get_base::__num_get_buf_sz] = {0};
1298 char* __a_end = __a;
1299 unsigned __g[__num_get_base::__num_get_buf_sz];
1300 unsigned* __g_end = __g;
1301 unsigned __dc = 0;
1302 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001303 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
1304 __thousands_sep, __grouping,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001305 __g, __g_end, __atoms))
1306 break;
1307 // Stage 3
1308 __a[sizeof(__a)-1] = 0;
Howard Hinnant866569b2011-09-28 23:39:33 +00001309#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001310 if (sscanf_l(__a, _LIBCPP_GET_C_LOCALE, "%p", &__v) != 1)
Sean Huntf3907e62011-07-15 05:40:33 +00001311#else
1312 if (__sscanf_l(__a, __cloc(), "%p", &__v) != 1)
1313#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001314 __err = ios_base::failbit;
1315 // EOF checked
1316 if (__b == __e)
1317 __err |= ios_base::eofbit;
1318 return __b;
1319}
1320
Howard Hinnantff926772012-11-06 21:08:48 +00001321_LIBCPP_EXTERN_TEMPLATE(class num_get<char>)
1322_LIBCPP_EXTERN_TEMPLATE(class num_get<wchar_t>)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001323
1324struct __num_put_base
1325{
1326protected:
1327 static void __format_int(char* __fmt, const char* __len, bool __signd,
1328 ios_base::fmtflags __flags);
1329 static bool __format_float(char* __fmt, const char* __len,
1330 ios_base::fmtflags __flags);
1331 static char* __identify_padding(char* __nb, char* __ne,
1332 const ios_base& __iob);
1333};
1334
1335template <class _CharT>
1336struct __num_put
1337 : protected __num_put_base
1338{
1339 static void __widen_and_group_int(char* __nb, char* __np, char* __ne,
1340 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1341 const locale& __loc);
1342 static void __widen_and_group_float(char* __nb, char* __np, char* __ne,
1343 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1344 const locale& __loc);
1345};
1346
1347template <class _CharT>
1348void
1349__num_put<_CharT>::__widen_and_group_int(char* __nb, char* __np, char* __ne,
1350 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1351 const locale& __loc)
1352{
1353 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> > (__loc);
1354 const numpunct<_CharT>& __npt = use_facet<numpunct<_CharT> >(__loc);
1355 string __grouping = __npt.grouping();
1356 if (__grouping.empty())
1357 {
1358 __ct.widen(__nb, __ne, __ob);
1359 __oe = __ob + (__ne - __nb);
1360 }
1361 else
1362 {
1363 __oe = __ob;
1364 char* __nf = __nb;
1365 if (*__nf == '-' || *__nf == '+')
1366 *__oe++ = __ct.widen(*__nf++);
1367 if (__ne - __nf >= 2 && __nf[0] == '0' && (__nf[1] == 'x' ||
1368 __nf[1] == 'X'))
1369 {
1370 *__oe++ = __ct.widen(*__nf++);
1371 *__oe++ = __ct.widen(*__nf++);
1372 }
1373 reverse(__nf, __ne);
1374 _CharT __thousands_sep = __npt.thousands_sep();
1375 unsigned __dc = 0;
1376 unsigned __dg = 0;
1377 for (char* __p = __nf; __p < __ne; ++__p)
1378 {
1379 if (static_cast<unsigned>(__grouping[__dg]) > 0 &&
1380 __dc == static_cast<unsigned>(__grouping[__dg]))
1381 {
1382 *__oe++ = __thousands_sep;
1383 __dc = 0;
1384 if (__dg < __grouping.size()-1)
1385 ++__dg;
1386 }
1387 *__oe++ = __ct.widen(*__p);
1388 ++__dc;
1389 }
1390 reverse(__ob + (__nf - __nb), __oe);
1391 }
1392 if (__np == __ne)
1393 __op = __oe;
1394 else
1395 __op = __ob + (__np - __nb);
1396}
1397
1398template <class _CharT>
1399void
1400__num_put<_CharT>::__widen_and_group_float(char* __nb, char* __np, char* __ne,
1401 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1402 const locale& __loc)
1403{
1404 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> > (__loc);
1405 const numpunct<_CharT>& __npt = use_facet<numpunct<_CharT> >(__loc);
1406 string __grouping = __npt.grouping();
1407 __oe = __ob;
1408 char* __nf = __nb;
1409 if (*__nf == '-' || *__nf == '+')
1410 *__oe++ = __ct.widen(*__nf++);
1411 char* __ns;
1412 if (__ne - __nf >= 2 && __nf[0] == '0' && (__nf[1] == 'x' ||
1413 __nf[1] == 'X'))
1414 {
1415 *__oe++ = __ct.widen(*__nf++);
1416 *__oe++ = __ct.widen(*__nf++);
1417 for (__ns = __nf; __ns < __ne; ++__ns)
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001418 if (!isxdigit_l(*__ns, _LIBCPP_GET_C_LOCALE))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001419 break;
1420 }
1421 else
1422 {
1423 for (__ns = __nf; __ns < __ne; ++__ns)
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001424 if (!isdigit_l(*__ns, _LIBCPP_GET_C_LOCALE))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001425 break;
1426 }
1427 if (__grouping.empty())
1428 {
1429 __ct.widen(__nf, __ns, __oe);
1430 __oe += __ns - __nf;
1431 }
1432 else
1433 {
1434 reverse(__nf, __ns);
1435 _CharT __thousands_sep = __npt.thousands_sep();
1436 unsigned __dc = 0;
1437 unsigned __dg = 0;
1438 for (char* __p = __nf; __p < __ns; ++__p)
1439 {
1440 if (__grouping[__dg] > 0 && __dc == static_cast<unsigned>(__grouping[__dg]))
1441 {
1442 *__oe++ = __thousands_sep;
1443 __dc = 0;
1444 if (__dg < __grouping.size()-1)
1445 ++__dg;
1446 }
1447 *__oe++ = __ct.widen(*__p);
1448 ++__dc;
1449 }
1450 reverse(__ob + (__nf - __nb), __oe);
1451 }
1452 for (__nf = __ns; __nf < __ne; ++__nf)
1453 {
1454 if (*__nf == '.')
1455 {
1456 *__oe++ = __npt.decimal_point();
1457 ++__nf;
1458 break;
1459 }
1460 else
1461 *__oe++ = __ct.widen(*__nf);
1462 }
1463 __ct.widen(__nf, __ne, __oe);
1464 __oe += __ne - __nf;
1465 if (__np == __ne)
1466 __op = __oe;
1467 else
1468 __op = __ob + (__np - __nb);
1469}
1470
Howard Hinnantff926772012-11-06 21:08:48 +00001471_LIBCPP_EXTERN_TEMPLATE(struct __num_put<char>)
1472_LIBCPP_EXTERN_TEMPLATE(struct __num_put<wchar_t>)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001473
1474template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00001475class _LIBCPP_VISIBLE num_put
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001476 : public locale::facet,
1477 private __num_put<_CharT>
1478{
1479public:
1480 typedef _CharT char_type;
1481 typedef _OutputIterator iter_type;
1482
1483 _LIBCPP_ALWAYS_INLINE
1484 explicit num_put(size_t __refs = 0)
1485 : locale::facet(__refs) {}
1486
1487 _LIBCPP_ALWAYS_INLINE
1488 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1489 bool __v) const
1490 {
1491 return do_put(__s, __iob, __fl, __v);
1492 }
1493
1494 _LIBCPP_ALWAYS_INLINE
1495 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1496 long __v) const
1497 {
1498 return do_put(__s, __iob, __fl, __v);
1499 }
1500
1501 _LIBCPP_ALWAYS_INLINE
1502 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1503 long long __v) const
1504 {
1505 return do_put(__s, __iob, __fl, __v);
1506 }
1507
1508 _LIBCPP_ALWAYS_INLINE
1509 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1510 unsigned long __v) const
1511 {
1512 return do_put(__s, __iob, __fl, __v);
1513 }
1514
1515 _LIBCPP_ALWAYS_INLINE
1516 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1517 unsigned long long __v) const
1518 {
1519 return do_put(__s, __iob, __fl, __v);
1520 }
1521
1522 _LIBCPP_ALWAYS_INLINE
1523 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1524 double __v) const
1525 {
1526 return do_put(__s, __iob, __fl, __v);
1527 }
1528
1529 _LIBCPP_ALWAYS_INLINE
1530 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1531 long double __v) const
1532 {
1533 return do_put(__s, __iob, __fl, __v);
1534 }
1535
1536 _LIBCPP_ALWAYS_INLINE
1537 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1538 const void* __v) const
1539 {
1540 return do_put(__s, __iob, __fl, __v);
1541 }
1542
1543 static locale::id id;
1544
1545protected:
Howard Hinnant82894812010-09-22 16:48:34 +00001546 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001547 ~num_put() {}
1548
1549 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1550 bool __v) const;
1551 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1552 long __v) const;
1553 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1554 long long __v) const;
1555 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1556 unsigned long) const;
1557 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1558 unsigned long long) const;
1559 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1560 double __v) const;
1561 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1562 long double __v) const;
1563 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1564 const void* __v) const;
1565};
1566
1567template <class _CharT, class _OutputIterator>
1568locale::id
1569num_put<_CharT, _OutputIterator>::id;
1570
1571template <class _CharT, class _OutputIterator>
1572_LIBCPP_HIDDEN
1573_OutputIterator
1574__pad_and_output(_OutputIterator __s,
1575 const _CharT* __ob, const _CharT* __op, const _CharT* __oe,
1576 ios_base& __iob, _CharT __fl)
1577{
1578 streamsize __sz = __oe - __ob;
1579 streamsize __ns = __iob.width();
1580 if (__ns > __sz)
1581 __ns -= __sz;
1582 else
1583 __ns = 0;
1584 for (;__ob < __op; ++__ob, ++__s)
1585 *__s = *__ob;
1586 for (; __ns; --__ns, ++__s)
1587 *__s = __fl;
1588 for (; __ob < __oe; ++__ob, ++__s)
1589 *__s = *__ob;
1590 __iob.width(0);
1591 return __s;
1592}
1593
Howard Hinnant537b2fa2012-11-14 21:17:15 +00001594#if !defined(__APPLE__) || \
1595 (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED > __MAC_10_8) || \
1596 (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED > __IPHONE_6_0)
1597
Howard Hinnanta585de62012-09-19 19:14:15 +00001598template <class _CharT, class _Traits>
1599_LIBCPP_HIDDEN
1600ostreambuf_iterator<_CharT, _Traits>
1601__pad_and_output(ostreambuf_iterator<_CharT, _Traits> __s,
1602 const _CharT* __ob, const _CharT* __op, const _CharT* __oe,
1603 ios_base& __iob, _CharT __fl)
1604{
1605 if (__s.__sbuf_ == nullptr)
1606 return __s;
1607 streamsize __sz = __oe - __ob;
1608 streamsize __ns = __iob.width();
1609 if (__ns > __sz)
1610 __ns -= __sz;
1611 else
1612 __ns = 0;
1613 streamsize __np = __op - __ob;
1614 if (__np > 0)
1615 {
1616 if (__s.__sbuf_->sputn(__ob, __np) != __np)
1617 {
1618 __s.__sbuf_ = nullptr;
1619 return __s;
1620 }
1621 }
1622 if (__ns > 0)
1623 {
1624 basic_string<_CharT, _Traits> __sp(__ns, __fl);
1625 if (__s.__sbuf_->sputn(__sp.data(), __ns) != __ns)
1626 {
1627 __s.__sbuf_ = nullptr;
1628 return __s;
1629 }
1630 }
1631 __np = __oe - __op;
1632 if (__np > 0)
1633 {
1634 if (__s.__sbuf_->sputn(__op, __np) != __np)
1635 {
1636 __s.__sbuf_ = nullptr;
1637 return __s;
1638 }
1639 }
1640 __iob.width(0);
1641 return __s;
1642}
1643
Howard Hinnant537b2fa2012-11-14 21:17:15 +00001644#endif
1645
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001646template <class _CharT, class _OutputIterator>
1647_OutputIterator
1648num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1649 char_type __fl, bool __v) const
1650{
1651 if ((__iob.flags() & ios_base::boolalpha) == 0)
1652 return do_put(__s, __iob, __fl, (unsigned long)__v);
1653 const numpunct<char_type>& __np = use_facet<numpunct<char_type> >(__iob.getloc());
1654 typedef typename numpunct<char_type>::string_type string_type;
1655 string_type __nm = __v ? __np.truename() : __np.falsename();
1656 for (typename string_type::iterator __i = __nm.begin(); __i != __nm.end(); ++__i, ++__s)
1657 *__s = *__i;
1658 return __s;
1659}
1660
1661template <class _CharT, class _OutputIterator>
1662_OutputIterator
1663num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1664 char_type __fl, long __v) const
1665{
1666 // Stage 1 - Get number in narrow char
1667 char __fmt[6] = {'%', 0};
1668 const char* __len = "l";
1669 this->__format_int(__fmt+1, __len, true, __iob.flags());
1670 const unsigned __nbuf = (numeric_limits<long>::digits / 3)
1671 + ((numeric_limits<long>::digits % 3) != 0)
1672 + 1;
1673 char __nar[__nbuf];
Howard Hinnant866569b2011-09-28 23:39:33 +00001674#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001675 int __nc = sprintf_l(__nar, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001676#else
1677 int __nc = __sprintf_l(__nar, __cloc(), __fmt, __v);
1678#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001679 char* __ne = __nar + __nc;
1680 char* __np = this->__identify_padding(__nar, __ne, __iob);
1681 // Stage 2 - Widen __nar while adding thousands separators
1682 char_type __o[2*(__nbuf-1) - 1];
1683 char_type* __op; // pad here
1684 char_type* __oe; // end of output
1685 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1686 // [__o, __oe) contains thousands_sep'd wide number
1687 // Stage 3 & 4
1688 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1689}
1690
1691template <class _CharT, class _OutputIterator>
1692_OutputIterator
1693num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1694 char_type __fl, long long __v) const
1695{
1696 // Stage 1 - Get number in narrow char
1697 char __fmt[8] = {'%', 0};
1698 const char* __len = "ll";
1699 this->__format_int(__fmt+1, __len, true, __iob.flags());
1700 const unsigned __nbuf = (numeric_limits<long long>::digits / 3)
1701 + ((numeric_limits<long long>::digits % 3) != 0)
1702 + 1;
1703 char __nar[__nbuf];
Howard Hinnant866569b2011-09-28 23:39:33 +00001704#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001705 int __nc = sprintf_l(__nar, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001706#else
1707 int __nc = __sprintf_l(__nar, __cloc(), __fmt, __v);
1708#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001709 char* __ne = __nar + __nc;
1710 char* __np = this->__identify_padding(__nar, __ne, __iob);
1711 // Stage 2 - Widen __nar while adding thousands separators
1712 char_type __o[2*(__nbuf-1) - 1];
1713 char_type* __op; // pad here
1714 char_type* __oe; // end of output
1715 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1716 // [__o, __oe) contains thousands_sep'd wide number
1717 // Stage 3 & 4
1718 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1719}
1720
1721template <class _CharT, class _OutputIterator>
1722_OutputIterator
1723num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1724 char_type __fl, unsigned long __v) const
1725{
1726 // Stage 1 - Get number in narrow char
1727 char __fmt[6] = {'%', 0};
1728 const char* __len = "l";
1729 this->__format_int(__fmt+1, __len, false, __iob.flags());
1730 const unsigned __nbuf = (numeric_limits<unsigned long>::digits / 3)
1731 + ((numeric_limits<unsigned long>::digits % 3) != 0)
1732 + 1;
1733 char __nar[__nbuf];
Howard Hinnant866569b2011-09-28 23:39:33 +00001734#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001735 int __nc = sprintf_l(__nar, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001736#else
1737 int __nc = __sprintf_l(__nar, __cloc(), __fmt, __v);
1738#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001739 char* __ne = __nar + __nc;
1740 char* __np = this->__identify_padding(__nar, __ne, __iob);
1741 // Stage 2 - Widen __nar while adding thousands separators
1742 char_type __o[2*(__nbuf-1) - 1];
1743 char_type* __op; // pad here
1744 char_type* __oe; // end of output
1745 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1746 // [__o, __oe) contains thousands_sep'd wide number
1747 // Stage 3 & 4
1748 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1749}
1750
1751template <class _CharT, class _OutputIterator>
1752_OutputIterator
1753num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1754 char_type __fl, unsigned long long __v) const
1755{
1756 // Stage 1 - Get number in narrow char
1757 char __fmt[8] = {'%', 0};
1758 const char* __len = "ll";
1759 this->__format_int(__fmt+1, __len, false, __iob.flags());
1760 const unsigned __nbuf = (numeric_limits<unsigned long long>::digits / 3)
1761 + ((numeric_limits<unsigned long long>::digits % 3) != 0)
1762 + 1;
1763 char __nar[__nbuf];
Howard Hinnant866569b2011-09-28 23:39:33 +00001764#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001765 int __nc = sprintf_l(__nar, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001766#else
1767 int __nc = __sprintf_l(__nar, __cloc(), __fmt, __v);
1768#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001769 char* __ne = __nar + __nc;
1770 char* __np = this->__identify_padding(__nar, __ne, __iob);
1771 // Stage 2 - Widen __nar while adding thousands separators
1772 char_type __o[2*(__nbuf-1) - 1];
1773 char_type* __op; // pad here
1774 char_type* __oe; // end of output
1775 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1776 // [__o, __oe) contains thousands_sep'd wide number
1777 // Stage 3 & 4
1778 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1779}
1780
1781template <class _CharT, class _OutputIterator>
1782_OutputIterator
1783num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1784 char_type __fl, double __v) const
1785{
1786 // Stage 1 - Get number in narrow char
1787 char __fmt[8] = {'%', 0};
1788 const char* __len = "";
1789 bool __specify_precision = this->__format_float(__fmt+1, __len, __iob.flags());
1790 const unsigned __nbuf = 30;
1791 char __nar[__nbuf];
1792 char* __nb = __nar;
1793 int __nc;
1794 if (__specify_precision)
Howard Hinnant866569b2011-09-28 23:39:33 +00001795#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001796 __nc = snprintf_l(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt,
Howard Hinnantadff4892010-05-24 17:49:41 +00001797 (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001798#else
1799 __nc = __snprintf_l(__nb, __nbuf, __cloc(), __fmt,
1800 (int)__iob.precision(), __v);
1801#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001802 else
Howard Hinnant866569b2011-09-28 23:39:33 +00001803#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001804 __nc = snprintf_l(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001805#else
1806 __nc = __snprintf_l(__nb, __nbuf, __cloc(), __fmt, __v);
1807#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001808 unique_ptr<char, void(*)(void*)> __nbh(0, free);
1809 if (__nc > static_cast<int>(__nbuf-1))
1810 {
1811 if (__specify_precision)
Howard Hinnant866569b2011-09-28 23:39:33 +00001812#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001813 __nc = asprintf_l(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001814#else
1815 __nc = __asprintf_l(&__nb, __cloc(), __fmt,
David Chisnallc512df12011-09-21 08:39:44 +00001816 (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001817#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001818 else
Howard Hinnant866569b2011-09-28 23:39:33 +00001819#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001820 __nc = asprintf_l(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001821#else
David Chisnallc512df12011-09-21 08:39:44 +00001822 __nc = __asprintf_l(&__nb, __cloc(), __fmt, (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001823#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001824 if (__nb == 0)
1825 __throw_bad_alloc();
1826 __nbh.reset(__nb);
1827 }
1828 char* __ne = __nb + __nc;
1829 char* __np = this->__identify_padding(__nb, __ne, __iob);
1830 // Stage 2 - Widen __nar while adding thousands separators
1831 char_type __o[2*(__nbuf-1) - 1];
1832 char_type* __ob = __o;
1833 unique_ptr<char_type, void(*)(void*)> __obh(0, free);
1834 if (__nb != __nar)
1835 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00001836 __ob = (char_type*)malloc(2*static_cast<size_t>(__nc)*sizeof(char_type));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001837 if (__ob == 0)
1838 __throw_bad_alloc();
1839 __obh.reset(__ob);
1840 }
1841 char_type* __op; // pad here
1842 char_type* __oe; // end of output
1843 this->__widen_and_group_float(__nb, __np, __ne, __ob, __op, __oe, __iob.getloc());
1844 // [__o, __oe) contains thousands_sep'd wide number
1845 // Stage 3 & 4
1846 __s = __pad_and_output(__s, __ob, __op, __oe, __iob, __fl);
1847 return __s;
1848}
1849
1850template <class _CharT, class _OutputIterator>
1851_OutputIterator
1852num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1853 char_type __fl, long double __v) const
1854{
1855 // Stage 1 - Get number in narrow char
1856 char __fmt[8] = {'%', 0};
1857 const char* __len = "L";
1858 bool __specify_precision = this->__format_float(__fmt+1, __len, __iob.flags());
1859 const unsigned __nbuf = 30;
1860 char __nar[__nbuf];
1861 char* __nb = __nar;
1862 int __nc;
1863 if (__specify_precision)
Howard Hinnant866569b2011-09-28 23:39:33 +00001864#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001865 __nc = snprintf_l(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt,
Howard Hinnantadff4892010-05-24 17:49:41 +00001866 (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001867#else
1868 __nc = __snprintf_l(__nb, __nbuf, __cloc(), __fmt,
1869 (int)__iob.precision(), __v);
1870#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001871 else
Howard Hinnant866569b2011-09-28 23:39:33 +00001872#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001873 __nc = snprintf_l(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001874#else
1875 __nc = __snprintf_l(__nb, __nbuf, __cloc(), __fmt, __v);
1876#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001877 unique_ptr<char, void(*)(void*)> __nbh(0, free);
1878 if (__nc > static_cast<int>(__nbuf-1))
1879 {
1880 if (__specify_precision)
Howard Hinnant866569b2011-09-28 23:39:33 +00001881#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001882 __nc = asprintf_l(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001883#else
1884 __nc = __asprintf_l(&__nb, __cloc(), __fmt,
David Chisnallc512df12011-09-21 08:39:44 +00001885 (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001886#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001887 else
Howard Hinnant866569b2011-09-28 23:39:33 +00001888#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001889 __nc = asprintf_l(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001890#else
David Chisnallc512df12011-09-21 08:39:44 +00001891 __nc = __asprintf_l(&__nb, __cloc(), __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001892#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001893 if (__nb == 0)
1894 __throw_bad_alloc();
1895 __nbh.reset(__nb);
1896 }
1897 char* __ne = __nb + __nc;
1898 char* __np = this->__identify_padding(__nb, __ne, __iob);
1899 // Stage 2 - Widen __nar while adding thousands separators
1900 char_type __o[2*(__nbuf-1) - 1];
1901 char_type* __ob = __o;
1902 unique_ptr<char_type, void(*)(void*)> __obh(0, free);
1903 if (__nb != __nar)
1904 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00001905 __ob = (char_type*)malloc(2*static_cast<size_t>(__nc)*sizeof(char_type));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001906 if (__ob == 0)
1907 __throw_bad_alloc();
1908 __obh.reset(__ob);
1909 }
1910 char_type* __op; // pad here
1911 char_type* __oe; // end of output
1912 this->__widen_and_group_float(__nb, __np, __ne, __ob, __op, __oe, __iob.getloc());
1913 // [__o, __oe) contains thousands_sep'd wide number
1914 // Stage 3 & 4
1915 __s = __pad_and_output(__s, __ob, __op, __oe, __iob, __fl);
1916 return __s;
1917}
1918
1919template <class _CharT, class _OutputIterator>
1920_OutputIterator
1921num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1922 char_type __fl, const void* __v) const
1923{
1924 // Stage 1 - Get pointer in narrow char
1925 char __fmt[6] = "%p";
1926 const unsigned __nbuf = 20;
1927 char __nar[__nbuf];
Howard Hinnant866569b2011-09-28 23:39:33 +00001928#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001929 int __nc = sprintf_l(__nar, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001930#else
1931 int __nc = __sprintf_l(__nar, __cloc(), __fmt, __v);
1932#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001933 char* __ne = __nar + __nc;
1934 char* __np = this->__identify_padding(__nar, __ne, __iob);
1935 // Stage 2 - Widen __nar
1936 char_type __o[2*(__nbuf-1) - 1];
1937 char_type* __op; // pad here
1938 char_type* __oe; // end of output
1939 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
1940 __ct.widen(__nar, __ne, __o);
1941 __oe = __o + (__ne - __nar);
1942 if (__np == __ne)
1943 __op = __oe;
1944 else
1945 __op = __o + (__np - __nar);
1946 // [__o, __oe) contains wide number
1947 // Stage 3 & 4
1948 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1949}
1950
Howard Hinnantff926772012-11-06 21:08:48 +00001951_LIBCPP_EXTERN_TEMPLATE(class num_put<char>)
1952_LIBCPP_EXTERN_TEMPLATE(class num_put<wchar_t>)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001953
1954template <class _CharT, class _InputIterator>
1955_LIBCPP_HIDDEN
1956int
1957__get_up_to_n_digits(_InputIterator& __b, _InputIterator __e,
1958 ios_base::iostate& __err, const ctype<_CharT>& __ct, int __n)
1959{
1960 // Precondition: __n >= 1
1961 if (__b == __e)
1962 {
1963 __err |= ios_base::eofbit | ios_base::failbit;
1964 return 0;
1965 }
1966 // get first digit
1967 _CharT __c = *__b;
1968 if (!__ct.is(ctype_base::digit, __c))
1969 {
1970 __err |= ios_base::failbit;
1971 return 0;
1972 }
1973 int __r = __ct.narrow(__c, 0) - '0';
1974 for (++__b, --__n; __b != __e && __n > 0; ++__b, --__n)
1975 {
1976 // get next digit
1977 __c = *__b;
1978 if (!__ct.is(ctype_base::digit, __c))
1979 return __r;
1980 __r = __r * 10 + __ct.narrow(__c, 0) - '0';
1981 }
1982 if (__b == __e)
1983 __err |= ios_base::eofbit;
1984 return __r;
1985}
1986
Howard Hinnant82894812010-09-22 16:48:34 +00001987class _LIBCPP_VISIBLE time_base
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001988{
1989public:
1990 enum dateorder {no_order, dmy, mdy, ymd, ydm};
1991};
1992
1993template <class _CharT>
Howard Hinnant2d72b1e2010-12-17 14:46:43 +00001994class __time_get_c_storage // purposefully not decorated
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001995{
1996protected:
1997 typedef basic_string<_CharT> string_type;
1998
1999 virtual const string_type* __weeks() const;
2000 virtual const string_type* __months() const;
2001 virtual const string_type* __am_pm() const;
2002 virtual const string_type& __c() const;
2003 virtual const string_type& __r() const;
2004 virtual const string_type& __x() const;
2005 virtual const string_type& __X() const;
2006};
2007
2008template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00002009class _LIBCPP_VISIBLE time_get
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002010 : public locale::facet,
2011 public time_base,
2012 private __time_get_c_storage<_CharT>
2013{
2014public:
2015 typedef _CharT char_type;
2016 typedef _InputIterator iter_type;
2017 typedef time_base::dateorder dateorder;
2018 typedef basic_string<char_type> string_type;
2019
2020 _LIBCPP_ALWAYS_INLINE
2021 explicit time_get(size_t __refs = 0)
2022 : locale::facet(__refs) {}
2023
2024 _LIBCPP_ALWAYS_INLINE
2025 dateorder date_order() const
2026 {
2027 return this->do_date_order();
2028 }
2029
2030 _LIBCPP_ALWAYS_INLINE
2031 iter_type get_time(iter_type __b, iter_type __e, ios_base& __iob,
2032 ios_base::iostate& __err, tm* __tm) const
2033 {
2034 return do_get_time(__b, __e, __iob, __err, __tm);
2035 }
2036
2037 _LIBCPP_ALWAYS_INLINE
2038 iter_type get_date(iter_type __b, iter_type __e, ios_base& __iob,
2039 ios_base::iostate& __err, tm* __tm) const
2040 {
2041 return do_get_date(__b, __e, __iob, __err, __tm);
2042 }
2043
2044 _LIBCPP_ALWAYS_INLINE
2045 iter_type get_weekday(iter_type __b, iter_type __e, ios_base& __iob,
2046 ios_base::iostate& __err, tm* __tm) const
2047 {
2048 return do_get_weekday(__b, __e, __iob, __err, __tm);
2049 }
2050
2051 _LIBCPP_ALWAYS_INLINE
2052 iter_type get_monthname(iter_type __b, iter_type __e, ios_base& __iob,
2053 ios_base::iostate& __err, tm* __tm) const
2054 {
2055 return do_get_monthname(__b, __e, __iob, __err, __tm);
2056 }
2057
2058 _LIBCPP_ALWAYS_INLINE
2059 iter_type get_year(iter_type __b, iter_type __e, ios_base& __iob,
2060 ios_base::iostate& __err, tm* __tm) const
2061 {
2062 return do_get_year(__b, __e, __iob, __err, __tm);
2063 }
2064
2065 _LIBCPP_ALWAYS_INLINE
2066 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
2067 ios_base::iostate& __err, tm *__tm,
2068 char __fmt, char __mod = 0) const
2069 {
2070 return do_get(__b, __e, __iob, __err, __tm, __fmt, __mod);
2071 }
2072
2073 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
2074 ios_base::iostate& __err, tm* __tm,
2075 const char_type* __fmtb, const char_type* __fmte) const;
2076
2077 static locale::id id;
2078
2079protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002080 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002081 ~time_get() {}
2082
2083 virtual dateorder do_date_order() const;
2084 virtual iter_type do_get_time(iter_type __b, iter_type __e, ios_base& __iob,
2085 ios_base::iostate& __err, tm* __tm) const;
2086 virtual iter_type do_get_date(iter_type __b, iter_type __e, ios_base& __iob,
2087 ios_base::iostate& __err, tm* __tm) const;
2088 virtual iter_type do_get_weekday(iter_type __b, iter_type __e, ios_base& __iob,
2089 ios_base::iostate& __err, tm* __tm) const;
2090 virtual iter_type do_get_monthname(iter_type __b, iter_type __e, ios_base& __iob,
2091 ios_base::iostate& __err, tm* __tm) const;
2092 virtual iter_type do_get_year(iter_type __b, iter_type __e, ios_base& __iob,
2093 ios_base::iostate& __err, tm* __tm) const;
2094 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
2095 ios_base::iostate& __err, tm* __tm,
2096 char __fmt, char __mod) const;
2097private:
2098 void __get_white_space(iter_type& __b, iter_type __e,
2099 ios_base::iostate& __err, const ctype<char_type>& __ct) const;
2100 void __get_percent(iter_type& __b, iter_type __e, ios_base::iostate& __err,
2101 const ctype<char_type>& __ct) const;
2102
2103 void __get_weekdayname(int& __m,
2104 iter_type& __b, iter_type __e,
2105 ios_base::iostate& __err,
2106 const ctype<char_type>& __ct) const;
2107 void __get_monthname(int& __m,
2108 iter_type& __b, iter_type __e,
2109 ios_base::iostate& __err,
2110 const ctype<char_type>& __ct) const;
2111 void __get_day(int& __d,
2112 iter_type& __b, iter_type __e,
2113 ios_base::iostate& __err,
2114 const ctype<char_type>& __ct) const;
2115 void __get_month(int& __m,
2116 iter_type& __b, iter_type __e,
2117 ios_base::iostate& __err,
2118 const ctype<char_type>& __ct) const;
2119 void __get_year(int& __y,
2120 iter_type& __b, iter_type __e,
2121 ios_base::iostate& __err,
2122 const ctype<char_type>& __ct) const;
2123 void __get_year4(int& __y,
2124 iter_type& __b, iter_type __e,
2125 ios_base::iostate& __err,
2126 const ctype<char_type>& __ct) const;
2127 void __get_hour(int& __d,
2128 iter_type& __b, iter_type __e,
2129 ios_base::iostate& __err,
2130 const ctype<char_type>& __ct) const;
2131 void __get_12_hour(int& __h,
2132 iter_type& __b, iter_type __e,
2133 ios_base::iostate& __err,
2134 const ctype<char_type>& __ct) const;
2135 void __get_am_pm(int& __h,
2136 iter_type& __b, iter_type __e,
2137 ios_base::iostate& __err,
2138 const ctype<char_type>& __ct) const;
2139 void __get_minute(int& __m,
2140 iter_type& __b, iter_type __e,
2141 ios_base::iostate& __err,
2142 const ctype<char_type>& __ct) const;
2143 void __get_second(int& __s,
2144 iter_type& __b, iter_type __e,
2145 ios_base::iostate& __err,
2146 const ctype<char_type>& __ct) const;
2147 void __get_weekday(int& __w,
2148 iter_type& __b, iter_type __e,
2149 ios_base::iostate& __err,
2150 const ctype<char_type>& __ct) const;
2151 void __get_day_year_num(int& __w,
2152 iter_type& __b, iter_type __e,
2153 ios_base::iostate& __err,
2154 const ctype<char_type>& __ct) const;
2155};
2156
2157template <class _CharT, class _InputIterator>
2158locale::id
2159time_get<_CharT, _InputIterator>::id;
2160
2161// time_get primatives
2162
2163template <class _CharT, class _InputIterator>
2164void
2165time_get<_CharT, _InputIterator>::__get_weekdayname(int& __w,
2166 iter_type& __b, iter_type __e,
2167 ios_base::iostate& __err,
2168 const ctype<char_type>& __ct) const
2169{
2170 // Note: ignoring case comes from the POSIX strptime spec
2171 const string_type* __wk = this->__weeks();
Howard Hinnantec3773c2011-12-01 20:21:04 +00002172 ptrdiff_t __i = __scan_keyword(__b, __e, __wk, __wk+14, __ct, __err, false) - __wk;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002173 if (__i < 14)
2174 __w = __i % 7;
2175}
2176
2177template <class _CharT, class _InputIterator>
2178void
2179time_get<_CharT, _InputIterator>::__get_monthname(int& __m,
2180 iter_type& __b, iter_type __e,
2181 ios_base::iostate& __err,
2182 const ctype<char_type>& __ct) const
2183{
2184 // Note: ignoring case comes from the POSIX strptime spec
2185 const string_type* __month = this->__months();
Howard Hinnantec3773c2011-12-01 20:21:04 +00002186 ptrdiff_t __i = __scan_keyword(__b, __e, __month, __month+24, __ct, __err, false) - __month;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002187 if (__i < 24)
2188 __m = __i % 12;
2189}
2190
2191template <class _CharT, class _InputIterator>
2192void
2193time_get<_CharT, _InputIterator>::__get_day(int& __d,
2194 iter_type& __b, iter_type __e,
2195 ios_base::iostate& __err,
2196 const ctype<char_type>& __ct) const
2197{
2198 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2199 if (!(__err & ios_base::failbit) && 1 <= __t && __t <= 31)
2200 __d = __t;
2201 else
2202 __err |= ios_base::failbit;
2203}
2204
2205template <class _CharT, class _InputIterator>
2206void
2207time_get<_CharT, _InputIterator>::__get_month(int& __m,
2208 iter_type& __b, iter_type __e,
2209 ios_base::iostate& __err,
2210 const ctype<char_type>& __ct) const
2211{
2212 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2) - 1;
2213 if (!(__err & ios_base::failbit) && __t <= 11)
2214 __m = __t;
2215 else
2216 __err |= ios_base::failbit;
2217}
2218
2219template <class _CharT, class _InputIterator>
2220void
2221time_get<_CharT, _InputIterator>::__get_year(int& __y,
2222 iter_type& __b, iter_type __e,
2223 ios_base::iostate& __err,
2224 const ctype<char_type>& __ct) const
2225{
2226 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 4);
2227 if (!(__err & ios_base::failbit))
2228 {
2229 if (__t < 69)
2230 __t += 2000;
2231 else if (69 <= __t && __t <= 99)
2232 __t += 1900;
2233 __y = __t - 1900;
2234 }
2235}
2236
2237template <class _CharT, class _InputIterator>
2238void
2239time_get<_CharT, _InputIterator>::__get_year4(int& __y,
2240 iter_type& __b, iter_type __e,
2241 ios_base::iostate& __err,
2242 const ctype<char_type>& __ct) const
2243{
2244 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 4);
2245 if (!(__err & ios_base::failbit))
2246 __y = __t - 1900;
2247}
2248
2249template <class _CharT, class _InputIterator>
2250void
2251time_get<_CharT, _InputIterator>::__get_hour(int& __h,
2252 iter_type& __b, iter_type __e,
2253 ios_base::iostate& __err,
2254 const ctype<char_type>& __ct) const
2255{
2256 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2257 if (!(__err & ios_base::failbit) && __t <= 23)
2258 __h = __t;
2259 else
2260 __err |= ios_base::failbit;
2261}
2262
2263template <class _CharT, class _InputIterator>
2264void
2265time_get<_CharT, _InputIterator>::__get_12_hour(int& __h,
2266 iter_type& __b, iter_type __e,
2267 ios_base::iostate& __err,
2268 const ctype<char_type>& __ct) const
2269{
2270 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2271 if (!(__err & ios_base::failbit) && 1 <= __t && __t <= 12)
2272 __h = __t;
2273 else
2274 __err |= ios_base::failbit;
2275}
2276
2277template <class _CharT, class _InputIterator>
2278void
2279time_get<_CharT, _InputIterator>::__get_minute(int& __m,
2280 iter_type& __b, iter_type __e,
2281 ios_base::iostate& __err,
2282 const ctype<char_type>& __ct) const
2283{
2284 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2285 if (!(__err & ios_base::failbit) && __t <= 59)
2286 __m = __t;
2287 else
2288 __err |= ios_base::failbit;
2289}
2290
2291template <class _CharT, class _InputIterator>
2292void
2293time_get<_CharT, _InputIterator>::__get_second(int& __s,
2294 iter_type& __b, iter_type __e,
2295 ios_base::iostate& __err,
2296 const ctype<char_type>& __ct) const
2297{
2298 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2299 if (!(__err & ios_base::failbit) && __t <= 60)
2300 __s = __t;
2301 else
2302 __err |= ios_base::failbit;
2303}
2304
2305template <class _CharT, class _InputIterator>
2306void
2307time_get<_CharT, _InputIterator>::__get_weekday(int& __w,
2308 iter_type& __b, iter_type __e,
2309 ios_base::iostate& __err,
2310 const ctype<char_type>& __ct) const
2311{
2312 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 1);
2313 if (!(__err & ios_base::failbit) && __t <= 6)
2314 __w = __t;
2315 else
2316 __err |= ios_base::failbit;
2317}
2318
2319template <class _CharT, class _InputIterator>
2320void
2321time_get<_CharT, _InputIterator>::__get_day_year_num(int& __d,
2322 iter_type& __b, iter_type __e,
2323 ios_base::iostate& __err,
2324 const ctype<char_type>& __ct) const
2325{
2326 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 3);
2327 if (!(__err & ios_base::failbit) && __t <= 365)
2328 __d = __t;
2329 else
2330 __err |= ios_base::failbit;
2331}
2332
2333template <class _CharT, class _InputIterator>
2334void
2335time_get<_CharT, _InputIterator>::__get_white_space(iter_type& __b, iter_type __e,
2336 ios_base::iostate& __err,
2337 const ctype<char_type>& __ct) const
2338{
2339 for (; __b != __e && __ct.is(ctype_base::space, *__b); ++__b)
2340 ;
2341 if (__b == __e)
2342 __err |= ios_base::eofbit;
2343}
2344
2345template <class _CharT, class _InputIterator>
2346void
2347time_get<_CharT, _InputIterator>::__get_am_pm(int& __h,
2348 iter_type& __b, iter_type __e,
2349 ios_base::iostate& __err,
2350 const ctype<char_type>& __ct) const
2351{
2352 const string_type* __ap = this->__am_pm();
2353 if (__ap[0].size() + __ap[1].size() == 0)
2354 {
2355 __err |= ios_base::failbit;
2356 return;
2357 }
Howard Hinnantec3773c2011-12-01 20:21:04 +00002358 ptrdiff_t __i = __scan_keyword(__b, __e, __ap, __ap+2, __ct, __err, false) - __ap;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002359 if (__i == 0 && __h == 12)
2360 __h = 0;
2361 else if (__i == 1 && __h < 12)
2362 __h += 12;
2363}
2364
2365template <class _CharT, class _InputIterator>
2366void
2367time_get<_CharT, _InputIterator>::__get_percent(iter_type& __b, iter_type __e,
2368 ios_base::iostate& __err,
2369 const ctype<char_type>& __ct) const
2370{
2371 if (__b == __e)
2372 {
2373 __err |= ios_base::eofbit | ios_base::failbit;
2374 return;
2375 }
2376 if (__ct.narrow(*__b, 0) != '%')
2377 __err |= ios_base::failbit;
2378 else if(++__b == __e)
2379 __err |= ios_base::eofbit;
2380}
2381
2382// time_get end primatives
2383
2384template <class _CharT, class _InputIterator>
2385_InputIterator
2386time_get<_CharT, _InputIterator>::get(iter_type __b, iter_type __e,
2387 ios_base& __iob,
2388 ios_base::iostate& __err, tm* __tm,
2389 const char_type* __fmtb, const char_type* __fmte) const
2390{
2391 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2392 __err = ios_base::goodbit;
2393 while (__fmtb != __fmte && __err == ios_base::goodbit)
2394 {
2395 if (__b == __e)
2396 {
2397 __err = ios_base::failbit;
2398 break;
2399 }
2400 if (__ct.narrow(*__fmtb, 0) == '%')
2401 {
2402 if (++__fmtb == __fmte)
2403 {
2404 __err = ios_base::failbit;
2405 break;
2406 }
2407 char __cmd = __ct.narrow(*__fmtb, 0);
2408 char __opt = '\0';
2409 if (__cmd == 'E' || __cmd == '0')
2410 {
2411 if (++__fmtb == __fmte)
2412 {
2413 __err = ios_base::failbit;
2414 break;
2415 }
2416 __opt = __cmd;
2417 __cmd = __ct.narrow(*__fmtb, 0);
2418 }
2419 __b = do_get(__b, __e, __iob, __err, __tm, __cmd, __opt);
2420 ++__fmtb;
2421 }
2422 else if (__ct.is(ctype_base::space, *__fmtb))
2423 {
2424 for (++__fmtb; __fmtb != __fmte && __ct.is(ctype_base::space, *__fmtb); ++__fmtb)
2425 ;
2426 for ( ; __b != __e && __ct.is(ctype_base::space, *__b); ++__b)
2427 ;
2428 }
2429 else if (__ct.toupper(*__b) == __ct.toupper(*__fmtb))
2430 {
2431 ++__b;
2432 ++__fmtb;
2433 }
2434 else
2435 __err = ios_base::failbit;
2436 }
2437 if (__b == __e)
2438 __err |= ios_base::eofbit;
2439 return __b;
2440}
2441
2442template <class _CharT, class _InputIterator>
2443typename time_get<_CharT, _InputIterator>::dateorder
2444time_get<_CharT, _InputIterator>::do_date_order() const
2445{
2446 return mdy;
2447}
2448
2449template <class _CharT, class _InputIterator>
2450_InputIterator
2451time_get<_CharT, _InputIterator>::do_get_time(iter_type __b, iter_type __e,
2452 ios_base& __iob,
2453 ios_base::iostate& __err,
2454 tm* __tm) const
2455{
2456 const char_type __fmt[] = {'%', 'H', ':', '%', 'M', ':', '%', 'S'};
2457 return get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2458}
2459
2460template <class _CharT, class _InputIterator>
2461_InputIterator
2462time_get<_CharT, _InputIterator>::do_get_date(iter_type __b, iter_type __e,
2463 ios_base& __iob,
2464 ios_base::iostate& __err,
2465 tm* __tm) const
2466{
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002467 const string_type& __fmt = this->__x();
2468 return get(__b, __e, __iob, __err, __tm, __fmt.data(), __fmt.data() + __fmt.size());
2469}
2470
2471template <class _CharT, class _InputIterator>
2472_InputIterator
2473time_get<_CharT, _InputIterator>::do_get_weekday(iter_type __b, iter_type __e,
2474 ios_base& __iob,
2475 ios_base::iostate& __err,
2476 tm* __tm) const
2477{
2478 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2479 __get_weekdayname(__tm->tm_wday, __b, __e, __err, __ct);
2480 return __b;
2481}
2482
2483template <class _CharT, class _InputIterator>
2484_InputIterator
2485time_get<_CharT, _InputIterator>::do_get_monthname(iter_type __b, iter_type __e,
2486 ios_base& __iob,
2487 ios_base::iostate& __err,
2488 tm* __tm) const
2489{
2490 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2491 __get_monthname(__tm->tm_mon, __b, __e, __err, __ct);
2492 return __b;
2493}
2494
2495template <class _CharT, class _InputIterator>
2496_InputIterator
2497time_get<_CharT, _InputIterator>::do_get_year(iter_type __b, iter_type __e,
2498 ios_base& __iob,
2499 ios_base::iostate& __err,
2500 tm* __tm) const
2501{
2502 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2503 __get_year(__tm->tm_year, __b, __e, __err, __ct);
2504 return __b;
2505}
2506
2507template <class _CharT, class _InputIterator>
2508_InputIterator
2509time_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
2510 ios_base& __iob,
2511 ios_base::iostate& __err, tm* __tm,
2512 char __fmt, char) const
2513{
2514 __err = ios_base::goodbit;
2515 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2516 switch (__fmt)
2517 {
2518 case 'a':
2519 case 'A':
2520 __get_weekdayname(__tm->tm_wday, __b, __e, __err, __ct);
2521 break;
2522 case 'b':
2523 case 'B':
2524 case 'h':
2525 __get_monthname(__tm->tm_mon, __b, __e, __err, __ct);
2526 break;
2527 case 'c':
2528 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002529 const string_type& __fm = this->__c();
2530 __b = get(__b, __e, __iob, __err, __tm, __fm.data(), __fm.data() + __fm.size());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002531 }
2532 break;
2533 case 'd':
2534 case 'e':
2535 __get_day(__tm->tm_mday, __b, __e, __err, __ct);
2536 break;
2537 case 'D':
2538 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002539 const char_type __fm[] = {'%', 'm', '/', '%', 'd', '/', '%', 'y'};
2540 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm)/sizeof(__fm[0]));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002541 }
2542 break;
Howard Hinnant506b3642011-04-10 17:54:14 +00002543 case 'F':
2544 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002545 const char_type __fm[] = {'%', 'Y', '-', '%', 'm', '-', '%', 'd'};
2546 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm)/sizeof(__fm[0]));
Howard Hinnant506b3642011-04-10 17:54:14 +00002547 }
2548 break;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002549 case 'H':
2550 __get_hour(__tm->tm_hour, __b, __e, __err, __ct);
2551 break;
2552 case 'I':
2553 __get_12_hour(__tm->tm_hour, __b, __e, __err, __ct);
2554 break;
2555 case 'j':
2556 __get_day_year_num(__tm->tm_yday, __b, __e, __err, __ct);
2557 break;
2558 case 'm':
2559 __get_month(__tm->tm_mon, __b, __e, __err, __ct);
2560 break;
2561 case 'M':
2562 __get_minute(__tm->tm_min, __b, __e, __err, __ct);
2563 break;
2564 case 'n':
2565 case 't':
2566 __get_white_space(__b, __e, __err, __ct);
2567 break;
2568 case 'p':
2569 __get_am_pm(__tm->tm_hour, __b, __e, __err, __ct);
2570 break;
2571 case 'r':
2572 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002573 const char_type __fm[] = {'%', 'I', ':', '%', 'M', ':', '%', 'S', ' ', '%', 'p'};
2574 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm)/sizeof(__fm[0]));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002575 }
2576 break;
2577 case 'R':
2578 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002579 const char_type __fm[] = {'%', 'H', ':', '%', 'M'};
2580 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm)/sizeof(__fm[0]));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002581 }
2582 break;
2583 case 'S':
2584 __get_second(__tm->tm_sec, __b, __e, __err, __ct);
2585 break;
2586 case 'T':
2587 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002588 const char_type __fm[] = {'%', 'H', ':', '%', 'M', ':', '%', 'S'};
2589 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm)/sizeof(__fm[0]));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002590 }
2591 break;
2592 case 'w':
2593 __get_weekday(__tm->tm_wday, __b, __e, __err, __ct);
2594 break;
2595 case 'x':
2596 return do_get_date(__b, __e, __iob, __err, __tm);
2597 case 'X':
2598 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002599 const string_type& __fm = this->__X();
2600 __b = get(__b, __e, __iob, __err, __tm, __fm.data(), __fm.data() + __fm.size());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002601 }
2602 break;
2603 case 'y':
2604 __get_year(__tm->tm_year, __b, __e, __err, __ct);
2605 break;
2606 case 'Y':
2607 __get_year4(__tm->tm_year, __b, __e, __err, __ct);
2608 break;
2609 case '%':
2610 __get_percent(__b, __e, __err, __ct);
2611 break;
2612 default:
2613 __err |= ios_base::failbit;
2614 }
2615 return __b;
2616}
2617
Howard Hinnantff926772012-11-06 21:08:48 +00002618_LIBCPP_EXTERN_TEMPLATE(class time_get<char>)
2619_LIBCPP_EXTERN_TEMPLATE(class time_get<wchar_t>)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002620
2621class __time_get
2622{
2623protected:
2624 locale_t __loc_;
2625
2626 __time_get(const char* __nm);
2627 __time_get(const string& __nm);
2628 ~__time_get();
2629};
2630
2631template <class _CharT>
2632class __time_get_storage
2633 : public __time_get
2634{
2635protected:
2636 typedef basic_string<_CharT> string_type;
2637
2638 string_type __weeks_[14];
2639 string_type __months_[24];
2640 string_type __am_pm_[2];
2641 string_type __c_;
2642 string_type __r_;
2643 string_type __x_;
2644 string_type __X_;
2645
2646 explicit __time_get_storage(const char* __nm);
2647 explicit __time_get_storage(const string& __nm);
2648
2649 _LIBCPP_ALWAYS_INLINE ~__time_get_storage() {}
2650
2651 time_base::dateorder __do_date_order() const;
2652
2653private:
2654 void init(const ctype<_CharT>&);
2655 string_type __analyze(char __fmt, const ctype<_CharT>&);
2656};
2657
2658template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00002659class _LIBCPP_VISIBLE time_get_byname
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002660 : public time_get<_CharT, _InputIterator>,
2661 private __time_get_storage<_CharT>
2662{
2663public:
2664 typedef time_base::dateorder dateorder;
2665 typedef _InputIterator iter_type;
2666 typedef _CharT char_type;
2667 typedef basic_string<char_type> string_type;
2668
Howard Hinnant82894812010-09-22 16:48:34 +00002669 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002670 explicit time_get_byname(const char* __nm, size_t __refs = 0)
2671 : time_get<_CharT, _InputIterator>(__refs),
2672 __time_get_storage<_CharT>(__nm) {}
Howard Hinnant82894812010-09-22 16:48:34 +00002673 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002674 explicit time_get_byname(const string& __nm, size_t __refs = 0)
2675 : time_get<_CharT, _InputIterator>(__refs),
2676 __time_get_storage<_CharT>(__nm) {}
2677
2678protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002679 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002680 ~time_get_byname() {}
2681
Howard Hinnant82894812010-09-22 16:48:34 +00002682 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002683 virtual dateorder do_date_order() const {return this->__do_date_order();}
2684private:
Howard Hinnant82894812010-09-22 16:48:34 +00002685 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002686 virtual const string_type* __weeks() const {return this->__weeks_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002687 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002688 virtual const string_type* __months() const {return this->__months_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002689 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002690 virtual const string_type* __am_pm() const {return this->__am_pm_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002691 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002692 virtual const string_type& __c() const {return this->__c_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002693 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002694 virtual const string_type& __r() const {return this->__r_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002695 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002696 virtual const string_type& __x() const {return this->__x_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002697 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002698 virtual const string_type& __X() const {return this->__X_;}
2699};
2700
Howard Hinnantff926772012-11-06 21:08:48 +00002701_LIBCPP_EXTERN_TEMPLATE(class time_get_byname<char>)
2702_LIBCPP_EXTERN_TEMPLATE(class time_get_byname<wchar_t>)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002703
2704class __time_put
2705{
2706 locale_t __loc_;
2707protected:
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00002708 _LIBCPP_ALWAYS_INLINE __time_put() : __loc_(_LIBCPP_GET_C_LOCALE) {}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002709 __time_put(const char* __nm);
2710 __time_put(const string& __nm);
2711 ~__time_put();
2712 void __do_put(char* __nb, char*& __ne, const tm* __tm,
2713 char __fmt, char __mod) const;
2714 void __do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
2715 char __fmt, char __mod) const;
2716};
2717
2718template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00002719class _LIBCPP_VISIBLE time_put
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002720 : public locale::facet,
2721 private __time_put
2722{
2723public:
2724 typedef _CharT char_type;
2725 typedef _OutputIterator iter_type;
2726
2727 _LIBCPP_ALWAYS_INLINE
2728 explicit time_put(size_t __refs = 0)
2729 : locale::facet(__refs) {}
2730
2731 iter_type put(iter_type __s, ios_base& __iob, char_type __fl, const tm* __tm,
2732 const char_type* __pb, const char_type* __pe) const;
2733
2734 _LIBCPP_ALWAYS_INLINE
2735 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
2736 const tm* __tm, char __fmt, char __mod = 0) const
2737 {
2738 return do_put(__s, __iob, __fl, __tm, __fmt, __mod);
2739 }
2740
2741 static locale::id id;
2742
2743protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002744 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002745 ~time_put() {}
2746 virtual iter_type do_put(iter_type __s, ios_base&, char_type, const tm* __tm,
2747 char __fmt, char __mod) const;
2748
Howard Hinnant82894812010-09-22 16:48:34 +00002749 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002750 explicit time_put(const char* __nm, size_t __refs)
2751 : locale::facet(__refs),
2752 __time_put(__nm) {}
Howard Hinnant82894812010-09-22 16:48:34 +00002753 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002754 explicit time_put(const string& __nm, size_t __refs)
2755 : locale::facet(__refs),
2756 __time_put(__nm) {}
2757};
2758
2759template <class _CharT, class _OutputIterator>
2760locale::id
2761time_put<_CharT, _OutputIterator>::id;
2762
2763template <class _CharT, class _OutputIterator>
2764_OutputIterator
2765time_put<_CharT, _OutputIterator>::put(iter_type __s, ios_base& __iob,
2766 char_type __fl, const tm* __tm,
2767 const char_type* __pb,
2768 const char_type* __pe) const
2769{
2770 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2771 for (; __pb != __pe; ++__pb)
2772 {
2773 if (__ct.narrow(*__pb, 0) == '%')
2774 {
2775 if (++__pb == __pe)
2776 {
2777 *__s++ = __pb[-1];
2778 break;
2779 }
2780 char __mod = 0;
2781 char __fmt = __ct.narrow(*__pb, 0);
2782 if (__fmt == 'E' || __fmt == 'O')
2783 {
2784 if (++__pb == __pe)
2785 {
2786 *__s++ = __pb[-2];
2787 *__s++ = __pb[-1];
2788 break;
2789 }
2790 __mod = __fmt;
2791 __fmt = __ct.narrow(*__pb, 0);
2792 }
2793 __s = do_put(__s, __iob, __fl, __tm, __fmt, __mod);
2794 }
2795 else
2796 *__s++ = *__pb;
2797 }
2798 return __s;
2799}
2800
2801template <class _CharT, class _OutputIterator>
2802_OutputIterator
Howard Hinnantec3773c2011-12-01 20:21:04 +00002803time_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002804 char_type, const tm* __tm,
2805 char __fmt, char __mod) const
2806{
2807 char_type __nar[100];
2808 char_type* __nb = __nar;
2809 char_type* __ne = __nb + 100;
2810 __do_put(__nb, __ne, __tm, __fmt, __mod);
Howard Hinnant0949eed2011-06-30 21:18:19 +00002811 return _VSTD::copy(__nb, __ne, __s);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002812}
2813
Howard Hinnantff926772012-11-06 21:08:48 +00002814_LIBCPP_EXTERN_TEMPLATE(class time_put<char>)
2815_LIBCPP_EXTERN_TEMPLATE(class time_put<wchar_t>)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002816
2817template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00002818class _LIBCPP_VISIBLE time_put_byname
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002819 : public time_put<_CharT, _OutputIterator>
2820{
2821public:
2822 _LIBCPP_ALWAYS_INLINE
2823 explicit time_put_byname(const char* __nm, size_t __refs = 0)
2824 : time_put<_CharT, _OutputIterator>(__nm, __refs) {}
2825
2826 _LIBCPP_ALWAYS_INLINE
2827 explicit time_put_byname(const string& __nm, size_t __refs = 0)
2828 : time_put<_CharT, _OutputIterator>(__nm, __refs) {}
2829
2830protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002831 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002832 ~time_put_byname() {}
2833};
2834
Howard Hinnantff926772012-11-06 21:08:48 +00002835_LIBCPP_EXTERN_TEMPLATE(class time_put_byname<char>)
2836_LIBCPP_EXTERN_TEMPLATE(class time_put_byname<wchar_t>)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002837
2838// money_base
2839
Howard Hinnant82894812010-09-22 16:48:34 +00002840class _LIBCPP_VISIBLE money_base
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002841{
2842public:
2843 enum part {none, space, symbol, sign, value};
2844 struct pattern {char field[4];};
2845
2846 _LIBCPP_ALWAYS_INLINE money_base() {}
2847};
2848
2849// moneypunct
2850
2851template <class _CharT, bool _International = false>
Howard Hinnant82894812010-09-22 16:48:34 +00002852class _LIBCPP_VISIBLE moneypunct
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002853 : public locale::facet,
2854 public money_base
2855{
2856public:
2857 typedef _CharT char_type;
2858 typedef basic_string<char_type> string_type;
2859
Howard Hinnant82894812010-09-22 16:48:34 +00002860 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002861 explicit moneypunct(size_t __refs = 0)
2862 : locale::facet(__refs) {}
2863
2864 _LIBCPP_ALWAYS_INLINE char_type decimal_point() const {return do_decimal_point();}
2865 _LIBCPP_ALWAYS_INLINE char_type thousands_sep() const {return do_thousands_sep();}
2866 _LIBCPP_ALWAYS_INLINE string grouping() const {return do_grouping();}
2867 _LIBCPP_ALWAYS_INLINE string_type curr_symbol() const {return do_curr_symbol();}
2868 _LIBCPP_ALWAYS_INLINE string_type positive_sign() const {return do_positive_sign();}
2869 _LIBCPP_ALWAYS_INLINE string_type negative_sign() const {return do_negative_sign();}
2870 _LIBCPP_ALWAYS_INLINE int frac_digits() const {return do_frac_digits();}
2871 _LIBCPP_ALWAYS_INLINE pattern pos_format() const {return do_pos_format();}
2872 _LIBCPP_ALWAYS_INLINE pattern neg_format() const {return do_neg_format();}
2873
2874 static locale::id id;
2875 static const bool intl = _International;
2876
2877protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002878 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002879 ~moneypunct() {}
2880
2881 virtual char_type do_decimal_point() const {return numeric_limits<char_type>::max();}
2882 virtual char_type do_thousands_sep() const {return numeric_limits<char_type>::max();}
2883 virtual string do_grouping() const {return string();}
2884 virtual string_type do_curr_symbol() const {return string_type();}
2885 virtual string_type do_positive_sign() const {return string_type();}
2886 virtual string_type do_negative_sign() const {return string_type(1, '-');}
2887 virtual int do_frac_digits() const {return 0;}
2888 virtual pattern do_pos_format() const
Howard Hinnant9bae2a92012-11-06 21:48:33 +00002889 {pattern __p = {{symbol, sign, none, value}}; return __p;}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002890 virtual pattern do_neg_format() const
Howard Hinnant9bae2a92012-11-06 21:48:33 +00002891 {pattern __p = {{symbol, sign, none, value}}; return __p;}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002892};
2893
2894template <class _CharT, bool _International>
2895locale::id
2896moneypunct<_CharT, _International>::id;
2897
Howard Hinnantff926772012-11-06 21:08:48 +00002898_LIBCPP_EXTERN_TEMPLATE(class moneypunct<char, false>)
2899_LIBCPP_EXTERN_TEMPLATE(class moneypunct<char, true>)
2900_LIBCPP_EXTERN_TEMPLATE(class moneypunct<wchar_t, false>)
2901_LIBCPP_EXTERN_TEMPLATE(class moneypunct<wchar_t, true>)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002902
2903// moneypunct_byname
2904
2905template <class _CharT, bool _International = false>
Howard Hinnant82894812010-09-22 16:48:34 +00002906class _LIBCPP_VISIBLE moneypunct_byname
2907 : public moneypunct<_CharT, _International>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002908{
2909public:
2910 typedef money_base::pattern pattern;
2911 typedef _CharT char_type;
2912 typedef basic_string<char_type> string_type;
2913
2914 _LIBCPP_ALWAYS_INLINE
2915 explicit moneypunct_byname(const char* __nm, size_t __refs = 0)
2916 : moneypunct<_CharT, _International>(__refs) {init(__nm);}
2917
2918 _LIBCPP_ALWAYS_INLINE
2919 explicit moneypunct_byname(const string& __nm, size_t __refs = 0)
2920 : moneypunct<_CharT, _International>(__refs) {init(__nm.c_str());}
2921
2922protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002923 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002924 ~moneypunct_byname() {}
2925
2926 virtual char_type do_decimal_point() const {return __decimal_point_;}
2927 virtual char_type do_thousands_sep() const {return __thousands_sep_;}
2928 virtual string do_grouping() const {return __grouping_;}
2929 virtual string_type do_curr_symbol() const {return __curr_symbol_;}
2930 virtual string_type do_positive_sign() const {return __positive_sign_;}
2931 virtual string_type do_negative_sign() const {return __negative_sign_;}
2932 virtual int do_frac_digits() const {return __frac_digits_;}
2933 virtual pattern do_pos_format() const {return __pos_format_;}
2934 virtual pattern do_neg_format() const {return __neg_format_;}
2935
2936private:
2937 char_type __decimal_point_;
2938 char_type __thousands_sep_;
2939 string __grouping_;
2940 string_type __curr_symbol_;
2941 string_type __positive_sign_;
2942 string_type __negative_sign_;
2943 int __frac_digits_;
2944 pattern __pos_format_;
2945 pattern __neg_format_;
2946
2947 void init(const char*);
2948};
2949
2950template<> void moneypunct_byname<char, false>::init(const char*);
2951template<> void moneypunct_byname<char, true>::init(const char*);
2952template<> void moneypunct_byname<wchar_t, false>::init(const char*);
2953template<> void moneypunct_byname<wchar_t, true>::init(const char*);
2954
Howard Hinnantff926772012-11-06 21:08:48 +00002955_LIBCPP_EXTERN_TEMPLATE(class moneypunct_byname<char, false>)
2956_LIBCPP_EXTERN_TEMPLATE(class moneypunct_byname<char, true>)
2957_LIBCPP_EXTERN_TEMPLATE(class moneypunct_byname<wchar_t, false>)
2958_LIBCPP_EXTERN_TEMPLATE(class moneypunct_byname<wchar_t, true>)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002959
2960// money_get
2961
2962template <class _CharT>
2963class __money_get
2964{
2965protected:
2966 typedef _CharT char_type;
2967 typedef basic_string<char_type> string_type;
2968
2969 _LIBCPP_ALWAYS_INLINE __money_get() {}
2970
2971 static void __gather_info(bool __intl, const locale& __loc,
2972 money_base::pattern& __pat, char_type& __dp,
2973 char_type& __ts, string& __grp,
2974 string_type& __sym, string_type& __psn,
2975 string_type& __nsn, int& __fd);
2976};
2977
2978template <class _CharT>
2979void
2980__money_get<_CharT>::__gather_info(bool __intl, const locale& __loc,
2981 money_base::pattern& __pat, char_type& __dp,
2982 char_type& __ts, string& __grp,
2983 string_type& __sym, string_type& __psn,
2984 string_type& __nsn, int& __fd)
2985{
2986 if (__intl)
2987 {
2988 const moneypunct<char_type, true>& __mp =
2989 use_facet<moneypunct<char_type, true> >(__loc);
2990 __pat = __mp.neg_format();
2991 __nsn = __mp.negative_sign();
2992 __psn = __mp.positive_sign();
2993 __dp = __mp.decimal_point();
2994 __ts = __mp.thousands_sep();
2995 __grp = __mp.grouping();
2996 __sym = __mp.curr_symbol();
2997 __fd = __mp.frac_digits();
2998 }
2999 else
3000 {
3001 const moneypunct<char_type, false>& __mp =
3002 use_facet<moneypunct<char_type, false> >(__loc);
3003 __pat = __mp.neg_format();
3004 __nsn = __mp.negative_sign();
3005 __psn = __mp.positive_sign();
3006 __dp = __mp.decimal_point();
3007 __ts = __mp.thousands_sep();
3008 __grp = __mp.grouping();
3009 __sym = __mp.curr_symbol();
3010 __fd = __mp.frac_digits();
3011 }
3012}
3013
Howard Hinnantff926772012-11-06 21:08:48 +00003014_LIBCPP_EXTERN_TEMPLATE(class __money_get<char>)
3015_LIBCPP_EXTERN_TEMPLATE(class __money_get<wchar_t>)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003016
3017template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00003018class _LIBCPP_VISIBLE money_get
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003019 : public locale::facet,
3020 private __money_get<_CharT>
3021{
3022public:
3023 typedef _CharT char_type;
3024 typedef _InputIterator iter_type;
3025 typedef basic_string<char_type> string_type;
3026
3027 _LIBCPP_ALWAYS_INLINE
3028 explicit money_get(size_t __refs = 0)
3029 : locale::facet(__refs) {}
3030
3031 _LIBCPP_ALWAYS_INLINE
3032 iter_type get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob,
3033 ios_base::iostate& __err, long double& __v) const
3034 {
3035 return do_get(__b, __e, __intl, __iob, __err, __v);
3036 }
3037
3038 _LIBCPP_ALWAYS_INLINE
3039 iter_type get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob,
3040 ios_base::iostate& __err, string_type& __v) const
3041 {
3042 return do_get(__b, __e, __intl, __iob, __err, __v);
3043 }
3044
3045 static locale::id id;
3046
3047protected:
3048
Howard Hinnant82894812010-09-22 16:48:34 +00003049 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003050 ~money_get() {}
Howard Hinnant324bb032010-08-22 00:02:43 +00003051
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003052 virtual iter_type do_get(iter_type __b, iter_type __e, bool __intl,
3053 ios_base& __iob, ios_base::iostate& __err,
3054 long double& __v) const;
3055 virtual iter_type do_get(iter_type __b, iter_type __e, bool __intl,
3056 ios_base& __iob, ios_base::iostate& __err,
3057 string_type& __v) const;
3058
3059private:
3060 static bool __do_get(iter_type& __b, iter_type __e,
3061 bool __intl, const locale& __loc,
3062 ios_base::fmtflags __flags, ios_base::iostate& __err,
3063 bool& __neg, const ctype<char_type>& __ct,
3064 unique_ptr<char_type, void(*)(void*)>& __wb,
3065 char_type*& __wn, char_type* __we);
3066};
3067
3068template <class _CharT, class _InputIterator>
3069locale::id
3070money_get<_CharT, _InputIterator>::id;
3071
3072void __do_nothing(void*);
3073
3074template <class _Tp>
3075_LIBCPP_HIDDEN
3076void
3077__double_or_nothing(unique_ptr<_Tp, void(*)(void*)>& __b, _Tp*& __n, _Tp*& __e)
3078{
3079 bool __owns = __b.get_deleter() != __do_nothing;
Howard Hinnantec3773c2011-12-01 20:21:04 +00003080 size_t __cur_cap = static_cast<size_t>(__e-__b.get()) * sizeof(_Tp);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003081 size_t __new_cap = __cur_cap < numeric_limits<size_t>::max() / 2 ?
3082 2 * __cur_cap : numeric_limits<size_t>::max();
Howard Hinnantec3773c2011-12-01 20:21:04 +00003083 size_t __n_off = static_cast<size_t>(__n - __b.get());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003084 _Tp* __t = (_Tp*)realloc(__owns ? __b.get() : 0, __new_cap);
3085 if (__t == 0)
3086 __throw_bad_alloc();
3087 if (__owns)
3088 __b.release();
3089 __b = unique_ptr<_Tp, void(*)(void*)>(__t, free);
3090 __new_cap /= sizeof(_Tp);
3091 __n = __b.get() + __n_off;
3092 __e = __b.get() + __new_cap;
3093}
3094
3095// true == success
3096template <class _CharT, class _InputIterator>
3097bool
3098money_get<_CharT, _InputIterator>::__do_get(iter_type& __b, iter_type __e,
3099 bool __intl, const locale& __loc,
3100 ios_base::fmtflags __flags,
3101 ios_base::iostate& __err,
3102 bool& __neg,
3103 const ctype<char_type>& __ct,
3104 unique_ptr<char_type, void(*)(void*)>& __wb,
3105 char_type*& __wn, char_type* __we)
3106{
3107 const unsigned __bz = 100;
3108 unsigned __gbuf[__bz];
3109 unique_ptr<unsigned, void(*)(void*)> __gb(__gbuf, __do_nothing);
3110 unsigned* __gn = __gb.get();
3111 unsigned* __ge = __gn + __bz;
3112 money_base::pattern __pat;
3113 char_type __dp;
3114 char_type __ts;
3115 string __grp;
3116 string_type __sym;
3117 string_type __psn;
3118 string_type __nsn;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00003119 // Capture the spaces read into money_base::{space,none} so they
3120 // can be compared to initial spaces in __sym.
3121 string_type __spaces;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003122 int __fd;
3123 __money_get<_CharT>::__gather_info(__intl, __loc, __pat, __dp, __ts, __grp,
3124 __sym, __psn, __nsn, __fd);
3125 const string_type* __trailing_sign = 0;
3126 __wn = __wb.get();
3127 for (unsigned __p = 0; __p < 4 && __b != __e; ++__p)
3128 {
3129 switch (__pat.field[__p])
3130 {
3131 case money_base::space:
3132 if (__p != 3)
3133 {
3134 if (__ct.is(ctype_base::space, *__b))
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00003135 __spaces.push_back(*__b++);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003136 else
3137 {
3138 __err |= ios_base::failbit;
3139 return false;
3140 }
3141 }
Howard Hinnant324bb032010-08-22 00:02:43 +00003142 // drop through
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003143 case money_base::none:
3144 if (__p != 3)
3145 {
3146 while (__b != __e && __ct.is(ctype_base::space, *__b))
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00003147 __spaces.push_back(*__b++);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003148 }
3149 break;
3150 case money_base::sign:
3151 if (__psn.size() + __nsn.size() > 0)
3152 {
3153 if (__psn.size() == 0 || __nsn.size() == 0)
3154 { // sign is optional
3155 if (__psn.size() > 0)
3156 { // __nsn.size() == 0
3157 if (*__b == __psn[0])
3158 {
3159 ++__b;
3160 if (__psn.size() > 1)
3161 __trailing_sign = &__psn;
3162 }
3163 else
3164 __neg = true;
3165 }
3166 else if (*__b == __nsn[0]) // __nsn.size() > 0 && __psn.size() == 0
3167 {
3168 ++__b;
3169 __neg = true;
3170 if (__nsn.size() > 1)
3171 __trailing_sign = &__nsn;
3172 }
3173 }
3174 else // sign is required
3175 {
3176 if (*__b == __psn[0])
3177 {
3178 ++__b;
3179 if (__psn.size() > 1)
3180 __trailing_sign = &__psn;
3181 }
3182 else if (*__b == __nsn[0])
3183 {
3184 ++__b;
3185 __neg = true;
3186 if (__nsn.size() > 1)
3187 __trailing_sign = &__nsn;
3188 }
3189 else
3190 {
3191 __err |= ios_base::failbit;
3192 return false;
3193 }
3194 }
3195 }
3196 break;
3197 case money_base::symbol:
3198 {
3199 bool __more_needed = __trailing_sign ||
3200 (__p < 2) ||
3201 (__p == 2 && __pat.field[3] != static_cast<char>(money_base::none));
3202 bool __sb = __flags & ios_base::showbase;
3203 if (__sb || __more_needed)
3204 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00003205 typename string_type::const_iterator __sym_space_end = __sym.begin();
3206 if (__p > 0 && (__pat.field[__p - 1] == money_base::none ||
3207 __pat.field[__p - 1] == money_base::space)) {
3208 // Match spaces we've already read against spaces at
3209 // the beginning of __sym.
3210 while (__sym_space_end != __sym.end() &&
3211 __ct.is(ctype_base::space, *__sym_space_end))
3212 ++__sym_space_end;
3213 const size_t __num_spaces = __sym_space_end - __sym.begin();
3214 if (__num_spaces > __spaces.size() ||
3215 !equal(__spaces.end() - __num_spaces, __spaces.end(),
3216 __sym.begin())) {
3217 // No match. Put __sym_space_end back at the
3218 // beginning of __sym, which will prevent a
3219 // match in the next loop.
3220 __sym_space_end = __sym.begin();
3221 }
3222 }
3223 typename string_type::const_iterator __sym_curr_char = __sym_space_end;
3224 while (__sym_curr_char != __sym.end() && __b != __e &&
3225 *__b == *__sym_curr_char) {
3226 ++__b;
3227 ++__sym_curr_char;
3228 }
3229 if (__sb && __sym_curr_char != __sym.end())
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003230 {
3231 __err |= ios_base::failbit;
3232 return false;
3233 }
3234 }
3235 }
3236 break;
3237 case money_base::value:
3238 {
3239 unsigned __ng = 0;
3240 for (; __b != __e; ++__b)
3241 {
3242 char_type __c = *__b;
3243 if (__ct.is(ctype_base::digit, __c))
3244 {
3245 if (__wn == __we)
3246 __double_or_nothing(__wb, __wn, __we);
3247 *__wn++ = __c;
3248 ++__ng;
3249 }
3250 else if (__grp.size() > 0 && __ng > 0 && __c == __ts)
3251 {
3252 if (__gn == __ge)
3253 __double_or_nothing(__gb, __gn, __ge);
3254 *__gn++ = __ng;
3255 __ng = 0;
3256 }
3257 else
3258 break;
3259 }
3260 if (__gb.get() != __gn && __ng > 0)
3261 {
3262 if (__gn == __ge)
3263 __double_or_nothing(__gb, __gn, __ge);
3264 *__gn++ = __ng;
3265 }
3266 if (__fd > 0)
3267 {
3268 if (__b == __e || *__b != __dp)
3269 {
3270 __err |= ios_base::failbit;
3271 return false;
3272 }
3273 for (++__b; __fd > 0; --__fd, ++__b)
3274 {
3275 if (__b == __e || !__ct.is(ctype_base::digit, *__b))
3276 {
3277 __err |= ios_base::failbit;
3278 return false;
3279 }
3280 if (__wn == __we)
3281 __double_or_nothing(__wb, __wn, __we);
3282 *__wn++ = *__b;
3283 }
3284 }
3285 if (__wn == __wb.get())
3286 {
3287 __err |= ios_base::failbit;
3288 return false;
3289 }
3290 }
3291 break;
3292 }
3293 }
3294 if (__trailing_sign)
3295 {
3296 for (unsigned __i = 1; __i < __trailing_sign->size(); ++__i, ++__b)
3297 {
3298 if (__b == __e || *__b != (*__trailing_sign)[__i])
3299 {
3300 __err |= ios_base::failbit;
3301 return false;
3302 }
3303 }
3304 }
3305 if (__gb.get() != __gn)
3306 {
3307 ios_base::iostate __et = ios_base::goodbit;
3308 __check_grouping(__grp, __gb.get(), __gn, __et);
3309 if (__et)
3310 {
3311 __err |= ios_base::failbit;
3312 return false;
3313 }
3314 }
3315 return true;
3316}
3317
3318template <class _CharT, class _InputIterator>
3319_InputIterator
3320money_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
3321 bool __intl, ios_base& __iob,
3322 ios_base::iostate& __err,
3323 long double& __v) const
3324{
Howard Hinnantec3773c2011-12-01 20:21:04 +00003325 const int __bz = 100;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003326 char_type __wbuf[__bz];
3327 unique_ptr<char_type, void(*)(void*)> __wb(__wbuf, __do_nothing);
3328 char_type* __wn;
3329 char_type* __we = __wbuf + __bz;
3330 locale __loc = __iob.getloc();
3331 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3332 bool __neg = false;
3333 if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct,
3334 __wb, __wn, __we))
3335 {
3336 const char __src[] = "0123456789";
3337 char_type __atoms[sizeof(__src)-1];
3338 __ct.widen(__src, __src + (sizeof(__src)-1), __atoms);
3339 char __nbuf[__bz];
3340 char* __nc = __nbuf;
3341 unique_ptr<char, void(*)(void*)> __h(0, free);
3342 if (__wn - __wb.get() > __bz-2)
3343 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00003344 __h.reset((char*)malloc(static_cast<size_t>(__wn - __wb.get() + 2)));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003345 if (__h.get() == 0)
3346 __throw_bad_alloc();
3347 __nc = __h.get();
3348 }
3349 if (__neg)
3350 *__nc++ = '-';
3351 for (const char_type* __w = __wb.get(); __w < __wn; ++__w, ++__nc)
3352 *__nc = __src[find(__atoms, __atoms+sizeof(__atoms), *__w) - __atoms];
3353 *__nc = char();
3354 if (sscanf(__nbuf, "%Lf", &__v) != 1)
3355 __throw_runtime_error("money_get error");
3356 }
3357 if (__b == __e)
3358 __err |= ios_base::eofbit;
3359 return __b;
3360}
3361
3362template <class _CharT, class _InputIterator>
3363_InputIterator
3364money_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
3365 bool __intl, ios_base& __iob,
3366 ios_base::iostate& __err,
3367 string_type& __v) const
3368{
Howard Hinnantec3773c2011-12-01 20:21:04 +00003369 const int __bz = 100;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003370 char_type __wbuf[__bz];
3371 unique_ptr<char_type, void(*)(void*)> __wb(__wbuf, __do_nothing);
3372 char_type* __wn;
3373 char_type* __we = __wbuf + __bz;
3374 locale __loc = __iob.getloc();
3375 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3376 bool __neg = false;
3377 if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct,
3378 __wb, __wn, __we))
3379 {
3380 __v.clear();
3381 if (__neg)
3382 __v.push_back(__ct.widen('-'));
3383 char_type __z = __ct.widen('0');
3384 char_type* __w;
3385 for (__w = __wb.get(); __w < __wn-1; ++__w)
3386 if (*__w != __z)
3387 break;
3388 __v.append(__w, __wn);
3389 }
3390 if (__b == __e)
3391 __err |= ios_base::eofbit;
3392 return __b;
3393}
3394
Howard Hinnantff926772012-11-06 21:08:48 +00003395_LIBCPP_EXTERN_TEMPLATE(class money_get<char>)
3396_LIBCPP_EXTERN_TEMPLATE(class money_get<wchar_t>)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003397
3398// money_put
3399
3400template <class _CharT>
3401class __money_put
3402{
3403protected:
3404 typedef _CharT char_type;
3405 typedef basic_string<char_type> string_type;
3406
3407 _LIBCPP_ALWAYS_INLINE __money_put() {}
3408
3409 static void __gather_info(bool __intl, bool __neg, const locale& __loc,
3410 money_base::pattern& __pat, char_type& __dp,
3411 char_type& __ts, string& __grp,
3412 string_type& __sym, string_type& __sn,
3413 int& __fd);
3414 static void __format(char_type* __mb, char_type*& __mi, char_type*& __me,
3415 ios_base::fmtflags __flags,
3416 const char_type* __db, const char_type* __de,
3417 const ctype<char_type>& __ct, bool __neg,
3418 const money_base::pattern& __pat, char_type __dp,
3419 char_type __ts, const string& __grp,
3420 const string_type& __sym, const string_type& __sn,
3421 int __fd);
3422};
3423
3424template <class _CharT>
3425void
3426__money_put<_CharT>::__gather_info(bool __intl, bool __neg, const locale& __loc,
3427 money_base::pattern& __pat, char_type& __dp,
3428 char_type& __ts, string& __grp,
3429 string_type& __sym, string_type& __sn,
3430 int& __fd)
3431{
3432 if (__intl)
3433 {
3434 const moneypunct<char_type, true>& __mp =
3435 use_facet<moneypunct<char_type, true> >(__loc);
3436 if (__neg)
3437 {
3438 __pat = __mp.neg_format();
3439 __sn = __mp.negative_sign();
3440 }
3441 else
3442 {
3443 __pat = __mp.pos_format();
3444 __sn = __mp.positive_sign();
3445 }
3446 __dp = __mp.decimal_point();
3447 __ts = __mp.thousands_sep();
3448 __grp = __mp.grouping();
3449 __sym = __mp.curr_symbol();
3450 __fd = __mp.frac_digits();
3451 }
3452 else
3453 {
3454 const moneypunct<char_type, false>& __mp =
3455 use_facet<moneypunct<char_type, false> >(__loc);
3456 if (__neg)
3457 {
3458 __pat = __mp.neg_format();
3459 __sn = __mp.negative_sign();
3460 }
3461 else
3462 {
3463 __pat = __mp.pos_format();
3464 __sn = __mp.positive_sign();
3465 }
3466 __dp = __mp.decimal_point();
3467 __ts = __mp.thousands_sep();
3468 __grp = __mp.grouping();
3469 __sym = __mp.curr_symbol();
3470 __fd = __mp.frac_digits();
3471 }
3472}
3473
3474template <class _CharT>
3475void
3476__money_put<_CharT>::__format(char_type* __mb, char_type*& __mi, char_type*& __me,
3477 ios_base::fmtflags __flags,
3478 const char_type* __db, const char_type* __de,
3479 const ctype<char_type>& __ct, bool __neg,
3480 const money_base::pattern& __pat, char_type __dp,
3481 char_type __ts, const string& __grp,
3482 const string_type& __sym, const string_type& __sn,
3483 int __fd)
3484{
3485 __me = __mb;
3486 for (unsigned __p = 0; __p < 4; ++__p)
3487 {
3488 switch (__pat.field[__p])
3489 {
3490 case money_base::none:
3491 __mi = __me;
3492 break;
3493 case money_base::space:
3494 __mi = __me;
3495 *__me++ = __ct.widen(' ');
3496 break;
3497 case money_base::sign:
3498 if (!__sn.empty())
3499 *__me++ = __sn[0];
3500 break;
3501 case money_base::symbol:
3502 if (!__sym.empty() && (__flags & ios_base::showbase))
Howard Hinnant0949eed2011-06-30 21:18:19 +00003503 __me = _VSTD::copy(__sym.begin(), __sym.end(), __me);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003504 break;
3505 case money_base::value:
3506 {
3507 // remember start of value so we can reverse it
3508 char_type* __t = __me;
3509 // find beginning of digits
3510 if (__neg)
3511 ++__db;
3512 // find end of digits
3513 const char_type* __d;
3514 for (__d = __db; __d < __de; ++__d)
3515 if (!__ct.is(ctype_base::digit, *__d))
3516 break;
3517 // print fractional part
3518 if (__fd > 0)
3519 {
3520 int __f;
3521 for (__f = __fd; __d > __db && __f > 0; --__f)
3522 *__me++ = *--__d;
3523 char_type __z = __f > 0 ? __ct.widen('0') : char_type();
3524 for (; __f > 0; --__f)
3525 *__me++ = __z;
3526 *__me++ = __dp;
3527 }
3528 // print units part
3529 if (__d == __db)
3530 {
3531 *__me++ = __ct.widen('0');
3532 }
3533 else
3534 {
3535 unsigned __ng = 0;
3536 unsigned __ig = 0;
3537 unsigned __gl = __grp.empty() ? numeric_limits<unsigned>::max()
3538 : static_cast<unsigned>(__grp[__ig]);
3539 while (__d != __db)
3540 {
3541 if (__ng == __gl)
3542 {
3543 *__me++ = __ts;
3544 __ng = 0;
3545 if (++__ig < __grp.size())
3546 __gl = __grp[__ig] == numeric_limits<char>::max() ?
3547 numeric_limits<unsigned>::max() :
3548 static_cast<unsigned>(__grp[__ig]);
3549 }
3550 *__me++ = *--__d;
3551 ++__ng;
3552 }
3553 }
3554 // reverse it
3555 reverse(__t, __me);
3556 }
3557 break;
3558 }
3559 }
3560 // print rest of sign, if any
3561 if (__sn.size() > 1)
Howard Hinnant0949eed2011-06-30 21:18:19 +00003562 __me = _VSTD::copy(__sn.begin()+1, __sn.end(), __me);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003563 // set alignment
3564 if ((__flags & ios_base::adjustfield) == ios_base::left)
3565 __mi = __me;
3566 else if ((__flags & ios_base::adjustfield) != ios_base::internal)
3567 __mi = __mb;
3568}
3569
Howard Hinnantff926772012-11-06 21:08:48 +00003570_LIBCPP_EXTERN_TEMPLATE(class __money_put<char>)
3571_LIBCPP_EXTERN_TEMPLATE(class __money_put<wchar_t>)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003572
3573template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00003574class _LIBCPP_VISIBLE money_put
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003575 : public locale::facet,
3576 private __money_put<_CharT>
3577{
3578public:
3579 typedef _CharT char_type;
3580 typedef _OutputIterator iter_type;
3581 typedef basic_string<char_type> string_type;
3582
3583 _LIBCPP_ALWAYS_INLINE
3584 explicit money_put(size_t __refs = 0)
3585 : locale::facet(__refs) {}
3586
3587 _LIBCPP_ALWAYS_INLINE
3588 iter_type put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl,
3589 long double __units) const
3590 {
3591 return do_put(__s, __intl, __iob, __fl, __units);
3592 }
3593
3594 _LIBCPP_ALWAYS_INLINE
3595 iter_type put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl,
3596 const string_type& __digits) const
3597 {
3598 return do_put(__s, __intl, __iob, __fl, __digits);
3599 }
3600
3601 static locale::id id;
3602
3603protected:
Howard Hinnant82894812010-09-22 16:48:34 +00003604 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003605 ~money_put() {}
3606
3607 virtual iter_type do_put(iter_type __s, bool __intl, ios_base& __iob,
3608 char_type __fl, long double __units) const;
3609 virtual iter_type do_put(iter_type __s, bool __intl, ios_base& __iob,
3610 char_type __fl, const string_type& __digits) const;
3611};
3612
3613template <class _CharT, class _OutputIterator>
3614locale::id
3615money_put<_CharT, _OutputIterator>::id;
3616
3617template <class _CharT, class _OutputIterator>
3618_OutputIterator
3619money_put<_CharT, _OutputIterator>::do_put(iter_type __s, bool __intl,
3620 ios_base& __iob, char_type __fl,
3621 long double __units) const
3622{
3623 // convert to char
3624 const size_t __bs = 100;
3625 char __buf[__bs];
3626 char* __bb = __buf;
3627 char_type __digits[__bs];
3628 char_type* __db = __digits;
Howard Hinnantec3773c2011-12-01 20:21:04 +00003629 size_t __n = static_cast<size_t>(snprintf(__bb, __bs, "%.0Lf", __units));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003630 unique_ptr<char, void(*)(void*)> __hn(0, free);
3631 unique_ptr<char_type, void(*)(void*)> __hd(0, free);
3632 // secure memory for digit storage
3633 if (__n > __bs-1)
3634 {
Howard Hinnant866569b2011-09-28 23:39:33 +00003635#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00003636 __n = static_cast<size_t>(asprintf_l(&__bb, _LIBCPP_GET_C_LOCALE, "%.0Lf", __units));
Sean Huntf3907e62011-07-15 05:40:33 +00003637#else
3638 __n = __asprintf_l(&__bb, __cloc(), "%.0Lf", __units);
3639#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003640 if (__bb == 0)
3641 __throw_bad_alloc();
3642 __hn.reset(__bb);
3643 __hd.reset((char_type*)malloc(__n * sizeof(char_type)));
Howard Hinnant05b57d52012-03-07 20:37:43 +00003644 if (__hd == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003645 __throw_bad_alloc();
3646 __db = __hd.get();
3647 }
3648 // gather info
3649 locale __loc = __iob.getloc();
3650 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3651 __ct.widen(__bb, __bb + __n, __db);
3652 bool __neg = __n > 0 && __bb[0] == '-';
3653 money_base::pattern __pat;
3654 char_type __dp;
3655 char_type __ts;
3656 string __grp;
3657 string_type __sym;
3658 string_type __sn;
3659 int __fd;
3660 this->__gather_info(__intl, __neg, __loc, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3661 // secure memory for formatting
3662 char_type __mbuf[__bs];
3663 char_type* __mb = __mbuf;
3664 unique_ptr<char_type, void(*)(void*)> __hw(0, free);
3665 size_t __exn = static_cast<int>(__n) > __fd ?
Howard Hinnantec3773c2011-12-01 20:21:04 +00003666 (__n - static_cast<size_t>(__fd)) * 2 + __sn.size() +
3667 __sym.size() + static_cast<size_t>(__fd) + 1
3668 : __sn.size() + __sym.size() + static_cast<size_t>(__fd) + 2;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003669 if (__exn > __bs)
3670 {
3671 __hw.reset((char_type*)malloc(__exn * sizeof(char_type)));
3672 __mb = __hw.get();
3673 if (__mb == 0)
3674 __throw_bad_alloc();
3675 }
3676 // format
3677 char_type* __mi;
3678 char_type* __me;
3679 this->__format(__mb, __mi, __me, __iob.flags(),
3680 __db, __db + __n, __ct,
3681 __neg, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3682 return __pad_and_output(__s, __mb, __mi, __me, __iob, __fl);
3683}
3684
3685template <class _CharT, class _OutputIterator>
3686_OutputIterator
3687money_put<_CharT, _OutputIterator>::do_put(iter_type __s, bool __intl,
3688 ios_base& __iob, char_type __fl,
3689 const string_type& __digits) const
3690{
3691 // gather info
3692 locale __loc = __iob.getloc();
3693 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3694 bool __neg = __digits.size() > 0 && __digits[0] == __ct.widen('-');
3695 money_base::pattern __pat;
3696 char_type __dp;
3697 char_type __ts;
3698 string __grp;
3699 string_type __sym;
3700 string_type __sn;
3701 int __fd;
3702 this->__gather_info(__intl, __neg, __loc, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3703 // secure memory for formatting
3704 char_type __mbuf[100];
3705 char_type* __mb = __mbuf;
3706 unique_ptr<char_type, void(*)(void*)> __h(0, free);
Howard Hinnantec3773c2011-12-01 20:21:04 +00003707 size_t __exn = static_cast<int>(__digits.size()) > __fd ?
3708 (__digits.size() - static_cast<size_t>(__fd)) * 2 +
3709 __sn.size() + __sym.size() + static_cast<size_t>(__fd) + 1
3710 : __sn.size() + __sym.size() + static_cast<size_t>(__fd) + 2;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003711 if (__exn > 100)
3712 {
3713 __h.reset((char_type*)malloc(__exn * sizeof(char_type)));
3714 __mb = __h.get();
3715 if (__mb == 0)
3716 __throw_bad_alloc();
3717 }
3718 // format
3719 char_type* __mi;
3720 char_type* __me;
3721 this->__format(__mb, __mi, __me, __iob.flags(),
3722 __digits.data(), __digits.data() + __digits.size(), __ct,
3723 __neg, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3724 return __pad_and_output(__s, __mb, __mi, __me, __iob, __fl);
3725}
3726
Howard Hinnantff926772012-11-06 21:08:48 +00003727_LIBCPP_EXTERN_TEMPLATE(class money_put<char>)
3728_LIBCPP_EXTERN_TEMPLATE(class money_put<wchar_t>)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003729
3730// messages
3731
Howard Hinnant82894812010-09-22 16:48:34 +00003732class _LIBCPP_VISIBLE messages_base
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003733{
3734public:
Howard Hinnantb2080c72011-02-25 00:51:08 +00003735 typedef ptrdiff_t catalog;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003736
3737 _LIBCPP_ALWAYS_INLINE messages_base() {}
3738};
3739
3740template <class _CharT>
Howard Hinnant82894812010-09-22 16:48:34 +00003741class _LIBCPP_VISIBLE messages
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003742 : public locale::facet,
3743 public messages_base
3744{
3745public:
3746 typedef _CharT char_type;
3747 typedef basic_string<_CharT> string_type;
3748
3749 _LIBCPP_ALWAYS_INLINE
3750 explicit messages(size_t __refs = 0)
3751 : locale::facet(__refs) {}
3752
3753 _LIBCPP_ALWAYS_INLINE
3754 catalog open(const basic_string<char>& __nm, const locale& __loc) const
3755 {
3756 return do_open(__nm, __loc);
3757 }
3758
3759 _LIBCPP_ALWAYS_INLINE
3760 string_type get(catalog __c, int __set, int __msgid,
3761 const string_type& __dflt) const
3762 {
3763 return do_get(__c, __set, __msgid, __dflt);
3764 }
3765
3766 _LIBCPP_ALWAYS_INLINE
3767 void close(catalog __c) const
3768 {
3769 do_close(__c);
3770 }
3771
3772 static locale::id id;
3773
3774protected:
Howard Hinnant82894812010-09-22 16:48:34 +00003775 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003776 ~messages() {}
3777
3778 virtual catalog do_open(const basic_string<char>&, const locale&) const;
3779 virtual string_type do_get(catalog, int __set, int __msgid,
3780 const string_type& __dflt) const;
3781 virtual void do_close(catalog) const;
3782};
3783
3784template <class _CharT>
3785locale::id
3786messages<_CharT>::id;
3787
3788template <class _CharT>
3789typename messages<_CharT>::catalog
3790messages<_CharT>::do_open(const basic_string<char>& __nm, const locale&) const
3791{
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00003792#if _WIN32
3793 return -1;
3794#else // _WIN32
Howard Hinnant11624452011-10-11 16:00:46 +00003795 catalog __cat = (catalog)catopen(__nm.c_str(), NL_CAT_LOCALE);
Howard Hinnantb2080c72011-02-25 00:51:08 +00003796 if (__cat != -1)
3797 __cat = static_cast<catalog>((static_cast<size_t>(__cat) >> 1));
3798 return __cat;
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00003799#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003800}
3801
3802template <class _CharT>
3803typename messages<_CharT>::string_type
3804messages<_CharT>::do_get(catalog __c, int __set, int __msgid,
3805 const string_type& __dflt) const
3806{
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00003807#if _WIN32
3808 return __dflt;
3809#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003810 string __ndflt;
3811 __narrow_to_utf8<sizeof(char_type)*__CHAR_BIT__>()(back_inserter(__ndflt),
3812 __dflt.c_str(),
3813 __dflt.c_str() + __dflt.size());
Howard Hinnantb2080c72011-02-25 00:51:08 +00003814 if (__c != -1)
3815 __c <<= 1;
Howard Hinnant11624452011-10-11 16:00:46 +00003816 nl_catd __cat = (nl_catd)__c;
Howard Hinnantb2080c72011-02-25 00:51:08 +00003817 char* __n = catgets(__cat, __set, __msgid, __ndflt.c_str());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003818 string_type __w;
3819 __widen_from_utf8<sizeof(char_type)*__CHAR_BIT__>()(back_inserter(__w),
3820 __n, __n + strlen(__n));
3821 return __w;
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00003822#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003823}
3824
3825template <class _CharT>
3826void
3827messages<_CharT>::do_close(catalog __c) const
3828{
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00003829#if !_WIN32
Howard Hinnantb2080c72011-02-25 00:51:08 +00003830 if (__c != -1)
3831 __c <<= 1;
Howard Hinnant11624452011-10-11 16:00:46 +00003832 nl_catd __cat = (nl_catd)__c;
Howard Hinnantb2080c72011-02-25 00:51:08 +00003833 catclose(__cat);
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00003834#endif // !_WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003835}
3836
Howard Hinnantff926772012-11-06 21:08:48 +00003837_LIBCPP_EXTERN_TEMPLATE(class messages<char>)
3838_LIBCPP_EXTERN_TEMPLATE(class messages<wchar_t>)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003839
3840template <class _CharT>
Howard Hinnant82894812010-09-22 16:48:34 +00003841class _LIBCPP_VISIBLE messages_byname
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003842 : public messages<_CharT>
3843{
3844public:
3845 typedef messages_base::catalog catalog;
3846 typedef basic_string<_CharT> string_type;
3847
3848 _LIBCPP_ALWAYS_INLINE
3849 explicit messages_byname(const char*, size_t __refs = 0)
3850 : messages<_CharT>(__refs) {}
3851
3852 _LIBCPP_ALWAYS_INLINE
3853 explicit messages_byname(const string&, size_t __refs = 0)
3854 : messages<_CharT>(__refs) {}
3855
3856protected:
Howard Hinnant82894812010-09-22 16:48:34 +00003857 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003858 ~messages_byname() {}
3859};
3860
Howard Hinnantff926772012-11-06 21:08:48 +00003861_LIBCPP_EXTERN_TEMPLATE(class messages_byname<char>)
3862_LIBCPP_EXTERN_TEMPLATE(class messages_byname<wchar_t>)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003863
Howard Hinnantd23b4642010-05-31 20:58:54 +00003864template<class _Codecvt, class _Elem = wchar_t,
3865 class _Wide_alloc = allocator<_Elem>,
3866 class _Byte_alloc = allocator<char> >
Howard Hinnant82894812010-09-22 16:48:34 +00003867class _LIBCPP_VISIBLE wstring_convert
Howard Hinnantd23b4642010-05-31 20:58:54 +00003868{
3869public:
3870 typedef basic_string<char, char_traits<char>, _Byte_alloc> byte_string;
3871 typedef basic_string<_Elem, char_traits<_Elem>, _Wide_alloc> wide_string;
3872 typedef typename _Codecvt::state_type state_type;
3873 typedef typename wide_string::traits_type::int_type int_type;
3874
3875private:
3876 byte_string __byte_err_string_;
3877 wide_string __wide_err_string_;
3878 _Codecvt* __cvtptr_;
3879 state_type __cvtstate_;
3880 size_t __cvtcount_;
3881
3882 wstring_convert(const wstring_convert& __wc);
3883 wstring_convert& operator=(const wstring_convert& __wc);
3884public:
3885 wstring_convert(_Codecvt* __pcvt = new _Codecvt);
3886 wstring_convert(_Codecvt* __pcvt, state_type __state);
3887 wstring_convert(const byte_string& __byte_err,
3888 const wide_string& __wide_err = wide_string());
Howard Hinnant73d21a42010-09-04 23:28:19 +00003889#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantd23b4642010-05-31 20:58:54 +00003890 wstring_convert(wstring_convert&& __wc);
3891#endif
3892 ~wstring_convert();
3893
Howard Hinnant82894812010-09-22 16:48:34 +00003894 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003895 wide_string from_bytes(char __byte)
3896 {return from_bytes(&__byte, &__byte+1);}
Howard Hinnant82894812010-09-22 16:48:34 +00003897 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003898 wide_string from_bytes(const char* __ptr)
3899 {return from_bytes(__ptr, __ptr + char_traits<char>::length(__ptr));}
Howard Hinnant82894812010-09-22 16:48:34 +00003900 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003901 wide_string from_bytes(const byte_string& __str)
3902 {return from_bytes(__str.data(), __str.data() + __str.size());}
3903 wide_string from_bytes(const char* __first, const char* __last);
3904
Howard Hinnant82894812010-09-22 16:48:34 +00003905 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003906 byte_string to_bytes(_Elem __wchar)
3907 {return to_bytes(&__wchar, &__wchar+1);}
Howard Hinnant82894812010-09-22 16:48:34 +00003908 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003909 byte_string to_bytes(const _Elem* __wptr)
3910 {return to_bytes(__wptr, __wptr + char_traits<_Elem>::length(__wptr));}
Howard Hinnant82894812010-09-22 16:48:34 +00003911 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003912 byte_string to_bytes(const wide_string& __wstr)
3913 {return to_bytes(__wstr.data(), __wstr.data() + __wstr.size());}
3914 byte_string to_bytes(const _Elem* __first, const _Elem* __last);
3915
Howard Hinnant82894812010-09-22 16:48:34 +00003916 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003917 size_t converted() const {return __cvtcount_;}
Howard Hinnant82894812010-09-22 16:48:34 +00003918 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003919 state_type state() const {return __cvtstate_;}
3920};
3921
3922template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Howard Hinnant82894812010-09-22 16:48:34 +00003923inline _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003924wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3925 wstring_convert(_Codecvt* __pcvt)
3926 : __cvtptr_(__pcvt), __cvtstate_(), __cvtcount_(0)
3927{
3928}
3929
3930template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Howard Hinnant82894812010-09-22 16:48:34 +00003931inline _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003932wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3933 wstring_convert(_Codecvt* __pcvt, state_type __state)
3934 : __cvtptr_(__pcvt), __cvtstate_(__state), __cvtcount_(0)
3935{
3936}
3937
3938template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3939wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3940 wstring_convert(const byte_string& __byte_err, const wide_string& __wide_err)
3941 : __byte_err_string_(__byte_err), __wide_err_string_(__wide_err),
3942 __cvtstate_(), __cvtcount_(0)
3943{
3944 __cvtptr_ = new _Codecvt;
3945}
3946
Howard Hinnant73d21a42010-09-04 23:28:19 +00003947#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantd23b4642010-05-31 20:58:54 +00003948
3949template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Howard Hinnant82894812010-09-22 16:48:34 +00003950inline _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003951wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3952 wstring_convert(wstring_convert&& __wc)
Howard Hinnant0949eed2011-06-30 21:18:19 +00003953 : __byte_err_string_(_VSTD::move(__wc.__byte_err_string_)),
3954 __wide_err_string_(_VSTD::move(__wc.__wide_err_string_)),
Howard Hinnantd23b4642010-05-31 20:58:54 +00003955 __cvtptr_(__wc.__cvtptr_),
3956 __cvtstate_(__wc.__cvtstate_), __cvtcount_(__wc.__cvtstate_)
3957{
3958 __wc.__cvtptr_ = nullptr;
3959}
3960
Howard Hinnantbfd55302010-09-04 23:46:48 +00003961#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantd23b4642010-05-31 20:58:54 +00003962
3963template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3964wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::~wstring_convert()
3965{
3966 delete __cvtptr_;
3967}
3968
3969template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3970typename wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::wide_string
3971wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3972 from_bytes(const char* __frm, const char* __frm_end)
3973{
3974 __cvtcount_ = 0;
3975 if (__cvtptr_ != nullptr)
3976 {
3977 wide_string __ws(2*(__frm_end - __frm), _Elem());
Howard Hinnant1ca23672012-07-12 18:07:41 +00003978 if (__frm != __frm_end)
3979 __ws.resize(__ws.capacity());
Howard Hinnantd23b4642010-05-31 20:58:54 +00003980 codecvt_base::result __r = codecvt_base::ok;
3981 state_type __st = __cvtstate_;
3982 if (__frm != __frm_end)
3983 {
3984 _Elem* __to = &__ws[0];
3985 _Elem* __to_end = __to + __ws.size();
3986 const char* __frm_nxt;
3987 do
3988 {
3989 _Elem* __to_nxt;
3990 __r = __cvtptr_->in(__st, __frm, __frm_end, __frm_nxt,
3991 __to, __to_end, __to_nxt);
3992 __cvtcount_ += __frm_nxt - __frm;
3993 if (__frm_nxt == __frm)
3994 {
3995 __r = codecvt_base::error;
3996 }
3997 else if (__r == codecvt_base::noconv)
3998 {
3999 __ws.resize(__to - &__ws[0]);
4000 // This only gets executed if _Elem is char
4001 __ws.append((const _Elem*)__frm, (const _Elem*)__frm_end);
4002 __frm = __frm_nxt;
4003 __r = codecvt_base::ok;
4004 }
4005 else if (__r == codecvt_base::ok)
4006 {
4007 __ws.resize(__to_nxt - &__ws[0]);
4008 __frm = __frm_nxt;
4009 }
4010 else if (__r == codecvt_base::partial)
4011 {
4012 ptrdiff_t __s = __to_nxt - &__ws[0];
4013 __ws.resize(2 * __s);
4014 __to = &__ws[0] + __s;
4015 __to_end = &__ws[0] + __ws.size();
4016 __frm = __frm_nxt;
4017 }
4018 } while (__r == codecvt_base::partial && __frm_nxt < __frm_end);
4019 }
4020 if (__r == codecvt_base::ok)
4021 return __ws;
4022 }
Howard Hinnantd4444702010-08-11 17:04:31 +00004023#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00004024 if (__wide_err_string_.empty())
4025 throw range_error("wstring_convert: from_bytes error");
Howard Hinnant324bb032010-08-22 00:02:43 +00004026#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00004027 return __wide_err_string_;
4028}
4029
4030template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
4031typename wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::byte_string
4032wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
4033 to_bytes(const _Elem* __frm, const _Elem* __frm_end)
4034{
4035 __cvtcount_ = 0;
4036 if (__cvtptr_ != nullptr)
4037 {
4038 byte_string __bs(2*(__frm_end - __frm), char());
Howard Hinnant1ca23672012-07-12 18:07:41 +00004039 if (__frm != __frm_end)
4040 __bs.resize(__bs.capacity());
Howard Hinnantd23b4642010-05-31 20:58:54 +00004041 codecvt_base::result __r = codecvt_base::ok;
4042 state_type __st = __cvtstate_;
4043 if (__frm != __frm_end)
4044 {
4045 char* __to = &__bs[0];
4046 char* __to_end = __to + __bs.size();
4047 const _Elem* __frm_nxt;
4048 do
4049 {
4050 char* __to_nxt;
4051 __r = __cvtptr_->out(__st, __frm, __frm_end, __frm_nxt,
4052 __to, __to_end, __to_nxt);
4053 __cvtcount_ += __frm_nxt - __frm;
4054 if (__frm_nxt == __frm)
4055 {
4056 __r = codecvt_base::error;
4057 }
4058 else if (__r == codecvt_base::noconv)
4059 {
4060 __bs.resize(__to - &__bs[0]);
4061 // This only gets executed if _Elem is char
4062 __bs.append((const char*)__frm, (const char*)__frm_end);
4063 __frm = __frm_nxt;
4064 __r = codecvt_base::ok;
4065 }
4066 else if (__r == codecvt_base::ok)
4067 {
4068 __bs.resize(__to_nxt - &__bs[0]);
4069 __frm = __frm_nxt;
4070 }
4071 else if (__r == codecvt_base::partial)
4072 {
4073 ptrdiff_t __s = __to_nxt - &__bs[0];
4074 __bs.resize(2 * __s);
4075 __to = &__bs[0] + __s;
4076 __to_end = &__bs[0] + __bs.size();
4077 __frm = __frm_nxt;
4078 }
4079 } while (__r == codecvt_base::partial && __frm_nxt < __frm_end);
4080 }
4081 if (__r == codecvt_base::ok)
4082 {
4083 size_t __s = __bs.size();
4084 __bs.resize(__bs.capacity());
4085 char* __to = &__bs[0] + __s;
4086 char* __to_end = __to + __bs.size();
4087 do
4088 {
4089 char* __to_nxt;
4090 __r = __cvtptr_->unshift(__st, __to, __to_end, __to_nxt);
4091 if (__r == codecvt_base::noconv)
4092 {
4093 __bs.resize(__to - &__bs[0]);
4094 __r = codecvt_base::ok;
4095 }
4096 else if (__r == codecvt_base::ok)
4097 {
4098 __bs.resize(__to_nxt - &__bs[0]);
4099 }
4100 else if (__r == codecvt_base::partial)
4101 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00004102 ptrdiff_t __sp = __to_nxt - &__bs[0];
4103 __bs.resize(2 * __sp);
4104 __to = &__bs[0] + __sp;
Howard Hinnantd23b4642010-05-31 20:58:54 +00004105 __to_end = &__bs[0] + __bs.size();
4106 }
4107 } while (__r == codecvt_base::partial);
4108 if (__r == codecvt_base::ok)
4109 return __bs;
4110 }
4111 }
Howard Hinnantd4444702010-08-11 17:04:31 +00004112#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00004113 if (__byte_err_string_.empty())
4114 throw range_error("wstring_convert: to_bytes error");
Howard Hinnant324bb032010-08-22 00:02:43 +00004115#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00004116 return __byte_err_string_;
4117}
4118
4119template <class _Codecvt, class _Elem = wchar_t, class _Tr = char_traits<_Elem> >
Howard Hinnant82894812010-09-22 16:48:34 +00004120class _LIBCPP_VISIBLE wbuffer_convert
Howard Hinnantd23b4642010-05-31 20:58:54 +00004121 : public basic_streambuf<_Elem, _Tr>
4122{
4123public:
4124 // types:
4125 typedef _Elem char_type;
4126 typedef _Tr traits_type;
4127 typedef typename traits_type::int_type int_type;
4128 typedef typename traits_type::pos_type pos_type;
4129 typedef typename traits_type::off_type off_type;
4130 typedef typename _Codecvt::state_type state_type;
4131
4132private:
Howard Hinnant4b53f502010-06-01 20:09:18 +00004133 char* __extbuf_;
4134 const char* __extbufnext_;
4135 const char* __extbufend_;
4136 char __extbuf_min_[8];
4137 size_t __ebs_;
4138 char_type* __intbuf_;
4139 size_t __ibs_;
Howard Hinnantd23b4642010-05-31 20:58:54 +00004140 streambuf* __bufptr_;
Howard Hinnant4b53f502010-06-01 20:09:18 +00004141 _Codecvt* __cv_;
4142 state_type __st_;
4143 ios_base::openmode __cm_;
4144 bool __owns_eb_;
4145 bool __owns_ib_;
4146 bool __always_noconv_;
Howard Hinnantd23b4642010-05-31 20:58:54 +00004147
Howard Hinnant4b53f502010-06-01 20:09:18 +00004148 wbuffer_convert(const wbuffer_convert&);
4149 wbuffer_convert& operator=(const wbuffer_convert&);
Howard Hinnantd23b4642010-05-31 20:58:54 +00004150public:
4151 wbuffer_convert(streambuf* __bytebuf = 0, _Codecvt* __pcvt = new _Codecvt,
Howard Hinnant4b53f502010-06-01 20:09:18 +00004152 state_type __state = state_type());
4153 ~wbuffer_convert();
Howard Hinnantd23b4642010-05-31 20:58:54 +00004154
Howard Hinnant82894812010-09-22 16:48:34 +00004155 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantd23b4642010-05-31 20:58:54 +00004156 streambuf* rdbuf() const {return __bufptr_;}
Howard Hinnant82894812010-09-22 16:48:34 +00004157 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantd23b4642010-05-31 20:58:54 +00004158 streambuf* rdbuf(streambuf* __bytebuf)
4159 {
4160 streambuf* __r = __bufptr_;
4161 __bufptr_ = __bytebuf;
4162 return __r;
4163 }
4164
Howard Hinnant82894812010-09-22 16:48:34 +00004165 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant4b53f502010-06-01 20:09:18 +00004166 state_type state() const {return __st_;}
Howard Hinnantd23b4642010-05-31 20:58:54 +00004167
4168protected:
Howard Hinnant4b53f502010-06-01 20:09:18 +00004169 virtual int_type underflow();
4170 virtual int_type pbackfail(int_type __c = traits_type::eof());
Howard Hinnantd23b4642010-05-31 20:58:54 +00004171 virtual int_type overflow (int_type __c = traits_type::eof());
Howard Hinnant4b53f502010-06-01 20:09:18 +00004172 virtual basic_streambuf<char_type, traits_type>* setbuf(char_type* __s,
4173 streamsize __n);
4174 virtual pos_type seekoff(off_type __off, ios_base::seekdir __way,
4175 ios_base::openmode __wch = ios_base::in | ios_base::out);
4176 virtual pos_type seekpos(pos_type __sp,
4177 ios_base::openmode __wch = ios_base::in | ios_base::out);
4178 virtual int sync();
4179
4180private:
4181 bool __read_mode();
4182 void __write_mode();
4183 wbuffer_convert* __close();
Howard Hinnantd23b4642010-05-31 20:58:54 +00004184};
4185
4186template <class _Codecvt, class _Elem, class _Tr>
Howard Hinnant4b53f502010-06-01 20:09:18 +00004187wbuffer_convert<_Codecvt, _Elem, _Tr>::
4188 wbuffer_convert(streambuf* __bytebuf, _Codecvt* __pcvt, state_type __state)
4189 : __extbuf_(0),
4190 __extbufnext_(0),
4191 __extbufend_(0),
4192 __ebs_(0),
4193 __intbuf_(0),
4194 __ibs_(0),
4195 __bufptr_(__bytebuf),
4196 __cv_(__pcvt),
4197 __st_(__state),
4198 __cm_(0),
4199 __owns_eb_(false),
4200 __owns_ib_(false),
4201 __always_noconv_(__cv_ ? __cv_->always_noconv() : false)
4202{
4203 setbuf(0, 4096);
4204}
4205
4206template <class _Codecvt, class _Elem, class _Tr>
4207wbuffer_convert<_Codecvt, _Elem, _Tr>::~wbuffer_convert()
4208{
4209 __close();
4210 delete __cv_;
4211 if (__owns_eb_)
4212 delete [] __extbuf_;
4213 if (__owns_ib_)
4214 delete [] __intbuf_;
4215}
4216
4217template <class _Codecvt, class _Elem, class _Tr>
4218typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
4219wbuffer_convert<_Codecvt, _Elem, _Tr>::underflow()
4220{
4221 if (__cv_ == 0 || __bufptr_ == 0)
4222 return traits_type::eof();
4223 bool __initial = __read_mode();
4224 char_type __1buf;
4225 if (this->gptr() == 0)
4226 this->setg(&__1buf, &__1buf+1, &__1buf+1);
4227 const size_t __unget_sz = __initial ? 0 : min<size_t>((this->egptr() - this->eback()) / 2, 4);
4228 int_type __c = traits_type::eof();
4229 if (this->gptr() == this->egptr())
4230 {
4231 memmove(this->eback(), this->egptr() - __unget_sz, __unget_sz * sizeof(char_type));
4232 if (__always_noconv_)
4233 {
4234 streamsize __nmemb = static_cast<streamsize>(this->egptr() - this->eback() - __unget_sz);
4235 __nmemb = __bufptr_->sgetn((char*)this->eback() + __unget_sz, __nmemb);
4236 if (__nmemb != 0)
4237 {
4238 this->setg(this->eback(),
4239 this->eback() + __unget_sz,
4240 this->eback() + __unget_sz + __nmemb);
4241 __c = *this->gptr();
4242 }
4243 }
4244 else
4245 {
4246 memmove(__extbuf_, __extbufnext_, __extbufend_ - __extbufnext_);
4247 __extbufnext_ = __extbuf_ + (__extbufend_ - __extbufnext_);
4248 __extbufend_ = __extbuf_ + (__extbuf_ == __extbuf_min_ ? sizeof(__extbuf_min_) : __ebs_);
Howard Hinnant0949eed2011-06-30 21:18:19 +00004249 streamsize __nmemb = _VSTD::min(static_cast<streamsize>(this->egptr() - this->eback() - __unget_sz),
Howard Hinnant4b53f502010-06-01 20:09:18 +00004250 static_cast<streamsize>(__extbufend_ - __extbufnext_));
4251 codecvt_base::result __r;
4252 state_type __svs = __st_;
4253 streamsize __nr = __bufptr_->sgetn(const_cast<char*>(__extbufnext_), __nmemb);
4254 if (__nr != 0)
4255 {
4256 __extbufend_ = __extbufnext_ + __nr;
4257 char_type* __inext;
4258 __r = __cv_->in(__st_, __extbuf_, __extbufend_, __extbufnext_,
4259 this->eback() + __unget_sz,
4260 this->egptr(), __inext);
4261 if (__r == codecvt_base::noconv)
4262 {
4263 this->setg((char_type*)__extbuf_, (char_type*)__extbuf_, (char_type*)__extbufend_);
4264 __c = *this->gptr();
4265 }
4266 else if (__inext != this->eback() + __unget_sz)
4267 {
4268 this->setg(this->eback(), this->eback() + __unget_sz, __inext);
4269 __c = *this->gptr();
4270 }
4271 }
4272 }
4273 }
4274 else
4275 __c = *this->gptr();
4276 if (this->eback() == &__1buf)
4277 this->setg(0, 0, 0);
4278 return __c;
4279}
4280
4281template <class _Codecvt, class _Elem, class _Tr>
4282typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
4283wbuffer_convert<_Codecvt, _Elem, _Tr>::pbackfail(int_type __c)
4284{
4285 if (__cv_ != 0 && __bufptr_ != 0 && this->eback() < this->gptr())
4286 {
4287 if (traits_type::eq_int_type(__c, traits_type::eof()))
4288 {
4289 this->gbump(-1);
4290 return traits_type::not_eof(__c);
4291 }
4292 if (traits_type::eq(traits_type::to_char_type(__c), this->gptr()[-1]))
4293 {
4294 this->gbump(-1);
4295 *this->gptr() = traits_type::to_char_type(__c);
4296 return __c;
4297 }
4298 }
4299 return traits_type::eof();
4300}
4301
4302template <class _Codecvt, class _Elem, class _Tr>
Howard Hinnantd23b4642010-05-31 20:58:54 +00004303typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
4304wbuffer_convert<_Codecvt, _Elem, _Tr>::overflow(int_type __c)
4305{
Howard Hinnant4b53f502010-06-01 20:09:18 +00004306 if (__cv_ == 0 || __bufptr_ == 0)
4307 return traits_type::eof();
4308 __write_mode();
4309 char_type __1buf;
4310 char_type* __pb_save = this->pbase();
4311 char_type* __epb_save = this->epptr();
4312 if (!traits_type::eq_int_type(__c, traits_type::eof()))
4313 {
4314 if (this->pptr() == 0)
4315 this->setp(&__1buf, &__1buf+1);
4316 *this->pptr() = traits_type::to_char_type(__c);
4317 this->pbump(1);
4318 }
4319 if (this->pptr() != this->pbase())
4320 {
4321 if (__always_noconv_)
4322 {
4323 streamsize __nmemb = static_cast<streamsize>(this->pptr() - this->pbase());
4324 if (__bufptr_->sputn((const char*)this->pbase(), __nmemb) != __nmemb)
4325 return traits_type::eof();
4326 }
4327 else
4328 {
4329 char* __extbe = __extbuf_;
4330 codecvt_base::result __r;
4331 do
4332 {
4333 const char_type* __e;
4334 __r = __cv_->out(__st_, this->pbase(), this->pptr(), __e,
4335 __extbuf_, __extbuf_ + __ebs_, __extbe);
4336 if (__e == this->pbase())
4337 return traits_type::eof();
4338 if (__r == codecvt_base::noconv)
4339 {
4340 streamsize __nmemb = static_cast<size_t>(this->pptr() - this->pbase());
4341 if (__bufptr_->sputn((const char*)this->pbase(), __nmemb) != __nmemb)
4342 return traits_type::eof();
4343 }
4344 else if (__r == codecvt_base::ok || __r == codecvt_base::partial)
4345 {
4346 streamsize __nmemb = static_cast<size_t>(__extbe - __extbuf_);
4347 if (__bufptr_->sputn(__extbuf_, __nmemb) != __nmemb)
4348 return traits_type::eof();
4349 if (__r == codecvt_base::partial)
4350 {
4351 this->setp((char_type*)__e, this->pptr());
4352 this->pbump(this->epptr() - this->pbase());
4353 }
4354 }
4355 else
4356 return traits_type::eof();
4357 } while (__r == codecvt_base::partial);
4358 }
4359 this->setp(__pb_save, __epb_save);
4360 }
4361 return traits_type::not_eof(__c);
4362}
4363
4364template <class _Codecvt, class _Elem, class _Tr>
4365basic_streambuf<_Elem, _Tr>*
4366wbuffer_convert<_Codecvt, _Elem, _Tr>::setbuf(char_type* __s, streamsize __n)
4367{
4368 this->setg(0, 0, 0);
4369 this->setp(0, 0);
4370 if (__owns_eb_)
4371 delete [] __extbuf_;
4372 if (__owns_ib_)
4373 delete [] __intbuf_;
4374 __ebs_ = __n;
4375 if (__ebs_ > sizeof(__extbuf_min_))
4376 {
4377 if (__always_noconv_ && __s)
4378 {
4379 __extbuf_ = (char*)__s;
4380 __owns_eb_ = false;
4381 }
4382 else
4383 {
4384 __extbuf_ = new char[__ebs_];
4385 __owns_eb_ = true;
4386 }
4387 }
4388 else
4389 {
4390 __extbuf_ = __extbuf_min_;
4391 __ebs_ = sizeof(__extbuf_min_);
4392 __owns_eb_ = false;
4393 }
4394 if (!__always_noconv_)
4395 {
4396 __ibs_ = max<streamsize>(__n, sizeof(__extbuf_min_));
4397 if (__s && __ibs_ >= sizeof(__extbuf_min_))
4398 {
4399 __intbuf_ = __s;
4400 __owns_ib_ = false;
4401 }
4402 else
4403 {
4404 __intbuf_ = new char_type[__ibs_];
4405 __owns_ib_ = true;
4406 }
4407 }
4408 else
4409 {
4410 __ibs_ = 0;
4411 __intbuf_ = 0;
4412 __owns_ib_ = false;
4413 }
4414 return this;
4415}
4416
4417template <class _Codecvt, class _Elem, class _Tr>
4418typename wbuffer_convert<_Codecvt, _Elem, _Tr>::pos_type
4419wbuffer_convert<_Codecvt, _Elem, _Tr>::seekoff(off_type __off, ios_base::seekdir __way,
4420 ios_base::openmode __om)
4421{
4422 int __width = __cv_->encoding();
4423 if (__cv_ == 0 || __bufptr_ == 0 || (__width <= 0 && __off != 0) || sync())
4424 return pos_type(off_type(-1));
4425 // __width > 0 || __off == 0
4426 switch (__way)
4427 {
4428 case ios_base::beg:
4429 break;
4430 case ios_base::cur:
4431 break;
4432 case ios_base::end:
4433 break;
4434 default:
4435 return pos_type(off_type(-1));
4436 }
4437 pos_type __r = __bufptr_->pubseekoff(__width * __off, __way, __om);
4438 __r.state(__st_);
4439 return __r;
4440}
4441
4442template <class _Codecvt, class _Elem, class _Tr>
4443typename wbuffer_convert<_Codecvt, _Elem, _Tr>::pos_type
4444wbuffer_convert<_Codecvt, _Elem, _Tr>::seekpos(pos_type __sp, ios_base::openmode __wch)
4445{
4446 if (__cv_ == 0 || __bufptr_ == 0 || sync())
4447 return pos_type(off_type(-1));
4448 if (__bufptr_->pubseekpos(__sp, __wch) == pos_type(off_type(-1)))
4449 return pos_type(off_type(-1));
4450 return __sp;
4451}
4452
4453template <class _Codecvt, class _Elem, class _Tr>
4454int
4455wbuffer_convert<_Codecvt, _Elem, _Tr>::sync()
4456{
4457 if (__cv_ == 0 || __bufptr_ == 0)
4458 return 0;
4459 if (__cm_ & ios_base::out)
4460 {
4461 if (this->pptr() != this->pbase())
4462 if (overflow() == traits_type::eof())
4463 return -1;
4464 codecvt_base::result __r;
4465 do
4466 {
4467 char* __extbe;
4468 __r = __cv_->unshift(__st_, __extbuf_, __extbuf_ + __ebs_, __extbe);
4469 streamsize __nmemb = static_cast<streamsize>(__extbe - __extbuf_);
4470 if (__bufptr_->sputn(__extbuf_, __nmemb) != __nmemb)
4471 return -1;
4472 } while (__r == codecvt_base::partial);
4473 if (__r == codecvt_base::error)
4474 return -1;
4475 if (__bufptr_->pubsync())
4476 return -1;
4477 }
4478 else if (__cm_ & ios_base::in)
4479 {
4480 off_type __c;
4481 if (__always_noconv_)
4482 __c = this->egptr() - this->gptr();
4483 else
4484 {
4485 int __width = __cv_->encoding();
4486 __c = __extbufend_ - __extbufnext_;
4487 if (__width > 0)
4488 __c += __width * (this->egptr() - this->gptr());
4489 else
4490 {
4491 if (this->gptr() != this->egptr())
4492 {
4493 reverse(this->gptr(), this->egptr());
4494 codecvt_base::result __r;
4495 const char_type* __e = this->gptr();
4496 char* __extbe;
4497 do
4498 {
4499 __r = __cv_->out(__st_, __e, this->egptr(), __e,
4500 __extbuf_, __extbuf_ + __ebs_, __extbe);
4501 switch (__r)
4502 {
4503 case codecvt_base::noconv:
4504 __c += this->egptr() - this->gptr();
4505 break;
4506 case codecvt_base::ok:
4507 case codecvt_base::partial:
4508 __c += __extbe - __extbuf_;
4509 break;
4510 default:
4511 return -1;
4512 }
4513 } while (__r == codecvt_base::partial);
4514 }
4515 }
4516 }
4517 if (__bufptr_->pubseekoff(-__c, ios_base::cur, __cm_) == pos_type(off_type(-1)))
4518 return -1;
4519 this->setg(0, 0, 0);
4520 __cm_ = 0;
4521 }
4522 return 0;
4523}
4524
4525template <class _Codecvt, class _Elem, class _Tr>
4526bool
4527wbuffer_convert<_Codecvt, _Elem, _Tr>::__read_mode()
4528{
4529 if (!(__cm_ & ios_base::in))
4530 {
4531 this->setp(0, 0);
4532 if (__always_noconv_)
4533 this->setg((char_type*)__extbuf_,
4534 (char_type*)__extbuf_ + __ebs_,
4535 (char_type*)__extbuf_ + __ebs_);
4536 else
4537 this->setg(__intbuf_, __intbuf_ + __ibs_, __intbuf_ + __ibs_);
4538 __cm_ = ios_base::in;
4539 return true;
4540 }
4541 return false;
4542}
4543
4544template <class _Codecvt, class _Elem, class _Tr>
4545void
4546wbuffer_convert<_Codecvt, _Elem, _Tr>::__write_mode()
4547{
4548 if (!(__cm_ & ios_base::out))
4549 {
4550 this->setg(0, 0, 0);
4551 if (__ebs_ > sizeof(__extbuf_min_))
4552 {
4553 if (__always_noconv_)
4554 this->setp((char_type*)__extbuf_,
4555 (char_type*)__extbuf_ + (__ebs_ - 1));
4556 else
4557 this->setp(__intbuf_, __intbuf_ + (__ibs_ - 1));
4558 }
4559 else
4560 this->setp(0, 0);
4561 __cm_ = ios_base::out;
4562 }
4563}
4564
4565template <class _Codecvt, class _Elem, class _Tr>
4566wbuffer_convert<_Codecvt, _Elem, _Tr>*
4567wbuffer_convert<_Codecvt, _Elem, _Tr>::__close()
4568{
4569 wbuffer_convert* __rt = 0;
4570 if (__cv_ != 0 && __bufptr_ != 0)
4571 {
4572 __rt = this;
4573 if ((__cm_ & ios_base::out) && sync())
4574 __rt = 0;
4575 }
4576 return __rt;
Howard Hinnantd23b4642010-05-31 20:58:54 +00004577}
4578
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004579_LIBCPP_END_NAMESPACE_STD
4580
4581#endif // _LIBCPP_LOCALE