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