blob: 9f9996a01f2629ccd614458d4216a900888d7786 [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
195#pragma GCC system_header
196
197_LIBCPP_BEGIN_NAMESPACE_STD
198
Howard Hinnant866569b2011-09-28 23:39:33 +0000199#if __APPLE__ || __FreeBSD__
Howard Hinnant2ea1ca92011-09-28 21:05:01 +0000200# define _LIBCPP_GET_C_LOCALE 0
201#else
202# define _LIBCPP_GET_C_LOCALE __cloc()
Howard Hinnant866569b2011-09-28 23:39:33 +0000203 // Get the C locale object
204 locale_t __cloc();
205#define __cloc_defined
Howard Hinnant2ea1ca92011-09-28 21:05:01 +0000206#endif
207
Sean Huntf3907e62011-07-15 05:40:33 +0000208typedef _VSTD::remove_pointer<locale_t>::type __locale_struct;
209typedef _VSTD::unique_ptr<__locale_struct, decltype(&freelocale)> __locale_unique_ptr;
210typedef _VSTD::unique_ptr<__locale_struct, decltype(&uselocale)> __locale_raii;
211
Howard Hinnantadff4892010-05-24 17:49:41 +0000212// OSX has nice foo_l() functions that let you turn off use of the global
213// locale. Linux, not so much. The following functions avoid the locale when
214// that's possible and otherwise do the wrong thing. FIXME.
Howard Hinnant866569b2011-09-28 23:39:33 +0000215#ifdef __linux__
Sean Huntf3907e62011-07-15 05:40:33 +0000216
217#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
218decltype(MB_CUR_MAX_L(_VSTD::declval<locale_t>()))
Howard Hinnant82894812010-09-22 16:48:34 +0000219inline _LIBCPP_INLINE_VISIBILITY
Sean Huntf3907e62011-07-15 05:40:33 +0000220__mb_cur_max_l(locale_t __l)
Howard Hinnantadff4892010-05-24 17:49:41 +0000221{
Sean Huntf3907e62011-07-15 05:40:33 +0000222 return MB_CUR_MAX_L(__l);
223}
224#else // _LIBCPP_LOCALE__L_EXTENSIONS
225_LIBCPP_ALWAYS_INLINE inline
226decltype(MB_CUR_MAX) __mb_cur_max_l(locale_t __l)
227{
228 __locale_raii __current(uselocale(__l), uselocale);
229 return MB_CUR_MAX;
230}
231#endif // _LIBCPP_LOCALE__L_EXTENSIONS
232
233_LIBCPP_ALWAYS_INLINE inline
234wint_t __btowc_l(int __c, locale_t __l)
235{
Howard Hinnant866569b2011-09-28 23:39:33 +0000236#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +0000237 return btowc_l(__c, __l);
238#else
239 __locale_raii __current(uselocale(__l), uselocale);
240 return btowc(__c);
241#endif
Sean Huntc97da3a2011-07-13 06:40:50 +0000242}
Howard Hinnant8d756322011-07-13 15:48:16 +0000243
Sean Huntf3907e62011-07-15 05:40:33 +0000244_LIBCPP_ALWAYS_INLINE inline
245int __wctob_l(wint_t __c, locale_t __l)
Sean Huntc97da3a2011-07-13 06:40:50 +0000246{
Sean Huntf3907e62011-07-15 05:40:33 +0000247#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
248 return wctob_l(__c, __l);
249#else
250 __locale_raii __current(uselocale(__l), uselocale);
251 return wctob(__c);
252#endif
Sean Huntc97da3a2011-07-13 06:40:50 +0000253}
Sean Huntf3907e62011-07-15 05:40:33 +0000254
255_LIBCPP_ALWAYS_INLINE inline
256size_t __wcsnrtombs_l(char *__dest, const wchar_t **__src, size_t __nwc,
257 size_t __len, mbstate_t *__ps, locale_t __l)
258{
259#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
260 return wcsnrtombs_l(__dest, __src, __nwc, __len, __ps, __l);
261#else
262 __locale_raii __current(uselocale(__l), uselocale);
263 return wcsnrtombs(__dest, __src, __nwc, __len, __ps);
264#endif
265}
266
267_LIBCPP_ALWAYS_INLINE inline
268size_t __wcrtomb_l(char *__s, wchar_t __wc, mbstate_t *__ps, locale_t __l)
269{
270#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
271 return wcrtomb_l(__s, __wc, __ps, __l);
272#else
273 __locale_raii __current(uselocale(__l), uselocale);
274 return wcrtomb(__s, __wc, __ps);
275#endif
276}
277
278_LIBCPP_ALWAYS_INLINE inline
279size_t __mbsnrtowcs_l(wchar_t * __dest, const char **__src, size_t __nms,
280 size_t __len, mbstate_t *__ps, locale_t __l)
281{
282#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
David Chisnallc512df12011-09-21 08:39:44 +0000283 return mbsnrtowcs_l(__dest, __src, __nms, __len, __ps, __l);
Sean Huntf3907e62011-07-15 05:40:33 +0000284#else
285 __locale_raii __current(uselocale(__l), uselocale);
286 return mbsnrtowcs(__dest, __src, __nms, __len, __ps);
287#endif
288}
289
290_LIBCPP_ALWAYS_INLINE inline
291size_t __mbrtowc_l(wchar_t *__pwc, const char *__s, size_t __n,
292 mbstate_t *__ps, locale_t __l)
293{
294#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
295 return mbrtowc_l(__pwc, __s, __n, __ps, __l);
296#else
297 __locale_raii __current(uselocale(__l), uselocale);
298 return mbrtowc(__pwc, __s, __n, __ps);
299#endif
300}
301
302_LIBCPP_ALWAYS_INLINE inline
303int __mbtowc_l(wchar_t *__pwc, const char *__pmb, size_t __max, locale_t __l)
304{
305#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
David Chisnallc512df12011-09-21 08:39:44 +0000306 return mbtowc_l(__pwc, __pmb, __max, __l);
Sean Huntf3907e62011-07-15 05:40:33 +0000307#else
308 __locale_raii __current(uselocale(__l), uselocale);
309 return mbtowc(__pwc, __pmb, __max);
310#endif
311}
312
313_LIBCPP_ALWAYS_INLINE inline
314size_t __mbrlen_l(const char *__s, size_t __n, mbstate_t *__ps, locale_t __l)
315{
316#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
317 return mbrlen_l(__s, __n, __ps, __l);
318#else
319 __locale_raii __current(uselocale(__l), uselocale);
320 return mbrlen(__s, __n, __ps);
321#endif
322}
323
324_LIBCPP_ALWAYS_INLINE inline
325lconv *__localeconv_l(locale_t __l)
326{
327#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
328 return localeconv_l(__l);
329#else
330 __locale_raii __current(uselocale(__l), uselocale);
331 return localeconv();
332#endif
333}
334
335_LIBCPP_ALWAYS_INLINE inline
336size_t __mbsrtowcs_l(wchar_t *__dest, const char **__src, size_t __len,
337 mbstate_t *__ps, locale_t __l)
338{
339#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
340 return mbsrtowcs_l(__dest, __src, __len, __ps, __l);
341#else
342 __locale_raii __current(uselocale(__l), uselocale);
343 return mbsrtowcs(__dest, __src, __len, __ps);
344#endif
345}
346
347_LIBCPP_ALWAYS_INLINE inline
348int __sprintf_l(char *__s, locale_t __l, const char *__format, ...) {
349 va_list __va;
350 va_start(__va, __format);
351#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
352 int __res = vsprintf_l(__s, __l, __format, __va);
353#else
354 __locale_raii __current(uselocale(__l), uselocale);
355 int __res = vsprintf(__s, __format, __va);
356#endif
357 va_end(__va);
358 return __res;
359}
360
361_LIBCPP_ALWAYS_INLINE inline
362int __snprintf_l(char *__s, size_t __n, locale_t __l, const char *__format, ...) {
363 va_list __va;
364 va_start(__va, __format);
365#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
366 int __res = vsnprintf_l(__s, __n, __l, __format, __va);
367#else
368 __locale_raii __current(uselocale(__l), uselocale);
369 int __res = vsnprintf(__s, __n, __format, __va);
370#endif
371 va_end(__va);
372 return __res;
373}
374
375_LIBCPP_ALWAYS_INLINE inline
376int __asprintf_l(char **__s, locale_t __l, const char *__format, ...) {
377 va_list __va;
378 va_start(__va, __format);
379#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
380 int __res = vasprintf_l(__s, __l, __format, __va);
381#else
382 __locale_raii __current(uselocale(__l), uselocale);
383 int __res = vasprintf(__s, __format, __va);
384#endif
385 va_end(__va);
386 return __res;
387}
388
389_LIBCPP_ALWAYS_INLINE inline
390int __sscanf_l(const char *__s, locale_t __l, const char *__format, ...) {
391 va_list __va;
392 va_start(__va, __format);
393#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
394 int __res = vsscanf_l(__s, __l, __format, __va);
395#else
396 __locale_raii __current(uselocale(__l), uselocale);
397 int __res = vsscanf(__s, __format, __va);
398#endif
399 va_end(__va);
400 return __res;
401}
402
Howard Hinnant866569b2011-09-28 23:39:33 +0000403#endif // __linux__
Howard Hinnantadff4892010-05-24 17:49:41 +0000404
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000405// __scan_keyword
406// Scans [__b, __e) until a match is found in the basic_strings range
407// [__kb, __ke) or until it can be shown that there is no match in [__kb, __ke).
408// __b will be incremented (visibly), consuming CharT until a match is found
409// or proved to not exist. A keyword may be "", in which will match anything.
410// If one keyword is a prefix of another, and the next CharT in the input
411// might match another keyword, the algorithm will attempt to find the longest
412// matching keyword. If the longer matching keyword ends up not matching, then
413// no keyword match is found. If no keyword match is found, __ke is returned
414// and failbit is set in __err.
415// Else an iterator pointing to the matching keyword is found. If more than
416// one keyword matches, an iterator to the first matching keyword is returned.
417// If on exit __b == __e, eofbit is set in __err. If __case_senstive is false,
418// __ct is used to force to lower case before comparing characters.
419// Examples:
420// Keywords: "a", "abb"
421// If the input is "a", the first keyword matches and eofbit is set.
422// If the input is "abc", no match is found and "ab" are consumed.
423template <class _InputIterator, class _ForwardIterator, class _Ctype>
424_LIBCPP_HIDDEN
425_ForwardIterator
426__scan_keyword(_InputIterator& __b, _InputIterator __e,
427 _ForwardIterator __kb, _ForwardIterator __ke,
428 const _Ctype& __ct, ios_base::iostate& __err,
429 bool __case_sensitive = true)
430{
431 typedef typename iterator_traits<_InputIterator>::value_type _CharT;
Howard Hinnant0949eed2011-06-30 21:18:19 +0000432 size_t __nkw = _VSTD::distance(__kb, __ke);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000433 const unsigned char __doesnt_match = '\0';
434 const unsigned char __might_match = '\1';
435 const unsigned char __does_match = '\2';
436 unsigned char __statbuf[100];
437 unsigned char* __status = __statbuf;
438 unique_ptr<unsigned char, void(*)(void*)> __stat_hold(0, free);
439 if (__nkw > sizeof(__statbuf))
440 {
441 __status = (unsigned char*)malloc(__nkw);
442 if (__status == 0)
443 __throw_bad_alloc();
444 __stat_hold.reset(__status);
445 }
446 size_t __n_might_match = __nkw; // At this point, any keyword might match
447 size_t __n_does_match = 0; // but none of them definitely do
448 // Initialize all statuses to __might_match, except for "" keywords are __does_match
449 unsigned char* __st = __status;
450 for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, ++__st)
451 {
452 if (!__ky->empty())
453 *__st = __might_match;
454 else
455 {
456 *__st = __does_match;
457 --__n_might_match;
458 ++__n_does_match;
459 }
460 }
461 // While there might be a match, test keywords against the next CharT
462 for (size_t __indx = 0; __b != __e && __n_might_match > 0; ++__indx)
463 {
464 // Peek at the next CharT but don't consume it
465 _CharT __c = *__b;
466 if (!__case_sensitive)
467 __c = __ct.toupper(__c);
468 bool __consume = false;
469 // For each keyword which might match, see if the __indx character is __c
470 // If a match if found, consume __c
471 // If a match is found, and that is the last character in the keyword,
472 // then that keyword matches.
473 // If the keyword doesn't match this character, then change the keyword
474 // to doesn't match
475 __st = __status;
476 for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, ++__st)
477 {
478 if (*__st == __might_match)
479 {
480 _CharT __kc = (*__ky)[__indx];
481 if (!__case_sensitive)
482 __kc = __ct.toupper(__kc);
483 if (__c == __kc)
484 {
485 __consume = true;
486 if (__ky->size() == __indx+1)
487 {
488 *__st = __does_match;
489 --__n_might_match;
490 ++__n_does_match;
491 }
492 }
493 else
494 {
495 *__st = __doesnt_match;
496 --__n_might_match;
497 }
498 }
499 }
500 // consume if we matched a character
501 if (__consume)
502 {
503 ++__b;
504 // If we consumed a character and there might be a matched keyword that
505 // was marked matched on a previous iteration, then such keywords
506 // which are now marked as not matching.
507 if (__n_might_match + __n_does_match > 1)
508 {
509 __st = __status;
510 for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, ++__st)
511 {
512 if (*__st == __does_match && __ky->size() != __indx+1)
513 {
514 *__st = __doesnt_match;
515 --__n_does_match;
516 }
517 }
518 }
519 }
520 }
521 // We've exited the loop because we hit eof and/or we have no more "might matches".
522 if (__b == __e)
523 __err |= ios_base::eofbit;
524 // Return the first matching result
525 for (__st = __status; __kb != __ke; ++__kb, ++__st)
526 if (*__st == __does_match)
527 break;
528 if (__kb == __ke)
529 __err |= ios_base::failbit;
530 return __kb;
531}
532
533struct __num_get_base
534{
535 static const int __num_get_buf_sz = 40;
536
537 static int __get_base(ios_base&);
538 static const char __src[33];
539};
540
541void __check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
542 ios_base::iostate& __err);
543
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000544template <class _CharT>
545struct __num_get
546 : protected __num_get_base
547{
548 static string __stage2_int_prep(ios_base& __iob, _CharT* __atoms, _CharT& __thousands_sep);
549 static string __stage2_float_prep(ios_base& __iob, _CharT* __atoms, _CharT& __decimal_point,
550 _CharT& __thousands_sep);
551 static int __stage2_int_loop(_CharT __ct, int __base, char* __a, char*& __a_end,
552 unsigned& __dc, _CharT __thousands_sep, const string& __grouping,
553 unsigned* __g, unsigned*& __g_end, _CharT* __atoms);
554 static int __stage2_float_loop(_CharT __ct, bool& __in_units, char& __exp,
555 char* __a, char*& __a_end,
556 _CharT __decimal_point, _CharT __thousands_sep,
557 const string& __grouping, unsigned* __g,
558 unsigned*& __g_end, unsigned& __dc, _CharT* __atoms);
559};
560
561template <class _CharT>
562string
563__num_get<_CharT>::__stage2_int_prep(ios_base& __iob, _CharT* __atoms, _CharT& __thousands_sep)
564{
565 locale __loc = __iob.getloc();
566 use_facet<ctype<_CharT> >(__loc).widen(__src, __src + 26, __atoms);
567 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
568 __thousands_sep = __np.thousands_sep();
569 return __np.grouping();
570}
571
572template <class _CharT>
573string
574__num_get<_CharT>::__stage2_float_prep(ios_base& __iob, _CharT* __atoms, _CharT& __decimal_point,
575 _CharT& __thousands_sep)
576{
577 locale __loc = __iob.getloc();
578 use_facet<ctype<_CharT> >(__loc).widen(__src, __src + 32, __atoms);
579 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
580 __decimal_point = __np.decimal_point();
581 __thousands_sep = __np.thousands_sep();
582 return __np.grouping();
583}
584
585template <class _CharT>
586int
587__num_get<_CharT>::__stage2_int_loop(_CharT __ct, int __base, char* __a, char*& __a_end,
588 unsigned& __dc, _CharT __thousands_sep, const string& __grouping,
589 unsigned* __g, unsigned*& __g_end, _CharT* __atoms)
590{
Howard Hinnant80586722011-03-09 01:03:19 +0000591 if (__a_end == __a && (__ct == __atoms[24] || __ct == __atoms[25]))
592 {
593 *__a_end++ = __ct == __atoms[24] ? '+' : '-';
594 __dc = 0;
595 return 0;
596 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000597 if (__ct == __thousands_sep && __grouping.size() != 0)
598 {
599 if (__g_end-__g < __num_get_buf_sz)
600 {
601 *__g_end++ = __dc;
602 __dc = 0;
603 }
604 return 0;
605 }
606 ptrdiff_t __f = find(__atoms, __atoms + 26, __ct) - __atoms;
Howard Hinnant80586722011-03-09 01:03:19 +0000607 if (__f >= 24)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000608 return -1;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000609 switch (__base)
610 {
611 case 8:
612 case 10:
613 if (__f >= __base)
Howard Hinnant80586722011-03-09 01:03:19 +0000614 return -1;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000615 break;
Howard Hinnant80586722011-03-09 01:03:19 +0000616 case 16:
617 if (__f < 22)
618 break;
619 if (__a_end != __a && __a_end - __a <= 2 && __a_end[-1] == '0')
620 {
621 __dc = 0;
622 *__a_end++ = __src[__f];
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000623 return 0;
Howard Hinnant80586722011-03-09 01:03:19 +0000624 }
625 return -1;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000626 }
Howard Hinnant80586722011-03-09 01:03:19 +0000627 if (__a_end-__a < __num_get_buf_sz - 1)
628 *__a_end++ = __src[__f];
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000629 ++__dc;
630 return 0;
631}
632
633template <class _CharT>
634int
635__num_get<_CharT>::__stage2_float_loop(_CharT __ct, bool& __in_units, char& __exp, char* __a, char*& __a_end,
636 _CharT __decimal_point, _CharT __thousands_sep, const string& __grouping,
637 unsigned* __g, unsigned*& __g_end, unsigned& __dc, _CharT* __atoms)
638{
639 if (__ct == __decimal_point)
640 {
641 if (!__in_units)
642 return -1;
643 __in_units = false;
644 *__a_end++ = '.';
645 if (__grouping.size() != 0 && __g_end-__g < __num_get_buf_sz)
646 *__g_end++ = __dc;
647 return 0;
648 }
649 if (__ct == __thousands_sep && __grouping.size() != 0)
650 {
651 if (!__in_units)
652 return -1;
653 if (__g_end-__g < __num_get_buf_sz)
654 {
655 *__g_end++ = __dc;
656 __dc = 0;
657 }
658 return 0;
659 }
660 ptrdiff_t __f = find(__atoms, __atoms + 32, __ct) - __atoms;
661 if (__f >= 32)
662 return -1;
663 char __x = __src[__f];
664 if (__a_end-__a < __num_get_buf_sz - 1)
665 *__a_end++ = __x;
666 if (__x == 'x' || __x == 'X')
667 __exp = 'P';
668 else if ((__x & 0xDF) == __exp)
669 {
670 __in_units = false;
671 if (__grouping.size() != 0 && __g_end-__g < __num_get_buf_sz)
672 *__g_end++ = __dc;
673 }
674 if (__f >= 22)
675 return 0;
676 ++__dc;
677 return 0;
678}
679
680extern template class __num_get<char>;
681extern template class __num_get<wchar_t>;
682
683template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +0000684class _LIBCPP_VISIBLE num_get
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000685 : public locale::facet,
686 private __num_get<_CharT>
687{
688public:
689 typedef _CharT char_type;
690 typedef _InputIterator iter_type;
691
692 _LIBCPP_ALWAYS_INLINE
693 explicit num_get(size_t __refs = 0)
694 : locale::facet(__refs) {}
695
696 _LIBCPP_ALWAYS_INLINE
697 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
698 ios_base::iostate& __err, bool& __v) const
699 {
700 return do_get(__b, __e, __iob, __err, __v);
701 }
702
703 _LIBCPP_ALWAYS_INLINE
704 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
705 ios_base::iostate& __err, long& __v) const
706 {
707 return do_get(__b, __e, __iob, __err, __v);
708 }
709
710 _LIBCPP_ALWAYS_INLINE
711 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
712 ios_base::iostate& __err, long long& __v) const
713 {
714 return do_get(__b, __e, __iob, __err, __v);
715 }
716
717 _LIBCPP_ALWAYS_INLINE
718 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
719 ios_base::iostate& __err, unsigned short& __v) const
720 {
721 return do_get(__b, __e, __iob, __err, __v);
722 }
723
724 _LIBCPP_ALWAYS_INLINE
725 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
726 ios_base::iostate& __err, unsigned int& __v) const
727 {
728 return do_get(__b, __e, __iob, __err, __v);
729 }
730
731 _LIBCPP_ALWAYS_INLINE
732 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
733 ios_base::iostate& __err, unsigned long& __v) const
734 {
735 return do_get(__b, __e, __iob, __err, __v);
736 }
737
738 _LIBCPP_ALWAYS_INLINE
739 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
740 ios_base::iostate& __err, unsigned long long& __v) const
741 {
742 return do_get(__b, __e, __iob, __err, __v);
743 }
744
745 _LIBCPP_ALWAYS_INLINE
746 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
747 ios_base::iostate& __err, float& __v) const
748 {
749 return do_get(__b, __e, __iob, __err, __v);
750 }
751
752 _LIBCPP_ALWAYS_INLINE
753 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
754 ios_base::iostate& __err, double& __v) const
755 {
756 return do_get(__b, __e, __iob, __err, __v);
757 }
758
759 _LIBCPP_ALWAYS_INLINE
760 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
761 ios_base::iostate& __err, long double& __v) const
762 {
763 return do_get(__b, __e, __iob, __err, __v);
764 }
765
766 _LIBCPP_ALWAYS_INLINE
767 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
768 ios_base::iostate& __err, void*& __v) const
769 {
770 return do_get(__b, __e, __iob, __err, __v);
771 }
772
773 static locale::id id;
774
775protected:
Howard Hinnant82894812010-09-22 16:48:34 +0000776 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000777 ~num_get() {}
778
779 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
780 ios_base::iostate& __err, bool& __v) const;
781 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
782 ios_base::iostate& __err, long& __v) const;
783 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
784 ios_base::iostate& __err, long long& __v) const;
785 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
786 ios_base::iostate& __err, unsigned short& __v) const;
787 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
788 ios_base::iostate& __err, unsigned int& __v) const;
789 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
790 ios_base::iostate& __err, unsigned long& __v) const;
791 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
792 ios_base::iostate& __err, unsigned long long& __v) const;
793 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
794 ios_base::iostate& __err, float& __v) const;
795 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
796 ios_base::iostate& __err, double& __v) const;
797 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
798 ios_base::iostate& __err, long double& __v) const;
799 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
800 ios_base::iostate& __err, void*& __v) const;
801};
802
803template <class _CharT, class _InputIterator>
804locale::id
805num_get<_CharT, _InputIterator>::id;
806
807template <class _Tp>
808_Tp
809__num_get_signed_integral(const char* __a, const char* __a_end,
810 ios_base::iostate& __err, int __base)
811{
812 if (__a != __a_end)
813 {
Howard Hinnante7c8da62011-02-25 19:52:41 +0000814 int __save_errno = errno;
815 errno = 0;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000816 char *__p2;
Howard Hinnant2ea1ca92011-09-28 21:05:01 +0000817 long long __ll = strtoll_l(__a, &__p2, __base, _LIBCPP_GET_C_LOCALE);
Howard Hinnante7c8da62011-02-25 19:52:41 +0000818 int __current_errno = errno;
819 if (__current_errno == 0)
820 errno = __save_errno;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000821 if (__p2 != __a_end)
822 {
823 __err = ios_base::failbit;
824 return 0;
825 }
Howard Hinnante7c8da62011-02-25 19:52:41 +0000826 else if (__current_errno == ERANGE ||
827 __ll < numeric_limits<_Tp>::min() ||
828 numeric_limits<_Tp>::max() < __ll)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000829 {
830 __err = ios_base::failbit;
Howard Hinnante7c8da62011-02-25 19:52:41 +0000831 if (__ll > 0)
832 return numeric_limits<_Tp>::max();
833 else
834 return numeric_limits<_Tp>::min();
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000835 }
836 return static_cast<_Tp>(__ll);
837 }
838 __err = ios_base::failbit;
839 return 0;
840}
841
842template <class _Tp>
843_Tp
844__num_get_unsigned_integral(const char* __a, const char* __a_end,
845 ios_base::iostate& __err, int __base)
846{
847 if (__a != __a_end)
848 {
Howard Hinnante7c8da62011-02-25 19:52:41 +0000849 if (*__a == '-')
850 {
851 __err = ios_base::failbit;
852 return 0;
853 }
854 int __save_errno = errno;
855 errno = 0;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000856 char *__p2;
Howard Hinnant2ea1ca92011-09-28 21:05:01 +0000857 unsigned long long __ll = strtoull_l(__a, &__p2, __base, _LIBCPP_GET_C_LOCALE);
Howard Hinnante7c8da62011-02-25 19:52:41 +0000858 int __current_errno = errno;
859 if (__current_errno == 0)
860 errno = __save_errno;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000861 if (__p2 != __a_end)
862 {
863 __err = ios_base::failbit;
864 return 0;
865 }
Howard Hinnante7c8da62011-02-25 19:52:41 +0000866 else if (__current_errno == ERANGE ||
867 numeric_limits<_Tp>::max() < __ll)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000868 {
869 __err = ios_base::failbit;
870 return numeric_limits<_Tp>::max();
871 }
872 return static_cast<_Tp>(__ll);
873 }
874 __err = ios_base::failbit;
875 return 0;
876}
877
878template <class _Tp>
879_Tp
880__num_get_float(const char* __a, const char* __a_end, ios_base::iostate& __err)
881{
882 if (__a != __a_end)
883 {
884 char *__p2;
Howard Hinnant2ea1ca92011-09-28 21:05:01 +0000885 long double __ld = strtold_l(__a, &__p2, _LIBCPP_GET_C_LOCALE);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000886 if (__p2 != __a_end)
887 {
888 __err = ios_base::failbit;
889 return 0;
890 }
891 return static_cast<_Tp>(__ld);
892 }
893 __err = ios_base::failbit;
894 return 0;
895}
896
897template <class _CharT, class _InputIterator>
898_InputIterator
899num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
900 ios_base& __iob,
901 ios_base::iostate& __err,
902 bool& __v) const
903{
904 if ((__iob.flags() & ios_base::boolalpha) == 0)
905 {
906 long __lv = -1;
907 __b = do_get(__b, __e, __iob, __err, __lv);
908 switch (__lv)
909 {
910 case 0:
911 __v = false;
912 break;
913 case 1:
914 __v = true;
915 break;
916 default:
917 __v = true;
918 __err = ios_base::failbit;
919 break;
920 }
921 return __b;
922 }
923 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__iob.getloc());
924 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__iob.getloc());
925 typedef typename numpunct<_CharT>::string_type string_type;
926 const string_type __names[2] = {__np.truename(), __np.falsename()};
927 const string_type* __i = __scan_keyword(__b, __e, __names, __names+2,
928 __ct, __err);
929 __v = __i == __names;
930 return __b;
931}
932
933template <class _CharT, class _InputIterator>
934_InputIterator
935num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
936 ios_base& __iob,
937 ios_base::iostate& __err,
938 long& __v) const
939{
940 // Stage 1
941 int __base = this->__get_base(__iob);
942 // Stage 2
943 char_type __atoms[26];
944 char_type __thousands_sep;
945 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
946 char __a[__num_get_base::__num_get_buf_sz] = {0};
947 char* __a_end = __a;
948 unsigned __g[__num_get_base::__num_get_buf_sz];
949 unsigned* __g_end = __g;
950 unsigned __dc = 0;
951 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +0000952 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000953 __thousands_sep, __grouping, __g, __g_end,
954 __atoms))
955 break;
956 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
957 *__g_end++ = __dc;
958 // Stage 3
959 __v = __num_get_signed_integral<long>(__a, __a_end, __err, __base);
960 // Digit grouping checked
961 __check_grouping(__grouping, __g, __g_end, __err);
962 // EOF checked
963 if (__b == __e)
964 __err |= ios_base::eofbit;
965 return __b;
966}
967
968template <class _CharT, class _InputIterator>
969_InputIterator
970num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
971 ios_base& __iob,
972 ios_base::iostate& __err,
973 long long& __v) const
974{
975 // Stage 1
976 int __base = this->__get_base(__iob);
977 // Stage 2
978 char_type __atoms[26];
979 char_type __thousands_sep;
980 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
981 char __a[__num_get_base::__num_get_buf_sz] = {0};
982 char* __a_end = __a;
983 unsigned __g[__num_get_base::__num_get_buf_sz];
984 unsigned* __g_end = __g;
985 unsigned __dc = 0;
986 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +0000987 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
988 __thousands_sep, __grouping, __g, __g_end,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000989 __atoms))
990 break;
991 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
992 *__g_end++ = __dc;
993 // Stage 3
994 __v = __num_get_signed_integral<long long>(__a, __a_end, __err, __base);
995 // Digit grouping checked
996 __check_grouping(__grouping, __g, __g_end, __err);
997 // EOF checked
998 if (__b == __e)
999 __err |= ios_base::eofbit;
1000 return __b;
1001}
1002
1003template <class _CharT, class _InputIterator>
1004_InputIterator
1005num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1006 ios_base& __iob,
1007 ios_base::iostate& __err,
1008 unsigned short& __v) const
1009{
1010 // Stage 1
1011 int __base = this->__get_base(__iob);
1012 // Stage 2
1013 char_type __atoms[26];
1014 char_type __thousands_sep;
1015 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
1016 char __a[__num_get_base::__num_get_buf_sz] = {0};
1017 char* __a_end = __a;
1018 unsigned __g[__num_get_base::__num_get_buf_sz];
1019 unsigned* __g_end = __g;
1020 unsigned __dc = 0;
1021 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001022 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001023 __thousands_sep, __grouping, __g, __g_end,
1024 __atoms))
1025 break;
1026 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
1027 *__g_end++ = __dc;
1028 // Stage 3
1029 __v = __num_get_unsigned_integral<unsigned short>(__a, __a_end, __err, __base);
1030 // Digit grouping checked
1031 __check_grouping(__grouping, __g, __g_end, __err);
1032 // EOF checked
1033 if (__b == __e)
1034 __err |= ios_base::eofbit;
1035 return __b;
1036}
1037
1038template <class _CharT, class _InputIterator>
1039_InputIterator
1040num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1041 ios_base& __iob,
1042 ios_base::iostate& __err,
1043 unsigned int& __v) const
1044{
1045 // Stage 1
1046 int __base = this->__get_base(__iob);
1047 // Stage 2
1048 char_type __atoms[26];
1049 char_type __thousands_sep;
1050 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
1051 char __a[__num_get_base::__num_get_buf_sz] = {0};
1052 char* __a_end = __a;
1053 unsigned __g[__num_get_base::__num_get_buf_sz];
1054 unsigned* __g_end = __g;
1055 unsigned __dc = 0;
1056 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001057 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001058 __thousands_sep, __grouping, __g, __g_end,
1059 __atoms))
1060 break;
1061 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
1062 *__g_end++ = __dc;
1063 // Stage 3
1064 __v = __num_get_unsigned_integral<unsigned int>(__a, __a_end, __err, __base);
1065 // Digit grouping checked
1066 __check_grouping(__grouping, __g, __g_end, __err);
1067 // EOF checked
1068 if (__b == __e)
1069 __err |= ios_base::eofbit;
1070 return __b;
1071}
1072
1073template <class _CharT, class _InputIterator>
1074_InputIterator
1075num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1076 ios_base& __iob,
1077 ios_base::iostate& __err,
1078 unsigned long& __v) const
1079{
1080 // Stage 1
1081 int __base = this->__get_base(__iob);
1082 // Stage 2
1083 char_type __atoms[26];
1084 char_type __thousands_sep;
1085 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
1086 char __a[__num_get_base::__num_get_buf_sz] = {0};
1087 char* __a_end = __a;
1088 unsigned __g[__num_get_base::__num_get_buf_sz];
1089 unsigned* __g_end = __g;
1090 unsigned __dc = 0;
1091 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001092 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001093 __thousands_sep, __grouping, __g, __g_end,
1094 __atoms))
1095 break;
1096 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
1097 *__g_end++ = __dc;
1098 // Stage 3
1099 __v = __num_get_unsigned_integral<unsigned long>(__a, __a_end, __err, __base);
1100 // Digit grouping checked
1101 __check_grouping(__grouping, __g, __g_end, __err);
1102 // EOF checked
1103 if (__b == __e)
1104 __err |= ios_base::eofbit;
1105 return __b;
1106}
1107
1108template <class _CharT, class _InputIterator>
1109_InputIterator
1110num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1111 ios_base& __iob,
1112 ios_base::iostate& __err,
1113 unsigned long long& __v) const
1114{
1115 // Stage 1
1116 int __base = this->__get_base(__iob);
1117 // Stage 2
1118 char_type __atoms[26];
1119 char_type __thousands_sep;
1120 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
1121 char __a[__num_get_base::__num_get_buf_sz] = {0};
1122 char* __a_end = __a;
1123 unsigned __g[__num_get_base::__num_get_buf_sz];
1124 unsigned* __g_end = __g;
1125 unsigned __dc = 0;
1126 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001127 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001128 __thousands_sep, __grouping, __g, __g_end,
1129 __atoms))
1130 break;
1131 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
1132 *__g_end++ = __dc;
1133 // Stage 3
1134 __v = __num_get_unsigned_integral<unsigned long long>(__a, __a_end, __err, __base);
1135 // Digit grouping checked
1136 __check_grouping(__grouping, __g, __g_end, __err);
1137 // EOF checked
1138 if (__b == __e)
1139 __err |= ios_base::eofbit;
1140 return __b;
1141}
1142
1143template <class _CharT, class _InputIterator>
1144_InputIterator
1145num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1146 ios_base& __iob,
1147 ios_base::iostate& __err,
1148 float& __v) const
1149{
1150 // Stage 1, nothing to do
1151 // Stage 2
1152 char_type __atoms[32];
1153 char_type __decimal_point;
1154 char_type __thousands_sep;
Howard Hinnant324bb032010-08-22 00:02:43 +00001155 string __grouping = this->__stage2_float_prep(__iob, __atoms,
1156 __decimal_point,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001157 __thousands_sep);
1158 char __a[__num_get_base::__num_get_buf_sz] = {0};
1159 char* __a_end = __a;
1160 unsigned __g[__num_get_base::__num_get_buf_sz];
1161 unsigned* __g_end = __g;
1162 unsigned __dc = 0;
1163 bool __in_units = true;
1164 char __exp = 'E';
1165 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001166 if (this->__stage2_float_loop(*__b, __in_units, __exp, __a, __a_end,
1167 __decimal_point, __thousands_sep,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001168 __grouping, __g, __g_end,
1169 __dc, __atoms))
1170 break;
1171 if (__grouping.size() != 0 && __in_units && __g_end-__g < __num_get_base::__num_get_buf_sz)
1172 *__g_end++ = __dc;
1173 // Stage 3
1174 __v = __num_get_float<float>(__a, __a_end, __err);
1175 // Digit grouping checked
1176 __check_grouping(__grouping, __g, __g_end, __err);
1177 // EOF checked
1178 if (__b == __e)
1179 __err |= ios_base::eofbit;
1180 return __b;
1181}
1182
1183template <class _CharT, class _InputIterator>
1184_InputIterator
1185num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1186 ios_base& __iob,
1187 ios_base::iostate& __err,
1188 double& __v) const
1189{
1190 // Stage 1, nothing to do
1191 // Stage 2
1192 char_type __atoms[32];
1193 char_type __decimal_point;
1194 char_type __thousands_sep;
Howard Hinnant324bb032010-08-22 00:02:43 +00001195 string __grouping = this->__stage2_float_prep(__iob, __atoms,
1196 __decimal_point,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001197 __thousands_sep);
1198 char __a[__num_get_base::__num_get_buf_sz] = {0};
1199 char* __a_end = __a;
1200 unsigned __g[__num_get_base::__num_get_buf_sz];
1201 unsigned* __g_end = __g;
1202 unsigned __dc = 0;
1203 bool __in_units = true;
1204 char __exp = 'E';
1205 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001206 if (this->__stage2_float_loop(*__b, __in_units, __exp, __a, __a_end,
1207 __decimal_point, __thousands_sep,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001208 __grouping, __g, __g_end,
1209 __dc, __atoms))
1210 break;
1211 if (__grouping.size() != 0 && __in_units && __g_end-__g < __num_get_base::__num_get_buf_sz)
1212 *__g_end++ = __dc;
1213 // Stage 3
1214 __v = __num_get_float<double>(__a, __a_end, __err);
1215 // Digit grouping checked
1216 __check_grouping(__grouping, __g, __g_end, __err);
1217 // EOF checked
1218 if (__b == __e)
1219 __err |= ios_base::eofbit;
1220 return __b;
1221}
1222
1223template <class _CharT, class _InputIterator>
1224_InputIterator
1225num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1226 ios_base& __iob,
1227 ios_base::iostate& __err,
1228 long double& __v) const
1229{
1230 // Stage 1, nothing to do
1231 // Stage 2
1232 char_type __atoms[32];
1233 char_type __decimal_point;
1234 char_type __thousands_sep;
Howard Hinnant324bb032010-08-22 00:02:43 +00001235 string __grouping = this->__stage2_float_prep(__iob, __atoms,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001236 __decimal_point,
1237 __thousands_sep);
1238 char __a[__num_get_base::__num_get_buf_sz] = {0};
1239 char* __a_end = __a;
1240 unsigned __g[__num_get_base::__num_get_buf_sz];
1241 unsigned* __g_end = __g;
1242 unsigned __dc = 0;
1243 bool __in_units = true;
1244 char __exp = 'E';
1245 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001246 if (this->__stage2_float_loop(*__b, __in_units, __exp, __a, __a_end,
1247 __decimal_point, __thousands_sep,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001248 __grouping, __g, __g_end,
1249 __dc, __atoms))
1250 break;
1251 if (__grouping.size() != 0 && __in_units && __g_end-__g < __num_get_base::__num_get_buf_sz)
1252 *__g_end++ = __dc;
1253 // Stage 3
1254 __v = __num_get_float<long double>(__a, __a_end, __err);
1255 // Digit grouping checked
1256 __check_grouping(__grouping, __g, __g_end, __err);
1257 // EOF checked
1258 if (__b == __e)
1259 __err |= ios_base::eofbit;
1260 return __b;
1261}
1262
1263template <class _CharT, class _InputIterator>
1264_InputIterator
1265num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1266 ios_base& __iob,
1267 ios_base::iostate& __err,
1268 void*& __v) const
1269{
1270 // Stage 1
1271 int __base = 16;
1272 // Stage 2
1273 char_type __atoms[26];
1274 char_type __thousands_sep;
1275 string __grouping;
1276 use_facet<ctype<_CharT> >(__iob.getloc()).widen(__num_get_base::__src,
1277 __num_get_base::__src + 26, __atoms);
1278 char __a[__num_get_base::__num_get_buf_sz] = {0};
1279 char* __a_end = __a;
1280 unsigned __g[__num_get_base::__num_get_buf_sz];
1281 unsigned* __g_end = __g;
1282 unsigned __dc = 0;
1283 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001284 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
1285 __thousands_sep, __grouping,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001286 __g, __g_end, __atoms))
1287 break;
1288 // Stage 3
1289 __a[sizeof(__a)-1] = 0;
Howard Hinnant866569b2011-09-28 23:39:33 +00001290#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001291 if (sscanf_l(__a, _LIBCPP_GET_C_LOCALE, "%p", &__v) != 1)
Sean Huntf3907e62011-07-15 05:40:33 +00001292#else
1293 if (__sscanf_l(__a, __cloc(), "%p", &__v) != 1)
1294#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001295 __err = ios_base::failbit;
1296 // EOF checked
1297 if (__b == __e)
1298 __err |= ios_base::eofbit;
1299 return __b;
1300}
1301
1302extern template class num_get<char>;
1303extern template class num_get<wchar_t>;
1304
1305struct __num_put_base
1306{
1307protected:
1308 static void __format_int(char* __fmt, const char* __len, bool __signd,
1309 ios_base::fmtflags __flags);
1310 static bool __format_float(char* __fmt, const char* __len,
1311 ios_base::fmtflags __flags);
1312 static char* __identify_padding(char* __nb, char* __ne,
1313 const ios_base& __iob);
1314};
1315
1316template <class _CharT>
1317struct __num_put
1318 : protected __num_put_base
1319{
1320 static void __widen_and_group_int(char* __nb, char* __np, char* __ne,
1321 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1322 const locale& __loc);
1323 static void __widen_and_group_float(char* __nb, char* __np, char* __ne,
1324 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1325 const locale& __loc);
1326};
1327
1328template <class _CharT>
1329void
1330__num_put<_CharT>::__widen_and_group_int(char* __nb, char* __np, char* __ne,
1331 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1332 const locale& __loc)
1333{
1334 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> > (__loc);
1335 const numpunct<_CharT>& __npt = use_facet<numpunct<_CharT> >(__loc);
1336 string __grouping = __npt.grouping();
1337 if (__grouping.empty())
1338 {
1339 __ct.widen(__nb, __ne, __ob);
1340 __oe = __ob + (__ne - __nb);
1341 }
1342 else
1343 {
1344 __oe = __ob;
1345 char* __nf = __nb;
1346 if (*__nf == '-' || *__nf == '+')
1347 *__oe++ = __ct.widen(*__nf++);
1348 if (__ne - __nf >= 2 && __nf[0] == '0' && (__nf[1] == 'x' ||
1349 __nf[1] == 'X'))
1350 {
1351 *__oe++ = __ct.widen(*__nf++);
1352 *__oe++ = __ct.widen(*__nf++);
1353 }
1354 reverse(__nf, __ne);
1355 _CharT __thousands_sep = __npt.thousands_sep();
1356 unsigned __dc = 0;
1357 unsigned __dg = 0;
1358 for (char* __p = __nf; __p < __ne; ++__p)
1359 {
1360 if (static_cast<unsigned>(__grouping[__dg]) > 0 &&
1361 __dc == static_cast<unsigned>(__grouping[__dg]))
1362 {
1363 *__oe++ = __thousands_sep;
1364 __dc = 0;
1365 if (__dg < __grouping.size()-1)
1366 ++__dg;
1367 }
1368 *__oe++ = __ct.widen(*__p);
1369 ++__dc;
1370 }
1371 reverse(__ob + (__nf - __nb), __oe);
1372 }
1373 if (__np == __ne)
1374 __op = __oe;
1375 else
1376 __op = __ob + (__np - __nb);
1377}
1378
1379template <class _CharT>
1380void
1381__num_put<_CharT>::__widen_and_group_float(char* __nb, char* __np, char* __ne,
1382 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1383 const locale& __loc)
1384{
1385 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> > (__loc);
1386 const numpunct<_CharT>& __npt = use_facet<numpunct<_CharT> >(__loc);
1387 string __grouping = __npt.grouping();
1388 __oe = __ob;
1389 char* __nf = __nb;
1390 if (*__nf == '-' || *__nf == '+')
1391 *__oe++ = __ct.widen(*__nf++);
1392 char* __ns;
1393 if (__ne - __nf >= 2 && __nf[0] == '0' && (__nf[1] == 'x' ||
1394 __nf[1] == 'X'))
1395 {
1396 *__oe++ = __ct.widen(*__nf++);
1397 *__oe++ = __ct.widen(*__nf++);
1398 for (__ns = __nf; __ns < __ne; ++__ns)
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001399 if (!isxdigit_l(*__ns, _LIBCPP_GET_C_LOCALE))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001400 break;
1401 }
1402 else
1403 {
1404 for (__ns = __nf; __ns < __ne; ++__ns)
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001405 if (!isdigit_l(*__ns, _LIBCPP_GET_C_LOCALE))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001406 break;
1407 }
1408 if (__grouping.empty())
1409 {
1410 __ct.widen(__nf, __ns, __oe);
1411 __oe += __ns - __nf;
1412 }
1413 else
1414 {
1415 reverse(__nf, __ns);
1416 _CharT __thousands_sep = __npt.thousands_sep();
1417 unsigned __dc = 0;
1418 unsigned __dg = 0;
1419 for (char* __p = __nf; __p < __ns; ++__p)
1420 {
1421 if (__grouping[__dg] > 0 && __dc == static_cast<unsigned>(__grouping[__dg]))
1422 {
1423 *__oe++ = __thousands_sep;
1424 __dc = 0;
1425 if (__dg < __grouping.size()-1)
1426 ++__dg;
1427 }
1428 *__oe++ = __ct.widen(*__p);
1429 ++__dc;
1430 }
1431 reverse(__ob + (__nf - __nb), __oe);
1432 }
1433 for (__nf = __ns; __nf < __ne; ++__nf)
1434 {
1435 if (*__nf == '.')
1436 {
1437 *__oe++ = __npt.decimal_point();
1438 ++__nf;
1439 break;
1440 }
1441 else
1442 *__oe++ = __ct.widen(*__nf);
1443 }
1444 __ct.widen(__nf, __ne, __oe);
1445 __oe += __ne - __nf;
1446 if (__np == __ne)
1447 __op = __oe;
1448 else
1449 __op = __ob + (__np - __nb);
1450}
1451
1452extern template class __num_put<char>;
1453extern template class __num_put<wchar_t>;
1454
1455template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00001456class _LIBCPP_VISIBLE num_put
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001457 : public locale::facet,
1458 private __num_put<_CharT>
1459{
1460public:
1461 typedef _CharT char_type;
1462 typedef _OutputIterator iter_type;
1463
1464 _LIBCPP_ALWAYS_INLINE
1465 explicit num_put(size_t __refs = 0)
1466 : locale::facet(__refs) {}
1467
1468 _LIBCPP_ALWAYS_INLINE
1469 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1470 bool __v) const
1471 {
1472 return do_put(__s, __iob, __fl, __v);
1473 }
1474
1475 _LIBCPP_ALWAYS_INLINE
1476 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1477 long __v) const
1478 {
1479 return do_put(__s, __iob, __fl, __v);
1480 }
1481
1482 _LIBCPP_ALWAYS_INLINE
1483 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1484 long long __v) const
1485 {
1486 return do_put(__s, __iob, __fl, __v);
1487 }
1488
1489 _LIBCPP_ALWAYS_INLINE
1490 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1491 unsigned long __v) const
1492 {
1493 return do_put(__s, __iob, __fl, __v);
1494 }
1495
1496 _LIBCPP_ALWAYS_INLINE
1497 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1498 unsigned long long __v) const
1499 {
1500 return do_put(__s, __iob, __fl, __v);
1501 }
1502
1503 _LIBCPP_ALWAYS_INLINE
1504 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1505 double __v) const
1506 {
1507 return do_put(__s, __iob, __fl, __v);
1508 }
1509
1510 _LIBCPP_ALWAYS_INLINE
1511 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1512 long double __v) const
1513 {
1514 return do_put(__s, __iob, __fl, __v);
1515 }
1516
1517 _LIBCPP_ALWAYS_INLINE
1518 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1519 const void* __v) const
1520 {
1521 return do_put(__s, __iob, __fl, __v);
1522 }
1523
1524 static locale::id id;
1525
1526protected:
Howard Hinnant82894812010-09-22 16:48:34 +00001527 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001528 ~num_put() {}
1529
1530 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1531 bool __v) const;
1532 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1533 long __v) const;
1534 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1535 long long __v) const;
1536 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1537 unsigned long) const;
1538 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1539 unsigned long long) const;
1540 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1541 double __v) const;
1542 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1543 long double __v) const;
1544 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1545 const void* __v) const;
1546};
1547
1548template <class _CharT, class _OutputIterator>
1549locale::id
1550num_put<_CharT, _OutputIterator>::id;
1551
1552template <class _CharT, class _OutputIterator>
1553_LIBCPP_HIDDEN
1554_OutputIterator
1555__pad_and_output(_OutputIterator __s,
1556 const _CharT* __ob, const _CharT* __op, const _CharT* __oe,
1557 ios_base& __iob, _CharT __fl)
1558{
1559 streamsize __sz = __oe - __ob;
1560 streamsize __ns = __iob.width();
1561 if (__ns > __sz)
1562 __ns -= __sz;
1563 else
1564 __ns = 0;
1565 for (;__ob < __op; ++__ob, ++__s)
1566 *__s = *__ob;
1567 for (; __ns; --__ns, ++__s)
1568 *__s = __fl;
1569 for (; __ob < __oe; ++__ob, ++__s)
1570 *__s = *__ob;
1571 __iob.width(0);
1572 return __s;
1573}
1574
1575template <class _CharT, class _OutputIterator>
1576_OutputIterator
1577num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1578 char_type __fl, bool __v) const
1579{
1580 if ((__iob.flags() & ios_base::boolalpha) == 0)
1581 return do_put(__s, __iob, __fl, (unsigned long)__v);
1582 const numpunct<char_type>& __np = use_facet<numpunct<char_type> >(__iob.getloc());
1583 typedef typename numpunct<char_type>::string_type string_type;
1584 string_type __nm = __v ? __np.truename() : __np.falsename();
1585 for (typename string_type::iterator __i = __nm.begin(); __i != __nm.end(); ++__i, ++__s)
1586 *__s = *__i;
1587 return __s;
1588}
1589
1590template <class _CharT, class _OutputIterator>
1591_OutputIterator
1592num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1593 char_type __fl, long __v) const
1594{
1595 // Stage 1 - Get number in narrow char
1596 char __fmt[6] = {'%', 0};
1597 const char* __len = "l";
1598 this->__format_int(__fmt+1, __len, true, __iob.flags());
1599 const unsigned __nbuf = (numeric_limits<long>::digits / 3)
1600 + ((numeric_limits<long>::digits % 3) != 0)
1601 + 1;
1602 char __nar[__nbuf];
Howard Hinnant866569b2011-09-28 23:39:33 +00001603#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001604 int __nc = sprintf_l(__nar, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001605#else
1606 int __nc = __sprintf_l(__nar, __cloc(), __fmt, __v);
1607#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001608 char* __ne = __nar + __nc;
1609 char* __np = this->__identify_padding(__nar, __ne, __iob);
1610 // Stage 2 - Widen __nar while adding thousands separators
1611 char_type __o[2*(__nbuf-1) - 1];
1612 char_type* __op; // pad here
1613 char_type* __oe; // end of output
1614 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1615 // [__o, __oe) contains thousands_sep'd wide number
1616 // Stage 3 & 4
1617 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1618}
1619
1620template <class _CharT, class _OutputIterator>
1621_OutputIterator
1622num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1623 char_type __fl, long long __v) const
1624{
1625 // Stage 1 - Get number in narrow char
1626 char __fmt[8] = {'%', 0};
1627 const char* __len = "ll";
1628 this->__format_int(__fmt+1, __len, true, __iob.flags());
1629 const unsigned __nbuf = (numeric_limits<long long>::digits / 3)
1630 + ((numeric_limits<long long>::digits % 3) != 0)
1631 + 1;
1632 char __nar[__nbuf];
Howard Hinnant866569b2011-09-28 23:39:33 +00001633#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001634 int __nc = sprintf_l(__nar, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001635#else
1636 int __nc = __sprintf_l(__nar, __cloc(), __fmt, __v);
1637#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001638 char* __ne = __nar + __nc;
1639 char* __np = this->__identify_padding(__nar, __ne, __iob);
1640 // Stage 2 - Widen __nar while adding thousands separators
1641 char_type __o[2*(__nbuf-1) - 1];
1642 char_type* __op; // pad here
1643 char_type* __oe; // end of output
1644 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1645 // [__o, __oe) contains thousands_sep'd wide number
1646 // Stage 3 & 4
1647 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1648}
1649
1650template <class _CharT, class _OutputIterator>
1651_OutputIterator
1652num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1653 char_type __fl, unsigned long __v) const
1654{
1655 // Stage 1 - Get number in narrow char
1656 char __fmt[6] = {'%', 0};
1657 const char* __len = "l";
1658 this->__format_int(__fmt+1, __len, false, __iob.flags());
1659 const unsigned __nbuf = (numeric_limits<unsigned long>::digits / 3)
1660 + ((numeric_limits<unsigned long>::digits % 3) != 0)
1661 + 1;
1662 char __nar[__nbuf];
Howard Hinnant866569b2011-09-28 23:39:33 +00001663#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001664 int __nc = sprintf_l(__nar, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001665#else
1666 int __nc = __sprintf_l(__nar, __cloc(), __fmt, __v);
1667#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001668 char* __ne = __nar + __nc;
1669 char* __np = this->__identify_padding(__nar, __ne, __iob);
1670 // Stage 2 - Widen __nar while adding thousands separators
1671 char_type __o[2*(__nbuf-1) - 1];
1672 char_type* __op; // pad here
1673 char_type* __oe; // end of output
1674 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1675 // [__o, __oe) contains thousands_sep'd wide number
1676 // Stage 3 & 4
1677 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1678}
1679
1680template <class _CharT, class _OutputIterator>
1681_OutputIterator
1682num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1683 char_type __fl, unsigned long long __v) const
1684{
1685 // Stage 1 - Get number in narrow char
1686 char __fmt[8] = {'%', 0};
1687 const char* __len = "ll";
1688 this->__format_int(__fmt+1, __len, false, __iob.flags());
1689 const unsigned __nbuf = (numeric_limits<unsigned long long>::digits / 3)
1690 + ((numeric_limits<unsigned long long>::digits % 3) != 0)
1691 + 1;
1692 char __nar[__nbuf];
Howard Hinnant866569b2011-09-28 23:39:33 +00001693#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001694 int __nc = sprintf_l(__nar, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001695#else
1696 int __nc = __sprintf_l(__nar, __cloc(), __fmt, __v);
1697#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001698 char* __ne = __nar + __nc;
1699 char* __np = this->__identify_padding(__nar, __ne, __iob);
1700 // Stage 2 - Widen __nar while adding thousands separators
1701 char_type __o[2*(__nbuf-1) - 1];
1702 char_type* __op; // pad here
1703 char_type* __oe; // end of output
1704 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1705 // [__o, __oe) contains thousands_sep'd wide number
1706 // Stage 3 & 4
1707 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1708}
1709
1710template <class _CharT, class _OutputIterator>
1711_OutputIterator
1712num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1713 char_type __fl, double __v) const
1714{
1715 // Stage 1 - Get number in narrow char
1716 char __fmt[8] = {'%', 0};
1717 const char* __len = "";
1718 bool __specify_precision = this->__format_float(__fmt+1, __len, __iob.flags());
1719 const unsigned __nbuf = 30;
1720 char __nar[__nbuf];
1721 char* __nb = __nar;
1722 int __nc;
1723 if (__specify_precision)
Howard Hinnant866569b2011-09-28 23:39:33 +00001724#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001725 __nc = snprintf_l(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt,
Howard Hinnantadff4892010-05-24 17:49:41 +00001726 (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001727#else
1728 __nc = __snprintf_l(__nb, __nbuf, __cloc(), __fmt,
1729 (int)__iob.precision(), __v);
1730#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001731 else
Howard Hinnant866569b2011-09-28 23:39:33 +00001732#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001733 __nc = snprintf_l(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001734#else
1735 __nc = __snprintf_l(__nb, __nbuf, __cloc(), __fmt, __v);
1736#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001737 unique_ptr<char, void(*)(void*)> __nbh(0, free);
1738 if (__nc > static_cast<int>(__nbuf-1))
1739 {
1740 if (__specify_precision)
Howard Hinnant866569b2011-09-28 23:39:33 +00001741#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001742 __nc = asprintf_l(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001743#else
1744 __nc = __asprintf_l(&__nb, __cloc(), __fmt,
David Chisnallc512df12011-09-21 08:39:44 +00001745 (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001746#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001747 else
Howard Hinnant866569b2011-09-28 23:39:33 +00001748#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001749 __nc = asprintf_l(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001750#else
David Chisnallc512df12011-09-21 08:39:44 +00001751 __nc = __asprintf_l(&__nb, __cloc(), __fmt, (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001752#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001753 if (__nb == 0)
1754 __throw_bad_alloc();
1755 __nbh.reset(__nb);
1756 }
1757 char* __ne = __nb + __nc;
1758 char* __np = this->__identify_padding(__nb, __ne, __iob);
1759 // Stage 2 - Widen __nar while adding thousands separators
1760 char_type __o[2*(__nbuf-1) - 1];
1761 char_type* __ob = __o;
1762 unique_ptr<char_type, void(*)(void*)> __obh(0, free);
1763 if (__nb != __nar)
1764 {
1765 __ob = (char_type*)malloc((2*__nc)*sizeof(char_type));
1766 if (__ob == 0)
1767 __throw_bad_alloc();
1768 __obh.reset(__ob);
1769 }
1770 char_type* __op; // pad here
1771 char_type* __oe; // end of output
1772 this->__widen_and_group_float(__nb, __np, __ne, __ob, __op, __oe, __iob.getloc());
1773 // [__o, __oe) contains thousands_sep'd wide number
1774 // Stage 3 & 4
1775 __s = __pad_and_output(__s, __ob, __op, __oe, __iob, __fl);
1776 return __s;
1777}
1778
1779template <class _CharT, class _OutputIterator>
1780_OutputIterator
1781num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1782 char_type __fl, long double __v) const
1783{
1784 // Stage 1 - Get number in narrow char
1785 char __fmt[8] = {'%', 0};
1786 const char* __len = "L";
1787 bool __specify_precision = this->__format_float(__fmt+1, __len, __iob.flags());
1788 const unsigned __nbuf = 30;
1789 char __nar[__nbuf];
1790 char* __nb = __nar;
1791 int __nc;
1792 if (__specify_precision)
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,
Howard Hinnantadff4892010-05-24 17:49:41 +00001795 (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001796#else
1797 __nc = __snprintf_l(__nb, __nbuf, __cloc(), __fmt,
1798 (int)__iob.precision(), __v);
1799#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001800 else
Howard Hinnant866569b2011-09-28 23:39:33 +00001801#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001802 __nc = snprintf_l(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001803#else
1804 __nc = __snprintf_l(__nb, __nbuf, __cloc(), __fmt, __v);
1805#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001806 unique_ptr<char, void(*)(void*)> __nbh(0, free);
1807 if (__nc > static_cast<int>(__nbuf-1))
1808 {
1809 if (__specify_precision)
Howard Hinnant866569b2011-09-28 23:39:33 +00001810#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001811 __nc = asprintf_l(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001812#else
1813 __nc = __asprintf_l(&__nb, __cloc(), __fmt,
David Chisnallc512df12011-09-21 08:39:44 +00001814 (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001815#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001816 else
Howard Hinnant866569b2011-09-28 23:39:33 +00001817#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001818 __nc = asprintf_l(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001819#else
David Chisnallc512df12011-09-21 08:39:44 +00001820 __nc = __asprintf_l(&__nb, __cloc(), __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001821#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001822 if (__nb == 0)
1823 __throw_bad_alloc();
1824 __nbh.reset(__nb);
1825 }
1826 char* __ne = __nb + __nc;
1827 char* __np = this->__identify_padding(__nb, __ne, __iob);
1828 // Stage 2 - Widen __nar while adding thousands separators
1829 char_type __o[2*(__nbuf-1) - 1];
1830 char_type* __ob = __o;
1831 unique_ptr<char_type, void(*)(void*)> __obh(0, free);
1832 if (__nb != __nar)
1833 {
1834 __ob = (char_type*)malloc((2*__nc)*sizeof(char_type));
1835 if (__ob == 0)
1836 __throw_bad_alloc();
1837 __obh.reset(__ob);
1838 }
1839 char_type* __op; // pad here
1840 char_type* __oe; // end of output
1841 this->__widen_and_group_float(__nb, __np, __ne, __ob, __op, __oe, __iob.getloc());
1842 // [__o, __oe) contains thousands_sep'd wide number
1843 // Stage 3 & 4
1844 __s = __pad_and_output(__s, __ob, __op, __oe, __iob, __fl);
1845 return __s;
1846}
1847
1848template <class _CharT, class _OutputIterator>
1849_OutputIterator
1850num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1851 char_type __fl, const void* __v) const
1852{
1853 // Stage 1 - Get pointer in narrow char
1854 char __fmt[6] = "%p";
1855 const unsigned __nbuf = 20;
1856 char __nar[__nbuf];
Howard Hinnant866569b2011-09-28 23:39:33 +00001857#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001858 int __nc = sprintf_l(__nar, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001859#else
1860 int __nc = __sprintf_l(__nar, __cloc(), __fmt, __v);
1861#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001862 char* __ne = __nar + __nc;
1863 char* __np = this->__identify_padding(__nar, __ne, __iob);
1864 // Stage 2 - Widen __nar
1865 char_type __o[2*(__nbuf-1) - 1];
1866 char_type* __op; // pad here
1867 char_type* __oe; // end of output
1868 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
1869 __ct.widen(__nar, __ne, __o);
1870 __oe = __o + (__ne - __nar);
1871 if (__np == __ne)
1872 __op = __oe;
1873 else
1874 __op = __o + (__np - __nar);
1875 // [__o, __oe) contains wide number
1876 // Stage 3 & 4
1877 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1878}
1879
1880extern template class num_put<char>;
1881extern template class num_put<wchar_t>;
1882
1883template <class _CharT, class _InputIterator>
1884_LIBCPP_HIDDEN
1885int
1886__get_up_to_n_digits(_InputIterator& __b, _InputIterator __e,
1887 ios_base::iostate& __err, const ctype<_CharT>& __ct, int __n)
1888{
1889 // Precondition: __n >= 1
1890 if (__b == __e)
1891 {
1892 __err |= ios_base::eofbit | ios_base::failbit;
1893 return 0;
1894 }
1895 // get first digit
1896 _CharT __c = *__b;
1897 if (!__ct.is(ctype_base::digit, __c))
1898 {
1899 __err |= ios_base::failbit;
1900 return 0;
1901 }
1902 int __r = __ct.narrow(__c, 0) - '0';
1903 for (++__b, --__n; __b != __e && __n > 0; ++__b, --__n)
1904 {
1905 // get next digit
1906 __c = *__b;
1907 if (!__ct.is(ctype_base::digit, __c))
1908 return __r;
1909 __r = __r * 10 + __ct.narrow(__c, 0) - '0';
1910 }
1911 if (__b == __e)
1912 __err |= ios_base::eofbit;
1913 return __r;
1914}
1915
Howard Hinnant82894812010-09-22 16:48:34 +00001916class _LIBCPP_VISIBLE time_base
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001917{
1918public:
1919 enum dateorder {no_order, dmy, mdy, ymd, ydm};
1920};
1921
1922template <class _CharT>
Howard Hinnant2d72b1e2010-12-17 14:46:43 +00001923class __time_get_c_storage // purposefully not decorated
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001924{
1925protected:
1926 typedef basic_string<_CharT> string_type;
1927
1928 virtual const string_type* __weeks() const;
1929 virtual const string_type* __months() const;
1930 virtual const string_type* __am_pm() const;
1931 virtual const string_type& __c() const;
1932 virtual const string_type& __r() const;
1933 virtual const string_type& __x() const;
1934 virtual const string_type& __X() const;
1935};
1936
1937template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00001938class _LIBCPP_VISIBLE time_get
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001939 : public locale::facet,
1940 public time_base,
1941 private __time_get_c_storage<_CharT>
1942{
1943public:
1944 typedef _CharT char_type;
1945 typedef _InputIterator iter_type;
1946 typedef time_base::dateorder dateorder;
1947 typedef basic_string<char_type> string_type;
1948
1949 _LIBCPP_ALWAYS_INLINE
1950 explicit time_get(size_t __refs = 0)
1951 : locale::facet(__refs) {}
1952
1953 _LIBCPP_ALWAYS_INLINE
1954 dateorder date_order() const
1955 {
1956 return this->do_date_order();
1957 }
1958
1959 _LIBCPP_ALWAYS_INLINE
1960 iter_type get_time(iter_type __b, iter_type __e, ios_base& __iob,
1961 ios_base::iostate& __err, tm* __tm) const
1962 {
1963 return do_get_time(__b, __e, __iob, __err, __tm);
1964 }
1965
1966 _LIBCPP_ALWAYS_INLINE
1967 iter_type get_date(iter_type __b, iter_type __e, ios_base& __iob,
1968 ios_base::iostate& __err, tm* __tm) const
1969 {
1970 return do_get_date(__b, __e, __iob, __err, __tm);
1971 }
1972
1973 _LIBCPP_ALWAYS_INLINE
1974 iter_type get_weekday(iter_type __b, iter_type __e, ios_base& __iob,
1975 ios_base::iostate& __err, tm* __tm) const
1976 {
1977 return do_get_weekday(__b, __e, __iob, __err, __tm);
1978 }
1979
1980 _LIBCPP_ALWAYS_INLINE
1981 iter_type get_monthname(iter_type __b, iter_type __e, ios_base& __iob,
1982 ios_base::iostate& __err, tm* __tm) const
1983 {
1984 return do_get_monthname(__b, __e, __iob, __err, __tm);
1985 }
1986
1987 _LIBCPP_ALWAYS_INLINE
1988 iter_type get_year(iter_type __b, iter_type __e, ios_base& __iob,
1989 ios_base::iostate& __err, tm* __tm) const
1990 {
1991 return do_get_year(__b, __e, __iob, __err, __tm);
1992 }
1993
1994 _LIBCPP_ALWAYS_INLINE
1995 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
1996 ios_base::iostate& __err, tm *__tm,
1997 char __fmt, char __mod = 0) const
1998 {
1999 return do_get(__b, __e, __iob, __err, __tm, __fmt, __mod);
2000 }
2001
2002 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
2003 ios_base::iostate& __err, tm* __tm,
2004 const char_type* __fmtb, const char_type* __fmte) const;
2005
2006 static locale::id id;
2007
2008protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002009 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002010 ~time_get() {}
2011
2012 virtual dateorder do_date_order() const;
2013 virtual iter_type do_get_time(iter_type __b, iter_type __e, ios_base& __iob,
2014 ios_base::iostate& __err, tm* __tm) const;
2015 virtual iter_type do_get_date(iter_type __b, iter_type __e, ios_base& __iob,
2016 ios_base::iostate& __err, tm* __tm) const;
2017 virtual iter_type do_get_weekday(iter_type __b, iter_type __e, ios_base& __iob,
2018 ios_base::iostate& __err, tm* __tm) const;
2019 virtual iter_type do_get_monthname(iter_type __b, iter_type __e, ios_base& __iob,
2020 ios_base::iostate& __err, tm* __tm) const;
2021 virtual iter_type do_get_year(iter_type __b, iter_type __e, ios_base& __iob,
2022 ios_base::iostate& __err, tm* __tm) const;
2023 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
2024 ios_base::iostate& __err, tm* __tm,
2025 char __fmt, char __mod) const;
2026private:
2027 void __get_white_space(iter_type& __b, iter_type __e,
2028 ios_base::iostate& __err, const ctype<char_type>& __ct) const;
2029 void __get_percent(iter_type& __b, iter_type __e, ios_base::iostate& __err,
2030 const ctype<char_type>& __ct) const;
2031
2032 void __get_weekdayname(int& __m,
2033 iter_type& __b, iter_type __e,
2034 ios_base::iostate& __err,
2035 const ctype<char_type>& __ct) const;
2036 void __get_monthname(int& __m,
2037 iter_type& __b, iter_type __e,
2038 ios_base::iostate& __err,
2039 const ctype<char_type>& __ct) const;
2040 void __get_day(int& __d,
2041 iter_type& __b, iter_type __e,
2042 ios_base::iostate& __err,
2043 const ctype<char_type>& __ct) const;
2044 void __get_month(int& __m,
2045 iter_type& __b, iter_type __e,
2046 ios_base::iostate& __err,
2047 const ctype<char_type>& __ct) const;
2048 void __get_year(int& __y,
2049 iter_type& __b, iter_type __e,
2050 ios_base::iostate& __err,
2051 const ctype<char_type>& __ct) const;
2052 void __get_year4(int& __y,
2053 iter_type& __b, iter_type __e,
2054 ios_base::iostate& __err,
2055 const ctype<char_type>& __ct) const;
2056 void __get_hour(int& __d,
2057 iter_type& __b, iter_type __e,
2058 ios_base::iostate& __err,
2059 const ctype<char_type>& __ct) const;
2060 void __get_12_hour(int& __h,
2061 iter_type& __b, iter_type __e,
2062 ios_base::iostate& __err,
2063 const ctype<char_type>& __ct) const;
2064 void __get_am_pm(int& __h,
2065 iter_type& __b, iter_type __e,
2066 ios_base::iostate& __err,
2067 const ctype<char_type>& __ct) const;
2068 void __get_minute(int& __m,
2069 iter_type& __b, iter_type __e,
2070 ios_base::iostate& __err,
2071 const ctype<char_type>& __ct) const;
2072 void __get_second(int& __s,
2073 iter_type& __b, iter_type __e,
2074 ios_base::iostate& __err,
2075 const ctype<char_type>& __ct) const;
2076 void __get_weekday(int& __w,
2077 iter_type& __b, iter_type __e,
2078 ios_base::iostate& __err,
2079 const ctype<char_type>& __ct) const;
2080 void __get_day_year_num(int& __w,
2081 iter_type& __b, iter_type __e,
2082 ios_base::iostate& __err,
2083 const ctype<char_type>& __ct) const;
2084};
2085
2086template <class _CharT, class _InputIterator>
2087locale::id
2088time_get<_CharT, _InputIterator>::id;
2089
2090// time_get primatives
2091
2092template <class _CharT, class _InputIterator>
2093void
2094time_get<_CharT, _InputIterator>::__get_weekdayname(int& __w,
2095 iter_type& __b, iter_type __e,
2096 ios_base::iostate& __err,
2097 const ctype<char_type>& __ct) const
2098{
2099 // Note: ignoring case comes from the POSIX strptime spec
2100 const string_type* __wk = this->__weeks();
2101 int __i = __scan_keyword(__b, __e, __wk, __wk+14, __ct, __err, false) - __wk;
2102 if (__i < 14)
2103 __w = __i % 7;
2104}
2105
2106template <class _CharT, class _InputIterator>
2107void
2108time_get<_CharT, _InputIterator>::__get_monthname(int& __m,
2109 iter_type& __b, iter_type __e,
2110 ios_base::iostate& __err,
2111 const ctype<char_type>& __ct) const
2112{
2113 // Note: ignoring case comes from the POSIX strptime spec
2114 const string_type* __month = this->__months();
2115 int __i = __scan_keyword(__b, __e, __month, __month+24, __ct, __err, false) - __month;
2116 if (__i < 24)
2117 __m = __i % 12;
2118}
2119
2120template <class _CharT, class _InputIterator>
2121void
2122time_get<_CharT, _InputIterator>::__get_day(int& __d,
2123 iter_type& __b, iter_type __e,
2124 ios_base::iostate& __err,
2125 const ctype<char_type>& __ct) const
2126{
2127 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2128 if (!(__err & ios_base::failbit) && 1 <= __t && __t <= 31)
2129 __d = __t;
2130 else
2131 __err |= ios_base::failbit;
2132}
2133
2134template <class _CharT, class _InputIterator>
2135void
2136time_get<_CharT, _InputIterator>::__get_month(int& __m,
2137 iter_type& __b, iter_type __e,
2138 ios_base::iostate& __err,
2139 const ctype<char_type>& __ct) const
2140{
2141 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2) - 1;
2142 if (!(__err & ios_base::failbit) && __t <= 11)
2143 __m = __t;
2144 else
2145 __err |= ios_base::failbit;
2146}
2147
2148template <class _CharT, class _InputIterator>
2149void
2150time_get<_CharT, _InputIterator>::__get_year(int& __y,
2151 iter_type& __b, iter_type __e,
2152 ios_base::iostate& __err,
2153 const ctype<char_type>& __ct) const
2154{
2155 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 4);
2156 if (!(__err & ios_base::failbit))
2157 {
2158 if (__t < 69)
2159 __t += 2000;
2160 else if (69 <= __t && __t <= 99)
2161 __t += 1900;
2162 __y = __t - 1900;
2163 }
2164}
2165
2166template <class _CharT, class _InputIterator>
2167void
2168time_get<_CharT, _InputIterator>::__get_year4(int& __y,
2169 iter_type& __b, iter_type __e,
2170 ios_base::iostate& __err,
2171 const ctype<char_type>& __ct) const
2172{
2173 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 4);
2174 if (!(__err & ios_base::failbit))
2175 __y = __t - 1900;
2176}
2177
2178template <class _CharT, class _InputIterator>
2179void
2180time_get<_CharT, _InputIterator>::__get_hour(int& __h,
2181 iter_type& __b, iter_type __e,
2182 ios_base::iostate& __err,
2183 const ctype<char_type>& __ct) const
2184{
2185 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2186 if (!(__err & ios_base::failbit) && __t <= 23)
2187 __h = __t;
2188 else
2189 __err |= ios_base::failbit;
2190}
2191
2192template <class _CharT, class _InputIterator>
2193void
2194time_get<_CharT, _InputIterator>::__get_12_hour(int& __h,
2195 iter_type& __b, iter_type __e,
2196 ios_base::iostate& __err,
2197 const ctype<char_type>& __ct) const
2198{
2199 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2200 if (!(__err & ios_base::failbit) && 1 <= __t && __t <= 12)
2201 __h = __t;
2202 else
2203 __err |= ios_base::failbit;
2204}
2205
2206template <class _CharT, class _InputIterator>
2207void
2208time_get<_CharT, _InputIterator>::__get_minute(int& __m,
2209 iter_type& __b, iter_type __e,
2210 ios_base::iostate& __err,
2211 const ctype<char_type>& __ct) const
2212{
2213 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2214 if (!(__err & ios_base::failbit) && __t <= 59)
2215 __m = __t;
2216 else
2217 __err |= ios_base::failbit;
2218}
2219
2220template <class _CharT, class _InputIterator>
2221void
2222time_get<_CharT, _InputIterator>::__get_second(int& __s,
2223 iter_type& __b, iter_type __e,
2224 ios_base::iostate& __err,
2225 const ctype<char_type>& __ct) const
2226{
2227 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2228 if (!(__err & ios_base::failbit) && __t <= 60)
2229 __s = __t;
2230 else
2231 __err |= ios_base::failbit;
2232}
2233
2234template <class _CharT, class _InputIterator>
2235void
2236time_get<_CharT, _InputIterator>::__get_weekday(int& __w,
2237 iter_type& __b, iter_type __e,
2238 ios_base::iostate& __err,
2239 const ctype<char_type>& __ct) const
2240{
2241 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 1);
2242 if (!(__err & ios_base::failbit) && __t <= 6)
2243 __w = __t;
2244 else
2245 __err |= ios_base::failbit;
2246}
2247
2248template <class _CharT, class _InputIterator>
2249void
2250time_get<_CharT, _InputIterator>::__get_day_year_num(int& __d,
2251 iter_type& __b, iter_type __e,
2252 ios_base::iostate& __err,
2253 const ctype<char_type>& __ct) const
2254{
2255 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 3);
2256 if (!(__err & ios_base::failbit) && __t <= 365)
2257 __d = __t;
2258 else
2259 __err |= ios_base::failbit;
2260}
2261
2262template <class _CharT, class _InputIterator>
2263void
2264time_get<_CharT, _InputIterator>::__get_white_space(iter_type& __b, iter_type __e,
2265 ios_base::iostate& __err,
2266 const ctype<char_type>& __ct) const
2267{
2268 for (; __b != __e && __ct.is(ctype_base::space, *__b); ++__b)
2269 ;
2270 if (__b == __e)
2271 __err |= ios_base::eofbit;
2272}
2273
2274template <class _CharT, class _InputIterator>
2275void
2276time_get<_CharT, _InputIterator>::__get_am_pm(int& __h,
2277 iter_type& __b, iter_type __e,
2278 ios_base::iostate& __err,
2279 const ctype<char_type>& __ct) const
2280{
2281 const string_type* __ap = this->__am_pm();
2282 if (__ap[0].size() + __ap[1].size() == 0)
2283 {
2284 __err |= ios_base::failbit;
2285 return;
2286 }
2287 int __i = __scan_keyword(__b, __e, __ap, __ap+2, __ct, __err, false) - __ap;
2288 if (__i == 0 && __h == 12)
2289 __h = 0;
2290 else if (__i == 1 && __h < 12)
2291 __h += 12;
2292}
2293
2294template <class _CharT, class _InputIterator>
2295void
2296time_get<_CharT, _InputIterator>::__get_percent(iter_type& __b, iter_type __e,
2297 ios_base::iostate& __err,
2298 const ctype<char_type>& __ct) const
2299{
2300 if (__b == __e)
2301 {
2302 __err |= ios_base::eofbit | ios_base::failbit;
2303 return;
2304 }
2305 if (__ct.narrow(*__b, 0) != '%')
2306 __err |= ios_base::failbit;
2307 else if(++__b == __e)
2308 __err |= ios_base::eofbit;
2309}
2310
2311// time_get end primatives
2312
2313template <class _CharT, class _InputIterator>
2314_InputIterator
2315time_get<_CharT, _InputIterator>::get(iter_type __b, iter_type __e,
2316 ios_base& __iob,
2317 ios_base::iostate& __err, tm* __tm,
2318 const char_type* __fmtb, const char_type* __fmte) const
2319{
2320 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2321 __err = ios_base::goodbit;
2322 while (__fmtb != __fmte && __err == ios_base::goodbit)
2323 {
2324 if (__b == __e)
2325 {
2326 __err = ios_base::failbit;
2327 break;
2328 }
2329 if (__ct.narrow(*__fmtb, 0) == '%')
2330 {
2331 if (++__fmtb == __fmte)
2332 {
2333 __err = ios_base::failbit;
2334 break;
2335 }
2336 char __cmd = __ct.narrow(*__fmtb, 0);
2337 char __opt = '\0';
2338 if (__cmd == 'E' || __cmd == '0')
2339 {
2340 if (++__fmtb == __fmte)
2341 {
2342 __err = ios_base::failbit;
2343 break;
2344 }
2345 __opt = __cmd;
2346 __cmd = __ct.narrow(*__fmtb, 0);
2347 }
2348 __b = do_get(__b, __e, __iob, __err, __tm, __cmd, __opt);
2349 ++__fmtb;
2350 }
2351 else if (__ct.is(ctype_base::space, *__fmtb))
2352 {
2353 for (++__fmtb; __fmtb != __fmte && __ct.is(ctype_base::space, *__fmtb); ++__fmtb)
2354 ;
2355 for ( ; __b != __e && __ct.is(ctype_base::space, *__b); ++__b)
2356 ;
2357 }
2358 else if (__ct.toupper(*__b) == __ct.toupper(*__fmtb))
2359 {
2360 ++__b;
2361 ++__fmtb;
2362 }
2363 else
2364 __err = ios_base::failbit;
2365 }
2366 if (__b == __e)
2367 __err |= ios_base::eofbit;
2368 return __b;
2369}
2370
2371template <class _CharT, class _InputIterator>
2372typename time_get<_CharT, _InputIterator>::dateorder
2373time_get<_CharT, _InputIterator>::do_date_order() const
2374{
2375 return mdy;
2376}
2377
2378template <class _CharT, class _InputIterator>
2379_InputIterator
2380time_get<_CharT, _InputIterator>::do_get_time(iter_type __b, iter_type __e,
2381 ios_base& __iob,
2382 ios_base::iostate& __err,
2383 tm* __tm) const
2384{
2385 const char_type __fmt[] = {'%', 'H', ':', '%', 'M', ':', '%', 'S'};
2386 return get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2387}
2388
2389template <class _CharT, class _InputIterator>
2390_InputIterator
2391time_get<_CharT, _InputIterator>::do_get_date(iter_type __b, iter_type __e,
2392 ios_base& __iob,
2393 ios_base::iostate& __err,
2394 tm* __tm) const
2395{
2396 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2397 const string_type& __fmt = this->__x();
2398 return get(__b, __e, __iob, __err, __tm, __fmt.data(), __fmt.data() + __fmt.size());
2399}
2400
2401template <class _CharT, class _InputIterator>
2402_InputIterator
2403time_get<_CharT, _InputIterator>::do_get_weekday(iter_type __b, iter_type __e,
2404 ios_base& __iob,
2405 ios_base::iostate& __err,
2406 tm* __tm) const
2407{
2408 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2409 __get_weekdayname(__tm->tm_wday, __b, __e, __err, __ct);
2410 return __b;
2411}
2412
2413template <class _CharT, class _InputIterator>
2414_InputIterator
2415time_get<_CharT, _InputIterator>::do_get_monthname(iter_type __b, iter_type __e,
2416 ios_base& __iob,
2417 ios_base::iostate& __err,
2418 tm* __tm) const
2419{
2420 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2421 __get_monthname(__tm->tm_mon, __b, __e, __err, __ct);
2422 return __b;
2423}
2424
2425template <class _CharT, class _InputIterator>
2426_InputIterator
2427time_get<_CharT, _InputIterator>::do_get_year(iter_type __b, iter_type __e,
2428 ios_base& __iob,
2429 ios_base::iostate& __err,
2430 tm* __tm) const
2431{
2432 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2433 __get_year(__tm->tm_year, __b, __e, __err, __ct);
2434 return __b;
2435}
2436
2437template <class _CharT, class _InputIterator>
2438_InputIterator
2439time_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
2440 ios_base& __iob,
2441 ios_base::iostate& __err, tm* __tm,
2442 char __fmt, char) const
2443{
2444 __err = ios_base::goodbit;
2445 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2446 switch (__fmt)
2447 {
2448 case 'a':
2449 case 'A':
2450 __get_weekdayname(__tm->tm_wday, __b, __e, __err, __ct);
2451 break;
2452 case 'b':
2453 case 'B':
2454 case 'h':
2455 __get_monthname(__tm->tm_mon, __b, __e, __err, __ct);
2456 break;
2457 case 'c':
2458 {
2459 const string_type& __fmt = this->__c();
2460 __b = get(__b, __e, __iob, __err, __tm, __fmt.data(), __fmt.data() + __fmt.size());
2461 }
2462 break;
2463 case 'd':
2464 case 'e':
2465 __get_day(__tm->tm_mday, __b, __e, __err, __ct);
2466 break;
2467 case 'D':
2468 {
2469 const char_type __fmt[] = {'%', 'm', '/', '%', 'd', '/', '%', 'y'};
2470 __b = get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2471 }
2472 break;
Howard Hinnant506b3642011-04-10 17:54:14 +00002473 case 'F':
2474 {
2475 const char_type __fmt[] = {'%', 'Y', '-', '%', 'm', '-', '%', 'd'};
2476 __b = get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2477 }
2478 break;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002479 case 'H':
2480 __get_hour(__tm->tm_hour, __b, __e, __err, __ct);
2481 break;
2482 case 'I':
2483 __get_12_hour(__tm->tm_hour, __b, __e, __err, __ct);
2484 break;
2485 case 'j':
2486 __get_day_year_num(__tm->tm_yday, __b, __e, __err, __ct);
2487 break;
2488 case 'm':
2489 __get_month(__tm->tm_mon, __b, __e, __err, __ct);
2490 break;
2491 case 'M':
2492 __get_minute(__tm->tm_min, __b, __e, __err, __ct);
2493 break;
2494 case 'n':
2495 case 't':
2496 __get_white_space(__b, __e, __err, __ct);
2497 break;
2498 case 'p':
2499 __get_am_pm(__tm->tm_hour, __b, __e, __err, __ct);
2500 break;
2501 case 'r':
2502 {
2503 const char_type __fmt[] = {'%', 'I', ':', '%', 'M', ':', '%', 'S', ' ', '%', 'p'};
2504 __b = get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2505 }
2506 break;
2507 case 'R':
2508 {
2509 const char_type __fmt[] = {'%', 'H', ':', '%', 'M'};
2510 __b = get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2511 }
2512 break;
2513 case 'S':
2514 __get_second(__tm->tm_sec, __b, __e, __err, __ct);
2515 break;
2516 case 'T':
2517 {
2518 const char_type __fmt[] = {'%', 'H', ':', '%', 'M', ':', '%', 'S'};
2519 __b = get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2520 }
2521 break;
2522 case 'w':
2523 __get_weekday(__tm->tm_wday, __b, __e, __err, __ct);
2524 break;
2525 case 'x':
2526 return do_get_date(__b, __e, __iob, __err, __tm);
2527 case 'X':
2528 {
2529 const string_type& __fmt = this->__X();
2530 __b = get(__b, __e, __iob, __err, __tm, __fmt.data(), __fmt.data() + __fmt.size());
2531 }
2532 break;
2533 case 'y':
2534 __get_year(__tm->tm_year, __b, __e, __err, __ct);
2535 break;
2536 case 'Y':
2537 __get_year4(__tm->tm_year, __b, __e, __err, __ct);
2538 break;
2539 case '%':
2540 __get_percent(__b, __e, __err, __ct);
2541 break;
2542 default:
2543 __err |= ios_base::failbit;
2544 }
2545 return __b;
2546}
2547
2548extern template class time_get<char>;
2549extern template class time_get<wchar_t>;
2550
2551class __time_get
2552{
2553protected:
2554 locale_t __loc_;
2555
2556 __time_get(const char* __nm);
2557 __time_get(const string& __nm);
2558 ~__time_get();
2559};
2560
2561template <class _CharT>
2562class __time_get_storage
2563 : public __time_get
2564{
2565protected:
2566 typedef basic_string<_CharT> string_type;
2567
2568 string_type __weeks_[14];
2569 string_type __months_[24];
2570 string_type __am_pm_[2];
2571 string_type __c_;
2572 string_type __r_;
2573 string_type __x_;
2574 string_type __X_;
2575
2576 explicit __time_get_storage(const char* __nm);
2577 explicit __time_get_storage(const string& __nm);
2578
2579 _LIBCPP_ALWAYS_INLINE ~__time_get_storage() {}
2580
2581 time_base::dateorder __do_date_order() const;
2582
2583private:
2584 void init(const ctype<_CharT>&);
2585 string_type __analyze(char __fmt, const ctype<_CharT>&);
2586};
2587
2588template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00002589class _LIBCPP_VISIBLE time_get_byname
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002590 : public time_get<_CharT, _InputIterator>,
2591 private __time_get_storage<_CharT>
2592{
2593public:
2594 typedef time_base::dateorder dateorder;
2595 typedef _InputIterator iter_type;
2596 typedef _CharT char_type;
2597 typedef basic_string<char_type> string_type;
2598
Howard Hinnant82894812010-09-22 16:48:34 +00002599 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002600 explicit time_get_byname(const char* __nm, size_t __refs = 0)
2601 : time_get<_CharT, _InputIterator>(__refs),
2602 __time_get_storage<_CharT>(__nm) {}
Howard Hinnant82894812010-09-22 16:48:34 +00002603 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002604 explicit time_get_byname(const string& __nm, size_t __refs = 0)
2605 : time_get<_CharT, _InputIterator>(__refs),
2606 __time_get_storage<_CharT>(__nm) {}
2607
2608protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002609 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002610 ~time_get_byname() {}
2611
Howard Hinnant82894812010-09-22 16:48:34 +00002612 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002613 virtual dateorder do_date_order() const {return this->__do_date_order();}
2614private:
Howard Hinnant82894812010-09-22 16:48:34 +00002615 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002616 virtual const string_type* __weeks() const {return this->__weeks_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002617 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002618 virtual const string_type* __months() const {return this->__months_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002619 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002620 virtual const string_type* __am_pm() const {return this->__am_pm_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002621 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002622 virtual const string_type& __c() const {return this->__c_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002623 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002624 virtual const string_type& __r() const {return this->__r_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002625 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002626 virtual const string_type& __x() const {return this->__x_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002627 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002628 virtual const string_type& __X() const {return this->__X_;}
2629};
2630
2631extern template class time_get_byname<char>;
2632extern template class time_get_byname<wchar_t>;
2633
2634class __time_put
2635{
2636 locale_t __loc_;
2637protected:
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00002638 _LIBCPP_ALWAYS_INLINE __time_put() : __loc_(_LIBCPP_GET_C_LOCALE) {}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002639 __time_put(const char* __nm);
2640 __time_put(const string& __nm);
2641 ~__time_put();
2642 void __do_put(char* __nb, char*& __ne, const tm* __tm,
2643 char __fmt, char __mod) const;
2644 void __do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
2645 char __fmt, char __mod) const;
2646};
2647
2648template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00002649class _LIBCPP_VISIBLE time_put
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002650 : public locale::facet,
2651 private __time_put
2652{
2653public:
2654 typedef _CharT char_type;
2655 typedef _OutputIterator iter_type;
2656
2657 _LIBCPP_ALWAYS_INLINE
2658 explicit time_put(size_t __refs = 0)
2659 : locale::facet(__refs) {}
2660
2661 iter_type put(iter_type __s, ios_base& __iob, char_type __fl, const tm* __tm,
2662 const char_type* __pb, const char_type* __pe) const;
2663
2664 _LIBCPP_ALWAYS_INLINE
2665 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
2666 const tm* __tm, char __fmt, char __mod = 0) const
2667 {
2668 return do_put(__s, __iob, __fl, __tm, __fmt, __mod);
2669 }
2670
2671 static locale::id id;
2672
2673protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002674 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002675 ~time_put() {}
2676 virtual iter_type do_put(iter_type __s, ios_base&, char_type, const tm* __tm,
2677 char __fmt, char __mod) const;
2678
Howard Hinnant82894812010-09-22 16:48:34 +00002679 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002680 explicit time_put(const char* __nm, size_t __refs)
2681 : locale::facet(__refs),
2682 __time_put(__nm) {}
Howard Hinnant82894812010-09-22 16:48:34 +00002683 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002684 explicit time_put(const string& __nm, size_t __refs)
2685 : locale::facet(__refs),
2686 __time_put(__nm) {}
2687};
2688
2689template <class _CharT, class _OutputIterator>
2690locale::id
2691time_put<_CharT, _OutputIterator>::id;
2692
2693template <class _CharT, class _OutputIterator>
2694_OutputIterator
2695time_put<_CharT, _OutputIterator>::put(iter_type __s, ios_base& __iob,
2696 char_type __fl, const tm* __tm,
2697 const char_type* __pb,
2698 const char_type* __pe) const
2699{
2700 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2701 for (; __pb != __pe; ++__pb)
2702 {
2703 if (__ct.narrow(*__pb, 0) == '%')
2704 {
2705 if (++__pb == __pe)
2706 {
2707 *__s++ = __pb[-1];
2708 break;
2709 }
2710 char __mod = 0;
2711 char __fmt = __ct.narrow(*__pb, 0);
2712 if (__fmt == 'E' || __fmt == 'O')
2713 {
2714 if (++__pb == __pe)
2715 {
2716 *__s++ = __pb[-2];
2717 *__s++ = __pb[-1];
2718 break;
2719 }
2720 __mod = __fmt;
2721 __fmt = __ct.narrow(*__pb, 0);
2722 }
2723 __s = do_put(__s, __iob, __fl, __tm, __fmt, __mod);
2724 }
2725 else
2726 *__s++ = *__pb;
2727 }
2728 return __s;
2729}
2730
2731template <class _CharT, class _OutputIterator>
2732_OutputIterator
2733time_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
2734 char_type, const tm* __tm,
2735 char __fmt, char __mod) const
2736{
2737 char_type __nar[100];
2738 char_type* __nb = __nar;
2739 char_type* __ne = __nb + 100;
2740 __do_put(__nb, __ne, __tm, __fmt, __mod);
Howard Hinnant0949eed2011-06-30 21:18:19 +00002741 return _VSTD::copy(__nb, __ne, __s);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002742}
2743
2744extern template class time_put<char>;
2745extern template class time_put<wchar_t>;
2746
2747template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00002748class _LIBCPP_VISIBLE time_put_byname
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002749 : public time_put<_CharT, _OutputIterator>
2750{
2751public:
2752 _LIBCPP_ALWAYS_INLINE
2753 explicit time_put_byname(const char* __nm, size_t __refs = 0)
2754 : time_put<_CharT, _OutputIterator>(__nm, __refs) {}
2755
2756 _LIBCPP_ALWAYS_INLINE
2757 explicit time_put_byname(const string& __nm, size_t __refs = 0)
2758 : time_put<_CharT, _OutputIterator>(__nm, __refs) {}
2759
2760protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002761 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002762 ~time_put_byname() {}
2763};
2764
2765extern template class time_put_byname<char>;
2766extern template class time_put_byname<wchar_t>;
2767
2768// money_base
2769
Howard Hinnant82894812010-09-22 16:48:34 +00002770class _LIBCPP_VISIBLE money_base
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002771{
2772public:
2773 enum part {none, space, symbol, sign, value};
2774 struct pattern {char field[4];};
2775
2776 _LIBCPP_ALWAYS_INLINE money_base() {}
2777};
2778
2779// moneypunct
2780
2781template <class _CharT, bool _International = false>
Howard Hinnant82894812010-09-22 16:48:34 +00002782class _LIBCPP_VISIBLE moneypunct
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002783 : public locale::facet,
2784 public money_base
2785{
2786public:
2787 typedef _CharT char_type;
2788 typedef basic_string<char_type> string_type;
2789
Howard Hinnant82894812010-09-22 16:48:34 +00002790 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002791 explicit moneypunct(size_t __refs = 0)
2792 : locale::facet(__refs) {}
2793
2794 _LIBCPP_ALWAYS_INLINE char_type decimal_point() const {return do_decimal_point();}
2795 _LIBCPP_ALWAYS_INLINE char_type thousands_sep() const {return do_thousands_sep();}
2796 _LIBCPP_ALWAYS_INLINE string grouping() const {return do_grouping();}
2797 _LIBCPP_ALWAYS_INLINE string_type curr_symbol() const {return do_curr_symbol();}
2798 _LIBCPP_ALWAYS_INLINE string_type positive_sign() const {return do_positive_sign();}
2799 _LIBCPP_ALWAYS_INLINE string_type negative_sign() const {return do_negative_sign();}
2800 _LIBCPP_ALWAYS_INLINE int frac_digits() const {return do_frac_digits();}
2801 _LIBCPP_ALWAYS_INLINE pattern pos_format() const {return do_pos_format();}
2802 _LIBCPP_ALWAYS_INLINE pattern neg_format() const {return do_neg_format();}
2803
2804 static locale::id id;
2805 static const bool intl = _International;
2806
2807protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002808 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002809 ~moneypunct() {}
2810
2811 virtual char_type do_decimal_point() const {return numeric_limits<char_type>::max();}
2812 virtual char_type do_thousands_sep() const {return numeric_limits<char_type>::max();}
2813 virtual string do_grouping() const {return string();}
2814 virtual string_type do_curr_symbol() const {return string_type();}
2815 virtual string_type do_positive_sign() const {return string_type();}
2816 virtual string_type do_negative_sign() const {return string_type(1, '-');}
2817 virtual int do_frac_digits() const {return 0;}
2818 virtual pattern do_pos_format() const
2819 {pattern __p = {symbol, sign, none, value}; return __p;}
2820 virtual pattern do_neg_format() const
2821 {pattern __p = {symbol, sign, none, value}; return __p;}
2822};
2823
2824template <class _CharT, bool _International>
2825locale::id
2826moneypunct<_CharT, _International>::id;
2827
2828extern template class moneypunct<char, false>;
2829extern template class moneypunct<char, true>;
2830extern template class moneypunct<wchar_t, false>;
2831extern template class moneypunct<wchar_t, true>;
2832
2833// moneypunct_byname
2834
2835template <class _CharT, bool _International = false>
Howard Hinnant82894812010-09-22 16:48:34 +00002836class _LIBCPP_VISIBLE moneypunct_byname
2837 : public moneypunct<_CharT, _International>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002838{
2839public:
2840 typedef money_base::pattern pattern;
2841 typedef _CharT char_type;
2842 typedef basic_string<char_type> string_type;
2843
2844 _LIBCPP_ALWAYS_INLINE
2845 explicit moneypunct_byname(const char* __nm, size_t __refs = 0)
2846 : moneypunct<_CharT, _International>(__refs) {init(__nm);}
2847
2848 _LIBCPP_ALWAYS_INLINE
2849 explicit moneypunct_byname(const string& __nm, size_t __refs = 0)
2850 : moneypunct<_CharT, _International>(__refs) {init(__nm.c_str());}
2851
2852protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002853 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002854 ~moneypunct_byname() {}
2855
2856 virtual char_type do_decimal_point() const {return __decimal_point_;}
2857 virtual char_type do_thousands_sep() const {return __thousands_sep_;}
2858 virtual string do_grouping() const {return __grouping_;}
2859 virtual string_type do_curr_symbol() const {return __curr_symbol_;}
2860 virtual string_type do_positive_sign() const {return __positive_sign_;}
2861 virtual string_type do_negative_sign() const {return __negative_sign_;}
2862 virtual int do_frac_digits() const {return __frac_digits_;}
2863 virtual pattern do_pos_format() const {return __pos_format_;}
2864 virtual pattern do_neg_format() const {return __neg_format_;}
2865
2866private:
2867 char_type __decimal_point_;
2868 char_type __thousands_sep_;
2869 string __grouping_;
2870 string_type __curr_symbol_;
2871 string_type __positive_sign_;
2872 string_type __negative_sign_;
2873 int __frac_digits_;
2874 pattern __pos_format_;
2875 pattern __neg_format_;
2876
2877 void init(const char*);
2878};
2879
2880template<> void moneypunct_byname<char, false>::init(const char*);
2881template<> void moneypunct_byname<char, true>::init(const char*);
2882template<> void moneypunct_byname<wchar_t, false>::init(const char*);
2883template<> void moneypunct_byname<wchar_t, true>::init(const char*);
2884
2885extern template class moneypunct_byname<char, false>;
2886extern template class moneypunct_byname<char, true>;
2887extern template class moneypunct_byname<wchar_t, false>;
2888extern template class moneypunct_byname<wchar_t, true>;
2889
2890// money_get
2891
2892template <class _CharT>
2893class __money_get
2894{
2895protected:
2896 typedef _CharT char_type;
2897 typedef basic_string<char_type> string_type;
2898
2899 _LIBCPP_ALWAYS_INLINE __money_get() {}
2900
2901 static void __gather_info(bool __intl, const locale& __loc,
2902 money_base::pattern& __pat, char_type& __dp,
2903 char_type& __ts, string& __grp,
2904 string_type& __sym, string_type& __psn,
2905 string_type& __nsn, int& __fd);
2906};
2907
2908template <class _CharT>
2909void
2910__money_get<_CharT>::__gather_info(bool __intl, const locale& __loc,
2911 money_base::pattern& __pat, char_type& __dp,
2912 char_type& __ts, string& __grp,
2913 string_type& __sym, string_type& __psn,
2914 string_type& __nsn, int& __fd)
2915{
2916 if (__intl)
2917 {
2918 const moneypunct<char_type, true>& __mp =
2919 use_facet<moneypunct<char_type, true> >(__loc);
2920 __pat = __mp.neg_format();
2921 __nsn = __mp.negative_sign();
2922 __psn = __mp.positive_sign();
2923 __dp = __mp.decimal_point();
2924 __ts = __mp.thousands_sep();
2925 __grp = __mp.grouping();
2926 __sym = __mp.curr_symbol();
2927 __fd = __mp.frac_digits();
2928 }
2929 else
2930 {
2931 const moneypunct<char_type, false>& __mp =
2932 use_facet<moneypunct<char_type, false> >(__loc);
2933 __pat = __mp.neg_format();
2934 __nsn = __mp.negative_sign();
2935 __psn = __mp.positive_sign();
2936 __dp = __mp.decimal_point();
2937 __ts = __mp.thousands_sep();
2938 __grp = __mp.grouping();
2939 __sym = __mp.curr_symbol();
2940 __fd = __mp.frac_digits();
2941 }
2942}
2943
2944extern template class __money_get<char>;
2945extern template class __money_get<wchar_t>;
2946
2947template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00002948class _LIBCPP_VISIBLE money_get
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002949 : public locale::facet,
2950 private __money_get<_CharT>
2951{
2952public:
2953 typedef _CharT char_type;
2954 typedef _InputIterator iter_type;
2955 typedef basic_string<char_type> string_type;
2956
2957 _LIBCPP_ALWAYS_INLINE
2958 explicit money_get(size_t __refs = 0)
2959 : locale::facet(__refs) {}
2960
2961 _LIBCPP_ALWAYS_INLINE
2962 iter_type get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob,
2963 ios_base::iostate& __err, long double& __v) const
2964 {
2965 return do_get(__b, __e, __intl, __iob, __err, __v);
2966 }
2967
2968 _LIBCPP_ALWAYS_INLINE
2969 iter_type get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob,
2970 ios_base::iostate& __err, string_type& __v) const
2971 {
2972 return do_get(__b, __e, __intl, __iob, __err, __v);
2973 }
2974
2975 static locale::id id;
2976
2977protected:
2978
Howard Hinnant82894812010-09-22 16:48:34 +00002979 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002980 ~money_get() {}
Howard Hinnant324bb032010-08-22 00:02:43 +00002981
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002982 virtual iter_type do_get(iter_type __b, iter_type __e, bool __intl,
2983 ios_base& __iob, ios_base::iostate& __err,
2984 long double& __v) const;
2985 virtual iter_type do_get(iter_type __b, iter_type __e, bool __intl,
2986 ios_base& __iob, ios_base::iostate& __err,
2987 string_type& __v) const;
2988
2989private:
2990 static bool __do_get(iter_type& __b, iter_type __e,
2991 bool __intl, const locale& __loc,
2992 ios_base::fmtflags __flags, ios_base::iostate& __err,
2993 bool& __neg, const ctype<char_type>& __ct,
2994 unique_ptr<char_type, void(*)(void*)>& __wb,
2995 char_type*& __wn, char_type* __we);
2996};
2997
2998template <class _CharT, class _InputIterator>
2999locale::id
3000money_get<_CharT, _InputIterator>::id;
3001
3002void __do_nothing(void*);
3003
3004template <class _Tp>
3005_LIBCPP_HIDDEN
3006void
3007__double_or_nothing(unique_ptr<_Tp, void(*)(void*)>& __b, _Tp*& __n, _Tp*& __e)
3008{
3009 bool __owns = __b.get_deleter() != __do_nothing;
3010 size_t __cur_cap = (__e-__b.get()) * sizeof(_Tp);
3011 size_t __new_cap = __cur_cap < numeric_limits<size_t>::max() / 2 ?
3012 2 * __cur_cap : numeric_limits<size_t>::max();
3013 size_t __n_off = __n - __b.get();
3014 _Tp* __t = (_Tp*)realloc(__owns ? __b.get() : 0, __new_cap);
3015 if (__t == 0)
3016 __throw_bad_alloc();
3017 if (__owns)
3018 __b.release();
3019 __b = unique_ptr<_Tp, void(*)(void*)>(__t, free);
3020 __new_cap /= sizeof(_Tp);
3021 __n = __b.get() + __n_off;
3022 __e = __b.get() + __new_cap;
3023}
3024
3025// true == success
3026template <class _CharT, class _InputIterator>
3027bool
3028money_get<_CharT, _InputIterator>::__do_get(iter_type& __b, iter_type __e,
3029 bool __intl, const locale& __loc,
3030 ios_base::fmtflags __flags,
3031 ios_base::iostate& __err,
3032 bool& __neg,
3033 const ctype<char_type>& __ct,
3034 unique_ptr<char_type, void(*)(void*)>& __wb,
3035 char_type*& __wn, char_type* __we)
3036{
3037 const unsigned __bz = 100;
3038 unsigned __gbuf[__bz];
3039 unique_ptr<unsigned, void(*)(void*)> __gb(__gbuf, __do_nothing);
3040 unsigned* __gn = __gb.get();
3041 unsigned* __ge = __gn + __bz;
3042 money_base::pattern __pat;
3043 char_type __dp;
3044 char_type __ts;
3045 string __grp;
3046 string_type __sym;
3047 string_type __psn;
3048 string_type __nsn;
3049 int __fd;
3050 __money_get<_CharT>::__gather_info(__intl, __loc, __pat, __dp, __ts, __grp,
3051 __sym, __psn, __nsn, __fd);
3052 const string_type* __trailing_sign = 0;
3053 __wn = __wb.get();
3054 for (unsigned __p = 0; __p < 4 && __b != __e; ++__p)
3055 {
3056 switch (__pat.field[__p])
3057 {
3058 case money_base::space:
3059 if (__p != 3)
3060 {
3061 if (__ct.is(ctype_base::space, *__b))
3062 ++__b;
3063 else
3064 {
3065 __err |= ios_base::failbit;
3066 return false;
3067 }
3068 }
Howard Hinnant324bb032010-08-22 00:02:43 +00003069 // drop through
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003070 case money_base::none:
3071 if (__p != 3)
3072 {
3073 while (__b != __e && __ct.is(ctype_base::space, *__b))
3074 ++__b;
3075 }
3076 break;
3077 case money_base::sign:
3078 if (__psn.size() + __nsn.size() > 0)
3079 {
3080 if (__psn.size() == 0 || __nsn.size() == 0)
3081 { // sign is optional
3082 if (__psn.size() > 0)
3083 { // __nsn.size() == 0
3084 if (*__b == __psn[0])
3085 {
3086 ++__b;
3087 if (__psn.size() > 1)
3088 __trailing_sign = &__psn;
3089 }
3090 else
3091 __neg = true;
3092 }
3093 else if (*__b == __nsn[0]) // __nsn.size() > 0 && __psn.size() == 0
3094 {
3095 ++__b;
3096 __neg = true;
3097 if (__nsn.size() > 1)
3098 __trailing_sign = &__nsn;
3099 }
3100 }
3101 else // sign is required
3102 {
3103 if (*__b == __psn[0])
3104 {
3105 ++__b;
3106 if (__psn.size() > 1)
3107 __trailing_sign = &__psn;
3108 }
3109 else if (*__b == __nsn[0])
3110 {
3111 ++__b;
3112 __neg = true;
3113 if (__nsn.size() > 1)
3114 __trailing_sign = &__nsn;
3115 }
3116 else
3117 {
3118 __err |= ios_base::failbit;
3119 return false;
3120 }
3121 }
3122 }
3123 break;
3124 case money_base::symbol:
3125 {
3126 bool __more_needed = __trailing_sign ||
3127 (__p < 2) ||
3128 (__p == 2 && __pat.field[3] != static_cast<char>(money_base::none));
3129 bool __sb = __flags & ios_base::showbase;
3130 if (__sb || __more_needed)
3131 {
3132 ios_base::iostate __et = ios_base::goodbit;
3133 string_type* __k = __scan_keyword(__b, __e, &__sym, &__sym+1,
3134 __ct, __et);
3135 if (__sb && __k != &__sym)
3136 {
3137 __err |= ios_base::failbit;
3138 return false;
3139 }
3140 }
3141 }
3142 break;
3143 case money_base::value:
3144 {
3145 unsigned __ng = 0;
3146 for (; __b != __e; ++__b)
3147 {
3148 char_type __c = *__b;
3149 if (__ct.is(ctype_base::digit, __c))
3150 {
3151 if (__wn == __we)
3152 __double_or_nothing(__wb, __wn, __we);
3153 *__wn++ = __c;
3154 ++__ng;
3155 }
3156 else if (__grp.size() > 0 && __ng > 0 && __c == __ts)
3157 {
3158 if (__gn == __ge)
3159 __double_or_nothing(__gb, __gn, __ge);
3160 *__gn++ = __ng;
3161 __ng = 0;
3162 }
3163 else
3164 break;
3165 }
3166 if (__gb.get() != __gn && __ng > 0)
3167 {
3168 if (__gn == __ge)
3169 __double_or_nothing(__gb, __gn, __ge);
3170 *__gn++ = __ng;
3171 }
3172 if (__fd > 0)
3173 {
3174 if (__b == __e || *__b != __dp)
3175 {
3176 __err |= ios_base::failbit;
3177 return false;
3178 }
3179 for (++__b; __fd > 0; --__fd, ++__b)
3180 {
3181 if (__b == __e || !__ct.is(ctype_base::digit, *__b))
3182 {
3183 __err |= ios_base::failbit;
3184 return false;
3185 }
3186 if (__wn == __we)
3187 __double_or_nothing(__wb, __wn, __we);
3188 *__wn++ = *__b;
3189 }
3190 }
3191 if (__wn == __wb.get())
3192 {
3193 __err |= ios_base::failbit;
3194 return false;
3195 }
3196 }
3197 break;
3198 }
3199 }
3200 if (__trailing_sign)
3201 {
3202 for (unsigned __i = 1; __i < __trailing_sign->size(); ++__i, ++__b)
3203 {
3204 if (__b == __e || *__b != (*__trailing_sign)[__i])
3205 {
3206 __err |= ios_base::failbit;
3207 return false;
3208 }
3209 }
3210 }
3211 if (__gb.get() != __gn)
3212 {
3213 ios_base::iostate __et = ios_base::goodbit;
3214 __check_grouping(__grp, __gb.get(), __gn, __et);
3215 if (__et)
3216 {
3217 __err |= ios_base::failbit;
3218 return false;
3219 }
3220 }
3221 return true;
3222}
3223
3224template <class _CharT, class _InputIterator>
3225_InputIterator
3226money_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
3227 bool __intl, ios_base& __iob,
3228 ios_base::iostate& __err,
3229 long double& __v) const
3230{
3231 const unsigned __bz = 100;
3232 char_type __wbuf[__bz];
3233 unique_ptr<char_type, void(*)(void*)> __wb(__wbuf, __do_nothing);
3234 char_type* __wn;
3235 char_type* __we = __wbuf + __bz;
3236 locale __loc = __iob.getloc();
3237 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3238 bool __neg = false;
3239 if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct,
3240 __wb, __wn, __we))
3241 {
3242 const char __src[] = "0123456789";
3243 char_type __atoms[sizeof(__src)-1];
3244 __ct.widen(__src, __src + (sizeof(__src)-1), __atoms);
3245 char __nbuf[__bz];
3246 char* __nc = __nbuf;
3247 unique_ptr<char, void(*)(void*)> __h(0, free);
3248 if (__wn - __wb.get() > __bz-2)
3249 {
3250 __h.reset((char*)malloc(__wn - __wb.get() + 2));
3251 if (__h.get() == 0)
3252 __throw_bad_alloc();
3253 __nc = __h.get();
3254 }
3255 if (__neg)
3256 *__nc++ = '-';
3257 for (const char_type* __w = __wb.get(); __w < __wn; ++__w, ++__nc)
3258 *__nc = __src[find(__atoms, __atoms+sizeof(__atoms), *__w) - __atoms];
3259 *__nc = char();
3260 if (sscanf(__nbuf, "%Lf", &__v) != 1)
3261 __throw_runtime_error("money_get error");
3262 }
3263 if (__b == __e)
3264 __err |= ios_base::eofbit;
3265 return __b;
3266}
3267
3268template <class _CharT, class _InputIterator>
3269_InputIterator
3270money_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
3271 bool __intl, ios_base& __iob,
3272 ios_base::iostate& __err,
3273 string_type& __v) const
3274{
3275 const unsigned __bz = 100;
3276 char_type __wbuf[__bz];
3277 unique_ptr<char_type, void(*)(void*)> __wb(__wbuf, __do_nothing);
3278 char_type* __wn;
3279 char_type* __we = __wbuf + __bz;
3280 locale __loc = __iob.getloc();
3281 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3282 bool __neg = false;
3283 if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct,
3284 __wb, __wn, __we))
3285 {
3286 __v.clear();
3287 if (__neg)
3288 __v.push_back(__ct.widen('-'));
3289 char_type __z = __ct.widen('0');
3290 char_type* __w;
3291 for (__w = __wb.get(); __w < __wn-1; ++__w)
3292 if (*__w != __z)
3293 break;
3294 __v.append(__w, __wn);
3295 }
3296 if (__b == __e)
3297 __err |= ios_base::eofbit;
3298 return __b;
3299}
3300
3301extern template class money_get<char>;
3302extern template class money_get<wchar_t>;
3303
3304// money_put
3305
3306template <class _CharT>
3307class __money_put
3308{
3309protected:
3310 typedef _CharT char_type;
3311 typedef basic_string<char_type> string_type;
3312
3313 _LIBCPP_ALWAYS_INLINE __money_put() {}
3314
3315 static void __gather_info(bool __intl, bool __neg, const locale& __loc,
3316 money_base::pattern& __pat, char_type& __dp,
3317 char_type& __ts, string& __grp,
3318 string_type& __sym, string_type& __sn,
3319 int& __fd);
3320 static void __format(char_type* __mb, char_type*& __mi, char_type*& __me,
3321 ios_base::fmtflags __flags,
3322 const char_type* __db, const char_type* __de,
3323 const ctype<char_type>& __ct, bool __neg,
3324 const money_base::pattern& __pat, char_type __dp,
3325 char_type __ts, const string& __grp,
3326 const string_type& __sym, const string_type& __sn,
3327 int __fd);
3328};
3329
3330template <class _CharT>
3331void
3332__money_put<_CharT>::__gather_info(bool __intl, bool __neg, const locale& __loc,
3333 money_base::pattern& __pat, char_type& __dp,
3334 char_type& __ts, string& __grp,
3335 string_type& __sym, string_type& __sn,
3336 int& __fd)
3337{
3338 if (__intl)
3339 {
3340 const moneypunct<char_type, true>& __mp =
3341 use_facet<moneypunct<char_type, true> >(__loc);
3342 if (__neg)
3343 {
3344 __pat = __mp.neg_format();
3345 __sn = __mp.negative_sign();
3346 }
3347 else
3348 {
3349 __pat = __mp.pos_format();
3350 __sn = __mp.positive_sign();
3351 }
3352 __dp = __mp.decimal_point();
3353 __ts = __mp.thousands_sep();
3354 __grp = __mp.grouping();
3355 __sym = __mp.curr_symbol();
3356 __fd = __mp.frac_digits();
3357 }
3358 else
3359 {
3360 const moneypunct<char_type, false>& __mp =
3361 use_facet<moneypunct<char_type, false> >(__loc);
3362 if (__neg)
3363 {
3364 __pat = __mp.neg_format();
3365 __sn = __mp.negative_sign();
3366 }
3367 else
3368 {
3369 __pat = __mp.pos_format();
3370 __sn = __mp.positive_sign();
3371 }
3372 __dp = __mp.decimal_point();
3373 __ts = __mp.thousands_sep();
3374 __grp = __mp.grouping();
3375 __sym = __mp.curr_symbol();
3376 __fd = __mp.frac_digits();
3377 }
3378}
3379
3380template <class _CharT>
3381void
3382__money_put<_CharT>::__format(char_type* __mb, char_type*& __mi, char_type*& __me,
3383 ios_base::fmtflags __flags,
3384 const char_type* __db, const char_type* __de,
3385 const ctype<char_type>& __ct, bool __neg,
3386 const money_base::pattern& __pat, char_type __dp,
3387 char_type __ts, const string& __grp,
3388 const string_type& __sym, const string_type& __sn,
3389 int __fd)
3390{
3391 __me = __mb;
3392 for (unsigned __p = 0; __p < 4; ++__p)
3393 {
3394 switch (__pat.field[__p])
3395 {
3396 case money_base::none:
3397 __mi = __me;
3398 break;
3399 case money_base::space:
3400 __mi = __me;
3401 *__me++ = __ct.widen(' ');
3402 break;
3403 case money_base::sign:
3404 if (!__sn.empty())
3405 *__me++ = __sn[0];
3406 break;
3407 case money_base::symbol:
3408 if (!__sym.empty() && (__flags & ios_base::showbase))
Howard Hinnant0949eed2011-06-30 21:18:19 +00003409 __me = _VSTD::copy(__sym.begin(), __sym.end(), __me);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003410 break;
3411 case money_base::value:
3412 {
3413 // remember start of value so we can reverse it
3414 char_type* __t = __me;
3415 // find beginning of digits
3416 if (__neg)
3417 ++__db;
3418 // find end of digits
3419 const char_type* __d;
3420 for (__d = __db; __d < __de; ++__d)
3421 if (!__ct.is(ctype_base::digit, *__d))
3422 break;
3423 // print fractional part
3424 if (__fd > 0)
3425 {
3426 int __f;
3427 for (__f = __fd; __d > __db && __f > 0; --__f)
3428 *__me++ = *--__d;
3429 char_type __z = __f > 0 ? __ct.widen('0') : char_type();
3430 for (; __f > 0; --__f)
3431 *__me++ = __z;
3432 *__me++ = __dp;
3433 }
3434 // print units part
3435 if (__d == __db)
3436 {
3437 *__me++ = __ct.widen('0');
3438 }
3439 else
3440 {
3441 unsigned __ng = 0;
3442 unsigned __ig = 0;
3443 unsigned __gl = __grp.empty() ? numeric_limits<unsigned>::max()
3444 : static_cast<unsigned>(__grp[__ig]);
3445 while (__d != __db)
3446 {
3447 if (__ng == __gl)
3448 {
3449 *__me++ = __ts;
3450 __ng = 0;
3451 if (++__ig < __grp.size())
3452 __gl = __grp[__ig] == numeric_limits<char>::max() ?
3453 numeric_limits<unsigned>::max() :
3454 static_cast<unsigned>(__grp[__ig]);
3455 }
3456 *__me++ = *--__d;
3457 ++__ng;
3458 }
3459 }
3460 // reverse it
3461 reverse(__t, __me);
3462 }
3463 break;
3464 }
3465 }
3466 // print rest of sign, if any
3467 if (__sn.size() > 1)
Howard Hinnant0949eed2011-06-30 21:18:19 +00003468 __me = _VSTD::copy(__sn.begin()+1, __sn.end(), __me);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003469 // set alignment
3470 if ((__flags & ios_base::adjustfield) == ios_base::left)
3471 __mi = __me;
3472 else if ((__flags & ios_base::adjustfield) != ios_base::internal)
3473 __mi = __mb;
3474}
3475
3476extern template class __money_put<char>;
3477extern template class __money_put<wchar_t>;
3478
3479template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00003480class _LIBCPP_VISIBLE money_put
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003481 : public locale::facet,
3482 private __money_put<_CharT>
3483{
3484public:
3485 typedef _CharT char_type;
3486 typedef _OutputIterator iter_type;
3487 typedef basic_string<char_type> string_type;
3488
3489 _LIBCPP_ALWAYS_INLINE
3490 explicit money_put(size_t __refs = 0)
3491 : locale::facet(__refs) {}
3492
3493 _LIBCPP_ALWAYS_INLINE
3494 iter_type put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl,
3495 long double __units) const
3496 {
3497 return do_put(__s, __intl, __iob, __fl, __units);
3498 }
3499
3500 _LIBCPP_ALWAYS_INLINE
3501 iter_type put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl,
3502 const string_type& __digits) const
3503 {
3504 return do_put(__s, __intl, __iob, __fl, __digits);
3505 }
3506
3507 static locale::id id;
3508
3509protected:
Howard Hinnant82894812010-09-22 16:48:34 +00003510 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003511 ~money_put() {}
3512
3513 virtual iter_type do_put(iter_type __s, bool __intl, ios_base& __iob,
3514 char_type __fl, long double __units) const;
3515 virtual iter_type do_put(iter_type __s, bool __intl, ios_base& __iob,
3516 char_type __fl, const string_type& __digits) const;
3517};
3518
3519template <class _CharT, class _OutputIterator>
3520locale::id
3521money_put<_CharT, _OutputIterator>::id;
3522
3523template <class _CharT, class _OutputIterator>
3524_OutputIterator
3525money_put<_CharT, _OutputIterator>::do_put(iter_type __s, bool __intl,
3526 ios_base& __iob, char_type __fl,
3527 long double __units) const
3528{
3529 // convert to char
3530 const size_t __bs = 100;
3531 char __buf[__bs];
3532 char* __bb = __buf;
3533 char_type __digits[__bs];
3534 char_type* __db = __digits;
3535 size_t __n = snprintf(__bb, __bs, "%.0Lf", __units);
3536 unique_ptr<char, void(*)(void*)> __hn(0, free);
3537 unique_ptr<char_type, void(*)(void*)> __hd(0, free);
3538 // secure memory for digit storage
3539 if (__n > __bs-1)
3540 {
Howard Hinnant866569b2011-09-28 23:39:33 +00003541#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00003542 __n = asprintf_l(&__bb, _LIBCPP_GET_C_LOCALE, "%.0Lf", __units);
Sean Huntf3907e62011-07-15 05:40:33 +00003543#else
3544 __n = __asprintf_l(&__bb, __cloc(), "%.0Lf", __units);
3545#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003546 if (__bb == 0)
3547 __throw_bad_alloc();
3548 __hn.reset(__bb);
3549 __hd.reset((char_type*)malloc(__n * sizeof(char_type)));
3550 if (__hd == 0)
3551 __throw_bad_alloc();
3552 __db = __hd.get();
3553 }
3554 // gather info
3555 locale __loc = __iob.getloc();
3556 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3557 __ct.widen(__bb, __bb + __n, __db);
3558 bool __neg = __n > 0 && __bb[0] == '-';
3559 money_base::pattern __pat;
3560 char_type __dp;
3561 char_type __ts;
3562 string __grp;
3563 string_type __sym;
3564 string_type __sn;
3565 int __fd;
3566 this->__gather_info(__intl, __neg, __loc, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3567 // secure memory for formatting
3568 char_type __mbuf[__bs];
3569 char_type* __mb = __mbuf;
3570 unique_ptr<char_type, void(*)(void*)> __hw(0, free);
3571 size_t __exn = static_cast<int>(__n) > __fd ?
3572 (__n - __fd) * 2 + __sn.size() + __sym.size() + __fd + 1
3573 : __sn.size() + __sym.size() + __fd + 2;
3574 if (__exn > __bs)
3575 {
3576 __hw.reset((char_type*)malloc(__exn * sizeof(char_type)));
3577 __mb = __hw.get();
3578 if (__mb == 0)
3579 __throw_bad_alloc();
3580 }
3581 // format
3582 char_type* __mi;
3583 char_type* __me;
3584 this->__format(__mb, __mi, __me, __iob.flags(),
3585 __db, __db + __n, __ct,
3586 __neg, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3587 return __pad_and_output(__s, __mb, __mi, __me, __iob, __fl);
3588}
3589
3590template <class _CharT, class _OutputIterator>
3591_OutputIterator
3592money_put<_CharT, _OutputIterator>::do_put(iter_type __s, bool __intl,
3593 ios_base& __iob, char_type __fl,
3594 const string_type& __digits) const
3595{
3596 // gather info
3597 locale __loc = __iob.getloc();
3598 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3599 bool __neg = __digits.size() > 0 && __digits[0] == __ct.widen('-');
3600 money_base::pattern __pat;
3601 char_type __dp;
3602 char_type __ts;
3603 string __grp;
3604 string_type __sym;
3605 string_type __sn;
3606 int __fd;
3607 this->__gather_info(__intl, __neg, __loc, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3608 // secure memory for formatting
3609 char_type __mbuf[100];
3610 char_type* __mb = __mbuf;
3611 unique_ptr<char_type, void(*)(void*)> __h(0, free);
3612 size_t __exn = __digits.size() > __fd ?
3613 (__digits.size() - __fd) * 2 + __sn.size() + __sym.size() + __fd + 1
3614 : __sn.size() + __sym.size() + __fd + 2;
3615 if (__exn > 100)
3616 {
3617 __h.reset((char_type*)malloc(__exn * sizeof(char_type)));
3618 __mb = __h.get();
3619 if (__mb == 0)
3620 __throw_bad_alloc();
3621 }
3622 // format
3623 char_type* __mi;
3624 char_type* __me;
3625 this->__format(__mb, __mi, __me, __iob.flags(),
3626 __digits.data(), __digits.data() + __digits.size(), __ct,
3627 __neg, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3628 return __pad_and_output(__s, __mb, __mi, __me, __iob, __fl);
3629}
3630
3631extern template class money_put<char>;
3632extern template class money_put<wchar_t>;
3633
3634// messages
3635
Howard Hinnant82894812010-09-22 16:48:34 +00003636class _LIBCPP_VISIBLE messages_base
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003637{
3638public:
Howard Hinnantb2080c72011-02-25 00:51:08 +00003639 typedef ptrdiff_t catalog;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003640
3641 _LIBCPP_ALWAYS_INLINE messages_base() {}
3642};
3643
3644template <class _CharT>
Howard Hinnant82894812010-09-22 16:48:34 +00003645class _LIBCPP_VISIBLE messages
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003646 : public locale::facet,
3647 public messages_base
3648{
3649public:
3650 typedef _CharT char_type;
3651 typedef basic_string<_CharT> string_type;
3652
3653 _LIBCPP_ALWAYS_INLINE
3654 explicit messages(size_t __refs = 0)
3655 : locale::facet(__refs) {}
3656
3657 _LIBCPP_ALWAYS_INLINE
3658 catalog open(const basic_string<char>& __nm, const locale& __loc) const
3659 {
3660 return do_open(__nm, __loc);
3661 }
3662
3663 _LIBCPP_ALWAYS_INLINE
3664 string_type get(catalog __c, int __set, int __msgid,
3665 const string_type& __dflt) const
3666 {
3667 return do_get(__c, __set, __msgid, __dflt);
3668 }
3669
3670 _LIBCPP_ALWAYS_INLINE
3671 void close(catalog __c) const
3672 {
3673 do_close(__c);
3674 }
3675
3676 static locale::id id;
3677
3678protected:
Howard Hinnant82894812010-09-22 16:48:34 +00003679 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003680 ~messages() {}
3681
3682 virtual catalog do_open(const basic_string<char>&, const locale&) const;
3683 virtual string_type do_get(catalog, int __set, int __msgid,
3684 const string_type& __dflt) const;
3685 virtual void do_close(catalog) const;
3686};
3687
3688template <class _CharT>
3689locale::id
3690messages<_CharT>::id;
3691
3692template <class _CharT>
3693typename messages<_CharT>::catalog
3694messages<_CharT>::do_open(const basic_string<char>& __nm, const locale&) const
3695{
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00003696#if _WIN32
3697 return -1;
3698#else // _WIN32
Howard Hinnantb2080c72011-02-25 00:51:08 +00003699 catalog __cat = reinterpret_cast<catalog>(catopen(__nm.c_str(), NL_CAT_LOCALE));
3700 if (__cat != -1)
3701 __cat = static_cast<catalog>((static_cast<size_t>(__cat) >> 1));
3702 return __cat;
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00003703#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003704}
3705
3706template <class _CharT>
3707typename messages<_CharT>::string_type
3708messages<_CharT>::do_get(catalog __c, int __set, int __msgid,
3709 const string_type& __dflt) const
3710{
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00003711#if _WIN32
3712 return __dflt;
3713#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003714 string __ndflt;
3715 __narrow_to_utf8<sizeof(char_type)*__CHAR_BIT__>()(back_inserter(__ndflt),
3716 __dflt.c_str(),
3717 __dflt.c_str() + __dflt.size());
Howard Hinnantb2080c72011-02-25 00:51:08 +00003718 if (__c != -1)
3719 __c <<= 1;
3720 nl_catd __cat = reinterpret_cast<nl_catd>(__c);
3721 char* __n = catgets(__cat, __set, __msgid, __ndflt.c_str());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003722 string_type __w;
3723 __widen_from_utf8<sizeof(char_type)*__CHAR_BIT__>()(back_inserter(__w),
3724 __n, __n + strlen(__n));
3725 return __w;
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00003726#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003727}
3728
3729template <class _CharT>
3730void
3731messages<_CharT>::do_close(catalog __c) const
3732{
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00003733#if !_WIN32
Howard Hinnantb2080c72011-02-25 00:51:08 +00003734 if (__c != -1)
3735 __c <<= 1;
3736 nl_catd __cat = reinterpret_cast<nl_catd>(__c);
3737 catclose(__cat);
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00003738#endif // !_WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003739}
3740
3741extern template class messages<char>;
3742extern template class messages<wchar_t>;
3743
3744template <class _CharT>
Howard Hinnant82894812010-09-22 16:48:34 +00003745class _LIBCPP_VISIBLE messages_byname
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003746 : public messages<_CharT>
3747{
3748public:
3749 typedef messages_base::catalog catalog;
3750 typedef basic_string<_CharT> string_type;
3751
3752 _LIBCPP_ALWAYS_INLINE
3753 explicit messages_byname(const char*, size_t __refs = 0)
3754 : messages<_CharT>(__refs) {}
3755
3756 _LIBCPP_ALWAYS_INLINE
3757 explicit messages_byname(const string&, size_t __refs = 0)
3758 : messages<_CharT>(__refs) {}
3759
3760protected:
Howard Hinnant82894812010-09-22 16:48:34 +00003761 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003762 ~messages_byname() {}
3763};
3764
3765extern template class messages_byname<char>;
3766extern template class messages_byname<wchar_t>;
3767
Howard Hinnantd23b4642010-05-31 20:58:54 +00003768template<class _Codecvt, class _Elem = wchar_t,
3769 class _Wide_alloc = allocator<_Elem>,
3770 class _Byte_alloc = allocator<char> >
Howard Hinnant82894812010-09-22 16:48:34 +00003771class _LIBCPP_VISIBLE wstring_convert
Howard Hinnantd23b4642010-05-31 20:58:54 +00003772{
3773public:
3774 typedef basic_string<char, char_traits<char>, _Byte_alloc> byte_string;
3775 typedef basic_string<_Elem, char_traits<_Elem>, _Wide_alloc> wide_string;
3776 typedef typename _Codecvt::state_type state_type;
3777 typedef typename wide_string::traits_type::int_type int_type;
3778
3779private:
3780 byte_string __byte_err_string_;
3781 wide_string __wide_err_string_;
3782 _Codecvt* __cvtptr_;
3783 state_type __cvtstate_;
3784 size_t __cvtcount_;
3785
3786 wstring_convert(const wstring_convert& __wc);
3787 wstring_convert& operator=(const wstring_convert& __wc);
3788public:
3789 wstring_convert(_Codecvt* __pcvt = new _Codecvt);
3790 wstring_convert(_Codecvt* __pcvt, state_type __state);
3791 wstring_convert(const byte_string& __byte_err,
3792 const wide_string& __wide_err = wide_string());
Howard Hinnant73d21a42010-09-04 23:28:19 +00003793#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantd23b4642010-05-31 20:58:54 +00003794 wstring_convert(wstring_convert&& __wc);
3795#endif
3796 ~wstring_convert();
3797
Howard Hinnant82894812010-09-22 16:48:34 +00003798 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003799 wide_string from_bytes(char __byte)
3800 {return from_bytes(&__byte, &__byte+1);}
Howard Hinnant82894812010-09-22 16:48:34 +00003801 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003802 wide_string from_bytes(const char* __ptr)
3803 {return from_bytes(__ptr, __ptr + char_traits<char>::length(__ptr));}
Howard Hinnant82894812010-09-22 16:48:34 +00003804 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003805 wide_string from_bytes(const byte_string& __str)
3806 {return from_bytes(__str.data(), __str.data() + __str.size());}
3807 wide_string from_bytes(const char* __first, const char* __last);
3808
Howard Hinnant82894812010-09-22 16:48:34 +00003809 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003810 byte_string to_bytes(_Elem __wchar)
3811 {return to_bytes(&__wchar, &__wchar+1);}
Howard Hinnant82894812010-09-22 16:48:34 +00003812 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003813 byte_string to_bytes(const _Elem* __wptr)
3814 {return to_bytes(__wptr, __wptr + char_traits<_Elem>::length(__wptr));}
Howard Hinnant82894812010-09-22 16:48:34 +00003815 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003816 byte_string to_bytes(const wide_string& __wstr)
3817 {return to_bytes(__wstr.data(), __wstr.data() + __wstr.size());}
3818 byte_string to_bytes(const _Elem* __first, const _Elem* __last);
3819
Howard Hinnant82894812010-09-22 16:48:34 +00003820 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003821 size_t converted() const {return __cvtcount_;}
Howard Hinnant82894812010-09-22 16:48:34 +00003822 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003823 state_type state() const {return __cvtstate_;}
3824};
3825
3826template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Howard Hinnant82894812010-09-22 16:48:34 +00003827inline _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003828wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3829 wstring_convert(_Codecvt* __pcvt)
3830 : __cvtptr_(__pcvt), __cvtstate_(), __cvtcount_(0)
3831{
3832}
3833
3834template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Howard Hinnant82894812010-09-22 16:48:34 +00003835inline _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003836wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3837 wstring_convert(_Codecvt* __pcvt, state_type __state)
3838 : __cvtptr_(__pcvt), __cvtstate_(__state), __cvtcount_(0)
3839{
3840}
3841
3842template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3843wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3844 wstring_convert(const byte_string& __byte_err, const wide_string& __wide_err)
3845 : __byte_err_string_(__byte_err), __wide_err_string_(__wide_err),
3846 __cvtstate_(), __cvtcount_(0)
3847{
3848 __cvtptr_ = new _Codecvt;
3849}
3850
Howard Hinnant73d21a42010-09-04 23:28:19 +00003851#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantd23b4642010-05-31 20:58:54 +00003852
3853template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Howard Hinnant82894812010-09-22 16:48:34 +00003854inline _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003855wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3856 wstring_convert(wstring_convert&& __wc)
Howard Hinnant0949eed2011-06-30 21:18:19 +00003857 : __byte_err_string_(_VSTD::move(__wc.__byte_err_string_)),
3858 __wide_err_string_(_VSTD::move(__wc.__wide_err_string_)),
Howard Hinnantd23b4642010-05-31 20:58:54 +00003859 __cvtptr_(__wc.__cvtptr_),
3860 __cvtstate_(__wc.__cvtstate_), __cvtcount_(__wc.__cvtstate_)
3861{
3862 __wc.__cvtptr_ = nullptr;
3863}
3864
Howard Hinnantbfd55302010-09-04 23:46:48 +00003865#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantd23b4642010-05-31 20:58:54 +00003866
3867template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3868wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::~wstring_convert()
3869{
3870 delete __cvtptr_;
3871}
3872
3873template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3874typename wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::wide_string
3875wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3876 from_bytes(const char* __frm, const char* __frm_end)
3877{
3878 __cvtcount_ = 0;
3879 if (__cvtptr_ != nullptr)
3880 {
3881 wide_string __ws(2*(__frm_end - __frm), _Elem());
3882 __ws.resize(__ws.capacity());
3883 codecvt_base::result __r = codecvt_base::ok;
3884 state_type __st = __cvtstate_;
3885 if (__frm != __frm_end)
3886 {
3887 _Elem* __to = &__ws[0];
3888 _Elem* __to_end = __to + __ws.size();
3889 const char* __frm_nxt;
3890 do
3891 {
3892 _Elem* __to_nxt;
3893 __r = __cvtptr_->in(__st, __frm, __frm_end, __frm_nxt,
3894 __to, __to_end, __to_nxt);
3895 __cvtcount_ += __frm_nxt - __frm;
3896 if (__frm_nxt == __frm)
3897 {
3898 __r = codecvt_base::error;
3899 }
3900 else if (__r == codecvt_base::noconv)
3901 {
3902 __ws.resize(__to - &__ws[0]);
3903 // This only gets executed if _Elem is char
3904 __ws.append((const _Elem*)__frm, (const _Elem*)__frm_end);
3905 __frm = __frm_nxt;
3906 __r = codecvt_base::ok;
3907 }
3908 else if (__r == codecvt_base::ok)
3909 {
3910 __ws.resize(__to_nxt - &__ws[0]);
3911 __frm = __frm_nxt;
3912 }
3913 else if (__r == codecvt_base::partial)
3914 {
3915 ptrdiff_t __s = __to_nxt - &__ws[0];
3916 __ws.resize(2 * __s);
3917 __to = &__ws[0] + __s;
3918 __to_end = &__ws[0] + __ws.size();
3919 __frm = __frm_nxt;
3920 }
3921 } while (__r == codecvt_base::partial && __frm_nxt < __frm_end);
3922 }
3923 if (__r == codecvt_base::ok)
3924 return __ws;
3925 }
Howard Hinnantd4444702010-08-11 17:04:31 +00003926#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00003927 if (__wide_err_string_.empty())
3928 throw range_error("wstring_convert: from_bytes error");
Howard Hinnant324bb032010-08-22 00:02:43 +00003929#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00003930 return __wide_err_string_;
3931}
3932
3933template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3934typename wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::byte_string
3935wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3936 to_bytes(const _Elem* __frm, const _Elem* __frm_end)
3937{
3938 __cvtcount_ = 0;
3939 if (__cvtptr_ != nullptr)
3940 {
3941 byte_string __bs(2*(__frm_end - __frm), char());
3942 __bs.resize(__bs.capacity());
3943 codecvt_base::result __r = codecvt_base::ok;
3944 state_type __st = __cvtstate_;
3945 if (__frm != __frm_end)
3946 {
3947 char* __to = &__bs[0];
3948 char* __to_end = __to + __bs.size();
3949 const _Elem* __frm_nxt;
3950 do
3951 {
3952 char* __to_nxt;
3953 __r = __cvtptr_->out(__st, __frm, __frm_end, __frm_nxt,
3954 __to, __to_end, __to_nxt);
3955 __cvtcount_ += __frm_nxt - __frm;
3956 if (__frm_nxt == __frm)
3957 {
3958 __r = codecvt_base::error;
3959 }
3960 else if (__r == codecvt_base::noconv)
3961 {
3962 __bs.resize(__to - &__bs[0]);
3963 // This only gets executed if _Elem is char
3964 __bs.append((const char*)__frm, (const char*)__frm_end);
3965 __frm = __frm_nxt;
3966 __r = codecvt_base::ok;
3967 }
3968 else if (__r == codecvt_base::ok)
3969 {
3970 __bs.resize(__to_nxt - &__bs[0]);
3971 __frm = __frm_nxt;
3972 }
3973 else if (__r == codecvt_base::partial)
3974 {
3975 ptrdiff_t __s = __to_nxt - &__bs[0];
3976 __bs.resize(2 * __s);
3977 __to = &__bs[0] + __s;
3978 __to_end = &__bs[0] + __bs.size();
3979 __frm = __frm_nxt;
3980 }
3981 } while (__r == codecvt_base::partial && __frm_nxt < __frm_end);
3982 }
3983 if (__r == codecvt_base::ok)
3984 {
3985 size_t __s = __bs.size();
3986 __bs.resize(__bs.capacity());
3987 char* __to = &__bs[0] + __s;
3988 char* __to_end = __to + __bs.size();
3989 do
3990 {
3991 char* __to_nxt;
3992 __r = __cvtptr_->unshift(__st, __to, __to_end, __to_nxt);
3993 if (__r == codecvt_base::noconv)
3994 {
3995 __bs.resize(__to - &__bs[0]);
3996 __r = codecvt_base::ok;
3997 }
3998 else if (__r == codecvt_base::ok)
3999 {
4000 __bs.resize(__to_nxt - &__bs[0]);
4001 }
4002 else if (__r == codecvt_base::partial)
4003 {
4004 ptrdiff_t __s = __to_nxt - &__bs[0];
4005 __bs.resize(2 * __s);
4006 __to = &__bs[0] + __s;
4007 __to_end = &__bs[0] + __bs.size();
4008 }
4009 } while (__r == codecvt_base::partial);
4010 if (__r == codecvt_base::ok)
4011 return __bs;
4012 }
4013 }
Howard Hinnantd4444702010-08-11 17:04:31 +00004014#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00004015 if (__byte_err_string_.empty())
4016 throw range_error("wstring_convert: to_bytes error");
Howard Hinnant324bb032010-08-22 00:02:43 +00004017#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00004018 return __byte_err_string_;
4019}
4020
4021template <class _Codecvt, class _Elem = wchar_t, class _Tr = char_traits<_Elem> >
Howard Hinnant82894812010-09-22 16:48:34 +00004022class _LIBCPP_VISIBLE wbuffer_convert
Howard Hinnantd23b4642010-05-31 20:58:54 +00004023 : public basic_streambuf<_Elem, _Tr>
4024{
4025public:
4026 // types:
4027 typedef _Elem char_type;
4028 typedef _Tr traits_type;
4029 typedef typename traits_type::int_type int_type;
4030 typedef typename traits_type::pos_type pos_type;
4031 typedef typename traits_type::off_type off_type;
4032 typedef typename _Codecvt::state_type state_type;
4033
4034private:
Howard Hinnant4b53f502010-06-01 20:09:18 +00004035 char* __extbuf_;
4036 const char* __extbufnext_;
4037 const char* __extbufend_;
4038 char __extbuf_min_[8];
4039 size_t __ebs_;
4040 char_type* __intbuf_;
4041 size_t __ibs_;
Howard Hinnantd23b4642010-05-31 20:58:54 +00004042 streambuf* __bufptr_;
Howard Hinnant4b53f502010-06-01 20:09:18 +00004043 _Codecvt* __cv_;
4044 state_type __st_;
4045 ios_base::openmode __cm_;
4046 bool __owns_eb_;
4047 bool __owns_ib_;
4048 bool __always_noconv_;
Howard Hinnantd23b4642010-05-31 20:58:54 +00004049
Howard Hinnant4b53f502010-06-01 20:09:18 +00004050 wbuffer_convert(const wbuffer_convert&);
4051 wbuffer_convert& operator=(const wbuffer_convert&);
Howard Hinnantd23b4642010-05-31 20:58:54 +00004052public:
4053 wbuffer_convert(streambuf* __bytebuf = 0, _Codecvt* __pcvt = new _Codecvt,
Howard Hinnant4b53f502010-06-01 20:09:18 +00004054 state_type __state = state_type());
4055 ~wbuffer_convert();
Howard Hinnantd23b4642010-05-31 20:58:54 +00004056
Howard Hinnant82894812010-09-22 16:48:34 +00004057 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantd23b4642010-05-31 20:58:54 +00004058 streambuf* rdbuf() const {return __bufptr_;}
Howard Hinnant82894812010-09-22 16:48:34 +00004059 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantd23b4642010-05-31 20:58:54 +00004060 streambuf* rdbuf(streambuf* __bytebuf)
4061 {
4062 streambuf* __r = __bufptr_;
4063 __bufptr_ = __bytebuf;
4064 return __r;
4065 }
4066
Howard Hinnant82894812010-09-22 16:48:34 +00004067 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant4b53f502010-06-01 20:09:18 +00004068 state_type state() const {return __st_;}
Howard Hinnantd23b4642010-05-31 20:58:54 +00004069
4070protected:
Howard Hinnant4b53f502010-06-01 20:09:18 +00004071 virtual int_type underflow();
4072 virtual int_type pbackfail(int_type __c = traits_type::eof());
Howard Hinnantd23b4642010-05-31 20:58:54 +00004073 virtual int_type overflow (int_type __c = traits_type::eof());
Howard Hinnant4b53f502010-06-01 20:09:18 +00004074 virtual basic_streambuf<char_type, traits_type>* setbuf(char_type* __s,
4075 streamsize __n);
4076 virtual pos_type seekoff(off_type __off, ios_base::seekdir __way,
4077 ios_base::openmode __wch = ios_base::in | ios_base::out);
4078 virtual pos_type seekpos(pos_type __sp,
4079 ios_base::openmode __wch = ios_base::in | ios_base::out);
4080 virtual int sync();
4081
4082private:
4083 bool __read_mode();
4084 void __write_mode();
4085 wbuffer_convert* __close();
Howard Hinnantd23b4642010-05-31 20:58:54 +00004086};
4087
4088template <class _Codecvt, class _Elem, class _Tr>
Howard Hinnant4b53f502010-06-01 20:09:18 +00004089wbuffer_convert<_Codecvt, _Elem, _Tr>::
4090 wbuffer_convert(streambuf* __bytebuf, _Codecvt* __pcvt, state_type __state)
4091 : __extbuf_(0),
4092 __extbufnext_(0),
4093 __extbufend_(0),
4094 __ebs_(0),
4095 __intbuf_(0),
4096 __ibs_(0),
4097 __bufptr_(__bytebuf),
4098 __cv_(__pcvt),
4099 __st_(__state),
4100 __cm_(0),
4101 __owns_eb_(false),
4102 __owns_ib_(false),
4103 __always_noconv_(__cv_ ? __cv_->always_noconv() : false)
4104{
4105 setbuf(0, 4096);
4106}
4107
4108template <class _Codecvt, class _Elem, class _Tr>
4109wbuffer_convert<_Codecvt, _Elem, _Tr>::~wbuffer_convert()
4110{
4111 __close();
4112 delete __cv_;
4113 if (__owns_eb_)
4114 delete [] __extbuf_;
4115 if (__owns_ib_)
4116 delete [] __intbuf_;
4117}
4118
4119template <class _Codecvt, class _Elem, class _Tr>
4120typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
4121wbuffer_convert<_Codecvt, _Elem, _Tr>::underflow()
4122{
4123 if (__cv_ == 0 || __bufptr_ == 0)
4124 return traits_type::eof();
4125 bool __initial = __read_mode();
4126 char_type __1buf;
4127 if (this->gptr() == 0)
4128 this->setg(&__1buf, &__1buf+1, &__1buf+1);
4129 const size_t __unget_sz = __initial ? 0 : min<size_t>((this->egptr() - this->eback()) / 2, 4);
4130 int_type __c = traits_type::eof();
4131 if (this->gptr() == this->egptr())
4132 {
4133 memmove(this->eback(), this->egptr() - __unget_sz, __unget_sz * sizeof(char_type));
4134 if (__always_noconv_)
4135 {
4136 streamsize __nmemb = static_cast<streamsize>(this->egptr() - this->eback() - __unget_sz);
4137 __nmemb = __bufptr_->sgetn((char*)this->eback() + __unget_sz, __nmemb);
4138 if (__nmemb != 0)
4139 {
4140 this->setg(this->eback(),
4141 this->eback() + __unget_sz,
4142 this->eback() + __unget_sz + __nmemb);
4143 __c = *this->gptr();
4144 }
4145 }
4146 else
4147 {
4148 memmove(__extbuf_, __extbufnext_, __extbufend_ - __extbufnext_);
4149 __extbufnext_ = __extbuf_ + (__extbufend_ - __extbufnext_);
4150 __extbufend_ = __extbuf_ + (__extbuf_ == __extbuf_min_ ? sizeof(__extbuf_min_) : __ebs_);
Howard Hinnant0949eed2011-06-30 21:18:19 +00004151 streamsize __nmemb = _VSTD::min(static_cast<streamsize>(this->egptr() - this->eback() - __unget_sz),
Howard Hinnant4b53f502010-06-01 20:09:18 +00004152 static_cast<streamsize>(__extbufend_ - __extbufnext_));
4153 codecvt_base::result __r;
4154 state_type __svs = __st_;
4155 streamsize __nr = __bufptr_->sgetn(const_cast<char*>(__extbufnext_), __nmemb);
4156 if (__nr != 0)
4157 {
4158 __extbufend_ = __extbufnext_ + __nr;
4159 char_type* __inext;
4160 __r = __cv_->in(__st_, __extbuf_, __extbufend_, __extbufnext_,
4161 this->eback() + __unget_sz,
4162 this->egptr(), __inext);
4163 if (__r == codecvt_base::noconv)
4164 {
4165 this->setg((char_type*)__extbuf_, (char_type*)__extbuf_, (char_type*)__extbufend_);
4166 __c = *this->gptr();
4167 }
4168 else if (__inext != this->eback() + __unget_sz)
4169 {
4170 this->setg(this->eback(), this->eback() + __unget_sz, __inext);
4171 __c = *this->gptr();
4172 }
4173 }
4174 }
4175 }
4176 else
4177 __c = *this->gptr();
4178 if (this->eback() == &__1buf)
4179 this->setg(0, 0, 0);
4180 return __c;
4181}
4182
4183template <class _Codecvt, class _Elem, class _Tr>
4184typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
4185wbuffer_convert<_Codecvt, _Elem, _Tr>::pbackfail(int_type __c)
4186{
4187 if (__cv_ != 0 && __bufptr_ != 0 && this->eback() < this->gptr())
4188 {
4189 if (traits_type::eq_int_type(__c, traits_type::eof()))
4190 {
4191 this->gbump(-1);
4192 return traits_type::not_eof(__c);
4193 }
4194 if (traits_type::eq(traits_type::to_char_type(__c), this->gptr()[-1]))
4195 {
4196 this->gbump(-1);
4197 *this->gptr() = traits_type::to_char_type(__c);
4198 return __c;
4199 }
4200 }
4201 return traits_type::eof();
4202}
4203
4204template <class _Codecvt, class _Elem, class _Tr>
Howard Hinnantd23b4642010-05-31 20:58:54 +00004205typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
4206wbuffer_convert<_Codecvt, _Elem, _Tr>::overflow(int_type __c)
4207{
Howard Hinnant4b53f502010-06-01 20:09:18 +00004208 if (__cv_ == 0 || __bufptr_ == 0)
4209 return traits_type::eof();
4210 __write_mode();
4211 char_type __1buf;
4212 char_type* __pb_save = this->pbase();
4213 char_type* __epb_save = this->epptr();
4214 if (!traits_type::eq_int_type(__c, traits_type::eof()))
4215 {
4216 if (this->pptr() == 0)
4217 this->setp(&__1buf, &__1buf+1);
4218 *this->pptr() = traits_type::to_char_type(__c);
4219 this->pbump(1);
4220 }
4221 if (this->pptr() != this->pbase())
4222 {
4223 if (__always_noconv_)
4224 {
4225 streamsize __nmemb = static_cast<streamsize>(this->pptr() - this->pbase());
4226 if (__bufptr_->sputn((const char*)this->pbase(), __nmemb) != __nmemb)
4227 return traits_type::eof();
4228 }
4229 else
4230 {
4231 char* __extbe = __extbuf_;
4232 codecvt_base::result __r;
4233 do
4234 {
4235 const char_type* __e;
4236 __r = __cv_->out(__st_, this->pbase(), this->pptr(), __e,
4237 __extbuf_, __extbuf_ + __ebs_, __extbe);
4238 if (__e == this->pbase())
4239 return traits_type::eof();
4240 if (__r == codecvt_base::noconv)
4241 {
4242 streamsize __nmemb = static_cast<size_t>(this->pptr() - this->pbase());
4243 if (__bufptr_->sputn((const char*)this->pbase(), __nmemb) != __nmemb)
4244 return traits_type::eof();
4245 }
4246 else if (__r == codecvt_base::ok || __r == codecvt_base::partial)
4247 {
4248 streamsize __nmemb = static_cast<size_t>(__extbe - __extbuf_);
4249 if (__bufptr_->sputn(__extbuf_, __nmemb) != __nmemb)
4250 return traits_type::eof();
4251 if (__r == codecvt_base::partial)
4252 {
4253 this->setp((char_type*)__e, this->pptr());
4254 this->pbump(this->epptr() - this->pbase());
4255 }
4256 }
4257 else
4258 return traits_type::eof();
4259 } while (__r == codecvt_base::partial);
4260 }
4261 this->setp(__pb_save, __epb_save);
4262 }
4263 return traits_type::not_eof(__c);
4264}
4265
4266template <class _Codecvt, class _Elem, class _Tr>
4267basic_streambuf<_Elem, _Tr>*
4268wbuffer_convert<_Codecvt, _Elem, _Tr>::setbuf(char_type* __s, streamsize __n)
4269{
4270 this->setg(0, 0, 0);
4271 this->setp(0, 0);
4272 if (__owns_eb_)
4273 delete [] __extbuf_;
4274 if (__owns_ib_)
4275 delete [] __intbuf_;
4276 __ebs_ = __n;
4277 if (__ebs_ > sizeof(__extbuf_min_))
4278 {
4279 if (__always_noconv_ && __s)
4280 {
4281 __extbuf_ = (char*)__s;
4282 __owns_eb_ = false;
4283 }
4284 else
4285 {
4286 __extbuf_ = new char[__ebs_];
4287 __owns_eb_ = true;
4288 }
4289 }
4290 else
4291 {
4292 __extbuf_ = __extbuf_min_;
4293 __ebs_ = sizeof(__extbuf_min_);
4294 __owns_eb_ = false;
4295 }
4296 if (!__always_noconv_)
4297 {
4298 __ibs_ = max<streamsize>(__n, sizeof(__extbuf_min_));
4299 if (__s && __ibs_ >= sizeof(__extbuf_min_))
4300 {
4301 __intbuf_ = __s;
4302 __owns_ib_ = false;
4303 }
4304 else
4305 {
4306 __intbuf_ = new char_type[__ibs_];
4307 __owns_ib_ = true;
4308 }
4309 }
4310 else
4311 {
4312 __ibs_ = 0;
4313 __intbuf_ = 0;
4314 __owns_ib_ = false;
4315 }
4316 return this;
4317}
4318
4319template <class _Codecvt, class _Elem, class _Tr>
4320typename wbuffer_convert<_Codecvt, _Elem, _Tr>::pos_type
4321wbuffer_convert<_Codecvt, _Elem, _Tr>::seekoff(off_type __off, ios_base::seekdir __way,
4322 ios_base::openmode __om)
4323{
4324 int __width = __cv_->encoding();
4325 if (__cv_ == 0 || __bufptr_ == 0 || (__width <= 0 && __off != 0) || sync())
4326 return pos_type(off_type(-1));
4327 // __width > 0 || __off == 0
4328 switch (__way)
4329 {
4330 case ios_base::beg:
4331 break;
4332 case ios_base::cur:
4333 break;
4334 case ios_base::end:
4335 break;
4336 default:
4337 return pos_type(off_type(-1));
4338 }
4339 pos_type __r = __bufptr_->pubseekoff(__width * __off, __way, __om);
4340 __r.state(__st_);
4341 return __r;
4342}
4343
4344template <class _Codecvt, class _Elem, class _Tr>
4345typename wbuffer_convert<_Codecvt, _Elem, _Tr>::pos_type
4346wbuffer_convert<_Codecvt, _Elem, _Tr>::seekpos(pos_type __sp, ios_base::openmode __wch)
4347{
4348 if (__cv_ == 0 || __bufptr_ == 0 || sync())
4349 return pos_type(off_type(-1));
4350 if (__bufptr_->pubseekpos(__sp, __wch) == pos_type(off_type(-1)))
4351 return pos_type(off_type(-1));
4352 return __sp;
4353}
4354
4355template <class _Codecvt, class _Elem, class _Tr>
4356int
4357wbuffer_convert<_Codecvt, _Elem, _Tr>::sync()
4358{
4359 if (__cv_ == 0 || __bufptr_ == 0)
4360 return 0;
4361 if (__cm_ & ios_base::out)
4362 {
4363 if (this->pptr() != this->pbase())
4364 if (overflow() == traits_type::eof())
4365 return -1;
4366 codecvt_base::result __r;
4367 do
4368 {
4369 char* __extbe;
4370 __r = __cv_->unshift(__st_, __extbuf_, __extbuf_ + __ebs_, __extbe);
4371 streamsize __nmemb = static_cast<streamsize>(__extbe - __extbuf_);
4372 if (__bufptr_->sputn(__extbuf_, __nmemb) != __nmemb)
4373 return -1;
4374 } while (__r == codecvt_base::partial);
4375 if (__r == codecvt_base::error)
4376 return -1;
4377 if (__bufptr_->pubsync())
4378 return -1;
4379 }
4380 else if (__cm_ & ios_base::in)
4381 {
4382 off_type __c;
4383 if (__always_noconv_)
4384 __c = this->egptr() - this->gptr();
4385 else
4386 {
4387 int __width = __cv_->encoding();
4388 __c = __extbufend_ - __extbufnext_;
4389 if (__width > 0)
4390 __c += __width * (this->egptr() - this->gptr());
4391 else
4392 {
4393 if (this->gptr() != this->egptr())
4394 {
4395 reverse(this->gptr(), this->egptr());
4396 codecvt_base::result __r;
4397 const char_type* __e = this->gptr();
4398 char* __extbe;
4399 do
4400 {
4401 __r = __cv_->out(__st_, __e, this->egptr(), __e,
4402 __extbuf_, __extbuf_ + __ebs_, __extbe);
4403 switch (__r)
4404 {
4405 case codecvt_base::noconv:
4406 __c += this->egptr() - this->gptr();
4407 break;
4408 case codecvt_base::ok:
4409 case codecvt_base::partial:
4410 __c += __extbe - __extbuf_;
4411 break;
4412 default:
4413 return -1;
4414 }
4415 } while (__r == codecvt_base::partial);
4416 }
4417 }
4418 }
4419 if (__bufptr_->pubseekoff(-__c, ios_base::cur, __cm_) == pos_type(off_type(-1)))
4420 return -1;
4421 this->setg(0, 0, 0);
4422 __cm_ = 0;
4423 }
4424 return 0;
4425}
4426
4427template <class _Codecvt, class _Elem, class _Tr>
4428bool
4429wbuffer_convert<_Codecvt, _Elem, _Tr>::__read_mode()
4430{
4431 if (!(__cm_ & ios_base::in))
4432 {
4433 this->setp(0, 0);
4434 if (__always_noconv_)
4435 this->setg((char_type*)__extbuf_,
4436 (char_type*)__extbuf_ + __ebs_,
4437 (char_type*)__extbuf_ + __ebs_);
4438 else
4439 this->setg(__intbuf_, __intbuf_ + __ibs_, __intbuf_ + __ibs_);
4440 __cm_ = ios_base::in;
4441 return true;
4442 }
4443 return false;
4444}
4445
4446template <class _Codecvt, class _Elem, class _Tr>
4447void
4448wbuffer_convert<_Codecvt, _Elem, _Tr>::__write_mode()
4449{
4450 if (!(__cm_ & ios_base::out))
4451 {
4452 this->setg(0, 0, 0);
4453 if (__ebs_ > sizeof(__extbuf_min_))
4454 {
4455 if (__always_noconv_)
4456 this->setp((char_type*)__extbuf_,
4457 (char_type*)__extbuf_ + (__ebs_ - 1));
4458 else
4459 this->setp(__intbuf_, __intbuf_ + (__ibs_ - 1));
4460 }
4461 else
4462 this->setp(0, 0);
4463 __cm_ = ios_base::out;
4464 }
4465}
4466
4467template <class _Codecvt, class _Elem, class _Tr>
4468wbuffer_convert<_Codecvt, _Elem, _Tr>*
4469wbuffer_convert<_Codecvt, _Elem, _Tr>::__close()
4470{
4471 wbuffer_convert* __rt = 0;
4472 if (__cv_ != 0 && __bufptr_ != 0)
4473 {
4474 __rt = this;
4475 if ((__cm_ & ios_base::out) && sync())
4476 __rt = 0;
4477 }
4478 return __rt;
Howard Hinnantd23b4642010-05-31 20:58:54 +00004479}
4480
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004481_LIBCPP_END_NAMESPACE_STD
4482
4483#endif // _LIBCPP_LOCALE