blob: e9a18e321268e7b33ec05978606944bac0057ad6 [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
190#include <support/win32/support.h> // vasprintf
191#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
Sean Hunte59f7242011-07-09 01:09:31 +0000199#ifndef _LIBCPP_STABLE_APPLE_ABI
Sean Hunt62a6ac32011-07-09 00:56:23 +0000200// Get the C locale object
201locale_t __cloc();
Sean Hunte59f7242011-07-09 01:09:31 +0000202#endif
Sean Hunt62a6ac32011-07-09 00:56:23 +0000203
Sean Huntf3907e62011-07-15 05:40:33 +0000204typedef _VSTD::remove_pointer<locale_t>::type __locale_struct;
205typedef _VSTD::unique_ptr<__locale_struct, decltype(&freelocale)> __locale_unique_ptr;
206typedef _VSTD::unique_ptr<__locale_struct, decltype(&uselocale)> __locale_raii;
207
Howard Hinnantadff4892010-05-24 17:49:41 +0000208// OSX has nice foo_l() functions that let you turn off use of the global
209// locale. Linux, not so much. The following functions avoid the locale when
210// that's possible and otherwise do the wrong thing. FIXME.
Howard Hinnantbcbbd4d2011-07-15 14:46:11 +0000211#ifndef _LIBCPP_STABLE_APPLE_ABI
Sean Huntf3907e62011-07-15 05:40:33 +0000212
213#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
214decltype(MB_CUR_MAX_L(_VSTD::declval<locale_t>()))
Howard Hinnant82894812010-09-22 16:48:34 +0000215inline _LIBCPP_INLINE_VISIBILITY
Sean Huntf3907e62011-07-15 05:40:33 +0000216__mb_cur_max_l(locale_t __l)
Howard Hinnantadff4892010-05-24 17:49:41 +0000217{
Sean Huntf3907e62011-07-15 05:40:33 +0000218 return MB_CUR_MAX_L(__l);
219}
220#else // _LIBCPP_LOCALE__L_EXTENSIONS
221_LIBCPP_ALWAYS_INLINE inline
222decltype(MB_CUR_MAX) __mb_cur_max_l(locale_t __l)
223{
224 __locale_raii __current(uselocale(__l), uselocale);
225 return MB_CUR_MAX;
226}
227#endif // _LIBCPP_LOCALE__L_EXTENSIONS
228
229_LIBCPP_ALWAYS_INLINE inline
230wint_t __btowc_l(int __c, locale_t __l)
231{
232#ifdef _LIBCPP_STABLE_APPLE_ABI
233 return btowc_l(__c, __l);
234#else
235 __locale_raii __current(uselocale(__l), uselocale);
236 return btowc(__c);
237#endif
Sean Huntc97da3a2011-07-13 06:40:50 +0000238}
Howard Hinnant8d756322011-07-13 15:48:16 +0000239
Sean Huntf3907e62011-07-15 05:40:33 +0000240_LIBCPP_ALWAYS_INLINE inline
241int __wctob_l(wint_t __c, locale_t __l)
Sean Huntc97da3a2011-07-13 06:40:50 +0000242{
Sean Huntf3907e62011-07-15 05:40:33 +0000243#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
244 return wctob_l(__c, __l);
245#else
246 __locale_raii __current(uselocale(__l), uselocale);
247 return wctob(__c);
248#endif
Sean Huntc97da3a2011-07-13 06:40:50 +0000249}
Sean Huntf3907e62011-07-15 05:40:33 +0000250
251_LIBCPP_ALWAYS_INLINE inline
252size_t __wcsnrtombs_l(char *__dest, const wchar_t **__src, size_t __nwc,
253 size_t __len, mbstate_t *__ps, locale_t __l)
254{
255#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
256 return wcsnrtombs_l(__dest, __src, __nwc, __len, __ps, __l);
257#else
258 __locale_raii __current(uselocale(__l), uselocale);
259 return wcsnrtombs(__dest, __src, __nwc, __len, __ps);
260#endif
261}
262
263_LIBCPP_ALWAYS_INLINE inline
264size_t __wcrtomb_l(char *__s, wchar_t __wc, mbstate_t *__ps, locale_t __l)
265{
266#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
267 return wcrtomb_l(__s, __wc, __ps, __l);
268#else
269 __locale_raii __current(uselocale(__l), uselocale);
270 return wcrtomb(__s, __wc, __ps);
271#endif
272}
273
274_LIBCPP_ALWAYS_INLINE inline
275size_t __mbsnrtowcs_l(wchar_t * __dest, const char **__src, size_t __nms,
276 size_t __len, mbstate_t *__ps, locale_t __l)
277{
278#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
David Chisnallc512df12011-09-21 08:39:44 +0000279 return mbsnrtowcs_l(__dest, __src, __nms, __len, __ps, __l);
Sean Huntf3907e62011-07-15 05:40:33 +0000280#else
281 __locale_raii __current(uselocale(__l), uselocale);
282 return mbsnrtowcs(__dest, __src, __nms, __len, __ps);
283#endif
284}
285
286_LIBCPP_ALWAYS_INLINE inline
287size_t __mbrtowc_l(wchar_t *__pwc, const char *__s, size_t __n,
288 mbstate_t *__ps, locale_t __l)
289{
290#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
291 return mbrtowc_l(__pwc, __s, __n, __ps, __l);
292#else
293 __locale_raii __current(uselocale(__l), uselocale);
294 return mbrtowc(__pwc, __s, __n, __ps);
295#endif
296}
297
298_LIBCPP_ALWAYS_INLINE inline
299int __mbtowc_l(wchar_t *__pwc, const char *__pmb, size_t __max, locale_t __l)
300{
301#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
David Chisnallc512df12011-09-21 08:39:44 +0000302 return mbtowc_l(__pwc, __pmb, __max, __l);
Sean Huntf3907e62011-07-15 05:40:33 +0000303#else
304 __locale_raii __current(uselocale(__l), uselocale);
305 return mbtowc(__pwc, __pmb, __max);
306#endif
307}
308
309_LIBCPP_ALWAYS_INLINE inline
310size_t __mbrlen_l(const char *__s, size_t __n, mbstate_t *__ps, locale_t __l)
311{
312#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
313 return mbrlen_l(__s, __n, __ps, __l);
314#else
315 __locale_raii __current(uselocale(__l), uselocale);
316 return mbrlen(__s, __n, __ps);
317#endif
318}
319
320_LIBCPP_ALWAYS_INLINE inline
321lconv *__localeconv_l(locale_t __l)
322{
323#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
324 return localeconv_l(__l);
325#else
326 __locale_raii __current(uselocale(__l), uselocale);
327 return localeconv();
328#endif
329}
330
331_LIBCPP_ALWAYS_INLINE inline
332size_t __mbsrtowcs_l(wchar_t *__dest, const char **__src, size_t __len,
333 mbstate_t *__ps, locale_t __l)
334{
335#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
336 return mbsrtowcs_l(__dest, __src, __len, __ps, __l);
337#else
338 __locale_raii __current(uselocale(__l), uselocale);
339 return mbsrtowcs(__dest, __src, __len, __ps);
340#endif
341}
342
343_LIBCPP_ALWAYS_INLINE inline
344int __sprintf_l(char *__s, locale_t __l, const char *__format, ...) {
345 va_list __va;
346 va_start(__va, __format);
347#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
348 int __res = vsprintf_l(__s, __l, __format, __va);
349#else
350 __locale_raii __current(uselocale(__l), uselocale);
351 int __res = vsprintf(__s, __format, __va);
352#endif
353 va_end(__va);
354 return __res;
355}
356
357_LIBCPP_ALWAYS_INLINE inline
358int __snprintf_l(char *__s, size_t __n, locale_t __l, const char *__format, ...) {
359 va_list __va;
360 va_start(__va, __format);
361#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
362 int __res = vsnprintf_l(__s, __n, __l, __format, __va);
363#else
364 __locale_raii __current(uselocale(__l), uselocale);
365 int __res = vsnprintf(__s, __n, __format, __va);
366#endif
367 va_end(__va);
368 return __res;
369}
370
371_LIBCPP_ALWAYS_INLINE inline
372int __asprintf_l(char **__s, locale_t __l, const char *__format, ...) {
373 va_list __va;
374 va_start(__va, __format);
375#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
376 int __res = vasprintf_l(__s, __l, __format, __va);
377#else
378 __locale_raii __current(uselocale(__l), uselocale);
379 int __res = vasprintf(__s, __format, __va);
380#endif
381 va_end(__va);
382 return __res;
383}
384
385_LIBCPP_ALWAYS_INLINE inline
386int __sscanf_l(const char *__s, locale_t __l, const char *__format, ...) {
387 va_list __va;
388 va_start(__va, __format);
389#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
390 int __res = vsscanf_l(__s, __l, __format, __va);
391#else
392 __locale_raii __current(uselocale(__l), uselocale);
393 int __res = vsscanf(__s, __format, __va);
394#endif
395 va_end(__va);
396 return __res;
397}
398
399#endif // _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantadff4892010-05-24 17:49:41 +0000400
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000401// __scan_keyword
402// Scans [__b, __e) until a match is found in the basic_strings range
403// [__kb, __ke) or until it can be shown that there is no match in [__kb, __ke).
404// __b will be incremented (visibly), consuming CharT until a match is found
405// or proved to not exist. A keyword may be "", in which will match anything.
406// If one keyword is a prefix of another, and the next CharT in the input
407// might match another keyword, the algorithm will attempt to find the longest
408// matching keyword. If the longer matching keyword ends up not matching, then
409// no keyword match is found. If no keyword match is found, __ke is returned
410// and failbit is set in __err.
411// Else an iterator pointing to the matching keyword is found. If more than
412// one keyword matches, an iterator to the first matching keyword is returned.
413// If on exit __b == __e, eofbit is set in __err. If __case_senstive is false,
414// __ct is used to force to lower case before comparing characters.
415// Examples:
416// Keywords: "a", "abb"
417// If the input is "a", the first keyword matches and eofbit is set.
418// If the input is "abc", no match is found and "ab" are consumed.
419template <class _InputIterator, class _ForwardIterator, class _Ctype>
420_LIBCPP_HIDDEN
421_ForwardIterator
422__scan_keyword(_InputIterator& __b, _InputIterator __e,
423 _ForwardIterator __kb, _ForwardIterator __ke,
424 const _Ctype& __ct, ios_base::iostate& __err,
425 bool __case_sensitive = true)
426{
427 typedef typename iterator_traits<_InputIterator>::value_type _CharT;
Howard Hinnant0949eed2011-06-30 21:18:19 +0000428 size_t __nkw = _VSTD::distance(__kb, __ke);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000429 const unsigned char __doesnt_match = '\0';
430 const unsigned char __might_match = '\1';
431 const unsigned char __does_match = '\2';
432 unsigned char __statbuf[100];
433 unsigned char* __status = __statbuf;
434 unique_ptr<unsigned char, void(*)(void*)> __stat_hold(0, free);
435 if (__nkw > sizeof(__statbuf))
436 {
437 __status = (unsigned char*)malloc(__nkw);
438 if (__status == 0)
439 __throw_bad_alloc();
440 __stat_hold.reset(__status);
441 }
442 size_t __n_might_match = __nkw; // At this point, any keyword might match
443 size_t __n_does_match = 0; // but none of them definitely do
444 // Initialize all statuses to __might_match, except for "" keywords are __does_match
445 unsigned char* __st = __status;
446 for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, ++__st)
447 {
448 if (!__ky->empty())
449 *__st = __might_match;
450 else
451 {
452 *__st = __does_match;
453 --__n_might_match;
454 ++__n_does_match;
455 }
456 }
457 // While there might be a match, test keywords against the next CharT
458 for (size_t __indx = 0; __b != __e && __n_might_match > 0; ++__indx)
459 {
460 // Peek at the next CharT but don't consume it
461 _CharT __c = *__b;
462 if (!__case_sensitive)
463 __c = __ct.toupper(__c);
464 bool __consume = false;
465 // For each keyword which might match, see if the __indx character is __c
466 // If a match if found, consume __c
467 // If a match is found, and that is the last character in the keyword,
468 // then that keyword matches.
469 // If the keyword doesn't match this character, then change the keyword
470 // to doesn't match
471 __st = __status;
472 for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, ++__st)
473 {
474 if (*__st == __might_match)
475 {
476 _CharT __kc = (*__ky)[__indx];
477 if (!__case_sensitive)
478 __kc = __ct.toupper(__kc);
479 if (__c == __kc)
480 {
481 __consume = true;
482 if (__ky->size() == __indx+1)
483 {
484 *__st = __does_match;
485 --__n_might_match;
486 ++__n_does_match;
487 }
488 }
489 else
490 {
491 *__st = __doesnt_match;
492 --__n_might_match;
493 }
494 }
495 }
496 // consume if we matched a character
497 if (__consume)
498 {
499 ++__b;
500 // If we consumed a character and there might be a matched keyword that
501 // was marked matched on a previous iteration, then such keywords
502 // which are now marked as not matching.
503 if (__n_might_match + __n_does_match > 1)
504 {
505 __st = __status;
506 for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, ++__st)
507 {
508 if (*__st == __does_match && __ky->size() != __indx+1)
509 {
510 *__st = __doesnt_match;
511 --__n_does_match;
512 }
513 }
514 }
515 }
516 }
517 // We've exited the loop because we hit eof and/or we have no more "might matches".
518 if (__b == __e)
519 __err |= ios_base::eofbit;
520 // Return the first matching result
521 for (__st = __status; __kb != __ke; ++__kb, ++__st)
522 if (*__st == __does_match)
523 break;
524 if (__kb == __ke)
525 __err |= ios_base::failbit;
526 return __kb;
527}
528
529struct __num_get_base
530{
531 static const int __num_get_buf_sz = 40;
532
533 static int __get_base(ios_base&);
534 static const char __src[33];
535};
536
537void __check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
538 ios_base::iostate& __err);
539
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000540template <class _CharT>
541struct __num_get
542 : protected __num_get_base
543{
544 static string __stage2_int_prep(ios_base& __iob, _CharT* __atoms, _CharT& __thousands_sep);
545 static string __stage2_float_prep(ios_base& __iob, _CharT* __atoms, _CharT& __decimal_point,
546 _CharT& __thousands_sep);
547 static int __stage2_int_loop(_CharT __ct, int __base, char* __a, char*& __a_end,
548 unsigned& __dc, _CharT __thousands_sep, const string& __grouping,
549 unsigned* __g, unsigned*& __g_end, _CharT* __atoms);
550 static int __stage2_float_loop(_CharT __ct, bool& __in_units, char& __exp,
551 char* __a, char*& __a_end,
552 _CharT __decimal_point, _CharT __thousands_sep,
553 const string& __grouping, unsigned* __g,
554 unsigned*& __g_end, unsigned& __dc, _CharT* __atoms);
555};
556
557template <class _CharT>
558string
559__num_get<_CharT>::__stage2_int_prep(ios_base& __iob, _CharT* __atoms, _CharT& __thousands_sep)
560{
561 locale __loc = __iob.getloc();
562 use_facet<ctype<_CharT> >(__loc).widen(__src, __src + 26, __atoms);
563 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
564 __thousands_sep = __np.thousands_sep();
565 return __np.grouping();
566}
567
568template <class _CharT>
569string
570__num_get<_CharT>::__stage2_float_prep(ios_base& __iob, _CharT* __atoms, _CharT& __decimal_point,
571 _CharT& __thousands_sep)
572{
573 locale __loc = __iob.getloc();
574 use_facet<ctype<_CharT> >(__loc).widen(__src, __src + 32, __atoms);
575 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
576 __decimal_point = __np.decimal_point();
577 __thousands_sep = __np.thousands_sep();
578 return __np.grouping();
579}
580
581template <class _CharT>
582int
583__num_get<_CharT>::__stage2_int_loop(_CharT __ct, int __base, char* __a, char*& __a_end,
584 unsigned& __dc, _CharT __thousands_sep, const string& __grouping,
585 unsigned* __g, unsigned*& __g_end, _CharT* __atoms)
586{
Howard Hinnant80586722011-03-09 01:03:19 +0000587 if (__a_end == __a && (__ct == __atoms[24] || __ct == __atoms[25]))
588 {
589 *__a_end++ = __ct == __atoms[24] ? '+' : '-';
590 __dc = 0;
591 return 0;
592 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000593 if (__ct == __thousands_sep && __grouping.size() != 0)
594 {
595 if (__g_end-__g < __num_get_buf_sz)
596 {
597 *__g_end++ = __dc;
598 __dc = 0;
599 }
600 return 0;
601 }
602 ptrdiff_t __f = find(__atoms, __atoms + 26, __ct) - __atoms;
Howard Hinnant80586722011-03-09 01:03:19 +0000603 if (__f >= 24)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000604 return -1;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000605 switch (__base)
606 {
607 case 8:
608 case 10:
609 if (__f >= __base)
Howard Hinnant80586722011-03-09 01:03:19 +0000610 return -1;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000611 break;
Howard Hinnant80586722011-03-09 01:03:19 +0000612 case 16:
613 if (__f < 22)
614 break;
615 if (__a_end != __a && __a_end - __a <= 2 && __a_end[-1] == '0')
616 {
617 __dc = 0;
618 *__a_end++ = __src[__f];
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000619 return 0;
Howard Hinnant80586722011-03-09 01:03:19 +0000620 }
621 return -1;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000622 }
Howard Hinnant80586722011-03-09 01:03:19 +0000623 if (__a_end-__a < __num_get_buf_sz - 1)
624 *__a_end++ = __src[__f];
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000625 ++__dc;
626 return 0;
627}
628
629template <class _CharT>
630int
631__num_get<_CharT>::__stage2_float_loop(_CharT __ct, bool& __in_units, char& __exp, char* __a, char*& __a_end,
632 _CharT __decimal_point, _CharT __thousands_sep, const string& __grouping,
633 unsigned* __g, unsigned*& __g_end, unsigned& __dc, _CharT* __atoms)
634{
635 if (__ct == __decimal_point)
636 {
637 if (!__in_units)
638 return -1;
639 __in_units = false;
640 *__a_end++ = '.';
641 if (__grouping.size() != 0 && __g_end-__g < __num_get_buf_sz)
642 *__g_end++ = __dc;
643 return 0;
644 }
645 if (__ct == __thousands_sep && __grouping.size() != 0)
646 {
647 if (!__in_units)
648 return -1;
649 if (__g_end-__g < __num_get_buf_sz)
650 {
651 *__g_end++ = __dc;
652 __dc = 0;
653 }
654 return 0;
655 }
656 ptrdiff_t __f = find(__atoms, __atoms + 32, __ct) - __atoms;
657 if (__f >= 32)
658 return -1;
659 char __x = __src[__f];
660 if (__a_end-__a < __num_get_buf_sz - 1)
661 *__a_end++ = __x;
662 if (__x == 'x' || __x == 'X')
663 __exp = 'P';
664 else if ((__x & 0xDF) == __exp)
665 {
666 __in_units = false;
667 if (__grouping.size() != 0 && __g_end-__g < __num_get_buf_sz)
668 *__g_end++ = __dc;
669 }
670 if (__f >= 22)
671 return 0;
672 ++__dc;
673 return 0;
674}
675
676extern template class __num_get<char>;
677extern template class __num_get<wchar_t>;
678
679template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +0000680class _LIBCPP_VISIBLE num_get
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000681 : public locale::facet,
682 private __num_get<_CharT>
683{
684public:
685 typedef _CharT char_type;
686 typedef _InputIterator iter_type;
687
688 _LIBCPP_ALWAYS_INLINE
689 explicit num_get(size_t __refs = 0)
690 : locale::facet(__refs) {}
691
692 _LIBCPP_ALWAYS_INLINE
693 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
694 ios_base::iostate& __err, bool& __v) const
695 {
696 return do_get(__b, __e, __iob, __err, __v);
697 }
698
699 _LIBCPP_ALWAYS_INLINE
700 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
701 ios_base::iostate& __err, long& __v) const
702 {
703 return do_get(__b, __e, __iob, __err, __v);
704 }
705
706 _LIBCPP_ALWAYS_INLINE
707 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
708 ios_base::iostate& __err, long long& __v) const
709 {
710 return do_get(__b, __e, __iob, __err, __v);
711 }
712
713 _LIBCPP_ALWAYS_INLINE
714 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
715 ios_base::iostate& __err, unsigned short& __v) const
716 {
717 return do_get(__b, __e, __iob, __err, __v);
718 }
719
720 _LIBCPP_ALWAYS_INLINE
721 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
722 ios_base::iostate& __err, unsigned int& __v) const
723 {
724 return do_get(__b, __e, __iob, __err, __v);
725 }
726
727 _LIBCPP_ALWAYS_INLINE
728 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
729 ios_base::iostate& __err, unsigned long& __v) const
730 {
731 return do_get(__b, __e, __iob, __err, __v);
732 }
733
734 _LIBCPP_ALWAYS_INLINE
735 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
736 ios_base::iostate& __err, unsigned long long& __v) const
737 {
738 return do_get(__b, __e, __iob, __err, __v);
739 }
740
741 _LIBCPP_ALWAYS_INLINE
742 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
743 ios_base::iostate& __err, float& __v) const
744 {
745 return do_get(__b, __e, __iob, __err, __v);
746 }
747
748 _LIBCPP_ALWAYS_INLINE
749 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
750 ios_base::iostate& __err, double& __v) const
751 {
752 return do_get(__b, __e, __iob, __err, __v);
753 }
754
755 _LIBCPP_ALWAYS_INLINE
756 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
757 ios_base::iostate& __err, long double& __v) const
758 {
759 return do_get(__b, __e, __iob, __err, __v);
760 }
761
762 _LIBCPP_ALWAYS_INLINE
763 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
764 ios_base::iostate& __err, void*& __v) const
765 {
766 return do_get(__b, __e, __iob, __err, __v);
767 }
768
769 static locale::id id;
770
771protected:
Howard Hinnant82894812010-09-22 16:48:34 +0000772 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000773 ~num_get() {}
774
775 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
776 ios_base::iostate& __err, bool& __v) const;
777 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
778 ios_base::iostate& __err, long& __v) const;
779 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
780 ios_base::iostate& __err, long long& __v) const;
781 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
782 ios_base::iostate& __err, unsigned short& __v) const;
783 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
784 ios_base::iostate& __err, unsigned int& __v) const;
785 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
786 ios_base::iostate& __err, unsigned long& __v) const;
787 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
788 ios_base::iostate& __err, unsigned long long& __v) const;
789 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
790 ios_base::iostate& __err, float& __v) const;
791 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
792 ios_base::iostate& __err, double& __v) const;
793 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
794 ios_base::iostate& __err, long double& __v) const;
795 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
796 ios_base::iostate& __err, void*& __v) const;
797};
798
799template <class _CharT, class _InputIterator>
800locale::id
801num_get<_CharT, _InputIterator>::id;
802
803template <class _Tp>
804_Tp
805__num_get_signed_integral(const char* __a, const char* __a_end,
806 ios_base::iostate& __err, int __base)
807{
808 if (__a != __a_end)
809 {
Howard Hinnante7c8da62011-02-25 19:52:41 +0000810 int __save_errno = errno;
811 errno = 0;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000812 char *__p2;
Howard Hinnant9a207812011-07-15 14:25:40 +0000813#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000814 long long __ll = strtoll_l(__a, &__p2, __base, 0);
Sean Huntf3907e62011-07-15 05:40:33 +0000815#else
816 long long __ll = strtoll_l(__a, &__p2, __base, __cloc());
817#endif
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 Hinnant9a207812011-07-15 14:25:40 +0000857#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000858 unsigned long long __ll = strtoull_l(__a, &__p2, __base, 0);
Sean Huntf3907e62011-07-15 05:40:33 +0000859#else
860 unsigned long long __ll = strtoull_l(__a, &__p2, __base, __cloc());
861#endif
Howard Hinnante7c8da62011-02-25 19:52:41 +0000862 int __current_errno = errno;
863 if (__current_errno == 0)
864 errno = __save_errno;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000865 if (__p2 != __a_end)
866 {
867 __err = ios_base::failbit;
868 return 0;
869 }
Howard Hinnante7c8da62011-02-25 19:52:41 +0000870 else if (__current_errno == ERANGE ||
871 numeric_limits<_Tp>::max() < __ll)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000872 {
873 __err = ios_base::failbit;
874 return numeric_limits<_Tp>::max();
875 }
876 return static_cast<_Tp>(__ll);
877 }
878 __err = ios_base::failbit;
879 return 0;
880}
881
882template <class _Tp>
883_Tp
884__num_get_float(const char* __a, const char* __a_end, ios_base::iostate& __err)
885{
886 if (__a != __a_end)
887 {
888 char *__p2;
Howard Hinnant9a207812011-07-15 14:25:40 +0000889#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000890 long double __ld = strtold_l(__a, &__p2, 0);
Sean Huntf3907e62011-07-15 05:40:33 +0000891#else
892 long double __ld = strtold_l(__a, &__p2, __cloc());
893#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000894 if (__p2 != __a_end)
895 {
896 __err = ios_base::failbit;
897 return 0;
898 }
899 return static_cast<_Tp>(__ld);
900 }
901 __err = ios_base::failbit;
902 return 0;
903}
904
905template <class _CharT, class _InputIterator>
906_InputIterator
907num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
908 ios_base& __iob,
909 ios_base::iostate& __err,
910 bool& __v) const
911{
912 if ((__iob.flags() & ios_base::boolalpha) == 0)
913 {
914 long __lv = -1;
915 __b = do_get(__b, __e, __iob, __err, __lv);
916 switch (__lv)
917 {
918 case 0:
919 __v = false;
920 break;
921 case 1:
922 __v = true;
923 break;
924 default:
925 __v = true;
926 __err = ios_base::failbit;
927 break;
928 }
929 return __b;
930 }
931 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__iob.getloc());
932 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__iob.getloc());
933 typedef typename numpunct<_CharT>::string_type string_type;
934 const string_type __names[2] = {__np.truename(), __np.falsename()};
935 const string_type* __i = __scan_keyword(__b, __e, __names, __names+2,
936 __ct, __err);
937 __v = __i == __names;
938 return __b;
939}
940
941template <class _CharT, class _InputIterator>
942_InputIterator
943num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
944 ios_base& __iob,
945 ios_base::iostate& __err,
946 long& __v) const
947{
948 // Stage 1
949 int __base = this->__get_base(__iob);
950 // Stage 2
951 char_type __atoms[26];
952 char_type __thousands_sep;
953 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
954 char __a[__num_get_base::__num_get_buf_sz] = {0};
955 char* __a_end = __a;
956 unsigned __g[__num_get_base::__num_get_buf_sz];
957 unsigned* __g_end = __g;
958 unsigned __dc = 0;
959 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +0000960 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000961 __thousands_sep, __grouping, __g, __g_end,
962 __atoms))
963 break;
964 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
965 *__g_end++ = __dc;
966 // Stage 3
967 __v = __num_get_signed_integral<long>(__a, __a_end, __err, __base);
968 // Digit grouping checked
969 __check_grouping(__grouping, __g, __g_end, __err);
970 // EOF checked
971 if (__b == __e)
972 __err |= ios_base::eofbit;
973 return __b;
974}
975
976template <class _CharT, class _InputIterator>
977_InputIterator
978num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
979 ios_base& __iob,
980 ios_base::iostate& __err,
981 long long& __v) const
982{
983 // Stage 1
984 int __base = this->__get_base(__iob);
985 // Stage 2
986 char_type __atoms[26];
987 char_type __thousands_sep;
988 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
989 char __a[__num_get_base::__num_get_buf_sz] = {0};
990 char* __a_end = __a;
991 unsigned __g[__num_get_base::__num_get_buf_sz];
992 unsigned* __g_end = __g;
993 unsigned __dc = 0;
994 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +0000995 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
996 __thousands_sep, __grouping, __g, __g_end,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000997 __atoms))
998 break;
999 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
1000 *__g_end++ = __dc;
1001 // Stage 3
1002 __v = __num_get_signed_integral<long long>(__a, __a_end, __err, __base);
1003 // Digit grouping checked
1004 __check_grouping(__grouping, __g, __g_end, __err);
1005 // EOF checked
1006 if (__b == __e)
1007 __err |= ios_base::eofbit;
1008 return __b;
1009}
1010
1011template <class _CharT, class _InputIterator>
1012_InputIterator
1013num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1014 ios_base& __iob,
1015 ios_base::iostate& __err,
1016 unsigned short& __v) const
1017{
1018 // Stage 1
1019 int __base = this->__get_base(__iob);
1020 // Stage 2
1021 char_type __atoms[26];
1022 char_type __thousands_sep;
1023 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
1024 char __a[__num_get_base::__num_get_buf_sz] = {0};
1025 char* __a_end = __a;
1026 unsigned __g[__num_get_base::__num_get_buf_sz];
1027 unsigned* __g_end = __g;
1028 unsigned __dc = 0;
1029 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001030 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001031 __thousands_sep, __grouping, __g, __g_end,
1032 __atoms))
1033 break;
1034 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
1035 *__g_end++ = __dc;
1036 // Stage 3
1037 __v = __num_get_unsigned_integral<unsigned short>(__a, __a_end, __err, __base);
1038 // Digit grouping checked
1039 __check_grouping(__grouping, __g, __g_end, __err);
1040 // EOF checked
1041 if (__b == __e)
1042 __err |= ios_base::eofbit;
1043 return __b;
1044}
1045
1046template <class _CharT, class _InputIterator>
1047_InputIterator
1048num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1049 ios_base& __iob,
1050 ios_base::iostate& __err,
1051 unsigned int& __v) const
1052{
1053 // Stage 1
1054 int __base = this->__get_base(__iob);
1055 // Stage 2
1056 char_type __atoms[26];
1057 char_type __thousands_sep;
1058 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
1059 char __a[__num_get_base::__num_get_buf_sz] = {0};
1060 char* __a_end = __a;
1061 unsigned __g[__num_get_base::__num_get_buf_sz];
1062 unsigned* __g_end = __g;
1063 unsigned __dc = 0;
1064 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001065 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001066 __thousands_sep, __grouping, __g, __g_end,
1067 __atoms))
1068 break;
1069 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
1070 *__g_end++ = __dc;
1071 // Stage 3
1072 __v = __num_get_unsigned_integral<unsigned int>(__a, __a_end, __err, __base);
1073 // Digit grouping checked
1074 __check_grouping(__grouping, __g, __g_end, __err);
1075 // EOF checked
1076 if (__b == __e)
1077 __err |= ios_base::eofbit;
1078 return __b;
1079}
1080
1081template <class _CharT, class _InputIterator>
1082_InputIterator
1083num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1084 ios_base& __iob,
1085 ios_base::iostate& __err,
1086 unsigned long& __v) const
1087{
1088 // Stage 1
1089 int __base = this->__get_base(__iob);
1090 // Stage 2
1091 char_type __atoms[26];
1092 char_type __thousands_sep;
1093 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
1094 char __a[__num_get_base::__num_get_buf_sz] = {0};
1095 char* __a_end = __a;
1096 unsigned __g[__num_get_base::__num_get_buf_sz];
1097 unsigned* __g_end = __g;
1098 unsigned __dc = 0;
1099 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001100 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001101 __thousands_sep, __grouping, __g, __g_end,
1102 __atoms))
1103 break;
1104 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
1105 *__g_end++ = __dc;
1106 // Stage 3
1107 __v = __num_get_unsigned_integral<unsigned long>(__a, __a_end, __err, __base);
1108 // Digit grouping checked
1109 __check_grouping(__grouping, __g, __g_end, __err);
1110 // EOF checked
1111 if (__b == __e)
1112 __err |= ios_base::eofbit;
1113 return __b;
1114}
1115
1116template <class _CharT, class _InputIterator>
1117_InputIterator
1118num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1119 ios_base& __iob,
1120 ios_base::iostate& __err,
1121 unsigned long long& __v) const
1122{
1123 // Stage 1
1124 int __base = this->__get_base(__iob);
1125 // Stage 2
1126 char_type __atoms[26];
1127 char_type __thousands_sep;
1128 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
1129 char __a[__num_get_base::__num_get_buf_sz] = {0};
1130 char* __a_end = __a;
1131 unsigned __g[__num_get_base::__num_get_buf_sz];
1132 unsigned* __g_end = __g;
1133 unsigned __dc = 0;
1134 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001135 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001136 __thousands_sep, __grouping, __g, __g_end,
1137 __atoms))
1138 break;
1139 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
1140 *__g_end++ = __dc;
1141 // Stage 3
1142 __v = __num_get_unsigned_integral<unsigned long long>(__a, __a_end, __err, __base);
1143 // Digit grouping checked
1144 __check_grouping(__grouping, __g, __g_end, __err);
1145 // EOF checked
1146 if (__b == __e)
1147 __err |= ios_base::eofbit;
1148 return __b;
1149}
1150
1151template <class _CharT, class _InputIterator>
1152_InputIterator
1153num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1154 ios_base& __iob,
1155 ios_base::iostate& __err,
1156 float& __v) const
1157{
1158 // Stage 1, nothing to do
1159 // Stage 2
1160 char_type __atoms[32];
1161 char_type __decimal_point;
1162 char_type __thousands_sep;
Howard Hinnant324bb032010-08-22 00:02:43 +00001163 string __grouping = this->__stage2_float_prep(__iob, __atoms,
1164 __decimal_point,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001165 __thousands_sep);
1166 char __a[__num_get_base::__num_get_buf_sz] = {0};
1167 char* __a_end = __a;
1168 unsigned __g[__num_get_base::__num_get_buf_sz];
1169 unsigned* __g_end = __g;
1170 unsigned __dc = 0;
1171 bool __in_units = true;
1172 char __exp = 'E';
1173 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001174 if (this->__stage2_float_loop(*__b, __in_units, __exp, __a, __a_end,
1175 __decimal_point, __thousands_sep,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001176 __grouping, __g, __g_end,
1177 __dc, __atoms))
1178 break;
1179 if (__grouping.size() != 0 && __in_units && __g_end-__g < __num_get_base::__num_get_buf_sz)
1180 *__g_end++ = __dc;
1181 // Stage 3
1182 __v = __num_get_float<float>(__a, __a_end, __err);
1183 // Digit grouping checked
1184 __check_grouping(__grouping, __g, __g_end, __err);
1185 // EOF checked
1186 if (__b == __e)
1187 __err |= ios_base::eofbit;
1188 return __b;
1189}
1190
1191template <class _CharT, class _InputIterator>
1192_InputIterator
1193num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1194 ios_base& __iob,
1195 ios_base::iostate& __err,
1196 double& __v) const
1197{
1198 // Stage 1, nothing to do
1199 // Stage 2
1200 char_type __atoms[32];
1201 char_type __decimal_point;
1202 char_type __thousands_sep;
Howard Hinnant324bb032010-08-22 00:02:43 +00001203 string __grouping = this->__stage2_float_prep(__iob, __atoms,
1204 __decimal_point,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001205 __thousands_sep);
1206 char __a[__num_get_base::__num_get_buf_sz] = {0};
1207 char* __a_end = __a;
1208 unsigned __g[__num_get_base::__num_get_buf_sz];
1209 unsigned* __g_end = __g;
1210 unsigned __dc = 0;
1211 bool __in_units = true;
1212 char __exp = 'E';
1213 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001214 if (this->__stage2_float_loop(*__b, __in_units, __exp, __a, __a_end,
1215 __decimal_point, __thousands_sep,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001216 __grouping, __g, __g_end,
1217 __dc, __atoms))
1218 break;
1219 if (__grouping.size() != 0 && __in_units && __g_end-__g < __num_get_base::__num_get_buf_sz)
1220 *__g_end++ = __dc;
1221 // Stage 3
1222 __v = __num_get_float<double>(__a, __a_end, __err);
1223 // Digit grouping checked
1224 __check_grouping(__grouping, __g, __g_end, __err);
1225 // EOF checked
1226 if (__b == __e)
1227 __err |= ios_base::eofbit;
1228 return __b;
1229}
1230
1231template <class _CharT, class _InputIterator>
1232_InputIterator
1233num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1234 ios_base& __iob,
1235 ios_base::iostate& __err,
1236 long double& __v) const
1237{
1238 // Stage 1, nothing to do
1239 // Stage 2
1240 char_type __atoms[32];
1241 char_type __decimal_point;
1242 char_type __thousands_sep;
Howard Hinnant324bb032010-08-22 00:02:43 +00001243 string __grouping = this->__stage2_float_prep(__iob, __atoms,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001244 __decimal_point,
1245 __thousands_sep);
1246 char __a[__num_get_base::__num_get_buf_sz] = {0};
1247 char* __a_end = __a;
1248 unsigned __g[__num_get_base::__num_get_buf_sz];
1249 unsigned* __g_end = __g;
1250 unsigned __dc = 0;
1251 bool __in_units = true;
1252 char __exp = 'E';
1253 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001254 if (this->__stage2_float_loop(*__b, __in_units, __exp, __a, __a_end,
1255 __decimal_point, __thousands_sep,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001256 __grouping, __g, __g_end,
1257 __dc, __atoms))
1258 break;
1259 if (__grouping.size() != 0 && __in_units && __g_end-__g < __num_get_base::__num_get_buf_sz)
1260 *__g_end++ = __dc;
1261 // Stage 3
1262 __v = __num_get_float<long double>(__a, __a_end, __err);
1263 // Digit grouping checked
1264 __check_grouping(__grouping, __g, __g_end, __err);
1265 // EOF checked
1266 if (__b == __e)
1267 __err |= ios_base::eofbit;
1268 return __b;
1269}
1270
1271template <class _CharT, class _InputIterator>
1272_InputIterator
1273num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1274 ios_base& __iob,
1275 ios_base::iostate& __err,
1276 void*& __v) const
1277{
1278 // Stage 1
1279 int __base = 16;
1280 // Stage 2
1281 char_type __atoms[26];
1282 char_type __thousands_sep;
1283 string __grouping;
1284 use_facet<ctype<_CharT> >(__iob.getloc()).widen(__num_get_base::__src,
1285 __num_get_base::__src + 26, __atoms);
1286 char __a[__num_get_base::__num_get_buf_sz] = {0};
1287 char* __a_end = __a;
1288 unsigned __g[__num_get_base::__num_get_buf_sz];
1289 unsigned* __g_end = __g;
1290 unsigned __dc = 0;
1291 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001292 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
1293 __thousands_sep, __grouping,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001294 __g, __g_end, __atoms))
1295 break;
1296 // Stage 3
1297 __a[sizeof(__a)-1] = 0;
Sean Huntf3907e62011-07-15 05:40:33 +00001298#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantbcbbd4d2011-07-15 14:46:11 +00001299 if (sscanf_l(__a, 0, "%p", &__v) != 1)
Sean Huntf3907e62011-07-15 05:40:33 +00001300#else
1301 if (__sscanf_l(__a, __cloc(), "%p", &__v) != 1)
1302#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001303 __err = ios_base::failbit;
1304 // EOF checked
1305 if (__b == __e)
1306 __err |= ios_base::eofbit;
1307 return __b;
1308}
1309
1310extern template class num_get<char>;
1311extern template class num_get<wchar_t>;
1312
1313struct __num_put_base
1314{
1315protected:
1316 static void __format_int(char* __fmt, const char* __len, bool __signd,
1317 ios_base::fmtflags __flags);
1318 static bool __format_float(char* __fmt, const char* __len,
1319 ios_base::fmtflags __flags);
1320 static char* __identify_padding(char* __nb, char* __ne,
1321 const ios_base& __iob);
1322};
1323
1324template <class _CharT>
1325struct __num_put
1326 : protected __num_put_base
1327{
1328 static void __widen_and_group_int(char* __nb, char* __np, char* __ne,
1329 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1330 const locale& __loc);
1331 static void __widen_and_group_float(char* __nb, char* __np, char* __ne,
1332 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1333 const locale& __loc);
1334};
1335
1336template <class _CharT>
1337void
1338__num_put<_CharT>::__widen_and_group_int(char* __nb, char* __np, char* __ne,
1339 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1340 const locale& __loc)
1341{
1342 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> > (__loc);
1343 const numpunct<_CharT>& __npt = use_facet<numpunct<_CharT> >(__loc);
1344 string __grouping = __npt.grouping();
1345 if (__grouping.empty())
1346 {
1347 __ct.widen(__nb, __ne, __ob);
1348 __oe = __ob + (__ne - __nb);
1349 }
1350 else
1351 {
1352 __oe = __ob;
1353 char* __nf = __nb;
1354 if (*__nf == '-' || *__nf == '+')
1355 *__oe++ = __ct.widen(*__nf++);
1356 if (__ne - __nf >= 2 && __nf[0] == '0' && (__nf[1] == 'x' ||
1357 __nf[1] == 'X'))
1358 {
1359 *__oe++ = __ct.widen(*__nf++);
1360 *__oe++ = __ct.widen(*__nf++);
1361 }
1362 reverse(__nf, __ne);
1363 _CharT __thousands_sep = __npt.thousands_sep();
1364 unsigned __dc = 0;
1365 unsigned __dg = 0;
1366 for (char* __p = __nf; __p < __ne; ++__p)
1367 {
1368 if (static_cast<unsigned>(__grouping[__dg]) > 0 &&
1369 __dc == static_cast<unsigned>(__grouping[__dg]))
1370 {
1371 *__oe++ = __thousands_sep;
1372 __dc = 0;
1373 if (__dg < __grouping.size()-1)
1374 ++__dg;
1375 }
1376 *__oe++ = __ct.widen(*__p);
1377 ++__dc;
1378 }
1379 reverse(__ob + (__nf - __nb), __oe);
1380 }
1381 if (__np == __ne)
1382 __op = __oe;
1383 else
1384 __op = __ob + (__np - __nb);
1385}
1386
1387template <class _CharT>
1388void
1389__num_put<_CharT>::__widen_and_group_float(char* __nb, char* __np, char* __ne,
1390 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1391 const locale& __loc)
1392{
1393 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> > (__loc);
1394 const numpunct<_CharT>& __npt = use_facet<numpunct<_CharT> >(__loc);
1395 string __grouping = __npt.grouping();
1396 __oe = __ob;
1397 char* __nf = __nb;
1398 if (*__nf == '-' || *__nf == '+')
1399 *__oe++ = __ct.widen(*__nf++);
1400 char* __ns;
1401 if (__ne - __nf >= 2 && __nf[0] == '0' && (__nf[1] == 'x' ||
1402 __nf[1] == 'X'))
1403 {
1404 *__oe++ = __ct.widen(*__nf++);
1405 *__oe++ = __ct.widen(*__nf++);
1406 for (__ns = __nf; __ns < __ne; ++__ns)
Sean Huntf3907e62011-07-15 05:40:33 +00001407#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantbcbbd4d2011-07-15 14:46:11 +00001408 if (!isxdigit_l(*__ns, 0))
Sean Huntf3907e62011-07-15 05:40:33 +00001409#else
1410 if (!isxdigit_l(*__ns, __cloc()))
1411#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001412 break;
1413 }
1414 else
1415 {
1416 for (__ns = __nf; __ns < __ne; ++__ns)
Sean Huntf3907e62011-07-15 05:40:33 +00001417#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantbcbbd4d2011-07-15 14:46:11 +00001418 if (!isdigit_l(*__ns, 0))
Sean Huntf3907e62011-07-15 05:40:33 +00001419#else
1420 if (!isdigit_l(*__ns, __cloc()))
1421#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001422 break;
1423 }
1424 if (__grouping.empty())
1425 {
1426 __ct.widen(__nf, __ns, __oe);
1427 __oe += __ns - __nf;
1428 }
1429 else
1430 {
1431 reverse(__nf, __ns);
1432 _CharT __thousands_sep = __npt.thousands_sep();
1433 unsigned __dc = 0;
1434 unsigned __dg = 0;
1435 for (char* __p = __nf; __p < __ns; ++__p)
1436 {
1437 if (__grouping[__dg] > 0 && __dc == static_cast<unsigned>(__grouping[__dg]))
1438 {
1439 *__oe++ = __thousands_sep;
1440 __dc = 0;
1441 if (__dg < __grouping.size()-1)
1442 ++__dg;
1443 }
1444 *__oe++ = __ct.widen(*__p);
1445 ++__dc;
1446 }
1447 reverse(__ob + (__nf - __nb), __oe);
1448 }
1449 for (__nf = __ns; __nf < __ne; ++__nf)
1450 {
1451 if (*__nf == '.')
1452 {
1453 *__oe++ = __npt.decimal_point();
1454 ++__nf;
1455 break;
1456 }
1457 else
1458 *__oe++ = __ct.widen(*__nf);
1459 }
1460 __ct.widen(__nf, __ne, __oe);
1461 __oe += __ne - __nf;
1462 if (__np == __ne)
1463 __op = __oe;
1464 else
1465 __op = __ob + (__np - __nb);
1466}
1467
1468extern template class __num_put<char>;
1469extern template class __num_put<wchar_t>;
1470
1471template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00001472class _LIBCPP_VISIBLE num_put
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001473 : public locale::facet,
1474 private __num_put<_CharT>
1475{
1476public:
1477 typedef _CharT char_type;
1478 typedef _OutputIterator iter_type;
1479
1480 _LIBCPP_ALWAYS_INLINE
1481 explicit num_put(size_t __refs = 0)
1482 : locale::facet(__refs) {}
1483
1484 _LIBCPP_ALWAYS_INLINE
1485 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1486 bool __v) const
1487 {
1488 return do_put(__s, __iob, __fl, __v);
1489 }
1490
1491 _LIBCPP_ALWAYS_INLINE
1492 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1493 long __v) const
1494 {
1495 return do_put(__s, __iob, __fl, __v);
1496 }
1497
1498 _LIBCPP_ALWAYS_INLINE
1499 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1500 long long __v) const
1501 {
1502 return do_put(__s, __iob, __fl, __v);
1503 }
1504
1505 _LIBCPP_ALWAYS_INLINE
1506 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1507 unsigned long __v) const
1508 {
1509 return do_put(__s, __iob, __fl, __v);
1510 }
1511
1512 _LIBCPP_ALWAYS_INLINE
1513 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1514 unsigned long long __v) const
1515 {
1516 return do_put(__s, __iob, __fl, __v);
1517 }
1518
1519 _LIBCPP_ALWAYS_INLINE
1520 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1521 double __v) const
1522 {
1523 return do_put(__s, __iob, __fl, __v);
1524 }
1525
1526 _LIBCPP_ALWAYS_INLINE
1527 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1528 long double __v) const
1529 {
1530 return do_put(__s, __iob, __fl, __v);
1531 }
1532
1533 _LIBCPP_ALWAYS_INLINE
1534 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1535 const void* __v) const
1536 {
1537 return do_put(__s, __iob, __fl, __v);
1538 }
1539
1540 static locale::id id;
1541
1542protected:
Howard Hinnant82894812010-09-22 16:48:34 +00001543 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001544 ~num_put() {}
1545
1546 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1547 bool __v) const;
1548 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1549 long __v) const;
1550 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1551 long long __v) const;
1552 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1553 unsigned long) const;
1554 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1555 unsigned long long) const;
1556 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1557 double __v) const;
1558 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1559 long double __v) const;
1560 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1561 const void* __v) const;
1562};
1563
1564template <class _CharT, class _OutputIterator>
1565locale::id
1566num_put<_CharT, _OutputIterator>::id;
1567
1568template <class _CharT, class _OutputIterator>
1569_LIBCPP_HIDDEN
1570_OutputIterator
1571__pad_and_output(_OutputIterator __s,
1572 const _CharT* __ob, const _CharT* __op, const _CharT* __oe,
1573 ios_base& __iob, _CharT __fl)
1574{
1575 streamsize __sz = __oe - __ob;
1576 streamsize __ns = __iob.width();
1577 if (__ns > __sz)
1578 __ns -= __sz;
1579 else
1580 __ns = 0;
1581 for (;__ob < __op; ++__ob, ++__s)
1582 *__s = *__ob;
1583 for (; __ns; --__ns, ++__s)
1584 *__s = __fl;
1585 for (; __ob < __oe; ++__ob, ++__s)
1586 *__s = *__ob;
1587 __iob.width(0);
1588 return __s;
1589}
1590
1591template <class _CharT, class _OutputIterator>
1592_OutputIterator
1593num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1594 char_type __fl, bool __v) const
1595{
1596 if ((__iob.flags() & ios_base::boolalpha) == 0)
1597 return do_put(__s, __iob, __fl, (unsigned long)__v);
1598 const numpunct<char_type>& __np = use_facet<numpunct<char_type> >(__iob.getloc());
1599 typedef typename numpunct<char_type>::string_type string_type;
1600 string_type __nm = __v ? __np.truename() : __np.falsename();
1601 for (typename string_type::iterator __i = __nm.begin(); __i != __nm.end(); ++__i, ++__s)
1602 *__s = *__i;
1603 return __s;
1604}
1605
1606template <class _CharT, class _OutputIterator>
1607_OutputIterator
1608num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1609 char_type __fl, long __v) const
1610{
1611 // Stage 1 - Get number in narrow char
1612 char __fmt[6] = {'%', 0};
1613 const char* __len = "l";
1614 this->__format_int(__fmt+1, __len, true, __iob.flags());
1615 const unsigned __nbuf = (numeric_limits<long>::digits / 3)
1616 + ((numeric_limits<long>::digits % 3) != 0)
1617 + 1;
1618 char __nar[__nbuf];
Sean Huntf3907e62011-07-15 05:40:33 +00001619#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantbcbbd4d2011-07-15 14:46:11 +00001620 int __nc = sprintf_l(__nar, 0, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001621#else
1622 int __nc = __sprintf_l(__nar, __cloc(), __fmt, __v);
1623#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001624 char* __ne = __nar + __nc;
1625 char* __np = this->__identify_padding(__nar, __ne, __iob);
1626 // Stage 2 - Widen __nar while adding thousands separators
1627 char_type __o[2*(__nbuf-1) - 1];
1628 char_type* __op; // pad here
1629 char_type* __oe; // end of output
1630 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1631 // [__o, __oe) contains thousands_sep'd wide number
1632 // Stage 3 & 4
1633 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1634}
1635
1636template <class _CharT, class _OutputIterator>
1637_OutputIterator
1638num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1639 char_type __fl, long long __v) const
1640{
1641 // Stage 1 - Get number in narrow char
1642 char __fmt[8] = {'%', 0};
1643 const char* __len = "ll";
1644 this->__format_int(__fmt+1, __len, true, __iob.flags());
1645 const unsigned __nbuf = (numeric_limits<long long>::digits / 3)
1646 + ((numeric_limits<long long>::digits % 3) != 0)
1647 + 1;
1648 char __nar[__nbuf];
Sean Huntf3907e62011-07-15 05:40:33 +00001649#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantbcbbd4d2011-07-15 14:46:11 +00001650 int __nc = sprintf_l(__nar, 0, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001651#else
1652 int __nc = __sprintf_l(__nar, __cloc(), __fmt, __v);
1653#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001654 char* __ne = __nar + __nc;
1655 char* __np = this->__identify_padding(__nar, __ne, __iob);
1656 // Stage 2 - Widen __nar while adding thousands separators
1657 char_type __o[2*(__nbuf-1) - 1];
1658 char_type* __op; // pad here
1659 char_type* __oe; // end of output
1660 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1661 // [__o, __oe) contains thousands_sep'd wide number
1662 // Stage 3 & 4
1663 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1664}
1665
1666template <class _CharT, class _OutputIterator>
1667_OutputIterator
1668num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1669 char_type __fl, unsigned long __v) const
1670{
1671 // Stage 1 - Get number in narrow char
1672 char __fmt[6] = {'%', 0};
1673 const char* __len = "l";
1674 this->__format_int(__fmt+1, __len, false, __iob.flags());
1675 const unsigned __nbuf = (numeric_limits<unsigned long>::digits / 3)
1676 + ((numeric_limits<unsigned long>::digits % 3) != 0)
1677 + 1;
1678 char __nar[__nbuf];
Sean Huntf3907e62011-07-15 05:40:33 +00001679#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantbcbbd4d2011-07-15 14:46:11 +00001680 int __nc = sprintf_l(__nar, 0, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001681#else
1682 int __nc = __sprintf_l(__nar, __cloc(), __fmt, __v);
1683#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001684 char* __ne = __nar + __nc;
1685 char* __np = this->__identify_padding(__nar, __ne, __iob);
1686 // Stage 2 - Widen __nar while adding thousands separators
1687 char_type __o[2*(__nbuf-1) - 1];
1688 char_type* __op; // pad here
1689 char_type* __oe; // end of output
1690 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1691 // [__o, __oe) contains thousands_sep'd wide number
1692 // Stage 3 & 4
1693 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1694}
1695
1696template <class _CharT, class _OutputIterator>
1697_OutputIterator
1698num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1699 char_type __fl, unsigned long long __v) const
1700{
1701 // Stage 1 - Get number in narrow char
1702 char __fmt[8] = {'%', 0};
1703 const char* __len = "ll";
1704 this->__format_int(__fmt+1, __len, false, __iob.flags());
1705 const unsigned __nbuf = (numeric_limits<unsigned long long>::digits / 3)
1706 + ((numeric_limits<unsigned long long>::digits % 3) != 0)
1707 + 1;
1708 char __nar[__nbuf];
Sean Huntf3907e62011-07-15 05:40:33 +00001709#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantbcbbd4d2011-07-15 14:46:11 +00001710 int __nc = sprintf_l(__nar, 0, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001711#else
1712 int __nc = __sprintf_l(__nar, __cloc(), __fmt, __v);
1713#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001714 char* __ne = __nar + __nc;
1715 char* __np = this->__identify_padding(__nar, __ne, __iob);
1716 // Stage 2 - Widen __nar while adding thousands separators
1717 char_type __o[2*(__nbuf-1) - 1];
1718 char_type* __op; // pad here
1719 char_type* __oe; // end of output
1720 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1721 // [__o, __oe) contains thousands_sep'd wide number
1722 // Stage 3 & 4
1723 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1724}
1725
1726template <class _CharT, class _OutputIterator>
1727_OutputIterator
1728num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1729 char_type __fl, double __v) const
1730{
1731 // Stage 1 - Get number in narrow char
1732 char __fmt[8] = {'%', 0};
1733 const char* __len = "";
1734 bool __specify_precision = this->__format_float(__fmt+1, __len, __iob.flags());
1735 const unsigned __nbuf = 30;
1736 char __nar[__nbuf];
1737 char* __nb = __nar;
1738 int __nc;
1739 if (__specify_precision)
Sean Huntf3907e62011-07-15 05:40:33 +00001740#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantbcbbd4d2011-07-15 14:46:11 +00001741 __nc = snprintf_l(__nb, __nbuf, 0, __fmt,
Howard Hinnantadff4892010-05-24 17:49:41 +00001742 (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001743#else
1744 __nc = __snprintf_l(__nb, __nbuf, __cloc(), __fmt,
1745 (int)__iob.precision(), __v);
1746#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001747 else
Sean Huntf3907e62011-07-15 05:40:33 +00001748#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantbcbbd4d2011-07-15 14:46:11 +00001749 __nc = snprintf_l(__nb, __nbuf, 0, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001750#else
1751 __nc = __snprintf_l(__nb, __nbuf, __cloc(), __fmt, __v);
1752#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001753 unique_ptr<char, void(*)(void*)> __nbh(0, free);
1754 if (__nc > static_cast<int>(__nbuf-1))
1755 {
1756 if (__specify_precision)
Sean Huntf3907e62011-07-15 05:40:33 +00001757#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantbcbbd4d2011-07-15 14:46:11 +00001758 __nc = asprintf_l(&__nb, 0, __fmt, (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001759#else
1760 __nc = __asprintf_l(&__nb, __cloc(), __fmt,
David Chisnallc512df12011-09-21 08:39:44 +00001761 (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001762#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001763 else
Sean Huntf3907e62011-07-15 05:40:33 +00001764#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantbcbbd4d2011-07-15 14:46:11 +00001765 __nc = asprintf_l(&__nb, 0, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001766#else
David Chisnallc512df12011-09-21 08:39:44 +00001767 __nc = __asprintf_l(&__nb, __cloc(), __fmt, (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001768#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001769 if (__nb == 0)
1770 __throw_bad_alloc();
1771 __nbh.reset(__nb);
1772 }
1773 char* __ne = __nb + __nc;
1774 char* __np = this->__identify_padding(__nb, __ne, __iob);
1775 // Stage 2 - Widen __nar while adding thousands separators
1776 char_type __o[2*(__nbuf-1) - 1];
1777 char_type* __ob = __o;
1778 unique_ptr<char_type, void(*)(void*)> __obh(0, free);
1779 if (__nb != __nar)
1780 {
1781 __ob = (char_type*)malloc((2*__nc)*sizeof(char_type));
1782 if (__ob == 0)
1783 __throw_bad_alloc();
1784 __obh.reset(__ob);
1785 }
1786 char_type* __op; // pad here
1787 char_type* __oe; // end of output
1788 this->__widen_and_group_float(__nb, __np, __ne, __ob, __op, __oe, __iob.getloc());
1789 // [__o, __oe) contains thousands_sep'd wide number
1790 // Stage 3 & 4
1791 __s = __pad_and_output(__s, __ob, __op, __oe, __iob, __fl);
1792 return __s;
1793}
1794
1795template <class _CharT, class _OutputIterator>
1796_OutputIterator
1797num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1798 char_type __fl, long double __v) const
1799{
1800 // Stage 1 - Get number in narrow char
1801 char __fmt[8] = {'%', 0};
1802 const char* __len = "L";
1803 bool __specify_precision = this->__format_float(__fmt+1, __len, __iob.flags());
1804 const unsigned __nbuf = 30;
1805 char __nar[__nbuf];
1806 char* __nb = __nar;
1807 int __nc;
1808 if (__specify_precision)
Sean Huntf3907e62011-07-15 05:40:33 +00001809#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantbcbbd4d2011-07-15 14:46:11 +00001810 __nc = snprintf_l(__nb, __nbuf, 0, __fmt,
Howard Hinnantadff4892010-05-24 17:49:41 +00001811 (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001812#else
1813 __nc = __snprintf_l(__nb, __nbuf, __cloc(), __fmt,
1814 (int)__iob.precision(), __v);
1815#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001816 else
Sean Huntf3907e62011-07-15 05:40:33 +00001817#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantbcbbd4d2011-07-15 14:46:11 +00001818 __nc = snprintf_l(__nb, __nbuf, 0, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001819#else
1820 __nc = __snprintf_l(__nb, __nbuf, __cloc(), __fmt, __v);
1821#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001822 unique_ptr<char, void(*)(void*)> __nbh(0, free);
1823 if (__nc > static_cast<int>(__nbuf-1))
1824 {
1825 if (__specify_precision)
Sean Huntf3907e62011-07-15 05:40:33 +00001826#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantbcbbd4d2011-07-15 14:46:11 +00001827 __nc = asprintf_l(&__nb, 0, __fmt, (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001828#else
1829 __nc = __asprintf_l(&__nb, __cloc(), __fmt,
David Chisnallc512df12011-09-21 08:39:44 +00001830 (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001831#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001832 else
Sean Huntf3907e62011-07-15 05:40:33 +00001833#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantbcbbd4d2011-07-15 14:46:11 +00001834 __nc = asprintf_l(&__nb, 0, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001835#else
David Chisnallc512df12011-09-21 08:39:44 +00001836 __nc = __asprintf_l(&__nb, __cloc(), __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001837#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001838 if (__nb == 0)
1839 __throw_bad_alloc();
1840 __nbh.reset(__nb);
1841 }
1842 char* __ne = __nb + __nc;
1843 char* __np = this->__identify_padding(__nb, __ne, __iob);
1844 // Stage 2 - Widen __nar while adding thousands separators
1845 char_type __o[2*(__nbuf-1) - 1];
1846 char_type* __ob = __o;
1847 unique_ptr<char_type, void(*)(void*)> __obh(0, free);
1848 if (__nb != __nar)
1849 {
1850 __ob = (char_type*)malloc((2*__nc)*sizeof(char_type));
1851 if (__ob == 0)
1852 __throw_bad_alloc();
1853 __obh.reset(__ob);
1854 }
1855 char_type* __op; // pad here
1856 char_type* __oe; // end of output
1857 this->__widen_and_group_float(__nb, __np, __ne, __ob, __op, __oe, __iob.getloc());
1858 // [__o, __oe) contains thousands_sep'd wide number
1859 // Stage 3 & 4
1860 __s = __pad_and_output(__s, __ob, __op, __oe, __iob, __fl);
1861 return __s;
1862}
1863
1864template <class _CharT, class _OutputIterator>
1865_OutputIterator
1866num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1867 char_type __fl, const void* __v) const
1868{
1869 // Stage 1 - Get pointer in narrow char
1870 char __fmt[6] = "%p";
1871 const unsigned __nbuf = 20;
1872 char __nar[__nbuf];
Sean Huntf3907e62011-07-15 05:40:33 +00001873#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantbcbbd4d2011-07-15 14:46:11 +00001874 int __nc = sprintf_l(__nar, 0, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001875#else
1876 int __nc = __sprintf_l(__nar, __cloc(), __fmt, __v);
1877#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001878 char* __ne = __nar + __nc;
1879 char* __np = this->__identify_padding(__nar, __ne, __iob);
1880 // Stage 2 - Widen __nar
1881 char_type __o[2*(__nbuf-1) - 1];
1882 char_type* __op; // pad here
1883 char_type* __oe; // end of output
1884 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
1885 __ct.widen(__nar, __ne, __o);
1886 __oe = __o + (__ne - __nar);
1887 if (__np == __ne)
1888 __op = __oe;
1889 else
1890 __op = __o + (__np - __nar);
1891 // [__o, __oe) contains wide number
1892 // Stage 3 & 4
1893 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1894}
1895
1896extern template class num_put<char>;
1897extern template class num_put<wchar_t>;
1898
1899template <class _CharT, class _InputIterator>
1900_LIBCPP_HIDDEN
1901int
1902__get_up_to_n_digits(_InputIterator& __b, _InputIterator __e,
1903 ios_base::iostate& __err, const ctype<_CharT>& __ct, int __n)
1904{
1905 // Precondition: __n >= 1
1906 if (__b == __e)
1907 {
1908 __err |= ios_base::eofbit | ios_base::failbit;
1909 return 0;
1910 }
1911 // get first digit
1912 _CharT __c = *__b;
1913 if (!__ct.is(ctype_base::digit, __c))
1914 {
1915 __err |= ios_base::failbit;
1916 return 0;
1917 }
1918 int __r = __ct.narrow(__c, 0) - '0';
1919 for (++__b, --__n; __b != __e && __n > 0; ++__b, --__n)
1920 {
1921 // get next digit
1922 __c = *__b;
1923 if (!__ct.is(ctype_base::digit, __c))
1924 return __r;
1925 __r = __r * 10 + __ct.narrow(__c, 0) - '0';
1926 }
1927 if (__b == __e)
1928 __err |= ios_base::eofbit;
1929 return __r;
1930}
1931
Howard Hinnant82894812010-09-22 16:48:34 +00001932class _LIBCPP_VISIBLE time_base
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001933{
1934public:
1935 enum dateorder {no_order, dmy, mdy, ymd, ydm};
1936};
1937
1938template <class _CharT>
Howard Hinnant2d72b1e2010-12-17 14:46:43 +00001939class __time_get_c_storage // purposefully not decorated
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001940{
1941protected:
1942 typedef basic_string<_CharT> string_type;
1943
1944 virtual const string_type* __weeks() const;
1945 virtual const string_type* __months() const;
1946 virtual const string_type* __am_pm() const;
1947 virtual const string_type& __c() const;
1948 virtual const string_type& __r() const;
1949 virtual const string_type& __x() const;
1950 virtual const string_type& __X() const;
1951};
1952
1953template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00001954class _LIBCPP_VISIBLE time_get
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001955 : public locale::facet,
1956 public time_base,
1957 private __time_get_c_storage<_CharT>
1958{
1959public:
1960 typedef _CharT char_type;
1961 typedef _InputIterator iter_type;
1962 typedef time_base::dateorder dateorder;
1963 typedef basic_string<char_type> string_type;
1964
1965 _LIBCPP_ALWAYS_INLINE
1966 explicit time_get(size_t __refs = 0)
1967 : locale::facet(__refs) {}
1968
1969 _LIBCPP_ALWAYS_INLINE
1970 dateorder date_order() const
1971 {
1972 return this->do_date_order();
1973 }
1974
1975 _LIBCPP_ALWAYS_INLINE
1976 iter_type get_time(iter_type __b, iter_type __e, ios_base& __iob,
1977 ios_base::iostate& __err, tm* __tm) const
1978 {
1979 return do_get_time(__b, __e, __iob, __err, __tm);
1980 }
1981
1982 _LIBCPP_ALWAYS_INLINE
1983 iter_type get_date(iter_type __b, iter_type __e, ios_base& __iob,
1984 ios_base::iostate& __err, tm* __tm) const
1985 {
1986 return do_get_date(__b, __e, __iob, __err, __tm);
1987 }
1988
1989 _LIBCPP_ALWAYS_INLINE
1990 iter_type get_weekday(iter_type __b, iter_type __e, ios_base& __iob,
1991 ios_base::iostate& __err, tm* __tm) const
1992 {
1993 return do_get_weekday(__b, __e, __iob, __err, __tm);
1994 }
1995
1996 _LIBCPP_ALWAYS_INLINE
1997 iter_type get_monthname(iter_type __b, iter_type __e, ios_base& __iob,
1998 ios_base::iostate& __err, tm* __tm) const
1999 {
2000 return do_get_monthname(__b, __e, __iob, __err, __tm);
2001 }
2002
2003 _LIBCPP_ALWAYS_INLINE
2004 iter_type get_year(iter_type __b, iter_type __e, ios_base& __iob,
2005 ios_base::iostate& __err, tm* __tm) const
2006 {
2007 return do_get_year(__b, __e, __iob, __err, __tm);
2008 }
2009
2010 _LIBCPP_ALWAYS_INLINE
2011 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
2012 ios_base::iostate& __err, tm *__tm,
2013 char __fmt, char __mod = 0) const
2014 {
2015 return do_get(__b, __e, __iob, __err, __tm, __fmt, __mod);
2016 }
2017
2018 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
2019 ios_base::iostate& __err, tm* __tm,
2020 const char_type* __fmtb, const char_type* __fmte) const;
2021
2022 static locale::id id;
2023
2024protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002025 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002026 ~time_get() {}
2027
2028 virtual dateorder do_date_order() const;
2029 virtual iter_type do_get_time(iter_type __b, iter_type __e, ios_base& __iob,
2030 ios_base::iostate& __err, tm* __tm) const;
2031 virtual iter_type do_get_date(iter_type __b, iter_type __e, ios_base& __iob,
2032 ios_base::iostate& __err, tm* __tm) const;
2033 virtual iter_type do_get_weekday(iter_type __b, iter_type __e, ios_base& __iob,
2034 ios_base::iostate& __err, tm* __tm) const;
2035 virtual iter_type do_get_monthname(iter_type __b, iter_type __e, ios_base& __iob,
2036 ios_base::iostate& __err, tm* __tm) const;
2037 virtual iter_type do_get_year(iter_type __b, iter_type __e, ios_base& __iob,
2038 ios_base::iostate& __err, tm* __tm) const;
2039 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
2040 ios_base::iostate& __err, tm* __tm,
2041 char __fmt, char __mod) const;
2042private:
2043 void __get_white_space(iter_type& __b, iter_type __e,
2044 ios_base::iostate& __err, const ctype<char_type>& __ct) const;
2045 void __get_percent(iter_type& __b, iter_type __e, ios_base::iostate& __err,
2046 const ctype<char_type>& __ct) const;
2047
2048 void __get_weekdayname(int& __m,
2049 iter_type& __b, iter_type __e,
2050 ios_base::iostate& __err,
2051 const ctype<char_type>& __ct) const;
2052 void __get_monthname(int& __m,
2053 iter_type& __b, iter_type __e,
2054 ios_base::iostate& __err,
2055 const ctype<char_type>& __ct) const;
2056 void __get_day(int& __d,
2057 iter_type& __b, iter_type __e,
2058 ios_base::iostate& __err,
2059 const ctype<char_type>& __ct) const;
2060 void __get_month(int& __m,
2061 iter_type& __b, iter_type __e,
2062 ios_base::iostate& __err,
2063 const ctype<char_type>& __ct) const;
2064 void __get_year(int& __y,
2065 iter_type& __b, iter_type __e,
2066 ios_base::iostate& __err,
2067 const ctype<char_type>& __ct) const;
2068 void __get_year4(int& __y,
2069 iter_type& __b, iter_type __e,
2070 ios_base::iostate& __err,
2071 const ctype<char_type>& __ct) const;
2072 void __get_hour(int& __d,
2073 iter_type& __b, iter_type __e,
2074 ios_base::iostate& __err,
2075 const ctype<char_type>& __ct) const;
2076 void __get_12_hour(int& __h,
2077 iter_type& __b, iter_type __e,
2078 ios_base::iostate& __err,
2079 const ctype<char_type>& __ct) const;
2080 void __get_am_pm(int& __h,
2081 iter_type& __b, iter_type __e,
2082 ios_base::iostate& __err,
2083 const ctype<char_type>& __ct) const;
2084 void __get_minute(int& __m,
2085 iter_type& __b, iter_type __e,
2086 ios_base::iostate& __err,
2087 const ctype<char_type>& __ct) const;
2088 void __get_second(int& __s,
2089 iter_type& __b, iter_type __e,
2090 ios_base::iostate& __err,
2091 const ctype<char_type>& __ct) const;
2092 void __get_weekday(int& __w,
2093 iter_type& __b, iter_type __e,
2094 ios_base::iostate& __err,
2095 const ctype<char_type>& __ct) const;
2096 void __get_day_year_num(int& __w,
2097 iter_type& __b, iter_type __e,
2098 ios_base::iostate& __err,
2099 const ctype<char_type>& __ct) const;
2100};
2101
2102template <class _CharT, class _InputIterator>
2103locale::id
2104time_get<_CharT, _InputIterator>::id;
2105
2106// time_get primatives
2107
2108template <class _CharT, class _InputIterator>
2109void
2110time_get<_CharT, _InputIterator>::__get_weekdayname(int& __w,
2111 iter_type& __b, iter_type __e,
2112 ios_base::iostate& __err,
2113 const ctype<char_type>& __ct) const
2114{
2115 // Note: ignoring case comes from the POSIX strptime spec
2116 const string_type* __wk = this->__weeks();
2117 int __i = __scan_keyword(__b, __e, __wk, __wk+14, __ct, __err, false) - __wk;
2118 if (__i < 14)
2119 __w = __i % 7;
2120}
2121
2122template <class _CharT, class _InputIterator>
2123void
2124time_get<_CharT, _InputIterator>::__get_monthname(int& __m,
2125 iter_type& __b, iter_type __e,
2126 ios_base::iostate& __err,
2127 const ctype<char_type>& __ct) const
2128{
2129 // Note: ignoring case comes from the POSIX strptime spec
2130 const string_type* __month = this->__months();
2131 int __i = __scan_keyword(__b, __e, __month, __month+24, __ct, __err, false) - __month;
2132 if (__i < 24)
2133 __m = __i % 12;
2134}
2135
2136template <class _CharT, class _InputIterator>
2137void
2138time_get<_CharT, _InputIterator>::__get_day(int& __d,
2139 iter_type& __b, iter_type __e,
2140 ios_base::iostate& __err,
2141 const ctype<char_type>& __ct) const
2142{
2143 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2144 if (!(__err & ios_base::failbit) && 1 <= __t && __t <= 31)
2145 __d = __t;
2146 else
2147 __err |= ios_base::failbit;
2148}
2149
2150template <class _CharT, class _InputIterator>
2151void
2152time_get<_CharT, _InputIterator>::__get_month(int& __m,
2153 iter_type& __b, iter_type __e,
2154 ios_base::iostate& __err,
2155 const ctype<char_type>& __ct) const
2156{
2157 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2) - 1;
2158 if (!(__err & ios_base::failbit) && __t <= 11)
2159 __m = __t;
2160 else
2161 __err |= ios_base::failbit;
2162}
2163
2164template <class _CharT, class _InputIterator>
2165void
2166time_get<_CharT, _InputIterator>::__get_year(int& __y,
2167 iter_type& __b, iter_type __e,
2168 ios_base::iostate& __err,
2169 const ctype<char_type>& __ct) const
2170{
2171 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 4);
2172 if (!(__err & ios_base::failbit))
2173 {
2174 if (__t < 69)
2175 __t += 2000;
2176 else if (69 <= __t && __t <= 99)
2177 __t += 1900;
2178 __y = __t - 1900;
2179 }
2180}
2181
2182template <class _CharT, class _InputIterator>
2183void
2184time_get<_CharT, _InputIterator>::__get_year4(int& __y,
2185 iter_type& __b, iter_type __e,
2186 ios_base::iostate& __err,
2187 const ctype<char_type>& __ct) const
2188{
2189 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 4);
2190 if (!(__err & ios_base::failbit))
2191 __y = __t - 1900;
2192}
2193
2194template <class _CharT, class _InputIterator>
2195void
2196time_get<_CharT, _InputIterator>::__get_hour(int& __h,
2197 iter_type& __b, iter_type __e,
2198 ios_base::iostate& __err,
2199 const ctype<char_type>& __ct) const
2200{
2201 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2202 if (!(__err & ios_base::failbit) && __t <= 23)
2203 __h = __t;
2204 else
2205 __err |= ios_base::failbit;
2206}
2207
2208template <class _CharT, class _InputIterator>
2209void
2210time_get<_CharT, _InputIterator>::__get_12_hour(int& __h,
2211 iter_type& __b, iter_type __e,
2212 ios_base::iostate& __err,
2213 const ctype<char_type>& __ct) const
2214{
2215 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2216 if (!(__err & ios_base::failbit) && 1 <= __t && __t <= 12)
2217 __h = __t;
2218 else
2219 __err |= ios_base::failbit;
2220}
2221
2222template <class _CharT, class _InputIterator>
2223void
2224time_get<_CharT, _InputIterator>::__get_minute(int& __m,
2225 iter_type& __b, iter_type __e,
2226 ios_base::iostate& __err,
2227 const ctype<char_type>& __ct) const
2228{
2229 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2230 if (!(__err & ios_base::failbit) && __t <= 59)
2231 __m = __t;
2232 else
2233 __err |= ios_base::failbit;
2234}
2235
2236template <class _CharT, class _InputIterator>
2237void
2238time_get<_CharT, _InputIterator>::__get_second(int& __s,
2239 iter_type& __b, iter_type __e,
2240 ios_base::iostate& __err,
2241 const ctype<char_type>& __ct) const
2242{
2243 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2244 if (!(__err & ios_base::failbit) && __t <= 60)
2245 __s = __t;
2246 else
2247 __err |= ios_base::failbit;
2248}
2249
2250template <class _CharT, class _InputIterator>
2251void
2252time_get<_CharT, _InputIterator>::__get_weekday(int& __w,
2253 iter_type& __b, iter_type __e,
2254 ios_base::iostate& __err,
2255 const ctype<char_type>& __ct) const
2256{
2257 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 1);
2258 if (!(__err & ios_base::failbit) && __t <= 6)
2259 __w = __t;
2260 else
2261 __err |= ios_base::failbit;
2262}
2263
2264template <class _CharT, class _InputIterator>
2265void
2266time_get<_CharT, _InputIterator>::__get_day_year_num(int& __d,
2267 iter_type& __b, iter_type __e,
2268 ios_base::iostate& __err,
2269 const ctype<char_type>& __ct) const
2270{
2271 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 3);
2272 if (!(__err & ios_base::failbit) && __t <= 365)
2273 __d = __t;
2274 else
2275 __err |= ios_base::failbit;
2276}
2277
2278template <class _CharT, class _InputIterator>
2279void
2280time_get<_CharT, _InputIterator>::__get_white_space(iter_type& __b, iter_type __e,
2281 ios_base::iostate& __err,
2282 const ctype<char_type>& __ct) const
2283{
2284 for (; __b != __e && __ct.is(ctype_base::space, *__b); ++__b)
2285 ;
2286 if (__b == __e)
2287 __err |= ios_base::eofbit;
2288}
2289
2290template <class _CharT, class _InputIterator>
2291void
2292time_get<_CharT, _InputIterator>::__get_am_pm(int& __h,
2293 iter_type& __b, iter_type __e,
2294 ios_base::iostate& __err,
2295 const ctype<char_type>& __ct) const
2296{
2297 const string_type* __ap = this->__am_pm();
2298 if (__ap[0].size() + __ap[1].size() == 0)
2299 {
2300 __err |= ios_base::failbit;
2301 return;
2302 }
2303 int __i = __scan_keyword(__b, __e, __ap, __ap+2, __ct, __err, false) - __ap;
2304 if (__i == 0 && __h == 12)
2305 __h = 0;
2306 else if (__i == 1 && __h < 12)
2307 __h += 12;
2308}
2309
2310template <class _CharT, class _InputIterator>
2311void
2312time_get<_CharT, _InputIterator>::__get_percent(iter_type& __b, iter_type __e,
2313 ios_base::iostate& __err,
2314 const ctype<char_type>& __ct) const
2315{
2316 if (__b == __e)
2317 {
2318 __err |= ios_base::eofbit | ios_base::failbit;
2319 return;
2320 }
2321 if (__ct.narrow(*__b, 0) != '%')
2322 __err |= ios_base::failbit;
2323 else if(++__b == __e)
2324 __err |= ios_base::eofbit;
2325}
2326
2327// time_get end primatives
2328
2329template <class _CharT, class _InputIterator>
2330_InputIterator
2331time_get<_CharT, _InputIterator>::get(iter_type __b, iter_type __e,
2332 ios_base& __iob,
2333 ios_base::iostate& __err, tm* __tm,
2334 const char_type* __fmtb, const char_type* __fmte) const
2335{
2336 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2337 __err = ios_base::goodbit;
2338 while (__fmtb != __fmte && __err == ios_base::goodbit)
2339 {
2340 if (__b == __e)
2341 {
2342 __err = ios_base::failbit;
2343 break;
2344 }
2345 if (__ct.narrow(*__fmtb, 0) == '%')
2346 {
2347 if (++__fmtb == __fmte)
2348 {
2349 __err = ios_base::failbit;
2350 break;
2351 }
2352 char __cmd = __ct.narrow(*__fmtb, 0);
2353 char __opt = '\0';
2354 if (__cmd == 'E' || __cmd == '0')
2355 {
2356 if (++__fmtb == __fmte)
2357 {
2358 __err = ios_base::failbit;
2359 break;
2360 }
2361 __opt = __cmd;
2362 __cmd = __ct.narrow(*__fmtb, 0);
2363 }
2364 __b = do_get(__b, __e, __iob, __err, __tm, __cmd, __opt);
2365 ++__fmtb;
2366 }
2367 else if (__ct.is(ctype_base::space, *__fmtb))
2368 {
2369 for (++__fmtb; __fmtb != __fmte && __ct.is(ctype_base::space, *__fmtb); ++__fmtb)
2370 ;
2371 for ( ; __b != __e && __ct.is(ctype_base::space, *__b); ++__b)
2372 ;
2373 }
2374 else if (__ct.toupper(*__b) == __ct.toupper(*__fmtb))
2375 {
2376 ++__b;
2377 ++__fmtb;
2378 }
2379 else
2380 __err = ios_base::failbit;
2381 }
2382 if (__b == __e)
2383 __err |= ios_base::eofbit;
2384 return __b;
2385}
2386
2387template <class _CharT, class _InputIterator>
2388typename time_get<_CharT, _InputIterator>::dateorder
2389time_get<_CharT, _InputIterator>::do_date_order() const
2390{
2391 return mdy;
2392}
2393
2394template <class _CharT, class _InputIterator>
2395_InputIterator
2396time_get<_CharT, _InputIterator>::do_get_time(iter_type __b, iter_type __e,
2397 ios_base& __iob,
2398 ios_base::iostate& __err,
2399 tm* __tm) const
2400{
2401 const char_type __fmt[] = {'%', 'H', ':', '%', 'M', ':', '%', 'S'};
2402 return get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2403}
2404
2405template <class _CharT, class _InputIterator>
2406_InputIterator
2407time_get<_CharT, _InputIterator>::do_get_date(iter_type __b, iter_type __e,
2408 ios_base& __iob,
2409 ios_base::iostate& __err,
2410 tm* __tm) const
2411{
2412 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2413 const string_type& __fmt = this->__x();
2414 return get(__b, __e, __iob, __err, __tm, __fmt.data(), __fmt.data() + __fmt.size());
2415}
2416
2417template <class _CharT, class _InputIterator>
2418_InputIterator
2419time_get<_CharT, _InputIterator>::do_get_weekday(iter_type __b, iter_type __e,
2420 ios_base& __iob,
2421 ios_base::iostate& __err,
2422 tm* __tm) const
2423{
2424 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2425 __get_weekdayname(__tm->tm_wday, __b, __e, __err, __ct);
2426 return __b;
2427}
2428
2429template <class _CharT, class _InputIterator>
2430_InputIterator
2431time_get<_CharT, _InputIterator>::do_get_monthname(iter_type __b, iter_type __e,
2432 ios_base& __iob,
2433 ios_base::iostate& __err,
2434 tm* __tm) const
2435{
2436 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2437 __get_monthname(__tm->tm_mon, __b, __e, __err, __ct);
2438 return __b;
2439}
2440
2441template <class _CharT, class _InputIterator>
2442_InputIterator
2443time_get<_CharT, _InputIterator>::do_get_year(iter_type __b, iter_type __e,
2444 ios_base& __iob,
2445 ios_base::iostate& __err,
2446 tm* __tm) const
2447{
2448 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2449 __get_year(__tm->tm_year, __b, __e, __err, __ct);
2450 return __b;
2451}
2452
2453template <class _CharT, class _InputIterator>
2454_InputIterator
2455time_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
2456 ios_base& __iob,
2457 ios_base::iostate& __err, tm* __tm,
2458 char __fmt, char) const
2459{
2460 __err = ios_base::goodbit;
2461 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2462 switch (__fmt)
2463 {
2464 case 'a':
2465 case 'A':
2466 __get_weekdayname(__tm->tm_wday, __b, __e, __err, __ct);
2467 break;
2468 case 'b':
2469 case 'B':
2470 case 'h':
2471 __get_monthname(__tm->tm_mon, __b, __e, __err, __ct);
2472 break;
2473 case 'c':
2474 {
2475 const string_type& __fmt = this->__c();
2476 __b = get(__b, __e, __iob, __err, __tm, __fmt.data(), __fmt.data() + __fmt.size());
2477 }
2478 break;
2479 case 'd':
2480 case 'e':
2481 __get_day(__tm->tm_mday, __b, __e, __err, __ct);
2482 break;
2483 case 'D':
2484 {
2485 const char_type __fmt[] = {'%', 'm', '/', '%', 'd', '/', '%', 'y'};
2486 __b = get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2487 }
2488 break;
Howard Hinnant506b3642011-04-10 17:54:14 +00002489 case 'F':
2490 {
2491 const char_type __fmt[] = {'%', 'Y', '-', '%', 'm', '-', '%', 'd'};
2492 __b = get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2493 }
2494 break;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002495 case 'H':
2496 __get_hour(__tm->tm_hour, __b, __e, __err, __ct);
2497 break;
2498 case 'I':
2499 __get_12_hour(__tm->tm_hour, __b, __e, __err, __ct);
2500 break;
2501 case 'j':
2502 __get_day_year_num(__tm->tm_yday, __b, __e, __err, __ct);
2503 break;
2504 case 'm':
2505 __get_month(__tm->tm_mon, __b, __e, __err, __ct);
2506 break;
2507 case 'M':
2508 __get_minute(__tm->tm_min, __b, __e, __err, __ct);
2509 break;
2510 case 'n':
2511 case 't':
2512 __get_white_space(__b, __e, __err, __ct);
2513 break;
2514 case 'p':
2515 __get_am_pm(__tm->tm_hour, __b, __e, __err, __ct);
2516 break;
2517 case 'r':
2518 {
2519 const char_type __fmt[] = {'%', 'I', ':', '%', 'M', ':', '%', 'S', ' ', '%', 'p'};
2520 __b = get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2521 }
2522 break;
2523 case 'R':
2524 {
2525 const char_type __fmt[] = {'%', 'H', ':', '%', 'M'};
2526 __b = get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2527 }
2528 break;
2529 case 'S':
2530 __get_second(__tm->tm_sec, __b, __e, __err, __ct);
2531 break;
2532 case 'T':
2533 {
2534 const char_type __fmt[] = {'%', 'H', ':', '%', 'M', ':', '%', 'S'};
2535 __b = get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2536 }
2537 break;
2538 case 'w':
2539 __get_weekday(__tm->tm_wday, __b, __e, __err, __ct);
2540 break;
2541 case 'x':
2542 return do_get_date(__b, __e, __iob, __err, __tm);
2543 case 'X':
2544 {
2545 const string_type& __fmt = this->__X();
2546 __b = get(__b, __e, __iob, __err, __tm, __fmt.data(), __fmt.data() + __fmt.size());
2547 }
2548 break;
2549 case 'y':
2550 __get_year(__tm->tm_year, __b, __e, __err, __ct);
2551 break;
2552 case 'Y':
2553 __get_year4(__tm->tm_year, __b, __e, __err, __ct);
2554 break;
2555 case '%':
2556 __get_percent(__b, __e, __err, __ct);
2557 break;
2558 default:
2559 __err |= ios_base::failbit;
2560 }
2561 return __b;
2562}
2563
2564extern template class time_get<char>;
2565extern template class time_get<wchar_t>;
2566
2567class __time_get
2568{
2569protected:
2570 locale_t __loc_;
2571
2572 __time_get(const char* __nm);
2573 __time_get(const string& __nm);
2574 ~__time_get();
2575};
2576
2577template <class _CharT>
2578class __time_get_storage
2579 : public __time_get
2580{
2581protected:
2582 typedef basic_string<_CharT> string_type;
2583
2584 string_type __weeks_[14];
2585 string_type __months_[24];
2586 string_type __am_pm_[2];
2587 string_type __c_;
2588 string_type __r_;
2589 string_type __x_;
2590 string_type __X_;
2591
2592 explicit __time_get_storage(const char* __nm);
2593 explicit __time_get_storage(const string& __nm);
2594
2595 _LIBCPP_ALWAYS_INLINE ~__time_get_storage() {}
2596
2597 time_base::dateorder __do_date_order() const;
2598
2599private:
2600 void init(const ctype<_CharT>&);
2601 string_type __analyze(char __fmt, const ctype<_CharT>&);
2602};
2603
2604template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00002605class _LIBCPP_VISIBLE time_get_byname
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002606 : public time_get<_CharT, _InputIterator>,
2607 private __time_get_storage<_CharT>
2608{
2609public:
2610 typedef time_base::dateorder dateorder;
2611 typedef _InputIterator iter_type;
2612 typedef _CharT char_type;
2613 typedef basic_string<char_type> string_type;
2614
Howard Hinnant82894812010-09-22 16:48:34 +00002615 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002616 explicit time_get_byname(const char* __nm, size_t __refs = 0)
2617 : time_get<_CharT, _InputIterator>(__refs),
2618 __time_get_storage<_CharT>(__nm) {}
Howard Hinnant82894812010-09-22 16:48:34 +00002619 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002620 explicit time_get_byname(const string& __nm, size_t __refs = 0)
2621 : time_get<_CharT, _InputIterator>(__refs),
2622 __time_get_storage<_CharT>(__nm) {}
2623
2624protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002625 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002626 ~time_get_byname() {}
2627
Howard Hinnant82894812010-09-22 16:48:34 +00002628 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002629 virtual dateorder do_date_order() const {return this->__do_date_order();}
2630private:
Howard Hinnant82894812010-09-22 16:48:34 +00002631 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002632 virtual const string_type* __weeks() const {return this->__weeks_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002633 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002634 virtual const string_type* __months() const {return this->__months_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002635 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002636 virtual const string_type* __am_pm() const {return this->__am_pm_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002637 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002638 virtual const string_type& __c() const {return this->__c_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002639 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002640 virtual const string_type& __r() const {return this->__r_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002641 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002642 virtual const string_type& __x() const {return this->__x_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002643 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002644 virtual const string_type& __X() const {return this->__X_;}
2645};
2646
2647extern template class time_get_byname<char>;
2648extern template class time_get_byname<wchar_t>;
2649
2650class __time_put
2651{
2652 locale_t __loc_;
2653protected:
Sean Hunt0389c532011-07-12 00:55:04 +00002654#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002655 _LIBCPP_ALWAYS_INLINE __time_put() : __loc_(0) {}
Sean Hunt0389c532011-07-12 00:55:04 +00002656#else // _LIBCPP_STABLE_APPLE_ABI
2657 _LIBCPP_ALWAYS_INLINE __time_put() : __loc_(__cloc()) {}
2658#endif // _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002659 __time_put(const char* __nm);
2660 __time_put(const string& __nm);
2661 ~__time_put();
2662 void __do_put(char* __nb, char*& __ne, const tm* __tm,
2663 char __fmt, char __mod) const;
2664 void __do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
2665 char __fmt, char __mod) const;
2666};
2667
2668template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00002669class _LIBCPP_VISIBLE time_put
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002670 : public locale::facet,
2671 private __time_put
2672{
2673public:
2674 typedef _CharT char_type;
2675 typedef _OutputIterator iter_type;
2676
2677 _LIBCPP_ALWAYS_INLINE
2678 explicit time_put(size_t __refs = 0)
2679 : locale::facet(__refs) {}
2680
2681 iter_type put(iter_type __s, ios_base& __iob, char_type __fl, const tm* __tm,
2682 const char_type* __pb, const char_type* __pe) const;
2683
2684 _LIBCPP_ALWAYS_INLINE
2685 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
2686 const tm* __tm, char __fmt, char __mod = 0) const
2687 {
2688 return do_put(__s, __iob, __fl, __tm, __fmt, __mod);
2689 }
2690
2691 static locale::id id;
2692
2693protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002694 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002695 ~time_put() {}
2696 virtual iter_type do_put(iter_type __s, ios_base&, char_type, const tm* __tm,
2697 char __fmt, char __mod) const;
2698
Howard Hinnant82894812010-09-22 16:48:34 +00002699 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002700 explicit time_put(const char* __nm, size_t __refs)
2701 : locale::facet(__refs),
2702 __time_put(__nm) {}
Howard Hinnant82894812010-09-22 16:48:34 +00002703 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002704 explicit time_put(const string& __nm, size_t __refs)
2705 : locale::facet(__refs),
2706 __time_put(__nm) {}
2707};
2708
2709template <class _CharT, class _OutputIterator>
2710locale::id
2711time_put<_CharT, _OutputIterator>::id;
2712
2713template <class _CharT, class _OutputIterator>
2714_OutputIterator
2715time_put<_CharT, _OutputIterator>::put(iter_type __s, ios_base& __iob,
2716 char_type __fl, const tm* __tm,
2717 const char_type* __pb,
2718 const char_type* __pe) const
2719{
2720 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2721 for (; __pb != __pe; ++__pb)
2722 {
2723 if (__ct.narrow(*__pb, 0) == '%')
2724 {
2725 if (++__pb == __pe)
2726 {
2727 *__s++ = __pb[-1];
2728 break;
2729 }
2730 char __mod = 0;
2731 char __fmt = __ct.narrow(*__pb, 0);
2732 if (__fmt == 'E' || __fmt == 'O')
2733 {
2734 if (++__pb == __pe)
2735 {
2736 *__s++ = __pb[-2];
2737 *__s++ = __pb[-1];
2738 break;
2739 }
2740 __mod = __fmt;
2741 __fmt = __ct.narrow(*__pb, 0);
2742 }
2743 __s = do_put(__s, __iob, __fl, __tm, __fmt, __mod);
2744 }
2745 else
2746 *__s++ = *__pb;
2747 }
2748 return __s;
2749}
2750
2751template <class _CharT, class _OutputIterator>
2752_OutputIterator
2753time_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
2754 char_type, const tm* __tm,
2755 char __fmt, char __mod) const
2756{
2757 char_type __nar[100];
2758 char_type* __nb = __nar;
2759 char_type* __ne = __nb + 100;
2760 __do_put(__nb, __ne, __tm, __fmt, __mod);
Howard Hinnant0949eed2011-06-30 21:18:19 +00002761 return _VSTD::copy(__nb, __ne, __s);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002762}
2763
2764extern template class time_put<char>;
2765extern template class time_put<wchar_t>;
2766
2767template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00002768class _LIBCPP_VISIBLE time_put_byname
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002769 : public time_put<_CharT, _OutputIterator>
2770{
2771public:
2772 _LIBCPP_ALWAYS_INLINE
2773 explicit time_put_byname(const char* __nm, size_t __refs = 0)
2774 : time_put<_CharT, _OutputIterator>(__nm, __refs) {}
2775
2776 _LIBCPP_ALWAYS_INLINE
2777 explicit time_put_byname(const string& __nm, size_t __refs = 0)
2778 : time_put<_CharT, _OutputIterator>(__nm, __refs) {}
2779
2780protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002781 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002782 ~time_put_byname() {}
2783};
2784
2785extern template class time_put_byname<char>;
2786extern template class time_put_byname<wchar_t>;
2787
2788// money_base
2789
Howard Hinnant82894812010-09-22 16:48:34 +00002790class _LIBCPP_VISIBLE money_base
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002791{
2792public:
2793 enum part {none, space, symbol, sign, value};
2794 struct pattern {char field[4];};
2795
2796 _LIBCPP_ALWAYS_INLINE money_base() {}
2797};
2798
2799// moneypunct
2800
2801template <class _CharT, bool _International = false>
Howard Hinnant82894812010-09-22 16:48:34 +00002802class _LIBCPP_VISIBLE moneypunct
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002803 : public locale::facet,
2804 public money_base
2805{
2806public:
2807 typedef _CharT char_type;
2808 typedef basic_string<char_type> string_type;
2809
Howard Hinnant82894812010-09-22 16:48:34 +00002810 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002811 explicit moneypunct(size_t __refs = 0)
2812 : locale::facet(__refs) {}
2813
2814 _LIBCPP_ALWAYS_INLINE char_type decimal_point() const {return do_decimal_point();}
2815 _LIBCPP_ALWAYS_INLINE char_type thousands_sep() const {return do_thousands_sep();}
2816 _LIBCPP_ALWAYS_INLINE string grouping() const {return do_grouping();}
2817 _LIBCPP_ALWAYS_INLINE string_type curr_symbol() const {return do_curr_symbol();}
2818 _LIBCPP_ALWAYS_INLINE string_type positive_sign() const {return do_positive_sign();}
2819 _LIBCPP_ALWAYS_INLINE string_type negative_sign() const {return do_negative_sign();}
2820 _LIBCPP_ALWAYS_INLINE int frac_digits() const {return do_frac_digits();}
2821 _LIBCPP_ALWAYS_INLINE pattern pos_format() const {return do_pos_format();}
2822 _LIBCPP_ALWAYS_INLINE pattern neg_format() const {return do_neg_format();}
2823
2824 static locale::id id;
2825 static const bool intl = _International;
2826
2827protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002828 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002829 ~moneypunct() {}
2830
2831 virtual char_type do_decimal_point() const {return numeric_limits<char_type>::max();}
2832 virtual char_type do_thousands_sep() const {return numeric_limits<char_type>::max();}
2833 virtual string do_grouping() const {return string();}
2834 virtual string_type do_curr_symbol() const {return string_type();}
2835 virtual string_type do_positive_sign() const {return string_type();}
2836 virtual string_type do_negative_sign() const {return string_type(1, '-');}
2837 virtual int do_frac_digits() const {return 0;}
2838 virtual pattern do_pos_format() const
2839 {pattern __p = {symbol, sign, none, value}; return __p;}
2840 virtual pattern do_neg_format() const
2841 {pattern __p = {symbol, sign, none, value}; return __p;}
2842};
2843
2844template <class _CharT, bool _International>
2845locale::id
2846moneypunct<_CharT, _International>::id;
2847
2848extern template class moneypunct<char, false>;
2849extern template class moneypunct<char, true>;
2850extern template class moneypunct<wchar_t, false>;
2851extern template class moneypunct<wchar_t, true>;
2852
2853// moneypunct_byname
2854
2855template <class _CharT, bool _International = false>
Howard Hinnant82894812010-09-22 16:48:34 +00002856class _LIBCPP_VISIBLE moneypunct_byname
2857 : public moneypunct<_CharT, _International>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002858{
2859public:
2860 typedef money_base::pattern pattern;
2861 typedef _CharT char_type;
2862 typedef basic_string<char_type> string_type;
2863
2864 _LIBCPP_ALWAYS_INLINE
2865 explicit moneypunct_byname(const char* __nm, size_t __refs = 0)
2866 : moneypunct<_CharT, _International>(__refs) {init(__nm);}
2867
2868 _LIBCPP_ALWAYS_INLINE
2869 explicit moneypunct_byname(const string& __nm, size_t __refs = 0)
2870 : moneypunct<_CharT, _International>(__refs) {init(__nm.c_str());}
2871
2872protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002873 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002874 ~moneypunct_byname() {}
2875
2876 virtual char_type do_decimal_point() const {return __decimal_point_;}
2877 virtual char_type do_thousands_sep() const {return __thousands_sep_;}
2878 virtual string do_grouping() const {return __grouping_;}
2879 virtual string_type do_curr_symbol() const {return __curr_symbol_;}
2880 virtual string_type do_positive_sign() const {return __positive_sign_;}
2881 virtual string_type do_negative_sign() const {return __negative_sign_;}
2882 virtual int do_frac_digits() const {return __frac_digits_;}
2883 virtual pattern do_pos_format() const {return __pos_format_;}
2884 virtual pattern do_neg_format() const {return __neg_format_;}
2885
2886private:
2887 char_type __decimal_point_;
2888 char_type __thousands_sep_;
2889 string __grouping_;
2890 string_type __curr_symbol_;
2891 string_type __positive_sign_;
2892 string_type __negative_sign_;
2893 int __frac_digits_;
2894 pattern __pos_format_;
2895 pattern __neg_format_;
2896
2897 void init(const char*);
2898};
2899
2900template<> void moneypunct_byname<char, false>::init(const char*);
2901template<> void moneypunct_byname<char, true>::init(const char*);
2902template<> void moneypunct_byname<wchar_t, false>::init(const char*);
2903template<> void moneypunct_byname<wchar_t, true>::init(const char*);
2904
2905extern template class moneypunct_byname<char, false>;
2906extern template class moneypunct_byname<char, true>;
2907extern template class moneypunct_byname<wchar_t, false>;
2908extern template class moneypunct_byname<wchar_t, true>;
2909
2910// money_get
2911
2912template <class _CharT>
2913class __money_get
2914{
2915protected:
2916 typedef _CharT char_type;
2917 typedef basic_string<char_type> string_type;
2918
2919 _LIBCPP_ALWAYS_INLINE __money_get() {}
2920
2921 static void __gather_info(bool __intl, const locale& __loc,
2922 money_base::pattern& __pat, char_type& __dp,
2923 char_type& __ts, string& __grp,
2924 string_type& __sym, string_type& __psn,
2925 string_type& __nsn, int& __fd);
2926};
2927
2928template <class _CharT>
2929void
2930__money_get<_CharT>::__gather_info(bool __intl, const locale& __loc,
2931 money_base::pattern& __pat, char_type& __dp,
2932 char_type& __ts, string& __grp,
2933 string_type& __sym, string_type& __psn,
2934 string_type& __nsn, int& __fd)
2935{
2936 if (__intl)
2937 {
2938 const moneypunct<char_type, true>& __mp =
2939 use_facet<moneypunct<char_type, true> >(__loc);
2940 __pat = __mp.neg_format();
2941 __nsn = __mp.negative_sign();
2942 __psn = __mp.positive_sign();
2943 __dp = __mp.decimal_point();
2944 __ts = __mp.thousands_sep();
2945 __grp = __mp.grouping();
2946 __sym = __mp.curr_symbol();
2947 __fd = __mp.frac_digits();
2948 }
2949 else
2950 {
2951 const moneypunct<char_type, false>& __mp =
2952 use_facet<moneypunct<char_type, false> >(__loc);
2953 __pat = __mp.neg_format();
2954 __nsn = __mp.negative_sign();
2955 __psn = __mp.positive_sign();
2956 __dp = __mp.decimal_point();
2957 __ts = __mp.thousands_sep();
2958 __grp = __mp.grouping();
2959 __sym = __mp.curr_symbol();
2960 __fd = __mp.frac_digits();
2961 }
2962}
2963
2964extern template class __money_get<char>;
2965extern template class __money_get<wchar_t>;
2966
2967template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00002968class _LIBCPP_VISIBLE money_get
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002969 : public locale::facet,
2970 private __money_get<_CharT>
2971{
2972public:
2973 typedef _CharT char_type;
2974 typedef _InputIterator iter_type;
2975 typedef basic_string<char_type> string_type;
2976
2977 _LIBCPP_ALWAYS_INLINE
2978 explicit money_get(size_t __refs = 0)
2979 : locale::facet(__refs) {}
2980
2981 _LIBCPP_ALWAYS_INLINE
2982 iter_type get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob,
2983 ios_base::iostate& __err, long double& __v) const
2984 {
2985 return do_get(__b, __e, __intl, __iob, __err, __v);
2986 }
2987
2988 _LIBCPP_ALWAYS_INLINE
2989 iter_type get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob,
2990 ios_base::iostate& __err, string_type& __v) const
2991 {
2992 return do_get(__b, __e, __intl, __iob, __err, __v);
2993 }
2994
2995 static locale::id id;
2996
2997protected:
2998
Howard Hinnant82894812010-09-22 16:48:34 +00002999 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003000 ~money_get() {}
Howard Hinnant324bb032010-08-22 00:02:43 +00003001
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003002 virtual iter_type do_get(iter_type __b, iter_type __e, bool __intl,
3003 ios_base& __iob, ios_base::iostate& __err,
3004 long double& __v) const;
3005 virtual iter_type do_get(iter_type __b, iter_type __e, bool __intl,
3006 ios_base& __iob, ios_base::iostate& __err,
3007 string_type& __v) const;
3008
3009private:
3010 static bool __do_get(iter_type& __b, iter_type __e,
3011 bool __intl, const locale& __loc,
3012 ios_base::fmtflags __flags, ios_base::iostate& __err,
3013 bool& __neg, const ctype<char_type>& __ct,
3014 unique_ptr<char_type, void(*)(void*)>& __wb,
3015 char_type*& __wn, char_type* __we);
3016};
3017
3018template <class _CharT, class _InputIterator>
3019locale::id
3020money_get<_CharT, _InputIterator>::id;
3021
3022void __do_nothing(void*);
3023
3024template <class _Tp>
3025_LIBCPP_HIDDEN
3026void
3027__double_or_nothing(unique_ptr<_Tp, void(*)(void*)>& __b, _Tp*& __n, _Tp*& __e)
3028{
3029 bool __owns = __b.get_deleter() != __do_nothing;
3030 size_t __cur_cap = (__e-__b.get()) * sizeof(_Tp);
3031 size_t __new_cap = __cur_cap < numeric_limits<size_t>::max() / 2 ?
3032 2 * __cur_cap : numeric_limits<size_t>::max();
3033 size_t __n_off = __n - __b.get();
3034 _Tp* __t = (_Tp*)realloc(__owns ? __b.get() : 0, __new_cap);
3035 if (__t == 0)
3036 __throw_bad_alloc();
3037 if (__owns)
3038 __b.release();
3039 __b = unique_ptr<_Tp, void(*)(void*)>(__t, free);
3040 __new_cap /= sizeof(_Tp);
3041 __n = __b.get() + __n_off;
3042 __e = __b.get() + __new_cap;
3043}
3044
3045// true == success
3046template <class _CharT, class _InputIterator>
3047bool
3048money_get<_CharT, _InputIterator>::__do_get(iter_type& __b, iter_type __e,
3049 bool __intl, const locale& __loc,
3050 ios_base::fmtflags __flags,
3051 ios_base::iostate& __err,
3052 bool& __neg,
3053 const ctype<char_type>& __ct,
3054 unique_ptr<char_type, void(*)(void*)>& __wb,
3055 char_type*& __wn, char_type* __we)
3056{
3057 const unsigned __bz = 100;
3058 unsigned __gbuf[__bz];
3059 unique_ptr<unsigned, void(*)(void*)> __gb(__gbuf, __do_nothing);
3060 unsigned* __gn = __gb.get();
3061 unsigned* __ge = __gn + __bz;
3062 money_base::pattern __pat;
3063 char_type __dp;
3064 char_type __ts;
3065 string __grp;
3066 string_type __sym;
3067 string_type __psn;
3068 string_type __nsn;
3069 int __fd;
3070 __money_get<_CharT>::__gather_info(__intl, __loc, __pat, __dp, __ts, __grp,
3071 __sym, __psn, __nsn, __fd);
3072 const string_type* __trailing_sign = 0;
3073 __wn = __wb.get();
3074 for (unsigned __p = 0; __p < 4 && __b != __e; ++__p)
3075 {
3076 switch (__pat.field[__p])
3077 {
3078 case money_base::space:
3079 if (__p != 3)
3080 {
3081 if (__ct.is(ctype_base::space, *__b))
3082 ++__b;
3083 else
3084 {
3085 __err |= ios_base::failbit;
3086 return false;
3087 }
3088 }
Howard Hinnant324bb032010-08-22 00:02:43 +00003089 // drop through
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003090 case money_base::none:
3091 if (__p != 3)
3092 {
3093 while (__b != __e && __ct.is(ctype_base::space, *__b))
3094 ++__b;
3095 }
3096 break;
3097 case money_base::sign:
3098 if (__psn.size() + __nsn.size() > 0)
3099 {
3100 if (__psn.size() == 0 || __nsn.size() == 0)
3101 { // sign is optional
3102 if (__psn.size() > 0)
3103 { // __nsn.size() == 0
3104 if (*__b == __psn[0])
3105 {
3106 ++__b;
3107 if (__psn.size() > 1)
3108 __trailing_sign = &__psn;
3109 }
3110 else
3111 __neg = true;
3112 }
3113 else if (*__b == __nsn[0]) // __nsn.size() > 0 && __psn.size() == 0
3114 {
3115 ++__b;
3116 __neg = true;
3117 if (__nsn.size() > 1)
3118 __trailing_sign = &__nsn;
3119 }
3120 }
3121 else // sign is required
3122 {
3123 if (*__b == __psn[0])
3124 {
3125 ++__b;
3126 if (__psn.size() > 1)
3127 __trailing_sign = &__psn;
3128 }
3129 else if (*__b == __nsn[0])
3130 {
3131 ++__b;
3132 __neg = true;
3133 if (__nsn.size() > 1)
3134 __trailing_sign = &__nsn;
3135 }
3136 else
3137 {
3138 __err |= ios_base::failbit;
3139 return false;
3140 }
3141 }
3142 }
3143 break;
3144 case money_base::symbol:
3145 {
3146 bool __more_needed = __trailing_sign ||
3147 (__p < 2) ||
3148 (__p == 2 && __pat.field[3] != static_cast<char>(money_base::none));
3149 bool __sb = __flags & ios_base::showbase;
3150 if (__sb || __more_needed)
3151 {
3152 ios_base::iostate __et = ios_base::goodbit;
3153 string_type* __k = __scan_keyword(__b, __e, &__sym, &__sym+1,
3154 __ct, __et);
3155 if (__sb && __k != &__sym)
3156 {
3157 __err |= ios_base::failbit;
3158 return false;
3159 }
3160 }
3161 }
3162 break;
3163 case money_base::value:
3164 {
3165 unsigned __ng = 0;
3166 for (; __b != __e; ++__b)
3167 {
3168 char_type __c = *__b;
3169 if (__ct.is(ctype_base::digit, __c))
3170 {
3171 if (__wn == __we)
3172 __double_or_nothing(__wb, __wn, __we);
3173 *__wn++ = __c;
3174 ++__ng;
3175 }
3176 else if (__grp.size() > 0 && __ng > 0 && __c == __ts)
3177 {
3178 if (__gn == __ge)
3179 __double_or_nothing(__gb, __gn, __ge);
3180 *__gn++ = __ng;
3181 __ng = 0;
3182 }
3183 else
3184 break;
3185 }
3186 if (__gb.get() != __gn && __ng > 0)
3187 {
3188 if (__gn == __ge)
3189 __double_or_nothing(__gb, __gn, __ge);
3190 *__gn++ = __ng;
3191 }
3192 if (__fd > 0)
3193 {
3194 if (__b == __e || *__b != __dp)
3195 {
3196 __err |= ios_base::failbit;
3197 return false;
3198 }
3199 for (++__b; __fd > 0; --__fd, ++__b)
3200 {
3201 if (__b == __e || !__ct.is(ctype_base::digit, *__b))
3202 {
3203 __err |= ios_base::failbit;
3204 return false;
3205 }
3206 if (__wn == __we)
3207 __double_or_nothing(__wb, __wn, __we);
3208 *__wn++ = *__b;
3209 }
3210 }
3211 if (__wn == __wb.get())
3212 {
3213 __err |= ios_base::failbit;
3214 return false;
3215 }
3216 }
3217 break;
3218 }
3219 }
3220 if (__trailing_sign)
3221 {
3222 for (unsigned __i = 1; __i < __trailing_sign->size(); ++__i, ++__b)
3223 {
3224 if (__b == __e || *__b != (*__trailing_sign)[__i])
3225 {
3226 __err |= ios_base::failbit;
3227 return false;
3228 }
3229 }
3230 }
3231 if (__gb.get() != __gn)
3232 {
3233 ios_base::iostate __et = ios_base::goodbit;
3234 __check_grouping(__grp, __gb.get(), __gn, __et);
3235 if (__et)
3236 {
3237 __err |= ios_base::failbit;
3238 return false;
3239 }
3240 }
3241 return true;
3242}
3243
3244template <class _CharT, class _InputIterator>
3245_InputIterator
3246money_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
3247 bool __intl, ios_base& __iob,
3248 ios_base::iostate& __err,
3249 long double& __v) const
3250{
3251 const unsigned __bz = 100;
3252 char_type __wbuf[__bz];
3253 unique_ptr<char_type, void(*)(void*)> __wb(__wbuf, __do_nothing);
3254 char_type* __wn;
3255 char_type* __we = __wbuf + __bz;
3256 locale __loc = __iob.getloc();
3257 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3258 bool __neg = false;
3259 if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct,
3260 __wb, __wn, __we))
3261 {
3262 const char __src[] = "0123456789";
3263 char_type __atoms[sizeof(__src)-1];
3264 __ct.widen(__src, __src + (sizeof(__src)-1), __atoms);
3265 char __nbuf[__bz];
3266 char* __nc = __nbuf;
3267 unique_ptr<char, void(*)(void*)> __h(0, free);
3268 if (__wn - __wb.get() > __bz-2)
3269 {
3270 __h.reset((char*)malloc(__wn - __wb.get() + 2));
3271 if (__h.get() == 0)
3272 __throw_bad_alloc();
3273 __nc = __h.get();
3274 }
3275 if (__neg)
3276 *__nc++ = '-';
3277 for (const char_type* __w = __wb.get(); __w < __wn; ++__w, ++__nc)
3278 *__nc = __src[find(__atoms, __atoms+sizeof(__atoms), *__w) - __atoms];
3279 *__nc = char();
3280 if (sscanf(__nbuf, "%Lf", &__v) != 1)
3281 __throw_runtime_error("money_get error");
3282 }
3283 if (__b == __e)
3284 __err |= ios_base::eofbit;
3285 return __b;
3286}
3287
3288template <class _CharT, class _InputIterator>
3289_InputIterator
3290money_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
3291 bool __intl, ios_base& __iob,
3292 ios_base::iostate& __err,
3293 string_type& __v) const
3294{
3295 const unsigned __bz = 100;
3296 char_type __wbuf[__bz];
3297 unique_ptr<char_type, void(*)(void*)> __wb(__wbuf, __do_nothing);
3298 char_type* __wn;
3299 char_type* __we = __wbuf + __bz;
3300 locale __loc = __iob.getloc();
3301 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3302 bool __neg = false;
3303 if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct,
3304 __wb, __wn, __we))
3305 {
3306 __v.clear();
3307 if (__neg)
3308 __v.push_back(__ct.widen('-'));
3309 char_type __z = __ct.widen('0');
3310 char_type* __w;
3311 for (__w = __wb.get(); __w < __wn-1; ++__w)
3312 if (*__w != __z)
3313 break;
3314 __v.append(__w, __wn);
3315 }
3316 if (__b == __e)
3317 __err |= ios_base::eofbit;
3318 return __b;
3319}
3320
3321extern template class money_get<char>;
3322extern template class money_get<wchar_t>;
3323
3324// money_put
3325
3326template <class _CharT>
3327class __money_put
3328{
3329protected:
3330 typedef _CharT char_type;
3331 typedef basic_string<char_type> string_type;
3332
3333 _LIBCPP_ALWAYS_INLINE __money_put() {}
3334
3335 static void __gather_info(bool __intl, bool __neg, const locale& __loc,
3336 money_base::pattern& __pat, char_type& __dp,
3337 char_type& __ts, string& __grp,
3338 string_type& __sym, string_type& __sn,
3339 int& __fd);
3340 static void __format(char_type* __mb, char_type*& __mi, char_type*& __me,
3341 ios_base::fmtflags __flags,
3342 const char_type* __db, const char_type* __de,
3343 const ctype<char_type>& __ct, bool __neg,
3344 const money_base::pattern& __pat, char_type __dp,
3345 char_type __ts, const string& __grp,
3346 const string_type& __sym, const string_type& __sn,
3347 int __fd);
3348};
3349
3350template <class _CharT>
3351void
3352__money_put<_CharT>::__gather_info(bool __intl, bool __neg, const locale& __loc,
3353 money_base::pattern& __pat, char_type& __dp,
3354 char_type& __ts, string& __grp,
3355 string_type& __sym, string_type& __sn,
3356 int& __fd)
3357{
3358 if (__intl)
3359 {
3360 const moneypunct<char_type, true>& __mp =
3361 use_facet<moneypunct<char_type, true> >(__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 else
3379 {
3380 const moneypunct<char_type, false>& __mp =
3381 use_facet<moneypunct<char_type, false> >(__loc);
3382 if (__neg)
3383 {
3384 __pat = __mp.neg_format();
3385 __sn = __mp.negative_sign();
3386 }
3387 else
3388 {
3389 __pat = __mp.pos_format();
3390 __sn = __mp.positive_sign();
3391 }
3392 __dp = __mp.decimal_point();
3393 __ts = __mp.thousands_sep();
3394 __grp = __mp.grouping();
3395 __sym = __mp.curr_symbol();
3396 __fd = __mp.frac_digits();
3397 }
3398}
3399
3400template <class _CharT>
3401void
3402__money_put<_CharT>::__format(char_type* __mb, char_type*& __mi, char_type*& __me,
3403 ios_base::fmtflags __flags,
3404 const char_type* __db, const char_type* __de,
3405 const ctype<char_type>& __ct, bool __neg,
3406 const money_base::pattern& __pat, char_type __dp,
3407 char_type __ts, const string& __grp,
3408 const string_type& __sym, const string_type& __sn,
3409 int __fd)
3410{
3411 __me = __mb;
3412 for (unsigned __p = 0; __p < 4; ++__p)
3413 {
3414 switch (__pat.field[__p])
3415 {
3416 case money_base::none:
3417 __mi = __me;
3418 break;
3419 case money_base::space:
3420 __mi = __me;
3421 *__me++ = __ct.widen(' ');
3422 break;
3423 case money_base::sign:
3424 if (!__sn.empty())
3425 *__me++ = __sn[0];
3426 break;
3427 case money_base::symbol:
3428 if (!__sym.empty() && (__flags & ios_base::showbase))
Howard Hinnant0949eed2011-06-30 21:18:19 +00003429 __me = _VSTD::copy(__sym.begin(), __sym.end(), __me);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003430 break;
3431 case money_base::value:
3432 {
3433 // remember start of value so we can reverse it
3434 char_type* __t = __me;
3435 // find beginning of digits
3436 if (__neg)
3437 ++__db;
3438 // find end of digits
3439 const char_type* __d;
3440 for (__d = __db; __d < __de; ++__d)
3441 if (!__ct.is(ctype_base::digit, *__d))
3442 break;
3443 // print fractional part
3444 if (__fd > 0)
3445 {
3446 int __f;
3447 for (__f = __fd; __d > __db && __f > 0; --__f)
3448 *__me++ = *--__d;
3449 char_type __z = __f > 0 ? __ct.widen('0') : char_type();
3450 for (; __f > 0; --__f)
3451 *__me++ = __z;
3452 *__me++ = __dp;
3453 }
3454 // print units part
3455 if (__d == __db)
3456 {
3457 *__me++ = __ct.widen('0');
3458 }
3459 else
3460 {
3461 unsigned __ng = 0;
3462 unsigned __ig = 0;
3463 unsigned __gl = __grp.empty() ? numeric_limits<unsigned>::max()
3464 : static_cast<unsigned>(__grp[__ig]);
3465 while (__d != __db)
3466 {
3467 if (__ng == __gl)
3468 {
3469 *__me++ = __ts;
3470 __ng = 0;
3471 if (++__ig < __grp.size())
3472 __gl = __grp[__ig] == numeric_limits<char>::max() ?
3473 numeric_limits<unsigned>::max() :
3474 static_cast<unsigned>(__grp[__ig]);
3475 }
3476 *__me++ = *--__d;
3477 ++__ng;
3478 }
3479 }
3480 // reverse it
3481 reverse(__t, __me);
3482 }
3483 break;
3484 }
3485 }
3486 // print rest of sign, if any
3487 if (__sn.size() > 1)
Howard Hinnant0949eed2011-06-30 21:18:19 +00003488 __me = _VSTD::copy(__sn.begin()+1, __sn.end(), __me);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003489 // set alignment
3490 if ((__flags & ios_base::adjustfield) == ios_base::left)
3491 __mi = __me;
3492 else if ((__flags & ios_base::adjustfield) != ios_base::internal)
3493 __mi = __mb;
3494}
3495
3496extern template class __money_put<char>;
3497extern template class __money_put<wchar_t>;
3498
3499template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00003500class _LIBCPP_VISIBLE money_put
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003501 : public locale::facet,
3502 private __money_put<_CharT>
3503{
3504public:
3505 typedef _CharT char_type;
3506 typedef _OutputIterator iter_type;
3507 typedef basic_string<char_type> string_type;
3508
3509 _LIBCPP_ALWAYS_INLINE
3510 explicit money_put(size_t __refs = 0)
3511 : locale::facet(__refs) {}
3512
3513 _LIBCPP_ALWAYS_INLINE
3514 iter_type put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl,
3515 long double __units) const
3516 {
3517 return do_put(__s, __intl, __iob, __fl, __units);
3518 }
3519
3520 _LIBCPP_ALWAYS_INLINE
3521 iter_type put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl,
3522 const string_type& __digits) const
3523 {
3524 return do_put(__s, __intl, __iob, __fl, __digits);
3525 }
3526
3527 static locale::id id;
3528
3529protected:
Howard Hinnant82894812010-09-22 16:48:34 +00003530 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003531 ~money_put() {}
3532
3533 virtual iter_type do_put(iter_type __s, bool __intl, ios_base& __iob,
3534 char_type __fl, long double __units) const;
3535 virtual iter_type do_put(iter_type __s, bool __intl, ios_base& __iob,
3536 char_type __fl, const string_type& __digits) const;
3537};
3538
3539template <class _CharT, class _OutputIterator>
3540locale::id
3541money_put<_CharT, _OutputIterator>::id;
3542
3543template <class _CharT, class _OutputIterator>
3544_OutputIterator
3545money_put<_CharT, _OutputIterator>::do_put(iter_type __s, bool __intl,
3546 ios_base& __iob, char_type __fl,
3547 long double __units) const
3548{
3549 // convert to char
3550 const size_t __bs = 100;
3551 char __buf[__bs];
3552 char* __bb = __buf;
3553 char_type __digits[__bs];
3554 char_type* __db = __digits;
3555 size_t __n = snprintf(__bb, __bs, "%.0Lf", __units);
3556 unique_ptr<char, void(*)(void*)> __hn(0, free);
3557 unique_ptr<char_type, void(*)(void*)> __hd(0, free);
3558 // secure memory for digit storage
3559 if (__n > __bs-1)
3560 {
Sean Huntf3907e62011-07-15 05:40:33 +00003561#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantbcbbd4d2011-07-15 14:46:11 +00003562 __n = asprintf_l(&__bb, 0, "%.0Lf", __units);
Sean Huntf3907e62011-07-15 05:40:33 +00003563#else
3564 __n = __asprintf_l(&__bb, __cloc(), "%.0Lf", __units);
3565#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003566 if (__bb == 0)
3567 __throw_bad_alloc();
3568 __hn.reset(__bb);
3569 __hd.reset((char_type*)malloc(__n * sizeof(char_type)));
3570 if (__hd == 0)
3571 __throw_bad_alloc();
3572 __db = __hd.get();
3573 }
3574 // gather info
3575 locale __loc = __iob.getloc();
3576 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3577 __ct.widen(__bb, __bb + __n, __db);
3578 bool __neg = __n > 0 && __bb[0] == '-';
3579 money_base::pattern __pat;
3580 char_type __dp;
3581 char_type __ts;
3582 string __grp;
3583 string_type __sym;
3584 string_type __sn;
3585 int __fd;
3586 this->__gather_info(__intl, __neg, __loc, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3587 // secure memory for formatting
3588 char_type __mbuf[__bs];
3589 char_type* __mb = __mbuf;
3590 unique_ptr<char_type, void(*)(void*)> __hw(0, free);
3591 size_t __exn = static_cast<int>(__n) > __fd ?
3592 (__n - __fd) * 2 + __sn.size() + __sym.size() + __fd + 1
3593 : __sn.size() + __sym.size() + __fd + 2;
3594 if (__exn > __bs)
3595 {
3596 __hw.reset((char_type*)malloc(__exn * sizeof(char_type)));
3597 __mb = __hw.get();
3598 if (__mb == 0)
3599 __throw_bad_alloc();
3600 }
3601 // format
3602 char_type* __mi;
3603 char_type* __me;
3604 this->__format(__mb, __mi, __me, __iob.flags(),
3605 __db, __db + __n, __ct,
3606 __neg, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3607 return __pad_and_output(__s, __mb, __mi, __me, __iob, __fl);
3608}
3609
3610template <class _CharT, class _OutputIterator>
3611_OutputIterator
3612money_put<_CharT, _OutputIterator>::do_put(iter_type __s, bool __intl,
3613 ios_base& __iob, char_type __fl,
3614 const string_type& __digits) const
3615{
3616 // gather info
3617 locale __loc = __iob.getloc();
3618 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3619 bool __neg = __digits.size() > 0 && __digits[0] == __ct.widen('-');
3620 money_base::pattern __pat;
3621 char_type __dp;
3622 char_type __ts;
3623 string __grp;
3624 string_type __sym;
3625 string_type __sn;
3626 int __fd;
3627 this->__gather_info(__intl, __neg, __loc, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3628 // secure memory for formatting
3629 char_type __mbuf[100];
3630 char_type* __mb = __mbuf;
3631 unique_ptr<char_type, void(*)(void*)> __h(0, free);
3632 size_t __exn = __digits.size() > __fd ?
3633 (__digits.size() - __fd) * 2 + __sn.size() + __sym.size() + __fd + 1
3634 : __sn.size() + __sym.size() + __fd + 2;
3635 if (__exn > 100)
3636 {
3637 __h.reset((char_type*)malloc(__exn * sizeof(char_type)));
3638 __mb = __h.get();
3639 if (__mb == 0)
3640 __throw_bad_alloc();
3641 }
3642 // format
3643 char_type* __mi;
3644 char_type* __me;
3645 this->__format(__mb, __mi, __me, __iob.flags(),
3646 __digits.data(), __digits.data() + __digits.size(), __ct,
3647 __neg, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3648 return __pad_and_output(__s, __mb, __mi, __me, __iob, __fl);
3649}
3650
3651extern template class money_put<char>;
3652extern template class money_put<wchar_t>;
3653
3654// messages
3655
Howard Hinnant82894812010-09-22 16:48:34 +00003656class _LIBCPP_VISIBLE messages_base
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003657{
3658public:
Howard Hinnantb2080c72011-02-25 00:51:08 +00003659 typedef ptrdiff_t catalog;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003660
3661 _LIBCPP_ALWAYS_INLINE messages_base() {}
3662};
3663
3664template <class _CharT>
Howard Hinnant82894812010-09-22 16:48:34 +00003665class _LIBCPP_VISIBLE messages
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003666 : public locale::facet,
3667 public messages_base
3668{
3669public:
3670 typedef _CharT char_type;
3671 typedef basic_string<_CharT> string_type;
3672
3673 _LIBCPP_ALWAYS_INLINE
3674 explicit messages(size_t __refs = 0)
3675 : locale::facet(__refs) {}
3676
3677 _LIBCPP_ALWAYS_INLINE
3678 catalog open(const basic_string<char>& __nm, const locale& __loc) const
3679 {
3680 return do_open(__nm, __loc);
3681 }
3682
3683 _LIBCPP_ALWAYS_INLINE
3684 string_type get(catalog __c, int __set, int __msgid,
3685 const string_type& __dflt) const
3686 {
3687 return do_get(__c, __set, __msgid, __dflt);
3688 }
3689
3690 _LIBCPP_ALWAYS_INLINE
3691 void close(catalog __c) const
3692 {
3693 do_close(__c);
3694 }
3695
3696 static locale::id id;
3697
3698protected:
Howard Hinnant82894812010-09-22 16:48:34 +00003699 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003700 ~messages() {}
3701
3702 virtual catalog do_open(const basic_string<char>&, const locale&) const;
3703 virtual string_type do_get(catalog, int __set, int __msgid,
3704 const string_type& __dflt) const;
3705 virtual void do_close(catalog) const;
3706};
3707
3708template <class _CharT>
3709locale::id
3710messages<_CharT>::id;
3711
3712template <class _CharT>
3713typename messages<_CharT>::catalog
3714messages<_CharT>::do_open(const basic_string<char>& __nm, const locale&) const
3715{
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00003716#if _WIN32
3717 return -1;
3718#else // _WIN32
Howard Hinnantb2080c72011-02-25 00:51:08 +00003719 catalog __cat = reinterpret_cast<catalog>(catopen(__nm.c_str(), NL_CAT_LOCALE));
3720 if (__cat != -1)
3721 __cat = static_cast<catalog>((static_cast<size_t>(__cat) >> 1));
3722 return __cat;
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00003723#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003724}
3725
3726template <class _CharT>
3727typename messages<_CharT>::string_type
3728messages<_CharT>::do_get(catalog __c, int __set, int __msgid,
3729 const string_type& __dflt) const
3730{
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00003731#if _WIN32
3732 return __dflt;
3733#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003734 string __ndflt;
3735 __narrow_to_utf8<sizeof(char_type)*__CHAR_BIT__>()(back_inserter(__ndflt),
3736 __dflt.c_str(),
3737 __dflt.c_str() + __dflt.size());
Howard Hinnantb2080c72011-02-25 00:51:08 +00003738 if (__c != -1)
3739 __c <<= 1;
3740 nl_catd __cat = reinterpret_cast<nl_catd>(__c);
3741 char* __n = catgets(__cat, __set, __msgid, __ndflt.c_str());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003742 string_type __w;
3743 __widen_from_utf8<sizeof(char_type)*__CHAR_BIT__>()(back_inserter(__w),
3744 __n, __n + strlen(__n));
3745 return __w;
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00003746#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003747}
3748
3749template <class _CharT>
3750void
3751messages<_CharT>::do_close(catalog __c) const
3752{
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00003753#if !_WIN32
Howard Hinnantb2080c72011-02-25 00:51:08 +00003754 if (__c != -1)
3755 __c <<= 1;
3756 nl_catd __cat = reinterpret_cast<nl_catd>(__c);
3757 catclose(__cat);
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00003758#endif // !_WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003759}
3760
3761extern template class messages<char>;
3762extern template class messages<wchar_t>;
3763
3764template <class _CharT>
Howard Hinnant82894812010-09-22 16:48:34 +00003765class _LIBCPP_VISIBLE messages_byname
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003766 : public messages<_CharT>
3767{
3768public:
3769 typedef messages_base::catalog catalog;
3770 typedef basic_string<_CharT> string_type;
3771
3772 _LIBCPP_ALWAYS_INLINE
3773 explicit messages_byname(const char*, size_t __refs = 0)
3774 : messages<_CharT>(__refs) {}
3775
3776 _LIBCPP_ALWAYS_INLINE
3777 explicit messages_byname(const string&, size_t __refs = 0)
3778 : messages<_CharT>(__refs) {}
3779
3780protected:
Howard Hinnant82894812010-09-22 16:48:34 +00003781 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003782 ~messages_byname() {}
3783};
3784
3785extern template class messages_byname<char>;
3786extern template class messages_byname<wchar_t>;
3787
Howard Hinnantd23b4642010-05-31 20:58:54 +00003788template<class _Codecvt, class _Elem = wchar_t,
3789 class _Wide_alloc = allocator<_Elem>,
3790 class _Byte_alloc = allocator<char> >
Howard Hinnant82894812010-09-22 16:48:34 +00003791class _LIBCPP_VISIBLE wstring_convert
Howard Hinnantd23b4642010-05-31 20:58:54 +00003792{
3793public:
3794 typedef basic_string<char, char_traits<char>, _Byte_alloc> byte_string;
3795 typedef basic_string<_Elem, char_traits<_Elem>, _Wide_alloc> wide_string;
3796 typedef typename _Codecvt::state_type state_type;
3797 typedef typename wide_string::traits_type::int_type int_type;
3798
3799private:
3800 byte_string __byte_err_string_;
3801 wide_string __wide_err_string_;
3802 _Codecvt* __cvtptr_;
3803 state_type __cvtstate_;
3804 size_t __cvtcount_;
3805
3806 wstring_convert(const wstring_convert& __wc);
3807 wstring_convert& operator=(const wstring_convert& __wc);
3808public:
3809 wstring_convert(_Codecvt* __pcvt = new _Codecvt);
3810 wstring_convert(_Codecvt* __pcvt, state_type __state);
3811 wstring_convert(const byte_string& __byte_err,
3812 const wide_string& __wide_err = wide_string());
Howard Hinnant73d21a42010-09-04 23:28:19 +00003813#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantd23b4642010-05-31 20:58:54 +00003814 wstring_convert(wstring_convert&& __wc);
3815#endif
3816 ~wstring_convert();
3817
Howard Hinnant82894812010-09-22 16:48:34 +00003818 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003819 wide_string from_bytes(char __byte)
3820 {return from_bytes(&__byte, &__byte+1);}
Howard Hinnant82894812010-09-22 16:48:34 +00003821 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003822 wide_string from_bytes(const char* __ptr)
3823 {return from_bytes(__ptr, __ptr + char_traits<char>::length(__ptr));}
Howard Hinnant82894812010-09-22 16:48:34 +00003824 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003825 wide_string from_bytes(const byte_string& __str)
3826 {return from_bytes(__str.data(), __str.data() + __str.size());}
3827 wide_string from_bytes(const char* __first, const char* __last);
3828
Howard Hinnant82894812010-09-22 16:48:34 +00003829 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003830 byte_string to_bytes(_Elem __wchar)
3831 {return to_bytes(&__wchar, &__wchar+1);}
Howard Hinnant82894812010-09-22 16:48:34 +00003832 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003833 byte_string to_bytes(const _Elem* __wptr)
3834 {return to_bytes(__wptr, __wptr + char_traits<_Elem>::length(__wptr));}
Howard Hinnant82894812010-09-22 16:48:34 +00003835 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003836 byte_string to_bytes(const wide_string& __wstr)
3837 {return to_bytes(__wstr.data(), __wstr.data() + __wstr.size());}
3838 byte_string to_bytes(const _Elem* __first, const _Elem* __last);
3839
Howard Hinnant82894812010-09-22 16:48:34 +00003840 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003841 size_t converted() const {return __cvtcount_;}
Howard Hinnant82894812010-09-22 16:48:34 +00003842 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003843 state_type state() const {return __cvtstate_;}
3844};
3845
3846template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Howard Hinnant82894812010-09-22 16:48:34 +00003847inline _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003848wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3849 wstring_convert(_Codecvt* __pcvt)
3850 : __cvtptr_(__pcvt), __cvtstate_(), __cvtcount_(0)
3851{
3852}
3853
3854template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Howard Hinnant82894812010-09-22 16:48:34 +00003855inline _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003856wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3857 wstring_convert(_Codecvt* __pcvt, state_type __state)
3858 : __cvtptr_(__pcvt), __cvtstate_(__state), __cvtcount_(0)
3859{
3860}
3861
3862template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3863wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3864 wstring_convert(const byte_string& __byte_err, const wide_string& __wide_err)
3865 : __byte_err_string_(__byte_err), __wide_err_string_(__wide_err),
3866 __cvtstate_(), __cvtcount_(0)
3867{
3868 __cvtptr_ = new _Codecvt;
3869}
3870
Howard Hinnant73d21a42010-09-04 23:28:19 +00003871#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantd23b4642010-05-31 20:58:54 +00003872
3873template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Howard Hinnant82894812010-09-22 16:48:34 +00003874inline _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003875wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3876 wstring_convert(wstring_convert&& __wc)
Howard Hinnant0949eed2011-06-30 21:18:19 +00003877 : __byte_err_string_(_VSTD::move(__wc.__byte_err_string_)),
3878 __wide_err_string_(_VSTD::move(__wc.__wide_err_string_)),
Howard Hinnantd23b4642010-05-31 20:58:54 +00003879 __cvtptr_(__wc.__cvtptr_),
3880 __cvtstate_(__wc.__cvtstate_), __cvtcount_(__wc.__cvtstate_)
3881{
3882 __wc.__cvtptr_ = nullptr;
3883}
3884
Howard Hinnantbfd55302010-09-04 23:46:48 +00003885#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantd23b4642010-05-31 20:58:54 +00003886
3887template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3888wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::~wstring_convert()
3889{
3890 delete __cvtptr_;
3891}
3892
3893template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3894typename wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::wide_string
3895wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3896 from_bytes(const char* __frm, const char* __frm_end)
3897{
3898 __cvtcount_ = 0;
3899 if (__cvtptr_ != nullptr)
3900 {
3901 wide_string __ws(2*(__frm_end - __frm), _Elem());
3902 __ws.resize(__ws.capacity());
3903 codecvt_base::result __r = codecvt_base::ok;
3904 state_type __st = __cvtstate_;
3905 if (__frm != __frm_end)
3906 {
3907 _Elem* __to = &__ws[0];
3908 _Elem* __to_end = __to + __ws.size();
3909 const char* __frm_nxt;
3910 do
3911 {
3912 _Elem* __to_nxt;
3913 __r = __cvtptr_->in(__st, __frm, __frm_end, __frm_nxt,
3914 __to, __to_end, __to_nxt);
3915 __cvtcount_ += __frm_nxt - __frm;
3916 if (__frm_nxt == __frm)
3917 {
3918 __r = codecvt_base::error;
3919 }
3920 else if (__r == codecvt_base::noconv)
3921 {
3922 __ws.resize(__to - &__ws[0]);
3923 // This only gets executed if _Elem is char
3924 __ws.append((const _Elem*)__frm, (const _Elem*)__frm_end);
3925 __frm = __frm_nxt;
3926 __r = codecvt_base::ok;
3927 }
3928 else if (__r == codecvt_base::ok)
3929 {
3930 __ws.resize(__to_nxt - &__ws[0]);
3931 __frm = __frm_nxt;
3932 }
3933 else if (__r == codecvt_base::partial)
3934 {
3935 ptrdiff_t __s = __to_nxt - &__ws[0];
3936 __ws.resize(2 * __s);
3937 __to = &__ws[0] + __s;
3938 __to_end = &__ws[0] + __ws.size();
3939 __frm = __frm_nxt;
3940 }
3941 } while (__r == codecvt_base::partial && __frm_nxt < __frm_end);
3942 }
3943 if (__r == codecvt_base::ok)
3944 return __ws;
3945 }
Howard Hinnantd4444702010-08-11 17:04:31 +00003946#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00003947 if (__wide_err_string_.empty())
3948 throw range_error("wstring_convert: from_bytes error");
Howard Hinnant324bb032010-08-22 00:02:43 +00003949#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00003950 return __wide_err_string_;
3951}
3952
3953template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3954typename wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::byte_string
3955wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3956 to_bytes(const _Elem* __frm, const _Elem* __frm_end)
3957{
3958 __cvtcount_ = 0;
3959 if (__cvtptr_ != nullptr)
3960 {
3961 byte_string __bs(2*(__frm_end - __frm), char());
3962 __bs.resize(__bs.capacity());
3963 codecvt_base::result __r = codecvt_base::ok;
3964 state_type __st = __cvtstate_;
3965 if (__frm != __frm_end)
3966 {
3967 char* __to = &__bs[0];
3968 char* __to_end = __to + __bs.size();
3969 const _Elem* __frm_nxt;
3970 do
3971 {
3972 char* __to_nxt;
3973 __r = __cvtptr_->out(__st, __frm, __frm_end, __frm_nxt,
3974 __to, __to_end, __to_nxt);
3975 __cvtcount_ += __frm_nxt - __frm;
3976 if (__frm_nxt == __frm)
3977 {
3978 __r = codecvt_base::error;
3979 }
3980 else if (__r == codecvt_base::noconv)
3981 {
3982 __bs.resize(__to - &__bs[0]);
3983 // This only gets executed if _Elem is char
3984 __bs.append((const char*)__frm, (const char*)__frm_end);
3985 __frm = __frm_nxt;
3986 __r = codecvt_base::ok;
3987 }
3988 else if (__r == codecvt_base::ok)
3989 {
3990 __bs.resize(__to_nxt - &__bs[0]);
3991 __frm = __frm_nxt;
3992 }
3993 else if (__r == codecvt_base::partial)
3994 {
3995 ptrdiff_t __s = __to_nxt - &__bs[0];
3996 __bs.resize(2 * __s);
3997 __to = &__bs[0] + __s;
3998 __to_end = &__bs[0] + __bs.size();
3999 __frm = __frm_nxt;
4000 }
4001 } while (__r == codecvt_base::partial && __frm_nxt < __frm_end);
4002 }
4003 if (__r == codecvt_base::ok)
4004 {
4005 size_t __s = __bs.size();
4006 __bs.resize(__bs.capacity());
4007 char* __to = &__bs[0] + __s;
4008 char* __to_end = __to + __bs.size();
4009 do
4010 {
4011 char* __to_nxt;
4012 __r = __cvtptr_->unshift(__st, __to, __to_end, __to_nxt);
4013 if (__r == codecvt_base::noconv)
4014 {
4015 __bs.resize(__to - &__bs[0]);
4016 __r = codecvt_base::ok;
4017 }
4018 else if (__r == codecvt_base::ok)
4019 {
4020 __bs.resize(__to_nxt - &__bs[0]);
4021 }
4022 else if (__r == codecvt_base::partial)
4023 {
4024 ptrdiff_t __s = __to_nxt - &__bs[0];
4025 __bs.resize(2 * __s);
4026 __to = &__bs[0] + __s;
4027 __to_end = &__bs[0] + __bs.size();
4028 }
4029 } while (__r == codecvt_base::partial);
4030 if (__r == codecvt_base::ok)
4031 return __bs;
4032 }
4033 }
Howard Hinnantd4444702010-08-11 17:04:31 +00004034#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00004035 if (__byte_err_string_.empty())
4036 throw range_error("wstring_convert: to_bytes error");
Howard Hinnant324bb032010-08-22 00:02:43 +00004037#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00004038 return __byte_err_string_;
4039}
4040
4041template <class _Codecvt, class _Elem = wchar_t, class _Tr = char_traits<_Elem> >
Howard Hinnant82894812010-09-22 16:48:34 +00004042class _LIBCPP_VISIBLE wbuffer_convert
Howard Hinnantd23b4642010-05-31 20:58:54 +00004043 : public basic_streambuf<_Elem, _Tr>
4044{
4045public:
4046 // types:
4047 typedef _Elem char_type;
4048 typedef _Tr traits_type;
4049 typedef typename traits_type::int_type int_type;
4050 typedef typename traits_type::pos_type pos_type;
4051 typedef typename traits_type::off_type off_type;
4052 typedef typename _Codecvt::state_type state_type;
4053
4054private:
Howard Hinnant4b53f502010-06-01 20:09:18 +00004055 char* __extbuf_;
4056 const char* __extbufnext_;
4057 const char* __extbufend_;
4058 char __extbuf_min_[8];
4059 size_t __ebs_;
4060 char_type* __intbuf_;
4061 size_t __ibs_;
Howard Hinnantd23b4642010-05-31 20:58:54 +00004062 streambuf* __bufptr_;
Howard Hinnant4b53f502010-06-01 20:09:18 +00004063 _Codecvt* __cv_;
4064 state_type __st_;
4065 ios_base::openmode __cm_;
4066 bool __owns_eb_;
4067 bool __owns_ib_;
4068 bool __always_noconv_;
Howard Hinnantd23b4642010-05-31 20:58:54 +00004069
Howard Hinnant4b53f502010-06-01 20:09:18 +00004070 wbuffer_convert(const wbuffer_convert&);
4071 wbuffer_convert& operator=(const wbuffer_convert&);
Howard Hinnantd23b4642010-05-31 20:58:54 +00004072public:
4073 wbuffer_convert(streambuf* __bytebuf = 0, _Codecvt* __pcvt = new _Codecvt,
Howard Hinnant4b53f502010-06-01 20:09:18 +00004074 state_type __state = state_type());
4075 ~wbuffer_convert();
Howard Hinnantd23b4642010-05-31 20:58:54 +00004076
Howard Hinnant82894812010-09-22 16:48:34 +00004077 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantd23b4642010-05-31 20:58:54 +00004078 streambuf* rdbuf() const {return __bufptr_;}
Howard Hinnant82894812010-09-22 16:48:34 +00004079 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantd23b4642010-05-31 20:58:54 +00004080 streambuf* rdbuf(streambuf* __bytebuf)
4081 {
4082 streambuf* __r = __bufptr_;
4083 __bufptr_ = __bytebuf;
4084 return __r;
4085 }
4086
Howard Hinnant82894812010-09-22 16:48:34 +00004087 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant4b53f502010-06-01 20:09:18 +00004088 state_type state() const {return __st_;}
Howard Hinnantd23b4642010-05-31 20:58:54 +00004089
4090protected:
Howard Hinnant4b53f502010-06-01 20:09:18 +00004091 virtual int_type underflow();
4092 virtual int_type pbackfail(int_type __c = traits_type::eof());
Howard Hinnantd23b4642010-05-31 20:58:54 +00004093 virtual int_type overflow (int_type __c = traits_type::eof());
Howard Hinnant4b53f502010-06-01 20:09:18 +00004094 virtual basic_streambuf<char_type, traits_type>* setbuf(char_type* __s,
4095 streamsize __n);
4096 virtual pos_type seekoff(off_type __off, ios_base::seekdir __way,
4097 ios_base::openmode __wch = ios_base::in | ios_base::out);
4098 virtual pos_type seekpos(pos_type __sp,
4099 ios_base::openmode __wch = ios_base::in | ios_base::out);
4100 virtual int sync();
4101
4102private:
4103 bool __read_mode();
4104 void __write_mode();
4105 wbuffer_convert* __close();
Howard Hinnantd23b4642010-05-31 20:58:54 +00004106};
4107
4108template <class _Codecvt, class _Elem, class _Tr>
Howard Hinnant4b53f502010-06-01 20:09:18 +00004109wbuffer_convert<_Codecvt, _Elem, _Tr>::
4110 wbuffer_convert(streambuf* __bytebuf, _Codecvt* __pcvt, state_type __state)
4111 : __extbuf_(0),
4112 __extbufnext_(0),
4113 __extbufend_(0),
4114 __ebs_(0),
4115 __intbuf_(0),
4116 __ibs_(0),
4117 __bufptr_(__bytebuf),
4118 __cv_(__pcvt),
4119 __st_(__state),
4120 __cm_(0),
4121 __owns_eb_(false),
4122 __owns_ib_(false),
4123 __always_noconv_(__cv_ ? __cv_->always_noconv() : false)
4124{
4125 setbuf(0, 4096);
4126}
4127
4128template <class _Codecvt, class _Elem, class _Tr>
4129wbuffer_convert<_Codecvt, _Elem, _Tr>::~wbuffer_convert()
4130{
4131 __close();
4132 delete __cv_;
4133 if (__owns_eb_)
4134 delete [] __extbuf_;
4135 if (__owns_ib_)
4136 delete [] __intbuf_;
4137}
4138
4139template <class _Codecvt, class _Elem, class _Tr>
4140typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
4141wbuffer_convert<_Codecvt, _Elem, _Tr>::underflow()
4142{
4143 if (__cv_ == 0 || __bufptr_ == 0)
4144 return traits_type::eof();
4145 bool __initial = __read_mode();
4146 char_type __1buf;
4147 if (this->gptr() == 0)
4148 this->setg(&__1buf, &__1buf+1, &__1buf+1);
4149 const size_t __unget_sz = __initial ? 0 : min<size_t>((this->egptr() - this->eback()) / 2, 4);
4150 int_type __c = traits_type::eof();
4151 if (this->gptr() == this->egptr())
4152 {
4153 memmove(this->eback(), this->egptr() - __unget_sz, __unget_sz * sizeof(char_type));
4154 if (__always_noconv_)
4155 {
4156 streamsize __nmemb = static_cast<streamsize>(this->egptr() - this->eback() - __unget_sz);
4157 __nmemb = __bufptr_->sgetn((char*)this->eback() + __unget_sz, __nmemb);
4158 if (__nmemb != 0)
4159 {
4160 this->setg(this->eback(),
4161 this->eback() + __unget_sz,
4162 this->eback() + __unget_sz + __nmemb);
4163 __c = *this->gptr();
4164 }
4165 }
4166 else
4167 {
4168 memmove(__extbuf_, __extbufnext_, __extbufend_ - __extbufnext_);
4169 __extbufnext_ = __extbuf_ + (__extbufend_ - __extbufnext_);
4170 __extbufend_ = __extbuf_ + (__extbuf_ == __extbuf_min_ ? sizeof(__extbuf_min_) : __ebs_);
Howard Hinnant0949eed2011-06-30 21:18:19 +00004171 streamsize __nmemb = _VSTD::min(static_cast<streamsize>(this->egptr() - this->eback() - __unget_sz),
Howard Hinnant4b53f502010-06-01 20:09:18 +00004172 static_cast<streamsize>(__extbufend_ - __extbufnext_));
4173 codecvt_base::result __r;
4174 state_type __svs = __st_;
4175 streamsize __nr = __bufptr_->sgetn(const_cast<char*>(__extbufnext_), __nmemb);
4176 if (__nr != 0)
4177 {
4178 __extbufend_ = __extbufnext_ + __nr;
4179 char_type* __inext;
4180 __r = __cv_->in(__st_, __extbuf_, __extbufend_, __extbufnext_,
4181 this->eback() + __unget_sz,
4182 this->egptr(), __inext);
4183 if (__r == codecvt_base::noconv)
4184 {
4185 this->setg((char_type*)__extbuf_, (char_type*)__extbuf_, (char_type*)__extbufend_);
4186 __c = *this->gptr();
4187 }
4188 else if (__inext != this->eback() + __unget_sz)
4189 {
4190 this->setg(this->eback(), this->eback() + __unget_sz, __inext);
4191 __c = *this->gptr();
4192 }
4193 }
4194 }
4195 }
4196 else
4197 __c = *this->gptr();
4198 if (this->eback() == &__1buf)
4199 this->setg(0, 0, 0);
4200 return __c;
4201}
4202
4203template <class _Codecvt, class _Elem, class _Tr>
4204typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
4205wbuffer_convert<_Codecvt, _Elem, _Tr>::pbackfail(int_type __c)
4206{
4207 if (__cv_ != 0 && __bufptr_ != 0 && this->eback() < this->gptr())
4208 {
4209 if (traits_type::eq_int_type(__c, traits_type::eof()))
4210 {
4211 this->gbump(-1);
4212 return traits_type::not_eof(__c);
4213 }
4214 if (traits_type::eq(traits_type::to_char_type(__c), this->gptr()[-1]))
4215 {
4216 this->gbump(-1);
4217 *this->gptr() = traits_type::to_char_type(__c);
4218 return __c;
4219 }
4220 }
4221 return traits_type::eof();
4222}
4223
4224template <class _Codecvt, class _Elem, class _Tr>
Howard Hinnantd23b4642010-05-31 20:58:54 +00004225typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
4226wbuffer_convert<_Codecvt, _Elem, _Tr>::overflow(int_type __c)
4227{
Howard Hinnant4b53f502010-06-01 20:09:18 +00004228 if (__cv_ == 0 || __bufptr_ == 0)
4229 return traits_type::eof();
4230 __write_mode();
4231 char_type __1buf;
4232 char_type* __pb_save = this->pbase();
4233 char_type* __epb_save = this->epptr();
4234 if (!traits_type::eq_int_type(__c, traits_type::eof()))
4235 {
4236 if (this->pptr() == 0)
4237 this->setp(&__1buf, &__1buf+1);
4238 *this->pptr() = traits_type::to_char_type(__c);
4239 this->pbump(1);
4240 }
4241 if (this->pptr() != this->pbase())
4242 {
4243 if (__always_noconv_)
4244 {
4245 streamsize __nmemb = static_cast<streamsize>(this->pptr() - this->pbase());
4246 if (__bufptr_->sputn((const char*)this->pbase(), __nmemb) != __nmemb)
4247 return traits_type::eof();
4248 }
4249 else
4250 {
4251 char* __extbe = __extbuf_;
4252 codecvt_base::result __r;
4253 do
4254 {
4255 const char_type* __e;
4256 __r = __cv_->out(__st_, this->pbase(), this->pptr(), __e,
4257 __extbuf_, __extbuf_ + __ebs_, __extbe);
4258 if (__e == this->pbase())
4259 return traits_type::eof();
4260 if (__r == codecvt_base::noconv)
4261 {
4262 streamsize __nmemb = static_cast<size_t>(this->pptr() - this->pbase());
4263 if (__bufptr_->sputn((const char*)this->pbase(), __nmemb) != __nmemb)
4264 return traits_type::eof();
4265 }
4266 else if (__r == codecvt_base::ok || __r == codecvt_base::partial)
4267 {
4268 streamsize __nmemb = static_cast<size_t>(__extbe - __extbuf_);
4269 if (__bufptr_->sputn(__extbuf_, __nmemb) != __nmemb)
4270 return traits_type::eof();
4271 if (__r == codecvt_base::partial)
4272 {
4273 this->setp((char_type*)__e, this->pptr());
4274 this->pbump(this->epptr() - this->pbase());
4275 }
4276 }
4277 else
4278 return traits_type::eof();
4279 } while (__r == codecvt_base::partial);
4280 }
4281 this->setp(__pb_save, __epb_save);
4282 }
4283 return traits_type::not_eof(__c);
4284}
4285
4286template <class _Codecvt, class _Elem, class _Tr>
4287basic_streambuf<_Elem, _Tr>*
4288wbuffer_convert<_Codecvt, _Elem, _Tr>::setbuf(char_type* __s, streamsize __n)
4289{
4290 this->setg(0, 0, 0);
4291 this->setp(0, 0);
4292 if (__owns_eb_)
4293 delete [] __extbuf_;
4294 if (__owns_ib_)
4295 delete [] __intbuf_;
4296 __ebs_ = __n;
4297 if (__ebs_ > sizeof(__extbuf_min_))
4298 {
4299 if (__always_noconv_ && __s)
4300 {
4301 __extbuf_ = (char*)__s;
4302 __owns_eb_ = false;
4303 }
4304 else
4305 {
4306 __extbuf_ = new char[__ebs_];
4307 __owns_eb_ = true;
4308 }
4309 }
4310 else
4311 {
4312 __extbuf_ = __extbuf_min_;
4313 __ebs_ = sizeof(__extbuf_min_);
4314 __owns_eb_ = false;
4315 }
4316 if (!__always_noconv_)
4317 {
4318 __ibs_ = max<streamsize>(__n, sizeof(__extbuf_min_));
4319 if (__s && __ibs_ >= sizeof(__extbuf_min_))
4320 {
4321 __intbuf_ = __s;
4322 __owns_ib_ = false;
4323 }
4324 else
4325 {
4326 __intbuf_ = new char_type[__ibs_];
4327 __owns_ib_ = true;
4328 }
4329 }
4330 else
4331 {
4332 __ibs_ = 0;
4333 __intbuf_ = 0;
4334 __owns_ib_ = false;
4335 }
4336 return this;
4337}
4338
4339template <class _Codecvt, class _Elem, class _Tr>
4340typename wbuffer_convert<_Codecvt, _Elem, _Tr>::pos_type
4341wbuffer_convert<_Codecvt, _Elem, _Tr>::seekoff(off_type __off, ios_base::seekdir __way,
4342 ios_base::openmode __om)
4343{
4344 int __width = __cv_->encoding();
4345 if (__cv_ == 0 || __bufptr_ == 0 || (__width <= 0 && __off != 0) || sync())
4346 return pos_type(off_type(-1));
4347 // __width > 0 || __off == 0
4348 switch (__way)
4349 {
4350 case ios_base::beg:
4351 break;
4352 case ios_base::cur:
4353 break;
4354 case ios_base::end:
4355 break;
4356 default:
4357 return pos_type(off_type(-1));
4358 }
4359 pos_type __r = __bufptr_->pubseekoff(__width * __off, __way, __om);
4360 __r.state(__st_);
4361 return __r;
4362}
4363
4364template <class _Codecvt, class _Elem, class _Tr>
4365typename wbuffer_convert<_Codecvt, _Elem, _Tr>::pos_type
4366wbuffer_convert<_Codecvt, _Elem, _Tr>::seekpos(pos_type __sp, ios_base::openmode __wch)
4367{
4368 if (__cv_ == 0 || __bufptr_ == 0 || sync())
4369 return pos_type(off_type(-1));
4370 if (__bufptr_->pubseekpos(__sp, __wch) == pos_type(off_type(-1)))
4371 return pos_type(off_type(-1));
4372 return __sp;
4373}
4374
4375template <class _Codecvt, class _Elem, class _Tr>
4376int
4377wbuffer_convert<_Codecvt, _Elem, _Tr>::sync()
4378{
4379 if (__cv_ == 0 || __bufptr_ == 0)
4380 return 0;
4381 if (__cm_ & ios_base::out)
4382 {
4383 if (this->pptr() != this->pbase())
4384 if (overflow() == traits_type::eof())
4385 return -1;
4386 codecvt_base::result __r;
4387 do
4388 {
4389 char* __extbe;
4390 __r = __cv_->unshift(__st_, __extbuf_, __extbuf_ + __ebs_, __extbe);
4391 streamsize __nmemb = static_cast<streamsize>(__extbe - __extbuf_);
4392 if (__bufptr_->sputn(__extbuf_, __nmemb) != __nmemb)
4393 return -1;
4394 } while (__r == codecvt_base::partial);
4395 if (__r == codecvt_base::error)
4396 return -1;
4397 if (__bufptr_->pubsync())
4398 return -1;
4399 }
4400 else if (__cm_ & ios_base::in)
4401 {
4402 off_type __c;
4403 if (__always_noconv_)
4404 __c = this->egptr() - this->gptr();
4405 else
4406 {
4407 int __width = __cv_->encoding();
4408 __c = __extbufend_ - __extbufnext_;
4409 if (__width > 0)
4410 __c += __width * (this->egptr() - this->gptr());
4411 else
4412 {
4413 if (this->gptr() != this->egptr())
4414 {
4415 reverse(this->gptr(), this->egptr());
4416 codecvt_base::result __r;
4417 const char_type* __e = this->gptr();
4418 char* __extbe;
4419 do
4420 {
4421 __r = __cv_->out(__st_, __e, this->egptr(), __e,
4422 __extbuf_, __extbuf_ + __ebs_, __extbe);
4423 switch (__r)
4424 {
4425 case codecvt_base::noconv:
4426 __c += this->egptr() - this->gptr();
4427 break;
4428 case codecvt_base::ok:
4429 case codecvt_base::partial:
4430 __c += __extbe - __extbuf_;
4431 break;
4432 default:
4433 return -1;
4434 }
4435 } while (__r == codecvt_base::partial);
4436 }
4437 }
4438 }
4439 if (__bufptr_->pubseekoff(-__c, ios_base::cur, __cm_) == pos_type(off_type(-1)))
4440 return -1;
4441 this->setg(0, 0, 0);
4442 __cm_ = 0;
4443 }
4444 return 0;
4445}
4446
4447template <class _Codecvt, class _Elem, class _Tr>
4448bool
4449wbuffer_convert<_Codecvt, _Elem, _Tr>::__read_mode()
4450{
4451 if (!(__cm_ & ios_base::in))
4452 {
4453 this->setp(0, 0);
4454 if (__always_noconv_)
4455 this->setg((char_type*)__extbuf_,
4456 (char_type*)__extbuf_ + __ebs_,
4457 (char_type*)__extbuf_ + __ebs_);
4458 else
4459 this->setg(__intbuf_, __intbuf_ + __ibs_, __intbuf_ + __ibs_);
4460 __cm_ = ios_base::in;
4461 return true;
4462 }
4463 return false;
4464}
4465
4466template <class _Codecvt, class _Elem, class _Tr>
4467void
4468wbuffer_convert<_Codecvt, _Elem, _Tr>::__write_mode()
4469{
4470 if (!(__cm_ & ios_base::out))
4471 {
4472 this->setg(0, 0, 0);
4473 if (__ebs_ > sizeof(__extbuf_min_))
4474 {
4475 if (__always_noconv_)
4476 this->setp((char_type*)__extbuf_,
4477 (char_type*)__extbuf_ + (__ebs_ - 1));
4478 else
4479 this->setp(__intbuf_, __intbuf_ + (__ibs_ - 1));
4480 }
4481 else
4482 this->setp(0, 0);
4483 __cm_ = ios_base::out;
4484 }
4485}
4486
4487template <class _Codecvt, class _Elem, class _Tr>
4488wbuffer_convert<_Codecvt, _Elem, _Tr>*
4489wbuffer_convert<_Codecvt, _Elem, _Tr>::__close()
4490{
4491 wbuffer_convert* __rt = 0;
4492 if (__cv_ != 0 && __bufptr_ != 0)
4493 {
4494 __rt = this;
4495 if ((__cm_ & ios_base::out) && sync())
4496 __rt = 0;
4497 }
4498 return __rt;
Howard Hinnantd23b4642010-05-31 20:58:54 +00004499}
4500
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004501_LIBCPP_END_NAMESPACE_STD
4502
4503#endif // _LIBCPP_LOCALE