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