blob: b1cac28fb840c0b1d19c77b090fcc14c342072ff [file] [log] [blame]
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001// -*- C++ -*-
2//===-------------------------- locale ------------------------------------===//
3//
Howard Hinnantf5256e12010-05-11 21:36:01 +00004// The LLVM Compiler Infrastructure
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005//
Howard Hinnantb64f8b02010-11-16 22:09:02 +00006// This file is dual licensed under the MIT and the University of Illinois Open
7// Source Licenses. See LICENSE.TXT for details.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00008//
9//===----------------------------------------------------------------------===//
10
11#ifndef _LIBCPP_LOCALE
12#define _LIBCPP_LOCALE
13
14/*
15 locale synopsis
16
17namespace std
18{
19
20class locale
21{
22public:
23 // types:
24 class facet;
25 class id;
26
27 typedef int category;
28 static const category // values assigned here are for exposition only
29 none = 0x000,
30 collate = 0x010,
31 ctype = 0x020,
32 monetary = 0x040,
33 numeric = 0x080,
34 time = 0x100,
35 messages = 0x200,
36 all = collate | ctype | monetary | numeric | time | messages;
37
38 // construct/copy/destroy:
Howard Hinnantc9834542011-05-31 15:34:58 +000039 locale() noexcept;
40 locale(const locale& other) noexcept;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000041 explicit locale(const char* std_name);
42 explicit locale(const string& std_name);
43 locale(const locale& other, const char* std_name, category);
44 locale(const locale& other, const string& std_name, category);
45 template <class Facet> locale(const locale& other, Facet* f);
46 locale(const locale& other, const locale& one, category);
47
Howard Hinnantc9834542011-05-31 15:34:58 +000048 ~locale(); // not virtual
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000049
Howard Hinnantc9834542011-05-31 15:34:58 +000050 const locale& operator=(const locale& other) noexcept;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000051
52 template <class Facet> locale combine(const locale& other) const;
53
54 // locale operations:
55 basic_string<char> name() const;
56 bool operator==(const locale& other) const;
57 bool operator!=(const locale& other) const;
58 template <class charT, class Traits, class Allocator>
59 bool operator()(const basic_string<charT,Traits,Allocator>& s1,
60 const basic_string<charT,Traits,Allocator>& s2) const;
61
62 // global locale objects:
63 static locale global(const locale&);
64 static const locale& classic();
65};
66
67template <class Facet> const Facet& use_facet(const locale&);
Howard Hinnantc9834542011-05-31 15:34:58 +000068template <class Facet> bool has_facet(const locale&) noexcept;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000069
70// 22.3.3, convenience interfaces:
71template <class charT> bool isspace (charT c, const locale& loc);
72template <class charT> bool isprint (charT c, const locale& loc);
73template <class charT> bool iscntrl (charT c, const locale& loc);
74template <class charT> bool isupper (charT c, const locale& loc);
75template <class charT> bool islower (charT c, const locale& loc);
76template <class charT> bool isalpha (charT c, const locale& loc);
77template <class charT> bool isdigit (charT c, const locale& loc);
78template <class charT> bool ispunct (charT c, const locale& loc);
79template <class charT> bool isxdigit(charT c, const locale& loc);
80template <class charT> bool isalnum (charT c, const locale& loc);
81template <class charT> bool isgraph (charT c, const locale& loc);
82template <class charT> charT toupper(charT c, const locale& loc);
83template <class charT> charT tolower(charT c, const locale& loc);
Howard Hinnantd23b4642010-05-31 20:58:54 +000084
85template<class Codecvt, class Elem = wchar_t,
86 class Wide_alloc = allocator<Elem>,
87 class Byte_alloc = allocator<char>>
88class wstring_convert
89{
90public:
91 typedef basic_string<char, char_traits<char>, Byte_alloc> byte_string;
92 typedef basic_string<Elem, char_traits<Elem>, Wide_alloc> wide_string;
93 typedef typename Codecvt::state_type state_type;
94 typedef typename wide_string::traits_type::int_type int_type;
95
Marshall Clow83179a72013-08-27 20:18:59 +000096 explicit wstring_convert(Codecvt* pcvt = new Codecvt); // explicit in C++14
Howard Hinnantd23b4642010-05-31 20:58:54 +000097 wstring_convert(Codecvt* pcvt, state_type state);
Marshall Clow83179a72013-08-27 20:18:59 +000098 explicit wstring_convert(const byte_string& byte_err, // explicit in C++14
Howard Hinnantd23b4642010-05-31 20:58:54 +000099 const wide_string& wide_err = wide_string());
Marshall Clow83179a72013-08-27 20:18:59 +0000100 wstring_convert(const wstring_convert&) = delete; // C++14
101 wstring_convert & operator=(const wstring_convert &) = delete; // C++14
Howard Hinnantd23b4642010-05-31 20:58:54 +0000102 ~wstring_convert();
103
104 wide_string from_bytes(char byte);
105 wide_string from_bytes(const char* ptr);
106 wide_string from_bytes(const byte_string& str);
107 wide_string from_bytes(const char* first, const char* last);
108
109 byte_string to_bytes(Elem wchar);
110 byte_string to_bytes(const Elem* wptr);
111 byte_string to_bytes(const wide_string& wstr);
112 byte_string to_bytes(const Elem* first, const Elem* last);
113
Marshall Clow83179a72013-08-27 20:18:59 +0000114 size_t converted() const; // noexcept in C++14
Howard Hinnantd23b4642010-05-31 20:58:54 +0000115 state_type state() const;
116};
117
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000118template <class Codecvt, class Elem = wchar_t, class Tr = char_traits<Elem>>
Howard Hinnantd23b4642010-05-31 20:58:54 +0000119class wbuffer_convert
120 : public basic_streambuf<Elem, Tr>
121{
122public:
123 typedef typename Tr::state_type state_type;
124
Marshall Clow83179a72013-08-27 20:18:59 +0000125 explicit wbuffer_convert(streambuf* bytebuf = 0, Codecvt* pcvt = new Codecvt,
126 state_type state = state_type()); // explicit in C++14
127 wbuffer_convert(const wbuffer_convert&) = delete; // C++14
128 wbuffer_convert & operator=(const wbuffer_convert &) = delete; // C++14
129 ~wbuffer_convert(); // C++14
130
Howard Hinnantd23b4642010-05-31 20:58:54 +0000131 streambuf* rdbuf() const;
132 streambuf* rdbuf(streambuf* bytebuf);
133
134 state_type state() const;
135};
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000136
137// 22.4.1 and 22.4.1.3, ctype:
138class ctype_base;
139template <class charT> class ctype;
140template <> class ctype<char>; // specialization
141template <class charT> class ctype_byname;
142template <> class ctype_byname<char>; // specialization
143
144class codecvt_base;
145template <class internT, class externT, class stateT> class codecvt;
146template <class internT, class externT, class stateT> class codecvt_byname;
147
148// 22.4.2 and 22.4.3, numeric:
149template <class charT, class InputIterator> class num_get;
150template <class charT, class OutputIterator> class num_put;
151template <class charT> class numpunct;
152template <class charT> class numpunct_byname;
153
154// 22.4.4, col lation:
155template <class charT> class collate;
156template <class charT> class collate_byname;
157
158// 22.4.5, date and time:
159class time_base;
160template <class charT, class InputIterator> class time_get;
161template <class charT, class InputIterator> class time_get_byname;
162template <class charT, class OutputIterator> class time_put;
163template <class charT, class OutputIterator> class time_put_byname;
164
165// 22.4.6, money:
166class money_base;
167template <class charT, class InputIterator> class money_get;
168template <class charT, class OutputIterator> class money_put;
169template <class charT, bool Intl> class moneypunct;
170template <class charT, bool Intl> class moneypunct_byname;
171
172// 22.4.7, message retrieval:
173class messages_base;
174template <class charT> class messages;
175template <class charT> class messages_byname;
176
177} // std
178
179*/
180
181#include <__config>
182#include <__locale>
183#include <algorithm>
184#include <memory>
185#include <ios>
186#include <streambuf>
187#include <iterator>
188#include <limits>
Marshall Clowdece7fe2013-03-18 17:45:34 +0000189#ifndef __APPLE__
Howard Hinnantadff4892010-05-24 17:49:41 +0000190#include <cstdarg>
191#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000192#include <cstdlib>
193#include <ctime>
Howard Hinnantef5aa932013-09-17 01:34:47 +0000194#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnant14fa9f92011-09-29 20:33:10 +0000195#include <support/win32/locale_win32.h>
Jonathan Roelofs6a5a8ab2014-09-19 20:09:12 +0000196#elif defined(_NEWLIB_VERSION)
197// FIXME: replace all the uses of _NEWLIB_VERSION with __NEWLIB__ preceded by an
198// include of <sys/cdefs.h> once https://sourceware.org/ml/newlib-cvs/2014-q3/msg00038.html
199// has had a chance to bake for a bit
200#include <support/newlib/xlocale.h>
Ed Schouten0251f0f2015-03-11 16:39:36 +0000201#endif
202#ifdef _LIBCPP_HAS_CATOPEN
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000203#include <nl_types.h>
Marshall Clowa6439262014-07-10 15:20:28 +0000204#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000205
Marshall Clowdece7fe2013-03-18 17:45:34 +0000206#ifdef __APPLE__
Howard Hinnant537b2fa2012-11-14 21:17:15 +0000207#include <Availability.h>
208#endif
209
Howard Hinnant66c6f972011-11-29 16:45:27 +0000210#include <__undef_min_max>
211
Howard Hinnant08e17472011-10-17 20:05:10 +0000212#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000213#pragma GCC system_header
Howard Hinnant08e17472011-10-17 20:05:10 +0000214#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000215
Ben Craigfd556582016-03-09 15:39:39 +0000216#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
217#include <__bsd_locale_defaults.h>
218#else
219#include <__bsd_locale_fallbacks.h>
220#endif
221
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000222_LIBCPP_BEGIN_NAMESPACE_STD
223
Marshall Clow53e27632013-03-18 19:34:07 +0000224#if defined(__APPLE__) || defined(__FreeBSD__)
Howard Hinnant2ea1ca92011-09-28 21:05:01 +0000225# define _LIBCPP_GET_C_LOCALE 0
Ed Schouten681abae2015-03-10 09:35:22 +0000226#elif defined(__CloudABI__) || defined(__NetBSD__)
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +0000227# define _LIBCPP_GET_C_LOCALE LC_C_LOCALE
Howard Hinnant2ea1ca92011-09-28 21:05:01 +0000228#else
229# define _LIBCPP_GET_C_LOCALE __cloc()
Howard Hinnant866569b2011-09-28 23:39:33 +0000230 // Get the C locale object
Howard Hinnant0f678bd2013-08-12 18:38:34 +0000231 _LIBCPP_FUNC_VIS locale_t __cloc();
Howard Hinnant866569b2011-09-28 23:39:33 +0000232#define __cloc_defined
Howard Hinnant2ea1ca92011-09-28 21:05:01 +0000233#endif
234
Sean Huntf3907e62011-07-15 05:40:33 +0000235typedef _VSTD::remove_pointer<locale_t>::type __locale_struct;
236typedef _VSTD::unique_ptr<__locale_struct, decltype(&freelocale)> __locale_unique_ptr;
Howard Hinnantadff4892010-05-24 17:49:41 +0000237
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000238// __scan_keyword
239// Scans [__b, __e) until a match is found in the basic_strings range
240// [__kb, __ke) or until it can be shown that there is no match in [__kb, __ke).
241// __b will be incremented (visibly), consuming CharT until a match is found
242// or proved to not exist. A keyword may be "", in which will match anything.
243// If one keyword is a prefix of another, and the next CharT in the input
244// might match another keyword, the algorithm will attempt to find the longest
245// matching keyword. If the longer matching keyword ends up not matching, then
246// no keyword match is found. If no keyword match is found, __ke is returned
247// and failbit is set in __err.
248// Else an iterator pointing to the matching keyword is found. If more than
249// one keyword matches, an iterator to the first matching keyword is returned.
Alp Tokerec34c482014-05-15 11:27:39 +0000250// If on exit __b == __e, eofbit is set in __err. If __case_sensitive is false,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000251// __ct is used to force to lower case before comparing characters.
252// Examples:
253// Keywords: "a", "abb"
254// If the input is "a", the first keyword matches and eofbit is set.
255// If the input is "abc", no match is found and "ab" are consumed.
256template <class _InputIterator, class _ForwardIterator, class _Ctype>
257_LIBCPP_HIDDEN
258_ForwardIterator
259__scan_keyword(_InputIterator& __b, _InputIterator __e,
260 _ForwardIterator __kb, _ForwardIterator __ke,
261 const _Ctype& __ct, ios_base::iostate& __err,
262 bool __case_sensitive = true)
263{
264 typedef typename iterator_traits<_InputIterator>::value_type _CharT;
Howard Hinnantec3773c2011-12-01 20:21:04 +0000265 size_t __nkw = static_cast<size_t>(_VSTD::distance(__kb, __ke));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000266 const unsigned char __doesnt_match = '\0';
267 const unsigned char __might_match = '\1';
268 const unsigned char __does_match = '\2';
269 unsigned char __statbuf[100];
270 unsigned char* __status = __statbuf;
271 unique_ptr<unsigned char, void(*)(void*)> __stat_hold(0, free);
272 if (__nkw > sizeof(__statbuf))
273 {
274 __status = (unsigned char*)malloc(__nkw);
275 if (__status == 0)
276 __throw_bad_alloc();
277 __stat_hold.reset(__status);
278 }
279 size_t __n_might_match = __nkw; // At this point, any keyword might match
280 size_t __n_does_match = 0; // but none of them definitely do
281 // Initialize all statuses to __might_match, except for "" keywords are __does_match
282 unsigned char* __st = __status;
Eric Fiselierb9919752014-10-27 19:28:20 +0000283 for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, (void) ++__st)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000284 {
285 if (!__ky->empty())
286 *__st = __might_match;
287 else
288 {
289 *__st = __does_match;
290 --__n_might_match;
291 ++__n_does_match;
292 }
293 }
294 // While there might be a match, test keywords against the next CharT
295 for (size_t __indx = 0; __b != __e && __n_might_match > 0; ++__indx)
296 {
297 // Peek at the next CharT but don't consume it
298 _CharT __c = *__b;
299 if (!__case_sensitive)
300 __c = __ct.toupper(__c);
301 bool __consume = false;
302 // For each keyword which might match, see if the __indx character is __c
303 // If a match if found, consume __c
304 // If a match is found, and that is the last character in the keyword,
305 // then that keyword matches.
306 // If the keyword doesn't match this character, then change the keyword
307 // to doesn't match
308 __st = __status;
Eric Fiselierb9919752014-10-27 19:28:20 +0000309 for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, (void) ++__st)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000310 {
311 if (*__st == __might_match)
312 {
313 _CharT __kc = (*__ky)[__indx];
314 if (!__case_sensitive)
315 __kc = __ct.toupper(__kc);
316 if (__c == __kc)
317 {
318 __consume = true;
319 if (__ky->size() == __indx+1)
320 {
321 *__st = __does_match;
322 --__n_might_match;
323 ++__n_does_match;
324 }
325 }
326 else
327 {
328 *__st = __doesnt_match;
329 --__n_might_match;
330 }
331 }
332 }
333 // consume if we matched a character
334 if (__consume)
335 {
336 ++__b;
337 // If we consumed a character and there might be a matched keyword that
338 // was marked matched on a previous iteration, then such keywords
339 // which are now marked as not matching.
340 if (__n_might_match + __n_does_match > 1)
341 {
342 __st = __status;
Eric Fiselierb9919752014-10-27 19:28:20 +0000343 for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, (void) ++__st)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000344 {
345 if (*__st == __does_match && __ky->size() != __indx+1)
346 {
347 *__st = __doesnt_match;
348 --__n_does_match;
349 }
350 }
351 }
352 }
353 }
354 // We've exited the loop because we hit eof and/or we have no more "might matches".
355 if (__b == __e)
356 __err |= ios_base::eofbit;
357 // Return the first matching result
Eric Fiselierb9919752014-10-27 19:28:20 +0000358 for (__st = __status; __kb != __ke; ++__kb, (void) ++__st)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000359 if (*__st == __does_match)
360 break;
361 if (__kb == __ke)
362 __err |= ios_base::failbit;
363 return __kb;
364}
365
Howard Hinnant0f678bd2013-08-12 18:38:34 +0000366struct _LIBCPP_TYPE_VIS __num_get_base
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000367{
368 static const int __num_get_buf_sz = 40;
369
370 static int __get_base(ios_base&);
371 static const char __src[33];
372};
373
Howard Hinnant0f678bd2013-08-12 18:38:34 +0000374_LIBCPP_FUNC_VIS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000375void __check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
376 ios_base::iostate& __err);
377
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000378template <class _CharT>
379struct __num_get
380 : protected __num_get_base
381{
382 static string __stage2_int_prep(ios_base& __iob, _CharT* __atoms, _CharT& __thousands_sep);
383 static string __stage2_float_prep(ios_base& __iob, _CharT* __atoms, _CharT& __decimal_point,
384 _CharT& __thousands_sep);
385 static int __stage2_int_loop(_CharT __ct, int __base, char* __a, char*& __a_end,
386 unsigned& __dc, _CharT __thousands_sep, const string& __grouping,
387 unsigned* __g, unsigned*& __g_end, _CharT* __atoms);
388 static int __stage2_float_loop(_CharT __ct, bool& __in_units, char& __exp,
389 char* __a, char*& __a_end,
390 _CharT __decimal_point, _CharT __thousands_sep,
391 const string& __grouping, unsigned* __g,
392 unsigned*& __g_end, unsigned& __dc, _CharT* __atoms);
393};
394
395template <class _CharT>
396string
397__num_get<_CharT>::__stage2_int_prep(ios_base& __iob, _CharT* __atoms, _CharT& __thousands_sep)
398{
399 locale __loc = __iob.getloc();
400 use_facet<ctype<_CharT> >(__loc).widen(__src, __src + 26, __atoms);
401 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
402 __thousands_sep = __np.thousands_sep();
403 return __np.grouping();
404}
405
406template <class _CharT>
407string
408__num_get<_CharT>::__stage2_float_prep(ios_base& __iob, _CharT* __atoms, _CharT& __decimal_point,
409 _CharT& __thousands_sep)
410{
411 locale __loc = __iob.getloc();
412 use_facet<ctype<_CharT> >(__loc).widen(__src, __src + 32, __atoms);
413 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
414 __decimal_point = __np.decimal_point();
415 __thousands_sep = __np.thousands_sep();
416 return __np.grouping();
417}
418
419template <class _CharT>
420int
421__num_get<_CharT>::__stage2_int_loop(_CharT __ct, int __base, char* __a, char*& __a_end,
422 unsigned& __dc, _CharT __thousands_sep, const string& __grouping,
423 unsigned* __g, unsigned*& __g_end, _CharT* __atoms)
424{
Howard Hinnant80586722011-03-09 01:03:19 +0000425 if (__a_end == __a && (__ct == __atoms[24] || __ct == __atoms[25]))
426 {
427 *__a_end++ = __ct == __atoms[24] ? '+' : '-';
428 __dc = 0;
429 return 0;
430 }
Howard Hinnantec3773c2011-12-01 20:21:04 +0000431 if (__grouping.size() != 0 && __ct == __thousands_sep)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000432 {
433 if (__g_end-__g < __num_get_buf_sz)
434 {
435 *__g_end++ = __dc;
436 __dc = 0;
437 }
438 return 0;
439 }
440 ptrdiff_t __f = find(__atoms, __atoms + 26, __ct) - __atoms;
Howard Hinnant80586722011-03-09 01:03:19 +0000441 if (__f >= 24)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000442 return -1;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000443 switch (__base)
444 {
445 case 8:
446 case 10:
447 if (__f >= __base)
Howard Hinnant80586722011-03-09 01:03:19 +0000448 return -1;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000449 break;
Howard Hinnant80586722011-03-09 01:03:19 +0000450 case 16:
451 if (__f < 22)
452 break;
453 if (__a_end != __a && __a_end - __a <= 2 && __a_end[-1] == '0')
454 {
455 __dc = 0;
456 *__a_end++ = __src[__f];
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000457 return 0;
Howard Hinnant80586722011-03-09 01:03:19 +0000458 }
459 return -1;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000460 }
Howard Hinnantae57a1a2013-04-15 20:40:06 +0000461 *__a_end++ = __src[__f];
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000462 ++__dc;
463 return 0;
464}
465
466template <class _CharT>
467int
468__num_get<_CharT>::__stage2_float_loop(_CharT __ct, bool& __in_units, char& __exp, char* __a, char*& __a_end,
469 _CharT __decimal_point, _CharT __thousands_sep, const string& __grouping,
470 unsigned* __g, unsigned*& __g_end, unsigned& __dc, _CharT* __atoms)
471{
472 if (__ct == __decimal_point)
473 {
474 if (!__in_units)
475 return -1;
476 __in_units = false;
477 *__a_end++ = '.';
478 if (__grouping.size() != 0 && __g_end-__g < __num_get_buf_sz)
479 *__g_end++ = __dc;
480 return 0;
481 }
482 if (__ct == __thousands_sep && __grouping.size() != 0)
483 {
484 if (!__in_units)
485 return -1;
486 if (__g_end-__g < __num_get_buf_sz)
487 {
488 *__g_end++ = __dc;
489 __dc = 0;
490 }
491 return 0;
492 }
493 ptrdiff_t __f = find(__atoms, __atoms + 32, __ct) - __atoms;
494 if (__f >= 32)
495 return -1;
496 char __x = __src[__f];
Howard Hinnantb04ad412012-02-15 19:19:37 +0000497 if (__x == '-' || __x == '+')
498 {
Howard Hinnant6319f142013-03-08 19:06:24 +0000499 if (__a_end == __a || (__a_end[-1] & 0x5F) == (__exp & 0x7F))
Howard Hinnantb04ad412012-02-15 19:19:37 +0000500 {
501 *__a_end++ = __x;
502 return 0;
503 }
504 return -1;
505 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000506 if (__x == 'x' || __x == 'X')
507 __exp = 'P';
Howard Hinnant6319f142013-03-08 19:06:24 +0000508 else if ((__x & 0x5F) == __exp)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000509 {
Howard Hinnant6319f142013-03-08 19:06:24 +0000510 __exp |= 0x80;
511 if (__in_units)
512 {
513 __in_units = false;
514 if (__grouping.size() != 0 && __g_end-__g < __num_get_buf_sz)
515 *__g_end++ = __dc;
516 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000517 }
Howard Hinnantae57a1a2013-04-15 20:40:06 +0000518 *__a_end++ = __x;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000519 if (__f >= 22)
520 return 0;
521 ++__dc;
522 return 0;
523}
524
Howard Hinnant499cea12013-08-23 17:37:05 +0000525_LIBCPP_EXTERN_TEMPLATE2(struct _LIBCPP_TYPE_VIS __num_get<char>)
526_LIBCPP_EXTERN_TEMPLATE2(struct _LIBCPP_TYPE_VIS __num_get<wchar_t>)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000527
528template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnant0f678bd2013-08-12 18:38:34 +0000529class _LIBCPP_TYPE_VIS_ONLY num_get
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000530 : public locale::facet,
531 private __num_get<_CharT>
532{
533public:
534 typedef _CharT char_type;
535 typedef _InputIterator iter_type;
536
537 _LIBCPP_ALWAYS_INLINE
538 explicit num_get(size_t __refs = 0)
539 : locale::facet(__refs) {}
540
541 _LIBCPP_ALWAYS_INLINE
542 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
543 ios_base::iostate& __err, bool& __v) const
544 {
545 return do_get(__b, __e, __iob, __err, __v);
546 }
547
548 _LIBCPP_ALWAYS_INLINE
549 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
550 ios_base::iostate& __err, long& __v) const
551 {
552 return do_get(__b, __e, __iob, __err, __v);
553 }
554
555 _LIBCPP_ALWAYS_INLINE
556 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
557 ios_base::iostate& __err, long long& __v) const
558 {
559 return do_get(__b, __e, __iob, __err, __v);
560 }
561
562 _LIBCPP_ALWAYS_INLINE
563 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
564 ios_base::iostate& __err, unsigned short& __v) const
565 {
566 return do_get(__b, __e, __iob, __err, __v);
567 }
568
569 _LIBCPP_ALWAYS_INLINE
570 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
571 ios_base::iostate& __err, unsigned int& __v) const
572 {
573 return do_get(__b, __e, __iob, __err, __v);
574 }
575
576 _LIBCPP_ALWAYS_INLINE
577 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
578 ios_base::iostate& __err, unsigned long& __v) const
579 {
580 return do_get(__b, __e, __iob, __err, __v);
581 }
582
583 _LIBCPP_ALWAYS_INLINE
584 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
585 ios_base::iostate& __err, unsigned long long& __v) const
586 {
587 return do_get(__b, __e, __iob, __err, __v);
588 }
589
590 _LIBCPP_ALWAYS_INLINE
591 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
592 ios_base::iostate& __err, float& __v) const
593 {
594 return do_get(__b, __e, __iob, __err, __v);
595 }
596
597 _LIBCPP_ALWAYS_INLINE
598 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
599 ios_base::iostate& __err, double& __v) const
600 {
601 return do_get(__b, __e, __iob, __err, __v);
602 }
603
604 _LIBCPP_ALWAYS_INLINE
605 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
606 ios_base::iostate& __err, long double& __v) const
607 {
608 return do_get(__b, __e, __iob, __err, __v);
609 }
610
611 _LIBCPP_ALWAYS_INLINE
612 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
613 ios_base::iostate& __err, void*& __v) const
614 {
615 return do_get(__b, __e, __iob, __err, __v);
616 }
617
618 static locale::id id;
619
620protected:
Howard Hinnant82894812010-09-22 16:48:34 +0000621 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000622 ~num_get() {}
623
Marshall Clow5ffe5912013-11-05 14:28:52 +0000624 template <class _Fp>
625 iter_type __do_get_floating_point
626 (iter_type __b, iter_type __e, ios_base& __iob,
627 ios_base::iostate& __err, _Fp& __v) const;
Marshall Clowfe2a5612013-11-07 01:00:50 +0000628
629 template <class _Signed>
630 iter_type __do_get_signed
631 (iter_type __b, iter_type __e, ios_base& __iob,
632 ios_base::iostate& __err, _Signed& __v) const;
633
634 template <class _Unsigned>
635 iter_type __do_get_unsigned
636 (iter_type __b, iter_type __e, ios_base& __iob,
637 ios_base::iostate& __err, _Unsigned& __v) const;
638
639
640 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
641 ios_base::iostate& __err, bool& __v) const;
642
643 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
644 ios_base::iostate& __err, long& __v) const
645 { return this->__do_get_signed ( __b, __e, __iob, __err, __v ); }
646
647 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
648 ios_base::iostate& __err, long long& __v) const
649 { return this->__do_get_signed ( __b, __e, __iob, __err, __v ); }
650
651 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
652 ios_base::iostate& __err, unsigned short& __v) const
653 { return this->__do_get_unsigned ( __b, __e, __iob, __err, __v ); }
654
655 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
656 ios_base::iostate& __err, unsigned int& __v) const
657 { return this->__do_get_unsigned ( __b, __e, __iob, __err, __v ); }
658
659 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
660 ios_base::iostate& __err, unsigned long& __v) const
661 { return this->__do_get_unsigned ( __b, __e, __iob, __err, __v ); }
662
663 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
664 ios_base::iostate& __err, unsigned long long& __v) const
665 { return this->__do_get_unsigned ( __b, __e, __iob, __err, __v ); }
666
667 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
668 ios_base::iostate& __err, float& __v) const
669 { return this->__do_get_floating_point ( __b, __e, __iob, __err, __v ); }
670
671 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
672 ios_base::iostate& __err, double& __v) const
673 { return this->__do_get_floating_point ( __b, __e, __iob, __err, __v ); }
674
675 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
676 ios_base::iostate& __err, long double& __v) const
677 { return this->__do_get_floating_point ( __b, __e, __iob, __err, __v ); }
678
679 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
680 ios_base::iostate& __err, void*& __v) const;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000681};
682
683template <class _CharT, class _InputIterator>
684locale::id
685num_get<_CharT, _InputIterator>::id;
686
687template <class _Tp>
688_Tp
689__num_get_signed_integral(const char* __a, const char* __a_end,
690 ios_base::iostate& __err, int __base)
691{
692 if (__a != __a_end)
693 {
Howard Hinnant54e2fff2013-01-22 17:26:08 +0000694 typename remove_reference<decltype(errno)>::type __save_errno = errno;
Howard Hinnante7c8da62011-02-25 19:52:41 +0000695 errno = 0;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000696 char *__p2;
Howard Hinnant2ea1ca92011-09-28 21:05:01 +0000697 long long __ll = strtoll_l(__a, &__p2, __base, _LIBCPP_GET_C_LOCALE);
Howard Hinnant54e2fff2013-01-22 17:26:08 +0000698 typename remove_reference<decltype(errno)>::type __current_errno = errno;
Howard Hinnante7c8da62011-02-25 19:52:41 +0000699 if (__current_errno == 0)
700 errno = __save_errno;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000701 if (__p2 != __a_end)
702 {
703 __err = ios_base::failbit;
704 return 0;
705 }
Howard Hinnante7c8da62011-02-25 19:52:41 +0000706 else if (__current_errno == ERANGE ||
707 __ll < numeric_limits<_Tp>::min() ||
708 numeric_limits<_Tp>::max() < __ll)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000709 {
710 __err = ios_base::failbit;
Howard Hinnante7c8da62011-02-25 19:52:41 +0000711 if (__ll > 0)
712 return numeric_limits<_Tp>::max();
713 else
714 return numeric_limits<_Tp>::min();
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000715 }
716 return static_cast<_Tp>(__ll);
717 }
718 __err = ios_base::failbit;
719 return 0;
720}
721
722template <class _Tp>
723_Tp
724__num_get_unsigned_integral(const char* __a, const char* __a_end,
725 ios_base::iostate& __err, int __base)
726{
727 if (__a != __a_end)
728 {
Howard Hinnante7c8da62011-02-25 19:52:41 +0000729 if (*__a == '-')
730 {
731 __err = ios_base::failbit;
732 return 0;
733 }
Howard Hinnant54e2fff2013-01-22 17:26:08 +0000734 typename remove_reference<decltype(errno)>::type __save_errno = errno;
Howard Hinnante7c8da62011-02-25 19:52:41 +0000735 errno = 0;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000736 char *__p2;
Howard Hinnant2ea1ca92011-09-28 21:05:01 +0000737 unsigned long long __ll = strtoull_l(__a, &__p2, __base, _LIBCPP_GET_C_LOCALE);
Howard Hinnant54e2fff2013-01-22 17:26:08 +0000738 typename remove_reference<decltype(errno)>::type __current_errno = errno;
Howard Hinnante7c8da62011-02-25 19:52:41 +0000739 if (__current_errno == 0)
740 errno = __save_errno;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000741 if (__p2 != __a_end)
742 {
743 __err = ios_base::failbit;
744 return 0;
745 }
Howard Hinnante7c8da62011-02-25 19:52:41 +0000746 else if (__current_errno == ERANGE ||
747 numeric_limits<_Tp>::max() < __ll)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000748 {
749 __err = ios_base::failbit;
750 return numeric_limits<_Tp>::max();
751 }
752 return static_cast<_Tp>(__ll);
753 }
754 __err = ios_base::failbit;
755 return 0;
756}
757
758template <class _Tp>
759_Tp
760__num_get_float(const char* __a, const char* __a_end, ios_base::iostate& __err)
761{
762 if (__a != __a_end)
763 {
Howard Hinnant4f671002013-04-13 18:19:25 +0000764 typename remove_reference<decltype(errno)>::type __save_errno = errno;
765 errno = 0;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000766 char *__p2;
Howard Hinnant2ea1ca92011-09-28 21:05:01 +0000767 long double __ld = strtold_l(__a, &__p2, _LIBCPP_GET_C_LOCALE);
Howard Hinnant4f671002013-04-13 18:19:25 +0000768 typename remove_reference<decltype(errno)>::type __current_errno = errno;
769 if (__current_errno == 0)
770 errno = __save_errno;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000771 if (__p2 != __a_end)
772 {
773 __err = ios_base::failbit;
774 return 0;
775 }
Howard Hinnant4f671002013-04-13 18:19:25 +0000776 else if (__current_errno == ERANGE)
777 __err = ios_base::failbit;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000778 return static_cast<_Tp>(__ld);
779 }
780 __err = ios_base::failbit;
781 return 0;
782}
783
784template <class _CharT, class _InputIterator>
785_InputIterator
786num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
787 ios_base& __iob,
788 ios_base::iostate& __err,
789 bool& __v) const
790{
791 if ((__iob.flags() & ios_base::boolalpha) == 0)
792 {
793 long __lv = -1;
794 __b = do_get(__b, __e, __iob, __err, __lv);
795 switch (__lv)
796 {
797 case 0:
798 __v = false;
799 break;
800 case 1:
801 __v = true;
802 break;
803 default:
804 __v = true;
805 __err = ios_base::failbit;
806 break;
807 }
808 return __b;
809 }
810 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__iob.getloc());
811 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__iob.getloc());
812 typedef typename numpunct<_CharT>::string_type string_type;
813 const string_type __names[2] = {__np.truename(), __np.falsename()};
814 const string_type* __i = __scan_keyword(__b, __e, __names, __names+2,
815 __ct, __err);
816 __v = __i == __names;
817 return __b;
818}
819
Marshall Clowfe2a5612013-11-07 01:00:50 +0000820// signed
821
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000822template <class _CharT, class _InputIterator>
Marshall Clowfe2a5612013-11-07 01:00:50 +0000823template <class _Signed>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000824_InputIterator
Marshall Clowfe2a5612013-11-07 01:00:50 +0000825num_get<_CharT, _InputIterator>::__do_get_signed(iter_type __b, iter_type __e,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000826 ios_base& __iob,
827 ios_base::iostate& __err,
Marshall Clowfe2a5612013-11-07 01:00:50 +0000828 _Signed& __v) const
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000829{
830 // Stage 1
831 int __base = this->__get_base(__iob);
832 // Stage 2
833 char_type __atoms[26];
834 char_type __thousands_sep;
835 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
Howard Hinnantae57a1a2013-04-15 20:40:06 +0000836 string __buf;
837 __buf.resize(__buf.capacity());
838 char* __a = &__buf[0];
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000839 char* __a_end = __a;
840 unsigned __g[__num_get_base::__num_get_buf_sz];
841 unsigned* __g_end = __g;
842 unsigned __dc = 0;
843 for (; __b != __e; ++__b)
Howard Hinnantae57a1a2013-04-15 20:40:06 +0000844 {
Joerg Sonnenbergercf7278a2014-02-07 21:14:29 +0000845 if (__a_end == __a + __buf.size())
Howard Hinnantae57a1a2013-04-15 20:40:06 +0000846 {
847 size_t __tmp = __buf.size();
848 __buf.resize(2*__buf.size());
849 __buf.resize(__buf.capacity());
850 __a = &__buf[0];
851 __a_end = __a + __tmp;
852 }
Howard Hinnant324bb032010-08-22 00:02:43 +0000853 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000854 __thousands_sep, __grouping, __g, __g_end,
855 __atoms))
856 break;
Howard Hinnantae57a1a2013-04-15 20:40:06 +0000857 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000858 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
859 *__g_end++ = __dc;
860 // Stage 3
Marshall Clowfe2a5612013-11-07 01:00:50 +0000861 __v = __num_get_signed_integral<_Signed>(__a, __a_end, __err, __base);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000862 // Digit grouping checked
863 __check_grouping(__grouping, __g, __g_end, __err);
864 // EOF checked
865 if (__b == __e)
866 __err |= ios_base::eofbit;
867 return __b;
868}
869
Marshall Clowfe2a5612013-11-07 01:00:50 +0000870// unsigned
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000871
872template <class _CharT, class _InputIterator>
Marshall Clowfe2a5612013-11-07 01:00:50 +0000873template <class _Unsigned>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000874_InputIterator
Marshall Clowfe2a5612013-11-07 01:00:50 +0000875num_get<_CharT, _InputIterator>::__do_get_unsigned(iter_type __b, iter_type __e,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000876 ios_base& __iob,
877 ios_base::iostate& __err,
Marshall Clowfe2a5612013-11-07 01:00:50 +0000878 _Unsigned& __v) const
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000879{
880 // Stage 1
881 int __base = this->__get_base(__iob);
882 // Stage 2
883 char_type __atoms[26];
884 char_type __thousands_sep;
885 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
Howard Hinnantae57a1a2013-04-15 20:40:06 +0000886 string __buf;
887 __buf.resize(__buf.capacity());
888 char* __a = &__buf[0];
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000889 char* __a_end = __a;
890 unsigned __g[__num_get_base::__num_get_buf_sz];
891 unsigned* __g_end = __g;
892 unsigned __dc = 0;
893 for (; __b != __e; ++__b)
Howard Hinnantae57a1a2013-04-15 20:40:06 +0000894 {
Joerg Sonnenbergercf7278a2014-02-07 21:14:29 +0000895 if (__a_end == __a + __buf.size())
Howard Hinnantae57a1a2013-04-15 20:40:06 +0000896 {
897 size_t __tmp = __buf.size();
898 __buf.resize(2*__buf.size());
899 __buf.resize(__buf.capacity());
900 __a = &__buf[0];
901 __a_end = __a + __tmp;
902 }
Howard Hinnant324bb032010-08-22 00:02:43 +0000903 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000904 __thousands_sep, __grouping, __g, __g_end,
905 __atoms))
906 break;
Howard Hinnantae57a1a2013-04-15 20:40:06 +0000907 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000908 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
909 *__g_end++ = __dc;
910 // Stage 3
Marshall Clowfe2a5612013-11-07 01:00:50 +0000911 __v = __num_get_unsigned_integral<_Unsigned>(__a, __a_end, __err, __base);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000912 // Digit grouping checked
913 __check_grouping(__grouping, __g, __g_end, __err);
914 // EOF checked
915 if (__b == __e)
916 __err |= ios_base::eofbit;
917 return __b;
918}
919
Marshall Clow5ffe5912013-11-05 14:28:52 +0000920// floating point
921
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000922template <class _CharT, class _InputIterator>
Marshall Clow5ffe5912013-11-05 14:28:52 +0000923template <class _Fp>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000924_InputIterator
Marshall Clow5ffe5912013-11-05 14:28:52 +0000925num_get<_CharT, _InputIterator>::__do_get_floating_point(iter_type __b, iter_type __e,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000926 ios_base& __iob,
927 ios_base::iostate& __err,
Marshall Clow5ffe5912013-11-05 14:28:52 +0000928 _Fp& __v) const
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000929{
930 // Stage 1, nothing to do
931 // Stage 2
932 char_type __atoms[32];
933 char_type __decimal_point;
934 char_type __thousands_sep;
Howard Hinnant324bb032010-08-22 00:02:43 +0000935 string __grouping = this->__stage2_float_prep(__iob, __atoms,
936 __decimal_point,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000937 __thousands_sep);
Howard Hinnantae57a1a2013-04-15 20:40:06 +0000938 string __buf;
939 __buf.resize(__buf.capacity());
940 char* __a = &__buf[0];
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000941 char* __a_end = __a;
942 unsigned __g[__num_get_base::__num_get_buf_sz];
943 unsigned* __g_end = __g;
944 unsigned __dc = 0;
945 bool __in_units = true;
946 char __exp = 'E';
947 for (; __b != __e; ++__b)
Howard Hinnantae57a1a2013-04-15 20:40:06 +0000948 {
Joerg Sonnenbergercf7278a2014-02-07 21:14:29 +0000949 if (__a_end == __a + __buf.size())
Howard Hinnantae57a1a2013-04-15 20:40:06 +0000950 {
951 size_t __tmp = __buf.size();
952 __buf.resize(2*__buf.size());
953 __buf.resize(__buf.capacity());
954 __a = &__buf[0];
955 __a_end = __a + __tmp;
956 }
Howard Hinnant324bb032010-08-22 00:02:43 +0000957 if (this->__stage2_float_loop(*__b, __in_units, __exp, __a, __a_end,
958 __decimal_point, __thousands_sep,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000959 __grouping, __g, __g_end,
960 __dc, __atoms))
961 break;
Howard Hinnantae57a1a2013-04-15 20:40:06 +0000962 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000963 if (__grouping.size() != 0 && __in_units && __g_end-__g < __num_get_base::__num_get_buf_sz)
964 *__g_end++ = __dc;
965 // Stage 3
Marshall Clow5ffe5912013-11-05 14:28:52 +0000966 __v = __num_get_float<_Fp>(__a, __a_end, __err);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000967 // Digit grouping checked
968 __check_grouping(__grouping, __g, __g_end, __err);
969 // EOF checked
970 if (__b == __e)
971 __err |= ios_base::eofbit;
972 return __b;
973}
974
975template <class _CharT, class _InputIterator>
976_InputIterator
977num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
978 ios_base& __iob,
979 ios_base::iostate& __err,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000980 void*& __v) const
981{
982 // Stage 1
983 int __base = 16;
984 // Stage 2
985 char_type __atoms[26];
Howard Hinnantec3773c2011-12-01 20:21:04 +0000986 char_type __thousands_sep = 0;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000987 string __grouping;
988 use_facet<ctype<_CharT> >(__iob.getloc()).widen(__num_get_base::__src,
989 __num_get_base::__src + 26, __atoms);
Howard Hinnantae57a1a2013-04-15 20:40:06 +0000990 string __buf;
991 __buf.resize(__buf.capacity());
992 char* __a = &__buf[0];
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000993 char* __a_end = __a;
994 unsigned __g[__num_get_base::__num_get_buf_sz];
995 unsigned* __g_end = __g;
996 unsigned __dc = 0;
997 for (; __b != __e; ++__b)
Howard Hinnantae57a1a2013-04-15 20:40:06 +0000998 {
Joerg Sonnenbergercf7278a2014-02-07 21:14:29 +0000999 if (__a_end == __a + __buf.size())
Howard Hinnantae57a1a2013-04-15 20:40:06 +00001000 {
1001 size_t __tmp = __buf.size();
1002 __buf.resize(2*__buf.size());
1003 __buf.resize(__buf.capacity());
1004 __a = &__buf[0];
1005 __a_end = __a + __tmp;
1006 }
Howard Hinnant324bb032010-08-22 00:02:43 +00001007 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
1008 __thousands_sep, __grouping,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001009 __g, __g_end, __atoms))
1010 break;
Howard Hinnantae57a1a2013-04-15 20:40:06 +00001011 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001012 // Stage 3
Marshall Clow117563c2014-05-21 16:02:20 +00001013 __buf.resize(__a_end - __a);
Ben Craigfd556582016-03-09 15:39:39 +00001014 if (__libcpp_sscanf_l(__buf.c_str(), _LIBCPP_GET_C_LOCALE, "%p", &__v) != 1)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001015 __err = ios_base::failbit;
1016 // EOF checked
1017 if (__b == __e)
1018 __err |= ios_base::eofbit;
1019 return __b;
1020}
1021
Howard Hinnant499cea12013-08-23 17:37:05 +00001022_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS num_get<char>)
1023_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS num_get<wchar_t>)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001024
Howard Hinnant0f678bd2013-08-12 18:38:34 +00001025struct _LIBCPP_TYPE_VIS __num_put_base
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001026{
1027protected:
1028 static void __format_int(char* __fmt, const char* __len, bool __signd,
1029 ios_base::fmtflags __flags);
1030 static bool __format_float(char* __fmt, const char* __len,
1031 ios_base::fmtflags __flags);
1032 static char* __identify_padding(char* __nb, char* __ne,
1033 const ios_base& __iob);
1034};
1035
1036template <class _CharT>
1037struct __num_put
1038 : protected __num_put_base
1039{
1040 static void __widen_and_group_int(char* __nb, char* __np, char* __ne,
1041 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1042 const locale& __loc);
1043 static void __widen_and_group_float(char* __nb, char* __np, char* __ne,
1044 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1045 const locale& __loc);
1046};
1047
1048template <class _CharT>
1049void
1050__num_put<_CharT>::__widen_and_group_int(char* __nb, char* __np, char* __ne,
1051 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1052 const locale& __loc)
1053{
1054 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> > (__loc);
1055 const numpunct<_CharT>& __npt = use_facet<numpunct<_CharT> >(__loc);
1056 string __grouping = __npt.grouping();
1057 if (__grouping.empty())
1058 {
1059 __ct.widen(__nb, __ne, __ob);
1060 __oe = __ob + (__ne - __nb);
1061 }
1062 else
1063 {
1064 __oe = __ob;
1065 char* __nf = __nb;
1066 if (*__nf == '-' || *__nf == '+')
1067 *__oe++ = __ct.widen(*__nf++);
1068 if (__ne - __nf >= 2 && __nf[0] == '0' && (__nf[1] == 'x' ||
1069 __nf[1] == 'X'))
1070 {
1071 *__oe++ = __ct.widen(*__nf++);
1072 *__oe++ = __ct.widen(*__nf++);
1073 }
1074 reverse(__nf, __ne);
1075 _CharT __thousands_sep = __npt.thousands_sep();
1076 unsigned __dc = 0;
1077 unsigned __dg = 0;
1078 for (char* __p = __nf; __p < __ne; ++__p)
1079 {
1080 if (static_cast<unsigned>(__grouping[__dg]) > 0 &&
1081 __dc == static_cast<unsigned>(__grouping[__dg]))
1082 {
1083 *__oe++ = __thousands_sep;
1084 __dc = 0;
1085 if (__dg < __grouping.size()-1)
1086 ++__dg;
1087 }
1088 *__oe++ = __ct.widen(*__p);
1089 ++__dc;
1090 }
1091 reverse(__ob + (__nf - __nb), __oe);
1092 }
1093 if (__np == __ne)
1094 __op = __oe;
1095 else
1096 __op = __ob + (__np - __nb);
1097}
1098
1099template <class _CharT>
1100void
1101__num_put<_CharT>::__widen_and_group_float(char* __nb, char* __np, char* __ne,
1102 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1103 const locale& __loc)
1104{
1105 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> > (__loc);
1106 const numpunct<_CharT>& __npt = use_facet<numpunct<_CharT> >(__loc);
1107 string __grouping = __npt.grouping();
1108 __oe = __ob;
1109 char* __nf = __nb;
1110 if (*__nf == '-' || *__nf == '+')
1111 *__oe++ = __ct.widen(*__nf++);
1112 char* __ns;
1113 if (__ne - __nf >= 2 && __nf[0] == '0' && (__nf[1] == 'x' ||
1114 __nf[1] == 'X'))
1115 {
1116 *__oe++ = __ct.widen(*__nf++);
1117 *__oe++ = __ct.widen(*__nf++);
1118 for (__ns = __nf; __ns < __ne; ++__ns)
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001119 if (!isxdigit_l(*__ns, _LIBCPP_GET_C_LOCALE))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001120 break;
1121 }
1122 else
1123 {
1124 for (__ns = __nf; __ns < __ne; ++__ns)
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00001125 if (!isdigit_l(*__ns, _LIBCPP_GET_C_LOCALE))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001126 break;
1127 }
1128 if (__grouping.empty())
1129 {
1130 __ct.widen(__nf, __ns, __oe);
1131 __oe += __ns - __nf;
1132 }
1133 else
1134 {
1135 reverse(__nf, __ns);
1136 _CharT __thousands_sep = __npt.thousands_sep();
1137 unsigned __dc = 0;
1138 unsigned __dg = 0;
1139 for (char* __p = __nf; __p < __ns; ++__p)
1140 {
1141 if (__grouping[__dg] > 0 && __dc == static_cast<unsigned>(__grouping[__dg]))
1142 {
1143 *__oe++ = __thousands_sep;
1144 __dc = 0;
1145 if (__dg < __grouping.size()-1)
1146 ++__dg;
1147 }
1148 *__oe++ = __ct.widen(*__p);
1149 ++__dc;
1150 }
1151 reverse(__ob + (__nf - __nb), __oe);
1152 }
1153 for (__nf = __ns; __nf < __ne; ++__nf)
1154 {
1155 if (*__nf == '.')
1156 {
1157 *__oe++ = __npt.decimal_point();
1158 ++__nf;
1159 break;
1160 }
1161 else
1162 *__oe++ = __ct.widen(*__nf);
1163 }
1164 __ct.widen(__nf, __ne, __oe);
1165 __oe += __ne - __nf;
1166 if (__np == __ne)
1167 __op = __oe;
1168 else
1169 __op = __ob + (__np - __nb);
1170}
1171
Howard Hinnant499cea12013-08-23 17:37:05 +00001172_LIBCPP_EXTERN_TEMPLATE2(struct _LIBCPP_TYPE_VIS __num_put<char>)
1173_LIBCPP_EXTERN_TEMPLATE2(struct _LIBCPP_TYPE_VIS __num_put<wchar_t>)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001174
1175template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant0f678bd2013-08-12 18:38:34 +00001176class _LIBCPP_TYPE_VIS_ONLY num_put
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001177 : public locale::facet,
1178 private __num_put<_CharT>
1179{
1180public:
1181 typedef _CharT char_type;
1182 typedef _OutputIterator iter_type;
1183
1184 _LIBCPP_ALWAYS_INLINE
1185 explicit num_put(size_t __refs = 0)
1186 : locale::facet(__refs) {}
1187
1188 _LIBCPP_ALWAYS_INLINE
1189 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1190 bool __v) const
1191 {
1192 return do_put(__s, __iob, __fl, __v);
1193 }
1194
1195 _LIBCPP_ALWAYS_INLINE
1196 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1197 long __v) const
1198 {
1199 return do_put(__s, __iob, __fl, __v);
1200 }
1201
1202 _LIBCPP_ALWAYS_INLINE
1203 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1204 long long __v) const
1205 {
1206 return do_put(__s, __iob, __fl, __v);
1207 }
1208
1209 _LIBCPP_ALWAYS_INLINE
1210 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1211 unsigned long __v) const
1212 {
1213 return do_put(__s, __iob, __fl, __v);
1214 }
1215
1216 _LIBCPP_ALWAYS_INLINE
1217 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1218 unsigned long long __v) const
1219 {
1220 return do_put(__s, __iob, __fl, __v);
1221 }
1222
1223 _LIBCPP_ALWAYS_INLINE
1224 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1225 double __v) const
1226 {
1227 return do_put(__s, __iob, __fl, __v);
1228 }
1229
1230 _LIBCPP_ALWAYS_INLINE
1231 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1232 long double __v) const
1233 {
1234 return do_put(__s, __iob, __fl, __v);
1235 }
1236
1237 _LIBCPP_ALWAYS_INLINE
1238 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1239 const void* __v) const
1240 {
1241 return do_put(__s, __iob, __fl, __v);
1242 }
1243
1244 static locale::id id;
1245
1246protected:
Howard Hinnant82894812010-09-22 16:48:34 +00001247 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001248 ~num_put() {}
1249
1250 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1251 bool __v) const;
1252 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1253 long __v) const;
1254 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1255 long long __v) const;
1256 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1257 unsigned long) const;
1258 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1259 unsigned long long) const;
1260 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1261 double __v) const;
1262 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1263 long double __v) const;
1264 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1265 const void* __v) const;
1266};
1267
1268template <class _CharT, class _OutputIterator>
1269locale::id
1270num_put<_CharT, _OutputIterator>::id;
1271
1272template <class _CharT, class _OutputIterator>
1273_LIBCPP_HIDDEN
1274_OutputIterator
1275__pad_and_output(_OutputIterator __s,
1276 const _CharT* __ob, const _CharT* __op, const _CharT* __oe,
1277 ios_base& __iob, _CharT __fl)
1278{
1279 streamsize __sz = __oe - __ob;
1280 streamsize __ns = __iob.width();
1281 if (__ns > __sz)
1282 __ns -= __sz;
1283 else
1284 __ns = 0;
1285 for (;__ob < __op; ++__ob, ++__s)
1286 *__s = *__ob;
1287 for (; __ns; --__ns, ++__s)
1288 *__s = __fl;
1289 for (; __ob < __oe; ++__ob, ++__s)
1290 *__s = *__ob;
1291 __iob.width(0);
1292 return __s;
1293}
1294
Howard Hinnant537b2fa2012-11-14 21:17:15 +00001295#if !defined(__APPLE__) || \
1296 (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED > __MAC_10_8) || \
1297 (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED > __IPHONE_6_0)
1298
Howard Hinnanta585de62012-09-19 19:14:15 +00001299template <class _CharT, class _Traits>
1300_LIBCPP_HIDDEN
1301ostreambuf_iterator<_CharT, _Traits>
1302__pad_and_output(ostreambuf_iterator<_CharT, _Traits> __s,
1303 const _CharT* __ob, const _CharT* __op, const _CharT* __oe,
1304 ios_base& __iob, _CharT __fl)
1305{
1306 if (__s.__sbuf_ == nullptr)
1307 return __s;
1308 streamsize __sz = __oe - __ob;
1309 streamsize __ns = __iob.width();
1310 if (__ns > __sz)
1311 __ns -= __sz;
1312 else
1313 __ns = 0;
1314 streamsize __np = __op - __ob;
1315 if (__np > 0)
1316 {
1317 if (__s.__sbuf_->sputn(__ob, __np) != __np)
1318 {
1319 __s.__sbuf_ = nullptr;
1320 return __s;
1321 }
1322 }
1323 if (__ns > 0)
1324 {
1325 basic_string<_CharT, _Traits> __sp(__ns, __fl);
1326 if (__s.__sbuf_->sputn(__sp.data(), __ns) != __ns)
1327 {
1328 __s.__sbuf_ = nullptr;
1329 return __s;
1330 }
1331 }
1332 __np = __oe - __op;
1333 if (__np > 0)
1334 {
1335 if (__s.__sbuf_->sputn(__op, __np) != __np)
1336 {
1337 __s.__sbuf_ = nullptr;
1338 return __s;
1339 }
1340 }
1341 __iob.width(0);
1342 return __s;
1343}
1344
Howard Hinnant537b2fa2012-11-14 21:17:15 +00001345#endif
1346
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001347template <class _CharT, class _OutputIterator>
1348_OutputIterator
1349num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1350 char_type __fl, bool __v) const
1351{
1352 if ((__iob.flags() & ios_base::boolalpha) == 0)
1353 return do_put(__s, __iob, __fl, (unsigned long)__v);
1354 const numpunct<char_type>& __np = use_facet<numpunct<char_type> >(__iob.getloc());
1355 typedef typename numpunct<char_type>::string_type string_type;
Howard Hinnant499cea12013-08-23 17:37:05 +00001356#if _LIBCPP_DEBUG_LEVEL >= 2
1357 string_type __tmp(__v ? __np.truename() : __np.falsename());
1358 string_type __nm = _VSTD::move(__tmp);
1359#else
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001360 string_type __nm = __v ? __np.truename() : __np.falsename();
Howard Hinnant499cea12013-08-23 17:37:05 +00001361#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001362 for (typename string_type::iterator __i = __nm.begin(); __i != __nm.end(); ++__i, ++__s)
1363 *__s = *__i;
1364 return __s;
1365}
1366
1367template <class _CharT, class _OutputIterator>
1368_OutputIterator
1369num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1370 char_type __fl, long __v) const
1371{
1372 // Stage 1 - Get number in narrow char
1373 char __fmt[6] = {'%', 0};
1374 const char* __len = "l";
1375 this->__format_int(__fmt+1, __len, true, __iob.flags());
1376 const unsigned __nbuf = (numeric_limits<long>::digits / 3)
1377 + ((numeric_limits<long>::digits % 3) != 0)
Eric Fiselier59af3f82016-04-29 07:23:20 +00001378 + 2;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001379 char __nar[__nbuf];
Ben Craigfd556582016-03-09 15:39:39 +00001380 int __nc = __libcpp_snprintf_l(__nar, sizeof(__nar), _LIBCPP_GET_C_LOCALE, __fmt, __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001381 char* __ne = __nar + __nc;
1382 char* __np = this->__identify_padding(__nar, __ne, __iob);
1383 // Stage 2 - Widen __nar while adding thousands separators
1384 char_type __o[2*(__nbuf-1) - 1];
1385 char_type* __op; // pad here
1386 char_type* __oe; // end of output
1387 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1388 // [__o, __oe) contains thousands_sep'd wide number
1389 // Stage 3 & 4
1390 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1391}
1392
1393template <class _CharT, class _OutputIterator>
1394_OutputIterator
1395num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1396 char_type __fl, long long __v) const
1397{
1398 // Stage 1 - Get number in narrow char
1399 char __fmt[8] = {'%', 0};
1400 const char* __len = "ll";
1401 this->__format_int(__fmt+1, __len, true, __iob.flags());
1402 const unsigned __nbuf = (numeric_limits<long long>::digits / 3)
1403 + ((numeric_limits<long long>::digits % 3) != 0)
Marshall Clowb9bf4a22015-01-26 17:24:52 +00001404 + 2;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001405 char __nar[__nbuf];
Ben Craigfd556582016-03-09 15:39:39 +00001406 int __nc = __libcpp_snprintf_l(__nar, sizeof(__nar), _LIBCPP_GET_C_LOCALE, __fmt, __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001407 char* __ne = __nar + __nc;
1408 char* __np = this->__identify_padding(__nar, __ne, __iob);
1409 // Stage 2 - Widen __nar while adding thousands separators
1410 char_type __o[2*(__nbuf-1) - 1];
1411 char_type* __op; // pad here
1412 char_type* __oe; // end of output
1413 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1414 // [__o, __oe) contains thousands_sep'd wide number
1415 // Stage 3 & 4
1416 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1417}
1418
1419template <class _CharT, class _OutputIterator>
1420_OutputIterator
1421num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1422 char_type __fl, unsigned long __v) const
1423{
1424 // Stage 1 - Get number in narrow char
1425 char __fmt[6] = {'%', 0};
1426 const char* __len = "l";
1427 this->__format_int(__fmt+1, __len, false, __iob.flags());
1428 const unsigned __nbuf = (numeric_limits<unsigned long>::digits / 3)
1429 + ((numeric_limits<unsigned long>::digits % 3) != 0)
1430 + 1;
1431 char __nar[__nbuf];
Ben Craigfd556582016-03-09 15:39:39 +00001432 int __nc = __libcpp_snprintf_l(__nar, sizeof(__nar), _LIBCPP_GET_C_LOCALE, __fmt, __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001433 char* __ne = __nar + __nc;
1434 char* __np = this->__identify_padding(__nar, __ne, __iob);
1435 // Stage 2 - Widen __nar while adding thousands separators
1436 char_type __o[2*(__nbuf-1) - 1];
1437 char_type* __op; // pad here
1438 char_type* __oe; // end of output
1439 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1440 // [__o, __oe) contains thousands_sep'd wide number
1441 // Stage 3 & 4
1442 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1443}
1444
1445template <class _CharT, class _OutputIterator>
1446_OutputIterator
1447num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1448 char_type __fl, unsigned long long __v) const
1449{
1450 // Stage 1 - Get number in narrow char
1451 char __fmt[8] = {'%', 0};
1452 const char* __len = "ll";
1453 this->__format_int(__fmt+1, __len, false, __iob.flags());
1454 const unsigned __nbuf = (numeric_limits<unsigned long long>::digits / 3)
1455 + ((numeric_limits<unsigned long long>::digits % 3) != 0)
1456 + 1;
1457 char __nar[__nbuf];
Ben Craigfd556582016-03-09 15:39:39 +00001458 int __nc = __libcpp_snprintf_l(__nar, sizeof(__nar), _LIBCPP_GET_C_LOCALE, __fmt, __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001459 char* __ne = __nar + __nc;
1460 char* __np = this->__identify_padding(__nar, __ne, __iob);
1461 // Stage 2 - Widen __nar while adding thousands separators
1462 char_type __o[2*(__nbuf-1) - 1];
1463 char_type* __op; // pad here
1464 char_type* __oe; // end of output
1465 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1466 // [__o, __oe) contains thousands_sep'd wide number
1467 // Stage 3 & 4
1468 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1469}
1470
1471template <class _CharT, class _OutputIterator>
1472_OutputIterator
1473num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1474 char_type __fl, double __v) const
1475{
1476 // Stage 1 - Get number in narrow char
1477 char __fmt[8] = {'%', 0};
1478 const char* __len = "";
1479 bool __specify_precision = this->__format_float(__fmt+1, __len, __iob.flags());
1480 const unsigned __nbuf = 30;
1481 char __nar[__nbuf];
1482 char* __nb = __nar;
1483 int __nc;
1484 if (__specify_precision)
Ben Craigfd556582016-03-09 15:39:39 +00001485 __nc = __libcpp_snprintf_l(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt,
Howard Hinnantadff4892010-05-24 17:49:41 +00001486 (int)__iob.precision(), __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001487 else
Ben Craigfd556582016-03-09 15:39:39 +00001488 __nc = __libcpp_snprintf_l(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001489 unique_ptr<char, void(*)(void*)> __nbh(0, free);
1490 if (__nc > static_cast<int>(__nbuf-1))
1491 {
1492 if (__specify_precision)
Ben Craigfd556582016-03-09 15:39:39 +00001493 __nc = __libcpp_asprintf_l(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, (int)__iob.precision(), __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001494 else
Ben Craigfd556582016-03-09 15:39:39 +00001495 __nc = __libcpp_asprintf_l(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001496 if (__nb == 0)
1497 __throw_bad_alloc();
1498 __nbh.reset(__nb);
1499 }
1500 char* __ne = __nb + __nc;
1501 char* __np = this->__identify_padding(__nb, __ne, __iob);
1502 // Stage 2 - Widen __nar while adding thousands separators
1503 char_type __o[2*(__nbuf-1) - 1];
1504 char_type* __ob = __o;
1505 unique_ptr<char_type, void(*)(void*)> __obh(0, free);
1506 if (__nb != __nar)
1507 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00001508 __ob = (char_type*)malloc(2*static_cast<size_t>(__nc)*sizeof(char_type));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001509 if (__ob == 0)
1510 __throw_bad_alloc();
1511 __obh.reset(__ob);
1512 }
1513 char_type* __op; // pad here
1514 char_type* __oe; // end of output
1515 this->__widen_and_group_float(__nb, __np, __ne, __ob, __op, __oe, __iob.getloc());
1516 // [__o, __oe) contains thousands_sep'd wide number
1517 // Stage 3 & 4
1518 __s = __pad_and_output(__s, __ob, __op, __oe, __iob, __fl);
1519 return __s;
1520}
1521
1522template <class _CharT, class _OutputIterator>
1523_OutputIterator
1524num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1525 char_type __fl, long double __v) const
1526{
1527 // Stage 1 - Get number in narrow char
1528 char __fmt[8] = {'%', 0};
1529 const char* __len = "L";
1530 bool __specify_precision = this->__format_float(__fmt+1, __len, __iob.flags());
1531 const unsigned __nbuf = 30;
1532 char __nar[__nbuf];
1533 char* __nb = __nar;
1534 int __nc;
1535 if (__specify_precision)
Ben Craigfd556582016-03-09 15:39:39 +00001536 __nc = __libcpp_snprintf_l(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt,
Howard Hinnantadff4892010-05-24 17:49:41 +00001537 (int)__iob.precision(), __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001538 else
Ben Craigfd556582016-03-09 15:39:39 +00001539 __nc = __libcpp_snprintf_l(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001540 unique_ptr<char, void(*)(void*)> __nbh(0, free);
1541 if (__nc > static_cast<int>(__nbuf-1))
1542 {
1543 if (__specify_precision)
Ben Craigfd556582016-03-09 15:39:39 +00001544 __nc = __libcpp_asprintf_l(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, (int)__iob.precision(), __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001545 else
Ben Craigfd556582016-03-09 15:39:39 +00001546 __nc = __libcpp_asprintf_l(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001547 if (__nb == 0)
1548 __throw_bad_alloc();
1549 __nbh.reset(__nb);
1550 }
1551 char* __ne = __nb + __nc;
1552 char* __np = this->__identify_padding(__nb, __ne, __iob);
1553 // Stage 2 - Widen __nar while adding thousands separators
1554 char_type __o[2*(__nbuf-1) - 1];
1555 char_type* __ob = __o;
1556 unique_ptr<char_type, void(*)(void*)> __obh(0, free);
1557 if (__nb != __nar)
1558 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00001559 __ob = (char_type*)malloc(2*static_cast<size_t>(__nc)*sizeof(char_type));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001560 if (__ob == 0)
1561 __throw_bad_alloc();
1562 __obh.reset(__ob);
1563 }
1564 char_type* __op; // pad here
1565 char_type* __oe; // end of output
1566 this->__widen_and_group_float(__nb, __np, __ne, __ob, __op, __oe, __iob.getloc());
1567 // [__o, __oe) contains thousands_sep'd wide number
1568 // Stage 3 & 4
1569 __s = __pad_and_output(__s, __ob, __op, __oe, __iob, __fl);
1570 return __s;
1571}
1572
1573template <class _CharT, class _OutputIterator>
1574_OutputIterator
1575num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1576 char_type __fl, const void* __v) const
1577{
1578 // Stage 1 - Get pointer in narrow char
1579 char __fmt[6] = "%p";
1580 const unsigned __nbuf = 20;
1581 char __nar[__nbuf];
Ben Craigfd556582016-03-09 15:39:39 +00001582 int __nc = __libcpp_snprintf_l(__nar, sizeof(__nar), _LIBCPP_GET_C_LOCALE, __fmt, __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001583 char* __ne = __nar + __nc;
1584 char* __np = this->__identify_padding(__nar, __ne, __iob);
1585 // Stage 2 - Widen __nar
1586 char_type __o[2*(__nbuf-1) - 1];
1587 char_type* __op; // pad here
1588 char_type* __oe; // end of output
1589 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
1590 __ct.widen(__nar, __ne, __o);
1591 __oe = __o + (__ne - __nar);
1592 if (__np == __ne)
1593 __op = __oe;
1594 else
1595 __op = __o + (__np - __nar);
1596 // [__o, __oe) contains wide number
1597 // Stage 3 & 4
1598 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1599}
1600
Howard Hinnant499cea12013-08-23 17:37:05 +00001601_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS num_put<char>)
1602_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS num_put<wchar_t>)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001603
1604template <class _CharT, class _InputIterator>
1605_LIBCPP_HIDDEN
1606int
1607__get_up_to_n_digits(_InputIterator& __b, _InputIterator __e,
1608 ios_base::iostate& __err, const ctype<_CharT>& __ct, int __n)
1609{
1610 // Precondition: __n >= 1
1611 if (__b == __e)
1612 {
1613 __err |= ios_base::eofbit | ios_base::failbit;
1614 return 0;
1615 }
1616 // get first digit
1617 _CharT __c = *__b;
1618 if (!__ct.is(ctype_base::digit, __c))
1619 {
1620 __err |= ios_base::failbit;
1621 return 0;
1622 }
1623 int __r = __ct.narrow(__c, 0) - '0';
Eric Fiselierb9919752014-10-27 19:28:20 +00001624 for (++__b, (void) --__n; __b != __e && __n > 0; ++__b, (void) --__n)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001625 {
1626 // get next digit
1627 __c = *__b;
1628 if (!__ct.is(ctype_base::digit, __c))
1629 return __r;
1630 __r = __r * 10 + __ct.narrow(__c, 0) - '0';
1631 }
1632 if (__b == __e)
1633 __err |= ios_base::eofbit;
1634 return __r;
1635}
1636
Howard Hinnant83eade62013-03-06 23:30:19 +00001637class _LIBCPP_TYPE_VIS time_base
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001638{
1639public:
1640 enum dateorder {no_order, dmy, mdy, ymd, ydm};
1641};
1642
1643template <class _CharT>
Saleem Abdulrasool7ef03b72014-07-16 01:00:26 +00001644class _LIBCPP_TYPE_VIS_ONLY __time_get_c_storage
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001645{
1646protected:
1647 typedef basic_string<_CharT> string_type;
1648
1649 virtual const string_type* __weeks() const;
1650 virtual const string_type* __months() const;
1651 virtual const string_type* __am_pm() const;
1652 virtual const string_type& __c() const;
1653 virtual const string_type& __r() const;
1654 virtual const string_type& __x() const;
1655 virtual const string_type& __X() const;
Eric Fiselier85d45f62015-08-18 19:39:35 +00001656
1657 _LIBCPP_ALWAYS_INLINE
1658 ~__time_get_c_storage() {}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001659};
1660
1661template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnant0f678bd2013-08-12 18:38:34 +00001662class _LIBCPP_TYPE_VIS_ONLY time_get
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001663 : public locale::facet,
1664 public time_base,
1665 private __time_get_c_storage<_CharT>
1666{
1667public:
1668 typedef _CharT char_type;
1669 typedef _InputIterator iter_type;
1670 typedef time_base::dateorder dateorder;
1671 typedef basic_string<char_type> string_type;
1672
1673 _LIBCPP_ALWAYS_INLINE
1674 explicit time_get(size_t __refs = 0)
1675 : locale::facet(__refs) {}
1676
1677 _LIBCPP_ALWAYS_INLINE
1678 dateorder date_order() const
1679 {
1680 return this->do_date_order();
1681 }
1682
1683 _LIBCPP_ALWAYS_INLINE
1684 iter_type get_time(iter_type __b, iter_type __e, ios_base& __iob,
1685 ios_base::iostate& __err, tm* __tm) const
1686 {
1687 return do_get_time(__b, __e, __iob, __err, __tm);
1688 }
1689
1690 _LIBCPP_ALWAYS_INLINE
1691 iter_type get_date(iter_type __b, iter_type __e, ios_base& __iob,
1692 ios_base::iostate& __err, tm* __tm) const
1693 {
1694 return do_get_date(__b, __e, __iob, __err, __tm);
1695 }
1696
1697 _LIBCPP_ALWAYS_INLINE
1698 iter_type get_weekday(iter_type __b, iter_type __e, ios_base& __iob,
1699 ios_base::iostate& __err, tm* __tm) const
1700 {
1701 return do_get_weekday(__b, __e, __iob, __err, __tm);
1702 }
1703
1704 _LIBCPP_ALWAYS_INLINE
1705 iter_type get_monthname(iter_type __b, iter_type __e, ios_base& __iob,
1706 ios_base::iostate& __err, tm* __tm) const
1707 {
1708 return do_get_monthname(__b, __e, __iob, __err, __tm);
1709 }
1710
1711 _LIBCPP_ALWAYS_INLINE
1712 iter_type get_year(iter_type __b, iter_type __e, ios_base& __iob,
1713 ios_base::iostate& __err, tm* __tm) const
1714 {
1715 return do_get_year(__b, __e, __iob, __err, __tm);
1716 }
1717
1718 _LIBCPP_ALWAYS_INLINE
1719 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
1720 ios_base::iostate& __err, tm *__tm,
1721 char __fmt, char __mod = 0) const
1722 {
1723 return do_get(__b, __e, __iob, __err, __tm, __fmt, __mod);
1724 }
1725
1726 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
1727 ios_base::iostate& __err, tm* __tm,
1728 const char_type* __fmtb, const char_type* __fmte) const;
1729
1730 static locale::id id;
1731
1732protected:
Howard Hinnant82894812010-09-22 16:48:34 +00001733 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001734 ~time_get() {}
1735
1736 virtual dateorder do_date_order() const;
1737 virtual iter_type do_get_time(iter_type __b, iter_type __e, ios_base& __iob,
1738 ios_base::iostate& __err, tm* __tm) const;
1739 virtual iter_type do_get_date(iter_type __b, iter_type __e, ios_base& __iob,
1740 ios_base::iostate& __err, tm* __tm) const;
1741 virtual iter_type do_get_weekday(iter_type __b, iter_type __e, ios_base& __iob,
1742 ios_base::iostate& __err, tm* __tm) const;
1743 virtual iter_type do_get_monthname(iter_type __b, iter_type __e, ios_base& __iob,
1744 ios_base::iostate& __err, tm* __tm) const;
1745 virtual iter_type do_get_year(iter_type __b, iter_type __e, ios_base& __iob,
1746 ios_base::iostate& __err, tm* __tm) const;
1747 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
1748 ios_base::iostate& __err, tm* __tm,
1749 char __fmt, char __mod) const;
1750private:
1751 void __get_white_space(iter_type& __b, iter_type __e,
1752 ios_base::iostate& __err, const ctype<char_type>& __ct) const;
1753 void __get_percent(iter_type& __b, iter_type __e, ios_base::iostate& __err,
1754 const ctype<char_type>& __ct) const;
1755
1756 void __get_weekdayname(int& __m,
1757 iter_type& __b, iter_type __e,
1758 ios_base::iostate& __err,
1759 const ctype<char_type>& __ct) const;
1760 void __get_monthname(int& __m,
1761 iter_type& __b, iter_type __e,
1762 ios_base::iostate& __err,
1763 const ctype<char_type>& __ct) const;
1764 void __get_day(int& __d,
1765 iter_type& __b, iter_type __e,
1766 ios_base::iostate& __err,
1767 const ctype<char_type>& __ct) const;
1768 void __get_month(int& __m,
1769 iter_type& __b, iter_type __e,
1770 ios_base::iostate& __err,
1771 const ctype<char_type>& __ct) const;
1772 void __get_year(int& __y,
1773 iter_type& __b, iter_type __e,
1774 ios_base::iostate& __err,
1775 const ctype<char_type>& __ct) const;
1776 void __get_year4(int& __y,
1777 iter_type& __b, iter_type __e,
1778 ios_base::iostate& __err,
1779 const ctype<char_type>& __ct) const;
1780 void __get_hour(int& __d,
1781 iter_type& __b, iter_type __e,
1782 ios_base::iostate& __err,
1783 const ctype<char_type>& __ct) const;
1784 void __get_12_hour(int& __h,
1785 iter_type& __b, iter_type __e,
1786 ios_base::iostate& __err,
1787 const ctype<char_type>& __ct) const;
1788 void __get_am_pm(int& __h,
1789 iter_type& __b, iter_type __e,
1790 ios_base::iostate& __err,
1791 const ctype<char_type>& __ct) const;
1792 void __get_minute(int& __m,
1793 iter_type& __b, iter_type __e,
1794 ios_base::iostate& __err,
1795 const ctype<char_type>& __ct) const;
1796 void __get_second(int& __s,
1797 iter_type& __b, iter_type __e,
1798 ios_base::iostate& __err,
1799 const ctype<char_type>& __ct) const;
1800 void __get_weekday(int& __w,
1801 iter_type& __b, iter_type __e,
1802 ios_base::iostate& __err,
1803 const ctype<char_type>& __ct) const;
1804 void __get_day_year_num(int& __w,
1805 iter_type& __b, iter_type __e,
1806 ios_base::iostate& __err,
1807 const ctype<char_type>& __ct) const;
1808};
1809
1810template <class _CharT, class _InputIterator>
1811locale::id
1812time_get<_CharT, _InputIterator>::id;
1813
Alp Tokerec34c482014-05-15 11:27:39 +00001814// time_get primitives
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001815
1816template <class _CharT, class _InputIterator>
1817void
1818time_get<_CharT, _InputIterator>::__get_weekdayname(int& __w,
1819 iter_type& __b, iter_type __e,
1820 ios_base::iostate& __err,
1821 const ctype<char_type>& __ct) const
1822{
1823 // Note: ignoring case comes from the POSIX strptime spec
1824 const string_type* __wk = this->__weeks();
Howard Hinnantec3773c2011-12-01 20:21:04 +00001825 ptrdiff_t __i = __scan_keyword(__b, __e, __wk, __wk+14, __ct, __err, false) - __wk;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001826 if (__i < 14)
1827 __w = __i % 7;
1828}
1829
1830template <class _CharT, class _InputIterator>
1831void
1832time_get<_CharT, _InputIterator>::__get_monthname(int& __m,
1833 iter_type& __b, iter_type __e,
1834 ios_base::iostate& __err,
1835 const ctype<char_type>& __ct) const
1836{
1837 // Note: ignoring case comes from the POSIX strptime spec
1838 const string_type* __month = this->__months();
Howard Hinnantec3773c2011-12-01 20:21:04 +00001839 ptrdiff_t __i = __scan_keyword(__b, __e, __month, __month+24, __ct, __err, false) - __month;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001840 if (__i < 24)
1841 __m = __i % 12;
1842}
1843
1844template <class _CharT, class _InputIterator>
1845void
1846time_get<_CharT, _InputIterator>::__get_day(int& __d,
1847 iter_type& __b, iter_type __e,
1848 ios_base::iostate& __err,
1849 const ctype<char_type>& __ct) const
1850{
1851 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
1852 if (!(__err & ios_base::failbit) && 1 <= __t && __t <= 31)
1853 __d = __t;
1854 else
1855 __err |= ios_base::failbit;
1856}
1857
1858template <class _CharT, class _InputIterator>
1859void
1860time_get<_CharT, _InputIterator>::__get_month(int& __m,
1861 iter_type& __b, iter_type __e,
1862 ios_base::iostate& __err,
1863 const ctype<char_type>& __ct) const
1864{
1865 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2) - 1;
1866 if (!(__err & ios_base::failbit) && __t <= 11)
1867 __m = __t;
1868 else
1869 __err |= ios_base::failbit;
1870}
1871
1872template <class _CharT, class _InputIterator>
1873void
1874time_get<_CharT, _InputIterator>::__get_year(int& __y,
1875 iter_type& __b, iter_type __e,
1876 ios_base::iostate& __err,
1877 const ctype<char_type>& __ct) const
1878{
1879 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 4);
1880 if (!(__err & ios_base::failbit))
1881 {
1882 if (__t < 69)
1883 __t += 2000;
1884 else if (69 <= __t && __t <= 99)
1885 __t += 1900;
1886 __y = __t - 1900;
1887 }
1888}
1889
1890template <class _CharT, class _InputIterator>
1891void
1892time_get<_CharT, _InputIterator>::__get_year4(int& __y,
1893 iter_type& __b, iter_type __e,
1894 ios_base::iostate& __err,
1895 const ctype<char_type>& __ct) const
1896{
1897 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 4);
1898 if (!(__err & ios_base::failbit))
1899 __y = __t - 1900;
1900}
1901
1902template <class _CharT, class _InputIterator>
1903void
1904time_get<_CharT, _InputIterator>::__get_hour(int& __h,
1905 iter_type& __b, iter_type __e,
1906 ios_base::iostate& __err,
1907 const ctype<char_type>& __ct) const
1908{
1909 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
1910 if (!(__err & ios_base::failbit) && __t <= 23)
1911 __h = __t;
1912 else
1913 __err |= ios_base::failbit;
1914}
1915
1916template <class _CharT, class _InputIterator>
1917void
1918time_get<_CharT, _InputIterator>::__get_12_hour(int& __h,
1919 iter_type& __b, iter_type __e,
1920 ios_base::iostate& __err,
1921 const ctype<char_type>& __ct) const
1922{
1923 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
1924 if (!(__err & ios_base::failbit) && 1 <= __t && __t <= 12)
1925 __h = __t;
1926 else
1927 __err |= ios_base::failbit;
1928}
1929
1930template <class _CharT, class _InputIterator>
1931void
1932time_get<_CharT, _InputIterator>::__get_minute(int& __m,
1933 iter_type& __b, iter_type __e,
1934 ios_base::iostate& __err,
1935 const ctype<char_type>& __ct) const
1936{
1937 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
1938 if (!(__err & ios_base::failbit) && __t <= 59)
1939 __m = __t;
1940 else
1941 __err |= ios_base::failbit;
1942}
1943
1944template <class _CharT, class _InputIterator>
1945void
1946time_get<_CharT, _InputIterator>::__get_second(int& __s,
1947 iter_type& __b, iter_type __e,
1948 ios_base::iostate& __err,
1949 const ctype<char_type>& __ct) const
1950{
1951 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
1952 if (!(__err & ios_base::failbit) && __t <= 60)
1953 __s = __t;
1954 else
1955 __err |= ios_base::failbit;
1956}
1957
1958template <class _CharT, class _InputIterator>
1959void
1960time_get<_CharT, _InputIterator>::__get_weekday(int& __w,
1961 iter_type& __b, iter_type __e,
1962 ios_base::iostate& __err,
1963 const ctype<char_type>& __ct) const
1964{
1965 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 1);
1966 if (!(__err & ios_base::failbit) && __t <= 6)
1967 __w = __t;
1968 else
1969 __err |= ios_base::failbit;
1970}
1971
1972template <class _CharT, class _InputIterator>
1973void
1974time_get<_CharT, _InputIterator>::__get_day_year_num(int& __d,
1975 iter_type& __b, iter_type __e,
1976 ios_base::iostate& __err,
1977 const ctype<char_type>& __ct) const
1978{
1979 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 3);
1980 if (!(__err & ios_base::failbit) && __t <= 365)
1981 __d = __t;
1982 else
1983 __err |= ios_base::failbit;
1984}
1985
1986template <class _CharT, class _InputIterator>
1987void
1988time_get<_CharT, _InputIterator>::__get_white_space(iter_type& __b, iter_type __e,
1989 ios_base::iostate& __err,
1990 const ctype<char_type>& __ct) const
1991{
1992 for (; __b != __e && __ct.is(ctype_base::space, *__b); ++__b)
1993 ;
1994 if (__b == __e)
1995 __err |= ios_base::eofbit;
1996}
1997
1998template <class _CharT, class _InputIterator>
1999void
2000time_get<_CharT, _InputIterator>::__get_am_pm(int& __h,
2001 iter_type& __b, iter_type __e,
2002 ios_base::iostate& __err,
2003 const ctype<char_type>& __ct) const
2004{
2005 const string_type* __ap = this->__am_pm();
2006 if (__ap[0].size() + __ap[1].size() == 0)
2007 {
2008 __err |= ios_base::failbit;
2009 return;
2010 }
Howard Hinnantec3773c2011-12-01 20:21:04 +00002011 ptrdiff_t __i = __scan_keyword(__b, __e, __ap, __ap+2, __ct, __err, false) - __ap;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002012 if (__i == 0 && __h == 12)
2013 __h = 0;
2014 else if (__i == 1 && __h < 12)
2015 __h += 12;
2016}
2017
2018template <class _CharT, class _InputIterator>
2019void
2020time_get<_CharT, _InputIterator>::__get_percent(iter_type& __b, iter_type __e,
2021 ios_base::iostate& __err,
2022 const ctype<char_type>& __ct) const
2023{
2024 if (__b == __e)
2025 {
2026 __err |= ios_base::eofbit | ios_base::failbit;
2027 return;
2028 }
2029 if (__ct.narrow(*__b, 0) != '%')
2030 __err |= ios_base::failbit;
2031 else if(++__b == __e)
2032 __err |= ios_base::eofbit;
2033}
2034
Alp Tokerec34c482014-05-15 11:27:39 +00002035// time_get end primitives
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002036
2037template <class _CharT, class _InputIterator>
2038_InputIterator
2039time_get<_CharT, _InputIterator>::get(iter_type __b, iter_type __e,
2040 ios_base& __iob,
2041 ios_base::iostate& __err, tm* __tm,
2042 const char_type* __fmtb, const char_type* __fmte) const
2043{
2044 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2045 __err = ios_base::goodbit;
2046 while (__fmtb != __fmte && __err == ios_base::goodbit)
2047 {
2048 if (__b == __e)
2049 {
2050 __err = ios_base::failbit;
2051 break;
2052 }
2053 if (__ct.narrow(*__fmtb, 0) == '%')
2054 {
2055 if (++__fmtb == __fmte)
2056 {
2057 __err = ios_base::failbit;
2058 break;
2059 }
2060 char __cmd = __ct.narrow(*__fmtb, 0);
2061 char __opt = '\0';
2062 if (__cmd == 'E' || __cmd == '0')
2063 {
2064 if (++__fmtb == __fmte)
2065 {
2066 __err = ios_base::failbit;
2067 break;
2068 }
2069 __opt = __cmd;
2070 __cmd = __ct.narrow(*__fmtb, 0);
2071 }
2072 __b = do_get(__b, __e, __iob, __err, __tm, __cmd, __opt);
2073 ++__fmtb;
2074 }
2075 else if (__ct.is(ctype_base::space, *__fmtb))
2076 {
2077 for (++__fmtb; __fmtb != __fmte && __ct.is(ctype_base::space, *__fmtb); ++__fmtb)
2078 ;
2079 for ( ; __b != __e && __ct.is(ctype_base::space, *__b); ++__b)
2080 ;
2081 }
2082 else if (__ct.toupper(*__b) == __ct.toupper(*__fmtb))
2083 {
2084 ++__b;
2085 ++__fmtb;
2086 }
2087 else
2088 __err = ios_base::failbit;
2089 }
2090 if (__b == __e)
2091 __err |= ios_base::eofbit;
2092 return __b;
2093}
2094
2095template <class _CharT, class _InputIterator>
2096typename time_get<_CharT, _InputIterator>::dateorder
2097time_get<_CharT, _InputIterator>::do_date_order() const
2098{
2099 return mdy;
2100}
2101
2102template <class _CharT, class _InputIterator>
2103_InputIterator
2104time_get<_CharT, _InputIterator>::do_get_time(iter_type __b, iter_type __e,
2105 ios_base& __iob,
2106 ios_base::iostate& __err,
2107 tm* __tm) const
2108{
2109 const char_type __fmt[] = {'%', 'H', ':', '%', 'M', ':', '%', 'S'};
2110 return get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2111}
2112
2113template <class _CharT, class _InputIterator>
2114_InputIterator
2115time_get<_CharT, _InputIterator>::do_get_date(iter_type __b, iter_type __e,
2116 ios_base& __iob,
2117 ios_base::iostate& __err,
2118 tm* __tm) const
2119{
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002120 const string_type& __fmt = this->__x();
2121 return get(__b, __e, __iob, __err, __tm, __fmt.data(), __fmt.data() + __fmt.size());
2122}
2123
2124template <class _CharT, class _InputIterator>
2125_InputIterator
2126time_get<_CharT, _InputIterator>::do_get_weekday(iter_type __b, iter_type __e,
2127 ios_base& __iob,
2128 ios_base::iostate& __err,
2129 tm* __tm) const
2130{
2131 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2132 __get_weekdayname(__tm->tm_wday, __b, __e, __err, __ct);
2133 return __b;
2134}
2135
2136template <class _CharT, class _InputIterator>
2137_InputIterator
2138time_get<_CharT, _InputIterator>::do_get_monthname(iter_type __b, iter_type __e,
2139 ios_base& __iob,
2140 ios_base::iostate& __err,
2141 tm* __tm) const
2142{
2143 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2144 __get_monthname(__tm->tm_mon, __b, __e, __err, __ct);
2145 return __b;
2146}
2147
2148template <class _CharT, class _InputIterator>
2149_InputIterator
2150time_get<_CharT, _InputIterator>::do_get_year(iter_type __b, iter_type __e,
2151 ios_base& __iob,
2152 ios_base::iostate& __err,
2153 tm* __tm) const
2154{
2155 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2156 __get_year(__tm->tm_year, __b, __e, __err, __ct);
2157 return __b;
2158}
2159
2160template <class _CharT, class _InputIterator>
2161_InputIterator
2162time_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
2163 ios_base& __iob,
2164 ios_base::iostate& __err, tm* __tm,
2165 char __fmt, char) const
2166{
2167 __err = ios_base::goodbit;
2168 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2169 switch (__fmt)
2170 {
2171 case 'a':
2172 case 'A':
2173 __get_weekdayname(__tm->tm_wday, __b, __e, __err, __ct);
2174 break;
2175 case 'b':
2176 case 'B':
2177 case 'h':
2178 __get_monthname(__tm->tm_mon, __b, __e, __err, __ct);
2179 break;
2180 case 'c':
2181 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002182 const string_type& __fm = this->__c();
2183 __b = get(__b, __e, __iob, __err, __tm, __fm.data(), __fm.data() + __fm.size());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002184 }
2185 break;
2186 case 'd':
2187 case 'e':
2188 __get_day(__tm->tm_mday, __b, __e, __err, __ct);
2189 break;
2190 case 'D':
2191 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002192 const char_type __fm[] = {'%', 'm', '/', '%', 'd', '/', '%', 'y'};
2193 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm)/sizeof(__fm[0]));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002194 }
2195 break;
Howard Hinnant506b3642011-04-10 17:54:14 +00002196 case 'F':
2197 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002198 const char_type __fm[] = {'%', 'Y', '-', '%', 'm', '-', '%', 'd'};
2199 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm)/sizeof(__fm[0]));
Howard Hinnant506b3642011-04-10 17:54:14 +00002200 }
2201 break;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002202 case 'H':
2203 __get_hour(__tm->tm_hour, __b, __e, __err, __ct);
2204 break;
2205 case 'I':
2206 __get_12_hour(__tm->tm_hour, __b, __e, __err, __ct);
2207 break;
2208 case 'j':
2209 __get_day_year_num(__tm->tm_yday, __b, __e, __err, __ct);
2210 break;
2211 case 'm':
2212 __get_month(__tm->tm_mon, __b, __e, __err, __ct);
2213 break;
2214 case 'M':
2215 __get_minute(__tm->tm_min, __b, __e, __err, __ct);
2216 break;
2217 case 'n':
2218 case 't':
2219 __get_white_space(__b, __e, __err, __ct);
2220 break;
2221 case 'p':
2222 __get_am_pm(__tm->tm_hour, __b, __e, __err, __ct);
2223 break;
2224 case 'r':
2225 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002226 const char_type __fm[] = {'%', 'I', ':', '%', 'M', ':', '%', 'S', ' ', '%', 'p'};
2227 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm)/sizeof(__fm[0]));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002228 }
2229 break;
2230 case 'R':
2231 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002232 const char_type __fm[] = {'%', 'H', ':', '%', 'M'};
2233 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm)/sizeof(__fm[0]));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002234 }
2235 break;
2236 case 'S':
2237 __get_second(__tm->tm_sec, __b, __e, __err, __ct);
2238 break;
2239 case 'T':
2240 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002241 const char_type __fm[] = {'%', 'H', ':', '%', 'M', ':', '%', 'S'};
2242 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm)/sizeof(__fm[0]));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002243 }
2244 break;
2245 case 'w':
2246 __get_weekday(__tm->tm_wday, __b, __e, __err, __ct);
2247 break;
2248 case 'x':
2249 return do_get_date(__b, __e, __iob, __err, __tm);
2250 case 'X':
2251 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002252 const string_type& __fm = this->__X();
2253 __b = get(__b, __e, __iob, __err, __tm, __fm.data(), __fm.data() + __fm.size());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002254 }
2255 break;
2256 case 'y':
2257 __get_year(__tm->tm_year, __b, __e, __err, __ct);
2258 break;
2259 case 'Y':
2260 __get_year4(__tm->tm_year, __b, __e, __err, __ct);
2261 break;
2262 case '%':
2263 __get_percent(__b, __e, __err, __ct);
2264 break;
2265 default:
2266 __err |= ios_base::failbit;
2267 }
2268 return __b;
2269}
2270
Howard Hinnant499cea12013-08-23 17:37:05 +00002271_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS time_get<char>)
2272_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS time_get<wchar_t>)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002273
Howard Hinnant0f678bd2013-08-12 18:38:34 +00002274class _LIBCPP_TYPE_VIS __time_get
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002275{
2276protected:
2277 locale_t __loc_;
2278
2279 __time_get(const char* __nm);
2280 __time_get(const string& __nm);
2281 ~__time_get();
2282};
2283
2284template <class _CharT>
Saleem Abdulrasool7ef03b72014-07-16 01:00:26 +00002285class _LIBCPP_TYPE_VIS_ONLY __time_get_storage
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002286 : public __time_get
2287{
2288protected:
2289 typedef basic_string<_CharT> string_type;
2290
2291 string_type __weeks_[14];
2292 string_type __months_[24];
2293 string_type __am_pm_[2];
2294 string_type __c_;
2295 string_type __r_;
2296 string_type __x_;
2297 string_type __X_;
2298
2299 explicit __time_get_storage(const char* __nm);
2300 explicit __time_get_storage(const string& __nm);
2301
2302 _LIBCPP_ALWAYS_INLINE ~__time_get_storage() {}
2303
2304 time_base::dateorder __do_date_order() const;
2305
2306private:
2307 void init(const ctype<_CharT>&);
2308 string_type __analyze(char __fmt, const ctype<_CharT>&);
2309};
2310
2311template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnant0f678bd2013-08-12 18:38:34 +00002312class _LIBCPP_TYPE_VIS_ONLY time_get_byname
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002313 : public time_get<_CharT, _InputIterator>,
2314 private __time_get_storage<_CharT>
2315{
2316public:
2317 typedef time_base::dateorder dateorder;
2318 typedef _InputIterator iter_type;
2319 typedef _CharT char_type;
2320 typedef basic_string<char_type> string_type;
2321
Howard Hinnant82894812010-09-22 16:48:34 +00002322 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002323 explicit time_get_byname(const char* __nm, size_t __refs = 0)
2324 : time_get<_CharT, _InputIterator>(__refs),
2325 __time_get_storage<_CharT>(__nm) {}
Howard Hinnant82894812010-09-22 16:48:34 +00002326 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002327 explicit time_get_byname(const string& __nm, size_t __refs = 0)
2328 : time_get<_CharT, _InputIterator>(__refs),
2329 __time_get_storage<_CharT>(__nm) {}
2330
2331protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002332 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002333 ~time_get_byname() {}
2334
Howard Hinnant82894812010-09-22 16:48:34 +00002335 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002336 virtual dateorder do_date_order() const {return this->__do_date_order();}
2337private:
Howard Hinnant82894812010-09-22 16:48:34 +00002338 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002339 virtual const string_type* __weeks() const {return this->__weeks_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002340 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002341 virtual const string_type* __months() const {return this->__months_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002342 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002343 virtual const string_type* __am_pm() const {return this->__am_pm_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002344 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002345 virtual const string_type& __c() const {return this->__c_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002346 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002347 virtual const string_type& __r() const {return this->__r_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002348 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002349 virtual const string_type& __x() const {return this->__x_;}
Howard Hinnant82894812010-09-22 16:48:34 +00002350 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002351 virtual const string_type& __X() const {return this->__X_;}
2352};
2353
Howard Hinnant499cea12013-08-23 17:37:05 +00002354_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS time_get_byname<char>)
2355_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS time_get_byname<wchar_t>)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002356
Howard Hinnant0f678bd2013-08-12 18:38:34 +00002357class _LIBCPP_TYPE_VIS __time_put
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002358{
2359 locale_t __loc_;
2360protected:
Howard Hinnant2ea1ca92011-09-28 21:05:01 +00002361 _LIBCPP_ALWAYS_INLINE __time_put() : __loc_(_LIBCPP_GET_C_LOCALE) {}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002362 __time_put(const char* __nm);
2363 __time_put(const string& __nm);
2364 ~__time_put();
2365 void __do_put(char* __nb, char*& __ne, const tm* __tm,
2366 char __fmt, char __mod) const;
2367 void __do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
2368 char __fmt, char __mod) const;
2369};
2370
2371template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant0f678bd2013-08-12 18:38:34 +00002372class _LIBCPP_TYPE_VIS_ONLY time_put
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002373 : public locale::facet,
2374 private __time_put
2375{
2376public:
2377 typedef _CharT char_type;
2378 typedef _OutputIterator iter_type;
2379
2380 _LIBCPP_ALWAYS_INLINE
2381 explicit time_put(size_t __refs = 0)
2382 : locale::facet(__refs) {}
2383
2384 iter_type put(iter_type __s, ios_base& __iob, char_type __fl, const tm* __tm,
2385 const char_type* __pb, const char_type* __pe) const;
2386
2387 _LIBCPP_ALWAYS_INLINE
2388 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
2389 const tm* __tm, char __fmt, char __mod = 0) const
2390 {
2391 return do_put(__s, __iob, __fl, __tm, __fmt, __mod);
2392 }
2393
2394 static locale::id id;
2395
2396protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002397 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002398 ~time_put() {}
2399 virtual iter_type do_put(iter_type __s, ios_base&, char_type, const tm* __tm,
2400 char __fmt, char __mod) const;
2401
Howard Hinnant82894812010-09-22 16:48:34 +00002402 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002403 explicit time_put(const char* __nm, size_t __refs)
2404 : locale::facet(__refs),
2405 __time_put(__nm) {}
Howard Hinnant82894812010-09-22 16:48:34 +00002406 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002407 explicit time_put(const string& __nm, size_t __refs)
2408 : locale::facet(__refs),
2409 __time_put(__nm) {}
2410};
2411
2412template <class _CharT, class _OutputIterator>
2413locale::id
2414time_put<_CharT, _OutputIterator>::id;
2415
2416template <class _CharT, class _OutputIterator>
2417_OutputIterator
2418time_put<_CharT, _OutputIterator>::put(iter_type __s, ios_base& __iob,
2419 char_type __fl, const tm* __tm,
2420 const char_type* __pb,
2421 const char_type* __pe) const
2422{
2423 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2424 for (; __pb != __pe; ++__pb)
2425 {
2426 if (__ct.narrow(*__pb, 0) == '%')
2427 {
2428 if (++__pb == __pe)
2429 {
2430 *__s++ = __pb[-1];
2431 break;
2432 }
2433 char __mod = 0;
2434 char __fmt = __ct.narrow(*__pb, 0);
2435 if (__fmt == 'E' || __fmt == 'O')
2436 {
2437 if (++__pb == __pe)
2438 {
2439 *__s++ = __pb[-2];
2440 *__s++ = __pb[-1];
2441 break;
2442 }
2443 __mod = __fmt;
2444 __fmt = __ct.narrow(*__pb, 0);
2445 }
2446 __s = do_put(__s, __iob, __fl, __tm, __fmt, __mod);
2447 }
2448 else
2449 *__s++ = *__pb;
2450 }
2451 return __s;
2452}
2453
2454template <class _CharT, class _OutputIterator>
2455_OutputIterator
Howard Hinnantec3773c2011-12-01 20:21:04 +00002456time_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002457 char_type, const tm* __tm,
2458 char __fmt, char __mod) const
2459{
2460 char_type __nar[100];
2461 char_type* __nb = __nar;
2462 char_type* __ne = __nb + 100;
2463 __do_put(__nb, __ne, __tm, __fmt, __mod);
Howard Hinnant0949eed2011-06-30 21:18:19 +00002464 return _VSTD::copy(__nb, __ne, __s);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002465}
2466
Howard Hinnant499cea12013-08-23 17:37:05 +00002467_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS time_put<char>)
2468_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS time_put<wchar_t>)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002469
2470template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant0f678bd2013-08-12 18:38:34 +00002471class _LIBCPP_TYPE_VIS_ONLY time_put_byname
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002472 : public time_put<_CharT, _OutputIterator>
2473{
2474public:
2475 _LIBCPP_ALWAYS_INLINE
2476 explicit time_put_byname(const char* __nm, size_t __refs = 0)
2477 : time_put<_CharT, _OutputIterator>(__nm, __refs) {}
2478
2479 _LIBCPP_ALWAYS_INLINE
2480 explicit time_put_byname(const string& __nm, size_t __refs = 0)
2481 : time_put<_CharT, _OutputIterator>(__nm, __refs) {}
2482
2483protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002484 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002485 ~time_put_byname() {}
2486};
2487
Howard Hinnant499cea12013-08-23 17:37:05 +00002488_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS time_put_byname<char>)
2489_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS time_put_byname<wchar_t>)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002490
2491// money_base
2492
Howard Hinnant83eade62013-03-06 23:30:19 +00002493class _LIBCPP_TYPE_VIS money_base
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002494{
2495public:
2496 enum part {none, space, symbol, sign, value};
2497 struct pattern {char field[4];};
2498
2499 _LIBCPP_ALWAYS_INLINE money_base() {}
2500};
2501
2502// moneypunct
2503
2504template <class _CharT, bool _International = false>
Howard Hinnant0f678bd2013-08-12 18:38:34 +00002505class _LIBCPP_TYPE_VIS_ONLY moneypunct
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002506 : public locale::facet,
2507 public money_base
2508{
2509public:
2510 typedef _CharT char_type;
2511 typedef basic_string<char_type> string_type;
2512
Howard Hinnant82894812010-09-22 16:48:34 +00002513 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002514 explicit moneypunct(size_t __refs = 0)
2515 : locale::facet(__refs) {}
2516
2517 _LIBCPP_ALWAYS_INLINE char_type decimal_point() const {return do_decimal_point();}
2518 _LIBCPP_ALWAYS_INLINE char_type thousands_sep() const {return do_thousands_sep();}
2519 _LIBCPP_ALWAYS_INLINE string grouping() const {return do_grouping();}
2520 _LIBCPP_ALWAYS_INLINE string_type curr_symbol() const {return do_curr_symbol();}
2521 _LIBCPP_ALWAYS_INLINE string_type positive_sign() const {return do_positive_sign();}
2522 _LIBCPP_ALWAYS_INLINE string_type negative_sign() const {return do_negative_sign();}
2523 _LIBCPP_ALWAYS_INLINE int frac_digits() const {return do_frac_digits();}
2524 _LIBCPP_ALWAYS_INLINE pattern pos_format() const {return do_pos_format();}
2525 _LIBCPP_ALWAYS_INLINE pattern neg_format() const {return do_neg_format();}
2526
2527 static locale::id id;
2528 static const bool intl = _International;
2529
2530protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002531 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002532 ~moneypunct() {}
2533
2534 virtual char_type do_decimal_point() const {return numeric_limits<char_type>::max();}
2535 virtual char_type do_thousands_sep() const {return numeric_limits<char_type>::max();}
2536 virtual string do_grouping() const {return string();}
2537 virtual string_type do_curr_symbol() const {return string_type();}
2538 virtual string_type do_positive_sign() const {return string_type();}
2539 virtual string_type do_negative_sign() const {return string_type(1, '-');}
2540 virtual int do_frac_digits() const {return 0;}
2541 virtual pattern do_pos_format() const
Howard Hinnant9bae2a92012-11-06 21:48:33 +00002542 {pattern __p = {{symbol, sign, none, value}}; return __p;}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002543 virtual pattern do_neg_format() const
Howard Hinnant9bae2a92012-11-06 21:48:33 +00002544 {pattern __p = {{symbol, sign, none, value}}; return __p;}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002545};
2546
2547template <class _CharT, bool _International>
2548locale::id
2549moneypunct<_CharT, _International>::id;
2550
Howard Hinnant0a69fa12012-12-12 21:14:28 +00002551template <class _CharT, bool _International>
2552const bool
2553moneypunct<_CharT, _International>::intl;
2554
Howard Hinnant499cea12013-08-23 17:37:05 +00002555_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS moneypunct<char, false>)
2556_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS moneypunct<char, true>)
2557_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS moneypunct<wchar_t, false>)
2558_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS moneypunct<wchar_t, true>)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002559
2560// moneypunct_byname
2561
2562template <class _CharT, bool _International = false>
Howard Hinnant0f678bd2013-08-12 18:38:34 +00002563class _LIBCPP_TYPE_VIS_ONLY moneypunct_byname
Howard Hinnant82894812010-09-22 16:48:34 +00002564 : public moneypunct<_CharT, _International>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002565{
2566public:
2567 typedef money_base::pattern pattern;
2568 typedef _CharT char_type;
2569 typedef basic_string<char_type> string_type;
2570
2571 _LIBCPP_ALWAYS_INLINE
2572 explicit moneypunct_byname(const char* __nm, size_t __refs = 0)
2573 : moneypunct<_CharT, _International>(__refs) {init(__nm);}
2574
2575 _LIBCPP_ALWAYS_INLINE
2576 explicit moneypunct_byname(const string& __nm, size_t __refs = 0)
2577 : moneypunct<_CharT, _International>(__refs) {init(__nm.c_str());}
2578
2579protected:
Howard Hinnant82894812010-09-22 16:48:34 +00002580 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002581 ~moneypunct_byname() {}
2582
2583 virtual char_type do_decimal_point() const {return __decimal_point_;}
2584 virtual char_type do_thousands_sep() const {return __thousands_sep_;}
2585 virtual string do_grouping() const {return __grouping_;}
2586 virtual string_type do_curr_symbol() const {return __curr_symbol_;}
2587 virtual string_type do_positive_sign() const {return __positive_sign_;}
2588 virtual string_type do_negative_sign() const {return __negative_sign_;}
2589 virtual int do_frac_digits() const {return __frac_digits_;}
2590 virtual pattern do_pos_format() const {return __pos_format_;}
2591 virtual pattern do_neg_format() const {return __neg_format_;}
2592
2593private:
2594 char_type __decimal_point_;
2595 char_type __thousands_sep_;
2596 string __grouping_;
2597 string_type __curr_symbol_;
2598 string_type __positive_sign_;
2599 string_type __negative_sign_;
2600 int __frac_digits_;
2601 pattern __pos_format_;
2602 pattern __neg_format_;
2603
2604 void init(const char*);
2605};
2606
2607template<> void moneypunct_byname<char, false>::init(const char*);
2608template<> void moneypunct_byname<char, true>::init(const char*);
2609template<> void moneypunct_byname<wchar_t, false>::init(const char*);
2610template<> void moneypunct_byname<wchar_t, true>::init(const char*);
2611
Howard Hinnant499cea12013-08-23 17:37:05 +00002612_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS moneypunct_byname<char, false>)
2613_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS moneypunct_byname<char, true>)
2614_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS moneypunct_byname<wchar_t, false>)
2615_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS moneypunct_byname<wchar_t, true>)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002616
2617// money_get
2618
2619template <class _CharT>
2620class __money_get
2621{
2622protected:
2623 typedef _CharT char_type;
2624 typedef basic_string<char_type> string_type;
2625
2626 _LIBCPP_ALWAYS_INLINE __money_get() {}
2627
2628 static void __gather_info(bool __intl, const locale& __loc,
2629 money_base::pattern& __pat, char_type& __dp,
2630 char_type& __ts, string& __grp,
2631 string_type& __sym, string_type& __psn,
2632 string_type& __nsn, int& __fd);
2633};
2634
2635template <class _CharT>
2636void
2637__money_get<_CharT>::__gather_info(bool __intl, const locale& __loc,
2638 money_base::pattern& __pat, char_type& __dp,
2639 char_type& __ts, string& __grp,
2640 string_type& __sym, string_type& __psn,
2641 string_type& __nsn, int& __fd)
2642{
2643 if (__intl)
2644 {
2645 const moneypunct<char_type, true>& __mp =
2646 use_facet<moneypunct<char_type, true> >(__loc);
2647 __pat = __mp.neg_format();
2648 __nsn = __mp.negative_sign();
2649 __psn = __mp.positive_sign();
2650 __dp = __mp.decimal_point();
2651 __ts = __mp.thousands_sep();
2652 __grp = __mp.grouping();
2653 __sym = __mp.curr_symbol();
2654 __fd = __mp.frac_digits();
2655 }
2656 else
2657 {
2658 const moneypunct<char_type, false>& __mp =
2659 use_facet<moneypunct<char_type, false> >(__loc);
2660 __pat = __mp.neg_format();
2661 __nsn = __mp.negative_sign();
2662 __psn = __mp.positive_sign();
2663 __dp = __mp.decimal_point();
2664 __ts = __mp.thousands_sep();
2665 __grp = __mp.grouping();
2666 __sym = __mp.curr_symbol();
2667 __fd = __mp.frac_digits();
2668 }
2669}
2670
Howard Hinnant499cea12013-08-23 17:37:05 +00002671_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS __money_get<char>)
2672_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS __money_get<wchar_t>)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002673
2674template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Howard Hinnant0f678bd2013-08-12 18:38:34 +00002675class _LIBCPP_TYPE_VIS_ONLY money_get
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002676 : public locale::facet,
2677 private __money_get<_CharT>
2678{
2679public:
2680 typedef _CharT char_type;
2681 typedef _InputIterator iter_type;
2682 typedef basic_string<char_type> string_type;
2683
2684 _LIBCPP_ALWAYS_INLINE
2685 explicit money_get(size_t __refs = 0)
2686 : locale::facet(__refs) {}
2687
2688 _LIBCPP_ALWAYS_INLINE
2689 iter_type get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob,
2690 ios_base::iostate& __err, long double& __v) const
2691 {
2692 return do_get(__b, __e, __intl, __iob, __err, __v);
2693 }
2694
2695 _LIBCPP_ALWAYS_INLINE
2696 iter_type get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob,
2697 ios_base::iostate& __err, string_type& __v) const
2698 {
2699 return do_get(__b, __e, __intl, __iob, __err, __v);
2700 }
2701
2702 static locale::id id;
2703
2704protected:
2705
Howard Hinnant82894812010-09-22 16:48:34 +00002706 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002707 ~money_get() {}
Howard Hinnant324bb032010-08-22 00:02:43 +00002708
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002709 virtual iter_type do_get(iter_type __b, iter_type __e, bool __intl,
2710 ios_base& __iob, ios_base::iostate& __err,
2711 long double& __v) const;
2712 virtual iter_type do_get(iter_type __b, iter_type __e, bool __intl,
2713 ios_base& __iob, ios_base::iostate& __err,
2714 string_type& __v) const;
2715
2716private:
2717 static bool __do_get(iter_type& __b, iter_type __e,
2718 bool __intl, const locale& __loc,
2719 ios_base::fmtflags __flags, ios_base::iostate& __err,
2720 bool& __neg, const ctype<char_type>& __ct,
2721 unique_ptr<char_type, void(*)(void*)>& __wb,
2722 char_type*& __wn, char_type* __we);
2723};
2724
2725template <class _CharT, class _InputIterator>
2726locale::id
2727money_get<_CharT, _InputIterator>::id;
2728
Howard Hinnant0f678bd2013-08-12 18:38:34 +00002729_LIBCPP_FUNC_VIS void __do_nothing(void*);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002730
2731template <class _Tp>
2732_LIBCPP_HIDDEN
2733void
2734__double_or_nothing(unique_ptr<_Tp, void(*)(void*)>& __b, _Tp*& __n, _Tp*& __e)
2735{
2736 bool __owns = __b.get_deleter() != __do_nothing;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002737 size_t __cur_cap = static_cast<size_t>(__e-__b.get()) * sizeof(_Tp);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002738 size_t __new_cap = __cur_cap < numeric_limits<size_t>::max() / 2 ?
2739 2 * __cur_cap : numeric_limits<size_t>::max();
Marshall Clow1d306de2014-10-27 19:08:10 +00002740 if (__new_cap == 0)
2741 __new_cap = sizeof(_Tp);
Howard Hinnantec3773c2011-12-01 20:21:04 +00002742 size_t __n_off = static_cast<size_t>(__n - __b.get());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002743 _Tp* __t = (_Tp*)realloc(__owns ? __b.get() : 0, __new_cap);
2744 if (__t == 0)
2745 __throw_bad_alloc();
2746 if (__owns)
2747 __b.release();
2748 __b = unique_ptr<_Tp, void(*)(void*)>(__t, free);
2749 __new_cap /= sizeof(_Tp);
2750 __n = __b.get() + __n_off;
2751 __e = __b.get() + __new_cap;
2752}
2753
2754// true == success
2755template <class _CharT, class _InputIterator>
2756bool
2757money_get<_CharT, _InputIterator>::__do_get(iter_type& __b, iter_type __e,
2758 bool __intl, const locale& __loc,
2759 ios_base::fmtflags __flags,
2760 ios_base::iostate& __err,
2761 bool& __neg,
2762 const ctype<char_type>& __ct,
2763 unique_ptr<char_type, void(*)(void*)>& __wb,
2764 char_type*& __wn, char_type* __we)
2765{
2766 const unsigned __bz = 100;
2767 unsigned __gbuf[__bz];
2768 unique_ptr<unsigned, void(*)(void*)> __gb(__gbuf, __do_nothing);
2769 unsigned* __gn = __gb.get();
2770 unsigned* __ge = __gn + __bz;
2771 money_base::pattern __pat;
2772 char_type __dp;
2773 char_type __ts;
2774 string __grp;
2775 string_type __sym;
2776 string_type __psn;
2777 string_type __nsn;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00002778 // Capture the spaces read into money_base::{space,none} so they
2779 // can be compared to initial spaces in __sym.
2780 string_type __spaces;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002781 int __fd;
2782 __money_get<_CharT>::__gather_info(__intl, __loc, __pat, __dp, __ts, __grp,
2783 __sym, __psn, __nsn, __fd);
2784 const string_type* __trailing_sign = 0;
2785 __wn = __wb.get();
2786 for (unsigned __p = 0; __p < 4 && __b != __e; ++__p)
2787 {
2788 switch (__pat.field[__p])
2789 {
2790 case money_base::space:
2791 if (__p != 3)
2792 {
2793 if (__ct.is(ctype_base::space, *__b))
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00002794 __spaces.push_back(*__b++);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002795 else
2796 {
2797 __err |= ios_base::failbit;
2798 return false;
2799 }
2800 }
Howard Hinnant324bb032010-08-22 00:02:43 +00002801 // drop through
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002802 case money_base::none:
2803 if (__p != 3)
2804 {
2805 while (__b != __e && __ct.is(ctype_base::space, *__b))
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00002806 __spaces.push_back(*__b++);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002807 }
2808 break;
2809 case money_base::sign:
2810 if (__psn.size() + __nsn.size() > 0)
2811 {
2812 if (__psn.size() == 0 || __nsn.size() == 0)
2813 { // sign is optional
2814 if (__psn.size() > 0)
2815 { // __nsn.size() == 0
2816 if (*__b == __psn[0])
2817 {
2818 ++__b;
2819 if (__psn.size() > 1)
2820 __trailing_sign = &__psn;
2821 }
2822 else
2823 __neg = true;
2824 }
2825 else if (*__b == __nsn[0]) // __nsn.size() > 0 && __psn.size() == 0
2826 {
2827 ++__b;
2828 __neg = true;
2829 if (__nsn.size() > 1)
2830 __trailing_sign = &__nsn;
2831 }
2832 }
2833 else // sign is required
2834 {
2835 if (*__b == __psn[0])
2836 {
2837 ++__b;
2838 if (__psn.size() > 1)
2839 __trailing_sign = &__psn;
2840 }
2841 else if (*__b == __nsn[0])
2842 {
2843 ++__b;
2844 __neg = true;
2845 if (__nsn.size() > 1)
2846 __trailing_sign = &__nsn;
2847 }
2848 else
2849 {
2850 __err |= ios_base::failbit;
2851 return false;
2852 }
2853 }
2854 }
2855 break;
2856 case money_base::symbol:
2857 {
2858 bool __more_needed = __trailing_sign ||
2859 (__p < 2) ||
2860 (__p == 2 && __pat.field[3] != static_cast<char>(money_base::none));
Marshall Clow9de3d4c2013-10-13 01:02:45 +00002861 bool __sb = (__flags & ios_base::showbase) != 0;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002862 if (__sb || __more_needed)
2863 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00002864 typename string_type::const_iterator __sym_space_end = __sym.begin();
2865 if (__p > 0 && (__pat.field[__p - 1] == money_base::none ||
2866 __pat.field[__p - 1] == money_base::space)) {
2867 // Match spaces we've already read against spaces at
2868 // the beginning of __sym.
2869 while (__sym_space_end != __sym.end() &&
2870 __ct.is(ctype_base::space, *__sym_space_end))
2871 ++__sym_space_end;
2872 const size_t __num_spaces = __sym_space_end - __sym.begin();
2873 if (__num_spaces > __spaces.size() ||
2874 !equal(__spaces.end() - __num_spaces, __spaces.end(),
2875 __sym.begin())) {
2876 // No match. Put __sym_space_end back at the
2877 // beginning of __sym, which will prevent a
2878 // match in the next loop.
2879 __sym_space_end = __sym.begin();
2880 }
2881 }
2882 typename string_type::const_iterator __sym_curr_char = __sym_space_end;
2883 while (__sym_curr_char != __sym.end() && __b != __e &&
2884 *__b == *__sym_curr_char) {
2885 ++__b;
2886 ++__sym_curr_char;
2887 }
2888 if (__sb && __sym_curr_char != __sym.end())
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002889 {
2890 __err |= ios_base::failbit;
2891 return false;
2892 }
2893 }
2894 }
2895 break;
2896 case money_base::value:
2897 {
2898 unsigned __ng = 0;
2899 for (; __b != __e; ++__b)
2900 {
2901 char_type __c = *__b;
2902 if (__ct.is(ctype_base::digit, __c))
2903 {
2904 if (__wn == __we)
2905 __double_or_nothing(__wb, __wn, __we);
2906 *__wn++ = __c;
2907 ++__ng;
2908 }
2909 else if (__grp.size() > 0 && __ng > 0 && __c == __ts)
2910 {
2911 if (__gn == __ge)
2912 __double_or_nothing(__gb, __gn, __ge);
2913 *__gn++ = __ng;
2914 __ng = 0;
2915 }
2916 else
2917 break;
2918 }
2919 if (__gb.get() != __gn && __ng > 0)
2920 {
2921 if (__gn == __ge)
2922 __double_or_nothing(__gb, __gn, __ge);
2923 *__gn++ = __ng;
2924 }
2925 if (__fd > 0)
2926 {
2927 if (__b == __e || *__b != __dp)
2928 {
2929 __err |= ios_base::failbit;
2930 return false;
2931 }
2932 for (++__b; __fd > 0; --__fd, ++__b)
2933 {
2934 if (__b == __e || !__ct.is(ctype_base::digit, *__b))
2935 {
2936 __err |= ios_base::failbit;
2937 return false;
2938 }
2939 if (__wn == __we)
2940 __double_or_nothing(__wb, __wn, __we);
2941 *__wn++ = *__b;
2942 }
2943 }
2944 if (__wn == __wb.get())
2945 {
2946 __err |= ios_base::failbit;
2947 return false;
2948 }
2949 }
2950 break;
2951 }
2952 }
2953 if (__trailing_sign)
2954 {
2955 for (unsigned __i = 1; __i < __trailing_sign->size(); ++__i, ++__b)
2956 {
2957 if (__b == __e || *__b != (*__trailing_sign)[__i])
2958 {
2959 __err |= ios_base::failbit;
2960 return false;
2961 }
2962 }
2963 }
2964 if (__gb.get() != __gn)
2965 {
2966 ios_base::iostate __et = ios_base::goodbit;
2967 __check_grouping(__grp, __gb.get(), __gn, __et);
2968 if (__et)
2969 {
2970 __err |= ios_base::failbit;
2971 return false;
2972 }
2973 }
2974 return true;
2975}
2976
2977template <class _CharT, class _InputIterator>
2978_InputIterator
2979money_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
2980 bool __intl, ios_base& __iob,
2981 ios_base::iostate& __err,
2982 long double& __v) const
2983{
Howard Hinnantec3773c2011-12-01 20:21:04 +00002984 const int __bz = 100;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002985 char_type __wbuf[__bz];
2986 unique_ptr<char_type, void(*)(void*)> __wb(__wbuf, __do_nothing);
2987 char_type* __wn;
2988 char_type* __we = __wbuf + __bz;
2989 locale __loc = __iob.getloc();
2990 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
2991 bool __neg = false;
2992 if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct,
2993 __wb, __wn, __we))
2994 {
2995 const char __src[] = "0123456789";
2996 char_type __atoms[sizeof(__src)-1];
2997 __ct.widen(__src, __src + (sizeof(__src)-1), __atoms);
2998 char __nbuf[__bz];
2999 char* __nc = __nbuf;
3000 unique_ptr<char, void(*)(void*)> __h(0, free);
3001 if (__wn - __wb.get() > __bz-2)
3002 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00003003 __h.reset((char*)malloc(static_cast<size_t>(__wn - __wb.get() + 2)));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003004 if (__h.get() == 0)
3005 __throw_bad_alloc();
3006 __nc = __h.get();
3007 }
3008 if (__neg)
3009 *__nc++ = '-';
3010 for (const char_type* __w = __wb.get(); __w < __wn; ++__w, ++__nc)
Marshall Clow9b145da2013-03-22 02:14:40 +00003011 *__nc = __src[find(__atoms, _VSTD::end(__atoms), *__w) - __atoms];
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003012 *__nc = char();
3013 if (sscanf(__nbuf, "%Lf", &__v) != 1)
3014 __throw_runtime_error("money_get error");
3015 }
3016 if (__b == __e)
3017 __err |= ios_base::eofbit;
3018 return __b;
3019}
3020
3021template <class _CharT, class _InputIterator>
3022_InputIterator
3023money_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
3024 bool __intl, ios_base& __iob,
3025 ios_base::iostate& __err,
3026 string_type& __v) const
3027{
Howard Hinnantec3773c2011-12-01 20:21:04 +00003028 const int __bz = 100;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003029 char_type __wbuf[__bz];
3030 unique_ptr<char_type, void(*)(void*)> __wb(__wbuf, __do_nothing);
3031 char_type* __wn;
3032 char_type* __we = __wbuf + __bz;
3033 locale __loc = __iob.getloc();
3034 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3035 bool __neg = false;
3036 if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct,
3037 __wb, __wn, __we))
3038 {
3039 __v.clear();
3040 if (__neg)
3041 __v.push_back(__ct.widen('-'));
3042 char_type __z = __ct.widen('0');
3043 char_type* __w;
3044 for (__w = __wb.get(); __w < __wn-1; ++__w)
3045 if (*__w != __z)
3046 break;
3047 __v.append(__w, __wn);
3048 }
3049 if (__b == __e)
3050 __err |= ios_base::eofbit;
3051 return __b;
3052}
3053
Howard Hinnant499cea12013-08-23 17:37:05 +00003054_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS money_get<char>)
3055_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS money_get<wchar_t>)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003056
3057// money_put
3058
3059template <class _CharT>
3060class __money_put
3061{
3062protected:
3063 typedef _CharT char_type;
3064 typedef basic_string<char_type> string_type;
3065
3066 _LIBCPP_ALWAYS_INLINE __money_put() {}
3067
3068 static void __gather_info(bool __intl, bool __neg, const locale& __loc,
3069 money_base::pattern& __pat, char_type& __dp,
3070 char_type& __ts, string& __grp,
3071 string_type& __sym, string_type& __sn,
3072 int& __fd);
3073 static void __format(char_type* __mb, char_type*& __mi, char_type*& __me,
3074 ios_base::fmtflags __flags,
3075 const char_type* __db, const char_type* __de,
3076 const ctype<char_type>& __ct, bool __neg,
3077 const money_base::pattern& __pat, char_type __dp,
3078 char_type __ts, const string& __grp,
3079 const string_type& __sym, const string_type& __sn,
3080 int __fd);
3081};
3082
3083template <class _CharT>
3084void
3085__money_put<_CharT>::__gather_info(bool __intl, bool __neg, const locale& __loc,
3086 money_base::pattern& __pat, char_type& __dp,
3087 char_type& __ts, string& __grp,
3088 string_type& __sym, string_type& __sn,
3089 int& __fd)
3090{
3091 if (__intl)
3092 {
3093 const moneypunct<char_type, true>& __mp =
3094 use_facet<moneypunct<char_type, true> >(__loc);
3095 if (__neg)
3096 {
3097 __pat = __mp.neg_format();
3098 __sn = __mp.negative_sign();
3099 }
3100 else
3101 {
3102 __pat = __mp.pos_format();
3103 __sn = __mp.positive_sign();
3104 }
3105 __dp = __mp.decimal_point();
3106 __ts = __mp.thousands_sep();
3107 __grp = __mp.grouping();
3108 __sym = __mp.curr_symbol();
3109 __fd = __mp.frac_digits();
3110 }
3111 else
3112 {
3113 const moneypunct<char_type, false>& __mp =
3114 use_facet<moneypunct<char_type, false> >(__loc);
3115 if (__neg)
3116 {
3117 __pat = __mp.neg_format();
3118 __sn = __mp.negative_sign();
3119 }
3120 else
3121 {
3122 __pat = __mp.pos_format();
3123 __sn = __mp.positive_sign();
3124 }
3125 __dp = __mp.decimal_point();
3126 __ts = __mp.thousands_sep();
3127 __grp = __mp.grouping();
3128 __sym = __mp.curr_symbol();
3129 __fd = __mp.frac_digits();
3130 }
3131}
3132
3133template <class _CharT>
3134void
3135__money_put<_CharT>::__format(char_type* __mb, char_type*& __mi, char_type*& __me,
3136 ios_base::fmtflags __flags,
3137 const char_type* __db, const char_type* __de,
3138 const ctype<char_type>& __ct, bool __neg,
3139 const money_base::pattern& __pat, char_type __dp,
3140 char_type __ts, const string& __grp,
3141 const string_type& __sym, const string_type& __sn,
3142 int __fd)
3143{
3144 __me = __mb;
3145 for (unsigned __p = 0; __p < 4; ++__p)
3146 {
3147 switch (__pat.field[__p])
3148 {
3149 case money_base::none:
3150 __mi = __me;
3151 break;
3152 case money_base::space:
3153 __mi = __me;
3154 *__me++ = __ct.widen(' ');
3155 break;
3156 case money_base::sign:
3157 if (!__sn.empty())
3158 *__me++ = __sn[0];
3159 break;
3160 case money_base::symbol:
3161 if (!__sym.empty() && (__flags & ios_base::showbase))
Howard Hinnant0949eed2011-06-30 21:18:19 +00003162 __me = _VSTD::copy(__sym.begin(), __sym.end(), __me);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003163 break;
3164 case money_base::value:
3165 {
3166 // remember start of value so we can reverse it
3167 char_type* __t = __me;
3168 // find beginning of digits
3169 if (__neg)
3170 ++__db;
3171 // find end of digits
3172 const char_type* __d;
3173 for (__d = __db; __d < __de; ++__d)
3174 if (!__ct.is(ctype_base::digit, *__d))
3175 break;
3176 // print fractional part
3177 if (__fd > 0)
3178 {
3179 int __f;
3180 for (__f = __fd; __d > __db && __f > 0; --__f)
3181 *__me++ = *--__d;
3182 char_type __z = __f > 0 ? __ct.widen('0') : char_type();
3183 for (; __f > 0; --__f)
3184 *__me++ = __z;
3185 *__me++ = __dp;
3186 }
3187 // print units part
3188 if (__d == __db)
3189 {
3190 *__me++ = __ct.widen('0');
3191 }
3192 else
3193 {
3194 unsigned __ng = 0;
3195 unsigned __ig = 0;
3196 unsigned __gl = __grp.empty() ? numeric_limits<unsigned>::max()
3197 : static_cast<unsigned>(__grp[__ig]);
3198 while (__d != __db)
3199 {
3200 if (__ng == __gl)
3201 {
3202 *__me++ = __ts;
3203 __ng = 0;
3204 if (++__ig < __grp.size())
3205 __gl = __grp[__ig] == numeric_limits<char>::max() ?
3206 numeric_limits<unsigned>::max() :
3207 static_cast<unsigned>(__grp[__ig]);
3208 }
3209 *__me++ = *--__d;
3210 ++__ng;
3211 }
3212 }
3213 // reverse it
3214 reverse(__t, __me);
3215 }
3216 break;
3217 }
3218 }
3219 // print rest of sign, if any
3220 if (__sn.size() > 1)
Howard Hinnant0949eed2011-06-30 21:18:19 +00003221 __me = _VSTD::copy(__sn.begin()+1, __sn.end(), __me);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003222 // set alignment
3223 if ((__flags & ios_base::adjustfield) == ios_base::left)
3224 __mi = __me;
3225 else if ((__flags & ios_base::adjustfield) != ios_base::internal)
3226 __mi = __mb;
3227}
3228
Howard Hinnant499cea12013-08-23 17:37:05 +00003229_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS __money_put<char>)
3230_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS __money_put<wchar_t>)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003231
3232template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Howard Hinnant0f678bd2013-08-12 18:38:34 +00003233class _LIBCPP_TYPE_VIS_ONLY money_put
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003234 : public locale::facet,
3235 private __money_put<_CharT>
3236{
3237public:
3238 typedef _CharT char_type;
3239 typedef _OutputIterator iter_type;
3240 typedef basic_string<char_type> string_type;
3241
3242 _LIBCPP_ALWAYS_INLINE
3243 explicit money_put(size_t __refs = 0)
3244 : locale::facet(__refs) {}
3245
3246 _LIBCPP_ALWAYS_INLINE
3247 iter_type put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl,
3248 long double __units) const
3249 {
3250 return do_put(__s, __intl, __iob, __fl, __units);
3251 }
3252
3253 _LIBCPP_ALWAYS_INLINE
3254 iter_type put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl,
3255 const string_type& __digits) const
3256 {
3257 return do_put(__s, __intl, __iob, __fl, __digits);
3258 }
3259
3260 static locale::id id;
3261
3262protected:
Howard Hinnant82894812010-09-22 16:48:34 +00003263 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003264 ~money_put() {}
3265
3266 virtual iter_type do_put(iter_type __s, bool __intl, ios_base& __iob,
3267 char_type __fl, long double __units) const;
3268 virtual iter_type do_put(iter_type __s, bool __intl, ios_base& __iob,
3269 char_type __fl, const string_type& __digits) const;
3270};
3271
3272template <class _CharT, class _OutputIterator>
3273locale::id
3274money_put<_CharT, _OutputIterator>::id;
3275
3276template <class _CharT, class _OutputIterator>
3277_OutputIterator
3278money_put<_CharT, _OutputIterator>::do_put(iter_type __s, bool __intl,
3279 ios_base& __iob, char_type __fl,
3280 long double __units) const
3281{
3282 // convert to char
3283 const size_t __bs = 100;
3284 char __buf[__bs];
3285 char* __bb = __buf;
3286 char_type __digits[__bs];
3287 char_type* __db = __digits;
Howard Hinnantec3773c2011-12-01 20:21:04 +00003288 size_t __n = static_cast<size_t>(snprintf(__bb, __bs, "%.0Lf", __units));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003289 unique_ptr<char, void(*)(void*)> __hn(0, free);
3290 unique_ptr<char_type, void(*)(void*)> __hd(0, free);
3291 // secure memory for digit storage
3292 if (__n > __bs-1)
3293 {
Ben Craigfd556582016-03-09 15:39:39 +00003294 __n = static_cast<size_t>(__libcpp_asprintf_l(&__bb, _LIBCPP_GET_C_LOCALE, "%.0Lf", __units));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003295 if (__bb == 0)
3296 __throw_bad_alloc();
3297 __hn.reset(__bb);
3298 __hd.reset((char_type*)malloc(__n * sizeof(char_type)));
Howard Hinnant05b57d52012-03-07 20:37:43 +00003299 if (__hd == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003300 __throw_bad_alloc();
3301 __db = __hd.get();
3302 }
3303 // gather info
3304 locale __loc = __iob.getloc();
3305 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3306 __ct.widen(__bb, __bb + __n, __db);
3307 bool __neg = __n > 0 && __bb[0] == '-';
3308 money_base::pattern __pat;
3309 char_type __dp;
3310 char_type __ts;
3311 string __grp;
3312 string_type __sym;
3313 string_type __sn;
3314 int __fd;
3315 this->__gather_info(__intl, __neg, __loc, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3316 // secure memory for formatting
3317 char_type __mbuf[__bs];
3318 char_type* __mb = __mbuf;
3319 unique_ptr<char_type, void(*)(void*)> __hw(0, free);
3320 size_t __exn = static_cast<int>(__n) > __fd ?
Howard Hinnantec3773c2011-12-01 20:21:04 +00003321 (__n - static_cast<size_t>(__fd)) * 2 + __sn.size() +
3322 __sym.size() + static_cast<size_t>(__fd) + 1
3323 : __sn.size() + __sym.size() + static_cast<size_t>(__fd) + 2;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003324 if (__exn > __bs)
3325 {
3326 __hw.reset((char_type*)malloc(__exn * sizeof(char_type)));
3327 __mb = __hw.get();
3328 if (__mb == 0)
3329 __throw_bad_alloc();
3330 }
3331 // format
3332 char_type* __mi;
3333 char_type* __me;
3334 this->__format(__mb, __mi, __me, __iob.flags(),
3335 __db, __db + __n, __ct,
3336 __neg, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3337 return __pad_and_output(__s, __mb, __mi, __me, __iob, __fl);
3338}
3339
3340template <class _CharT, class _OutputIterator>
3341_OutputIterator
3342money_put<_CharT, _OutputIterator>::do_put(iter_type __s, bool __intl,
3343 ios_base& __iob, char_type __fl,
3344 const string_type& __digits) const
3345{
3346 // gather info
3347 locale __loc = __iob.getloc();
3348 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3349 bool __neg = __digits.size() > 0 && __digits[0] == __ct.widen('-');
3350 money_base::pattern __pat;
3351 char_type __dp;
3352 char_type __ts;
3353 string __grp;
3354 string_type __sym;
3355 string_type __sn;
3356 int __fd;
3357 this->__gather_info(__intl, __neg, __loc, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3358 // secure memory for formatting
3359 char_type __mbuf[100];
3360 char_type* __mb = __mbuf;
3361 unique_ptr<char_type, void(*)(void*)> __h(0, free);
Howard Hinnantec3773c2011-12-01 20:21:04 +00003362 size_t __exn = static_cast<int>(__digits.size()) > __fd ?
3363 (__digits.size() - static_cast<size_t>(__fd)) * 2 +
3364 __sn.size() + __sym.size() + static_cast<size_t>(__fd) + 1
3365 : __sn.size() + __sym.size() + static_cast<size_t>(__fd) + 2;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003366 if (__exn > 100)
3367 {
3368 __h.reset((char_type*)malloc(__exn * sizeof(char_type)));
3369 __mb = __h.get();
3370 if (__mb == 0)
3371 __throw_bad_alloc();
3372 }
3373 // format
3374 char_type* __mi;
3375 char_type* __me;
3376 this->__format(__mb, __mi, __me, __iob.flags(),
3377 __digits.data(), __digits.data() + __digits.size(), __ct,
3378 __neg, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3379 return __pad_and_output(__s, __mb, __mi, __me, __iob, __fl);
3380}
3381
Howard Hinnant499cea12013-08-23 17:37:05 +00003382_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS money_put<char>)
3383_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS money_put<wchar_t>)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003384
3385// messages
3386
Howard Hinnant83eade62013-03-06 23:30:19 +00003387class _LIBCPP_TYPE_VIS messages_base
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003388{
3389public:
Howard Hinnantb2080c72011-02-25 00:51:08 +00003390 typedef ptrdiff_t catalog;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003391
3392 _LIBCPP_ALWAYS_INLINE messages_base() {}
3393};
3394
3395template <class _CharT>
Howard Hinnant0f678bd2013-08-12 18:38:34 +00003396class _LIBCPP_TYPE_VIS_ONLY messages
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003397 : public locale::facet,
3398 public messages_base
3399{
3400public:
3401 typedef _CharT char_type;
3402 typedef basic_string<_CharT> string_type;
3403
3404 _LIBCPP_ALWAYS_INLINE
3405 explicit messages(size_t __refs = 0)
3406 : locale::facet(__refs) {}
3407
3408 _LIBCPP_ALWAYS_INLINE
3409 catalog open(const basic_string<char>& __nm, const locale& __loc) const
3410 {
3411 return do_open(__nm, __loc);
3412 }
3413
3414 _LIBCPP_ALWAYS_INLINE
3415 string_type get(catalog __c, int __set, int __msgid,
3416 const string_type& __dflt) const
3417 {
3418 return do_get(__c, __set, __msgid, __dflt);
3419 }
3420
3421 _LIBCPP_ALWAYS_INLINE
3422 void close(catalog __c) const
3423 {
3424 do_close(__c);
3425 }
3426
3427 static locale::id id;
3428
3429protected:
Howard Hinnant82894812010-09-22 16:48:34 +00003430 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003431 ~messages() {}
3432
3433 virtual catalog do_open(const basic_string<char>&, const locale&) const;
3434 virtual string_type do_get(catalog, int __set, int __msgid,
3435 const string_type& __dflt) const;
3436 virtual void do_close(catalog) const;
3437};
3438
3439template <class _CharT>
3440locale::id
3441messages<_CharT>::id;
3442
3443template <class _CharT>
3444typename messages<_CharT>::catalog
3445messages<_CharT>::do_open(const basic_string<char>& __nm, const locale&) const
3446{
Ed Schouten0251f0f2015-03-11 16:39:36 +00003447#ifdef _LIBCPP_HAS_CATOPEN
Howard Hinnant11624452011-10-11 16:00:46 +00003448 catalog __cat = (catalog)catopen(__nm.c_str(), NL_CAT_LOCALE);
Howard Hinnantb2080c72011-02-25 00:51:08 +00003449 if (__cat != -1)
3450 __cat = static_cast<catalog>((static_cast<size_t>(__cat) >> 1));
3451 return __cat;
Ed Schouten0251f0f2015-03-11 16:39:36 +00003452#else // !_LIBCPP_HAS_CATOPEN
3453 return -1;
3454#endif // _LIBCPP_HAS_CATOPEN
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003455}
3456
3457template <class _CharT>
3458typename messages<_CharT>::string_type
3459messages<_CharT>::do_get(catalog __c, int __set, int __msgid,
3460 const string_type& __dflt) const
3461{
Ed Schouten0251f0f2015-03-11 16:39:36 +00003462#ifdef _LIBCPP_HAS_CATOPEN
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003463 string __ndflt;
3464 __narrow_to_utf8<sizeof(char_type)*__CHAR_BIT__>()(back_inserter(__ndflt),
3465 __dflt.c_str(),
3466 __dflt.c_str() + __dflt.size());
Howard Hinnantb2080c72011-02-25 00:51:08 +00003467 if (__c != -1)
3468 __c <<= 1;
Howard Hinnant11624452011-10-11 16:00:46 +00003469 nl_catd __cat = (nl_catd)__c;
Howard Hinnantb2080c72011-02-25 00:51:08 +00003470 char* __n = catgets(__cat, __set, __msgid, __ndflt.c_str());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003471 string_type __w;
3472 __widen_from_utf8<sizeof(char_type)*__CHAR_BIT__>()(back_inserter(__w),
3473 __n, __n + strlen(__n));
3474 return __w;
Ed Schouten0251f0f2015-03-11 16:39:36 +00003475#else // !_LIBCPP_HAS_CATOPEN
3476 return __dflt;
3477#endif // _LIBCPP_HAS_CATOPEN
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003478}
3479
3480template <class _CharT>
3481void
3482messages<_CharT>::do_close(catalog __c) const
3483{
Ed Schouten0251f0f2015-03-11 16:39:36 +00003484#ifdef _LIBCPP_HAS_CATOPEN
Howard Hinnantb2080c72011-02-25 00:51:08 +00003485 if (__c != -1)
3486 __c <<= 1;
Howard Hinnant11624452011-10-11 16:00:46 +00003487 nl_catd __cat = (nl_catd)__c;
Howard Hinnantb2080c72011-02-25 00:51:08 +00003488 catclose(__cat);
Ed Schouten0251f0f2015-03-11 16:39:36 +00003489#endif // _LIBCPP_HAS_CATOPEN
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003490}
3491
Howard Hinnant499cea12013-08-23 17:37:05 +00003492_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS messages<char>)
3493_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS messages<wchar_t>)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003494
3495template <class _CharT>
Howard Hinnant0f678bd2013-08-12 18:38:34 +00003496class _LIBCPP_TYPE_VIS_ONLY messages_byname
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003497 : public messages<_CharT>
3498{
3499public:
3500 typedef messages_base::catalog catalog;
3501 typedef basic_string<_CharT> string_type;
3502
3503 _LIBCPP_ALWAYS_INLINE
3504 explicit messages_byname(const char*, size_t __refs = 0)
3505 : messages<_CharT>(__refs) {}
3506
3507 _LIBCPP_ALWAYS_INLINE
3508 explicit messages_byname(const string&, size_t __refs = 0)
3509 : messages<_CharT>(__refs) {}
3510
3511protected:
Howard Hinnant82894812010-09-22 16:48:34 +00003512 _LIBCPP_ALWAYS_INLINE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003513 ~messages_byname() {}
3514};
3515
Howard Hinnant499cea12013-08-23 17:37:05 +00003516_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS messages_byname<char>)
3517_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS messages_byname<wchar_t>)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003518
Howard Hinnantd23b4642010-05-31 20:58:54 +00003519template<class _Codecvt, class _Elem = wchar_t,
3520 class _Wide_alloc = allocator<_Elem>,
3521 class _Byte_alloc = allocator<char> >
Howard Hinnant0f678bd2013-08-12 18:38:34 +00003522class _LIBCPP_TYPE_VIS_ONLY wstring_convert
Howard Hinnantd23b4642010-05-31 20:58:54 +00003523{
3524public:
3525 typedef basic_string<char, char_traits<char>, _Byte_alloc> byte_string;
3526 typedef basic_string<_Elem, char_traits<_Elem>, _Wide_alloc> wide_string;
3527 typedef typename _Codecvt::state_type state_type;
3528 typedef typename wide_string::traits_type::int_type int_type;
3529
3530private:
3531 byte_string __byte_err_string_;
3532 wide_string __wide_err_string_;
3533 _Codecvt* __cvtptr_;
3534 state_type __cvtstate_;
3535 size_t __cvtcount_;
3536
3537 wstring_convert(const wstring_convert& __wc);
3538 wstring_convert& operator=(const wstring_convert& __wc);
3539public:
Evgeniy Stepanova3b25f82015-11-07 01:22:13 +00003540 _LIBCPP_ALWAYS_INLINE
Marshall Clow83179a72013-08-27 20:18:59 +00003541 _LIBCPP_EXPLICIT_AFTER_CXX11 wstring_convert(_Codecvt* __pcvt = new _Codecvt);
Evgeniy Stepanova3b25f82015-11-07 01:22:13 +00003542 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003543 wstring_convert(_Codecvt* __pcvt, state_type __state);
Marshall Clow83179a72013-08-27 20:18:59 +00003544 _LIBCPP_EXPLICIT_AFTER_CXX11 wstring_convert(const byte_string& __byte_err,
Howard Hinnantd23b4642010-05-31 20:58:54 +00003545 const wide_string& __wide_err = wide_string());
Howard Hinnant73d21a42010-09-04 23:28:19 +00003546#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Evgeniy Stepanova3b25f82015-11-07 01:22:13 +00003547 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003548 wstring_convert(wstring_convert&& __wc);
3549#endif
3550 ~wstring_convert();
3551
Howard Hinnant82894812010-09-22 16:48:34 +00003552 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003553 wide_string from_bytes(char __byte)
3554 {return from_bytes(&__byte, &__byte+1);}
Howard Hinnant82894812010-09-22 16:48:34 +00003555 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003556 wide_string from_bytes(const char* __ptr)
3557 {return from_bytes(__ptr, __ptr + char_traits<char>::length(__ptr));}
Howard Hinnant82894812010-09-22 16:48:34 +00003558 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003559 wide_string from_bytes(const byte_string& __str)
3560 {return from_bytes(__str.data(), __str.data() + __str.size());}
3561 wide_string from_bytes(const char* __first, const char* __last);
3562
Howard Hinnant82894812010-09-22 16:48:34 +00003563 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003564 byte_string to_bytes(_Elem __wchar)
3565 {return to_bytes(&__wchar, &__wchar+1);}
Howard Hinnant82894812010-09-22 16:48:34 +00003566 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003567 byte_string to_bytes(const _Elem* __wptr)
3568 {return to_bytes(__wptr, __wptr + char_traits<_Elem>::length(__wptr));}
Howard Hinnant82894812010-09-22 16:48:34 +00003569 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003570 byte_string to_bytes(const wide_string& __wstr)
3571 {return to_bytes(__wstr.data(), __wstr.data() + __wstr.size());}
3572 byte_string to_bytes(const _Elem* __first, const _Elem* __last);
3573
Howard Hinnant82894812010-09-22 16:48:34 +00003574 _LIBCPP_ALWAYS_INLINE
Marshall Clow83179a72013-08-27 20:18:59 +00003575 size_t converted() const _NOEXCEPT {return __cvtcount_;}
Howard Hinnant82894812010-09-22 16:48:34 +00003576 _LIBCPP_ALWAYS_INLINE
Howard Hinnantd23b4642010-05-31 20:58:54 +00003577 state_type state() const {return __cvtstate_;}
3578};
3579
3580template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Evgeniy Stepanova3b25f82015-11-07 01:22:13 +00003581inline
Howard Hinnantd23b4642010-05-31 20:58:54 +00003582wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3583 wstring_convert(_Codecvt* __pcvt)
3584 : __cvtptr_(__pcvt), __cvtstate_(), __cvtcount_(0)
3585{
3586}
3587
3588template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Evgeniy Stepanova3b25f82015-11-07 01:22:13 +00003589inline
Howard Hinnantd23b4642010-05-31 20:58:54 +00003590wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3591 wstring_convert(_Codecvt* __pcvt, state_type __state)
3592 : __cvtptr_(__pcvt), __cvtstate_(__state), __cvtcount_(0)
3593{
3594}
3595
3596template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3597wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3598 wstring_convert(const byte_string& __byte_err, const wide_string& __wide_err)
3599 : __byte_err_string_(__byte_err), __wide_err_string_(__wide_err),
3600 __cvtstate_(), __cvtcount_(0)
3601{
3602 __cvtptr_ = new _Codecvt;
3603}
3604
Howard Hinnant73d21a42010-09-04 23:28:19 +00003605#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantd23b4642010-05-31 20:58:54 +00003606
3607template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Evgeniy Stepanova3b25f82015-11-07 01:22:13 +00003608inline
Howard Hinnantd23b4642010-05-31 20:58:54 +00003609wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3610 wstring_convert(wstring_convert&& __wc)
Howard Hinnant0949eed2011-06-30 21:18:19 +00003611 : __byte_err_string_(_VSTD::move(__wc.__byte_err_string_)),
3612 __wide_err_string_(_VSTD::move(__wc.__wide_err_string_)),
Howard Hinnantd23b4642010-05-31 20:58:54 +00003613 __cvtptr_(__wc.__cvtptr_),
3614 __cvtstate_(__wc.__cvtstate_), __cvtcount_(__wc.__cvtstate_)
3615{
3616 __wc.__cvtptr_ = nullptr;
3617}
3618
Howard Hinnantbfd55302010-09-04 23:46:48 +00003619#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantd23b4642010-05-31 20:58:54 +00003620
3621template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3622wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::~wstring_convert()
3623{
3624 delete __cvtptr_;
3625}
3626
3627template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3628typename wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::wide_string
3629wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3630 from_bytes(const char* __frm, const char* __frm_end)
3631{
3632 __cvtcount_ = 0;
3633 if (__cvtptr_ != nullptr)
3634 {
3635 wide_string __ws(2*(__frm_end - __frm), _Elem());
Howard Hinnant1ca23672012-07-12 18:07:41 +00003636 if (__frm != __frm_end)
3637 __ws.resize(__ws.capacity());
Howard Hinnantd23b4642010-05-31 20:58:54 +00003638 codecvt_base::result __r = codecvt_base::ok;
3639 state_type __st = __cvtstate_;
3640 if (__frm != __frm_end)
3641 {
3642 _Elem* __to = &__ws[0];
3643 _Elem* __to_end = __to + __ws.size();
3644 const char* __frm_nxt;
3645 do
3646 {
3647 _Elem* __to_nxt;
3648 __r = __cvtptr_->in(__st, __frm, __frm_end, __frm_nxt,
3649 __to, __to_end, __to_nxt);
3650 __cvtcount_ += __frm_nxt - __frm;
3651 if (__frm_nxt == __frm)
3652 {
3653 __r = codecvt_base::error;
3654 }
3655 else if (__r == codecvt_base::noconv)
3656 {
3657 __ws.resize(__to - &__ws[0]);
3658 // This only gets executed if _Elem is char
3659 __ws.append((const _Elem*)__frm, (const _Elem*)__frm_end);
3660 __frm = __frm_nxt;
3661 __r = codecvt_base::ok;
3662 }
3663 else if (__r == codecvt_base::ok)
3664 {
3665 __ws.resize(__to_nxt - &__ws[0]);
3666 __frm = __frm_nxt;
3667 }
3668 else if (__r == codecvt_base::partial)
3669 {
3670 ptrdiff_t __s = __to_nxt - &__ws[0];
3671 __ws.resize(2 * __s);
3672 __to = &__ws[0] + __s;
3673 __to_end = &__ws[0] + __ws.size();
3674 __frm = __frm_nxt;
3675 }
3676 } while (__r == codecvt_base::partial && __frm_nxt < __frm_end);
3677 }
3678 if (__r == codecvt_base::ok)
3679 return __ws;
3680 }
Howard Hinnantd4444702010-08-11 17:04:31 +00003681#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00003682 if (__wide_err_string_.empty())
3683 throw range_error("wstring_convert: from_bytes error");
Howard Hinnant324bb032010-08-22 00:02:43 +00003684#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00003685 return __wide_err_string_;
3686}
3687
3688template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3689typename wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::byte_string
3690wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3691 to_bytes(const _Elem* __frm, const _Elem* __frm_end)
3692{
3693 __cvtcount_ = 0;
3694 if (__cvtptr_ != nullptr)
3695 {
3696 byte_string __bs(2*(__frm_end - __frm), char());
Howard Hinnant1ca23672012-07-12 18:07:41 +00003697 if (__frm != __frm_end)
3698 __bs.resize(__bs.capacity());
Howard Hinnantd23b4642010-05-31 20:58:54 +00003699 codecvt_base::result __r = codecvt_base::ok;
3700 state_type __st = __cvtstate_;
3701 if (__frm != __frm_end)
3702 {
3703 char* __to = &__bs[0];
3704 char* __to_end = __to + __bs.size();
3705 const _Elem* __frm_nxt;
3706 do
3707 {
3708 char* __to_nxt;
3709 __r = __cvtptr_->out(__st, __frm, __frm_end, __frm_nxt,
3710 __to, __to_end, __to_nxt);
3711 __cvtcount_ += __frm_nxt - __frm;
3712 if (__frm_nxt == __frm)
3713 {
3714 __r = codecvt_base::error;
3715 }
3716 else if (__r == codecvt_base::noconv)
3717 {
3718 __bs.resize(__to - &__bs[0]);
3719 // This only gets executed if _Elem is char
3720 __bs.append((const char*)__frm, (const char*)__frm_end);
3721 __frm = __frm_nxt;
3722 __r = codecvt_base::ok;
3723 }
3724 else if (__r == codecvt_base::ok)
3725 {
3726 __bs.resize(__to_nxt - &__bs[0]);
3727 __frm = __frm_nxt;
3728 }
3729 else if (__r == codecvt_base::partial)
3730 {
3731 ptrdiff_t __s = __to_nxt - &__bs[0];
3732 __bs.resize(2 * __s);
3733 __to = &__bs[0] + __s;
3734 __to_end = &__bs[0] + __bs.size();
3735 __frm = __frm_nxt;
3736 }
3737 } while (__r == codecvt_base::partial && __frm_nxt < __frm_end);
3738 }
3739 if (__r == codecvt_base::ok)
3740 {
3741 size_t __s = __bs.size();
3742 __bs.resize(__bs.capacity());
3743 char* __to = &__bs[0] + __s;
3744 char* __to_end = __to + __bs.size();
3745 do
3746 {
3747 char* __to_nxt;
3748 __r = __cvtptr_->unshift(__st, __to, __to_end, __to_nxt);
3749 if (__r == codecvt_base::noconv)
3750 {
3751 __bs.resize(__to - &__bs[0]);
3752 __r = codecvt_base::ok;
3753 }
3754 else if (__r == codecvt_base::ok)
3755 {
3756 __bs.resize(__to_nxt - &__bs[0]);
3757 }
3758 else if (__r == codecvt_base::partial)
3759 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00003760 ptrdiff_t __sp = __to_nxt - &__bs[0];
3761 __bs.resize(2 * __sp);
3762 __to = &__bs[0] + __sp;
Howard Hinnantd23b4642010-05-31 20:58:54 +00003763 __to_end = &__bs[0] + __bs.size();
3764 }
3765 } while (__r == codecvt_base::partial);
3766 if (__r == codecvt_base::ok)
3767 return __bs;
3768 }
3769 }
Howard Hinnantd4444702010-08-11 17:04:31 +00003770#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00003771 if (__byte_err_string_.empty())
3772 throw range_error("wstring_convert: to_bytes error");
Howard Hinnant324bb032010-08-22 00:02:43 +00003773#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd23b4642010-05-31 20:58:54 +00003774 return __byte_err_string_;
3775}
3776
3777template <class _Codecvt, class _Elem = wchar_t, class _Tr = char_traits<_Elem> >
Howard Hinnant0f678bd2013-08-12 18:38:34 +00003778class _LIBCPP_TYPE_VIS_ONLY wbuffer_convert
Howard Hinnantd23b4642010-05-31 20:58:54 +00003779 : public basic_streambuf<_Elem, _Tr>
3780{
3781public:
3782 // types:
3783 typedef _Elem char_type;
3784 typedef _Tr traits_type;
3785 typedef typename traits_type::int_type int_type;
3786 typedef typename traits_type::pos_type pos_type;
3787 typedef typename traits_type::off_type off_type;
3788 typedef typename _Codecvt::state_type state_type;
3789
3790private:
Howard Hinnant4b53f502010-06-01 20:09:18 +00003791 char* __extbuf_;
3792 const char* __extbufnext_;
3793 const char* __extbufend_;
3794 char __extbuf_min_[8];
3795 size_t __ebs_;
3796 char_type* __intbuf_;
3797 size_t __ibs_;
Howard Hinnantd23b4642010-05-31 20:58:54 +00003798 streambuf* __bufptr_;
Howard Hinnant4b53f502010-06-01 20:09:18 +00003799 _Codecvt* __cv_;
3800 state_type __st_;
3801 ios_base::openmode __cm_;
3802 bool __owns_eb_;
3803 bool __owns_ib_;
3804 bool __always_noconv_;
Howard Hinnantd23b4642010-05-31 20:58:54 +00003805
Howard Hinnant4b53f502010-06-01 20:09:18 +00003806 wbuffer_convert(const wbuffer_convert&);
3807 wbuffer_convert& operator=(const wbuffer_convert&);
Howard Hinnantd23b4642010-05-31 20:58:54 +00003808public:
Marshall Clow83179a72013-08-27 20:18:59 +00003809 _LIBCPP_EXPLICIT_AFTER_CXX11 wbuffer_convert(streambuf* __bytebuf = 0,
3810 _Codecvt* __pcvt = new _Codecvt, state_type __state = state_type());
Howard Hinnant4b53f502010-06-01 20:09:18 +00003811 ~wbuffer_convert();
Howard Hinnantd23b4642010-05-31 20:58:54 +00003812
Howard Hinnant82894812010-09-22 16:48:34 +00003813 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantd23b4642010-05-31 20:58:54 +00003814 streambuf* rdbuf() const {return __bufptr_;}
Howard Hinnant82894812010-09-22 16:48:34 +00003815 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantd23b4642010-05-31 20:58:54 +00003816 streambuf* rdbuf(streambuf* __bytebuf)
3817 {
3818 streambuf* __r = __bufptr_;
3819 __bufptr_ = __bytebuf;
3820 return __r;
3821 }
3822
Howard Hinnant82894812010-09-22 16:48:34 +00003823 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant4b53f502010-06-01 20:09:18 +00003824 state_type state() const {return __st_;}
Howard Hinnantd23b4642010-05-31 20:58:54 +00003825
3826protected:
Howard Hinnant4b53f502010-06-01 20:09:18 +00003827 virtual int_type underflow();
3828 virtual int_type pbackfail(int_type __c = traits_type::eof());
Howard Hinnantd23b4642010-05-31 20:58:54 +00003829 virtual int_type overflow (int_type __c = traits_type::eof());
Howard Hinnant4b53f502010-06-01 20:09:18 +00003830 virtual basic_streambuf<char_type, traits_type>* setbuf(char_type* __s,
3831 streamsize __n);
3832 virtual pos_type seekoff(off_type __off, ios_base::seekdir __way,
3833 ios_base::openmode __wch = ios_base::in | ios_base::out);
3834 virtual pos_type seekpos(pos_type __sp,
3835 ios_base::openmode __wch = ios_base::in | ios_base::out);
3836 virtual int sync();
3837
3838private:
3839 bool __read_mode();
3840 void __write_mode();
3841 wbuffer_convert* __close();
Howard Hinnantd23b4642010-05-31 20:58:54 +00003842};
3843
3844template <class _Codecvt, class _Elem, class _Tr>
Howard Hinnant4b53f502010-06-01 20:09:18 +00003845wbuffer_convert<_Codecvt, _Elem, _Tr>::
3846 wbuffer_convert(streambuf* __bytebuf, _Codecvt* __pcvt, state_type __state)
3847 : __extbuf_(0),
3848 __extbufnext_(0),
3849 __extbufend_(0),
3850 __ebs_(0),
3851 __intbuf_(0),
3852 __ibs_(0),
3853 __bufptr_(__bytebuf),
3854 __cv_(__pcvt),
3855 __st_(__state),
3856 __cm_(0),
3857 __owns_eb_(false),
3858 __owns_ib_(false),
3859 __always_noconv_(__cv_ ? __cv_->always_noconv() : false)
3860{
3861 setbuf(0, 4096);
3862}
3863
3864template <class _Codecvt, class _Elem, class _Tr>
3865wbuffer_convert<_Codecvt, _Elem, _Tr>::~wbuffer_convert()
3866{
3867 __close();
3868 delete __cv_;
3869 if (__owns_eb_)
3870 delete [] __extbuf_;
3871 if (__owns_ib_)
3872 delete [] __intbuf_;
3873}
3874
3875template <class _Codecvt, class _Elem, class _Tr>
3876typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
3877wbuffer_convert<_Codecvt, _Elem, _Tr>::underflow()
3878{
3879 if (__cv_ == 0 || __bufptr_ == 0)
3880 return traits_type::eof();
3881 bool __initial = __read_mode();
3882 char_type __1buf;
3883 if (this->gptr() == 0)
3884 this->setg(&__1buf, &__1buf+1, &__1buf+1);
3885 const size_t __unget_sz = __initial ? 0 : min<size_t>((this->egptr() - this->eback()) / 2, 4);
3886 int_type __c = traits_type::eof();
3887 if (this->gptr() == this->egptr())
3888 {
3889 memmove(this->eback(), this->egptr() - __unget_sz, __unget_sz * sizeof(char_type));
3890 if (__always_noconv_)
3891 {
3892 streamsize __nmemb = static_cast<streamsize>(this->egptr() - this->eback() - __unget_sz);
3893 __nmemb = __bufptr_->sgetn((char*)this->eback() + __unget_sz, __nmemb);
3894 if (__nmemb != 0)
3895 {
3896 this->setg(this->eback(),
3897 this->eback() + __unget_sz,
3898 this->eback() + __unget_sz + __nmemb);
3899 __c = *this->gptr();
3900 }
3901 }
3902 else
3903 {
3904 memmove(__extbuf_, __extbufnext_, __extbufend_ - __extbufnext_);
3905 __extbufnext_ = __extbuf_ + (__extbufend_ - __extbufnext_);
3906 __extbufend_ = __extbuf_ + (__extbuf_ == __extbuf_min_ ? sizeof(__extbuf_min_) : __ebs_);
Howard Hinnant0949eed2011-06-30 21:18:19 +00003907 streamsize __nmemb = _VSTD::min(static_cast<streamsize>(this->egptr() - this->eback() - __unget_sz),
Howard Hinnant4b53f502010-06-01 20:09:18 +00003908 static_cast<streamsize>(__extbufend_ - __extbufnext_));
3909 codecvt_base::result __r;
3910 state_type __svs = __st_;
3911 streamsize __nr = __bufptr_->sgetn(const_cast<char*>(__extbufnext_), __nmemb);
3912 if (__nr != 0)
3913 {
3914 __extbufend_ = __extbufnext_ + __nr;
3915 char_type* __inext;
3916 __r = __cv_->in(__st_, __extbuf_, __extbufend_, __extbufnext_,
3917 this->eback() + __unget_sz,
3918 this->egptr(), __inext);
3919 if (__r == codecvt_base::noconv)
3920 {
3921 this->setg((char_type*)__extbuf_, (char_type*)__extbuf_, (char_type*)__extbufend_);
3922 __c = *this->gptr();
3923 }
3924 else if (__inext != this->eback() + __unget_sz)
3925 {
3926 this->setg(this->eback(), this->eback() + __unget_sz, __inext);
3927 __c = *this->gptr();
3928 }
3929 }
3930 }
3931 }
3932 else
3933 __c = *this->gptr();
3934 if (this->eback() == &__1buf)
3935 this->setg(0, 0, 0);
3936 return __c;
3937}
3938
3939template <class _Codecvt, class _Elem, class _Tr>
3940typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
3941wbuffer_convert<_Codecvt, _Elem, _Tr>::pbackfail(int_type __c)
3942{
3943 if (__cv_ != 0 && __bufptr_ != 0 && this->eback() < this->gptr())
3944 {
3945 if (traits_type::eq_int_type(__c, traits_type::eof()))
3946 {
3947 this->gbump(-1);
3948 return traits_type::not_eof(__c);
3949 }
3950 if (traits_type::eq(traits_type::to_char_type(__c), this->gptr()[-1]))
3951 {
3952 this->gbump(-1);
3953 *this->gptr() = traits_type::to_char_type(__c);
3954 return __c;
3955 }
3956 }
3957 return traits_type::eof();
3958}
3959
3960template <class _Codecvt, class _Elem, class _Tr>
Howard Hinnantd23b4642010-05-31 20:58:54 +00003961typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
3962wbuffer_convert<_Codecvt, _Elem, _Tr>::overflow(int_type __c)
3963{
Howard Hinnant4b53f502010-06-01 20:09:18 +00003964 if (__cv_ == 0 || __bufptr_ == 0)
3965 return traits_type::eof();
3966 __write_mode();
3967 char_type __1buf;
3968 char_type* __pb_save = this->pbase();
3969 char_type* __epb_save = this->epptr();
3970 if (!traits_type::eq_int_type(__c, traits_type::eof()))
3971 {
3972 if (this->pptr() == 0)
3973 this->setp(&__1buf, &__1buf+1);
3974 *this->pptr() = traits_type::to_char_type(__c);
3975 this->pbump(1);
3976 }
3977 if (this->pptr() != this->pbase())
3978 {
3979 if (__always_noconv_)
3980 {
3981 streamsize __nmemb = static_cast<streamsize>(this->pptr() - this->pbase());
3982 if (__bufptr_->sputn((const char*)this->pbase(), __nmemb) != __nmemb)
3983 return traits_type::eof();
3984 }
3985 else
3986 {
3987 char* __extbe = __extbuf_;
3988 codecvt_base::result __r;
3989 do
3990 {
3991 const char_type* __e;
3992 __r = __cv_->out(__st_, this->pbase(), this->pptr(), __e,
3993 __extbuf_, __extbuf_ + __ebs_, __extbe);
3994 if (__e == this->pbase())
3995 return traits_type::eof();
3996 if (__r == codecvt_base::noconv)
3997 {
3998 streamsize __nmemb = static_cast<size_t>(this->pptr() - this->pbase());
3999 if (__bufptr_->sputn((const char*)this->pbase(), __nmemb) != __nmemb)
4000 return traits_type::eof();
4001 }
4002 else if (__r == codecvt_base::ok || __r == codecvt_base::partial)
4003 {
4004 streamsize __nmemb = static_cast<size_t>(__extbe - __extbuf_);
4005 if (__bufptr_->sputn(__extbuf_, __nmemb) != __nmemb)
4006 return traits_type::eof();
4007 if (__r == codecvt_base::partial)
4008 {
4009 this->setp((char_type*)__e, this->pptr());
4010 this->pbump(this->epptr() - this->pbase());
4011 }
4012 }
4013 else
4014 return traits_type::eof();
4015 } while (__r == codecvt_base::partial);
4016 }
4017 this->setp(__pb_save, __epb_save);
4018 }
4019 return traits_type::not_eof(__c);
4020}
4021
4022template <class _Codecvt, class _Elem, class _Tr>
4023basic_streambuf<_Elem, _Tr>*
4024wbuffer_convert<_Codecvt, _Elem, _Tr>::setbuf(char_type* __s, streamsize __n)
4025{
4026 this->setg(0, 0, 0);
4027 this->setp(0, 0);
4028 if (__owns_eb_)
4029 delete [] __extbuf_;
4030 if (__owns_ib_)
4031 delete [] __intbuf_;
4032 __ebs_ = __n;
4033 if (__ebs_ > sizeof(__extbuf_min_))
4034 {
4035 if (__always_noconv_ && __s)
4036 {
4037 __extbuf_ = (char*)__s;
4038 __owns_eb_ = false;
4039 }
4040 else
4041 {
4042 __extbuf_ = new char[__ebs_];
4043 __owns_eb_ = true;
4044 }
4045 }
4046 else
4047 {
4048 __extbuf_ = __extbuf_min_;
4049 __ebs_ = sizeof(__extbuf_min_);
4050 __owns_eb_ = false;
4051 }
4052 if (!__always_noconv_)
4053 {
4054 __ibs_ = max<streamsize>(__n, sizeof(__extbuf_min_));
4055 if (__s && __ibs_ >= sizeof(__extbuf_min_))
4056 {
4057 __intbuf_ = __s;
4058 __owns_ib_ = false;
4059 }
4060 else
4061 {
4062 __intbuf_ = new char_type[__ibs_];
4063 __owns_ib_ = true;
4064 }
4065 }
4066 else
4067 {
4068 __ibs_ = 0;
4069 __intbuf_ = 0;
4070 __owns_ib_ = false;
4071 }
4072 return this;
4073}
4074
4075template <class _Codecvt, class _Elem, class _Tr>
4076typename wbuffer_convert<_Codecvt, _Elem, _Tr>::pos_type
4077wbuffer_convert<_Codecvt, _Elem, _Tr>::seekoff(off_type __off, ios_base::seekdir __way,
4078 ios_base::openmode __om)
4079{
4080 int __width = __cv_->encoding();
4081 if (__cv_ == 0 || __bufptr_ == 0 || (__width <= 0 && __off != 0) || sync())
4082 return pos_type(off_type(-1));
Marshall Clow5ea44302015-08-27 14:37:22 +00004083 // __width > 0 || __off == 0, now check __way
4084 if (__way != ios_base::beg && __way != ios_base::cur && __way != ios_base::end)
Howard Hinnant4b53f502010-06-01 20:09:18 +00004085 return pos_type(off_type(-1));
Howard Hinnant4b53f502010-06-01 20:09:18 +00004086 pos_type __r = __bufptr_->pubseekoff(__width * __off, __way, __om);
4087 __r.state(__st_);
4088 return __r;
4089}
4090
4091template <class _Codecvt, class _Elem, class _Tr>
4092typename wbuffer_convert<_Codecvt, _Elem, _Tr>::pos_type
4093wbuffer_convert<_Codecvt, _Elem, _Tr>::seekpos(pos_type __sp, ios_base::openmode __wch)
4094{
4095 if (__cv_ == 0 || __bufptr_ == 0 || sync())
4096 return pos_type(off_type(-1));
4097 if (__bufptr_->pubseekpos(__sp, __wch) == pos_type(off_type(-1)))
4098 return pos_type(off_type(-1));
4099 return __sp;
4100}
4101
4102template <class _Codecvt, class _Elem, class _Tr>
4103int
4104wbuffer_convert<_Codecvt, _Elem, _Tr>::sync()
4105{
4106 if (__cv_ == 0 || __bufptr_ == 0)
4107 return 0;
4108 if (__cm_ & ios_base::out)
4109 {
4110 if (this->pptr() != this->pbase())
4111 if (overflow() == traits_type::eof())
4112 return -1;
4113 codecvt_base::result __r;
4114 do
4115 {
4116 char* __extbe;
4117 __r = __cv_->unshift(__st_, __extbuf_, __extbuf_ + __ebs_, __extbe);
4118 streamsize __nmemb = static_cast<streamsize>(__extbe - __extbuf_);
4119 if (__bufptr_->sputn(__extbuf_, __nmemb) != __nmemb)
4120 return -1;
4121 } while (__r == codecvt_base::partial);
4122 if (__r == codecvt_base::error)
4123 return -1;
4124 if (__bufptr_->pubsync())
4125 return -1;
4126 }
4127 else if (__cm_ & ios_base::in)
4128 {
4129 off_type __c;
4130 if (__always_noconv_)
4131 __c = this->egptr() - this->gptr();
4132 else
4133 {
4134 int __width = __cv_->encoding();
4135 __c = __extbufend_ - __extbufnext_;
4136 if (__width > 0)
4137 __c += __width * (this->egptr() - this->gptr());
4138 else
4139 {
4140 if (this->gptr() != this->egptr())
4141 {
4142 reverse(this->gptr(), this->egptr());
4143 codecvt_base::result __r;
4144 const char_type* __e = this->gptr();
4145 char* __extbe;
4146 do
4147 {
4148 __r = __cv_->out(__st_, __e, this->egptr(), __e,
4149 __extbuf_, __extbuf_ + __ebs_, __extbe);
4150 switch (__r)
4151 {
4152 case codecvt_base::noconv:
4153 __c += this->egptr() - this->gptr();
4154 break;
4155 case codecvt_base::ok:
4156 case codecvt_base::partial:
4157 __c += __extbe - __extbuf_;
4158 break;
4159 default:
4160 return -1;
4161 }
4162 } while (__r == codecvt_base::partial);
4163 }
4164 }
4165 }
4166 if (__bufptr_->pubseekoff(-__c, ios_base::cur, __cm_) == pos_type(off_type(-1)))
4167 return -1;
4168 this->setg(0, 0, 0);
4169 __cm_ = 0;
4170 }
4171 return 0;
4172}
4173
4174template <class _Codecvt, class _Elem, class _Tr>
4175bool
4176wbuffer_convert<_Codecvt, _Elem, _Tr>::__read_mode()
4177{
4178 if (!(__cm_ & ios_base::in))
4179 {
4180 this->setp(0, 0);
4181 if (__always_noconv_)
4182 this->setg((char_type*)__extbuf_,
4183 (char_type*)__extbuf_ + __ebs_,
4184 (char_type*)__extbuf_ + __ebs_);
4185 else
4186 this->setg(__intbuf_, __intbuf_ + __ibs_, __intbuf_ + __ibs_);
4187 __cm_ = ios_base::in;
4188 return true;
4189 }
4190 return false;
4191}
4192
4193template <class _Codecvt, class _Elem, class _Tr>
4194void
4195wbuffer_convert<_Codecvt, _Elem, _Tr>::__write_mode()
4196{
4197 if (!(__cm_ & ios_base::out))
4198 {
4199 this->setg(0, 0, 0);
4200 if (__ebs_ > sizeof(__extbuf_min_))
4201 {
4202 if (__always_noconv_)
4203 this->setp((char_type*)__extbuf_,
4204 (char_type*)__extbuf_ + (__ebs_ - 1));
4205 else
4206 this->setp(__intbuf_, __intbuf_ + (__ibs_ - 1));
4207 }
4208 else
4209 this->setp(0, 0);
4210 __cm_ = ios_base::out;
4211 }
4212}
4213
4214template <class _Codecvt, class _Elem, class _Tr>
4215wbuffer_convert<_Codecvt, _Elem, _Tr>*
4216wbuffer_convert<_Codecvt, _Elem, _Tr>::__close()
4217{
4218 wbuffer_convert* __rt = 0;
4219 if (__cv_ != 0 && __bufptr_ != 0)
4220 {
4221 __rt = this;
4222 if ((__cm_ & ios_base::out) && sync())
4223 __rt = 0;
4224 }
4225 return __rt;
Howard Hinnantd23b4642010-05-31 20:58:54 +00004226}
4227
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004228_LIBCPP_END_NAMESPACE_STD
4229
4230#endif // _LIBCPP_LOCALE