blob: 549ae60d2c6279562c2b0fbd56186d4c8f0e29b1 [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>
189#include <nl_types.h>
190
191#pragma GCC system_header
192
193_LIBCPP_BEGIN_NAMESPACE_STD
194
Sean Hunte59f7242011-07-09 01:09:31 +0000195#ifndef _LIBCPP_STABLE_APPLE_ABI
Sean Hunt62a6ac32011-07-09 00:56:23 +0000196// Get the C locale object
197locale_t __cloc();
Sean Hunte59f7242011-07-09 01:09:31 +0000198#endif
Sean Hunt62a6ac32011-07-09 00:56:23 +0000199
Sean Huntf3907e62011-07-15 05:40:33 +0000200typedef _VSTD::remove_pointer<locale_t>::type __locale_struct;
201typedef _VSTD::unique_ptr<__locale_struct, decltype(&freelocale)> __locale_unique_ptr;
202typedef _VSTD::unique_ptr<__locale_struct, decltype(&uselocale)> __locale_raii;
203
Howard Hinnantadff4892010-05-24 17:49:41 +0000204// OSX has nice foo_l() functions that let you turn off use of the global
205// locale. Linux, not so much. The following functions avoid the locale when
206// that's possible and otherwise do the wrong thing. FIXME.
Sean Huntf3907e62011-07-15 05:40:33 +0000207#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantadff4892010-05-24 17:49:41 +0000208template <class _Tp>
Howard Hinnant82894812010-09-22 16:48:34 +0000209inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantadff4892010-05-24 17:49:41 +0000210int
211__nolocale_sprintf(char* __restrict __str,
212 const char* __restrict __format, _Tp __v)
213{
214 return sprintf_l(__str, 0, __format, __v);
215}
216
217template <class _Tp>
Howard Hinnant82894812010-09-22 16:48:34 +0000218inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantadff4892010-05-24 17:49:41 +0000219int
220__nolocale_snprintf(char* __restrict __str, size_t __size,
221 const char* __restrict __format, _Tp __v)
222{
223 return snprintf_l(__str, __size, 0, __format, __v);
224}
225
226template <class _Tp>
Howard Hinnant82894812010-09-22 16:48:34 +0000227inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantadff4892010-05-24 17:49:41 +0000228int
229__nolocale_snprintf(char* __restrict __str, size_t __size,
230 const char* __restrict __format, int __prec, _Tp __v)
231{
232 return snprintf_l(__str, __size, 0, __format, __prec, __v);
233}
234
235template <class _Tp>
Howard Hinnant82894812010-09-22 16:48:34 +0000236inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantadff4892010-05-24 17:49:41 +0000237int
238__nolocale_asprintf(char** __ret, const char* __restrict __format, _Tp __v)
239{
240 return asprintf_l(__ret, 0, __format, __v);
241}
242
243template <class _Tp>
Howard Hinnant82894812010-09-22 16:48:34 +0000244inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantadff4892010-05-24 17:49:41 +0000245int
246__nolocale_asprintf(char** __ret, const char* __restrict __format, int __prec,
247 _Tp __v)
248{
249 return asprintf_l(__ret, 0, __format, __prec, __v);
250}
251
252template <class _Tp>
Howard Hinnant82894812010-09-22 16:48:34 +0000253inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantadff4892010-05-24 17:49:41 +0000254int
255__nolocale_sscanf(const char* __restrict __str,
256 const char* __restrict __format, _Tp* __v)
257{
258 return sscanf_l(__str, 0, __format, __v);
259}
260
Howard Hinnant82894812010-09-22 16:48:34 +0000261inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantadff4892010-05-24 17:49:41 +0000262int
263__nolocale_isxdigit(int __c)
264{
265 return isxdigit_l(__c, 0);
266}
267
Howard Hinnant82894812010-09-22 16:48:34 +0000268inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantadff4892010-05-24 17:49:41 +0000269int
270__nolocale_isdigit(int __c)
271{
272 return isdigit_l(__c, 0);
273}
274
Sean Huntf3907e62011-07-15 05:40:33 +0000275#else // _LIBCPP_STABLE_APPLE_ABI
276
277#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
278decltype(MB_CUR_MAX_L(_VSTD::declval<locale_t>()))
Howard Hinnant82894812010-09-22 16:48:34 +0000279inline _LIBCPP_INLINE_VISIBILITY
Sean Huntf3907e62011-07-15 05:40:33 +0000280__mb_cur_max_l(locale_t __l)
Howard Hinnantadff4892010-05-24 17:49:41 +0000281{
Sean Huntf3907e62011-07-15 05:40:33 +0000282 return MB_CUR_MAX_L(__l);
283}
284#else // _LIBCPP_LOCALE__L_EXTENSIONS
285_LIBCPP_ALWAYS_INLINE inline
286decltype(MB_CUR_MAX) __mb_cur_max_l(locale_t __l)
287{
288 __locale_raii __current(uselocale(__l), uselocale);
289 return MB_CUR_MAX;
290}
291#endif // _LIBCPP_LOCALE__L_EXTENSIONS
292
293_LIBCPP_ALWAYS_INLINE inline
294wint_t __btowc_l(int __c, locale_t __l)
295{
296#ifdef _LIBCPP_STABLE_APPLE_ABI
297 return btowc_l(__c, __l);
298#else
299 __locale_raii __current(uselocale(__l), uselocale);
300 return btowc(__c);
301#endif
Sean Huntc97da3a2011-07-13 06:40:50 +0000302}
Howard Hinnant8d756322011-07-13 15:48:16 +0000303
Sean Huntf3907e62011-07-15 05:40:33 +0000304_LIBCPP_ALWAYS_INLINE inline
305int __wctob_l(wint_t __c, locale_t __l)
Sean Huntc97da3a2011-07-13 06:40:50 +0000306{
Sean Huntf3907e62011-07-15 05:40:33 +0000307#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
308 return wctob_l(__c, __l);
309#else
310 __locale_raii __current(uselocale(__l), uselocale);
311 return wctob(__c);
312#endif
Sean Huntc97da3a2011-07-13 06:40:50 +0000313}
Sean Huntf3907e62011-07-15 05:40:33 +0000314
315_LIBCPP_ALWAYS_INLINE inline
316size_t __wcsnrtombs_l(char *__dest, const wchar_t **__src, size_t __nwc,
317 size_t __len, mbstate_t *__ps, locale_t __l)
318{
319#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
320 return wcsnrtombs_l(__dest, __src, __nwc, __len, __ps, __l);
321#else
322 __locale_raii __current(uselocale(__l), uselocale);
323 return wcsnrtombs(__dest, __src, __nwc, __len, __ps);
324#endif
325}
326
327_LIBCPP_ALWAYS_INLINE inline
328size_t __wcrtomb_l(char *__s, wchar_t __wc, mbstate_t *__ps, locale_t __l)
329{
330#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
331 return wcrtomb_l(__s, __wc, __ps, __l);
332#else
333 __locale_raii __current(uselocale(__l), uselocale);
334 return wcrtomb(__s, __wc, __ps);
335#endif
336}
337
338_LIBCPP_ALWAYS_INLINE inline
339size_t __mbsnrtowcs_l(wchar_t * __dest, const char **__src, size_t __nms,
340 size_t __len, mbstate_t *__ps, locale_t __l)
341{
342#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
343 return mbsnrtowcs_l(__dest, __src, __nms__len, __ps, __l);
344#else
345 __locale_raii __current(uselocale(__l), uselocale);
346 return mbsnrtowcs(__dest, __src, __nms, __len, __ps);
347#endif
348}
349
350_LIBCPP_ALWAYS_INLINE inline
351size_t __mbrtowc_l(wchar_t *__pwc, const char *__s, size_t __n,
352 mbstate_t *__ps, locale_t __l)
353{
354#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
355 return mbrtowc_l(__pwc, __s, __n, __ps, __l);
356#else
357 __locale_raii __current(uselocale(__l), uselocale);
358 return mbrtowc(__pwc, __s, __n, __ps);
359#endif
360}
361
362_LIBCPP_ALWAYS_INLINE inline
363int __mbtowc_l(wchar_t *__pwc, const char *__pmb, size_t __max, locale_t __l)
364{
365#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
366 return mbtowc(__pwc, __pmb, __max, __l);
367#else
368 __locale_raii __current(uselocale(__l), uselocale);
369 return mbtowc(__pwc, __pmb, __max);
370#endif
371}
372
373_LIBCPP_ALWAYS_INLINE inline
374size_t __mbrlen_l(const char *__s, size_t __n, mbstate_t *__ps, locale_t __l)
375{
376#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
377 return mbrlen_l(__s, __n, __ps, __l);
378#else
379 __locale_raii __current(uselocale(__l), uselocale);
380 return mbrlen(__s, __n, __ps);
381#endif
382}
383
384_LIBCPP_ALWAYS_INLINE inline
385lconv *__localeconv_l(locale_t __l)
386{
387#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
388 return localeconv_l(__l);
389#else
390 __locale_raii __current(uselocale(__l), uselocale);
391 return localeconv();
392#endif
393}
394
395_LIBCPP_ALWAYS_INLINE inline
396size_t __mbsrtowcs_l(wchar_t *__dest, const char **__src, size_t __len,
397 mbstate_t *__ps, locale_t __l)
398{
399#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
400 return mbsrtowcs_l(__dest, __src, __len, __ps, __l);
401#else
402 __locale_raii __current(uselocale(__l), uselocale);
403 return mbsrtowcs(__dest, __src, __len, __ps);
404#endif
405}
406
407_LIBCPP_ALWAYS_INLINE inline
408int __sprintf_l(char *__s, locale_t __l, const char *__format, ...) {
409 va_list __va;
410 va_start(__va, __format);
411#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
412 int __res = vsprintf_l(__s, __l, __format, __va);
413#else
414 __locale_raii __current(uselocale(__l), uselocale);
415 int __res = vsprintf(__s, __format, __va);
416#endif
417 va_end(__va);
418 return __res;
419}
420
421_LIBCPP_ALWAYS_INLINE inline
422int __snprintf_l(char *__s, size_t __n, locale_t __l, const char *__format, ...) {
423 va_list __va;
424 va_start(__va, __format);
425#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
426 int __res = vsnprintf_l(__s, __n, __l, __format, __va);
427#else
428 __locale_raii __current(uselocale(__l), uselocale);
429 int __res = vsnprintf(__s, __n, __format, __va);
430#endif
431 va_end(__va);
432 return __res;
433}
434
435_LIBCPP_ALWAYS_INLINE inline
436int __asprintf_l(char **__s, locale_t __l, const char *__format, ...) {
437 va_list __va;
438 va_start(__va, __format);
439#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
440 int __res = vasprintf_l(__s, __l, __format, __va);
441#else
442 __locale_raii __current(uselocale(__l), uselocale);
443 int __res = vasprintf(__s, __format, __va);
444#endif
445 va_end(__va);
446 return __res;
447}
448
449_LIBCPP_ALWAYS_INLINE inline
450int __sscanf_l(const char *__s, locale_t __l, const char *__format, ...) {
451 va_list __va;
452 va_start(__va, __format);
453#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
454 int __res = vsscanf_l(__s, __l, __format, __va);
455#else
456 __locale_raii __current(uselocale(__l), uselocale);
457 int __res = vsscanf(__s, __format, __va);
458#endif
459 va_end(__va);
460 return __res;
461}
462
463#endif // _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantadff4892010-05-24 17:49:41 +0000464
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000465// __scan_keyword
466// Scans [__b, __e) until a match is found in the basic_strings range
467// [__kb, __ke) or until it can be shown that there is no match in [__kb, __ke).
468// __b will be incremented (visibly), consuming CharT until a match is found
469// or proved to not exist. A keyword may be "", in which will match anything.
470// If one keyword is a prefix of another, and the next CharT in the input
471// might match another keyword, the algorithm will attempt to find the longest
472// matching keyword. If the longer matching keyword ends up not matching, then
473// no keyword match is found. If no keyword match is found, __ke is returned
474// and failbit is set in __err.
475// Else an iterator pointing to the matching keyword is found. If more than
476// one keyword matches, an iterator to the first matching keyword is returned.
477// If on exit __b == __e, eofbit is set in __err. If __case_senstive is false,
478// __ct is used to force to lower case before comparing characters.
479// Examples:
480// Keywords: "a", "abb"
481// If the input is "a", the first keyword matches and eofbit is set.
482// If the input is "abc", no match is found and "ab" are consumed.
483template <class _InputIterator, class _ForwardIterator, class _Ctype>
484_LIBCPP_HIDDEN
485_ForwardIterator
486__scan_keyword(_InputIterator& __b, _InputIterator __e,
487 _ForwardIterator __kb, _ForwardIterator __ke,
488 const _Ctype& __ct, ios_base::iostate& __err,
489 bool __case_sensitive = true)
490{
491 typedef typename iterator_traits<_InputIterator>::value_type _CharT;
Howard Hinnant0949eed2011-06-30 21:18:19 +0000492 size_t __nkw = _VSTD::distance(__kb, __ke);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000493 const unsigned char __doesnt_match = '\0';
494 const unsigned char __might_match = '\1';
495 const unsigned char __does_match = '\2';
496 unsigned char __statbuf[100];
497 unsigned char* __status = __statbuf;
498 unique_ptr<unsigned char, void(*)(void*)> __stat_hold(0, free);
499 if (__nkw > sizeof(__statbuf))
500 {
501 __status = (unsigned char*)malloc(__nkw);
502 if (__status == 0)
503 __throw_bad_alloc();
504 __stat_hold.reset(__status);
505 }
506 size_t __n_might_match = __nkw; // At this point, any keyword might match
507 size_t __n_does_match = 0; // but none of them definitely do
508 // Initialize all statuses to __might_match, except for "" keywords are __does_match
509 unsigned char* __st = __status;
510 for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, ++__st)
511 {
512 if (!__ky->empty())
513 *__st = __might_match;
514 else
515 {
516 *__st = __does_match;
517 --__n_might_match;
518 ++__n_does_match;
519 }
520 }
521 // While there might be a match, test keywords against the next CharT
522 for (size_t __indx = 0; __b != __e && __n_might_match > 0; ++__indx)
523 {
524 // Peek at the next CharT but don't consume it
525 _CharT __c = *__b;
526 if (!__case_sensitive)
527 __c = __ct.toupper(__c);
528 bool __consume = false;
529 // For each keyword which might match, see if the __indx character is __c
530 // If a match if found, consume __c
531 // If a match is found, and that is the last character in the keyword,
532 // then that keyword matches.
533 // If the keyword doesn't match this character, then change the keyword
534 // to doesn't match
535 __st = __status;
536 for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, ++__st)
537 {
538 if (*__st == __might_match)
539 {
540 _CharT __kc = (*__ky)[__indx];
541 if (!__case_sensitive)
542 __kc = __ct.toupper(__kc);
543 if (__c == __kc)
544 {
545 __consume = true;
546 if (__ky->size() == __indx+1)
547 {
548 *__st = __does_match;
549 --__n_might_match;
550 ++__n_does_match;
551 }
552 }
553 else
554 {
555 *__st = __doesnt_match;
556 --__n_might_match;
557 }
558 }
559 }
560 // consume if we matched a character
561 if (__consume)
562 {
563 ++__b;
564 // If we consumed a character and there might be a matched keyword that
565 // was marked matched on a previous iteration, then such keywords
566 // which are now marked as not matching.
567 if (__n_might_match + __n_does_match > 1)
568 {
569 __st = __status;
570 for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, ++__st)
571 {
572 if (*__st == __does_match && __ky->size() != __indx+1)
573 {
574 *__st = __doesnt_match;
575 --__n_does_match;
576 }
577 }
578 }
579 }
580 }
581 // We've exited the loop because we hit eof and/or we have no more "might matches".
582 if (__b == __e)
583 __err |= ios_base::eofbit;
584 // Return the first matching result
585 for (__st = __status; __kb != __ke; ++__kb, ++__st)
586 if (*__st == __does_match)
587 break;
588 if (__kb == __ke)
589 __err |= ios_base::failbit;
590 return __kb;
591}
592
593struct __num_get_base
594{
595 static const int __num_get_buf_sz = 40;
596
597 static int __get_base(ios_base&);
598 static const char __src[33];
599};
600
601void __check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
602 ios_base::iostate& __err);
603
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000604template <class _CharT>
605struct __num_get
606 : protected __num_get_base
607{
608 static string __stage2_int_prep(ios_base& __iob, _CharT* __atoms, _CharT& __thousands_sep);
609 static string __stage2_float_prep(ios_base& __iob, _CharT* __atoms, _CharT& __decimal_point,
610 _CharT& __thousands_sep);
611 static int __stage2_int_loop(_CharT __ct, int __base, char* __a, char*& __a_end,
612 unsigned& __dc, _CharT __thousands_sep, const string& __grouping,
613 unsigned* __g, unsigned*& __g_end, _CharT* __atoms);
614 static int __stage2_float_loop(_CharT __ct, bool& __in_units, char& __exp,
615 char* __a, char*& __a_end,
616 _CharT __decimal_point, _CharT __thousands_sep,
617 const string& __grouping, unsigned* __g,
618 unsigned*& __g_end, unsigned& __dc, _CharT* __atoms);
619};
620
621template <class _CharT>
622string
623__num_get<_CharT>::__stage2_int_prep(ios_base& __iob, _CharT* __atoms, _CharT& __thousands_sep)
624{
625 locale __loc = __iob.getloc();
626 use_facet<ctype<_CharT> >(__loc).widen(__src, __src + 26, __atoms);
627 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
628 __thousands_sep = __np.thousands_sep();
629 return __np.grouping();
630}
631
632template <class _CharT>
633string
634__num_get<_CharT>::__stage2_float_prep(ios_base& __iob, _CharT* __atoms, _CharT& __decimal_point,
635 _CharT& __thousands_sep)
636{
637 locale __loc = __iob.getloc();
638 use_facet<ctype<_CharT> >(__loc).widen(__src, __src + 32, __atoms);
639 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
640 __decimal_point = __np.decimal_point();
641 __thousands_sep = __np.thousands_sep();
642 return __np.grouping();
643}
644
645template <class _CharT>
646int
647__num_get<_CharT>::__stage2_int_loop(_CharT __ct, int __base, char* __a, char*& __a_end,
648 unsigned& __dc, _CharT __thousands_sep, const string& __grouping,
649 unsigned* __g, unsigned*& __g_end, _CharT* __atoms)
650{
Howard Hinnant80586722011-03-09 01:03:19 +0000651 if (__a_end == __a && (__ct == __atoms[24] || __ct == __atoms[25]))
652 {
653 *__a_end++ = __ct == __atoms[24] ? '+' : '-';
654 __dc = 0;
655 return 0;
656 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000657 if (__ct == __thousands_sep && __grouping.size() != 0)
658 {
659 if (__g_end-__g < __num_get_buf_sz)
660 {
661 *__g_end++ = __dc;
662 __dc = 0;
663 }
664 return 0;
665 }
666 ptrdiff_t __f = find(__atoms, __atoms + 26, __ct) - __atoms;
Howard Hinnant80586722011-03-09 01:03:19 +0000667 if (__f >= 24)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000668 return -1;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000669 switch (__base)
670 {
671 case 8:
672 case 10:
673 if (__f >= __base)
Howard Hinnant80586722011-03-09 01:03:19 +0000674 return -1;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000675 break;
Howard Hinnant80586722011-03-09 01:03:19 +0000676 case 16:
677 if (__f < 22)
678 break;
679 if (__a_end != __a && __a_end - __a <= 2 && __a_end[-1] == '0')
680 {
681 __dc = 0;
682 *__a_end++ = __src[__f];
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000683 return 0;
Howard Hinnant80586722011-03-09 01:03:19 +0000684 }
685 return -1;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000686 }
Howard Hinnant80586722011-03-09 01:03:19 +0000687 if (__a_end-__a < __num_get_buf_sz - 1)
688 *__a_end++ = __src[__f];
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000689 ++__dc;
690 return 0;
691}
692
693template <class _CharT>
694int
695__num_get<_CharT>::__stage2_float_loop(_CharT __ct, bool& __in_units, char& __exp, char* __a, char*& __a_end,
696 _CharT __decimal_point, _CharT __thousands_sep, const string& __grouping,
697 unsigned* __g, unsigned*& __g_end, unsigned& __dc, _CharT* __atoms)
698{
699 if (__ct == __decimal_point)
700 {
701 if (!__in_units)
702 return -1;
703 __in_units = false;
704 *__a_end++ = '.';
705 if (__grouping.size() != 0 && __g_end-__g < __num_get_buf_sz)
706 *__g_end++ = __dc;
707 return 0;
708 }
709 if (__ct == __thousands_sep && __grouping.size() != 0)
710 {
711 if (!__in_units)
712 return -1;
713 if (__g_end-__g < __num_get_buf_sz)
714 {
715 *__g_end++ = __dc;
716 __dc = 0;
717 }
718 return 0;
719 }
720 ptrdiff_t __f = find(__atoms, __atoms + 32, __ct) - __atoms;
721 if (__f >= 32)
722 return -1;
723 char __x = __src[__f];
724 if (__a_end-__a < __num_get_buf_sz - 1)
725 *__a_end++ = __x;
726 if (__x == 'x' || __x == 'X')
727 __exp = 'P';
728 else if ((__x & 0xDF) == __exp)
729 {
730 __in_units = false;
731 if (__grouping.size() != 0 && __g_end-__g < __num_get_buf_sz)
732 *__g_end++ = __dc;
733 }
734 if (__f >= 22)
735 return 0;
736 ++__dc;
737 return 0;
738}
739
740extern template class __num_get<char>;
741extern template class __num_get<wchar_t>;
742
743template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +0000744class _LIBCPP_VISIBLE num_get
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000745 : public locale::facet,
746 private __num_get<_CharT>
747{
748public:
749 typedef _CharT char_type;
750 typedef _InputIterator iter_type;
751
752 _LIBCPP_ALWAYS_INLINE
753 explicit num_get(size_t __refs = 0)
754 : locale::facet(__refs) {}
755
756 _LIBCPP_ALWAYS_INLINE
757 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
758 ios_base::iostate& __err, bool& __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& __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, long long& __v) const
773 {
774 return do_get(__b, __e, __iob, __err, __v);
775 }
776
777 _LIBCPP_ALWAYS_INLINE
778 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
779 ios_base::iostate& __err, unsigned short& __v) const
780 {
781 return do_get(__b, __e, __iob, __err, __v);
782 }
783
784 _LIBCPP_ALWAYS_INLINE
785 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
786 ios_base::iostate& __err, unsigned int& __v) const
787 {
788 return do_get(__b, __e, __iob, __err, __v);
789 }
790
791 _LIBCPP_ALWAYS_INLINE
792 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
793 ios_base::iostate& __err, unsigned long& __v) const
794 {
795 return do_get(__b, __e, __iob, __err, __v);
796 }
797
798 _LIBCPP_ALWAYS_INLINE
799 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
800 ios_base::iostate& __err, unsigned long long& __v) const
801 {
802 return do_get(__b, __e, __iob, __err, __v);
803 }
804
805 _LIBCPP_ALWAYS_INLINE
806 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
807 ios_base::iostate& __err, float& __v) const
808 {
809 return do_get(__b, __e, __iob, __err, __v);
810 }
811
812 _LIBCPP_ALWAYS_INLINE
813 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
814 ios_base::iostate& __err, double& __v) const
815 {
816 return do_get(__b, __e, __iob, __err, __v);
817 }
818
819 _LIBCPP_ALWAYS_INLINE
820 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
821 ios_base::iostate& __err, long double& __v) const
822 {
823 return do_get(__b, __e, __iob, __err, __v);
824 }
825
826 _LIBCPP_ALWAYS_INLINE
827 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
828 ios_base::iostate& __err, void*& __v) const
829 {
830 return do_get(__b, __e, __iob, __err, __v);
831 }
832
833 static locale::id id;
834
835protected:
Howard Hinnant82894812010-09-22 16:48:34 +0000836 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000837 ~num_get() {}
838
839 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
840 ios_base::iostate& __err, bool& __v) const;
841 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
842 ios_base::iostate& __err, long& __v) const;
843 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
844 ios_base::iostate& __err, long long& __v) const;
845 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
846 ios_base::iostate& __err, unsigned short& __v) const;
847 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
848 ios_base::iostate& __err, unsigned int& __v) const;
849 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
850 ios_base::iostate& __err, unsigned long& __v) const;
851 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
852 ios_base::iostate& __err, unsigned long long& __v) const;
853 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
854 ios_base::iostate& __err, float& __v) const;
855 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
856 ios_base::iostate& __err, double& __v) const;
857 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
858 ios_base::iostate& __err, long double& __v) const;
859 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
860 ios_base::iostate& __err, void*& __v) const;
861};
862
863template <class _CharT, class _InputIterator>
864locale::id
865num_get<_CharT, _InputIterator>::id;
866
867template <class _Tp>
868_Tp
869__num_get_signed_integral(const char* __a, const char* __a_end,
870 ios_base::iostate& __err, int __base)
871{
872 if (__a != __a_end)
873 {
Howard Hinnante7c8da62011-02-25 19:52:41 +0000874 int __save_errno = errno;
875 errno = 0;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000876 char *__p2;
Sean Huntf3907e62011-07-15 05:40:33 +0000877#ifdef _LIBCXX_STABLE_APPLE_ABI
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000878 long long __ll = strtoll_l(__a, &__p2, __base, 0);
Sean Huntf3907e62011-07-15 05:40:33 +0000879#else
880 long long __ll = strtoll_l(__a, &__p2, __base, __cloc());
881#endif
Howard Hinnante7c8da62011-02-25 19:52:41 +0000882 int __current_errno = errno;
883 if (__current_errno == 0)
884 errno = __save_errno;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000885 if (__p2 != __a_end)
886 {
887 __err = ios_base::failbit;
888 return 0;
889 }
Howard Hinnante7c8da62011-02-25 19:52:41 +0000890 else if (__current_errno == ERANGE ||
891 __ll < numeric_limits<_Tp>::min() ||
892 numeric_limits<_Tp>::max() < __ll)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000893 {
894 __err = ios_base::failbit;
Howard Hinnante7c8da62011-02-25 19:52:41 +0000895 if (__ll > 0)
896 return numeric_limits<_Tp>::max();
897 else
898 return numeric_limits<_Tp>::min();
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000899 }
900 return static_cast<_Tp>(__ll);
901 }
902 __err = ios_base::failbit;
903 return 0;
904}
905
906template <class _Tp>
907_Tp
908__num_get_unsigned_integral(const char* __a, const char* __a_end,
909 ios_base::iostate& __err, int __base)
910{
911 if (__a != __a_end)
912 {
Howard Hinnante7c8da62011-02-25 19:52:41 +0000913 if (*__a == '-')
914 {
915 __err = ios_base::failbit;
916 return 0;
917 }
918 int __save_errno = errno;
919 errno = 0;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000920 char *__p2;
Sean Huntf3907e62011-07-15 05:40:33 +0000921#ifdef _LIBCXX_STABLE_APPLE_ABI
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000922 unsigned long long __ll = strtoull_l(__a, &__p2, __base, 0);
Sean Huntf3907e62011-07-15 05:40:33 +0000923#else
924 unsigned long long __ll = strtoull_l(__a, &__p2, __base, __cloc());
925#endif
Howard Hinnante7c8da62011-02-25 19:52:41 +0000926 int __current_errno = errno;
927 if (__current_errno == 0)
928 errno = __save_errno;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000929 if (__p2 != __a_end)
930 {
931 __err = ios_base::failbit;
932 return 0;
933 }
Howard Hinnante7c8da62011-02-25 19:52:41 +0000934 else if (__current_errno == ERANGE ||
935 numeric_limits<_Tp>::max() < __ll)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000936 {
937 __err = ios_base::failbit;
938 return numeric_limits<_Tp>::max();
939 }
940 return static_cast<_Tp>(__ll);
941 }
942 __err = ios_base::failbit;
943 return 0;
944}
945
946template <class _Tp>
947_Tp
948__num_get_float(const char* __a, const char* __a_end, ios_base::iostate& __err)
949{
950 if (__a != __a_end)
951 {
952 char *__p2;
Sean Huntf3907e62011-07-15 05:40:33 +0000953#ifdef _LIBCXX_STABLE_APPLE_ABI
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000954 long double __ld = strtold_l(__a, &__p2, 0);
Sean Huntf3907e62011-07-15 05:40:33 +0000955#else
956 long double __ld = strtold_l(__a, &__p2, __cloc());
957#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000958 if (__p2 != __a_end)
959 {
960 __err = ios_base::failbit;
961 return 0;
962 }
963 return static_cast<_Tp>(__ld);
964 }
965 __err = ios_base::failbit;
966 return 0;
967}
968
969template <class _CharT, class _InputIterator>
970_InputIterator
971num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
972 ios_base& __iob,
973 ios_base::iostate& __err,
974 bool& __v) const
975{
976 if ((__iob.flags() & ios_base::boolalpha) == 0)
977 {
978 long __lv = -1;
979 __b = do_get(__b, __e, __iob, __err, __lv);
980 switch (__lv)
981 {
982 case 0:
983 __v = false;
984 break;
985 case 1:
986 __v = true;
987 break;
988 default:
989 __v = true;
990 __err = ios_base::failbit;
991 break;
992 }
993 return __b;
994 }
995 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__iob.getloc());
996 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__iob.getloc());
997 typedef typename numpunct<_CharT>::string_type string_type;
998 const string_type __names[2] = {__np.truename(), __np.falsename()};
999 const string_type* __i = __scan_keyword(__b, __e, __names, __names+2,
1000 __ct, __err);
1001 __v = __i == __names;
1002 return __b;
1003}
1004
1005template <class _CharT, class _InputIterator>
1006_InputIterator
1007num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1008 ios_base& __iob,
1009 ios_base::iostate& __err,
1010 long& __v) const
1011{
1012 // Stage 1
1013 int __base = this->__get_base(__iob);
1014 // Stage 2
1015 char_type __atoms[26];
1016 char_type __thousands_sep;
1017 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
1018 char __a[__num_get_base::__num_get_buf_sz] = {0};
1019 char* __a_end = __a;
1020 unsigned __g[__num_get_base::__num_get_buf_sz];
1021 unsigned* __g_end = __g;
1022 unsigned __dc = 0;
1023 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001024 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001025 __thousands_sep, __grouping, __g, __g_end,
1026 __atoms))
1027 break;
1028 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
1029 *__g_end++ = __dc;
1030 // Stage 3
1031 __v = __num_get_signed_integral<long>(__a, __a_end, __err, __base);
1032 // Digit grouping checked
1033 __check_grouping(__grouping, __g, __g_end, __err);
1034 // EOF checked
1035 if (__b == __e)
1036 __err |= ios_base::eofbit;
1037 return __b;
1038}
1039
1040template <class _CharT, class _InputIterator>
1041_InputIterator
1042num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1043 ios_base& __iob,
1044 ios_base::iostate& __err,
1045 long long& __v) const
1046{
1047 // Stage 1
1048 int __base = this->__get_base(__iob);
1049 // Stage 2
1050 char_type __atoms[26];
1051 char_type __thousands_sep;
1052 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
1053 char __a[__num_get_base::__num_get_buf_sz] = {0};
1054 char* __a_end = __a;
1055 unsigned __g[__num_get_base::__num_get_buf_sz];
1056 unsigned* __g_end = __g;
1057 unsigned __dc = 0;
1058 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001059 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
1060 __thousands_sep, __grouping, __g, __g_end,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001061 __atoms))
1062 break;
1063 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
1064 *__g_end++ = __dc;
1065 // Stage 3
1066 __v = __num_get_signed_integral<long long>(__a, __a_end, __err, __base);
1067 // Digit grouping checked
1068 __check_grouping(__grouping, __g, __g_end, __err);
1069 // EOF checked
1070 if (__b == __e)
1071 __err |= ios_base::eofbit;
1072 return __b;
1073}
1074
1075template <class _CharT, class _InputIterator>
1076_InputIterator
1077num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1078 ios_base& __iob,
1079 ios_base::iostate& __err,
1080 unsigned short& __v) const
1081{
1082 // Stage 1
1083 int __base = this->__get_base(__iob);
1084 // Stage 2
1085 char_type __atoms[26];
1086 char_type __thousands_sep;
1087 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
1088 char __a[__num_get_base::__num_get_buf_sz] = {0};
1089 char* __a_end = __a;
1090 unsigned __g[__num_get_base::__num_get_buf_sz];
1091 unsigned* __g_end = __g;
1092 unsigned __dc = 0;
1093 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001094 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001095 __thousands_sep, __grouping, __g, __g_end,
1096 __atoms))
1097 break;
1098 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
1099 *__g_end++ = __dc;
1100 // Stage 3
1101 __v = __num_get_unsigned_integral<unsigned short>(__a, __a_end, __err, __base);
1102 // Digit grouping checked
1103 __check_grouping(__grouping, __g, __g_end, __err);
1104 // EOF checked
1105 if (__b == __e)
1106 __err |= ios_base::eofbit;
1107 return __b;
1108}
1109
1110template <class _CharT, class _InputIterator>
1111_InputIterator
1112num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1113 ios_base& __iob,
1114 ios_base::iostate& __err,
1115 unsigned int& __v) const
1116{
1117 // Stage 1
1118 int __base = this->__get_base(__iob);
1119 // Stage 2
1120 char_type __atoms[26];
1121 char_type __thousands_sep;
1122 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
1123 char __a[__num_get_base::__num_get_buf_sz] = {0};
1124 char* __a_end = __a;
1125 unsigned __g[__num_get_base::__num_get_buf_sz];
1126 unsigned* __g_end = __g;
1127 unsigned __dc = 0;
1128 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001129 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001130 __thousands_sep, __grouping, __g, __g_end,
1131 __atoms))
1132 break;
1133 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
1134 *__g_end++ = __dc;
1135 // Stage 3
1136 __v = __num_get_unsigned_integral<unsigned int>(__a, __a_end, __err, __base);
1137 // Digit grouping checked
1138 __check_grouping(__grouping, __g, __g_end, __err);
1139 // EOF checked
1140 if (__b == __e)
1141 __err |= ios_base::eofbit;
1142 return __b;
1143}
1144
1145template <class _CharT, class _InputIterator>
1146_InputIterator
1147num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1148 ios_base& __iob,
1149 ios_base::iostate& __err,
1150 unsigned long& __v) const
1151{
1152 // Stage 1
1153 int __base = this->__get_base(__iob);
1154 // Stage 2
1155 char_type __atoms[26];
1156 char_type __thousands_sep;
1157 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
1158 char __a[__num_get_base::__num_get_buf_sz] = {0};
1159 char* __a_end = __a;
1160 unsigned __g[__num_get_base::__num_get_buf_sz];
1161 unsigned* __g_end = __g;
1162 unsigned __dc = 0;
1163 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001164 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001165 __thousands_sep, __grouping, __g, __g_end,
1166 __atoms))
1167 break;
1168 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
1169 *__g_end++ = __dc;
1170 // Stage 3
1171 __v = __num_get_unsigned_integral<unsigned long>(__a, __a_end, __err, __base);
1172 // Digit grouping checked
1173 __check_grouping(__grouping, __g, __g_end, __err);
1174 // EOF checked
1175 if (__b == __e)
1176 __err |= ios_base::eofbit;
1177 return __b;
1178}
1179
1180template <class _CharT, class _InputIterator>
1181_InputIterator
1182num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1183 ios_base& __iob,
1184 ios_base::iostate& __err,
1185 unsigned long long& __v) const
1186{
1187 // Stage 1
1188 int __base = this->__get_base(__iob);
1189 // Stage 2
1190 char_type __atoms[26];
1191 char_type __thousands_sep;
1192 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
1193 char __a[__num_get_base::__num_get_buf_sz] = {0};
1194 char* __a_end = __a;
1195 unsigned __g[__num_get_base::__num_get_buf_sz];
1196 unsigned* __g_end = __g;
1197 unsigned __dc = 0;
1198 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001199 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001200 __thousands_sep, __grouping, __g, __g_end,
1201 __atoms))
1202 break;
1203 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
1204 *__g_end++ = __dc;
1205 // Stage 3
1206 __v = __num_get_unsigned_integral<unsigned long long>(__a, __a_end, __err, __base);
1207 // Digit grouping checked
1208 __check_grouping(__grouping, __g, __g_end, __err);
1209 // EOF checked
1210 if (__b == __e)
1211 __err |= ios_base::eofbit;
1212 return __b;
1213}
1214
1215template <class _CharT, class _InputIterator>
1216_InputIterator
1217num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1218 ios_base& __iob,
1219 ios_base::iostate& __err,
1220 float& __v) const
1221{
1222 // Stage 1, nothing to do
1223 // Stage 2
1224 char_type __atoms[32];
1225 char_type __decimal_point;
1226 char_type __thousands_sep;
Howard Hinnant324bb032010-08-22 00:02:43 +00001227 string __grouping = this->__stage2_float_prep(__iob, __atoms,
1228 __decimal_point,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001229 __thousands_sep);
1230 char __a[__num_get_base::__num_get_buf_sz] = {0};
1231 char* __a_end = __a;
1232 unsigned __g[__num_get_base::__num_get_buf_sz];
1233 unsigned* __g_end = __g;
1234 unsigned __dc = 0;
1235 bool __in_units = true;
1236 char __exp = 'E';
1237 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001238 if (this->__stage2_float_loop(*__b, __in_units, __exp, __a, __a_end,
1239 __decimal_point, __thousands_sep,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001240 __grouping, __g, __g_end,
1241 __dc, __atoms))
1242 break;
1243 if (__grouping.size() != 0 && __in_units && __g_end-__g < __num_get_base::__num_get_buf_sz)
1244 *__g_end++ = __dc;
1245 // Stage 3
1246 __v = __num_get_float<float>(__a, __a_end, __err);
1247 // Digit grouping checked
1248 __check_grouping(__grouping, __g, __g_end, __err);
1249 // EOF checked
1250 if (__b == __e)
1251 __err |= ios_base::eofbit;
1252 return __b;
1253}
1254
1255template <class _CharT, class _InputIterator>
1256_InputIterator
1257num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1258 ios_base& __iob,
1259 ios_base::iostate& __err,
1260 double& __v) const
1261{
1262 // Stage 1, nothing to do
1263 // Stage 2
1264 char_type __atoms[32];
1265 char_type __decimal_point;
1266 char_type __thousands_sep;
Howard Hinnant324bb032010-08-22 00:02:43 +00001267 string __grouping = this->__stage2_float_prep(__iob, __atoms,
1268 __decimal_point,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001269 __thousands_sep);
1270 char __a[__num_get_base::__num_get_buf_sz] = {0};
1271 char* __a_end = __a;
1272 unsigned __g[__num_get_base::__num_get_buf_sz];
1273 unsigned* __g_end = __g;
1274 unsigned __dc = 0;
1275 bool __in_units = true;
1276 char __exp = 'E';
1277 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001278 if (this->__stage2_float_loop(*__b, __in_units, __exp, __a, __a_end,
1279 __decimal_point, __thousands_sep,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001280 __grouping, __g, __g_end,
1281 __dc, __atoms))
1282 break;
1283 if (__grouping.size() != 0 && __in_units && __g_end-__g < __num_get_base::__num_get_buf_sz)
1284 *__g_end++ = __dc;
1285 // Stage 3
1286 __v = __num_get_float<double>(__a, __a_end, __err);
1287 // Digit grouping checked
1288 __check_grouping(__grouping, __g, __g_end, __err);
1289 // EOF checked
1290 if (__b == __e)
1291 __err |= ios_base::eofbit;
1292 return __b;
1293}
1294
1295template <class _CharT, class _InputIterator>
1296_InputIterator
1297num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1298 ios_base& __iob,
1299 ios_base::iostate& __err,
1300 long double& __v) const
1301{
1302 // Stage 1, nothing to do
1303 // Stage 2
1304 char_type __atoms[32];
1305 char_type __decimal_point;
1306 char_type __thousands_sep;
Howard Hinnant324bb032010-08-22 00:02:43 +00001307 string __grouping = this->__stage2_float_prep(__iob, __atoms,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001308 __decimal_point,
1309 __thousands_sep);
1310 char __a[__num_get_base::__num_get_buf_sz] = {0};
1311 char* __a_end = __a;
1312 unsigned __g[__num_get_base::__num_get_buf_sz];
1313 unsigned* __g_end = __g;
1314 unsigned __dc = 0;
1315 bool __in_units = true;
1316 char __exp = 'E';
1317 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001318 if (this->__stage2_float_loop(*__b, __in_units, __exp, __a, __a_end,
1319 __decimal_point, __thousands_sep,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001320 __grouping, __g, __g_end,
1321 __dc, __atoms))
1322 break;
1323 if (__grouping.size() != 0 && __in_units && __g_end-__g < __num_get_base::__num_get_buf_sz)
1324 *__g_end++ = __dc;
1325 // Stage 3
1326 __v = __num_get_float<long double>(__a, __a_end, __err);
1327 // Digit grouping checked
1328 __check_grouping(__grouping, __g, __g_end, __err);
1329 // EOF checked
1330 if (__b == __e)
1331 __err |= ios_base::eofbit;
1332 return __b;
1333}
1334
1335template <class _CharT, class _InputIterator>
1336_InputIterator
1337num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1338 ios_base& __iob,
1339 ios_base::iostate& __err,
1340 void*& __v) const
1341{
1342 // Stage 1
1343 int __base = 16;
1344 // Stage 2
1345 char_type __atoms[26];
1346 char_type __thousands_sep;
1347 string __grouping;
1348 use_facet<ctype<_CharT> >(__iob.getloc()).widen(__num_get_base::__src,
1349 __num_get_base::__src + 26, __atoms);
1350 char __a[__num_get_base::__num_get_buf_sz] = {0};
1351 char* __a_end = __a;
1352 unsigned __g[__num_get_base::__num_get_buf_sz];
1353 unsigned* __g_end = __g;
1354 unsigned __dc = 0;
1355 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001356 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
1357 __thousands_sep, __grouping,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001358 __g, __g_end, __atoms))
1359 break;
1360 // Stage 3
1361 __a[sizeof(__a)-1] = 0;
Sean Huntf3907e62011-07-15 05:40:33 +00001362#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantadff4892010-05-24 17:49:41 +00001363 if (__nolocale_sscanf(__a, "%p", &__v) != 1)
Sean Huntf3907e62011-07-15 05:40:33 +00001364#else
1365 if (__sscanf_l(__a, __cloc(), "%p", &__v) != 1)
1366#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001367 __err = ios_base::failbit;
1368 // EOF checked
1369 if (__b == __e)
1370 __err |= ios_base::eofbit;
1371 return __b;
1372}
1373
1374extern template class num_get<char>;
1375extern template class num_get<wchar_t>;
1376
1377struct __num_put_base
1378{
1379protected:
1380 static void __format_int(char* __fmt, const char* __len, bool __signd,
1381 ios_base::fmtflags __flags);
1382 static bool __format_float(char* __fmt, const char* __len,
1383 ios_base::fmtflags __flags);
1384 static char* __identify_padding(char* __nb, char* __ne,
1385 const ios_base& __iob);
1386};
1387
1388template <class _CharT>
1389struct __num_put
1390 : protected __num_put_base
1391{
1392 static void __widen_and_group_int(char* __nb, char* __np, char* __ne,
1393 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1394 const locale& __loc);
1395 static void __widen_and_group_float(char* __nb, char* __np, char* __ne,
1396 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1397 const locale& __loc);
1398};
1399
1400template <class _CharT>
1401void
1402__num_put<_CharT>::__widen_and_group_int(char* __nb, char* __np, char* __ne,
1403 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1404 const locale& __loc)
1405{
1406 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> > (__loc);
1407 const numpunct<_CharT>& __npt = use_facet<numpunct<_CharT> >(__loc);
1408 string __grouping = __npt.grouping();
1409 if (__grouping.empty())
1410 {
1411 __ct.widen(__nb, __ne, __ob);
1412 __oe = __ob + (__ne - __nb);
1413 }
1414 else
1415 {
1416 __oe = __ob;
1417 char* __nf = __nb;
1418 if (*__nf == '-' || *__nf == '+')
1419 *__oe++ = __ct.widen(*__nf++);
1420 if (__ne - __nf >= 2 && __nf[0] == '0' && (__nf[1] == 'x' ||
1421 __nf[1] == 'X'))
1422 {
1423 *__oe++ = __ct.widen(*__nf++);
1424 *__oe++ = __ct.widen(*__nf++);
1425 }
1426 reverse(__nf, __ne);
1427 _CharT __thousands_sep = __npt.thousands_sep();
1428 unsigned __dc = 0;
1429 unsigned __dg = 0;
1430 for (char* __p = __nf; __p < __ne; ++__p)
1431 {
1432 if (static_cast<unsigned>(__grouping[__dg]) > 0 &&
1433 __dc == static_cast<unsigned>(__grouping[__dg]))
1434 {
1435 *__oe++ = __thousands_sep;
1436 __dc = 0;
1437 if (__dg < __grouping.size()-1)
1438 ++__dg;
1439 }
1440 *__oe++ = __ct.widen(*__p);
1441 ++__dc;
1442 }
1443 reverse(__ob + (__nf - __nb), __oe);
1444 }
1445 if (__np == __ne)
1446 __op = __oe;
1447 else
1448 __op = __ob + (__np - __nb);
1449}
1450
1451template <class _CharT>
1452void
1453__num_put<_CharT>::__widen_and_group_float(char* __nb, char* __np, char* __ne,
1454 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1455 const locale& __loc)
1456{
1457 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> > (__loc);
1458 const numpunct<_CharT>& __npt = use_facet<numpunct<_CharT> >(__loc);
1459 string __grouping = __npt.grouping();
1460 __oe = __ob;
1461 char* __nf = __nb;
1462 if (*__nf == '-' || *__nf == '+')
1463 *__oe++ = __ct.widen(*__nf++);
1464 char* __ns;
1465 if (__ne - __nf >= 2 && __nf[0] == '0' && (__nf[1] == 'x' ||
1466 __nf[1] == 'X'))
1467 {
1468 *__oe++ = __ct.widen(*__nf++);
1469 *__oe++ = __ct.widen(*__nf++);
1470 for (__ns = __nf; __ns < __ne; ++__ns)
Sean Huntf3907e62011-07-15 05:40:33 +00001471#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantadff4892010-05-24 17:49:41 +00001472 if (!__nolocale_isxdigit(*__ns))
Sean Huntf3907e62011-07-15 05:40:33 +00001473#else
1474 if (!isxdigit_l(*__ns, __cloc()))
1475#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001476 break;
1477 }
1478 else
1479 {
1480 for (__ns = __nf; __ns < __ne; ++__ns)
Sean Huntf3907e62011-07-15 05:40:33 +00001481#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantadff4892010-05-24 17:49:41 +00001482 if (!__nolocale_isdigit(*__ns))
Sean Huntf3907e62011-07-15 05:40:33 +00001483#else
1484 if (!isdigit_l(*__ns, __cloc()))
1485#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001486 break;
1487 }
1488 if (__grouping.empty())
1489 {
1490 __ct.widen(__nf, __ns, __oe);
1491 __oe += __ns - __nf;
1492 }
1493 else
1494 {
1495 reverse(__nf, __ns);
1496 _CharT __thousands_sep = __npt.thousands_sep();
1497 unsigned __dc = 0;
1498 unsigned __dg = 0;
1499 for (char* __p = __nf; __p < __ns; ++__p)
1500 {
1501 if (__grouping[__dg] > 0 && __dc == static_cast<unsigned>(__grouping[__dg]))
1502 {
1503 *__oe++ = __thousands_sep;
1504 __dc = 0;
1505 if (__dg < __grouping.size()-1)
1506 ++__dg;
1507 }
1508 *__oe++ = __ct.widen(*__p);
1509 ++__dc;
1510 }
1511 reverse(__ob + (__nf - __nb), __oe);
1512 }
1513 for (__nf = __ns; __nf < __ne; ++__nf)
1514 {
1515 if (*__nf == '.')
1516 {
1517 *__oe++ = __npt.decimal_point();
1518 ++__nf;
1519 break;
1520 }
1521 else
1522 *__oe++ = __ct.widen(*__nf);
1523 }
1524 __ct.widen(__nf, __ne, __oe);
1525 __oe += __ne - __nf;
1526 if (__np == __ne)
1527 __op = __oe;
1528 else
1529 __op = __ob + (__np - __nb);
1530}
1531
1532extern template class __num_put<char>;
1533extern template class __num_put<wchar_t>;
1534
1535template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00001536class _LIBCPP_VISIBLE num_put
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001537 : public locale::facet,
1538 private __num_put<_CharT>
1539{
1540public:
1541 typedef _CharT char_type;
1542 typedef _OutputIterator iter_type;
1543
1544 _LIBCPP_ALWAYS_INLINE
1545 explicit num_put(size_t __refs = 0)
1546 : locale::facet(__refs) {}
1547
1548 _LIBCPP_ALWAYS_INLINE
1549 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1550 bool __v) const
1551 {
1552 return do_put(__s, __iob, __fl, __v);
1553 }
1554
1555 _LIBCPP_ALWAYS_INLINE
1556 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1557 long __v) const
1558 {
1559 return do_put(__s, __iob, __fl, __v);
1560 }
1561
1562 _LIBCPP_ALWAYS_INLINE
1563 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1564 long long __v) const
1565 {
1566 return do_put(__s, __iob, __fl, __v);
1567 }
1568
1569 _LIBCPP_ALWAYS_INLINE
1570 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1571 unsigned long __v) const
1572 {
1573 return do_put(__s, __iob, __fl, __v);
1574 }
1575
1576 _LIBCPP_ALWAYS_INLINE
1577 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1578 unsigned long long __v) const
1579 {
1580 return do_put(__s, __iob, __fl, __v);
1581 }
1582
1583 _LIBCPP_ALWAYS_INLINE
1584 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1585 double __v) const
1586 {
1587 return do_put(__s, __iob, __fl, __v);
1588 }
1589
1590 _LIBCPP_ALWAYS_INLINE
1591 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1592 long double __v) const
1593 {
1594 return do_put(__s, __iob, __fl, __v);
1595 }
1596
1597 _LIBCPP_ALWAYS_INLINE
1598 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1599 const void* __v) const
1600 {
1601 return do_put(__s, __iob, __fl, __v);
1602 }
1603
1604 static locale::id id;
1605
1606protected:
Howard Hinnant82894812010-09-22 16:48:34 +00001607 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001608 ~num_put() {}
1609
1610 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1611 bool __v) const;
1612 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1613 long __v) const;
1614 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1615 long long __v) const;
1616 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1617 unsigned long) const;
1618 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1619 unsigned long long) const;
1620 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1621 double __v) const;
1622 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1623 long double __v) const;
1624 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1625 const void* __v) const;
1626};
1627
1628template <class _CharT, class _OutputIterator>
1629locale::id
1630num_put<_CharT, _OutputIterator>::id;
1631
1632template <class _CharT, class _OutputIterator>
1633_LIBCPP_HIDDEN
1634_OutputIterator
1635__pad_and_output(_OutputIterator __s,
1636 const _CharT* __ob, const _CharT* __op, const _CharT* __oe,
1637 ios_base& __iob, _CharT __fl)
1638{
1639 streamsize __sz = __oe - __ob;
1640 streamsize __ns = __iob.width();
1641 if (__ns > __sz)
1642 __ns -= __sz;
1643 else
1644 __ns = 0;
1645 for (;__ob < __op; ++__ob, ++__s)
1646 *__s = *__ob;
1647 for (; __ns; --__ns, ++__s)
1648 *__s = __fl;
1649 for (; __ob < __oe; ++__ob, ++__s)
1650 *__s = *__ob;
1651 __iob.width(0);
1652 return __s;
1653}
1654
1655template <class _CharT, class _OutputIterator>
1656_OutputIterator
1657num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1658 char_type __fl, bool __v) const
1659{
1660 if ((__iob.flags() & ios_base::boolalpha) == 0)
1661 return do_put(__s, __iob, __fl, (unsigned long)__v);
1662 const numpunct<char_type>& __np = use_facet<numpunct<char_type> >(__iob.getloc());
1663 typedef typename numpunct<char_type>::string_type string_type;
1664 string_type __nm = __v ? __np.truename() : __np.falsename();
1665 for (typename string_type::iterator __i = __nm.begin(); __i != __nm.end(); ++__i, ++__s)
1666 *__s = *__i;
1667 return __s;
1668}
1669
1670template <class _CharT, class _OutputIterator>
1671_OutputIterator
1672num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1673 char_type __fl, long __v) const
1674{
1675 // Stage 1 - Get number in narrow char
1676 char __fmt[6] = {'%', 0};
1677 const char* __len = "l";
1678 this->__format_int(__fmt+1, __len, true, __iob.flags());
1679 const unsigned __nbuf = (numeric_limits<long>::digits / 3)
1680 + ((numeric_limits<long>::digits % 3) != 0)
1681 + 1;
1682 char __nar[__nbuf];
Sean Huntf3907e62011-07-15 05:40:33 +00001683#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantadff4892010-05-24 17:49:41 +00001684 int __nc = __nolocale_sprintf(__nar, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001685#else
1686 int __nc = __sprintf_l(__nar, __cloc(), __fmt, __v);
1687#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001688 char* __ne = __nar + __nc;
1689 char* __np = this->__identify_padding(__nar, __ne, __iob);
1690 // Stage 2 - Widen __nar while adding thousands separators
1691 char_type __o[2*(__nbuf-1) - 1];
1692 char_type* __op; // pad here
1693 char_type* __oe; // end of output
1694 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1695 // [__o, __oe) contains thousands_sep'd wide number
1696 // Stage 3 & 4
1697 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1698}
1699
1700template <class _CharT, class _OutputIterator>
1701_OutputIterator
1702num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1703 char_type __fl, long long __v) const
1704{
1705 // Stage 1 - Get number in narrow char
1706 char __fmt[8] = {'%', 0};
1707 const char* __len = "ll";
1708 this->__format_int(__fmt+1, __len, true, __iob.flags());
1709 const unsigned __nbuf = (numeric_limits<long long>::digits / 3)
1710 + ((numeric_limits<long long>::digits % 3) != 0)
1711 + 1;
1712 char __nar[__nbuf];
Sean Huntf3907e62011-07-15 05:40:33 +00001713#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantadff4892010-05-24 17:49:41 +00001714 int __nc = __nolocale_sprintf(__nar, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001715#else
1716 int __nc = __sprintf_l(__nar, __cloc(), __fmt, __v);
1717#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001718 char* __ne = __nar + __nc;
1719 char* __np = this->__identify_padding(__nar, __ne, __iob);
1720 // Stage 2 - Widen __nar while adding thousands separators
1721 char_type __o[2*(__nbuf-1) - 1];
1722 char_type* __op; // pad here
1723 char_type* __oe; // end of output
1724 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1725 // [__o, __oe) contains thousands_sep'd wide number
1726 // Stage 3 & 4
1727 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1728}
1729
1730template <class _CharT, class _OutputIterator>
1731_OutputIterator
1732num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1733 char_type __fl, unsigned long __v) const
1734{
1735 // Stage 1 - Get number in narrow char
1736 char __fmt[6] = {'%', 0};
1737 const char* __len = "l";
1738 this->__format_int(__fmt+1, __len, false, __iob.flags());
1739 const unsigned __nbuf = (numeric_limits<unsigned long>::digits / 3)
1740 + ((numeric_limits<unsigned long>::digits % 3) != 0)
1741 + 1;
1742 char __nar[__nbuf];
Sean Huntf3907e62011-07-15 05:40:33 +00001743#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantadff4892010-05-24 17:49:41 +00001744 int __nc = __nolocale_sprintf(__nar, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001745#else
1746 int __nc = __sprintf_l(__nar, __cloc(), __fmt, __v);
1747#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001748 char* __ne = __nar + __nc;
1749 char* __np = this->__identify_padding(__nar, __ne, __iob);
1750 // Stage 2 - Widen __nar while adding thousands separators
1751 char_type __o[2*(__nbuf-1) - 1];
1752 char_type* __op; // pad here
1753 char_type* __oe; // end of output
1754 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1755 // [__o, __oe) contains thousands_sep'd wide number
1756 // Stage 3 & 4
1757 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1758}
1759
1760template <class _CharT, class _OutputIterator>
1761_OutputIterator
1762num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1763 char_type __fl, unsigned long long __v) const
1764{
1765 // Stage 1 - Get number in narrow char
1766 char __fmt[8] = {'%', 0};
1767 const char* __len = "ll";
1768 this->__format_int(__fmt+1, __len, false, __iob.flags());
1769 const unsigned __nbuf = (numeric_limits<unsigned long long>::digits / 3)
1770 + ((numeric_limits<unsigned long long>::digits % 3) != 0)
1771 + 1;
1772 char __nar[__nbuf];
Sean Huntf3907e62011-07-15 05:40:33 +00001773#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantadff4892010-05-24 17:49:41 +00001774 int __nc = __nolocale_sprintf(__nar, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001775#else
1776 int __nc = __sprintf_l(__nar, __cloc(), __fmt, __v);
1777#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001778 char* __ne = __nar + __nc;
1779 char* __np = this->__identify_padding(__nar, __ne, __iob);
1780 // Stage 2 - Widen __nar while adding thousands separators
1781 char_type __o[2*(__nbuf-1) - 1];
1782 char_type* __op; // pad here
1783 char_type* __oe; // end of output
1784 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1785 // [__o, __oe) contains thousands_sep'd wide number
1786 // Stage 3 & 4
1787 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1788}
1789
1790template <class _CharT, class _OutputIterator>
1791_OutputIterator
1792num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1793 char_type __fl, double __v) const
1794{
1795 // Stage 1 - Get number in narrow char
1796 char __fmt[8] = {'%', 0};
1797 const char* __len = "";
1798 bool __specify_precision = this->__format_float(__fmt+1, __len, __iob.flags());
1799 const unsigned __nbuf = 30;
1800 char __nar[__nbuf];
1801 char* __nb = __nar;
1802 int __nc;
1803 if (__specify_precision)
Sean Huntf3907e62011-07-15 05:40:33 +00001804#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantadff4892010-05-24 17:49:41 +00001805 __nc = __nolocale_snprintf(__nb, __nbuf, __fmt,
1806 (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001807#else
1808 __nc = __snprintf_l(__nb, __nbuf, __cloc(), __fmt,
1809 (int)__iob.precision(), __v);
1810#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001811 else
Sean Huntf3907e62011-07-15 05:40:33 +00001812#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantadff4892010-05-24 17:49:41 +00001813 __nc = __nolocale_snprintf(__nb, __nbuf, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001814#else
1815 __nc = __snprintf_l(__nb, __nbuf, __cloc(), __fmt, __v);
1816#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001817 unique_ptr<char, void(*)(void*)> __nbh(0, free);
1818 if (__nc > static_cast<int>(__nbuf-1))
1819 {
1820 if (__specify_precision)
Sean Huntf3907e62011-07-15 05:40:33 +00001821#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantadff4892010-05-24 17:49:41 +00001822 __nc = __nolocale_asprintf(&__nb, __fmt, (int)__iob.precision(),
1823 __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001824#else
1825 __nc = __asprintf_l(&__nb, __cloc(), __fmt,
1826 (int)__iob.precision());
1827#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001828 else
Sean Huntf3907e62011-07-15 05:40:33 +00001829#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantadff4892010-05-24 17:49:41 +00001830 __nc = __nolocale_asprintf(&__nb, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001831#else
1832 __nc = __asprintf_l(&__nb, __cloc(), __fmt, (int)__iob.precision());
1833#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001834 if (__nb == 0)
1835 __throw_bad_alloc();
1836 __nbh.reset(__nb);
1837 }
1838 char* __ne = __nb + __nc;
1839 char* __np = this->__identify_padding(__nb, __ne, __iob);
1840 // Stage 2 - Widen __nar while adding thousands separators
1841 char_type __o[2*(__nbuf-1) - 1];
1842 char_type* __ob = __o;
1843 unique_ptr<char_type, void(*)(void*)> __obh(0, free);
1844 if (__nb != __nar)
1845 {
1846 __ob = (char_type*)malloc((2*__nc)*sizeof(char_type));
1847 if (__ob == 0)
1848 __throw_bad_alloc();
1849 __obh.reset(__ob);
1850 }
1851 char_type* __op; // pad here
1852 char_type* __oe; // end of output
1853 this->__widen_and_group_float(__nb, __np, __ne, __ob, __op, __oe, __iob.getloc());
1854 // [__o, __oe) contains thousands_sep'd wide number
1855 // Stage 3 & 4
1856 __s = __pad_and_output(__s, __ob, __op, __oe, __iob, __fl);
1857 return __s;
1858}
1859
1860template <class _CharT, class _OutputIterator>
1861_OutputIterator
1862num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1863 char_type __fl, long double __v) const
1864{
1865 // Stage 1 - Get number in narrow char
1866 char __fmt[8] = {'%', 0};
1867 const char* __len = "L";
1868 bool __specify_precision = this->__format_float(__fmt+1, __len, __iob.flags());
1869 const unsigned __nbuf = 30;
1870 char __nar[__nbuf];
1871 char* __nb = __nar;
1872 int __nc;
1873 if (__specify_precision)
Sean Huntf3907e62011-07-15 05:40:33 +00001874#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantadff4892010-05-24 17:49:41 +00001875 __nc = __nolocale_snprintf(__nb, __nbuf, __fmt,
1876 (int)__iob.precision(), __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001877#else
1878 __nc = __snprintf_l(__nb, __nbuf, __cloc(), __fmt,
1879 (int)__iob.precision(), __v);
1880#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001881 else
Sean Huntf3907e62011-07-15 05:40:33 +00001882#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantadff4892010-05-24 17:49:41 +00001883 __nc = __nolocale_snprintf(__nb, __nbuf, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001884#else
1885 __nc = __snprintf_l(__nb, __nbuf, __cloc(), __fmt, __v);
1886#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001887 unique_ptr<char, void(*)(void*)> __nbh(0, free);
1888 if (__nc > static_cast<int>(__nbuf-1))
1889 {
1890 if (__specify_precision)
Sean Huntf3907e62011-07-15 05:40:33 +00001891#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantadff4892010-05-24 17:49:41 +00001892 __nc = __nolocale_asprintf(&__nb, __fmt, (int)__iob.precision(),
1893 __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001894#else
1895 __nc = __asprintf_l(&__nb, __cloc(), __fmt,
1896 (int)__iob.precision());
1897#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001898 else
Sean Huntf3907e62011-07-15 05:40:33 +00001899#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantadff4892010-05-24 17:49:41 +00001900 __nc = __nolocale_asprintf(&__nb, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001901#else
1902 __nc = __asprintf_l(&__nb, __cloc(), __fmt, (int)__iob.precision());
1903#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001904 if (__nb == 0)
1905 __throw_bad_alloc();
1906 __nbh.reset(__nb);
1907 }
1908 char* __ne = __nb + __nc;
1909 char* __np = this->__identify_padding(__nb, __ne, __iob);
1910 // Stage 2 - Widen __nar while adding thousands separators
1911 char_type __o[2*(__nbuf-1) - 1];
1912 char_type* __ob = __o;
1913 unique_ptr<char_type, void(*)(void*)> __obh(0, free);
1914 if (__nb != __nar)
1915 {
1916 __ob = (char_type*)malloc((2*__nc)*sizeof(char_type));
1917 if (__ob == 0)
1918 __throw_bad_alloc();
1919 __obh.reset(__ob);
1920 }
1921 char_type* __op; // pad here
1922 char_type* __oe; // end of output
1923 this->__widen_and_group_float(__nb, __np, __ne, __ob, __op, __oe, __iob.getloc());
1924 // [__o, __oe) contains thousands_sep'd wide number
1925 // Stage 3 & 4
1926 __s = __pad_and_output(__s, __ob, __op, __oe, __iob, __fl);
1927 return __s;
1928}
1929
1930template <class _CharT, class _OutputIterator>
1931_OutputIterator
1932num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1933 char_type __fl, const void* __v) const
1934{
1935 // Stage 1 - Get pointer in narrow char
1936 char __fmt[6] = "%p";
1937 const unsigned __nbuf = 20;
1938 char __nar[__nbuf];
Sean Huntf3907e62011-07-15 05:40:33 +00001939#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantadff4892010-05-24 17:49:41 +00001940 int __nc = __nolocale_sprintf(__nar, __fmt, __v);
Sean Huntf3907e62011-07-15 05:40:33 +00001941#else
1942 int __nc = __sprintf_l(__nar, __cloc(), __fmt, __v);
1943#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001944 char* __ne = __nar + __nc;
1945 char* __np = this->__identify_padding(__nar, __ne, __iob);
1946 // Stage 2 - Widen __nar
1947 char_type __o[2*(__nbuf-1) - 1];
1948 char_type* __op; // pad here
1949 char_type* __oe; // end of output
1950 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
1951 __ct.widen(__nar, __ne, __o);
1952 __oe = __o + (__ne - __nar);
1953 if (__np == __ne)
1954 __op = __oe;
1955 else
1956 __op = __o + (__np - __nar);
1957 // [__o, __oe) contains wide number
1958 // Stage 3 & 4
1959 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1960}
1961
1962extern template class num_put<char>;
1963extern template class num_put<wchar_t>;
1964
1965template <class _CharT, class _InputIterator>
1966_LIBCPP_HIDDEN
1967int
1968__get_up_to_n_digits(_InputIterator& __b, _InputIterator __e,
1969 ios_base::iostate& __err, const ctype<_CharT>& __ct, int __n)
1970{
1971 // Precondition: __n >= 1
1972 if (__b == __e)
1973 {
1974 __err |= ios_base::eofbit | ios_base::failbit;
1975 return 0;
1976 }
1977 // get first digit
1978 _CharT __c = *__b;
1979 if (!__ct.is(ctype_base::digit, __c))
1980 {
1981 __err |= ios_base::failbit;
1982 return 0;
1983 }
1984 int __r = __ct.narrow(__c, 0) - '0';
1985 for (++__b, --__n; __b != __e && __n > 0; ++__b, --__n)
1986 {
1987 // get next digit
1988 __c = *__b;
1989 if (!__ct.is(ctype_base::digit, __c))
1990 return __r;
1991 __r = __r * 10 + __ct.narrow(__c, 0) - '0';
1992 }
1993 if (__b == __e)
1994 __err |= ios_base::eofbit;
1995 return __r;
1996}
1997
Howard Hinnant82894812010-09-22 16:48:34 +00001998class _LIBCPP_VISIBLE time_base
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001999{
2000public:
2001 enum dateorder {no_order, dmy, mdy, ymd, ydm};
2002};
2003
2004template <class _CharT>
Howard Hinnant2d72b1e2010-12-17 14:46:43 +00002005class __time_get_c_storage // purposefully not decorated
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002006{
2007protected:
2008 typedef basic_string<_CharT> string_type;
2009
2010 virtual const string_type* __weeks() const;
2011 virtual const string_type* __months() const;
2012 virtual const string_type* __am_pm() const;
2013 virtual const string_type& __c() const;
2014 virtual const string_type& __r() const;
2015 virtual const string_type& __x() const;
2016 virtual const string_type& __X() const;
2017};
2018
2019template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00002020class _LIBCPP_VISIBLE time_get
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002021 : public locale::facet,
2022 public time_base,
2023 private __time_get_c_storage<_CharT>
2024{
2025public:
2026 typedef _CharT char_type;
2027 typedef _InputIterator iter_type;
2028 typedef time_base::dateorder dateorder;
2029 typedef basic_string<char_type> string_type;
2030
2031 _LIBCPP_ALWAYS_INLINE
2032 explicit time_get(size_t __refs = 0)
2033 : locale::facet(__refs) {}
2034
2035 _LIBCPP_ALWAYS_INLINE
2036 dateorder date_order() const
2037 {
2038 return this->do_date_order();
2039 }
2040
2041 _LIBCPP_ALWAYS_INLINE
2042 iter_type get_time(iter_type __b, iter_type __e, ios_base& __iob,
2043 ios_base::iostate& __err, tm* __tm) const
2044 {
2045 return do_get_time(__b, __e, __iob, __err, __tm);
2046 }
2047
2048 _LIBCPP_ALWAYS_INLINE
2049 iter_type get_date(iter_type __b, iter_type __e, ios_base& __iob,
2050 ios_base::iostate& __err, tm* __tm) const
2051 {
2052 return do_get_date(__b, __e, __iob, __err, __tm);
2053 }
2054
2055 _LIBCPP_ALWAYS_INLINE
2056 iter_type get_weekday(iter_type __b, iter_type __e, ios_base& __iob,
2057 ios_base::iostate& __err, tm* __tm) const
2058 {
2059 return do_get_weekday(__b, __e, __iob, __err, __tm);
2060 }
2061
2062 _LIBCPP_ALWAYS_INLINE
2063 iter_type get_monthname(iter_type __b, iter_type __e, ios_base& __iob,
2064 ios_base::iostate& __err, tm* __tm) const
2065 {
2066 return do_get_monthname(__b, __e, __iob, __err, __tm);
2067 }
2068
2069 _LIBCPP_ALWAYS_INLINE
2070 iter_type get_year(iter_type __b, iter_type __e, ios_base& __iob,
2071 ios_base::iostate& __err, tm* __tm) const
2072 {
2073 return do_get_year(__b, __e, __iob, __err, __tm);
2074 }
2075
2076 _LIBCPP_ALWAYS_INLINE
2077 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
2078 ios_base::iostate& __err, tm *__tm,
2079 char __fmt, char __mod = 0) const
2080 {
2081 return do_get(__b, __e, __iob, __err, __tm, __fmt, __mod);
2082 }
2083
2084 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
2085 ios_base::iostate& __err, tm* __tm,
2086 const char_type* __fmtb, const char_type* __fmte) const;
2087
2088 static locale::id id;
2089
2090protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002091 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002092 ~time_get() {}
2093
2094 virtual dateorder do_date_order() const;
2095 virtual iter_type do_get_time(iter_type __b, iter_type __e, ios_base& __iob,
2096 ios_base::iostate& __err, tm* __tm) const;
2097 virtual iter_type do_get_date(iter_type __b, iter_type __e, ios_base& __iob,
2098 ios_base::iostate& __err, tm* __tm) const;
2099 virtual iter_type do_get_weekday(iter_type __b, iter_type __e, ios_base& __iob,
2100 ios_base::iostate& __err, tm* __tm) const;
2101 virtual iter_type do_get_monthname(iter_type __b, iter_type __e, ios_base& __iob,
2102 ios_base::iostate& __err, tm* __tm) const;
2103 virtual iter_type do_get_year(iter_type __b, iter_type __e, ios_base& __iob,
2104 ios_base::iostate& __err, tm* __tm) const;
2105 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
2106 ios_base::iostate& __err, tm* __tm,
2107 char __fmt, char __mod) const;
2108private:
2109 void __get_white_space(iter_type& __b, iter_type __e,
2110 ios_base::iostate& __err, const ctype<char_type>& __ct) const;
2111 void __get_percent(iter_type& __b, iter_type __e, ios_base::iostate& __err,
2112 const ctype<char_type>& __ct) const;
2113
2114 void __get_weekdayname(int& __m,
2115 iter_type& __b, iter_type __e,
2116 ios_base::iostate& __err,
2117 const ctype<char_type>& __ct) const;
2118 void __get_monthname(int& __m,
2119 iter_type& __b, iter_type __e,
2120 ios_base::iostate& __err,
2121 const ctype<char_type>& __ct) const;
2122 void __get_day(int& __d,
2123 iter_type& __b, iter_type __e,
2124 ios_base::iostate& __err,
2125 const ctype<char_type>& __ct) const;
2126 void __get_month(int& __m,
2127 iter_type& __b, iter_type __e,
2128 ios_base::iostate& __err,
2129 const ctype<char_type>& __ct) const;
2130 void __get_year(int& __y,
2131 iter_type& __b, iter_type __e,
2132 ios_base::iostate& __err,
2133 const ctype<char_type>& __ct) const;
2134 void __get_year4(int& __y,
2135 iter_type& __b, iter_type __e,
2136 ios_base::iostate& __err,
2137 const ctype<char_type>& __ct) const;
2138 void __get_hour(int& __d,
2139 iter_type& __b, iter_type __e,
2140 ios_base::iostate& __err,
2141 const ctype<char_type>& __ct) const;
2142 void __get_12_hour(int& __h,
2143 iter_type& __b, iter_type __e,
2144 ios_base::iostate& __err,
2145 const ctype<char_type>& __ct) const;
2146 void __get_am_pm(int& __h,
2147 iter_type& __b, iter_type __e,
2148 ios_base::iostate& __err,
2149 const ctype<char_type>& __ct) const;
2150 void __get_minute(int& __m,
2151 iter_type& __b, iter_type __e,
2152 ios_base::iostate& __err,
2153 const ctype<char_type>& __ct) const;
2154 void __get_second(int& __s,
2155 iter_type& __b, iter_type __e,
2156 ios_base::iostate& __err,
2157 const ctype<char_type>& __ct) const;
2158 void __get_weekday(int& __w,
2159 iter_type& __b, iter_type __e,
2160 ios_base::iostate& __err,
2161 const ctype<char_type>& __ct) const;
2162 void __get_day_year_num(int& __w,
2163 iter_type& __b, iter_type __e,
2164 ios_base::iostate& __err,
2165 const ctype<char_type>& __ct) const;
2166};
2167
2168template <class _CharT, class _InputIterator>
2169locale::id
2170time_get<_CharT, _InputIterator>::id;
2171
2172// time_get primatives
2173
2174template <class _CharT, class _InputIterator>
2175void
2176time_get<_CharT, _InputIterator>::__get_weekdayname(int& __w,
2177 iter_type& __b, iter_type __e,
2178 ios_base::iostate& __err,
2179 const ctype<char_type>& __ct) const
2180{
2181 // Note: ignoring case comes from the POSIX strptime spec
2182 const string_type* __wk = this->__weeks();
2183 int __i = __scan_keyword(__b, __e, __wk, __wk+14, __ct, __err, false) - __wk;
2184 if (__i < 14)
2185 __w = __i % 7;
2186}
2187
2188template <class _CharT, class _InputIterator>
2189void
2190time_get<_CharT, _InputIterator>::__get_monthname(int& __m,
2191 iter_type& __b, iter_type __e,
2192 ios_base::iostate& __err,
2193 const ctype<char_type>& __ct) const
2194{
2195 // Note: ignoring case comes from the POSIX strptime spec
2196 const string_type* __month = this->__months();
2197 int __i = __scan_keyword(__b, __e, __month, __month+24, __ct, __err, false) - __month;
2198 if (__i < 24)
2199 __m = __i % 12;
2200}
2201
2202template <class _CharT, class _InputIterator>
2203void
2204time_get<_CharT, _InputIterator>::__get_day(int& __d,
2205 iter_type& __b, iter_type __e,
2206 ios_base::iostate& __err,
2207 const ctype<char_type>& __ct) const
2208{
2209 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2210 if (!(__err & ios_base::failbit) && 1 <= __t && __t <= 31)
2211 __d = __t;
2212 else
2213 __err |= ios_base::failbit;
2214}
2215
2216template <class _CharT, class _InputIterator>
2217void
2218time_get<_CharT, _InputIterator>::__get_month(int& __m,
2219 iter_type& __b, iter_type __e,
2220 ios_base::iostate& __err,
2221 const ctype<char_type>& __ct) const
2222{
2223 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2) - 1;
2224 if (!(__err & ios_base::failbit) && __t <= 11)
2225 __m = __t;
2226 else
2227 __err |= ios_base::failbit;
2228}
2229
2230template <class _CharT, class _InputIterator>
2231void
2232time_get<_CharT, _InputIterator>::__get_year(int& __y,
2233 iter_type& __b, iter_type __e,
2234 ios_base::iostate& __err,
2235 const ctype<char_type>& __ct) const
2236{
2237 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 4);
2238 if (!(__err & ios_base::failbit))
2239 {
2240 if (__t < 69)
2241 __t += 2000;
2242 else if (69 <= __t && __t <= 99)
2243 __t += 1900;
2244 __y = __t - 1900;
2245 }
2246}
2247
2248template <class _CharT, class _InputIterator>
2249void
2250time_get<_CharT, _InputIterator>::__get_year4(int& __y,
2251 iter_type& __b, iter_type __e,
2252 ios_base::iostate& __err,
2253 const ctype<char_type>& __ct) const
2254{
2255 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 4);
2256 if (!(__err & ios_base::failbit))
2257 __y = __t - 1900;
2258}
2259
2260template <class _CharT, class _InputIterator>
2261void
2262time_get<_CharT, _InputIterator>::__get_hour(int& __h,
2263 iter_type& __b, iter_type __e,
2264 ios_base::iostate& __err,
2265 const ctype<char_type>& __ct) const
2266{
2267 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2268 if (!(__err & ios_base::failbit) && __t <= 23)
2269 __h = __t;
2270 else
2271 __err |= ios_base::failbit;
2272}
2273
2274template <class _CharT, class _InputIterator>
2275void
2276time_get<_CharT, _InputIterator>::__get_12_hour(int& __h,
2277 iter_type& __b, iter_type __e,
2278 ios_base::iostate& __err,
2279 const ctype<char_type>& __ct) const
2280{
2281 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2282 if (!(__err & ios_base::failbit) && 1 <= __t && __t <= 12)
2283 __h = __t;
2284 else
2285 __err |= ios_base::failbit;
2286}
2287
2288template <class _CharT, class _InputIterator>
2289void
2290time_get<_CharT, _InputIterator>::__get_minute(int& __m,
2291 iter_type& __b, iter_type __e,
2292 ios_base::iostate& __err,
2293 const ctype<char_type>& __ct) const
2294{
2295 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2296 if (!(__err & ios_base::failbit) && __t <= 59)
2297 __m = __t;
2298 else
2299 __err |= ios_base::failbit;
2300}
2301
2302template <class _CharT, class _InputIterator>
2303void
2304time_get<_CharT, _InputIterator>::__get_second(int& __s,
2305 iter_type& __b, iter_type __e,
2306 ios_base::iostate& __err,
2307 const ctype<char_type>& __ct) const
2308{
2309 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2310 if (!(__err & ios_base::failbit) && __t <= 60)
2311 __s = __t;
2312 else
2313 __err |= ios_base::failbit;
2314}
2315
2316template <class _CharT, class _InputIterator>
2317void
2318time_get<_CharT, _InputIterator>::__get_weekday(int& __w,
2319 iter_type& __b, iter_type __e,
2320 ios_base::iostate& __err,
2321 const ctype<char_type>& __ct) const
2322{
2323 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 1);
2324 if (!(__err & ios_base::failbit) && __t <= 6)
2325 __w = __t;
2326 else
2327 __err |= ios_base::failbit;
2328}
2329
2330template <class _CharT, class _InputIterator>
2331void
2332time_get<_CharT, _InputIterator>::__get_day_year_num(int& __d,
2333 iter_type& __b, iter_type __e,
2334 ios_base::iostate& __err,
2335 const ctype<char_type>& __ct) const
2336{
2337 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 3);
2338 if (!(__err & ios_base::failbit) && __t <= 365)
2339 __d = __t;
2340 else
2341 __err |= ios_base::failbit;
2342}
2343
2344template <class _CharT, class _InputIterator>
2345void
2346time_get<_CharT, _InputIterator>::__get_white_space(iter_type& __b, iter_type __e,
2347 ios_base::iostate& __err,
2348 const ctype<char_type>& __ct) const
2349{
2350 for (; __b != __e && __ct.is(ctype_base::space, *__b); ++__b)
2351 ;
2352 if (__b == __e)
2353 __err |= ios_base::eofbit;
2354}
2355
2356template <class _CharT, class _InputIterator>
2357void
2358time_get<_CharT, _InputIterator>::__get_am_pm(int& __h,
2359 iter_type& __b, iter_type __e,
2360 ios_base::iostate& __err,
2361 const ctype<char_type>& __ct) const
2362{
2363 const string_type* __ap = this->__am_pm();
2364 if (__ap[0].size() + __ap[1].size() == 0)
2365 {
2366 __err |= ios_base::failbit;
2367 return;
2368 }
2369 int __i = __scan_keyword(__b, __e, __ap, __ap+2, __ct, __err, false) - __ap;
2370 if (__i == 0 && __h == 12)
2371 __h = 0;
2372 else if (__i == 1 && __h < 12)
2373 __h += 12;
2374}
2375
2376template <class _CharT, class _InputIterator>
2377void
2378time_get<_CharT, _InputIterator>::__get_percent(iter_type& __b, iter_type __e,
2379 ios_base::iostate& __err,
2380 const ctype<char_type>& __ct) const
2381{
2382 if (__b == __e)
2383 {
2384 __err |= ios_base::eofbit | ios_base::failbit;
2385 return;
2386 }
2387 if (__ct.narrow(*__b, 0) != '%')
2388 __err |= ios_base::failbit;
2389 else if(++__b == __e)
2390 __err |= ios_base::eofbit;
2391}
2392
2393// time_get end primatives
2394
2395template <class _CharT, class _InputIterator>
2396_InputIterator
2397time_get<_CharT, _InputIterator>::get(iter_type __b, iter_type __e,
2398 ios_base& __iob,
2399 ios_base::iostate& __err, tm* __tm,
2400 const char_type* __fmtb, const char_type* __fmte) const
2401{
2402 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2403 __err = ios_base::goodbit;
2404 while (__fmtb != __fmte && __err == ios_base::goodbit)
2405 {
2406 if (__b == __e)
2407 {
2408 __err = ios_base::failbit;
2409 break;
2410 }
2411 if (__ct.narrow(*__fmtb, 0) == '%')
2412 {
2413 if (++__fmtb == __fmte)
2414 {
2415 __err = ios_base::failbit;
2416 break;
2417 }
2418 char __cmd = __ct.narrow(*__fmtb, 0);
2419 char __opt = '\0';
2420 if (__cmd == 'E' || __cmd == '0')
2421 {
2422 if (++__fmtb == __fmte)
2423 {
2424 __err = ios_base::failbit;
2425 break;
2426 }
2427 __opt = __cmd;
2428 __cmd = __ct.narrow(*__fmtb, 0);
2429 }
2430 __b = do_get(__b, __e, __iob, __err, __tm, __cmd, __opt);
2431 ++__fmtb;
2432 }
2433 else if (__ct.is(ctype_base::space, *__fmtb))
2434 {
2435 for (++__fmtb; __fmtb != __fmte && __ct.is(ctype_base::space, *__fmtb); ++__fmtb)
2436 ;
2437 for ( ; __b != __e && __ct.is(ctype_base::space, *__b); ++__b)
2438 ;
2439 }
2440 else if (__ct.toupper(*__b) == __ct.toupper(*__fmtb))
2441 {
2442 ++__b;
2443 ++__fmtb;
2444 }
2445 else
2446 __err = ios_base::failbit;
2447 }
2448 if (__b == __e)
2449 __err |= ios_base::eofbit;
2450 return __b;
2451}
2452
2453template <class _CharT, class _InputIterator>
2454typename time_get<_CharT, _InputIterator>::dateorder
2455time_get<_CharT, _InputIterator>::do_date_order() const
2456{
2457 return mdy;
2458}
2459
2460template <class _CharT, class _InputIterator>
2461_InputIterator
2462time_get<_CharT, _InputIterator>::do_get_time(iter_type __b, iter_type __e,
2463 ios_base& __iob,
2464 ios_base::iostate& __err,
2465 tm* __tm) const
2466{
2467 const char_type __fmt[] = {'%', 'H', ':', '%', 'M', ':', '%', 'S'};
2468 return get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2469}
2470
2471template <class _CharT, class _InputIterator>
2472_InputIterator
2473time_get<_CharT, _InputIterator>::do_get_date(iter_type __b, iter_type __e,
2474 ios_base& __iob,
2475 ios_base::iostate& __err,
2476 tm* __tm) const
2477{
2478 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2479 const string_type& __fmt = this->__x();
2480 return get(__b, __e, __iob, __err, __tm, __fmt.data(), __fmt.data() + __fmt.size());
2481}
2482
2483template <class _CharT, class _InputIterator>
2484_InputIterator
2485time_get<_CharT, _InputIterator>::do_get_weekday(iter_type __b, iter_type __e,
2486 ios_base& __iob,
2487 ios_base::iostate& __err,
2488 tm* __tm) const
2489{
2490 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2491 __get_weekdayname(__tm->tm_wday, __b, __e, __err, __ct);
2492 return __b;
2493}
2494
2495template <class _CharT, class _InputIterator>
2496_InputIterator
2497time_get<_CharT, _InputIterator>::do_get_monthname(iter_type __b, iter_type __e,
2498 ios_base& __iob,
2499 ios_base::iostate& __err,
2500 tm* __tm) const
2501{
2502 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2503 __get_monthname(__tm->tm_mon, __b, __e, __err, __ct);
2504 return __b;
2505}
2506
2507template <class _CharT, class _InputIterator>
2508_InputIterator
2509time_get<_CharT, _InputIterator>::do_get_year(iter_type __b, iter_type __e,
2510 ios_base& __iob,
2511 ios_base::iostate& __err,
2512 tm* __tm) const
2513{
2514 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2515 __get_year(__tm->tm_year, __b, __e, __err, __ct);
2516 return __b;
2517}
2518
2519template <class _CharT, class _InputIterator>
2520_InputIterator
2521time_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
2522 ios_base& __iob,
2523 ios_base::iostate& __err, tm* __tm,
2524 char __fmt, char) const
2525{
2526 __err = ios_base::goodbit;
2527 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2528 switch (__fmt)
2529 {
2530 case 'a':
2531 case 'A':
2532 __get_weekdayname(__tm->tm_wday, __b, __e, __err, __ct);
2533 break;
2534 case 'b':
2535 case 'B':
2536 case 'h':
2537 __get_monthname(__tm->tm_mon, __b, __e, __err, __ct);
2538 break;
2539 case 'c':
2540 {
2541 const string_type& __fmt = this->__c();
2542 __b = get(__b, __e, __iob, __err, __tm, __fmt.data(), __fmt.data() + __fmt.size());
2543 }
2544 break;
2545 case 'd':
2546 case 'e':
2547 __get_day(__tm->tm_mday, __b, __e, __err, __ct);
2548 break;
2549 case 'D':
2550 {
2551 const char_type __fmt[] = {'%', 'm', '/', '%', 'd', '/', '%', 'y'};
2552 __b = get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2553 }
2554 break;
Howard Hinnant506b3642011-04-10 17:54:14 +00002555 case 'F':
2556 {
2557 const char_type __fmt[] = {'%', 'Y', '-', '%', 'm', '-', '%', 'd'};
2558 __b = get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2559 }
2560 break;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002561 case 'H':
2562 __get_hour(__tm->tm_hour, __b, __e, __err, __ct);
2563 break;
2564 case 'I':
2565 __get_12_hour(__tm->tm_hour, __b, __e, __err, __ct);
2566 break;
2567 case 'j':
2568 __get_day_year_num(__tm->tm_yday, __b, __e, __err, __ct);
2569 break;
2570 case 'm':
2571 __get_month(__tm->tm_mon, __b, __e, __err, __ct);
2572 break;
2573 case 'M':
2574 __get_minute(__tm->tm_min, __b, __e, __err, __ct);
2575 break;
2576 case 'n':
2577 case 't':
2578 __get_white_space(__b, __e, __err, __ct);
2579 break;
2580 case 'p':
2581 __get_am_pm(__tm->tm_hour, __b, __e, __err, __ct);
2582 break;
2583 case 'r':
2584 {
2585 const char_type __fmt[] = {'%', 'I', ':', '%', 'M', ':', '%', 'S', ' ', '%', 'p'};
2586 __b = get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2587 }
2588 break;
2589 case 'R':
2590 {
2591 const char_type __fmt[] = {'%', 'H', ':', '%', 'M'};
2592 __b = get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2593 }
2594 break;
2595 case 'S':
2596 __get_second(__tm->tm_sec, __b, __e, __err, __ct);
2597 break;
2598 case 'T':
2599 {
2600 const char_type __fmt[] = {'%', 'H', ':', '%', 'M', ':', '%', 'S'};
2601 __b = get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2602 }
2603 break;
2604 case 'w':
2605 __get_weekday(__tm->tm_wday, __b, __e, __err, __ct);
2606 break;
2607 case 'x':
2608 return do_get_date(__b, __e, __iob, __err, __tm);
2609 case 'X':
2610 {
2611 const string_type& __fmt = this->__X();
2612 __b = get(__b, __e, __iob, __err, __tm, __fmt.data(), __fmt.data() + __fmt.size());
2613 }
2614 break;
2615 case 'y':
2616 __get_year(__tm->tm_year, __b, __e, __err, __ct);
2617 break;
2618 case 'Y':
2619 __get_year4(__tm->tm_year, __b, __e, __err, __ct);
2620 break;
2621 case '%':
2622 __get_percent(__b, __e, __err, __ct);
2623 break;
2624 default:
2625 __err |= ios_base::failbit;
2626 }
2627 return __b;
2628}
2629
2630extern template class time_get<char>;
2631extern template class time_get<wchar_t>;
2632
2633class __time_get
2634{
2635protected:
2636 locale_t __loc_;
2637
2638 __time_get(const char* __nm);
2639 __time_get(const string& __nm);
2640 ~__time_get();
2641};
2642
2643template <class _CharT>
2644class __time_get_storage
2645 : public __time_get
2646{
2647protected:
2648 typedef basic_string<_CharT> string_type;
2649
2650 string_type __weeks_[14];
2651 string_type __months_[24];
2652 string_type __am_pm_[2];
2653 string_type __c_;
2654 string_type __r_;
2655 string_type __x_;
2656 string_type __X_;
2657
2658 explicit __time_get_storage(const char* __nm);
2659 explicit __time_get_storage(const string& __nm);
2660
2661 _LIBCPP_ALWAYS_INLINE ~__time_get_storage() {}
2662
2663 time_base::dateorder __do_date_order() const;
2664
2665private:
2666 void init(const ctype<_CharT>&);
2667 string_type __analyze(char __fmt, const ctype<_CharT>&);
2668};
2669
2670template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00002671class _LIBCPP_VISIBLE time_get_byname
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002672 : public time_get<_CharT, _InputIterator>,
2673 private __time_get_storage<_CharT>
2674{
2675public:
2676 typedef time_base::dateorder dateorder;
2677 typedef _InputIterator iter_type;
2678 typedef _CharT char_type;
2679 typedef basic_string<char_type> string_type;
2680
Howard Hinnant82894812010-09-22 16:48:34 +00002681 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002682 explicit time_get_byname(const char* __nm, size_t __refs = 0)
2683 : time_get<_CharT, _InputIterator>(__refs),
2684 __time_get_storage<_CharT>(__nm) {}
Howard Hinnant82894812010-09-22 16:48:34 +00002685 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002686 explicit time_get_byname(const string& __nm, size_t __refs = 0)
2687 : time_get<_CharT, _InputIterator>(__refs),
2688 __time_get_storage<_CharT>(__nm) {}
2689
2690protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002691 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002692 ~time_get_byname() {}
2693
Howard Hinnant82894812010-09-22 16:48:34 +00002694 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002695 virtual dateorder do_date_order() const {return this->__do_date_order();}
2696private:
Howard Hinnant82894812010-09-22 16:48:34 +00002697 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002698 virtual const string_type* __weeks() const {return this->__weeks_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002699 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002700 virtual const string_type* __months() const {return this->__months_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002701 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002702 virtual const string_type* __am_pm() const {return this->__am_pm_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002703 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002704 virtual const string_type& __c() const {return this->__c_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002705 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002706 virtual const string_type& __r() const {return this->__r_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002707 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002708 virtual const string_type& __x() const {return this->__x_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002709 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002710 virtual const string_type& __X() const {return this->__X_;}
2711};
2712
2713extern template class time_get_byname<char>;
2714extern template class time_get_byname<wchar_t>;
2715
2716class __time_put
2717{
2718 locale_t __loc_;
2719protected:
Sean Hunt0389c532011-07-12 00:55:04 +00002720#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002721 _LIBCPP_ALWAYS_INLINE __time_put() : __loc_(0) {}
Sean Hunt0389c532011-07-12 00:55:04 +00002722#else // _LIBCPP_STABLE_APPLE_ABI
2723 _LIBCPP_ALWAYS_INLINE __time_put() : __loc_(__cloc()) {}
2724#endif // _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002725 __time_put(const char* __nm);
2726 __time_put(const string& __nm);
2727 ~__time_put();
2728 void __do_put(char* __nb, char*& __ne, const tm* __tm,
2729 char __fmt, char __mod) const;
2730 void __do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
2731 char __fmt, char __mod) const;
2732};
2733
2734template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00002735class _LIBCPP_VISIBLE time_put
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002736 : public locale::facet,
2737 private __time_put
2738{
2739public:
2740 typedef _CharT char_type;
2741 typedef _OutputIterator iter_type;
2742
2743 _LIBCPP_ALWAYS_INLINE
2744 explicit time_put(size_t __refs = 0)
2745 : locale::facet(__refs) {}
2746
2747 iter_type put(iter_type __s, ios_base& __iob, char_type __fl, const tm* __tm,
2748 const char_type* __pb, const char_type* __pe) const;
2749
2750 _LIBCPP_ALWAYS_INLINE
2751 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
2752 const tm* __tm, char __fmt, char __mod = 0) const
2753 {
2754 return do_put(__s, __iob, __fl, __tm, __fmt, __mod);
2755 }
2756
2757 static locale::id id;
2758
2759protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002760 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002761 ~time_put() {}
2762 virtual iter_type do_put(iter_type __s, ios_base&, char_type, const tm* __tm,
2763 char __fmt, char __mod) const;
2764
Howard Hinnant82894812010-09-22 16:48:34 +00002765 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002766 explicit time_put(const char* __nm, size_t __refs)
2767 : locale::facet(__refs),
2768 __time_put(__nm) {}
Howard Hinnant82894812010-09-22 16:48:34 +00002769 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002770 explicit time_put(const string& __nm, size_t __refs)
2771 : locale::facet(__refs),
2772 __time_put(__nm) {}
2773};
2774
2775template <class _CharT, class _OutputIterator>
2776locale::id
2777time_put<_CharT, _OutputIterator>::id;
2778
2779template <class _CharT, class _OutputIterator>
2780_OutputIterator
2781time_put<_CharT, _OutputIterator>::put(iter_type __s, ios_base& __iob,
2782 char_type __fl, const tm* __tm,
2783 const char_type* __pb,
2784 const char_type* __pe) const
2785{
2786 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2787 for (; __pb != __pe; ++__pb)
2788 {
2789 if (__ct.narrow(*__pb, 0) == '%')
2790 {
2791 if (++__pb == __pe)
2792 {
2793 *__s++ = __pb[-1];
2794 break;
2795 }
2796 char __mod = 0;
2797 char __fmt = __ct.narrow(*__pb, 0);
2798 if (__fmt == 'E' || __fmt == 'O')
2799 {
2800 if (++__pb == __pe)
2801 {
2802 *__s++ = __pb[-2];
2803 *__s++ = __pb[-1];
2804 break;
2805 }
2806 __mod = __fmt;
2807 __fmt = __ct.narrow(*__pb, 0);
2808 }
2809 __s = do_put(__s, __iob, __fl, __tm, __fmt, __mod);
2810 }
2811 else
2812 *__s++ = *__pb;
2813 }
2814 return __s;
2815}
2816
2817template <class _CharT, class _OutputIterator>
2818_OutputIterator
2819time_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
2820 char_type, const tm* __tm,
2821 char __fmt, char __mod) const
2822{
2823 char_type __nar[100];
2824 char_type* __nb = __nar;
2825 char_type* __ne = __nb + 100;
2826 __do_put(__nb, __ne, __tm, __fmt, __mod);
Howard Hinnant0949eed2011-06-30 21:18:19 +00002827 return _VSTD::copy(__nb, __ne, __s);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002828}
2829
2830extern template class time_put<char>;
2831extern template class time_put<wchar_t>;
2832
2833template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00002834class _LIBCPP_VISIBLE time_put_byname
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002835 : public time_put<_CharT, _OutputIterator>
2836{
2837public:
2838 _LIBCPP_ALWAYS_INLINE
2839 explicit time_put_byname(const char* __nm, size_t __refs = 0)
2840 : time_put<_CharT, _OutputIterator>(__nm, __refs) {}
2841
2842 _LIBCPP_ALWAYS_INLINE
2843 explicit time_put_byname(const string& __nm, size_t __refs = 0)
2844 : time_put<_CharT, _OutputIterator>(__nm, __refs) {}
2845
2846protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002847 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002848 ~time_put_byname() {}
2849};
2850
2851extern template class time_put_byname<char>;
2852extern template class time_put_byname<wchar_t>;
2853
2854// money_base
2855
Howard Hinnant82894812010-09-22 16:48:34 +00002856class _LIBCPP_VISIBLE money_base
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002857{
2858public:
2859 enum part {none, space, symbol, sign, value};
2860 struct pattern {char field[4];};
2861
2862 _LIBCPP_ALWAYS_INLINE money_base() {}
2863};
2864
2865// moneypunct
2866
2867template <class _CharT, bool _International = false>
Howard Hinnant82894812010-09-22 16:48:34 +00002868class _LIBCPP_VISIBLE moneypunct
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002869 : public locale::facet,
2870 public money_base
2871{
2872public:
2873 typedef _CharT char_type;
2874 typedef basic_string<char_type> string_type;
2875
Howard Hinnant82894812010-09-22 16:48:34 +00002876 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002877 explicit moneypunct(size_t __refs = 0)
2878 : locale::facet(__refs) {}
2879
2880 _LIBCPP_ALWAYS_INLINE char_type decimal_point() const {return do_decimal_point();}
2881 _LIBCPP_ALWAYS_INLINE char_type thousands_sep() const {return do_thousands_sep();}
2882 _LIBCPP_ALWAYS_INLINE string grouping() const {return do_grouping();}
2883 _LIBCPP_ALWAYS_INLINE string_type curr_symbol() const {return do_curr_symbol();}
2884 _LIBCPP_ALWAYS_INLINE string_type positive_sign() const {return do_positive_sign();}
2885 _LIBCPP_ALWAYS_INLINE string_type negative_sign() const {return do_negative_sign();}
2886 _LIBCPP_ALWAYS_INLINE int frac_digits() const {return do_frac_digits();}
2887 _LIBCPP_ALWAYS_INLINE pattern pos_format() const {return do_pos_format();}
2888 _LIBCPP_ALWAYS_INLINE pattern neg_format() const {return do_neg_format();}
2889
2890 static locale::id id;
2891 static const bool intl = _International;
2892
2893protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002894 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002895 ~moneypunct() {}
2896
2897 virtual char_type do_decimal_point() const {return numeric_limits<char_type>::max();}
2898 virtual char_type do_thousands_sep() const {return numeric_limits<char_type>::max();}
2899 virtual string do_grouping() const {return string();}
2900 virtual string_type do_curr_symbol() const {return string_type();}
2901 virtual string_type do_positive_sign() const {return string_type();}
2902 virtual string_type do_negative_sign() const {return string_type(1, '-');}
2903 virtual int do_frac_digits() const {return 0;}
2904 virtual pattern do_pos_format() const
2905 {pattern __p = {symbol, sign, none, value}; return __p;}
2906 virtual pattern do_neg_format() const
2907 {pattern __p = {symbol, sign, none, value}; return __p;}
2908};
2909
2910template <class _CharT, bool _International>
2911locale::id
2912moneypunct<_CharT, _International>::id;
2913
2914extern template class moneypunct<char, false>;
2915extern template class moneypunct<char, true>;
2916extern template class moneypunct<wchar_t, false>;
2917extern template class moneypunct<wchar_t, true>;
2918
2919// moneypunct_byname
2920
2921template <class _CharT, bool _International = false>
Howard Hinnant82894812010-09-22 16:48:34 +00002922class _LIBCPP_VISIBLE moneypunct_byname
2923 : public moneypunct<_CharT, _International>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002924{
2925public:
2926 typedef money_base::pattern pattern;
2927 typedef _CharT char_type;
2928 typedef basic_string<char_type> string_type;
2929
2930 _LIBCPP_ALWAYS_INLINE
2931 explicit moneypunct_byname(const char* __nm, size_t __refs = 0)
2932 : moneypunct<_CharT, _International>(__refs) {init(__nm);}
2933
2934 _LIBCPP_ALWAYS_INLINE
2935 explicit moneypunct_byname(const string& __nm, size_t __refs = 0)
2936 : moneypunct<_CharT, _International>(__refs) {init(__nm.c_str());}
2937
2938protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002939 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002940 ~moneypunct_byname() {}
2941
2942 virtual char_type do_decimal_point() const {return __decimal_point_;}
2943 virtual char_type do_thousands_sep() const {return __thousands_sep_;}
2944 virtual string do_grouping() const {return __grouping_;}
2945 virtual string_type do_curr_symbol() const {return __curr_symbol_;}
2946 virtual string_type do_positive_sign() const {return __positive_sign_;}
2947 virtual string_type do_negative_sign() const {return __negative_sign_;}
2948 virtual int do_frac_digits() const {return __frac_digits_;}
2949 virtual pattern do_pos_format() const {return __pos_format_;}
2950 virtual pattern do_neg_format() const {return __neg_format_;}
2951
2952private:
2953 char_type __decimal_point_;
2954 char_type __thousands_sep_;
2955 string __grouping_;
2956 string_type __curr_symbol_;
2957 string_type __positive_sign_;
2958 string_type __negative_sign_;
2959 int __frac_digits_;
2960 pattern __pos_format_;
2961 pattern __neg_format_;
2962
2963 void init(const char*);
2964};
2965
2966template<> void moneypunct_byname<char, false>::init(const char*);
2967template<> void moneypunct_byname<char, true>::init(const char*);
2968template<> void moneypunct_byname<wchar_t, false>::init(const char*);
2969template<> void moneypunct_byname<wchar_t, true>::init(const char*);
2970
2971extern template class moneypunct_byname<char, false>;
2972extern template class moneypunct_byname<char, true>;
2973extern template class moneypunct_byname<wchar_t, false>;
2974extern template class moneypunct_byname<wchar_t, true>;
2975
2976// money_get
2977
2978template <class _CharT>
2979class __money_get
2980{
2981protected:
2982 typedef _CharT char_type;
2983 typedef basic_string<char_type> string_type;
2984
2985 _LIBCPP_ALWAYS_INLINE __money_get() {}
2986
2987 static void __gather_info(bool __intl, const locale& __loc,
2988 money_base::pattern& __pat, char_type& __dp,
2989 char_type& __ts, string& __grp,
2990 string_type& __sym, string_type& __psn,
2991 string_type& __nsn, int& __fd);
2992};
2993
2994template <class _CharT>
2995void
2996__money_get<_CharT>::__gather_info(bool __intl, const locale& __loc,
2997 money_base::pattern& __pat, char_type& __dp,
2998 char_type& __ts, string& __grp,
2999 string_type& __sym, string_type& __psn,
3000 string_type& __nsn, int& __fd)
3001{
3002 if (__intl)
3003 {
3004 const moneypunct<char_type, true>& __mp =
3005 use_facet<moneypunct<char_type, true> >(__loc);
3006 __pat = __mp.neg_format();
3007 __nsn = __mp.negative_sign();
3008 __psn = __mp.positive_sign();
3009 __dp = __mp.decimal_point();
3010 __ts = __mp.thousands_sep();
3011 __grp = __mp.grouping();
3012 __sym = __mp.curr_symbol();
3013 __fd = __mp.frac_digits();
3014 }
3015 else
3016 {
3017 const moneypunct<char_type, false>& __mp =
3018 use_facet<moneypunct<char_type, false> >(__loc);
3019 __pat = __mp.neg_format();
3020 __nsn = __mp.negative_sign();
3021 __psn = __mp.positive_sign();
3022 __dp = __mp.decimal_point();
3023 __ts = __mp.thousands_sep();
3024 __grp = __mp.grouping();
3025 __sym = __mp.curr_symbol();
3026 __fd = __mp.frac_digits();
3027 }
3028}
3029
3030extern template class __money_get<char>;
3031extern template class __money_get<wchar_t>;
3032
3033template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00003034class _LIBCPP_VISIBLE money_get
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003035 : public locale::facet,
3036 private __money_get<_CharT>
3037{
3038public:
3039 typedef _CharT char_type;
3040 typedef _InputIterator iter_type;
3041 typedef basic_string<char_type> string_type;
3042
3043 _LIBCPP_ALWAYS_INLINE
3044 explicit money_get(size_t __refs = 0)
3045 : locale::facet(__refs) {}
3046
3047 _LIBCPP_ALWAYS_INLINE
3048 iter_type get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob,
3049 ios_base::iostate& __err, long double& __v) const
3050 {
3051 return do_get(__b, __e, __intl, __iob, __err, __v);
3052 }
3053
3054 _LIBCPP_ALWAYS_INLINE
3055 iter_type get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob,
3056 ios_base::iostate& __err, string_type& __v) const
3057 {
3058 return do_get(__b, __e, __intl, __iob, __err, __v);
3059 }
3060
3061 static locale::id id;
3062
3063protected:
3064
Howard Hinnant82894812010-09-22 16:48:34 +00003065 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003066 ~money_get() {}
Howard Hinnant324bb032010-08-22 00:02:43 +00003067
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003068 virtual iter_type do_get(iter_type __b, iter_type __e, bool __intl,
3069 ios_base& __iob, ios_base::iostate& __err,
3070 long double& __v) const;
3071 virtual iter_type do_get(iter_type __b, iter_type __e, bool __intl,
3072 ios_base& __iob, ios_base::iostate& __err,
3073 string_type& __v) const;
3074
3075private:
3076 static bool __do_get(iter_type& __b, iter_type __e,
3077 bool __intl, const locale& __loc,
3078 ios_base::fmtflags __flags, ios_base::iostate& __err,
3079 bool& __neg, const ctype<char_type>& __ct,
3080 unique_ptr<char_type, void(*)(void*)>& __wb,
3081 char_type*& __wn, char_type* __we);
3082};
3083
3084template <class _CharT, class _InputIterator>
3085locale::id
3086money_get<_CharT, _InputIterator>::id;
3087
3088void __do_nothing(void*);
3089
3090template <class _Tp>
3091_LIBCPP_HIDDEN
3092void
3093__double_or_nothing(unique_ptr<_Tp, void(*)(void*)>& __b, _Tp*& __n, _Tp*& __e)
3094{
3095 bool __owns = __b.get_deleter() != __do_nothing;
3096 size_t __cur_cap = (__e-__b.get()) * sizeof(_Tp);
3097 size_t __new_cap = __cur_cap < numeric_limits<size_t>::max() / 2 ?
3098 2 * __cur_cap : numeric_limits<size_t>::max();
3099 size_t __n_off = __n - __b.get();
3100 _Tp* __t = (_Tp*)realloc(__owns ? __b.get() : 0, __new_cap);
3101 if (__t == 0)
3102 __throw_bad_alloc();
3103 if (__owns)
3104 __b.release();
3105 __b = unique_ptr<_Tp, void(*)(void*)>(__t, free);
3106 __new_cap /= sizeof(_Tp);
3107 __n = __b.get() + __n_off;
3108 __e = __b.get() + __new_cap;
3109}
3110
3111// true == success
3112template <class _CharT, class _InputIterator>
3113bool
3114money_get<_CharT, _InputIterator>::__do_get(iter_type& __b, iter_type __e,
3115 bool __intl, const locale& __loc,
3116 ios_base::fmtflags __flags,
3117 ios_base::iostate& __err,
3118 bool& __neg,
3119 const ctype<char_type>& __ct,
3120 unique_ptr<char_type, void(*)(void*)>& __wb,
3121 char_type*& __wn, char_type* __we)
3122{
3123 const unsigned __bz = 100;
3124 unsigned __gbuf[__bz];
3125 unique_ptr<unsigned, void(*)(void*)> __gb(__gbuf, __do_nothing);
3126 unsigned* __gn = __gb.get();
3127 unsigned* __ge = __gn + __bz;
3128 money_base::pattern __pat;
3129 char_type __dp;
3130 char_type __ts;
3131 string __grp;
3132 string_type __sym;
3133 string_type __psn;
3134 string_type __nsn;
3135 int __fd;
3136 __money_get<_CharT>::__gather_info(__intl, __loc, __pat, __dp, __ts, __grp,
3137 __sym, __psn, __nsn, __fd);
3138 const string_type* __trailing_sign = 0;
3139 __wn = __wb.get();
3140 for (unsigned __p = 0; __p < 4 && __b != __e; ++__p)
3141 {
3142 switch (__pat.field[__p])
3143 {
3144 case money_base::space:
3145 if (__p != 3)
3146 {
3147 if (__ct.is(ctype_base::space, *__b))
3148 ++__b;
3149 else
3150 {
3151 __err |= ios_base::failbit;
3152 return false;
3153 }
3154 }
Howard Hinnant324bb032010-08-22 00:02:43 +00003155 // drop through
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003156 case money_base::none:
3157 if (__p != 3)
3158 {
3159 while (__b != __e && __ct.is(ctype_base::space, *__b))
3160 ++__b;
3161 }
3162 break;
3163 case money_base::sign:
3164 if (__psn.size() + __nsn.size() > 0)
3165 {
3166 if (__psn.size() == 0 || __nsn.size() == 0)
3167 { // sign is optional
3168 if (__psn.size() > 0)
3169 { // __nsn.size() == 0
3170 if (*__b == __psn[0])
3171 {
3172 ++__b;
3173 if (__psn.size() > 1)
3174 __trailing_sign = &__psn;
3175 }
3176 else
3177 __neg = true;
3178 }
3179 else if (*__b == __nsn[0]) // __nsn.size() > 0 && __psn.size() == 0
3180 {
3181 ++__b;
3182 __neg = true;
3183 if (__nsn.size() > 1)
3184 __trailing_sign = &__nsn;
3185 }
3186 }
3187 else // sign is required
3188 {
3189 if (*__b == __psn[0])
3190 {
3191 ++__b;
3192 if (__psn.size() > 1)
3193 __trailing_sign = &__psn;
3194 }
3195 else if (*__b == __nsn[0])
3196 {
3197 ++__b;
3198 __neg = true;
3199 if (__nsn.size() > 1)
3200 __trailing_sign = &__nsn;
3201 }
3202 else
3203 {
3204 __err |= ios_base::failbit;
3205 return false;
3206 }
3207 }
3208 }
3209 break;
3210 case money_base::symbol:
3211 {
3212 bool __more_needed = __trailing_sign ||
3213 (__p < 2) ||
3214 (__p == 2 && __pat.field[3] != static_cast<char>(money_base::none));
3215 bool __sb = __flags & ios_base::showbase;
3216 if (__sb || __more_needed)
3217 {
3218 ios_base::iostate __et = ios_base::goodbit;
3219 string_type* __k = __scan_keyword(__b, __e, &__sym, &__sym+1,
3220 __ct, __et);
3221 if (__sb && __k != &__sym)
3222 {
3223 __err |= ios_base::failbit;
3224 return false;
3225 }
3226 }
3227 }
3228 break;
3229 case money_base::value:
3230 {
3231 unsigned __ng = 0;
3232 for (; __b != __e; ++__b)
3233 {
3234 char_type __c = *__b;
3235 if (__ct.is(ctype_base::digit, __c))
3236 {
3237 if (__wn == __we)
3238 __double_or_nothing(__wb, __wn, __we);
3239 *__wn++ = __c;
3240 ++__ng;
3241 }
3242 else if (__grp.size() > 0 && __ng > 0 && __c == __ts)
3243 {
3244 if (__gn == __ge)
3245 __double_or_nothing(__gb, __gn, __ge);
3246 *__gn++ = __ng;
3247 __ng = 0;
3248 }
3249 else
3250 break;
3251 }
3252 if (__gb.get() != __gn && __ng > 0)
3253 {
3254 if (__gn == __ge)
3255 __double_or_nothing(__gb, __gn, __ge);
3256 *__gn++ = __ng;
3257 }
3258 if (__fd > 0)
3259 {
3260 if (__b == __e || *__b != __dp)
3261 {
3262 __err |= ios_base::failbit;
3263 return false;
3264 }
3265 for (++__b; __fd > 0; --__fd, ++__b)
3266 {
3267 if (__b == __e || !__ct.is(ctype_base::digit, *__b))
3268 {
3269 __err |= ios_base::failbit;
3270 return false;
3271 }
3272 if (__wn == __we)
3273 __double_or_nothing(__wb, __wn, __we);
3274 *__wn++ = *__b;
3275 }
3276 }
3277 if (__wn == __wb.get())
3278 {
3279 __err |= ios_base::failbit;
3280 return false;
3281 }
3282 }
3283 break;
3284 }
3285 }
3286 if (__trailing_sign)
3287 {
3288 for (unsigned __i = 1; __i < __trailing_sign->size(); ++__i, ++__b)
3289 {
3290 if (__b == __e || *__b != (*__trailing_sign)[__i])
3291 {
3292 __err |= ios_base::failbit;
3293 return false;
3294 }
3295 }
3296 }
3297 if (__gb.get() != __gn)
3298 {
3299 ios_base::iostate __et = ios_base::goodbit;
3300 __check_grouping(__grp, __gb.get(), __gn, __et);
3301 if (__et)
3302 {
3303 __err |= ios_base::failbit;
3304 return false;
3305 }
3306 }
3307 return true;
3308}
3309
3310template <class _CharT, class _InputIterator>
3311_InputIterator
3312money_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
3313 bool __intl, ios_base& __iob,
3314 ios_base::iostate& __err,
3315 long double& __v) const
3316{
3317 const unsigned __bz = 100;
3318 char_type __wbuf[__bz];
3319 unique_ptr<char_type, void(*)(void*)> __wb(__wbuf, __do_nothing);
3320 char_type* __wn;
3321 char_type* __we = __wbuf + __bz;
3322 locale __loc = __iob.getloc();
3323 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3324 bool __neg = false;
3325 if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct,
3326 __wb, __wn, __we))
3327 {
3328 const char __src[] = "0123456789";
3329 char_type __atoms[sizeof(__src)-1];
3330 __ct.widen(__src, __src + (sizeof(__src)-1), __atoms);
3331 char __nbuf[__bz];
3332 char* __nc = __nbuf;
3333 unique_ptr<char, void(*)(void*)> __h(0, free);
3334 if (__wn - __wb.get() > __bz-2)
3335 {
3336 __h.reset((char*)malloc(__wn - __wb.get() + 2));
3337 if (__h.get() == 0)
3338 __throw_bad_alloc();
3339 __nc = __h.get();
3340 }
3341 if (__neg)
3342 *__nc++ = '-';
3343 for (const char_type* __w = __wb.get(); __w < __wn; ++__w, ++__nc)
3344 *__nc = __src[find(__atoms, __atoms+sizeof(__atoms), *__w) - __atoms];
3345 *__nc = char();
3346 if (sscanf(__nbuf, "%Lf", &__v) != 1)
3347 __throw_runtime_error("money_get error");
3348 }
3349 if (__b == __e)
3350 __err |= ios_base::eofbit;
3351 return __b;
3352}
3353
3354template <class _CharT, class _InputIterator>
3355_InputIterator
3356money_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
3357 bool __intl, ios_base& __iob,
3358 ios_base::iostate& __err,
3359 string_type& __v) const
3360{
3361 const unsigned __bz = 100;
3362 char_type __wbuf[__bz];
3363 unique_ptr<char_type, void(*)(void*)> __wb(__wbuf, __do_nothing);
3364 char_type* __wn;
3365 char_type* __we = __wbuf + __bz;
3366 locale __loc = __iob.getloc();
3367 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3368 bool __neg = false;
3369 if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct,
3370 __wb, __wn, __we))
3371 {
3372 __v.clear();
3373 if (__neg)
3374 __v.push_back(__ct.widen('-'));
3375 char_type __z = __ct.widen('0');
3376 char_type* __w;
3377 for (__w = __wb.get(); __w < __wn-1; ++__w)
3378 if (*__w != __z)
3379 break;
3380 __v.append(__w, __wn);
3381 }
3382 if (__b == __e)
3383 __err |= ios_base::eofbit;
3384 return __b;
3385}
3386
3387extern template class money_get<char>;
3388extern template class money_get<wchar_t>;
3389
3390// money_put
3391
3392template <class _CharT>
3393class __money_put
3394{
3395protected:
3396 typedef _CharT char_type;
3397 typedef basic_string<char_type> string_type;
3398
3399 _LIBCPP_ALWAYS_INLINE __money_put() {}
3400
3401 static void __gather_info(bool __intl, bool __neg, const locale& __loc,
3402 money_base::pattern& __pat, char_type& __dp,
3403 char_type& __ts, string& __grp,
3404 string_type& __sym, string_type& __sn,
3405 int& __fd);
3406 static void __format(char_type* __mb, char_type*& __mi, char_type*& __me,
3407 ios_base::fmtflags __flags,
3408 const char_type* __db, const char_type* __de,
3409 const ctype<char_type>& __ct, bool __neg,
3410 const money_base::pattern& __pat, char_type __dp,
3411 char_type __ts, const string& __grp,
3412 const string_type& __sym, const string_type& __sn,
3413 int __fd);
3414};
3415
3416template <class _CharT>
3417void
3418__money_put<_CharT>::__gather_info(bool __intl, bool __neg, const locale& __loc,
3419 money_base::pattern& __pat, char_type& __dp,
3420 char_type& __ts, string& __grp,
3421 string_type& __sym, string_type& __sn,
3422 int& __fd)
3423{
3424 if (__intl)
3425 {
3426 const moneypunct<char_type, true>& __mp =
3427 use_facet<moneypunct<char_type, true> >(__loc);
3428 if (__neg)
3429 {
3430 __pat = __mp.neg_format();
3431 __sn = __mp.negative_sign();
3432 }
3433 else
3434 {
3435 __pat = __mp.pos_format();
3436 __sn = __mp.positive_sign();
3437 }
3438 __dp = __mp.decimal_point();
3439 __ts = __mp.thousands_sep();
3440 __grp = __mp.grouping();
3441 __sym = __mp.curr_symbol();
3442 __fd = __mp.frac_digits();
3443 }
3444 else
3445 {
3446 const moneypunct<char_type, false>& __mp =
3447 use_facet<moneypunct<char_type, false> >(__loc);
3448 if (__neg)
3449 {
3450 __pat = __mp.neg_format();
3451 __sn = __mp.negative_sign();
3452 }
3453 else
3454 {
3455 __pat = __mp.pos_format();
3456 __sn = __mp.positive_sign();
3457 }
3458 __dp = __mp.decimal_point();
3459 __ts = __mp.thousands_sep();
3460 __grp = __mp.grouping();
3461 __sym = __mp.curr_symbol();
3462 __fd = __mp.frac_digits();
3463 }
3464}
3465
3466template <class _CharT>
3467void
3468__money_put<_CharT>::__format(char_type* __mb, char_type*& __mi, char_type*& __me,
3469 ios_base::fmtflags __flags,
3470 const char_type* __db, const char_type* __de,
3471 const ctype<char_type>& __ct, bool __neg,
3472 const money_base::pattern& __pat, char_type __dp,
3473 char_type __ts, const string& __grp,
3474 const string_type& __sym, const string_type& __sn,
3475 int __fd)
3476{
3477 __me = __mb;
3478 for (unsigned __p = 0; __p < 4; ++__p)
3479 {
3480 switch (__pat.field[__p])
3481 {
3482 case money_base::none:
3483 __mi = __me;
3484 break;
3485 case money_base::space:
3486 __mi = __me;
3487 *__me++ = __ct.widen(' ');
3488 break;
3489 case money_base::sign:
3490 if (!__sn.empty())
3491 *__me++ = __sn[0];
3492 break;
3493 case money_base::symbol:
3494 if (!__sym.empty() && (__flags & ios_base::showbase))
Howard Hinnant0949eed2011-06-30 21:18:19 +00003495 __me = _VSTD::copy(__sym.begin(), __sym.end(), __me);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003496 break;
3497 case money_base::value:
3498 {
3499 // remember start of value so we can reverse it
3500 char_type* __t = __me;
3501 // find beginning of digits
3502 if (__neg)
3503 ++__db;
3504 // find end of digits
3505 const char_type* __d;
3506 for (__d = __db; __d < __de; ++__d)
3507 if (!__ct.is(ctype_base::digit, *__d))
3508 break;
3509 // print fractional part
3510 if (__fd > 0)
3511 {
3512 int __f;
3513 for (__f = __fd; __d > __db && __f > 0; --__f)
3514 *__me++ = *--__d;
3515 char_type __z = __f > 0 ? __ct.widen('0') : char_type();
3516 for (; __f > 0; --__f)
3517 *__me++ = __z;
3518 *__me++ = __dp;
3519 }
3520 // print units part
3521 if (__d == __db)
3522 {
3523 *__me++ = __ct.widen('0');
3524 }
3525 else
3526 {
3527 unsigned __ng = 0;
3528 unsigned __ig = 0;
3529 unsigned __gl = __grp.empty() ? numeric_limits<unsigned>::max()
3530 : static_cast<unsigned>(__grp[__ig]);
3531 while (__d != __db)
3532 {
3533 if (__ng == __gl)
3534 {
3535 *__me++ = __ts;
3536 __ng = 0;
3537 if (++__ig < __grp.size())
3538 __gl = __grp[__ig] == numeric_limits<char>::max() ?
3539 numeric_limits<unsigned>::max() :
3540 static_cast<unsigned>(__grp[__ig]);
3541 }
3542 *__me++ = *--__d;
3543 ++__ng;
3544 }
3545 }
3546 // reverse it
3547 reverse(__t, __me);
3548 }
3549 break;
3550 }
3551 }
3552 // print rest of sign, if any
3553 if (__sn.size() > 1)
Howard Hinnant0949eed2011-06-30 21:18:19 +00003554 __me = _VSTD::copy(__sn.begin()+1, __sn.end(), __me);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003555 // set alignment
3556 if ((__flags & ios_base::adjustfield) == ios_base::left)
3557 __mi = __me;
3558 else if ((__flags & ios_base::adjustfield) != ios_base::internal)
3559 __mi = __mb;
3560}
3561
3562extern template class __money_put<char>;
3563extern template class __money_put<wchar_t>;
3564
3565template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00003566class _LIBCPP_VISIBLE money_put
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003567 : public locale::facet,
3568 private __money_put<_CharT>
3569{
3570public:
3571 typedef _CharT char_type;
3572 typedef _OutputIterator iter_type;
3573 typedef basic_string<char_type> string_type;
3574
3575 _LIBCPP_ALWAYS_INLINE
3576 explicit money_put(size_t __refs = 0)
3577 : locale::facet(__refs) {}
3578
3579 _LIBCPP_ALWAYS_INLINE
3580 iter_type put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl,
3581 long double __units) const
3582 {
3583 return do_put(__s, __intl, __iob, __fl, __units);
3584 }
3585
3586 _LIBCPP_ALWAYS_INLINE
3587 iter_type put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl,
3588 const string_type& __digits) const
3589 {
3590 return do_put(__s, __intl, __iob, __fl, __digits);
3591 }
3592
3593 static locale::id id;
3594
3595protected:
Howard Hinnant82894812010-09-22 16:48:34 +00003596 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003597 ~money_put() {}
3598
3599 virtual iter_type do_put(iter_type __s, bool __intl, ios_base& __iob,
3600 char_type __fl, long double __units) const;
3601 virtual iter_type do_put(iter_type __s, bool __intl, ios_base& __iob,
3602 char_type __fl, const string_type& __digits) const;
3603};
3604
3605template <class _CharT, class _OutputIterator>
3606locale::id
3607money_put<_CharT, _OutputIterator>::id;
3608
3609template <class _CharT, class _OutputIterator>
3610_OutputIterator
3611money_put<_CharT, _OutputIterator>::do_put(iter_type __s, bool __intl,
3612 ios_base& __iob, char_type __fl,
3613 long double __units) const
3614{
3615 // convert to char
3616 const size_t __bs = 100;
3617 char __buf[__bs];
3618 char* __bb = __buf;
3619 char_type __digits[__bs];
3620 char_type* __db = __digits;
3621 size_t __n = snprintf(__bb, __bs, "%.0Lf", __units);
3622 unique_ptr<char, void(*)(void*)> __hn(0, free);
3623 unique_ptr<char_type, void(*)(void*)> __hd(0, free);
3624 // secure memory for digit storage
3625 if (__n > __bs-1)
3626 {
Sean Huntf3907e62011-07-15 05:40:33 +00003627#ifdef _LIBCPP_STABLE_APPLE_ABI
Howard Hinnantadff4892010-05-24 17:49:41 +00003628 __n = __nolocale_asprintf(&__bb, "%.0Lf", __units);
Sean Huntf3907e62011-07-15 05:40:33 +00003629#else
3630 __n = __asprintf_l(&__bb, __cloc(), "%.0Lf", __units);
3631#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003632 if (__bb == 0)
3633 __throw_bad_alloc();
3634 __hn.reset(__bb);
3635 __hd.reset((char_type*)malloc(__n * sizeof(char_type)));
3636 if (__hd == 0)
3637 __throw_bad_alloc();
3638 __db = __hd.get();
3639 }
3640 // gather info
3641 locale __loc = __iob.getloc();
3642 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3643 __ct.widen(__bb, __bb + __n, __db);
3644 bool __neg = __n > 0 && __bb[0] == '-';
3645 money_base::pattern __pat;
3646 char_type __dp;
3647 char_type __ts;
3648 string __grp;
3649 string_type __sym;
3650 string_type __sn;
3651 int __fd;
3652 this->__gather_info(__intl, __neg, __loc, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3653 // secure memory for formatting
3654 char_type __mbuf[__bs];
3655 char_type* __mb = __mbuf;
3656 unique_ptr<char_type, void(*)(void*)> __hw(0, free);
3657 size_t __exn = static_cast<int>(__n) > __fd ?
3658 (__n - __fd) * 2 + __sn.size() + __sym.size() + __fd + 1
3659 : __sn.size() + __sym.size() + __fd + 2;
3660 if (__exn > __bs)
3661 {
3662 __hw.reset((char_type*)malloc(__exn * sizeof(char_type)));
3663 __mb = __hw.get();
3664 if (__mb == 0)
3665 __throw_bad_alloc();
3666 }
3667 // format
3668 char_type* __mi;
3669 char_type* __me;
3670 this->__format(__mb, __mi, __me, __iob.flags(),
3671 __db, __db + __n, __ct,
3672 __neg, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3673 return __pad_and_output(__s, __mb, __mi, __me, __iob, __fl);
3674}
3675
3676template <class _CharT, class _OutputIterator>
3677_OutputIterator
3678money_put<_CharT, _OutputIterator>::do_put(iter_type __s, bool __intl,
3679 ios_base& __iob, char_type __fl,
3680 const string_type& __digits) const
3681{
3682 // gather info
3683 locale __loc = __iob.getloc();
3684 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3685 bool __neg = __digits.size() > 0 && __digits[0] == __ct.widen('-');
3686 money_base::pattern __pat;
3687 char_type __dp;
3688 char_type __ts;
3689 string __grp;
3690 string_type __sym;
3691 string_type __sn;
3692 int __fd;
3693 this->__gather_info(__intl, __neg, __loc, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3694 // secure memory for formatting
3695 char_type __mbuf[100];
3696 char_type* __mb = __mbuf;
3697 unique_ptr<char_type, void(*)(void*)> __h(0, free);
3698 size_t __exn = __digits.size() > __fd ?
3699 (__digits.size() - __fd) * 2 + __sn.size() + __sym.size() + __fd + 1
3700 : __sn.size() + __sym.size() + __fd + 2;
3701 if (__exn > 100)
3702 {
3703 __h.reset((char_type*)malloc(__exn * sizeof(char_type)));
3704 __mb = __h.get();
3705 if (__mb == 0)
3706 __throw_bad_alloc();
3707 }
3708 // format
3709 char_type* __mi;
3710 char_type* __me;
3711 this->__format(__mb, __mi, __me, __iob.flags(),
3712 __digits.data(), __digits.data() + __digits.size(), __ct,
3713 __neg, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3714 return __pad_and_output(__s, __mb, __mi, __me, __iob, __fl);
3715}
3716
3717extern template class money_put<char>;
3718extern template class money_put<wchar_t>;
3719
3720// messages
3721
Howard Hinnant82894812010-09-22 16:48:34 +00003722class _LIBCPP_VISIBLE messages_base
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003723{
3724public:
Howard Hinnantb2080c72011-02-25 00:51:08 +00003725 typedef ptrdiff_t catalog;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003726
3727 _LIBCPP_ALWAYS_INLINE messages_base() {}
3728};
3729
3730template <class _CharT>
Howard Hinnant82894812010-09-22 16:48:34 +00003731class _LIBCPP_VISIBLE messages
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003732 : public locale::facet,
3733 public messages_base
3734{
3735public:
3736 typedef _CharT char_type;
3737 typedef basic_string<_CharT> string_type;
3738
3739 _LIBCPP_ALWAYS_INLINE
3740 explicit messages(size_t __refs = 0)
3741 : locale::facet(__refs) {}
3742
3743 _LIBCPP_ALWAYS_INLINE
3744 catalog open(const basic_string<char>& __nm, const locale& __loc) const
3745 {
3746 return do_open(__nm, __loc);
3747 }
3748
3749 _LIBCPP_ALWAYS_INLINE
3750 string_type get(catalog __c, int __set, int __msgid,
3751 const string_type& __dflt) const
3752 {
3753 return do_get(__c, __set, __msgid, __dflt);
3754 }
3755
3756 _LIBCPP_ALWAYS_INLINE
3757 void close(catalog __c) const
3758 {
3759 do_close(__c);
3760 }
3761
3762 static locale::id id;
3763
3764protected:
Howard Hinnant82894812010-09-22 16:48:34 +00003765 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003766 ~messages() {}
3767
3768 virtual catalog do_open(const basic_string<char>&, const locale&) const;
3769 virtual string_type do_get(catalog, int __set, int __msgid,
3770 const string_type& __dflt) const;
3771 virtual void do_close(catalog) const;
3772};
3773
3774template <class _CharT>
3775locale::id
3776messages<_CharT>::id;
3777
3778template <class _CharT>
3779typename messages<_CharT>::catalog
3780messages<_CharT>::do_open(const basic_string<char>& __nm, const locale&) const
3781{
Howard Hinnantb2080c72011-02-25 00:51:08 +00003782 catalog __cat = reinterpret_cast<catalog>(catopen(__nm.c_str(), NL_CAT_LOCALE));
3783 if (__cat != -1)
3784 __cat = static_cast<catalog>((static_cast<size_t>(__cat) >> 1));
3785 return __cat;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003786}
3787
3788template <class _CharT>
3789typename messages<_CharT>::string_type
3790messages<_CharT>::do_get(catalog __c, int __set, int __msgid,
3791 const string_type& __dflt) const
3792{
3793 string __ndflt;
3794 __narrow_to_utf8<sizeof(char_type)*__CHAR_BIT__>()(back_inserter(__ndflt),
3795 __dflt.c_str(),
3796 __dflt.c_str() + __dflt.size());
Howard Hinnantb2080c72011-02-25 00:51:08 +00003797 if (__c != -1)
3798 __c <<= 1;
3799 nl_catd __cat = reinterpret_cast<nl_catd>(__c);
3800 char* __n = catgets(__cat, __set, __msgid, __ndflt.c_str());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003801 string_type __w;
3802 __widen_from_utf8<sizeof(char_type)*__CHAR_BIT__>()(back_inserter(__w),
3803 __n, __n + strlen(__n));
3804 return __w;
3805}
3806
3807template <class _CharT>
3808void
3809messages<_CharT>::do_close(catalog __c) const
3810{
Howard Hinnantb2080c72011-02-25 00:51:08 +00003811 if (__c != -1)
3812 __c <<= 1;
3813 nl_catd __cat = reinterpret_cast<nl_catd>(__c);
3814 catclose(__cat);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003815}
3816
3817extern template class messages<char>;
3818extern template class messages<wchar_t>;
3819
3820template <class _CharT>
Howard Hinnant82894812010-09-22 16:48:34 +00003821class _LIBCPP_VISIBLE messages_byname
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003822 : public messages<_CharT>
3823{
3824public:
3825 typedef messages_base::catalog catalog;
3826 typedef basic_string<_CharT> string_type;
3827
3828 _LIBCPP_ALWAYS_INLINE
3829 explicit messages_byname(const char*, size_t __refs = 0)
3830 : messages<_CharT>(__refs) {}
3831
3832 _LIBCPP_ALWAYS_INLINE
3833 explicit messages_byname(const string&, size_t __refs = 0)
3834 : messages<_CharT>(__refs) {}
3835
3836protected:
Howard Hinnant82894812010-09-22 16:48:34 +00003837 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003838 ~messages_byname() {}
3839};
3840
3841extern template class messages_byname<char>;
3842extern template class messages_byname<wchar_t>;
3843
Howard Hinnantd23b4642010-05-31 20:58:54 +00003844template<class _Codecvt, class _Elem = wchar_t,
3845 class _Wide_alloc = allocator<_Elem>,
3846 class _Byte_alloc = allocator<char> >
Howard Hinnant82894812010-09-22 16:48:34 +00003847class _LIBCPP_VISIBLE wstring_convert
Howard Hinnantd23b4642010-05-31 20:58:54 +00003848{
3849public:
3850 typedef basic_string<char, char_traits<char>, _Byte_alloc> byte_string;
3851 typedef basic_string<_Elem, char_traits<_Elem>, _Wide_alloc> wide_string;
3852 typedef typename _Codecvt::state_type state_type;
3853 typedef typename wide_string::traits_type::int_type int_type;
3854
3855private:
3856 byte_string __byte_err_string_;
3857 wide_string __wide_err_string_;
3858 _Codecvt* __cvtptr_;
3859 state_type __cvtstate_;
3860 size_t __cvtcount_;
3861
3862 wstring_convert(const wstring_convert& __wc);
3863 wstring_convert& operator=(const wstring_convert& __wc);
3864public:
3865 wstring_convert(_Codecvt* __pcvt = new _Codecvt);
3866 wstring_convert(_Codecvt* __pcvt, state_type __state);
3867 wstring_convert(const byte_string& __byte_err,
3868 const wide_string& __wide_err = wide_string());
Howard Hinnant73d21a42010-09-04 23:28:19 +00003869#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantd23b4642010-05-31 20:58:54 +00003870 wstring_convert(wstring_convert&& __wc);
3871#endif
3872 ~wstring_convert();
3873
Howard Hinnant82894812010-09-22 16:48:34 +00003874 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003875 wide_string from_bytes(char __byte)
3876 {return from_bytes(&__byte, &__byte+1);}
Howard Hinnant82894812010-09-22 16:48:34 +00003877 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003878 wide_string from_bytes(const char* __ptr)
3879 {return from_bytes(__ptr, __ptr + char_traits<char>::length(__ptr));}
Howard Hinnant82894812010-09-22 16:48:34 +00003880 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003881 wide_string from_bytes(const byte_string& __str)
3882 {return from_bytes(__str.data(), __str.data() + __str.size());}
3883 wide_string from_bytes(const char* __first, const char* __last);
3884
Howard Hinnant82894812010-09-22 16:48:34 +00003885 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003886 byte_string to_bytes(_Elem __wchar)
3887 {return to_bytes(&__wchar, &__wchar+1);}
Howard Hinnant82894812010-09-22 16:48:34 +00003888 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003889 byte_string to_bytes(const _Elem* __wptr)
3890 {return to_bytes(__wptr, __wptr + char_traits<_Elem>::length(__wptr));}
Howard Hinnant82894812010-09-22 16:48:34 +00003891 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003892 byte_string to_bytes(const wide_string& __wstr)
3893 {return to_bytes(__wstr.data(), __wstr.data() + __wstr.size());}
3894 byte_string to_bytes(const _Elem* __first, const _Elem* __last);
3895
Howard Hinnant82894812010-09-22 16:48:34 +00003896 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003897 size_t converted() const {return __cvtcount_;}
Howard Hinnant82894812010-09-22 16:48:34 +00003898 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003899 state_type state() const {return __cvtstate_;}
3900};
3901
3902template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Howard Hinnant82894812010-09-22 16:48:34 +00003903inline _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003904wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3905 wstring_convert(_Codecvt* __pcvt)
3906 : __cvtptr_(__pcvt), __cvtstate_(), __cvtcount_(0)
3907{
3908}
3909
3910template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Howard Hinnant82894812010-09-22 16:48:34 +00003911inline _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003912wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3913 wstring_convert(_Codecvt* __pcvt, state_type __state)
3914 : __cvtptr_(__pcvt), __cvtstate_(__state), __cvtcount_(0)
3915{
3916}
3917
3918template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3919wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3920 wstring_convert(const byte_string& __byte_err, const wide_string& __wide_err)
3921 : __byte_err_string_(__byte_err), __wide_err_string_(__wide_err),
3922 __cvtstate_(), __cvtcount_(0)
3923{
3924 __cvtptr_ = new _Codecvt;
3925}
3926
Howard Hinnant73d21a42010-09-04 23:28:19 +00003927#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantd23b4642010-05-31 20:58:54 +00003928
3929template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Howard Hinnant82894812010-09-22 16:48:34 +00003930inline _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003931wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3932 wstring_convert(wstring_convert&& __wc)
Howard Hinnant0949eed2011-06-30 21:18:19 +00003933 : __byte_err_string_(_VSTD::move(__wc.__byte_err_string_)),
3934 __wide_err_string_(_VSTD::move(__wc.__wide_err_string_)),
Howard Hinnantd23b4642010-05-31 20:58:54 +00003935 __cvtptr_(__wc.__cvtptr_),
3936 __cvtstate_(__wc.__cvtstate_), __cvtcount_(__wc.__cvtstate_)
3937{
3938 __wc.__cvtptr_ = nullptr;
3939}
3940
Howard Hinnantbfd55302010-09-04 23:46:48 +00003941#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantd23b4642010-05-31 20:58:54 +00003942
3943template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3944wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::~wstring_convert()
3945{
3946 delete __cvtptr_;
3947}
3948
3949template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3950typename wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::wide_string
3951wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3952 from_bytes(const char* __frm, const char* __frm_end)
3953{
3954 __cvtcount_ = 0;
3955 if (__cvtptr_ != nullptr)
3956 {
3957 wide_string __ws(2*(__frm_end - __frm), _Elem());
3958 __ws.resize(__ws.capacity());
3959 codecvt_base::result __r = codecvt_base::ok;
3960 state_type __st = __cvtstate_;
3961 if (__frm != __frm_end)
3962 {
3963 _Elem* __to = &__ws[0];
3964 _Elem* __to_end = __to + __ws.size();
3965 const char* __frm_nxt;
3966 do
3967 {
3968 _Elem* __to_nxt;
3969 __r = __cvtptr_->in(__st, __frm, __frm_end, __frm_nxt,
3970 __to, __to_end, __to_nxt);
3971 __cvtcount_ += __frm_nxt - __frm;
3972 if (__frm_nxt == __frm)
3973 {
3974 __r = codecvt_base::error;
3975 }
3976 else if (__r == codecvt_base::noconv)
3977 {
3978 __ws.resize(__to - &__ws[0]);
3979 // This only gets executed if _Elem is char
3980 __ws.append((const _Elem*)__frm, (const _Elem*)__frm_end);
3981 __frm = __frm_nxt;
3982 __r = codecvt_base::ok;
3983 }
3984 else if (__r == codecvt_base::ok)
3985 {
3986 __ws.resize(__to_nxt - &__ws[0]);
3987 __frm = __frm_nxt;
3988 }
3989 else if (__r == codecvt_base::partial)
3990 {
3991 ptrdiff_t __s = __to_nxt - &__ws[0];
3992 __ws.resize(2 * __s);
3993 __to = &__ws[0] + __s;
3994 __to_end = &__ws[0] + __ws.size();
3995 __frm = __frm_nxt;
3996 }
3997 } while (__r == codecvt_base::partial && __frm_nxt < __frm_end);
3998 }
3999 if (__r == codecvt_base::ok)
4000 return __ws;
4001 }
Howard Hinnantd4444702010-08-11 17:04:31 +00004002#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00004003 if (__wide_err_string_.empty())
4004 throw range_error("wstring_convert: from_bytes error");
Howard Hinnant324bb032010-08-22 00:02:43 +00004005#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00004006 return __wide_err_string_;
4007}
4008
4009template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
4010typename wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::byte_string
4011wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
4012 to_bytes(const _Elem* __frm, const _Elem* __frm_end)
4013{
4014 __cvtcount_ = 0;
4015 if (__cvtptr_ != nullptr)
4016 {
4017 byte_string __bs(2*(__frm_end - __frm), char());
4018 __bs.resize(__bs.capacity());
4019 codecvt_base::result __r = codecvt_base::ok;
4020 state_type __st = __cvtstate_;
4021 if (__frm != __frm_end)
4022 {
4023 char* __to = &__bs[0];
4024 char* __to_end = __to + __bs.size();
4025 const _Elem* __frm_nxt;
4026 do
4027 {
4028 char* __to_nxt;
4029 __r = __cvtptr_->out(__st, __frm, __frm_end, __frm_nxt,
4030 __to, __to_end, __to_nxt);
4031 __cvtcount_ += __frm_nxt - __frm;
4032 if (__frm_nxt == __frm)
4033 {
4034 __r = codecvt_base::error;
4035 }
4036 else if (__r == codecvt_base::noconv)
4037 {
4038 __bs.resize(__to - &__bs[0]);
4039 // This only gets executed if _Elem is char
4040 __bs.append((const char*)__frm, (const char*)__frm_end);
4041 __frm = __frm_nxt;
4042 __r = codecvt_base::ok;
4043 }
4044 else if (__r == codecvt_base::ok)
4045 {
4046 __bs.resize(__to_nxt - &__bs[0]);
4047 __frm = __frm_nxt;
4048 }
4049 else if (__r == codecvt_base::partial)
4050 {
4051 ptrdiff_t __s = __to_nxt - &__bs[0];
4052 __bs.resize(2 * __s);
4053 __to = &__bs[0] + __s;
4054 __to_end = &__bs[0] + __bs.size();
4055 __frm = __frm_nxt;
4056 }
4057 } while (__r == codecvt_base::partial && __frm_nxt < __frm_end);
4058 }
4059 if (__r == codecvt_base::ok)
4060 {
4061 size_t __s = __bs.size();
4062 __bs.resize(__bs.capacity());
4063 char* __to = &__bs[0] + __s;
4064 char* __to_end = __to + __bs.size();
4065 do
4066 {
4067 char* __to_nxt;
4068 __r = __cvtptr_->unshift(__st, __to, __to_end, __to_nxt);
4069 if (__r == codecvt_base::noconv)
4070 {
4071 __bs.resize(__to - &__bs[0]);
4072 __r = codecvt_base::ok;
4073 }
4074 else if (__r == codecvt_base::ok)
4075 {
4076 __bs.resize(__to_nxt - &__bs[0]);
4077 }
4078 else if (__r == codecvt_base::partial)
4079 {
4080 ptrdiff_t __s = __to_nxt - &__bs[0];
4081 __bs.resize(2 * __s);
4082 __to = &__bs[0] + __s;
4083 __to_end = &__bs[0] + __bs.size();
4084 }
4085 } while (__r == codecvt_base::partial);
4086 if (__r == codecvt_base::ok)
4087 return __bs;
4088 }
4089 }
Howard Hinnantd4444702010-08-11 17:04:31 +00004090#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00004091 if (__byte_err_string_.empty())
4092 throw range_error("wstring_convert: to_bytes error");
Howard Hinnant324bb032010-08-22 00:02:43 +00004093#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00004094 return __byte_err_string_;
4095}
4096
4097template <class _Codecvt, class _Elem = wchar_t, class _Tr = char_traits<_Elem> >
Howard Hinnant82894812010-09-22 16:48:34 +00004098class _LIBCPP_VISIBLE wbuffer_convert
Howard Hinnantd23b4642010-05-31 20:58:54 +00004099 : public basic_streambuf<_Elem, _Tr>
4100{
4101public:
4102 // types:
4103 typedef _Elem char_type;
4104 typedef _Tr traits_type;
4105 typedef typename traits_type::int_type int_type;
4106 typedef typename traits_type::pos_type pos_type;
4107 typedef typename traits_type::off_type off_type;
4108 typedef typename _Codecvt::state_type state_type;
4109
4110private:
Howard Hinnant4b53f502010-06-01 20:09:18 +00004111 char* __extbuf_;
4112 const char* __extbufnext_;
4113 const char* __extbufend_;
4114 char __extbuf_min_[8];
4115 size_t __ebs_;
4116 char_type* __intbuf_;
4117 size_t __ibs_;
Howard Hinnantd23b4642010-05-31 20:58:54 +00004118 streambuf* __bufptr_;
Howard Hinnant4b53f502010-06-01 20:09:18 +00004119 _Codecvt* __cv_;
4120 state_type __st_;
4121 ios_base::openmode __cm_;
4122 bool __owns_eb_;
4123 bool __owns_ib_;
4124 bool __always_noconv_;
Howard Hinnantd23b4642010-05-31 20:58:54 +00004125
Howard Hinnant4b53f502010-06-01 20:09:18 +00004126 wbuffer_convert(const wbuffer_convert&);
4127 wbuffer_convert& operator=(const wbuffer_convert&);
Howard Hinnantd23b4642010-05-31 20:58:54 +00004128public:
4129 wbuffer_convert(streambuf* __bytebuf = 0, _Codecvt* __pcvt = new _Codecvt,
Howard Hinnant4b53f502010-06-01 20:09:18 +00004130 state_type __state = state_type());
4131 ~wbuffer_convert();
Howard Hinnantd23b4642010-05-31 20:58:54 +00004132
Howard Hinnant82894812010-09-22 16:48:34 +00004133 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantd23b4642010-05-31 20:58:54 +00004134 streambuf* rdbuf() const {return __bufptr_;}
Howard Hinnant82894812010-09-22 16:48:34 +00004135 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantd23b4642010-05-31 20:58:54 +00004136 streambuf* rdbuf(streambuf* __bytebuf)
4137 {
4138 streambuf* __r = __bufptr_;
4139 __bufptr_ = __bytebuf;
4140 return __r;
4141 }
4142
Howard Hinnant82894812010-09-22 16:48:34 +00004143 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant4b53f502010-06-01 20:09:18 +00004144 state_type state() const {return __st_;}
Howard Hinnantd23b4642010-05-31 20:58:54 +00004145
4146protected:
Howard Hinnant4b53f502010-06-01 20:09:18 +00004147 virtual int_type underflow();
4148 virtual int_type pbackfail(int_type __c = traits_type::eof());
Howard Hinnantd23b4642010-05-31 20:58:54 +00004149 virtual int_type overflow (int_type __c = traits_type::eof());
Howard Hinnant4b53f502010-06-01 20:09:18 +00004150 virtual basic_streambuf<char_type, traits_type>* setbuf(char_type* __s,
4151 streamsize __n);
4152 virtual pos_type seekoff(off_type __off, ios_base::seekdir __way,
4153 ios_base::openmode __wch = ios_base::in | ios_base::out);
4154 virtual pos_type seekpos(pos_type __sp,
4155 ios_base::openmode __wch = ios_base::in | ios_base::out);
4156 virtual int sync();
4157
4158private:
4159 bool __read_mode();
4160 void __write_mode();
4161 wbuffer_convert* __close();
Howard Hinnantd23b4642010-05-31 20:58:54 +00004162};
4163
4164template <class _Codecvt, class _Elem, class _Tr>
Howard Hinnant4b53f502010-06-01 20:09:18 +00004165wbuffer_convert<_Codecvt, _Elem, _Tr>::
4166 wbuffer_convert(streambuf* __bytebuf, _Codecvt* __pcvt, state_type __state)
4167 : __extbuf_(0),
4168 __extbufnext_(0),
4169 __extbufend_(0),
4170 __ebs_(0),
4171 __intbuf_(0),
4172 __ibs_(0),
4173 __bufptr_(__bytebuf),
4174 __cv_(__pcvt),
4175 __st_(__state),
4176 __cm_(0),
4177 __owns_eb_(false),
4178 __owns_ib_(false),
4179 __always_noconv_(__cv_ ? __cv_->always_noconv() : false)
4180{
4181 setbuf(0, 4096);
4182}
4183
4184template <class _Codecvt, class _Elem, class _Tr>
4185wbuffer_convert<_Codecvt, _Elem, _Tr>::~wbuffer_convert()
4186{
4187 __close();
4188 delete __cv_;
4189 if (__owns_eb_)
4190 delete [] __extbuf_;
4191 if (__owns_ib_)
4192 delete [] __intbuf_;
4193}
4194
4195template <class _Codecvt, class _Elem, class _Tr>
4196typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
4197wbuffer_convert<_Codecvt, _Elem, _Tr>::underflow()
4198{
4199 if (__cv_ == 0 || __bufptr_ == 0)
4200 return traits_type::eof();
4201 bool __initial = __read_mode();
4202 char_type __1buf;
4203 if (this->gptr() == 0)
4204 this->setg(&__1buf, &__1buf+1, &__1buf+1);
4205 const size_t __unget_sz = __initial ? 0 : min<size_t>((this->egptr() - this->eback()) / 2, 4);
4206 int_type __c = traits_type::eof();
4207 if (this->gptr() == this->egptr())
4208 {
4209 memmove(this->eback(), this->egptr() - __unget_sz, __unget_sz * sizeof(char_type));
4210 if (__always_noconv_)
4211 {
4212 streamsize __nmemb = static_cast<streamsize>(this->egptr() - this->eback() - __unget_sz);
4213 __nmemb = __bufptr_->sgetn((char*)this->eback() + __unget_sz, __nmemb);
4214 if (__nmemb != 0)
4215 {
4216 this->setg(this->eback(),
4217 this->eback() + __unget_sz,
4218 this->eback() + __unget_sz + __nmemb);
4219 __c = *this->gptr();
4220 }
4221 }
4222 else
4223 {
4224 memmove(__extbuf_, __extbufnext_, __extbufend_ - __extbufnext_);
4225 __extbufnext_ = __extbuf_ + (__extbufend_ - __extbufnext_);
4226 __extbufend_ = __extbuf_ + (__extbuf_ == __extbuf_min_ ? sizeof(__extbuf_min_) : __ebs_);
Howard Hinnant0949eed2011-06-30 21:18:19 +00004227 streamsize __nmemb = _VSTD::min(static_cast<streamsize>(this->egptr() - this->eback() - __unget_sz),
Howard Hinnant4b53f502010-06-01 20:09:18 +00004228 static_cast<streamsize>(__extbufend_ - __extbufnext_));
4229 codecvt_base::result __r;
4230 state_type __svs = __st_;
4231 streamsize __nr = __bufptr_->sgetn(const_cast<char*>(__extbufnext_), __nmemb);
4232 if (__nr != 0)
4233 {
4234 __extbufend_ = __extbufnext_ + __nr;
4235 char_type* __inext;
4236 __r = __cv_->in(__st_, __extbuf_, __extbufend_, __extbufnext_,
4237 this->eback() + __unget_sz,
4238 this->egptr(), __inext);
4239 if (__r == codecvt_base::noconv)
4240 {
4241 this->setg((char_type*)__extbuf_, (char_type*)__extbuf_, (char_type*)__extbufend_);
4242 __c = *this->gptr();
4243 }
4244 else if (__inext != this->eback() + __unget_sz)
4245 {
4246 this->setg(this->eback(), this->eback() + __unget_sz, __inext);
4247 __c = *this->gptr();
4248 }
4249 }
4250 }
4251 }
4252 else
4253 __c = *this->gptr();
4254 if (this->eback() == &__1buf)
4255 this->setg(0, 0, 0);
4256 return __c;
4257}
4258
4259template <class _Codecvt, class _Elem, class _Tr>
4260typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
4261wbuffer_convert<_Codecvt, _Elem, _Tr>::pbackfail(int_type __c)
4262{
4263 if (__cv_ != 0 && __bufptr_ != 0 && this->eback() < this->gptr())
4264 {
4265 if (traits_type::eq_int_type(__c, traits_type::eof()))
4266 {
4267 this->gbump(-1);
4268 return traits_type::not_eof(__c);
4269 }
4270 if (traits_type::eq(traits_type::to_char_type(__c), this->gptr()[-1]))
4271 {
4272 this->gbump(-1);
4273 *this->gptr() = traits_type::to_char_type(__c);
4274 return __c;
4275 }
4276 }
4277 return traits_type::eof();
4278}
4279
4280template <class _Codecvt, class _Elem, class _Tr>
Howard Hinnantd23b4642010-05-31 20:58:54 +00004281typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
4282wbuffer_convert<_Codecvt, _Elem, _Tr>::overflow(int_type __c)
4283{
Howard Hinnant4b53f502010-06-01 20:09:18 +00004284 if (__cv_ == 0 || __bufptr_ == 0)
4285 return traits_type::eof();
4286 __write_mode();
4287 char_type __1buf;
4288 char_type* __pb_save = this->pbase();
4289 char_type* __epb_save = this->epptr();
4290 if (!traits_type::eq_int_type(__c, traits_type::eof()))
4291 {
4292 if (this->pptr() == 0)
4293 this->setp(&__1buf, &__1buf+1);
4294 *this->pptr() = traits_type::to_char_type(__c);
4295 this->pbump(1);
4296 }
4297 if (this->pptr() != this->pbase())
4298 {
4299 if (__always_noconv_)
4300 {
4301 streamsize __nmemb = static_cast<streamsize>(this->pptr() - this->pbase());
4302 if (__bufptr_->sputn((const char*)this->pbase(), __nmemb) != __nmemb)
4303 return traits_type::eof();
4304 }
4305 else
4306 {
4307 char* __extbe = __extbuf_;
4308 codecvt_base::result __r;
4309 do
4310 {
4311 const char_type* __e;
4312 __r = __cv_->out(__st_, this->pbase(), this->pptr(), __e,
4313 __extbuf_, __extbuf_ + __ebs_, __extbe);
4314 if (__e == this->pbase())
4315 return traits_type::eof();
4316 if (__r == codecvt_base::noconv)
4317 {
4318 streamsize __nmemb = static_cast<size_t>(this->pptr() - this->pbase());
4319 if (__bufptr_->sputn((const char*)this->pbase(), __nmemb) != __nmemb)
4320 return traits_type::eof();
4321 }
4322 else if (__r == codecvt_base::ok || __r == codecvt_base::partial)
4323 {
4324 streamsize __nmemb = static_cast<size_t>(__extbe - __extbuf_);
4325 if (__bufptr_->sputn(__extbuf_, __nmemb) != __nmemb)
4326 return traits_type::eof();
4327 if (__r == codecvt_base::partial)
4328 {
4329 this->setp((char_type*)__e, this->pptr());
4330 this->pbump(this->epptr() - this->pbase());
4331 }
4332 }
4333 else
4334 return traits_type::eof();
4335 } while (__r == codecvt_base::partial);
4336 }
4337 this->setp(__pb_save, __epb_save);
4338 }
4339 return traits_type::not_eof(__c);
4340}
4341
4342template <class _Codecvt, class _Elem, class _Tr>
4343basic_streambuf<_Elem, _Tr>*
4344wbuffer_convert<_Codecvt, _Elem, _Tr>::setbuf(char_type* __s, streamsize __n)
4345{
4346 this->setg(0, 0, 0);
4347 this->setp(0, 0);
4348 if (__owns_eb_)
4349 delete [] __extbuf_;
4350 if (__owns_ib_)
4351 delete [] __intbuf_;
4352 __ebs_ = __n;
4353 if (__ebs_ > sizeof(__extbuf_min_))
4354 {
4355 if (__always_noconv_ && __s)
4356 {
4357 __extbuf_ = (char*)__s;
4358 __owns_eb_ = false;
4359 }
4360 else
4361 {
4362 __extbuf_ = new char[__ebs_];
4363 __owns_eb_ = true;
4364 }
4365 }
4366 else
4367 {
4368 __extbuf_ = __extbuf_min_;
4369 __ebs_ = sizeof(__extbuf_min_);
4370 __owns_eb_ = false;
4371 }
4372 if (!__always_noconv_)
4373 {
4374 __ibs_ = max<streamsize>(__n, sizeof(__extbuf_min_));
4375 if (__s && __ibs_ >= sizeof(__extbuf_min_))
4376 {
4377 __intbuf_ = __s;
4378 __owns_ib_ = false;
4379 }
4380 else
4381 {
4382 __intbuf_ = new char_type[__ibs_];
4383 __owns_ib_ = true;
4384 }
4385 }
4386 else
4387 {
4388 __ibs_ = 0;
4389 __intbuf_ = 0;
4390 __owns_ib_ = false;
4391 }
4392 return this;
4393}
4394
4395template <class _Codecvt, class _Elem, class _Tr>
4396typename wbuffer_convert<_Codecvt, _Elem, _Tr>::pos_type
4397wbuffer_convert<_Codecvt, _Elem, _Tr>::seekoff(off_type __off, ios_base::seekdir __way,
4398 ios_base::openmode __om)
4399{
4400 int __width = __cv_->encoding();
4401 if (__cv_ == 0 || __bufptr_ == 0 || (__width <= 0 && __off != 0) || sync())
4402 return pos_type(off_type(-1));
4403 // __width > 0 || __off == 0
4404 switch (__way)
4405 {
4406 case ios_base::beg:
4407 break;
4408 case ios_base::cur:
4409 break;
4410 case ios_base::end:
4411 break;
4412 default:
4413 return pos_type(off_type(-1));
4414 }
4415 pos_type __r = __bufptr_->pubseekoff(__width * __off, __way, __om);
4416 __r.state(__st_);
4417 return __r;
4418}
4419
4420template <class _Codecvt, class _Elem, class _Tr>
4421typename wbuffer_convert<_Codecvt, _Elem, _Tr>::pos_type
4422wbuffer_convert<_Codecvt, _Elem, _Tr>::seekpos(pos_type __sp, ios_base::openmode __wch)
4423{
4424 if (__cv_ == 0 || __bufptr_ == 0 || sync())
4425 return pos_type(off_type(-1));
4426 if (__bufptr_->pubseekpos(__sp, __wch) == pos_type(off_type(-1)))
4427 return pos_type(off_type(-1));
4428 return __sp;
4429}
4430
4431template <class _Codecvt, class _Elem, class _Tr>
4432int
4433wbuffer_convert<_Codecvt, _Elem, _Tr>::sync()
4434{
4435 if (__cv_ == 0 || __bufptr_ == 0)
4436 return 0;
4437 if (__cm_ & ios_base::out)
4438 {
4439 if (this->pptr() != this->pbase())
4440 if (overflow() == traits_type::eof())
4441 return -1;
4442 codecvt_base::result __r;
4443 do
4444 {
4445 char* __extbe;
4446 __r = __cv_->unshift(__st_, __extbuf_, __extbuf_ + __ebs_, __extbe);
4447 streamsize __nmemb = static_cast<streamsize>(__extbe - __extbuf_);
4448 if (__bufptr_->sputn(__extbuf_, __nmemb) != __nmemb)
4449 return -1;
4450 } while (__r == codecvt_base::partial);
4451 if (__r == codecvt_base::error)
4452 return -1;
4453 if (__bufptr_->pubsync())
4454 return -1;
4455 }
4456 else if (__cm_ & ios_base::in)
4457 {
4458 off_type __c;
4459 if (__always_noconv_)
4460 __c = this->egptr() - this->gptr();
4461 else
4462 {
4463 int __width = __cv_->encoding();
4464 __c = __extbufend_ - __extbufnext_;
4465 if (__width > 0)
4466 __c += __width * (this->egptr() - this->gptr());
4467 else
4468 {
4469 if (this->gptr() != this->egptr())
4470 {
4471 reverse(this->gptr(), this->egptr());
4472 codecvt_base::result __r;
4473 const char_type* __e = this->gptr();
4474 char* __extbe;
4475 do
4476 {
4477 __r = __cv_->out(__st_, __e, this->egptr(), __e,
4478 __extbuf_, __extbuf_ + __ebs_, __extbe);
4479 switch (__r)
4480 {
4481 case codecvt_base::noconv:
4482 __c += this->egptr() - this->gptr();
4483 break;
4484 case codecvt_base::ok:
4485 case codecvt_base::partial:
4486 __c += __extbe - __extbuf_;
4487 break;
4488 default:
4489 return -1;
4490 }
4491 } while (__r == codecvt_base::partial);
4492 }
4493 }
4494 }
4495 if (__bufptr_->pubseekoff(-__c, ios_base::cur, __cm_) == pos_type(off_type(-1)))
4496 return -1;
4497 this->setg(0, 0, 0);
4498 __cm_ = 0;
4499 }
4500 return 0;
4501}
4502
4503template <class _Codecvt, class _Elem, class _Tr>
4504bool
4505wbuffer_convert<_Codecvt, _Elem, _Tr>::__read_mode()
4506{
4507 if (!(__cm_ & ios_base::in))
4508 {
4509 this->setp(0, 0);
4510 if (__always_noconv_)
4511 this->setg((char_type*)__extbuf_,
4512 (char_type*)__extbuf_ + __ebs_,
4513 (char_type*)__extbuf_ + __ebs_);
4514 else
4515 this->setg(__intbuf_, __intbuf_ + __ibs_, __intbuf_ + __ibs_);
4516 __cm_ = ios_base::in;
4517 return true;
4518 }
4519 return false;
4520}
4521
4522template <class _Codecvt, class _Elem, class _Tr>
4523void
4524wbuffer_convert<_Codecvt, _Elem, _Tr>::__write_mode()
4525{
4526 if (!(__cm_ & ios_base::out))
4527 {
4528 this->setg(0, 0, 0);
4529 if (__ebs_ > sizeof(__extbuf_min_))
4530 {
4531 if (__always_noconv_)
4532 this->setp((char_type*)__extbuf_,
4533 (char_type*)__extbuf_ + (__ebs_ - 1));
4534 else
4535 this->setp(__intbuf_, __intbuf_ + (__ibs_ - 1));
4536 }
4537 else
4538 this->setp(0, 0);
4539 __cm_ = ios_base::out;
4540 }
4541}
4542
4543template <class _Codecvt, class _Elem, class _Tr>
4544wbuffer_convert<_Codecvt, _Elem, _Tr>*
4545wbuffer_convert<_Codecvt, _Elem, _Tr>::__close()
4546{
4547 wbuffer_convert* __rt = 0;
4548 if (__cv_ != 0 && __bufptr_ != 0)
4549 {
4550 __rt = this;
4551 if ((__cm_ & ios_base::out) && sync())
4552 __rt = 0;
4553 }
4554 return __rt;
Howard Hinnantd23b4642010-05-31 20:58:54 +00004555}
4556
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004557_LIBCPP_END_NAMESPACE_STD
4558
4559#endif // _LIBCPP_LOCALE