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