blob: adf8e2f9cfc17fe47d1663bcbca9a88bd6f37793 [file] [log] [blame]
Howard Hinnantc51e1022010-05-11 19:42:16 +00001// -*- C++ -*-
2//===-------------------------- locale ------------------------------------===//
3//
Howard Hinnantc566dc32010-05-11 21:36:01 +00004// The LLVM Compiler Infrastructure
Howard Hinnantc51e1022010-05-11 19:42:16 +00005//
Howard Hinnantee11c312010-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 Hinnantc51e1022010-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 Hinnant7c9e5732011-05-31 15:34:58 +000039 locale() noexcept;
40 locale(const locale& other) noexcept;
Howard Hinnantc51e1022010-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 Hinnant7c9e5732011-05-31 15:34:58 +000048 ~locale(); // not virtual
Howard Hinnantc51e1022010-05-11 19:42:16 +000049
Howard Hinnant7c9e5732011-05-31 15:34:58 +000050 const locale& operator=(const locale& other) noexcept;
Howard Hinnantc51e1022010-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 Hinnant7c9e5732011-05-31 15:34:58 +000068template <class Facet> bool has_facet(const locale&) noexcept;
Howard Hinnantc51e1022010-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 Hinnant9dd7e892010-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 Hinnantc51e1022010-05-11 19:42:16 +0000116template <class Codecvt, class Elem = wchar_t, class Tr = char_traits<Elem>>
Howard Hinnant9dd7e892010-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 Hinnantc51e1022010-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 Hinnant155c2af2010-05-24 17:49:41 +0000184#if !__APPLE__
185#include <cstdarg>
186#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000187#include <cstdlib>
188#include <ctime>
Howard Hinnanteb505f62011-09-23 16:11:27 +0000189#if _WIN32
Howard Hinnantae0f80b2011-09-29 20:33:10 +0000190#include <support/win32/locale_win32.h>
Howard Hinnanteb505f62011-09-23 16:11:27 +0000191#else // _WIN32
Howard Hinnantc51e1022010-05-11 19:42:16 +0000192#include <nl_types.h>
Howard Hinnantdd0d7022011-09-22 19:10:18 +0000193#endif // !_WIN32
Howard Hinnantc51e1022010-05-11 19:42:16 +0000194
Howard Hinnantc5a5fbd2011-11-29 16:45:27 +0000195#include <__undef_min_max>
196
Howard Hinnantaaaa52b2011-10-17 20:05:10 +0000197#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000198#pragma GCC system_header
Howard Hinnantaaaa52b2011-10-17 20:05:10 +0000199#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000200
201_LIBCPP_BEGIN_NAMESPACE_STD
202
Howard Hinnantf312e3e2011-09-28 23:39:33 +0000203#if __APPLE__ || __FreeBSD__
Howard Hinnant1ab52da2011-09-28 21:05:01 +0000204# define _LIBCPP_GET_C_LOCALE 0
205#else
206# define _LIBCPP_GET_C_LOCALE __cloc()
Howard Hinnantf312e3e2011-09-28 23:39:33 +0000207 // Get the C locale object
208 locale_t __cloc();
209#define __cloc_defined
Howard Hinnant1ab52da2011-09-28 21:05:01 +0000210#endif
211
Alexis Hunt1adf2aa2011-07-15 05:40:33 +0000212typedef _VSTD::remove_pointer<locale_t>::type __locale_struct;
213typedef _VSTD::unique_ptr<__locale_struct, decltype(&freelocale)> __locale_unique_ptr;
214typedef _VSTD::unique_ptr<__locale_struct, decltype(&uselocale)> __locale_raii;
215
Howard Hinnant155c2af2010-05-24 17:49:41 +0000216// OSX has nice foo_l() functions that let you turn off use of the global
217// locale. Linux, not so much. The following functions avoid the locale when
218// that's possible and otherwise do the wrong thing. FIXME.
Howard Hinnantf312e3e2011-09-28 23:39:33 +0000219#ifdef __linux__
Alexis Hunt1adf2aa2011-07-15 05:40:33 +0000220
221#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
222decltype(MB_CUR_MAX_L(_VSTD::declval<locale_t>()))
Howard Hinnant756c69b2010-09-22 16:48:34 +0000223inline _LIBCPP_INLINE_VISIBILITY
Alexis Hunt1adf2aa2011-07-15 05:40:33 +0000224__mb_cur_max_l(locale_t __l)
Howard Hinnant155c2af2010-05-24 17:49:41 +0000225{
Alexis Hunt1adf2aa2011-07-15 05:40:33 +0000226 return MB_CUR_MAX_L(__l);
227}
228#else // _LIBCPP_LOCALE__L_EXTENSIONS
229_LIBCPP_ALWAYS_INLINE inline
230decltype(MB_CUR_MAX) __mb_cur_max_l(locale_t __l)
231{
232 __locale_raii __current(uselocale(__l), uselocale);
233 return MB_CUR_MAX;
234}
235#endif // _LIBCPP_LOCALE__L_EXTENSIONS
236
237_LIBCPP_ALWAYS_INLINE inline
238wint_t __btowc_l(int __c, locale_t __l)
239{
Howard Hinnantf312e3e2011-09-28 23:39:33 +0000240#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Alexis Hunt1adf2aa2011-07-15 05:40:33 +0000241 return btowc_l(__c, __l);
242#else
243 __locale_raii __current(uselocale(__l), uselocale);
244 return btowc(__c);
245#endif
Alexis Huntd4a24912011-07-13 06:40:50 +0000246}
Howard Hinnant2de5c472011-07-13 15:48:16 +0000247
Alexis Hunt1adf2aa2011-07-15 05:40:33 +0000248_LIBCPP_ALWAYS_INLINE inline
249int __wctob_l(wint_t __c, locale_t __l)
Alexis Huntd4a24912011-07-13 06:40:50 +0000250{
Alexis Hunt1adf2aa2011-07-15 05:40:33 +0000251#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
252 return wctob_l(__c, __l);
253#else
254 __locale_raii __current(uselocale(__l), uselocale);
255 return wctob(__c);
256#endif
Alexis Huntd4a24912011-07-13 06:40:50 +0000257}
Alexis Hunt1adf2aa2011-07-15 05:40:33 +0000258
259_LIBCPP_ALWAYS_INLINE inline
260size_t __wcsnrtombs_l(char *__dest, const wchar_t **__src, size_t __nwc,
261 size_t __len, mbstate_t *__ps, locale_t __l)
262{
263#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
264 return wcsnrtombs_l(__dest, __src, __nwc, __len, __ps, __l);
265#else
266 __locale_raii __current(uselocale(__l), uselocale);
267 return wcsnrtombs(__dest, __src, __nwc, __len, __ps);
268#endif
269}
270
271_LIBCPP_ALWAYS_INLINE inline
272size_t __wcrtomb_l(char *__s, wchar_t __wc, mbstate_t *__ps, locale_t __l)
273{
274#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
275 return wcrtomb_l(__s, __wc, __ps, __l);
276#else
277 __locale_raii __current(uselocale(__l), uselocale);
278 return wcrtomb(__s, __wc, __ps);
279#endif
280}
281
282_LIBCPP_ALWAYS_INLINE inline
283size_t __mbsnrtowcs_l(wchar_t * __dest, const char **__src, size_t __nms,
284 size_t __len, mbstate_t *__ps, locale_t __l)
285{
286#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
David Chisnall1d581062011-09-21 08:39:44 +0000287 return mbsnrtowcs_l(__dest, __src, __nms, __len, __ps, __l);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +0000288#else
289 __locale_raii __current(uselocale(__l), uselocale);
290 return mbsnrtowcs(__dest, __src, __nms, __len, __ps);
291#endif
292}
293
294_LIBCPP_ALWAYS_INLINE inline
295size_t __mbrtowc_l(wchar_t *__pwc, const char *__s, size_t __n,
296 mbstate_t *__ps, locale_t __l)
297{
298#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
299 return mbrtowc_l(__pwc, __s, __n, __ps, __l);
300#else
301 __locale_raii __current(uselocale(__l), uselocale);
302 return mbrtowc(__pwc, __s, __n, __ps);
303#endif
304}
305
306_LIBCPP_ALWAYS_INLINE inline
307int __mbtowc_l(wchar_t *__pwc, const char *__pmb, size_t __max, locale_t __l)
308{
309#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
David Chisnall1d581062011-09-21 08:39:44 +0000310 return mbtowc_l(__pwc, __pmb, __max, __l);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +0000311#else
312 __locale_raii __current(uselocale(__l), uselocale);
313 return mbtowc(__pwc, __pmb, __max);
314#endif
315}
316
317_LIBCPP_ALWAYS_INLINE inline
318size_t __mbrlen_l(const char *__s, size_t __n, mbstate_t *__ps, locale_t __l)
319{
320#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
321 return mbrlen_l(__s, __n, __ps, __l);
322#else
323 __locale_raii __current(uselocale(__l), uselocale);
324 return mbrlen(__s, __n, __ps);
325#endif
326}
327
328_LIBCPP_ALWAYS_INLINE inline
329lconv *__localeconv_l(locale_t __l)
330{
331#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
332 return localeconv_l(__l);
333#else
334 __locale_raii __current(uselocale(__l), uselocale);
335 return localeconv();
336#endif
337}
338
339_LIBCPP_ALWAYS_INLINE inline
340size_t __mbsrtowcs_l(wchar_t *__dest, const char **__src, size_t __len,
341 mbstate_t *__ps, locale_t __l)
342{
343#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
344 return mbsrtowcs_l(__dest, __src, __len, __ps, __l);
345#else
346 __locale_raii __current(uselocale(__l), uselocale);
347 return mbsrtowcs(__dest, __src, __len, __ps);
348#endif
349}
350
351_LIBCPP_ALWAYS_INLINE inline
352int __sprintf_l(char *__s, locale_t __l, const char *__format, ...) {
353 va_list __va;
354 va_start(__va, __format);
355#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
356 int __res = vsprintf_l(__s, __l, __format, __va);
357#else
358 __locale_raii __current(uselocale(__l), uselocale);
359 int __res = vsprintf(__s, __format, __va);
360#endif
361 va_end(__va);
362 return __res;
363}
364
365_LIBCPP_ALWAYS_INLINE inline
366int __snprintf_l(char *__s, size_t __n, locale_t __l, const char *__format, ...) {
367 va_list __va;
368 va_start(__va, __format);
369#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
370 int __res = vsnprintf_l(__s, __n, __l, __format, __va);
371#else
372 __locale_raii __current(uselocale(__l), uselocale);
373 int __res = vsnprintf(__s, __n, __format, __va);
374#endif
375 va_end(__va);
376 return __res;
377}
378
379_LIBCPP_ALWAYS_INLINE inline
380int __asprintf_l(char **__s, locale_t __l, const char *__format, ...) {
381 va_list __va;
382 va_start(__va, __format);
383#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
384 int __res = vasprintf_l(__s, __l, __format, __va);
385#else
386 __locale_raii __current(uselocale(__l), uselocale);
387 int __res = vasprintf(__s, __format, __va);
388#endif
389 va_end(__va);
390 return __res;
391}
392
393_LIBCPP_ALWAYS_INLINE inline
394int __sscanf_l(const char *__s, locale_t __l, const char *__format, ...) {
395 va_list __va;
396 va_start(__va, __format);
397#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
398 int __res = vsscanf_l(__s, __l, __format, __va);
399#else
400 __locale_raii __current(uselocale(__l), uselocale);
401 int __res = vsscanf(__s, __format, __va);
402#endif
403 va_end(__va);
404 return __res;
405}
406
Howard Hinnantf312e3e2011-09-28 23:39:33 +0000407#endif // __linux__
Howard Hinnant155c2af2010-05-24 17:49:41 +0000408
Howard Hinnantc51e1022010-05-11 19:42:16 +0000409// __scan_keyword
410// Scans [__b, __e) until a match is found in the basic_strings range
411// [__kb, __ke) or until it can be shown that there is no match in [__kb, __ke).
412// __b will be incremented (visibly), consuming CharT until a match is found
413// or proved to not exist. A keyword may be "", in which will match anything.
414// If one keyword is a prefix of another, and the next CharT in the input
415// might match another keyword, the algorithm will attempt to find the longest
416// matching keyword. If the longer matching keyword ends up not matching, then
417// no keyword match is found. If no keyword match is found, __ke is returned
418// and failbit is set in __err.
419// Else an iterator pointing to the matching keyword is found. If more than
420// one keyword matches, an iterator to the first matching keyword is returned.
421// If on exit __b == __e, eofbit is set in __err. If __case_senstive is false,
422// __ct is used to force to lower case before comparing characters.
423// Examples:
424// Keywords: "a", "abb"
425// If the input is "a", the first keyword matches and eofbit is set.
426// If the input is "abc", no match is found and "ab" are consumed.
427template <class _InputIterator, class _ForwardIterator, class _Ctype>
428_LIBCPP_HIDDEN
429_ForwardIterator
430__scan_keyword(_InputIterator& __b, _InputIterator __e,
431 _ForwardIterator __kb, _ForwardIterator __ke,
432 const _Ctype& __ct, ios_base::iostate& __err,
433 bool __case_sensitive = true)
434{
435 typedef typename iterator_traits<_InputIterator>::value_type _CharT;
Howard Hinnant28b24882011-12-01 20:21:04 +0000436 size_t __nkw = static_cast<size_t>(_VSTD::distance(__kb, __ke));
Howard Hinnantc51e1022010-05-11 19:42:16 +0000437 const unsigned char __doesnt_match = '\0';
438 const unsigned char __might_match = '\1';
439 const unsigned char __does_match = '\2';
440 unsigned char __statbuf[100];
441 unsigned char* __status = __statbuf;
442 unique_ptr<unsigned char, void(*)(void*)> __stat_hold(0, free);
443 if (__nkw > sizeof(__statbuf))
444 {
445 __status = (unsigned char*)malloc(__nkw);
446 if (__status == 0)
447 __throw_bad_alloc();
448 __stat_hold.reset(__status);
449 }
450 size_t __n_might_match = __nkw; // At this point, any keyword might match
451 size_t __n_does_match = 0; // but none of them definitely do
452 // Initialize all statuses to __might_match, except for "" keywords are __does_match
453 unsigned char* __st = __status;
454 for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, ++__st)
455 {
456 if (!__ky->empty())
457 *__st = __might_match;
458 else
459 {
460 *__st = __does_match;
461 --__n_might_match;
462 ++__n_does_match;
463 }
464 }
465 // While there might be a match, test keywords against the next CharT
466 for (size_t __indx = 0; __b != __e && __n_might_match > 0; ++__indx)
467 {
468 // Peek at the next CharT but don't consume it
469 _CharT __c = *__b;
470 if (!__case_sensitive)
471 __c = __ct.toupper(__c);
472 bool __consume = false;
473 // For each keyword which might match, see if the __indx character is __c
474 // If a match if found, consume __c
475 // If a match is found, and that is the last character in the keyword,
476 // then that keyword matches.
477 // If the keyword doesn't match this character, then change the keyword
478 // to doesn't match
479 __st = __status;
480 for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, ++__st)
481 {
482 if (*__st == __might_match)
483 {
484 _CharT __kc = (*__ky)[__indx];
485 if (!__case_sensitive)
486 __kc = __ct.toupper(__kc);
487 if (__c == __kc)
488 {
489 __consume = true;
490 if (__ky->size() == __indx+1)
491 {
492 *__st = __does_match;
493 --__n_might_match;
494 ++__n_does_match;
495 }
496 }
497 else
498 {
499 *__st = __doesnt_match;
500 --__n_might_match;
501 }
502 }
503 }
504 // consume if we matched a character
505 if (__consume)
506 {
507 ++__b;
508 // If we consumed a character and there might be a matched keyword that
509 // was marked matched on a previous iteration, then such keywords
510 // which are now marked as not matching.
511 if (__n_might_match + __n_does_match > 1)
512 {
513 __st = __status;
514 for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, ++__st)
515 {
516 if (*__st == __does_match && __ky->size() != __indx+1)
517 {
518 *__st = __doesnt_match;
519 --__n_does_match;
520 }
521 }
522 }
523 }
524 }
525 // We've exited the loop because we hit eof and/or we have no more "might matches".
526 if (__b == __e)
527 __err |= ios_base::eofbit;
528 // Return the first matching result
529 for (__st = __status; __kb != __ke; ++__kb, ++__st)
530 if (*__st == __does_match)
531 break;
532 if (__kb == __ke)
533 __err |= ios_base::failbit;
534 return __kb;
535}
536
537struct __num_get_base
538{
539 static const int __num_get_buf_sz = 40;
540
541 static int __get_base(ios_base&);
542 static const char __src[33];
543};
544
545void __check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
546 ios_base::iostate& __err);
547
Howard Hinnantc51e1022010-05-11 19:42:16 +0000548template <class _CharT>
549struct __num_get
550 : protected __num_get_base
551{
552 static string __stage2_int_prep(ios_base& __iob, _CharT* __atoms, _CharT& __thousands_sep);
553 static string __stage2_float_prep(ios_base& __iob, _CharT* __atoms, _CharT& __decimal_point,
554 _CharT& __thousands_sep);
555 static int __stage2_int_loop(_CharT __ct, int __base, char* __a, char*& __a_end,
556 unsigned& __dc, _CharT __thousands_sep, const string& __grouping,
557 unsigned* __g, unsigned*& __g_end, _CharT* __atoms);
558 static int __stage2_float_loop(_CharT __ct, bool& __in_units, char& __exp,
559 char* __a, char*& __a_end,
560 _CharT __decimal_point, _CharT __thousands_sep,
561 const string& __grouping, unsigned* __g,
562 unsigned*& __g_end, unsigned& __dc, _CharT* __atoms);
563};
564
565template <class _CharT>
566string
567__num_get<_CharT>::__stage2_int_prep(ios_base& __iob, _CharT* __atoms, _CharT& __thousands_sep)
568{
569 locale __loc = __iob.getloc();
570 use_facet<ctype<_CharT> >(__loc).widen(__src, __src + 26, __atoms);
571 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
572 __thousands_sep = __np.thousands_sep();
573 return __np.grouping();
574}
575
576template <class _CharT>
577string
578__num_get<_CharT>::__stage2_float_prep(ios_base& __iob, _CharT* __atoms, _CharT& __decimal_point,
579 _CharT& __thousands_sep)
580{
581 locale __loc = __iob.getloc();
582 use_facet<ctype<_CharT> >(__loc).widen(__src, __src + 32, __atoms);
583 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
584 __decimal_point = __np.decimal_point();
585 __thousands_sep = __np.thousands_sep();
586 return __np.grouping();
587}
588
589template <class _CharT>
590int
591__num_get<_CharT>::__stage2_int_loop(_CharT __ct, int __base, char* __a, char*& __a_end,
592 unsigned& __dc, _CharT __thousands_sep, const string& __grouping,
593 unsigned* __g, unsigned*& __g_end, _CharT* __atoms)
594{
Howard Hinnantf57b3fc2011-03-09 01:03:19 +0000595 if (__a_end == __a && (__ct == __atoms[24] || __ct == __atoms[25]))
596 {
597 *__a_end++ = __ct == __atoms[24] ? '+' : '-';
598 __dc = 0;
599 return 0;
600 }
Howard Hinnant28b24882011-12-01 20:21:04 +0000601 if (__grouping.size() != 0 && __ct == __thousands_sep)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000602 {
603 if (__g_end-__g < __num_get_buf_sz)
604 {
605 *__g_end++ = __dc;
606 __dc = 0;
607 }
608 return 0;
609 }
610 ptrdiff_t __f = find(__atoms, __atoms + 26, __ct) - __atoms;
Howard Hinnantf57b3fc2011-03-09 01:03:19 +0000611 if (__f >= 24)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000612 return -1;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000613 switch (__base)
614 {
615 case 8:
616 case 10:
617 if (__f >= __base)
Howard Hinnantf57b3fc2011-03-09 01:03:19 +0000618 return -1;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000619 break;
Howard Hinnantf57b3fc2011-03-09 01:03:19 +0000620 case 16:
621 if (__f < 22)
622 break;
623 if (__a_end != __a && __a_end - __a <= 2 && __a_end[-1] == '0')
624 {
625 __dc = 0;
626 *__a_end++ = __src[__f];
Howard Hinnantc51e1022010-05-11 19:42:16 +0000627 return 0;
Howard Hinnantf57b3fc2011-03-09 01:03:19 +0000628 }
629 return -1;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000630 }
Howard Hinnantf57b3fc2011-03-09 01:03:19 +0000631 if (__a_end-__a < __num_get_buf_sz - 1)
632 *__a_end++ = __src[__f];
Howard Hinnantc51e1022010-05-11 19:42:16 +0000633 ++__dc;
634 return 0;
635}
636
637template <class _CharT>
638int
639__num_get<_CharT>::__stage2_float_loop(_CharT __ct, bool& __in_units, char& __exp, char* __a, char*& __a_end,
640 _CharT __decimal_point, _CharT __thousands_sep, const string& __grouping,
641 unsigned* __g, unsigned*& __g_end, unsigned& __dc, _CharT* __atoms)
642{
643 if (__ct == __decimal_point)
644 {
645 if (!__in_units)
646 return -1;
647 __in_units = false;
648 *__a_end++ = '.';
649 if (__grouping.size() != 0 && __g_end-__g < __num_get_buf_sz)
650 *__g_end++ = __dc;
651 return 0;
652 }
653 if (__ct == __thousands_sep && __grouping.size() != 0)
654 {
655 if (!__in_units)
656 return -1;
657 if (__g_end-__g < __num_get_buf_sz)
658 {
659 *__g_end++ = __dc;
660 __dc = 0;
661 }
662 return 0;
663 }
664 ptrdiff_t __f = find(__atoms, __atoms + 32, __ct) - __atoms;
665 if (__f >= 32)
666 return -1;
667 char __x = __src[__f];
Howard Hinnant5132e192012-02-15 19:19:37 +0000668 if (__x == '-' || __x == '+')
669 {
670 if (__a_end == __a || (__a_end[-1] & 0xDF) == __exp)
671 {
672 *__a_end++ = __x;
673 return 0;
674 }
675 return -1;
676 }
Howard Hinnantc51e1022010-05-11 19:42:16 +0000677 if (__a_end-__a < __num_get_buf_sz - 1)
678 *__a_end++ = __x;
679 if (__x == 'x' || __x == 'X')
680 __exp = 'P';
681 else if ((__x & 0xDF) == __exp)
682 {
683 __in_units = false;
684 if (__grouping.size() != 0 && __g_end-__g < __num_get_buf_sz)
685 *__g_end++ = __dc;
686 }
687 if (__f >= 22)
688 return 0;
689 ++__dc;
690 return 0;
691}
692
Howard Hinnant28b24882011-12-01 20:21:04 +0000693extern template struct __num_get<char>;
694extern template struct __num_get<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000695
696template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnant756c69b2010-09-22 16:48:34 +0000697class _LIBCPP_VISIBLE num_get
Howard Hinnantc51e1022010-05-11 19:42:16 +0000698 : public locale::facet,
699 private __num_get<_CharT>
700{
701public:
702 typedef _CharT char_type;
703 typedef _InputIterator iter_type;
704
705 _LIBCPP_ALWAYS_INLINE
706 explicit num_get(size_t __refs = 0)
707 : locale::facet(__refs) {}
708
709 _LIBCPP_ALWAYS_INLINE
710 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
711 ios_base::iostate& __err, bool& __v) const
712 {
713 return do_get(__b, __e, __iob, __err, __v);
714 }
715
716 _LIBCPP_ALWAYS_INLINE
717 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
718 ios_base::iostate& __err, long& __v) const
719 {
720 return do_get(__b, __e, __iob, __err, __v);
721 }
722
723 _LIBCPP_ALWAYS_INLINE
724 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
725 ios_base::iostate& __err, long long& __v) const
726 {
727 return do_get(__b, __e, __iob, __err, __v);
728 }
729
730 _LIBCPP_ALWAYS_INLINE
731 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
732 ios_base::iostate& __err, unsigned short& __v) const
733 {
734 return do_get(__b, __e, __iob, __err, __v);
735 }
736
737 _LIBCPP_ALWAYS_INLINE
738 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
739 ios_base::iostate& __err, unsigned int& __v) const
740 {
741 return do_get(__b, __e, __iob, __err, __v);
742 }
743
744 _LIBCPP_ALWAYS_INLINE
745 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
746 ios_base::iostate& __err, unsigned long& __v) const
747 {
748 return do_get(__b, __e, __iob, __err, __v);
749 }
750
751 _LIBCPP_ALWAYS_INLINE
752 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
753 ios_base::iostate& __err, unsigned long long& __v) const
754 {
755 return do_get(__b, __e, __iob, __err, __v);
756 }
757
758 _LIBCPP_ALWAYS_INLINE
759 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
760 ios_base::iostate& __err, float& __v) const
761 {
762 return do_get(__b, __e, __iob, __err, __v);
763 }
764
765 _LIBCPP_ALWAYS_INLINE
766 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
767 ios_base::iostate& __err, double& __v) const
768 {
769 return do_get(__b, __e, __iob, __err, __v);
770 }
771
772 _LIBCPP_ALWAYS_INLINE
773 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
774 ios_base::iostate& __err, long double& __v) const
775 {
776 return do_get(__b, __e, __iob, __err, __v);
777 }
778
779 _LIBCPP_ALWAYS_INLINE
780 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
781 ios_base::iostate& __err, void*& __v) const
782 {
783 return do_get(__b, __e, __iob, __err, __v);
784 }
785
786 static locale::id id;
787
788protected:
Howard Hinnant756c69b2010-09-22 16:48:34 +0000789 _LIBCPP_ALWAYS_INLINE
Howard Hinnantc51e1022010-05-11 19:42:16 +0000790 ~num_get() {}
791
792 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
793 ios_base::iostate& __err, bool& __v) const;
794 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
795 ios_base::iostate& __err, long& __v) const;
796 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
797 ios_base::iostate& __err, long long& __v) const;
798 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
799 ios_base::iostate& __err, unsigned short& __v) const;
800 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
801 ios_base::iostate& __err, unsigned int& __v) const;
802 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
803 ios_base::iostate& __err, unsigned long& __v) const;
804 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
805 ios_base::iostate& __err, unsigned long long& __v) const;
806 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
807 ios_base::iostate& __err, float& __v) const;
808 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
809 ios_base::iostate& __err, double& __v) const;
810 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
811 ios_base::iostate& __err, long double& __v) const;
812 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
813 ios_base::iostate& __err, void*& __v) const;
814};
815
816template <class _CharT, class _InputIterator>
817locale::id
818num_get<_CharT, _InputIterator>::id;
819
820template <class _Tp>
821_Tp
822__num_get_signed_integral(const char* __a, const char* __a_end,
823 ios_base::iostate& __err, int __base)
824{
825 if (__a != __a_end)
826 {
Howard Hinnant05c71342011-02-25 19:52:41 +0000827 int __save_errno = errno;
828 errno = 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000829 char *__p2;
Howard Hinnant1ab52da2011-09-28 21:05:01 +0000830 long long __ll = strtoll_l(__a, &__p2, __base, _LIBCPP_GET_C_LOCALE);
Howard Hinnant05c71342011-02-25 19:52:41 +0000831 int __current_errno = errno;
832 if (__current_errno == 0)
833 errno = __save_errno;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000834 if (__p2 != __a_end)
835 {
836 __err = ios_base::failbit;
837 return 0;
838 }
Howard Hinnant05c71342011-02-25 19:52:41 +0000839 else if (__current_errno == ERANGE ||
840 __ll < numeric_limits<_Tp>::min() ||
841 numeric_limits<_Tp>::max() < __ll)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000842 {
843 __err = ios_base::failbit;
Howard Hinnant05c71342011-02-25 19:52:41 +0000844 if (__ll > 0)
845 return numeric_limits<_Tp>::max();
846 else
847 return numeric_limits<_Tp>::min();
Howard Hinnantc51e1022010-05-11 19:42:16 +0000848 }
849 return static_cast<_Tp>(__ll);
850 }
851 __err = ios_base::failbit;
852 return 0;
853}
854
855template <class _Tp>
856_Tp
857__num_get_unsigned_integral(const char* __a, const char* __a_end,
858 ios_base::iostate& __err, int __base)
859{
860 if (__a != __a_end)
861 {
Howard Hinnant05c71342011-02-25 19:52:41 +0000862 if (*__a == '-')
863 {
864 __err = ios_base::failbit;
865 return 0;
866 }
867 int __save_errno = errno;
868 errno = 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000869 char *__p2;
Howard Hinnant1ab52da2011-09-28 21:05:01 +0000870 unsigned long long __ll = strtoull_l(__a, &__p2, __base, _LIBCPP_GET_C_LOCALE);
Howard Hinnant05c71342011-02-25 19:52:41 +0000871 int __current_errno = errno;
872 if (__current_errno == 0)
873 errno = __save_errno;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000874 if (__p2 != __a_end)
875 {
876 __err = ios_base::failbit;
877 return 0;
878 }
Howard Hinnant05c71342011-02-25 19:52:41 +0000879 else if (__current_errno == ERANGE ||
880 numeric_limits<_Tp>::max() < __ll)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000881 {
882 __err = ios_base::failbit;
883 return numeric_limits<_Tp>::max();
884 }
885 return static_cast<_Tp>(__ll);
886 }
887 __err = ios_base::failbit;
888 return 0;
889}
890
891template <class _Tp>
892_Tp
893__num_get_float(const char* __a, const char* __a_end, ios_base::iostate& __err)
894{
895 if (__a != __a_end)
896 {
897 char *__p2;
Howard Hinnant1ab52da2011-09-28 21:05:01 +0000898 long double __ld = strtold_l(__a, &__p2, _LIBCPP_GET_C_LOCALE);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000899 if (__p2 != __a_end)
900 {
901 __err = ios_base::failbit;
902 return 0;
903 }
904 return static_cast<_Tp>(__ld);
905 }
906 __err = ios_base::failbit;
907 return 0;
908}
909
910template <class _CharT, class _InputIterator>
911_InputIterator
912num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
913 ios_base& __iob,
914 ios_base::iostate& __err,
915 bool& __v) const
916{
917 if ((__iob.flags() & ios_base::boolalpha) == 0)
918 {
919 long __lv = -1;
920 __b = do_get(__b, __e, __iob, __err, __lv);
921 switch (__lv)
922 {
923 case 0:
924 __v = false;
925 break;
926 case 1:
927 __v = true;
928 break;
929 default:
930 __v = true;
931 __err = ios_base::failbit;
932 break;
933 }
934 return __b;
935 }
936 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__iob.getloc());
937 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__iob.getloc());
938 typedef typename numpunct<_CharT>::string_type string_type;
939 const string_type __names[2] = {__np.truename(), __np.falsename()};
940 const string_type* __i = __scan_keyword(__b, __e, __names, __names+2,
941 __ct, __err);
942 __v = __i == __names;
943 return __b;
944}
945
946template <class _CharT, class _InputIterator>
947_InputIterator
948num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
949 ios_base& __iob,
950 ios_base::iostate& __err,
951 long& __v) const
952{
953 // Stage 1
954 int __base = this->__get_base(__iob);
955 // Stage 2
956 char_type __atoms[26];
957 char_type __thousands_sep;
958 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
959 char __a[__num_get_base::__num_get_buf_sz] = {0};
960 char* __a_end = __a;
961 unsigned __g[__num_get_base::__num_get_buf_sz];
962 unsigned* __g_end = __g;
963 unsigned __dc = 0;
964 for (; __b != __e; ++__b)
Howard Hinnant3b6579a2010-08-22 00:02:43 +0000965 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantc51e1022010-05-11 19:42:16 +0000966 __thousands_sep, __grouping, __g, __g_end,
967 __atoms))
968 break;
969 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
970 *__g_end++ = __dc;
971 // Stage 3
972 __v = __num_get_signed_integral<long>(__a, __a_end, __err, __base);
973 // Digit grouping checked
974 __check_grouping(__grouping, __g, __g_end, __err);
975 // EOF checked
976 if (__b == __e)
977 __err |= ios_base::eofbit;
978 return __b;
979}
980
981template <class _CharT, class _InputIterator>
982_InputIterator
983num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
984 ios_base& __iob,
985 ios_base::iostate& __err,
986 long long& __v) const
987{
988 // Stage 1
989 int __base = this->__get_base(__iob);
990 // Stage 2
991 char_type __atoms[26];
992 char_type __thousands_sep;
993 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
994 char __a[__num_get_base::__num_get_buf_sz] = {0};
995 char* __a_end = __a;
996 unsigned __g[__num_get_base::__num_get_buf_sz];
997 unsigned* __g_end = __g;
998 unsigned __dc = 0;
999 for (; __b != __e; ++__b)
Howard Hinnant3b6579a2010-08-22 00:02:43 +00001000 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
1001 __thousands_sep, __grouping, __g, __g_end,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001002 __atoms))
1003 break;
1004 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
1005 *__g_end++ = __dc;
1006 // Stage 3
1007 __v = __num_get_signed_integral<long long>(__a, __a_end, __err, __base);
1008 // Digit grouping checked
1009 __check_grouping(__grouping, __g, __g_end, __err);
1010 // EOF checked
1011 if (__b == __e)
1012 __err |= ios_base::eofbit;
1013 return __b;
1014}
1015
1016template <class _CharT, class _InputIterator>
1017_InputIterator
1018num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1019 ios_base& __iob,
1020 ios_base::iostate& __err,
1021 unsigned short& __v) const
1022{
1023 // Stage 1
1024 int __base = this->__get_base(__iob);
1025 // Stage 2
1026 char_type __atoms[26];
1027 char_type __thousands_sep;
1028 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
1029 char __a[__num_get_base::__num_get_buf_sz] = {0};
1030 char* __a_end = __a;
1031 unsigned __g[__num_get_base::__num_get_buf_sz];
1032 unsigned* __g_end = __g;
1033 unsigned __dc = 0;
1034 for (; __b != __e; ++__b)
Howard Hinnant3b6579a2010-08-22 00:02:43 +00001035 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001036 __thousands_sep, __grouping, __g, __g_end,
1037 __atoms))
1038 break;
1039 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
1040 *__g_end++ = __dc;
1041 // Stage 3
1042 __v = __num_get_unsigned_integral<unsigned short>(__a, __a_end, __err, __base);
1043 // Digit grouping checked
1044 __check_grouping(__grouping, __g, __g_end, __err);
1045 // EOF checked
1046 if (__b == __e)
1047 __err |= ios_base::eofbit;
1048 return __b;
1049}
1050
1051template <class _CharT, class _InputIterator>
1052_InputIterator
1053num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1054 ios_base& __iob,
1055 ios_base::iostate& __err,
1056 unsigned int& __v) const
1057{
1058 // Stage 1
1059 int __base = this->__get_base(__iob);
1060 // Stage 2
1061 char_type __atoms[26];
1062 char_type __thousands_sep;
1063 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
1064 char __a[__num_get_base::__num_get_buf_sz] = {0};
1065 char* __a_end = __a;
1066 unsigned __g[__num_get_base::__num_get_buf_sz];
1067 unsigned* __g_end = __g;
1068 unsigned __dc = 0;
1069 for (; __b != __e; ++__b)
Howard Hinnant3b6579a2010-08-22 00:02:43 +00001070 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001071 __thousands_sep, __grouping, __g, __g_end,
1072 __atoms))
1073 break;
1074 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
1075 *__g_end++ = __dc;
1076 // Stage 3
1077 __v = __num_get_unsigned_integral<unsigned int>(__a, __a_end, __err, __base);
1078 // Digit grouping checked
1079 __check_grouping(__grouping, __g, __g_end, __err);
1080 // EOF checked
1081 if (__b == __e)
1082 __err |= ios_base::eofbit;
1083 return __b;
1084}
1085
1086template <class _CharT, class _InputIterator>
1087_InputIterator
1088num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1089 ios_base& __iob,
1090 ios_base::iostate& __err,
1091 unsigned long& __v) const
1092{
1093 // Stage 1
1094 int __base = this->__get_base(__iob);
1095 // Stage 2
1096 char_type __atoms[26];
1097 char_type __thousands_sep;
1098 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
1099 char __a[__num_get_base::__num_get_buf_sz] = {0};
1100 char* __a_end = __a;
1101 unsigned __g[__num_get_base::__num_get_buf_sz];
1102 unsigned* __g_end = __g;
1103 unsigned __dc = 0;
1104 for (; __b != __e; ++__b)
Howard Hinnant3b6579a2010-08-22 00:02:43 +00001105 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001106 __thousands_sep, __grouping, __g, __g_end,
1107 __atoms))
1108 break;
1109 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
1110 *__g_end++ = __dc;
1111 // Stage 3
1112 __v = __num_get_unsigned_integral<unsigned long>(__a, __a_end, __err, __base);
1113 // Digit grouping checked
1114 __check_grouping(__grouping, __g, __g_end, __err);
1115 // EOF checked
1116 if (__b == __e)
1117 __err |= ios_base::eofbit;
1118 return __b;
1119}
1120
1121template <class _CharT, class _InputIterator>
1122_InputIterator
1123num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1124 ios_base& __iob,
1125 ios_base::iostate& __err,
1126 unsigned long long& __v) const
1127{
1128 // Stage 1
1129 int __base = this->__get_base(__iob);
1130 // Stage 2
1131 char_type __atoms[26];
1132 char_type __thousands_sep;
1133 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
1134 char __a[__num_get_base::__num_get_buf_sz] = {0};
1135 char* __a_end = __a;
1136 unsigned __g[__num_get_base::__num_get_buf_sz];
1137 unsigned* __g_end = __g;
1138 unsigned __dc = 0;
1139 for (; __b != __e; ++__b)
Howard Hinnant3b6579a2010-08-22 00:02:43 +00001140 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001141 __thousands_sep, __grouping, __g, __g_end,
1142 __atoms))
1143 break;
1144 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
1145 *__g_end++ = __dc;
1146 // Stage 3
1147 __v = __num_get_unsigned_integral<unsigned long long>(__a, __a_end, __err, __base);
1148 // Digit grouping checked
1149 __check_grouping(__grouping, __g, __g_end, __err);
1150 // EOF checked
1151 if (__b == __e)
1152 __err |= ios_base::eofbit;
1153 return __b;
1154}
1155
1156template <class _CharT, class _InputIterator>
1157_InputIterator
1158num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1159 ios_base& __iob,
1160 ios_base::iostate& __err,
1161 float& __v) const
1162{
1163 // Stage 1, nothing to do
1164 // Stage 2
1165 char_type __atoms[32];
1166 char_type __decimal_point;
1167 char_type __thousands_sep;
Howard Hinnant3b6579a2010-08-22 00:02:43 +00001168 string __grouping = this->__stage2_float_prep(__iob, __atoms,
1169 __decimal_point,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001170 __thousands_sep);
1171 char __a[__num_get_base::__num_get_buf_sz] = {0};
1172 char* __a_end = __a;
1173 unsigned __g[__num_get_base::__num_get_buf_sz];
1174 unsigned* __g_end = __g;
1175 unsigned __dc = 0;
1176 bool __in_units = true;
1177 char __exp = 'E';
1178 for (; __b != __e; ++__b)
Howard Hinnant3b6579a2010-08-22 00:02:43 +00001179 if (this->__stage2_float_loop(*__b, __in_units, __exp, __a, __a_end,
1180 __decimal_point, __thousands_sep,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001181 __grouping, __g, __g_end,
1182 __dc, __atoms))
1183 break;
1184 if (__grouping.size() != 0 && __in_units && __g_end-__g < __num_get_base::__num_get_buf_sz)
1185 *__g_end++ = __dc;
1186 // Stage 3
1187 __v = __num_get_float<float>(__a, __a_end, __err);
1188 // Digit grouping checked
1189 __check_grouping(__grouping, __g, __g_end, __err);
1190 // EOF checked
1191 if (__b == __e)
1192 __err |= ios_base::eofbit;
1193 return __b;
1194}
1195
1196template <class _CharT, class _InputIterator>
1197_InputIterator
1198num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1199 ios_base& __iob,
1200 ios_base::iostate& __err,
1201 double& __v) const
1202{
1203 // Stage 1, nothing to do
1204 // Stage 2
1205 char_type __atoms[32];
1206 char_type __decimal_point;
1207 char_type __thousands_sep;
Howard Hinnant3b6579a2010-08-22 00:02:43 +00001208 string __grouping = this->__stage2_float_prep(__iob, __atoms,
1209 __decimal_point,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001210 __thousands_sep);
1211 char __a[__num_get_base::__num_get_buf_sz] = {0};
1212 char* __a_end = __a;
1213 unsigned __g[__num_get_base::__num_get_buf_sz];
1214 unsigned* __g_end = __g;
1215 unsigned __dc = 0;
1216 bool __in_units = true;
1217 char __exp = 'E';
1218 for (; __b != __e; ++__b)
Howard Hinnant3b6579a2010-08-22 00:02:43 +00001219 if (this->__stage2_float_loop(*__b, __in_units, __exp, __a, __a_end,
1220 __decimal_point, __thousands_sep,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001221 __grouping, __g, __g_end,
1222 __dc, __atoms))
1223 break;
1224 if (__grouping.size() != 0 && __in_units && __g_end-__g < __num_get_base::__num_get_buf_sz)
1225 *__g_end++ = __dc;
1226 // Stage 3
1227 __v = __num_get_float<double>(__a, __a_end, __err);
1228 // Digit grouping checked
1229 __check_grouping(__grouping, __g, __g_end, __err);
1230 // EOF checked
1231 if (__b == __e)
1232 __err |= ios_base::eofbit;
1233 return __b;
1234}
1235
1236template <class _CharT, class _InputIterator>
1237_InputIterator
1238num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1239 ios_base& __iob,
1240 ios_base::iostate& __err,
1241 long double& __v) const
1242{
1243 // Stage 1, nothing to do
1244 // Stage 2
1245 char_type __atoms[32];
1246 char_type __decimal_point;
1247 char_type __thousands_sep;
Howard Hinnant3b6579a2010-08-22 00:02:43 +00001248 string __grouping = this->__stage2_float_prep(__iob, __atoms,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001249 __decimal_point,
1250 __thousands_sep);
1251 char __a[__num_get_base::__num_get_buf_sz] = {0};
1252 char* __a_end = __a;
1253 unsigned __g[__num_get_base::__num_get_buf_sz];
1254 unsigned* __g_end = __g;
1255 unsigned __dc = 0;
1256 bool __in_units = true;
1257 char __exp = 'E';
1258 for (; __b != __e; ++__b)
Howard Hinnant3b6579a2010-08-22 00:02:43 +00001259 if (this->__stage2_float_loop(*__b, __in_units, __exp, __a, __a_end,
1260 __decimal_point, __thousands_sep,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001261 __grouping, __g, __g_end,
1262 __dc, __atoms))
1263 break;
1264 if (__grouping.size() != 0 && __in_units && __g_end-__g < __num_get_base::__num_get_buf_sz)
1265 *__g_end++ = __dc;
1266 // Stage 3
1267 __v = __num_get_float<long double>(__a, __a_end, __err);
1268 // Digit grouping checked
1269 __check_grouping(__grouping, __g, __g_end, __err);
1270 // EOF checked
1271 if (__b == __e)
1272 __err |= ios_base::eofbit;
1273 return __b;
1274}
1275
1276template <class _CharT, class _InputIterator>
1277_InputIterator
1278num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1279 ios_base& __iob,
1280 ios_base::iostate& __err,
1281 void*& __v) const
1282{
1283 // Stage 1
1284 int __base = 16;
1285 // Stage 2
1286 char_type __atoms[26];
Howard Hinnant28b24882011-12-01 20:21:04 +00001287 char_type __thousands_sep = 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001288 string __grouping;
1289 use_facet<ctype<_CharT> >(__iob.getloc()).widen(__num_get_base::__src,
1290 __num_get_base::__src + 26, __atoms);
1291 char __a[__num_get_base::__num_get_buf_sz] = {0};
1292 char* __a_end = __a;
1293 unsigned __g[__num_get_base::__num_get_buf_sz];
1294 unsigned* __g_end = __g;
1295 unsigned __dc = 0;
1296 for (; __b != __e; ++__b)
Howard Hinnant3b6579a2010-08-22 00:02:43 +00001297 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
1298 __thousands_sep, __grouping,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001299 __g, __g_end, __atoms))
1300 break;
1301 // Stage 3
1302 __a[sizeof(__a)-1] = 0;
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001303#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant1ab52da2011-09-28 21:05:01 +00001304 if (sscanf_l(__a, _LIBCPP_GET_C_LOCALE, "%p", &__v) != 1)
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001305#else
1306 if (__sscanf_l(__a, __cloc(), "%p", &__v) != 1)
1307#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001308 __err = ios_base::failbit;
1309 // EOF checked
1310 if (__b == __e)
1311 __err |= ios_base::eofbit;
1312 return __b;
1313}
1314
1315extern template class num_get<char>;
1316extern template class num_get<wchar_t>;
1317
1318struct __num_put_base
1319{
1320protected:
1321 static void __format_int(char* __fmt, const char* __len, bool __signd,
1322 ios_base::fmtflags __flags);
1323 static bool __format_float(char* __fmt, const char* __len,
1324 ios_base::fmtflags __flags);
1325 static char* __identify_padding(char* __nb, char* __ne,
1326 const ios_base& __iob);
1327};
1328
1329template <class _CharT>
1330struct __num_put
1331 : protected __num_put_base
1332{
1333 static void __widen_and_group_int(char* __nb, char* __np, char* __ne,
1334 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1335 const locale& __loc);
1336 static void __widen_and_group_float(char* __nb, char* __np, char* __ne,
1337 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1338 const locale& __loc);
1339};
1340
1341template <class _CharT>
1342void
1343__num_put<_CharT>::__widen_and_group_int(char* __nb, char* __np, char* __ne,
1344 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1345 const locale& __loc)
1346{
1347 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> > (__loc);
1348 const numpunct<_CharT>& __npt = use_facet<numpunct<_CharT> >(__loc);
1349 string __grouping = __npt.grouping();
1350 if (__grouping.empty())
1351 {
1352 __ct.widen(__nb, __ne, __ob);
1353 __oe = __ob + (__ne - __nb);
1354 }
1355 else
1356 {
1357 __oe = __ob;
1358 char* __nf = __nb;
1359 if (*__nf == '-' || *__nf == '+')
1360 *__oe++ = __ct.widen(*__nf++);
1361 if (__ne - __nf >= 2 && __nf[0] == '0' && (__nf[1] == 'x' ||
1362 __nf[1] == 'X'))
1363 {
1364 *__oe++ = __ct.widen(*__nf++);
1365 *__oe++ = __ct.widen(*__nf++);
1366 }
1367 reverse(__nf, __ne);
1368 _CharT __thousands_sep = __npt.thousands_sep();
1369 unsigned __dc = 0;
1370 unsigned __dg = 0;
1371 for (char* __p = __nf; __p < __ne; ++__p)
1372 {
1373 if (static_cast<unsigned>(__grouping[__dg]) > 0 &&
1374 __dc == static_cast<unsigned>(__grouping[__dg]))
1375 {
1376 *__oe++ = __thousands_sep;
1377 __dc = 0;
1378 if (__dg < __grouping.size()-1)
1379 ++__dg;
1380 }
1381 *__oe++ = __ct.widen(*__p);
1382 ++__dc;
1383 }
1384 reverse(__ob + (__nf - __nb), __oe);
1385 }
1386 if (__np == __ne)
1387 __op = __oe;
1388 else
1389 __op = __ob + (__np - __nb);
1390}
1391
1392template <class _CharT>
1393void
1394__num_put<_CharT>::__widen_and_group_float(char* __nb, char* __np, char* __ne,
1395 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1396 const locale& __loc)
1397{
1398 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> > (__loc);
1399 const numpunct<_CharT>& __npt = use_facet<numpunct<_CharT> >(__loc);
1400 string __grouping = __npt.grouping();
1401 __oe = __ob;
1402 char* __nf = __nb;
1403 if (*__nf == '-' || *__nf == '+')
1404 *__oe++ = __ct.widen(*__nf++);
1405 char* __ns;
1406 if (__ne - __nf >= 2 && __nf[0] == '0' && (__nf[1] == 'x' ||
1407 __nf[1] == 'X'))
1408 {
1409 *__oe++ = __ct.widen(*__nf++);
1410 *__oe++ = __ct.widen(*__nf++);
1411 for (__ns = __nf; __ns < __ne; ++__ns)
Howard Hinnant1ab52da2011-09-28 21:05:01 +00001412 if (!isxdigit_l(*__ns, _LIBCPP_GET_C_LOCALE))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001413 break;
1414 }
1415 else
1416 {
1417 for (__ns = __nf; __ns < __ne; ++__ns)
Howard Hinnant1ab52da2011-09-28 21:05:01 +00001418 if (!isdigit_l(*__ns, _LIBCPP_GET_C_LOCALE))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001419 break;
1420 }
1421 if (__grouping.empty())
1422 {
1423 __ct.widen(__nf, __ns, __oe);
1424 __oe += __ns - __nf;
1425 }
1426 else
1427 {
1428 reverse(__nf, __ns);
1429 _CharT __thousands_sep = __npt.thousands_sep();
1430 unsigned __dc = 0;
1431 unsigned __dg = 0;
1432 for (char* __p = __nf; __p < __ns; ++__p)
1433 {
1434 if (__grouping[__dg] > 0 && __dc == static_cast<unsigned>(__grouping[__dg]))
1435 {
1436 *__oe++ = __thousands_sep;
1437 __dc = 0;
1438 if (__dg < __grouping.size()-1)
1439 ++__dg;
1440 }
1441 *__oe++ = __ct.widen(*__p);
1442 ++__dc;
1443 }
1444 reverse(__ob + (__nf - __nb), __oe);
1445 }
1446 for (__nf = __ns; __nf < __ne; ++__nf)
1447 {
1448 if (*__nf == '.')
1449 {
1450 *__oe++ = __npt.decimal_point();
1451 ++__nf;
1452 break;
1453 }
1454 else
1455 *__oe++ = __ct.widen(*__nf);
1456 }
1457 __ct.widen(__nf, __ne, __oe);
1458 __oe += __ne - __nf;
1459 if (__np == __ne)
1460 __op = __oe;
1461 else
1462 __op = __ob + (__np - __nb);
1463}
1464
Howard Hinnant28b24882011-12-01 20:21:04 +00001465extern template struct __num_put<char>;
1466extern template struct __num_put<wchar_t>;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001467
1468template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant756c69b2010-09-22 16:48:34 +00001469class _LIBCPP_VISIBLE num_put
Howard Hinnantc51e1022010-05-11 19:42:16 +00001470 : public locale::facet,
1471 private __num_put<_CharT>
1472{
1473public:
1474 typedef _CharT char_type;
1475 typedef _OutputIterator iter_type;
1476
1477 _LIBCPP_ALWAYS_INLINE
1478 explicit num_put(size_t __refs = 0)
1479 : locale::facet(__refs) {}
1480
1481 _LIBCPP_ALWAYS_INLINE
1482 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1483 bool __v) const
1484 {
1485 return do_put(__s, __iob, __fl, __v);
1486 }
1487
1488 _LIBCPP_ALWAYS_INLINE
1489 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1490 long __v) const
1491 {
1492 return do_put(__s, __iob, __fl, __v);
1493 }
1494
1495 _LIBCPP_ALWAYS_INLINE
1496 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1497 long long __v) const
1498 {
1499 return do_put(__s, __iob, __fl, __v);
1500 }
1501
1502 _LIBCPP_ALWAYS_INLINE
1503 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1504 unsigned long __v) const
1505 {
1506 return do_put(__s, __iob, __fl, __v);
1507 }
1508
1509 _LIBCPP_ALWAYS_INLINE
1510 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1511 unsigned long long __v) const
1512 {
1513 return do_put(__s, __iob, __fl, __v);
1514 }
1515
1516 _LIBCPP_ALWAYS_INLINE
1517 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1518 double __v) const
1519 {
1520 return do_put(__s, __iob, __fl, __v);
1521 }
1522
1523 _LIBCPP_ALWAYS_INLINE
1524 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1525 long double __v) const
1526 {
1527 return do_put(__s, __iob, __fl, __v);
1528 }
1529
1530 _LIBCPP_ALWAYS_INLINE
1531 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1532 const void* __v) const
1533 {
1534 return do_put(__s, __iob, __fl, __v);
1535 }
1536
1537 static locale::id id;
1538
1539protected:
Howard Hinnant756c69b2010-09-22 16:48:34 +00001540 _LIBCPP_ALWAYS_INLINE
Howard Hinnantc51e1022010-05-11 19:42:16 +00001541 ~num_put() {}
1542
1543 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1544 bool __v) const;
1545 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1546 long __v) const;
1547 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1548 long long __v) const;
1549 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1550 unsigned long) const;
1551 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1552 unsigned long long) const;
1553 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1554 double __v) const;
1555 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1556 long double __v) const;
1557 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1558 const void* __v) const;
1559};
1560
1561template <class _CharT, class _OutputIterator>
1562locale::id
1563num_put<_CharT, _OutputIterator>::id;
1564
1565template <class _CharT, class _OutputIterator>
1566_LIBCPP_HIDDEN
1567_OutputIterator
1568__pad_and_output(_OutputIterator __s,
1569 const _CharT* __ob, const _CharT* __op, const _CharT* __oe,
1570 ios_base& __iob, _CharT __fl)
1571{
1572 streamsize __sz = __oe - __ob;
1573 streamsize __ns = __iob.width();
1574 if (__ns > __sz)
1575 __ns -= __sz;
1576 else
1577 __ns = 0;
1578 for (;__ob < __op; ++__ob, ++__s)
1579 *__s = *__ob;
1580 for (; __ns; --__ns, ++__s)
1581 *__s = __fl;
1582 for (; __ob < __oe; ++__ob, ++__s)
1583 *__s = *__ob;
1584 __iob.width(0);
1585 return __s;
1586}
1587
1588template <class _CharT, class _OutputIterator>
1589_OutputIterator
1590num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1591 char_type __fl, bool __v) const
1592{
1593 if ((__iob.flags() & ios_base::boolalpha) == 0)
1594 return do_put(__s, __iob, __fl, (unsigned long)__v);
1595 const numpunct<char_type>& __np = use_facet<numpunct<char_type> >(__iob.getloc());
1596 typedef typename numpunct<char_type>::string_type string_type;
1597 string_type __nm = __v ? __np.truename() : __np.falsename();
1598 for (typename string_type::iterator __i = __nm.begin(); __i != __nm.end(); ++__i, ++__s)
1599 *__s = *__i;
1600 return __s;
1601}
1602
1603template <class _CharT, class _OutputIterator>
1604_OutputIterator
1605num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1606 char_type __fl, long __v) const
1607{
1608 // Stage 1 - Get number in narrow char
1609 char __fmt[6] = {'%', 0};
1610 const char* __len = "l";
1611 this->__format_int(__fmt+1, __len, true, __iob.flags());
1612 const unsigned __nbuf = (numeric_limits<long>::digits / 3)
1613 + ((numeric_limits<long>::digits % 3) != 0)
1614 + 1;
1615 char __nar[__nbuf];
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001616#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant1ab52da2011-09-28 21:05:01 +00001617 int __nc = sprintf_l(__nar, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001618#else
1619 int __nc = __sprintf_l(__nar, __cloc(), __fmt, __v);
1620#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001621 char* __ne = __nar + __nc;
1622 char* __np = this->__identify_padding(__nar, __ne, __iob);
1623 // Stage 2 - Widen __nar while adding thousands separators
1624 char_type __o[2*(__nbuf-1) - 1];
1625 char_type* __op; // pad here
1626 char_type* __oe; // end of output
1627 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1628 // [__o, __oe) contains thousands_sep'd wide number
1629 // Stage 3 & 4
1630 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1631}
1632
1633template <class _CharT, class _OutputIterator>
1634_OutputIterator
1635num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1636 char_type __fl, long long __v) const
1637{
1638 // Stage 1 - Get number in narrow char
1639 char __fmt[8] = {'%', 0};
1640 const char* __len = "ll";
1641 this->__format_int(__fmt+1, __len, true, __iob.flags());
1642 const unsigned __nbuf = (numeric_limits<long long>::digits / 3)
1643 + ((numeric_limits<long long>::digits % 3) != 0)
1644 + 1;
1645 char __nar[__nbuf];
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001646#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant1ab52da2011-09-28 21:05:01 +00001647 int __nc = sprintf_l(__nar, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001648#else
1649 int __nc = __sprintf_l(__nar, __cloc(), __fmt, __v);
1650#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001651 char* __ne = __nar + __nc;
1652 char* __np = this->__identify_padding(__nar, __ne, __iob);
1653 // Stage 2 - Widen __nar while adding thousands separators
1654 char_type __o[2*(__nbuf-1) - 1];
1655 char_type* __op; // pad here
1656 char_type* __oe; // end of output
1657 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1658 // [__o, __oe) contains thousands_sep'd wide number
1659 // Stage 3 & 4
1660 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1661}
1662
1663template <class _CharT, class _OutputIterator>
1664_OutputIterator
1665num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1666 char_type __fl, unsigned long __v) const
1667{
1668 // Stage 1 - Get number in narrow char
1669 char __fmt[6] = {'%', 0};
1670 const char* __len = "l";
1671 this->__format_int(__fmt+1, __len, false, __iob.flags());
1672 const unsigned __nbuf = (numeric_limits<unsigned long>::digits / 3)
1673 + ((numeric_limits<unsigned long>::digits % 3) != 0)
1674 + 1;
1675 char __nar[__nbuf];
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001676#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant1ab52da2011-09-28 21:05:01 +00001677 int __nc = sprintf_l(__nar, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001678#else
1679 int __nc = __sprintf_l(__nar, __cloc(), __fmt, __v);
1680#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001681 char* __ne = __nar + __nc;
1682 char* __np = this->__identify_padding(__nar, __ne, __iob);
1683 // Stage 2 - Widen __nar while adding thousands separators
1684 char_type __o[2*(__nbuf-1) - 1];
1685 char_type* __op; // pad here
1686 char_type* __oe; // end of output
1687 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1688 // [__o, __oe) contains thousands_sep'd wide number
1689 // Stage 3 & 4
1690 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1691}
1692
1693template <class _CharT, class _OutputIterator>
1694_OutputIterator
1695num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1696 char_type __fl, unsigned long long __v) const
1697{
1698 // Stage 1 - Get number in narrow char
1699 char __fmt[8] = {'%', 0};
1700 const char* __len = "ll";
1701 this->__format_int(__fmt+1, __len, false, __iob.flags());
1702 const unsigned __nbuf = (numeric_limits<unsigned long long>::digits / 3)
1703 + ((numeric_limits<unsigned long long>::digits % 3) != 0)
1704 + 1;
1705 char __nar[__nbuf];
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001706#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant1ab52da2011-09-28 21:05:01 +00001707 int __nc = sprintf_l(__nar, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001708#else
1709 int __nc = __sprintf_l(__nar, __cloc(), __fmt, __v);
1710#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001711 char* __ne = __nar + __nc;
1712 char* __np = this->__identify_padding(__nar, __ne, __iob);
1713 // Stage 2 - Widen __nar while adding thousands separators
1714 char_type __o[2*(__nbuf-1) - 1];
1715 char_type* __op; // pad here
1716 char_type* __oe; // end of output
1717 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1718 // [__o, __oe) contains thousands_sep'd wide number
1719 // Stage 3 & 4
1720 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1721}
1722
1723template <class _CharT, class _OutputIterator>
1724_OutputIterator
1725num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1726 char_type __fl, double __v) const
1727{
1728 // Stage 1 - Get number in narrow char
1729 char __fmt[8] = {'%', 0};
1730 const char* __len = "";
1731 bool __specify_precision = this->__format_float(__fmt+1, __len, __iob.flags());
1732 const unsigned __nbuf = 30;
1733 char __nar[__nbuf];
1734 char* __nb = __nar;
1735 int __nc;
1736 if (__specify_precision)
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001737#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant1ab52da2011-09-28 21:05:01 +00001738 __nc = snprintf_l(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt,
Howard Hinnant155c2af2010-05-24 17:49:41 +00001739 (int)__iob.precision(), __v);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001740#else
1741 __nc = __snprintf_l(__nb, __nbuf, __cloc(), __fmt,
1742 (int)__iob.precision(), __v);
1743#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001744 else
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001745#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant1ab52da2011-09-28 21:05:01 +00001746 __nc = snprintf_l(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001747#else
1748 __nc = __snprintf_l(__nb, __nbuf, __cloc(), __fmt, __v);
1749#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001750 unique_ptr<char, void(*)(void*)> __nbh(0, free);
1751 if (__nc > static_cast<int>(__nbuf-1))
1752 {
1753 if (__specify_precision)
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001754#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant1ab52da2011-09-28 21:05:01 +00001755 __nc = asprintf_l(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, (int)__iob.precision(), __v);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001756#else
1757 __nc = __asprintf_l(&__nb, __cloc(), __fmt,
David Chisnall1d581062011-09-21 08:39:44 +00001758 (int)__iob.precision(), __v);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001759#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001760 else
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001761#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant1ab52da2011-09-28 21:05:01 +00001762 __nc = asprintf_l(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001763#else
David Chisnall1d581062011-09-21 08:39:44 +00001764 __nc = __asprintf_l(&__nb, __cloc(), __fmt, (int)__iob.precision(), __v);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001765#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001766 if (__nb == 0)
1767 __throw_bad_alloc();
1768 __nbh.reset(__nb);
1769 }
1770 char* __ne = __nb + __nc;
1771 char* __np = this->__identify_padding(__nb, __ne, __iob);
1772 // Stage 2 - Widen __nar while adding thousands separators
1773 char_type __o[2*(__nbuf-1) - 1];
1774 char_type* __ob = __o;
1775 unique_ptr<char_type, void(*)(void*)> __obh(0, free);
1776 if (__nb != __nar)
1777 {
Howard Hinnant28b24882011-12-01 20:21:04 +00001778 __ob = (char_type*)malloc(2*static_cast<size_t>(__nc)*sizeof(char_type));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001779 if (__ob == 0)
1780 __throw_bad_alloc();
1781 __obh.reset(__ob);
1782 }
1783 char_type* __op; // pad here
1784 char_type* __oe; // end of output
1785 this->__widen_and_group_float(__nb, __np, __ne, __ob, __op, __oe, __iob.getloc());
1786 // [__o, __oe) contains thousands_sep'd wide number
1787 // Stage 3 & 4
1788 __s = __pad_and_output(__s, __ob, __op, __oe, __iob, __fl);
1789 return __s;
1790}
1791
1792template <class _CharT, class _OutputIterator>
1793_OutputIterator
1794num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1795 char_type __fl, long double __v) const
1796{
1797 // Stage 1 - Get number in narrow char
1798 char __fmt[8] = {'%', 0};
1799 const char* __len = "L";
1800 bool __specify_precision = this->__format_float(__fmt+1, __len, __iob.flags());
1801 const unsigned __nbuf = 30;
1802 char __nar[__nbuf];
1803 char* __nb = __nar;
1804 int __nc;
1805 if (__specify_precision)
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001806#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant1ab52da2011-09-28 21:05:01 +00001807 __nc = snprintf_l(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt,
Howard Hinnant155c2af2010-05-24 17:49:41 +00001808 (int)__iob.precision(), __v);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001809#else
1810 __nc = __snprintf_l(__nb, __nbuf, __cloc(), __fmt,
1811 (int)__iob.precision(), __v);
1812#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001813 else
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001814#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant1ab52da2011-09-28 21:05:01 +00001815 __nc = snprintf_l(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001816#else
1817 __nc = __snprintf_l(__nb, __nbuf, __cloc(), __fmt, __v);
1818#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001819 unique_ptr<char, void(*)(void*)> __nbh(0, free);
1820 if (__nc > static_cast<int>(__nbuf-1))
1821 {
1822 if (__specify_precision)
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001823#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant1ab52da2011-09-28 21:05:01 +00001824 __nc = asprintf_l(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, (int)__iob.precision(), __v);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001825#else
1826 __nc = __asprintf_l(&__nb, __cloc(), __fmt,
David Chisnall1d581062011-09-21 08:39:44 +00001827 (int)__iob.precision(), __v);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001828#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001829 else
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001830#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant1ab52da2011-09-28 21:05:01 +00001831 __nc = asprintf_l(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001832#else
David Chisnall1d581062011-09-21 08:39:44 +00001833 __nc = __asprintf_l(&__nb, __cloc(), __fmt, __v);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001834#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001835 if (__nb == 0)
1836 __throw_bad_alloc();
1837 __nbh.reset(__nb);
1838 }
1839 char* __ne = __nb + __nc;
1840 char* __np = this->__identify_padding(__nb, __ne, __iob);
1841 // Stage 2 - Widen __nar while adding thousands separators
1842 char_type __o[2*(__nbuf-1) - 1];
1843 char_type* __ob = __o;
1844 unique_ptr<char_type, void(*)(void*)> __obh(0, free);
1845 if (__nb != __nar)
1846 {
Howard Hinnant28b24882011-12-01 20:21:04 +00001847 __ob = (char_type*)malloc(2*static_cast<size_t>(__nc)*sizeof(char_type));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001848 if (__ob == 0)
1849 __throw_bad_alloc();
1850 __obh.reset(__ob);
1851 }
1852 char_type* __op; // pad here
1853 char_type* __oe; // end of output
1854 this->__widen_and_group_float(__nb, __np, __ne, __ob, __op, __oe, __iob.getloc());
1855 // [__o, __oe) contains thousands_sep'd wide number
1856 // Stage 3 & 4
1857 __s = __pad_and_output(__s, __ob, __op, __oe, __iob, __fl);
1858 return __s;
1859}
1860
1861template <class _CharT, class _OutputIterator>
1862_OutputIterator
1863num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1864 char_type __fl, const void* __v) const
1865{
1866 // Stage 1 - Get pointer in narrow char
1867 char __fmt[6] = "%p";
1868 const unsigned __nbuf = 20;
1869 char __nar[__nbuf];
Howard Hinnantf312e3e2011-09-28 23:39:33 +00001870#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant1ab52da2011-09-28 21:05:01 +00001871 int __nc = sprintf_l(__nar, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00001872#else
1873 int __nc = __sprintf_l(__nar, __cloc(), __fmt, __v);
1874#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001875 char* __ne = __nar + __nc;
1876 char* __np = this->__identify_padding(__nar, __ne, __iob);
1877 // Stage 2 - Widen __nar
1878 char_type __o[2*(__nbuf-1) - 1];
1879 char_type* __op; // pad here
1880 char_type* __oe; // end of output
1881 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
1882 __ct.widen(__nar, __ne, __o);
1883 __oe = __o + (__ne - __nar);
1884 if (__np == __ne)
1885 __op = __oe;
1886 else
1887 __op = __o + (__np - __nar);
1888 // [__o, __oe) contains wide number
1889 // Stage 3 & 4
1890 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1891}
1892
1893extern template class num_put<char>;
1894extern template class num_put<wchar_t>;
1895
1896template <class _CharT, class _InputIterator>
1897_LIBCPP_HIDDEN
1898int
1899__get_up_to_n_digits(_InputIterator& __b, _InputIterator __e,
1900 ios_base::iostate& __err, const ctype<_CharT>& __ct, int __n)
1901{
1902 // Precondition: __n >= 1
1903 if (__b == __e)
1904 {
1905 __err |= ios_base::eofbit | ios_base::failbit;
1906 return 0;
1907 }
1908 // get first digit
1909 _CharT __c = *__b;
1910 if (!__ct.is(ctype_base::digit, __c))
1911 {
1912 __err |= ios_base::failbit;
1913 return 0;
1914 }
1915 int __r = __ct.narrow(__c, 0) - '0';
1916 for (++__b, --__n; __b != __e && __n > 0; ++__b, --__n)
1917 {
1918 // get next digit
1919 __c = *__b;
1920 if (!__ct.is(ctype_base::digit, __c))
1921 return __r;
1922 __r = __r * 10 + __ct.narrow(__c, 0) - '0';
1923 }
1924 if (__b == __e)
1925 __err |= ios_base::eofbit;
1926 return __r;
1927}
1928
Howard Hinnant756c69b2010-09-22 16:48:34 +00001929class _LIBCPP_VISIBLE time_base
Howard Hinnantc51e1022010-05-11 19:42:16 +00001930{
1931public:
1932 enum dateorder {no_order, dmy, mdy, ymd, ydm};
1933};
1934
1935template <class _CharT>
Howard Hinnantcf823322010-12-17 14:46:43 +00001936class __time_get_c_storage // purposefully not decorated
Howard Hinnantc51e1022010-05-11 19:42:16 +00001937{
1938protected:
1939 typedef basic_string<_CharT> string_type;
1940
1941 virtual const string_type* __weeks() const;
1942 virtual const string_type* __months() const;
1943 virtual const string_type* __am_pm() const;
1944 virtual const string_type& __c() const;
1945 virtual const string_type& __r() const;
1946 virtual const string_type& __x() const;
1947 virtual const string_type& __X() const;
1948};
1949
1950template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnant756c69b2010-09-22 16:48:34 +00001951class _LIBCPP_VISIBLE time_get
Howard Hinnantc51e1022010-05-11 19:42:16 +00001952 : public locale::facet,
1953 public time_base,
1954 private __time_get_c_storage<_CharT>
1955{
1956public:
1957 typedef _CharT char_type;
1958 typedef _InputIterator iter_type;
1959 typedef time_base::dateorder dateorder;
1960 typedef basic_string<char_type> string_type;
1961
1962 _LIBCPP_ALWAYS_INLINE
1963 explicit time_get(size_t __refs = 0)
1964 : locale::facet(__refs) {}
1965
1966 _LIBCPP_ALWAYS_INLINE
1967 dateorder date_order() const
1968 {
1969 return this->do_date_order();
1970 }
1971
1972 _LIBCPP_ALWAYS_INLINE
1973 iter_type get_time(iter_type __b, iter_type __e, ios_base& __iob,
1974 ios_base::iostate& __err, tm* __tm) const
1975 {
1976 return do_get_time(__b, __e, __iob, __err, __tm);
1977 }
1978
1979 _LIBCPP_ALWAYS_INLINE
1980 iter_type get_date(iter_type __b, iter_type __e, ios_base& __iob,
1981 ios_base::iostate& __err, tm* __tm) const
1982 {
1983 return do_get_date(__b, __e, __iob, __err, __tm);
1984 }
1985
1986 _LIBCPP_ALWAYS_INLINE
1987 iter_type get_weekday(iter_type __b, iter_type __e, ios_base& __iob,
1988 ios_base::iostate& __err, tm* __tm) const
1989 {
1990 return do_get_weekday(__b, __e, __iob, __err, __tm);
1991 }
1992
1993 _LIBCPP_ALWAYS_INLINE
1994 iter_type get_monthname(iter_type __b, iter_type __e, ios_base& __iob,
1995 ios_base::iostate& __err, tm* __tm) const
1996 {
1997 return do_get_monthname(__b, __e, __iob, __err, __tm);
1998 }
1999
2000 _LIBCPP_ALWAYS_INLINE
2001 iter_type get_year(iter_type __b, iter_type __e, ios_base& __iob,
2002 ios_base::iostate& __err, tm* __tm) const
2003 {
2004 return do_get_year(__b, __e, __iob, __err, __tm);
2005 }
2006
2007 _LIBCPP_ALWAYS_INLINE
2008 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
2009 ios_base::iostate& __err, tm *__tm,
2010 char __fmt, char __mod = 0) const
2011 {
2012 return do_get(__b, __e, __iob, __err, __tm, __fmt, __mod);
2013 }
2014
2015 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
2016 ios_base::iostate& __err, tm* __tm,
2017 const char_type* __fmtb, const char_type* __fmte) const;
2018
2019 static locale::id id;
2020
2021protected:
Howard Hinnant756c69b2010-09-22 16:48:34 +00002022 _LIBCPP_ALWAYS_INLINE
Howard Hinnantc51e1022010-05-11 19:42:16 +00002023 ~time_get() {}
2024
2025 virtual dateorder do_date_order() const;
2026 virtual iter_type do_get_time(iter_type __b, iter_type __e, ios_base& __iob,
2027 ios_base::iostate& __err, tm* __tm) const;
2028 virtual iter_type do_get_date(iter_type __b, iter_type __e, ios_base& __iob,
2029 ios_base::iostate& __err, tm* __tm) const;
2030 virtual iter_type do_get_weekday(iter_type __b, iter_type __e, ios_base& __iob,
2031 ios_base::iostate& __err, tm* __tm) const;
2032 virtual iter_type do_get_monthname(iter_type __b, iter_type __e, ios_base& __iob,
2033 ios_base::iostate& __err, tm* __tm) const;
2034 virtual iter_type do_get_year(iter_type __b, iter_type __e, ios_base& __iob,
2035 ios_base::iostate& __err, tm* __tm) const;
2036 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
2037 ios_base::iostate& __err, tm* __tm,
2038 char __fmt, char __mod) const;
2039private:
2040 void __get_white_space(iter_type& __b, iter_type __e,
2041 ios_base::iostate& __err, const ctype<char_type>& __ct) const;
2042 void __get_percent(iter_type& __b, iter_type __e, ios_base::iostate& __err,
2043 const ctype<char_type>& __ct) const;
2044
2045 void __get_weekdayname(int& __m,
2046 iter_type& __b, iter_type __e,
2047 ios_base::iostate& __err,
2048 const ctype<char_type>& __ct) const;
2049 void __get_monthname(int& __m,
2050 iter_type& __b, iter_type __e,
2051 ios_base::iostate& __err,
2052 const ctype<char_type>& __ct) const;
2053 void __get_day(int& __d,
2054 iter_type& __b, iter_type __e,
2055 ios_base::iostate& __err,
2056 const ctype<char_type>& __ct) const;
2057 void __get_month(int& __m,
2058 iter_type& __b, iter_type __e,
2059 ios_base::iostate& __err,
2060 const ctype<char_type>& __ct) const;
2061 void __get_year(int& __y,
2062 iter_type& __b, iter_type __e,
2063 ios_base::iostate& __err,
2064 const ctype<char_type>& __ct) const;
2065 void __get_year4(int& __y,
2066 iter_type& __b, iter_type __e,
2067 ios_base::iostate& __err,
2068 const ctype<char_type>& __ct) const;
2069 void __get_hour(int& __d,
2070 iter_type& __b, iter_type __e,
2071 ios_base::iostate& __err,
2072 const ctype<char_type>& __ct) const;
2073 void __get_12_hour(int& __h,
2074 iter_type& __b, iter_type __e,
2075 ios_base::iostate& __err,
2076 const ctype<char_type>& __ct) const;
2077 void __get_am_pm(int& __h,
2078 iter_type& __b, iter_type __e,
2079 ios_base::iostate& __err,
2080 const ctype<char_type>& __ct) const;
2081 void __get_minute(int& __m,
2082 iter_type& __b, iter_type __e,
2083 ios_base::iostate& __err,
2084 const ctype<char_type>& __ct) const;
2085 void __get_second(int& __s,
2086 iter_type& __b, iter_type __e,
2087 ios_base::iostate& __err,
2088 const ctype<char_type>& __ct) const;
2089 void __get_weekday(int& __w,
2090 iter_type& __b, iter_type __e,
2091 ios_base::iostate& __err,
2092 const ctype<char_type>& __ct) const;
2093 void __get_day_year_num(int& __w,
2094 iter_type& __b, iter_type __e,
2095 ios_base::iostate& __err,
2096 const ctype<char_type>& __ct) const;
2097};
2098
2099template <class _CharT, class _InputIterator>
2100locale::id
2101time_get<_CharT, _InputIterator>::id;
2102
2103// time_get primatives
2104
2105template <class _CharT, class _InputIterator>
2106void
2107time_get<_CharT, _InputIterator>::__get_weekdayname(int& __w,
2108 iter_type& __b, iter_type __e,
2109 ios_base::iostate& __err,
2110 const ctype<char_type>& __ct) const
2111{
2112 // Note: ignoring case comes from the POSIX strptime spec
2113 const string_type* __wk = this->__weeks();
Howard Hinnant28b24882011-12-01 20:21:04 +00002114 ptrdiff_t __i = __scan_keyword(__b, __e, __wk, __wk+14, __ct, __err, false) - __wk;
Howard Hinnantc51e1022010-05-11 19:42:16 +00002115 if (__i < 14)
2116 __w = __i % 7;
2117}
2118
2119template <class _CharT, class _InputIterator>
2120void
2121time_get<_CharT, _InputIterator>::__get_monthname(int& __m,
2122 iter_type& __b, iter_type __e,
2123 ios_base::iostate& __err,
2124 const ctype<char_type>& __ct) const
2125{
2126 // Note: ignoring case comes from the POSIX strptime spec
2127 const string_type* __month = this->__months();
Howard Hinnant28b24882011-12-01 20:21:04 +00002128 ptrdiff_t __i = __scan_keyword(__b, __e, __month, __month+24, __ct, __err, false) - __month;
Howard Hinnantc51e1022010-05-11 19:42:16 +00002129 if (__i < 24)
2130 __m = __i % 12;
2131}
2132
2133template <class _CharT, class _InputIterator>
2134void
2135time_get<_CharT, _InputIterator>::__get_day(int& __d,
2136 iter_type& __b, iter_type __e,
2137 ios_base::iostate& __err,
2138 const ctype<char_type>& __ct) const
2139{
2140 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2141 if (!(__err & ios_base::failbit) && 1 <= __t && __t <= 31)
2142 __d = __t;
2143 else
2144 __err |= ios_base::failbit;
2145}
2146
2147template <class _CharT, class _InputIterator>
2148void
2149time_get<_CharT, _InputIterator>::__get_month(int& __m,
2150 iter_type& __b, iter_type __e,
2151 ios_base::iostate& __err,
2152 const ctype<char_type>& __ct) const
2153{
2154 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2) - 1;
2155 if (!(__err & ios_base::failbit) && __t <= 11)
2156 __m = __t;
2157 else
2158 __err |= ios_base::failbit;
2159}
2160
2161template <class _CharT, class _InputIterator>
2162void
2163time_get<_CharT, _InputIterator>::__get_year(int& __y,
2164 iter_type& __b, iter_type __e,
2165 ios_base::iostate& __err,
2166 const ctype<char_type>& __ct) const
2167{
2168 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 4);
2169 if (!(__err & ios_base::failbit))
2170 {
2171 if (__t < 69)
2172 __t += 2000;
2173 else if (69 <= __t && __t <= 99)
2174 __t += 1900;
2175 __y = __t - 1900;
2176 }
2177}
2178
2179template <class _CharT, class _InputIterator>
2180void
2181time_get<_CharT, _InputIterator>::__get_year4(int& __y,
2182 iter_type& __b, iter_type __e,
2183 ios_base::iostate& __err,
2184 const ctype<char_type>& __ct) const
2185{
2186 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 4);
2187 if (!(__err & ios_base::failbit))
2188 __y = __t - 1900;
2189}
2190
2191template <class _CharT, class _InputIterator>
2192void
2193time_get<_CharT, _InputIterator>::__get_hour(int& __h,
2194 iter_type& __b, iter_type __e,
2195 ios_base::iostate& __err,
2196 const ctype<char_type>& __ct) const
2197{
2198 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2199 if (!(__err & ios_base::failbit) && __t <= 23)
2200 __h = __t;
2201 else
2202 __err |= ios_base::failbit;
2203}
2204
2205template <class _CharT, class _InputIterator>
2206void
2207time_get<_CharT, _InputIterator>::__get_12_hour(int& __h,
2208 iter_type& __b, iter_type __e,
2209 ios_base::iostate& __err,
2210 const ctype<char_type>& __ct) const
2211{
2212 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2213 if (!(__err & ios_base::failbit) && 1 <= __t && __t <= 12)
2214 __h = __t;
2215 else
2216 __err |= ios_base::failbit;
2217}
2218
2219template <class _CharT, class _InputIterator>
2220void
2221time_get<_CharT, _InputIterator>::__get_minute(int& __m,
2222 iter_type& __b, iter_type __e,
2223 ios_base::iostate& __err,
2224 const ctype<char_type>& __ct) const
2225{
2226 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2227 if (!(__err & ios_base::failbit) && __t <= 59)
2228 __m = __t;
2229 else
2230 __err |= ios_base::failbit;
2231}
2232
2233template <class _CharT, class _InputIterator>
2234void
2235time_get<_CharT, _InputIterator>::__get_second(int& __s,
2236 iter_type& __b, iter_type __e,
2237 ios_base::iostate& __err,
2238 const ctype<char_type>& __ct) const
2239{
2240 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2241 if (!(__err & ios_base::failbit) && __t <= 60)
2242 __s = __t;
2243 else
2244 __err |= ios_base::failbit;
2245}
2246
2247template <class _CharT, class _InputIterator>
2248void
2249time_get<_CharT, _InputIterator>::__get_weekday(int& __w,
2250 iter_type& __b, iter_type __e,
2251 ios_base::iostate& __err,
2252 const ctype<char_type>& __ct) const
2253{
2254 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 1);
2255 if (!(__err & ios_base::failbit) && __t <= 6)
2256 __w = __t;
2257 else
2258 __err |= ios_base::failbit;
2259}
2260
2261template <class _CharT, class _InputIterator>
2262void
2263time_get<_CharT, _InputIterator>::__get_day_year_num(int& __d,
2264 iter_type& __b, iter_type __e,
2265 ios_base::iostate& __err,
2266 const ctype<char_type>& __ct) const
2267{
2268 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 3);
2269 if (!(__err & ios_base::failbit) && __t <= 365)
2270 __d = __t;
2271 else
2272 __err |= ios_base::failbit;
2273}
2274
2275template <class _CharT, class _InputIterator>
2276void
2277time_get<_CharT, _InputIterator>::__get_white_space(iter_type& __b, iter_type __e,
2278 ios_base::iostate& __err,
2279 const ctype<char_type>& __ct) const
2280{
2281 for (; __b != __e && __ct.is(ctype_base::space, *__b); ++__b)
2282 ;
2283 if (__b == __e)
2284 __err |= ios_base::eofbit;
2285}
2286
2287template <class _CharT, class _InputIterator>
2288void
2289time_get<_CharT, _InputIterator>::__get_am_pm(int& __h,
2290 iter_type& __b, iter_type __e,
2291 ios_base::iostate& __err,
2292 const ctype<char_type>& __ct) const
2293{
2294 const string_type* __ap = this->__am_pm();
2295 if (__ap[0].size() + __ap[1].size() == 0)
2296 {
2297 __err |= ios_base::failbit;
2298 return;
2299 }
Howard Hinnant28b24882011-12-01 20:21:04 +00002300 ptrdiff_t __i = __scan_keyword(__b, __e, __ap, __ap+2, __ct, __err, false) - __ap;
Howard Hinnantc51e1022010-05-11 19:42:16 +00002301 if (__i == 0 && __h == 12)
2302 __h = 0;
2303 else if (__i == 1 && __h < 12)
2304 __h += 12;
2305}
2306
2307template <class _CharT, class _InputIterator>
2308void
2309time_get<_CharT, _InputIterator>::__get_percent(iter_type& __b, iter_type __e,
2310 ios_base::iostate& __err,
2311 const ctype<char_type>& __ct) const
2312{
2313 if (__b == __e)
2314 {
2315 __err |= ios_base::eofbit | ios_base::failbit;
2316 return;
2317 }
2318 if (__ct.narrow(*__b, 0) != '%')
2319 __err |= ios_base::failbit;
2320 else if(++__b == __e)
2321 __err |= ios_base::eofbit;
2322}
2323
2324// time_get end primatives
2325
2326template <class _CharT, class _InputIterator>
2327_InputIterator
2328time_get<_CharT, _InputIterator>::get(iter_type __b, iter_type __e,
2329 ios_base& __iob,
2330 ios_base::iostate& __err, tm* __tm,
2331 const char_type* __fmtb, const char_type* __fmte) const
2332{
2333 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2334 __err = ios_base::goodbit;
2335 while (__fmtb != __fmte && __err == ios_base::goodbit)
2336 {
2337 if (__b == __e)
2338 {
2339 __err = ios_base::failbit;
2340 break;
2341 }
2342 if (__ct.narrow(*__fmtb, 0) == '%')
2343 {
2344 if (++__fmtb == __fmte)
2345 {
2346 __err = ios_base::failbit;
2347 break;
2348 }
2349 char __cmd = __ct.narrow(*__fmtb, 0);
2350 char __opt = '\0';
2351 if (__cmd == 'E' || __cmd == '0')
2352 {
2353 if (++__fmtb == __fmte)
2354 {
2355 __err = ios_base::failbit;
2356 break;
2357 }
2358 __opt = __cmd;
2359 __cmd = __ct.narrow(*__fmtb, 0);
2360 }
2361 __b = do_get(__b, __e, __iob, __err, __tm, __cmd, __opt);
2362 ++__fmtb;
2363 }
2364 else if (__ct.is(ctype_base::space, *__fmtb))
2365 {
2366 for (++__fmtb; __fmtb != __fmte && __ct.is(ctype_base::space, *__fmtb); ++__fmtb)
2367 ;
2368 for ( ; __b != __e && __ct.is(ctype_base::space, *__b); ++__b)
2369 ;
2370 }
2371 else if (__ct.toupper(*__b) == __ct.toupper(*__fmtb))
2372 {
2373 ++__b;
2374 ++__fmtb;
2375 }
2376 else
2377 __err = ios_base::failbit;
2378 }
2379 if (__b == __e)
2380 __err |= ios_base::eofbit;
2381 return __b;
2382}
2383
2384template <class _CharT, class _InputIterator>
2385typename time_get<_CharT, _InputIterator>::dateorder
2386time_get<_CharT, _InputIterator>::do_date_order() const
2387{
2388 return mdy;
2389}
2390
2391template <class _CharT, class _InputIterator>
2392_InputIterator
2393time_get<_CharT, _InputIterator>::do_get_time(iter_type __b, iter_type __e,
2394 ios_base& __iob,
2395 ios_base::iostate& __err,
2396 tm* __tm) const
2397{
2398 const char_type __fmt[] = {'%', 'H', ':', '%', 'M', ':', '%', 'S'};
2399 return get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2400}
2401
2402template <class _CharT, class _InputIterator>
2403_InputIterator
2404time_get<_CharT, _InputIterator>::do_get_date(iter_type __b, iter_type __e,
2405 ios_base& __iob,
2406 ios_base::iostate& __err,
2407 tm* __tm) const
2408{
Howard Hinnantc51e1022010-05-11 19:42:16 +00002409 const string_type& __fmt = this->__x();
2410 return get(__b, __e, __iob, __err, __tm, __fmt.data(), __fmt.data() + __fmt.size());
2411}
2412
2413template <class _CharT, class _InputIterator>
2414_InputIterator
2415time_get<_CharT, _InputIterator>::do_get_weekday(iter_type __b, iter_type __e,
2416 ios_base& __iob,
2417 ios_base::iostate& __err,
2418 tm* __tm) const
2419{
2420 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2421 __get_weekdayname(__tm->tm_wday, __b, __e, __err, __ct);
2422 return __b;
2423}
2424
2425template <class _CharT, class _InputIterator>
2426_InputIterator
2427time_get<_CharT, _InputIterator>::do_get_monthname(iter_type __b, iter_type __e,
2428 ios_base& __iob,
2429 ios_base::iostate& __err,
2430 tm* __tm) const
2431{
2432 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2433 __get_monthname(__tm->tm_mon, __b, __e, __err, __ct);
2434 return __b;
2435}
2436
2437template <class _CharT, class _InputIterator>
2438_InputIterator
2439time_get<_CharT, _InputIterator>::do_get_year(iter_type __b, iter_type __e,
2440 ios_base& __iob,
2441 ios_base::iostate& __err,
2442 tm* __tm) const
2443{
2444 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2445 __get_year(__tm->tm_year, __b, __e, __err, __ct);
2446 return __b;
2447}
2448
2449template <class _CharT, class _InputIterator>
2450_InputIterator
2451time_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
2452 ios_base& __iob,
2453 ios_base::iostate& __err, tm* __tm,
2454 char __fmt, char) const
2455{
2456 __err = ios_base::goodbit;
2457 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2458 switch (__fmt)
2459 {
2460 case 'a':
2461 case 'A':
2462 __get_weekdayname(__tm->tm_wday, __b, __e, __err, __ct);
2463 break;
2464 case 'b':
2465 case 'B':
2466 case 'h':
2467 __get_monthname(__tm->tm_mon, __b, __e, __err, __ct);
2468 break;
2469 case 'c':
2470 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002471 const string_type& __fm = this->__c();
2472 __b = get(__b, __e, __iob, __err, __tm, __fm.data(), __fm.data() + __fm.size());
Howard Hinnantc51e1022010-05-11 19:42:16 +00002473 }
2474 break;
2475 case 'd':
2476 case 'e':
2477 __get_day(__tm->tm_mday, __b, __e, __err, __ct);
2478 break;
2479 case 'D':
2480 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002481 const char_type __fm[] = {'%', 'm', '/', '%', 'd', '/', '%', 'y'};
2482 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm)/sizeof(__fm[0]));
Howard Hinnantc51e1022010-05-11 19:42:16 +00002483 }
2484 break;
Howard Hinnantf60ff4e2011-04-10 17:54:14 +00002485 case 'F':
2486 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002487 const char_type __fm[] = {'%', 'Y', '-', '%', 'm', '-', '%', 'd'};
2488 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm)/sizeof(__fm[0]));
Howard Hinnantf60ff4e2011-04-10 17:54:14 +00002489 }
2490 break;
Howard Hinnantc51e1022010-05-11 19:42:16 +00002491 case 'H':
2492 __get_hour(__tm->tm_hour, __b, __e, __err, __ct);
2493 break;
2494 case 'I':
2495 __get_12_hour(__tm->tm_hour, __b, __e, __err, __ct);
2496 break;
2497 case 'j':
2498 __get_day_year_num(__tm->tm_yday, __b, __e, __err, __ct);
2499 break;
2500 case 'm':
2501 __get_month(__tm->tm_mon, __b, __e, __err, __ct);
2502 break;
2503 case 'M':
2504 __get_minute(__tm->tm_min, __b, __e, __err, __ct);
2505 break;
2506 case 'n':
2507 case 't':
2508 __get_white_space(__b, __e, __err, __ct);
2509 break;
2510 case 'p':
2511 __get_am_pm(__tm->tm_hour, __b, __e, __err, __ct);
2512 break;
2513 case 'r':
2514 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002515 const char_type __fm[] = {'%', 'I', ':', '%', 'M', ':', '%', 'S', ' ', '%', 'p'};
2516 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm)/sizeof(__fm[0]));
Howard Hinnantc51e1022010-05-11 19:42:16 +00002517 }
2518 break;
2519 case 'R':
2520 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002521 const char_type __fm[] = {'%', 'H', ':', '%', 'M'};
2522 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm)/sizeof(__fm[0]));
Howard Hinnantc51e1022010-05-11 19:42:16 +00002523 }
2524 break;
2525 case 'S':
2526 __get_second(__tm->tm_sec, __b, __e, __err, __ct);
2527 break;
2528 case 'T':
2529 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002530 const char_type __fm[] = {'%', 'H', ':', '%', 'M', ':', '%', 'S'};
2531 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm)/sizeof(__fm[0]));
Howard Hinnantc51e1022010-05-11 19:42:16 +00002532 }
2533 break;
2534 case 'w':
2535 __get_weekday(__tm->tm_wday, __b, __e, __err, __ct);
2536 break;
2537 case 'x':
2538 return do_get_date(__b, __e, __iob, __err, __tm);
2539 case 'X':
2540 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002541 const string_type& __fm = this->__X();
2542 __b = get(__b, __e, __iob, __err, __tm, __fm.data(), __fm.data() + __fm.size());
Howard Hinnantc51e1022010-05-11 19:42:16 +00002543 }
2544 break;
2545 case 'y':
2546 __get_year(__tm->tm_year, __b, __e, __err, __ct);
2547 break;
2548 case 'Y':
2549 __get_year4(__tm->tm_year, __b, __e, __err, __ct);
2550 break;
2551 case '%':
2552 __get_percent(__b, __e, __err, __ct);
2553 break;
2554 default:
2555 __err |= ios_base::failbit;
2556 }
2557 return __b;
2558}
2559
2560extern template class time_get<char>;
2561extern template class time_get<wchar_t>;
2562
2563class __time_get
2564{
2565protected:
2566 locale_t __loc_;
2567
2568 __time_get(const char* __nm);
2569 __time_get(const string& __nm);
2570 ~__time_get();
2571};
2572
2573template <class _CharT>
2574class __time_get_storage
2575 : public __time_get
2576{
2577protected:
2578 typedef basic_string<_CharT> string_type;
2579
2580 string_type __weeks_[14];
2581 string_type __months_[24];
2582 string_type __am_pm_[2];
2583 string_type __c_;
2584 string_type __r_;
2585 string_type __x_;
2586 string_type __X_;
2587
2588 explicit __time_get_storage(const char* __nm);
2589 explicit __time_get_storage(const string& __nm);
2590
2591 _LIBCPP_ALWAYS_INLINE ~__time_get_storage() {}
2592
2593 time_base::dateorder __do_date_order() const;
2594
2595private:
2596 void init(const ctype<_CharT>&);
2597 string_type __analyze(char __fmt, const ctype<_CharT>&);
2598};
2599
2600template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnant756c69b2010-09-22 16:48:34 +00002601class _LIBCPP_VISIBLE time_get_byname
Howard Hinnantc51e1022010-05-11 19:42:16 +00002602 : public time_get<_CharT, _InputIterator>,
2603 private __time_get_storage<_CharT>
2604{
2605public:
2606 typedef time_base::dateorder dateorder;
2607 typedef _InputIterator iter_type;
2608 typedef _CharT char_type;
2609 typedef basic_string<char_type> string_type;
2610
Howard Hinnant756c69b2010-09-22 16:48:34 +00002611 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002612 explicit time_get_byname(const char* __nm, size_t __refs = 0)
2613 : time_get<_CharT, _InputIterator>(__refs),
2614 __time_get_storage<_CharT>(__nm) {}
Howard Hinnant756c69b2010-09-22 16:48:34 +00002615 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002616 explicit time_get_byname(const string& __nm, size_t __refs = 0)
2617 : time_get<_CharT, _InputIterator>(__refs),
2618 __time_get_storage<_CharT>(__nm) {}
2619
2620protected:
Howard Hinnant756c69b2010-09-22 16:48:34 +00002621 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002622 ~time_get_byname() {}
2623
Howard Hinnant756c69b2010-09-22 16:48:34 +00002624 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002625 virtual dateorder do_date_order() const {return this->__do_date_order();}
2626private:
Howard Hinnant756c69b2010-09-22 16:48:34 +00002627 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002628 virtual const string_type* __weeks() const {return this->__weeks_;}
Howard Hinnant756c69b2010-09-22 16:48:34 +00002629 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002630 virtual const string_type* __months() const {return this->__months_;}
Howard Hinnant756c69b2010-09-22 16:48:34 +00002631 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002632 virtual const string_type* __am_pm() const {return this->__am_pm_;}
Howard Hinnant756c69b2010-09-22 16:48:34 +00002633 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002634 virtual const string_type& __c() const {return this->__c_;}
Howard Hinnant756c69b2010-09-22 16:48:34 +00002635 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002636 virtual const string_type& __r() const {return this->__r_;}
Howard Hinnant756c69b2010-09-22 16:48:34 +00002637 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002638 virtual const string_type& __x() const {return this->__x_;}
Howard Hinnant756c69b2010-09-22 16:48:34 +00002639 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002640 virtual const string_type& __X() const {return this->__X_;}
2641};
2642
2643extern template class time_get_byname<char>;
2644extern template class time_get_byname<wchar_t>;
2645
2646class __time_put
2647{
2648 locale_t __loc_;
2649protected:
Howard Hinnant1ab52da2011-09-28 21:05:01 +00002650 _LIBCPP_ALWAYS_INLINE __time_put() : __loc_(_LIBCPP_GET_C_LOCALE) {}
Howard Hinnantc51e1022010-05-11 19:42:16 +00002651 __time_put(const char* __nm);
2652 __time_put(const string& __nm);
2653 ~__time_put();
2654 void __do_put(char* __nb, char*& __ne, const tm* __tm,
2655 char __fmt, char __mod) const;
2656 void __do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
2657 char __fmt, char __mod) const;
2658};
2659
2660template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant756c69b2010-09-22 16:48:34 +00002661class _LIBCPP_VISIBLE time_put
Howard Hinnantc51e1022010-05-11 19:42:16 +00002662 : public locale::facet,
2663 private __time_put
2664{
2665public:
2666 typedef _CharT char_type;
2667 typedef _OutputIterator iter_type;
2668
2669 _LIBCPP_ALWAYS_INLINE
2670 explicit time_put(size_t __refs = 0)
2671 : locale::facet(__refs) {}
2672
2673 iter_type put(iter_type __s, ios_base& __iob, char_type __fl, const tm* __tm,
2674 const char_type* __pb, const char_type* __pe) const;
2675
2676 _LIBCPP_ALWAYS_INLINE
2677 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
2678 const tm* __tm, char __fmt, char __mod = 0) const
2679 {
2680 return do_put(__s, __iob, __fl, __tm, __fmt, __mod);
2681 }
2682
2683 static locale::id id;
2684
2685protected:
Howard Hinnant756c69b2010-09-22 16:48:34 +00002686 _LIBCPP_ALWAYS_INLINE
Howard Hinnantc51e1022010-05-11 19:42:16 +00002687 ~time_put() {}
2688 virtual iter_type do_put(iter_type __s, ios_base&, char_type, const tm* __tm,
2689 char __fmt, char __mod) const;
2690
Howard Hinnant756c69b2010-09-22 16:48:34 +00002691 _LIBCPP_ALWAYS_INLINE
Howard Hinnantc51e1022010-05-11 19:42:16 +00002692 explicit time_put(const char* __nm, size_t __refs)
2693 : locale::facet(__refs),
2694 __time_put(__nm) {}
Howard Hinnant756c69b2010-09-22 16:48:34 +00002695 _LIBCPP_ALWAYS_INLINE
Howard Hinnantc51e1022010-05-11 19:42:16 +00002696 explicit time_put(const string& __nm, size_t __refs)
2697 : locale::facet(__refs),
2698 __time_put(__nm) {}
2699};
2700
2701template <class _CharT, class _OutputIterator>
2702locale::id
2703time_put<_CharT, _OutputIterator>::id;
2704
2705template <class _CharT, class _OutputIterator>
2706_OutputIterator
2707time_put<_CharT, _OutputIterator>::put(iter_type __s, ios_base& __iob,
2708 char_type __fl, const tm* __tm,
2709 const char_type* __pb,
2710 const char_type* __pe) const
2711{
2712 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2713 for (; __pb != __pe; ++__pb)
2714 {
2715 if (__ct.narrow(*__pb, 0) == '%')
2716 {
2717 if (++__pb == __pe)
2718 {
2719 *__s++ = __pb[-1];
2720 break;
2721 }
2722 char __mod = 0;
2723 char __fmt = __ct.narrow(*__pb, 0);
2724 if (__fmt == 'E' || __fmt == 'O')
2725 {
2726 if (++__pb == __pe)
2727 {
2728 *__s++ = __pb[-2];
2729 *__s++ = __pb[-1];
2730 break;
2731 }
2732 __mod = __fmt;
2733 __fmt = __ct.narrow(*__pb, 0);
2734 }
2735 __s = do_put(__s, __iob, __fl, __tm, __fmt, __mod);
2736 }
2737 else
2738 *__s++ = *__pb;
2739 }
2740 return __s;
2741}
2742
2743template <class _CharT, class _OutputIterator>
2744_OutputIterator
Howard Hinnant28b24882011-12-01 20:21:04 +00002745time_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00002746 char_type, const tm* __tm,
2747 char __fmt, char __mod) const
2748{
2749 char_type __nar[100];
2750 char_type* __nb = __nar;
2751 char_type* __ne = __nb + 100;
2752 __do_put(__nb, __ne, __tm, __fmt, __mod);
Howard Hinnantb1ad5a82011-06-30 21:18:19 +00002753 return _VSTD::copy(__nb, __ne, __s);
Howard Hinnantc51e1022010-05-11 19:42:16 +00002754}
2755
2756extern template class time_put<char>;
2757extern template class time_put<wchar_t>;
2758
2759template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant756c69b2010-09-22 16:48:34 +00002760class _LIBCPP_VISIBLE time_put_byname
Howard Hinnantc51e1022010-05-11 19:42:16 +00002761 : public time_put<_CharT, _OutputIterator>
2762{
2763public:
2764 _LIBCPP_ALWAYS_INLINE
2765 explicit time_put_byname(const char* __nm, size_t __refs = 0)
2766 : time_put<_CharT, _OutputIterator>(__nm, __refs) {}
2767
2768 _LIBCPP_ALWAYS_INLINE
2769 explicit time_put_byname(const string& __nm, size_t __refs = 0)
2770 : time_put<_CharT, _OutputIterator>(__nm, __refs) {}
2771
2772protected:
Howard Hinnant756c69b2010-09-22 16:48:34 +00002773 _LIBCPP_ALWAYS_INLINE
Howard Hinnantc51e1022010-05-11 19:42:16 +00002774 ~time_put_byname() {}
2775};
2776
2777extern template class time_put_byname<char>;
2778extern template class time_put_byname<wchar_t>;
2779
2780// money_base
2781
Howard Hinnant756c69b2010-09-22 16:48:34 +00002782class _LIBCPP_VISIBLE money_base
Howard Hinnantc51e1022010-05-11 19:42:16 +00002783{
2784public:
2785 enum part {none, space, symbol, sign, value};
2786 struct pattern {char field[4];};
2787
2788 _LIBCPP_ALWAYS_INLINE money_base() {}
2789};
2790
2791// moneypunct
2792
2793template <class _CharT, bool _International = false>
Howard Hinnant756c69b2010-09-22 16:48:34 +00002794class _LIBCPP_VISIBLE moneypunct
Howard Hinnantc51e1022010-05-11 19:42:16 +00002795 : public locale::facet,
2796 public money_base
2797{
2798public:
2799 typedef _CharT char_type;
2800 typedef basic_string<char_type> string_type;
2801
Howard Hinnant756c69b2010-09-22 16:48:34 +00002802 _LIBCPP_ALWAYS_INLINE
Howard Hinnantc51e1022010-05-11 19:42:16 +00002803 explicit moneypunct(size_t __refs = 0)
2804 : locale::facet(__refs) {}
2805
2806 _LIBCPP_ALWAYS_INLINE char_type decimal_point() const {return do_decimal_point();}
2807 _LIBCPP_ALWAYS_INLINE char_type thousands_sep() const {return do_thousands_sep();}
2808 _LIBCPP_ALWAYS_INLINE string grouping() const {return do_grouping();}
2809 _LIBCPP_ALWAYS_INLINE string_type curr_symbol() const {return do_curr_symbol();}
2810 _LIBCPP_ALWAYS_INLINE string_type positive_sign() const {return do_positive_sign();}
2811 _LIBCPP_ALWAYS_INLINE string_type negative_sign() const {return do_negative_sign();}
2812 _LIBCPP_ALWAYS_INLINE int frac_digits() const {return do_frac_digits();}
2813 _LIBCPP_ALWAYS_INLINE pattern pos_format() const {return do_pos_format();}
2814 _LIBCPP_ALWAYS_INLINE pattern neg_format() const {return do_neg_format();}
2815
2816 static locale::id id;
2817 static const bool intl = _International;
2818
2819protected:
Howard Hinnant756c69b2010-09-22 16:48:34 +00002820 _LIBCPP_ALWAYS_INLINE
Howard Hinnantc51e1022010-05-11 19:42:16 +00002821 ~moneypunct() {}
2822
2823 virtual char_type do_decimal_point() const {return numeric_limits<char_type>::max();}
2824 virtual char_type do_thousands_sep() const {return numeric_limits<char_type>::max();}
2825 virtual string do_grouping() const {return string();}
2826 virtual string_type do_curr_symbol() const {return string_type();}
2827 virtual string_type do_positive_sign() const {return string_type();}
2828 virtual string_type do_negative_sign() const {return string_type(1, '-');}
2829 virtual int do_frac_digits() const {return 0;}
2830 virtual pattern do_pos_format() const
2831 {pattern __p = {symbol, sign, none, value}; return __p;}
2832 virtual pattern do_neg_format() const
2833 {pattern __p = {symbol, sign, none, value}; return __p;}
2834};
2835
2836template <class _CharT, bool _International>
2837locale::id
2838moneypunct<_CharT, _International>::id;
2839
2840extern template class moneypunct<char, false>;
2841extern template class moneypunct<char, true>;
2842extern template class moneypunct<wchar_t, false>;
2843extern template class moneypunct<wchar_t, true>;
2844
2845// moneypunct_byname
2846
2847template <class _CharT, bool _International = false>
Howard Hinnant756c69b2010-09-22 16:48:34 +00002848class _LIBCPP_VISIBLE moneypunct_byname
2849 : public moneypunct<_CharT, _International>
Howard Hinnantc51e1022010-05-11 19:42:16 +00002850{
2851public:
2852 typedef money_base::pattern pattern;
2853 typedef _CharT char_type;
2854 typedef basic_string<char_type> string_type;
2855
2856 _LIBCPP_ALWAYS_INLINE
2857 explicit moneypunct_byname(const char* __nm, size_t __refs = 0)
2858 : moneypunct<_CharT, _International>(__refs) {init(__nm);}
2859
2860 _LIBCPP_ALWAYS_INLINE
2861 explicit moneypunct_byname(const string& __nm, size_t __refs = 0)
2862 : moneypunct<_CharT, _International>(__refs) {init(__nm.c_str());}
2863
2864protected:
Howard Hinnant756c69b2010-09-22 16:48:34 +00002865 _LIBCPP_ALWAYS_INLINE
Howard Hinnantc51e1022010-05-11 19:42:16 +00002866 ~moneypunct_byname() {}
2867
2868 virtual char_type do_decimal_point() const {return __decimal_point_;}
2869 virtual char_type do_thousands_sep() const {return __thousands_sep_;}
2870 virtual string do_grouping() const {return __grouping_;}
2871 virtual string_type do_curr_symbol() const {return __curr_symbol_;}
2872 virtual string_type do_positive_sign() const {return __positive_sign_;}
2873 virtual string_type do_negative_sign() const {return __negative_sign_;}
2874 virtual int do_frac_digits() const {return __frac_digits_;}
2875 virtual pattern do_pos_format() const {return __pos_format_;}
2876 virtual pattern do_neg_format() const {return __neg_format_;}
2877
2878private:
2879 char_type __decimal_point_;
2880 char_type __thousands_sep_;
2881 string __grouping_;
2882 string_type __curr_symbol_;
2883 string_type __positive_sign_;
2884 string_type __negative_sign_;
2885 int __frac_digits_;
2886 pattern __pos_format_;
2887 pattern __neg_format_;
2888
2889 void init(const char*);
2890};
2891
2892template<> void moneypunct_byname<char, false>::init(const char*);
2893template<> void moneypunct_byname<char, true>::init(const char*);
2894template<> void moneypunct_byname<wchar_t, false>::init(const char*);
2895template<> void moneypunct_byname<wchar_t, true>::init(const char*);
2896
2897extern template class moneypunct_byname<char, false>;
2898extern template class moneypunct_byname<char, true>;
2899extern template class moneypunct_byname<wchar_t, false>;
2900extern template class moneypunct_byname<wchar_t, true>;
2901
2902// money_get
2903
2904template <class _CharT>
2905class __money_get
2906{
2907protected:
2908 typedef _CharT char_type;
2909 typedef basic_string<char_type> string_type;
2910
2911 _LIBCPP_ALWAYS_INLINE __money_get() {}
2912
2913 static void __gather_info(bool __intl, const locale& __loc,
2914 money_base::pattern& __pat, char_type& __dp,
2915 char_type& __ts, string& __grp,
2916 string_type& __sym, string_type& __psn,
2917 string_type& __nsn, int& __fd);
2918};
2919
2920template <class _CharT>
2921void
2922__money_get<_CharT>::__gather_info(bool __intl, const locale& __loc,
2923 money_base::pattern& __pat, char_type& __dp,
2924 char_type& __ts, string& __grp,
2925 string_type& __sym, string_type& __psn,
2926 string_type& __nsn, int& __fd)
2927{
2928 if (__intl)
2929 {
2930 const moneypunct<char_type, true>& __mp =
2931 use_facet<moneypunct<char_type, true> >(__loc);
2932 __pat = __mp.neg_format();
2933 __nsn = __mp.negative_sign();
2934 __psn = __mp.positive_sign();
2935 __dp = __mp.decimal_point();
2936 __ts = __mp.thousands_sep();
2937 __grp = __mp.grouping();
2938 __sym = __mp.curr_symbol();
2939 __fd = __mp.frac_digits();
2940 }
2941 else
2942 {
2943 const moneypunct<char_type, false>& __mp =
2944 use_facet<moneypunct<char_type, false> >(__loc);
2945 __pat = __mp.neg_format();
2946 __nsn = __mp.negative_sign();
2947 __psn = __mp.positive_sign();
2948 __dp = __mp.decimal_point();
2949 __ts = __mp.thousands_sep();
2950 __grp = __mp.grouping();
2951 __sym = __mp.curr_symbol();
2952 __fd = __mp.frac_digits();
2953 }
2954}
2955
2956extern template class __money_get<char>;
2957extern template class __money_get<wchar_t>;
2958
2959template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnant756c69b2010-09-22 16:48:34 +00002960class _LIBCPP_VISIBLE money_get
Howard Hinnantc51e1022010-05-11 19:42:16 +00002961 : public locale::facet,
2962 private __money_get<_CharT>
2963{
2964public:
2965 typedef _CharT char_type;
2966 typedef _InputIterator iter_type;
2967 typedef basic_string<char_type> string_type;
2968
2969 _LIBCPP_ALWAYS_INLINE
2970 explicit money_get(size_t __refs = 0)
2971 : locale::facet(__refs) {}
2972
2973 _LIBCPP_ALWAYS_INLINE
2974 iter_type get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob,
2975 ios_base::iostate& __err, long double& __v) const
2976 {
2977 return do_get(__b, __e, __intl, __iob, __err, __v);
2978 }
2979
2980 _LIBCPP_ALWAYS_INLINE
2981 iter_type get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob,
2982 ios_base::iostate& __err, string_type& __v) const
2983 {
2984 return do_get(__b, __e, __intl, __iob, __err, __v);
2985 }
2986
2987 static locale::id id;
2988
2989protected:
2990
Howard Hinnant756c69b2010-09-22 16:48:34 +00002991 _LIBCPP_ALWAYS_INLINE
Howard Hinnantc51e1022010-05-11 19:42:16 +00002992 ~money_get() {}
Howard Hinnant3b6579a2010-08-22 00:02:43 +00002993
Howard Hinnantc51e1022010-05-11 19:42:16 +00002994 virtual iter_type do_get(iter_type __b, iter_type __e, bool __intl,
2995 ios_base& __iob, ios_base::iostate& __err,
2996 long double& __v) const;
2997 virtual iter_type do_get(iter_type __b, iter_type __e, bool __intl,
2998 ios_base& __iob, ios_base::iostate& __err,
2999 string_type& __v) const;
3000
3001private:
3002 static bool __do_get(iter_type& __b, iter_type __e,
3003 bool __intl, const locale& __loc,
3004 ios_base::fmtflags __flags, ios_base::iostate& __err,
3005 bool& __neg, const ctype<char_type>& __ct,
3006 unique_ptr<char_type, void(*)(void*)>& __wb,
3007 char_type*& __wn, char_type* __we);
3008};
3009
3010template <class _CharT, class _InputIterator>
3011locale::id
3012money_get<_CharT, _InputIterator>::id;
3013
3014void __do_nothing(void*);
3015
3016template <class _Tp>
3017_LIBCPP_HIDDEN
3018void
3019__double_or_nothing(unique_ptr<_Tp, void(*)(void*)>& __b, _Tp*& __n, _Tp*& __e)
3020{
3021 bool __owns = __b.get_deleter() != __do_nothing;
Howard Hinnant28b24882011-12-01 20:21:04 +00003022 size_t __cur_cap = static_cast<size_t>(__e-__b.get()) * sizeof(_Tp);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003023 size_t __new_cap = __cur_cap < numeric_limits<size_t>::max() / 2 ?
3024 2 * __cur_cap : numeric_limits<size_t>::max();
Howard Hinnant28b24882011-12-01 20:21:04 +00003025 size_t __n_off = static_cast<size_t>(__n - __b.get());
Howard Hinnantc51e1022010-05-11 19:42:16 +00003026 _Tp* __t = (_Tp*)realloc(__owns ? __b.get() : 0, __new_cap);
3027 if (__t == 0)
3028 __throw_bad_alloc();
3029 if (__owns)
3030 __b.release();
3031 __b = unique_ptr<_Tp, void(*)(void*)>(__t, free);
3032 __new_cap /= sizeof(_Tp);
3033 __n = __b.get() + __n_off;
3034 __e = __b.get() + __new_cap;
3035}
3036
3037// true == success
3038template <class _CharT, class _InputIterator>
3039bool
3040money_get<_CharT, _InputIterator>::__do_get(iter_type& __b, iter_type __e,
3041 bool __intl, const locale& __loc,
3042 ios_base::fmtflags __flags,
3043 ios_base::iostate& __err,
3044 bool& __neg,
3045 const ctype<char_type>& __ct,
3046 unique_ptr<char_type, void(*)(void*)>& __wb,
3047 char_type*& __wn, char_type* __we)
3048{
3049 const unsigned __bz = 100;
3050 unsigned __gbuf[__bz];
3051 unique_ptr<unsigned, void(*)(void*)> __gb(__gbuf, __do_nothing);
3052 unsigned* __gn = __gb.get();
3053 unsigned* __ge = __gn + __bz;
3054 money_base::pattern __pat;
3055 char_type __dp;
3056 char_type __ts;
3057 string __grp;
3058 string_type __sym;
3059 string_type __psn;
3060 string_type __nsn;
3061 int __fd;
3062 __money_get<_CharT>::__gather_info(__intl, __loc, __pat, __dp, __ts, __grp,
3063 __sym, __psn, __nsn, __fd);
3064 const string_type* __trailing_sign = 0;
3065 __wn = __wb.get();
3066 for (unsigned __p = 0; __p < 4 && __b != __e; ++__p)
3067 {
3068 switch (__pat.field[__p])
3069 {
3070 case money_base::space:
3071 if (__p != 3)
3072 {
3073 if (__ct.is(ctype_base::space, *__b))
3074 ++__b;
3075 else
3076 {
3077 __err |= ios_base::failbit;
3078 return false;
3079 }
3080 }
Howard Hinnant3b6579a2010-08-22 00:02:43 +00003081 // drop through
Howard Hinnantc51e1022010-05-11 19:42:16 +00003082 case money_base::none:
3083 if (__p != 3)
3084 {
3085 while (__b != __e && __ct.is(ctype_base::space, *__b))
3086 ++__b;
3087 }
3088 break;
3089 case money_base::sign:
3090 if (__psn.size() + __nsn.size() > 0)
3091 {
3092 if (__psn.size() == 0 || __nsn.size() == 0)
3093 { // sign is optional
3094 if (__psn.size() > 0)
3095 { // __nsn.size() == 0
3096 if (*__b == __psn[0])
3097 {
3098 ++__b;
3099 if (__psn.size() > 1)
3100 __trailing_sign = &__psn;
3101 }
3102 else
3103 __neg = true;
3104 }
3105 else if (*__b == __nsn[0]) // __nsn.size() > 0 && __psn.size() == 0
3106 {
3107 ++__b;
3108 __neg = true;
3109 if (__nsn.size() > 1)
3110 __trailing_sign = &__nsn;
3111 }
3112 }
3113 else // sign is required
3114 {
3115 if (*__b == __psn[0])
3116 {
3117 ++__b;
3118 if (__psn.size() > 1)
3119 __trailing_sign = &__psn;
3120 }
3121 else if (*__b == __nsn[0])
3122 {
3123 ++__b;
3124 __neg = true;
3125 if (__nsn.size() > 1)
3126 __trailing_sign = &__nsn;
3127 }
3128 else
3129 {
3130 __err |= ios_base::failbit;
3131 return false;
3132 }
3133 }
3134 }
3135 break;
3136 case money_base::symbol:
3137 {
3138 bool __more_needed = __trailing_sign ||
3139 (__p < 2) ||
3140 (__p == 2 && __pat.field[3] != static_cast<char>(money_base::none));
3141 bool __sb = __flags & ios_base::showbase;
3142 if (__sb || __more_needed)
3143 {
3144 ios_base::iostate __et = ios_base::goodbit;
3145 string_type* __k = __scan_keyword(__b, __e, &__sym, &__sym+1,
3146 __ct, __et);
3147 if (__sb && __k != &__sym)
3148 {
3149 __err |= ios_base::failbit;
3150 return false;
3151 }
3152 }
3153 }
3154 break;
3155 case money_base::value:
3156 {
3157 unsigned __ng = 0;
3158 for (; __b != __e; ++__b)
3159 {
3160 char_type __c = *__b;
3161 if (__ct.is(ctype_base::digit, __c))
3162 {
3163 if (__wn == __we)
3164 __double_or_nothing(__wb, __wn, __we);
3165 *__wn++ = __c;
3166 ++__ng;
3167 }
3168 else if (__grp.size() > 0 && __ng > 0 && __c == __ts)
3169 {
3170 if (__gn == __ge)
3171 __double_or_nothing(__gb, __gn, __ge);
3172 *__gn++ = __ng;
3173 __ng = 0;
3174 }
3175 else
3176 break;
3177 }
3178 if (__gb.get() != __gn && __ng > 0)
3179 {
3180 if (__gn == __ge)
3181 __double_or_nothing(__gb, __gn, __ge);
3182 *__gn++ = __ng;
3183 }
3184 if (__fd > 0)
3185 {
3186 if (__b == __e || *__b != __dp)
3187 {
3188 __err |= ios_base::failbit;
3189 return false;
3190 }
3191 for (++__b; __fd > 0; --__fd, ++__b)
3192 {
3193 if (__b == __e || !__ct.is(ctype_base::digit, *__b))
3194 {
3195 __err |= ios_base::failbit;
3196 return false;
3197 }
3198 if (__wn == __we)
3199 __double_or_nothing(__wb, __wn, __we);
3200 *__wn++ = *__b;
3201 }
3202 }
3203 if (__wn == __wb.get())
3204 {
3205 __err |= ios_base::failbit;
3206 return false;
3207 }
3208 }
3209 break;
3210 }
3211 }
3212 if (__trailing_sign)
3213 {
3214 for (unsigned __i = 1; __i < __trailing_sign->size(); ++__i, ++__b)
3215 {
3216 if (__b == __e || *__b != (*__trailing_sign)[__i])
3217 {
3218 __err |= ios_base::failbit;
3219 return false;
3220 }
3221 }
3222 }
3223 if (__gb.get() != __gn)
3224 {
3225 ios_base::iostate __et = ios_base::goodbit;
3226 __check_grouping(__grp, __gb.get(), __gn, __et);
3227 if (__et)
3228 {
3229 __err |= ios_base::failbit;
3230 return false;
3231 }
3232 }
3233 return true;
3234}
3235
3236template <class _CharT, class _InputIterator>
3237_InputIterator
3238money_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
3239 bool __intl, ios_base& __iob,
3240 ios_base::iostate& __err,
3241 long double& __v) const
3242{
Howard Hinnant28b24882011-12-01 20:21:04 +00003243 const int __bz = 100;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003244 char_type __wbuf[__bz];
3245 unique_ptr<char_type, void(*)(void*)> __wb(__wbuf, __do_nothing);
3246 char_type* __wn;
3247 char_type* __we = __wbuf + __bz;
3248 locale __loc = __iob.getloc();
3249 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3250 bool __neg = false;
3251 if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct,
3252 __wb, __wn, __we))
3253 {
3254 const char __src[] = "0123456789";
3255 char_type __atoms[sizeof(__src)-1];
3256 __ct.widen(__src, __src + (sizeof(__src)-1), __atoms);
3257 char __nbuf[__bz];
3258 char* __nc = __nbuf;
3259 unique_ptr<char, void(*)(void*)> __h(0, free);
3260 if (__wn - __wb.get() > __bz-2)
3261 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003262 __h.reset((char*)malloc(static_cast<size_t>(__wn - __wb.get() + 2)));
Howard Hinnantc51e1022010-05-11 19:42:16 +00003263 if (__h.get() == 0)
3264 __throw_bad_alloc();
3265 __nc = __h.get();
3266 }
3267 if (__neg)
3268 *__nc++ = '-';
3269 for (const char_type* __w = __wb.get(); __w < __wn; ++__w, ++__nc)
3270 *__nc = __src[find(__atoms, __atoms+sizeof(__atoms), *__w) - __atoms];
3271 *__nc = char();
3272 if (sscanf(__nbuf, "%Lf", &__v) != 1)
3273 __throw_runtime_error("money_get error");
3274 }
3275 if (__b == __e)
3276 __err |= ios_base::eofbit;
3277 return __b;
3278}
3279
3280template <class _CharT, class _InputIterator>
3281_InputIterator
3282money_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
3283 bool __intl, ios_base& __iob,
3284 ios_base::iostate& __err,
3285 string_type& __v) const
3286{
Howard Hinnant28b24882011-12-01 20:21:04 +00003287 const int __bz = 100;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003288 char_type __wbuf[__bz];
3289 unique_ptr<char_type, void(*)(void*)> __wb(__wbuf, __do_nothing);
3290 char_type* __wn;
3291 char_type* __we = __wbuf + __bz;
3292 locale __loc = __iob.getloc();
3293 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3294 bool __neg = false;
3295 if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct,
3296 __wb, __wn, __we))
3297 {
3298 __v.clear();
3299 if (__neg)
3300 __v.push_back(__ct.widen('-'));
3301 char_type __z = __ct.widen('0');
3302 char_type* __w;
3303 for (__w = __wb.get(); __w < __wn-1; ++__w)
3304 if (*__w != __z)
3305 break;
3306 __v.append(__w, __wn);
3307 }
3308 if (__b == __e)
3309 __err |= ios_base::eofbit;
3310 return __b;
3311}
3312
3313extern template class money_get<char>;
3314extern template class money_get<wchar_t>;
3315
3316// money_put
3317
3318template <class _CharT>
3319class __money_put
3320{
3321protected:
3322 typedef _CharT char_type;
3323 typedef basic_string<char_type> string_type;
3324
3325 _LIBCPP_ALWAYS_INLINE __money_put() {}
3326
3327 static void __gather_info(bool __intl, bool __neg, const locale& __loc,
3328 money_base::pattern& __pat, char_type& __dp,
3329 char_type& __ts, string& __grp,
3330 string_type& __sym, string_type& __sn,
3331 int& __fd);
3332 static void __format(char_type* __mb, char_type*& __mi, char_type*& __me,
3333 ios_base::fmtflags __flags,
3334 const char_type* __db, const char_type* __de,
3335 const ctype<char_type>& __ct, bool __neg,
3336 const money_base::pattern& __pat, char_type __dp,
3337 char_type __ts, const string& __grp,
3338 const string_type& __sym, const string_type& __sn,
3339 int __fd);
3340};
3341
3342template <class _CharT>
3343void
3344__money_put<_CharT>::__gather_info(bool __intl, bool __neg, const locale& __loc,
3345 money_base::pattern& __pat, char_type& __dp,
3346 char_type& __ts, string& __grp,
3347 string_type& __sym, string_type& __sn,
3348 int& __fd)
3349{
3350 if (__intl)
3351 {
3352 const moneypunct<char_type, true>& __mp =
3353 use_facet<moneypunct<char_type, true> >(__loc);
3354 if (__neg)
3355 {
3356 __pat = __mp.neg_format();
3357 __sn = __mp.negative_sign();
3358 }
3359 else
3360 {
3361 __pat = __mp.pos_format();
3362 __sn = __mp.positive_sign();
3363 }
3364 __dp = __mp.decimal_point();
3365 __ts = __mp.thousands_sep();
3366 __grp = __mp.grouping();
3367 __sym = __mp.curr_symbol();
3368 __fd = __mp.frac_digits();
3369 }
3370 else
3371 {
3372 const moneypunct<char_type, false>& __mp =
3373 use_facet<moneypunct<char_type, false> >(__loc);
3374 if (__neg)
3375 {
3376 __pat = __mp.neg_format();
3377 __sn = __mp.negative_sign();
3378 }
3379 else
3380 {
3381 __pat = __mp.pos_format();
3382 __sn = __mp.positive_sign();
3383 }
3384 __dp = __mp.decimal_point();
3385 __ts = __mp.thousands_sep();
3386 __grp = __mp.grouping();
3387 __sym = __mp.curr_symbol();
3388 __fd = __mp.frac_digits();
3389 }
3390}
3391
3392template <class _CharT>
3393void
3394__money_put<_CharT>::__format(char_type* __mb, char_type*& __mi, char_type*& __me,
3395 ios_base::fmtflags __flags,
3396 const char_type* __db, const char_type* __de,
3397 const ctype<char_type>& __ct, bool __neg,
3398 const money_base::pattern& __pat, char_type __dp,
3399 char_type __ts, const string& __grp,
3400 const string_type& __sym, const string_type& __sn,
3401 int __fd)
3402{
3403 __me = __mb;
3404 for (unsigned __p = 0; __p < 4; ++__p)
3405 {
3406 switch (__pat.field[__p])
3407 {
3408 case money_base::none:
3409 __mi = __me;
3410 break;
3411 case money_base::space:
3412 __mi = __me;
3413 *__me++ = __ct.widen(' ');
3414 break;
3415 case money_base::sign:
3416 if (!__sn.empty())
3417 *__me++ = __sn[0];
3418 break;
3419 case money_base::symbol:
3420 if (!__sym.empty() && (__flags & ios_base::showbase))
Howard Hinnantb1ad5a82011-06-30 21:18:19 +00003421 __me = _VSTD::copy(__sym.begin(), __sym.end(), __me);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003422 break;
3423 case money_base::value:
3424 {
3425 // remember start of value so we can reverse it
3426 char_type* __t = __me;
3427 // find beginning of digits
3428 if (__neg)
3429 ++__db;
3430 // find end of digits
3431 const char_type* __d;
3432 for (__d = __db; __d < __de; ++__d)
3433 if (!__ct.is(ctype_base::digit, *__d))
3434 break;
3435 // print fractional part
3436 if (__fd > 0)
3437 {
3438 int __f;
3439 for (__f = __fd; __d > __db && __f > 0; --__f)
3440 *__me++ = *--__d;
3441 char_type __z = __f > 0 ? __ct.widen('0') : char_type();
3442 for (; __f > 0; --__f)
3443 *__me++ = __z;
3444 *__me++ = __dp;
3445 }
3446 // print units part
3447 if (__d == __db)
3448 {
3449 *__me++ = __ct.widen('0');
3450 }
3451 else
3452 {
3453 unsigned __ng = 0;
3454 unsigned __ig = 0;
3455 unsigned __gl = __grp.empty() ? numeric_limits<unsigned>::max()
3456 : static_cast<unsigned>(__grp[__ig]);
3457 while (__d != __db)
3458 {
3459 if (__ng == __gl)
3460 {
3461 *__me++ = __ts;
3462 __ng = 0;
3463 if (++__ig < __grp.size())
3464 __gl = __grp[__ig] == numeric_limits<char>::max() ?
3465 numeric_limits<unsigned>::max() :
3466 static_cast<unsigned>(__grp[__ig]);
3467 }
3468 *__me++ = *--__d;
3469 ++__ng;
3470 }
3471 }
3472 // reverse it
3473 reverse(__t, __me);
3474 }
3475 break;
3476 }
3477 }
3478 // print rest of sign, if any
3479 if (__sn.size() > 1)
Howard Hinnantb1ad5a82011-06-30 21:18:19 +00003480 __me = _VSTD::copy(__sn.begin()+1, __sn.end(), __me);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003481 // set alignment
3482 if ((__flags & ios_base::adjustfield) == ios_base::left)
3483 __mi = __me;
3484 else if ((__flags & ios_base::adjustfield) != ios_base::internal)
3485 __mi = __mb;
3486}
3487
3488extern template class __money_put<char>;
3489extern template class __money_put<wchar_t>;
3490
3491template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant756c69b2010-09-22 16:48:34 +00003492class _LIBCPP_VISIBLE money_put
Howard Hinnantc51e1022010-05-11 19:42:16 +00003493 : public locale::facet,
3494 private __money_put<_CharT>
3495{
3496public:
3497 typedef _CharT char_type;
3498 typedef _OutputIterator iter_type;
3499 typedef basic_string<char_type> string_type;
3500
3501 _LIBCPP_ALWAYS_INLINE
3502 explicit money_put(size_t __refs = 0)
3503 : locale::facet(__refs) {}
3504
3505 _LIBCPP_ALWAYS_INLINE
3506 iter_type put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl,
3507 long double __units) const
3508 {
3509 return do_put(__s, __intl, __iob, __fl, __units);
3510 }
3511
3512 _LIBCPP_ALWAYS_INLINE
3513 iter_type put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl,
3514 const string_type& __digits) const
3515 {
3516 return do_put(__s, __intl, __iob, __fl, __digits);
3517 }
3518
3519 static locale::id id;
3520
3521protected:
Howard Hinnant756c69b2010-09-22 16:48:34 +00003522 _LIBCPP_ALWAYS_INLINE
Howard Hinnantc51e1022010-05-11 19:42:16 +00003523 ~money_put() {}
3524
3525 virtual iter_type do_put(iter_type __s, bool __intl, ios_base& __iob,
3526 char_type __fl, long double __units) const;
3527 virtual iter_type do_put(iter_type __s, bool __intl, ios_base& __iob,
3528 char_type __fl, const string_type& __digits) const;
3529};
3530
3531template <class _CharT, class _OutputIterator>
3532locale::id
3533money_put<_CharT, _OutputIterator>::id;
3534
3535template <class _CharT, class _OutputIterator>
3536_OutputIterator
3537money_put<_CharT, _OutputIterator>::do_put(iter_type __s, bool __intl,
3538 ios_base& __iob, char_type __fl,
3539 long double __units) const
3540{
3541 // convert to char
3542 const size_t __bs = 100;
3543 char __buf[__bs];
3544 char* __bb = __buf;
3545 char_type __digits[__bs];
3546 char_type* __db = __digits;
Howard Hinnant28b24882011-12-01 20:21:04 +00003547 size_t __n = static_cast<size_t>(snprintf(__bb, __bs, "%.0Lf", __units));
Howard Hinnantc51e1022010-05-11 19:42:16 +00003548 unique_ptr<char, void(*)(void*)> __hn(0, free);
3549 unique_ptr<char_type, void(*)(void*)> __hd(0, free);
3550 // secure memory for digit storage
3551 if (__n > __bs-1)
3552 {
Howard Hinnantf312e3e2011-09-28 23:39:33 +00003553#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant28b24882011-12-01 20:21:04 +00003554 __n = static_cast<size_t>(asprintf_l(&__bb, _LIBCPP_GET_C_LOCALE, "%.0Lf", __units));
Alexis Hunt1adf2aa2011-07-15 05:40:33 +00003555#else
3556 __n = __asprintf_l(&__bb, __cloc(), "%.0Lf", __units);
3557#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00003558 if (__bb == 0)
3559 __throw_bad_alloc();
3560 __hn.reset(__bb);
3561 __hd.reset((char_type*)malloc(__n * sizeof(char_type)));
3562 if (__hd == 0)
3563 __throw_bad_alloc();
3564 __db = __hd.get();
3565 }
3566 // gather info
3567 locale __loc = __iob.getloc();
3568 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3569 __ct.widen(__bb, __bb + __n, __db);
3570 bool __neg = __n > 0 && __bb[0] == '-';
3571 money_base::pattern __pat;
3572 char_type __dp;
3573 char_type __ts;
3574 string __grp;
3575 string_type __sym;
3576 string_type __sn;
3577 int __fd;
3578 this->__gather_info(__intl, __neg, __loc, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3579 // secure memory for formatting
3580 char_type __mbuf[__bs];
3581 char_type* __mb = __mbuf;
3582 unique_ptr<char_type, void(*)(void*)> __hw(0, free);
3583 size_t __exn = static_cast<int>(__n) > __fd ?
Howard Hinnant28b24882011-12-01 20:21:04 +00003584 (__n - static_cast<size_t>(__fd)) * 2 + __sn.size() +
3585 __sym.size() + static_cast<size_t>(__fd) + 1
3586 : __sn.size() + __sym.size() + static_cast<size_t>(__fd) + 2;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003587 if (__exn > __bs)
3588 {
3589 __hw.reset((char_type*)malloc(__exn * sizeof(char_type)));
3590 __mb = __hw.get();
3591 if (__mb == 0)
3592 __throw_bad_alloc();
3593 }
3594 // format
3595 char_type* __mi;
3596 char_type* __me;
3597 this->__format(__mb, __mi, __me, __iob.flags(),
3598 __db, __db + __n, __ct,
3599 __neg, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3600 return __pad_and_output(__s, __mb, __mi, __me, __iob, __fl);
3601}
3602
3603template <class _CharT, class _OutputIterator>
3604_OutputIterator
3605money_put<_CharT, _OutputIterator>::do_put(iter_type __s, bool __intl,
3606 ios_base& __iob, char_type __fl,
3607 const string_type& __digits) const
3608{
3609 // gather info
3610 locale __loc = __iob.getloc();
3611 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3612 bool __neg = __digits.size() > 0 && __digits[0] == __ct.widen('-');
3613 money_base::pattern __pat;
3614 char_type __dp;
3615 char_type __ts;
3616 string __grp;
3617 string_type __sym;
3618 string_type __sn;
3619 int __fd;
3620 this->__gather_info(__intl, __neg, __loc, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3621 // secure memory for formatting
3622 char_type __mbuf[100];
3623 char_type* __mb = __mbuf;
3624 unique_ptr<char_type, void(*)(void*)> __h(0, free);
Howard Hinnant28b24882011-12-01 20:21:04 +00003625 size_t __exn = static_cast<int>(__digits.size()) > __fd ?
3626 (__digits.size() - static_cast<size_t>(__fd)) * 2 +
3627 __sn.size() + __sym.size() + static_cast<size_t>(__fd) + 1
3628 : __sn.size() + __sym.size() + static_cast<size_t>(__fd) + 2;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003629 if (__exn > 100)
3630 {
3631 __h.reset((char_type*)malloc(__exn * sizeof(char_type)));
3632 __mb = __h.get();
3633 if (__mb == 0)
3634 __throw_bad_alloc();
3635 }
3636 // format
3637 char_type* __mi;
3638 char_type* __me;
3639 this->__format(__mb, __mi, __me, __iob.flags(),
3640 __digits.data(), __digits.data() + __digits.size(), __ct,
3641 __neg, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3642 return __pad_and_output(__s, __mb, __mi, __me, __iob, __fl);
3643}
3644
3645extern template class money_put<char>;
3646extern template class money_put<wchar_t>;
3647
3648// messages
3649
Howard Hinnant756c69b2010-09-22 16:48:34 +00003650class _LIBCPP_VISIBLE messages_base
Howard Hinnantc51e1022010-05-11 19:42:16 +00003651{
3652public:
Howard Hinnant2862aeb2011-02-25 00:51:08 +00003653 typedef ptrdiff_t catalog;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003654
3655 _LIBCPP_ALWAYS_INLINE messages_base() {}
3656};
3657
3658template <class _CharT>
Howard Hinnant756c69b2010-09-22 16:48:34 +00003659class _LIBCPP_VISIBLE messages
Howard Hinnantc51e1022010-05-11 19:42:16 +00003660 : public locale::facet,
3661 public messages_base
3662{
3663public:
3664 typedef _CharT char_type;
3665 typedef basic_string<_CharT> string_type;
3666
3667 _LIBCPP_ALWAYS_INLINE
3668 explicit messages(size_t __refs = 0)
3669 : locale::facet(__refs) {}
3670
3671 _LIBCPP_ALWAYS_INLINE
3672 catalog open(const basic_string<char>& __nm, const locale& __loc) const
3673 {
3674 return do_open(__nm, __loc);
3675 }
3676
3677 _LIBCPP_ALWAYS_INLINE
3678 string_type get(catalog __c, int __set, int __msgid,
3679 const string_type& __dflt) const
3680 {
3681 return do_get(__c, __set, __msgid, __dflt);
3682 }
3683
3684 _LIBCPP_ALWAYS_INLINE
3685 void close(catalog __c) const
3686 {
3687 do_close(__c);
3688 }
3689
3690 static locale::id id;
3691
3692protected:
Howard Hinnant756c69b2010-09-22 16:48:34 +00003693 _LIBCPP_ALWAYS_INLINE
Howard Hinnantc51e1022010-05-11 19:42:16 +00003694 ~messages() {}
3695
3696 virtual catalog do_open(const basic_string<char>&, const locale&) const;
3697 virtual string_type do_get(catalog, int __set, int __msgid,
3698 const string_type& __dflt) const;
3699 virtual void do_close(catalog) const;
3700};
3701
3702template <class _CharT>
3703locale::id
3704messages<_CharT>::id;
3705
3706template <class _CharT>
3707typename messages<_CharT>::catalog
3708messages<_CharT>::do_open(const basic_string<char>& __nm, const locale&) const
3709{
Howard Hinnanteb505f62011-09-23 16:11:27 +00003710#if _WIN32
3711 return -1;
3712#else // _WIN32
Howard Hinnant8c2bf6b2011-10-11 16:00:46 +00003713 catalog __cat = (catalog)catopen(__nm.c_str(), NL_CAT_LOCALE);
Howard Hinnant2862aeb2011-02-25 00:51:08 +00003714 if (__cat != -1)
3715 __cat = static_cast<catalog>((static_cast<size_t>(__cat) >> 1));
3716 return __cat;
Howard Hinnanteb505f62011-09-23 16:11:27 +00003717#endif // _WIN32
Howard Hinnantc51e1022010-05-11 19:42:16 +00003718}
3719
3720template <class _CharT>
3721typename messages<_CharT>::string_type
3722messages<_CharT>::do_get(catalog __c, int __set, int __msgid,
3723 const string_type& __dflt) const
3724{
Howard Hinnanteb505f62011-09-23 16:11:27 +00003725#if _WIN32
3726 return __dflt;
3727#else // _WIN32
Howard Hinnantc51e1022010-05-11 19:42:16 +00003728 string __ndflt;
3729 __narrow_to_utf8<sizeof(char_type)*__CHAR_BIT__>()(back_inserter(__ndflt),
3730 __dflt.c_str(),
3731 __dflt.c_str() + __dflt.size());
Howard Hinnant2862aeb2011-02-25 00:51:08 +00003732 if (__c != -1)
3733 __c <<= 1;
Howard Hinnant8c2bf6b2011-10-11 16:00:46 +00003734 nl_catd __cat = (nl_catd)__c;
Howard Hinnant2862aeb2011-02-25 00:51:08 +00003735 char* __n = catgets(__cat, __set, __msgid, __ndflt.c_str());
Howard Hinnantc51e1022010-05-11 19:42:16 +00003736 string_type __w;
3737 __widen_from_utf8<sizeof(char_type)*__CHAR_BIT__>()(back_inserter(__w),
3738 __n, __n + strlen(__n));
3739 return __w;
Howard Hinnanteb505f62011-09-23 16:11:27 +00003740#endif // _WIN32
Howard Hinnantc51e1022010-05-11 19:42:16 +00003741}
3742
3743template <class _CharT>
3744void
3745messages<_CharT>::do_close(catalog __c) const
3746{
Howard Hinnanteb505f62011-09-23 16:11:27 +00003747#if !_WIN32
Howard Hinnant2862aeb2011-02-25 00:51:08 +00003748 if (__c != -1)
3749 __c <<= 1;
Howard Hinnant8c2bf6b2011-10-11 16:00:46 +00003750 nl_catd __cat = (nl_catd)__c;
Howard Hinnant2862aeb2011-02-25 00:51:08 +00003751 catclose(__cat);
Howard Hinnanteb505f62011-09-23 16:11:27 +00003752#endif // !_WIN32
Howard Hinnantc51e1022010-05-11 19:42:16 +00003753}
3754
3755extern template class messages<char>;
3756extern template class messages<wchar_t>;
3757
3758template <class _CharT>
Howard Hinnant756c69b2010-09-22 16:48:34 +00003759class _LIBCPP_VISIBLE messages_byname
Howard Hinnantc51e1022010-05-11 19:42:16 +00003760 : public messages<_CharT>
3761{
3762public:
3763 typedef messages_base::catalog catalog;
3764 typedef basic_string<_CharT> string_type;
3765
3766 _LIBCPP_ALWAYS_INLINE
3767 explicit messages_byname(const char*, size_t __refs = 0)
3768 : messages<_CharT>(__refs) {}
3769
3770 _LIBCPP_ALWAYS_INLINE
3771 explicit messages_byname(const string&, size_t __refs = 0)
3772 : messages<_CharT>(__refs) {}
3773
3774protected:
Howard Hinnant756c69b2010-09-22 16:48:34 +00003775 _LIBCPP_ALWAYS_INLINE
Howard Hinnantc51e1022010-05-11 19:42:16 +00003776 ~messages_byname() {}
3777};
3778
3779extern template class messages_byname<char>;
3780extern template class messages_byname<wchar_t>;
3781
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003782template<class _Codecvt, class _Elem = wchar_t,
3783 class _Wide_alloc = allocator<_Elem>,
3784 class _Byte_alloc = allocator<char> >
Howard Hinnant756c69b2010-09-22 16:48:34 +00003785class _LIBCPP_VISIBLE wstring_convert
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003786{
3787public:
3788 typedef basic_string<char, char_traits<char>, _Byte_alloc> byte_string;
3789 typedef basic_string<_Elem, char_traits<_Elem>, _Wide_alloc> wide_string;
3790 typedef typename _Codecvt::state_type state_type;
3791 typedef typename wide_string::traits_type::int_type int_type;
3792
3793private:
3794 byte_string __byte_err_string_;
3795 wide_string __wide_err_string_;
3796 _Codecvt* __cvtptr_;
3797 state_type __cvtstate_;
3798 size_t __cvtcount_;
3799
3800 wstring_convert(const wstring_convert& __wc);
3801 wstring_convert& operator=(const wstring_convert& __wc);
3802public:
3803 wstring_convert(_Codecvt* __pcvt = new _Codecvt);
3804 wstring_convert(_Codecvt* __pcvt, state_type __state);
3805 wstring_convert(const byte_string& __byte_err,
3806 const wide_string& __wide_err = wide_string());
Howard Hinnant74279a52010-09-04 23:28:19 +00003807#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003808 wstring_convert(wstring_convert&& __wc);
3809#endif
3810 ~wstring_convert();
3811
Howard Hinnant756c69b2010-09-22 16:48:34 +00003812 _LIBCPP_ALWAYS_INLINE
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003813 wide_string from_bytes(char __byte)
3814 {return from_bytes(&__byte, &__byte+1);}
Howard Hinnant756c69b2010-09-22 16:48:34 +00003815 _LIBCPP_ALWAYS_INLINE
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003816 wide_string from_bytes(const char* __ptr)
3817 {return from_bytes(__ptr, __ptr + char_traits<char>::length(__ptr));}
Howard Hinnant756c69b2010-09-22 16:48:34 +00003818 _LIBCPP_ALWAYS_INLINE
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003819 wide_string from_bytes(const byte_string& __str)
3820 {return from_bytes(__str.data(), __str.data() + __str.size());}
3821 wide_string from_bytes(const char* __first, const char* __last);
3822
Howard Hinnant756c69b2010-09-22 16:48:34 +00003823 _LIBCPP_ALWAYS_INLINE
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003824 byte_string to_bytes(_Elem __wchar)
3825 {return to_bytes(&__wchar, &__wchar+1);}
Howard Hinnant756c69b2010-09-22 16:48:34 +00003826 _LIBCPP_ALWAYS_INLINE
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003827 byte_string to_bytes(const _Elem* __wptr)
3828 {return to_bytes(__wptr, __wptr + char_traits<_Elem>::length(__wptr));}
Howard Hinnant756c69b2010-09-22 16:48:34 +00003829 _LIBCPP_ALWAYS_INLINE
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003830 byte_string to_bytes(const wide_string& __wstr)
3831 {return to_bytes(__wstr.data(), __wstr.data() + __wstr.size());}
3832 byte_string to_bytes(const _Elem* __first, const _Elem* __last);
3833
Howard Hinnant756c69b2010-09-22 16:48:34 +00003834 _LIBCPP_ALWAYS_INLINE
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003835 size_t converted() const {return __cvtcount_;}
Howard Hinnant756c69b2010-09-22 16:48:34 +00003836 _LIBCPP_ALWAYS_INLINE
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003837 state_type state() const {return __cvtstate_;}
3838};
3839
3840template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Howard Hinnant756c69b2010-09-22 16:48:34 +00003841inline _LIBCPP_ALWAYS_INLINE
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003842wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3843 wstring_convert(_Codecvt* __pcvt)
3844 : __cvtptr_(__pcvt), __cvtstate_(), __cvtcount_(0)
3845{
3846}
3847
3848template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Howard Hinnant756c69b2010-09-22 16:48:34 +00003849inline _LIBCPP_ALWAYS_INLINE
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003850wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3851 wstring_convert(_Codecvt* __pcvt, state_type __state)
3852 : __cvtptr_(__pcvt), __cvtstate_(__state), __cvtcount_(0)
3853{
3854}
3855
3856template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3857wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3858 wstring_convert(const byte_string& __byte_err, const wide_string& __wide_err)
3859 : __byte_err_string_(__byte_err), __wide_err_string_(__wide_err),
3860 __cvtstate_(), __cvtcount_(0)
3861{
3862 __cvtptr_ = new _Codecvt;
3863}
3864
Howard Hinnant74279a52010-09-04 23:28:19 +00003865#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003866
3867template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Howard Hinnant756c69b2010-09-22 16:48:34 +00003868inline _LIBCPP_ALWAYS_INLINE
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003869wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3870 wstring_convert(wstring_convert&& __wc)
Howard Hinnantb1ad5a82011-06-30 21:18:19 +00003871 : __byte_err_string_(_VSTD::move(__wc.__byte_err_string_)),
3872 __wide_err_string_(_VSTD::move(__wc.__wide_err_string_)),
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003873 __cvtptr_(__wc.__cvtptr_),
3874 __cvtstate_(__wc.__cvtstate_), __cvtcount_(__wc.__cvtstate_)
3875{
3876 __wc.__cvtptr_ = nullptr;
3877}
3878
Howard Hinnant5dc89112010-09-04 23:46:48 +00003879#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003880
3881template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3882wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::~wstring_convert()
3883{
3884 delete __cvtptr_;
3885}
3886
3887template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3888typename wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::wide_string
3889wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3890 from_bytes(const char* __frm, const char* __frm_end)
3891{
3892 __cvtcount_ = 0;
3893 if (__cvtptr_ != nullptr)
3894 {
3895 wide_string __ws(2*(__frm_end - __frm), _Elem());
3896 __ws.resize(__ws.capacity());
3897 codecvt_base::result __r = codecvt_base::ok;
3898 state_type __st = __cvtstate_;
3899 if (__frm != __frm_end)
3900 {
3901 _Elem* __to = &__ws[0];
3902 _Elem* __to_end = __to + __ws.size();
3903 const char* __frm_nxt;
3904 do
3905 {
3906 _Elem* __to_nxt;
3907 __r = __cvtptr_->in(__st, __frm, __frm_end, __frm_nxt,
3908 __to, __to_end, __to_nxt);
3909 __cvtcount_ += __frm_nxt - __frm;
3910 if (__frm_nxt == __frm)
3911 {
3912 __r = codecvt_base::error;
3913 }
3914 else if (__r == codecvt_base::noconv)
3915 {
3916 __ws.resize(__to - &__ws[0]);
3917 // This only gets executed if _Elem is char
3918 __ws.append((const _Elem*)__frm, (const _Elem*)__frm_end);
3919 __frm = __frm_nxt;
3920 __r = codecvt_base::ok;
3921 }
3922 else if (__r == codecvt_base::ok)
3923 {
3924 __ws.resize(__to_nxt - &__ws[0]);
3925 __frm = __frm_nxt;
3926 }
3927 else if (__r == codecvt_base::partial)
3928 {
3929 ptrdiff_t __s = __to_nxt - &__ws[0];
3930 __ws.resize(2 * __s);
3931 __to = &__ws[0] + __s;
3932 __to_end = &__ws[0] + __ws.size();
3933 __frm = __frm_nxt;
3934 }
3935 } while (__r == codecvt_base::partial && __frm_nxt < __frm_end);
3936 }
3937 if (__r == codecvt_base::ok)
3938 return __ws;
3939 }
Howard Hinnant72f73582010-08-11 17:04:31 +00003940#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003941 if (__wide_err_string_.empty())
3942 throw range_error("wstring_convert: from_bytes error");
Howard Hinnant3b6579a2010-08-22 00:02:43 +00003943#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003944 return __wide_err_string_;
3945}
3946
3947template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3948typename wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::byte_string
3949wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3950 to_bytes(const _Elem* __frm, const _Elem* __frm_end)
3951{
3952 __cvtcount_ = 0;
3953 if (__cvtptr_ != nullptr)
3954 {
3955 byte_string __bs(2*(__frm_end - __frm), char());
3956 __bs.resize(__bs.capacity());
3957 codecvt_base::result __r = codecvt_base::ok;
3958 state_type __st = __cvtstate_;
3959 if (__frm != __frm_end)
3960 {
3961 char* __to = &__bs[0];
3962 char* __to_end = __to + __bs.size();
3963 const _Elem* __frm_nxt;
3964 do
3965 {
3966 char* __to_nxt;
3967 __r = __cvtptr_->out(__st, __frm, __frm_end, __frm_nxt,
3968 __to, __to_end, __to_nxt);
3969 __cvtcount_ += __frm_nxt - __frm;
3970 if (__frm_nxt == __frm)
3971 {
3972 __r = codecvt_base::error;
3973 }
3974 else if (__r == codecvt_base::noconv)
3975 {
3976 __bs.resize(__to - &__bs[0]);
3977 // This only gets executed if _Elem is char
3978 __bs.append((const char*)__frm, (const char*)__frm_end);
3979 __frm = __frm_nxt;
3980 __r = codecvt_base::ok;
3981 }
3982 else if (__r == codecvt_base::ok)
3983 {
3984 __bs.resize(__to_nxt - &__bs[0]);
3985 __frm = __frm_nxt;
3986 }
3987 else if (__r == codecvt_base::partial)
3988 {
3989 ptrdiff_t __s = __to_nxt - &__bs[0];
3990 __bs.resize(2 * __s);
3991 __to = &__bs[0] + __s;
3992 __to_end = &__bs[0] + __bs.size();
3993 __frm = __frm_nxt;
3994 }
3995 } while (__r == codecvt_base::partial && __frm_nxt < __frm_end);
3996 }
3997 if (__r == codecvt_base::ok)
3998 {
3999 size_t __s = __bs.size();
4000 __bs.resize(__bs.capacity());
4001 char* __to = &__bs[0] + __s;
4002 char* __to_end = __to + __bs.size();
4003 do
4004 {
4005 char* __to_nxt;
4006 __r = __cvtptr_->unshift(__st, __to, __to_end, __to_nxt);
4007 if (__r == codecvt_base::noconv)
4008 {
4009 __bs.resize(__to - &__bs[0]);
4010 __r = codecvt_base::ok;
4011 }
4012 else if (__r == codecvt_base::ok)
4013 {
4014 __bs.resize(__to_nxt - &__bs[0]);
4015 }
4016 else if (__r == codecvt_base::partial)
4017 {
Howard Hinnant28b24882011-12-01 20:21:04 +00004018 ptrdiff_t __sp = __to_nxt - &__bs[0];
4019 __bs.resize(2 * __sp);
4020 __to = &__bs[0] + __sp;
Howard Hinnant9dd7e892010-05-31 20:58:54 +00004021 __to_end = &__bs[0] + __bs.size();
4022 }
4023 } while (__r == codecvt_base::partial);
4024 if (__r == codecvt_base::ok)
4025 return __bs;
4026 }
4027 }
Howard Hinnant72f73582010-08-11 17:04:31 +00004028#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant9dd7e892010-05-31 20:58:54 +00004029 if (__byte_err_string_.empty())
4030 throw range_error("wstring_convert: to_bytes error");
Howard Hinnant3b6579a2010-08-22 00:02:43 +00004031#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant9dd7e892010-05-31 20:58:54 +00004032 return __byte_err_string_;
4033}
4034
4035template <class _Codecvt, class _Elem = wchar_t, class _Tr = char_traits<_Elem> >
Howard Hinnant756c69b2010-09-22 16:48:34 +00004036class _LIBCPP_VISIBLE wbuffer_convert
Howard Hinnant9dd7e892010-05-31 20:58:54 +00004037 : public basic_streambuf<_Elem, _Tr>
4038{
4039public:
4040 // types:
4041 typedef _Elem char_type;
4042 typedef _Tr traits_type;
4043 typedef typename traits_type::int_type int_type;
4044 typedef typename traits_type::pos_type pos_type;
4045 typedef typename traits_type::off_type off_type;
4046 typedef typename _Codecvt::state_type state_type;
4047
4048private:
Howard Hinnant0ac182a2010-06-01 20:09:18 +00004049 char* __extbuf_;
4050 const char* __extbufnext_;
4051 const char* __extbufend_;
4052 char __extbuf_min_[8];
4053 size_t __ebs_;
4054 char_type* __intbuf_;
4055 size_t __ibs_;
Howard Hinnant9dd7e892010-05-31 20:58:54 +00004056 streambuf* __bufptr_;
Howard Hinnant0ac182a2010-06-01 20:09:18 +00004057 _Codecvt* __cv_;
4058 state_type __st_;
4059 ios_base::openmode __cm_;
4060 bool __owns_eb_;
4061 bool __owns_ib_;
4062 bool __always_noconv_;
Howard Hinnant9dd7e892010-05-31 20:58:54 +00004063
Howard Hinnant0ac182a2010-06-01 20:09:18 +00004064 wbuffer_convert(const wbuffer_convert&);
4065 wbuffer_convert& operator=(const wbuffer_convert&);
Howard Hinnant9dd7e892010-05-31 20:58:54 +00004066public:
4067 wbuffer_convert(streambuf* __bytebuf = 0, _Codecvt* __pcvt = new _Codecvt,
Howard Hinnant0ac182a2010-06-01 20:09:18 +00004068 state_type __state = state_type());
4069 ~wbuffer_convert();
Howard Hinnant9dd7e892010-05-31 20:58:54 +00004070
Howard Hinnant756c69b2010-09-22 16:48:34 +00004071 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant9dd7e892010-05-31 20:58:54 +00004072 streambuf* rdbuf() const {return __bufptr_;}
Howard Hinnant756c69b2010-09-22 16:48:34 +00004073 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant9dd7e892010-05-31 20:58:54 +00004074 streambuf* rdbuf(streambuf* __bytebuf)
4075 {
4076 streambuf* __r = __bufptr_;
4077 __bufptr_ = __bytebuf;
4078 return __r;
4079 }
4080
Howard Hinnant756c69b2010-09-22 16:48:34 +00004081 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant0ac182a2010-06-01 20:09:18 +00004082 state_type state() const {return __st_;}
Howard Hinnant9dd7e892010-05-31 20:58:54 +00004083
4084protected:
Howard Hinnant0ac182a2010-06-01 20:09:18 +00004085 virtual int_type underflow();
4086 virtual int_type pbackfail(int_type __c = traits_type::eof());
Howard Hinnant9dd7e892010-05-31 20:58:54 +00004087 virtual int_type overflow (int_type __c = traits_type::eof());
Howard Hinnant0ac182a2010-06-01 20:09:18 +00004088 virtual basic_streambuf<char_type, traits_type>* setbuf(char_type* __s,
4089 streamsize __n);
4090 virtual pos_type seekoff(off_type __off, ios_base::seekdir __way,
4091 ios_base::openmode __wch = ios_base::in | ios_base::out);
4092 virtual pos_type seekpos(pos_type __sp,
4093 ios_base::openmode __wch = ios_base::in | ios_base::out);
4094 virtual int sync();
4095
4096private:
4097 bool __read_mode();
4098 void __write_mode();
4099 wbuffer_convert* __close();
Howard Hinnant9dd7e892010-05-31 20:58:54 +00004100};
4101
4102template <class _Codecvt, class _Elem, class _Tr>
Howard Hinnant0ac182a2010-06-01 20:09:18 +00004103wbuffer_convert<_Codecvt, _Elem, _Tr>::
4104 wbuffer_convert(streambuf* __bytebuf, _Codecvt* __pcvt, state_type __state)
4105 : __extbuf_(0),
4106 __extbufnext_(0),
4107 __extbufend_(0),
4108 __ebs_(0),
4109 __intbuf_(0),
4110 __ibs_(0),
4111 __bufptr_(__bytebuf),
4112 __cv_(__pcvt),
4113 __st_(__state),
4114 __cm_(0),
4115 __owns_eb_(false),
4116 __owns_ib_(false),
4117 __always_noconv_(__cv_ ? __cv_->always_noconv() : false)
4118{
4119 setbuf(0, 4096);
4120}
4121
4122template <class _Codecvt, class _Elem, class _Tr>
4123wbuffer_convert<_Codecvt, _Elem, _Tr>::~wbuffer_convert()
4124{
4125 __close();
4126 delete __cv_;
4127 if (__owns_eb_)
4128 delete [] __extbuf_;
4129 if (__owns_ib_)
4130 delete [] __intbuf_;
4131}
4132
4133template <class _Codecvt, class _Elem, class _Tr>
4134typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
4135wbuffer_convert<_Codecvt, _Elem, _Tr>::underflow()
4136{
4137 if (__cv_ == 0 || __bufptr_ == 0)
4138 return traits_type::eof();
4139 bool __initial = __read_mode();
4140 char_type __1buf;
4141 if (this->gptr() == 0)
4142 this->setg(&__1buf, &__1buf+1, &__1buf+1);
4143 const size_t __unget_sz = __initial ? 0 : min<size_t>((this->egptr() - this->eback()) / 2, 4);
4144 int_type __c = traits_type::eof();
4145 if (this->gptr() == this->egptr())
4146 {
4147 memmove(this->eback(), this->egptr() - __unget_sz, __unget_sz * sizeof(char_type));
4148 if (__always_noconv_)
4149 {
4150 streamsize __nmemb = static_cast<streamsize>(this->egptr() - this->eback() - __unget_sz);
4151 __nmemb = __bufptr_->sgetn((char*)this->eback() + __unget_sz, __nmemb);
4152 if (__nmemb != 0)
4153 {
4154 this->setg(this->eback(),
4155 this->eback() + __unget_sz,
4156 this->eback() + __unget_sz + __nmemb);
4157 __c = *this->gptr();
4158 }
4159 }
4160 else
4161 {
4162 memmove(__extbuf_, __extbufnext_, __extbufend_ - __extbufnext_);
4163 __extbufnext_ = __extbuf_ + (__extbufend_ - __extbufnext_);
4164 __extbufend_ = __extbuf_ + (__extbuf_ == __extbuf_min_ ? sizeof(__extbuf_min_) : __ebs_);
Howard Hinnantb1ad5a82011-06-30 21:18:19 +00004165 streamsize __nmemb = _VSTD::min(static_cast<streamsize>(this->egptr() - this->eback() - __unget_sz),
Howard Hinnant0ac182a2010-06-01 20:09:18 +00004166 static_cast<streamsize>(__extbufend_ - __extbufnext_));
4167 codecvt_base::result __r;
4168 state_type __svs = __st_;
4169 streamsize __nr = __bufptr_->sgetn(const_cast<char*>(__extbufnext_), __nmemb);
4170 if (__nr != 0)
4171 {
4172 __extbufend_ = __extbufnext_ + __nr;
4173 char_type* __inext;
4174 __r = __cv_->in(__st_, __extbuf_, __extbufend_, __extbufnext_,
4175 this->eback() + __unget_sz,
4176 this->egptr(), __inext);
4177 if (__r == codecvt_base::noconv)
4178 {
4179 this->setg((char_type*)__extbuf_, (char_type*)__extbuf_, (char_type*)__extbufend_);
4180 __c = *this->gptr();
4181 }
4182 else if (__inext != this->eback() + __unget_sz)
4183 {
4184 this->setg(this->eback(), this->eback() + __unget_sz, __inext);
4185 __c = *this->gptr();
4186 }
4187 }
4188 }
4189 }
4190 else
4191 __c = *this->gptr();
4192 if (this->eback() == &__1buf)
4193 this->setg(0, 0, 0);
4194 return __c;
4195}
4196
4197template <class _Codecvt, class _Elem, class _Tr>
4198typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
4199wbuffer_convert<_Codecvt, _Elem, _Tr>::pbackfail(int_type __c)
4200{
4201 if (__cv_ != 0 && __bufptr_ != 0 && this->eback() < this->gptr())
4202 {
4203 if (traits_type::eq_int_type(__c, traits_type::eof()))
4204 {
4205 this->gbump(-1);
4206 return traits_type::not_eof(__c);
4207 }
4208 if (traits_type::eq(traits_type::to_char_type(__c), this->gptr()[-1]))
4209 {
4210 this->gbump(-1);
4211 *this->gptr() = traits_type::to_char_type(__c);
4212 return __c;
4213 }
4214 }
4215 return traits_type::eof();
4216}
4217
4218template <class _Codecvt, class _Elem, class _Tr>
Howard Hinnant9dd7e892010-05-31 20:58:54 +00004219typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
4220wbuffer_convert<_Codecvt, _Elem, _Tr>::overflow(int_type __c)
4221{
Howard Hinnant0ac182a2010-06-01 20:09:18 +00004222 if (__cv_ == 0 || __bufptr_ == 0)
4223 return traits_type::eof();
4224 __write_mode();
4225 char_type __1buf;
4226 char_type* __pb_save = this->pbase();
4227 char_type* __epb_save = this->epptr();
4228 if (!traits_type::eq_int_type(__c, traits_type::eof()))
4229 {
4230 if (this->pptr() == 0)
4231 this->setp(&__1buf, &__1buf+1);
4232 *this->pptr() = traits_type::to_char_type(__c);
4233 this->pbump(1);
4234 }
4235 if (this->pptr() != this->pbase())
4236 {
4237 if (__always_noconv_)
4238 {
4239 streamsize __nmemb = static_cast<streamsize>(this->pptr() - this->pbase());
4240 if (__bufptr_->sputn((const char*)this->pbase(), __nmemb) != __nmemb)
4241 return traits_type::eof();
4242 }
4243 else
4244 {
4245 char* __extbe = __extbuf_;
4246 codecvt_base::result __r;
4247 do
4248 {
4249 const char_type* __e;
4250 __r = __cv_->out(__st_, this->pbase(), this->pptr(), __e,
4251 __extbuf_, __extbuf_ + __ebs_, __extbe);
4252 if (__e == this->pbase())
4253 return traits_type::eof();
4254 if (__r == codecvt_base::noconv)
4255 {
4256 streamsize __nmemb = static_cast<size_t>(this->pptr() - this->pbase());
4257 if (__bufptr_->sputn((const char*)this->pbase(), __nmemb) != __nmemb)
4258 return traits_type::eof();
4259 }
4260 else if (__r == codecvt_base::ok || __r == codecvt_base::partial)
4261 {
4262 streamsize __nmemb = static_cast<size_t>(__extbe - __extbuf_);
4263 if (__bufptr_->sputn(__extbuf_, __nmemb) != __nmemb)
4264 return traits_type::eof();
4265 if (__r == codecvt_base::partial)
4266 {
4267 this->setp((char_type*)__e, this->pptr());
4268 this->pbump(this->epptr() - this->pbase());
4269 }
4270 }
4271 else
4272 return traits_type::eof();
4273 } while (__r == codecvt_base::partial);
4274 }
4275 this->setp(__pb_save, __epb_save);
4276 }
4277 return traits_type::not_eof(__c);
4278}
4279
4280template <class _Codecvt, class _Elem, class _Tr>
4281basic_streambuf<_Elem, _Tr>*
4282wbuffer_convert<_Codecvt, _Elem, _Tr>::setbuf(char_type* __s, streamsize __n)
4283{
4284 this->setg(0, 0, 0);
4285 this->setp(0, 0);
4286 if (__owns_eb_)
4287 delete [] __extbuf_;
4288 if (__owns_ib_)
4289 delete [] __intbuf_;
4290 __ebs_ = __n;
4291 if (__ebs_ > sizeof(__extbuf_min_))
4292 {
4293 if (__always_noconv_ && __s)
4294 {
4295 __extbuf_ = (char*)__s;
4296 __owns_eb_ = false;
4297 }
4298 else
4299 {
4300 __extbuf_ = new char[__ebs_];
4301 __owns_eb_ = true;
4302 }
4303 }
4304 else
4305 {
4306 __extbuf_ = __extbuf_min_;
4307 __ebs_ = sizeof(__extbuf_min_);
4308 __owns_eb_ = false;
4309 }
4310 if (!__always_noconv_)
4311 {
4312 __ibs_ = max<streamsize>(__n, sizeof(__extbuf_min_));
4313 if (__s && __ibs_ >= sizeof(__extbuf_min_))
4314 {
4315 __intbuf_ = __s;
4316 __owns_ib_ = false;
4317 }
4318 else
4319 {
4320 __intbuf_ = new char_type[__ibs_];
4321 __owns_ib_ = true;
4322 }
4323 }
4324 else
4325 {
4326 __ibs_ = 0;
4327 __intbuf_ = 0;
4328 __owns_ib_ = false;
4329 }
4330 return this;
4331}
4332
4333template <class _Codecvt, class _Elem, class _Tr>
4334typename wbuffer_convert<_Codecvt, _Elem, _Tr>::pos_type
4335wbuffer_convert<_Codecvt, _Elem, _Tr>::seekoff(off_type __off, ios_base::seekdir __way,
4336 ios_base::openmode __om)
4337{
4338 int __width = __cv_->encoding();
4339 if (__cv_ == 0 || __bufptr_ == 0 || (__width <= 0 && __off != 0) || sync())
4340 return pos_type(off_type(-1));
4341 // __width > 0 || __off == 0
4342 switch (__way)
4343 {
4344 case ios_base::beg:
4345 break;
4346 case ios_base::cur:
4347 break;
4348 case ios_base::end:
4349 break;
4350 default:
4351 return pos_type(off_type(-1));
4352 }
4353 pos_type __r = __bufptr_->pubseekoff(__width * __off, __way, __om);
4354 __r.state(__st_);
4355 return __r;
4356}
4357
4358template <class _Codecvt, class _Elem, class _Tr>
4359typename wbuffer_convert<_Codecvt, _Elem, _Tr>::pos_type
4360wbuffer_convert<_Codecvt, _Elem, _Tr>::seekpos(pos_type __sp, ios_base::openmode __wch)
4361{
4362 if (__cv_ == 0 || __bufptr_ == 0 || sync())
4363 return pos_type(off_type(-1));
4364 if (__bufptr_->pubseekpos(__sp, __wch) == pos_type(off_type(-1)))
4365 return pos_type(off_type(-1));
4366 return __sp;
4367}
4368
4369template <class _Codecvt, class _Elem, class _Tr>
4370int
4371wbuffer_convert<_Codecvt, _Elem, _Tr>::sync()
4372{
4373 if (__cv_ == 0 || __bufptr_ == 0)
4374 return 0;
4375 if (__cm_ & ios_base::out)
4376 {
4377 if (this->pptr() != this->pbase())
4378 if (overflow() == traits_type::eof())
4379 return -1;
4380 codecvt_base::result __r;
4381 do
4382 {
4383 char* __extbe;
4384 __r = __cv_->unshift(__st_, __extbuf_, __extbuf_ + __ebs_, __extbe);
4385 streamsize __nmemb = static_cast<streamsize>(__extbe - __extbuf_);
4386 if (__bufptr_->sputn(__extbuf_, __nmemb) != __nmemb)
4387 return -1;
4388 } while (__r == codecvt_base::partial);
4389 if (__r == codecvt_base::error)
4390 return -1;
4391 if (__bufptr_->pubsync())
4392 return -1;
4393 }
4394 else if (__cm_ & ios_base::in)
4395 {
4396 off_type __c;
4397 if (__always_noconv_)
4398 __c = this->egptr() - this->gptr();
4399 else
4400 {
4401 int __width = __cv_->encoding();
4402 __c = __extbufend_ - __extbufnext_;
4403 if (__width > 0)
4404 __c += __width * (this->egptr() - this->gptr());
4405 else
4406 {
4407 if (this->gptr() != this->egptr())
4408 {
4409 reverse(this->gptr(), this->egptr());
4410 codecvt_base::result __r;
4411 const char_type* __e = this->gptr();
4412 char* __extbe;
4413 do
4414 {
4415 __r = __cv_->out(__st_, __e, this->egptr(), __e,
4416 __extbuf_, __extbuf_ + __ebs_, __extbe);
4417 switch (__r)
4418 {
4419 case codecvt_base::noconv:
4420 __c += this->egptr() - this->gptr();
4421 break;
4422 case codecvt_base::ok:
4423 case codecvt_base::partial:
4424 __c += __extbe - __extbuf_;
4425 break;
4426 default:
4427 return -1;
4428 }
4429 } while (__r == codecvt_base::partial);
4430 }
4431 }
4432 }
4433 if (__bufptr_->pubseekoff(-__c, ios_base::cur, __cm_) == pos_type(off_type(-1)))
4434 return -1;
4435 this->setg(0, 0, 0);
4436 __cm_ = 0;
4437 }
4438 return 0;
4439}
4440
4441template <class _Codecvt, class _Elem, class _Tr>
4442bool
4443wbuffer_convert<_Codecvt, _Elem, _Tr>::__read_mode()
4444{
4445 if (!(__cm_ & ios_base::in))
4446 {
4447 this->setp(0, 0);
4448 if (__always_noconv_)
4449 this->setg((char_type*)__extbuf_,
4450 (char_type*)__extbuf_ + __ebs_,
4451 (char_type*)__extbuf_ + __ebs_);
4452 else
4453 this->setg(__intbuf_, __intbuf_ + __ibs_, __intbuf_ + __ibs_);
4454 __cm_ = ios_base::in;
4455 return true;
4456 }
4457 return false;
4458}
4459
4460template <class _Codecvt, class _Elem, class _Tr>
4461void
4462wbuffer_convert<_Codecvt, _Elem, _Tr>::__write_mode()
4463{
4464 if (!(__cm_ & ios_base::out))
4465 {
4466 this->setg(0, 0, 0);
4467 if (__ebs_ > sizeof(__extbuf_min_))
4468 {
4469 if (__always_noconv_)
4470 this->setp((char_type*)__extbuf_,
4471 (char_type*)__extbuf_ + (__ebs_ - 1));
4472 else
4473 this->setp(__intbuf_, __intbuf_ + (__ibs_ - 1));
4474 }
4475 else
4476 this->setp(0, 0);
4477 __cm_ = ios_base::out;
4478 }
4479}
4480
4481template <class _Codecvt, class _Elem, class _Tr>
4482wbuffer_convert<_Codecvt, _Elem, _Tr>*
4483wbuffer_convert<_Codecvt, _Elem, _Tr>::__close()
4484{
4485 wbuffer_convert* __rt = 0;
4486 if (__cv_ != 0 && __bufptr_ != 0)
4487 {
4488 __rt = this;
4489 if ((__cm_ & ios_base::out) && sync())
4490 __rt = 0;
4491 }
4492 return __rt;
Howard Hinnant9dd7e892010-05-31 20:58:54 +00004493}
4494
Howard Hinnantc51e1022010-05-11 19:42:16 +00004495_LIBCPP_END_NAMESPACE_STD
4496
4497#endif // _LIBCPP_LOCALE