blob: 78f85d8d0700fa7fb233b26c212e724638299705 [file] [log] [blame]
Howard Hinnant3e519522010-05-11 19:42:16 +00001// -*- C++ -*-
2//===-------------------------- locale ------------------------------------===//
3//
Howard Hinnant5b08a8a2010-05-11 21:36:01 +00004// The LLVM Compiler Infrastructure
Howard Hinnant3e519522010-05-11 19:42:16 +00005//
Howard Hinnant412dbeb2010-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 Hinnant3e519522010-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 Hinnantb5d866d2011-05-31 15:34:58 +000039 locale() noexcept;
40 locale(const locale& other) noexcept;
Howard Hinnant3e519522010-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 Hinnantb5d866d2011-05-31 15:34:58 +000048 ~locale(); // not virtual
Howard Hinnant3e519522010-05-11 19:42:16 +000049
Howard Hinnantb5d866d2011-05-31 15:34:58 +000050 const locale& operator=(const locale& other) noexcept;
Howard Hinnant3e519522010-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 Hinnantb5d866d2011-05-31 15:34:58 +000068template <class Facet> bool has_facet(const locale&) noexcept;
Howard Hinnant3e519522010-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 Hinnant5d3c1132010-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
Marshall Clow7988106b2013-08-27 20:18:59 +000096 explicit wstring_convert(Codecvt* pcvt = new Codecvt); // explicit in C++14
Howard Hinnant5d3c1132010-05-31 20:58:54 +000097 wstring_convert(Codecvt* pcvt, state_type state);
Marshall Clow7988106b2013-08-27 20:18:59 +000098 explicit wstring_convert(const byte_string& byte_err, // explicit in C++14
Howard Hinnant5d3c1132010-05-31 20:58:54 +000099 const wide_string& wide_err = wide_string());
Marshall Clow7988106b2013-08-27 20:18:59 +0000100 wstring_convert(const wstring_convert&) = delete; // C++14
101 wstring_convert & operator=(const wstring_convert &) = delete; // C++14
Howard Hinnant5d3c1132010-05-31 20:58:54 +0000102 ~wstring_convert();
103
104 wide_string from_bytes(char byte);
105 wide_string from_bytes(const char* ptr);
106 wide_string from_bytes(const byte_string& str);
107 wide_string from_bytes(const char* first, const char* last);
108
109 byte_string to_bytes(Elem wchar);
110 byte_string to_bytes(const Elem* wptr);
111 byte_string to_bytes(const wide_string& wstr);
112 byte_string to_bytes(const Elem* first, const Elem* last);
113
Marshall Clow7988106b2013-08-27 20:18:59 +0000114 size_t converted() const; // noexcept in C++14
Howard Hinnant5d3c1132010-05-31 20:58:54 +0000115 state_type state() const;
116};
117
Howard Hinnant3e519522010-05-11 19:42:16 +0000118template <class Codecvt, class Elem = wchar_t, class Tr = char_traits<Elem>>
Howard Hinnant5d3c1132010-05-31 20:58:54 +0000119class wbuffer_convert
120 : public basic_streambuf<Elem, Tr>
121{
122public:
123 typedef typename Tr::state_type state_type;
124
Marshall Clow7988106b2013-08-27 20:18:59 +0000125 explicit wbuffer_convert(streambuf* bytebuf = 0, Codecvt* pcvt = new Codecvt,
126 state_type state = state_type()); // explicit in C++14
127 wbuffer_convert(const wbuffer_convert&) = delete; // C++14
128 wbuffer_convert & operator=(const wbuffer_convert &) = delete; // C++14
129 ~wbuffer_convert(); // C++14
130
Howard Hinnant5d3c1132010-05-31 20:58:54 +0000131 streambuf* rdbuf() const;
132 streambuf* rdbuf(streambuf* bytebuf);
133
134 state_type state() const;
135};
Howard Hinnant3e519522010-05-11 19:42:16 +0000136
137// 22.4.1 and 22.4.1.3, ctype:
138class ctype_base;
139template <class charT> class ctype;
140template <> class ctype<char>; // specialization
141template <class charT> class ctype_byname;
142template <> class ctype_byname<char>; // specialization
143
144class codecvt_base;
145template <class internT, class externT, class stateT> class codecvt;
146template <class internT, class externT, class stateT> class codecvt_byname;
147
148// 22.4.2 and 22.4.3, numeric:
149template <class charT, class InputIterator> class num_get;
150template <class charT, class OutputIterator> class num_put;
151template <class charT> class numpunct;
152template <class charT> class numpunct_byname;
153
154// 22.4.4, col lation:
155template <class charT> class collate;
156template <class charT> class collate_byname;
157
158// 22.4.5, date and time:
159class time_base;
160template <class charT, class InputIterator> class time_get;
161template <class charT, class InputIterator> class time_get_byname;
162template <class charT, class OutputIterator> class time_put;
163template <class charT, class OutputIterator> class time_put_byname;
164
165// 22.4.6, money:
166class money_base;
167template <class charT, class InputIterator> class money_get;
168template <class charT, class OutputIterator> class money_put;
169template <class charT, bool Intl> class moneypunct;
170template <class charT, bool Intl> class moneypunct_byname;
171
172// 22.4.7, message retrieval:
173class messages_base;
174template <class charT> class messages;
175template <class charT> class messages_byname;
176
177} // std
178
179*/
180
181#include <__config>
182#include <__locale>
183#include <algorithm>
184#include <memory>
185#include <ios>
186#include <streambuf>
187#include <iterator>
188#include <limits>
Marshall Clowb56e8582013-03-18 17:45:34 +0000189#ifndef __APPLE__
Howard Hinnant128ba712010-05-24 17:49:41 +0000190#include <cstdarg>
191#endif
Howard Hinnant3e519522010-05-11 19:42:16 +0000192#include <cstdlib>
193#include <ctime>
Howard Hinnant5f878d42013-09-17 01:34:47 +0000194#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnant8909cdf2011-09-29 20:33:10 +0000195#include <support/win32/locale_win32.h>
Jonathan Roelofs4f1561a2014-09-19 20:09:12 +0000196#elif defined(_NEWLIB_VERSION)
197// FIXME: replace all the uses of _NEWLIB_VERSION with __NEWLIB__ preceded by an
198// include of <sys/cdefs.h> once https://sourceware.org/ml/newlib-cvs/2014-q3/msg00038.html
199// has had a chance to bake for a bit
200#include <support/newlib/xlocale.h>
Marshall Clowb38f8f02014-07-10 15:20:28 +0000201#elif !defined(__ANDROID__)
Howard Hinnant3e519522010-05-11 19:42:16 +0000202#include <nl_types.h>
Marshall Clowb38f8f02014-07-10 15:20:28 +0000203#endif
Howard Hinnant3e519522010-05-11 19:42:16 +0000204
Marshall Clowb56e8582013-03-18 17:45:34 +0000205#ifdef __APPLE__
Howard Hinnantb5c63a22012-11-14 21:17:15 +0000206#include <Availability.h>
207#endif
208
Howard Hinnantab4f4382011-11-29 16:45:27 +0000209#include <__undef_min_max>
210
Howard Hinnant073458b2011-10-17 20:05:10 +0000211#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
Howard Hinnant3e519522010-05-11 19:42:16 +0000212#pragma GCC system_header
Howard Hinnant073458b2011-10-17 20:05:10 +0000213#endif
Howard Hinnant3e519522010-05-11 19:42:16 +0000214
215_LIBCPP_BEGIN_NAMESPACE_STD
216
Marshall Clow69e76f82013-03-18 19:34:07 +0000217#if defined(__APPLE__) || defined(__FreeBSD__)
Howard Hinnant0470a632011-09-28 21:05:01 +0000218# define _LIBCPP_GET_C_LOCALE 0
Joerg Sonnenberger50544e72013-05-17 21:17:34 +0000219#elif defined(__NetBSD__)
220# define _LIBCPP_GET_C_LOCALE LC_C_LOCALE
Howard Hinnant0470a632011-09-28 21:05:01 +0000221#else
222# define _LIBCPP_GET_C_LOCALE __cloc()
Howard Hinnant9978e372011-09-28 23:39:33 +0000223 // Get the C locale object
Howard Hinnantf0544c22013-08-12 18:38:34 +0000224 _LIBCPP_FUNC_VIS locale_t __cloc();
Howard Hinnant9978e372011-09-28 23:39:33 +0000225#define __cloc_defined
Howard Hinnant0470a632011-09-28 21:05:01 +0000226#endif
227
Alexis Hunt4084c9e2011-07-15 05:40:33 +0000228typedef _VSTD::remove_pointer<locale_t>::type __locale_struct;
229typedef _VSTD::unique_ptr<__locale_struct, decltype(&freelocale)> __locale_unique_ptr;
David Chisnallca785922012-02-29 13:00:07 +0000230#ifndef _LIBCPP_LOCALE__L_EXTENSIONS
Alexis Hunt4084c9e2011-07-15 05:40:33 +0000231typedef _VSTD::unique_ptr<__locale_struct, decltype(&uselocale)> __locale_raii;
David Chisnallca785922012-02-29 13:00:07 +0000232#endif
Alexis Hunt4084c9e2011-07-15 05:40:33 +0000233
Howard Hinnant128ba712010-05-24 17:49:41 +0000234// OSX has nice foo_l() functions that let you turn off use of the global
235// locale. Linux, not so much. The following functions avoid the locale when
236// that's possible and otherwise do the wrong thing. FIXME.
Jonathan Roelofs4f1561a2014-09-19 20:09:12 +0000237#if defined(__linux__) || defined(__EMSCRIPTEN__) || defined(_AIX) || \
238 defined(_NEWLIB_VERSION)
Alexis Hunt4084c9e2011-07-15 05:40:33 +0000239
240#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
241decltype(MB_CUR_MAX_L(_VSTD::declval<locale_t>()))
Howard Hinnant848a5372010-09-22 16:48:34 +0000242inline _LIBCPP_INLINE_VISIBILITY
Alexis Hunt4084c9e2011-07-15 05:40:33 +0000243__mb_cur_max_l(locale_t __l)
Howard Hinnant128ba712010-05-24 17:49:41 +0000244{
Alexis Hunt4084c9e2011-07-15 05:40:33 +0000245 return MB_CUR_MAX_L(__l);
246}
247#else // _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant3af48ef2013-10-04 22:09:00 +0000248inline _LIBCPP_ALWAYS_INLINE
Alexis Hunt4084c9e2011-07-15 05:40:33 +0000249decltype(MB_CUR_MAX) __mb_cur_max_l(locale_t __l)
250{
251 __locale_raii __current(uselocale(__l), uselocale);
252 return MB_CUR_MAX;
253}
254#endif // _LIBCPP_LOCALE__L_EXTENSIONS
255
Howard Hinnant3af48ef2013-10-04 22:09:00 +0000256inline _LIBCPP_ALWAYS_INLINE
Alexis Hunt4084c9e2011-07-15 05:40:33 +0000257wint_t __btowc_l(int __c, locale_t __l)
258{
Howard Hinnant9978e372011-09-28 23:39:33 +0000259#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Alexis Hunt4084c9e2011-07-15 05:40:33 +0000260 return btowc_l(__c, __l);
261#else
262 __locale_raii __current(uselocale(__l), uselocale);
263 return btowc(__c);
264#endif
Alexis Hunt8a02a632011-07-13 06:40:50 +0000265}
Howard Hinnantf6b7e202011-07-13 15:48:16 +0000266
Howard Hinnant3af48ef2013-10-04 22:09:00 +0000267inline _LIBCPP_ALWAYS_INLINE
Alexis Hunt4084c9e2011-07-15 05:40:33 +0000268int __wctob_l(wint_t __c, locale_t __l)
Alexis Hunt8a02a632011-07-13 06:40:50 +0000269{
Alexis Hunt4084c9e2011-07-15 05:40:33 +0000270#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
271 return wctob_l(__c, __l);
272#else
273 __locale_raii __current(uselocale(__l), uselocale);
274 return wctob(__c);
275#endif
Alexis Hunt8a02a632011-07-13 06:40:50 +0000276}
Alexis Hunt4084c9e2011-07-15 05:40:33 +0000277
Howard Hinnant3af48ef2013-10-04 22:09:00 +0000278inline _LIBCPP_ALWAYS_INLINE
Alexis Hunt4084c9e2011-07-15 05:40:33 +0000279size_t __wcsnrtombs_l(char *__dest, const wchar_t **__src, size_t __nwc,
280 size_t __len, mbstate_t *__ps, locale_t __l)
281{
282#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
283 return wcsnrtombs_l(__dest, __src, __nwc, __len, __ps, __l);
284#else
285 __locale_raii __current(uselocale(__l), uselocale);
286 return wcsnrtombs(__dest, __src, __nwc, __len, __ps);
287#endif
288}
289
Howard Hinnant3af48ef2013-10-04 22:09:00 +0000290inline _LIBCPP_ALWAYS_INLINE
Alexis Hunt4084c9e2011-07-15 05:40:33 +0000291size_t __wcrtomb_l(char *__s, wchar_t __wc, mbstate_t *__ps, locale_t __l)
292{
293#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
294 return wcrtomb_l(__s, __wc, __ps, __l);
295#else
296 __locale_raii __current(uselocale(__l), uselocale);
297 return wcrtomb(__s, __wc, __ps);
298#endif
299}
300
Howard Hinnant3af48ef2013-10-04 22:09:00 +0000301inline _LIBCPP_ALWAYS_INLINE
Alexis Hunt4084c9e2011-07-15 05:40:33 +0000302size_t __mbsnrtowcs_l(wchar_t * __dest, const char **__src, size_t __nms,
303 size_t __len, mbstate_t *__ps, locale_t __l)
304{
305#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
David Chisnall89728132011-09-21 08:39:44 +0000306 return mbsnrtowcs_l(__dest, __src, __nms, __len, __ps, __l);
Alexis Hunt4084c9e2011-07-15 05:40:33 +0000307#else
308 __locale_raii __current(uselocale(__l), uselocale);
309 return mbsnrtowcs(__dest, __src, __nms, __len, __ps);
310#endif
311}
312
Howard Hinnant3af48ef2013-10-04 22:09:00 +0000313inline _LIBCPP_ALWAYS_INLINE
Alexis Hunt4084c9e2011-07-15 05:40:33 +0000314size_t __mbrtowc_l(wchar_t *__pwc, const char *__s, size_t __n,
315 mbstate_t *__ps, locale_t __l)
316{
317#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
318 return mbrtowc_l(__pwc, __s, __n, __ps, __l);
319#else
320 __locale_raii __current(uselocale(__l), uselocale);
321 return mbrtowc(__pwc, __s, __n, __ps);
322#endif
323}
324
Howard Hinnant3af48ef2013-10-04 22:09:00 +0000325inline _LIBCPP_ALWAYS_INLINE
Alexis Hunt4084c9e2011-07-15 05:40:33 +0000326int __mbtowc_l(wchar_t *__pwc, const char *__pmb, size_t __max, locale_t __l)
327{
328#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
David Chisnall89728132011-09-21 08:39:44 +0000329 return mbtowc_l(__pwc, __pmb, __max, __l);
Alexis Hunt4084c9e2011-07-15 05:40:33 +0000330#else
331 __locale_raii __current(uselocale(__l), uselocale);
332 return mbtowc(__pwc, __pmb, __max);
333#endif
334}
335
Howard Hinnant3af48ef2013-10-04 22:09:00 +0000336inline _LIBCPP_ALWAYS_INLINE
Alexis Hunt4084c9e2011-07-15 05:40:33 +0000337size_t __mbrlen_l(const char *__s, size_t __n, mbstate_t *__ps, locale_t __l)
338{
339#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
340 return mbrlen_l(__s, __n, __ps, __l);
341#else
342 __locale_raii __current(uselocale(__l), uselocale);
343 return mbrlen(__s, __n, __ps);
344#endif
345}
346
Howard Hinnant3af48ef2013-10-04 22:09:00 +0000347inline _LIBCPP_ALWAYS_INLINE
Alexis Hunt4084c9e2011-07-15 05:40:33 +0000348lconv *__localeconv_l(locale_t __l)
349{
350#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
351 return localeconv_l(__l);
352#else
353 __locale_raii __current(uselocale(__l), uselocale);
354 return localeconv();
355#endif
356}
357
Howard Hinnant3af48ef2013-10-04 22:09:00 +0000358inline _LIBCPP_ALWAYS_INLINE
Alexis Hunt4084c9e2011-07-15 05:40:33 +0000359size_t __mbsrtowcs_l(wchar_t *__dest, const char **__src, size_t __len,
360 mbstate_t *__ps, locale_t __l)
361{
362#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
363 return mbsrtowcs_l(__dest, __src, __len, __ps, __l);
364#else
365 __locale_raii __current(uselocale(__l), uselocale);
366 return mbsrtowcs(__dest, __src, __len, __ps);
367#endif
368}
369
Chandler Carruthe70a8132012-12-31 06:09:54 +0000370inline
Alexis Hunt4084c9e2011-07-15 05:40:33 +0000371int __snprintf_l(char *__s, size_t __n, locale_t __l, const char *__format, ...) {
372 va_list __va;
373 va_start(__va, __format);
374#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
375 int __res = vsnprintf_l(__s, __n, __l, __format, __va);
376#else
377 __locale_raii __current(uselocale(__l), uselocale);
378 int __res = vsnprintf(__s, __n, __format, __va);
379#endif
380 va_end(__va);
381 return __res;
382}
383
Chandler Carruthe70a8132012-12-31 06:09:54 +0000384inline
Alexis Hunt4084c9e2011-07-15 05:40:33 +0000385int __asprintf_l(char **__s, locale_t __l, const char *__format, ...) {
386 va_list __va;
387 va_start(__va, __format);
388#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
389 int __res = vasprintf_l(__s, __l, __format, __va);
390#else
391 __locale_raii __current(uselocale(__l), uselocale);
392 int __res = vasprintf(__s, __format, __va);
393#endif
394 va_end(__va);
395 return __res;
396}
397
Chandler Carruthe70a8132012-12-31 06:09:54 +0000398inline
Alexis Hunt4084c9e2011-07-15 05:40:33 +0000399int __sscanf_l(const char *__s, locale_t __l, const char *__format, ...) {
400 va_list __va;
401 va_start(__va, __format);
402#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
403 int __res = vsscanf_l(__s, __l, __format, __va);
404#else
405 __locale_raii __current(uselocale(__l), uselocale);
406 int __res = vsscanf(__s, __format, __va);
407#endif
408 va_end(__va);
409 return __res;
410}
411
Howard Hinnant9978e372011-09-28 23:39:33 +0000412#endif // __linux__
Howard Hinnant128ba712010-05-24 17:49:41 +0000413
Howard Hinnant3e519522010-05-11 19:42:16 +0000414// __scan_keyword
415// Scans [__b, __e) until a match is found in the basic_strings range
416// [__kb, __ke) or until it can be shown that there is no match in [__kb, __ke).
417// __b will be incremented (visibly), consuming CharT until a match is found
418// or proved to not exist. A keyword may be "", in which will match anything.
419// If one keyword is a prefix of another, and the next CharT in the input
420// might match another keyword, the algorithm will attempt to find the longest
421// matching keyword. If the longer matching keyword ends up not matching, then
422// no keyword match is found. If no keyword match is found, __ke is returned
423// and failbit is set in __err.
424// Else an iterator pointing to the matching keyword is found. If more than
425// one keyword matches, an iterator to the first matching keyword is returned.
Alp Tokerf03763a2014-05-15 11:27:39 +0000426// If on exit __b == __e, eofbit is set in __err. If __case_sensitive is false,
Howard Hinnant3e519522010-05-11 19:42:16 +0000427// __ct is used to force to lower case before comparing characters.
428// Examples:
429// Keywords: "a", "abb"
430// If the input is "a", the first keyword matches and eofbit is set.
431// If the input is "abc", no match is found and "ab" are consumed.
432template <class _InputIterator, class _ForwardIterator, class _Ctype>
433_LIBCPP_HIDDEN
434_ForwardIterator
435__scan_keyword(_InputIterator& __b, _InputIterator __e,
436 _ForwardIterator __kb, _ForwardIterator __ke,
437 const _Ctype& __ct, ios_base::iostate& __err,
438 bool __case_sensitive = true)
439{
440 typedef typename iterator_traits<_InputIterator>::value_type _CharT;
Howard Hinnantc2063662011-12-01 20:21:04 +0000441 size_t __nkw = static_cast<size_t>(_VSTD::distance(__kb, __ke));
Howard Hinnant3e519522010-05-11 19:42:16 +0000442 const unsigned char __doesnt_match = '\0';
443 const unsigned char __might_match = '\1';
444 const unsigned char __does_match = '\2';
445 unsigned char __statbuf[100];
446 unsigned char* __status = __statbuf;
447 unique_ptr<unsigned char, void(*)(void*)> __stat_hold(0, free);
448 if (__nkw > sizeof(__statbuf))
449 {
450 __status = (unsigned char*)malloc(__nkw);
451 if (__status == 0)
452 __throw_bad_alloc();
453 __stat_hold.reset(__status);
454 }
455 size_t __n_might_match = __nkw; // At this point, any keyword might match
456 size_t __n_does_match = 0; // but none of them definitely do
457 // Initialize all statuses to __might_match, except for "" keywords are __does_match
458 unsigned char* __st = __status;
459 for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, ++__st)
460 {
461 if (!__ky->empty())
462 *__st = __might_match;
463 else
464 {
465 *__st = __does_match;
466 --__n_might_match;
467 ++__n_does_match;
468 }
469 }
470 // While there might be a match, test keywords against the next CharT
471 for (size_t __indx = 0; __b != __e && __n_might_match > 0; ++__indx)
472 {
473 // Peek at the next CharT but don't consume it
474 _CharT __c = *__b;
475 if (!__case_sensitive)
476 __c = __ct.toupper(__c);
477 bool __consume = false;
478 // For each keyword which might match, see if the __indx character is __c
479 // If a match if found, consume __c
480 // If a match is found, and that is the last character in the keyword,
481 // then that keyword matches.
482 // If the keyword doesn't match this character, then change the keyword
483 // to doesn't match
484 __st = __status;
485 for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, ++__st)
486 {
487 if (*__st == __might_match)
488 {
489 _CharT __kc = (*__ky)[__indx];
490 if (!__case_sensitive)
491 __kc = __ct.toupper(__kc);
492 if (__c == __kc)
493 {
494 __consume = true;
495 if (__ky->size() == __indx+1)
496 {
497 *__st = __does_match;
498 --__n_might_match;
499 ++__n_does_match;
500 }
501 }
502 else
503 {
504 *__st = __doesnt_match;
505 --__n_might_match;
506 }
507 }
508 }
509 // consume if we matched a character
510 if (__consume)
511 {
512 ++__b;
513 // If we consumed a character and there might be a matched keyword that
514 // was marked matched on a previous iteration, then such keywords
515 // which are now marked as not matching.
516 if (__n_might_match + __n_does_match > 1)
517 {
518 __st = __status;
519 for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, ++__st)
520 {
521 if (*__st == __does_match && __ky->size() != __indx+1)
522 {
523 *__st = __doesnt_match;
524 --__n_does_match;
525 }
526 }
527 }
528 }
529 }
530 // We've exited the loop because we hit eof and/or we have no more "might matches".
531 if (__b == __e)
532 __err |= ios_base::eofbit;
533 // Return the first matching result
534 for (__st = __status; __kb != __ke; ++__kb, ++__st)
535 if (*__st == __does_match)
536 break;
537 if (__kb == __ke)
538 __err |= ios_base::failbit;
539 return __kb;
540}
541
Howard Hinnantf0544c22013-08-12 18:38:34 +0000542struct _LIBCPP_TYPE_VIS __num_get_base
Howard Hinnant3e519522010-05-11 19:42:16 +0000543{
544 static const int __num_get_buf_sz = 40;
545
546 static int __get_base(ios_base&);
547 static const char __src[33];
548};
549
Howard Hinnantf0544c22013-08-12 18:38:34 +0000550_LIBCPP_FUNC_VIS
Howard Hinnant3e519522010-05-11 19:42:16 +0000551void __check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
552 ios_base::iostate& __err);
553
Howard Hinnant3e519522010-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 Hinnantf1bf6f92011-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 Hinnantc2063662011-12-01 20:21:04 +0000607 if (__grouping.size() != 0 && __ct == __thousands_sep)
Howard Hinnant3e519522010-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 Hinnantf1bf6f92011-03-09 01:03:19 +0000617 if (__f >= 24)
Howard Hinnant3e519522010-05-11 19:42:16 +0000618 return -1;
Howard Hinnant3e519522010-05-11 19:42:16 +0000619 switch (__base)
620 {
621 case 8:
622 case 10:
623 if (__f >= __base)
Howard Hinnantf1bf6f92011-03-09 01:03:19 +0000624 return -1;
Howard Hinnant3e519522010-05-11 19:42:16 +0000625 break;
Howard Hinnantf1bf6f92011-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 Hinnant3e519522010-05-11 19:42:16 +0000633 return 0;
Howard Hinnantf1bf6f92011-03-09 01:03:19 +0000634 }
635 return -1;
Howard Hinnant3e519522010-05-11 19:42:16 +0000636 }
Howard Hinnante7389a62013-04-15 20:40:06 +0000637 *__a_end++ = __src[__f];
Howard Hinnant3e519522010-05-11 19:42:16 +0000638 ++__dc;
639 return 0;
640}
641
642template <class _CharT>
643int
644__num_get<_CharT>::__stage2_float_loop(_CharT __ct, bool& __in_units, char& __exp, char* __a, char*& __a_end,
645 _CharT __decimal_point, _CharT __thousands_sep, const string& __grouping,
646 unsigned* __g, unsigned*& __g_end, unsigned& __dc, _CharT* __atoms)
647{
648 if (__ct == __decimal_point)
649 {
650 if (!__in_units)
651 return -1;
652 __in_units = false;
653 *__a_end++ = '.';
654 if (__grouping.size() != 0 && __g_end-__g < __num_get_buf_sz)
655 *__g_end++ = __dc;
656 return 0;
657 }
658 if (__ct == __thousands_sep && __grouping.size() != 0)
659 {
660 if (!__in_units)
661 return -1;
662 if (__g_end-__g < __num_get_buf_sz)
663 {
664 *__g_end++ = __dc;
665 __dc = 0;
666 }
667 return 0;
668 }
669 ptrdiff_t __f = find(__atoms, __atoms + 32, __ct) - __atoms;
670 if (__f >= 32)
671 return -1;
672 char __x = __src[__f];
Howard Hinnant65609532012-02-15 19:19:37 +0000673 if (__x == '-' || __x == '+')
674 {
Howard Hinnant7e4844b2013-03-08 19:06:24 +0000675 if (__a_end == __a || (__a_end[-1] & 0x5F) == (__exp & 0x7F))
Howard Hinnant65609532012-02-15 19:19:37 +0000676 {
677 *__a_end++ = __x;
678 return 0;
679 }
680 return -1;
681 }
Howard Hinnant3e519522010-05-11 19:42:16 +0000682 if (__x == 'x' || __x == 'X')
683 __exp = 'P';
Howard Hinnant7e4844b2013-03-08 19:06:24 +0000684 else if ((__x & 0x5F) == __exp)
Howard Hinnant3e519522010-05-11 19:42:16 +0000685 {
Howard Hinnant7e4844b2013-03-08 19:06:24 +0000686 __exp |= 0x80;
687 if (__in_units)
688 {
689 __in_units = false;
690 if (__grouping.size() != 0 && __g_end-__g < __num_get_buf_sz)
691 *__g_end++ = __dc;
692 }
Howard Hinnant3e519522010-05-11 19:42:16 +0000693 }
Howard Hinnante7389a62013-04-15 20:40:06 +0000694 *__a_end++ = __x;
Howard Hinnant3e519522010-05-11 19:42:16 +0000695 if (__f >= 22)
696 return 0;
697 ++__dc;
698 return 0;
699}
700
Howard Hinnantfc88dbd2013-08-23 17:37:05 +0000701_LIBCPP_EXTERN_TEMPLATE2(struct _LIBCPP_TYPE_VIS __num_get<char>)
702_LIBCPP_EXTERN_TEMPLATE2(struct _LIBCPP_TYPE_VIS __num_get<wchar_t>)
Howard Hinnant3e519522010-05-11 19:42:16 +0000703
704template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnantf0544c22013-08-12 18:38:34 +0000705class _LIBCPP_TYPE_VIS_ONLY num_get
Howard Hinnant3e519522010-05-11 19:42:16 +0000706 : public locale::facet,
707 private __num_get<_CharT>
708{
709public:
710 typedef _CharT char_type;
711 typedef _InputIterator iter_type;
712
713 _LIBCPP_ALWAYS_INLINE
714 explicit num_get(size_t __refs = 0)
715 : locale::facet(__refs) {}
716
717 _LIBCPP_ALWAYS_INLINE
718 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
719 ios_base::iostate& __err, bool& __v) const
720 {
721 return do_get(__b, __e, __iob, __err, __v);
722 }
723
724 _LIBCPP_ALWAYS_INLINE
725 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
726 ios_base::iostate& __err, long& __v) const
727 {
728 return do_get(__b, __e, __iob, __err, __v);
729 }
730
731 _LIBCPP_ALWAYS_INLINE
732 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
733 ios_base::iostate& __err, long long& __v) const
734 {
735 return do_get(__b, __e, __iob, __err, __v);
736 }
737
738 _LIBCPP_ALWAYS_INLINE
739 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
740 ios_base::iostate& __err, unsigned short& __v) const
741 {
742 return do_get(__b, __e, __iob, __err, __v);
743 }
744
745 _LIBCPP_ALWAYS_INLINE
746 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
747 ios_base::iostate& __err, unsigned int& __v) const
748 {
749 return do_get(__b, __e, __iob, __err, __v);
750 }
751
752 _LIBCPP_ALWAYS_INLINE
753 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
754 ios_base::iostate& __err, unsigned long& __v) const
755 {
756 return do_get(__b, __e, __iob, __err, __v);
757 }
758
759 _LIBCPP_ALWAYS_INLINE
760 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
761 ios_base::iostate& __err, unsigned long long& __v) const
762 {
763 return do_get(__b, __e, __iob, __err, __v);
764 }
765
766 _LIBCPP_ALWAYS_INLINE
767 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
768 ios_base::iostate& __err, float& __v) const
769 {
770 return do_get(__b, __e, __iob, __err, __v);
771 }
772
773 _LIBCPP_ALWAYS_INLINE
774 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
775 ios_base::iostate& __err, double& __v) const
776 {
777 return do_get(__b, __e, __iob, __err, __v);
778 }
779
780 _LIBCPP_ALWAYS_INLINE
781 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
782 ios_base::iostate& __err, long double& __v) const
783 {
784 return do_get(__b, __e, __iob, __err, __v);
785 }
786
787 _LIBCPP_ALWAYS_INLINE
788 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
789 ios_base::iostate& __err, void*& __v) const
790 {
791 return do_get(__b, __e, __iob, __err, __v);
792 }
793
794 static locale::id id;
795
796protected:
Howard Hinnant848a5372010-09-22 16:48:34 +0000797 _LIBCPP_ALWAYS_INLINE
Howard Hinnant3e519522010-05-11 19:42:16 +0000798 ~num_get() {}
799
Marshall Clow9d66b722013-11-05 14:28:52 +0000800 template <class _Fp>
801 iter_type __do_get_floating_point
802 (iter_type __b, iter_type __e, ios_base& __iob,
803 ios_base::iostate& __err, _Fp& __v) const;
Marshall Clow57b8f442013-11-07 01:00:50 +0000804
805 template <class _Signed>
806 iter_type __do_get_signed
807 (iter_type __b, iter_type __e, ios_base& __iob,
808 ios_base::iostate& __err, _Signed& __v) const;
809
810 template <class _Unsigned>
811 iter_type __do_get_unsigned
812 (iter_type __b, iter_type __e, ios_base& __iob,
813 ios_base::iostate& __err, _Unsigned& __v) const;
814
815
816 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
817 ios_base::iostate& __err, bool& __v) const;
818
819 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
820 ios_base::iostate& __err, long& __v) const
821 { return this->__do_get_signed ( __b, __e, __iob, __err, __v ); }
822
823 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
824 ios_base::iostate& __err, long long& __v) const
825 { return this->__do_get_signed ( __b, __e, __iob, __err, __v ); }
826
827 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
828 ios_base::iostate& __err, unsigned short& __v) const
829 { return this->__do_get_unsigned ( __b, __e, __iob, __err, __v ); }
830
831 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
832 ios_base::iostate& __err, unsigned int& __v) const
833 { return this->__do_get_unsigned ( __b, __e, __iob, __err, __v ); }
834
835 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
836 ios_base::iostate& __err, unsigned long& __v) const
837 { return this->__do_get_unsigned ( __b, __e, __iob, __err, __v ); }
838
839 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
840 ios_base::iostate& __err, unsigned long long& __v) const
841 { return this->__do_get_unsigned ( __b, __e, __iob, __err, __v ); }
842
843 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
844 ios_base::iostate& __err, float& __v) const
845 { return this->__do_get_floating_point ( __b, __e, __iob, __err, __v ); }
846
847 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
848 ios_base::iostate& __err, double& __v) const
849 { return this->__do_get_floating_point ( __b, __e, __iob, __err, __v ); }
850
851 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
852 ios_base::iostate& __err, long double& __v) const
853 { return this->__do_get_floating_point ( __b, __e, __iob, __err, __v ); }
854
855 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
856 ios_base::iostate& __err, void*& __v) const;
Howard Hinnant3e519522010-05-11 19:42:16 +0000857};
858
859template <class _CharT, class _InputIterator>
860locale::id
861num_get<_CharT, _InputIterator>::id;
862
863template <class _Tp>
864_Tp
865__num_get_signed_integral(const char* __a, const char* __a_end,
866 ios_base::iostate& __err, int __base)
867{
868 if (__a != __a_end)
869 {
Howard Hinnant24466492013-01-22 17:26:08 +0000870 typename remove_reference<decltype(errno)>::type __save_errno = errno;
Howard Hinnanta8d8ca42011-02-25 19:52:41 +0000871 errno = 0;
Howard Hinnant3e519522010-05-11 19:42:16 +0000872 char *__p2;
Howard Hinnant0470a632011-09-28 21:05:01 +0000873 long long __ll = strtoll_l(__a, &__p2, __base, _LIBCPP_GET_C_LOCALE);
Howard Hinnant24466492013-01-22 17:26:08 +0000874 typename remove_reference<decltype(errno)>::type __current_errno = errno;
Howard Hinnanta8d8ca42011-02-25 19:52:41 +0000875 if (__current_errno == 0)
876 errno = __save_errno;
Howard Hinnant3e519522010-05-11 19:42:16 +0000877 if (__p2 != __a_end)
878 {
879 __err = ios_base::failbit;
880 return 0;
881 }
Howard Hinnanta8d8ca42011-02-25 19:52:41 +0000882 else if (__current_errno == ERANGE ||
883 __ll < numeric_limits<_Tp>::min() ||
884 numeric_limits<_Tp>::max() < __ll)
Howard Hinnant3e519522010-05-11 19:42:16 +0000885 {
886 __err = ios_base::failbit;
Howard Hinnanta8d8ca42011-02-25 19:52:41 +0000887 if (__ll > 0)
888 return numeric_limits<_Tp>::max();
889 else
890 return numeric_limits<_Tp>::min();
Howard Hinnant3e519522010-05-11 19:42:16 +0000891 }
892 return static_cast<_Tp>(__ll);
893 }
894 __err = ios_base::failbit;
895 return 0;
896}
897
898template <class _Tp>
899_Tp
900__num_get_unsigned_integral(const char* __a, const char* __a_end,
901 ios_base::iostate& __err, int __base)
902{
903 if (__a != __a_end)
904 {
Howard Hinnanta8d8ca42011-02-25 19:52:41 +0000905 if (*__a == '-')
906 {
907 __err = ios_base::failbit;
908 return 0;
909 }
Howard Hinnant24466492013-01-22 17:26:08 +0000910 typename remove_reference<decltype(errno)>::type __save_errno = errno;
Howard Hinnanta8d8ca42011-02-25 19:52:41 +0000911 errno = 0;
Howard Hinnant3e519522010-05-11 19:42:16 +0000912 char *__p2;
Howard Hinnant0470a632011-09-28 21:05:01 +0000913 unsigned long long __ll = strtoull_l(__a, &__p2, __base, _LIBCPP_GET_C_LOCALE);
Howard Hinnant24466492013-01-22 17:26:08 +0000914 typename remove_reference<decltype(errno)>::type __current_errno = errno;
Howard Hinnanta8d8ca42011-02-25 19:52:41 +0000915 if (__current_errno == 0)
916 errno = __save_errno;
Howard Hinnant3e519522010-05-11 19:42:16 +0000917 if (__p2 != __a_end)
918 {
919 __err = ios_base::failbit;
920 return 0;
921 }
Howard Hinnanta8d8ca42011-02-25 19:52:41 +0000922 else if (__current_errno == ERANGE ||
923 numeric_limits<_Tp>::max() < __ll)
Howard Hinnant3e519522010-05-11 19:42:16 +0000924 {
925 __err = ios_base::failbit;
926 return numeric_limits<_Tp>::max();
927 }
928 return static_cast<_Tp>(__ll);
929 }
930 __err = ios_base::failbit;
931 return 0;
932}
933
934template <class _Tp>
935_Tp
936__num_get_float(const char* __a, const char* __a_end, ios_base::iostate& __err)
937{
938 if (__a != __a_end)
939 {
Howard Hinnant40487ca2013-04-13 18:19:25 +0000940 typename remove_reference<decltype(errno)>::type __save_errno = errno;
941 errno = 0;
Howard Hinnant3e519522010-05-11 19:42:16 +0000942 char *__p2;
Howard Hinnant0470a632011-09-28 21:05:01 +0000943 long double __ld = strtold_l(__a, &__p2, _LIBCPP_GET_C_LOCALE);
Howard Hinnant40487ca2013-04-13 18:19:25 +0000944 typename remove_reference<decltype(errno)>::type __current_errno = errno;
945 if (__current_errno == 0)
946 errno = __save_errno;
Howard Hinnant3e519522010-05-11 19:42:16 +0000947 if (__p2 != __a_end)
948 {
949 __err = ios_base::failbit;
950 return 0;
951 }
Howard Hinnant40487ca2013-04-13 18:19:25 +0000952 else if (__current_errno == ERANGE)
953 __err = ios_base::failbit;
Howard Hinnant3e519522010-05-11 19:42:16 +0000954 return static_cast<_Tp>(__ld);
955 }
956 __err = ios_base::failbit;
957 return 0;
958}
959
960template <class _CharT, class _InputIterator>
961_InputIterator
962num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
963 ios_base& __iob,
964 ios_base::iostate& __err,
965 bool& __v) const
966{
967 if ((__iob.flags() & ios_base::boolalpha) == 0)
968 {
969 long __lv = -1;
970 __b = do_get(__b, __e, __iob, __err, __lv);
971 switch (__lv)
972 {
973 case 0:
974 __v = false;
975 break;
976 case 1:
977 __v = true;
978 break;
979 default:
980 __v = true;
981 __err = ios_base::failbit;
982 break;
983 }
984 return __b;
985 }
986 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__iob.getloc());
987 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__iob.getloc());
988 typedef typename numpunct<_CharT>::string_type string_type;
989 const string_type __names[2] = {__np.truename(), __np.falsename()};
990 const string_type* __i = __scan_keyword(__b, __e, __names, __names+2,
991 __ct, __err);
992 __v = __i == __names;
993 return __b;
994}
995
Marshall Clow57b8f442013-11-07 01:00:50 +0000996// signed
997
Howard Hinnant3e519522010-05-11 19:42:16 +0000998template <class _CharT, class _InputIterator>
Marshall Clow57b8f442013-11-07 01:00:50 +0000999template <class _Signed>
Howard Hinnant3e519522010-05-11 19:42:16 +00001000_InputIterator
Marshall Clow57b8f442013-11-07 01:00:50 +00001001num_get<_CharT, _InputIterator>::__do_get_signed(iter_type __b, iter_type __e,
Howard Hinnant3e519522010-05-11 19:42:16 +00001002 ios_base& __iob,
1003 ios_base::iostate& __err,
Marshall Clow57b8f442013-11-07 01:00:50 +00001004 _Signed& __v) const
Howard Hinnant3e519522010-05-11 19:42:16 +00001005{
1006 // Stage 1
1007 int __base = this->__get_base(__iob);
1008 // Stage 2
1009 char_type __atoms[26];
1010 char_type __thousands_sep;
1011 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
Howard Hinnante7389a62013-04-15 20:40:06 +00001012 string __buf;
1013 __buf.resize(__buf.capacity());
1014 char* __a = &__buf[0];
Howard Hinnant3e519522010-05-11 19:42:16 +00001015 char* __a_end = __a;
1016 unsigned __g[__num_get_base::__num_get_buf_sz];
1017 unsigned* __g_end = __g;
1018 unsigned __dc = 0;
1019 for (; __b != __e; ++__b)
Howard Hinnante7389a62013-04-15 20:40:06 +00001020 {
Joerg Sonnenbergera0a14362014-02-07 21:14:29 +00001021 if (__a_end == __a + __buf.size())
Howard Hinnante7389a62013-04-15 20:40:06 +00001022 {
1023 size_t __tmp = __buf.size();
1024 __buf.resize(2*__buf.size());
1025 __buf.resize(__buf.capacity());
1026 __a = &__buf[0];
1027 __a_end = __a + __tmp;
1028 }
Howard Hinnantb3371f62010-08-22 00:02:43 +00001029 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnant3e519522010-05-11 19:42:16 +00001030 __thousands_sep, __grouping, __g, __g_end,
1031 __atoms))
1032 break;
Howard Hinnante7389a62013-04-15 20:40:06 +00001033 }
Howard Hinnant3e519522010-05-11 19:42:16 +00001034 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
1035 *__g_end++ = __dc;
1036 // Stage 3
Marshall Clow57b8f442013-11-07 01:00:50 +00001037 __v = __num_get_signed_integral<_Signed>(__a, __a_end, __err, __base);
Howard Hinnant3e519522010-05-11 19:42:16 +00001038 // Digit grouping checked
1039 __check_grouping(__grouping, __g, __g_end, __err);
1040 // EOF checked
1041 if (__b == __e)
1042 __err |= ios_base::eofbit;
1043 return __b;
1044}
1045
Marshall Clow57b8f442013-11-07 01:00:50 +00001046// unsigned
Howard Hinnant3e519522010-05-11 19:42:16 +00001047
1048template <class _CharT, class _InputIterator>
Marshall Clow57b8f442013-11-07 01:00:50 +00001049template <class _Unsigned>
Howard Hinnant3e519522010-05-11 19:42:16 +00001050_InputIterator
Marshall Clow57b8f442013-11-07 01:00:50 +00001051num_get<_CharT, _InputIterator>::__do_get_unsigned(iter_type __b, iter_type __e,
Howard Hinnant3e519522010-05-11 19:42:16 +00001052 ios_base& __iob,
1053 ios_base::iostate& __err,
Marshall Clow57b8f442013-11-07 01:00:50 +00001054 _Unsigned& __v) const
Howard Hinnant3e519522010-05-11 19:42:16 +00001055{
1056 // Stage 1
1057 int __base = this->__get_base(__iob);
1058 // Stage 2
1059 char_type __atoms[26];
1060 char_type __thousands_sep;
1061 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
Howard Hinnante7389a62013-04-15 20:40:06 +00001062 string __buf;
1063 __buf.resize(__buf.capacity());
1064 char* __a = &__buf[0];
Howard Hinnant3e519522010-05-11 19:42:16 +00001065 char* __a_end = __a;
1066 unsigned __g[__num_get_base::__num_get_buf_sz];
1067 unsigned* __g_end = __g;
1068 unsigned __dc = 0;
1069 for (; __b != __e; ++__b)
Howard Hinnante7389a62013-04-15 20:40:06 +00001070 {
Joerg Sonnenbergera0a14362014-02-07 21:14:29 +00001071 if (__a_end == __a + __buf.size())
Howard Hinnante7389a62013-04-15 20:40:06 +00001072 {
1073 size_t __tmp = __buf.size();
1074 __buf.resize(2*__buf.size());
1075 __buf.resize(__buf.capacity());
1076 __a = &__buf[0];
1077 __a_end = __a + __tmp;
1078 }
Howard Hinnantb3371f62010-08-22 00:02:43 +00001079 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnant3e519522010-05-11 19:42:16 +00001080 __thousands_sep, __grouping, __g, __g_end,
1081 __atoms))
1082 break;
Howard Hinnante7389a62013-04-15 20:40:06 +00001083 }
Howard Hinnant3e519522010-05-11 19:42:16 +00001084 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
1085 *__g_end++ = __dc;
1086 // Stage 3
Marshall Clow57b8f442013-11-07 01:00:50 +00001087 __v = __num_get_unsigned_integral<_Unsigned>(__a, __a_end, __err, __base);
Howard Hinnant3e519522010-05-11 19:42:16 +00001088 // Digit grouping checked
1089 __check_grouping(__grouping, __g, __g_end, __err);
1090 // EOF checked
1091 if (__b == __e)
1092 __err |= ios_base::eofbit;
1093 return __b;
1094}
1095
Marshall Clow9d66b722013-11-05 14:28:52 +00001096// floating point
1097
Howard Hinnant3e519522010-05-11 19:42:16 +00001098template <class _CharT, class _InputIterator>
Marshall Clow9d66b722013-11-05 14:28:52 +00001099template <class _Fp>
Howard Hinnant3e519522010-05-11 19:42:16 +00001100_InputIterator
Marshall Clow9d66b722013-11-05 14:28:52 +00001101num_get<_CharT, _InputIterator>::__do_get_floating_point(iter_type __b, iter_type __e,
Howard Hinnant3e519522010-05-11 19:42:16 +00001102 ios_base& __iob,
1103 ios_base::iostate& __err,
Marshall Clow9d66b722013-11-05 14:28:52 +00001104 _Fp& __v) const
Howard Hinnant3e519522010-05-11 19:42:16 +00001105{
1106 // Stage 1, nothing to do
1107 // Stage 2
1108 char_type __atoms[32];
1109 char_type __decimal_point;
1110 char_type __thousands_sep;
Howard Hinnantb3371f62010-08-22 00:02:43 +00001111 string __grouping = this->__stage2_float_prep(__iob, __atoms,
1112 __decimal_point,
Howard Hinnant3e519522010-05-11 19:42:16 +00001113 __thousands_sep);
Howard Hinnante7389a62013-04-15 20:40:06 +00001114 string __buf;
1115 __buf.resize(__buf.capacity());
1116 char* __a = &__buf[0];
Howard Hinnant3e519522010-05-11 19:42:16 +00001117 char* __a_end = __a;
1118 unsigned __g[__num_get_base::__num_get_buf_sz];
1119 unsigned* __g_end = __g;
1120 unsigned __dc = 0;
1121 bool __in_units = true;
1122 char __exp = 'E';
1123 for (; __b != __e; ++__b)
Howard Hinnante7389a62013-04-15 20:40:06 +00001124 {
Joerg Sonnenbergera0a14362014-02-07 21:14:29 +00001125 if (__a_end == __a + __buf.size())
Howard Hinnante7389a62013-04-15 20:40:06 +00001126 {
1127 size_t __tmp = __buf.size();
1128 __buf.resize(2*__buf.size());
1129 __buf.resize(__buf.capacity());
1130 __a = &__buf[0];
1131 __a_end = __a + __tmp;
1132 }
Howard Hinnantb3371f62010-08-22 00:02:43 +00001133 if (this->__stage2_float_loop(*__b, __in_units, __exp, __a, __a_end,
1134 __decimal_point, __thousands_sep,
Howard Hinnant3e519522010-05-11 19:42:16 +00001135 __grouping, __g, __g_end,
1136 __dc, __atoms))
1137 break;
Howard Hinnante7389a62013-04-15 20:40:06 +00001138 }
Howard Hinnant3e519522010-05-11 19:42:16 +00001139 if (__grouping.size() != 0 && __in_units && __g_end-__g < __num_get_base::__num_get_buf_sz)
1140 *__g_end++ = __dc;
1141 // Stage 3
Marshall Clow9d66b722013-11-05 14:28:52 +00001142 __v = __num_get_float<_Fp>(__a, __a_end, __err);
Howard Hinnant3e519522010-05-11 19:42:16 +00001143 // Digit grouping checked
1144 __check_grouping(__grouping, __g, __g_end, __err);
1145 // EOF checked
1146 if (__b == __e)
1147 __err |= ios_base::eofbit;
1148 return __b;
1149}
1150
1151template <class _CharT, class _InputIterator>
1152_InputIterator
1153num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1154 ios_base& __iob,
1155 ios_base::iostate& __err,
Howard Hinnant3e519522010-05-11 19:42:16 +00001156 void*& __v) const
1157{
1158 // Stage 1
1159 int __base = 16;
1160 // Stage 2
1161 char_type __atoms[26];
Howard Hinnantc2063662011-12-01 20:21:04 +00001162 char_type __thousands_sep = 0;
Howard Hinnant3e519522010-05-11 19:42:16 +00001163 string __grouping;
1164 use_facet<ctype<_CharT> >(__iob.getloc()).widen(__num_get_base::__src,
1165 __num_get_base::__src + 26, __atoms);
Howard Hinnante7389a62013-04-15 20:40:06 +00001166 string __buf;
1167 __buf.resize(__buf.capacity());
1168 char* __a = &__buf[0];
Howard Hinnant3e519522010-05-11 19:42:16 +00001169 char* __a_end = __a;
1170 unsigned __g[__num_get_base::__num_get_buf_sz];
1171 unsigned* __g_end = __g;
1172 unsigned __dc = 0;
1173 for (; __b != __e; ++__b)
Howard Hinnante7389a62013-04-15 20:40:06 +00001174 {
Joerg Sonnenbergera0a14362014-02-07 21:14:29 +00001175 if (__a_end == __a + __buf.size())
Howard Hinnante7389a62013-04-15 20:40:06 +00001176 {
1177 size_t __tmp = __buf.size();
1178 __buf.resize(2*__buf.size());
1179 __buf.resize(__buf.capacity());
1180 __a = &__buf[0];
1181 __a_end = __a + __tmp;
1182 }
Howard Hinnantb3371f62010-08-22 00:02:43 +00001183 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
1184 __thousands_sep, __grouping,
Howard Hinnant3e519522010-05-11 19:42:16 +00001185 __g, __g_end, __atoms))
1186 break;
Howard Hinnante7389a62013-04-15 20:40:06 +00001187 }
Howard Hinnant3e519522010-05-11 19:42:16 +00001188 // Stage 3
Marshall Clowef0e8c32014-05-21 16:02:20 +00001189 __buf.resize(__a_end - __a);
Howard Hinnant9978e372011-09-28 23:39:33 +00001190#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Marshall Clowef0e8c32014-05-21 16:02:20 +00001191 if (sscanf_l(__buf.c_str(), _LIBCPP_GET_C_LOCALE, "%p", &__v) != 1)
Alexis Hunt4084c9e2011-07-15 05:40:33 +00001192#else
Marshall Clowef0e8c32014-05-21 16:02:20 +00001193 if (__sscanf_l(__buf.c_str(), __cloc(), "%p", &__v) != 1)
Alexis Hunt4084c9e2011-07-15 05:40:33 +00001194#endif
Howard Hinnant3e519522010-05-11 19:42:16 +00001195 __err = ios_base::failbit;
1196 // EOF checked
1197 if (__b == __e)
1198 __err |= ios_base::eofbit;
1199 return __b;
1200}
1201
Howard Hinnantfc88dbd2013-08-23 17:37:05 +00001202_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS num_get<char>)
1203_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS num_get<wchar_t>)
Howard Hinnant3e519522010-05-11 19:42:16 +00001204
Howard Hinnantf0544c22013-08-12 18:38:34 +00001205struct _LIBCPP_TYPE_VIS __num_put_base
Howard Hinnant3e519522010-05-11 19:42:16 +00001206{
1207protected:
1208 static void __format_int(char* __fmt, const char* __len, bool __signd,
1209 ios_base::fmtflags __flags);
1210 static bool __format_float(char* __fmt, const char* __len,
1211 ios_base::fmtflags __flags);
1212 static char* __identify_padding(char* __nb, char* __ne,
1213 const ios_base& __iob);
1214};
1215
1216template <class _CharT>
1217struct __num_put
1218 : protected __num_put_base
1219{
1220 static void __widen_and_group_int(char* __nb, char* __np, char* __ne,
1221 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1222 const locale& __loc);
1223 static void __widen_and_group_float(char* __nb, char* __np, char* __ne,
1224 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1225 const locale& __loc);
1226};
1227
1228template <class _CharT>
1229void
1230__num_put<_CharT>::__widen_and_group_int(char* __nb, char* __np, char* __ne,
1231 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1232 const locale& __loc)
1233{
1234 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> > (__loc);
1235 const numpunct<_CharT>& __npt = use_facet<numpunct<_CharT> >(__loc);
1236 string __grouping = __npt.grouping();
1237 if (__grouping.empty())
1238 {
1239 __ct.widen(__nb, __ne, __ob);
1240 __oe = __ob + (__ne - __nb);
1241 }
1242 else
1243 {
1244 __oe = __ob;
1245 char* __nf = __nb;
1246 if (*__nf == '-' || *__nf == '+')
1247 *__oe++ = __ct.widen(*__nf++);
1248 if (__ne - __nf >= 2 && __nf[0] == '0' && (__nf[1] == 'x' ||
1249 __nf[1] == 'X'))
1250 {
1251 *__oe++ = __ct.widen(*__nf++);
1252 *__oe++ = __ct.widen(*__nf++);
1253 }
1254 reverse(__nf, __ne);
1255 _CharT __thousands_sep = __npt.thousands_sep();
1256 unsigned __dc = 0;
1257 unsigned __dg = 0;
1258 for (char* __p = __nf; __p < __ne; ++__p)
1259 {
1260 if (static_cast<unsigned>(__grouping[__dg]) > 0 &&
1261 __dc == static_cast<unsigned>(__grouping[__dg]))
1262 {
1263 *__oe++ = __thousands_sep;
1264 __dc = 0;
1265 if (__dg < __grouping.size()-1)
1266 ++__dg;
1267 }
1268 *__oe++ = __ct.widen(*__p);
1269 ++__dc;
1270 }
1271 reverse(__ob + (__nf - __nb), __oe);
1272 }
1273 if (__np == __ne)
1274 __op = __oe;
1275 else
1276 __op = __ob + (__np - __nb);
1277}
1278
1279template <class _CharT>
1280void
1281__num_put<_CharT>::__widen_and_group_float(char* __nb, char* __np, char* __ne,
1282 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1283 const locale& __loc)
1284{
1285 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> > (__loc);
1286 const numpunct<_CharT>& __npt = use_facet<numpunct<_CharT> >(__loc);
1287 string __grouping = __npt.grouping();
1288 __oe = __ob;
1289 char* __nf = __nb;
1290 if (*__nf == '-' || *__nf == '+')
1291 *__oe++ = __ct.widen(*__nf++);
1292 char* __ns;
1293 if (__ne - __nf >= 2 && __nf[0] == '0' && (__nf[1] == 'x' ||
1294 __nf[1] == 'X'))
1295 {
1296 *__oe++ = __ct.widen(*__nf++);
1297 *__oe++ = __ct.widen(*__nf++);
1298 for (__ns = __nf; __ns < __ne; ++__ns)
Howard Hinnant0470a632011-09-28 21:05:01 +00001299 if (!isxdigit_l(*__ns, _LIBCPP_GET_C_LOCALE))
Howard Hinnant3e519522010-05-11 19:42:16 +00001300 break;
1301 }
1302 else
1303 {
1304 for (__ns = __nf; __ns < __ne; ++__ns)
Howard Hinnant0470a632011-09-28 21:05:01 +00001305 if (!isdigit_l(*__ns, _LIBCPP_GET_C_LOCALE))
Howard Hinnant3e519522010-05-11 19:42:16 +00001306 break;
1307 }
1308 if (__grouping.empty())
1309 {
1310 __ct.widen(__nf, __ns, __oe);
1311 __oe += __ns - __nf;
1312 }
1313 else
1314 {
1315 reverse(__nf, __ns);
1316 _CharT __thousands_sep = __npt.thousands_sep();
1317 unsigned __dc = 0;
1318 unsigned __dg = 0;
1319 for (char* __p = __nf; __p < __ns; ++__p)
1320 {
1321 if (__grouping[__dg] > 0 && __dc == static_cast<unsigned>(__grouping[__dg]))
1322 {
1323 *__oe++ = __thousands_sep;
1324 __dc = 0;
1325 if (__dg < __grouping.size()-1)
1326 ++__dg;
1327 }
1328 *__oe++ = __ct.widen(*__p);
1329 ++__dc;
1330 }
1331 reverse(__ob + (__nf - __nb), __oe);
1332 }
1333 for (__nf = __ns; __nf < __ne; ++__nf)
1334 {
1335 if (*__nf == '.')
1336 {
1337 *__oe++ = __npt.decimal_point();
1338 ++__nf;
1339 break;
1340 }
1341 else
1342 *__oe++ = __ct.widen(*__nf);
1343 }
1344 __ct.widen(__nf, __ne, __oe);
1345 __oe += __ne - __nf;
1346 if (__np == __ne)
1347 __op = __oe;
1348 else
1349 __op = __ob + (__np - __nb);
1350}
1351
Howard Hinnantfc88dbd2013-08-23 17:37:05 +00001352_LIBCPP_EXTERN_TEMPLATE2(struct _LIBCPP_TYPE_VIS __num_put<char>)
1353_LIBCPP_EXTERN_TEMPLATE2(struct _LIBCPP_TYPE_VIS __num_put<wchar_t>)
Howard Hinnant3e519522010-05-11 19:42:16 +00001354
1355template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnantf0544c22013-08-12 18:38:34 +00001356class _LIBCPP_TYPE_VIS_ONLY num_put
Howard Hinnant3e519522010-05-11 19:42:16 +00001357 : public locale::facet,
1358 private __num_put<_CharT>
1359{
1360public:
1361 typedef _CharT char_type;
1362 typedef _OutputIterator iter_type;
1363
1364 _LIBCPP_ALWAYS_INLINE
1365 explicit num_put(size_t __refs = 0)
1366 : locale::facet(__refs) {}
1367
1368 _LIBCPP_ALWAYS_INLINE
1369 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1370 bool __v) const
1371 {
1372 return do_put(__s, __iob, __fl, __v);
1373 }
1374
1375 _LIBCPP_ALWAYS_INLINE
1376 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1377 long __v) const
1378 {
1379 return do_put(__s, __iob, __fl, __v);
1380 }
1381
1382 _LIBCPP_ALWAYS_INLINE
1383 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1384 long long __v) const
1385 {
1386 return do_put(__s, __iob, __fl, __v);
1387 }
1388
1389 _LIBCPP_ALWAYS_INLINE
1390 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1391 unsigned long __v) const
1392 {
1393 return do_put(__s, __iob, __fl, __v);
1394 }
1395
1396 _LIBCPP_ALWAYS_INLINE
1397 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1398 unsigned long long __v) const
1399 {
1400 return do_put(__s, __iob, __fl, __v);
1401 }
1402
1403 _LIBCPP_ALWAYS_INLINE
1404 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1405 double __v) const
1406 {
1407 return do_put(__s, __iob, __fl, __v);
1408 }
1409
1410 _LIBCPP_ALWAYS_INLINE
1411 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1412 long double __v) const
1413 {
1414 return do_put(__s, __iob, __fl, __v);
1415 }
1416
1417 _LIBCPP_ALWAYS_INLINE
1418 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1419 const void* __v) const
1420 {
1421 return do_put(__s, __iob, __fl, __v);
1422 }
1423
1424 static locale::id id;
1425
1426protected:
Howard Hinnant848a5372010-09-22 16:48:34 +00001427 _LIBCPP_ALWAYS_INLINE
Howard Hinnant3e519522010-05-11 19:42:16 +00001428 ~num_put() {}
1429
1430 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1431 bool __v) const;
1432 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1433 long __v) const;
1434 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1435 long long __v) const;
1436 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1437 unsigned long) const;
1438 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1439 unsigned long long) const;
1440 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1441 double __v) const;
1442 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1443 long double __v) const;
1444 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1445 const void* __v) const;
1446};
1447
1448template <class _CharT, class _OutputIterator>
1449locale::id
1450num_put<_CharT, _OutputIterator>::id;
1451
1452template <class _CharT, class _OutputIterator>
1453_LIBCPP_HIDDEN
1454_OutputIterator
1455__pad_and_output(_OutputIterator __s,
1456 const _CharT* __ob, const _CharT* __op, const _CharT* __oe,
1457 ios_base& __iob, _CharT __fl)
1458{
1459 streamsize __sz = __oe - __ob;
1460 streamsize __ns = __iob.width();
1461 if (__ns > __sz)
1462 __ns -= __sz;
1463 else
1464 __ns = 0;
1465 for (;__ob < __op; ++__ob, ++__s)
1466 *__s = *__ob;
1467 for (; __ns; --__ns, ++__s)
1468 *__s = __fl;
1469 for (; __ob < __oe; ++__ob, ++__s)
1470 *__s = *__ob;
1471 __iob.width(0);
1472 return __s;
1473}
1474
Howard Hinnantb5c63a22012-11-14 21:17:15 +00001475#if !defined(__APPLE__) || \
1476 (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED > __MAC_10_8) || \
1477 (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED > __IPHONE_6_0)
1478
Howard Hinnant92b59402012-09-19 19:14:15 +00001479template <class _CharT, class _Traits>
1480_LIBCPP_HIDDEN
1481ostreambuf_iterator<_CharT, _Traits>
1482__pad_and_output(ostreambuf_iterator<_CharT, _Traits> __s,
1483 const _CharT* __ob, const _CharT* __op, const _CharT* __oe,
1484 ios_base& __iob, _CharT __fl)
1485{
1486 if (__s.__sbuf_ == nullptr)
1487 return __s;
1488 streamsize __sz = __oe - __ob;
1489 streamsize __ns = __iob.width();
1490 if (__ns > __sz)
1491 __ns -= __sz;
1492 else
1493 __ns = 0;
1494 streamsize __np = __op - __ob;
1495 if (__np > 0)
1496 {
1497 if (__s.__sbuf_->sputn(__ob, __np) != __np)
1498 {
1499 __s.__sbuf_ = nullptr;
1500 return __s;
1501 }
1502 }
1503 if (__ns > 0)
1504 {
1505 basic_string<_CharT, _Traits> __sp(__ns, __fl);
1506 if (__s.__sbuf_->sputn(__sp.data(), __ns) != __ns)
1507 {
1508 __s.__sbuf_ = nullptr;
1509 return __s;
1510 }
1511 }
1512 __np = __oe - __op;
1513 if (__np > 0)
1514 {
1515 if (__s.__sbuf_->sputn(__op, __np) != __np)
1516 {
1517 __s.__sbuf_ = nullptr;
1518 return __s;
1519 }
1520 }
1521 __iob.width(0);
1522 return __s;
1523}
1524
Howard Hinnantb5c63a22012-11-14 21:17:15 +00001525#endif
1526
Howard Hinnant3e519522010-05-11 19:42:16 +00001527template <class _CharT, class _OutputIterator>
1528_OutputIterator
1529num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1530 char_type __fl, bool __v) const
1531{
1532 if ((__iob.flags() & ios_base::boolalpha) == 0)
1533 return do_put(__s, __iob, __fl, (unsigned long)__v);
1534 const numpunct<char_type>& __np = use_facet<numpunct<char_type> >(__iob.getloc());
1535 typedef typename numpunct<char_type>::string_type string_type;
Howard Hinnantfc88dbd2013-08-23 17:37:05 +00001536#if _LIBCPP_DEBUG_LEVEL >= 2
1537 string_type __tmp(__v ? __np.truename() : __np.falsename());
1538 string_type __nm = _VSTD::move(__tmp);
1539#else
Howard Hinnant3e519522010-05-11 19:42:16 +00001540 string_type __nm = __v ? __np.truename() : __np.falsename();
Howard Hinnantfc88dbd2013-08-23 17:37:05 +00001541#endif
Howard Hinnant3e519522010-05-11 19:42:16 +00001542 for (typename string_type::iterator __i = __nm.begin(); __i != __nm.end(); ++__i, ++__s)
1543 *__s = *__i;
1544 return __s;
1545}
1546
1547template <class _CharT, class _OutputIterator>
1548_OutputIterator
1549num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1550 char_type __fl, long __v) const
1551{
1552 // Stage 1 - Get number in narrow char
1553 char __fmt[6] = {'%', 0};
1554 const char* __len = "l";
1555 this->__format_int(__fmt+1, __len, true, __iob.flags());
1556 const unsigned __nbuf = (numeric_limits<long>::digits / 3)
1557 + ((numeric_limits<long>::digits % 3) != 0)
1558 + 1;
1559 char __nar[__nbuf];
Howard Hinnant9978e372011-09-28 23:39:33 +00001560#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant9cfcdcb2013-07-02 18:42:28 +00001561 int __nc = snprintf_l(__nar, sizeof(__nar), _LIBCPP_GET_C_LOCALE, __fmt, __v);
Alexis Hunt4084c9e2011-07-15 05:40:33 +00001562#else
Howard Hinnant9cfcdcb2013-07-02 18:42:28 +00001563 int __nc = __snprintf_l(__nar, sizeof(__nar), __cloc(), __fmt, __v);
Alexis Hunt4084c9e2011-07-15 05:40:33 +00001564#endif
Howard Hinnant3e519522010-05-11 19:42:16 +00001565 char* __ne = __nar + __nc;
1566 char* __np = this->__identify_padding(__nar, __ne, __iob);
1567 // Stage 2 - Widen __nar while adding thousands separators
1568 char_type __o[2*(__nbuf-1) - 1];
1569 char_type* __op; // pad here
1570 char_type* __oe; // end of output
1571 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1572 // [__o, __oe) contains thousands_sep'd wide number
1573 // Stage 3 & 4
1574 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1575}
1576
1577template <class _CharT, class _OutputIterator>
1578_OutputIterator
1579num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1580 char_type __fl, long long __v) const
1581{
1582 // Stage 1 - Get number in narrow char
1583 char __fmt[8] = {'%', 0};
1584 const char* __len = "ll";
1585 this->__format_int(__fmt+1, __len, true, __iob.flags());
1586 const unsigned __nbuf = (numeric_limits<long long>::digits / 3)
1587 + ((numeric_limits<long long>::digits % 3) != 0)
1588 + 1;
1589 char __nar[__nbuf];
Howard Hinnant9978e372011-09-28 23:39:33 +00001590#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant9cfcdcb2013-07-02 18:42:28 +00001591 int __nc = snprintf_l(__nar, sizeof(__nar), _LIBCPP_GET_C_LOCALE, __fmt, __v);
Alexis Hunt4084c9e2011-07-15 05:40:33 +00001592#else
Howard Hinnant9cfcdcb2013-07-02 18:42:28 +00001593 int __nc = __snprintf_l(__nar, sizeof(__nar), __cloc(), __fmt, __v);
Alexis Hunt4084c9e2011-07-15 05:40:33 +00001594#endif
Howard Hinnant3e519522010-05-11 19:42:16 +00001595 char* __ne = __nar + __nc;
1596 char* __np = this->__identify_padding(__nar, __ne, __iob);
1597 // Stage 2 - Widen __nar while adding thousands separators
1598 char_type __o[2*(__nbuf-1) - 1];
1599 char_type* __op; // pad here
1600 char_type* __oe; // end of output
1601 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1602 // [__o, __oe) contains thousands_sep'd wide number
1603 // Stage 3 & 4
1604 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1605}
1606
1607template <class _CharT, class _OutputIterator>
1608_OutputIterator
1609num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1610 char_type __fl, unsigned long __v) const
1611{
1612 // Stage 1 - Get number in narrow char
1613 char __fmt[6] = {'%', 0};
1614 const char* __len = "l";
1615 this->__format_int(__fmt+1, __len, false, __iob.flags());
1616 const unsigned __nbuf = (numeric_limits<unsigned long>::digits / 3)
1617 + ((numeric_limits<unsigned long>::digits % 3) != 0)
1618 + 1;
1619 char __nar[__nbuf];
Howard Hinnant9978e372011-09-28 23:39:33 +00001620#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant9cfcdcb2013-07-02 18:42:28 +00001621 int __nc = snprintf_l(__nar, sizeof(__nar), _LIBCPP_GET_C_LOCALE, __fmt, __v);
Alexis Hunt4084c9e2011-07-15 05:40:33 +00001622#else
Howard Hinnant9cfcdcb2013-07-02 18:42:28 +00001623 int __nc = __snprintf_l(__nar, sizeof(__nar), __cloc(), __fmt, __v);
Alexis Hunt4084c9e2011-07-15 05:40:33 +00001624#endif
Howard Hinnant3e519522010-05-11 19:42:16 +00001625 char* __ne = __nar + __nc;
1626 char* __np = this->__identify_padding(__nar, __ne, __iob);
1627 // Stage 2 - Widen __nar while adding thousands separators
1628 char_type __o[2*(__nbuf-1) - 1];
1629 char_type* __op; // pad here
1630 char_type* __oe; // end of output
1631 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1632 // [__o, __oe) contains thousands_sep'd wide number
1633 // Stage 3 & 4
1634 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1635}
1636
1637template <class _CharT, class _OutputIterator>
1638_OutputIterator
1639num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1640 char_type __fl, unsigned long long __v) const
1641{
1642 // Stage 1 - Get number in narrow char
1643 char __fmt[8] = {'%', 0};
1644 const char* __len = "ll";
1645 this->__format_int(__fmt+1, __len, false, __iob.flags());
1646 const unsigned __nbuf = (numeric_limits<unsigned long long>::digits / 3)
1647 + ((numeric_limits<unsigned long long>::digits % 3) != 0)
1648 + 1;
1649 char __nar[__nbuf];
Howard Hinnant9978e372011-09-28 23:39:33 +00001650#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant9cfcdcb2013-07-02 18:42:28 +00001651 int __nc = snprintf_l(__nar, sizeof(__nar), _LIBCPP_GET_C_LOCALE, __fmt, __v);
Alexis Hunt4084c9e2011-07-15 05:40:33 +00001652#else
Howard Hinnant9cfcdcb2013-07-02 18:42:28 +00001653 int __nc = __snprintf_l(__nar, sizeof(__nar), __cloc(), __fmt, __v);
Alexis Hunt4084c9e2011-07-15 05:40:33 +00001654#endif
Howard Hinnant3e519522010-05-11 19:42:16 +00001655 char* __ne = __nar + __nc;
1656 char* __np = this->__identify_padding(__nar, __ne, __iob);
1657 // Stage 2 - Widen __nar while adding thousands separators
1658 char_type __o[2*(__nbuf-1) - 1];
1659 char_type* __op; // pad here
1660 char_type* __oe; // end of output
1661 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1662 // [__o, __oe) contains thousands_sep'd wide number
1663 // Stage 3 & 4
1664 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1665}
1666
1667template <class _CharT, class _OutputIterator>
1668_OutputIterator
1669num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1670 char_type __fl, double __v) const
1671{
1672 // Stage 1 - Get number in narrow char
1673 char __fmt[8] = {'%', 0};
1674 const char* __len = "";
1675 bool __specify_precision = this->__format_float(__fmt+1, __len, __iob.flags());
1676 const unsigned __nbuf = 30;
1677 char __nar[__nbuf];
1678 char* __nb = __nar;
1679 int __nc;
1680 if (__specify_precision)
Howard Hinnant9978e372011-09-28 23:39:33 +00001681#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant0470a632011-09-28 21:05:01 +00001682 __nc = snprintf_l(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt,
Howard Hinnant128ba712010-05-24 17:49:41 +00001683 (int)__iob.precision(), __v);
Alexis Hunt4084c9e2011-07-15 05:40:33 +00001684#else
1685 __nc = __snprintf_l(__nb, __nbuf, __cloc(), __fmt,
1686 (int)__iob.precision(), __v);
1687#endif
Howard Hinnant3e519522010-05-11 19:42:16 +00001688 else
Howard Hinnant9978e372011-09-28 23:39:33 +00001689#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant0470a632011-09-28 21:05:01 +00001690 __nc = snprintf_l(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Alexis Hunt4084c9e2011-07-15 05:40:33 +00001691#else
1692 __nc = __snprintf_l(__nb, __nbuf, __cloc(), __fmt, __v);
1693#endif
Howard Hinnant3e519522010-05-11 19:42:16 +00001694 unique_ptr<char, void(*)(void*)> __nbh(0, free);
1695 if (__nc > static_cast<int>(__nbuf-1))
1696 {
1697 if (__specify_precision)
Howard Hinnant9978e372011-09-28 23:39:33 +00001698#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant0470a632011-09-28 21:05:01 +00001699 __nc = asprintf_l(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, (int)__iob.precision(), __v);
Alexis Hunt4084c9e2011-07-15 05:40:33 +00001700#else
1701 __nc = __asprintf_l(&__nb, __cloc(), __fmt,
David Chisnall89728132011-09-21 08:39:44 +00001702 (int)__iob.precision(), __v);
Alexis Hunt4084c9e2011-07-15 05:40:33 +00001703#endif
Howard Hinnant3e519522010-05-11 19:42:16 +00001704 else
Howard Hinnant9978e372011-09-28 23:39:33 +00001705#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant0470a632011-09-28 21:05:01 +00001706 __nc = asprintf_l(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Alexis Hunt4084c9e2011-07-15 05:40:33 +00001707#else
David Chisnall89728132011-09-21 08:39:44 +00001708 __nc = __asprintf_l(&__nb, __cloc(), __fmt, (int)__iob.precision(), __v);
Alexis Hunt4084c9e2011-07-15 05:40:33 +00001709#endif
Howard Hinnant3e519522010-05-11 19:42:16 +00001710 if (__nb == 0)
1711 __throw_bad_alloc();
1712 __nbh.reset(__nb);
1713 }
1714 char* __ne = __nb + __nc;
1715 char* __np = this->__identify_padding(__nb, __ne, __iob);
1716 // Stage 2 - Widen __nar while adding thousands separators
1717 char_type __o[2*(__nbuf-1) - 1];
1718 char_type* __ob = __o;
1719 unique_ptr<char_type, void(*)(void*)> __obh(0, free);
1720 if (__nb != __nar)
1721 {
Howard Hinnantc2063662011-12-01 20:21:04 +00001722 __ob = (char_type*)malloc(2*static_cast<size_t>(__nc)*sizeof(char_type));
Howard Hinnant3e519522010-05-11 19:42:16 +00001723 if (__ob == 0)
1724 __throw_bad_alloc();
1725 __obh.reset(__ob);
1726 }
1727 char_type* __op; // pad here
1728 char_type* __oe; // end of output
1729 this->__widen_and_group_float(__nb, __np, __ne, __ob, __op, __oe, __iob.getloc());
1730 // [__o, __oe) contains thousands_sep'd wide number
1731 // Stage 3 & 4
1732 __s = __pad_and_output(__s, __ob, __op, __oe, __iob, __fl);
1733 return __s;
1734}
1735
1736template <class _CharT, class _OutputIterator>
1737_OutputIterator
1738num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1739 char_type __fl, long double __v) const
1740{
1741 // Stage 1 - Get number in narrow char
1742 char __fmt[8] = {'%', 0};
1743 const char* __len = "L";
1744 bool __specify_precision = this->__format_float(__fmt+1, __len, __iob.flags());
1745 const unsigned __nbuf = 30;
1746 char __nar[__nbuf];
1747 char* __nb = __nar;
1748 int __nc;
1749 if (__specify_precision)
Howard Hinnant9978e372011-09-28 23:39:33 +00001750#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant0470a632011-09-28 21:05:01 +00001751 __nc = snprintf_l(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt,
Howard Hinnant128ba712010-05-24 17:49:41 +00001752 (int)__iob.precision(), __v);
Alexis Hunt4084c9e2011-07-15 05:40:33 +00001753#else
1754 __nc = __snprintf_l(__nb, __nbuf, __cloc(), __fmt,
1755 (int)__iob.precision(), __v);
1756#endif
Howard Hinnant3e519522010-05-11 19:42:16 +00001757 else
Howard Hinnant9978e372011-09-28 23:39:33 +00001758#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant0470a632011-09-28 21:05:01 +00001759 __nc = snprintf_l(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Alexis Hunt4084c9e2011-07-15 05:40:33 +00001760#else
1761 __nc = __snprintf_l(__nb, __nbuf, __cloc(), __fmt, __v);
1762#endif
Howard Hinnant3e519522010-05-11 19:42:16 +00001763 unique_ptr<char, void(*)(void*)> __nbh(0, free);
1764 if (__nc > static_cast<int>(__nbuf-1))
1765 {
1766 if (__specify_precision)
Howard Hinnant9978e372011-09-28 23:39:33 +00001767#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant0470a632011-09-28 21:05:01 +00001768 __nc = asprintf_l(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, (int)__iob.precision(), __v);
Alexis Hunt4084c9e2011-07-15 05:40:33 +00001769#else
1770 __nc = __asprintf_l(&__nb, __cloc(), __fmt,
David Chisnall89728132011-09-21 08:39:44 +00001771 (int)__iob.precision(), __v);
Alexis Hunt4084c9e2011-07-15 05:40:33 +00001772#endif
Howard Hinnant3e519522010-05-11 19:42:16 +00001773 else
Howard Hinnant9978e372011-09-28 23:39:33 +00001774#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant0470a632011-09-28 21:05:01 +00001775 __nc = asprintf_l(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Alexis Hunt4084c9e2011-07-15 05:40:33 +00001776#else
David Chisnall89728132011-09-21 08:39:44 +00001777 __nc = __asprintf_l(&__nb, __cloc(), __fmt, __v);
Alexis Hunt4084c9e2011-07-15 05:40:33 +00001778#endif
Howard Hinnant3e519522010-05-11 19:42:16 +00001779 if (__nb == 0)
1780 __throw_bad_alloc();
1781 __nbh.reset(__nb);
1782 }
1783 char* __ne = __nb + __nc;
1784 char* __np = this->__identify_padding(__nb, __ne, __iob);
1785 // Stage 2 - Widen __nar while adding thousands separators
1786 char_type __o[2*(__nbuf-1) - 1];
1787 char_type* __ob = __o;
1788 unique_ptr<char_type, void(*)(void*)> __obh(0, free);
1789 if (__nb != __nar)
1790 {
Howard Hinnantc2063662011-12-01 20:21:04 +00001791 __ob = (char_type*)malloc(2*static_cast<size_t>(__nc)*sizeof(char_type));
Howard Hinnant3e519522010-05-11 19:42:16 +00001792 if (__ob == 0)
1793 __throw_bad_alloc();
1794 __obh.reset(__ob);
1795 }
1796 char_type* __op; // pad here
1797 char_type* __oe; // end of output
1798 this->__widen_and_group_float(__nb, __np, __ne, __ob, __op, __oe, __iob.getloc());
1799 // [__o, __oe) contains thousands_sep'd wide number
1800 // Stage 3 & 4
1801 __s = __pad_and_output(__s, __ob, __op, __oe, __iob, __fl);
1802 return __s;
1803}
1804
1805template <class _CharT, class _OutputIterator>
1806_OutputIterator
1807num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1808 char_type __fl, const void* __v) const
1809{
1810 // Stage 1 - Get pointer in narrow char
1811 char __fmt[6] = "%p";
1812 const unsigned __nbuf = 20;
1813 char __nar[__nbuf];
Howard Hinnant9978e372011-09-28 23:39:33 +00001814#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant9cfcdcb2013-07-02 18:42:28 +00001815 int __nc = snprintf_l(__nar, sizeof(__nar), _LIBCPP_GET_C_LOCALE, __fmt, __v);
Alexis Hunt4084c9e2011-07-15 05:40:33 +00001816#else
Howard Hinnant9cfcdcb2013-07-02 18:42:28 +00001817 int __nc = __snprintf_l(__nar, sizeof(__nar), __cloc(), __fmt, __v);
Alexis Hunt4084c9e2011-07-15 05:40:33 +00001818#endif
Howard Hinnant3e519522010-05-11 19:42:16 +00001819 char* __ne = __nar + __nc;
1820 char* __np = this->__identify_padding(__nar, __ne, __iob);
1821 // Stage 2 - Widen __nar
1822 char_type __o[2*(__nbuf-1) - 1];
1823 char_type* __op; // pad here
1824 char_type* __oe; // end of output
1825 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
1826 __ct.widen(__nar, __ne, __o);
1827 __oe = __o + (__ne - __nar);
1828 if (__np == __ne)
1829 __op = __oe;
1830 else
1831 __op = __o + (__np - __nar);
1832 // [__o, __oe) contains wide number
1833 // Stage 3 & 4
1834 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1835}
1836
Howard Hinnantfc88dbd2013-08-23 17:37:05 +00001837_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS num_put<char>)
1838_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS num_put<wchar_t>)
Howard Hinnant3e519522010-05-11 19:42:16 +00001839
1840template <class _CharT, class _InputIterator>
1841_LIBCPP_HIDDEN
1842int
1843__get_up_to_n_digits(_InputIterator& __b, _InputIterator __e,
1844 ios_base::iostate& __err, const ctype<_CharT>& __ct, int __n)
1845{
1846 // Precondition: __n >= 1
1847 if (__b == __e)
1848 {
1849 __err |= ios_base::eofbit | ios_base::failbit;
1850 return 0;
1851 }
1852 // get first digit
1853 _CharT __c = *__b;
1854 if (!__ct.is(ctype_base::digit, __c))
1855 {
1856 __err |= ios_base::failbit;
1857 return 0;
1858 }
1859 int __r = __ct.narrow(__c, 0) - '0';
1860 for (++__b, --__n; __b != __e && __n > 0; ++__b, --__n)
1861 {
1862 // get next digit
1863 __c = *__b;
1864 if (!__ct.is(ctype_base::digit, __c))
1865 return __r;
1866 __r = __r * 10 + __ct.narrow(__c, 0) - '0';
1867 }
1868 if (__b == __e)
1869 __err |= ios_base::eofbit;
1870 return __r;
1871}
1872
Howard Hinnant6e412562013-03-06 23:30:19 +00001873class _LIBCPP_TYPE_VIS time_base
Howard Hinnant3e519522010-05-11 19:42:16 +00001874{
1875public:
1876 enum dateorder {no_order, dmy, mdy, ymd, ydm};
1877};
1878
1879template <class _CharT>
Saleem Abdulrasoolf4a391c02014-07-16 01:00:26 +00001880class _LIBCPP_TYPE_VIS_ONLY __time_get_c_storage
Howard Hinnant3e519522010-05-11 19:42:16 +00001881{
1882protected:
1883 typedef basic_string<_CharT> string_type;
1884
1885 virtual const string_type* __weeks() const;
1886 virtual const string_type* __months() const;
1887 virtual const string_type* __am_pm() const;
1888 virtual const string_type& __c() const;
1889 virtual const string_type& __r() const;
1890 virtual const string_type& __x() const;
1891 virtual const string_type& __X() const;
1892};
1893
1894template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnantf0544c22013-08-12 18:38:34 +00001895class _LIBCPP_TYPE_VIS_ONLY time_get
Howard Hinnant3e519522010-05-11 19:42:16 +00001896 : public locale::facet,
1897 public time_base,
1898 private __time_get_c_storage<_CharT>
1899{
1900public:
1901 typedef _CharT char_type;
1902 typedef _InputIterator iter_type;
1903 typedef time_base::dateorder dateorder;
1904 typedef basic_string<char_type> string_type;
1905
1906 _LIBCPP_ALWAYS_INLINE
1907 explicit time_get(size_t __refs = 0)
1908 : locale::facet(__refs) {}
1909
1910 _LIBCPP_ALWAYS_INLINE
1911 dateorder date_order() const
1912 {
1913 return this->do_date_order();
1914 }
1915
1916 _LIBCPP_ALWAYS_INLINE
1917 iter_type get_time(iter_type __b, iter_type __e, ios_base& __iob,
1918 ios_base::iostate& __err, tm* __tm) const
1919 {
1920 return do_get_time(__b, __e, __iob, __err, __tm);
1921 }
1922
1923 _LIBCPP_ALWAYS_INLINE
1924 iter_type get_date(iter_type __b, iter_type __e, ios_base& __iob,
1925 ios_base::iostate& __err, tm* __tm) const
1926 {
1927 return do_get_date(__b, __e, __iob, __err, __tm);
1928 }
1929
1930 _LIBCPP_ALWAYS_INLINE
1931 iter_type get_weekday(iter_type __b, iter_type __e, ios_base& __iob,
1932 ios_base::iostate& __err, tm* __tm) const
1933 {
1934 return do_get_weekday(__b, __e, __iob, __err, __tm);
1935 }
1936
1937 _LIBCPP_ALWAYS_INLINE
1938 iter_type get_monthname(iter_type __b, iter_type __e, ios_base& __iob,
1939 ios_base::iostate& __err, tm* __tm) const
1940 {
1941 return do_get_monthname(__b, __e, __iob, __err, __tm);
1942 }
1943
1944 _LIBCPP_ALWAYS_INLINE
1945 iter_type get_year(iter_type __b, iter_type __e, ios_base& __iob,
1946 ios_base::iostate& __err, tm* __tm) const
1947 {
1948 return do_get_year(__b, __e, __iob, __err, __tm);
1949 }
1950
1951 _LIBCPP_ALWAYS_INLINE
1952 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
1953 ios_base::iostate& __err, tm *__tm,
1954 char __fmt, char __mod = 0) const
1955 {
1956 return do_get(__b, __e, __iob, __err, __tm, __fmt, __mod);
1957 }
1958
1959 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
1960 ios_base::iostate& __err, tm* __tm,
1961 const char_type* __fmtb, const char_type* __fmte) const;
1962
1963 static locale::id id;
1964
1965protected:
Howard Hinnant848a5372010-09-22 16:48:34 +00001966 _LIBCPP_ALWAYS_INLINE
Howard Hinnant3e519522010-05-11 19:42:16 +00001967 ~time_get() {}
1968
1969 virtual dateorder do_date_order() const;
1970 virtual iter_type do_get_time(iter_type __b, iter_type __e, ios_base& __iob,
1971 ios_base::iostate& __err, tm* __tm) const;
1972 virtual iter_type do_get_date(iter_type __b, iter_type __e, ios_base& __iob,
1973 ios_base::iostate& __err, tm* __tm) const;
1974 virtual iter_type do_get_weekday(iter_type __b, iter_type __e, ios_base& __iob,
1975 ios_base::iostate& __err, tm* __tm) const;
1976 virtual iter_type do_get_monthname(iter_type __b, iter_type __e, ios_base& __iob,
1977 ios_base::iostate& __err, tm* __tm) const;
1978 virtual iter_type do_get_year(iter_type __b, iter_type __e, ios_base& __iob,
1979 ios_base::iostate& __err, tm* __tm) const;
1980 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
1981 ios_base::iostate& __err, tm* __tm,
1982 char __fmt, char __mod) const;
1983private:
1984 void __get_white_space(iter_type& __b, iter_type __e,
1985 ios_base::iostate& __err, const ctype<char_type>& __ct) const;
1986 void __get_percent(iter_type& __b, iter_type __e, ios_base::iostate& __err,
1987 const ctype<char_type>& __ct) const;
1988
1989 void __get_weekdayname(int& __m,
1990 iter_type& __b, iter_type __e,
1991 ios_base::iostate& __err,
1992 const ctype<char_type>& __ct) const;
1993 void __get_monthname(int& __m,
1994 iter_type& __b, iter_type __e,
1995 ios_base::iostate& __err,
1996 const ctype<char_type>& __ct) const;
1997 void __get_day(int& __d,
1998 iter_type& __b, iter_type __e,
1999 ios_base::iostate& __err,
2000 const ctype<char_type>& __ct) const;
2001 void __get_month(int& __m,
2002 iter_type& __b, iter_type __e,
2003 ios_base::iostate& __err,
2004 const ctype<char_type>& __ct) const;
2005 void __get_year(int& __y,
2006 iter_type& __b, iter_type __e,
2007 ios_base::iostate& __err,
2008 const ctype<char_type>& __ct) const;
2009 void __get_year4(int& __y,
2010 iter_type& __b, iter_type __e,
2011 ios_base::iostate& __err,
2012 const ctype<char_type>& __ct) const;
2013 void __get_hour(int& __d,
2014 iter_type& __b, iter_type __e,
2015 ios_base::iostate& __err,
2016 const ctype<char_type>& __ct) const;
2017 void __get_12_hour(int& __h,
2018 iter_type& __b, iter_type __e,
2019 ios_base::iostate& __err,
2020 const ctype<char_type>& __ct) const;
2021 void __get_am_pm(int& __h,
2022 iter_type& __b, iter_type __e,
2023 ios_base::iostate& __err,
2024 const ctype<char_type>& __ct) const;
2025 void __get_minute(int& __m,
2026 iter_type& __b, iter_type __e,
2027 ios_base::iostate& __err,
2028 const ctype<char_type>& __ct) const;
2029 void __get_second(int& __s,
2030 iter_type& __b, iter_type __e,
2031 ios_base::iostate& __err,
2032 const ctype<char_type>& __ct) const;
2033 void __get_weekday(int& __w,
2034 iter_type& __b, iter_type __e,
2035 ios_base::iostate& __err,
2036 const ctype<char_type>& __ct) const;
2037 void __get_day_year_num(int& __w,
2038 iter_type& __b, iter_type __e,
2039 ios_base::iostate& __err,
2040 const ctype<char_type>& __ct) const;
2041};
2042
2043template <class _CharT, class _InputIterator>
2044locale::id
2045time_get<_CharT, _InputIterator>::id;
2046
Alp Tokerf03763a2014-05-15 11:27:39 +00002047// time_get primitives
Howard Hinnant3e519522010-05-11 19:42:16 +00002048
2049template <class _CharT, class _InputIterator>
2050void
2051time_get<_CharT, _InputIterator>::__get_weekdayname(int& __w,
2052 iter_type& __b, iter_type __e,
2053 ios_base::iostate& __err,
2054 const ctype<char_type>& __ct) const
2055{
2056 // Note: ignoring case comes from the POSIX strptime spec
2057 const string_type* __wk = this->__weeks();
Howard Hinnantc2063662011-12-01 20:21:04 +00002058 ptrdiff_t __i = __scan_keyword(__b, __e, __wk, __wk+14, __ct, __err, false) - __wk;
Howard Hinnant3e519522010-05-11 19:42:16 +00002059 if (__i < 14)
2060 __w = __i % 7;
2061}
2062
2063template <class _CharT, class _InputIterator>
2064void
2065time_get<_CharT, _InputIterator>::__get_monthname(int& __m,
2066 iter_type& __b, iter_type __e,
2067 ios_base::iostate& __err,
2068 const ctype<char_type>& __ct) const
2069{
2070 // Note: ignoring case comes from the POSIX strptime spec
2071 const string_type* __month = this->__months();
Howard Hinnantc2063662011-12-01 20:21:04 +00002072 ptrdiff_t __i = __scan_keyword(__b, __e, __month, __month+24, __ct, __err, false) - __month;
Howard Hinnant3e519522010-05-11 19:42:16 +00002073 if (__i < 24)
2074 __m = __i % 12;
2075}
2076
2077template <class _CharT, class _InputIterator>
2078void
2079time_get<_CharT, _InputIterator>::__get_day(int& __d,
2080 iter_type& __b, iter_type __e,
2081 ios_base::iostate& __err,
2082 const ctype<char_type>& __ct) const
2083{
2084 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2085 if (!(__err & ios_base::failbit) && 1 <= __t && __t <= 31)
2086 __d = __t;
2087 else
2088 __err |= ios_base::failbit;
2089}
2090
2091template <class _CharT, class _InputIterator>
2092void
2093time_get<_CharT, _InputIterator>::__get_month(int& __m,
2094 iter_type& __b, iter_type __e,
2095 ios_base::iostate& __err,
2096 const ctype<char_type>& __ct) const
2097{
2098 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2) - 1;
2099 if (!(__err & ios_base::failbit) && __t <= 11)
2100 __m = __t;
2101 else
2102 __err |= ios_base::failbit;
2103}
2104
2105template <class _CharT, class _InputIterator>
2106void
2107time_get<_CharT, _InputIterator>::__get_year(int& __y,
2108 iter_type& __b, iter_type __e,
2109 ios_base::iostate& __err,
2110 const ctype<char_type>& __ct) const
2111{
2112 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 4);
2113 if (!(__err & ios_base::failbit))
2114 {
2115 if (__t < 69)
2116 __t += 2000;
2117 else if (69 <= __t && __t <= 99)
2118 __t += 1900;
2119 __y = __t - 1900;
2120 }
2121}
2122
2123template <class _CharT, class _InputIterator>
2124void
2125time_get<_CharT, _InputIterator>::__get_year4(int& __y,
2126 iter_type& __b, iter_type __e,
2127 ios_base::iostate& __err,
2128 const ctype<char_type>& __ct) const
2129{
2130 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 4);
2131 if (!(__err & ios_base::failbit))
2132 __y = __t - 1900;
2133}
2134
2135template <class _CharT, class _InputIterator>
2136void
2137time_get<_CharT, _InputIterator>::__get_hour(int& __h,
2138 iter_type& __b, iter_type __e,
2139 ios_base::iostate& __err,
2140 const ctype<char_type>& __ct) const
2141{
2142 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2143 if (!(__err & ios_base::failbit) && __t <= 23)
2144 __h = __t;
2145 else
2146 __err |= ios_base::failbit;
2147}
2148
2149template <class _CharT, class _InputIterator>
2150void
2151time_get<_CharT, _InputIterator>::__get_12_hour(int& __h,
2152 iter_type& __b, iter_type __e,
2153 ios_base::iostate& __err,
2154 const ctype<char_type>& __ct) const
2155{
2156 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2157 if (!(__err & ios_base::failbit) && 1 <= __t && __t <= 12)
2158 __h = __t;
2159 else
2160 __err |= ios_base::failbit;
2161}
2162
2163template <class _CharT, class _InputIterator>
2164void
2165time_get<_CharT, _InputIterator>::__get_minute(int& __m,
2166 iter_type& __b, iter_type __e,
2167 ios_base::iostate& __err,
2168 const ctype<char_type>& __ct) const
2169{
2170 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2171 if (!(__err & ios_base::failbit) && __t <= 59)
2172 __m = __t;
2173 else
2174 __err |= ios_base::failbit;
2175}
2176
2177template <class _CharT, class _InputIterator>
2178void
2179time_get<_CharT, _InputIterator>::__get_second(int& __s,
2180 iter_type& __b, iter_type __e,
2181 ios_base::iostate& __err,
2182 const ctype<char_type>& __ct) const
2183{
2184 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2185 if (!(__err & ios_base::failbit) && __t <= 60)
2186 __s = __t;
2187 else
2188 __err |= ios_base::failbit;
2189}
2190
2191template <class _CharT, class _InputIterator>
2192void
2193time_get<_CharT, _InputIterator>::__get_weekday(int& __w,
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, 1);
2199 if (!(__err & ios_base::failbit) && __t <= 6)
2200 __w = __t;
2201 else
2202 __err |= ios_base::failbit;
2203}
2204
2205template <class _CharT, class _InputIterator>
2206void
2207time_get<_CharT, _InputIterator>::__get_day_year_num(int& __d,
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, 3);
2213 if (!(__err & ios_base::failbit) && __t <= 365)
2214 __d = __t;
2215 else
2216 __err |= ios_base::failbit;
2217}
2218
2219template <class _CharT, class _InputIterator>
2220void
2221time_get<_CharT, _InputIterator>::__get_white_space(iter_type& __b, iter_type __e,
2222 ios_base::iostate& __err,
2223 const ctype<char_type>& __ct) const
2224{
2225 for (; __b != __e && __ct.is(ctype_base::space, *__b); ++__b)
2226 ;
2227 if (__b == __e)
2228 __err |= ios_base::eofbit;
2229}
2230
2231template <class _CharT, class _InputIterator>
2232void
2233time_get<_CharT, _InputIterator>::__get_am_pm(int& __h,
2234 iter_type& __b, iter_type __e,
2235 ios_base::iostate& __err,
2236 const ctype<char_type>& __ct) const
2237{
2238 const string_type* __ap = this->__am_pm();
2239 if (__ap[0].size() + __ap[1].size() == 0)
2240 {
2241 __err |= ios_base::failbit;
2242 return;
2243 }
Howard Hinnantc2063662011-12-01 20:21:04 +00002244 ptrdiff_t __i = __scan_keyword(__b, __e, __ap, __ap+2, __ct, __err, false) - __ap;
Howard Hinnant3e519522010-05-11 19:42:16 +00002245 if (__i == 0 && __h == 12)
2246 __h = 0;
2247 else if (__i == 1 && __h < 12)
2248 __h += 12;
2249}
2250
2251template <class _CharT, class _InputIterator>
2252void
2253time_get<_CharT, _InputIterator>::__get_percent(iter_type& __b, iter_type __e,
2254 ios_base::iostate& __err,
2255 const ctype<char_type>& __ct) const
2256{
2257 if (__b == __e)
2258 {
2259 __err |= ios_base::eofbit | ios_base::failbit;
2260 return;
2261 }
2262 if (__ct.narrow(*__b, 0) != '%')
2263 __err |= ios_base::failbit;
2264 else if(++__b == __e)
2265 __err |= ios_base::eofbit;
2266}
2267
Alp Tokerf03763a2014-05-15 11:27:39 +00002268// time_get end primitives
Howard Hinnant3e519522010-05-11 19:42:16 +00002269
2270template <class _CharT, class _InputIterator>
2271_InputIterator
2272time_get<_CharT, _InputIterator>::get(iter_type __b, iter_type __e,
2273 ios_base& __iob,
2274 ios_base::iostate& __err, tm* __tm,
2275 const char_type* __fmtb, const char_type* __fmte) const
2276{
2277 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2278 __err = ios_base::goodbit;
2279 while (__fmtb != __fmte && __err == ios_base::goodbit)
2280 {
2281 if (__b == __e)
2282 {
2283 __err = ios_base::failbit;
2284 break;
2285 }
2286 if (__ct.narrow(*__fmtb, 0) == '%')
2287 {
2288 if (++__fmtb == __fmte)
2289 {
2290 __err = ios_base::failbit;
2291 break;
2292 }
2293 char __cmd = __ct.narrow(*__fmtb, 0);
2294 char __opt = '\0';
2295 if (__cmd == 'E' || __cmd == '0')
2296 {
2297 if (++__fmtb == __fmte)
2298 {
2299 __err = ios_base::failbit;
2300 break;
2301 }
2302 __opt = __cmd;
2303 __cmd = __ct.narrow(*__fmtb, 0);
2304 }
2305 __b = do_get(__b, __e, __iob, __err, __tm, __cmd, __opt);
2306 ++__fmtb;
2307 }
2308 else if (__ct.is(ctype_base::space, *__fmtb))
2309 {
2310 for (++__fmtb; __fmtb != __fmte && __ct.is(ctype_base::space, *__fmtb); ++__fmtb)
2311 ;
2312 for ( ; __b != __e && __ct.is(ctype_base::space, *__b); ++__b)
2313 ;
2314 }
2315 else if (__ct.toupper(*__b) == __ct.toupper(*__fmtb))
2316 {
2317 ++__b;
2318 ++__fmtb;
2319 }
2320 else
2321 __err = ios_base::failbit;
2322 }
2323 if (__b == __e)
2324 __err |= ios_base::eofbit;
2325 return __b;
2326}
2327
2328template <class _CharT, class _InputIterator>
2329typename time_get<_CharT, _InputIterator>::dateorder
2330time_get<_CharT, _InputIterator>::do_date_order() const
2331{
2332 return mdy;
2333}
2334
2335template <class _CharT, class _InputIterator>
2336_InputIterator
2337time_get<_CharT, _InputIterator>::do_get_time(iter_type __b, iter_type __e,
2338 ios_base& __iob,
2339 ios_base::iostate& __err,
2340 tm* __tm) const
2341{
2342 const char_type __fmt[] = {'%', 'H', ':', '%', 'M', ':', '%', 'S'};
2343 return get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2344}
2345
2346template <class _CharT, class _InputIterator>
2347_InputIterator
2348time_get<_CharT, _InputIterator>::do_get_date(iter_type __b, iter_type __e,
2349 ios_base& __iob,
2350 ios_base::iostate& __err,
2351 tm* __tm) const
2352{
Howard Hinnant3e519522010-05-11 19:42:16 +00002353 const string_type& __fmt = this->__x();
2354 return get(__b, __e, __iob, __err, __tm, __fmt.data(), __fmt.data() + __fmt.size());
2355}
2356
2357template <class _CharT, class _InputIterator>
2358_InputIterator
2359time_get<_CharT, _InputIterator>::do_get_weekday(iter_type __b, iter_type __e,
2360 ios_base& __iob,
2361 ios_base::iostate& __err,
2362 tm* __tm) const
2363{
2364 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2365 __get_weekdayname(__tm->tm_wday, __b, __e, __err, __ct);
2366 return __b;
2367}
2368
2369template <class _CharT, class _InputIterator>
2370_InputIterator
2371time_get<_CharT, _InputIterator>::do_get_monthname(iter_type __b, iter_type __e,
2372 ios_base& __iob,
2373 ios_base::iostate& __err,
2374 tm* __tm) const
2375{
2376 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2377 __get_monthname(__tm->tm_mon, __b, __e, __err, __ct);
2378 return __b;
2379}
2380
2381template <class _CharT, class _InputIterator>
2382_InputIterator
2383time_get<_CharT, _InputIterator>::do_get_year(iter_type __b, iter_type __e,
2384 ios_base& __iob,
2385 ios_base::iostate& __err,
2386 tm* __tm) const
2387{
2388 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2389 __get_year(__tm->tm_year, __b, __e, __err, __ct);
2390 return __b;
2391}
2392
2393template <class _CharT, class _InputIterator>
2394_InputIterator
2395time_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
2396 ios_base& __iob,
2397 ios_base::iostate& __err, tm* __tm,
2398 char __fmt, char) const
2399{
2400 __err = ios_base::goodbit;
2401 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2402 switch (__fmt)
2403 {
2404 case 'a':
2405 case 'A':
2406 __get_weekdayname(__tm->tm_wday, __b, __e, __err, __ct);
2407 break;
2408 case 'b':
2409 case 'B':
2410 case 'h':
2411 __get_monthname(__tm->tm_mon, __b, __e, __err, __ct);
2412 break;
2413 case 'c':
2414 {
Howard Hinnantc2063662011-12-01 20:21:04 +00002415 const string_type& __fm = this->__c();
2416 __b = get(__b, __e, __iob, __err, __tm, __fm.data(), __fm.data() + __fm.size());
Howard Hinnant3e519522010-05-11 19:42:16 +00002417 }
2418 break;
2419 case 'd':
2420 case 'e':
2421 __get_day(__tm->tm_mday, __b, __e, __err, __ct);
2422 break;
2423 case 'D':
2424 {
Howard Hinnantc2063662011-12-01 20:21:04 +00002425 const char_type __fm[] = {'%', 'm', '/', '%', 'd', '/', '%', 'y'};
2426 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm)/sizeof(__fm[0]));
Howard Hinnant3e519522010-05-11 19:42:16 +00002427 }
2428 break;
Howard Hinnant1444d852011-04-10 17:54:14 +00002429 case 'F':
2430 {
Howard Hinnantc2063662011-12-01 20:21:04 +00002431 const char_type __fm[] = {'%', 'Y', '-', '%', 'm', '-', '%', 'd'};
2432 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm)/sizeof(__fm[0]));
Howard Hinnant1444d852011-04-10 17:54:14 +00002433 }
2434 break;
Howard Hinnant3e519522010-05-11 19:42:16 +00002435 case 'H':
2436 __get_hour(__tm->tm_hour, __b, __e, __err, __ct);
2437 break;
2438 case 'I':
2439 __get_12_hour(__tm->tm_hour, __b, __e, __err, __ct);
2440 break;
2441 case 'j':
2442 __get_day_year_num(__tm->tm_yday, __b, __e, __err, __ct);
2443 break;
2444 case 'm':
2445 __get_month(__tm->tm_mon, __b, __e, __err, __ct);
2446 break;
2447 case 'M':
2448 __get_minute(__tm->tm_min, __b, __e, __err, __ct);
2449 break;
2450 case 'n':
2451 case 't':
2452 __get_white_space(__b, __e, __err, __ct);
2453 break;
2454 case 'p':
2455 __get_am_pm(__tm->tm_hour, __b, __e, __err, __ct);
2456 break;
2457 case 'r':
2458 {
Howard Hinnantc2063662011-12-01 20:21:04 +00002459 const char_type __fm[] = {'%', 'I', ':', '%', 'M', ':', '%', 'S', ' ', '%', 'p'};
2460 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm)/sizeof(__fm[0]));
Howard Hinnant3e519522010-05-11 19:42:16 +00002461 }
2462 break;
2463 case 'R':
2464 {
Howard Hinnantc2063662011-12-01 20:21:04 +00002465 const char_type __fm[] = {'%', 'H', ':', '%', 'M'};
2466 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm)/sizeof(__fm[0]));
Howard Hinnant3e519522010-05-11 19:42:16 +00002467 }
2468 break;
2469 case 'S':
2470 __get_second(__tm->tm_sec, __b, __e, __err, __ct);
2471 break;
2472 case 'T':
2473 {
Howard Hinnantc2063662011-12-01 20:21:04 +00002474 const char_type __fm[] = {'%', 'H', ':', '%', 'M', ':', '%', 'S'};
2475 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm)/sizeof(__fm[0]));
Howard Hinnant3e519522010-05-11 19:42:16 +00002476 }
2477 break;
2478 case 'w':
2479 __get_weekday(__tm->tm_wday, __b, __e, __err, __ct);
2480 break;
2481 case 'x':
2482 return do_get_date(__b, __e, __iob, __err, __tm);
2483 case 'X':
2484 {
Howard Hinnantc2063662011-12-01 20:21:04 +00002485 const string_type& __fm = this->__X();
2486 __b = get(__b, __e, __iob, __err, __tm, __fm.data(), __fm.data() + __fm.size());
Howard Hinnant3e519522010-05-11 19:42:16 +00002487 }
2488 break;
2489 case 'y':
2490 __get_year(__tm->tm_year, __b, __e, __err, __ct);
2491 break;
2492 case 'Y':
2493 __get_year4(__tm->tm_year, __b, __e, __err, __ct);
2494 break;
2495 case '%':
2496 __get_percent(__b, __e, __err, __ct);
2497 break;
2498 default:
2499 __err |= ios_base::failbit;
2500 }
2501 return __b;
2502}
2503
Howard Hinnantfc88dbd2013-08-23 17:37:05 +00002504_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS time_get<char>)
2505_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS time_get<wchar_t>)
Howard Hinnant3e519522010-05-11 19:42:16 +00002506
Howard Hinnantf0544c22013-08-12 18:38:34 +00002507class _LIBCPP_TYPE_VIS __time_get
Howard Hinnant3e519522010-05-11 19:42:16 +00002508{
2509protected:
2510 locale_t __loc_;
2511
2512 __time_get(const char* __nm);
2513 __time_get(const string& __nm);
2514 ~__time_get();
2515};
2516
2517template <class _CharT>
Saleem Abdulrasoolf4a391c02014-07-16 01:00:26 +00002518class _LIBCPP_TYPE_VIS_ONLY __time_get_storage
Howard Hinnant3e519522010-05-11 19:42:16 +00002519 : public __time_get
2520{
2521protected:
2522 typedef basic_string<_CharT> string_type;
2523
2524 string_type __weeks_[14];
2525 string_type __months_[24];
2526 string_type __am_pm_[2];
2527 string_type __c_;
2528 string_type __r_;
2529 string_type __x_;
2530 string_type __X_;
2531
2532 explicit __time_get_storage(const char* __nm);
2533 explicit __time_get_storage(const string& __nm);
2534
2535 _LIBCPP_ALWAYS_INLINE ~__time_get_storage() {}
2536
2537 time_base::dateorder __do_date_order() const;
2538
2539private:
2540 void init(const ctype<_CharT>&);
2541 string_type __analyze(char __fmt, const ctype<_CharT>&);
2542};
2543
2544template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnantf0544c22013-08-12 18:38:34 +00002545class _LIBCPP_TYPE_VIS_ONLY time_get_byname
Howard Hinnant3e519522010-05-11 19:42:16 +00002546 : public time_get<_CharT, _InputIterator>,
2547 private __time_get_storage<_CharT>
2548{
2549public:
2550 typedef time_base::dateorder dateorder;
2551 typedef _InputIterator iter_type;
2552 typedef _CharT char_type;
2553 typedef basic_string<char_type> string_type;
2554
Howard Hinnant848a5372010-09-22 16:48:34 +00002555 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant3e519522010-05-11 19:42:16 +00002556 explicit time_get_byname(const char* __nm, size_t __refs = 0)
2557 : time_get<_CharT, _InputIterator>(__refs),
2558 __time_get_storage<_CharT>(__nm) {}
Howard Hinnant848a5372010-09-22 16:48:34 +00002559 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant3e519522010-05-11 19:42:16 +00002560 explicit time_get_byname(const string& __nm, size_t __refs = 0)
2561 : time_get<_CharT, _InputIterator>(__refs),
2562 __time_get_storage<_CharT>(__nm) {}
2563
2564protected:
Howard Hinnant848a5372010-09-22 16:48:34 +00002565 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant3e519522010-05-11 19:42:16 +00002566 ~time_get_byname() {}
2567
Howard Hinnant848a5372010-09-22 16:48:34 +00002568 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant3e519522010-05-11 19:42:16 +00002569 virtual dateorder do_date_order() const {return this->__do_date_order();}
2570private:
Howard Hinnant848a5372010-09-22 16:48:34 +00002571 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant3e519522010-05-11 19:42:16 +00002572 virtual const string_type* __weeks() const {return this->__weeks_;}
Howard Hinnant848a5372010-09-22 16:48:34 +00002573 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant3e519522010-05-11 19:42:16 +00002574 virtual const string_type* __months() const {return this->__months_;}
Howard Hinnant848a5372010-09-22 16:48:34 +00002575 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant3e519522010-05-11 19:42:16 +00002576 virtual const string_type* __am_pm() const {return this->__am_pm_;}
Howard Hinnant848a5372010-09-22 16:48:34 +00002577 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant3e519522010-05-11 19:42:16 +00002578 virtual const string_type& __c() const {return this->__c_;}
Howard Hinnant848a5372010-09-22 16:48:34 +00002579 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant3e519522010-05-11 19:42:16 +00002580 virtual const string_type& __r() const {return this->__r_;}
Howard Hinnant848a5372010-09-22 16:48:34 +00002581 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant3e519522010-05-11 19:42:16 +00002582 virtual const string_type& __x() const {return this->__x_;}
Howard Hinnant848a5372010-09-22 16:48:34 +00002583 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant3e519522010-05-11 19:42:16 +00002584 virtual const string_type& __X() const {return this->__X_;}
2585};
2586
Howard Hinnantfc88dbd2013-08-23 17:37:05 +00002587_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS time_get_byname<char>)
2588_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS time_get_byname<wchar_t>)
Howard Hinnant3e519522010-05-11 19:42:16 +00002589
Howard Hinnantf0544c22013-08-12 18:38:34 +00002590class _LIBCPP_TYPE_VIS __time_put
Howard Hinnant3e519522010-05-11 19:42:16 +00002591{
2592 locale_t __loc_;
2593protected:
Howard Hinnant0470a632011-09-28 21:05:01 +00002594 _LIBCPP_ALWAYS_INLINE __time_put() : __loc_(_LIBCPP_GET_C_LOCALE) {}
Howard Hinnant3e519522010-05-11 19:42:16 +00002595 __time_put(const char* __nm);
2596 __time_put(const string& __nm);
2597 ~__time_put();
2598 void __do_put(char* __nb, char*& __ne, const tm* __tm,
2599 char __fmt, char __mod) const;
2600 void __do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
2601 char __fmt, char __mod) const;
2602};
2603
2604template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnantf0544c22013-08-12 18:38:34 +00002605class _LIBCPP_TYPE_VIS_ONLY time_put
Howard Hinnant3e519522010-05-11 19:42:16 +00002606 : public locale::facet,
2607 private __time_put
2608{
2609public:
2610 typedef _CharT char_type;
2611 typedef _OutputIterator iter_type;
2612
2613 _LIBCPP_ALWAYS_INLINE
2614 explicit time_put(size_t __refs = 0)
2615 : locale::facet(__refs) {}
2616
2617 iter_type put(iter_type __s, ios_base& __iob, char_type __fl, const tm* __tm,
2618 const char_type* __pb, const char_type* __pe) const;
2619
2620 _LIBCPP_ALWAYS_INLINE
2621 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
2622 const tm* __tm, char __fmt, char __mod = 0) const
2623 {
2624 return do_put(__s, __iob, __fl, __tm, __fmt, __mod);
2625 }
2626
2627 static locale::id id;
2628
2629protected:
Howard Hinnant848a5372010-09-22 16:48:34 +00002630 _LIBCPP_ALWAYS_INLINE
Howard Hinnant3e519522010-05-11 19:42:16 +00002631 ~time_put() {}
2632 virtual iter_type do_put(iter_type __s, ios_base&, char_type, const tm* __tm,
2633 char __fmt, char __mod) const;
2634
Howard Hinnant848a5372010-09-22 16:48:34 +00002635 _LIBCPP_ALWAYS_INLINE
Howard Hinnant3e519522010-05-11 19:42:16 +00002636 explicit time_put(const char* __nm, size_t __refs)
2637 : locale::facet(__refs),
2638 __time_put(__nm) {}
Howard Hinnant848a5372010-09-22 16:48:34 +00002639 _LIBCPP_ALWAYS_INLINE
Howard Hinnant3e519522010-05-11 19:42:16 +00002640 explicit time_put(const string& __nm, size_t __refs)
2641 : locale::facet(__refs),
2642 __time_put(__nm) {}
2643};
2644
2645template <class _CharT, class _OutputIterator>
2646locale::id
2647time_put<_CharT, _OutputIterator>::id;
2648
2649template <class _CharT, class _OutputIterator>
2650_OutputIterator
2651time_put<_CharT, _OutputIterator>::put(iter_type __s, ios_base& __iob,
2652 char_type __fl, const tm* __tm,
2653 const char_type* __pb,
2654 const char_type* __pe) const
2655{
2656 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2657 for (; __pb != __pe; ++__pb)
2658 {
2659 if (__ct.narrow(*__pb, 0) == '%')
2660 {
2661 if (++__pb == __pe)
2662 {
2663 *__s++ = __pb[-1];
2664 break;
2665 }
2666 char __mod = 0;
2667 char __fmt = __ct.narrow(*__pb, 0);
2668 if (__fmt == 'E' || __fmt == 'O')
2669 {
2670 if (++__pb == __pe)
2671 {
2672 *__s++ = __pb[-2];
2673 *__s++ = __pb[-1];
2674 break;
2675 }
2676 __mod = __fmt;
2677 __fmt = __ct.narrow(*__pb, 0);
2678 }
2679 __s = do_put(__s, __iob, __fl, __tm, __fmt, __mod);
2680 }
2681 else
2682 *__s++ = *__pb;
2683 }
2684 return __s;
2685}
2686
2687template <class _CharT, class _OutputIterator>
2688_OutputIterator
Howard Hinnantc2063662011-12-01 20:21:04 +00002689time_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base&,
Howard Hinnant3e519522010-05-11 19:42:16 +00002690 char_type, const tm* __tm,
2691 char __fmt, char __mod) const
2692{
2693 char_type __nar[100];
2694 char_type* __nb = __nar;
2695 char_type* __ne = __nb + 100;
2696 __do_put(__nb, __ne, __tm, __fmt, __mod);
Howard Hinnantce48a112011-06-30 21:18:19 +00002697 return _VSTD::copy(__nb, __ne, __s);
Howard Hinnant3e519522010-05-11 19:42:16 +00002698}
2699
Howard Hinnantfc88dbd2013-08-23 17:37:05 +00002700_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS time_put<char>)
2701_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS time_put<wchar_t>)
Howard Hinnant3e519522010-05-11 19:42:16 +00002702
2703template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnantf0544c22013-08-12 18:38:34 +00002704class _LIBCPP_TYPE_VIS_ONLY time_put_byname
Howard Hinnant3e519522010-05-11 19:42:16 +00002705 : public time_put<_CharT, _OutputIterator>
2706{
2707public:
2708 _LIBCPP_ALWAYS_INLINE
2709 explicit time_put_byname(const char* __nm, size_t __refs = 0)
2710 : time_put<_CharT, _OutputIterator>(__nm, __refs) {}
2711
2712 _LIBCPP_ALWAYS_INLINE
2713 explicit time_put_byname(const string& __nm, size_t __refs = 0)
2714 : time_put<_CharT, _OutputIterator>(__nm, __refs) {}
2715
2716protected:
Howard Hinnant848a5372010-09-22 16:48:34 +00002717 _LIBCPP_ALWAYS_INLINE
Howard Hinnant3e519522010-05-11 19:42:16 +00002718 ~time_put_byname() {}
2719};
2720
Howard Hinnantfc88dbd2013-08-23 17:37:05 +00002721_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS time_put_byname<char>)
2722_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS time_put_byname<wchar_t>)
Howard Hinnant3e519522010-05-11 19:42:16 +00002723
2724// money_base
2725
Howard Hinnant6e412562013-03-06 23:30:19 +00002726class _LIBCPP_TYPE_VIS money_base
Howard Hinnant3e519522010-05-11 19:42:16 +00002727{
2728public:
2729 enum part {none, space, symbol, sign, value};
2730 struct pattern {char field[4];};
2731
2732 _LIBCPP_ALWAYS_INLINE money_base() {}
2733};
2734
2735// moneypunct
2736
2737template <class _CharT, bool _International = false>
Howard Hinnantf0544c22013-08-12 18:38:34 +00002738class _LIBCPP_TYPE_VIS_ONLY moneypunct
Howard Hinnant3e519522010-05-11 19:42:16 +00002739 : public locale::facet,
2740 public money_base
2741{
2742public:
2743 typedef _CharT char_type;
2744 typedef basic_string<char_type> string_type;
2745
Howard Hinnant848a5372010-09-22 16:48:34 +00002746 _LIBCPP_ALWAYS_INLINE
Howard Hinnant3e519522010-05-11 19:42:16 +00002747 explicit moneypunct(size_t __refs = 0)
2748 : locale::facet(__refs) {}
2749
2750 _LIBCPP_ALWAYS_INLINE char_type decimal_point() const {return do_decimal_point();}
2751 _LIBCPP_ALWAYS_INLINE char_type thousands_sep() const {return do_thousands_sep();}
2752 _LIBCPP_ALWAYS_INLINE string grouping() const {return do_grouping();}
2753 _LIBCPP_ALWAYS_INLINE string_type curr_symbol() const {return do_curr_symbol();}
2754 _LIBCPP_ALWAYS_INLINE string_type positive_sign() const {return do_positive_sign();}
2755 _LIBCPP_ALWAYS_INLINE string_type negative_sign() const {return do_negative_sign();}
2756 _LIBCPP_ALWAYS_INLINE int frac_digits() const {return do_frac_digits();}
2757 _LIBCPP_ALWAYS_INLINE pattern pos_format() const {return do_pos_format();}
2758 _LIBCPP_ALWAYS_INLINE pattern neg_format() const {return do_neg_format();}
2759
2760 static locale::id id;
2761 static const bool intl = _International;
2762
2763protected:
Howard Hinnant848a5372010-09-22 16:48:34 +00002764 _LIBCPP_ALWAYS_INLINE
Howard Hinnant3e519522010-05-11 19:42:16 +00002765 ~moneypunct() {}
2766
2767 virtual char_type do_decimal_point() const {return numeric_limits<char_type>::max();}
2768 virtual char_type do_thousands_sep() const {return numeric_limits<char_type>::max();}
2769 virtual string do_grouping() const {return string();}
2770 virtual string_type do_curr_symbol() const {return string_type();}
2771 virtual string_type do_positive_sign() const {return string_type();}
2772 virtual string_type do_negative_sign() const {return string_type(1, '-');}
2773 virtual int do_frac_digits() const {return 0;}
2774 virtual pattern do_pos_format() const
Howard Hinnant3e2740a2012-11-06 21:48:33 +00002775 {pattern __p = {{symbol, sign, none, value}}; return __p;}
Howard Hinnant3e519522010-05-11 19:42:16 +00002776 virtual pattern do_neg_format() const
Howard Hinnant3e2740a2012-11-06 21:48:33 +00002777 {pattern __p = {{symbol, sign, none, value}}; return __p;}
Howard Hinnant3e519522010-05-11 19:42:16 +00002778};
2779
2780template <class _CharT, bool _International>
2781locale::id
2782moneypunct<_CharT, _International>::id;
2783
Howard Hinnant16694b52012-12-12 21:14:28 +00002784template <class _CharT, bool _International>
2785const bool
2786moneypunct<_CharT, _International>::intl;
2787
Howard Hinnantfc88dbd2013-08-23 17:37:05 +00002788_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS moneypunct<char, false>)
2789_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS moneypunct<char, true>)
2790_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS moneypunct<wchar_t, false>)
2791_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS moneypunct<wchar_t, true>)
Howard Hinnant3e519522010-05-11 19:42:16 +00002792
2793// moneypunct_byname
2794
2795template <class _CharT, bool _International = false>
Howard Hinnantf0544c22013-08-12 18:38:34 +00002796class _LIBCPP_TYPE_VIS_ONLY moneypunct_byname
Howard Hinnant848a5372010-09-22 16:48:34 +00002797 : public moneypunct<_CharT, _International>
Howard Hinnant3e519522010-05-11 19:42:16 +00002798{
2799public:
2800 typedef money_base::pattern pattern;
2801 typedef _CharT char_type;
2802 typedef basic_string<char_type> string_type;
2803
2804 _LIBCPP_ALWAYS_INLINE
2805 explicit moneypunct_byname(const char* __nm, size_t __refs = 0)
2806 : moneypunct<_CharT, _International>(__refs) {init(__nm);}
2807
2808 _LIBCPP_ALWAYS_INLINE
2809 explicit moneypunct_byname(const string& __nm, size_t __refs = 0)
2810 : moneypunct<_CharT, _International>(__refs) {init(__nm.c_str());}
2811
2812protected:
Howard Hinnant848a5372010-09-22 16:48:34 +00002813 _LIBCPP_ALWAYS_INLINE
Howard Hinnant3e519522010-05-11 19:42:16 +00002814 ~moneypunct_byname() {}
2815
2816 virtual char_type do_decimal_point() const {return __decimal_point_;}
2817 virtual char_type do_thousands_sep() const {return __thousands_sep_;}
2818 virtual string do_grouping() const {return __grouping_;}
2819 virtual string_type do_curr_symbol() const {return __curr_symbol_;}
2820 virtual string_type do_positive_sign() const {return __positive_sign_;}
2821 virtual string_type do_negative_sign() const {return __negative_sign_;}
2822 virtual int do_frac_digits() const {return __frac_digits_;}
2823 virtual pattern do_pos_format() const {return __pos_format_;}
2824 virtual pattern do_neg_format() const {return __neg_format_;}
2825
2826private:
2827 char_type __decimal_point_;
2828 char_type __thousands_sep_;
2829 string __grouping_;
2830 string_type __curr_symbol_;
2831 string_type __positive_sign_;
2832 string_type __negative_sign_;
2833 int __frac_digits_;
2834 pattern __pos_format_;
2835 pattern __neg_format_;
2836
2837 void init(const char*);
2838};
2839
2840template<> void moneypunct_byname<char, false>::init(const char*);
2841template<> void moneypunct_byname<char, true>::init(const char*);
2842template<> void moneypunct_byname<wchar_t, false>::init(const char*);
2843template<> void moneypunct_byname<wchar_t, true>::init(const char*);
2844
Howard Hinnantfc88dbd2013-08-23 17:37:05 +00002845_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS moneypunct_byname<char, false>)
2846_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS moneypunct_byname<char, true>)
2847_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS moneypunct_byname<wchar_t, false>)
2848_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS moneypunct_byname<wchar_t, true>)
Howard Hinnant3e519522010-05-11 19:42:16 +00002849
2850// money_get
2851
2852template <class _CharT>
2853class __money_get
2854{
2855protected:
2856 typedef _CharT char_type;
2857 typedef basic_string<char_type> string_type;
2858
2859 _LIBCPP_ALWAYS_INLINE __money_get() {}
2860
2861 static void __gather_info(bool __intl, const locale& __loc,
2862 money_base::pattern& __pat, char_type& __dp,
2863 char_type& __ts, string& __grp,
2864 string_type& __sym, string_type& __psn,
2865 string_type& __nsn, int& __fd);
2866};
2867
2868template <class _CharT>
2869void
2870__money_get<_CharT>::__gather_info(bool __intl, const locale& __loc,
2871 money_base::pattern& __pat, char_type& __dp,
2872 char_type& __ts, string& __grp,
2873 string_type& __sym, string_type& __psn,
2874 string_type& __nsn, int& __fd)
2875{
2876 if (__intl)
2877 {
2878 const moneypunct<char_type, true>& __mp =
2879 use_facet<moneypunct<char_type, true> >(__loc);
2880 __pat = __mp.neg_format();
2881 __nsn = __mp.negative_sign();
2882 __psn = __mp.positive_sign();
2883 __dp = __mp.decimal_point();
2884 __ts = __mp.thousands_sep();
2885 __grp = __mp.grouping();
2886 __sym = __mp.curr_symbol();
2887 __fd = __mp.frac_digits();
2888 }
2889 else
2890 {
2891 const moneypunct<char_type, false>& __mp =
2892 use_facet<moneypunct<char_type, false> >(__loc);
2893 __pat = __mp.neg_format();
2894 __nsn = __mp.negative_sign();
2895 __psn = __mp.positive_sign();
2896 __dp = __mp.decimal_point();
2897 __ts = __mp.thousands_sep();
2898 __grp = __mp.grouping();
2899 __sym = __mp.curr_symbol();
2900 __fd = __mp.frac_digits();
2901 }
2902}
2903
Howard Hinnantfc88dbd2013-08-23 17:37:05 +00002904_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS __money_get<char>)
2905_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS __money_get<wchar_t>)
Howard Hinnant3e519522010-05-11 19:42:16 +00002906
2907template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnantf0544c22013-08-12 18:38:34 +00002908class _LIBCPP_TYPE_VIS_ONLY money_get
Howard Hinnant3e519522010-05-11 19:42:16 +00002909 : public locale::facet,
2910 private __money_get<_CharT>
2911{
2912public:
2913 typedef _CharT char_type;
2914 typedef _InputIterator iter_type;
2915 typedef basic_string<char_type> string_type;
2916
2917 _LIBCPP_ALWAYS_INLINE
2918 explicit money_get(size_t __refs = 0)
2919 : locale::facet(__refs) {}
2920
2921 _LIBCPP_ALWAYS_INLINE
2922 iter_type get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob,
2923 ios_base::iostate& __err, long double& __v) const
2924 {
2925 return do_get(__b, __e, __intl, __iob, __err, __v);
2926 }
2927
2928 _LIBCPP_ALWAYS_INLINE
2929 iter_type get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob,
2930 ios_base::iostate& __err, string_type& __v) const
2931 {
2932 return do_get(__b, __e, __intl, __iob, __err, __v);
2933 }
2934
2935 static locale::id id;
2936
2937protected:
2938
Howard Hinnant848a5372010-09-22 16:48:34 +00002939 _LIBCPP_ALWAYS_INLINE
Howard Hinnant3e519522010-05-11 19:42:16 +00002940 ~money_get() {}
Howard Hinnantb3371f62010-08-22 00:02:43 +00002941
Howard Hinnant3e519522010-05-11 19:42:16 +00002942 virtual iter_type do_get(iter_type __b, iter_type __e, bool __intl,
2943 ios_base& __iob, ios_base::iostate& __err,
2944 long double& __v) const;
2945 virtual iter_type do_get(iter_type __b, iter_type __e, bool __intl,
2946 ios_base& __iob, ios_base::iostate& __err,
2947 string_type& __v) const;
2948
2949private:
2950 static bool __do_get(iter_type& __b, iter_type __e,
2951 bool __intl, const locale& __loc,
2952 ios_base::fmtflags __flags, ios_base::iostate& __err,
2953 bool& __neg, const ctype<char_type>& __ct,
2954 unique_ptr<char_type, void(*)(void*)>& __wb,
2955 char_type*& __wn, char_type* __we);
2956};
2957
2958template <class _CharT, class _InputIterator>
2959locale::id
2960money_get<_CharT, _InputIterator>::id;
2961
Howard Hinnantf0544c22013-08-12 18:38:34 +00002962_LIBCPP_FUNC_VIS void __do_nothing(void*);
Howard Hinnant3e519522010-05-11 19:42:16 +00002963
2964template <class _Tp>
2965_LIBCPP_HIDDEN
2966void
2967__double_or_nothing(unique_ptr<_Tp, void(*)(void*)>& __b, _Tp*& __n, _Tp*& __e)
2968{
2969 bool __owns = __b.get_deleter() != __do_nothing;
Howard Hinnantc2063662011-12-01 20:21:04 +00002970 size_t __cur_cap = static_cast<size_t>(__e-__b.get()) * sizeof(_Tp);
Howard Hinnant3e519522010-05-11 19:42:16 +00002971 size_t __new_cap = __cur_cap < numeric_limits<size_t>::max() / 2 ?
2972 2 * __cur_cap : numeric_limits<size_t>::max();
Howard Hinnantc2063662011-12-01 20:21:04 +00002973 size_t __n_off = static_cast<size_t>(__n - __b.get());
Howard Hinnant3e519522010-05-11 19:42:16 +00002974 _Tp* __t = (_Tp*)realloc(__owns ? __b.get() : 0, __new_cap);
2975 if (__t == 0)
2976 __throw_bad_alloc();
2977 if (__owns)
2978 __b.release();
2979 __b = unique_ptr<_Tp, void(*)(void*)>(__t, free);
2980 __new_cap /= sizeof(_Tp);
2981 __n = __b.get() + __n_off;
2982 __e = __b.get() + __new_cap;
2983}
2984
2985// true == success
2986template <class _CharT, class _InputIterator>
2987bool
2988money_get<_CharT, _InputIterator>::__do_get(iter_type& __b, iter_type __e,
2989 bool __intl, const locale& __loc,
2990 ios_base::fmtflags __flags,
2991 ios_base::iostate& __err,
2992 bool& __neg,
2993 const ctype<char_type>& __ct,
2994 unique_ptr<char_type, void(*)(void*)>& __wb,
2995 char_type*& __wn, char_type* __we)
2996{
2997 const unsigned __bz = 100;
2998 unsigned __gbuf[__bz];
2999 unique_ptr<unsigned, void(*)(void*)> __gb(__gbuf, __do_nothing);
3000 unsigned* __gn = __gb.get();
3001 unsigned* __ge = __gn + __bz;
3002 money_base::pattern __pat;
3003 char_type __dp;
3004 char_type __ts;
3005 string __grp;
3006 string_type __sym;
3007 string_type __psn;
3008 string_type __nsn;
Jeffrey Yasskin9c95b192012-03-10 18:31:43 +00003009 // Capture the spaces read into money_base::{space,none} so they
3010 // can be compared to initial spaces in __sym.
3011 string_type __spaces;
Howard Hinnant3e519522010-05-11 19:42:16 +00003012 int __fd;
3013 __money_get<_CharT>::__gather_info(__intl, __loc, __pat, __dp, __ts, __grp,
3014 __sym, __psn, __nsn, __fd);
3015 const string_type* __trailing_sign = 0;
3016 __wn = __wb.get();
3017 for (unsigned __p = 0; __p < 4 && __b != __e; ++__p)
3018 {
3019 switch (__pat.field[__p])
3020 {
3021 case money_base::space:
3022 if (__p != 3)
3023 {
3024 if (__ct.is(ctype_base::space, *__b))
Jeffrey Yasskin9c95b192012-03-10 18:31:43 +00003025 __spaces.push_back(*__b++);
Howard Hinnant3e519522010-05-11 19:42:16 +00003026 else
3027 {
3028 __err |= ios_base::failbit;
3029 return false;
3030 }
3031 }
Howard Hinnantb3371f62010-08-22 00:02:43 +00003032 // drop through
Howard Hinnant3e519522010-05-11 19:42:16 +00003033 case money_base::none:
3034 if (__p != 3)
3035 {
3036 while (__b != __e && __ct.is(ctype_base::space, *__b))
Jeffrey Yasskin9c95b192012-03-10 18:31:43 +00003037 __spaces.push_back(*__b++);
Howard Hinnant3e519522010-05-11 19:42:16 +00003038 }
3039 break;
3040 case money_base::sign:
3041 if (__psn.size() + __nsn.size() > 0)
3042 {
3043 if (__psn.size() == 0 || __nsn.size() == 0)
3044 { // sign is optional
3045 if (__psn.size() > 0)
3046 { // __nsn.size() == 0
3047 if (*__b == __psn[0])
3048 {
3049 ++__b;
3050 if (__psn.size() > 1)
3051 __trailing_sign = &__psn;
3052 }
3053 else
3054 __neg = true;
3055 }
3056 else if (*__b == __nsn[0]) // __nsn.size() > 0 && __psn.size() == 0
3057 {
3058 ++__b;
3059 __neg = true;
3060 if (__nsn.size() > 1)
3061 __trailing_sign = &__nsn;
3062 }
3063 }
3064 else // sign is required
3065 {
3066 if (*__b == __psn[0])
3067 {
3068 ++__b;
3069 if (__psn.size() > 1)
3070 __trailing_sign = &__psn;
3071 }
3072 else if (*__b == __nsn[0])
3073 {
3074 ++__b;
3075 __neg = true;
3076 if (__nsn.size() > 1)
3077 __trailing_sign = &__nsn;
3078 }
3079 else
3080 {
3081 __err |= ios_base::failbit;
3082 return false;
3083 }
3084 }
3085 }
3086 break;
3087 case money_base::symbol:
3088 {
3089 bool __more_needed = __trailing_sign ||
3090 (__p < 2) ||
3091 (__p == 2 && __pat.field[3] != static_cast<char>(money_base::none));
Marshall Clow9f213252013-10-13 01:02:45 +00003092 bool __sb = (__flags & ios_base::showbase) != 0;
Howard Hinnant3e519522010-05-11 19:42:16 +00003093 if (__sb || __more_needed)
3094 {
Jeffrey Yasskin9c95b192012-03-10 18:31:43 +00003095 typename string_type::const_iterator __sym_space_end = __sym.begin();
3096 if (__p > 0 && (__pat.field[__p - 1] == money_base::none ||
3097 __pat.field[__p - 1] == money_base::space)) {
3098 // Match spaces we've already read against spaces at
3099 // the beginning of __sym.
3100 while (__sym_space_end != __sym.end() &&
3101 __ct.is(ctype_base::space, *__sym_space_end))
3102 ++__sym_space_end;
3103 const size_t __num_spaces = __sym_space_end - __sym.begin();
3104 if (__num_spaces > __spaces.size() ||
3105 !equal(__spaces.end() - __num_spaces, __spaces.end(),
3106 __sym.begin())) {
3107 // No match. Put __sym_space_end back at the
3108 // beginning of __sym, which will prevent a
3109 // match in the next loop.
3110 __sym_space_end = __sym.begin();
3111 }
3112 }
3113 typename string_type::const_iterator __sym_curr_char = __sym_space_end;
3114 while (__sym_curr_char != __sym.end() && __b != __e &&
3115 *__b == *__sym_curr_char) {
3116 ++__b;
3117 ++__sym_curr_char;
3118 }
3119 if (__sb && __sym_curr_char != __sym.end())
Howard Hinnant3e519522010-05-11 19:42:16 +00003120 {
3121 __err |= ios_base::failbit;
3122 return false;
3123 }
3124 }
3125 }
3126 break;
3127 case money_base::value:
3128 {
3129 unsigned __ng = 0;
3130 for (; __b != __e; ++__b)
3131 {
3132 char_type __c = *__b;
3133 if (__ct.is(ctype_base::digit, __c))
3134 {
3135 if (__wn == __we)
3136 __double_or_nothing(__wb, __wn, __we);
3137 *__wn++ = __c;
3138 ++__ng;
3139 }
3140 else if (__grp.size() > 0 && __ng > 0 && __c == __ts)
3141 {
3142 if (__gn == __ge)
3143 __double_or_nothing(__gb, __gn, __ge);
3144 *__gn++ = __ng;
3145 __ng = 0;
3146 }
3147 else
3148 break;
3149 }
3150 if (__gb.get() != __gn && __ng > 0)
3151 {
3152 if (__gn == __ge)
3153 __double_or_nothing(__gb, __gn, __ge);
3154 *__gn++ = __ng;
3155 }
3156 if (__fd > 0)
3157 {
3158 if (__b == __e || *__b != __dp)
3159 {
3160 __err |= ios_base::failbit;
3161 return false;
3162 }
3163 for (++__b; __fd > 0; --__fd, ++__b)
3164 {
3165 if (__b == __e || !__ct.is(ctype_base::digit, *__b))
3166 {
3167 __err |= ios_base::failbit;
3168 return false;
3169 }
3170 if (__wn == __we)
3171 __double_or_nothing(__wb, __wn, __we);
3172 *__wn++ = *__b;
3173 }
3174 }
3175 if (__wn == __wb.get())
3176 {
3177 __err |= ios_base::failbit;
3178 return false;
3179 }
3180 }
3181 break;
3182 }
3183 }
3184 if (__trailing_sign)
3185 {
3186 for (unsigned __i = 1; __i < __trailing_sign->size(); ++__i, ++__b)
3187 {
3188 if (__b == __e || *__b != (*__trailing_sign)[__i])
3189 {
3190 __err |= ios_base::failbit;
3191 return false;
3192 }
3193 }
3194 }
3195 if (__gb.get() != __gn)
3196 {
3197 ios_base::iostate __et = ios_base::goodbit;
3198 __check_grouping(__grp, __gb.get(), __gn, __et);
3199 if (__et)
3200 {
3201 __err |= ios_base::failbit;
3202 return false;
3203 }
3204 }
3205 return true;
3206}
3207
3208template <class _CharT, class _InputIterator>
3209_InputIterator
3210money_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
3211 bool __intl, ios_base& __iob,
3212 ios_base::iostate& __err,
3213 long double& __v) const
3214{
Howard Hinnantc2063662011-12-01 20:21:04 +00003215 const int __bz = 100;
Howard Hinnant3e519522010-05-11 19:42:16 +00003216 char_type __wbuf[__bz];
3217 unique_ptr<char_type, void(*)(void*)> __wb(__wbuf, __do_nothing);
3218 char_type* __wn;
3219 char_type* __we = __wbuf + __bz;
3220 locale __loc = __iob.getloc();
3221 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3222 bool __neg = false;
3223 if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct,
3224 __wb, __wn, __we))
3225 {
3226 const char __src[] = "0123456789";
3227 char_type __atoms[sizeof(__src)-1];
3228 __ct.widen(__src, __src + (sizeof(__src)-1), __atoms);
3229 char __nbuf[__bz];
3230 char* __nc = __nbuf;
3231 unique_ptr<char, void(*)(void*)> __h(0, free);
3232 if (__wn - __wb.get() > __bz-2)
3233 {
Howard Hinnantc2063662011-12-01 20:21:04 +00003234 __h.reset((char*)malloc(static_cast<size_t>(__wn - __wb.get() + 2)));
Howard Hinnant3e519522010-05-11 19:42:16 +00003235 if (__h.get() == 0)
3236 __throw_bad_alloc();
3237 __nc = __h.get();
3238 }
3239 if (__neg)
3240 *__nc++ = '-';
3241 for (const char_type* __w = __wb.get(); __w < __wn; ++__w, ++__nc)
Marshall Clowc962cdf2013-03-22 02:14:40 +00003242 *__nc = __src[find(__atoms, _VSTD::end(__atoms), *__w) - __atoms];
Howard Hinnant3e519522010-05-11 19:42:16 +00003243 *__nc = char();
3244 if (sscanf(__nbuf, "%Lf", &__v) != 1)
3245 __throw_runtime_error("money_get error");
3246 }
3247 if (__b == __e)
3248 __err |= ios_base::eofbit;
3249 return __b;
3250}
3251
3252template <class _CharT, class _InputIterator>
3253_InputIterator
3254money_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
3255 bool __intl, ios_base& __iob,
3256 ios_base::iostate& __err,
3257 string_type& __v) const
3258{
Howard Hinnantc2063662011-12-01 20:21:04 +00003259 const int __bz = 100;
Howard Hinnant3e519522010-05-11 19:42:16 +00003260 char_type __wbuf[__bz];
3261 unique_ptr<char_type, void(*)(void*)> __wb(__wbuf, __do_nothing);
3262 char_type* __wn;
3263 char_type* __we = __wbuf + __bz;
3264 locale __loc = __iob.getloc();
3265 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3266 bool __neg = false;
3267 if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct,
3268 __wb, __wn, __we))
3269 {
3270 __v.clear();
3271 if (__neg)
3272 __v.push_back(__ct.widen('-'));
3273 char_type __z = __ct.widen('0');
3274 char_type* __w;
3275 for (__w = __wb.get(); __w < __wn-1; ++__w)
3276 if (*__w != __z)
3277 break;
3278 __v.append(__w, __wn);
3279 }
3280 if (__b == __e)
3281 __err |= ios_base::eofbit;
3282 return __b;
3283}
3284
Howard Hinnantfc88dbd2013-08-23 17:37:05 +00003285_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS money_get<char>)
3286_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS money_get<wchar_t>)
Howard Hinnant3e519522010-05-11 19:42:16 +00003287
3288// money_put
3289
3290template <class _CharT>
3291class __money_put
3292{
3293protected:
3294 typedef _CharT char_type;
3295 typedef basic_string<char_type> string_type;
3296
3297 _LIBCPP_ALWAYS_INLINE __money_put() {}
3298
3299 static void __gather_info(bool __intl, bool __neg, const locale& __loc,
3300 money_base::pattern& __pat, char_type& __dp,
3301 char_type& __ts, string& __grp,
3302 string_type& __sym, string_type& __sn,
3303 int& __fd);
3304 static void __format(char_type* __mb, char_type*& __mi, char_type*& __me,
3305 ios_base::fmtflags __flags,
3306 const char_type* __db, const char_type* __de,
3307 const ctype<char_type>& __ct, bool __neg,
3308 const money_base::pattern& __pat, char_type __dp,
3309 char_type __ts, const string& __grp,
3310 const string_type& __sym, const string_type& __sn,
3311 int __fd);
3312};
3313
3314template <class _CharT>
3315void
3316__money_put<_CharT>::__gather_info(bool __intl, bool __neg, const locale& __loc,
3317 money_base::pattern& __pat, char_type& __dp,
3318 char_type& __ts, string& __grp,
3319 string_type& __sym, string_type& __sn,
3320 int& __fd)
3321{
3322 if (__intl)
3323 {
3324 const moneypunct<char_type, true>& __mp =
3325 use_facet<moneypunct<char_type, true> >(__loc);
3326 if (__neg)
3327 {
3328 __pat = __mp.neg_format();
3329 __sn = __mp.negative_sign();
3330 }
3331 else
3332 {
3333 __pat = __mp.pos_format();
3334 __sn = __mp.positive_sign();
3335 }
3336 __dp = __mp.decimal_point();
3337 __ts = __mp.thousands_sep();
3338 __grp = __mp.grouping();
3339 __sym = __mp.curr_symbol();
3340 __fd = __mp.frac_digits();
3341 }
3342 else
3343 {
3344 const moneypunct<char_type, false>& __mp =
3345 use_facet<moneypunct<char_type, false> >(__loc);
3346 if (__neg)
3347 {
3348 __pat = __mp.neg_format();
3349 __sn = __mp.negative_sign();
3350 }
3351 else
3352 {
3353 __pat = __mp.pos_format();
3354 __sn = __mp.positive_sign();
3355 }
3356 __dp = __mp.decimal_point();
3357 __ts = __mp.thousands_sep();
3358 __grp = __mp.grouping();
3359 __sym = __mp.curr_symbol();
3360 __fd = __mp.frac_digits();
3361 }
3362}
3363
3364template <class _CharT>
3365void
3366__money_put<_CharT>::__format(char_type* __mb, char_type*& __mi, char_type*& __me,
3367 ios_base::fmtflags __flags,
3368 const char_type* __db, const char_type* __de,
3369 const ctype<char_type>& __ct, bool __neg,
3370 const money_base::pattern& __pat, char_type __dp,
3371 char_type __ts, const string& __grp,
3372 const string_type& __sym, const string_type& __sn,
3373 int __fd)
3374{
3375 __me = __mb;
3376 for (unsigned __p = 0; __p < 4; ++__p)
3377 {
3378 switch (__pat.field[__p])
3379 {
3380 case money_base::none:
3381 __mi = __me;
3382 break;
3383 case money_base::space:
3384 __mi = __me;
3385 *__me++ = __ct.widen(' ');
3386 break;
3387 case money_base::sign:
3388 if (!__sn.empty())
3389 *__me++ = __sn[0];
3390 break;
3391 case money_base::symbol:
3392 if (!__sym.empty() && (__flags & ios_base::showbase))
Howard Hinnantce48a112011-06-30 21:18:19 +00003393 __me = _VSTD::copy(__sym.begin(), __sym.end(), __me);
Howard Hinnant3e519522010-05-11 19:42:16 +00003394 break;
3395 case money_base::value:
3396 {
3397 // remember start of value so we can reverse it
3398 char_type* __t = __me;
3399 // find beginning of digits
3400 if (__neg)
3401 ++__db;
3402 // find end of digits
3403 const char_type* __d;
3404 for (__d = __db; __d < __de; ++__d)
3405 if (!__ct.is(ctype_base::digit, *__d))
3406 break;
3407 // print fractional part
3408 if (__fd > 0)
3409 {
3410 int __f;
3411 for (__f = __fd; __d > __db && __f > 0; --__f)
3412 *__me++ = *--__d;
3413 char_type __z = __f > 0 ? __ct.widen('0') : char_type();
3414 for (; __f > 0; --__f)
3415 *__me++ = __z;
3416 *__me++ = __dp;
3417 }
3418 // print units part
3419 if (__d == __db)
3420 {
3421 *__me++ = __ct.widen('0');
3422 }
3423 else
3424 {
3425 unsigned __ng = 0;
3426 unsigned __ig = 0;
3427 unsigned __gl = __grp.empty() ? numeric_limits<unsigned>::max()
3428 : static_cast<unsigned>(__grp[__ig]);
3429 while (__d != __db)
3430 {
3431 if (__ng == __gl)
3432 {
3433 *__me++ = __ts;
3434 __ng = 0;
3435 if (++__ig < __grp.size())
3436 __gl = __grp[__ig] == numeric_limits<char>::max() ?
3437 numeric_limits<unsigned>::max() :
3438 static_cast<unsigned>(__grp[__ig]);
3439 }
3440 *__me++ = *--__d;
3441 ++__ng;
3442 }
3443 }
3444 // reverse it
3445 reverse(__t, __me);
3446 }
3447 break;
3448 }
3449 }
3450 // print rest of sign, if any
3451 if (__sn.size() > 1)
Howard Hinnantce48a112011-06-30 21:18:19 +00003452 __me = _VSTD::copy(__sn.begin()+1, __sn.end(), __me);
Howard Hinnant3e519522010-05-11 19:42:16 +00003453 // set alignment
3454 if ((__flags & ios_base::adjustfield) == ios_base::left)
3455 __mi = __me;
3456 else if ((__flags & ios_base::adjustfield) != ios_base::internal)
3457 __mi = __mb;
3458}
3459
Howard Hinnantfc88dbd2013-08-23 17:37:05 +00003460_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS __money_put<char>)
3461_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS __money_put<wchar_t>)
Howard Hinnant3e519522010-05-11 19:42:16 +00003462
3463template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnantf0544c22013-08-12 18:38:34 +00003464class _LIBCPP_TYPE_VIS_ONLY money_put
Howard Hinnant3e519522010-05-11 19:42:16 +00003465 : public locale::facet,
3466 private __money_put<_CharT>
3467{
3468public:
3469 typedef _CharT char_type;
3470 typedef _OutputIterator iter_type;
3471 typedef basic_string<char_type> string_type;
3472
3473 _LIBCPP_ALWAYS_INLINE
3474 explicit money_put(size_t __refs = 0)
3475 : locale::facet(__refs) {}
3476
3477 _LIBCPP_ALWAYS_INLINE
3478 iter_type put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl,
3479 long double __units) const
3480 {
3481 return do_put(__s, __intl, __iob, __fl, __units);
3482 }
3483
3484 _LIBCPP_ALWAYS_INLINE
3485 iter_type put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl,
3486 const string_type& __digits) const
3487 {
3488 return do_put(__s, __intl, __iob, __fl, __digits);
3489 }
3490
3491 static locale::id id;
3492
3493protected:
Howard Hinnant848a5372010-09-22 16:48:34 +00003494 _LIBCPP_ALWAYS_INLINE
Howard Hinnant3e519522010-05-11 19:42:16 +00003495 ~money_put() {}
3496
3497 virtual iter_type do_put(iter_type __s, bool __intl, ios_base& __iob,
3498 char_type __fl, long double __units) const;
3499 virtual iter_type do_put(iter_type __s, bool __intl, ios_base& __iob,
3500 char_type __fl, const string_type& __digits) const;
3501};
3502
3503template <class _CharT, class _OutputIterator>
3504locale::id
3505money_put<_CharT, _OutputIterator>::id;
3506
3507template <class _CharT, class _OutputIterator>
3508_OutputIterator
3509money_put<_CharT, _OutputIterator>::do_put(iter_type __s, bool __intl,
3510 ios_base& __iob, char_type __fl,
3511 long double __units) const
3512{
3513 // convert to char
3514 const size_t __bs = 100;
3515 char __buf[__bs];
3516 char* __bb = __buf;
3517 char_type __digits[__bs];
3518 char_type* __db = __digits;
Howard Hinnantc2063662011-12-01 20:21:04 +00003519 size_t __n = static_cast<size_t>(snprintf(__bb, __bs, "%.0Lf", __units));
Howard Hinnant3e519522010-05-11 19:42:16 +00003520 unique_ptr<char, void(*)(void*)> __hn(0, free);
3521 unique_ptr<char_type, void(*)(void*)> __hd(0, free);
3522 // secure memory for digit storage
3523 if (__n > __bs-1)
3524 {
Howard Hinnant9978e372011-09-28 23:39:33 +00003525#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantc2063662011-12-01 20:21:04 +00003526 __n = static_cast<size_t>(asprintf_l(&__bb, _LIBCPP_GET_C_LOCALE, "%.0Lf", __units));
Alexis Hunt4084c9e2011-07-15 05:40:33 +00003527#else
3528 __n = __asprintf_l(&__bb, __cloc(), "%.0Lf", __units);
3529#endif
Howard Hinnant3e519522010-05-11 19:42:16 +00003530 if (__bb == 0)
3531 __throw_bad_alloc();
3532 __hn.reset(__bb);
3533 __hd.reset((char_type*)malloc(__n * sizeof(char_type)));
Howard Hinnant8d5df9b2012-03-07 20:37:43 +00003534 if (__hd == nullptr)
Howard Hinnant3e519522010-05-11 19:42:16 +00003535 __throw_bad_alloc();
3536 __db = __hd.get();
3537 }
3538 // gather info
3539 locale __loc = __iob.getloc();
3540 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3541 __ct.widen(__bb, __bb + __n, __db);
3542 bool __neg = __n > 0 && __bb[0] == '-';
3543 money_base::pattern __pat;
3544 char_type __dp;
3545 char_type __ts;
3546 string __grp;
3547 string_type __sym;
3548 string_type __sn;
3549 int __fd;
3550 this->__gather_info(__intl, __neg, __loc, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3551 // secure memory for formatting
3552 char_type __mbuf[__bs];
3553 char_type* __mb = __mbuf;
3554 unique_ptr<char_type, void(*)(void*)> __hw(0, free);
3555 size_t __exn = static_cast<int>(__n) > __fd ?
Howard Hinnantc2063662011-12-01 20:21:04 +00003556 (__n - static_cast<size_t>(__fd)) * 2 + __sn.size() +
3557 __sym.size() + static_cast<size_t>(__fd) + 1
3558 : __sn.size() + __sym.size() + static_cast<size_t>(__fd) + 2;
Howard Hinnant3e519522010-05-11 19:42:16 +00003559 if (__exn > __bs)
3560 {
3561 __hw.reset((char_type*)malloc(__exn * sizeof(char_type)));
3562 __mb = __hw.get();
3563 if (__mb == 0)
3564 __throw_bad_alloc();
3565 }
3566 // format
3567 char_type* __mi;
3568 char_type* __me;
3569 this->__format(__mb, __mi, __me, __iob.flags(),
3570 __db, __db + __n, __ct,
3571 __neg, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3572 return __pad_and_output(__s, __mb, __mi, __me, __iob, __fl);
3573}
3574
3575template <class _CharT, class _OutputIterator>
3576_OutputIterator
3577money_put<_CharT, _OutputIterator>::do_put(iter_type __s, bool __intl,
3578 ios_base& __iob, char_type __fl,
3579 const string_type& __digits) const
3580{
3581 // gather info
3582 locale __loc = __iob.getloc();
3583 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3584 bool __neg = __digits.size() > 0 && __digits[0] == __ct.widen('-');
3585 money_base::pattern __pat;
3586 char_type __dp;
3587 char_type __ts;
3588 string __grp;
3589 string_type __sym;
3590 string_type __sn;
3591 int __fd;
3592 this->__gather_info(__intl, __neg, __loc, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3593 // secure memory for formatting
3594 char_type __mbuf[100];
3595 char_type* __mb = __mbuf;
3596 unique_ptr<char_type, void(*)(void*)> __h(0, free);
Howard Hinnantc2063662011-12-01 20:21:04 +00003597 size_t __exn = static_cast<int>(__digits.size()) > __fd ?
3598 (__digits.size() - static_cast<size_t>(__fd)) * 2 +
3599 __sn.size() + __sym.size() + static_cast<size_t>(__fd) + 1
3600 : __sn.size() + __sym.size() + static_cast<size_t>(__fd) + 2;
Howard Hinnant3e519522010-05-11 19:42:16 +00003601 if (__exn > 100)
3602 {
3603 __h.reset((char_type*)malloc(__exn * sizeof(char_type)));
3604 __mb = __h.get();
3605 if (__mb == 0)
3606 __throw_bad_alloc();
3607 }
3608 // format
3609 char_type* __mi;
3610 char_type* __me;
3611 this->__format(__mb, __mi, __me, __iob.flags(),
3612 __digits.data(), __digits.data() + __digits.size(), __ct,
3613 __neg, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3614 return __pad_and_output(__s, __mb, __mi, __me, __iob, __fl);
3615}
3616
Howard Hinnantfc88dbd2013-08-23 17:37:05 +00003617_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS money_put<char>)
3618_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS money_put<wchar_t>)
Howard Hinnant3e519522010-05-11 19:42:16 +00003619
3620// messages
3621
Howard Hinnant6e412562013-03-06 23:30:19 +00003622class _LIBCPP_TYPE_VIS messages_base
Howard Hinnant3e519522010-05-11 19:42:16 +00003623{
3624public:
Howard Hinnant0c68ed02011-02-25 00:51:08 +00003625 typedef ptrdiff_t catalog;
Howard Hinnant3e519522010-05-11 19:42:16 +00003626
3627 _LIBCPP_ALWAYS_INLINE messages_base() {}
3628};
3629
3630template <class _CharT>
Howard Hinnantf0544c22013-08-12 18:38:34 +00003631class _LIBCPP_TYPE_VIS_ONLY messages
Howard Hinnant3e519522010-05-11 19:42:16 +00003632 : public locale::facet,
3633 public messages_base
3634{
3635public:
3636 typedef _CharT char_type;
3637 typedef basic_string<_CharT> string_type;
3638
3639 _LIBCPP_ALWAYS_INLINE
3640 explicit messages(size_t __refs = 0)
3641 : locale::facet(__refs) {}
3642
3643 _LIBCPP_ALWAYS_INLINE
3644 catalog open(const basic_string<char>& __nm, const locale& __loc) const
3645 {
3646 return do_open(__nm, __loc);
3647 }
3648
3649 _LIBCPP_ALWAYS_INLINE
3650 string_type get(catalog __c, int __set, int __msgid,
3651 const string_type& __dflt) const
3652 {
3653 return do_get(__c, __set, __msgid, __dflt);
3654 }
3655
3656 _LIBCPP_ALWAYS_INLINE
3657 void close(catalog __c) const
3658 {
3659 do_close(__c);
3660 }
3661
3662 static locale::id id;
3663
3664protected:
Howard Hinnant848a5372010-09-22 16:48:34 +00003665 _LIBCPP_ALWAYS_INLINE
Howard Hinnant3e519522010-05-11 19:42:16 +00003666 ~messages() {}
3667
3668 virtual catalog do_open(const basic_string<char>&, const locale&) const;
3669 virtual string_type do_get(catalog, int __set, int __msgid,
3670 const string_type& __dflt) const;
3671 virtual void do_close(catalog) const;
3672};
3673
3674template <class _CharT>
3675locale::id
3676messages<_CharT>::id;
3677
3678template <class _CharT>
3679typename messages<_CharT>::catalog
3680messages<_CharT>::do_open(const basic_string<char>& __nm, const locale&) const
3681{
Jonathan Roelofs4f1561a2014-09-19 20:09:12 +00003682#if defined(_WIN32) || defined(__ANDROID__) || defined(_NEWLIB_VERSION)
Howard Hinnantdbe81112011-09-23 16:11:27 +00003683 return -1;
Marshall Clowb38f8f02014-07-10 15:20:28 +00003684#else // _WIN32 || __ANDROID__
Howard Hinnanta33d4bc2011-10-11 16:00:46 +00003685 catalog __cat = (catalog)catopen(__nm.c_str(), NL_CAT_LOCALE);
Howard Hinnant0c68ed02011-02-25 00:51:08 +00003686 if (__cat != -1)
3687 __cat = static_cast<catalog>((static_cast<size_t>(__cat) >> 1));
3688 return __cat;
Marshall Clowb38f8f02014-07-10 15:20:28 +00003689#endif // _WIN32 || __ANDROID__
Howard Hinnant3e519522010-05-11 19:42:16 +00003690}
3691
3692template <class _CharT>
3693typename messages<_CharT>::string_type
3694messages<_CharT>::do_get(catalog __c, int __set, int __msgid,
3695 const string_type& __dflt) const
3696{
Jonathan Roelofs4f1561a2014-09-19 20:09:12 +00003697#if defined(_WIN32) || defined(__ANDROID__) || defined(_NEWLIB_VERSION)
Howard Hinnantdbe81112011-09-23 16:11:27 +00003698 return __dflt;
3699#else // _WIN32
Howard Hinnant3e519522010-05-11 19:42:16 +00003700 string __ndflt;
3701 __narrow_to_utf8<sizeof(char_type)*__CHAR_BIT__>()(back_inserter(__ndflt),
3702 __dflt.c_str(),
3703 __dflt.c_str() + __dflt.size());
Howard Hinnant0c68ed02011-02-25 00:51:08 +00003704 if (__c != -1)
3705 __c <<= 1;
Howard Hinnanta33d4bc2011-10-11 16:00:46 +00003706 nl_catd __cat = (nl_catd)__c;
Howard Hinnant0c68ed02011-02-25 00:51:08 +00003707 char* __n = catgets(__cat, __set, __msgid, __ndflt.c_str());
Howard Hinnant3e519522010-05-11 19:42:16 +00003708 string_type __w;
3709 __widen_from_utf8<sizeof(char_type)*__CHAR_BIT__>()(back_inserter(__w),
3710 __n, __n + strlen(__n));
3711 return __w;
Howard Hinnantdbe81112011-09-23 16:11:27 +00003712#endif // _WIN32
Howard Hinnant3e519522010-05-11 19:42:16 +00003713}
3714
3715template <class _CharT>
3716void
3717messages<_CharT>::do_close(catalog __c) const
3718{
Jonathan Roelofs4f1561a2014-09-19 20:09:12 +00003719#if !defined(_WIN32) && !defined(__ANDROID__) && !defined(_NEWLIB_VERSION)
Howard Hinnant0c68ed02011-02-25 00:51:08 +00003720 if (__c != -1)
3721 __c <<= 1;
Howard Hinnanta33d4bc2011-10-11 16:00:46 +00003722 nl_catd __cat = (nl_catd)__c;
Howard Hinnant0c68ed02011-02-25 00:51:08 +00003723 catclose(__cat);
Howard Hinnantdbe81112011-09-23 16:11:27 +00003724#endif // !_WIN32
Howard Hinnant3e519522010-05-11 19:42:16 +00003725}
3726
Howard Hinnantfc88dbd2013-08-23 17:37:05 +00003727_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS messages<char>)
3728_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS messages<wchar_t>)
Howard Hinnant3e519522010-05-11 19:42:16 +00003729
3730template <class _CharT>
Howard Hinnantf0544c22013-08-12 18:38:34 +00003731class _LIBCPP_TYPE_VIS_ONLY messages_byname
Howard Hinnant3e519522010-05-11 19:42:16 +00003732 : public messages<_CharT>
3733{
3734public:
3735 typedef messages_base::catalog catalog;
3736 typedef basic_string<_CharT> string_type;
3737
3738 _LIBCPP_ALWAYS_INLINE
3739 explicit messages_byname(const char*, size_t __refs = 0)
3740 : messages<_CharT>(__refs) {}
3741
3742 _LIBCPP_ALWAYS_INLINE
3743 explicit messages_byname(const string&, size_t __refs = 0)
3744 : messages<_CharT>(__refs) {}
3745
3746protected:
Howard Hinnant848a5372010-09-22 16:48:34 +00003747 _LIBCPP_ALWAYS_INLINE
Howard Hinnant3e519522010-05-11 19:42:16 +00003748 ~messages_byname() {}
3749};
3750
Howard Hinnantfc88dbd2013-08-23 17:37:05 +00003751_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS messages_byname<char>)
3752_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS messages_byname<wchar_t>)
Howard Hinnant3e519522010-05-11 19:42:16 +00003753
Howard Hinnant5d3c1132010-05-31 20:58:54 +00003754template<class _Codecvt, class _Elem = wchar_t,
3755 class _Wide_alloc = allocator<_Elem>,
3756 class _Byte_alloc = allocator<char> >
Howard Hinnantf0544c22013-08-12 18:38:34 +00003757class _LIBCPP_TYPE_VIS_ONLY wstring_convert
Howard Hinnant5d3c1132010-05-31 20:58:54 +00003758{
3759public:
3760 typedef basic_string<char, char_traits<char>, _Byte_alloc> byte_string;
3761 typedef basic_string<_Elem, char_traits<_Elem>, _Wide_alloc> wide_string;
3762 typedef typename _Codecvt::state_type state_type;
3763 typedef typename wide_string::traits_type::int_type int_type;
3764
3765private:
3766 byte_string __byte_err_string_;
3767 wide_string __wide_err_string_;
3768 _Codecvt* __cvtptr_;
3769 state_type __cvtstate_;
3770 size_t __cvtcount_;
3771
3772 wstring_convert(const wstring_convert& __wc);
3773 wstring_convert& operator=(const wstring_convert& __wc);
3774public:
Marshall Clow7988106b2013-08-27 20:18:59 +00003775 _LIBCPP_EXPLICIT_AFTER_CXX11 wstring_convert(_Codecvt* __pcvt = new _Codecvt);
Howard Hinnant5d3c1132010-05-31 20:58:54 +00003776 wstring_convert(_Codecvt* __pcvt, state_type __state);
Marshall Clow7988106b2013-08-27 20:18:59 +00003777 _LIBCPP_EXPLICIT_AFTER_CXX11 wstring_convert(const byte_string& __byte_err,
Howard Hinnant5d3c1132010-05-31 20:58:54 +00003778 const wide_string& __wide_err = wide_string());
Howard Hinnant7609c9b2010-09-04 23:28:19 +00003779#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnant5d3c1132010-05-31 20:58:54 +00003780 wstring_convert(wstring_convert&& __wc);
3781#endif
3782 ~wstring_convert();
3783
Howard Hinnant848a5372010-09-22 16:48:34 +00003784 _LIBCPP_ALWAYS_INLINE
Howard Hinnant5d3c1132010-05-31 20:58:54 +00003785 wide_string from_bytes(char __byte)
3786 {return from_bytes(&__byte, &__byte+1);}
Howard Hinnant848a5372010-09-22 16:48:34 +00003787 _LIBCPP_ALWAYS_INLINE
Howard Hinnant5d3c1132010-05-31 20:58:54 +00003788 wide_string from_bytes(const char* __ptr)
3789 {return from_bytes(__ptr, __ptr + char_traits<char>::length(__ptr));}
Howard Hinnant848a5372010-09-22 16:48:34 +00003790 _LIBCPP_ALWAYS_INLINE
Howard Hinnant5d3c1132010-05-31 20:58:54 +00003791 wide_string from_bytes(const byte_string& __str)
3792 {return from_bytes(__str.data(), __str.data() + __str.size());}
3793 wide_string from_bytes(const char* __first, const char* __last);
3794
Howard Hinnant848a5372010-09-22 16:48:34 +00003795 _LIBCPP_ALWAYS_INLINE
Howard Hinnant5d3c1132010-05-31 20:58:54 +00003796 byte_string to_bytes(_Elem __wchar)
3797 {return to_bytes(&__wchar, &__wchar+1);}
Howard Hinnant848a5372010-09-22 16:48:34 +00003798 _LIBCPP_ALWAYS_INLINE
Howard Hinnant5d3c1132010-05-31 20:58:54 +00003799 byte_string to_bytes(const _Elem* __wptr)
3800 {return to_bytes(__wptr, __wptr + char_traits<_Elem>::length(__wptr));}
Howard Hinnant848a5372010-09-22 16:48:34 +00003801 _LIBCPP_ALWAYS_INLINE
Howard Hinnant5d3c1132010-05-31 20:58:54 +00003802 byte_string to_bytes(const wide_string& __wstr)
3803 {return to_bytes(__wstr.data(), __wstr.data() + __wstr.size());}
3804 byte_string to_bytes(const _Elem* __first, const _Elem* __last);
3805
Howard Hinnant848a5372010-09-22 16:48:34 +00003806 _LIBCPP_ALWAYS_INLINE
Marshall Clow7988106b2013-08-27 20:18:59 +00003807 size_t converted() const _NOEXCEPT {return __cvtcount_;}
Howard Hinnant848a5372010-09-22 16:48:34 +00003808 _LIBCPP_ALWAYS_INLINE
Howard Hinnant5d3c1132010-05-31 20:58:54 +00003809 state_type state() const {return __cvtstate_;}
3810};
3811
3812template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Howard Hinnant848a5372010-09-22 16:48:34 +00003813inline _LIBCPP_ALWAYS_INLINE
Howard Hinnant5d3c1132010-05-31 20:58:54 +00003814wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3815 wstring_convert(_Codecvt* __pcvt)
3816 : __cvtptr_(__pcvt), __cvtstate_(), __cvtcount_(0)
3817{
3818}
3819
3820template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Howard Hinnant848a5372010-09-22 16:48:34 +00003821inline _LIBCPP_ALWAYS_INLINE
Howard Hinnant5d3c1132010-05-31 20:58:54 +00003822wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3823 wstring_convert(_Codecvt* __pcvt, state_type __state)
3824 : __cvtptr_(__pcvt), __cvtstate_(__state), __cvtcount_(0)
3825{
3826}
3827
3828template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3829wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3830 wstring_convert(const byte_string& __byte_err, const wide_string& __wide_err)
3831 : __byte_err_string_(__byte_err), __wide_err_string_(__wide_err),
3832 __cvtstate_(), __cvtcount_(0)
3833{
3834 __cvtptr_ = new _Codecvt;
3835}
3836
Howard Hinnant7609c9b2010-09-04 23:28:19 +00003837#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnant5d3c1132010-05-31 20:58:54 +00003838
3839template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Howard Hinnant848a5372010-09-22 16:48:34 +00003840inline _LIBCPP_ALWAYS_INLINE
Howard Hinnant5d3c1132010-05-31 20:58:54 +00003841wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3842 wstring_convert(wstring_convert&& __wc)
Howard Hinnantce48a112011-06-30 21:18:19 +00003843 : __byte_err_string_(_VSTD::move(__wc.__byte_err_string_)),
3844 __wide_err_string_(_VSTD::move(__wc.__wide_err_string_)),
Howard Hinnant5d3c1132010-05-31 20:58:54 +00003845 __cvtptr_(__wc.__cvtptr_),
3846 __cvtstate_(__wc.__cvtstate_), __cvtcount_(__wc.__cvtstate_)
3847{
3848 __wc.__cvtptr_ = nullptr;
3849}
3850
Howard Hinnant959cf8a2010-09-04 23:46:48 +00003851#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnant5d3c1132010-05-31 20:58:54 +00003852
3853template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3854wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::~wstring_convert()
3855{
3856 delete __cvtptr_;
3857}
3858
3859template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3860typename wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::wide_string
3861wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3862 from_bytes(const char* __frm, const char* __frm_end)
3863{
3864 __cvtcount_ = 0;
3865 if (__cvtptr_ != nullptr)
3866 {
3867 wide_string __ws(2*(__frm_end - __frm), _Elem());
Howard Hinnant91469842012-07-12 18:07:41 +00003868 if (__frm != __frm_end)
3869 __ws.resize(__ws.capacity());
Howard Hinnant5d3c1132010-05-31 20:58:54 +00003870 codecvt_base::result __r = codecvt_base::ok;
3871 state_type __st = __cvtstate_;
3872 if (__frm != __frm_end)
3873 {
3874 _Elem* __to = &__ws[0];
3875 _Elem* __to_end = __to + __ws.size();
3876 const char* __frm_nxt;
3877 do
3878 {
3879 _Elem* __to_nxt;
3880 __r = __cvtptr_->in(__st, __frm, __frm_end, __frm_nxt,
3881 __to, __to_end, __to_nxt);
3882 __cvtcount_ += __frm_nxt - __frm;
3883 if (__frm_nxt == __frm)
3884 {
3885 __r = codecvt_base::error;
3886 }
3887 else if (__r == codecvt_base::noconv)
3888 {
3889 __ws.resize(__to - &__ws[0]);
3890 // This only gets executed if _Elem is char
3891 __ws.append((const _Elem*)__frm, (const _Elem*)__frm_end);
3892 __frm = __frm_nxt;
3893 __r = codecvt_base::ok;
3894 }
3895 else if (__r == codecvt_base::ok)
3896 {
3897 __ws.resize(__to_nxt - &__ws[0]);
3898 __frm = __frm_nxt;
3899 }
3900 else if (__r == codecvt_base::partial)
3901 {
3902 ptrdiff_t __s = __to_nxt - &__ws[0];
3903 __ws.resize(2 * __s);
3904 __to = &__ws[0] + __s;
3905 __to_end = &__ws[0] + __ws.size();
3906 __frm = __frm_nxt;
3907 }
3908 } while (__r == codecvt_base::partial && __frm_nxt < __frm_end);
3909 }
3910 if (__r == codecvt_base::ok)
3911 return __ws;
3912 }
Howard Hinnant54b409f2010-08-11 17:04:31 +00003913#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant5d3c1132010-05-31 20:58:54 +00003914 if (__wide_err_string_.empty())
3915 throw range_error("wstring_convert: from_bytes error");
Howard Hinnantb3371f62010-08-22 00:02:43 +00003916#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant5d3c1132010-05-31 20:58:54 +00003917 return __wide_err_string_;
3918}
3919
3920template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3921typename wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::byte_string
3922wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3923 to_bytes(const _Elem* __frm, const _Elem* __frm_end)
3924{
3925 __cvtcount_ = 0;
3926 if (__cvtptr_ != nullptr)
3927 {
3928 byte_string __bs(2*(__frm_end - __frm), char());
Howard Hinnant91469842012-07-12 18:07:41 +00003929 if (__frm != __frm_end)
3930 __bs.resize(__bs.capacity());
Howard Hinnant5d3c1132010-05-31 20:58:54 +00003931 codecvt_base::result __r = codecvt_base::ok;
3932 state_type __st = __cvtstate_;
3933 if (__frm != __frm_end)
3934 {
3935 char* __to = &__bs[0];
3936 char* __to_end = __to + __bs.size();
3937 const _Elem* __frm_nxt;
3938 do
3939 {
3940 char* __to_nxt;
3941 __r = __cvtptr_->out(__st, __frm, __frm_end, __frm_nxt,
3942 __to, __to_end, __to_nxt);
3943 __cvtcount_ += __frm_nxt - __frm;
3944 if (__frm_nxt == __frm)
3945 {
3946 __r = codecvt_base::error;
3947 }
3948 else if (__r == codecvt_base::noconv)
3949 {
3950 __bs.resize(__to - &__bs[0]);
3951 // This only gets executed if _Elem is char
3952 __bs.append((const char*)__frm, (const char*)__frm_end);
3953 __frm = __frm_nxt;
3954 __r = codecvt_base::ok;
3955 }
3956 else if (__r == codecvt_base::ok)
3957 {
3958 __bs.resize(__to_nxt - &__bs[0]);
3959 __frm = __frm_nxt;
3960 }
3961 else if (__r == codecvt_base::partial)
3962 {
3963 ptrdiff_t __s = __to_nxt - &__bs[0];
3964 __bs.resize(2 * __s);
3965 __to = &__bs[0] + __s;
3966 __to_end = &__bs[0] + __bs.size();
3967 __frm = __frm_nxt;
3968 }
3969 } while (__r == codecvt_base::partial && __frm_nxt < __frm_end);
3970 }
3971 if (__r == codecvt_base::ok)
3972 {
3973 size_t __s = __bs.size();
3974 __bs.resize(__bs.capacity());
3975 char* __to = &__bs[0] + __s;
3976 char* __to_end = __to + __bs.size();
3977 do
3978 {
3979 char* __to_nxt;
3980 __r = __cvtptr_->unshift(__st, __to, __to_end, __to_nxt);
3981 if (__r == codecvt_base::noconv)
3982 {
3983 __bs.resize(__to - &__bs[0]);
3984 __r = codecvt_base::ok;
3985 }
3986 else if (__r == codecvt_base::ok)
3987 {
3988 __bs.resize(__to_nxt - &__bs[0]);
3989 }
3990 else if (__r == codecvt_base::partial)
3991 {
Howard Hinnantc2063662011-12-01 20:21:04 +00003992 ptrdiff_t __sp = __to_nxt - &__bs[0];
3993 __bs.resize(2 * __sp);
3994 __to = &__bs[0] + __sp;
Howard Hinnant5d3c1132010-05-31 20:58:54 +00003995 __to_end = &__bs[0] + __bs.size();
3996 }
3997 } while (__r == codecvt_base::partial);
3998 if (__r == codecvt_base::ok)
3999 return __bs;
4000 }
4001 }
Howard Hinnant54b409f2010-08-11 17:04:31 +00004002#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant5d3c1132010-05-31 20:58:54 +00004003 if (__byte_err_string_.empty())
4004 throw range_error("wstring_convert: to_bytes error");
Howard Hinnantb3371f62010-08-22 00:02:43 +00004005#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant5d3c1132010-05-31 20:58:54 +00004006 return __byte_err_string_;
4007}
4008
4009template <class _Codecvt, class _Elem = wchar_t, class _Tr = char_traits<_Elem> >
Howard Hinnantf0544c22013-08-12 18:38:34 +00004010class _LIBCPP_TYPE_VIS_ONLY wbuffer_convert
Howard Hinnant5d3c1132010-05-31 20:58:54 +00004011 : public basic_streambuf<_Elem, _Tr>
4012{
4013public:
4014 // types:
4015 typedef _Elem char_type;
4016 typedef _Tr traits_type;
4017 typedef typename traits_type::int_type int_type;
4018 typedef typename traits_type::pos_type pos_type;
4019 typedef typename traits_type::off_type off_type;
4020 typedef typename _Codecvt::state_type state_type;
4021
4022private:
Howard Hinnant6508e992010-06-01 20:09:18 +00004023 char* __extbuf_;
4024 const char* __extbufnext_;
4025 const char* __extbufend_;
4026 char __extbuf_min_[8];
4027 size_t __ebs_;
4028 char_type* __intbuf_;
4029 size_t __ibs_;
Howard Hinnant5d3c1132010-05-31 20:58:54 +00004030 streambuf* __bufptr_;
Howard Hinnant6508e992010-06-01 20:09:18 +00004031 _Codecvt* __cv_;
4032 state_type __st_;
4033 ios_base::openmode __cm_;
4034 bool __owns_eb_;
4035 bool __owns_ib_;
4036 bool __always_noconv_;
Howard Hinnant5d3c1132010-05-31 20:58:54 +00004037
Howard Hinnant6508e992010-06-01 20:09:18 +00004038 wbuffer_convert(const wbuffer_convert&);
4039 wbuffer_convert& operator=(const wbuffer_convert&);
Howard Hinnant5d3c1132010-05-31 20:58:54 +00004040public:
Marshall Clow7988106b2013-08-27 20:18:59 +00004041 _LIBCPP_EXPLICIT_AFTER_CXX11 wbuffer_convert(streambuf* __bytebuf = 0,
4042 _Codecvt* __pcvt = new _Codecvt, state_type __state = state_type());
Howard Hinnant6508e992010-06-01 20:09:18 +00004043 ~wbuffer_convert();
Howard Hinnant5d3c1132010-05-31 20:58:54 +00004044
Howard Hinnant848a5372010-09-22 16:48:34 +00004045 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5d3c1132010-05-31 20:58:54 +00004046 streambuf* rdbuf() const {return __bufptr_;}
Howard Hinnant848a5372010-09-22 16:48:34 +00004047 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5d3c1132010-05-31 20:58:54 +00004048 streambuf* rdbuf(streambuf* __bytebuf)
4049 {
4050 streambuf* __r = __bufptr_;
4051 __bufptr_ = __bytebuf;
4052 return __r;
4053 }
4054
Howard Hinnant848a5372010-09-22 16:48:34 +00004055 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant6508e992010-06-01 20:09:18 +00004056 state_type state() const {return __st_;}
Howard Hinnant5d3c1132010-05-31 20:58:54 +00004057
4058protected:
Howard Hinnant6508e992010-06-01 20:09:18 +00004059 virtual int_type underflow();
4060 virtual int_type pbackfail(int_type __c = traits_type::eof());
Howard Hinnant5d3c1132010-05-31 20:58:54 +00004061 virtual int_type overflow (int_type __c = traits_type::eof());
Howard Hinnant6508e992010-06-01 20:09:18 +00004062 virtual basic_streambuf<char_type, traits_type>* setbuf(char_type* __s,
4063 streamsize __n);
4064 virtual pos_type seekoff(off_type __off, ios_base::seekdir __way,
4065 ios_base::openmode __wch = ios_base::in | ios_base::out);
4066 virtual pos_type seekpos(pos_type __sp,
4067 ios_base::openmode __wch = ios_base::in | ios_base::out);
4068 virtual int sync();
4069
4070private:
4071 bool __read_mode();
4072 void __write_mode();
4073 wbuffer_convert* __close();
Howard Hinnant5d3c1132010-05-31 20:58:54 +00004074};
4075
4076template <class _Codecvt, class _Elem, class _Tr>
Howard Hinnant6508e992010-06-01 20:09:18 +00004077wbuffer_convert<_Codecvt, _Elem, _Tr>::
4078 wbuffer_convert(streambuf* __bytebuf, _Codecvt* __pcvt, state_type __state)
4079 : __extbuf_(0),
4080 __extbufnext_(0),
4081 __extbufend_(0),
4082 __ebs_(0),
4083 __intbuf_(0),
4084 __ibs_(0),
4085 __bufptr_(__bytebuf),
4086 __cv_(__pcvt),
4087 __st_(__state),
4088 __cm_(0),
4089 __owns_eb_(false),
4090 __owns_ib_(false),
4091 __always_noconv_(__cv_ ? __cv_->always_noconv() : false)
4092{
4093 setbuf(0, 4096);
4094}
4095
4096template <class _Codecvt, class _Elem, class _Tr>
4097wbuffer_convert<_Codecvt, _Elem, _Tr>::~wbuffer_convert()
4098{
4099 __close();
4100 delete __cv_;
4101 if (__owns_eb_)
4102 delete [] __extbuf_;
4103 if (__owns_ib_)
4104 delete [] __intbuf_;
4105}
4106
4107template <class _Codecvt, class _Elem, class _Tr>
4108typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
4109wbuffer_convert<_Codecvt, _Elem, _Tr>::underflow()
4110{
4111 if (__cv_ == 0 || __bufptr_ == 0)
4112 return traits_type::eof();
4113 bool __initial = __read_mode();
4114 char_type __1buf;
4115 if (this->gptr() == 0)
4116 this->setg(&__1buf, &__1buf+1, &__1buf+1);
4117 const size_t __unget_sz = __initial ? 0 : min<size_t>((this->egptr() - this->eback()) / 2, 4);
4118 int_type __c = traits_type::eof();
4119 if (this->gptr() == this->egptr())
4120 {
4121 memmove(this->eback(), this->egptr() - __unget_sz, __unget_sz * sizeof(char_type));
4122 if (__always_noconv_)
4123 {
4124 streamsize __nmemb = static_cast<streamsize>(this->egptr() - this->eback() - __unget_sz);
4125 __nmemb = __bufptr_->sgetn((char*)this->eback() + __unget_sz, __nmemb);
4126 if (__nmemb != 0)
4127 {
4128 this->setg(this->eback(),
4129 this->eback() + __unget_sz,
4130 this->eback() + __unget_sz + __nmemb);
4131 __c = *this->gptr();
4132 }
4133 }
4134 else
4135 {
4136 memmove(__extbuf_, __extbufnext_, __extbufend_ - __extbufnext_);
4137 __extbufnext_ = __extbuf_ + (__extbufend_ - __extbufnext_);
4138 __extbufend_ = __extbuf_ + (__extbuf_ == __extbuf_min_ ? sizeof(__extbuf_min_) : __ebs_);
Howard Hinnantce48a112011-06-30 21:18:19 +00004139 streamsize __nmemb = _VSTD::min(static_cast<streamsize>(this->egptr() - this->eback() - __unget_sz),
Howard Hinnant6508e992010-06-01 20:09:18 +00004140 static_cast<streamsize>(__extbufend_ - __extbufnext_));
4141 codecvt_base::result __r;
4142 state_type __svs = __st_;
4143 streamsize __nr = __bufptr_->sgetn(const_cast<char*>(__extbufnext_), __nmemb);
4144 if (__nr != 0)
4145 {
4146 __extbufend_ = __extbufnext_ + __nr;
4147 char_type* __inext;
4148 __r = __cv_->in(__st_, __extbuf_, __extbufend_, __extbufnext_,
4149 this->eback() + __unget_sz,
4150 this->egptr(), __inext);
4151 if (__r == codecvt_base::noconv)
4152 {
4153 this->setg((char_type*)__extbuf_, (char_type*)__extbuf_, (char_type*)__extbufend_);
4154 __c = *this->gptr();
4155 }
4156 else if (__inext != this->eback() + __unget_sz)
4157 {
4158 this->setg(this->eback(), this->eback() + __unget_sz, __inext);
4159 __c = *this->gptr();
4160 }
4161 }
4162 }
4163 }
4164 else
4165 __c = *this->gptr();
4166 if (this->eback() == &__1buf)
4167 this->setg(0, 0, 0);
4168 return __c;
4169}
4170
4171template <class _Codecvt, class _Elem, class _Tr>
4172typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
4173wbuffer_convert<_Codecvt, _Elem, _Tr>::pbackfail(int_type __c)
4174{
4175 if (__cv_ != 0 && __bufptr_ != 0 && this->eback() < this->gptr())
4176 {
4177 if (traits_type::eq_int_type(__c, traits_type::eof()))
4178 {
4179 this->gbump(-1);
4180 return traits_type::not_eof(__c);
4181 }
4182 if (traits_type::eq(traits_type::to_char_type(__c), this->gptr()[-1]))
4183 {
4184 this->gbump(-1);
4185 *this->gptr() = traits_type::to_char_type(__c);
4186 return __c;
4187 }
4188 }
4189 return traits_type::eof();
4190}
4191
4192template <class _Codecvt, class _Elem, class _Tr>
Howard Hinnant5d3c1132010-05-31 20:58:54 +00004193typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
4194wbuffer_convert<_Codecvt, _Elem, _Tr>::overflow(int_type __c)
4195{
Howard Hinnant6508e992010-06-01 20:09:18 +00004196 if (__cv_ == 0 || __bufptr_ == 0)
4197 return traits_type::eof();
4198 __write_mode();
4199 char_type __1buf;
4200 char_type* __pb_save = this->pbase();
4201 char_type* __epb_save = this->epptr();
4202 if (!traits_type::eq_int_type(__c, traits_type::eof()))
4203 {
4204 if (this->pptr() == 0)
4205 this->setp(&__1buf, &__1buf+1);
4206 *this->pptr() = traits_type::to_char_type(__c);
4207 this->pbump(1);
4208 }
4209 if (this->pptr() != this->pbase())
4210 {
4211 if (__always_noconv_)
4212 {
4213 streamsize __nmemb = static_cast<streamsize>(this->pptr() - this->pbase());
4214 if (__bufptr_->sputn((const char*)this->pbase(), __nmemb) != __nmemb)
4215 return traits_type::eof();
4216 }
4217 else
4218 {
4219 char* __extbe = __extbuf_;
4220 codecvt_base::result __r;
4221 do
4222 {
4223 const char_type* __e;
4224 __r = __cv_->out(__st_, this->pbase(), this->pptr(), __e,
4225 __extbuf_, __extbuf_ + __ebs_, __extbe);
4226 if (__e == this->pbase())
4227 return traits_type::eof();
4228 if (__r == codecvt_base::noconv)
4229 {
4230 streamsize __nmemb = static_cast<size_t>(this->pptr() - this->pbase());
4231 if (__bufptr_->sputn((const char*)this->pbase(), __nmemb) != __nmemb)
4232 return traits_type::eof();
4233 }
4234 else if (__r == codecvt_base::ok || __r == codecvt_base::partial)
4235 {
4236 streamsize __nmemb = static_cast<size_t>(__extbe - __extbuf_);
4237 if (__bufptr_->sputn(__extbuf_, __nmemb) != __nmemb)
4238 return traits_type::eof();
4239 if (__r == codecvt_base::partial)
4240 {
4241 this->setp((char_type*)__e, this->pptr());
4242 this->pbump(this->epptr() - this->pbase());
4243 }
4244 }
4245 else
4246 return traits_type::eof();
4247 } while (__r == codecvt_base::partial);
4248 }
4249 this->setp(__pb_save, __epb_save);
4250 }
4251 return traits_type::not_eof(__c);
4252}
4253
4254template <class _Codecvt, class _Elem, class _Tr>
4255basic_streambuf<_Elem, _Tr>*
4256wbuffer_convert<_Codecvt, _Elem, _Tr>::setbuf(char_type* __s, streamsize __n)
4257{
4258 this->setg(0, 0, 0);
4259 this->setp(0, 0);
4260 if (__owns_eb_)
4261 delete [] __extbuf_;
4262 if (__owns_ib_)
4263 delete [] __intbuf_;
4264 __ebs_ = __n;
4265 if (__ebs_ > sizeof(__extbuf_min_))
4266 {
4267 if (__always_noconv_ && __s)
4268 {
4269 __extbuf_ = (char*)__s;
4270 __owns_eb_ = false;
4271 }
4272 else
4273 {
4274 __extbuf_ = new char[__ebs_];
4275 __owns_eb_ = true;
4276 }
4277 }
4278 else
4279 {
4280 __extbuf_ = __extbuf_min_;
4281 __ebs_ = sizeof(__extbuf_min_);
4282 __owns_eb_ = false;
4283 }
4284 if (!__always_noconv_)
4285 {
4286 __ibs_ = max<streamsize>(__n, sizeof(__extbuf_min_));
4287 if (__s && __ibs_ >= sizeof(__extbuf_min_))
4288 {
4289 __intbuf_ = __s;
4290 __owns_ib_ = false;
4291 }
4292 else
4293 {
4294 __intbuf_ = new char_type[__ibs_];
4295 __owns_ib_ = true;
4296 }
4297 }
4298 else
4299 {
4300 __ibs_ = 0;
4301 __intbuf_ = 0;
4302 __owns_ib_ = false;
4303 }
4304 return this;
4305}
4306
4307template <class _Codecvt, class _Elem, class _Tr>
4308typename wbuffer_convert<_Codecvt, _Elem, _Tr>::pos_type
4309wbuffer_convert<_Codecvt, _Elem, _Tr>::seekoff(off_type __off, ios_base::seekdir __way,
4310 ios_base::openmode __om)
4311{
4312 int __width = __cv_->encoding();
4313 if (__cv_ == 0 || __bufptr_ == 0 || (__width <= 0 && __off != 0) || sync())
4314 return pos_type(off_type(-1));
4315 // __width > 0 || __off == 0
4316 switch (__way)
4317 {
4318 case ios_base::beg:
4319 break;
4320 case ios_base::cur:
4321 break;
4322 case ios_base::end:
4323 break;
4324 default:
4325 return pos_type(off_type(-1));
4326 }
4327 pos_type __r = __bufptr_->pubseekoff(__width * __off, __way, __om);
4328 __r.state(__st_);
4329 return __r;
4330}
4331
4332template <class _Codecvt, class _Elem, class _Tr>
4333typename wbuffer_convert<_Codecvt, _Elem, _Tr>::pos_type
4334wbuffer_convert<_Codecvt, _Elem, _Tr>::seekpos(pos_type __sp, ios_base::openmode __wch)
4335{
4336 if (__cv_ == 0 || __bufptr_ == 0 || sync())
4337 return pos_type(off_type(-1));
4338 if (__bufptr_->pubseekpos(__sp, __wch) == pos_type(off_type(-1)))
4339 return pos_type(off_type(-1));
4340 return __sp;
4341}
4342
4343template <class _Codecvt, class _Elem, class _Tr>
4344int
4345wbuffer_convert<_Codecvt, _Elem, _Tr>::sync()
4346{
4347 if (__cv_ == 0 || __bufptr_ == 0)
4348 return 0;
4349 if (__cm_ & ios_base::out)
4350 {
4351 if (this->pptr() != this->pbase())
4352 if (overflow() == traits_type::eof())
4353 return -1;
4354 codecvt_base::result __r;
4355 do
4356 {
4357 char* __extbe;
4358 __r = __cv_->unshift(__st_, __extbuf_, __extbuf_ + __ebs_, __extbe);
4359 streamsize __nmemb = static_cast<streamsize>(__extbe - __extbuf_);
4360 if (__bufptr_->sputn(__extbuf_, __nmemb) != __nmemb)
4361 return -1;
4362 } while (__r == codecvt_base::partial);
4363 if (__r == codecvt_base::error)
4364 return -1;
4365 if (__bufptr_->pubsync())
4366 return -1;
4367 }
4368 else if (__cm_ & ios_base::in)
4369 {
4370 off_type __c;
4371 if (__always_noconv_)
4372 __c = this->egptr() - this->gptr();
4373 else
4374 {
4375 int __width = __cv_->encoding();
4376 __c = __extbufend_ - __extbufnext_;
4377 if (__width > 0)
4378 __c += __width * (this->egptr() - this->gptr());
4379 else
4380 {
4381 if (this->gptr() != this->egptr())
4382 {
4383 reverse(this->gptr(), this->egptr());
4384 codecvt_base::result __r;
4385 const char_type* __e = this->gptr();
4386 char* __extbe;
4387 do
4388 {
4389 __r = __cv_->out(__st_, __e, this->egptr(), __e,
4390 __extbuf_, __extbuf_ + __ebs_, __extbe);
4391 switch (__r)
4392 {
4393 case codecvt_base::noconv:
4394 __c += this->egptr() - this->gptr();
4395 break;
4396 case codecvt_base::ok:
4397 case codecvt_base::partial:
4398 __c += __extbe - __extbuf_;
4399 break;
4400 default:
4401 return -1;
4402 }
4403 } while (__r == codecvt_base::partial);
4404 }
4405 }
4406 }
4407 if (__bufptr_->pubseekoff(-__c, ios_base::cur, __cm_) == pos_type(off_type(-1)))
4408 return -1;
4409 this->setg(0, 0, 0);
4410 __cm_ = 0;
4411 }
4412 return 0;
4413}
4414
4415template <class _Codecvt, class _Elem, class _Tr>
4416bool
4417wbuffer_convert<_Codecvt, _Elem, _Tr>::__read_mode()
4418{
4419 if (!(__cm_ & ios_base::in))
4420 {
4421 this->setp(0, 0);
4422 if (__always_noconv_)
4423 this->setg((char_type*)__extbuf_,
4424 (char_type*)__extbuf_ + __ebs_,
4425 (char_type*)__extbuf_ + __ebs_);
4426 else
4427 this->setg(__intbuf_, __intbuf_ + __ibs_, __intbuf_ + __ibs_);
4428 __cm_ = ios_base::in;
4429 return true;
4430 }
4431 return false;
4432}
4433
4434template <class _Codecvt, class _Elem, class _Tr>
4435void
4436wbuffer_convert<_Codecvt, _Elem, _Tr>::__write_mode()
4437{
4438 if (!(__cm_ & ios_base::out))
4439 {
4440 this->setg(0, 0, 0);
4441 if (__ebs_ > sizeof(__extbuf_min_))
4442 {
4443 if (__always_noconv_)
4444 this->setp((char_type*)__extbuf_,
4445 (char_type*)__extbuf_ + (__ebs_ - 1));
4446 else
4447 this->setp(__intbuf_, __intbuf_ + (__ibs_ - 1));
4448 }
4449 else
4450 this->setp(0, 0);
4451 __cm_ = ios_base::out;
4452 }
4453}
4454
4455template <class _Codecvt, class _Elem, class _Tr>
4456wbuffer_convert<_Codecvt, _Elem, _Tr>*
4457wbuffer_convert<_Codecvt, _Elem, _Tr>::__close()
4458{
4459 wbuffer_convert* __rt = 0;
4460 if (__cv_ != 0 && __bufptr_ != 0)
4461 {
4462 __rt = this;
4463 if ((__cm_ & ios_base::out) && sync())
4464 __rt = 0;
4465 }
4466 return __rt;
Howard Hinnant5d3c1132010-05-31 20:58:54 +00004467}
4468
Howard Hinnant3e519522010-05-11 19:42:16 +00004469_LIBCPP_END_NAMESPACE_STD
4470
4471#endif // _LIBCPP_LOCALE