blob: 778d6c6f9021a7b1925d8e24cf5c8f6281b33ccf [file] [log] [blame]
Howard Hinnantbc8d3f92010-05-11 19:42:161// -*- C++ -*-
2//===-------------------------- locale ------------------------------------===//
3//
Howard Hinnantf5256e12010-05-11 21:36:014// The LLVM Compiler Infrastructure
Howard Hinnantbc8d3f92010-05-11 19:42:165//
Howard Hinnantb64f8b02010-11-16 22:09:026// 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:168//
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:5839 locale() noexcept;
40 locale(const locale& other) noexcept;
Howard Hinnantbc8d3f92010-05-11 19:42:1641 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:5848 ~locale(); // not virtual
Howard Hinnantbc8d3f92010-05-11 19:42:1649
Howard Hinnantc9834542011-05-31 15:34:5850 const locale& operator=(const locale& other) noexcept;
Howard Hinnantbc8d3f92010-05-11 19:42:1651
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:5868template <class Facet> bool has_facet(const locale&) noexcept;
Howard Hinnantbc8d3f92010-05-11 19:42:1669
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:5484
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:16116template <class Codecvt, class Elem = wchar_t, class Tr = char_traits<Elem>>
Howard Hinnantd23b4642010-05-31 20:58:54117class 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:16131
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:41184#if !__APPLE__
185#include <cstdarg>
186#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16187#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:31195#ifndef _LIBCPP_STABLE_APPLE_ABI
Sean Hunt62a6ac32011-07-09 00:56:23196// Get the C locale object
197locale_t __cloc();
Sean Hunte59f7242011-07-09 01:09:31198#endif
Sean Hunt62a6ac32011-07-09 00:56:23199
Howard Hinnantadff4892010-05-24 17:49:41200// 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:34206inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantadff4892010-05-24 17:49:41207int
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:34215inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantadff4892010-05-24 17:49:41216int
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:34224inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantadff4892010-05-24 17:49:41225int
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:34233inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantadff4892010-05-24 17:49:41234int
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:34241inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantadff4892010-05-24 17:49:41242int
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:34250inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantadff4892010-05-24 17:49:41251int
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:34258inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantadff4892010-05-24 17:49:41259int
260__nolocale_isxdigit(int __c)
261{
262 return isxdigit_l(__c, 0);
263}
264
Howard Hinnant82894812010-09-22 16:48:34265inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantadff4892010-05-24 17:49:41266int
267__nolocale_isdigit(int __c)
268{
269 return isdigit_l(__c, 0);
270}
271
Howard Hinnant324bb032010-08-22 00:02:43272#else // __APPLE__
Michael J. Spencer626916f2010-12-10 19:47:54273inline
274#ifndef _LIBCPP_HAS_NO_ALWAYS_INLINE_VARIADICS
275_LIBCPP_INLINE_VISIBILITY
276#endif
Howard Hinnant82894812010-09-22 16:48:34277int
Howard Hinnantadff4892010-05-24 17:49:41278__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:54287inline
288#ifndef _LIBCPP_HAS_NO_ALWAYS_INLINE_VARIADICS
289_LIBCPP_INLINE_VISIBILITY
290#endif
Howard Hinnant82894812010-09-22 16:48:34291int
Howard Hinnantadff4892010-05-24 17:49:41292__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:54301inline
302#ifndef _LIBCPP_HAS_NO_ALWAYS_INLINE_VARIADICS
303_LIBCPP_INLINE_VISIBILITY
304#endif
Howard Hinnant82894812010-09-22 16:48:34305int
Howard Hinnantadff4892010-05-24 17:49:41306__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:54315inline
316#ifndef _LIBCPP_HAS_NO_ALWAYS_INLINE_VARIADICS
317_LIBCPP_INLINE_VISIBILITY
318#endif
Howard Hinnant82894812010-09-22 16:48:34319int
Howard Hinnantadff4892010-05-24 17:49:41320__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:34329inline _LIBCPP_INLINE_VISIBILITY
330int
Howard Hinnantadff4892010-05-24 17:49:41331__nolocale_isxdigit(int __c)
332{
333 return isxdigit(__c);
334}
Howard Hinnant82894812010-09-22 16:48:34335
336inline _LIBCPP_INLINE_VISIBILITY
337int
Howard Hinnantadff4892010-05-24 17:49:41338__nolocale_isdigit(int __c)
339{
340 return isdigit(__c);
341}
Howard Hinnant324bb032010-08-22 00:02:43342#endif // __APPLE__
Howard Hinnantadff4892010-05-24 17:49:41343
Howard Hinnantbc8d3f92010-05-11 19:42:16344// __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:19371 size_t __nkw = _VSTD::distance(__kb, __ke);
Howard Hinnantbc8d3f92010-05-11 19:42:16372 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:16483template <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:19530 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:16536 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:19546 if (__f >= 24)
Howard Hinnantbc8d3f92010-05-11 19:42:16547 return -1;
Howard Hinnantbc8d3f92010-05-11 19:42:16548 switch (__base)
549 {
550 case 8:
551 case 10:
552 if (__f >= __base)
Howard Hinnant80586722011-03-09 01:03:19553 return -1;
Howard Hinnantbc8d3f92010-05-11 19:42:16554 break;
Howard Hinnant80586722011-03-09 01:03:19555 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:16562 return 0;
Howard Hinnant80586722011-03-09 01:03:19563 }
564 return -1;
Howard Hinnantbc8d3f92010-05-11 19:42:16565 }
Howard Hinnant80586722011-03-09 01:03:19566 if (__a_end-__a < __num_get_buf_sz - 1)
567 *__a_end++ = __src[__f];
Howard Hinnantbc8d3f92010-05-11 19:42:16568 ++__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:34623class _LIBCPP_VISIBLE num_get
Howard Hinnantbc8d3f92010-05-11 19:42:16624 : 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:34715 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16716 ~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:41753 int __save_errno = errno;
754 errno = 0;
Howard Hinnantbc8d3f92010-05-11 19:42:16755 char *__p2;
756 long long __ll = strtoll_l(__a, &__p2, __base, 0);
Howard Hinnante7c8da62011-02-25 19:52:41757 int __current_errno = errno;
758 if (__current_errno == 0)
759 errno = __save_errno;
Howard Hinnantbc8d3f92010-05-11 19:42:16760 if (__p2 != __a_end)
761 {
762 __err = ios_base::failbit;
763 return 0;
764 }
Howard Hinnante7c8da62011-02-25 19:52:41765 else if (__current_errno == ERANGE ||
766 __ll < numeric_limits<_Tp>::min() ||
767 numeric_limits<_Tp>::max() < __ll)
Howard Hinnantbc8d3f92010-05-11 19:42:16768 {
769 __err = ios_base::failbit;
Howard Hinnante7c8da62011-02-25 19:52:41770 if (__ll > 0)
771 return numeric_limits<_Tp>::max();
772 else
773 return numeric_limits<_Tp>::min();
Howard Hinnantbc8d3f92010-05-11 19:42:16774 }
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:41788 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:16795 char *__p2;
796 unsigned long long __ll = strtoull_l(__a, &__p2, __base, 0);
Howard Hinnante7c8da62011-02-25 19:52:41797 int __current_errno = errno;
798 if (__current_errno == 0)
799 errno = __save_errno;
Howard Hinnantbc8d3f92010-05-11 19:42:16800 if (__p2 != __a_end)
801 {
802 __err = ios_base::failbit;
803 return 0;
804 }
Howard Hinnante7c8da62011-02-25 19:52:41805 else if (__current_errno == ERANGE ||
806 numeric_limits<_Tp>::max() < __ll)
Howard Hinnantbc8d3f92010-05-11 19:42:16807 {
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:43891 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:16892 __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:43926 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
927 __thousands_sep, __grouping, __g, __g_end,
Howard Hinnantbc8d3f92010-05-11 19:42:16928 __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:43961 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:16962 __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:43996 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:16997 __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:431031 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:161032 __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:431066 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:161067 __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:431094 string __grouping = this->__stage2_float_prep(__iob, __atoms,
1095 __decimal_point,
Howard Hinnantbc8d3f92010-05-11 19:42:161096 __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:431105 if (this->__stage2_float_loop(*__b, __in_units, __exp, __a, __a_end,
1106 __decimal_point, __thousands_sep,
Howard Hinnantbc8d3f92010-05-11 19:42:161107 __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:431134 string __grouping = this->__stage2_float_prep(__iob, __atoms,
1135 __decimal_point,
Howard Hinnantbc8d3f92010-05-11 19:42:161136 __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:431145 if (this->__stage2_float_loop(*__b, __in_units, __exp, __a, __a_end,
1146 __decimal_point, __thousands_sep,
Howard Hinnantbc8d3f92010-05-11 19:42:161147 __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:431174 string __grouping = this->__stage2_float_prep(__iob, __atoms,
Howard Hinnantbc8d3f92010-05-11 19:42:161175 __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:431185 if (this->__stage2_float_loop(*__b, __in_units, __exp, __a, __a_end,
1186 __decimal_point, __thousands_sep,
Howard Hinnantbc8d3f92010-05-11 19:42:161187 __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:431223 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
1224 __thousands_sep, __grouping,
Howard Hinnantbc8d3f92010-05-11 19:42:161225 __g, __g_end, __atoms))
1226 break;
1227 // Stage 3
1228 __a[sizeof(__a)-1] = 0;
Howard Hinnantadff4892010-05-24 17:49:411229 if (__nolocale_sscanf(__a, "%p", &__v) != 1)
Howard Hinnantbc8d3f92010-05-11 19:42:161230 __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:411334 if (!__nolocale_isxdigit(*__ns))
Howard Hinnantbc8d3f92010-05-11 19:42:161335 break;
1336 }
1337 else
1338 {
1339 for (__ns = __nf; __ns < __ne; ++__ns)
Howard Hinnantadff4892010-05-24 17:49:411340 if (!__nolocale_isdigit(*__ns))
Howard Hinnantbc8d3f92010-05-11 19:42:161341 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:341391class _LIBCPP_VISIBLE num_put
Howard Hinnantbc8d3f92010-05-11 19:42:161392 : 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:341462 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:161463 ~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:411538 int __nc = __nolocale_sprintf(__nar, __fmt, __v);
Howard Hinnantbc8d3f92010-05-11 19:42:161539 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:411564 int __nc = __nolocale_sprintf(__nar, __fmt, __v);
Howard Hinnantbc8d3f92010-05-11 19:42:161565 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:411590 int __nc = __nolocale_sprintf(__nar, __fmt, __v);
Howard Hinnantbc8d3f92010-05-11 19:42:161591 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:411616 int __nc = __nolocale_sprintf(__nar, __fmt, __v);
Howard Hinnantbc8d3f92010-05-11 19:42:161617 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:411643 __nc = __nolocale_snprintf(__nb, __nbuf, __fmt,
1644 (int)__iob.precision(), __v);
Howard Hinnantbc8d3f92010-05-11 19:42:161645 else
Howard Hinnantadff4892010-05-24 17:49:411646 __nc = __nolocale_snprintf(__nb, __nbuf, __fmt, __v);
Howard Hinnantbc8d3f92010-05-11 19:42:161647 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:411651 __nc = __nolocale_asprintf(&__nb, __fmt, (int)__iob.precision(),
1652 __v);
Howard Hinnantbc8d3f92010-05-11 19:42:161653 else
Howard Hinnantadff4892010-05-24 17:49:411654 __nc = __nolocale_asprintf(&__nb, __fmt, __v);
Howard Hinnantbc8d3f92010-05-11 19:42:161655 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:411695 __nc = __nolocale_snprintf(__nb, __nbuf, __fmt,
1696 (int)__iob.precision(), __v);
Howard Hinnantbc8d3f92010-05-11 19:42:161697 else
Howard Hinnantadff4892010-05-24 17:49:411698 __nc = __nolocale_snprintf(__nb, __nbuf, __fmt, __v);
Howard Hinnantbc8d3f92010-05-11 19:42:161699 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:411703 __nc = __nolocale_asprintf(&__nb, __fmt, (int)__iob.precision(),
1704 __v);
Howard Hinnantbc8d3f92010-05-11 19:42:161705 else
Howard Hinnantadff4892010-05-24 17:49:411706 __nc = __nolocale_asprintf(&__nb, __fmt, __v);
Howard Hinnantbc8d3f92010-05-11 19:42:161707 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:411742 int __nc = __nolocale_sprintf(__nar, __fmt, __v);
Howard Hinnantbc8d3f92010-05-11 19:42:161743 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:341797class _LIBCPP_VISIBLE time_base
Howard Hinnantbc8d3f92010-05-11 19:42:161798{
1799public:
1800 enum dateorder {no_order, dmy, mdy, ymd, ydm};
1801};
1802
1803template <class _CharT>
Howard Hinnant2d72b1e2010-12-17 14:46:431804class __time_get_c_storage // purposefully not decorated
Howard Hinnantbc8d3f92010-05-11 19:42:161805{
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:341819class _LIBCPP_VISIBLE time_get
Howard Hinnantbc8d3f92010-05-11 19:42:161820 : 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:341890 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:161891 ~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:142354 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:162360 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:342470class _LIBCPP_VISIBLE time_get_byname
Howard Hinnantbc8d3f92010-05-11 19:42:162471 : 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:342480 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:162481 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:342484 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:162485 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:342490 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:162491 ~time_get_byname() {}
2492
Howard Hinnant82894812010-09-22 16:48:342493 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:162494 virtual dateorder do_date_order() const {return this->__do_date_order();}
2495private:
Howard Hinnant82894812010-09-22 16:48:342496 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:162497 virtual const string_type* __weeks() const {return this->__weeks_;}
Howard Hinnant82894812010-09-22 16:48:342498 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:162499 virtual const string_type* __months() const {return this->__months_;}
Howard Hinnant82894812010-09-22 16:48:342500 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:162501 virtual const string_type* __am_pm() const {return this->__am_pm_;}
Howard Hinnant82894812010-09-22 16:48:342502 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:162503 virtual const string_type& __c() const {return this->__c_;}
Howard Hinnant82894812010-09-22 16:48:342504 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:162505 virtual const string_type& __r() const {return this->__r_;}
Howard Hinnant82894812010-09-22 16:48:342506 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:162507 virtual const string_type& __x() const {return this->__x_;}
Howard Hinnant82894812010-09-22 16:48:342508 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:162509 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:
2519 _LIBCPP_ALWAYS_INLINE __time_put() : __loc_(0) {}
2520 __time_put(const char* __nm);
2521 __time_put(const string& __nm);
2522 ~__time_put();
2523 void __do_put(char* __nb, char*& __ne, const tm* __tm,
2524 char __fmt, char __mod) const;
2525 void __do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
2526 char __fmt, char __mod) const;
2527};
2528
2529template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:342530class _LIBCPP_VISIBLE time_put
Howard Hinnantbc8d3f92010-05-11 19:42:162531 : public locale::facet,
2532 private __time_put
2533{
2534public:
2535 typedef _CharT char_type;
2536 typedef _OutputIterator iter_type;
2537
2538 _LIBCPP_ALWAYS_INLINE
2539 explicit time_put(size_t __refs = 0)
2540 : locale::facet(__refs) {}
2541
2542 iter_type put(iter_type __s, ios_base& __iob, char_type __fl, const tm* __tm,
2543 const char_type* __pb, const char_type* __pe) const;
2544
2545 _LIBCPP_ALWAYS_INLINE
2546 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
2547 const tm* __tm, char __fmt, char __mod = 0) const
2548 {
2549 return do_put(__s, __iob, __fl, __tm, __fmt, __mod);
2550 }
2551
2552 static locale::id id;
2553
2554protected:
Howard Hinnant82894812010-09-22 16:48:342555 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:162556 ~time_put() {}
2557 virtual iter_type do_put(iter_type __s, ios_base&, char_type, const tm* __tm,
2558 char __fmt, char __mod) const;
2559
Howard Hinnant82894812010-09-22 16:48:342560 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:162561 explicit time_put(const char* __nm, size_t __refs)
2562 : locale::facet(__refs),
2563 __time_put(__nm) {}
Howard Hinnant82894812010-09-22 16:48:342564 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:162565 explicit time_put(const string& __nm, size_t __refs)
2566 : locale::facet(__refs),
2567 __time_put(__nm) {}
2568};
2569
2570template <class _CharT, class _OutputIterator>
2571locale::id
2572time_put<_CharT, _OutputIterator>::id;
2573
2574template <class _CharT, class _OutputIterator>
2575_OutputIterator
2576time_put<_CharT, _OutputIterator>::put(iter_type __s, ios_base& __iob,
2577 char_type __fl, const tm* __tm,
2578 const char_type* __pb,
2579 const char_type* __pe) const
2580{
2581 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2582 for (; __pb != __pe; ++__pb)
2583 {
2584 if (__ct.narrow(*__pb, 0) == '%')
2585 {
2586 if (++__pb == __pe)
2587 {
2588 *__s++ = __pb[-1];
2589 break;
2590 }
2591 char __mod = 0;
2592 char __fmt = __ct.narrow(*__pb, 0);
2593 if (__fmt == 'E' || __fmt == 'O')
2594 {
2595 if (++__pb == __pe)
2596 {
2597 *__s++ = __pb[-2];
2598 *__s++ = __pb[-1];
2599 break;
2600 }
2601 __mod = __fmt;
2602 __fmt = __ct.narrow(*__pb, 0);
2603 }
2604 __s = do_put(__s, __iob, __fl, __tm, __fmt, __mod);
2605 }
2606 else
2607 *__s++ = *__pb;
2608 }
2609 return __s;
2610}
2611
2612template <class _CharT, class _OutputIterator>
2613_OutputIterator
2614time_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
2615 char_type, const tm* __tm,
2616 char __fmt, char __mod) const
2617{
2618 char_type __nar[100];
2619 char_type* __nb = __nar;
2620 char_type* __ne = __nb + 100;
2621 __do_put(__nb, __ne, __tm, __fmt, __mod);
Howard Hinnant0949eed2011-06-30 21:18:192622 return _VSTD::copy(__nb, __ne, __s);
Howard Hinnantbc8d3f92010-05-11 19:42:162623}
2624
2625extern template class time_put<char>;
2626extern template class time_put<wchar_t>;
2627
2628template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:342629class _LIBCPP_VISIBLE time_put_byname
Howard Hinnantbc8d3f92010-05-11 19:42:162630 : public time_put<_CharT, _OutputIterator>
2631{
2632public:
2633 _LIBCPP_ALWAYS_INLINE
2634 explicit time_put_byname(const char* __nm, size_t __refs = 0)
2635 : time_put<_CharT, _OutputIterator>(__nm, __refs) {}
2636
2637 _LIBCPP_ALWAYS_INLINE
2638 explicit time_put_byname(const string& __nm, size_t __refs = 0)
2639 : time_put<_CharT, _OutputIterator>(__nm, __refs) {}
2640
2641protected:
Howard Hinnant82894812010-09-22 16:48:342642 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:162643 ~time_put_byname() {}
2644};
2645
2646extern template class time_put_byname<char>;
2647extern template class time_put_byname<wchar_t>;
2648
2649// money_base
2650
Howard Hinnant82894812010-09-22 16:48:342651class _LIBCPP_VISIBLE money_base
Howard Hinnantbc8d3f92010-05-11 19:42:162652{
2653public:
2654 enum part {none, space, symbol, sign, value};
2655 struct pattern {char field[4];};
2656
2657 _LIBCPP_ALWAYS_INLINE money_base() {}
2658};
2659
2660// moneypunct
2661
2662template <class _CharT, bool _International = false>
Howard Hinnant82894812010-09-22 16:48:342663class _LIBCPP_VISIBLE moneypunct
Howard Hinnantbc8d3f92010-05-11 19:42:162664 : public locale::facet,
2665 public money_base
2666{
2667public:
2668 typedef _CharT char_type;
2669 typedef basic_string<char_type> string_type;
2670
Howard Hinnant82894812010-09-22 16:48:342671 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:162672 explicit moneypunct(size_t __refs = 0)
2673 : locale::facet(__refs) {}
2674
2675 _LIBCPP_ALWAYS_INLINE char_type decimal_point() const {return do_decimal_point();}
2676 _LIBCPP_ALWAYS_INLINE char_type thousands_sep() const {return do_thousands_sep();}
2677 _LIBCPP_ALWAYS_INLINE string grouping() const {return do_grouping();}
2678 _LIBCPP_ALWAYS_INLINE string_type curr_symbol() const {return do_curr_symbol();}
2679 _LIBCPP_ALWAYS_INLINE string_type positive_sign() const {return do_positive_sign();}
2680 _LIBCPP_ALWAYS_INLINE string_type negative_sign() const {return do_negative_sign();}
2681 _LIBCPP_ALWAYS_INLINE int frac_digits() const {return do_frac_digits();}
2682 _LIBCPP_ALWAYS_INLINE pattern pos_format() const {return do_pos_format();}
2683 _LIBCPP_ALWAYS_INLINE pattern neg_format() const {return do_neg_format();}
2684
2685 static locale::id id;
2686 static const bool intl = _International;
2687
2688protected:
Howard Hinnant82894812010-09-22 16:48:342689 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:162690 ~moneypunct() {}
2691
2692 virtual char_type do_decimal_point() const {return numeric_limits<char_type>::max();}
2693 virtual char_type do_thousands_sep() const {return numeric_limits<char_type>::max();}
2694 virtual string do_grouping() const {return string();}
2695 virtual string_type do_curr_symbol() const {return string_type();}
2696 virtual string_type do_positive_sign() const {return string_type();}
2697 virtual string_type do_negative_sign() const {return string_type(1, '-');}
2698 virtual int do_frac_digits() const {return 0;}
2699 virtual pattern do_pos_format() const
2700 {pattern __p = {symbol, sign, none, value}; return __p;}
2701 virtual pattern do_neg_format() const
2702 {pattern __p = {symbol, sign, none, value}; return __p;}
2703};
2704
2705template <class _CharT, bool _International>
2706locale::id
2707moneypunct<_CharT, _International>::id;
2708
2709extern template class moneypunct<char, false>;
2710extern template class moneypunct<char, true>;
2711extern template class moneypunct<wchar_t, false>;
2712extern template class moneypunct<wchar_t, true>;
2713
2714// moneypunct_byname
2715
2716template <class _CharT, bool _International = false>
Howard Hinnant82894812010-09-22 16:48:342717class _LIBCPP_VISIBLE moneypunct_byname
2718 : public moneypunct<_CharT, _International>
Howard Hinnantbc8d3f92010-05-11 19:42:162719{
2720public:
2721 typedef money_base::pattern pattern;
2722 typedef _CharT char_type;
2723 typedef basic_string<char_type> string_type;
2724
2725 _LIBCPP_ALWAYS_INLINE
2726 explicit moneypunct_byname(const char* __nm, size_t __refs = 0)
2727 : moneypunct<_CharT, _International>(__refs) {init(__nm);}
2728
2729 _LIBCPP_ALWAYS_INLINE
2730 explicit moneypunct_byname(const string& __nm, size_t __refs = 0)
2731 : moneypunct<_CharT, _International>(__refs) {init(__nm.c_str());}
2732
2733protected:
Howard Hinnant82894812010-09-22 16:48:342734 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:162735 ~moneypunct_byname() {}
2736
2737 virtual char_type do_decimal_point() const {return __decimal_point_;}
2738 virtual char_type do_thousands_sep() const {return __thousands_sep_;}
2739 virtual string do_grouping() const {return __grouping_;}
2740 virtual string_type do_curr_symbol() const {return __curr_symbol_;}
2741 virtual string_type do_positive_sign() const {return __positive_sign_;}
2742 virtual string_type do_negative_sign() const {return __negative_sign_;}
2743 virtual int do_frac_digits() const {return __frac_digits_;}
2744 virtual pattern do_pos_format() const {return __pos_format_;}
2745 virtual pattern do_neg_format() const {return __neg_format_;}
2746
2747private:
2748 char_type __decimal_point_;
2749 char_type __thousands_sep_;
2750 string __grouping_;
2751 string_type __curr_symbol_;
2752 string_type __positive_sign_;
2753 string_type __negative_sign_;
2754 int __frac_digits_;
2755 pattern __pos_format_;
2756 pattern __neg_format_;
2757
2758 void init(const char*);
2759};
2760
2761template<> void moneypunct_byname<char, false>::init(const char*);
2762template<> void moneypunct_byname<char, true>::init(const char*);
2763template<> void moneypunct_byname<wchar_t, false>::init(const char*);
2764template<> void moneypunct_byname<wchar_t, true>::init(const char*);
2765
2766extern template class moneypunct_byname<char, false>;
2767extern template class moneypunct_byname<char, true>;
2768extern template class moneypunct_byname<wchar_t, false>;
2769extern template class moneypunct_byname<wchar_t, true>;
2770
2771// money_get
2772
2773template <class _CharT>
2774class __money_get
2775{
2776protected:
2777 typedef _CharT char_type;
2778 typedef basic_string<char_type> string_type;
2779
2780 _LIBCPP_ALWAYS_INLINE __money_get() {}
2781
2782 static void __gather_info(bool __intl, const locale& __loc,
2783 money_base::pattern& __pat, char_type& __dp,
2784 char_type& __ts, string& __grp,
2785 string_type& __sym, string_type& __psn,
2786 string_type& __nsn, int& __fd);
2787};
2788
2789template <class _CharT>
2790void
2791__money_get<_CharT>::__gather_info(bool __intl, const locale& __loc,
2792 money_base::pattern& __pat, char_type& __dp,
2793 char_type& __ts, string& __grp,
2794 string_type& __sym, string_type& __psn,
2795 string_type& __nsn, int& __fd)
2796{
2797 if (__intl)
2798 {
2799 const moneypunct<char_type, true>& __mp =
2800 use_facet<moneypunct<char_type, true> >(__loc);
2801 __pat = __mp.neg_format();
2802 __nsn = __mp.negative_sign();
2803 __psn = __mp.positive_sign();
2804 __dp = __mp.decimal_point();
2805 __ts = __mp.thousands_sep();
2806 __grp = __mp.grouping();
2807 __sym = __mp.curr_symbol();
2808 __fd = __mp.frac_digits();
2809 }
2810 else
2811 {
2812 const moneypunct<char_type, false>& __mp =
2813 use_facet<moneypunct<char_type, false> >(__loc);
2814 __pat = __mp.neg_format();
2815 __nsn = __mp.negative_sign();
2816 __psn = __mp.positive_sign();
2817 __dp = __mp.decimal_point();
2818 __ts = __mp.thousands_sep();
2819 __grp = __mp.grouping();
2820 __sym = __mp.curr_symbol();
2821 __fd = __mp.frac_digits();
2822 }
2823}
2824
2825extern template class __money_get<char>;
2826extern template class __money_get<wchar_t>;
2827
2828template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:342829class _LIBCPP_VISIBLE money_get
Howard Hinnantbc8d3f92010-05-11 19:42:162830 : public locale::facet,
2831 private __money_get<_CharT>
2832{
2833public:
2834 typedef _CharT char_type;
2835 typedef _InputIterator iter_type;
2836 typedef basic_string<char_type> string_type;
2837
2838 _LIBCPP_ALWAYS_INLINE
2839 explicit money_get(size_t __refs = 0)
2840 : locale::facet(__refs) {}
2841
2842 _LIBCPP_ALWAYS_INLINE
2843 iter_type get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob,
2844 ios_base::iostate& __err, long double& __v) const
2845 {
2846 return do_get(__b, __e, __intl, __iob, __err, __v);
2847 }
2848
2849 _LIBCPP_ALWAYS_INLINE
2850 iter_type get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob,
2851 ios_base::iostate& __err, string_type& __v) const
2852 {
2853 return do_get(__b, __e, __intl, __iob, __err, __v);
2854 }
2855
2856 static locale::id id;
2857
2858protected:
2859
Howard Hinnant82894812010-09-22 16:48:342860 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:162861 ~money_get() {}
Howard Hinnant324bb032010-08-22 00:02:432862
Howard Hinnantbc8d3f92010-05-11 19:42:162863 virtual iter_type do_get(iter_type __b, iter_type __e, bool __intl,
2864 ios_base& __iob, ios_base::iostate& __err,
2865 long double& __v) const;
2866 virtual iter_type do_get(iter_type __b, iter_type __e, bool __intl,
2867 ios_base& __iob, ios_base::iostate& __err,
2868 string_type& __v) const;
2869
2870private:
2871 static bool __do_get(iter_type& __b, iter_type __e,
2872 bool __intl, const locale& __loc,
2873 ios_base::fmtflags __flags, ios_base::iostate& __err,
2874 bool& __neg, const ctype<char_type>& __ct,
2875 unique_ptr<char_type, void(*)(void*)>& __wb,
2876 char_type*& __wn, char_type* __we);
2877};
2878
2879template <class _CharT, class _InputIterator>
2880locale::id
2881money_get<_CharT, _InputIterator>::id;
2882
2883void __do_nothing(void*);
2884
2885template <class _Tp>
2886_LIBCPP_HIDDEN
2887void
2888__double_or_nothing(unique_ptr<_Tp, void(*)(void*)>& __b, _Tp*& __n, _Tp*& __e)
2889{
2890 bool __owns = __b.get_deleter() != __do_nothing;
2891 size_t __cur_cap = (__e-__b.get()) * sizeof(_Tp);
2892 size_t __new_cap = __cur_cap < numeric_limits<size_t>::max() / 2 ?
2893 2 * __cur_cap : numeric_limits<size_t>::max();
2894 size_t __n_off = __n - __b.get();
2895 _Tp* __t = (_Tp*)realloc(__owns ? __b.get() : 0, __new_cap);
2896 if (__t == 0)
2897 __throw_bad_alloc();
2898 if (__owns)
2899 __b.release();
2900 __b = unique_ptr<_Tp, void(*)(void*)>(__t, free);
2901 __new_cap /= sizeof(_Tp);
2902 __n = __b.get() + __n_off;
2903 __e = __b.get() + __new_cap;
2904}
2905
2906// true == success
2907template <class _CharT, class _InputIterator>
2908bool
2909money_get<_CharT, _InputIterator>::__do_get(iter_type& __b, iter_type __e,
2910 bool __intl, const locale& __loc,
2911 ios_base::fmtflags __flags,
2912 ios_base::iostate& __err,
2913 bool& __neg,
2914 const ctype<char_type>& __ct,
2915 unique_ptr<char_type, void(*)(void*)>& __wb,
2916 char_type*& __wn, char_type* __we)
2917{
2918 const unsigned __bz = 100;
2919 unsigned __gbuf[__bz];
2920 unique_ptr<unsigned, void(*)(void*)> __gb(__gbuf, __do_nothing);
2921 unsigned* __gn = __gb.get();
2922 unsigned* __ge = __gn + __bz;
2923 money_base::pattern __pat;
2924 char_type __dp;
2925 char_type __ts;
2926 string __grp;
2927 string_type __sym;
2928 string_type __psn;
2929 string_type __nsn;
2930 int __fd;
2931 __money_get<_CharT>::__gather_info(__intl, __loc, __pat, __dp, __ts, __grp,
2932 __sym, __psn, __nsn, __fd);
2933 const string_type* __trailing_sign = 0;
2934 __wn = __wb.get();
2935 for (unsigned __p = 0; __p < 4 && __b != __e; ++__p)
2936 {
2937 switch (__pat.field[__p])
2938 {
2939 case money_base::space:
2940 if (__p != 3)
2941 {
2942 if (__ct.is(ctype_base::space, *__b))
2943 ++__b;
2944 else
2945 {
2946 __err |= ios_base::failbit;
2947 return false;
2948 }
2949 }
Howard Hinnant324bb032010-08-22 00:02:432950 // drop through
Howard Hinnantbc8d3f92010-05-11 19:42:162951 case money_base::none:
2952 if (__p != 3)
2953 {
2954 while (__b != __e && __ct.is(ctype_base::space, *__b))
2955 ++__b;
2956 }
2957 break;
2958 case money_base::sign:
2959 if (__psn.size() + __nsn.size() > 0)
2960 {
2961 if (__psn.size() == 0 || __nsn.size() == 0)
2962 { // sign is optional
2963 if (__psn.size() > 0)
2964 { // __nsn.size() == 0
2965 if (*__b == __psn[0])
2966 {
2967 ++__b;
2968 if (__psn.size() > 1)
2969 __trailing_sign = &__psn;
2970 }
2971 else
2972 __neg = true;
2973 }
2974 else if (*__b == __nsn[0]) // __nsn.size() > 0 && __psn.size() == 0
2975 {
2976 ++__b;
2977 __neg = true;
2978 if (__nsn.size() > 1)
2979 __trailing_sign = &__nsn;
2980 }
2981 }
2982 else // sign is required
2983 {
2984 if (*__b == __psn[0])
2985 {
2986 ++__b;
2987 if (__psn.size() > 1)
2988 __trailing_sign = &__psn;
2989 }
2990 else if (*__b == __nsn[0])
2991 {
2992 ++__b;
2993 __neg = true;
2994 if (__nsn.size() > 1)
2995 __trailing_sign = &__nsn;
2996 }
2997 else
2998 {
2999 __err |= ios_base::failbit;
3000 return false;
3001 }
3002 }
3003 }
3004 break;
3005 case money_base::symbol:
3006 {
3007 bool __more_needed = __trailing_sign ||
3008 (__p < 2) ||
3009 (__p == 2 && __pat.field[3] != static_cast<char>(money_base::none));
3010 bool __sb = __flags & ios_base::showbase;
3011 if (__sb || __more_needed)
3012 {
3013 ios_base::iostate __et = ios_base::goodbit;
3014 string_type* __k = __scan_keyword(__b, __e, &__sym, &__sym+1,
3015 __ct, __et);
3016 if (__sb && __k != &__sym)
3017 {
3018 __err |= ios_base::failbit;
3019 return false;
3020 }
3021 }
3022 }
3023 break;
3024 case money_base::value:
3025 {
3026 unsigned __ng = 0;
3027 for (; __b != __e; ++__b)
3028 {
3029 char_type __c = *__b;
3030 if (__ct.is(ctype_base::digit, __c))
3031 {
3032 if (__wn == __we)
3033 __double_or_nothing(__wb, __wn, __we);
3034 *__wn++ = __c;
3035 ++__ng;
3036 }
3037 else if (__grp.size() > 0 && __ng > 0 && __c == __ts)
3038 {
3039 if (__gn == __ge)
3040 __double_or_nothing(__gb, __gn, __ge);
3041 *__gn++ = __ng;
3042 __ng = 0;
3043 }
3044 else
3045 break;
3046 }
3047 if (__gb.get() != __gn && __ng > 0)
3048 {
3049 if (__gn == __ge)
3050 __double_or_nothing(__gb, __gn, __ge);
3051 *__gn++ = __ng;
3052 }
3053 if (__fd > 0)
3054 {
3055 if (__b == __e || *__b != __dp)
3056 {
3057 __err |= ios_base::failbit;
3058 return false;
3059 }
3060 for (++__b; __fd > 0; --__fd, ++__b)
3061 {
3062 if (__b == __e || !__ct.is(ctype_base::digit, *__b))
3063 {
3064 __err |= ios_base::failbit;
3065 return false;
3066 }
3067 if (__wn == __we)
3068 __double_or_nothing(__wb, __wn, __we);
3069 *__wn++ = *__b;
3070 }
3071 }
3072 if (__wn == __wb.get())
3073 {
3074 __err |= ios_base::failbit;
3075 return false;
3076 }
3077 }
3078 break;
3079 }
3080 }
3081 if (__trailing_sign)
3082 {
3083 for (unsigned __i = 1; __i < __trailing_sign->size(); ++__i, ++__b)
3084 {
3085 if (__b == __e || *__b != (*__trailing_sign)[__i])
3086 {
3087 __err |= ios_base::failbit;
3088 return false;
3089 }
3090 }
3091 }
3092 if (__gb.get() != __gn)
3093 {
3094 ios_base::iostate __et = ios_base::goodbit;
3095 __check_grouping(__grp, __gb.get(), __gn, __et);
3096 if (__et)
3097 {
3098 __err |= ios_base::failbit;
3099 return false;
3100 }
3101 }
3102 return true;
3103}
3104
3105template <class _CharT, class _InputIterator>
3106_InputIterator
3107money_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
3108 bool __intl, ios_base& __iob,
3109 ios_base::iostate& __err,
3110 long double& __v) const
3111{
3112 const unsigned __bz = 100;
3113 char_type __wbuf[__bz];
3114 unique_ptr<char_type, void(*)(void*)> __wb(__wbuf, __do_nothing);
3115 char_type* __wn;
3116 char_type* __we = __wbuf + __bz;
3117 locale __loc = __iob.getloc();
3118 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3119 bool __neg = false;
3120 if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct,
3121 __wb, __wn, __we))
3122 {
3123 const char __src[] = "0123456789";
3124 char_type __atoms[sizeof(__src)-1];
3125 __ct.widen(__src, __src + (sizeof(__src)-1), __atoms);
3126 char __nbuf[__bz];
3127 char* __nc = __nbuf;
3128 unique_ptr<char, void(*)(void*)> __h(0, free);
3129 if (__wn - __wb.get() > __bz-2)
3130 {
3131 __h.reset((char*)malloc(__wn - __wb.get() + 2));
3132 if (__h.get() == 0)
3133 __throw_bad_alloc();
3134 __nc = __h.get();
3135 }
3136 if (__neg)
3137 *__nc++ = '-';
3138 for (const char_type* __w = __wb.get(); __w < __wn; ++__w, ++__nc)
3139 *__nc = __src[find(__atoms, __atoms+sizeof(__atoms), *__w) - __atoms];
3140 *__nc = char();
3141 if (sscanf(__nbuf, "%Lf", &__v) != 1)
3142 __throw_runtime_error("money_get error");
3143 }
3144 if (__b == __e)
3145 __err |= ios_base::eofbit;
3146 return __b;
3147}
3148
3149template <class _CharT, class _InputIterator>
3150_InputIterator
3151money_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
3152 bool __intl, ios_base& __iob,
3153 ios_base::iostate& __err,
3154 string_type& __v) const
3155{
3156 const unsigned __bz = 100;
3157 char_type __wbuf[__bz];
3158 unique_ptr<char_type, void(*)(void*)> __wb(__wbuf, __do_nothing);
3159 char_type* __wn;
3160 char_type* __we = __wbuf + __bz;
3161 locale __loc = __iob.getloc();
3162 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3163 bool __neg = false;
3164 if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct,
3165 __wb, __wn, __we))
3166 {
3167 __v.clear();
3168 if (__neg)
3169 __v.push_back(__ct.widen('-'));
3170 char_type __z = __ct.widen('0');
3171 char_type* __w;
3172 for (__w = __wb.get(); __w < __wn-1; ++__w)
3173 if (*__w != __z)
3174 break;
3175 __v.append(__w, __wn);
3176 }
3177 if (__b == __e)
3178 __err |= ios_base::eofbit;
3179 return __b;
3180}
3181
3182extern template class money_get<char>;
3183extern template class money_get<wchar_t>;
3184
3185// money_put
3186
3187template <class _CharT>
3188class __money_put
3189{
3190protected:
3191 typedef _CharT char_type;
3192 typedef basic_string<char_type> string_type;
3193
3194 _LIBCPP_ALWAYS_INLINE __money_put() {}
3195
3196 static void __gather_info(bool __intl, bool __neg, const locale& __loc,
3197 money_base::pattern& __pat, char_type& __dp,
3198 char_type& __ts, string& __grp,
3199 string_type& __sym, string_type& __sn,
3200 int& __fd);
3201 static void __format(char_type* __mb, char_type*& __mi, char_type*& __me,
3202 ios_base::fmtflags __flags,
3203 const char_type* __db, const char_type* __de,
3204 const ctype<char_type>& __ct, bool __neg,
3205 const money_base::pattern& __pat, char_type __dp,
3206 char_type __ts, const string& __grp,
3207 const string_type& __sym, const string_type& __sn,
3208 int __fd);
3209};
3210
3211template <class _CharT>
3212void
3213__money_put<_CharT>::__gather_info(bool __intl, bool __neg, const locale& __loc,
3214 money_base::pattern& __pat, char_type& __dp,
3215 char_type& __ts, string& __grp,
3216 string_type& __sym, string_type& __sn,
3217 int& __fd)
3218{
3219 if (__intl)
3220 {
3221 const moneypunct<char_type, true>& __mp =
3222 use_facet<moneypunct<char_type, true> >(__loc);
3223 if (__neg)
3224 {
3225 __pat = __mp.neg_format();
3226 __sn = __mp.negative_sign();
3227 }
3228 else
3229 {
3230 __pat = __mp.pos_format();
3231 __sn = __mp.positive_sign();
3232 }
3233 __dp = __mp.decimal_point();
3234 __ts = __mp.thousands_sep();
3235 __grp = __mp.grouping();
3236 __sym = __mp.curr_symbol();
3237 __fd = __mp.frac_digits();
3238 }
3239 else
3240 {
3241 const moneypunct<char_type, false>& __mp =
3242 use_facet<moneypunct<char_type, false> >(__loc);
3243 if (__neg)
3244 {
3245 __pat = __mp.neg_format();
3246 __sn = __mp.negative_sign();
3247 }
3248 else
3249 {
3250 __pat = __mp.pos_format();
3251 __sn = __mp.positive_sign();
3252 }
3253 __dp = __mp.decimal_point();
3254 __ts = __mp.thousands_sep();
3255 __grp = __mp.grouping();
3256 __sym = __mp.curr_symbol();
3257 __fd = __mp.frac_digits();
3258 }
3259}
3260
3261template <class _CharT>
3262void
3263__money_put<_CharT>::__format(char_type* __mb, char_type*& __mi, char_type*& __me,
3264 ios_base::fmtflags __flags,
3265 const char_type* __db, const char_type* __de,
3266 const ctype<char_type>& __ct, bool __neg,
3267 const money_base::pattern& __pat, char_type __dp,
3268 char_type __ts, const string& __grp,
3269 const string_type& __sym, const string_type& __sn,
3270 int __fd)
3271{
3272 __me = __mb;
3273 for (unsigned __p = 0; __p < 4; ++__p)
3274 {
3275 switch (__pat.field[__p])
3276 {
3277 case money_base::none:
3278 __mi = __me;
3279 break;
3280 case money_base::space:
3281 __mi = __me;
3282 *__me++ = __ct.widen(' ');
3283 break;
3284 case money_base::sign:
3285 if (!__sn.empty())
3286 *__me++ = __sn[0];
3287 break;
3288 case money_base::symbol:
3289 if (!__sym.empty() && (__flags & ios_base::showbase))
Howard Hinnant0949eed2011-06-30 21:18:193290 __me = _VSTD::copy(__sym.begin(), __sym.end(), __me);
Howard Hinnantbc8d3f92010-05-11 19:42:163291 break;
3292 case money_base::value:
3293 {
3294 // remember start of value so we can reverse it
3295 char_type* __t = __me;
3296 // find beginning of digits
3297 if (__neg)
3298 ++__db;
3299 // find end of digits
3300 const char_type* __d;
3301 for (__d = __db; __d < __de; ++__d)
3302 if (!__ct.is(ctype_base::digit, *__d))
3303 break;
3304 // print fractional part
3305 if (__fd > 0)
3306 {
3307 int __f;
3308 for (__f = __fd; __d > __db && __f > 0; --__f)
3309 *__me++ = *--__d;
3310 char_type __z = __f > 0 ? __ct.widen('0') : char_type();
3311 for (; __f > 0; --__f)
3312 *__me++ = __z;
3313 *__me++ = __dp;
3314 }
3315 // print units part
3316 if (__d == __db)
3317 {
3318 *__me++ = __ct.widen('0');
3319 }
3320 else
3321 {
3322 unsigned __ng = 0;
3323 unsigned __ig = 0;
3324 unsigned __gl = __grp.empty() ? numeric_limits<unsigned>::max()
3325 : static_cast<unsigned>(__grp[__ig]);
3326 while (__d != __db)
3327 {
3328 if (__ng == __gl)
3329 {
3330 *__me++ = __ts;
3331 __ng = 0;
3332 if (++__ig < __grp.size())
3333 __gl = __grp[__ig] == numeric_limits<char>::max() ?
3334 numeric_limits<unsigned>::max() :
3335 static_cast<unsigned>(__grp[__ig]);
3336 }
3337 *__me++ = *--__d;
3338 ++__ng;
3339 }
3340 }
3341 // reverse it
3342 reverse(__t, __me);
3343 }
3344 break;
3345 }
3346 }
3347 // print rest of sign, if any
3348 if (__sn.size() > 1)
Howard Hinnant0949eed2011-06-30 21:18:193349 __me = _VSTD::copy(__sn.begin()+1, __sn.end(), __me);
Howard Hinnantbc8d3f92010-05-11 19:42:163350 // set alignment
3351 if ((__flags & ios_base::adjustfield) == ios_base::left)
3352 __mi = __me;
3353 else if ((__flags & ios_base::adjustfield) != ios_base::internal)
3354 __mi = __mb;
3355}
3356
3357extern template class __money_put<char>;
3358extern template class __money_put<wchar_t>;
3359
3360template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant82894812010-09-22 16:48:343361class _LIBCPP_VISIBLE money_put
Howard Hinnantbc8d3f92010-05-11 19:42:163362 : public locale::facet,
3363 private __money_put<_CharT>
3364{
3365public:
3366 typedef _CharT char_type;
3367 typedef _OutputIterator iter_type;
3368 typedef basic_string<char_type> string_type;
3369
3370 _LIBCPP_ALWAYS_INLINE
3371 explicit money_put(size_t __refs = 0)
3372 : locale::facet(__refs) {}
3373
3374 _LIBCPP_ALWAYS_INLINE
3375 iter_type put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl,
3376 long double __units) const
3377 {
3378 return do_put(__s, __intl, __iob, __fl, __units);
3379 }
3380
3381 _LIBCPP_ALWAYS_INLINE
3382 iter_type put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl,
3383 const string_type& __digits) const
3384 {
3385 return do_put(__s, __intl, __iob, __fl, __digits);
3386 }
3387
3388 static locale::id id;
3389
3390protected:
Howard Hinnant82894812010-09-22 16:48:343391 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:163392 ~money_put() {}
3393
3394 virtual iter_type do_put(iter_type __s, bool __intl, ios_base& __iob,
3395 char_type __fl, long double __units) const;
3396 virtual iter_type do_put(iter_type __s, bool __intl, ios_base& __iob,
3397 char_type __fl, const string_type& __digits) const;
3398};
3399
3400template <class _CharT, class _OutputIterator>
3401locale::id
3402money_put<_CharT, _OutputIterator>::id;
3403
3404template <class _CharT, class _OutputIterator>
3405_OutputIterator
3406money_put<_CharT, _OutputIterator>::do_put(iter_type __s, bool __intl,
3407 ios_base& __iob, char_type __fl,
3408 long double __units) const
3409{
3410 // convert to char
3411 const size_t __bs = 100;
3412 char __buf[__bs];
3413 char* __bb = __buf;
3414 char_type __digits[__bs];
3415 char_type* __db = __digits;
3416 size_t __n = snprintf(__bb, __bs, "%.0Lf", __units);
3417 unique_ptr<char, void(*)(void*)> __hn(0, free);
3418 unique_ptr<char_type, void(*)(void*)> __hd(0, free);
3419 // secure memory for digit storage
3420 if (__n > __bs-1)
3421 {
Howard Hinnantadff4892010-05-24 17:49:413422 __n = __nolocale_asprintf(&__bb, "%.0Lf", __units);
Howard Hinnantbc8d3f92010-05-11 19:42:163423 if (__bb == 0)
3424 __throw_bad_alloc();
3425 __hn.reset(__bb);
3426 __hd.reset((char_type*)malloc(__n * sizeof(char_type)));
3427 if (__hd == 0)
3428 __throw_bad_alloc();
3429 __db = __hd.get();
3430 }
3431 // gather info
3432 locale __loc = __iob.getloc();
3433 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3434 __ct.widen(__bb, __bb + __n, __db);
3435 bool __neg = __n > 0 && __bb[0] == '-';
3436 money_base::pattern __pat;
3437 char_type __dp;
3438 char_type __ts;
3439 string __grp;
3440 string_type __sym;
3441 string_type __sn;
3442 int __fd;
3443 this->__gather_info(__intl, __neg, __loc, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3444 // secure memory for formatting
3445 char_type __mbuf[__bs];
3446 char_type* __mb = __mbuf;
3447 unique_ptr<char_type, void(*)(void*)> __hw(0, free);
3448 size_t __exn = static_cast<int>(__n) > __fd ?
3449 (__n - __fd) * 2 + __sn.size() + __sym.size() + __fd + 1
3450 : __sn.size() + __sym.size() + __fd + 2;
3451 if (__exn > __bs)
3452 {
3453 __hw.reset((char_type*)malloc(__exn * sizeof(char_type)));
3454 __mb = __hw.get();
3455 if (__mb == 0)
3456 __throw_bad_alloc();
3457 }
3458 // format
3459 char_type* __mi;
3460 char_type* __me;
3461 this->__format(__mb, __mi, __me, __iob.flags(),
3462 __db, __db + __n, __ct,
3463 __neg, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3464 return __pad_and_output(__s, __mb, __mi, __me, __iob, __fl);
3465}
3466
3467template <class _CharT, class _OutputIterator>
3468_OutputIterator
3469money_put<_CharT, _OutputIterator>::do_put(iter_type __s, bool __intl,
3470 ios_base& __iob, char_type __fl,
3471 const string_type& __digits) const
3472{
3473 // gather info
3474 locale __loc = __iob.getloc();
3475 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3476 bool __neg = __digits.size() > 0 && __digits[0] == __ct.widen('-');
3477 money_base::pattern __pat;
3478 char_type __dp;
3479 char_type __ts;
3480 string __grp;
3481 string_type __sym;
3482 string_type __sn;
3483 int __fd;
3484 this->__gather_info(__intl, __neg, __loc, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3485 // secure memory for formatting
3486 char_type __mbuf[100];
3487 char_type* __mb = __mbuf;
3488 unique_ptr<char_type, void(*)(void*)> __h(0, free);
3489 size_t __exn = __digits.size() > __fd ?
3490 (__digits.size() - __fd) * 2 + __sn.size() + __sym.size() + __fd + 1
3491 : __sn.size() + __sym.size() + __fd + 2;
3492 if (__exn > 100)
3493 {
3494 __h.reset((char_type*)malloc(__exn * sizeof(char_type)));
3495 __mb = __h.get();
3496 if (__mb == 0)
3497 __throw_bad_alloc();
3498 }
3499 // format
3500 char_type* __mi;
3501 char_type* __me;
3502 this->__format(__mb, __mi, __me, __iob.flags(),
3503 __digits.data(), __digits.data() + __digits.size(), __ct,
3504 __neg, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3505 return __pad_and_output(__s, __mb, __mi, __me, __iob, __fl);
3506}
3507
3508extern template class money_put<char>;
3509extern template class money_put<wchar_t>;
3510
3511// messages
3512
Howard Hinnant82894812010-09-22 16:48:343513class _LIBCPP_VISIBLE messages_base
Howard Hinnantbc8d3f92010-05-11 19:42:163514{
3515public:
Howard Hinnantb2080c72011-02-25 00:51:083516 typedef ptrdiff_t catalog;
Howard Hinnantbc8d3f92010-05-11 19:42:163517
3518 _LIBCPP_ALWAYS_INLINE messages_base() {}
3519};
3520
3521template <class _CharT>
Howard Hinnant82894812010-09-22 16:48:343522class _LIBCPP_VISIBLE messages
Howard Hinnantbc8d3f92010-05-11 19:42:163523 : public locale::facet,
3524 public messages_base
3525{
3526public:
3527 typedef _CharT char_type;
3528 typedef basic_string<_CharT> string_type;
3529
3530 _LIBCPP_ALWAYS_INLINE
3531 explicit messages(size_t __refs = 0)
3532 : locale::facet(__refs) {}
3533
3534 _LIBCPP_ALWAYS_INLINE
3535 catalog open(const basic_string<char>& __nm, const locale& __loc) const
3536 {
3537 return do_open(__nm, __loc);
3538 }
3539
3540 _LIBCPP_ALWAYS_INLINE
3541 string_type get(catalog __c, int __set, int __msgid,
3542 const string_type& __dflt) const
3543 {
3544 return do_get(__c, __set, __msgid, __dflt);
3545 }
3546
3547 _LIBCPP_ALWAYS_INLINE
3548 void close(catalog __c) const
3549 {
3550 do_close(__c);
3551 }
3552
3553 static locale::id id;
3554
3555protected:
Howard Hinnant82894812010-09-22 16:48:343556 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:163557 ~messages() {}
3558
3559 virtual catalog do_open(const basic_string<char>&, const locale&) const;
3560 virtual string_type do_get(catalog, int __set, int __msgid,
3561 const string_type& __dflt) const;
3562 virtual void do_close(catalog) const;
3563};
3564
3565template <class _CharT>
3566locale::id
3567messages<_CharT>::id;
3568
3569template <class _CharT>
3570typename messages<_CharT>::catalog
3571messages<_CharT>::do_open(const basic_string<char>& __nm, const locale&) const
3572{
Howard Hinnantb2080c72011-02-25 00:51:083573 catalog __cat = reinterpret_cast<catalog>(catopen(__nm.c_str(), NL_CAT_LOCALE));
3574 if (__cat != -1)
3575 __cat = static_cast<catalog>((static_cast<size_t>(__cat) >> 1));
3576 return __cat;
Howard Hinnantbc8d3f92010-05-11 19:42:163577}
3578
3579template <class _CharT>
3580typename messages<_CharT>::string_type
3581messages<_CharT>::do_get(catalog __c, int __set, int __msgid,
3582 const string_type& __dflt) const
3583{
3584 string __ndflt;
3585 __narrow_to_utf8<sizeof(char_type)*__CHAR_BIT__>()(back_inserter(__ndflt),
3586 __dflt.c_str(),
3587 __dflt.c_str() + __dflt.size());
Howard Hinnantb2080c72011-02-25 00:51:083588 if (__c != -1)
3589 __c <<= 1;
3590 nl_catd __cat = reinterpret_cast<nl_catd>(__c);
3591 char* __n = catgets(__cat, __set, __msgid, __ndflt.c_str());
Howard Hinnantbc8d3f92010-05-11 19:42:163592 string_type __w;
3593 __widen_from_utf8<sizeof(char_type)*__CHAR_BIT__>()(back_inserter(__w),
3594 __n, __n + strlen(__n));
3595 return __w;
3596}
3597
3598template <class _CharT>
3599void
3600messages<_CharT>::do_close(catalog __c) const
3601{
Howard Hinnantb2080c72011-02-25 00:51:083602 if (__c != -1)
3603 __c <<= 1;
3604 nl_catd __cat = reinterpret_cast<nl_catd>(__c);
3605 catclose(__cat);
Howard Hinnantbc8d3f92010-05-11 19:42:163606}
3607
3608extern template class messages<char>;
3609extern template class messages<wchar_t>;
3610
3611template <class _CharT>
Howard Hinnant82894812010-09-22 16:48:343612class _LIBCPP_VISIBLE messages_byname
Howard Hinnantbc8d3f92010-05-11 19:42:163613 : public messages<_CharT>
3614{
3615public:
3616 typedef messages_base::catalog catalog;
3617 typedef basic_string<_CharT> string_type;
3618
3619 _LIBCPP_ALWAYS_INLINE
3620 explicit messages_byname(const char*, size_t __refs = 0)
3621 : messages<_CharT>(__refs) {}
3622
3623 _LIBCPP_ALWAYS_INLINE
3624 explicit messages_byname(const string&, size_t __refs = 0)
3625 : messages<_CharT>(__refs) {}
3626
3627protected:
Howard Hinnant82894812010-09-22 16:48:343628 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:163629 ~messages_byname() {}
3630};
3631
3632extern template class messages_byname<char>;
3633extern template class messages_byname<wchar_t>;
3634
Howard Hinnantd23b4642010-05-31 20:58:543635template<class _Codecvt, class _Elem = wchar_t,
3636 class _Wide_alloc = allocator<_Elem>,
3637 class _Byte_alloc = allocator<char> >
Howard Hinnant82894812010-09-22 16:48:343638class _LIBCPP_VISIBLE wstring_convert
Howard Hinnantd23b4642010-05-31 20:58:543639{
3640public:
3641 typedef basic_string<char, char_traits<char>, _Byte_alloc> byte_string;
3642 typedef basic_string<_Elem, char_traits<_Elem>, _Wide_alloc> wide_string;
3643 typedef typename _Codecvt::state_type state_type;
3644 typedef typename wide_string::traits_type::int_type int_type;
3645
3646private:
3647 byte_string __byte_err_string_;
3648 wide_string __wide_err_string_;
3649 _Codecvt* __cvtptr_;
3650 state_type __cvtstate_;
3651 size_t __cvtcount_;
3652
3653 wstring_convert(const wstring_convert& __wc);
3654 wstring_convert& operator=(const wstring_convert& __wc);
3655public:
3656 wstring_convert(_Codecvt* __pcvt = new _Codecvt);
3657 wstring_convert(_Codecvt* __pcvt, state_type __state);
3658 wstring_convert(const byte_string& __byte_err,
3659 const wide_string& __wide_err = wide_string());
Howard Hinnant73d21a42010-09-04 23:28:193660#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantd23b4642010-05-31 20:58:543661 wstring_convert(wstring_convert&& __wc);
3662#endif
3663 ~wstring_convert();
3664
Howard Hinnant82894812010-09-22 16:48:343665 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:543666 wide_string from_bytes(char __byte)
3667 {return from_bytes(&__byte, &__byte+1);}
Howard Hinnant82894812010-09-22 16:48:343668 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:543669 wide_string from_bytes(const char* __ptr)
3670 {return from_bytes(__ptr, __ptr + char_traits<char>::length(__ptr));}
Howard Hinnant82894812010-09-22 16:48:343671 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:543672 wide_string from_bytes(const byte_string& __str)
3673 {return from_bytes(__str.data(), __str.data() + __str.size());}
3674 wide_string from_bytes(const char* __first, const char* __last);
3675
Howard Hinnant82894812010-09-22 16:48:343676 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:543677 byte_string to_bytes(_Elem __wchar)
3678 {return to_bytes(&__wchar, &__wchar+1);}
Howard Hinnant82894812010-09-22 16:48:343679 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:543680 byte_string to_bytes(const _Elem* __wptr)
3681 {return to_bytes(__wptr, __wptr + char_traits<_Elem>::length(__wptr));}
Howard Hinnant82894812010-09-22 16:48:343682 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:543683 byte_string to_bytes(const wide_string& __wstr)
3684 {return to_bytes(__wstr.data(), __wstr.data() + __wstr.size());}
3685 byte_string to_bytes(const _Elem* __first, const _Elem* __last);
3686
Howard Hinnant82894812010-09-22 16:48:343687 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:543688 size_t converted() const {return __cvtcount_;}
Howard Hinnant82894812010-09-22 16:48:343689 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:543690 state_type state() const {return __cvtstate_;}
3691};
3692
3693template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Howard Hinnant82894812010-09-22 16:48:343694inline _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:543695wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3696 wstring_convert(_Codecvt* __pcvt)
3697 : __cvtptr_(__pcvt), __cvtstate_(), __cvtcount_(0)
3698{
3699}
3700
3701template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Howard Hinnant82894812010-09-22 16:48:343702inline _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:543703wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3704 wstring_convert(_Codecvt* __pcvt, state_type __state)
3705 : __cvtptr_(__pcvt), __cvtstate_(__state), __cvtcount_(0)
3706{
3707}
3708
3709template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3710wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3711 wstring_convert(const byte_string& __byte_err, const wide_string& __wide_err)
3712 : __byte_err_string_(__byte_err), __wide_err_string_(__wide_err),
3713 __cvtstate_(), __cvtcount_(0)
3714{
3715 __cvtptr_ = new _Codecvt;
3716}
3717
Howard Hinnant73d21a42010-09-04 23:28:193718#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantd23b4642010-05-31 20:58:543719
3720template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Howard Hinnant82894812010-09-22 16:48:343721inline _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:543722wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3723 wstring_convert(wstring_convert&& __wc)
Howard Hinnant0949eed2011-06-30 21:18:193724 : __byte_err_string_(_VSTD::move(__wc.__byte_err_string_)),
3725 __wide_err_string_(_VSTD::move(__wc.__wide_err_string_)),
Howard Hinnantd23b4642010-05-31 20:58:543726 __cvtptr_(__wc.__cvtptr_),
3727 __cvtstate_(__wc.__cvtstate_), __cvtcount_(__wc.__cvtstate_)
3728{
3729 __wc.__cvtptr_ = nullptr;
3730}
3731
Howard Hinnantbfd55302010-09-04 23:46:483732#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantd23b4642010-05-31 20:58:543733
3734template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3735wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::~wstring_convert()
3736{
3737 delete __cvtptr_;
3738}
3739
3740template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3741typename wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::wide_string
3742wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3743 from_bytes(const char* __frm, const char* __frm_end)
3744{
3745 __cvtcount_ = 0;
3746 if (__cvtptr_ != nullptr)
3747 {
3748 wide_string __ws(2*(__frm_end - __frm), _Elem());
3749 __ws.resize(__ws.capacity());
3750 codecvt_base::result __r = codecvt_base::ok;
3751 state_type __st = __cvtstate_;
3752 if (__frm != __frm_end)
3753 {
3754 _Elem* __to = &__ws[0];
3755 _Elem* __to_end = __to + __ws.size();
3756 const char* __frm_nxt;
3757 do
3758 {
3759 _Elem* __to_nxt;
3760 __r = __cvtptr_->in(__st, __frm, __frm_end, __frm_nxt,
3761 __to, __to_end, __to_nxt);
3762 __cvtcount_ += __frm_nxt - __frm;
3763 if (__frm_nxt == __frm)
3764 {
3765 __r = codecvt_base::error;
3766 }
3767 else if (__r == codecvt_base::noconv)
3768 {
3769 __ws.resize(__to - &__ws[0]);
3770 // This only gets executed if _Elem is char
3771 __ws.append((const _Elem*)__frm, (const _Elem*)__frm_end);
3772 __frm = __frm_nxt;
3773 __r = codecvt_base::ok;
3774 }
3775 else if (__r == codecvt_base::ok)
3776 {
3777 __ws.resize(__to_nxt - &__ws[0]);
3778 __frm = __frm_nxt;
3779 }
3780 else if (__r == codecvt_base::partial)
3781 {
3782 ptrdiff_t __s = __to_nxt - &__ws[0];
3783 __ws.resize(2 * __s);
3784 __to = &__ws[0] + __s;
3785 __to_end = &__ws[0] + __ws.size();
3786 __frm = __frm_nxt;
3787 }
3788 } while (__r == codecvt_base::partial && __frm_nxt < __frm_end);
3789 }
3790 if (__r == codecvt_base::ok)
3791 return __ws;
3792 }
Howard Hinnantd4444702010-08-11 17:04:313793#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:543794 if (__wide_err_string_.empty())
3795 throw range_error("wstring_convert: from_bytes error");
Howard Hinnant324bb032010-08-22 00:02:433796#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:543797 return __wide_err_string_;
3798}
3799
3800template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3801typename wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::byte_string
3802wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3803 to_bytes(const _Elem* __frm, const _Elem* __frm_end)
3804{
3805 __cvtcount_ = 0;
3806 if (__cvtptr_ != nullptr)
3807 {
3808 byte_string __bs(2*(__frm_end - __frm), char());
3809 __bs.resize(__bs.capacity());
3810 codecvt_base::result __r = codecvt_base::ok;
3811 state_type __st = __cvtstate_;
3812 if (__frm != __frm_end)
3813 {
3814 char* __to = &__bs[0];
3815 char* __to_end = __to + __bs.size();
3816 const _Elem* __frm_nxt;
3817 do
3818 {
3819 char* __to_nxt;
3820 __r = __cvtptr_->out(__st, __frm, __frm_end, __frm_nxt,
3821 __to, __to_end, __to_nxt);
3822 __cvtcount_ += __frm_nxt - __frm;
3823 if (__frm_nxt == __frm)
3824 {
3825 __r = codecvt_base::error;
3826 }
3827 else if (__r == codecvt_base::noconv)
3828 {
3829 __bs.resize(__to - &__bs[0]);
3830 // This only gets executed if _Elem is char
3831 __bs.append((const char*)__frm, (const char*)__frm_end);
3832 __frm = __frm_nxt;
3833 __r = codecvt_base::ok;
3834 }
3835 else if (__r == codecvt_base::ok)
3836 {
3837 __bs.resize(__to_nxt - &__bs[0]);
3838 __frm = __frm_nxt;
3839 }
3840 else if (__r == codecvt_base::partial)
3841 {
3842 ptrdiff_t __s = __to_nxt - &__bs[0];
3843 __bs.resize(2 * __s);
3844 __to = &__bs[0] + __s;
3845 __to_end = &__bs[0] + __bs.size();
3846 __frm = __frm_nxt;
3847 }
3848 } while (__r == codecvt_base::partial && __frm_nxt < __frm_end);
3849 }
3850 if (__r == codecvt_base::ok)
3851 {
3852 size_t __s = __bs.size();
3853 __bs.resize(__bs.capacity());
3854 char* __to = &__bs[0] + __s;
3855 char* __to_end = __to + __bs.size();
3856 do
3857 {
3858 char* __to_nxt;
3859 __r = __cvtptr_->unshift(__st, __to, __to_end, __to_nxt);
3860 if (__r == codecvt_base::noconv)
3861 {
3862 __bs.resize(__to - &__bs[0]);
3863 __r = codecvt_base::ok;
3864 }
3865 else if (__r == codecvt_base::ok)
3866 {
3867 __bs.resize(__to_nxt - &__bs[0]);
3868 }
3869 else if (__r == codecvt_base::partial)
3870 {
3871 ptrdiff_t __s = __to_nxt - &__bs[0];
3872 __bs.resize(2 * __s);
3873 __to = &__bs[0] + __s;
3874 __to_end = &__bs[0] + __bs.size();
3875 }
3876 } while (__r == codecvt_base::partial);
3877 if (__r == codecvt_base::ok)
3878 return __bs;
3879 }
3880 }
Howard Hinnantd4444702010-08-11 17:04:313881#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:543882 if (__byte_err_string_.empty())
3883 throw range_error("wstring_convert: to_bytes error");
Howard Hinnant324bb032010-08-22 00:02:433884#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:543885 return __byte_err_string_;
3886}
3887
3888template <class _Codecvt, class _Elem = wchar_t, class _Tr = char_traits<_Elem> >
Howard Hinnant82894812010-09-22 16:48:343889class _LIBCPP_VISIBLE wbuffer_convert
Howard Hinnantd23b4642010-05-31 20:58:543890 : public basic_streambuf<_Elem, _Tr>
3891{
3892public:
3893 // types:
3894 typedef _Elem char_type;
3895 typedef _Tr traits_type;
3896 typedef typename traits_type::int_type int_type;
3897 typedef typename traits_type::pos_type pos_type;
3898 typedef typename traits_type::off_type off_type;
3899 typedef typename _Codecvt::state_type state_type;
3900
3901private:
Howard Hinnant4b53f502010-06-01 20:09:183902 char* __extbuf_;
3903 const char* __extbufnext_;
3904 const char* __extbufend_;
3905 char __extbuf_min_[8];
3906 size_t __ebs_;
3907 char_type* __intbuf_;
3908 size_t __ibs_;
Howard Hinnantd23b4642010-05-31 20:58:543909 streambuf* __bufptr_;
Howard Hinnant4b53f502010-06-01 20:09:183910 _Codecvt* __cv_;
3911 state_type __st_;
3912 ios_base::openmode __cm_;
3913 bool __owns_eb_;
3914 bool __owns_ib_;
3915 bool __always_noconv_;
Howard Hinnantd23b4642010-05-31 20:58:543916
Howard Hinnant4b53f502010-06-01 20:09:183917 wbuffer_convert(const wbuffer_convert&);
3918 wbuffer_convert& operator=(const wbuffer_convert&);
Howard Hinnantd23b4642010-05-31 20:58:543919public:
3920 wbuffer_convert(streambuf* __bytebuf = 0, _Codecvt* __pcvt = new _Codecvt,
Howard Hinnant4b53f502010-06-01 20:09:183921 state_type __state = state_type());
3922 ~wbuffer_convert();
Howard Hinnantd23b4642010-05-31 20:58:543923
Howard Hinnant82894812010-09-22 16:48:343924 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantd23b4642010-05-31 20:58:543925 streambuf* rdbuf() const {return __bufptr_;}
Howard Hinnant82894812010-09-22 16:48:343926 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantd23b4642010-05-31 20:58:543927 streambuf* rdbuf(streambuf* __bytebuf)
3928 {
3929 streambuf* __r = __bufptr_;
3930 __bufptr_ = __bytebuf;
3931 return __r;
3932 }
3933
Howard Hinnant82894812010-09-22 16:48:343934 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant4b53f502010-06-01 20:09:183935 state_type state() const {return __st_;}
Howard Hinnantd23b4642010-05-31 20:58:543936
3937protected:
Howard Hinnant4b53f502010-06-01 20:09:183938 virtual int_type underflow();
3939 virtual int_type pbackfail(int_type __c = traits_type::eof());
Howard Hinnantd23b4642010-05-31 20:58:543940 virtual int_type overflow (int_type __c = traits_type::eof());
Howard Hinnant4b53f502010-06-01 20:09:183941 virtual basic_streambuf<char_type, traits_type>* setbuf(char_type* __s,
3942 streamsize __n);
3943 virtual pos_type seekoff(off_type __off, ios_base::seekdir __way,
3944 ios_base::openmode __wch = ios_base::in | ios_base::out);
3945 virtual pos_type seekpos(pos_type __sp,
3946 ios_base::openmode __wch = ios_base::in | ios_base::out);
3947 virtual int sync();
3948
3949private:
3950 bool __read_mode();
3951 void __write_mode();
3952 wbuffer_convert* __close();
Howard Hinnantd23b4642010-05-31 20:58:543953};
3954
3955template <class _Codecvt, class _Elem, class _Tr>
Howard Hinnant4b53f502010-06-01 20:09:183956wbuffer_convert<_Codecvt, _Elem, _Tr>::
3957 wbuffer_convert(streambuf* __bytebuf, _Codecvt* __pcvt, state_type __state)
3958 : __extbuf_(0),
3959 __extbufnext_(0),
3960 __extbufend_(0),
3961 __ebs_(0),
3962 __intbuf_(0),
3963 __ibs_(0),
3964 __bufptr_(__bytebuf),
3965 __cv_(__pcvt),
3966 __st_(__state),
3967 __cm_(0),
3968 __owns_eb_(false),
3969 __owns_ib_(false),
3970 __always_noconv_(__cv_ ? __cv_->always_noconv() : false)
3971{
3972 setbuf(0, 4096);
3973}
3974
3975template <class _Codecvt, class _Elem, class _Tr>
3976wbuffer_convert<_Codecvt, _Elem, _Tr>::~wbuffer_convert()
3977{
3978 __close();
3979 delete __cv_;
3980 if (__owns_eb_)
3981 delete [] __extbuf_;
3982 if (__owns_ib_)
3983 delete [] __intbuf_;
3984}
3985
3986template <class _Codecvt, class _Elem, class _Tr>
3987typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
3988wbuffer_convert<_Codecvt, _Elem, _Tr>::underflow()
3989{
3990 if (__cv_ == 0 || __bufptr_ == 0)
3991 return traits_type::eof();
3992 bool __initial = __read_mode();
3993 char_type __1buf;
3994 if (this->gptr() == 0)
3995 this->setg(&__1buf, &__1buf+1, &__1buf+1);
3996 const size_t __unget_sz = __initial ? 0 : min<size_t>((this->egptr() - this->eback()) / 2, 4);
3997 int_type __c = traits_type::eof();
3998 if (this->gptr() == this->egptr())
3999 {
4000 memmove(this->eback(), this->egptr() - __unget_sz, __unget_sz * sizeof(char_type));
4001 if (__always_noconv_)
4002 {
4003 streamsize __nmemb = static_cast<streamsize>(this->egptr() - this->eback() - __unget_sz);
4004 __nmemb = __bufptr_->sgetn((char*)this->eback() + __unget_sz, __nmemb);
4005 if (__nmemb != 0)
4006 {
4007 this->setg(this->eback(),
4008 this->eback() + __unget_sz,
4009 this->eback() + __unget_sz + __nmemb);
4010 __c = *this->gptr();
4011 }
4012 }
4013 else
4014 {
4015 memmove(__extbuf_, __extbufnext_, __extbufend_ - __extbufnext_);
4016 __extbufnext_ = __extbuf_ + (__extbufend_ - __extbufnext_);
4017 __extbufend_ = __extbuf_ + (__extbuf_ == __extbuf_min_ ? sizeof(__extbuf_min_) : __ebs_);
Howard Hinnant0949eed2011-06-30 21:18:194018 streamsize __nmemb = _VSTD::min(static_cast<streamsize>(this->egptr() - this->eback() - __unget_sz),
Howard Hinnant4b53f502010-06-01 20:09:184019 static_cast<streamsize>(__extbufend_ - __extbufnext_));
4020 codecvt_base::result __r;
4021 state_type __svs = __st_;
4022 streamsize __nr = __bufptr_->sgetn(const_cast<char*>(__extbufnext_), __nmemb);
4023 if (__nr != 0)
4024 {
4025 __extbufend_ = __extbufnext_ + __nr;
4026 char_type* __inext;
4027 __r = __cv_->in(__st_, __extbuf_, __extbufend_, __extbufnext_,
4028 this->eback() + __unget_sz,
4029 this->egptr(), __inext);
4030 if (__r == codecvt_base::noconv)
4031 {
4032 this->setg((char_type*)__extbuf_, (char_type*)__extbuf_, (char_type*)__extbufend_);
4033 __c = *this->gptr();
4034 }
4035 else if (__inext != this->eback() + __unget_sz)
4036 {
4037 this->setg(this->eback(), this->eback() + __unget_sz, __inext);
4038 __c = *this->gptr();
4039 }
4040 }
4041 }
4042 }
4043 else
4044 __c = *this->gptr();
4045 if (this->eback() == &__1buf)
4046 this->setg(0, 0, 0);
4047 return __c;
4048}
4049
4050template <class _Codecvt, class _Elem, class _Tr>
4051typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
4052wbuffer_convert<_Codecvt, _Elem, _Tr>::pbackfail(int_type __c)
4053{
4054 if (__cv_ != 0 && __bufptr_ != 0 && this->eback() < this->gptr())
4055 {
4056 if (traits_type::eq_int_type(__c, traits_type::eof()))
4057 {
4058 this->gbump(-1);
4059 return traits_type::not_eof(__c);
4060 }
4061 if (traits_type::eq(traits_type::to_char_type(__c), this->gptr()[-1]))
4062 {
4063 this->gbump(-1);
4064 *this->gptr() = traits_type::to_char_type(__c);
4065 return __c;
4066 }
4067 }
4068 return traits_type::eof();
4069}
4070
4071template <class _Codecvt, class _Elem, class _Tr>
Howard Hinnantd23b4642010-05-31 20:58:544072typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
4073wbuffer_convert<_Codecvt, _Elem, _Tr>::overflow(int_type __c)
4074{
Howard Hinnant4b53f502010-06-01 20:09:184075 if (__cv_ == 0 || __bufptr_ == 0)
4076 return traits_type::eof();
4077 __write_mode();
4078 char_type __1buf;
4079 char_type* __pb_save = this->pbase();
4080 char_type* __epb_save = this->epptr();
4081 if (!traits_type::eq_int_type(__c, traits_type::eof()))
4082 {
4083 if (this->pptr() == 0)
4084 this->setp(&__1buf, &__1buf+1);
4085 *this->pptr() = traits_type::to_char_type(__c);
4086 this->pbump(1);
4087 }
4088 if (this->pptr() != this->pbase())
4089 {
4090 if (__always_noconv_)
4091 {
4092 streamsize __nmemb = static_cast<streamsize>(this->pptr() - this->pbase());
4093 if (__bufptr_->sputn((const char*)this->pbase(), __nmemb) != __nmemb)
4094 return traits_type::eof();
4095 }
4096 else
4097 {
4098 char* __extbe = __extbuf_;
4099 codecvt_base::result __r;
4100 do
4101 {
4102 const char_type* __e;
4103 __r = __cv_->out(__st_, this->pbase(), this->pptr(), __e,
4104 __extbuf_, __extbuf_ + __ebs_, __extbe);
4105 if (__e == this->pbase())
4106 return traits_type::eof();
4107 if (__r == codecvt_base::noconv)
4108 {
4109 streamsize __nmemb = static_cast<size_t>(this->pptr() - this->pbase());
4110 if (__bufptr_->sputn((const char*)this->pbase(), __nmemb) != __nmemb)
4111 return traits_type::eof();
4112 }
4113 else if (__r == codecvt_base::ok || __r == codecvt_base::partial)
4114 {
4115 streamsize __nmemb = static_cast<size_t>(__extbe - __extbuf_);
4116 if (__bufptr_->sputn(__extbuf_, __nmemb) != __nmemb)
4117 return traits_type::eof();
4118 if (__r == codecvt_base::partial)
4119 {
4120 this->setp((char_type*)__e, this->pptr());
4121 this->pbump(this->epptr() - this->pbase());
4122 }
4123 }
4124 else
4125 return traits_type::eof();
4126 } while (__r == codecvt_base::partial);
4127 }
4128 this->setp(__pb_save, __epb_save);
4129 }
4130 return traits_type::not_eof(__c);
4131}
4132
4133template <class _Codecvt, class _Elem, class _Tr>
4134basic_streambuf<_Elem, _Tr>*
4135wbuffer_convert<_Codecvt, _Elem, _Tr>::setbuf(char_type* __s, streamsize __n)
4136{
4137 this->setg(0, 0, 0);
4138 this->setp(0, 0);
4139 if (__owns_eb_)
4140 delete [] __extbuf_;
4141 if (__owns_ib_)
4142 delete [] __intbuf_;
4143 __ebs_ = __n;
4144 if (__ebs_ > sizeof(__extbuf_min_))
4145 {
4146 if (__always_noconv_ && __s)
4147 {
4148 __extbuf_ = (char*)__s;
4149 __owns_eb_ = false;
4150 }
4151 else
4152 {
4153 __extbuf_ = new char[__ebs_];
4154 __owns_eb_ = true;
4155 }
4156 }
4157 else
4158 {
4159 __extbuf_ = __extbuf_min_;
4160 __ebs_ = sizeof(__extbuf_min_);
4161 __owns_eb_ = false;
4162 }
4163 if (!__always_noconv_)
4164 {
4165 __ibs_ = max<streamsize>(__n, sizeof(__extbuf_min_));
4166 if (__s && __ibs_ >= sizeof(__extbuf_min_))
4167 {
4168 __intbuf_ = __s;
4169 __owns_ib_ = false;
4170 }
4171 else
4172 {
4173 __intbuf_ = new char_type[__ibs_];
4174 __owns_ib_ = true;
4175 }
4176 }
4177 else
4178 {
4179 __ibs_ = 0;
4180 __intbuf_ = 0;
4181 __owns_ib_ = false;
4182 }
4183 return this;
4184}
4185
4186template <class _Codecvt, class _Elem, class _Tr>
4187typename wbuffer_convert<_Codecvt, _Elem, _Tr>::pos_type
4188wbuffer_convert<_Codecvt, _Elem, _Tr>::seekoff(off_type __off, ios_base::seekdir __way,
4189 ios_base::openmode __om)
4190{
4191 int __width = __cv_->encoding();
4192 if (__cv_ == 0 || __bufptr_ == 0 || (__width <= 0 && __off != 0) || sync())
4193 return pos_type(off_type(-1));
4194 // __width > 0 || __off == 0
4195 switch (__way)
4196 {
4197 case ios_base::beg:
4198 break;
4199 case ios_base::cur:
4200 break;
4201 case ios_base::end:
4202 break;
4203 default:
4204 return pos_type(off_type(-1));
4205 }
4206 pos_type __r = __bufptr_->pubseekoff(__width * __off, __way, __om);
4207 __r.state(__st_);
4208 return __r;
4209}
4210
4211template <class _Codecvt, class _Elem, class _Tr>
4212typename wbuffer_convert<_Codecvt, _Elem, _Tr>::pos_type
4213wbuffer_convert<_Codecvt, _Elem, _Tr>::seekpos(pos_type __sp, ios_base::openmode __wch)
4214{
4215 if (__cv_ == 0 || __bufptr_ == 0 || sync())
4216 return pos_type(off_type(-1));
4217 if (__bufptr_->pubseekpos(__sp, __wch) == pos_type(off_type(-1)))
4218 return pos_type(off_type(-1));
4219 return __sp;
4220}
4221
4222template <class _Codecvt, class _Elem, class _Tr>
4223int
4224wbuffer_convert<_Codecvt, _Elem, _Tr>::sync()
4225{
4226 if (__cv_ == 0 || __bufptr_ == 0)
4227 return 0;
4228 if (__cm_ & ios_base::out)
4229 {
4230 if (this->pptr() != this->pbase())
4231 if (overflow() == traits_type::eof())
4232 return -1;
4233 codecvt_base::result __r;
4234 do
4235 {
4236 char* __extbe;
4237 __r = __cv_->unshift(__st_, __extbuf_, __extbuf_ + __ebs_, __extbe);
4238 streamsize __nmemb = static_cast<streamsize>(__extbe - __extbuf_);
4239 if (__bufptr_->sputn(__extbuf_, __nmemb) != __nmemb)
4240 return -1;
4241 } while (__r == codecvt_base::partial);
4242 if (__r == codecvt_base::error)
4243 return -1;
4244 if (__bufptr_->pubsync())
4245 return -1;
4246 }
4247 else if (__cm_ & ios_base::in)
4248 {
4249 off_type __c;
4250 if (__always_noconv_)
4251 __c = this->egptr() - this->gptr();
4252 else
4253 {
4254 int __width = __cv_->encoding();
4255 __c = __extbufend_ - __extbufnext_;
4256 if (__width > 0)
4257 __c += __width * (this->egptr() - this->gptr());
4258 else
4259 {
4260 if (this->gptr() != this->egptr())
4261 {
4262 reverse(this->gptr(), this->egptr());
4263 codecvt_base::result __r;
4264 const char_type* __e = this->gptr();
4265 char* __extbe;
4266 do
4267 {
4268 __r = __cv_->out(__st_, __e, this->egptr(), __e,
4269 __extbuf_, __extbuf_ + __ebs_, __extbe);
4270 switch (__r)
4271 {
4272 case codecvt_base::noconv:
4273 __c += this->egptr() - this->gptr();
4274 break;
4275 case codecvt_base::ok:
4276 case codecvt_base::partial:
4277 __c += __extbe - __extbuf_;
4278 break;
4279 default:
4280 return -1;
4281 }
4282 } while (__r == codecvt_base::partial);
4283 }
4284 }
4285 }
4286 if (__bufptr_->pubseekoff(-__c, ios_base::cur, __cm_) == pos_type(off_type(-1)))
4287 return -1;
4288 this->setg(0, 0, 0);
4289 __cm_ = 0;
4290 }
4291 return 0;
4292}
4293
4294template <class _Codecvt, class _Elem, class _Tr>
4295bool
4296wbuffer_convert<_Codecvt, _Elem, _Tr>::__read_mode()
4297{
4298 if (!(__cm_ & ios_base::in))
4299 {
4300 this->setp(0, 0);
4301 if (__always_noconv_)
4302 this->setg((char_type*)__extbuf_,
4303 (char_type*)__extbuf_ + __ebs_,
4304 (char_type*)__extbuf_ + __ebs_);
4305 else
4306 this->setg(__intbuf_, __intbuf_ + __ibs_, __intbuf_ + __ibs_);
4307 __cm_ = ios_base::in;
4308 return true;
4309 }
4310 return false;
4311}
4312
4313template <class _Codecvt, class _Elem, class _Tr>
4314void
4315wbuffer_convert<_Codecvt, _Elem, _Tr>::__write_mode()
4316{
4317 if (!(__cm_ & ios_base::out))
4318 {
4319 this->setg(0, 0, 0);
4320 if (__ebs_ > sizeof(__extbuf_min_))
4321 {
4322 if (__always_noconv_)
4323 this->setp((char_type*)__extbuf_,
4324 (char_type*)__extbuf_ + (__ebs_ - 1));
4325 else
4326 this->setp(__intbuf_, __intbuf_ + (__ibs_ - 1));
4327 }
4328 else
4329 this->setp(0, 0);
4330 __cm_ = ios_base::out;
4331 }
4332}
4333
4334template <class _Codecvt, class _Elem, class _Tr>
4335wbuffer_convert<_Codecvt, _Elem, _Tr>*
4336wbuffer_convert<_Codecvt, _Elem, _Tr>::__close()
4337{
4338 wbuffer_convert* __rt = 0;
4339 if (__cv_ != 0 && __bufptr_ != 0)
4340 {
4341 __rt = this;
4342 if ((__cm_ & ios_base::out) && sync())
4343 __rt = 0;
4344 }
4345 return __rt;
Howard Hinnantd23b4642010-05-31 20:58:544346}
4347
Howard Hinnantbc8d3f92010-05-11 19:42:164348_LIBCPP_END_NAMESPACE_STD
4349
4350#endif // _LIBCPP_LOCALE