blob: bdedbeae24667c55f4e780980cadde04d587d632 [file] [log] [blame]
Howard Hinnantc51e1022010-05-11 19:42:16 +00001// -*- C++ -*-
2//===-------------------------- locale ------------------------------------===//
3//
Howard Hinnantc566dc32010-05-11 21:36:01 +00004// The LLVM Compiler Infrastructure
Howard Hinnantc51e1022010-05-11 19:42:16 +00005//
Howard Hinnantee11c312010-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 Hinnantc51e1022010-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 Hinnant7c9e5732011-05-31 15:34:58 +000039 locale() noexcept;
40 locale(const locale& other) noexcept;
Howard Hinnantc51e1022010-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 Hinnant7c9e5732011-05-31 15:34:58 +000048 ~locale(); // not virtual
Howard Hinnantc51e1022010-05-11 19:42:16 +000049
Howard Hinnant7c9e5732011-05-31 15:34:58 +000050 const locale& operator=(const locale& other) noexcept;
Howard Hinnantc51e1022010-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 Hinnant7c9e5732011-05-31 15:34:58 +000068template <class Facet> bool has_facet(const locale&) noexcept;
Howard Hinnantc51e1022010-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 Hinnant9dd7e892010-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 Clowccaa0fb2013-08-27 20:18:59 +000096 explicit wstring_convert(Codecvt* pcvt = new Codecvt); // explicit in C++14
Howard Hinnant9dd7e892010-05-31 20:58:54 +000097 wstring_convert(Codecvt* pcvt, state_type state);
Marshall Clowccaa0fb2013-08-27 20:18:59 +000098 explicit wstring_convert(const byte_string& byte_err, // explicit in C++14
Howard Hinnant9dd7e892010-05-31 20:58:54 +000099 const wide_string& wide_err = wide_string());
Marshall Clowccaa0fb2013-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 Hinnant9dd7e892010-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 Clowccaa0fb2013-08-27 20:18:59 +0000114 size_t converted() const; // noexcept in C++14
Howard Hinnant9dd7e892010-05-31 20:58:54 +0000115 state_type state() const;
116};
117
Howard Hinnantc51e1022010-05-11 19:42:16 +0000118template <class Codecvt, class Elem = wchar_t, class Tr = char_traits<Elem>>
Howard Hinnant9dd7e892010-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 Clowccaa0fb2013-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 Hinnant9dd7e892010-05-31 20:58:54 +0000131 streambuf* rdbuf() const;
132 streambuf* rdbuf(streambuf* bytebuf);
133
134 state_type state() const;
135};
Howard Hinnantc51e1022010-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>
Eric Fiselier98e428d2016-06-19 06:58:22 +0000183#include <__debug>
Howard Hinnantc51e1022010-05-11 19:42:16 +0000184#include <algorithm>
185#include <memory>
186#include <ios>
187#include <streambuf>
188#include <iterator>
189#include <limits>
Marshall Clowdde4bfe2013-03-18 17:45:34 +0000190#ifndef __APPLE__
Howard Hinnant155c2af2010-05-24 17:49:41 +0000191#include <cstdarg>
192#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000193#include <cstdlib>
194#include <ctime>
Howard Hinnant8ad70912013-09-17 01:34:47 +0000195#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnantae0f80b2011-09-29 20:33:10 +0000196#include <support/win32/locale_win32.h>
Jonathan Roelofs37058612014-09-19 20:09:12 +0000197#elif defined(_NEWLIB_VERSION)
198// FIXME: replace all the uses of _NEWLIB_VERSION with __NEWLIB__ preceded by an
199// include of <sys/cdefs.h> once https://sourceware.org/ml/newlib-cvs/2014-q3/msg00038.html
200// has had a chance to bake for a bit
201#include <support/newlib/xlocale.h>
Ed Schouten118b6032015-03-11 16:39:36 +0000202#endif
203#ifdef _LIBCPP_HAS_CATOPEN
Howard Hinnantc51e1022010-05-11 19:42:16 +0000204#include <nl_types.h>
Marshall Clow3477ec92014-07-10 15:20:28 +0000205#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000206
Marshall Clowdde4bfe2013-03-18 17:45:34 +0000207#ifdef __APPLE__
Howard Hinnant48fd5d52012-11-14 21:17:15 +0000208#include <Availability.h>
209#endif
210
Ben Craig3756b922016-03-09 15:39:39 +0000211#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
212#include <__bsd_locale_defaults.h>
213#else
214#include <__bsd_locale_fallbacks.h>
215#endif
216
Eric Fiselierf4433a32017-05-31 22:07:49 +0000217#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
218#pragma GCC system_header
219#endif
220
221_LIBCPP_PUSH_MACROS
222#include <__undef_macros>
223
224
Howard Hinnantc51e1022010-05-11 19:42:16 +0000225_LIBCPP_BEGIN_NAMESPACE_STD
226
Marshall Clow82378c02013-03-18 19:34:07 +0000227#if defined(__APPLE__) || defined(__FreeBSD__)
Howard Hinnant1ab52da2011-09-28 21:05:01 +0000228# define _LIBCPP_GET_C_LOCALE 0
Ed Schoutenaa497c82015-03-10 09:35:22 +0000229#elif defined(__CloudABI__) || defined(__NetBSD__)
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000230# define _LIBCPP_GET_C_LOCALE LC_C_LOCALE
Howard Hinnant1ab52da2011-09-28 21:05:01 +0000231#else
232# define _LIBCPP_GET_C_LOCALE __cloc()
Howard Hinnantf312e3e2011-09-28 23:39:33 +0000233 // Get the C locale object
Howard Hinnanta37d3cf2013-08-12 18:38:34 +0000234 _LIBCPP_FUNC_VIS locale_t __cloc();
Howard Hinnantf312e3e2011-09-28 23:39:33 +0000235#define __cloc_defined
Howard Hinnant1ab52da2011-09-28 21:05:01 +0000236#endif
237
Howard Hinnantc51e1022010-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 Tokerb8a95f52014-05-15 11:27:39 +0000250// If on exit __b == __e, eofbit is set in __err. If __case_sensitive is false,
Howard Hinnantc51e1022010-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 Hinnant28b24882011-12-01 20:21:04 +0000265 size_t __nkw = static_cast<size_t>(_VSTD::distance(__kb, __ke));
Howard Hinnantc51e1022010-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 Fiseliera09a3b42014-10-27 19:28:20 +0000283 for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, (void) ++__st)
Howard Hinnantc51e1022010-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 Fiseliera09a3b42014-10-27 19:28:20 +0000309 for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, (void) ++__st)
Howard Hinnantc51e1022010-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 Fiseliera09a3b42014-10-27 19:28:20 +0000343 for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, (void) ++__st)
Howard Hinnantc51e1022010-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 Fiseliera09a3b42014-10-27 19:28:20 +0000358 for (__st = __status; __kb != __ke; ++__kb, (void) ++__st)
Howard Hinnantc51e1022010-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 Hinnanta37d3cf2013-08-12 18:38:34 +0000366struct _LIBCPP_TYPE_VIS __num_get_base
Howard Hinnantc51e1022010-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 Hinnanta37d3cf2013-08-12 18:38:34 +0000374_LIBCPP_FUNC_VIS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000375void __check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
376 ios_base::iostate& __err);
377
Howard Hinnantc51e1022010-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 Hinnantf57b3fc2011-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 Hinnant28b24882011-12-01 20:21:04 +0000431 if (__grouping.size() != 0 && __ct == __thousands_sep)
Howard Hinnantc51e1022010-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 Hinnantf57b3fc2011-03-09 01:03:19 +0000441 if (__f >= 24)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000442 return -1;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000443 switch (__base)
444 {
445 case 8:
446 case 10:
447 if (__f >= __base)
Howard Hinnantf57b3fc2011-03-09 01:03:19 +0000448 return -1;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000449 break;
Howard Hinnantf57b3fc2011-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 Hinnantc51e1022010-05-11 19:42:16 +0000457 return 0;
Howard Hinnantf57b3fc2011-03-09 01:03:19 +0000458 }
459 return -1;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000460 }
Howard Hinnant5d4013d2013-04-15 20:40:06 +0000461 *__a_end++ = __src[__f];
Howard Hinnantc51e1022010-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 Hinnant5132e192012-02-15 19:19:37 +0000497 if (__x == '-' || __x == '+')
498 {
Howard Hinnant21413152013-03-08 19:06:24 +0000499 if (__a_end == __a || (__a_end[-1] & 0x5F) == (__exp & 0x7F))
Howard Hinnant5132e192012-02-15 19:19:37 +0000500 {
501 *__a_end++ = __x;
502 return 0;
503 }
504 return -1;
505 }
Howard Hinnantc51e1022010-05-11 19:42:16 +0000506 if (__x == 'x' || __x == 'X')
507 __exp = 'P';
Howard Hinnant21413152013-03-08 19:06:24 +0000508 else if ((__x & 0x5F) == __exp)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000509 {
Howard Hinnant21413152013-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 Hinnantc51e1022010-05-11 19:42:16 +0000517 }
Howard Hinnant5d4013d2013-04-15 20:40:06 +0000518 *__a_end++ = __x;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000519 if (__f >= 22)
520 return 0;
521 ++__dc;
522 return 0;
523}
524
Eric Fiselier1b57fa82016-09-15 22:27:07 +0000525_LIBCPP_EXTERN_TEMPLATE2(struct _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __num_get<char>)
526_LIBCPP_EXTERN_TEMPLATE2(struct _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __num_get<wchar_t>)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000527
528template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +0000529class _LIBCPP_TEMPLATE_VIS num_get
Howard Hinnantc51e1022010-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 Hinnant756c69b2010-09-22 16:48:34 +0000621 _LIBCPP_ALWAYS_INLINE
Howard Hinnantc51e1022010-05-11 19:42:16 +0000622 ~num_get() {}
623
Marshall Clowae385382013-11-05 14:28:52 +0000624 template <class _Fp>
Shoaib Meenai69c57412017-03-02 03:02:50 +0000625 _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
626 iter_type __do_get_floating_point
Marshall Clowae385382013-11-05 14:28:52 +0000627 (iter_type __b, iter_type __e, ios_base& __iob,
628 ios_base::iostate& __err, _Fp& __v) const;
Marshall Clow96d86d82013-11-07 01:00:50 +0000629
630 template <class _Signed>
Shoaib Meenai69c57412017-03-02 03:02:50 +0000631 _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
632 iter_type __do_get_signed
Marshall Clow96d86d82013-11-07 01:00:50 +0000633 (iter_type __b, iter_type __e, ios_base& __iob,
634 ios_base::iostate& __err, _Signed& __v) const;
635
636 template <class _Unsigned>
Shoaib Meenai69c57412017-03-02 03:02:50 +0000637 _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
638 iter_type __do_get_unsigned
Marshall Clow96d86d82013-11-07 01:00:50 +0000639 (iter_type __b, iter_type __e, ios_base& __iob,
640 ios_base::iostate& __err, _Unsigned& __v) const;
641
642
643 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
644 ios_base::iostate& __err, bool& __v) const;
645
646 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
647 ios_base::iostate& __err, long& __v) const
648 { return this->__do_get_signed ( __b, __e, __iob, __err, __v ); }
649
650 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
651 ios_base::iostate& __err, long long& __v) const
652 { return this->__do_get_signed ( __b, __e, __iob, __err, __v ); }
653
654 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
655 ios_base::iostate& __err, unsigned short& __v) const
656 { return this->__do_get_unsigned ( __b, __e, __iob, __err, __v ); }
657
658 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
659 ios_base::iostate& __err, unsigned int& __v) const
660 { return this->__do_get_unsigned ( __b, __e, __iob, __err, __v ); }
661
662 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
663 ios_base::iostate& __err, unsigned long& __v) const
664 { return this->__do_get_unsigned ( __b, __e, __iob, __err, __v ); }
665
666 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
667 ios_base::iostate& __err, unsigned long long& __v) const
668 { return this->__do_get_unsigned ( __b, __e, __iob, __err, __v ); }
669
670 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
671 ios_base::iostate& __err, float& __v) const
672 { return this->__do_get_floating_point ( __b, __e, __iob, __err, __v ); }
673
674 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
675 ios_base::iostate& __err, double& __v) const
676 { return this->__do_get_floating_point ( __b, __e, __iob, __err, __v ); }
677
678 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
679 ios_base::iostate& __err, long double& __v) const
680 { return this->__do_get_floating_point ( __b, __e, __iob, __err, __v ); }
681
682 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
683 ios_base::iostate& __err, void*& __v) const;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000684};
685
686template <class _CharT, class _InputIterator>
687locale::id
688num_get<_CharT, _InputIterator>::id;
689
690template <class _Tp>
691_Tp
692__num_get_signed_integral(const char* __a, const char* __a_end,
693 ios_base::iostate& __err, int __base)
694{
695 if (__a != __a_end)
696 {
Howard Hinnantca8923c2013-01-22 17:26:08 +0000697 typename remove_reference<decltype(errno)>::type __save_errno = errno;
Howard Hinnant05c71342011-02-25 19:52:41 +0000698 errno = 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000699 char *__p2;
Howard Hinnant1ab52da2011-09-28 21:05:01 +0000700 long long __ll = strtoll_l(__a, &__p2, __base, _LIBCPP_GET_C_LOCALE);
Howard Hinnantca8923c2013-01-22 17:26:08 +0000701 typename remove_reference<decltype(errno)>::type __current_errno = errno;
Howard Hinnant05c71342011-02-25 19:52:41 +0000702 if (__current_errno == 0)
703 errno = __save_errno;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000704 if (__p2 != __a_end)
705 {
706 __err = ios_base::failbit;
707 return 0;
708 }
Howard Hinnant05c71342011-02-25 19:52:41 +0000709 else if (__current_errno == ERANGE ||
710 __ll < numeric_limits<_Tp>::min() ||
711 numeric_limits<_Tp>::max() < __ll)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000712 {
713 __err = ios_base::failbit;
Howard Hinnant05c71342011-02-25 19:52:41 +0000714 if (__ll > 0)
715 return numeric_limits<_Tp>::max();
716 else
717 return numeric_limits<_Tp>::min();
Howard Hinnantc51e1022010-05-11 19:42:16 +0000718 }
719 return static_cast<_Tp>(__ll);
720 }
721 __err = ios_base::failbit;
722 return 0;
723}
724
725template <class _Tp>
726_Tp
727__num_get_unsigned_integral(const char* __a, const char* __a_end,
728 ios_base::iostate& __err, int __base)
729{
730 if (__a != __a_end)
731 {
Howard Hinnant05c71342011-02-25 19:52:41 +0000732 if (*__a == '-')
733 {
734 __err = ios_base::failbit;
735 return 0;
736 }
Howard Hinnantca8923c2013-01-22 17:26:08 +0000737 typename remove_reference<decltype(errno)>::type __save_errno = errno;
Howard Hinnant05c71342011-02-25 19:52:41 +0000738 errno = 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000739 char *__p2;
Howard Hinnant1ab52da2011-09-28 21:05:01 +0000740 unsigned long long __ll = strtoull_l(__a, &__p2, __base, _LIBCPP_GET_C_LOCALE);
Howard Hinnantca8923c2013-01-22 17:26:08 +0000741 typename remove_reference<decltype(errno)>::type __current_errno = errno;
Howard Hinnant05c71342011-02-25 19:52:41 +0000742 if (__current_errno == 0)
743 errno = __save_errno;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000744 if (__p2 != __a_end)
745 {
746 __err = ios_base::failbit;
747 return 0;
748 }
Howard Hinnant05c71342011-02-25 19:52:41 +0000749 else if (__current_errno == ERANGE ||
750 numeric_limits<_Tp>::max() < __ll)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000751 {
752 __err = ios_base::failbit;
753 return numeric_limits<_Tp>::max();
754 }
755 return static_cast<_Tp>(__ll);
756 }
757 __err = ios_base::failbit;
758 return 0;
759}
760
761template <class _Tp>
Eric Fiselier98e428d2016-06-19 06:58:22 +0000762_LIBCPP_INLINE_VISIBILITY
763_Tp __do_strtod(const char* __a, char** __p2);
764
765template <>
766inline _LIBCPP_INLINE_VISIBILITY
767float __do_strtod<float>(const char* __a, char** __p2) {
768 return strtof_l(__a, __p2, _LIBCPP_GET_C_LOCALE);
769}
770
771template <>
772inline _LIBCPP_INLINE_VISIBILITY
773double __do_strtod<double>(const char* __a, char** __p2) {
774 return strtod_l(__a, __p2, _LIBCPP_GET_C_LOCALE);
775}
776
777template <>
778inline _LIBCPP_INLINE_VISIBILITY
779long double __do_strtod<long double>(const char* __a, char** __p2) {
780 return strtold_l(__a, __p2, _LIBCPP_GET_C_LOCALE);
781}
782
783template <class _Tp>
Shoaib Meenai54c6fd62016-12-24 18:05:32 +0000784_LIBCPP_HIDDEN
Howard Hinnantc51e1022010-05-11 19:42:16 +0000785_Tp
786__num_get_float(const char* __a, const char* __a_end, ios_base::iostate& __err)
787{
788 if (__a != __a_end)
789 {
Howard Hinnantc9567812013-04-13 18:19:25 +0000790 typename remove_reference<decltype(errno)>::type __save_errno = errno;
791 errno = 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000792 char *__p2;
Eric Fiselier98e428d2016-06-19 06:58:22 +0000793 _Tp __ld = __do_strtod<_Tp>(__a, &__p2);
Howard Hinnantc9567812013-04-13 18:19:25 +0000794 typename remove_reference<decltype(errno)>::type __current_errno = errno;
795 if (__current_errno == 0)
796 errno = __save_errno;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000797 if (__p2 != __a_end)
798 {
799 __err = ios_base::failbit;
800 return 0;
801 }
Howard Hinnantc9567812013-04-13 18:19:25 +0000802 else if (__current_errno == ERANGE)
803 __err = ios_base::failbit;
Eric Fiselier98e428d2016-06-19 06:58:22 +0000804 return __ld;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000805 }
806 __err = ios_base::failbit;
807 return 0;
808}
809
810template <class _CharT, class _InputIterator>
811_InputIterator
812num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
813 ios_base& __iob,
814 ios_base::iostate& __err,
815 bool& __v) const
816{
817 if ((__iob.flags() & ios_base::boolalpha) == 0)
818 {
819 long __lv = -1;
820 __b = do_get(__b, __e, __iob, __err, __lv);
821 switch (__lv)
822 {
823 case 0:
824 __v = false;
825 break;
826 case 1:
827 __v = true;
828 break;
829 default:
830 __v = true;
831 __err = ios_base::failbit;
832 break;
833 }
834 return __b;
835 }
836 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__iob.getloc());
837 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__iob.getloc());
838 typedef typename numpunct<_CharT>::string_type string_type;
839 const string_type __names[2] = {__np.truename(), __np.falsename()};
840 const string_type* __i = __scan_keyword(__b, __e, __names, __names+2,
841 __ct, __err);
842 __v = __i == __names;
843 return __b;
844}
845
Marshall Clow96d86d82013-11-07 01:00:50 +0000846// signed
847
Howard Hinnantc51e1022010-05-11 19:42:16 +0000848template <class _CharT, class _InputIterator>
Marshall Clow96d86d82013-11-07 01:00:50 +0000849template <class _Signed>
Howard Hinnantc51e1022010-05-11 19:42:16 +0000850_InputIterator
Marshall Clow96d86d82013-11-07 01:00:50 +0000851num_get<_CharT, _InputIterator>::__do_get_signed(iter_type __b, iter_type __e,
Howard Hinnantc51e1022010-05-11 19:42:16 +0000852 ios_base& __iob,
853 ios_base::iostate& __err,
Marshall Clow96d86d82013-11-07 01:00:50 +0000854 _Signed& __v) const
Howard Hinnantc51e1022010-05-11 19:42:16 +0000855{
856 // Stage 1
857 int __base = this->__get_base(__iob);
858 // Stage 2
859 char_type __atoms[26];
860 char_type __thousands_sep;
861 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
Howard Hinnant5d4013d2013-04-15 20:40:06 +0000862 string __buf;
863 __buf.resize(__buf.capacity());
864 char* __a = &__buf[0];
Howard Hinnantc51e1022010-05-11 19:42:16 +0000865 char* __a_end = __a;
866 unsigned __g[__num_get_base::__num_get_buf_sz];
867 unsigned* __g_end = __g;
868 unsigned __dc = 0;
869 for (; __b != __e; ++__b)
Howard Hinnant5d4013d2013-04-15 20:40:06 +0000870 {
Joerg Sonnenberger7a804f62014-02-07 21:14:29 +0000871 if (__a_end == __a + __buf.size())
Howard Hinnant5d4013d2013-04-15 20:40:06 +0000872 {
873 size_t __tmp = __buf.size();
874 __buf.resize(2*__buf.size());
875 __buf.resize(__buf.capacity());
876 __a = &__buf[0];
877 __a_end = __a + __tmp;
878 }
Howard Hinnant3b6579a2010-08-22 00:02:43 +0000879 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantc51e1022010-05-11 19:42:16 +0000880 __thousands_sep, __grouping, __g, __g_end,
881 __atoms))
882 break;
Howard Hinnant5d4013d2013-04-15 20:40:06 +0000883 }
Howard Hinnantc51e1022010-05-11 19:42:16 +0000884 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
885 *__g_end++ = __dc;
886 // Stage 3
Marshall Clow96d86d82013-11-07 01:00:50 +0000887 __v = __num_get_signed_integral<_Signed>(__a, __a_end, __err, __base);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000888 // Digit grouping checked
889 __check_grouping(__grouping, __g, __g_end, __err);
890 // EOF checked
891 if (__b == __e)
892 __err |= ios_base::eofbit;
893 return __b;
894}
895
Marshall Clow96d86d82013-11-07 01:00:50 +0000896// unsigned
Howard Hinnantc51e1022010-05-11 19:42:16 +0000897
898template <class _CharT, class _InputIterator>
Marshall Clow96d86d82013-11-07 01:00:50 +0000899template <class _Unsigned>
Howard Hinnantc51e1022010-05-11 19:42:16 +0000900_InputIterator
Marshall Clow96d86d82013-11-07 01:00:50 +0000901num_get<_CharT, _InputIterator>::__do_get_unsigned(iter_type __b, iter_type __e,
Howard Hinnantc51e1022010-05-11 19:42:16 +0000902 ios_base& __iob,
903 ios_base::iostate& __err,
Marshall Clow96d86d82013-11-07 01:00:50 +0000904 _Unsigned& __v) const
Howard Hinnantc51e1022010-05-11 19:42:16 +0000905{
906 // Stage 1
907 int __base = this->__get_base(__iob);
908 // Stage 2
909 char_type __atoms[26];
910 char_type __thousands_sep;
911 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
Howard Hinnant5d4013d2013-04-15 20:40:06 +0000912 string __buf;
913 __buf.resize(__buf.capacity());
914 char* __a = &__buf[0];
Howard Hinnantc51e1022010-05-11 19:42:16 +0000915 char* __a_end = __a;
916 unsigned __g[__num_get_base::__num_get_buf_sz];
917 unsigned* __g_end = __g;
918 unsigned __dc = 0;
919 for (; __b != __e; ++__b)
Howard Hinnant5d4013d2013-04-15 20:40:06 +0000920 {
Joerg Sonnenberger7a804f62014-02-07 21:14:29 +0000921 if (__a_end == __a + __buf.size())
Howard Hinnant5d4013d2013-04-15 20:40:06 +0000922 {
923 size_t __tmp = __buf.size();
924 __buf.resize(2*__buf.size());
925 __buf.resize(__buf.capacity());
926 __a = &__buf[0];
927 __a_end = __a + __tmp;
928 }
Howard Hinnant3b6579a2010-08-22 00:02:43 +0000929 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantc51e1022010-05-11 19:42:16 +0000930 __thousands_sep, __grouping, __g, __g_end,
931 __atoms))
932 break;
Howard Hinnant5d4013d2013-04-15 20:40:06 +0000933 }
Howard Hinnantc51e1022010-05-11 19:42:16 +0000934 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
935 *__g_end++ = __dc;
936 // Stage 3
Marshall Clow96d86d82013-11-07 01:00:50 +0000937 __v = __num_get_unsigned_integral<_Unsigned>(__a, __a_end, __err, __base);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000938 // Digit grouping checked
939 __check_grouping(__grouping, __g, __g_end, __err);
940 // EOF checked
941 if (__b == __e)
942 __err |= ios_base::eofbit;
943 return __b;
944}
945
Marshall Clowae385382013-11-05 14:28:52 +0000946// floating point
947
Howard Hinnantc51e1022010-05-11 19:42:16 +0000948template <class _CharT, class _InputIterator>
Marshall Clowae385382013-11-05 14:28:52 +0000949template <class _Fp>
Howard Hinnantc51e1022010-05-11 19:42:16 +0000950_InputIterator
Marshall Clowae385382013-11-05 14:28:52 +0000951num_get<_CharT, _InputIterator>::__do_get_floating_point(iter_type __b, iter_type __e,
Howard Hinnantc51e1022010-05-11 19:42:16 +0000952 ios_base& __iob,
953 ios_base::iostate& __err,
Marshall Clowae385382013-11-05 14:28:52 +0000954 _Fp& __v) const
Howard Hinnantc51e1022010-05-11 19:42:16 +0000955{
956 // Stage 1, nothing to do
957 // Stage 2
958 char_type __atoms[32];
959 char_type __decimal_point;
960 char_type __thousands_sep;
Howard Hinnant3b6579a2010-08-22 00:02:43 +0000961 string __grouping = this->__stage2_float_prep(__iob, __atoms,
962 __decimal_point,
Howard Hinnantc51e1022010-05-11 19:42:16 +0000963 __thousands_sep);
Howard Hinnant5d4013d2013-04-15 20:40:06 +0000964 string __buf;
965 __buf.resize(__buf.capacity());
966 char* __a = &__buf[0];
Howard Hinnantc51e1022010-05-11 19:42:16 +0000967 char* __a_end = __a;
968 unsigned __g[__num_get_base::__num_get_buf_sz];
969 unsigned* __g_end = __g;
970 unsigned __dc = 0;
971 bool __in_units = true;
972 char __exp = 'E';
973 for (; __b != __e; ++__b)
Howard Hinnant5d4013d2013-04-15 20:40:06 +0000974 {
Joerg Sonnenberger7a804f62014-02-07 21:14:29 +0000975 if (__a_end == __a + __buf.size())
Howard Hinnant5d4013d2013-04-15 20:40:06 +0000976 {
977 size_t __tmp = __buf.size();
978 __buf.resize(2*__buf.size());
979 __buf.resize(__buf.capacity());
980 __a = &__buf[0];
981 __a_end = __a + __tmp;
982 }
Howard Hinnant3b6579a2010-08-22 00:02:43 +0000983 if (this->__stage2_float_loop(*__b, __in_units, __exp, __a, __a_end,
984 __decimal_point, __thousands_sep,
Howard Hinnantc51e1022010-05-11 19:42:16 +0000985 __grouping, __g, __g_end,
986 __dc, __atoms))
987 break;
Howard Hinnant5d4013d2013-04-15 20:40:06 +0000988 }
Howard Hinnantc51e1022010-05-11 19:42:16 +0000989 if (__grouping.size() != 0 && __in_units && __g_end-__g < __num_get_base::__num_get_buf_sz)
990 *__g_end++ = __dc;
991 // Stage 3
Marshall Clowae385382013-11-05 14:28:52 +0000992 __v = __num_get_float<_Fp>(__a, __a_end, __err);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000993 // Digit grouping checked
994 __check_grouping(__grouping, __g, __g_end, __err);
995 // EOF checked
996 if (__b == __e)
997 __err |= ios_base::eofbit;
998 return __b;
999}
1000
1001template <class _CharT, class _InputIterator>
1002_InputIterator
1003num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1004 ios_base& __iob,
1005 ios_base::iostate& __err,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001006 void*& __v) const
1007{
1008 // Stage 1
1009 int __base = 16;
1010 // Stage 2
1011 char_type __atoms[26];
Howard Hinnant28b24882011-12-01 20:21:04 +00001012 char_type __thousands_sep = 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001013 string __grouping;
1014 use_facet<ctype<_CharT> >(__iob.getloc()).widen(__num_get_base::__src,
1015 __num_get_base::__src + 26, __atoms);
Howard Hinnant5d4013d2013-04-15 20:40:06 +00001016 string __buf;
1017 __buf.resize(__buf.capacity());
1018 char* __a = &__buf[0];
Howard Hinnantc51e1022010-05-11 19:42:16 +00001019 char* __a_end = __a;
1020 unsigned __g[__num_get_base::__num_get_buf_sz];
1021 unsigned* __g_end = __g;
1022 unsigned __dc = 0;
1023 for (; __b != __e; ++__b)
Howard Hinnant5d4013d2013-04-15 20:40:06 +00001024 {
Joerg Sonnenberger7a804f62014-02-07 21:14:29 +00001025 if (__a_end == __a + __buf.size())
Howard Hinnant5d4013d2013-04-15 20:40:06 +00001026 {
1027 size_t __tmp = __buf.size();
1028 __buf.resize(2*__buf.size());
1029 __buf.resize(__buf.capacity());
1030 __a = &__buf[0];
1031 __a_end = __a + __tmp;
1032 }
Howard Hinnant3b6579a2010-08-22 00:02:43 +00001033 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
1034 __thousands_sep, __grouping,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001035 __g, __g_end, __atoms))
1036 break;
Howard Hinnant5d4013d2013-04-15 20:40:06 +00001037 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00001038 // Stage 3
Marshall Clow0db963d2014-05-21 16:02:20 +00001039 __buf.resize(__a_end - __a);
Ben Craig3756b922016-03-09 15:39:39 +00001040 if (__libcpp_sscanf_l(__buf.c_str(), _LIBCPP_GET_C_LOCALE, "%p", &__v) != 1)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001041 __err = ios_base::failbit;
1042 // EOF checked
1043 if (__b == __e)
1044 __err |= ios_base::eofbit;
1045 return __b;
1046}
1047
Eric Fiselier1b57fa82016-09-15 22:27:07 +00001048_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS num_get<char>)
1049_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS num_get<wchar_t>)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001050
Howard Hinnanta37d3cf2013-08-12 18:38:34 +00001051struct _LIBCPP_TYPE_VIS __num_put_base
Howard Hinnantc51e1022010-05-11 19:42:16 +00001052{
1053protected:
1054 static void __format_int(char* __fmt, const char* __len, bool __signd,
1055 ios_base::fmtflags __flags);
1056 static bool __format_float(char* __fmt, const char* __len,
1057 ios_base::fmtflags __flags);
1058 static char* __identify_padding(char* __nb, char* __ne,
1059 const ios_base& __iob);
1060};
1061
1062template <class _CharT>
1063struct __num_put
1064 : protected __num_put_base
1065{
1066 static void __widen_and_group_int(char* __nb, char* __np, char* __ne,
1067 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1068 const locale& __loc);
1069 static void __widen_and_group_float(char* __nb, char* __np, char* __ne,
1070 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1071 const locale& __loc);
1072};
1073
1074template <class _CharT>
1075void
1076__num_put<_CharT>::__widen_and_group_int(char* __nb, char* __np, char* __ne,
1077 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1078 const locale& __loc)
1079{
1080 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> > (__loc);
1081 const numpunct<_CharT>& __npt = use_facet<numpunct<_CharT> >(__loc);
1082 string __grouping = __npt.grouping();
1083 if (__grouping.empty())
1084 {
1085 __ct.widen(__nb, __ne, __ob);
1086 __oe = __ob + (__ne - __nb);
1087 }
1088 else
1089 {
1090 __oe = __ob;
1091 char* __nf = __nb;
1092 if (*__nf == '-' || *__nf == '+')
1093 *__oe++ = __ct.widen(*__nf++);
1094 if (__ne - __nf >= 2 && __nf[0] == '0' && (__nf[1] == 'x' ||
1095 __nf[1] == 'X'))
1096 {
1097 *__oe++ = __ct.widen(*__nf++);
1098 *__oe++ = __ct.widen(*__nf++);
1099 }
1100 reverse(__nf, __ne);
1101 _CharT __thousands_sep = __npt.thousands_sep();
1102 unsigned __dc = 0;
1103 unsigned __dg = 0;
1104 for (char* __p = __nf; __p < __ne; ++__p)
1105 {
1106 if (static_cast<unsigned>(__grouping[__dg]) > 0 &&
1107 __dc == static_cast<unsigned>(__grouping[__dg]))
1108 {
1109 *__oe++ = __thousands_sep;
1110 __dc = 0;
1111 if (__dg < __grouping.size()-1)
1112 ++__dg;
1113 }
1114 *__oe++ = __ct.widen(*__p);
1115 ++__dc;
1116 }
1117 reverse(__ob + (__nf - __nb), __oe);
1118 }
1119 if (__np == __ne)
1120 __op = __oe;
1121 else
1122 __op = __ob + (__np - __nb);
1123}
1124
1125template <class _CharT>
1126void
1127__num_put<_CharT>::__widen_and_group_float(char* __nb, char* __np, char* __ne,
1128 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1129 const locale& __loc)
1130{
1131 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> > (__loc);
1132 const numpunct<_CharT>& __npt = use_facet<numpunct<_CharT> >(__loc);
1133 string __grouping = __npt.grouping();
1134 __oe = __ob;
1135 char* __nf = __nb;
1136 if (*__nf == '-' || *__nf == '+')
1137 *__oe++ = __ct.widen(*__nf++);
1138 char* __ns;
1139 if (__ne - __nf >= 2 && __nf[0] == '0' && (__nf[1] == 'x' ||
1140 __nf[1] == 'X'))
1141 {
1142 *__oe++ = __ct.widen(*__nf++);
1143 *__oe++ = __ct.widen(*__nf++);
1144 for (__ns = __nf; __ns < __ne; ++__ns)
Howard Hinnant1ab52da2011-09-28 21:05:01 +00001145 if (!isxdigit_l(*__ns, _LIBCPP_GET_C_LOCALE))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001146 break;
1147 }
1148 else
1149 {
1150 for (__ns = __nf; __ns < __ne; ++__ns)
Howard Hinnant1ab52da2011-09-28 21:05:01 +00001151 if (!isdigit_l(*__ns, _LIBCPP_GET_C_LOCALE))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001152 break;
1153 }
1154 if (__grouping.empty())
1155 {
1156 __ct.widen(__nf, __ns, __oe);
1157 __oe += __ns - __nf;
1158 }
1159 else
1160 {
1161 reverse(__nf, __ns);
1162 _CharT __thousands_sep = __npt.thousands_sep();
1163 unsigned __dc = 0;
1164 unsigned __dg = 0;
1165 for (char* __p = __nf; __p < __ns; ++__p)
1166 {
1167 if (__grouping[__dg] > 0 && __dc == static_cast<unsigned>(__grouping[__dg]))
1168 {
1169 *__oe++ = __thousands_sep;
1170 __dc = 0;
1171 if (__dg < __grouping.size()-1)
1172 ++__dg;
1173 }
1174 *__oe++ = __ct.widen(*__p);
1175 ++__dc;
1176 }
1177 reverse(__ob + (__nf - __nb), __oe);
1178 }
1179 for (__nf = __ns; __nf < __ne; ++__nf)
1180 {
1181 if (*__nf == '.')
1182 {
1183 *__oe++ = __npt.decimal_point();
1184 ++__nf;
1185 break;
1186 }
1187 else
1188 *__oe++ = __ct.widen(*__nf);
1189 }
1190 __ct.widen(__nf, __ne, __oe);
1191 __oe += __ne - __nf;
1192 if (__np == __ne)
1193 __op = __oe;
1194 else
1195 __op = __ob + (__np - __nb);
1196}
1197
Eric Fiselier1b57fa82016-09-15 22:27:07 +00001198_LIBCPP_EXTERN_TEMPLATE2(struct _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __num_put<char>)
1199_LIBCPP_EXTERN_TEMPLATE2(struct _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __num_put<wchar_t>)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001200
1201template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +00001202class _LIBCPP_TEMPLATE_VIS num_put
Howard Hinnantc51e1022010-05-11 19:42:16 +00001203 : public locale::facet,
1204 private __num_put<_CharT>
1205{
1206public:
1207 typedef _CharT char_type;
1208 typedef _OutputIterator iter_type;
1209
1210 _LIBCPP_ALWAYS_INLINE
1211 explicit num_put(size_t __refs = 0)
1212 : locale::facet(__refs) {}
1213
1214 _LIBCPP_ALWAYS_INLINE
1215 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1216 bool __v) const
1217 {
1218 return do_put(__s, __iob, __fl, __v);
1219 }
1220
1221 _LIBCPP_ALWAYS_INLINE
1222 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1223 long __v) const
1224 {
1225 return do_put(__s, __iob, __fl, __v);
1226 }
1227
1228 _LIBCPP_ALWAYS_INLINE
1229 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1230 long long __v) const
1231 {
1232 return do_put(__s, __iob, __fl, __v);
1233 }
1234
1235 _LIBCPP_ALWAYS_INLINE
1236 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1237 unsigned long __v) const
1238 {
1239 return do_put(__s, __iob, __fl, __v);
1240 }
1241
1242 _LIBCPP_ALWAYS_INLINE
1243 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1244 unsigned long long __v) const
1245 {
1246 return do_put(__s, __iob, __fl, __v);
1247 }
1248
1249 _LIBCPP_ALWAYS_INLINE
1250 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1251 double __v) const
1252 {
1253 return do_put(__s, __iob, __fl, __v);
1254 }
1255
1256 _LIBCPP_ALWAYS_INLINE
1257 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1258 long double __v) const
1259 {
1260 return do_put(__s, __iob, __fl, __v);
1261 }
1262
1263 _LIBCPP_ALWAYS_INLINE
1264 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1265 const void* __v) const
1266 {
1267 return do_put(__s, __iob, __fl, __v);
1268 }
1269
1270 static locale::id id;
1271
1272protected:
Howard Hinnant756c69b2010-09-22 16:48:34 +00001273 _LIBCPP_ALWAYS_INLINE
Howard Hinnantc51e1022010-05-11 19:42:16 +00001274 ~num_put() {}
1275
1276 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1277 bool __v) const;
1278 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1279 long __v) const;
1280 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1281 long long __v) const;
1282 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1283 unsigned long) const;
1284 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1285 unsigned long long) const;
1286 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1287 double __v) const;
1288 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1289 long double __v) const;
1290 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1291 const void* __v) const;
1292};
1293
1294template <class _CharT, class _OutputIterator>
1295locale::id
1296num_put<_CharT, _OutputIterator>::id;
1297
1298template <class _CharT, class _OutputIterator>
1299_LIBCPP_HIDDEN
1300_OutputIterator
1301__pad_and_output(_OutputIterator __s,
1302 const _CharT* __ob, const _CharT* __op, const _CharT* __oe,
1303 ios_base& __iob, _CharT __fl)
1304{
1305 streamsize __sz = __oe - __ob;
1306 streamsize __ns = __iob.width();
1307 if (__ns > __sz)
1308 __ns -= __sz;
1309 else
1310 __ns = 0;
1311 for (;__ob < __op; ++__ob, ++__s)
1312 *__s = *__ob;
1313 for (; __ns; --__ns, ++__s)
1314 *__s = __fl;
1315 for (; __ob < __oe; ++__ob, ++__s)
1316 *__s = *__ob;
1317 __iob.width(0);
1318 return __s;
1319}
1320
Howard Hinnant48fd5d52012-11-14 21:17:15 +00001321#if !defined(__APPLE__) || \
1322 (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED > __MAC_10_8) || \
1323 (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED > __IPHONE_6_0)
1324
Howard Hinnant97955172012-09-19 19:14:15 +00001325template <class _CharT, class _Traits>
1326_LIBCPP_HIDDEN
1327ostreambuf_iterator<_CharT, _Traits>
1328__pad_and_output(ostreambuf_iterator<_CharT, _Traits> __s,
1329 const _CharT* __ob, const _CharT* __op, const _CharT* __oe,
1330 ios_base& __iob, _CharT __fl)
1331{
1332 if (__s.__sbuf_ == nullptr)
1333 return __s;
1334 streamsize __sz = __oe - __ob;
1335 streamsize __ns = __iob.width();
1336 if (__ns > __sz)
1337 __ns -= __sz;
1338 else
1339 __ns = 0;
1340 streamsize __np = __op - __ob;
1341 if (__np > 0)
1342 {
1343 if (__s.__sbuf_->sputn(__ob, __np) != __np)
1344 {
1345 __s.__sbuf_ = nullptr;
1346 return __s;
1347 }
1348 }
1349 if (__ns > 0)
1350 {
1351 basic_string<_CharT, _Traits> __sp(__ns, __fl);
1352 if (__s.__sbuf_->sputn(__sp.data(), __ns) != __ns)
1353 {
1354 __s.__sbuf_ = nullptr;
1355 return __s;
1356 }
1357 }
1358 __np = __oe - __op;
1359 if (__np > 0)
1360 {
1361 if (__s.__sbuf_->sputn(__op, __np) != __np)
1362 {
1363 __s.__sbuf_ = nullptr;
1364 return __s;
1365 }
1366 }
1367 __iob.width(0);
1368 return __s;
1369}
1370
Howard Hinnant48fd5d52012-11-14 21:17:15 +00001371#endif
1372
Howard Hinnantc51e1022010-05-11 19:42:16 +00001373template <class _CharT, class _OutputIterator>
1374_OutputIterator
1375num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1376 char_type __fl, bool __v) const
1377{
1378 if ((__iob.flags() & ios_base::boolalpha) == 0)
1379 return do_put(__s, __iob, __fl, (unsigned long)__v);
1380 const numpunct<char_type>& __np = use_facet<numpunct<char_type> >(__iob.getloc());
1381 typedef typename numpunct<char_type>::string_type string_type;
Howard Hinnant8ea98242013-08-23 17:37:05 +00001382#if _LIBCPP_DEBUG_LEVEL >= 2
1383 string_type __tmp(__v ? __np.truename() : __np.falsename());
1384 string_type __nm = _VSTD::move(__tmp);
1385#else
Howard Hinnantc51e1022010-05-11 19:42:16 +00001386 string_type __nm = __v ? __np.truename() : __np.falsename();
Howard Hinnant8ea98242013-08-23 17:37:05 +00001387#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001388 for (typename string_type::iterator __i = __nm.begin(); __i != __nm.end(); ++__i, ++__s)
1389 *__s = *__i;
1390 return __s;
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 __v) const
1397{
1398 // Stage 1 - Get number in narrow char
1399 char __fmt[6] = {'%', 0};
1400 const char* __len = "l";
1401 this->__format_int(__fmt+1, __len, true, __iob.flags());
1402 const unsigned __nbuf = (numeric_limits<long>::digits / 3)
1403 + ((numeric_limits<long>::digits % 3) != 0)
Dimitry Andriccfb7b5d2017-05-06 20:58:50 +00001404 + ((__iob.flags() & ios_base::showbase) != 0)
Eric Fiselier4cc37352016-04-29 07:23:20 +00001405 + 2;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001406 char __nar[__nbuf];
Ben Craig3756b922016-03-09 15:39:39 +00001407 int __nc = __libcpp_snprintf_l(__nar, sizeof(__nar), _LIBCPP_GET_C_LOCALE, __fmt, __v);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001408 char* __ne = __nar + __nc;
1409 char* __np = this->__identify_padding(__nar, __ne, __iob);
1410 // Stage 2 - Widen __nar while adding thousands separators
1411 char_type __o[2*(__nbuf-1) - 1];
1412 char_type* __op; // pad here
1413 char_type* __oe; // end of output
1414 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1415 // [__o, __oe) contains thousands_sep'd wide number
1416 // Stage 3 & 4
1417 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1418}
1419
1420template <class _CharT, class _OutputIterator>
1421_OutputIterator
1422num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1423 char_type __fl, long long __v) const
1424{
1425 // Stage 1 - Get number in narrow char
1426 char __fmt[8] = {'%', 0};
1427 const char* __len = "ll";
1428 this->__format_int(__fmt+1, __len, true, __iob.flags());
1429 const unsigned __nbuf = (numeric_limits<long long>::digits / 3)
1430 + ((numeric_limits<long long>::digits % 3) != 0)
Dimitry Andriccfb7b5d2017-05-06 20:58:50 +00001431 + ((__iob.flags() & ios_base::showbase) != 0)
Marshall Clow7ac088f2015-01-26 17:24:52 +00001432 + 2;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001433 char __nar[__nbuf];
Ben Craig3756b922016-03-09 15:39:39 +00001434 int __nc = __libcpp_snprintf_l(__nar, sizeof(__nar), _LIBCPP_GET_C_LOCALE, __fmt, __v);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001435 char* __ne = __nar + __nc;
1436 char* __np = this->__identify_padding(__nar, __ne, __iob);
1437 // Stage 2 - Widen __nar while adding thousands separators
1438 char_type __o[2*(__nbuf-1) - 1];
1439 char_type* __op; // pad here
1440 char_type* __oe; // end of output
1441 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1442 // [__o, __oe) contains thousands_sep'd wide number
1443 // Stage 3 & 4
1444 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1445}
1446
1447template <class _CharT, class _OutputIterator>
1448_OutputIterator
1449num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1450 char_type __fl, unsigned long __v) const
1451{
1452 // Stage 1 - Get number in narrow char
1453 char __fmt[6] = {'%', 0};
1454 const char* __len = "l";
1455 this->__format_int(__fmt+1, __len, false, __iob.flags());
1456 const unsigned __nbuf = (numeric_limits<unsigned long>::digits / 3)
1457 + ((numeric_limits<unsigned long>::digits % 3) != 0)
Dimitry Andriccfb7b5d2017-05-06 20:58:50 +00001458 + ((__iob.flags() & ios_base::showbase) != 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001459 + 1;
1460 char __nar[__nbuf];
Ben Craig3756b922016-03-09 15:39:39 +00001461 int __nc = __libcpp_snprintf_l(__nar, sizeof(__nar), _LIBCPP_GET_C_LOCALE, __fmt, __v);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001462 char* __ne = __nar + __nc;
1463 char* __np = this->__identify_padding(__nar, __ne, __iob);
1464 // Stage 2 - Widen __nar while adding thousands separators
1465 char_type __o[2*(__nbuf-1) - 1];
1466 char_type* __op; // pad here
1467 char_type* __oe; // end of output
1468 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1469 // [__o, __oe) contains thousands_sep'd wide number
1470 // Stage 3 & 4
1471 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1472}
1473
1474template <class _CharT, class _OutputIterator>
1475_OutputIterator
1476num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1477 char_type __fl, unsigned long long __v) const
1478{
1479 // Stage 1 - Get number in narrow char
1480 char __fmt[8] = {'%', 0};
1481 const char* __len = "ll";
1482 this->__format_int(__fmt+1, __len, false, __iob.flags());
1483 const unsigned __nbuf = (numeric_limits<unsigned long long>::digits / 3)
1484 + ((numeric_limits<unsigned long long>::digits % 3) != 0)
Dimitry Andriccfb7b5d2017-05-06 20:58:50 +00001485 + ((__iob.flags() & ios_base::showbase) != 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001486 + 1;
1487 char __nar[__nbuf];
Ben Craig3756b922016-03-09 15:39:39 +00001488 int __nc = __libcpp_snprintf_l(__nar, sizeof(__nar), _LIBCPP_GET_C_LOCALE, __fmt, __v);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001489 char* __ne = __nar + __nc;
1490 char* __np = this->__identify_padding(__nar, __ne, __iob);
1491 // Stage 2 - Widen __nar while adding thousands separators
1492 char_type __o[2*(__nbuf-1) - 1];
1493 char_type* __op; // pad here
1494 char_type* __oe; // end of output
1495 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1496 // [__o, __oe) contains thousands_sep'd wide number
1497 // Stage 3 & 4
1498 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1499}
1500
1501template <class _CharT, class _OutputIterator>
1502_OutputIterator
1503num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1504 char_type __fl, double __v) const
1505{
1506 // Stage 1 - Get number in narrow char
1507 char __fmt[8] = {'%', 0};
1508 const char* __len = "";
1509 bool __specify_precision = this->__format_float(__fmt+1, __len, __iob.flags());
1510 const unsigned __nbuf = 30;
1511 char __nar[__nbuf];
1512 char* __nb = __nar;
1513 int __nc;
1514 if (__specify_precision)
Ben Craig3756b922016-03-09 15:39:39 +00001515 __nc = __libcpp_snprintf_l(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt,
Howard Hinnant155c2af2010-05-24 17:49:41 +00001516 (int)__iob.precision(), __v);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001517 else
Ben Craig3756b922016-03-09 15:39:39 +00001518 __nc = __libcpp_snprintf_l(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001519 unique_ptr<char, void(*)(void*)> __nbh(0, free);
1520 if (__nc > static_cast<int>(__nbuf-1))
1521 {
1522 if (__specify_precision)
Ben Craig3756b922016-03-09 15:39:39 +00001523 __nc = __libcpp_asprintf_l(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, (int)__iob.precision(), __v);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001524 else
Ben Craig3756b922016-03-09 15:39:39 +00001525 __nc = __libcpp_asprintf_l(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001526 if (__nb == 0)
1527 __throw_bad_alloc();
1528 __nbh.reset(__nb);
1529 }
1530 char* __ne = __nb + __nc;
1531 char* __np = this->__identify_padding(__nb, __ne, __iob);
1532 // Stage 2 - Widen __nar while adding thousands separators
1533 char_type __o[2*(__nbuf-1) - 1];
1534 char_type* __ob = __o;
1535 unique_ptr<char_type, void(*)(void*)> __obh(0, free);
1536 if (__nb != __nar)
1537 {
Howard Hinnant28b24882011-12-01 20:21:04 +00001538 __ob = (char_type*)malloc(2*static_cast<size_t>(__nc)*sizeof(char_type));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001539 if (__ob == 0)
1540 __throw_bad_alloc();
1541 __obh.reset(__ob);
1542 }
1543 char_type* __op; // pad here
1544 char_type* __oe; // end of output
1545 this->__widen_and_group_float(__nb, __np, __ne, __ob, __op, __oe, __iob.getloc());
1546 // [__o, __oe) contains thousands_sep'd wide number
1547 // Stage 3 & 4
1548 __s = __pad_and_output(__s, __ob, __op, __oe, __iob, __fl);
1549 return __s;
1550}
1551
1552template <class _CharT, class _OutputIterator>
1553_OutputIterator
1554num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1555 char_type __fl, long double __v) const
1556{
1557 // Stage 1 - Get number in narrow char
1558 char __fmt[8] = {'%', 0};
1559 const char* __len = "L";
1560 bool __specify_precision = this->__format_float(__fmt+1, __len, __iob.flags());
1561 const unsigned __nbuf = 30;
1562 char __nar[__nbuf];
1563 char* __nb = __nar;
1564 int __nc;
1565 if (__specify_precision)
Ben Craig3756b922016-03-09 15:39:39 +00001566 __nc = __libcpp_snprintf_l(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt,
Howard Hinnant155c2af2010-05-24 17:49:41 +00001567 (int)__iob.precision(), __v);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001568 else
Ben Craig3756b922016-03-09 15:39:39 +00001569 __nc = __libcpp_snprintf_l(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001570 unique_ptr<char, void(*)(void*)> __nbh(0, free);
1571 if (__nc > static_cast<int>(__nbuf-1))
1572 {
1573 if (__specify_precision)
Ben Craig3756b922016-03-09 15:39:39 +00001574 __nc = __libcpp_asprintf_l(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, (int)__iob.precision(), __v);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001575 else
Ben Craig3756b922016-03-09 15:39:39 +00001576 __nc = __libcpp_asprintf_l(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001577 if (__nb == 0)
1578 __throw_bad_alloc();
1579 __nbh.reset(__nb);
1580 }
1581 char* __ne = __nb + __nc;
1582 char* __np = this->__identify_padding(__nb, __ne, __iob);
1583 // Stage 2 - Widen __nar while adding thousands separators
1584 char_type __o[2*(__nbuf-1) - 1];
1585 char_type* __ob = __o;
1586 unique_ptr<char_type, void(*)(void*)> __obh(0, free);
1587 if (__nb != __nar)
1588 {
Howard Hinnant28b24882011-12-01 20:21:04 +00001589 __ob = (char_type*)malloc(2*static_cast<size_t>(__nc)*sizeof(char_type));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001590 if (__ob == 0)
1591 __throw_bad_alloc();
1592 __obh.reset(__ob);
1593 }
1594 char_type* __op; // pad here
1595 char_type* __oe; // end of output
1596 this->__widen_and_group_float(__nb, __np, __ne, __ob, __op, __oe, __iob.getloc());
1597 // [__o, __oe) contains thousands_sep'd wide number
1598 // Stage 3 & 4
1599 __s = __pad_and_output(__s, __ob, __op, __oe, __iob, __fl);
1600 return __s;
1601}
1602
1603template <class _CharT, class _OutputIterator>
1604_OutputIterator
1605num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1606 char_type __fl, const void* __v) const
1607{
1608 // Stage 1 - Get pointer in narrow char
1609 char __fmt[6] = "%p";
1610 const unsigned __nbuf = 20;
1611 char __nar[__nbuf];
Ben Craig3756b922016-03-09 15:39:39 +00001612 int __nc = __libcpp_snprintf_l(__nar, sizeof(__nar), _LIBCPP_GET_C_LOCALE, __fmt, __v);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001613 char* __ne = __nar + __nc;
1614 char* __np = this->__identify_padding(__nar, __ne, __iob);
1615 // Stage 2 - Widen __nar
1616 char_type __o[2*(__nbuf-1) - 1];
1617 char_type* __op; // pad here
1618 char_type* __oe; // end of output
1619 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
1620 __ct.widen(__nar, __ne, __o);
1621 __oe = __o + (__ne - __nar);
1622 if (__np == __ne)
1623 __op = __oe;
1624 else
1625 __op = __o + (__np - __nar);
1626 // [__o, __oe) contains wide number
1627 // Stage 3 & 4
1628 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1629}
1630
Eric Fiselier1b57fa82016-09-15 22:27:07 +00001631_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS num_put<char>)
1632_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS num_put<wchar_t>)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001633
1634template <class _CharT, class _InputIterator>
1635_LIBCPP_HIDDEN
1636int
1637__get_up_to_n_digits(_InputIterator& __b, _InputIterator __e,
1638 ios_base::iostate& __err, const ctype<_CharT>& __ct, int __n)
1639{
1640 // Precondition: __n >= 1
1641 if (__b == __e)
1642 {
1643 __err |= ios_base::eofbit | ios_base::failbit;
1644 return 0;
1645 }
1646 // get first digit
1647 _CharT __c = *__b;
1648 if (!__ct.is(ctype_base::digit, __c))
1649 {
1650 __err |= ios_base::failbit;
1651 return 0;
1652 }
1653 int __r = __ct.narrow(__c, 0) - '0';
Eric Fiseliera09a3b42014-10-27 19:28:20 +00001654 for (++__b, (void) --__n; __b != __e && __n > 0; ++__b, (void) --__n)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001655 {
1656 // get next digit
1657 __c = *__b;
1658 if (!__ct.is(ctype_base::digit, __c))
1659 return __r;
1660 __r = __r * 10 + __ct.narrow(__c, 0) - '0';
1661 }
1662 if (__b == __e)
1663 __err |= ios_base::eofbit;
1664 return __r;
1665}
1666
Howard Hinnant8331b762013-03-06 23:30:19 +00001667class _LIBCPP_TYPE_VIS time_base
Howard Hinnantc51e1022010-05-11 19:42:16 +00001668{
1669public:
1670 enum dateorder {no_order, dmy, mdy, ymd, ydm};
1671};
1672
1673template <class _CharT>
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +00001674class _LIBCPP_TEMPLATE_VIS __time_get_c_storage
Howard Hinnantc51e1022010-05-11 19:42:16 +00001675{
1676protected:
1677 typedef basic_string<_CharT> string_type;
1678
1679 virtual const string_type* __weeks() const;
1680 virtual const string_type* __months() const;
1681 virtual const string_type* __am_pm() const;
1682 virtual const string_type& __c() const;
1683 virtual const string_type& __r() const;
1684 virtual const string_type& __x() const;
1685 virtual const string_type& __X() const;
Eric Fiselier5eb6efc2015-08-18 19:39:35 +00001686
1687 _LIBCPP_ALWAYS_INLINE
1688 ~__time_get_c_storage() {}
Howard Hinnantc51e1022010-05-11 19:42:16 +00001689};
1690
Eric Fiselierf30c0af2017-05-08 00:29:32 +00001691template <> _LIBCPP_FUNC_VIS const string* __time_get_c_storage<char>::__weeks() const;
1692template <> _LIBCPP_FUNC_VIS const string* __time_get_c_storage<char>::__months() const;
1693template <> _LIBCPP_FUNC_VIS const string* __time_get_c_storage<char>::__am_pm() const;
1694template <> _LIBCPP_FUNC_VIS const string& __time_get_c_storage<char>::__c() const;
1695template <> _LIBCPP_FUNC_VIS const string& __time_get_c_storage<char>::__r() const;
1696template <> _LIBCPP_FUNC_VIS const string& __time_get_c_storage<char>::__x() const;
1697template <> _LIBCPP_FUNC_VIS const string& __time_get_c_storage<char>::__X() const;
1698
1699template <> _LIBCPP_FUNC_VIS const wstring* __time_get_c_storage<wchar_t>::__weeks() const;
1700template <> _LIBCPP_FUNC_VIS const wstring* __time_get_c_storage<wchar_t>::__months() const;
1701template <> _LIBCPP_FUNC_VIS const wstring* __time_get_c_storage<wchar_t>::__am_pm() const;
1702template <> _LIBCPP_FUNC_VIS const wstring& __time_get_c_storage<wchar_t>::__c() const;
1703template <> _LIBCPP_FUNC_VIS const wstring& __time_get_c_storage<wchar_t>::__r() const;
1704template <> _LIBCPP_FUNC_VIS const wstring& __time_get_c_storage<wchar_t>::__x() const;
1705template <> _LIBCPP_FUNC_VIS const wstring& __time_get_c_storage<wchar_t>::__X() const;
1706
Howard Hinnantc51e1022010-05-11 19:42:16 +00001707template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +00001708class _LIBCPP_TEMPLATE_VIS time_get
Howard Hinnantc51e1022010-05-11 19:42:16 +00001709 : public locale::facet,
1710 public time_base,
1711 private __time_get_c_storage<_CharT>
1712{
1713public:
1714 typedef _CharT char_type;
1715 typedef _InputIterator iter_type;
1716 typedef time_base::dateorder dateorder;
1717 typedef basic_string<char_type> string_type;
1718
1719 _LIBCPP_ALWAYS_INLINE
1720 explicit time_get(size_t __refs = 0)
1721 : locale::facet(__refs) {}
1722
1723 _LIBCPP_ALWAYS_INLINE
1724 dateorder date_order() const
1725 {
1726 return this->do_date_order();
1727 }
1728
1729 _LIBCPP_ALWAYS_INLINE
1730 iter_type get_time(iter_type __b, iter_type __e, ios_base& __iob,
1731 ios_base::iostate& __err, tm* __tm) const
1732 {
1733 return do_get_time(__b, __e, __iob, __err, __tm);
1734 }
1735
1736 _LIBCPP_ALWAYS_INLINE
1737 iter_type get_date(iter_type __b, iter_type __e, ios_base& __iob,
1738 ios_base::iostate& __err, tm* __tm) const
1739 {
1740 return do_get_date(__b, __e, __iob, __err, __tm);
1741 }
1742
1743 _LIBCPP_ALWAYS_INLINE
1744 iter_type get_weekday(iter_type __b, iter_type __e, ios_base& __iob,
1745 ios_base::iostate& __err, tm* __tm) const
1746 {
1747 return do_get_weekday(__b, __e, __iob, __err, __tm);
1748 }
1749
1750 _LIBCPP_ALWAYS_INLINE
1751 iter_type get_monthname(iter_type __b, iter_type __e, ios_base& __iob,
1752 ios_base::iostate& __err, tm* __tm) const
1753 {
1754 return do_get_monthname(__b, __e, __iob, __err, __tm);
1755 }
1756
1757 _LIBCPP_ALWAYS_INLINE
1758 iter_type get_year(iter_type __b, iter_type __e, ios_base& __iob,
1759 ios_base::iostate& __err, tm* __tm) const
1760 {
1761 return do_get_year(__b, __e, __iob, __err, __tm);
1762 }
1763
1764 _LIBCPP_ALWAYS_INLINE
1765 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
1766 ios_base::iostate& __err, tm *__tm,
1767 char __fmt, char __mod = 0) const
1768 {
1769 return do_get(__b, __e, __iob, __err, __tm, __fmt, __mod);
1770 }
1771
1772 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
1773 ios_base::iostate& __err, tm* __tm,
1774 const char_type* __fmtb, const char_type* __fmte) const;
1775
1776 static locale::id id;
1777
1778protected:
Howard Hinnant756c69b2010-09-22 16:48:34 +00001779 _LIBCPP_ALWAYS_INLINE
Howard Hinnantc51e1022010-05-11 19:42:16 +00001780 ~time_get() {}
1781
1782 virtual dateorder do_date_order() const;
1783 virtual iter_type do_get_time(iter_type __b, iter_type __e, ios_base& __iob,
1784 ios_base::iostate& __err, tm* __tm) const;
1785 virtual iter_type do_get_date(iter_type __b, iter_type __e, ios_base& __iob,
1786 ios_base::iostate& __err, tm* __tm) const;
1787 virtual iter_type do_get_weekday(iter_type __b, iter_type __e, ios_base& __iob,
1788 ios_base::iostate& __err, tm* __tm) const;
1789 virtual iter_type do_get_monthname(iter_type __b, iter_type __e, ios_base& __iob,
1790 ios_base::iostate& __err, tm* __tm) const;
1791 virtual iter_type do_get_year(iter_type __b, iter_type __e, ios_base& __iob,
1792 ios_base::iostate& __err, tm* __tm) const;
1793 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
1794 ios_base::iostate& __err, tm* __tm,
1795 char __fmt, char __mod) const;
1796private:
1797 void __get_white_space(iter_type& __b, iter_type __e,
1798 ios_base::iostate& __err, const ctype<char_type>& __ct) const;
1799 void __get_percent(iter_type& __b, iter_type __e, ios_base::iostate& __err,
1800 const ctype<char_type>& __ct) const;
1801
1802 void __get_weekdayname(int& __m,
1803 iter_type& __b, iter_type __e,
1804 ios_base::iostate& __err,
1805 const ctype<char_type>& __ct) const;
1806 void __get_monthname(int& __m,
1807 iter_type& __b, iter_type __e,
1808 ios_base::iostate& __err,
1809 const ctype<char_type>& __ct) const;
1810 void __get_day(int& __d,
1811 iter_type& __b, iter_type __e,
1812 ios_base::iostate& __err,
1813 const ctype<char_type>& __ct) const;
1814 void __get_month(int& __m,
1815 iter_type& __b, iter_type __e,
1816 ios_base::iostate& __err,
1817 const ctype<char_type>& __ct) const;
1818 void __get_year(int& __y,
1819 iter_type& __b, iter_type __e,
1820 ios_base::iostate& __err,
1821 const ctype<char_type>& __ct) const;
1822 void __get_year4(int& __y,
1823 iter_type& __b, iter_type __e,
1824 ios_base::iostate& __err,
1825 const ctype<char_type>& __ct) const;
1826 void __get_hour(int& __d,
1827 iter_type& __b, iter_type __e,
1828 ios_base::iostate& __err,
1829 const ctype<char_type>& __ct) const;
1830 void __get_12_hour(int& __h,
1831 iter_type& __b, iter_type __e,
1832 ios_base::iostate& __err,
1833 const ctype<char_type>& __ct) const;
1834 void __get_am_pm(int& __h,
1835 iter_type& __b, iter_type __e,
1836 ios_base::iostate& __err,
1837 const ctype<char_type>& __ct) const;
1838 void __get_minute(int& __m,
1839 iter_type& __b, iter_type __e,
1840 ios_base::iostate& __err,
1841 const ctype<char_type>& __ct) const;
1842 void __get_second(int& __s,
1843 iter_type& __b, iter_type __e,
1844 ios_base::iostate& __err,
1845 const ctype<char_type>& __ct) const;
1846 void __get_weekday(int& __w,
1847 iter_type& __b, iter_type __e,
1848 ios_base::iostate& __err,
1849 const ctype<char_type>& __ct) const;
1850 void __get_day_year_num(int& __w,
1851 iter_type& __b, iter_type __e,
1852 ios_base::iostate& __err,
1853 const ctype<char_type>& __ct) const;
1854};
1855
1856template <class _CharT, class _InputIterator>
1857locale::id
1858time_get<_CharT, _InputIterator>::id;
1859
Alp Tokerb8a95f52014-05-15 11:27:39 +00001860// time_get primitives
Howard Hinnantc51e1022010-05-11 19:42:16 +00001861
1862template <class _CharT, class _InputIterator>
1863void
1864time_get<_CharT, _InputIterator>::__get_weekdayname(int& __w,
1865 iter_type& __b, iter_type __e,
1866 ios_base::iostate& __err,
1867 const ctype<char_type>& __ct) const
1868{
1869 // Note: ignoring case comes from the POSIX strptime spec
1870 const string_type* __wk = this->__weeks();
Howard Hinnant28b24882011-12-01 20:21:04 +00001871 ptrdiff_t __i = __scan_keyword(__b, __e, __wk, __wk+14, __ct, __err, false) - __wk;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001872 if (__i < 14)
1873 __w = __i % 7;
1874}
1875
1876template <class _CharT, class _InputIterator>
1877void
1878time_get<_CharT, _InputIterator>::__get_monthname(int& __m,
1879 iter_type& __b, iter_type __e,
1880 ios_base::iostate& __err,
1881 const ctype<char_type>& __ct) const
1882{
1883 // Note: ignoring case comes from the POSIX strptime spec
1884 const string_type* __month = this->__months();
Howard Hinnant28b24882011-12-01 20:21:04 +00001885 ptrdiff_t __i = __scan_keyword(__b, __e, __month, __month+24, __ct, __err, false) - __month;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001886 if (__i < 24)
1887 __m = __i % 12;
1888}
1889
1890template <class _CharT, class _InputIterator>
1891void
1892time_get<_CharT, _InputIterator>::__get_day(int& __d,
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, 2);
1898 if (!(__err & ios_base::failbit) && 1 <= __t && __t <= 31)
1899 __d = __t;
1900 else
1901 __err |= ios_base::failbit;
1902}
1903
1904template <class _CharT, class _InputIterator>
1905void
1906time_get<_CharT, _InputIterator>::__get_month(int& __m,
1907 iter_type& __b, iter_type __e,
1908 ios_base::iostate& __err,
1909 const ctype<char_type>& __ct) const
1910{
1911 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2) - 1;
1912 if (!(__err & ios_base::failbit) && __t <= 11)
1913 __m = __t;
1914 else
1915 __err |= ios_base::failbit;
1916}
1917
1918template <class _CharT, class _InputIterator>
1919void
1920time_get<_CharT, _InputIterator>::__get_year(int& __y,
1921 iter_type& __b, iter_type __e,
1922 ios_base::iostate& __err,
1923 const ctype<char_type>& __ct) const
1924{
1925 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 4);
1926 if (!(__err & ios_base::failbit))
1927 {
1928 if (__t < 69)
1929 __t += 2000;
1930 else if (69 <= __t && __t <= 99)
1931 __t += 1900;
1932 __y = __t - 1900;
1933 }
1934}
1935
1936template <class _CharT, class _InputIterator>
1937void
1938time_get<_CharT, _InputIterator>::__get_year4(int& __y,
1939 iter_type& __b, iter_type __e,
1940 ios_base::iostate& __err,
1941 const ctype<char_type>& __ct) const
1942{
1943 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 4);
1944 if (!(__err & ios_base::failbit))
1945 __y = __t - 1900;
1946}
1947
1948template <class _CharT, class _InputIterator>
1949void
1950time_get<_CharT, _InputIterator>::__get_hour(int& __h,
1951 iter_type& __b, iter_type __e,
1952 ios_base::iostate& __err,
1953 const ctype<char_type>& __ct) const
1954{
1955 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
1956 if (!(__err & ios_base::failbit) && __t <= 23)
1957 __h = __t;
1958 else
1959 __err |= ios_base::failbit;
1960}
1961
1962template <class _CharT, class _InputIterator>
1963void
1964time_get<_CharT, _InputIterator>::__get_12_hour(int& __h,
1965 iter_type& __b, iter_type __e,
1966 ios_base::iostate& __err,
1967 const ctype<char_type>& __ct) const
1968{
1969 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
1970 if (!(__err & ios_base::failbit) && 1 <= __t && __t <= 12)
1971 __h = __t;
1972 else
1973 __err |= ios_base::failbit;
1974}
1975
1976template <class _CharT, class _InputIterator>
1977void
1978time_get<_CharT, _InputIterator>::__get_minute(int& __m,
1979 iter_type& __b, iter_type __e,
1980 ios_base::iostate& __err,
1981 const ctype<char_type>& __ct) const
1982{
1983 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
1984 if (!(__err & ios_base::failbit) && __t <= 59)
1985 __m = __t;
1986 else
1987 __err |= ios_base::failbit;
1988}
1989
1990template <class _CharT, class _InputIterator>
1991void
1992time_get<_CharT, _InputIterator>::__get_second(int& __s,
1993 iter_type& __b, iter_type __e,
1994 ios_base::iostate& __err,
1995 const ctype<char_type>& __ct) const
1996{
1997 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
1998 if (!(__err & ios_base::failbit) && __t <= 60)
1999 __s = __t;
2000 else
2001 __err |= ios_base::failbit;
2002}
2003
2004template <class _CharT, class _InputIterator>
2005void
2006time_get<_CharT, _InputIterator>::__get_weekday(int& __w,
2007 iter_type& __b, iter_type __e,
2008 ios_base::iostate& __err,
2009 const ctype<char_type>& __ct) const
2010{
2011 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 1);
2012 if (!(__err & ios_base::failbit) && __t <= 6)
2013 __w = __t;
2014 else
2015 __err |= ios_base::failbit;
2016}
2017
2018template <class _CharT, class _InputIterator>
2019void
2020time_get<_CharT, _InputIterator>::__get_day_year_num(int& __d,
2021 iter_type& __b, iter_type __e,
2022 ios_base::iostate& __err,
2023 const ctype<char_type>& __ct) const
2024{
2025 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 3);
2026 if (!(__err & ios_base::failbit) && __t <= 365)
2027 __d = __t;
2028 else
2029 __err |= ios_base::failbit;
2030}
2031
2032template <class _CharT, class _InputIterator>
2033void
2034time_get<_CharT, _InputIterator>::__get_white_space(iter_type& __b, iter_type __e,
2035 ios_base::iostate& __err,
2036 const ctype<char_type>& __ct) const
2037{
2038 for (; __b != __e && __ct.is(ctype_base::space, *__b); ++__b)
2039 ;
2040 if (__b == __e)
2041 __err |= ios_base::eofbit;
2042}
2043
2044template <class _CharT, class _InputIterator>
2045void
2046time_get<_CharT, _InputIterator>::__get_am_pm(int& __h,
2047 iter_type& __b, iter_type __e,
2048 ios_base::iostate& __err,
2049 const ctype<char_type>& __ct) const
2050{
2051 const string_type* __ap = this->__am_pm();
2052 if (__ap[0].size() + __ap[1].size() == 0)
2053 {
2054 __err |= ios_base::failbit;
2055 return;
2056 }
Howard Hinnant28b24882011-12-01 20:21:04 +00002057 ptrdiff_t __i = __scan_keyword(__b, __e, __ap, __ap+2, __ct, __err, false) - __ap;
Howard Hinnantc51e1022010-05-11 19:42:16 +00002058 if (__i == 0 && __h == 12)
2059 __h = 0;
2060 else if (__i == 1 && __h < 12)
2061 __h += 12;
2062}
2063
2064template <class _CharT, class _InputIterator>
2065void
2066time_get<_CharT, _InputIterator>::__get_percent(iter_type& __b, iter_type __e,
2067 ios_base::iostate& __err,
2068 const ctype<char_type>& __ct) const
2069{
2070 if (__b == __e)
2071 {
2072 __err |= ios_base::eofbit | ios_base::failbit;
2073 return;
2074 }
2075 if (__ct.narrow(*__b, 0) != '%')
2076 __err |= ios_base::failbit;
2077 else if(++__b == __e)
2078 __err |= ios_base::eofbit;
2079}
2080
Alp Tokerb8a95f52014-05-15 11:27:39 +00002081// time_get end primitives
Howard Hinnantc51e1022010-05-11 19:42:16 +00002082
2083template <class _CharT, class _InputIterator>
2084_InputIterator
2085time_get<_CharT, _InputIterator>::get(iter_type __b, iter_type __e,
2086 ios_base& __iob,
2087 ios_base::iostate& __err, tm* __tm,
2088 const char_type* __fmtb, const char_type* __fmte) const
2089{
2090 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2091 __err = ios_base::goodbit;
2092 while (__fmtb != __fmte && __err == ios_base::goodbit)
2093 {
2094 if (__b == __e)
2095 {
2096 __err = ios_base::failbit;
2097 break;
2098 }
2099 if (__ct.narrow(*__fmtb, 0) == '%')
2100 {
2101 if (++__fmtb == __fmte)
2102 {
2103 __err = ios_base::failbit;
2104 break;
2105 }
2106 char __cmd = __ct.narrow(*__fmtb, 0);
2107 char __opt = '\0';
2108 if (__cmd == 'E' || __cmd == '0')
2109 {
2110 if (++__fmtb == __fmte)
2111 {
2112 __err = ios_base::failbit;
2113 break;
2114 }
2115 __opt = __cmd;
2116 __cmd = __ct.narrow(*__fmtb, 0);
2117 }
2118 __b = do_get(__b, __e, __iob, __err, __tm, __cmd, __opt);
2119 ++__fmtb;
2120 }
2121 else if (__ct.is(ctype_base::space, *__fmtb))
2122 {
2123 for (++__fmtb; __fmtb != __fmte && __ct.is(ctype_base::space, *__fmtb); ++__fmtb)
2124 ;
2125 for ( ; __b != __e && __ct.is(ctype_base::space, *__b); ++__b)
2126 ;
2127 }
2128 else if (__ct.toupper(*__b) == __ct.toupper(*__fmtb))
2129 {
2130 ++__b;
2131 ++__fmtb;
2132 }
2133 else
2134 __err = ios_base::failbit;
2135 }
2136 if (__b == __e)
2137 __err |= ios_base::eofbit;
2138 return __b;
2139}
2140
2141template <class _CharT, class _InputIterator>
2142typename time_get<_CharT, _InputIterator>::dateorder
2143time_get<_CharT, _InputIterator>::do_date_order() const
2144{
2145 return mdy;
2146}
2147
2148template <class _CharT, class _InputIterator>
2149_InputIterator
2150time_get<_CharT, _InputIterator>::do_get_time(iter_type __b, iter_type __e,
2151 ios_base& __iob,
2152 ios_base::iostate& __err,
2153 tm* __tm) const
2154{
2155 const char_type __fmt[] = {'%', 'H', ':', '%', 'M', ':', '%', 'S'};
2156 return get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2157}
2158
2159template <class _CharT, class _InputIterator>
2160_InputIterator
2161time_get<_CharT, _InputIterator>::do_get_date(iter_type __b, iter_type __e,
2162 ios_base& __iob,
2163 ios_base::iostate& __err,
2164 tm* __tm) const
2165{
Howard Hinnantc51e1022010-05-11 19:42:16 +00002166 const string_type& __fmt = this->__x();
2167 return get(__b, __e, __iob, __err, __tm, __fmt.data(), __fmt.data() + __fmt.size());
2168}
2169
2170template <class _CharT, class _InputIterator>
2171_InputIterator
2172time_get<_CharT, _InputIterator>::do_get_weekday(iter_type __b, iter_type __e,
2173 ios_base& __iob,
2174 ios_base::iostate& __err,
2175 tm* __tm) const
2176{
2177 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2178 __get_weekdayname(__tm->tm_wday, __b, __e, __err, __ct);
2179 return __b;
2180}
2181
2182template <class _CharT, class _InputIterator>
2183_InputIterator
2184time_get<_CharT, _InputIterator>::do_get_monthname(iter_type __b, iter_type __e,
2185 ios_base& __iob,
2186 ios_base::iostate& __err,
2187 tm* __tm) const
2188{
2189 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2190 __get_monthname(__tm->tm_mon, __b, __e, __err, __ct);
2191 return __b;
2192}
2193
2194template <class _CharT, class _InputIterator>
2195_InputIterator
2196time_get<_CharT, _InputIterator>::do_get_year(iter_type __b, iter_type __e,
2197 ios_base& __iob,
2198 ios_base::iostate& __err,
2199 tm* __tm) const
2200{
2201 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2202 __get_year(__tm->tm_year, __b, __e, __err, __ct);
2203 return __b;
2204}
2205
2206template <class _CharT, class _InputIterator>
2207_InputIterator
2208time_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
2209 ios_base& __iob,
2210 ios_base::iostate& __err, tm* __tm,
2211 char __fmt, char) const
2212{
2213 __err = ios_base::goodbit;
2214 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2215 switch (__fmt)
2216 {
2217 case 'a':
2218 case 'A':
2219 __get_weekdayname(__tm->tm_wday, __b, __e, __err, __ct);
2220 break;
2221 case 'b':
2222 case 'B':
2223 case 'h':
2224 __get_monthname(__tm->tm_mon, __b, __e, __err, __ct);
2225 break;
2226 case 'c':
2227 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002228 const string_type& __fm = this->__c();
2229 __b = get(__b, __e, __iob, __err, __tm, __fm.data(), __fm.data() + __fm.size());
Howard Hinnantc51e1022010-05-11 19:42:16 +00002230 }
2231 break;
2232 case 'd':
2233 case 'e':
2234 __get_day(__tm->tm_mday, __b, __e, __err, __ct);
2235 break;
2236 case 'D':
2237 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002238 const char_type __fm[] = {'%', 'm', '/', '%', 'd', '/', '%', 'y'};
2239 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm)/sizeof(__fm[0]));
Howard Hinnantc51e1022010-05-11 19:42:16 +00002240 }
2241 break;
Howard Hinnantf60ff4e2011-04-10 17:54:14 +00002242 case 'F':
2243 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002244 const char_type __fm[] = {'%', 'Y', '-', '%', 'm', '-', '%', 'd'};
2245 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm)/sizeof(__fm[0]));
Howard Hinnantf60ff4e2011-04-10 17:54:14 +00002246 }
2247 break;
Howard Hinnantc51e1022010-05-11 19:42:16 +00002248 case 'H':
2249 __get_hour(__tm->tm_hour, __b, __e, __err, __ct);
2250 break;
2251 case 'I':
2252 __get_12_hour(__tm->tm_hour, __b, __e, __err, __ct);
2253 break;
2254 case 'j':
2255 __get_day_year_num(__tm->tm_yday, __b, __e, __err, __ct);
2256 break;
2257 case 'm':
2258 __get_month(__tm->tm_mon, __b, __e, __err, __ct);
2259 break;
2260 case 'M':
2261 __get_minute(__tm->tm_min, __b, __e, __err, __ct);
2262 break;
2263 case 'n':
2264 case 't':
2265 __get_white_space(__b, __e, __err, __ct);
2266 break;
2267 case 'p':
2268 __get_am_pm(__tm->tm_hour, __b, __e, __err, __ct);
2269 break;
2270 case 'r':
2271 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002272 const char_type __fm[] = {'%', 'I', ':', '%', 'M', ':', '%', 'S', ' ', '%', 'p'};
2273 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm)/sizeof(__fm[0]));
Howard Hinnantc51e1022010-05-11 19:42:16 +00002274 }
2275 break;
2276 case 'R':
2277 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002278 const char_type __fm[] = {'%', 'H', ':', '%', 'M'};
2279 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm)/sizeof(__fm[0]));
Howard Hinnantc51e1022010-05-11 19:42:16 +00002280 }
2281 break;
2282 case 'S':
2283 __get_second(__tm->tm_sec, __b, __e, __err, __ct);
2284 break;
2285 case 'T':
2286 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002287 const char_type __fm[] = {'%', 'H', ':', '%', 'M', ':', '%', 'S'};
2288 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm)/sizeof(__fm[0]));
Howard Hinnantc51e1022010-05-11 19:42:16 +00002289 }
2290 break;
2291 case 'w':
2292 __get_weekday(__tm->tm_wday, __b, __e, __err, __ct);
2293 break;
2294 case 'x':
2295 return do_get_date(__b, __e, __iob, __err, __tm);
2296 case 'X':
2297 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002298 const string_type& __fm = this->__X();
2299 __b = get(__b, __e, __iob, __err, __tm, __fm.data(), __fm.data() + __fm.size());
Howard Hinnantc51e1022010-05-11 19:42:16 +00002300 }
2301 break;
2302 case 'y':
2303 __get_year(__tm->tm_year, __b, __e, __err, __ct);
2304 break;
2305 case 'Y':
2306 __get_year4(__tm->tm_year, __b, __e, __err, __ct);
2307 break;
2308 case '%':
2309 __get_percent(__b, __e, __err, __ct);
2310 break;
2311 default:
2312 __err |= ios_base::failbit;
2313 }
2314 return __b;
2315}
2316
Eric Fiselier1b57fa82016-09-15 22:27:07 +00002317_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_get<char>)
2318_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_get<wchar_t>)
Howard Hinnantc51e1022010-05-11 19:42:16 +00002319
Howard Hinnanta37d3cf2013-08-12 18:38:34 +00002320class _LIBCPP_TYPE_VIS __time_get
Howard Hinnantc51e1022010-05-11 19:42:16 +00002321{
2322protected:
2323 locale_t __loc_;
2324
2325 __time_get(const char* __nm);
2326 __time_get(const string& __nm);
2327 ~__time_get();
2328};
2329
2330template <class _CharT>
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +00002331class _LIBCPP_TEMPLATE_VIS __time_get_storage
Howard Hinnantc51e1022010-05-11 19:42:16 +00002332 : public __time_get
2333{
2334protected:
2335 typedef basic_string<_CharT> string_type;
2336
2337 string_type __weeks_[14];
2338 string_type __months_[24];
2339 string_type __am_pm_[2];
2340 string_type __c_;
2341 string_type __r_;
2342 string_type __x_;
2343 string_type __X_;
2344
2345 explicit __time_get_storage(const char* __nm);
2346 explicit __time_get_storage(const string& __nm);
2347
2348 _LIBCPP_ALWAYS_INLINE ~__time_get_storage() {}
2349
2350 time_base::dateorder __do_date_order() const;
2351
2352private:
2353 void init(const ctype<_CharT>&);
2354 string_type __analyze(char __fmt, const ctype<_CharT>&);
2355};
2356
2357template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +00002358class _LIBCPP_TEMPLATE_VIS time_get_byname
Howard Hinnantc51e1022010-05-11 19:42:16 +00002359 : public time_get<_CharT, _InputIterator>,
2360 private __time_get_storage<_CharT>
2361{
2362public:
2363 typedef time_base::dateorder dateorder;
2364 typedef _InputIterator iter_type;
2365 typedef _CharT char_type;
2366 typedef basic_string<char_type> string_type;
2367
Howard Hinnant756c69b2010-09-22 16:48:34 +00002368 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002369 explicit time_get_byname(const char* __nm, size_t __refs = 0)
2370 : time_get<_CharT, _InputIterator>(__refs),
2371 __time_get_storage<_CharT>(__nm) {}
Howard Hinnant756c69b2010-09-22 16:48:34 +00002372 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002373 explicit time_get_byname(const string& __nm, size_t __refs = 0)
2374 : time_get<_CharT, _InputIterator>(__refs),
2375 __time_get_storage<_CharT>(__nm) {}
2376
2377protected:
Howard Hinnant756c69b2010-09-22 16:48:34 +00002378 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002379 ~time_get_byname() {}
2380
Howard Hinnant756c69b2010-09-22 16:48:34 +00002381 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002382 virtual dateorder do_date_order() const {return this->__do_date_order();}
2383private:
Howard Hinnant756c69b2010-09-22 16:48:34 +00002384 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002385 virtual const string_type* __weeks() const {return this->__weeks_;}
Howard Hinnant756c69b2010-09-22 16:48:34 +00002386 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002387 virtual const string_type* __months() const {return this->__months_;}
Howard Hinnant756c69b2010-09-22 16:48:34 +00002388 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002389 virtual const string_type* __am_pm() const {return this->__am_pm_;}
Howard Hinnant756c69b2010-09-22 16:48:34 +00002390 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002391 virtual const string_type& __c() const {return this->__c_;}
Howard Hinnant756c69b2010-09-22 16:48:34 +00002392 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002393 virtual const string_type& __r() const {return this->__r_;}
Howard Hinnant756c69b2010-09-22 16:48:34 +00002394 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002395 virtual const string_type& __x() const {return this->__x_;}
Howard Hinnant756c69b2010-09-22 16:48:34 +00002396 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002397 virtual const string_type& __X() const {return this->__X_;}
2398};
2399
Eric Fiselier1b57fa82016-09-15 22:27:07 +00002400_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_get_byname<char>)
2401_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_get_byname<wchar_t>)
Howard Hinnantc51e1022010-05-11 19:42:16 +00002402
Howard Hinnanta37d3cf2013-08-12 18:38:34 +00002403class _LIBCPP_TYPE_VIS __time_put
Howard Hinnantc51e1022010-05-11 19:42:16 +00002404{
2405 locale_t __loc_;
2406protected:
Howard Hinnant1ab52da2011-09-28 21:05:01 +00002407 _LIBCPP_ALWAYS_INLINE __time_put() : __loc_(_LIBCPP_GET_C_LOCALE) {}
Howard Hinnantc51e1022010-05-11 19:42:16 +00002408 __time_put(const char* __nm);
2409 __time_put(const string& __nm);
2410 ~__time_put();
2411 void __do_put(char* __nb, char*& __ne, const tm* __tm,
2412 char __fmt, char __mod) const;
2413 void __do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
2414 char __fmt, char __mod) const;
2415};
2416
2417template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +00002418class _LIBCPP_TEMPLATE_VIS time_put
Howard Hinnantc51e1022010-05-11 19:42:16 +00002419 : public locale::facet,
2420 private __time_put
2421{
2422public:
2423 typedef _CharT char_type;
2424 typedef _OutputIterator iter_type;
2425
2426 _LIBCPP_ALWAYS_INLINE
2427 explicit time_put(size_t __refs = 0)
2428 : locale::facet(__refs) {}
2429
2430 iter_type put(iter_type __s, ios_base& __iob, char_type __fl, const tm* __tm,
2431 const char_type* __pb, const char_type* __pe) const;
2432
2433 _LIBCPP_ALWAYS_INLINE
2434 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
2435 const tm* __tm, char __fmt, char __mod = 0) const
2436 {
2437 return do_put(__s, __iob, __fl, __tm, __fmt, __mod);
2438 }
2439
2440 static locale::id id;
2441
2442protected:
Howard Hinnant756c69b2010-09-22 16:48:34 +00002443 _LIBCPP_ALWAYS_INLINE
Howard Hinnantc51e1022010-05-11 19:42:16 +00002444 ~time_put() {}
2445 virtual iter_type do_put(iter_type __s, ios_base&, char_type, const tm* __tm,
2446 char __fmt, char __mod) const;
2447
Howard Hinnant756c69b2010-09-22 16:48:34 +00002448 _LIBCPP_ALWAYS_INLINE
Howard Hinnantc51e1022010-05-11 19:42:16 +00002449 explicit time_put(const char* __nm, size_t __refs)
2450 : locale::facet(__refs),
2451 __time_put(__nm) {}
Howard Hinnant756c69b2010-09-22 16:48:34 +00002452 _LIBCPP_ALWAYS_INLINE
Howard Hinnantc51e1022010-05-11 19:42:16 +00002453 explicit time_put(const string& __nm, size_t __refs)
2454 : locale::facet(__refs),
2455 __time_put(__nm) {}
2456};
2457
2458template <class _CharT, class _OutputIterator>
2459locale::id
2460time_put<_CharT, _OutputIterator>::id;
2461
2462template <class _CharT, class _OutputIterator>
2463_OutputIterator
2464time_put<_CharT, _OutputIterator>::put(iter_type __s, ios_base& __iob,
2465 char_type __fl, const tm* __tm,
2466 const char_type* __pb,
2467 const char_type* __pe) const
2468{
2469 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2470 for (; __pb != __pe; ++__pb)
2471 {
2472 if (__ct.narrow(*__pb, 0) == '%')
2473 {
2474 if (++__pb == __pe)
2475 {
2476 *__s++ = __pb[-1];
2477 break;
2478 }
2479 char __mod = 0;
2480 char __fmt = __ct.narrow(*__pb, 0);
2481 if (__fmt == 'E' || __fmt == 'O')
2482 {
2483 if (++__pb == __pe)
2484 {
2485 *__s++ = __pb[-2];
2486 *__s++ = __pb[-1];
2487 break;
2488 }
2489 __mod = __fmt;
2490 __fmt = __ct.narrow(*__pb, 0);
2491 }
2492 __s = do_put(__s, __iob, __fl, __tm, __fmt, __mod);
2493 }
2494 else
2495 *__s++ = *__pb;
2496 }
2497 return __s;
2498}
2499
2500template <class _CharT, class _OutputIterator>
2501_OutputIterator
Howard Hinnant28b24882011-12-01 20:21:04 +00002502time_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00002503 char_type, const tm* __tm,
2504 char __fmt, char __mod) const
2505{
2506 char_type __nar[100];
2507 char_type* __nb = __nar;
2508 char_type* __ne = __nb + 100;
2509 __do_put(__nb, __ne, __tm, __fmt, __mod);
Howard Hinnantb1ad5a82011-06-30 21:18:19 +00002510 return _VSTD::copy(__nb, __ne, __s);
Howard Hinnantc51e1022010-05-11 19:42:16 +00002511}
2512
Eric Fiselier1b57fa82016-09-15 22:27:07 +00002513_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_put<char>)
2514_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_put<wchar_t>)
Howard Hinnantc51e1022010-05-11 19:42:16 +00002515
2516template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +00002517class _LIBCPP_TEMPLATE_VIS time_put_byname
Howard Hinnantc51e1022010-05-11 19:42:16 +00002518 : public time_put<_CharT, _OutputIterator>
2519{
2520public:
2521 _LIBCPP_ALWAYS_INLINE
2522 explicit time_put_byname(const char* __nm, size_t __refs = 0)
2523 : time_put<_CharT, _OutputIterator>(__nm, __refs) {}
2524
2525 _LIBCPP_ALWAYS_INLINE
2526 explicit time_put_byname(const string& __nm, size_t __refs = 0)
2527 : time_put<_CharT, _OutputIterator>(__nm, __refs) {}
2528
2529protected:
Howard Hinnant756c69b2010-09-22 16:48:34 +00002530 _LIBCPP_ALWAYS_INLINE
Howard Hinnantc51e1022010-05-11 19:42:16 +00002531 ~time_put_byname() {}
2532};
2533
Eric Fiselier1b57fa82016-09-15 22:27:07 +00002534_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_put_byname<char>)
2535_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_put_byname<wchar_t>)
Howard Hinnantc51e1022010-05-11 19:42:16 +00002536
2537// money_base
2538
Howard Hinnant8331b762013-03-06 23:30:19 +00002539class _LIBCPP_TYPE_VIS money_base
Howard Hinnantc51e1022010-05-11 19:42:16 +00002540{
2541public:
2542 enum part {none, space, symbol, sign, value};
2543 struct pattern {char field[4];};
2544
2545 _LIBCPP_ALWAYS_INLINE money_base() {}
2546};
2547
2548// moneypunct
2549
2550template <class _CharT, bool _International = false>
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +00002551class _LIBCPP_TEMPLATE_VIS moneypunct
Howard Hinnantc51e1022010-05-11 19:42:16 +00002552 : public locale::facet,
2553 public money_base
2554{
2555public:
2556 typedef _CharT char_type;
2557 typedef basic_string<char_type> string_type;
2558
Howard Hinnant756c69b2010-09-22 16:48:34 +00002559 _LIBCPP_ALWAYS_INLINE
Howard Hinnantc51e1022010-05-11 19:42:16 +00002560 explicit moneypunct(size_t __refs = 0)
2561 : locale::facet(__refs) {}
2562
2563 _LIBCPP_ALWAYS_INLINE char_type decimal_point() const {return do_decimal_point();}
2564 _LIBCPP_ALWAYS_INLINE char_type thousands_sep() const {return do_thousands_sep();}
2565 _LIBCPP_ALWAYS_INLINE string grouping() const {return do_grouping();}
2566 _LIBCPP_ALWAYS_INLINE string_type curr_symbol() const {return do_curr_symbol();}
2567 _LIBCPP_ALWAYS_INLINE string_type positive_sign() const {return do_positive_sign();}
2568 _LIBCPP_ALWAYS_INLINE string_type negative_sign() const {return do_negative_sign();}
2569 _LIBCPP_ALWAYS_INLINE int frac_digits() const {return do_frac_digits();}
2570 _LIBCPP_ALWAYS_INLINE pattern pos_format() const {return do_pos_format();}
2571 _LIBCPP_ALWAYS_INLINE pattern neg_format() const {return do_neg_format();}
2572
2573 static locale::id id;
2574 static const bool intl = _International;
2575
2576protected:
Howard Hinnant756c69b2010-09-22 16:48:34 +00002577 _LIBCPP_ALWAYS_INLINE
Howard Hinnantc51e1022010-05-11 19:42:16 +00002578 ~moneypunct() {}
2579
2580 virtual char_type do_decimal_point() const {return numeric_limits<char_type>::max();}
2581 virtual char_type do_thousands_sep() const {return numeric_limits<char_type>::max();}
2582 virtual string do_grouping() const {return string();}
2583 virtual string_type do_curr_symbol() const {return string_type();}
2584 virtual string_type do_positive_sign() const {return string_type();}
2585 virtual string_type do_negative_sign() const {return string_type(1, '-');}
2586 virtual int do_frac_digits() const {return 0;}
2587 virtual pattern do_pos_format() const
Howard Hinnantb10e6cf2012-11-06 21:48:33 +00002588 {pattern __p = {{symbol, sign, none, value}}; return __p;}
Howard Hinnantc51e1022010-05-11 19:42:16 +00002589 virtual pattern do_neg_format() const
Howard Hinnantb10e6cf2012-11-06 21:48:33 +00002590 {pattern __p = {{symbol, sign, none, value}}; return __p;}
Howard Hinnantc51e1022010-05-11 19:42:16 +00002591};
2592
2593template <class _CharT, bool _International>
2594locale::id
2595moneypunct<_CharT, _International>::id;
2596
Howard Hinnant2c45cb42012-12-12 21:14:28 +00002597template <class _CharT, bool _International>
2598const bool
2599moneypunct<_CharT, _International>::intl;
2600
Eric Fiselier1b57fa82016-09-15 22:27:07 +00002601_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct<char, false>)
2602_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct<char, true>)
2603_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct<wchar_t, false>)
2604_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct<wchar_t, true>)
Howard Hinnantc51e1022010-05-11 19:42:16 +00002605
2606// moneypunct_byname
2607
2608template <class _CharT, bool _International = false>
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +00002609class _LIBCPP_TEMPLATE_VIS moneypunct_byname
Howard Hinnant756c69b2010-09-22 16:48:34 +00002610 : public moneypunct<_CharT, _International>
Howard Hinnantc51e1022010-05-11 19:42:16 +00002611{
2612public:
2613 typedef money_base::pattern pattern;
2614 typedef _CharT char_type;
2615 typedef basic_string<char_type> string_type;
2616
2617 _LIBCPP_ALWAYS_INLINE
2618 explicit moneypunct_byname(const char* __nm, size_t __refs = 0)
2619 : moneypunct<_CharT, _International>(__refs) {init(__nm);}
2620
2621 _LIBCPP_ALWAYS_INLINE
2622 explicit moneypunct_byname(const string& __nm, size_t __refs = 0)
2623 : moneypunct<_CharT, _International>(__refs) {init(__nm.c_str());}
2624
2625protected:
Howard Hinnant756c69b2010-09-22 16:48:34 +00002626 _LIBCPP_ALWAYS_INLINE
Howard Hinnantc51e1022010-05-11 19:42:16 +00002627 ~moneypunct_byname() {}
2628
2629 virtual char_type do_decimal_point() const {return __decimal_point_;}
2630 virtual char_type do_thousands_sep() const {return __thousands_sep_;}
2631 virtual string do_grouping() const {return __grouping_;}
2632 virtual string_type do_curr_symbol() const {return __curr_symbol_;}
2633 virtual string_type do_positive_sign() const {return __positive_sign_;}
2634 virtual string_type do_negative_sign() const {return __negative_sign_;}
2635 virtual int do_frac_digits() const {return __frac_digits_;}
2636 virtual pattern do_pos_format() const {return __pos_format_;}
2637 virtual pattern do_neg_format() const {return __neg_format_;}
2638
2639private:
2640 char_type __decimal_point_;
2641 char_type __thousands_sep_;
2642 string __grouping_;
2643 string_type __curr_symbol_;
2644 string_type __positive_sign_;
2645 string_type __negative_sign_;
2646 int __frac_digits_;
2647 pattern __pos_format_;
2648 pattern __neg_format_;
2649
2650 void init(const char*);
2651};
2652
Shoaib Meenai094c3d22017-04-03 04:04:24 +00002653template<> _LIBCPP_FUNC_VIS void moneypunct_byname<char, false>::init(const char*);
2654template<> _LIBCPP_FUNC_VIS void moneypunct_byname<char, true>::init(const char*);
2655template<> _LIBCPP_FUNC_VIS void moneypunct_byname<wchar_t, false>::init(const char*);
2656template<> _LIBCPP_FUNC_VIS void moneypunct_byname<wchar_t, true>::init(const char*);
Howard Hinnantc51e1022010-05-11 19:42:16 +00002657
Eric Fiselier1b57fa82016-09-15 22:27:07 +00002658_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct_byname<char, false>)
2659_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct_byname<char, true>)
2660_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct_byname<wchar_t, false>)
2661_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct_byname<wchar_t, true>)
Howard Hinnantc51e1022010-05-11 19:42:16 +00002662
2663// money_get
2664
2665template <class _CharT>
2666class __money_get
2667{
2668protected:
2669 typedef _CharT char_type;
2670 typedef basic_string<char_type> string_type;
2671
2672 _LIBCPP_ALWAYS_INLINE __money_get() {}
2673
2674 static void __gather_info(bool __intl, const locale& __loc,
2675 money_base::pattern& __pat, char_type& __dp,
2676 char_type& __ts, string& __grp,
2677 string_type& __sym, string_type& __psn,
2678 string_type& __nsn, int& __fd);
2679};
2680
2681template <class _CharT>
2682void
2683__money_get<_CharT>::__gather_info(bool __intl, const locale& __loc,
2684 money_base::pattern& __pat, char_type& __dp,
2685 char_type& __ts, string& __grp,
2686 string_type& __sym, string_type& __psn,
2687 string_type& __nsn, int& __fd)
2688{
2689 if (__intl)
2690 {
2691 const moneypunct<char_type, true>& __mp =
2692 use_facet<moneypunct<char_type, true> >(__loc);
2693 __pat = __mp.neg_format();
2694 __nsn = __mp.negative_sign();
2695 __psn = __mp.positive_sign();
2696 __dp = __mp.decimal_point();
2697 __ts = __mp.thousands_sep();
2698 __grp = __mp.grouping();
2699 __sym = __mp.curr_symbol();
2700 __fd = __mp.frac_digits();
2701 }
2702 else
2703 {
2704 const moneypunct<char_type, false>& __mp =
2705 use_facet<moneypunct<char_type, false> >(__loc);
2706 __pat = __mp.neg_format();
2707 __nsn = __mp.negative_sign();
2708 __psn = __mp.positive_sign();
2709 __dp = __mp.decimal_point();
2710 __ts = __mp.thousands_sep();
2711 __grp = __mp.grouping();
2712 __sym = __mp.curr_symbol();
2713 __fd = __mp.frac_digits();
2714 }
2715}
2716
Eric Fiselier1b57fa82016-09-15 22:27:07 +00002717_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __money_get<char>)
2718_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __money_get<wchar_t>)
Howard Hinnantc51e1022010-05-11 19:42:16 +00002719
2720template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +00002721class _LIBCPP_TEMPLATE_VIS money_get
Howard Hinnantc51e1022010-05-11 19:42:16 +00002722 : public locale::facet,
2723 private __money_get<_CharT>
2724{
2725public:
2726 typedef _CharT char_type;
2727 typedef _InputIterator iter_type;
2728 typedef basic_string<char_type> string_type;
2729
2730 _LIBCPP_ALWAYS_INLINE
2731 explicit money_get(size_t __refs = 0)
2732 : locale::facet(__refs) {}
2733
2734 _LIBCPP_ALWAYS_INLINE
2735 iter_type get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob,
2736 ios_base::iostate& __err, long double& __v) const
2737 {
2738 return do_get(__b, __e, __intl, __iob, __err, __v);
2739 }
2740
2741 _LIBCPP_ALWAYS_INLINE
2742 iter_type get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob,
2743 ios_base::iostate& __err, string_type& __v) const
2744 {
2745 return do_get(__b, __e, __intl, __iob, __err, __v);
2746 }
2747
2748 static locale::id id;
2749
2750protected:
2751
Howard Hinnant756c69b2010-09-22 16:48:34 +00002752 _LIBCPP_ALWAYS_INLINE
Howard Hinnantc51e1022010-05-11 19:42:16 +00002753 ~money_get() {}
Howard Hinnant3b6579a2010-08-22 00:02:43 +00002754
Howard Hinnantc51e1022010-05-11 19:42:16 +00002755 virtual iter_type do_get(iter_type __b, iter_type __e, bool __intl,
2756 ios_base& __iob, ios_base::iostate& __err,
2757 long double& __v) const;
2758 virtual iter_type do_get(iter_type __b, iter_type __e, bool __intl,
2759 ios_base& __iob, ios_base::iostate& __err,
2760 string_type& __v) const;
2761
2762private:
2763 static bool __do_get(iter_type& __b, iter_type __e,
2764 bool __intl, const locale& __loc,
2765 ios_base::fmtflags __flags, ios_base::iostate& __err,
2766 bool& __neg, const ctype<char_type>& __ct,
2767 unique_ptr<char_type, void(*)(void*)>& __wb,
2768 char_type*& __wn, char_type* __we);
2769};
2770
2771template <class _CharT, class _InputIterator>
2772locale::id
2773money_get<_CharT, _InputIterator>::id;
2774
Howard Hinnanta37d3cf2013-08-12 18:38:34 +00002775_LIBCPP_FUNC_VIS void __do_nothing(void*);
Howard Hinnantc51e1022010-05-11 19:42:16 +00002776
2777template <class _Tp>
2778_LIBCPP_HIDDEN
2779void
2780__double_or_nothing(unique_ptr<_Tp, void(*)(void*)>& __b, _Tp*& __n, _Tp*& __e)
2781{
2782 bool __owns = __b.get_deleter() != __do_nothing;
Howard Hinnant28b24882011-12-01 20:21:04 +00002783 size_t __cur_cap = static_cast<size_t>(__e-__b.get()) * sizeof(_Tp);
Howard Hinnantc51e1022010-05-11 19:42:16 +00002784 size_t __new_cap = __cur_cap < numeric_limits<size_t>::max() / 2 ?
2785 2 * __cur_cap : numeric_limits<size_t>::max();
Marshall Clow6c9ddc22014-10-27 19:08:10 +00002786 if (__new_cap == 0)
2787 __new_cap = sizeof(_Tp);
Howard Hinnant28b24882011-12-01 20:21:04 +00002788 size_t __n_off = static_cast<size_t>(__n - __b.get());
Howard Hinnantc51e1022010-05-11 19:42:16 +00002789 _Tp* __t = (_Tp*)realloc(__owns ? __b.get() : 0, __new_cap);
2790 if (__t == 0)
2791 __throw_bad_alloc();
2792 if (__owns)
2793 __b.release();
2794 __b = unique_ptr<_Tp, void(*)(void*)>(__t, free);
2795 __new_cap /= sizeof(_Tp);
2796 __n = __b.get() + __n_off;
2797 __e = __b.get() + __new_cap;
2798}
2799
2800// true == success
2801template <class _CharT, class _InputIterator>
2802bool
2803money_get<_CharT, _InputIterator>::__do_get(iter_type& __b, iter_type __e,
2804 bool __intl, const locale& __loc,
2805 ios_base::fmtflags __flags,
2806 ios_base::iostate& __err,
2807 bool& __neg,
2808 const ctype<char_type>& __ct,
2809 unique_ptr<char_type, void(*)(void*)>& __wb,
2810 char_type*& __wn, char_type* __we)
2811{
2812 const unsigned __bz = 100;
2813 unsigned __gbuf[__bz];
2814 unique_ptr<unsigned, void(*)(void*)> __gb(__gbuf, __do_nothing);
2815 unsigned* __gn = __gb.get();
2816 unsigned* __ge = __gn + __bz;
2817 money_base::pattern __pat;
2818 char_type __dp;
2819 char_type __ts;
2820 string __grp;
2821 string_type __sym;
2822 string_type __psn;
2823 string_type __nsn;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00002824 // Capture the spaces read into money_base::{space,none} so they
2825 // can be compared to initial spaces in __sym.
2826 string_type __spaces;
Howard Hinnantc51e1022010-05-11 19:42:16 +00002827 int __fd;
2828 __money_get<_CharT>::__gather_info(__intl, __loc, __pat, __dp, __ts, __grp,
2829 __sym, __psn, __nsn, __fd);
2830 const string_type* __trailing_sign = 0;
2831 __wn = __wb.get();
2832 for (unsigned __p = 0; __p < 4 && __b != __e; ++__p)
2833 {
2834 switch (__pat.field[__p])
2835 {
2836 case money_base::space:
2837 if (__p != 3)
2838 {
2839 if (__ct.is(ctype_base::space, *__b))
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00002840 __spaces.push_back(*__b++);
Howard Hinnantc51e1022010-05-11 19:42:16 +00002841 else
2842 {
2843 __err |= ios_base::failbit;
2844 return false;
2845 }
2846 }
Eric Fiselier4db80032017-05-05 20:32:26 +00002847 _LIBCPP_FALLTHROUGH();
Howard Hinnantc51e1022010-05-11 19:42:16 +00002848 case money_base::none:
2849 if (__p != 3)
2850 {
2851 while (__b != __e && __ct.is(ctype_base::space, *__b))
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00002852 __spaces.push_back(*__b++);
Howard Hinnantc51e1022010-05-11 19:42:16 +00002853 }
2854 break;
2855 case money_base::sign:
2856 if (__psn.size() + __nsn.size() > 0)
2857 {
2858 if (__psn.size() == 0 || __nsn.size() == 0)
2859 { // sign is optional
2860 if (__psn.size() > 0)
2861 { // __nsn.size() == 0
2862 if (*__b == __psn[0])
2863 {
2864 ++__b;
2865 if (__psn.size() > 1)
2866 __trailing_sign = &__psn;
2867 }
2868 else
2869 __neg = true;
2870 }
2871 else if (*__b == __nsn[0]) // __nsn.size() > 0 && __psn.size() == 0
2872 {
2873 ++__b;
2874 __neg = true;
2875 if (__nsn.size() > 1)
2876 __trailing_sign = &__nsn;
2877 }
2878 }
2879 else // sign is required
2880 {
2881 if (*__b == __psn[0])
2882 {
2883 ++__b;
2884 if (__psn.size() > 1)
2885 __trailing_sign = &__psn;
2886 }
2887 else if (*__b == __nsn[0])
2888 {
2889 ++__b;
2890 __neg = true;
2891 if (__nsn.size() > 1)
2892 __trailing_sign = &__nsn;
2893 }
2894 else
2895 {
2896 __err |= ios_base::failbit;
2897 return false;
2898 }
2899 }
2900 }
2901 break;
2902 case money_base::symbol:
2903 {
2904 bool __more_needed = __trailing_sign ||
2905 (__p < 2) ||
2906 (__p == 2 && __pat.field[3] != static_cast<char>(money_base::none));
Marshall Clowdfcbb432013-10-13 01:02:45 +00002907 bool __sb = (__flags & ios_base::showbase) != 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +00002908 if (__sb || __more_needed)
2909 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00002910 typename string_type::const_iterator __sym_space_end = __sym.begin();
2911 if (__p > 0 && (__pat.field[__p - 1] == money_base::none ||
2912 __pat.field[__p - 1] == money_base::space)) {
2913 // Match spaces we've already read against spaces at
2914 // the beginning of __sym.
2915 while (__sym_space_end != __sym.end() &&
2916 __ct.is(ctype_base::space, *__sym_space_end))
2917 ++__sym_space_end;
2918 const size_t __num_spaces = __sym_space_end - __sym.begin();
2919 if (__num_spaces > __spaces.size() ||
2920 !equal(__spaces.end() - __num_spaces, __spaces.end(),
2921 __sym.begin())) {
2922 // No match. Put __sym_space_end back at the
2923 // beginning of __sym, which will prevent a
2924 // match in the next loop.
2925 __sym_space_end = __sym.begin();
2926 }
2927 }
2928 typename string_type::const_iterator __sym_curr_char = __sym_space_end;
2929 while (__sym_curr_char != __sym.end() && __b != __e &&
2930 *__b == *__sym_curr_char) {
2931 ++__b;
2932 ++__sym_curr_char;
2933 }
2934 if (__sb && __sym_curr_char != __sym.end())
Howard Hinnantc51e1022010-05-11 19:42:16 +00002935 {
2936 __err |= ios_base::failbit;
2937 return false;
2938 }
2939 }
2940 }
2941 break;
2942 case money_base::value:
2943 {
2944 unsigned __ng = 0;
2945 for (; __b != __e; ++__b)
2946 {
2947 char_type __c = *__b;
2948 if (__ct.is(ctype_base::digit, __c))
2949 {
2950 if (__wn == __we)
2951 __double_or_nothing(__wb, __wn, __we);
2952 *__wn++ = __c;
2953 ++__ng;
2954 }
2955 else if (__grp.size() > 0 && __ng > 0 && __c == __ts)
2956 {
2957 if (__gn == __ge)
2958 __double_or_nothing(__gb, __gn, __ge);
2959 *__gn++ = __ng;
2960 __ng = 0;
2961 }
2962 else
2963 break;
2964 }
2965 if (__gb.get() != __gn && __ng > 0)
2966 {
2967 if (__gn == __ge)
2968 __double_or_nothing(__gb, __gn, __ge);
2969 *__gn++ = __ng;
2970 }
2971 if (__fd > 0)
2972 {
2973 if (__b == __e || *__b != __dp)
2974 {
2975 __err |= ios_base::failbit;
2976 return false;
2977 }
2978 for (++__b; __fd > 0; --__fd, ++__b)
2979 {
2980 if (__b == __e || !__ct.is(ctype_base::digit, *__b))
2981 {
2982 __err |= ios_base::failbit;
2983 return false;
2984 }
2985 if (__wn == __we)
2986 __double_or_nothing(__wb, __wn, __we);
2987 *__wn++ = *__b;
2988 }
2989 }
2990 if (__wn == __wb.get())
2991 {
2992 __err |= ios_base::failbit;
2993 return false;
2994 }
2995 }
2996 break;
2997 }
2998 }
2999 if (__trailing_sign)
3000 {
3001 for (unsigned __i = 1; __i < __trailing_sign->size(); ++__i, ++__b)
3002 {
3003 if (__b == __e || *__b != (*__trailing_sign)[__i])
3004 {
3005 __err |= ios_base::failbit;
3006 return false;
3007 }
3008 }
3009 }
3010 if (__gb.get() != __gn)
3011 {
3012 ios_base::iostate __et = ios_base::goodbit;
3013 __check_grouping(__grp, __gb.get(), __gn, __et);
3014 if (__et)
3015 {
3016 __err |= ios_base::failbit;
3017 return false;
3018 }
3019 }
3020 return true;
3021}
3022
3023template <class _CharT, class _InputIterator>
3024_InputIterator
3025money_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
3026 bool __intl, ios_base& __iob,
3027 ios_base::iostate& __err,
3028 long double& __v) const
3029{
Howard Hinnant28b24882011-12-01 20:21:04 +00003030 const int __bz = 100;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003031 char_type __wbuf[__bz];
3032 unique_ptr<char_type, void(*)(void*)> __wb(__wbuf, __do_nothing);
3033 char_type* __wn;
3034 char_type* __we = __wbuf + __bz;
3035 locale __loc = __iob.getloc();
3036 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3037 bool __neg = false;
3038 if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct,
3039 __wb, __wn, __we))
3040 {
3041 const char __src[] = "0123456789";
3042 char_type __atoms[sizeof(__src)-1];
3043 __ct.widen(__src, __src + (sizeof(__src)-1), __atoms);
3044 char __nbuf[__bz];
3045 char* __nc = __nbuf;
3046 unique_ptr<char, void(*)(void*)> __h(0, free);
3047 if (__wn - __wb.get() > __bz-2)
3048 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003049 __h.reset((char*)malloc(static_cast<size_t>(__wn - __wb.get() + 2)));
Howard Hinnantc51e1022010-05-11 19:42:16 +00003050 if (__h.get() == 0)
3051 __throw_bad_alloc();
3052 __nc = __h.get();
3053 }
3054 if (__neg)
3055 *__nc++ = '-';
3056 for (const char_type* __w = __wb.get(); __w < __wn; ++__w, ++__nc)
Marshall Clow1e68fd42013-03-22 02:14:40 +00003057 *__nc = __src[find(__atoms, _VSTD::end(__atoms), *__w) - __atoms];
Howard Hinnantc51e1022010-05-11 19:42:16 +00003058 *__nc = char();
3059 if (sscanf(__nbuf, "%Lf", &__v) != 1)
3060 __throw_runtime_error("money_get error");
3061 }
3062 if (__b == __e)
3063 __err |= ios_base::eofbit;
3064 return __b;
3065}
3066
3067template <class _CharT, class _InputIterator>
3068_InputIterator
3069money_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
3070 bool __intl, ios_base& __iob,
3071 ios_base::iostate& __err,
3072 string_type& __v) const
3073{
Howard Hinnant28b24882011-12-01 20:21:04 +00003074 const int __bz = 100;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003075 char_type __wbuf[__bz];
3076 unique_ptr<char_type, void(*)(void*)> __wb(__wbuf, __do_nothing);
3077 char_type* __wn;
3078 char_type* __we = __wbuf + __bz;
3079 locale __loc = __iob.getloc();
3080 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3081 bool __neg = false;
3082 if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct,
3083 __wb, __wn, __we))
3084 {
3085 __v.clear();
3086 if (__neg)
3087 __v.push_back(__ct.widen('-'));
3088 char_type __z = __ct.widen('0');
3089 char_type* __w;
3090 for (__w = __wb.get(); __w < __wn-1; ++__w)
3091 if (*__w != __z)
3092 break;
3093 __v.append(__w, __wn);
3094 }
3095 if (__b == __e)
3096 __err |= ios_base::eofbit;
3097 return __b;
3098}
3099
Eric Fiselier1b57fa82016-09-15 22:27:07 +00003100_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS money_get<char>)
3101_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS money_get<wchar_t>)
Howard Hinnantc51e1022010-05-11 19:42:16 +00003102
3103// money_put
3104
3105template <class _CharT>
3106class __money_put
3107{
3108protected:
3109 typedef _CharT char_type;
3110 typedef basic_string<char_type> string_type;
3111
3112 _LIBCPP_ALWAYS_INLINE __money_put() {}
3113
3114 static void __gather_info(bool __intl, bool __neg, const locale& __loc,
3115 money_base::pattern& __pat, char_type& __dp,
3116 char_type& __ts, string& __grp,
3117 string_type& __sym, string_type& __sn,
3118 int& __fd);
3119 static void __format(char_type* __mb, char_type*& __mi, char_type*& __me,
3120 ios_base::fmtflags __flags,
3121 const char_type* __db, const char_type* __de,
3122 const ctype<char_type>& __ct, bool __neg,
3123 const money_base::pattern& __pat, char_type __dp,
3124 char_type __ts, const string& __grp,
3125 const string_type& __sym, const string_type& __sn,
3126 int __fd);
3127};
3128
3129template <class _CharT>
3130void
3131__money_put<_CharT>::__gather_info(bool __intl, bool __neg, const locale& __loc,
3132 money_base::pattern& __pat, char_type& __dp,
3133 char_type& __ts, string& __grp,
3134 string_type& __sym, string_type& __sn,
3135 int& __fd)
3136{
3137 if (__intl)
3138 {
3139 const moneypunct<char_type, true>& __mp =
3140 use_facet<moneypunct<char_type, true> >(__loc);
3141 if (__neg)
3142 {
3143 __pat = __mp.neg_format();
3144 __sn = __mp.negative_sign();
3145 }
3146 else
3147 {
3148 __pat = __mp.pos_format();
3149 __sn = __mp.positive_sign();
3150 }
3151 __dp = __mp.decimal_point();
3152 __ts = __mp.thousands_sep();
3153 __grp = __mp.grouping();
3154 __sym = __mp.curr_symbol();
3155 __fd = __mp.frac_digits();
3156 }
3157 else
3158 {
3159 const moneypunct<char_type, false>& __mp =
3160 use_facet<moneypunct<char_type, false> >(__loc);
3161 if (__neg)
3162 {
3163 __pat = __mp.neg_format();
3164 __sn = __mp.negative_sign();
3165 }
3166 else
3167 {
3168 __pat = __mp.pos_format();
3169 __sn = __mp.positive_sign();
3170 }
3171 __dp = __mp.decimal_point();
3172 __ts = __mp.thousands_sep();
3173 __grp = __mp.grouping();
3174 __sym = __mp.curr_symbol();
3175 __fd = __mp.frac_digits();
3176 }
3177}
3178
3179template <class _CharT>
3180void
3181__money_put<_CharT>::__format(char_type* __mb, char_type*& __mi, char_type*& __me,
3182 ios_base::fmtflags __flags,
3183 const char_type* __db, const char_type* __de,
3184 const ctype<char_type>& __ct, bool __neg,
3185 const money_base::pattern& __pat, char_type __dp,
3186 char_type __ts, const string& __grp,
3187 const string_type& __sym, const string_type& __sn,
3188 int __fd)
3189{
3190 __me = __mb;
3191 for (unsigned __p = 0; __p < 4; ++__p)
3192 {
3193 switch (__pat.field[__p])
3194 {
3195 case money_base::none:
3196 __mi = __me;
3197 break;
3198 case money_base::space:
3199 __mi = __me;
3200 *__me++ = __ct.widen(' ');
3201 break;
3202 case money_base::sign:
3203 if (!__sn.empty())
3204 *__me++ = __sn[0];
3205 break;
3206 case money_base::symbol:
3207 if (!__sym.empty() && (__flags & ios_base::showbase))
Howard Hinnantb1ad5a82011-06-30 21:18:19 +00003208 __me = _VSTD::copy(__sym.begin(), __sym.end(), __me);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003209 break;
3210 case money_base::value:
3211 {
3212 // remember start of value so we can reverse it
3213 char_type* __t = __me;
3214 // find beginning of digits
3215 if (__neg)
3216 ++__db;
3217 // find end of digits
3218 const char_type* __d;
3219 for (__d = __db; __d < __de; ++__d)
3220 if (!__ct.is(ctype_base::digit, *__d))
3221 break;
3222 // print fractional part
3223 if (__fd > 0)
3224 {
3225 int __f;
3226 for (__f = __fd; __d > __db && __f > 0; --__f)
3227 *__me++ = *--__d;
3228 char_type __z = __f > 0 ? __ct.widen('0') : char_type();
3229 for (; __f > 0; --__f)
3230 *__me++ = __z;
3231 *__me++ = __dp;
3232 }
3233 // print units part
3234 if (__d == __db)
3235 {
3236 *__me++ = __ct.widen('0');
3237 }
3238 else
3239 {
3240 unsigned __ng = 0;
3241 unsigned __ig = 0;
3242 unsigned __gl = __grp.empty() ? numeric_limits<unsigned>::max()
3243 : static_cast<unsigned>(__grp[__ig]);
3244 while (__d != __db)
3245 {
3246 if (__ng == __gl)
3247 {
3248 *__me++ = __ts;
3249 __ng = 0;
3250 if (++__ig < __grp.size())
3251 __gl = __grp[__ig] == numeric_limits<char>::max() ?
3252 numeric_limits<unsigned>::max() :
3253 static_cast<unsigned>(__grp[__ig]);
3254 }
3255 *__me++ = *--__d;
3256 ++__ng;
3257 }
3258 }
3259 // reverse it
3260 reverse(__t, __me);
3261 }
3262 break;
3263 }
3264 }
3265 // print rest of sign, if any
3266 if (__sn.size() > 1)
Howard Hinnantb1ad5a82011-06-30 21:18:19 +00003267 __me = _VSTD::copy(__sn.begin()+1, __sn.end(), __me);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003268 // set alignment
3269 if ((__flags & ios_base::adjustfield) == ios_base::left)
3270 __mi = __me;
3271 else if ((__flags & ios_base::adjustfield) != ios_base::internal)
3272 __mi = __mb;
3273}
3274
Eric Fiselier1b57fa82016-09-15 22:27:07 +00003275_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __money_put<char>)
3276_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __money_put<wchar_t>)
Howard Hinnantc51e1022010-05-11 19:42:16 +00003277
3278template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +00003279class _LIBCPP_TEMPLATE_VIS money_put
Howard Hinnantc51e1022010-05-11 19:42:16 +00003280 : public locale::facet,
3281 private __money_put<_CharT>
3282{
3283public:
3284 typedef _CharT char_type;
3285 typedef _OutputIterator iter_type;
3286 typedef basic_string<char_type> string_type;
3287
3288 _LIBCPP_ALWAYS_INLINE
3289 explicit money_put(size_t __refs = 0)
3290 : locale::facet(__refs) {}
3291
3292 _LIBCPP_ALWAYS_INLINE
3293 iter_type put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl,
3294 long double __units) const
3295 {
3296 return do_put(__s, __intl, __iob, __fl, __units);
3297 }
3298
3299 _LIBCPP_ALWAYS_INLINE
3300 iter_type put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl,
3301 const string_type& __digits) const
3302 {
3303 return do_put(__s, __intl, __iob, __fl, __digits);
3304 }
3305
3306 static locale::id id;
3307
3308protected:
Howard Hinnant756c69b2010-09-22 16:48:34 +00003309 _LIBCPP_ALWAYS_INLINE
Howard Hinnantc51e1022010-05-11 19:42:16 +00003310 ~money_put() {}
3311
3312 virtual iter_type do_put(iter_type __s, bool __intl, ios_base& __iob,
3313 char_type __fl, long double __units) const;
3314 virtual iter_type do_put(iter_type __s, bool __intl, ios_base& __iob,
3315 char_type __fl, const string_type& __digits) const;
3316};
3317
3318template <class _CharT, class _OutputIterator>
3319locale::id
3320money_put<_CharT, _OutputIterator>::id;
3321
3322template <class _CharT, class _OutputIterator>
3323_OutputIterator
3324money_put<_CharT, _OutputIterator>::do_put(iter_type __s, bool __intl,
3325 ios_base& __iob, char_type __fl,
3326 long double __units) const
3327{
3328 // convert to char
3329 const size_t __bs = 100;
3330 char __buf[__bs];
3331 char* __bb = __buf;
3332 char_type __digits[__bs];
3333 char_type* __db = __digits;
Howard Hinnant28b24882011-12-01 20:21:04 +00003334 size_t __n = static_cast<size_t>(snprintf(__bb, __bs, "%.0Lf", __units));
Howard Hinnantc51e1022010-05-11 19:42:16 +00003335 unique_ptr<char, void(*)(void*)> __hn(0, free);
3336 unique_ptr<char_type, void(*)(void*)> __hd(0, free);
3337 // secure memory for digit storage
3338 if (__n > __bs-1)
3339 {
Ben Craig3756b922016-03-09 15:39:39 +00003340 __n = static_cast<size_t>(__libcpp_asprintf_l(&__bb, _LIBCPP_GET_C_LOCALE, "%.0Lf", __units));
Howard Hinnantc51e1022010-05-11 19:42:16 +00003341 if (__bb == 0)
3342 __throw_bad_alloc();
3343 __hn.reset(__bb);
3344 __hd.reset((char_type*)malloc(__n * sizeof(char_type)));
Howard Hinnant03de6f92012-03-07 20:37:43 +00003345 if (__hd == nullptr)
Howard Hinnantc51e1022010-05-11 19:42:16 +00003346 __throw_bad_alloc();
3347 __db = __hd.get();
3348 }
3349 // gather info
3350 locale __loc = __iob.getloc();
3351 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3352 __ct.widen(__bb, __bb + __n, __db);
3353 bool __neg = __n > 0 && __bb[0] == '-';
3354 money_base::pattern __pat;
3355 char_type __dp;
3356 char_type __ts;
3357 string __grp;
3358 string_type __sym;
3359 string_type __sn;
3360 int __fd;
3361 this->__gather_info(__intl, __neg, __loc, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3362 // secure memory for formatting
3363 char_type __mbuf[__bs];
3364 char_type* __mb = __mbuf;
3365 unique_ptr<char_type, void(*)(void*)> __hw(0, free);
3366 size_t __exn = static_cast<int>(__n) > __fd ?
Howard Hinnant28b24882011-12-01 20:21:04 +00003367 (__n - static_cast<size_t>(__fd)) * 2 + __sn.size() +
3368 __sym.size() + static_cast<size_t>(__fd) + 1
3369 : __sn.size() + __sym.size() + static_cast<size_t>(__fd) + 2;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003370 if (__exn > __bs)
3371 {
3372 __hw.reset((char_type*)malloc(__exn * sizeof(char_type)));
3373 __mb = __hw.get();
3374 if (__mb == 0)
3375 __throw_bad_alloc();
3376 }
3377 // format
3378 char_type* __mi;
3379 char_type* __me;
3380 this->__format(__mb, __mi, __me, __iob.flags(),
3381 __db, __db + __n, __ct,
3382 __neg, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3383 return __pad_and_output(__s, __mb, __mi, __me, __iob, __fl);
3384}
3385
3386template <class _CharT, class _OutputIterator>
3387_OutputIterator
3388money_put<_CharT, _OutputIterator>::do_put(iter_type __s, bool __intl,
3389 ios_base& __iob, char_type __fl,
3390 const string_type& __digits) const
3391{
3392 // gather info
3393 locale __loc = __iob.getloc();
3394 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3395 bool __neg = __digits.size() > 0 && __digits[0] == __ct.widen('-');
3396 money_base::pattern __pat;
3397 char_type __dp;
3398 char_type __ts;
3399 string __grp;
3400 string_type __sym;
3401 string_type __sn;
3402 int __fd;
3403 this->__gather_info(__intl, __neg, __loc, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3404 // secure memory for formatting
3405 char_type __mbuf[100];
3406 char_type* __mb = __mbuf;
3407 unique_ptr<char_type, void(*)(void*)> __h(0, free);
Howard Hinnant28b24882011-12-01 20:21:04 +00003408 size_t __exn = static_cast<int>(__digits.size()) > __fd ?
3409 (__digits.size() - static_cast<size_t>(__fd)) * 2 +
3410 __sn.size() + __sym.size() + static_cast<size_t>(__fd) + 1
3411 : __sn.size() + __sym.size() + static_cast<size_t>(__fd) + 2;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003412 if (__exn > 100)
3413 {
3414 __h.reset((char_type*)malloc(__exn * sizeof(char_type)));
3415 __mb = __h.get();
3416 if (__mb == 0)
3417 __throw_bad_alloc();
3418 }
3419 // format
3420 char_type* __mi;
3421 char_type* __me;
3422 this->__format(__mb, __mi, __me, __iob.flags(),
3423 __digits.data(), __digits.data() + __digits.size(), __ct,
3424 __neg, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3425 return __pad_and_output(__s, __mb, __mi, __me, __iob, __fl);
3426}
3427
Eric Fiselier1b57fa82016-09-15 22:27:07 +00003428_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS money_put<char>)
3429_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS money_put<wchar_t>)
Howard Hinnantc51e1022010-05-11 19:42:16 +00003430
3431// messages
3432
Howard Hinnant8331b762013-03-06 23:30:19 +00003433class _LIBCPP_TYPE_VIS messages_base
Howard Hinnantc51e1022010-05-11 19:42:16 +00003434{
3435public:
Howard Hinnant2862aeb2011-02-25 00:51:08 +00003436 typedef ptrdiff_t catalog;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003437
3438 _LIBCPP_ALWAYS_INLINE messages_base() {}
3439};
3440
3441template <class _CharT>
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +00003442class _LIBCPP_TEMPLATE_VIS messages
Howard Hinnantc51e1022010-05-11 19:42:16 +00003443 : public locale::facet,
3444 public messages_base
3445{
3446public:
3447 typedef _CharT char_type;
3448 typedef basic_string<_CharT> string_type;
3449
3450 _LIBCPP_ALWAYS_INLINE
3451 explicit messages(size_t __refs = 0)
3452 : locale::facet(__refs) {}
3453
3454 _LIBCPP_ALWAYS_INLINE
3455 catalog open(const basic_string<char>& __nm, const locale& __loc) const
3456 {
3457 return do_open(__nm, __loc);
3458 }
3459
3460 _LIBCPP_ALWAYS_INLINE
3461 string_type get(catalog __c, int __set, int __msgid,
3462 const string_type& __dflt) const
3463 {
3464 return do_get(__c, __set, __msgid, __dflt);
3465 }
3466
3467 _LIBCPP_ALWAYS_INLINE
3468 void close(catalog __c) const
3469 {
3470 do_close(__c);
3471 }
3472
3473 static locale::id id;
3474
3475protected:
Howard Hinnant756c69b2010-09-22 16:48:34 +00003476 _LIBCPP_ALWAYS_INLINE
Howard Hinnantc51e1022010-05-11 19:42:16 +00003477 ~messages() {}
3478
3479 virtual catalog do_open(const basic_string<char>&, const locale&) const;
3480 virtual string_type do_get(catalog, int __set, int __msgid,
3481 const string_type& __dflt) const;
3482 virtual void do_close(catalog) const;
3483};
3484
3485template <class _CharT>
3486locale::id
3487messages<_CharT>::id;
3488
3489template <class _CharT>
3490typename messages<_CharT>::catalog
3491messages<_CharT>::do_open(const basic_string<char>& __nm, const locale&) const
3492{
Ed Schouten118b6032015-03-11 16:39:36 +00003493#ifdef _LIBCPP_HAS_CATOPEN
Howard Hinnant8c2bf6b2011-10-11 16:00:46 +00003494 catalog __cat = (catalog)catopen(__nm.c_str(), NL_CAT_LOCALE);
Howard Hinnant2862aeb2011-02-25 00:51:08 +00003495 if (__cat != -1)
3496 __cat = static_cast<catalog>((static_cast<size_t>(__cat) >> 1));
3497 return __cat;
Ed Schouten118b6032015-03-11 16:39:36 +00003498#else // !_LIBCPP_HAS_CATOPEN
3499 return -1;
3500#endif // _LIBCPP_HAS_CATOPEN
Howard Hinnantc51e1022010-05-11 19:42:16 +00003501}
3502
3503template <class _CharT>
3504typename messages<_CharT>::string_type
3505messages<_CharT>::do_get(catalog __c, int __set, int __msgid,
3506 const string_type& __dflt) const
3507{
Ed Schouten118b6032015-03-11 16:39:36 +00003508#ifdef _LIBCPP_HAS_CATOPEN
Howard Hinnantc51e1022010-05-11 19:42:16 +00003509 string __ndflt;
3510 __narrow_to_utf8<sizeof(char_type)*__CHAR_BIT__>()(back_inserter(__ndflt),
3511 __dflt.c_str(),
3512 __dflt.c_str() + __dflt.size());
Howard Hinnant2862aeb2011-02-25 00:51:08 +00003513 if (__c != -1)
3514 __c <<= 1;
Howard Hinnant8c2bf6b2011-10-11 16:00:46 +00003515 nl_catd __cat = (nl_catd)__c;
Howard Hinnant2862aeb2011-02-25 00:51:08 +00003516 char* __n = catgets(__cat, __set, __msgid, __ndflt.c_str());
Howard Hinnantc51e1022010-05-11 19:42:16 +00003517 string_type __w;
3518 __widen_from_utf8<sizeof(char_type)*__CHAR_BIT__>()(back_inserter(__w),
3519 __n, __n + strlen(__n));
3520 return __w;
Ed Schouten118b6032015-03-11 16:39:36 +00003521#else // !_LIBCPP_HAS_CATOPEN
3522 return __dflt;
3523#endif // _LIBCPP_HAS_CATOPEN
Howard Hinnantc51e1022010-05-11 19:42:16 +00003524}
3525
3526template <class _CharT>
3527void
3528messages<_CharT>::do_close(catalog __c) const
3529{
Ed Schouten118b6032015-03-11 16:39:36 +00003530#ifdef _LIBCPP_HAS_CATOPEN
Howard Hinnant2862aeb2011-02-25 00:51:08 +00003531 if (__c != -1)
3532 __c <<= 1;
Howard Hinnant8c2bf6b2011-10-11 16:00:46 +00003533 nl_catd __cat = (nl_catd)__c;
Howard Hinnant2862aeb2011-02-25 00:51:08 +00003534 catclose(__cat);
Ed Schouten118b6032015-03-11 16:39:36 +00003535#endif // _LIBCPP_HAS_CATOPEN
Howard Hinnantc51e1022010-05-11 19:42:16 +00003536}
3537
Eric Fiselier1b57fa82016-09-15 22:27:07 +00003538_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS messages<char>)
3539_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS messages<wchar_t>)
Howard Hinnantc51e1022010-05-11 19:42:16 +00003540
3541template <class _CharT>
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +00003542class _LIBCPP_TEMPLATE_VIS messages_byname
Howard Hinnantc51e1022010-05-11 19:42:16 +00003543 : public messages<_CharT>
3544{
3545public:
3546 typedef messages_base::catalog catalog;
3547 typedef basic_string<_CharT> string_type;
3548
3549 _LIBCPP_ALWAYS_INLINE
3550 explicit messages_byname(const char*, size_t __refs = 0)
3551 : messages<_CharT>(__refs) {}
3552
3553 _LIBCPP_ALWAYS_INLINE
3554 explicit messages_byname(const string&, size_t __refs = 0)
3555 : messages<_CharT>(__refs) {}
3556
3557protected:
Howard Hinnant756c69b2010-09-22 16:48:34 +00003558 _LIBCPP_ALWAYS_INLINE
Howard Hinnantc51e1022010-05-11 19:42:16 +00003559 ~messages_byname() {}
3560};
3561
Eric Fiselier1b57fa82016-09-15 22:27:07 +00003562_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS messages_byname<char>)
3563_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS messages_byname<wchar_t>)
Howard Hinnantc51e1022010-05-11 19:42:16 +00003564
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003565template<class _Codecvt, class _Elem = wchar_t,
3566 class _Wide_alloc = allocator<_Elem>,
3567 class _Byte_alloc = allocator<char> >
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +00003568class _LIBCPP_TEMPLATE_VIS wstring_convert
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003569{
3570public:
3571 typedef basic_string<char, char_traits<char>, _Byte_alloc> byte_string;
3572 typedef basic_string<_Elem, char_traits<_Elem>, _Wide_alloc> wide_string;
3573 typedef typename _Codecvt::state_type state_type;
3574 typedef typename wide_string::traits_type::int_type int_type;
3575
3576private:
3577 byte_string __byte_err_string_;
3578 wide_string __wide_err_string_;
3579 _Codecvt* __cvtptr_;
3580 state_type __cvtstate_;
3581 size_t __cvtcount_;
3582
3583 wstring_convert(const wstring_convert& __wc);
3584 wstring_convert& operator=(const wstring_convert& __wc);
3585public:
Evgeniy Stepanov2fb1cb62015-11-07 01:22:13 +00003586 _LIBCPP_ALWAYS_INLINE
Marshall Clowccaa0fb2013-08-27 20:18:59 +00003587 _LIBCPP_EXPLICIT_AFTER_CXX11 wstring_convert(_Codecvt* __pcvt = new _Codecvt);
Evgeniy Stepanov2fb1cb62015-11-07 01:22:13 +00003588 _LIBCPP_ALWAYS_INLINE
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003589 wstring_convert(_Codecvt* __pcvt, state_type __state);
Marshall Clowccaa0fb2013-08-27 20:18:59 +00003590 _LIBCPP_EXPLICIT_AFTER_CXX11 wstring_convert(const byte_string& __byte_err,
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003591 const wide_string& __wide_err = wide_string());
Eric Fiselierf07d88c2017-04-19 01:34:08 +00003592#ifndef _LIBCPP_CXX03_LANG
Evgeniy Stepanov2fb1cb62015-11-07 01:22:13 +00003593 _LIBCPP_ALWAYS_INLINE
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003594 wstring_convert(wstring_convert&& __wc);
3595#endif
3596 ~wstring_convert();
3597
Howard Hinnant756c69b2010-09-22 16:48:34 +00003598 _LIBCPP_ALWAYS_INLINE
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003599 wide_string from_bytes(char __byte)
3600 {return from_bytes(&__byte, &__byte+1);}
Howard Hinnant756c69b2010-09-22 16:48:34 +00003601 _LIBCPP_ALWAYS_INLINE
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003602 wide_string from_bytes(const char* __ptr)
3603 {return from_bytes(__ptr, __ptr + char_traits<char>::length(__ptr));}
Howard Hinnant756c69b2010-09-22 16:48:34 +00003604 _LIBCPP_ALWAYS_INLINE
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003605 wide_string from_bytes(const byte_string& __str)
3606 {return from_bytes(__str.data(), __str.data() + __str.size());}
3607 wide_string from_bytes(const char* __first, const char* __last);
3608
Howard Hinnant756c69b2010-09-22 16:48:34 +00003609 _LIBCPP_ALWAYS_INLINE
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003610 byte_string to_bytes(_Elem __wchar)
3611 {return to_bytes(&__wchar, &__wchar+1);}
Howard Hinnant756c69b2010-09-22 16:48:34 +00003612 _LIBCPP_ALWAYS_INLINE
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003613 byte_string to_bytes(const _Elem* __wptr)
3614 {return to_bytes(__wptr, __wptr + char_traits<_Elem>::length(__wptr));}
Howard Hinnant756c69b2010-09-22 16:48:34 +00003615 _LIBCPP_ALWAYS_INLINE
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003616 byte_string to_bytes(const wide_string& __wstr)
3617 {return to_bytes(__wstr.data(), __wstr.data() + __wstr.size());}
3618 byte_string to_bytes(const _Elem* __first, const _Elem* __last);
3619
Howard Hinnant756c69b2010-09-22 16:48:34 +00003620 _LIBCPP_ALWAYS_INLINE
Marshall Clowccaa0fb2013-08-27 20:18:59 +00003621 size_t converted() const _NOEXCEPT {return __cvtcount_;}
Howard Hinnant756c69b2010-09-22 16:48:34 +00003622 _LIBCPP_ALWAYS_INLINE
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003623 state_type state() const {return __cvtstate_;}
3624};
3625
3626template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Evgeniy Stepanov2fb1cb62015-11-07 01:22:13 +00003627inline
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003628wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3629 wstring_convert(_Codecvt* __pcvt)
3630 : __cvtptr_(__pcvt), __cvtstate_(), __cvtcount_(0)
3631{
3632}
3633
3634template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Evgeniy Stepanov2fb1cb62015-11-07 01:22:13 +00003635inline
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003636wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3637 wstring_convert(_Codecvt* __pcvt, state_type __state)
3638 : __cvtptr_(__pcvt), __cvtstate_(__state), __cvtcount_(0)
3639{
3640}
3641
3642template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3643wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3644 wstring_convert(const byte_string& __byte_err, const wide_string& __wide_err)
3645 : __byte_err_string_(__byte_err), __wide_err_string_(__wide_err),
3646 __cvtstate_(), __cvtcount_(0)
3647{
3648 __cvtptr_ = new _Codecvt;
3649}
3650
Eric Fiselierf07d88c2017-04-19 01:34:08 +00003651#ifndef _LIBCPP_CXX03_LANG
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003652
3653template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Evgeniy Stepanov2fb1cb62015-11-07 01:22:13 +00003654inline
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003655wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3656 wstring_convert(wstring_convert&& __wc)
Howard Hinnantb1ad5a82011-06-30 21:18:19 +00003657 : __byte_err_string_(_VSTD::move(__wc.__byte_err_string_)),
3658 __wide_err_string_(_VSTD::move(__wc.__wide_err_string_)),
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003659 __cvtptr_(__wc.__cvtptr_),
Eric Fiselier35c67232016-06-26 22:56:26 +00003660 __cvtstate_(__wc.__cvtstate_), __cvtcount_(__wc.__cvtcount_)
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003661{
3662 __wc.__cvtptr_ = nullptr;
3663}
3664
Eric Fiselierf07d88c2017-04-19 01:34:08 +00003665#endif // _LIBCPP_CXX03_LANG
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003666
3667template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3668wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::~wstring_convert()
3669{
3670 delete __cvtptr_;
3671}
3672
3673template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3674typename wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::wide_string
3675wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3676 from_bytes(const char* __frm, const char* __frm_end)
3677{
3678 __cvtcount_ = 0;
3679 if (__cvtptr_ != nullptr)
3680 {
3681 wide_string __ws(2*(__frm_end - __frm), _Elem());
Howard Hinnant16d54f22012-07-12 18:07:41 +00003682 if (__frm != __frm_end)
3683 __ws.resize(__ws.capacity());
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003684 codecvt_base::result __r = codecvt_base::ok;
3685 state_type __st = __cvtstate_;
3686 if (__frm != __frm_end)
3687 {
3688 _Elem* __to = &__ws[0];
3689 _Elem* __to_end = __to + __ws.size();
3690 const char* __frm_nxt;
3691 do
3692 {
3693 _Elem* __to_nxt;
3694 __r = __cvtptr_->in(__st, __frm, __frm_end, __frm_nxt,
3695 __to, __to_end, __to_nxt);
3696 __cvtcount_ += __frm_nxt - __frm;
3697 if (__frm_nxt == __frm)
3698 {
3699 __r = codecvt_base::error;
3700 }
3701 else if (__r == codecvt_base::noconv)
3702 {
3703 __ws.resize(__to - &__ws[0]);
3704 // This only gets executed if _Elem is char
3705 __ws.append((const _Elem*)__frm, (const _Elem*)__frm_end);
3706 __frm = __frm_nxt;
3707 __r = codecvt_base::ok;
3708 }
3709 else if (__r == codecvt_base::ok)
3710 {
3711 __ws.resize(__to_nxt - &__ws[0]);
3712 __frm = __frm_nxt;
3713 }
3714 else if (__r == codecvt_base::partial)
3715 {
3716 ptrdiff_t __s = __to_nxt - &__ws[0];
3717 __ws.resize(2 * __s);
3718 __to = &__ws[0] + __s;
3719 __to_end = &__ws[0] + __ws.size();
3720 __frm = __frm_nxt;
3721 }
3722 } while (__r == codecvt_base::partial && __frm_nxt < __frm_end);
3723 }
3724 if (__r == codecvt_base::ok)
3725 return __ws;
3726 }
Marshall Clow8fea1612016-08-25 15:09:01 +00003727
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003728 if (__wide_err_string_.empty())
Marshall Clow8fea1612016-08-25 15:09:01 +00003729 __throw_range_error("wstring_convert: from_bytes error");
3730
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003731 return __wide_err_string_;
3732}
3733
3734template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3735typename wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::byte_string
3736wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3737 to_bytes(const _Elem* __frm, const _Elem* __frm_end)
3738{
3739 __cvtcount_ = 0;
3740 if (__cvtptr_ != nullptr)
3741 {
3742 byte_string __bs(2*(__frm_end - __frm), char());
Howard Hinnant16d54f22012-07-12 18:07:41 +00003743 if (__frm != __frm_end)
3744 __bs.resize(__bs.capacity());
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003745 codecvt_base::result __r = codecvt_base::ok;
3746 state_type __st = __cvtstate_;
3747 if (__frm != __frm_end)
3748 {
3749 char* __to = &__bs[0];
3750 char* __to_end = __to + __bs.size();
3751 const _Elem* __frm_nxt;
3752 do
3753 {
3754 char* __to_nxt;
3755 __r = __cvtptr_->out(__st, __frm, __frm_end, __frm_nxt,
3756 __to, __to_end, __to_nxt);
3757 __cvtcount_ += __frm_nxt - __frm;
3758 if (__frm_nxt == __frm)
3759 {
3760 __r = codecvt_base::error;
3761 }
3762 else if (__r == codecvt_base::noconv)
3763 {
3764 __bs.resize(__to - &__bs[0]);
3765 // This only gets executed if _Elem is char
3766 __bs.append((const char*)__frm, (const char*)__frm_end);
3767 __frm = __frm_nxt;
3768 __r = codecvt_base::ok;
3769 }
3770 else if (__r == codecvt_base::ok)
3771 {
3772 __bs.resize(__to_nxt - &__bs[0]);
3773 __frm = __frm_nxt;
3774 }
3775 else if (__r == codecvt_base::partial)
3776 {
3777 ptrdiff_t __s = __to_nxt - &__bs[0];
3778 __bs.resize(2 * __s);
3779 __to = &__bs[0] + __s;
3780 __to_end = &__bs[0] + __bs.size();
3781 __frm = __frm_nxt;
3782 }
3783 } while (__r == codecvt_base::partial && __frm_nxt < __frm_end);
3784 }
3785 if (__r == codecvt_base::ok)
3786 {
3787 size_t __s = __bs.size();
3788 __bs.resize(__bs.capacity());
3789 char* __to = &__bs[0] + __s;
3790 char* __to_end = __to + __bs.size();
3791 do
3792 {
3793 char* __to_nxt;
3794 __r = __cvtptr_->unshift(__st, __to, __to_end, __to_nxt);
3795 if (__r == codecvt_base::noconv)
3796 {
3797 __bs.resize(__to - &__bs[0]);
3798 __r = codecvt_base::ok;
3799 }
3800 else if (__r == codecvt_base::ok)
3801 {
3802 __bs.resize(__to_nxt - &__bs[0]);
3803 }
3804 else if (__r == codecvt_base::partial)
3805 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003806 ptrdiff_t __sp = __to_nxt - &__bs[0];
3807 __bs.resize(2 * __sp);
3808 __to = &__bs[0] + __sp;
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003809 __to_end = &__bs[0] + __bs.size();
3810 }
3811 } while (__r == codecvt_base::partial);
3812 if (__r == codecvt_base::ok)
3813 return __bs;
3814 }
3815 }
Marshall Clow8fea1612016-08-25 15:09:01 +00003816
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003817 if (__byte_err_string_.empty())
Marshall Clow8fea1612016-08-25 15:09:01 +00003818 __throw_range_error("wstring_convert: to_bytes error");
3819
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003820 return __byte_err_string_;
3821}
3822
3823template <class _Codecvt, class _Elem = wchar_t, class _Tr = char_traits<_Elem> >
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +00003824class _LIBCPP_TEMPLATE_VIS wbuffer_convert
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003825 : public basic_streambuf<_Elem, _Tr>
3826{
3827public:
3828 // types:
3829 typedef _Elem char_type;
3830 typedef _Tr traits_type;
3831 typedef typename traits_type::int_type int_type;
3832 typedef typename traits_type::pos_type pos_type;
3833 typedef typename traits_type::off_type off_type;
3834 typedef typename _Codecvt::state_type state_type;
3835
3836private:
Howard Hinnant0ac182a2010-06-01 20:09:18 +00003837 char* __extbuf_;
3838 const char* __extbufnext_;
3839 const char* __extbufend_;
3840 char __extbuf_min_[8];
3841 size_t __ebs_;
3842 char_type* __intbuf_;
3843 size_t __ibs_;
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003844 streambuf* __bufptr_;
Howard Hinnant0ac182a2010-06-01 20:09:18 +00003845 _Codecvt* __cv_;
3846 state_type __st_;
3847 ios_base::openmode __cm_;
3848 bool __owns_eb_;
3849 bool __owns_ib_;
3850 bool __always_noconv_;
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003851
Howard Hinnant0ac182a2010-06-01 20:09:18 +00003852 wbuffer_convert(const wbuffer_convert&);
3853 wbuffer_convert& operator=(const wbuffer_convert&);
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003854public:
Marshall Clowccaa0fb2013-08-27 20:18:59 +00003855 _LIBCPP_EXPLICIT_AFTER_CXX11 wbuffer_convert(streambuf* __bytebuf = 0,
3856 _Codecvt* __pcvt = new _Codecvt, state_type __state = state_type());
Howard Hinnant0ac182a2010-06-01 20:09:18 +00003857 ~wbuffer_convert();
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003858
Howard Hinnant756c69b2010-09-22 16:48:34 +00003859 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003860 streambuf* rdbuf() const {return __bufptr_;}
Howard Hinnant756c69b2010-09-22 16:48:34 +00003861 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003862 streambuf* rdbuf(streambuf* __bytebuf)
3863 {
3864 streambuf* __r = __bufptr_;
3865 __bufptr_ = __bytebuf;
3866 return __r;
3867 }
3868
Howard Hinnant756c69b2010-09-22 16:48:34 +00003869 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant0ac182a2010-06-01 20:09:18 +00003870 state_type state() const {return __st_;}
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003871
3872protected:
Howard Hinnant0ac182a2010-06-01 20:09:18 +00003873 virtual int_type underflow();
3874 virtual int_type pbackfail(int_type __c = traits_type::eof());
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003875 virtual int_type overflow (int_type __c = traits_type::eof());
Howard Hinnant0ac182a2010-06-01 20:09:18 +00003876 virtual basic_streambuf<char_type, traits_type>* setbuf(char_type* __s,
3877 streamsize __n);
3878 virtual pos_type seekoff(off_type __off, ios_base::seekdir __way,
3879 ios_base::openmode __wch = ios_base::in | ios_base::out);
3880 virtual pos_type seekpos(pos_type __sp,
3881 ios_base::openmode __wch = ios_base::in | ios_base::out);
3882 virtual int sync();
3883
3884private:
3885 bool __read_mode();
3886 void __write_mode();
3887 wbuffer_convert* __close();
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003888};
3889
3890template <class _Codecvt, class _Elem, class _Tr>
Howard Hinnant0ac182a2010-06-01 20:09:18 +00003891wbuffer_convert<_Codecvt, _Elem, _Tr>::
3892 wbuffer_convert(streambuf* __bytebuf, _Codecvt* __pcvt, state_type __state)
3893 : __extbuf_(0),
3894 __extbufnext_(0),
3895 __extbufend_(0),
3896 __ebs_(0),
3897 __intbuf_(0),
3898 __ibs_(0),
3899 __bufptr_(__bytebuf),
3900 __cv_(__pcvt),
3901 __st_(__state),
3902 __cm_(0),
3903 __owns_eb_(false),
3904 __owns_ib_(false),
3905 __always_noconv_(__cv_ ? __cv_->always_noconv() : false)
3906{
3907 setbuf(0, 4096);
3908}
3909
3910template <class _Codecvt, class _Elem, class _Tr>
3911wbuffer_convert<_Codecvt, _Elem, _Tr>::~wbuffer_convert()
3912{
3913 __close();
3914 delete __cv_;
3915 if (__owns_eb_)
3916 delete [] __extbuf_;
3917 if (__owns_ib_)
3918 delete [] __intbuf_;
3919}
3920
3921template <class _Codecvt, class _Elem, class _Tr>
3922typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
3923wbuffer_convert<_Codecvt, _Elem, _Tr>::underflow()
3924{
3925 if (__cv_ == 0 || __bufptr_ == 0)
3926 return traits_type::eof();
3927 bool __initial = __read_mode();
3928 char_type __1buf;
3929 if (this->gptr() == 0)
3930 this->setg(&__1buf, &__1buf+1, &__1buf+1);
3931 const size_t __unget_sz = __initial ? 0 : min<size_t>((this->egptr() - this->eback()) / 2, 4);
3932 int_type __c = traits_type::eof();
3933 if (this->gptr() == this->egptr())
3934 {
3935 memmove(this->eback(), this->egptr() - __unget_sz, __unget_sz * sizeof(char_type));
3936 if (__always_noconv_)
3937 {
3938 streamsize __nmemb = static_cast<streamsize>(this->egptr() - this->eback() - __unget_sz);
3939 __nmemb = __bufptr_->sgetn((char*)this->eback() + __unget_sz, __nmemb);
3940 if (__nmemb != 0)
3941 {
3942 this->setg(this->eback(),
3943 this->eback() + __unget_sz,
3944 this->eback() + __unget_sz + __nmemb);
3945 __c = *this->gptr();
3946 }
3947 }
3948 else
3949 {
Eric Fiselier98e428d2016-06-19 06:58:22 +00003950 _LIBCPP_ASSERT(!(__extbufnext_ == NULL && (__extbufend_ != __extbufnext_)), "underflow moving from NULL" );
3951 if (__extbufend_ != __extbufnext_)
3952 memmove(__extbuf_, __extbufnext_, __extbufend_ - __extbufnext_);
Howard Hinnant0ac182a2010-06-01 20:09:18 +00003953 __extbufnext_ = __extbuf_ + (__extbufend_ - __extbufnext_);
3954 __extbufend_ = __extbuf_ + (__extbuf_ == __extbuf_min_ ? sizeof(__extbuf_min_) : __ebs_);
Howard Hinnantb1ad5a82011-06-30 21:18:19 +00003955 streamsize __nmemb = _VSTD::min(static_cast<streamsize>(this->egptr() - this->eback() - __unget_sz),
Howard Hinnant0ac182a2010-06-01 20:09:18 +00003956 static_cast<streamsize>(__extbufend_ - __extbufnext_));
3957 codecvt_base::result __r;
Eric Fiselier6003c772016-12-23 23:37:52 +00003958 // FIXME: Do we ever need to restore the state here?
3959 //state_type __svs = __st_;
Howard Hinnant0ac182a2010-06-01 20:09:18 +00003960 streamsize __nr = __bufptr_->sgetn(const_cast<char*>(__extbufnext_), __nmemb);
3961 if (__nr != 0)
3962 {
3963 __extbufend_ = __extbufnext_ + __nr;
3964 char_type* __inext;
3965 __r = __cv_->in(__st_, __extbuf_, __extbufend_, __extbufnext_,
3966 this->eback() + __unget_sz,
3967 this->egptr(), __inext);
3968 if (__r == codecvt_base::noconv)
3969 {
3970 this->setg((char_type*)__extbuf_, (char_type*)__extbuf_, (char_type*)__extbufend_);
3971 __c = *this->gptr();
3972 }
3973 else if (__inext != this->eback() + __unget_sz)
3974 {
3975 this->setg(this->eback(), this->eback() + __unget_sz, __inext);
3976 __c = *this->gptr();
3977 }
3978 }
3979 }
3980 }
3981 else
3982 __c = *this->gptr();
3983 if (this->eback() == &__1buf)
3984 this->setg(0, 0, 0);
3985 return __c;
3986}
3987
3988template <class _Codecvt, class _Elem, class _Tr>
3989typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
3990wbuffer_convert<_Codecvt, _Elem, _Tr>::pbackfail(int_type __c)
3991{
3992 if (__cv_ != 0 && __bufptr_ != 0 && this->eback() < this->gptr())
3993 {
3994 if (traits_type::eq_int_type(__c, traits_type::eof()))
3995 {
3996 this->gbump(-1);
3997 return traits_type::not_eof(__c);
3998 }
3999 if (traits_type::eq(traits_type::to_char_type(__c), this->gptr()[-1]))
4000 {
4001 this->gbump(-1);
4002 *this->gptr() = traits_type::to_char_type(__c);
4003 return __c;
4004 }
4005 }
4006 return traits_type::eof();
4007}
4008
4009template <class _Codecvt, class _Elem, class _Tr>
Howard Hinnant9dd7e892010-05-31 20:58:54 +00004010typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
4011wbuffer_convert<_Codecvt, _Elem, _Tr>::overflow(int_type __c)
4012{
Howard Hinnant0ac182a2010-06-01 20:09:18 +00004013 if (__cv_ == 0 || __bufptr_ == 0)
4014 return traits_type::eof();
4015 __write_mode();
4016 char_type __1buf;
4017 char_type* __pb_save = this->pbase();
4018 char_type* __epb_save = this->epptr();
4019 if (!traits_type::eq_int_type(__c, traits_type::eof()))
4020 {
4021 if (this->pptr() == 0)
4022 this->setp(&__1buf, &__1buf+1);
4023 *this->pptr() = traits_type::to_char_type(__c);
4024 this->pbump(1);
4025 }
4026 if (this->pptr() != this->pbase())
4027 {
4028 if (__always_noconv_)
4029 {
4030 streamsize __nmemb = static_cast<streamsize>(this->pptr() - this->pbase());
4031 if (__bufptr_->sputn((const char*)this->pbase(), __nmemb) != __nmemb)
4032 return traits_type::eof();
4033 }
4034 else
4035 {
4036 char* __extbe = __extbuf_;
4037 codecvt_base::result __r;
4038 do
4039 {
4040 const char_type* __e;
4041 __r = __cv_->out(__st_, this->pbase(), this->pptr(), __e,
4042 __extbuf_, __extbuf_ + __ebs_, __extbe);
4043 if (__e == this->pbase())
4044 return traits_type::eof();
4045 if (__r == codecvt_base::noconv)
4046 {
4047 streamsize __nmemb = static_cast<size_t>(this->pptr() - this->pbase());
4048 if (__bufptr_->sputn((const char*)this->pbase(), __nmemb) != __nmemb)
4049 return traits_type::eof();
4050 }
4051 else if (__r == codecvt_base::ok || __r == codecvt_base::partial)
4052 {
4053 streamsize __nmemb = static_cast<size_t>(__extbe - __extbuf_);
4054 if (__bufptr_->sputn(__extbuf_, __nmemb) != __nmemb)
4055 return traits_type::eof();
4056 if (__r == codecvt_base::partial)
4057 {
4058 this->setp((char_type*)__e, this->pptr());
4059 this->pbump(this->epptr() - this->pbase());
4060 }
4061 }
4062 else
4063 return traits_type::eof();
4064 } while (__r == codecvt_base::partial);
4065 }
4066 this->setp(__pb_save, __epb_save);
4067 }
4068 return traits_type::not_eof(__c);
4069}
4070
4071template <class _Codecvt, class _Elem, class _Tr>
4072basic_streambuf<_Elem, _Tr>*
4073wbuffer_convert<_Codecvt, _Elem, _Tr>::setbuf(char_type* __s, streamsize __n)
4074{
4075 this->setg(0, 0, 0);
4076 this->setp(0, 0);
4077 if (__owns_eb_)
4078 delete [] __extbuf_;
4079 if (__owns_ib_)
4080 delete [] __intbuf_;
4081 __ebs_ = __n;
4082 if (__ebs_ > sizeof(__extbuf_min_))
4083 {
4084 if (__always_noconv_ && __s)
4085 {
4086 __extbuf_ = (char*)__s;
4087 __owns_eb_ = false;
4088 }
4089 else
4090 {
4091 __extbuf_ = new char[__ebs_];
4092 __owns_eb_ = true;
4093 }
4094 }
4095 else
4096 {
4097 __extbuf_ = __extbuf_min_;
4098 __ebs_ = sizeof(__extbuf_min_);
4099 __owns_eb_ = false;
4100 }
4101 if (!__always_noconv_)
4102 {
4103 __ibs_ = max<streamsize>(__n, sizeof(__extbuf_min_));
4104 if (__s && __ibs_ >= sizeof(__extbuf_min_))
4105 {
4106 __intbuf_ = __s;
4107 __owns_ib_ = false;
4108 }
4109 else
4110 {
4111 __intbuf_ = new char_type[__ibs_];
4112 __owns_ib_ = true;
4113 }
4114 }
4115 else
4116 {
4117 __ibs_ = 0;
4118 __intbuf_ = 0;
4119 __owns_ib_ = false;
4120 }
4121 return this;
4122}
4123
4124template <class _Codecvt, class _Elem, class _Tr>
4125typename wbuffer_convert<_Codecvt, _Elem, _Tr>::pos_type
4126wbuffer_convert<_Codecvt, _Elem, _Tr>::seekoff(off_type __off, ios_base::seekdir __way,
4127 ios_base::openmode __om)
4128{
4129 int __width = __cv_->encoding();
4130 if (__cv_ == 0 || __bufptr_ == 0 || (__width <= 0 && __off != 0) || sync())
4131 return pos_type(off_type(-1));
Marshall Clowc2a72762015-08-27 14:37:22 +00004132 // __width > 0 || __off == 0, now check __way
4133 if (__way != ios_base::beg && __way != ios_base::cur && __way != ios_base::end)
Howard Hinnant0ac182a2010-06-01 20:09:18 +00004134 return pos_type(off_type(-1));
Howard Hinnant0ac182a2010-06-01 20:09:18 +00004135 pos_type __r = __bufptr_->pubseekoff(__width * __off, __way, __om);
4136 __r.state(__st_);
4137 return __r;
4138}
4139
4140template <class _Codecvt, class _Elem, class _Tr>
4141typename wbuffer_convert<_Codecvt, _Elem, _Tr>::pos_type
4142wbuffer_convert<_Codecvt, _Elem, _Tr>::seekpos(pos_type __sp, ios_base::openmode __wch)
4143{
4144 if (__cv_ == 0 || __bufptr_ == 0 || sync())
4145 return pos_type(off_type(-1));
4146 if (__bufptr_->pubseekpos(__sp, __wch) == pos_type(off_type(-1)))
4147 return pos_type(off_type(-1));
4148 return __sp;
4149}
4150
4151template <class _Codecvt, class _Elem, class _Tr>
4152int
4153wbuffer_convert<_Codecvt, _Elem, _Tr>::sync()
4154{
4155 if (__cv_ == 0 || __bufptr_ == 0)
4156 return 0;
4157 if (__cm_ & ios_base::out)
4158 {
4159 if (this->pptr() != this->pbase())
4160 if (overflow() == traits_type::eof())
4161 return -1;
4162 codecvt_base::result __r;
4163 do
4164 {
4165 char* __extbe;
4166 __r = __cv_->unshift(__st_, __extbuf_, __extbuf_ + __ebs_, __extbe);
4167 streamsize __nmemb = static_cast<streamsize>(__extbe - __extbuf_);
4168 if (__bufptr_->sputn(__extbuf_, __nmemb) != __nmemb)
4169 return -1;
4170 } while (__r == codecvt_base::partial);
4171 if (__r == codecvt_base::error)
4172 return -1;
4173 if (__bufptr_->pubsync())
4174 return -1;
4175 }
4176 else if (__cm_ & ios_base::in)
4177 {
4178 off_type __c;
4179 if (__always_noconv_)
4180 __c = this->egptr() - this->gptr();
4181 else
4182 {
4183 int __width = __cv_->encoding();
4184 __c = __extbufend_ - __extbufnext_;
4185 if (__width > 0)
4186 __c += __width * (this->egptr() - this->gptr());
4187 else
4188 {
4189 if (this->gptr() != this->egptr())
4190 {
4191 reverse(this->gptr(), this->egptr());
4192 codecvt_base::result __r;
4193 const char_type* __e = this->gptr();
4194 char* __extbe;
4195 do
4196 {
4197 __r = __cv_->out(__st_, __e, this->egptr(), __e,
4198 __extbuf_, __extbuf_ + __ebs_, __extbe);
4199 switch (__r)
4200 {
4201 case codecvt_base::noconv:
4202 __c += this->egptr() - this->gptr();
4203 break;
4204 case codecvt_base::ok:
4205 case codecvt_base::partial:
4206 __c += __extbe - __extbuf_;
4207 break;
4208 default:
4209 return -1;
4210 }
4211 } while (__r == codecvt_base::partial);
4212 }
4213 }
4214 }
4215 if (__bufptr_->pubseekoff(-__c, ios_base::cur, __cm_) == pos_type(off_type(-1)))
4216 return -1;
4217 this->setg(0, 0, 0);
4218 __cm_ = 0;
4219 }
4220 return 0;
4221}
4222
4223template <class _Codecvt, class _Elem, class _Tr>
4224bool
4225wbuffer_convert<_Codecvt, _Elem, _Tr>::__read_mode()
4226{
4227 if (!(__cm_ & ios_base::in))
4228 {
4229 this->setp(0, 0);
4230 if (__always_noconv_)
4231 this->setg((char_type*)__extbuf_,
4232 (char_type*)__extbuf_ + __ebs_,
4233 (char_type*)__extbuf_ + __ebs_);
4234 else
4235 this->setg(__intbuf_, __intbuf_ + __ibs_, __intbuf_ + __ibs_);
4236 __cm_ = ios_base::in;
4237 return true;
4238 }
4239 return false;
4240}
4241
4242template <class _Codecvt, class _Elem, class _Tr>
4243void
4244wbuffer_convert<_Codecvt, _Elem, _Tr>::__write_mode()
4245{
4246 if (!(__cm_ & ios_base::out))
4247 {
4248 this->setg(0, 0, 0);
4249 if (__ebs_ > sizeof(__extbuf_min_))
4250 {
4251 if (__always_noconv_)
4252 this->setp((char_type*)__extbuf_,
4253 (char_type*)__extbuf_ + (__ebs_ - 1));
4254 else
4255 this->setp(__intbuf_, __intbuf_ + (__ibs_ - 1));
4256 }
4257 else
4258 this->setp(0, 0);
4259 __cm_ = ios_base::out;
4260 }
4261}
4262
4263template <class _Codecvt, class _Elem, class _Tr>
4264wbuffer_convert<_Codecvt, _Elem, _Tr>*
4265wbuffer_convert<_Codecvt, _Elem, _Tr>::__close()
4266{
4267 wbuffer_convert* __rt = 0;
4268 if (__cv_ != 0 && __bufptr_ != 0)
4269 {
4270 __rt = this;
4271 if ((__cm_ & ios_base::out) && sync())
4272 __rt = 0;
4273 }
4274 return __rt;
Howard Hinnant9dd7e892010-05-31 20:58:54 +00004275}
4276
Howard Hinnantc51e1022010-05-11 19:42:16 +00004277_LIBCPP_END_NAMESPACE_STD
4278
Eric Fiselierf4433a32017-05-31 22:07:49 +00004279_LIBCPP_POP_MACROS
4280
Howard Hinnantc51e1022010-05-11 19:42:16 +00004281#endif // _LIBCPP_LOCALE