blob: 3f0fa4d17c001eba6fab84832a7ed27443e48c3b [file] [log] [blame]
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001// -*- C++ -*-
2//===-------------------------- locale ------------------------------------===//
3//
Howard Hinnantf5256e12010-05-11 21:36:01 +00004// The LLVM Compiler Infrastructure
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005//
Howard Hinnantb64f8b02010-11-16 22:09:02 +00006// This file is dual licensed under the MIT and the University of Illinois Open
7// Source Licenses. See LICENSE.TXT for details.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00008//
9//===----------------------------------------------------------------------===//
10
11#ifndef _LIBCPP_LOCALE
12#define _LIBCPP_LOCALE
13
14/*
15 locale synopsis
16
17namespace std
18{
19
20class locale
21{
22public:
23 // types:
24 class facet;
25 class id;
26
27 typedef int category;
28 static const category // values assigned here are for exposition only
29 none = 0x000,
30 collate = 0x010,
31 ctype = 0x020,
32 monetary = 0x040,
33 numeric = 0x080,
34 time = 0x100,
35 messages = 0x200,
36 all = collate | ctype | monetary | numeric | time | messages;
37
38 // construct/copy/destroy:
Howard Hinnantc9834542011-05-31 15:34:58 +000039 locale() noexcept;
40 locale(const locale& other) noexcept;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000041 explicit locale(const char* std_name);
42 explicit locale(const string& std_name);
43 locale(const locale& other, const char* std_name, category);
44 locale(const locale& other, const string& std_name, category);
45 template <class Facet> locale(const locale& other, Facet* f);
46 locale(const locale& other, const locale& one, category);
47
Howard Hinnantc9834542011-05-31 15:34:58 +000048 ~locale(); // not virtual
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000049
Howard Hinnantc9834542011-05-31 15:34:58 +000050 const locale& operator=(const locale& other) noexcept;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000051
52 template <class Facet> locale combine(const locale& other) const;
53
54 // locale operations:
55 basic_string<char> name() const;
56 bool operator==(const locale& other) const;
57 bool operator!=(const locale& other) const;
58 template <class charT, class Traits, class Allocator>
59 bool operator()(const basic_string<charT,Traits,Allocator>& s1,
60 const basic_string<charT,Traits,Allocator>& s2) const;
61
62 // global locale objects:
63 static locale global(const locale&);
64 static const locale& classic();
65};
66
67template <class Facet> const Facet& use_facet(const locale&);
Howard Hinnantc9834542011-05-31 15:34:58 +000068template <class Facet> bool has_facet(const locale&) noexcept;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000069
70// 22.3.3, convenience interfaces:
71template <class charT> bool isspace (charT c, const locale& loc);
72template <class charT> bool isprint (charT c, const locale& loc);
73template <class charT> bool iscntrl (charT c, const locale& loc);
74template <class charT> bool isupper (charT c, const locale& loc);
75template <class charT> bool islower (charT c, const locale& loc);
76template <class charT> bool isalpha (charT c, const locale& loc);
77template <class charT> bool isdigit (charT c, const locale& loc);
78template <class charT> bool ispunct (charT c, const locale& loc);
79template <class charT> bool isxdigit(charT c, const locale& loc);
80template <class charT> bool isalnum (charT c, const locale& loc);
81template <class charT> bool isgraph (charT c, const locale& loc);
82template <class charT> charT toupper(charT c, const locale& loc);
83template <class charT> charT tolower(charT c, const locale& loc);
Howard Hinnantd23b4642010-05-31 20:58:54 +000084
85template<class Codecvt, class Elem = wchar_t,
86 class Wide_alloc = allocator<Elem>,
87 class Byte_alloc = allocator<char>>
88class wstring_convert
89{
90public:
91 typedef basic_string<char, char_traits<char>, Byte_alloc> byte_string;
92 typedef basic_string<Elem, char_traits<Elem>, Wide_alloc> wide_string;
93 typedef typename Codecvt::state_type state_type;
94 typedef typename wide_string::traits_type::int_type int_type;
95
Marshall Clow83179a72013-08-27 20:18:59 +000096 explicit wstring_convert(Codecvt* pcvt = new Codecvt); // explicit in C++14
Howard Hinnantd23b4642010-05-31 20:58:54 +000097 wstring_convert(Codecvt* pcvt, state_type state);
Marshall Clow83179a72013-08-27 20:18:59 +000098 explicit wstring_convert(const byte_string& byte_err, // explicit in C++14
Howard Hinnantd23b4642010-05-31 20:58:54 +000099 const wide_string& wide_err = wide_string());
Marshall Clow83179a72013-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 Hinnantd23b4642010-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 Clow83179a72013-08-27 20:18:59 +0000114 size_t converted() const; // noexcept in C++14
Howard Hinnantd23b4642010-05-31 20:58:54 +0000115 state_type state() const;
116};
117
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000118template <class Codecvt, class Elem = wchar_t, class Tr = char_traits<Elem>>
Howard Hinnantd23b4642010-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 Clow83179a72013-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 Hinnantd23b4642010-05-31 20:58:54 +0000131 streambuf* rdbuf() const;
132 streambuf* rdbuf(streambuf* bytebuf);
133
134 state_type state() const;
135};
Howard Hinnantbc8d3f92010-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 Clowdece7fe2013-03-18 17:45:34 +0000189#ifndef __APPLE__
Howard Hinnantadff4892010-05-24 17:49:41 +0000190#include <cstdarg>
191#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000192#include <cstdlib>
193#include <ctime>
Howard Hinnantef5aa932013-09-17 01:34:47 +0000194#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnant14fa9f92011-09-29 20:33:10 +0000195#include <support/win32/locale_win32.h>
Dan Albert2ef012e2014-04-08 12:03:21 -0700196#elif defined(__ANDROID__)
197#include <support/android/nl_types.h>
Howard Hinnante9df0a52013-08-01 18:17:34 +0000198#else // _LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000199#include <nl_types.h>
Howard Hinnante9df0a52013-08-01 18:17:34 +0000200#endif // !_LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000201
Marshall Clowdece7fe2013-03-18 17:45:34 +0000202#ifdef __APPLE__
Howard Hinnant537b2fa2012-11-14 21:17:15 +0000203#include <Availability.h>
204#endif
205
Howard Hinnant66c6f972011-11-29 16:45:27 +0000206#include <__undef_min_max>
207
Howard Hinnant08e17472011-10-17 20:05:10 +0000208#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000209#pragma GCC system_header
Howard Hinnant08e17472011-10-17 20:05:10 +0000210#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000211
212_LIBCPP_BEGIN_NAMESPACE_STD
213
Marshall Clow53e27632013-03-18 19:34:07 +0000214#if defined(__APPLE__) || defined(__FreeBSD__)
Howard Hinnant2ea1ca92011-09-28 21:05:01 +0000215# define _LIBCPP_GET_C_LOCALE 0
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +0000216#elif defined(__NetBSD__)
217# define _LIBCPP_GET_C_LOCALE LC_C_LOCALE
Howard Hinnant2ea1ca92011-09-28 21:05:01 +0000218#else
219# define _LIBCPP_GET_C_LOCALE __cloc()
Howard Hinnant866569b2011-09-28 23:39:33 +0000220 // Get the C locale object
Howard Hinnant0f678bd2013-08-12 18:38:34 +0000221 _LIBCPP_FUNC_VIS locale_t __cloc();
Howard Hinnant866569b2011-09-28 23:39:33 +0000222#define __cloc_defined
Howard Hinnant2ea1ca92011-09-28 21:05:01 +0000223#endif
224
Sean Huntf3907e62011-07-15 05:40:33 +0000225typedef _VSTD::remove_pointer<locale_t>::type __locale_struct;
226typedef _VSTD::unique_ptr<__locale_struct, decltype(&freelocale)> __locale_unique_ptr;
David Chisnall8fa14e92012-02-29 13:00:07 +0000227#ifndef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +0000228typedef _VSTD::unique_ptr<__locale_struct, decltype(&uselocale)> __locale_raii;
David Chisnall8fa14e92012-02-29 13:00:07 +0000229#endif
Sean Huntf3907e62011-07-15 05:40:33 +0000230
Howard Hinnantadff4892010-05-24 17:49:41 +0000231// OSX has nice foo_l() functions that let you turn off use of the global
232// locale. Linux, not so much. The following functions avoid the locale when
233// that's possible and otherwise do the wrong thing. FIXME.
Marshall Clow2ccffef2013-11-19 18:05:03 +0000234#if defined(__linux__) || defined(__EMSCRIPTEN__) || defined(_AIX)
Sean Huntf3907e62011-07-15 05:40:33 +0000235
236#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
237decltype(MB_CUR_MAX_L(_VSTD::declval<locale_t>()))
Howard Hinnant82894812010-09-22 16:48:34 +0000238inline _LIBCPP_INLINE_VISIBILITY
Sean Huntf3907e62011-07-15 05:40:33 +0000239__mb_cur_max_l(locale_t __l)
Howard Hinnantadff4892010-05-24 17:49:41 +0000240{
Sean Huntf3907e62011-07-15 05:40:33 +0000241 return MB_CUR_MAX_L(__l);
242}
243#else // _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant1e564242013-10-04 22:09:00 +0000244inline _LIBCPP_ALWAYS_INLINE
Sean Huntf3907e62011-07-15 05:40:33 +0000245decltype(MB_CUR_MAX) __mb_cur_max_l(locale_t __l)
246{
247 __locale_raii __current(uselocale(__l), uselocale);
248 return MB_CUR_MAX;
249}
250#endif // _LIBCPP_LOCALE__L_EXTENSIONS
251
Howard Hinnant1e564242013-10-04 22:09:00 +0000252inline _LIBCPP_ALWAYS_INLINE
Sean Huntf3907e62011-07-15 05:40:33 +0000253wint_t __btowc_l(int __c, locale_t __l)
254{
Howard Hinnant866569b2011-09-28 23:39:33 +0000255#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +0000256 return btowc_l(__c, __l);
257#else
258 __locale_raii __current(uselocale(__l), uselocale);
259 return btowc(__c);
260#endif
Sean Huntc97da3a2011-07-13 06:40:50 +0000261}
Howard Hinnant8d756322011-07-13 15:48:16 +0000262
Howard Hinnant1e564242013-10-04 22:09:00 +0000263inline _LIBCPP_ALWAYS_INLINE
Sean Huntf3907e62011-07-15 05:40:33 +0000264int __wctob_l(wint_t __c, locale_t __l)
Sean Huntc97da3a2011-07-13 06:40:50 +0000265{
Sean Huntf3907e62011-07-15 05:40:33 +0000266#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
267 return wctob_l(__c, __l);
268#else
269 __locale_raii __current(uselocale(__l), uselocale);
270 return wctob(__c);
271#endif
Sean Huntc97da3a2011-07-13 06:40:50 +0000272}
Sean Huntf3907e62011-07-15 05:40:33 +0000273
Howard Hinnant1e564242013-10-04 22:09:00 +0000274inline _LIBCPP_ALWAYS_INLINE
Sean Huntf3907e62011-07-15 05:40:33 +0000275size_t __wcsnrtombs_l(char *__dest, const wchar_t **__src, size_t __nwc,
276 size_t __len, mbstate_t *__ps, locale_t __l)
277{
278#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
279 return wcsnrtombs_l(__dest, __src, __nwc, __len, __ps, __l);
280#else
281 __locale_raii __current(uselocale(__l), uselocale);
282 return wcsnrtombs(__dest, __src, __nwc, __len, __ps);
283#endif
284}
285
Howard Hinnant1e564242013-10-04 22:09:00 +0000286inline _LIBCPP_ALWAYS_INLINE
Sean Huntf3907e62011-07-15 05:40:33 +0000287size_t __wcrtomb_l(char *__s, wchar_t __wc, mbstate_t *__ps, locale_t __l)
288{
289#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
290 return wcrtomb_l(__s, __wc, __ps, __l);
291#else
292 __locale_raii __current(uselocale(__l), uselocale);
293 return wcrtomb(__s, __wc, __ps);
294#endif
295}
296
Howard Hinnant1e564242013-10-04 22:09:00 +0000297inline _LIBCPP_ALWAYS_INLINE
Sean Huntf3907e62011-07-15 05:40:33 +0000298size_t __mbsnrtowcs_l(wchar_t * __dest, const char **__src, size_t __nms,
299 size_t __len, mbstate_t *__ps, locale_t __l)
300{
301#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
David Chisnallc512df12011-09-21 08:39:44 +0000302 return mbsnrtowcs_l(__dest, __src, __nms, __len, __ps, __l);
Sean Huntf3907e62011-07-15 05:40:33 +0000303#else
304 __locale_raii __current(uselocale(__l), uselocale);
305 return mbsnrtowcs(__dest, __src, __nms, __len, __ps);
306#endif
307}
308
Howard Hinnant1e564242013-10-04 22:09:00 +0000309inline _LIBCPP_ALWAYS_INLINE
Sean Huntf3907e62011-07-15 05:40:33 +0000310size_t __mbrtowc_l(wchar_t *__pwc, const char *__s, size_t __n,
311 mbstate_t *__ps, locale_t __l)
312{
313#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
314 return mbrtowc_l(__pwc, __s, __n, __ps, __l);
315#else
316 __locale_raii __current(uselocale(__l), uselocale);
317 return mbrtowc(__pwc, __s, __n, __ps);
318#endif
319}
320
Howard Hinnant1e564242013-10-04 22:09:00 +0000321inline _LIBCPP_ALWAYS_INLINE
Sean Huntf3907e62011-07-15 05:40:33 +0000322int __mbtowc_l(wchar_t *__pwc, const char *__pmb, size_t __max, locale_t __l)
323{
324#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
David Chisnallc512df12011-09-21 08:39:44 +0000325 return mbtowc_l(__pwc, __pmb, __max, __l);
Sean Huntf3907e62011-07-15 05:40:33 +0000326#else
327 __locale_raii __current(uselocale(__l), uselocale);
328 return mbtowc(__pwc, __pmb, __max);
329#endif
330}
331
Howard Hinnant1e564242013-10-04 22:09:00 +0000332inline _LIBCPP_ALWAYS_INLINE
Sean Huntf3907e62011-07-15 05:40:33 +0000333size_t __mbrlen_l(const char *__s, size_t __n, mbstate_t *__ps, locale_t __l)
334{
335#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
336 return mbrlen_l(__s, __n, __ps, __l);
337#else
338 __locale_raii __current(uselocale(__l), uselocale);
339 return mbrlen(__s, __n, __ps);
340#endif
341}
342
Howard Hinnant1e564242013-10-04 22:09:00 +0000343inline _LIBCPP_ALWAYS_INLINE
Sean Huntf3907e62011-07-15 05:40:33 +0000344lconv *__localeconv_l(locale_t __l)
345{
346#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
347 return localeconv_l(__l);
348#else
349 __locale_raii __current(uselocale(__l), uselocale);
350 return localeconv();
351#endif
352}
353
Howard Hinnant1e564242013-10-04 22:09:00 +0000354inline _LIBCPP_ALWAYS_INLINE
Sean Huntf3907e62011-07-15 05:40:33 +0000355size_t __mbsrtowcs_l(wchar_t *__dest, const char **__src, size_t __len,
356 mbstate_t *__ps, locale_t __l)
357{
358#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
359 return mbsrtowcs_l(__dest, __src, __len, __ps, __l);
360#else
361 __locale_raii __current(uselocale(__l), uselocale);
362 return mbsrtowcs(__dest, __src, __len, __ps);
363#endif
364}
365
Chandler Carruthed9f69d2012-12-31 06:09:54 +0000366inline
Sean Huntf3907e62011-07-15 05:40:33 +0000367int __snprintf_l(char *__s, size_t __n, locale_t __l, const char *__format, ...) {
368 va_list __va;
369 va_start(__va, __format);
370#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
371 int __res = vsnprintf_l(__s, __n, __l, __format, __va);
372#else
373 __locale_raii __current(uselocale(__l), uselocale);
374 int __res = vsnprintf(__s, __n, __format, __va);
375#endif
376 va_end(__va);
377 return __res;
378}
379
Chandler Carruthed9f69d2012-12-31 06:09:54 +0000380inline
Sean Huntf3907e62011-07-15 05:40:33 +0000381int __asprintf_l(char **__s, locale_t __l, const char *__format, ...) {
382 va_list __va;
383 va_start(__va, __format);
384#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
385 int __res = vasprintf_l(__s, __l, __format, __va);
386#else
387 __locale_raii __current(uselocale(__l), uselocale);
388 int __res = vasprintf(__s, __format, __va);
389#endif
390 va_end(__va);
391 return __res;
392}
393
Chandler Carruthed9f69d2012-12-31 06:09:54 +0000394inline
Sean Huntf3907e62011-07-15 05:40:33 +0000395int __sscanf_l(const char *__s, locale_t __l, const char *__format, ...) {
396 va_list __va;
397 va_start(__va, __format);
398#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
399 int __res = vsscanf_l(__s, __l, __format, __va);
400#else
401 __locale_raii __current(uselocale(__l), uselocale);
402 int __res = vsscanf(__s, __format, __va);
403#endif
404 va_end(__va);
405 return __res;
406}
407
Howard Hinnant866569b2011-09-28 23:39:33 +0000408#endif // __linux__
Howard Hinnantadff4892010-05-24 17:49:41 +0000409
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000410// __scan_keyword
411// Scans [__b, __e) until a match is found in the basic_strings range
412// [__kb, __ke) or until it can be shown that there is no match in [__kb, __ke).
413// __b will be incremented (visibly), consuming CharT until a match is found
414// or proved to not exist. A keyword may be "", in which will match anything.
415// If one keyword is a prefix of another, and the next CharT in the input
416// might match another keyword, the algorithm will attempt to find the longest
417// matching keyword. If the longer matching keyword ends up not matching, then
418// no keyword match is found. If no keyword match is found, __ke is returned
419// and failbit is set in __err.
420// Else an iterator pointing to the matching keyword is found. If more than
421// one keyword matches, an iterator to the first matching keyword is returned.
422// If on exit __b == __e, eofbit is set in __err. If __case_senstive is false,
423// __ct is used to force to lower case before comparing characters.
424// Examples:
425// Keywords: "a", "abb"
426// If the input is "a", the first keyword matches and eofbit is set.
427// If the input is "abc", no match is found and "ab" are consumed.
428template <class _InputIterator, class _ForwardIterator, class _Ctype>
429_LIBCPP_HIDDEN
430_ForwardIterator
431__scan_keyword(_InputIterator& __b, _InputIterator __e,
432 _ForwardIterator __kb, _ForwardIterator __ke,
433 const _Ctype& __ct, ios_base::iostate& __err,
434 bool __case_sensitive = true)
435{
436 typedef typename iterator_traits<_InputIterator>::value_type _CharT;
Howard Hinnantec3773c2011-12-01 20:21:04 +0000437 size_t __nkw = static_cast<size_t>(_VSTD::distance(__kb, __ke));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000438 const unsigned char __doesnt_match = '\0';
439 const unsigned char __might_match = '\1';
440 const unsigned char __does_match = '\2';
441 unsigned char __statbuf[100];
442 unsigned char* __status = __statbuf;
443 unique_ptr<unsigned char, void(*)(void*)> __stat_hold(0, free);
444 if (__nkw > sizeof(__statbuf))
445 {
446 __status = (unsigned char*)malloc(__nkw);
447 if (__status == 0)
448 __throw_bad_alloc();
449 __stat_hold.reset(__status);
450 }
451 size_t __n_might_match = __nkw; // At this point, any keyword might match
452 size_t __n_does_match = 0; // but none of them definitely do
453 // Initialize all statuses to __might_match, except for "" keywords are __does_match
454 unsigned char* __st = __status;
455 for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, ++__st)
456 {
457 if (!__ky->empty())
458 *__st = __might_match;
459 else
460 {
461 *__st = __does_match;
462 --__n_might_match;
463 ++__n_does_match;
464 }
465 }
466 // While there might be a match, test keywords against the next CharT
467 for (size_t __indx = 0; __b != __e && __n_might_match > 0; ++__indx)
468 {
469 // Peek at the next CharT but don't consume it
470 _CharT __c = *__b;
471 if (!__case_sensitive)
472 __c = __ct.toupper(__c);
473 bool __consume = false;
474 // For each keyword which might match, see if the __indx character is __c
475 // If a match if found, consume __c
476 // If a match is found, and that is the last character in the keyword,
477 // then that keyword matches.
478 // If the keyword doesn't match this character, then change the keyword
479 // to doesn't match
480 __st = __status;
481 for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, ++__st)
482 {
483 if (*__st == __might_match)
484 {
485 _CharT __kc = (*__ky)[__indx];
486 if (!__case_sensitive)
487 __kc = __ct.toupper(__kc);
488 if (__c == __kc)
489 {
490 __consume = true;
491 if (__ky->size() == __indx+1)
492 {
493 *__st = __does_match;
494 --__n_might_match;
495 ++__n_does_match;
496 }
497 }
498 else
499 {
500 *__st = __doesnt_match;
501 --__n_might_match;
502 }
503 }
504 }
505 // consume if we matched a character
506 if (__consume)
507 {
508 ++__b;
509 // If we consumed a character and there might be a matched keyword that
510 // was marked matched on a previous iteration, then such keywords
511 // which are now marked as not matching.
512 if (__n_might_match + __n_does_match > 1)
513 {
514 __st = __status;
515 for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, ++__st)
516 {
517 if (*__st == __does_match && __ky->size() != __indx+1)
518 {
519 *__st = __doesnt_match;
520 --__n_does_match;
521 }
522 }
523 }
524 }
525 }
526 // We've exited the loop because we hit eof and/or we have no more "might matches".
527 if (__b == __e)
528 __err |= ios_base::eofbit;
529 // Return the first matching result
530 for (__st = __status; __kb != __ke; ++__kb, ++__st)
531 if (*__st == __does_match)
532 break;
533 if (__kb == __ke)
534 __err |= ios_base::failbit;
535 return __kb;
536}
537
Howard Hinnant0f678bd2013-08-12 18:38:34 +0000538struct _LIBCPP_TYPE_VIS __num_get_base
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000539{
540 static const int __num_get_buf_sz = 40;
541
542 static int __get_base(ios_base&);
543 static const char __src[33];
544};
545
Howard Hinnant0f678bd2013-08-12 18:38:34 +0000546_LIBCPP_FUNC_VIS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000547void __check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
548 ios_base::iostate& __err);
549
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000550template <class _CharT>
551struct __num_get
552 : protected __num_get_base
553{
554 static string __stage2_int_prep(ios_base& __iob, _CharT* __atoms, _CharT& __thousands_sep);
555 static string __stage2_float_prep(ios_base& __iob, _CharT* __atoms, _CharT& __decimal_point,
556 _CharT& __thousands_sep);
557 static int __stage2_int_loop(_CharT __ct, int __base, char* __a, char*& __a_end,
558 unsigned& __dc, _CharT __thousands_sep, const string& __grouping,
559 unsigned* __g, unsigned*& __g_end, _CharT* __atoms);
560 static int __stage2_float_loop(_CharT __ct, bool& __in_units, char& __exp,
561 char* __a, char*& __a_end,
562 _CharT __decimal_point, _CharT __thousands_sep,
563 const string& __grouping, unsigned* __g,
564 unsigned*& __g_end, unsigned& __dc, _CharT* __atoms);
565};
566
567template <class _CharT>
568string
569__num_get<_CharT>::__stage2_int_prep(ios_base& __iob, _CharT* __atoms, _CharT& __thousands_sep)
570{
571 locale __loc = __iob.getloc();
572 use_facet<ctype<_CharT> >(__loc).widen(__src, __src + 26, __atoms);
573 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
574 __thousands_sep = __np.thousands_sep();
575 return __np.grouping();
576}
577
578template <class _CharT>
579string
580__num_get<_CharT>::__stage2_float_prep(ios_base& __iob, _CharT* __atoms, _CharT& __decimal_point,
581 _CharT& __thousands_sep)
582{
583 locale __loc = __iob.getloc();
584 use_facet<ctype<_CharT> >(__loc).widen(__src, __src + 32, __atoms);
585 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
586 __decimal_point = __np.decimal_point();
587 __thousands_sep = __np.thousands_sep();
588 return __np.grouping();
589}
590
591template <class _CharT>
592int
593__num_get<_CharT>::__stage2_int_loop(_CharT __ct, int __base, char* __a, char*& __a_end,
594 unsigned& __dc, _CharT __thousands_sep, const string& __grouping,
595 unsigned* __g, unsigned*& __g_end, _CharT* __atoms)
596{
Howard Hinnant80586722011-03-09 01:03:19 +0000597 if (__a_end == __a && (__ct == __atoms[24] || __ct == __atoms[25]))
598 {
599 *__a_end++ = __ct == __atoms[24] ? '+' : '-';
600 __dc = 0;
601 return 0;
602 }
Howard Hinnantec3773c2011-12-01 20:21:04 +0000603 if (__grouping.size() != 0 && __ct == __thousands_sep)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000604 {
605 if (__g_end-__g < __num_get_buf_sz)
606 {
607 *__g_end++ = __dc;
608 __dc = 0;
609 }
610 return 0;
611 }
612 ptrdiff_t __f = find(__atoms, __atoms + 26, __ct) - __atoms;
Howard Hinnant80586722011-03-09 01:03:19 +0000613 if (__f >= 24)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000614 return -1;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000615 switch (__base)
616 {
617 case 8:
618 case 10:
619 if (__f >= __base)
Howard Hinnant80586722011-03-09 01:03:19 +0000620 return -1;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000621 break;
Howard Hinnant80586722011-03-09 01:03:19 +0000622 case 16:
623 if (__f < 22)
624 break;
625 if (__a_end != __a && __a_end - __a <= 2 && __a_end[-1] == '0')
626 {
627 __dc = 0;
628 *__a_end++ = __src[__f];
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000629 return 0;
Howard Hinnant80586722011-03-09 01:03:19 +0000630 }
631 return -1;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000632 }
Howard Hinnantae57a1a2013-04-15 20:40:06 +0000633 *__a_end++ = __src[__f];
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000634 ++__dc;
635 return 0;
636}
637
638template <class _CharT>
639int
640__num_get<_CharT>::__stage2_float_loop(_CharT __ct, bool& __in_units, char& __exp, char* __a, char*& __a_end,
641 _CharT __decimal_point, _CharT __thousands_sep, const string& __grouping,
642 unsigned* __g, unsigned*& __g_end, unsigned& __dc, _CharT* __atoms)
643{
644 if (__ct == __decimal_point)
645 {
646 if (!__in_units)
647 return -1;
648 __in_units = false;
649 *__a_end++ = '.';
650 if (__grouping.size() != 0 && __g_end-__g < __num_get_buf_sz)
651 *__g_end++ = __dc;
652 return 0;
653 }
654 if (__ct == __thousands_sep && __grouping.size() != 0)
655 {
656 if (!__in_units)
657 return -1;
658 if (__g_end-__g < __num_get_buf_sz)
659 {
660 *__g_end++ = __dc;
661 __dc = 0;
662 }
663 return 0;
664 }
665 ptrdiff_t __f = find(__atoms, __atoms + 32, __ct) - __atoms;
666 if (__f >= 32)
667 return -1;
668 char __x = __src[__f];
Howard Hinnantb04ad412012-02-15 19:19:37 +0000669 if (__x == '-' || __x == '+')
670 {
Howard Hinnant6319f142013-03-08 19:06:24 +0000671 if (__a_end == __a || (__a_end[-1] & 0x5F) == (__exp & 0x7F))
Howard Hinnantb04ad412012-02-15 19:19:37 +0000672 {
673 *__a_end++ = __x;
674 return 0;
675 }
676 return -1;
677 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000678 if (__x == 'x' || __x == 'X')
679 __exp = 'P';
Howard Hinnant6319f142013-03-08 19:06:24 +0000680 else if ((__x & 0x5F) == __exp)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000681 {
Howard Hinnant6319f142013-03-08 19:06:24 +0000682 __exp |= 0x80;
683 if (__in_units)
684 {
685 __in_units = false;
686 if (__grouping.size() != 0 && __g_end-__g < __num_get_buf_sz)
687 *__g_end++ = __dc;
688 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000689 }
Howard Hinnantae57a1a2013-04-15 20:40:06 +0000690 *__a_end++ = __x;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000691 if (__f >= 22)
692 return 0;
693 ++__dc;
694 return 0;
695}
696
Howard Hinnant499cea12013-08-23 17:37:05 +0000697_LIBCPP_EXTERN_TEMPLATE2(struct _LIBCPP_TYPE_VIS __num_get<char>)
698_LIBCPP_EXTERN_TEMPLATE2(struct _LIBCPP_TYPE_VIS __num_get<wchar_t>)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000699
700template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnant0f678bd2013-08-12 18:38:34 +0000701class _LIBCPP_TYPE_VIS_ONLY num_get
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000702 : public locale::facet,
703 private __num_get<_CharT>
704{
705public:
706 typedef _CharT char_type;
707 typedef _InputIterator iter_type;
708
709 _LIBCPP_ALWAYS_INLINE
710 explicit num_get(size_t __refs = 0)
711 : locale::facet(__refs) {}
712
713 _LIBCPP_ALWAYS_INLINE
714 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
715 ios_base::iostate& __err, bool& __v) const
716 {
717 return do_get(__b, __e, __iob, __err, __v);
718 }
719
720 _LIBCPP_ALWAYS_INLINE
721 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
722 ios_base::iostate& __err, long& __v) const
723 {
724 return do_get(__b, __e, __iob, __err, __v);
725 }
726
727 _LIBCPP_ALWAYS_INLINE
728 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
729 ios_base::iostate& __err, long long& __v) const
730 {
731 return do_get(__b, __e, __iob, __err, __v);
732 }
733
734 _LIBCPP_ALWAYS_INLINE
735 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
736 ios_base::iostate& __err, unsigned short& __v) const
737 {
738 return do_get(__b, __e, __iob, __err, __v);
739 }
740
741 _LIBCPP_ALWAYS_INLINE
742 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
743 ios_base::iostate& __err, unsigned int& __v) const
744 {
745 return do_get(__b, __e, __iob, __err, __v);
746 }
747
748 _LIBCPP_ALWAYS_INLINE
749 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
750 ios_base::iostate& __err, unsigned long& __v) const
751 {
752 return do_get(__b, __e, __iob, __err, __v);
753 }
754
755 _LIBCPP_ALWAYS_INLINE
756 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
757 ios_base::iostate& __err, unsigned long long& __v) const
758 {
759 return do_get(__b, __e, __iob, __err, __v);
760 }
761
762 _LIBCPP_ALWAYS_INLINE
763 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
764 ios_base::iostate& __err, float& __v) const
765 {
766 return do_get(__b, __e, __iob, __err, __v);
767 }
768
769 _LIBCPP_ALWAYS_INLINE
770 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
771 ios_base::iostate& __err, double& __v) const
772 {
773 return do_get(__b, __e, __iob, __err, __v);
774 }
775
776 _LIBCPP_ALWAYS_INLINE
777 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
778 ios_base::iostate& __err, long double& __v) const
779 {
780 return do_get(__b, __e, __iob, __err, __v);
781 }
782
783 _LIBCPP_ALWAYS_INLINE
784 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
785 ios_base::iostate& __err, void*& __v) const
786 {
787 return do_get(__b, __e, __iob, __err, __v);
788 }
789
790 static locale::id id;
791
792protected:
Howard Hinnant82894812010-09-22 16:48:34 +0000793 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000794 ~num_get() {}
795
Marshall Clow5ffe5912013-11-05 14:28:52 +0000796 template <class _Fp>
797 iter_type __do_get_floating_point
798 (iter_type __b, iter_type __e, ios_base& __iob,
799 ios_base::iostate& __err, _Fp& __v) const;
Marshall Clowfe2a5612013-11-07 01:00:50 +0000800
801 template <class _Signed>
802 iter_type __do_get_signed
803 (iter_type __b, iter_type __e, ios_base& __iob,
804 ios_base::iostate& __err, _Signed& __v) const;
805
806 template <class _Unsigned>
807 iter_type __do_get_unsigned
808 (iter_type __b, iter_type __e, ios_base& __iob,
809 ios_base::iostate& __err, _Unsigned& __v) const;
810
811
812 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
813 ios_base::iostate& __err, bool& __v) const;
814
815 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
816 ios_base::iostate& __err, long& __v) const
817 { return this->__do_get_signed ( __b, __e, __iob, __err, __v ); }
818
819 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
820 ios_base::iostate& __err, long 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, unsigned short& __v) const
825 { return this->__do_get_unsigned ( __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 int& __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 long& __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 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, float& __v) const
841 { return this->__do_get_floating_point ( __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, double& __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, long 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, void*& __v) const;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000853};
854
855template <class _CharT, class _InputIterator>
856locale::id
857num_get<_CharT, _InputIterator>::id;
858
859template <class _Tp>
860_Tp
861__num_get_signed_integral(const char* __a, const char* __a_end,
862 ios_base::iostate& __err, int __base)
863{
864 if (__a != __a_end)
865 {
Howard Hinnant54e2fff2013-01-22 17:26:08 +0000866 typename remove_reference<decltype(errno)>::type __save_errno = errno;
Howard Hinnante7c8da62011-02-25 19:52:41 +0000867 errno = 0;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000868 char *__p2;
Howard Hinnant2ea1ca92011-09-28 21:05:01 +0000869 long long __ll = strtoll_l(__a, &__p2, __base, _LIBCPP_GET_C_LOCALE);
Howard Hinnant54e2fff2013-01-22 17:26:08 +0000870 typename remove_reference<decltype(errno)>::type __current_errno = errno;
Howard Hinnante7c8da62011-02-25 19:52:41 +0000871 if (__current_errno == 0)
872 errno = __save_errno;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000873 if (__p2 != __a_end)
874 {
875 __err = ios_base::failbit;
876 return 0;
877 }
Howard Hinnante7c8da62011-02-25 19:52:41 +0000878 else if (__current_errno == ERANGE ||
879 __ll < numeric_limits<_Tp>::min() ||
880 numeric_limits<_Tp>::max() < __ll)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000881 {
882 __err = ios_base::failbit;
Howard Hinnante7c8da62011-02-25 19:52:41 +0000883 if (__ll > 0)
884 return numeric_limits<_Tp>::max();
885 else
886 return numeric_limits<_Tp>::min();
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000887 }
888 return static_cast<_Tp>(__ll);
889 }
890 __err = ios_base::failbit;
891 return 0;
892}
893
894template <class _Tp>
895_Tp
896__num_get_unsigned_integral(const char* __a, const char* __a_end,
897 ios_base::iostate& __err, int __base)
898{
899 if (__a != __a_end)
900 {
Howard Hinnante7c8da62011-02-25 19:52:41 +0000901 if (*__a == '-')
902 {
903 __err = ios_base::failbit;
904 return 0;
905 }
Howard Hinnant54e2fff2013-01-22 17:26:08 +0000906 typename remove_reference<decltype(errno)>::type __save_errno = errno;
Howard Hinnante7c8da62011-02-25 19:52:41 +0000907 errno = 0;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000908 char *__p2;
Howard Hinnant2ea1ca92011-09-28 21:05:01 +0000909 unsigned long long __ll = strtoull_l(__a, &__p2, __base, _LIBCPP_GET_C_LOCALE);
Howard Hinnant54e2fff2013-01-22 17:26:08 +0000910 typename remove_reference<decltype(errno)>::type __current_errno = errno;
Howard Hinnante7c8da62011-02-25 19:52:41 +0000911 if (__current_errno == 0)
912 errno = __save_errno;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000913 if (__p2 != __a_end)
914 {
915 __err = ios_base::failbit;
916 return 0;
917 }
Howard Hinnante7c8da62011-02-25 19:52:41 +0000918 else if (__current_errno == ERANGE ||
919 numeric_limits<_Tp>::max() < __ll)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000920 {
921 __err = ios_base::failbit;
922 return numeric_limits<_Tp>::max();
923 }
924 return static_cast<_Tp>(__ll);
925 }
926 __err = ios_base::failbit;
927 return 0;
928}
929
930template <class _Tp>
931_Tp
932__num_get_float(const char* __a, const char* __a_end, ios_base::iostate& __err)
933{
934 if (__a != __a_end)
935 {
Howard Hinnant4f671002013-04-13 18:19:25 +0000936 typename remove_reference<decltype(errno)>::type __save_errno = errno;
937 errno = 0;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000938 char *__p2;
Howard Hinnant2ea1ca92011-09-28 21:05:01 +0000939 long double __ld = strtold_l(__a, &__p2, _LIBCPP_GET_C_LOCALE);
Howard Hinnant4f671002013-04-13 18:19:25 +0000940 typename remove_reference<decltype(errno)>::type __current_errno = errno;
941 if (__current_errno == 0)
942 errno = __save_errno;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000943 if (__p2 != __a_end)
944 {
945 __err = ios_base::failbit;
946 return 0;
947 }
Howard Hinnant4f671002013-04-13 18:19:25 +0000948 else if (__current_errno == ERANGE)
949 __err = ios_base::failbit;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000950 return static_cast<_Tp>(__ld);
951 }
952 __err = ios_base::failbit;
953 return 0;
954}
955
956template <class _CharT, class _InputIterator>
957_InputIterator
958num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
959 ios_base& __iob,
960 ios_base::iostate& __err,
961 bool& __v) const
962{
963 if ((__iob.flags() & ios_base::boolalpha) == 0)
964 {
965 long __lv = -1;
966 __b = do_get(__b, __e, __iob, __err, __lv);
967 switch (__lv)
968 {
969 case 0:
970 __v = false;
971 break;
972 case 1:
973 __v = true;
974 break;
975 default:
976 __v = true;
977 __err = ios_base::failbit;
978 break;
979 }
980 return __b;
981 }
982 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__iob.getloc());
983 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__iob.getloc());
984 typedef typename numpunct<_CharT>::string_type string_type;
985 const string_type __names[2] = {__np.truename(), __np.falsename()};
986 const string_type* __i = __scan_keyword(__b, __e, __names, __names+2,
987 __ct, __err);
988 __v = __i == __names;
989 return __b;
990}
991
Marshall Clowfe2a5612013-11-07 01:00:50 +0000992// signed
993
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000994template <class _CharT, class _InputIterator>
Marshall Clowfe2a5612013-11-07 01:00:50 +0000995template <class _Signed>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000996_InputIterator
Marshall Clowfe2a5612013-11-07 01:00:50 +0000997num_get<_CharT, _InputIterator>::__do_get_signed(iter_type __b, iter_type __e,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000998 ios_base& __iob,
999 ios_base::iostate& __err,
Marshall Clowfe2a5612013-11-07 01:00:50 +00001000 _Signed& __v) const
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001001{
1002 // Stage 1
1003 int __base = this->__get_base(__iob);
1004 // Stage 2
1005 char_type __atoms[26];
1006 char_type __thousands_sep;
1007 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
Howard Hinnantae57a1a2013-04-15 20:40:06 +00001008 string __buf;
1009 __buf.resize(__buf.capacity());
1010 char* __a = &__buf[0];
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001011 char* __a_end = __a;
1012 unsigned __g[__num_get_base::__num_get_buf_sz];
1013 unsigned* __g_end = __g;
1014 unsigned __dc = 0;
1015 for (; __b != __e; ++__b)
Howard Hinnantae57a1a2013-04-15 20:40:06 +00001016 {
Joerg Sonnenbergercf7278a2014-02-07 21:14:29 +00001017 if (__a_end == __a + __buf.size())
Howard Hinnantae57a1a2013-04-15 20:40:06 +00001018 {
1019 size_t __tmp = __buf.size();
1020 __buf.resize(2*__buf.size());
1021 __buf.resize(__buf.capacity());
1022 __a = &__buf[0];
1023 __a_end = __a + __tmp;
1024 }
Howard Hinnant324bb032010-08-22 00:02:43 +00001025 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001026 __thousands_sep, __grouping, __g, __g_end,
1027 __atoms))
1028 break;
Howard Hinnantae57a1a2013-04-15 20:40:06 +00001029 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001030 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
1031 *__g_end++ = __dc;
1032 // Stage 3
Marshall Clowfe2a5612013-11-07 01:00:50 +00001033 __v = __num_get_signed_integral<_Signed>(__a, __a_end, __err, __base);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001034 // Digit grouping checked
1035 __check_grouping(__grouping, __g, __g_end, __err);
1036 // EOF checked
1037 if (__b == __e)
1038 __err |= ios_base::eofbit;
1039 return __b;
1040}
1041
Marshall Clowfe2a5612013-11-07 01:00:50 +00001042// unsigned
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001043
1044template <class _CharT, class _InputIterator>
Marshall Clowfe2a5612013-11-07 01:00:50 +00001045template <class _Unsigned>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001046_InputIterator
Marshall Clowfe2a5612013-11-07 01:00:50 +00001047num_get<_CharT, _InputIterator>::__do_get_unsigned(iter_type __b, iter_type __e,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001048 ios_base& __iob,
1049 ios_base::iostate& __err,
Marshall Clowfe2a5612013-11-07 01:00:50 +00001050 _Unsigned& __v) const
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001051{
1052 // Stage 1
1053 int __base = this->__get_base(__iob);
1054 // Stage 2
1055 char_type __atoms[26];
1056 char_type __thousands_sep;
1057 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
Howard Hinnantae57a1a2013-04-15 20:40:06 +00001058 string __buf;
1059 __buf.resize(__buf.capacity());
1060 char* __a = &__buf[0];
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001061 char* __a_end = __a;
1062 unsigned __g[__num_get_base::__num_get_buf_sz];
1063 unsigned* __g_end = __g;
1064 unsigned __dc = 0;
1065 for (; __b != __e; ++__b)
Howard Hinnantae57a1a2013-04-15 20:40:06 +00001066 {
Joerg Sonnenbergercf7278a2014-02-07 21:14:29 +00001067 if (__a_end == __a + __buf.size())
Howard Hinnantae57a1a2013-04-15 20:40:06 +00001068 {
1069 size_t __tmp = __buf.size();
1070 __buf.resize(2*__buf.size());
1071 __buf.resize(__buf.capacity());
1072 __a = &__buf[0];
1073 __a_end = __a + __tmp;
1074 }
Howard Hinnant324bb032010-08-22 00:02:43 +00001075 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001076 __thousands_sep, __grouping, __g, __g_end,
1077 __atoms))
1078 break;
Howard Hinnantae57a1a2013-04-15 20:40:06 +00001079 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001080 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
1081 *__g_end++ = __dc;
1082 // Stage 3
Marshall Clowfe2a5612013-11-07 01:00:50 +00001083 __v = __num_get_unsigned_integral<_Unsigned>(__a, __a_end, __err, __base);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001084 // Digit grouping checked
1085 __check_grouping(__grouping, __g, __g_end, __err);
1086 // EOF checked
1087 if (__b == __e)
1088 __err |= ios_base::eofbit;
1089 return __b;
1090}
1091
Marshall Clow5ffe5912013-11-05 14:28:52 +00001092// floating point
1093
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001094template <class _CharT, class _InputIterator>
Marshall Clow5ffe5912013-11-05 14:28:52 +00001095template <class _Fp>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001096_InputIterator
Marshall Clow5ffe5912013-11-05 14:28:52 +00001097num_get<_CharT, _InputIterator>::__do_get_floating_point(iter_type __b, iter_type __e,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001098 ios_base& __iob,
1099 ios_base::iostate& __err,
Marshall Clow5ffe5912013-11-05 14:28:52 +00001100 _Fp& __v) const
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001101{
1102 // Stage 1, nothing to do
1103 // Stage 2
1104 char_type __atoms[32];
1105 char_type __decimal_point;
1106 char_type __thousands_sep;
Howard Hinnant324bb032010-08-22 00:02:43 +00001107 string __grouping = this->__stage2_float_prep(__iob, __atoms,
1108 __decimal_point,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001109 __thousands_sep);
Howard Hinnantae57a1a2013-04-15 20:40:06 +00001110 string __buf;
1111 __buf.resize(__buf.capacity());
1112 char* __a = &__buf[0];
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001113 char* __a_end = __a;
1114 unsigned __g[__num_get_base::__num_get_buf_sz];
1115 unsigned* __g_end = __g;
1116 unsigned __dc = 0;
1117 bool __in_units = true;
1118 char __exp = 'E';
1119 for (; __b != __e; ++__b)
Howard Hinnantae57a1a2013-04-15 20:40:06 +00001120 {
Joerg Sonnenbergercf7278a2014-02-07 21:14:29 +00001121 if (__a_end == __a + __buf.size())
Howard Hinnantae57a1a2013-04-15 20:40:06 +00001122 {
1123 size_t __tmp = __buf.size();
1124 __buf.resize(2*__buf.size());
1125 __buf.resize(__buf.capacity());
1126 __a = &__buf[0];
1127 __a_end = __a + __tmp;
1128 }
Howard Hinnant324bb032010-08-22 00:02:43 +00001129 if (this->__stage2_float_loop(*__b, __in_units, __exp, __a, __a_end,
1130 __decimal_point, __thousands_sep,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001131 __grouping, __g, __g_end,
1132 __dc, __atoms))
1133 break;
Howard Hinnantae57a1a2013-04-15 20:40:06 +00001134 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001135 if (__grouping.size() != 0 && __in_units && __g_end-__g < __num_get_base::__num_get_buf_sz)
1136 *__g_end++ = __dc;
1137 // Stage 3
Marshall Clow5ffe5912013-11-05 14:28:52 +00001138 __v = __num_get_float<_Fp>(__a, __a_end, __err);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001139 // Digit grouping checked
1140 __check_grouping(__grouping, __g, __g_end, __err);
1141 // EOF checked
1142 if (__b == __e)
1143 __err |= ios_base::eofbit;
1144 return __b;
1145}
1146
1147template <class _CharT, class _InputIterator>
1148_InputIterator
1149num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1150 ios_base& __iob,
1151 ios_base::iostate& __err,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001152 void*& __v) const
1153{
1154 // Stage 1
1155 int __base = 16;
1156 // Stage 2
1157 char_type __atoms[26];
Howard Hinnantec3773c2011-12-01 20:21:04 +00001158 char_type __thousands_sep = 0;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001159 string __grouping;
1160 use_facet<ctype<_CharT> >(__iob.getloc()).widen(__num_get_base::__src,
1161 __num_get_base::__src + 26, __atoms);
Howard Hinnantae57a1a2013-04-15 20:40:06 +00001162 string __buf;
1163 __buf.resize(__buf.capacity());
1164 char* __a = &__buf[0];
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001165 char* __a_end = __a;
1166 unsigned __g[__num_get_base::__num_get_buf_sz];
1167 unsigned* __g_end = __g;
1168 unsigned __dc = 0;
1169 for (; __b != __e; ++__b)
Howard Hinnantae57a1a2013-04-15 20:40:06 +00001170 {
Joerg Sonnenbergercf7278a2014-02-07 21:14:29 +00001171 if (__a_end == __a + __buf.size())
Howard Hinnantae57a1a2013-04-15 20:40:06 +00001172 {
1173 size_t __tmp = __buf.size();
1174 __buf.resize(2*__buf.size());
1175 __buf.resize(__buf.capacity());
1176 __a = &__buf[0];
1177 __a_end = __a + __tmp;
1178 }
Howard Hinnant324bb032010-08-22 00:02:43 +00001179 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
1180 __thousands_sep, __grouping,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001181 __g, __g_end, __atoms))
1182 break;
Howard Hinnantae57a1a2013-04-15 20:40:06 +00001183 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001184 // Stage 3
1185 __a[sizeof(__a)-1] = 0;
Howard Hinnant866569b2011-09-28 23:39:33 +00001186#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001187 if (sscanf_l(__a, _LIBCPP_GET_C_LOCALE, "%p", &__v) != 1)
Sean Huntf3907e62011-07-15 05:40:33 +00001188#else
1189 if (__sscanf_l(__a, __cloc(), "%p", &__v) != 1)
1190#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001191 __err = ios_base::failbit;
1192 // EOF checked
1193 if (__b == __e)
1194 __err |= ios_base::eofbit;
1195 return __b;
1196}
1197
Howard Hinnant499cea12013-08-23 17:37:05 +00001198_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS num_get<char>)
1199_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS num_get<wchar_t>)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001200
Howard Hinnant0f678bd2013-08-12 18:38:34 +00001201struct _LIBCPP_TYPE_VIS __num_put_base
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001202{
1203protected:
1204 static void __format_int(char* __fmt, const char* __len, bool __signd,
1205 ios_base::fmtflags __flags);
1206 static bool __format_float(char* __fmt, const char* __len,
1207 ios_base::fmtflags __flags);
1208 static char* __identify_padding(char* __nb, char* __ne,
1209 const ios_base& __iob);
1210};
1211
1212template <class _CharT>
1213struct __num_put
1214 : protected __num_put_base
1215{
1216 static void __widen_and_group_int(char* __nb, char* __np, char* __ne,
1217 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1218 const locale& __loc);
1219 static void __widen_and_group_float(char* __nb, char* __np, char* __ne,
1220 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1221 const locale& __loc);
1222};
1223
1224template <class _CharT>
1225void
1226__num_put<_CharT>::__widen_and_group_int(char* __nb, char* __np, char* __ne,
1227 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1228 const locale& __loc)
1229{
1230 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> > (__loc);
1231 const numpunct<_CharT>& __npt = use_facet<numpunct<_CharT> >(__loc);
1232 string __grouping = __npt.grouping();
1233 if (__grouping.empty())
1234 {
1235 __ct.widen(__nb, __ne, __ob);
1236 __oe = __ob + (__ne - __nb);
1237 }
1238 else
1239 {
1240 __oe = __ob;
1241 char* __nf = __nb;
1242 if (*__nf == '-' || *__nf == '+')
1243 *__oe++ = __ct.widen(*__nf++);
1244 if (__ne - __nf >= 2 && __nf[0] == '0' && (__nf[1] == 'x' ||
1245 __nf[1] == 'X'))
1246 {
1247 *__oe++ = __ct.widen(*__nf++);
1248 *__oe++ = __ct.widen(*__nf++);
1249 }
1250 reverse(__nf, __ne);
1251 _CharT __thousands_sep = __npt.thousands_sep();
1252 unsigned __dc = 0;
1253 unsigned __dg = 0;
1254 for (char* __p = __nf; __p < __ne; ++__p)
1255 {
1256 if (static_cast<unsigned>(__grouping[__dg]) > 0 &&
1257 __dc == static_cast<unsigned>(__grouping[__dg]))
1258 {
1259 *__oe++ = __thousands_sep;
1260 __dc = 0;
1261 if (__dg < __grouping.size()-1)
1262 ++__dg;
1263 }
1264 *__oe++ = __ct.widen(*__p);
1265 ++__dc;
1266 }
1267 reverse(__ob + (__nf - __nb), __oe);
1268 }
1269 if (__np == __ne)
1270 __op = __oe;
1271 else
1272 __op = __ob + (__np - __nb);
1273}
1274
1275template <class _CharT>
1276void
1277__num_put<_CharT>::__widen_and_group_float(char* __nb, char* __np, char* __ne,
1278 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1279 const locale& __loc)
1280{
1281 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> > (__loc);
1282 const numpunct<_CharT>& __npt = use_facet<numpunct<_CharT> >(__loc);
1283 string __grouping = __npt.grouping();
1284 __oe = __ob;
1285 char* __nf = __nb;
1286 if (*__nf == '-' || *__nf == '+')
1287 *__oe++ = __ct.widen(*__nf++);
1288 char* __ns;
1289 if (__ne - __nf >= 2 && __nf[0] == '0' && (__nf[1] == 'x' ||
1290 __nf[1] == 'X'))
1291 {
1292 *__oe++ = __ct.widen(*__nf++);
1293 *__oe++ = __ct.widen(*__nf++);
1294 for (__ns = __nf; __ns < __ne; ++__ns)
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001295 if (!isxdigit_l(*__ns, _LIBCPP_GET_C_LOCALE))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001296 break;
1297 }
1298 else
1299 {
1300 for (__ns = __nf; __ns < __ne; ++__ns)
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001301 if (!isdigit_l(*__ns, _LIBCPP_GET_C_LOCALE))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001302 break;
1303 }
1304 if (__grouping.empty())
1305 {
1306 __ct.widen(__nf, __ns, __oe);
1307 __oe += __ns - __nf;
1308 }
1309 else
1310 {
1311 reverse(__nf, __ns);
1312 _CharT __thousands_sep = __npt.thousands_sep();
1313 unsigned __dc = 0;
1314 unsigned __dg = 0;
1315 for (char* __p = __nf; __p < __ns; ++__p)
1316 {
1317 if (__grouping[__dg] > 0 && __dc == static_cast<unsigned>(__grouping[__dg]))
1318 {
1319 *__oe++ = __thousands_sep;
1320 __dc = 0;
1321 if (__dg < __grouping.size()-1)
1322 ++__dg;
1323 }
1324 *__oe++ = __ct.widen(*__p);
1325 ++__dc;
1326 }
1327 reverse(__ob + (__nf - __nb), __oe);
1328 }
1329 for (__nf = __ns; __nf < __ne; ++__nf)
1330 {
1331 if (*__nf == '.')
1332 {
1333 *__oe++ = __npt.decimal_point();
1334 ++__nf;
1335 break;
1336 }
1337 else
1338 *__oe++ = __ct.widen(*__nf);
1339 }
1340 __ct.widen(__nf, __ne, __oe);
1341 __oe += __ne - __nf;
1342 if (__np == __ne)
1343 __op = __oe;
1344 else
1345 __op = __ob + (__np - __nb);
1346}
1347
Howard Hinnant499cea12013-08-23 17:37:05 +00001348_LIBCPP_EXTERN_TEMPLATE2(struct _LIBCPP_TYPE_VIS __num_put<char>)
1349_LIBCPP_EXTERN_TEMPLATE2(struct _LIBCPP_TYPE_VIS __num_put<wchar_t>)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001350
1351template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant0f678bd2013-08-12 18:38:34 +00001352class _LIBCPP_TYPE_VIS_ONLY num_put
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001353 : public locale::facet,
1354 private __num_put<_CharT>
1355{
1356public:
1357 typedef _CharT char_type;
1358 typedef _OutputIterator iter_type;
1359
1360 _LIBCPP_ALWAYS_INLINE
1361 explicit num_put(size_t __refs = 0)
1362 : locale::facet(__refs) {}
1363
1364 _LIBCPP_ALWAYS_INLINE
1365 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1366 bool __v) const
1367 {
1368 return do_put(__s, __iob, __fl, __v);
1369 }
1370
1371 _LIBCPP_ALWAYS_INLINE
1372 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1373 long __v) const
1374 {
1375 return do_put(__s, __iob, __fl, __v);
1376 }
1377
1378 _LIBCPP_ALWAYS_INLINE
1379 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1380 long long __v) const
1381 {
1382 return do_put(__s, __iob, __fl, __v);
1383 }
1384
1385 _LIBCPP_ALWAYS_INLINE
1386 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1387 unsigned long __v) const
1388 {
1389 return do_put(__s, __iob, __fl, __v);
1390 }
1391
1392 _LIBCPP_ALWAYS_INLINE
1393 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1394 unsigned long long __v) const
1395 {
1396 return do_put(__s, __iob, __fl, __v);
1397 }
1398
1399 _LIBCPP_ALWAYS_INLINE
1400 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1401 double __v) const
1402 {
1403 return do_put(__s, __iob, __fl, __v);
1404 }
1405
1406 _LIBCPP_ALWAYS_INLINE
1407 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1408 long double __v) const
1409 {
1410 return do_put(__s, __iob, __fl, __v);
1411 }
1412
1413 _LIBCPP_ALWAYS_INLINE
1414 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1415 const void* __v) const
1416 {
1417 return do_put(__s, __iob, __fl, __v);
1418 }
1419
1420 static locale::id id;
1421
1422protected:
Howard Hinnant82894812010-09-22 16:48:34 +00001423 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001424 ~num_put() {}
1425
1426 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1427 bool __v) const;
1428 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1429 long __v) const;
1430 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1431 long long __v) const;
1432 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1433 unsigned long) const;
1434 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1435 unsigned long long) const;
1436 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1437 double __v) const;
1438 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1439 long double __v) const;
1440 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1441 const void* __v) const;
1442};
1443
1444template <class _CharT, class _OutputIterator>
1445locale::id
1446num_put<_CharT, _OutputIterator>::id;
1447
1448template <class _CharT, class _OutputIterator>
1449_LIBCPP_HIDDEN
1450_OutputIterator
1451__pad_and_output(_OutputIterator __s,
1452 const _CharT* __ob, const _CharT* __op, const _CharT* __oe,
1453 ios_base& __iob, _CharT __fl)
1454{
1455 streamsize __sz = __oe - __ob;
1456 streamsize __ns = __iob.width();
1457 if (__ns > __sz)
1458 __ns -= __sz;
1459 else
1460 __ns = 0;
1461 for (;__ob < __op; ++__ob, ++__s)
1462 *__s = *__ob;
1463 for (; __ns; --__ns, ++__s)
1464 *__s = __fl;
1465 for (; __ob < __oe; ++__ob, ++__s)
1466 *__s = *__ob;
1467 __iob.width(0);
1468 return __s;
1469}
1470
Howard Hinnant537b2fa2012-11-14 21:17:15 +00001471#if !defined(__APPLE__) || \
1472 (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED > __MAC_10_8) || \
1473 (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED > __IPHONE_6_0)
1474
Howard Hinnanta585de62012-09-19 19:14:15 +00001475template <class _CharT, class _Traits>
1476_LIBCPP_HIDDEN
1477ostreambuf_iterator<_CharT, _Traits>
1478__pad_and_output(ostreambuf_iterator<_CharT, _Traits> __s,
1479 const _CharT* __ob, const _CharT* __op, const _CharT* __oe,
1480 ios_base& __iob, _CharT __fl)
1481{
1482 if (__s.__sbuf_ == nullptr)
1483 return __s;
1484 streamsize __sz = __oe - __ob;
1485 streamsize __ns = __iob.width();
1486 if (__ns > __sz)
1487 __ns -= __sz;
1488 else
1489 __ns = 0;
1490 streamsize __np = __op - __ob;
1491 if (__np > 0)
1492 {
1493 if (__s.__sbuf_->sputn(__ob, __np) != __np)
1494 {
1495 __s.__sbuf_ = nullptr;
1496 return __s;
1497 }
1498 }
1499 if (__ns > 0)
1500 {
1501 basic_string<_CharT, _Traits> __sp(__ns, __fl);
1502 if (__s.__sbuf_->sputn(__sp.data(), __ns) != __ns)
1503 {
1504 __s.__sbuf_ = nullptr;
1505 return __s;
1506 }
1507 }
1508 __np = __oe - __op;
1509 if (__np > 0)
1510 {
1511 if (__s.__sbuf_->sputn(__op, __np) != __np)
1512 {
1513 __s.__sbuf_ = nullptr;
1514 return __s;
1515 }
1516 }
1517 __iob.width(0);
1518 return __s;
1519}
1520
Howard Hinnant537b2fa2012-11-14 21:17:15 +00001521#endif
1522
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001523template <class _CharT, class _OutputIterator>
1524_OutputIterator
1525num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1526 char_type __fl, bool __v) const
1527{
1528 if ((__iob.flags() & ios_base::boolalpha) == 0)
1529 return do_put(__s, __iob, __fl, (unsigned long)__v);
1530 const numpunct<char_type>& __np = use_facet<numpunct<char_type> >(__iob.getloc());
1531 typedef typename numpunct<char_type>::string_type string_type;
Howard Hinnant499cea12013-08-23 17:37:05 +00001532#if _LIBCPP_DEBUG_LEVEL >= 2
1533 string_type __tmp(__v ? __np.truename() : __np.falsename());
1534 string_type __nm = _VSTD::move(__tmp);
1535#else
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001536 string_type __nm = __v ? __np.truename() : __np.falsename();
Howard Hinnant499cea12013-08-23 17:37:05 +00001537#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001538 for (typename string_type::iterator __i = __nm.begin(); __i != __nm.end(); ++__i, ++__s)
1539 *__s = *__i;
1540 return __s;
1541}
1542
1543template <class _CharT, class _OutputIterator>
1544_OutputIterator
1545num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1546 char_type __fl, long __v) const
1547{
1548 // Stage 1 - Get number in narrow char
1549 char __fmt[6] = {'%', 0};
1550 const char* __len = "l";
1551 this->__format_int(__fmt+1, __len, true, __iob.flags());
1552 const unsigned __nbuf = (numeric_limits<long>::digits / 3)
1553 + ((numeric_limits<long>::digits % 3) != 0)
1554 + 1;
1555 char __nar[__nbuf];
Howard Hinnant866569b2011-09-28 23:39:33 +00001556#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant839ae582013-07-02 18:42:28 +00001557 int __nc = snprintf_l(__nar, sizeof(__nar), _LIBCPP_GET_C_LOCALE, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001558#else
Howard Hinnant839ae582013-07-02 18:42:28 +00001559 int __nc = __snprintf_l(__nar, sizeof(__nar), __cloc(), __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001560#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001561 char* __ne = __nar + __nc;
1562 char* __np = this->__identify_padding(__nar, __ne, __iob);
1563 // Stage 2 - Widen __nar while adding thousands separators
1564 char_type __o[2*(__nbuf-1) - 1];
1565 char_type* __op; // pad here
1566 char_type* __oe; // end of output
1567 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1568 // [__o, __oe) contains thousands_sep'd wide number
1569 // Stage 3 & 4
1570 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1571}
1572
1573template <class _CharT, class _OutputIterator>
1574_OutputIterator
1575num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1576 char_type __fl, long long __v) const
1577{
1578 // Stage 1 - Get number in narrow char
1579 char __fmt[8] = {'%', 0};
1580 const char* __len = "ll";
1581 this->__format_int(__fmt+1, __len, true, __iob.flags());
1582 const unsigned __nbuf = (numeric_limits<long long>::digits / 3)
1583 + ((numeric_limits<long long>::digits % 3) != 0)
1584 + 1;
1585 char __nar[__nbuf];
Howard Hinnant866569b2011-09-28 23:39:33 +00001586#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant839ae582013-07-02 18:42:28 +00001587 int __nc = snprintf_l(__nar, sizeof(__nar), _LIBCPP_GET_C_LOCALE, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001588#else
Howard Hinnant839ae582013-07-02 18:42:28 +00001589 int __nc = __snprintf_l(__nar, sizeof(__nar), __cloc(), __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001590#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001591 char* __ne = __nar + __nc;
1592 char* __np = this->__identify_padding(__nar, __ne, __iob);
1593 // Stage 2 - Widen __nar while adding thousands separators
1594 char_type __o[2*(__nbuf-1) - 1];
1595 char_type* __op; // pad here
1596 char_type* __oe; // end of output
1597 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1598 // [__o, __oe) contains thousands_sep'd wide number
1599 // Stage 3 & 4
1600 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1601}
1602
1603template <class _CharT, class _OutputIterator>
1604_OutputIterator
1605num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1606 char_type __fl, unsigned long __v) const
1607{
1608 // Stage 1 - Get number in narrow char
1609 char __fmt[6] = {'%', 0};
1610 const char* __len = "l";
1611 this->__format_int(__fmt+1, __len, false, __iob.flags());
1612 const unsigned __nbuf = (numeric_limits<unsigned long>::digits / 3)
1613 + ((numeric_limits<unsigned long>::digits % 3) != 0)
1614 + 1;
1615 char __nar[__nbuf];
Howard Hinnant866569b2011-09-28 23:39:33 +00001616#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant839ae582013-07-02 18:42:28 +00001617 int __nc = snprintf_l(__nar, sizeof(__nar), _LIBCPP_GET_C_LOCALE, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001618#else
Howard Hinnant839ae582013-07-02 18:42:28 +00001619 int __nc = __snprintf_l(__nar, sizeof(__nar), __cloc(), __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001620#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001621 char* __ne = __nar + __nc;
1622 char* __np = this->__identify_padding(__nar, __ne, __iob);
1623 // Stage 2 - Widen __nar while adding thousands separators
1624 char_type __o[2*(__nbuf-1) - 1];
1625 char_type* __op; // pad here
1626 char_type* __oe; // end of output
1627 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1628 // [__o, __oe) contains thousands_sep'd wide number
1629 // Stage 3 & 4
1630 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1631}
1632
1633template <class _CharT, class _OutputIterator>
1634_OutputIterator
1635num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1636 char_type __fl, unsigned long long __v) const
1637{
1638 // Stage 1 - Get number in narrow char
1639 char __fmt[8] = {'%', 0};
1640 const char* __len = "ll";
1641 this->__format_int(__fmt+1, __len, false, __iob.flags());
1642 const unsigned __nbuf = (numeric_limits<unsigned long long>::digits / 3)
1643 + ((numeric_limits<unsigned long long>::digits % 3) != 0)
1644 + 1;
1645 char __nar[__nbuf];
Howard Hinnant866569b2011-09-28 23:39:33 +00001646#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant839ae582013-07-02 18:42:28 +00001647 int __nc = snprintf_l(__nar, sizeof(__nar), _LIBCPP_GET_C_LOCALE, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001648#else
Howard Hinnant839ae582013-07-02 18:42:28 +00001649 int __nc = __snprintf_l(__nar, sizeof(__nar), __cloc(), __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001650#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001651 char* __ne = __nar + __nc;
1652 char* __np = this->__identify_padding(__nar, __ne, __iob);
1653 // Stage 2 - Widen __nar while adding thousands separators
1654 char_type __o[2*(__nbuf-1) - 1];
1655 char_type* __op; // pad here
1656 char_type* __oe; // end of output
1657 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1658 // [__o, __oe) contains thousands_sep'd wide number
1659 // Stage 3 & 4
1660 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1661}
1662
1663template <class _CharT, class _OutputIterator>
1664_OutputIterator
1665num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1666 char_type __fl, double __v) const
1667{
1668 // Stage 1 - Get number in narrow char
1669 char __fmt[8] = {'%', 0};
1670 const char* __len = "";
1671 bool __specify_precision = this->__format_float(__fmt+1, __len, __iob.flags());
1672 const unsigned __nbuf = 30;
1673 char __nar[__nbuf];
1674 char* __nb = __nar;
1675 int __nc;
1676 if (__specify_precision)
Howard Hinnant866569b2011-09-28 23:39:33 +00001677#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001678 __nc = snprintf_l(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt,
Howard Hinnantadff4892010-05-24 17:49:41 +00001679 (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001680#else
1681 __nc = __snprintf_l(__nb, __nbuf, __cloc(), __fmt,
1682 (int)__iob.precision(), __v);
1683#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001684 else
Howard Hinnant866569b2011-09-28 23:39:33 +00001685#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001686 __nc = snprintf_l(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001687#else
1688 __nc = __snprintf_l(__nb, __nbuf, __cloc(), __fmt, __v);
1689#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001690 unique_ptr<char, void(*)(void*)> __nbh(0, free);
1691 if (__nc > static_cast<int>(__nbuf-1))
1692 {
1693 if (__specify_precision)
Howard Hinnant866569b2011-09-28 23:39:33 +00001694#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001695 __nc = asprintf_l(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001696#else
1697 __nc = __asprintf_l(&__nb, __cloc(), __fmt,
David Chisnallc512df12011-09-21 08:39:44 +00001698 (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001699#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001700 else
Howard Hinnant866569b2011-09-28 23:39:33 +00001701#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001702 __nc = asprintf_l(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001703#else
David Chisnallc512df12011-09-21 08:39:44 +00001704 __nc = __asprintf_l(&__nb, __cloc(), __fmt, (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001705#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001706 if (__nb == 0)
1707 __throw_bad_alloc();
1708 __nbh.reset(__nb);
1709 }
1710 char* __ne = __nb + __nc;
1711 char* __np = this->__identify_padding(__nb, __ne, __iob);
1712 // Stage 2 - Widen __nar while adding thousands separators
1713 char_type __o[2*(__nbuf-1) - 1];
1714 char_type* __ob = __o;
1715 unique_ptr<char_type, void(*)(void*)> __obh(0, free);
1716 if (__nb != __nar)
1717 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00001718 __ob = (char_type*)malloc(2*static_cast<size_t>(__nc)*sizeof(char_type));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001719 if (__ob == 0)
1720 __throw_bad_alloc();
1721 __obh.reset(__ob);
1722 }
1723 char_type* __op; // pad here
1724 char_type* __oe; // end of output
1725 this->__widen_and_group_float(__nb, __np, __ne, __ob, __op, __oe, __iob.getloc());
1726 // [__o, __oe) contains thousands_sep'd wide number
1727 // Stage 3 & 4
1728 __s = __pad_and_output(__s, __ob, __op, __oe, __iob, __fl);
1729 return __s;
1730}
1731
1732template <class _CharT, class _OutputIterator>
1733_OutputIterator
1734num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1735 char_type __fl, long double __v) const
1736{
1737 // Stage 1 - Get number in narrow char
1738 char __fmt[8] = {'%', 0};
1739 const char* __len = "L";
1740 bool __specify_precision = this->__format_float(__fmt+1, __len, __iob.flags());
1741 const unsigned __nbuf = 30;
1742 char __nar[__nbuf];
1743 char* __nb = __nar;
1744 int __nc;
1745 if (__specify_precision)
Howard Hinnant866569b2011-09-28 23:39:33 +00001746#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001747 __nc = snprintf_l(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt,
Howard Hinnantadff4892010-05-24 17:49:41 +00001748 (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001749#else
1750 __nc = __snprintf_l(__nb, __nbuf, __cloc(), __fmt,
1751 (int)__iob.precision(), __v);
1752#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001753 else
Howard Hinnant866569b2011-09-28 23:39:33 +00001754#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001755 __nc = snprintf_l(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001756#else
1757 __nc = __snprintf_l(__nb, __nbuf, __cloc(), __fmt, __v);
1758#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001759 unique_ptr<char, void(*)(void*)> __nbh(0, free);
1760 if (__nc > static_cast<int>(__nbuf-1))
1761 {
1762 if (__specify_precision)
Howard Hinnant866569b2011-09-28 23:39:33 +00001763#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001764 __nc = asprintf_l(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001765#else
1766 __nc = __asprintf_l(&__nb, __cloc(), __fmt,
David Chisnallc512df12011-09-21 08:39:44 +00001767 (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001768#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001769 else
Howard Hinnant866569b2011-09-28 23:39:33 +00001770#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001771 __nc = asprintf_l(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001772#else
David Chisnallc512df12011-09-21 08:39:44 +00001773 __nc = __asprintf_l(&__nb, __cloc(), __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001774#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001775 if (__nb == 0)
1776 __throw_bad_alloc();
1777 __nbh.reset(__nb);
1778 }
1779 char* __ne = __nb + __nc;
1780 char* __np = this->__identify_padding(__nb, __ne, __iob);
1781 // Stage 2 - Widen __nar while adding thousands separators
1782 char_type __o[2*(__nbuf-1) - 1];
1783 char_type* __ob = __o;
1784 unique_ptr<char_type, void(*)(void*)> __obh(0, free);
1785 if (__nb != __nar)
1786 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00001787 __ob = (char_type*)malloc(2*static_cast<size_t>(__nc)*sizeof(char_type));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001788 if (__ob == 0)
1789 __throw_bad_alloc();
1790 __obh.reset(__ob);
1791 }
1792 char_type* __op; // pad here
1793 char_type* __oe; // end of output
1794 this->__widen_and_group_float(__nb, __np, __ne, __ob, __op, __oe, __iob.getloc());
1795 // [__o, __oe) contains thousands_sep'd wide number
1796 // Stage 3 & 4
1797 __s = __pad_and_output(__s, __ob, __op, __oe, __iob, __fl);
1798 return __s;
1799}
1800
1801template <class _CharT, class _OutputIterator>
1802_OutputIterator
1803num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1804 char_type __fl, const void* __v) const
1805{
1806 // Stage 1 - Get pointer in narrow char
1807 char __fmt[6] = "%p";
1808 const unsigned __nbuf = 20;
1809 char __nar[__nbuf];
Howard Hinnant866569b2011-09-28 23:39:33 +00001810#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant839ae582013-07-02 18:42:28 +00001811 int __nc = snprintf_l(__nar, sizeof(__nar), _LIBCPP_GET_C_LOCALE, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001812#else
Howard Hinnant839ae582013-07-02 18:42:28 +00001813 int __nc = __snprintf_l(__nar, sizeof(__nar), __cloc(), __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001814#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001815 char* __ne = __nar + __nc;
1816 char* __np = this->__identify_padding(__nar, __ne, __iob);
1817 // Stage 2 - Widen __nar
1818 char_type __o[2*(__nbuf-1) - 1];
1819 char_type* __op; // pad here
1820 char_type* __oe; // end of output
1821 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
1822 __ct.widen(__nar, __ne, __o);
1823 __oe = __o + (__ne - __nar);
1824 if (__np == __ne)
1825 __op = __oe;
1826 else
1827 __op = __o + (__np - __nar);
1828 // [__o, __oe) contains wide number
1829 // Stage 3 & 4
1830 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1831}
1832
Howard Hinnant499cea12013-08-23 17:37:05 +00001833_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS num_put<char>)
1834_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS num_put<wchar_t>)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001835
1836template <class _CharT, class _InputIterator>
1837_LIBCPP_HIDDEN
1838int
1839__get_up_to_n_digits(_InputIterator& __b, _InputIterator __e,
1840 ios_base::iostate& __err, const ctype<_CharT>& __ct, int __n)
1841{
1842 // Precondition: __n >= 1
1843 if (__b == __e)
1844 {
1845 __err |= ios_base::eofbit | ios_base::failbit;
1846 return 0;
1847 }
1848 // get first digit
1849 _CharT __c = *__b;
1850 if (!__ct.is(ctype_base::digit, __c))
1851 {
1852 __err |= ios_base::failbit;
1853 return 0;
1854 }
1855 int __r = __ct.narrow(__c, 0) - '0';
1856 for (++__b, --__n; __b != __e && __n > 0; ++__b, --__n)
1857 {
1858 // get next digit
1859 __c = *__b;
1860 if (!__ct.is(ctype_base::digit, __c))
1861 return __r;
1862 __r = __r * 10 + __ct.narrow(__c, 0) - '0';
1863 }
1864 if (__b == __e)
1865 __err |= ios_base::eofbit;
1866 return __r;
1867}
1868
Howard Hinnant83eade62013-03-06 23:30:19 +00001869class _LIBCPP_TYPE_VIS time_base
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001870{
1871public:
1872 enum dateorder {no_order, dmy, mdy, ymd, ydm};
1873};
1874
1875template <class _CharT>
Howard Hinnant0f678bd2013-08-12 18:38:34 +00001876class _LIBCPP_TYPE_VIS __time_get_c_storage
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001877{
1878protected:
1879 typedef basic_string<_CharT> string_type;
1880
1881 virtual const string_type* __weeks() const;
1882 virtual const string_type* __months() const;
1883 virtual const string_type* __am_pm() const;
1884 virtual const string_type& __c() const;
1885 virtual const string_type& __r() const;
1886 virtual const string_type& __x() const;
1887 virtual const string_type& __X() const;
1888};
1889
1890template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnant0f678bd2013-08-12 18:38:34 +00001891class _LIBCPP_TYPE_VIS_ONLY time_get
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001892 : public locale::facet,
1893 public time_base,
1894 private __time_get_c_storage<_CharT>
1895{
1896public:
1897 typedef _CharT char_type;
1898 typedef _InputIterator iter_type;
1899 typedef time_base::dateorder dateorder;
1900 typedef basic_string<char_type> string_type;
1901
1902 _LIBCPP_ALWAYS_INLINE
1903 explicit time_get(size_t __refs = 0)
1904 : locale::facet(__refs) {}
1905
1906 _LIBCPP_ALWAYS_INLINE
1907 dateorder date_order() const
1908 {
1909 return this->do_date_order();
1910 }
1911
1912 _LIBCPP_ALWAYS_INLINE
1913 iter_type get_time(iter_type __b, iter_type __e, ios_base& __iob,
1914 ios_base::iostate& __err, tm* __tm) const
1915 {
1916 return do_get_time(__b, __e, __iob, __err, __tm);
1917 }
1918
1919 _LIBCPP_ALWAYS_INLINE
1920 iter_type get_date(iter_type __b, iter_type __e, ios_base& __iob,
1921 ios_base::iostate& __err, tm* __tm) const
1922 {
1923 return do_get_date(__b, __e, __iob, __err, __tm);
1924 }
1925
1926 _LIBCPP_ALWAYS_INLINE
1927 iter_type get_weekday(iter_type __b, iter_type __e, ios_base& __iob,
1928 ios_base::iostate& __err, tm* __tm) const
1929 {
1930 return do_get_weekday(__b, __e, __iob, __err, __tm);
1931 }
1932
1933 _LIBCPP_ALWAYS_INLINE
1934 iter_type get_monthname(iter_type __b, iter_type __e, ios_base& __iob,
1935 ios_base::iostate& __err, tm* __tm) const
1936 {
1937 return do_get_monthname(__b, __e, __iob, __err, __tm);
1938 }
1939
1940 _LIBCPP_ALWAYS_INLINE
1941 iter_type get_year(iter_type __b, iter_type __e, ios_base& __iob,
1942 ios_base::iostate& __err, tm* __tm) const
1943 {
1944 return do_get_year(__b, __e, __iob, __err, __tm);
1945 }
1946
1947 _LIBCPP_ALWAYS_INLINE
1948 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
1949 ios_base::iostate& __err, tm *__tm,
1950 char __fmt, char __mod = 0) const
1951 {
1952 return do_get(__b, __e, __iob, __err, __tm, __fmt, __mod);
1953 }
1954
1955 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
1956 ios_base::iostate& __err, tm* __tm,
1957 const char_type* __fmtb, const char_type* __fmte) const;
1958
1959 static locale::id id;
1960
1961protected:
Howard Hinnant82894812010-09-22 16:48:34 +00001962 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001963 ~time_get() {}
1964
1965 virtual dateorder do_date_order() const;
1966 virtual iter_type do_get_time(iter_type __b, iter_type __e, ios_base& __iob,
1967 ios_base::iostate& __err, tm* __tm) const;
1968 virtual iter_type do_get_date(iter_type __b, iter_type __e, ios_base& __iob,
1969 ios_base::iostate& __err, tm* __tm) const;
1970 virtual iter_type do_get_weekday(iter_type __b, iter_type __e, ios_base& __iob,
1971 ios_base::iostate& __err, tm* __tm) const;
1972 virtual iter_type do_get_monthname(iter_type __b, iter_type __e, ios_base& __iob,
1973 ios_base::iostate& __err, tm* __tm) const;
1974 virtual iter_type do_get_year(iter_type __b, iter_type __e, ios_base& __iob,
1975 ios_base::iostate& __err, tm* __tm) const;
1976 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
1977 ios_base::iostate& __err, tm* __tm,
1978 char __fmt, char __mod) const;
1979private:
1980 void __get_white_space(iter_type& __b, iter_type __e,
1981 ios_base::iostate& __err, const ctype<char_type>& __ct) const;
1982 void __get_percent(iter_type& __b, iter_type __e, ios_base::iostate& __err,
1983 const ctype<char_type>& __ct) const;
1984
1985 void __get_weekdayname(int& __m,
1986 iter_type& __b, iter_type __e,
1987 ios_base::iostate& __err,
1988 const ctype<char_type>& __ct) const;
1989 void __get_monthname(int& __m,
1990 iter_type& __b, iter_type __e,
1991 ios_base::iostate& __err,
1992 const ctype<char_type>& __ct) const;
1993 void __get_day(int& __d,
1994 iter_type& __b, iter_type __e,
1995 ios_base::iostate& __err,
1996 const ctype<char_type>& __ct) const;
1997 void __get_month(int& __m,
1998 iter_type& __b, iter_type __e,
1999 ios_base::iostate& __err,
2000 const ctype<char_type>& __ct) const;
2001 void __get_year(int& __y,
2002 iter_type& __b, iter_type __e,
2003 ios_base::iostate& __err,
2004 const ctype<char_type>& __ct) const;
2005 void __get_year4(int& __y,
2006 iter_type& __b, iter_type __e,
2007 ios_base::iostate& __err,
2008 const ctype<char_type>& __ct) const;
2009 void __get_hour(int& __d,
2010 iter_type& __b, iter_type __e,
2011 ios_base::iostate& __err,
2012 const ctype<char_type>& __ct) const;
2013 void __get_12_hour(int& __h,
2014 iter_type& __b, iter_type __e,
2015 ios_base::iostate& __err,
2016 const ctype<char_type>& __ct) const;
2017 void __get_am_pm(int& __h,
2018 iter_type& __b, iter_type __e,
2019 ios_base::iostate& __err,
2020 const ctype<char_type>& __ct) const;
2021 void __get_minute(int& __m,
2022 iter_type& __b, iter_type __e,
2023 ios_base::iostate& __err,
2024 const ctype<char_type>& __ct) const;
2025 void __get_second(int& __s,
2026 iter_type& __b, iter_type __e,
2027 ios_base::iostate& __err,
2028 const ctype<char_type>& __ct) const;
2029 void __get_weekday(int& __w,
2030 iter_type& __b, iter_type __e,
2031 ios_base::iostate& __err,
2032 const ctype<char_type>& __ct) const;
2033 void __get_day_year_num(int& __w,
2034 iter_type& __b, iter_type __e,
2035 ios_base::iostate& __err,
2036 const ctype<char_type>& __ct) const;
2037};
2038
2039template <class _CharT, class _InputIterator>
2040locale::id
2041time_get<_CharT, _InputIterator>::id;
2042
2043// time_get primatives
2044
2045template <class _CharT, class _InputIterator>
2046void
2047time_get<_CharT, _InputIterator>::__get_weekdayname(int& __w,
2048 iter_type& __b, iter_type __e,
2049 ios_base::iostate& __err,
2050 const ctype<char_type>& __ct) const
2051{
2052 // Note: ignoring case comes from the POSIX strptime spec
2053 const string_type* __wk = this->__weeks();
Howard Hinnantec3773c2011-12-01 20:21:04 +00002054 ptrdiff_t __i = __scan_keyword(__b, __e, __wk, __wk+14, __ct, __err, false) - __wk;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002055 if (__i < 14)
2056 __w = __i % 7;
2057}
2058
2059template <class _CharT, class _InputIterator>
2060void
2061time_get<_CharT, _InputIterator>::__get_monthname(int& __m,
2062 iter_type& __b, iter_type __e,
2063 ios_base::iostate& __err,
2064 const ctype<char_type>& __ct) const
2065{
2066 // Note: ignoring case comes from the POSIX strptime spec
2067 const string_type* __month = this->__months();
Howard Hinnantec3773c2011-12-01 20:21:04 +00002068 ptrdiff_t __i = __scan_keyword(__b, __e, __month, __month+24, __ct, __err, false) - __month;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002069 if (__i < 24)
2070 __m = __i % 12;
2071}
2072
2073template <class _CharT, class _InputIterator>
2074void
2075time_get<_CharT, _InputIterator>::__get_day(int& __d,
2076 iter_type& __b, iter_type __e,
2077 ios_base::iostate& __err,
2078 const ctype<char_type>& __ct) const
2079{
2080 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2081 if (!(__err & ios_base::failbit) && 1 <= __t && __t <= 31)
2082 __d = __t;
2083 else
2084 __err |= ios_base::failbit;
2085}
2086
2087template <class _CharT, class _InputIterator>
2088void
2089time_get<_CharT, _InputIterator>::__get_month(int& __m,
2090 iter_type& __b, iter_type __e,
2091 ios_base::iostate& __err,
2092 const ctype<char_type>& __ct) const
2093{
2094 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2) - 1;
2095 if (!(__err & ios_base::failbit) && __t <= 11)
2096 __m = __t;
2097 else
2098 __err |= ios_base::failbit;
2099}
2100
2101template <class _CharT, class _InputIterator>
2102void
2103time_get<_CharT, _InputIterator>::__get_year(int& __y,
2104 iter_type& __b, iter_type __e,
2105 ios_base::iostate& __err,
2106 const ctype<char_type>& __ct) const
2107{
2108 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 4);
2109 if (!(__err & ios_base::failbit))
2110 {
2111 if (__t < 69)
2112 __t += 2000;
2113 else if (69 <= __t && __t <= 99)
2114 __t += 1900;
2115 __y = __t - 1900;
2116 }
2117}
2118
2119template <class _CharT, class _InputIterator>
2120void
2121time_get<_CharT, _InputIterator>::__get_year4(int& __y,
2122 iter_type& __b, iter_type __e,
2123 ios_base::iostate& __err,
2124 const ctype<char_type>& __ct) const
2125{
2126 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 4);
2127 if (!(__err & ios_base::failbit))
2128 __y = __t - 1900;
2129}
2130
2131template <class _CharT, class _InputIterator>
2132void
2133time_get<_CharT, _InputIterator>::__get_hour(int& __h,
2134 iter_type& __b, iter_type __e,
2135 ios_base::iostate& __err,
2136 const ctype<char_type>& __ct) const
2137{
2138 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2139 if (!(__err & ios_base::failbit) && __t <= 23)
2140 __h = __t;
2141 else
2142 __err |= ios_base::failbit;
2143}
2144
2145template <class _CharT, class _InputIterator>
2146void
2147time_get<_CharT, _InputIterator>::__get_12_hour(int& __h,
2148 iter_type& __b, iter_type __e,
2149 ios_base::iostate& __err,
2150 const ctype<char_type>& __ct) const
2151{
2152 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2153 if (!(__err & ios_base::failbit) && 1 <= __t && __t <= 12)
2154 __h = __t;
2155 else
2156 __err |= ios_base::failbit;
2157}
2158
2159template <class _CharT, class _InputIterator>
2160void
2161time_get<_CharT, _InputIterator>::__get_minute(int& __m,
2162 iter_type& __b, iter_type __e,
2163 ios_base::iostate& __err,
2164 const ctype<char_type>& __ct) const
2165{
2166 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2167 if (!(__err & ios_base::failbit) && __t <= 59)
2168 __m = __t;
2169 else
2170 __err |= ios_base::failbit;
2171}
2172
2173template <class _CharT, class _InputIterator>
2174void
2175time_get<_CharT, _InputIterator>::__get_second(int& __s,
2176 iter_type& __b, iter_type __e,
2177 ios_base::iostate& __err,
2178 const ctype<char_type>& __ct) const
2179{
2180 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2181 if (!(__err & ios_base::failbit) && __t <= 60)
2182 __s = __t;
2183 else
2184 __err |= ios_base::failbit;
2185}
2186
2187template <class _CharT, class _InputIterator>
2188void
2189time_get<_CharT, _InputIterator>::__get_weekday(int& __w,
2190 iter_type& __b, iter_type __e,
2191 ios_base::iostate& __err,
2192 const ctype<char_type>& __ct) const
2193{
2194 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 1);
2195 if (!(__err & ios_base::failbit) && __t <= 6)
2196 __w = __t;
2197 else
2198 __err |= ios_base::failbit;
2199}
2200
2201template <class _CharT, class _InputIterator>
2202void
2203time_get<_CharT, _InputIterator>::__get_day_year_num(int& __d,
2204 iter_type& __b, iter_type __e,
2205 ios_base::iostate& __err,
2206 const ctype<char_type>& __ct) const
2207{
2208 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 3);
2209 if (!(__err & ios_base::failbit) && __t <= 365)
2210 __d = __t;
2211 else
2212 __err |= ios_base::failbit;
2213}
2214
2215template <class _CharT, class _InputIterator>
2216void
2217time_get<_CharT, _InputIterator>::__get_white_space(iter_type& __b, iter_type __e,
2218 ios_base::iostate& __err,
2219 const ctype<char_type>& __ct) const
2220{
2221 for (; __b != __e && __ct.is(ctype_base::space, *__b); ++__b)
2222 ;
2223 if (__b == __e)
2224 __err |= ios_base::eofbit;
2225}
2226
2227template <class _CharT, class _InputIterator>
2228void
2229time_get<_CharT, _InputIterator>::__get_am_pm(int& __h,
2230 iter_type& __b, iter_type __e,
2231 ios_base::iostate& __err,
2232 const ctype<char_type>& __ct) const
2233{
2234 const string_type* __ap = this->__am_pm();
2235 if (__ap[0].size() + __ap[1].size() == 0)
2236 {
2237 __err |= ios_base::failbit;
2238 return;
2239 }
Howard Hinnantec3773c2011-12-01 20:21:04 +00002240 ptrdiff_t __i = __scan_keyword(__b, __e, __ap, __ap+2, __ct, __err, false) - __ap;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002241 if (__i == 0 && __h == 12)
2242 __h = 0;
2243 else if (__i == 1 && __h < 12)
2244 __h += 12;
2245}
2246
2247template <class _CharT, class _InputIterator>
2248void
2249time_get<_CharT, _InputIterator>::__get_percent(iter_type& __b, iter_type __e,
2250 ios_base::iostate& __err,
2251 const ctype<char_type>& __ct) const
2252{
2253 if (__b == __e)
2254 {
2255 __err |= ios_base::eofbit | ios_base::failbit;
2256 return;
2257 }
2258 if (__ct.narrow(*__b, 0) != '%')
2259 __err |= ios_base::failbit;
2260 else if(++__b == __e)
2261 __err |= ios_base::eofbit;
2262}
2263
2264// time_get end primatives
2265
2266template <class _CharT, class _InputIterator>
2267_InputIterator
2268time_get<_CharT, _InputIterator>::get(iter_type __b, iter_type __e,
2269 ios_base& __iob,
2270 ios_base::iostate& __err, tm* __tm,
2271 const char_type* __fmtb, const char_type* __fmte) const
2272{
2273 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2274 __err = ios_base::goodbit;
2275 while (__fmtb != __fmte && __err == ios_base::goodbit)
2276 {
2277 if (__b == __e)
2278 {
2279 __err = ios_base::failbit;
2280 break;
2281 }
2282 if (__ct.narrow(*__fmtb, 0) == '%')
2283 {
2284 if (++__fmtb == __fmte)
2285 {
2286 __err = ios_base::failbit;
2287 break;
2288 }
2289 char __cmd = __ct.narrow(*__fmtb, 0);
2290 char __opt = '\0';
2291 if (__cmd == 'E' || __cmd == '0')
2292 {
2293 if (++__fmtb == __fmte)
2294 {
2295 __err = ios_base::failbit;
2296 break;
2297 }
2298 __opt = __cmd;
2299 __cmd = __ct.narrow(*__fmtb, 0);
2300 }
2301 __b = do_get(__b, __e, __iob, __err, __tm, __cmd, __opt);
2302 ++__fmtb;
2303 }
2304 else if (__ct.is(ctype_base::space, *__fmtb))
2305 {
2306 for (++__fmtb; __fmtb != __fmte && __ct.is(ctype_base::space, *__fmtb); ++__fmtb)
2307 ;
2308 for ( ; __b != __e && __ct.is(ctype_base::space, *__b); ++__b)
2309 ;
2310 }
2311 else if (__ct.toupper(*__b) == __ct.toupper(*__fmtb))
2312 {
2313 ++__b;
2314 ++__fmtb;
2315 }
2316 else
2317 __err = ios_base::failbit;
2318 }
2319 if (__b == __e)
2320 __err |= ios_base::eofbit;
2321 return __b;
2322}
2323
2324template <class _CharT, class _InputIterator>
2325typename time_get<_CharT, _InputIterator>::dateorder
2326time_get<_CharT, _InputIterator>::do_date_order() const
2327{
2328 return mdy;
2329}
2330
2331template <class _CharT, class _InputIterator>
2332_InputIterator
2333time_get<_CharT, _InputIterator>::do_get_time(iter_type __b, iter_type __e,
2334 ios_base& __iob,
2335 ios_base::iostate& __err,
2336 tm* __tm) const
2337{
2338 const char_type __fmt[] = {'%', 'H', ':', '%', 'M', ':', '%', 'S'};
2339 return get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2340}
2341
2342template <class _CharT, class _InputIterator>
2343_InputIterator
2344time_get<_CharT, _InputIterator>::do_get_date(iter_type __b, iter_type __e,
2345 ios_base& __iob,
2346 ios_base::iostate& __err,
2347 tm* __tm) const
2348{
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002349 const string_type& __fmt = this->__x();
2350 return get(__b, __e, __iob, __err, __tm, __fmt.data(), __fmt.data() + __fmt.size());
2351}
2352
2353template <class _CharT, class _InputIterator>
2354_InputIterator
2355time_get<_CharT, _InputIterator>::do_get_weekday(iter_type __b, iter_type __e,
2356 ios_base& __iob,
2357 ios_base::iostate& __err,
2358 tm* __tm) const
2359{
2360 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2361 __get_weekdayname(__tm->tm_wday, __b, __e, __err, __ct);
2362 return __b;
2363}
2364
2365template <class _CharT, class _InputIterator>
2366_InputIterator
2367time_get<_CharT, _InputIterator>::do_get_monthname(iter_type __b, iter_type __e,
2368 ios_base& __iob,
2369 ios_base::iostate& __err,
2370 tm* __tm) const
2371{
2372 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2373 __get_monthname(__tm->tm_mon, __b, __e, __err, __ct);
2374 return __b;
2375}
2376
2377template <class _CharT, class _InputIterator>
2378_InputIterator
2379time_get<_CharT, _InputIterator>::do_get_year(iter_type __b, iter_type __e,
2380 ios_base& __iob,
2381 ios_base::iostate& __err,
2382 tm* __tm) const
2383{
2384 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2385 __get_year(__tm->tm_year, __b, __e, __err, __ct);
2386 return __b;
2387}
2388
2389template <class _CharT, class _InputIterator>
2390_InputIterator
2391time_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
2392 ios_base& __iob,
2393 ios_base::iostate& __err, tm* __tm,
2394 char __fmt, char) const
2395{
2396 __err = ios_base::goodbit;
2397 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2398 switch (__fmt)
2399 {
2400 case 'a':
2401 case 'A':
2402 __get_weekdayname(__tm->tm_wday, __b, __e, __err, __ct);
2403 break;
2404 case 'b':
2405 case 'B':
2406 case 'h':
2407 __get_monthname(__tm->tm_mon, __b, __e, __err, __ct);
2408 break;
2409 case 'c':
2410 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002411 const string_type& __fm = this->__c();
2412 __b = get(__b, __e, __iob, __err, __tm, __fm.data(), __fm.data() + __fm.size());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002413 }
2414 break;
2415 case 'd':
2416 case 'e':
2417 __get_day(__tm->tm_mday, __b, __e, __err, __ct);
2418 break;
2419 case 'D':
2420 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002421 const char_type __fm[] = {'%', 'm', '/', '%', 'd', '/', '%', 'y'};
2422 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm)/sizeof(__fm[0]));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002423 }
2424 break;
Howard Hinnant506b3642011-04-10 17:54:14 +00002425 case 'F':
2426 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002427 const char_type __fm[] = {'%', 'Y', '-', '%', 'm', '-', '%', 'd'};
2428 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm)/sizeof(__fm[0]));
Howard Hinnant506b3642011-04-10 17:54:14 +00002429 }
2430 break;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002431 case 'H':
2432 __get_hour(__tm->tm_hour, __b, __e, __err, __ct);
2433 break;
2434 case 'I':
2435 __get_12_hour(__tm->tm_hour, __b, __e, __err, __ct);
2436 break;
2437 case 'j':
2438 __get_day_year_num(__tm->tm_yday, __b, __e, __err, __ct);
2439 break;
2440 case 'm':
2441 __get_month(__tm->tm_mon, __b, __e, __err, __ct);
2442 break;
2443 case 'M':
2444 __get_minute(__tm->tm_min, __b, __e, __err, __ct);
2445 break;
2446 case 'n':
2447 case 't':
2448 __get_white_space(__b, __e, __err, __ct);
2449 break;
2450 case 'p':
2451 __get_am_pm(__tm->tm_hour, __b, __e, __err, __ct);
2452 break;
2453 case 'r':
2454 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002455 const char_type __fm[] = {'%', 'I', ':', '%', 'M', ':', '%', 'S', ' ', '%', 'p'};
2456 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm)/sizeof(__fm[0]));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002457 }
2458 break;
2459 case 'R':
2460 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002461 const char_type __fm[] = {'%', 'H', ':', '%', 'M'};
2462 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm)/sizeof(__fm[0]));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002463 }
2464 break;
2465 case 'S':
2466 __get_second(__tm->tm_sec, __b, __e, __err, __ct);
2467 break;
2468 case 'T':
2469 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002470 const char_type __fm[] = {'%', 'H', ':', '%', 'M', ':', '%', 'S'};
2471 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm)/sizeof(__fm[0]));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002472 }
2473 break;
2474 case 'w':
2475 __get_weekday(__tm->tm_wday, __b, __e, __err, __ct);
2476 break;
2477 case 'x':
2478 return do_get_date(__b, __e, __iob, __err, __tm);
2479 case 'X':
2480 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002481 const string_type& __fm = this->__X();
2482 __b = get(__b, __e, __iob, __err, __tm, __fm.data(), __fm.data() + __fm.size());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002483 }
2484 break;
2485 case 'y':
2486 __get_year(__tm->tm_year, __b, __e, __err, __ct);
2487 break;
2488 case 'Y':
2489 __get_year4(__tm->tm_year, __b, __e, __err, __ct);
2490 break;
2491 case '%':
2492 __get_percent(__b, __e, __err, __ct);
2493 break;
2494 default:
2495 __err |= ios_base::failbit;
2496 }
2497 return __b;
2498}
2499
Howard Hinnant499cea12013-08-23 17:37:05 +00002500_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS time_get<char>)
2501_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS time_get<wchar_t>)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002502
Howard Hinnant0f678bd2013-08-12 18:38:34 +00002503class _LIBCPP_TYPE_VIS __time_get
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002504{
2505protected:
2506 locale_t __loc_;
2507
2508 __time_get(const char* __nm);
2509 __time_get(const string& __nm);
2510 ~__time_get();
2511};
2512
2513template <class _CharT>
Howard Hinnant0f678bd2013-08-12 18:38:34 +00002514class _LIBCPP_TYPE_VIS __time_get_storage
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002515 : public __time_get
2516{
2517protected:
2518 typedef basic_string<_CharT> string_type;
2519
2520 string_type __weeks_[14];
2521 string_type __months_[24];
2522 string_type __am_pm_[2];
2523 string_type __c_;
2524 string_type __r_;
2525 string_type __x_;
2526 string_type __X_;
2527
2528 explicit __time_get_storage(const char* __nm);
2529 explicit __time_get_storage(const string& __nm);
2530
2531 _LIBCPP_ALWAYS_INLINE ~__time_get_storage() {}
2532
2533 time_base::dateorder __do_date_order() const;
2534
2535private:
2536 void init(const ctype<_CharT>&);
2537 string_type __analyze(char __fmt, const ctype<_CharT>&);
2538};
2539
2540template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnant0f678bd2013-08-12 18:38:34 +00002541class _LIBCPP_TYPE_VIS_ONLY time_get_byname
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002542 : public time_get<_CharT, _InputIterator>,
2543 private __time_get_storage<_CharT>
2544{
2545public:
2546 typedef time_base::dateorder dateorder;
2547 typedef _InputIterator iter_type;
2548 typedef _CharT char_type;
2549 typedef basic_string<char_type> string_type;
2550
Howard Hinnant82894812010-09-22 16:48:34 +00002551 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002552 explicit time_get_byname(const char* __nm, size_t __refs = 0)
2553 : time_get<_CharT, _InputIterator>(__refs),
2554 __time_get_storage<_CharT>(__nm) {}
Howard Hinnant82894812010-09-22 16:48:34 +00002555 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002556 explicit time_get_byname(const string& __nm, size_t __refs = 0)
2557 : time_get<_CharT, _InputIterator>(__refs),
2558 __time_get_storage<_CharT>(__nm) {}
2559
2560protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002561 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002562 ~time_get_byname() {}
2563
Howard Hinnant82894812010-09-22 16:48:34 +00002564 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002565 virtual dateorder do_date_order() const {return this->__do_date_order();}
2566private:
Howard Hinnant82894812010-09-22 16:48:34 +00002567 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002568 virtual const string_type* __weeks() const {return this->__weeks_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002569 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002570 virtual const string_type* __months() const {return this->__months_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002571 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002572 virtual const string_type* __am_pm() const {return this->__am_pm_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002573 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002574 virtual const string_type& __c() const {return this->__c_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002575 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002576 virtual const string_type& __r() const {return this->__r_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002577 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002578 virtual const string_type& __x() const {return this->__x_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002579 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002580 virtual const string_type& __X() const {return this->__X_;}
2581};
2582
Howard Hinnant499cea12013-08-23 17:37:05 +00002583_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS time_get_byname<char>)
2584_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS time_get_byname<wchar_t>)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002585
Howard Hinnant0f678bd2013-08-12 18:38:34 +00002586class _LIBCPP_TYPE_VIS __time_put
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002587{
2588 locale_t __loc_;
2589protected:
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00002590 _LIBCPP_ALWAYS_INLINE __time_put() : __loc_(_LIBCPP_GET_C_LOCALE) {}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002591 __time_put(const char* __nm);
2592 __time_put(const string& __nm);
2593 ~__time_put();
2594 void __do_put(char* __nb, char*& __ne, const tm* __tm,
2595 char __fmt, char __mod) const;
2596 void __do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
2597 char __fmt, char __mod) const;
2598};
2599
2600template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant0f678bd2013-08-12 18:38:34 +00002601class _LIBCPP_TYPE_VIS_ONLY time_put
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002602 : public locale::facet,
2603 private __time_put
2604{
2605public:
2606 typedef _CharT char_type;
2607 typedef _OutputIterator iter_type;
2608
2609 _LIBCPP_ALWAYS_INLINE
2610 explicit time_put(size_t __refs = 0)
2611 : locale::facet(__refs) {}
2612
2613 iter_type put(iter_type __s, ios_base& __iob, char_type __fl, const tm* __tm,
2614 const char_type* __pb, const char_type* __pe) const;
2615
2616 _LIBCPP_ALWAYS_INLINE
2617 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
2618 const tm* __tm, char __fmt, char __mod = 0) const
2619 {
2620 return do_put(__s, __iob, __fl, __tm, __fmt, __mod);
2621 }
2622
2623 static locale::id id;
2624
2625protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002626 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002627 ~time_put() {}
2628 virtual iter_type do_put(iter_type __s, ios_base&, char_type, const tm* __tm,
2629 char __fmt, char __mod) const;
2630
Howard Hinnant82894812010-09-22 16:48:34 +00002631 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002632 explicit time_put(const char* __nm, size_t __refs)
2633 : locale::facet(__refs),
2634 __time_put(__nm) {}
Howard Hinnant82894812010-09-22 16:48:34 +00002635 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002636 explicit time_put(const string& __nm, size_t __refs)
2637 : locale::facet(__refs),
2638 __time_put(__nm) {}
2639};
2640
2641template <class _CharT, class _OutputIterator>
2642locale::id
2643time_put<_CharT, _OutputIterator>::id;
2644
2645template <class _CharT, class _OutputIterator>
2646_OutputIterator
2647time_put<_CharT, _OutputIterator>::put(iter_type __s, ios_base& __iob,
2648 char_type __fl, const tm* __tm,
2649 const char_type* __pb,
2650 const char_type* __pe) const
2651{
2652 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2653 for (; __pb != __pe; ++__pb)
2654 {
2655 if (__ct.narrow(*__pb, 0) == '%')
2656 {
2657 if (++__pb == __pe)
2658 {
2659 *__s++ = __pb[-1];
2660 break;
2661 }
2662 char __mod = 0;
2663 char __fmt = __ct.narrow(*__pb, 0);
2664 if (__fmt == 'E' || __fmt == 'O')
2665 {
2666 if (++__pb == __pe)
2667 {
2668 *__s++ = __pb[-2];
2669 *__s++ = __pb[-1];
2670 break;
2671 }
2672 __mod = __fmt;
2673 __fmt = __ct.narrow(*__pb, 0);
2674 }
2675 __s = do_put(__s, __iob, __fl, __tm, __fmt, __mod);
2676 }
2677 else
2678 *__s++ = *__pb;
2679 }
2680 return __s;
2681}
2682
2683template <class _CharT, class _OutputIterator>
2684_OutputIterator
Howard Hinnantec3773c2011-12-01 20:21:04 +00002685time_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002686 char_type, const tm* __tm,
2687 char __fmt, char __mod) const
2688{
2689 char_type __nar[100];
2690 char_type* __nb = __nar;
2691 char_type* __ne = __nb + 100;
2692 __do_put(__nb, __ne, __tm, __fmt, __mod);
Howard Hinnant0949eed2011-06-30 21:18:19 +00002693 return _VSTD::copy(__nb, __ne, __s);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002694}
2695
Howard Hinnant499cea12013-08-23 17:37:05 +00002696_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS time_put<char>)
2697_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS time_put<wchar_t>)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002698
2699template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant0f678bd2013-08-12 18:38:34 +00002700class _LIBCPP_TYPE_VIS_ONLY time_put_byname
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002701 : public time_put<_CharT, _OutputIterator>
2702{
2703public:
2704 _LIBCPP_ALWAYS_INLINE
2705 explicit time_put_byname(const char* __nm, size_t __refs = 0)
2706 : time_put<_CharT, _OutputIterator>(__nm, __refs) {}
2707
2708 _LIBCPP_ALWAYS_INLINE
2709 explicit time_put_byname(const string& __nm, size_t __refs = 0)
2710 : time_put<_CharT, _OutputIterator>(__nm, __refs) {}
2711
2712protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002713 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002714 ~time_put_byname() {}
2715};
2716
Howard Hinnant499cea12013-08-23 17:37:05 +00002717_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS time_put_byname<char>)
2718_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS time_put_byname<wchar_t>)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002719
2720// money_base
2721
Howard Hinnant83eade62013-03-06 23:30:19 +00002722class _LIBCPP_TYPE_VIS money_base
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002723{
2724public:
2725 enum part {none, space, symbol, sign, value};
2726 struct pattern {char field[4];};
2727
2728 _LIBCPP_ALWAYS_INLINE money_base() {}
2729};
2730
2731// moneypunct
2732
2733template <class _CharT, bool _International = false>
Howard Hinnant0f678bd2013-08-12 18:38:34 +00002734class _LIBCPP_TYPE_VIS_ONLY moneypunct
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002735 : public locale::facet,
2736 public money_base
2737{
2738public:
2739 typedef _CharT char_type;
2740 typedef basic_string<char_type> string_type;
2741
Howard Hinnant82894812010-09-22 16:48:34 +00002742 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002743 explicit moneypunct(size_t __refs = 0)
2744 : locale::facet(__refs) {}
2745
2746 _LIBCPP_ALWAYS_INLINE char_type decimal_point() const {return do_decimal_point();}
2747 _LIBCPP_ALWAYS_INLINE char_type thousands_sep() const {return do_thousands_sep();}
2748 _LIBCPP_ALWAYS_INLINE string grouping() const {return do_grouping();}
2749 _LIBCPP_ALWAYS_INLINE string_type curr_symbol() const {return do_curr_symbol();}
2750 _LIBCPP_ALWAYS_INLINE string_type positive_sign() const {return do_positive_sign();}
2751 _LIBCPP_ALWAYS_INLINE string_type negative_sign() const {return do_negative_sign();}
2752 _LIBCPP_ALWAYS_INLINE int frac_digits() const {return do_frac_digits();}
2753 _LIBCPP_ALWAYS_INLINE pattern pos_format() const {return do_pos_format();}
2754 _LIBCPP_ALWAYS_INLINE pattern neg_format() const {return do_neg_format();}
2755
2756 static locale::id id;
2757 static const bool intl = _International;
2758
2759protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002760 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002761 ~moneypunct() {}
2762
2763 virtual char_type do_decimal_point() const {return numeric_limits<char_type>::max();}
2764 virtual char_type do_thousands_sep() const {return numeric_limits<char_type>::max();}
2765 virtual string do_grouping() const {return string();}
2766 virtual string_type do_curr_symbol() const {return string_type();}
2767 virtual string_type do_positive_sign() const {return string_type();}
2768 virtual string_type do_negative_sign() const {return string_type(1, '-');}
2769 virtual int do_frac_digits() const {return 0;}
2770 virtual pattern do_pos_format() const
Howard Hinnant9bae2a92012-11-06 21:48:33 +00002771 {pattern __p = {{symbol, sign, none, value}}; return __p;}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002772 virtual pattern do_neg_format() const
Howard Hinnant9bae2a92012-11-06 21:48:33 +00002773 {pattern __p = {{symbol, sign, none, value}}; return __p;}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002774};
2775
2776template <class _CharT, bool _International>
2777locale::id
2778moneypunct<_CharT, _International>::id;
2779
Howard Hinnant0a69fa12012-12-12 21:14:28 +00002780template <class _CharT, bool _International>
2781const bool
2782moneypunct<_CharT, _International>::intl;
2783
Howard Hinnant499cea12013-08-23 17:37:05 +00002784_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS moneypunct<char, false>)
2785_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS moneypunct<char, true>)
2786_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS moneypunct<wchar_t, false>)
2787_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS moneypunct<wchar_t, true>)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002788
2789// moneypunct_byname
2790
2791template <class _CharT, bool _International = false>
Howard Hinnant0f678bd2013-08-12 18:38:34 +00002792class _LIBCPP_TYPE_VIS_ONLY moneypunct_byname
Howard Hinnant82894812010-09-22 16:48:34 +00002793 : public moneypunct<_CharT, _International>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002794{
2795public:
2796 typedef money_base::pattern pattern;
2797 typedef _CharT char_type;
2798 typedef basic_string<char_type> string_type;
2799
2800 _LIBCPP_ALWAYS_INLINE
2801 explicit moneypunct_byname(const char* __nm, size_t __refs = 0)
2802 : moneypunct<_CharT, _International>(__refs) {init(__nm);}
2803
2804 _LIBCPP_ALWAYS_INLINE
2805 explicit moneypunct_byname(const string& __nm, size_t __refs = 0)
2806 : moneypunct<_CharT, _International>(__refs) {init(__nm.c_str());}
2807
2808protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002809 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002810 ~moneypunct_byname() {}
2811
2812 virtual char_type do_decimal_point() const {return __decimal_point_;}
2813 virtual char_type do_thousands_sep() const {return __thousands_sep_;}
2814 virtual string do_grouping() const {return __grouping_;}
2815 virtual string_type do_curr_symbol() const {return __curr_symbol_;}
2816 virtual string_type do_positive_sign() const {return __positive_sign_;}
2817 virtual string_type do_negative_sign() const {return __negative_sign_;}
2818 virtual int do_frac_digits() const {return __frac_digits_;}
2819 virtual pattern do_pos_format() const {return __pos_format_;}
2820 virtual pattern do_neg_format() const {return __neg_format_;}
2821
2822private:
2823 char_type __decimal_point_;
2824 char_type __thousands_sep_;
2825 string __grouping_;
2826 string_type __curr_symbol_;
2827 string_type __positive_sign_;
2828 string_type __negative_sign_;
2829 int __frac_digits_;
2830 pattern __pos_format_;
2831 pattern __neg_format_;
2832
2833 void init(const char*);
2834};
2835
2836template<> void moneypunct_byname<char, false>::init(const char*);
2837template<> void moneypunct_byname<char, true>::init(const char*);
2838template<> void moneypunct_byname<wchar_t, false>::init(const char*);
2839template<> void moneypunct_byname<wchar_t, true>::init(const char*);
2840
Howard Hinnant499cea12013-08-23 17:37:05 +00002841_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS moneypunct_byname<char, false>)
2842_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS moneypunct_byname<char, true>)
2843_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS moneypunct_byname<wchar_t, false>)
2844_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS moneypunct_byname<wchar_t, true>)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002845
2846// money_get
2847
2848template <class _CharT>
2849class __money_get
2850{
2851protected:
2852 typedef _CharT char_type;
2853 typedef basic_string<char_type> string_type;
2854
2855 _LIBCPP_ALWAYS_INLINE __money_get() {}
2856
2857 static void __gather_info(bool __intl, const locale& __loc,
2858 money_base::pattern& __pat, char_type& __dp,
2859 char_type& __ts, string& __grp,
2860 string_type& __sym, string_type& __psn,
2861 string_type& __nsn, int& __fd);
2862};
2863
2864template <class _CharT>
2865void
2866__money_get<_CharT>::__gather_info(bool __intl, const locale& __loc,
2867 money_base::pattern& __pat, char_type& __dp,
2868 char_type& __ts, string& __grp,
2869 string_type& __sym, string_type& __psn,
2870 string_type& __nsn, int& __fd)
2871{
2872 if (__intl)
2873 {
2874 const moneypunct<char_type, true>& __mp =
2875 use_facet<moneypunct<char_type, true> >(__loc);
2876 __pat = __mp.neg_format();
2877 __nsn = __mp.negative_sign();
2878 __psn = __mp.positive_sign();
2879 __dp = __mp.decimal_point();
2880 __ts = __mp.thousands_sep();
2881 __grp = __mp.grouping();
2882 __sym = __mp.curr_symbol();
2883 __fd = __mp.frac_digits();
2884 }
2885 else
2886 {
2887 const moneypunct<char_type, false>& __mp =
2888 use_facet<moneypunct<char_type, false> >(__loc);
2889 __pat = __mp.neg_format();
2890 __nsn = __mp.negative_sign();
2891 __psn = __mp.positive_sign();
2892 __dp = __mp.decimal_point();
2893 __ts = __mp.thousands_sep();
2894 __grp = __mp.grouping();
2895 __sym = __mp.curr_symbol();
2896 __fd = __mp.frac_digits();
2897 }
2898}
2899
Howard Hinnant499cea12013-08-23 17:37:05 +00002900_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS __money_get<char>)
2901_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS __money_get<wchar_t>)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002902
2903template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnant0f678bd2013-08-12 18:38:34 +00002904class _LIBCPP_TYPE_VIS_ONLY money_get
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002905 : public locale::facet,
2906 private __money_get<_CharT>
2907{
2908public:
2909 typedef _CharT char_type;
2910 typedef _InputIterator iter_type;
2911 typedef basic_string<char_type> string_type;
2912
2913 _LIBCPP_ALWAYS_INLINE
2914 explicit money_get(size_t __refs = 0)
2915 : locale::facet(__refs) {}
2916
2917 _LIBCPP_ALWAYS_INLINE
2918 iter_type get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob,
2919 ios_base::iostate& __err, long double& __v) const
2920 {
2921 return do_get(__b, __e, __intl, __iob, __err, __v);
2922 }
2923
2924 _LIBCPP_ALWAYS_INLINE
2925 iter_type get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob,
2926 ios_base::iostate& __err, string_type& __v) const
2927 {
2928 return do_get(__b, __e, __intl, __iob, __err, __v);
2929 }
2930
2931 static locale::id id;
2932
2933protected:
2934
Howard Hinnant82894812010-09-22 16:48:34 +00002935 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002936 ~money_get() {}
Howard Hinnant324bb032010-08-22 00:02:43 +00002937
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002938 virtual iter_type do_get(iter_type __b, iter_type __e, bool __intl,
2939 ios_base& __iob, ios_base::iostate& __err,
2940 long double& __v) const;
2941 virtual iter_type do_get(iter_type __b, iter_type __e, bool __intl,
2942 ios_base& __iob, ios_base::iostate& __err,
2943 string_type& __v) const;
2944
2945private:
2946 static bool __do_get(iter_type& __b, iter_type __e,
2947 bool __intl, const locale& __loc,
2948 ios_base::fmtflags __flags, ios_base::iostate& __err,
2949 bool& __neg, const ctype<char_type>& __ct,
2950 unique_ptr<char_type, void(*)(void*)>& __wb,
2951 char_type*& __wn, char_type* __we);
2952};
2953
2954template <class _CharT, class _InputIterator>
2955locale::id
2956money_get<_CharT, _InputIterator>::id;
2957
Howard Hinnant0f678bd2013-08-12 18:38:34 +00002958_LIBCPP_FUNC_VIS void __do_nothing(void*);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002959
2960template <class _Tp>
2961_LIBCPP_HIDDEN
2962void
2963__double_or_nothing(unique_ptr<_Tp, void(*)(void*)>& __b, _Tp*& __n, _Tp*& __e)
2964{
2965 bool __owns = __b.get_deleter() != __do_nothing;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002966 size_t __cur_cap = static_cast<size_t>(__e-__b.get()) * sizeof(_Tp);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002967 size_t __new_cap = __cur_cap < numeric_limits<size_t>::max() / 2 ?
2968 2 * __cur_cap : numeric_limits<size_t>::max();
Howard Hinnantec3773c2011-12-01 20:21:04 +00002969 size_t __n_off = static_cast<size_t>(__n - __b.get());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002970 _Tp* __t = (_Tp*)realloc(__owns ? __b.get() : 0, __new_cap);
2971 if (__t == 0)
2972 __throw_bad_alloc();
2973 if (__owns)
2974 __b.release();
2975 __b = unique_ptr<_Tp, void(*)(void*)>(__t, free);
2976 __new_cap /= sizeof(_Tp);
2977 __n = __b.get() + __n_off;
2978 __e = __b.get() + __new_cap;
2979}
2980
2981// true == success
2982template <class _CharT, class _InputIterator>
2983bool
2984money_get<_CharT, _InputIterator>::__do_get(iter_type& __b, iter_type __e,
2985 bool __intl, const locale& __loc,
2986 ios_base::fmtflags __flags,
2987 ios_base::iostate& __err,
2988 bool& __neg,
2989 const ctype<char_type>& __ct,
2990 unique_ptr<char_type, void(*)(void*)>& __wb,
2991 char_type*& __wn, char_type* __we)
2992{
2993 const unsigned __bz = 100;
2994 unsigned __gbuf[__bz];
2995 unique_ptr<unsigned, void(*)(void*)> __gb(__gbuf, __do_nothing);
2996 unsigned* __gn = __gb.get();
2997 unsigned* __ge = __gn + __bz;
2998 money_base::pattern __pat;
2999 char_type __dp;
3000 char_type __ts;
3001 string __grp;
3002 string_type __sym;
3003 string_type __psn;
3004 string_type __nsn;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00003005 // Capture the spaces read into money_base::{space,none} so they
3006 // can be compared to initial spaces in __sym.
3007 string_type __spaces;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003008 int __fd;
3009 __money_get<_CharT>::__gather_info(__intl, __loc, __pat, __dp, __ts, __grp,
3010 __sym, __psn, __nsn, __fd);
3011 const string_type* __trailing_sign = 0;
3012 __wn = __wb.get();
3013 for (unsigned __p = 0; __p < 4 && __b != __e; ++__p)
3014 {
3015 switch (__pat.field[__p])
3016 {
3017 case money_base::space:
3018 if (__p != 3)
3019 {
3020 if (__ct.is(ctype_base::space, *__b))
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00003021 __spaces.push_back(*__b++);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003022 else
3023 {
3024 __err |= ios_base::failbit;
3025 return false;
3026 }
3027 }
Howard Hinnant324bb032010-08-22 00:02:43 +00003028 // drop through
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003029 case money_base::none:
3030 if (__p != 3)
3031 {
3032 while (__b != __e && __ct.is(ctype_base::space, *__b))
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00003033 __spaces.push_back(*__b++);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003034 }
3035 break;
3036 case money_base::sign:
3037 if (__psn.size() + __nsn.size() > 0)
3038 {
3039 if (__psn.size() == 0 || __nsn.size() == 0)
3040 { // sign is optional
3041 if (__psn.size() > 0)
3042 { // __nsn.size() == 0
3043 if (*__b == __psn[0])
3044 {
3045 ++__b;
3046 if (__psn.size() > 1)
3047 __trailing_sign = &__psn;
3048 }
3049 else
3050 __neg = true;
3051 }
3052 else if (*__b == __nsn[0]) // __nsn.size() > 0 && __psn.size() == 0
3053 {
3054 ++__b;
3055 __neg = true;
3056 if (__nsn.size() > 1)
3057 __trailing_sign = &__nsn;
3058 }
3059 }
3060 else // sign is required
3061 {
3062 if (*__b == __psn[0])
3063 {
3064 ++__b;
3065 if (__psn.size() > 1)
3066 __trailing_sign = &__psn;
3067 }
3068 else if (*__b == __nsn[0])
3069 {
3070 ++__b;
3071 __neg = true;
3072 if (__nsn.size() > 1)
3073 __trailing_sign = &__nsn;
3074 }
3075 else
3076 {
3077 __err |= ios_base::failbit;
3078 return false;
3079 }
3080 }
3081 }
3082 break;
3083 case money_base::symbol:
3084 {
3085 bool __more_needed = __trailing_sign ||
3086 (__p < 2) ||
3087 (__p == 2 && __pat.field[3] != static_cast<char>(money_base::none));
Marshall Clow9de3d4c2013-10-13 01:02:45 +00003088 bool __sb = (__flags & ios_base::showbase) != 0;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003089 if (__sb || __more_needed)
3090 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00003091 typename string_type::const_iterator __sym_space_end = __sym.begin();
3092 if (__p > 0 && (__pat.field[__p - 1] == money_base::none ||
3093 __pat.field[__p - 1] == money_base::space)) {
3094 // Match spaces we've already read against spaces at
3095 // the beginning of __sym.
3096 while (__sym_space_end != __sym.end() &&
3097 __ct.is(ctype_base::space, *__sym_space_end))
3098 ++__sym_space_end;
3099 const size_t __num_spaces = __sym_space_end - __sym.begin();
3100 if (__num_spaces > __spaces.size() ||
3101 !equal(__spaces.end() - __num_spaces, __spaces.end(),
3102 __sym.begin())) {
3103 // No match. Put __sym_space_end back at the
3104 // beginning of __sym, which will prevent a
3105 // match in the next loop.
3106 __sym_space_end = __sym.begin();
3107 }
3108 }
3109 typename string_type::const_iterator __sym_curr_char = __sym_space_end;
3110 while (__sym_curr_char != __sym.end() && __b != __e &&
3111 *__b == *__sym_curr_char) {
3112 ++__b;
3113 ++__sym_curr_char;
3114 }
3115 if (__sb && __sym_curr_char != __sym.end())
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003116 {
3117 __err |= ios_base::failbit;
3118 return false;
3119 }
3120 }
3121 }
3122 break;
3123 case money_base::value:
3124 {
3125 unsigned __ng = 0;
3126 for (; __b != __e; ++__b)
3127 {
3128 char_type __c = *__b;
3129 if (__ct.is(ctype_base::digit, __c))
3130 {
3131 if (__wn == __we)
3132 __double_or_nothing(__wb, __wn, __we);
3133 *__wn++ = __c;
3134 ++__ng;
3135 }
3136 else if (__grp.size() > 0 && __ng > 0 && __c == __ts)
3137 {
3138 if (__gn == __ge)
3139 __double_or_nothing(__gb, __gn, __ge);
3140 *__gn++ = __ng;
3141 __ng = 0;
3142 }
3143 else
3144 break;
3145 }
3146 if (__gb.get() != __gn && __ng > 0)
3147 {
3148 if (__gn == __ge)
3149 __double_or_nothing(__gb, __gn, __ge);
3150 *__gn++ = __ng;
3151 }
3152 if (__fd > 0)
3153 {
3154 if (__b == __e || *__b != __dp)
3155 {
3156 __err |= ios_base::failbit;
3157 return false;
3158 }
3159 for (++__b; __fd > 0; --__fd, ++__b)
3160 {
3161 if (__b == __e || !__ct.is(ctype_base::digit, *__b))
3162 {
3163 __err |= ios_base::failbit;
3164 return false;
3165 }
3166 if (__wn == __we)
3167 __double_or_nothing(__wb, __wn, __we);
3168 *__wn++ = *__b;
3169 }
3170 }
3171 if (__wn == __wb.get())
3172 {
3173 __err |= ios_base::failbit;
3174 return false;
3175 }
3176 }
3177 break;
3178 }
3179 }
3180 if (__trailing_sign)
3181 {
3182 for (unsigned __i = 1; __i < __trailing_sign->size(); ++__i, ++__b)
3183 {
3184 if (__b == __e || *__b != (*__trailing_sign)[__i])
3185 {
3186 __err |= ios_base::failbit;
3187 return false;
3188 }
3189 }
3190 }
3191 if (__gb.get() != __gn)
3192 {
3193 ios_base::iostate __et = ios_base::goodbit;
3194 __check_grouping(__grp, __gb.get(), __gn, __et);
3195 if (__et)
3196 {
3197 __err |= ios_base::failbit;
3198 return false;
3199 }
3200 }
3201 return true;
3202}
3203
3204template <class _CharT, class _InputIterator>
3205_InputIterator
3206money_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
3207 bool __intl, ios_base& __iob,
3208 ios_base::iostate& __err,
3209 long double& __v) const
3210{
Howard Hinnantec3773c2011-12-01 20:21:04 +00003211 const int __bz = 100;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003212 char_type __wbuf[__bz];
3213 unique_ptr<char_type, void(*)(void*)> __wb(__wbuf, __do_nothing);
3214 char_type* __wn;
3215 char_type* __we = __wbuf + __bz;
3216 locale __loc = __iob.getloc();
3217 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3218 bool __neg = false;
3219 if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct,
3220 __wb, __wn, __we))
3221 {
3222 const char __src[] = "0123456789";
3223 char_type __atoms[sizeof(__src)-1];
3224 __ct.widen(__src, __src + (sizeof(__src)-1), __atoms);
3225 char __nbuf[__bz];
3226 char* __nc = __nbuf;
3227 unique_ptr<char, void(*)(void*)> __h(0, free);
3228 if (__wn - __wb.get() > __bz-2)
3229 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00003230 __h.reset((char*)malloc(static_cast<size_t>(__wn - __wb.get() + 2)));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003231 if (__h.get() == 0)
3232 __throw_bad_alloc();
3233 __nc = __h.get();
3234 }
3235 if (__neg)
3236 *__nc++ = '-';
3237 for (const char_type* __w = __wb.get(); __w < __wn; ++__w, ++__nc)
Marshall Clow9b145da2013-03-22 02:14:40 +00003238 *__nc = __src[find(__atoms, _VSTD::end(__atoms), *__w) - __atoms];
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003239 *__nc = char();
3240 if (sscanf(__nbuf, "%Lf", &__v) != 1)
3241 __throw_runtime_error("money_get error");
3242 }
3243 if (__b == __e)
3244 __err |= ios_base::eofbit;
3245 return __b;
3246}
3247
3248template <class _CharT, class _InputIterator>
3249_InputIterator
3250money_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
3251 bool __intl, ios_base& __iob,
3252 ios_base::iostate& __err,
3253 string_type& __v) const
3254{
Howard Hinnantec3773c2011-12-01 20:21:04 +00003255 const int __bz = 100;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003256 char_type __wbuf[__bz];
3257 unique_ptr<char_type, void(*)(void*)> __wb(__wbuf, __do_nothing);
3258 char_type* __wn;
3259 char_type* __we = __wbuf + __bz;
3260 locale __loc = __iob.getloc();
3261 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3262 bool __neg = false;
3263 if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct,
3264 __wb, __wn, __we))
3265 {
3266 __v.clear();
3267 if (__neg)
3268 __v.push_back(__ct.widen('-'));
3269 char_type __z = __ct.widen('0');
3270 char_type* __w;
3271 for (__w = __wb.get(); __w < __wn-1; ++__w)
3272 if (*__w != __z)
3273 break;
3274 __v.append(__w, __wn);
3275 }
3276 if (__b == __e)
3277 __err |= ios_base::eofbit;
3278 return __b;
3279}
3280
Howard Hinnant499cea12013-08-23 17:37:05 +00003281_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS money_get<char>)
3282_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS money_get<wchar_t>)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003283
3284// money_put
3285
3286template <class _CharT>
3287class __money_put
3288{
3289protected:
3290 typedef _CharT char_type;
3291 typedef basic_string<char_type> string_type;
3292
3293 _LIBCPP_ALWAYS_INLINE __money_put() {}
3294
3295 static void __gather_info(bool __intl, bool __neg, const locale& __loc,
3296 money_base::pattern& __pat, char_type& __dp,
3297 char_type& __ts, string& __grp,
3298 string_type& __sym, string_type& __sn,
3299 int& __fd);
3300 static void __format(char_type* __mb, char_type*& __mi, char_type*& __me,
3301 ios_base::fmtflags __flags,
3302 const char_type* __db, const char_type* __de,
3303 const ctype<char_type>& __ct, bool __neg,
3304 const money_base::pattern& __pat, char_type __dp,
3305 char_type __ts, const string& __grp,
3306 const string_type& __sym, const string_type& __sn,
3307 int __fd);
3308};
3309
3310template <class _CharT>
3311void
3312__money_put<_CharT>::__gather_info(bool __intl, bool __neg, const locale& __loc,
3313 money_base::pattern& __pat, char_type& __dp,
3314 char_type& __ts, string& __grp,
3315 string_type& __sym, string_type& __sn,
3316 int& __fd)
3317{
3318 if (__intl)
3319 {
3320 const moneypunct<char_type, true>& __mp =
3321 use_facet<moneypunct<char_type, true> >(__loc);
3322 if (__neg)
3323 {
3324 __pat = __mp.neg_format();
3325 __sn = __mp.negative_sign();
3326 }
3327 else
3328 {
3329 __pat = __mp.pos_format();
3330 __sn = __mp.positive_sign();
3331 }
3332 __dp = __mp.decimal_point();
3333 __ts = __mp.thousands_sep();
3334 __grp = __mp.grouping();
3335 __sym = __mp.curr_symbol();
3336 __fd = __mp.frac_digits();
3337 }
3338 else
3339 {
3340 const moneypunct<char_type, false>& __mp =
3341 use_facet<moneypunct<char_type, false> >(__loc);
3342 if (__neg)
3343 {
3344 __pat = __mp.neg_format();
3345 __sn = __mp.negative_sign();
3346 }
3347 else
3348 {
3349 __pat = __mp.pos_format();
3350 __sn = __mp.positive_sign();
3351 }
3352 __dp = __mp.decimal_point();
3353 __ts = __mp.thousands_sep();
3354 __grp = __mp.grouping();
3355 __sym = __mp.curr_symbol();
3356 __fd = __mp.frac_digits();
3357 }
3358}
3359
3360template <class _CharT>
3361void
3362__money_put<_CharT>::__format(char_type* __mb, char_type*& __mi, char_type*& __me,
3363 ios_base::fmtflags __flags,
3364 const char_type* __db, const char_type* __de,
3365 const ctype<char_type>& __ct, bool __neg,
3366 const money_base::pattern& __pat, char_type __dp,
3367 char_type __ts, const string& __grp,
3368 const string_type& __sym, const string_type& __sn,
3369 int __fd)
3370{
3371 __me = __mb;
3372 for (unsigned __p = 0; __p < 4; ++__p)
3373 {
3374 switch (__pat.field[__p])
3375 {
3376 case money_base::none:
3377 __mi = __me;
3378 break;
3379 case money_base::space:
3380 __mi = __me;
3381 *__me++ = __ct.widen(' ');
3382 break;
3383 case money_base::sign:
3384 if (!__sn.empty())
3385 *__me++ = __sn[0];
3386 break;
3387 case money_base::symbol:
3388 if (!__sym.empty() && (__flags & ios_base::showbase))
Howard Hinnant0949eed2011-06-30 21:18:19 +00003389 __me = _VSTD::copy(__sym.begin(), __sym.end(), __me);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003390 break;
3391 case money_base::value:
3392 {
3393 // remember start of value so we can reverse it
3394 char_type* __t = __me;
3395 // find beginning of digits
3396 if (__neg)
3397 ++__db;
3398 // find end of digits
3399 const char_type* __d;
3400 for (__d = __db; __d < __de; ++__d)
3401 if (!__ct.is(ctype_base::digit, *__d))
3402 break;
3403 // print fractional part
3404 if (__fd > 0)
3405 {
3406 int __f;
3407 for (__f = __fd; __d > __db && __f > 0; --__f)
3408 *__me++ = *--__d;
3409 char_type __z = __f > 0 ? __ct.widen('0') : char_type();
3410 for (; __f > 0; --__f)
3411 *__me++ = __z;
3412 *__me++ = __dp;
3413 }
3414 // print units part
3415 if (__d == __db)
3416 {
3417 *__me++ = __ct.widen('0');
3418 }
3419 else
3420 {
3421 unsigned __ng = 0;
3422 unsigned __ig = 0;
3423 unsigned __gl = __grp.empty() ? numeric_limits<unsigned>::max()
3424 : static_cast<unsigned>(__grp[__ig]);
3425 while (__d != __db)
3426 {
3427 if (__ng == __gl)
3428 {
3429 *__me++ = __ts;
3430 __ng = 0;
3431 if (++__ig < __grp.size())
3432 __gl = __grp[__ig] == numeric_limits<char>::max() ?
3433 numeric_limits<unsigned>::max() :
3434 static_cast<unsigned>(__grp[__ig]);
3435 }
3436 *__me++ = *--__d;
3437 ++__ng;
3438 }
3439 }
3440 // reverse it
3441 reverse(__t, __me);
3442 }
3443 break;
3444 }
3445 }
3446 // print rest of sign, if any
3447 if (__sn.size() > 1)
Howard Hinnant0949eed2011-06-30 21:18:19 +00003448 __me = _VSTD::copy(__sn.begin()+1, __sn.end(), __me);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003449 // set alignment
3450 if ((__flags & ios_base::adjustfield) == ios_base::left)
3451 __mi = __me;
3452 else if ((__flags & ios_base::adjustfield) != ios_base::internal)
3453 __mi = __mb;
3454}
3455
Howard Hinnant499cea12013-08-23 17:37:05 +00003456_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS __money_put<char>)
3457_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS __money_put<wchar_t>)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003458
3459template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant0f678bd2013-08-12 18:38:34 +00003460class _LIBCPP_TYPE_VIS_ONLY money_put
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003461 : public locale::facet,
3462 private __money_put<_CharT>
3463{
3464public:
3465 typedef _CharT char_type;
3466 typedef _OutputIterator iter_type;
3467 typedef basic_string<char_type> string_type;
3468
3469 _LIBCPP_ALWAYS_INLINE
3470 explicit money_put(size_t __refs = 0)
3471 : locale::facet(__refs) {}
3472
3473 _LIBCPP_ALWAYS_INLINE
3474 iter_type put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl,
3475 long double __units) const
3476 {
3477 return do_put(__s, __intl, __iob, __fl, __units);
3478 }
3479
3480 _LIBCPP_ALWAYS_INLINE
3481 iter_type put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl,
3482 const string_type& __digits) const
3483 {
3484 return do_put(__s, __intl, __iob, __fl, __digits);
3485 }
3486
3487 static locale::id id;
3488
3489protected:
Howard Hinnant82894812010-09-22 16:48:34 +00003490 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003491 ~money_put() {}
3492
3493 virtual iter_type do_put(iter_type __s, bool __intl, ios_base& __iob,
3494 char_type __fl, long double __units) const;
3495 virtual iter_type do_put(iter_type __s, bool __intl, ios_base& __iob,
3496 char_type __fl, const string_type& __digits) const;
3497};
3498
3499template <class _CharT, class _OutputIterator>
3500locale::id
3501money_put<_CharT, _OutputIterator>::id;
3502
3503template <class _CharT, class _OutputIterator>
3504_OutputIterator
3505money_put<_CharT, _OutputIterator>::do_put(iter_type __s, bool __intl,
3506 ios_base& __iob, char_type __fl,
3507 long double __units) const
3508{
3509 // convert to char
3510 const size_t __bs = 100;
3511 char __buf[__bs];
3512 char* __bb = __buf;
3513 char_type __digits[__bs];
3514 char_type* __db = __digits;
Howard Hinnantec3773c2011-12-01 20:21:04 +00003515 size_t __n = static_cast<size_t>(snprintf(__bb, __bs, "%.0Lf", __units));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003516 unique_ptr<char, void(*)(void*)> __hn(0, free);
3517 unique_ptr<char_type, void(*)(void*)> __hd(0, free);
3518 // secure memory for digit storage
3519 if (__n > __bs-1)
3520 {
Howard Hinnant866569b2011-09-28 23:39:33 +00003521#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00003522 __n = static_cast<size_t>(asprintf_l(&__bb, _LIBCPP_GET_C_LOCALE, "%.0Lf", __units));
Sean Huntf3907e62011-07-15 05:40:33 +00003523#else
3524 __n = __asprintf_l(&__bb, __cloc(), "%.0Lf", __units);
3525#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003526 if (__bb == 0)
3527 __throw_bad_alloc();
3528 __hn.reset(__bb);
3529 __hd.reset((char_type*)malloc(__n * sizeof(char_type)));
Howard Hinnant05b57d52012-03-07 20:37:43 +00003530 if (__hd == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003531 __throw_bad_alloc();
3532 __db = __hd.get();
3533 }
3534 // gather info
3535 locale __loc = __iob.getloc();
3536 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3537 __ct.widen(__bb, __bb + __n, __db);
3538 bool __neg = __n > 0 && __bb[0] == '-';
3539 money_base::pattern __pat;
3540 char_type __dp;
3541 char_type __ts;
3542 string __grp;
3543 string_type __sym;
3544 string_type __sn;
3545 int __fd;
3546 this->__gather_info(__intl, __neg, __loc, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3547 // secure memory for formatting
3548 char_type __mbuf[__bs];
3549 char_type* __mb = __mbuf;
3550 unique_ptr<char_type, void(*)(void*)> __hw(0, free);
3551 size_t __exn = static_cast<int>(__n) > __fd ?
Howard Hinnantec3773c2011-12-01 20:21:04 +00003552 (__n - static_cast<size_t>(__fd)) * 2 + __sn.size() +
3553 __sym.size() + static_cast<size_t>(__fd) + 1
3554 : __sn.size() + __sym.size() + static_cast<size_t>(__fd) + 2;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003555 if (__exn > __bs)
3556 {
3557 __hw.reset((char_type*)malloc(__exn * sizeof(char_type)));
3558 __mb = __hw.get();
3559 if (__mb == 0)
3560 __throw_bad_alloc();
3561 }
3562 // format
3563 char_type* __mi;
3564 char_type* __me;
3565 this->__format(__mb, __mi, __me, __iob.flags(),
3566 __db, __db + __n, __ct,
3567 __neg, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3568 return __pad_and_output(__s, __mb, __mi, __me, __iob, __fl);
3569}
3570
3571template <class _CharT, class _OutputIterator>
3572_OutputIterator
3573money_put<_CharT, _OutputIterator>::do_put(iter_type __s, bool __intl,
3574 ios_base& __iob, char_type __fl,
3575 const string_type& __digits) const
3576{
3577 // gather info
3578 locale __loc = __iob.getloc();
3579 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3580 bool __neg = __digits.size() > 0 && __digits[0] == __ct.widen('-');
3581 money_base::pattern __pat;
3582 char_type __dp;
3583 char_type __ts;
3584 string __grp;
3585 string_type __sym;
3586 string_type __sn;
3587 int __fd;
3588 this->__gather_info(__intl, __neg, __loc, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3589 // secure memory for formatting
3590 char_type __mbuf[100];
3591 char_type* __mb = __mbuf;
3592 unique_ptr<char_type, void(*)(void*)> __h(0, free);
Howard Hinnantec3773c2011-12-01 20:21:04 +00003593 size_t __exn = static_cast<int>(__digits.size()) > __fd ?
3594 (__digits.size() - static_cast<size_t>(__fd)) * 2 +
3595 __sn.size() + __sym.size() + static_cast<size_t>(__fd) + 1
3596 : __sn.size() + __sym.size() + static_cast<size_t>(__fd) + 2;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003597 if (__exn > 100)
3598 {
3599 __h.reset((char_type*)malloc(__exn * sizeof(char_type)));
3600 __mb = __h.get();
3601 if (__mb == 0)
3602 __throw_bad_alloc();
3603 }
3604 // format
3605 char_type* __mi;
3606 char_type* __me;
3607 this->__format(__mb, __mi, __me, __iob.flags(),
3608 __digits.data(), __digits.data() + __digits.size(), __ct,
3609 __neg, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3610 return __pad_and_output(__s, __mb, __mi, __me, __iob, __fl);
3611}
3612
Howard Hinnant499cea12013-08-23 17:37:05 +00003613_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS money_put<char>)
3614_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS money_put<wchar_t>)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003615
3616// messages
3617
Howard Hinnant83eade62013-03-06 23:30:19 +00003618class _LIBCPP_TYPE_VIS messages_base
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003619{
3620public:
Howard Hinnantb2080c72011-02-25 00:51:08 +00003621 typedef ptrdiff_t catalog;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003622
3623 _LIBCPP_ALWAYS_INLINE messages_base() {}
3624};
3625
3626template <class _CharT>
Howard Hinnant0f678bd2013-08-12 18:38:34 +00003627class _LIBCPP_TYPE_VIS_ONLY messages
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003628 : public locale::facet,
3629 public messages_base
3630{
3631public:
3632 typedef _CharT char_type;
3633 typedef basic_string<_CharT> string_type;
3634
3635 _LIBCPP_ALWAYS_INLINE
3636 explicit messages(size_t __refs = 0)
3637 : locale::facet(__refs) {}
3638
3639 _LIBCPP_ALWAYS_INLINE
3640 catalog open(const basic_string<char>& __nm, const locale& __loc) const
3641 {
3642 return do_open(__nm, __loc);
3643 }
3644
3645 _LIBCPP_ALWAYS_INLINE
3646 string_type get(catalog __c, int __set, int __msgid,
3647 const string_type& __dflt) const
3648 {
3649 return do_get(__c, __set, __msgid, __dflt);
3650 }
3651
3652 _LIBCPP_ALWAYS_INLINE
3653 void close(catalog __c) const
3654 {
3655 do_close(__c);
3656 }
3657
3658 static locale::id id;
3659
3660protected:
Howard Hinnant82894812010-09-22 16:48:34 +00003661 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003662 ~messages() {}
3663
3664 virtual catalog do_open(const basic_string<char>&, const locale&) const;
3665 virtual string_type do_get(catalog, int __set, int __msgid,
3666 const string_type& __dflt) const;
3667 virtual void do_close(catalog) const;
3668};
3669
3670template <class _CharT>
3671locale::id
3672messages<_CharT>::id;
3673
3674template <class _CharT>
3675typename messages<_CharT>::catalog
3676messages<_CharT>::do_open(const basic_string<char>& __nm, const locale&) const
3677{
Marshall Clowa22d2ad2013-03-18 17:04:29 +00003678#ifdef _WIN32
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00003679 return -1;
3680#else // _WIN32
Howard Hinnant11624452011-10-11 16:00:46 +00003681 catalog __cat = (catalog)catopen(__nm.c_str(), NL_CAT_LOCALE);
Howard Hinnantb2080c72011-02-25 00:51:08 +00003682 if (__cat != -1)
3683 __cat = static_cast<catalog>((static_cast<size_t>(__cat) >> 1));
3684 return __cat;
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00003685#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003686}
3687
3688template <class _CharT>
3689typename messages<_CharT>::string_type
3690messages<_CharT>::do_get(catalog __c, int __set, int __msgid,
3691 const string_type& __dflt) const
3692{
Marshall Clowa22d2ad2013-03-18 17:04:29 +00003693#ifdef _WIN32
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00003694 return __dflt;
3695#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003696 string __ndflt;
3697 __narrow_to_utf8<sizeof(char_type)*__CHAR_BIT__>()(back_inserter(__ndflt),
3698 __dflt.c_str(),
3699 __dflt.c_str() + __dflt.size());
Howard Hinnantb2080c72011-02-25 00:51:08 +00003700 if (__c != -1)
3701 __c <<= 1;
Howard Hinnant11624452011-10-11 16:00:46 +00003702 nl_catd __cat = (nl_catd)__c;
Howard Hinnantb2080c72011-02-25 00:51:08 +00003703 char* __n = catgets(__cat, __set, __msgid, __ndflt.c_str());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003704 string_type __w;
3705 __widen_from_utf8<sizeof(char_type)*__CHAR_BIT__>()(back_inserter(__w),
3706 __n, __n + strlen(__n));
3707 return __w;
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00003708#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003709}
3710
3711template <class _CharT>
3712void
3713messages<_CharT>::do_close(catalog __c) const
3714{
Marshall Clowa22d2ad2013-03-18 17:04:29 +00003715#if !defined(_WIN32)
Howard Hinnantb2080c72011-02-25 00:51:08 +00003716 if (__c != -1)
3717 __c <<= 1;
Howard Hinnant11624452011-10-11 16:00:46 +00003718 nl_catd __cat = (nl_catd)__c;
Howard Hinnantb2080c72011-02-25 00:51:08 +00003719 catclose(__cat);
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00003720#endif // !_WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003721}
3722
Howard Hinnant499cea12013-08-23 17:37:05 +00003723_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS messages<char>)
3724_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS messages<wchar_t>)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003725
3726template <class _CharT>
Howard Hinnant0f678bd2013-08-12 18:38:34 +00003727class _LIBCPP_TYPE_VIS_ONLY messages_byname
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003728 : public messages<_CharT>
3729{
3730public:
3731 typedef messages_base::catalog catalog;
3732 typedef basic_string<_CharT> string_type;
3733
3734 _LIBCPP_ALWAYS_INLINE
3735 explicit messages_byname(const char*, size_t __refs = 0)
3736 : messages<_CharT>(__refs) {}
3737
3738 _LIBCPP_ALWAYS_INLINE
3739 explicit messages_byname(const string&, size_t __refs = 0)
3740 : messages<_CharT>(__refs) {}
3741
3742protected:
Howard Hinnant82894812010-09-22 16:48:34 +00003743 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003744 ~messages_byname() {}
3745};
3746
Howard Hinnant499cea12013-08-23 17:37:05 +00003747_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS messages_byname<char>)
3748_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS messages_byname<wchar_t>)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003749
Howard Hinnantd23b4642010-05-31 20:58:54 +00003750template<class _Codecvt, class _Elem = wchar_t,
3751 class _Wide_alloc = allocator<_Elem>,
3752 class _Byte_alloc = allocator<char> >
Howard Hinnant0f678bd2013-08-12 18:38:34 +00003753class _LIBCPP_TYPE_VIS_ONLY wstring_convert
Howard Hinnantd23b4642010-05-31 20:58:54 +00003754{
3755public:
3756 typedef basic_string<char, char_traits<char>, _Byte_alloc> byte_string;
3757 typedef basic_string<_Elem, char_traits<_Elem>, _Wide_alloc> wide_string;
3758 typedef typename _Codecvt::state_type state_type;
3759 typedef typename wide_string::traits_type::int_type int_type;
3760
3761private:
3762 byte_string __byte_err_string_;
3763 wide_string __wide_err_string_;
3764 _Codecvt* __cvtptr_;
3765 state_type __cvtstate_;
3766 size_t __cvtcount_;
3767
3768 wstring_convert(const wstring_convert& __wc);
3769 wstring_convert& operator=(const wstring_convert& __wc);
3770public:
Marshall Clow83179a72013-08-27 20:18:59 +00003771 _LIBCPP_EXPLICIT_AFTER_CXX11 wstring_convert(_Codecvt* __pcvt = new _Codecvt);
Howard Hinnantd23b4642010-05-31 20:58:54 +00003772 wstring_convert(_Codecvt* __pcvt, state_type __state);
Marshall Clow83179a72013-08-27 20:18:59 +00003773 _LIBCPP_EXPLICIT_AFTER_CXX11 wstring_convert(const byte_string& __byte_err,
Howard Hinnantd23b4642010-05-31 20:58:54 +00003774 const wide_string& __wide_err = wide_string());
Howard Hinnant73d21a42010-09-04 23:28:19 +00003775#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantd23b4642010-05-31 20:58:54 +00003776 wstring_convert(wstring_convert&& __wc);
3777#endif
3778 ~wstring_convert();
3779
Howard Hinnant82894812010-09-22 16:48:34 +00003780 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003781 wide_string from_bytes(char __byte)
3782 {return from_bytes(&__byte, &__byte+1);}
Howard Hinnant82894812010-09-22 16:48:34 +00003783 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003784 wide_string from_bytes(const char* __ptr)
3785 {return from_bytes(__ptr, __ptr + char_traits<char>::length(__ptr));}
Howard Hinnant82894812010-09-22 16:48:34 +00003786 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003787 wide_string from_bytes(const byte_string& __str)
3788 {return from_bytes(__str.data(), __str.data() + __str.size());}
3789 wide_string from_bytes(const char* __first, const char* __last);
3790
Howard Hinnant82894812010-09-22 16:48:34 +00003791 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003792 byte_string to_bytes(_Elem __wchar)
3793 {return to_bytes(&__wchar, &__wchar+1);}
Howard Hinnant82894812010-09-22 16:48:34 +00003794 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003795 byte_string to_bytes(const _Elem* __wptr)
3796 {return to_bytes(__wptr, __wptr + char_traits<_Elem>::length(__wptr));}
Howard Hinnant82894812010-09-22 16:48:34 +00003797 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003798 byte_string to_bytes(const wide_string& __wstr)
3799 {return to_bytes(__wstr.data(), __wstr.data() + __wstr.size());}
3800 byte_string to_bytes(const _Elem* __first, const _Elem* __last);
3801
Howard Hinnant82894812010-09-22 16:48:34 +00003802 _LIBCPP_ALWAYS_INLINE
Marshall Clow83179a72013-08-27 20:18:59 +00003803 size_t converted() const _NOEXCEPT {return __cvtcount_;}
Howard Hinnant82894812010-09-22 16:48:34 +00003804 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003805 state_type state() const {return __cvtstate_;}
3806};
3807
3808template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Howard Hinnant82894812010-09-22 16:48:34 +00003809inline _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003810wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3811 wstring_convert(_Codecvt* __pcvt)
3812 : __cvtptr_(__pcvt), __cvtstate_(), __cvtcount_(0)
3813{
3814}
3815
3816template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Howard Hinnant82894812010-09-22 16:48:34 +00003817inline _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003818wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3819 wstring_convert(_Codecvt* __pcvt, state_type __state)
3820 : __cvtptr_(__pcvt), __cvtstate_(__state), __cvtcount_(0)
3821{
3822}
3823
3824template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3825wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3826 wstring_convert(const byte_string& __byte_err, const wide_string& __wide_err)
3827 : __byte_err_string_(__byte_err), __wide_err_string_(__wide_err),
3828 __cvtstate_(), __cvtcount_(0)
3829{
3830 __cvtptr_ = new _Codecvt;
3831}
3832
Howard Hinnant73d21a42010-09-04 23:28:19 +00003833#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantd23b4642010-05-31 20:58:54 +00003834
3835template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Howard Hinnant82894812010-09-22 16:48:34 +00003836inline _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003837wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3838 wstring_convert(wstring_convert&& __wc)
Howard Hinnant0949eed2011-06-30 21:18:19 +00003839 : __byte_err_string_(_VSTD::move(__wc.__byte_err_string_)),
3840 __wide_err_string_(_VSTD::move(__wc.__wide_err_string_)),
Howard Hinnantd23b4642010-05-31 20:58:54 +00003841 __cvtptr_(__wc.__cvtptr_),
3842 __cvtstate_(__wc.__cvtstate_), __cvtcount_(__wc.__cvtstate_)
3843{
3844 __wc.__cvtptr_ = nullptr;
3845}
3846
Howard Hinnantbfd55302010-09-04 23:46:48 +00003847#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantd23b4642010-05-31 20:58:54 +00003848
3849template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3850wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::~wstring_convert()
3851{
3852 delete __cvtptr_;
3853}
3854
3855template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3856typename wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::wide_string
3857wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3858 from_bytes(const char* __frm, const char* __frm_end)
3859{
3860 __cvtcount_ = 0;
3861 if (__cvtptr_ != nullptr)
3862 {
3863 wide_string __ws(2*(__frm_end - __frm), _Elem());
Howard Hinnant1ca23672012-07-12 18:07:41 +00003864 if (__frm != __frm_end)
3865 __ws.resize(__ws.capacity());
Howard Hinnantd23b4642010-05-31 20:58:54 +00003866 codecvt_base::result __r = codecvt_base::ok;
3867 state_type __st = __cvtstate_;
3868 if (__frm != __frm_end)
3869 {
3870 _Elem* __to = &__ws[0];
3871 _Elem* __to_end = __to + __ws.size();
3872 const char* __frm_nxt;
3873 do
3874 {
3875 _Elem* __to_nxt;
3876 __r = __cvtptr_->in(__st, __frm, __frm_end, __frm_nxt,
3877 __to, __to_end, __to_nxt);
3878 __cvtcount_ += __frm_nxt - __frm;
3879 if (__frm_nxt == __frm)
3880 {
3881 __r = codecvt_base::error;
3882 }
3883 else if (__r == codecvt_base::noconv)
3884 {
3885 __ws.resize(__to - &__ws[0]);
3886 // This only gets executed if _Elem is char
3887 __ws.append((const _Elem*)__frm, (const _Elem*)__frm_end);
3888 __frm = __frm_nxt;
3889 __r = codecvt_base::ok;
3890 }
3891 else if (__r == codecvt_base::ok)
3892 {
3893 __ws.resize(__to_nxt - &__ws[0]);
3894 __frm = __frm_nxt;
3895 }
3896 else if (__r == codecvt_base::partial)
3897 {
3898 ptrdiff_t __s = __to_nxt - &__ws[0];
3899 __ws.resize(2 * __s);
3900 __to = &__ws[0] + __s;
3901 __to_end = &__ws[0] + __ws.size();
3902 __frm = __frm_nxt;
3903 }
3904 } while (__r == codecvt_base::partial && __frm_nxt < __frm_end);
3905 }
3906 if (__r == codecvt_base::ok)
3907 return __ws;
3908 }
Howard Hinnantd4444702010-08-11 17:04:31 +00003909#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00003910 if (__wide_err_string_.empty())
3911 throw range_error("wstring_convert: from_bytes error");
Howard Hinnant324bb032010-08-22 00:02:43 +00003912#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00003913 return __wide_err_string_;
3914}
3915
3916template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3917typename wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::byte_string
3918wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3919 to_bytes(const _Elem* __frm, const _Elem* __frm_end)
3920{
3921 __cvtcount_ = 0;
3922 if (__cvtptr_ != nullptr)
3923 {
3924 byte_string __bs(2*(__frm_end - __frm), char());
Howard Hinnant1ca23672012-07-12 18:07:41 +00003925 if (__frm != __frm_end)
3926 __bs.resize(__bs.capacity());
Howard Hinnantd23b4642010-05-31 20:58:54 +00003927 codecvt_base::result __r = codecvt_base::ok;
3928 state_type __st = __cvtstate_;
3929 if (__frm != __frm_end)
3930 {
3931 char* __to = &__bs[0];
3932 char* __to_end = __to + __bs.size();
3933 const _Elem* __frm_nxt;
3934 do
3935 {
3936 char* __to_nxt;
3937 __r = __cvtptr_->out(__st, __frm, __frm_end, __frm_nxt,
3938 __to, __to_end, __to_nxt);
3939 __cvtcount_ += __frm_nxt - __frm;
3940 if (__frm_nxt == __frm)
3941 {
3942 __r = codecvt_base::error;
3943 }
3944 else if (__r == codecvt_base::noconv)
3945 {
3946 __bs.resize(__to - &__bs[0]);
3947 // This only gets executed if _Elem is char
3948 __bs.append((const char*)__frm, (const char*)__frm_end);
3949 __frm = __frm_nxt;
3950 __r = codecvt_base::ok;
3951 }
3952 else if (__r == codecvt_base::ok)
3953 {
3954 __bs.resize(__to_nxt - &__bs[0]);
3955 __frm = __frm_nxt;
3956 }
3957 else if (__r == codecvt_base::partial)
3958 {
3959 ptrdiff_t __s = __to_nxt - &__bs[0];
3960 __bs.resize(2 * __s);
3961 __to = &__bs[0] + __s;
3962 __to_end = &__bs[0] + __bs.size();
3963 __frm = __frm_nxt;
3964 }
3965 } while (__r == codecvt_base::partial && __frm_nxt < __frm_end);
3966 }
3967 if (__r == codecvt_base::ok)
3968 {
3969 size_t __s = __bs.size();
3970 __bs.resize(__bs.capacity());
3971 char* __to = &__bs[0] + __s;
3972 char* __to_end = __to + __bs.size();
3973 do
3974 {
3975 char* __to_nxt;
3976 __r = __cvtptr_->unshift(__st, __to, __to_end, __to_nxt);
3977 if (__r == codecvt_base::noconv)
3978 {
3979 __bs.resize(__to - &__bs[0]);
3980 __r = codecvt_base::ok;
3981 }
3982 else if (__r == codecvt_base::ok)
3983 {
3984 __bs.resize(__to_nxt - &__bs[0]);
3985 }
3986 else if (__r == codecvt_base::partial)
3987 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00003988 ptrdiff_t __sp = __to_nxt - &__bs[0];
3989 __bs.resize(2 * __sp);
3990 __to = &__bs[0] + __sp;
Howard Hinnantd23b4642010-05-31 20:58:54 +00003991 __to_end = &__bs[0] + __bs.size();
3992 }
3993 } while (__r == codecvt_base::partial);
3994 if (__r == codecvt_base::ok)
3995 return __bs;
3996 }
3997 }
Howard Hinnantd4444702010-08-11 17:04:31 +00003998#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00003999 if (__byte_err_string_.empty())
4000 throw range_error("wstring_convert: to_bytes error");
Howard Hinnant324bb032010-08-22 00:02:43 +00004001#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00004002 return __byte_err_string_;
4003}
4004
4005template <class _Codecvt, class _Elem = wchar_t, class _Tr = char_traits<_Elem> >
Howard Hinnant0f678bd2013-08-12 18:38:34 +00004006class _LIBCPP_TYPE_VIS_ONLY wbuffer_convert
Howard Hinnantd23b4642010-05-31 20:58:54 +00004007 : public basic_streambuf<_Elem, _Tr>
4008{
4009public:
4010 // types:
4011 typedef _Elem char_type;
4012 typedef _Tr traits_type;
4013 typedef typename traits_type::int_type int_type;
4014 typedef typename traits_type::pos_type pos_type;
4015 typedef typename traits_type::off_type off_type;
4016 typedef typename _Codecvt::state_type state_type;
4017
4018private:
Howard Hinnant4b53f502010-06-01 20:09:18 +00004019 char* __extbuf_;
4020 const char* __extbufnext_;
4021 const char* __extbufend_;
4022 char __extbuf_min_[8];
4023 size_t __ebs_;
4024 char_type* __intbuf_;
4025 size_t __ibs_;
Howard Hinnantd23b4642010-05-31 20:58:54 +00004026 streambuf* __bufptr_;
Howard Hinnant4b53f502010-06-01 20:09:18 +00004027 _Codecvt* __cv_;
4028 state_type __st_;
4029 ios_base::openmode __cm_;
4030 bool __owns_eb_;
4031 bool __owns_ib_;
4032 bool __always_noconv_;
Howard Hinnantd23b4642010-05-31 20:58:54 +00004033
Howard Hinnant4b53f502010-06-01 20:09:18 +00004034 wbuffer_convert(const wbuffer_convert&);
4035 wbuffer_convert& operator=(const wbuffer_convert&);
Howard Hinnantd23b4642010-05-31 20:58:54 +00004036public:
Marshall Clow83179a72013-08-27 20:18:59 +00004037 _LIBCPP_EXPLICIT_AFTER_CXX11 wbuffer_convert(streambuf* __bytebuf = 0,
4038 _Codecvt* __pcvt = new _Codecvt, state_type __state = state_type());
Howard Hinnant4b53f502010-06-01 20:09:18 +00004039 ~wbuffer_convert();
Howard Hinnantd23b4642010-05-31 20:58:54 +00004040
Howard Hinnant82894812010-09-22 16:48:34 +00004041 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantd23b4642010-05-31 20:58:54 +00004042 streambuf* rdbuf() const {return __bufptr_;}
Howard Hinnant82894812010-09-22 16:48:34 +00004043 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantd23b4642010-05-31 20:58:54 +00004044 streambuf* rdbuf(streambuf* __bytebuf)
4045 {
4046 streambuf* __r = __bufptr_;
4047 __bufptr_ = __bytebuf;
4048 return __r;
4049 }
4050
Howard Hinnant82894812010-09-22 16:48:34 +00004051 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant4b53f502010-06-01 20:09:18 +00004052 state_type state() const {return __st_;}
Howard Hinnantd23b4642010-05-31 20:58:54 +00004053
4054protected:
Howard Hinnant4b53f502010-06-01 20:09:18 +00004055 virtual int_type underflow();
4056 virtual int_type pbackfail(int_type __c = traits_type::eof());
Howard Hinnantd23b4642010-05-31 20:58:54 +00004057 virtual int_type overflow (int_type __c = traits_type::eof());
Howard Hinnant4b53f502010-06-01 20:09:18 +00004058 virtual basic_streambuf<char_type, traits_type>* setbuf(char_type* __s,
4059 streamsize __n);
4060 virtual pos_type seekoff(off_type __off, ios_base::seekdir __way,
4061 ios_base::openmode __wch = ios_base::in | ios_base::out);
4062 virtual pos_type seekpos(pos_type __sp,
4063 ios_base::openmode __wch = ios_base::in | ios_base::out);
4064 virtual int sync();
4065
4066private:
4067 bool __read_mode();
4068 void __write_mode();
4069 wbuffer_convert* __close();
Howard Hinnantd23b4642010-05-31 20:58:54 +00004070};
4071
4072template <class _Codecvt, class _Elem, class _Tr>
Howard Hinnant4b53f502010-06-01 20:09:18 +00004073wbuffer_convert<_Codecvt, _Elem, _Tr>::
4074 wbuffer_convert(streambuf* __bytebuf, _Codecvt* __pcvt, state_type __state)
4075 : __extbuf_(0),
4076 __extbufnext_(0),
4077 __extbufend_(0),
4078 __ebs_(0),
4079 __intbuf_(0),
4080 __ibs_(0),
4081 __bufptr_(__bytebuf),
4082 __cv_(__pcvt),
4083 __st_(__state),
4084 __cm_(0),
4085 __owns_eb_(false),
4086 __owns_ib_(false),
4087 __always_noconv_(__cv_ ? __cv_->always_noconv() : false)
4088{
4089 setbuf(0, 4096);
4090}
4091
4092template <class _Codecvt, class _Elem, class _Tr>
4093wbuffer_convert<_Codecvt, _Elem, _Tr>::~wbuffer_convert()
4094{
4095 __close();
4096 delete __cv_;
4097 if (__owns_eb_)
4098 delete [] __extbuf_;
4099 if (__owns_ib_)
4100 delete [] __intbuf_;
4101}
4102
4103template <class _Codecvt, class _Elem, class _Tr>
4104typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
4105wbuffer_convert<_Codecvt, _Elem, _Tr>::underflow()
4106{
4107 if (__cv_ == 0 || __bufptr_ == 0)
4108 return traits_type::eof();
4109 bool __initial = __read_mode();
4110 char_type __1buf;
4111 if (this->gptr() == 0)
4112 this->setg(&__1buf, &__1buf+1, &__1buf+1);
4113 const size_t __unget_sz = __initial ? 0 : min<size_t>((this->egptr() - this->eback()) / 2, 4);
4114 int_type __c = traits_type::eof();
4115 if (this->gptr() == this->egptr())
4116 {
4117 memmove(this->eback(), this->egptr() - __unget_sz, __unget_sz * sizeof(char_type));
4118 if (__always_noconv_)
4119 {
4120 streamsize __nmemb = static_cast<streamsize>(this->egptr() - this->eback() - __unget_sz);
4121 __nmemb = __bufptr_->sgetn((char*)this->eback() + __unget_sz, __nmemb);
4122 if (__nmemb != 0)
4123 {
4124 this->setg(this->eback(),
4125 this->eback() + __unget_sz,
4126 this->eback() + __unget_sz + __nmemb);
4127 __c = *this->gptr();
4128 }
4129 }
4130 else
4131 {
4132 memmove(__extbuf_, __extbufnext_, __extbufend_ - __extbufnext_);
4133 __extbufnext_ = __extbuf_ + (__extbufend_ - __extbufnext_);
4134 __extbufend_ = __extbuf_ + (__extbuf_ == __extbuf_min_ ? sizeof(__extbuf_min_) : __ebs_);
Howard Hinnant0949eed2011-06-30 21:18:19 +00004135 streamsize __nmemb = _VSTD::min(static_cast<streamsize>(this->egptr() - this->eback() - __unget_sz),
Howard Hinnant4b53f502010-06-01 20:09:18 +00004136 static_cast<streamsize>(__extbufend_ - __extbufnext_));
4137 codecvt_base::result __r;
4138 state_type __svs = __st_;
4139 streamsize __nr = __bufptr_->sgetn(const_cast<char*>(__extbufnext_), __nmemb);
4140 if (__nr != 0)
4141 {
4142 __extbufend_ = __extbufnext_ + __nr;
4143 char_type* __inext;
4144 __r = __cv_->in(__st_, __extbuf_, __extbufend_, __extbufnext_,
4145 this->eback() + __unget_sz,
4146 this->egptr(), __inext);
4147 if (__r == codecvt_base::noconv)
4148 {
4149 this->setg((char_type*)__extbuf_, (char_type*)__extbuf_, (char_type*)__extbufend_);
4150 __c = *this->gptr();
4151 }
4152 else if (__inext != this->eback() + __unget_sz)
4153 {
4154 this->setg(this->eback(), this->eback() + __unget_sz, __inext);
4155 __c = *this->gptr();
4156 }
4157 }
4158 }
4159 }
4160 else
4161 __c = *this->gptr();
4162 if (this->eback() == &__1buf)
4163 this->setg(0, 0, 0);
4164 return __c;
4165}
4166
4167template <class _Codecvt, class _Elem, class _Tr>
4168typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
4169wbuffer_convert<_Codecvt, _Elem, _Tr>::pbackfail(int_type __c)
4170{
4171 if (__cv_ != 0 && __bufptr_ != 0 && this->eback() < this->gptr())
4172 {
4173 if (traits_type::eq_int_type(__c, traits_type::eof()))
4174 {
4175 this->gbump(-1);
4176 return traits_type::not_eof(__c);
4177 }
4178 if (traits_type::eq(traits_type::to_char_type(__c), this->gptr()[-1]))
4179 {
4180 this->gbump(-1);
4181 *this->gptr() = traits_type::to_char_type(__c);
4182 return __c;
4183 }
4184 }
4185 return traits_type::eof();
4186}
4187
4188template <class _Codecvt, class _Elem, class _Tr>
Howard Hinnantd23b4642010-05-31 20:58:54 +00004189typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
4190wbuffer_convert<_Codecvt, _Elem, _Tr>::overflow(int_type __c)
4191{
Howard Hinnant4b53f502010-06-01 20:09:18 +00004192 if (__cv_ == 0 || __bufptr_ == 0)
4193 return traits_type::eof();
4194 __write_mode();
4195 char_type __1buf;
4196 char_type* __pb_save = this->pbase();
4197 char_type* __epb_save = this->epptr();
4198 if (!traits_type::eq_int_type(__c, traits_type::eof()))
4199 {
4200 if (this->pptr() == 0)
4201 this->setp(&__1buf, &__1buf+1);
4202 *this->pptr() = traits_type::to_char_type(__c);
4203 this->pbump(1);
4204 }
4205 if (this->pptr() != this->pbase())
4206 {
4207 if (__always_noconv_)
4208 {
4209 streamsize __nmemb = static_cast<streamsize>(this->pptr() - this->pbase());
4210 if (__bufptr_->sputn((const char*)this->pbase(), __nmemb) != __nmemb)
4211 return traits_type::eof();
4212 }
4213 else
4214 {
4215 char* __extbe = __extbuf_;
4216 codecvt_base::result __r;
4217 do
4218 {
4219 const char_type* __e;
4220 __r = __cv_->out(__st_, this->pbase(), this->pptr(), __e,
4221 __extbuf_, __extbuf_ + __ebs_, __extbe);
4222 if (__e == this->pbase())
4223 return traits_type::eof();
4224 if (__r == codecvt_base::noconv)
4225 {
4226 streamsize __nmemb = static_cast<size_t>(this->pptr() - this->pbase());
4227 if (__bufptr_->sputn((const char*)this->pbase(), __nmemb) != __nmemb)
4228 return traits_type::eof();
4229 }
4230 else if (__r == codecvt_base::ok || __r == codecvt_base::partial)
4231 {
4232 streamsize __nmemb = static_cast<size_t>(__extbe - __extbuf_);
4233 if (__bufptr_->sputn(__extbuf_, __nmemb) != __nmemb)
4234 return traits_type::eof();
4235 if (__r == codecvt_base::partial)
4236 {
4237 this->setp((char_type*)__e, this->pptr());
4238 this->pbump(this->epptr() - this->pbase());
4239 }
4240 }
4241 else
4242 return traits_type::eof();
4243 } while (__r == codecvt_base::partial);
4244 }
4245 this->setp(__pb_save, __epb_save);
4246 }
4247 return traits_type::not_eof(__c);
4248}
4249
4250template <class _Codecvt, class _Elem, class _Tr>
4251basic_streambuf<_Elem, _Tr>*
4252wbuffer_convert<_Codecvt, _Elem, _Tr>::setbuf(char_type* __s, streamsize __n)
4253{
4254 this->setg(0, 0, 0);
4255 this->setp(0, 0);
4256 if (__owns_eb_)
4257 delete [] __extbuf_;
4258 if (__owns_ib_)
4259 delete [] __intbuf_;
4260 __ebs_ = __n;
4261 if (__ebs_ > sizeof(__extbuf_min_))
4262 {
4263 if (__always_noconv_ && __s)
4264 {
4265 __extbuf_ = (char*)__s;
4266 __owns_eb_ = false;
4267 }
4268 else
4269 {
4270 __extbuf_ = new char[__ebs_];
4271 __owns_eb_ = true;
4272 }
4273 }
4274 else
4275 {
4276 __extbuf_ = __extbuf_min_;
4277 __ebs_ = sizeof(__extbuf_min_);
4278 __owns_eb_ = false;
4279 }
4280 if (!__always_noconv_)
4281 {
4282 __ibs_ = max<streamsize>(__n, sizeof(__extbuf_min_));
4283 if (__s && __ibs_ >= sizeof(__extbuf_min_))
4284 {
4285 __intbuf_ = __s;
4286 __owns_ib_ = false;
4287 }
4288 else
4289 {
4290 __intbuf_ = new char_type[__ibs_];
4291 __owns_ib_ = true;
4292 }
4293 }
4294 else
4295 {
4296 __ibs_ = 0;
4297 __intbuf_ = 0;
4298 __owns_ib_ = false;
4299 }
4300 return this;
4301}
4302
4303template <class _Codecvt, class _Elem, class _Tr>
4304typename wbuffer_convert<_Codecvt, _Elem, _Tr>::pos_type
4305wbuffer_convert<_Codecvt, _Elem, _Tr>::seekoff(off_type __off, ios_base::seekdir __way,
4306 ios_base::openmode __om)
4307{
4308 int __width = __cv_->encoding();
4309 if (__cv_ == 0 || __bufptr_ == 0 || (__width <= 0 && __off != 0) || sync())
4310 return pos_type(off_type(-1));
4311 // __width > 0 || __off == 0
4312 switch (__way)
4313 {
4314 case ios_base::beg:
4315 break;
4316 case ios_base::cur:
4317 break;
4318 case ios_base::end:
4319 break;
4320 default:
4321 return pos_type(off_type(-1));
4322 }
4323 pos_type __r = __bufptr_->pubseekoff(__width * __off, __way, __om);
4324 __r.state(__st_);
4325 return __r;
4326}
4327
4328template <class _Codecvt, class _Elem, class _Tr>
4329typename wbuffer_convert<_Codecvt, _Elem, _Tr>::pos_type
4330wbuffer_convert<_Codecvt, _Elem, _Tr>::seekpos(pos_type __sp, ios_base::openmode __wch)
4331{
4332 if (__cv_ == 0 || __bufptr_ == 0 || sync())
4333 return pos_type(off_type(-1));
4334 if (__bufptr_->pubseekpos(__sp, __wch) == pos_type(off_type(-1)))
4335 return pos_type(off_type(-1));
4336 return __sp;
4337}
4338
4339template <class _Codecvt, class _Elem, class _Tr>
4340int
4341wbuffer_convert<_Codecvt, _Elem, _Tr>::sync()
4342{
4343 if (__cv_ == 0 || __bufptr_ == 0)
4344 return 0;
4345 if (__cm_ & ios_base::out)
4346 {
4347 if (this->pptr() != this->pbase())
4348 if (overflow() == traits_type::eof())
4349 return -1;
4350 codecvt_base::result __r;
4351 do
4352 {
4353 char* __extbe;
4354 __r = __cv_->unshift(__st_, __extbuf_, __extbuf_ + __ebs_, __extbe);
4355 streamsize __nmemb = static_cast<streamsize>(__extbe - __extbuf_);
4356 if (__bufptr_->sputn(__extbuf_, __nmemb) != __nmemb)
4357 return -1;
4358 } while (__r == codecvt_base::partial);
4359 if (__r == codecvt_base::error)
4360 return -1;
4361 if (__bufptr_->pubsync())
4362 return -1;
4363 }
4364 else if (__cm_ & ios_base::in)
4365 {
4366 off_type __c;
4367 if (__always_noconv_)
4368 __c = this->egptr() - this->gptr();
4369 else
4370 {
4371 int __width = __cv_->encoding();
4372 __c = __extbufend_ - __extbufnext_;
4373 if (__width > 0)
4374 __c += __width * (this->egptr() - this->gptr());
4375 else
4376 {
4377 if (this->gptr() != this->egptr())
4378 {
4379 reverse(this->gptr(), this->egptr());
4380 codecvt_base::result __r;
4381 const char_type* __e = this->gptr();
4382 char* __extbe;
4383 do
4384 {
4385 __r = __cv_->out(__st_, __e, this->egptr(), __e,
4386 __extbuf_, __extbuf_ + __ebs_, __extbe);
4387 switch (__r)
4388 {
4389 case codecvt_base::noconv:
4390 __c += this->egptr() - this->gptr();
4391 break;
4392 case codecvt_base::ok:
4393 case codecvt_base::partial:
4394 __c += __extbe - __extbuf_;
4395 break;
4396 default:
4397 return -1;
4398 }
4399 } while (__r == codecvt_base::partial);
4400 }
4401 }
4402 }
4403 if (__bufptr_->pubseekoff(-__c, ios_base::cur, __cm_) == pos_type(off_type(-1)))
4404 return -1;
4405 this->setg(0, 0, 0);
4406 __cm_ = 0;
4407 }
4408 return 0;
4409}
4410
4411template <class _Codecvt, class _Elem, class _Tr>
4412bool
4413wbuffer_convert<_Codecvt, _Elem, _Tr>::__read_mode()
4414{
4415 if (!(__cm_ & ios_base::in))
4416 {
4417 this->setp(0, 0);
4418 if (__always_noconv_)
4419 this->setg((char_type*)__extbuf_,
4420 (char_type*)__extbuf_ + __ebs_,
4421 (char_type*)__extbuf_ + __ebs_);
4422 else
4423 this->setg(__intbuf_, __intbuf_ + __ibs_, __intbuf_ + __ibs_);
4424 __cm_ = ios_base::in;
4425 return true;
4426 }
4427 return false;
4428}
4429
4430template <class _Codecvt, class _Elem, class _Tr>
4431void
4432wbuffer_convert<_Codecvt, _Elem, _Tr>::__write_mode()
4433{
4434 if (!(__cm_ & ios_base::out))
4435 {
4436 this->setg(0, 0, 0);
4437 if (__ebs_ > sizeof(__extbuf_min_))
4438 {
4439 if (__always_noconv_)
4440 this->setp((char_type*)__extbuf_,
4441 (char_type*)__extbuf_ + (__ebs_ - 1));
4442 else
4443 this->setp(__intbuf_, __intbuf_ + (__ibs_ - 1));
4444 }
4445 else
4446 this->setp(0, 0);
4447 __cm_ = ios_base::out;
4448 }
4449}
4450
4451template <class _Codecvt, class _Elem, class _Tr>
4452wbuffer_convert<_Codecvt, _Elem, _Tr>*
4453wbuffer_convert<_Codecvt, _Elem, _Tr>::__close()
4454{
4455 wbuffer_convert* __rt = 0;
4456 if (__cv_ != 0 && __bufptr_ != 0)
4457 {
4458 __rt = this;
4459 if ((__cm_ & ios_base::out) && sync())
4460 __rt = 0;
4461 }
4462 return __rt;
Howard Hinnantd23b4642010-05-31 20:58:54 +00004463}
4464
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004465_LIBCPP_END_NAMESPACE_STD
4466
4467#endif // _LIBCPP_LOCALE