blob: 4a65eb6bec84c6585a4d9ac3ef75c1b2763654f4 [file] [log] [blame]
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001// -*- C++ -*-
2//===-------------------------- locale ------------------------------------===//
3//
Howard Hinnantf5256e12010-05-11 21:36:01 +00004// The LLVM Compiler Infrastructure
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005//
Howard Hinnantb64f8b02010-11-16 22:09:02 +00006// This file is dual licensed under the MIT and the University of Illinois Open
7// Source Licenses. See LICENSE.TXT for details.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00008//
9//===----------------------------------------------------------------------===//
10
11#ifndef _LIBCPP_LOCALE
12#define _LIBCPP_LOCALE
13
14/*
15 locale synopsis
16
17namespace std
18{
19
20class locale
21{
22public:
23 // types:
24 class facet;
25 class id;
26
27 typedef int category;
28 static const category // values assigned here are for exposition only
29 none = 0x000,
30 collate = 0x010,
31 ctype = 0x020,
32 monetary = 0x040,
33 numeric = 0x080,
34 time = 0x100,
35 messages = 0x200,
36 all = collate | ctype | monetary | numeric | time | messages;
37
38 // construct/copy/destroy:
Howard Hinnantc9834542011-05-31 15:34:58 +000039 locale() noexcept;
40 locale(const locale& other) noexcept;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000041 explicit locale(const char* std_name);
42 explicit locale(const string& std_name);
43 locale(const locale& other, const char* std_name, category);
44 locale(const locale& other, const string& std_name, category);
45 template <class Facet> locale(const locale& other, Facet* f);
46 locale(const locale& other, const locale& one, category);
47
Howard Hinnantc9834542011-05-31 15:34:58 +000048 ~locale(); // not virtual
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000049
Howard Hinnantc9834542011-05-31 15:34:58 +000050 const locale& operator=(const locale& other) noexcept;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000051
52 template <class Facet> locale combine(const locale& other) const;
53
54 // locale operations:
55 basic_string<char> name() const;
56 bool operator==(const locale& other) const;
57 bool operator!=(const locale& other) const;
58 template <class charT, class Traits, class Allocator>
59 bool operator()(const basic_string<charT,Traits,Allocator>& s1,
60 const basic_string<charT,Traits,Allocator>& s2) const;
61
62 // global locale objects:
63 static locale global(const locale&);
64 static const locale& classic();
65};
66
67template <class Facet> const Facet& use_facet(const locale&);
Howard Hinnantc9834542011-05-31 15:34:58 +000068template <class Facet> bool has_facet(const locale&) noexcept;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000069
70// 22.3.3, convenience interfaces:
71template <class charT> bool isspace (charT c, const locale& loc);
72template <class charT> bool isprint (charT c, const locale& loc);
73template <class charT> bool iscntrl (charT c, const locale& loc);
74template <class charT> bool isupper (charT c, const locale& loc);
75template <class charT> bool islower (charT c, const locale& loc);
76template <class charT> bool isalpha (charT c, const locale& loc);
77template <class charT> bool isdigit (charT c, const locale& loc);
78template <class charT> bool ispunct (charT c, const locale& loc);
79template <class charT> bool isxdigit(charT c, const locale& loc);
80template <class charT> bool isalnum (charT c, const locale& loc);
81template <class charT> bool isgraph (charT c, const locale& loc);
82template <class charT> charT toupper(charT c, const locale& loc);
83template <class charT> charT tolower(charT c, const locale& loc);
Howard Hinnantd23b4642010-05-31 20:58:54 +000084
85template<class Codecvt, class Elem = wchar_t,
86 class Wide_alloc = allocator<Elem>,
87 class Byte_alloc = allocator<char>>
88class wstring_convert
89{
90public:
91 typedef basic_string<char, char_traits<char>, Byte_alloc> byte_string;
92 typedef basic_string<Elem, char_traits<Elem>, Wide_alloc> wide_string;
93 typedef typename Codecvt::state_type state_type;
94 typedef typename wide_string::traits_type::int_type int_type;
95
96 wstring_convert(Codecvt* pcvt = new Codecvt);
97 wstring_convert(Codecvt* pcvt, state_type state);
98 wstring_convert(const byte_string& byte_err,
99 const wide_string& wide_err = wide_string());
100 ~wstring_convert();
101
102 wide_string from_bytes(char byte);
103 wide_string from_bytes(const char* ptr);
104 wide_string from_bytes(const byte_string& str);
105 wide_string from_bytes(const char* first, const char* last);
106
107 byte_string to_bytes(Elem wchar);
108 byte_string to_bytes(const Elem* wptr);
109 byte_string to_bytes(const wide_string& wstr);
110 byte_string to_bytes(const Elem* first, const Elem* last);
111
112 size_t converted() const;
113 state_type state() const;
114};
115
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000116template <class Codecvt, class Elem = wchar_t, class Tr = char_traits<Elem>>
Howard Hinnantd23b4642010-05-31 20:58:54 +0000117class wbuffer_convert
118 : public basic_streambuf<Elem, Tr>
119{
120public:
121 typedef typename Tr::state_type state_type;
122
123 wbuffer_convert(streambuf* bytebuf = 0, Codecvt* pcvt = new Codecvt,
124 state_type state = state_type());
125
126 streambuf* rdbuf() const;
127 streambuf* rdbuf(streambuf* bytebuf);
128
129 state_type state() const;
130};
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000131
132// 22.4.1 and 22.4.1.3, ctype:
133class ctype_base;
134template <class charT> class ctype;
135template <> class ctype<char>; // specialization
136template <class charT> class ctype_byname;
137template <> class ctype_byname<char>; // specialization
138
139class codecvt_base;
140template <class internT, class externT, class stateT> class codecvt;
141template <class internT, class externT, class stateT> class codecvt_byname;
142
143// 22.4.2 and 22.4.3, numeric:
144template <class charT, class InputIterator> class num_get;
145template <class charT, class OutputIterator> class num_put;
146template <class charT> class numpunct;
147template <class charT> class numpunct_byname;
148
149// 22.4.4, col lation:
150template <class charT> class collate;
151template <class charT> class collate_byname;
152
153// 22.4.5, date and time:
154class time_base;
155template <class charT, class InputIterator> class time_get;
156template <class charT, class InputIterator> class time_get_byname;
157template <class charT, class OutputIterator> class time_put;
158template <class charT, class OutputIterator> class time_put_byname;
159
160// 22.4.6, money:
161class money_base;
162template <class charT, class InputIterator> class money_get;
163template <class charT, class OutputIterator> class money_put;
164template <class charT, bool Intl> class moneypunct;
165template <class charT, bool Intl> class moneypunct_byname;
166
167// 22.4.7, message retrieval:
168class messages_base;
169template <class charT> class messages;
170template <class charT> class messages_byname;
171
172} // std
173
174*/
175
176#include <__config>
177#include <__locale>
178#include <algorithm>
179#include <memory>
180#include <ios>
181#include <streambuf>
182#include <iterator>
183#include <limits>
Howard Hinnantadff4892010-05-24 17:49:41 +0000184#if !__APPLE__
185#include <cstdarg>
186#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000187#include <cstdlib>
188#include <ctime>
189#include <nl_types.h>
190
191#pragma GCC system_header
192
193_LIBCPP_BEGIN_NAMESPACE_STD
194
Sean Hunt62a6ac32011-07-09 00:56:23 +0000195// Get the C locale object
196locale_t __cloc();
197
Howard Hinnantadff4892010-05-24 17:49:41 +0000198// OSX has nice foo_l() functions that let you turn off use of the global
199// locale. Linux, not so much. The following functions avoid the locale when
200// that's possible and otherwise do the wrong thing. FIXME.
201#if __APPLE__
202
203template <class _Tp>
Howard Hinnant82894812010-09-22 16:48:34 +0000204inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantadff4892010-05-24 17:49:41 +0000205int
206__nolocale_sprintf(char* __restrict __str,
207 const char* __restrict __format, _Tp __v)
208{
209 return sprintf_l(__str, 0, __format, __v);
210}
211
212template <class _Tp>
Howard Hinnant82894812010-09-22 16:48:34 +0000213inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantadff4892010-05-24 17:49:41 +0000214int
215__nolocale_snprintf(char* __restrict __str, size_t __size,
216 const char* __restrict __format, _Tp __v)
217{
218 return snprintf_l(__str, __size, 0, __format, __v);
219}
220
221template <class _Tp>
Howard Hinnant82894812010-09-22 16:48:34 +0000222inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantadff4892010-05-24 17:49:41 +0000223int
224__nolocale_snprintf(char* __restrict __str, size_t __size,
225 const char* __restrict __format, int __prec, _Tp __v)
226{
227 return snprintf_l(__str, __size, 0, __format, __prec, __v);
228}
229
230template <class _Tp>
Howard Hinnant82894812010-09-22 16:48:34 +0000231inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantadff4892010-05-24 17:49:41 +0000232int
233__nolocale_asprintf(char** __ret, const char* __restrict __format, _Tp __v)
234{
235 return asprintf_l(__ret, 0, __format, __v);
236}
237
238template <class _Tp>
Howard Hinnant82894812010-09-22 16:48:34 +0000239inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantadff4892010-05-24 17:49:41 +0000240int
241__nolocale_asprintf(char** __ret, const char* __restrict __format, int __prec,
242 _Tp __v)
243{
244 return asprintf_l(__ret, 0, __format, __prec, __v);
245}
246
247template <class _Tp>
Howard Hinnant82894812010-09-22 16:48:34 +0000248inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantadff4892010-05-24 17:49:41 +0000249int
250__nolocale_sscanf(const char* __restrict __str,
251 const char* __restrict __format, _Tp* __v)
252{
253 return sscanf_l(__str, 0, __format, __v);
254}
255
Howard Hinnant82894812010-09-22 16:48:34 +0000256inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantadff4892010-05-24 17:49:41 +0000257int
258__nolocale_isxdigit(int __c)
259{
260 return isxdigit_l(__c, 0);
261}
262
Howard Hinnant82894812010-09-22 16:48:34 +0000263inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantadff4892010-05-24 17:49:41 +0000264int
265__nolocale_isdigit(int __c)
266{
267 return isdigit_l(__c, 0);
268}
269
Howard Hinnant324bb032010-08-22 00:02:43 +0000270#else // __APPLE__
Michael J. Spencer626916f2010-12-10 19:47:54 +0000271inline
272#ifndef _LIBCPP_HAS_NO_ALWAYS_INLINE_VARIADICS
273_LIBCPP_INLINE_VISIBILITY
274#endif
Howard Hinnant82894812010-09-22 16:48:34 +0000275int
Howard Hinnantadff4892010-05-24 17:49:41 +0000276__nolocale_sprintf(char* __restrict __str,
277 const char* __restrict __format, ...)
278{
279 va_list __ap;
280 va_start(__ap, __format);
281 int __result = vsprintf(__str, __format, __ap);
282 va_end(__ap);
283 return __result;
284}
Michael J. Spencer626916f2010-12-10 19:47:54 +0000285inline
286#ifndef _LIBCPP_HAS_NO_ALWAYS_INLINE_VARIADICS
287_LIBCPP_INLINE_VISIBILITY
288#endif
Howard Hinnant82894812010-09-22 16:48:34 +0000289int
Howard Hinnantadff4892010-05-24 17:49:41 +0000290__nolocale_snprintf(char* __restrict __str, size_t __size,
291 const char* __restrict __format, ...)
292{
293 va_list __ap;
294 va_start(__ap, __format);
295 int __result = vsnprintf(__str, __size, __format, __ap);
296 va_end(__ap);
297 return __result;
298}
Michael J. Spencer626916f2010-12-10 19:47:54 +0000299inline
300#ifndef _LIBCPP_HAS_NO_ALWAYS_INLINE_VARIADICS
301_LIBCPP_INLINE_VISIBILITY
302#endif
Howard Hinnant82894812010-09-22 16:48:34 +0000303int
Howard Hinnantadff4892010-05-24 17:49:41 +0000304__nolocale_asprintf(char** __ret,
305 const char* __restrict __format, ...)
306{
307 va_list __ap;
308 va_start(__ap, __format);
309 int __result = vasprintf(__ret, __format, __ap);
310 va_end(__ap);
311 return __result;
312}
Michael J. Spencer626916f2010-12-10 19:47:54 +0000313inline
314#ifndef _LIBCPP_HAS_NO_ALWAYS_INLINE_VARIADICS
315_LIBCPP_INLINE_VISIBILITY
316#endif
Howard Hinnant82894812010-09-22 16:48:34 +0000317int
Howard Hinnantadff4892010-05-24 17:49:41 +0000318__nolocale_sscanf(const char* __restrict __str,
319 const char* __restrict __format, ...)
320{
321 va_list __ap;
322 va_start(__ap, __format);
323 int __result = vsscanf(__str, __format, __ap);
324 va_end(__ap);
325 return __result;
326}
Howard Hinnant82894812010-09-22 16:48:34 +0000327inline _LIBCPP_INLINE_VISIBILITY
328int
Howard Hinnantadff4892010-05-24 17:49:41 +0000329__nolocale_isxdigit(int __c)
330{
331 return isxdigit(__c);
332}
Howard Hinnant82894812010-09-22 16:48:34 +0000333
334inline _LIBCPP_INLINE_VISIBILITY
335int
Howard Hinnantadff4892010-05-24 17:49:41 +0000336__nolocale_isdigit(int __c)
337{
338 return isdigit(__c);
339}
Howard Hinnant324bb032010-08-22 00:02:43 +0000340#endif // __APPLE__
Howard Hinnantadff4892010-05-24 17:49:41 +0000341
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000342// __scan_keyword
343// Scans [__b, __e) until a match is found in the basic_strings range
344// [__kb, __ke) or until it can be shown that there is no match in [__kb, __ke).
345// __b will be incremented (visibly), consuming CharT until a match is found
346// or proved to not exist. A keyword may be "", in which will match anything.
347// If one keyword is a prefix of another, and the next CharT in the input
348// might match another keyword, the algorithm will attempt to find the longest
349// matching keyword. If the longer matching keyword ends up not matching, then
350// no keyword match is found. If no keyword match is found, __ke is returned
351// and failbit is set in __err.
352// Else an iterator pointing to the matching keyword is found. If more than
353// one keyword matches, an iterator to the first matching keyword is returned.
354// If on exit __b == __e, eofbit is set in __err. If __case_senstive is false,
355// __ct is used to force to lower case before comparing characters.
356// Examples:
357// Keywords: "a", "abb"
358// If the input is "a", the first keyword matches and eofbit is set.
359// If the input is "abc", no match is found and "ab" are consumed.
360template <class _InputIterator, class _ForwardIterator, class _Ctype>
361_LIBCPP_HIDDEN
362_ForwardIterator
363__scan_keyword(_InputIterator& __b, _InputIterator __e,
364 _ForwardIterator __kb, _ForwardIterator __ke,
365 const _Ctype& __ct, ios_base::iostate& __err,
366 bool __case_sensitive = true)
367{
368 typedef typename iterator_traits<_InputIterator>::value_type _CharT;
Howard Hinnant0949eed2011-06-30 21:18:19 +0000369 size_t __nkw = _VSTD::distance(__kb, __ke);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000370 const unsigned char __doesnt_match = '\0';
371 const unsigned char __might_match = '\1';
372 const unsigned char __does_match = '\2';
373 unsigned char __statbuf[100];
374 unsigned char* __status = __statbuf;
375 unique_ptr<unsigned char, void(*)(void*)> __stat_hold(0, free);
376 if (__nkw > sizeof(__statbuf))
377 {
378 __status = (unsigned char*)malloc(__nkw);
379 if (__status == 0)
380 __throw_bad_alloc();
381 __stat_hold.reset(__status);
382 }
383 size_t __n_might_match = __nkw; // At this point, any keyword might match
384 size_t __n_does_match = 0; // but none of them definitely do
385 // Initialize all statuses to __might_match, except for "" keywords are __does_match
386 unsigned char* __st = __status;
387 for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, ++__st)
388 {
389 if (!__ky->empty())
390 *__st = __might_match;
391 else
392 {
393 *__st = __does_match;
394 --__n_might_match;
395 ++__n_does_match;
396 }
397 }
398 // While there might be a match, test keywords against the next CharT
399 for (size_t __indx = 0; __b != __e && __n_might_match > 0; ++__indx)
400 {
401 // Peek at the next CharT but don't consume it
402 _CharT __c = *__b;
403 if (!__case_sensitive)
404 __c = __ct.toupper(__c);
405 bool __consume = false;
406 // For each keyword which might match, see if the __indx character is __c
407 // If a match if found, consume __c
408 // If a match is found, and that is the last character in the keyword,
409 // then that keyword matches.
410 // If the keyword doesn't match this character, then change the keyword
411 // to doesn't match
412 __st = __status;
413 for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, ++__st)
414 {
415 if (*__st == __might_match)
416 {
417 _CharT __kc = (*__ky)[__indx];
418 if (!__case_sensitive)
419 __kc = __ct.toupper(__kc);
420 if (__c == __kc)
421 {
422 __consume = true;
423 if (__ky->size() == __indx+1)
424 {
425 *__st = __does_match;
426 --__n_might_match;
427 ++__n_does_match;
428 }
429 }
430 else
431 {
432 *__st = __doesnt_match;
433 --__n_might_match;
434 }
435 }
436 }
437 // consume if we matched a character
438 if (__consume)
439 {
440 ++__b;
441 // If we consumed a character and there might be a matched keyword that
442 // was marked matched on a previous iteration, then such keywords
443 // which are now marked as not matching.
444 if (__n_might_match + __n_does_match > 1)
445 {
446 __st = __status;
447 for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, ++__st)
448 {
449 if (*__st == __does_match && __ky->size() != __indx+1)
450 {
451 *__st = __doesnt_match;
452 --__n_does_match;
453 }
454 }
455 }
456 }
457 }
458 // We've exited the loop because we hit eof and/or we have no more "might matches".
459 if (__b == __e)
460 __err |= ios_base::eofbit;
461 // Return the first matching result
462 for (__st = __status; __kb != __ke; ++__kb, ++__st)
463 if (*__st == __does_match)
464 break;
465 if (__kb == __ke)
466 __err |= ios_base::failbit;
467 return __kb;
468}
469
470struct __num_get_base
471{
472 static const int __num_get_buf_sz = 40;
473
474 static int __get_base(ios_base&);
475 static const char __src[33];
476};
477
478void __check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
479 ios_base::iostate& __err);
480
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000481template <class _CharT>
482struct __num_get
483 : protected __num_get_base
484{
485 static string __stage2_int_prep(ios_base& __iob, _CharT* __atoms, _CharT& __thousands_sep);
486 static string __stage2_float_prep(ios_base& __iob, _CharT* __atoms, _CharT& __decimal_point,
487 _CharT& __thousands_sep);
488 static int __stage2_int_loop(_CharT __ct, int __base, char* __a, char*& __a_end,
489 unsigned& __dc, _CharT __thousands_sep, const string& __grouping,
490 unsigned* __g, unsigned*& __g_end, _CharT* __atoms);
491 static int __stage2_float_loop(_CharT __ct, bool& __in_units, char& __exp,
492 char* __a, char*& __a_end,
493 _CharT __decimal_point, _CharT __thousands_sep,
494 const string& __grouping, unsigned* __g,
495 unsigned*& __g_end, unsigned& __dc, _CharT* __atoms);
496};
497
498template <class _CharT>
499string
500__num_get<_CharT>::__stage2_int_prep(ios_base& __iob, _CharT* __atoms, _CharT& __thousands_sep)
501{
502 locale __loc = __iob.getloc();
503 use_facet<ctype<_CharT> >(__loc).widen(__src, __src + 26, __atoms);
504 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
505 __thousands_sep = __np.thousands_sep();
506 return __np.grouping();
507}
508
509template <class _CharT>
510string
511__num_get<_CharT>::__stage2_float_prep(ios_base& __iob, _CharT* __atoms, _CharT& __decimal_point,
512 _CharT& __thousands_sep)
513{
514 locale __loc = __iob.getloc();
515 use_facet<ctype<_CharT> >(__loc).widen(__src, __src + 32, __atoms);
516 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
517 __decimal_point = __np.decimal_point();
518 __thousands_sep = __np.thousands_sep();
519 return __np.grouping();
520}
521
522template <class _CharT>
523int
524__num_get<_CharT>::__stage2_int_loop(_CharT __ct, int __base, char* __a, char*& __a_end,
525 unsigned& __dc, _CharT __thousands_sep, const string& __grouping,
526 unsigned* __g, unsigned*& __g_end, _CharT* __atoms)
527{
Howard Hinnant80586722011-03-09 01:03:19 +0000528 if (__a_end == __a && (__ct == __atoms[24] || __ct == __atoms[25]))
529 {
530 *__a_end++ = __ct == __atoms[24] ? '+' : '-';
531 __dc = 0;
532 return 0;
533 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000534 if (__ct == __thousands_sep && __grouping.size() != 0)
535 {
536 if (__g_end-__g < __num_get_buf_sz)
537 {
538 *__g_end++ = __dc;
539 __dc = 0;
540 }
541 return 0;
542 }
543 ptrdiff_t __f = find(__atoms, __atoms + 26, __ct) - __atoms;
Howard Hinnant80586722011-03-09 01:03:19 +0000544 if (__f >= 24)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000545 return -1;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000546 switch (__base)
547 {
548 case 8:
549 case 10:
550 if (__f >= __base)
Howard Hinnant80586722011-03-09 01:03:19 +0000551 return -1;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000552 break;
Howard Hinnant80586722011-03-09 01:03:19 +0000553 case 16:
554 if (__f < 22)
555 break;
556 if (__a_end != __a && __a_end - __a <= 2 && __a_end[-1] == '0')
557 {
558 __dc = 0;
559 *__a_end++ = __src[__f];
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000560 return 0;
Howard Hinnant80586722011-03-09 01:03:19 +0000561 }
562 return -1;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000563 }
Howard Hinnant80586722011-03-09 01:03:19 +0000564 if (__a_end-__a < __num_get_buf_sz - 1)
565 *__a_end++ = __src[__f];
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000566 ++__dc;
567 return 0;
568}
569
570template <class _CharT>
571int
572__num_get<_CharT>::__stage2_float_loop(_CharT __ct, bool& __in_units, char& __exp, char* __a, char*& __a_end,
573 _CharT __decimal_point, _CharT __thousands_sep, const string& __grouping,
574 unsigned* __g, unsigned*& __g_end, unsigned& __dc, _CharT* __atoms)
575{
576 if (__ct == __decimal_point)
577 {
578 if (!__in_units)
579 return -1;
580 __in_units = false;
581 *__a_end++ = '.';
582 if (__grouping.size() != 0 && __g_end-__g < __num_get_buf_sz)
583 *__g_end++ = __dc;
584 return 0;
585 }
586 if (__ct == __thousands_sep && __grouping.size() != 0)
587 {
588 if (!__in_units)
589 return -1;
590 if (__g_end-__g < __num_get_buf_sz)
591 {
592 *__g_end++ = __dc;
593 __dc = 0;
594 }
595 return 0;
596 }
597 ptrdiff_t __f = find(__atoms, __atoms + 32, __ct) - __atoms;
598 if (__f >= 32)
599 return -1;
600 char __x = __src[__f];
601 if (__a_end-__a < __num_get_buf_sz - 1)
602 *__a_end++ = __x;
603 if (__x == 'x' || __x == 'X')
604 __exp = 'P';
605 else if ((__x & 0xDF) == __exp)
606 {
607 __in_units = false;
608 if (__grouping.size() != 0 && __g_end-__g < __num_get_buf_sz)
609 *__g_end++ = __dc;
610 }
611 if (__f >= 22)
612 return 0;
613 ++__dc;
614 return 0;
615}
616
617extern template class __num_get<char>;
618extern template class __num_get<wchar_t>;
619
620template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +0000621class _LIBCPP_VISIBLE num_get
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000622 : public locale::facet,
623 private __num_get<_CharT>
624{
625public:
626 typedef _CharT char_type;
627 typedef _InputIterator iter_type;
628
629 _LIBCPP_ALWAYS_INLINE
630 explicit num_get(size_t __refs = 0)
631 : locale::facet(__refs) {}
632
633 _LIBCPP_ALWAYS_INLINE
634 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
635 ios_base::iostate& __err, bool& __v) const
636 {
637 return do_get(__b, __e, __iob, __err, __v);
638 }
639
640 _LIBCPP_ALWAYS_INLINE
641 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
642 ios_base::iostate& __err, long& __v) const
643 {
644 return do_get(__b, __e, __iob, __err, __v);
645 }
646
647 _LIBCPP_ALWAYS_INLINE
648 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
649 ios_base::iostate& __err, long long& __v) const
650 {
651 return do_get(__b, __e, __iob, __err, __v);
652 }
653
654 _LIBCPP_ALWAYS_INLINE
655 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
656 ios_base::iostate& __err, unsigned short& __v) const
657 {
658 return do_get(__b, __e, __iob, __err, __v);
659 }
660
661 _LIBCPP_ALWAYS_INLINE
662 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
663 ios_base::iostate& __err, unsigned int& __v) const
664 {
665 return do_get(__b, __e, __iob, __err, __v);
666 }
667
668 _LIBCPP_ALWAYS_INLINE
669 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
670 ios_base::iostate& __err, unsigned long& __v) const
671 {
672 return do_get(__b, __e, __iob, __err, __v);
673 }
674
675 _LIBCPP_ALWAYS_INLINE
676 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
677 ios_base::iostate& __err, unsigned long long& __v) const
678 {
679 return do_get(__b, __e, __iob, __err, __v);
680 }
681
682 _LIBCPP_ALWAYS_INLINE
683 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
684 ios_base::iostate& __err, float& __v) const
685 {
686 return do_get(__b, __e, __iob, __err, __v);
687 }
688
689 _LIBCPP_ALWAYS_INLINE
690 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
691 ios_base::iostate& __err, double& __v) const
692 {
693 return do_get(__b, __e, __iob, __err, __v);
694 }
695
696 _LIBCPP_ALWAYS_INLINE
697 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
698 ios_base::iostate& __err, long double& __v) const
699 {
700 return do_get(__b, __e, __iob, __err, __v);
701 }
702
703 _LIBCPP_ALWAYS_INLINE
704 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
705 ios_base::iostate& __err, void*& __v) const
706 {
707 return do_get(__b, __e, __iob, __err, __v);
708 }
709
710 static locale::id id;
711
712protected:
Howard Hinnant82894812010-09-22 16:48:34 +0000713 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000714 ~num_get() {}
715
716 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
717 ios_base::iostate& __err, bool& __v) const;
718 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
719 ios_base::iostate& __err, long& __v) const;
720 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
721 ios_base::iostate& __err, long long& __v) const;
722 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
723 ios_base::iostate& __err, unsigned short& __v) const;
724 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
725 ios_base::iostate& __err, unsigned int& __v) const;
726 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
727 ios_base::iostate& __err, unsigned long& __v) const;
728 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
729 ios_base::iostate& __err, unsigned long long& __v) const;
730 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
731 ios_base::iostate& __err, float& __v) const;
732 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
733 ios_base::iostate& __err, double& __v) const;
734 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
735 ios_base::iostate& __err, long double& __v) const;
736 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
737 ios_base::iostate& __err, void*& __v) const;
738};
739
740template <class _CharT, class _InputIterator>
741locale::id
742num_get<_CharT, _InputIterator>::id;
743
744template <class _Tp>
745_Tp
746__num_get_signed_integral(const char* __a, const char* __a_end,
747 ios_base::iostate& __err, int __base)
748{
749 if (__a != __a_end)
750 {
Howard Hinnante7c8da62011-02-25 19:52:41 +0000751 int __save_errno = errno;
752 errno = 0;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000753 char *__p2;
754 long long __ll = strtoll_l(__a, &__p2, __base, 0);
Howard Hinnante7c8da62011-02-25 19:52:41 +0000755 int __current_errno = errno;
756 if (__current_errno == 0)
757 errno = __save_errno;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000758 if (__p2 != __a_end)
759 {
760 __err = ios_base::failbit;
761 return 0;
762 }
Howard Hinnante7c8da62011-02-25 19:52:41 +0000763 else if (__current_errno == ERANGE ||
764 __ll < numeric_limits<_Tp>::min() ||
765 numeric_limits<_Tp>::max() < __ll)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000766 {
767 __err = ios_base::failbit;
Howard Hinnante7c8da62011-02-25 19:52:41 +0000768 if (__ll > 0)
769 return numeric_limits<_Tp>::max();
770 else
771 return numeric_limits<_Tp>::min();
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000772 }
773 return static_cast<_Tp>(__ll);
774 }
775 __err = ios_base::failbit;
776 return 0;
777}
778
779template <class _Tp>
780_Tp
781__num_get_unsigned_integral(const char* __a, const char* __a_end,
782 ios_base::iostate& __err, int __base)
783{
784 if (__a != __a_end)
785 {
Howard Hinnante7c8da62011-02-25 19:52:41 +0000786 if (*__a == '-')
787 {
788 __err = ios_base::failbit;
789 return 0;
790 }
791 int __save_errno = errno;
792 errno = 0;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000793 char *__p2;
794 unsigned long long __ll = strtoull_l(__a, &__p2, __base, 0);
Howard Hinnante7c8da62011-02-25 19:52:41 +0000795 int __current_errno = errno;
796 if (__current_errno == 0)
797 errno = __save_errno;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000798 if (__p2 != __a_end)
799 {
800 __err = ios_base::failbit;
801 return 0;
802 }
Howard Hinnante7c8da62011-02-25 19:52:41 +0000803 else if (__current_errno == ERANGE ||
804 numeric_limits<_Tp>::max() < __ll)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000805 {
806 __err = ios_base::failbit;
807 return numeric_limits<_Tp>::max();
808 }
809 return static_cast<_Tp>(__ll);
810 }
811 __err = ios_base::failbit;
812 return 0;
813}
814
815template <class _Tp>
816_Tp
817__num_get_float(const char* __a, const char* __a_end, ios_base::iostate& __err)
818{
819 if (__a != __a_end)
820 {
821 char *__p2;
822 long double __ld = strtold_l(__a, &__p2, 0);
823 if (__p2 != __a_end)
824 {
825 __err = ios_base::failbit;
826 return 0;
827 }
828 return static_cast<_Tp>(__ld);
829 }
830 __err = ios_base::failbit;
831 return 0;
832}
833
834template <class _CharT, class _InputIterator>
835_InputIterator
836num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
837 ios_base& __iob,
838 ios_base::iostate& __err,
839 bool& __v) const
840{
841 if ((__iob.flags() & ios_base::boolalpha) == 0)
842 {
843 long __lv = -1;
844 __b = do_get(__b, __e, __iob, __err, __lv);
845 switch (__lv)
846 {
847 case 0:
848 __v = false;
849 break;
850 case 1:
851 __v = true;
852 break;
853 default:
854 __v = true;
855 __err = ios_base::failbit;
856 break;
857 }
858 return __b;
859 }
860 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__iob.getloc());
861 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__iob.getloc());
862 typedef typename numpunct<_CharT>::string_type string_type;
863 const string_type __names[2] = {__np.truename(), __np.falsename()};
864 const string_type* __i = __scan_keyword(__b, __e, __names, __names+2,
865 __ct, __err);
866 __v = __i == __names;
867 return __b;
868}
869
870template <class _CharT, class _InputIterator>
871_InputIterator
872num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
873 ios_base& __iob,
874 ios_base::iostate& __err,
875 long& __v) const
876{
877 // Stage 1
878 int __base = this->__get_base(__iob);
879 // Stage 2
880 char_type __atoms[26];
881 char_type __thousands_sep;
882 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
883 char __a[__num_get_base::__num_get_buf_sz] = {0};
884 char* __a_end = __a;
885 unsigned __g[__num_get_base::__num_get_buf_sz];
886 unsigned* __g_end = __g;
887 unsigned __dc = 0;
888 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +0000889 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000890 __thousands_sep, __grouping, __g, __g_end,
891 __atoms))
892 break;
893 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
894 *__g_end++ = __dc;
895 // Stage 3
896 __v = __num_get_signed_integral<long>(__a, __a_end, __err, __base);
897 // Digit grouping checked
898 __check_grouping(__grouping, __g, __g_end, __err);
899 // EOF checked
900 if (__b == __e)
901 __err |= ios_base::eofbit;
902 return __b;
903}
904
905template <class _CharT, class _InputIterator>
906_InputIterator
907num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
908 ios_base& __iob,
909 ios_base::iostate& __err,
910 long long& __v) const
911{
912 // Stage 1
913 int __base = this->__get_base(__iob);
914 // Stage 2
915 char_type __atoms[26];
916 char_type __thousands_sep;
917 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
918 char __a[__num_get_base::__num_get_buf_sz] = {0};
919 char* __a_end = __a;
920 unsigned __g[__num_get_base::__num_get_buf_sz];
921 unsigned* __g_end = __g;
922 unsigned __dc = 0;
923 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +0000924 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
925 __thousands_sep, __grouping, __g, __g_end,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000926 __atoms))
927 break;
928 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
929 *__g_end++ = __dc;
930 // Stage 3
931 __v = __num_get_signed_integral<long long>(__a, __a_end, __err, __base);
932 // Digit grouping checked
933 __check_grouping(__grouping, __g, __g_end, __err);
934 // EOF checked
935 if (__b == __e)
936 __err |= ios_base::eofbit;
937 return __b;
938}
939
940template <class _CharT, class _InputIterator>
941_InputIterator
942num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
943 ios_base& __iob,
944 ios_base::iostate& __err,
945 unsigned short& __v) const
946{
947 // Stage 1
948 int __base = this->__get_base(__iob);
949 // Stage 2
950 char_type __atoms[26];
951 char_type __thousands_sep;
952 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
953 char __a[__num_get_base::__num_get_buf_sz] = {0};
954 char* __a_end = __a;
955 unsigned __g[__num_get_base::__num_get_buf_sz];
956 unsigned* __g_end = __g;
957 unsigned __dc = 0;
958 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +0000959 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000960 __thousands_sep, __grouping, __g, __g_end,
961 __atoms))
962 break;
963 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
964 *__g_end++ = __dc;
965 // Stage 3
966 __v = __num_get_unsigned_integral<unsigned short>(__a, __a_end, __err, __base);
967 // Digit grouping checked
968 __check_grouping(__grouping, __g, __g_end, __err);
969 // EOF checked
970 if (__b == __e)
971 __err |= ios_base::eofbit;
972 return __b;
973}
974
975template <class _CharT, class _InputIterator>
976_InputIterator
977num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
978 ios_base& __iob,
979 ios_base::iostate& __err,
980 unsigned int& __v) const
981{
982 // Stage 1
983 int __base = this->__get_base(__iob);
984 // Stage 2
985 char_type __atoms[26];
986 char_type __thousands_sep;
987 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
988 char __a[__num_get_base::__num_get_buf_sz] = {0};
989 char* __a_end = __a;
990 unsigned __g[__num_get_base::__num_get_buf_sz];
991 unsigned* __g_end = __g;
992 unsigned __dc = 0;
993 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +0000994 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000995 __thousands_sep, __grouping, __g, __g_end,
996 __atoms))
997 break;
998 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
999 *__g_end++ = __dc;
1000 // Stage 3
1001 __v = __num_get_unsigned_integral<unsigned int>(__a, __a_end, __err, __base);
1002 // Digit grouping checked
1003 __check_grouping(__grouping, __g, __g_end, __err);
1004 // EOF checked
1005 if (__b == __e)
1006 __err |= ios_base::eofbit;
1007 return __b;
1008}
1009
1010template <class _CharT, class _InputIterator>
1011_InputIterator
1012num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1013 ios_base& __iob,
1014 ios_base::iostate& __err,
1015 unsigned long& __v) const
1016{
1017 // Stage 1
1018 int __base = this->__get_base(__iob);
1019 // Stage 2
1020 char_type __atoms[26];
1021 char_type __thousands_sep;
1022 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
1023 char __a[__num_get_base::__num_get_buf_sz] = {0};
1024 char* __a_end = __a;
1025 unsigned __g[__num_get_base::__num_get_buf_sz];
1026 unsigned* __g_end = __g;
1027 unsigned __dc = 0;
1028 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001029 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001030 __thousands_sep, __grouping, __g, __g_end,
1031 __atoms))
1032 break;
1033 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
1034 *__g_end++ = __dc;
1035 // Stage 3
1036 __v = __num_get_unsigned_integral<unsigned long>(__a, __a_end, __err, __base);
1037 // Digit grouping checked
1038 __check_grouping(__grouping, __g, __g_end, __err);
1039 // EOF checked
1040 if (__b == __e)
1041 __err |= ios_base::eofbit;
1042 return __b;
1043}
1044
1045template <class _CharT, class _InputIterator>
1046_InputIterator
1047num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1048 ios_base& __iob,
1049 ios_base::iostate& __err,
1050 unsigned long long& __v) const
1051{
1052 // Stage 1
1053 int __base = this->__get_base(__iob);
1054 // Stage 2
1055 char_type __atoms[26];
1056 char_type __thousands_sep;
1057 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
1058 char __a[__num_get_base::__num_get_buf_sz] = {0};
1059 char* __a_end = __a;
1060 unsigned __g[__num_get_base::__num_get_buf_sz];
1061 unsigned* __g_end = __g;
1062 unsigned __dc = 0;
1063 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001064 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001065 __thousands_sep, __grouping, __g, __g_end,
1066 __atoms))
1067 break;
1068 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
1069 *__g_end++ = __dc;
1070 // Stage 3
1071 __v = __num_get_unsigned_integral<unsigned long long>(__a, __a_end, __err, __base);
1072 // Digit grouping checked
1073 __check_grouping(__grouping, __g, __g_end, __err);
1074 // EOF checked
1075 if (__b == __e)
1076 __err |= ios_base::eofbit;
1077 return __b;
1078}
1079
1080template <class _CharT, class _InputIterator>
1081_InputIterator
1082num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1083 ios_base& __iob,
1084 ios_base::iostate& __err,
1085 float& __v) const
1086{
1087 // Stage 1, nothing to do
1088 // Stage 2
1089 char_type __atoms[32];
1090 char_type __decimal_point;
1091 char_type __thousands_sep;
Howard Hinnant324bb032010-08-22 00:02:43 +00001092 string __grouping = this->__stage2_float_prep(__iob, __atoms,
1093 __decimal_point,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001094 __thousands_sep);
1095 char __a[__num_get_base::__num_get_buf_sz] = {0};
1096 char* __a_end = __a;
1097 unsigned __g[__num_get_base::__num_get_buf_sz];
1098 unsigned* __g_end = __g;
1099 unsigned __dc = 0;
1100 bool __in_units = true;
1101 char __exp = 'E';
1102 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001103 if (this->__stage2_float_loop(*__b, __in_units, __exp, __a, __a_end,
1104 __decimal_point, __thousands_sep,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001105 __grouping, __g, __g_end,
1106 __dc, __atoms))
1107 break;
1108 if (__grouping.size() != 0 && __in_units && __g_end-__g < __num_get_base::__num_get_buf_sz)
1109 *__g_end++ = __dc;
1110 // Stage 3
1111 __v = __num_get_float<float>(__a, __a_end, __err);
1112 // Digit grouping checked
1113 __check_grouping(__grouping, __g, __g_end, __err);
1114 // EOF checked
1115 if (__b == __e)
1116 __err |= ios_base::eofbit;
1117 return __b;
1118}
1119
1120template <class _CharT, class _InputIterator>
1121_InputIterator
1122num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1123 ios_base& __iob,
1124 ios_base::iostate& __err,
1125 double& __v) const
1126{
1127 // Stage 1, nothing to do
1128 // Stage 2
1129 char_type __atoms[32];
1130 char_type __decimal_point;
1131 char_type __thousands_sep;
Howard Hinnant324bb032010-08-22 00:02:43 +00001132 string __grouping = this->__stage2_float_prep(__iob, __atoms,
1133 __decimal_point,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001134 __thousands_sep);
1135 char __a[__num_get_base::__num_get_buf_sz] = {0};
1136 char* __a_end = __a;
1137 unsigned __g[__num_get_base::__num_get_buf_sz];
1138 unsigned* __g_end = __g;
1139 unsigned __dc = 0;
1140 bool __in_units = true;
1141 char __exp = 'E';
1142 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001143 if (this->__stage2_float_loop(*__b, __in_units, __exp, __a, __a_end,
1144 __decimal_point, __thousands_sep,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001145 __grouping, __g, __g_end,
1146 __dc, __atoms))
1147 break;
1148 if (__grouping.size() != 0 && __in_units && __g_end-__g < __num_get_base::__num_get_buf_sz)
1149 *__g_end++ = __dc;
1150 // Stage 3
1151 __v = __num_get_float<double>(__a, __a_end, __err);
1152 // Digit grouping checked
1153 __check_grouping(__grouping, __g, __g_end, __err);
1154 // EOF checked
1155 if (__b == __e)
1156 __err |= ios_base::eofbit;
1157 return __b;
1158}
1159
1160template <class _CharT, class _InputIterator>
1161_InputIterator
1162num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1163 ios_base& __iob,
1164 ios_base::iostate& __err,
1165 long double& __v) const
1166{
1167 // Stage 1, nothing to do
1168 // Stage 2
1169 char_type __atoms[32];
1170 char_type __decimal_point;
1171 char_type __thousands_sep;
Howard Hinnant324bb032010-08-22 00:02:43 +00001172 string __grouping = this->__stage2_float_prep(__iob, __atoms,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001173 __decimal_point,
1174 __thousands_sep);
1175 char __a[__num_get_base::__num_get_buf_sz] = {0};
1176 char* __a_end = __a;
1177 unsigned __g[__num_get_base::__num_get_buf_sz];
1178 unsigned* __g_end = __g;
1179 unsigned __dc = 0;
1180 bool __in_units = true;
1181 char __exp = 'E';
1182 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001183 if (this->__stage2_float_loop(*__b, __in_units, __exp, __a, __a_end,
1184 __decimal_point, __thousands_sep,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001185 __grouping, __g, __g_end,
1186 __dc, __atoms))
1187 break;
1188 if (__grouping.size() != 0 && __in_units && __g_end-__g < __num_get_base::__num_get_buf_sz)
1189 *__g_end++ = __dc;
1190 // Stage 3
1191 __v = __num_get_float<long double>(__a, __a_end, __err);
1192 // Digit grouping checked
1193 __check_grouping(__grouping, __g, __g_end, __err);
1194 // EOF checked
1195 if (__b == __e)
1196 __err |= ios_base::eofbit;
1197 return __b;
1198}
1199
1200template <class _CharT, class _InputIterator>
1201_InputIterator
1202num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1203 ios_base& __iob,
1204 ios_base::iostate& __err,
1205 void*& __v) const
1206{
1207 // Stage 1
1208 int __base = 16;
1209 // Stage 2
1210 char_type __atoms[26];
1211 char_type __thousands_sep;
1212 string __grouping;
1213 use_facet<ctype<_CharT> >(__iob.getloc()).widen(__num_get_base::__src,
1214 __num_get_base::__src + 26, __atoms);
1215 char __a[__num_get_base::__num_get_buf_sz] = {0};
1216 char* __a_end = __a;
1217 unsigned __g[__num_get_base::__num_get_buf_sz];
1218 unsigned* __g_end = __g;
1219 unsigned __dc = 0;
1220 for (; __b != __e; ++__b)
Howard Hinnant324bb032010-08-22 00:02:43 +00001221 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
1222 __thousands_sep, __grouping,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001223 __g, __g_end, __atoms))
1224 break;
1225 // Stage 3
1226 __a[sizeof(__a)-1] = 0;
Howard Hinnantadff4892010-05-24 17:49:41 +00001227 if (__nolocale_sscanf(__a, "%p", &__v) != 1)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001228 __err = ios_base::failbit;
1229 // EOF checked
1230 if (__b == __e)
1231 __err |= ios_base::eofbit;
1232 return __b;
1233}
1234
1235extern template class num_get<char>;
1236extern template class num_get<wchar_t>;
1237
1238struct __num_put_base
1239{
1240protected:
1241 static void __format_int(char* __fmt, const char* __len, bool __signd,
1242 ios_base::fmtflags __flags);
1243 static bool __format_float(char* __fmt, const char* __len,
1244 ios_base::fmtflags __flags);
1245 static char* __identify_padding(char* __nb, char* __ne,
1246 const ios_base& __iob);
1247};
1248
1249template <class _CharT>
1250struct __num_put
1251 : protected __num_put_base
1252{
1253 static void __widen_and_group_int(char* __nb, char* __np, char* __ne,
1254 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1255 const locale& __loc);
1256 static void __widen_and_group_float(char* __nb, char* __np, char* __ne,
1257 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1258 const locale& __loc);
1259};
1260
1261template <class _CharT>
1262void
1263__num_put<_CharT>::__widen_and_group_int(char* __nb, char* __np, char* __ne,
1264 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1265 const locale& __loc)
1266{
1267 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> > (__loc);
1268 const numpunct<_CharT>& __npt = use_facet<numpunct<_CharT> >(__loc);
1269 string __grouping = __npt.grouping();
1270 if (__grouping.empty())
1271 {
1272 __ct.widen(__nb, __ne, __ob);
1273 __oe = __ob + (__ne - __nb);
1274 }
1275 else
1276 {
1277 __oe = __ob;
1278 char* __nf = __nb;
1279 if (*__nf == '-' || *__nf == '+')
1280 *__oe++ = __ct.widen(*__nf++);
1281 if (__ne - __nf >= 2 && __nf[0] == '0' && (__nf[1] == 'x' ||
1282 __nf[1] == 'X'))
1283 {
1284 *__oe++ = __ct.widen(*__nf++);
1285 *__oe++ = __ct.widen(*__nf++);
1286 }
1287 reverse(__nf, __ne);
1288 _CharT __thousands_sep = __npt.thousands_sep();
1289 unsigned __dc = 0;
1290 unsigned __dg = 0;
1291 for (char* __p = __nf; __p < __ne; ++__p)
1292 {
1293 if (static_cast<unsigned>(__grouping[__dg]) > 0 &&
1294 __dc == static_cast<unsigned>(__grouping[__dg]))
1295 {
1296 *__oe++ = __thousands_sep;
1297 __dc = 0;
1298 if (__dg < __grouping.size()-1)
1299 ++__dg;
1300 }
1301 *__oe++ = __ct.widen(*__p);
1302 ++__dc;
1303 }
1304 reverse(__ob + (__nf - __nb), __oe);
1305 }
1306 if (__np == __ne)
1307 __op = __oe;
1308 else
1309 __op = __ob + (__np - __nb);
1310}
1311
1312template <class _CharT>
1313void
1314__num_put<_CharT>::__widen_and_group_float(char* __nb, char* __np, char* __ne,
1315 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1316 const locale& __loc)
1317{
1318 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> > (__loc);
1319 const numpunct<_CharT>& __npt = use_facet<numpunct<_CharT> >(__loc);
1320 string __grouping = __npt.grouping();
1321 __oe = __ob;
1322 char* __nf = __nb;
1323 if (*__nf == '-' || *__nf == '+')
1324 *__oe++ = __ct.widen(*__nf++);
1325 char* __ns;
1326 if (__ne - __nf >= 2 && __nf[0] == '0' && (__nf[1] == 'x' ||
1327 __nf[1] == 'X'))
1328 {
1329 *__oe++ = __ct.widen(*__nf++);
1330 *__oe++ = __ct.widen(*__nf++);
1331 for (__ns = __nf; __ns < __ne; ++__ns)
Howard Hinnantadff4892010-05-24 17:49:41 +00001332 if (!__nolocale_isxdigit(*__ns))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001333 break;
1334 }
1335 else
1336 {
1337 for (__ns = __nf; __ns < __ne; ++__ns)
Howard Hinnantadff4892010-05-24 17:49:41 +00001338 if (!__nolocale_isdigit(*__ns))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001339 break;
1340 }
1341 if (__grouping.empty())
1342 {
1343 __ct.widen(__nf, __ns, __oe);
1344 __oe += __ns - __nf;
1345 }
1346 else
1347 {
1348 reverse(__nf, __ns);
1349 _CharT __thousands_sep = __npt.thousands_sep();
1350 unsigned __dc = 0;
1351 unsigned __dg = 0;
1352 for (char* __p = __nf; __p < __ns; ++__p)
1353 {
1354 if (__grouping[__dg] > 0 && __dc == static_cast<unsigned>(__grouping[__dg]))
1355 {
1356 *__oe++ = __thousands_sep;
1357 __dc = 0;
1358 if (__dg < __grouping.size()-1)
1359 ++__dg;
1360 }
1361 *__oe++ = __ct.widen(*__p);
1362 ++__dc;
1363 }
1364 reverse(__ob + (__nf - __nb), __oe);
1365 }
1366 for (__nf = __ns; __nf < __ne; ++__nf)
1367 {
1368 if (*__nf == '.')
1369 {
1370 *__oe++ = __npt.decimal_point();
1371 ++__nf;
1372 break;
1373 }
1374 else
1375 *__oe++ = __ct.widen(*__nf);
1376 }
1377 __ct.widen(__nf, __ne, __oe);
1378 __oe += __ne - __nf;
1379 if (__np == __ne)
1380 __op = __oe;
1381 else
1382 __op = __ob + (__np - __nb);
1383}
1384
1385extern template class __num_put<char>;
1386extern template class __num_put<wchar_t>;
1387
1388template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00001389class _LIBCPP_VISIBLE num_put
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001390 : public locale::facet,
1391 private __num_put<_CharT>
1392{
1393public:
1394 typedef _CharT char_type;
1395 typedef _OutputIterator iter_type;
1396
1397 _LIBCPP_ALWAYS_INLINE
1398 explicit num_put(size_t __refs = 0)
1399 : locale::facet(__refs) {}
1400
1401 _LIBCPP_ALWAYS_INLINE
1402 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1403 bool __v) const
1404 {
1405 return do_put(__s, __iob, __fl, __v);
1406 }
1407
1408 _LIBCPP_ALWAYS_INLINE
1409 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1410 long __v) const
1411 {
1412 return do_put(__s, __iob, __fl, __v);
1413 }
1414
1415 _LIBCPP_ALWAYS_INLINE
1416 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1417 long long __v) const
1418 {
1419 return do_put(__s, __iob, __fl, __v);
1420 }
1421
1422 _LIBCPP_ALWAYS_INLINE
1423 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1424 unsigned long __v) const
1425 {
1426 return do_put(__s, __iob, __fl, __v);
1427 }
1428
1429 _LIBCPP_ALWAYS_INLINE
1430 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1431 unsigned long long __v) const
1432 {
1433 return do_put(__s, __iob, __fl, __v);
1434 }
1435
1436 _LIBCPP_ALWAYS_INLINE
1437 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1438 double __v) const
1439 {
1440 return do_put(__s, __iob, __fl, __v);
1441 }
1442
1443 _LIBCPP_ALWAYS_INLINE
1444 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1445 long double __v) const
1446 {
1447 return do_put(__s, __iob, __fl, __v);
1448 }
1449
1450 _LIBCPP_ALWAYS_INLINE
1451 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1452 const void* __v) const
1453 {
1454 return do_put(__s, __iob, __fl, __v);
1455 }
1456
1457 static locale::id id;
1458
1459protected:
Howard Hinnant82894812010-09-22 16:48:34 +00001460 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001461 ~num_put() {}
1462
1463 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1464 bool __v) const;
1465 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1466 long __v) const;
1467 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1468 long long __v) const;
1469 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1470 unsigned long) const;
1471 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1472 unsigned long long) const;
1473 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1474 double __v) const;
1475 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1476 long double __v) const;
1477 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1478 const void* __v) const;
1479};
1480
1481template <class _CharT, class _OutputIterator>
1482locale::id
1483num_put<_CharT, _OutputIterator>::id;
1484
1485template <class _CharT, class _OutputIterator>
1486_LIBCPP_HIDDEN
1487_OutputIterator
1488__pad_and_output(_OutputIterator __s,
1489 const _CharT* __ob, const _CharT* __op, const _CharT* __oe,
1490 ios_base& __iob, _CharT __fl)
1491{
1492 streamsize __sz = __oe - __ob;
1493 streamsize __ns = __iob.width();
1494 if (__ns > __sz)
1495 __ns -= __sz;
1496 else
1497 __ns = 0;
1498 for (;__ob < __op; ++__ob, ++__s)
1499 *__s = *__ob;
1500 for (; __ns; --__ns, ++__s)
1501 *__s = __fl;
1502 for (; __ob < __oe; ++__ob, ++__s)
1503 *__s = *__ob;
1504 __iob.width(0);
1505 return __s;
1506}
1507
1508template <class _CharT, class _OutputIterator>
1509_OutputIterator
1510num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1511 char_type __fl, bool __v) const
1512{
1513 if ((__iob.flags() & ios_base::boolalpha) == 0)
1514 return do_put(__s, __iob, __fl, (unsigned long)__v);
1515 const numpunct<char_type>& __np = use_facet<numpunct<char_type> >(__iob.getloc());
1516 typedef typename numpunct<char_type>::string_type string_type;
1517 string_type __nm = __v ? __np.truename() : __np.falsename();
1518 for (typename string_type::iterator __i = __nm.begin(); __i != __nm.end(); ++__i, ++__s)
1519 *__s = *__i;
1520 return __s;
1521}
1522
1523template <class _CharT, class _OutputIterator>
1524_OutputIterator
1525num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1526 char_type __fl, long __v) const
1527{
1528 // Stage 1 - Get number in narrow char
1529 char __fmt[6] = {'%', 0};
1530 const char* __len = "l";
1531 this->__format_int(__fmt+1, __len, true, __iob.flags());
1532 const unsigned __nbuf = (numeric_limits<long>::digits / 3)
1533 + ((numeric_limits<long>::digits % 3) != 0)
1534 + 1;
1535 char __nar[__nbuf];
Howard Hinnantadff4892010-05-24 17:49:41 +00001536 int __nc = __nolocale_sprintf(__nar, __fmt, __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001537 char* __ne = __nar + __nc;
1538 char* __np = this->__identify_padding(__nar, __ne, __iob);
1539 // Stage 2 - Widen __nar while adding thousands separators
1540 char_type __o[2*(__nbuf-1) - 1];
1541 char_type* __op; // pad here
1542 char_type* __oe; // end of output
1543 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1544 // [__o, __oe) contains thousands_sep'd wide number
1545 // Stage 3 & 4
1546 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1547}
1548
1549template <class _CharT, class _OutputIterator>
1550_OutputIterator
1551num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1552 char_type __fl, long long __v) const
1553{
1554 // Stage 1 - Get number in narrow char
1555 char __fmt[8] = {'%', 0};
1556 const char* __len = "ll";
1557 this->__format_int(__fmt+1, __len, true, __iob.flags());
1558 const unsigned __nbuf = (numeric_limits<long long>::digits / 3)
1559 + ((numeric_limits<long long>::digits % 3) != 0)
1560 + 1;
1561 char __nar[__nbuf];
Howard Hinnantadff4892010-05-24 17:49:41 +00001562 int __nc = __nolocale_sprintf(__nar, __fmt, __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001563 char* __ne = __nar + __nc;
1564 char* __np = this->__identify_padding(__nar, __ne, __iob);
1565 // Stage 2 - Widen __nar while adding thousands separators
1566 char_type __o[2*(__nbuf-1) - 1];
1567 char_type* __op; // pad here
1568 char_type* __oe; // end of output
1569 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1570 // [__o, __oe) contains thousands_sep'd wide number
1571 // Stage 3 & 4
1572 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1573}
1574
1575template <class _CharT, class _OutputIterator>
1576_OutputIterator
1577num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1578 char_type __fl, unsigned long __v) const
1579{
1580 // Stage 1 - Get number in narrow char
1581 char __fmt[6] = {'%', 0};
1582 const char* __len = "l";
1583 this->__format_int(__fmt+1, __len, false, __iob.flags());
1584 const unsigned __nbuf = (numeric_limits<unsigned long>::digits / 3)
1585 + ((numeric_limits<unsigned long>::digits % 3) != 0)
1586 + 1;
1587 char __nar[__nbuf];
Howard Hinnantadff4892010-05-24 17:49:41 +00001588 int __nc = __nolocale_sprintf(__nar, __fmt, __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001589 char* __ne = __nar + __nc;
1590 char* __np = this->__identify_padding(__nar, __ne, __iob);
1591 // Stage 2 - Widen __nar while adding thousands separators
1592 char_type __o[2*(__nbuf-1) - 1];
1593 char_type* __op; // pad here
1594 char_type* __oe; // end of output
1595 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1596 // [__o, __oe) contains thousands_sep'd wide number
1597 // Stage 3 & 4
1598 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1599}
1600
1601template <class _CharT, class _OutputIterator>
1602_OutputIterator
1603num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1604 char_type __fl, unsigned long long __v) const
1605{
1606 // Stage 1 - Get number in narrow char
1607 char __fmt[8] = {'%', 0};
1608 const char* __len = "ll";
1609 this->__format_int(__fmt+1, __len, false, __iob.flags());
1610 const unsigned __nbuf = (numeric_limits<unsigned long long>::digits / 3)
1611 + ((numeric_limits<unsigned long long>::digits % 3) != 0)
1612 + 1;
1613 char __nar[__nbuf];
Howard Hinnantadff4892010-05-24 17:49:41 +00001614 int __nc = __nolocale_sprintf(__nar, __fmt, __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001615 char* __ne = __nar + __nc;
1616 char* __np = this->__identify_padding(__nar, __ne, __iob);
1617 // Stage 2 - Widen __nar while adding thousands separators
1618 char_type __o[2*(__nbuf-1) - 1];
1619 char_type* __op; // pad here
1620 char_type* __oe; // end of output
1621 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1622 // [__o, __oe) contains thousands_sep'd wide number
1623 // Stage 3 & 4
1624 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1625}
1626
1627template <class _CharT, class _OutputIterator>
1628_OutputIterator
1629num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1630 char_type __fl, double __v) const
1631{
1632 // Stage 1 - Get number in narrow char
1633 char __fmt[8] = {'%', 0};
1634 const char* __len = "";
1635 bool __specify_precision = this->__format_float(__fmt+1, __len, __iob.flags());
1636 const unsigned __nbuf = 30;
1637 char __nar[__nbuf];
1638 char* __nb = __nar;
1639 int __nc;
1640 if (__specify_precision)
Howard Hinnantadff4892010-05-24 17:49:41 +00001641 __nc = __nolocale_snprintf(__nb, __nbuf, __fmt,
1642 (int)__iob.precision(), __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001643 else
Howard Hinnantadff4892010-05-24 17:49:41 +00001644 __nc = __nolocale_snprintf(__nb, __nbuf, __fmt, __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001645 unique_ptr<char, void(*)(void*)> __nbh(0, free);
1646 if (__nc > static_cast<int>(__nbuf-1))
1647 {
1648 if (__specify_precision)
Howard Hinnantadff4892010-05-24 17:49:41 +00001649 __nc = __nolocale_asprintf(&__nb, __fmt, (int)__iob.precision(),
1650 __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001651 else
Howard Hinnantadff4892010-05-24 17:49:41 +00001652 __nc = __nolocale_asprintf(&__nb, __fmt, __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001653 if (__nb == 0)
1654 __throw_bad_alloc();
1655 __nbh.reset(__nb);
1656 }
1657 char* __ne = __nb + __nc;
1658 char* __np = this->__identify_padding(__nb, __ne, __iob);
1659 // Stage 2 - Widen __nar while adding thousands separators
1660 char_type __o[2*(__nbuf-1) - 1];
1661 char_type* __ob = __o;
1662 unique_ptr<char_type, void(*)(void*)> __obh(0, free);
1663 if (__nb != __nar)
1664 {
1665 __ob = (char_type*)malloc((2*__nc)*sizeof(char_type));
1666 if (__ob == 0)
1667 __throw_bad_alloc();
1668 __obh.reset(__ob);
1669 }
1670 char_type* __op; // pad here
1671 char_type* __oe; // end of output
1672 this->__widen_and_group_float(__nb, __np, __ne, __ob, __op, __oe, __iob.getloc());
1673 // [__o, __oe) contains thousands_sep'd wide number
1674 // Stage 3 & 4
1675 __s = __pad_and_output(__s, __ob, __op, __oe, __iob, __fl);
1676 return __s;
1677}
1678
1679template <class _CharT, class _OutputIterator>
1680_OutputIterator
1681num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1682 char_type __fl, long double __v) const
1683{
1684 // Stage 1 - Get number in narrow char
1685 char __fmt[8] = {'%', 0};
1686 const char* __len = "L";
1687 bool __specify_precision = this->__format_float(__fmt+1, __len, __iob.flags());
1688 const unsigned __nbuf = 30;
1689 char __nar[__nbuf];
1690 char* __nb = __nar;
1691 int __nc;
1692 if (__specify_precision)
Howard Hinnantadff4892010-05-24 17:49:41 +00001693 __nc = __nolocale_snprintf(__nb, __nbuf, __fmt,
1694 (int)__iob.precision(), __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001695 else
Howard Hinnantadff4892010-05-24 17:49:41 +00001696 __nc = __nolocale_snprintf(__nb, __nbuf, __fmt, __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001697 unique_ptr<char, void(*)(void*)> __nbh(0, free);
1698 if (__nc > static_cast<int>(__nbuf-1))
1699 {
1700 if (__specify_precision)
Howard Hinnantadff4892010-05-24 17:49:41 +00001701 __nc = __nolocale_asprintf(&__nb, __fmt, (int)__iob.precision(),
1702 __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001703 else
Howard Hinnantadff4892010-05-24 17:49:41 +00001704 __nc = __nolocale_asprintf(&__nb, __fmt, __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001705 if (__nb == 0)
1706 __throw_bad_alloc();
1707 __nbh.reset(__nb);
1708 }
1709 char* __ne = __nb + __nc;
1710 char* __np = this->__identify_padding(__nb, __ne, __iob);
1711 // Stage 2 - Widen __nar while adding thousands separators
1712 char_type __o[2*(__nbuf-1) - 1];
1713 char_type* __ob = __o;
1714 unique_ptr<char_type, void(*)(void*)> __obh(0, free);
1715 if (__nb != __nar)
1716 {
1717 __ob = (char_type*)malloc((2*__nc)*sizeof(char_type));
1718 if (__ob == 0)
1719 __throw_bad_alloc();
1720 __obh.reset(__ob);
1721 }
1722 char_type* __op; // pad here
1723 char_type* __oe; // end of output
1724 this->__widen_and_group_float(__nb, __np, __ne, __ob, __op, __oe, __iob.getloc());
1725 // [__o, __oe) contains thousands_sep'd wide number
1726 // Stage 3 & 4
1727 __s = __pad_and_output(__s, __ob, __op, __oe, __iob, __fl);
1728 return __s;
1729}
1730
1731template <class _CharT, class _OutputIterator>
1732_OutputIterator
1733num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1734 char_type __fl, const void* __v) const
1735{
1736 // Stage 1 - Get pointer in narrow char
1737 char __fmt[6] = "%p";
1738 const unsigned __nbuf = 20;
1739 char __nar[__nbuf];
Howard Hinnantadff4892010-05-24 17:49:41 +00001740 int __nc = __nolocale_sprintf(__nar, __fmt, __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001741 char* __ne = __nar + __nc;
1742 char* __np = this->__identify_padding(__nar, __ne, __iob);
1743 // Stage 2 - Widen __nar
1744 char_type __o[2*(__nbuf-1) - 1];
1745 char_type* __op; // pad here
1746 char_type* __oe; // end of output
1747 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
1748 __ct.widen(__nar, __ne, __o);
1749 __oe = __o + (__ne - __nar);
1750 if (__np == __ne)
1751 __op = __oe;
1752 else
1753 __op = __o + (__np - __nar);
1754 // [__o, __oe) contains wide number
1755 // Stage 3 & 4
1756 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1757}
1758
1759extern template class num_put<char>;
1760extern template class num_put<wchar_t>;
1761
1762template <class _CharT, class _InputIterator>
1763_LIBCPP_HIDDEN
1764int
1765__get_up_to_n_digits(_InputIterator& __b, _InputIterator __e,
1766 ios_base::iostate& __err, const ctype<_CharT>& __ct, int __n)
1767{
1768 // Precondition: __n >= 1
1769 if (__b == __e)
1770 {
1771 __err |= ios_base::eofbit | ios_base::failbit;
1772 return 0;
1773 }
1774 // get first digit
1775 _CharT __c = *__b;
1776 if (!__ct.is(ctype_base::digit, __c))
1777 {
1778 __err |= ios_base::failbit;
1779 return 0;
1780 }
1781 int __r = __ct.narrow(__c, 0) - '0';
1782 for (++__b, --__n; __b != __e && __n > 0; ++__b, --__n)
1783 {
1784 // get next digit
1785 __c = *__b;
1786 if (!__ct.is(ctype_base::digit, __c))
1787 return __r;
1788 __r = __r * 10 + __ct.narrow(__c, 0) - '0';
1789 }
1790 if (__b == __e)
1791 __err |= ios_base::eofbit;
1792 return __r;
1793}
1794
Howard Hinnant82894812010-09-22 16:48:34 +00001795class _LIBCPP_VISIBLE time_base
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001796{
1797public:
1798 enum dateorder {no_order, dmy, mdy, ymd, ydm};
1799};
1800
1801template <class _CharT>
Howard Hinnant2d72b1e2010-12-17 14:46:43 +00001802class __time_get_c_storage // purposefully not decorated
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001803{
1804protected:
1805 typedef basic_string<_CharT> string_type;
1806
1807 virtual const string_type* __weeks() const;
1808 virtual const string_type* __months() const;
1809 virtual const string_type* __am_pm() const;
1810 virtual const string_type& __c() const;
1811 virtual const string_type& __r() const;
1812 virtual const string_type& __x() const;
1813 virtual const string_type& __X() const;
1814};
1815
1816template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00001817class _LIBCPP_VISIBLE time_get
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001818 : public locale::facet,
1819 public time_base,
1820 private __time_get_c_storage<_CharT>
1821{
1822public:
1823 typedef _CharT char_type;
1824 typedef _InputIterator iter_type;
1825 typedef time_base::dateorder dateorder;
1826 typedef basic_string<char_type> string_type;
1827
1828 _LIBCPP_ALWAYS_INLINE
1829 explicit time_get(size_t __refs = 0)
1830 : locale::facet(__refs) {}
1831
1832 _LIBCPP_ALWAYS_INLINE
1833 dateorder date_order() const
1834 {
1835 return this->do_date_order();
1836 }
1837
1838 _LIBCPP_ALWAYS_INLINE
1839 iter_type get_time(iter_type __b, iter_type __e, ios_base& __iob,
1840 ios_base::iostate& __err, tm* __tm) const
1841 {
1842 return do_get_time(__b, __e, __iob, __err, __tm);
1843 }
1844
1845 _LIBCPP_ALWAYS_INLINE
1846 iter_type get_date(iter_type __b, iter_type __e, ios_base& __iob,
1847 ios_base::iostate& __err, tm* __tm) const
1848 {
1849 return do_get_date(__b, __e, __iob, __err, __tm);
1850 }
1851
1852 _LIBCPP_ALWAYS_INLINE
1853 iter_type get_weekday(iter_type __b, iter_type __e, ios_base& __iob,
1854 ios_base::iostate& __err, tm* __tm) const
1855 {
1856 return do_get_weekday(__b, __e, __iob, __err, __tm);
1857 }
1858
1859 _LIBCPP_ALWAYS_INLINE
1860 iter_type get_monthname(iter_type __b, iter_type __e, ios_base& __iob,
1861 ios_base::iostate& __err, tm* __tm) const
1862 {
1863 return do_get_monthname(__b, __e, __iob, __err, __tm);
1864 }
1865
1866 _LIBCPP_ALWAYS_INLINE
1867 iter_type get_year(iter_type __b, iter_type __e, ios_base& __iob,
1868 ios_base::iostate& __err, tm* __tm) const
1869 {
1870 return do_get_year(__b, __e, __iob, __err, __tm);
1871 }
1872
1873 _LIBCPP_ALWAYS_INLINE
1874 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
1875 ios_base::iostate& __err, tm *__tm,
1876 char __fmt, char __mod = 0) const
1877 {
1878 return do_get(__b, __e, __iob, __err, __tm, __fmt, __mod);
1879 }
1880
1881 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
1882 ios_base::iostate& __err, tm* __tm,
1883 const char_type* __fmtb, const char_type* __fmte) const;
1884
1885 static locale::id id;
1886
1887protected:
Howard Hinnant82894812010-09-22 16:48:34 +00001888 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001889 ~time_get() {}
1890
1891 virtual dateorder do_date_order() const;
1892 virtual iter_type do_get_time(iter_type __b, iter_type __e, ios_base& __iob,
1893 ios_base::iostate& __err, tm* __tm) const;
1894 virtual iter_type do_get_date(iter_type __b, iter_type __e, ios_base& __iob,
1895 ios_base::iostate& __err, tm* __tm) const;
1896 virtual iter_type do_get_weekday(iter_type __b, iter_type __e, ios_base& __iob,
1897 ios_base::iostate& __err, tm* __tm) const;
1898 virtual iter_type do_get_monthname(iter_type __b, iter_type __e, ios_base& __iob,
1899 ios_base::iostate& __err, tm* __tm) const;
1900 virtual iter_type do_get_year(iter_type __b, iter_type __e, ios_base& __iob,
1901 ios_base::iostate& __err, tm* __tm) const;
1902 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
1903 ios_base::iostate& __err, tm* __tm,
1904 char __fmt, char __mod) const;
1905private:
1906 void __get_white_space(iter_type& __b, iter_type __e,
1907 ios_base::iostate& __err, const ctype<char_type>& __ct) const;
1908 void __get_percent(iter_type& __b, iter_type __e, ios_base::iostate& __err,
1909 const ctype<char_type>& __ct) const;
1910
1911 void __get_weekdayname(int& __m,
1912 iter_type& __b, iter_type __e,
1913 ios_base::iostate& __err,
1914 const ctype<char_type>& __ct) const;
1915 void __get_monthname(int& __m,
1916 iter_type& __b, iter_type __e,
1917 ios_base::iostate& __err,
1918 const ctype<char_type>& __ct) const;
1919 void __get_day(int& __d,
1920 iter_type& __b, iter_type __e,
1921 ios_base::iostate& __err,
1922 const ctype<char_type>& __ct) const;
1923 void __get_month(int& __m,
1924 iter_type& __b, iter_type __e,
1925 ios_base::iostate& __err,
1926 const ctype<char_type>& __ct) const;
1927 void __get_year(int& __y,
1928 iter_type& __b, iter_type __e,
1929 ios_base::iostate& __err,
1930 const ctype<char_type>& __ct) const;
1931 void __get_year4(int& __y,
1932 iter_type& __b, iter_type __e,
1933 ios_base::iostate& __err,
1934 const ctype<char_type>& __ct) const;
1935 void __get_hour(int& __d,
1936 iter_type& __b, iter_type __e,
1937 ios_base::iostate& __err,
1938 const ctype<char_type>& __ct) const;
1939 void __get_12_hour(int& __h,
1940 iter_type& __b, iter_type __e,
1941 ios_base::iostate& __err,
1942 const ctype<char_type>& __ct) const;
1943 void __get_am_pm(int& __h,
1944 iter_type& __b, iter_type __e,
1945 ios_base::iostate& __err,
1946 const ctype<char_type>& __ct) const;
1947 void __get_minute(int& __m,
1948 iter_type& __b, iter_type __e,
1949 ios_base::iostate& __err,
1950 const ctype<char_type>& __ct) const;
1951 void __get_second(int& __s,
1952 iter_type& __b, iter_type __e,
1953 ios_base::iostate& __err,
1954 const ctype<char_type>& __ct) const;
1955 void __get_weekday(int& __w,
1956 iter_type& __b, iter_type __e,
1957 ios_base::iostate& __err,
1958 const ctype<char_type>& __ct) const;
1959 void __get_day_year_num(int& __w,
1960 iter_type& __b, iter_type __e,
1961 ios_base::iostate& __err,
1962 const ctype<char_type>& __ct) const;
1963};
1964
1965template <class _CharT, class _InputIterator>
1966locale::id
1967time_get<_CharT, _InputIterator>::id;
1968
1969// time_get primatives
1970
1971template <class _CharT, class _InputIterator>
1972void
1973time_get<_CharT, _InputIterator>::__get_weekdayname(int& __w,
1974 iter_type& __b, iter_type __e,
1975 ios_base::iostate& __err,
1976 const ctype<char_type>& __ct) const
1977{
1978 // Note: ignoring case comes from the POSIX strptime spec
1979 const string_type* __wk = this->__weeks();
1980 int __i = __scan_keyword(__b, __e, __wk, __wk+14, __ct, __err, false) - __wk;
1981 if (__i < 14)
1982 __w = __i % 7;
1983}
1984
1985template <class _CharT, class _InputIterator>
1986void
1987time_get<_CharT, _InputIterator>::__get_monthname(int& __m,
1988 iter_type& __b, iter_type __e,
1989 ios_base::iostate& __err,
1990 const ctype<char_type>& __ct) const
1991{
1992 // Note: ignoring case comes from the POSIX strptime spec
1993 const string_type* __month = this->__months();
1994 int __i = __scan_keyword(__b, __e, __month, __month+24, __ct, __err, false) - __month;
1995 if (__i < 24)
1996 __m = __i % 12;
1997}
1998
1999template <class _CharT, class _InputIterator>
2000void
2001time_get<_CharT, _InputIterator>::__get_day(int& __d,
2002 iter_type& __b, iter_type __e,
2003 ios_base::iostate& __err,
2004 const ctype<char_type>& __ct) const
2005{
2006 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2007 if (!(__err & ios_base::failbit) && 1 <= __t && __t <= 31)
2008 __d = __t;
2009 else
2010 __err |= ios_base::failbit;
2011}
2012
2013template <class _CharT, class _InputIterator>
2014void
2015time_get<_CharT, _InputIterator>::__get_month(int& __m,
2016 iter_type& __b, iter_type __e,
2017 ios_base::iostate& __err,
2018 const ctype<char_type>& __ct) const
2019{
2020 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2) - 1;
2021 if (!(__err & ios_base::failbit) && __t <= 11)
2022 __m = __t;
2023 else
2024 __err |= ios_base::failbit;
2025}
2026
2027template <class _CharT, class _InputIterator>
2028void
2029time_get<_CharT, _InputIterator>::__get_year(int& __y,
2030 iter_type& __b, iter_type __e,
2031 ios_base::iostate& __err,
2032 const ctype<char_type>& __ct) const
2033{
2034 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 4);
2035 if (!(__err & ios_base::failbit))
2036 {
2037 if (__t < 69)
2038 __t += 2000;
2039 else if (69 <= __t && __t <= 99)
2040 __t += 1900;
2041 __y = __t - 1900;
2042 }
2043}
2044
2045template <class _CharT, class _InputIterator>
2046void
2047time_get<_CharT, _InputIterator>::__get_year4(int& __y,
2048 iter_type& __b, iter_type __e,
2049 ios_base::iostate& __err,
2050 const ctype<char_type>& __ct) const
2051{
2052 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 4);
2053 if (!(__err & ios_base::failbit))
2054 __y = __t - 1900;
2055}
2056
2057template <class _CharT, class _InputIterator>
2058void
2059time_get<_CharT, _InputIterator>::__get_hour(int& __h,
2060 iter_type& __b, iter_type __e,
2061 ios_base::iostate& __err,
2062 const ctype<char_type>& __ct) const
2063{
2064 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2065 if (!(__err & ios_base::failbit) && __t <= 23)
2066 __h = __t;
2067 else
2068 __err |= ios_base::failbit;
2069}
2070
2071template <class _CharT, class _InputIterator>
2072void
2073time_get<_CharT, _InputIterator>::__get_12_hour(int& __h,
2074 iter_type& __b, iter_type __e,
2075 ios_base::iostate& __err,
2076 const ctype<char_type>& __ct) const
2077{
2078 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2079 if (!(__err & ios_base::failbit) && 1 <= __t && __t <= 12)
2080 __h = __t;
2081 else
2082 __err |= ios_base::failbit;
2083}
2084
2085template <class _CharT, class _InputIterator>
2086void
2087time_get<_CharT, _InputIterator>::__get_minute(int& __m,
2088 iter_type& __b, iter_type __e,
2089 ios_base::iostate& __err,
2090 const ctype<char_type>& __ct) const
2091{
2092 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2093 if (!(__err & ios_base::failbit) && __t <= 59)
2094 __m = __t;
2095 else
2096 __err |= ios_base::failbit;
2097}
2098
2099template <class _CharT, class _InputIterator>
2100void
2101time_get<_CharT, _InputIterator>::__get_second(int& __s,
2102 iter_type& __b, iter_type __e,
2103 ios_base::iostate& __err,
2104 const ctype<char_type>& __ct) const
2105{
2106 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2107 if (!(__err & ios_base::failbit) && __t <= 60)
2108 __s = __t;
2109 else
2110 __err |= ios_base::failbit;
2111}
2112
2113template <class _CharT, class _InputIterator>
2114void
2115time_get<_CharT, _InputIterator>::__get_weekday(int& __w,
2116 iter_type& __b, iter_type __e,
2117 ios_base::iostate& __err,
2118 const ctype<char_type>& __ct) const
2119{
2120 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 1);
2121 if (!(__err & ios_base::failbit) && __t <= 6)
2122 __w = __t;
2123 else
2124 __err |= ios_base::failbit;
2125}
2126
2127template <class _CharT, class _InputIterator>
2128void
2129time_get<_CharT, _InputIterator>::__get_day_year_num(int& __d,
2130 iter_type& __b, iter_type __e,
2131 ios_base::iostate& __err,
2132 const ctype<char_type>& __ct) const
2133{
2134 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 3);
2135 if (!(__err & ios_base::failbit) && __t <= 365)
2136 __d = __t;
2137 else
2138 __err |= ios_base::failbit;
2139}
2140
2141template <class _CharT, class _InputIterator>
2142void
2143time_get<_CharT, _InputIterator>::__get_white_space(iter_type& __b, iter_type __e,
2144 ios_base::iostate& __err,
2145 const ctype<char_type>& __ct) const
2146{
2147 for (; __b != __e && __ct.is(ctype_base::space, *__b); ++__b)
2148 ;
2149 if (__b == __e)
2150 __err |= ios_base::eofbit;
2151}
2152
2153template <class _CharT, class _InputIterator>
2154void
2155time_get<_CharT, _InputIterator>::__get_am_pm(int& __h,
2156 iter_type& __b, iter_type __e,
2157 ios_base::iostate& __err,
2158 const ctype<char_type>& __ct) const
2159{
2160 const string_type* __ap = this->__am_pm();
2161 if (__ap[0].size() + __ap[1].size() == 0)
2162 {
2163 __err |= ios_base::failbit;
2164 return;
2165 }
2166 int __i = __scan_keyword(__b, __e, __ap, __ap+2, __ct, __err, false) - __ap;
2167 if (__i == 0 && __h == 12)
2168 __h = 0;
2169 else if (__i == 1 && __h < 12)
2170 __h += 12;
2171}
2172
2173template <class _CharT, class _InputIterator>
2174void
2175time_get<_CharT, _InputIterator>::__get_percent(iter_type& __b, iter_type __e,
2176 ios_base::iostate& __err,
2177 const ctype<char_type>& __ct) const
2178{
2179 if (__b == __e)
2180 {
2181 __err |= ios_base::eofbit | ios_base::failbit;
2182 return;
2183 }
2184 if (__ct.narrow(*__b, 0) != '%')
2185 __err |= ios_base::failbit;
2186 else if(++__b == __e)
2187 __err |= ios_base::eofbit;
2188}
2189
2190// time_get end primatives
2191
2192template <class _CharT, class _InputIterator>
2193_InputIterator
2194time_get<_CharT, _InputIterator>::get(iter_type __b, iter_type __e,
2195 ios_base& __iob,
2196 ios_base::iostate& __err, tm* __tm,
2197 const char_type* __fmtb, const char_type* __fmte) const
2198{
2199 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2200 __err = ios_base::goodbit;
2201 while (__fmtb != __fmte && __err == ios_base::goodbit)
2202 {
2203 if (__b == __e)
2204 {
2205 __err = ios_base::failbit;
2206 break;
2207 }
2208 if (__ct.narrow(*__fmtb, 0) == '%')
2209 {
2210 if (++__fmtb == __fmte)
2211 {
2212 __err = ios_base::failbit;
2213 break;
2214 }
2215 char __cmd = __ct.narrow(*__fmtb, 0);
2216 char __opt = '\0';
2217 if (__cmd == 'E' || __cmd == '0')
2218 {
2219 if (++__fmtb == __fmte)
2220 {
2221 __err = ios_base::failbit;
2222 break;
2223 }
2224 __opt = __cmd;
2225 __cmd = __ct.narrow(*__fmtb, 0);
2226 }
2227 __b = do_get(__b, __e, __iob, __err, __tm, __cmd, __opt);
2228 ++__fmtb;
2229 }
2230 else if (__ct.is(ctype_base::space, *__fmtb))
2231 {
2232 for (++__fmtb; __fmtb != __fmte && __ct.is(ctype_base::space, *__fmtb); ++__fmtb)
2233 ;
2234 for ( ; __b != __e && __ct.is(ctype_base::space, *__b); ++__b)
2235 ;
2236 }
2237 else if (__ct.toupper(*__b) == __ct.toupper(*__fmtb))
2238 {
2239 ++__b;
2240 ++__fmtb;
2241 }
2242 else
2243 __err = ios_base::failbit;
2244 }
2245 if (__b == __e)
2246 __err |= ios_base::eofbit;
2247 return __b;
2248}
2249
2250template <class _CharT, class _InputIterator>
2251typename time_get<_CharT, _InputIterator>::dateorder
2252time_get<_CharT, _InputIterator>::do_date_order() const
2253{
2254 return mdy;
2255}
2256
2257template <class _CharT, class _InputIterator>
2258_InputIterator
2259time_get<_CharT, _InputIterator>::do_get_time(iter_type __b, iter_type __e,
2260 ios_base& __iob,
2261 ios_base::iostate& __err,
2262 tm* __tm) const
2263{
2264 const char_type __fmt[] = {'%', 'H', ':', '%', 'M', ':', '%', 'S'};
2265 return get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2266}
2267
2268template <class _CharT, class _InputIterator>
2269_InputIterator
2270time_get<_CharT, _InputIterator>::do_get_date(iter_type __b, iter_type __e,
2271 ios_base& __iob,
2272 ios_base::iostate& __err,
2273 tm* __tm) const
2274{
2275 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2276 const string_type& __fmt = this->__x();
2277 return get(__b, __e, __iob, __err, __tm, __fmt.data(), __fmt.data() + __fmt.size());
2278}
2279
2280template <class _CharT, class _InputIterator>
2281_InputIterator
2282time_get<_CharT, _InputIterator>::do_get_weekday(iter_type __b, iter_type __e,
2283 ios_base& __iob,
2284 ios_base::iostate& __err,
2285 tm* __tm) const
2286{
2287 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2288 __get_weekdayname(__tm->tm_wday, __b, __e, __err, __ct);
2289 return __b;
2290}
2291
2292template <class _CharT, class _InputIterator>
2293_InputIterator
2294time_get<_CharT, _InputIterator>::do_get_monthname(iter_type __b, iter_type __e,
2295 ios_base& __iob,
2296 ios_base::iostate& __err,
2297 tm* __tm) const
2298{
2299 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2300 __get_monthname(__tm->tm_mon, __b, __e, __err, __ct);
2301 return __b;
2302}
2303
2304template <class _CharT, class _InputIterator>
2305_InputIterator
2306time_get<_CharT, _InputIterator>::do_get_year(iter_type __b, iter_type __e,
2307 ios_base& __iob,
2308 ios_base::iostate& __err,
2309 tm* __tm) const
2310{
2311 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2312 __get_year(__tm->tm_year, __b, __e, __err, __ct);
2313 return __b;
2314}
2315
2316template <class _CharT, class _InputIterator>
2317_InputIterator
2318time_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
2319 ios_base& __iob,
2320 ios_base::iostate& __err, tm* __tm,
2321 char __fmt, char) const
2322{
2323 __err = ios_base::goodbit;
2324 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2325 switch (__fmt)
2326 {
2327 case 'a':
2328 case 'A':
2329 __get_weekdayname(__tm->tm_wday, __b, __e, __err, __ct);
2330 break;
2331 case 'b':
2332 case 'B':
2333 case 'h':
2334 __get_monthname(__tm->tm_mon, __b, __e, __err, __ct);
2335 break;
2336 case 'c':
2337 {
2338 const string_type& __fmt = this->__c();
2339 __b = get(__b, __e, __iob, __err, __tm, __fmt.data(), __fmt.data() + __fmt.size());
2340 }
2341 break;
2342 case 'd':
2343 case 'e':
2344 __get_day(__tm->tm_mday, __b, __e, __err, __ct);
2345 break;
2346 case 'D':
2347 {
2348 const char_type __fmt[] = {'%', 'm', '/', '%', 'd', '/', '%', 'y'};
2349 __b = get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2350 }
2351 break;
Howard Hinnant506b3642011-04-10 17:54:14 +00002352 case 'F':
2353 {
2354 const char_type __fmt[] = {'%', 'Y', '-', '%', 'm', '-', '%', 'd'};
2355 __b = get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2356 }
2357 break;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002358 case 'H':
2359 __get_hour(__tm->tm_hour, __b, __e, __err, __ct);
2360 break;
2361 case 'I':
2362 __get_12_hour(__tm->tm_hour, __b, __e, __err, __ct);
2363 break;
2364 case 'j':
2365 __get_day_year_num(__tm->tm_yday, __b, __e, __err, __ct);
2366 break;
2367 case 'm':
2368 __get_month(__tm->tm_mon, __b, __e, __err, __ct);
2369 break;
2370 case 'M':
2371 __get_minute(__tm->tm_min, __b, __e, __err, __ct);
2372 break;
2373 case 'n':
2374 case 't':
2375 __get_white_space(__b, __e, __err, __ct);
2376 break;
2377 case 'p':
2378 __get_am_pm(__tm->tm_hour, __b, __e, __err, __ct);
2379 break;
2380 case 'r':
2381 {
2382 const char_type __fmt[] = {'%', 'I', ':', '%', 'M', ':', '%', 'S', ' ', '%', 'p'};
2383 __b = get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2384 }
2385 break;
2386 case 'R':
2387 {
2388 const char_type __fmt[] = {'%', 'H', ':', '%', 'M'};
2389 __b = get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2390 }
2391 break;
2392 case 'S':
2393 __get_second(__tm->tm_sec, __b, __e, __err, __ct);
2394 break;
2395 case 'T':
2396 {
2397 const char_type __fmt[] = {'%', 'H', ':', '%', 'M', ':', '%', 'S'};
2398 __b = get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2399 }
2400 break;
2401 case 'w':
2402 __get_weekday(__tm->tm_wday, __b, __e, __err, __ct);
2403 break;
2404 case 'x':
2405 return do_get_date(__b, __e, __iob, __err, __tm);
2406 case 'X':
2407 {
2408 const string_type& __fmt = this->__X();
2409 __b = get(__b, __e, __iob, __err, __tm, __fmt.data(), __fmt.data() + __fmt.size());
2410 }
2411 break;
2412 case 'y':
2413 __get_year(__tm->tm_year, __b, __e, __err, __ct);
2414 break;
2415 case 'Y':
2416 __get_year4(__tm->tm_year, __b, __e, __err, __ct);
2417 break;
2418 case '%':
2419 __get_percent(__b, __e, __err, __ct);
2420 break;
2421 default:
2422 __err |= ios_base::failbit;
2423 }
2424 return __b;
2425}
2426
2427extern template class time_get<char>;
2428extern template class time_get<wchar_t>;
2429
2430class __time_get
2431{
2432protected:
2433 locale_t __loc_;
2434
2435 __time_get(const char* __nm);
2436 __time_get(const string& __nm);
2437 ~__time_get();
2438};
2439
2440template <class _CharT>
2441class __time_get_storage
2442 : public __time_get
2443{
2444protected:
2445 typedef basic_string<_CharT> string_type;
2446
2447 string_type __weeks_[14];
2448 string_type __months_[24];
2449 string_type __am_pm_[2];
2450 string_type __c_;
2451 string_type __r_;
2452 string_type __x_;
2453 string_type __X_;
2454
2455 explicit __time_get_storage(const char* __nm);
2456 explicit __time_get_storage(const string& __nm);
2457
2458 _LIBCPP_ALWAYS_INLINE ~__time_get_storage() {}
2459
2460 time_base::dateorder __do_date_order() const;
2461
2462private:
2463 void init(const ctype<_CharT>&);
2464 string_type __analyze(char __fmt, const ctype<_CharT>&);
2465};
2466
2467template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00002468class _LIBCPP_VISIBLE time_get_byname
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002469 : public time_get<_CharT, _InputIterator>,
2470 private __time_get_storage<_CharT>
2471{
2472public:
2473 typedef time_base::dateorder dateorder;
2474 typedef _InputIterator iter_type;
2475 typedef _CharT char_type;
2476 typedef basic_string<char_type> string_type;
2477
Howard Hinnant82894812010-09-22 16:48:34 +00002478 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002479 explicit time_get_byname(const char* __nm, size_t __refs = 0)
2480 : time_get<_CharT, _InputIterator>(__refs),
2481 __time_get_storage<_CharT>(__nm) {}
Howard Hinnant82894812010-09-22 16:48:34 +00002482 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002483 explicit time_get_byname(const string& __nm, size_t __refs = 0)
2484 : time_get<_CharT, _InputIterator>(__refs),
2485 __time_get_storage<_CharT>(__nm) {}
2486
2487protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002488 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002489 ~time_get_byname() {}
2490
Howard Hinnant82894812010-09-22 16:48:34 +00002491 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002492 virtual dateorder do_date_order() const {return this->__do_date_order();}
2493private:
Howard Hinnant82894812010-09-22 16:48:34 +00002494 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002495 virtual const string_type* __weeks() const {return this->__weeks_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002496 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002497 virtual const string_type* __months() const {return this->__months_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002498 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002499 virtual const string_type* __am_pm() const {return this->__am_pm_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002500 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002501 virtual const string_type& __c() const {return this->__c_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002502 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002503 virtual const string_type& __r() const {return this->__r_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002504 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002505 virtual const string_type& __x() const {return this->__x_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002506 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002507 virtual const string_type& __X() const {return this->__X_;}
2508};
2509
2510extern template class time_get_byname<char>;
2511extern template class time_get_byname<wchar_t>;
2512
2513class __time_put
2514{
2515 locale_t __loc_;
2516protected:
2517 _LIBCPP_ALWAYS_INLINE __time_put() : __loc_(0) {}
2518 __time_put(const char* __nm);
2519 __time_put(const string& __nm);
2520 ~__time_put();
2521 void __do_put(char* __nb, char*& __ne, const tm* __tm,
2522 char __fmt, char __mod) const;
2523 void __do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
2524 char __fmt, char __mod) const;
2525};
2526
2527template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00002528class _LIBCPP_VISIBLE time_put
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002529 : public locale::facet,
2530 private __time_put
2531{
2532public:
2533 typedef _CharT char_type;
2534 typedef _OutputIterator iter_type;
2535
2536 _LIBCPP_ALWAYS_INLINE
2537 explicit time_put(size_t __refs = 0)
2538 : locale::facet(__refs) {}
2539
2540 iter_type put(iter_type __s, ios_base& __iob, char_type __fl, const tm* __tm,
2541 const char_type* __pb, const char_type* __pe) const;
2542
2543 _LIBCPP_ALWAYS_INLINE
2544 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
2545 const tm* __tm, char __fmt, char __mod = 0) const
2546 {
2547 return do_put(__s, __iob, __fl, __tm, __fmt, __mod);
2548 }
2549
2550 static locale::id id;
2551
2552protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002553 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002554 ~time_put() {}
2555 virtual iter_type do_put(iter_type __s, ios_base&, char_type, const tm* __tm,
2556 char __fmt, char __mod) const;
2557
Howard Hinnant82894812010-09-22 16:48:34 +00002558 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002559 explicit time_put(const char* __nm, size_t __refs)
2560 : locale::facet(__refs),
2561 __time_put(__nm) {}
Howard Hinnant82894812010-09-22 16:48:34 +00002562 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002563 explicit time_put(const string& __nm, size_t __refs)
2564 : locale::facet(__refs),
2565 __time_put(__nm) {}
2566};
2567
2568template <class _CharT, class _OutputIterator>
2569locale::id
2570time_put<_CharT, _OutputIterator>::id;
2571
2572template <class _CharT, class _OutputIterator>
2573_OutputIterator
2574time_put<_CharT, _OutputIterator>::put(iter_type __s, ios_base& __iob,
2575 char_type __fl, const tm* __tm,
2576 const char_type* __pb,
2577 const char_type* __pe) const
2578{
2579 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2580 for (; __pb != __pe; ++__pb)
2581 {
2582 if (__ct.narrow(*__pb, 0) == '%')
2583 {
2584 if (++__pb == __pe)
2585 {
2586 *__s++ = __pb[-1];
2587 break;
2588 }
2589 char __mod = 0;
2590 char __fmt = __ct.narrow(*__pb, 0);
2591 if (__fmt == 'E' || __fmt == 'O')
2592 {
2593 if (++__pb == __pe)
2594 {
2595 *__s++ = __pb[-2];
2596 *__s++ = __pb[-1];
2597 break;
2598 }
2599 __mod = __fmt;
2600 __fmt = __ct.narrow(*__pb, 0);
2601 }
2602 __s = do_put(__s, __iob, __fl, __tm, __fmt, __mod);
2603 }
2604 else
2605 *__s++ = *__pb;
2606 }
2607 return __s;
2608}
2609
2610template <class _CharT, class _OutputIterator>
2611_OutputIterator
2612time_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
2613 char_type, const tm* __tm,
2614 char __fmt, char __mod) const
2615{
2616 char_type __nar[100];
2617 char_type* __nb = __nar;
2618 char_type* __ne = __nb + 100;
2619 __do_put(__nb, __ne, __tm, __fmt, __mod);
Howard Hinnant0949eed2011-06-30 21:18:19 +00002620 return _VSTD::copy(__nb, __ne, __s);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002621}
2622
2623extern template class time_put<char>;
2624extern template class time_put<wchar_t>;
2625
2626template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00002627class _LIBCPP_VISIBLE time_put_byname
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002628 : public time_put<_CharT, _OutputIterator>
2629{
2630public:
2631 _LIBCPP_ALWAYS_INLINE
2632 explicit time_put_byname(const char* __nm, size_t __refs = 0)
2633 : time_put<_CharT, _OutputIterator>(__nm, __refs) {}
2634
2635 _LIBCPP_ALWAYS_INLINE
2636 explicit time_put_byname(const string& __nm, size_t __refs = 0)
2637 : time_put<_CharT, _OutputIterator>(__nm, __refs) {}
2638
2639protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002640 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002641 ~time_put_byname() {}
2642};
2643
2644extern template class time_put_byname<char>;
2645extern template class time_put_byname<wchar_t>;
2646
2647// money_base
2648
Howard Hinnant82894812010-09-22 16:48:34 +00002649class _LIBCPP_VISIBLE money_base
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002650{
2651public:
2652 enum part {none, space, symbol, sign, value};
2653 struct pattern {char field[4];};
2654
2655 _LIBCPP_ALWAYS_INLINE money_base() {}
2656};
2657
2658// moneypunct
2659
2660template <class _CharT, bool _International = false>
Howard Hinnant82894812010-09-22 16:48:34 +00002661class _LIBCPP_VISIBLE moneypunct
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002662 : public locale::facet,
2663 public money_base
2664{
2665public:
2666 typedef _CharT char_type;
2667 typedef basic_string<char_type> string_type;
2668
Howard Hinnant82894812010-09-22 16:48:34 +00002669 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002670 explicit moneypunct(size_t __refs = 0)
2671 : locale::facet(__refs) {}
2672
2673 _LIBCPP_ALWAYS_INLINE char_type decimal_point() const {return do_decimal_point();}
2674 _LIBCPP_ALWAYS_INLINE char_type thousands_sep() const {return do_thousands_sep();}
2675 _LIBCPP_ALWAYS_INLINE string grouping() const {return do_grouping();}
2676 _LIBCPP_ALWAYS_INLINE string_type curr_symbol() const {return do_curr_symbol();}
2677 _LIBCPP_ALWAYS_INLINE string_type positive_sign() const {return do_positive_sign();}
2678 _LIBCPP_ALWAYS_INLINE string_type negative_sign() const {return do_negative_sign();}
2679 _LIBCPP_ALWAYS_INLINE int frac_digits() const {return do_frac_digits();}
2680 _LIBCPP_ALWAYS_INLINE pattern pos_format() const {return do_pos_format();}
2681 _LIBCPP_ALWAYS_INLINE pattern neg_format() const {return do_neg_format();}
2682
2683 static locale::id id;
2684 static const bool intl = _International;
2685
2686protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002687 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002688 ~moneypunct() {}
2689
2690 virtual char_type do_decimal_point() const {return numeric_limits<char_type>::max();}
2691 virtual char_type do_thousands_sep() const {return numeric_limits<char_type>::max();}
2692 virtual string do_grouping() const {return string();}
2693 virtual string_type do_curr_symbol() const {return string_type();}
2694 virtual string_type do_positive_sign() const {return string_type();}
2695 virtual string_type do_negative_sign() const {return string_type(1, '-');}
2696 virtual int do_frac_digits() const {return 0;}
2697 virtual pattern do_pos_format() const
2698 {pattern __p = {symbol, sign, none, value}; return __p;}
2699 virtual pattern do_neg_format() const
2700 {pattern __p = {symbol, sign, none, value}; return __p;}
2701};
2702
2703template <class _CharT, bool _International>
2704locale::id
2705moneypunct<_CharT, _International>::id;
2706
2707extern template class moneypunct<char, false>;
2708extern template class moneypunct<char, true>;
2709extern template class moneypunct<wchar_t, false>;
2710extern template class moneypunct<wchar_t, true>;
2711
2712// moneypunct_byname
2713
2714template <class _CharT, bool _International = false>
Howard Hinnant82894812010-09-22 16:48:34 +00002715class _LIBCPP_VISIBLE moneypunct_byname
2716 : public moneypunct<_CharT, _International>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002717{
2718public:
2719 typedef money_base::pattern pattern;
2720 typedef _CharT char_type;
2721 typedef basic_string<char_type> string_type;
2722
2723 _LIBCPP_ALWAYS_INLINE
2724 explicit moneypunct_byname(const char* __nm, size_t __refs = 0)
2725 : moneypunct<_CharT, _International>(__refs) {init(__nm);}
2726
2727 _LIBCPP_ALWAYS_INLINE
2728 explicit moneypunct_byname(const string& __nm, size_t __refs = 0)
2729 : moneypunct<_CharT, _International>(__refs) {init(__nm.c_str());}
2730
2731protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002732 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002733 ~moneypunct_byname() {}
2734
2735 virtual char_type do_decimal_point() const {return __decimal_point_;}
2736 virtual char_type do_thousands_sep() const {return __thousands_sep_;}
2737 virtual string do_grouping() const {return __grouping_;}
2738 virtual string_type do_curr_symbol() const {return __curr_symbol_;}
2739 virtual string_type do_positive_sign() const {return __positive_sign_;}
2740 virtual string_type do_negative_sign() const {return __negative_sign_;}
2741 virtual int do_frac_digits() const {return __frac_digits_;}
2742 virtual pattern do_pos_format() const {return __pos_format_;}
2743 virtual pattern do_neg_format() const {return __neg_format_;}
2744
2745private:
2746 char_type __decimal_point_;
2747 char_type __thousands_sep_;
2748 string __grouping_;
2749 string_type __curr_symbol_;
2750 string_type __positive_sign_;
2751 string_type __negative_sign_;
2752 int __frac_digits_;
2753 pattern __pos_format_;
2754 pattern __neg_format_;
2755
2756 void init(const char*);
2757};
2758
2759template<> void moneypunct_byname<char, false>::init(const char*);
2760template<> void moneypunct_byname<char, true>::init(const char*);
2761template<> void moneypunct_byname<wchar_t, false>::init(const char*);
2762template<> void moneypunct_byname<wchar_t, true>::init(const char*);
2763
2764extern template class moneypunct_byname<char, false>;
2765extern template class moneypunct_byname<char, true>;
2766extern template class moneypunct_byname<wchar_t, false>;
2767extern template class moneypunct_byname<wchar_t, true>;
2768
2769// money_get
2770
2771template <class _CharT>
2772class __money_get
2773{
2774protected:
2775 typedef _CharT char_type;
2776 typedef basic_string<char_type> string_type;
2777
2778 _LIBCPP_ALWAYS_INLINE __money_get() {}
2779
2780 static void __gather_info(bool __intl, const locale& __loc,
2781 money_base::pattern& __pat, char_type& __dp,
2782 char_type& __ts, string& __grp,
2783 string_type& __sym, string_type& __psn,
2784 string_type& __nsn, int& __fd);
2785};
2786
2787template <class _CharT>
2788void
2789__money_get<_CharT>::__gather_info(bool __intl, const locale& __loc,
2790 money_base::pattern& __pat, char_type& __dp,
2791 char_type& __ts, string& __grp,
2792 string_type& __sym, string_type& __psn,
2793 string_type& __nsn, int& __fd)
2794{
2795 if (__intl)
2796 {
2797 const moneypunct<char_type, true>& __mp =
2798 use_facet<moneypunct<char_type, true> >(__loc);
2799 __pat = __mp.neg_format();
2800 __nsn = __mp.negative_sign();
2801 __psn = __mp.positive_sign();
2802 __dp = __mp.decimal_point();
2803 __ts = __mp.thousands_sep();
2804 __grp = __mp.grouping();
2805 __sym = __mp.curr_symbol();
2806 __fd = __mp.frac_digits();
2807 }
2808 else
2809 {
2810 const moneypunct<char_type, false>& __mp =
2811 use_facet<moneypunct<char_type, false> >(__loc);
2812 __pat = __mp.neg_format();
2813 __nsn = __mp.negative_sign();
2814 __psn = __mp.positive_sign();
2815 __dp = __mp.decimal_point();
2816 __ts = __mp.thousands_sep();
2817 __grp = __mp.grouping();
2818 __sym = __mp.curr_symbol();
2819 __fd = __mp.frac_digits();
2820 }
2821}
2822
2823extern template class __money_get<char>;
2824extern template class __money_get<wchar_t>;
2825
2826template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00002827class _LIBCPP_VISIBLE money_get
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002828 : public locale::facet,
2829 private __money_get<_CharT>
2830{
2831public:
2832 typedef _CharT char_type;
2833 typedef _InputIterator iter_type;
2834 typedef basic_string<char_type> string_type;
2835
2836 _LIBCPP_ALWAYS_INLINE
2837 explicit money_get(size_t __refs = 0)
2838 : locale::facet(__refs) {}
2839
2840 _LIBCPP_ALWAYS_INLINE
2841 iter_type get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob,
2842 ios_base::iostate& __err, long double& __v) const
2843 {
2844 return do_get(__b, __e, __intl, __iob, __err, __v);
2845 }
2846
2847 _LIBCPP_ALWAYS_INLINE
2848 iter_type get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob,
2849 ios_base::iostate& __err, string_type& __v) const
2850 {
2851 return do_get(__b, __e, __intl, __iob, __err, __v);
2852 }
2853
2854 static locale::id id;
2855
2856protected:
2857
Howard Hinnant82894812010-09-22 16:48:34 +00002858 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002859 ~money_get() {}
Howard Hinnant324bb032010-08-22 00:02:43 +00002860
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002861 virtual iter_type do_get(iter_type __b, iter_type __e, bool __intl,
2862 ios_base& __iob, ios_base::iostate& __err,
2863 long double& __v) const;
2864 virtual iter_type do_get(iter_type __b, iter_type __e, bool __intl,
2865 ios_base& __iob, ios_base::iostate& __err,
2866 string_type& __v) const;
2867
2868private:
2869 static bool __do_get(iter_type& __b, iter_type __e,
2870 bool __intl, const locale& __loc,
2871 ios_base::fmtflags __flags, ios_base::iostate& __err,
2872 bool& __neg, const ctype<char_type>& __ct,
2873 unique_ptr<char_type, void(*)(void*)>& __wb,
2874 char_type*& __wn, char_type* __we);
2875};
2876
2877template <class _CharT, class _InputIterator>
2878locale::id
2879money_get<_CharT, _InputIterator>::id;
2880
2881void __do_nothing(void*);
2882
2883template <class _Tp>
2884_LIBCPP_HIDDEN
2885void
2886__double_or_nothing(unique_ptr<_Tp, void(*)(void*)>& __b, _Tp*& __n, _Tp*& __e)
2887{
2888 bool __owns = __b.get_deleter() != __do_nothing;
2889 size_t __cur_cap = (__e-__b.get()) * sizeof(_Tp);
2890 size_t __new_cap = __cur_cap < numeric_limits<size_t>::max() / 2 ?
2891 2 * __cur_cap : numeric_limits<size_t>::max();
2892 size_t __n_off = __n - __b.get();
2893 _Tp* __t = (_Tp*)realloc(__owns ? __b.get() : 0, __new_cap);
2894 if (__t == 0)
2895 __throw_bad_alloc();
2896 if (__owns)
2897 __b.release();
2898 __b = unique_ptr<_Tp, void(*)(void*)>(__t, free);
2899 __new_cap /= sizeof(_Tp);
2900 __n = __b.get() + __n_off;
2901 __e = __b.get() + __new_cap;
2902}
2903
2904// true == success
2905template <class _CharT, class _InputIterator>
2906bool
2907money_get<_CharT, _InputIterator>::__do_get(iter_type& __b, iter_type __e,
2908 bool __intl, const locale& __loc,
2909 ios_base::fmtflags __flags,
2910 ios_base::iostate& __err,
2911 bool& __neg,
2912 const ctype<char_type>& __ct,
2913 unique_ptr<char_type, void(*)(void*)>& __wb,
2914 char_type*& __wn, char_type* __we)
2915{
2916 const unsigned __bz = 100;
2917 unsigned __gbuf[__bz];
2918 unique_ptr<unsigned, void(*)(void*)> __gb(__gbuf, __do_nothing);
2919 unsigned* __gn = __gb.get();
2920 unsigned* __ge = __gn + __bz;
2921 money_base::pattern __pat;
2922 char_type __dp;
2923 char_type __ts;
2924 string __grp;
2925 string_type __sym;
2926 string_type __psn;
2927 string_type __nsn;
2928 int __fd;
2929 __money_get<_CharT>::__gather_info(__intl, __loc, __pat, __dp, __ts, __grp,
2930 __sym, __psn, __nsn, __fd);
2931 const string_type* __trailing_sign = 0;
2932 __wn = __wb.get();
2933 for (unsigned __p = 0; __p < 4 && __b != __e; ++__p)
2934 {
2935 switch (__pat.field[__p])
2936 {
2937 case money_base::space:
2938 if (__p != 3)
2939 {
2940 if (__ct.is(ctype_base::space, *__b))
2941 ++__b;
2942 else
2943 {
2944 __err |= ios_base::failbit;
2945 return false;
2946 }
2947 }
Howard Hinnant324bb032010-08-22 00:02:43 +00002948 // drop through
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002949 case money_base::none:
2950 if (__p != 3)
2951 {
2952 while (__b != __e && __ct.is(ctype_base::space, *__b))
2953 ++__b;
2954 }
2955 break;
2956 case money_base::sign:
2957 if (__psn.size() + __nsn.size() > 0)
2958 {
2959 if (__psn.size() == 0 || __nsn.size() == 0)
2960 { // sign is optional
2961 if (__psn.size() > 0)
2962 { // __nsn.size() == 0
2963 if (*__b == __psn[0])
2964 {
2965 ++__b;
2966 if (__psn.size() > 1)
2967 __trailing_sign = &__psn;
2968 }
2969 else
2970 __neg = true;
2971 }
2972 else if (*__b == __nsn[0]) // __nsn.size() > 0 && __psn.size() == 0
2973 {
2974 ++__b;
2975 __neg = true;
2976 if (__nsn.size() > 1)
2977 __trailing_sign = &__nsn;
2978 }
2979 }
2980 else // sign is required
2981 {
2982 if (*__b == __psn[0])
2983 {
2984 ++__b;
2985 if (__psn.size() > 1)
2986 __trailing_sign = &__psn;
2987 }
2988 else if (*__b == __nsn[0])
2989 {
2990 ++__b;
2991 __neg = true;
2992 if (__nsn.size() > 1)
2993 __trailing_sign = &__nsn;
2994 }
2995 else
2996 {
2997 __err |= ios_base::failbit;
2998 return false;
2999 }
3000 }
3001 }
3002 break;
3003 case money_base::symbol:
3004 {
3005 bool __more_needed = __trailing_sign ||
3006 (__p < 2) ||
3007 (__p == 2 && __pat.field[3] != static_cast<char>(money_base::none));
3008 bool __sb = __flags & ios_base::showbase;
3009 if (__sb || __more_needed)
3010 {
3011 ios_base::iostate __et = ios_base::goodbit;
3012 string_type* __k = __scan_keyword(__b, __e, &__sym, &__sym+1,
3013 __ct, __et);
3014 if (__sb && __k != &__sym)
3015 {
3016 __err |= ios_base::failbit;
3017 return false;
3018 }
3019 }
3020 }
3021 break;
3022 case money_base::value:
3023 {
3024 unsigned __ng = 0;
3025 for (; __b != __e; ++__b)
3026 {
3027 char_type __c = *__b;
3028 if (__ct.is(ctype_base::digit, __c))
3029 {
3030 if (__wn == __we)
3031 __double_or_nothing(__wb, __wn, __we);
3032 *__wn++ = __c;
3033 ++__ng;
3034 }
3035 else if (__grp.size() > 0 && __ng > 0 && __c == __ts)
3036 {
3037 if (__gn == __ge)
3038 __double_or_nothing(__gb, __gn, __ge);
3039 *__gn++ = __ng;
3040 __ng = 0;
3041 }
3042 else
3043 break;
3044 }
3045 if (__gb.get() != __gn && __ng > 0)
3046 {
3047 if (__gn == __ge)
3048 __double_or_nothing(__gb, __gn, __ge);
3049 *__gn++ = __ng;
3050 }
3051 if (__fd > 0)
3052 {
3053 if (__b == __e || *__b != __dp)
3054 {
3055 __err |= ios_base::failbit;
3056 return false;
3057 }
3058 for (++__b; __fd > 0; --__fd, ++__b)
3059 {
3060 if (__b == __e || !__ct.is(ctype_base::digit, *__b))
3061 {
3062 __err |= ios_base::failbit;
3063 return false;
3064 }
3065 if (__wn == __we)
3066 __double_or_nothing(__wb, __wn, __we);
3067 *__wn++ = *__b;
3068 }
3069 }
3070 if (__wn == __wb.get())
3071 {
3072 __err |= ios_base::failbit;
3073 return false;
3074 }
3075 }
3076 break;
3077 }
3078 }
3079 if (__trailing_sign)
3080 {
3081 for (unsigned __i = 1; __i < __trailing_sign->size(); ++__i, ++__b)
3082 {
3083 if (__b == __e || *__b != (*__trailing_sign)[__i])
3084 {
3085 __err |= ios_base::failbit;
3086 return false;
3087 }
3088 }
3089 }
3090 if (__gb.get() != __gn)
3091 {
3092 ios_base::iostate __et = ios_base::goodbit;
3093 __check_grouping(__grp, __gb.get(), __gn, __et);
3094 if (__et)
3095 {
3096 __err |= ios_base::failbit;
3097 return false;
3098 }
3099 }
3100 return true;
3101}
3102
3103template <class _CharT, class _InputIterator>
3104_InputIterator
3105money_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
3106 bool __intl, ios_base& __iob,
3107 ios_base::iostate& __err,
3108 long double& __v) const
3109{
3110 const unsigned __bz = 100;
3111 char_type __wbuf[__bz];
3112 unique_ptr<char_type, void(*)(void*)> __wb(__wbuf, __do_nothing);
3113 char_type* __wn;
3114 char_type* __we = __wbuf + __bz;
3115 locale __loc = __iob.getloc();
3116 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3117 bool __neg = false;
3118 if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct,
3119 __wb, __wn, __we))
3120 {
3121 const char __src[] = "0123456789";
3122 char_type __atoms[sizeof(__src)-1];
3123 __ct.widen(__src, __src + (sizeof(__src)-1), __atoms);
3124 char __nbuf[__bz];
3125 char* __nc = __nbuf;
3126 unique_ptr<char, void(*)(void*)> __h(0, free);
3127 if (__wn - __wb.get() > __bz-2)
3128 {
3129 __h.reset((char*)malloc(__wn - __wb.get() + 2));
3130 if (__h.get() == 0)
3131 __throw_bad_alloc();
3132 __nc = __h.get();
3133 }
3134 if (__neg)
3135 *__nc++ = '-';
3136 for (const char_type* __w = __wb.get(); __w < __wn; ++__w, ++__nc)
3137 *__nc = __src[find(__atoms, __atoms+sizeof(__atoms), *__w) - __atoms];
3138 *__nc = char();
3139 if (sscanf(__nbuf, "%Lf", &__v) != 1)
3140 __throw_runtime_error("money_get error");
3141 }
3142 if (__b == __e)
3143 __err |= ios_base::eofbit;
3144 return __b;
3145}
3146
3147template <class _CharT, class _InputIterator>
3148_InputIterator
3149money_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
3150 bool __intl, ios_base& __iob,
3151 ios_base::iostate& __err,
3152 string_type& __v) const
3153{
3154 const unsigned __bz = 100;
3155 char_type __wbuf[__bz];
3156 unique_ptr<char_type, void(*)(void*)> __wb(__wbuf, __do_nothing);
3157 char_type* __wn;
3158 char_type* __we = __wbuf + __bz;
3159 locale __loc = __iob.getloc();
3160 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3161 bool __neg = false;
3162 if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct,
3163 __wb, __wn, __we))
3164 {
3165 __v.clear();
3166 if (__neg)
3167 __v.push_back(__ct.widen('-'));
3168 char_type __z = __ct.widen('0');
3169 char_type* __w;
3170 for (__w = __wb.get(); __w < __wn-1; ++__w)
3171 if (*__w != __z)
3172 break;
3173 __v.append(__w, __wn);
3174 }
3175 if (__b == __e)
3176 __err |= ios_base::eofbit;
3177 return __b;
3178}
3179
3180extern template class money_get<char>;
3181extern template class money_get<wchar_t>;
3182
3183// money_put
3184
3185template <class _CharT>
3186class __money_put
3187{
3188protected:
3189 typedef _CharT char_type;
3190 typedef basic_string<char_type> string_type;
3191
3192 _LIBCPP_ALWAYS_INLINE __money_put() {}
3193
3194 static void __gather_info(bool __intl, bool __neg, const locale& __loc,
3195 money_base::pattern& __pat, char_type& __dp,
3196 char_type& __ts, string& __grp,
3197 string_type& __sym, string_type& __sn,
3198 int& __fd);
3199 static void __format(char_type* __mb, char_type*& __mi, char_type*& __me,
3200 ios_base::fmtflags __flags,
3201 const char_type* __db, const char_type* __de,
3202 const ctype<char_type>& __ct, bool __neg,
3203 const money_base::pattern& __pat, char_type __dp,
3204 char_type __ts, const string& __grp,
3205 const string_type& __sym, const string_type& __sn,
3206 int __fd);
3207};
3208
3209template <class _CharT>
3210void
3211__money_put<_CharT>::__gather_info(bool __intl, bool __neg, const locale& __loc,
3212 money_base::pattern& __pat, char_type& __dp,
3213 char_type& __ts, string& __grp,
3214 string_type& __sym, string_type& __sn,
3215 int& __fd)
3216{
3217 if (__intl)
3218 {
3219 const moneypunct<char_type, true>& __mp =
3220 use_facet<moneypunct<char_type, true> >(__loc);
3221 if (__neg)
3222 {
3223 __pat = __mp.neg_format();
3224 __sn = __mp.negative_sign();
3225 }
3226 else
3227 {
3228 __pat = __mp.pos_format();
3229 __sn = __mp.positive_sign();
3230 }
3231 __dp = __mp.decimal_point();
3232 __ts = __mp.thousands_sep();
3233 __grp = __mp.grouping();
3234 __sym = __mp.curr_symbol();
3235 __fd = __mp.frac_digits();
3236 }
3237 else
3238 {
3239 const moneypunct<char_type, false>& __mp =
3240 use_facet<moneypunct<char_type, false> >(__loc);
3241 if (__neg)
3242 {
3243 __pat = __mp.neg_format();
3244 __sn = __mp.negative_sign();
3245 }
3246 else
3247 {
3248 __pat = __mp.pos_format();
3249 __sn = __mp.positive_sign();
3250 }
3251 __dp = __mp.decimal_point();
3252 __ts = __mp.thousands_sep();
3253 __grp = __mp.grouping();
3254 __sym = __mp.curr_symbol();
3255 __fd = __mp.frac_digits();
3256 }
3257}
3258
3259template <class _CharT>
3260void
3261__money_put<_CharT>::__format(char_type* __mb, char_type*& __mi, char_type*& __me,
3262 ios_base::fmtflags __flags,
3263 const char_type* __db, const char_type* __de,
3264 const ctype<char_type>& __ct, bool __neg,
3265 const money_base::pattern& __pat, char_type __dp,
3266 char_type __ts, const string& __grp,
3267 const string_type& __sym, const string_type& __sn,
3268 int __fd)
3269{
3270 __me = __mb;
3271 for (unsigned __p = 0; __p < 4; ++__p)
3272 {
3273 switch (__pat.field[__p])
3274 {
3275 case money_base::none:
3276 __mi = __me;
3277 break;
3278 case money_base::space:
3279 __mi = __me;
3280 *__me++ = __ct.widen(' ');
3281 break;
3282 case money_base::sign:
3283 if (!__sn.empty())
3284 *__me++ = __sn[0];
3285 break;
3286 case money_base::symbol:
3287 if (!__sym.empty() && (__flags & ios_base::showbase))
Howard Hinnant0949eed2011-06-30 21:18:19 +00003288 __me = _VSTD::copy(__sym.begin(), __sym.end(), __me);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003289 break;
3290 case money_base::value:
3291 {
3292 // remember start of value so we can reverse it
3293 char_type* __t = __me;
3294 // find beginning of digits
3295 if (__neg)
3296 ++__db;
3297 // find end of digits
3298 const char_type* __d;
3299 for (__d = __db; __d < __de; ++__d)
3300 if (!__ct.is(ctype_base::digit, *__d))
3301 break;
3302 // print fractional part
3303 if (__fd > 0)
3304 {
3305 int __f;
3306 for (__f = __fd; __d > __db && __f > 0; --__f)
3307 *__me++ = *--__d;
3308 char_type __z = __f > 0 ? __ct.widen('0') : char_type();
3309 for (; __f > 0; --__f)
3310 *__me++ = __z;
3311 *__me++ = __dp;
3312 }
3313 // print units part
3314 if (__d == __db)
3315 {
3316 *__me++ = __ct.widen('0');
3317 }
3318 else
3319 {
3320 unsigned __ng = 0;
3321 unsigned __ig = 0;
3322 unsigned __gl = __grp.empty() ? numeric_limits<unsigned>::max()
3323 : static_cast<unsigned>(__grp[__ig]);
3324 while (__d != __db)
3325 {
3326 if (__ng == __gl)
3327 {
3328 *__me++ = __ts;
3329 __ng = 0;
3330 if (++__ig < __grp.size())
3331 __gl = __grp[__ig] == numeric_limits<char>::max() ?
3332 numeric_limits<unsigned>::max() :
3333 static_cast<unsigned>(__grp[__ig]);
3334 }
3335 *__me++ = *--__d;
3336 ++__ng;
3337 }
3338 }
3339 // reverse it
3340 reverse(__t, __me);
3341 }
3342 break;
3343 }
3344 }
3345 // print rest of sign, if any
3346 if (__sn.size() > 1)
Howard Hinnant0949eed2011-06-30 21:18:19 +00003347 __me = _VSTD::copy(__sn.begin()+1, __sn.end(), __me);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003348 // set alignment
3349 if ((__flags & ios_base::adjustfield) == ios_base::left)
3350 __mi = __me;
3351 else if ((__flags & ios_base::adjustfield) != ios_base::internal)
3352 __mi = __mb;
3353}
3354
3355extern template class __money_put<char>;
3356extern template class __money_put<wchar_t>;
3357
3358template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:34 +00003359class _LIBCPP_VISIBLE money_put
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003360 : public locale::facet,
3361 private __money_put<_CharT>
3362{
3363public:
3364 typedef _CharT char_type;
3365 typedef _OutputIterator iter_type;
3366 typedef basic_string<char_type> string_type;
3367
3368 _LIBCPP_ALWAYS_INLINE
3369 explicit money_put(size_t __refs = 0)
3370 : locale::facet(__refs) {}
3371
3372 _LIBCPP_ALWAYS_INLINE
3373 iter_type put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl,
3374 long double __units) const
3375 {
3376 return do_put(__s, __intl, __iob, __fl, __units);
3377 }
3378
3379 _LIBCPP_ALWAYS_INLINE
3380 iter_type put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl,
3381 const string_type& __digits) const
3382 {
3383 return do_put(__s, __intl, __iob, __fl, __digits);
3384 }
3385
3386 static locale::id id;
3387
3388protected:
Howard Hinnant82894812010-09-22 16:48:34 +00003389 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003390 ~money_put() {}
3391
3392 virtual iter_type do_put(iter_type __s, bool __intl, ios_base& __iob,
3393 char_type __fl, long double __units) const;
3394 virtual iter_type do_put(iter_type __s, bool __intl, ios_base& __iob,
3395 char_type __fl, const string_type& __digits) const;
3396};
3397
3398template <class _CharT, class _OutputIterator>
3399locale::id
3400money_put<_CharT, _OutputIterator>::id;
3401
3402template <class _CharT, class _OutputIterator>
3403_OutputIterator
3404money_put<_CharT, _OutputIterator>::do_put(iter_type __s, bool __intl,
3405 ios_base& __iob, char_type __fl,
3406 long double __units) const
3407{
3408 // convert to char
3409 const size_t __bs = 100;
3410 char __buf[__bs];
3411 char* __bb = __buf;
3412 char_type __digits[__bs];
3413 char_type* __db = __digits;
3414 size_t __n = snprintf(__bb, __bs, "%.0Lf", __units);
3415 unique_ptr<char, void(*)(void*)> __hn(0, free);
3416 unique_ptr<char_type, void(*)(void*)> __hd(0, free);
3417 // secure memory for digit storage
3418 if (__n > __bs-1)
3419 {
Howard Hinnantadff4892010-05-24 17:49:41 +00003420 __n = __nolocale_asprintf(&__bb, "%.0Lf", __units);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003421 if (__bb == 0)
3422 __throw_bad_alloc();
3423 __hn.reset(__bb);
3424 __hd.reset((char_type*)malloc(__n * sizeof(char_type)));
3425 if (__hd == 0)
3426 __throw_bad_alloc();
3427 __db = __hd.get();
3428 }
3429 // gather info
3430 locale __loc = __iob.getloc();
3431 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3432 __ct.widen(__bb, __bb + __n, __db);
3433 bool __neg = __n > 0 && __bb[0] == '-';
3434 money_base::pattern __pat;
3435 char_type __dp;
3436 char_type __ts;
3437 string __grp;
3438 string_type __sym;
3439 string_type __sn;
3440 int __fd;
3441 this->__gather_info(__intl, __neg, __loc, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3442 // secure memory for formatting
3443 char_type __mbuf[__bs];
3444 char_type* __mb = __mbuf;
3445 unique_ptr<char_type, void(*)(void*)> __hw(0, free);
3446 size_t __exn = static_cast<int>(__n) > __fd ?
3447 (__n - __fd) * 2 + __sn.size() + __sym.size() + __fd + 1
3448 : __sn.size() + __sym.size() + __fd + 2;
3449 if (__exn > __bs)
3450 {
3451 __hw.reset((char_type*)malloc(__exn * sizeof(char_type)));
3452 __mb = __hw.get();
3453 if (__mb == 0)
3454 __throw_bad_alloc();
3455 }
3456 // format
3457 char_type* __mi;
3458 char_type* __me;
3459 this->__format(__mb, __mi, __me, __iob.flags(),
3460 __db, __db + __n, __ct,
3461 __neg, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3462 return __pad_and_output(__s, __mb, __mi, __me, __iob, __fl);
3463}
3464
3465template <class _CharT, class _OutputIterator>
3466_OutputIterator
3467money_put<_CharT, _OutputIterator>::do_put(iter_type __s, bool __intl,
3468 ios_base& __iob, char_type __fl,
3469 const string_type& __digits) const
3470{
3471 // gather info
3472 locale __loc = __iob.getloc();
3473 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3474 bool __neg = __digits.size() > 0 && __digits[0] == __ct.widen('-');
3475 money_base::pattern __pat;
3476 char_type __dp;
3477 char_type __ts;
3478 string __grp;
3479 string_type __sym;
3480 string_type __sn;
3481 int __fd;
3482 this->__gather_info(__intl, __neg, __loc, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3483 // secure memory for formatting
3484 char_type __mbuf[100];
3485 char_type* __mb = __mbuf;
3486 unique_ptr<char_type, void(*)(void*)> __h(0, free);
3487 size_t __exn = __digits.size() > __fd ?
3488 (__digits.size() - __fd) * 2 + __sn.size() + __sym.size() + __fd + 1
3489 : __sn.size() + __sym.size() + __fd + 2;
3490 if (__exn > 100)
3491 {
3492 __h.reset((char_type*)malloc(__exn * sizeof(char_type)));
3493 __mb = __h.get();
3494 if (__mb == 0)
3495 __throw_bad_alloc();
3496 }
3497 // format
3498 char_type* __mi;
3499 char_type* __me;
3500 this->__format(__mb, __mi, __me, __iob.flags(),
3501 __digits.data(), __digits.data() + __digits.size(), __ct,
3502 __neg, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3503 return __pad_and_output(__s, __mb, __mi, __me, __iob, __fl);
3504}
3505
3506extern template class money_put<char>;
3507extern template class money_put<wchar_t>;
3508
3509// messages
3510
Howard Hinnant82894812010-09-22 16:48:34 +00003511class _LIBCPP_VISIBLE messages_base
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003512{
3513public:
Howard Hinnantb2080c72011-02-25 00:51:08 +00003514 typedef ptrdiff_t catalog;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003515
3516 _LIBCPP_ALWAYS_INLINE messages_base() {}
3517};
3518
3519template <class _CharT>
Howard Hinnant82894812010-09-22 16:48:34 +00003520class _LIBCPP_VISIBLE messages
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003521 : public locale::facet,
3522 public messages_base
3523{
3524public:
3525 typedef _CharT char_type;
3526 typedef basic_string<_CharT> string_type;
3527
3528 _LIBCPP_ALWAYS_INLINE
3529 explicit messages(size_t __refs = 0)
3530 : locale::facet(__refs) {}
3531
3532 _LIBCPP_ALWAYS_INLINE
3533 catalog open(const basic_string<char>& __nm, const locale& __loc) const
3534 {
3535 return do_open(__nm, __loc);
3536 }
3537
3538 _LIBCPP_ALWAYS_INLINE
3539 string_type get(catalog __c, int __set, int __msgid,
3540 const string_type& __dflt) const
3541 {
3542 return do_get(__c, __set, __msgid, __dflt);
3543 }
3544
3545 _LIBCPP_ALWAYS_INLINE
3546 void close(catalog __c) const
3547 {
3548 do_close(__c);
3549 }
3550
3551 static locale::id id;
3552
3553protected:
Howard Hinnant82894812010-09-22 16:48:34 +00003554 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003555 ~messages() {}
3556
3557 virtual catalog do_open(const basic_string<char>&, const locale&) const;
3558 virtual string_type do_get(catalog, int __set, int __msgid,
3559 const string_type& __dflt) const;
3560 virtual void do_close(catalog) const;
3561};
3562
3563template <class _CharT>
3564locale::id
3565messages<_CharT>::id;
3566
3567template <class _CharT>
3568typename messages<_CharT>::catalog
3569messages<_CharT>::do_open(const basic_string<char>& __nm, const locale&) const
3570{
Howard Hinnantb2080c72011-02-25 00:51:08 +00003571 catalog __cat = reinterpret_cast<catalog>(catopen(__nm.c_str(), NL_CAT_LOCALE));
3572 if (__cat != -1)
3573 __cat = static_cast<catalog>((static_cast<size_t>(__cat) >> 1));
3574 return __cat;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003575}
3576
3577template <class _CharT>
3578typename messages<_CharT>::string_type
3579messages<_CharT>::do_get(catalog __c, int __set, int __msgid,
3580 const string_type& __dflt) const
3581{
3582 string __ndflt;
3583 __narrow_to_utf8<sizeof(char_type)*__CHAR_BIT__>()(back_inserter(__ndflt),
3584 __dflt.c_str(),
3585 __dflt.c_str() + __dflt.size());
Howard Hinnantb2080c72011-02-25 00:51:08 +00003586 if (__c != -1)
3587 __c <<= 1;
3588 nl_catd __cat = reinterpret_cast<nl_catd>(__c);
3589 char* __n = catgets(__cat, __set, __msgid, __ndflt.c_str());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003590 string_type __w;
3591 __widen_from_utf8<sizeof(char_type)*__CHAR_BIT__>()(back_inserter(__w),
3592 __n, __n + strlen(__n));
3593 return __w;
3594}
3595
3596template <class _CharT>
3597void
3598messages<_CharT>::do_close(catalog __c) const
3599{
Howard Hinnantb2080c72011-02-25 00:51:08 +00003600 if (__c != -1)
3601 __c <<= 1;
3602 nl_catd __cat = reinterpret_cast<nl_catd>(__c);
3603 catclose(__cat);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003604}
3605
3606extern template class messages<char>;
3607extern template class messages<wchar_t>;
3608
3609template <class _CharT>
Howard Hinnant82894812010-09-22 16:48:34 +00003610class _LIBCPP_VISIBLE messages_byname
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003611 : public messages<_CharT>
3612{
3613public:
3614 typedef messages_base::catalog catalog;
3615 typedef basic_string<_CharT> string_type;
3616
3617 _LIBCPP_ALWAYS_INLINE
3618 explicit messages_byname(const char*, size_t __refs = 0)
3619 : messages<_CharT>(__refs) {}
3620
3621 _LIBCPP_ALWAYS_INLINE
3622 explicit messages_byname(const string&, size_t __refs = 0)
3623 : messages<_CharT>(__refs) {}
3624
3625protected:
Howard Hinnant82894812010-09-22 16:48:34 +00003626 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003627 ~messages_byname() {}
3628};
3629
3630extern template class messages_byname<char>;
3631extern template class messages_byname<wchar_t>;
3632
Howard Hinnantd23b4642010-05-31 20:58:54 +00003633template<class _Codecvt, class _Elem = wchar_t,
3634 class _Wide_alloc = allocator<_Elem>,
3635 class _Byte_alloc = allocator<char> >
Howard Hinnant82894812010-09-22 16:48:34 +00003636class _LIBCPP_VISIBLE wstring_convert
Howard Hinnantd23b4642010-05-31 20:58:54 +00003637{
3638public:
3639 typedef basic_string<char, char_traits<char>, _Byte_alloc> byte_string;
3640 typedef basic_string<_Elem, char_traits<_Elem>, _Wide_alloc> wide_string;
3641 typedef typename _Codecvt::state_type state_type;
3642 typedef typename wide_string::traits_type::int_type int_type;
3643
3644private:
3645 byte_string __byte_err_string_;
3646 wide_string __wide_err_string_;
3647 _Codecvt* __cvtptr_;
3648 state_type __cvtstate_;
3649 size_t __cvtcount_;
3650
3651 wstring_convert(const wstring_convert& __wc);
3652 wstring_convert& operator=(const wstring_convert& __wc);
3653public:
3654 wstring_convert(_Codecvt* __pcvt = new _Codecvt);
3655 wstring_convert(_Codecvt* __pcvt, state_type __state);
3656 wstring_convert(const byte_string& __byte_err,
3657 const wide_string& __wide_err = wide_string());
Howard Hinnant73d21a42010-09-04 23:28:19 +00003658#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantd23b4642010-05-31 20:58:54 +00003659 wstring_convert(wstring_convert&& __wc);
3660#endif
3661 ~wstring_convert();
3662
Howard Hinnant82894812010-09-22 16:48:34 +00003663 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003664 wide_string from_bytes(char __byte)
3665 {return from_bytes(&__byte, &__byte+1);}
Howard Hinnant82894812010-09-22 16:48:34 +00003666 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003667 wide_string from_bytes(const char* __ptr)
3668 {return from_bytes(__ptr, __ptr + char_traits<char>::length(__ptr));}
Howard Hinnant82894812010-09-22 16:48:34 +00003669 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003670 wide_string from_bytes(const byte_string& __str)
3671 {return from_bytes(__str.data(), __str.data() + __str.size());}
3672 wide_string from_bytes(const char* __first, const char* __last);
3673
Howard Hinnant82894812010-09-22 16:48:34 +00003674 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003675 byte_string to_bytes(_Elem __wchar)
3676 {return to_bytes(&__wchar, &__wchar+1);}
Howard Hinnant82894812010-09-22 16:48:34 +00003677 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003678 byte_string to_bytes(const _Elem* __wptr)
3679 {return to_bytes(__wptr, __wptr + char_traits<_Elem>::length(__wptr));}
Howard Hinnant82894812010-09-22 16:48:34 +00003680 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003681 byte_string to_bytes(const wide_string& __wstr)
3682 {return to_bytes(__wstr.data(), __wstr.data() + __wstr.size());}
3683 byte_string to_bytes(const _Elem* __first, const _Elem* __last);
3684
Howard Hinnant82894812010-09-22 16:48:34 +00003685 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003686 size_t converted() const {return __cvtcount_;}
Howard Hinnant82894812010-09-22 16:48:34 +00003687 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003688 state_type state() const {return __cvtstate_;}
3689};
3690
3691template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Howard Hinnant82894812010-09-22 16:48:34 +00003692inline _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003693wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3694 wstring_convert(_Codecvt* __pcvt)
3695 : __cvtptr_(__pcvt), __cvtstate_(), __cvtcount_(0)
3696{
3697}
3698
3699template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Howard Hinnant82894812010-09-22 16:48:34 +00003700inline _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003701wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3702 wstring_convert(_Codecvt* __pcvt, state_type __state)
3703 : __cvtptr_(__pcvt), __cvtstate_(__state), __cvtcount_(0)
3704{
3705}
3706
3707template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3708wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3709 wstring_convert(const byte_string& __byte_err, const wide_string& __wide_err)
3710 : __byte_err_string_(__byte_err), __wide_err_string_(__wide_err),
3711 __cvtstate_(), __cvtcount_(0)
3712{
3713 __cvtptr_ = new _Codecvt;
3714}
3715
Howard Hinnant73d21a42010-09-04 23:28:19 +00003716#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantd23b4642010-05-31 20:58:54 +00003717
3718template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Howard Hinnant82894812010-09-22 16:48:34 +00003719inline _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003720wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3721 wstring_convert(wstring_convert&& __wc)
Howard Hinnant0949eed2011-06-30 21:18:19 +00003722 : __byte_err_string_(_VSTD::move(__wc.__byte_err_string_)),
3723 __wide_err_string_(_VSTD::move(__wc.__wide_err_string_)),
Howard Hinnantd23b4642010-05-31 20:58:54 +00003724 __cvtptr_(__wc.__cvtptr_),
3725 __cvtstate_(__wc.__cvtstate_), __cvtcount_(__wc.__cvtstate_)
3726{
3727 __wc.__cvtptr_ = nullptr;
3728}
3729
Howard Hinnantbfd55302010-09-04 23:46:48 +00003730#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantd23b4642010-05-31 20:58:54 +00003731
3732template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3733wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::~wstring_convert()
3734{
3735 delete __cvtptr_;
3736}
3737
3738template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3739typename wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::wide_string
3740wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3741 from_bytes(const char* __frm, const char* __frm_end)
3742{
3743 __cvtcount_ = 0;
3744 if (__cvtptr_ != nullptr)
3745 {
3746 wide_string __ws(2*(__frm_end - __frm), _Elem());
3747 __ws.resize(__ws.capacity());
3748 codecvt_base::result __r = codecvt_base::ok;
3749 state_type __st = __cvtstate_;
3750 if (__frm != __frm_end)
3751 {
3752 _Elem* __to = &__ws[0];
3753 _Elem* __to_end = __to + __ws.size();
3754 const char* __frm_nxt;
3755 do
3756 {
3757 _Elem* __to_nxt;
3758 __r = __cvtptr_->in(__st, __frm, __frm_end, __frm_nxt,
3759 __to, __to_end, __to_nxt);
3760 __cvtcount_ += __frm_nxt - __frm;
3761 if (__frm_nxt == __frm)
3762 {
3763 __r = codecvt_base::error;
3764 }
3765 else if (__r == codecvt_base::noconv)
3766 {
3767 __ws.resize(__to - &__ws[0]);
3768 // This only gets executed if _Elem is char
3769 __ws.append((const _Elem*)__frm, (const _Elem*)__frm_end);
3770 __frm = __frm_nxt;
3771 __r = codecvt_base::ok;
3772 }
3773 else if (__r == codecvt_base::ok)
3774 {
3775 __ws.resize(__to_nxt - &__ws[0]);
3776 __frm = __frm_nxt;
3777 }
3778 else if (__r == codecvt_base::partial)
3779 {
3780 ptrdiff_t __s = __to_nxt - &__ws[0];
3781 __ws.resize(2 * __s);
3782 __to = &__ws[0] + __s;
3783 __to_end = &__ws[0] + __ws.size();
3784 __frm = __frm_nxt;
3785 }
3786 } while (__r == codecvt_base::partial && __frm_nxt < __frm_end);
3787 }
3788 if (__r == codecvt_base::ok)
3789 return __ws;
3790 }
Howard Hinnantd4444702010-08-11 17:04:31 +00003791#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00003792 if (__wide_err_string_.empty())
3793 throw range_error("wstring_convert: from_bytes error");
Howard Hinnant324bb032010-08-22 00:02:43 +00003794#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00003795 return __wide_err_string_;
3796}
3797
3798template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3799typename wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::byte_string
3800wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3801 to_bytes(const _Elem* __frm, const _Elem* __frm_end)
3802{
3803 __cvtcount_ = 0;
3804 if (__cvtptr_ != nullptr)
3805 {
3806 byte_string __bs(2*(__frm_end - __frm), char());
3807 __bs.resize(__bs.capacity());
3808 codecvt_base::result __r = codecvt_base::ok;
3809 state_type __st = __cvtstate_;
3810 if (__frm != __frm_end)
3811 {
3812 char* __to = &__bs[0];
3813 char* __to_end = __to + __bs.size();
3814 const _Elem* __frm_nxt;
3815 do
3816 {
3817 char* __to_nxt;
3818 __r = __cvtptr_->out(__st, __frm, __frm_end, __frm_nxt,
3819 __to, __to_end, __to_nxt);
3820 __cvtcount_ += __frm_nxt - __frm;
3821 if (__frm_nxt == __frm)
3822 {
3823 __r = codecvt_base::error;
3824 }
3825 else if (__r == codecvt_base::noconv)
3826 {
3827 __bs.resize(__to - &__bs[0]);
3828 // This only gets executed if _Elem is char
3829 __bs.append((const char*)__frm, (const char*)__frm_end);
3830 __frm = __frm_nxt;
3831 __r = codecvt_base::ok;
3832 }
3833 else if (__r == codecvt_base::ok)
3834 {
3835 __bs.resize(__to_nxt - &__bs[0]);
3836 __frm = __frm_nxt;
3837 }
3838 else if (__r == codecvt_base::partial)
3839 {
3840 ptrdiff_t __s = __to_nxt - &__bs[0];
3841 __bs.resize(2 * __s);
3842 __to = &__bs[0] + __s;
3843 __to_end = &__bs[0] + __bs.size();
3844 __frm = __frm_nxt;
3845 }
3846 } while (__r == codecvt_base::partial && __frm_nxt < __frm_end);
3847 }
3848 if (__r == codecvt_base::ok)
3849 {
3850 size_t __s = __bs.size();
3851 __bs.resize(__bs.capacity());
3852 char* __to = &__bs[0] + __s;
3853 char* __to_end = __to + __bs.size();
3854 do
3855 {
3856 char* __to_nxt;
3857 __r = __cvtptr_->unshift(__st, __to, __to_end, __to_nxt);
3858 if (__r == codecvt_base::noconv)
3859 {
3860 __bs.resize(__to - &__bs[0]);
3861 __r = codecvt_base::ok;
3862 }
3863 else if (__r == codecvt_base::ok)
3864 {
3865 __bs.resize(__to_nxt - &__bs[0]);
3866 }
3867 else if (__r == codecvt_base::partial)
3868 {
3869 ptrdiff_t __s = __to_nxt - &__bs[0];
3870 __bs.resize(2 * __s);
3871 __to = &__bs[0] + __s;
3872 __to_end = &__bs[0] + __bs.size();
3873 }
3874 } while (__r == codecvt_base::partial);
3875 if (__r == codecvt_base::ok)
3876 return __bs;
3877 }
3878 }
Howard Hinnantd4444702010-08-11 17:04:31 +00003879#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00003880 if (__byte_err_string_.empty())
3881 throw range_error("wstring_convert: to_bytes error");
Howard Hinnant324bb032010-08-22 00:02:43 +00003882#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00003883 return __byte_err_string_;
3884}
3885
3886template <class _Codecvt, class _Elem = wchar_t, class _Tr = char_traits<_Elem> >
Howard Hinnant82894812010-09-22 16:48:34 +00003887class _LIBCPP_VISIBLE wbuffer_convert
Howard Hinnantd23b4642010-05-31 20:58:54 +00003888 : public basic_streambuf<_Elem, _Tr>
3889{
3890public:
3891 // types:
3892 typedef _Elem char_type;
3893 typedef _Tr traits_type;
3894 typedef typename traits_type::int_type int_type;
3895 typedef typename traits_type::pos_type pos_type;
3896 typedef typename traits_type::off_type off_type;
3897 typedef typename _Codecvt::state_type state_type;
3898
3899private:
Howard Hinnant4b53f502010-06-01 20:09:18 +00003900 char* __extbuf_;
3901 const char* __extbufnext_;
3902 const char* __extbufend_;
3903 char __extbuf_min_[8];
3904 size_t __ebs_;
3905 char_type* __intbuf_;
3906 size_t __ibs_;
Howard Hinnantd23b4642010-05-31 20:58:54 +00003907 streambuf* __bufptr_;
Howard Hinnant4b53f502010-06-01 20:09:18 +00003908 _Codecvt* __cv_;
3909 state_type __st_;
3910 ios_base::openmode __cm_;
3911 bool __owns_eb_;
3912 bool __owns_ib_;
3913 bool __always_noconv_;
Howard Hinnantd23b4642010-05-31 20:58:54 +00003914
Howard Hinnant4b53f502010-06-01 20:09:18 +00003915 wbuffer_convert(const wbuffer_convert&);
3916 wbuffer_convert& operator=(const wbuffer_convert&);
Howard Hinnantd23b4642010-05-31 20:58:54 +00003917public:
3918 wbuffer_convert(streambuf* __bytebuf = 0, _Codecvt* __pcvt = new _Codecvt,
Howard Hinnant4b53f502010-06-01 20:09:18 +00003919 state_type __state = state_type());
3920 ~wbuffer_convert();
Howard Hinnantd23b4642010-05-31 20:58:54 +00003921
Howard Hinnant82894812010-09-22 16:48:34 +00003922 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantd23b4642010-05-31 20:58:54 +00003923 streambuf* rdbuf() const {return __bufptr_;}
Howard Hinnant82894812010-09-22 16:48:34 +00003924 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantd23b4642010-05-31 20:58:54 +00003925 streambuf* rdbuf(streambuf* __bytebuf)
3926 {
3927 streambuf* __r = __bufptr_;
3928 __bufptr_ = __bytebuf;
3929 return __r;
3930 }
3931
Howard Hinnant82894812010-09-22 16:48:34 +00003932 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant4b53f502010-06-01 20:09:18 +00003933 state_type state() const {return __st_;}
Howard Hinnantd23b4642010-05-31 20:58:54 +00003934
3935protected:
Howard Hinnant4b53f502010-06-01 20:09:18 +00003936 virtual int_type underflow();
3937 virtual int_type pbackfail(int_type __c = traits_type::eof());
Howard Hinnantd23b4642010-05-31 20:58:54 +00003938 virtual int_type overflow (int_type __c = traits_type::eof());
Howard Hinnant4b53f502010-06-01 20:09:18 +00003939 virtual basic_streambuf<char_type, traits_type>* setbuf(char_type* __s,
3940 streamsize __n);
3941 virtual pos_type seekoff(off_type __off, ios_base::seekdir __way,
3942 ios_base::openmode __wch = ios_base::in | ios_base::out);
3943 virtual pos_type seekpos(pos_type __sp,
3944 ios_base::openmode __wch = ios_base::in | ios_base::out);
3945 virtual int sync();
3946
3947private:
3948 bool __read_mode();
3949 void __write_mode();
3950 wbuffer_convert* __close();
Howard Hinnantd23b4642010-05-31 20:58:54 +00003951};
3952
3953template <class _Codecvt, class _Elem, class _Tr>
Howard Hinnant4b53f502010-06-01 20:09:18 +00003954wbuffer_convert<_Codecvt, _Elem, _Tr>::
3955 wbuffer_convert(streambuf* __bytebuf, _Codecvt* __pcvt, state_type __state)
3956 : __extbuf_(0),
3957 __extbufnext_(0),
3958 __extbufend_(0),
3959 __ebs_(0),
3960 __intbuf_(0),
3961 __ibs_(0),
3962 __bufptr_(__bytebuf),
3963 __cv_(__pcvt),
3964 __st_(__state),
3965 __cm_(0),
3966 __owns_eb_(false),
3967 __owns_ib_(false),
3968 __always_noconv_(__cv_ ? __cv_->always_noconv() : false)
3969{
3970 setbuf(0, 4096);
3971}
3972
3973template <class _Codecvt, class _Elem, class _Tr>
3974wbuffer_convert<_Codecvt, _Elem, _Tr>::~wbuffer_convert()
3975{
3976 __close();
3977 delete __cv_;
3978 if (__owns_eb_)
3979 delete [] __extbuf_;
3980 if (__owns_ib_)
3981 delete [] __intbuf_;
3982}
3983
3984template <class _Codecvt, class _Elem, class _Tr>
3985typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
3986wbuffer_convert<_Codecvt, _Elem, _Tr>::underflow()
3987{
3988 if (__cv_ == 0 || __bufptr_ == 0)
3989 return traits_type::eof();
3990 bool __initial = __read_mode();
3991 char_type __1buf;
3992 if (this->gptr() == 0)
3993 this->setg(&__1buf, &__1buf+1, &__1buf+1);
3994 const size_t __unget_sz = __initial ? 0 : min<size_t>((this->egptr() - this->eback()) / 2, 4);
3995 int_type __c = traits_type::eof();
3996 if (this->gptr() == this->egptr())
3997 {
3998 memmove(this->eback(), this->egptr() - __unget_sz, __unget_sz * sizeof(char_type));
3999 if (__always_noconv_)
4000 {
4001 streamsize __nmemb = static_cast<streamsize>(this->egptr() - this->eback() - __unget_sz);
4002 __nmemb = __bufptr_->sgetn((char*)this->eback() + __unget_sz, __nmemb);
4003 if (__nmemb != 0)
4004 {
4005 this->setg(this->eback(),
4006 this->eback() + __unget_sz,
4007 this->eback() + __unget_sz + __nmemb);
4008 __c = *this->gptr();
4009 }
4010 }
4011 else
4012 {
4013 memmove(__extbuf_, __extbufnext_, __extbufend_ - __extbufnext_);
4014 __extbufnext_ = __extbuf_ + (__extbufend_ - __extbufnext_);
4015 __extbufend_ = __extbuf_ + (__extbuf_ == __extbuf_min_ ? sizeof(__extbuf_min_) : __ebs_);
Howard Hinnant0949eed2011-06-30 21:18:19 +00004016 streamsize __nmemb = _VSTD::min(static_cast<streamsize>(this->egptr() - this->eback() - __unget_sz),
Howard Hinnant4b53f502010-06-01 20:09:18 +00004017 static_cast<streamsize>(__extbufend_ - __extbufnext_));
4018 codecvt_base::result __r;
4019 state_type __svs = __st_;
4020 streamsize __nr = __bufptr_->sgetn(const_cast<char*>(__extbufnext_), __nmemb);
4021 if (__nr != 0)
4022 {
4023 __extbufend_ = __extbufnext_ + __nr;
4024 char_type* __inext;
4025 __r = __cv_->in(__st_, __extbuf_, __extbufend_, __extbufnext_,
4026 this->eback() + __unget_sz,
4027 this->egptr(), __inext);
4028 if (__r == codecvt_base::noconv)
4029 {
4030 this->setg((char_type*)__extbuf_, (char_type*)__extbuf_, (char_type*)__extbufend_);
4031 __c = *this->gptr();
4032 }
4033 else if (__inext != this->eback() + __unget_sz)
4034 {
4035 this->setg(this->eback(), this->eback() + __unget_sz, __inext);
4036 __c = *this->gptr();
4037 }
4038 }
4039 }
4040 }
4041 else
4042 __c = *this->gptr();
4043 if (this->eback() == &__1buf)
4044 this->setg(0, 0, 0);
4045 return __c;
4046}
4047
4048template <class _Codecvt, class _Elem, class _Tr>
4049typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
4050wbuffer_convert<_Codecvt, _Elem, _Tr>::pbackfail(int_type __c)
4051{
4052 if (__cv_ != 0 && __bufptr_ != 0 && this->eback() < this->gptr())
4053 {
4054 if (traits_type::eq_int_type(__c, traits_type::eof()))
4055 {
4056 this->gbump(-1);
4057 return traits_type::not_eof(__c);
4058 }
4059 if (traits_type::eq(traits_type::to_char_type(__c), this->gptr()[-1]))
4060 {
4061 this->gbump(-1);
4062 *this->gptr() = traits_type::to_char_type(__c);
4063 return __c;
4064 }
4065 }
4066 return traits_type::eof();
4067}
4068
4069template <class _Codecvt, class _Elem, class _Tr>
Howard Hinnantd23b4642010-05-31 20:58:54 +00004070typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
4071wbuffer_convert<_Codecvt, _Elem, _Tr>::overflow(int_type __c)
4072{
Howard Hinnant4b53f502010-06-01 20:09:18 +00004073 if (__cv_ == 0 || __bufptr_ == 0)
4074 return traits_type::eof();
4075 __write_mode();
4076 char_type __1buf;
4077 char_type* __pb_save = this->pbase();
4078 char_type* __epb_save = this->epptr();
4079 if (!traits_type::eq_int_type(__c, traits_type::eof()))
4080 {
4081 if (this->pptr() == 0)
4082 this->setp(&__1buf, &__1buf+1);
4083 *this->pptr() = traits_type::to_char_type(__c);
4084 this->pbump(1);
4085 }
4086 if (this->pptr() != this->pbase())
4087 {
4088 if (__always_noconv_)
4089 {
4090 streamsize __nmemb = static_cast<streamsize>(this->pptr() - this->pbase());
4091 if (__bufptr_->sputn((const char*)this->pbase(), __nmemb) != __nmemb)
4092 return traits_type::eof();
4093 }
4094 else
4095 {
4096 char* __extbe = __extbuf_;
4097 codecvt_base::result __r;
4098 do
4099 {
4100 const char_type* __e;
4101 __r = __cv_->out(__st_, this->pbase(), this->pptr(), __e,
4102 __extbuf_, __extbuf_ + __ebs_, __extbe);
4103 if (__e == this->pbase())
4104 return traits_type::eof();
4105 if (__r == codecvt_base::noconv)
4106 {
4107 streamsize __nmemb = static_cast<size_t>(this->pptr() - this->pbase());
4108 if (__bufptr_->sputn((const char*)this->pbase(), __nmemb) != __nmemb)
4109 return traits_type::eof();
4110 }
4111 else if (__r == codecvt_base::ok || __r == codecvt_base::partial)
4112 {
4113 streamsize __nmemb = static_cast<size_t>(__extbe - __extbuf_);
4114 if (__bufptr_->sputn(__extbuf_, __nmemb) != __nmemb)
4115 return traits_type::eof();
4116 if (__r == codecvt_base::partial)
4117 {
4118 this->setp((char_type*)__e, this->pptr());
4119 this->pbump(this->epptr() - this->pbase());
4120 }
4121 }
4122 else
4123 return traits_type::eof();
4124 } while (__r == codecvt_base::partial);
4125 }
4126 this->setp(__pb_save, __epb_save);
4127 }
4128 return traits_type::not_eof(__c);
4129}
4130
4131template <class _Codecvt, class _Elem, class _Tr>
4132basic_streambuf<_Elem, _Tr>*
4133wbuffer_convert<_Codecvt, _Elem, _Tr>::setbuf(char_type* __s, streamsize __n)
4134{
4135 this->setg(0, 0, 0);
4136 this->setp(0, 0);
4137 if (__owns_eb_)
4138 delete [] __extbuf_;
4139 if (__owns_ib_)
4140 delete [] __intbuf_;
4141 __ebs_ = __n;
4142 if (__ebs_ > sizeof(__extbuf_min_))
4143 {
4144 if (__always_noconv_ && __s)
4145 {
4146 __extbuf_ = (char*)__s;
4147 __owns_eb_ = false;
4148 }
4149 else
4150 {
4151 __extbuf_ = new char[__ebs_];
4152 __owns_eb_ = true;
4153 }
4154 }
4155 else
4156 {
4157 __extbuf_ = __extbuf_min_;
4158 __ebs_ = sizeof(__extbuf_min_);
4159 __owns_eb_ = false;
4160 }
4161 if (!__always_noconv_)
4162 {
4163 __ibs_ = max<streamsize>(__n, sizeof(__extbuf_min_));
4164 if (__s && __ibs_ >= sizeof(__extbuf_min_))
4165 {
4166 __intbuf_ = __s;
4167 __owns_ib_ = false;
4168 }
4169 else
4170 {
4171 __intbuf_ = new char_type[__ibs_];
4172 __owns_ib_ = true;
4173 }
4174 }
4175 else
4176 {
4177 __ibs_ = 0;
4178 __intbuf_ = 0;
4179 __owns_ib_ = false;
4180 }
4181 return this;
4182}
4183
4184template <class _Codecvt, class _Elem, class _Tr>
4185typename wbuffer_convert<_Codecvt, _Elem, _Tr>::pos_type
4186wbuffer_convert<_Codecvt, _Elem, _Tr>::seekoff(off_type __off, ios_base::seekdir __way,
4187 ios_base::openmode __om)
4188{
4189 int __width = __cv_->encoding();
4190 if (__cv_ == 0 || __bufptr_ == 0 || (__width <= 0 && __off != 0) || sync())
4191 return pos_type(off_type(-1));
4192 // __width > 0 || __off == 0
4193 switch (__way)
4194 {
4195 case ios_base::beg:
4196 break;
4197 case ios_base::cur:
4198 break;
4199 case ios_base::end:
4200 break;
4201 default:
4202 return pos_type(off_type(-1));
4203 }
4204 pos_type __r = __bufptr_->pubseekoff(__width * __off, __way, __om);
4205 __r.state(__st_);
4206 return __r;
4207}
4208
4209template <class _Codecvt, class _Elem, class _Tr>
4210typename wbuffer_convert<_Codecvt, _Elem, _Tr>::pos_type
4211wbuffer_convert<_Codecvt, _Elem, _Tr>::seekpos(pos_type __sp, ios_base::openmode __wch)
4212{
4213 if (__cv_ == 0 || __bufptr_ == 0 || sync())
4214 return pos_type(off_type(-1));
4215 if (__bufptr_->pubseekpos(__sp, __wch) == pos_type(off_type(-1)))
4216 return pos_type(off_type(-1));
4217 return __sp;
4218}
4219
4220template <class _Codecvt, class _Elem, class _Tr>
4221int
4222wbuffer_convert<_Codecvt, _Elem, _Tr>::sync()
4223{
4224 if (__cv_ == 0 || __bufptr_ == 0)
4225 return 0;
4226 if (__cm_ & ios_base::out)
4227 {
4228 if (this->pptr() != this->pbase())
4229 if (overflow() == traits_type::eof())
4230 return -1;
4231 codecvt_base::result __r;
4232 do
4233 {
4234 char* __extbe;
4235 __r = __cv_->unshift(__st_, __extbuf_, __extbuf_ + __ebs_, __extbe);
4236 streamsize __nmemb = static_cast<streamsize>(__extbe - __extbuf_);
4237 if (__bufptr_->sputn(__extbuf_, __nmemb) != __nmemb)
4238 return -1;
4239 } while (__r == codecvt_base::partial);
4240 if (__r == codecvt_base::error)
4241 return -1;
4242 if (__bufptr_->pubsync())
4243 return -1;
4244 }
4245 else if (__cm_ & ios_base::in)
4246 {
4247 off_type __c;
4248 if (__always_noconv_)
4249 __c = this->egptr() - this->gptr();
4250 else
4251 {
4252 int __width = __cv_->encoding();
4253 __c = __extbufend_ - __extbufnext_;
4254 if (__width > 0)
4255 __c += __width * (this->egptr() - this->gptr());
4256 else
4257 {
4258 if (this->gptr() != this->egptr())
4259 {
4260 reverse(this->gptr(), this->egptr());
4261 codecvt_base::result __r;
4262 const char_type* __e = this->gptr();
4263 char* __extbe;
4264 do
4265 {
4266 __r = __cv_->out(__st_, __e, this->egptr(), __e,
4267 __extbuf_, __extbuf_ + __ebs_, __extbe);
4268 switch (__r)
4269 {
4270 case codecvt_base::noconv:
4271 __c += this->egptr() - this->gptr();
4272 break;
4273 case codecvt_base::ok:
4274 case codecvt_base::partial:
4275 __c += __extbe - __extbuf_;
4276 break;
4277 default:
4278 return -1;
4279 }
4280 } while (__r == codecvt_base::partial);
4281 }
4282 }
4283 }
4284 if (__bufptr_->pubseekoff(-__c, ios_base::cur, __cm_) == pos_type(off_type(-1)))
4285 return -1;
4286 this->setg(0, 0, 0);
4287 __cm_ = 0;
4288 }
4289 return 0;
4290}
4291
4292template <class _Codecvt, class _Elem, class _Tr>
4293bool
4294wbuffer_convert<_Codecvt, _Elem, _Tr>::__read_mode()
4295{
4296 if (!(__cm_ & ios_base::in))
4297 {
4298 this->setp(0, 0);
4299 if (__always_noconv_)
4300 this->setg((char_type*)__extbuf_,
4301 (char_type*)__extbuf_ + __ebs_,
4302 (char_type*)__extbuf_ + __ebs_);
4303 else
4304 this->setg(__intbuf_, __intbuf_ + __ibs_, __intbuf_ + __ibs_);
4305 __cm_ = ios_base::in;
4306 return true;
4307 }
4308 return false;
4309}
4310
4311template <class _Codecvt, class _Elem, class _Tr>
4312void
4313wbuffer_convert<_Codecvt, _Elem, _Tr>::__write_mode()
4314{
4315 if (!(__cm_ & ios_base::out))
4316 {
4317 this->setg(0, 0, 0);
4318 if (__ebs_ > sizeof(__extbuf_min_))
4319 {
4320 if (__always_noconv_)
4321 this->setp((char_type*)__extbuf_,
4322 (char_type*)__extbuf_ + (__ebs_ - 1));
4323 else
4324 this->setp(__intbuf_, __intbuf_ + (__ibs_ - 1));
4325 }
4326 else
4327 this->setp(0, 0);
4328 __cm_ = ios_base::out;
4329 }
4330}
4331
4332template <class _Codecvt, class _Elem, class _Tr>
4333wbuffer_convert<_Codecvt, _Elem, _Tr>*
4334wbuffer_convert<_Codecvt, _Elem, _Tr>::__close()
4335{
4336 wbuffer_convert* __rt = 0;
4337 if (__cv_ != 0 && __bufptr_ != 0)
4338 {
4339 __rt = this;
4340 if ((__cm_ & ios_base::out) && sync())
4341 __rt = 0;
4342 }
4343 return __rt;
Howard Hinnantd23b4642010-05-31 20:58:54 +00004344}
4345
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004346_LIBCPP_END_NAMESPACE_STD
4347
4348#endif // _LIBCPP_LOCALE