blob: 976c4cf50a17f2ead286252feaa9218e39784ff9 [file] [log] [blame]
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001// -*- C++ -*-
2//===-------------------------- locale ------------------------------------===//
3//
Howard Hinnantf5256e12010-05-11 21:36:01 +00004// The LLVM Compiler Infrastructure
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005//
Howard Hinnantb64f8b02010-11-16 22:09:02 +00006// This file is dual licensed under the MIT and the University of Illinois Open
7// Source Licenses. See LICENSE.TXT for details.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00008//
9//===----------------------------------------------------------------------===//
10
11#ifndef _LIBCPP_LOCALE
12#define _LIBCPP_LOCALE
13
14/*
15 locale synopsis
16
17namespace std
18{
19
20class locale
21{
22public:
23 // types:
24 class facet;
25 class id;
26
27 typedef int category;
28 static const category // values assigned here are for exposition only
29 none = 0x000,
30 collate = 0x010,
31 ctype = 0x020,
32 monetary = 0x040,
33 numeric = 0x080,
34 time = 0x100,
35 messages = 0x200,
36 all = collate | ctype | monetary | numeric | time | messages;
37
38 // construct/copy/destroy:
Howard Hinnantc9834542011-05-31 15:34:58 +000039 locale() noexcept;
40 locale(const locale& other) noexcept;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000041 explicit locale(const char* std_name);
42 explicit locale(const string& std_name);
43 locale(const locale& other, const char* std_name, category);
44 locale(const locale& other, const string& std_name, category);
45 template <class Facet> locale(const locale& other, Facet* f);
46 locale(const locale& other, const locale& one, category);
47
Howard Hinnantc9834542011-05-31 15:34:58 +000048 ~locale(); // not virtual
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000049
Howard Hinnantc9834542011-05-31 15:34:58 +000050 const locale& operator=(const locale& other) noexcept;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000051
52 template <class Facet> locale combine(const locale& other) const;
53
54 // locale operations:
55 basic_string<char> name() const;
56 bool operator==(const locale& other) const;
57 bool operator!=(const locale& other) const;
58 template <class charT, class Traits, class Allocator>
59 bool operator()(const basic_string<charT,Traits,Allocator>& s1,
60 const basic_string<charT,Traits,Allocator>& s2) const;
61
62 // global locale objects:
63 static locale global(const locale&);
64 static const locale& classic();
65};
66
67template <class Facet> const Facet& use_facet(const locale&);
Howard Hinnantc9834542011-05-31 15:34:58 +000068template <class Facet> bool has_facet(const locale&) noexcept;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000069
70// 22.3.3, convenience interfaces:
71template <class charT> bool isspace (charT c, const locale& loc);
72template <class charT> bool isprint (charT c, const locale& loc);
73template <class charT> bool iscntrl (charT c, const locale& loc);
74template <class charT> bool isupper (charT c, const locale& loc);
75template <class charT> bool islower (charT c, const locale& loc);
76template <class charT> bool isalpha (charT c, const locale& loc);
77template <class charT> bool isdigit (charT c, const locale& loc);
78template <class charT> bool ispunct (charT c, const locale& loc);
79template <class charT> bool isxdigit(charT c, const locale& loc);
80template <class charT> bool isalnum (charT c, const locale& loc);
81template <class charT> bool isgraph (charT c, const locale& loc);
82template <class charT> charT toupper(charT c, const locale& loc);
83template <class charT> charT tolower(charT c, const locale& loc);
Howard Hinnantd23b4642010-05-31 20:58:54 +000084
85template<class Codecvt, class Elem = wchar_t,
86 class Wide_alloc = allocator<Elem>,
87 class Byte_alloc = allocator<char>>
88class wstring_convert
89{
90public:
91 typedef basic_string<char, char_traits<char>, Byte_alloc> byte_string;
92 typedef basic_string<Elem, char_traits<Elem>, Wide_alloc> wide_string;
93 typedef typename Codecvt::state_type state_type;
94 typedef typename wide_string::traits_type::int_type int_type;
95
96 wstring_convert(Codecvt* pcvt = new Codecvt);
97 wstring_convert(Codecvt* pcvt, state_type state);
98 wstring_convert(const byte_string& byte_err,
99 const wide_string& wide_err = wide_string());
100 ~wstring_convert();
101
102 wide_string from_bytes(char byte);
103 wide_string from_bytes(const char* ptr);
104 wide_string from_bytes(const byte_string& str);
105 wide_string from_bytes(const char* first, const char* last);
106
107 byte_string to_bytes(Elem wchar);
108 byte_string to_bytes(const Elem* wptr);
109 byte_string to_bytes(const wide_string& wstr);
110 byte_string to_bytes(const Elem* first, const Elem* last);
111
112 size_t converted() const;
113 state_type state() const;
114};
115
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000116template <class Codecvt, class Elem = wchar_t, class Tr = char_traits<Elem>>
Howard Hinnantd23b4642010-05-31 20:58:54 +0000117class wbuffer_convert
118 : public basic_streambuf<Elem, Tr>
119{
120public:
121 typedef typename Tr::state_type state_type;
122
123 wbuffer_convert(streambuf* bytebuf = 0, Codecvt* pcvt = new Codecvt,
124 state_type state = state_type());
125
126 streambuf* rdbuf() const;
127 streambuf* rdbuf(streambuf* bytebuf);
128
129 state_type state() const;
130};
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000131
132// 22.4.1 and 22.4.1.3, ctype:
133class ctype_base;
134template <class charT> class ctype;
135template <> class ctype<char>; // specialization
136template <class charT> class ctype_byname;
137template <> class ctype_byname<char>; // specialization
138
139class codecvt_base;
140template <class internT, class externT, class stateT> class codecvt;
141template <class internT, class externT, class stateT> class codecvt_byname;
142
143// 22.4.2 and 22.4.3, numeric:
144template <class charT, class InputIterator> class num_get;
145template <class charT, class OutputIterator> class num_put;
146template <class charT> class numpunct;
147template <class charT> class numpunct_byname;
148
149// 22.4.4, col lation:
150template <class charT> class collate;
151template <class charT> class collate_byname;
152
153// 22.4.5, date and time:
154class time_base;
155template <class charT, class InputIterator> class time_get;
156template <class charT, class InputIterator> class time_get_byname;
157template <class charT, class OutputIterator> class time_put;
158template <class charT, class OutputIterator> class time_put_byname;
159
160// 22.4.6, money:
161class money_base;
162template <class charT, class InputIterator> class money_get;
163template <class charT, class OutputIterator> class money_put;
164template <class charT, bool Intl> class moneypunct;
165template <class charT, bool Intl> class moneypunct_byname;
166
167// 22.4.7, message retrieval:
168class messages_base;
169template <class charT> class messages;
170template <class charT> class messages_byname;
171
172} // std
173
174*/
175
176#include <__config>
177#include <__locale>
178#include <algorithm>
179#include <memory>
180#include <ios>
181#include <streambuf>
182#include <iterator>
183#include <limits>
Howard Hinnantadff4892010-05-24 17:49:41 +0000184#if !__APPLE__
185#include <cstdarg>
186#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000187#include <cstdlib>
188#include <ctime>
Howard Hinnant6cd05ee2011-09-23 16:11:27 +0000189#if _WIN32
Howard Hinnant14fa9f92011-09-29 20:33:10 +0000190#include <support/win32/locale_win32.h>
Howard Hinnant6cd05ee2011-09-23 16:11:27 +0000191#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000192#include <nl_types.h>
Howard Hinnant92a07002011-09-22 19:10:18 +0000193#endif // !_WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000194
Howard Hinnant66c6f972011-11-29 16:45:27 +0000195#include <__undef_min_max>
196
Howard Hinnant08e17472011-10-17 20:05:10 +0000197#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000198#pragma GCC system_header
Howard Hinnant08e17472011-10-17 20:05:10 +0000199#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000200
201_LIBCPP_BEGIN_NAMESPACE_STD
202
Howard Hinnant866569b2011-09-28 23:39:33 +0000203#if __APPLE__ || __FreeBSD__
Howard Hinnant2ea1ca92011-09-28 21:05:01 +0000204# define _LIBCPP_GET_C_LOCALE 0
205#else
206# define _LIBCPP_GET_C_LOCALE __cloc()
Howard Hinnant866569b2011-09-28 23:39:33 +0000207 // Get the C locale object
208 locale_t __cloc();
209#define __cloc_defined
Howard Hinnant2ea1ca92011-09-28 21:05:01 +0000210#endif
211
Sean Huntf3907e62011-07-15 05:40:33 +0000212typedef _VSTD::remove_pointer<locale_t>::type __locale_struct;
213typedef _VSTD::unique_ptr<__locale_struct, decltype(&freelocale)> __locale_unique_ptr;
David Chisnall8fa14e92012-02-29 13:00:07 +0000214#ifndef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +0000215typedef _VSTD::unique_ptr<__locale_struct, decltype(&uselocale)> __locale_raii;
David Chisnall8fa14e92012-02-29 13:00:07 +0000216#endif
Sean Huntf3907e62011-07-15 05:40:33 +0000217
Howard Hinnantadff4892010-05-24 17:49:41 +0000218// OSX has nice foo_l() functions that let you turn off use of the global
219// locale. Linux, not so much. The following functions avoid the locale when
220// that's possible and otherwise do the wrong thing. FIXME.
Howard Hinnant866569b2011-09-28 23:39:33 +0000221#ifdef __linux__
Sean Huntf3907e62011-07-15 05:40:33 +0000222
223#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
224decltype(MB_CUR_MAX_L(_VSTD::declval<locale_t>()))
Howard Hinnant82894812010-09-22 16:48:34 +0000225inline _LIBCPP_INLINE_VISIBILITY
Sean Huntf3907e62011-07-15 05:40:33 +0000226__mb_cur_max_l(locale_t __l)
Howard Hinnantadff4892010-05-24 17:49:41 +0000227{
Sean Huntf3907e62011-07-15 05:40:33 +0000228 return MB_CUR_MAX_L(__l);
229}
230#else // _LIBCPP_LOCALE__L_EXTENSIONS
231_LIBCPP_ALWAYS_INLINE inline
232decltype(MB_CUR_MAX) __mb_cur_max_l(locale_t __l)
233{
234 __locale_raii __current(uselocale(__l), uselocale);
235 return MB_CUR_MAX;
236}
237#endif // _LIBCPP_LOCALE__L_EXTENSIONS
238
239_LIBCPP_ALWAYS_INLINE inline
240wint_t __btowc_l(int __c, locale_t __l)
241{
Howard Hinnant866569b2011-09-28 23:39:33 +0000242#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +0000243 return btowc_l(__c, __l);
244#else
245 __locale_raii __current(uselocale(__l), uselocale);
246 return btowc(__c);
247#endif
Sean Huntc97da3a2011-07-13 06:40:50 +0000248}
Howard Hinnant8d756322011-07-13 15:48:16 +0000249
Sean Huntf3907e62011-07-15 05:40:33 +0000250_LIBCPP_ALWAYS_INLINE inline
251int __wctob_l(wint_t __c, locale_t __l)
Sean Huntc97da3a2011-07-13 06:40:50 +0000252{
Sean Huntf3907e62011-07-15 05:40:33 +0000253#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
254 return wctob_l(__c, __l);
255#else
256 __locale_raii __current(uselocale(__l), uselocale);
257 return wctob(__c);
258#endif
Sean Huntc97da3a2011-07-13 06:40:50 +0000259}
Sean Huntf3907e62011-07-15 05:40:33 +0000260
261_LIBCPP_ALWAYS_INLINE inline
262size_t __wcsnrtombs_l(char *__dest, const wchar_t **__src, size_t __nwc,
263 size_t __len, mbstate_t *__ps, locale_t __l)
264{
265#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
266 return wcsnrtombs_l(__dest, __src, __nwc, __len, __ps, __l);
267#else
268 __locale_raii __current(uselocale(__l), uselocale);
269 return wcsnrtombs(__dest, __src, __nwc, __len, __ps);
270#endif
271}
272
273_LIBCPP_ALWAYS_INLINE inline
274size_t __wcrtomb_l(char *__s, wchar_t __wc, mbstate_t *__ps, locale_t __l)
275{
276#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
277 return wcrtomb_l(__s, __wc, __ps, __l);
278#else
279 __locale_raii __current(uselocale(__l), uselocale);
280 return wcrtomb(__s, __wc, __ps);
281#endif
282}
283
284_LIBCPP_ALWAYS_INLINE inline
285size_t __mbsnrtowcs_l(wchar_t * __dest, const char **__src, size_t __nms,
286 size_t __len, mbstate_t *__ps, locale_t __l)
287{
288#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
David Chisnallc512df12011-09-21 08:39:44 +0000289 return mbsnrtowcs_l(__dest, __src, __nms, __len, __ps, __l);
Sean Huntf3907e62011-07-15 05:40:33 +0000290#else
291 __locale_raii __current(uselocale(__l), uselocale);
292 return mbsnrtowcs(__dest, __src, __nms, __len, __ps);
293#endif
294}
295
296_LIBCPP_ALWAYS_INLINE inline
297size_t __mbrtowc_l(wchar_t *__pwc, const char *__s, size_t __n,
298 mbstate_t *__ps, locale_t __l)
299{
300#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
301 return mbrtowc_l(__pwc, __s, __n, __ps, __l);
302#else
303 __locale_raii __current(uselocale(__l), uselocale);
304 return mbrtowc(__pwc, __s, __n, __ps);
305#endif
306}
307
308_LIBCPP_ALWAYS_INLINE inline
309int __mbtowc_l(wchar_t *__pwc, const char *__pmb, size_t __max, locale_t __l)
310{
311#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
David Chisnallc512df12011-09-21 08:39:44 +0000312 return mbtowc_l(__pwc, __pmb, __max, __l);
Sean Huntf3907e62011-07-15 05:40:33 +0000313#else
314 __locale_raii __current(uselocale(__l), uselocale);
315 return mbtowc(__pwc, __pmb, __max);
316#endif
317}
318
319_LIBCPP_ALWAYS_INLINE inline
320size_t __mbrlen_l(const char *__s, size_t __n, mbstate_t *__ps, locale_t __l)
321{
322#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
323 return mbrlen_l(__s, __n, __ps, __l);
324#else
325 __locale_raii __current(uselocale(__l), uselocale);
326 return mbrlen(__s, __n, __ps);
327#endif
328}
329
330_LIBCPP_ALWAYS_INLINE inline
331lconv *__localeconv_l(locale_t __l)
332{
333#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
334 return localeconv_l(__l);
335#else
336 __locale_raii __current(uselocale(__l), uselocale);
337 return localeconv();
338#endif
339}
340
341_LIBCPP_ALWAYS_INLINE inline
342size_t __mbsrtowcs_l(wchar_t *__dest, const char **__src, size_t __len,
343 mbstate_t *__ps, locale_t __l)
344{
345#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
346 return mbsrtowcs_l(__dest, __src, __len, __ps, __l);
347#else
348 __locale_raii __current(uselocale(__l), uselocale);
349 return mbsrtowcs(__dest, __src, __len, __ps);
350#endif
351}
352
353_LIBCPP_ALWAYS_INLINE inline
354int __sprintf_l(char *__s, locale_t __l, const char *__format, ...) {
355 va_list __va;
356 va_start(__va, __format);
357#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
358 int __res = vsprintf_l(__s, __l, __format, __va);
359#else
360 __locale_raii __current(uselocale(__l), uselocale);
361 int __res = vsprintf(__s, __format, __va);
362#endif
363 va_end(__va);
364 return __res;
365}
366
367_LIBCPP_ALWAYS_INLINE inline
368int __snprintf_l(char *__s, size_t __n, locale_t __l, const char *__format, ...) {
369 va_list __va;
370 va_start(__va, __format);
371#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
372 int __res = vsnprintf_l(__s, __n, __l, __format, __va);
373#else
374 __locale_raii __current(uselocale(__l), uselocale);
375 int __res = vsnprintf(__s, __n, __format, __va);
376#endif
377 va_end(__va);
378 return __res;
379}
380
381_LIBCPP_ALWAYS_INLINE inline
382int __asprintf_l(char **__s, locale_t __l, const char *__format, ...) {
383 va_list __va;
384 va_start(__va, __format);
385#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
386 int __res = vasprintf_l(__s, __l, __format, __va);
387#else
388 __locale_raii __current(uselocale(__l), uselocale);
389 int __res = vasprintf(__s, __format, __va);
390#endif
391 va_end(__va);
392 return __res;
393}
394
395_LIBCPP_ALWAYS_INLINE inline
396int __sscanf_l(const char *__s, locale_t __l, const char *__format, ...) {
397 va_list __va;
398 va_start(__va, __format);
399#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
400 int __res = vsscanf_l(__s, __l, __format, __va);
401#else
402 __locale_raii __current(uselocale(__l), uselocale);
403 int __res = vsscanf(__s, __format, __va);
404#endif
405 va_end(__va);
406 return __res;
407}
408
Howard Hinnant866569b2011-09-28 23:39:33 +0000409#endif // __linux__
Howard Hinnantadff4892010-05-24 17:49:41 +0000410
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000411// __scan_keyword
412// Scans [__b, __e) until a match is found in the basic_strings range
413// [__kb, __ke) or until it can be shown that there is no match in [__kb, __ke).
414// __b will be incremented (visibly), consuming CharT until a match is found
415// or proved to not exist. A keyword may be "", in which will match anything.
416// If one keyword is a prefix of another, and the next CharT in the input
417// might match another keyword, the algorithm will attempt to find the longest
418// matching keyword. If the longer matching keyword ends up not matching, then
419// no keyword match is found. If no keyword match is found, __ke is returned
420// and failbit is set in __err.
421// Else an iterator pointing to the matching keyword is found. If more than
422// one keyword matches, an iterator to the first matching keyword is returned.
423// If on exit __b == __e, eofbit is set in __err. If __case_senstive is false,
424// __ct is used to force to lower case before comparing characters.
425// Examples:
426// Keywords: "a", "abb"
427// If the input is "a", the first keyword matches and eofbit is set.
428// If the input is "abc", no match is found and "ab" are consumed.
429template <class _InputIterator, class _ForwardIterator, class _Ctype>
430_LIBCPP_HIDDEN
431_ForwardIterator
432__scan_keyword(_InputIterator& __b, _InputIterator __e,
433 _ForwardIterator __kb, _ForwardIterator __ke,
434 const _Ctype& __ct, ios_base::iostate& __err,
435 bool __case_sensitive = true)
436{
437 typedef typename iterator_traits<_InputIterator>::value_type _CharT;
Howard Hinnantec3773c2011-12-01 20:21:04 +0000438 size_t __nkw = static_cast<size_t>(_VSTD::distance(__kb, __ke));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000439 const unsigned char __doesnt_match = '\0';
440 const unsigned char __might_match = '\1';
441 const unsigned char __does_match = '\2';
442 unsigned char __statbuf[100];
443 unsigned char* __status = __statbuf;
444 unique_ptr<unsigned char, void(*)(void*)> __stat_hold(0, free);
445 if (__nkw > sizeof(__statbuf))
446 {
447 __status = (unsigned char*)malloc(__nkw);
448 if (__status == 0)
449 __throw_bad_alloc();
450 __stat_hold.reset(__status);
451 }
452 size_t __n_might_match = __nkw; // At this point, any keyword might match
453 size_t __n_does_match = 0; // but none of them definitely do
454 // Initialize all statuses to __might_match, except for "" keywords are __does_match
455 unsigned char* __st = __status;
456 for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, ++__st)
457 {
458 if (!__ky->empty())
459 *__st = __might_match;
460 else
461 {
462 *__st = __does_match;
463 --__n_might_match;
464 ++__n_does_match;
465 }
466 }
467 // While there might be a match, test keywords against the next CharT
468 for (size_t __indx = 0; __b != __e && __n_might_match > 0; ++__indx)
469 {
470 // Peek at the next CharT but don't consume it
471 _CharT __c = *__b;
472 if (!__case_sensitive)
473 __c = __ct.toupper(__c);
474 bool __consume = false;
475 // For each keyword which might match, see if the __indx character is __c
476 // If a match if found, consume __c
477 // If a match is found, and that is the last character in the keyword,
478 // then that keyword matches.
479 // If the keyword doesn't match this character, then change the keyword
480 // to doesn't match
481 __st = __status;
482 for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, ++__st)
483 {
484 if (*__st == __might_match)
485 {
486 _CharT __kc = (*__ky)[__indx];
487 if (!__case_sensitive)
488 __kc = __ct.toupper(__kc);
489 if (__c == __kc)
490 {
491 __consume = true;
492 if (__ky->size() == __indx+1)
493 {
494 *__st = __does_match;
495 --__n_might_match;
496 ++__n_does_match;
497 }
498 }
499 else
500 {
501 *__st = __doesnt_match;
502 --__n_might_match;
503 }
504 }
505 }
506 // consume if we matched a character
507 if (__consume)
508 {
509 ++__b;
510 // If we consumed a character and there might be a matched keyword that
511 // was marked matched on a previous iteration, then such keywords
512 // which are now marked as not matching.
513 if (__n_might_match + __n_does_match > 1)
514 {
515 __st = __status;
516 for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, ++__st)
517 {
518 if (*__st == __does_match && __ky->size() != __indx+1)
519 {
520 *__st = __doesnt_match;
521 --__n_does_match;
522 }
523 }
524 }
525 }
526 }
527 // We've exited the loop because we hit eof and/or we have no more "might matches".
528 if (__b == __e)
529 __err |= ios_base::eofbit;
530 // Return the first matching result
531 for (__st = __status; __kb != __ke; ++__kb, ++__st)
532 if (*__st == __does_match)
533 break;
534 if (__kb == __ke)
535 __err |= ios_base::failbit;
536 return __kb;
537}
538
539struct __num_get_base
540{
541 static const int __num_get_buf_sz = 40;
542
543 static int __get_base(ios_base&);
544 static const char __src[33];
545};
546
547void __check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
548 ios_base::iostate& __err);
549
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000550template <class _CharT>
551struct __num_get
552 : protected __num_get_base
553{
554 static string __stage2_int_prep(ios_base& __iob, _CharT* __atoms, _CharT& __thousands_sep);
555 static string __stage2_float_prep(ios_base& __iob, _CharT* __atoms, _CharT& __decimal_point,
556 _CharT& __thousands_sep);
557 static int __stage2_int_loop(_CharT __ct, int __base, char* __a, char*& __a_end,
558 unsigned& __dc, _CharT __thousands_sep, const string& __grouping,
559 unsigned* __g, unsigned*& __g_end, _CharT* __atoms);
560 static int __stage2_float_loop(_CharT __ct, bool& __in_units, char& __exp,
561 char* __a, char*& __a_end,
562 _CharT __decimal_point, _CharT __thousands_sep,
563 const string& __grouping, unsigned* __g,
564 unsigned*& __g_end, unsigned& __dc, _CharT* __atoms);
565};
566
567template <class _CharT>
568string
569__num_get<_CharT>::__stage2_int_prep(ios_base& __iob, _CharT* __atoms, _CharT& __thousands_sep)
570{
571 locale __loc = __iob.getloc();
572 use_facet<ctype<_CharT> >(__loc).widen(__src, __src + 26, __atoms);
573 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
574 __thousands_sep = __np.thousands_sep();
575 return __np.grouping();
576}
577
578template <class _CharT>
579string
580__num_get<_CharT>::__stage2_float_prep(ios_base& __iob, _CharT* __atoms, _CharT& __decimal_point,
581 _CharT& __thousands_sep)
582{
583 locale __loc = __iob.getloc();
584 use_facet<ctype<_CharT> >(__loc).widen(__src, __src + 32, __atoms);
585 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
586 __decimal_point = __np.decimal_point();
587 __thousands_sep = __np.thousands_sep();
588 return __np.grouping();
589}
590
591template <class _CharT>
592int
593__num_get<_CharT>::__stage2_int_loop(_CharT __ct, int __base, char* __a, char*& __a_end,
594 unsigned& __dc, _CharT __thousands_sep, const string& __grouping,
595 unsigned* __g, unsigned*& __g_end, _CharT* __atoms)
596{
Howard Hinnant80586722011-03-09 01:03:19 +0000597 if (__a_end == __a && (__ct == __atoms[24] || __ct == __atoms[25]))
598 {
599 *__a_end++ = __ct == __atoms[24] ? '+' : '-';
600 __dc = 0;
601 return 0;
602 }
Howard Hinnantec3773c2011-12-01 20:21:04 +0000603 if (__grouping.size() != 0 && __ct == __thousands_sep)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000604 {
605 if (__g_end-__g < __num_get_buf_sz)
606 {
607 *__g_end++ = __dc;
608 __dc = 0;
609 }
610 return 0;
611 }
612 ptrdiff_t __f = find(__atoms, __atoms + 26, __ct) - __atoms;
Howard Hinnant80586722011-03-09 01:03:19 +0000613 if (__f >= 24)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000614 return -1;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000615 switch (__base)
616 {
617 case 8:
618 case 10:
619 if (__f >= __base)
Howard Hinnant80586722011-03-09 01:03:19 +0000620 return -1;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000621 break;
Howard Hinnant80586722011-03-09 01:03:19 +0000622 case 16:
623 if (__f < 22)
624 break;
625 if (__a_end != __a && __a_end - __a <= 2 && __a_end[-1] == '0')
626 {
627 __dc = 0;
628 *__a_end++ = __src[__f];
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000629 return 0;
Howard Hinnant80586722011-03-09 01:03:19 +0000630 }
631 return -1;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000632 }
Howard Hinnant80586722011-03-09 01:03:19 +0000633 if (__a_end-__a < __num_get_buf_sz - 1)
634 *__a_end++ = __src[__f];
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000635 ++__dc;
636 return 0;
637}
638
639template <class _CharT>
640int
641__num_get<_CharT>::__stage2_float_loop(_CharT __ct, bool& __in_units, char& __exp, char* __a, char*& __a_end,
642 _CharT __decimal_point, _CharT __thousands_sep, const string& __grouping,
643 unsigned* __g, unsigned*& __g_end, unsigned& __dc, _CharT* __atoms)
644{
645 if (__ct == __decimal_point)
646 {
647 if (!__in_units)
648 return -1;
649 __in_units = false;
650 *__a_end++ = '.';
651 if (__grouping.size() != 0 && __g_end-__g < __num_get_buf_sz)
652 *__g_end++ = __dc;
653 return 0;
654 }
655 if (__ct == __thousands_sep && __grouping.size() != 0)
656 {
657 if (!__in_units)
658 return -1;
659 if (__g_end-__g < __num_get_buf_sz)
660 {
661 *__g_end++ = __dc;
662 __dc = 0;
663 }
664 return 0;
665 }
666 ptrdiff_t __f = find(__atoms, __atoms + 32, __ct) - __atoms;
667 if (__f >= 32)
668 return -1;
669 char __x = __src[__f];
Howard Hinnantb04ad412012-02-15 19:19:37 +0000670 if (__x == '-' || __x == '+')
671 {
672 if (__a_end == __a || (__a_end[-1] & 0xDF) == __exp)
673 {
674 *__a_end++ = __x;
675 return 0;
676 }
677 return -1;
678 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000679 if (__a_end-__a < __num_get_buf_sz - 1)
680 *__a_end++ = __x;
681 if (__x == 'x' || __x == 'X')
682 __exp = 'P';
683 else if ((__x & 0xDF) == __exp)
684 {
685 __in_units = false;
686 if (__grouping.size() != 0 && __g_end-__g < __num_get_buf_sz)
687 *__g_end++ = __dc;
688 }
689 if (__f >= 22)
690 return 0;
691 ++__dc;
692 return 0;
693}
694
Howard Hinnantff926772012-11-06 21:08:48 +0000695_LIBCPP_EXTERN_TEMPLATE(struct __num_get<char>)
696_LIBCPP_EXTERN_TEMPLATE(struct __num_get<wchar_t>)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000697
698template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +0000699class _LIBCPP_VISIBLE num_get
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000700 : public locale::facet,
701 private __num_get<_CharT>
702{
703public:
704 typedef _CharT char_type;
705 typedef _InputIterator iter_type;
706
707 _LIBCPP_ALWAYS_INLINE
708 explicit num_get(size_t __refs = 0)
709 : locale::facet(__refs) {}
710
711 _LIBCPP_ALWAYS_INLINE
712 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
713 ios_base::iostate& __err, bool& __v) const
714 {
715 return do_get(__b, __e, __iob, __err, __v);
716 }
717
718 _LIBCPP_ALWAYS_INLINE
719 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
720 ios_base::iostate& __err, long& __v) const
721 {
722 return do_get(__b, __e, __iob, __err, __v);
723 }
724
725 _LIBCPP_ALWAYS_INLINE
726 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
727 ios_base::iostate& __err, long long& __v) const
728 {
729 return do_get(__b, __e, __iob, __err, __v);
730 }
731
732 _LIBCPP_ALWAYS_INLINE
733 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
734 ios_base::iostate& __err, unsigned short& __v) const
735 {
736 return do_get(__b, __e, __iob, __err, __v);
737 }
738
739 _LIBCPP_ALWAYS_INLINE
740 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
741 ios_base::iostate& __err, unsigned int& __v) const
742 {
743 return do_get(__b, __e, __iob, __err, __v);
744 }
745
746 _LIBCPP_ALWAYS_INLINE
747 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
748 ios_base::iostate& __err, unsigned long& __v) const
749 {
750 return do_get(__b, __e, __iob, __err, __v);
751 }
752
753 _LIBCPP_ALWAYS_INLINE
754 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
755 ios_base::iostate& __err, unsigned long long& __v) const
756 {
757 return do_get(__b, __e, __iob, __err, __v);
758 }
759
760 _LIBCPP_ALWAYS_INLINE
761 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
762 ios_base::iostate& __err, float& __v) const
763 {
764 return do_get(__b, __e, __iob, __err, __v);
765 }
766
767 _LIBCPP_ALWAYS_INLINE
768 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
769 ios_base::iostate& __err, double& __v) const
770 {
771 return do_get(__b, __e, __iob, __err, __v);
772 }
773
774 _LIBCPP_ALWAYS_INLINE
775 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
776 ios_base::iostate& __err, long double& __v) const
777 {
778 return do_get(__b, __e, __iob, __err, __v);
779 }
780
781 _LIBCPP_ALWAYS_INLINE
782 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
783 ios_base::iostate& __err, void*& __v) const
784 {
785 return do_get(__b, __e, __iob, __err, __v);
786 }
787
788 static locale::id id;
789
790protected:
Howard Hinnant82894812010-09-22 16:48:34 +0000791 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000792 ~num_get() {}
793
794 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
795 ios_base::iostate& __err, bool& __v) const;
796 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
797 ios_base::iostate& __err, long& __v) const;
798 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
799 ios_base::iostate& __err, long long& __v) const;
800 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
801 ios_base::iostate& __err, unsigned short& __v) const;
802 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
803 ios_base::iostate& __err, unsigned int& __v) const;
804 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
805 ios_base::iostate& __err, unsigned long& __v) const;
806 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
807 ios_base::iostate& __err, unsigned long long& __v) const;
808 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
809 ios_base::iostate& __err, float& __v) const;
810 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
811 ios_base::iostate& __err, double& __v) const;
812 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
813 ios_base::iostate& __err, long double& __v) const;
814 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
815 ios_base::iostate& __err, void*& __v) const;
816};
817
818template <class _CharT, class _InputIterator>
819locale::id
820num_get<_CharT, _InputIterator>::id;
821
822template <class _Tp>
823_Tp
824__num_get_signed_integral(const char* __a, const char* __a_end,
825 ios_base::iostate& __err, int __base)
826{
827 if (__a != __a_end)
828 {
Howard Hinnante7c8da62011-02-25 19:52:41 +0000829 int __save_errno = errno;
830 errno = 0;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000831 char *__p2;
Howard Hinnant2ea1ca92011-09-28 21:05:01 +0000832 long long __ll = strtoll_l(__a, &__p2, __base, _LIBCPP_GET_C_LOCALE);
Howard Hinnante7c8da62011-02-25 19:52:41 +0000833 int __current_errno = errno;
834 if (__current_errno == 0)
835 errno = __save_errno;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000836 if (__p2 != __a_end)
837 {
838 __err = ios_base::failbit;
839 return 0;
840 }
Howard Hinnante7c8da62011-02-25 19:52:41 +0000841 else if (__current_errno == ERANGE ||
842 __ll < numeric_limits<_Tp>::min() ||
843 numeric_limits<_Tp>::max() < __ll)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000844 {
845 __err = ios_base::failbit;
Howard Hinnante7c8da62011-02-25 19:52:41 +0000846 if (__ll > 0)
847 return numeric_limits<_Tp>::max();
848 else
849 return numeric_limits<_Tp>::min();
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000850 }
851 return static_cast<_Tp>(__ll);
852 }
853 __err = ios_base::failbit;
854 return 0;
855}
856
857template <class _Tp>
858_Tp
859__num_get_unsigned_integral(const char* __a, const char* __a_end,
860 ios_base::iostate& __err, int __base)
861{
862 if (__a != __a_end)
863 {
Howard Hinnante7c8da62011-02-25 19:52:41 +0000864 if (*__a == '-')
865 {
866 __err = ios_base::failbit;
867 return 0;
868 }
869 int __save_errno = errno;
870 errno = 0;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000871 char *__p2;
Howard Hinnant2ea1ca92011-09-28 21:05:01 +0000872 unsigned long long __ll = strtoull_l(__a, &__p2, __base, _LIBCPP_GET_C_LOCALE);
Howard Hinnante7c8da62011-02-25 19:52:41 +0000873 int __current_errno = errno;
874 if (__current_errno == 0)
875 errno = __save_errno;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000876 if (__p2 != __a_end)
877 {
878 __err = ios_base::failbit;
879 return 0;
880 }
Howard Hinnante7c8da62011-02-25 19:52:41 +0000881 else if (__current_errno == ERANGE ||
882 numeric_limits<_Tp>::max() < __ll)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000883 {
884 __err = ios_base::failbit;
885 return numeric_limits<_Tp>::max();
886 }
887 return static_cast<_Tp>(__ll);
888 }
889 __err = ios_base::failbit;
890 return 0;
891}
892
893template <class _Tp>
894_Tp
895__num_get_float(const char* __a, const char* __a_end, ios_base::iostate& __err)
896{
897 if (__a != __a_end)
898 {
899 char *__p2;
Howard Hinnant2ea1ca92011-09-28 21:05:01 +0000900 long double __ld = strtold_l(__a, &__p2, _LIBCPP_GET_C_LOCALE);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000901 if (__p2 != __a_end)
902 {
903 __err = ios_base::failbit;
904 return 0;
905 }
906 return static_cast<_Tp>(__ld);
907 }
908 __err = ios_base::failbit;
909 return 0;
910}
911
912template <class _CharT, class _InputIterator>
913_InputIterator
914num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
915 ios_base& __iob,
916 ios_base::iostate& __err,
917 bool& __v) const
918{
919 if ((__iob.flags() & ios_base::boolalpha) == 0)
920 {
921 long __lv = -1;
922 __b = do_get(__b, __e, __iob, __err, __lv);
923 switch (__lv)
924 {
925 case 0:
926 __v = false;
927 break;
928 case 1:
929 __v = true;
930 break;
931 default:
932 __v = true;
933 __err = ios_base::failbit;
934 break;
935 }
936 return __b;
937 }
938 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__iob.getloc());
939 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__iob.getloc());
940 typedef typename numpunct<_CharT>::string_type string_type;
941 const string_type __names[2] = {__np.truename(), __np.falsename()};
942 const string_type* __i = __scan_keyword(__b, __e, __names, __names+2,
943 __ct, __err);
944 __v = __i == __names;
945 return __b;
946}
947
948template <class _CharT, class _InputIterator>
949_InputIterator
950num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
951 ios_base& __iob,
952 ios_base::iostate& __err,
953 long& __v) const
954{
955 // Stage 1
956 int __base = this->__get_base(__iob);
957 // Stage 2
958 char_type __atoms[26];
959 char_type __thousands_sep;
960 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
961 char __a[__num_get_base::__num_get_buf_sz] = {0};
962 char* __a_end = __a;
963 unsigned __g[__num_get_base::__num_get_buf_sz];
964 unsigned* __g_end = __g;
965 unsigned __dc = 0;
966 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +0000967 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000968 __thousands_sep, __grouping, __g, __g_end,
969 __atoms))
970 break;
971 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
972 *__g_end++ = __dc;
973 // Stage 3
974 __v = __num_get_signed_integral<long>(__a, __a_end, __err, __base);
975 // Digit grouping checked
976 __check_grouping(__grouping, __g, __g_end, __err);
977 // EOF checked
978 if (__b == __e)
979 __err |= ios_base::eofbit;
980 return __b;
981}
982
983template <class _CharT, class _InputIterator>
984_InputIterator
985num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
986 ios_base& __iob,
987 ios_base::iostate& __err,
988 long long& __v) const
989{
990 // Stage 1
991 int __base = this->__get_base(__iob);
992 // Stage 2
993 char_type __atoms[26];
994 char_type __thousands_sep;
995 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
996 char __a[__num_get_base::__num_get_buf_sz] = {0};
997 char* __a_end = __a;
998 unsigned __g[__num_get_base::__num_get_buf_sz];
999 unsigned* __g_end = __g;
1000 unsigned __dc = 0;
1001 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001002 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
1003 __thousands_sep, __grouping, __g, __g_end,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001004 __atoms))
1005 break;
1006 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
1007 *__g_end++ = __dc;
1008 // Stage 3
1009 __v = __num_get_signed_integral<long long>(__a, __a_end, __err, __base);
1010 // Digit grouping checked
1011 __check_grouping(__grouping, __g, __g_end, __err);
1012 // EOF checked
1013 if (__b == __e)
1014 __err |= ios_base::eofbit;
1015 return __b;
1016}
1017
1018template <class _CharT, class _InputIterator>
1019_InputIterator
1020num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1021 ios_base& __iob,
1022 ios_base::iostate& __err,
1023 unsigned short& __v) const
1024{
1025 // Stage 1
1026 int __base = this->__get_base(__iob);
1027 // Stage 2
1028 char_type __atoms[26];
1029 char_type __thousands_sep;
1030 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
1031 char __a[__num_get_base::__num_get_buf_sz] = {0};
1032 char* __a_end = __a;
1033 unsigned __g[__num_get_base::__num_get_buf_sz];
1034 unsigned* __g_end = __g;
1035 unsigned __dc = 0;
1036 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001037 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001038 __thousands_sep, __grouping, __g, __g_end,
1039 __atoms))
1040 break;
1041 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
1042 *__g_end++ = __dc;
1043 // Stage 3
1044 __v = __num_get_unsigned_integral<unsigned short>(__a, __a_end, __err, __base);
1045 // Digit grouping checked
1046 __check_grouping(__grouping, __g, __g_end, __err);
1047 // EOF checked
1048 if (__b == __e)
1049 __err |= ios_base::eofbit;
1050 return __b;
1051}
1052
1053template <class _CharT, class _InputIterator>
1054_InputIterator
1055num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1056 ios_base& __iob,
1057 ios_base::iostate& __err,
1058 unsigned int& __v) const
1059{
1060 // Stage 1
1061 int __base = this->__get_base(__iob);
1062 // Stage 2
1063 char_type __atoms[26];
1064 char_type __thousands_sep;
1065 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
1066 char __a[__num_get_base::__num_get_buf_sz] = {0};
1067 char* __a_end = __a;
1068 unsigned __g[__num_get_base::__num_get_buf_sz];
1069 unsigned* __g_end = __g;
1070 unsigned __dc = 0;
1071 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001072 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001073 __thousands_sep, __grouping, __g, __g_end,
1074 __atoms))
1075 break;
1076 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
1077 *__g_end++ = __dc;
1078 // Stage 3
1079 __v = __num_get_unsigned_integral<unsigned int>(__a, __a_end, __err, __base);
1080 // Digit grouping checked
1081 __check_grouping(__grouping, __g, __g_end, __err);
1082 // EOF checked
1083 if (__b == __e)
1084 __err |= ios_base::eofbit;
1085 return __b;
1086}
1087
1088template <class _CharT, class _InputIterator>
1089_InputIterator
1090num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1091 ios_base& __iob,
1092 ios_base::iostate& __err,
1093 unsigned long& __v) const
1094{
1095 // Stage 1
1096 int __base = this->__get_base(__iob);
1097 // Stage 2
1098 char_type __atoms[26];
1099 char_type __thousands_sep;
1100 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
1101 char __a[__num_get_base::__num_get_buf_sz] = {0};
1102 char* __a_end = __a;
1103 unsigned __g[__num_get_base::__num_get_buf_sz];
1104 unsigned* __g_end = __g;
1105 unsigned __dc = 0;
1106 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001107 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001108 __thousands_sep, __grouping, __g, __g_end,
1109 __atoms))
1110 break;
1111 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
1112 *__g_end++ = __dc;
1113 // Stage 3
1114 __v = __num_get_unsigned_integral<unsigned long>(__a, __a_end, __err, __base);
1115 // Digit grouping checked
1116 __check_grouping(__grouping, __g, __g_end, __err);
1117 // EOF checked
1118 if (__b == __e)
1119 __err |= ios_base::eofbit;
1120 return __b;
1121}
1122
1123template <class _CharT, class _InputIterator>
1124_InputIterator
1125num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1126 ios_base& __iob,
1127 ios_base::iostate& __err,
1128 unsigned long long& __v) const
1129{
1130 // Stage 1
1131 int __base = this->__get_base(__iob);
1132 // Stage 2
1133 char_type __atoms[26];
1134 char_type __thousands_sep;
1135 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
1136 char __a[__num_get_base::__num_get_buf_sz] = {0};
1137 char* __a_end = __a;
1138 unsigned __g[__num_get_base::__num_get_buf_sz];
1139 unsigned* __g_end = __g;
1140 unsigned __dc = 0;
1141 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001142 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001143 __thousands_sep, __grouping, __g, __g_end,
1144 __atoms))
1145 break;
1146 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
1147 *__g_end++ = __dc;
1148 // Stage 3
1149 __v = __num_get_unsigned_integral<unsigned long long>(__a, __a_end, __err, __base);
1150 // Digit grouping checked
1151 __check_grouping(__grouping, __g, __g_end, __err);
1152 // EOF checked
1153 if (__b == __e)
1154 __err |= ios_base::eofbit;
1155 return __b;
1156}
1157
1158template <class _CharT, class _InputIterator>
1159_InputIterator
1160num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1161 ios_base& __iob,
1162 ios_base::iostate& __err,
1163 float& __v) const
1164{
1165 // Stage 1, nothing to do
1166 // Stage 2
1167 char_type __atoms[32];
1168 char_type __decimal_point;
1169 char_type __thousands_sep;
Howard Hinnant324bb032010-08-22 00:02:43 +00001170 string __grouping = this->__stage2_float_prep(__iob, __atoms,
1171 __decimal_point,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001172 __thousands_sep);
1173 char __a[__num_get_base::__num_get_buf_sz] = {0};
1174 char* __a_end = __a;
1175 unsigned __g[__num_get_base::__num_get_buf_sz];
1176 unsigned* __g_end = __g;
1177 unsigned __dc = 0;
1178 bool __in_units = true;
1179 char __exp = 'E';
1180 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001181 if (this->__stage2_float_loop(*__b, __in_units, __exp, __a, __a_end,
1182 __decimal_point, __thousands_sep,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001183 __grouping, __g, __g_end,
1184 __dc, __atoms))
1185 break;
1186 if (__grouping.size() != 0 && __in_units && __g_end-__g < __num_get_base::__num_get_buf_sz)
1187 *__g_end++ = __dc;
1188 // Stage 3
1189 __v = __num_get_float<float>(__a, __a_end, __err);
1190 // Digit grouping checked
1191 __check_grouping(__grouping, __g, __g_end, __err);
1192 // EOF checked
1193 if (__b == __e)
1194 __err |= ios_base::eofbit;
1195 return __b;
1196}
1197
1198template <class _CharT, class _InputIterator>
1199_InputIterator
1200num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1201 ios_base& __iob,
1202 ios_base::iostate& __err,
1203 double& __v) const
1204{
1205 // Stage 1, nothing to do
1206 // Stage 2
1207 char_type __atoms[32];
1208 char_type __decimal_point;
1209 char_type __thousands_sep;
Howard Hinnant324bb032010-08-22 00:02:43 +00001210 string __grouping = this->__stage2_float_prep(__iob, __atoms,
1211 __decimal_point,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001212 __thousands_sep);
1213 char __a[__num_get_base::__num_get_buf_sz] = {0};
1214 char* __a_end = __a;
1215 unsigned __g[__num_get_base::__num_get_buf_sz];
1216 unsigned* __g_end = __g;
1217 unsigned __dc = 0;
1218 bool __in_units = true;
1219 char __exp = 'E';
1220 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001221 if (this->__stage2_float_loop(*__b, __in_units, __exp, __a, __a_end,
1222 __decimal_point, __thousands_sep,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001223 __grouping, __g, __g_end,
1224 __dc, __atoms))
1225 break;
1226 if (__grouping.size() != 0 && __in_units && __g_end-__g < __num_get_base::__num_get_buf_sz)
1227 *__g_end++ = __dc;
1228 // Stage 3
1229 __v = __num_get_float<double>(__a, __a_end, __err);
1230 // Digit grouping checked
1231 __check_grouping(__grouping, __g, __g_end, __err);
1232 // EOF checked
1233 if (__b == __e)
1234 __err |= ios_base::eofbit;
1235 return __b;
1236}
1237
1238template <class _CharT, class _InputIterator>
1239_InputIterator
1240num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1241 ios_base& __iob,
1242 ios_base::iostate& __err,
1243 long double& __v) const
1244{
1245 // Stage 1, nothing to do
1246 // Stage 2
1247 char_type __atoms[32];
1248 char_type __decimal_point;
1249 char_type __thousands_sep;
Howard Hinnant324bb032010-08-22 00:02:43 +00001250 string __grouping = this->__stage2_float_prep(__iob, __atoms,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001251 __decimal_point,
1252 __thousands_sep);
1253 char __a[__num_get_base::__num_get_buf_sz] = {0};
1254 char* __a_end = __a;
1255 unsigned __g[__num_get_base::__num_get_buf_sz];
1256 unsigned* __g_end = __g;
1257 unsigned __dc = 0;
1258 bool __in_units = true;
1259 char __exp = 'E';
1260 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001261 if (this->__stage2_float_loop(*__b, __in_units, __exp, __a, __a_end,
1262 __decimal_point, __thousands_sep,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001263 __grouping, __g, __g_end,
1264 __dc, __atoms))
1265 break;
1266 if (__grouping.size() != 0 && __in_units && __g_end-__g < __num_get_base::__num_get_buf_sz)
1267 *__g_end++ = __dc;
1268 // Stage 3
1269 __v = __num_get_float<long double>(__a, __a_end, __err);
1270 // Digit grouping checked
1271 __check_grouping(__grouping, __g, __g_end, __err);
1272 // EOF checked
1273 if (__b == __e)
1274 __err |= ios_base::eofbit;
1275 return __b;
1276}
1277
1278template <class _CharT, class _InputIterator>
1279_InputIterator
1280num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1281 ios_base& __iob,
1282 ios_base::iostate& __err,
1283 void*& __v) const
1284{
1285 // Stage 1
1286 int __base = 16;
1287 // Stage 2
1288 char_type __atoms[26];
Howard Hinnantec3773c2011-12-01 20:21:04 +00001289 char_type __thousands_sep = 0;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001290 string __grouping;
1291 use_facet<ctype<_CharT> >(__iob.getloc()).widen(__num_get_base::__src,
1292 __num_get_base::__src + 26, __atoms);
1293 char __a[__num_get_base::__num_get_buf_sz] = {0};
1294 char* __a_end = __a;
1295 unsigned __g[__num_get_base::__num_get_buf_sz];
1296 unsigned* __g_end = __g;
1297 unsigned __dc = 0;
1298 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001299 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
1300 __thousands_sep, __grouping,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001301 __g, __g_end, __atoms))
1302 break;
1303 // Stage 3
1304 __a[sizeof(__a)-1] = 0;
Howard Hinnant866569b2011-09-28 23:39:33 +00001305#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001306 if (sscanf_l(__a, _LIBCPP_GET_C_LOCALE, "%p", &__v) != 1)
Sean Huntf3907e62011-07-15 05:40:33 +00001307#else
1308 if (__sscanf_l(__a, __cloc(), "%p", &__v) != 1)
1309#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001310 __err = ios_base::failbit;
1311 // EOF checked
1312 if (__b == __e)
1313 __err |= ios_base::eofbit;
1314 return __b;
1315}
1316
Howard Hinnantff926772012-11-06 21:08:48 +00001317_LIBCPP_EXTERN_TEMPLATE(class num_get<char>)
1318_LIBCPP_EXTERN_TEMPLATE(class num_get<wchar_t>)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001319
1320struct __num_put_base
1321{
1322protected:
1323 static void __format_int(char* __fmt, const char* __len, bool __signd,
1324 ios_base::fmtflags __flags);
1325 static bool __format_float(char* __fmt, const char* __len,
1326 ios_base::fmtflags __flags);
1327 static char* __identify_padding(char* __nb, char* __ne,
1328 const ios_base& __iob);
1329};
1330
1331template <class _CharT>
1332struct __num_put
1333 : protected __num_put_base
1334{
1335 static void __widen_and_group_int(char* __nb, char* __np, char* __ne,
1336 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1337 const locale& __loc);
1338 static void __widen_and_group_float(char* __nb, char* __np, char* __ne,
1339 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1340 const locale& __loc);
1341};
1342
1343template <class _CharT>
1344void
1345__num_put<_CharT>::__widen_and_group_int(char* __nb, char* __np, char* __ne,
1346 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1347 const locale& __loc)
1348{
1349 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> > (__loc);
1350 const numpunct<_CharT>& __npt = use_facet<numpunct<_CharT> >(__loc);
1351 string __grouping = __npt.grouping();
1352 if (__grouping.empty())
1353 {
1354 __ct.widen(__nb, __ne, __ob);
1355 __oe = __ob + (__ne - __nb);
1356 }
1357 else
1358 {
1359 __oe = __ob;
1360 char* __nf = __nb;
1361 if (*__nf == '-' || *__nf == '+')
1362 *__oe++ = __ct.widen(*__nf++);
1363 if (__ne - __nf >= 2 && __nf[0] == '0' && (__nf[1] == 'x' ||
1364 __nf[1] == 'X'))
1365 {
1366 *__oe++ = __ct.widen(*__nf++);
1367 *__oe++ = __ct.widen(*__nf++);
1368 }
1369 reverse(__nf, __ne);
1370 _CharT __thousands_sep = __npt.thousands_sep();
1371 unsigned __dc = 0;
1372 unsigned __dg = 0;
1373 for (char* __p = __nf; __p < __ne; ++__p)
1374 {
1375 if (static_cast<unsigned>(__grouping[__dg]) > 0 &&
1376 __dc == static_cast<unsigned>(__grouping[__dg]))
1377 {
1378 *__oe++ = __thousands_sep;
1379 __dc = 0;
1380 if (__dg < __grouping.size()-1)
1381 ++__dg;
1382 }
1383 *__oe++ = __ct.widen(*__p);
1384 ++__dc;
1385 }
1386 reverse(__ob + (__nf - __nb), __oe);
1387 }
1388 if (__np == __ne)
1389 __op = __oe;
1390 else
1391 __op = __ob + (__np - __nb);
1392}
1393
1394template <class _CharT>
1395void
1396__num_put<_CharT>::__widen_and_group_float(char* __nb, char* __np, char* __ne,
1397 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1398 const locale& __loc)
1399{
1400 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> > (__loc);
1401 const numpunct<_CharT>& __npt = use_facet<numpunct<_CharT> >(__loc);
1402 string __grouping = __npt.grouping();
1403 __oe = __ob;
1404 char* __nf = __nb;
1405 if (*__nf == '-' || *__nf == '+')
1406 *__oe++ = __ct.widen(*__nf++);
1407 char* __ns;
1408 if (__ne - __nf >= 2 && __nf[0] == '0' && (__nf[1] == 'x' ||
1409 __nf[1] == 'X'))
1410 {
1411 *__oe++ = __ct.widen(*__nf++);
1412 *__oe++ = __ct.widen(*__nf++);
1413 for (__ns = __nf; __ns < __ne; ++__ns)
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001414 if (!isxdigit_l(*__ns, _LIBCPP_GET_C_LOCALE))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001415 break;
1416 }
1417 else
1418 {
1419 for (__ns = __nf; __ns < __ne; ++__ns)
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001420 if (!isdigit_l(*__ns, _LIBCPP_GET_C_LOCALE))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001421 break;
1422 }
1423 if (__grouping.empty())
1424 {
1425 __ct.widen(__nf, __ns, __oe);
1426 __oe += __ns - __nf;
1427 }
1428 else
1429 {
1430 reverse(__nf, __ns);
1431 _CharT __thousands_sep = __npt.thousands_sep();
1432 unsigned __dc = 0;
1433 unsigned __dg = 0;
1434 for (char* __p = __nf; __p < __ns; ++__p)
1435 {
1436 if (__grouping[__dg] > 0 && __dc == static_cast<unsigned>(__grouping[__dg]))
1437 {
1438 *__oe++ = __thousands_sep;
1439 __dc = 0;
1440 if (__dg < __grouping.size()-1)
1441 ++__dg;
1442 }
1443 *__oe++ = __ct.widen(*__p);
1444 ++__dc;
1445 }
1446 reverse(__ob + (__nf - __nb), __oe);
1447 }
1448 for (__nf = __ns; __nf < __ne; ++__nf)
1449 {
1450 if (*__nf == '.')
1451 {
1452 *__oe++ = __npt.decimal_point();
1453 ++__nf;
1454 break;
1455 }
1456 else
1457 *__oe++ = __ct.widen(*__nf);
1458 }
1459 __ct.widen(__nf, __ne, __oe);
1460 __oe += __ne - __nf;
1461 if (__np == __ne)
1462 __op = __oe;
1463 else
1464 __op = __ob + (__np - __nb);
1465}
1466
Howard Hinnantff926772012-11-06 21:08:48 +00001467_LIBCPP_EXTERN_TEMPLATE(struct __num_put<char>)
1468_LIBCPP_EXTERN_TEMPLATE(struct __num_put<wchar_t>)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001469
1470template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00001471class _LIBCPP_VISIBLE num_put
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001472 : public locale::facet,
1473 private __num_put<_CharT>
1474{
1475public:
1476 typedef _CharT char_type;
1477 typedef _OutputIterator iter_type;
1478
1479 _LIBCPP_ALWAYS_INLINE
1480 explicit num_put(size_t __refs = 0)
1481 : locale::facet(__refs) {}
1482
1483 _LIBCPP_ALWAYS_INLINE
1484 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1485 bool __v) const
1486 {
1487 return do_put(__s, __iob, __fl, __v);
1488 }
1489
1490 _LIBCPP_ALWAYS_INLINE
1491 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1492 long __v) const
1493 {
1494 return do_put(__s, __iob, __fl, __v);
1495 }
1496
1497 _LIBCPP_ALWAYS_INLINE
1498 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1499 long long __v) const
1500 {
1501 return do_put(__s, __iob, __fl, __v);
1502 }
1503
1504 _LIBCPP_ALWAYS_INLINE
1505 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1506 unsigned long __v) const
1507 {
1508 return do_put(__s, __iob, __fl, __v);
1509 }
1510
1511 _LIBCPP_ALWAYS_INLINE
1512 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1513 unsigned long long __v) const
1514 {
1515 return do_put(__s, __iob, __fl, __v);
1516 }
1517
1518 _LIBCPP_ALWAYS_INLINE
1519 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1520 double __v) const
1521 {
1522 return do_put(__s, __iob, __fl, __v);
1523 }
1524
1525 _LIBCPP_ALWAYS_INLINE
1526 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1527 long double __v) const
1528 {
1529 return do_put(__s, __iob, __fl, __v);
1530 }
1531
1532 _LIBCPP_ALWAYS_INLINE
1533 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1534 const void* __v) const
1535 {
1536 return do_put(__s, __iob, __fl, __v);
1537 }
1538
1539 static locale::id id;
1540
1541protected:
Howard Hinnant82894812010-09-22 16:48:34 +00001542 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001543 ~num_put() {}
1544
1545 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1546 bool __v) const;
1547 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1548 long __v) const;
1549 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1550 long long __v) const;
1551 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1552 unsigned long) const;
1553 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1554 unsigned long long) const;
1555 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1556 double __v) const;
1557 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1558 long double __v) const;
1559 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1560 const void* __v) const;
1561};
1562
1563template <class _CharT, class _OutputIterator>
1564locale::id
1565num_put<_CharT, _OutputIterator>::id;
1566
1567template <class _CharT, class _OutputIterator>
1568_LIBCPP_HIDDEN
1569_OutputIterator
1570__pad_and_output(_OutputIterator __s,
1571 const _CharT* __ob, const _CharT* __op, const _CharT* __oe,
1572 ios_base& __iob, _CharT __fl)
1573{
1574 streamsize __sz = __oe - __ob;
1575 streamsize __ns = __iob.width();
1576 if (__ns > __sz)
1577 __ns -= __sz;
1578 else
1579 __ns = 0;
1580 for (;__ob < __op; ++__ob, ++__s)
1581 *__s = *__ob;
1582 for (; __ns; --__ns, ++__s)
1583 *__s = __fl;
1584 for (; __ob < __oe; ++__ob, ++__s)
1585 *__s = *__ob;
1586 __iob.width(0);
1587 return __s;
1588}
1589
Howard Hinnanta585de62012-09-19 19:14:15 +00001590template <class _CharT, class _Traits>
1591_LIBCPP_HIDDEN
1592ostreambuf_iterator<_CharT, _Traits>
1593__pad_and_output(ostreambuf_iterator<_CharT, _Traits> __s,
1594 const _CharT* __ob, const _CharT* __op, const _CharT* __oe,
1595 ios_base& __iob, _CharT __fl)
1596{
1597 if (__s.__sbuf_ == nullptr)
1598 return __s;
1599 streamsize __sz = __oe - __ob;
1600 streamsize __ns = __iob.width();
1601 if (__ns > __sz)
1602 __ns -= __sz;
1603 else
1604 __ns = 0;
1605 streamsize __np = __op - __ob;
1606 if (__np > 0)
1607 {
1608 if (__s.__sbuf_->sputn(__ob, __np) != __np)
1609 {
1610 __s.__sbuf_ = nullptr;
1611 return __s;
1612 }
1613 }
1614 if (__ns > 0)
1615 {
1616 basic_string<_CharT, _Traits> __sp(__ns, __fl);
1617 if (__s.__sbuf_->sputn(__sp.data(), __ns) != __ns)
1618 {
1619 __s.__sbuf_ = nullptr;
1620 return __s;
1621 }
1622 }
1623 __np = __oe - __op;
1624 if (__np > 0)
1625 {
1626 if (__s.__sbuf_->sputn(__op, __np) != __np)
1627 {
1628 __s.__sbuf_ = nullptr;
1629 return __s;
1630 }
1631 }
1632 __iob.width(0);
1633 return __s;
1634}
1635
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001636template <class _CharT, class _OutputIterator>
1637_OutputIterator
1638num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1639 char_type __fl, bool __v) const
1640{
1641 if ((__iob.flags() & ios_base::boolalpha) == 0)
1642 return do_put(__s, __iob, __fl, (unsigned long)__v);
1643 const numpunct<char_type>& __np = use_facet<numpunct<char_type> >(__iob.getloc());
1644 typedef typename numpunct<char_type>::string_type string_type;
1645 string_type __nm = __v ? __np.truename() : __np.falsename();
1646 for (typename string_type::iterator __i = __nm.begin(); __i != __nm.end(); ++__i, ++__s)
1647 *__s = *__i;
1648 return __s;
1649}
1650
1651template <class _CharT, class _OutputIterator>
1652_OutputIterator
1653num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1654 char_type __fl, long __v) const
1655{
1656 // Stage 1 - Get number in narrow char
1657 char __fmt[6] = {'%', 0};
1658 const char* __len = "l";
1659 this->__format_int(__fmt+1, __len, true, __iob.flags());
1660 const unsigned __nbuf = (numeric_limits<long>::digits / 3)
1661 + ((numeric_limits<long>::digits % 3) != 0)
1662 + 1;
1663 char __nar[__nbuf];
Howard Hinnant866569b2011-09-28 23:39:33 +00001664#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001665 int __nc = sprintf_l(__nar, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001666#else
1667 int __nc = __sprintf_l(__nar, __cloc(), __fmt, __v);
1668#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001669 char* __ne = __nar + __nc;
1670 char* __np = this->__identify_padding(__nar, __ne, __iob);
1671 // Stage 2 - Widen __nar while adding thousands separators
1672 char_type __o[2*(__nbuf-1) - 1];
1673 char_type* __op; // pad here
1674 char_type* __oe; // end of output
1675 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1676 // [__o, __oe) contains thousands_sep'd wide number
1677 // Stage 3 & 4
1678 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1679}
1680
1681template <class _CharT, class _OutputIterator>
1682_OutputIterator
1683num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1684 char_type __fl, long long __v) const
1685{
1686 // Stage 1 - Get number in narrow char
1687 char __fmt[8] = {'%', 0};
1688 const char* __len = "ll";
1689 this->__format_int(__fmt+1, __len, true, __iob.flags());
1690 const unsigned __nbuf = (numeric_limits<long long>::digits / 3)
1691 + ((numeric_limits<long long>::digits % 3) != 0)
1692 + 1;
1693 char __nar[__nbuf];
Howard Hinnant866569b2011-09-28 23:39:33 +00001694#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001695 int __nc = sprintf_l(__nar, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001696#else
1697 int __nc = __sprintf_l(__nar, __cloc(), __fmt, __v);
1698#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001699 char* __ne = __nar + __nc;
1700 char* __np = this->__identify_padding(__nar, __ne, __iob);
1701 // Stage 2 - Widen __nar while adding thousands separators
1702 char_type __o[2*(__nbuf-1) - 1];
1703 char_type* __op; // pad here
1704 char_type* __oe; // end of output
1705 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1706 // [__o, __oe) contains thousands_sep'd wide number
1707 // Stage 3 & 4
1708 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1709}
1710
1711template <class _CharT, class _OutputIterator>
1712_OutputIterator
1713num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1714 char_type __fl, unsigned long __v) const
1715{
1716 // Stage 1 - Get number in narrow char
1717 char __fmt[6] = {'%', 0};
1718 const char* __len = "l";
1719 this->__format_int(__fmt+1, __len, false, __iob.flags());
1720 const unsigned __nbuf = (numeric_limits<unsigned long>::digits / 3)
1721 + ((numeric_limits<unsigned long>::digits % 3) != 0)
1722 + 1;
1723 char __nar[__nbuf];
Howard Hinnant866569b2011-09-28 23:39:33 +00001724#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001725 int __nc = sprintf_l(__nar, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001726#else
1727 int __nc = __sprintf_l(__nar, __cloc(), __fmt, __v);
1728#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001729 char* __ne = __nar + __nc;
1730 char* __np = this->__identify_padding(__nar, __ne, __iob);
1731 // Stage 2 - Widen __nar while adding thousands separators
1732 char_type __o[2*(__nbuf-1) - 1];
1733 char_type* __op; // pad here
1734 char_type* __oe; // end of output
1735 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1736 // [__o, __oe) contains thousands_sep'd wide number
1737 // Stage 3 & 4
1738 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1739}
1740
1741template <class _CharT, class _OutputIterator>
1742_OutputIterator
1743num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1744 char_type __fl, unsigned long long __v) const
1745{
1746 // Stage 1 - Get number in narrow char
1747 char __fmt[8] = {'%', 0};
1748 const char* __len = "ll";
1749 this->__format_int(__fmt+1, __len, false, __iob.flags());
1750 const unsigned __nbuf = (numeric_limits<unsigned long long>::digits / 3)
1751 + ((numeric_limits<unsigned long long>::digits % 3) != 0)
1752 + 1;
1753 char __nar[__nbuf];
Howard Hinnant866569b2011-09-28 23:39:33 +00001754#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001755 int __nc = sprintf_l(__nar, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001756#else
1757 int __nc = __sprintf_l(__nar, __cloc(), __fmt, __v);
1758#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001759 char* __ne = __nar + __nc;
1760 char* __np = this->__identify_padding(__nar, __ne, __iob);
1761 // Stage 2 - Widen __nar while adding thousands separators
1762 char_type __o[2*(__nbuf-1) - 1];
1763 char_type* __op; // pad here
1764 char_type* __oe; // end of output
1765 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1766 // [__o, __oe) contains thousands_sep'd wide number
1767 // Stage 3 & 4
1768 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1769}
1770
1771template <class _CharT, class _OutputIterator>
1772_OutputIterator
1773num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1774 char_type __fl, double __v) const
1775{
1776 // Stage 1 - Get number in narrow char
1777 char __fmt[8] = {'%', 0};
1778 const char* __len = "";
1779 bool __specify_precision = this->__format_float(__fmt+1, __len, __iob.flags());
1780 const unsigned __nbuf = 30;
1781 char __nar[__nbuf];
1782 char* __nb = __nar;
1783 int __nc;
1784 if (__specify_precision)
Howard Hinnant866569b2011-09-28 23:39:33 +00001785#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001786 __nc = snprintf_l(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt,
Howard Hinnantadff4892010-05-24 17:49:41 +00001787 (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001788#else
1789 __nc = __snprintf_l(__nb, __nbuf, __cloc(), __fmt,
1790 (int)__iob.precision(), __v);
1791#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001792 else
Howard Hinnant866569b2011-09-28 23:39:33 +00001793#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001794 __nc = snprintf_l(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001795#else
1796 __nc = __snprintf_l(__nb, __nbuf, __cloc(), __fmt, __v);
1797#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001798 unique_ptr<char, void(*)(void*)> __nbh(0, free);
1799 if (__nc > static_cast<int>(__nbuf-1))
1800 {
1801 if (__specify_precision)
Howard Hinnant866569b2011-09-28 23:39:33 +00001802#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001803 __nc = asprintf_l(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001804#else
1805 __nc = __asprintf_l(&__nb, __cloc(), __fmt,
David Chisnallc512df12011-09-21 08:39:44 +00001806 (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001807#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001808 else
Howard Hinnant866569b2011-09-28 23:39:33 +00001809#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001810 __nc = asprintf_l(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001811#else
David Chisnallc512df12011-09-21 08:39:44 +00001812 __nc = __asprintf_l(&__nb, __cloc(), __fmt, (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001813#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001814 if (__nb == 0)
1815 __throw_bad_alloc();
1816 __nbh.reset(__nb);
1817 }
1818 char* __ne = __nb + __nc;
1819 char* __np = this->__identify_padding(__nb, __ne, __iob);
1820 // Stage 2 - Widen __nar while adding thousands separators
1821 char_type __o[2*(__nbuf-1) - 1];
1822 char_type* __ob = __o;
1823 unique_ptr<char_type, void(*)(void*)> __obh(0, free);
1824 if (__nb != __nar)
1825 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00001826 __ob = (char_type*)malloc(2*static_cast<size_t>(__nc)*sizeof(char_type));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001827 if (__ob == 0)
1828 __throw_bad_alloc();
1829 __obh.reset(__ob);
1830 }
1831 char_type* __op; // pad here
1832 char_type* __oe; // end of output
1833 this->__widen_and_group_float(__nb, __np, __ne, __ob, __op, __oe, __iob.getloc());
1834 // [__o, __oe) contains thousands_sep'd wide number
1835 // Stage 3 & 4
1836 __s = __pad_and_output(__s, __ob, __op, __oe, __iob, __fl);
1837 return __s;
1838}
1839
1840template <class _CharT, class _OutputIterator>
1841_OutputIterator
1842num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1843 char_type __fl, long double __v) const
1844{
1845 // Stage 1 - Get number in narrow char
1846 char __fmt[8] = {'%', 0};
1847 const char* __len = "L";
1848 bool __specify_precision = this->__format_float(__fmt+1, __len, __iob.flags());
1849 const unsigned __nbuf = 30;
1850 char __nar[__nbuf];
1851 char* __nb = __nar;
1852 int __nc;
1853 if (__specify_precision)
Howard Hinnant866569b2011-09-28 23:39:33 +00001854#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001855 __nc = snprintf_l(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt,
Howard Hinnantadff4892010-05-24 17:49:41 +00001856 (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001857#else
1858 __nc = __snprintf_l(__nb, __nbuf, __cloc(), __fmt,
1859 (int)__iob.precision(), __v);
1860#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001861 else
Howard Hinnant866569b2011-09-28 23:39:33 +00001862#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001863 __nc = snprintf_l(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001864#else
1865 __nc = __snprintf_l(__nb, __nbuf, __cloc(), __fmt, __v);
1866#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001867 unique_ptr<char, void(*)(void*)> __nbh(0, free);
1868 if (__nc > static_cast<int>(__nbuf-1))
1869 {
1870 if (__specify_precision)
Howard Hinnant866569b2011-09-28 23:39:33 +00001871#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001872 __nc = asprintf_l(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001873#else
1874 __nc = __asprintf_l(&__nb, __cloc(), __fmt,
David Chisnallc512df12011-09-21 08:39:44 +00001875 (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001876#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001877 else
Howard Hinnant866569b2011-09-28 23:39:33 +00001878#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001879 __nc = asprintf_l(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001880#else
David Chisnallc512df12011-09-21 08:39:44 +00001881 __nc = __asprintf_l(&__nb, __cloc(), __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001882#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001883 if (__nb == 0)
1884 __throw_bad_alloc();
1885 __nbh.reset(__nb);
1886 }
1887 char* __ne = __nb + __nc;
1888 char* __np = this->__identify_padding(__nb, __ne, __iob);
1889 // Stage 2 - Widen __nar while adding thousands separators
1890 char_type __o[2*(__nbuf-1) - 1];
1891 char_type* __ob = __o;
1892 unique_ptr<char_type, void(*)(void*)> __obh(0, free);
1893 if (__nb != __nar)
1894 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00001895 __ob = (char_type*)malloc(2*static_cast<size_t>(__nc)*sizeof(char_type));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001896 if (__ob == 0)
1897 __throw_bad_alloc();
1898 __obh.reset(__ob);
1899 }
1900 char_type* __op; // pad here
1901 char_type* __oe; // end of output
1902 this->__widen_and_group_float(__nb, __np, __ne, __ob, __op, __oe, __iob.getloc());
1903 // [__o, __oe) contains thousands_sep'd wide number
1904 // Stage 3 & 4
1905 __s = __pad_and_output(__s, __ob, __op, __oe, __iob, __fl);
1906 return __s;
1907}
1908
1909template <class _CharT, class _OutputIterator>
1910_OutputIterator
1911num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1912 char_type __fl, const void* __v) const
1913{
1914 // Stage 1 - Get pointer in narrow char
1915 char __fmt[6] = "%p";
1916 const unsigned __nbuf = 20;
1917 char __nar[__nbuf];
Howard Hinnant866569b2011-09-28 23:39:33 +00001918#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001919 int __nc = sprintf_l(__nar, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001920#else
1921 int __nc = __sprintf_l(__nar, __cloc(), __fmt, __v);
1922#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001923 char* __ne = __nar + __nc;
1924 char* __np = this->__identify_padding(__nar, __ne, __iob);
1925 // Stage 2 - Widen __nar
1926 char_type __o[2*(__nbuf-1) - 1];
1927 char_type* __op; // pad here
1928 char_type* __oe; // end of output
1929 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
1930 __ct.widen(__nar, __ne, __o);
1931 __oe = __o + (__ne - __nar);
1932 if (__np == __ne)
1933 __op = __oe;
1934 else
1935 __op = __o + (__np - __nar);
1936 // [__o, __oe) contains wide number
1937 // Stage 3 & 4
1938 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1939}
1940
Howard Hinnantff926772012-11-06 21:08:48 +00001941_LIBCPP_EXTERN_TEMPLATE(class num_put<char>)
1942_LIBCPP_EXTERN_TEMPLATE(class num_put<wchar_t>)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001943
1944template <class _CharT, class _InputIterator>
1945_LIBCPP_HIDDEN
1946int
1947__get_up_to_n_digits(_InputIterator& __b, _InputIterator __e,
1948 ios_base::iostate& __err, const ctype<_CharT>& __ct, int __n)
1949{
1950 // Precondition: __n >= 1
1951 if (__b == __e)
1952 {
1953 __err |= ios_base::eofbit | ios_base::failbit;
1954 return 0;
1955 }
1956 // get first digit
1957 _CharT __c = *__b;
1958 if (!__ct.is(ctype_base::digit, __c))
1959 {
1960 __err |= ios_base::failbit;
1961 return 0;
1962 }
1963 int __r = __ct.narrow(__c, 0) - '0';
1964 for (++__b, --__n; __b != __e && __n > 0; ++__b, --__n)
1965 {
1966 // get next digit
1967 __c = *__b;
1968 if (!__ct.is(ctype_base::digit, __c))
1969 return __r;
1970 __r = __r * 10 + __ct.narrow(__c, 0) - '0';
1971 }
1972 if (__b == __e)
1973 __err |= ios_base::eofbit;
1974 return __r;
1975}
1976
Howard Hinnant82894812010-09-22 16:48:34 +00001977class _LIBCPP_VISIBLE time_base
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001978{
1979public:
1980 enum dateorder {no_order, dmy, mdy, ymd, ydm};
1981};
1982
1983template <class _CharT>
Howard Hinnant2d72b1e2010-12-17 14:46:43 +00001984class __time_get_c_storage // purposefully not decorated
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001985{
1986protected:
1987 typedef basic_string<_CharT> string_type;
1988
1989 virtual const string_type* __weeks() const;
1990 virtual const string_type* __months() const;
1991 virtual const string_type* __am_pm() const;
1992 virtual const string_type& __c() const;
1993 virtual const string_type& __r() const;
1994 virtual const string_type& __x() const;
1995 virtual const string_type& __X() const;
1996};
1997
1998template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00001999class _LIBCPP_VISIBLE time_get
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002000 : public locale::facet,
2001 public time_base,
2002 private __time_get_c_storage<_CharT>
2003{
2004public:
2005 typedef _CharT char_type;
2006 typedef _InputIterator iter_type;
2007 typedef time_base::dateorder dateorder;
2008 typedef basic_string<char_type> string_type;
2009
2010 _LIBCPP_ALWAYS_INLINE
2011 explicit time_get(size_t __refs = 0)
2012 : locale::facet(__refs) {}
2013
2014 _LIBCPP_ALWAYS_INLINE
2015 dateorder date_order() const
2016 {
2017 return this->do_date_order();
2018 }
2019
2020 _LIBCPP_ALWAYS_INLINE
2021 iter_type get_time(iter_type __b, iter_type __e, ios_base& __iob,
2022 ios_base::iostate& __err, tm* __tm) const
2023 {
2024 return do_get_time(__b, __e, __iob, __err, __tm);
2025 }
2026
2027 _LIBCPP_ALWAYS_INLINE
2028 iter_type get_date(iter_type __b, iter_type __e, ios_base& __iob,
2029 ios_base::iostate& __err, tm* __tm) const
2030 {
2031 return do_get_date(__b, __e, __iob, __err, __tm);
2032 }
2033
2034 _LIBCPP_ALWAYS_INLINE
2035 iter_type get_weekday(iter_type __b, iter_type __e, ios_base& __iob,
2036 ios_base::iostate& __err, tm* __tm) const
2037 {
2038 return do_get_weekday(__b, __e, __iob, __err, __tm);
2039 }
2040
2041 _LIBCPP_ALWAYS_INLINE
2042 iter_type get_monthname(iter_type __b, iter_type __e, ios_base& __iob,
2043 ios_base::iostate& __err, tm* __tm) const
2044 {
2045 return do_get_monthname(__b, __e, __iob, __err, __tm);
2046 }
2047
2048 _LIBCPP_ALWAYS_INLINE
2049 iter_type get_year(iter_type __b, iter_type __e, ios_base& __iob,
2050 ios_base::iostate& __err, tm* __tm) const
2051 {
2052 return do_get_year(__b, __e, __iob, __err, __tm);
2053 }
2054
2055 _LIBCPP_ALWAYS_INLINE
2056 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
2057 ios_base::iostate& __err, tm *__tm,
2058 char __fmt, char __mod = 0) const
2059 {
2060 return do_get(__b, __e, __iob, __err, __tm, __fmt, __mod);
2061 }
2062
2063 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
2064 ios_base::iostate& __err, tm* __tm,
2065 const char_type* __fmtb, const char_type* __fmte) const;
2066
2067 static locale::id id;
2068
2069protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002070 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002071 ~time_get() {}
2072
2073 virtual dateorder do_date_order() const;
2074 virtual iter_type do_get_time(iter_type __b, iter_type __e, ios_base& __iob,
2075 ios_base::iostate& __err, tm* __tm) const;
2076 virtual iter_type do_get_date(iter_type __b, iter_type __e, ios_base& __iob,
2077 ios_base::iostate& __err, tm* __tm) const;
2078 virtual iter_type do_get_weekday(iter_type __b, iter_type __e, ios_base& __iob,
2079 ios_base::iostate& __err, tm* __tm) const;
2080 virtual iter_type do_get_monthname(iter_type __b, iter_type __e, ios_base& __iob,
2081 ios_base::iostate& __err, tm* __tm) const;
2082 virtual iter_type do_get_year(iter_type __b, iter_type __e, ios_base& __iob,
2083 ios_base::iostate& __err, tm* __tm) const;
2084 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
2085 ios_base::iostate& __err, tm* __tm,
2086 char __fmt, char __mod) const;
2087private:
2088 void __get_white_space(iter_type& __b, iter_type __e,
2089 ios_base::iostate& __err, const ctype<char_type>& __ct) const;
2090 void __get_percent(iter_type& __b, iter_type __e, ios_base::iostate& __err,
2091 const ctype<char_type>& __ct) const;
2092
2093 void __get_weekdayname(int& __m,
2094 iter_type& __b, iter_type __e,
2095 ios_base::iostate& __err,
2096 const ctype<char_type>& __ct) const;
2097 void __get_monthname(int& __m,
2098 iter_type& __b, iter_type __e,
2099 ios_base::iostate& __err,
2100 const ctype<char_type>& __ct) const;
2101 void __get_day(int& __d,
2102 iter_type& __b, iter_type __e,
2103 ios_base::iostate& __err,
2104 const ctype<char_type>& __ct) const;
2105 void __get_month(int& __m,
2106 iter_type& __b, iter_type __e,
2107 ios_base::iostate& __err,
2108 const ctype<char_type>& __ct) const;
2109 void __get_year(int& __y,
2110 iter_type& __b, iter_type __e,
2111 ios_base::iostate& __err,
2112 const ctype<char_type>& __ct) const;
2113 void __get_year4(int& __y,
2114 iter_type& __b, iter_type __e,
2115 ios_base::iostate& __err,
2116 const ctype<char_type>& __ct) const;
2117 void __get_hour(int& __d,
2118 iter_type& __b, iter_type __e,
2119 ios_base::iostate& __err,
2120 const ctype<char_type>& __ct) const;
2121 void __get_12_hour(int& __h,
2122 iter_type& __b, iter_type __e,
2123 ios_base::iostate& __err,
2124 const ctype<char_type>& __ct) const;
2125 void __get_am_pm(int& __h,
2126 iter_type& __b, iter_type __e,
2127 ios_base::iostate& __err,
2128 const ctype<char_type>& __ct) const;
2129 void __get_minute(int& __m,
2130 iter_type& __b, iter_type __e,
2131 ios_base::iostate& __err,
2132 const ctype<char_type>& __ct) const;
2133 void __get_second(int& __s,
2134 iter_type& __b, iter_type __e,
2135 ios_base::iostate& __err,
2136 const ctype<char_type>& __ct) const;
2137 void __get_weekday(int& __w,
2138 iter_type& __b, iter_type __e,
2139 ios_base::iostate& __err,
2140 const ctype<char_type>& __ct) const;
2141 void __get_day_year_num(int& __w,
2142 iter_type& __b, iter_type __e,
2143 ios_base::iostate& __err,
2144 const ctype<char_type>& __ct) const;
2145};
2146
2147template <class _CharT, class _InputIterator>
2148locale::id
2149time_get<_CharT, _InputIterator>::id;
2150
2151// time_get primatives
2152
2153template <class _CharT, class _InputIterator>
2154void
2155time_get<_CharT, _InputIterator>::__get_weekdayname(int& __w,
2156 iter_type& __b, iter_type __e,
2157 ios_base::iostate& __err,
2158 const ctype<char_type>& __ct) const
2159{
2160 // Note: ignoring case comes from the POSIX strptime spec
2161 const string_type* __wk = this->__weeks();
Howard Hinnantec3773c2011-12-01 20:21:04 +00002162 ptrdiff_t __i = __scan_keyword(__b, __e, __wk, __wk+14, __ct, __err, false) - __wk;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002163 if (__i < 14)
2164 __w = __i % 7;
2165}
2166
2167template <class _CharT, class _InputIterator>
2168void
2169time_get<_CharT, _InputIterator>::__get_monthname(int& __m,
2170 iter_type& __b, iter_type __e,
2171 ios_base::iostate& __err,
2172 const ctype<char_type>& __ct) const
2173{
2174 // Note: ignoring case comes from the POSIX strptime spec
2175 const string_type* __month = this->__months();
Howard Hinnantec3773c2011-12-01 20:21:04 +00002176 ptrdiff_t __i = __scan_keyword(__b, __e, __month, __month+24, __ct, __err, false) - __month;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002177 if (__i < 24)
2178 __m = __i % 12;
2179}
2180
2181template <class _CharT, class _InputIterator>
2182void
2183time_get<_CharT, _InputIterator>::__get_day(int& __d,
2184 iter_type& __b, iter_type __e,
2185 ios_base::iostate& __err,
2186 const ctype<char_type>& __ct) const
2187{
2188 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2189 if (!(__err & ios_base::failbit) && 1 <= __t && __t <= 31)
2190 __d = __t;
2191 else
2192 __err |= ios_base::failbit;
2193}
2194
2195template <class _CharT, class _InputIterator>
2196void
2197time_get<_CharT, _InputIterator>::__get_month(int& __m,
2198 iter_type& __b, iter_type __e,
2199 ios_base::iostate& __err,
2200 const ctype<char_type>& __ct) const
2201{
2202 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2) - 1;
2203 if (!(__err & ios_base::failbit) && __t <= 11)
2204 __m = __t;
2205 else
2206 __err |= ios_base::failbit;
2207}
2208
2209template <class _CharT, class _InputIterator>
2210void
2211time_get<_CharT, _InputIterator>::__get_year(int& __y,
2212 iter_type& __b, iter_type __e,
2213 ios_base::iostate& __err,
2214 const ctype<char_type>& __ct) const
2215{
2216 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 4);
2217 if (!(__err & ios_base::failbit))
2218 {
2219 if (__t < 69)
2220 __t += 2000;
2221 else if (69 <= __t && __t <= 99)
2222 __t += 1900;
2223 __y = __t - 1900;
2224 }
2225}
2226
2227template <class _CharT, class _InputIterator>
2228void
2229time_get<_CharT, _InputIterator>::__get_year4(int& __y,
2230 iter_type& __b, iter_type __e,
2231 ios_base::iostate& __err,
2232 const ctype<char_type>& __ct) const
2233{
2234 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 4);
2235 if (!(__err & ios_base::failbit))
2236 __y = __t - 1900;
2237}
2238
2239template <class _CharT, class _InputIterator>
2240void
2241time_get<_CharT, _InputIterator>::__get_hour(int& __h,
2242 iter_type& __b, iter_type __e,
2243 ios_base::iostate& __err,
2244 const ctype<char_type>& __ct) const
2245{
2246 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2247 if (!(__err & ios_base::failbit) && __t <= 23)
2248 __h = __t;
2249 else
2250 __err |= ios_base::failbit;
2251}
2252
2253template <class _CharT, class _InputIterator>
2254void
2255time_get<_CharT, _InputIterator>::__get_12_hour(int& __h,
2256 iter_type& __b, iter_type __e,
2257 ios_base::iostate& __err,
2258 const ctype<char_type>& __ct) const
2259{
2260 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2261 if (!(__err & ios_base::failbit) && 1 <= __t && __t <= 12)
2262 __h = __t;
2263 else
2264 __err |= ios_base::failbit;
2265}
2266
2267template <class _CharT, class _InputIterator>
2268void
2269time_get<_CharT, _InputIterator>::__get_minute(int& __m,
2270 iter_type& __b, iter_type __e,
2271 ios_base::iostate& __err,
2272 const ctype<char_type>& __ct) const
2273{
2274 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2275 if (!(__err & ios_base::failbit) && __t <= 59)
2276 __m = __t;
2277 else
2278 __err |= ios_base::failbit;
2279}
2280
2281template <class _CharT, class _InputIterator>
2282void
2283time_get<_CharT, _InputIterator>::__get_second(int& __s,
2284 iter_type& __b, iter_type __e,
2285 ios_base::iostate& __err,
2286 const ctype<char_type>& __ct) const
2287{
2288 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2289 if (!(__err & ios_base::failbit) && __t <= 60)
2290 __s = __t;
2291 else
2292 __err |= ios_base::failbit;
2293}
2294
2295template <class _CharT, class _InputIterator>
2296void
2297time_get<_CharT, _InputIterator>::__get_weekday(int& __w,
2298 iter_type& __b, iter_type __e,
2299 ios_base::iostate& __err,
2300 const ctype<char_type>& __ct) const
2301{
2302 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 1);
2303 if (!(__err & ios_base::failbit) && __t <= 6)
2304 __w = __t;
2305 else
2306 __err |= ios_base::failbit;
2307}
2308
2309template <class _CharT, class _InputIterator>
2310void
2311time_get<_CharT, _InputIterator>::__get_day_year_num(int& __d,
2312 iter_type& __b, iter_type __e,
2313 ios_base::iostate& __err,
2314 const ctype<char_type>& __ct) const
2315{
2316 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 3);
2317 if (!(__err & ios_base::failbit) && __t <= 365)
2318 __d = __t;
2319 else
2320 __err |= ios_base::failbit;
2321}
2322
2323template <class _CharT, class _InputIterator>
2324void
2325time_get<_CharT, _InputIterator>::__get_white_space(iter_type& __b, iter_type __e,
2326 ios_base::iostate& __err,
2327 const ctype<char_type>& __ct) const
2328{
2329 for (; __b != __e && __ct.is(ctype_base::space, *__b); ++__b)
2330 ;
2331 if (__b == __e)
2332 __err |= ios_base::eofbit;
2333}
2334
2335template <class _CharT, class _InputIterator>
2336void
2337time_get<_CharT, _InputIterator>::__get_am_pm(int& __h,
2338 iter_type& __b, iter_type __e,
2339 ios_base::iostate& __err,
2340 const ctype<char_type>& __ct) const
2341{
2342 const string_type* __ap = this->__am_pm();
2343 if (__ap[0].size() + __ap[1].size() == 0)
2344 {
2345 __err |= ios_base::failbit;
2346 return;
2347 }
Howard Hinnantec3773c2011-12-01 20:21:04 +00002348 ptrdiff_t __i = __scan_keyword(__b, __e, __ap, __ap+2, __ct, __err, false) - __ap;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002349 if (__i == 0 && __h == 12)
2350 __h = 0;
2351 else if (__i == 1 && __h < 12)
2352 __h += 12;
2353}
2354
2355template <class _CharT, class _InputIterator>
2356void
2357time_get<_CharT, _InputIterator>::__get_percent(iter_type& __b, iter_type __e,
2358 ios_base::iostate& __err,
2359 const ctype<char_type>& __ct) const
2360{
2361 if (__b == __e)
2362 {
2363 __err |= ios_base::eofbit | ios_base::failbit;
2364 return;
2365 }
2366 if (__ct.narrow(*__b, 0) != '%')
2367 __err |= ios_base::failbit;
2368 else if(++__b == __e)
2369 __err |= ios_base::eofbit;
2370}
2371
2372// time_get end primatives
2373
2374template <class _CharT, class _InputIterator>
2375_InputIterator
2376time_get<_CharT, _InputIterator>::get(iter_type __b, iter_type __e,
2377 ios_base& __iob,
2378 ios_base::iostate& __err, tm* __tm,
2379 const char_type* __fmtb, const char_type* __fmte) const
2380{
2381 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2382 __err = ios_base::goodbit;
2383 while (__fmtb != __fmte && __err == ios_base::goodbit)
2384 {
2385 if (__b == __e)
2386 {
2387 __err = ios_base::failbit;
2388 break;
2389 }
2390 if (__ct.narrow(*__fmtb, 0) == '%')
2391 {
2392 if (++__fmtb == __fmte)
2393 {
2394 __err = ios_base::failbit;
2395 break;
2396 }
2397 char __cmd = __ct.narrow(*__fmtb, 0);
2398 char __opt = '\0';
2399 if (__cmd == 'E' || __cmd == '0')
2400 {
2401 if (++__fmtb == __fmte)
2402 {
2403 __err = ios_base::failbit;
2404 break;
2405 }
2406 __opt = __cmd;
2407 __cmd = __ct.narrow(*__fmtb, 0);
2408 }
2409 __b = do_get(__b, __e, __iob, __err, __tm, __cmd, __opt);
2410 ++__fmtb;
2411 }
2412 else if (__ct.is(ctype_base::space, *__fmtb))
2413 {
2414 for (++__fmtb; __fmtb != __fmte && __ct.is(ctype_base::space, *__fmtb); ++__fmtb)
2415 ;
2416 for ( ; __b != __e && __ct.is(ctype_base::space, *__b); ++__b)
2417 ;
2418 }
2419 else if (__ct.toupper(*__b) == __ct.toupper(*__fmtb))
2420 {
2421 ++__b;
2422 ++__fmtb;
2423 }
2424 else
2425 __err = ios_base::failbit;
2426 }
2427 if (__b == __e)
2428 __err |= ios_base::eofbit;
2429 return __b;
2430}
2431
2432template <class _CharT, class _InputIterator>
2433typename time_get<_CharT, _InputIterator>::dateorder
2434time_get<_CharT, _InputIterator>::do_date_order() const
2435{
2436 return mdy;
2437}
2438
2439template <class _CharT, class _InputIterator>
2440_InputIterator
2441time_get<_CharT, _InputIterator>::do_get_time(iter_type __b, iter_type __e,
2442 ios_base& __iob,
2443 ios_base::iostate& __err,
2444 tm* __tm) const
2445{
2446 const char_type __fmt[] = {'%', 'H', ':', '%', 'M', ':', '%', 'S'};
2447 return get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2448}
2449
2450template <class _CharT, class _InputIterator>
2451_InputIterator
2452time_get<_CharT, _InputIterator>::do_get_date(iter_type __b, iter_type __e,
2453 ios_base& __iob,
2454 ios_base::iostate& __err,
2455 tm* __tm) const
2456{
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002457 const string_type& __fmt = this->__x();
2458 return get(__b, __e, __iob, __err, __tm, __fmt.data(), __fmt.data() + __fmt.size());
2459}
2460
2461template <class _CharT, class _InputIterator>
2462_InputIterator
2463time_get<_CharT, _InputIterator>::do_get_weekday(iter_type __b, iter_type __e,
2464 ios_base& __iob,
2465 ios_base::iostate& __err,
2466 tm* __tm) const
2467{
2468 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2469 __get_weekdayname(__tm->tm_wday, __b, __e, __err, __ct);
2470 return __b;
2471}
2472
2473template <class _CharT, class _InputIterator>
2474_InputIterator
2475time_get<_CharT, _InputIterator>::do_get_monthname(iter_type __b, iter_type __e,
2476 ios_base& __iob,
2477 ios_base::iostate& __err,
2478 tm* __tm) const
2479{
2480 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2481 __get_monthname(__tm->tm_mon, __b, __e, __err, __ct);
2482 return __b;
2483}
2484
2485template <class _CharT, class _InputIterator>
2486_InputIterator
2487time_get<_CharT, _InputIterator>::do_get_year(iter_type __b, iter_type __e,
2488 ios_base& __iob,
2489 ios_base::iostate& __err,
2490 tm* __tm) const
2491{
2492 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2493 __get_year(__tm->tm_year, __b, __e, __err, __ct);
2494 return __b;
2495}
2496
2497template <class _CharT, class _InputIterator>
2498_InputIterator
2499time_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
2500 ios_base& __iob,
2501 ios_base::iostate& __err, tm* __tm,
2502 char __fmt, char) const
2503{
2504 __err = ios_base::goodbit;
2505 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2506 switch (__fmt)
2507 {
2508 case 'a':
2509 case 'A':
2510 __get_weekdayname(__tm->tm_wday, __b, __e, __err, __ct);
2511 break;
2512 case 'b':
2513 case 'B':
2514 case 'h':
2515 __get_monthname(__tm->tm_mon, __b, __e, __err, __ct);
2516 break;
2517 case 'c':
2518 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002519 const string_type& __fm = this->__c();
2520 __b = get(__b, __e, __iob, __err, __tm, __fm.data(), __fm.data() + __fm.size());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002521 }
2522 break;
2523 case 'd':
2524 case 'e':
2525 __get_day(__tm->tm_mday, __b, __e, __err, __ct);
2526 break;
2527 case 'D':
2528 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002529 const char_type __fm[] = {'%', 'm', '/', '%', 'd', '/', '%', 'y'};
2530 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm)/sizeof(__fm[0]));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002531 }
2532 break;
Howard Hinnant506b3642011-04-10 17:54:14 +00002533 case 'F':
2534 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002535 const char_type __fm[] = {'%', 'Y', '-', '%', 'm', '-', '%', 'd'};
2536 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm)/sizeof(__fm[0]));
Howard Hinnant506b3642011-04-10 17:54:14 +00002537 }
2538 break;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002539 case 'H':
2540 __get_hour(__tm->tm_hour, __b, __e, __err, __ct);
2541 break;
2542 case 'I':
2543 __get_12_hour(__tm->tm_hour, __b, __e, __err, __ct);
2544 break;
2545 case 'j':
2546 __get_day_year_num(__tm->tm_yday, __b, __e, __err, __ct);
2547 break;
2548 case 'm':
2549 __get_month(__tm->tm_mon, __b, __e, __err, __ct);
2550 break;
2551 case 'M':
2552 __get_minute(__tm->tm_min, __b, __e, __err, __ct);
2553 break;
2554 case 'n':
2555 case 't':
2556 __get_white_space(__b, __e, __err, __ct);
2557 break;
2558 case 'p':
2559 __get_am_pm(__tm->tm_hour, __b, __e, __err, __ct);
2560 break;
2561 case 'r':
2562 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002563 const char_type __fm[] = {'%', 'I', ':', '%', 'M', ':', '%', 'S', ' ', '%', 'p'};
2564 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm)/sizeof(__fm[0]));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002565 }
2566 break;
2567 case 'R':
2568 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002569 const char_type __fm[] = {'%', 'H', ':', '%', 'M'};
2570 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm)/sizeof(__fm[0]));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002571 }
2572 break;
2573 case 'S':
2574 __get_second(__tm->tm_sec, __b, __e, __err, __ct);
2575 break;
2576 case 'T':
2577 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002578 const char_type __fm[] = {'%', 'H', ':', '%', 'M', ':', '%', 'S'};
2579 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm)/sizeof(__fm[0]));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002580 }
2581 break;
2582 case 'w':
2583 __get_weekday(__tm->tm_wday, __b, __e, __err, __ct);
2584 break;
2585 case 'x':
2586 return do_get_date(__b, __e, __iob, __err, __tm);
2587 case 'X':
2588 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002589 const string_type& __fm = this->__X();
2590 __b = get(__b, __e, __iob, __err, __tm, __fm.data(), __fm.data() + __fm.size());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002591 }
2592 break;
2593 case 'y':
2594 __get_year(__tm->tm_year, __b, __e, __err, __ct);
2595 break;
2596 case 'Y':
2597 __get_year4(__tm->tm_year, __b, __e, __err, __ct);
2598 break;
2599 case '%':
2600 __get_percent(__b, __e, __err, __ct);
2601 break;
2602 default:
2603 __err |= ios_base::failbit;
2604 }
2605 return __b;
2606}
2607
Howard Hinnantff926772012-11-06 21:08:48 +00002608_LIBCPP_EXTERN_TEMPLATE(class time_get<char>)
2609_LIBCPP_EXTERN_TEMPLATE(class time_get<wchar_t>)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002610
2611class __time_get
2612{
2613protected:
2614 locale_t __loc_;
2615
2616 __time_get(const char* __nm);
2617 __time_get(const string& __nm);
2618 ~__time_get();
2619};
2620
2621template <class _CharT>
2622class __time_get_storage
2623 : public __time_get
2624{
2625protected:
2626 typedef basic_string<_CharT> string_type;
2627
2628 string_type __weeks_[14];
2629 string_type __months_[24];
2630 string_type __am_pm_[2];
2631 string_type __c_;
2632 string_type __r_;
2633 string_type __x_;
2634 string_type __X_;
2635
2636 explicit __time_get_storage(const char* __nm);
2637 explicit __time_get_storage(const string& __nm);
2638
2639 _LIBCPP_ALWAYS_INLINE ~__time_get_storage() {}
2640
2641 time_base::dateorder __do_date_order() const;
2642
2643private:
2644 void init(const ctype<_CharT>&);
2645 string_type __analyze(char __fmt, const ctype<_CharT>&);
2646};
2647
2648template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00002649class _LIBCPP_VISIBLE time_get_byname
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002650 : public time_get<_CharT, _InputIterator>,
2651 private __time_get_storage<_CharT>
2652{
2653public:
2654 typedef time_base::dateorder dateorder;
2655 typedef _InputIterator iter_type;
2656 typedef _CharT char_type;
2657 typedef basic_string<char_type> string_type;
2658
Howard Hinnant82894812010-09-22 16:48:34 +00002659 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002660 explicit time_get_byname(const char* __nm, size_t __refs = 0)
2661 : time_get<_CharT, _InputIterator>(__refs),
2662 __time_get_storage<_CharT>(__nm) {}
Howard Hinnant82894812010-09-22 16:48:34 +00002663 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002664 explicit time_get_byname(const string& __nm, size_t __refs = 0)
2665 : time_get<_CharT, _InputIterator>(__refs),
2666 __time_get_storage<_CharT>(__nm) {}
2667
2668protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002669 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002670 ~time_get_byname() {}
2671
Howard Hinnant82894812010-09-22 16:48:34 +00002672 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002673 virtual dateorder do_date_order() const {return this->__do_date_order();}
2674private:
Howard Hinnant82894812010-09-22 16:48:34 +00002675 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002676 virtual const string_type* __weeks() const {return this->__weeks_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002677 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002678 virtual const string_type* __months() const {return this->__months_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002679 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002680 virtual const string_type* __am_pm() const {return this->__am_pm_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002681 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002682 virtual const string_type& __c() const {return this->__c_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002683 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002684 virtual const string_type& __r() const {return this->__r_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002685 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002686 virtual const string_type& __x() const {return this->__x_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002687 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002688 virtual const string_type& __X() const {return this->__X_;}
2689};
2690
Howard Hinnantff926772012-11-06 21:08:48 +00002691_LIBCPP_EXTERN_TEMPLATE(class time_get_byname<char>)
2692_LIBCPP_EXTERN_TEMPLATE(class time_get_byname<wchar_t>)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002693
2694class __time_put
2695{
2696 locale_t __loc_;
2697protected:
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00002698 _LIBCPP_ALWAYS_INLINE __time_put() : __loc_(_LIBCPP_GET_C_LOCALE) {}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002699 __time_put(const char* __nm);
2700 __time_put(const string& __nm);
2701 ~__time_put();
2702 void __do_put(char* __nb, char*& __ne, const tm* __tm,
2703 char __fmt, char __mod) const;
2704 void __do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
2705 char __fmt, char __mod) const;
2706};
2707
2708template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00002709class _LIBCPP_VISIBLE time_put
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002710 : public locale::facet,
2711 private __time_put
2712{
2713public:
2714 typedef _CharT char_type;
2715 typedef _OutputIterator iter_type;
2716
2717 _LIBCPP_ALWAYS_INLINE
2718 explicit time_put(size_t __refs = 0)
2719 : locale::facet(__refs) {}
2720
2721 iter_type put(iter_type __s, ios_base& __iob, char_type __fl, const tm* __tm,
2722 const char_type* __pb, const char_type* __pe) const;
2723
2724 _LIBCPP_ALWAYS_INLINE
2725 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
2726 const tm* __tm, char __fmt, char __mod = 0) const
2727 {
2728 return do_put(__s, __iob, __fl, __tm, __fmt, __mod);
2729 }
2730
2731 static locale::id id;
2732
2733protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002734 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002735 ~time_put() {}
2736 virtual iter_type do_put(iter_type __s, ios_base&, char_type, const tm* __tm,
2737 char __fmt, char __mod) const;
2738
Howard Hinnant82894812010-09-22 16:48:34 +00002739 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002740 explicit time_put(const char* __nm, size_t __refs)
2741 : locale::facet(__refs),
2742 __time_put(__nm) {}
Howard Hinnant82894812010-09-22 16:48:34 +00002743 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002744 explicit time_put(const string& __nm, size_t __refs)
2745 : locale::facet(__refs),
2746 __time_put(__nm) {}
2747};
2748
2749template <class _CharT, class _OutputIterator>
2750locale::id
2751time_put<_CharT, _OutputIterator>::id;
2752
2753template <class _CharT, class _OutputIterator>
2754_OutputIterator
2755time_put<_CharT, _OutputIterator>::put(iter_type __s, ios_base& __iob,
2756 char_type __fl, const tm* __tm,
2757 const char_type* __pb,
2758 const char_type* __pe) const
2759{
2760 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2761 for (; __pb != __pe; ++__pb)
2762 {
2763 if (__ct.narrow(*__pb, 0) == '%')
2764 {
2765 if (++__pb == __pe)
2766 {
2767 *__s++ = __pb[-1];
2768 break;
2769 }
2770 char __mod = 0;
2771 char __fmt = __ct.narrow(*__pb, 0);
2772 if (__fmt == 'E' || __fmt == 'O')
2773 {
2774 if (++__pb == __pe)
2775 {
2776 *__s++ = __pb[-2];
2777 *__s++ = __pb[-1];
2778 break;
2779 }
2780 __mod = __fmt;
2781 __fmt = __ct.narrow(*__pb, 0);
2782 }
2783 __s = do_put(__s, __iob, __fl, __tm, __fmt, __mod);
2784 }
2785 else
2786 *__s++ = *__pb;
2787 }
2788 return __s;
2789}
2790
2791template <class _CharT, class _OutputIterator>
2792_OutputIterator
Howard Hinnantec3773c2011-12-01 20:21:04 +00002793time_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002794 char_type, const tm* __tm,
2795 char __fmt, char __mod) const
2796{
2797 char_type __nar[100];
2798 char_type* __nb = __nar;
2799 char_type* __ne = __nb + 100;
2800 __do_put(__nb, __ne, __tm, __fmt, __mod);
Howard Hinnant0949eed2011-06-30 21:18:19 +00002801 return _VSTD::copy(__nb, __ne, __s);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002802}
2803
Howard Hinnantff926772012-11-06 21:08:48 +00002804_LIBCPP_EXTERN_TEMPLATE(class time_put<char>)
2805_LIBCPP_EXTERN_TEMPLATE(class time_put<wchar_t>)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002806
2807template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00002808class _LIBCPP_VISIBLE time_put_byname
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002809 : public time_put<_CharT, _OutputIterator>
2810{
2811public:
2812 _LIBCPP_ALWAYS_INLINE
2813 explicit time_put_byname(const char* __nm, size_t __refs = 0)
2814 : time_put<_CharT, _OutputIterator>(__nm, __refs) {}
2815
2816 _LIBCPP_ALWAYS_INLINE
2817 explicit time_put_byname(const string& __nm, size_t __refs = 0)
2818 : time_put<_CharT, _OutputIterator>(__nm, __refs) {}
2819
2820protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002821 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002822 ~time_put_byname() {}
2823};
2824
Howard Hinnantff926772012-11-06 21:08:48 +00002825_LIBCPP_EXTERN_TEMPLATE(class time_put_byname<char>)
2826_LIBCPP_EXTERN_TEMPLATE(class time_put_byname<wchar_t>)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002827
2828// money_base
2829
Howard Hinnant82894812010-09-22 16:48:34 +00002830class _LIBCPP_VISIBLE money_base
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002831{
2832public:
2833 enum part {none, space, symbol, sign, value};
2834 struct pattern {char field[4];};
2835
2836 _LIBCPP_ALWAYS_INLINE money_base() {}
2837};
2838
2839// moneypunct
2840
2841template <class _CharT, bool _International = false>
Howard Hinnant82894812010-09-22 16:48:34 +00002842class _LIBCPP_VISIBLE moneypunct
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002843 : public locale::facet,
2844 public money_base
2845{
2846public:
2847 typedef _CharT char_type;
2848 typedef basic_string<char_type> string_type;
2849
Howard Hinnant82894812010-09-22 16:48:34 +00002850 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002851 explicit moneypunct(size_t __refs = 0)
2852 : locale::facet(__refs) {}
2853
2854 _LIBCPP_ALWAYS_INLINE char_type decimal_point() const {return do_decimal_point();}
2855 _LIBCPP_ALWAYS_INLINE char_type thousands_sep() const {return do_thousands_sep();}
2856 _LIBCPP_ALWAYS_INLINE string grouping() const {return do_grouping();}
2857 _LIBCPP_ALWAYS_INLINE string_type curr_symbol() const {return do_curr_symbol();}
2858 _LIBCPP_ALWAYS_INLINE string_type positive_sign() const {return do_positive_sign();}
2859 _LIBCPP_ALWAYS_INLINE string_type negative_sign() const {return do_negative_sign();}
2860 _LIBCPP_ALWAYS_INLINE int frac_digits() const {return do_frac_digits();}
2861 _LIBCPP_ALWAYS_INLINE pattern pos_format() const {return do_pos_format();}
2862 _LIBCPP_ALWAYS_INLINE pattern neg_format() const {return do_neg_format();}
2863
2864 static locale::id id;
2865 static const bool intl = _International;
2866
2867protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002868 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002869 ~moneypunct() {}
2870
2871 virtual char_type do_decimal_point() const {return numeric_limits<char_type>::max();}
2872 virtual char_type do_thousands_sep() const {return numeric_limits<char_type>::max();}
2873 virtual string do_grouping() const {return string();}
2874 virtual string_type do_curr_symbol() const {return string_type();}
2875 virtual string_type do_positive_sign() const {return string_type();}
2876 virtual string_type do_negative_sign() const {return string_type(1, '-');}
2877 virtual int do_frac_digits() const {return 0;}
2878 virtual pattern do_pos_format() const
Howard Hinnant9bae2a92012-11-06 21:48:33 +00002879 {pattern __p = {{symbol, sign, none, value}}; return __p;}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002880 virtual pattern do_neg_format() const
Howard Hinnant9bae2a92012-11-06 21:48:33 +00002881 {pattern __p = {{symbol, sign, none, value}}; return __p;}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002882};
2883
2884template <class _CharT, bool _International>
2885locale::id
2886moneypunct<_CharT, _International>::id;
2887
Howard Hinnantff926772012-11-06 21:08:48 +00002888_LIBCPP_EXTERN_TEMPLATE(class moneypunct<char, false>)
2889_LIBCPP_EXTERN_TEMPLATE(class moneypunct<char, true>)
2890_LIBCPP_EXTERN_TEMPLATE(class moneypunct<wchar_t, false>)
2891_LIBCPP_EXTERN_TEMPLATE(class moneypunct<wchar_t, true>)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002892
2893// moneypunct_byname
2894
2895template <class _CharT, bool _International = false>
Howard Hinnant82894812010-09-22 16:48:34 +00002896class _LIBCPP_VISIBLE moneypunct_byname
2897 : public moneypunct<_CharT, _International>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002898{
2899public:
2900 typedef money_base::pattern pattern;
2901 typedef _CharT char_type;
2902 typedef basic_string<char_type> string_type;
2903
2904 _LIBCPP_ALWAYS_INLINE
2905 explicit moneypunct_byname(const char* __nm, size_t __refs = 0)
2906 : moneypunct<_CharT, _International>(__refs) {init(__nm);}
2907
2908 _LIBCPP_ALWAYS_INLINE
2909 explicit moneypunct_byname(const string& __nm, size_t __refs = 0)
2910 : moneypunct<_CharT, _International>(__refs) {init(__nm.c_str());}
2911
2912protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002913 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002914 ~moneypunct_byname() {}
2915
2916 virtual char_type do_decimal_point() const {return __decimal_point_;}
2917 virtual char_type do_thousands_sep() const {return __thousands_sep_;}
2918 virtual string do_grouping() const {return __grouping_;}
2919 virtual string_type do_curr_symbol() const {return __curr_symbol_;}
2920 virtual string_type do_positive_sign() const {return __positive_sign_;}
2921 virtual string_type do_negative_sign() const {return __negative_sign_;}
2922 virtual int do_frac_digits() const {return __frac_digits_;}
2923 virtual pattern do_pos_format() const {return __pos_format_;}
2924 virtual pattern do_neg_format() const {return __neg_format_;}
2925
2926private:
2927 char_type __decimal_point_;
2928 char_type __thousands_sep_;
2929 string __grouping_;
2930 string_type __curr_symbol_;
2931 string_type __positive_sign_;
2932 string_type __negative_sign_;
2933 int __frac_digits_;
2934 pattern __pos_format_;
2935 pattern __neg_format_;
2936
2937 void init(const char*);
2938};
2939
2940template<> void moneypunct_byname<char, false>::init(const char*);
2941template<> void moneypunct_byname<char, true>::init(const char*);
2942template<> void moneypunct_byname<wchar_t, false>::init(const char*);
2943template<> void moneypunct_byname<wchar_t, true>::init(const char*);
2944
Howard Hinnantff926772012-11-06 21:08:48 +00002945_LIBCPP_EXTERN_TEMPLATE(class moneypunct_byname<char, false>)
2946_LIBCPP_EXTERN_TEMPLATE(class moneypunct_byname<char, true>)
2947_LIBCPP_EXTERN_TEMPLATE(class moneypunct_byname<wchar_t, false>)
2948_LIBCPP_EXTERN_TEMPLATE(class moneypunct_byname<wchar_t, true>)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002949
2950// money_get
2951
2952template <class _CharT>
2953class __money_get
2954{
2955protected:
2956 typedef _CharT char_type;
2957 typedef basic_string<char_type> string_type;
2958
2959 _LIBCPP_ALWAYS_INLINE __money_get() {}
2960
2961 static void __gather_info(bool __intl, const locale& __loc,
2962 money_base::pattern& __pat, char_type& __dp,
2963 char_type& __ts, string& __grp,
2964 string_type& __sym, string_type& __psn,
2965 string_type& __nsn, int& __fd);
2966};
2967
2968template <class _CharT>
2969void
2970__money_get<_CharT>::__gather_info(bool __intl, const locale& __loc,
2971 money_base::pattern& __pat, char_type& __dp,
2972 char_type& __ts, string& __grp,
2973 string_type& __sym, string_type& __psn,
2974 string_type& __nsn, int& __fd)
2975{
2976 if (__intl)
2977 {
2978 const moneypunct<char_type, true>& __mp =
2979 use_facet<moneypunct<char_type, true> >(__loc);
2980 __pat = __mp.neg_format();
2981 __nsn = __mp.negative_sign();
2982 __psn = __mp.positive_sign();
2983 __dp = __mp.decimal_point();
2984 __ts = __mp.thousands_sep();
2985 __grp = __mp.grouping();
2986 __sym = __mp.curr_symbol();
2987 __fd = __mp.frac_digits();
2988 }
2989 else
2990 {
2991 const moneypunct<char_type, false>& __mp =
2992 use_facet<moneypunct<char_type, false> >(__loc);
2993 __pat = __mp.neg_format();
2994 __nsn = __mp.negative_sign();
2995 __psn = __mp.positive_sign();
2996 __dp = __mp.decimal_point();
2997 __ts = __mp.thousands_sep();
2998 __grp = __mp.grouping();
2999 __sym = __mp.curr_symbol();
3000 __fd = __mp.frac_digits();
3001 }
3002}
3003
Howard Hinnantff926772012-11-06 21:08:48 +00003004_LIBCPP_EXTERN_TEMPLATE(class __money_get<char>)
3005_LIBCPP_EXTERN_TEMPLATE(class __money_get<wchar_t>)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003006
3007template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00003008class _LIBCPP_VISIBLE money_get
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003009 : public locale::facet,
3010 private __money_get<_CharT>
3011{
3012public:
3013 typedef _CharT char_type;
3014 typedef _InputIterator iter_type;
3015 typedef basic_string<char_type> string_type;
3016
3017 _LIBCPP_ALWAYS_INLINE
3018 explicit money_get(size_t __refs = 0)
3019 : locale::facet(__refs) {}
3020
3021 _LIBCPP_ALWAYS_INLINE
3022 iter_type get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob,
3023 ios_base::iostate& __err, long double& __v) const
3024 {
3025 return do_get(__b, __e, __intl, __iob, __err, __v);
3026 }
3027
3028 _LIBCPP_ALWAYS_INLINE
3029 iter_type get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob,
3030 ios_base::iostate& __err, string_type& __v) const
3031 {
3032 return do_get(__b, __e, __intl, __iob, __err, __v);
3033 }
3034
3035 static locale::id id;
3036
3037protected:
3038
Howard Hinnant82894812010-09-22 16:48:34 +00003039 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003040 ~money_get() {}
Howard Hinnant324bb032010-08-22 00:02:43 +00003041
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003042 virtual iter_type do_get(iter_type __b, iter_type __e, bool __intl,
3043 ios_base& __iob, ios_base::iostate& __err,
3044 long double& __v) const;
3045 virtual iter_type do_get(iter_type __b, iter_type __e, bool __intl,
3046 ios_base& __iob, ios_base::iostate& __err,
3047 string_type& __v) const;
3048
3049private:
3050 static bool __do_get(iter_type& __b, iter_type __e,
3051 bool __intl, const locale& __loc,
3052 ios_base::fmtflags __flags, ios_base::iostate& __err,
3053 bool& __neg, const ctype<char_type>& __ct,
3054 unique_ptr<char_type, void(*)(void*)>& __wb,
3055 char_type*& __wn, char_type* __we);
3056};
3057
3058template <class _CharT, class _InputIterator>
3059locale::id
3060money_get<_CharT, _InputIterator>::id;
3061
3062void __do_nothing(void*);
3063
3064template <class _Tp>
3065_LIBCPP_HIDDEN
3066void
3067__double_or_nothing(unique_ptr<_Tp, void(*)(void*)>& __b, _Tp*& __n, _Tp*& __e)
3068{
3069 bool __owns = __b.get_deleter() != __do_nothing;
Howard Hinnantec3773c2011-12-01 20:21:04 +00003070 size_t __cur_cap = static_cast<size_t>(__e-__b.get()) * sizeof(_Tp);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003071 size_t __new_cap = __cur_cap < numeric_limits<size_t>::max() / 2 ?
3072 2 * __cur_cap : numeric_limits<size_t>::max();
Howard Hinnantec3773c2011-12-01 20:21:04 +00003073 size_t __n_off = static_cast<size_t>(__n - __b.get());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003074 _Tp* __t = (_Tp*)realloc(__owns ? __b.get() : 0, __new_cap);
3075 if (__t == 0)
3076 __throw_bad_alloc();
3077 if (__owns)
3078 __b.release();
3079 __b = unique_ptr<_Tp, void(*)(void*)>(__t, free);
3080 __new_cap /= sizeof(_Tp);
3081 __n = __b.get() + __n_off;
3082 __e = __b.get() + __new_cap;
3083}
3084
3085// true == success
3086template <class _CharT, class _InputIterator>
3087bool
3088money_get<_CharT, _InputIterator>::__do_get(iter_type& __b, iter_type __e,
3089 bool __intl, const locale& __loc,
3090 ios_base::fmtflags __flags,
3091 ios_base::iostate& __err,
3092 bool& __neg,
3093 const ctype<char_type>& __ct,
3094 unique_ptr<char_type, void(*)(void*)>& __wb,
3095 char_type*& __wn, char_type* __we)
3096{
3097 const unsigned __bz = 100;
3098 unsigned __gbuf[__bz];
3099 unique_ptr<unsigned, void(*)(void*)> __gb(__gbuf, __do_nothing);
3100 unsigned* __gn = __gb.get();
3101 unsigned* __ge = __gn + __bz;
3102 money_base::pattern __pat;
3103 char_type __dp;
3104 char_type __ts;
3105 string __grp;
3106 string_type __sym;
3107 string_type __psn;
3108 string_type __nsn;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00003109 // Capture the spaces read into money_base::{space,none} so they
3110 // can be compared to initial spaces in __sym.
3111 string_type __spaces;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003112 int __fd;
3113 __money_get<_CharT>::__gather_info(__intl, __loc, __pat, __dp, __ts, __grp,
3114 __sym, __psn, __nsn, __fd);
3115 const string_type* __trailing_sign = 0;
3116 __wn = __wb.get();
3117 for (unsigned __p = 0; __p < 4 && __b != __e; ++__p)
3118 {
3119 switch (__pat.field[__p])
3120 {
3121 case money_base::space:
3122 if (__p != 3)
3123 {
3124 if (__ct.is(ctype_base::space, *__b))
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00003125 __spaces.push_back(*__b++);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003126 else
3127 {
3128 __err |= ios_base::failbit;
3129 return false;
3130 }
3131 }
Howard Hinnant324bb032010-08-22 00:02:43 +00003132 // drop through
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003133 case money_base::none:
3134 if (__p != 3)
3135 {
3136 while (__b != __e && __ct.is(ctype_base::space, *__b))
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00003137 __spaces.push_back(*__b++);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003138 }
3139 break;
3140 case money_base::sign:
3141 if (__psn.size() + __nsn.size() > 0)
3142 {
3143 if (__psn.size() == 0 || __nsn.size() == 0)
3144 { // sign is optional
3145 if (__psn.size() > 0)
3146 { // __nsn.size() == 0
3147 if (*__b == __psn[0])
3148 {
3149 ++__b;
3150 if (__psn.size() > 1)
3151 __trailing_sign = &__psn;
3152 }
3153 else
3154 __neg = true;
3155 }
3156 else if (*__b == __nsn[0]) // __nsn.size() > 0 && __psn.size() == 0
3157 {
3158 ++__b;
3159 __neg = true;
3160 if (__nsn.size() > 1)
3161 __trailing_sign = &__nsn;
3162 }
3163 }
3164 else // sign is required
3165 {
3166 if (*__b == __psn[0])
3167 {
3168 ++__b;
3169 if (__psn.size() > 1)
3170 __trailing_sign = &__psn;
3171 }
3172 else if (*__b == __nsn[0])
3173 {
3174 ++__b;
3175 __neg = true;
3176 if (__nsn.size() > 1)
3177 __trailing_sign = &__nsn;
3178 }
3179 else
3180 {
3181 __err |= ios_base::failbit;
3182 return false;
3183 }
3184 }
3185 }
3186 break;
3187 case money_base::symbol:
3188 {
3189 bool __more_needed = __trailing_sign ||
3190 (__p < 2) ||
3191 (__p == 2 && __pat.field[3] != static_cast<char>(money_base::none));
3192 bool __sb = __flags & ios_base::showbase;
3193 if (__sb || __more_needed)
3194 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00003195 typename string_type::const_iterator __sym_space_end = __sym.begin();
3196 if (__p > 0 && (__pat.field[__p - 1] == money_base::none ||
3197 __pat.field[__p - 1] == money_base::space)) {
3198 // Match spaces we've already read against spaces at
3199 // the beginning of __sym.
3200 while (__sym_space_end != __sym.end() &&
3201 __ct.is(ctype_base::space, *__sym_space_end))
3202 ++__sym_space_end;
3203 const size_t __num_spaces = __sym_space_end - __sym.begin();
3204 if (__num_spaces > __spaces.size() ||
3205 !equal(__spaces.end() - __num_spaces, __spaces.end(),
3206 __sym.begin())) {
3207 // No match. Put __sym_space_end back at the
3208 // beginning of __sym, which will prevent a
3209 // match in the next loop.
3210 __sym_space_end = __sym.begin();
3211 }
3212 }
3213 typename string_type::const_iterator __sym_curr_char = __sym_space_end;
3214 while (__sym_curr_char != __sym.end() && __b != __e &&
3215 *__b == *__sym_curr_char) {
3216 ++__b;
3217 ++__sym_curr_char;
3218 }
3219 if (__sb && __sym_curr_char != __sym.end())
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003220 {
3221 __err |= ios_base::failbit;
3222 return false;
3223 }
3224 }
3225 }
3226 break;
3227 case money_base::value:
3228 {
3229 unsigned __ng = 0;
3230 for (; __b != __e; ++__b)
3231 {
3232 char_type __c = *__b;
3233 if (__ct.is(ctype_base::digit, __c))
3234 {
3235 if (__wn == __we)
3236 __double_or_nothing(__wb, __wn, __we);
3237 *__wn++ = __c;
3238 ++__ng;
3239 }
3240 else if (__grp.size() > 0 && __ng > 0 && __c == __ts)
3241 {
3242 if (__gn == __ge)
3243 __double_or_nothing(__gb, __gn, __ge);
3244 *__gn++ = __ng;
3245 __ng = 0;
3246 }
3247 else
3248 break;
3249 }
3250 if (__gb.get() != __gn && __ng > 0)
3251 {
3252 if (__gn == __ge)
3253 __double_or_nothing(__gb, __gn, __ge);
3254 *__gn++ = __ng;
3255 }
3256 if (__fd > 0)
3257 {
3258 if (__b == __e || *__b != __dp)
3259 {
3260 __err |= ios_base::failbit;
3261 return false;
3262 }
3263 for (++__b; __fd > 0; --__fd, ++__b)
3264 {
3265 if (__b == __e || !__ct.is(ctype_base::digit, *__b))
3266 {
3267 __err |= ios_base::failbit;
3268 return false;
3269 }
3270 if (__wn == __we)
3271 __double_or_nothing(__wb, __wn, __we);
3272 *__wn++ = *__b;
3273 }
3274 }
3275 if (__wn == __wb.get())
3276 {
3277 __err |= ios_base::failbit;
3278 return false;
3279 }
3280 }
3281 break;
3282 }
3283 }
3284 if (__trailing_sign)
3285 {
3286 for (unsigned __i = 1; __i < __trailing_sign->size(); ++__i, ++__b)
3287 {
3288 if (__b == __e || *__b != (*__trailing_sign)[__i])
3289 {
3290 __err |= ios_base::failbit;
3291 return false;
3292 }
3293 }
3294 }
3295 if (__gb.get() != __gn)
3296 {
3297 ios_base::iostate __et = ios_base::goodbit;
3298 __check_grouping(__grp, __gb.get(), __gn, __et);
3299 if (__et)
3300 {
3301 __err |= ios_base::failbit;
3302 return false;
3303 }
3304 }
3305 return true;
3306}
3307
3308template <class _CharT, class _InputIterator>
3309_InputIterator
3310money_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
3311 bool __intl, ios_base& __iob,
3312 ios_base::iostate& __err,
3313 long double& __v) const
3314{
Howard Hinnantec3773c2011-12-01 20:21:04 +00003315 const int __bz = 100;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003316 char_type __wbuf[__bz];
3317 unique_ptr<char_type, void(*)(void*)> __wb(__wbuf, __do_nothing);
3318 char_type* __wn;
3319 char_type* __we = __wbuf + __bz;
3320 locale __loc = __iob.getloc();
3321 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3322 bool __neg = false;
3323 if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct,
3324 __wb, __wn, __we))
3325 {
3326 const char __src[] = "0123456789";
3327 char_type __atoms[sizeof(__src)-1];
3328 __ct.widen(__src, __src + (sizeof(__src)-1), __atoms);
3329 char __nbuf[__bz];
3330 char* __nc = __nbuf;
3331 unique_ptr<char, void(*)(void*)> __h(0, free);
3332 if (__wn - __wb.get() > __bz-2)
3333 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00003334 __h.reset((char*)malloc(static_cast<size_t>(__wn - __wb.get() + 2)));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003335 if (__h.get() == 0)
3336 __throw_bad_alloc();
3337 __nc = __h.get();
3338 }
3339 if (__neg)
3340 *__nc++ = '-';
3341 for (const char_type* __w = __wb.get(); __w < __wn; ++__w, ++__nc)
3342 *__nc = __src[find(__atoms, __atoms+sizeof(__atoms), *__w) - __atoms];
3343 *__nc = char();
3344 if (sscanf(__nbuf, "%Lf", &__v) != 1)
3345 __throw_runtime_error("money_get error");
3346 }
3347 if (__b == __e)
3348 __err |= ios_base::eofbit;
3349 return __b;
3350}
3351
3352template <class _CharT, class _InputIterator>
3353_InputIterator
3354money_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
3355 bool __intl, ios_base& __iob,
3356 ios_base::iostate& __err,
3357 string_type& __v) const
3358{
Howard Hinnantec3773c2011-12-01 20:21:04 +00003359 const int __bz = 100;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003360 char_type __wbuf[__bz];
3361 unique_ptr<char_type, void(*)(void*)> __wb(__wbuf, __do_nothing);
3362 char_type* __wn;
3363 char_type* __we = __wbuf + __bz;
3364 locale __loc = __iob.getloc();
3365 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3366 bool __neg = false;
3367 if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct,
3368 __wb, __wn, __we))
3369 {
3370 __v.clear();
3371 if (__neg)
3372 __v.push_back(__ct.widen('-'));
3373 char_type __z = __ct.widen('0');
3374 char_type* __w;
3375 for (__w = __wb.get(); __w < __wn-1; ++__w)
3376 if (*__w != __z)
3377 break;
3378 __v.append(__w, __wn);
3379 }
3380 if (__b == __e)
3381 __err |= ios_base::eofbit;
3382 return __b;
3383}
3384
Howard Hinnantff926772012-11-06 21:08:48 +00003385_LIBCPP_EXTERN_TEMPLATE(class money_get<char>)
3386_LIBCPP_EXTERN_TEMPLATE(class money_get<wchar_t>)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003387
3388// money_put
3389
3390template <class _CharT>
3391class __money_put
3392{
3393protected:
3394 typedef _CharT char_type;
3395 typedef basic_string<char_type> string_type;
3396
3397 _LIBCPP_ALWAYS_INLINE __money_put() {}
3398
3399 static void __gather_info(bool __intl, bool __neg, const locale& __loc,
3400 money_base::pattern& __pat, char_type& __dp,
3401 char_type& __ts, string& __grp,
3402 string_type& __sym, string_type& __sn,
3403 int& __fd);
3404 static void __format(char_type* __mb, char_type*& __mi, char_type*& __me,
3405 ios_base::fmtflags __flags,
3406 const char_type* __db, const char_type* __de,
3407 const ctype<char_type>& __ct, bool __neg,
3408 const money_base::pattern& __pat, char_type __dp,
3409 char_type __ts, const string& __grp,
3410 const string_type& __sym, const string_type& __sn,
3411 int __fd);
3412};
3413
3414template <class _CharT>
3415void
3416__money_put<_CharT>::__gather_info(bool __intl, bool __neg, const locale& __loc,
3417 money_base::pattern& __pat, char_type& __dp,
3418 char_type& __ts, string& __grp,
3419 string_type& __sym, string_type& __sn,
3420 int& __fd)
3421{
3422 if (__intl)
3423 {
3424 const moneypunct<char_type, true>& __mp =
3425 use_facet<moneypunct<char_type, true> >(__loc);
3426 if (__neg)
3427 {
3428 __pat = __mp.neg_format();
3429 __sn = __mp.negative_sign();
3430 }
3431 else
3432 {
3433 __pat = __mp.pos_format();
3434 __sn = __mp.positive_sign();
3435 }
3436 __dp = __mp.decimal_point();
3437 __ts = __mp.thousands_sep();
3438 __grp = __mp.grouping();
3439 __sym = __mp.curr_symbol();
3440 __fd = __mp.frac_digits();
3441 }
3442 else
3443 {
3444 const moneypunct<char_type, false>& __mp =
3445 use_facet<moneypunct<char_type, false> >(__loc);
3446 if (__neg)
3447 {
3448 __pat = __mp.neg_format();
3449 __sn = __mp.negative_sign();
3450 }
3451 else
3452 {
3453 __pat = __mp.pos_format();
3454 __sn = __mp.positive_sign();
3455 }
3456 __dp = __mp.decimal_point();
3457 __ts = __mp.thousands_sep();
3458 __grp = __mp.grouping();
3459 __sym = __mp.curr_symbol();
3460 __fd = __mp.frac_digits();
3461 }
3462}
3463
3464template <class _CharT>
3465void
3466__money_put<_CharT>::__format(char_type* __mb, char_type*& __mi, char_type*& __me,
3467 ios_base::fmtflags __flags,
3468 const char_type* __db, const char_type* __de,
3469 const ctype<char_type>& __ct, bool __neg,
3470 const money_base::pattern& __pat, char_type __dp,
3471 char_type __ts, const string& __grp,
3472 const string_type& __sym, const string_type& __sn,
3473 int __fd)
3474{
3475 __me = __mb;
3476 for (unsigned __p = 0; __p < 4; ++__p)
3477 {
3478 switch (__pat.field[__p])
3479 {
3480 case money_base::none:
3481 __mi = __me;
3482 break;
3483 case money_base::space:
3484 __mi = __me;
3485 *__me++ = __ct.widen(' ');
3486 break;
3487 case money_base::sign:
3488 if (!__sn.empty())
3489 *__me++ = __sn[0];
3490 break;
3491 case money_base::symbol:
3492 if (!__sym.empty() && (__flags & ios_base::showbase))
Howard Hinnant0949eed2011-06-30 21:18:19 +00003493 __me = _VSTD::copy(__sym.begin(), __sym.end(), __me);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003494 break;
3495 case money_base::value:
3496 {
3497 // remember start of value so we can reverse it
3498 char_type* __t = __me;
3499 // find beginning of digits
3500 if (__neg)
3501 ++__db;
3502 // find end of digits
3503 const char_type* __d;
3504 for (__d = __db; __d < __de; ++__d)
3505 if (!__ct.is(ctype_base::digit, *__d))
3506 break;
3507 // print fractional part
3508 if (__fd > 0)
3509 {
3510 int __f;
3511 for (__f = __fd; __d > __db && __f > 0; --__f)
3512 *__me++ = *--__d;
3513 char_type __z = __f > 0 ? __ct.widen('0') : char_type();
3514 for (; __f > 0; --__f)
3515 *__me++ = __z;
3516 *__me++ = __dp;
3517 }
3518 // print units part
3519 if (__d == __db)
3520 {
3521 *__me++ = __ct.widen('0');
3522 }
3523 else
3524 {
3525 unsigned __ng = 0;
3526 unsigned __ig = 0;
3527 unsigned __gl = __grp.empty() ? numeric_limits<unsigned>::max()
3528 : static_cast<unsigned>(__grp[__ig]);
3529 while (__d != __db)
3530 {
3531 if (__ng == __gl)
3532 {
3533 *__me++ = __ts;
3534 __ng = 0;
3535 if (++__ig < __grp.size())
3536 __gl = __grp[__ig] == numeric_limits<char>::max() ?
3537 numeric_limits<unsigned>::max() :
3538 static_cast<unsigned>(__grp[__ig]);
3539 }
3540 *__me++ = *--__d;
3541 ++__ng;
3542 }
3543 }
3544 // reverse it
3545 reverse(__t, __me);
3546 }
3547 break;
3548 }
3549 }
3550 // print rest of sign, if any
3551 if (__sn.size() > 1)
Howard Hinnant0949eed2011-06-30 21:18:19 +00003552 __me = _VSTD::copy(__sn.begin()+1, __sn.end(), __me);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003553 // set alignment
3554 if ((__flags & ios_base::adjustfield) == ios_base::left)
3555 __mi = __me;
3556 else if ((__flags & ios_base::adjustfield) != ios_base::internal)
3557 __mi = __mb;
3558}
3559
Howard Hinnantff926772012-11-06 21:08:48 +00003560_LIBCPP_EXTERN_TEMPLATE(class __money_put<char>)
3561_LIBCPP_EXTERN_TEMPLATE(class __money_put<wchar_t>)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003562
3563template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00003564class _LIBCPP_VISIBLE money_put
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003565 : public locale::facet,
3566 private __money_put<_CharT>
3567{
3568public:
3569 typedef _CharT char_type;
3570 typedef _OutputIterator iter_type;
3571 typedef basic_string<char_type> string_type;
3572
3573 _LIBCPP_ALWAYS_INLINE
3574 explicit money_put(size_t __refs = 0)
3575 : locale::facet(__refs) {}
3576
3577 _LIBCPP_ALWAYS_INLINE
3578 iter_type put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl,
3579 long double __units) const
3580 {
3581 return do_put(__s, __intl, __iob, __fl, __units);
3582 }
3583
3584 _LIBCPP_ALWAYS_INLINE
3585 iter_type put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl,
3586 const string_type& __digits) const
3587 {
3588 return do_put(__s, __intl, __iob, __fl, __digits);
3589 }
3590
3591 static locale::id id;
3592
3593protected:
Howard Hinnant82894812010-09-22 16:48:34 +00003594 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003595 ~money_put() {}
3596
3597 virtual iter_type do_put(iter_type __s, bool __intl, ios_base& __iob,
3598 char_type __fl, long double __units) const;
3599 virtual iter_type do_put(iter_type __s, bool __intl, ios_base& __iob,
3600 char_type __fl, const string_type& __digits) const;
3601};
3602
3603template <class _CharT, class _OutputIterator>
3604locale::id
3605money_put<_CharT, _OutputIterator>::id;
3606
3607template <class _CharT, class _OutputIterator>
3608_OutputIterator
3609money_put<_CharT, _OutputIterator>::do_put(iter_type __s, bool __intl,
3610 ios_base& __iob, char_type __fl,
3611 long double __units) const
3612{
3613 // convert to char
3614 const size_t __bs = 100;
3615 char __buf[__bs];
3616 char* __bb = __buf;
3617 char_type __digits[__bs];
3618 char_type* __db = __digits;
Howard Hinnantec3773c2011-12-01 20:21:04 +00003619 size_t __n = static_cast<size_t>(snprintf(__bb, __bs, "%.0Lf", __units));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003620 unique_ptr<char, void(*)(void*)> __hn(0, free);
3621 unique_ptr<char_type, void(*)(void*)> __hd(0, free);
3622 // secure memory for digit storage
3623 if (__n > __bs-1)
3624 {
Howard Hinnant866569b2011-09-28 23:39:33 +00003625#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00003626 __n = static_cast<size_t>(asprintf_l(&__bb, _LIBCPP_GET_C_LOCALE, "%.0Lf", __units));
Sean Huntf3907e62011-07-15 05:40:33 +00003627#else
3628 __n = __asprintf_l(&__bb, __cloc(), "%.0Lf", __units);
3629#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003630 if (__bb == 0)
3631 __throw_bad_alloc();
3632 __hn.reset(__bb);
3633 __hd.reset((char_type*)malloc(__n * sizeof(char_type)));
Howard Hinnant05b57d52012-03-07 20:37:43 +00003634 if (__hd == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003635 __throw_bad_alloc();
3636 __db = __hd.get();
3637 }
3638 // gather info
3639 locale __loc = __iob.getloc();
3640 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3641 __ct.widen(__bb, __bb + __n, __db);
3642 bool __neg = __n > 0 && __bb[0] == '-';
3643 money_base::pattern __pat;
3644 char_type __dp;
3645 char_type __ts;
3646 string __grp;
3647 string_type __sym;
3648 string_type __sn;
3649 int __fd;
3650 this->__gather_info(__intl, __neg, __loc, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3651 // secure memory for formatting
3652 char_type __mbuf[__bs];
3653 char_type* __mb = __mbuf;
3654 unique_ptr<char_type, void(*)(void*)> __hw(0, free);
3655 size_t __exn = static_cast<int>(__n) > __fd ?
Howard Hinnantec3773c2011-12-01 20:21:04 +00003656 (__n - static_cast<size_t>(__fd)) * 2 + __sn.size() +
3657 __sym.size() + static_cast<size_t>(__fd) + 1
3658 : __sn.size() + __sym.size() + static_cast<size_t>(__fd) + 2;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003659 if (__exn > __bs)
3660 {
3661 __hw.reset((char_type*)malloc(__exn * sizeof(char_type)));
3662 __mb = __hw.get();
3663 if (__mb == 0)
3664 __throw_bad_alloc();
3665 }
3666 // format
3667 char_type* __mi;
3668 char_type* __me;
3669 this->__format(__mb, __mi, __me, __iob.flags(),
3670 __db, __db + __n, __ct,
3671 __neg, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3672 return __pad_and_output(__s, __mb, __mi, __me, __iob, __fl);
3673}
3674
3675template <class _CharT, class _OutputIterator>
3676_OutputIterator
3677money_put<_CharT, _OutputIterator>::do_put(iter_type __s, bool __intl,
3678 ios_base& __iob, char_type __fl,
3679 const string_type& __digits) const
3680{
3681 // gather info
3682 locale __loc = __iob.getloc();
3683 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3684 bool __neg = __digits.size() > 0 && __digits[0] == __ct.widen('-');
3685 money_base::pattern __pat;
3686 char_type __dp;
3687 char_type __ts;
3688 string __grp;
3689 string_type __sym;
3690 string_type __sn;
3691 int __fd;
3692 this->__gather_info(__intl, __neg, __loc, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3693 // secure memory for formatting
3694 char_type __mbuf[100];
3695 char_type* __mb = __mbuf;
3696 unique_ptr<char_type, void(*)(void*)> __h(0, free);
Howard Hinnantec3773c2011-12-01 20:21:04 +00003697 size_t __exn = static_cast<int>(__digits.size()) > __fd ?
3698 (__digits.size() - static_cast<size_t>(__fd)) * 2 +
3699 __sn.size() + __sym.size() + static_cast<size_t>(__fd) + 1
3700 : __sn.size() + __sym.size() + static_cast<size_t>(__fd) + 2;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003701 if (__exn > 100)
3702 {
3703 __h.reset((char_type*)malloc(__exn * sizeof(char_type)));
3704 __mb = __h.get();
3705 if (__mb == 0)
3706 __throw_bad_alloc();
3707 }
3708 // format
3709 char_type* __mi;
3710 char_type* __me;
3711 this->__format(__mb, __mi, __me, __iob.flags(),
3712 __digits.data(), __digits.data() + __digits.size(), __ct,
3713 __neg, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3714 return __pad_and_output(__s, __mb, __mi, __me, __iob, __fl);
3715}
3716
Howard Hinnantff926772012-11-06 21:08:48 +00003717_LIBCPP_EXTERN_TEMPLATE(class money_put<char>)
3718_LIBCPP_EXTERN_TEMPLATE(class money_put<wchar_t>)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003719
3720// messages
3721
Howard Hinnant82894812010-09-22 16:48:34 +00003722class _LIBCPP_VISIBLE messages_base
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003723{
3724public:
Howard Hinnantb2080c72011-02-25 00:51:08 +00003725 typedef ptrdiff_t catalog;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003726
3727 _LIBCPP_ALWAYS_INLINE messages_base() {}
3728};
3729
3730template <class _CharT>
Howard Hinnant82894812010-09-22 16:48:34 +00003731class _LIBCPP_VISIBLE messages
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003732 : public locale::facet,
3733 public messages_base
3734{
3735public:
3736 typedef _CharT char_type;
3737 typedef basic_string<_CharT> string_type;
3738
3739 _LIBCPP_ALWAYS_INLINE
3740 explicit messages(size_t __refs = 0)
3741 : locale::facet(__refs) {}
3742
3743 _LIBCPP_ALWAYS_INLINE
3744 catalog open(const basic_string<char>& __nm, const locale& __loc) const
3745 {
3746 return do_open(__nm, __loc);
3747 }
3748
3749 _LIBCPP_ALWAYS_INLINE
3750 string_type get(catalog __c, int __set, int __msgid,
3751 const string_type& __dflt) const
3752 {
3753 return do_get(__c, __set, __msgid, __dflt);
3754 }
3755
3756 _LIBCPP_ALWAYS_INLINE
3757 void close(catalog __c) const
3758 {
3759 do_close(__c);
3760 }
3761
3762 static locale::id id;
3763
3764protected:
Howard Hinnant82894812010-09-22 16:48:34 +00003765 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003766 ~messages() {}
3767
3768 virtual catalog do_open(const basic_string<char>&, const locale&) const;
3769 virtual string_type do_get(catalog, int __set, int __msgid,
3770 const string_type& __dflt) const;
3771 virtual void do_close(catalog) const;
3772};
3773
3774template <class _CharT>
3775locale::id
3776messages<_CharT>::id;
3777
3778template <class _CharT>
3779typename messages<_CharT>::catalog
3780messages<_CharT>::do_open(const basic_string<char>& __nm, const locale&) const
3781{
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00003782#if _WIN32
3783 return -1;
3784#else // _WIN32
Howard Hinnant11624452011-10-11 16:00:46 +00003785 catalog __cat = (catalog)catopen(__nm.c_str(), NL_CAT_LOCALE);
Howard Hinnantb2080c72011-02-25 00:51:08 +00003786 if (__cat != -1)
3787 __cat = static_cast<catalog>((static_cast<size_t>(__cat) >> 1));
3788 return __cat;
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00003789#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003790}
3791
3792template <class _CharT>
3793typename messages<_CharT>::string_type
3794messages<_CharT>::do_get(catalog __c, int __set, int __msgid,
3795 const string_type& __dflt) const
3796{
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00003797#if _WIN32
3798 return __dflt;
3799#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003800 string __ndflt;
3801 __narrow_to_utf8<sizeof(char_type)*__CHAR_BIT__>()(back_inserter(__ndflt),
3802 __dflt.c_str(),
3803 __dflt.c_str() + __dflt.size());
Howard Hinnantb2080c72011-02-25 00:51:08 +00003804 if (__c != -1)
3805 __c <<= 1;
Howard Hinnant11624452011-10-11 16:00:46 +00003806 nl_catd __cat = (nl_catd)__c;
Howard Hinnantb2080c72011-02-25 00:51:08 +00003807 char* __n = catgets(__cat, __set, __msgid, __ndflt.c_str());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003808 string_type __w;
3809 __widen_from_utf8<sizeof(char_type)*__CHAR_BIT__>()(back_inserter(__w),
3810 __n, __n + strlen(__n));
3811 return __w;
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00003812#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003813}
3814
3815template <class _CharT>
3816void
3817messages<_CharT>::do_close(catalog __c) const
3818{
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00003819#if !_WIN32
Howard Hinnantb2080c72011-02-25 00:51:08 +00003820 if (__c != -1)
3821 __c <<= 1;
Howard Hinnant11624452011-10-11 16:00:46 +00003822 nl_catd __cat = (nl_catd)__c;
Howard Hinnantb2080c72011-02-25 00:51:08 +00003823 catclose(__cat);
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00003824#endif // !_WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003825}
3826
Howard Hinnantff926772012-11-06 21:08:48 +00003827_LIBCPP_EXTERN_TEMPLATE(class messages<char>)
3828_LIBCPP_EXTERN_TEMPLATE(class messages<wchar_t>)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003829
3830template <class _CharT>
Howard Hinnant82894812010-09-22 16:48:34 +00003831class _LIBCPP_VISIBLE messages_byname
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003832 : public messages<_CharT>
3833{
3834public:
3835 typedef messages_base::catalog catalog;
3836 typedef basic_string<_CharT> string_type;
3837
3838 _LIBCPP_ALWAYS_INLINE
3839 explicit messages_byname(const char*, size_t __refs = 0)
3840 : messages<_CharT>(__refs) {}
3841
3842 _LIBCPP_ALWAYS_INLINE
3843 explicit messages_byname(const string&, size_t __refs = 0)
3844 : messages<_CharT>(__refs) {}
3845
3846protected:
Howard Hinnant82894812010-09-22 16:48:34 +00003847 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003848 ~messages_byname() {}
3849};
3850
Howard Hinnantff926772012-11-06 21:08:48 +00003851_LIBCPP_EXTERN_TEMPLATE(class messages_byname<char>)
3852_LIBCPP_EXTERN_TEMPLATE(class messages_byname<wchar_t>)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003853
Howard Hinnantd23b4642010-05-31 20:58:54 +00003854template<class _Codecvt, class _Elem = wchar_t,
3855 class _Wide_alloc = allocator<_Elem>,
3856 class _Byte_alloc = allocator<char> >
Howard Hinnant82894812010-09-22 16:48:34 +00003857class _LIBCPP_VISIBLE wstring_convert
Howard Hinnantd23b4642010-05-31 20:58:54 +00003858{
3859public:
3860 typedef basic_string<char, char_traits<char>, _Byte_alloc> byte_string;
3861 typedef basic_string<_Elem, char_traits<_Elem>, _Wide_alloc> wide_string;
3862 typedef typename _Codecvt::state_type state_type;
3863 typedef typename wide_string::traits_type::int_type int_type;
3864
3865private:
3866 byte_string __byte_err_string_;
3867 wide_string __wide_err_string_;
3868 _Codecvt* __cvtptr_;
3869 state_type __cvtstate_;
3870 size_t __cvtcount_;
3871
3872 wstring_convert(const wstring_convert& __wc);
3873 wstring_convert& operator=(const wstring_convert& __wc);
3874public:
3875 wstring_convert(_Codecvt* __pcvt = new _Codecvt);
3876 wstring_convert(_Codecvt* __pcvt, state_type __state);
3877 wstring_convert(const byte_string& __byte_err,
3878 const wide_string& __wide_err = wide_string());
Howard Hinnant73d21a42010-09-04 23:28:19 +00003879#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantd23b4642010-05-31 20:58:54 +00003880 wstring_convert(wstring_convert&& __wc);
3881#endif
3882 ~wstring_convert();
3883
Howard Hinnant82894812010-09-22 16:48:34 +00003884 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003885 wide_string from_bytes(char __byte)
3886 {return from_bytes(&__byte, &__byte+1);}
Howard Hinnant82894812010-09-22 16:48:34 +00003887 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003888 wide_string from_bytes(const char* __ptr)
3889 {return from_bytes(__ptr, __ptr + char_traits<char>::length(__ptr));}
Howard Hinnant82894812010-09-22 16:48:34 +00003890 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003891 wide_string from_bytes(const byte_string& __str)
3892 {return from_bytes(__str.data(), __str.data() + __str.size());}
3893 wide_string from_bytes(const char* __first, const char* __last);
3894
Howard Hinnant82894812010-09-22 16:48:34 +00003895 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003896 byte_string to_bytes(_Elem __wchar)
3897 {return to_bytes(&__wchar, &__wchar+1);}
Howard Hinnant82894812010-09-22 16:48:34 +00003898 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003899 byte_string to_bytes(const _Elem* __wptr)
3900 {return to_bytes(__wptr, __wptr + char_traits<_Elem>::length(__wptr));}
Howard Hinnant82894812010-09-22 16:48:34 +00003901 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003902 byte_string to_bytes(const wide_string& __wstr)
3903 {return to_bytes(__wstr.data(), __wstr.data() + __wstr.size());}
3904 byte_string to_bytes(const _Elem* __first, const _Elem* __last);
3905
Howard Hinnant82894812010-09-22 16:48:34 +00003906 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003907 size_t converted() const {return __cvtcount_;}
Howard Hinnant82894812010-09-22 16:48:34 +00003908 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003909 state_type state() const {return __cvtstate_;}
3910};
3911
3912template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Howard Hinnant82894812010-09-22 16:48:34 +00003913inline _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003914wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3915 wstring_convert(_Codecvt* __pcvt)
3916 : __cvtptr_(__pcvt), __cvtstate_(), __cvtcount_(0)
3917{
3918}
3919
3920template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Howard Hinnant82894812010-09-22 16:48:34 +00003921inline _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003922wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3923 wstring_convert(_Codecvt* __pcvt, state_type __state)
3924 : __cvtptr_(__pcvt), __cvtstate_(__state), __cvtcount_(0)
3925{
3926}
3927
3928template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3929wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3930 wstring_convert(const byte_string& __byte_err, const wide_string& __wide_err)
3931 : __byte_err_string_(__byte_err), __wide_err_string_(__wide_err),
3932 __cvtstate_(), __cvtcount_(0)
3933{
3934 __cvtptr_ = new _Codecvt;
3935}
3936
Howard Hinnant73d21a42010-09-04 23:28:19 +00003937#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantd23b4642010-05-31 20:58:54 +00003938
3939template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Howard Hinnant82894812010-09-22 16:48:34 +00003940inline _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003941wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3942 wstring_convert(wstring_convert&& __wc)
Howard Hinnant0949eed2011-06-30 21:18:19 +00003943 : __byte_err_string_(_VSTD::move(__wc.__byte_err_string_)),
3944 __wide_err_string_(_VSTD::move(__wc.__wide_err_string_)),
Howard Hinnantd23b4642010-05-31 20:58:54 +00003945 __cvtptr_(__wc.__cvtptr_),
3946 __cvtstate_(__wc.__cvtstate_), __cvtcount_(__wc.__cvtstate_)
3947{
3948 __wc.__cvtptr_ = nullptr;
3949}
3950
Howard Hinnantbfd55302010-09-04 23:46:48 +00003951#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantd23b4642010-05-31 20:58:54 +00003952
3953template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3954wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::~wstring_convert()
3955{
3956 delete __cvtptr_;
3957}
3958
3959template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3960typename wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::wide_string
3961wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3962 from_bytes(const char* __frm, const char* __frm_end)
3963{
3964 __cvtcount_ = 0;
3965 if (__cvtptr_ != nullptr)
3966 {
3967 wide_string __ws(2*(__frm_end - __frm), _Elem());
Howard Hinnant1ca23672012-07-12 18:07:41 +00003968 if (__frm != __frm_end)
3969 __ws.resize(__ws.capacity());
Howard Hinnantd23b4642010-05-31 20:58:54 +00003970 codecvt_base::result __r = codecvt_base::ok;
3971 state_type __st = __cvtstate_;
3972 if (__frm != __frm_end)
3973 {
3974 _Elem* __to = &__ws[0];
3975 _Elem* __to_end = __to + __ws.size();
3976 const char* __frm_nxt;
3977 do
3978 {
3979 _Elem* __to_nxt;
3980 __r = __cvtptr_->in(__st, __frm, __frm_end, __frm_nxt,
3981 __to, __to_end, __to_nxt);
3982 __cvtcount_ += __frm_nxt - __frm;
3983 if (__frm_nxt == __frm)
3984 {
3985 __r = codecvt_base::error;
3986 }
3987 else if (__r == codecvt_base::noconv)
3988 {
3989 __ws.resize(__to - &__ws[0]);
3990 // This only gets executed if _Elem is char
3991 __ws.append((const _Elem*)__frm, (const _Elem*)__frm_end);
3992 __frm = __frm_nxt;
3993 __r = codecvt_base::ok;
3994 }
3995 else if (__r == codecvt_base::ok)
3996 {
3997 __ws.resize(__to_nxt - &__ws[0]);
3998 __frm = __frm_nxt;
3999 }
4000 else if (__r == codecvt_base::partial)
4001 {
4002 ptrdiff_t __s = __to_nxt - &__ws[0];
4003 __ws.resize(2 * __s);
4004 __to = &__ws[0] + __s;
4005 __to_end = &__ws[0] + __ws.size();
4006 __frm = __frm_nxt;
4007 }
4008 } while (__r == codecvt_base::partial && __frm_nxt < __frm_end);
4009 }
4010 if (__r == codecvt_base::ok)
4011 return __ws;
4012 }
Howard Hinnantd4444702010-08-11 17:04:31 +00004013#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00004014 if (__wide_err_string_.empty())
4015 throw range_error("wstring_convert: from_bytes error");
Howard Hinnant324bb032010-08-22 00:02:43 +00004016#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00004017 return __wide_err_string_;
4018}
4019
4020template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
4021typename wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::byte_string
4022wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
4023 to_bytes(const _Elem* __frm, const _Elem* __frm_end)
4024{
4025 __cvtcount_ = 0;
4026 if (__cvtptr_ != nullptr)
4027 {
4028 byte_string __bs(2*(__frm_end - __frm), char());
Howard Hinnant1ca23672012-07-12 18:07:41 +00004029 if (__frm != __frm_end)
4030 __bs.resize(__bs.capacity());
Howard Hinnantd23b4642010-05-31 20:58:54 +00004031 codecvt_base::result __r = codecvt_base::ok;
4032 state_type __st = __cvtstate_;
4033 if (__frm != __frm_end)
4034 {
4035 char* __to = &__bs[0];
4036 char* __to_end = __to + __bs.size();
4037 const _Elem* __frm_nxt;
4038 do
4039 {
4040 char* __to_nxt;
4041 __r = __cvtptr_->out(__st, __frm, __frm_end, __frm_nxt,
4042 __to, __to_end, __to_nxt);
4043 __cvtcount_ += __frm_nxt - __frm;
4044 if (__frm_nxt == __frm)
4045 {
4046 __r = codecvt_base::error;
4047 }
4048 else if (__r == codecvt_base::noconv)
4049 {
4050 __bs.resize(__to - &__bs[0]);
4051 // This only gets executed if _Elem is char
4052 __bs.append((const char*)__frm, (const char*)__frm_end);
4053 __frm = __frm_nxt;
4054 __r = codecvt_base::ok;
4055 }
4056 else if (__r == codecvt_base::ok)
4057 {
4058 __bs.resize(__to_nxt - &__bs[0]);
4059 __frm = __frm_nxt;
4060 }
4061 else if (__r == codecvt_base::partial)
4062 {
4063 ptrdiff_t __s = __to_nxt - &__bs[0];
4064 __bs.resize(2 * __s);
4065 __to = &__bs[0] + __s;
4066 __to_end = &__bs[0] + __bs.size();
4067 __frm = __frm_nxt;
4068 }
4069 } while (__r == codecvt_base::partial && __frm_nxt < __frm_end);
4070 }
4071 if (__r == codecvt_base::ok)
4072 {
4073 size_t __s = __bs.size();
4074 __bs.resize(__bs.capacity());
4075 char* __to = &__bs[0] + __s;
4076 char* __to_end = __to + __bs.size();
4077 do
4078 {
4079 char* __to_nxt;
4080 __r = __cvtptr_->unshift(__st, __to, __to_end, __to_nxt);
4081 if (__r == codecvt_base::noconv)
4082 {
4083 __bs.resize(__to - &__bs[0]);
4084 __r = codecvt_base::ok;
4085 }
4086 else if (__r == codecvt_base::ok)
4087 {
4088 __bs.resize(__to_nxt - &__bs[0]);
4089 }
4090 else if (__r == codecvt_base::partial)
4091 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00004092 ptrdiff_t __sp = __to_nxt - &__bs[0];
4093 __bs.resize(2 * __sp);
4094 __to = &__bs[0] + __sp;
Howard Hinnantd23b4642010-05-31 20:58:54 +00004095 __to_end = &__bs[0] + __bs.size();
4096 }
4097 } while (__r == codecvt_base::partial);
4098 if (__r == codecvt_base::ok)
4099 return __bs;
4100 }
4101 }
Howard Hinnantd4444702010-08-11 17:04:31 +00004102#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00004103 if (__byte_err_string_.empty())
4104 throw range_error("wstring_convert: to_bytes error");
Howard Hinnant324bb032010-08-22 00:02:43 +00004105#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00004106 return __byte_err_string_;
4107}
4108
4109template <class _Codecvt, class _Elem = wchar_t, class _Tr = char_traits<_Elem> >
Howard Hinnant82894812010-09-22 16:48:34 +00004110class _LIBCPP_VISIBLE wbuffer_convert
Howard Hinnantd23b4642010-05-31 20:58:54 +00004111 : public basic_streambuf<_Elem, _Tr>
4112{
4113public:
4114 // types:
4115 typedef _Elem char_type;
4116 typedef _Tr traits_type;
4117 typedef typename traits_type::int_type int_type;
4118 typedef typename traits_type::pos_type pos_type;
4119 typedef typename traits_type::off_type off_type;
4120 typedef typename _Codecvt::state_type state_type;
4121
4122private:
Howard Hinnant4b53f502010-06-01 20:09:18 +00004123 char* __extbuf_;
4124 const char* __extbufnext_;
4125 const char* __extbufend_;
4126 char __extbuf_min_[8];
4127 size_t __ebs_;
4128 char_type* __intbuf_;
4129 size_t __ibs_;
Howard Hinnantd23b4642010-05-31 20:58:54 +00004130 streambuf* __bufptr_;
Howard Hinnant4b53f502010-06-01 20:09:18 +00004131 _Codecvt* __cv_;
4132 state_type __st_;
4133 ios_base::openmode __cm_;
4134 bool __owns_eb_;
4135 bool __owns_ib_;
4136 bool __always_noconv_;
Howard Hinnantd23b4642010-05-31 20:58:54 +00004137
Howard Hinnant4b53f502010-06-01 20:09:18 +00004138 wbuffer_convert(const wbuffer_convert&);
4139 wbuffer_convert& operator=(const wbuffer_convert&);
Howard Hinnantd23b4642010-05-31 20:58:54 +00004140public:
4141 wbuffer_convert(streambuf* __bytebuf = 0, _Codecvt* __pcvt = new _Codecvt,
Howard Hinnant4b53f502010-06-01 20:09:18 +00004142 state_type __state = state_type());
4143 ~wbuffer_convert();
Howard Hinnantd23b4642010-05-31 20:58:54 +00004144
Howard Hinnant82894812010-09-22 16:48:34 +00004145 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantd23b4642010-05-31 20:58:54 +00004146 streambuf* rdbuf() const {return __bufptr_;}
Howard Hinnant82894812010-09-22 16:48:34 +00004147 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantd23b4642010-05-31 20:58:54 +00004148 streambuf* rdbuf(streambuf* __bytebuf)
4149 {
4150 streambuf* __r = __bufptr_;
4151 __bufptr_ = __bytebuf;
4152 return __r;
4153 }
4154
Howard Hinnant82894812010-09-22 16:48:34 +00004155 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant4b53f502010-06-01 20:09:18 +00004156 state_type state() const {return __st_;}
Howard Hinnantd23b4642010-05-31 20:58:54 +00004157
4158protected:
Howard Hinnant4b53f502010-06-01 20:09:18 +00004159 virtual int_type underflow();
4160 virtual int_type pbackfail(int_type __c = traits_type::eof());
Howard Hinnantd23b4642010-05-31 20:58:54 +00004161 virtual int_type overflow (int_type __c = traits_type::eof());
Howard Hinnant4b53f502010-06-01 20:09:18 +00004162 virtual basic_streambuf<char_type, traits_type>* setbuf(char_type* __s,
4163 streamsize __n);
4164 virtual pos_type seekoff(off_type __off, ios_base::seekdir __way,
4165 ios_base::openmode __wch = ios_base::in | ios_base::out);
4166 virtual pos_type seekpos(pos_type __sp,
4167 ios_base::openmode __wch = ios_base::in | ios_base::out);
4168 virtual int sync();
4169
4170private:
4171 bool __read_mode();
4172 void __write_mode();
4173 wbuffer_convert* __close();
Howard Hinnantd23b4642010-05-31 20:58:54 +00004174};
4175
4176template <class _Codecvt, class _Elem, class _Tr>
Howard Hinnant4b53f502010-06-01 20:09:18 +00004177wbuffer_convert<_Codecvt, _Elem, _Tr>::
4178 wbuffer_convert(streambuf* __bytebuf, _Codecvt* __pcvt, state_type __state)
4179 : __extbuf_(0),
4180 __extbufnext_(0),
4181 __extbufend_(0),
4182 __ebs_(0),
4183 __intbuf_(0),
4184 __ibs_(0),
4185 __bufptr_(__bytebuf),
4186 __cv_(__pcvt),
4187 __st_(__state),
4188 __cm_(0),
4189 __owns_eb_(false),
4190 __owns_ib_(false),
4191 __always_noconv_(__cv_ ? __cv_->always_noconv() : false)
4192{
4193 setbuf(0, 4096);
4194}
4195
4196template <class _Codecvt, class _Elem, class _Tr>
4197wbuffer_convert<_Codecvt, _Elem, _Tr>::~wbuffer_convert()
4198{
4199 __close();
4200 delete __cv_;
4201 if (__owns_eb_)
4202 delete [] __extbuf_;
4203 if (__owns_ib_)
4204 delete [] __intbuf_;
4205}
4206
4207template <class _Codecvt, class _Elem, class _Tr>
4208typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
4209wbuffer_convert<_Codecvt, _Elem, _Tr>::underflow()
4210{
4211 if (__cv_ == 0 || __bufptr_ == 0)
4212 return traits_type::eof();
4213 bool __initial = __read_mode();
4214 char_type __1buf;
4215 if (this->gptr() == 0)
4216 this->setg(&__1buf, &__1buf+1, &__1buf+1);
4217 const size_t __unget_sz = __initial ? 0 : min<size_t>((this->egptr() - this->eback()) / 2, 4);
4218 int_type __c = traits_type::eof();
4219 if (this->gptr() == this->egptr())
4220 {
4221 memmove(this->eback(), this->egptr() - __unget_sz, __unget_sz * sizeof(char_type));
4222 if (__always_noconv_)
4223 {
4224 streamsize __nmemb = static_cast<streamsize>(this->egptr() - this->eback() - __unget_sz);
4225 __nmemb = __bufptr_->sgetn((char*)this->eback() + __unget_sz, __nmemb);
4226 if (__nmemb != 0)
4227 {
4228 this->setg(this->eback(),
4229 this->eback() + __unget_sz,
4230 this->eback() + __unget_sz + __nmemb);
4231 __c = *this->gptr();
4232 }
4233 }
4234 else
4235 {
4236 memmove(__extbuf_, __extbufnext_, __extbufend_ - __extbufnext_);
4237 __extbufnext_ = __extbuf_ + (__extbufend_ - __extbufnext_);
4238 __extbufend_ = __extbuf_ + (__extbuf_ == __extbuf_min_ ? sizeof(__extbuf_min_) : __ebs_);
Howard Hinnant0949eed2011-06-30 21:18:19 +00004239 streamsize __nmemb = _VSTD::min(static_cast<streamsize>(this->egptr() - this->eback() - __unget_sz),
Howard Hinnant4b53f502010-06-01 20:09:18 +00004240 static_cast<streamsize>(__extbufend_ - __extbufnext_));
4241 codecvt_base::result __r;
4242 state_type __svs = __st_;
4243 streamsize __nr = __bufptr_->sgetn(const_cast<char*>(__extbufnext_), __nmemb);
4244 if (__nr != 0)
4245 {
4246 __extbufend_ = __extbufnext_ + __nr;
4247 char_type* __inext;
4248 __r = __cv_->in(__st_, __extbuf_, __extbufend_, __extbufnext_,
4249 this->eback() + __unget_sz,
4250 this->egptr(), __inext);
4251 if (__r == codecvt_base::noconv)
4252 {
4253 this->setg((char_type*)__extbuf_, (char_type*)__extbuf_, (char_type*)__extbufend_);
4254 __c = *this->gptr();
4255 }
4256 else if (__inext != this->eback() + __unget_sz)
4257 {
4258 this->setg(this->eback(), this->eback() + __unget_sz, __inext);
4259 __c = *this->gptr();
4260 }
4261 }
4262 }
4263 }
4264 else
4265 __c = *this->gptr();
4266 if (this->eback() == &__1buf)
4267 this->setg(0, 0, 0);
4268 return __c;
4269}
4270
4271template <class _Codecvt, class _Elem, class _Tr>
4272typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
4273wbuffer_convert<_Codecvt, _Elem, _Tr>::pbackfail(int_type __c)
4274{
4275 if (__cv_ != 0 && __bufptr_ != 0 && this->eback() < this->gptr())
4276 {
4277 if (traits_type::eq_int_type(__c, traits_type::eof()))
4278 {
4279 this->gbump(-1);
4280 return traits_type::not_eof(__c);
4281 }
4282 if (traits_type::eq(traits_type::to_char_type(__c), this->gptr()[-1]))
4283 {
4284 this->gbump(-1);
4285 *this->gptr() = traits_type::to_char_type(__c);
4286 return __c;
4287 }
4288 }
4289 return traits_type::eof();
4290}
4291
4292template <class _Codecvt, class _Elem, class _Tr>
Howard Hinnantd23b4642010-05-31 20:58:54 +00004293typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
4294wbuffer_convert<_Codecvt, _Elem, _Tr>::overflow(int_type __c)
4295{
Howard Hinnant4b53f502010-06-01 20:09:18 +00004296 if (__cv_ == 0 || __bufptr_ == 0)
4297 return traits_type::eof();
4298 __write_mode();
4299 char_type __1buf;
4300 char_type* __pb_save = this->pbase();
4301 char_type* __epb_save = this->epptr();
4302 if (!traits_type::eq_int_type(__c, traits_type::eof()))
4303 {
4304 if (this->pptr() == 0)
4305 this->setp(&__1buf, &__1buf+1);
4306 *this->pptr() = traits_type::to_char_type(__c);
4307 this->pbump(1);
4308 }
4309 if (this->pptr() != this->pbase())
4310 {
4311 if (__always_noconv_)
4312 {
4313 streamsize __nmemb = static_cast<streamsize>(this->pptr() - this->pbase());
4314 if (__bufptr_->sputn((const char*)this->pbase(), __nmemb) != __nmemb)
4315 return traits_type::eof();
4316 }
4317 else
4318 {
4319 char* __extbe = __extbuf_;
4320 codecvt_base::result __r;
4321 do
4322 {
4323 const char_type* __e;
4324 __r = __cv_->out(__st_, this->pbase(), this->pptr(), __e,
4325 __extbuf_, __extbuf_ + __ebs_, __extbe);
4326 if (__e == this->pbase())
4327 return traits_type::eof();
4328 if (__r == codecvt_base::noconv)
4329 {
4330 streamsize __nmemb = static_cast<size_t>(this->pptr() - this->pbase());
4331 if (__bufptr_->sputn((const char*)this->pbase(), __nmemb) != __nmemb)
4332 return traits_type::eof();
4333 }
4334 else if (__r == codecvt_base::ok || __r == codecvt_base::partial)
4335 {
4336 streamsize __nmemb = static_cast<size_t>(__extbe - __extbuf_);
4337 if (__bufptr_->sputn(__extbuf_, __nmemb) != __nmemb)
4338 return traits_type::eof();
4339 if (__r == codecvt_base::partial)
4340 {
4341 this->setp((char_type*)__e, this->pptr());
4342 this->pbump(this->epptr() - this->pbase());
4343 }
4344 }
4345 else
4346 return traits_type::eof();
4347 } while (__r == codecvt_base::partial);
4348 }
4349 this->setp(__pb_save, __epb_save);
4350 }
4351 return traits_type::not_eof(__c);
4352}
4353
4354template <class _Codecvt, class _Elem, class _Tr>
4355basic_streambuf<_Elem, _Tr>*
4356wbuffer_convert<_Codecvt, _Elem, _Tr>::setbuf(char_type* __s, streamsize __n)
4357{
4358 this->setg(0, 0, 0);
4359 this->setp(0, 0);
4360 if (__owns_eb_)
4361 delete [] __extbuf_;
4362 if (__owns_ib_)
4363 delete [] __intbuf_;
4364 __ebs_ = __n;
4365 if (__ebs_ > sizeof(__extbuf_min_))
4366 {
4367 if (__always_noconv_ && __s)
4368 {
4369 __extbuf_ = (char*)__s;
4370 __owns_eb_ = false;
4371 }
4372 else
4373 {
4374 __extbuf_ = new char[__ebs_];
4375 __owns_eb_ = true;
4376 }
4377 }
4378 else
4379 {
4380 __extbuf_ = __extbuf_min_;
4381 __ebs_ = sizeof(__extbuf_min_);
4382 __owns_eb_ = false;
4383 }
4384 if (!__always_noconv_)
4385 {
4386 __ibs_ = max<streamsize>(__n, sizeof(__extbuf_min_));
4387 if (__s && __ibs_ >= sizeof(__extbuf_min_))
4388 {
4389 __intbuf_ = __s;
4390 __owns_ib_ = false;
4391 }
4392 else
4393 {
4394 __intbuf_ = new char_type[__ibs_];
4395 __owns_ib_ = true;
4396 }
4397 }
4398 else
4399 {
4400 __ibs_ = 0;
4401 __intbuf_ = 0;
4402 __owns_ib_ = false;
4403 }
4404 return this;
4405}
4406
4407template <class _Codecvt, class _Elem, class _Tr>
4408typename wbuffer_convert<_Codecvt, _Elem, _Tr>::pos_type
4409wbuffer_convert<_Codecvt, _Elem, _Tr>::seekoff(off_type __off, ios_base::seekdir __way,
4410 ios_base::openmode __om)
4411{
4412 int __width = __cv_->encoding();
4413 if (__cv_ == 0 || __bufptr_ == 0 || (__width <= 0 && __off != 0) || sync())
4414 return pos_type(off_type(-1));
4415 // __width > 0 || __off == 0
4416 switch (__way)
4417 {
4418 case ios_base::beg:
4419 break;
4420 case ios_base::cur:
4421 break;
4422 case ios_base::end:
4423 break;
4424 default:
4425 return pos_type(off_type(-1));
4426 }
4427 pos_type __r = __bufptr_->pubseekoff(__width * __off, __way, __om);
4428 __r.state(__st_);
4429 return __r;
4430}
4431
4432template <class _Codecvt, class _Elem, class _Tr>
4433typename wbuffer_convert<_Codecvt, _Elem, _Tr>::pos_type
4434wbuffer_convert<_Codecvt, _Elem, _Tr>::seekpos(pos_type __sp, ios_base::openmode __wch)
4435{
4436 if (__cv_ == 0 || __bufptr_ == 0 || sync())
4437 return pos_type(off_type(-1));
4438 if (__bufptr_->pubseekpos(__sp, __wch) == pos_type(off_type(-1)))
4439 return pos_type(off_type(-1));
4440 return __sp;
4441}
4442
4443template <class _Codecvt, class _Elem, class _Tr>
4444int
4445wbuffer_convert<_Codecvt, _Elem, _Tr>::sync()
4446{
4447 if (__cv_ == 0 || __bufptr_ == 0)
4448 return 0;
4449 if (__cm_ & ios_base::out)
4450 {
4451 if (this->pptr() != this->pbase())
4452 if (overflow() == traits_type::eof())
4453 return -1;
4454 codecvt_base::result __r;
4455 do
4456 {
4457 char* __extbe;
4458 __r = __cv_->unshift(__st_, __extbuf_, __extbuf_ + __ebs_, __extbe);
4459 streamsize __nmemb = static_cast<streamsize>(__extbe - __extbuf_);
4460 if (__bufptr_->sputn(__extbuf_, __nmemb) != __nmemb)
4461 return -1;
4462 } while (__r == codecvt_base::partial);
4463 if (__r == codecvt_base::error)
4464 return -1;
4465 if (__bufptr_->pubsync())
4466 return -1;
4467 }
4468 else if (__cm_ & ios_base::in)
4469 {
4470 off_type __c;
4471 if (__always_noconv_)
4472 __c = this->egptr() - this->gptr();
4473 else
4474 {
4475 int __width = __cv_->encoding();
4476 __c = __extbufend_ - __extbufnext_;
4477 if (__width > 0)
4478 __c += __width * (this->egptr() - this->gptr());
4479 else
4480 {
4481 if (this->gptr() != this->egptr())
4482 {
4483 reverse(this->gptr(), this->egptr());
4484 codecvt_base::result __r;
4485 const char_type* __e = this->gptr();
4486 char* __extbe;
4487 do
4488 {
4489 __r = __cv_->out(__st_, __e, this->egptr(), __e,
4490 __extbuf_, __extbuf_ + __ebs_, __extbe);
4491 switch (__r)
4492 {
4493 case codecvt_base::noconv:
4494 __c += this->egptr() - this->gptr();
4495 break;
4496 case codecvt_base::ok:
4497 case codecvt_base::partial:
4498 __c += __extbe - __extbuf_;
4499 break;
4500 default:
4501 return -1;
4502 }
4503 } while (__r == codecvt_base::partial);
4504 }
4505 }
4506 }
4507 if (__bufptr_->pubseekoff(-__c, ios_base::cur, __cm_) == pos_type(off_type(-1)))
4508 return -1;
4509 this->setg(0, 0, 0);
4510 __cm_ = 0;
4511 }
4512 return 0;
4513}
4514
4515template <class _Codecvt, class _Elem, class _Tr>
4516bool
4517wbuffer_convert<_Codecvt, _Elem, _Tr>::__read_mode()
4518{
4519 if (!(__cm_ & ios_base::in))
4520 {
4521 this->setp(0, 0);
4522 if (__always_noconv_)
4523 this->setg((char_type*)__extbuf_,
4524 (char_type*)__extbuf_ + __ebs_,
4525 (char_type*)__extbuf_ + __ebs_);
4526 else
4527 this->setg(__intbuf_, __intbuf_ + __ibs_, __intbuf_ + __ibs_);
4528 __cm_ = ios_base::in;
4529 return true;
4530 }
4531 return false;
4532}
4533
4534template <class _Codecvt, class _Elem, class _Tr>
4535void
4536wbuffer_convert<_Codecvt, _Elem, _Tr>::__write_mode()
4537{
4538 if (!(__cm_ & ios_base::out))
4539 {
4540 this->setg(0, 0, 0);
4541 if (__ebs_ > sizeof(__extbuf_min_))
4542 {
4543 if (__always_noconv_)
4544 this->setp((char_type*)__extbuf_,
4545 (char_type*)__extbuf_ + (__ebs_ - 1));
4546 else
4547 this->setp(__intbuf_, __intbuf_ + (__ibs_ - 1));
4548 }
4549 else
4550 this->setp(0, 0);
4551 __cm_ = ios_base::out;
4552 }
4553}
4554
4555template <class _Codecvt, class _Elem, class _Tr>
4556wbuffer_convert<_Codecvt, _Elem, _Tr>*
4557wbuffer_convert<_Codecvt, _Elem, _Tr>::__close()
4558{
4559 wbuffer_convert* __rt = 0;
4560 if (__cv_ != 0 && __bufptr_ != 0)
4561 {
4562 __rt = this;
4563 if ((__cm_ & ios_base::out) && sync())
4564 __rt = 0;
4565 }
4566 return __rt;
Howard Hinnantd23b4642010-05-31 20:58:54 +00004567}
4568
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004569_LIBCPP_END_NAMESPACE_STD
4570
4571#endif // _LIBCPP_LOCALE