blob: 60aab1d84bf0b1694bd2045af085869bd7f0202c [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>
1771class __time_get_c_storage
1772{
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
Howard Hinnant82894812010-09-22 16:48:34 +00002653 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002654 virtual char_type do_decimal_point() const {return numeric_limits<char_type>::max();}
Howard Hinnant82894812010-09-22 16:48:34 +00002655 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002656 virtual char_type do_thousands_sep() const {return numeric_limits<char_type>::max();}
Howard Hinnant82894812010-09-22 16:48:34 +00002657 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002658 virtual string do_grouping() const {return string();}
Howard Hinnant82894812010-09-22 16:48:34 +00002659 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002660 virtual string_type do_curr_symbol() const {return string_type();}
Howard Hinnant82894812010-09-22 16:48:34 +00002661 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002662 virtual string_type do_positive_sign() const {return string_type();}
Howard Hinnant82894812010-09-22 16:48:34 +00002663 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002664 virtual string_type do_negative_sign() const {return string_type(1, '-');}
Howard Hinnant82894812010-09-22 16:48:34 +00002665 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002666 virtual int do_frac_digits() const {return 0;}
Howard Hinnant82894812010-09-22 16:48:34 +00002667 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002668 virtual pattern do_pos_format() const
2669 {pattern __p = {symbol, sign, none, value}; return __p;}
Howard Hinnant82894812010-09-22 16:48:34 +00002670 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002671 virtual pattern do_neg_format() const
2672 {pattern __p = {symbol, sign, none, value}; return __p;}
2673};
2674
2675template <class _CharT, bool _International>
2676locale::id
2677moneypunct<_CharT, _International>::id;
2678
2679extern template class moneypunct<char, false>;
2680extern template class moneypunct<char, true>;
2681extern template class moneypunct<wchar_t, false>;
2682extern template class moneypunct<wchar_t, true>;
2683
2684// moneypunct_byname
2685
2686template <class _CharT, bool _International = false>
Howard Hinnant82894812010-09-22 16:48:34 +00002687class _LIBCPP_VISIBLE moneypunct_byname
2688 : public moneypunct<_CharT, _International>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002689{
2690public:
2691 typedef money_base::pattern pattern;
2692 typedef _CharT char_type;
2693 typedef basic_string<char_type> string_type;
2694
2695 _LIBCPP_ALWAYS_INLINE
2696 explicit moneypunct_byname(const char* __nm, size_t __refs = 0)
2697 : moneypunct<_CharT, _International>(__refs) {init(__nm);}
2698
2699 _LIBCPP_ALWAYS_INLINE
2700 explicit moneypunct_byname(const string& __nm, size_t __refs = 0)
2701 : moneypunct<_CharT, _International>(__refs) {init(__nm.c_str());}
2702
2703protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002704 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002705 ~moneypunct_byname() {}
2706
Howard Hinnant82894812010-09-22 16:48:34 +00002707 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002708 virtual char_type do_decimal_point() const {return __decimal_point_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002709 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002710 virtual char_type do_thousands_sep() const {return __thousands_sep_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002711 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002712 virtual string do_grouping() const {return __grouping_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002713 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002714 virtual string_type do_curr_symbol() const {return __curr_symbol_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002715 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002716 virtual string_type do_positive_sign() const {return __positive_sign_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002717 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002718 virtual string_type do_negative_sign() const {return __negative_sign_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002719 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002720 virtual int do_frac_digits() const {return __frac_digits_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002721 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002722 virtual pattern do_pos_format() const {return __pos_format_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002723 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002724 virtual pattern do_neg_format() const {return __neg_format_;}
2725
2726private:
2727 char_type __decimal_point_;
2728 char_type __thousands_sep_;
2729 string __grouping_;
2730 string_type __curr_symbol_;
2731 string_type __positive_sign_;
2732 string_type __negative_sign_;
2733 int __frac_digits_;
2734 pattern __pos_format_;
2735 pattern __neg_format_;
2736
2737 void init(const char*);
2738};
2739
2740template<> void moneypunct_byname<char, false>::init(const char*);
2741template<> void moneypunct_byname<char, true>::init(const char*);
2742template<> void moneypunct_byname<wchar_t, false>::init(const char*);
2743template<> void moneypunct_byname<wchar_t, true>::init(const char*);
2744
2745extern template class moneypunct_byname<char, false>;
2746extern template class moneypunct_byname<char, true>;
2747extern template class moneypunct_byname<wchar_t, false>;
2748extern template class moneypunct_byname<wchar_t, true>;
2749
2750// money_get
2751
2752template <class _CharT>
2753class __money_get
2754{
2755protected:
2756 typedef _CharT char_type;
2757 typedef basic_string<char_type> string_type;
2758
2759 _LIBCPP_ALWAYS_INLINE __money_get() {}
2760
2761 static void __gather_info(bool __intl, const locale& __loc,
2762 money_base::pattern& __pat, char_type& __dp,
2763 char_type& __ts, string& __grp,
2764 string_type& __sym, string_type& __psn,
2765 string_type& __nsn, int& __fd);
2766};
2767
2768template <class _CharT>
2769void
2770__money_get<_CharT>::__gather_info(bool __intl, const locale& __loc,
2771 money_base::pattern& __pat, char_type& __dp,
2772 char_type& __ts, string& __grp,
2773 string_type& __sym, string_type& __psn,
2774 string_type& __nsn, int& __fd)
2775{
2776 if (__intl)
2777 {
2778 const moneypunct<char_type, true>& __mp =
2779 use_facet<moneypunct<char_type, true> >(__loc);
2780 __pat = __mp.neg_format();
2781 __nsn = __mp.negative_sign();
2782 __psn = __mp.positive_sign();
2783 __dp = __mp.decimal_point();
2784 __ts = __mp.thousands_sep();
2785 __grp = __mp.grouping();
2786 __sym = __mp.curr_symbol();
2787 __fd = __mp.frac_digits();
2788 }
2789 else
2790 {
2791 const moneypunct<char_type, false>& __mp =
2792 use_facet<moneypunct<char_type, false> >(__loc);
2793 __pat = __mp.neg_format();
2794 __nsn = __mp.negative_sign();
2795 __psn = __mp.positive_sign();
2796 __dp = __mp.decimal_point();
2797 __ts = __mp.thousands_sep();
2798 __grp = __mp.grouping();
2799 __sym = __mp.curr_symbol();
2800 __fd = __mp.frac_digits();
2801 }
2802}
2803
2804extern template class __money_get<char>;
2805extern template class __money_get<wchar_t>;
2806
2807template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00002808class _LIBCPP_VISIBLE money_get
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002809 : public locale::facet,
2810 private __money_get<_CharT>
2811{
2812public:
2813 typedef _CharT char_type;
2814 typedef _InputIterator iter_type;
2815 typedef basic_string<char_type> string_type;
2816
2817 _LIBCPP_ALWAYS_INLINE
2818 explicit money_get(size_t __refs = 0)
2819 : locale::facet(__refs) {}
2820
2821 _LIBCPP_ALWAYS_INLINE
2822 iter_type get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob,
2823 ios_base::iostate& __err, long double& __v) const
2824 {
2825 return do_get(__b, __e, __intl, __iob, __err, __v);
2826 }
2827
2828 _LIBCPP_ALWAYS_INLINE
2829 iter_type get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob,
2830 ios_base::iostate& __err, string_type& __v) const
2831 {
2832 return do_get(__b, __e, __intl, __iob, __err, __v);
2833 }
2834
2835 static locale::id id;
2836
2837protected:
2838
Howard Hinnant82894812010-09-22 16:48:34 +00002839 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002840 ~money_get() {}
Howard Hinnant324bb032010-08-22 00:02:43 +00002841
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002842 virtual iter_type do_get(iter_type __b, iter_type __e, bool __intl,
2843 ios_base& __iob, ios_base::iostate& __err,
2844 long double& __v) const;
2845 virtual iter_type do_get(iter_type __b, iter_type __e, bool __intl,
2846 ios_base& __iob, ios_base::iostate& __err,
2847 string_type& __v) const;
2848
2849private:
2850 static bool __do_get(iter_type& __b, iter_type __e,
2851 bool __intl, const locale& __loc,
2852 ios_base::fmtflags __flags, ios_base::iostate& __err,
2853 bool& __neg, const ctype<char_type>& __ct,
2854 unique_ptr<char_type, void(*)(void*)>& __wb,
2855 char_type*& __wn, char_type* __we);
2856};
2857
2858template <class _CharT, class _InputIterator>
2859locale::id
2860money_get<_CharT, _InputIterator>::id;
2861
2862void __do_nothing(void*);
2863
2864template <class _Tp>
2865_LIBCPP_HIDDEN
2866void
2867__double_or_nothing(unique_ptr<_Tp, void(*)(void*)>& __b, _Tp*& __n, _Tp*& __e)
2868{
2869 bool __owns = __b.get_deleter() != __do_nothing;
2870 size_t __cur_cap = (__e-__b.get()) * sizeof(_Tp);
2871 size_t __new_cap = __cur_cap < numeric_limits<size_t>::max() / 2 ?
2872 2 * __cur_cap : numeric_limits<size_t>::max();
2873 size_t __n_off = __n - __b.get();
2874 _Tp* __t = (_Tp*)realloc(__owns ? __b.get() : 0, __new_cap);
2875 if (__t == 0)
2876 __throw_bad_alloc();
2877 if (__owns)
2878 __b.release();
2879 __b = unique_ptr<_Tp, void(*)(void*)>(__t, free);
2880 __new_cap /= sizeof(_Tp);
2881 __n = __b.get() + __n_off;
2882 __e = __b.get() + __new_cap;
2883}
2884
2885// true == success
2886template <class _CharT, class _InputIterator>
2887bool
2888money_get<_CharT, _InputIterator>::__do_get(iter_type& __b, iter_type __e,
2889 bool __intl, const locale& __loc,
2890 ios_base::fmtflags __flags,
2891 ios_base::iostate& __err,
2892 bool& __neg,
2893 const ctype<char_type>& __ct,
2894 unique_ptr<char_type, void(*)(void*)>& __wb,
2895 char_type*& __wn, char_type* __we)
2896{
2897 const unsigned __bz = 100;
2898 unsigned __gbuf[__bz];
2899 unique_ptr<unsigned, void(*)(void*)> __gb(__gbuf, __do_nothing);
2900 unsigned* __gn = __gb.get();
2901 unsigned* __ge = __gn + __bz;
2902 money_base::pattern __pat;
2903 char_type __dp;
2904 char_type __ts;
2905 string __grp;
2906 string_type __sym;
2907 string_type __psn;
2908 string_type __nsn;
2909 int __fd;
2910 __money_get<_CharT>::__gather_info(__intl, __loc, __pat, __dp, __ts, __grp,
2911 __sym, __psn, __nsn, __fd);
2912 const string_type* __trailing_sign = 0;
2913 __wn = __wb.get();
2914 for (unsigned __p = 0; __p < 4 && __b != __e; ++__p)
2915 {
2916 switch (__pat.field[__p])
2917 {
2918 case money_base::space:
2919 if (__p != 3)
2920 {
2921 if (__ct.is(ctype_base::space, *__b))
2922 ++__b;
2923 else
2924 {
2925 __err |= ios_base::failbit;
2926 return false;
2927 }
2928 }
Howard Hinnant324bb032010-08-22 00:02:43 +00002929 // drop through
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002930 case money_base::none:
2931 if (__p != 3)
2932 {
2933 while (__b != __e && __ct.is(ctype_base::space, *__b))
2934 ++__b;
2935 }
2936 break;
2937 case money_base::sign:
2938 if (__psn.size() + __nsn.size() > 0)
2939 {
2940 if (__psn.size() == 0 || __nsn.size() == 0)
2941 { // sign is optional
2942 if (__psn.size() > 0)
2943 { // __nsn.size() == 0
2944 if (*__b == __psn[0])
2945 {
2946 ++__b;
2947 if (__psn.size() > 1)
2948 __trailing_sign = &__psn;
2949 }
2950 else
2951 __neg = true;
2952 }
2953 else if (*__b == __nsn[0]) // __nsn.size() > 0 && __psn.size() == 0
2954 {
2955 ++__b;
2956 __neg = true;
2957 if (__nsn.size() > 1)
2958 __trailing_sign = &__nsn;
2959 }
2960 }
2961 else // sign is required
2962 {
2963 if (*__b == __psn[0])
2964 {
2965 ++__b;
2966 if (__psn.size() > 1)
2967 __trailing_sign = &__psn;
2968 }
2969 else if (*__b == __nsn[0])
2970 {
2971 ++__b;
2972 __neg = true;
2973 if (__nsn.size() > 1)
2974 __trailing_sign = &__nsn;
2975 }
2976 else
2977 {
2978 __err |= ios_base::failbit;
2979 return false;
2980 }
2981 }
2982 }
2983 break;
2984 case money_base::symbol:
2985 {
2986 bool __more_needed = __trailing_sign ||
2987 (__p < 2) ||
2988 (__p == 2 && __pat.field[3] != static_cast<char>(money_base::none));
2989 bool __sb = __flags & ios_base::showbase;
2990 if (__sb || __more_needed)
2991 {
2992 ios_base::iostate __et = ios_base::goodbit;
2993 string_type* __k = __scan_keyword(__b, __e, &__sym, &__sym+1,
2994 __ct, __et);
2995 if (__sb && __k != &__sym)
2996 {
2997 __err |= ios_base::failbit;
2998 return false;
2999 }
3000 }
3001 }
3002 break;
3003 case money_base::value:
3004 {
3005 unsigned __ng = 0;
3006 for (; __b != __e; ++__b)
3007 {
3008 char_type __c = *__b;
3009 if (__ct.is(ctype_base::digit, __c))
3010 {
3011 if (__wn == __we)
3012 __double_or_nothing(__wb, __wn, __we);
3013 *__wn++ = __c;
3014 ++__ng;
3015 }
3016 else if (__grp.size() > 0 && __ng > 0 && __c == __ts)
3017 {
3018 if (__gn == __ge)
3019 __double_or_nothing(__gb, __gn, __ge);
3020 *__gn++ = __ng;
3021 __ng = 0;
3022 }
3023 else
3024 break;
3025 }
3026 if (__gb.get() != __gn && __ng > 0)
3027 {
3028 if (__gn == __ge)
3029 __double_or_nothing(__gb, __gn, __ge);
3030 *__gn++ = __ng;
3031 }
3032 if (__fd > 0)
3033 {
3034 if (__b == __e || *__b != __dp)
3035 {
3036 __err |= ios_base::failbit;
3037 return false;
3038 }
3039 for (++__b; __fd > 0; --__fd, ++__b)
3040 {
3041 if (__b == __e || !__ct.is(ctype_base::digit, *__b))
3042 {
3043 __err |= ios_base::failbit;
3044 return false;
3045 }
3046 if (__wn == __we)
3047 __double_or_nothing(__wb, __wn, __we);
3048 *__wn++ = *__b;
3049 }
3050 }
3051 if (__wn == __wb.get())
3052 {
3053 __err |= ios_base::failbit;
3054 return false;
3055 }
3056 }
3057 break;
3058 }
3059 }
3060 if (__trailing_sign)
3061 {
3062 for (unsigned __i = 1; __i < __trailing_sign->size(); ++__i, ++__b)
3063 {
3064 if (__b == __e || *__b != (*__trailing_sign)[__i])
3065 {
3066 __err |= ios_base::failbit;
3067 return false;
3068 }
3069 }
3070 }
3071 if (__gb.get() != __gn)
3072 {
3073 ios_base::iostate __et = ios_base::goodbit;
3074 __check_grouping(__grp, __gb.get(), __gn, __et);
3075 if (__et)
3076 {
3077 __err |= ios_base::failbit;
3078 return false;
3079 }
3080 }
3081 return true;
3082}
3083
3084template <class _CharT, class _InputIterator>
3085_InputIterator
3086money_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
3087 bool __intl, ios_base& __iob,
3088 ios_base::iostate& __err,
3089 long double& __v) const
3090{
3091 const unsigned __bz = 100;
3092 char_type __wbuf[__bz];
3093 unique_ptr<char_type, void(*)(void*)> __wb(__wbuf, __do_nothing);
3094 char_type* __wn;
3095 char_type* __we = __wbuf + __bz;
3096 locale __loc = __iob.getloc();
3097 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3098 bool __neg = false;
3099 if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct,
3100 __wb, __wn, __we))
3101 {
3102 const char __src[] = "0123456789";
3103 char_type __atoms[sizeof(__src)-1];
3104 __ct.widen(__src, __src + (sizeof(__src)-1), __atoms);
3105 char __nbuf[__bz];
3106 char* __nc = __nbuf;
3107 unique_ptr<char, void(*)(void*)> __h(0, free);
3108 if (__wn - __wb.get() > __bz-2)
3109 {
3110 __h.reset((char*)malloc(__wn - __wb.get() + 2));
3111 if (__h.get() == 0)
3112 __throw_bad_alloc();
3113 __nc = __h.get();
3114 }
3115 if (__neg)
3116 *__nc++ = '-';
3117 for (const char_type* __w = __wb.get(); __w < __wn; ++__w, ++__nc)
3118 *__nc = __src[find(__atoms, __atoms+sizeof(__atoms), *__w) - __atoms];
3119 *__nc = char();
3120 if (sscanf(__nbuf, "%Lf", &__v) != 1)
3121 __throw_runtime_error("money_get error");
3122 }
3123 if (__b == __e)
3124 __err |= ios_base::eofbit;
3125 return __b;
3126}
3127
3128template <class _CharT, class _InputIterator>
3129_InputIterator
3130money_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
3131 bool __intl, ios_base& __iob,
3132 ios_base::iostate& __err,
3133 string_type& __v) const
3134{
3135 const unsigned __bz = 100;
3136 char_type __wbuf[__bz];
3137 unique_ptr<char_type, void(*)(void*)> __wb(__wbuf, __do_nothing);
3138 char_type* __wn;
3139 char_type* __we = __wbuf + __bz;
3140 locale __loc = __iob.getloc();
3141 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3142 bool __neg = false;
3143 if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct,
3144 __wb, __wn, __we))
3145 {
3146 __v.clear();
3147 if (__neg)
3148 __v.push_back(__ct.widen('-'));
3149 char_type __z = __ct.widen('0');
3150 char_type* __w;
3151 for (__w = __wb.get(); __w < __wn-1; ++__w)
3152 if (*__w != __z)
3153 break;
3154 __v.append(__w, __wn);
3155 }
3156 if (__b == __e)
3157 __err |= ios_base::eofbit;
3158 return __b;
3159}
3160
3161extern template class money_get<char>;
3162extern template class money_get<wchar_t>;
3163
3164// money_put
3165
3166template <class _CharT>
3167class __money_put
3168{
3169protected:
3170 typedef _CharT char_type;
3171 typedef basic_string<char_type> string_type;
3172
3173 _LIBCPP_ALWAYS_INLINE __money_put() {}
3174
3175 static void __gather_info(bool __intl, bool __neg, const locale& __loc,
3176 money_base::pattern& __pat, char_type& __dp,
3177 char_type& __ts, string& __grp,
3178 string_type& __sym, string_type& __sn,
3179 int& __fd);
3180 static void __format(char_type* __mb, char_type*& __mi, char_type*& __me,
3181 ios_base::fmtflags __flags,
3182 const char_type* __db, const char_type* __de,
3183 const ctype<char_type>& __ct, bool __neg,
3184 const money_base::pattern& __pat, char_type __dp,
3185 char_type __ts, const string& __grp,
3186 const string_type& __sym, const string_type& __sn,
3187 int __fd);
3188};
3189
3190template <class _CharT>
3191void
3192__money_put<_CharT>::__gather_info(bool __intl, bool __neg, const locale& __loc,
3193 money_base::pattern& __pat, char_type& __dp,
3194 char_type& __ts, string& __grp,
3195 string_type& __sym, string_type& __sn,
3196 int& __fd)
3197{
3198 if (__intl)
3199 {
3200 const moneypunct<char_type, true>& __mp =
3201 use_facet<moneypunct<char_type, true> >(__loc);
3202 if (__neg)
3203 {
3204 __pat = __mp.neg_format();
3205 __sn = __mp.negative_sign();
3206 }
3207 else
3208 {
3209 __pat = __mp.pos_format();
3210 __sn = __mp.positive_sign();
3211 }
3212 __dp = __mp.decimal_point();
3213 __ts = __mp.thousands_sep();
3214 __grp = __mp.grouping();
3215 __sym = __mp.curr_symbol();
3216 __fd = __mp.frac_digits();
3217 }
3218 else
3219 {
3220 const moneypunct<char_type, false>& __mp =
3221 use_facet<moneypunct<char_type, false> >(__loc);
3222 if (__neg)
3223 {
3224 __pat = __mp.neg_format();
3225 __sn = __mp.negative_sign();
3226 }
3227 else
3228 {
3229 __pat = __mp.pos_format();
3230 __sn = __mp.positive_sign();
3231 }
3232 __dp = __mp.decimal_point();
3233 __ts = __mp.thousands_sep();
3234 __grp = __mp.grouping();
3235 __sym = __mp.curr_symbol();
3236 __fd = __mp.frac_digits();
3237 }
3238}
3239
3240template <class _CharT>
3241void
3242__money_put<_CharT>::__format(char_type* __mb, char_type*& __mi, char_type*& __me,
3243 ios_base::fmtflags __flags,
3244 const char_type* __db, const char_type* __de,
3245 const ctype<char_type>& __ct, bool __neg,
3246 const money_base::pattern& __pat, char_type __dp,
3247 char_type __ts, const string& __grp,
3248 const string_type& __sym, const string_type& __sn,
3249 int __fd)
3250{
3251 __me = __mb;
3252 for (unsigned __p = 0; __p < 4; ++__p)
3253 {
3254 switch (__pat.field[__p])
3255 {
3256 case money_base::none:
3257 __mi = __me;
3258 break;
3259 case money_base::space:
3260 __mi = __me;
3261 *__me++ = __ct.widen(' ');
3262 break;
3263 case money_base::sign:
3264 if (!__sn.empty())
3265 *__me++ = __sn[0];
3266 break;
3267 case money_base::symbol:
3268 if (!__sym.empty() && (__flags & ios_base::showbase))
3269 __me = copy(__sym.begin(), __sym.end(), __me);
3270 break;
3271 case money_base::value:
3272 {
3273 // remember start of value so we can reverse it
3274 char_type* __t = __me;
3275 // find beginning of digits
3276 if (__neg)
3277 ++__db;
3278 // find end of digits
3279 const char_type* __d;
3280 for (__d = __db; __d < __de; ++__d)
3281 if (!__ct.is(ctype_base::digit, *__d))
3282 break;
3283 // print fractional part
3284 if (__fd > 0)
3285 {
3286 int __f;
3287 for (__f = __fd; __d > __db && __f > 0; --__f)
3288 *__me++ = *--__d;
3289 char_type __z = __f > 0 ? __ct.widen('0') : char_type();
3290 for (; __f > 0; --__f)
3291 *__me++ = __z;
3292 *__me++ = __dp;
3293 }
3294 // print units part
3295 if (__d == __db)
3296 {
3297 *__me++ = __ct.widen('0');
3298 }
3299 else
3300 {
3301 unsigned __ng = 0;
3302 unsigned __ig = 0;
3303 unsigned __gl = __grp.empty() ? numeric_limits<unsigned>::max()
3304 : static_cast<unsigned>(__grp[__ig]);
3305 while (__d != __db)
3306 {
3307 if (__ng == __gl)
3308 {
3309 *__me++ = __ts;
3310 __ng = 0;
3311 if (++__ig < __grp.size())
3312 __gl = __grp[__ig] == numeric_limits<char>::max() ?
3313 numeric_limits<unsigned>::max() :
3314 static_cast<unsigned>(__grp[__ig]);
3315 }
3316 *__me++ = *--__d;
3317 ++__ng;
3318 }
3319 }
3320 // reverse it
3321 reverse(__t, __me);
3322 }
3323 break;
3324 }
3325 }
3326 // print rest of sign, if any
3327 if (__sn.size() > 1)
3328 __me = copy(__sn.begin()+1, __sn.end(), __me);
3329 // set alignment
3330 if ((__flags & ios_base::adjustfield) == ios_base::left)
3331 __mi = __me;
3332 else if ((__flags & ios_base::adjustfield) != ios_base::internal)
3333 __mi = __mb;
3334}
3335
3336extern template class __money_put<char>;
3337extern template class __money_put<wchar_t>;
3338
3339template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00003340class _LIBCPP_VISIBLE money_put
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003341 : public locale::facet,
3342 private __money_put<_CharT>
3343{
3344public:
3345 typedef _CharT char_type;
3346 typedef _OutputIterator iter_type;
3347 typedef basic_string<char_type> string_type;
3348
3349 _LIBCPP_ALWAYS_INLINE
3350 explicit money_put(size_t __refs = 0)
3351 : locale::facet(__refs) {}
3352
3353 _LIBCPP_ALWAYS_INLINE
3354 iter_type put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl,
3355 long double __units) const
3356 {
3357 return do_put(__s, __intl, __iob, __fl, __units);
3358 }
3359
3360 _LIBCPP_ALWAYS_INLINE
3361 iter_type put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl,
3362 const string_type& __digits) const
3363 {
3364 return do_put(__s, __intl, __iob, __fl, __digits);
3365 }
3366
3367 static locale::id id;
3368
3369protected:
Howard Hinnant82894812010-09-22 16:48:34 +00003370 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003371 ~money_put() {}
3372
3373 virtual iter_type do_put(iter_type __s, bool __intl, ios_base& __iob,
3374 char_type __fl, long double __units) const;
3375 virtual iter_type do_put(iter_type __s, bool __intl, ios_base& __iob,
3376 char_type __fl, const string_type& __digits) const;
3377};
3378
3379template <class _CharT, class _OutputIterator>
3380locale::id
3381money_put<_CharT, _OutputIterator>::id;
3382
3383template <class _CharT, class _OutputIterator>
3384_OutputIterator
3385money_put<_CharT, _OutputIterator>::do_put(iter_type __s, bool __intl,
3386 ios_base& __iob, char_type __fl,
3387 long double __units) const
3388{
3389 // convert to char
3390 const size_t __bs = 100;
3391 char __buf[__bs];
3392 char* __bb = __buf;
3393 char_type __digits[__bs];
3394 char_type* __db = __digits;
3395 size_t __n = snprintf(__bb, __bs, "%.0Lf", __units);
3396 unique_ptr<char, void(*)(void*)> __hn(0, free);
3397 unique_ptr<char_type, void(*)(void*)> __hd(0, free);
3398 // secure memory for digit storage
3399 if (__n > __bs-1)
3400 {
Howard Hinnantadff4892010-05-24 17:49:41 +00003401 __n = __nolocale_asprintf(&__bb, "%.0Lf", __units);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003402 if (__bb == 0)
3403 __throw_bad_alloc();
3404 __hn.reset(__bb);
3405 __hd.reset((char_type*)malloc(__n * sizeof(char_type)));
3406 if (__hd == 0)
3407 __throw_bad_alloc();
3408 __db = __hd.get();
3409 }
3410 // gather info
3411 locale __loc = __iob.getloc();
3412 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3413 __ct.widen(__bb, __bb + __n, __db);
3414 bool __neg = __n > 0 && __bb[0] == '-';
3415 money_base::pattern __pat;
3416 char_type __dp;
3417 char_type __ts;
3418 string __grp;
3419 string_type __sym;
3420 string_type __sn;
3421 int __fd;
3422 this->__gather_info(__intl, __neg, __loc, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3423 // secure memory for formatting
3424 char_type __mbuf[__bs];
3425 char_type* __mb = __mbuf;
3426 unique_ptr<char_type, void(*)(void*)> __hw(0, free);
3427 size_t __exn = static_cast<int>(__n) > __fd ?
3428 (__n - __fd) * 2 + __sn.size() + __sym.size() + __fd + 1
3429 : __sn.size() + __sym.size() + __fd + 2;
3430 if (__exn > __bs)
3431 {
3432 __hw.reset((char_type*)malloc(__exn * sizeof(char_type)));
3433 __mb = __hw.get();
3434 if (__mb == 0)
3435 __throw_bad_alloc();
3436 }
3437 // format
3438 char_type* __mi;
3439 char_type* __me;
3440 this->__format(__mb, __mi, __me, __iob.flags(),
3441 __db, __db + __n, __ct,
3442 __neg, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3443 return __pad_and_output(__s, __mb, __mi, __me, __iob, __fl);
3444}
3445
3446template <class _CharT, class _OutputIterator>
3447_OutputIterator
3448money_put<_CharT, _OutputIterator>::do_put(iter_type __s, bool __intl,
3449 ios_base& __iob, char_type __fl,
3450 const string_type& __digits) const
3451{
3452 // gather info
3453 locale __loc = __iob.getloc();
3454 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3455 bool __neg = __digits.size() > 0 && __digits[0] == __ct.widen('-');
3456 money_base::pattern __pat;
3457 char_type __dp;
3458 char_type __ts;
3459 string __grp;
3460 string_type __sym;
3461 string_type __sn;
3462 int __fd;
3463 this->__gather_info(__intl, __neg, __loc, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3464 // secure memory for formatting
3465 char_type __mbuf[100];
3466 char_type* __mb = __mbuf;
3467 unique_ptr<char_type, void(*)(void*)> __h(0, free);
3468 size_t __exn = __digits.size() > __fd ?
3469 (__digits.size() - __fd) * 2 + __sn.size() + __sym.size() + __fd + 1
3470 : __sn.size() + __sym.size() + __fd + 2;
3471 if (__exn > 100)
3472 {
3473 __h.reset((char_type*)malloc(__exn * sizeof(char_type)));
3474 __mb = __h.get();
3475 if (__mb == 0)
3476 __throw_bad_alloc();
3477 }
3478 // format
3479 char_type* __mi;
3480 char_type* __me;
3481 this->__format(__mb, __mi, __me, __iob.flags(),
3482 __digits.data(), __digits.data() + __digits.size(), __ct,
3483 __neg, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3484 return __pad_and_output(__s, __mb, __mi, __me, __iob, __fl);
3485}
3486
3487extern template class money_put<char>;
3488extern template class money_put<wchar_t>;
3489
3490// messages
3491
Howard Hinnant82894812010-09-22 16:48:34 +00003492class _LIBCPP_VISIBLE messages_base
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003493{
3494public:
3495 typedef nl_catd catalog;
3496
3497 _LIBCPP_ALWAYS_INLINE messages_base() {}
3498};
3499
3500template <class _CharT>
Howard Hinnant82894812010-09-22 16:48:34 +00003501class _LIBCPP_VISIBLE messages
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003502 : public locale::facet,
3503 public messages_base
3504{
3505public:
3506 typedef _CharT char_type;
3507 typedef basic_string<_CharT> string_type;
3508
3509 _LIBCPP_ALWAYS_INLINE
3510 explicit messages(size_t __refs = 0)
3511 : locale::facet(__refs) {}
3512
3513 _LIBCPP_ALWAYS_INLINE
3514 catalog open(const basic_string<char>& __nm, const locale& __loc) const
3515 {
3516 return do_open(__nm, __loc);
3517 }
3518
3519 _LIBCPP_ALWAYS_INLINE
3520 string_type get(catalog __c, int __set, int __msgid,
3521 const string_type& __dflt) const
3522 {
3523 return do_get(__c, __set, __msgid, __dflt);
3524 }
3525
3526 _LIBCPP_ALWAYS_INLINE
3527 void close(catalog __c) const
3528 {
3529 do_close(__c);
3530 }
3531
3532 static locale::id id;
3533
3534protected:
Howard Hinnant82894812010-09-22 16:48:34 +00003535 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003536 ~messages() {}
3537
3538 virtual catalog do_open(const basic_string<char>&, const locale&) const;
3539 virtual string_type do_get(catalog, int __set, int __msgid,
3540 const string_type& __dflt) const;
3541 virtual void do_close(catalog) const;
3542};
3543
3544template <class _CharT>
3545locale::id
3546messages<_CharT>::id;
3547
3548template <class _CharT>
3549typename messages<_CharT>::catalog
3550messages<_CharT>::do_open(const basic_string<char>& __nm, const locale&) const
3551{
3552 return catopen(__nm.c_str(), NL_CAT_LOCALE);
3553}
3554
3555template <class _CharT>
3556typename messages<_CharT>::string_type
3557messages<_CharT>::do_get(catalog __c, int __set, int __msgid,
3558 const string_type& __dflt) const
3559{
3560 string __ndflt;
3561 __narrow_to_utf8<sizeof(char_type)*__CHAR_BIT__>()(back_inserter(__ndflt),
3562 __dflt.c_str(),
3563 __dflt.c_str() + __dflt.size());
3564 char* __n = catgets(__c, __set, __msgid, __ndflt.c_str());
3565 string_type __w;
3566 __widen_from_utf8<sizeof(char_type)*__CHAR_BIT__>()(back_inserter(__w),
3567 __n, __n + strlen(__n));
3568 return __w;
3569}
3570
3571template <class _CharT>
3572void
3573messages<_CharT>::do_close(catalog __c) const
3574{
3575 catclose(__c);
3576}
3577
3578extern template class messages<char>;
3579extern template class messages<wchar_t>;
3580
3581template <class _CharT>
Howard Hinnant82894812010-09-22 16:48:34 +00003582class _LIBCPP_VISIBLE messages_byname
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003583 : public messages<_CharT>
3584{
3585public:
3586 typedef messages_base::catalog catalog;
3587 typedef basic_string<_CharT> string_type;
3588
3589 _LIBCPP_ALWAYS_INLINE
3590 explicit messages_byname(const char*, size_t __refs = 0)
3591 : messages<_CharT>(__refs) {}
3592
3593 _LIBCPP_ALWAYS_INLINE
3594 explicit messages_byname(const string&, size_t __refs = 0)
3595 : messages<_CharT>(__refs) {}
3596
3597protected:
Howard Hinnant82894812010-09-22 16:48:34 +00003598 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003599 ~messages_byname() {}
3600};
3601
3602extern template class messages_byname<char>;
3603extern template class messages_byname<wchar_t>;
3604
Howard Hinnantd23b4642010-05-31 20:58:54 +00003605template<class _Codecvt, class _Elem = wchar_t,
3606 class _Wide_alloc = allocator<_Elem>,
3607 class _Byte_alloc = allocator<char> >
Howard Hinnant82894812010-09-22 16:48:34 +00003608class _LIBCPP_VISIBLE wstring_convert
Howard Hinnantd23b4642010-05-31 20:58:54 +00003609{
3610public:
3611 typedef basic_string<char, char_traits<char>, _Byte_alloc> byte_string;
3612 typedef basic_string<_Elem, char_traits<_Elem>, _Wide_alloc> wide_string;
3613 typedef typename _Codecvt::state_type state_type;
3614 typedef typename wide_string::traits_type::int_type int_type;
3615
3616private:
3617 byte_string __byte_err_string_;
3618 wide_string __wide_err_string_;
3619 _Codecvt* __cvtptr_;
3620 state_type __cvtstate_;
3621 size_t __cvtcount_;
3622
3623 wstring_convert(const wstring_convert& __wc);
3624 wstring_convert& operator=(const wstring_convert& __wc);
3625public:
3626 wstring_convert(_Codecvt* __pcvt = new _Codecvt);
3627 wstring_convert(_Codecvt* __pcvt, state_type __state);
3628 wstring_convert(const byte_string& __byte_err,
3629 const wide_string& __wide_err = wide_string());
Howard Hinnant73d21a42010-09-04 23:28:19 +00003630#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantd23b4642010-05-31 20:58:54 +00003631 wstring_convert(wstring_convert&& __wc);
3632#endif
3633 ~wstring_convert();
3634
Howard Hinnant82894812010-09-22 16:48:34 +00003635 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003636 wide_string from_bytes(char __byte)
3637 {return from_bytes(&__byte, &__byte+1);}
Howard Hinnant82894812010-09-22 16:48:34 +00003638 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003639 wide_string from_bytes(const char* __ptr)
3640 {return from_bytes(__ptr, __ptr + char_traits<char>::length(__ptr));}
Howard Hinnant82894812010-09-22 16:48:34 +00003641 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003642 wide_string from_bytes(const byte_string& __str)
3643 {return from_bytes(__str.data(), __str.data() + __str.size());}
3644 wide_string from_bytes(const char* __first, const char* __last);
3645
Howard Hinnant82894812010-09-22 16:48:34 +00003646 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003647 byte_string to_bytes(_Elem __wchar)
3648 {return to_bytes(&__wchar, &__wchar+1);}
Howard Hinnant82894812010-09-22 16:48:34 +00003649 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003650 byte_string to_bytes(const _Elem* __wptr)
3651 {return to_bytes(__wptr, __wptr + char_traits<_Elem>::length(__wptr));}
Howard Hinnant82894812010-09-22 16:48:34 +00003652 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003653 byte_string to_bytes(const wide_string& __wstr)
3654 {return to_bytes(__wstr.data(), __wstr.data() + __wstr.size());}
3655 byte_string to_bytes(const _Elem* __first, const _Elem* __last);
3656
Howard Hinnant82894812010-09-22 16:48:34 +00003657 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003658 size_t converted() const {return __cvtcount_;}
Howard Hinnant82894812010-09-22 16:48:34 +00003659 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003660 state_type state() const {return __cvtstate_;}
3661};
3662
3663template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Howard Hinnant82894812010-09-22 16:48:34 +00003664inline _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003665wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3666 wstring_convert(_Codecvt* __pcvt)
3667 : __cvtptr_(__pcvt), __cvtstate_(), __cvtcount_(0)
3668{
3669}
3670
3671template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Howard Hinnant82894812010-09-22 16:48:34 +00003672inline _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003673wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3674 wstring_convert(_Codecvt* __pcvt, state_type __state)
3675 : __cvtptr_(__pcvt), __cvtstate_(__state), __cvtcount_(0)
3676{
3677}
3678
3679template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3680wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3681 wstring_convert(const byte_string& __byte_err, const wide_string& __wide_err)
3682 : __byte_err_string_(__byte_err), __wide_err_string_(__wide_err),
3683 __cvtstate_(), __cvtcount_(0)
3684{
3685 __cvtptr_ = new _Codecvt;
3686}
3687
Howard Hinnant73d21a42010-09-04 23:28:19 +00003688#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantd23b4642010-05-31 20:58:54 +00003689
3690template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Howard Hinnant82894812010-09-22 16:48:34 +00003691inline _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003692wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3693 wstring_convert(wstring_convert&& __wc)
3694 : __byte_err_string_(_STD::move(__wc.__byte_err_string_)),
3695 __wide_err_string_(_STD::move(__wc.__wide_err_string_)),
3696 __cvtptr_(__wc.__cvtptr_),
3697 __cvtstate_(__wc.__cvtstate_), __cvtcount_(__wc.__cvtstate_)
3698{
3699 __wc.__cvtptr_ = nullptr;
3700}
3701
Howard Hinnantbfd55302010-09-04 23:46:48 +00003702#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantd23b4642010-05-31 20:58:54 +00003703
3704template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3705wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::~wstring_convert()
3706{
3707 delete __cvtptr_;
3708}
3709
3710template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3711typename wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::wide_string
3712wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3713 from_bytes(const char* __frm, const char* __frm_end)
3714{
3715 __cvtcount_ = 0;
3716 if (__cvtptr_ != nullptr)
3717 {
3718 wide_string __ws(2*(__frm_end - __frm), _Elem());
3719 __ws.resize(__ws.capacity());
3720 codecvt_base::result __r = codecvt_base::ok;
3721 state_type __st = __cvtstate_;
3722 if (__frm != __frm_end)
3723 {
3724 _Elem* __to = &__ws[0];
3725 _Elem* __to_end = __to + __ws.size();
3726 const char* __frm_nxt;
3727 do
3728 {
3729 _Elem* __to_nxt;
3730 __r = __cvtptr_->in(__st, __frm, __frm_end, __frm_nxt,
3731 __to, __to_end, __to_nxt);
3732 __cvtcount_ += __frm_nxt - __frm;
3733 if (__frm_nxt == __frm)
3734 {
3735 __r = codecvt_base::error;
3736 }
3737 else if (__r == codecvt_base::noconv)
3738 {
3739 __ws.resize(__to - &__ws[0]);
3740 // This only gets executed if _Elem is char
3741 __ws.append((const _Elem*)__frm, (const _Elem*)__frm_end);
3742 __frm = __frm_nxt;
3743 __r = codecvt_base::ok;
3744 }
3745 else if (__r == codecvt_base::ok)
3746 {
3747 __ws.resize(__to_nxt - &__ws[0]);
3748 __frm = __frm_nxt;
3749 }
3750 else if (__r == codecvt_base::partial)
3751 {
3752 ptrdiff_t __s = __to_nxt - &__ws[0];
3753 __ws.resize(2 * __s);
3754 __to = &__ws[0] + __s;
3755 __to_end = &__ws[0] + __ws.size();
3756 __frm = __frm_nxt;
3757 }
3758 } while (__r == codecvt_base::partial && __frm_nxt < __frm_end);
3759 }
3760 if (__r == codecvt_base::ok)
3761 return __ws;
3762 }
Howard Hinnantd4444702010-08-11 17:04:31 +00003763#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00003764 if (__wide_err_string_.empty())
3765 throw range_error("wstring_convert: from_bytes error");
Howard Hinnant324bb032010-08-22 00:02:43 +00003766#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00003767 return __wide_err_string_;
3768}
3769
3770template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3771typename wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::byte_string
3772wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3773 to_bytes(const _Elem* __frm, const _Elem* __frm_end)
3774{
3775 __cvtcount_ = 0;
3776 if (__cvtptr_ != nullptr)
3777 {
3778 byte_string __bs(2*(__frm_end - __frm), char());
3779 __bs.resize(__bs.capacity());
3780 codecvt_base::result __r = codecvt_base::ok;
3781 state_type __st = __cvtstate_;
3782 if (__frm != __frm_end)
3783 {
3784 char* __to = &__bs[0];
3785 char* __to_end = __to + __bs.size();
3786 const _Elem* __frm_nxt;
3787 do
3788 {
3789 char* __to_nxt;
3790 __r = __cvtptr_->out(__st, __frm, __frm_end, __frm_nxt,
3791 __to, __to_end, __to_nxt);
3792 __cvtcount_ += __frm_nxt - __frm;
3793 if (__frm_nxt == __frm)
3794 {
3795 __r = codecvt_base::error;
3796 }
3797 else if (__r == codecvt_base::noconv)
3798 {
3799 __bs.resize(__to - &__bs[0]);
3800 // This only gets executed if _Elem is char
3801 __bs.append((const char*)__frm, (const char*)__frm_end);
3802 __frm = __frm_nxt;
3803 __r = codecvt_base::ok;
3804 }
3805 else if (__r == codecvt_base::ok)
3806 {
3807 __bs.resize(__to_nxt - &__bs[0]);
3808 __frm = __frm_nxt;
3809 }
3810 else if (__r == codecvt_base::partial)
3811 {
3812 ptrdiff_t __s = __to_nxt - &__bs[0];
3813 __bs.resize(2 * __s);
3814 __to = &__bs[0] + __s;
3815 __to_end = &__bs[0] + __bs.size();
3816 __frm = __frm_nxt;
3817 }
3818 } while (__r == codecvt_base::partial && __frm_nxt < __frm_end);
3819 }
3820 if (__r == codecvt_base::ok)
3821 {
3822 size_t __s = __bs.size();
3823 __bs.resize(__bs.capacity());
3824 char* __to = &__bs[0] + __s;
3825 char* __to_end = __to + __bs.size();
3826 do
3827 {
3828 char* __to_nxt;
3829 __r = __cvtptr_->unshift(__st, __to, __to_end, __to_nxt);
3830 if (__r == codecvt_base::noconv)
3831 {
3832 __bs.resize(__to - &__bs[0]);
3833 __r = codecvt_base::ok;
3834 }
3835 else if (__r == codecvt_base::ok)
3836 {
3837 __bs.resize(__to_nxt - &__bs[0]);
3838 }
3839 else if (__r == codecvt_base::partial)
3840 {
3841 ptrdiff_t __s = __to_nxt - &__bs[0];
3842 __bs.resize(2 * __s);
3843 __to = &__bs[0] + __s;
3844 __to_end = &__bs[0] + __bs.size();
3845 }
3846 } while (__r == codecvt_base::partial);
3847 if (__r == codecvt_base::ok)
3848 return __bs;
3849 }
3850 }
Howard Hinnantd4444702010-08-11 17:04:31 +00003851#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00003852 if (__byte_err_string_.empty())
3853 throw range_error("wstring_convert: to_bytes error");
Howard Hinnant324bb032010-08-22 00:02:43 +00003854#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00003855 return __byte_err_string_;
3856}
3857
3858template <class _Codecvt, class _Elem = wchar_t, class _Tr = char_traits<_Elem> >
Howard Hinnant82894812010-09-22 16:48:34 +00003859class _LIBCPP_VISIBLE wbuffer_convert
Howard Hinnantd23b4642010-05-31 20:58:54 +00003860 : public basic_streambuf<_Elem, _Tr>
3861{
3862public:
3863 // types:
3864 typedef _Elem char_type;
3865 typedef _Tr traits_type;
3866 typedef typename traits_type::int_type int_type;
3867 typedef typename traits_type::pos_type pos_type;
3868 typedef typename traits_type::off_type off_type;
3869 typedef typename _Codecvt::state_type state_type;
3870
3871private:
Howard Hinnant4b53f502010-06-01 20:09:18 +00003872 char* __extbuf_;
3873 const char* __extbufnext_;
3874 const char* __extbufend_;
3875 char __extbuf_min_[8];
3876 size_t __ebs_;
3877 char_type* __intbuf_;
3878 size_t __ibs_;
Howard Hinnantd23b4642010-05-31 20:58:54 +00003879 streambuf* __bufptr_;
Howard Hinnant4b53f502010-06-01 20:09:18 +00003880 _Codecvt* __cv_;
3881 state_type __st_;
3882 ios_base::openmode __cm_;
3883 bool __owns_eb_;
3884 bool __owns_ib_;
3885 bool __always_noconv_;
Howard Hinnantd23b4642010-05-31 20:58:54 +00003886
Howard Hinnant4b53f502010-06-01 20:09:18 +00003887 wbuffer_convert(const wbuffer_convert&);
3888 wbuffer_convert& operator=(const wbuffer_convert&);
Howard Hinnantd23b4642010-05-31 20:58:54 +00003889public:
3890 wbuffer_convert(streambuf* __bytebuf = 0, _Codecvt* __pcvt = new _Codecvt,
Howard Hinnant4b53f502010-06-01 20:09:18 +00003891 state_type __state = state_type());
3892 ~wbuffer_convert();
Howard Hinnantd23b4642010-05-31 20:58:54 +00003893
Howard Hinnant82894812010-09-22 16:48:34 +00003894 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantd23b4642010-05-31 20:58:54 +00003895 streambuf* rdbuf() const {return __bufptr_;}
Howard Hinnant82894812010-09-22 16:48:34 +00003896 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantd23b4642010-05-31 20:58:54 +00003897 streambuf* rdbuf(streambuf* __bytebuf)
3898 {
3899 streambuf* __r = __bufptr_;
3900 __bufptr_ = __bytebuf;
3901 return __r;
3902 }
3903
Howard Hinnant82894812010-09-22 16:48:34 +00003904 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant4b53f502010-06-01 20:09:18 +00003905 state_type state() const {return __st_;}
Howard Hinnantd23b4642010-05-31 20:58:54 +00003906
3907protected:
Howard Hinnant4b53f502010-06-01 20:09:18 +00003908 virtual int_type underflow();
3909 virtual int_type pbackfail(int_type __c = traits_type::eof());
Howard Hinnantd23b4642010-05-31 20:58:54 +00003910 virtual int_type overflow (int_type __c = traits_type::eof());
Howard Hinnant4b53f502010-06-01 20:09:18 +00003911 virtual basic_streambuf<char_type, traits_type>* setbuf(char_type* __s,
3912 streamsize __n);
3913 virtual pos_type seekoff(off_type __off, ios_base::seekdir __way,
3914 ios_base::openmode __wch = ios_base::in | ios_base::out);
3915 virtual pos_type seekpos(pos_type __sp,
3916 ios_base::openmode __wch = ios_base::in | ios_base::out);
3917 virtual int sync();
3918
3919private:
3920 bool __read_mode();
3921 void __write_mode();
3922 wbuffer_convert* __close();
Howard Hinnantd23b4642010-05-31 20:58:54 +00003923};
3924
3925template <class _Codecvt, class _Elem, class _Tr>
Howard Hinnant4b53f502010-06-01 20:09:18 +00003926wbuffer_convert<_Codecvt, _Elem, _Tr>::
3927 wbuffer_convert(streambuf* __bytebuf, _Codecvt* __pcvt, state_type __state)
3928 : __extbuf_(0),
3929 __extbufnext_(0),
3930 __extbufend_(0),
3931 __ebs_(0),
3932 __intbuf_(0),
3933 __ibs_(0),
3934 __bufptr_(__bytebuf),
3935 __cv_(__pcvt),
3936 __st_(__state),
3937 __cm_(0),
3938 __owns_eb_(false),
3939 __owns_ib_(false),
3940 __always_noconv_(__cv_ ? __cv_->always_noconv() : false)
3941{
3942 setbuf(0, 4096);
3943}
3944
3945template <class _Codecvt, class _Elem, class _Tr>
3946wbuffer_convert<_Codecvt, _Elem, _Tr>::~wbuffer_convert()
3947{
3948 __close();
3949 delete __cv_;
3950 if (__owns_eb_)
3951 delete [] __extbuf_;
3952 if (__owns_ib_)
3953 delete [] __intbuf_;
3954}
3955
3956template <class _Codecvt, class _Elem, class _Tr>
3957typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
3958wbuffer_convert<_Codecvt, _Elem, _Tr>::underflow()
3959{
3960 if (__cv_ == 0 || __bufptr_ == 0)
3961 return traits_type::eof();
3962 bool __initial = __read_mode();
3963 char_type __1buf;
3964 if (this->gptr() == 0)
3965 this->setg(&__1buf, &__1buf+1, &__1buf+1);
3966 const size_t __unget_sz = __initial ? 0 : min<size_t>((this->egptr() - this->eback()) / 2, 4);
3967 int_type __c = traits_type::eof();
3968 if (this->gptr() == this->egptr())
3969 {
3970 memmove(this->eback(), this->egptr() - __unget_sz, __unget_sz * sizeof(char_type));
3971 if (__always_noconv_)
3972 {
3973 streamsize __nmemb = static_cast<streamsize>(this->egptr() - this->eback() - __unget_sz);
3974 __nmemb = __bufptr_->sgetn((char*)this->eback() + __unget_sz, __nmemb);
3975 if (__nmemb != 0)
3976 {
3977 this->setg(this->eback(),
3978 this->eback() + __unget_sz,
3979 this->eback() + __unget_sz + __nmemb);
3980 __c = *this->gptr();
3981 }
3982 }
3983 else
3984 {
3985 memmove(__extbuf_, __extbufnext_, __extbufend_ - __extbufnext_);
3986 __extbufnext_ = __extbuf_ + (__extbufend_ - __extbufnext_);
3987 __extbufend_ = __extbuf_ + (__extbuf_ == __extbuf_min_ ? sizeof(__extbuf_min_) : __ebs_);
3988 streamsize __nmemb = min(static_cast<streamsize>(this->egptr() - this->eback() - __unget_sz),
3989 static_cast<streamsize>(__extbufend_ - __extbufnext_));
3990 codecvt_base::result __r;
3991 state_type __svs = __st_;
3992 streamsize __nr = __bufptr_->sgetn(const_cast<char*>(__extbufnext_), __nmemb);
3993 if (__nr != 0)
3994 {
3995 __extbufend_ = __extbufnext_ + __nr;
3996 char_type* __inext;
3997 __r = __cv_->in(__st_, __extbuf_, __extbufend_, __extbufnext_,
3998 this->eback() + __unget_sz,
3999 this->egptr(), __inext);
4000 if (__r == codecvt_base::noconv)
4001 {
4002 this->setg((char_type*)__extbuf_, (char_type*)__extbuf_, (char_type*)__extbufend_);
4003 __c = *this->gptr();
4004 }
4005 else if (__inext != this->eback() + __unget_sz)
4006 {
4007 this->setg(this->eback(), this->eback() + __unget_sz, __inext);
4008 __c = *this->gptr();
4009 }
4010 }
4011 }
4012 }
4013 else
4014 __c = *this->gptr();
4015 if (this->eback() == &__1buf)
4016 this->setg(0, 0, 0);
4017 return __c;
4018}
4019
4020template <class _Codecvt, class _Elem, class _Tr>
4021typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
4022wbuffer_convert<_Codecvt, _Elem, _Tr>::pbackfail(int_type __c)
4023{
4024 if (__cv_ != 0 && __bufptr_ != 0 && this->eback() < this->gptr())
4025 {
4026 if (traits_type::eq_int_type(__c, traits_type::eof()))
4027 {
4028 this->gbump(-1);
4029 return traits_type::not_eof(__c);
4030 }
4031 if (traits_type::eq(traits_type::to_char_type(__c), this->gptr()[-1]))
4032 {
4033 this->gbump(-1);
4034 *this->gptr() = traits_type::to_char_type(__c);
4035 return __c;
4036 }
4037 }
4038 return traits_type::eof();
4039}
4040
4041template <class _Codecvt, class _Elem, class _Tr>
Howard Hinnantd23b4642010-05-31 20:58:54 +00004042typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
4043wbuffer_convert<_Codecvt, _Elem, _Tr>::overflow(int_type __c)
4044{
Howard Hinnant4b53f502010-06-01 20:09:18 +00004045 if (__cv_ == 0 || __bufptr_ == 0)
4046 return traits_type::eof();
4047 __write_mode();
4048 char_type __1buf;
4049 char_type* __pb_save = this->pbase();
4050 char_type* __epb_save = this->epptr();
4051 if (!traits_type::eq_int_type(__c, traits_type::eof()))
4052 {
4053 if (this->pptr() == 0)
4054 this->setp(&__1buf, &__1buf+1);
4055 *this->pptr() = traits_type::to_char_type(__c);
4056 this->pbump(1);
4057 }
4058 if (this->pptr() != this->pbase())
4059 {
4060 if (__always_noconv_)
4061 {
4062 streamsize __nmemb = static_cast<streamsize>(this->pptr() - this->pbase());
4063 if (__bufptr_->sputn((const char*)this->pbase(), __nmemb) != __nmemb)
4064 return traits_type::eof();
4065 }
4066 else
4067 {
4068 char* __extbe = __extbuf_;
4069 codecvt_base::result __r;
4070 do
4071 {
4072 const char_type* __e;
4073 __r = __cv_->out(__st_, this->pbase(), this->pptr(), __e,
4074 __extbuf_, __extbuf_ + __ebs_, __extbe);
4075 if (__e == this->pbase())
4076 return traits_type::eof();
4077 if (__r == codecvt_base::noconv)
4078 {
4079 streamsize __nmemb = static_cast<size_t>(this->pptr() - this->pbase());
4080 if (__bufptr_->sputn((const char*)this->pbase(), __nmemb) != __nmemb)
4081 return traits_type::eof();
4082 }
4083 else if (__r == codecvt_base::ok || __r == codecvt_base::partial)
4084 {
4085 streamsize __nmemb = static_cast<size_t>(__extbe - __extbuf_);
4086 if (__bufptr_->sputn(__extbuf_, __nmemb) != __nmemb)
4087 return traits_type::eof();
4088 if (__r == codecvt_base::partial)
4089 {
4090 this->setp((char_type*)__e, this->pptr());
4091 this->pbump(this->epptr() - this->pbase());
4092 }
4093 }
4094 else
4095 return traits_type::eof();
4096 } while (__r == codecvt_base::partial);
4097 }
4098 this->setp(__pb_save, __epb_save);
4099 }
4100 return traits_type::not_eof(__c);
4101}
4102
4103template <class _Codecvt, class _Elem, class _Tr>
4104basic_streambuf<_Elem, _Tr>*
4105wbuffer_convert<_Codecvt, _Elem, _Tr>::setbuf(char_type* __s, streamsize __n)
4106{
4107 this->setg(0, 0, 0);
4108 this->setp(0, 0);
4109 if (__owns_eb_)
4110 delete [] __extbuf_;
4111 if (__owns_ib_)
4112 delete [] __intbuf_;
4113 __ebs_ = __n;
4114 if (__ebs_ > sizeof(__extbuf_min_))
4115 {
4116 if (__always_noconv_ && __s)
4117 {
4118 __extbuf_ = (char*)__s;
4119 __owns_eb_ = false;
4120 }
4121 else
4122 {
4123 __extbuf_ = new char[__ebs_];
4124 __owns_eb_ = true;
4125 }
4126 }
4127 else
4128 {
4129 __extbuf_ = __extbuf_min_;
4130 __ebs_ = sizeof(__extbuf_min_);
4131 __owns_eb_ = false;
4132 }
4133 if (!__always_noconv_)
4134 {
4135 __ibs_ = max<streamsize>(__n, sizeof(__extbuf_min_));
4136 if (__s && __ibs_ >= sizeof(__extbuf_min_))
4137 {
4138 __intbuf_ = __s;
4139 __owns_ib_ = false;
4140 }
4141 else
4142 {
4143 __intbuf_ = new char_type[__ibs_];
4144 __owns_ib_ = true;
4145 }
4146 }
4147 else
4148 {
4149 __ibs_ = 0;
4150 __intbuf_ = 0;
4151 __owns_ib_ = false;
4152 }
4153 return this;
4154}
4155
4156template <class _Codecvt, class _Elem, class _Tr>
4157typename wbuffer_convert<_Codecvt, _Elem, _Tr>::pos_type
4158wbuffer_convert<_Codecvt, _Elem, _Tr>::seekoff(off_type __off, ios_base::seekdir __way,
4159 ios_base::openmode __om)
4160{
4161 int __width = __cv_->encoding();
4162 if (__cv_ == 0 || __bufptr_ == 0 || (__width <= 0 && __off != 0) || sync())
4163 return pos_type(off_type(-1));
4164 // __width > 0 || __off == 0
4165 switch (__way)
4166 {
4167 case ios_base::beg:
4168 break;
4169 case ios_base::cur:
4170 break;
4171 case ios_base::end:
4172 break;
4173 default:
4174 return pos_type(off_type(-1));
4175 }
4176 pos_type __r = __bufptr_->pubseekoff(__width * __off, __way, __om);
4177 __r.state(__st_);
4178 return __r;
4179}
4180
4181template <class _Codecvt, class _Elem, class _Tr>
4182typename wbuffer_convert<_Codecvt, _Elem, _Tr>::pos_type
4183wbuffer_convert<_Codecvt, _Elem, _Tr>::seekpos(pos_type __sp, ios_base::openmode __wch)
4184{
4185 if (__cv_ == 0 || __bufptr_ == 0 || sync())
4186 return pos_type(off_type(-1));
4187 if (__bufptr_->pubseekpos(__sp, __wch) == pos_type(off_type(-1)))
4188 return pos_type(off_type(-1));
4189 return __sp;
4190}
4191
4192template <class _Codecvt, class _Elem, class _Tr>
4193int
4194wbuffer_convert<_Codecvt, _Elem, _Tr>::sync()
4195{
4196 if (__cv_ == 0 || __bufptr_ == 0)
4197 return 0;
4198 if (__cm_ & ios_base::out)
4199 {
4200 if (this->pptr() != this->pbase())
4201 if (overflow() == traits_type::eof())
4202 return -1;
4203 codecvt_base::result __r;
4204 do
4205 {
4206 char* __extbe;
4207 __r = __cv_->unshift(__st_, __extbuf_, __extbuf_ + __ebs_, __extbe);
4208 streamsize __nmemb = static_cast<streamsize>(__extbe - __extbuf_);
4209 if (__bufptr_->sputn(__extbuf_, __nmemb) != __nmemb)
4210 return -1;
4211 } while (__r == codecvt_base::partial);
4212 if (__r == codecvt_base::error)
4213 return -1;
4214 if (__bufptr_->pubsync())
4215 return -1;
4216 }
4217 else if (__cm_ & ios_base::in)
4218 {
4219 off_type __c;
4220 if (__always_noconv_)
4221 __c = this->egptr() - this->gptr();
4222 else
4223 {
4224 int __width = __cv_->encoding();
4225 __c = __extbufend_ - __extbufnext_;
4226 if (__width > 0)
4227 __c += __width * (this->egptr() - this->gptr());
4228 else
4229 {
4230 if (this->gptr() != this->egptr())
4231 {
4232 reverse(this->gptr(), this->egptr());
4233 codecvt_base::result __r;
4234 const char_type* __e = this->gptr();
4235 char* __extbe;
4236 do
4237 {
4238 __r = __cv_->out(__st_, __e, this->egptr(), __e,
4239 __extbuf_, __extbuf_ + __ebs_, __extbe);
4240 switch (__r)
4241 {
4242 case codecvt_base::noconv:
4243 __c += this->egptr() - this->gptr();
4244 break;
4245 case codecvt_base::ok:
4246 case codecvt_base::partial:
4247 __c += __extbe - __extbuf_;
4248 break;
4249 default:
4250 return -1;
4251 }
4252 } while (__r == codecvt_base::partial);
4253 }
4254 }
4255 }
4256 if (__bufptr_->pubseekoff(-__c, ios_base::cur, __cm_) == pos_type(off_type(-1)))
4257 return -1;
4258 this->setg(0, 0, 0);
4259 __cm_ = 0;
4260 }
4261 return 0;
4262}
4263
4264template <class _Codecvt, class _Elem, class _Tr>
4265bool
4266wbuffer_convert<_Codecvt, _Elem, _Tr>::__read_mode()
4267{
4268 if (!(__cm_ & ios_base::in))
4269 {
4270 this->setp(0, 0);
4271 if (__always_noconv_)
4272 this->setg((char_type*)__extbuf_,
4273 (char_type*)__extbuf_ + __ebs_,
4274 (char_type*)__extbuf_ + __ebs_);
4275 else
4276 this->setg(__intbuf_, __intbuf_ + __ibs_, __intbuf_ + __ibs_);
4277 __cm_ = ios_base::in;
4278 return true;
4279 }
4280 return false;
4281}
4282
4283template <class _Codecvt, class _Elem, class _Tr>
4284void
4285wbuffer_convert<_Codecvt, _Elem, _Tr>::__write_mode()
4286{
4287 if (!(__cm_ & ios_base::out))
4288 {
4289 this->setg(0, 0, 0);
4290 if (__ebs_ > sizeof(__extbuf_min_))
4291 {
4292 if (__always_noconv_)
4293 this->setp((char_type*)__extbuf_,
4294 (char_type*)__extbuf_ + (__ebs_ - 1));
4295 else
4296 this->setp(__intbuf_, __intbuf_ + (__ibs_ - 1));
4297 }
4298 else
4299 this->setp(0, 0);
4300 __cm_ = ios_base::out;
4301 }
4302}
4303
4304template <class _Codecvt, class _Elem, class _Tr>
4305wbuffer_convert<_Codecvt, _Elem, _Tr>*
4306wbuffer_convert<_Codecvt, _Elem, _Tr>::__close()
4307{
4308 wbuffer_convert* __rt = 0;
4309 if (__cv_ != 0 && __bufptr_ != 0)
4310 {
4311 __rt = this;
4312 if ((__cm_ & ios_base::out) && sync())
4313 __rt = 0;
4314 }
4315 return __rt;
Howard Hinnantd23b4642010-05-31 20:58:54 +00004316}
4317
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004318_LIBCPP_END_NAMESPACE_STD
4319
4320#endif // _LIBCPP_LOCALE