blob: b2afbd40e07bc95223abda588d8f417d2fcdf631 [file] [log] [blame]
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001// -*- C++ -*-
2//===-------------------------- locale ------------------------------------===//
3//
Howard Hinnantf5256e12010-05-11 21:36:01 +00004// The LLVM Compiler Infrastructure
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005//
Howard Hinnantb64f8b02010-11-16 22:09:02 +00006// This file is dual licensed under the MIT and the University of Illinois Open
7// Source Licenses. See LICENSE.TXT for details.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00008//
9//===----------------------------------------------------------------------===//
10
11#ifndef _LIBCPP_LOCALE
12#define _LIBCPP_LOCALE
13
14/*
15 locale synopsis
16
17namespace std
18{
19
20class locale
21{
22public:
23 // types:
24 class facet;
25 class id;
26
27 typedef int category;
28 static const category // values assigned here are for exposition only
29 none = 0x000,
30 collate = 0x010,
31 ctype = 0x020,
32 monetary = 0x040,
33 numeric = 0x080,
34 time = 0x100,
35 messages = 0x200,
36 all = collate | ctype | monetary | numeric | time | messages;
37
38 // construct/copy/destroy:
Howard Hinnantc9834542011-05-31 15:34:58 +000039 locale() noexcept;
40 locale(const locale& other) noexcept;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000041 explicit locale(const char* std_name);
42 explicit locale(const string& std_name);
43 locale(const locale& other, const char* std_name, category);
44 locale(const locale& other, const string& std_name, category);
45 template <class Facet> locale(const locale& other, Facet* f);
46 locale(const locale& other, const locale& one, category);
47
Howard Hinnantc9834542011-05-31 15:34:58 +000048 ~locale(); // not virtual
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000049
Howard Hinnantc9834542011-05-31 15:34:58 +000050 const locale& operator=(const locale& other) noexcept;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000051
52 template <class Facet> locale combine(const locale& other) const;
53
54 // locale operations:
55 basic_string<char> name() const;
56 bool operator==(const locale& other) const;
57 bool operator!=(const locale& other) const;
58 template <class charT, class Traits, class Allocator>
59 bool operator()(const basic_string<charT,Traits,Allocator>& s1,
60 const basic_string<charT,Traits,Allocator>& s2) const;
61
62 // global locale objects:
63 static locale global(const locale&);
64 static const locale& classic();
65};
66
67template <class Facet> const Facet& use_facet(const locale&);
Howard Hinnantc9834542011-05-31 15:34:58 +000068template <class Facet> bool has_facet(const locale&) noexcept;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000069
70// 22.3.3, convenience interfaces:
71template <class charT> bool isspace (charT c, const locale& loc);
72template <class charT> bool isprint (charT c, const locale& loc);
73template <class charT> bool iscntrl (charT c, const locale& loc);
74template <class charT> bool isupper (charT c, const locale& loc);
75template <class charT> bool islower (charT c, const locale& loc);
76template <class charT> bool isalpha (charT c, const locale& loc);
77template <class charT> bool isdigit (charT c, const locale& loc);
78template <class charT> bool ispunct (charT c, const locale& loc);
79template <class charT> bool isxdigit(charT c, const locale& loc);
80template <class charT> bool isalnum (charT c, const locale& loc);
81template <class charT> bool isgraph (charT c, const locale& loc);
82template <class charT> charT toupper(charT c, const locale& loc);
83template <class charT> charT tolower(charT c, const locale& loc);
Howard Hinnantd23b4642010-05-31 20:58:54 +000084
85template<class Codecvt, class Elem = wchar_t,
86 class Wide_alloc = allocator<Elem>,
87 class Byte_alloc = allocator<char>>
88class wstring_convert
89{
90public:
91 typedef basic_string<char, char_traits<char>, Byte_alloc> byte_string;
92 typedef basic_string<Elem, char_traits<Elem>, Wide_alloc> wide_string;
93 typedef typename Codecvt::state_type state_type;
94 typedef typename wide_string::traits_type::int_type int_type;
95
96 wstring_convert(Codecvt* pcvt = new Codecvt);
97 wstring_convert(Codecvt* pcvt, state_type state);
98 wstring_convert(const byte_string& byte_err,
99 const wide_string& wide_err = wide_string());
100 ~wstring_convert();
101
102 wide_string from_bytes(char byte);
103 wide_string from_bytes(const char* ptr);
104 wide_string from_bytes(const byte_string& str);
105 wide_string from_bytes(const char* first, const char* last);
106
107 byte_string to_bytes(Elem wchar);
108 byte_string to_bytes(const Elem* wptr);
109 byte_string to_bytes(const wide_string& wstr);
110 byte_string to_bytes(const Elem* first, const Elem* last);
111
112 size_t converted() const;
113 state_type state() const;
114};
115
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000116template <class Codecvt, class Elem = wchar_t, class Tr = char_traits<Elem>>
Howard Hinnantd23b4642010-05-31 20:58:54 +0000117class wbuffer_convert
118 : public basic_streambuf<Elem, Tr>
119{
120public:
121 typedef typename Tr::state_type state_type;
122
123 wbuffer_convert(streambuf* bytebuf = 0, Codecvt* pcvt = new Codecvt,
124 state_type state = state_type());
125
126 streambuf* rdbuf() const;
127 streambuf* rdbuf(streambuf* bytebuf);
128
129 state_type state() const;
130};
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000131
132// 22.4.1 and 22.4.1.3, ctype:
133class ctype_base;
134template <class charT> class ctype;
135template <> class ctype<char>; // specialization
136template <class charT> class ctype_byname;
137template <> class ctype_byname<char>; // specialization
138
139class codecvt_base;
140template <class internT, class externT, class stateT> class codecvt;
141template <class internT, class externT, class stateT> class codecvt_byname;
142
143// 22.4.2 and 22.4.3, numeric:
144template <class charT, class InputIterator> class num_get;
145template <class charT, class OutputIterator> class num_put;
146template <class charT> class numpunct;
147template <class charT> class numpunct_byname;
148
149// 22.4.4, col lation:
150template <class charT> class collate;
151template <class charT> class collate_byname;
152
153// 22.4.5, date and time:
154class time_base;
155template <class charT, class InputIterator> class time_get;
156template <class charT, class InputIterator> class time_get_byname;
157template <class charT, class OutputIterator> class time_put;
158template <class charT, class OutputIterator> class time_put_byname;
159
160// 22.4.6, money:
161class money_base;
162template <class charT, class InputIterator> class money_get;
163template <class charT, class OutputIterator> class money_put;
164template <class charT, bool Intl> class moneypunct;
165template <class charT, bool Intl> class moneypunct_byname;
166
167// 22.4.7, message retrieval:
168class messages_base;
169template <class charT> class messages;
170template <class charT> class messages_byname;
171
172} // std
173
174*/
175
176#include <__config>
177#include <__locale>
178#include <algorithm>
179#include <memory>
180#include <ios>
181#include <streambuf>
182#include <iterator>
183#include <limits>
Howard Hinnantadff4892010-05-24 17:49:41 +0000184#if !__APPLE__
185#include <cstdarg>
186#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000187#include <cstdlib>
188#include <ctime>
Howard Hinnant6cd05ee2011-09-23 16:11:27 +0000189#if _WIN32
Howard Hinnant14fa9f92011-09-29 20:33:10 +0000190#include <support/win32/locale_win32.h>
Howard Hinnant6cd05ee2011-09-23 16:11:27 +0000191#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000192#include <nl_types.h>
Howard Hinnant92a07002011-09-22 19:10:18 +0000193#endif // !_WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000194
Howard Hinnant08e17472011-10-17 20:05:10 +0000195#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000196#pragma GCC system_header
Howard Hinnant08e17472011-10-17 20:05:10 +0000197#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000198
199_LIBCPP_BEGIN_NAMESPACE_STD
200
Howard Hinnant866569b2011-09-28 23:39:33 +0000201#if __APPLE__ || __FreeBSD__
Howard Hinnant2ea1ca92011-09-28 21:05:01 +0000202# define _LIBCPP_GET_C_LOCALE 0
203#else
204# define _LIBCPP_GET_C_LOCALE __cloc()
Howard Hinnant866569b2011-09-28 23:39:33 +0000205 // Get the C locale object
206 locale_t __cloc();
207#define __cloc_defined
Howard Hinnant2ea1ca92011-09-28 21:05:01 +0000208#endif
209
Sean Huntf3907e62011-07-15 05:40:33 +0000210typedef _VSTD::remove_pointer<locale_t>::type __locale_struct;
211typedef _VSTD::unique_ptr<__locale_struct, decltype(&freelocale)> __locale_unique_ptr;
212typedef _VSTD::unique_ptr<__locale_struct, decltype(&uselocale)> __locale_raii;
213
Howard Hinnantadff4892010-05-24 17:49:41 +0000214// OSX has nice foo_l() functions that let you turn off use of the global
215// locale. Linux, not so much. The following functions avoid the locale when
216// that's possible and otherwise do the wrong thing. FIXME.
Howard Hinnant866569b2011-09-28 23:39:33 +0000217#ifdef __linux__
Sean Huntf3907e62011-07-15 05:40:33 +0000218
219#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
220decltype(MB_CUR_MAX_L(_VSTD::declval<locale_t>()))
Howard Hinnant82894812010-09-22 16:48:34 +0000221inline _LIBCPP_INLINE_VISIBILITY
Sean Huntf3907e62011-07-15 05:40:33 +0000222__mb_cur_max_l(locale_t __l)
Howard Hinnantadff4892010-05-24 17:49:41 +0000223{
Sean Huntf3907e62011-07-15 05:40:33 +0000224 return MB_CUR_MAX_L(__l);
225}
226#else // _LIBCPP_LOCALE__L_EXTENSIONS
227_LIBCPP_ALWAYS_INLINE inline
228decltype(MB_CUR_MAX) __mb_cur_max_l(locale_t __l)
229{
230 __locale_raii __current(uselocale(__l), uselocale);
231 return MB_CUR_MAX;
232}
233#endif // _LIBCPP_LOCALE__L_EXTENSIONS
234
235_LIBCPP_ALWAYS_INLINE inline
236wint_t __btowc_l(int __c, locale_t __l)
237{
Howard Hinnant866569b2011-09-28 23:39:33 +0000238#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +0000239 return btowc_l(__c, __l);
240#else
241 __locale_raii __current(uselocale(__l), uselocale);
242 return btowc(__c);
243#endif
Sean Huntc97da3a2011-07-13 06:40:50 +0000244}
Howard Hinnant8d756322011-07-13 15:48:16 +0000245
Sean Huntf3907e62011-07-15 05:40:33 +0000246_LIBCPP_ALWAYS_INLINE inline
247int __wctob_l(wint_t __c, locale_t __l)
Sean Huntc97da3a2011-07-13 06:40:50 +0000248{
Sean Huntf3907e62011-07-15 05:40:33 +0000249#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
250 return wctob_l(__c, __l);
251#else
252 __locale_raii __current(uselocale(__l), uselocale);
253 return wctob(__c);
254#endif
Sean Huntc97da3a2011-07-13 06:40:50 +0000255}
Sean Huntf3907e62011-07-15 05:40:33 +0000256
257_LIBCPP_ALWAYS_INLINE inline
258size_t __wcsnrtombs_l(char *__dest, const wchar_t **__src, size_t __nwc,
259 size_t __len, mbstate_t *__ps, locale_t __l)
260{
261#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
262 return wcsnrtombs_l(__dest, __src, __nwc, __len, __ps, __l);
263#else
264 __locale_raii __current(uselocale(__l), uselocale);
265 return wcsnrtombs(__dest, __src, __nwc, __len, __ps);
266#endif
267}
268
269_LIBCPP_ALWAYS_INLINE inline
270size_t __wcrtomb_l(char *__s, wchar_t __wc, mbstate_t *__ps, locale_t __l)
271{
272#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
273 return wcrtomb_l(__s, __wc, __ps, __l);
274#else
275 __locale_raii __current(uselocale(__l), uselocale);
276 return wcrtomb(__s, __wc, __ps);
277#endif
278}
279
280_LIBCPP_ALWAYS_INLINE inline
281size_t __mbsnrtowcs_l(wchar_t * __dest, const char **__src, size_t __nms,
282 size_t __len, mbstate_t *__ps, locale_t __l)
283{
284#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
David Chisnallc512df12011-09-21 08:39:44 +0000285 return mbsnrtowcs_l(__dest, __src, __nms, __len, __ps, __l);
Sean Huntf3907e62011-07-15 05:40:33 +0000286#else
287 __locale_raii __current(uselocale(__l), uselocale);
288 return mbsnrtowcs(__dest, __src, __nms, __len, __ps);
289#endif
290}
291
292_LIBCPP_ALWAYS_INLINE inline
293size_t __mbrtowc_l(wchar_t *__pwc, const char *__s, size_t __n,
294 mbstate_t *__ps, locale_t __l)
295{
296#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
297 return mbrtowc_l(__pwc, __s, __n, __ps, __l);
298#else
299 __locale_raii __current(uselocale(__l), uselocale);
300 return mbrtowc(__pwc, __s, __n, __ps);
301#endif
302}
303
304_LIBCPP_ALWAYS_INLINE inline
305int __mbtowc_l(wchar_t *__pwc, const char *__pmb, size_t __max, locale_t __l)
306{
307#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
David Chisnallc512df12011-09-21 08:39:44 +0000308 return mbtowc_l(__pwc, __pmb, __max, __l);
Sean Huntf3907e62011-07-15 05:40:33 +0000309#else
310 __locale_raii __current(uselocale(__l), uselocale);
311 return mbtowc(__pwc, __pmb, __max);
312#endif
313}
314
315_LIBCPP_ALWAYS_INLINE inline
316size_t __mbrlen_l(const char *__s, size_t __n, mbstate_t *__ps, locale_t __l)
317{
318#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
319 return mbrlen_l(__s, __n, __ps, __l);
320#else
321 __locale_raii __current(uselocale(__l), uselocale);
322 return mbrlen(__s, __n, __ps);
323#endif
324}
325
326_LIBCPP_ALWAYS_INLINE inline
327lconv *__localeconv_l(locale_t __l)
328{
329#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
330 return localeconv_l(__l);
331#else
332 __locale_raii __current(uselocale(__l), uselocale);
333 return localeconv();
334#endif
335}
336
337_LIBCPP_ALWAYS_INLINE inline
338size_t __mbsrtowcs_l(wchar_t *__dest, const char **__src, size_t __len,
339 mbstate_t *__ps, locale_t __l)
340{
341#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
342 return mbsrtowcs_l(__dest, __src, __len, __ps, __l);
343#else
344 __locale_raii __current(uselocale(__l), uselocale);
345 return mbsrtowcs(__dest, __src, __len, __ps);
346#endif
347}
348
349_LIBCPP_ALWAYS_INLINE inline
350int __sprintf_l(char *__s, locale_t __l, const char *__format, ...) {
351 va_list __va;
352 va_start(__va, __format);
353#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
354 int __res = vsprintf_l(__s, __l, __format, __va);
355#else
356 __locale_raii __current(uselocale(__l), uselocale);
357 int __res = vsprintf(__s, __format, __va);
358#endif
359 va_end(__va);
360 return __res;
361}
362
363_LIBCPP_ALWAYS_INLINE inline
364int __snprintf_l(char *__s, size_t __n, locale_t __l, const char *__format, ...) {
365 va_list __va;
366 va_start(__va, __format);
367#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
368 int __res = vsnprintf_l(__s, __n, __l, __format, __va);
369#else
370 __locale_raii __current(uselocale(__l), uselocale);
371 int __res = vsnprintf(__s, __n, __format, __va);
372#endif
373 va_end(__va);
374 return __res;
375}
376
377_LIBCPP_ALWAYS_INLINE inline
378int __asprintf_l(char **__s, locale_t __l, const char *__format, ...) {
379 va_list __va;
380 va_start(__va, __format);
381#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
382 int __res = vasprintf_l(__s, __l, __format, __va);
383#else
384 __locale_raii __current(uselocale(__l), uselocale);
385 int __res = vasprintf(__s, __format, __va);
386#endif
387 va_end(__va);
388 return __res;
389}
390
391_LIBCPP_ALWAYS_INLINE inline
392int __sscanf_l(const char *__s, locale_t __l, const char *__format, ...) {
393 va_list __va;
394 va_start(__va, __format);
395#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
396 int __res = vsscanf_l(__s, __l, __format, __va);
397#else
398 __locale_raii __current(uselocale(__l), uselocale);
399 int __res = vsscanf(__s, __format, __va);
400#endif
401 va_end(__va);
402 return __res;
403}
404
Howard Hinnant866569b2011-09-28 23:39:33 +0000405#endif // __linux__
Howard Hinnantadff4892010-05-24 17:49:41 +0000406
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000407// __scan_keyword
408// Scans [__b, __e) until a match is found in the basic_strings range
409// [__kb, __ke) or until it can be shown that there is no match in [__kb, __ke).
410// __b will be incremented (visibly), consuming CharT until a match is found
411// or proved to not exist. A keyword may be "", in which will match anything.
412// If one keyword is a prefix of another, and the next CharT in the input
413// might match another keyword, the algorithm will attempt to find the longest
414// matching keyword. If the longer matching keyword ends up not matching, then
415// no keyword match is found. If no keyword match is found, __ke is returned
416// and failbit is set in __err.
417// Else an iterator pointing to the matching keyword is found. If more than
418// one keyword matches, an iterator to the first matching keyword is returned.
419// If on exit __b == __e, eofbit is set in __err. If __case_senstive is false,
420// __ct is used to force to lower case before comparing characters.
421// Examples:
422// Keywords: "a", "abb"
423// If the input is "a", the first keyword matches and eofbit is set.
424// If the input is "abc", no match is found and "ab" are consumed.
425template <class _InputIterator, class _ForwardIterator, class _Ctype>
426_LIBCPP_HIDDEN
427_ForwardIterator
428__scan_keyword(_InputIterator& __b, _InputIterator __e,
429 _ForwardIterator __kb, _ForwardIterator __ke,
430 const _Ctype& __ct, ios_base::iostate& __err,
431 bool __case_sensitive = true)
432{
433 typedef typename iterator_traits<_InputIterator>::value_type _CharT;
Howard Hinnant0949eed2011-06-30 21:18:19 +0000434 size_t __nkw = _VSTD::distance(__kb, __ke);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000435 const unsigned char __doesnt_match = '\0';
436 const unsigned char __might_match = '\1';
437 const unsigned char __does_match = '\2';
438 unsigned char __statbuf[100];
439 unsigned char* __status = __statbuf;
440 unique_ptr<unsigned char, void(*)(void*)> __stat_hold(0, free);
441 if (__nkw > sizeof(__statbuf))
442 {
443 __status = (unsigned char*)malloc(__nkw);
444 if (__status == 0)
445 __throw_bad_alloc();
446 __stat_hold.reset(__status);
447 }
448 size_t __n_might_match = __nkw; // At this point, any keyword might match
449 size_t __n_does_match = 0; // but none of them definitely do
450 // Initialize all statuses to __might_match, except for "" keywords are __does_match
451 unsigned char* __st = __status;
452 for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, ++__st)
453 {
454 if (!__ky->empty())
455 *__st = __might_match;
456 else
457 {
458 *__st = __does_match;
459 --__n_might_match;
460 ++__n_does_match;
461 }
462 }
463 // While there might be a match, test keywords against the next CharT
464 for (size_t __indx = 0; __b != __e && __n_might_match > 0; ++__indx)
465 {
466 // Peek at the next CharT but don't consume it
467 _CharT __c = *__b;
468 if (!__case_sensitive)
469 __c = __ct.toupper(__c);
470 bool __consume = false;
471 // For each keyword which might match, see if the __indx character is __c
472 // If a match if found, consume __c
473 // If a match is found, and that is the last character in the keyword,
474 // then that keyword matches.
475 // If the keyword doesn't match this character, then change the keyword
476 // to doesn't match
477 __st = __status;
478 for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, ++__st)
479 {
480 if (*__st == __might_match)
481 {
482 _CharT __kc = (*__ky)[__indx];
483 if (!__case_sensitive)
484 __kc = __ct.toupper(__kc);
485 if (__c == __kc)
486 {
487 __consume = true;
488 if (__ky->size() == __indx+1)
489 {
490 *__st = __does_match;
491 --__n_might_match;
492 ++__n_does_match;
493 }
494 }
495 else
496 {
497 *__st = __doesnt_match;
498 --__n_might_match;
499 }
500 }
501 }
502 // consume if we matched a character
503 if (__consume)
504 {
505 ++__b;
506 // If we consumed a character and there might be a matched keyword that
507 // was marked matched on a previous iteration, then such keywords
508 // which are now marked as not matching.
509 if (__n_might_match + __n_does_match > 1)
510 {
511 __st = __status;
512 for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, ++__st)
513 {
514 if (*__st == __does_match && __ky->size() != __indx+1)
515 {
516 *__st = __doesnt_match;
517 --__n_does_match;
518 }
519 }
520 }
521 }
522 }
523 // We've exited the loop because we hit eof and/or we have no more "might matches".
524 if (__b == __e)
525 __err |= ios_base::eofbit;
526 // Return the first matching result
527 for (__st = __status; __kb != __ke; ++__kb, ++__st)
528 if (*__st == __does_match)
529 break;
530 if (__kb == __ke)
531 __err |= ios_base::failbit;
532 return __kb;
533}
534
535struct __num_get_base
536{
537 static const int __num_get_buf_sz = 40;
538
539 static int __get_base(ios_base&);
540 static const char __src[33];
541};
542
543void __check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
544 ios_base::iostate& __err);
545
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000546template <class _CharT>
547struct __num_get
548 : protected __num_get_base
549{
550 static string __stage2_int_prep(ios_base& __iob, _CharT* __atoms, _CharT& __thousands_sep);
551 static string __stage2_float_prep(ios_base& __iob, _CharT* __atoms, _CharT& __decimal_point,
552 _CharT& __thousands_sep);
553 static int __stage2_int_loop(_CharT __ct, int __base, char* __a, char*& __a_end,
554 unsigned& __dc, _CharT __thousands_sep, const string& __grouping,
555 unsigned* __g, unsigned*& __g_end, _CharT* __atoms);
556 static int __stage2_float_loop(_CharT __ct, bool& __in_units, char& __exp,
557 char* __a, char*& __a_end,
558 _CharT __decimal_point, _CharT __thousands_sep,
559 const string& __grouping, unsigned* __g,
560 unsigned*& __g_end, unsigned& __dc, _CharT* __atoms);
561};
562
563template <class _CharT>
564string
565__num_get<_CharT>::__stage2_int_prep(ios_base& __iob, _CharT* __atoms, _CharT& __thousands_sep)
566{
567 locale __loc = __iob.getloc();
568 use_facet<ctype<_CharT> >(__loc).widen(__src, __src + 26, __atoms);
569 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
570 __thousands_sep = __np.thousands_sep();
571 return __np.grouping();
572}
573
574template <class _CharT>
575string
576__num_get<_CharT>::__stage2_float_prep(ios_base& __iob, _CharT* __atoms, _CharT& __decimal_point,
577 _CharT& __thousands_sep)
578{
579 locale __loc = __iob.getloc();
580 use_facet<ctype<_CharT> >(__loc).widen(__src, __src + 32, __atoms);
581 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
582 __decimal_point = __np.decimal_point();
583 __thousands_sep = __np.thousands_sep();
584 return __np.grouping();
585}
586
587template <class _CharT>
588int
589__num_get<_CharT>::__stage2_int_loop(_CharT __ct, int __base, char* __a, char*& __a_end,
590 unsigned& __dc, _CharT __thousands_sep, const string& __grouping,
591 unsigned* __g, unsigned*& __g_end, _CharT* __atoms)
592{
Howard Hinnant80586722011-03-09 01:03:19 +0000593 if (__a_end == __a && (__ct == __atoms[24] || __ct == __atoms[25]))
594 {
595 *__a_end++ = __ct == __atoms[24] ? '+' : '-';
596 __dc = 0;
597 return 0;
598 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000599 if (__ct == __thousands_sep && __grouping.size() != 0)
600 {
601 if (__g_end-__g < __num_get_buf_sz)
602 {
603 *__g_end++ = __dc;
604 __dc = 0;
605 }
606 return 0;
607 }
608 ptrdiff_t __f = find(__atoms, __atoms + 26, __ct) - __atoms;
Howard Hinnant80586722011-03-09 01:03:19 +0000609 if (__f >= 24)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000610 return -1;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000611 switch (__base)
612 {
613 case 8:
614 case 10:
615 if (__f >= __base)
Howard Hinnant80586722011-03-09 01:03:19 +0000616 return -1;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000617 break;
Howard Hinnant80586722011-03-09 01:03:19 +0000618 case 16:
619 if (__f < 22)
620 break;
621 if (__a_end != __a && __a_end - __a <= 2 && __a_end[-1] == '0')
622 {
623 __dc = 0;
624 *__a_end++ = __src[__f];
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000625 return 0;
Howard Hinnant80586722011-03-09 01:03:19 +0000626 }
627 return -1;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000628 }
Howard Hinnant80586722011-03-09 01:03:19 +0000629 if (__a_end-__a < __num_get_buf_sz - 1)
630 *__a_end++ = __src[__f];
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000631 ++__dc;
632 return 0;
633}
634
635template <class _CharT>
636int
637__num_get<_CharT>::__stage2_float_loop(_CharT __ct, bool& __in_units, char& __exp, char* __a, char*& __a_end,
638 _CharT __decimal_point, _CharT __thousands_sep, const string& __grouping,
639 unsigned* __g, unsigned*& __g_end, unsigned& __dc, _CharT* __atoms)
640{
641 if (__ct == __decimal_point)
642 {
643 if (!__in_units)
644 return -1;
645 __in_units = false;
646 *__a_end++ = '.';
647 if (__grouping.size() != 0 && __g_end-__g < __num_get_buf_sz)
648 *__g_end++ = __dc;
649 return 0;
650 }
651 if (__ct == __thousands_sep && __grouping.size() != 0)
652 {
653 if (!__in_units)
654 return -1;
655 if (__g_end-__g < __num_get_buf_sz)
656 {
657 *__g_end++ = __dc;
658 __dc = 0;
659 }
660 return 0;
661 }
662 ptrdiff_t __f = find(__atoms, __atoms + 32, __ct) - __atoms;
663 if (__f >= 32)
664 return -1;
665 char __x = __src[__f];
666 if (__a_end-__a < __num_get_buf_sz - 1)
667 *__a_end++ = __x;
668 if (__x == 'x' || __x == 'X')
669 __exp = 'P';
670 else if ((__x & 0xDF) == __exp)
671 {
672 __in_units = false;
673 if (__grouping.size() != 0 && __g_end-__g < __num_get_buf_sz)
674 *__g_end++ = __dc;
675 }
676 if (__f >= 22)
677 return 0;
678 ++__dc;
679 return 0;
680}
681
682extern template class __num_get<char>;
683extern template class __num_get<wchar_t>;
684
685template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +0000686class _LIBCPP_VISIBLE num_get
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000687 : public locale::facet,
688 private __num_get<_CharT>
689{
690public:
691 typedef _CharT char_type;
692 typedef _InputIterator iter_type;
693
694 _LIBCPP_ALWAYS_INLINE
695 explicit num_get(size_t __refs = 0)
696 : locale::facet(__refs) {}
697
698 _LIBCPP_ALWAYS_INLINE
699 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
700 ios_base::iostate& __err, bool& __v) const
701 {
702 return do_get(__b, __e, __iob, __err, __v);
703 }
704
705 _LIBCPP_ALWAYS_INLINE
706 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
707 ios_base::iostate& __err, long& __v) const
708 {
709 return do_get(__b, __e, __iob, __err, __v);
710 }
711
712 _LIBCPP_ALWAYS_INLINE
713 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
714 ios_base::iostate& __err, long long& __v) const
715 {
716 return do_get(__b, __e, __iob, __err, __v);
717 }
718
719 _LIBCPP_ALWAYS_INLINE
720 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
721 ios_base::iostate& __err, unsigned short& __v) const
722 {
723 return do_get(__b, __e, __iob, __err, __v);
724 }
725
726 _LIBCPP_ALWAYS_INLINE
727 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
728 ios_base::iostate& __err, unsigned int& __v) const
729 {
730 return do_get(__b, __e, __iob, __err, __v);
731 }
732
733 _LIBCPP_ALWAYS_INLINE
734 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
735 ios_base::iostate& __err, unsigned long& __v) const
736 {
737 return do_get(__b, __e, __iob, __err, __v);
738 }
739
740 _LIBCPP_ALWAYS_INLINE
741 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
742 ios_base::iostate& __err, unsigned long long& __v) const
743 {
744 return do_get(__b, __e, __iob, __err, __v);
745 }
746
747 _LIBCPP_ALWAYS_INLINE
748 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
749 ios_base::iostate& __err, float& __v) const
750 {
751 return do_get(__b, __e, __iob, __err, __v);
752 }
753
754 _LIBCPP_ALWAYS_INLINE
755 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
756 ios_base::iostate& __err, double& __v) const
757 {
758 return do_get(__b, __e, __iob, __err, __v);
759 }
760
761 _LIBCPP_ALWAYS_INLINE
762 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
763 ios_base::iostate& __err, long double& __v) const
764 {
765 return do_get(__b, __e, __iob, __err, __v);
766 }
767
768 _LIBCPP_ALWAYS_INLINE
769 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
770 ios_base::iostate& __err, void*& __v) const
771 {
772 return do_get(__b, __e, __iob, __err, __v);
773 }
774
775 static locale::id id;
776
777protected:
Howard Hinnant82894812010-09-22 16:48:34 +0000778 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000779 ~num_get() {}
780
781 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
782 ios_base::iostate& __err, bool& __v) const;
783 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
784 ios_base::iostate& __err, long& __v) const;
785 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
786 ios_base::iostate& __err, long long& __v) const;
787 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
788 ios_base::iostate& __err, unsigned short& __v) const;
789 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
790 ios_base::iostate& __err, unsigned int& __v) const;
791 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
792 ios_base::iostate& __err, unsigned long& __v) const;
793 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
794 ios_base::iostate& __err, unsigned long long& __v) const;
795 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
796 ios_base::iostate& __err, float& __v) const;
797 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
798 ios_base::iostate& __err, double& __v) const;
799 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
800 ios_base::iostate& __err, long double& __v) const;
801 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
802 ios_base::iostate& __err, void*& __v) const;
803};
804
805template <class _CharT, class _InputIterator>
806locale::id
807num_get<_CharT, _InputIterator>::id;
808
809template <class _Tp>
810_Tp
811__num_get_signed_integral(const char* __a, const char* __a_end,
812 ios_base::iostate& __err, int __base)
813{
814 if (__a != __a_end)
815 {
Howard Hinnante7c8da62011-02-25 19:52:41 +0000816 int __save_errno = errno;
817 errno = 0;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000818 char *__p2;
Howard Hinnant2ea1ca92011-09-28 21:05:01 +0000819 long long __ll = strtoll_l(__a, &__p2, __base, _LIBCPP_GET_C_LOCALE);
Howard Hinnante7c8da62011-02-25 19:52:41 +0000820 int __current_errno = errno;
821 if (__current_errno == 0)
822 errno = __save_errno;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000823 if (__p2 != __a_end)
824 {
825 __err = ios_base::failbit;
826 return 0;
827 }
Howard Hinnante7c8da62011-02-25 19:52:41 +0000828 else if (__current_errno == ERANGE ||
829 __ll < numeric_limits<_Tp>::min() ||
830 numeric_limits<_Tp>::max() < __ll)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000831 {
832 __err = ios_base::failbit;
Howard Hinnante7c8da62011-02-25 19:52:41 +0000833 if (__ll > 0)
834 return numeric_limits<_Tp>::max();
835 else
836 return numeric_limits<_Tp>::min();
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000837 }
838 return static_cast<_Tp>(__ll);
839 }
840 __err = ios_base::failbit;
841 return 0;
842}
843
844template <class _Tp>
845_Tp
846__num_get_unsigned_integral(const char* __a, const char* __a_end,
847 ios_base::iostate& __err, int __base)
848{
849 if (__a != __a_end)
850 {
Howard Hinnante7c8da62011-02-25 19:52:41 +0000851 if (*__a == '-')
852 {
853 __err = ios_base::failbit;
854 return 0;
855 }
856 int __save_errno = errno;
857 errno = 0;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000858 char *__p2;
Howard Hinnant2ea1ca92011-09-28 21:05:01 +0000859 unsigned long long __ll = strtoull_l(__a, &__p2, __base, _LIBCPP_GET_C_LOCALE);
Howard Hinnante7c8da62011-02-25 19:52:41 +0000860 int __current_errno = errno;
861 if (__current_errno == 0)
862 errno = __save_errno;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000863 if (__p2 != __a_end)
864 {
865 __err = ios_base::failbit;
866 return 0;
867 }
Howard Hinnante7c8da62011-02-25 19:52:41 +0000868 else if (__current_errno == ERANGE ||
869 numeric_limits<_Tp>::max() < __ll)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000870 {
871 __err = ios_base::failbit;
872 return numeric_limits<_Tp>::max();
873 }
874 return static_cast<_Tp>(__ll);
875 }
876 __err = ios_base::failbit;
877 return 0;
878}
879
880template <class _Tp>
881_Tp
882__num_get_float(const char* __a, const char* __a_end, ios_base::iostate& __err)
883{
884 if (__a != __a_end)
885 {
886 char *__p2;
Howard Hinnant2ea1ca92011-09-28 21:05:01 +0000887 long double __ld = strtold_l(__a, &__p2, _LIBCPP_GET_C_LOCALE);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000888 if (__p2 != __a_end)
889 {
890 __err = ios_base::failbit;
891 return 0;
892 }
893 return static_cast<_Tp>(__ld);
894 }
895 __err = ios_base::failbit;
896 return 0;
897}
898
899template <class _CharT, class _InputIterator>
900_InputIterator
901num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
902 ios_base& __iob,
903 ios_base::iostate& __err,
904 bool& __v) const
905{
906 if ((__iob.flags() & ios_base::boolalpha) == 0)
907 {
908 long __lv = -1;
909 __b = do_get(__b, __e, __iob, __err, __lv);
910 switch (__lv)
911 {
912 case 0:
913 __v = false;
914 break;
915 case 1:
916 __v = true;
917 break;
918 default:
919 __v = true;
920 __err = ios_base::failbit;
921 break;
922 }
923 return __b;
924 }
925 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__iob.getloc());
926 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__iob.getloc());
927 typedef typename numpunct<_CharT>::string_type string_type;
928 const string_type __names[2] = {__np.truename(), __np.falsename()};
929 const string_type* __i = __scan_keyword(__b, __e, __names, __names+2,
930 __ct, __err);
931 __v = __i == __names;
932 return __b;
933}
934
935template <class _CharT, class _InputIterator>
936_InputIterator
937num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
938 ios_base& __iob,
939 ios_base::iostate& __err,
940 long& __v) const
941{
942 // Stage 1
943 int __base = this->__get_base(__iob);
944 // Stage 2
945 char_type __atoms[26];
946 char_type __thousands_sep;
947 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
948 char __a[__num_get_base::__num_get_buf_sz] = {0};
949 char* __a_end = __a;
950 unsigned __g[__num_get_base::__num_get_buf_sz];
951 unsigned* __g_end = __g;
952 unsigned __dc = 0;
953 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +0000954 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000955 __thousands_sep, __grouping, __g, __g_end,
956 __atoms))
957 break;
958 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
959 *__g_end++ = __dc;
960 // Stage 3
961 __v = __num_get_signed_integral<long>(__a, __a_end, __err, __base);
962 // Digit grouping checked
963 __check_grouping(__grouping, __g, __g_end, __err);
964 // EOF checked
965 if (__b == __e)
966 __err |= ios_base::eofbit;
967 return __b;
968}
969
970template <class _CharT, class _InputIterator>
971_InputIterator
972num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
973 ios_base& __iob,
974 ios_base::iostate& __err,
975 long long& __v) const
976{
977 // Stage 1
978 int __base = this->__get_base(__iob);
979 // Stage 2
980 char_type __atoms[26];
981 char_type __thousands_sep;
982 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
983 char __a[__num_get_base::__num_get_buf_sz] = {0};
984 char* __a_end = __a;
985 unsigned __g[__num_get_base::__num_get_buf_sz];
986 unsigned* __g_end = __g;
987 unsigned __dc = 0;
988 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +0000989 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
990 __thousands_sep, __grouping, __g, __g_end,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000991 __atoms))
992 break;
993 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
994 *__g_end++ = __dc;
995 // Stage 3
996 __v = __num_get_signed_integral<long long>(__a, __a_end, __err, __base);
997 // Digit grouping checked
998 __check_grouping(__grouping, __g, __g_end, __err);
999 // EOF checked
1000 if (__b == __e)
1001 __err |= ios_base::eofbit;
1002 return __b;
1003}
1004
1005template <class _CharT, class _InputIterator>
1006_InputIterator
1007num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1008 ios_base& __iob,
1009 ios_base::iostate& __err,
1010 unsigned short& __v) const
1011{
1012 // Stage 1
1013 int __base = this->__get_base(__iob);
1014 // Stage 2
1015 char_type __atoms[26];
1016 char_type __thousands_sep;
1017 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
1018 char __a[__num_get_base::__num_get_buf_sz] = {0};
1019 char* __a_end = __a;
1020 unsigned __g[__num_get_base::__num_get_buf_sz];
1021 unsigned* __g_end = __g;
1022 unsigned __dc = 0;
1023 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001024 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001025 __thousands_sep, __grouping, __g, __g_end,
1026 __atoms))
1027 break;
1028 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
1029 *__g_end++ = __dc;
1030 // Stage 3
1031 __v = __num_get_unsigned_integral<unsigned short>(__a, __a_end, __err, __base);
1032 // Digit grouping checked
1033 __check_grouping(__grouping, __g, __g_end, __err);
1034 // EOF checked
1035 if (__b == __e)
1036 __err |= ios_base::eofbit;
1037 return __b;
1038}
1039
1040template <class _CharT, class _InputIterator>
1041_InputIterator
1042num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1043 ios_base& __iob,
1044 ios_base::iostate& __err,
1045 unsigned int& __v) const
1046{
1047 // Stage 1
1048 int __base = this->__get_base(__iob);
1049 // Stage 2
1050 char_type __atoms[26];
1051 char_type __thousands_sep;
1052 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
1053 char __a[__num_get_base::__num_get_buf_sz] = {0};
1054 char* __a_end = __a;
1055 unsigned __g[__num_get_base::__num_get_buf_sz];
1056 unsigned* __g_end = __g;
1057 unsigned __dc = 0;
1058 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001059 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001060 __thousands_sep, __grouping, __g, __g_end,
1061 __atoms))
1062 break;
1063 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
1064 *__g_end++ = __dc;
1065 // Stage 3
1066 __v = __num_get_unsigned_integral<unsigned int>(__a, __a_end, __err, __base);
1067 // Digit grouping checked
1068 __check_grouping(__grouping, __g, __g_end, __err);
1069 // EOF checked
1070 if (__b == __e)
1071 __err |= ios_base::eofbit;
1072 return __b;
1073}
1074
1075template <class _CharT, class _InputIterator>
1076_InputIterator
1077num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1078 ios_base& __iob,
1079 ios_base::iostate& __err,
1080 unsigned long& __v) const
1081{
1082 // Stage 1
1083 int __base = this->__get_base(__iob);
1084 // Stage 2
1085 char_type __atoms[26];
1086 char_type __thousands_sep;
1087 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
1088 char __a[__num_get_base::__num_get_buf_sz] = {0};
1089 char* __a_end = __a;
1090 unsigned __g[__num_get_base::__num_get_buf_sz];
1091 unsigned* __g_end = __g;
1092 unsigned __dc = 0;
1093 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001094 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001095 __thousands_sep, __grouping, __g, __g_end,
1096 __atoms))
1097 break;
1098 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
1099 *__g_end++ = __dc;
1100 // Stage 3
1101 __v = __num_get_unsigned_integral<unsigned long>(__a, __a_end, __err, __base);
1102 // Digit grouping checked
1103 __check_grouping(__grouping, __g, __g_end, __err);
1104 // EOF checked
1105 if (__b == __e)
1106 __err |= ios_base::eofbit;
1107 return __b;
1108}
1109
1110template <class _CharT, class _InputIterator>
1111_InputIterator
1112num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1113 ios_base& __iob,
1114 ios_base::iostate& __err,
1115 unsigned long long& __v) const
1116{
1117 // Stage 1
1118 int __base = this->__get_base(__iob);
1119 // Stage 2
1120 char_type __atoms[26];
1121 char_type __thousands_sep;
1122 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
1123 char __a[__num_get_base::__num_get_buf_sz] = {0};
1124 char* __a_end = __a;
1125 unsigned __g[__num_get_base::__num_get_buf_sz];
1126 unsigned* __g_end = __g;
1127 unsigned __dc = 0;
1128 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001129 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001130 __thousands_sep, __grouping, __g, __g_end,
1131 __atoms))
1132 break;
1133 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
1134 *__g_end++ = __dc;
1135 // Stage 3
1136 __v = __num_get_unsigned_integral<unsigned long long>(__a, __a_end, __err, __base);
1137 // Digit grouping checked
1138 __check_grouping(__grouping, __g, __g_end, __err);
1139 // EOF checked
1140 if (__b == __e)
1141 __err |= ios_base::eofbit;
1142 return __b;
1143}
1144
1145template <class _CharT, class _InputIterator>
1146_InputIterator
1147num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1148 ios_base& __iob,
1149 ios_base::iostate& __err,
1150 float& __v) const
1151{
1152 // Stage 1, nothing to do
1153 // Stage 2
1154 char_type __atoms[32];
1155 char_type __decimal_point;
1156 char_type __thousands_sep;
Howard Hinnant324bb032010-08-22 00:02:43 +00001157 string __grouping = this->__stage2_float_prep(__iob, __atoms,
1158 __decimal_point,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001159 __thousands_sep);
1160 char __a[__num_get_base::__num_get_buf_sz] = {0};
1161 char* __a_end = __a;
1162 unsigned __g[__num_get_base::__num_get_buf_sz];
1163 unsigned* __g_end = __g;
1164 unsigned __dc = 0;
1165 bool __in_units = true;
1166 char __exp = 'E';
1167 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001168 if (this->__stage2_float_loop(*__b, __in_units, __exp, __a, __a_end,
1169 __decimal_point, __thousands_sep,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001170 __grouping, __g, __g_end,
1171 __dc, __atoms))
1172 break;
1173 if (__grouping.size() != 0 && __in_units && __g_end-__g < __num_get_base::__num_get_buf_sz)
1174 *__g_end++ = __dc;
1175 // Stage 3
1176 __v = __num_get_float<float>(__a, __a_end, __err);
1177 // Digit grouping checked
1178 __check_grouping(__grouping, __g, __g_end, __err);
1179 // EOF checked
1180 if (__b == __e)
1181 __err |= ios_base::eofbit;
1182 return __b;
1183}
1184
1185template <class _CharT, class _InputIterator>
1186_InputIterator
1187num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1188 ios_base& __iob,
1189 ios_base::iostate& __err,
1190 double& __v) const
1191{
1192 // Stage 1, nothing to do
1193 // Stage 2
1194 char_type __atoms[32];
1195 char_type __decimal_point;
1196 char_type __thousands_sep;
Howard Hinnant324bb032010-08-22 00:02:43 +00001197 string __grouping = this->__stage2_float_prep(__iob, __atoms,
1198 __decimal_point,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001199 __thousands_sep);
1200 char __a[__num_get_base::__num_get_buf_sz] = {0};
1201 char* __a_end = __a;
1202 unsigned __g[__num_get_base::__num_get_buf_sz];
1203 unsigned* __g_end = __g;
1204 unsigned __dc = 0;
1205 bool __in_units = true;
1206 char __exp = 'E';
1207 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001208 if (this->__stage2_float_loop(*__b, __in_units, __exp, __a, __a_end,
1209 __decimal_point, __thousands_sep,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001210 __grouping, __g, __g_end,
1211 __dc, __atoms))
1212 break;
1213 if (__grouping.size() != 0 && __in_units && __g_end-__g < __num_get_base::__num_get_buf_sz)
1214 *__g_end++ = __dc;
1215 // Stage 3
1216 __v = __num_get_float<double>(__a, __a_end, __err);
1217 // Digit grouping checked
1218 __check_grouping(__grouping, __g, __g_end, __err);
1219 // EOF checked
1220 if (__b == __e)
1221 __err |= ios_base::eofbit;
1222 return __b;
1223}
1224
1225template <class _CharT, class _InputIterator>
1226_InputIterator
1227num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1228 ios_base& __iob,
1229 ios_base::iostate& __err,
1230 long double& __v) const
1231{
1232 // Stage 1, nothing to do
1233 // Stage 2
1234 char_type __atoms[32];
1235 char_type __decimal_point;
1236 char_type __thousands_sep;
Howard Hinnant324bb032010-08-22 00:02:43 +00001237 string __grouping = this->__stage2_float_prep(__iob, __atoms,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001238 __decimal_point,
1239 __thousands_sep);
1240 char __a[__num_get_base::__num_get_buf_sz] = {0};
1241 char* __a_end = __a;
1242 unsigned __g[__num_get_base::__num_get_buf_sz];
1243 unsigned* __g_end = __g;
1244 unsigned __dc = 0;
1245 bool __in_units = true;
1246 char __exp = 'E';
1247 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001248 if (this->__stage2_float_loop(*__b, __in_units, __exp, __a, __a_end,
1249 __decimal_point, __thousands_sep,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001250 __grouping, __g, __g_end,
1251 __dc, __atoms))
1252 break;
1253 if (__grouping.size() != 0 && __in_units && __g_end-__g < __num_get_base::__num_get_buf_sz)
1254 *__g_end++ = __dc;
1255 // Stage 3
1256 __v = __num_get_float<long double>(__a, __a_end, __err);
1257 // Digit grouping checked
1258 __check_grouping(__grouping, __g, __g_end, __err);
1259 // EOF checked
1260 if (__b == __e)
1261 __err |= ios_base::eofbit;
1262 return __b;
1263}
1264
1265template <class _CharT, class _InputIterator>
1266_InputIterator
1267num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1268 ios_base& __iob,
1269 ios_base::iostate& __err,
1270 void*& __v) const
1271{
1272 // Stage 1
1273 int __base = 16;
1274 // Stage 2
1275 char_type __atoms[26];
1276 char_type __thousands_sep;
1277 string __grouping;
1278 use_facet<ctype<_CharT> >(__iob.getloc()).widen(__num_get_base::__src,
1279 __num_get_base::__src + 26, __atoms);
1280 char __a[__num_get_base::__num_get_buf_sz] = {0};
1281 char* __a_end = __a;
1282 unsigned __g[__num_get_base::__num_get_buf_sz];
1283 unsigned* __g_end = __g;
1284 unsigned __dc = 0;
1285 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001286 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
1287 __thousands_sep, __grouping,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001288 __g, __g_end, __atoms))
1289 break;
1290 // Stage 3
1291 __a[sizeof(__a)-1] = 0;
Howard Hinnant866569b2011-09-28 23:39:33 +00001292#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001293 if (sscanf_l(__a, _LIBCPP_GET_C_LOCALE, "%p", &__v) != 1)
Sean Huntf3907e62011-07-15 05:40:33 +00001294#else
1295 if (__sscanf_l(__a, __cloc(), "%p", &__v) != 1)
1296#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001297 __err = ios_base::failbit;
1298 // EOF checked
1299 if (__b == __e)
1300 __err |= ios_base::eofbit;
1301 return __b;
1302}
1303
1304extern template class num_get<char>;
1305extern template class num_get<wchar_t>;
1306
1307struct __num_put_base
1308{
1309protected:
1310 static void __format_int(char* __fmt, const char* __len, bool __signd,
1311 ios_base::fmtflags __flags);
1312 static bool __format_float(char* __fmt, const char* __len,
1313 ios_base::fmtflags __flags);
1314 static char* __identify_padding(char* __nb, char* __ne,
1315 const ios_base& __iob);
1316};
1317
1318template <class _CharT>
1319struct __num_put
1320 : protected __num_put_base
1321{
1322 static void __widen_and_group_int(char* __nb, char* __np, char* __ne,
1323 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1324 const locale& __loc);
1325 static void __widen_and_group_float(char* __nb, char* __np, char* __ne,
1326 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1327 const locale& __loc);
1328};
1329
1330template <class _CharT>
1331void
1332__num_put<_CharT>::__widen_and_group_int(char* __nb, char* __np, char* __ne,
1333 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1334 const locale& __loc)
1335{
1336 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> > (__loc);
1337 const numpunct<_CharT>& __npt = use_facet<numpunct<_CharT> >(__loc);
1338 string __grouping = __npt.grouping();
1339 if (__grouping.empty())
1340 {
1341 __ct.widen(__nb, __ne, __ob);
1342 __oe = __ob + (__ne - __nb);
1343 }
1344 else
1345 {
1346 __oe = __ob;
1347 char* __nf = __nb;
1348 if (*__nf == '-' || *__nf == '+')
1349 *__oe++ = __ct.widen(*__nf++);
1350 if (__ne - __nf >= 2 && __nf[0] == '0' && (__nf[1] == 'x' ||
1351 __nf[1] == 'X'))
1352 {
1353 *__oe++ = __ct.widen(*__nf++);
1354 *__oe++ = __ct.widen(*__nf++);
1355 }
1356 reverse(__nf, __ne);
1357 _CharT __thousands_sep = __npt.thousands_sep();
1358 unsigned __dc = 0;
1359 unsigned __dg = 0;
1360 for (char* __p = __nf; __p < __ne; ++__p)
1361 {
1362 if (static_cast<unsigned>(__grouping[__dg]) > 0 &&
1363 __dc == static_cast<unsigned>(__grouping[__dg]))
1364 {
1365 *__oe++ = __thousands_sep;
1366 __dc = 0;
1367 if (__dg < __grouping.size()-1)
1368 ++__dg;
1369 }
1370 *__oe++ = __ct.widen(*__p);
1371 ++__dc;
1372 }
1373 reverse(__ob + (__nf - __nb), __oe);
1374 }
1375 if (__np == __ne)
1376 __op = __oe;
1377 else
1378 __op = __ob + (__np - __nb);
1379}
1380
1381template <class _CharT>
1382void
1383__num_put<_CharT>::__widen_and_group_float(char* __nb, char* __np, char* __ne,
1384 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1385 const locale& __loc)
1386{
1387 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> > (__loc);
1388 const numpunct<_CharT>& __npt = use_facet<numpunct<_CharT> >(__loc);
1389 string __grouping = __npt.grouping();
1390 __oe = __ob;
1391 char* __nf = __nb;
1392 if (*__nf == '-' || *__nf == '+')
1393 *__oe++ = __ct.widen(*__nf++);
1394 char* __ns;
1395 if (__ne - __nf >= 2 && __nf[0] == '0' && (__nf[1] == 'x' ||
1396 __nf[1] == 'X'))
1397 {
1398 *__oe++ = __ct.widen(*__nf++);
1399 *__oe++ = __ct.widen(*__nf++);
1400 for (__ns = __nf; __ns < __ne; ++__ns)
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001401 if (!isxdigit_l(*__ns, _LIBCPP_GET_C_LOCALE))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001402 break;
1403 }
1404 else
1405 {
1406 for (__ns = __nf; __ns < __ne; ++__ns)
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001407 if (!isdigit_l(*__ns, _LIBCPP_GET_C_LOCALE))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001408 break;
1409 }
1410 if (__grouping.empty())
1411 {
1412 __ct.widen(__nf, __ns, __oe);
1413 __oe += __ns - __nf;
1414 }
1415 else
1416 {
1417 reverse(__nf, __ns);
1418 _CharT __thousands_sep = __npt.thousands_sep();
1419 unsigned __dc = 0;
1420 unsigned __dg = 0;
1421 for (char* __p = __nf; __p < __ns; ++__p)
1422 {
1423 if (__grouping[__dg] > 0 && __dc == static_cast<unsigned>(__grouping[__dg]))
1424 {
1425 *__oe++ = __thousands_sep;
1426 __dc = 0;
1427 if (__dg < __grouping.size()-1)
1428 ++__dg;
1429 }
1430 *__oe++ = __ct.widen(*__p);
1431 ++__dc;
1432 }
1433 reverse(__ob + (__nf - __nb), __oe);
1434 }
1435 for (__nf = __ns; __nf < __ne; ++__nf)
1436 {
1437 if (*__nf == '.')
1438 {
1439 *__oe++ = __npt.decimal_point();
1440 ++__nf;
1441 break;
1442 }
1443 else
1444 *__oe++ = __ct.widen(*__nf);
1445 }
1446 __ct.widen(__nf, __ne, __oe);
1447 __oe += __ne - __nf;
1448 if (__np == __ne)
1449 __op = __oe;
1450 else
1451 __op = __ob + (__np - __nb);
1452}
1453
1454extern template class __num_put<char>;
1455extern template class __num_put<wchar_t>;
1456
1457template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00001458class _LIBCPP_VISIBLE num_put
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001459 : public locale::facet,
1460 private __num_put<_CharT>
1461{
1462public:
1463 typedef _CharT char_type;
1464 typedef _OutputIterator iter_type;
1465
1466 _LIBCPP_ALWAYS_INLINE
1467 explicit num_put(size_t __refs = 0)
1468 : locale::facet(__refs) {}
1469
1470 _LIBCPP_ALWAYS_INLINE
1471 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1472 bool __v) const
1473 {
1474 return do_put(__s, __iob, __fl, __v);
1475 }
1476
1477 _LIBCPP_ALWAYS_INLINE
1478 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1479 long __v) const
1480 {
1481 return do_put(__s, __iob, __fl, __v);
1482 }
1483
1484 _LIBCPP_ALWAYS_INLINE
1485 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1486 long long __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 unsigned 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 unsigned 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 double __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 long double __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 const void* __v) const
1522 {
1523 return do_put(__s, __iob, __fl, __v);
1524 }
1525
1526 static locale::id id;
1527
1528protected:
Howard Hinnant82894812010-09-22 16:48:34 +00001529 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001530 ~num_put() {}
1531
1532 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1533 bool __v) const;
1534 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1535 long __v) const;
1536 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1537 long long __v) const;
1538 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1539 unsigned long) const;
1540 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1541 unsigned long long) const;
1542 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1543 double __v) const;
1544 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1545 long double __v) const;
1546 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1547 const void* __v) const;
1548};
1549
1550template <class _CharT, class _OutputIterator>
1551locale::id
1552num_put<_CharT, _OutputIterator>::id;
1553
1554template <class _CharT, class _OutputIterator>
1555_LIBCPP_HIDDEN
1556_OutputIterator
1557__pad_and_output(_OutputIterator __s,
1558 const _CharT* __ob, const _CharT* __op, const _CharT* __oe,
1559 ios_base& __iob, _CharT __fl)
1560{
1561 streamsize __sz = __oe - __ob;
1562 streamsize __ns = __iob.width();
1563 if (__ns > __sz)
1564 __ns -= __sz;
1565 else
1566 __ns = 0;
1567 for (;__ob < __op; ++__ob, ++__s)
1568 *__s = *__ob;
1569 for (; __ns; --__ns, ++__s)
1570 *__s = __fl;
1571 for (; __ob < __oe; ++__ob, ++__s)
1572 *__s = *__ob;
1573 __iob.width(0);
1574 return __s;
1575}
1576
1577template <class _CharT, class _OutputIterator>
1578_OutputIterator
1579num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1580 char_type __fl, bool __v) const
1581{
1582 if ((__iob.flags() & ios_base::boolalpha) == 0)
1583 return do_put(__s, __iob, __fl, (unsigned long)__v);
1584 const numpunct<char_type>& __np = use_facet<numpunct<char_type> >(__iob.getloc());
1585 typedef typename numpunct<char_type>::string_type string_type;
1586 string_type __nm = __v ? __np.truename() : __np.falsename();
1587 for (typename string_type::iterator __i = __nm.begin(); __i != __nm.end(); ++__i, ++__s)
1588 *__s = *__i;
1589 return __s;
1590}
1591
1592template <class _CharT, class _OutputIterator>
1593_OutputIterator
1594num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1595 char_type __fl, long __v) const
1596{
1597 // Stage 1 - Get number in narrow char
1598 char __fmt[6] = {'%', 0};
1599 const char* __len = "l";
1600 this->__format_int(__fmt+1, __len, true, __iob.flags());
1601 const unsigned __nbuf = (numeric_limits<long>::digits / 3)
1602 + ((numeric_limits<long>::digits % 3) != 0)
1603 + 1;
1604 char __nar[__nbuf];
Howard Hinnant866569b2011-09-28 23:39:33 +00001605#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001606 int __nc = sprintf_l(__nar, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001607#else
1608 int __nc = __sprintf_l(__nar, __cloc(), __fmt, __v);
1609#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001610 char* __ne = __nar + __nc;
1611 char* __np = this->__identify_padding(__nar, __ne, __iob);
1612 // Stage 2 - Widen __nar while adding thousands separators
1613 char_type __o[2*(__nbuf-1) - 1];
1614 char_type* __op; // pad here
1615 char_type* __oe; // end of output
1616 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1617 // [__o, __oe) contains thousands_sep'd wide number
1618 // Stage 3 & 4
1619 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1620}
1621
1622template <class _CharT, class _OutputIterator>
1623_OutputIterator
1624num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1625 char_type __fl, long long __v) const
1626{
1627 // Stage 1 - Get number in narrow char
1628 char __fmt[8] = {'%', 0};
1629 const char* __len = "ll";
1630 this->__format_int(__fmt+1, __len, true, __iob.flags());
1631 const unsigned __nbuf = (numeric_limits<long long>::digits / 3)
1632 + ((numeric_limits<long long>::digits % 3) != 0)
1633 + 1;
1634 char __nar[__nbuf];
Howard Hinnant866569b2011-09-28 23:39:33 +00001635#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001636 int __nc = sprintf_l(__nar, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001637#else
1638 int __nc = __sprintf_l(__nar, __cloc(), __fmt, __v);
1639#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001640 char* __ne = __nar + __nc;
1641 char* __np = this->__identify_padding(__nar, __ne, __iob);
1642 // Stage 2 - Widen __nar while adding thousands separators
1643 char_type __o[2*(__nbuf-1) - 1];
1644 char_type* __op; // pad here
1645 char_type* __oe; // end of output
1646 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1647 // [__o, __oe) contains thousands_sep'd wide number
1648 // Stage 3 & 4
1649 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1650}
1651
1652template <class _CharT, class _OutputIterator>
1653_OutputIterator
1654num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1655 char_type __fl, unsigned long __v) const
1656{
1657 // Stage 1 - Get number in narrow char
1658 char __fmt[6] = {'%', 0};
1659 const char* __len = "l";
1660 this->__format_int(__fmt+1, __len, false, __iob.flags());
1661 const unsigned __nbuf = (numeric_limits<unsigned long>::digits / 3)
1662 + ((numeric_limits<unsigned long>::digits % 3) != 0)
1663 + 1;
1664 char __nar[__nbuf];
Howard Hinnant866569b2011-09-28 23:39:33 +00001665#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001666 int __nc = sprintf_l(__nar, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001667#else
1668 int __nc = __sprintf_l(__nar, __cloc(), __fmt, __v);
1669#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001670 char* __ne = __nar + __nc;
1671 char* __np = this->__identify_padding(__nar, __ne, __iob);
1672 // Stage 2 - Widen __nar while adding thousands separators
1673 char_type __o[2*(__nbuf-1) - 1];
1674 char_type* __op; // pad here
1675 char_type* __oe; // end of output
1676 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1677 // [__o, __oe) contains thousands_sep'd wide number
1678 // Stage 3 & 4
1679 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1680}
1681
1682template <class _CharT, class _OutputIterator>
1683_OutputIterator
1684num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1685 char_type __fl, unsigned long long __v) const
1686{
1687 // Stage 1 - Get number in narrow char
1688 char __fmt[8] = {'%', 0};
1689 const char* __len = "ll";
1690 this->__format_int(__fmt+1, __len, false, __iob.flags());
1691 const unsigned __nbuf = (numeric_limits<unsigned long long>::digits / 3)
1692 + ((numeric_limits<unsigned long long>::digits % 3) != 0)
1693 + 1;
1694 char __nar[__nbuf];
Howard Hinnant866569b2011-09-28 23:39:33 +00001695#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001696 int __nc = sprintf_l(__nar, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001697#else
1698 int __nc = __sprintf_l(__nar, __cloc(), __fmt, __v);
1699#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001700 char* __ne = __nar + __nc;
1701 char* __np = this->__identify_padding(__nar, __ne, __iob);
1702 // Stage 2 - Widen __nar while adding thousands separators
1703 char_type __o[2*(__nbuf-1) - 1];
1704 char_type* __op; // pad here
1705 char_type* __oe; // end of output
1706 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1707 // [__o, __oe) contains thousands_sep'd wide number
1708 // Stage 3 & 4
1709 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1710}
1711
1712template <class _CharT, class _OutputIterator>
1713_OutputIterator
1714num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1715 char_type __fl, double __v) const
1716{
1717 // Stage 1 - Get number in narrow char
1718 char __fmt[8] = {'%', 0};
1719 const char* __len = "";
1720 bool __specify_precision = this->__format_float(__fmt+1, __len, __iob.flags());
1721 const unsigned __nbuf = 30;
1722 char __nar[__nbuf];
1723 char* __nb = __nar;
1724 int __nc;
1725 if (__specify_precision)
Howard Hinnant866569b2011-09-28 23:39:33 +00001726#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001727 __nc = snprintf_l(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt,
Howard Hinnantadff4892010-05-24 17:49:41 +00001728 (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001729#else
1730 __nc = __snprintf_l(__nb, __nbuf, __cloc(), __fmt,
1731 (int)__iob.precision(), __v);
1732#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001733 else
Howard Hinnant866569b2011-09-28 23:39:33 +00001734#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001735 __nc = snprintf_l(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001736#else
1737 __nc = __snprintf_l(__nb, __nbuf, __cloc(), __fmt, __v);
1738#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001739 unique_ptr<char, void(*)(void*)> __nbh(0, free);
1740 if (__nc > static_cast<int>(__nbuf-1))
1741 {
1742 if (__specify_precision)
Howard Hinnant866569b2011-09-28 23:39:33 +00001743#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001744 __nc = asprintf_l(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001745#else
1746 __nc = __asprintf_l(&__nb, __cloc(), __fmt,
David Chisnallc512df12011-09-21 08:39:44 +00001747 (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001748#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001749 else
Howard Hinnant866569b2011-09-28 23:39:33 +00001750#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001751 __nc = asprintf_l(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001752#else
David Chisnallc512df12011-09-21 08:39:44 +00001753 __nc = __asprintf_l(&__nb, __cloc(), __fmt, (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001754#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001755 if (__nb == 0)
1756 __throw_bad_alloc();
1757 __nbh.reset(__nb);
1758 }
1759 char* __ne = __nb + __nc;
1760 char* __np = this->__identify_padding(__nb, __ne, __iob);
1761 // Stage 2 - Widen __nar while adding thousands separators
1762 char_type __o[2*(__nbuf-1) - 1];
1763 char_type* __ob = __o;
1764 unique_ptr<char_type, void(*)(void*)> __obh(0, free);
1765 if (__nb != __nar)
1766 {
1767 __ob = (char_type*)malloc((2*__nc)*sizeof(char_type));
1768 if (__ob == 0)
1769 __throw_bad_alloc();
1770 __obh.reset(__ob);
1771 }
1772 char_type* __op; // pad here
1773 char_type* __oe; // end of output
1774 this->__widen_and_group_float(__nb, __np, __ne, __ob, __op, __oe, __iob.getloc());
1775 // [__o, __oe) contains thousands_sep'd wide number
1776 // Stage 3 & 4
1777 __s = __pad_and_output(__s, __ob, __op, __oe, __iob, __fl);
1778 return __s;
1779}
1780
1781template <class _CharT, class _OutputIterator>
1782_OutputIterator
1783num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1784 char_type __fl, long double __v) const
1785{
1786 // Stage 1 - Get number in narrow char
1787 char __fmt[8] = {'%', 0};
1788 const char* __len = "L";
1789 bool __specify_precision = this->__format_float(__fmt+1, __len, __iob.flags());
1790 const unsigned __nbuf = 30;
1791 char __nar[__nbuf];
1792 char* __nb = __nar;
1793 int __nc;
1794 if (__specify_precision)
Howard Hinnant866569b2011-09-28 23:39:33 +00001795#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001796 __nc = snprintf_l(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt,
Howard Hinnantadff4892010-05-24 17:49:41 +00001797 (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001798#else
1799 __nc = __snprintf_l(__nb, __nbuf, __cloc(), __fmt,
1800 (int)__iob.precision(), __v);
1801#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001802 else
Howard Hinnant866569b2011-09-28 23:39:33 +00001803#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001804 __nc = snprintf_l(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001805#else
1806 __nc = __snprintf_l(__nb, __nbuf, __cloc(), __fmt, __v);
1807#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001808 unique_ptr<char, void(*)(void*)> __nbh(0, free);
1809 if (__nc > static_cast<int>(__nbuf-1))
1810 {
1811 if (__specify_precision)
Howard Hinnant866569b2011-09-28 23:39:33 +00001812#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001813 __nc = asprintf_l(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001814#else
1815 __nc = __asprintf_l(&__nb, __cloc(), __fmt,
David Chisnallc512df12011-09-21 08:39:44 +00001816 (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001817#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001818 else
Howard Hinnant866569b2011-09-28 23:39:33 +00001819#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001820 __nc = asprintf_l(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001821#else
David Chisnallc512df12011-09-21 08:39:44 +00001822 __nc = __asprintf_l(&__nb, __cloc(), __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001823#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001824 if (__nb == 0)
1825 __throw_bad_alloc();
1826 __nbh.reset(__nb);
1827 }
1828 char* __ne = __nb + __nc;
1829 char* __np = this->__identify_padding(__nb, __ne, __iob);
1830 // Stage 2 - Widen __nar while adding thousands separators
1831 char_type __o[2*(__nbuf-1) - 1];
1832 char_type* __ob = __o;
1833 unique_ptr<char_type, void(*)(void*)> __obh(0, free);
1834 if (__nb != __nar)
1835 {
1836 __ob = (char_type*)malloc((2*__nc)*sizeof(char_type));
1837 if (__ob == 0)
1838 __throw_bad_alloc();
1839 __obh.reset(__ob);
1840 }
1841 char_type* __op; // pad here
1842 char_type* __oe; // end of output
1843 this->__widen_and_group_float(__nb, __np, __ne, __ob, __op, __oe, __iob.getloc());
1844 // [__o, __oe) contains thousands_sep'd wide number
1845 // Stage 3 & 4
1846 __s = __pad_and_output(__s, __ob, __op, __oe, __iob, __fl);
1847 return __s;
1848}
1849
1850template <class _CharT, class _OutputIterator>
1851_OutputIterator
1852num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1853 char_type __fl, const void* __v) const
1854{
1855 // Stage 1 - Get pointer in narrow char
1856 char __fmt[6] = "%p";
1857 const unsigned __nbuf = 20;
1858 char __nar[__nbuf];
Howard Hinnant866569b2011-09-28 23:39:33 +00001859#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001860 int __nc = sprintf_l(__nar, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001861#else
1862 int __nc = __sprintf_l(__nar, __cloc(), __fmt, __v);
1863#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001864 char* __ne = __nar + __nc;
1865 char* __np = this->__identify_padding(__nar, __ne, __iob);
1866 // Stage 2 - Widen __nar
1867 char_type __o[2*(__nbuf-1) - 1];
1868 char_type* __op; // pad here
1869 char_type* __oe; // end of output
1870 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
1871 __ct.widen(__nar, __ne, __o);
1872 __oe = __o + (__ne - __nar);
1873 if (__np == __ne)
1874 __op = __oe;
1875 else
1876 __op = __o + (__np - __nar);
1877 // [__o, __oe) contains wide number
1878 // Stage 3 & 4
1879 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1880}
1881
1882extern template class num_put<char>;
1883extern template class num_put<wchar_t>;
1884
1885template <class _CharT, class _InputIterator>
1886_LIBCPP_HIDDEN
1887int
1888__get_up_to_n_digits(_InputIterator& __b, _InputIterator __e,
1889 ios_base::iostate& __err, const ctype<_CharT>& __ct, int __n)
1890{
1891 // Precondition: __n >= 1
1892 if (__b == __e)
1893 {
1894 __err |= ios_base::eofbit | ios_base::failbit;
1895 return 0;
1896 }
1897 // get first digit
1898 _CharT __c = *__b;
1899 if (!__ct.is(ctype_base::digit, __c))
1900 {
1901 __err |= ios_base::failbit;
1902 return 0;
1903 }
1904 int __r = __ct.narrow(__c, 0) - '0';
1905 for (++__b, --__n; __b != __e && __n > 0; ++__b, --__n)
1906 {
1907 // get next digit
1908 __c = *__b;
1909 if (!__ct.is(ctype_base::digit, __c))
1910 return __r;
1911 __r = __r * 10 + __ct.narrow(__c, 0) - '0';
1912 }
1913 if (__b == __e)
1914 __err |= ios_base::eofbit;
1915 return __r;
1916}
1917
Howard Hinnant82894812010-09-22 16:48:34 +00001918class _LIBCPP_VISIBLE time_base
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001919{
1920public:
1921 enum dateorder {no_order, dmy, mdy, ymd, ydm};
1922};
1923
1924template <class _CharT>
Howard Hinnant2d72b1e2010-12-17 14:46:43 +00001925class __time_get_c_storage // purposefully not decorated
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001926{
1927protected:
1928 typedef basic_string<_CharT> string_type;
1929
1930 virtual const string_type* __weeks() const;
1931 virtual const string_type* __months() const;
1932 virtual const string_type* __am_pm() const;
1933 virtual const string_type& __c() const;
1934 virtual const string_type& __r() const;
1935 virtual const string_type& __x() const;
1936 virtual const string_type& __X() const;
1937};
1938
1939template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00001940class _LIBCPP_VISIBLE time_get
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001941 : public locale::facet,
1942 public time_base,
1943 private __time_get_c_storage<_CharT>
1944{
1945public:
1946 typedef _CharT char_type;
1947 typedef _InputIterator iter_type;
1948 typedef time_base::dateorder dateorder;
1949 typedef basic_string<char_type> string_type;
1950
1951 _LIBCPP_ALWAYS_INLINE
1952 explicit time_get(size_t __refs = 0)
1953 : locale::facet(__refs) {}
1954
1955 _LIBCPP_ALWAYS_INLINE
1956 dateorder date_order() const
1957 {
1958 return this->do_date_order();
1959 }
1960
1961 _LIBCPP_ALWAYS_INLINE
1962 iter_type get_time(iter_type __b, iter_type __e, ios_base& __iob,
1963 ios_base::iostate& __err, tm* __tm) const
1964 {
1965 return do_get_time(__b, __e, __iob, __err, __tm);
1966 }
1967
1968 _LIBCPP_ALWAYS_INLINE
1969 iter_type get_date(iter_type __b, iter_type __e, ios_base& __iob,
1970 ios_base::iostate& __err, tm* __tm) const
1971 {
1972 return do_get_date(__b, __e, __iob, __err, __tm);
1973 }
1974
1975 _LIBCPP_ALWAYS_INLINE
1976 iter_type get_weekday(iter_type __b, iter_type __e, ios_base& __iob,
1977 ios_base::iostate& __err, tm* __tm) const
1978 {
1979 return do_get_weekday(__b, __e, __iob, __err, __tm);
1980 }
1981
1982 _LIBCPP_ALWAYS_INLINE
1983 iter_type get_monthname(iter_type __b, iter_type __e, ios_base& __iob,
1984 ios_base::iostate& __err, tm* __tm) const
1985 {
1986 return do_get_monthname(__b, __e, __iob, __err, __tm);
1987 }
1988
1989 _LIBCPP_ALWAYS_INLINE
1990 iter_type get_year(iter_type __b, iter_type __e, ios_base& __iob,
1991 ios_base::iostate& __err, tm* __tm) const
1992 {
1993 return do_get_year(__b, __e, __iob, __err, __tm);
1994 }
1995
1996 _LIBCPP_ALWAYS_INLINE
1997 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
1998 ios_base::iostate& __err, tm *__tm,
1999 char __fmt, char __mod = 0) const
2000 {
2001 return do_get(__b, __e, __iob, __err, __tm, __fmt, __mod);
2002 }
2003
2004 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
2005 ios_base::iostate& __err, tm* __tm,
2006 const char_type* __fmtb, const char_type* __fmte) const;
2007
2008 static locale::id id;
2009
2010protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002011 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002012 ~time_get() {}
2013
2014 virtual dateorder do_date_order() const;
2015 virtual iter_type do_get_time(iter_type __b, iter_type __e, ios_base& __iob,
2016 ios_base::iostate& __err, tm* __tm) const;
2017 virtual iter_type do_get_date(iter_type __b, iter_type __e, ios_base& __iob,
2018 ios_base::iostate& __err, tm* __tm) const;
2019 virtual iter_type do_get_weekday(iter_type __b, iter_type __e, ios_base& __iob,
2020 ios_base::iostate& __err, tm* __tm) const;
2021 virtual iter_type do_get_monthname(iter_type __b, iter_type __e, ios_base& __iob,
2022 ios_base::iostate& __err, tm* __tm) const;
2023 virtual iter_type do_get_year(iter_type __b, iter_type __e, ios_base& __iob,
2024 ios_base::iostate& __err, tm* __tm) const;
2025 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
2026 ios_base::iostate& __err, tm* __tm,
2027 char __fmt, char __mod) const;
2028private:
2029 void __get_white_space(iter_type& __b, iter_type __e,
2030 ios_base::iostate& __err, const ctype<char_type>& __ct) const;
2031 void __get_percent(iter_type& __b, iter_type __e, ios_base::iostate& __err,
2032 const ctype<char_type>& __ct) const;
2033
2034 void __get_weekdayname(int& __m,
2035 iter_type& __b, iter_type __e,
2036 ios_base::iostate& __err,
2037 const ctype<char_type>& __ct) const;
2038 void __get_monthname(int& __m,
2039 iter_type& __b, iter_type __e,
2040 ios_base::iostate& __err,
2041 const ctype<char_type>& __ct) const;
2042 void __get_day(int& __d,
2043 iter_type& __b, iter_type __e,
2044 ios_base::iostate& __err,
2045 const ctype<char_type>& __ct) const;
2046 void __get_month(int& __m,
2047 iter_type& __b, iter_type __e,
2048 ios_base::iostate& __err,
2049 const ctype<char_type>& __ct) const;
2050 void __get_year(int& __y,
2051 iter_type& __b, iter_type __e,
2052 ios_base::iostate& __err,
2053 const ctype<char_type>& __ct) const;
2054 void __get_year4(int& __y,
2055 iter_type& __b, iter_type __e,
2056 ios_base::iostate& __err,
2057 const ctype<char_type>& __ct) const;
2058 void __get_hour(int& __d,
2059 iter_type& __b, iter_type __e,
2060 ios_base::iostate& __err,
2061 const ctype<char_type>& __ct) const;
2062 void __get_12_hour(int& __h,
2063 iter_type& __b, iter_type __e,
2064 ios_base::iostate& __err,
2065 const ctype<char_type>& __ct) const;
2066 void __get_am_pm(int& __h,
2067 iter_type& __b, iter_type __e,
2068 ios_base::iostate& __err,
2069 const ctype<char_type>& __ct) const;
2070 void __get_minute(int& __m,
2071 iter_type& __b, iter_type __e,
2072 ios_base::iostate& __err,
2073 const ctype<char_type>& __ct) const;
2074 void __get_second(int& __s,
2075 iter_type& __b, iter_type __e,
2076 ios_base::iostate& __err,
2077 const ctype<char_type>& __ct) const;
2078 void __get_weekday(int& __w,
2079 iter_type& __b, iter_type __e,
2080 ios_base::iostate& __err,
2081 const ctype<char_type>& __ct) const;
2082 void __get_day_year_num(int& __w,
2083 iter_type& __b, iter_type __e,
2084 ios_base::iostate& __err,
2085 const ctype<char_type>& __ct) const;
2086};
2087
2088template <class _CharT, class _InputIterator>
2089locale::id
2090time_get<_CharT, _InputIterator>::id;
2091
2092// time_get primatives
2093
2094template <class _CharT, class _InputIterator>
2095void
2096time_get<_CharT, _InputIterator>::__get_weekdayname(int& __w,
2097 iter_type& __b, iter_type __e,
2098 ios_base::iostate& __err,
2099 const ctype<char_type>& __ct) const
2100{
2101 // Note: ignoring case comes from the POSIX strptime spec
2102 const string_type* __wk = this->__weeks();
2103 int __i = __scan_keyword(__b, __e, __wk, __wk+14, __ct, __err, false) - __wk;
2104 if (__i < 14)
2105 __w = __i % 7;
2106}
2107
2108template <class _CharT, class _InputIterator>
2109void
2110time_get<_CharT, _InputIterator>::__get_monthname(int& __m,
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* __month = this->__months();
2117 int __i = __scan_keyword(__b, __e, __month, __month+24, __ct, __err, false) - __month;
2118 if (__i < 24)
2119 __m = __i % 12;
2120}
2121
2122template <class _CharT, class _InputIterator>
2123void
2124time_get<_CharT, _InputIterator>::__get_day(int& __d,
2125 iter_type& __b, iter_type __e,
2126 ios_base::iostate& __err,
2127 const ctype<char_type>& __ct) const
2128{
2129 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2130 if (!(__err & ios_base::failbit) && 1 <= __t && __t <= 31)
2131 __d = __t;
2132 else
2133 __err |= ios_base::failbit;
2134}
2135
2136template <class _CharT, class _InputIterator>
2137void
2138time_get<_CharT, _InputIterator>::__get_month(int& __m,
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) - 1;
2144 if (!(__err & ios_base::failbit) && __t <= 11)
2145 __m = __t;
2146 else
2147 __err |= ios_base::failbit;
2148}
2149
2150template <class _CharT, class _InputIterator>
2151void
2152time_get<_CharT, _InputIterator>::__get_year(int& __y,
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, 4);
2158 if (!(__err & ios_base::failbit))
2159 {
2160 if (__t < 69)
2161 __t += 2000;
2162 else if (69 <= __t && __t <= 99)
2163 __t += 1900;
2164 __y = __t - 1900;
2165 }
2166}
2167
2168template <class _CharT, class _InputIterator>
2169void
2170time_get<_CharT, _InputIterator>::__get_year4(int& __y,
2171 iter_type& __b, iter_type __e,
2172 ios_base::iostate& __err,
2173 const ctype<char_type>& __ct) const
2174{
2175 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 4);
2176 if (!(__err & ios_base::failbit))
2177 __y = __t - 1900;
2178}
2179
2180template <class _CharT, class _InputIterator>
2181void
2182time_get<_CharT, _InputIterator>::__get_hour(int& __h,
2183 iter_type& __b, iter_type __e,
2184 ios_base::iostate& __err,
2185 const ctype<char_type>& __ct) const
2186{
2187 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2188 if (!(__err & ios_base::failbit) && __t <= 23)
2189 __h = __t;
2190 else
2191 __err |= ios_base::failbit;
2192}
2193
2194template <class _CharT, class _InputIterator>
2195void
2196time_get<_CharT, _InputIterator>::__get_12_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) && 1 <= __t && __t <= 12)
2203 __h = __t;
2204 else
2205 __err |= ios_base::failbit;
2206}
2207
2208template <class _CharT, class _InputIterator>
2209void
2210time_get<_CharT, _InputIterator>::__get_minute(int& __m,
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) && __t <= 59)
2217 __m = __t;
2218 else
2219 __err |= ios_base::failbit;
2220}
2221
2222template <class _CharT, class _InputIterator>
2223void
2224time_get<_CharT, _InputIterator>::__get_second(int& __s,
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 <= 60)
2231 __s = __t;
2232 else
2233 __err |= ios_base::failbit;
2234}
2235
2236template <class _CharT, class _InputIterator>
2237void
2238time_get<_CharT, _InputIterator>::__get_weekday(int& __w,
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, 1);
2244 if (!(__err & ios_base::failbit) && __t <= 6)
2245 __w = __t;
2246 else
2247 __err |= ios_base::failbit;
2248}
2249
2250template <class _CharT, class _InputIterator>
2251void
2252time_get<_CharT, _InputIterator>::__get_day_year_num(int& __d,
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, 3);
2258 if (!(__err & ios_base::failbit) && __t <= 365)
2259 __d = __t;
2260 else
2261 __err |= ios_base::failbit;
2262}
2263
2264template <class _CharT, class _InputIterator>
2265void
2266time_get<_CharT, _InputIterator>::__get_white_space(iter_type& __b, iter_type __e,
2267 ios_base::iostate& __err,
2268 const ctype<char_type>& __ct) const
2269{
2270 for (; __b != __e && __ct.is(ctype_base::space, *__b); ++__b)
2271 ;
2272 if (__b == __e)
2273 __err |= ios_base::eofbit;
2274}
2275
2276template <class _CharT, class _InputIterator>
2277void
2278time_get<_CharT, _InputIterator>::__get_am_pm(int& __h,
2279 iter_type& __b, iter_type __e,
2280 ios_base::iostate& __err,
2281 const ctype<char_type>& __ct) const
2282{
2283 const string_type* __ap = this->__am_pm();
2284 if (__ap[0].size() + __ap[1].size() == 0)
2285 {
2286 __err |= ios_base::failbit;
2287 return;
2288 }
2289 int __i = __scan_keyword(__b, __e, __ap, __ap+2, __ct, __err, false) - __ap;
2290 if (__i == 0 && __h == 12)
2291 __h = 0;
2292 else if (__i == 1 && __h < 12)
2293 __h += 12;
2294}
2295
2296template <class _CharT, class _InputIterator>
2297void
2298time_get<_CharT, _InputIterator>::__get_percent(iter_type& __b, iter_type __e,
2299 ios_base::iostate& __err,
2300 const ctype<char_type>& __ct) const
2301{
2302 if (__b == __e)
2303 {
2304 __err |= ios_base::eofbit | ios_base::failbit;
2305 return;
2306 }
2307 if (__ct.narrow(*__b, 0) != '%')
2308 __err |= ios_base::failbit;
2309 else if(++__b == __e)
2310 __err |= ios_base::eofbit;
2311}
2312
2313// time_get end primatives
2314
2315template <class _CharT, class _InputIterator>
2316_InputIterator
2317time_get<_CharT, _InputIterator>::get(iter_type __b, iter_type __e,
2318 ios_base& __iob,
2319 ios_base::iostate& __err, tm* __tm,
2320 const char_type* __fmtb, const char_type* __fmte) const
2321{
2322 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2323 __err = ios_base::goodbit;
2324 while (__fmtb != __fmte && __err == ios_base::goodbit)
2325 {
2326 if (__b == __e)
2327 {
2328 __err = ios_base::failbit;
2329 break;
2330 }
2331 if (__ct.narrow(*__fmtb, 0) == '%')
2332 {
2333 if (++__fmtb == __fmte)
2334 {
2335 __err = ios_base::failbit;
2336 break;
2337 }
2338 char __cmd = __ct.narrow(*__fmtb, 0);
2339 char __opt = '\0';
2340 if (__cmd == 'E' || __cmd == '0')
2341 {
2342 if (++__fmtb == __fmte)
2343 {
2344 __err = ios_base::failbit;
2345 break;
2346 }
2347 __opt = __cmd;
2348 __cmd = __ct.narrow(*__fmtb, 0);
2349 }
2350 __b = do_get(__b, __e, __iob, __err, __tm, __cmd, __opt);
2351 ++__fmtb;
2352 }
2353 else if (__ct.is(ctype_base::space, *__fmtb))
2354 {
2355 for (++__fmtb; __fmtb != __fmte && __ct.is(ctype_base::space, *__fmtb); ++__fmtb)
2356 ;
2357 for ( ; __b != __e && __ct.is(ctype_base::space, *__b); ++__b)
2358 ;
2359 }
2360 else if (__ct.toupper(*__b) == __ct.toupper(*__fmtb))
2361 {
2362 ++__b;
2363 ++__fmtb;
2364 }
2365 else
2366 __err = ios_base::failbit;
2367 }
2368 if (__b == __e)
2369 __err |= ios_base::eofbit;
2370 return __b;
2371}
2372
2373template <class _CharT, class _InputIterator>
2374typename time_get<_CharT, _InputIterator>::dateorder
2375time_get<_CharT, _InputIterator>::do_date_order() const
2376{
2377 return mdy;
2378}
2379
2380template <class _CharT, class _InputIterator>
2381_InputIterator
2382time_get<_CharT, _InputIterator>::do_get_time(iter_type __b, iter_type __e,
2383 ios_base& __iob,
2384 ios_base::iostate& __err,
2385 tm* __tm) const
2386{
2387 const char_type __fmt[] = {'%', 'H', ':', '%', 'M', ':', '%', 'S'};
2388 return get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2389}
2390
2391template <class _CharT, class _InputIterator>
2392_InputIterator
2393time_get<_CharT, _InputIterator>::do_get_date(iter_type __b, iter_type __e,
2394 ios_base& __iob,
2395 ios_base::iostate& __err,
2396 tm* __tm) const
2397{
2398 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2399 const string_type& __fmt = this->__x();
2400 return get(__b, __e, __iob, __err, __tm, __fmt.data(), __fmt.data() + __fmt.size());
2401}
2402
2403template <class _CharT, class _InputIterator>
2404_InputIterator
2405time_get<_CharT, _InputIterator>::do_get_weekday(iter_type __b, iter_type __e,
2406 ios_base& __iob,
2407 ios_base::iostate& __err,
2408 tm* __tm) const
2409{
2410 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2411 __get_weekdayname(__tm->tm_wday, __b, __e, __err, __ct);
2412 return __b;
2413}
2414
2415template <class _CharT, class _InputIterator>
2416_InputIterator
2417time_get<_CharT, _InputIterator>::do_get_monthname(iter_type __b, iter_type __e,
2418 ios_base& __iob,
2419 ios_base::iostate& __err,
2420 tm* __tm) const
2421{
2422 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2423 __get_monthname(__tm->tm_mon, __b, __e, __err, __ct);
2424 return __b;
2425}
2426
2427template <class _CharT, class _InputIterator>
2428_InputIterator
2429time_get<_CharT, _InputIterator>::do_get_year(iter_type __b, iter_type __e,
2430 ios_base& __iob,
2431 ios_base::iostate& __err,
2432 tm* __tm) const
2433{
2434 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2435 __get_year(__tm->tm_year, __b, __e, __err, __ct);
2436 return __b;
2437}
2438
2439template <class _CharT, class _InputIterator>
2440_InputIterator
2441time_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
2442 ios_base& __iob,
2443 ios_base::iostate& __err, tm* __tm,
2444 char __fmt, char) const
2445{
2446 __err = ios_base::goodbit;
2447 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2448 switch (__fmt)
2449 {
2450 case 'a':
2451 case 'A':
2452 __get_weekdayname(__tm->tm_wday, __b, __e, __err, __ct);
2453 break;
2454 case 'b':
2455 case 'B':
2456 case 'h':
2457 __get_monthname(__tm->tm_mon, __b, __e, __err, __ct);
2458 break;
2459 case 'c':
2460 {
2461 const string_type& __fmt = this->__c();
2462 __b = get(__b, __e, __iob, __err, __tm, __fmt.data(), __fmt.data() + __fmt.size());
2463 }
2464 break;
2465 case 'd':
2466 case 'e':
2467 __get_day(__tm->tm_mday, __b, __e, __err, __ct);
2468 break;
2469 case 'D':
2470 {
2471 const char_type __fmt[] = {'%', 'm', '/', '%', 'd', '/', '%', 'y'};
2472 __b = get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2473 }
2474 break;
Howard Hinnant506b3642011-04-10 17:54:14 +00002475 case 'F':
2476 {
2477 const char_type __fmt[] = {'%', 'Y', '-', '%', 'm', '-', '%', 'd'};
2478 __b = get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2479 }
2480 break;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002481 case 'H':
2482 __get_hour(__tm->tm_hour, __b, __e, __err, __ct);
2483 break;
2484 case 'I':
2485 __get_12_hour(__tm->tm_hour, __b, __e, __err, __ct);
2486 break;
2487 case 'j':
2488 __get_day_year_num(__tm->tm_yday, __b, __e, __err, __ct);
2489 break;
2490 case 'm':
2491 __get_month(__tm->tm_mon, __b, __e, __err, __ct);
2492 break;
2493 case 'M':
2494 __get_minute(__tm->tm_min, __b, __e, __err, __ct);
2495 break;
2496 case 'n':
2497 case 't':
2498 __get_white_space(__b, __e, __err, __ct);
2499 break;
2500 case 'p':
2501 __get_am_pm(__tm->tm_hour, __b, __e, __err, __ct);
2502 break;
2503 case 'r':
2504 {
2505 const char_type __fmt[] = {'%', 'I', ':', '%', 'M', ':', '%', 'S', ' ', '%', 'p'};
2506 __b = get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2507 }
2508 break;
2509 case 'R':
2510 {
2511 const char_type __fmt[] = {'%', 'H', ':', '%', 'M'};
2512 __b = get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2513 }
2514 break;
2515 case 'S':
2516 __get_second(__tm->tm_sec, __b, __e, __err, __ct);
2517 break;
2518 case 'T':
2519 {
2520 const char_type __fmt[] = {'%', 'H', ':', '%', 'M', ':', '%', 'S'};
2521 __b = get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2522 }
2523 break;
2524 case 'w':
2525 __get_weekday(__tm->tm_wday, __b, __e, __err, __ct);
2526 break;
2527 case 'x':
2528 return do_get_date(__b, __e, __iob, __err, __tm);
2529 case 'X':
2530 {
2531 const string_type& __fmt = this->__X();
2532 __b = get(__b, __e, __iob, __err, __tm, __fmt.data(), __fmt.data() + __fmt.size());
2533 }
2534 break;
2535 case 'y':
2536 __get_year(__tm->tm_year, __b, __e, __err, __ct);
2537 break;
2538 case 'Y':
2539 __get_year4(__tm->tm_year, __b, __e, __err, __ct);
2540 break;
2541 case '%':
2542 __get_percent(__b, __e, __err, __ct);
2543 break;
2544 default:
2545 __err |= ios_base::failbit;
2546 }
2547 return __b;
2548}
2549
2550extern template class time_get<char>;
2551extern template class time_get<wchar_t>;
2552
2553class __time_get
2554{
2555protected:
2556 locale_t __loc_;
2557
2558 __time_get(const char* __nm);
2559 __time_get(const string& __nm);
2560 ~__time_get();
2561};
2562
2563template <class _CharT>
2564class __time_get_storage
2565 : public __time_get
2566{
2567protected:
2568 typedef basic_string<_CharT> string_type;
2569
2570 string_type __weeks_[14];
2571 string_type __months_[24];
2572 string_type __am_pm_[2];
2573 string_type __c_;
2574 string_type __r_;
2575 string_type __x_;
2576 string_type __X_;
2577
2578 explicit __time_get_storage(const char* __nm);
2579 explicit __time_get_storage(const string& __nm);
2580
2581 _LIBCPP_ALWAYS_INLINE ~__time_get_storage() {}
2582
2583 time_base::dateorder __do_date_order() const;
2584
2585private:
2586 void init(const ctype<_CharT>&);
2587 string_type __analyze(char __fmt, const ctype<_CharT>&);
2588};
2589
2590template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00002591class _LIBCPP_VISIBLE time_get_byname
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002592 : public time_get<_CharT, _InputIterator>,
2593 private __time_get_storage<_CharT>
2594{
2595public:
2596 typedef time_base::dateorder dateorder;
2597 typedef _InputIterator iter_type;
2598 typedef _CharT char_type;
2599 typedef basic_string<char_type> string_type;
2600
Howard Hinnant82894812010-09-22 16:48:34 +00002601 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002602 explicit time_get_byname(const char* __nm, size_t __refs = 0)
2603 : time_get<_CharT, _InputIterator>(__refs),
2604 __time_get_storage<_CharT>(__nm) {}
Howard Hinnant82894812010-09-22 16:48:34 +00002605 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002606 explicit time_get_byname(const string& __nm, size_t __refs = 0)
2607 : time_get<_CharT, _InputIterator>(__refs),
2608 __time_get_storage<_CharT>(__nm) {}
2609
2610protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002611 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002612 ~time_get_byname() {}
2613
Howard Hinnant82894812010-09-22 16:48:34 +00002614 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002615 virtual dateorder do_date_order() const {return this->__do_date_order();}
2616private:
Howard Hinnant82894812010-09-22 16:48:34 +00002617 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002618 virtual const string_type* __weeks() const {return this->__weeks_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002619 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002620 virtual const string_type* __months() const {return this->__months_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002621 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002622 virtual const string_type* __am_pm() const {return this->__am_pm_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002623 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002624 virtual const string_type& __c() const {return this->__c_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002625 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002626 virtual const string_type& __r() const {return this->__r_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002627 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002628 virtual const string_type& __x() const {return this->__x_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002629 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002630 virtual const string_type& __X() const {return this->__X_;}
2631};
2632
2633extern template class time_get_byname<char>;
2634extern template class time_get_byname<wchar_t>;
2635
2636class __time_put
2637{
2638 locale_t __loc_;
2639protected:
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00002640 _LIBCPP_ALWAYS_INLINE __time_put() : __loc_(_LIBCPP_GET_C_LOCALE) {}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002641 __time_put(const char* __nm);
2642 __time_put(const string& __nm);
2643 ~__time_put();
2644 void __do_put(char* __nb, char*& __ne, const tm* __tm,
2645 char __fmt, char __mod) const;
2646 void __do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
2647 char __fmt, char __mod) const;
2648};
2649
2650template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00002651class _LIBCPP_VISIBLE time_put
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002652 : public locale::facet,
2653 private __time_put
2654{
2655public:
2656 typedef _CharT char_type;
2657 typedef _OutputIterator iter_type;
2658
2659 _LIBCPP_ALWAYS_INLINE
2660 explicit time_put(size_t __refs = 0)
2661 : locale::facet(__refs) {}
2662
2663 iter_type put(iter_type __s, ios_base& __iob, char_type __fl, const tm* __tm,
2664 const char_type* __pb, const char_type* __pe) const;
2665
2666 _LIBCPP_ALWAYS_INLINE
2667 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
2668 const tm* __tm, char __fmt, char __mod = 0) const
2669 {
2670 return do_put(__s, __iob, __fl, __tm, __fmt, __mod);
2671 }
2672
2673 static locale::id id;
2674
2675protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002676 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002677 ~time_put() {}
2678 virtual iter_type do_put(iter_type __s, ios_base&, char_type, const tm* __tm,
2679 char __fmt, char __mod) const;
2680
Howard Hinnant82894812010-09-22 16:48:34 +00002681 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002682 explicit time_put(const char* __nm, size_t __refs)
2683 : locale::facet(__refs),
2684 __time_put(__nm) {}
Howard Hinnant82894812010-09-22 16:48:34 +00002685 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002686 explicit time_put(const string& __nm, size_t __refs)
2687 : locale::facet(__refs),
2688 __time_put(__nm) {}
2689};
2690
2691template <class _CharT, class _OutputIterator>
2692locale::id
2693time_put<_CharT, _OutputIterator>::id;
2694
2695template <class _CharT, class _OutputIterator>
2696_OutputIterator
2697time_put<_CharT, _OutputIterator>::put(iter_type __s, ios_base& __iob,
2698 char_type __fl, const tm* __tm,
2699 const char_type* __pb,
2700 const char_type* __pe) const
2701{
2702 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2703 for (; __pb != __pe; ++__pb)
2704 {
2705 if (__ct.narrow(*__pb, 0) == '%')
2706 {
2707 if (++__pb == __pe)
2708 {
2709 *__s++ = __pb[-1];
2710 break;
2711 }
2712 char __mod = 0;
2713 char __fmt = __ct.narrow(*__pb, 0);
2714 if (__fmt == 'E' || __fmt == 'O')
2715 {
2716 if (++__pb == __pe)
2717 {
2718 *__s++ = __pb[-2];
2719 *__s++ = __pb[-1];
2720 break;
2721 }
2722 __mod = __fmt;
2723 __fmt = __ct.narrow(*__pb, 0);
2724 }
2725 __s = do_put(__s, __iob, __fl, __tm, __fmt, __mod);
2726 }
2727 else
2728 *__s++ = *__pb;
2729 }
2730 return __s;
2731}
2732
2733template <class _CharT, class _OutputIterator>
2734_OutputIterator
2735time_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
2736 char_type, const tm* __tm,
2737 char __fmt, char __mod) const
2738{
2739 char_type __nar[100];
2740 char_type* __nb = __nar;
2741 char_type* __ne = __nb + 100;
2742 __do_put(__nb, __ne, __tm, __fmt, __mod);
Howard Hinnant0949eed2011-06-30 21:18:19 +00002743 return _VSTD::copy(__nb, __ne, __s);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002744}
2745
2746extern template class time_put<char>;
2747extern template class time_put<wchar_t>;
2748
2749template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00002750class _LIBCPP_VISIBLE time_put_byname
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002751 : public time_put<_CharT, _OutputIterator>
2752{
2753public:
2754 _LIBCPP_ALWAYS_INLINE
2755 explicit time_put_byname(const char* __nm, size_t __refs = 0)
2756 : time_put<_CharT, _OutputIterator>(__nm, __refs) {}
2757
2758 _LIBCPP_ALWAYS_INLINE
2759 explicit time_put_byname(const string& __nm, size_t __refs = 0)
2760 : time_put<_CharT, _OutputIterator>(__nm, __refs) {}
2761
2762protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002763 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002764 ~time_put_byname() {}
2765};
2766
2767extern template class time_put_byname<char>;
2768extern template class time_put_byname<wchar_t>;
2769
2770// money_base
2771
Howard Hinnant82894812010-09-22 16:48:34 +00002772class _LIBCPP_VISIBLE money_base
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002773{
2774public:
2775 enum part {none, space, symbol, sign, value};
2776 struct pattern {char field[4];};
2777
2778 _LIBCPP_ALWAYS_INLINE money_base() {}
2779};
2780
2781// moneypunct
2782
2783template <class _CharT, bool _International = false>
Howard Hinnant82894812010-09-22 16:48:34 +00002784class _LIBCPP_VISIBLE moneypunct
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002785 : public locale::facet,
2786 public money_base
2787{
2788public:
2789 typedef _CharT char_type;
2790 typedef basic_string<char_type> string_type;
2791
Howard Hinnant82894812010-09-22 16:48:34 +00002792 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002793 explicit moneypunct(size_t __refs = 0)
2794 : locale::facet(__refs) {}
2795
2796 _LIBCPP_ALWAYS_INLINE char_type decimal_point() const {return do_decimal_point();}
2797 _LIBCPP_ALWAYS_INLINE char_type thousands_sep() const {return do_thousands_sep();}
2798 _LIBCPP_ALWAYS_INLINE string grouping() const {return do_grouping();}
2799 _LIBCPP_ALWAYS_INLINE string_type curr_symbol() const {return do_curr_symbol();}
2800 _LIBCPP_ALWAYS_INLINE string_type positive_sign() const {return do_positive_sign();}
2801 _LIBCPP_ALWAYS_INLINE string_type negative_sign() const {return do_negative_sign();}
2802 _LIBCPP_ALWAYS_INLINE int frac_digits() const {return do_frac_digits();}
2803 _LIBCPP_ALWAYS_INLINE pattern pos_format() const {return do_pos_format();}
2804 _LIBCPP_ALWAYS_INLINE pattern neg_format() const {return do_neg_format();}
2805
2806 static locale::id id;
2807 static const bool intl = _International;
2808
2809protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002810 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002811 ~moneypunct() {}
2812
2813 virtual char_type do_decimal_point() const {return numeric_limits<char_type>::max();}
2814 virtual char_type do_thousands_sep() const {return numeric_limits<char_type>::max();}
2815 virtual string do_grouping() const {return string();}
2816 virtual string_type do_curr_symbol() const {return string_type();}
2817 virtual string_type do_positive_sign() const {return string_type();}
2818 virtual string_type do_negative_sign() const {return string_type(1, '-');}
2819 virtual int do_frac_digits() const {return 0;}
2820 virtual pattern do_pos_format() const
2821 {pattern __p = {symbol, sign, none, value}; return __p;}
2822 virtual pattern do_neg_format() const
2823 {pattern __p = {symbol, sign, none, value}; return __p;}
2824};
2825
2826template <class _CharT, bool _International>
2827locale::id
2828moneypunct<_CharT, _International>::id;
2829
2830extern template class moneypunct<char, false>;
2831extern template class moneypunct<char, true>;
2832extern template class moneypunct<wchar_t, false>;
2833extern template class moneypunct<wchar_t, true>;
2834
2835// moneypunct_byname
2836
2837template <class _CharT, bool _International = false>
Howard Hinnant82894812010-09-22 16:48:34 +00002838class _LIBCPP_VISIBLE moneypunct_byname
2839 : public moneypunct<_CharT, _International>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002840{
2841public:
2842 typedef money_base::pattern pattern;
2843 typedef _CharT char_type;
2844 typedef basic_string<char_type> string_type;
2845
2846 _LIBCPP_ALWAYS_INLINE
2847 explicit moneypunct_byname(const char* __nm, size_t __refs = 0)
2848 : moneypunct<_CharT, _International>(__refs) {init(__nm);}
2849
2850 _LIBCPP_ALWAYS_INLINE
2851 explicit moneypunct_byname(const string& __nm, size_t __refs = 0)
2852 : moneypunct<_CharT, _International>(__refs) {init(__nm.c_str());}
2853
2854protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002855 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002856 ~moneypunct_byname() {}
2857
2858 virtual char_type do_decimal_point() const {return __decimal_point_;}
2859 virtual char_type do_thousands_sep() const {return __thousands_sep_;}
2860 virtual string do_grouping() const {return __grouping_;}
2861 virtual string_type do_curr_symbol() const {return __curr_symbol_;}
2862 virtual string_type do_positive_sign() const {return __positive_sign_;}
2863 virtual string_type do_negative_sign() const {return __negative_sign_;}
2864 virtual int do_frac_digits() const {return __frac_digits_;}
2865 virtual pattern do_pos_format() const {return __pos_format_;}
2866 virtual pattern do_neg_format() const {return __neg_format_;}
2867
2868private:
2869 char_type __decimal_point_;
2870 char_type __thousands_sep_;
2871 string __grouping_;
2872 string_type __curr_symbol_;
2873 string_type __positive_sign_;
2874 string_type __negative_sign_;
2875 int __frac_digits_;
2876 pattern __pos_format_;
2877 pattern __neg_format_;
2878
2879 void init(const char*);
2880};
2881
2882template<> void moneypunct_byname<char, false>::init(const char*);
2883template<> void moneypunct_byname<char, true>::init(const char*);
2884template<> void moneypunct_byname<wchar_t, false>::init(const char*);
2885template<> void moneypunct_byname<wchar_t, true>::init(const char*);
2886
2887extern template class moneypunct_byname<char, false>;
2888extern template class moneypunct_byname<char, true>;
2889extern template class moneypunct_byname<wchar_t, false>;
2890extern template class moneypunct_byname<wchar_t, true>;
2891
2892// money_get
2893
2894template <class _CharT>
2895class __money_get
2896{
2897protected:
2898 typedef _CharT char_type;
2899 typedef basic_string<char_type> string_type;
2900
2901 _LIBCPP_ALWAYS_INLINE __money_get() {}
2902
2903 static void __gather_info(bool __intl, const locale& __loc,
2904 money_base::pattern& __pat, char_type& __dp,
2905 char_type& __ts, string& __grp,
2906 string_type& __sym, string_type& __psn,
2907 string_type& __nsn, int& __fd);
2908};
2909
2910template <class _CharT>
2911void
2912__money_get<_CharT>::__gather_info(bool __intl, const locale& __loc,
2913 money_base::pattern& __pat, char_type& __dp,
2914 char_type& __ts, string& __grp,
2915 string_type& __sym, string_type& __psn,
2916 string_type& __nsn, int& __fd)
2917{
2918 if (__intl)
2919 {
2920 const moneypunct<char_type, true>& __mp =
2921 use_facet<moneypunct<char_type, true> >(__loc);
2922 __pat = __mp.neg_format();
2923 __nsn = __mp.negative_sign();
2924 __psn = __mp.positive_sign();
2925 __dp = __mp.decimal_point();
2926 __ts = __mp.thousands_sep();
2927 __grp = __mp.grouping();
2928 __sym = __mp.curr_symbol();
2929 __fd = __mp.frac_digits();
2930 }
2931 else
2932 {
2933 const moneypunct<char_type, false>& __mp =
2934 use_facet<moneypunct<char_type, false> >(__loc);
2935 __pat = __mp.neg_format();
2936 __nsn = __mp.negative_sign();
2937 __psn = __mp.positive_sign();
2938 __dp = __mp.decimal_point();
2939 __ts = __mp.thousands_sep();
2940 __grp = __mp.grouping();
2941 __sym = __mp.curr_symbol();
2942 __fd = __mp.frac_digits();
2943 }
2944}
2945
2946extern template class __money_get<char>;
2947extern template class __money_get<wchar_t>;
2948
2949template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00002950class _LIBCPP_VISIBLE money_get
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002951 : public locale::facet,
2952 private __money_get<_CharT>
2953{
2954public:
2955 typedef _CharT char_type;
2956 typedef _InputIterator iter_type;
2957 typedef basic_string<char_type> string_type;
2958
2959 _LIBCPP_ALWAYS_INLINE
2960 explicit money_get(size_t __refs = 0)
2961 : locale::facet(__refs) {}
2962
2963 _LIBCPP_ALWAYS_INLINE
2964 iter_type get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob,
2965 ios_base::iostate& __err, long double& __v) const
2966 {
2967 return do_get(__b, __e, __intl, __iob, __err, __v);
2968 }
2969
2970 _LIBCPP_ALWAYS_INLINE
2971 iter_type get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob,
2972 ios_base::iostate& __err, string_type& __v) const
2973 {
2974 return do_get(__b, __e, __intl, __iob, __err, __v);
2975 }
2976
2977 static locale::id id;
2978
2979protected:
2980
Howard Hinnant82894812010-09-22 16:48:34 +00002981 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002982 ~money_get() {}
Howard Hinnant324bb032010-08-22 00:02:43 +00002983
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002984 virtual iter_type do_get(iter_type __b, iter_type __e, bool __intl,
2985 ios_base& __iob, ios_base::iostate& __err,
2986 long double& __v) const;
2987 virtual iter_type do_get(iter_type __b, iter_type __e, bool __intl,
2988 ios_base& __iob, ios_base::iostate& __err,
2989 string_type& __v) const;
2990
2991private:
2992 static bool __do_get(iter_type& __b, iter_type __e,
2993 bool __intl, const locale& __loc,
2994 ios_base::fmtflags __flags, ios_base::iostate& __err,
2995 bool& __neg, const ctype<char_type>& __ct,
2996 unique_ptr<char_type, void(*)(void*)>& __wb,
2997 char_type*& __wn, char_type* __we);
2998};
2999
3000template <class _CharT, class _InputIterator>
3001locale::id
3002money_get<_CharT, _InputIterator>::id;
3003
3004void __do_nothing(void*);
3005
3006template <class _Tp>
3007_LIBCPP_HIDDEN
3008void
3009__double_or_nothing(unique_ptr<_Tp, void(*)(void*)>& __b, _Tp*& __n, _Tp*& __e)
3010{
3011 bool __owns = __b.get_deleter() != __do_nothing;
3012 size_t __cur_cap = (__e-__b.get()) * sizeof(_Tp);
3013 size_t __new_cap = __cur_cap < numeric_limits<size_t>::max() / 2 ?
3014 2 * __cur_cap : numeric_limits<size_t>::max();
3015 size_t __n_off = __n - __b.get();
3016 _Tp* __t = (_Tp*)realloc(__owns ? __b.get() : 0, __new_cap);
3017 if (__t == 0)
3018 __throw_bad_alloc();
3019 if (__owns)
3020 __b.release();
3021 __b = unique_ptr<_Tp, void(*)(void*)>(__t, free);
3022 __new_cap /= sizeof(_Tp);
3023 __n = __b.get() + __n_off;
3024 __e = __b.get() + __new_cap;
3025}
3026
3027// true == success
3028template <class _CharT, class _InputIterator>
3029bool
3030money_get<_CharT, _InputIterator>::__do_get(iter_type& __b, iter_type __e,
3031 bool __intl, const locale& __loc,
3032 ios_base::fmtflags __flags,
3033 ios_base::iostate& __err,
3034 bool& __neg,
3035 const ctype<char_type>& __ct,
3036 unique_ptr<char_type, void(*)(void*)>& __wb,
3037 char_type*& __wn, char_type* __we)
3038{
3039 const unsigned __bz = 100;
3040 unsigned __gbuf[__bz];
3041 unique_ptr<unsigned, void(*)(void*)> __gb(__gbuf, __do_nothing);
3042 unsigned* __gn = __gb.get();
3043 unsigned* __ge = __gn + __bz;
3044 money_base::pattern __pat;
3045 char_type __dp;
3046 char_type __ts;
3047 string __grp;
3048 string_type __sym;
3049 string_type __psn;
3050 string_type __nsn;
3051 int __fd;
3052 __money_get<_CharT>::__gather_info(__intl, __loc, __pat, __dp, __ts, __grp,
3053 __sym, __psn, __nsn, __fd);
3054 const string_type* __trailing_sign = 0;
3055 __wn = __wb.get();
3056 for (unsigned __p = 0; __p < 4 && __b != __e; ++__p)
3057 {
3058 switch (__pat.field[__p])
3059 {
3060 case money_base::space:
3061 if (__p != 3)
3062 {
3063 if (__ct.is(ctype_base::space, *__b))
3064 ++__b;
3065 else
3066 {
3067 __err |= ios_base::failbit;
3068 return false;
3069 }
3070 }
Howard Hinnant324bb032010-08-22 00:02:43 +00003071 // drop through
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003072 case money_base::none:
3073 if (__p != 3)
3074 {
3075 while (__b != __e && __ct.is(ctype_base::space, *__b))
3076 ++__b;
3077 }
3078 break;
3079 case money_base::sign:
3080 if (__psn.size() + __nsn.size() > 0)
3081 {
3082 if (__psn.size() == 0 || __nsn.size() == 0)
3083 { // sign is optional
3084 if (__psn.size() > 0)
3085 { // __nsn.size() == 0
3086 if (*__b == __psn[0])
3087 {
3088 ++__b;
3089 if (__psn.size() > 1)
3090 __trailing_sign = &__psn;
3091 }
3092 else
3093 __neg = true;
3094 }
3095 else if (*__b == __nsn[0]) // __nsn.size() > 0 && __psn.size() == 0
3096 {
3097 ++__b;
3098 __neg = true;
3099 if (__nsn.size() > 1)
3100 __trailing_sign = &__nsn;
3101 }
3102 }
3103 else // sign is required
3104 {
3105 if (*__b == __psn[0])
3106 {
3107 ++__b;
3108 if (__psn.size() > 1)
3109 __trailing_sign = &__psn;
3110 }
3111 else if (*__b == __nsn[0])
3112 {
3113 ++__b;
3114 __neg = true;
3115 if (__nsn.size() > 1)
3116 __trailing_sign = &__nsn;
3117 }
3118 else
3119 {
3120 __err |= ios_base::failbit;
3121 return false;
3122 }
3123 }
3124 }
3125 break;
3126 case money_base::symbol:
3127 {
3128 bool __more_needed = __trailing_sign ||
3129 (__p < 2) ||
3130 (__p == 2 && __pat.field[3] != static_cast<char>(money_base::none));
3131 bool __sb = __flags & ios_base::showbase;
3132 if (__sb || __more_needed)
3133 {
3134 ios_base::iostate __et = ios_base::goodbit;
3135 string_type* __k = __scan_keyword(__b, __e, &__sym, &__sym+1,
3136 __ct, __et);
3137 if (__sb && __k != &__sym)
3138 {
3139 __err |= ios_base::failbit;
3140 return false;
3141 }
3142 }
3143 }
3144 break;
3145 case money_base::value:
3146 {
3147 unsigned __ng = 0;
3148 for (; __b != __e; ++__b)
3149 {
3150 char_type __c = *__b;
3151 if (__ct.is(ctype_base::digit, __c))
3152 {
3153 if (__wn == __we)
3154 __double_or_nothing(__wb, __wn, __we);
3155 *__wn++ = __c;
3156 ++__ng;
3157 }
3158 else if (__grp.size() > 0 && __ng > 0 && __c == __ts)
3159 {
3160 if (__gn == __ge)
3161 __double_or_nothing(__gb, __gn, __ge);
3162 *__gn++ = __ng;
3163 __ng = 0;
3164 }
3165 else
3166 break;
3167 }
3168 if (__gb.get() != __gn && __ng > 0)
3169 {
3170 if (__gn == __ge)
3171 __double_or_nothing(__gb, __gn, __ge);
3172 *__gn++ = __ng;
3173 }
3174 if (__fd > 0)
3175 {
3176 if (__b == __e || *__b != __dp)
3177 {
3178 __err |= ios_base::failbit;
3179 return false;
3180 }
3181 for (++__b; __fd > 0; --__fd, ++__b)
3182 {
3183 if (__b == __e || !__ct.is(ctype_base::digit, *__b))
3184 {
3185 __err |= ios_base::failbit;
3186 return false;
3187 }
3188 if (__wn == __we)
3189 __double_or_nothing(__wb, __wn, __we);
3190 *__wn++ = *__b;
3191 }
3192 }
3193 if (__wn == __wb.get())
3194 {
3195 __err |= ios_base::failbit;
3196 return false;
3197 }
3198 }
3199 break;
3200 }
3201 }
3202 if (__trailing_sign)
3203 {
3204 for (unsigned __i = 1; __i < __trailing_sign->size(); ++__i, ++__b)
3205 {
3206 if (__b == __e || *__b != (*__trailing_sign)[__i])
3207 {
3208 __err |= ios_base::failbit;
3209 return false;
3210 }
3211 }
3212 }
3213 if (__gb.get() != __gn)
3214 {
3215 ios_base::iostate __et = ios_base::goodbit;
3216 __check_grouping(__grp, __gb.get(), __gn, __et);
3217 if (__et)
3218 {
3219 __err |= ios_base::failbit;
3220 return false;
3221 }
3222 }
3223 return true;
3224}
3225
3226template <class _CharT, class _InputIterator>
3227_InputIterator
3228money_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
3229 bool __intl, ios_base& __iob,
3230 ios_base::iostate& __err,
3231 long double& __v) const
3232{
3233 const unsigned __bz = 100;
3234 char_type __wbuf[__bz];
3235 unique_ptr<char_type, void(*)(void*)> __wb(__wbuf, __do_nothing);
3236 char_type* __wn;
3237 char_type* __we = __wbuf + __bz;
3238 locale __loc = __iob.getloc();
3239 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3240 bool __neg = false;
3241 if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct,
3242 __wb, __wn, __we))
3243 {
3244 const char __src[] = "0123456789";
3245 char_type __atoms[sizeof(__src)-1];
3246 __ct.widen(__src, __src + (sizeof(__src)-1), __atoms);
3247 char __nbuf[__bz];
3248 char* __nc = __nbuf;
3249 unique_ptr<char, void(*)(void*)> __h(0, free);
3250 if (__wn - __wb.get() > __bz-2)
3251 {
3252 __h.reset((char*)malloc(__wn - __wb.get() + 2));
3253 if (__h.get() == 0)
3254 __throw_bad_alloc();
3255 __nc = __h.get();
3256 }
3257 if (__neg)
3258 *__nc++ = '-';
3259 for (const char_type* __w = __wb.get(); __w < __wn; ++__w, ++__nc)
3260 *__nc = __src[find(__atoms, __atoms+sizeof(__atoms), *__w) - __atoms];
3261 *__nc = char();
3262 if (sscanf(__nbuf, "%Lf", &__v) != 1)
3263 __throw_runtime_error("money_get error");
3264 }
3265 if (__b == __e)
3266 __err |= ios_base::eofbit;
3267 return __b;
3268}
3269
3270template <class _CharT, class _InputIterator>
3271_InputIterator
3272money_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
3273 bool __intl, ios_base& __iob,
3274 ios_base::iostate& __err,
3275 string_type& __v) const
3276{
3277 const unsigned __bz = 100;
3278 char_type __wbuf[__bz];
3279 unique_ptr<char_type, void(*)(void*)> __wb(__wbuf, __do_nothing);
3280 char_type* __wn;
3281 char_type* __we = __wbuf + __bz;
3282 locale __loc = __iob.getloc();
3283 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3284 bool __neg = false;
3285 if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct,
3286 __wb, __wn, __we))
3287 {
3288 __v.clear();
3289 if (__neg)
3290 __v.push_back(__ct.widen('-'));
3291 char_type __z = __ct.widen('0');
3292 char_type* __w;
3293 for (__w = __wb.get(); __w < __wn-1; ++__w)
3294 if (*__w != __z)
3295 break;
3296 __v.append(__w, __wn);
3297 }
3298 if (__b == __e)
3299 __err |= ios_base::eofbit;
3300 return __b;
3301}
3302
3303extern template class money_get<char>;
3304extern template class money_get<wchar_t>;
3305
3306// money_put
3307
3308template <class _CharT>
3309class __money_put
3310{
3311protected:
3312 typedef _CharT char_type;
3313 typedef basic_string<char_type> string_type;
3314
3315 _LIBCPP_ALWAYS_INLINE __money_put() {}
3316
3317 static void __gather_info(bool __intl, bool __neg, const locale& __loc,
3318 money_base::pattern& __pat, char_type& __dp,
3319 char_type& __ts, string& __grp,
3320 string_type& __sym, string_type& __sn,
3321 int& __fd);
3322 static void __format(char_type* __mb, char_type*& __mi, char_type*& __me,
3323 ios_base::fmtflags __flags,
3324 const char_type* __db, const char_type* __de,
3325 const ctype<char_type>& __ct, bool __neg,
3326 const money_base::pattern& __pat, char_type __dp,
3327 char_type __ts, const string& __grp,
3328 const string_type& __sym, const string_type& __sn,
3329 int __fd);
3330};
3331
3332template <class _CharT>
3333void
3334__money_put<_CharT>::__gather_info(bool __intl, bool __neg, const locale& __loc,
3335 money_base::pattern& __pat, char_type& __dp,
3336 char_type& __ts, string& __grp,
3337 string_type& __sym, string_type& __sn,
3338 int& __fd)
3339{
3340 if (__intl)
3341 {
3342 const moneypunct<char_type, true>& __mp =
3343 use_facet<moneypunct<char_type, true> >(__loc);
3344 if (__neg)
3345 {
3346 __pat = __mp.neg_format();
3347 __sn = __mp.negative_sign();
3348 }
3349 else
3350 {
3351 __pat = __mp.pos_format();
3352 __sn = __mp.positive_sign();
3353 }
3354 __dp = __mp.decimal_point();
3355 __ts = __mp.thousands_sep();
3356 __grp = __mp.grouping();
3357 __sym = __mp.curr_symbol();
3358 __fd = __mp.frac_digits();
3359 }
3360 else
3361 {
3362 const moneypunct<char_type, false>& __mp =
3363 use_facet<moneypunct<char_type, false> >(__loc);
3364 if (__neg)
3365 {
3366 __pat = __mp.neg_format();
3367 __sn = __mp.negative_sign();
3368 }
3369 else
3370 {
3371 __pat = __mp.pos_format();
3372 __sn = __mp.positive_sign();
3373 }
3374 __dp = __mp.decimal_point();
3375 __ts = __mp.thousands_sep();
3376 __grp = __mp.grouping();
3377 __sym = __mp.curr_symbol();
3378 __fd = __mp.frac_digits();
3379 }
3380}
3381
3382template <class _CharT>
3383void
3384__money_put<_CharT>::__format(char_type* __mb, char_type*& __mi, char_type*& __me,
3385 ios_base::fmtflags __flags,
3386 const char_type* __db, const char_type* __de,
3387 const ctype<char_type>& __ct, bool __neg,
3388 const money_base::pattern& __pat, char_type __dp,
3389 char_type __ts, const string& __grp,
3390 const string_type& __sym, const string_type& __sn,
3391 int __fd)
3392{
3393 __me = __mb;
3394 for (unsigned __p = 0; __p < 4; ++__p)
3395 {
3396 switch (__pat.field[__p])
3397 {
3398 case money_base::none:
3399 __mi = __me;
3400 break;
3401 case money_base::space:
3402 __mi = __me;
3403 *__me++ = __ct.widen(' ');
3404 break;
3405 case money_base::sign:
3406 if (!__sn.empty())
3407 *__me++ = __sn[0];
3408 break;
3409 case money_base::symbol:
3410 if (!__sym.empty() && (__flags & ios_base::showbase))
Howard Hinnant0949eed2011-06-30 21:18:19 +00003411 __me = _VSTD::copy(__sym.begin(), __sym.end(), __me);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003412 break;
3413 case money_base::value:
3414 {
3415 // remember start of value so we can reverse it
3416 char_type* __t = __me;
3417 // find beginning of digits
3418 if (__neg)
3419 ++__db;
3420 // find end of digits
3421 const char_type* __d;
3422 for (__d = __db; __d < __de; ++__d)
3423 if (!__ct.is(ctype_base::digit, *__d))
3424 break;
3425 // print fractional part
3426 if (__fd > 0)
3427 {
3428 int __f;
3429 for (__f = __fd; __d > __db && __f > 0; --__f)
3430 *__me++ = *--__d;
3431 char_type __z = __f > 0 ? __ct.widen('0') : char_type();
3432 for (; __f > 0; --__f)
3433 *__me++ = __z;
3434 *__me++ = __dp;
3435 }
3436 // print units part
3437 if (__d == __db)
3438 {
3439 *__me++ = __ct.widen('0');
3440 }
3441 else
3442 {
3443 unsigned __ng = 0;
3444 unsigned __ig = 0;
3445 unsigned __gl = __grp.empty() ? numeric_limits<unsigned>::max()
3446 : static_cast<unsigned>(__grp[__ig]);
3447 while (__d != __db)
3448 {
3449 if (__ng == __gl)
3450 {
3451 *__me++ = __ts;
3452 __ng = 0;
3453 if (++__ig < __grp.size())
3454 __gl = __grp[__ig] == numeric_limits<char>::max() ?
3455 numeric_limits<unsigned>::max() :
3456 static_cast<unsigned>(__grp[__ig]);
3457 }
3458 *__me++ = *--__d;
3459 ++__ng;
3460 }
3461 }
3462 // reverse it
3463 reverse(__t, __me);
3464 }
3465 break;
3466 }
3467 }
3468 // print rest of sign, if any
3469 if (__sn.size() > 1)
Howard Hinnant0949eed2011-06-30 21:18:19 +00003470 __me = _VSTD::copy(__sn.begin()+1, __sn.end(), __me);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003471 // set alignment
3472 if ((__flags & ios_base::adjustfield) == ios_base::left)
3473 __mi = __me;
3474 else if ((__flags & ios_base::adjustfield) != ios_base::internal)
3475 __mi = __mb;
3476}
3477
3478extern template class __money_put<char>;
3479extern template class __money_put<wchar_t>;
3480
3481template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00003482class _LIBCPP_VISIBLE money_put
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003483 : public locale::facet,
3484 private __money_put<_CharT>
3485{
3486public:
3487 typedef _CharT char_type;
3488 typedef _OutputIterator iter_type;
3489 typedef basic_string<char_type> string_type;
3490
3491 _LIBCPP_ALWAYS_INLINE
3492 explicit money_put(size_t __refs = 0)
3493 : locale::facet(__refs) {}
3494
3495 _LIBCPP_ALWAYS_INLINE
3496 iter_type put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl,
3497 long double __units) const
3498 {
3499 return do_put(__s, __intl, __iob, __fl, __units);
3500 }
3501
3502 _LIBCPP_ALWAYS_INLINE
3503 iter_type put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl,
3504 const string_type& __digits) const
3505 {
3506 return do_put(__s, __intl, __iob, __fl, __digits);
3507 }
3508
3509 static locale::id id;
3510
3511protected:
Howard Hinnant82894812010-09-22 16:48:34 +00003512 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003513 ~money_put() {}
3514
3515 virtual iter_type do_put(iter_type __s, bool __intl, ios_base& __iob,
3516 char_type __fl, long double __units) const;
3517 virtual iter_type do_put(iter_type __s, bool __intl, ios_base& __iob,
3518 char_type __fl, const string_type& __digits) const;
3519};
3520
3521template <class _CharT, class _OutputIterator>
3522locale::id
3523money_put<_CharT, _OutputIterator>::id;
3524
3525template <class _CharT, class _OutputIterator>
3526_OutputIterator
3527money_put<_CharT, _OutputIterator>::do_put(iter_type __s, bool __intl,
3528 ios_base& __iob, char_type __fl,
3529 long double __units) const
3530{
3531 // convert to char
3532 const size_t __bs = 100;
3533 char __buf[__bs];
3534 char* __bb = __buf;
3535 char_type __digits[__bs];
3536 char_type* __db = __digits;
3537 size_t __n = snprintf(__bb, __bs, "%.0Lf", __units);
3538 unique_ptr<char, void(*)(void*)> __hn(0, free);
3539 unique_ptr<char_type, void(*)(void*)> __hd(0, free);
3540 // secure memory for digit storage
3541 if (__n > __bs-1)
3542 {
Howard Hinnant866569b2011-09-28 23:39:33 +00003543#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00003544 __n = asprintf_l(&__bb, _LIBCPP_GET_C_LOCALE, "%.0Lf", __units);
Sean Huntf3907e62011-07-15 05:40:33 +00003545#else
3546 __n = __asprintf_l(&__bb, __cloc(), "%.0Lf", __units);
3547#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003548 if (__bb == 0)
3549 __throw_bad_alloc();
3550 __hn.reset(__bb);
3551 __hd.reset((char_type*)malloc(__n * sizeof(char_type)));
3552 if (__hd == 0)
3553 __throw_bad_alloc();
3554 __db = __hd.get();
3555 }
3556 // gather info
3557 locale __loc = __iob.getloc();
3558 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3559 __ct.widen(__bb, __bb + __n, __db);
3560 bool __neg = __n > 0 && __bb[0] == '-';
3561 money_base::pattern __pat;
3562 char_type __dp;
3563 char_type __ts;
3564 string __grp;
3565 string_type __sym;
3566 string_type __sn;
3567 int __fd;
3568 this->__gather_info(__intl, __neg, __loc, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3569 // secure memory for formatting
3570 char_type __mbuf[__bs];
3571 char_type* __mb = __mbuf;
3572 unique_ptr<char_type, void(*)(void*)> __hw(0, free);
3573 size_t __exn = static_cast<int>(__n) > __fd ?
3574 (__n - __fd) * 2 + __sn.size() + __sym.size() + __fd + 1
3575 : __sn.size() + __sym.size() + __fd + 2;
3576 if (__exn > __bs)
3577 {
3578 __hw.reset((char_type*)malloc(__exn * sizeof(char_type)));
3579 __mb = __hw.get();
3580 if (__mb == 0)
3581 __throw_bad_alloc();
3582 }
3583 // format
3584 char_type* __mi;
3585 char_type* __me;
3586 this->__format(__mb, __mi, __me, __iob.flags(),
3587 __db, __db + __n, __ct,
3588 __neg, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3589 return __pad_and_output(__s, __mb, __mi, __me, __iob, __fl);
3590}
3591
3592template <class _CharT, class _OutputIterator>
3593_OutputIterator
3594money_put<_CharT, _OutputIterator>::do_put(iter_type __s, bool __intl,
3595 ios_base& __iob, char_type __fl,
3596 const string_type& __digits) const
3597{
3598 // gather info
3599 locale __loc = __iob.getloc();
3600 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3601 bool __neg = __digits.size() > 0 && __digits[0] == __ct.widen('-');
3602 money_base::pattern __pat;
3603 char_type __dp;
3604 char_type __ts;
3605 string __grp;
3606 string_type __sym;
3607 string_type __sn;
3608 int __fd;
3609 this->__gather_info(__intl, __neg, __loc, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3610 // secure memory for formatting
3611 char_type __mbuf[100];
3612 char_type* __mb = __mbuf;
3613 unique_ptr<char_type, void(*)(void*)> __h(0, free);
3614 size_t __exn = __digits.size() > __fd ?
3615 (__digits.size() - __fd) * 2 + __sn.size() + __sym.size() + __fd + 1
3616 : __sn.size() + __sym.size() + __fd + 2;
3617 if (__exn > 100)
3618 {
3619 __h.reset((char_type*)malloc(__exn * sizeof(char_type)));
3620 __mb = __h.get();
3621 if (__mb == 0)
3622 __throw_bad_alloc();
3623 }
3624 // format
3625 char_type* __mi;
3626 char_type* __me;
3627 this->__format(__mb, __mi, __me, __iob.flags(),
3628 __digits.data(), __digits.data() + __digits.size(), __ct,
3629 __neg, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3630 return __pad_and_output(__s, __mb, __mi, __me, __iob, __fl);
3631}
3632
3633extern template class money_put<char>;
3634extern template class money_put<wchar_t>;
3635
3636// messages
3637
Howard Hinnant82894812010-09-22 16:48:34 +00003638class _LIBCPP_VISIBLE messages_base
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003639{
3640public:
Howard Hinnantb2080c72011-02-25 00:51:08 +00003641 typedef ptrdiff_t catalog;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003642
3643 _LIBCPP_ALWAYS_INLINE messages_base() {}
3644};
3645
3646template <class _CharT>
Howard Hinnant82894812010-09-22 16:48:34 +00003647class _LIBCPP_VISIBLE messages
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003648 : public locale::facet,
3649 public messages_base
3650{
3651public:
3652 typedef _CharT char_type;
3653 typedef basic_string<_CharT> string_type;
3654
3655 _LIBCPP_ALWAYS_INLINE
3656 explicit messages(size_t __refs = 0)
3657 : locale::facet(__refs) {}
3658
3659 _LIBCPP_ALWAYS_INLINE
3660 catalog open(const basic_string<char>& __nm, const locale& __loc) const
3661 {
3662 return do_open(__nm, __loc);
3663 }
3664
3665 _LIBCPP_ALWAYS_INLINE
3666 string_type get(catalog __c, int __set, int __msgid,
3667 const string_type& __dflt) const
3668 {
3669 return do_get(__c, __set, __msgid, __dflt);
3670 }
3671
3672 _LIBCPP_ALWAYS_INLINE
3673 void close(catalog __c) const
3674 {
3675 do_close(__c);
3676 }
3677
3678 static locale::id id;
3679
3680protected:
Howard Hinnant82894812010-09-22 16:48:34 +00003681 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003682 ~messages() {}
3683
3684 virtual catalog do_open(const basic_string<char>&, const locale&) const;
3685 virtual string_type do_get(catalog, int __set, int __msgid,
3686 const string_type& __dflt) const;
3687 virtual void do_close(catalog) const;
3688};
3689
3690template <class _CharT>
3691locale::id
3692messages<_CharT>::id;
3693
3694template <class _CharT>
3695typename messages<_CharT>::catalog
3696messages<_CharT>::do_open(const basic_string<char>& __nm, const locale&) const
3697{
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00003698#if _WIN32
3699 return -1;
3700#else // _WIN32
Howard Hinnant11624452011-10-11 16:00:46 +00003701 catalog __cat = (catalog)catopen(__nm.c_str(), NL_CAT_LOCALE);
Howard Hinnantb2080c72011-02-25 00:51:08 +00003702 if (__cat != -1)
3703 __cat = static_cast<catalog>((static_cast<size_t>(__cat) >> 1));
3704 return __cat;
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00003705#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003706}
3707
3708template <class _CharT>
3709typename messages<_CharT>::string_type
3710messages<_CharT>::do_get(catalog __c, int __set, int __msgid,
3711 const string_type& __dflt) const
3712{
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00003713#if _WIN32
3714 return __dflt;
3715#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003716 string __ndflt;
3717 __narrow_to_utf8<sizeof(char_type)*__CHAR_BIT__>()(back_inserter(__ndflt),
3718 __dflt.c_str(),
3719 __dflt.c_str() + __dflt.size());
Howard Hinnantb2080c72011-02-25 00:51:08 +00003720 if (__c != -1)
3721 __c <<= 1;
Howard Hinnant11624452011-10-11 16:00:46 +00003722 nl_catd __cat = (nl_catd)__c;
Howard Hinnantb2080c72011-02-25 00:51:08 +00003723 char* __n = catgets(__cat, __set, __msgid, __ndflt.c_str());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003724 string_type __w;
3725 __widen_from_utf8<sizeof(char_type)*__CHAR_BIT__>()(back_inserter(__w),
3726 __n, __n + strlen(__n));
3727 return __w;
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00003728#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003729}
3730
3731template <class _CharT>
3732void
3733messages<_CharT>::do_close(catalog __c) const
3734{
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00003735#if !_WIN32
Howard Hinnantb2080c72011-02-25 00:51:08 +00003736 if (__c != -1)
3737 __c <<= 1;
Howard Hinnant11624452011-10-11 16:00:46 +00003738 nl_catd __cat = (nl_catd)__c;
Howard Hinnantb2080c72011-02-25 00:51:08 +00003739 catclose(__cat);
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00003740#endif // !_WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003741}
3742
3743extern template class messages<char>;
3744extern template class messages<wchar_t>;
3745
3746template <class _CharT>
Howard Hinnant82894812010-09-22 16:48:34 +00003747class _LIBCPP_VISIBLE messages_byname
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003748 : public messages<_CharT>
3749{
3750public:
3751 typedef messages_base::catalog catalog;
3752 typedef basic_string<_CharT> string_type;
3753
3754 _LIBCPP_ALWAYS_INLINE
3755 explicit messages_byname(const char*, size_t __refs = 0)
3756 : messages<_CharT>(__refs) {}
3757
3758 _LIBCPP_ALWAYS_INLINE
3759 explicit messages_byname(const string&, size_t __refs = 0)
3760 : messages<_CharT>(__refs) {}
3761
3762protected:
Howard Hinnant82894812010-09-22 16:48:34 +00003763 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003764 ~messages_byname() {}
3765};
3766
3767extern template class messages_byname<char>;
3768extern template class messages_byname<wchar_t>;
3769
Howard Hinnantd23b4642010-05-31 20:58:54 +00003770template<class _Codecvt, class _Elem = wchar_t,
3771 class _Wide_alloc = allocator<_Elem>,
3772 class _Byte_alloc = allocator<char> >
Howard Hinnant82894812010-09-22 16:48:34 +00003773class _LIBCPP_VISIBLE wstring_convert
Howard Hinnantd23b4642010-05-31 20:58:54 +00003774{
3775public:
3776 typedef basic_string<char, char_traits<char>, _Byte_alloc> byte_string;
3777 typedef basic_string<_Elem, char_traits<_Elem>, _Wide_alloc> wide_string;
3778 typedef typename _Codecvt::state_type state_type;
3779 typedef typename wide_string::traits_type::int_type int_type;
3780
3781private:
3782 byte_string __byte_err_string_;
3783 wide_string __wide_err_string_;
3784 _Codecvt* __cvtptr_;
3785 state_type __cvtstate_;
3786 size_t __cvtcount_;
3787
3788 wstring_convert(const wstring_convert& __wc);
3789 wstring_convert& operator=(const wstring_convert& __wc);
3790public:
3791 wstring_convert(_Codecvt* __pcvt = new _Codecvt);
3792 wstring_convert(_Codecvt* __pcvt, state_type __state);
3793 wstring_convert(const byte_string& __byte_err,
3794 const wide_string& __wide_err = wide_string());
Howard Hinnant73d21a42010-09-04 23:28:19 +00003795#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantd23b4642010-05-31 20:58:54 +00003796 wstring_convert(wstring_convert&& __wc);
3797#endif
3798 ~wstring_convert();
3799
Howard Hinnant82894812010-09-22 16:48:34 +00003800 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003801 wide_string from_bytes(char __byte)
3802 {return from_bytes(&__byte, &__byte+1);}
Howard Hinnant82894812010-09-22 16:48:34 +00003803 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003804 wide_string from_bytes(const char* __ptr)
3805 {return from_bytes(__ptr, __ptr + char_traits<char>::length(__ptr));}
Howard Hinnant82894812010-09-22 16:48:34 +00003806 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003807 wide_string from_bytes(const byte_string& __str)
3808 {return from_bytes(__str.data(), __str.data() + __str.size());}
3809 wide_string from_bytes(const char* __first, const char* __last);
3810
Howard Hinnant82894812010-09-22 16:48:34 +00003811 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003812 byte_string to_bytes(_Elem __wchar)
3813 {return to_bytes(&__wchar, &__wchar+1);}
Howard Hinnant82894812010-09-22 16:48:34 +00003814 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003815 byte_string to_bytes(const _Elem* __wptr)
3816 {return to_bytes(__wptr, __wptr + char_traits<_Elem>::length(__wptr));}
Howard Hinnant82894812010-09-22 16:48:34 +00003817 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003818 byte_string to_bytes(const wide_string& __wstr)
3819 {return to_bytes(__wstr.data(), __wstr.data() + __wstr.size());}
3820 byte_string to_bytes(const _Elem* __first, const _Elem* __last);
3821
Howard Hinnant82894812010-09-22 16:48:34 +00003822 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003823 size_t converted() const {return __cvtcount_;}
Howard Hinnant82894812010-09-22 16:48:34 +00003824 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003825 state_type state() const {return __cvtstate_;}
3826};
3827
3828template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Howard Hinnant82894812010-09-22 16:48:34 +00003829inline _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003830wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3831 wstring_convert(_Codecvt* __pcvt)
3832 : __cvtptr_(__pcvt), __cvtstate_(), __cvtcount_(0)
3833{
3834}
3835
3836template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Howard Hinnant82894812010-09-22 16:48:34 +00003837inline _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003838wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3839 wstring_convert(_Codecvt* __pcvt, state_type __state)
3840 : __cvtptr_(__pcvt), __cvtstate_(__state), __cvtcount_(0)
3841{
3842}
3843
3844template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3845wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3846 wstring_convert(const byte_string& __byte_err, const wide_string& __wide_err)
3847 : __byte_err_string_(__byte_err), __wide_err_string_(__wide_err),
3848 __cvtstate_(), __cvtcount_(0)
3849{
3850 __cvtptr_ = new _Codecvt;
3851}
3852
Howard Hinnant73d21a42010-09-04 23:28:19 +00003853#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantd23b4642010-05-31 20:58:54 +00003854
3855template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Howard Hinnant82894812010-09-22 16:48:34 +00003856inline _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003857wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3858 wstring_convert(wstring_convert&& __wc)
Howard Hinnant0949eed2011-06-30 21:18:19 +00003859 : __byte_err_string_(_VSTD::move(__wc.__byte_err_string_)),
3860 __wide_err_string_(_VSTD::move(__wc.__wide_err_string_)),
Howard Hinnantd23b4642010-05-31 20:58:54 +00003861 __cvtptr_(__wc.__cvtptr_),
3862 __cvtstate_(__wc.__cvtstate_), __cvtcount_(__wc.__cvtstate_)
3863{
3864 __wc.__cvtptr_ = nullptr;
3865}
3866
Howard Hinnantbfd55302010-09-04 23:46:48 +00003867#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantd23b4642010-05-31 20:58:54 +00003868
3869template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3870wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::~wstring_convert()
3871{
3872 delete __cvtptr_;
3873}
3874
3875template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3876typename wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::wide_string
3877wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3878 from_bytes(const char* __frm, const char* __frm_end)
3879{
3880 __cvtcount_ = 0;
3881 if (__cvtptr_ != nullptr)
3882 {
3883 wide_string __ws(2*(__frm_end - __frm), _Elem());
3884 __ws.resize(__ws.capacity());
3885 codecvt_base::result __r = codecvt_base::ok;
3886 state_type __st = __cvtstate_;
3887 if (__frm != __frm_end)
3888 {
3889 _Elem* __to = &__ws[0];
3890 _Elem* __to_end = __to + __ws.size();
3891 const char* __frm_nxt;
3892 do
3893 {
3894 _Elem* __to_nxt;
3895 __r = __cvtptr_->in(__st, __frm, __frm_end, __frm_nxt,
3896 __to, __to_end, __to_nxt);
3897 __cvtcount_ += __frm_nxt - __frm;
3898 if (__frm_nxt == __frm)
3899 {
3900 __r = codecvt_base::error;
3901 }
3902 else if (__r == codecvt_base::noconv)
3903 {
3904 __ws.resize(__to - &__ws[0]);
3905 // This only gets executed if _Elem is char
3906 __ws.append((const _Elem*)__frm, (const _Elem*)__frm_end);
3907 __frm = __frm_nxt;
3908 __r = codecvt_base::ok;
3909 }
3910 else if (__r == codecvt_base::ok)
3911 {
3912 __ws.resize(__to_nxt - &__ws[0]);
3913 __frm = __frm_nxt;
3914 }
3915 else if (__r == codecvt_base::partial)
3916 {
3917 ptrdiff_t __s = __to_nxt - &__ws[0];
3918 __ws.resize(2 * __s);
3919 __to = &__ws[0] + __s;
3920 __to_end = &__ws[0] + __ws.size();
3921 __frm = __frm_nxt;
3922 }
3923 } while (__r == codecvt_base::partial && __frm_nxt < __frm_end);
3924 }
3925 if (__r == codecvt_base::ok)
3926 return __ws;
3927 }
Howard Hinnantd4444702010-08-11 17:04:31 +00003928#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00003929 if (__wide_err_string_.empty())
3930 throw range_error("wstring_convert: from_bytes error");
Howard Hinnant324bb032010-08-22 00:02:43 +00003931#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00003932 return __wide_err_string_;
3933}
3934
3935template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3936typename wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::byte_string
3937wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3938 to_bytes(const _Elem* __frm, const _Elem* __frm_end)
3939{
3940 __cvtcount_ = 0;
3941 if (__cvtptr_ != nullptr)
3942 {
3943 byte_string __bs(2*(__frm_end - __frm), char());
3944 __bs.resize(__bs.capacity());
3945 codecvt_base::result __r = codecvt_base::ok;
3946 state_type __st = __cvtstate_;
3947 if (__frm != __frm_end)
3948 {
3949 char* __to = &__bs[0];
3950 char* __to_end = __to + __bs.size();
3951 const _Elem* __frm_nxt;
3952 do
3953 {
3954 char* __to_nxt;
3955 __r = __cvtptr_->out(__st, __frm, __frm_end, __frm_nxt,
3956 __to, __to_end, __to_nxt);
3957 __cvtcount_ += __frm_nxt - __frm;
3958 if (__frm_nxt == __frm)
3959 {
3960 __r = codecvt_base::error;
3961 }
3962 else if (__r == codecvt_base::noconv)
3963 {
3964 __bs.resize(__to - &__bs[0]);
3965 // This only gets executed if _Elem is char
3966 __bs.append((const char*)__frm, (const char*)__frm_end);
3967 __frm = __frm_nxt;
3968 __r = codecvt_base::ok;
3969 }
3970 else if (__r == codecvt_base::ok)
3971 {
3972 __bs.resize(__to_nxt - &__bs[0]);
3973 __frm = __frm_nxt;
3974 }
3975 else if (__r == codecvt_base::partial)
3976 {
3977 ptrdiff_t __s = __to_nxt - &__bs[0];
3978 __bs.resize(2 * __s);
3979 __to = &__bs[0] + __s;
3980 __to_end = &__bs[0] + __bs.size();
3981 __frm = __frm_nxt;
3982 }
3983 } while (__r == codecvt_base::partial && __frm_nxt < __frm_end);
3984 }
3985 if (__r == codecvt_base::ok)
3986 {
3987 size_t __s = __bs.size();
3988 __bs.resize(__bs.capacity());
3989 char* __to = &__bs[0] + __s;
3990 char* __to_end = __to + __bs.size();
3991 do
3992 {
3993 char* __to_nxt;
3994 __r = __cvtptr_->unshift(__st, __to, __to_end, __to_nxt);
3995 if (__r == codecvt_base::noconv)
3996 {
3997 __bs.resize(__to - &__bs[0]);
3998 __r = codecvt_base::ok;
3999 }
4000 else if (__r == codecvt_base::ok)
4001 {
4002 __bs.resize(__to_nxt - &__bs[0]);
4003 }
4004 else if (__r == codecvt_base::partial)
4005 {
4006 ptrdiff_t __s = __to_nxt - &__bs[0];
4007 __bs.resize(2 * __s);
4008 __to = &__bs[0] + __s;
4009 __to_end = &__bs[0] + __bs.size();
4010 }
4011 } while (__r == codecvt_base::partial);
4012 if (__r == codecvt_base::ok)
4013 return __bs;
4014 }
4015 }
Howard Hinnantd4444702010-08-11 17:04:31 +00004016#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00004017 if (__byte_err_string_.empty())
4018 throw range_error("wstring_convert: to_bytes error");
Howard Hinnant324bb032010-08-22 00:02:43 +00004019#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00004020 return __byte_err_string_;
4021}
4022
4023template <class _Codecvt, class _Elem = wchar_t, class _Tr = char_traits<_Elem> >
Howard Hinnant82894812010-09-22 16:48:34 +00004024class _LIBCPP_VISIBLE wbuffer_convert
Howard Hinnantd23b4642010-05-31 20:58:54 +00004025 : public basic_streambuf<_Elem, _Tr>
4026{
4027public:
4028 // types:
4029 typedef _Elem char_type;
4030 typedef _Tr traits_type;
4031 typedef typename traits_type::int_type int_type;
4032 typedef typename traits_type::pos_type pos_type;
4033 typedef typename traits_type::off_type off_type;
4034 typedef typename _Codecvt::state_type state_type;
4035
4036private:
Howard Hinnant4b53f502010-06-01 20:09:18 +00004037 char* __extbuf_;
4038 const char* __extbufnext_;
4039 const char* __extbufend_;
4040 char __extbuf_min_[8];
4041 size_t __ebs_;
4042 char_type* __intbuf_;
4043 size_t __ibs_;
Howard Hinnantd23b4642010-05-31 20:58:54 +00004044 streambuf* __bufptr_;
Howard Hinnant4b53f502010-06-01 20:09:18 +00004045 _Codecvt* __cv_;
4046 state_type __st_;
4047 ios_base::openmode __cm_;
4048 bool __owns_eb_;
4049 bool __owns_ib_;
4050 bool __always_noconv_;
Howard Hinnantd23b4642010-05-31 20:58:54 +00004051
Howard Hinnant4b53f502010-06-01 20:09:18 +00004052 wbuffer_convert(const wbuffer_convert&);
4053 wbuffer_convert& operator=(const wbuffer_convert&);
Howard Hinnantd23b4642010-05-31 20:58:54 +00004054public:
4055 wbuffer_convert(streambuf* __bytebuf = 0, _Codecvt* __pcvt = new _Codecvt,
Howard Hinnant4b53f502010-06-01 20:09:18 +00004056 state_type __state = state_type());
4057 ~wbuffer_convert();
Howard Hinnantd23b4642010-05-31 20:58:54 +00004058
Howard Hinnant82894812010-09-22 16:48:34 +00004059 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantd23b4642010-05-31 20:58:54 +00004060 streambuf* rdbuf() const {return __bufptr_;}
Howard Hinnant82894812010-09-22 16:48:34 +00004061 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantd23b4642010-05-31 20:58:54 +00004062 streambuf* rdbuf(streambuf* __bytebuf)
4063 {
4064 streambuf* __r = __bufptr_;
4065 __bufptr_ = __bytebuf;
4066 return __r;
4067 }
4068
Howard Hinnant82894812010-09-22 16:48:34 +00004069 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant4b53f502010-06-01 20:09:18 +00004070 state_type state() const {return __st_;}
Howard Hinnantd23b4642010-05-31 20:58:54 +00004071
4072protected:
Howard Hinnant4b53f502010-06-01 20:09:18 +00004073 virtual int_type underflow();
4074 virtual int_type pbackfail(int_type __c = traits_type::eof());
Howard Hinnantd23b4642010-05-31 20:58:54 +00004075 virtual int_type overflow (int_type __c = traits_type::eof());
Howard Hinnant4b53f502010-06-01 20:09:18 +00004076 virtual basic_streambuf<char_type, traits_type>* setbuf(char_type* __s,
4077 streamsize __n);
4078 virtual pos_type seekoff(off_type __off, ios_base::seekdir __way,
4079 ios_base::openmode __wch = ios_base::in | ios_base::out);
4080 virtual pos_type seekpos(pos_type __sp,
4081 ios_base::openmode __wch = ios_base::in | ios_base::out);
4082 virtual int sync();
4083
4084private:
4085 bool __read_mode();
4086 void __write_mode();
4087 wbuffer_convert* __close();
Howard Hinnantd23b4642010-05-31 20:58:54 +00004088};
4089
4090template <class _Codecvt, class _Elem, class _Tr>
Howard Hinnant4b53f502010-06-01 20:09:18 +00004091wbuffer_convert<_Codecvt, _Elem, _Tr>::
4092 wbuffer_convert(streambuf* __bytebuf, _Codecvt* __pcvt, state_type __state)
4093 : __extbuf_(0),
4094 __extbufnext_(0),
4095 __extbufend_(0),
4096 __ebs_(0),
4097 __intbuf_(0),
4098 __ibs_(0),
4099 __bufptr_(__bytebuf),
4100 __cv_(__pcvt),
4101 __st_(__state),
4102 __cm_(0),
4103 __owns_eb_(false),
4104 __owns_ib_(false),
4105 __always_noconv_(__cv_ ? __cv_->always_noconv() : false)
4106{
4107 setbuf(0, 4096);
4108}
4109
4110template <class _Codecvt, class _Elem, class _Tr>
4111wbuffer_convert<_Codecvt, _Elem, _Tr>::~wbuffer_convert()
4112{
4113 __close();
4114 delete __cv_;
4115 if (__owns_eb_)
4116 delete [] __extbuf_;
4117 if (__owns_ib_)
4118 delete [] __intbuf_;
4119}
4120
4121template <class _Codecvt, class _Elem, class _Tr>
4122typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
4123wbuffer_convert<_Codecvt, _Elem, _Tr>::underflow()
4124{
4125 if (__cv_ == 0 || __bufptr_ == 0)
4126 return traits_type::eof();
4127 bool __initial = __read_mode();
4128 char_type __1buf;
4129 if (this->gptr() == 0)
4130 this->setg(&__1buf, &__1buf+1, &__1buf+1);
4131 const size_t __unget_sz = __initial ? 0 : min<size_t>((this->egptr() - this->eback()) / 2, 4);
4132 int_type __c = traits_type::eof();
4133 if (this->gptr() == this->egptr())
4134 {
4135 memmove(this->eback(), this->egptr() - __unget_sz, __unget_sz * sizeof(char_type));
4136 if (__always_noconv_)
4137 {
4138 streamsize __nmemb = static_cast<streamsize>(this->egptr() - this->eback() - __unget_sz);
4139 __nmemb = __bufptr_->sgetn((char*)this->eback() + __unget_sz, __nmemb);
4140 if (__nmemb != 0)
4141 {
4142 this->setg(this->eback(),
4143 this->eback() + __unget_sz,
4144 this->eback() + __unget_sz + __nmemb);
4145 __c = *this->gptr();
4146 }
4147 }
4148 else
4149 {
4150 memmove(__extbuf_, __extbufnext_, __extbufend_ - __extbufnext_);
4151 __extbufnext_ = __extbuf_ + (__extbufend_ - __extbufnext_);
4152 __extbufend_ = __extbuf_ + (__extbuf_ == __extbuf_min_ ? sizeof(__extbuf_min_) : __ebs_);
Howard Hinnant0949eed2011-06-30 21:18:19 +00004153 streamsize __nmemb = _VSTD::min(static_cast<streamsize>(this->egptr() - this->eback() - __unget_sz),
Howard Hinnant4b53f502010-06-01 20:09:18 +00004154 static_cast<streamsize>(__extbufend_ - __extbufnext_));
4155 codecvt_base::result __r;
4156 state_type __svs = __st_;
4157 streamsize __nr = __bufptr_->sgetn(const_cast<char*>(__extbufnext_), __nmemb);
4158 if (__nr != 0)
4159 {
4160 __extbufend_ = __extbufnext_ + __nr;
4161 char_type* __inext;
4162 __r = __cv_->in(__st_, __extbuf_, __extbufend_, __extbufnext_,
4163 this->eback() + __unget_sz,
4164 this->egptr(), __inext);
4165 if (__r == codecvt_base::noconv)
4166 {
4167 this->setg((char_type*)__extbuf_, (char_type*)__extbuf_, (char_type*)__extbufend_);
4168 __c = *this->gptr();
4169 }
4170 else if (__inext != this->eback() + __unget_sz)
4171 {
4172 this->setg(this->eback(), this->eback() + __unget_sz, __inext);
4173 __c = *this->gptr();
4174 }
4175 }
4176 }
4177 }
4178 else
4179 __c = *this->gptr();
4180 if (this->eback() == &__1buf)
4181 this->setg(0, 0, 0);
4182 return __c;
4183}
4184
4185template <class _Codecvt, class _Elem, class _Tr>
4186typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
4187wbuffer_convert<_Codecvt, _Elem, _Tr>::pbackfail(int_type __c)
4188{
4189 if (__cv_ != 0 && __bufptr_ != 0 && this->eback() < this->gptr())
4190 {
4191 if (traits_type::eq_int_type(__c, traits_type::eof()))
4192 {
4193 this->gbump(-1);
4194 return traits_type::not_eof(__c);
4195 }
4196 if (traits_type::eq(traits_type::to_char_type(__c), this->gptr()[-1]))
4197 {
4198 this->gbump(-1);
4199 *this->gptr() = traits_type::to_char_type(__c);
4200 return __c;
4201 }
4202 }
4203 return traits_type::eof();
4204}
4205
4206template <class _Codecvt, class _Elem, class _Tr>
Howard Hinnantd23b4642010-05-31 20:58:54 +00004207typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
4208wbuffer_convert<_Codecvt, _Elem, _Tr>::overflow(int_type __c)
4209{
Howard Hinnant4b53f502010-06-01 20:09:18 +00004210 if (__cv_ == 0 || __bufptr_ == 0)
4211 return traits_type::eof();
4212 __write_mode();
4213 char_type __1buf;
4214 char_type* __pb_save = this->pbase();
4215 char_type* __epb_save = this->epptr();
4216 if (!traits_type::eq_int_type(__c, traits_type::eof()))
4217 {
4218 if (this->pptr() == 0)
4219 this->setp(&__1buf, &__1buf+1);
4220 *this->pptr() = traits_type::to_char_type(__c);
4221 this->pbump(1);
4222 }
4223 if (this->pptr() != this->pbase())
4224 {
4225 if (__always_noconv_)
4226 {
4227 streamsize __nmemb = static_cast<streamsize>(this->pptr() - this->pbase());
4228 if (__bufptr_->sputn((const char*)this->pbase(), __nmemb) != __nmemb)
4229 return traits_type::eof();
4230 }
4231 else
4232 {
4233 char* __extbe = __extbuf_;
4234 codecvt_base::result __r;
4235 do
4236 {
4237 const char_type* __e;
4238 __r = __cv_->out(__st_, this->pbase(), this->pptr(), __e,
4239 __extbuf_, __extbuf_ + __ebs_, __extbe);
4240 if (__e == this->pbase())
4241 return traits_type::eof();
4242 if (__r == codecvt_base::noconv)
4243 {
4244 streamsize __nmemb = static_cast<size_t>(this->pptr() - this->pbase());
4245 if (__bufptr_->sputn((const char*)this->pbase(), __nmemb) != __nmemb)
4246 return traits_type::eof();
4247 }
4248 else if (__r == codecvt_base::ok || __r == codecvt_base::partial)
4249 {
4250 streamsize __nmemb = static_cast<size_t>(__extbe - __extbuf_);
4251 if (__bufptr_->sputn(__extbuf_, __nmemb) != __nmemb)
4252 return traits_type::eof();
4253 if (__r == codecvt_base::partial)
4254 {
4255 this->setp((char_type*)__e, this->pptr());
4256 this->pbump(this->epptr() - this->pbase());
4257 }
4258 }
4259 else
4260 return traits_type::eof();
4261 } while (__r == codecvt_base::partial);
4262 }
4263 this->setp(__pb_save, __epb_save);
4264 }
4265 return traits_type::not_eof(__c);
4266}
4267
4268template <class _Codecvt, class _Elem, class _Tr>
4269basic_streambuf<_Elem, _Tr>*
4270wbuffer_convert<_Codecvt, _Elem, _Tr>::setbuf(char_type* __s, streamsize __n)
4271{
4272 this->setg(0, 0, 0);
4273 this->setp(0, 0);
4274 if (__owns_eb_)
4275 delete [] __extbuf_;
4276 if (__owns_ib_)
4277 delete [] __intbuf_;
4278 __ebs_ = __n;
4279 if (__ebs_ > sizeof(__extbuf_min_))
4280 {
4281 if (__always_noconv_ && __s)
4282 {
4283 __extbuf_ = (char*)__s;
4284 __owns_eb_ = false;
4285 }
4286 else
4287 {
4288 __extbuf_ = new char[__ebs_];
4289 __owns_eb_ = true;
4290 }
4291 }
4292 else
4293 {
4294 __extbuf_ = __extbuf_min_;
4295 __ebs_ = sizeof(__extbuf_min_);
4296 __owns_eb_ = false;
4297 }
4298 if (!__always_noconv_)
4299 {
4300 __ibs_ = max<streamsize>(__n, sizeof(__extbuf_min_));
4301 if (__s && __ibs_ >= sizeof(__extbuf_min_))
4302 {
4303 __intbuf_ = __s;
4304 __owns_ib_ = false;
4305 }
4306 else
4307 {
4308 __intbuf_ = new char_type[__ibs_];
4309 __owns_ib_ = true;
4310 }
4311 }
4312 else
4313 {
4314 __ibs_ = 0;
4315 __intbuf_ = 0;
4316 __owns_ib_ = false;
4317 }
4318 return this;
4319}
4320
4321template <class _Codecvt, class _Elem, class _Tr>
4322typename wbuffer_convert<_Codecvt, _Elem, _Tr>::pos_type
4323wbuffer_convert<_Codecvt, _Elem, _Tr>::seekoff(off_type __off, ios_base::seekdir __way,
4324 ios_base::openmode __om)
4325{
4326 int __width = __cv_->encoding();
4327 if (__cv_ == 0 || __bufptr_ == 0 || (__width <= 0 && __off != 0) || sync())
4328 return pos_type(off_type(-1));
4329 // __width > 0 || __off == 0
4330 switch (__way)
4331 {
4332 case ios_base::beg:
4333 break;
4334 case ios_base::cur:
4335 break;
4336 case ios_base::end:
4337 break;
4338 default:
4339 return pos_type(off_type(-1));
4340 }
4341 pos_type __r = __bufptr_->pubseekoff(__width * __off, __way, __om);
4342 __r.state(__st_);
4343 return __r;
4344}
4345
4346template <class _Codecvt, class _Elem, class _Tr>
4347typename wbuffer_convert<_Codecvt, _Elem, _Tr>::pos_type
4348wbuffer_convert<_Codecvt, _Elem, _Tr>::seekpos(pos_type __sp, ios_base::openmode __wch)
4349{
4350 if (__cv_ == 0 || __bufptr_ == 0 || sync())
4351 return pos_type(off_type(-1));
4352 if (__bufptr_->pubseekpos(__sp, __wch) == pos_type(off_type(-1)))
4353 return pos_type(off_type(-1));
4354 return __sp;
4355}
4356
4357template <class _Codecvt, class _Elem, class _Tr>
4358int
4359wbuffer_convert<_Codecvt, _Elem, _Tr>::sync()
4360{
4361 if (__cv_ == 0 || __bufptr_ == 0)
4362 return 0;
4363 if (__cm_ & ios_base::out)
4364 {
4365 if (this->pptr() != this->pbase())
4366 if (overflow() == traits_type::eof())
4367 return -1;
4368 codecvt_base::result __r;
4369 do
4370 {
4371 char* __extbe;
4372 __r = __cv_->unshift(__st_, __extbuf_, __extbuf_ + __ebs_, __extbe);
4373 streamsize __nmemb = static_cast<streamsize>(__extbe - __extbuf_);
4374 if (__bufptr_->sputn(__extbuf_, __nmemb) != __nmemb)
4375 return -1;
4376 } while (__r == codecvt_base::partial);
4377 if (__r == codecvt_base::error)
4378 return -1;
4379 if (__bufptr_->pubsync())
4380 return -1;
4381 }
4382 else if (__cm_ & ios_base::in)
4383 {
4384 off_type __c;
4385 if (__always_noconv_)
4386 __c = this->egptr() - this->gptr();
4387 else
4388 {
4389 int __width = __cv_->encoding();
4390 __c = __extbufend_ - __extbufnext_;
4391 if (__width > 0)
4392 __c += __width * (this->egptr() - this->gptr());
4393 else
4394 {
4395 if (this->gptr() != this->egptr())
4396 {
4397 reverse(this->gptr(), this->egptr());
4398 codecvt_base::result __r;
4399 const char_type* __e = this->gptr();
4400 char* __extbe;
4401 do
4402 {
4403 __r = __cv_->out(__st_, __e, this->egptr(), __e,
4404 __extbuf_, __extbuf_ + __ebs_, __extbe);
4405 switch (__r)
4406 {
4407 case codecvt_base::noconv:
4408 __c += this->egptr() - this->gptr();
4409 break;
4410 case codecvt_base::ok:
4411 case codecvt_base::partial:
4412 __c += __extbe - __extbuf_;
4413 break;
4414 default:
4415 return -1;
4416 }
4417 } while (__r == codecvt_base::partial);
4418 }
4419 }
4420 }
4421 if (__bufptr_->pubseekoff(-__c, ios_base::cur, __cm_) == pos_type(off_type(-1)))
4422 return -1;
4423 this->setg(0, 0, 0);
4424 __cm_ = 0;
4425 }
4426 return 0;
4427}
4428
4429template <class _Codecvt, class _Elem, class _Tr>
4430bool
4431wbuffer_convert<_Codecvt, _Elem, _Tr>::__read_mode()
4432{
4433 if (!(__cm_ & ios_base::in))
4434 {
4435 this->setp(0, 0);
4436 if (__always_noconv_)
4437 this->setg((char_type*)__extbuf_,
4438 (char_type*)__extbuf_ + __ebs_,
4439 (char_type*)__extbuf_ + __ebs_);
4440 else
4441 this->setg(__intbuf_, __intbuf_ + __ibs_, __intbuf_ + __ibs_);
4442 __cm_ = ios_base::in;
4443 return true;
4444 }
4445 return false;
4446}
4447
4448template <class _Codecvt, class _Elem, class _Tr>
4449void
4450wbuffer_convert<_Codecvt, _Elem, _Tr>::__write_mode()
4451{
4452 if (!(__cm_ & ios_base::out))
4453 {
4454 this->setg(0, 0, 0);
4455 if (__ebs_ > sizeof(__extbuf_min_))
4456 {
4457 if (__always_noconv_)
4458 this->setp((char_type*)__extbuf_,
4459 (char_type*)__extbuf_ + (__ebs_ - 1));
4460 else
4461 this->setp(__intbuf_, __intbuf_ + (__ibs_ - 1));
4462 }
4463 else
4464 this->setp(0, 0);
4465 __cm_ = ios_base::out;
4466 }
4467}
4468
4469template <class _Codecvt, class _Elem, class _Tr>
4470wbuffer_convert<_Codecvt, _Elem, _Tr>*
4471wbuffer_convert<_Codecvt, _Elem, _Tr>::__close()
4472{
4473 wbuffer_convert* __rt = 0;
4474 if (__cv_ != 0 && __bufptr_ != 0)
4475 {
4476 __rt = this;
4477 if ((__cm_ & ios_base::out) && sync())
4478 __rt = 0;
4479 }
4480 return __rt;
Howard Hinnantd23b4642010-05-31 20:58:54 +00004481}
4482
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004483_LIBCPP_END_NAMESPACE_STD
4484
4485#endif // _LIBCPP_LOCALE