blob: 5dc3ff24096270fbc263c06fe932aaf0a511ec28 [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 Hinnant0949eed2011-06-30 21:18:19 +0000436 size_t __nkw = _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 Hinnantbc8d3f92010-05-11 19:42:16 +0000601 if (__ct == __thousands_sep && __grouping.size() != 0)
602 {
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
684extern template class __num_get<char>;
685extern template class __num_get<wchar_t>;
686
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];
1278 char_type __thousands_sep;
1279 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
1456extern template class __num_put<char>;
1457extern template class __num_put<wchar_t>;
1458
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 {
1769 __ob = (char_type*)malloc((2*__nc)*sizeof(char_type));
1770 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 {
1838 __ob = (char_type*)malloc((2*__nc)*sizeof(char_type));
1839 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();
2105 int __i = __scan_keyword(__b, __e, __wk, __wk+14, __ct, __err, false) - __wk;
2106 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();
2119 int __i = __scan_keyword(__b, __e, __month, __month+24, __ct, __err, false) - __month;
2120 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 }
2291 int __i = __scan_keyword(__b, __e, __ap, __ap+2, __ct, __err, false) - __ap;
2292 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{
2400 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2401 const string_type& __fmt = this->__x();
2402 return get(__b, __e, __iob, __err, __tm, __fmt.data(), __fmt.data() + __fmt.size());
2403}
2404
2405template <class _CharT, class _InputIterator>
2406_InputIterator
2407time_get<_CharT, _InputIterator>::do_get_weekday(iter_type __b, iter_type __e,
2408 ios_base& __iob,
2409 ios_base::iostate& __err,
2410 tm* __tm) const
2411{
2412 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2413 __get_weekdayname(__tm->tm_wday, __b, __e, __err, __ct);
2414 return __b;
2415}
2416
2417template <class _CharT, class _InputIterator>
2418_InputIterator
2419time_get<_CharT, _InputIterator>::do_get_monthname(iter_type __b, iter_type __e,
2420 ios_base& __iob,
2421 ios_base::iostate& __err,
2422 tm* __tm) const
2423{
2424 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2425 __get_monthname(__tm->tm_mon, __b, __e, __err, __ct);
2426 return __b;
2427}
2428
2429template <class _CharT, class _InputIterator>
2430_InputIterator
2431time_get<_CharT, _InputIterator>::do_get_year(iter_type __b, iter_type __e,
2432 ios_base& __iob,
2433 ios_base::iostate& __err,
2434 tm* __tm) const
2435{
2436 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2437 __get_year(__tm->tm_year, __b, __e, __err, __ct);
2438 return __b;
2439}
2440
2441template <class _CharT, class _InputIterator>
2442_InputIterator
2443time_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
2444 ios_base& __iob,
2445 ios_base::iostate& __err, tm* __tm,
2446 char __fmt, char) const
2447{
2448 __err = ios_base::goodbit;
2449 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2450 switch (__fmt)
2451 {
2452 case 'a':
2453 case 'A':
2454 __get_weekdayname(__tm->tm_wday, __b, __e, __err, __ct);
2455 break;
2456 case 'b':
2457 case 'B':
2458 case 'h':
2459 __get_monthname(__tm->tm_mon, __b, __e, __err, __ct);
2460 break;
2461 case 'c':
2462 {
2463 const string_type& __fmt = this->__c();
2464 __b = get(__b, __e, __iob, __err, __tm, __fmt.data(), __fmt.data() + __fmt.size());
2465 }
2466 break;
2467 case 'd':
2468 case 'e':
2469 __get_day(__tm->tm_mday, __b, __e, __err, __ct);
2470 break;
2471 case 'D':
2472 {
2473 const char_type __fmt[] = {'%', 'm', '/', '%', 'd', '/', '%', 'y'};
2474 __b = get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2475 }
2476 break;
Howard Hinnant506b3642011-04-10 17:54:14 +00002477 case 'F':
2478 {
2479 const char_type __fmt[] = {'%', 'Y', '-', '%', 'm', '-', '%', 'd'};
2480 __b = get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2481 }
2482 break;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002483 case 'H':
2484 __get_hour(__tm->tm_hour, __b, __e, __err, __ct);
2485 break;
2486 case 'I':
2487 __get_12_hour(__tm->tm_hour, __b, __e, __err, __ct);
2488 break;
2489 case 'j':
2490 __get_day_year_num(__tm->tm_yday, __b, __e, __err, __ct);
2491 break;
2492 case 'm':
2493 __get_month(__tm->tm_mon, __b, __e, __err, __ct);
2494 break;
2495 case 'M':
2496 __get_minute(__tm->tm_min, __b, __e, __err, __ct);
2497 break;
2498 case 'n':
2499 case 't':
2500 __get_white_space(__b, __e, __err, __ct);
2501 break;
2502 case 'p':
2503 __get_am_pm(__tm->tm_hour, __b, __e, __err, __ct);
2504 break;
2505 case 'r':
2506 {
2507 const char_type __fmt[] = {'%', 'I', ':', '%', 'M', ':', '%', 'S', ' ', '%', 'p'};
2508 __b = get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2509 }
2510 break;
2511 case 'R':
2512 {
2513 const char_type __fmt[] = {'%', 'H', ':', '%', 'M'};
2514 __b = get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2515 }
2516 break;
2517 case 'S':
2518 __get_second(__tm->tm_sec, __b, __e, __err, __ct);
2519 break;
2520 case 'T':
2521 {
2522 const char_type __fmt[] = {'%', 'H', ':', '%', 'M', ':', '%', 'S'};
2523 __b = get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2524 }
2525 break;
2526 case 'w':
2527 __get_weekday(__tm->tm_wday, __b, __e, __err, __ct);
2528 break;
2529 case 'x':
2530 return do_get_date(__b, __e, __iob, __err, __tm);
2531 case 'X':
2532 {
2533 const string_type& __fmt = this->__X();
2534 __b = get(__b, __e, __iob, __err, __tm, __fmt.data(), __fmt.data() + __fmt.size());
2535 }
2536 break;
2537 case 'y':
2538 __get_year(__tm->tm_year, __b, __e, __err, __ct);
2539 break;
2540 case 'Y':
2541 __get_year4(__tm->tm_year, __b, __e, __err, __ct);
2542 break;
2543 case '%':
2544 __get_percent(__b, __e, __err, __ct);
2545 break;
2546 default:
2547 __err |= ios_base::failbit;
2548 }
2549 return __b;
2550}
2551
2552extern template class time_get<char>;
2553extern template class time_get<wchar_t>;
2554
2555class __time_get
2556{
2557protected:
2558 locale_t __loc_;
2559
2560 __time_get(const char* __nm);
2561 __time_get(const string& __nm);
2562 ~__time_get();
2563};
2564
2565template <class _CharT>
2566class __time_get_storage
2567 : public __time_get
2568{
2569protected:
2570 typedef basic_string<_CharT> string_type;
2571
2572 string_type __weeks_[14];
2573 string_type __months_[24];
2574 string_type __am_pm_[2];
2575 string_type __c_;
2576 string_type __r_;
2577 string_type __x_;
2578 string_type __X_;
2579
2580 explicit __time_get_storage(const char* __nm);
2581 explicit __time_get_storage(const string& __nm);
2582
2583 _LIBCPP_ALWAYS_INLINE ~__time_get_storage() {}
2584
2585 time_base::dateorder __do_date_order() const;
2586
2587private:
2588 void init(const ctype<_CharT>&);
2589 string_type __analyze(char __fmt, const ctype<_CharT>&);
2590};
2591
2592template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00002593class _LIBCPP_VISIBLE time_get_byname
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002594 : public time_get<_CharT, _InputIterator>,
2595 private __time_get_storage<_CharT>
2596{
2597public:
2598 typedef time_base::dateorder dateorder;
2599 typedef _InputIterator iter_type;
2600 typedef _CharT char_type;
2601 typedef basic_string<char_type> string_type;
2602
Howard Hinnant82894812010-09-22 16:48:34 +00002603 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002604 explicit time_get_byname(const char* __nm, size_t __refs = 0)
2605 : time_get<_CharT, _InputIterator>(__refs),
2606 __time_get_storage<_CharT>(__nm) {}
Howard Hinnant82894812010-09-22 16:48:34 +00002607 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002608 explicit time_get_byname(const string& __nm, size_t __refs = 0)
2609 : time_get<_CharT, _InputIterator>(__refs),
2610 __time_get_storage<_CharT>(__nm) {}
2611
2612protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002613 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002614 ~time_get_byname() {}
2615
Howard Hinnant82894812010-09-22 16:48:34 +00002616 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002617 virtual dateorder do_date_order() const {return this->__do_date_order();}
2618private:
Howard Hinnant82894812010-09-22 16:48:34 +00002619 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002620 virtual const string_type* __weeks() const {return this->__weeks_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002621 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002622 virtual const string_type* __months() const {return this->__months_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002623 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002624 virtual const string_type* __am_pm() const {return this->__am_pm_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002625 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002626 virtual const string_type& __c() const {return this->__c_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002627 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002628 virtual const string_type& __r() const {return this->__r_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002629 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002630 virtual const string_type& __x() const {return this->__x_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002631 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002632 virtual const string_type& __X() const {return this->__X_;}
2633};
2634
2635extern template class time_get_byname<char>;
2636extern template class time_get_byname<wchar_t>;
2637
2638class __time_put
2639{
2640 locale_t __loc_;
2641protected:
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00002642 _LIBCPP_ALWAYS_INLINE __time_put() : __loc_(_LIBCPP_GET_C_LOCALE) {}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002643 __time_put(const char* __nm);
2644 __time_put(const string& __nm);
2645 ~__time_put();
2646 void __do_put(char* __nb, char*& __ne, const tm* __tm,
2647 char __fmt, char __mod) const;
2648 void __do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
2649 char __fmt, char __mod) const;
2650};
2651
2652template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00002653class _LIBCPP_VISIBLE time_put
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002654 : public locale::facet,
2655 private __time_put
2656{
2657public:
2658 typedef _CharT char_type;
2659 typedef _OutputIterator iter_type;
2660
2661 _LIBCPP_ALWAYS_INLINE
2662 explicit time_put(size_t __refs = 0)
2663 : locale::facet(__refs) {}
2664
2665 iter_type put(iter_type __s, ios_base& __iob, char_type __fl, const tm* __tm,
2666 const char_type* __pb, const char_type* __pe) const;
2667
2668 _LIBCPP_ALWAYS_INLINE
2669 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
2670 const tm* __tm, char __fmt, char __mod = 0) const
2671 {
2672 return do_put(__s, __iob, __fl, __tm, __fmt, __mod);
2673 }
2674
2675 static locale::id id;
2676
2677protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002678 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002679 ~time_put() {}
2680 virtual iter_type do_put(iter_type __s, ios_base&, char_type, const tm* __tm,
2681 char __fmt, char __mod) const;
2682
Howard Hinnant82894812010-09-22 16:48:34 +00002683 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002684 explicit time_put(const char* __nm, size_t __refs)
2685 : locale::facet(__refs),
2686 __time_put(__nm) {}
Howard Hinnant82894812010-09-22 16:48:34 +00002687 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002688 explicit time_put(const string& __nm, size_t __refs)
2689 : locale::facet(__refs),
2690 __time_put(__nm) {}
2691};
2692
2693template <class _CharT, class _OutputIterator>
2694locale::id
2695time_put<_CharT, _OutputIterator>::id;
2696
2697template <class _CharT, class _OutputIterator>
2698_OutputIterator
2699time_put<_CharT, _OutputIterator>::put(iter_type __s, ios_base& __iob,
2700 char_type __fl, const tm* __tm,
2701 const char_type* __pb,
2702 const char_type* __pe) const
2703{
2704 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2705 for (; __pb != __pe; ++__pb)
2706 {
2707 if (__ct.narrow(*__pb, 0) == '%')
2708 {
2709 if (++__pb == __pe)
2710 {
2711 *__s++ = __pb[-1];
2712 break;
2713 }
2714 char __mod = 0;
2715 char __fmt = __ct.narrow(*__pb, 0);
2716 if (__fmt == 'E' || __fmt == 'O')
2717 {
2718 if (++__pb == __pe)
2719 {
2720 *__s++ = __pb[-2];
2721 *__s++ = __pb[-1];
2722 break;
2723 }
2724 __mod = __fmt;
2725 __fmt = __ct.narrow(*__pb, 0);
2726 }
2727 __s = do_put(__s, __iob, __fl, __tm, __fmt, __mod);
2728 }
2729 else
2730 *__s++ = *__pb;
2731 }
2732 return __s;
2733}
2734
2735template <class _CharT, class _OutputIterator>
2736_OutputIterator
2737time_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
2738 char_type, const tm* __tm,
2739 char __fmt, char __mod) const
2740{
2741 char_type __nar[100];
2742 char_type* __nb = __nar;
2743 char_type* __ne = __nb + 100;
2744 __do_put(__nb, __ne, __tm, __fmt, __mod);
Howard Hinnant0949eed2011-06-30 21:18:19 +00002745 return _VSTD::copy(__nb, __ne, __s);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002746}
2747
2748extern template class time_put<char>;
2749extern template class time_put<wchar_t>;
2750
2751template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00002752class _LIBCPP_VISIBLE time_put_byname
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002753 : public time_put<_CharT, _OutputIterator>
2754{
2755public:
2756 _LIBCPP_ALWAYS_INLINE
2757 explicit time_put_byname(const char* __nm, size_t __refs = 0)
2758 : time_put<_CharT, _OutputIterator>(__nm, __refs) {}
2759
2760 _LIBCPP_ALWAYS_INLINE
2761 explicit time_put_byname(const string& __nm, size_t __refs = 0)
2762 : time_put<_CharT, _OutputIterator>(__nm, __refs) {}
2763
2764protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002765 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002766 ~time_put_byname() {}
2767};
2768
2769extern template class time_put_byname<char>;
2770extern template class time_put_byname<wchar_t>;
2771
2772// money_base
2773
Howard Hinnant82894812010-09-22 16:48:34 +00002774class _LIBCPP_VISIBLE money_base
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002775{
2776public:
2777 enum part {none, space, symbol, sign, value};
2778 struct pattern {char field[4];};
2779
2780 _LIBCPP_ALWAYS_INLINE money_base() {}
2781};
2782
2783// moneypunct
2784
2785template <class _CharT, bool _International = false>
Howard Hinnant82894812010-09-22 16:48:34 +00002786class _LIBCPP_VISIBLE moneypunct
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002787 : public locale::facet,
2788 public money_base
2789{
2790public:
2791 typedef _CharT char_type;
2792 typedef basic_string<char_type> string_type;
2793
Howard Hinnant82894812010-09-22 16:48:34 +00002794 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002795 explicit moneypunct(size_t __refs = 0)
2796 : locale::facet(__refs) {}
2797
2798 _LIBCPP_ALWAYS_INLINE char_type decimal_point() const {return do_decimal_point();}
2799 _LIBCPP_ALWAYS_INLINE char_type thousands_sep() const {return do_thousands_sep();}
2800 _LIBCPP_ALWAYS_INLINE string grouping() const {return do_grouping();}
2801 _LIBCPP_ALWAYS_INLINE string_type curr_symbol() const {return do_curr_symbol();}
2802 _LIBCPP_ALWAYS_INLINE string_type positive_sign() const {return do_positive_sign();}
2803 _LIBCPP_ALWAYS_INLINE string_type negative_sign() const {return do_negative_sign();}
2804 _LIBCPP_ALWAYS_INLINE int frac_digits() const {return do_frac_digits();}
2805 _LIBCPP_ALWAYS_INLINE pattern pos_format() const {return do_pos_format();}
2806 _LIBCPP_ALWAYS_INLINE pattern neg_format() const {return do_neg_format();}
2807
2808 static locale::id id;
2809 static const bool intl = _International;
2810
2811protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002812 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002813 ~moneypunct() {}
2814
2815 virtual char_type do_decimal_point() const {return numeric_limits<char_type>::max();}
2816 virtual char_type do_thousands_sep() const {return numeric_limits<char_type>::max();}
2817 virtual string do_grouping() const {return string();}
2818 virtual string_type do_curr_symbol() const {return string_type();}
2819 virtual string_type do_positive_sign() const {return string_type();}
2820 virtual string_type do_negative_sign() const {return string_type(1, '-');}
2821 virtual int do_frac_digits() const {return 0;}
2822 virtual pattern do_pos_format() const
2823 {pattern __p = {symbol, sign, none, value}; return __p;}
2824 virtual pattern do_neg_format() const
2825 {pattern __p = {symbol, sign, none, value}; return __p;}
2826};
2827
2828template <class _CharT, bool _International>
2829locale::id
2830moneypunct<_CharT, _International>::id;
2831
2832extern template class moneypunct<char, false>;
2833extern template class moneypunct<char, true>;
2834extern template class moneypunct<wchar_t, false>;
2835extern template class moneypunct<wchar_t, true>;
2836
2837// moneypunct_byname
2838
2839template <class _CharT, bool _International = false>
Howard Hinnant82894812010-09-22 16:48:34 +00002840class _LIBCPP_VISIBLE moneypunct_byname
2841 : public moneypunct<_CharT, _International>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002842{
2843public:
2844 typedef money_base::pattern pattern;
2845 typedef _CharT char_type;
2846 typedef basic_string<char_type> string_type;
2847
2848 _LIBCPP_ALWAYS_INLINE
2849 explicit moneypunct_byname(const char* __nm, size_t __refs = 0)
2850 : moneypunct<_CharT, _International>(__refs) {init(__nm);}
2851
2852 _LIBCPP_ALWAYS_INLINE
2853 explicit moneypunct_byname(const string& __nm, size_t __refs = 0)
2854 : moneypunct<_CharT, _International>(__refs) {init(__nm.c_str());}
2855
2856protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002857 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002858 ~moneypunct_byname() {}
2859
2860 virtual char_type do_decimal_point() const {return __decimal_point_;}
2861 virtual char_type do_thousands_sep() const {return __thousands_sep_;}
2862 virtual string do_grouping() const {return __grouping_;}
2863 virtual string_type do_curr_symbol() const {return __curr_symbol_;}
2864 virtual string_type do_positive_sign() const {return __positive_sign_;}
2865 virtual string_type do_negative_sign() const {return __negative_sign_;}
2866 virtual int do_frac_digits() const {return __frac_digits_;}
2867 virtual pattern do_pos_format() const {return __pos_format_;}
2868 virtual pattern do_neg_format() const {return __neg_format_;}
2869
2870private:
2871 char_type __decimal_point_;
2872 char_type __thousands_sep_;
2873 string __grouping_;
2874 string_type __curr_symbol_;
2875 string_type __positive_sign_;
2876 string_type __negative_sign_;
2877 int __frac_digits_;
2878 pattern __pos_format_;
2879 pattern __neg_format_;
2880
2881 void init(const char*);
2882};
2883
2884template<> void moneypunct_byname<char, false>::init(const char*);
2885template<> void moneypunct_byname<char, true>::init(const char*);
2886template<> void moneypunct_byname<wchar_t, false>::init(const char*);
2887template<> void moneypunct_byname<wchar_t, true>::init(const char*);
2888
2889extern template class moneypunct_byname<char, false>;
2890extern template class moneypunct_byname<char, true>;
2891extern template class moneypunct_byname<wchar_t, false>;
2892extern template class moneypunct_byname<wchar_t, true>;
2893
2894// money_get
2895
2896template <class _CharT>
2897class __money_get
2898{
2899protected:
2900 typedef _CharT char_type;
2901 typedef basic_string<char_type> string_type;
2902
2903 _LIBCPP_ALWAYS_INLINE __money_get() {}
2904
2905 static void __gather_info(bool __intl, const locale& __loc,
2906 money_base::pattern& __pat, char_type& __dp,
2907 char_type& __ts, string& __grp,
2908 string_type& __sym, string_type& __psn,
2909 string_type& __nsn, int& __fd);
2910};
2911
2912template <class _CharT>
2913void
2914__money_get<_CharT>::__gather_info(bool __intl, const locale& __loc,
2915 money_base::pattern& __pat, char_type& __dp,
2916 char_type& __ts, string& __grp,
2917 string_type& __sym, string_type& __psn,
2918 string_type& __nsn, int& __fd)
2919{
2920 if (__intl)
2921 {
2922 const moneypunct<char_type, true>& __mp =
2923 use_facet<moneypunct<char_type, true> >(__loc);
2924 __pat = __mp.neg_format();
2925 __nsn = __mp.negative_sign();
2926 __psn = __mp.positive_sign();
2927 __dp = __mp.decimal_point();
2928 __ts = __mp.thousands_sep();
2929 __grp = __mp.grouping();
2930 __sym = __mp.curr_symbol();
2931 __fd = __mp.frac_digits();
2932 }
2933 else
2934 {
2935 const moneypunct<char_type, false>& __mp =
2936 use_facet<moneypunct<char_type, false> >(__loc);
2937 __pat = __mp.neg_format();
2938 __nsn = __mp.negative_sign();
2939 __psn = __mp.positive_sign();
2940 __dp = __mp.decimal_point();
2941 __ts = __mp.thousands_sep();
2942 __grp = __mp.grouping();
2943 __sym = __mp.curr_symbol();
2944 __fd = __mp.frac_digits();
2945 }
2946}
2947
2948extern template class __money_get<char>;
2949extern template class __money_get<wchar_t>;
2950
2951template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00002952class _LIBCPP_VISIBLE money_get
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002953 : public locale::facet,
2954 private __money_get<_CharT>
2955{
2956public:
2957 typedef _CharT char_type;
2958 typedef _InputIterator iter_type;
2959 typedef basic_string<char_type> string_type;
2960
2961 _LIBCPP_ALWAYS_INLINE
2962 explicit money_get(size_t __refs = 0)
2963 : locale::facet(__refs) {}
2964
2965 _LIBCPP_ALWAYS_INLINE
2966 iter_type get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob,
2967 ios_base::iostate& __err, long double& __v) const
2968 {
2969 return do_get(__b, __e, __intl, __iob, __err, __v);
2970 }
2971
2972 _LIBCPP_ALWAYS_INLINE
2973 iter_type get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob,
2974 ios_base::iostate& __err, string_type& __v) const
2975 {
2976 return do_get(__b, __e, __intl, __iob, __err, __v);
2977 }
2978
2979 static locale::id id;
2980
2981protected:
2982
Howard Hinnant82894812010-09-22 16:48:34 +00002983 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002984 ~money_get() {}
Howard Hinnant324bb032010-08-22 00:02:43 +00002985
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002986 virtual iter_type do_get(iter_type __b, iter_type __e, bool __intl,
2987 ios_base& __iob, ios_base::iostate& __err,
2988 long double& __v) const;
2989 virtual iter_type do_get(iter_type __b, iter_type __e, bool __intl,
2990 ios_base& __iob, ios_base::iostate& __err,
2991 string_type& __v) const;
2992
2993private:
2994 static bool __do_get(iter_type& __b, iter_type __e,
2995 bool __intl, const locale& __loc,
2996 ios_base::fmtflags __flags, ios_base::iostate& __err,
2997 bool& __neg, const ctype<char_type>& __ct,
2998 unique_ptr<char_type, void(*)(void*)>& __wb,
2999 char_type*& __wn, char_type* __we);
3000};
3001
3002template <class _CharT, class _InputIterator>
3003locale::id
3004money_get<_CharT, _InputIterator>::id;
3005
3006void __do_nothing(void*);
3007
3008template <class _Tp>
3009_LIBCPP_HIDDEN
3010void
3011__double_or_nothing(unique_ptr<_Tp, void(*)(void*)>& __b, _Tp*& __n, _Tp*& __e)
3012{
3013 bool __owns = __b.get_deleter() != __do_nothing;
3014 size_t __cur_cap = (__e-__b.get()) * sizeof(_Tp);
3015 size_t __new_cap = __cur_cap < numeric_limits<size_t>::max() / 2 ?
3016 2 * __cur_cap : numeric_limits<size_t>::max();
3017 size_t __n_off = __n - __b.get();
3018 _Tp* __t = (_Tp*)realloc(__owns ? __b.get() : 0, __new_cap);
3019 if (__t == 0)
3020 __throw_bad_alloc();
3021 if (__owns)
3022 __b.release();
3023 __b = unique_ptr<_Tp, void(*)(void*)>(__t, free);
3024 __new_cap /= sizeof(_Tp);
3025 __n = __b.get() + __n_off;
3026 __e = __b.get() + __new_cap;
3027}
3028
3029// true == success
3030template <class _CharT, class _InputIterator>
3031bool
3032money_get<_CharT, _InputIterator>::__do_get(iter_type& __b, iter_type __e,
3033 bool __intl, const locale& __loc,
3034 ios_base::fmtflags __flags,
3035 ios_base::iostate& __err,
3036 bool& __neg,
3037 const ctype<char_type>& __ct,
3038 unique_ptr<char_type, void(*)(void*)>& __wb,
3039 char_type*& __wn, char_type* __we)
3040{
3041 const unsigned __bz = 100;
3042 unsigned __gbuf[__bz];
3043 unique_ptr<unsigned, void(*)(void*)> __gb(__gbuf, __do_nothing);
3044 unsigned* __gn = __gb.get();
3045 unsigned* __ge = __gn + __bz;
3046 money_base::pattern __pat;
3047 char_type __dp;
3048 char_type __ts;
3049 string __grp;
3050 string_type __sym;
3051 string_type __psn;
3052 string_type __nsn;
3053 int __fd;
3054 __money_get<_CharT>::__gather_info(__intl, __loc, __pat, __dp, __ts, __grp,
3055 __sym, __psn, __nsn, __fd);
3056 const string_type* __trailing_sign = 0;
3057 __wn = __wb.get();
3058 for (unsigned __p = 0; __p < 4 && __b != __e; ++__p)
3059 {
3060 switch (__pat.field[__p])
3061 {
3062 case money_base::space:
3063 if (__p != 3)
3064 {
3065 if (__ct.is(ctype_base::space, *__b))
3066 ++__b;
3067 else
3068 {
3069 __err |= ios_base::failbit;
3070 return false;
3071 }
3072 }
Howard Hinnant324bb032010-08-22 00:02:43 +00003073 // drop through
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003074 case money_base::none:
3075 if (__p != 3)
3076 {
3077 while (__b != __e && __ct.is(ctype_base::space, *__b))
3078 ++__b;
3079 }
3080 break;
3081 case money_base::sign:
3082 if (__psn.size() + __nsn.size() > 0)
3083 {
3084 if (__psn.size() == 0 || __nsn.size() == 0)
3085 { // sign is optional
3086 if (__psn.size() > 0)
3087 { // __nsn.size() == 0
3088 if (*__b == __psn[0])
3089 {
3090 ++__b;
3091 if (__psn.size() > 1)
3092 __trailing_sign = &__psn;
3093 }
3094 else
3095 __neg = true;
3096 }
3097 else if (*__b == __nsn[0]) // __nsn.size() > 0 && __psn.size() == 0
3098 {
3099 ++__b;
3100 __neg = true;
3101 if (__nsn.size() > 1)
3102 __trailing_sign = &__nsn;
3103 }
3104 }
3105 else // sign is required
3106 {
3107 if (*__b == __psn[0])
3108 {
3109 ++__b;
3110 if (__psn.size() > 1)
3111 __trailing_sign = &__psn;
3112 }
3113 else if (*__b == __nsn[0])
3114 {
3115 ++__b;
3116 __neg = true;
3117 if (__nsn.size() > 1)
3118 __trailing_sign = &__nsn;
3119 }
3120 else
3121 {
3122 __err |= ios_base::failbit;
3123 return false;
3124 }
3125 }
3126 }
3127 break;
3128 case money_base::symbol:
3129 {
3130 bool __more_needed = __trailing_sign ||
3131 (__p < 2) ||
3132 (__p == 2 && __pat.field[3] != static_cast<char>(money_base::none));
3133 bool __sb = __flags & ios_base::showbase;
3134 if (__sb || __more_needed)
3135 {
3136 ios_base::iostate __et = ios_base::goodbit;
3137 string_type* __k = __scan_keyword(__b, __e, &__sym, &__sym+1,
3138 __ct, __et);
3139 if (__sb && __k != &__sym)
3140 {
3141 __err |= ios_base::failbit;
3142 return false;
3143 }
3144 }
3145 }
3146 break;
3147 case money_base::value:
3148 {
3149 unsigned __ng = 0;
3150 for (; __b != __e; ++__b)
3151 {
3152 char_type __c = *__b;
3153 if (__ct.is(ctype_base::digit, __c))
3154 {
3155 if (__wn == __we)
3156 __double_or_nothing(__wb, __wn, __we);
3157 *__wn++ = __c;
3158 ++__ng;
3159 }
3160 else if (__grp.size() > 0 && __ng > 0 && __c == __ts)
3161 {
3162 if (__gn == __ge)
3163 __double_or_nothing(__gb, __gn, __ge);
3164 *__gn++ = __ng;
3165 __ng = 0;
3166 }
3167 else
3168 break;
3169 }
3170 if (__gb.get() != __gn && __ng > 0)
3171 {
3172 if (__gn == __ge)
3173 __double_or_nothing(__gb, __gn, __ge);
3174 *__gn++ = __ng;
3175 }
3176 if (__fd > 0)
3177 {
3178 if (__b == __e || *__b != __dp)
3179 {
3180 __err |= ios_base::failbit;
3181 return false;
3182 }
3183 for (++__b; __fd > 0; --__fd, ++__b)
3184 {
3185 if (__b == __e || !__ct.is(ctype_base::digit, *__b))
3186 {
3187 __err |= ios_base::failbit;
3188 return false;
3189 }
3190 if (__wn == __we)
3191 __double_or_nothing(__wb, __wn, __we);
3192 *__wn++ = *__b;
3193 }
3194 }
3195 if (__wn == __wb.get())
3196 {
3197 __err |= ios_base::failbit;
3198 return false;
3199 }
3200 }
3201 break;
3202 }
3203 }
3204 if (__trailing_sign)
3205 {
3206 for (unsigned __i = 1; __i < __trailing_sign->size(); ++__i, ++__b)
3207 {
3208 if (__b == __e || *__b != (*__trailing_sign)[__i])
3209 {
3210 __err |= ios_base::failbit;
3211 return false;
3212 }
3213 }
3214 }
3215 if (__gb.get() != __gn)
3216 {
3217 ios_base::iostate __et = ios_base::goodbit;
3218 __check_grouping(__grp, __gb.get(), __gn, __et);
3219 if (__et)
3220 {
3221 __err |= ios_base::failbit;
3222 return false;
3223 }
3224 }
3225 return true;
3226}
3227
3228template <class _CharT, class _InputIterator>
3229_InputIterator
3230money_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
3231 bool __intl, ios_base& __iob,
3232 ios_base::iostate& __err,
3233 long double& __v) const
3234{
3235 const unsigned __bz = 100;
3236 char_type __wbuf[__bz];
3237 unique_ptr<char_type, void(*)(void*)> __wb(__wbuf, __do_nothing);
3238 char_type* __wn;
3239 char_type* __we = __wbuf + __bz;
3240 locale __loc = __iob.getloc();
3241 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3242 bool __neg = false;
3243 if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct,
3244 __wb, __wn, __we))
3245 {
3246 const char __src[] = "0123456789";
3247 char_type __atoms[sizeof(__src)-1];
3248 __ct.widen(__src, __src + (sizeof(__src)-1), __atoms);
3249 char __nbuf[__bz];
3250 char* __nc = __nbuf;
3251 unique_ptr<char, void(*)(void*)> __h(0, free);
3252 if (__wn - __wb.get() > __bz-2)
3253 {
3254 __h.reset((char*)malloc(__wn - __wb.get() + 2));
3255 if (__h.get() == 0)
3256 __throw_bad_alloc();
3257 __nc = __h.get();
3258 }
3259 if (__neg)
3260 *__nc++ = '-';
3261 for (const char_type* __w = __wb.get(); __w < __wn; ++__w, ++__nc)
3262 *__nc = __src[find(__atoms, __atoms+sizeof(__atoms), *__w) - __atoms];
3263 *__nc = char();
3264 if (sscanf(__nbuf, "%Lf", &__v) != 1)
3265 __throw_runtime_error("money_get error");
3266 }
3267 if (__b == __e)
3268 __err |= ios_base::eofbit;
3269 return __b;
3270}
3271
3272template <class _CharT, class _InputIterator>
3273_InputIterator
3274money_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
3275 bool __intl, ios_base& __iob,
3276 ios_base::iostate& __err,
3277 string_type& __v) const
3278{
3279 const unsigned __bz = 100;
3280 char_type __wbuf[__bz];
3281 unique_ptr<char_type, void(*)(void*)> __wb(__wbuf, __do_nothing);
3282 char_type* __wn;
3283 char_type* __we = __wbuf + __bz;
3284 locale __loc = __iob.getloc();
3285 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3286 bool __neg = false;
3287 if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct,
3288 __wb, __wn, __we))
3289 {
3290 __v.clear();
3291 if (__neg)
3292 __v.push_back(__ct.widen('-'));
3293 char_type __z = __ct.widen('0');
3294 char_type* __w;
3295 for (__w = __wb.get(); __w < __wn-1; ++__w)
3296 if (*__w != __z)
3297 break;
3298 __v.append(__w, __wn);
3299 }
3300 if (__b == __e)
3301 __err |= ios_base::eofbit;
3302 return __b;
3303}
3304
3305extern template class money_get<char>;
3306extern template class money_get<wchar_t>;
3307
3308// money_put
3309
3310template <class _CharT>
3311class __money_put
3312{
3313protected:
3314 typedef _CharT char_type;
3315 typedef basic_string<char_type> string_type;
3316
3317 _LIBCPP_ALWAYS_INLINE __money_put() {}
3318
3319 static void __gather_info(bool __intl, bool __neg, const locale& __loc,
3320 money_base::pattern& __pat, char_type& __dp,
3321 char_type& __ts, string& __grp,
3322 string_type& __sym, string_type& __sn,
3323 int& __fd);
3324 static void __format(char_type* __mb, char_type*& __mi, char_type*& __me,
3325 ios_base::fmtflags __flags,
3326 const char_type* __db, const char_type* __de,
3327 const ctype<char_type>& __ct, bool __neg,
3328 const money_base::pattern& __pat, char_type __dp,
3329 char_type __ts, const string& __grp,
3330 const string_type& __sym, const string_type& __sn,
3331 int __fd);
3332};
3333
3334template <class _CharT>
3335void
3336__money_put<_CharT>::__gather_info(bool __intl, bool __neg, const locale& __loc,
3337 money_base::pattern& __pat, char_type& __dp,
3338 char_type& __ts, string& __grp,
3339 string_type& __sym, string_type& __sn,
3340 int& __fd)
3341{
3342 if (__intl)
3343 {
3344 const moneypunct<char_type, true>& __mp =
3345 use_facet<moneypunct<char_type, true> >(__loc);
3346 if (__neg)
3347 {
3348 __pat = __mp.neg_format();
3349 __sn = __mp.negative_sign();
3350 }
3351 else
3352 {
3353 __pat = __mp.pos_format();
3354 __sn = __mp.positive_sign();
3355 }
3356 __dp = __mp.decimal_point();
3357 __ts = __mp.thousands_sep();
3358 __grp = __mp.grouping();
3359 __sym = __mp.curr_symbol();
3360 __fd = __mp.frac_digits();
3361 }
3362 else
3363 {
3364 const moneypunct<char_type, false>& __mp =
3365 use_facet<moneypunct<char_type, false> >(__loc);
3366 if (__neg)
3367 {
3368 __pat = __mp.neg_format();
3369 __sn = __mp.negative_sign();
3370 }
3371 else
3372 {
3373 __pat = __mp.pos_format();
3374 __sn = __mp.positive_sign();
3375 }
3376 __dp = __mp.decimal_point();
3377 __ts = __mp.thousands_sep();
3378 __grp = __mp.grouping();
3379 __sym = __mp.curr_symbol();
3380 __fd = __mp.frac_digits();
3381 }
3382}
3383
3384template <class _CharT>
3385void
3386__money_put<_CharT>::__format(char_type* __mb, char_type*& __mi, char_type*& __me,
3387 ios_base::fmtflags __flags,
3388 const char_type* __db, const char_type* __de,
3389 const ctype<char_type>& __ct, bool __neg,
3390 const money_base::pattern& __pat, char_type __dp,
3391 char_type __ts, const string& __grp,
3392 const string_type& __sym, const string_type& __sn,
3393 int __fd)
3394{
3395 __me = __mb;
3396 for (unsigned __p = 0; __p < 4; ++__p)
3397 {
3398 switch (__pat.field[__p])
3399 {
3400 case money_base::none:
3401 __mi = __me;
3402 break;
3403 case money_base::space:
3404 __mi = __me;
3405 *__me++ = __ct.widen(' ');
3406 break;
3407 case money_base::sign:
3408 if (!__sn.empty())
3409 *__me++ = __sn[0];
3410 break;
3411 case money_base::symbol:
3412 if (!__sym.empty() && (__flags & ios_base::showbase))
Howard Hinnant0949eed2011-06-30 21:18:19 +00003413 __me = _VSTD::copy(__sym.begin(), __sym.end(), __me);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003414 break;
3415 case money_base::value:
3416 {
3417 // remember start of value so we can reverse it
3418 char_type* __t = __me;
3419 // find beginning of digits
3420 if (__neg)
3421 ++__db;
3422 // find end of digits
3423 const char_type* __d;
3424 for (__d = __db; __d < __de; ++__d)
3425 if (!__ct.is(ctype_base::digit, *__d))
3426 break;
3427 // print fractional part
3428 if (__fd > 0)
3429 {
3430 int __f;
3431 for (__f = __fd; __d > __db && __f > 0; --__f)
3432 *__me++ = *--__d;
3433 char_type __z = __f > 0 ? __ct.widen('0') : char_type();
3434 for (; __f > 0; --__f)
3435 *__me++ = __z;
3436 *__me++ = __dp;
3437 }
3438 // print units part
3439 if (__d == __db)
3440 {
3441 *__me++ = __ct.widen('0');
3442 }
3443 else
3444 {
3445 unsigned __ng = 0;
3446 unsigned __ig = 0;
3447 unsigned __gl = __grp.empty() ? numeric_limits<unsigned>::max()
3448 : static_cast<unsigned>(__grp[__ig]);
3449 while (__d != __db)
3450 {
3451 if (__ng == __gl)
3452 {
3453 *__me++ = __ts;
3454 __ng = 0;
3455 if (++__ig < __grp.size())
3456 __gl = __grp[__ig] == numeric_limits<char>::max() ?
3457 numeric_limits<unsigned>::max() :
3458 static_cast<unsigned>(__grp[__ig]);
3459 }
3460 *__me++ = *--__d;
3461 ++__ng;
3462 }
3463 }
3464 // reverse it
3465 reverse(__t, __me);
3466 }
3467 break;
3468 }
3469 }
3470 // print rest of sign, if any
3471 if (__sn.size() > 1)
Howard Hinnant0949eed2011-06-30 21:18:19 +00003472 __me = _VSTD::copy(__sn.begin()+1, __sn.end(), __me);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003473 // set alignment
3474 if ((__flags & ios_base::adjustfield) == ios_base::left)
3475 __mi = __me;
3476 else if ((__flags & ios_base::adjustfield) != ios_base::internal)
3477 __mi = __mb;
3478}
3479
3480extern template class __money_put<char>;
3481extern template class __money_put<wchar_t>;
3482
3483template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00003484class _LIBCPP_VISIBLE money_put
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003485 : public locale::facet,
3486 private __money_put<_CharT>
3487{
3488public:
3489 typedef _CharT char_type;
3490 typedef _OutputIterator iter_type;
3491 typedef basic_string<char_type> string_type;
3492
3493 _LIBCPP_ALWAYS_INLINE
3494 explicit money_put(size_t __refs = 0)
3495 : locale::facet(__refs) {}
3496
3497 _LIBCPP_ALWAYS_INLINE
3498 iter_type put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl,
3499 long double __units) const
3500 {
3501 return do_put(__s, __intl, __iob, __fl, __units);
3502 }
3503
3504 _LIBCPP_ALWAYS_INLINE
3505 iter_type put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl,
3506 const string_type& __digits) const
3507 {
3508 return do_put(__s, __intl, __iob, __fl, __digits);
3509 }
3510
3511 static locale::id id;
3512
3513protected:
Howard Hinnant82894812010-09-22 16:48:34 +00003514 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003515 ~money_put() {}
3516
3517 virtual iter_type do_put(iter_type __s, bool __intl, ios_base& __iob,
3518 char_type __fl, long double __units) const;
3519 virtual iter_type do_put(iter_type __s, bool __intl, ios_base& __iob,
3520 char_type __fl, const string_type& __digits) const;
3521};
3522
3523template <class _CharT, class _OutputIterator>
3524locale::id
3525money_put<_CharT, _OutputIterator>::id;
3526
3527template <class _CharT, class _OutputIterator>
3528_OutputIterator
3529money_put<_CharT, _OutputIterator>::do_put(iter_type __s, bool __intl,
3530 ios_base& __iob, char_type __fl,
3531 long double __units) const
3532{
3533 // convert to char
3534 const size_t __bs = 100;
3535 char __buf[__bs];
3536 char* __bb = __buf;
3537 char_type __digits[__bs];
3538 char_type* __db = __digits;
3539 size_t __n = snprintf(__bb, __bs, "%.0Lf", __units);
3540 unique_ptr<char, void(*)(void*)> __hn(0, free);
3541 unique_ptr<char_type, void(*)(void*)> __hd(0, free);
3542 // secure memory for digit storage
3543 if (__n > __bs-1)
3544 {
Howard Hinnant866569b2011-09-28 23:39:33 +00003545#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00003546 __n = asprintf_l(&__bb, _LIBCPP_GET_C_LOCALE, "%.0Lf", __units);
Sean Huntf3907e62011-07-15 05:40:33 +00003547#else
3548 __n = __asprintf_l(&__bb, __cloc(), "%.0Lf", __units);
3549#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003550 if (__bb == 0)
3551 __throw_bad_alloc();
3552 __hn.reset(__bb);
3553 __hd.reset((char_type*)malloc(__n * sizeof(char_type)));
3554 if (__hd == 0)
3555 __throw_bad_alloc();
3556 __db = __hd.get();
3557 }
3558 // gather info
3559 locale __loc = __iob.getloc();
3560 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3561 __ct.widen(__bb, __bb + __n, __db);
3562 bool __neg = __n > 0 && __bb[0] == '-';
3563 money_base::pattern __pat;
3564 char_type __dp;
3565 char_type __ts;
3566 string __grp;
3567 string_type __sym;
3568 string_type __sn;
3569 int __fd;
3570 this->__gather_info(__intl, __neg, __loc, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3571 // secure memory for formatting
3572 char_type __mbuf[__bs];
3573 char_type* __mb = __mbuf;
3574 unique_ptr<char_type, void(*)(void*)> __hw(0, free);
3575 size_t __exn = static_cast<int>(__n) > __fd ?
3576 (__n - __fd) * 2 + __sn.size() + __sym.size() + __fd + 1
3577 : __sn.size() + __sym.size() + __fd + 2;
3578 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);
3616 size_t __exn = __digits.size() > __fd ?
3617 (__digits.size() - __fd) * 2 + __sn.size() + __sym.size() + __fd + 1
3618 : __sn.size() + __sym.size() + __fd + 2;
3619 if (__exn > 100)
3620 {
3621 __h.reset((char_type*)malloc(__exn * sizeof(char_type)));
3622 __mb = __h.get();
3623 if (__mb == 0)
3624 __throw_bad_alloc();
3625 }
3626 // format
3627 char_type* __mi;
3628 char_type* __me;
3629 this->__format(__mb, __mi, __me, __iob.flags(),
3630 __digits.data(), __digits.data() + __digits.size(), __ct,
3631 __neg, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3632 return __pad_and_output(__s, __mb, __mi, __me, __iob, __fl);
3633}
3634
3635extern template class money_put<char>;
3636extern template class money_put<wchar_t>;
3637
3638// messages
3639
Howard Hinnant82894812010-09-22 16:48:34 +00003640class _LIBCPP_VISIBLE messages_base
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003641{
3642public:
Howard Hinnantb2080c72011-02-25 00:51:08 +00003643 typedef ptrdiff_t catalog;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003644
3645 _LIBCPP_ALWAYS_INLINE messages_base() {}
3646};
3647
3648template <class _CharT>
Howard Hinnant82894812010-09-22 16:48:34 +00003649class _LIBCPP_VISIBLE messages
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003650 : public locale::facet,
3651 public messages_base
3652{
3653public:
3654 typedef _CharT char_type;
3655 typedef basic_string<_CharT> string_type;
3656
3657 _LIBCPP_ALWAYS_INLINE
3658 explicit messages(size_t __refs = 0)
3659 : locale::facet(__refs) {}
3660
3661 _LIBCPP_ALWAYS_INLINE
3662 catalog open(const basic_string<char>& __nm, const locale& __loc) const
3663 {
3664 return do_open(__nm, __loc);
3665 }
3666
3667 _LIBCPP_ALWAYS_INLINE
3668 string_type get(catalog __c, int __set, int __msgid,
3669 const string_type& __dflt) const
3670 {
3671 return do_get(__c, __set, __msgid, __dflt);
3672 }
3673
3674 _LIBCPP_ALWAYS_INLINE
3675 void close(catalog __c) const
3676 {
3677 do_close(__c);
3678 }
3679
3680 static locale::id id;
3681
3682protected:
Howard Hinnant82894812010-09-22 16:48:34 +00003683 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003684 ~messages() {}
3685
3686 virtual catalog do_open(const basic_string<char>&, const locale&) const;
3687 virtual string_type do_get(catalog, int __set, int __msgid,
3688 const string_type& __dflt) const;
3689 virtual void do_close(catalog) const;
3690};
3691
3692template <class _CharT>
3693locale::id
3694messages<_CharT>::id;
3695
3696template <class _CharT>
3697typename messages<_CharT>::catalog
3698messages<_CharT>::do_open(const basic_string<char>& __nm, const locale&) const
3699{
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00003700#if _WIN32
3701 return -1;
3702#else // _WIN32
Howard Hinnant11624452011-10-11 16:00:46 +00003703 catalog __cat = (catalog)catopen(__nm.c_str(), NL_CAT_LOCALE);
Howard Hinnantb2080c72011-02-25 00:51:08 +00003704 if (__cat != -1)
3705 __cat = static_cast<catalog>((static_cast<size_t>(__cat) >> 1));
3706 return __cat;
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00003707#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003708}
3709
3710template <class _CharT>
3711typename messages<_CharT>::string_type
3712messages<_CharT>::do_get(catalog __c, int __set, int __msgid,
3713 const string_type& __dflt) const
3714{
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00003715#if _WIN32
3716 return __dflt;
3717#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003718 string __ndflt;
3719 __narrow_to_utf8<sizeof(char_type)*__CHAR_BIT__>()(back_inserter(__ndflt),
3720 __dflt.c_str(),
3721 __dflt.c_str() + __dflt.size());
Howard Hinnantb2080c72011-02-25 00:51:08 +00003722 if (__c != -1)
3723 __c <<= 1;
Howard Hinnant11624452011-10-11 16:00:46 +00003724 nl_catd __cat = (nl_catd)__c;
Howard Hinnantb2080c72011-02-25 00:51:08 +00003725 char* __n = catgets(__cat, __set, __msgid, __ndflt.c_str());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003726 string_type __w;
3727 __widen_from_utf8<sizeof(char_type)*__CHAR_BIT__>()(back_inserter(__w),
3728 __n, __n + strlen(__n));
3729 return __w;
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00003730#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003731}
3732
3733template <class _CharT>
3734void
3735messages<_CharT>::do_close(catalog __c) const
3736{
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00003737#if !_WIN32
Howard Hinnantb2080c72011-02-25 00:51:08 +00003738 if (__c != -1)
3739 __c <<= 1;
Howard Hinnant11624452011-10-11 16:00:46 +00003740 nl_catd __cat = (nl_catd)__c;
Howard Hinnantb2080c72011-02-25 00:51:08 +00003741 catclose(__cat);
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00003742#endif // !_WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003743}
3744
3745extern template class messages<char>;
3746extern template class messages<wchar_t>;
3747
3748template <class _CharT>
Howard Hinnant82894812010-09-22 16:48:34 +00003749class _LIBCPP_VISIBLE messages_byname
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003750 : public messages<_CharT>
3751{
3752public:
3753 typedef messages_base::catalog catalog;
3754 typedef basic_string<_CharT> string_type;
3755
3756 _LIBCPP_ALWAYS_INLINE
3757 explicit messages_byname(const char*, size_t __refs = 0)
3758 : messages<_CharT>(__refs) {}
3759
3760 _LIBCPP_ALWAYS_INLINE
3761 explicit messages_byname(const string&, size_t __refs = 0)
3762 : messages<_CharT>(__refs) {}
3763
3764protected:
Howard Hinnant82894812010-09-22 16:48:34 +00003765 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003766 ~messages_byname() {}
3767};
3768
3769extern template class messages_byname<char>;
3770extern template class messages_byname<wchar_t>;
3771
Howard Hinnantd23b4642010-05-31 20:58:54 +00003772template<class _Codecvt, class _Elem = wchar_t,
3773 class _Wide_alloc = allocator<_Elem>,
3774 class _Byte_alloc = allocator<char> >
Howard Hinnant82894812010-09-22 16:48:34 +00003775class _LIBCPP_VISIBLE wstring_convert
Howard Hinnantd23b4642010-05-31 20:58:54 +00003776{
3777public:
3778 typedef basic_string<char, char_traits<char>, _Byte_alloc> byte_string;
3779 typedef basic_string<_Elem, char_traits<_Elem>, _Wide_alloc> wide_string;
3780 typedef typename _Codecvt::state_type state_type;
3781 typedef typename wide_string::traits_type::int_type int_type;
3782
3783private:
3784 byte_string __byte_err_string_;
3785 wide_string __wide_err_string_;
3786 _Codecvt* __cvtptr_;
3787 state_type __cvtstate_;
3788 size_t __cvtcount_;
3789
3790 wstring_convert(const wstring_convert& __wc);
3791 wstring_convert& operator=(const wstring_convert& __wc);
3792public:
3793 wstring_convert(_Codecvt* __pcvt = new _Codecvt);
3794 wstring_convert(_Codecvt* __pcvt, state_type __state);
3795 wstring_convert(const byte_string& __byte_err,
3796 const wide_string& __wide_err = wide_string());
Howard Hinnant73d21a42010-09-04 23:28:19 +00003797#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantd23b4642010-05-31 20:58:54 +00003798 wstring_convert(wstring_convert&& __wc);
3799#endif
3800 ~wstring_convert();
3801
Howard Hinnant82894812010-09-22 16:48:34 +00003802 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003803 wide_string from_bytes(char __byte)
3804 {return from_bytes(&__byte, &__byte+1);}
Howard Hinnant82894812010-09-22 16:48:34 +00003805 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003806 wide_string from_bytes(const char* __ptr)
3807 {return from_bytes(__ptr, __ptr + char_traits<char>::length(__ptr));}
Howard Hinnant82894812010-09-22 16:48:34 +00003808 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003809 wide_string from_bytes(const byte_string& __str)
3810 {return from_bytes(__str.data(), __str.data() + __str.size());}
3811 wide_string from_bytes(const char* __first, const char* __last);
3812
Howard Hinnant82894812010-09-22 16:48:34 +00003813 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003814 byte_string to_bytes(_Elem __wchar)
3815 {return to_bytes(&__wchar, &__wchar+1);}
Howard Hinnant82894812010-09-22 16:48:34 +00003816 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003817 byte_string to_bytes(const _Elem* __wptr)
3818 {return to_bytes(__wptr, __wptr + char_traits<_Elem>::length(__wptr));}
Howard Hinnant82894812010-09-22 16:48:34 +00003819 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003820 byte_string to_bytes(const wide_string& __wstr)
3821 {return to_bytes(__wstr.data(), __wstr.data() + __wstr.size());}
3822 byte_string to_bytes(const _Elem* __first, const _Elem* __last);
3823
Howard Hinnant82894812010-09-22 16:48:34 +00003824 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003825 size_t converted() const {return __cvtcount_;}
Howard Hinnant82894812010-09-22 16:48:34 +00003826 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003827 state_type state() const {return __cvtstate_;}
3828};
3829
3830template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Howard Hinnant82894812010-09-22 16:48:34 +00003831inline _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003832wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3833 wstring_convert(_Codecvt* __pcvt)
3834 : __cvtptr_(__pcvt), __cvtstate_(), __cvtcount_(0)
3835{
3836}
3837
3838template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Howard Hinnant82894812010-09-22 16:48:34 +00003839inline _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003840wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3841 wstring_convert(_Codecvt* __pcvt, state_type __state)
3842 : __cvtptr_(__pcvt), __cvtstate_(__state), __cvtcount_(0)
3843{
3844}
3845
3846template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3847wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3848 wstring_convert(const byte_string& __byte_err, const wide_string& __wide_err)
3849 : __byte_err_string_(__byte_err), __wide_err_string_(__wide_err),
3850 __cvtstate_(), __cvtcount_(0)
3851{
3852 __cvtptr_ = new _Codecvt;
3853}
3854
Howard Hinnant73d21a42010-09-04 23:28:19 +00003855#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantd23b4642010-05-31 20:58:54 +00003856
3857template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Howard Hinnant82894812010-09-22 16:48:34 +00003858inline _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003859wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3860 wstring_convert(wstring_convert&& __wc)
Howard Hinnant0949eed2011-06-30 21:18:19 +00003861 : __byte_err_string_(_VSTD::move(__wc.__byte_err_string_)),
3862 __wide_err_string_(_VSTD::move(__wc.__wide_err_string_)),
Howard Hinnantd23b4642010-05-31 20:58:54 +00003863 __cvtptr_(__wc.__cvtptr_),
3864 __cvtstate_(__wc.__cvtstate_), __cvtcount_(__wc.__cvtstate_)
3865{
3866 __wc.__cvtptr_ = nullptr;
3867}
3868
Howard Hinnantbfd55302010-09-04 23:46:48 +00003869#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantd23b4642010-05-31 20:58:54 +00003870
3871template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3872wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::~wstring_convert()
3873{
3874 delete __cvtptr_;
3875}
3876
3877template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3878typename wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::wide_string
3879wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3880 from_bytes(const char* __frm, const char* __frm_end)
3881{
3882 __cvtcount_ = 0;
3883 if (__cvtptr_ != nullptr)
3884 {
3885 wide_string __ws(2*(__frm_end - __frm), _Elem());
3886 __ws.resize(__ws.capacity());
3887 codecvt_base::result __r = codecvt_base::ok;
3888 state_type __st = __cvtstate_;
3889 if (__frm != __frm_end)
3890 {
3891 _Elem* __to = &__ws[0];
3892 _Elem* __to_end = __to + __ws.size();
3893 const char* __frm_nxt;
3894 do
3895 {
3896 _Elem* __to_nxt;
3897 __r = __cvtptr_->in(__st, __frm, __frm_end, __frm_nxt,
3898 __to, __to_end, __to_nxt);
3899 __cvtcount_ += __frm_nxt - __frm;
3900 if (__frm_nxt == __frm)
3901 {
3902 __r = codecvt_base::error;
3903 }
3904 else if (__r == codecvt_base::noconv)
3905 {
3906 __ws.resize(__to - &__ws[0]);
3907 // This only gets executed if _Elem is char
3908 __ws.append((const _Elem*)__frm, (const _Elem*)__frm_end);
3909 __frm = __frm_nxt;
3910 __r = codecvt_base::ok;
3911 }
3912 else if (__r == codecvt_base::ok)
3913 {
3914 __ws.resize(__to_nxt - &__ws[0]);
3915 __frm = __frm_nxt;
3916 }
3917 else if (__r == codecvt_base::partial)
3918 {
3919 ptrdiff_t __s = __to_nxt - &__ws[0];
3920 __ws.resize(2 * __s);
3921 __to = &__ws[0] + __s;
3922 __to_end = &__ws[0] + __ws.size();
3923 __frm = __frm_nxt;
3924 }
3925 } while (__r == codecvt_base::partial && __frm_nxt < __frm_end);
3926 }
3927 if (__r == codecvt_base::ok)
3928 return __ws;
3929 }
Howard Hinnantd4444702010-08-11 17:04:31 +00003930#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00003931 if (__wide_err_string_.empty())
3932 throw range_error("wstring_convert: from_bytes error");
Howard Hinnant324bb032010-08-22 00:02:43 +00003933#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00003934 return __wide_err_string_;
3935}
3936
3937template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3938typename wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::byte_string
3939wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3940 to_bytes(const _Elem* __frm, const _Elem* __frm_end)
3941{
3942 __cvtcount_ = 0;
3943 if (__cvtptr_ != nullptr)
3944 {
3945 byte_string __bs(2*(__frm_end - __frm), char());
3946 __bs.resize(__bs.capacity());
3947 codecvt_base::result __r = codecvt_base::ok;
3948 state_type __st = __cvtstate_;
3949 if (__frm != __frm_end)
3950 {
3951 char* __to = &__bs[0];
3952 char* __to_end = __to + __bs.size();
3953 const _Elem* __frm_nxt;
3954 do
3955 {
3956 char* __to_nxt;
3957 __r = __cvtptr_->out(__st, __frm, __frm_end, __frm_nxt,
3958 __to, __to_end, __to_nxt);
3959 __cvtcount_ += __frm_nxt - __frm;
3960 if (__frm_nxt == __frm)
3961 {
3962 __r = codecvt_base::error;
3963 }
3964 else if (__r == codecvt_base::noconv)
3965 {
3966 __bs.resize(__to - &__bs[0]);
3967 // This only gets executed if _Elem is char
3968 __bs.append((const char*)__frm, (const char*)__frm_end);
3969 __frm = __frm_nxt;
3970 __r = codecvt_base::ok;
3971 }
3972 else if (__r == codecvt_base::ok)
3973 {
3974 __bs.resize(__to_nxt - &__bs[0]);
3975 __frm = __frm_nxt;
3976 }
3977 else if (__r == codecvt_base::partial)
3978 {
3979 ptrdiff_t __s = __to_nxt - &__bs[0];
3980 __bs.resize(2 * __s);
3981 __to = &__bs[0] + __s;
3982 __to_end = &__bs[0] + __bs.size();
3983 __frm = __frm_nxt;
3984 }
3985 } while (__r == codecvt_base::partial && __frm_nxt < __frm_end);
3986 }
3987 if (__r == codecvt_base::ok)
3988 {
3989 size_t __s = __bs.size();
3990 __bs.resize(__bs.capacity());
3991 char* __to = &__bs[0] + __s;
3992 char* __to_end = __to + __bs.size();
3993 do
3994 {
3995 char* __to_nxt;
3996 __r = __cvtptr_->unshift(__st, __to, __to_end, __to_nxt);
3997 if (__r == codecvt_base::noconv)
3998 {
3999 __bs.resize(__to - &__bs[0]);
4000 __r = codecvt_base::ok;
4001 }
4002 else if (__r == codecvt_base::ok)
4003 {
4004 __bs.resize(__to_nxt - &__bs[0]);
4005 }
4006 else if (__r == codecvt_base::partial)
4007 {
4008 ptrdiff_t __s = __to_nxt - &__bs[0];
4009 __bs.resize(2 * __s);
4010 __to = &__bs[0] + __s;
4011 __to_end = &__bs[0] + __bs.size();
4012 }
4013 } while (__r == codecvt_base::partial);
4014 if (__r == codecvt_base::ok)
4015 return __bs;
4016 }
4017 }
Howard Hinnantd4444702010-08-11 17:04:31 +00004018#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00004019 if (__byte_err_string_.empty())
4020 throw range_error("wstring_convert: to_bytes error");
Howard Hinnant324bb032010-08-22 00:02:43 +00004021#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00004022 return __byte_err_string_;
4023}
4024
4025template <class _Codecvt, class _Elem = wchar_t, class _Tr = char_traits<_Elem> >
Howard Hinnant82894812010-09-22 16:48:34 +00004026class _LIBCPP_VISIBLE wbuffer_convert
Howard Hinnantd23b4642010-05-31 20:58:54 +00004027 : public basic_streambuf<_Elem, _Tr>
4028{
4029public:
4030 // types:
4031 typedef _Elem char_type;
4032 typedef _Tr traits_type;
4033 typedef typename traits_type::int_type int_type;
4034 typedef typename traits_type::pos_type pos_type;
4035 typedef typename traits_type::off_type off_type;
4036 typedef typename _Codecvt::state_type state_type;
4037
4038private:
Howard Hinnant4b53f502010-06-01 20:09:18 +00004039 char* __extbuf_;
4040 const char* __extbufnext_;
4041 const char* __extbufend_;
4042 char __extbuf_min_[8];
4043 size_t __ebs_;
4044 char_type* __intbuf_;
4045 size_t __ibs_;
Howard Hinnantd23b4642010-05-31 20:58:54 +00004046 streambuf* __bufptr_;
Howard Hinnant4b53f502010-06-01 20:09:18 +00004047 _Codecvt* __cv_;
4048 state_type __st_;
4049 ios_base::openmode __cm_;
4050 bool __owns_eb_;
4051 bool __owns_ib_;
4052 bool __always_noconv_;
Howard Hinnantd23b4642010-05-31 20:58:54 +00004053
Howard Hinnant4b53f502010-06-01 20:09:18 +00004054 wbuffer_convert(const wbuffer_convert&);
4055 wbuffer_convert& operator=(const wbuffer_convert&);
Howard Hinnantd23b4642010-05-31 20:58:54 +00004056public:
4057 wbuffer_convert(streambuf* __bytebuf = 0, _Codecvt* __pcvt = new _Codecvt,
Howard Hinnant4b53f502010-06-01 20:09:18 +00004058 state_type __state = state_type());
4059 ~wbuffer_convert();
Howard Hinnantd23b4642010-05-31 20:58:54 +00004060
Howard Hinnant82894812010-09-22 16:48:34 +00004061 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantd23b4642010-05-31 20:58:54 +00004062 streambuf* rdbuf() const {return __bufptr_;}
Howard Hinnant82894812010-09-22 16:48:34 +00004063 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantd23b4642010-05-31 20:58:54 +00004064 streambuf* rdbuf(streambuf* __bytebuf)
4065 {
4066 streambuf* __r = __bufptr_;
4067 __bufptr_ = __bytebuf;
4068 return __r;
4069 }
4070
Howard Hinnant82894812010-09-22 16:48:34 +00004071 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant4b53f502010-06-01 20:09:18 +00004072 state_type state() const {return __st_;}
Howard Hinnantd23b4642010-05-31 20:58:54 +00004073
4074protected:
Howard Hinnant4b53f502010-06-01 20:09:18 +00004075 virtual int_type underflow();
4076 virtual int_type pbackfail(int_type __c = traits_type::eof());
Howard Hinnantd23b4642010-05-31 20:58:54 +00004077 virtual int_type overflow (int_type __c = traits_type::eof());
Howard Hinnant4b53f502010-06-01 20:09:18 +00004078 virtual basic_streambuf<char_type, traits_type>* setbuf(char_type* __s,
4079 streamsize __n);
4080 virtual pos_type seekoff(off_type __off, ios_base::seekdir __way,
4081 ios_base::openmode __wch = ios_base::in | ios_base::out);
4082 virtual pos_type seekpos(pos_type __sp,
4083 ios_base::openmode __wch = ios_base::in | ios_base::out);
4084 virtual int sync();
4085
4086private:
4087 bool __read_mode();
4088 void __write_mode();
4089 wbuffer_convert* __close();
Howard Hinnantd23b4642010-05-31 20:58:54 +00004090};
4091
4092template <class _Codecvt, class _Elem, class _Tr>
Howard Hinnant4b53f502010-06-01 20:09:18 +00004093wbuffer_convert<_Codecvt, _Elem, _Tr>::
4094 wbuffer_convert(streambuf* __bytebuf, _Codecvt* __pcvt, state_type __state)
4095 : __extbuf_(0),
4096 __extbufnext_(0),
4097 __extbufend_(0),
4098 __ebs_(0),
4099 __intbuf_(0),
4100 __ibs_(0),
4101 __bufptr_(__bytebuf),
4102 __cv_(__pcvt),
4103 __st_(__state),
4104 __cm_(0),
4105 __owns_eb_(false),
4106 __owns_ib_(false),
4107 __always_noconv_(__cv_ ? __cv_->always_noconv() : false)
4108{
4109 setbuf(0, 4096);
4110}
4111
4112template <class _Codecvt, class _Elem, class _Tr>
4113wbuffer_convert<_Codecvt, _Elem, _Tr>::~wbuffer_convert()
4114{
4115 __close();
4116 delete __cv_;
4117 if (__owns_eb_)
4118 delete [] __extbuf_;
4119 if (__owns_ib_)
4120 delete [] __intbuf_;
4121}
4122
4123template <class _Codecvt, class _Elem, class _Tr>
4124typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
4125wbuffer_convert<_Codecvt, _Elem, _Tr>::underflow()
4126{
4127 if (__cv_ == 0 || __bufptr_ == 0)
4128 return traits_type::eof();
4129 bool __initial = __read_mode();
4130 char_type __1buf;
4131 if (this->gptr() == 0)
4132 this->setg(&__1buf, &__1buf+1, &__1buf+1);
4133 const size_t __unget_sz = __initial ? 0 : min<size_t>((this->egptr() - this->eback()) / 2, 4);
4134 int_type __c = traits_type::eof();
4135 if (this->gptr() == this->egptr())
4136 {
4137 memmove(this->eback(), this->egptr() - __unget_sz, __unget_sz * sizeof(char_type));
4138 if (__always_noconv_)
4139 {
4140 streamsize __nmemb = static_cast<streamsize>(this->egptr() - this->eback() - __unget_sz);
4141 __nmemb = __bufptr_->sgetn((char*)this->eback() + __unget_sz, __nmemb);
4142 if (__nmemb != 0)
4143 {
4144 this->setg(this->eback(),
4145 this->eback() + __unget_sz,
4146 this->eback() + __unget_sz + __nmemb);
4147 __c = *this->gptr();
4148 }
4149 }
4150 else
4151 {
4152 memmove(__extbuf_, __extbufnext_, __extbufend_ - __extbufnext_);
4153 __extbufnext_ = __extbuf_ + (__extbufend_ - __extbufnext_);
4154 __extbufend_ = __extbuf_ + (__extbuf_ == __extbuf_min_ ? sizeof(__extbuf_min_) : __ebs_);
Howard Hinnant0949eed2011-06-30 21:18:19 +00004155 streamsize __nmemb = _VSTD::min(static_cast<streamsize>(this->egptr() - this->eback() - __unget_sz),
Howard Hinnant4b53f502010-06-01 20:09:18 +00004156 static_cast<streamsize>(__extbufend_ - __extbufnext_));
4157 codecvt_base::result __r;
4158 state_type __svs = __st_;
4159 streamsize __nr = __bufptr_->sgetn(const_cast<char*>(__extbufnext_), __nmemb);
4160 if (__nr != 0)
4161 {
4162 __extbufend_ = __extbufnext_ + __nr;
4163 char_type* __inext;
4164 __r = __cv_->in(__st_, __extbuf_, __extbufend_, __extbufnext_,
4165 this->eback() + __unget_sz,
4166 this->egptr(), __inext);
4167 if (__r == codecvt_base::noconv)
4168 {
4169 this->setg((char_type*)__extbuf_, (char_type*)__extbuf_, (char_type*)__extbufend_);
4170 __c = *this->gptr();
4171 }
4172 else if (__inext != this->eback() + __unget_sz)
4173 {
4174 this->setg(this->eback(), this->eback() + __unget_sz, __inext);
4175 __c = *this->gptr();
4176 }
4177 }
4178 }
4179 }
4180 else
4181 __c = *this->gptr();
4182 if (this->eback() == &__1buf)
4183 this->setg(0, 0, 0);
4184 return __c;
4185}
4186
4187template <class _Codecvt, class _Elem, class _Tr>
4188typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
4189wbuffer_convert<_Codecvt, _Elem, _Tr>::pbackfail(int_type __c)
4190{
4191 if (__cv_ != 0 && __bufptr_ != 0 && this->eback() < this->gptr())
4192 {
4193 if (traits_type::eq_int_type(__c, traits_type::eof()))
4194 {
4195 this->gbump(-1);
4196 return traits_type::not_eof(__c);
4197 }
4198 if (traits_type::eq(traits_type::to_char_type(__c), this->gptr()[-1]))
4199 {
4200 this->gbump(-1);
4201 *this->gptr() = traits_type::to_char_type(__c);
4202 return __c;
4203 }
4204 }
4205 return traits_type::eof();
4206}
4207
4208template <class _Codecvt, class _Elem, class _Tr>
Howard Hinnantd23b4642010-05-31 20:58:54 +00004209typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
4210wbuffer_convert<_Codecvt, _Elem, _Tr>::overflow(int_type __c)
4211{
Howard Hinnant4b53f502010-06-01 20:09:18 +00004212 if (__cv_ == 0 || __bufptr_ == 0)
4213 return traits_type::eof();
4214 __write_mode();
4215 char_type __1buf;
4216 char_type* __pb_save = this->pbase();
4217 char_type* __epb_save = this->epptr();
4218 if (!traits_type::eq_int_type(__c, traits_type::eof()))
4219 {
4220 if (this->pptr() == 0)
4221 this->setp(&__1buf, &__1buf+1);
4222 *this->pptr() = traits_type::to_char_type(__c);
4223 this->pbump(1);
4224 }
4225 if (this->pptr() != this->pbase())
4226 {
4227 if (__always_noconv_)
4228 {
4229 streamsize __nmemb = static_cast<streamsize>(this->pptr() - this->pbase());
4230 if (__bufptr_->sputn((const char*)this->pbase(), __nmemb) != __nmemb)
4231 return traits_type::eof();
4232 }
4233 else
4234 {
4235 char* __extbe = __extbuf_;
4236 codecvt_base::result __r;
4237 do
4238 {
4239 const char_type* __e;
4240 __r = __cv_->out(__st_, this->pbase(), this->pptr(), __e,
4241 __extbuf_, __extbuf_ + __ebs_, __extbe);
4242 if (__e == this->pbase())
4243 return traits_type::eof();
4244 if (__r == codecvt_base::noconv)
4245 {
4246 streamsize __nmemb = static_cast<size_t>(this->pptr() - this->pbase());
4247 if (__bufptr_->sputn((const char*)this->pbase(), __nmemb) != __nmemb)
4248 return traits_type::eof();
4249 }
4250 else if (__r == codecvt_base::ok || __r == codecvt_base::partial)
4251 {
4252 streamsize __nmemb = static_cast<size_t>(__extbe - __extbuf_);
4253 if (__bufptr_->sputn(__extbuf_, __nmemb) != __nmemb)
4254 return traits_type::eof();
4255 if (__r == codecvt_base::partial)
4256 {
4257 this->setp((char_type*)__e, this->pptr());
4258 this->pbump(this->epptr() - this->pbase());
4259 }
4260 }
4261 else
4262 return traits_type::eof();
4263 } while (__r == codecvt_base::partial);
4264 }
4265 this->setp(__pb_save, __epb_save);
4266 }
4267 return traits_type::not_eof(__c);
4268}
4269
4270template <class _Codecvt, class _Elem, class _Tr>
4271basic_streambuf<_Elem, _Tr>*
4272wbuffer_convert<_Codecvt, _Elem, _Tr>::setbuf(char_type* __s, streamsize __n)
4273{
4274 this->setg(0, 0, 0);
4275 this->setp(0, 0);
4276 if (__owns_eb_)
4277 delete [] __extbuf_;
4278 if (__owns_ib_)
4279 delete [] __intbuf_;
4280 __ebs_ = __n;
4281 if (__ebs_ > sizeof(__extbuf_min_))
4282 {
4283 if (__always_noconv_ && __s)
4284 {
4285 __extbuf_ = (char*)__s;
4286 __owns_eb_ = false;
4287 }
4288 else
4289 {
4290 __extbuf_ = new char[__ebs_];
4291 __owns_eb_ = true;
4292 }
4293 }
4294 else
4295 {
4296 __extbuf_ = __extbuf_min_;
4297 __ebs_ = sizeof(__extbuf_min_);
4298 __owns_eb_ = false;
4299 }
4300 if (!__always_noconv_)
4301 {
4302 __ibs_ = max<streamsize>(__n, sizeof(__extbuf_min_));
4303 if (__s && __ibs_ >= sizeof(__extbuf_min_))
4304 {
4305 __intbuf_ = __s;
4306 __owns_ib_ = false;
4307 }
4308 else
4309 {
4310 __intbuf_ = new char_type[__ibs_];
4311 __owns_ib_ = true;
4312 }
4313 }
4314 else
4315 {
4316 __ibs_ = 0;
4317 __intbuf_ = 0;
4318 __owns_ib_ = false;
4319 }
4320 return this;
4321}
4322
4323template <class _Codecvt, class _Elem, class _Tr>
4324typename wbuffer_convert<_Codecvt, _Elem, _Tr>::pos_type
4325wbuffer_convert<_Codecvt, _Elem, _Tr>::seekoff(off_type __off, ios_base::seekdir __way,
4326 ios_base::openmode __om)
4327{
4328 int __width = __cv_->encoding();
4329 if (__cv_ == 0 || __bufptr_ == 0 || (__width <= 0 && __off != 0) || sync())
4330 return pos_type(off_type(-1));
4331 // __width > 0 || __off == 0
4332 switch (__way)
4333 {
4334 case ios_base::beg:
4335 break;
4336 case ios_base::cur:
4337 break;
4338 case ios_base::end:
4339 break;
4340 default:
4341 return pos_type(off_type(-1));
4342 }
4343 pos_type __r = __bufptr_->pubseekoff(__width * __off, __way, __om);
4344 __r.state(__st_);
4345 return __r;
4346}
4347
4348template <class _Codecvt, class _Elem, class _Tr>
4349typename wbuffer_convert<_Codecvt, _Elem, _Tr>::pos_type
4350wbuffer_convert<_Codecvt, _Elem, _Tr>::seekpos(pos_type __sp, ios_base::openmode __wch)
4351{
4352 if (__cv_ == 0 || __bufptr_ == 0 || sync())
4353 return pos_type(off_type(-1));
4354 if (__bufptr_->pubseekpos(__sp, __wch) == pos_type(off_type(-1)))
4355 return pos_type(off_type(-1));
4356 return __sp;
4357}
4358
4359template <class _Codecvt, class _Elem, class _Tr>
4360int
4361wbuffer_convert<_Codecvt, _Elem, _Tr>::sync()
4362{
4363 if (__cv_ == 0 || __bufptr_ == 0)
4364 return 0;
4365 if (__cm_ & ios_base::out)
4366 {
4367 if (this->pptr() != this->pbase())
4368 if (overflow() == traits_type::eof())
4369 return -1;
4370 codecvt_base::result __r;
4371 do
4372 {
4373 char* __extbe;
4374 __r = __cv_->unshift(__st_, __extbuf_, __extbuf_ + __ebs_, __extbe);
4375 streamsize __nmemb = static_cast<streamsize>(__extbe - __extbuf_);
4376 if (__bufptr_->sputn(__extbuf_, __nmemb) != __nmemb)
4377 return -1;
4378 } while (__r == codecvt_base::partial);
4379 if (__r == codecvt_base::error)
4380 return -1;
4381 if (__bufptr_->pubsync())
4382 return -1;
4383 }
4384 else if (__cm_ & ios_base::in)
4385 {
4386 off_type __c;
4387 if (__always_noconv_)
4388 __c = this->egptr() - this->gptr();
4389 else
4390 {
4391 int __width = __cv_->encoding();
4392 __c = __extbufend_ - __extbufnext_;
4393 if (__width > 0)
4394 __c += __width * (this->egptr() - this->gptr());
4395 else
4396 {
4397 if (this->gptr() != this->egptr())
4398 {
4399 reverse(this->gptr(), this->egptr());
4400 codecvt_base::result __r;
4401 const char_type* __e = this->gptr();
4402 char* __extbe;
4403 do
4404 {
4405 __r = __cv_->out(__st_, __e, this->egptr(), __e,
4406 __extbuf_, __extbuf_ + __ebs_, __extbe);
4407 switch (__r)
4408 {
4409 case codecvt_base::noconv:
4410 __c += this->egptr() - this->gptr();
4411 break;
4412 case codecvt_base::ok:
4413 case codecvt_base::partial:
4414 __c += __extbe - __extbuf_;
4415 break;
4416 default:
4417 return -1;
4418 }
4419 } while (__r == codecvt_base::partial);
4420 }
4421 }
4422 }
4423 if (__bufptr_->pubseekoff(-__c, ios_base::cur, __cm_) == pos_type(off_type(-1)))
4424 return -1;
4425 this->setg(0, 0, 0);
4426 __cm_ = 0;
4427 }
4428 return 0;
4429}
4430
4431template <class _Codecvt, class _Elem, class _Tr>
4432bool
4433wbuffer_convert<_Codecvt, _Elem, _Tr>::__read_mode()
4434{
4435 if (!(__cm_ & ios_base::in))
4436 {
4437 this->setp(0, 0);
4438 if (__always_noconv_)
4439 this->setg((char_type*)__extbuf_,
4440 (char_type*)__extbuf_ + __ebs_,
4441 (char_type*)__extbuf_ + __ebs_);
4442 else
4443 this->setg(__intbuf_, __intbuf_ + __ibs_, __intbuf_ + __ibs_);
4444 __cm_ = ios_base::in;
4445 return true;
4446 }
4447 return false;
4448}
4449
4450template <class _Codecvt, class _Elem, class _Tr>
4451void
4452wbuffer_convert<_Codecvt, _Elem, _Tr>::__write_mode()
4453{
4454 if (!(__cm_ & ios_base::out))
4455 {
4456 this->setg(0, 0, 0);
4457 if (__ebs_ > sizeof(__extbuf_min_))
4458 {
4459 if (__always_noconv_)
4460 this->setp((char_type*)__extbuf_,
4461 (char_type*)__extbuf_ + (__ebs_ - 1));
4462 else
4463 this->setp(__intbuf_, __intbuf_ + (__ibs_ - 1));
4464 }
4465 else
4466 this->setp(0, 0);
4467 __cm_ = ios_base::out;
4468 }
4469}
4470
4471template <class _Codecvt, class _Elem, class _Tr>
4472wbuffer_convert<_Codecvt, _Elem, _Tr>*
4473wbuffer_convert<_Codecvt, _Elem, _Tr>::__close()
4474{
4475 wbuffer_convert* __rt = 0;
4476 if (__cv_ != 0 && __bufptr_ != 0)
4477 {
4478 __rt = this;
4479 if ((__cm_ & ios_base::out) && sync())
4480 __rt = 0;
4481 }
4482 return __rt;
Howard Hinnantd23b4642010-05-31 20:58:54 +00004483}
4484
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004485_LIBCPP_END_NAMESPACE_STD
4486
4487#endif // _LIBCPP_LOCALE