blob: f9e849b16955b1cd5db555fcb3fb9be81d87382e [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
Howard Hinnantadff4892010-05-24 17:49:41 +0000195// OSX has nice foo_l() functions that let you turn off use of the global
196// locale. Linux, not so much. The following functions avoid the locale when
197// that's possible and otherwise do the wrong thing. FIXME.
198#if __APPLE__
199
200template <class _Tp>
Howard Hinnant82894812010-09-22 16:48:34 +0000201inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantadff4892010-05-24 17:49:41 +0000202int
203__nolocale_sprintf(char* __restrict __str,
204 const char* __restrict __format, _Tp __v)
205{
206 return sprintf_l(__str, 0, __format, __v);
207}
208
209template <class _Tp>
Howard Hinnant82894812010-09-22 16:48:34 +0000210inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantadff4892010-05-24 17:49:41 +0000211int
212__nolocale_snprintf(char* __restrict __str, size_t __size,
213 const char* __restrict __format, _Tp __v)
214{
215 return snprintf_l(__str, __size, 0, __format, __v);
216}
217
218template <class _Tp>
Howard Hinnant82894812010-09-22 16:48:34 +0000219inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantadff4892010-05-24 17:49:41 +0000220int
221__nolocale_snprintf(char* __restrict __str, size_t __size,
222 const char* __restrict __format, int __prec, _Tp __v)
223{
224 return snprintf_l(__str, __size, 0, __format, __prec, __v);
225}
226
227template <class _Tp>
Howard Hinnant82894812010-09-22 16:48:34 +0000228inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantadff4892010-05-24 17:49:41 +0000229int
230__nolocale_asprintf(char** __ret, const char* __restrict __format, _Tp __v)
231{
232 return asprintf_l(__ret, 0, __format, __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, int __prec,
239 _Tp __v)
240{
241 return asprintf_l(__ret, 0, __format, __prec, __v);
242}
243
244template <class _Tp>
Howard Hinnant82894812010-09-22 16:48:34 +0000245inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantadff4892010-05-24 17:49:41 +0000246int
247__nolocale_sscanf(const char* __restrict __str,
248 const char* __restrict __format, _Tp* __v)
249{
250 return sscanf_l(__str, 0, __format, __v);
251}
252
Howard Hinnant82894812010-09-22 16:48:34 +0000253inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantadff4892010-05-24 17:49:41 +0000254int
255__nolocale_isxdigit(int __c)
256{
257 return isxdigit_l(__c, 0);
258}
259
Howard Hinnant82894812010-09-22 16:48:34 +0000260inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantadff4892010-05-24 17:49:41 +0000261int
262__nolocale_isdigit(int __c)
263{
264 return isdigit_l(__c, 0);
265}
266
Howard Hinnant324bb032010-08-22 00:02:43 +0000267#else // __APPLE__
Michael J. Spencer626916f2010-12-10 19:47:54 +0000268inline
269#ifndef _LIBCPP_HAS_NO_ALWAYS_INLINE_VARIADICS
270_LIBCPP_INLINE_VISIBILITY
271#endif
Howard Hinnant82894812010-09-22 16:48:34 +0000272int
Howard Hinnantadff4892010-05-24 17:49:41 +0000273__nolocale_sprintf(char* __restrict __str,
274 const char* __restrict __format, ...)
275{
276 va_list __ap;
277 va_start(__ap, __format);
278 int __result = vsprintf(__str, __format, __ap);
279 va_end(__ap);
280 return __result;
281}
Michael J. Spencer626916f2010-12-10 19:47:54 +0000282inline
283#ifndef _LIBCPP_HAS_NO_ALWAYS_INLINE_VARIADICS
284_LIBCPP_INLINE_VISIBILITY
285#endif
Howard Hinnant82894812010-09-22 16:48:34 +0000286int
Howard Hinnantadff4892010-05-24 17:49:41 +0000287__nolocale_snprintf(char* __restrict __str, size_t __size,
288 const char* __restrict __format, ...)
289{
290 va_list __ap;
291 va_start(__ap, __format);
292 int __result = vsnprintf(__str, __size, __format, __ap);
293 va_end(__ap);
294 return __result;
295}
Michael J. Spencer626916f2010-12-10 19:47:54 +0000296inline
297#ifndef _LIBCPP_HAS_NO_ALWAYS_INLINE_VARIADICS
298_LIBCPP_INLINE_VISIBILITY
299#endif
Howard Hinnant82894812010-09-22 16:48:34 +0000300int
Howard Hinnantadff4892010-05-24 17:49:41 +0000301__nolocale_asprintf(char** __ret,
302 const char* __restrict __format, ...)
303{
304 va_list __ap;
305 va_start(__ap, __format);
306 int __result = vasprintf(__ret, __format, __ap);
307 va_end(__ap);
308 return __result;
309}
Michael J. Spencer626916f2010-12-10 19:47:54 +0000310inline
311#ifndef _LIBCPP_HAS_NO_ALWAYS_INLINE_VARIADICS
312_LIBCPP_INLINE_VISIBILITY
313#endif
Howard Hinnant82894812010-09-22 16:48:34 +0000314int
Howard Hinnantadff4892010-05-24 17:49:41 +0000315__nolocale_sscanf(const char* __restrict __str,
316 const char* __restrict __format, ...)
317{
318 va_list __ap;
319 va_start(__ap, __format);
320 int __result = vsscanf(__str, __format, __ap);
321 va_end(__ap);
322 return __result;
323}
Howard Hinnant82894812010-09-22 16:48:34 +0000324inline _LIBCPP_INLINE_VISIBILITY
325int
Howard Hinnantadff4892010-05-24 17:49:41 +0000326__nolocale_isxdigit(int __c)
327{
328 return isxdigit(__c);
329}
Howard Hinnant82894812010-09-22 16:48:34 +0000330
331inline _LIBCPP_INLINE_VISIBILITY
332int
Howard Hinnantadff4892010-05-24 17:49:41 +0000333__nolocale_isdigit(int __c)
334{
335 return isdigit(__c);
336}
Howard Hinnant324bb032010-08-22 00:02:43 +0000337#endif // __APPLE__
Howard Hinnantadff4892010-05-24 17:49:41 +0000338
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000339// __scan_keyword
340// Scans [__b, __e) until a match is found in the basic_strings range
341// [__kb, __ke) or until it can be shown that there is no match in [__kb, __ke).
342// __b will be incremented (visibly), consuming CharT until a match is found
343// or proved to not exist. A keyword may be "", in which will match anything.
344// If one keyword is a prefix of another, and the next CharT in the input
345// might match another keyword, the algorithm will attempt to find the longest
346// matching keyword. If the longer matching keyword ends up not matching, then
347// no keyword match is found. If no keyword match is found, __ke is returned
348// and failbit is set in __err.
349// Else an iterator pointing to the matching keyword is found. If more than
350// one keyword matches, an iterator to the first matching keyword is returned.
351// If on exit __b == __e, eofbit is set in __err. If __case_senstive is false,
352// __ct is used to force to lower case before comparing characters.
353// Examples:
354// Keywords: "a", "abb"
355// If the input is "a", the first keyword matches and eofbit is set.
356// If the input is "abc", no match is found and "ab" are consumed.
357template <class _InputIterator, class _ForwardIterator, class _Ctype>
358_LIBCPP_HIDDEN
359_ForwardIterator
360__scan_keyword(_InputIterator& __b, _InputIterator __e,
361 _ForwardIterator __kb, _ForwardIterator __ke,
362 const _Ctype& __ct, ios_base::iostate& __err,
363 bool __case_sensitive = true)
364{
365 typedef typename iterator_traits<_InputIterator>::value_type _CharT;
366 size_t __nkw = _STD::distance(__kb, __ke);
367 const unsigned char __doesnt_match = '\0';
368 const unsigned char __might_match = '\1';
369 const unsigned char __does_match = '\2';
370 unsigned char __statbuf[100];
371 unsigned char* __status = __statbuf;
372 unique_ptr<unsigned char, void(*)(void*)> __stat_hold(0, free);
373 if (__nkw > sizeof(__statbuf))
374 {
375 __status = (unsigned char*)malloc(__nkw);
376 if (__status == 0)
377 __throw_bad_alloc();
378 __stat_hold.reset(__status);
379 }
380 size_t __n_might_match = __nkw; // At this point, any keyword might match
381 size_t __n_does_match = 0; // but none of them definitely do
382 // Initialize all statuses to __might_match, except for "" keywords are __does_match
383 unsigned char* __st = __status;
384 for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, ++__st)
385 {
386 if (!__ky->empty())
387 *__st = __might_match;
388 else
389 {
390 *__st = __does_match;
391 --__n_might_match;
392 ++__n_does_match;
393 }
394 }
395 // While there might be a match, test keywords against the next CharT
396 for (size_t __indx = 0; __b != __e && __n_might_match > 0; ++__indx)
397 {
398 // Peek at the next CharT but don't consume it
399 _CharT __c = *__b;
400 if (!__case_sensitive)
401 __c = __ct.toupper(__c);
402 bool __consume = false;
403 // For each keyword which might match, see if the __indx character is __c
404 // If a match if found, consume __c
405 // If a match is found, and that is the last character in the keyword,
406 // then that keyword matches.
407 // If the keyword doesn't match this character, then change the keyword
408 // to doesn't match
409 __st = __status;
410 for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, ++__st)
411 {
412 if (*__st == __might_match)
413 {
414 _CharT __kc = (*__ky)[__indx];
415 if (!__case_sensitive)
416 __kc = __ct.toupper(__kc);
417 if (__c == __kc)
418 {
419 __consume = true;
420 if (__ky->size() == __indx+1)
421 {
422 *__st = __does_match;
423 --__n_might_match;
424 ++__n_does_match;
425 }
426 }
427 else
428 {
429 *__st = __doesnt_match;
430 --__n_might_match;
431 }
432 }
433 }
434 // consume if we matched a character
435 if (__consume)
436 {
437 ++__b;
438 // If we consumed a character and there might be a matched keyword that
439 // was marked matched on a previous iteration, then such keywords
440 // which are now marked as not matching.
441 if (__n_might_match + __n_does_match > 1)
442 {
443 __st = __status;
444 for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, ++__st)
445 {
446 if (*__st == __does_match && __ky->size() != __indx+1)
447 {
448 *__st = __doesnt_match;
449 --__n_does_match;
450 }
451 }
452 }
453 }
454 }
455 // We've exited the loop because we hit eof and/or we have no more "might matches".
456 if (__b == __e)
457 __err |= ios_base::eofbit;
458 // Return the first matching result
459 for (__st = __status; __kb != __ke; ++__kb, ++__st)
460 if (*__st == __does_match)
461 break;
462 if (__kb == __ke)
463 __err |= ios_base::failbit;
464 return __kb;
465}
466
467struct __num_get_base
468{
469 static const int __num_get_buf_sz = 40;
470
471 static int __get_base(ios_base&);
472 static const char __src[33];
473};
474
475void __check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
476 ios_base::iostate& __err);
477
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000478template <class _CharT>
479struct __num_get
480 : protected __num_get_base
481{
482 static string __stage2_int_prep(ios_base& __iob, _CharT* __atoms, _CharT& __thousands_sep);
483 static string __stage2_float_prep(ios_base& __iob, _CharT* __atoms, _CharT& __decimal_point,
484 _CharT& __thousands_sep);
485 static int __stage2_int_loop(_CharT __ct, int __base, char* __a, char*& __a_end,
486 unsigned& __dc, _CharT __thousands_sep, const string& __grouping,
487 unsigned* __g, unsigned*& __g_end, _CharT* __atoms);
488 static int __stage2_float_loop(_CharT __ct, bool& __in_units, char& __exp,
489 char* __a, char*& __a_end,
490 _CharT __decimal_point, _CharT __thousands_sep,
491 const string& __grouping, unsigned* __g,
492 unsigned*& __g_end, unsigned& __dc, _CharT* __atoms);
493};
494
495template <class _CharT>
496string
497__num_get<_CharT>::__stage2_int_prep(ios_base& __iob, _CharT* __atoms, _CharT& __thousands_sep)
498{
499 locale __loc = __iob.getloc();
500 use_facet<ctype<_CharT> >(__loc).widen(__src, __src + 26, __atoms);
501 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
502 __thousands_sep = __np.thousands_sep();
503 return __np.grouping();
504}
505
506template <class _CharT>
507string
508__num_get<_CharT>::__stage2_float_prep(ios_base& __iob, _CharT* __atoms, _CharT& __decimal_point,
509 _CharT& __thousands_sep)
510{
511 locale __loc = __iob.getloc();
512 use_facet<ctype<_CharT> >(__loc).widen(__src, __src + 32, __atoms);
513 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
514 __decimal_point = __np.decimal_point();
515 __thousands_sep = __np.thousands_sep();
516 return __np.grouping();
517}
518
519template <class _CharT>
520int
521__num_get<_CharT>::__stage2_int_loop(_CharT __ct, int __base, char* __a, char*& __a_end,
522 unsigned& __dc, _CharT __thousands_sep, const string& __grouping,
523 unsigned* __g, unsigned*& __g_end, _CharT* __atoms)
524{
Howard Hinnant80586722011-03-09 01:03:19 +0000525 if (__a_end == __a && (__ct == __atoms[24] || __ct == __atoms[25]))
526 {
527 *__a_end++ = __ct == __atoms[24] ? '+' : '-';
528 __dc = 0;
529 return 0;
530 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000531 if (__ct == __thousands_sep && __grouping.size() != 0)
532 {
533 if (__g_end-__g < __num_get_buf_sz)
534 {
535 *__g_end++ = __dc;
536 __dc = 0;
537 }
538 return 0;
539 }
540 ptrdiff_t __f = find(__atoms, __atoms + 26, __ct) - __atoms;
Howard Hinnant80586722011-03-09 01:03:19 +0000541 if (__f >= 24)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000542 return -1;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000543 switch (__base)
544 {
545 case 8:
546 case 10:
547 if (__f >= __base)
Howard Hinnant80586722011-03-09 01:03:19 +0000548 return -1;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000549 break;
Howard Hinnant80586722011-03-09 01:03:19 +0000550 case 16:
551 if (__f < 22)
552 break;
553 if (__a_end != __a && __a_end - __a <= 2 && __a_end[-1] == '0')
554 {
555 __dc = 0;
556 *__a_end++ = __src[__f];
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000557 return 0;
Howard Hinnant80586722011-03-09 01:03:19 +0000558 }
559 return -1;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000560 }
Howard Hinnant80586722011-03-09 01:03:19 +0000561 if (__a_end-__a < __num_get_buf_sz - 1)
562 *__a_end++ = __src[__f];
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000563 ++__dc;
564 return 0;
565}
566
567template <class _CharT>
568int
569__num_get<_CharT>::__stage2_float_loop(_CharT __ct, bool& __in_units, char& __exp, char* __a, char*& __a_end,
570 _CharT __decimal_point, _CharT __thousands_sep, const string& __grouping,
571 unsigned* __g, unsigned*& __g_end, unsigned& __dc, _CharT* __atoms)
572{
573 if (__ct == __decimal_point)
574 {
575 if (!__in_units)
576 return -1;
577 __in_units = false;
578 *__a_end++ = '.';
579 if (__grouping.size() != 0 && __g_end-__g < __num_get_buf_sz)
580 *__g_end++ = __dc;
581 return 0;
582 }
583 if (__ct == __thousands_sep && __grouping.size() != 0)
584 {
585 if (!__in_units)
586 return -1;
587 if (__g_end-__g < __num_get_buf_sz)
588 {
589 *__g_end++ = __dc;
590 __dc = 0;
591 }
592 return 0;
593 }
594 ptrdiff_t __f = find(__atoms, __atoms + 32, __ct) - __atoms;
595 if (__f >= 32)
596 return -1;
597 char __x = __src[__f];
598 if (__a_end-__a < __num_get_buf_sz - 1)
599 *__a_end++ = __x;
600 if (__x == 'x' || __x == 'X')
601 __exp = 'P';
602 else if ((__x & 0xDF) == __exp)
603 {
604 __in_units = false;
605 if (__grouping.size() != 0 && __g_end-__g < __num_get_buf_sz)
606 *__g_end++ = __dc;
607 }
608 if (__f >= 22)
609 return 0;
610 ++__dc;
611 return 0;
612}
613
614extern template class __num_get<char>;
615extern template class __num_get<wchar_t>;
616
617template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +0000618class _LIBCPP_VISIBLE num_get
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000619 : public locale::facet,
620 private __num_get<_CharT>
621{
622public:
623 typedef _CharT char_type;
624 typedef _InputIterator iter_type;
625
626 _LIBCPP_ALWAYS_INLINE
627 explicit num_get(size_t __refs = 0)
628 : locale::facet(__refs) {}
629
630 _LIBCPP_ALWAYS_INLINE
631 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
632 ios_base::iostate& __err, bool& __v) const
633 {
634 return do_get(__b, __e, __iob, __err, __v);
635 }
636
637 _LIBCPP_ALWAYS_INLINE
638 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
639 ios_base::iostate& __err, long& __v) const
640 {
641 return do_get(__b, __e, __iob, __err, __v);
642 }
643
644 _LIBCPP_ALWAYS_INLINE
645 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
646 ios_base::iostate& __err, long long& __v) const
647 {
648 return do_get(__b, __e, __iob, __err, __v);
649 }
650
651 _LIBCPP_ALWAYS_INLINE
652 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
653 ios_base::iostate& __err, unsigned short& __v) const
654 {
655 return do_get(__b, __e, __iob, __err, __v);
656 }
657
658 _LIBCPP_ALWAYS_INLINE
659 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
660 ios_base::iostate& __err, unsigned int& __v) const
661 {
662 return do_get(__b, __e, __iob, __err, __v);
663 }
664
665 _LIBCPP_ALWAYS_INLINE
666 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
667 ios_base::iostate& __err, unsigned long& __v) const
668 {
669 return do_get(__b, __e, __iob, __err, __v);
670 }
671
672 _LIBCPP_ALWAYS_INLINE
673 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
674 ios_base::iostate& __err, unsigned long long& __v) const
675 {
676 return do_get(__b, __e, __iob, __err, __v);
677 }
678
679 _LIBCPP_ALWAYS_INLINE
680 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
681 ios_base::iostate& __err, float& __v) const
682 {
683 return do_get(__b, __e, __iob, __err, __v);
684 }
685
686 _LIBCPP_ALWAYS_INLINE
687 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
688 ios_base::iostate& __err, double& __v) const
689 {
690 return do_get(__b, __e, __iob, __err, __v);
691 }
692
693 _LIBCPP_ALWAYS_INLINE
694 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
695 ios_base::iostate& __err, long double& __v) const
696 {
697 return do_get(__b, __e, __iob, __err, __v);
698 }
699
700 _LIBCPP_ALWAYS_INLINE
701 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
702 ios_base::iostate& __err, void*& __v) const
703 {
704 return do_get(__b, __e, __iob, __err, __v);
705 }
706
707 static locale::id id;
708
709protected:
Howard Hinnant82894812010-09-22 16:48:34 +0000710 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000711 ~num_get() {}
712
713 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
714 ios_base::iostate& __err, bool& __v) const;
715 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
716 ios_base::iostate& __err, long& __v) const;
717 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
718 ios_base::iostate& __err, long long& __v) const;
719 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
720 ios_base::iostate& __err, unsigned short& __v) const;
721 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
722 ios_base::iostate& __err, unsigned int& __v) const;
723 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
724 ios_base::iostate& __err, unsigned long& __v) const;
725 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
726 ios_base::iostate& __err, unsigned long long& __v) const;
727 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
728 ios_base::iostate& __err, float& __v) const;
729 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
730 ios_base::iostate& __err, double& __v) const;
731 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
732 ios_base::iostate& __err, long double& __v) const;
733 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
734 ios_base::iostate& __err, void*& __v) const;
735};
736
737template <class _CharT, class _InputIterator>
738locale::id
739num_get<_CharT, _InputIterator>::id;
740
741template <class _Tp>
742_Tp
743__num_get_signed_integral(const char* __a, const char* __a_end,
744 ios_base::iostate& __err, int __base)
745{
746 if (__a != __a_end)
747 {
Howard Hinnante7c8da62011-02-25 19:52:41 +0000748 int __save_errno = errno;
749 errno = 0;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000750 char *__p2;
751 long long __ll = strtoll_l(__a, &__p2, __base, 0);
Howard Hinnante7c8da62011-02-25 19:52:41 +0000752 int __current_errno = errno;
753 if (__current_errno == 0)
754 errno = __save_errno;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000755 if (__p2 != __a_end)
756 {
757 __err = ios_base::failbit;
758 return 0;
759 }
Howard Hinnante7c8da62011-02-25 19:52:41 +0000760 else if (__current_errno == ERANGE ||
761 __ll < numeric_limits<_Tp>::min() ||
762 numeric_limits<_Tp>::max() < __ll)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000763 {
764 __err = ios_base::failbit;
Howard Hinnante7c8da62011-02-25 19:52:41 +0000765 if (__ll > 0)
766 return numeric_limits<_Tp>::max();
767 else
768 return numeric_limits<_Tp>::min();
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000769 }
770 return static_cast<_Tp>(__ll);
771 }
772 __err = ios_base::failbit;
773 return 0;
774}
775
776template <class _Tp>
777_Tp
778__num_get_unsigned_integral(const char* __a, const char* __a_end,
779 ios_base::iostate& __err, int __base)
780{
781 if (__a != __a_end)
782 {
Howard Hinnante7c8da62011-02-25 19:52:41 +0000783 if (*__a == '-')
784 {
785 __err = ios_base::failbit;
786 return 0;
787 }
788 int __save_errno = errno;
789 errno = 0;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000790 char *__p2;
791 unsigned long long __ll = strtoull_l(__a, &__p2, __base, 0);
Howard Hinnante7c8da62011-02-25 19:52:41 +0000792 int __current_errno = errno;
793 if (__current_errno == 0)
794 errno = __save_errno;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000795 if (__p2 != __a_end)
796 {
797 __err = ios_base::failbit;
798 return 0;
799 }
Howard Hinnante7c8da62011-02-25 19:52:41 +0000800 else if (__current_errno == ERANGE ||
801 numeric_limits<_Tp>::max() < __ll)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000802 {
803 __err = ios_base::failbit;
804 return numeric_limits<_Tp>::max();
805 }
806 return static_cast<_Tp>(__ll);
807 }
808 __err = ios_base::failbit;
809 return 0;
810}
811
812template <class _Tp>
813_Tp
814__num_get_float(const char* __a, const char* __a_end, ios_base::iostate& __err)
815{
816 if (__a != __a_end)
817 {
818 char *__p2;
819 long double __ld = strtold_l(__a, &__p2, 0);
820 if (__p2 != __a_end)
821 {
822 __err = ios_base::failbit;
823 return 0;
824 }
825 return static_cast<_Tp>(__ld);
826 }
827 __err = ios_base::failbit;
828 return 0;
829}
830
831template <class _CharT, class _InputIterator>
832_InputIterator
833num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
834 ios_base& __iob,
835 ios_base::iostate& __err,
836 bool& __v) const
837{
838 if ((__iob.flags() & ios_base::boolalpha) == 0)
839 {
840 long __lv = -1;
841 __b = do_get(__b, __e, __iob, __err, __lv);
842 switch (__lv)
843 {
844 case 0:
845 __v = false;
846 break;
847 case 1:
848 __v = true;
849 break;
850 default:
851 __v = true;
852 __err = ios_base::failbit;
853 break;
854 }
855 return __b;
856 }
857 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__iob.getloc());
858 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__iob.getloc());
859 typedef typename numpunct<_CharT>::string_type string_type;
860 const string_type __names[2] = {__np.truename(), __np.falsename()};
861 const string_type* __i = __scan_keyword(__b, __e, __names, __names+2,
862 __ct, __err);
863 __v = __i == __names;
864 return __b;
865}
866
867template <class _CharT, class _InputIterator>
868_InputIterator
869num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
870 ios_base& __iob,
871 ios_base::iostate& __err,
872 long& __v) const
873{
874 // Stage 1
875 int __base = this->__get_base(__iob);
876 // Stage 2
877 char_type __atoms[26];
878 char_type __thousands_sep;
879 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
880 char __a[__num_get_base::__num_get_buf_sz] = {0};
881 char* __a_end = __a;
882 unsigned __g[__num_get_base::__num_get_buf_sz];
883 unsigned* __g_end = __g;
884 unsigned __dc = 0;
885 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +0000886 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000887 __thousands_sep, __grouping, __g, __g_end,
888 __atoms))
889 break;
890 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
891 *__g_end++ = __dc;
892 // Stage 3
893 __v = __num_get_signed_integral<long>(__a, __a_end, __err, __base);
894 // Digit grouping checked
895 __check_grouping(__grouping, __g, __g_end, __err);
896 // EOF checked
897 if (__b == __e)
898 __err |= ios_base::eofbit;
899 return __b;
900}
901
902template <class _CharT, class _InputIterator>
903_InputIterator
904num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
905 ios_base& __iob,
906 ios_base::iostate& __err,
907 long long& __v) const
908{
909 // Stage 1
910 int __base = this->__get_base(__iob);
911 // Stage 2
912 char_type __atoms[26];
913 char_type __thousands_sep;
914 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
915 char __a[__num_get_base::__num_get_buf_sz] = {0};
916 char* __a_end = __a;
917 unsigned __g[__num_get_base::__num_get_buf_sz];
918 unsigned* __g_end = __g;
919 unsigned __dc = 0;
920 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +0000921 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
922 __thousands_sep, __grouping, __g, __g_end,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000923 __atoms))
924 break;
925 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
926 *__g_end++ = __dc;
927 // Stage 3
928 __v = __num_get_signed_integral<long long>(__a, __a_end, __err, __base);
929 // Digit grouping checked
930 __check_grouping(__grouping, __g, __g_end, __err);
931 // EOF checked
932 if (__b == __e)
933 __err |= ios_base::eofbit;
934 return __b;
935}
936
937template <class _CharT, class _InputIterator>
938_InputIterator
939num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
940 ios_base& __iob,
941 ios_base::iostate& __err,
942 unsigned short& __v) const
943{
944 // Stage 1
945 int __base = this->__get_base(__iob);
946 // Stage 2
947 char_type __atoms[26];
948 char_type __thousands_sep;
949 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
950 char __a[__num_get_base::__num_get_buf_sz] = {0};
951 char* __a_end = __a;
952 unsigned __g[__num_get_base::__num_get_buf_sz];
953 unsigned* __g_end = __g;
954 unsigned __dc = 0;
955 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +0000956 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000957 __thousands_sep, __grouping, __g, __g_end,
958 __atoms))
959 break;
960 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
961 *__g_end++ = __dc;
962 // Stage 3
963 __v = __num_get_unsigned_integral<unsigned short>(__a, __a_end, __err, __base);
964 // Digit grouping checked
965 __check_grouping(__grouping, __g, __g_end, __err);
966 // EOF checked
967 if (__b == __e)
968 __err |= ios_base::eofbit;
969 return __b;
970}
971
972template <class _CharT, class _InputIterator>
973_InputIterator
974num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
975 ios_base& __iob,
976 ios_base::iostate& __err,
977 unsigned int& __v) const
978{
979 // Stage 1
980 int __base = this->__get_base(__iob);
981 // Stage 2
982 char_type __atoms[26];
983 char_type __thousands_sep;
984 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
985 char __a[__num_get_base::__num_get_buf_sz] = {0};
986 char* __a_end = __a;
987 unsigned __g[__num_get_base::__num_get_buf_sz];
988 unsigned* __g_end = __g;
989 unsigned __dc = 0;
990 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +0000991 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000992 __thousands_sep, __grouping, __g, __g_end,
993 __atoms))
994 break;
995 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
996 *__g_end++ = __dc;
997 // Stage 3
998 __v = __num_get_unsigned_integral<unsigned int>(__a, __a_end, __err, __base);
999 // Digit grouping checked
1000 __check_grouping(__grouping, __g, __g_end, __err);
1001 // EOF checked
1002 if (__b == __e)
1003 __err |= ios_base::eofbit;
1004 return __b;
1005}
1006
1007template <class _CharT, class _InputIterator>
1008_InputIterator
1009num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1010 ios_base& __iob,
1011 ios_base::iostate& __err,
1012 unsigned long& __v) const
1013{
1014 // Stage 1
1015 int __base = this->__get_base(__iob);
1016 // Stage 2
1017 char_type __atoms[26];
1018 char_type __thousands_sep;
1019 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
1020 char __a[__num_get_base::__num_get_buf_sz] = {0};
1021 char* __a_end = __a;
1022 unsigned __g[__num_get_base::__num_get_buf_sz];
1023 unsigned* __g_end = __g;
1024 unsigned __dc = 0;
1025 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001026 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001027 __thousands_sep, __grouping, __g, __g_end,
1028 __atoms))
1029 break;
1030 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
1031 *__g_end++ = __dc;
1032 // Stage 3
1033 __v = __num_get_unsigned_integral<unsigned long>(__a, __a_end, __err, __base);
1034 // Digit grouping checked
1035 __check_grouping(__grouping, __g, __g_end, __err);
1036 // EOF checked
1037 if (__b == __e)
1038 __err |= ios_base::eofbit;
1039 return __b;
1040}
1041
1042template <class _CharT, class _InputIterator>
1043_InputIterator
1044num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1045 ios_base& __iob,
1046 ios_base::iostate& __err,
1047 unsigned long long& __v) const
1048{
1049 // Stage 1
1050 int __base = this->__get_base(__iob);
1051 // Stage 2
1052 char_type __atoms[26];
1053 char_type __thousands_sep;
1054 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
1055 char __a[__num_get_base::__num_get_buf_sz] = {0};
1056 char* __a_end = __a;
1057 unsigned __g[__num_get_base::__num_get_buf_sz];
1058 unsigned* __g_end = __g;
1059 unsigned __dc = 0;
1060 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001061 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001062 __thousands_sep, __grouping, __g, __g_end,
1063 __atoms))
1064 break;
1065 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
1066 *__g_end++ = __dc;
1067 // Stage 3
1068 __v = __num_get_unsigned_integral<unsigned long long>(__a, __a_end, __err, __base);
1069 // Digit grouping checked
1070 __check_grouping(__grouping, __g, __g_end, __err);
1071 // EOF checked
1072 if (__b == __e)
1073 __err |= ios_base::eofbit;
1074 return __b;
1075}
1076
1077template <class _CharT, class _InputIterator>
1078_InputIterator
1079num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1080 ios_base& __iob,
1081 ios_base::iostate& __err,
1082 float& __v) const
1083{
1084 // Stage 1, nothing to do
1085 // Stage 2
1086 char_type __atoms[32];
1087 char_type __decimal_point;
1088 char_type __thousands_sep;
Howard Hinnant324bb032010-08-22 00:02:43 +00001089 string __grouping = this->__stage2_float_prep(__iob, __atoms,
1090 __decimal_point,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001091 __thousands_sep);
1092 char __a[__num_get_base::__num_get_buf_sz] = {0};
1093 char* __a_end = __a;
1094 unsigned __g[__num_get_base::__num_get_buf_sz];
1095 unsigned* __g_end = __g;
1096 unsigned __dc = 0;
1097 bool __in_units = true;
1098 char __exp = 'E';
1099 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001100 if (this->__stage2_float_loop(*__b, __in_units, __exp, __a, __a_end,
1101 __decimal_point, __thousands_sep,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001102 __grouping, __g, __g_end,
1103 __dc, __atoms))
1104 break;
1105 if (__grouping.size() != 0 && __in_units && __g_end-__g < __num_get_base::__num_get_buf_sz)
1106 *__g_end++ = __dc;
1107 // Stage 3
1108 __v = __num_get_float<float>(__a, __a_end, __err);
1109 // Digit grouping checked
1110 __check_grouping(__grouping, __g, __g_end, __err);
1111 // EOF checked
1112 if (__b == __e)
1113 __err |= ios_base::eofbit;
1114 return __b;
1115}
1116
1117template <class _CharT, class _InputIterator>
1118_InputIterator
1119num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1120 ios_base& __iob,
1121 ios_base::iostate& __err,
1122 double& __v) const
1123{
1124 // Stage 1, nothing to do
1125 // Stage 2
1126 char_type __atoms[32];
1127 char_type __decimal_point;
1128 char_type __thousands_sep;
Howard Hinnant324bb032010-08-22 00:02:43 +00001129 string __grouping = this->__stage2_float_prep(__iob, __atoms,
1130 __decimal_point,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001131 __thousands_sep);
1132 char __a[__num_get_base::__num_get_buf_sz] = {0};
1133 char* __a_end = __a;
1134 unsigned __g[__num_get_base::__num_get_buf_sz];
1135 unsigned* __g_end = __g;
1136 unsigned __dc = 0;
1137 bool __in_units = true;
1138 char __exp = 'E';
1139 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001140 if (this->__stage2_float_loop(*__b, __in_units, __exp, __a, __a_end,
1141 __decimal_point, __thousands_sep,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001142 __grouping, __g, __g_end,
1143 __dc, __atoms))
1144 break;
1145 if (__grouping.size() != 0 && __in_units && __g_end-__g < __num_get_base::__num_get_buf_sz)
1146 *__g_end++ = __dc;
1147 // Stage 3
1148 __v = __num_get_float<double>(__a, __a_end, __err);
1149 // Digit grouping checked
1150 __check_grouping(__grouping, __g, __g_end, __err);
1151 // EOF checked
1152 if (__b == __e)
1153 __err |= ios_base::eofbit;
1154 return __b;
1155}
1156
1157template <class _CharT, class _InputIterator>
1158_InputIterator
1159num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1160 ios_base& __iob,
1161 ios_base::iostate& __err,
1162 long double& __v) const
1163{
1164 // Stage 1, nothing to do
1165 // Stage 2
1166 char_type __atoms[32];
1167 char_type __decimal_point;
1168 char_type __thousands_sep;
Howard Hinnant324bb032010-08-22 00:02:43 +00001169 string __grouping = this->__stage2_float_prep(__iob, __atoms,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001170 __decimal_point,
1171 __thousands_sep);
1172 char __a[__num_get_base::__num_get_buf_sz] = {0};
1173 char* __a_end = __a;
1174 unsigned __g[__num_get_base::__num_get_buf_sz];
1175 unsigned* __g_end = __g;
1176 unsigned __dc = 0;
1177 bool __in_units = true;
1178 char __exp = 'E';
1179 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001180 if (this->__stage2_float_loop(*__b, __in_units, __exp, __a, __a_end,
1181 __decimal_point, __thousands_sep,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001182 __grouping, __g, __g_end,
1183 __dc, __atoms))
1184 break;
1185 if (__grouping.size() != 0 && __in_units && __g_end-__g < __num_get_base::__num_get_buf_sz)
1186 *__g_end++ = __dc;
1187 // Stage 3
1188 __v = __num_get_float<long double>(__a, __a_end, __err);
1189 // Digit grouping checked
1190 __check_grouping(__grouping, __g, __g_end, __err);
1191 // EOF checked
1192 if (__b == __e)
1193 __err |= ios_base::eofbit;
1194 return __b;
1195}
1196
1197template <class _CharT, class _InputIterator>
1198_InputIterator
1199num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1200 ios_base& __iob,
1201 ios_base::iostate& __err,
1202 void*& __v) const
1203{
1204 // Stage 1
1205 int __base = 16;
1206 // Stage 2
1207 char_type __atoms[26];
1208 char_type __thousands_sep;
1209 string __grouping;
1210 use_facet<ctype<_CharT> >(__iob.getloc()).widen(__num_get_base::__src,
1211 __num_get_base::__src + 26, __atoms);
1212 char __a[__num_get_base::__num_get_buf_sz] = {0};
1213 char* __a_end = __a;
1214 unsigned __g[__num_get_base::__num_get_buf_sz];
1215 unsigned* __g_end = __g;
1216 unsigned __dc = 0;
1217 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001218 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
1219 __thousands_sep, __grouping,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001220 __g, __g_end, __atoms))
1221 break;
1222 // Stage 3
1223 __a[sizeof(__a)-1] = 0;
Howard Hinnantadff4892010-05-24 17:49:41 +00001224 if (__nolocale_sscanf(__a, "%p", &__v) != 1)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001225 __err = ios_base::failbit;
1226 // EOF checked
1227 if (__b == __e)
1228 __err |= ios_base::eofbit;
1229 return __b;
1230}
1231
1232extern template class num_get<char>;
1233extern template class num_get<wchar_t>;
1234
1235struct __num_put_base
1236{
1237protected:
1238 static void __format_int(char* __fmt, const char* __len, bool __signd,
1239 ios_base::fmtflags __flags);
1240 static bool __format_float(char* __fmt, const char* __len,
1241 ios_base::fmtflags __flags);
1242 static char* __identify_padding(char* __nb, char* __ne,
1243 const ios_base& __iob);
1244};
1245
1246template <class _CharT>
1247struct __num_put
1248 : protected __num_put_base
1249{
1250 static void __widen_and_group_int(char* __nb, char* __np, char* __ne,
1251 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1252 const locale& __loc);
1253 static void __widen_and_group_float(char* __nb, char* __np, char* __ne,
1254 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1255 const locale& __loc);
1256};
1257
1258template <class _CharT>
1259void
1260__num_put<_CharT>::__widen_and_group_int(char* __nb, char* __np, char* __ne,
1261 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1262 const locale& __loc)
1263{
1264 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> > (__loc);
1265 const numpunct<_CharT>& __npt = use_facet<numpunct<_CharT> >(__loc);
1266 string __grouping = __npt.grouping();
1267 if (__grouping.empty())
1268 {
1269 __ct.widen(__nb, __ne, __ob);
1270 __oe = __ob + (__ne - __nb);
1271 }
1272 else
1273 {
1274 __oe = __ob;
1275 char* __nf = __nb;
1276 if (*__nf == '-' || *__nf == '+')
1277 *__oe++ = __ct.widen(*__nf++);
1278 if (__ne - __nf >= 2 && __nf[0] == '0' && (__nf[1] == 'x' ||
1279 __nf[1] == 'X'))
1280 {
1281 *__oe++ = __ct.widen(*__nf++);
1282 *__oe++ = __ct.widen(*__nf++);
1283 }
1284 reverse(__nf, __ne);
1285 _CharT __thousands_sep = __npt.thousands_sep();
1286 unsigned __dc = 0;
1287 unsigned __dg = 0;
1288 for (char* __p = __nf; __p < __ne; ++__p)
1289 {
1290 if (static_cast<unsigned>(__grouping[__dg]) > 0 &&
1291 __dc == static_cast<unsigned>(__grouping[__dg]))
1292 {
1293 *__oe++ = __thousands_sep;
1294 __dc = 0;
1295 if (__dg < __grouping.size()-1)
1296 ++__dg;
1297 }
1298 *__oe++ = __ct.widen(*__p);
1299 ++__dc;
1300 }
1301 reverse(__ob + (__nf - __nb), __oe);
1302 }
1303 if (__np == __ne)
1304 __op = __oe;
1305 else
1306 __op = __ob + (__np - __nb);
1307}
1308
1309template <class _CharT>
1310void
1311__num_put<_CharT>::__widen_and_group_float(char* __nb, char* __np, char* __ne,
1312 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1313 const locale& __loc)
1314{
1315 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> > (__loc);
1316 const numpunct<_CharT>& __npt = use_facet<numpunct<_CharT> >(__loc);
1317 string __grouping = __npt.grouping();
1318 __oe = __ob;
1319 char* __nf = __nb;
1320 if (*__nf == '-' || *__nf == '+')
1321 *__oe++ = __ct.widen(*__nf++);
1322 char* __ns;
1323 if (__ne - __nf >= 2 && __nf[0] == '0' && (__nf[1] == 'x' ||
1324 __nf[1] == 'X'))
1325 {
1326 *__oe++ = __ct.widen(*__nf++);
1327 *__oe++ = __ct.widen(*__nf++);
1328 for (__ns = __nf; __ns < __ne; ++__ns)
Howard Hinnantadff4892010-05-24 17:49:41 +00001329 if (!__nolocale_isxdigit(*__ns))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001330 break;
1331 }
1332 else
1333 {
1334 for (__ns = __nf; __ns < __ne; ++__ns)
Howard Hinnantadff4892010-05-24 17:49:41 +00001335 if (!__nolocale_isdigit(*__ns))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001336 break;
1337 }
1338 if (__grouping.empty())
1339 {
1340 __ct.widen(__nf, __ns, __oe);
1341 __oe += __ns - __nf;
1342 }
1343 else
1344 {
1345 reverse(__nf, __ns);
1346 _CharT __thousands_sep = __npt.thousands_sep();
1347 unsigned __dc = 0;
1348 unsigned __dg = 0;
1349 for (char* __p = __nf; __p < __ns; ++__p)
1350 {
1351 if (__grouping[__dg] > 0 && __dc == static_cast<unsigned>(__grouping[__dg]))
1352 {
1353 *__oe++ = __thousands_sep;
1354 __dc = 0;
1355 if (__dg < __grouping.size()-1)
1356 ++__dg;
1357 }
1358 *__oe++ = __ct.widen(*__p);
1359 ++__dc;
1360 }
1361 reverse(__ob + (__nf - __nb), __oe);
1362 }
1363 for (__nf = __ns; __nf < __ne; ++__nf)
1364 {
1365 if (*__nf == '.')
1366 {
1367 *__oe++ = __npt.decimal_point();
1368 ++__nf;
1369 break;
1370 }
1371 else
1372 *__oe++ = __ct.widen(*__nf);
1373 }
1374 __ct.widen(__nf, __ne, __oe);
1375 __oe += __ne - __nf;
1376 if (__np == __ne)
1377 __op = __oe;
1378 else
1379 __op = __ob + (__np - __nb);
1380}
1381
1382extern template class __num_put<char>;
1383extern template class __num_put<wchar_t>;
1384
1385template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00001386class _LIBCPP_VISIBLE num_put
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001387 : public locale::facet,
1388 private __num_put<_CharT>
1389{
1390public:
1391 typedef _CharT char_type;
1392 typedef _OutputIterator iter_type;
1393
1394 _LIBCPP_ALWAYS_INLINE
1395 explicit num_put(size_t __refs = 0)
1396 : locale::facet(__refs) {}
1397
1398 _LIBCPP_ALWAYS_INLINE
1399 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1400 bool __v) const
1401 {
1402 return do_put(__s, __iob, __fl, __v);
1403 }
1404
1405 _LIBCPP_ALWAYS_INLINE
1406 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1407 long __v) const
1408 {
1409 return do_put(__s, __iob, __fl, __v);
1410 }
1411
1412 _LIBCPP_ALWAYS_INLINE
1413 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1414 long long __v) const
1415 {
1416 return do_put(__s, __iob, __fl, __v);
1417 }
1418
1419 _LIBCPP_ALWAYS_INLINE
1420 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1421 unsigned long __v) const
1422 {
1423 return do_put(__s, __iob, __fl, __v);
1424 }
1425
1426 _LIBCPP_ALWAYS_INLINE
1427 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1428 unsigned long long __v) const
1429 {
1430 return do_put(__s, __iob, __fl, __v);
1431 }
1432
1433 _LIBCPP_ALWAYS_INLINE
1434 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1435 double __v) const
1436 {
1437 return do_put(__s, __iob, __fl, __v);
1438 }
1439
1440 _LIBCPP_ALWAYS_INLINE
1441 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1442 long double __v) const
1443 {
1444 return do_put(__s, __iob, __fl, __v);
1445 }
1446
1447 _LIBCPP_ALWAYS_INLINE
1448 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1449 const void* __v) const
1450 {
1451 return do_put(__s, __iob, __fl, __v);
1452 }
1453
1454 static locale::id id;
1455
1456protected:
Howard Hinnant82894812010-09-22 16:48:34 +00001457 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001458 ~num_put() {}
1459
1460 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1461 bool __v) const;
1462 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1463 long __v) const;
1464 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1465 long long __v) const;
1466 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1467 unsigned long) const;
1468 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1469 unsigned long long) const;
1470 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1471 double __v) const;
1472 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1473 long double __v) const;
1474 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1475 const void* __v) const;
1476};
1477
1478template <class _CharT, class _OutputIterator>
1479locale::id
1480num_put<_CharT, _OutputIterator>::id;
1481
1482template <class _CharT, class _OutputIterator>
1483_LIBCPP_HIDDEN
1484_OutputIterator
1485__pad_and_output(_OutputIterator __s,
1486 const _CharT* __ob, const _CharT* __op, const _CharT* __oe,
1487 ios_base& __iob, _CharT __fl)
1488{
1489 streamsize __sz = __oe - __ob;
1490 streamsize __ns = __iob.width();
1491 if (__ns > __sz)
1492 __ns -= __sz;
1493 else
1494 __ns = 0;
1495 for (;__ob < __op; ++__ob, ++__s)
1496 *__s = *__ob;
1497 for (; __ns; --__ns, ++__s)
1498 *__s = __fl;
1499 for (; __ob < __oe; ++__ob, ++__s)
1500 *__s = *__ob;
1501 __iob.width(0);
1502 return __s;
1503}
1504
1505template <class _CharT, class _OutputIterator>
1506_OutputIterator
1507num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1508 char_type __fl, bool __v) const
1509{
1510 if ((__iob.flags() & ios_base::boolalpha) == 0)
1511 return do_put(__s, __iob, __fl, (unsigned long)__v);
1512 const numpunct<char_type>& __np = use_facet<numpunct<char_type> >(__iob.getloc());
1513 typedef typename numpunct<char_type>::string_type string_type;
1514 string_type __nm = __v ? __np.truename() : __np.falsename();
1515 for (typename string_type::iterator __i = __nm.begin(); __i != __nm.end(); ++__i, ++__s)
1516 *__s = *__i;
1517 return __s;
1518}
1519
1520template <class _CharT, class _OutputIterator>
1521_OutputIterator
1522num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1523 char_type __fl, long __v) const
1524{
1525 // Stage 1 - Get number in narrow char
1526 char __fmt[6] = {'%', 0};
1527 const char* __len = "l";
1528 this->__format_int(__fmt+1, __len, true, __iob.flags());
1529 const unsigned __nbuf = (numeric_limits<long>::digits / 3)
1530 + ((numeric_limits<long>::digits % 3) != 0)
1531 + 1;
1532 char __nar[__nbuf];
Howard Hinnantadff4892010-05-24 17:49:41 +00001533 int __nc = __nolocale_sprintf(__nar, __fmt, __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001534 char* __ne = __nar + __nc;
1535 char* __np = this->__identify_padding(__nar, __ne, __iob);
1536 // Stage 2 - Widen __nar while adding thousands separators
1537 char_type __o[2*(__nbuf-1) - 1];
1538 char_type* __op; // pad here
1539 char_type* __oe; // end of output
1540 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1541 // [__o, __oe) contains thousands_sep'd wide number
1542 // Stage 3 & 4
1543 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1544}
1545
1546template <class _CharT, class _OutputIterator>
1547_OutputIterator
1548num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1549 char_type __fl, long long __v) const
1550{
1551 // Stage 1 - Get number in narrow char
1552 char __fmt[8] = {'%', 0};
1553 const char* __len = "ll";
1554 this->__format_int(__fmt+1, __len, true, __iob.flags());
1555 const unsigned __nbuf = (numeric_limits<long long>::digits / 3)
1556 + ((numeric_limits<long long>::digits % 3) != 0)
1557 + 1;
1558 char __nar[__nbuf];
Howard Hinnantadff4892010-05-24 17:49:41 +00001559 int __nc = __nolocale_sprintf(__nar, __fmt, __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001560 char* __ne = __nar + __nc;
1561 char* __np = this->__identify_padding(__nar, __ne, __iob);
1562 // Stage 2 - Widen __nar while adding thousands separators
1563 char_type __o[2*(__nbuf-1) - 1];
1564 char_type* __op; // pad here
1565 char_type* __oe; // end of output
1566 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1567 // [__o, __oe) contains thousands_sep'd wide number
1568 // Stage 3 & 4
1569 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1570}
1571
1572template <class _CharT, class _OutputIterator>
1573_OutputIterator
1574num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1575 char_type __fl, unsigned long __v) const
1576{
1577 // Stage 1 - Get number in narrow char
1578 char __fmt[6] = {'%', 0};
1579 const char* __len = "l";
1580 this->__format_int(__fmt+1, __len, false, __iob.flags());
1581 const unsigned __nbuf = (numeric_limits<unsigned long>::digits / 3)
1582 + ((numeric_limits<unsigned long>::digits % 3) != 0)
1583 + 1;
1584 char __nar[__nbuf];
Howard Hinnantadff4892010-05-24 17:49:41 +00001585 int __nc = __nolocale_sprintf(__nar, __fmt, __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001586 char* __ne = __nar + __nc;
1587 char* __np = this->__identify_padding(__nar, __ne, __iob);
1588 // Stage 2 - Widen __nar while adding thousands separators
1589 char_type __o[2*(__nbuf-1) - 1];
1590 char_type* __op; // pad here
1591 char_type* __oe; // end of output
1592 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1593 // [__o, __oe) contains thousands_sep'd wide number
1594 // Stage 3 & 4
1595 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1596}
1597
1598template <class _CharT, class _OutputIterator>
1599_OutputIterator
1600num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1601 char_type __fl, unsigned long long __v) const
1602{
1603 // Stage 1 - Get number in narrow char
1604 char __fmt[8] = {'%', 0};
1605 const char* __len = "ll";
1606 this->__format_int(__fmt+1, __len, false, __iob.flags());
1607 const unsigned __nbuf = (numeric_limits<unsigned long long>::digits / 3)
1608 + ((numeric_limits<unsigned long long>::digits % 3) != 0)
1609 + 1;
1610 char __nar[__nbuf];
Howard Hinnantadff4892010-05-24 17:49:41 +00001611 int __nc = __nolocale_sprintf(__nar, __fmt, __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001612 char* __ne = __nar + __nc;
1613 char* __np = this->__identify_padding(__nar, __ne, __iob);
1614 // Stage 2 - Widen __nar while adding thousands separators
1615 char_type __o[2*(__nbuf-1) - 1];
1616 char_type* __op; // pad here
1617 char_type* __oe; // end of output
1618 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1619 // [__o, __oe) contains thousands_sep'd wide number
1620 // Stage 3 & 4
1621 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1622}
1623
1624template <class _CharT, class _OutputIterator>
1625_OutputIterator
1626num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1627 char_type __fl, double __v) const
1628{
1629 // Stage 1 - Get number in narrow char
1630 char __fmt[8] = {'%', 0};
1631 const char* __len = "";
1632 bool __specify_precision = this->__format_float(__fmt+1, __len, __iob.flags());
1633 const unsigned __nbuf = 30;
1634 char __nar[__nbuf];
1635 char* __nb = __nar;
1636 int __nc;
1637 if (__specify_precision)
Howard Hinnantadff4892010-05-24 17:49:41 +00001638 __nc = __nolocale_snprintf(__nb, __nbuf, __fmt,
1639 (int)__iob.precision(), __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001640 else
Howard Hinnantadff4892010-05-24 17:49:41 +00001641 __nc = __nolocale_snprintf(__nb, __nbuf, __fmt, __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001642 unique_ptr<char, void(*)(void*)> __nbh(0, free);
1643 if (__nc > static_cast<int>(__nbuf-1))
1644 {
1645 if (__specify_precision)
Howard Hinnantadff4892010-05-24 17:49:41 +00001646 __nc = __nolocale_asprintf(&__nb, __fmt, (int)__iob.precision(),
1647 __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001648 else
Howard Hinnantadff4892010-05-24 17:49:41 +00001649 __nc = __nolocale_asprintf(&__nb, __fmt, __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001650 if (__nb == 0)
1651 __throw_bad_alloc();
1652 __nbh.reset(__nb);
1653 }
1654 char* __ne = __nb + __nc;
1655 char* __np = this->__identify_padding(__nb, __ne, __iob);
1656 // Stage 2 - Widen __nar while adding thousands separators
1657 char_type __o[2*(__nbuf-1) - 1];
1658 char_type* __ob = __o;
1659 unique_ptr<char_type, void(*)(void*)> __obh(0, free);
1660 if (__nb != __nar)
1661 {
1662 __ob = (char_type*)malloc((2*__nc)*sizeof(char_type));
1663 if (__ob == 0)
1664 __throw_bad_alloc();
1665 __obh.reset(__ob);
1666 }
1667 char_type* __op; // pad here
1668 char_type* __oe; // end of output
1669 this->__widen_and_group_float(__nb, __np, __ne, __ob, __op, __oe, __iob.getloc());
1670 // [__o, __oe) contains thousands_sep'd wide number
1671 // Stage 3 & 4
1672 __s = __pad_and_output(__s, __ob, __op, __oe, __iob, __fl);
1673 return __s;
1674}
1675
1676template <class _CharT, class _OutputIterator>
1677_OutputIterator
1678num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1679 char_type __fl, long double __v) const
1680{
1681 // Stage 1 - Get number in narrow char
1682 char __fmt[8] = {'%', 0};
1683 const char* __len = "L";
1684 bool __specify_precision = this->__format_float(__fmt+1, __len, __iob.flags());
1685 const unsigned __nbuf = 30;
1686 char __nar[__nbuf];
1687 char* __nb = __nar;
1688 int __nc;
1689 if (__specify_precision)
Howard Hinnantadff4892010-05-24 17:49:41 +00001690 __nc = __nolocale_snprintf(__nb, __nbuf, __fmt,
1691 (int)__iob.precision(), __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001692 else
Howard Hinnantadff4892010-05-24 17:49:41 +00001693 __nc = __nolocale_snprintf(__nb, __nbuf, __fmt, __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001694 unique_ptr<char, void(*)(void*)> __nbh(0, free);
1695 if (__nc > static_cast<int>(__nbuf-1))
1696 {
1697 if (__specify_precision)
Howard Hinnantadff4892010-05-24 17:49:41 +00001698 __nc = __nolocale_asprintf(&__nb, __fmt, (int)__iob.precision(),
1699 __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001700 else
Howard Hinnantadff4892010-05-24 17:49:41 +00001701 __nc = __nolocale_asprintf(&__nb, __fmt, __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001702 if (__nb == 0)
1703 __throw_bad_alloc();
1704 __nbh.reset(__nb);
1705 }
1706 char* __ne = __nb + __nc;
1707 char* __np = this->__identify_padding(__nb, __ne, __iob);
1708 // Stage 2 - Widen __nar while adding thousands separators
1709 char_type __o[2*(__nbuf-1) - 1];
1710 char_type* __ob = __o;
1711 unique_ptr<char_type, void(*)(void*)> __obh(0, free);
1712 if (__nb != __nar)
1713 {
1714 __ob = (char_type*)malloc((2*__nc)*sizeof(char_type));
1715 if (__ob == 0)
1716 __throw_bad_alloc();
1717 __obh.reset(__ob);
1718 }
1719 char_type* __op; // pad here
1720 char_type* __oe; // end of output
1721 this->__widen_and_group_float(__nb, __np, __ne, __ob, __op, __oe, __iob.getloc());
1722 // [__o, __oe) contains thousands_sep'd wide number
1723 // Stage 3 & 4
1724 __s = __pad_and_output(__s, __ob, __op, __oe, __iob, __fl);
1725 return __s;
1726}
1727
1728template <class _CharT, class _OutputIterator>
1729_OutputIterator
1730num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1731 char_type __fl, const void* __v) const
1732{
1733 // Stage 1 - Get pointer in narrow char
1734 char __fmt[6] = "%p";
1735 const unsigned __nbuf = 20;
1736 char __nar[__nbuf];
Howard Hinnantadff4892010-05-24 17:49:41 +00001737 int __nc = __nolocale_sprintf(__nar, __fmt, __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001738 char* __ne = __nar + __nc;
1739 char* __np = this->__identify_padding(__nar, __ne, __iob);
1740 // Stage 2 - Widen __nar
1741 char_type __o[2*(__nbuf-1) - 1];
1742 char_type* __op; // pad here
1743 char_type* __oe; // end of output
1744 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
1745 __ct.widen(__nar, __ne, __o);
1746 __oe = __o + (__ne - __nar);
1747 if (__np == __ne)
1748 __op = __oe;
1749 else
1750 __op = __o + (__np - __nar);
1751 // [__o, __oe) contains wide number
1752 // Stage 3 & 4
1753 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1754}
1755
1756extern template class num_put<char>;
1757extern template class num_put<wchar_t>;
1758
1759template <class _CharT, class _InputIterator>
1760_LIBCPP_HIDDEN
1761int
1762__get_up_to_n_digits(_InputIterator& __b, _InputIterator __e,
1763 ios_base::iostate& __err, const ctype<_CharT>& __ct, int __n)
1764{
1765 // Precondition: __n >= 1
1766 if (__b == __e)
1767 {
1768 __err |= ios_base::eofbit | ios_base::failbit;
1769 return 0;
1770 }
1771 // get first digit
1772 _CharT __c = *__b;
1773 if (!__ct.is(ctype_base::digit, __c))
1774 {
1775 __err |= ios_base::failbit;
1776 return 0;
1777 }
1778 int __r = __ct.narrow(__c, 0) - '0';
1779 for (++__b, --__n; __b != __e && __n > 0; ++__b, --__n)
1780 {
1781 // get next digit
1782 __c = *__b;
1783 if (!__ct.is(ctype_base::digit, __c))
1784 return __r;
1785 __r = __r * 10 + __ct.narrow(__c, 0) - '0';
1786 }
1787 if (__b == __e)
1788 __err |= ios_base::eofbit;
1789 return __r;
1790}
1791
Howard Hinnant82894812010-09-22 16:48:34 +00001792class _LIBCPP_VISIBLE time_base
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001793{
1794public:
1795 enum dateorder {no_order, dmy, mdy, ymd, ydm};
1796};
1797
1798template <class _CharT>
Howard Hinnant2d72b1e2010-12-17 14:46:43 +00001799class __time_get_c_storage // purposefully not decorated
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001800{
1801protected:
1802 typedef basic_string<_CharT> string_type;
1803
1804 virtual const string_type* __weeks() const;
1805 virtual const string_type* __months() const;
1806 virtual const string_type* __am_pm() const;
1807 virtual const string_type& __c() const;
1808 virtual const string_type& __r() const;
1809 virtual const string_type& __x() const;
1810 virtual const string_type& __X() const;
1811};
1812
1813template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00001814class _LIBCPP_VISIBLE time_get
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001815 : public locale::facet,
1816 public time_base,
1817 private __time_get_c_storage<_CharT>
1818{
1819public:
1820 typedef _CharT char_type;
1821 typedef _InputIterator iter_type;
1822 typedef time_base::dateorder dateorder;
1823 typedef basic_string<char_type> string_type;
1824
1825 _LIBCPP_ALWAYS_INLINE
1826 explicit time_get(size_t __refs = 0)
1827 : locale::facet(__refs) {}
1828
1829 _LIBCPP_ALWAYS_INLINE
1830 dateorder date_order() const
1831 {
1832 return this->do_date_order();
1833 }
1834
1835 _LIBCPP_ALWAYS_INLINE
1836 iter_type get_time(iter_type __b, iter_type __e, ios_base& __iob,
1837 ios_base::iostate& __err, tm* __tm) const
1838 {
1839 return do_get_time(__b, __e, __iob, __err, __tm);
1840 }
1841
1842 _LIBCPP_ALWAYS_INLINE
1843 iter_type get_date(iter_type __b, iter_type __e, ios_base& __iob,
1844 ios_base::iostate& __err, tm* __tm) const
1845 {
1846 return do_get_date(__b, __e, __iob, __err, __tm);
1847 }
1848
1849 _LIBCPP_ALWAYS_INLINE
1850 iter_type get_weekday(iter_type __b, iter_type __e, ios_base& __iob,
1851 ios_base::iostate& __err, tm* __tm) const
1852 {
1853 return do_get_weekday(__b, __e, __iob, __err, __tm);
1854 }
1855
1856 _LIBCPP_ALWAYS_INLINE
1857 iter_type get_monthname(iter_type __b, iter_type __e, ios_base& __iob,
1858 ios_base::iostate& __err, tm* __tm) const
1859 {
1860 return do_get_monthname(__b, __e, __iob, __err, __tm);
1861 }
1862
1863 _LIBCPP_ALWAYS_INLINE
1864 iter_type get_year(iter_type __b, iter_type __e, ios_base& __iob,
1865 ios_base::iostate& __err, tm* __tm) const
1866 {
1867 return do_get_year(__b, __e, __iob, __err, __tm);
1868 }
1869
1870 _LIBCPP_ALWAYS_INLINE
1871 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
1872 ios_base::iostate& __err, tm *__tm,
1873 char __fmt, char __mod = 0) const
1874 {
1875 return do_get(__b, __e, __iob, __err, __tm, __fmt, __mod);
1876 }
1877
1878 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
1879 ios_base::iostate& __err, tm* __tm,
1880 const char_type* __fmtb, const char_type* __fmte) const;
1881
1882 static locale::id id;
1883
1884protected:
Howard Hinnant82894812010-09-22 16:48:34 +00001885 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001886 ~time_get() {}
1887
1888 virtual dateorder do_date_order() const;
1889 virtual iter_type do_get_time(iter_type __b, iter_type __e, ios_base& __iob,
1890 ios_base::iostate& __err, tm* __tm) const;
1891 virtual iter_type do_get_date(iter_type __b, iter_type __e, ios_base& __iob,
1892 ios_base::iostate& __err, tm* __tm) const;
1893 virtual iter_type do_get_weekday(iter_type __b, iter_type __e, ios_base& __iob,
1894 ios_base::iostate& __err, tm* __tm) const;
1895 virtual iter_type do_get_monthname(iter_type __b, iter_type __e, ios_base& __iob,
1896 ios_base::iostate& __err, tm* __tm) const;
1897 virtual iter_type do_get_year(iter_type __b, iter_type __e, ios_base& __iob,
1898 ios_base::iostate& __err, tm* __tm) const;
1899 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
1900 ios_base::iostate& __err, tm* __tm,
1901 char __fmt, char __mod) const;
1902private:
1903 void __get_white_space(iter_type& __b, iter_type __e,
1904 ios_base::iostate& __err, const ctype<char_type>& __ct) const;
1905 void __get_percent(iter_type& __b, iter_type __e, ios_base::iostate& __err,
1906 const ctype<char_type>& __ct) const;
1907
1908 void __get_weekdayname(int& __m,
1909 iter_type& __b, iter_type __e,
1910 ios_base::iostate& __err,
1911 const ctype<char_type>& __ct) const;
1912 void __get_monthname(int& __m,
1913 iter_type& __b, iter_type __e,
1914 ios_base::iostate& __err,
1915 const ctype<char_type>& __ct) const;
1916 void __get_day(int& __d,
1917 iter_type& __b, iter_type __e,
1918 ios_base::iostate& __err,
1919 const ctype<char_type>& __ct) const;
1920 void __get_month(int& __m,
1921 iter_type& __b, iter_type __e,
1922 ios_base::iostate& __err,
1923 const ctype<char_type>& __ct) const;
1924 void __get_year(int& __y,
1925 iter_type& __b, iter_type __e,
1926 ios_base::iostate& __err,
1927 const ctype<char_type>& __ct) const;
1928 void __get_year4(int& __y,
1929 iter_type& __b, iter_type __e,
1930 ios_base::iostate& __err,
1931 const ctype<char_type>& __ct) const;
1932 void __get_hour(int& __d,
1933 iter_type& __b, iter_type __e,
1934 ios_base::iostate& __err,
1935 const ctype<char_type>& __ct) const;
1936 void __get_12_hour(int& __h,
1937 iter_type& __b, iter_type __e,
1938 ios_base::iostate& __err,
1939 const ctype<char_type>& __ct) const;
1940 void __get_am_pm(int& __h,
1941 iter_type& __b, iter_type __e,
1942 ios_base::iostate& __err,
1943 const ctype<char_type>& __ct) const;
1944 void __get_minute(int& __m,
1945 iter_type& __b, iter_type __e,
1946 ios_base::iostate& __err,
1947 const ctype<char_type>& __ct) const;
1948 void __get_second(int& __s,
1949 iter_type& __b, iter_type __e,
1950 ios_base::iostate& __err,
1951 const ctype<char_type>& __ct) const;
1952 void __get_weekday(int& __w,
1953 iter_type& __b, iter_type __e,
1954 ios_base::iostate& __err,
1955 const ctype<char_type>& __ct) const;
1956 void __get_day_year_num(int& __w,
1957 iter_type& __b, iter_type __e,
1958 ios_base::iostate& __err,
1959 const ctype<char_type>& __ct) const;
1960};
1961
1962template <class _CharT, class _InputIterator>
1963locale::id
1964time_get<_CharT, _InputIterator>::id;
1965
1966// time_get primatives
1967
1968template <class _CharT, class _InputIterator>
1969void
1970time_get<_CharT, _InputIterator>::__get_weekdayname(int& __w,
1971 iter_type& __b, iter_type __e,
1972 ios_base::iostate& __err,
1973 const ctype<char_type>& __ct) const
1974{
1975 // Note: ignoring case comes from the POSIX strptime spec
1976 const string_type* __wk = this->__weeks();
1977 int __i = __scan_keyword(__b, __e, __wk, __wk+14, __ct, __err, false) - __wk;
1978 if (__i < 14)
1979 __w = __i % 7;
1980}
1981
1982template <class _CharT, class _InputIterator>
1983void
1984time_get<_CharT, _InputIterator>::__get_monthname(int& __m,
1985 iter_type& __b, iter_type __e,
1986 ios_base::iostate& __err,
1987 const ctype<char_type>& __ct) const
1988{
1989 // Note: ignoring case comes from the POSIX strptime spec
1990 const string_type* __month = this->__months();
1991 int __i = __scan_keyword(__b, __e, __month, __month+24, __ct, __err, false) - __month;
1992 if (__i < 24)
1993 __m = __i % 12;
1994}
1995
1996template <class _CharT, class _InputIterator>
1997void
1998time_get<_CharT, _InputIterator>::__get_day(int& __d,
1999 iter_type& __b, iter_type __e,
2000 ios_base::iostate& __err,
2001 const ctype<char_type>& __ct) const
2002{
2003 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2004 if (!(__err & ios_base::failbit) && 1 <= __t && __t <= 31)
2005 __d = __t;
2006 else
2007 __err |= ios_base::failbit;
2008}
2009
2010template <class _CharT, class _InputIterator>
2011void
2012time_get<_CharT, _InputIterator>::__get_month(int& __m,
2013 iter_type& __b, iter_type __e,
2014 ios_base::iostate& __err,
2015 const ctype<char_type>& __ct) const
2016{
2017 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2) - 1;
2018 if (!(__err & ios_base::failbit) && __t <= 11)
2019 __m = __t;
2020 else
2021 __err |= ios_base::failbit;
2022}
2023
2024template <class _CharT, class _InputIterator>
2025void
2026time_get<_CharT, _InputIterator>::__get_year(int& __y,
2027 iter_type& __b, iter_type __e,
2028 ios_base::iostate& __err,
2029 const ctype<char_type>& __ct) const
2030{
2031 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 4);
2032 if (!(__err & ios_base::failbit))
2033 {
2034 if (__t < 69)
2035 __t += 2000;
2036 else if (69 <= __t && __t <= 99)
2037 __t += 1900;
2038 __y = __t - 1900;
2039 }
2040}
2041
2042template <class _CharT, class _InputIterator>
2043void
2044time_get<_CharT, _InputIterator>::__get_year4(int& __y,
2045 iter_type& __b, iter_type __e,
2046 ios_base::iostate& __err,
2047 const ctype<char_type>& __ct) const
2048{
2049 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 4);
2050 if (!(__err & ios_base::failbit))
2051 __y = __t - 1900;
2052}
2053
2054template <class _CharT, class _InputIterator>
2055void
2056time_get<_CharT, _InputIterator>::__get_hour(int& __h,
2057 iter_type& __b, iter_type __e,
2058 ios_base::iostate& __err,
2059 const ctype<char_type>& __ct) const
2060{
2061 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2062 if (!(__err & ios_base::failbit) && __t <= 23)
2063 __h = __t;
2064 else
2065 __err |= ios_base::failbit;
2066}
2067
2068template <class _CharT, class _InputIterator>
2069void
2070time_get<_CharT, _InputIterator>::__get_12_hour(int& __h,
2071 iter_type& __b, iter_type __e,
2072 ios_base::iostate& __err,
2073 const ctype<char_type>& __ct) const
2074{
2075 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2076 if (!(__err & ios_base::failbit) && 1 <= __t && __t <= 12)
2077 __h = __t;
2078 else
2079 __err |= ios_base::failbit;
2080}
2081
2082template <class _CharT, class _InputIterator>
2083void
2084time_get<_CharT, _InputIterator>::__get_minute(int& __m,
2085 iter_type& __b, iter_type __e,
2086 ios_base::iostate& __err,
2087 const ctype<char_type>& __ct) const
2088{
2089 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2090 if (!(__err & ios_base::failbit) && __t <= 59)
2091 __m = __t;
2092 else
2093 __err |= ios_base::failbit;
2094}
2095
2096template <class _CharT, class _InputIterator>
2097void
2098time_get<_CharT, _InputIterator>::__get_second(int& __s,
2099 iter_type& __b, iter_type __e,
2100 ios_base::iostate& __err,
2101 const ctype<char_type>& __ct) const
2102{
2103 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2104 if (!(__err & ios_base::failbit) && __t <= 60)
2105 __s = __t;
2106 else
2107 __err |= ios_base::failbit;
2108}
2109
2110template <class _CharT, class _InputIterator>
2111void
2112time_get<_CharT, _InputIterator>::__get_weekday(int& __w,
2113 iter_type& __b, iter_type __e,
2114 ios_base::iostate& __err,
2115 const ctype<char_type>& __ct) const
2116{
2117 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 1);
2118 if (!(__err & ios_base::failbit) && __t <= 6)
2119 __w = __t;
2120 else
2121 __err |= ios_base::failbit;
2122}
2123
2124template <class _CharT, class _InputIterator>
2125void
2126time_get<_CharT, _InputIterator>::__get_day_year_num(int& __d,
2127 iter_type& __b, iter_type __e,
2128 ios_base::iostate& __err,
2129 const ctype<char_type>& __ct) const
2130{
2131 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 3);
2132 if (!(__err & ios_base::failbit) && __t <= 365)
2133 __d = __t;
2134 else
2135 __err |= ios_base::failbit;
2136}
2137
2138template <class _CharT, class _InputIterator>
2139void
2140time_get<_CharT, _InputIterator>::__get_white_space(iter_type& __b, iter_type __e,
2141 ios_base::iostate& __err,
2142 const ctype<char_type>& __ct) const
2143{
2144 for (; __b != __e && __ct.is(ctype_base::space, *__b); ++__b)
2145 ;
2146 if (__b == __e)
2147 __err |= ios_base::eofbit;
2148}
2149
2150template <class _CharT, class _InputIterator>
2151void
2152time_get<_CharT, _InputIterator>::__get_am_pm(int& __h,
2153 iter_type& __b, iter_type __e,
2154 ios_base::iostate& __err,
2155 const ctype<char_type>& __ct) const
2156{
2157 const string_type* __ap = this->__am_pm();
2158 if (__ap[0].size() + __ap[1].size() == 0)
2159 {
2160 __err |= ios_base::failbit;
2161 return;
2162 }
2163 int __i = __scan_keyword(__b, __e, __ap, __ap+2, __ct, __err, false) - __ap;
2164 if (__i == 0 && __h == 12)
2165 __h = 0;
2166 else if (__i == 1 && __h < 12)
2167 __h += 12;
2168}
2169
2170template <class _CharT, class _InputIterator>
2171void
2172time_get<_CharT, _InputIterator>::__get_percent(iter_type& __b, iter_type __e,
2173 ios_base::iostate& __err,
2174 const ctype<char_type>& __ct) const
2175{
2176 if (__b == __e)
2177 {
2178 __err |= ios_base::eofbit | ios_base::failbit;
2179 return;
2180 }
2181 if (__ct.narrow(*__b, 0) != '%')
2182 __err |= ios_base::failbit;
2183 else if(++__b == __e)
2184 __err |= ios_base::eofbit;
2185}
2186
2187// time_get end primatives
2188
2189template <class _CharT, class _InputIterator>
2190_InputIterator
2191time_get<_CharT, _InputIterator>::get(iter_type __b, iter_type __e,
2192 ios_base& __iob,
2193 ios_base::iostate& __err, tm* __tm,
2194 const char_type* __fmtb, const char_type* __fmte) const
2195{
2196 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2197 __err = ios_base::goodbit;
2198 while (__fmtb != __fmte && __err == ios_base::goodbit)
2199 {
2200 if (__b == __e)
2201 {
2202 __err = ios_base::failbit;
2203 break;
2204 }
2205 if (__ct.narrow(*__fmtb, 0) == '%')
2206 {
2207 if (++__fmtb == __fmte)
2208 {
2209 __err = ios_base::failbit;
2210 break;
2211 }
2212 char __cmd = __ct.narrow(*__fmtb, 0);
2213 char __opt = '\0';
2214 if (__cmd == 'E' || __cmd == '0')
2215 {
2216 if (++__fmtb == __fmte)
2217 {
2218 __err = ios_base::failbit;
2219 break;
2220 }
2221 __opt = __cmd;
2222 __cmd = __ct.narrow(*__fmtb, 0);
2223 }
2224 __b = do_get(__b, __e, __iob, __err, __tm, __cmd, __opt);
2225 ++__fmtb;
2226 }
2227 else if (__ct.is(ctype_base::space, *__fmtb))
2228 {
2229 for (++__fmtb; __fmtb != __fmte && __ct.is(ctype_base::space, *__fmtb); ++__fmtb)
2230 ;
2231 for ( ; __b != __e && __ct.is(ctype_base::space, *__b); ++__b)
2232 ;
2233 }
2234 else if (__ct.toupper(*__b) == __ct.toupper(*__fmtb))
2235 {
2236 ++__b;
2237 ++__fmtb;
2238 }
2239 else
2240 __err = ios_base::failbit;
2241 }
2242 if (__b == __e)
2243 __err |= ios_base::eofbit;
2244 return __b;
2245}
2246
2247template <class _CharT, class _InputIterator>
2248typename time_get<_CharT, _InputIterator>::dateorder
2249time_get<_CharT, _InputIterator>::do_date_order() const
2250{
2251 return mdy;
2252}
2253
2254template <class _CharT, class _InputIterator>
2255_InputIterator
2256time_get<_CharT, _InputIterator>::do_get_time(iter_type __b, iter_type __e,
2257 ios_base& __iob,
2258 ios_base::iostate& __err,
2259 tm* __tm) const
2260{
2261 const char_type __fmt[] = {'%', 'H', ':', '%', 'M', ':', '%', 'S'};
2262 return get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2263}
2264
2265template <class _CharT, class _InputIterator>
2266_InputIterator
2267time_get<_CharT, _InputIterator>::do_get_date(iter_type __b, iter_type __e,
2268 ios_base& __iob,
2269 ios_base::iostate& __err,
2270 tm* __tm) const
2271{
2272 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2273 const string_type& __fmt = this->__x();
2274 return get(__b, __e, __iob, __err, __tm, __fmt.data(), __fmt.data() + __fmt.size());
2275}
2276
2277template <class _CharT, class _InputIterator>
2278_InputIterator
2279time_get<_CharT, _InputIterator>::do_get_weekday(iter_type __b, iter_type __e,
2280 ios_base& __iob,
2281 ios_base::iostate& __err,
2282 tm* __tm) const
2283{
2284 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2285 __get_weekdayname(__tm->tm_wday, __b, __e, __err, __ct);
2286 return __b;
2287}
2288
2289template <class _CharT, class _InputIterator>
2290_InputIterator
2291time_get<_CharT, _InputIterator>::do_get_monthname(iter_type __b, iter_type __e,
2292 ios_base& __iob,
2293 ios_base::iostate& __err,
2294 tm* __tm) const
2295{
2296 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2297 __get_monthname(__tm->tm_mon, __b, __e, __err, __ct);
2298 return __b;
2299}
2300
2301template <class _CharT, class _InputIterator>
2302_InputIterator
2303time_get<_CharT, _InputIterator>::do_get_year(iter_type __b, iter_type __e,
2304 ios_base& __iob,
2305 ios_base::iostate& __err,
2306 tm* __tm) const
2307{
2308 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2309 __get_year(__tm->tm_year, __b, __e, __err, __ct);
2310 return __b;
2311}
2312
2313template <class _CharT, class _InputIterator>
2314_InputIterator
2315time_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
2316 ios_base& __iob,
2317 ios_base::iostate& __err, tm* __tm,
2318 char __fmt, char) const
2319{
2320 __err = ios_base::goodbit;
2321 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2322 switch (__fmt)
2323 {
2324 case 'a':
2325 case 'A':
2326 __get_weekdayname(__tm->tm_wday, __b, __e, __err, __ct);
2327 break;
2328 case 'b':
2329 case 'B':
2330 case 'h':
2331 __get_monthname(__tm->tm_mon, __b, __e, __err, __ct);
2332 break;
2333 case 'c':
2334 {
2335 const string_type& __fmt = this->__c();
2336 __b = get(__b, __e, __iob, __err, __tm, __fmt.data(), __fmt.data() + __fmt.size());
2337 }
2338 break;
2339 case 'd':
2340 case 'e':
2341 __get_day(__tm->tm_mday, __b, __e, __err, __ct);
2342 break;
2343 case 'D':
2344 {
2345 const char_type __fmt[] = {'%', 'm', '/', '%', 'd', '/', '%', 'y'};
2346 __b = get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2347 }
2348 break;
Howard Hinnant506b3642011-04-10 17:54:14 +00002349 case 'F':
2350 {
2351 const char_type __fmt[] = {'%', 'Y', '-', '%', 'm', '-', '%', 'd'};
2352 __b = get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2353 }
2354 break;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002355 case 'H':
2356 __get_hour(__tm->tm_hour, __b, __e, __err, __ct);
2357 break;
2358 case 'I':
2359 __get_12_hour(__tm->tm_hour, __b, __e, __err, __ct);
2360 break;
2361 case 'j':
2362 __get_day_year_num(__tm->tm_yday, __b, __e, __err, __ct);
2363 break;
2364 case 'm':
2365 __get_month(__tm->tm_mon, __b, __e, __err, __ct);
2366 break;
2367 case 'M':
2368 __get_minute(__tm->tm_min, __b, __e, __err, __ct);
2369 break;
2370 case 'n':
2371 case 't':
2372 __get_white_space(__b, __e, __err, __ct);
2373 break;
2374 case 'p':
2375 __get_am_pm(__tm->tm_hour, __b, __e, __err, __ct);
2376 break;
2377 case 'r':
2378 {
2379 const char_type __fmt[] = {'%', 'I', ':', '%', 'M', ':', '%', 'S', ' ', '%', 'p'};
2380 __b = get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2381 }
2382 break;
2383 case 'R':
2384 {
2385 const char_type __fmt[] = {'%', 'H', ':', '%', 'M'};
2386 __b = get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2387 }
2388 break;
2389 case 'S':
2390 __get_second(__tm->tm_sec, __b, __e, __err, __ct);
2391 break;
2392 case 'T':
2393 {
2394 const char_type __fmt[] = {'%', 'H', ':', '%', 'M', ':', '%', 'S'};
2395 __b = get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2396 }
2397 break;
2398 case 'w':
2399 __get_weekday(__tm->tm_wday, __b, __e, __err, __ct);
2400 break;
2401 case 'x':
2402 return do_get_date(__b, __e, __iob, __err, __tm);
2403 case 'X':
2404 {
2405 const string_type& __fmt = this->__X();
2406 __b = get(__b, __e, __iob, __err, __tm, __fmt.data(), __fmt.data() + __fmt.size());
2407 }
2408 break;
2409 case 'y':
2410 __get_year(__tm->tm_year, __b, __e, __err, __ct);
2411 break;
2412 case 'Y':
2413 __get_year4(__tm->tm_year, __b, __e, __err, __ct);
2414 break;
2415 case '%':
2416 __get_percent(__b, __e, __err, __ct);
2417 break;
2418 default:
2419 __err |= ios_base::failbit;
2420 }
2421 return __b;
2422}
2423
2424extern template class time_get<char>;
2425extern template class time_get<wchar_t>;
2426
2427class __time_get
2428{
2429protected:
2430 locale_t __loc_;
2431
2432 __time_get(const char* __nm);
2433 __time_get(const string& __nm);
2434 ~__time_get();
2435};
2436
2437template <class _CharT>
2438class __time_get_storage
2439 : public __time_get
2440{
2441protected:
2442 typedef basic_string<_CharT> string_type;
2443
2444 string_type __weeks_[14];
2445 string_type __months_[24];
2446 string_type __am_pm_[2];
2447 string_type __c_;
2448 string_type __r_;
2449 string_type __x_;
2450 string_type __X_;
2451
2452 explicit __time_get_storage(const char* __nm);
2453 explicit __time_get_storage(const string& __nm);
2454
2455 _LIBCPP_ALWAYS_INLINE ~__time_get_storage() {}
2456
2457 time_base::dateorder __do_date_order() const;
2458
2459private:
2460 void init(const ctype<_CharT>&);
2461 string_type __analyze(char __fmt, const ctype<_CharT>&);
2462};
2463
2464template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00002465class _LIBCPP_VISIBLE time_get_byname
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002466 : public time_get<_CharT, _InputIterator>,
2467 private __time_get_storage<_CharT>
2468{
2469public:
2470 typedef time_base::dateorder dateorder;
2471 typedef _InputIterator iter_type;
2472 typedef _CharT char_type;
2473 typedef basic_string<char_type> string_type;
2474
Howard Hinnant82894812010-09-22 16:48:34 +00002475 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002476 explicit time_get_byname(const char* __nm, size_t __refs = 0)
2477 : time_get<_CharT, _InputIterator>(__refs),
2478 __time_get_storage<_CharT>(__nm) {}
Howard Hinnant82894812010-09-22 16:48:34 +00002479 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002480 explicit time_get_byname(const string& __nm, size_t __refs = 0)
2481 : time_get<_CharT, _InputIterator>(__refs),
2482 __time_get_storage<_CharT>(__nm) {}
2483
2484protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002485 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002486 ~time_get_byname() {}
2487
Howard Hinnant82894812010-09-22 16:48:34 +00002488 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002489 virtual dateorder do_date_order() const {return this->__do_date_order();}
2490private:
Howard Hinnant82894812010-09-22 16:48:34 +00002491 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002492 virtual const string_type* __weeks() const {return this->__weeks_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002493 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002494 virtual const string_type* __months() const {return this->__months_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002495 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002496 virtual const string_type* __am_pm() const {return this->__am_pm_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002497 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002498 virtual const string_type& __c() const {return this->__c_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002499 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002500 virtual const string_type& __r() const {return this->__r_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002501 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002502 virtual const string_type& __x() const {return this->__x_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002503 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002504 virtual const string_type& __X() const {return this->__X_;}
2505};
2506
2507extern template class time_get_byname<char>;
2508extern template class time_get_byname<wchar_t>;
2509
2510class __time_put
2511{
2512 locale_t __loc_;
2513protected:
2514 _LIBCPP_ALWAYS_INLINE __time_put() : __loc_(0) {}
2515 __time_put(const char* __nm);
2516 __time_put(const string& __nm);
2517 ~__time_put();
2518 void __do_put(char* __nb, char*& __ne, const tm* __tm,
2519 char __fmt, char __mod) const;
2520 void __do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
2521 char __fmt, char __mod) const;
2522};
2523
2524template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00002525class _LIBCPP_VISIBLE time_put
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002526 : public locale::facet,
2527 private __time_put
2528{
2529public:
2530 typedef _CharT char_type;
2531 typedef _OutputIterator iter_type;
2532
2533 _LIBCPP_ALWAYS_INLINE
2534 explicit time_put(size_t __refs = 0)
2535 : locale::facet(__refs) {}
2536
2537 iter_type put(iter_type __s, ios_base& __iob, char_type __fl, const tm* __tm,
2538 const char_type* __pb, const char_type* __pe) const;
2539
2540 _LIBCPP_ALWAYS_INLINE
2541 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
2542 const tm* __tm, char __fmt, char __mod = 0) const
2543 {
2544 return do_put(__s, __iob, __fl, __tm, __fmt, __mod);
2545 }
2546
2547 static locale::id id;
2548
2549protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002550 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002551 ~time_put() {}
2552 virtual iter_type do_put(iter_type __s, ios_base&, char_type, const tm* __tm,
2553 char __fmt, char __mod) const;
2554
Howard Hinnant82894812010-09-22 16:48:34 +00002555 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002556 explicit time_put(const char* __nm, size_t __refs)
2557 : locale::facet(__refs),
2558 __time_put(__nm) {}
Howard Hinnant82894812010-09-22 16:48:34 +00002559 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002560 explicit time_put(const string& __nm, size_t __refs)
2561 : locale::facet(__refs),
2562 __time_put(__nm) {}
2563};
2564
2565template <class _CharT, class _OutputIterator>
2566locale::id
2567time_put<_CharT, _OutputIterator>::id;
2568
2569template <class _CharT, class _OutputIterator>
2570_OutputIterator
2571time_put<_CharT, _OutputIterator>::put(iter_type __s, ios_base& __iob,
2572 char_type __fl, const tm* __tm,
2573 const char_type* __pb,
2574 const char_type* __pe) const
2575{
2576 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2577 for (; __pb != __pe; ++__pb)
2578 {
2579 if (__ct.narrow(*__pb, 0) == '%')
2580 {
2581 if (++__pb == __pe)
2582 {
2583 *__s++ = __pb[-1];
2584 break;
2585 }
2586 char __mod = 0;
2587 char __fmt = __ct.narrow(*__pb, 0);
2588 if (__fmt == 'E' || __fmt == 'O')
2589 {
2590 if (++__pb == __pe)
2591 {
2592 *__s++ = __pb[-2];
2593 *__s++ = __pb[-1];
2594 break;
2595 }
2596 __mod = __fmt;
2597 __fmt = __ct.narrow(*__pb, 0);
2598 }
2599 __s = do_put(__s, __iob, __fl, __tm, __fmt, __mod);
2600 }
2601 else
2602 *__s++ = *__pb;
2603 }
2604 return __s;
2605}
2606
2607template <class _CharT, class _OutputIterator>
2608_OutputIterator
2609time_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
2610 char_type, const tm* __tm,
2611 char __fmt, char __mod) const
2612{
2613 char_type __nar[100];
2614 char_type* __nb = __nar;
2615 char_type* __ne = __nb + 100;
2616 __do_put(__nb, __ne, __tm, __fmt, __mod);
Howard Hinnant6cf5d8c2011-02-14 19:12:38 +00002617 return _STD::copy(__nb, __ne, __s);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002618}
2619
2620extern template class time_put<char>;
2621extern template class time_put<wchar_t>;
2622
2623template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00002624class _LIBCPP_VISIBLE time_put_byname
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002625 : public time_put<_CharT, _OutputIterator>
2626{
2627public:
2628 _LIBCPP_ALWAYS_INLINE
2629 explicit time_put_byname(const char* __nm, size_t __refs = 0)
2630 : time_put<_CharT, _OutputIterator>(__nm, __refs) {}
2631
2632 _LIBCPP_ALWAYS_INLINE
2633 explicit time_put_byname(const string& __nm, size_t __refs = 0)
2634 : time_put<_CharT, _OutputIterator>(__nm, __refs) {}
2635
2636protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002637 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002638 ~time_put_byname() {}
2639};
2640
2641extern template class time_put_byname<char>;
2642extern template class time_put_byname<wchar_t>;
2643
2644// money_base
2645
Howard Hinnant82894812010-09-22 16:48:34 +00002646class _LIBCPP_VISIBLE money_base
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002647{
2648public:
2649 enum part {none, space, symbol, sign, value};
2650 struct pattern {char field[4];};
2651
2652 _LIBCPP_ALWAYS_INLINE money_base() {}
2653};
2654
2655// moneypunct
2656
2657template <class _CharT, bool _International = false>
Howard Hinnant82894812010-09-22 16:48:34 +00002658class _LIBCPP_VISIBLE moneypunct
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002659 : public locale::facet,
2660 public money_base
2661{
2662public:
2663 typedef _CharT char_type;
2664 typedef basic_string<char_type> string_type;
2665
Howard Hinnant82894812010-09-22 16:48:34 +00002666 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002667 explicit moneypunct(size_t __refs = 0)
2668 : locale::facet(__refs) {}
2669
2670 _LIBCPP_ALWAYS_INLINE char_type decimal_point() const {return do_decimal_point();}
2671 _LIBCPP_ALWAYS_INLINE char_type thousands_sep() const {return do_thousands_sep();}
2672 _LIBCPP_ALWAYS_INLINE string grouping() const {return do_grouping();}
2673 _LIBCPP_ALWAYS_INLINE string_type curr_symbol() const {return do_curr_symbol();}
2674 _LIBCPP_ALWAYS_INLINE string_type positive_sign() const {return do_positive_sign();}
2675 _LIBCPP_ALWAYS_INLINE string_type negative_sign() const {return do_negative_sign();}
2676 _LIBCPP_ALWAYS_INLINE int frac_digits() const {return do_frac_digits();}
2677 _LIBCPP_ALWAYS_INLINE pattern pos_format() const {return do_pos_format();}
2678 _LIBCPP_ALWAYS_INLINE pattern neg_format() const {return do_neg_format();}
2679
2680 static locale::id id;
2681 static const bool intl = _International;
2682
2683protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002684 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002685 ~moneypunct() {}
2686
2687 virtual char_type do_decimal_point() const {return numeric_limits<char_type>::max();}
2688 virtual char_type do_thousands_sep() const {return numeric_limits<char_type>::max();}
2689 virtual string do_grouping() const {return string();}
2690 virtual string_type do_curr_symbol() const {return string_type();}
2691 virtual string_type do_positive_sign() const {return string_type();}
2692 virtual string_type do_negative_sign() const {return string_type(1, '-');}
2693 virtual int do_frac_digits() const {return 0;}
2694 virtual pattern do_pos_format() const
2695 {pattern __p = {symbol, sign, none, value}; return __p;}
2696 virtual pattern do_neg_format() const
2697 {pattern __p = {symbol, sign, none, value}; return __p;}
2698};
2699
2700template <class _CharT, bool _International>
2701locale::id
2702moneypunct<_CharT, _International>::id;
2703
2704extern template class moneypunct<char, false>;
2705extern template class moneypunct<char, true>;
2706extern template class moneypunct<wchar_t, false>;
2707extern template class moneypunct<wchar_t, true>;
2708
2709// moneypunct_byname
2710
2711template <class _CharT, bool _International = false>
Howard Hinnant82894812010-09-22 16:48:34 +00002712class _LIBCPP_VISIBLE moneypunct_byname
2713 : public moneypunct<_CharT, _International>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002714{
2715public:
2716 typedef money_base::pattern pattern;
2717 typedef _CharT char_type;
2718 typedef basic_string<char_type> string_type;
2719
2720 _LIBCPP_ALWAYS_INLINE
2721 explicit moneypunct_byname(const char* __nm, size_t __refs = 0)
2722 : moneypunct<_CharT, _International>(__refs) {init(__nm);}
2723
2724 _LIBCPP_ALWAYS_INLINE
2725 explicit moneypunct_byname(const string& __nm, size_t __refs = 0)
2726 : moneypunct<_CharT, _International>(__refs) {init(__nm.c_str());}
2727
2728protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002729 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002730 ~moneypunct_byname() {}
2731
2732 virtual char_type do_decimal_point() const {return __decimal_point_;}
2733 virtual char_type do_thousands_sep() const {return __thousands_sep_;}
2734 virtual string do_grouping() const {return __grouping_;}
2735 virtual string_type do_curr_symbol() const {return __curr_symbol_;}
2736 virtual string_type do_positive_sign() const {return __positive_sign_;}
2737 virtual string_type do_negative_sign() const {return __negative_sign_;}
2738 virtual int do_frac_digits() const {return __frac_digits_;}
2739 virtual pattern do_pos_format() const {return __pos_format_;}
2740 virtual pattern do_neg_format() const {return __neg_format_;}
2741
2742private:
2743 char_type __decimal_point_;
2744 char_type __thousands_sep_;
2745 string __grouping_;
2746 string_type __curr_symbol_;
2747 string_type __positive_sign_;
2748 string_type __negative_sign_;
2749 int __frac_digits_;
2750 pattern __pos_format_;
2751 pattern __neg_format_;
2752
2753 void init(const char*);
2754};
2755
2756template<> void moneypunct_byname<char, false>::init(const char*);
2757template<> void moneypunct_byname<char, true>::init(const char*);
2758template<> void moneypunct_byname<wchar_t, false>::init(const char*);
2759template<> void moneypunct_byname<wchar_t, true>::init(const char*);
2760
2761extern template class moneypunct_byname<char, false>;
2762extern template class moneypunct_byname<char, true>;
2763extern template class moneypunct_byname<wchar_t, false>;
2764extern template class moneypunct_byname<wchar_t, true>;
2765
2766// money_get
2767
2768template <class _CharT>
2769class __money_get
2770{
2771protected:
2772 typedef _CharT char_type;
2773 typedef basic_string<char_type> string_type;
2774
2775 _LIBCPP_ALWAYS_INLINE __money_get() {}
2776
2777 static void __gather_info(bool __intl, const locale& __loc,
2778 money_base::pattern& __pat, char_type& __dp,
2779 char_type& __ts, string& __grp,
2780 string_type& __sym, string_type& __psn,
2781 string_type& __nsn, int& __fd);
2782};
2783
2784template <class _CharT>
2785void
2786__money_get<_CharT>::__gather_info(bool __intl, const locale& __loc,
2787 money_base::pattern& __pat, char_type& __dp,
2788 char_type& __ts, string& __grp,
2789 string_type& __sym, string_type& __psn,
2790 string_type& __nsn, int& __fd)
2791{
2792 if (__intl)
2793 {
2794 const moneypunct<char_type, true>& __mp =
2795 use_facet<moneypunct<char_type, true> >(__loc);
2796 __pat = __mp.neg_format();
2797 __nsn = __mp.negative_sign();
2798 __psn = __mp.positive_sign();
2799 __dp = __mp.decimal_point();
2800 __ts = __mp.thousands_sep();
2801 __grp = __mp.grouping();
2802 __sym = __mp.curr_symbol();
2803 __fd = __mp.frac_digits();
2804 }
2805 else
2806 {
2807 const moneypunct<char_type, false>& __mp =
2808 use_facet<moneypunct<char_type, false> >(__loc);
2809 __pat = __mp.neg_format();
2810 __nsn = __mp.negative_sign();
2811 __psn = __mp.positive_sign();
2812 __dp = __mp.decimal_point();
2813 __ts = __mp.thousands_sep();
2814 __grp = __mp.grouping();
2815 __sym = __mp.curr_symbol();
2816 __fd = __mp.frac_digits();
2817 }
2818}
2819
2820extern template class __money_get<char>;
2821extern template class __money_get<wchar_t>;
2822
2823template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00002824class _LIBCPP_VISIBLE money_get
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002825 : public locale::facet,
2826 private __money_get<_CharT>
2827{
2828public:
2829 typedef _CharT char_type;
2830 typedef _InputIterator iter_type;
2831 typedef basic_string<char_type> string_type;
2832
2833 _LIBCPP_ALWAYS_INLINE
2834 explicit money_get(size_t __refs = 0)
2835 : locale::facet(__refs) {}
2836
2837 _LIBCPP_ALWAYS_INLINE
2838 iter_type get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob,
2839 ios_base::iostate& __err, long double& __v) const
2840 {
2841 return do_get(__b, __e, __intl, __iob, __err, __v);
2842 }
2843
2844 _LIBCPP_ALWAYS_INLINE
2845 iter_type get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob,
2846 ios_base::iostate& __err, string_type& __v) const
2847 {
2848 return do_get(__b, __e, __intl, __iob, __err, __v);
2849 }
2850
2851 static locale::id id;
2852
2853protected:
2854
Howard Hinnant82894812010-09-22 16:48:34 +00002855 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002856 ~money_get() {}
Howard Hinnant324bb032010-08-22 00:02:43 +00002857
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002858 virtual iter_type do_get(iter_type __b, iter_type __e, bool __intl,
2859 ios_base& __iob, ios_base::iostate& __err,
2860 long double& __v) const;
2861 virtual iter_type do_get(iter_type __b, iter_type __e, bool __intl,
2862 ios_base& __iob, ios_base::iostate& __err,
2863 string_type& __v) const;
2864
2865private:
2866 static bool __do_get(iter_type& __b, iter_type __e,
2867 bool __intl, const locale& __loc,
2868 ios_base::fmtflags __flags, ios_base::iostate& __err,
2869 bool& __neg, const ctype<char_type>& __ct,
2870 unique_ptr<char_type, void(*)(void*)>& __wb,
2871 char_type*& __wn, char_type* __we);
2872};
2873
2874template <class _CharT, class _InputIterator>
2875locale::id
2876money_get<_CharT, _InputIterator>::id;
2877
2878void __do_nothing(void*);
2879
2880template <class _Tp>
2881_LIBCPP_HIDDEN
2882void
2883__double_or_nothing(unique_ptr<_Tp, void(*)(void*)>& __b, _Tp*& __n, _Tp*& __e)
2884{
2885 bool __owns = __b.get_deleter() != __do_nothing;
2886 size_t __cur_cap = (__e-__b.get()) * sizeof(_Tp);
2887 size_t __new_cap = __cur_cap < numeric_limits<size_t>::max() / 2 ?
2888 2 * __cur_cap : numeric_limits<size_t>::max();
2889 size_t __n_off = __n - __b.get();
2890 _Tp* __t = (_Tp*)realloc(__owns ? __b.get() : 0, __new_cap);
2891 if (__t == 0)
2892 __throw_bad_alloc();
2893 if (__owns)
2894 __b.release();
2895 __b = unique_ptr<_Tp, void(*)(void*)>(__t, free);
2896 __new_cap /= sizeof(_Tp);
2897 __n = __b.get() + __n_off;
2898 __e = __b.get() + __new_cap;
2899}
2900
2901// true == success
2902template <class _CharT, class _InputIterator>
2903bool
2904money_get<_CharT, _InputIterator>::__do_get(iter_type& __b, iter_type __e,
2905 bool __intl, const locale& __loc,
2906 ios_base::fmtflags __flags,
2907 ios_base::iostate& __err,
2908 bool& __neg,
2909 const ctype<char_type>& __ct,
2910 unique_ptr<char_type, void(*)(void*)>& __wb,
2911 char_type*& __wn, char_type* __we)
2912{
2913 const unsigned __bz = 100;
2914 unsigned __gbuf[__bz];
2915 unique_ptr<unsigned, void(*)(void*)> __gb(__gbuf, __do_nothing);
2916 unsigned* __gn = __gb.get();
2917 unsigned* __ge = __gn + __bz;
2918 money_base::pattern __pat;
2919 char_type __dp;
2920 char_type __ts;
2921 string __grp;
2922 string_type __sym;
2923 string_type __psn;
2924 string_type __nsn;
2925 int __fd;
2926 __money_get<_CharT>::__gather_info(__intl, __loc, __pat, __dp, __ts, __grp,
2927 __sym, __psn, __nsn, __fd);
2928 const string_type* __trailing_sign = 0;
2929 __wn = __wb.get();
2930 for (unsigned __p = 0; __p < 4 && __b != __e; ++__p)
2931 {
2932 switch (__pat.field[__p])
2933 {
2934 case money_base::space:
2935 if (__p != 3)
2936 {
2937 if (__ct.is(ctype_base::space, *__b))
2938 ++__b;
2939 else
2940 {
2941 __err |= ios_base::failbit;
2942 return false;
2943 }
2944 }
Howard Hinnant324bb032010-08-22 00:02:43 +00002945 // drop through
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002946 case money_base::none:
2947 if (__p != 3)
2948 {
2949 while (__b != __e && __ct.is(ctype_base::space, *__b))
2950 ++__b;
2951 }
2952 break;
2953 case money_base::sign:
2954 if (__psn.size() + __nsn.size() > 0)
2955 {
2956 if (__psn.size() == 0 || __nsn.size() == 0)
2957 { // sign is optional
2958 if (__psn.size() > 0)
2959 { // __nsn.size() == 0
2960 if (*__b == __psn[0])
2961 {
2962 ++__b;
2963 if (__psn.size() > 1)
2964 __trailing_sign = &__psn;
2965 }
2966 else
2967 __neg = true;
2968 }
2969 else if (*__b == __nsn[0]) // __nsn.size() > 0 && __psn.size() == 0
2970 {
2971 ++__b;
2972 __neg = true;
2973 if (__nsn.size() > 1)
2974 __trailing_sign = &__nsn;
2975 }
2976 }
2977 else // sign is required
2978 {
2979 if (*__b == __psn[0])
2980 {
2981 ++__b;
2982 if (__psn.size() > 1)
2983 __trailing_sign = &__psn;
2984 }
2985 else if (*__b == __nsn[0])
2986 {
2987 ++__b;
2988 __neg = true;
2989 if (__nsn.size() > 1)
2990 __trailing_sign = &__nsn;
2991 }
2992 else
2993 {
2994 __err |= ios_base::failbit;
2995 return false;
2996 }
2997 }
2998 }
2999 break;
3000 case money_base::symbol:
3001 {
3002 bool __more_needed = __trailing_sign ||
3003 (__p < 2) ||
3004 (__p == 2 && __pat.field[3] != static_cast<char>(money_base::none));
3005 bool __sb = __flags & ios_base::showbase;
3006 if (__sb || __more_needed)
3007 {
3008 ios_base::iostate __et = ios_base::goodbit;
3009 string_type* __k = __scan_keyword(__b, __e, &__sym, &__sym+1,
3010 __ct, __et);
3011 if (__sb && __k != &__sym)
3012 {
3013 __err |= ios_base::failbit;
3014 return false;
3015 }
3016 }
3017 }
3018 break;
3019 case money_base::value:
3020 {
3021 unsigned __ng = 0;
3022 for (; __b != __e; ++__b)
3023 {
3024 char_type __c = *__b;
3025 if (__ct.is(ctype_base::digit, __c))
3026 {
3027 if (__wn == __we)
3028 __double_or_nothing(__wb, __wn, __we);
3029 *__wn++ = __c;
3030 ++__ng;
3031 }
3032 else if (__grp.size() > 0 && __ng > 0 && __c == __ts)
3033 {
3034 if (__gn == __ge)
3035 __double_or_nothing(__gb, __gn, __ge);
3036 *__gn++ = __ng;
3037 __ng = 0;
3038 }
3039 else
3040 break;
3041 }
3042 if (__gb.get() != __gn && __ng > 0)
3043 {
3044 if (__gn == __ge)
3045 __double_or_nothing(__gb, __gn, __ge);
3046 *__gn++ = __ng;
3047 }
3048 if (__fd > 0)
3049 {
3050 if (__b == __e || *__b != __dp)
3051 {
3052 __err |= ios_base::failbit;
3053 return false;
3054 }
3055 for (++__b; __fd > 0; --__fd, ++__b)
3056 {
3057 if (__b == __e || !__ct.is(ctype_base::digit, *__b))
3058 {
3059 __err |= ios_base::failbit;
3060 return false;
3061 }
3062 if (__wn == __we)
3063 __double_or_nothing(__wb, __wn, __we);
3064 *__wn++ = *__b;
3065 }
3066 }
3067 if (__wn == __wb.get())
3068 {
3069 __err |= ios_base::failbit;
3070 return false;
3071 }
3072 }
3073 break;
3074 }
3075 }
3076 if (__trailing_sign)
3077 {
3078 for (unsigned __i = 1; __i < __trailing_sign->size(); ++__i, ++__b)
3079 {
3080 if (__b == __e || *__b != (*__trailing_sign)[__i])
3081 {
3082 __err |= ios_base::failbit;
3083 return false;
3084 }
3085 }
3086 }
3087 if (__gb.get() != __gn)
3088 {
3089 ios_base::iostate __et = ios_base::goodbit;
3090 __check_grouping(__grp, __gb.get(), __gn, __et);
3091 if (__et)
3092 {
3093 __err |= ios_base::failbit;
3094 return false;
3095 }
3096 }
3097 return true;
3098}
3099
3100template <class _CharT, class _InputIterator>
3101_InputIterator
3102money_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
3103 bool __intl, ios_base& __iob,
3104 ios_base::iostate& __err,
3105 long double& __v) const
3106{
3107 const unsigned __bz = 100;
3108 char_type __wbuf[__bz];
3109 unique_ptr<char_type, void(*)(void*)> __wb(__wbuf, __do_nothing);
3110 char_type* __wn;
3111 char_type* __we = __wbuf + __bz;
3112 locale __loc = __iob.getloc();
3113 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3114 bool __neg = false;
3115 if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct,
3116 __wb, __wn, __we))
3117 {
3118 const char __src[] = "0123456789";
3119 char_type __atoms[sizeof(__src)-1];
3120 __ct.widen(__src, __src + (sizeof(__src)-1), __atoms);
3121 char __nbuf[__bz];
3122 char* __nc = __nbuf;
3123 unique_ptr<char, void(*)(void*)> __h(0, free);
3124 if (__wn - __wb.get() > __bz-2)
3125 {
3126 __h.reset((char*)malloc(__wn - __wb.get() + 2));
3127 if (__h.get() == 0)
3128 __throw_bad_alloc();
3129 __nc = __h.get();
3130 }
3131 if (__neg)
3132 *__nc++ = '-';
3133 for (const char_type* __w = __wb.get(); __w < __wn; ++__w, ++__nc)
3134 *__nc = __src[find(__atoms, __atoms+sizeof(__atoms), *__w) - __atoms];
3135 *__nc = char();
3136 if (sscanf(__nbuf, "%Lf", &__v) != 1)
3137 __throw_runtime_error("money_get error");
3138 }
3139 if (__b == __e)
3140 __err |= ios_base::eofbit;
3141 return __b;
3142}
3143
3144template <class _CharT, class _InputIterator>
3145_InputIterator
3146money_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
3147 bool __intl, ios_base& __iob,
3148 ios_base::iostate& __err,
3149 string_type& __v) const
3150{
3151 const unsigned __bz = 100;
3152 char_type __wbuf[__bz];
3153 unique_ptr<char_type, void(*)(void*)> __wb(__wbuf, __do_nothing);
3154 char_type* __wn;
3155 char_type* __we = __wbuf + __bz;
3156 locale __loc = __iob.getloc();
3157 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3158 bool __neg = false;
3159 if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct,
3160 __wb, __wn, __we))
3161 {
3162 __v.clear();
3163 if (__neg)
3164 __v.push_back(__ct.widen('-'));
3165 char_type __z = __ct.widen('0');
3166 char_type* __w;
3167 for (__w = __wb.get(); __w < __wn-1; ++__w)
3168 if (*__w != __z)
3169 break;
3170 __v.append(__w, __wn);
3171 }
3172 if (__b == __e)
3173 __err |= ios_base::eofbit;
3174 return __b;
3175}
3176
3177extern template class money_get<char>;
3178extern template class money_get<wchar_t>;
3179
3180// money_put
3181
3182template <class _CharT>
3183class __money_put
3184{
3185protected:
3186 typedef _CharT char_type;
3187 typedef basic_string<char_type> string_type;
3188
3189 _LIBCPP_ALWAYS_INLINE __money_put() {}
3190
3191 static void __gather_info(bool __intl, bool __neg, const locale& __loc,
3192 money_base::pattern& __pat, char_type& __dp,
3193 char_type& __ts, string& __grp,
3194 string_type& __sym, string_type& __sn,
3195 int& __fd);
3196 static void __format(char_type* __mb, char_type*& __mi, char_type*& __me,
3197 ios_base::fmtflags __flags,
3198 const char_type* __db, const char_type* __de,
3199 const ctype<char_type>& __ct, bool __neg,
3200 const money_base::pattern& __pat, char_type __dp,
3201 char_type __ts, const string& __grp,
3202 const string_type& __sym, const string_type& __sn,
3203 int __fd);
3204};
3205
3206template <class _CharT>
3207void
3208__money_put<_CharT>::__gather_info(bool __intl, bool __neg, const locale& __loc,
3209 money_base::pattern& __pat, char_type& __dp,
3210 char_type& __ts, string& __grp,
3211 string_type& __sym, string_type& __sn,
3212 int& __fd)
3213{
3214 if (__intl)
3215 {
3216 const moneypunct<char_type, true>& __mp =
3217 use_facet<moneypunct<char_type, true> >(__loc);
3218 if (__neg)
3219 {
3220 __pat = __mp.neg_format();
3221 __sn = __mp.negative_sign();
3222 }
3223 else
3224 {
3225 __pat = __mp.pos_format();
3226 __sn = __mp.positive_sign();
3227 }
3228 __dp = __mp.decimal_point();
3229 __ts = __mp.thousands_sep();
3230 __grp = __mp.grouping();
3231 __sym = __mp.curr_symbol();
3232 __fd = __mp.frac_digits();
3233 }
3234 else
3235 {
3236 const moneypunct<char_type, false>& __mp =
3237 use_facet<moneypunct<char_type, false> >(__loc);
3238 if (__neg)
3239 {
3240 __pat = __mp.neg_format();
3241 __sn = __mp.negative_sign();
3242 }
3243 else
3244 {
3245 __pat = __mp.pos_format();
3246 __sn = __mp.positive_sign();
3247 }
3248 __dp = __mp.decimal_point();
3249 __ts = __mp.thousands_sep();
3250 __grp = __mp.grouping();
3251 __sym = __mp.curr_symbol();
3252 __fd = __mp.frac_digits();
3253 }
3254}
3255
3256template <class _CharT>
3257void
3258__money_put<_CharT>::__format(char_type* __mb, char_type*& __mi, char_type*& __me,
3259 ios_base::fmtflags __flags,
3260 const char_type* __db, const char_type* __de,
3261 const ctype<char_type>& __ct, bool __neg,
3262 const money_base::pattern& __pat, char_type __dp,
3263 char_type __ts, const string& __grp,
3264 const string_type& __sym, const string_type& __sn,
3265 int __fd)
3266{
3267 __me = __mb;
3268 for (unsigned __p = 0; __p < 4; ++__p)
3269 {
3270 switch (__pat.field[__p])
3271 {
3272 case money_base::none:
3273 __mi = __me;
3274 break;
3275 case money_base::space:
3276 __mi = __me;
3277 *__me++ = __ct.widen(' ');
3278 break;
3279 case money_base::sign:
3280 if (!__sn.empty())
3281 *__me++ = __sn[0];
3282 break;
3283 case money_base::symbol:
3284 if (!__sym.empty() && (__flags & ios_base::showbase))
Howard Hinnant6cf5d8c2011-02-14 19:12:38 +00003285 __me = _STD::copy(__sym.begin(), __sym.end(), __me);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003286 break;
3287 case money_base::value:
3288 {
3289 // remember start of value so we can reverse it
3290 char_type* __t = __me;
3291 // find beginning of digits
3292 if (__neg)
3293 ++__db;
3294 // find end of digits
3295 const char_type* __d;
3296 for (__d = __db; __d < __de; ++__d)
3297 if (!__ct.is(ctype_base::digit, *__d))
3298 break;
3299 // print fractional part
3300 if (__fd > 0)
3301 {
3302 int __f;
3303 for (__f = __fd; __d > __db && __f > 0; --__f)
3304 *__me++ = *--__d;
3305 char_type __z = __f > 0 ? __ct.widen('0') : char_type();
3306 for (; __f > 0; --__f)
3307 *__me++ = __z;
3308 *__me++ = __dp;
3309 }
3310 // print units part
3311 if (__d == __db)
3312 {
3313 *__me++ = __ct.widen('0');
3314 }
3315 else
3316 {
3317 unsigned __ng = 0;
3318 unsigned __ig = 0;
3319 unsigned __gl = __grp.empty() ? numeric_limits<unsigned>::max()
3320 : static_cast<unsigned>(__grp[__ig]);
3321 while (__d != __db)
3322 {
3323 if (__ng == __gl)
3324 {
3325 *__me++ = __ts;
3326 __ng = 0;
3327 if (++__ig < __grp.size())
3328 __gl = __grp[__ig] == numeric_limits<char>::max() ?
3329 numeric_limits<unsigned>::max() :
3330 static_cast<unsigned>(__grp[__ig]);
3331 }
3332 *__me++ = *--__d;
3333 ++__ng;
3334 }
3335 }
3336 // reverse it
3337 reverse(__t, __me);
3338 }
3339 break;
3340 }
3341 }
3342 // print rest of sign, if any
3343 if (__sn.size() > 1)
Howard Hinnant6cf5d8c2011-02-14 19:12:38 +00003344 __me = _STD::copy(__sn.begin()+1, __sn.end(), __me);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003345 // set alignment
3346 if ((__flags & ios_base::adjustfield) == ios_base::left)
3347 __mi = __me;
3348 else if ((__flags & ios_base::adjustfield) != ios_base::internal)
3349 __mi = __mb;
3350}
3351
3352extern template class __money_put<char>;
3353extern template class __money_put<wchar_t>;
3354
3355template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00003356class _LIBCPP_VISIBLE money_put
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003357 : public locale::facet,
3358 private __money_put<_CharT>
3359{
3360public:
3361 typedef _CharT char_type;
3362 typedef _OutputIterator iter_type;
3363 typedef basic_string<char_type> string_type;
3364
3365 _LIBCPP_ALWAYS_INLINE
3366 explicit money_put(size_t __refs = 0)
3367 : locale::facet(__refs) {}
3368
3369 _LIBCPP_ALWAYS_INLINE
3370 iter_type put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl,
3371 long double __units) const
3372 {
3373 return do_put(__s, __intl, __iob, __fl, __units);
3374 }
3375
3376 _LIBCPP_ALWAYS_INLINE
3377 iter_type put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl,
3378 const string_type& __digits) const
3379 {
3380 return do_put(__s, __intl, __iob, __fl, __digits);
3381 }
3382
3383 static locale::id id;
3384
3385protected:
Howard Hinnant82894812010-09-22 16:48:34 +00003386 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003387 ~money_put() {}
3388
3389 virtual iter_type do_put(iter_type __s, bool __intl, ios_base& __iob,
3390 char_type __fl, long double __units) const;
3391 virtual iter_type do_put(iter_type __s, bool __intl, ios_base& __iob,
3392 char_type __fl, const string_type& __digits) const;
3393};
3394
3395template <class _CharT, class _OutputIterator>
3396locale::id
3397money_put<_CharT, _OutputIterator>::id;
3398
3399template <class _CharT, class _OutputIterator>
3400_OutputIterator
3401money_put<_CharT, _OutputIterator>::do_put(iter_type __s, bool __intl,
3402 ios_base& __iob, char_type __fl,
3403 long double __units) const
3404{
3405 // convert to char
3406 const size_t __bs = 100;
3407 char __buf[__bs];
3408 char* __bb = __buf;
3409 char_type __digits[__bs];
3410 char_type* __db = __digits;
3411 size_t __n = snprintf(__bb, __bs, "%.0Lf", __units);
3412 unique_ptr<char, void(*)(void*)> __hn(0, free);
3413 unique_ptr<char_type, void(*)(void*)> __hd(0, free);
3414 // secure memory for digit storage
3415 if (__n > __bs-1)
3416 {
Howard Hinnantadff4892010-05-24 17:49:41 +00003417 __n = __nolocale_asprintf(&__bb, "%.0Lf", __units);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003418 if (__bb == 0)
3419 __throw_bad_alloc();
3420 __hn.reset(__bb);
3421 __hd.reset((char_type*)malloc(__n * sizeof(char_type)));
3422 if (__hd == 0)
3423 __throw_bad_alloc();
3424 __db = __hd.get();
3425 }
3426 // gather info
3427 locale __loc = __iob.getloc();
3428 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3429 __ct.widen(__bb, __bb + __n, __db);
3430 bool __neg = __n > 0 && __bb[0] == '-';
3431 money_base::pattern __pat;
3432 char_type __dp;
3433 char_type __ts;
3434 string __grp;
3435 string_type __sym;
3436 string_type __sn;
3437 int __fd;
3438 this->__gather_info(__intl, __neg, __loc, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3439 // secure memory for formatting
3440 char_type __mbuf[__bs];
3441 char_type* __mb = __mbuf;
3442 unique_ptr<char_type, void(*)(void*)> __hw(0, free);
3443 size_t __exn = static_cast<int>(__n) > __fd ?
3444 (__n - __fd) * 2 + __sn.size() + __sym.size() + __fd + 1
3445 : __sn.size() + __sym.size() + __fd + 2;
3446 if (__exn > __bs)
3447 {
3448 __hw.reset((char_type*)malloc(__exn * sizeof(char_type)));
3449 __mb = __hw.get();
3450 if (__mb == 0)
3451 __throw_bad_alloc();
3452 }
3453 // format
3454 char_type* __mi;
3455 char_type* __me;
3456 this->__format(__mb, __mi, __me, __iob.flags(),
3457 __db, __db + __n, __ct,
3458 __neg, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3459 return __pad_and_output(__s, __mb, __mi, __me, __iob, __fl);
3460}
3461
3462template <class _CharT, class _OutputIterator>
3463_OutputIterator
3464money_put<_CharT, _OutputIterator>::do_put(iter_type __s, bool __intl,
3465 ios_base& __iob, char_type __fl,
3466 const string_type& __digits) const
3467{
3468 // gather info
3469 locale __loc = __iob.getloc();
3470 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3471 bool __neg = __digits.size() > 0 && __digits[0] == __ct.widen('-');
3472 money_base::pattern __pat;
3473 char_type __dp;
3474 char_type __ts;
3475 string __grp;
3476 string_type __sym;
3477 string_type __sn;
3478 int __fd;
3479 this->__gather_info(__intl, __neg, __loc, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3480 // secure memory for formatting
3481 char_type __mbuf[100];
3482 char_type* __mb = __mbuf;
3483 unique_ptr<char_type, void(*)(void*)> __h(0, free);
3484 size_t __exn = __digits.size() > __fd ?
3485 (__digits.size() - __fd) * 2 + __sn.size() + __sym.size() + __fd + 1
3486 : __sn.size() + __sym.size() + __fd + 2;
3487 if (__exn > 100)
3488 {
3489 __h.reset((char_type*)malloc(__exn * sizeof(char_type)));
3490 __mb = __h.get();
3491 if (__mb == 0)
3492 __throw_bad_alloc();
3493 }
3494 // format
3495 char_type* __mi;
3496 char_type* __me;
3497 this->__format(__mb, __mi, __me, __iob.flags(),
3498 __digits.data(), __digits.data() + __digits.size(), __ct,
3499 __neg, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3500 return __pad_and_output(__s, __mb, __mi, __me, __iob, __fl);
3501}
3502
3503extern template class money_put<char>;
3504extern template class money_put<wchar_t>;
3505
3506// messages
3507
Howard Hinnant82894812010-09-22 16:48:34 +00003508class _LIBCPP_VISIBLE messages_base
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003509{
3510public:
Howard Hinnantb2080c72011-02-25 00:51:08 +00003511 typedef ptrdiff_t catalog;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003512
3513 _LIBCPP_ALWAYS_INLINE messages_base() {}
3514};
3515
3516template <class _CharT>
Howard Hinnant82894812010-09-22 16:48:34 +00003517class _LIBCPP_VISIBLE messages
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003518 : public locale::facet,
3519 public messages_base
3520{
3521public:
3522 typedef _CharT char_type;
3523 typedef basic_string<_CharT> string_type;
3524
3525 _LIBCPP_ALWAYS_INLINE
3526 explicit messages(size_t __refs = 0)
3527 : locale::facet(__refs) {}
3528
3529 _LIBCPP_ALWAYS_INLINE
3530 catalog open(const basic_string<char>& __nm, const locale& __loc) const
3531 {
3532 return do_open(__nm, __loc);
3533 }
3534
3535 _LIBCPP_ALWAYS_INLINE
3536 string_type get(catalog __c, int __set, int __msgid,
3537 const string_type& __dflt) const
3538 {
3539 return do_get(__c, __set, __msgid, __dflt);
3540 }
3541
3542 _LIBCPP_ALWAYS_INLINE
3543 void close(catalog __c) const
3544 {
3545 do_close(__c);
3546 }
3547
3548 static locale::id id;
3549
3550protected:
Howard Hinnant82894812010-09-22 16:48:34 +00003551 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003552 ~messages() {}
3553
3554 virtual catalog do_open(const basic_string<char>&, const locale&) const;
3555 virtual string_type do_get(catalog, int __set, int __msgid,
3556 const string_type& __dflt) const;
3557 virtual void do_close(catalog) const;
3558};
3559
3560template <class _CharT>
3561locale::id
3562messages<_CharT>::id;
3563
3564template <class _CharT>
3565typename messages<_CharT>::catalog
3566messages<_CharT>::do_open(const basic_string<char>& __nm, const locale&) const
3567{
Howard Hinnantb2080c72011-02-25 00:51:08 +00003568 catalog __cat = reinterpret_cast<catalog>(catopen(__nm.c_str(), NL_CAT_LOCALE));
3569 if (__cat != -1)
3570 __cat = static_cast<catalog>((static_cast<size_t>(__cat) >> 1));
3571 return __cat;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003572}
3573
3574template <class _CharT>
3575typename messages<_CharT>::string_type
3576messages<_CharT>::do_get(catalog __c, int __set, int __msgid,
3577 const string_type& __dflt) const
3578{
3579 string __ndflt;
3580 __narrow_to_utf8<sizeof(char_type)*__CHAR_BIT__>()(back_inserter(__ndflt),
3581 __dflt.c_str(),
3582 __dflt.c_str() + __dflt.size());
Howard Hinnantb2080c72011-02-25 00:51:08 +00003583 if (__c != -1)
3584 __c <<= 1;
3585 nl_catd __cat = reinterpret_cast<nl_catd>(__c);
3586 char* __n = catgets(__cat, __set, __msgid, __ndflt.c_str());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003587 string_type __w;
3588 __widen_from_utf8<sizeof(char_type)*__CHAR_BIT__>()(back_inserter(__w),
3589 __n, __n + strlen(__n));
3590 return __w;
3591}
3592
3593template <class _CharT>
3594void
3595messages<_CharT>::do_close(catalog __c) const
3596{
Howard Hinnantb2080c72011-02-25 00:51:08 +00003597 if (__c != -1)
3598 __c <<= 1;
3599 nl_catd __cat = reinterpret_cast<nl_catd>(__c);
3600 catclose(__cat);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003601}
3602
3603extern template class messages<char>;
3604extern template class messages<wchar_t>;
3605
3606template <class _CharT>
Howard Hinnant82894812010-09-22 16:48:34 +00003607class _LIBCPP_VISIBLE messages_byname
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003608 : public messages<_CharT>
3609{
3610public:
3611 typedef messages_base::catalog catalog;
3612 typedef basic_string<_CharT> string_type;
3613
3614 _LIBCPP_ALWAYS_INLINE
3615 explicit messages_byname(const char*, size_t __refs = 0)
3616 : messages<_CharT>(__refs) {}
3617
3618 _LIBCPP_ALWAYS_INLINE
3619 explicit messages_byname(const string&, size_t __refs = 0)
3620 : messages<_CharT>(__refs) {}
3621
3622protected:
Howard Hinnant82894812010-09-22 16:48:34 +00003623 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003624 ~messages_byname() {}
3625};
3626
3627extern template class messages_byname<char>;
3628extern template class messages_byname<wchar_t>;
3629
Howard Hinnantd23b4642010-05-31 20:58:54 +00003630template<class _Codecvt, class _Elem = wchar_t,
3631 class _Wide_alloc = allocator<_Elem>,
3632 class _Byte_alloc = allocator<char> >
Howard Hinnant82894812010-09-22 16:48:34 +00003633class _LIBCPP_VISIBLE wstring_convert
Howard Hinnantd23b4642010-05-31 20:58:54 +00003634{
3635public:
3636 typedef basic_string<char, char_traits<char>, _Byte_alloc> byte_string;
3637 typedef basic_string<_Elem, char_traits<_Elem>, _Wide_alloc> wide_string;
3638 typedef typename _Codecvt::state_type state_type;
3639 typedef typename wide_string::traits_type::int_type int_type;
3640
3641private:
3642 byte_string __byte_err_string_;
3643 wide_string __wide_err_string_;
3644 _Codecvt* __cvtptr_;
3645 state_type __cvtstate_;
3646 size_t __cvtcount_;
3647
3648 wstring_convert(const wstring_convert& __wc);
3649 wstring_convert& operator=(const wstring_convert& __wc);
3650public:
3651 wstring_convert(_Codecvt* __pcvt = new _Codecvt);
3652 wstring_convert(_Codecvt* __pcvt, state_type __state);
3653 wstring_convert(const byte_string& __byte_err,
3654 const wide_string& __wide_err = wide_string());
Howard Hinnant73d21a42010-09-04 23:28:19 +00003655#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantd23b4642010-05-31 20:58:54 +00003656 wstring_convert(wstring_convert&& __wc);
3657#endif
3658 ~wstring_convert();
3659
Howard Hinnant82894812010-09-22 16:48:34 +00003660 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003661 wide_string from_bytes(char __byte)
3662 {return from_bytes(&__byte, &__byte+1);}
Howard Hinnant82894812010-09-22 16:48:34 +00003663 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003664 wide_string from_bytes(const char* __ptr)
3665 {return from_bytes(__ptr, __ptr + char_traits<char>::length(__ptr));}
Howard Hinnant82894812010-09-22 16:48:34 +00003666 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003667 wide_string from_bytes(const byte_string& __str)
3668 {return from_bytes(__str.data(), __str.data() + __str.size());}
3669 wide_string from_bytes(const char* __first, const char* __last);
3670
Howard Hinnant82894812010-09-22 16:48:34 +00003671 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003672 byte_string to_bytes(_Elem __wchar)
3673 {return to_bytes(&__wchar, &__wchar+1);}
Howard Hinnant82894812010-09-22 16:48:34 +00003674 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003675 byte_string to_bytes(const _Elem* __wptr)
3676 {return to_bytes(__wptr, __wptr + char_traits<_Elem>::length(__wptr));}
Howard Hinnant82894812010-09-22 16:48:34 +00003677 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003678 byte_string to_bytes(const wide_string& __wstr)
3679 {return to_bytes(__wstr.data(), __wstr.data() + __wstr.size());}
3680 byte_string to_bytes(const _Elem* __first, const _Elem* __last);
3681
Howard Hinnant82894812010-09-22 16:48:34 +00003682 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003683 size_t converted() const {return __cvtcount_;}
Howard Hinnant82894812010-09-22 16:48:34 +00003684 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003685 state_type state() const {return __cvtstate_;}
3686};
3687
3688template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Howard Hinnant82894812010-09-22 16:48:34 +00003689inline _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003690wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3691 wstring_convert(_Codecvt* __pcvt)
3692 : __cvtptr_(__pcvt), __cvtstate_(), __cvtcount_(0)
3693{
3694}
3695
3696template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Howard Hinnant82894812010-09-22 16:48:34 +00003697inline _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003698wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3699 wstring_convert(_Codecvt* __pcvt, state_type __state)
3700 : __cvtptr_(__pcvt), __cvtstate_(__state), __cvtcount_(0)
3701{
3702}
3703
3704template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3705wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3706 wstring_convert(const byte_string& __byte_err, const wide_string& __wide_err)
3707 : __byte_err_string_(__byte_err), __wide_err_string_(__wide_err),
3708 __cvtstate_(), __cvtcount_(0)
3709{
3710 __cvtptr_ = new _Codecvt;
3711}
3712
Howard Hinnant73d21a42010-09-04 23:28:19 +00003713#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantd23b4642010-05-31 20:58:54 +00003714
3715template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Howard Hinnant82894812010-09-22 16:48:34 +00003716inline _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003717wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3718 wstring_convert(wstring_convert&& __wc)
3719 : __byte_err_string_(_STD::move(__wc.__byte_err_string_)),
3720 __wide_err_string_(_STD::move(__wc.__wide_err_string_)),
3721 __cvtptr_(__wc.__cvtptr_),
3722 __cvtstate_(__wc.__cvtstate_), __cvtcount_(__wc.__cvtstate_)
3723{
3724 __wc.__cvtptr_ = nullptr;
3725}
3726
Howard Hinnantbfd55302010-09-04 23:46:48 +00003727#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantd23b4642010-05-31 20:58:54 +00003728
3729template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3730wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::~wstring_convert()
3731{
3732 delete __cvtptr_;
3733}
3734
3735template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3736typename wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::wide_string
3737wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3738 from_bytes(const char* __frm, const char* __frm_end)
3739{
3740 __cvtcount_ = 0;
3741 if (__cvtptr_ != nullptr)
3742 {
3743 wide_string __ws(2*(__frm_end - __frm), _Elem());
3744 __ws.resize(__ws.capacity());
3745 codecvt_base::result __r = codecvt_base::ok;
3746 state_type __st = __cvtstate_;
3747 if (__frm != __frm_end)
3748 {
3749 _Elem* __to = &__ws[0];
3750 _Elem* __to_end = __to + __ws.size();
3751 const char* __frm_nxt;
3752 do
3753 {
3754 _Elem* __to_nxt;
3755 __r = __cvtptr_->in(__st, __frm, __frm_end, __frm_nxt,
3756 __to, __to_end, __to_nxt);
3757 __cvtcount_ += __frm_nxt - __frm;
3758 if (__frm_nxt == __frm)
3759 {
3760 __r = codecvt_base::error;
3761 }
3762 else if (__r == codecvt_base::noconv)
3763 {
3764 __ws.resize(__to - &__ws[0]);
3765 // This only gets executed if _Elem is char
3766 __ws.append((const _Elem*)__frm, (const _Elem*)__frm_end);
3767 __frm = __frm_nxt;
3768 __r = codecvt_base::ok;
3769 }
3770 else if (__r == codecvt_base::ok)
3771 {
3772 __ws.resize(__to_nxt - &__ws[0]);
3773 __frm = __frm_nxt;
3774 }
3775 else if (__r == codecvt_base::partial)
3776 {
3777 ptrdiff_t __s = __to_nxt - &__ws[0];
3778 __ws.resize(2 * __s);
3779 __to = &__ws[0] + __s;
3780 __to_end = &__ws[0] + __ws.size();
3781 __frm = __frm_nxt;
3782 }
3783 } while (__r == codecvt_base::partial && __frm_nxt < __frm_end);
3784 }
3785 if (__r == codecvt_base::ok)
3786 return __ws;
3787 }
Howard Hinnantd4444702010-08-11 17:04:31 +00003788#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00003789 if (__wide_err_string_.empty())
3790 throw range_error("wstring_convert: from_bytes error");
Howard Hinnant324bb032010-08-22 00:02:43 +00003791#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00003792 return __wide_err_string_;
3793}
3794
3795template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3796typename wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::byte_string
3797wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3798 to_bytes(const _Elem* __frm, const _Elem* __frm_end)
3799{
3800 __cvtcount_ = 0;
3801 if (__cvtptr_ != nullptr)
3802 {
3803 byte_string __bs(2*(__frm_end - __frm), char());
3804 __bs.resize(__bs.capacity());
3805 codecvt_base::result __r = codecvt_base::ok;
3806 state_type __st = __cvtstate_;
3807 if (__frm != __frm_end)
3808 {
3809 char* __to = &__bs[0];
3810 char* __to_end = __to + __bs.size();
3811 const _Elem* __frm_nxt;
3812 do
3813 {
3814 char* __to_nxt;
3815 __r = __cvtptr_->out(__st, __frm, __frm_end, __frm_nxt,
3816 __to, __to_end, __to_nxt);
3817 __cvtcount_ += __frm_nxt - __frm;
3818 if (__frm_nxt == __frm)
3819 {
3820 __r = codecvt_base::error;
3821 }
3822 else if (__r == codecvt_base::noconv)
3823 {
3824 __bs.resize(__to - &__bs[0]);
3825 // This only gets executed if _Elem is char
3826 __bs.append((const char*)__frm, (const char*)__frm_end);
3827 __frm = __frm_nxt;
3828 __r = codecvt_base::ok;
3829 }
3830 else if (__r == codecvt_base::ok)
3831 {
3832 __bs.resize(__to_nxt - &__bs[0]);
3833 __frm = __frm_nxt;
3834 }
3835 else if (__r == codecvt_base::partial)
3836 {
3837 ptrdiff_t __s = __to_nxt - &__bs[0];
3838 __bs.resize(2 * __s);
3839 __to = &__bs[0] + __s;
3840 __to_end = &__bs[0] + __bs.size();
3841 __frm = __frm_nxt;
3842 }
3843 } while (__r == codecvt_base::partial && __frm_nxt < __frm_end);
3844 }
3845 if (__r == codecvt_base::ok)
3846 {
3847 size_t __s = __bs.size();
3848 __bs.resize(__bs.capacity());
3849 char* __to = &__bs[0] + __s;
3850 char* __to_end = __to + __bs.size();
3851 do
3852 {
3853 char* __to_nxt;
3854 __r = __cvtptr_->unshift(__st, __to, __to_end, __to_nxt);
3855 if (__r == codecvt_base::noconv)
3856 {
3857 __bs.resize(__to - &__bs[0]);
3858 __r = codecvt_base::ok;
3859 }
3860 else if (__r == codecvt_base::ok)
3861 {
3862 __bs.resize(__to_nxt - &__bs[0]);
3863 }
3864 else if (__r == codecvt_base::partial)
3865 {
3866 ptrdiff_t __s = __to_nxt - &__bs[0];
3867 __bs.resize(2 * __s);
3868 __to = &__bs[0] + __s;
3869 __to_end = &__bs[0] + __bs.size();
3870 }
3871 } while (__r == codecvt_base::partial);
3872 if (__r == codecvt_base::ok)
3873 return __bs;
3874 }
3875 }
Howard Hinnantd4444702010-08-11 17:04:31 +00003876#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00003877 if (__byte_err_string_.empty())
3878 throw range_error("wstring_convert: to_bytes error");
Howard Hinnant324bb032010-08-22 00:02:43 +00003879#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00003880 return __byte_err_string_;
3881}
3882
3883template <class _Codecvt, class _Elem = wchar_t, class _Tr = char_traits<_Elem> >
Howard Hinnant82894812010-09-22 16:48:34 +00003884class _LIBCPP_VISIBLE wbuffer_convert
Howard Hinnantd23b4642010-05-31 20:58:54 +00003885 : public basic_streambuf<_Elem, _Tr>
3886{
3887public:
3888 // types:
3889 typedef _Elem char_type;
3890 typedef _Tr traits_type;
3891 typedef typename traits_type::int_type int_type;
3892 typedef typename traits_type::pos_type pos_type;
3893 typedef typename traits_type::off_type off_type;
3894 typedef typename _Codecvt::state_type state_type;
3895
3896private:
Howard Hinnant4b53f502010-06-01 20:09:18 +00003897 char* __extbuf_;
3898 const char* __extbufnext_;
3899 const char* __extbufend_;
3900 char __extbuf_min_[8];
3901 size_t __ebs_;
3902 char_type* __intbuf_;
3903 size_t __ibs_;
Howard Hinnantd23b4642010-05-31 20:58:54 +00003904 streambuf* __bufptr_;
Howard Hinnant4b53f502010-06-01 20:09:18 +00003905 _Codecvt* __cv_;
3906 state_type __st_;
3907 ios_base::openmode __cm_;
3908 bool __owns_eb_;
3909 bool __owns_ib_;
3910 bool __always_noconv_;
Howard Hinnantd23b4642010-05-31 20:58:54 +00003911
Howard Hinnant4b53f502010-06-01 20:09:18 +00003912 wbuffer_convert(const wbuffer_convert&);
3913 wbuffer_convert& operator=(const wbuffer_convert&);
Howard Hinnantd23b4642010-05-31 20:58:54 +00003914public:
3915 wbuffer_convert(streambuf* __bytebuf = 0, _Codecvt* __pcvt = new _Codecvt,
Howard Hinnant4b53f502010-06-01 20:09:18 +00003916 state_type __state = state_type());
3917 ~wbuffer_convert();
Howard Hinnantd23b4642010-05-31 20:58:54 +00003918
Howard Hinnant82894812010-09-22 16:48:34 +00003919 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantd23b4642010-05-31 20:58:54 +00003920 streambuf* rdbuf() const {return __bufptr_;}
Howard Hinnant82894812010-09-22 16:48:34 +00003921 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantd23b4642010-05-31 20:58:54 +00003922 streambuf* rdbuf(streambuf* __bytebuf)
3923 {
3924 streambuf* __r = __bufptr_;
3925 __bufptr_ = __bytebuf;
3926 return __r;
3927 }
3928
Howard Hinnant82894812010-09-22 16:48:34 +00003929 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant4b53f502010-06-01 20:09:18 +00003930 state_type state() const {return __st_;}
Howard Hinnantd23b4642010-05-31 20:58:54 +00003931
3932protected:
Howard Hinnant4b53f502010-06-01 20:09:18 +00003933 virtual int_type underflow();
3934 virtual int_type pbackfail(int_type __c = traits_type::eof());
Howard Hinnantd23b4642010-05-31 20:58:54 +00003935 virtual int_type overflow (int_type __c = traits_type::eof());
Howard Hinnant4b53f502010-06-01 20:09:18 +00003936 virtual basic_streambuf<char_type, traits_type>* setbuf(char_type* __s,
3937 streamsize __n);
3938 virtual pos_type seekoff(off_type __off, ios_base::seekdir __way,
3939 ios_base::openmode __wch = ios_base::in | ios_base::out);
3940 virtual pos_type seekpos(pos_type __sp,
3941 ios_base::openmode __wch = ios_base::in | ios_base::out);
3942 virtual int sync();
3943
3944private:
3945 bool __read_mode();
3946 void __write_mode();
3947 wbuffer_convert* __close();
Howard Hinnantd23b4642010-05-31 20:58:54 +00003948};
3949
3950template <class _Codecvt, class _Elem, class _Tr>
Howard Hinnant4b53f502010-06-01 20:09:18 +00003951wbuffer_convert<_Codecvt, _Elem, _Tr>::
3952 wbuffer_convert(streambuf* __bytebuf, _Codecvt* __pcvt, state_type __state)
3953 : __extbuf_(0),
3954 __extbufnext_(0),
3955 __extbufend_(0),
3956 __ebs_(0),
3957 __intbuf_(0),
3958 __ibs_(0),
3959 __bufptr_(__bytebuf),
3960 __cv_(__pcvt),
3961 __st_(__state),
3962 __cm_(0),
3963 __owns_eb_(false),
3964 __owns_ib_(false),
3965 __always_noconv_(__cv_ ? __cv_->always_noconv() : false)
3966{
3967 setbuf(0, 4096);
3968}
3969
3970template <class _Codecvt, class _Elem, class _Tr>
3971wbuffer_convert<_Codecvt, _Elem, _Tr>::~wbuffer_convert()
3972{
3973 __close();
3974 delete __cv_;
3975 if (__owns_eb_)
3976 delete [] __extbuf_;
3977 if (__owns_ib_)
3978 delete [] __intbuf_;
3979}
3980
3981template <class _Codecvt, class _Elem, class _Tr>
3982typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
3983wbuffer_convert<_Codecvt, _Elem, _Tr>::underflow()
3984{
3985 if (__cv_ == 0 || __bufptr_ == 0)
3986 return traits_type::eof();
3987 bool __initial = __read_mode();
3988 char_type __1buf;
3989 if (this->gptr() == 0)
3990 this->setg(&__1buf, &__1buf+1, &__1buf+1);
3991 const size_t __unget_sz = __initial ? 0 : min<size_t>((this->egptr() - this->eback()) / 2, 4);
3992 int_type __c = traits_type::eof();
3993 if (this->gptr() == this->egptr())
3994 {
3995 memmove(this->eback(), this->egptr() - __unget_sz, __unget_sz * sizeof(char_type));
3996 if (__always_noconv_)
3997 {
3998 streamsize __nmemb = static_cast<streamsize>(this->egptr() - this->eback() - __unget_sz);
3999 __nmemb = __bufptr_->sgetn((char*)this->eback() + __unget_sz, __nmemb);
4000 if (__nmemb != 0)
4001 {
4002 this->setg(this->eback(),
4003 this->eback() + __unget_sz,
4004 this->eback() + __unget_sz + __nmemb);
4005 __c = *this->gptr();
4006 }
4007 }
4008 else
4009 {
4010 memmove(__extbuf_, __extbufnext_, __extbufend_ - __extbufnext_);
4011 __extbufnext_ = __extbuf_ + (__extbufend_ - __extbufnext_);
4012 __extbufend_ = __extbuf_ + (__extbuf_ == __extbuf_min_ ? sizeof(__extbuf_min_) : __ebs_);
Howard Hinnant6cf5d8c2011-02-14 19:12:38 +00004013 streamsize __nmemb = _STD::min(static_cast<streamsize>(this->egptr() - this->eback() - __unget_sz),
Howard Hinnant4b53f502010-06-01 20:09:18 +00004014 static_cast<streamsize>(__extbufend_ - __extbufnext_));
4015 codecvt_base::result __r;
4016 state_type __svs = __st_;
4017 streamsize __nr = __bufptr_->sgetn(const_cast<char*>(__extbufnext_), __nmemb);
4018 if (__nr != 0)
4019 {
4020 __extbufend_ = __extbufnext_ + __nr;
4021 char_type* __inext;
4022 __r = __cv_->in(__st_, __extbuf_, __extbufend_, __extbufnext_,
4023 this->eback() + __unget_sz,
4024 this->egptr(), __inext);
4025 if (__r == codecvt_base::noconv)
4026 {
4027 this->setg((char_type*)__extbuf_, (char_type*)__extbuf_, (char_type*)__extbufend_);
4028 __c = *this->gptr();
4029 }
4030 else if (__inext != this->eback() + __unget_sz)
4031 {
4032 this->setg(this->eback(), this->eback() + __unget_sz, __inext);
4033 __c = *this->gptr();
4034 }
4035 }
4036 }
4037 }
4038 else
4039 __c = *this->gptr();
4040 if (this->eback() == &__1buf)
4041 this->setg(0, 0, 0);
4042 return __c;
4043}
4044
4045template <class _Codecvt, class _Elem, class _Tr>
4046typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
4047wbuffer_convert<_Codecvt, _Elem, _Tr>::pbackfail(int_type __c)
4048{
4049 if (__cv_ != 0 && __bufptr_ != 0 && this->eback() < this->gptr())
4050 {
4051 if (traits_type::eq_int_type(__c, traits_type::eof()))
4052 {
4053 this->gbump(-1);
4054 return traits_type::not_eof(__c);
4055 }
4056 if (traits_type::eq(traits_type::to_char_type(__c), this->gptr()[-1]))
4057 {
4058 this->gbump(-1);
4059 *this->gptr() = traits_type::to_char_type(__c);
4060 return __c;
4061 }
4062 }
4063 return traits_type::eof();
4064}
4065
4066template <class _Codecvt, class _Elem, class _Tr>
Howard Hinnantd23b4642010-05-31 20:58:54 +00004067typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
4068wbuffer_convert<_Codecvt, _Elem, _Tr>::overflow(int_type __c)
4069{
Howard Hinnant4b53f502010-06-01 20:09:18 +00004070 if (__cv_ == 0 || __bufptr_ == 0)
4071 return traits_type::eof();
4072 __write_mode();
4073 char_type __1buf;
4074 char_type* __pb_save = this->pbase();
4075 char_type* __epb_save = this->epptr();
4076 if (!traits_type::eq_int_type(__c, traits_type::eof()))
4077 {
4078 if (this->pptr() == 0)
4079 this->setp(&__1buf, &__1buf+1);
4080 *this->pptr() = traits_type::to_char_type(__c);
4081 this->pbump(1);
4082 }
4083 if (this->pptr() != this->pbase())
4084 {
4085 if (__always_noconv_)
4086 {
4087 streamsize __nmemb = static_cast<streamsize>(this->pptr() - this->pbase());
4088 if (__bufptr_->sputn((const char*)this->pbase(), __nmemb) != __nmemb)
4089 return traits_type::eof();
4090 }
4091 else
4092 {
4093 char* __extbe = __extbuf_;
4094 codecvt_base::result __r;
4095 do
4096 {
4097 const char_type* __e;
4098 __r = __cv_->out(__st_, this->pbase(), this->pptr(), __e,
4099 __extbuf_, __extbuf_ + __ebs_, __extbe);
4100 if (__e == this->pbase())
4101 return traits_type::eof();
4102 if (__r == codecvt_base::noconv)
4103 {
4104 streamsize __nmemb = static_cast<size_t>(this->pptr() - this->pbase());
4105 if (__bufptr_->sputn((const char*)this->pbase(), __nmemb) != __nmemb)
4106 return traits_type::eof();
4107 }
4108 else if (__r == codecvt_base::ok || __r == codecvt_base::partial)
4109 {
4110 streamsize __nmemb = static_cast<size_t>(__extbe - __extbuf_);
4111 if (__bufptr_->sputn(__extbuf_, __nmemb) != __nmemb)
4112 return traits_type::eof();
4113 if (__r == codecvt_base::partial)
4114 {
4115 this->setp((char_type*)__e, this->pptr());
4116 this->pbump(this->epptr() - this->pbase());
4117 }
4118 }
4119 else
4120 return traits_type::eof();
4121 } while (__r == codecvt_base::partial);
4122 }
4123 this->setp(__pb_save, __epb_save);
4124 }
4125 return traits_type::not_eof(__c);
4126}
4127
4128template <class _Codecvt, class _Elem, class _Tr>
4129basic_streambuf<_Elem, _Tr>*
4130wbuffer_convert<_Codecvt, _Elem, _Tr>::setbuf(char_type* __s, streamsize __n)
4131{
4132 this->setg(0, 0, 0);
4133 this->setp(0, 0);
4134 if (__owns_eb_)
4135 delete [] __extbuf_;
4136 if (__owns_ib_)
4137 delete [] __intbuf_;
4138 __ebs_ = __n;
4139 if (__ebs_ > sizeof(__extbuf_min_))
4140 {
4141 if (__always_noconv_ && __s)
4142 {
4143 __extbuf_ = (char*)__s;
4144 __owns_eb_ = false;
4145 }
4146 else
4147 {
4148 __extbuf_ = new char[__ebs_];
4149 __owns_eb_ = true;
4150 }
4151 }
4152 else
4153 {
4154 __extbuf_ = __extbuf_min_;
4155 __ebs_ = sizeof(__extbuf_min_);
4156 __owns_eb_ = false;
4157 }
4158 if (!__always_noconv_)
4159 {
4160 __ibs_ = max<streamsize>(__n, sizeof(__extbuf_min_));
4161 if (__s && __ibs_ >= sizeof(__extbuf_min_))
4162 {
4163 __intbuf_ = __s;
4164 __owns_ib_ = false;
4165 }
4166 else
4167 {
4168 __intbuf_ = new char_type[__ibs_];
4169 __owns_ib_ = true;
4170 }
4171 }
4172 else
4173 {
4174 __ibs_ = 0;
4175 __intbuf_ = 0;
4176 __owns_ib_ = false;
4177 }
4178 return this;
4179}
4180
4181template <class _Codecvt, class _Elem, class _Tr>
4182typename wbuffer_convert<_Codecvt, _Elem, _Tr>::pos_type
4183wbuffer_convert<_Codecvt, _Elem, _Tr>::seekoff(off_type __off, ios_base::seekdir __way,
4184 ios_base::openmode __om)
4185{
4186 int __width = __cv_->encoding();
4187 if (__cv_ == 0 || __bufptr_ == 0 || (__width <= 0 && __off != 0) || sync())
4188 return pos_type(off_type(-1));
4189 // __width > 0 || __off == 0
4190 switch (__way)
4191 {
4192 case ios_base::beg:
4193 break;
4194 case ios_base::cur:
4195 break;
4196 case ios_base::end:
4197 break;
4198 default:
4199 return pos_type(off_type(-1));
4200 }
4201 pos_type __r = __bufptr_->pubseekoff(__width * __off, __way, __om);
4202 __r.state(__st_);
4203 return __r;
4204}
4205
4206template <class _Codecvt, class _Elem, class _Tr>
4207typename wbuffer_convert<_Codecvt, _Elem, _Tr>::pos_type
4208wbuffer_convert<_Codecvt, _Elem, _Tr>::seekpos(pos_type __sp, ios_base::openmode __wch)
4209{
4210 if (__cv_ == 0 || __bufptr_ == 0 || sync())
4211 return pos_type(off_type(-1));
4212 if (__bufptr_->pubseekpos(__sp, __wch) == pos_type(off_type(-1)))
4213 return pos_type(off_type(-1));
4214 return __sp;
4215}
4216
4217template <class _Codecvt, class _Elem, class _Tr>
4218int
4219wbuffer_convert<_Codecvt, _Elem, _Tr>::sync()
4220{
4221 if (__cv_ == 0 || __bufptr_ == 0)
4222 return 0;
4223 if (__cm_ & ios_base::out)
4224 {
4225 if (this->pptr() != this->pbase())
4226 if (overflow() == traits_type::eof())
4227 return -1;
4228 codecvt_base::result __r;
4229 do
4230 {
4231 char* __extbe;
4232 __r = __cv_->unshift(__st_, __extbuf_, __extbuf_ + __ebs_, __extbe);
4233 streamsize __nmemb = static_cast<streamsize>(__extbe - __extbuf_);
4234 if (__bufptr_->sputn(__extbuf_, __nmemb) != __nmemb)
4235 return -1;
4236 } while (__r == codecvt_base::partial);
4237 if (__r == codecvt_base::error)
4238 return -1;
4239 if (__bufptr_->pubsync())
4240 return -1;
4241 }
4242 else if (__cm_ & ios_base::in)
4243 {
4244 off_type __c;
4245 if (__always_noconv_)
4246 __c = this->egptr() - this->gptr();
4247 else
4248 {
4249 int __width = __cv_->encoding();
4250 __c = __extbufend_ - __extbufnext_;
4251 if (__width > 0)
4252 __c += __width * (this->egptr() - this->gptr());
4253 else
4254 {
4255 if (this->gptr() != this->egptr())
4256 {
4257 reverse(this->gptr(), this->egptr());
4258 codecvt_base::result __r;
4259 const char_type* __e = this->gptr();
4260 char* __extbe;
4261 do
4262 {
4263 __r = __cv_->out(__st_, __e, this->egptr(), __e,
4264 __extbuf_, __extbuf_ + __ebs_, __extbe);
4265 switch (__r)
4266 {
4267 case codecvt_base::noconv:
4268 __c += this->egptr() - this->gptr();
4269 break;
4270 case codecvt_base::ok:
4271 case codecvt_base::partial:
4272 __c += __extbe - __extbuf_;
4273 break;
4274 default:
4275 return -1;
4276 }
4277 } while (__r == codecvt_base::partial);
4278 }
4279 }
4280 }
4281 if (__bufptr_->pubseekoff(-__c, ios_base::cur, __cm_) == pos_type(off_type(-1)))
4282 return -1;
4283 this->setg(0, 0, 0);
4284 __cm_ = 0;
4285 }
4286 return 0;
4287}
4288
4289template <class _Codecvt, class _Elem, class _Tr>
4290bool
4291wbuffer_convert<_Codecvt, _Elem, _Tr>::__read_mode()
4292{
4293 if (!(__cm_ & ios_base::in))
4294 {
4295 this->setp(0, 0);
4296 if (__always_noconv_)
4297 this->setg((char_type*)__extbuf_,
4298 (char_type*)__extbuf_ + __ebs_,
4299 (char_type*)__extbuf_ + __ebs_);
4300 else
4301 this->setg(__intbuf_, __intbuf_ + __ibs_, __intbuf_ + __ibs_);
4302 __cm_ = ios_base::in;
4303 return true;
4304 }
4305 return false;
4306}
4307
4308template <class _Codecvt, class _Elem, class _Tr>
4309void
4310wbuffer_convert<_Codecvt, _Elem, _Tr>::__write_mode()
4311{
4312 if (!(__cm_ & ios_base::out))
4313 {
4314 this->setg(0, 0, 0);
4315 if (__ebs_ > sizeof(__extbuf_min_))
4316 {
4317 if (__always_noconv_)
4318 this->setp((char_type*)__extbuf_,
4319 (char_type*)__extbuf_ + (__ebs_ - 1));
4320 else
4321 this->setp(__intbuf_, __intbuf_ + (__ibs_ - 1));
4322 }
4323 else
4324 this->setp(0, 0);
4325 __cm_ = ios_base::out;
4326 }
4327}
4328
4329template <class _Codecvt, class _Elem, class _Tr>
4330wbuffer_convert<_Codecvt, _Elem, _Tr>*
4331wbuffer_convert<_Codecvt, _Elem, _Tr>::__close()
4332{
4333 wbuffer_convert* __rt = 0;
4334 if (__cv_ != 0 && __bufptr_ != 0)
4335 {
4336 __rt = this;
4337 if ((__cm_ & ios_base::out) && sync())
4338 __rt = 0;
4339 }
4340 return __rt;
Howard Hinnantd23b4642010-05-31 20:58:54 +00004341}
4342
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004343_LIBCPP_END_NAMESPACE_STD
4344
4345#endif // _LIBCPP_LOCALE