blob: a81a63a72e44f767b9a1eb482710ecb521f1616e [file] [log] [blame]
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001// -*- C++ -*-
2//===-------------------------- locale ------------------------------------===//
3//
Howard Hinnantf5256e12010-05-11 21:36:01 +00004// The LLVM Compiler Infrastructure
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005//
Howard Hinnantb64f8b02010-11-16 22:09:02 +00006// This file is dual licensed under the MIT and the University of Illinois Open
7// Source Licenses. See LICENSE.TXT for details.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00008//
9//===----------------------------------------------------------------------===//
10
11#ifndef _LIBCPP_LOCALE
12#define _LIBCPP_LOCALE
13
14/*
15 locale synopsis
16
17namespace std
18{
19
20class locale
21{
22public:
23 // types:
24 class facet;
25 class id;
26
27 typedef int category;
28 static const category // values assigned here are for exposition only
29 none = 0x000,
30 collate = 0x010,
31 ctype = 0x020,
32 monetary = 0x040,
33 numeric = 0x080,
34 time = 0x100,
35 messages = 0x200,
36 all = collate | ctype | monetary | numeric | time | messages;
37
38 // construct/copy/destroy:
Howard Hinnantc9834542011-05-31 15:34:58 +000039 locale() noexcept;
40 locale(const locale& other) noexcept;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000041 explicit locale(const char* std_name);
42 explicit locale(const string& std_name);
43 locale(const locale& other, const char* std_name, category);
44 locale(const locale& other, const string& std_name, category);
45 template <class Facet> locale(const locale& other, Facet* f);
46 locale(const locale& other, const locale& one, category);
47
Howard Hinnantc9834542011-05-31 15:34:58 +000048 ~locale(); // not virtual
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000049
Howard Hinnantc9834542011-05-31 15:34:58 +000050 const locale& operator=(const locale& other) noexcept;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000051
52 template <class Facet> locale combine(const locale& other) const;
53
54 // locale operations:
55 basic_string<char> name() const;
56 bool operator==(const locale& other) const;
57 bool operator!=(const locale& other) const;
58 template <class charT, class Traits, class Allocator>
59 bool operator()(const basic_string<charT,Traits,Allocator>& s1,
60 const basic_string<charT,Traits,Allocator>& s2) const;
61
62 // global locale objects:
63 static locale global(const locale&);
64 static const locale& classic();
65};
66
67template <class Facet> const Facet& use_facet(const locale&);
Howard Hinnantc9834542011-05-31 15:34:58 +000068template <class Facet> bool has_facet(const locale&) noexcept;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000069
70// 22.3.3, convenience interfaces:
71template <class charT> bool isspace (charT c, const locale& loc);
72template <class charT> bool isprint (charT c, const locale& loc);
73template <class charT> bool iscntrl (charT c, const locale& loc);
74template <class charT> bool isupper (charT c, const locale& loc);
75template <class charT> bool islower (charT c, const locale& loc);
76template <class charT> bool isalpha (charT c, const locale& loc);
77template <class charT> bool isdigit (charT c, const locale& loc);
78template <class charT> bool ispunct (charT c, const locale& loc);
79template <class charT> bool isxdigit(charT c, const locale& loc);
80template <class charT> bool isalnum (charT c, const locale& loc);
81template <class charT> bool isgraph (charT c, const locale& loc);
82template <class charT> charT toupper(charT c, const locale& loc);
83template <class charT> charT tolower(charT c, const locale& loc);
Howard Hinnantd23b4642010-05-31 20:58:54 +000084
85template<class Codecvt, class Elem = wchar_t,
86 class Wide_alloc = allocator<Elem>,
87 class Byte_alloc = allocator<char>>
88class wstring_convert
89{
90public:
91 typedef basic_string<char, char_traits<char>, Byte_alloc> byte_string;
92 typedef basic_string<Elem, char_traits<Elem>, Wide_alloc> wide_string;
93 typedef typename Codecvt::state_type state_type;
94 typedef typename wide_string::traits_type::int_type int_type;
95
96 wstring_convert(Codecvt* pcvt = new Codecvt);
97 wstring_convert(Codecvt* pcvt, state_type state);
98 wstring_convert(const byte_string& byte_err,
99 const wide_string& wide_err = wide_string());
100 ~wstring_convert();
101
102 wide_string from_bytes(char byte);
103 wide_string from_bytes(const char* ptr);
104 wide_string from_bytes(const byte_string& str);
105 wide_string from_bytes(const char* first, const char* last);
106
107 byte_string to_bytes(Elem wchar);
108 byte_string to_bytes(const Elem* wptr);
109 byte_string to_bytes(const wide_string& wstr);
110 byte_string to_bytes(const Elem* first, const Elem* last);
111
112 size_t converted() const;
113 state_type state() const;
114};
115
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000116template <class Codecvt, class Elem = wchar_t, class Tr = char_traits<Elem>>
Howard Hinnantd23b4642010-05-31 20:58:54 +0000117class wbuffer_convert
118 : public basic_streambuf<Elem, Tr>
119{
120public:
121 typedef typename Tr::state_type state_type;
122
123 wbuffer_convert(streambuf* bytebuf = 0, Codecvt* pcvt = new Codecvt,
124 state_type state = state_type());
125
126 streambuf* rdbuf() const;
127 streambuf* rdbuf(streambuf* bytebuf);
128
129 state_type state() const;
130};
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000131
132// 22.4.1 and 22.4.1.3, ctype:
133class ctype_base;
134template <class charT> class ctype;
135template <> class ctype<char>; // specialization
136template <class charT> class ctype_byname;
137template <> class ctype_byname<char>; // specialization
138
139class codecvt_base;
140template <class internT, class externT, class stateT> class codecvt;
141template <class internT, class externT, class stateT> class codecvt_byname;
142
143// 22.4.2 and 22.4.3, numeric:
144template <class charT, class InputIterator> class num_get;
145template <class charT, class OutputIterator> class num_put;
146template <class charT> class numpunct;
147template <class charT> class numpunct_byname;
148
149// 22.4.4, col lation:
150template <class charT> class collate;
151template <class charT> class collate_byname;
152
153// 22.4.5, date and time:
154class time_base;
155template <class charT, class InputIterator> class time_get;
156template <class charT, class InputIterator> class time_get_byname;
157template <class charT, class OutputIterator> class time_put;
158template <class charT, class OutputIterator> class time_put_byname;
159
160// 22.4.6, money:
161class money_base;
162template <class charT, class InputIterator> class money_get;
163template <class charT, class OutputIterator> class money_put;
164template <class charT, bool Intl> class moneypunct;
165template <class charT, bool Intl> class moneypunct_byname;
166
167// 22.4.7, message retrieval:
168class messages_base;
169template <class charT> class messages;
170template <class charT> class messages_byname;
171
172} // std
173
174*/
175
176#include <__config>
177#include <__locale>
178#include <algorithm>
179#include <memory>
180#include <ios>
181#include <streambuf>
182#include <iterator>
183#include <limits>
Howard Hinnantadff4892010-05-24 17:49:41 +0000184#if !__APPLE__
185#include <cstdarg>
186#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000187#include <cstdlib>
188#include <ctime>
Howard Hinnant6cd05ee2011-09-23 16:11:27 +0000189#if _WIN32
Howard Hinnant14fa9f92011-09-29 20:33:10 +0000190#include <support/win32/locale_win32.h>
Howard Hinnant6cd05ee2011-09-23 16:11:27 +0000191#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000192#include <nl_types.h>
Howard Hinnant92a07002011-09-22 19:10:18 +0000193#endif // !_WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000194
Howard Hinnant66c6f972011-11-29 16:45:27 +0000195#include <__undef_min_max>
196
Howard Hinnant08e17472011-10-17 20:05:10 +0000197#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000198#pragma GCC system_header
Howard Hinnant08e17472011-10-17 20:05:10 +0000199#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000200
201_LIBCPP_BEGIN_NAMESPACE_STD
202
Howard Hinnant866569b2011-09-28 23:39:33 +0000203#if __APPLE__ || __FreeBSD__
Howard Hinnant2ea1ca92011-09-28 21:05:01 +0000204# define _LIBCPP_GET_C_LOCALE 0
205#else
206# define _LIBCPP_GET_C_LOCALE __cloc()
Howard Hinnant866569b2011-09-28 23:39:33 +0000207 // Get the C locale object
208 locale_t __cloc();
209#define __cloc_defined
Howard Hinnant2ea1ca92011-09-28 21:05:01 +0000210#endif
211
Sean Huntf3907e62011-07-15 05:40:33 +0000212typedef _VSTD::remove_pointer<locale_t>::type __locale_struct;
213typedef _VSTD::unique_ptr<__locale_struct, decltype(&freelocale)> __locale_unique_ptr;
214typedef _VSTD::unique_ptr<__locale_struct, decltype(&uselocale)> __locale_raii;
215
Howard Hinnantadff4892010-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 Hinnant866569b2011-09-28 23:39:33 +0000219#ifdef __linux__
Sean Huntf3907e62011-07-15 05:40:33 +0000220
221#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
222decltype(MB_CUR_MAX_L(_VSTD::declval<locale_t>()))
Howard Hinnant82894812010-09-22 16:48:34 +0000223inline _LIBCPP_INLINE_VISIBILITY
Sean Huntf3907e62011-07-15 05:40:33 +0000224__mb_cur_max_l(locale_t __l)
Howard Hinnantadff4892010-05-24 17:49:41 +0000225{
Sean Huntf3907e62011-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 Hinnant866569b2011-09-28 23:39:33 +0000240#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-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
Sean Huntc97da3a2011-07-13 06:40:50 +0000246}
Howard Hinnant8d756322011-07-13 15:48:16 +0000247
Sean Huntf3907e62011-07-15 05:40:33 +0000248_LIBCPP_ALWAYS_INLINE inline
249int __wctob_l(wint_t __c, locale_t __l)
Sean Huntc97da3a2011-07-13 06:40:50 +0000250{
Sean Huntf3907e62011-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
Sean Huntc97da3a2011-07-13 06:40:50 +0000257}
Sean Huntf3907e62011-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 Chisnallc512df12011-09-21 08:39:44 +0000287 return mbsnrtowcs_l(__dest, __src, __nms, __len, __ps, __l);
Sean Huntf3907e62011-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 Chisnallc512df12011-09-21 08:39:44 +0000310 return mbtowc_l(__pwc, __pmb, __max, __l);
Sean Huntf3907e62011-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 Hinnant866569b2011-09-28 23:39:33 +0000407#endif // __linux__
Howard Hinnantadff4892010-05-24 17:49:41 +0000408
Howard Hinnantbc8d3f92010-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 Hinnantec3773c2011-12-01 20:21:04 +0000436 size_t __nkw = static_cast<size_t>(_VSTD::distance(__kb, __ke));
Howard Hinnantbc8d3f92010-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 Hinnantbc8d3f92010-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 Hinnant80586722011-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 Hinnantec3773c2011-12-01 20:21:04 +0000601 if (__grouping.size() != 0 && __ct == __thousands_sep)
Howard Hinnantbc8d3f92010-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 Hinnant80586722011-03-09 01:03:19 +0000611 if (__f >= 24)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000612 return -1;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000613 switch (__base)
614 {
615 case 8:
616 case 10:
617 if (__f >= __base)
Howard Hinnant80586722011-03-09 01:03:19 +0000618 return -1;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000619 break;
Howard Hinnant80586722011-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 Hinnantbc8d3f92010-05-11 19:42:16 +0000627 return 0;
Howard Hinnant80586722011-03-09 01:03:19 +0000628 }
629 return -1;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000630 }
Howard Hinnant80586722011-03-09 01:03:19 +0000631 if (__a_end-__a < __num_get_buf_sz - 1)
632 *__a_end++ = __src[__f];
Howard Hinnantbc8d3f92010-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];
668 if (__a_end-__a < __num_get_buf_sz - 1)
669 *__a_end++ = __x;
670 if (__x == 'x' || __x == 'X')
671 __exp = 'P';
672 else if ((__x & 0xDF) == __exp)
673 {
674 __in_units = false;
675 if (__grouping.size() != 0 && __g_end-__g < __num_get_buf_sz)
676 *__g_end++ = __dc;
677 }
678 if (__f >= 22)
679 return 0;
680 ++__dc;
681 return 0;
682}
683
Howard Hinnantec3773c2011-12-01 20:21:04 +0000684extern template struct __num_get<char>;
685extern template struct __num_get<wchar_t>;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000686
687template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +0000688class _LIBCPP_VISIBLE num_get
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000689 : public locale::facet,
690 private __num_get<_CharT>
691{
692public:
693 typedef _CharT char_type;
694 typedef _InputIterator iter_type;
695
696 _LIBCPP_ALWAYS_INLINE
697 explicit num_get(size_t __refs = 0)
698 : locale::facet(__refs) {}
699
700 _LIBCPP_ALWAYS_INLINE
701 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
702 ios_base::iostate& __err, bool& __v) const
703 {
704 return do_get(__b, __e, __iob, __err, __v);
705 }
706
707 _LIBCPP_ALWAYS_INLINE
708 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
709 ios_base::iostate& __err, long& __v) const
710 {
711 return do_get(__b, __e, __iob, __err, __v);
712 }
713
714 _LIBCPP_ALWAYS_INLINE
715 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
716 ios_base::iostate& __err, long long& __v) const
717 {
718 return do_get(__b, __e, __iob, __err, __v);
719 }
720
721 _LIBCPP_ALWAYS_INLINE
722 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
723 ios_base::iostate& __err, unsigned short& __v) const
724 {
725 return do_get(__b, __e, __iob, __err, __v);
726 }
727
728 _LIBCPP_ALWAYS_INLINE
729 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
730 ios_base::iostate& __err, unsigned int& __v) const
731 {
732 return do_get(__b, __e, __iob, __err, __v);
733 }
734
735 _LIBCPP_ALWAYS_INLINE
736 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
737 ios_base::iostate& __err, unsigned long& __v) const
738 {
739 return do_get(__b, __e, __iob, __err, __v);
740 }
741
742 _LIBCPP_ALWAYS_INLINE
743 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
744 ios_base::iostate& __err, unsigned long long& __v) const
745 {
746 return do_get(__b, __e, __iob, __err, __v);
747 }
748
749 _LIBCPP_ALWAYS_INLINE
750 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
751 ios_base::iostate& __err, float& __v) const
752 {
753 return do_get(__b, __e, __iob, __err, __v);
754 }
755
756 _LIBCPP_ALWAYS_INLINE
757 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
758 ios_base::iostate& __err, double& __v) const
759 {
760 return do_get(__b, __e, __iob, __err, __v);
761 }
762
763 _LIBCPP_ALWAYS_INLINE
764 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
765 ios_base::iostate& __err, long double& __v) const
766 {
767 return do_get(__b, __e, __iob, __err, __v);
768 }
769
770 _LIBCPP_ALWAYS_INLINE
771 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
772 ios_base::iostate& __err, void*& __v) const
773 {
774 return do_get(__b, __e, __iob, __err, __v);
775 }
776
777 static locale::id id;
778
779protected:
Howard Hinnant82894812010-09-22 16:48:34 +0000780 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000781 ~num_get() {}
782
783 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
784 ios_base::iostate& __err, bool& __v) const;
785 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
786 ios_base::iostate& __err, long& __v) const;
787 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
788 ios_base::iostate& __err, long long& __v) const;
789 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
790 ios_base::iostate& __err, unsigned short& __v) const;
791 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
792 ios_base::iostate& __err, unsigned int& __v) const;
793 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
794 ios_base::iostate& __err, unsigned long& __v) const;
795 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
796 ios_base::iostate& __err, unsigned long long& __v) const;
797 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
798 ios_base::iostate& __err, float& __v) const;
799 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
800 ios_base::iostate& __err, double& __v) const;
801 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
802 ios_base::iostate& __err, long double& __v) const;
803 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
804 ios_base::iostate& __err, void*& __v) const;
805};
806
807template <class _CharT, class _InputIterator>
808locale::id
809num_get<_CharT, _InputIterator>::id;
810
811template <class _Tp>
812_Tp
813__num_get_signed_integral(const char* __a, const char* __a_end,
814 ios_base::iostate& __err, int __base)
815{
816 if (__a != __a_end)
817 {
Howard Hinnante7c8da62011-02-25 19:52:41 +0000818 int __save_errno = errno;
819 errno = 0;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000820 char *__p2;
Howard Hinnant2ea1ca92011-09-28 21:05:01 +0000821 long long __ll = strtoll_l(__a, &__p2, __base, _LIBCPP_GET_C_LOCALE);
Howard Hinnante7c8da62011-02-25 19:52:41 +0000822 int __current_errno = errno;
823 if (__current_errno == 0)
824 errno = __save_errno;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000825 if (__p2 != __a_end)
826 {
827 __err = ios_base::failbit;
828 return 0;
829 }
Howard Hinnante7c8da62011-02-25 19:52:41 +0000830 else if (__current_errno == ERANGE ||
831 __ll < numeric_limits<_Tp>::min() ||
832 numeric_limits<_Tp>::max() < __ll)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000833 {
834 __err = ios_base::failbit;
Howard Hinnante7c8da62011-02-25 19:52:41 +0000835 if (__ll > 0)
836 return numeric_limits<_Tp>::max();
837 else
838 return numeric_limits<_Tp>::min();
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000839 }
840 return static_cast<_Tp>(__ll);
841 }
842 __err = ios_base::failbit;
843 return 0;
844}
845
846template <class _Tp>
847_Tp
848__num_get_unsigned_integral(const char* __a, const char* __a_end,
849 ios_base::iostate& __err, int __base)
850{
851 if (__a != __a_end)
852 {
Howard Hinnante7c8da62011-02-25 19:52:41 +0000853 if (*__a == '-')
854 {
855 __err = ios_base::failbit;
856 return 0;
857 }
858 int __save_errno = errno;
859 errno = 0;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000860 char *__p2;
Howard Hinnant2ea1ca92011-09-28 21:05:01 +0000861 unsigned long long __ll = strtoull_l(__a, &__p2, __base, _LIBCPP_GET_C_LOCALE);
Howard Hinnante7c8da62011-02-25 19:52:41 +0000862 int __current_errno = errno;
863 if (__current_errno == 0)
864 errno = __save_errno;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000865 if (__p2 != __a_end)
866 {
867 __err = ios_base::failbit;
868 return 0;
869 }
Howard Hinnante7c8da62011-02-25 19:52:41 +0000870 else if (__current_errno == ERANGE ||
871 numeric_limits<_Tp>::max() < __ll)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000872 {
873 __err = ios_base::failbit;
874 return numeric_limits<_Tp>::max();
875 }
876 return static_cast<_Tp>(__ll);
877 }
878 __err = ios_base::failbit;
879 return 0;
880}
881
882template <class _Tp>
883_Tp
884__num_get_float(const char* __a, const char* __a_end, ios_base::iostate& __err)
885{
886 if (__a != __a_end)
887 {
888 char *__p2;
Howard Hinnant2ea1ca92011-09-28 21:05:01 +0000889 long double __ld = strtold_l(__a, &__p2, _LIBCPP_GET_C_LOCALE);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000890 if (__p2 != __a_end)
891 {
892 __err = ios_base::failbit;
893 return 0;
894 }
895 return static_cast<_Tp>(__ld);
896 }
897 __err = ios_base::failbit;
898 return 0;
899}
900
901template <class _CharT, class _InputIterator>
902_InputIterator
903num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
904 ios_base& __iob,
905 ios_base::iostate& __err,
906 bool& __v) const
907{
908 if ((__iob.flags() & ios_base::boolalpha) == 0)
909 {
910 long __lv = -1;
911 __b = do_get(__b, __e, __iob, __err, __lv);
912 switch (__lv)
913 {
914 case 0:
915 __v = false;
916 break;
917 case 1:
918 __v = true;
919 break;
920 default:
921 __v = true;
922 __err = ios_base::failbit;
923 break;
924 }
925 return __b;
926 }
927 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__iob.getloc());
928 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__iob.getloc());
929 typedef typename numpunct<_CharT>::string_type string_type;
930 const string_type __names[2] = {__np.truename(), __np.falsename()};
931 const string_type* __i = __scan_keyword(__b, __e, __names, __names+2,
932 __ct, __err);
933 __v = __i == __names;
934 return __b;
935}
936
937template <class _CharT, class _InputIterator>
938_InputIterator
939num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
940 ios_base& __iob,
941 ios_base::iostate& __err,
942 long& __v) const
943{
944 // Stage 1
945 int __base = this->__get_base(__iob);
946 // Stage 2
947 char_type __atoms[26];
948 char_type __thousands_sep;
949 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
950 char __a[__num_get_base::__num_get_buf_sz] = {0};
951 char* __a_end = __a;
952 unsigned __g[__num_get_base::__num_get_buf_sz];
953 unsigned* __g_end = __g;
954 unsigned __dc = 0;
955 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +0000956 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000957 __thousands_sep, __grouping, __g, __g_end,
958 __atoms))
959 break;
960 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
961 *__g_end++ = __dc;
962 // Stage 3
963 __v = __num_get_signed_integral<long>(__a, __a_end, __err, __base);
964 // Digit grouping checked
965 __check_grouping(__grouping, __g, __g_end, __err);
966 // EOF checked
967 if (__b == __e)
968 __err |= ios_base::eofbit;
969 return __b;
970}
971
972template <class _CharT, class _InputIterator>
973_InputIterator
974num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
975 ios_base& __iob,
976 ios_base::iostate& __err,
977 long long& __v) const
978{
979 // Stage 1
980 int __base = this->__get_base(__iob);
981 // Stage 2
982 char_type __atoms[26];
983 char_type __thousands_sep;
984 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
985 char __a[__num_get_base::__num_get_buf_sz] = {0};
986 char* __a_end = __a;
987 unsigned __g[__num_get_base::__num_get_buf_sz];
988 unsigned* __g_end = __g;
989 unsigned __dc = 0;
990 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +0000991 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
992 __thousands_sep, __grouping, __g, __g_end,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000993 __atoms))
994 break;
995 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
996 *__g_end++ = __dc;
997 // Stage 3
998 __v = __num_get_signed_integral<long long>(__a, __a_end, __err, __base);
999 // Digit grouping checked
1000 __check_grouping(__grouping, __g, __g_end, __err);
1001 // EOF checked
1002 if (__b == __e)
1003 __err |= ios_base::eofbit;
1004 return __b;
1005}
1006
1007template <class _CharT, class _InputIterator>
1008_InputIterator
1009num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1010 ios_base& __iob,
1011 ios_base::iostate& __err,
1012 unsigned short& __v) const
1013{
1014 // Stage 1
1015 int __base = this->__get_base(__iob);
1016 // Stage 2
1017 char_type __atoms[26];
1018 char_type __thousands_sep;
1019 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
1020 char __a[__num_get_base::__num_get_buf_sz] = {0};
1021 char* __a_end = __a;
1022 unsigned __g[__num_get_base::__num_get_buf_sz];
1023 unsigned* __g_end = __g;
1024 unsigned __dc = 0;
1025 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001026 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001027 __thousands_sep, __grouping, __g, __g_end,
1028 __atoms))
1029 break;
1030 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
1031 *__g_end++ = __dc;
1032 // Stage 3
1033 __v = __num_get_unsigned_integral<unsigned short>(__a, __a_end, __err, __base);
1034 // Digit grouping checked
1035 __check_grouping(__grouping, __g, __g_end, __err);
1036 // EOF checked
1037 if (__b == __e)
1038 __err |= ios_base::eofbit;
1039 return __b;
1040}
1041
1042template <class _CharT, class _InputIterator>
1043_InputIterator
1044num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1045 ios_base& __iob,
1046 ios_base::iostate& __err,
1047 unsigned int& __v) const
1048{
1049 // Stage 1
1050 int __base = this->__get_base(__iob);
1051 // Stage 2
1052 char_type __atoms[26];
1053 char_type __thousands_sep;
1054 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
1055 char __a[__num_get_base::__num_get_buf_sz] = {0};
1056 char* __a_end = __a;
1057 unsigned __g[__num_get_base::__num_get_buf_sz];
1058 unsigned* __g_end = __g;
1059 unsigned __dc = 0;
1060 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001061 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001062 __thousands_sep, __grouping, __g, __g_end,
1063 __atoms))
1064 break;
1065 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
1066 *__g_end++ = __dc;
1067 // Stage 3
1068 __v = __num_get_unsigned_integral<unsigned int>(__a, __a_end, __err, __base);
1069 // Digit grouping checked
1070 __check_grouping(__grouping, __g, __g_end, __err);
1071 // EOF checked
1072 if (__b == __e)
1073 __err |= ios_base::eofbit;
1074 return __b;
1075}
1076
1077template <class _CharT, class _InputIterator>
1078_InputIterator
1079num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1080 ios_base& __iob,
1081 ios_base::iostate& __err,
1082 unsigned long& __v) const
1083{
1084 // Stage 1
1085 int __base = this->__get_base(__iob);
1086 // Stage 2
1087 char_type __atoms[26];
1088 char_type __thousands_sep;
1089 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
1090 char __a[__num_get_base::__num_get_buf_sz] = {0};
1091 char* __a_end = __a;
1092 unsigned __g[__num_get_base::__num_get_buf_sz];
1093 unsigned* __g_end = __g;
1094 unsigned __dc = 0;
1095 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001096 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001097 __thousands_sep, __grouping, __g, __g_end,
1098 __atoms))
1099 break;
1100 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
1101 *__g_end++ = __dc;
1102 // Stage 3
1103 __v = __num_get_unsigned_integral<unsigned long>(__a, __a_end, __err, __base);
1104 // Digit grouping checked
1105 __check_grouping(__grouping, __g, __g_end, __err);
1106 // EOF checked
1107 if (__b == __e)
1108 __err |= ios_base::eofbit;
1109 return __b;
1110}
1111
1112template <class _CharT, class _InputIterator>
1113_InputIterator
1114num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1115 ios_base& __iob,
1116 ios_base::iostate& __err,
1117 unsigned long long& __v) const
1118{
1119 // Stage 1
1120 int __base = this->__get_base(__iob);
1121 // Stage 2
1122 char_type __atoms[26];
1123 char_type __thousands_sep;
1124 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
1125 char __a[__num_get_base::__num_get_buf_sz] = {0};
1126 char* __a_end = __a;
1127 unsigned __g[__num_get_base::__num_get_buf_sz];
1128 unsigned* __g_end = __g;
1129 unsigned __dc = 0;
1130 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001131 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001132 __thousands_sep, __grouping, __g, __g_end,
1133 __atoms))
1134 break;
1135 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
1136 *__g_end++ = __dc;
1137 // Stage 3
1138 __v = __num_get_unsigned_integral<unsigned long long>(__a, __a_end, __err, __base);
1139 // Digit grouping checked
1140 __check_grouping(__grouping, __g, __g_end, __err);
1141 // EOF checked
1142 if (__b == __e)
1143 __err |= ios_base::eofbit;
1144 return __b;
1145}
1146
1147template <class _CharT, class _InputIterator>
1148_InputIterator
1149num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1150 ios_base& __iob,
1151 ios_base::iostate& __err,
1152 float& __v) const
1153{
1154 // Stage 1, nothing to do
1155 // Stage 2
1156 char_type __atoms[32];
1157 char_type __decimal_point;
1158 char_type __thousands_sep;
Howard Hinnant324bb032010-08-22 00:02:43 +00001159 string __grouping = this->__stage2_float_prep(__iob, __atoms,
1160 __decimal_point,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001161 __thousands_sep);
1162 char __a[__num_get_base::__num_get_buf_sz] = {0};
1163 char* __a_end = __a;
1164 unsigned __g[__num_get_base::__num_get_buf_sz];
1165 unsigned* __g_end = __g;
1166 unsigned __dc = 0;
1167 bool __in_units = true;
1168 char __exp = 'E';
1169 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001170 if (this->__stage2_float_loop(*__b, __in_units, __exp, __a, __a_end,
1171 __decimal_point, __thousands_sep,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001172 __grouping, __g, __g_end,
1173 __dc, __atoms))
1174 break;
1175 if (__grouping.size() != 0 && __in_units && __g_end-__g < __num_get_base::__num_get_buf_sz)
1176 *__g_end++ = __dc;
1177 // Stage 3
1178 __v = __num_get_float<float>(__a, __a_end, __err);
1179 // Digit grouping checked
1180 __check_grouping(__grouping, __g, __g_end, __err);
1181 // EOF checked
1182 if (__b == __e)
1183 __err |= ios_base::eofbit;
1184 return __b;
1185}
1186
1187template <class _CharT, class _InputIterator>
1188_InputIterator
1189num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1190 ios_base& __iob,
1191 ios_base::iostate& __err,
1192 double& __v) const
1193{
1194 // Stage 1, nothing to do
1195 // Stage 2
1196 char_type __atoms[32];
1197 char_type __decimal_point;
1198 char_type __thousands_sep;
Howard Hinnant324bb032010-08-22 00:02:43 +00001199 string __grouping = this->__stage2_float_prep(__iob, __atoms,
1200 __decimal_point,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001201 __thousands_sep);
1202 char __a[__num_get_base::__num_get_buf_sz] = {0};
1203 char* __a_end = __a;
1204 unsigned __g[__num_get_base::__num_get_buf_sz];
1205 unsigned* __g_end = __g;
1206 unsigned __dc = 0;
1207 bool __in_units = true;
1208 char __exp = 'E';
1209 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001210 if (this->__stage2_float_loop(*__b, __in_units, __exp, __a, __a_end,
1211 __decimal_point, __thousands_sep,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001212 __grouping, __g, __g_end,
1213 __dc, __atoms))
1214 break;
1215 if (__grouping.size() != 0 && __in_units && __g_end-__g < __num_get_base::__num_get_buf_sz)
1216 *__g_end++ = __dc;
1217 // Stage 3
1218 __v = __num_get_float<double>(__a, __a_end, __err);
1219 // Digit grouping checked
1220 __check_grouping(__grouping, __g, __g_end, __err);
1221 // EOF checked
1222 if (__b == __e)
1223 __err |= ios_base::eofbit;
1224 return __b;
1225}
1226
1227template <class _CharT, class _InputIterator>
1228_InputIterator
1229num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1230 ios_base& __iob,
1231 ios_base::iostate& __err,
1232 long double& __v) const
1233{
1234 // Stage 1, nothing to do
1235 // Stage 2
1236 char_type __atoms[32];
1237 char_type __decimal_point;
1238 char_type __thousands_sep;
Howard Hinnant324bb032010-08-22 00:02:43 +00001239 string __grouping = this->__stage2_float_prep(__iob, __atoms,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001240 __decimal_point,
1241 __thousands_sep);
1242 char __a[__num_get_base::__num_get_buf_sz] = {0};
1243 char* __a_end = __a;
1244 unsigned __g[__num_get_base::__num_get_buf_sz];
1245 unsigned* __g_end = __g;
1246 unsigned __dc = 0;
1247 bool __in_units = true;
1248 char __exp = 'E';
1249 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001250 if (this->__stage2_float_loop(*__b, __in_units, __exp, __a, __a_end,
1251 __decimal_point, __thousands_sep,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001252 __grouping, __g, __g_end,
1253 __dc, __atoms))
1254 break;
1255 if (__grouping.size() != 0 && __in_units && __g_end-__g < __num_get_base::__num_get_buf_sz)
1256 *__g_end++ = __dc;
1257 // Stage 3
1258 __v = __num_get_float<long double>(__a, __a_end, __err);
1259 // Digit grouping checked
1260 __check_grouping(__grouping, __g, __g_end, __err);
1261 // EOF checked
1262 if (__b == __e)
1263 __err |= ios_base::eofbit;
1264 return __b;
1265}
1266
1267template <class _CharT, class _InputIterator>
1268_InputIterator
1269num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1270 ios_base& __iob,
1271 ios_base::iostate& __err,
1272 void*& __v) const
1273{
1274 // Stage 1
1275 int __base = 16;
1276 // Stage 2
1277 char_type __atoms[26];
Howard Hinnantec3773c2011-12-01 20:21:04 +00001278 char_type __thousands_sep = 0;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001279 string __grouping;
1280 use_facet<ctype<_CharT> >(__iob.getloc()).widen(__num_get_base::__src,
1281 __num_get_base::__src + 26, __atoms);
1282 char __a[__num_get_base::__num_get_buf_sz] = {0};
1283 char* __a_end = __a;
1284 unsigned __g[__num_get_base::__num_get_buf_sz];
1285 unsigned* __g_end = __g;
1286 unsigned __dc = 0;
1287 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001288 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
1289 __thousands_sep, __grouping,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001290 __g, __g_end, __atoms))
1291 break;
1292 // Stage 3
1293 __a[sizeof(__a)-1] = 0;
Howard Hinnant866569b2011-09-28 23:39:33 +00001294#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001295 if (sscanf_l(__a, _LIBCPP_GET_C_LOCALE, "%p", &__v) != 1)
Sean Huntf3907e62011-07-15 05:40:33 +00001296#else
1297 if (__sscanf_l(__a, __cloc(), "%p", &__v) != 1)
1298#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001299 __err = ios_base::failbit;
1300 // EOF checked
1301 if (__b == __e)
1302 __err |= ios_base::eofbit;
1303 return __b;
1304}
1305
1306extern template class num_get<char>;
1307extern template class num_get<wchar_t>;
1308
1309struct __num_put_base
1310{
1311protected:
1312 static void __format_int(char* __fmt, const char* __len, bool __signd,
1313 ios_base::fmtflags __flags);
1314 static bool __format_float(char* __fmt, const char* __len,
1315 ios_base::fmtflags __flags);
1316 static char* __identify_padding(char* __nb, char* __ne,
1317 const ios_base& __iob);
1318};
1319
1320template <class _CharT>
1321struct __num_put
1322 : protected __num_put_base
1323{
1324 static void __widen_and_group_int(char* __nb, char* __np, char* __ne,
1325 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1326 const locale& __loc);
1327 static void __widen_and_group_float(char* __nb, char* __np, char* __ne,
1328 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1329 const locale& __loc);
1330};
1331
1332template <class _CharT>
1333void
1334__num_put<_CharT>::__widen_and_group_int(char* __nb, char* __np, char* __ne,
1335 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1336 const locale& __loc)
1337{
1338 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> > (__loc);
1339 const numpunct<_CharT>& __npt = use_facet<numpunct<_CharT> >(__loc);
1340 string __grouping = __npt.grouping();
1341 if (__grouping.empty())
1342 {
1343 __ct.widen(__nb, __ne, __ob);
1344 __oe = __ob + (__ne - __nb);
1345 }
1346 else
1347 {
1348 __oe = __ob;
1349 char* __nf = __nb;
1350 if (*__nf == '-' || *__nf == '+')
1351 *__oe++ = __ct.widen(*__nf++);
1352 if (__ne - __nf >= 2 && __nf[0] == '0' && (__nf[1] == 'x' ||
1353 __nf[1] == 'X'))
1354 {
1355 *__oe++ = __ct.widen(*__nf++);
1356 *__oe++ = __ct.widen(*__nf++);
1357 }
1358 reverse(__nf, __ne);
1359 _CharT __thousands_sep = __npt.thousands_sep();
1360 unsigned __dc = 0;
1361 unsigned __dg = 0;
1362 for (char* __p = __nf; __p < __ne; ++__p)
1363 {
1364 if (static_cast<unsigned>(__grouping[__dg]) > 0 &&
1365 __dc == static_cast<unsigned>(__grouping[__dg]))
1366 {
1367 *__oe++ = __thousands_sep;
1368 __dc = 0;
1369 if (__dg < __grouping.size()-1)
1370 ++__dg;
1371 }
1372 *__oe++ = __ct.widen(*__p);
1373 ++__dc;
1374 }
1375 reverse(__ob + (__nf - __nb), __oe);
1376 }
1377 if (__np == __ne)
1378 __op = __oe;
1379 else
1380 __op = __ob + (__np - __nb);
1381}
1382
1383template <class _CharT>
1384void
1385__num_put<_CharT>::__widen_and_group_float(char* __nb, char* __np, char* __ne,
1386 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1387 const locale& __loc)
1388{
1389 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> > (__loc);
1390 const numpunct<_CharT>& __npt = use_facet<numpunct<_CharT> >(__loc);
1391 string __grouping = __npt.grouping();
1392 __oe = __ob;
1393 char* __nf = __nb;
1394 if (*__nf == '-' || *__nf == '+')
1395 *__oe++ = __ct.widen(*__nf++);
1396 char* __ns;
1397 if (__ne - __nf >= 2 && __nf[0] == '0' && (__nf[1] == 'x' ||
1398 __nf[1] == 'X'))
1399 {
1400 *__oe++ = __ct.widen(*__nf++);
1401 *__oe++ = __ct.widen(*__nf++);
1402 for (__ns = __nf; __ns < __ne; ++__ns)
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001403 if (!isxdigit_l(*__ns, _LIBCPP_GET_C_LOCALE))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001404 break;
1405 }
1406 else
1407 {
1408 for (__ns = __nf; __ns < __ne; ++__ns)
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001409 if (!isdigit_l(*__ns, _LIBCPP_GET_C_LOCALE))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001410 break;
1411 }
1412 if (__grouping.empty())
1413 {
1414 __ct.widen(__nf, __ns, __oe);
1415 __oe += __ns - __nf;
1416 }
1417 else
1418 {
1419 reverse(__nf, __ns);
1420 _CharT __thousands_sep = __npt.thousands_sep();
1421 unsigned __dc = 0;
1422 unsigned __dg = 0;
1423 for (char* __p = __nf; __p < __ns; ++__p)
1424 {
1425 if (__grouping[__dg] > 0 && __dc == static_cast<unsigned>(__grouping[__dg]))
1426 {
1427 *__oe++ = __thousands_sep;
1428 __dc = 0;
1429 if (__dg < __grouping.size()-1)
1430 ++__dg;
1431 }
1432 *__oe++ = __ct.widen(*__p);
1433 ++__dc;
1434 }
1435 reverse(__ob + (__nf - __nb), __oe);
1436 }
1437 for (__nf = __ns; __nf < __ne; ++__nf)
1438 {
1439 if (*__nf == '.')
1440 {
1441 *__oe++ = __npt.decimal_point();
1442 ++__nf;
1443 break;
1444 }
1445 else
1446 *__oe++ = __ct.widen(*__nf);
1447 }
1448 __ct.widen(__nf, __ne, __oe);
1449 __oe += __ne - __nf;
1450 if (__np == __ne)
1451 __op = __oe;
1452 else
1453 __op = __ob + (__np - __nb);
1454}
1455
Howard Hinnantec3773c2011-12-01 20:21:04 +00001456extern template struct __num_put<char>;
1457extern template struct __num_put<wchar_t>;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001458
1459template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00001460class _LIBCPP_VISIBLE num_put
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001461 : public locale::facet,
1462 private __num_put<_CharT>
1463{
1464public:
1465 typedef _CharT char_type;
1466 typedef _OutputIterator iter_type;
1467
1468 _LIBCPP_ALWAYS_INLINE
1469 explicit num_put(size_t __refs = 0)
1470 : locale::facet(__refs) {}
1471
1472 _LIBCPP_ALWAYS_INLINE
1473 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1474 bool __v) const
1475 {
1476 return do_put(__s, __iob, __fl, __v);
1477 }
1478
1479 _LIBCPP_ALWAYS_INLINE
1480 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1481 long __v) const
1482 {
1483 return do_put(__s, __iob, __fl, __v);
1484 }
1485
1486 _LIBCPP_ALWAYS_INLINE
1487 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1488 long long __v) const
1489 {
1490 return do_put(__s, __iob, __fl, __v);
1491 }
1492
1493 _LIBCPP_ALWAYS_INLINE
1494 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1495 unsigned long __v) const
1496 {
1497 return do_put(__s, __iob, __fl, __v);
1498 }
1499
1500 _LIBCPP_ALWAYS_INLINE
1501 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1502 unsigned long long __v) const
1503 {
1504 return do_put(__s, __iob, __fl, __v);
1505 }
1506
1507 _LIBCPP_ALWAYS_INLINE
1508 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1509 double __v) const
1510 {
1511 return do_put(__s, __iob, __fl, __v);
1512 }
1513
1514 _LIBCPP_ALWAYS_INLINE
1515 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1516 long double __v) const
1517 {
1518 return do_put(__s, __iob, __fl, __v);
1519 }
1520
1521 _LIBCPP_ALWAYS_INLINE
1522 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1523 const void* __v) const
1524 {
1525 return do_put(__s, __iob, __fl, __v);
1526 }
1527
1528 static locale::id id;
1529
1530protected:
Howard Hinnant82894812010-09-22 16:48:34 +00001531 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001532 ~num_put() {}
1533
1534 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1535 bool __v) const;
1536 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1537 long __v) const;
1538 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1539 long long __v) const;
1540 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1541 unsigned long) const;
1542 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1543 unsigned long long) const;
1544 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1545 double __v) const;
1546 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1547 long double __v) const;
1548 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1549 const void* __v) const;
1550};
1551
1552template <class _CharT, class _OutputIterator>
1553locale::id
1554num_put<_CharT, _OutputIterator>::id;
1555
1556template <class _CharT, class _OutputIterator>
1557_LIBCPP_HIDDEN
1558_OutputIterator
1559__pad_and_output(_OutputIterator __s,
1560 const _CharT* __ob, const _CharT* __op, const _CharT* __oe,
1561 ios_base& __iob, _CharT __fl)
1562{
1563 streamsize __sz = __oe - __ob;
1564 streamsize __ns = __iob.width();
1565 if (__ns > __sz)
1566 __ns -= __sz;
1567 else
1568 __ns = 0;
1569 for (;__ob < __op; ++__ob, ++__s)
1570 *__s = *__ob;
1571 for (; __ns; --__ns, ++__s)
1572 *__s = __fl;
1573 for (; __ob < __oe; ++__ob, ++__s)
1574 *__s = *__ob;
1575 __iob.width(0);
1576 return __s;
1577}
1578
1579template <class _CharT, class _OutputIterator>
1580_OutputIterator
1581num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1582 char_type __fl, bool __v) const
1583{
1584 if ((__iob.flags() & ios_base::boolalpha) == 0)
1585 return do_put(__s, __iob, __fl, (unsigned long)__v);
1586 const numpunct<char_type>& __np = use_facet<numpunct<char_type> >(__iob.getloc());
1587 typedef typename numpunct<char_type>::string_type string_type;
1588 string_type __nm = __v ? __np.truename() : __np.falsename();
1589 for (typename string_type::iterator __i = __nm.begin(); __i != __nm.end(); ++__i, ++__s)
1590 *__s = *__i;
1591 return __s;
1592}
1593
1594template <class _CharT, class _OutputIterator>
1595_OutputIterator
1596num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1597 char_type __fl, long __v) const
1598{
1599 // Stage 1 - Get number in narrow char
1600 char __fmt[6] = {'%', 0};
1601 const char* __len = "l";
1602 this->__format_int(__fmt+1, __len, true, __iob.flags());
1603 const unsigned __nbuf = (numeric_limits<long>::digits / 3)
1604 + ((numeric_limits<long>::digits % 3) != 0)
1605 + 1;
1606 char __nar[__nbuf];
Howard Hinnant866569b2011-09-28 23:39:33 +00001607#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001608 int __nc = sprintf_l(__nar, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001609#else
1610 int __nc = __sprintf_l(__nar, __cloc(), __fmt, __v);
1611#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001612 char* __ne = __nar + __nc;
1613 char* __np = this->__identify_padding(__nar, __ne, __iob);
1614 // Stage 2 - Widen __nar while adding thousands separators
1615 char_type __o[2*(__nbuf-1) - 1];
1616 char_type* __op; // pad here
1617 char_type* __oe; // end of output
1618 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1619 // [__o, __oe) contains thousands_sep'd wide number
1620 // Stage 3 & 4
1621 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1622}
1623
1624template <class _CharT, class _OutputIterator>
1625_OutputIterator
1626num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1627 char_type __fl, long long __v) const
1628{
1629 // Stage 1 - Get number in narrow char
1630 char __fmt[8] = {'%', 0};
1631 const char* __len = "ll";
1632 this->__format_int(__fmt+1, __len, true, __iob.flags());
1633 const unsigned __nbuf = (numeric_limits<long long>::digits / 3)
1634 + ((numeric_limits<long long>::digits % 3) != 0)
1635 + 1;
1636 char __nar[__nbuf];
Howard Hinnant866569b2011-09-28 23:39:33 +00001637#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001638 int __nc = sprintf_l(__nar, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001639#else
1640 int __nc = __sprintf_l(__nar, __cloc(), __fmt, __v);
1641#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001642 char* __ne = __nar + __nc;
1643 char* __np = this->__identify_padding(__nar, __ne, __iob);
1644 // Stage 2 - Widen __nar while adding thousands separators
1645 char_type __o[2*(__nbuf-1) - 1];
1646 char_type* __op; // pad here
1647 char_type* __oe; // end of output
1648 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1649 // [__o, __oe) contains thousands_sep'd wide number
1650 // Stage 3 & 4
1651 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1652}
1653
1654template <class _CharT, class _OutputIterator>
1655_OutputIterator
1656num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1657 char_type __fl, unsigned long __v) const
1658{
1659 // Stage 1 - Get number in narrow char
1660 char __fmt[6] = {'%', 0};
1661 const char* __len = "l";
1662 this->__format_int(__fmt+1, __len, false, __iob.flags());
1663 const unsigned __nbuf = (numeric_limits<unsigned long>::digits / 3)
1664 + ((numeric_limits<unsigned long>::digits % 3) != 0)
1665 + 1;
1666 char __nar[__nbuf];
Howard Hinnant866569b2011-09-28 23:39:33 +00001667#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001668 int __nc = sprintf_l(__nar, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001669#else
1670 int __nc = __sprintf_l(__nar, __cloc(), __fmt, __v);
1671#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001672 char* __ne = __nar + __nc;
1673 char* __np = this->__identify_padding(__nar, __ne, __iob);
1674 // Stage 2 - Widen __nar while adding thousands separators
1675 char_type __o[2*(__nbuf-1) - 1];
1676 char_type* __op; // pad here
1677 char_type* __oe; // end of output
1678 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1679 // [__o, __oe) contains thousands_sep'd wide number
1680 // Stage 3 & 4
1681 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1682}
1683
1684template <class _CharT, class _OutputIterator>
1685_OutputIterator
1686num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1687 char_type __fl, unsigned long long __v) const
1688{
1689 // Stage 1 - Get number in narrow char
1690 char __fmt[8] = {'%', 0};
1691 const char* __len = "ll";
1692 this->__format_int(__fmt+1, __len, false, __iob.flags());
1693 const unsigned __nbuf = (numeric_limits<unsigned long long>::digits / 3)
1694 + ((numeric_limits<unsigned long long>::digits % 3) != 0)
1695 + 1;
1696 char __nar[__nbuf];
Howard Hinnant866569b2011-09-28 23:39:33 +00001697#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001698 int __nc = sprintf_l(__nar, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001699#else
1700 int __nc = __sprintf_l(__nar, __cloc(), __fmt, __v);
1701#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001702 char* __ne = __nar + __nc;
1703 char* __np = this->__identify_padding(__nar, __ne, __iob);
1704 // Stage 2 - Widen __nar while adding thousands separators
1705 char_type __o[2*(__nbuf-1) - 1];
1706 char_type* __op; // pad here
1707 char_type* __oe; // end of output
1708 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1709 // [__o, __oe) contains thousands_sep'd wide number
1710 // Stage 3 & 4
1711 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1712}
1713
1714template <class _CharT, class _OutputIterator>
1715_OutputIterator
1716num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1717 char_type __fl, double __v) const
1718{
1719 // Stage 1 - Get number in narrow char
1720 char __fmt[8] = {'%', 0};
1721 const char* __len = "";
1722 bool __specify_precision = this->__format_float(__fmt+1, __len, __iob.flags());
1723 const unsigned __nbuf = 30;
1724 char __nar[__nbuf];
1725 char* __nb = __nar;
1726 int __nc;
1727 if (__specify_precision)
Howard Hinnant866569b2011-09-28 23:39:33 +00001728#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001729 __nc = snprintf_l(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt,
Howard Hinnantadff4892010-05-24 17:49:41 +00001730 (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001731#else
1732 __nc = __snprintf_l(__nb, __nbuf, __cloc(), __fmt,
1733 (int)__iob.precision(), __v);
1734#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001735 else
Howard Hinnant866569b2011-09-28 23:39:33 +00001736#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001737 __nc = snprintf_l(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001738#else
1739 __nc = __snprintf_l(__nb, __nbuf, __cloc(), __fmt, __v);
1740#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001741 unique_ptr<char, void(*)(void*)> __nbh(0, free);
1742 if (__nc > static_cast<int>(__nbuf-1))
1743 {
1744 if (__specify_precision)
Howard Hinnant866569b2011-09-28 23:39:33 +00001745#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001746 __nc = asprintf_l(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001747#else
1748 __nc = __asprintf_l(&__nb, __cloc(), __fmt,
David Chisnallc512df12011-09-21 08:39:44 +00001749 (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001750#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001751 else
Howard Hinnant866569b2011-09-28 23:39:33 +00001752#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001753 __nc = asprintf_l(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001754#else
David Chisnallc512df12011-09-21 08:39:44 +00001755 __nc = __asprintf_l(&__nb, __cloc(), __fmt, (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001756#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001757 if (__nb == 0)
1758 __throw_bad_alloc();
1759 __nbh.reset(__nb);
1760 }
1761 char* __ne = __nb + __nc;
1762 char* __np = this->__identify_padding(__nb, __ne, __iob);
1763 // Stage 2 - Widen __nar while adding thousands separators
1764 char_type __o[2*(__nbuf-1) - 1];
1765 char_type* __ob = __o;
1766 unique_ptr<char_type, void(*)(void*)> __obh(0, free);
1767 if (__nb != __nar)
1768 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00001769 __ob = (char_type*)malloc(2*static_cast<size_t>(__nc)*sizeof(char_type));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001770 if (__ob == 0)
1771 __throw_bad_alloc();
1772 __obh.reset(__ob);
1773 }
1774 char_type* __op; // pad here
1775 char_type* __oe; // end of output
1776 this->__widen_and_group_float(__nb, __np, __ne, __ob, __op, __oe, __iob.getloc());
1777 // [__o, __oe) contains thousands_sep'd wide number
1778 // Stage 3 & 4
1779 __s = __pad_and_output(__s, __ob, __op, __oe, __iob, __fl);
1780 return __s;
1781}
1782
1783template <class _CharT, class _OutputIterator>
1784_OutputIterator
1785num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1786 char_type __fl, long double __v) const
1787{
1788 // Stage 1 - Get number in narrow char
1789 char __fmt[8] = {'%', 0};
1790 const char* __len = "L";
1791 bool __specify_precision = this->__format_float(__fmt+1, __len, __iob.flags());
1792 const unsigned __nbuf = 30;
1793 char __nar[__nbuf];
1794 char* __nb = __nar;
1795 int __nc;
1796 if (__specify_precision)
Howard Hinnant866569b2011-09-28 23:39:33 +00001797#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001798 __nc = snprintf_l(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt,
Howard Hinnantadff4892010-05-24 17:49:41 +00001799 (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001800#else
1801 __nc = __snprintf_l(__nb, __nbuf, __cloc(), __fmt,
1802 (int)__iob.precision(), __v);
1803#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001804 else
Howard Hinnant866569b2011-09-28 23:39:33 +00001805#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001806 __nc = snprintf_l(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001807#else
1808 __nc = __snprintf_l(__nb, __nbuf, __cloc(), __fmt, __v);
1809#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001810 unique_ptr<char, void(*)(void*)> __nbh(0, free);
1811 if (__nc > static_cast<int>(__nbuf-1))
1812 {
1813 if (__specify_precision)
Howard Hinnant866569b2011-09-28 23:39:33 +00001814#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001815 __nc = asprintf_l(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001816#else
1817 __nc = __asprintf_l(&__nb, __cloc(), __fmt,
David Chisnallc512df12011-09-21 08:39:44 +00001818 (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001819#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001820 else
Howard Hinnant866569b2011-09-28 23:39:33 +00001821#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001822 __nc = asprintf_l(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001823#else
David Chisnallc512df12011-09-21 08:39:44 +00001824 __nc = __asprintf_l(&__nb, __cloc(), __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001825#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001826 if (__nb == 0)
1827 __throw_bad_alloc();
1828 __nbh.reset(__nb);
1829 }
1830 char* __ne = __nb + __nc;
1831 char* __np = this->__identify_padding(__nb, __ne, __iob);
1832 // Stage 2 - Widen __nar while adding thousands separators
1833 char_type __o[2*(__nbuf-1) - 1];
1834 char_type* __ob = __o;
1835 unique_ptr<char_type, void(*)(void*)> __obh(0, free);
1836 if (__nb != __nar)
1837 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00001838 __ob = (char_type*)malloc(2*static_cast<size_t>(__nc)*sizeof(char_type));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001839 if (__ob == 0)
1840 __throw_bad_alloc();
1841 __obh.reset(__ob);
1842 }
1843 char_type* __op; // pad here
1844 char_type* __oe; // end of output
1845 this->__widen_and_group_float(__nb, __np, __ne, __ob, __op, __oe, __iob.getloc());
1846 // [__o, __oe) contains thousands_sep'd wide number
1847 // Stage 3 & 4
1848 __s = __pad_and_output(__s, __ob, __op, __oe, __iob, __fl);
1849 return __s;
1850}
1851
1852template <class _CharT, class _OutputIterator>
1853_OutputIterator
1854num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1855 char_type __fl, const void* __v) const
1856{
1857 // Stage 1 - Get pointer in narrow char
1858 char __fmt[6] = "%p";
1859 const unsigned __nbuf = 20;
1860 char __nar[__nbuf];
Howard Hinnant866569b2011-09-28 23:39:33 +00001861#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001862 int __nc = sprintf_l(__nar, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001863#else
1864 int __nc = __sprintf_l(__nar, __cloc(), __fmt, __v);
1865#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001866 char* __ne = __nar + __nc;
1867 char* __np = this->__identify_padding(__nar, __ne, __iob);
1868 // Stage 2 - Widen __nar
1869 char_type __o[2*(__nbuf-1) - 1];
1870 char_type* __op; // pad here
1871 char_type* __oe; // end of output
1872 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
1873 __ct.widen(__nar, __ne, __o);
1874 __oe = __o + (__ne - __nar);
1875 if (__np == __ne)
1876 __op = __oe;
1877 else
1878 __op = __o + (__np - __nar);
1879 // [__o, __oe) contains wide number
1880 // Stage 3 & 4
1881 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1882}
1883
1884extern template class num_put<char>;
1885extern template class num_put<wchar_t>;
1886
1887template <class _CharT, class _InputIterator>
1888_LIBCPP_HIDDEN
1889int
1890__get_up_to_n_digits(_InputIterator& __b, _InputIterator __e,
1891 ios_base::iostate& __err, const ctype<_CharT>& __ct, int __n)
1892{
1893 // Precondition: __n >= 1
1894 if (__b == __e)
1895 {
1896 __err |= ios_base::eofbit | ios_base::failbit;
1897 return 0;
1898 }
1899 // get first digit
1900 _CharT __c = *__b;
1901 if (!__ct.is(ctype_base::digit, __c))
1902 {
1903 __err |= ios_base::failbit;
1904 return 0;
1905 }
1906 int __r = __ct.narrow(__c, 0) - '0';
1907 for (++__b, --__n; __b != __e && __n > 0; ++__b, --__n)
1908 {
1909 // get next digit
1910 __c = *__b;
1911 if (!__ct.is(ctype_base::digit, __c))
1912 return __r;
1913 __r = __r * 10 + __ct.narrow(__c, 0) - '0';
1914 }
1915 if (__b == __e)
1916 __err |= ios_base::eofbit;
1917 return __r;
1918}
1919
Howard Hinnant82894812010-09-22 16:48:34 +00001920class _LIBCPP_VISIBLE time_base
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001921{
1922public:
1923 enum dateorder {no_order, dmy, mdy, ymd, ydm};
1924};
1925
1926template <class _CharT>
Howard Hinnant2d72b1e2010-12-17 14:46:43 +00001927class __time_get_c_storage // purposefully not decorated
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001928{
1929protected:
1930 typedef basic_string<_CharT> string_type;
1931
1932 virtual const string_type* __weeks() const;
1933 virtual const string_type* __months() const;
1934 virtual const string_type* __am_pm() const;
1935 virtual const string_type& __c() const;
1936 virtual const string_type& __r() const;
1937 virtual const string_type& __x() const;
1938 virtual const string_type& __X() const;
1939};
1940
1941template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00001942class _LIBCPP_VISIBLE time_get
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001943 : public locale::facet,
1944 public time_base,
1945 private __time_get_c_storage<_CharT>
1946{
1947public:
1948 typedef _CharT char_type;
1949 typedef _InputIterator iter_type;
1950 typedef time_base::dateorder dateorder;
1951 typedef basic_string<char_type> string_type;
1952
1953 _LIBCPP_ALWAYS_INLINE
1954 explicit time_get(size_t __refs = 0)
1955 : locale::facet(__refs) {}
1956
1957 _LIBCPP_ALWAYS_INLINE
1958 dateorder date_order() const
1959 {
1960 return this->do_date_order();
1961 }
1962
1963 _LIBCPP_ALWAYS_INLINE
1964 iter_type get_time(iter_type __b, iter_type __e, ios_base& __iob,
1965 ios_base::iostate& __err, tm* __tm) const
1966 {
1967 return do_get_time(__b, __e, __iob, __err, __tm);
1968 }
1969
1970 _LIBCPP_ALWAYS_INLINE
1971 iter_type get_date(iter_type __b, iter_type __e, ios_base& __iob,
1972 ios_base::iostate& __err, tm* __tm) const
1973 {
1974 return do_get_date(__b, __e, __iob, __err, __tm);
1975 }
1976
1977 _LIBCPP_ALWAYS_INLINE
1978 iter_type get_weekday(iter_type __b, iter_type __e, ios_base& __iob,
1979 ios_base::iostate& __err, tm* __tm) const
1980 {
1981 return do_get_weekday(__b, __e, __iob, __err, __tm);
1982 }
1983
1984 _LIBCPP_ALWAYS_INLINE
1985 iter_type get_monthname(iter_type __b, iter_type __e, ios_base& __iob,
1986 ios_base::iostate& __err, tm* __tm) const
1987 {
1988 return do_get_monthname(__b, __e, __iob, __err, __tm);
1989 }
1990
1991 _LIBCPP_ALWAYS_INLINE
1992 iter_type get_year(iter_type __b, iter_type __e, ios_base& __iob,
1993 ios_base::iostate& __err, tm* __tm) const
1994 {
1995 return do_get_year(__b, __e, __iob, __err, __tm);
1996 }
1997
1998 _LIBCPP_ALWAYS_INLINE
1999 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
2000 ios_base::iostate& __err, tm *__tm,
2001 char __fmt, char __mod = 0) const
2002 {
2003 return do_get(__b, __e, __iob, __err, __tm, __fmt, __mod);
2004 }
2005
2006 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
2007 ios_base::iostate& __err, tm* __tm,
2008 const char_type* __fmtb, const char_type* __fmte) const;
2009
2010 static locale::id id;
2011
2012protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002013 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002014 ~time_get() {}
2015
2016 virtual dateorder do_date_order() const;
2017 virtual iter_type do_get_time(iter_type __b, iter_type __e, ios_base& __iob,
2018 ios_base::iostate& __err, tm* __tm) const;
2019 virtual iter_type do_get_date(iter_type __b, iter_type __e, ios_base& __iob,
2020 ios_base::iostate& __err, tm* __tm) const;
2021 virtual iter_type do_get_weekday(iter_type __b, iter_type __e, ios_base& __iob,
2022 ios_base::iostate& __err, tm* __tm) const;
2023 virtual iter_type do_get_monthname(iter_type __b, iter_type __e, ios_base& __iob,
2024 ios_base::iostate& __err, tm* __tm) const;
2025 virtual iter_type do_get_year(iter_type __b, iter_type __e, ios_base& __iob,
2026 ios_base::iostate& __err, tm* __tm) const;
2027 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
2028 ios_base::iostate& __err, tm* __tm,
2029 char __fmt, char __mod) const;
2030private:
2031 void __get_white_space(iter_type& __b, iter_type __e,
2032 ios_base::iostate& __err, const ctype<char_type>& __ct) const;
2033 void __get_percent(iter_type& __b, iter_type __e, ios_base::iostate& __err,
2034 const ctype<char_type>& __ct) const;
2035
2036 void __get_weekdayname(int& __m,
2037 iter_type& __b, iter_type __e,
2038 ios_base::iostate& __err,
2039 const ctype<char_type>& __ct) const;
2040 void __get_monthname(int& __m,
2041 iter_type& __b, iter_type __e,
2042 ios_base::iostate& __err,
2043 const ctype<char_type>& __ct) const;
2044 void __get_day(int& __d,
2045 iter_type& __b, iter_type __e,
2046 ios_base::iostate& __err,
2047 const ctype<char_type>& __ct) const;
2048 void __get_month(int& __m,
2049 iter_type& __b, iter_type __e,
2050 ios_base::iostate& __err,
2051 const ctype<char_type>& __ct) const;
2052 void __get_year(int& __y,
2053 iter_type& __b, iter_type __e,
2054 ios_base::iostate& __err,
2055 const ctype<char_type>& __ct) const;
2056 void __get_year4(int& __y,
2057 iter_type& __b, iter_type __e,
2058 ios_base::iostate& __err,
2059 const ctype<char_type>& __ct) const;
2060 void __get_hour(int& __d,
2061 iter_type& __b, iter_type __e,
2062 ios_base::iostate& __err,
2063 const ctype<char_type>& __ct) const;
2064 void __get_12_hour(int& __h,
2065 iter_type& __b, iter_type __e,
2066 ios_base::iostate& __err,
2067 const ctype<char_type>& __ct) const;
2068 void __get_am_pm(int& __h,
2069 iter_type& __b, iter_type __e,
2070 ios_base::iostate& __err,
2071 const ctype<char_type>& __ct) const;
2072 void __get_minute(int& __m,
2073 iter_type& __b, iter_type __e,
2074 ios_base::iostate& __err,
2075 const ctype<char_type>& __ct) const;
2076 void __get_second(int& __s,
2077 iter_type& __b, iter_type __e,
2078 ios_base::iostate& __err,
2079 const ctype<char_type>& __ct) const;
2080 void __get_weekday(int& __w,
2081 iter_type& __b, iter_type __e,
2082 ios_base::iostate& __err,
2083 const ctype<char_type>& __ct) const;
2084 void __get_day_year_num(int& __w,
2085 iter_type& __b, iter_type __e,
2086 ios_base::iostate& __err,
2087 const ctype<char_type>& __ct) const;
2088};
2089
2090template <class _CharT, class _InputIterator>
2091locale::id
2092time_get<_CharT, _InputIterator>::id;
2093
2094// time_get primatives
2095
2096template <class _CharT, class _InputIterator>
2097void
2098time_get<_CharT, _InputIterator>::__get_weekdayname(int& __w,
2099 iter_type& __b, iter_type __e,
2100 ios_base::iostate& __err,
2101 const ctype<char_type>& __ct) const
2102{
2103 // Note: ignoring case comes from the POSIX strptime spec
2104 const string_type* __wk = this->__weeks();
Howard Hinnantec3773c2011-12-01 20:21:04 +00002105 ptrdiff_t __i = __scan_keyword(__b, __e, __wk, __wk+14, __ct, __err, false) - __wk;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002106 if (__i < 14)
2107 __w = __i % 7;
2108}
2109
2110template <class _CharT, class _InputIterator>
2111void
2112time_get<_CharT, _InputIterator>::__get_monthname(int& __m,
2113 iter_type& __b, iter_type __e,
2114 ios_base::iostate& __err,
2115 const ctype<char_type>& __ct) const
2116{
2117 // Note: ignoring case comes from the POSIX strptime spec
2118 const string_type* __month = this->__months();
Howard Hinnantec3773c2011-12-01 20:21:04 +00002119 ptrdiff_t __i = __scan_keyword(__b, __e, __month, __month+24, __ct, __err, false) - __month;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002120 if (__i < 24)
2121 __m = __i % 12;
2122}
2123
2124template <class _CharT, class _InputIterator>
2125void
2126time_get<_CharT, _InputIterator>::__get_day(int& __d,
2127 iter_type& __b, iter_type __e,
2128 ios_base::iostate& __err,
2129 const ctype<char_type>& __ct) const
2130{
2131 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2132 if (!(__err & ios_base::failbit) && 1 <= __t && __t <= 31)
2133 __d = __t;
2134 else
2135 __err |= ios_base::failbit;
2136}
2137
2138template <class _CharT, class _InputIterator>
2139void
2140time_get<_CharT, _InputIterator>::__get_month(int& __m,
2141 iter_type& __b, iter_type __e,
2142 ios_base::iostate& __err,
2143 const ctype<char_type>& __ct) const
2144{
2145 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2) - 1;
2146 if (!(__err & ios_base::failbit) && __t <= 11)
2147 __m = __t;
2148 else
2149 __err |= ios_base::failbit;
2150}
2151
2152template <class _CharT, class _InputIterator>
2153void
2154time_get<_CharT, _InputIterator>::__get_year(int& __y,
2155 iter_type& __b, iter_type __e,
2156 ios_base::iostate& __err,
2157 const ctype<char_type>& __ct) const
2158{
2159 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 4);
2160 if (!(__err & ios_base::failbit))
2161 {
2162 if (__t < 69)
2163 __t += 2000;
2164 else if (69 <= __t && __t <= 99)
2165 __t += 1900;
2166 __y = __t - 1900;
2167 }
2168}
2169
2170template <class _CharT, class _InputIterator>
2171void
2172time_get<_CharT, _InputIterator>::__get_year4(int& __y,
2173 iter_type& __b, iter_type __e,
2174 ios_base::iostate& __err,
2175 const ctype<char_type>& __ct) const
2176{
2177 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 4);
2178 if (!(__err & ios_base::failbit))
2179 __y = __t - 1900;
2180}
2181
2182template <class _CharT, class _InputIterator>
2183void
2184time_get<_CharT, _InputIterator>::__get_hour(int& __h,
2185 iter_type& __b, iter_type __e,
2186 ios_base::iostate& __err,
2187 const ctype<char_type>& __ct) const
2188{
2189 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2190 if (!(__err & ios_base::failbit) && __t <= 23)
2191 __h = __t;
2192 else
2193 __err |= ios_base::failbit;
2194}
2195
2196template <class _CharT, class _InputIterator>
2197void
2198time_get<_CharT, _InputIterator>::__get_12_hour(int& __h,
2199 iter_type& __b, iter_type __e,
2200 ios_base::iostate& __err,
2201 const ctype<char_type>& __ct) const
2202{
2203 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2204 if (!(__err & ios_base::failbit) && 1 <= __t && __t <= 12)
2205 __h = __t;
2206 else
2207 __err |= ios_base::failbit;
2208}
2209
2210template <class _CharT, class _InputIterator>
2211void
2212time_get<_CharT, _InputIterator>::__get_minute(int& __m,
2213 iter_type& __b, iter_type __e,
2214 ios_base::iostate& __err,
2215 const ctype<char_type>& __ct) const
2216{
2217 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2218 if (!(__err & ios_base::failbit) && __t <= 59)
2219 __m = __t;
2220 else
2221 __err |= ios_base::failbit;
2222}
2223
2224template <class _CharT, class _InputIterator>
2225void
2226time_get<_CharT, _InputIterator>::__get_second(int& __s,
2227 iter_type& __b, iter_type __e,
2228 ios_base::iostate& __err,
2229 const ctype<char_type>& __ct) const
2230{
2231 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2232 if (!(__err & ios_base::failbit) && __t <= 60)
2233 __s = __t;
2234 else
2235 __err |= ios_base::failbit;
2236}
2237
2238template <class _CharT, class _InputIterator>
2239void
2240time_get<_CharT, _InputIterator>::__get_weekday(int& __w,
2241 iter_type& __b, iter_type __e,
2242 ios_base::iostate& __err,
2243 const ctype<char_type>& __ct) const
2244{
2245 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 1);
2246 if (!(__err & ios_base::failbit) && __t <= 6)
2247 __w = __t;
2248 else
2249 __err |= ios_base::failbit;
2250}
2251
2252template <class _CharT, class _InputIterator>
2253void
2254time_get<_CharT, _InputIterator>::__get_day_year_num(int& __d,
2255 iter_type& __b, iter_type __e,
2256 ios_base::iostate& __err,
2257 const ctype<char_type>& __ct) const
2258{
2259 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 3);
2260 if (!(__err & ios_base::failbit) && __t <= 365)
2261 __d = __t;
2262 else
2263 __err |= ios_base::failbit;
2264}
2265
2266template <class _CharT, class _InputIterator>
2267void
2268time_get<_CharT, _InputIterator>::__get_white_space(iter_type& __b, iter_type __e,
2269 ios_base::iostate& __err,
2270 const ctype<char_type>& __ct) const
2271{
2272 for (; __b != __e && __ct.is(ctype_base::space, *__b); ++__b)
2273 ;
2274 if (__b == __e)
2275 __err |= ios_base::eofbit;
2276}
2277
2278template <class _CharT, class _InputIterator>
2279void
2280time_get<_CharT, _InputIterator>::__get_am_pm(int& __h,
2281 iter_type& __b, iter_type __e,
2282 ios_base::iostate& __err,
2283 const ctype<char_type>& __ct) const
2284{
2285 const string_type* __ap = this->__am_pm();
2286 if (__ap[0].size() + __ap[1].size() == 0)
2287 {
2288 __err |= ios_base::failbit;
2289 return;
2290 }
Howard Hinnantec3773c2011-12-01 20:21:04 +00002291 ptrdiff_t __i = __scan_keyword(__b, __e, __ap, __ap+2, __ct, __err, false) - __ap;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002292 if (__i == 0 && __h == 12)
2293 __h = 0;
2294 else if (__i == 1 && __h < 12)
2295 __h += 12;
2296}
2297
2298template <class _CharT, class _InputIterator>
2299void
2300time_get<_CharT, _InputIterator>::__get_percent(iter_type& __b, iter_type __e,
2301 ios_base::iostate& __err,
2302 const ctype<char_type>& __ct) const
2303{
2304 if (__b == __e)
2305 {
2306 __err |= ios_base::eofbit | ios_base::failbit;
2307 return;
2308 }
2309 if (__ct.narrow(*__b, 0) != '%')
2310 __err |= ios_base::failbit;
2311 else if(++__b == __e)
2312 __err |= ios_base::eofbit;
2313}
2314
2315// time_get end primatives
2316
2317template <class _CharT, class _InputIterator>
2318_InputIterator
2319time_get<_CharT, _InputIterator>::get(iter_type __b, iter_type __e,
2320 ios_base& __iob,
2321 ios_base::iostate& __err, tm* __tm,
2322 const char_type* __fmtb, const char_type* __fmte) const
2323{
2324 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2325 __err = ios_base::goodbit;
2326 while (__fmtb != __fmte && __err == ios_base::goodbit)
2327 {
2328 if (__b == __e)
2329 {
2330 __err = ios_base::failbit;
2331 break;
2332 }
2333 if (__ct.narrow(*__fmtb, 0) == '%')
2334 {
2335 if (++__fmtb == __fmte)
2336 {
2337 __err = ios_base::failbit;
2338 break;
2339 }
2340 char __cmd = __ct.narrow(*__fmtb, 0);
2341 char __opt = '\0';
2342 if (__cmd == 'E' || __cmd == '0')
2343 {
2344 if (++__fmtb == __fmte)
2345 {
2346 __err = ios_base::failbit;
2347 break;
2348 }
2349 __opt = __cmd;
2350 __cmd = __ct.narrow(*__fmtb, 0);
2351 }
2352 __b = do_get(__b, __e, __iob, __err, __tm, __cmd, __opt);
2353 ++__fmtb;
2354 }
2355 else if (__ct.is(ctype_base::space, *__fmtb))
2356 {
2357 for (++__fmtb; __fmtb != __fmte && __ct.is(ctype_base::space, *__fmtb); ++__fmtb)
2358 ;
2359 for ( ; __b != __e && __ct.is(ctype_base::space, *__b); ++__b)
2360 ;
2361 }
2362 else if (__ct.toupper(*__b) == __ct.toupper(*__fmtb))
2363 {
2364 ++__b;
2365 ++__fmtb;
2366 }
2367 else
2368 __err = ios_base::failbit;
2369 }
2370 if (__b == __e)
2371 __err |= ios_base::eofbit;
2372 return __b;
2373}
2374
2375template <class _CharT, class _InputIterator>
2376typename time_get<_CharT, _InputIterator>::dateorder
2377time_get<_CharT, _InputIterator>::do_date_order() const
2378{
2379 return mdy;
2380}
2381
2382template <class _CharT, class _InputIterator>
2383_InputIterator
2384time_get<_CharT, _InputIterator>::do_get_time(iter_type __b, iter_type __e,
2385 ios_base& __iob,
2386 ios_base::iostate& __err,
2387 tm* __tm) const
2388{
2389 const char_type __fmt[] = {'%', 'H', ':', '%', 'M', ':', '%', 'S'};
2390 return get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2391}
2392
2393template <class _CharT, class _InputIterator>
2394_InputIterator
2395time_get<_CharT, _InputIterator>::do_get_date(iter_type __b, iter_type __e,
2396 ios_base& __iob,
2397 ios_base::iostate& __err,
2398 tm* __tm) const
2399{
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002400 const string_type& __fmt = this->__x();
2401 return get(__b, __e, __iob, __err, __tm, __fmt.data(), __fmt.data() + __fmt.size());
2402}
2403
2404template <class _CharT, class _InputIterator>
2405_InputIterator
2406time_get<_CharT, _InputIterator>::do_get_weekday(iter_type __b, iter_type __e,
2407 ios_base& __iob,
2408 ios_base::iostate& __err,
2409 tm* __tm) const
2410{
2411 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2412 __get_weekdayname(__tm->tm_wday, __b, __e, __err, __ct);
2413 return __b;
2414}
2415
2416template <class _CharT, class _InputIterator>
2417_InputIterator
2418time_get<_CharT, _InputIterator>::do_get_monthname(iter_type __b, iter_type __e,
2419 ios_base& __iob,
2420 ios_base::iostate& __err,
2421 tm* __tm) const
2422{
2423 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2424 __get_monthname(__tm->tm_mon, __b, __e, __err, __ct);
2425 return __b;
2426}
2427
2428template <class _CharT, class _InputIterator>
2429_InputIterator
2430time_get<_CharT, _InputIterator>::do_get_year(iter_type __b, iter_type __e,
2431 ios_base& __iob,
2432 ios_base::iostate& __err,
2433 tm* __tm) const
2434{
2435 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2436 __get_year(__tm->tm_year, __b, __e, __err, __ct);
2437 return __b;
2438}
2439
2440template <class _CharT, class _InputIterator>
2441_InputIterator
2442time_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
2443 ios_base& __iob,
2444 ios_base::iostate& __err, tm* __tm,
2445 char __fmt, char) const
2446{
2447 __err = ios_base::goodbit;
2448 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2449 switch (__fmt)
2450 {
2451 case 'a':
2452 case 'A':
2453 __get_weekdayname(__tm->tm_wday, __b, __e, __err, __ct);
2454 break;
2455 case 'b':
2456 case 'B':
2457 case 'h':
2458 __get_monthname(__tm->tm_mon, __b, __e, __err, __ct);
2459 break;
2460 case 'c':
2461 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002462 const string_type& __fm = this->__c();
2463 __b = get(__b, __e, __iob, __err, __tm, __fm.data(), __fm.data() + __fm.size());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002464 }
2465 break;
2466 case 'd':
2467 case 'e':
2468 __get_day(__tm->tm_mday, __b, __e, __err, __ct);
2469 break;
2470 case 'D':
2471 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002472 const char_type __fm[] = {'%', 'm', '/', '%', 'd', '/', '%', 'y'};
2473 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm)/sizeof(__fm[0]));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002474 }
2475 break;
Howard Hinnant506b3642011-04-10 17:54:14 +00002476 case 'F':
2477 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002478 const char_type __fm[] = {'%', 'Y', '-', '%', 'm', '-', '%', 'd'};
2479 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm)/sizeof(__fm[0]));
Howard Hinnant506b3642011-04-10 17:54:14 +00002480 }
2481 break;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002482 case 'H':
2483 __get_hour(__tm->tm_hour, __b, __e, __err, __ct);
2484 break;
2485 case 'I':
2486 __get_12_hour(__tm->tm_hour, __b, __e, __err, __ct);
2487 break;
2488 case 'j':
2489 __get_day_year_num(__tm->tm_yday, __b, __e, __err, __ct);
2490 break;
2491 case 'm':
2492 __get_month(__tm->tm_mon, __b, __e, __err, __ct);
2493 break;
2494 case 'M':
2495 __get_minute(__tm->tm_min, __b, __e, __err, __ct);
2496 break;
2497 case 'n':
2498 case 't':
2499 __get_white_space(__b, __e, __err, __ct);
2500 break;
2501 case 'p':
2502 __get_am_pm(__tm->tm_hour, __b, __e, __err, __ct);
2503 break;
2504 case 'r':
2505 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002506 const char_type __fm[] = {'%', 'I', ':', '%', 'M', ':', '%', 'S', ' ', '%', 'p'};
2507 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm)/sizeof(__fm[0]));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002508 }
2509 break;
2510 case 'R':
2511 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002512 const char_type __fm[] = {'%', 'H', ':', '%', 'M'};
2513 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm)/sizeof(__fm[0]));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002514 }
2515 break;
2516 case 'S':
2517 __get_second(__tm->tm_sec, __b, __e, __err, __ct);
2518 break;
2519 case 'T':
2520 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002521 const char_type __fm[] = {'%', 'H', ':', '%', 'M', ':', '%', 'S'};
2522 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm)/sizeof(__fm[0]));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002523 }
2524 break;
2525 case 'w':
2526 __get_weekday(__tm->tm_wday, __b, __e, __err, __ct);
2527 break;
2528 case 'x':
2529 return do_get_date(__b, __e, __iob, __err, __tm);
2530 case 'X':
2531 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002532 const string_type& __fm = this->__X();
2533 __b = get(__b, __e, __iob, __err, __tm, __fm.data(), __fm.data() + __fm.size());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002534 }
2535 break;
2536 case 'y':
2537 __get_year(__tm->tm_year, __b, __e, __err, __ct);
2538 break;
2539 case 'Y':
2540 __get_year4(__tm->tm_year, __b, __e, __err, __ct);
2541 break;
2542 case '%':
2543 __get_percent(__b, __e, __err, __ct);
2544 break;
2545 default:
2546 __err |= ios_base::failbit;
2547 }
2548 return __b;
2549}
2550
2551extern template class time_get<char>;
2552extern template class time_get<wchar_t>;
2553
2554class __time_get
2555{
2556protected:
2557 locale_t __loc_;
2558
2559 __time_get(const char* __nm);
2560 __time_get(const string& __nm);
2561 ~__time_get();
2562};
2563
2564template <class _CharT>
2565class __time_get_storage
2566 : public __time_get
2567{
2568protected:
2569 typedef basic_string<_CharT> string_type;
2570
2571 string_type __weeks_[14];
2572 string_type __months_[24];
2573 string_type __am_pm_[2];
2574 string_type __c_;
2575 string_type __r_;
2576 string_type __x_;
2577 string_type __X_;
2578
2579 explicit __time_get_storage(const char* __nm);
2580 explicit __time_get_storage(const string& __nm);
2581
2582 _LIBCPP_ALWAYS_INLINE ~__time_get_storage() {}
2583
2584 time_base::dateorder __do_date_order() const;
2585
2586private:
2587 void init(const ctype<_CharT>&);
2588 string_type __analyze(char __fmt, const ctype<_CharT>&);
2589};
2590
2591template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00002592class _LIBCPP_VISIBLE time_get_byname
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002593 : public time_get<_CharT, _InputIterator>,
2594 private __time_get_storage<_CharT>
2595{
2596public:
2597 typedef time_base::dateorder dateorder;
2598 typedef _InputIterator iter_type;
2599 typedef _CharT char_type;
2600 typedef basic_string<char_type> string_type;
2601
Howard Hinnant82894812010-09-22 16:48:34 +00002602 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002603 explicit time_get_byname(const char* __nm, size_t __refs = 0)
2604 : time_get<_CharT, _InputIterator>(__refs),
2605 __time_get_storage<_CharT>(__nm) {}
Howard Hinnant82894812010-09-22 16:48:34 +00002606 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002607 explicit time_get_byname(const string& __nm, size_t __refs = 0)
2608 : time_get<_CharT, _InputIterator>(__refs),
2609 __time_get_storage<_CharT>(__nm) {}
2610
2611protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002612 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002613 ~time_get_byname() {}
2614
Howard Hinnant82894812010-09-22 16:48:34 +00002615 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002616 virtual dateorder do_date_order() const {return this->__do_date_order();}
2617private:
Howard Hinnant82894812010-09-22 16:48:34 +00002618 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002619 virtual const string_type* __weeks() const {return this->__weeks_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002620 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002621 virtual const string_type* __months() const {return this->__months_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002622 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002623 virtual const string_type* __am_pm() const {return this->__am_pm_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002624 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002625 virtual const string_type& __c() const {return this->__c_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002626 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002627 virtual const string_type& __r() const {return this->__r_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002628 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002629 virtual const string_type& __x() const {return this->__x_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002630 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002631 virtual const string_type& __X() const {return this->__X_;}
2632};
2633
2634extern template class time_get_byname<char>;
2635extern template class time_get_byname<wchar_t>;
2636
2637class __time_put
2638{
2639 locale_t __loc_;
2640protected:
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00002641 _LIBCPP_ALWAYS_INLINE __time_put() : __loc_(_LIBCPP_GET_C_LOCALE) {}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002642 __time_put(const char* __nm);
2643 __time_put(const string& __nm);
2644 ~__time_put();
2645 void __do_put(char* __nb, char*& __ne, const tm* __tm,
2646 char __fmt, char __mod) const;
2647 void __do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
2648 char __fmt, char __mod) const;
2649};
2650
2651template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00002652class _LIBCPP_VISIBLE time_put
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002653 : public locale::facet,
2654 private __time_put
2655{
2656public:
2657 typedef _CharT char_type;
2658 typedef _OutputIterator iter_type;
2659
2660 _LIBCPP_ALWAYS_INLINE
2661 explicit time_put(size_t __refs = 0)
2662 : locale::facet(__refs) {}
2663
2664 iter_type put(iter_type __s, ios_base& __iob, char_type __fl, const tm* __tm,
2665 const char_type* __pb, const char_type* __pe) const;
2666
2667 _LIBCPP_ALWAYS_INLINE
2668 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
2669 const tm* __tm, char __fmt, char __mod = 0) const
2670 {
2671 return do_put(__s, __iob, __fl, __tm, __fmt, __mod);
2672 }
2673
2674 static locale::id id;
2675
2676protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002677 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002678 ~time_put() {}
2679 virtual iter_type do_put(iter_type __s, ios_base&, char_type, const tm* __tm,
2680 char __fmt, char __mod) const;
2681
Howard Hinnant82894812010-09-22 16:48:34 +00002682 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002683 explicit time_put(const char* __nm, size_t __refs)
2684 : locale::facet(__refs),
2685 __time_put(__nm) {}
Howard Hinnant82894812010-09-22 16:48:34 +00002686 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002687 explicit time_put(const string& __nm, size_t __refs)
2688 : locale::facet(__refs),
2689 __time_put(__nm) {}
2690};
2691
2692template <class _CharT, class _OutputIterator>
2693locale::id
2694time_put<_CharT, _OutputIterator>::id;
2695
2696template <class _CharT, class _OutputIterator>
2697_OutputIterator
2698time_put<_CharT, _OutputIterator>::put(iter_type __s, ios_base& __iob,
2699 char_type __fl, const tm* __tm,
2700 const char_type* __pb,
2701 const char_type* __pe) const
2702{
2703 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2704 for (; __pb != __pe; ++__pb)
2705 {
2706 if (__ct.narrow(*__pb, 0) == '%')
2707 {
2708 if (++__pb == __pe)
2709 {
2710 *__s++ = __pb[-1];
2711 break;
2712 }
2713 char __mod = 0;
2714 char __fmt = __ct.narrow(*__pb, 0);
2715 if (__fmt == 'E' || __fmt == 'O')
2716 {
2717 if (++__pb == __pe)
2718 {
2719 *__s++ = __pb[-2];
2720 *__s++ = __pb[-1];
2721 break;
2722 }
2723 __mod = __fmt;
2724 __fmt = __ct.narrow(*__pb, 0);
2725 }
2726 __s = do_put(__s, __iob, __fl, __tm, __fmt, __mod);
2727 }
2728 else
2729 *__s++ = *__pb;
2730 }
2731 return __s;
2732}
2733
2734template <class _CharT, class _OutputIterator>
2735_OutputIterator
Howard Hinnantec3773c2011-12-01 20:21:04 +00002736time_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002737 char_type, const tm* __tm,
2738 char __fmt, char __mod) const
2739{
2740 char_type __nar[100];
2741 char_type* __nb = __nar;
2742 char_type* __ne = __nb + 100;
2743 __do_put(__nb, __ne, __tm, __fmt, __mod);
Howard Hinnant0949eed2011-06-30 21:18:19 +00002744 return _VSTD::copy(__nb, __ne, __s);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002745}
2746
2747extern template class time_put<char>;
2748extern template class time_put<wchar_t>;
2749
2750template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00002751class _LIBCPP_VISIBLE time_put_byname
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002752 : public time_put<_CharT, _OutputIterator>
2753{
2754public:
2755 _LIBCPP_ALWAYS_INLINE
2756 explicit time_put_byname(const char* __nm, size_t __refs = 0)
2757 : time_put<_CharT, _OutputIterator>(__nm, __refs) {}
2758
2759 _LIBCPP_ALWAYS_INLINE
2760 explicit time_put_byname(const string& __nm, size_t __refs = 0)
2761 : time_put<_CharT, _OutputIterator>(__nm, __refs) {}
2762
2763protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002764 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002765 ~time_put_byname() {}
2766};
2767
2768extern template class time_put_byname<char>;
2769extern template class time_put_byname<wchar_t>;
2770
2771// money_base
2772
Howard Hinnant82894812010-09-22 16:48:34 +00002773class _LIBCPP_VISIBLE money_base
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002774{
2775public:
2776 enum part {none, space, symbol, sign, value};
2777 struct pattern {char field[4];};
2778
2779 _LIBCPP_ALWAYS_INLINE money_base() {}
2780};
2781
2782// moneypunct
2783
2784template <class _CharT, bool _International = false>
Howard Hinnant82894812010-09-22 16:48:34 +00002785class _LIBCPP_VISIBLE moneypunct
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002786 : public locale::facet,
2787 public money_base
2788{
2789public:
2790 typedef _CharT char_type;
2791 typedef basic_string<char_type> string_type;
2792
Howard Hinnant82894812010-09-22 16:48:34 +00002793 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002794 explicit moneypunct(size_t __refs = 0)
2795 : locale::facet(__refs) {}
2796
2797 _LIBCPP_ALWAYS_INLINE char_type decimal_point() const {return do_decimal_point();}
2798 _LIBCPP_ALWAYS_INLINE char_type thousands_sep() const {return do_thousands_sep();}
2799 _LIBCPP_ALWAYS_INLINE string grouping() const {return do_grouping();}
2800 _LIBCPP_ALWAYS_INLINE string_type curr_symbol() const {return do_curr_symbol();}
2801 _LIBCPP_ALWAYS_INLINE string_type positive_sign() const {return do_positive_sign();}
2802 _LIBCPP_ALWAYS_INLINE string_type negative_sign() const {return do_negative_sign();}
2803 _LIBCPP_ALWAYS_INLINE int frac_digits() const {return do_frac_digits();}
2804 _LIBCPP_ALWAYS_INLINE pattern pos_format() const {return do_pos_format();}
2805 _LIBCPP_ALWAYS_INLINE pattern neg_format() const {return do_neg_format();}
2806
2807 static locale::id id;
2808 static const bool intl = _International;
2809
2810protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002811 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002812 ~moneypunct() {}
2813
2814 virtual char_type do_decimal_point() const {return numeric_limits<char_type>::max();}
2815 virtual char_type do_thousands_sep() const {return numeric_limits<char_type>::max();}
2816 virtual string do_grouping() const {return string();}
2817 virtual string_type do_curr_symbol() const {return string_type();}
2818 virtual string_type do_positive_sign() const {return string_type();}
2819 virtual string_type do_negative_sign() const {return string_type(1, '-');}
2820 virtual int do_frac_digits() const {return 0;}
2821 virtual pattern do_pos_format() const
2822 {pattern __p = {symbol, sign, none, value}; return __p;}
2823 virtual pattern do_neg_format() const
2824 {pattern __p = {symbol, sign, none, value}; return __p;}
2825};
2826
2827template <class _CharT, bool _International>
2828locale::id
2829moneypunct<_CharT, _International>::id;
2830
2831extern template class moneypunct<char, false>;
2832extern template class moneypunct<char, true>;
2833extern template class moneypunct<wchar_t, false>;
2834extern template class moneypunct<wchar_t, true>;
2835
2836// moneypunct_byname
2837
2838template <class _CharT, bool _International = false>
Howard Hinnant82894812010-09-22 16:48:34 +00002839class _LIBCPP_VISIBLE moneypunct_byname
2840 : public moneypunct<_CharT, _International>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002841{
2842public:
2843 typedef money_base::pattern pattern;
2844 typedef _CharT char_type;
2845 typedef basic_string<char_type> string_type;
2846
2847 _LIBCPP_ALWAYS_INLINE
2848 explicit moneypunct_byname(const char* __nm, size_t __refs = 0)
2849 : moneypunct<_CharT, _International>(__refs) {init(__nm);}
2850
2851 _LIBCPP_ALWAYS_INLINE
2852 explicit moneypunct_byname(const string& __nm, size_t __refs = 0)
2853 : moneypunct<_CharT, _International>(__refs) {init(__nm.c_str());}
2854
2855protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002856 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002857 ~moneypunct_byname() {}
2858
2859 virtual char_type do_decimal_point() const {return __decimal_point_;}
2860 virtual char_type do_thousands_sep() const {return __thousands_sep_;}
2861 virtual string do_grouping() const {return __grouping_;}
2862 virtual string_type do_curr_symbol() const {return __curr_symbol_;}
2863 virtual string_type do_positive_sign() const {return __positive_sign_;}
2864 virtual string_type do_negative_sign() const {return __negative_sign_;}
2865 virtual int do_frac_digits() const {return __frac_digits_;}
2866 virtual pattern do_pos_format() const {return __pos_format_;}
2867 virtual pattern do_neg_format() const {return __neg_format_;}
2868
2869private:
2870 char_type __decimal_point_;
2871 char_type __thousands_sep_;
2872 string __grouping_;
2873 string_type __curr_symbol_;
2874 string_type __positive_sign_;
2875 string_type __negative_sign_;
2876 int __frac_digits_;
2877 pattern __pos_format_;
2878 pattern __neg_format_;
2879
2880 void init(const char*);
2881};
2882
2883template<> void moneypunct_byname<char, false>::init(const char*);
2884template<> void moneypunct_byname<char, true>::init(const char*);
2885template<> void moneypunct_byname<wchar_t, false>::init(const char*);
2886template<> void moneypunct_byname<wchar_t, true>::init(const char*);
2887
2888extern template class moneypunct_byname<char, false>;
2889extern template class moneypunct_byname<char, true>;
2890extern template class moneypunct_byname<wchar_t, false>;
2891extern template class moneypunct_byname<wchar_t, true>;
2892
2893// money_get
2894
2895template <class _CharT>
2896class __money_get
2897{
2898protected:
2899 typedef _CharT char_type;
2900 typedef basic_string<char_type> string_type;
2901
2902 _LIBCPP_ALWAYS_INLINE __money_get() {}
2903
2904 static void __gather_info(bool __intl, const locale& __loc,
2905 money_base::pattern& __pat, char_type& __dp,
2906 char_type& __ts, string& __grp,
2907 string_type& __sym, string_type& __psn,
2908 string_type& __nsn, int& __fd);
2909};
2910
2911template <class _CharT>
2912void
2913__money_get<_CharT>::__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 if (__intl)
2920 {
2921 const moneypunct<char_type, true>& __mp =
2922 use_facet<moneypunct<char_type, true> >(__loc);
2923 __pat = __mp.neg_format();
2924 __nsn = __mp.negative_sign();
2925 __psn = __mp.positive_sign();
2926 __dp = __mp.decimal_point();
2927 __ts = __mp.thousands_sep();
2928 __grp = __mp.grouping();
2929 __sym = __mp.curr_symbol();
2930 __fd = __mp.frac_digits();
2931 }
2932 else
2933 {
2934 const moneypunct<char_type, false>& __mp =
2935 use_facet<moneypunct<char_type, false> >(__loc);
2936 __pat = __mp.neg_format();
2937 __nsn = __mp.negative_sign();
2938 __psn = __mp.positive_sign();
2939 __dp = __mp.decimal_point();
2940 __ts = __mp.thousands_sep();
2941 __grp = __mp.grouping();
2942 __sym = __mp.curr_symbol();
2943 __fd = __mp.frac_digits();
2944 }
2945}
2946
2947extern template class __money_get<char>;
2948extern template class __money_get<wchar_t>;
2949
2950template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00002951class _LIBCPP_VISIBLE money_get
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002952 : public locale::facet,
2953 private __money_get<_CharT>
2954{
2955public:
2956 typedef _CharT char_type;
2957 typedef _InputIterator iter_type;
2958 typedef basic_string<char_type> string_type;
2959
2960 _LIBCPP_ALWAYS_INLINE
2961 explicit money_get(size_t __refs = 0)
2962 : locale::facet(__refs) {}
2963
2964 _LIBCPP_ALWAYS_INLINE
2965 iter_type get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob,
2966 ios_base::iostate& __err, long double& __v) const
2967 {
2968 return do_get(__b, __e, __intl, __iob, __err, __v);
2969 }
2970
2971 _LIBCPP_ALWAYS_INLINE
2972 iter_type get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob,
2973 ios_base::iostate& __err, string_type& __v) const
2974 {
2975 return do_get(__b, __e, __intl, __iob, __err, __v);
2976 }
2977
2978 static locale::id id;
2979
2980protected:
2981
Howard Hinnant82894812010-09-22 16:48:34 +00002982 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002983 ~money_get() {}
Howard Hinnant324bb032010-08-22 00:02:43 +00002984
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002985 virtual iter_type do_get(iter_type __b, iter_type __e, bool __intl,
2986 ios_base& __iob, ios_base::iostate& __err,
2987 long double& __v) const;
2988 virtual iter_type do_get(iter_type __b, iter_type __e, bool __intl,
2989 ios_base& __iob, ios_base::iostate& __err,
2990 string_type& __v) const;
2991
2992private:
2993 static bool __do_get(iter_type& __b, iter_type __e,
2994 bool __intl, const locale& __loc,
2995 ios_base::fmtflags __flags, ios_base::iostate& __err,
2996 bool& __neg, const ctype<char_type>& __ct,
2997 unique_ptr<char_type, void(*)(void*)>& __wb,
2998 char_type*& __wn, char_type* __we);
2999};
3000
3001template <class _CharT, class _InputIterator>
3002locale::id
3003money_get<_CharT, _InputIterator>::id;
3004
3005void __do_nothing(void*);
3006
3007template <class _Tp>
3008_LIBCPP_HIDDEN
3009void
3010__double_or_nothing(unique_ptr<_Tp, void(*)(void*)>& __b, _Tp*& __n, _Tp*& __e)
3011{
3012 bool __owns = __b.get_deleter() != __do_nothing;
Howard Hinnantec3773c2011-12-01 20:21:04 +00003013 size_t __cur_cap = static_cast<size_t>(__e-__b.get()) * sizeof(_Tp);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003014 size_t __new_cap = __cur_cap < numeric_limits<size_t>::max() / 2 ?
3015 2 * __cur_cap : numeric_limits<size_t>::max();
Howard Hinnantec3773c2011-12-01 20:21:04 +00003016 size_t __n_off = static_cast<size_t>(__n - __b.get());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003017 _Tp* __t = (_Tp*)realloc(__owns ? __b.get() : 0, __new_cap);
3018 if (__t == 0)
3019 __throw_bad_alloc();
3020 if (__owns)
3021 __b.release();
3022 __b = unique_ptr<_Tp, void(*)(void*)>(__t, free);
3023 __new_cap /= sizeof(_Tp);
3024 __n = __b.get() + __n_off;
3025 __e = __b.get() + __new_cap;
3026}
3027
3028// true == success
3029template <class _CharT, class _InputIterator>
3030bool
3031money_get<_CharT, _InputIterator>::__do_get(iter_type& __b, iter_type __e,
3032 bool __intl, const locale& __loc,
3033 ios_base::fmtflags __flags,
3034 ios_base::iostate& __err,
3035 bool& __neg,
3036 const ctype<char_type>& __ct,
3037 unique_ptr<char_type, void(*)(void*)>& __wb,
3038 char_type*& __wn, char_type* __we)
3039{
3040 const unsigned __bz = 100;
3041 unsigned __gbuf[__bz];
3042 unique_ptr<unsigned, void(*)(void*)> __gb(__gbuf, __do_nothing);
3043 unsigned* __gn = __gb.get();
3044 unsigned* __ge = __gn + __bz;
3045 money_base::pattern __pat;
3046 char_type __dp;
3047 char_type __ts;
3048 string __grp;
3049 string_type __sym;
3050 string_type __psn;
3051 string_type __nsn;
3052 int __fd;
3053 __money_get<_CharT>::__gather_info(__intl, __loc, __pat, __dp, __ts, __grp,
3054 __sym, __psn, __nsn, __fd);
3055 const string_type* __trailing_sign = 0;
3056 __wn = __wb.get();
3057 for (unsigned __p = 0; __p < 4 && __b != __e; ++__p)
3058 {
3059 switch (__pat.field[__p])
3060 {
3061 case money_base::space:
3062 if (__p != 3)
3063 {
3064 if (__ct.is(ctype_base::space, *__b))
3065 ++__b;
3066 else
3067 {
3068 __err |= ios_base::failbit;
3069 return false;
3070 }
3071 }
Howard Hinnant324bb032010-08-22 00:02:43 +00003072 // drop through
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003073 case money_base::none:
3074 if (__p != 3)
3075 {
3076 while (__b != __e && __ct.is(ctype_base::space, *__b))
3077 ++__b;
3078 }
3079 break;
3080 case money_base::sign:
3081 if (__psn.size() + __nsn.size() > 0)
3082 {
3083 if (__psn.size() == 0 || __nsn.size() == 0)
3084 { // sign is optional
3085 if (__psn.size() > 0)
3086 { // __nsn.size() == 0
3087 if (*__b == __psn[0])
3088 {
3089 ++__b;
3090 if (__psn.size() > 1)
3091 __trailing_sign = &__psn;
3092 }
3093 else
3094 __neg = true;
3095 }
3096 else if (*__b == __nsn[0]) // __nsn.size() > 0 && __psn.size() == 0
3097 {
3098 ++__b;
3099 __neg = true;
3100 if (__nsn.size() > 1)
3101 __trailing_sign = &__nsn;
3102 }
3103 }
3104 else // sign is required
3105 {
3106 if (*__b == __psn[0])
3107 {
3108 ++__b;
3109 if (__psn.size() > 1)
3110 __trailing_sign = &__psn;
3111 }
3112 else if (*__b == __nsn[0])
3113 {
3114 ++__b;
3115 __neg = true;
3116 if (__nsn.size() > 1)
3117 __trailing_sign = &__nsn;
3118 }
3119 else
3120 {
3121 __err |= ios_base::failbit;
3122 return false;
3123 }
3124 }
3125 }
3126 break;
3127 case money_base::symbol:
3128 {
3129 bool __more_needed = __trailing_sign ||
3130 (__p < 2) ||
3131 (__p == 2 && __pat.field[3] != static_cast<char>(money_base::none));
3132 bool __sb = __flags & ios_base::showbase;
3133 if (__sb || __more_needed)
3134 {
3135 ios_base::iostate __et = ios_base::goodbit;
3136 string_type* __k = __scan_keyword(__b, __e, &__sym, &__sym+1,
3137 __ct, __et);
3138 if (__sb && __k != &__sym)
3139 {
3140 __err |= ios_base::failbit;
3141 return false;
3142 }
3143 }
3144 }
3145 break;
3146 case money_base::value:
3147 {
3148 unsigned __ng = 0;
3149 for (; __b != __e; ++__b)
3150 {
3151 char_type __c = *__b;
3152 if (__ct.is(ctype_base::digit, __c))
3153 {
3154 if (__wn == __we)
3155 __double_or_nothing(__wb, __wn, __we);
3156 *__wn++ = __c;
3157 ++__ng;
3158 }
3159 else if (__grp.size() > 0 && __ng > 0 && __c == __ts)
3160 {
3161 if (__gn == __ge)
3162 __double_or_nothing(__gb, __gn, __ge);
3163 *__gn++ = __ng;
3164 __ng = 0;
3165 }
3166 else
3167 break;
3168 }
3169 if (__gb.get() != __gn && __ng > 0)
3170 {
3171 if (__gn == __ge)
3172 __double_or_nothing(__gb, __gn, __ge);
3173 *__gn++ = __ng;
3174 }
3175 if (__fd > 0)
3176 {
3177 if (__b == __e || *__b != __dp)
3178 {
3179 __err |= ios_base::failbit;
3180 return false;
3181 }
3182 for (++__b; __fd > 0; --__fd, ++__b)
3183 {
3184 if (__b == __e || !__ct.is(ctype_base::digit, *__b))
3185 {
3186 __err |= ios_base::failbit;
3187 return false;
3188 }
3189 if (__wn == __we)
3190 __double_or_nothing(__wb, __wn, __we);
3191 *__wn++ = *__b;
3192 }
3193 }
3194 if (__wn == __wb.get())
3195 {
3196 __err |= ios_base::failbit;
3197 return false;
3198 }
3199 }
3200 break;
3201 }
3202 }
3203 if (__trailing_sign)
3204 {
3205 for (unsigned __i = 1; __i < __trailing_sign->size(); ++__i, ++__b)
3206 {
3207 if (__b == __e || *__b != (*__trailing_sign)[__i])
3208 {
3209 __err |= ios_base::failbit;
3210 return false;
3211 }
3212 }
3213 }
3214 if (__gb.get() != __gn)
3215 {
3216 ios_base::iostate __et = ios_base::goodbit;
3217 __check_grouping(__grp, __gb.get(), __gn, __et);
3218 if (__et)
3219 {
3220 __err |= ios_base::failbit;
3221 return false;
3222 }
3223 }
3224 return true;
3225}
3226
3227template <class _CharT, class _InputIterator>
3228_InputIterator
3229money_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
3230 bool __intl, ios_base& __iob,
3231 ios_base::iostate& __err,
3232 long double& __v) const
3233{
Howard Hinnantec3773c2011-12-01 20:21:04 +00003234 const int __bz = 100;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003235 char_type __wbuf[__bz];
3236 unique_ptr<char_type, void(*)(void*)> __wb(__wbuf, __do_nothing);
3237 char_type* __wn;
3238 char_type* __we = __wbuf + __bz;
3239 locale __loc = __iob.getloc();
3240 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3241 bool __neg = false;
3242 if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct,
3243 __wb, __wn, __we))
3244 {
3245 const char __src[] = "0123456789";
3246 char_type __atoms[sizeof(__src)-1];
3247 __ct.widen(__src, __src + (sizeof(__src)-1), __atoms);
3248 char __nbuf[__bz];
3249 char* __nc = __nbuf;
3250 unique_ptr<char, void(*)(void*)> __h(0, free);
3251 if (__wn - __wb.get() > __bz-2)
3252 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00003253 __h.reset((char*)malloc(static_cast<size_t>(__wn - __wb.get() + 2)));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003254 if (__h.get() == 0)
3255 __throw_bad_alloc();
3256 __nc = __h.get();
3257 }
3258 if (__neg)
3259 *__nc++ = '-';
3260 for (const char_type* __w = __wb.get(); __w < __wn; ++__w, ++__nc)
3261 *__nc = __src[find(__atoms, __atoms+sizeof(__atoms), *__w) - __atoms];
3262 *__nc = char();
3263 if (sscanf(__nbuf, "%Lf", &__v) != 1)
3264 __throw_runtime_error("money_get error");
3265 }
3266 if (__b == __e)
3267 __err |= ios_base::eofbit;
3268 return __b;
3269}
3270
3271template <class _CharT, class _InputIterator>
3272_InputIterator
3273money_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
3274 bool __intl, ios_base& __iob,
3275 ios_base::iostate& __err,
3276 string_type& __v) const
3277{
Howard Hinnantec3773c2011-12-01 20:21:04 +00003278 const int __bz = 100;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003279 char_type __wbuf[__bz];
3280 unique_ptr<char_type, void(*)(void*)> __wb(__wbuf, __do_nothing);
3281 char_type* __wn;
3282 char_type* __we = __wbuf + __bz;
3283 locale __loc = __iob.getloc();
3284 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3285 bool __neg = false;
3286 if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct,
3287 __wb, __wn, __we))
3288 {
3289 __v.clear();
3290 if (__neg)
3291 __v.push_back(__ct.widen('-'));
3292 char_type __z = __ct.widen('0');
3293 char_type* __w;
3294 for (__w = __wb.get(); __w < __wn-1; ++__w)
3295 if (*__w != __z)
3296 break;
3297 __v.append(__w, __wn);
3298 }
3299 if (__b == __e)
3300 __err |= ios_base::eofbit;
3301 return __b;
3302}
3303
3304extern template class money_get<char>;
3305extern template class money_get<wchar_t>;
3306
3307// money_put
3308
3309template <class _CharT>
3310class __money_put
3311{
3312protected:
3313 typedef _CharT char_type;
3314 typedef basic_string<char_type> string_type;
3315
3316 _LIBCPP_ALWAYS_INLINE __money_put() {}
3317
3318 static void __gather_info(bool __intl, bool __neg, const locale& __loc,
3319 money_base::pattern& __pat, char_type& __dp,
3320 char_type& __ts, string& __grp,
3321 string_type& __sym, string_type& __sn,
3322 int& __fd);
3323 static void __format(char_type* __mb, char_type*& __mi, char_type*& __me,
3324 ios_base::fmtflags __flags,
3325 const char_type* __db, const char_type* __de,
3326 const ctype<char_type>& __ct, bool __neg,
3327 const money_base::pattern& __pat, char_type __dp,
3328 char_type __ts, const string& __grp,
3329 const string_type& __sym, const string_type& __sn,
3330 int __fd);
3331};
3332
3333template <class _CharT>
3334void
3335__money_put<_CharT>::__gather_info(bool __intl, bool __neg, const locale& __loc,
3336 money_base::pattern& __pat, char_type& __dp,
3337 char_type& __ts, string& __grp,
3338 string_type& __sym, string_type& __sn,
3339 int& __fd)
3340{
3341 if (__intl)
3342 {
3343 const moneypunct<char_type, true>& __mp =
3344 use_facet<moneypunct<char_type, true> >(__loc);
3345 if (__neg)
3346 {
3347 __pat = __mp.neg_format();
3348 __sn = __mp.negative_sign();
3349 }
3350 else
3351 {
3352 __pat = __mp.pos_format();
3353 __sn = __mp.positive_sign();
3354 }
3355 __dp = __mp.decimal_point();
3356 __ts = __mp.thousands_sep();
3357 __grp = __mp.grouping();
3358 __sym = __mp.curr_symbol();
3359 __fd = __mp.frac_digits();
3360 }
3361 else
3362 {
3363 const moneypunct<char_type, false>& __mp =
3364 use_facet<moneypunct<char_type, false> >(__loc);
3365 if (__neg)
3366 {
3367 __pat = __mp.neg_format();
3368 __sn = __mp.negative_sign();
3369 }
3370 else
3371 {
3372 __pat = __mp.pos_format();
3373 __sn = __mp.positive_sign();
3374 }
3375 __dp = __mp.decimal_point();
3376 __ts = __mp.thousands_sep();
3377 __grp = __mp.grouping();
3378 __sym = __mp.curr_symbol();
3379 __fd = __mp.frac_digits();
3380 }
3381}
3382
3383template <class _CharT>
3384void
3385__money_put<_CharT>::__format(char_type* __mb, char_type*& __mi, char_type*& __me,
3386 ios_base::fmtflags __flags,
3387 const char_type* __db, const char_type* __de,
3388 const ctype<char_type>& __ct, bool __neg,
3389 const money_base::pattern& __pat, char_type __dp,
3390 char_type __ts, const string& __grp,
3391 const string_type& __sym, const string_type& __sn,
3392 int __fd)
3393{
3394 __me = __mb;
3395 for (unsigned __p = 0; __p < 4; ++__p)
3396 {
3397 switch (__pat.field[__p])
3398 {
3399 case money_base::none:
3400 __mi = __me;
3401 break;
3402 case money_base::space:
3403 __mi = __me;
3404 *__me++ = __ct.widen(' ');
3405 break;
3406 case money_base::sign:
3407 if (!__sn.empty())
3408 *__me++ = __sn[0];
3409 break;
3410 case money_base::symbol:
3411 if (!__sym.empty() && (__flags & ios_base::showbase))
Howard Hinnant0949eed2011-06-30 21:18:19 +00003412 __me = _VSTD::copy(__sym.begin(), __sym.end(), __me);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003413 break;
3414 case money_base::value:
3415 {
3416 // remember start of value so we can reverse it
3417 char_type* __t = __me;
3418 // find beginning of digits
3419 if (__neg)
3420 ++__db;
3421 // find end of digits
3422 const char_type* __d;
3423 for (__d = __db; __d < __de; ++__d)
3424 if (!__ct.is(ctype_base::digit, *__d))
3425 break;
3426 // print fractional part
3427 if (__fd > 0)
3428 {
3429 int __f;
3430 for (__f = __fd; __d > __db && __f > 0; --__f)
3431 *__me++ = *--__d;
3432 char_type __z = __f > 0 ? __ct.widen('0') : char_type();
3433 for (; __f > 0; --__f)
3434 *__me++ = __z;
3435 *__me++ = __dp;
3436 }
3437 // print units part
3438 if (__d == __db)
3439 {
3440 *__me++ = __ct.widen('0');
3441 }
3442 else
3443 {
3444 unsigned __ng = 0;
3445 unsigned __ig = 0;
3446 unsigned __gl = __grp.empty() ? numeric_limits<unsigned>::max()
3447 : static_cast<unsigned>(__grp[__ig]);
3448 while (__d != __db)
3449 {
3450 if (__ng == __gl)
3451 {
3452 *__me++ = __ts;
3453 __ng = 0;
3454 if (++__ig < __grp.size())
3455 __gl = __grp[__ig] == numeric_limits<char>::max() ?
3456 numeric_limits<unsigned>::max() :
3457 static_cast<unsigned>(__grp[__ig]);
3458 }
3459 *__me++ = *--__d;
3460 ++__ng;
3461 }
3462 }
3463 // reverse it
3464 reverse(__t, __me);
3465 }
3466 break;
3467 }
3468 }
3469 // print rest of sign, if any
3470 if (__sn.size() > 1)
Howard Hinnant0949eed2011-06-30 21:18:19 +00003471 __me = _VSTD::copy(__sn.begin()+1, __sn.end(), __me);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003472 // set alignment
3473 if ((__flags & ios_base::adjustfield) == ios_base::left)
3474 __mi = __me;
3475 else if ((__flags & ios_base::adjustfield) != ios_base::internal)
3476 __mi = __mb;
3477}
3478
3479extern template class __money_put<char>;
3480extern template class __money_put<wchar_t>;
3481
3482template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00003483class _LIBCPP_VISIBLE money_put
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003484 : public locale::facet,
3485 private __money_put<_CharT>
3486{
3487public:
3488 typedef _CharT char_type;
3489 typedef _OutputIterator iter_type;
3490 typedef basic_string<char_type> string_type;
3491
3492 _LIBCPP_ALWAYS_INLINE
3493 explicit money_put(size_t __refs = 0)
3494 : locale::facet(__refs) {}
3495
3496 _LIBCPP_ALWAYS_INLINE
3497 iter_type put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl,
3498 long double __units) const
3499 {
3500 return do_put(__s, __intl, __iob, __fl, __units);
3501 }
3502
3503 _LIBCPP_ALWAYS_INLINE
3504 iter_type put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl,
3505 const string_type& __digits) const
3506 {
3507 return do_put(__s, __intl, __iob, __fl, __digits);
3508 }
3509
3510 static locale::id id;
3511
3512protected:
Howard Hinnant82894812010-09-22 16:48:34 +00003513 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003514 ~money_put() {}
3515
3516 virtual iter_type do_put(iter_type __s, bool __intl, ios_base& __iob,
3517 char_type __fl, long double __units) const;
3518 virtual iter_type do_put(iter_type __s, bool __intl, ios_base& __iob,
3519 char_type __fl, const string_type& __digits) const;
3520};
3521
3522template <class _CharT, class _OutputIterator>
3523locale::id
3524money_put<_CharT, _OutputIterator>::id;
3525
3526template <class _CharT, class _OutputIterator>
3527_OutputIterator
3528money_put<_CharT, _OutputIterator>::do_put(iter_type __s, bool __intl,
3529 ios_base& __iob, char_type __fl,
3530 long double __units) const
3531{
3532 // convert to char
3533 const size_t __bs = 100;
3534 char __buf[__bs];
3535 char* __bb = __buf;
3536 char_type __digits[__bs];
3537 char_type* __db = __digits;
Howard Hinnantec3773c2011-12-01 20:21:04 +00003538 size_t __n = static_cast<size_t>(snprintf(__bb, __bs, "%.0Lf", __units));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003539 unique_ptr<char, void(*)(void*)> __hn(0, free);
3540 unique_ptr<char_type, void(*)(void*)> __hd(0, free);
3541 // secure memory for digit storage
3542 if (__n > __bs-1)
3543 {
Howard Hinnant866569b2011-09-28 23:39:33 +00003544#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00003545 __n = static_cast<size_t>(asprintf_l(&__bb, _LIBCPP_GET_C_LOCALE, "%.0Lf", __units));
Sean Huntf3907e62011-07-15 05:40:33 +00003546#else
3547 __n = __asprintf_l(&__bb, __cloc(), "%.0Lf", __units);
3548#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003549 if (__bb == 0)
3550 __throw_bad_alloc();
3551 __hn.reset(__bb);
3552 __hd.reset((char_type*)malloc(__n * sizeof(char_type)));
3553 if (__hd == 0)
3554 __throw_bad_alloc();
3555 __db = __hd.get();
3556 }
3557 // gather info
3558 locale __loc = __iob.getloc();
3559 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3560 __ct.widen(__bb, __bb + __n, __db);
3561 bool __neg = __n > 0 && __bb[0] == '-';
3562 money_base::pattern __pat;
3563 char_type __dp;
3564 char_type __ts;
3565 string __grp;
3566 string_type __sym;
3567 string_type __sn;
3568 int __fd;
3569 this->__gather_info(__intl, __neg, __loc, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3570 // secure memory for formatting
3571 char_type __mbuf[__bs];
3572 char_type* __mb = __mbuf;
3573 unique_ptr<char_type, void(*)(void*)> __hw(0, free);
3574 size_t __exn = static_cast<int>(__n) > __fd ?
Howard Hinnantec3773c2011-12-01 20:21:04 +00003575 (__n - static_cast<size_t>(__fd)) * 2 + __sn.size() +
3576 __sym.size() + static_cast<size_t>(__fd) + 1
3577 : __sn.size() + __sym.size() + static_cast<size_t>(__fd) + 2;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003578 if (__exn > __bs)
3579 {
3580 __hw.reset((char_type*)malloc(__exn * sizeof(char_type)));
3581 __mb = __hw.get();
3582 if (__mb == 0)
3583 __throw_bad_alloc();
3584 }
3585 // format
3586 char_type* __mi;
3587 char_type* __me;
3588 this->__format(__mb, __mi, __me, __iob.flags(),
3589 __db, __db + __n, __ct,
3590 __neg, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3591 return __pad_and_output(__s, __mb, __mi, __me, __iob, __fl);
3592}
3593
3594template <class _CharT, class _OutputIterator>
3595_OutputIterator
3596money_put<_CharT, _OutputIterator>::do_put(iter_type __s, bool __intl,
3597 ios_base& __iob, char_type __fl,
3598 const string_type& __digits) const
3599{
3600 // gather info
3601 locale __loc = __iob.getloc();
3602 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3603 bool __neg = __digits.size() > 0 && __digits[0] == __ct.widen('-');
3604 money_base::pattern __pat;
3605 char_type __dp;
3606 char_type __ts;
3607 string __grp;
3608 string_type __sym;
3609 string_type __sn;
3610 int __fd;
3611 this->__gather_info(__intl, __neg, __loc, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3612 // secure memory for formatting
3613 char_type __mbuf[100];
3614 char_type* __mb = __mbuf;
3615 unique_ptr<char_type, void(*)(void*)> __h(0, free);
Howard Hinnantec3773c2011-12-01 20:21:04 +00003616 size_t __exn = static_cast<int>(__digits.size()) > __fd ?
3617 (__digits.size() - static_cast<size_t>(__fd)) * 2 +
3618 __sn.size() + __sym.size() + static_cast<size_t>(__fd) + 1
3619 : __sn.size() + __sym.size() + static_cast<size_t>(__fd) + 2;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003620 if (__exn > 100)
3621 {
3622 __h.reset((char_type*)malloc(__exn * sizeof(char_type)));
3623 __mb = __h.get();
3624 if (__mb == 0)
3625 __throw_bad_alloc();
3626 }
3627 // format
3628 char_type* __mi;
3629 char_type* __me;
3630 this->__format(__mb, __mi, __me, __iob.flags(),
3631 __digits.data(), __digits.data() + __digits.size(), __ct,
3632 __neg, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3633 return __pad_and_output(__s, __mb, __mi, __me, __iob, __fl);
3634}
3635
3636extern template class money_put<char>;
3637extern template class money_put<wchar_t>;
3638
3639// messages
3640
Howard Hinnant82894812010-09-22 16:48:34 +00003641class _LIBCPP_VISIBLE messages_base
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003642{
3643public:
Howard Hinnantb2080c72011-02-25 00:51:08 +00003644 typedef ptrdiff_t catalog;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003645
3646 _LIBCPP_ALWAYS_INLINE messages_base() {}
3647};
3648
3649template <class _CharT>
Howard Hinnant82894812010-09-22 16:48:34 +00003650class _LIBCPP_VISIBLE messages
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003651 : public locale::facet,
3652 public messages_base
3653{
3654public:
3655 typedef _CharT char_type;
3656 typedef basic_string<_CharT> string_type;
3657
3658 _LIBCPP_ALWAYS_INLINE
3659 explicit messages(size_t __refs = 0)
3660 : locale::facet(__refs) {}
3661
3662 _LIBCPP_ALWAYS_INLINE
3663 catalog open(const basic_string<char>& __nm, const locale& __loc) const
3664 {
3665 return do_open(__nm, __loc);
3666 }
3667
3668 _LIBCPP_ALWAYS_INLINE
3669 string_type get(catalog __c, int __set, int __msgid,
3670 const string_type& __dflt) const
3671 {
3672 return do_get(__c, __set, __msgid, __dflt);
3673 }
3674
3675 _LIBCPP_ALWAYS_INLINE
3676 void close(catalog __c) const
3677 {
3678 do_close(__c);
3679 }
3680
3681 static locale::id id;
3682
3683protected:
Howard Hinnant82894812010-09-22 16:48:34 +00003684 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003685 ~messages() {}
3686
3687 virtual catalog do_open(const basic_string<char>&, const locale&) const;
3688 virtual string_type do_get(catalog, int __set, int __msgid,
3689 const string_type& __dflt) const;
3690 virtual void do_close(catalog) const;
3691};
3692
3693template <class _CharT>
3694locale::id
3695messages<_CharT>::id;
3696
3697template <class _CharT>
3698typename messages<_CharT>::catalog
3699messages<_CharT>::do_open(const basic_string<char>& __nm, const locale&) const
3700{
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00003701#if _WIN32
3702 return -1;
3703#else // _WIN32
Howard Hinnant11624452011-10-11 16:00:46 +00003704 catalog __cat = (catalog)catopen(__nm.c_str(), NL_CAT_LOCALE);
Howard Hinnantb2080c72011-02-25 00:51:08 +00003705 if (__cat != -1)
3706 __cat = static_cast<catalog>((static_cast<size_t>(__cat) >> 1));
3707 return __cat;
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00003708#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003709}
3710
3711template <class _CharT>
3712typename messages<_CharT>::string_type
3713messages<_CharT>::do_get(catalog __c, int __set, int __msgid,
3714 const string_type& __dflt) const
3715{
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00003716#if _WIN32
3717 return __dflt;
3718#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003719 string __ndflt;
3720 __narrow_to_utf8<sizeof(char_type)*__CHAR_BIT__>()(back_inserter(__ndflt),
3721 __dflt.c_str(),
3722 __dflt.c_str() + __dflt.size());
Howard Hinnantb2080c72011-02-25 00:51:08 +00003723 if (__c != -1)
3724 __c <<= 1;
Howard Hinnant11624452011-10-11 16:00:46 +00003725 nl_catd __cat = (nl_catd)__c;
Howard Hinnantb2080c72011-02-25 00:51:08 +00003726 char* __n = catgets(__cat, __set, __msgid, __ndflt.c_str());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003727 string_type __w;
3728 __widen_from_utf8<sizeof(char_type)*__CHAR_BIT__>()(back_inserter(__w),
3729 __n, __n + strlen(__n));
3730 return __w;
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00003731#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003732}
3733
3734template <class _CharT>
3735void
3736messages<_CharT>::do_close(catalog __c) const
3737{
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00003738#if !_WIN32
Howard Hinnantb2080c72011-02-25 00:51:08 +00003739 if (__c != -1)
3740 __c <<= 1;
Howard Hinnant11624452011-10-11 16:00:46 +00003741 nl_catd __cat = (nl_catd)__c;
Howard Hinnantb2080c72011-02-25 00:51:08 +00003742 catclose(__cat);
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00003743#endif // !_WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003744}
3745
3746extern template class messages<char>;
3747extern template class messages<wchar_t>;
3748
3749template <class _CharT>
Howard Hinnant82894812010-09-22 16:48:34 +00003750class _LIBCPP_VISIBLE messages_byname
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003751 : public messages<_CharT>
3752{
3753public:
3754 typedef messages_base::catalog catalog;
3755 typedef basic_string<_CharT> string_type;
3756
3757 _LIBCPP_ALWAYS_INLINE
3758 explicit messages_byname(const char*, size_t __refs = 0)
3759 : messages<_CharT>(__refs) {}
3760
3761 _LIBCPP_ALWAYS_INLINE
3762 explicit messages_byname(const string&, size_t __refs = 0)
3763 : messages<_CharT>(__refs) {}
3764
3765protected:
Howard Hinnant82894812010-09-22 16:48:34 +00003766 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003767 ~messages_byname() {}
3768};
3769
3770extern template class messages_byname<char>;
3771extern template class messages_byname<wchar_t>;
3772
Howard Hinnantd23b4642010-05-31 20:58:54 +00003773template<class _Codecvt, class _Elem = wchar_t,
3774 class _Wide_alloc = allocator<_Elem>,
3775 class _Byte_alloc = allocator<char> >
Howard Hinnant82894812010-09-22 16:48:34 +00003776class _LIBCPP_VISIBLE wstring_convert
Howard Hinnantd23b4642010-05-31 20:58:54 +00003777{
3778public:
3779 typedef basic_string<char, char_traits<char>, _Byte_alloc> byte_string;
3780 typedef basic_string<_Elem, char_traits<_Elem>, _Wide_alloc> wide_string;
3781 typedef typename _Codecvt::state_type state_type;
3782 typedef typename wide_string::traits_type::int_type int_type;
3783
3784private:
3785 byte_string __byte_err_string_;
3786 wide_string __wide_err_string_;
3787 _Codecvt* __cvtptr_;
3788 state_type __cvtstate_;
3789 size_t __cvtcount_;
3790
3791 wstring_convert(const wstring_convert& __wc);
3792 wstring_convert& operator=(const wstring_convert& __wc);
3793public:
3794 wstring_convert(_Codecvt* __pcvt = new _Codecvt);
3795 wstring_convert(_Codecvt* __pcvt, state_type __state);
3796 wstring_convert(const byte_string& __byte_err,
3797 const wide_string& __wide_err = wide_string());
Howard Hinnant73d21a42010-09-04 23:28:19 +00003798#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantd23b4642010-05-31 20:58:54 +00003799 wstring_convert(wstring_convert&& __wc);
3800#endif
3801 ~wstring_convert();
3802
Howard Hinnant82894812010-09-22 16:48:34 +00003803 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003804 wide_string from_bytes(char __byte)
3805 {return from_bytes(&__byte, &__byte+1);}
Howard Hinnant82894812010-09-22 16:48:34 +00003806 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003807 wide_string from_bytes(const char* __ptr)
3808 {return from_bytes(__ptr, __ptr + char_traits<char>::length(__ptr));}
Howard Hinnant82894812010-09-22 16:48:34 +00003809 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003810 wide_string from_bytes(const byte_string& __str)
3811 {return from_bytes(__str.data(), __str.data() + __str.size());}
3812 wide_string from_bytes(const char* __first, const char* __last);
3813
Howard Hinnant82894812010-09-22 16:48:34 +00003814 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003815 byte_string to_bytes(_Elem __wchar)
3816 {return to_bytes(&__wchar, &__wchar+1);}
Howard Hinnant82894812010-09-22 16:48:34 +00003817 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003818 byte_string to_bytes(const _Elem* __wptr)
3819 {return to_bytes(__wptr, __wptr + char_traits<_Elem>::length(__wptr));}
Howard Hinnant82894812010-09-22 16:48:34 +00003820 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003821 byte_string to_bytes(const wide_string& __wstr)
3822 {return to_bytes(__wstr.data(), __wstr.data() + __wstr.size());}
3823 byte_string to_bytes(const _Elem* __first, const _Elem* __last);
3824
Howard Hinnant82894812010-09-22 16:48:34 +00003825 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003826 size_t converted() const {return __cvtcount_;}
Howard Hinnant82894812010-09-22 16:48:34 +00003827 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003828 state_type state() const {return __cvtstate_;}
3829};
3830
3831template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Howard Hinnant82894812010-09-22 16:48:34 +00003832inline _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003833wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3834 wstring_convert(_Codecvt* __pcvt)
3835 : __cvtptr_(__pcvt), __cvtstate_(), __cvtcount_(0)
3836{
3837}
3838
3839template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Howard Hinnant82894812010-09-22 16:48:34 +00003840inline _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003841wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3842 wstring_convert(_Codecvt* __pcvt, state_type __state)
3843 : __cvtptr_(__pcvt), __cvtstate_(__state), __cvtcount_(0)
3844{
3845}
3846
3847template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3848wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3849 wstring_convert(const byte_string& __byte_err, const wide_string& __wide_err)
3850 : __byte_err_string_(__byte_err), __wide_err_string_(__wide_err),
3851 __cvtstate_(), __cvtcount_(0)
3852{
3853 __cvtptr_ = new _Codecvt;
3854}
3855
Howard Hinnant73d21a42010-09-04 23:28:19 +00003856#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantd23b4642010-05-31 20:58:54 +00003857
3858template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Howard Hinnant82894812010-09-22 16:48:34 +00003859inline _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003860wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3861 wstring_convert(wstring_convert&& __wc)
Howard Hinnant0949eed2011-06-30 21:18:19 +00003862 : __byte_err_string_(_VSTD::move(__wc.__byte_err_string_)),
3863 __wide_err_string_(_VSTD::move(__wc.__wide_err_string_)),
Howard Hinnantd23b4642010-05-31 20:58:54 +00003864 __cvtptr_(__wc.__cvtptr_),
3865 __cvtstate_(__wc.__cvtstate_), __cvtcount_(__wc.__cvtstate_)
3866{
3867 __wc.__cvtptr_ = nullptr;
3868}
3869
Howard Hinnantbfd55302010-09-04 23:46:48 +00003870#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantd23b4642010-05-31 20:58:54 +00003871
3872template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3873wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::~wstring_convert()
3874{
3875 delete __cvtptr_;
3876}
3877
3878template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3879typename wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::wide_string
3880wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3881 from_bytes(const char* __frm, const char* __frm_end)
3882{
3883 __cvtcount_ = 0;
3884 if (__cvtptr_ != nullptr)
3885 {
3886 wide_string __ws(2*(__frm_end - __frm), _Elem());
3887 __ws.resize(__ws.capacity());
3888 codecvt_base::result __r = codecvt_base::ok;
3889 state_type __st = __cvtstate_;
3890 if (__frm != __frm_end)
3891 {
3892 _Elem* __to = &__ws[0];
3893 _Elem* __to_end = __to + __ws.size();
3894 const char* __frm_nxt;
3895 do
3896 {
3897 _Elem* __to_nxt;
3898 __r = __cvtptr_->in(__st, __frm, __frm_end, __frm_nxt,
3899 __to, __to_end, __to_nxt);
3900 __cvtcount_ += __frm_nxt - __frm;
3901 if (__frm_nxt == __frm)
3902 {
3903 __r = codecvt_base::error;
3904 }
3905 else if (__r == codecvt_base::noconv)
3906 {
3907 __ws.resize(__to - &__ws[0]);
3908 // This only gets executed if _Elem is char
3909 __ws.append((const _Elem*)__frm, (const _Elem*)__frm_end);
3910 __frm = __frm_nxt;
3911 __r = codecvt_base::ok;
3912 }
3913 else if (__r == codecvt_base::ok)
3914 {
3915 __ws.resize(__to_nxt - &__ws[0]);
3916 __frm = __frm_nxt;
3917 }
3918 else if (__r == codecvt_base::partial)
3919 {
3920 ptrdiff_t __s = __to_nxt - &__ws[0];
3921 __ws.resize(2 * __s);
3922 __to = &__ws[0] + __s;
3923 __to_end = &__ws[0] + __ws.size();
3924 __frm = __frm_nxt;
3925 }
3926 } while (__r == codecvt_base::partial && __frm_nxt < __frm_end);
3927 }
3928 if (__r == codecvt_base::ok)
3929 return __ws;
3930 }
Howard Hinnantd4444702010-08-11 17:04:31 +00003931#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00003932 if (__wide_err_string_.empty())
3933 throw range_error("wstring_convert: from_bytes error");
Howard Hinnant324bb032010-08-22 00:02:43 +00003934#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00003935 return __wide_err_string_;
3936}
3937
3938template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3939typename wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::byte_string
3940wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3941 to_bytes(const _Elem* __frm, const _Elem* __frm_end)
3942{
3943 __cvtcount_ = 0;
3944 if (__cvtptr_ != nullptr)
3945 {
3946 byte_string __bs(2*(__frm_end - __frm), char());
3947 __bs.resize(__bs.capacity());
3948 codecvt_base::result __r = codecvt_base::ok;
3949 state_type __st = __cvtstate_;
3950 if (__frm != __frm_end)
3951 {
3952 char* __to = &__bs[0];
3953 char* __to_end = __to + __bs.size();
3954 const _Elem* __frm_nxt;
3955 do
3956 {
3957 char* __to_nxt;
3958 __r = __cvtptr_->out(__st, __frm, __frm_end, __frm_nxt,
3959 __to, __to_end, __to_nxt);
3960 __cvtcount_ += __frm_nxt - __frm;
3961 if (__frm_nxt == __frm)
3962 {
3963 __r = codecvt_base::error;
3964 }
3965 else if (__r == codecvt_base::noconv)
3966 {
3967 __bs.resize(__to - &__bs[0]);
3968 // This only gets executed if _Elem is char
3969 __bs.append((const char*)__frm, (const char*)__frm_end);
3970 __frm = __frm_nxt;
3971 __r = codecvt_base::ok;
3972 }
3973 else if (__r == codecvt_base::ok)
3974 {
3975 __bs.resize(__to_nxt - &__bs[0]);
3976 __frm = __frm_nxt;
3977 }
3978 else if (__r == codecvt_base::partial)
3979 {
3980 ptrdiff_t __s = __to_nxt - &__bs[0];
3981 __bs.resize(2 * __s);
3982 __to = &__bs[0] + __s;
3983 __to_end = &__bs[0] + __bs.size();
3984 __frm = __frm_nxt;
3985 }
3986 } while (__r == codecvt_base::partial && __frm_nxt < __frm_end);
3987 }
3988 if (__r == codecvt_base::ok)
3989 {
3990 size_t __s = __bs.size();
3991 __bs.resize(__bs.capacity());
3992 char* __to = &__bs[0] + __s;
3993 char* __to_end = __to + __bs.size();
3994 do
3995 {
3996 char* __to_nxt;
3997 __r = __cvtptr_->unshift(__st, __to, __to_end, __to_nxt);
3998 if (__r == codecvt_base::noconv)
3999 {
4000 __bs.resize(__to - &__bs[0]);
4001 __r = codecvt_base::ok;
4002 }
4003 else if (__r == codecvt_base::ok)
4004 {
4005 __bs.resize(__to_nxt - &__bs[0]);
4006 }
4007 else if (__r == codecvt_base::partial)
4008 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00004009 ptrdiff_t __sp = __to_nxt - &__bs[0];
4010 __bs.resize(2 * __sp);
4011 __to = &__bs[0] + __sp;
Howard Hinnantd23b4642010-05-31 20:58:54 +00004012 __to_end = &__bs[0] + __bs.size();
4013 }
4014 } while (__r == codecvt_base::partial);
4015 if (__r == codecvt_base::ok)
4016 return __bs;
4017 }
4018 }
Howard Hinnantd4444702010-08-11 17:04:31 +00004019#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00004020 if (__byte_err_string_.empty())
4021 throw range_error("wstring_convert: to_bytes error");
Howard Hinnant324bb032010-08-22 00:02:43 +00004022#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00004023 return __byte_err_string_;
4024}
4025
4026template <class _Codecvt, class _Elem = wchar_t, class _Tr = char_traits<_Elem> >
Howard Hinnant82894812010-09-22 16:48:34 +00004027class _LIBCPP_VISIBLE wbuffer_convert
Howard Hinnantd23b4642010-05-31 20:58:54 +00004028 : public basic_streambuf<_Elem, _Tr>
4029{
4030public:
4031 // types:
4032 typedef _Elem char_type;
4033 typedef _Tr traits_type;
4034 typedef typename traits_type::int_type int_type;
4035 typedef typename traits_type::pos_type pos_type;
4036 typedef typename traits_type::off_type off_type;
4037 typedef typename _Codecvt::state_type state_type;
4038
4039private:
Howard Hinnant4b53f502010-06-01 20:09:18 +00004040 char* __extbuf_;
4041 const char* __extbufnext_;
4042 const char* __extbufend_;
4043 char __extbuf_min_[8];
4044 size_t __ebs_;
4045 char_type* __intbuf_;
4046 size_t __ibs_;
Howard Hinnantd23b4642010-05-31 20:58:54 +00004047 streambuf* __bufptr_;
Howard Hinnant4b53f502010-06-01 20:09:18 +00004048 _Codecvt* __cv_;
4049 state_type __st_;
4050 ios_base::openmode __cm_;
4051 bool __owns_eb_;
4052 bool __owns_ib_;
4053 bool __always_noconv_;
Howard Hinnantd23b4642010-05-31 20:58:54 +00004054
Howard Hinnant4b53f502010-06-01 20:09:18 +00004055 wbuffer_convert(const wbuffer_convert&);
4056 wbuffer_convert& operator=(const wbuffer_convert&);
Howard Hinnantd23b4642010-05-31 20:58:54 +00004057public:
4058 wbuffer_convert(streambuf* __bytebuf = 0, _Codecvt* __pcvt = new _Codecvt,
Howard Hinnant4b53f502010-06-01 20:09:18 +00004059 state_type __state = state_type());
4060 ~wbuffer_convert();
Howard Hinnantd23b4642010-05-31 20:58:54 +00004061
Howard Hinnant82894812010-09-22 16:48:34 +00004062 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantd23b4642010-05-31 20:58:54 +00004063 streambuf* rdbuf() const {return __bufptr_;}
Howard Hinnant82894812010-09-22 16:48:34 +00004064 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantd23b4642010-05-31 20:58:54 +00004065 streambuf* rdbuf(streambuf* __bytebuf)
4066 {
4067 streambuf* __r = __bufptr_;
4068 __bufptr_ = __bytebuf;
4069 return __r;
4070 }
4071
Howard Hinnant82894812010-09-22 16:48:34 +00004072 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant4b53f502010-06-01 20:09:18 +00004073 state_type state() const {return __st_;}
Howard Hinnantd23b4642010-05-31 20:58:54 +00004074
4075protected:
Howard Hinnant4b53f502010-06-01 20:09:18 +00004076 virtual int_type underflow();
4077 virtual int_type pbackfail(int_type __c = traits_type::eof());
Howard Hinnantd23b4642010-05-31 20:58:54 +00004078 virtual int_type overflow (int_type __c = traits_type::eof());
Howard Hinnant4b53f502010-06-01 20:09:18 +00004079 virtual basic_streambuf<char_type, traits_type>* setbuf(char_type* __s,
4080 streamsize __n);
4081 virtual pos_type seekoff(off_type __off, ios_base::seekdir __way,
4082 ios_base::openmode __wch = ios_base::in | ios_base::out);
4083 virtual pos_type seekpos(pos_type __sp,
4084 ios_base::openmode __wch = ios_base::in | ios_base::out);
4085 virtual int sync();
4086
4087private:
4088 bool __read_mode();
4089 void __write_mode();
4090 wbuffer_convert* __close();
Howard Hinnantd23b4642010-05-31 20:58:54 +00004091};
4092
4093template <class _Codecvt, class _Elem, class _Tr>
Howard Hinnant4b53f502010-06-01 20:09:18 +00004094wbuffer_convert<_Codecvt, _Elem, _Tr>::
4095 wbuffer_convert(streambuf* __bytebuf, _Codecvt* __pcvt, state_type __state)
4096 : __extbuf_(0),
4097 __extbufnext_(0),
4098 __extbufend_(0),
4099 __ebs_(0),
4100 __intbuf_(0),
4101 __ibs_(0),
4102 __bufptr_(__bytebuf),
4103 __cv_(__pcvt),
4104 __st_(__state),
4105 __cm_(0),
4106 __owns_eb_(false),
4107 __owns_ib_(false),
4108 __always_noconv_(__cv_ ? __cv_->always_noconv() : false)
4109{
4110 setbuf(0, 4096);
4111}
4112
4113template <class _Codecvt, class _Elem, class _Tr>
4114wbuffer_convert<_Codecvt, _Elem, _Tr>::~wbuffer_convert()
4115{
4116 __close();
4117 delete __cv_;
4118 if (__owns_eb_)
4119 delete [] __extbuf_;
4120 if (__owns_ib_)
4121 delete [] __intbuf_;
4122}
4123
4124template <class _Codecvt, class _Elem, class _Tr>
4125typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
4126wbuffer_convert<_Codecvt, _Elem, _Tr>::underflow()
4127{
4128 if (__cv_ == 0 || __bufptr_ == 0)
4129 return traits_type::eof();
4130 bool __initial = __read_mode();
4131 char_type __1buf;
4132 if (this->gptr() == 0)
4133 this->setg(&__1buf, &__1buf+1, &__1buf+1);
4134 const size_t __unget_sz = __initial ? 0 : min<size_t>((this->egptr() - this->eback()) / 2, 4);
4135 int_type __c = traits_type::eof();
4136 if (this->gptr() == this->egptr())
4137 {
4138 memmove(this->eback(), this->egptr() - __unget_sz, __unget_sz * sizeof(char_type));
4139 if (__always_noconv_)
4140 {
4141 streamsize __nmemb = static_cast<streamsize>(this->egptr() - this->eback() - __unget_sz);
4142 __nmemb = __bufptr_->sgetn((char*)this->eback() + __unget_sz, __nmemb);
4143 if (__nmemb != 0)
4144 {
4145 this->setg(this->eback(),
4146 this->eback() + __unget_sz,
4147 this->eback() + __unget_sz + __nmemb);
4148 __c = *this->gptr();
4149 }
4150 }
4151 else
4152 {
4153 memmove(__extbuf_, __extbufnext_, __extbufend_ - __extbufnext_);
4154 __extbufnext_ = __extbuf_ + (__extbufend_ - __extbufnext_);
4155 __extbufend_ = __extbuf_ + (__extbuf_ == __extbuf_min_ ? sizeof(__extbuf_min_) : __ebs_);
Howard Hinnant0949eed2011-06-30 21:18:19 +00004156 streamsize __nmemb = _VSTD::min(static_cast<streamsize>(this->egptr() - this->eback() - __unget_sz),
Howard Hinnant4b53f502010-06-01 20:09:18 +00004157 static_cast<streamsize>(__extbufend_ - __extbufnext_));
4158 codecvt_base::result __r;
4159 state_type __svs = __st_;
4160 streamsize __nr = __bufptr_->sgetn(const_cast<char*>(__extbufnext_), __nmemb);
4161 if (__nr != 0)
4162 {
4163 __extbufend_ = __extbufnext_ + __nr;
4164 char_type* __inext;
4165 __r = __cv_->in(__st_, __extbuf_, __extbufend_, __extbufnext_,
4166 this->eback() + __unget_sz,
4167 this->egptr(), __inext);
4168 if (__r == codecvt_base::noconv)
4169 {
4170 this->setg((char_type*)__extbuf_, (char_type*)__extbuf_, (char_type*)__extbufend_);
4171 __c = *this->gptr();
4172 }
4173 else if (__inext != this->eback() + __unget_sz)
4174 {
4175 this->setg(this->eback(), this->eback() + __unget_sz, __inext);
4176 __c = *this->gptr();
4177 }
4178 }
4179 }
4180 }
4181 else
4182 __c = *this->gptr();
4183 if (this->eback() == &__1buf)
4184 this->setg(0, 0, 0);
4185 return __c;
4186}
4187
4188template <class _Codecvt, class _Elem, class _Tr>
4189typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
4190wbuffer_convert<_Codecvt, _Elem, _Tr>::pbackfail(int_type __c)
4191{
4192 if (__cv_ != 0 && __bufptr_ != 0 && this->eback() < this->gptr())
4193 {
4194 if (traits_type::eq_int_type(__c, traits_type::eof()))
4195 {
4196 this->gbump(-1);
4197 return traits_type::not_eof(__c);
4198 }
4199 if (traits_type::eq(traits_type::to_char_type(__c), this->gptr()[-1]))
4200 {
4201 this->gbump(-1);
4202 *this->gptr() = traits_type::to_char_type(__c);
4203 return __c;
4204 }
4205 }
4206 return traits_type::eof();
4207}
4208
4209template <class _Codecvt, class _Elem, class _Tr>
Howard Hinnantd23b4642010-05-31 20:58:54 +00004210typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
4211wbuffer_convert<_Codecvt, _Elem, _Tr>::overflow(int_type __c)
4212{
Howard Hinnant4b53f502010-06-01 20:09:18 +00004213 if (__cv_ == 0 || __bufptr_ == 0)
4214 return traits_type::eof();
4215 __write_mode();
4216 char_type __1buf;
4217 char_type* __pb_save = this->pbase();
4218 char_type* __epb_save = this->epptr();
4219 if (!traits_type::eq_int_type(__c, traits_type::eof()))
4220 {
4221 if (this->pptr() == 0)
4222 this->setp(&__1buf, &__1buf+1);
4223 *this->pptr() = traits_type::to_char_type(__c);
4224 this->pbump(1);
4225 }
4226 if (this->pptr() != this->pbase())
4227 {
4228 if (__always_noconv_)
4229 {
4230 streamsize __nmemb = static_cast<streamsize>(this->pptr() - this->pbase());
4231 if (__bufptr_->sputn((const char*)this->pbase(), __nmemb) != __nmemb)
4232 return traits_type::eof();
4233 }
4234 else
4235 {
4236 char* __extbe = __extbuf_;
4237 codecvt_base::result __r;
4238 do
4239 {
4240 const char_type* __e;
4241 __r = __cv_->out(__st_, this->pbase(), this->pptr(), __e,
4242 __extbuf_, __extbuf_ + __ebs_, __extbe);
4243 if (__e == this->pbase())
4244 return traits_type::eof();
4245 if (__r == codecvt_base::noconv)
4246 {
4247 streamsize __nmemb = static_cast<size_t>(this->pptr() - this->pbase());
4248 if (__bufptr_->sputn((const char*)this->pbase(), __nmemb) != __nmemb)
4249 return traits_type::eof();
4250 }
4251 else if (__r == codecvt_base::ok || __r == codecvt_base::partial)
4252 {
4253 streamsize __nmemb = static_cast<size_t>(__extbe - __extbuf_);
4254 if (__bufptr_->sputn(__extbuf_, __nmemb) != __nmemb)
4255 return traits_type::eof();
4256 if (__r == codecvt_base::partial)
4257 {
4258 this->setp((char_type*)__e, this->pptr());
4259 this->pbump(this->epptr() - this->pbase());
4260 }
4261 }
4262 else
4263 return traits_type::eof();
4264 } while (__r == codecvt_base::partial);
4265 }
4266 this->setp(__pb_save, __epb_save);
4267 }
4268 return traits_type::not_eof(__c);
4269}
4270
4271template <class _Codecvt, class _Elem, class _Tr>
4272basic_streambuf<_Elem, _Tr>*
4273wbuffer_convert<_Codecvt, _Elem, _Tr>::setbuf(char_type* __s, streamsize __n)
4274{
4275 this->setg(0, 0, 0);
4276 this->setp(0, 0);
4277 if (__owns_eb_)
4278 delete [] __extbuf_;
4279 if (__owns_ib_)
4280 delete [] __intbuf_;
4281 __ebs_ = __n;
4282 if (__ebs_ > sizeof(__extbuf_min_))
4283 {
4284 if (__always_noconv_ && __s)
4285 {
4286 __extbuf_ = (char*)__s;
4287 __owns_eb_ = false;
4288 }
4289 else
4290 {
4291 __extbuf_ = new char[__ebs_];
4292 __owns_eb_ = true;
4293 }
4294 }
4295 else
4296 {
4297 __extbuf_ = __extbuf_min_;
4298 __ebs_ = sizeof(__extbuf_min_);
4299 __owns_eb_ = false;
4300 }
4301 if (!__always_noconv_)
4302 {
4303 __ibs_ = max<streamsize>(__n, sizeof(__extbuf_min_));
4304 if (__s && __ibs_ >= sizeof(__extbuf_min_))
4305 {
4306 __intbuf_ = __s;
4307 __owns_ib_ = false;
4308 }
4309 else
4310 {
4311 __intbuf_ = new char_type[__ibs_];
4312 __owns_ib_ = true;
4313 }
4314 }
4315 else
4316 {
4317 __ibs_ = 0;
4318 __intbuf_ = 0;
4319 __owns_ib_ = false;
4320 }
4321 return this;
4322}
4323
4324template <class _Codecvt, class _Elem, class _Tr>
4325typename wbuffer_convert<_Codecvt, _Elem, _Tr>::pos_type
4326wbuffer_convert<_Codecvt, _Elem, _Tr>::seekoff(off_type __off, ios_base::seekdir __way,
4327 ios_base::openmode __om)
4328{
4329 int __width = __cv_->encoding();
4330 if (__cv_ == 0 || __bufptr_ == 0 || (__width <= 0 && __off != 0) || sync())
4331 return pos_type(off_type(-1));
4332 // __width > 0 || __off == 0
4333 switch (__way)
4334 {
4335 case ios_base::beg:
4336 break;
4337 case ios_base::cur:
4338 break;
4339 case ios_base::end:
4340 break;
4341 default:
4342 return pos_type(off_type(-1));
4343 }
4344 pos_type __r = __bufptr_->pubseekoff(__width * __off, __way, __om);
4345 __r.state(__st_);
4346 return __r;
4347}
4348
4349template <class _Codecvt, class _Elem, class _Tr>
4350typename wbuffer_convert<_Codecvt, _Elem, _Tr>::pos_type
4351wbuffer_convert<_Codecvt, _Elem, _Tr>::seekpos(pos_type __sp, ios_base::openmode __wch)
4352{
4353 if (__cv_ == 0 || __bufptr_ == 0 || sync())
4354 return pos_type(off_type(-1));
4355 if (__bufptr_->pubseekpos(__sp, __wch) == pos_type(off_type(-1)))
4356 return pos_type(off_type(-1));
4357 return __sp;
4358}
4359
4360template <class _Codecvt, class _Elem, class _Tr>
4361int
4362wbuffer_convert<_Codecvt, _Elem, _Tr>::sync()
4363{
4364 if (__cv_ == 0 || __bufptr_ == 0)
4365 return 0;
4366 if (__cm_ & ios_base::out)
4367 {
4368 if (this->pptr() != this->pbase())
4369 if (overflow() == traits_type::eof())
4370 return -1;
4371 codecvt_base::result __r;
4372 do
4373 {
4374 char* __extbe;
4375 __r = __cv_->unshift(__st_, __extbuf_, __extbuf_ + __ebs_, __extbe);
4376 streamsize __nmemb = static_cast<streamsize>(__extbe - __extbuf_);
4377 if (__bufptr_->sputn(__extbuf_, __nmemb) != __nmemb)
4378 return -1;
4379 } while (__r == codecvt_base::partial);
4380 if (__r == codecvt_base::error)
4381 return -1;
4382 if (__bufptr_->pubsync())
4383 return -1;
4384 }
4385 else if (__cm_ & ios_base::in)
4386 {
4387 off_type __c;
4388 if (__always_noconv_)
4389 __c = this->egptr() - this->gptr();
4390 else
4391 {
4392 int __width = __cv_->encoding();
4393 __c = __extbufend_ - __extbufnext_;
4394 if (__width > 0)
4395 __c += __width * (this->egptr() - this->gptr());
4396 else
4397 {
4398 if (this->gptr() != this->egptr())
4399 {
4400 reverse(this->gptr(), this->egptr());
4401 codecvt_base::result __r;
4402 const char_type* __e = this->gptr();
4403 char* __extbe;
4404 do
4405 {
4406 __r = __cv_->out(__st_, __e, this->egptr(), __e,
4407 __extbuf_, __extbuf_ + __ebs_, __extbe);
4408 switch (__r)
4409 {
4410 case codecvt_base::noconv:
4411 __c += this->egptr() - this->gptr();
4412 break;
4413 case codecvt_base::ok:
4414 case codecvt_base::partial:
4415 __c += __extbe - __extbuf_;
4416 break;
4417 default:
4418 return -1;
4419 }
4420 } while (__r == codecvt_base::partial);
4421 }
4422 }
4423 }
4424 if (__bufptr_->pubseekoff(-__c, ios_base::cur, __cm_) == pos_type(off_type(-1)))
4425 return -1;
4426 this->setg(0, 0, 0);
4427 __cm_ = 0;
4428 }
4429 return 0;
4430}
4431
4432template <class _Codecvt, class _Elem, class _Tr>
4433bool
4434wbuffer_convert<_Codecvt, _Elem, _Tr>::__read_mode()
4435{
4436 if (!(__cm_ & ios_base::in))
4437 {
4438 this->setp(0, 0);
4439 if (__always_noconv_)
4440 this->setg((char_type*)__extbuf_,
4441 (char_type*)__extbuf_ + __ebs_,
4442 (char_type*)__extbuf_ + __ebs_);
4443 else
4444 this->setg(__intbuf_, __intbuf_ + __ibs_, __intbuf_ + __ibs_);
4445 __cm_ = ios_base::in;
4446 return true;
4447 }
4448 return false;
4449}
4450
4451template <class _Codecvt, class _Elem, class _Tr>
4452void
4453wbuffer_convert<_Codecvt, _Elem, _Tr>::__write_mode()
4454{
4455 if (!(__cm_ & ios_base::out))
4456 {
4457 this->setg(0, 0, 0);
4458 if (__ebs_ > sizeof(__extbuf_min_))
4459 {
4460 if (__always_noconv_)
4461 this->setp((char_type*)__extbuf_,
4462 (char_type*)__extbuf_ + (__ebs_ - 1));
4463 else
4464 this->setp(__intbuf_, __intbuf_ + (__ibs_ - 1));
4465 }
4466 else
4467 this->setp(0, 0);
4468 __cm_ = ios_base::out;
4469 }
4470}
4471
4472template <class _Codecvt, class _Elem, class _Tr>
4473wbuffer_convert<_Codecvt, _Elem, _Tr>*
4474wbuffer_convert<_Codecvt, _Elem, _Tr>::__close()
4475{
4476 wbuffer_convert* __rt = 0;
4477 if (__cv_ != 0 && __bufptr_ != 0)
4478 {
4479 __rt = this;
4480 if ((__cm_ & ios_base::out) && sync())
4481 __rt = 0;
4482 }
4483 return __rt;
Howard Hinnantd23b4642010-05-31 20:58:54 +00004484}
4485
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004486_LIBCPP_END_NAMESPACE_STD
4487
4488#endif // _LIBCPP_LOCALE