blob: b88c6ac3e44da280b35418436a549047c17c1f67 [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:
39 locale() throw();
40 locale(const locale& other) throw();
41 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
48 ~locale() throw(); // not virtual
49
50 const locale& operator=(const locale& other) throw();
51
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&);
68template <class Facet> bool has_facet(const locale&) throw();
69
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{
525 if (__ct == __thousands_sep && __grouping.size() != 0)
526 {
527 if (__g_end-__g < __num_get_buf_sz)
528 {
529 *__g_end++ = __dc;
530 __dc = 0;
531 }
532 return 0;
533 }
534 ptrdiff_t __f = find(__atoms, __atoms + 26, __ct) - __atoms;
535 if (__f >= 26)
536 return -1;
537 if (__a_end-__a < __num_get_buf_sz - 1)
538 *__a_end++ = __src[__f];
539 switch (__base)
540 {
541 case 8:
542 case 10:
543 if (__f >= __base)
544 return 0;
545 break;
546 default:
547 if (__f >= 22)
548 return 0;
549 break;
550 }
551 ++__dc;
552 return 0;
553}
554
555template <class _CharT>
556int
557__num_get<_CharT>::__stage2_float_loop(_CharT __ct, bool& __in_units, char& __exp, char* __a, char*& __a_end,
558 _CharT __decimal_point, _CharT __thousands_sep, const string& __grouping,
559 unsigned* __g, unsigned*& __g_end, unsigned& __dc, _CharT* __atoms)
560{
561 if (__ct == __decimal_point)
562 {
563 if (!__in_units)
564 return -1;
565 __in_units = false;
566 *__a_end++ = '.';
567 if (__grouping.size() != 0 && __g_end-__g < __num_get_buf_sz)
568 *__g_end++ = __dc;
569 return 0;
570 }
571 if (__ct == __thousands_sep && __grouping.size() != 0)
572 {
573 if (!__in_units)
574 return -1;
575 if (__g_end-__g < __num_get_buf_sz)
576 {
577 *__g_end++ = __dc;
578 __dc = 0;
579 }
580 return 0;
581 }
582 ptrdiff_t __f = find(__atoms, __atoms + 32, __ct) - __atoms;
583 if (__f >= 32)
584 return -1;
585 char __x = __src[__f];
586 if (__a_end-__a < __num_get_buf_sz - 1)
587 *__a_end++ = __x;
588 if (__x == 'x' || __x == 'X')
589 __exp = 'P';
590 else if ((__x & 0xDF) == __exp)
591 {
592 __in_units = false;
593 if (__grouping.size() != 0 && __g_end-__g < __num_get_buf_sz)
594 *__g_end++ = __dc;
595 }
596 if (__f >= 22)
597 return 0;
598 ++__dc;
599 return 0;
600}
601
602extern template class __num_get<char>;
603extern template class __num_get<wchar_t>;
604
605template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +0000606class _LIBCPP_VISIBLE num_get
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000607 : public locale::facet,
608 private __num_get<_CharT>
609{
610public:
611 typedef _CharT char_type;
612 typedef _InputIterator iter_type;
613
614 _LIBCPP_ALWAYS_INLINE
615 explicit num_get(size_t __refs = 0)
616 : locale::facet(__refs) {}
617
618 _LIBCPP_ALWAYS_INLINE
619 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
620 ios_base::iostate& __err, bool& __v) const
621 {
622 return do_get(__b, __e, __iob, __err, __v);
623 }
624
625 _LIBCPP_ALWAYS_INLINE
626 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
627 ios_base::iostate& __err, long& __v) const
628 {
629 return do_get(__b, __e, __iob, __err, __v);
630 }
631
632 _LIBCPP_ALWAYS_INLINE
633 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
634 ios_base::iostate& __err, long long& __v) const
635 {
636 return do_get(__b, __e, __iob, __err, __v);
637 }
638
639 _LIBCPP_ALWAYS_INLINE
640 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
641 ios_base::iostate& __err, unsigned short& __v) const
642 {
643 return do_get(__b, __e, __iob, __err, __v);
644 }
645
646 _LIBCPP_ALWAYS_INLINE
647 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
648 ios_base::iostate& __err, unsigned int& __v) const
649 {
650 return do_get(__b, __e, __iob, __err, __v);
651 }
652
653 _LIBCPP_ALWAYS_INLINE
654 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
655 ios_base::iostate& __err, unsigned long& __v) const
656 {
657 return do_get(__b, __e, __iob, __err, __v);
658 }
659
660 _LIBCPP_ALWAYS_INLINE
661 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
662 ios_base::iostate& __err, unsigned long long& __v) const
663 {
664 return do_get(__b, __e, __iob, __err, __v);
665 }
666
667 _LIBCPP_ALWAYS_INLINE
668 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
669 ios_base::iostate& __err, float& __v) const
670 {
671 return do_get(__b, __e, __iob, __err, __v);
672 }
673
674 _LIBCPP_ALWAYS_INLINE
675 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
676 ios_base::iostate& __err, double& __v) const
677 {
678 return do_get(__b, __e, __iob, __err, __v);
679 }
680
681 _LIBCPP_ALWAYS_INLINE
682 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
683 ios_base::iostate& __err, long double& __v) const
684 {
685 return do_get(__b, __e, __iob, __err, __v);
686 }
687
688 _LIBCPP_ALWAYS_INLINE
689 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
690 ios_base::iostate& __err, void*& __v) const
691 {
692 return do_get(__b, __e, __iob, __err, __v);
693 }
694
695 static locale::id id;
696
697protected:
Howard Hinnant82894812010-09-22 16:48:34 +0000698 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000699 ~num_get() {}
700
701 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
702 ios_base::iostate& __err, bool& __v) const;
703 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
704 ios_base::iostate& __err, long& __v) const;
705 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
706 ios_base::iostate& __err, long long& __v) const;
707 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
708 ios_base::iostate& __err, unsigned short& __v) const;
709 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
710 ios_base::iostate& __err, unsigned int& __v) const;
711 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
712 ios_base::iostate& __err, unsigned long& __v) const;
713 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
714 ios_base::iostate& __err, unsigned long long& __v) const;
715 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
716 ios_base::iostate& __err, float& __v) const;
717 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
718 ios_base::iostate& __err, double& __v) const;
719 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
720 ios_base::iostate& __err, long double& __v) const;
721 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
722 ios_base::iostate& __err, void*& __v) const;
723};
724
725template <class _CharT, class _InputIterator>
726locale::id
727num_get<_CharT, _InputIterator>::id;
728
729template <class _Tp>
730_Tp
731__num_get_signed_integral(const char* __a, const char* __a_end,
732 ios_base::iostate& __err, int __base)
733{
734 if (__a != __a_end)
735 {
736 char *__p2;
737 long long __ll = strtoll_l(__a, &__p2, __base, 0);
738 if (__p2 != __a_end)
739 {
740 __err = ios_base::failbit;
741 return 0;
742 }
743 else if (__ll > numeric_limits<_Tp>::max())
744 {
745 __err = ios_base::failbit;
746 return numeric_limits<_Tp>::max();
747 }
748 else if (__ll < numeric_limits<_Tp>::min())
749 {
750 __err = ios_base::failbit;
751 return numeric_limits<_Tp>::min();
752 }
753 return static_cast<_Tp>(__ll);
754 }
755 __err = ios_base::failbit;
756 return 0;
757}
758
759template <class _Tp>
760_Tp
761__num_get_unsigned_integral(const char* __a, const char* __a_end,
762 ios_base::iostate& __err, int __base)
763{
764 if (__a != __a_end)
765 {
766 char *__p2;
767 unsigned long long __ll = strtoull_l(__a, &__p2, __base, 0);
768 if (__p2 != __a_end)
769 {
770 __err = ios_base::failbit;
771 return 0;
772 }
773 else if (__ll > numeric_limits<_Tp>::max())
774 {
775 __err = ios_base::failbit;
776 return numeric_limits<_Tp>::max();
777 }
778 return static_cast<_Tp>(__ll);
779 }
780 __err = ios_base::failbit;
781 return 0;
782}
783
784template <class _Tp>
785_Tp
786__num_get_float(const char* __a, const char* __a_end, ios_base::iostate& __err)
787{
788 if (__a != __a_end)
789 {
790 char *__p2;
791 long double __ld = strtold_l(__a, &__p2, 0);
792 if (__p2 != __a_end)
793 {
794 __err = ios_base::failbit;
795 return 0;
796 }
797 return static_cast<_Tp>(__ld);
798 }
799 __err = ios_base::failbit;
800 return 0;
801}
802
803template <class _CharT, class _InputIterator>
804_InputIterator
805num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
806 ios_base& __iob,
807 ios_base::iostate& __err,
808 bool& __v) const
809{
810 if ((__iob.flags() & ios_base::boolalpha) == 0)
811 {
812 long __lv = -1;
813 __b = do_get(__b, __e, __iob, __err, __lv);
814 switch (__lv)
815 {
816 case 0:
817 __v = false;
818 break;
819 case 1:
820 __v = true;
821 break;
822 default:
823 __v = true;
824 __err = ios_base::failbit;
825 break;
826 }
827 return __b;
828 }
829 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__iob.getloc());
830 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__iob.getloc());
831 typedef typename numpunct<_CharT>::string_type string_type;
832 const string_type __names[2] = {__np.truename(), __np.falsename()};
833 const string_type* __i = __scan_keyword(__b, __e, __names, __names+2,
834 __ct, __err);
835 __v = __i == __names;
836 return __b;
837}
838
839template <class _CharT, class _InputIterator>
840_InputIterator
841num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
842 ios_base& __iob,
843 ios_base::iostate& __err,
844 long& __v) const
845{
846 // Stage 1
847 int __base = this->__get_base(__iob);
848 // Stage 2
849 char_type __atoms[26];
850 char_type __thousands_sep;
851 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
852 char __a[__num_get_base::__num_get_buf_sz] = {0};
853 char* __a_end = __a;
854 unsigned __g[__num_get_base::__num_get_buf_sz];
855 unsigned* __g_end = __g;
856 unsigned __dc = 0;
857 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +0000858 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000859 __thousands_sep, __grouping, __g, __g_end,
860 __atoms))
861 break;
862 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
863 *__g_end++ = __dc;
864 // Stage 3
865 __v = __num_get_signed_integral<long>(__a, __a_end, __err, __base);
866 // Digit grouping checked
867 __check_grouping(__grouping, __g, __g_end, __err);
868 // EOF checked
869 if (__b == __e)
870 __err |= ios_base::eofbit;
871 return __b;
872}
873
874template <class _CharT, class _InputIterator>
875_InputIterator
876num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
877 ios_base& __iob,
878 ios_base::iostate& __err,
879 long long& __v) const
880{
881 // Stage 1
882 int __base = this->__get_base(__iob);
883 // Stage 2
884 char_type __atoms[26];
885 char_type __thousands_sep;
886 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
887 char __a[__num_get_base::__num_get_buf_sz] = {0};
888 char* __a_end = __a;
889 unsigned __g[__num_get_base::__num_get_buf_sz];
890 unsigned* __g_end = __g;
891 unsigned __dc = 0;
892 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +0000893 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
894 __thousands_sep, __grouping, __g, __g_end,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000895 __atoms))
896 break;
897 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
898 *__g_end++ = __dc;
899 // Stage 3
900 __v = __num_get_signed_integral<long long>(__a, __a_end, __err, __base);
901 // Digit grouping checked
902 __check_grouping(__grouping, __g, __g_end, __err);
903 // EOF checked
904 if (__b == __e)
905 __err |= ios_base::eofbit;
906 return __b;
907}
908
909template <class _CharT, class _InputIterator>
910_InputIterator
911num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
912 ios_base& __iob,
913 ios_base::iostate& __err,
914 unsigned short& __v) const
915{
916 // Stage 1
917 int __base = this->__get_base(__iob);
918 // Stage 2
919 char_type __atoms[26];
920 char_type __thousands_sep;
921 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
922 char __a[__num_get_base::__num_get_buf_sz] = {0};
923 char* __a_end = __a;
924 unsigned __g[__num_get_base::__num_get_buf_sz];
925 unsigned* __g_end = __g;
926 unsigned __dc = 0;
927 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +0000928 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000929 __thousands_sep, __grouping, __g, __g_end,
930 __atoms))
931 break;
932 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
933 *__g_end++ = __dc;
934 // Stage 3
935 __v = __num_get_unsigned_integral<unsigned short>(__a, __a_end, __err, __base);
936 // Digit grouping checked
937 __check_grouping(__grouping, __g, __g_end, __err);
938 // EOF checked
939 if (__b == __e)
940 __err |= ios_base::eofbit;
941 return __b;
942}
943
944template <class _CharT, class _InputIterator>
945_InputIterator
946num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
947 ios_base& __iob,
948 ios_base::iostate& __err,
949 unsigned int& __v) const
950{
951 // Stage 1
952 int __base = this->__get_base(__iob);
953 // Stage 2
954 char_type __atoms[26];
955 char_type __thousands_sep;
956 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
957 char __a[__num_get_base::__num_get_buf_sz] = {0};
958 char* __a_end = __a;
959 unsigned __g[__num_get_base::__num_get_buf_sz];
960 unsigned* __g_end = __g;
961 unsigned __dc = 0;
962 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +0000963 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000964 __thousands_sep, __grouping, __g, __g_end,
965 __atoms))
966 break;
967 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
968 *__g_end++ = __dc;
969 // Stage 3
970 __v = __num_get_unsigned_integral<unsigned int>(__a, __a_end, __err, __base);
971 // Digit grouping checked
972 __check_grouping(__grouping, __g, __g_end, __err);
973 // EOF checked
974 if (__b == __e)
975 __err |= ios_base::eofbit;
976 return __b;
977}
978
979template <class _CharT, class _InputIterator>
980_InputIterator
981num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
982 ios_base& __iob,
983 ios_base::iostate& __err,
984 unsigned long& __v) const
985{
986 // Stage 1
987 int __base = this->__get_base(__iob);
988 // Stage 2
989 char_type __atoms[26];
990 char_type __thousands_sep;
991 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
992 char __a[__num_get_base::__num_get_buf_sz] = {0};
993 char* __a_end = __a;
994 unsigned __g[__num_get_base::__num_get_buf_sz];
995 unsigned* __g_end = __g;
996 unsigned __dc = 0;
997 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +0000998 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000999 __thousands_sep, __grouping, __g, __g_end,
1000 __atoms))
1001 break;
1002 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
1003 *__g_end++ = __dc;
1004 // Stage 3
1005 __v = __num_get_unsigned_integral<unsigned long>(__a, __a_end, __err, __base);
1006 // Digit grouping checked
1007 __check_grouping(__grouping, __g, __g_end, __err);
1008 // EOF checked
1009 if (__b == __e)
1010 __err |= ios_base::eofbit;
1011 return __b;
1012}
1013
1014template <class _CharT, class _InputIterator>
1015_InputIterator
1016num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1017 ios_base& __iob,
1018 ios_base::iostate& __err,
1019 unsigned long long& __v) const
1020{
1021 // Stage 1
1022 int __base = this->__get_base(__iob);
1023 // Stage 2
1024 char_type __atoms[26];
1025 char_type __thousands_sep;
1026 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
1027 char __a[__num_get_base::__num_get_buf_sz] = {0};
1028 char* __a_end = __a;
1029 unsigned __g[__num_get_base::__num_get_buf_sz];
1030 unsigned* __g_end = __g;
1031 unsigned __dc = 0;
1032 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001033 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001034 __thousands_sep, __grouping, __g, __g_end,
1035 __atoms))
1036 break;
1037 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
1038 *__g_end++ = __dc;
1039 // Stage 3
1040 __v = __num_get_unsigned_integral<unsigned long long>(__a, __a_end, __err, __base);
1041 // Digit grouping checked
1042 __check_grouping(__grouping, __g, __g_end, __err);
1043 // EOF checked
1044 if (__b == __e)
1045 __err |= ios_base::eofbit;
1046 return __b;
1047}
1048
1049template <class _CharT, class _InputIterator>
1050_InputIterator
1051num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1052 ios_base& __iob,
1053 ios_base::iostate& __err,
1054 float& __v) const
1055{
1056 // Stage 1, nothing to do
1057 // Stage 2
1058 char_type __atoms[32];
1059 char_type __decimal_point;
1060 char_type __thousands_sep;
Howard Hinnant324bb032010-08-22 00:02:43 +00001061 string __grouping = this->__stage2_float_prep(__iob, __atoms,
1062 __decimal_point,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001063 __thousands_sep);
1064 char __a[__num_get_base::__num_get_buf_sz] = {0};
1065 char* __a_end = __a;
1066 unsigned __g[__num_get_base::__num_get_buf_sz];
1067 unsigned* __g_end = __g;
1068 unsigned __dc = 0;
1069 bool __in_units = true;
1070 char __exp = 'E';
1071 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001072 if (this->__stage2_float_loop(*__b, __in_units, __exp, __a, __a_end,
1073 __decimal_point, __thousands_sep,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001074 __grouping, __g, __g_end,
1075 __dc, __atoms))
1076 break;
1077 if (__grouping.size() != 0 && __in_units && __g_end-__g < __num_get_base::__num_get_buf_sz)
1078 *__g_end++ = __dc;
1079 // Stage 3
1080 __v = __num_get_float<float>(__a, __a_end, __err);
1081 // Digit grouping checked
1082 __check_grouping(__grouping, __g, __g_end, __err);
1083 // EOF checked
1084 if (__b == __e)
1085 __err |= ios_base::eofbit;
1086 return __b;
1087}
1088
1089template <class _CharT, class _InputIterator>
1090_InputIterator
1091num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1092 ios_base& __iob,
1093 ios_base::iostate& __err,
1094 double& __v) const
1095{
1096 // Stage 1, nothing to do
1097 // Stage 2
1098 char_type __atoms[32];
1099 char_type __decimal_point;
1100 char_type __thousands_sep;
Howard Hinnant324bb032010-08-22 00:02:43 +00001101 string __grouping = this->__stage2_float_prep(__iob, __atoms,
1102 __decimal_point,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001103 __thousands_sep);
1104 char __a[__num_get_base::__num_get_buf_sz] = {0};
1105 char* __a_end = __a;
1106 unsigned __g[__num_get_base::__num_get_buf_sz];
1107 unsigned* __g_end = __g;
1108 unsigned __dc = 0;
1109 bool __in_units = true;
1110 char __exp = 'E';
1111 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001112 if (this->__stage2_float_loop(*__b, __in_units, __exp, __a, __a_end,
1113 __decimal_point, __thousands_sep,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001114 __grouping, __g, __g_end,
1115 __dc, __atoms))
1116 break;
1117 if (__grouping.size() != 0 && __in_units && __g_end-__g < __num_get_base::__num_get_buf_sz)
1118 *__g_end++ = __dc;
1119 // Stage 3
1120 __v = __num_get_float<double>(__a, __a_end, __err);
1121 // Digit grouping checked
1122 __check_grouping(__grouping, __g, __g_end, __err);
1123 // EOF checked
1124 if (__b == __e)
1125 __err |= ios_base::eofbit;
1126 return __b;
1127}
1128
1129template <class _CharT, class _InputIterator>
1130_InputIterator
1131num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1132 ios_base& __iob,
1133 ios_base::iostate& __err,
1134 long double& __v) const
1135{
1136 // Stage 1, nothing to do
1137 // Stage 2
1138 char_type __atoms[32];
1139 char_type __decimal_point;
1140 char_type __thousands_sep;
Howard Hinnant324bb032010-08-22 00:02:43 +00001141 string __grouping = this->__stage2_float_prep(__iob, __atoms,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001142 __decimal_point,
1143 __thousands_sep);
1144 char __a[__num_get_base::__num_get_buf_sz] = {0};
1145 char* __a_end = __a;
1146 unsigned __g[__num_get_base::__num_get_buf_sz];
1147 unsigned* __g_end = __g;
1148 unsigned __dc = 0;
1149 bool __in_units = true;
1150 char __exp = 'E';
1151 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001152 if (this->__stage2_float_loop(*__b, __in_units, __exp, __a, __a_end,
1153 __decimal_point, __thousands_sep,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001154 __grouping, __g, __g_end,
1155 __dc, __atoms))
1156 break;
1157 if (__grouping.size() != 0 && __in_units && __g_end-__g < __num_get_base::__num_get_buf_sz)
1158 *__g_end++ = __dc;
1159 // Stage 3
1160 __v = __num_get_float<long double>(__a, __a_end, __err);
1161 // Digit grouping checked
1162 __check_grouping(__grouping, __g, __g_end, __err);
1163 // EOF checked
1164 if (__b == __e)
1165 __err |= ios_base::eofbit;
1166 return __b;
1167}
1168
1169template <class _CharT, class _InputIterator>
1170_InputIterator
1171num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1172 ios_base& __iob,
1173 ios_base::iostate& __err,
1174 void*& __v) const
1175{
1176 // Stage 1
1177 int __base = 16;
1178 // Stage 2
1179 char_type __atoms[26];
1180 char_type __thousands_sep;
1181 string __grouping;
1182 use_facet<ctype<_CharT> >(__iob.getloc()).widen(__num_get_base::__src,
1183 __num_get_base::__src + 26, __atoms);
1184 char __a[__num_get_base::__num_get_buf_sz] = {0};
1185 char* __a_end = __a;
1186 unsigned __g[__num_get_base::__num_get_buf_sz];
1187 unsigned* __g_end = __g;
1188 unsigned __dc = 0;
1189 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001190 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
1191 __thousands_sep, __grouping,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001192 __g, __g_end, __atoms))
1193 break;
1194 // Stage 3
1195 __a[sizeof(__a)-1] = 0;
Howard Hinnantadff4892010-05-24 17:49:41 +00001196 if (__nolocale_sscanf(__a, "%p", &__v) != 1)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001197 __err = ios_base::failbit;
1198 // EOF checked
1199 if (__b == __e)
1200 __err |= ios_base::eofbit;
1201 return __b;
1202}
1203
1204extern template class num_get<char>;
1205extern template class num_get<wchar_t>;
1206
1207struct __num_put_base
1208{
1209protected:
1210 static void __format_int(char* __fmt, const char* __len, bool __signd,
1211 ios_base::fmtflags __flags);
1212 static bool __format_float(char* __fmt, const char* __len,
1213 ios_base::fmtflags __flags);
1214 static char* __identify_padding(char* __nb, char* __ne,
1215 const ios_base& __iob);
1216};
1217
1218template <class _CharT>
1219struct __num_put
1220 : protected __num_put_base
1221{
1222 static void __widen_and_group_int(char* __nb, char* __np, char* __ne,
1223 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1224 const locale& __loc);
1225 static void __widen_and_group_float(char* __nb, char* __np, char* __ne,
1226 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1227 const locale& __loc);
1228};
1229
1230template <class _CharT>
1231void
1232__num_put<_CharT>::__widen_and_group_int(char* __nb, char* __np, char* __ne,
1233 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1234 const locale& __loc)
1235{
1236 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> > (__loc);
1237 const numpunct<_CharT>& __npt = use_facet<numpunct<_CharT> >(__loc);
1238 string __grouping = __npt.grouping();
1239 if (__grouping.empty())
1240 {
1241 __ct.widen(__nb, __ne, __ob);
1242 __oe = __ob + (__ne - __nb);
1243 }
1244 else
1245 {
1246 __oe = __ob;
1247 char* __nf = __nb;
1248 if (*__nf == '-' || *__nf == '+')
1249 *__oe++ = __ct.widen(*__nf++);
1250 if (__ne - __nf >= 2 && __nf[0] == '0' && (__nf[1] == 'x' ||
1251 __nf[1] == 'X'))
1252 {
1253 *__oe++ = __ct.widen(*__nf++);
1254 *__oe++ = __ct.widen(*__nf++);
1255 }
1256 reverse(__nf, __ne);
1257 _CharT __thousands_sep = __npt.thousands_sep();
1258 unsigned __dc = 0;
1259 unsigned __dg = 0;
1260 for (char* __p = __nf; __p < __ne; ++__p)
1261 {
1262 if (static_cast<unsigned>(__grouping[__dg]) > 0 &&
1263 __dc == static_cast<unsigned>(__grouping[__dg]))
1264 {
1265 *__oe++ = __thousands_sep;
1266 __dc = 0;
1267 if (__dg < __grouping.size()-1)
1268 ++__dg;
1269 }
1270 *__oe++ = __ct.widen(*__p);
1271 ++__dc;
1272 }
1273 reverse(__ob + (__nf - __nb), __oe);
1274 }
1275 if (__np == __ne)
1276 __op = __oe;
1277 else
1278 __op = __ob + (__np - __nb);
1279}
1280
1281template <class _CharT>
1282void
1283__num_put<_CharT>::__widen_and_group_float(char* __nb, char* __np, char* __ne,
1284 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1285 const locale& __loc)
1286{
1287 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> > (__loc);
1288 const numpunct<_CharT>& __npt = use_facet<numpunct<_CharT> >(__loc);
1289 string __grouping = __npt.grouping();
1290 __oe = __ob;
1291 char* __nf = __nb;
1292 if (*__nf == '-' || *__nf == '+')
1293 *__oe++ = __ct.widen(*__nf++);
1294 char* __ns;
1295 if (__ne - __nf >= 2 && __nf[0] == '0' && (__nf[1] == 'x' ||
1296 __nf[1] == 'X'))
1297 {
1298 *__oe++ = __ct.widen(*__nf++);
1299 *__oe++ = __ct.widen(*__nf++);
1300 for (__ns = __nf; __ns < __ne; ++__ns)
Howard Hinnantadff4892010-05-24 17:49:41 +00001301 if (!__nolocale_isxdigit(*__ns))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001302 break;
1303 }
1304 else
1305 {
1306 for (__ns = __nf; __ns < __ne; ++__ns)
Howard Hinnantadff4892010-05-24 17:49:41 +00001307 if (!__nolocale_isdigit(*__ns))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001308 break;
1309 }
1310 if (__grouping.empty())
1311 {
1312 __ct.widen(__nf, __ns, __oe);
1313 __oe += __ns - __nf;
1314 }
1315 else
1316 {
1317 reverse(__nf, __ns);
1318 _CharT __thousands_sep = __npt.thousands_sep();
1319 unsigned __dc = 0;
1320 unsigned __dg = 0;
1321 for (char* __p = __nf; __p < __ns; ++__p)
1322 {
1323 if (__grouping[__dg] > 0 && __dc == static_cast<unsigned>(__grouping[__dg]))
1324 {
1325 *__oe++ = __thousands_sep;
1326 __dc = 0;
1327 if (__dg < __grouping.size()-1)
1328 ++__dg;
1329 }
1330 *__oe++ = __ct.widen(*__p);
1331 ++__dc;
1332 }
1333 reverse(__ob + (__nf - __nb), __oe);
1334 }
1335 for (__nf = __ns; __nf < __ne; ++__nf)
1336 {
1337 if (*__nf == '.')
1338 {
1339 *__oe++ = __npt.decimal_point();
1340 ++__nf;
1341 break;
1342 }
1343 else
1344 *__oe++ = __ct.widen(*__nf);
1345 }
1346 __ct.widen(__nf, __ne, __oe);
1347 __oe += __ne - __nf;
1348 if (__np == __ne)
1349 __op = __oe;
1350 else
1351 __op = __ob + (__np - __nb);
1352}
1353
1354extern template class __num_put<char>;
1355extern template class __num_put<wchar_t>;
1356
1357template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00001358class _LIBCPP_VISIBLE num_put
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001359 : public locale::facet,
1360 private __num_put<_CharT>
1361{
1362public:
1363 typedef _CharT char_type;
1364 typedef _OutputIterator iter_type;
1365
1366 _LIBCPP_ALWAYS_INLINE
1367 explicit num_put(size_t __refs = 0)
1368 : locale::facet(__refs) {}
1369
1370 _LIBCPP_ALWAYS_INLINE
1371 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1372 bool __v) const
1373 {
1374 return do_put(__s, __iob, __fl, __v);
1375 }
1376
1377 _LIBCPP_ALWAYS_INLINE
1378 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1379 long __v) const
1380 {
1381 return do_put(__s, __iob, __fl, __v);
1382 }
1383
1384 _LIBCPP_ALWAYS_INLINE
1385 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1386 long long __v) const
1387 {
1388 return do_put(__s, __iob, __fl, __v);
1389 }
1390
1391 _LIBCPP_ALWAYS_INLINE
1392 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1393 unsigned long __v) const
1394 {
1395 return do_put(__s, __iob, __fl, __v);
1396 }
1397
1398 _LIBCPP_ALWAYS_INLINE
1399 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1400 unsigned long long __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 double __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 double __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 const void* __v) const
1422 {
1423 return do_put(__s, __iob, __fl, __v);
1424 }
1425
1426 static locale::id id;
1427
1428protected:
Howard Hinnant82894812010-09-22 16:48:34 +00001429 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001430 ~num_put() {}
1431
1432 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1433 bool __v) const;
1434 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1435 long __v) const;
1436 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1437 long long __v) const;
1438 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1439 unsigned long) const;
1440 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1441 unsigned long long) const;
1442 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1443 double __v) const;
1444 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1445 long double __v) const;
1446 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1447 const void* __v) const;
1448};
1449
1450template <class _CharT, class _OutputIterator>
1451locale::id
1452num_put<_CharT, _OutputIterator>::id;
1453
1454template <class _CharT, class _OutputIterator>
1455_LIBCPP_HIDDEN
1456_OutputIterator
1457__pad_and_output(_OutputIterator __s,
1458 const _CharT* __ob, const _CharT* __op, const _CharT* __oe,
1459 ios_base& __iob, _CharT __fl)
1460{
1461 streamsize __sz = __oe - __ob;
1462 streamsize __ns = __iob.width();
1463 if (__ns > __sz)
1464 __ns -= __sz;
1465 else
1466 __ns = 0;
1467 for (;__ob < __op; ++__ob, ++__s)
1468 *__s = *__ob;
1469 for (; __ns; --__ns, ++__s)
1470 *__s = __fl;
1471 for (; __ob < __oe; ++__ob, ++__s)
1472 *__s = *__ob;
1473 __iob.width(0);
1474 return __s;
1475}
1476
1477template <class _CharT, class _OutputIterator>
1478_OutputIterator
1479num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1480 char_type __fl, bool __v) const
1481{
1482 if ((__iob.flags() & ios_base::boolalpha) == 0)
1483 return do_put(__s, __iob, __fl, (unsigned long)__v);
1484 const numpunct<char_type>& __np = use_facet<numpunct<char_type> >(__iob.getloc());
1485 typedef typename numpunct<char_type>::string_type string_type;
1486 string_type __nm = __v ? __np.truename() : __np.falsename();
1487 for (typename string_type::iterator __i = __nm.begin(); __i != __nm.end(); ++__i, ++__s)
1488 *__s = *__i;
1489 return __s;
1490}
1491
1492template <class _CharT, class _OutputIterator>
1493_OutputIterator
1494num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1495 char_type __fl, long __v) const
1496{
1497 // Stage 1 - Get number in narrow char
1498 char __fmt[6] = {'%', 0};
1499 const char* __len = "l";
1500 this->__format_int(__fmt+1, __len, true, __iob.flags());
1501 const unsigned __nbuf = (numeric_limits<long>::digits / 3)
1502 + ((numeric_limits<long>::digits % 3) != 0)
1503 + 1;
1504 char __nar[__nbuf];
Howard Hinnantadff4892010-05-24 17:49:41 +00001505 int __nc = __nolocale_sprintf(__nar, __fmt, __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001506 char* __ne = __nar + __nc;
1507 char* __np = this->__identify_padding(__nar, __ne, __iob);
1508 // Stage 2 - Widen __nar while adding thousands separators
1509 char_type __o[2*(__nbuf-1) - 1];
1510 char_type* __op; // pad here
1511 char_type* __oe; // end of output
1512 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1513 // [__o, __oe) contains thousands_sep'd wide number
1514 // Stage 3 & 4
1515 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1516}
1517
1518template <class _CharT, class _OutputIterator>
1519_OutputIterator
1520num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1521 char_type __fl, long long __v) const
1522{
1523 // Stage 1 - Get number in narrow char
1524 char __fmt[8] = {'%', 0};
1525 const char* __len = "ll";
1526 this->__format_int(__fmt+1, __len, true, __iob.flags());
1527 const unsigned __nbuf = (numeric_limits<long long>::digits / 3)
1528 + ((numeric_limits<long long>::digits % 3) != 0)
1529 + 1;
1530 char __nar[__nbuf];
Howard Hinnantadff4892010-05-24 17:49:41 +00001531 int __nc = __nolocale_sprintf(__nar, __fmt, __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001532 char* __ne = __nar + __nc;
1533 char* __np = this->__identify_padding(__nar, __ne, __iob);
1534 // Stage 2 - Widen __nar while adding thousands separators
1535 char_type __o[2*(__nbuf-1) - 1];
1536 char_type* __op; // pad here
1537 char_type* __oe; // end of output
1538 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1539 // [__o, __oe) contains thousands_sep'd wide number
1540 // Stage 3 & 4
1541 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1542}
1543
1544template <class _CharT, class _OutputIterator>
1545_OutputIterator
1546num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1547 char_type __fl, unsigned long __v) const
1548{
1549 // Stage 1 - Get number in narrow char
1550 char __fmt[6] = {'%', 0};
1551 const char* __len = "l";
1552 this->__format_int(__fmt+1, __len, false, __iob.flags());
1553 const unsigned __nbuf = (numeric_limits<unsigned long>::digits / 3)
1554 + ((numeric_limits<unsigned long>::digits % 3) != 0)
1555 + 1;
1556 char __nar[__nbuf];
Howard Hinnantadff4892010-05-24 17:49:41 +00001557 int __nc = __nolocale_sprintf(__nar, __fmt, __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001558 char* __ne = __nar + __nc;
1559 char* __np = this->__identify_padding(__nar, __ne, __iob);
1560 // Stage 2 - Widen __nar while adding thousands separators
1561 char_type __o[2*(__nbuf-1) - 1];
1562 char_type* __op; // pad here
1563 char_type* __oe; // end of output
1564 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1565 // [__o, __oe) contains thousands_sep'd wide number
1566 // Stage 3 & 4
1567 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1568}
1569
1570template <class _CharT, class _OutputIterator>
1571_OutputIterator
1572num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1573 char_type __fl, unsigned long long __v) const
1574{
1575 // Stage 1 - Get number in narrow char
1576 char __fmt[8] = {'%', 0};
1577 const char* __len = "ll";
1578 this->__format_int(__fmt+1, __len, false, __iob.flags());
1579 const unsigned __nbuf = (numeric_limits<unsigned long long>::digits / 3)
1580 + ((numeric_limits<unsigned long long>::digits % 3) != 0)
1581 + 1;
1582 char __nar[__nbuf];
Howard Hinnantadff4892010-05-24 17:49:41 +00001583 int __nc = __nolocale_sprintf(__nar, __fmt, __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001584 char* __ne = __nar + __nc;
1585 char* __np = this->__identify_padding(__nar, __ne, __iob);
1586 // Stage 2 - Widen __nar while adding thousands separators
1587 char_type __o[2*(__nbuf-1) - 1];
1588 char_type* __op; // pad here
1589 char_type* __oe; // end of output
1590 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1591 // [__o, __oe) contains thousands_sep'd wide number
1592 // Stage 3 & 4
1593 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1594}
1595
1596template <class _CharT, class _OutputIterator>
1597_OutputIterator
1598num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1599 char_type __fl, double __v) const
1600{
1601 // Stage 1 - Get number in narrow char
1602 char __fmt[8] = {'%', 0};
1603 const char* __len = "";
1604 bool __specify_precision = this->__format_float(__fmt+1, __len, __iob.flags());
1605 const unsigned __nbuf = 30;
1606 char __nar[__nbuf];
1607 char* __nb = __nar;
1608 int __nc;
1609 if (__specify_precision)
Howard Hinnantadff4892010-05-24 17:49:41 +00001610 __nc = __nolocale_snprintf(__nb, __nbuf, __fmt,
1611 (int)__iob.precision(), __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001612 else
Howard Hinnantadff4892010-05-24 17:49:41 +00001613 __nc = __nolocale_snprintf(__nb, __nbuf, __fmt, __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001614 unique_ptr<char, void(*)(void*)> __nbh(0, free);
1615 if (__nc > static_cast<int>(__nbuf-1))
1616 {
1617 if (__specify_precision)
Howard Hinnantadff4892010-05-24 17:49:41 +00001618 __nc = __nolocale_asprintf(&__nb, __fmt, (int)__iob.precision(),
1619 __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001620 else
Howard Hinnantadff4892010-05-24 17:49:41 +00001621 __nc = __nolocale_asprintf(&__nb, __fmt, __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001622 if (__nb == 0)
1623 __throw_bad_alloc();
1624 __nbh.reset(__nb);
1625 }
1626 char* __ne = __nb + __nc;
1627 char* __np = this->__identify_padding(__nb, __ne, __iob);
1628 // Stage 2 - Widen __nar while adding thousands separators
1629 char_type __o[2*(__nbuf-1) - 1];
1630 char_type* __ob = __o;
1631 unique_ptr<char_type, void(*)(void*)> __obh(0, free);
1632 if (__nb != __nar)
1633 {
1634 __ob = (char_type*)malloc((2*__nc)*sizeof(char_type));
1635 if (__ob == 0)
1636 __throw_bad_alloc();
1637 __obh.reset(__ob);
1638 }
1639 char_type* __op; // pad here
1640 char_type* __oe; // end of output
1641 this->__widen_and_group_float(__nb, __np, __ne, __ob, __op, __oe, __iob.getloc());
1642 // [__o, __oe) contains thousands_sep'd wide number
1643 // Stage 3 & 4
1644 __s = __pad_and_output(__s, __ob, __op, __oe, __iob, __fl);
1645 return __s;
1646}
1647
1648template <class _CharT, class _OutputIterator>
1649_OutputIterator
1650num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1651 char_type __fl, long double __v) const
1652{
1653 // Stage 1 - Get number in narrow char
1654 char __fmt[8] = {'%', 0};
1655 const char* __len = "L";
1656 bool __specify_precision = this->__format_float(__fmt+1, __len, __iob.flags());
1657 const unsigned __nbuf = 30;
1658 char __nar[__nbuf];
1659 char* __nb = __nar;
1660 int __nc;
1661 if (__specify_precision)
Howard Hinnantadff4892010-05-24 17:49:41 +00001662 __nc = __nolocale_snprintf(__nb, __nbuf, __fmt,
1663 (int)__iob.precision(), __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001664 else
Howard Hinnantadff4892010-05-24 17:49:41 +00001665 __nc = __nolocale_snprintf(__nb, __nbuf, __fmt, __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001666 unique_ptr<char, void(*)(void*)> __nbh(0, free);
1667 if (__nc > static_cast<int>(__nbuf-1))
1668 {
1669 if (__specify_precision)
Howard Hinnantadff4892010-05-24 17:49:41 +00001670 __nc = __nolocale_asprintf(&__nb, __fmt, (int)__iob.precision(),
1671 __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001672 else
Howard Hinnantadff4892010-05-24 17:49:41 +00001673 __nc = __nolocale_asprintf(&__nb, __fmt, __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001674 if (__nb == 0)
1675 __throw_bad_alloc();
1676 __nbh.reset(__nb);
1677 }
1678 char* __ne = __nb + __nc;
1679 char* __np = this->__identify_padding(__nb, __ne, __iob);
1680 // Stage 2 - Widen __nar while adding thousands separators
1681 char_type __o[2*(__nbuf-1) - 1];
1682 char_type* __ob = __o;
1683 unique_ptr<char_type, void(*)(void*)> __obh(0, free);
1684 if (__nb != __nar)
1685 {
1686 __ob = (char_type*)malloc((2*__nc)*sizeof(char_type));
1687 if (__ob == 0)
1688 __throw_bad_alloc();
1689 __obh.reset(__ob);
1690 }
1691 char_type* __op; // pad here
1692 char_type* __oe; // end of output
1693 this->__widen_and_group_float(__nb, __np, __ne, __ob, __op, __oe, __iob.getloc());
1694 // [__o, __oe) contains thousands_sep'd wide number
1695 // Stage 3 & 4
1696 __s = __pad_and_output(__s, __ob, __op, __oe, __iob, __fl);
1697 return __s;
1698}
1699
1700template <class _CharT, class _OutputIterator>
1701_OutputIterator
1702num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1703 char_type __fl, const void* __v) const
1704{
1705 // Stage 1 - Get pointer in narrow char
1706 char __fmt[6] = "%p";
1707 const unsigned __nbuf = 20;
1708 char __nar[__nbuf];
Howard Hinnantadff4892010-05-24 17:49:41 +00001709 int __nc = __nolocale_sprintf(__nar, __fmt, __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001710 char* __ne = __nar + __nc;
1711 char* __np = this->__identify_padding(__nar, __ne, __iob);
1712 // Stage 2 - Widen __nar
1713 char_type __o[2*(__nbuf-1) - 1];
1714 char_type* __op; // pad here
1715 char_type* __oe; // end of output
1716 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
1717 __ct.widen(__nar, __ne, __o);
1718 __oe = __o + (__ne - __nar);
1719 if (__np == __ne)
1720 __op = __oe;
1721 else
1722 __op = __o + (__np - __nar);
1723 // [__o, __oe) contains wide number
1724 // Stage 3 & 4
1725 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1726}
1727
1728extern template class num_put<char>;
1729extern template class num_put<wchar_t>;
1730
1731template <class _CharT, class _InputIterator>
1732_LIBCPP_HIDDEN
1733int
1734__get_up_to_n_digits(_InputIterator& __b, _InputIterator __e,
1735 ios_base::iostate& __err, const ctype<_CharT>& __ct, int __n)
1736{
1737 // Precondition: __n >= 1
1738 if (__b == __e)
1739 {
1740 __err |= ios_base::eofbit | ios_base::failbit;
1741 return 0;
1742 }
1743 // get first digit
1744 _CharT __c = *__b;
1745 if (!__ct.is(ctype_base::digit, __c))
1746 {
1747 __err |= ios_base::failbit;
1748 return 0;
1749 }
1750 int __r = __ct.narrow(__c, 0) - '0';
1751 for (++__b, --__n; __b != __e && __n > 0; ++__b, --__n)
1752 {
1753 // get next digit
1754 __c = *__b;
1755 if (!__ct.is(ctype_base::digit, __c))
1756 return __r;
1757 __r = __r * 10 + __ct.narrow(__c, 0) - '0';
1758 }
1759 if (__b == __e)
1760 __err |= ios_base::eofbit;
1761 return __r;
1762}
1763
Howard Hinnant82894812010-09-22 16:48:34 +00001764class _LIBCPP_VISIBLE time_base
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001765{
1766public:
1767 enum dateorder {no_order, dmy, mdy, ymd, ydm};
1768};
1769
1770template <class _CharT>
Howard Hinnant2d72b1e2010-12-17 14:46:43 +00001771class __time_get_c_storage // purposefully not decorated
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001772{
1773protected:
1774 typedef basic_string<_CharT> string_type;
1775
1776 virtual const string_type* __weeks() const;
1777 virtual const string_type* __months() const;
1778 virtual const string_type* __am_pm() const;
1779 virtual const string_type& __c() const;
1780 virtual const string_type& __r() const;
1781 virtual const string_type& __x() const;
1782 virtual const string_type& __X() const;
1783};
1784
1785template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00001786class _LIBCPP_VISIBLE time_get
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001787 : public locale::facet,
1788 public time_base,
1789 private __time_get_c_storage<_CharT>
1790{
1791public:
1792 typedef _CharT char_type;
1793 typedef _InputIterator iter_type;
1794 typedef time_base::dateorder dateorder;
1795 typedef basic_string<char_type> string_type;
1796
1797 _LIBCPP_ALWAYS_INLINE
1798 explicit time_get(size_t __refs = 0)
1799 : locale::facet(__refs) {}
1800
1801 _LIBCPP_ALWAYS_INLINE
1802 dateorder date_order() const
1803 {
1804 return this->do_date_order();
1805 }
1806
1807 _LIBCPP_ALWAYS_INLINE
1808 iter_type get_time(iter_type __b, iter_type __e, ios_base& __iob,
1809 ios_base::iostate& __err, tm* __tm) const
1810 {
1811 return do_get_time(__b, __e, __iob, __err, __tm);
1812 }
1813
1814 _LIBCPP_ALWAYS_INLINE
1815 iter_type get_date(iter_type __b, iter_type __e, ios_base& __iob,
1816 ios_base::iostate& __err, tm* __tm) const
1817 {
1818 return do_get_date(__b, __e, __iob, __err, __tm);
1819 }
1820
1821 _LIBCPP_ALWAYS_INLINE
1822 iter_type get_weekday(iter_type __b, iter_type __e, ios_base& __iob,
1823 ios_base::iostate& __err, tm* __tm) const
1824 {
1825 return do_get_weekday(__b, __e, __iob, __err, __tm);
1826 }
1827
1828 _LIBCPP_ALWAYS_INLINE
1829 iter_type get_monthname(iter_type __b, iter_type __e, ios_base& __iob,
1830 ios_base::iostate& __err, tm* __tm) const
1831 {
1832 return do_get_monthname(__b, __e, __iob, __err, __tm);
1833 }
1834
1835 _LIBCPP_ALWAYS_INLINE
1836 iter_type get_year(iter_type __b, iter_type __e, ios_base& __iob,
1837 ios_base::iostate& __err, tm* __tm) const
1838 {
1839 return do_get_year(__b, __e, __iob, __err, __tm);
1840 }
1841
1842 _LIBCPP_ALWAYS_INLINE
1843 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
1844 ios_base::iostate& __err, tm *__tm,
1845 char __fmt, char __mod = 0) const
1846 {
1847 return do_get(__b, __e, __iob, __err, __tm, __fmt, __mod);
1848 }
1849
1850 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
1851 ios_base::iostate& __err, tm* __tm,
1852 const char_type* __fmtb, const char_type* __fmte) const;
1853
1854 static locale::id id;
1855
1856protected:
Howard Hinnant82894812010-09-22 16:48:34 +00001857 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001858 ~time_get() {}
1859
1860 virtual dateorder do_date_order() const;
1861 virtual iter_type do_get_time(iter_type __b, iter_type __e, ios_base& __iob,
1862 ios_base::iostate& __err, tm* __tm) const;
1863 virtual iter_type do_get_date(iter_type __b, iter_type __e, ios_base& __iob,
1864 ios_base::iostate& __err, tm* __tm) const;
1865 virtual iter_type do_get_weekday(iter_type __b, iter_type __e, ios_base& __iob,
1866 ios_base::iostate& __err, tm* __tm) const;
1867 virtual iter_type do_get_monthname(iter_type __b, iter_type __e, ios_base& __iob,
1868 ios_base::iostate& __err, tm* __tm) const;
1869 virtual iter_type do_get_year(iter_type __b, iter_type __e, ios_base& __iob,
1870 ios_base::iostate& __err, tm* __tm) const;
1871 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
1872 ios_base::iostate& __err, tm* __tm,
1873 char __fmt, char __mod) const;
1874private:
1875 void __get_white_space(iter_type& __b, iter_type __e,
1876 ios_base::iostate& __err, const ctype<char_type>& __ct) const;
1877 void __get_percent(iter_type& __b, iter_type __e, ios_base::iostate& __err,
1878 const ctype<char_type>& __ct) const;
1879
1880 void __get_weekdayname(int& __m,
1881 iter_type& __b, iter_type __e,
1882 ios_base::iostate& __err,
1883 const ctype<char_type>& __ct) const;
1884 void __get_monthname(int& __m,
1885 iter_type& __b, iter_type __e,
1886 ios_base::iostate& __err,
1887 const ctype<char_type>& __ct) const;
1888 void __get_day(int& __d,
1889 iter_type& __b, iter_type __e,
1890 ios_base::iostate& __err,
1891 const ctype<char_type>& __ct) const;
1892 void __get_month(int& __m,
1893 iter_type& __b, iter_type __e,
1894 ios_base::iostate& __err,
1895 const ctype<char_type>& __ct) const;
1896 void __get_year(int& __y,
1897 iter_type& __b, iter_type __e,
1898 ios_base::iostate& __err,
1899 const ctype<char_type>& __ct) const;
1900 void __get_year4(int& __y,
1901 iter_type& __b, iter_type __e,
1902 ios_base::iostate& __err,
1903 const ctype<char_type>& __ct) const;
1904 void __get_hour(int& __d,
1905 iter_type& __b, iter_type __e,
1906 ios_base::iostate& __err,
1907 const ctype<char_type>& __ct) const;
1908 void __get_12_hour(int& __h,
1909 iter_type& __b, iter_type __e,
1910 ios_base::iostate& __err,
1911 const ctype<char_type>& __ct) const;
1912 void __get_am_pm(int& __h,
1913 iter_type& __b, iter_type __e,
1914 ios_base::iostate& __err,
1915 const ctype<char_type>& __ct) const;
1916 void __get_minute(int& __m,
1917 iter_type& __b, iter_type __e,
1918 ios_base::iostate& __err,
1919 const ctype<char_type>& __ct) const;
1920 void __get_second(int& __s,
1921 iter_type& __b, iter_type __e,
1922 ios_base::iostate& __err,
1923 const ctype<char_type>& __ct) const;
1924 void __get_weekday(int& __w,
1925 iter_type& __b, iter_type __e,
1926 ios_base::iostate& __err,
1927 const ctype<char_type>& __ct) const;
1928 void __get_day_year_num(int& __w,
1929 iter_type& __b, iter_type __e,
1930 ios_base::iostate& __err,
1931 const ctype<char_type>& __ct) const;
1932};
1933
1934template <class _CharT, class _InputIterator>
1935locale::id
1936time_get<_CharT, _InputIterator>::id;
1937
1938// time_get primatives
1939
1940template <class _CharT, class _InputIterator>
1941void
1942time_get<_CharT, _InputIterator>::__get_weekdayname(int& __w,
1943 iter_type& __b, iter_type __e,
1944 ios_base::iostate& __err,
1945 const ctype<char_type>& __ct) const
1946{
1947 // Note: ignoring case comes from the POSIX strptime spec
1948 const string_type* __wk = this->__weeks();
1949 int __i = __scan_keyword(__b, __e, __wk, __wk+14, __ct, __err, false) - __wk;
1950 if (__i < 14)
1951 __w = __i % 7;
1952}
1953
1954template <class _CharT, class _InputIterator>
1955void
1956time_get<_CharT, _InputIterator>::__get_monthname(int& __m,
1957 iter_type& __b, iter_type __e,
1958 ios_base::iostate& __err,
1959 const ctype<char_type>& __ct) const
1960{
1961 // Note: ignoring case comes from the POSIX strptime spec
1962 const string_type* __month = this->__months();
1963 int __i = __scan_keyword(__b, __e, __month, __month+24, __ct, __err, false) - __month;
1964 if (__i < 24)
1965 __m = __i % 12;
1966}
1967
1968template <class _CharT, class _InputIterator>
1969void
1970time_get<_CharT, _InputIterator>::__get_day(int& __d,
1971 iter_type& __b, iter_type __e,
1972 ios_base::iostate& __err,
1973 const ctype<char_type>& __ct) const
1974{
1975 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
1976 if (!(__err & ios_base::failbit) && 1 <= __t && __t <= 31)
1977 __d = __t;
1978 else
1979 __err |= ios_base::failbit;
1980}
1981
1982template <class _CharT, class _InputIterator>
1983void
1984time_get<_CharT, _InputIterator>::__get_month(int& __m,
1985 iter_type& __b, iter_type __e,
1986 ios_base::iostate& __err,
1987 const ctype<char_type>& __ct) const
1988{
1989 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2) - 1;
1990 if (!(__err & ios_base::failbit) && __t <= 11)
1991 __m = __t;
1992 else
1993 __err |= ios_base::failbit;
1994}
1995
1996template <class _CharT, class _InputIterator>
1997void
1998time_get<_CharT, _InputIterator>::__get_year(int& __y,
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, 4);
2004 if (!(__err & ios_base::failbit))
2005 {
2006 if (__t < 69)
2007 __t += 2000;
2008 else if (69 <= __t && __t <= 99)
2009 __t += 1900;
2010 __y = __t - 1900;
2011 }
2012}
2013
2014template <class _CharT, class _InputIterator>
2015void
2016time_get<_CharT, _InputIterator>::__get_year4(int& __y,
2017 iter_type& __b, iter_type __e,
2018 ios_base::iostate& __err,
2019 const ctype<char_type>& __ct) const
2020{
2021 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 4);
2022 if (!(__err & ios_base::failbit))
2023 __y = __t - 1900;
2024}
2025
2026template <class _CharT, class _InputIterator>
2027void
2028time_get<_CharT, _InputIterator>::__get_hour(int& __h,
2029 iter_type& __b, iter_type __e,
2030 ios_base::iostate& __err,
2031 const ctype<char_type>& __ct) const
2032{
2033 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2034 if (!(__err & ios_base::failbit) && __t <= 23)
2035 __h = __t;
2036 else
2037 __err |= ios_base::failbit;
2038}
2039
2040template <class _CharT, class _InputIterator>
2041void
2042time_get<_CharT, _InputIterator>::__get_12_hour(int& __h,
2043 iter_type& __b, iter_type __e,
2044 ios_base::iostate& __err,
2045 const ctype<char_type>& __ct) const
2046{
2047 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2048 if (!(__err & ios_base::failbit) && 1 <= __t && __t <= 12)
2049 __h = __t;
2050 else
2051 __err |= ios_base::failbit;
2052}
2053
2054template <class _CharT, class _InputIterator>
2055void
2056time_get<_CharT, _InputIterator>::__get_minute(int& __m,
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 <= 59)
2063 __m = __t;
2064 else
2065 __err |= ios_base::failbit;
2066}
2067
2068template <class _CharT, class _InputIterator>
2069void
2070time_get<_CharT, _InputIterator>::__get_second(int& __s,
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) && __t <= 60)
2077 __s = __t;
2078 else
2079 __err |= ios_base::failbit;
2080}
2081
2082template <class _CharT, class _InputIterator>
2083void
2084time_get<_CharT, _InputIterator>::__get_weekday(int& __w,
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, 1);
2090 if (!(__err & ios_base::failbit) && __t <= 6)
2091 __w = __t;
2092 else
2093 __err |= ios_base::failbit;
2094}
2095
2096template <class _CharT, class _InputIterator>
2097void
2098time_get<_CharT, _InputIterator>::__get_day_year_num(int& __d,
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, 3);
2104 if (!(__err & ios_base::failbit) && __t <= 365)
2105 __d = __t;
2106 else
2107 __err |= ios_base::failbit;
2108}
2109
2110template <class _CharT, class _InputIterator>
2111void
2112time_get<_CharT, _InputIterator>::__get_white_space(iter_type& __b, iter_type __e,
2113 ios_base::iostate& __err,
2114 const ctype<char_type>& __ct) const
2115{
2116 for (; __b != __e && __ct.is(ctype_base::space, *__b); ++__b)
2117 ;
2118 if (__b == __e)
2119 __err |= ios_base::eofbit;
2120}
2121
2122template <class _CharT, class _InputIterator>
2123void
2124time_get<_CharT, _InputIterator>::__get_am_pm(int& __h,
2125 iter_type& __b, iter_type __e,
2126 ios_base::iostate& __err,
2127 const ctype<char_type>& __ct) const
2128{
2129 const string_type* __ap = this->__am_pm();
2130 if (__ap[0].size() + __ap[1].size() == 0)
2131 {
2132 __err |= ios_base::failbit;
2133 return;
2134 }
2135 int __i = __scan_keyword(__b, __e, __ap, __ap+2, __ct, __err, false) - __ap;
2136 if (__i == 0 && __h == 12)
2137 __h = 0;
2138 else if (__i == 1 && __h < 12)
2139 __h += 12;
2140}
2141
2142template <class _CharT, class _InputIterator>
2143void
2144time_get<_CharT, _InputIterator>::__get_percent(iter_type& __b, iter_type __e,
2145 ios_base::iostate& __err,
2146 const ctype<char_type>& __ct) const
2147{
2148 if (__b == __e)
2149 {
2150 __err |= ios_base::eofbit | ios_base::failbit;
2151 return;
2152 }
2153 if (__ct.narrow(*__b, 0) != '%')
2154 __err |= ios_base::failbit;
2155 else if(++__b == __e)
2156 __err |= ios_base::eofbit;
2157}
2158
2159// time_get end primatives
2160
2161template <class _CharT, class _InputIterator>
2162_InputIterator
2163time_get<_CharT, _InputIterator>::get(iter_type __b, iter_type __e,
2164 ios_base& __iob,
2165 ios_base::iostate& __err, tm* __tm,
2166 const char_type* __fmtb, const char_type* __fmte) const
2167{
2168 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2169 __err = ios_base::goodbit;
2170 while (__fmtb != __fmte && __err == ios_base::goodbit)
2171 {
2172 if (__b == __e)
2173 {
2174 __err = ios_base::failbit;
2175 break;
2176 }
2177 if (__ct.narrow(*__fmtb, 0) == '%')
2178 {
2179 if (++__fmtb == __fmte)
2180 {
2181 __err = ios_base::failbit;
2182 break;
2183 }
2184 char __cmd = __ct.narrow(*__fmtb, 0);
2185 char __opt = '\0';
2186 if (__cmd == 'E' || __cmd == '0')
2187 {
2188 if (++__fmtb == __fmte)
2189 {
2190 __err = ios_base::failbit;
2191 break;
2192 }
2193 __opt = __cmd;
2194 __cmd = __ct.narrow(*__fmtb, 0);
2195 }
2196 __b = do_get(__b, __e, __iob, __err, __tm, __cmd, __opt);
2197 ++__fmtb;
2198 }
2199 else if (__ct.is(ctype_base::space, *__fmtb))
2200 {
2201 for (++__fmtb; __fmtb != __fmte && __ct.is(ctype_base::space, *__fmtb); ++__fmtb)
2202 ;
2203 for ( ; __b != __e && __ct.is(ctype_base::space, *__b); ++__b)
2204 ;
2205 }
2206 else if (__ct.toupper(*__b) == __ct.toupper(*__fmtb))
2207 {
2208 ++__b;
2209 ++__fmtb;
2210 }
2211 else
2212 __err = ios_base::failbit;
2213 }
2214 if (__b == __e)
2215 __err |= ios_base::eofbit;
2216 return __b;
2217}
2218
2219template <class _CharT, class _InputIterator>
2220typename time_get<_CharT, _InputIterator>::dateorder
2221time_get<_CharT, _InputIterator>::do_date_order() const
2222{
2223 return mdy;
2224}
2225
2226template <class _CharT, class _InputIterator>
2227_InputIterator
2228time_get<_CharT, _InputIterator>::do_get_time(iter_type __b, iter_type __e,
2229 ios_base& __iob,
2230 ios_base::iostate& __err,
2231 tm* __tm) const
2232{
2233 const char_type __fmt[] = {'%', 'H', ':', '%', 'M', ':', '%', 'S'};
2234 return get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2235}
2236
2237template <class _CharT, class _InputIterator>
2238_InputIterator
2239time_get<_CharT, _InputIterator>::do_get_date(iter_type __b, iter_type __e,
2240 ios_base& __iob,
2241 ios_base::iostate& __err,
2242 tm* __tm) const
2243{
2244 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2245 const string_type& __fmt = this->__x();
2246 return get(__b, __e, __iob, __err, __tm, __fmt.data(), __fmt.data() + __fmt.size());
2247}
2248
2249template <class _CharT, class _InputIterator>
2250_InputIterator
2251time_get<_CharT, _InputIterator>::do_get_weekday(iter_type __b, iter_type __e,
2252 ios_base& __iob,
2253 ios_base::iostate& __err,
2254 tm* __tm) const
2255{
2256 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2257 __get_weekdayname(__tm->tm_wday, __b, __e, __err, __ct);
2258 return __b;
2259}
2260
2261template <class _CharT, class _InputIterator>
2262_InputIterator
2263time_get<_CharT, _InputIterator>::do_get_monthname(iter_type __b, iter_type __e,
2264 ios_base& __iob,
2265 ios_base::iostate& __err,
2266 tm* __tm) const
2267{
2268 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2269 __get_monthname(__tm->tm_mon, __b, __e, __err, __ct);
2270 return __b;
2271}
2272
2273template <class _CharT, class _InputIterator>
2274_InputIterator
2275time_get<_CharT, _InputIterator>::do_get_year(iter_type __b, iter_type __e,
2276 ios_base& __iob,
2277 ios_base::iostate& __err,
2278 tm* __tm) const
2279{
2280 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2281 __get_year(__tm->tm_year, __b, __e, __err, __ct);
2282 return __b;
2283}
2284
2285template <class _CharT, class _InputIterator>
2286_InputIterator
2287time_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
2288 ios_base& __iob,
2289 ios_base::iostate& __err, tm* __tm,
2290 char __fmt, char) const
2291{
2292 __err = ios_base::goodbit;
2293 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2294 switch (__fmt)
2295 {
2296 case 'a':
2297 case 'A':
2298 __get_weekdayname(__tm->tm_wday, __b, __e, __err, __ct);
2299 break;
2300 case 'b':
2301 case 'B':
2302 case 'h':
2303 __get_monthname(__tm->tm_mon, __b, __e, __err, __ct);
2304 break;
2305 case 'c':
2306 {
2307 const string_type& __fmt = this->__c();
2308 __b = get(__b, __e, __iob, __err, __tm, __fmt.data(), __fmt.data() + __fmt.size());
2309 }
2310 break;
2311 case 'd':
2312 case 'e':
2313 __get_day(__tm->tm_mday, __b, __e, __err, __ct);
2314 break;
2315 case 'D':
2316 {
2317 const char_type __fmt[] = {'%', 'm', '/', '%', 'd', '/', '%', 'y'};
2318 __b = get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2319 }
2320 break;
2321 case 'H':
2322 __get_hour(__tm->tm_hour, __b, __e, __err, __ct);
2323 break;
2324 case 'I':
2325 __get_12_hour(__tm->tm_hour, __b, __e, __err, __ct);
2326 break;
2327 case 'j':
2328 __get_day_year_num(__tm->tm_yday, __b, __e, __err, __ct);
2329 break;
2330 case 'm':
2331 __get_month(__tm->tm_mon, __b, __e, __err, __ct);
2332 break;
2333 case 'M':
2334 __get_minute(__tm->tm_min, __b, __e, __err, __ct);
2335 break;
2336 case 'n':
2337 case 't':
2338 __get_white_space(__b, __e, __err, __ct);
2339 break;
2340 case 'p':
2341 __get_am_pm(__tm->tm_hour, __b, __e, __err, __ct);
2342 break;
2343 case 'r':
2344 {
2345 const char_type __fmt[] = {'%', 'I', ':', '%', 'M', ':', '%', 'S', ' ', '%', 'p'};
2346 __b = get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2347 }
2348 break;
2349 case 'R':
2350 {
2351 const char_type __fmt[] = {'%', 'H', ':', '%', 'M'};
2352 __b = get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2353 }
2354 break;
2355 case 'S':
2356 __get_second(__tm->tm_sec, __b, __e, __err, __ct);
2357 break;
2358 case 'T':
2359 {
2360 const char_type __fmt[] = {'%', 'H', ':', '%', 'M', ':', '%', 'S'};
2361 __b = get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2362 }
2363 break;
2364 case 'w':
2365 __get_weekday(__tm->tm_wday, __b, __e, __err, __ct);
2366 break;
2367 case 'x':
2368 return do_get_date(__b, __e, __iob, __err, __tm);
2369 case 'X':
2370 {
2371 const string_type& __fmt = this->__X();
2372 __b = get(__b, __e, __iob, __err, __tm, __fmt.data(), __fmt.data() + __fmt.size());
2373 }
2374 break;
2375 case 'y':
2376 __get_year(__tm->tm_year, __b, __e, __err, __ct);
2377 break;
2378 case 'Y':
2379 __get_year4(__tm->tm_year, __b, __e, __err, __ct);
2380 break;
2381 case '%':
2382 __get_percent(__b, __e, __err, __ct);
2383 break;
2384 default:
2385 __err |= ios_base::failbit;
2386 }
2387 return __b;
2388}
2389
2390extern template class time_get<char>;
2391extern template class time_get<wchar_t>;
2392
2393class __time_get
2394{
2395protected:
2396 locale_t __loc_;
2397
2398 __time_get(const char* __nm);
2399 __time_get(const string& __nm);
2400 ~__time_get();
2401};
2402
2403template <class _CharT>
2404class __time_get_storage
2405 : public __time_get
2406{
2407protected:
2408 typedef basic_string<_CharT> string_type;
2409
2410 string_type __weeks_[14];
2411 string_type __months_[24];
2412 string_type __am_pm_[2];
2413 string_type __c_;
2414 string_type __r_;
2415 string_type __x_;
2416 string_type __X_;
2417
2418 explicit __time_get_storage(const char* __nm);
2419 explicit __time_get_storage(const string& __nm);
2420
2421 _LIBCPP_ALWAYS_INLINE ~__time_get_storage() {}
2422
2423 time_base::dateorder __do_date_order() const;
2424
2425private:
2426 void init(const ctype<_CharT>&);
2427 string_type __analyze(char __fmt, const ctype<_CharT>&);
2428};
2429
2430template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00002431class _LIBCPP_VISIBLE time_get_byname
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002432 : public time_get<_CharT, _InputIterator>,
2433 private __time_get_storage<_CharT>
2434{
2435public:
2436 typedef time_base::dateorder dateorder;
2437 typedef _InputIterator iter_type;
2438 typedef _CharT char_type;
2439 typedef basic_string<char_type> string_type;
2440
Howard Hinnant82894812010-09-22 16:48:34 +00002441 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002442 explicit time_get_byname(const char* __nm, size_t __refs = 0)
2443 : time_get<_CharT, _InputIterator>(__refs),
2444 __time_get_storage<_CharT>(__nm) {}
Howard Hinnant82894812010-09-22 16:48:34 +00002445 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002446 explicit time_get_byname(const string& __nm, size_t __refs = 0)
2447 : time_get<_CharT, _InputIterator>(__refs),
2448 __time_get_storage<_CharT>(__nm) {}
2449
2450protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002451 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002452 ~time_get_byname() {}
2453
Howard Hinnant82894812010-09-22 16:48:34 +00002454 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002455 virtual dateorder do_date_order() const {return this->__do_date_order();}
2456private:
Howard Hinnant82894812010-09-22 16:48:34 +00002457 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002458 virtual const string_type* __weeks() const {return this->__weeks_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002459 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002460 virtual const string_type* __months() const {return this->__months_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002461 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002462 virtual const string_type* __am_pm() const {return this->__am_pm_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002463 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002464 virtual const string_type& __c() const {return this->__c_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002465 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002466 virtual const string_type& __r() const {return this->__r_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002467 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002468 virtual const string_type& __x() const {return this->__x_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002469 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002470 virtual const string_type& __X() const {return this->__X_;}
2471};
2472
2473extern template class time_get_byname<char>;
2474extern template class time_get_byname<wchar_t>;
2475
2476class __time_put
2477{
2478 locale_t __loc_;
2479protected:
2480 _LIBCPP_ALWAYS_INLINE __time_put() : __loc_(0) {}
2481 __time_put(const char* __nm);
2482 __time_put(const string& __nm);
2483 ~__time_put();
2484 void __do_put(char* __nb, char*& __ne, const tm* __tm,
2485 char __fmt, char __mod) const;
2486 void __do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
2487 char __fmt, char __mod) const;
2488};
2489
2490template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00002491class _LIBCPP_VISIBLE time_put
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002492 : public locale::facet,
2493 private __time_put
2494{
2495public:
2496 typedef _CharT char_type;
2497 typedef _OutputIterator iter_type;
2498
2499 _LIBCPP_ALWAYS_INLINE
2500 explicit time_put(size_t __refs = 0)
2501 : locale::facet(__refs) {}
2502
2503 iter_type put(iter_type __s, ios_base& __iob, char_type __fl, const tm* __tm,
2504 const char_type* __pb, const char_type* __pe) const;
2505
2506 _LIBCPP_ALWAYS_INLINE
2507 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
2508 const tm* __tm, char __fmt, char __mod = 0) const
2509 {
2510 return do_put(__s, __iob, __fl, __tm, __fmt, __mod);
2511 }
2512
2513 static locale::id id;
2514
2515protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002516 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002517 ~time_put() {}
2518 virtual iter_type do_put(iter_type __s, ios_base&, char_type, const tm* __tm,
2519 char __fmt, char __mod) const;
2520
Howard Hinnant82894812010-09-22 16:48:34 +00002521 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002522 explicit time_put(const char* __nm, size_t __refs)
2523 : locale::facet(__refs),
2524 __time_put(__nm) {}
Howard Hinnant82894812010-09-22 16:48:34 +00002525 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002526 explicit time_put(const string& __nm, size_t __refs)
2527 : locale::facet(__refs),
2528 __time_put(__nm) {}
2529};
2530
2531template <class _CharT, class _OutputIterator>
2532locale::id
2533time_put<_CharT, _OutputIterator>::id;
2534
2535template <class _CharT, class _OutputIterator>
2536_OutputIterator
2537time_put<_CharT, _OutputIterator>::put(iter_type __s, ios_base& __iob,
2538 char_type __fl, const tm* __tm,
2539 const char_type* __pb,
2540 const char_type* __pe) const
2541{
2542 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2543 for (; __pb != __pe; ++__pb)
2544 {
2545 if (__ct.narrow(*__pb, 0) == '%')
2546 {
2547 if (++__pb == __pe)
2548 {
2549 *__s++ = __pb[-1];
2550 break;
2551 }
2552 char __mod = 0;
2553 char __fmt = __ct.narrow(*__pb, 0);
2554 if (__fmt == 'E' || __fmt == 'O')
2555 {
2556 if (++__pb == __pe)
2557 {
2558 *__s++ = __pb[-2];
2559 *__s++ = __pb[-1];
2560 break;
2561 }
2562 __mod = __fmt;
2563 __fmt = __ct.narrow(*__pb, 0);
2564 }
2565 __s = do_put(__s, __iob, __fl, __tm, __fmt, __mod);
2566 }
2567 else
2568 *__s++ = *__pb;
2569 }
2570 return __s;
2571}
2572
2573template <class _CharT, class _OutputIterator>
2574_OutputIterator
2575time_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
2576 char_type, const tm* __tm,
2577 char __fmt, char __mod) const
2578{
2579 char_type __nar[100];
2580 char_type* __nb = __nar;
2581 char_type* __ne = __nb + 100;
2582 __do_put(__nb, __ne, __tm, __fmt, __mod);
2583 return copy(__nb, __ne, __s);
2584}
2585
2586extern template class time_put<char>;
2587extern template class time_put<wchar_t>;
2588
2589template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00002590class _LIBCPP_VISIBLE time_put_byname
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002591 : public time_put<_CharT, _OutputIterator>
2592{
2593public:
2594 _LIBCPP_ALWAYS_INLINE
2595 explicit time_put_byname(const char* __nm, size_t __refs = 0)
2596 : time_put<_CharT, _OutputIterator>(__nm, __refs) {}
2597
2598 _LIBCPP_ALWAYS_INLINE
2599 explicit time_put_byname(const string& __nm, size_t __refs = 0)
2600 : time_put<_CharT, _OutputIterator>(__nm, __refs) {}
2601
2602protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002603 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002604 ~time_put_byname() {}
2605};
2606
2607extern template class time_put_byname<char>;
2608extern template class time_put_byname<wchar_t>;
2609
2610// money_base
2611
Howard Hinnant82894812010-09-22 16:48:34 +00002612class _LIBCPP_VISIBLE money_base
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002613{
2614public:
2615 enum part {none, space, symbol, sign, value};
2616 struct pattern {char field[4];};
2617
2618 _LIBCPP_ALWAYS_INLINE money_base() {}
2619};
2620
2621// moneypunct
2622
2623template <class _CharT, bool _International = false>
Howard Hinnant82894812010-09-22 16:48:34 +00002624class _LIBCPP_VISIBLE moneypunct
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002625 : public locale::facet,
2626 public money_base
2627{
2628public:
2629 typedef _CharT char_type;
2630 typedef basic_string<char_type> string_type;
2631
Howard Hinnant82894812010-09-22 16:48:34 +00002632 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002633 explicit moneypunct(size_t __refs = 0)
2634 : locale::facet(__refs) {}
2635
2636 _LIBCPP_ALWAYS_INLINE char_type decimal_point() const {return do_decimal_point();}
2637 _LIBCPP_ALWAYS_INLINE char_type thousands_sep() const {return do_thousands_sep();}
2638 _LIBCPP_ALWAYS_INLINE string grouping() const {return do_grouping();}
2639 _LIBCPP_ALWAYS_INLINE string_type curr_symbol() const {return do_curr_symbol();}
2640 _LIBCPP_ALWAYS_INLINE string_type positive_sign() const {return do_positive_sign();}
2641 _LIBCPP_ALWAYS_INLINE string_type negative_sign() const {return do_negative_sign();}
2642 _LIBCPP_ALWAYS_INLINE int frac_digits() const {return do_frac_digits();}
2643 _LIBCPP_ALWAYS_INLINE pattern pos_format() const {return do_pos_format();}
2644 _LIBCPP_ALWAYS_INLINE pattern neg_format() const {return do_neg_format();}
2645
2646 static locale::id id;
2647 static const bool intl = _International;
2648
2649protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002650 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002651 ~moneypunct() {}
2652
2653 virtual char_type do_decimal_point() const {return numeric_limits<char_type>::max();}
2654 virtual char_type do_thousands_sep() const {return numeric_limits<char_type>::max();}
2655 virtual string do_grouping() const {return string();}
2656 virtual string_type do_curr_symbol() const {return string_type();}
2657 virtual string_type do_positive_sign() const {return string_type();}
2658 virtual string_type do_negative_sign() const {return string_type(1, '-');}
2659 virtual int do_frac_digits() const {return 0;}
2660 virtual pattern do_pos_format() const
2661 {pattern __p = {symbol, sign, none, value}; return __p;}
2662 virtual pattern do_neg_format() const
2663 {pattern __p = {symbol, sign, none, value}; return __p;}
2664};
2665
2666template <class _CharT, bool _International>
2667locale::id
2668moneypunct<_CharT, _International>::id;
2669
2670extern template class moneypunct<char, false>;
2671extern template class moneypunct<char, true>;
2672extern template class moneypunct<wchar_t, false>;
2673extern template class moneypunct<wchar_t, true>;
2674
2675// moneypunct_byname
2676
2677template <class _CharT, bool _International = false>
Howard Hinnant82894812010-09-22 16:48:34 +00002678class _LIBCPP_VISIBLE moneypunct_byname
2679 : public moneypunct<_CharT, _International>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002680{
2681public:
2682 typedef money_base::pattern pattern;
2683 typedef _CharT char_type;
2684 typedef basic_string<char_type> string_type;
2685
2686 _LIBCPP_ALWAYS_INLINE
2687 explicit moneypunct_byname(const char* __nm, size_t __refs = 0)
2688 : moneypunct<_CharT, _International>(__refs) {init(__nm);}
2689
2690 _LIBCPP_ALWAYS_INLINE
2691 explicit moneypunct_byname(const string& __nm, size_t __refs = 0)
2692 : moneypunct<_CharT, _International>(__refs) {init(__nm.c_str());}
2693
2694protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002695 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002696 ~moneypunct_byname() {}
2697
2698 virtual char_type do_decimal_point() const {return __decimal_point_;}
2699 virtual char_type do_thousands_sep() const {return __thousands_sep_;}
2700 virtual string do_grouping() const {return __grouping_;}
2701 virtual string_type do_curr_symbol() const {return __curr_symbol_;}
2702 virtual string_type do_positive_sign() const {return __positive_sign_;}
2703 virtual string_type do_negative_sign() const {return __negative_sign_;}
2704 virtual int do_frac_digits() const {return __frac_digits_;}
2705 virtual pattern do_pos_format() const {return __pos_format_;}
2706 virtual pattern do_neg_format() const {return __neg_format_;}
2707
2708private:
2709 char_type __decimal_point_;
2710 char_type __thousands_sep_;
2711 string __grouping_;
2712 string_type __curr_symbol_;
2713 string_type __positive_sign_;
2714 string_type __negative_sign_;
2715 int __frac_digits_;
2716 pattern __pos_format_;
2717 pattern __neg_format_;
2718
2719 void init(const char*);
2720};
2721
2722template<> void moneypunct_byname<char, false>::init(const char*);
2723template<> void moneypunct_byname<char, true>::init(const char*);
2724template<> void moneypunct_byname<wchar_t, false>::init(const char*);
2725template<> void moneypunct_byname<wchar_t, true>::init(const char*);
2726
2727extern template class moneypunct_byname<char, false>;
2728extern template class moneypunct_byname<char, true>;
2729extern template class moneypunct_byname<wchar_t, false>;
2730extern template class moneypunct_byname<wchar_t, true>;
2731
2732// money_get
2733
2734template <class _CharT>
2735class __money_get
2736{
2737protected:
2738 typedef _CharT char_type;
2739 typedef basic_string<char_type> string_type;
2740
2741 _LIBCPP_ALWAYS_INLINE __money_get() {}
2742
2743 static void __gather_info(bool __intl, const locale& __loc,
2744 money_base::pattern& __pat, char_type& __dp,
2745 char_type& __ts, string& __grp,
2746 string_type& __sym, string_type& __psn,
2747 string_type& __nsn, int& __fd);
2748};
2749
2750template <class _CharT>
2751void
2752__money_get<_CharT>::__gather_info(bool __intl, const locale& __loc,
2753 money_base::pattern& __pat, char_type& __dp,
2754 char_type& __ts, string& __grp,
2755 string_type& __sym, string_type& __psn,
2756 string_type& __nsn, int& __fd)
2757{
2758 if (__intl)
2759 {
2760 const moneypunct<char_type, true>& __mp =
2761 use_facet<moneypunct<char_type, true> >(__loc);
2762 __pat = __mp.neg_format();
2763 __nsn = __mp.negative_sign();
2764 __psn = __mp.positive_sign();
2765 __dp = __mp.decimal_point();
2766 __ts = __mp.thousands_sep();
2767 __grp = __mp.grouping();
2768 __sym = __mp.curr_symbol();
2769 __fd = __mp.frac_digits();
2770 }
2771 else
2772 {
2773 const moneypunct<char_type, false>& __mp =
2774 use_facet<moneypunct<char_type, false> >(__loc);
2775 __pat = __mp.neg_format();
2776 __nsn = __mp.negative_sign();
2777 __psn = __mp.positive_sign();
2778 __dp = __mp.decimal_point();
2779 __ts = __mp.thousands_sep();
2780 __grp = __mp.grouping();
2781 __sym = __mp.curr_symbol();
2782 __fd = __mp.frac_digits();
2783 }
2784}
2785
2786extern template class __money_get<char>;
2787extern template class __money_get<wchar_t>;
2788
2789template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00002790class _LIBCPP_VISIBLE money_get
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002791 : public locale::facet,
2792 private __money_get<_CharT>
2793{
2794public:
2795 typedef _CharT char_type;
2796 typedef _InputIterator iter_type;
2797 typedef basic_string<char_type> string_type;
2798
2799 _LIBCPP_ALWAYS_INLINE
2800 explicit money_get(size_t __refs = 0)
2801 : locale::facet(__refs) {}
2802
2803 _LIBCPP_ALWAYS_INLINE
2804 iter_type get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob,
2805 ios_base::iostate& __err, long double& __v) const
2806 {
2807 return do_get(__b, __e, __intl, __iob, __err, __v);
2808 }
2809
2810 _LIBCPP_ALWAYS_INLINE
2811 iter_type get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob,
2812 ios_base::iostate& __err, string_type& __v) const
2813 {
2814 return do_get(__b, __e, __intl, __iob, __err, __v);
2815 }
2816
2817 static locale::id id;
2818
2819protected:
2820
Howard Hinnant82894812010-09-22 16:48:34 +00002821 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002822 ~money_get() {}
Howard Hinnant324bb032010-08-22 00:02:43 +00002823
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002824 virtual iter_type do_get(iter_type __b, iter_type __e, bool __intl,
2825 ios_base& __iob, ios_base::iostate& __err,
2826 long double& __v) const;
2827 virtual iter_type do_get(iter_type __b, iter_type __e, bool __intl,
2828 ios_base& __iob, ios_base::iostate& __err,
2829 string_type& __v) const;
2830
2831private:
2832 static bool __do_get(iter_type& __b, iter_type __e,
2833 bool __intl, const locale& __loc,
2834 ios_base::fmtflags __flags, ios_base::iostate& __err,
2835 bool& __neg, const ctype<char_type>& __ct,
2836 unique_ptr<char_type, void(*)(void*)>& __wb,
2837 char_type*& __wn, char_type* __we);
2838};
2839
2840template <class _CharT, class _InputIterator>
2841locale::id
2842money_get<_CharT, _InputIterator>::id;
2843
2844void __do_nothing(void*);
2845
2846template <class _Tp>
2847_LIBCPP_HIDDEN
2848void
2849__double_or_nothing(unique_ptr<_Tp, void(*)(void*)>& __b, _Tp*& __n, _Tp*& __e)
2850{
2851 bool __owns = __b.get_deleter() != __do_nothing;
2852 size_t __cur_cap = (__e-__b.get()) * sizeof(_Tp);
2853 size_t __new_cap = __cur_cap < numeric_limits<size_t>::max() / 2 ?
2854 2 * __cur_cap : numeric_limits<size_t>::max();
2855 size_t __n_off = __n - __b.get();
2856 _Tp* __t = (_Tp*)realloc(__owns ? __b.get() : 0, __new_cap);
2857 if (__t == 0)
2858 __throw_bad_alloc();
2859 if (__owns)
2860 __b.release();
2861 __b = unique_ptr<_Tp, void(*)(void*)>(__t, free);
2862 __new_cap /= sizeof(_Tp);
2863 __n = __b.get() + __n_off;
2864 __e = __b.get() + __new_cap;
2865}
2866
2867// true == success
2868template <class _CharT, class _InputIterator>
2869bool
2870money_get<_CharT, _InputIterator>::__do_get(iter_type& __b, iter_type __e,
2871 bool __intl, const locale& __loc,
2872 ios_base::fmtflags __flags,
2873 ios_base::iostate& __err,
2874 bool& __neg,
2875 const ctype<char_type>& __ct,
2876 unique_ptr<char_type, void(*)(void*)>& __wb,
2877 char_type*& __wn, char_type* __we)
2878{
2879 const unsigned __bz = 100;
2880 unsigned __gbuf[__bz];
2881 unique_ptr<unsigned, void(*)(void*)> __gb(__gbuf, __do_nothing);
2882 unsigned* __gn = __gb.get();
2883 unsigned* __ge = __gn + __bz;
2884 money_base::pattern __pat;
2885 char_type __dp;
2886 char_type __ts;
2887 string __grp;
2888 string_type __sym;
2889 string_type __psn;
2890 string_type __nsn;
2891 int __fd;
2892 __money_get<_CharT>::__gather_info(__intl, __loc, __pat, __dp, __ts, __grp,
2893 __sym, __psn, __nsn, __fd);
2894 const string_type* __trailing_sign = 0;
2895 __wn = __wb.get();
2896 for (unsigned __p = 0; __p < 4 && __b != __e; ++__p)
2897 {
2898 switch (__pat.field[__p])
2899 {
2900 case money_base::space:
2901 if (__p != 3)
2902 {
2903 if (__ct.is(ctype_base::space, *__b))
2904 ++__b;
2905 else
2906 {
2907 __err |= ios_base::failbit;
2908 return false;
2909 }
2910 }
Howard Hinnant324bb032010-08-22 00:02:43 +00002911 // drop through
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002912 case money_base::none:
2913 if (__p != 3)
2914 {
2915 while (__b != __e && __ct.is(ctype_base::space, *__b))
2916 ++__b;
2917 }
2918 break;
2919 case money_base::sign:
2920 if (__psn.size() + __nsn.size() > 0)
2921 {
2922 if (__psn.size() == 0 || __nsn.size() == 0)
2923 { // sign is optional
2924 if (__psn.size() > 0)
2925 { // __nsn.size() == 0
2926 if (*__b == __psn[0])
2927 {
2928 ++__b;
2929 if (__psn.size() > 1)
2930 __trailing_sign = &__psn;
2931 }
2932 else
2933 __neg = true;
2934 }
2935 else if (*__b == __nsn[0]) // __nsn.size() > 0 && __psn.size() == 0
2936 {
2937 ++__b;
2938 __neg = true;
2939 if (__nsn.size() > 1)
2940 __trailing_sign = &__nsn;
2941 }
2942 }
2943 else // sign is required
2944 {
2945 if (*__b == __psn[0])
2946 {
2947 ++__b;
2948 if (__psn.size() > 1)
2949 __trailing_sign = &__psn;
2950 }
2951 else if (*__b == __nsn[0])
2952 {
2953 ++__b;
2954 __neg = true;
2955 if (__nsn.size() > 1)
2956 __trailing_sign = &__nsn;
2957 }
2958 else
2959 {
2960 __err |= ios_base::failbit;
2961 return false;
2962 }
2963 }
2964 }
2965 break;
2966 case money_base::symbol:
2967 {
2968 bool __more_needed = __trailing_sign ||
2969 (__p < 2) ||
2970 (__p == 2 && __pat.field[3] != static_cast<char>(money_base::none));
2971 bool __sb = __flags & ios_base::showbase;
2972 if (__sb || __more_needed)
2973 {
2974 ios_base::iostate __et = ios_base::goodbit;
2975 string_type* __k = __scan_keyword(__b, __e, &__sym, &__sym+1,
2976 __ct, __et);
2977 if (__sb && __k != &__sym)
2978 {
2979 __err |= ios_base::failbit;
2980 return false;
2981 }
2982 }
2983 }
2984 break;
2985 case money_base::value:
2986 {
2987 unsigned __ng = 0;
2988 for (; __b != __e; ++__b)
2989 {
2990 char_type __c = *__b;
2991 if (__ct.is(ctype_base::digit, __c))
2992 {
2993 if (__wn == __we)
2994 __double_or_nothing(__wb, __wn, __we);
2995 *__wn++ = __c;
2996 ++__ng;
2997 }
2998 else if (__grp.size() > 0 && __ng > 0 && __c == __ts)
2999 {
3000 if (__gn == __ge)
3001 __double_or_nothing(__gb, __gn, __ge);
3002 *__gn++ = __ng;
3003 __ng = 0;
3004 }
3005 else
3006 break;
3007 }
3008 if (__gb.get() != __gn && __ng > 0)
3009 {
3010 if (__gn == __ge)
3011 __double_or_nothing(__gb, __gn, __ge);
3012 *__gn++ = __ng;
3013 }
3014 if (__fd > 0)
3015 {
3016 if (__b == __e || *__b != __dp)
3017 {
3018 __err |= ios_base::failbit;
3019 return false;
3020 }
3021 for (++__b; __fd > 0; --__fd, ++__b)
3022 {
3023 if (__b == __e || !__ct.is(ctype_base::digit, *__b))
3024 {
3025 __err |= ios_base::failbit;
3026 return false;
3027 }
3028 if (__wn == __we)
3029 __double_or_nothing(__wb, __wn, __we);
3030 *__wn++ = *__b;
3031 }
3032 }
3033 if (__wn == __wb.get())
3034 {
3035 __err |= ios_base::failbit;
3036 return false;
3037 }
3038 }
3039 break;
3040 }
3041 }
3042 if (__trailing_sign)
3043 {
3044 for (unsigned __i = 1; __i < __trailing_sign->size(); ++__i, ++__b)
3045 {
3046 if (__b == __e || *__b != (*__trailing_sign)[__i])
3047 {
3048 __err |= ios_base::failbit;
3049 return false;
3050 }
3051 }
3052 }
3053 if (__gb.get() != __gn)
3054 {
3055 ios_base::iostate __et = ios_base::goodbit;
3056 __check_grouping(__grp, __gb.get(), __gn, __et);
3057 if (__et)
3058 {
3059 __err |= ios_base::failbit;
3060 return false;
3061 }
3062 }
3063 return true;
3064}
3065
3066template <class _CharT, class _InputIterator>
3067_InputIterator
3068money_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
3069 bool __intl, ios_base& __iob,
3070 ios_base::iostate& __err,
3071 long double& __v) const
3072{
3073 const unsigned __bz = 100;
3074 char_type __wbuf[__bz];
3075 unique_ptr<char_type, void(*)(void*)> __wb(__wbuf, __do_nothing);
3076 char_type* __wn;
3077 char_type* __we = __wbuf + __bz;
3078 locale __loc = __iob.getloc();
3079 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3080 bool __neg = false;
3081 if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct,
3082 __wb, __wn, __we))
3083 {
3084 const char __src[] = "0123456789";
3085 char_type __atoms[sizeof(__src)-1];
3086 __ct.widen(__src, __src + (sizeof(__src)-1), __atoms);
3087 char __nbuf[__bz];
3088 char* __nc = __nbuf;
3089 unique_ptr<char, void(*)(void*)> __h(0, free);
3090 if (__wn - __wb.get() > __bz-2)
3091 {
3092 __h.reset((char*)malloc(__wn - __wb.get() + 2));
3093 if (__h.get() == 0)
3094 __throw_bad_alloc();
3095 __nc = __h.get();
3096 }
3097 if (__neg)
3098 *__nc++ = '-';
3099 for (const char_type* __w = __wb.get(); __w < __wn; ++__w, ++__nc)
3100 *__nc = __src[find(__atoms, __atoms+sizeof(__atoms), *__w) - __atoms];
3101 *__nc = char();
3102 if (sscanf(__nbuf, "%Lf", &__v) != 1)
3103 __throw_runtime_error("money_get error");
3104 }
3105 if (__b == __e)
3106 __err |= ios_base::eofbit;
3107 return __b;
3108}
3109
3110template <class _CharT, class _InputIterator>
3111_InputIterator
3112money_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
3113 bool __intl, ios_base& __iob,
3114 ios_base::iostate& __err,
3115 string_type& __v) const
3116{
3117 const unsigned __bz = 100;
3118 char_type __wbuf[__bz];
3119 unique_ptr<char_type, void(*)(void*)> __wb(__wbuf, __do_nothing);
3120 char_type* __wn;
3121 char_type* __we = __wbuf + __bz;
3122 locale __loc = __iob.getloc();
3123 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3124 bool __neg = false;
3125 if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct,
3126 __wb, __wn, __we))
3127 {
3128 __v.clear();
3129 if (__neg)
3130 __v.push_back(__ct.widen('-'));
3131 char_type __z = __ct.widen('0');
3132 char_type* __w;
3133 for (__w = __wb.get(); __w < __wn-1; ++__w)
3134 if (*__w != __z)
3135 break;
3136 __v.append(__w, __wn);
3137 }
3138 if (__b == __e)
3139 __err |= ios_base::eofbit;
3140 return __b;
3141}
3142
3143extern template class money_get<char>;
3144extern template class money_get<wchar_t>;
3145
3146// money_put
3147
3148template <class _CharT>
3149class __money_put
3150{
3151protected:
3152 typedef _CharT char_type;
3153 typedef basic_string<char_type> string_type;
3154
3155 _LIBCPP_ALWAYS_INLINE __money_put() {}
3156
3157 static void __gather_info(bool __intl, bool __neg, const locale& __loc,
3158 money_base::pattern& __pat, char_type& __dp,
3159 char_type& __ts, string& __grp,
3160 string_type& __sym, string_type& __sn,
3161 int& __fd);
3162 static void __format(char_type* __mb, char_type*& __mi, char_type*& __me,
3163 ios_base::fmtflags __flags,
3164 const char_type* __db, const char_type* __de,
3165 const ctype<char_type>& __ct, bool __neg,
3166 const money_base::pattern& __pat, char_type __dp,
3167 char_type __ts, const string& __grp,
3168 const string_type& __sym, const string_type& __sn,
3169 int __fd);
3170};
3171
3172template <class _CharT>
3173void
3174__money_put<_CharT>::__gather_info(bool __intl, bool __neg, const locale& __loc,
3175 money_base::pattern& __pat, char_type& __dp,
3176 char_type& __ts, string& __grp,
3177 string_type& __sym, string_type& __sn,
3178 int& __fd)
3179{
3180 if (__intl)
3181 {
3182 const moneypunct<char_type, true>& __mp =
3183 use_facet<moneypunct<char_type, true> >(__loc);
3184 if (__neg)
3185 {
3186 __pat = __mp.neg_format();
3187 __sn = __mp.negative_sign();
3188 }
3189 else
3190 {
3191 __pat = __mp.pos_format();
3192 __sn = __mp.positive_sign();
3193 }
3194 __dp = __mp.decimal_point();
3195 __ts = __mp.thousands_sep();
3196 __grp = __mp.grouping();
3197 __sym = __mp.curr_symbol();
3198 __fd = __mp.frac_digits();
3199 }
3200 else
3201 {
3202 const moneypunct<char_type, false>& __mp =
3203 use_facet<moneypunct<char_type, false> >(__loc);
3204 if (__neg)
3205 {
3206 __pat = __mp.neg_format();
3207 __sn = __mp.negative_sign();
3208 }
3209 else
3210 {
3211 __pat = __mp.pos_format();
3212 __sn = __mp.positive_sign();
3213 }
3214 __dp = __mp.decimal_point();
3215 __ts = __mp.thousands_sep();
3216 __grp = __mp.grouping();
3217 __sym = __mp.curr_symbol();
3218 __fd = __mp.frac_digits();
3219 }
3220}
3221
3222template <class _CharT>
3223void
3224__money_put<_CharT>::__format(char_type* __mb, char_type*& __mi, char_type*& __me,
3225 ios_base::fmtflags __flags,
3226 const char_type* __db, const char_type* __de,
3227 const ctype<char_type>& __ct, bool __neg,
3228 const money_base::pattern& __pat, char_type __dp,
3229 char_type __ts, const string& __grp,
3230 const string_type& __sym, const string_type& __sn,
3231 int __fd)
3232{
3233 __me = __mb;
3234 for (unsigned __p = 0; __p < 4; ++__p)
3235 {
3236 switch (__pat.field[__p])
3237 {
3238 case money_base::none:
3239 __mi = __me;
3240 break;
3241 case money_base::space:
3242 __mi = __me;
3243 *__me++ = __ct.widen(' ');
3244 break;
3245 case money_base::sign:
3246 if (!__sn.empty())
3247 *__me++ = __sn[0];
3248 break;
3249 case money_base::symbol:
3250 if (!__sym.empty() && (__flags & ios_base::showbase))
3251 __me = copy(__sym.begin(), __sym.end(), __me);
3252 break;
3253 case money_base::value:
3254 {
3255 // remember start of value so we can reverse it
3256 char_type* __t = __me;
3257 // find beginning of digits
3258 if (__neg)
3259 ++__db;
3260 // find end of digits
3261 const char_type* __d;
3262 for (__d = __db; __d < __de; ++__d)
3263 if (!__ct.is(ctype_base::digit, *__d))
3264 break;
3265 // print fractional part
3266 if (__fd > 0)
3267 {
3268 int __f;
3269 for (__f = __fd; __d > __db && __f > 0; --__f)
3270 *__me++ = *--__d;
3271 char_type __z = __f > 0 ? __ct.widen('0') : char_type();
3272 for (; __f > 0; --__f)
3273 *__me++ = __z;
3274 *__me++ = __dp;
3275 }
3276 // print units part
3277 if (__d == __db)
3278 {
3279 *__me++ = __ct.widen('0');
3280 }
3281 else
3282 {
3283 unsigned __ng = 0;
3284 unsigned __ig = 0;
3285 unsigned __gl = __grp.empty() ? numeric_limits<unsigned>::max()
3286 : static_cast<unsigned>(__grp[__ig]);
3287 while (__d != __db)
3288 {
3289 if (__ng == __gl)
3290 {
3291 *__me++ = __ts;
3292 __ng = 0;
3293 if (++__ig < __grp.size())
3294 __gl = __grp[__ig] == numeric_limits<char>::max() ?
3295 numeric_limits<unsigned>::max() :
3296 static_cast<unsigned>(__grp[__ig]);
3297 }
3298 *__me++ = *--__d;
3299 ++__ng;
3300 }
3301 }
3302 // reverse it
3303 reverse(__t, __me);
3304 }
3305 break;
3306 }
3307 }
3308 // print rest of sign, if any
3309 if (__sn.size() > 1)
3310 __me = copy(__sn.begin()+1, __sn.end(), __me);
3311 // set alignment
3312 if ((__flags & ios_base::adjustfield) == ios_base::left)
3313 __mi = __me;
3314 else if ((__flags & ios_base::adjustfield) != ios_base::internal)
3315 __mi = __mb;
3316}
3317
3318extern template class __money_put<char>;
3319extern template class __money_put<wchar_t>;
3320
3321template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00003322class _LIBCPP_VISIBLE money_put
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003323 : public locale::facet,
3324 private __money_put<_CharT>
3325{
3326public:
3327 typedef _CharT char_type;
3328 typedef _OutputIterator iter_type;
3329 typedef basic_string<char_type> string_type;
3330
3331 _LIBCPP_ALWAYS_INLINE
3332 explicit money_put(size_t __refs = 0)
3333 : locale::facet(__refs) {}
3334
3335 _LIBCPP_ALWAYS_INLINE
3336 iter_type put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl,
3337 long double __units) const
3338 {
3339 return do_put(__s, __intl, __iob, __fl, __units);
3340 }
3341
3342 _LIBCPP_ALWAYS_INLINE
3343 iter_type put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl,
3344 const string_type& __digits) const
3345 {
3346 return do_put(__s, __intl, __iob, __fl, __digits);
3347 }
3348
3349 static locale::id id;
3350
3351protected:
Howard Hinnant82894812010-09-22 16:48:34 +00003352 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003353 ~money_put() {}
3354
3355 virtual iter_type do_put(iter_type __s, bool __intl, ios_base& __iob,
3356 char_type __fl, long double __units) const;
3357 virtual iter_type do_put(iter_type __s, bool __intl, ios_base& __iob,
3358 char_type __fl, const string_type& __digits) const;
3359};
3360
3361template <class _CharT, class _OutputIterator>
3362locale::id
3363money_put<_CharT, _OutputIterator>::id;
3364
3365template <class _CharT, class _OutputIterator>
3366_OutputIterator
3367money_put<_CharT, _OutputIterator>::do_put(iter_type __s, bool __intl,
3368 ios_base& __iob, char_type __fl,
3369 long double __units) const
3370{
3371 // convert to char
3372 const size_t __bs = 100;
3373 char __buf[__bs];
3374 char* __bb = __buf;
3375 char_type __digits[__bs];
3376 char_type* __db = __digits;
3377 size_t __n = snprintf(__bb, __bs, "%.0Lf", __units);
3378 unique_ptr<char, void(*)(void*)> __hn(0, free);
3379 unique_ptr<char_type, void(*)(void*)> __hd(0, free);
3380 // secure memory for digit storage
3381 if (__n > __bs-1)
3382 {
Howard Hinnantadff4892010-05-24 17:49:41 +00003383 __n = __nolocale_asprintf(&__bb, "%.0Lf", __units);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003384 if (__bb == 0)
3385 __throw_bad_alloc();
3386 __hn.reset(__bb);
3387 __hd.reset((char_type*)malloc(__n * sizeof(char_type)));
3388 if (__hd == 0)
3389 __throw_bad_alloc();
3390 __db = __hd.get();
3391 }
3392 // gather info
3393 locale __loc = __iob.getloc();
3394 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3395 __ct.widen(__bb, __bb + __n, __db);
3396 bool __neg = __n > 0 && __bb[0] == '-';
3397 money_base::pattern __pat;
3398 char_type __dp;
3399 char_type __ts;
3400 string __grp;
3401 string_type __sym;
3402 string_type __sn;
3403 int __fd;
3404 this->__gather_info(__intl, __neg, __loc, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3405 // secure memory for formatting
3406 char_type __mbuf[__bs];
3407 char_type* __mb = __mbuf;
3408 unique_ptr<char_type, void(*)(void*)> __hw(0, free);
3409 size_t __exn = static_cast<int>(__n) > __fd ?
3410 (__n - __fd) * 2 + __sn.size() + __sym.size() + __fd + 1
3411 : __sn.size() + __sym.size() + __fd + 2;
3412 if (__exn > __bs)
3413 {
3414 __hw.reset((char_type*)malloc(__exn * sizeof(char_type)));
3415 __mb = __hw.get();
3416 if (__mb == 0)
3417 __throw_bad_alloc();
3418 }
3419 // format
3420 char_type* __mi;
3421 char_type* __me;
3422 this->__format(__mb, __mi, __me, __iob.flags(),
3423 __db, __db + __n, __ct,
3424 __neg, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3425 return __pad_and_output(__s, __mb, __mi, __me, __iob, __fl);
3426}
3427
3428template <class _CharT, class _OutputIterator>
3429_OutputIterator
3430money_put<_CharT, _OutputIterator>::do_put(iter_type __s, bool __intl,
3431 ios_base& __iob, char_type __fl,
3432 const string_type& __digits) const
3433{
3434 // gather info
3435 locale __loc = __iob.getloc();
3436 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3437 bool __neg = __digits.size() > 0 && __digits[0] == __ct.widen('-');
3438 money_base::pattern __pat;
3439 char_type __dp;
3440 char_type __ts;
3441 string __grp;
3442 string_type __sym;
3443 string_type __sn;
3444 int __fd;
3445 this->__gather_info(__intl, __neg, __loc, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3446 // secure memory for formatting
3447 char_type __mbuf[100];
3448 char_type* __mb = __mbuf;
3449 unique_ptr<char_type, void(*)(void*)> __h(0, free);
3450 size_t __exn = __digits.size() > __fd ?
3451 (__digits.size() - __fd) * 2 + __sn.size() + __sym.size() + __fd + 1
3452 : __sn.size() + __sym.size() + __fd + 2;
3453 if (__exn > 100)
3454 {
3455 __h.reset((char_type*)malloc(__exn * sizeof(char_type)));
3456 __mb = __h.get();
3457 if (__mb == 0)
3458 __throw_bad_alloc();
3459 }
3460 // format
3461 char_type* __mi;
3462 char_type* __me;
3463 this->__format(__mb, __mi, __me, __iob.flags(),
3464 __digits.data(), __digits.data() + __digits.size(), __ct,
3465 __neg, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3466 return __pad_and_output(__s, __mb, __mi, __me, __iob, __fl);
3467}
3468
3469extern template class money_put<char>;
3470extern template class money_put<wchar_t>;
3471
3472// messages
3473
Howard Hinnant82894812010-09-22 16:48:34 +00003474class _LIBCPP_VISIBLE messages_base
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003475{
3476public:
3477 typedef nl_catd catalog;
3478
3479 _LIBCPP_ALWAYS_INLINE messages_base() {}
3480};
3481
3482template <class _CharT>
Howard Hinnant82894812010-09-22 16:48:34 +00003483class _LIBCPP_VISIBLE messages
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003484 : public locale::facet,
3485 public messages_base
3486{
3487public:
3488 typedef _CharT char_type;
3489 typedef basic_string<_CharT> string_type;
3490
3491 _LIBCPP_ALWAYS_INLINE
3492 explicit messages(size_t __refs = 0)
3493 : locale::facet(__refs) {}
3494
3495 _LIBCPP_ALWAYS_INLINE
3496 catalog open(const basic_string<char>& __nm, const locale& __loc) const
3497 {
3498 return do_open(__nm, __loc);
3499 }
3500
3501 _LIBCPP_ALWAYS_INLINE
3502 string_type get(catalog __c, int __set, int __msgid,
3503 const string_type& __dflt) const
3504 {
3505 return do_get(__c, __set, __msgid, __dflt);
3506 }
3507
3508 _LIBCPP_ALWAYS_INLINE
3509 void close(catalog __c) const
3510 {
3511 do_close(__c);
3512 }
3513
3514 static locale::id id;
3515
3516protected:
Howard Hinnant82894812010-09-22 16:48:34 +00003517 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003518 ~messages() {}
3519
3520 virtual catalog do_open(const basic_string<char>&, const locale&) const;
3521 virtual string_type do_get(catalog, int __set, int __msgid,
3522 const string_type& __dflt) const;
3523 virtual void do_close(catalog) const;
3524};
3525
3526template <class _CharT>
3527locale::id
3528messages<_CharT>::id;
3529
3530template <class _CharT>
3531typename messages<_CharT>::catalog
3532messages<_CharT>::do_open(const basic_string<char>& __nm, const locale&) const
3533{
3534 return catopen(__nm.c_str(), NL_CAT_LOCALE);
3535}
3536
3537template <class _CharT>
3538typename messages<_CharT>::string_type
3539messages<_CharT>::do_get(catalog __c, int __set, int __msgid,
3540 const string_type& __dflt) const
3541{
3542 string __ndflt;
3543 __narrow_to_utf8<sizeof(char_type)*__CHAR_BIT__>()(back_inserter(__ndflt),
3544 __dflt.c_str(),
3545 __dflt.c_str() + __dflt.size());
3546 char* __n = catgets(__c, __set, __msgid, __ndflt.c_str());
3547 string_type __w;
3548 __widen_from_utf8<sizeof(char_type)*__CHAR_BIT__>()(back_inserter(__w),
3549 __n, __n + strlen(__n));
3550 return __w;
3551}
3552
3553template <class _CharT>
3554void
3555messages<_CharT>::do_close(catalog __c) const
3556{
3557 catclose(__c);
3558}
3559
3560extern template class messages<char>;
3561extern template class messages<wchar_t>;
3562
3563template <class _CharT>
Howard Hinnant82894812010-09-22 16:48:34 +00003564class _LIBCPP_VISIBLE messages_byname
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003565 : public messages<_CharT>
3566{
3567public:
3568 typedef messages_base::catalog catalog;
3569 typedef basic_string<_CharT> string_type;
3570
3571 _LIBCPP_ALWAYS_INLINE
3572 explicit messages_byname(const char*, size_t __refs = 0)
3573 : messages<_CharT>(__refs) {}
3574
3575 _LIBCPP_ALWAYS_INLINE
3576 explicit messages_byname(const string&, size_t __refs = 0)
3577 : messages<_CharT>(__refs) {}
3578
3579protected:
Howard Hinnant82894812010-09-22 16:48:34 +00003580 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003581 ~messages_byname() {}
3582};
3583
3584extern template class messages_byname<char>;
3585extern template class messages_byname<wchar_t>;
3586
Howard Hinnantd23b4642010-05-31 20:58:54 +00003587template<class _Codecvt, class _Elem = wchar_t,
3588 class _Wide_alloc = allocator<_Elem>,
3589 class _Byte_alloc = allocator<char> >
Howard Hinnant82894812010-09-22 16:48:34 +00003590class _LIBCPP_VISIBLE wstring_convert
Howard Hinnantd23b4642010-05-31 20:58:54 +00003591{
3592public:
3593 typedef basic_string<char, char_traits<char>, _Byte_alloc> byte_string;
3594 typedef basic_string<_Elem, char_traits<_Elem>, _Wide_alloc> wide_string;
3595 typedef typename _Codecvt::state_type state_type;
3596 typedef typename wide_string::traits_type::int_type int_type;
3597
3598private:
3599 byte_string __byte_err_string_;
3600 wide_string __wide_err_string_;
3601 _Codecvt* __cvtptr_;
3602 state_type __cvtstate_;
3603 size_t __cvtcount_;
3604
3605 wstring_convert(const wstring_convert& __wc);
3606 wstring_convert& operator=(const wstring_convert& __wc);
3607public:
3608 wstring_convert(_Codecvt* __pcvt = new _Codecvt);
3609 wstring_convert(_Codecvt* __pcvt, state_type __state);
3610 wstring_convert(const byte_string& __byte_err,
3611 const wide_string& __wide_err = wide_string());
Howard Hinnant73d21a42010-09-04 23:28:19 +00003612#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantd23b4642010-05-31 20:58:54 +00003613 wstring_convert(wstring_convert&& __wc);
3614#endif
3615 ~wstring_convert();
3616
Howard Hinnant82894812010-09-22 16:48:34 +00003617 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003618 wide_string from_bytes(char __byte)
3619 {return from_bytes(&__byte, &__byte+1);}
Howard Hinnant82894812010-09-22 16:48:34 +00003620 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003621 wide_string from_bytes(const char* __ptr)
3622 {return from_bytes(__ptr, __ptr + char_traits<char>::length(__ptr));}
Howard Hinnant82894812010-09-22 16:48:34 +00003623 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003624 wide_string from_bytes(const byte_string& __str)
3625 {return from_bytes(__str.data(), __str.data() + __str.size());}
3626 wide_string from_bytes(const char* __first, const char* __last);
3627
Howard Hinnant82894812010-09-22 16:48:34 +00003628 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003629 byte_string to_bytes(_Elem __wchar)
3630 {return to_bytes(&__wchar, &__wchar+1);}
Howard Hinnant82894812010-09-22 16:48:34 +00003631 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003632 byte_string to_bytes(const _Elem* __wptr)
3633 {return to_bytes(__wptr, __wptr + char_traits<_Elem>::length(__wptr));}
Howard Hinnant82894812010-09-22 16:48:34 +00003634 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003635 byte_string to_bytes(const wide_string& __wstr)
3636 {return to_bytes(__wstr.data(), __wstr.data() + __wstr.size());}
3637 byte_string to_bytes(const _Elem* __first, const _Elem* __last);
3638
Howard Hinnant82894812010-09-22 16:48:34 +00003639 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003640 size_t converted() const {return __cvtcount_;}
Howard Hinnant82894812010-09-22 16:48:34 +00003641 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003642 state_type state() const {return __cvtstate_;}
3643};
3644
3645template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Howard Hinnant82894812010-09-22 16:48:34 +00003646inline _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003647wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3648 wstring_convert(_Codecvt* __pcvt)
3649 : __cvtptr_(__pcvt), __cvtstate_(), __cvtcount_(0)
3650{
3651}
3652
3653template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Howard Hinnant82894812010-09-22 16:48:34 +00003654inline _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003655wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3656 wstring_convert(_Codecvt* __pcvt, state_type __state)
3657 : __cvtptr_(__pcvt), __cvtstate_(__state), __cvtcount_(0)
3658{
3659}
3660
3661template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3662wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3663 wstring_convert(const byte_string& __byte_err, const wide_string& __wide_err)
3664 : __byte_err_string_(__byte_err), __wide_err_string_(__wide_err),
3665 __cvtstate_(), __cvtcount_(0)
3666{
3667 __cvtptr_ = new _Codecvt;
3668}
3669
Howard Hinnant73d21a42010-09-04 23:28:19 +00003670#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantd23b4642010-05-31 20:58:54 +00003671
3672template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Howard Hinnant82894812010-09-22 16:48:34 +00003673inline _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003674wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3675 wstring_convert(wstring_convert&& __wc)
3676 : __byte_err_string_(_STD::move(__wc.__byte_err_string_)),
3677 __wide_err_string_(_STD::move(__wc.__wide_err_string_)),
3678 __cvtptr_(__wc.__cvtptr_),
3679 __cvtstate_(__wc.__cvtstate_), __cvtcount_(__wc.__cvtstate_)
3680{
3681 __wc.__cvtptr_ = nullptr;
3682}
3683
Howard Hinnantbfd55302010-09-04 23:46:48 +00003684#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantd23b4642010-05-31 20:58:54 +00003685
3686template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3687wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::~wstring_convert()
3688{
3689 delete __cvtptr_;
3690}
3691
3692template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3693typename wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::wide_string
3694wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3695 from_bytes(const char* __frm, const char* __frm_end)
3696{
3697 __cvtcount_ = 0;
3698 if (__cvtptr_ != nullptr)
3699 {
3700 wide_string __ws(2*(__frm_end - __frm), _Elem());
3701 __ws.resize(__ws.capacity());
3702 codecvt_base::result __r = codecvt_base::ok;
3703 state_type __st = __cvtstate_;
3704 if (__frm != __frm_end)
3705 {
3706 _Elem* __to = &__ws[0];
3707 _Elem* __to_end = __to + __ws.size();
3708 const char* __frm_nxt;
3709 do
3710 {
3711 _Elem* __to_nxt;
3712 __r = __cvtptr_->in(__st, __frm, __frm_end, __frm_nxt,
3713 __to, __to_end, __to_nxt);
3714 __cvtcount_ += __frm_nxt - __frm;
3715 if (__frm_nxt == __frm)
3716 {
3717 __r = codecvt_base::error;
3718 }
3719 else if (__r == codecvt_base::noconv)
3720 {
3721 __ws.resize(__to - &__ws[0]);
3722 // This only gets executed if _Elem is char
3723 __ws.append((const _Elem*)__frm, (const _Elem*)__frm_end);
3724 __frm = __frm_nxt;
3725 __r = codecvt_base::ok;
3726 }
3727 else if (__r == codecvt_base::ok)
3728 {
3729 __ws.resize(__to_nxt - &__ws[0]);
3730 __frm = __frm_nxt;
3731 }
3732 else if (__r == codecvt_base::partial)
3733 {
3734 ptrdiff_t __s = __to_nxt - &__ws[0];
3735 __ws.resize(2 * __s);
3736 __to = &__ws[0] + __s;
3737 __to_end = &__ws[0] + __ws.size();
3738 __frm = __frm_nxt;
3739 }
3740 } while (__r == codecvt_base::partial && __frm_nxt < __frm_end);
3741 }
3742 if (__r == codecvt_base::ok)
3743 return __ws;
3744 }
Howard Hinnantd4444702010-08-11 17:04:31 +00003745#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00003746 if (__wide_err_string_.empty())
3747 throw range_error("wstring_convert: from_bytes error");
Howard Hinnant324bb032010-08-22 00:02:43 +00003748#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00003749 return __wide_err_string_;
3750}
3751
3752template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3753typename wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::byte_string
3754wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3755 to_bytes(const _Elem* __frm, const _Elem* __frm_end)
3756{
3757 __cvtcount_ = 0;
3758 if (__cvtptr_ != nullptr)
3759 {
3760 byte_string __bs(2*(__frm_end - __frm), char());
3761 __bs.resize(__bs.capacity());
3762 codecvt_base::result __r = codecvt_base::ok;
3763 state_type __st = __cvtstate_;
3764 if (__frm != __frm_end)
3765 {
3766 char* __to = &__bs[0];
3767 char* __to_end = __to + __bs.size();
3768 const _Elem* __frm_nxt;
3769 do
3770 {
3771 char* __to_nxt;
3772 __r = __cvtptr_->out(__st, __frm, __frm_end, __frm_nxt,
3773 __to, __to_end, __to_nxt);
3774 __cvtcount_ += __frm_nxt - __frm;
3775 if (__frm_nxt == __frm)
3776 {
3777 __r = codecvt_base::error;
3778 }
3779 else if (__r == codecvt_base::noconv)
3780 {
3781 __bs.resize(__to - &__bs[0]);
3782 // This only gets executed if _Elem is char
3783 __bs.append((const char*)__frm, (const char*)__frm_end);
3784 __frm = __frm_nxt;
3785 __r = codecvt_base::ok;
3786 }
3787 else if (__r == codecvt_base::ok)
3788 {
3789 __bs.resize(__to_nxt - &__bs[0]);
3790 __frm = __frm_nxt;
3791 }
3792 else if (__r == codecvt_base::partial)
3793 {
3794 ptrdiff_t __s = __to_nxt - &__bs[0];
3795 __bs.resize(2 * __s);
3796 __to = &__bs[0] + __s;
3797 __to_end = &__bs[0] + __bs.size();
3798 __frm = __frm_nxt;
3799 }
3800 } while (__r == codecvt_base::partial && __frm_nxt < __frm_end);
3801 }
3802 if (__r == codecvt_base::ok)
3803 {
3804 size_t __s = __bs.size();
3805 __bs.resize(__bs.capacity());
3806 char* __to = &__bs[0] + __s;
3807 char* __to_end = __to + __bs.size();
3808 do
3809 {
3810 char* __to_nxt;
3811 __r = __cvtptr_->unshift(__st, __to, __to_end, __to_nxt);
3812 if (__r == codecvt_base::noconv)
3813 {
3814 __bs.resize(__to - &__bs[0]);
3815 __r = codecvt_base::ok;
3816 }
3817 else if (__r == codecvt_base::ok)
3818 {
3819 __bs.resize(__to_nxt - &__bs[0]);
3820 }
3821 else if (__r == codecvt_base::partial)
3822 {
3823 ptrdiff_t __s = __to_nxt - &__bs[0];
3824 __bs.resize(2 * __s);
3825 __to = &__bs[0] + __s;
3826 __to_end = &__bs[0] + __bs.size();
3827 }
3828 } while (__r == codecvt_base::partial);
3829 if (__r == codecvt_base::ok)
3830 return __bs;
3831 }
3832 }
Howard Hinnantd4444702010-08-11 17:04:31 +00003833#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00003834 if (__byte_err_string_.empty())
3835 throw range_error("wstring_convert: to_bytes error");
Howard Hinnant324bb032010-08-22 00:02:43 +00003836#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00003837 return __byte_err_string_;
3838}
3839
3840template <class _Codecvt, class _Elem = wchar_t, class _Tr = char_traits<_Elem> >
Howard Hinnant82894812010-09-22 16:48:34 +00003841class _LIBCPP_VISIBLE wbuffer_convert
Howard Hinnantd23b4642010-05-31 20:58:54 +00003842 : public basic_streambuf<_Elem, _Tr>
3843{
3844public:
3845 // types:
3846 typedef _Elem char_type;
3847 typedef _Tr traits_type;
3848 typedef typename traits_type::int_type int_type;
3849 typedef typename traits_type::pos_type pos_type;
3850 typedef typename traits_type::off_type off_type;
3851 typedef typename _Codecvt::state_type state_type;
3852
3853private:
Howard Hinnant4b53f502010-06-01 20:09:18 +00003854 char* __extbuf_;
3855 const char* __extbufnext_;
3856 const char* __extbufend_;
3857 char __extbuf_min_[8];
3858 size_t __ebs_;
3859 char_type* __intbuf_;
3860 size_t __ibs_;
Howard Hinnantd23b4642010-05-31 20:58:54 +00003861 streambuf* __bufptr_;
Howard Hinnant4b53f502010-06-01 20:09:18 +00003862 _Codecvt* __cv_;
3863 state_type __st_;
3864 ios_base::openmode __cm_;
3865 bool __owns_eb_;
3866 bool __owns_ib_;
3867 bool __always_noconv_;
Howard Hinnantd23b4642010-05-31 20:58:54 +00003868
Howard Hinnant4b53f502010-06-01 20:09:18 +00003869 wbuffer_convert(const wbuffer_convert&);
3870 wbuffer_convert& operator=(const wbuffer_convert&);
Howard Hinnantd23b4642010-05-31 20:58:54 +00003871public:
3872 wbuffer_convert(streambuf* __bytebuf = 0, _Codecvt* __pcvt = new _Codecvt,
Howard Hinnant4b53f502010-06-01 20:09:18 +00003873 state_type __state = state_type());
3874 ~wbuffer_convert();
Howard Hinnantd23b4642010-05-31 20:58:54 +00003875
Howard Hinnant82894812010-09-22 16:48:34 +00003876 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantd23b4642010-05-31 20:58:54 +00003877 streambuf* rdbuf() const {return __bufptr_;}
Howard Hinnant82894812010-09-22 16:48:34 +00003878 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantd23b4642010-05-31 20:58:54 +00003879 streambuf* rdbuf(streambuf* __bytebuf)
3880 {
3881 streambuf* __r = __bufptr_;
3882 __bufptr_ = __bytebuf;
3883 return __r;
3884 }
3885
Howard Hinnant82894812010-09-22 16:48:34 +00003886 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant4b53f502010-06-01 20:09:18 +00003887 state_type state() const {return __st_;}
Howard Hinnantd23b4642010-05-31 20:58:54 +00003888
3889protected:
Howard Hinnant4b53f502010-06-01 20:09:18 +00003890 virtual int_type underflow();
3891 virtual int_type pbackfail(int_type __c = traits_type::eof());
Howard Hinnantd23b4642010-05-31 20:58:54 +00003892 virtual int_type overflow (int_type __c = traits_type::eof());
Howard Hinnant4b53f502010-06-01 20:09:18 +00003893 virtual basic_streambuf<char_type, traits_type>* setbuf(char_type* __s,
3894 streamsize __n);
3895 virtual pos_type seekoff(off_type __off, ios_base::seekdir __way,
3896 ios_base::openmode __wch = ios_base::in | ios_base::out);
3897 virtual pos_type seekpos(pos_type __sp,
3898 ios_base::openmode __wch = ios_base::in | ios_base::out);
3899 virtual int sync();
3900
3901private:
3902 bool __read_mode();
3903 void __write_mode();
3904 wbuffer_convert* __close();
Howard Hinnantd23b4642010-05-31 20:58:54 +00003905};
3906
3907template <class _Codecvt, class _Elem, class _Tr>
Howard Hinnant4b53f502010-06-01 20:09:18 +00003908wbuffer_convert<_Codecvt, _Elem, _Tr>::
3909 wbuffer_convert(streambuf* __bytebuf, _Codecvt* __pcvt, state_type __state)
3910 : __extbuf_(0),
3911 __extbufnext_(0),
3912 __extbufend_(0),
3913 __ebs_(0),
3914 __intbuf_(0),
3915 __ibs_(0),
3916 __bufptr_(__bytebuf),
3917 __cv_(__pcvt),
3918 __st_(__state),
3919 __cm_(0),
3920 __owns_eb_(false),
3921 __owns_ib_(false),
3922 __always_noconv_(__cv_ ? __cv_->always_noconv() : false)
3923{
3924 setbuf(0, 4096);
3925}
3926
3927template <class _Codecvt, class _Elem, class _Tr>
3928wbuffer_convert<_Codecvt, _Elem, _Tr>::~wbuffer_convert()
3929{
3930 __close();
3931 delete __cv_;
3932 if (__owns_eb_)
3933 delete [] __extbuf_;
3934 if (__owns_ib_)
3935 delete [] __intbuf_;
3936}
3937
3938template <class _Codecvt, class _Elem, class _Tr>
3939typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
3940wbuffer_convert<_Codecvt, _Elem, _Tr>::underflow()
3941{
3942 if (__cv_ == 0 || __bufptr_ == 0)
3943 return traits_type::eof();
3944 bool __initial = __read_mode();
3945 char_type __1buf;
3946 if (this->gptr() == 0)
3947 this->setg(&__1buf, &__1buf+1, &__1buf+1);
3948 const size_t __unget_sz = __initial ? 0 : min<size_t>((this->egptr() - this->eback()) / 2, 4);
3949 int_type __c = traits_type::eof();
3950 if (this->gptr() == this->egptr())
3951 {
3952 memmove(this->eback(), this->egptr() - __unget_sz, __unget_sz * sizeof(char_type));
3953 if (__always_noconv_)
3954 {
3955 streamsize __nmemb = static_cast<streamsize>(this->egptr() - this->eback() - __unget_sz);
3956 __nmemb = __bufptr_->sgetn((char*)this->eback() + __unget_sz, __nmemb);
3957 if (__nmemb != 0)
3958 {
3959 this->setg(this->eback(),
3960 this->eback() + __unget_sz,
3961 this->eback() + __unget_sz + __nmemb);
3962 __c = *this->gptr();
3963 }
3964 }
3965 else
3966 {
3967 memmove(__extbuf_, __extbufnext_, __extbufend_ - __extbufnext_);
3968 __extbufnext_ = __extbuf_ + (__extbufend_ - __extbufnext_);
3969 __extbufend_ = __extbuf_ + (__extbuf_ == __extbuf_min_ ? sizeof(__extbuf_min_) : __ebs_);
3970 streamsize __nmemb = min(static_cast<streamsize>(this->egptr() - this->eback() - __unget_sz),
3971 static_cast<streamsize>(__extbufend_ - __extbufnext_));
3972 codecvt_base::result __r;
3973 state_type __svs = __st_;
3974 streamsize __nr = __bufptr_->sgetn(const_cast<char*>(__extbufnext_), __nmemb);
3975 if (__nr != 0)
3976 {
3977 __extbufend_ = __extbufnext_ + __nr;
3978 char_type* __inext;
3979 __r = __cv_->in(__st_, __extbuf_, __extbufend_, __extbufnext_,
3980 this->eback() + __unget_sz,
3981 this->egptr(), __inext);
3982 if (__r == codecvt_base::noconv)
3983 {
3984 this->setg((char_type*)__extbuf_, (char_type*)__extbuf_, (char_type*)__extbufend_);
3985 __c = *this->gptr();
3986 }
3987 else if (__inext != this->eback() + __unget_sz)
3988 {
3989 this->setg(this->eback(), this->eback() + __unget_sz, __inext);
3990 __c = *this->gptr();
3991 }
3992 }
3993 }
3994 }
3995 else
3996 __c = *this->gptr();
3997 if (this->eback() == &__1buf)
3998 this->setg(0, 0, 0);
3999 return __c;
4000}
4001
4002template <class _Codecvt, class _Elem, class _Tr>
4003typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
4004wbuffer_convert<_Codecvt, _Elem, _Tr>::pbackfail(int_type __c)
4005{
4006 if (__cv_ != 0 && __bufptr_ != 0 && this->eback() < this->gptr())
4007 {
4008 if (traits_type::eq_int_type(__c, traits_type::eof()))
4009 {
4010 this->gbump(-1);
4011 return traits_type::not_eof(__c);
4012 }
4013 if (traits_type::eq(traits_type::to_char_type(__c), this->gptr()[-1]))
4014 {
4015 this->gbump(-1);
4016 *this->gptr() = traits_type::to_char_type(__c);
4017 return __c;
4018 }
4019 }
4020 return traits_type::eof();
4021}
4022
4023template <class _Codecvt, class _Elem, class _Tr>
Howard Hinnantd23b4642010-05-31 20:58:54 +00004024typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
4025wbuffer_convert<_Codecvt, _Elem, _Tr>::overflow(int_type __c)
4026{
Howard Hinnant4b53f502010-06-01 20:09:18 +00004027 if (__cv_ == 0 || __bufptr_ == 0)
4028 return traits_type::eof();
4029 __write_mode();
4030 char_type __1buf;
4031 char_type* __pb_save = this->pbase();
4032 char_type* __epb_save = this->epptr();
4033 if (!traits_type::eq_int_type(__c, traits_type::eof()))
4034 {
4035 if (this->pptr() == 0)
4036 this->setp(&__1buf, &__1buf+1);
4037 *this->pptr() = traits_type::to_char_type(__c);
4038 this->pbump(1);
4039 }
4040 if (this->pptr() != this->pbase())
4041 {
4042 if (__always_noconv_)
4043 {
4044 streamsize __nmemb = static_cast<streamsize>(this->pptr() - this->pbase());
4045 if (__bufptr_->sputn((const char*)this->pbase(), __nmemb) != __nmemb)
4046 return traits_type::eof();
4047 }
4048 else
4049 {
4050 char* __extbe = __extbuf_;
4051 codecvt_base::result __r;
4052 do
4053 {
4054 const char_type* __e;
4055 __r = __cv_->out(__st_, this->pbase(), this->pptr(), __e,
4056 __extbuf_, __extbuf_ + __ebs_, __extbe);
4057 if (__e == this->pbase())
4058 return traits_type::eof();
4059 if (__r == codecvt_base::noconv)
4060 {
4061 streamsize __nmemb = static_cast<size_t>(this->pptr() - this->pbase());
4062 if (__bufptr_->sputn((const char*)this->pbase(), __nmemb) != __nmemb)
4063 return traits_type::eof();
4064 }
4065 else if (__r == codecvt_base::ok || __r == codecvt_base::partial)
4066 {
4067 streamsize __nmemb = static_cast<size_t>(__extbe - __extbuf_);
4068 if (__bufptr_->sputn(__extbuf_, __nmemb) != __nmemb)
4069 return traits_type::eof();
4070 if (__r == codecvt_base::partial)
4071 {
4072 this->setp((char_type*)__e, this->pptr());
4073 this->pbump(this->epptr() - this->pbase());
4074 }
4075 }
4076 else
4077 return traits_type::eof();
4078 } while (__r == codecvt_base::partial);
4079 }
4080 this->setp(__pb_save, __epb_save);
4081 }
4082 return traits_type::not_eof(__c);
4083}
4084
4085template <class _Codecvt, class _Elem, class _Tr>
4086basic_streambuf<_Elem, _Tr>*
4087wbuffer_convert<_Codecvt, _Elem, _Tr>::setbuf(char_type* __s, streamsize __n)
4088{
4089 this->setg(0, 0, 0);
4090 this->setp(0, 0);
4091 if (__owns_eb_)
4092 delete [] __extbuf_;
4093 if (__owns_ib_)
4094 delete [] __intbuf_;
4095 __ebs_ = __n;
4096 if (__ebs_ > sizeof(__extbuf_min_))
4097 {
4098 if (__always_noconv_ && __s)
4099 {
4100 __extbuf_ = (char*)__s;
4101 __owns_eb_ = false;
4102 }
4103 else
4104 {
4105 __extbuf_ = new char[__ebs_];
4106 __owns_eb_ = true;
4107 }
4108 }
4109 else
4110 {
4111 __extbuf_ = __extbuf_min_;
4112 __ebs_ = sizeof(__extbuf_min_);
4113 __owns_eb_ = false;
4114 }
4115 if (!__always_noconv_)
4116 {
4117 __ibs_ = max<streamsize>(__n, sizeof(__extbuf_min_));
4118 if (__s && __ibs_ >= sizeof(__extbuf_min_))
4119 {
4120 __intbuf_ = __s;
4121 __owns_ib_ = false;
4122 }
4123 else
4124 {
4125 __intbuf_ = new char_type[__ibs_];
4126 __owns_ib_ = true;
4127 }
4128 }
4129 else
4130 {
4131 __ibs_ = 0;
4132 __intbuf_ = 0;
4133 __owns_ib_ = false;
4134 }
4135 return this;
4136}
4137
4138template <class _Codecvt, class _Elem, class _Tr>
4139typename wbuffer_convert<_Codecvt, _Elem, _Tr>::pos_type
4140wbuffer_convert<_Codecvt, _Elem, _Tr>::seekoff(off_type __off, ios_base::seekdir __way,
4141 ios_base::openmode __om)
4142{
4143 int __width = __cv_->encoding();
4144 if (__cv_ == 0 || __bufptr_ == 0 || (__width <= 0 && __off != 0) || sync())
4145 return pos_type(off_type(-1));
4146 // __width > 0 || __off == 0
4147 switch (__way)
4148 {
4149 case ios_base::beg:
4150 break;
4151 case ios_base::cur:
4152 break;
4153 case ios_base::end:
4154 break;
4155 default:
4156 return pos_type(off_type(-1));
4157 }
4158 pos_type __r = __bufptr_->pubseekoff(__width * __off, __way, __om);
4159 __r.state(__st_);
4160 return __r;
4161}
4162
4163template <class _Codecvt, class _Elem, class _Tr>
4164typename wbuffer_convert<_Codecvt, _Elem, _Tr>::pos_type
4165wbuffer_convert<_Codecvt, _Elem, _Tr>::seekpos(pos_type __sp, ios_base::openmode __wch)
4166{
4167 if (__cv_ == 0 || __bufptr_ == 0 || sync())
4168 return pos_type(off_type(-1));
4169 if (__bufptr_->pubseekpos(__sp, __wch) == pos_type(off_type(-1)))
4170 return pos_type(off_type(-1));
4171 return __sp;
4172}
4173
4174template <class _Codecvt, class _Elem, class _Tr>
4175int
4176wbuffer_convert<_Codecvt, _Elem, _Tr>::sync()
4177{
4178 if (__cv_ == 0 || __bufptr_ == 0)
4179 return 0;
4180 if (__cm_ & ios_base::out)
4181 {
4182 if (this->pptr() != this->pbase())
4183 if (overflow() == traits_type::eof())
4184 return -1;
4185 codecvt_base::result __r;
4186 do
4187 {
4188 char* __extbe;
4189 __r = __cv_->unshift(__st_, __extbuf_, __extbuf_ + __ebs_, __extbe);
4190 streamsize __nmemb = static_cast<streamsize>(__extbe - __extbuf_);
4191 if (__bufptr_->sputn(__extbuf_, __nmemb) != __nmemb)
4192 return -1;
4193 } while (__r == codecvt_base::partial);
4194 if (__r == codecvt_base::error)
4195 return -1;
4196 if (__bufptr_->pubsync())
4197 return -1;
4198 }
4199 else if (__cm_ & ios_base::in)
4200 {
4201 off_type __c;
4202 if (__always_noconv_)
4203 __c = this->egptr() - this->gptr();
4204 else
4205 {
4206 int __width = __cv_->encoding();
4207 __c = __extbufend_ - __extbufnext_;
4208 if (__width > 0)
4209 __c += __width * (this->egptr() - this->gptr());
4210 else
4211 {
4212 if (this->gptr() != this->egptr())
4213 {
4214 reverse(this->gptr(), this->egptr());
4215 codecvt_base::result __r;
4216 const char_type* __e = this->gptr();
4217 char* __extbe;
4218 do
4219 {
4220 __r = __cv_->out(__st_, __e, this->egptr(), __e,
4221 __extbuf_, __extbuf_ + __ebs_, __extbe);
4222 switch (__r)
4223 {
4224 case codecvt_base::noconv:
4225 __c += this->egptr() - this->gptr();
4226 break;
4227 case codecvt_base::ok:
4228 case codecvt_base::partial:
4229 __c += __extbe - __extbuf_;
4230 break;
4231 default:
4232 return -1;
4233 }
4234 } while (__r == codecvt_base::partial);
4235 }
4236 }
4237 }
4238 if (__bufptr_->pubseekoff(-__c, ios_base::cur, __cm_) == pos_type(off_type(-1)))
4239 return -1;
4240 this->setg(0, 0, 0);
4241 __cm_ = 0;
4242 }
4243 return 0;
4244}
4245
4246template <class _Codecvt, class _Elem, class _Tr>
4247bool
4248wbuffer_convert<_Codecvt, _Elem, _Tr>::__read_mode()
4249{
4250 if (!(__cm_ & ios_base::in))
4251 {
4252 this->setp(0, 0);
4253 if (__always_noconv_)
4254 this->setg((char_type*)__extbuf_,
4255 (char_type*)__extbuf_ + __ebs_,
4256 (char_type*)__extbuf_ + __ebs_);
4257 else
4258 this->setg(__intbuf_, __intbuf_ + __ibs_, __intbuf_ + __ibs_);
4259 __cm_ = ios_base::in;
4260 return true;
4261 }
4262 return false;
4263}
4264
4265template <class _Codecvt, class _Elem, class _Tr>
4266void
4267wbuffer_convert<_Codecvt, _Elem, _Tr>::__write_mode()
4268{
4269 if (!(__cm_ & ios_base::out))
4270 {
4271 this->setg(0, 0, 0);
4272 if (__ebs_ > sizeof(__extbuf_min_))
4273 {
4274 if (__always_noconv_)
4275 this->setp((char_type*)__extbuf_,
4276 (char_type*)__extbuf_ + (__ebs_ - 1));
4277 else
4278 this->setp(__intbuf_, __intbuf_ + (__ibs_ - 1));
4279 }
4280 else
4281 this->setp(0, 0);
4282 __cm_ = ios_base::out;
4283 }
4284}
4285
4286template <class _Codecvt, class _Elem, class _Tr>
4287wbuffer_convert<_Codecvt, _Elem, _Tr>*
4288wbuffer_convert<_Codecvt, _Elem, _Tr>::__close()
4289{
4290 wbuffer_convert* __rt = 0;
4291 if (__cv_ != 0 && __bufptr_ != 0)
4292 {
4293 __rt = this;
4294 if ((__cm_ & ios_base::out) && sync())
4295 __rt = 0;
4296 }
4297 return __rt;
Howard Hinnantd23b4642010-05-31 20:58:54 +00004298}
4299
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004300_LIBCPP_END_NAMESPACE_STD
4301
4302#endif // _LIBCPP_LOCALE