blob: c20e15f3e750b95ebb7548829b3c1952f800c078 [file] [log] [blame]
Howard Hinnantc51e1022010-05-11 19:42:16 +00001// -*- C++ -*-
2//===-------------------------- locale ------------------------------------===//
3//
Chandler Carruthd2012102019-01-19 10:56:40 +00004// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5// See https://llvm.org/LICENSE.txt for license information.
6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Howard Hinnantc51e1022010-05-11 19:42:16 +00007//
8//===----------------------------------------------------------------------===//
9
10#ifndef _LIBCPP_LOCALE
11#define _LIBCPP_LOCALE
12
13/*
14 locale synopsis
15
16namespace std
17{
18
19class locale
20{
21public:
22 // types:
23 class facet;
24 class id;
25
26 typedef int category;
27 static const category // values assigned here are for exposition only
28 none = 0x000,
29 collate = 0x010,
30 ctype = 0x020,
31 monetary = 0x040,
32 numeric = 0x080,
33 time = 0x100,
34 messages = 0x200,
35 all = collate | ctype | monetary | numeric | time | messages;
36
37 // construct/copy/destroy:
Howard Hinnant7c9e5732011-05-31 15:34:58 +000038 locale() noexcept;
39 locale(const locale& other) noexcept;
Howard Hinnantc51e1022010-05-11 19:42:16 +000040 explicit locale(const char* std_name);
41 explicit locale(const string& std_name);
42 locale(const locale& other, const char* std_name, category);
43 locale(const locale& other, const string& std_name, category);
44 template <class Facet> locale(const locale& other, Facet* f);
45 locale(const locale& other, const locale& one, category);
46
Howard Hinnant7c9e5732011-05-31 15:34:58 +000047 ~locale(); // not virtual
Howard Hinnantc51e1022010-05-11 19:42:16 +000048
Howard Hinnant7c9e5732011-05-31 15:34:58 +000049 const locale& operator=(const locale& other) noexcept;
Howard Hinnantc51e1022010-05-11 19:42:16 +000050
51 template <class Facet> locale combine(const locale& other) const;
52
53 // locale operations:
54 basic_string<char> name() const;
55 bool operator==(const locale& other) const;
56 bool operator!=(const locale& other) const;
57 template <class charT, class Traits, class Allocator>
58 bool operator()(const basic_string<charT,Traits,Allocator>& s1,
59 const basic_string<charT,Traits,Allocator>& s2) const;
60
61 // global locale objects:
62 static locale global(const locale&);
63 static const locale& classic();
64};
65
66template <class Facet> const Facet& use_facet(const locale&);
Howard Hinnant7c9e5732011-05-31 15:34:58 +000067template <class Facet> bool has_facet(const locale&) noexcept;
Howard Hinnantc51e1022010-05-11 19:42:16 +000068
69// 22.3.3, convenience interfaces:
70template <class charT> bool isspace (charT c, const locale& loc);
71template <class charT> bool isprint (charT c, const locale& loc);
72template <class charT> bool iscntrl (charT c, const locale& loc);
73template <class charT> bool isupper (charT c, const locale& loc);
74template <class charT> bool islower (charT c, const locale& loc);
75template <class charT> bool isalpha (charT c, const locale& loc);
76template <class charT> bool isdigit (charT c, const locale& loc);
77template <class charT> bool ispunct (charT c, const locale& loc);
78template <class charT> bool isxdigit(charT c, const locale& loc);
79template <class charT> bool isalnum (charT c, const locale& loc);
80template <class charT> bool isgraph (charT c, const locale& loc);
81template <class charT> charT toupper(charT c, const locale& loc);
82template <class charT> charT tolower(charT c, const locale& loc);
Howard Hinnant9dd7e892010-05-31 20:58:54 +000083
84template<class Codecvt, class Elem = wchar_t,
85 class Wide_alloc = allocator<Elem>,
86 class Byte_alloc = allocator<char>>
87class wstring_convert
88{
89public:
90 typedef basic_string<char, char_traits<char>, Byte_alloc> byte_string;
91 typedef basic_string<Elem, char_traits<Elem>, Wide_alloc> wide_string;
92 typedef typename Codecvt::state_type state_type;
93 typedef typename wide_string::traits_type::int_type int_type;
94
Marek Kurdejcd0bd6a2021-01-19 08:21:09 +010095 wstring_convert(Codecvt* pcvt = new Codecvt); // before C++14
96 explicit wstring_convert(Codecvt* pcvt = new Codecvt); // before C++20
97 wstring_convert() : wstring_convert(new Codecvt) {} // C++20
98 explicit wstring_convert(Codecvt* pcvt); // C++20
99
Howard Hinnant9dd7e892010-05-31 20:58:54 +0000100 wstring_convert(Codecvt* pcvt, state_type state);
Marshall Clowccaa0fb2013-08-27 20:18:59 +0000101 explicit wstring_convert(const byte_string& byte_err, // explicit in C++14
Howard Hinnant9dd7e892010-05-31 20:58:54 +0000102 const wide_string& wide_err = wide_string());
Marshall Clowccaa0fb2013-08-27 20:18:59 +0000103 wstring_convert(const wstring_convert&) = delete; // C++14
104 wstring_convert & operator=(const wstring_convert &) = delete; // C++14
Howard Hinnant9dd7e892010-05-31 20:58:54 +0000105 ~wstring_convert();
106
107 wide_string from_bytes(char byte);
108 wide_string from_bytes(const char* ptr);
109 wide_string from_bytes(const byte_string& str);
110 wide_string from_bytes(const char* first, const char* last);
111
112 byte_string to_bytes(Elem wchar);
113 byte_string to_bytes(const Elem* wptr);
114 byte_string to_bytes(const wide_string& wstr);
115 byte_string to_bytes(const Elem* first, const Elem* last);
116
Marshall Clowccaa0fb2013-08-27 20:18:59 +0000117 size_t converted() const; // noexcept in C++14
Howard Hinnant9dd7e892010-05-31 20:58:54 +0000118 state_type state() const;
119};
120
Howard Hinnantc51e1022010-05-11 19:42:16 +0000121template <class Codecvt, class Elem = wchar_t, class Tr = char_traits<Elem>>
Howard Hinnant9dd7e892010-05-31 20:58:54 +0000122class wbuffer_convert
123 : public basic_streambuf<Elem, Tr>
124{
125public:
126 typedef typename Tr::state_type state_type;
127
Marek Kurdejcd0bd6a2021-01-19 08:21:09 +0100128 wbuffer_convert(streambuf* bytebuf = 0, Codecvt* pcvt = new Codecvt,
129 state_type state = state_type()); // before C++14
130 explicit wbuffer_convert(streambuf* bytebuf = nullptr, Codecvt* pcvt = new Codecvt,
131 state_type state = state_type()); // before C++20
132 wbuffer_convert() : wbuffer_convert(nullptr) {} // C++20
133 explicit wbuffer_convert(streambuf* bytebuf, Codecvt* pcvt = new Codecvt,
134 state_type state = state_type()); // C++20
135
Marshall Clowccaa0fb2013-08-27 20:18:59 +0000136 wbuffer_convert(const wbuffer_convert&) = delete; // C++14
137 wbuffer_convert & operator=(const wbuffer_convert &) = delete; // C++14
138 ~wbuffer_convert(); // C++14
Louis Dionne173f29e2019-05-29 16:01:36 +0000139
Howard Hinnant9dd7e892010-05-31 20:58:54 +0000140 streambuf* rdbuf() const;
141 streambuf* rdbuf(streambuf* bytebuf);
142
143 state_type state() const;
144};
Howard Hinnantc51e1022010-05-11 19:42:16 +0000145
146// 22.4.1 and 22.4.1.3, ctype:
147class ctype_base;
148template <class charT> class ctype;
149template <> class ctype<char>; // specialization
150template <class charT> class ctype_byname;
151template <> class ctype_byname<char>; // specialization
152
153class codecvt_base;
154template <class internT, class externT, class stateT> class codecvt;
155template <class internT, class externT, class stateT> class codecvt_byname;
156
157// 22.4.2 and 22.4.3, numeric:
158template <class charT, class InputIterator> class num_get;
159template <class charT, class OutputIterator> class num_put;
160template <class charT> class numpunct;
161template <class charT> class numpunct_byname;
162
163// 22.4.4, col lation:
164template <class charT> class collate;
165template <class charT> class collate_byname;
166
167// 22.4.5, date and time:
168class time_base;
169template <class charT, class InputIterator> class time_get;
170template <class charT, class InputIterator> class time_get_byname;
171template <class charT, class OutputIterator> class time_put;
172template <class charT, class OutputIterator> class time_put_byname;
173
174// 22.4.6, money:
175class money_base;
176template <class charT, class InputIterator> class money_get;
177template <class charT, class OutputIterator> class money_put;
178template <class charT, bool Intl> class moneypunct;
179template <class charT, bool Intl> class moneypunct_byname;
180
181// 22.4.7, message retrieval:
182class messages_base;
183template <class charT> class messages;
184template <class charT> class messages_byname;
185
186} // std
187
188*/
189
190#include <__config>
Eric Fiselier98e428d2016-06-19 06:58:22 +0000191#include <__debug>
Arthur O'Dwyeref181602021-05-19 11:57:04 -0400192#include <__locale>
Howard Hinnantc51e1022010-05-11 19:42:16 +0000193#include <algorithm>
Marshall Clowdde4bfe2013-03-18 17:45:34 +0000194#ifndef __APPLE__
Arthur O'Dwyeref181602021-05-19 11:57:04 -0400195# include <cstdarg>
Howard Hinnant155c2af2010-05-24 17:49:41 +0000196#endif
Arthur O'Dwyeref181602021-05-19 11:57:04 -0400197#include <cstdio>
Howard Hinnantc51e1022010-05-11 19:42:16 +0000198#include <cstdlib>
199#include <ctime>
Arthur O'Dwyeref181602021-05-19 11:57:04 -0400200#include <ios>
201#include <iterator>
202#include <limits>
203#include <memory>
204#include <streambuf>
205#include <version>
Mara Sophie Grosch60cbba82021-04-12 14:19:51 -0400206
207#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
208// Most unix variants have catopen. These are the specific ones that don't.
209# if !defined(__BIONIC__) && !defined(_NEWLIB_VERSION)
210# define _LIBCPP_HAS_CATOPEN 1
211# include <nl_types.h>
212# endif
Marshall Clow3477ec92014-07-10 15:20:28 +0000213#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000214
Ben Craig3756b922016-03-09 15:39:39 +0000215#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
216#include <__bsd_locale_defaults.h>
217#else
218#include <__bsd_locale_fallbacks.h>
219#endif
220
Eric Fiselierf4433a32017-05-31 22:07:49 +0000221#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
222#pragma GCC system_header
223#endif
224
225_LIBCPP_PUSH_MACROS
226#include <__undef_macros>
227
228
Howard Hinnantc51e1022010-05-11 19:42:16 +0000229_LIBCPP_BEGIN_NAMESPACE_STD
230
Marshall Clow82378c02013-03-18 19:34:07 +0000231#if defined(__APPLE__) || defined(__FreeBSD__)
Howard Hinnant1ab52da2011-09-28 21:05:01 +0000232# define _LIBCPP_GET_C_LOCALE 0
Louis Dionne59426ee2021-08-24 11:40:05 -0400233#elif defined(__NetBSD__)
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000234# define _LIBCPP_GET_C_LOCALE LC_C_LOCALE
Howard Hinnant1ab52da2011-09-28 21:05:01 +0000235#else
236# define _LIBCPP_GET_C_LOCALE __cloc()
Howard Hinnantf312e3e2011-09-28 23:39:33 +0000237 // Get the C locale object
Howard Hinnanta37d3cf2013-08-12 18:38:34 +0000238 _LIBCPP_FUNC_VIS locale_t __cloc();
Howard Hinnantf312e3e2011-09-28 23:39:33 +0000239#define __cloc_defined
Howard Hinnant1ab52da2011-09-28 21:05:01 +0000240#endif
241
Howard Hinnantc51e1022010-05-11 19:42:16 +0000242// __scan_keyword
243// Scans [__b, __e) until a match is found in the basic_strings range
244// [__kb, __ke) or until it can be shown that there is no match in [__kb, __ke).
245// __b will be incremented (visibly), consuming CharT until a match is found
246// or proved to not exist. A keyword may be "", in which will match anything.
247// If one keyword is a prefix of another, and the next CharT in the input
248// might match another keyword, the algorithm will attempt to find the longest
249// matching keyword. If the longer matching keyword ends up not matching, then
250// no keyword match is found. If no keyword match is found, __ke is returned
251// and failbit is set in __err.
252// Else an iterator pointing to the matching keyword is found. If more than
253// one keyword matches, an iterator to the first matching keyword is returned.
Alp Tokerb8a95f52014-05-15 11:27:39 +0000254// If on exit __b == __e, eofbit is set in __err. If __case_sensitive is false,
Howard Hinnantc51e1022010-05-11 19:42:16 +0000255// __ct is used to force to lower case before comparing characters.
256// Examples:
257// Keywords: "a", "abb"
258// If the input is "a", the first keyword matches and eofbit is set.
259// If the input is "abc", no match is found and "ab" are consumed.
260template <class _InputIterator, class _ForwardIterator, class _Ctype>
261_LIBCPP_HIDDEN
262_ForwardIterator
263__scan_keyword(_InputIterator& __b, _InputIterator __e,
264 _ForwardIterator __kb, _ForwardIterator __ke,
265 const _Ctype& __ct, ios_base::iostate& __err,
266 bool __case_sensitive = true)
267{
268 typedef typename iterator_traits<_InputIterator>::value_type _CharT;
Howard Hinnant28b24882011-12-01 20:21:04 +0000269 size_t __nkw = static_cast<size_t>(_VSTD::distance(__kb, __ke));
Howard Hinnantc51e1022010-05-11 19:42:16 +0000270 const unsigned char __doesnt_match = '\0';
271 const unsigned char __might_match = '\1';
272 const unsigned char __does_match = '\2';
273 unsigned char __statbuf[100];
274 unsigned char* __status = __statbuf;
Bruce Mitchener170d8972020-11-24 12:53:53 -0500275 unique_ptr<unsigned char, void(*)(void*)> __stat_hold(nullptr, free);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000276 if (__nkw > sizeof(__statbuf))
277 {
278 __status = (unsigned char*)malloc(__nkw);
Bruce Mitchener170d8972020-11-24 12:53:53 -0500279 if (__status == nullptr)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000280 __throw_bad_alloc();
281 __stat_hold.reset(__status);
282 }
283 size_t __n_might_match = __nkw; // At this point, any keyword might match
284 size_t __n_does_match = 0; // but none of them definitely do
285 // Initialize all statuses to __might_match, except for "" keywords are __does_match
286 unsigned char* __st = __status;
Eric Fiseliera09a3b42014-10-27 19:28:20 +0000287 for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, (void) ++__st)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000288 {
289 if (!__ky->empty())
290 *__st = __might_match;
291 else
292 {
293 *__st = __does_match;
294 --__n_might_match;
295 ++__n_does_match;
296 }
297 }
298 // While there might be a match, test keywords against the next CharT
299 for (size_t __indx = 0; __b != __e && __n_might_match > 0; ++__indx)
300 {
301 // Peek at the next CharT but don't consume it
302 _CharT __c = *__b;
303 if (!__case_sensitive)
304 __c = __ct.toupper(__c);
305 bool __consume = false;
306 // For each keyword which might match, see if the __indx character is __c
307 // If a match if found, consume __c
308 // If a match is found, and that is the last character in the keyword,
309 // then that keyword matches.
310 // If the keyword doesn't match this character, then change the keyword
311 // to doesn't match
312 __st = __status;
Eric Fiseliera09a3b42014-10-27 19:28:20 +0000313 for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, (void) ++__st)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000314 {
315 if (*__st == __might_match)
316 {
317 _CharT __kc = (*__ky)[__indx];
318 if (!__case_sensitive)
319 __kc = __ct.toupper(__kc);
320 if (__c == __kc)
321 {
322 __consume = true;
323 if (__ky->size() == __indx+1)
324 {
325 *__st = __does_match;
326 --__n_might_match;
327 ++__n_does_match;
328 }
329 }
330 else
331 {
332 *__st = __doesnt_match;
333 --__n_might_match;
334 }
335 }
336 }
337 // consume if we matched a character
338 if (__consume)
339 {
340 ++__b;
341 // If we consumed a character and there might be a matched keyword that
342 // was marked matched on a previous iteration, then such keywords
343 // which are now marked as not matching.
344 if (__n_might_match + __n_does_match > 1)
345 {
346 __st = __status;
Eric Fiseliera09a3b42014-10-27 19:28:20 +0000347 for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, (void) ++__st)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000348 {
349 if (*__st == __does_match && __ky->size() != __indx+1)
350 {
351 *__st = __doesnt_match;
352 --__n_does_match;
353 }
354 }
355 }
356 }
357 }
358 // We've exited the loop because we hit eof and/or we have no more "might matches".
359 if (__b == __e)
360 __err |= ios_base::eofbit;
361 // Return the first matching result
Eric Fiseliera09a3b42014-10-27 19:28:20 +0000362 for (__st = __status; __kb != __ke; ++__kb, (void) ++__st)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000363 if (*__st == __does_match)
364 break;
365 if (__kb == __ke)
366 __err |= ios_base::failbit;
367 return __kb;
368}
369
Howard Hinnanta37d3cf2013-08-12 18:38:34 +0000370struct _LIBCPP_TYPE_VIS __num_get_base
Howard Hinnantc51e1022010-05-11 19:42:16 +0000371{
372 static const int __num_get_buf_sz = 40;
373
374 static int __get_base(ios_base&);
375 static const char __src[33];
376};
377
Howard Hinnanta37d3cf2013-08-12 18:38:34 +0000378_LIBCPP_FUNC_VIS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000379void __check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
380 ios_base::iostate& __err);
381
Howard Hinnantc51e1022010-05-11 19:42:16 +0000382template <class _CharT>
383struct __num_get
384 : protected __num_get_base
385{
Howard Hinnantc51e1022010-05-11 19:42:16 +0000386 static string __stage2_float_prep(ios_base& __iob, _CharT* __atoms, _CharT& __decimal_point,
387 _CharT& __thousands_sep);
Aditya Kumaraa866182017-06-14 23:17:45 +0000388
Howard Hinnantc51e1022010-05-11 19:42:16 +0000389 static int __stage2_float_loop(_CharT __ct, bool& __in_units, char& __exp,
390 char* __a, char*& __a_end,
391 _CharT __decimal_point, _CharT __thousands_sep,
392 const string& __grouping, unsigned* __g,
393 unsigned*& __g_end, unsigned& __dc, _CharT* __atoms);
Aditya Kumaraa866182017-06-14 23:17:45 +0000394#ifndef _LIBCPP_ABI_OPTIMIZED_LOCALE_NUM_GET
395 static string __stage2_int_prep(ios_base& __iob, _CharT* __atoms, _CharT& __thousands_sep);
396 static int __stage2_int_loop(_CharT __ct, int __base, char* __a, char*& __a_end,
397 unsigned& __dc, _CharT __thousands_sep, const string& __grouping,
398 unsigned* __g, unsigned*& __g_end, _CharT* __atoms);
399
400#else
401 static string __stage2_int_prep(ios_base& __iob, _CharT& __thousands_sep)
402 {
403 locale __loc = __iob.getloc();
404 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
405 __thousands_sep = __np.thousands_sep();
406 return __np.grouping();
407 }
408
409 const _CharT* __do_widen(ios_base& __iob, _CharT* __atoms) const
410 {
411 return __do_widen_p(__iob, __atoms);
412 }
413
414
415 static int __stage2_int_loop(_CharT __ct, int __base, char* __a, char*& __a_end,
416 unsigned& __dc, _CharT __thousands_sep, const string& __grouping,
417 unsigned* __g, unsigned*& __g_end, const _CharT* __atoms);
418private:
419 template<typename T>
420 const T* __do_widen_p(ios_base& __iob, T* __atoms) const
421 {
422 locale __loc = __iob.getloc();
423 use_facet<ctype<T> >(__loc).widen(__src, __src + 26, __atoms);
424 return __atoms;
425 }
426
427 const char* __do_widen_p(ios_base& __iob, char* __atoms) const
428 {
429 (void)__iob;
430 (void)__atoms;
431 return __src;
432 }
433#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000434};
435
Aditya Kumaraa866182017-06-14 23:17:45 +0000436#ifndef _LIBCPP_ABI_OPTIMIZED_LOCALE_NUM_GET
Howard Hinnantc51e1022010-05-11 19:42:16 +0000437template <class _CharT>
438string
439__num_get<_CharT>::__stage2_int_prep(ios_base& __iob, _CharT* __atoms, _CharT& __thousands_sep)
440{
441 locale __loc = __iob.getloc();
442 use_facet<ctype<_CharT> >(__loc).widen(__src, __src + 26, __atoms);
443 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
444 __thousands_sep = __np.thousands_sep();
445 return __np.grouping();
446}
Aditya Kumaraa866182017-06-14 23:17:45 +0000447#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000448
449template <class _CharT>
450string
451__num_get<_CharT>::__stage2_float_prep(ios_base& __iob, _CharT* __atoms, _CharT& __decimal_point,
452 _CharT& __thousands_sep)
453{
454 locale __loc = __iob.getloc();
455 use_facet<ctype<_CharT> >(__loc).widen(__src, __src + 32, __atoms);
456 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
457 __decimal_point = __np.decimal_point();
458 __thousands_sep = __np.thousands_sep();
459 return __np.grouping();
460}
461
462template <class _CharT>
463int
Aditya Kumaraa866182017-06-14 23:17:45 +0000464#ifndef _LIBCPP_ABI_OPTIMIZED_LOCALE_NUM_GET
Howard Hinnantc51e1022010-05-11 19:42:16 +0000465__num_get<_CharT>::__stage2_int_loop(_CharT __ct, int __base, char* __a, char*& __a_end,
466 unsigned& __dc, _CharT __thousands_sep, const string& __grouping,
467 unsigned* __g, unsigned*& __g_end, _CharT* __atoms)
Aditya Kumaraa866182017-06-14 23:17:45 +0000468#else
469__num_get<_CharT>::__stage2_int_loop(_CharT __ct, int __base, char* __a, char*& __a_end,
470 unsigned& __dc, _CharT __thousands_sep, const string& __grouping,
471 unsigned* __g, unsigned*& __g_end, const _CharT* __atoms)
472
473#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000474{
Howard Hinnantf57b3fc2011-03-09 01:03:19 +0000475 if (__a_end == __a && (__ct == __atoms[24] || __ct == __atoms[25]))
476 {
477 *__a_end++ = __ct == __atoms[24] ? '+' : '-';
478 __dc = 0;
479 return 0;
480 }
Howard Hinnant28b24882011-12-01 20:21:04 +0000481 if (__grouping.size() != 0 && __ct == __thousands_sep)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000482 {
483 if (__g_end-__g < __num_get_buf_sz)
484 {
485 *__g_end++ = __dc;
486 __dc = 0;
487 }
488 return 0;
489 }
490 ptrdiff_t __f = find(__atoms, __atoms + 26, __ct) - __atoms;
Howard Hinnantf57b3fc2011-03-09 01:03:19 +0000491 if (__f >= 24)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000492 return -1;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000493 switch (__base)
494 {
495 case 8:
496 case 10:
497 if (__f >= __base)
Howard Hinnantf57b3fc2011-03-09 01:03:19 +0000498 return -1;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000499 break;
Howard Hinnantf57b3fc2011-03-09 01:03:19 +0000500 case 16:
501 if (__f < 22)
502 break;
503 if (__a_end != __a && __a_end - __a <= 2 && __a_end[-1] == '0')
504 {
505 __dc = 0;
506 *__a_end++ = __src[__f];
Howard Hinnantc51e1022010-05-11 19:42:16 +0000507 return 0;
Howard Hinnantf57b3fc2011-03-09 01:03:19 +0000508 }
509 return -1;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000510 }
Howard Hinnant5d4013d2013-04-15 20:40:06 +0000511 *__a_end++ = __src[__f];
Howard Hinnantc51e1022010-05-11 19:42:16 +0000512 ++__dc;
513 return 0;
514}
515
516template <class _CharT>
517int
518__num_get<_CharT>::__stage2_float_loop(_CharT __ct, bool& __in_units, char& __exp, char* __a, char*& __a_end,
519 _CharT __decimal_point, _CharT __thousands_sep, const string& __grouping,
520 unsigned* __g, unsigned*& __g_end, unsigned& __dc, _CharT* __atoms)
521{
522 if (__ct == __decimal_point)
523 {
524 if (!__in_units)
525 return -1;
526 __in_units = false;
527 *__a_end++ = '.';
528 if (__grouping.size() != 0 && __g_end-__g < __num_get_buf_sz)
529 *__g_end++ = __dc;
530 return 0;
531 }
532 if (__ct == __thousands_sep && __grouping.size() != 0)
533 {
534 if (!__in_units)
535 return -1;
536 if (__g_end-__g < __num_get_buf_sz)
537 {
538 *__g_end++ = __dc;
539 __dc = 0;
540 }
541 return 0;
542 }
543 ptrdiff_t __f = find(__atoms, __atoms + 32, __ct) - __atoms;
544 if (__f >= 32)
545 return -1;
546 char __x = __src[__f];
Howard Hinnant5132e192012-02-15 19:19:37 +0000547 if (__x == '-' || __x == '+')
548 {
Howard Hinnant21413152013-03-08 19:06:24 +0000549 if (__a_end == __a || (__a_end[-1] & 0x5F) == (__exp & 0x7F))
Howard Hinnant5132e192012-02-15 19:19:37 +0000550 {
551 *__a_end++ = __x;
552 return 0;
553 }
554 return -1;
555 }
Howard Hinnantc51e1022010-05-11 19:42:16 +0000556 if (__x == 'x' || __x == 'X')
557 __exp = 'P';
Howard Hinnant21413152013-03-08 19:06:24 +0000558 else if ((__x & 0x5F) == __exp)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000559 {
Marshall Clow5ca73ad2019-02-01 21:59:27 +0000560 __exp |= (char) 0x80;
Howard Hinnant21413152013-03-08 19:06:24 +0000561 if (__in_units)
562 {
563 __in_units = false;
564 if (__grouping.size() != 0 && __g_end-__g < __num_get_buf_sz)
565 *__g_end++ = __dc;
566 }
Howard Hinnantc51e1022010-05-11 19:42:16 +0000567 }
Howard Hinnant5d4013d2013-04-15 20:40:06 +0000568 *__a_end++ = __x;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000569 if (__f >= 22)
570 return 0;
571 ++__dc;
572 return 0;
573}
574
Louis Dionne9de5a672021-01-14 16:27:53 -0500575_LIBCPP_EXTERN_TEMPLATE_EVEN_IN_DEBUG_MODE(struct _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __num_get<char>)
Louis Dionne89258142021-08-23 15:32:36 -0400576#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Louis Dionne9de5a672021-01-14 16:27:53 -0500577_LIBCPP_EXTERN_TEMPLATE_EVEN_IN_DEBUG_MODE(struct _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __num_get<wchar_t>)
Louis Dionne89258142021-08-23 15:32:36 -0400578#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000579
580template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +0000581class _LIBCPP_TEMPLATE_VIS num_get
Howard Hinnantc51e1022010-05-11 19:42:16 +0000582 : public locale::facet,
583 private __num_get<_CharT>
584{
585public:
586 typedef _CharT char_type;
587 typedef _InputIterator iter_type;
588
Louis Dionne16fe2952018-07-11 23:14:33 +0000589 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +0000590 explicit num_get(size_t __refs = 0)
591 : locale::facet(__refs) {}
592
Louis Dionne16fe2952018-07-11 23:14:33 +0000593 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +0000594 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
595 ios_base::iostate& __err, bool& __v) const
596 {
597 return do_get(__b, __e, __iob, __err, __v);
598 }
599
Louis Dionne16fe2952018-07-11 23:14:33 +0000600 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +0000601 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
602 ios_base::iostate& __err, long& __v) const
603 {
604 return do_get(__b, __e, __iob, __err, __v);
605 }
606
Louis Dionne16fe2952018-07-11 23:14:33 +0000607 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +0000608 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
609 ios_base::iostate& __err, long long& __v) const
610 {
611 return do_get(__b, __e, __iob, __err, __v);
612 }
613
Louis Dionne16fe2952018-07-11 23:14:33 +0000614 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +0000615 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
616 ios_base::iostate& __err, unsigned short& __v) const
617 {
618 return do_get(__b, __e, __iob, __err, __v);
619 }
620
Louis Dionne16fe2952018-07-11 23:14:33 +0000621 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +0000622 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
623 ios_base::iostate& __err, unsigned int& __v) const
624 {
625 return do_get(__b, __e, __iob, __err, __v);
626 }
627
Louis Dionne16fe2952018-07-11 23:14:33 +0000628 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +0000629 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
630 ios_base::iostate& __err, unsigned long& __v) const
631 {
632 return do_get(__b, __e, __iob, __err, __v);
633 }
634
Louis Dionne16fe2952018-07-11 23:14:33 +0000635 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +0000636 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
637 ios_base::iostate& __err, unsigned long long& __v) const
638 {
639 return do_get(__b, __e, __iob, __err, __v);
640 }
641
Louis Dionne16fe2952018-07-11 23:14:33 +0000642 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +0000643 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
644 ios_base::iostate& __err, float& __v) const
645 {
646 return do_get(__b, __e, __iob, __err, __v);
647 }
648
Louis Dionne16fe2952018-07-11 23:14:33 +0000649 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +0000650 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
651 ios_base::iostate& __err, double& __v) const
652 {
653 return do_get(__b, __e, __iob, __err, __v);
654 }
655
Louis Dionne16fe2952018-07-11 23:14:33 +0000656 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +0000657 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
658 ios_base::iostate& __err, long double& __v) const
659 {
660 return do_get(__b, __e, __iob, __err, __v);
661 }
662
Louis Dionne16fe2952018-07-11 23:14:33 +0000663 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +0000664 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
665 ios_base::iostate& __err, void*& __v) const
666 {
667 return do_get(__b, __e, __iob, __err, __v);
668 }
669
670 static locale::id id;
671
672protected:
Louis Dionne16fe2952018-07-11 23:14:33 +0000673 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +0000674 ~num_get() {}
675
Marshall Clowae385382013-11-05 14:28:52 +0000676 template <class _Fp>
Shoaib Meenai69c57412017-03-02 03:02:50 +0000677 _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
678 iter_type __do_get_floating_point
Marshall Clowae385382013-11-05 14:28:52 +0000679 (iter_type __b, iter_type __e, ios_base& __iob,
680 ios_base::iostate& __err, _Fp& __v) const;
Marshall Clow96d86d82013-11-07 01:00:50 +0000681
682 template <class _Signed>
Shoaib Meenai69c57412017-03-02 03:02:50 +0000683 _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
684 iter_type __do_get_signed
Marshall Clow96d86d82013-11-07 01:00:50 +0000685 (iter_type __b, iter_type __e, ios_base& __iob,
686 ios_base::iostate& __err, _Signed& __v) const;
687
688 template <class _Unsigned>
Shoaib Meenai69c57412017-03-02 03:02:50 +0000689 _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
690 iter_type __do_get_unsigned
Marshall Clow96d86d82013-11-07 01:00:50 +0000691 (iter_type __b, iter_type __e, ios_base& __iob,
692 ios_base::iostate& __err, _Unsigned& __v) const;
693
694
695 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
696 ios_base::iostate& __err, bool& __v) const;
697
698 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
699 ios_base::iostate& __err, long& __v) const
700 { return this->__do_get_signed ( __b, __e, __iob, __err, __v ); }
701
702 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
703 ios_base::iostate& __err, long long& __v) const
704 { return this->__do_get_signed ( __b, __e, __iob, __err, __v ); }
705
706 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
707 ios_base::iostate& __err, unsigned short& __v) const
708 { return this->__do_get_unsigned ( __b, __e, __iob, __err, __v ); }
709
710 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
711 ios_base::iostate& __err, unsigned int& __v) const
712 { return this->__do_get_unsigned ( __b, __e, __iob, __err, __v ); }
713
714 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
715 ios_base::iostate& __err, unsigned long& __v) const
716 { return this->__do_get_unsigned ( __b, __e, __iob, __err, __v ); }
717
718 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
719 ios_base::iostate& __err, unsigned long long& __v) const
720 { return this->__do_get_unsigned ( __b, __e, __iob, __err, __v ); }
721
722 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
723 ios_base::iostate& __err, float& __v) const
724 { return this->__do_get_floating_point ( __b, __e, __iob, __err, __v ); }
725
726 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
727 ios_base::iostate& __err, double& __v) const
728 { return this->__do_get_floating_point ( __b, __e, __iob, __err, __v ); }
729
730 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
731 ios_base::iostate& __err, long double& __v) const
732 { return this->__do_get_floating_point ( __b, __e, __iob, __err, __v ); }
733
734 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
735 ios_base::iostate& __err, void*& __v) const;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000736};
737
738template <class _CharT, class _InputIterator>
739locale::id
740num_get<_CharT, _InputIterator>::id;
741
742template <class _Tp>
Louis Dionne9e70e362018-11-21 16:24:46 +0000743_LIBCPP_HIDDEN _Tp
Howard Hinnantc51e1022010-05-11 19:42:16 +0000744__num_get_signed_integral(const char* __a, const char* __a_end,
745 ios_base::iostate& __err, int __base)
746{
747 if (__a != __a_end)
748 {
Howard Hinnantca8923c2013-01-22 17:26:08 +0000749 typename remove_reference<decltype(errno)>::type __save_errno = errno;
Howard Hinnant05c71342011-02-25 19:52:41 +0000750 errno = 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000751 char *__p2;
Howard Hinnant1ab52da2011-09-28 21:05:01 +0000752 long long __ll = strtoll_l(__a, &__p2, __base, _LIBCPP_GET_C_LOCALE);
Howard Hinnantca8923c2013-01-22 17:26:08 +0000753 typename remove_reference<decltype(errno)>::type __current_errno = errno;
Howard Hinnant05c71342011-02-25 19:52:41 +0000754 if (__current_errno == 0)
755 errno = __save_errno;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000756 if (__p2 != __a_end)
757 {
758 __err = ios_base::failbit;
759 return 0;
760 }
Howard Hinnant05c71342011-02-25 19:52:41 +0000761 else if (__current_errno == ERANGE ||
762 __ll < numeric_limits<_Tp>::min() ||
763 numeric_limits<_Tp>::max() < __ll)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000764 {
765 __err = ios_base::failbit;
Howard Hinnant05c71342011-02-25 19:52:41 +0000766 if (__ll > 0)
767 return numeric_limits<_Tp>::max();
768 else
769 return numeric_limits<_Tp>::min();
Howard Hinnantc51e1022010-05-11 19:42:16 +0000770 }
771 return static_cast<_Tp>(__ll);
772 }
773 __err = ios_base::failbit;
774 return 0;
775}
776
777template <class _Tp>
Louis Dionne9e70e362018-11-21 16:24:46 +0000778_LIBCPP_HIDDEN _Tp
Howard Hinnantc51e1022010-05-11 19:42:16 +0000779__num_get_unsigned_integral(const char* __a, const char* __a_end,
780 ios_base::iostate& __err, int __base)
781{
782 if (__a != __a_end)
783 {
Eric Fiselierc03318c2018-03-29 01:18:53 +0000784 const bool __negate = *__a == '-';
785 if (__negate && ++__a == __a_end) {
786 __err = ios_base::failbit;
787 return 0;
Howard Hinnant05c71342011-02-25 19:52:41 +0000788 }
Howard Hinnantca8923c2013-01-22 17:26:08 +0000789 typename remove_reference<decltype(errno)>::type __save_errno = errno;
Howard Hinnant05c71342011-02-25 19:52:41 +0000790 errno = 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000791 char *__p2;
Howard Hinnant1ab52da2011-09-28 21:05:01 +0000792 unsigned long long __ll = strtoull_l(__a, &__p2, __base, _LIBCPP_GET_C_LOCALE);
Howard Hinnantca8923c2013-01-22 17:26:08 +0000793 typename remove_reference<decltype(errno)>::type __current_errno = errno;
Howard Hinnant05c71342011-02-25 19:52:41 +0000794 if (__current_errno == 0)
795 errno = __save_errno;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000796 if (__p2 != __a_end)
797 {
798 __err = ios_base::failbit;
799 return 0;
800 }
Eric Fiselierc03318c2018-03-29 01:18:53 +0000801 else if (__current_errno == ERANGE || numeric_limits<_Tp>::max() < __ll)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000802 {
803 __err = ios_base::failbit;
804 return numeric_limits<_Tp>::max();
805 }
Eric Fiselierc03318c2018-03-29 01:18:53 +0000806 _Tp __res = static_cast<_Tp>(__ll);
807 if (__negate) __res = -__res;
808 return __res;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000809 }
810 __err = ios_base::failbit;
811 return 0;
812}
813
814template <class _Tp>
Eric Fiselier98e428d2016-06-19 06:58:22 +0000815_LIBCPP_INLINE_VISIBILITY
816_Tp __do_strtod(const char* __a, char** __p2);
817
818template <>
819inline _LIBCPP_INLINE_VISIBILITY
820float __do_strtod<float>(const char* __a, char** __p2) {
821 return strtof_l(__a, __p2, _LIBCPP_GET_C_LOCALE);
822}
823
824template <>
825inline _LIBCPP_INLINE_VISIBILITY
826double __do_strtod<double>(const char* __a, char** __p2) {
827 return strtod_l(__a, __p2, _LIBCPP_GET_C_LOCALE);
828}
829
830template <>
831inline _LIBCPP_INLINE_VISIBILITY
832long double __do_strtod<long double>(const char* __a, char** __p2) {
833 return strtold_l(__a, __p2, _LIBCPP_GET_C_LOCALE);
834}
835
836template <class _Tp>
Shoaib Meenai54c6fd62016-12-24 18:05:32 +0000837_LIBCPP_HIDDEN
Howard Hinnantc51e1022010-05-11 19:42:16 +0000838_Tp
839__num_get_float(const char* __a, const char* __a_end, ios_base::iostate& __err)
840{
841 if (__a != __a_end)
842 {
Howard Hinnantc9567812013-04-13 18:19:25 +0000843 typename remove_reference<decltype(errno)>::type __save_errno = errno;
844 errno = 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000845 char *__p2;
Eric Fiselier98e428d2016-06-19 06:58:22 +0000846 _Tp __ld = __do_strtod<_Tp>(__a, &__p2);
Howard Hinnantc9567812013-04-13 18:19:25 +0000847 typename remove_reference<decltype(errno)>::type __current_errno = errno;
848 if (__current_errno == 0)
849 errno = __save_errno;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000850 if (__p2 != __a_end)
851 {
852 __err = ios_base::failbit;
853 return 0;
854 }
Howard Hinnantc9567812013-04-13 18:19:25 +0000855 else if (__current_errno == ERANGE)
856 __err = ios_base::failbit;
Eric Fiselier98e428d2016-06-19 06:58:22 +0000857 return __ld;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000858 }
859 __err = ios_base::failbit;
860 return 0;
861}
862
863template <class _CharT, class _InputIterator>
864_InputIterator
865num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
866 ios_base& __iob,
867 ios_base::iostate& __err,
868 bool& __v) const
869{
870 if ((__iob.flags() & ios_base::boolalpha) == 0)
871 {
872 long __lv = -1;
873 __b = do_get(__b, __e, __iob, __err, __lv);
874 switch (__lv)
875 {
876 case 0:
877 __v = false;
878 break;
879 case 1:
880 __v = true;
881 break;
882 default:
883 __v = true;
884 __err = ios_base::failbit;
885 break;
886 }
887 return __b;
888 }
889 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__iob.getloc());
890 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__iob.getloc());
891 typedef typename numpunct<_CharT>::string_type string_type;
892 const string_type __names[2] = {__np.truename(), __np.falsename()};
Arthur O'Dwyere75dcfa2020-11-22 13:21:11 -0500893 const string_type* __i = _VSTD::__scan_keyword(__b, __e, __names, __names+2,
894 __ct, __err);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000895 __v = __i == __names;
896 return __b;
897}
898
Marshall Clow96d86d82013-11-07 01:00:50 +0000899// signed
900
Howard Hinnantc51e1022010-05-11 19:42:16 +0000901template <class _CharT, class _InputIterator>
Marshall Clow96d86d82013-11-07 01:00:50 +0000902template <class _Signed>
Howard Hinnantc51e1022010-05-11 19:42:16 +0000903_InputIterator
Marshall Clow96d86d82013-11-07 01:00:50 +0000904num_get<_CharT, _InputIterator>::__do_get_signed(iter_type __b, iter_type __e,
Howard Hinnantc51e1022010-05-11 19:42:16 +0000905 ios_base& __iob,
906 ios_base::iostate& __err,
Marshall Clow96d86d82013-11-07 01:00:50 +0000907 _Signed& __v) const
Howard Hinnantc51e1022010-05-11 19:42:16 +0000908{
909 // Stage 1
910 int __base = this->__get_base(__iob);
911 // Stage 2
Howard Hinnantc51e1022010-05-11 19:42:16 +0000912 char_type __thousands_sep;
Aditya Kumaraa866182017-06-14 23:17:45 +0000913 const int __atoms_size = 26;
914#ifdef _LIBCPP_ABI_OPTIMIZED_LOCALE_NUM_GET
915 char_type __atoms1[__atoms_size];
916 const char_type *__atoms = this->__do_widen(__iob, __atoms1);
917 string __grouping = this->__stage2_int_prep(__iob, __thousands_sep);
918#else
919 char_type __atoms[__atoms_size];
Howard Hinnantc51e1022010-05-11 19:42:16 +0000920 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
Aditya Kumaraa866182017-06-14 23:17:45 +0000921#endif
Howard Hinnant5d4013d2013-04-15 20:40:06 +0000922 string __buf;
923 __buf.resize(__buf.capacity());
924 char* __a = &__buf[0];
Howard Hinnantc51e1022010-05-11 19:42:16 +0000925 char* __a_end = __a;
926 unsigned __g[__num_get_base::__num_get_buf_sz];
927 unsigned* __g_end = __g;
928 unsigned __dc = 0;
929 for (; __b != __e; ++__b)
Howard Hinnant5d4013d2013-04-15 20:40:06 +0000930 {
Joerg Sonnenberger7a804f62014-02-07 21:14:29 +0000931 if (__a_end == __a + __buf.size())
Howard Hinnant5d4013d2013-04-15 20:40:06 +0000932 {
933 size_t __tmp = __buf.size();
934 __buf.resize(2*__buf.size());
935 __buf.resize(__buf.capacity());
936 __a = &__buf[0];
937 __a_end = __a + __tmp;
938 }
Howard Hinnant3b6579a2010-08-22 00:02:43 +0000939 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantc51e1022010-05-11 19:42:16 +0000940 __thousands_sep, __grouping, __g, __g_end,
941 __atoms))
942 break;
Howard Hinnant5d4013d2013-04-15 20:40:06 +0000943 }
Howard Hinnantc51e1022010-05-11 19:42:16 +0000944 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
945 *__g_end++ = __dc;
946 // Stage 3
Marshall Clow96d86d82013-11-07 01:00:50 +0000947 __v = __num_get_signed_integral<_Signed>(__a, __a_end, __err, __base);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000948 // Digit grouping checked
949 __check_grouping(__grouping, __g, __g_end, __err);
950 // EOF checked
951 if (__b == __e)
952 __err |= ios_base::eofbit;
953 return __b;
954}
955
Marshall Clow96d86d82013-11-07 01:00:50 +0000956// unsigned
Howard Hinnantc51e1022010-05-11 19:42:16 +0000957
958template <class _CharT, class _InputIterator>
Marshall Clow96d86d82013-11-07 01:00:50 +0000959template <class _Unsigned>
Howard Hinnantc51e1022010-05-11 19:42:16 +0000960_InputIterator
Marshall Clow96d86d82013-11-07 01:00:50 +0000961num_get<_CharT, _InputIterator>::__do_get_unsigned(iter_type __b, iter_type __e,
Howard Hinnantc51e1022010-05-11 19:42:16 +0000962 ios_base& __iob,
963 ios_base::iostate& __err,
Marshall Clow96d86d82013-11-07 01:00:50 +0000964 _Unsigned& __v) const
Howard Hinnantc51e1022010-05-11 19:42:16 +0000965{
966 // Stage 1
967 int __base = this->__get_base(__iob);
968 // Stage 2
Howard Hinnantc51e1022010-05-11 19:42:16 +0000969 char_type __thousands_sep;
Aditya Kumaraa866182017-06-14 23:17:45 +0000970 const int __atoms_size = 26;
971#ifdef _LIBCPP_ABI_OPTIMIZED_LOCALE_NUM_GET
972 char_type __atoms1[__atoms_size];
973 const char_type *__atoms = this->__do_widen(__iob, __atoms1);
974 string __grouping = this->__stage2_int_prep(__iob, __thousands_sep);
975#else
976 char_type __atoms[__atoms_size];
Howard Hinnantc51e1022010-05-11 19:42:16 +0000977 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
Aditya Kumaraa866182017-06-14 23:17:45 +0000978#endif
Howard Hinnant5d4013d2013-04-15 20:40:06 +0000979 string __buf;
980 __buf.resize(__buf.capacity());
981 char* __a = &__buf[0];
Howard Hinnantc51e1022010-05-11 19:42:16 +0000982 char* __a_end = __a;
983 unsigned __g[__num_get_base::__num_get_buf_sz];
984 unsigned* __g_end = __g;
985 unsigned __dc = 0;
986 for (; __b != __e; ++__b)
Howard Hinnant5d4013d2013-04-15 20:40:06 +0000987 {
Joerg Sonnenberger7a804f62014-02-07 21:14:29 +0000988 if (__a_end == __a + __buf.size())
Howard Hinnant5d4013d2013-04-15 20:40:06 +0000989 {
990 size_t __tmp = __buf.size();
991 __buf.resize(2*__buf.size());
992 __buf.resize(__buf.capacity());
993 __a = &__buf[0];
994 __a_end = __a + __tmp;
995 }
Howard Hinnant3b6579a2010-08-22 00:02:43 +0000996 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantc51e1022010-05-11 19:42:16 +0000997 __thousands_sep, __grouping, __g, __g_end,
998 __atoms))
999 break;
Howard Hinnant5d4013d2013-04-15 20:40:06 +00001000 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00001001 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
1002 *__g_end++ = __dc;
1003 // Stage 3
Marshall Clow96d86d82013-11-07 01:00:50 +00001004 __v = __num_get_unsigned_integral<_Unsigned>(__a, __a_end, __err, __base);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001005 // Digit grouping checked
1006 __check_grouping(__grouping, __g, __g_end, __err);
1007 // EOF checked
1008 if (__b == __e)
1009 __err |= ios_base::eofbit;
1010 return __b;
1011}
1012
Marshall Clowae385382013-11-05 14:28:52 +00001013// floating point
1014
Howard Hinnantc51e1022010-05-11 19:42:16 +00001015template <class _CharT, class _InputIterator>
Marshall Clowae385382013-11-05 14:28:52 +00001016template <class _Fp>
Howard Hinnantc51e1022010-05-11 19:42:16 +00001017_InputIterator
Marshall Clowae385382013-11-05 14:28:52 +00001018num_get<_CharT, _InputIterator>::__do_get_floating_point(iter_type __b, iter_type __e,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001019 ios_base& __iob,
1020 ios_base::iostate& __err,
Marshall Clowae385382013-11-05 14:28:52 +00001021 _Fp& __v) const
Howard Hinnantc51e1022010-05-11 19:42:16 +00001022{
1023 // Stage 1, nothing to do
1024 // Stage 2
1025 char_type __atoms[32];
1026 char_type __decimal_point;
1027 char_type __thousands_sep;
Howard Hinnant3b6579a2010-08-22 00:02:43 +00001028 string __grouping = this->__stage2_float_prep(__iob, __atoms,
1029 __decimal_point,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001030 __thousands_sep);
Howard Hinnant5d4013d2013-04-15 20:40:06 +00001031 string __buf;
1032 __buf.resize(__buf.capacity());
1033 char* __a = &__buf[0];
Howard Hinnantc51e1022010-05-11 19:42:16 +00001034 char* __a_end = __a;
1035 unsigned __g[__num_get_base::__num_get_buf_sz];
1036 unsigned* __g_end = __g;
1037 unsigned __dc = 0;
1038 bool __in_units = true;
1039 char __exp = 'E';
1040 for (; __b != __e; ++__b)
Howard Hinnant5d4013d2013-04-15 20:40:06 +00001041 {
Joerg Sonnenberger7a804f62014-02-07 21:14:29 +00001042 if (__a_end == __a + __buf.size())
Howard Hinnant5d4013d2013-04-15 20:40:06 +00001043 {
1044 size_t __tmp = __buf.size();
1045 __buf.resize(2*__buf.size());
1046 __buf.resize(__buf.capacity());
1047 __a = &__buf[0];
1048 __a_end = __a + __tmp;
1049 }
Howard Hinnant3b6579a2010-08-22 00:02:43 +00001050 if (this->__stage2_float_loop(*__b, __in_units, __exp, __a, __a_end,
1051 __decimal_point, __thousands_sep,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001052 __grouping, __g, __g_end,
1053 __dc, __atoms))
1054 break;
Howard Hinnant5d4013d2013-04-15 20:40:06 +00001055 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00001056 if (__grouping.size() != 0 && __in_units && __g_end-__g < __num_get_base::__num_get_buf_sz)
1057 *__g_end++ = __dc;
1058 // Stage 3
Marshall Clowae385382013-11-05 14:28:52 +00001059 __v = __num_get_float<_Fp>(__a, __a_end, __err);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001060 // Digit grouping checked
1061 __check_grouping(__grouping, __g, __g_end, __err);
1062 // EOF checked
1063 if (__b == __e)
1064 __err |= ios_base::eofbit;
1065 return __b;
1066}
1067
1068template <class _CharT, class _InputIterator>
1069_InputIterator
1070num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1071 ios_base& __iob,
1072 ios_base::iostate& __err,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001073 void*& __v) const
1074{
1075 // Stage 1
1076 int __base = 16;
1077 // Stage 2
1078 char_type __atoms[26];
Howard Hinnant28b24882011-12-01 20:21:04 +00001079 char_type __thousands_sep = 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001080 string __grouping;
1081 use_facet<ctype<_CharT> >(__iob.getloc()).widen(__num_get_base::__src,
1082 __num_get_base::__src + 26, __atoms);
Howard Hinnant5d4013d2013-04-15 20:40:06 +00001083 string __buf;
1084 __buf.resize(__buf.capacity());
1085 char* __a = &__buf[0];
Howard Hinnantc51e1022010-05-11 19:42:16 +00001086 char* __a_end = __a;
1087 unsigned __g[__num_get_base::__num_get_buf_sz];
1088 unsigned* __g_end = __g;
1089 unsigned __dc = 0;
1090 for (; __b != __e; ++__b)
Howard Hinnant5d4013d2013-04-15 20:40:06 +00001091 {
Joerg Sonnenberger7a804f62014-02-07 21:14:29 +00001092 if (__a_end == __a + __buf.size())
Howard Hinnant5d4013d2013-04-15 20:40:06 +00001093 {
1094 size_t __tmp = __buf.size();
1095 __buf.resize(2*__buf.size());
1096 __buf.resize(__buf.capacity());
1097 __a = &__buf[0];
1098 __a_end = __a + __tmp;
1099 }
Howard Hinnant3b6579a2010-08-22 00:02:43 +00001100 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
1101 __thousands_sep, __grouping,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001102 __g, __g_end, __atoms))
1103 break;
Howard Hinnant5d4013d2013-04-15 20:40:06 +00001104 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00001105 // Stage 3
Marshall Clow0db963d2014-05-21 16:02:20 +00001106 __buf.resize(__a_end - __a);
Ben Craig3756b922016-03-09 15:39:39 +00001107 if (__libcpp_sscanf_l(__buf.c_str(), _LIBCPP_GET_C_LOCALE, "%p", &__v) != 1)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001108 __err = ios_base::failbit;
1109 // EOF checked
1110 if (__b == __e)
1111 __err |= ios_base::eofbit;
1112 return __b;
1113}
1114
Louis Dionne9de5a672021-01-14 16:27:53 -05001115_LIBCPP_EXTERN_TEMPLATE_EVEN_IN_DEBUG_MODE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS num_get<char>)
Louis Dionne89258142021-08-23 15:32:36 -04001116#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Louis Dionne9de5a672021-01-14 16:27:53 -05001117_LIBCPP_EXTERN_TEMPLATE_EVEN_IN_DEBUG_MODE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS num_get<wchar_t>)
Louis Dionne89258142021-08-23 15:32:36 -04001118#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001119
Howard Hinnanta37d3cf2013-08-12 18:38:34 +00001120struct _LIBCPP_TYPE_VIS __num_put_base
Howard Hinnantc51e1022010-05-11 19:42:16 +00001121{
1122protected:
1123 static void __format_int(char* __fmt, const char* __len, bool __signd,
1124 ios_base::fmtflags __flags);
1125 static bool __format_float(char* __fmt, const char* __len,
1126 ios_base::fmtflags __flags);
1127 static char* __identify_padding(char* __nb, char* __ne,
1128 const ios_base& __iob);
1129};
1130
1131template <class _CharT>
1132struct __num_put
1133 : protected __num_put_base
1134{
1135 static void __widen_and_group_int(char* __nb, char* __np, char* __ne,
1136 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1137 const locale& __loc);
1138 static void __widen_and_group_float(char* __nb, char* __np, char* __ne,
1139 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1140 const locale& __loc);
1141};
1142
1143template <class _CharT>
1144void
1145__num_put<_CharT>::__widen_and_group_int(char* __nb, char* __np, char* __ne,
1146 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1147 const locale& __loc)
1148{
1149 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> > (__loc);
1150 const numpunct<_CharT>& __npt = use_facet<numpunct<_CharT> >(__loc);
1151 string __grouping = __npt.grouping();
1152 if (__grouping.empty())
1153 {
1154 __ct.widen(__nb, __ne, __ob);
1155 __oe = __ob + (__ne - __nb);
1156 }
1157 else
1158 {
1159 __oe = __ob;
1160 char* __nf = __nb;
1161 if (*__nf == '-' || *__nf == '+')
1162 *__oe++ = __ct.widen(*__nf++);
1163 if (__ne - __nf >= 2 && __nf[0] == '0' && (__nf[1] == 'x' ||
1164 __nf[1] == 'X'))
1165 {
1166 *__oe++ = __ct.widen(*__nf++);
1167 *__oe++ = __ct.widen(*__nf++);
1168 }
1169 reverse(__nf, __ne);
1170 _CharT __thousands_sep = __npt.thousands_sep();
1171 unsigned __dc = 0;
1172 unsigned __dg = 0;
1173 for (char* __p = __nf; __p < __ne; ++__p)
1174 {
1175 if (static_cast<unsigned>(__grouping[__dg]) > 0 &&
1176 __dc == static_cast<unsigned>(__grouping[__dg]))
1177 {
1178 *__oe++ = __thousands_sep;
1179 __dc = 0;
1180 if (__dg < __grouping.size()-1)
1181 ++__dg;
1182 }
1183 *__oe++ = __ct.widen(*__p);
1184 ++__dc;
1185 }
1186 reverse(__ob + (__nf - __nb), __oe);
1187 }
1188 if (__np == __ne)
1189 __op = __oe;
1190 else
1191 __op = __ob + (__np - __nb);
1192}
1193
1194template <class _CharT>
1195void
1196__num_put<_CharT>::__widen_and_group_float(char* __nb, char* __np, char* __ne,
1197 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1198 const locale& __loc)
1199{
1200 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> > (__loc);
1201 const numpunct<_CharT>& __npt = use_facet<numpunct<_CharT> >(__loc);
1202 string __grouping = __npt.grouping();
1203 __oe = __ob;
1204 char* __nf = __nb;
1205 if (*__nf == '-' || *__nf == '+')
1206 *__oe++ = __ct.widen(*__nf++);
1207 char* __ns;
1208 if (__ne - __nf >= 2 && __nf[0] == '0' && (__nf[1] == 'x' ||
1209 __nf[1] == 'X'))
1210 {
1211 *__oe++ = __ct.widen(*__nf++);
1212 *__oe++ = __ct.widen(*__nf++);
1213 for (__ns = __nf; __ns < __ne; ++__ns)
Howard Hinnant1ab52da2011-09-28 21:05:01 +00001214 if (!isxdigit_l(*__ns, _LIBCPP_GET_C_LOCALE))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001215 break;
1216 }
1217 else
1218 {
1219 for (__ns = __nf; __ns < __ne; ++__ns)
Howard Hinnant1ab52da2011-09-28 21:05:01 +00001220 if (!isdigit_l(*__ns, _LIBCPP_GET_C_LOCALE))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001221 break;
1222 }
1223 if (__grouping.empty())
1224 {
1225 __ct.widen(__nf, __ns, __oe);
1226 __oe += __ns - __nf;
1227 }
1228 else
1229 {
1230 reverse(__nf, __ns);
1231 _CharT __thousands_sep = __npt.thousands_sep();
1232 unsigned __dc = 0;
1233 unsigned __dg = 0;
1234 for (char* __p = __nf; __p < __ns; ++__p)
1235 {
1236 if (__grouping[__dg] > 0 && __dc == static_cast<unsigned>(__grouping[__dg]))
1237 {
1238 *__oe++ = __thousands_sep;
1239 __dc = 0;
1240 if (__dg < __grouping.size()-1)
1241 ++__dg;
1242 }
1243 *__oe++ = __ct.widen(*__p);
1244 ++__dc;
1245 }
1246 reverse(__ob + (__nf - __nb), __oe);
1247 }
1248 for (__nf = __ns; __nf < __ne; ++__nf)
1249 {
1250 if (*__nf == '.')
1251 {
1252 *__oe++ = __npt.decimal_point();
1253 ++__nf;
1254 break;
1255 }
1256 else
1257 *__oe++ = __ct.widen(*__nf);
1258 }
1259 __ct.widen(__nf, __ne, __oe);
1260 __oe += __ne - __nf;
1261 if (__np == __ne)
1262 __op = __oe;
1263 else
1264 __op = __ob + (__np - __nb);
1265}
1266
Louis Dionne9de5a672021-01-14 16:27:53 -05001267_LIBCPP_EXTERN_TEMPLATE_EVEN_IN_DEBUG_MODE(struct _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __num_put<char>)
Louis Dionne89258142021-08-23 15:32:36 -04001268#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Louis Dionne9de5a672021-01-14 16:27:53 -05001269_LIBCPP_EXTERN_TEMPLATE_EVEN_IN_DEBUG_MODE(struct _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __num_put<wchar_t>)
Louis Dionne89258142021-08-23 15:32:36 -04001270#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001271
1272template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +00001273class _LIBCPP_TEMPLATE_VIS num_put
Howard Hinnantc51e1022010-05-11 19:42:16 +00001274 : public locale::facet,
1275 private __num_put<_CharT>
1276{
1277public:
1278 typedef _CharT char_type;
1279 typedef _OutputIterator iter_type;
1280
Louis Dionne16fe2952018-07-11 23:14:33 +00001281 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00001282 explicit num_put(size_t __refs = 0)
1283 : locale::facet(__refs) {}
1284
Louis Dionne16fe2952018-07-11 23:14:33 +00001285 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00001286 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1287 bool __v) const
1288 {
1289 return do_put(__s, __iob, __fl, __v);
1290 }
1291
Louis Dionne16fe2952018-07-11 23:14:33 +00001292 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00001293 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1294 long __v) const
1295 {
1296 return do_put(__s, __iob, __fl, __v);
1297 }
1298
Louis Dionne16fe2952018-07-11 23:14:33 +00001299 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00001300 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1301 long long __v) const
1302 {
1303 return do_put(__s, __iob, __fl, __v);
1304 }
1305
Louis Dionne16fe2952018-07-11 23:14:33 +00001306 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00001307 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1308 unsigned long __v) const
1309 {
1310 return do_put(__s, __iob, __fl, __v);
1311 }
1312
Louis Dionne16fe2952018-07-11 23:14:33 +00001313 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00001314 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1315 unsigned long long __v) const
1316 {
1317 return do_put(__s, __iob, __fl, __v);
1318 }
1319
Louis Dionne16fe2952018-07-11 23:14:33 +00001320 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00001321 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1322 double __v) const
1323 {
1324 return do_put(__s, __iob, __fl, __v);
1325 }
1326
Louis Dionne16fe2952018-07-11 23:14:33 +00001327 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00001328 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1329 long double __v) const
1330 {
1331 return do_put(__s, __iob, __fl, __v);
1332 }
1333
Louis Dionne16fe2952018-07-11 23:14:33 +00001334 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00001335 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1336 const void* __v) const
1337 {
1338 return do_put(__s, __iob, __fl, __v);
1339 }
1340
1341 static locale::id id;
1342
1343protected:
Louis Dionne16fe2952018-07-11 23:14:33 +00001344 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00001345 ~num_put() {}
1346
1347 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1348 bool __v) const;
1349 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1350 long __v) const;
1351 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1352 long long __v) const;
1353 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1354 unsigned long) const;
1355 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1356 unsigned long long) const;
1357 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1358 double __v) const;
1359 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1360 long double __v) const;
1361 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1362 const void* __v) const;
1363};
1364
1365template <class _CharT, class _OutputIterator>
1366locale::id
1367num_put<_CharT, _OutputIterator>::id;
1368
1369template <class _CharT, class _OutputIterator>
1370_LIBCPP_HIDDEN
1371_OutputIterator
1372__pad_and_output(_OutputIterator __s,
1373 const _CharT* __ob, const _CharT* __op, const _CharT* __oe,
1374 ios_base& __iob, _CharT __fl)
1375{
1376 streamsize __sz = __oe - __ob;
1377 streamsize __ns = __iob.width();
1378 if (__ns > __sz)
1379 __ns -= __sz;
1380 else
1381 __ns = 0;
1382 for (;__ob < __op; ++__ob, ++__s)
1383 *__s = *__ob;
1384 for (; __ns; --__ns, ++__s)
1385 *__s = __fl;
1386 for (; __ob < __oe; ++__ob, ++__s)
1387 *__s = *__ob;
1388 __iob.width(0);
1389 return __s;
1390}
1391
Howard Hinnant97955172012-09-19 19:14:15 +00001392template <class _CharT, class _Traits>
1393_LIBCPP_HIDDEN
1394ostreambuf_iterator<_CharT, _Traits>
1395__pad_and_output(ostreambuf_iterator<_CharT, _Traits> __s,
1396 const _CharT* __ob, const _CharT* __op, const _CharT* __oe,
1397 ios_base& __iob, _CharT __fl)
1398{
1399 if (__s.__sbuf_ == nullptr)
1400 return __s;
1401 streamsize __sz = __oe - __ob;
1402 streamsize __ns = __iob.width();
1403 if (__ns > __sz)
1404 __ns -= __sz;
1405 else
1406 __ns = 0;
1407 streamsize __np = __op - __ob;
1408 if (__np > 0)
1409 {
1410 if (__s.__sbuf_->sputn(__ob, __np) != __np)
1411 {
1412 __s.__sbuf_ = nullptr;
1413 return __s;
1414 }
1415 }
1416 if (__ns > 0)
1417 {
1418 basic_string<_CharT, _Traits> __sp(__ns, __fl);
1419 if (__s.__sbuf_->sputn(__sp.data(), __ns) != __ns)
1420 {
1421 __s.__sbuf_ = nullptr;
1422 return __s;
1423 }
1424 }
1425 __np = __oe - __op;
1426 if (__np > 0)
1427 {
1428 if (__s.__sbuf_->sputn(__op, __np) != __np)
1429 {
1430 __s.__sbuf_ = nullptr;
1431 return __s;
1432 }
1433 }
1434 __iob.width(0);
1435 return __s;
1436}
1437
Howard Hinnantc51e1022010-05-11 19:42:16 +00001438template <class _CharT, class _OutputIterator>
1439_OutputIterator
1440num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1441 char_type __fl, bool __v) const
1442{
1443 if ((__iob.flags() & ios_base::boolalpha) == 0)
1444 return do_put(__s, __iob, __fl, (unsigned long)__v);
1445 const numpunct<char_type>& __np = use_facet<numpunct<char_type> >(__iob.getloc());
1446 typedef typename numpunct<char_type>::string_type string_type;
Louis Dionneba400782020-10-02 15:02:52 -04001447#if _LIBCPP_DEBUG_LEVEL == 2
Howard Hinnant8ea98242013-08-23 17:37:05 +00001448 string_type __tmp(__v ? __np.truename() : __np.falsename());
1449 string_type __nm = _VSTD::move(__tmp);
1450#else
Howard Hinnantc51e1022010-05-11 19:42:16 +00001451 string_type __nm = __v ? __np.truename() : __np.falsename();
Howard Hinnant8ea98242013-08-23 17:37:05 +00001452#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001453 for (typename string_type::iterator __i = __nm.begin(); __i != __nm.end(); ++__i, ++__s)
1454 *__s = *__i;
1455 return __s;
1456}
1457
1458template <class _CharT, class _OutputIterator>
1459_OutputIterator
1460num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1461 char_type __fl, long __v) const
1462{
1463 // Stage 1 - Get number in narrow char
1464 char __fmt[6] = {'%', 0};
1465 const char* __len = "l";
1466 this->__format_int(__fmt+1, __len, true, __iob.flags());
Daniel McIntosh33dfba72021-06-02 11:44:07 -04001467 // Worst case is octal, with showbase enabled. Note that octal is always
1468 // printed as an unsigned value.
Daniel McIntosh30cb45e2021-06-08 13:59:11 -04001469 _LIBCPP_CONSTEXPR const unsigned __nbuf
1470 = (numeric_limits<unsigned long>::digits / 3) // 1 char per 3 bits
1471 + ((numeric_limits<unsigned long>::digits % 3) != 0) // round up
1472 + 2; // base prefix + terminating null character
Howard Hinnantc51e1022010-05-11 19:42:16 +00001473 char __nar[__nbuf];
Ben Craig3756b922016-03-09 15:39:39 +00001474 int __nc = __libcpp_snprintf_l(__nar, sizeof(__nar), _LIBCPP_GET_C_LOCALE, __fmt, __v);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001475 char* __ne = __nar + __nc;
1476 char* __np = this->__identify_padding(__nar, __ne, __iob);
1477 // Stage 2 - Widen __nar while adding thousands separators
1478 char_type __o[2*(__nbuf-1) - 1];
1479 char_type* __op; // pad here
1480 char_type* __oe; // end of output
1481 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1482 // [__o, __oe) contains thousands_sep'd wide number
1483 // Stage 3 & 4
1484 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1485}
1486
1487template <class _CharT, class _OutputIterator>
1488_OutputIterator
1489num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1490 char_type __fl, long long __v) const
1491{
1492 // Stage 1 - Get number in narrow char
1493 char __fmt[8] = {'%', 0};
1494 const char* __len = "ll";
1495 this->__format_int(__fmt+1, __len, true, __iob.flags());
Daniel McIntosh33dfba72021-06-02 11:44:07 -04001496 // Worst case is octal, with showbase enabled. Note that octal is always
1497 // printed as an unsigned value.
Daniel McIntosh30cb45e2021-06-08 13:59:11 -04001498 _LIBCPP_CONSTEXPR const unsigned __nbuf
1499 = (numeric_limits<unsigned long long>::digits / 3) // 1 char per 3 bits
1500 + ((numeric_limits<unsigned long long>::digits % 3) != 0) // round up
1501 + 2; // base prefix + terminating null character
Howard Hinnantc51e1022010-05-11 19:42:16 +00001502 char __nar[__nbuf];
Ben Craig3756b922016-03-09 15:39:39 +00001503 int __nc = __libcpp_snprintf_l(__nar, sizeof(__nar), _LIBCPP_GET_C_LOCALE, __fmt, __v);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001504 char* __ne = __nar + __nc;
1505 char* __np = this->__identify_padding(__nar, __ne, __iob);
1506 // Stage 2 - Widen __nar while adding thousands separators
1507 char_type __o[2*(__nbuf-1) - 1];
1508 char_type* __op; // pad here
1509 char_type* __oe; // end of output
1510 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1511 // [__o, __oe) contains thousands_sep'd wide number
1512 // Stage 3 & 4
1513 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1514}
1515
1516template <class _CharT, class _OutputIterator>
1517_OutputIterator
1518num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1519 char_type __fl, unsigned long __v) const
1520{
1521 // Stage 1 - Get number in narrow char
1522 char __fmt[6] = {'%', 0};
1523 const char* __len = "l";
1524 this->__format_int(__fmt+1, __len, false, __iob.flags());
Daniel McIntosh33dfba72021-06-02 11:44:07 -04001525 // Worst case is octal, with showbase enabled.
Daniel McIntosh30cb45e2021-06-08 13:59:11 -04001526 _LIBCPP_CONSTEXPR const unsigned __nbuf
1527 = (numeric_limits<unsigned long>::digits / 3) // 1 char per 3 bits
1528 + ((numeric_limits<unsigned long>::digits % 3) != 0) // round up
1529 + 2; // base prefix + terminating null character
Howard Hinnantc51e1022010-05-11 19:42:16 +00001530 char __nar[__nbuf];
Ben Craig3756b922016-03-09 15:39:39 +00001531 int __nc = __libcpp_snprintf_l(__nar, sizeof(__nar), _LIBCPP_GET_C_LOCALE, __fmt, __v);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001532 char* __ne = __nar + __nc;
1533 char* __np = this->__identify_padding(__nar, __ne, __iob);
1534 // Stage 2 - Widen __nar while adding thousands separators
1535 char_type __o[2*(__nbuf-1) - 1];
1536 char_type* __op; // pad here
1537 char_type* __oe; // end of output
1538 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1539 // [__o, __oe) contains thousands_sep'd wide number
1540 // Stage 3 & 4
1541 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1542}
1543
1544template <class _CharT, class _OutputIterator>
1545_OutputIterator
1546num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1547 char_type __fl, unsigned long long __v) const
1548{
1549 // Stage 1 - Get number in narrow char
1550 char __fmt[8] = {'%', 0};
1551 const char* __len = "ll";
1552 this->__format_int(__fmt+1, __len, false, __iob.flags());
Daniel McIntosh33dfba72021-06-02 11:44:07 -04001553 // Worst case is octal, with showbase enabled.
Daniel McIntosh30cb45e2021-06-08 13:59:11 -04001554 _LIBCPP_CONSTEXPR const unsigned __nbuf
1555 = (numeric_limits<unsigned long long>::digits / 3) // 1 char per 3 bits
1556 + ((numeric_limits<unsigned long long>::digits % 3) != 0) // round up
1557 + 2; // base prefix + terminating null character
Howard Hinnantc51e1022010-05-11 19:42:16 +00001558 char __nar[__nbuf];
Ben Craig3756b922016-03-09 15:39:39 +00001559 int __nc = __libcpp_snprintf_l(__nar, sizeof(__nar), _LIBCPP_GET_C_LOCALE, __fmt, __v);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001560 char* __ne = __nar + __nc;
1561 char* __np = this->__identify_padding(__nar, __ne, __iob);
1562 // Stage 2 - Widen __nar while adding thousands separators
1563 char_type __o[2*(__nbuf-1) - 1];
1564 char_type* __op; // pad here
1565 char_type* __oe; // end of output
1566 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1567 // [__o, __oe) contains thousands_sep'd wide number
1568 // Stage 3 & 4
1569 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1570}
1571
1572template <class _CharT, class _OutputIterator>
1573_OutputIterator
1574num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1575 char_type __fl, double __v) const
1576{
1577 // Stage 1 - Get number in narrow char
1578 char __fmt[8] = {'%', 0};
1579 const char* __len = "";
1580 bool __specify_precision = this->__format_float(__fmt+1, __len, __iob.flags());
1581 const unsigned __nbuf = 30;
1582 char __nar[__nbuf];
1583 char* __nb = __nar;
1584 int __nc;
1585 if (__specify_precision)
Ben Craig3756b922016-03-09 15:39:39 +00001586 __nc = __libcpp_snprintf_l(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt,
Howard Hinnant155c2af2010-05-24 17:49:41 +00001587 (int)__iob.precision(), __v);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001588 else
Ben Craig3756b922016-03-09 15:39:39 +00001589 __nc = __libcpp_snprintf_l(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Bruce Mitchener170d8972020-11-24 12:53:53 -05001590 unique_ptr<char, void(*)(void*)> __nbh(nullptr, free);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001591 if (__nc > static_cast<int>(__nbuf-1))
1592 {
1593 if (__specify_precision)
Ben Craig3756b922016-03-09 15:39:39 +00001594 __nc = __libcpp_asprintf_l(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, (int)__iob.precision(), __v);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001595 else
Ben Craig3756b922016-03-09 15:39:39 +00001596 __nc = __libcpp_asprintf_l(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Brad Smithaee2d992021-01-21 19:39:52 -05001597 if (__nc == -1)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001598 __throw_bad_alloc();
1599 __nbh.reset(__nb);
1600 }
1601 char* __ne = __nb + __nc;
1602 char* __np = this->__identify_padding(__nb, __ne, __iob);
1603 // Stage 2 - Widen __nar while adding thousands separators
1604 char_type __o[2*(__nbuf-1) - 1];
1605 char_type* __ob = __o;
1606 unique_ptr<char_type, void(*)(void*)> __obh(0, free);
1607 if (__nb != __nar)
1608 {
Howard Hinnant28b24882011-12-01 20:21:04 +00001609 __ob = (char_type*)malloc(2*static_cast<size_t>(__nc)*sizeof(char_type));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001610 if (__ob == 0)
1611 __throw_bad_alloc();
1612 __obh.reset(__ob);
1613 }
1614 char_type* __op; // pad here
1615 char_type* __oe; // end of output
1616 this->__widen_and_group_float(__nb, __np, __ne, __ob, __op, __oe, __iob.getloc());
1617 // [__o, __oe) contains thousands_sep'd wide number
1618 // Stage 3 & 4
1619 __s = __pad_and_output(__s, __ob, __op, __oe, __iob, __fl);
1620 return __s;
1621}
1622
1623template <class _CharT, class _OutputIterator>
1624_OutputIterator
1625num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1626 char_type __fl, long double __v) const
1627{
1628 // Stage 1 - Get number in narrow char
1629 char __fmt[8] = {'%', 0};
1630 const char* __len = "L";
1631 bool __specify_precision = this->__format_float(__fmt+1, __len, __iob.flags());
1632 const unsigned __nbuf = 30;
1633 char __nar[__nbuf];
1634 char* __nb = __nar;
1635 int __nc;
1636 if (__specify_precision)
Ben Craig3756b922016-03-09 15:39:39 +00001637 __nc = __libcpp_snprintf_l(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt,
Howard Hinnant155c2af2010-05-24 17:49:41 +00001638 (int)__iob.precision(), __v);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001639 else
Ben Craig3756b922016-03-09 15:39:39 +00001640 __nc = __libcpp_snprintf_l(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Bruce Mitchener170d8972020-11-24 12:53:53 -05001641 unique_ptr<char, void(*)(void*)> __nbh(nullptr, free);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001642 if (__nc > static_cast<int>(__nbuf-1))
1643 {
1644 if (__specify_precision)
Ben Craig3756b922016-03-09 15:39:39 +00001645 __nc = __libcpp_asprintf_l(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, (int)__iob.precision(), __v);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001646 else
Ben Craig3756b922016-03-09 15:39:39 +00001647 __nc = __libcpp_asprintf_l(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Brad Smithaee2d992021-01-21 19:39:52 -05001648 if (__nc == -1)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001649 __throw_bad_alloc();
1650 __nbh.reset(__nb);
1651 }
1652 char* __ne = __nb + __nc;
1653 char* __np = this->__identify_padding(__nb, __ne, __iob);
1654 // Stage 2 - Widen __nar while adding thousands separators
1655 char_type __o[2*(__nbuf-1) - 1];
1656 char_type* __ob = __o;
1657 unique_ptr<char_type, void(*)(void*)> __obh(0, free);
1658 if (__nb != __nar)
1659 {
Howard Hinnant28b24882011-12-01 20:21:04 +00001660 __ob = (char_type*)malloc(2*static_cast<size_t>(__nc)*sizeof(char_type));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001661 if (__ob == 0)
1662 __throw_bad_alloc();
1663 __obh.reset(__ob);
1664 }
1665 char_type* __op; // pad here
1666 char_type* __oe; // end of output
1667 this->__widen_and_group_float(__nb, __np, __ne, __ob, __op, __oe, __iob.getloc());
1668 // [__o, __oe) contains thousands_sep'd wide number
1669 // Stage 3 & 4
1670 __s = __pad_and_output(__s, __ob, __op, __oe, __iob, __fl);
1671 return __s;
1672}
1673
1674template <class _CharT, class _OutputIterator>
1675_OutputIterator
1676num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1677 char_type __fl, const void* __v) const
1678{
1679 // Stage 1 - Get pointer in narrow char
1680 char __fmt[6] = "%p";
1681 const unsigned __nbuf = 20;
1682 char __nar[__nbuf];
Ben Craig3756b922016-03-09 15:39:39 +00001683 int __nc = __libcpp_snprintf_l(__nar, sizeof(__nar), _LIBCPP_GET_C_LOCALE, __fmt, __v);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001684 char* __ne = __nar + __nc;
1685 char* __np = this->__identify_padding(__nar, __ne, __iob);
1686 // Stage 2 - Widen __nar
1687 char_type __o[2*(__nbuf-1) - 1];
1688 char_type* __op; // pad here
1689 char_type* __oe; // end of output
1690 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
1691 __ct.widen(__nar, __ne, __o);
1692 __oe = __o + (__ne - __nar);
1693 if (__np == __ne)
1694 __op = __oe;
1695 else
1696 __op = __o + (__np - __nar);
1697 // [__o, __oe) contains wide number
1698 // Stage 3 & 4
1699 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1700}
1701
Louis Dionne9de5a672021-01-14 16:27:53 -05001702_LIBCPP_EXTERN_TEMPLATE_EVEN_IN_DEBUG_MODE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS num_put<char>)
Louis Dionne89258142021-08-23 15:32:36 -04001703#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Louis Dionne9de5a672021-01-14 16:27:53 -05001704_LIBCPP_EXTERN_TEMPLATE_EVEN_IN_DEBUG_MODE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS num_put<wchar_t>)
Louis Dionne89258142021-08-23 15:32:36 -04001705#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001706
1707template <class _CharT, class _InputIterator>
1708_LIBCPP_HIDDEN
1709int
1710__get_up_to_n_digits(_InputIterator& __b, _InputIterator __e,
1711 ios_base::iostate& __err, const ctype<_CharT>& __ct, int __n)
1712{
1713 // Precondition: __n >= 1
1714 if (__b == __e)
1715 {
1716 __err |= ios_base::eofbit | ios_base::failbit;
1717 return 0;
1718 }
1719 // get first digit
1720 _CharT __c = *__b;
1721 if (!__ct.is(ctype_base::digit, __c))
1722 {
1723 __err |= ios_base::failbit;
1724 return 0;
1725 }
1726 int __r = __ct.narrow(__c, 0) - '0';
Eric Fiseliera09a3b42014-10-27 19:28:20 +00001727 for (++__b, (void) --__n; __b != __e && __n > 0; ++__b, (void) --__n)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001728 {
1729 // get next digit
1730 __c = *__b;
1731 if (!__ct.is(ctype_base::digit, __c))
1732 return __r;
1733 __r = __r * 10 + __ct.narrow(__c, 0) - '0';
1734 }
1735 if (__b == __e)
1736 __err |= ios_base::eofbit;
1737 return __r;
1738}
1739
Howard Hinnant8331b762013-03-06 23:30:19 +00001740class _LIBCPP_TYPE_VIS time_base
Howard Hinnantc51e1022010-05-11 19:42:16 +00001741{
1742public:
1743 enum dateorder {no_order, dmy, mdy, ymd, ydm};
1744};
1745
1746template <class _CharT>
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +00001747class _LIBCPP_TEMPLATE_VIS __time_get_c_storage
Howard Hinnantc51e1022010-05-11 19:42:16 +00001748{
1749protected:
1750 typedef basic_string<_CharT> string_type;
1751
1752 virtual const string_type* __weeks() const;
1753 virtual const string_type* __months() const;
1754 virtual const string_type* __am_pm() const;
1755 virtual const string_type& __c() const;
1756 virtual const string_type& __r() const;
1757 virtual const string_type& __x() const;
1758 virtual const string_type& __X() const;
Eric Fiselier5eb6efc2015-08-18 19:39:35 +00001759
Louis Dionne16fe2952018-07-11 23:14:33 +00001760 _LIBCPP_INLINE_VISIBILITY
Eric Fiselier5eb6efc2015-08-18 19:39:35 +00001761 ~__time_get_c_storage() {}
Howard Hinnantc51e1022010-05-11 19:42:16 +00001762};
1763
Eric Fiselierf30c0af2017-05-08 00:29:32 +00001764template <> _LIBCPP_FUNC_VIS const string* __time_get_c_storage<char>::__weeks() const;
1765template <> _LIBCPP_FUNC_VIS const string* __time_get_c_storage<char>::__months() const;
1766template <> _LIBCPP_FUNC_VIS const string* __time_get_c_storage<char>::__am_pm() const;
1767template <> _LIBCPP_FUNC_VIS const string& __time_get_c_storage<char>::__c() const;
1768template <> _LIBCPP_FUNC_VIS const string& __time_get_c_storage<char>::__r() const;
1769template <> _LIBCPP_FUNC_VIS const string& __time_get_c_storage<char>::__x() const;
1770template <> _LIBCPP_FUNC_VIS const string& __time_get_c_storage<char>::__X() const;
1771
Louis Dionne89258142021-08-23 15:32:36 -04001772#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Eric Fiselierf30c0af2017-05-08 00:29:32 +00001773template <> _LIBCPP_FUNC_VIS const wstring* __time_get_c_storage<wchar_t>::__weeks() const;
1774template <> _LIBCPP_FUNC_VIS const wstring* __time_get_c_storage<wchar_t>::__months() const;
1775template <> _LIBCPP_FUNC_VIS const wstring* __time_get_c_storage<wchar_t>::__am_pm() const;
1776template <> _LIBCPP_FUNC_VIS const wstring& __time_get_c_storage<wchar_t>::__c() const;
1777template <> _LIBCPP_FUNC_VIS const wstring& __time_get_c_storage<wchar_t>::__r() const;
1778template <> _LIBCPP_FUNC_VIS const wstring& __time_get_c_storage<wchar_t>::__x() const;
1779template <> _LIBCPP_FUNC_VIS const wstring& __time_get_c_storage<wchar_t>::__X() const;
Louis Dionne89258142021-08-23 15:32:36 -04001780#endif
Eric Fiselierf30c0af2017-05-08 00:29:32 +00001781
Howard Hinnantc51e1022010-05-11 19:42:16 +00001782template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +00001783class _LIBCPP_TEMPLATE_VIS time_get
Howard Hinnantc51e1022010-05-11 19:42:16 +00001784 : public locale::facet,
1785 public time_base,
1786 private __time_get_c_storage<_CharT>
1787{
1788public:
1789 typedef _CharT char_type;
1790 typedef _InputIterator iter_type;
1791 typedef time_base::dateorder dateorder;
1792 typedef basic_string<char_type> string_type;
1793
Louis Dionne16fe2952018-07-11 23:14:33 +00001794 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00001795 explicit time_get(size_t __refs = 0)
1796 : locale::facet(__refs) {}
1797
Louis Dionne16fe2952018-07-11 23:14:33 +00001798 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00001799 dateorder date_order() const
1800 {
1801 return this->do_date_order();
1802 }
1803
Louis Dionne16fe2952018-07-11 23:14:33 +00001804 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00001805 iter_type get_time(iter_type __b, iter_type __e, ios_base& __iob,
1806 ios_base::iostate& __err, tm* __tm) const
1807 {
1808 return do_get_time(__b, __e, __iob, __err, __tm);
1809 }
1810
Louis Dionne16fe2952018-07-11 23:14:33 +00001811 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00001812 iter_type get_date(iter_type __b, iter_type __e, ios_base& __iob,
1813 ios_base::iostate& __err, tm* __tm) const
1814 {
1815 return do_get_date(__b, __e, __iob, __err, __tm);
1816 }
1817
Louis Dionne16fe2952018-07-11 23:14:33 +00001818 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00001819 iter_type get_weekday(iter_type __b, iter_type __e, ios_base& __iob,
1820 ios_base::iostate& __err, tm* __tm) const
1821 {
1822 return do_get_weekday(__b, __e, __iob, __err, __tm);
1823 }
1824
Louis Dionne16fe2952018-07-11 23:14:33 +00001825 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00001826 iter_type get_monthname(iter_type __b, iter_type __e, ios_base& __iob,
1827 ios_base::iostate& __err, tm* __tm) const
1828 {
1829 return do_get_monthname(__b, __e, __iob, __err, __tm);
1830 }
1831
Louis Dionne16fe2952018-07-11 23:14:33 +00001832 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00001833 iter_type get_year(iter_type __b, iter_type __e, ios_base& __iob,
1834 ios_base::iostate& __err, tm* __tm) const
1835 {
1836 return do_get_year(__b, __e, __iob, __err, __tm);
1837 }
1838
Louis Dionne16fe2952018-07-11 23:14:33 +00001839 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00001840 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
1841 ios_base::iostate& __err, tm *__tm,
1842 char __fmt, char __mod = 0) const
1843 {
1844 return do_get(__b, __e, __iob, __err, __tm, __fmt, __mod);
1845 }
1846
1847 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
1848 ios_base::iostate& __err, tm* __tm,
1849 const char_type* __fmtb, const char_type* __fmte) const;
1850
1851 static locale::id id;
1852
1853protected:
Louis Dionne16fe2952018-07-11 23:14:33 +00001854 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00001855 ~time_get() {}
1856
1857 virtual dateorder do_date_order() const;
1858 virtual iter_type do_get_time(iter_type __b, iter_type __e, ios_base& __iob,
1859 ios_base::iostate& __err, tm* __tm) const;
1860 virtual iter_type do_get_date(iter_type __b, iter_type __e, ios_base& __iob,
1861 ios_base::iostate& __err, tm* __tm) const;
1862 virtual iter_type do_get_weekday(iter_type __b, iter_type __e, ios_base& __iob,
1863 ios_base::iostate& __err, tm* __tm) const;
1864 virtual iter_type do_get_monthname(iter_type __b, iter_type __e, ios_base& __iob,
1865 ios_base::iostate& __err, tm* __tm) const;
1866 virtual iter_type do_get_year(iter_type __b, iter_type __e, ios_base& __iob,
1867 ios_base::iostate& __err, tm* __tm) const;
1868 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
1869 ios_base::iostate& __err, tm* __tm,
1870 char __fmt, char __mod) const;
1871private:
1872 void __get_white_space(iter_type& __b, iter_type __e,
1873 ios_base::iostate& __err, const ctype<char_type>& __ct) const;
1874 void __get_percent(iter_type& __b, iter_type __e, ios_base::iostate& __err,
1875 const ctype<char_type>& __ct) const;
1876
1877 void __get_weekdayname(int& __m,
1878 iter_type& __b, iter_type __e,
1879 ios_base::iostate& __err,
1880 const ctype<char_type>& __ct) const;
1881 void __get_monthname(int& __m,
1882 iter_type& __b, iter_type __e,
1883 ios_base::iostate& __err,
1884 const ctype<char_type>& __ct) const;
1885 void __get_day(int& __d,
1886 iter_type& __b, iter_type __e,
1887 ios_base::iostate& __err,
1888 const ctype<char_type>& __ct) const;
1889 void __get_month(int& __m,
1890 iter_type& __b, iter_type __e,
1891 ios_base::iostate& __err,
1892 const ctype<char_type>& __ct) const;
1893 void __get_year(int& __y,
1894 iter_type& __b, iter_type __e,
1895 ios_base::iostate& __err,
1896 const ctype<char_type>& __ct) const;
1897 void __get_year4(int& __y,
1898 iter_type& __b, iter_type __e,
1899 ios_base::iostate& __err,
1900 const ctype<char_type>& __ct) const;
1901 void __get_hour(int& __d,
1902 iter_type& __b, iter_type __e,
1903 ios_base::iostate& __err,
1904 const ctype<char_type>& __ct) const;
1905 void __get_12_hour(int& __h,
1906 iter_type& __b, iter_type __e,
1907 ios_base::iostate& __err,
1908 const ctype<char_type>& __ct) const;
1909 void __get_am_pm(int& __h,
1910 iter_type& __b, iter_type __e,
1911 ios_base::iostate& __err,
1912 const ctype<char_type>& __ct) const;
1913 void __get_minute(int& __m,
1914 iter_type& __b, iter_type __e,
1915 ios_base::iostate& __err,
1916 const ctype<char_type>& __ct) const;
1917 void __get_second(int& __s,
1918 iter_type& __b, iter_type __e,
1919 ios_base::iostate& __err,
1920 const ctype<char_type>& __ct) const;
1921 void __get_weekday(int& __w,
1922 iter_type& __b, iter_type __e,
1923 ios_base::iostate& __err,
1924 const ctype<char_type>& __ct) const;
1925 void __get_day_year_num(int& __w,
1926 iter_type& __b, iter_type __e,
1927 ios_base::iostate& __err,
1928 const ctype<char_type>& __ct) const;
1929};
1930
1931template <class _CharT, class _InputIterator>
1932locale::id
1933time_get<_CharT, _InputIterator>::id;
1934
Alp Tokerb8a95f52014-05-15 11:27:39 +00001935// time_get primitives
Howard Hinnantc51e1022010-05-11 19:42:16 +00001936
1937template <class _CharT, class _InputIterator>
1938void
1939time_get<_CharT, _InputIterator>::__get_weekdayname(int& __w,
1940 iter_type& __b, iter_type __e,
1941 ios_base::iostate& __err,
1942 const ctype<char_type>& __ct) const
1943{
1944 // Note: ignoring case comes from the POSIX strptime spec
1945 const string_type* __wk = this->__weeks();
Arthur O'Dwyere75dcfa2020-11-22 13:21:11 -05001946 ptrdiff_t __i = _VSTD::__scan_keyword(__b, __e, __wk, __wk+14, __ct, __err, false) - __wk;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001947 if (__i < 14)
1948 __w = __i % 7;
1949}
1950
1951template <class _CharT, class _InputIterator>
1952void
1953time_get<_CharT, _InputIterator>::__get_monthname(int& __m,
1954 iter_type& __b, iter_type __e,
1955 ios_base::iostate& __err,
1956 const ctype<char_type>& __ct) const
1957{
1958 // Note: ignoring case comes from the POSIX strptime spec
1959 const string_type* __month = this->__months();
Arthur O'Dwyere75dcfa2020-11-22 13:21:11 -05001960 ptrdiff_t __i = _VSTD::__scan_keyword(__b, __e, __month, __month+24, __ct, __err, false) - __month;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001961 if (__i < 24)
1962 __m = __i % 12;
1963}
1964
1965template <class _CharT, class _InputIterator>
1966void
1967time_get<_CharT, _InputIterator>::__get_day(int& __d,
1968 iter_type& __b, iter_type __e,
1969 ios_base::iostate& __err,
1970 const ctype<char_type>& __ct) const
1971{
Arthur O'Dwyere75dcfa2020-11-22 13:21:11 -05001972 int __t = _VSTD::__get_up_to_n_digits(__b, __e, __err, __ct, 2);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001973 if (!(__err & ios_base::failbit) && 1 <= __t && __t <= 31)
1974 __d = __t;
1975 else
1976 __err |= ios_base::failbit;
1977}
1978
1979template <class _CharT, class _InputIterator>
1980void
1981time_get<_CharT, _InputIterator>::__get_month(int& __m,
1982 iter_type& __b, iter_type __e,
1983 ios_base::iostate& __err,
1984 const ctype<char_type>& __ct) const
1985{
1986 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2) - 1;
1987 if (!(__err & ios_base::failbit) && __t <= 11)
1988 __m = __t;
1989 else
1990 __err |= ios_base::failbit;
1991}
1992
1993template <class _CharT, class _InputIterator>
1994void
1995time_get<_CharT, _InputIterator>::__get_year(int& __y,
1996 iter_type& __b, iter_type __e,
1997 ios_base::iostate& __err,
1998 const ctype<char_type>& __ct) const
1999{
2000 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 4);
2001 if (!(__err & ios_base::failbit))
2002 {
2003 if (__t < 69)
2004 __t += 2000;
2005 else if (69 <= __t && __t <= 99)
2006 __t += 1900;
2007 __y = __t - 1900;
2008 }
2009}
2010
2011template <class _CharT, class _InputIterator>
2012void
2013time_get<_CharT, _InputIterator>::__get_year4(int& __y,
2014 iter_type& __b, iter_type __e,
2015 ios_base::iostate& __err,
2016 const ctype<char_type>& __ct) const
2017{
2018 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 4);
2019 if (!(__err & ios_base::failbit))
2020 __y = __t - 1900;
2021}
2022
2023template <class _CharT, class _InputIterator>
2024void
2025time_get<_CharT, _InputIterator>::__get_hour(int& __h,
2026 iter_type& __b, iter_type __e,
2027 ios_base::iostate& __err,
2028 const ctype<char_type>& __ct) const
2029{
2030 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2031 if (!(__err & ios_base::failbit) && __t <= 23)
2032 __h = __t;
2033 else
2034 __err |= ios_base::failbit;
2035}
2036
2037template <class _CharT, class _InputIterator>
2038void
2039time_get<_CharT, _InputIterator>::__get_12_hour(int& __h,
2040 iter_type& __b, iter_type __e,
2041 ios_base::iostate& __err,
2042 const ctype<char_type>& __ct) const
2043{
2044 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2045 if (!(__err & ios_base::failbit) && 1 <= __t && __t <= 12)
2046 __h = __t;
2047 else
2048 __err |= ios_base::failbit;
2049}
2050
2051template <class _CharT, class _InputIterator>
2052void
2053time_get<_CharT, _InputIterator>::__get_minute(int& __m,
2054 iter_type& __b, iter_type __e,
2055 ios_base::iostate& __err,
2056 const ctype<char_type>& __ct) const
2057{
2058 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2059 if (!(__err & ios_base::failbit) && __t <= 59)
2060 __m = __t;
2061 else
2062 __err |= ios_base::failbit;
2063}
2064
2065template <class _CharT, class _InputIterator>
2066void
2067time_get<_CharT, _InputIterator>::__get_second(int& __s,
2068 iter_type& __b, iter_type __e,
2069 ios_base::iostate& __err,
2070 const ctype<char_type>& __ct) const
2071{
2072 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2073 if (!(__err & ios_base::failbit) && __t <= 60)
2074 __s = __t;
2075 else
2076 __err |= ios_base::failbit;
2077}
2078
2079template <class _CharT, class _InputIterator>
2080void
2081time_get<_CharT, _InputIterator>::__get_weekday(int& __w,
2082 iter_type& __b, iter_type __e,
2083 ios_base::iostate& __err,
2084 const ctype<char_type>& __ct) const
2085{
2086 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 1);
2087 if (!(__err & ios_base::failbit) && __t <= 6)
2088 __w = __t;
2089 else
2090 __err |= ios_base::failbit;
2091}
2092
2093template <class _CharT, class _InputIterator>
2094void
2095time_get<_CharT, _InputIterator>::__get_day_year_num(int& __d,
2096 iter_type& __b, iter_type __e,
2097 ios_base::iostate& __err,
2098 const ctype<char_type>& __ct) const
2099{
2100 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 3);
2101 if (!(__err & ios_base::failbit) && __t <= 365)
2102 __d = __t;
2103 else
2104 __err |= ios_base::failbit;
2105}
2106
2107template <class _CharT, class _InputIterator>
2108void
2109time_get<_CharT, _InputIterator>::__get_white_space(iter_type& __b, iter_type __e,
2110 ios_base::iostate& __err,
2111 const ctype<char_type>& __ct) const
2112{
2113 for (; __b != __e && __ct.is(ctype_base::space, *__b); ++__b)
2114 ;
2115 if (__b == __e)
2116 __err |= ios_base::eofbit;
2117}
2118
2119template <class _CharT, class _InputIterator>
2120void
2121time_get<_CharT, _InputIterator>::__get_am_pm(int& __h,
2122 iter_type& __b, iter_type __e,
2123 ios_base::iostate& __err,
2124 const ctype<char_type>& __ct) const
2125{
2126 const string_type* __ap = this->__am_pm();
2127 if (__ap[0].size() + __ap[1].size() == 0)
2128 {
2129 __err |= ios_base::failbit;
2130 return;
2131 }
Arthur O'Dwyere75dcfa2020-11-22 13:21:11 -05002132 ptrdiff_t __i = _VSTD::__scan_keyword(__b, __e, __ap, __ap+2, __ct, __err, false) - __ap;
Howard Hinnantc51e1022010-05-11 19:42:16 +00002133 if (__i == 0 && __h == 12)
2134 __h = 0;
2135 else if (__i == 1 && __h < 12)
2136 __h += 12;
2137}
2138
2139template <class _CharT, class _InputIterator>
2140void
2141time_get<_CharT, _InputIterator>::__get_percent(iter_type& __b, iter_type __e,
2142 ios_base::iostate& __err,
2143 const ctype<char_type>& __ct) const
2144{
2145 if (__b == __e)
2146 {
2147 __err |= ios_base::eofbit | ios_base::failbit;
2148 return;
2149 }
2150 if (__ct.narrow(*__b, 0) != '%')
2151 __err |= ios_base::failbit;
2152 else if(++__b == __e)
2153 __err |= ios_base::eofbit;
2154}
2155
Alp Tokerb8a95f52014-05-15 11:27:39 +00002156// time_get end primitives
Howard Hinnantc51e1022010-05-11 19:42:16 +00002157
2158template <class _CharT, class _InputIterator>
2159_InputIterator
2160time_get<_CharT, _InputIterator>::get(iter_type __b, iter_type __e,
2161 ios_base& __iob,
2162 ios_base::iostate& __err, tm* __tm,
2163 const char_type* __fmtb, const char_type* __fmte) const
2164{
2165 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2166 __err = ios_base::goodbit;
2167 while (__fmtb != __fmte && __err == ios_base::goodbit)
2168 {
2169 if (__b == __e)
2170 {
2171 __err = ios_base::failbit;
2172 break;
2173 }
2174 if (__ct.narrow(*__fmtb, 0) == '%')
2175 {
2176 if (++__fmtb == __fmte)
2177 {
2178 __err = ios_base::failbit;
2179 break;
2180 }
2181 char __cmd = __ct.narrow(*__fmtb, 0);
2182 char __opt = '\0';
2183 if (__cmd == 'E' || __cmd == '0')
2184 {
2185 if (++__fmtb == __fmte)
2186 {
2187 __err = ios_base::failbit;
2188 break;
2189 }
2190 __opt = __cmd;
2191 __cmd = __ct.narrow(*__fmtb, 0);
2192 }
2193 __b = do_get(__b, __e, __iob, __err, __tm, __cmd, __opt);
2194 ++__fmtb;
2195 }
2196 else if (__ct.is(ctype_base::space, *__fmtb))
2197 {
2198 for (++__fmtb; __fmtb != __fmte && __ct.is(ctype_base::space, *__fmtb); ++__fmtb)
2199 ;
2200 for ( ; __b != __e && __ct.is(ctype_base::space, *__b); ++__b)
2201 ;
2202 }
2203 else if (__ct.toupper(*__b) == __ct.toupper(*__fmtb))
2204 {
2205 ++__b;
2206 ++__fmtb;
2207 }
2208 else
2209 __err = ios_base::failbit;
2210 }
2211 if (__b == __e)
2212 __err |= ios_base::eofbit;
2213 return __b;
2214}
2215
2216template <class _CharT, class _InputIterator>
2217typename time_get<_CharT, _InputIterator>::dateorder
2218time_get<_CharT, _InputIterator>::do_date_order() const
2219{
2220 return mdy;
2221}
2222
2223template <class _CharT, class _InputIterator>
2224_InputIterator
2225time_get<_CharT, _InputIterator>::do_get_time(iter_type __b, iter_type __e,
2226 ios_base& __iob,
2227 ios_base::iostate& __err,
2228 tm* __tm) const
2229{
2230 const char_type __fmt[] = {'%', 'H', ':', '%', 'M', ':', '%', 'S'};
2231 return get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2232}
2233
2234template <class _CharT, class _InputIterator>
2235_InputIterator
2236time_get<_CharT, _InputIterator>::do_get_date(iter_type __b, iter_type __e,
2237 ios_base& __iob,
2238 ios_base::iostate& __err,
2239 tm* __tm) const
2240{
Howard Hinnantc51e1022010-05-11 19:42:16 +00002241 const string_type& __fmt = this->__x();
2242 return get(__b, __e, __iob, __err, __tm, __fmt.data(), __fmt.data() + __fmt.size());
2243}
2244
2245template <class _CharT, class _InputIterator>
2246_InputIterator
2247time_get<_CharT, _InputIterator>::do_get_weekday(iter_type __b, iter_type __e,
2248 ios_base& __iob,
2249 ios_base::iostate& __err,
2250 tm* __tm) const
2251{
2252 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2253 __get_weekdayname(__tm->tm_wday, __b, __e, __err, __ct);
2254 return __b;
2255}
2256
2257template <class _CharT, class _InputIterator>
2258_InputIterator
2259time_get<_CharT, _InputIterator>::do_get_monthname(iter_type __b, iter_type __e,
2260 ios_base& __iob,
2261 ios_base::iostate& __err,
2262 tm* __tm) const
2263{
2264 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2265 __get_monthname(__tm->tm_mon, __b, __e, __err, __ct);
2266 return __b;
2267}
2268
2269template <class _CharT, class _InputIterator>
2270_InputIterator
2271time_get<_CharT, _InputIterator>::do_get_year(iter_type __b, iter_type __e,
2272 ios_base& __iob,
2273 ios_base::iostate& __err,
2274 tm* __tm) const
2275{
2276 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2277 __get_year(__tm->tm_year, __b, __e, __err, __ct);
2278 return __b;
2279}
2280
2281template <class _CharT, class _InputIterator>
2282_InputIterator
2283time_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
2284 ios_base& __iob,
2285 ios_base::iostate& __err, tm* __tm,
2286 char __fmt, char) const
2287{
2288 __err = ios_base::goodbit;
2289 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2290 switch (__fmt)
2291 {
2292 case 'a':
2293 case 'A':
2294 __get_weekdayname(__tm->tm_wday, __b, __e, __err, __ct);
2295 break;
2296 case 'b':
2297 case 'B':
2298 case 'h':
2299 __get_monthname(__tm->tm_mon, __b, __e, __err, __ct);
2300 break;
2301 case 'c':
2302 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002303 const string_type& __fm = this->__c();
2304 __b = get(__b, __e, __iob, __err, __tm, __fm.data(), __fm.data() + __fm.size());
Howard Hinnantc51e1022010-05-11 19:42:16 +00002305 }
2306 break;
2307 case 'd':
2308 case 'e':
2309 __get_day(__tm->tm_mday, __b, __e, __err, __ct);
2310 break;
2311 case 'D':
2312 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002313 const char_type __fm[] = {'%', 'm', '/', '%', 'd', '/', '%', 'y'};
2314 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm)/sizeof(__fm[0]));
Howard Hinnantc51e1022010-05-11 19:42:16 +00002315 }
2316 break;
Howard Hinnantf60ff4e2011-04-10 17:54:14 +00002317 case 'F':
2318 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002319 const char_type __fm[] = {'%', 'Y', '-', '%', 'm', '-', '%', 'd'};
2320 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm)/sizeof(__fm[0]));
Howard Hinnantf60ff4e2011-04-10 17:54:14 +00002321 }
2322 break;
Howard Hinnantc51e1022010-05-11 19:42:16 +00002323 case 'H':
2324 __get_hour(__tm->tm_hour, __b, __e, __err, __ct);
2325 break;
2326 case 'I':
2327 __get_12_hour(__tm->tm_hour, __b, __e, __err, __ct);
2328 break;
2329 case 'j':
2330 __get_day_year_num(__tm->tm_yday, __b, __e, __err, __ct);
2331 break;
2332 case 'm':
2333 __get_month(__tm->tm_mon, __b, __e, __err, __ct);
2334 break;
2335 case 'M':
2336 __get_minute(__tm->tm_min, __b, __e, __err, __ct);
2337 break;
2338 case 'n':
2339 case 't':
2340 __get_white_space(__b, __e, __err, __ct);
2341 break;
2342 case 'p':
2343 __get_am_pm(__tm->tm_hour, __b, __e, __err, __ct);
2344 break;
2345 case 'r':
2346 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002347 const char_type __fm[] = {'%', 'I', ':', '%', 'M', ':', '%', 'S', ' ', '%', 'p'};
2348 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm)/sizeof(__fm[0]));
Howard Hinnantc51e1022010-05-11 19:42:16 +00002349 }
2350 break;
2351 case 'R':
2352 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002353 const char_type __fm[] = {'%', 'H', ':', '%', 'M'};
2354 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm)/sizeof(__fm[0]));
Howard Hinnantc51e1022010-05-11 19:42:16 +00002355 }
2356 break;
2357 case 'S':
2358 __get_second(__tm->tm_sec, __b, __e, __err, __ct);
2359 break;
2360 case 'T':
2361 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002362 const char_type __fm[] = {'%', 'H', ':', '%', 'M', ':', '%', 'S'};
2363 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm)/sizeof(__fm[0]));
Howard Hinnantc51e1022010-05-11 19:42:16 +00002364 }
2365 break;
2366 case 'w':
2367 __get_weekday(__tm->tm_wday, __b, __e, __err, __ct);
2368 break;
2369 case 'x':
2370 return do_get_date(__b, __e, __iob, __err, __tm);
2371 case 'X':
2372 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002373 const string_type& __fm = this->__X();
2374 __b = get(__b, __e, __iob, __err, __tm, __fm.data(), __fm.data() + __fm.size());
Howard Hinnantc51e1022010-05-11 19:42:16 +00002375 }
2376 break;
2377 case 'y':
2378 __get_year(__tm->tm_year, __b, __e, __err, __ct);
2379 break;
2380 case 'Y':
2381 __get_year4(__tm->tm_year, __b, __e, __err, __ct);
2382 break;
2383 case '%':
2384 __get_percent(__b, __e, __err, __ct);
2385 break;
2386 default:
2387 __err |= ios_base::failbit;
2388 }
2389 return __b;
2390}
2391
Louis Dionne9de5a672021-01-14 16:27:53 -05002392_LIBCPP_EXTERN_TEMPLATE_EVEN_IN_DEBUG_MODE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_get<char>)
Louis Dionne89258142021-08-23 15:32:36 -04002393#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Louis Dionne9de5a672021-01-14 16:27:53 -05002394_LIBCPP_EXTERN_TEMPLATE_EVEN_IN_DEBUG_MODE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_get<wchar_t>)
Louis Dionne89258142021-08-23 15:32:36 -04002395#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00002396
Howard Hinnanta37d3cf2013-08-12 18:38:34 +00002397class _LIBCPP_TYPE_VIS __time_get
Howard Hinnantc51e1022010-05-11 19:42:16 +00002398{
2399protected:
2400 locale_t __loc_;
2401
2402 __time_get(const char* __nm);
2403 __time_get(const string& __nm);
2404 ~__time_get();
2405};
2406
2407template <class _CharT>
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +00002408class _LIBCPP_TEMPLATE_VIS __time_get_storage
Howard Hinnantc51e1022010-05-11 19:42:16 +00002409 : public __time_get
2410{
2411protected:
2412 typedef basic_string<_CharT> string_type;
2413
2414 string_type __weeks_[14];
2415 string_type __months_[24];
2416 string_type __am_pm_[2];
2417 string_type __c_;
2418 string_type __r_;
2419 string_type __x_;
2420 string_type __X_;
2421
2422 explicit __time_get_storage(const char* __nm);
2423 explicit __time_get_storage(const string& __nm);
2424
Louis Dionne16fe2952018-07-11 23:14:33 +00002425 _LIBCPP_INLINE_VISIBILITY ~__time_get_storage() {}
Howard Hinnantc51e1022010-05-11 19:42:16 +00002426
2427 time_base::dateorder __do_date_order() const;
2428
2429private:
2430 void init(const ctype<_CharT>&);
2431 string_type __analyze(char __fmt, const ctype<_CharT>&);
2432};
2433
Louis Dionne5254b372018-10-25 12:13:43 +00002434#define _LIBCPP_TIME_GET_STORAGE_EXPLICIT_INSTANTIATION(_CharT) \
2435template <> _LIBCPP_FUNC_VIS time_base::dateorder __time_get_storage<_CharT>::__do_date_order() const; \
2436template <> _LIBCPP_FUNC_VIS __time_get_storage<_CharT>::__time_get_storage(const char*); \
2437template <> _LIBCPP_FUNC_VIS __time_get_storage<_CharT>::__time_get_storage(const string&); \
2438template <> _LIBCPP_FUNC_VIS void __time_get_storage<_CharT>::init(const ctype<_CharT>&); \
2439template <> _LIBCPP_FUNC_VIS __time_get_storage<_CharT>::string_type __time_get_storage<_CharT>::__analyze(char, const ctype<_CharT>&); \
2440extern template _LIBCPP_FUNC_VIS time_base::dateorder __time_get_storage<_CharT>::__do_date_order() const; \
2441extern template _LIBCPP_FUNC_VIS __time_get_storage<_CharT>::__time_get_storage(const char*); \
2442extern template _LIBCPP_FUNC_VIS __time_get_storage<_CharT>::__time_get_storage(const string&); \
2443extern template _LIBCPP_FUNC_VIS void __time_get_storage<_CharT>::init(const ctype<_CharT>&); \
2444extern template _LIBCPP_FUNC_VIS __time_get_storage<_CharT>::string_type __time_get_storage<_CharT>::__analyze(char, const ctype<_CharT>&); \
2445/**/
2446
2447_LIBCPP_TIME_GET_STORAGE_EXPLICIT_INSTANTIATION(char)
2448_LIBCPP_TIME_GET_STORAGE_EXPLICIT_INSTANTIATION(wchar_t)
2449#undef _LIBCPP_TIME_GET_STORAGE_EXPLICIT_INSTANTIATION
2450
Howard Hinnantc51e1022010-05-11 19:42:16 +00002451template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +00002452class _LIBCPP_TEMPLATE_VIS time_get_byname
Howard Hinnantc51e1022010-05-11 19:42:16 +00002453 : public time_get<_CharT, _InputIterator>,
2454 private __time_get_storage<_CharT>
2455{
2456public:
2457 typedef time_base::dateorder dateorder;
2458 typedef _InputIterator iter_type;
2459 typedef _CharT char_type;
2460 typedef basic_string<char_type> string_type;
2461
Howard Hinnant756c69b2010-09-22 16:48:34 +00002462 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002463 explicit time_get_byname(const char* __nm, size_t __refs = 0)
2464 : time_get<_CharT, _InputIterator>(__refs),
2465 __time_get_storage<_CharT>(__nm) {}
Howard Hinnant756c69b2010-09-22 16:48:34 +00002466 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002467 explicit time_get_byname(const string& __nm, size_t __refs = 0)
2468 : time_get<_CharT, _InputIterator>(__refs),
2469 __time_get_storage<_CharT>(__nm) {}
2470
2471protected:
Howard Hinnant756c69b2010-09-22 16:48:34 +00002472 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002473 ~time_get_byname() {}
2474
Howard Hinnant756c69b2010-09-22 16:48:34 +00002475 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002476 virtual dateorder do_date_order() const {return this->__do_date_order();}
2477private:
Howard Hinnant756c69b2010-09-22 16:48:34 +00002478 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002479 virtual const string_type* __weeks() const {return this->__weeks_;}
Howard Hinnant756c69b2010-09-22 16:48:34 +00002480 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002481 virtual const string_type* __months() const {return this->__months_;}
Howard Hinnant756c69b2010-09-22 16:48:34 +00002482 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002483 virtual const string_type* __am_pm() const {return this->__am_pm_;}
Howard Hinnant756c69b2010-09-22 16:48:34 +00002484 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002485 virtual const string_type& __c() const {return this->__c_;}
Howard Hinnant756c69b2010-09-22 16:48:34 +00002486 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002487 virtual const string_type& __r() const {return this->__r_;}
Howard Hinnant756c69b2010-09-22 16:48:34 +00002488 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002489 virtual const string_type& __x() const {return this->__x_;}
Howard Hinnant756c69b2010-09-22 16:48:34 +00002490 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002491 virtual const string_type& __X() const {return this->__X_;}
2492};
2493
Louis Dionne9de5a672021-01-14 16:27:53 -05002494_LIBCPP_EXTERN_TEMPLATE_EVEN_IN_DEBUG_MODE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_get_byname<char>)
Louis Dionne89258142021-08-23 15:32:36 -04002495#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Louis Dionne9de5a672021-01-14 16:27:53 -05002496_LIBCPP_EXTERN_TEMPLATE_EVEN_IN_DEBUG_MODE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_get_byname<wchar_t>)
Louis Dionne89258142021-08-23 15:32:36 -04002497#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00002498
Howard Hinnanta37d3cf2013-08-12 18:38:34 +00002499class _LIBCPP_TYPE_VIS __time_put
Howard Hinnantc51e1022010-05-11 19:42:16 +00002500{
2501 locale_t __loc_;
2502protected:
Louis Dionne16fe2952018-07-11 23:14:33 +00002503 _LIBCPP_INLINE_VISIBILITY __time_put() : __loc_(_LIBCPP_GET_C_LOCALE) {}
Howard Hinnantc51e1022010-05-11 19:42:16 +00002504 __time_put(const char* __nm);
2505 __time_put(const string& __nm);
2506 ~__time_put();
2507 void __do_put(char* __nb, char*& __ne, const tm* __tm,
2508 char __fmt, char __mod) const;
2509 void __do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
2510 char __fmt, char __mod) const;
2511};
2512
2513template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +00002514class _LIBCPP_TEMPLATE_VIS time_put
Howard Hinnantc51e1022010-05-11 19:42:16 +00002515 : public locale::facet,
2516 private __time_put
2517{
2518public:
2519 typedef _CharT char_type;
2520 typedef _OutputIterator iter_type;
2521
Louis Dionne16fe2952018-07-11 23:14:33 +00002522 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002523 explicit time_put(size_t __refs = 0)
2524 : locale::facet(__refs) {}
2525
2526 iter_type put(iter_type __s, ios_base& __iob, char_type __fl, const tm* __tm,
2527 const char_type* __pb, const char_type* __pe) const;
2528
Louis Dionne16fe2952018-07-11 23:14:33 +00002529 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002530 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
2531 const tm* __tm, char __fmt, char __mod = 0) const
2532 {
2533 return do_put(__s, __iob, __fl, __tm, __fmt, __mod);
2534 }
2535
2536 static locale::id id;
2537
2538protected:
Louis Dionne16fe2952018-07-11 23:14:33 +00002539 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002540 ~time_put() {}
2541 virtual iter_type do_put(iter_type __s, ios_base&, char_type, const tm* __tm,
2542 char __fmt, char __mod) const;
2543
Louis Dionne16fe2952018-07-11 23:14:33 +00002544 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002545 explicit time_put(const char* __nm, size_t __refs)
2546 : locale::facet(__refs),
2547 __time_put(__nm) {}
Louis Dionne16fe2952018-07-11 23:14:33 +00002548 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002549 explicit time_put(const string& __nm, size_t __refs)
2550 : locale::facet(__refs),
2551 __time_put(__nm) {}
2552};
2553
2554template <class _CharT, class _OutputIterator>
2555locale::id
2556time_put<_CharT, _OutputIterator>::id;
2557
2558template <class _CharT, class _OutputIterator>
2559_OutputIterator
2560time_put<_CharT, _OutputIterator>::put(iter_type __s, ios_base& __iob,
2561 char_type __fl, const tm* __tm,
2562 const char_type* __pb,
2563 const char_type* __pe) const
2564{
2565 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2566 for (; __pb != __pe; ++__pb)
2567 {
2568 if (__ct.narrow(*__pb, 0) == '%')
2569 {
2570 if (++__pb == __pe)
2571 {
2572 *__s++ = __pb[-1];
2573 break;
2574 }
2575 char __mod = 0;
2576 char __fmt = __ct.narrow(*__pb, 0);
2577 if (__fmt == 'E' || __fmt == 'O')
2578 {
2579 if (++__pb == __pe)
2580 {
2581 *__s++ = __pb[-2];
2582 *__s++ = __pb[-1];
2583 break;
2584 }
2585 __mod = __fmt;
2586 __fmt = __ct.narrow(*__pb, 0);
2587 }
2588 __s = do_put(__s, __iob, __fl, __tm, __fmt, __mod);
2589 }
2590 else
2591 *__s++ = *__pb;
2592 }
2593 return __s;
2594}
2595
2596template <class _CharT, class _OutputIterator>
2597_OutputIterator
Howard Hinnant28b24882011-12-01 20:21:04 +00002598time_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00002599 char_type, const tm* __tm,
2600 char __fmt, char __mod) const
2601{
2602 char_type __nar[100];
2603 char_type* __nb = __nar;
2604 char_type* __ne = __nb + 100;
2605 __do_put(__nb, __ne, __tm, __fmt, __mod);
Howard Hinnantb1ad5a82011-06-30 21:18:19 +00002606 return _VSTD::copy(__nb, __ne, __s);
Howard Hinnantc51e1022010-05-11 19:42:16 +00002607}
2608
Louis Dionne9de5a672021-01-14 16:27:53 -05002609_LIBCPP_EXTERN_TEMPLATE_EVEN_IN_DEBUG_MODE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_put<char>)
Louis Dionne89258142021-08-23 15:32:36 -04002610#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Louis Dionne9de5a672021-01-14 16:27:53 -05002611_LIBCPP_EXTERN_TEMPLATE_EVEN_IN_DEBUG_MODE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_put<wchar_t>)
Louis Dionne89258142021-08-23 15:32:36 -04002612#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00002613
2614template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +00002615class _LIBCPP_TEMPLATE_VIS time_put_byname
Howard Hinnantc51e1022010-05-11 19:42:16 +00002616 : public time_put<_CharT, _OutputIterator>
2617{
2618public:
Louis Dionne16fe2952018-07-11 23:14:33 +00002619 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002620 explicit time_put_byname(const char* __nm, size_t __refs = 0)
2621 : time_put<_CharT, _OutputIterator>(__nm, __refs) {}
2622
Louis Dionne16fe2952018-07-11 23:14:33 +00002623 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002624 explicit time_put_byname(const string& __nm, size_t __refs = 0)
2625 : time_put<_CharT, _OutputIterator>(__nm, __refs) {}
2626
2627protected:
Louis Dionne16fe2952018-07-11 23:14:33 +00002628 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002629 ~time_put_byname() {}
2630};
2631
Louis Dionne9de5a672021-01-14 16:27:53 -05002632_LIBCPP_EXTERN_TEMPLATE_EVEN_IN_DEBUG_MODE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_put_byname<char>)
Louis Dionne89258142021-08-23 15:32:36 -04002633#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Louis Dionne9de5a672021-01-14 16:27:53 -05002634_LIBCPP_EXTERN_TEMPLATE_EVEN_IN_DEBUG_MODE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_put_byname<wchar_t>)
Louis Dionne89258142021-08-23 15:32:36 -04002635#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00002636
2637// money_base
2638
Howard Hinnant8331b762013-03-06 23:30:19 +00002639class _LIBCPP_TYPE_VIS money_base
Howard Hinnantc51e1022010-05-11 19:42:16 +00002640{
2641public:
2642 enum part {none, space, symbol, sign, value};
2643 struct pattern {char field[4];};
2644
Louis Dionne16fe2952018-07-11 23:14:33 +00002645 _LIBCPP_INLINE_VISIBILITY money_base() {}
Howard Hinnantc51e1022010-05-11 19:42:16 +00002646};
2647
2648// moneypunct
2649
2650template <class _CharT, bool _International = false>
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +00002651class _LIBCPP_TEMPLATE_VIS moneypunct
Howard Hinnantc51e1022010-05-11 19:42:16 +00002652 : public locale::facet,
2653 public money_base
2654{
2655public:
2656 typedef _CharT char_type;
2657 typedef basic_string<char_type> string_type;
2658
Louis Dionne16fe2952018-07-11 23:14:33 +00002659 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002660 explicit moneypunct(size_t __refs = 0)
2661 : locale::facet(__refs) {}
2662
Louis Dionne16fe2952018-07-11 23:14:33 +00002663 _LIBCPP_INLINE_VISIBILITY char_type decimal_point() const {return do_decimal_point();}
2664 _LIBCPP_INLINE_VISIBILITY char_type thousands_sep() const {return do_thousands_sep();}
2665 _LIBCPP_INLINE_VISIBILITY string grouping() const {return do_grouping();}
2666 _LIBCPP_INLINE_VISIBILITY string_type curr_symbol() const {return do_curr_symbol();}
2667 _LIBCPP_INLINE_VISIBILITY string_type positive_sign() const {return do_positive_sign();}
2668 _LIBCPP_INLINE_VISIBILITY string_type negative_sign() const {return do_negative_sign();}
2669 _LIBCPP_INLINE_VISIBILITY int frac_digits() const {return do_frac_digits();}
2670 _LIBCPP_INLINE_VISIBILITY pattern pos_format() const {return do_pos_format();}
2671 _LIBCPP_INLINE_VISIBILITY pattern neg_format() const {return do_neg_format();}
Howard Hinnantc51e1022010-05-11 19:42:16 +00002672
2673 static locale::id id;
2674 static const bool intl = _International;
2675
2676protected:
Louis Dionne16fe2952018-07-11 23:14:33 +00002677 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002678 ~moneypunct() {}
2679
2680 virtual char_type do_decimal_point() const {return numeric_limits<char_type>::max();}
2681 virtual char_type do_thousands_sep() const {return numeric_limits<char_type>::max();}
2682 virtual string do_grouping() const {return string();}
2683 virtual string_type do_curr_symbol() const {return string_type();}
2684 virtual string_type do_positive_sign() const {return string_type();}
2685 virtual string_type do_negative_sign() const {return string_type(1, '-');}
2686 virtual int do_frac_digits() const {return 0;}
2687 virtual pattern do_pos_format() const
Howard Hinnantb10e6cf2012-11-06 21:48:33 +00002688 {pattern __p = {{symbol, sign, none, value}}; return __p;}
Howard Hinnantc51e1022010-05-11 19:42:16 +00002689 virtual pattern do_neg_format() const
Howard Hinnantb10e6cf2012-11-06 21:48:33 +00002690 {pattern __p = {{symbol, sign, none, value}}; return __p;}
Howard Hinnantc51e1022010-05-11 19:42:16 +00002691};
2692
2693template <class _CharT, bool _International>
2694locale::id
2695moneypunct<_CharT, _International>::id;
2696
Howard Hinnant2c45cb42012-12-12 21:14:28 +00002697template <class _CharT, bool _International>
2698const bool
2699moneypunct<_CharT, _International>::intl;
2700
Louis Dionne9de5a672021-01-14 16:27:53 -05002701_LIBCPP_EXTERN_TEMPLATE_EVEN_IN_DEBUG_MODE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct<char, false>)
2702_LIBCPP_EXTERN_TEMPLATE_EVEN_IN_DEBUG_MODE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct<char, true>)
Louis Dionne89258142021-08-23 15:32:36 -04002703#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Louis Dionne9de5a672021-01-14 16:27:53 -05002704_LIBCPP_EXTERN_TEMPLATE_EVEN_IN_DEBUG_MODE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct<wchar_t, false>)
2705_LIBCPP_EXTERN_TEMPLATE_EVEN_IN_DEBUG_MODE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct<wchar_t, true>)
Louis Dionne89258142021-08-23 15:32:36 -04002706#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00002707
2708// moneypunct_byname
2709
2710template <class _CharT, bool _International = false>
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +00002711class _LIBCPP_TEMPLATE_VIS moneypunct_byname
Howard Hinnant756c69b2010-09-22 16:48:34 +00002712 : public moneypunct<_CharT, _International>
Howard Hinnantc51e1022010-05-11 19:42:16 +00002713{
2714public:
2715 typedef money_base::pattern pattern;
2716 typedef _CharT char_type;
2717 typedef basic_string<char_type> string_type;
2718
Louis Dionne16fe2952018-07-11 23:14:33 +00002719 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002720 explicit moneypunct_byname(const char* __nm, size_t __refs = 0)
2721 : moneypunct<_CharT, _International>(__refs) {init(__nm);}
2722
Louis Dionne16fe2952018-07-11 23:14:33 +00002723 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002724 explicit moneypunct_byname(const string& __nm, size_t __refs = 0)
2725 : moneypunct<_CharT, _International>(__refs) {init(__nm.c_str());}
2726
2727protected:
Louis Dionne16fe2952018-07-11 23:14:33 +00002728 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002729 ~moneypunct_byname() {}
2730
2731 virtual char_type do_decimal_point() const {return __decimal_point_;}
2732 virtual char_type do_thousands_sep() const {return __thousands_sep_;}
2733 virtual string do_grouping() const {return __grouping_;}
2734 virtual string_type do_curr_symbol() const {return __curr_symbol_;}
2735 virtual string_type do_positive_sign() const {return __positive_sign_;}
2736 virtual string_type do_negative_sign() const {return __negative_sign_;}
2737 virtual int do_frac_digits() const {return __frac_digits_;}
2738 virtual pattern do_pos_format() const {return __pos_format_;}
2739 virtual pattern do_neg_format() const {return __neg_format_;}
2740
2741private:
2742 char_type __decimal_point_;
2743 char_type __thousands_sep_;
2744 string __grouping_;
2745 string_type __curr_symbol_;
2746 string_type __positive_sign_;
2747 string_type __negative_sign_;
2748 int __frac_digits_;
2749 pattern __pos_format_;
2750 pattern __neg_format_;
2751
2752 void init(const char*);
2753};
2754
Shoaib Meenai094c3d22017-04-03 04:04:24 +00002755template<> _LIBCPP_FUNC_VIS void moneypunct_byname<char, false>::init(const char*);
2756template<> _LIBCPP_FUNC_VIS void moneypunct_byname<char, true>::init(const char*);
Louis Dionne9de5a672021-01-14 16:27:53 -05002757_LIBCPP_EXTERN_TEMPLATE_EVEN_IN_DEBUG_MODE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct_byname<char, false>)
2758_LIBCPP_EXTERN_TEMPLATE_EVEN_IN_DEBUG_MODE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct_byname<char, true>)
Louis Dionne89258142021-08-23 15:32:36 -04002759
2760#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
2761template<> _LIBCPP_FUNC_VIS void moneypunct_byname<wchar_t, false>::init(const char*);
2762template<> _LIBCPP_FUNC_VIS void moneypunct_byname<wchar_t, true>::init(const char*);
Louis Dionne9de5a672021-01-14 16:27:53 -05002763_LIBCPP_EXTERN_TEMPLATE_EVEN_IN_DEBUG_MODE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct_byname<wchar_t, false>)
2764_LIBCPP_EXTERN_TEMPLATE_EVEN_IN_DEBUG_MODE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct_byname<wchar_t, true>)
Louis Dionne89258142021-08-23 15:32:36 -04002765#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00002766
2767// money_get
2768
2769template <class _CharT>
2770class __money_get
2771{
2772protected:
2773 typedef _CharT char_type;
2774 typedef basic_string<char_type> string_type;
2775
Louis Dionne16fe2952018-07-11 23:14:33 +00002776 _LIBCPP_INLINE_VISIBILITY __money_get() {}
Howard Hinnantc51e1022010-05-11 19:42:16 +00002777
2778 static void __gather_info(bool __intl, const locale& __loc,
2779 money_base::pattern& __pat, char_type& __dp,
2780 char_type& __ts, string& __grp,
2781 string_type& __sym, string_type& __psn,
2782 string_type& __nsn, int& __fd);
2783};
2784
2785template <class _CharT>
2786void
2787__money_get<_CharT>::__gather_info(bool __intl, const locale& __loc,
2788 money_base::pattern& __pat, char_type& __dp,
2789 char_type& __ts, string& __grp,
2790 string_type& __sym, string_type& __psn,
2791 string_type& __nsn, int& __fd)
2792{
2793 if (__intl)
2794 {
2795 const moneypunct<char_type, true>& __mp =
2796 use_facet<moneypunct<char_type, true> >(__loc);
2797 __pat = __mp.neg_format();
2798 __nsn = __mp.negative_sign();
2799 __psn = __mp.positive_sign();
2800 __dp = __mp.decimal_point();
2801 __ts = __mp.thousands_sep();
2802 __grp = __mp.grouping();
2803 __sym = __mp.curr_symbol();
2804 __fd = __mp.frac_digits();
2805 }
2806 else
2807 {
2808 const moneypunct<char_type, false>& __mp =
2809 use_facet<moneypunct<char_type, false> >(__loc);
2810 __pat = __mp.neg_format();
2811 __nsn = __mp.negative_sign();
2812 __psn = __mp.positive_sign();
2813 __dp = __mp.decimal_point();
2814 __ts = __mp.thousands_sep();
2815 __grp = __mp.grouping();
2816 __sym = __mp.curr_symbol();
2817 __fd = __mp.frac_digits();
2818 }
2819}
2820
Louis Dionne9de5a672021-01-14 16:27:53 -05002821_LIBCPP_EXTERN_TEMPLATE_EVEN_IN_DEBUG_MODE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __money_get<char>)
Louis Dionne89258142021-08-23 15:32:36 -04002822#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Louis Dionne9de5a672021-01-14 16:27:53 -05002823_LIBCPP_EXTERN_TEMPLATE_EVEN_IN_DEBUG_MODE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __money_get<wchar_t>)
Louis Dionne89258142021-08-23 15:32:36 -04002824#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00002825
2826template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +00002827class _LIBCPP_TEMPLATE_VIS money_get
Howard Hinnantc51e1022010-05-11 19:42:16 +00002828 : public locale::facet,
2829 private __money_get<_CharT>
2830{
2831public:
2832 typedef _CharT char_type;
2833 typedef _InputIterator iter_type;
2834 typedef basic_string<char_type> string_type;
2835
Louis Dionne16fe2952018-07-11 23:14:33 +00002836 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002837 explicit money_get(size_t __refs = 0)
2838 : locale::facet(__refs) {}
2839
Louis Dionne16fe2952018-07-11 23:14:33 +00002840 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002841 iter_type get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob,
2842 ios_base::iostate& __err, long double& __v) const
2843 {
2844 return do_get(__b, __e, __intl, __iob, __err, __v);
2845 }
2846
Louis Dionne16fe2952018-07-11 23:14:33 +00002847 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002848 iter_type get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob,
2849 ios_base::iostate& __err, string_type& __v) const
2850 {
2851 return do_get(__b, __e, __intl, __iob, __err, __v);
2852 }
2853
2854 static locale::id id;
2855
2856protected:
2857
Louis Dionne16fe2952018-07-11 23:14:33 +00002858 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002859 ~money_get() {}
Howard Hinnant3b6579a2010-08-22 00:02:43 +00002860
Howard Hinnantc51e1022010-05-11 19:42:16 +00002861 virtual iter_type do_get(iter_type __b, iter_type __e, bool __intl,
2862 ios_base& __iob, ios_base::iostate& __err,
2863 long double& __v) const;
2864 virtual iter_type do_get(iter_type __b, iter_type __e, bool __intl,
2865 ios_base& __iob, ios_base::iostate& __err,
2866 string_type& __v) const;
2867
2868private:
2869 static bool __do_get(iter_type& __b, iter_type __e,
2870 bool __intl, const locale& __loc,
2871 ios_base::fmtflags __flags, ios_base::iostate& __err,
2872 bool& __neg, const ctype<char_type>& __ct,
2873 unique_ptr<char_type, void(*)(void*)>& __wb,
2874 char_type*& __wn, char_type* __we);
2875};
2876
2877template <class _CharT, class _InputIterator>
2878locale::id
2879money_get<_CharT, _InputIterator>::id;
2880
Howard Hinnanta37d3cf2013-08-12 18:38:34 +00002881_LIBCPP_FUNC_VIS void __do_nothing(void*);
Howard Hinnantc51e1022010-05-11 19:42:16 +00002882
2883template <class _Tp>
2884_LIBCPP_HIDDEN
2885void
2886__double_or_nothing(unique_ptr<_Tp, void(*)(void*)>& __b, _Tp*& __n, _Tp*& __e)
2887{
2888 bool __owns = __b.get_deleter() != __do_nothing;
Howard Hinnant28b24882011-12-01 20:21:04 +00002889 size_t __cur_cap = static_cast<size_t>(__e-__b.get()) * sizeof(_Tp);
Howard Hinnantc51e1022010-05-11 19:42:16 +00002890 size_t __new_cap = __cur_cap < numeric_limits<size_t>::max() / 2 ?
2891 2 * __cur_cap : numeric_limits<size_t>::max();
Marshall Clow6c9ddc22014-10-27 19:08:10 +00002892 if (__new_cap == 0)
2893 __new_cap = sizeof(_Tp);
Howard Hinnant28b24882011-12-01 20:21:04 +00002894 size_t __n_off = static_cast<size_t>(__n - __b.get());
Howard Hinnantc51e1022010-05-11 19:42:16 +00002895 _Tp* __t = (_Tp*)realloc(__owns ? __b.get() : 0, __new_cap);
2896 if (__t == 0)
2897 __throw_bad_alloc();
2898 if (__owns)
2899 __b.release();
2900 __b = unique_ptr<_Tp, void(*)(void*)>(__t, free);
2901 __new_cap /= sizeof(_Tp);
2902 __n = __b.get() + __n_off;
2903 __e = __b.get() + __new_cap;
2904}
2905
2906// true == success
2907template <class _CharT, class _InputIterator>
2908bool
2909money_get<_CharT, _InputIterator>::__do_get(iter_type& __b, iter_type __e,
2910 bool __intl, const locale& __loc,
2911 ios_base::fmtflags __flags,
2912 ios_base::iostate& __err,
2913 bool& __neg,
2914 const ctype<char_type>& __ct,
2915 unique_ptr<char_type, void(*)(void*)>& __wb,
2916 char_type*& __wn, char_type* __we)
2917{
Jason Liu4c9dadf2021-07-28 22:22:10 -04002918 if (__b == __e) {
2919 __err |= ios_base::failbit;
2920 return false;
2921 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00002922 const unsigned __bz = 100;
2923 unsigned __gbuf[__bz];
2924 unique_ptr<unsigned, void(*)(void*)> __gb(__gbuf, __do_nothing);
2925 unsigned* __gn = __gb.get();
2926 unsigned* __ge = __gn + __bz;
2927 money_base::pattern __pat;
2928 char_type __dp;
2929 char_type __ts;
2930 string __grp;
2931 string_type __sym;
2932 string_type __psn;
2933 string_type __nsn;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00002934 // Capture the spaces read into money_base::{space,none} so they
2935 // can be compared to initial spaces in __sym.
2936 string_type __spaces;
Howard Hinnantc51e1022010-05-11 19:42:16 +00002937 int __fd;
2938 __money_get<_CharT>::__gather_info(__intl, __loc, __pat, __dp, __ts, __grp,
2939 __sym, __psn, __nsn, __fd);
2940 const string_type* __trailing_sign = 0;
2941 __wn = __wb.get();
2942 for (unsigned __p = 0; __p < 4 && __b != __e; ++__p)
2943 {
2944 switch (__pat.field[__p])
2945 {
2946 case money_base::space:
2947 if (__p != 3)
2948 {
2949 if (__ct.is(ctype_base::space, *__b))
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00002950 __spaces.push_back(*__b++);
Howard Hinnantc51e1022010-05-11 19:42:16 +00002951 else
2952 {
2953 __err |= ios_base::failbit;
2954 return false;
2955 }
2956 }
Eric Fiselier4db80032017-05-05 20:32:26 +00002957 _LIBCPP_FALLTHROUGH();
Howard Hinnantc51e1022010-05-11 19:42:16 +00002958 case money_base::none:
2959 if (__p != 3)
2960 {
2961 while (__b != __e && __ct.is(ctype_base::space, *__b))
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00002962 __spaces.push_back(*__b++);
Howard Hinnantc51e1022010-05-11 19:42:16 +00002963 }
2964 break;
2965 case money_base::sign:
2966 if (__psn.size() + __nsn.size() > 0)
2967 {
2968 if (__psn.size() == 0 || __nsn.size() == 0)
2969 { // sign is optional
2970 if (__psn.size() > 0)
2971 { // __nsn.size() == 0
2972 if (*__b == __psn[0])
2973 {
2974 ++__b;
2975 if (__psn.size() > 1)
2976 __trailing_sign = &__psn;
2977 }
2978 else
2979 __neg = true;
2980 }
2981 else if (*__b == __nsn[0]) // __nsn.size() > 0 && __psn.size() == 0
2982 {
2983 ++__b;
2984 __neg = true;
2985 if (__nsn.size() > 1)
2986 __trailing_sign = &__nsn;
2987 }
2988 }
2989 else // sign is required
2990 {
2991 if (*__b == __psn[0])
2992 {
2993 ++__b;
2994 if (__psn.size() > 1)
2995 __trailing_sign = &__psn;
2996 }
2997 else if (*__b == __nsn[0])
2998 {
2999 ++__b;
3000 __neg = true;
3001 if (__nsn.size() > 1)
3002 __trailing_sign = &__nsn;
3003 }
3004 else
3005 {
3006 __err |= ios_base::failbit;
3007 return false;
3008 }
3009 }
3010 }
3011 break;
3012 case money_base::symbol:
3013 {
3014 bool __more_needed = __trailing_sign ||
3015 (__p < 2) ||
3016 (__p == 2 && __pat.field[3] != static_cast<char>(money_base::none));
Marshall Clowdfcbb432013-10-13 01:02:45 +00003017 bool __sb = (__flags & ios_base::showbase) != 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003018 if (__sb || __more_needed)
3019 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00003020 typename string_type::const_iterator __sym_space_end = __sym.begin();
3021 if (__p > 0 && (__pat.field[__p - 1] == money_base::none ||
3022 __pat.field[__p - 1] == money_base::space)) {
3023 // Match spaces we've already read against spaces at
3024 // the beginning of __sym.
3025 while (__sym_space_end != __sym.end() &&
3026 __ct.is(ctype_base::space, *__sym_space_end))
3027 ++__sym_space_end;
3028 const size_t __num_spaces = __sym_space_end - __sym.begin();
3029 if (__num_spaces > __spaces.size() ||
3030 !equal(__spaces.end() - __num_spaces, __spaces.end(),
3031 __sym.begin())) {
3032 // No match. Put __sym_space_end back at the
3033 // beginning of __sym, which will prevent a
3034 // match in the next loop.
3035 __sym_space_end = __sym.begin();
3036 }
3037 }
3038 typename string_type::const_iterator __sym_curr_char = __sym_space_end;
3039 while (__sym_curr_char != __sym.end() && __b != __e &&
3040 *__b == *__sym_curr_char) {
3041 ++__b;
3042 ++__sym_curr_char;
3043 }
3044 if (__sb && __sym_curr_char != __sym.end())
Howard Hinnantc51e1022010-05-11 19:42:16 +00003045 {
3046 __err |= ios_base::failbit;
3047 return false;
3048 }
3049 }
3050 }
3051 break;
3052 case money_base::value:
3053 {
3054 unsigned __ng = 0;
3055 for (; __b != __e; ++__b)
3056 {
3057 char_type __c = *__b;
3058 if (__ct.is(ctype_base::digit, __c))
3059 {
3060 if (__wn == __we)
3061 __double_or_nothing(__wb, __wn, __we);
3062 *__wn++ = __c;
3063 ++__ng;
3064 }
3065 else if (__grp.size() > 0 && __ng > 0 && __c == __ts)
3066 {
3067 if (__gn == __ge)
3068 __double_or_nothing(__gb, __gn, __ge);
3069 *__gn++ = __ng;
3070 __ng = 0;
3071 }
3072 else
3073 break;
3074 }
3075 if (__gb.get() != __gn && __ng > 0)
3076 {
3077 if (__gn == __ge)
3078 __double_or_nothing(__gb, __gn, __ge);
3079 *__gn++ = __ng;
3080 }
3081 if (__fd > 0)
3082 {
3083 if (__b == __e || *__b != __dp)
3084 {
3085 __err |= ios_base::failbit;
3086 return false;
3087 }
3088 for (++__b; __fd > 0; --__fd, ++__b)
3089 {
3090 if (__b == __e || !__ct.is(ctype_base::digit, *__b))
3091 {
3092 __err |= ios_base::failbit;
3093 return false;
3094 }
3095 if (__wn == __we)
3096 __double_or_nothing(__wb, __wn, __we);
3097 *__wn++ = *__b;
3098 }
3099 }
3100 if (__wn == __wb.get())
3101 {
3102 __err |= ios_base::failbit;
3103 return false;
3104 }
3105 }
3106 break;
3107 }
3108 }
3109 if (__trailing_sign)
3110 {
3111 for (unsigned __i = 1; __i < __trailing_sign->size(); ++__i, ++__b)
3112 {
3113 if (__b == __e || *__b != (*__trailing_sign)[__i])
3114 {
3115 __err |= ios_base::failbit;
3116 return false;
3117 }
3118 }
3119 }
3120 if (__gb.get() != __gn)
3121 {
3122 ios_base::iostate __et = ios_base::goodbit;
3123 __check_grouping(__grp, __gb.get(), __gn, __et);
3124 if (__et)
3125 {
3126 __err |= ios_base::failbit;
3127 return false;
3128 }
3129 }
3130 return true;
3131}
3132
3133template <class _CharT, class _InputIterator>
3134_InputIterator
3135money_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
3136 bool __intl, ios_base& __iob,
3137 ios_base::iostate& __err,
3138 long double& __v) const
3139{
Howard Hinnant28b24882011-12-01 20:21:04 +00003140 const int __bz = 100;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003141 char_type __wbuf[__bz];
3142 unique_ptr<char_type, void(*)(void*)> __wb(__wbuf, __do_nothing);
3143 char_type* __wn;
3144 char_type* __we = __wbuf + __bz;
3145 locale __loc = __iob.getloc();
3146 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3147 bool __neg = false;
3148 if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct,
3149 __wb, __wn, __we))
3150 {
3151 const char __src[] = "0123456789";
3152 char_type __atoms[sizeof(__src)-1];
3153 __ct.widen(__src, __src + (sizeof(__src)-1), __atoms);
3154 char __nbuf[__bz];
3155 char* __nc = __nbuf;
Bruce Mitchener170d8972020-11-24 12:53:53 -05003156 unique_ptr<char, void(*)(void*)> __h(nullptr, free);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003157 if (__wn - __wb.get() > __bz-2)
3158 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003159 __h.reset((char*)malloc(static_cast<size_t>(__wn - __wb.get() + 2)));
Bruce Mitchener170d8972020-11-24 12:53:53 -05003160 if (__h.get() == nullptr)
Howard Hinnantc51e1022010-05-11 19:42:16 +00003161 __throw_bad_alloc();
3162 __nc = __h.get();
3163 }
3164 if (__neg)
3165 *__nc++ = '-';
3166 for (const char_type* __w = __wb.get(); __w < __wn; ++__w, ++__nc)
Marshall Clow1e68fd42013-03-22 02:14:40 +00003167 *__nc = __src[find(__atoms, _VSTD::end(__atoms), *__w) - __atoms];
Howard Hinnantc51e1022010-05-11 19:42:16 +00003168 *__nc = char();
3169 if (sscanf(__nbuf, "%Lf", &__v) != 1)
3170 __throw_runtime_error("money_get error");
3171 }
3172 if (__b == __e)
3173 __err |= ios_base::eofbit;
3174 return __b;
3175}
3176
3177template <class _CharT, class _InputIterator>
3178_InputIterator
3179money_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
3180 bool __intl, ios_base& __iob,
3181 ios_base::iostate& __err,
3182 string_type& __v) const
3183{
Howard Hinnant28b24882011-12-01 20:21:04 +00003184 const int __bz = 100;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003185 char_type __wbuf[__bz];
3186 unique_ptr<char_type, void(*)(void*)> __wb(__wbuf, __do_nothing);
3187 char_type* __wn;
3188 char_type* __we = __wbuf + __bz;
3189 locale __loc = __iob.getloc();
3190 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3191 bool __neg = false;
3192 if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct,
3193 __wb, __wn, __we))
3194 {
3195 __v.clear();
3196 if (__neg)
3197 __v.push_back(__ct.widen('-'));
3198 char_type __z = __ct.widen('0');
3199 char_type* __w;
3200 for (__w = __wb.get(); __w < __wn-1; ++__w)
3201 if (*__w != __z)
3202 break;
3203 __v.append(__w, __wn);
3204 }
3205 if (__b == __e)
3206 __err |= ios_base::eofbit;
3207 return __b;
3208}
3209
Louis Dionne9de5a672021-01-14 16:27:53 -05003210_LIBCPP_EXTERN_TEMPLATE_EVEN_IN_DEBUG_MODE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS money_get<char>)
Louis Dionne89258142021-08-23 15:32:36 -04003211#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Louis Dionne9de5a672021-01-14 16:27:53 -05003212_LIBCPP_EXTERN_TEMPLATE_EVEN_IN_DEBUG_MODE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS money_get<wchar_t>)
Louis Dionne89258142021-08-23 15:32:36 -04003213#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00003214
3215// money_put
3216
3217template <class _CharT>
3218class __money_put
3219{
3220protected:
3221 typedef _CharT char_type;
3222 typedef basic_string<char_type> string_type;
3223
Louis Dionne16fe2952018-07-11 23:14:33 +00003224 _LIBCPP_INLINE_VISIBILITY __money_put() {}
Howard Hinnantc51e1022010-05-11 19:42:16 +00003225
3226 static void __gather_info(bool __intl, bool __neg, const locale& __loc,
3227 money_base::pattern& __pat, char_type& __dp,
3228 char_type& __ts, string& __grp,
3229 string_type& __sym, string_type& __sn,
3230 int& __fd);
3231 static void __format(char_type* __mb, char_type*& __mi, char_type*& __me,
3232 ios_base::fmtflags __flags,
3233 const char_type* __db, const char_type* __de,
3234 const ctype<char_type>& __ct, bool __neg,
3235 const money_base::pattern& __pat, char_type __dp,
3236 char_type __ts, const string& __grp,
3237 const string_type& __sym, const string_type& __sn,
3238 int __fd);
3239};
3240
3241template <class _CharT>
3242void
3243__money_put<_CharT>::__gather_info(bool __intl, bool __neg, const locale& __loc,
3244 money_base::pattern& __pat, char_type& __dp,
3245 char_type& __ts, string& __grp,
3246 string_type& __sym, string_type& __sn,
3247 int& __fd)
3248{
3249 if (__intl)
3250 {
3251 const moneypunct<char_type, true>& __mp =
3252 use_facet<moneypunct<char_type, true> >(__loc);
3253 if (__neg)
3254 {
3255 __pat = __mp.neg_format();
3256 __sn = __mp.negative_sign();
3257 }
3258 else
3259 {
3260 __pat = __mp.pos_format();
3261 __sn = __mp.positive_sign();
3262 }
3263 __dp = __mp.decimal_point();
3264 __ts = __mp.thousands_sep();
3265 __grp = __mp.grouping();
3266 __sym = __mp.curr_symbol();
3267 __fd = __mp.frac_digits();
3268 }
3269 else
3270 {
3271 const moneypunct<char_type, false>& __mp =
3272 use_facet<moneypunct<char_type, false> >(__loc);
3273 if (__neg)
3274 {
3275 __pat = __mp.neg_format();
3276 __sn = __mp.negative_sign();
3277 }
3278 else
3279 {
3280 __pat = __mp.pos_format();
3281 __sn = __mp.positive_sign();
3282 }
3283 __dp = __mp.decimal_point();
3284 __ts = __mp.thousands_sep();
3285 __grp = __mp.grouping();
3286 __sym = __mp.curr_symbol();
3287 __fd = __mp.frac_digits();
3288 }
3289}
3290
3291template <class _CharT>
3292void
3293__money_put<_CharT>::__format(char_type* __mb, char_type*& __mi, char_type*& __me,
3294 ios_base::fmtflags __flags,
3295 const char_type* __db, const char_type* __de,
3296 const ctype<char_type>& __ct, bool __neg,
3297 const money_base::pattern& __pat, char_type __dp,
3298 char_type __ts, const string& __grp,
3299 const string_type& __sym, const string_type& __sn,
3300 int __fd)
3301{
3302 __me = __mb;
3303 for (unsigned __p = 0; __p < 4; ++__p)
3304 {
3305 switch (__pat.field[__p])
3306 {
3307 case money_base::none:
3308 __mi = __me;
3309 break;
3310 case money_base::space:
3311 __mi = __me;
3312 *__me++ = __ct.widen(' ');
3313 break;
3314 case money_base::sign:
3315 if (!__sn.empty())
3316 *__me++ = __sn[0];
3317 break;
3318 case money_base::symbol:
3319 if (!__sym.empty() && (__flags & ios_base::showbase))
Howard Hinnantb1ad5a82011-06-30 21:18:19 +00003320 __me = _VSTD::copy(__sym.begin(), __sym.end(), __me);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003321 break;
3322 case money_base::value:
3323 {
3324 // remember start of value so we can reverse it
3325 char_type* __t = __me;
3326 // find beginning of digits
3327 if (__neg)
3328 ++__db;
3329 // find end of digits
3330 const char_type* __d;
3331 for (__d = __db; __d < __de; ++__d)
3332 if (!__ct.is(ctype_base::digit, *__d))
3333 break;
3334 // print fractional part
3335 if (__fd > 0)
3336 {
3337 int __f;
3338 for (__f = __fd; __d > __db && __f > 0; --__f)
3339 *__me++ = *--__d;
3340 char_type __z = __f > 0 ? __ct.widen('0') : char_type();
3341 for (; __f > 0; --__f)
3342 *__me++ = __z;
3343 *__me++ = __dp;
3344 }
3345 // print units part
3346 if (__d == __db)
3347 {
3348 *__me++ = __ct.widen('0');
3349 }
3350 else
3351 {
3352 unsigned __ng = 0;
3353 unsigned __ig = 0;
3354 unsigned __gl = __grp.empty() ? numeric_limits<unsigned>::max()
3355 : static_cast<unsigned>(__grp[__ig]);
3356 while (__d != __db)
3357 {
3358 if (__ng == __gl)
3359 {
3360 *__me++ = __ts;
3361 __ng = 0;
3362 if (++__ig < __grp.size())
3363 __gl = __grp[__ig] == numeric_limits<char>::max() ?
3364 numeric_limits<unsigned>::max() :
3365 static_cast<unsigned>(__grp[__ig]);
3366 }
3367 *__me++ = *--__d;
3368 ++__ng;
3369 }
3370 }
3371 // reverse it
3372 reverse(__t, __me);
3373 }
3374 break;
3375 }
3376 }
3377 // print rest of sign, if any
3378 if (__sn.size() > 1)
Howard Hinnantb1ad5a82011-06-30 21:18:19 +00003379 __me = _VSTD::copy(__sn.begin()+1, __sn.end(), __me);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003380 // set alignment
3381 if ((__flags & ios_base::adjustfield) == ios_base::left)
3382 __mi = __me;
3383 else if ((__flags & ios_base::adjustfield) != ios_base::internal)
3384 __mi = __mb;
3385}
3386
Louis Dionne9de5a672021-01-14 16:27:53 -05003387_LIBCPP_EXTERN_TEMPLATE_EVEN_IN_DEBUG_MODE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __money_put<char>)
Louis Dionne89258142021-08-23 15:32:36 -04003388#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Louis Dionne9de5a672021-01-14 16:27:53 -05003389_LIBCPP_EXTERN_TEMPLATE_EVEN_IN_DEBUG_MODE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __money_put<wchar_t>)
Louis Dionne89258142021-08-23 15:32:36 -04003390#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00003391
3392template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +00003393class _LIBCPP_TEMPLATE_VIS money_put
Howard Hinnantc51e1022010-05-11 19:42:16 +00003394 : public locale::facet,
3395 private __money_put<_CharT>
3396{
3397public:
3398 typedef _CharT char_type;
3399 typedef _OutputIterator iter_type;
3400 typedef basic_string<char_type> string_type;
3401
Louis Dionne16fe2952018-07-11 23:14:33 +00003402 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00003403 explicit money_put(size_t __refs = 0)
3404 : locale::facet(__refs) {}
3405
Louis Dionne16fe2952018-07-11 23:14:33 +00003406 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00003407 iter_type put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl,
3408 long double __units) const
3409 {
3410 return do_put(__s, __intl, __iob, __fl, __units);
3411 }
3412
Louis Dionne16fe2952018-07-11 23:14:33 +00003413 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00003414 iter_type put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl,
3415 const string_type& __digits) const
3416 {
3417 return do_put(__s, __intl, __iob, __fl, __digits);
3418 }
3419
3420 static locale::id id;
3421
3422protected:
Louis Dionne16fe2952018-07-11 23:14:33 +00003423 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00003424 ~money_put() {}
3425
3426 virtual iter_type do_put(iter_type __s, bool __intl, ios_base& __iob,
3427 char_type __fl, long double __units) const;
3428 virtual iter_type do_put(iter_type __s, bool __intl, ios_base& __iob,
3429 char_type __fl, const string_type& __digits) const;
3430};
3431
3432template <class _CharT, class _OutputIterator>
3433locale::id
3434money_put<_CharT, _OutputIterator>::id;
3435
3436template <class _CharT, class _OutputIterator>
3437_OutputIterator
3438money_put<_CharT, _OutputIterator>::do_put(iter_type __s, bool __intl,
3439 ios_base& __iob, char_type __fl,
3440 long double __units) const
3441{
3442 // convert to char
3443 const size_t __bs = 100;
3444 char __buf[__bs];
3445 char* __bb = __buf;
3446 char_type __digits[__bs];
3447 char_type* __db = __digits;
Brad Smithaee2d992021-01-21 19:39:52 -05003448 int __n = snprintf(__bb, __bs, "%.0Lf", __units);
Bruce Mitchener170d8972020-11-24 12:53:53 -05003449 unique_ptr<char, void(*)(void*)> __hn(nullptr, free);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003450 unique_ptr<char_type, void(*)(void*)> __hd(0, free);
3451 // secure memory for digit storage
Brad Smithaee2d992021-01-21 19:39:52 -05003452 if (static_cast<size_t>(__n) > __bs-1)
Howard Hinnantc51e1022010-05-11 19:42:16 +00003453 {
Brad Smithaee2d992021-01-21 19:39:52 -05003454 __n = __libcpp_asprintf_l(&__bb, _LIBCPP_GET_C_LOCALE, "%.0Lf", __units);
3455 if (__n == -1)
Howard Hinnantc51e1022010-05-11 19:42:16 +00003456 __throw_bad_alloc();
3457 __hn.reset(__bb);
Brad Smithaee2d992021-01-21 19:39:52 -05003458 __hd.reset((char_type*)malloc(static_cast<size_t>(__n) * sizeof(char_type)));
Howard Hinnant03de6f92012-03-07 20:37:43 +00003459 if (__hd == nullptr)
Howard Hinnantc51e1022010-05-11 19:42:16 +00003460 __throw_bad_alloc();
3461 __db = __hd.get();
3462 }
3463 // gather info
3464 locale __loc = __iob.getloc();
3465 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3466 __ct.widen(__bb, __bb + __n, __db);
3467 bool __neg = __n > 0 && __bb[0] == '-';
3468 money_base::pattern __pat;
3469 char_type __dp;
3470 char_type __ts;
3471 string __grp;
3472 string_type __sym;
3473 string_type __sn;
3474 int __fd;
3475 this->__gather_info(__intl, __neg, __loc, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3476 // secure memory for formatting
3477 char_type __mbuf[__bs];
3478 char_type* __mb = __mbuf;
3479 unique_ptr<char_type, void(*)(void*)> __hw(0, free);
Brad Smithaee2d992021-01-21 19:39:52 -05003480 size_t __exn = __n > __fd ?
3481 (static_cast<size_t>(__n) - static_cast<size_t>(__fd)) * 2 +
3482 __sn.size() + __sym.size() + static_cast<size_t>(__fd) + 1
Howard Hinnant28b24882011-12-01 20:21:04 +00003483 : __sn.size() + __sym.size() + static_cast<size_t>(__fd) + 2;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003484 if (__exn > __bs)
3485 {
3486 __hw.reset((char_type*)malloc(__exn * sizeof(char_type)));
3487 __mb = __hw.get();
3488 if (__mb == 0)
3489 __throw_bad_alloc();
3490 }
3491 // format
3492 char_type* __mi;
3493 char_type* __me;
3494 this->__format(__mb, __mi, __me, __iob.flags(),
3495 __db, __db + __n, __ct,
3496 __neg, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3497 return __pad_and_output(__s, __mb, __mi, __me, __iob, __fl);
3498}
3499
3500template <class _CharT, class _OutputIterator>
3501_OutputIterator
3502money_put<_CharT, _OutputIterator>::do_put(iter_type __s, bool __intl,
3503 ios_base& __iob, char_type __fl,
3504 const string_type& __digits) const
3505{
3506 // gather info
3507 locale __loc = __iob.getloc();
3508 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3509 bool __neg = __digits.size() > 0 && __digits[0] == __ct.widen('-');
3510 money_base::pattern __pat;
3511 char_type __dp;
3512 char_type __ts;
3513 string __grp;
3514 string_type __sym;
3515 string_type __sn;
3516 int __fd;
3517 this->__gather_info(__intl, __neg, __loc, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3518 // secure memory for formatting
3519 char_type __mbuf[100];
3520 char_type* __mb = __mbuf;
3521 unique_ptr<char_type, void(*)(void*)> __h(0, free);
Howard Hinnant28b24882011-12-01 20:21:04 +00003522 size_t __exn = static_cast<int>(__digits.size()) > __fd ?
3523 (__digits.size() - static_cast<size_t>(__fd)) * 2 +
3524 __sn.size() + __sym.size() + static_cast<size_t>(__fd) + 1
3525 : __sn.size() + __sym.size() + static_cast<size_t>(__fd) + 2;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003526 if (__exn > 100)
3527 {
3528 __h.reset((char_type*)malloc(__exn * sizeof(char_type)));
3529 __mb = __h.get();
3530 if (__mb == 0)
3531 __throw_bad_alloc();
3532 }
3533 // format
3534 char_type* __mi;
3535 char_type* __me;
3536 this->__format(__mb, __mi, __me, __iob.flags(),
3537 __digits.data(), __digits.data() + __digits.size(), __ct,
3538 __neg, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3539 return __pad_and_output(__s, __mb, __mi, __me, __iob, __fl);
3540}
3541
Louis Dionne9de5a672021-01-14 16:27:53 -05003542_LIBCPP_EXTERN_TEMPLATE_EVEN_IN_DEBUG_MODE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS money_put<char>)
Louis Dionne89258142021-08-23 15:32:36 -04003543#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Louis Dionne9de5a672021-01-14 16:27:53 -05003544_LIBCPP_EXTERN_TEMPLATE_EVEN_IN_DEBUG_MODE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS money_put<wchar_t>)
Louis Dionne89258142021-08-23 15:32:36 -04003545#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00003546
3547// messages
3548
Howard Hinnant8331b762013-03-06 23:30:19 +00003549class _LIBCPP_TYPE_VIS messages_base
Howard Hinnantc51e1022010-05-11 19:42:16 +00003550{
3551public:
Howard Hinnant2862aeb2011-02-25 00:51:08 +00003552 typedef ptrdiff_t catalog;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003553
Louis Dionne16fe2952018-07-11 23:14:33 +00003554 _LIBCPP_INLINE_VISIBILITY messages_base() {}
Howard Hinnantc51e1022010-05-11 19:42:16 +00003555};
3556
3557template <class _CharT>
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +00003558class _LIBCPP_TEMPLATE_VIS messages
Howard Hinnantc51e1022010-05-11 19:42:16 +00003559 : public locale::facet,
3560 public messages_base
3561{
3562public:
3563 typedef _CharT char_type;
3564 typedef basic_string<_CharT> string_type;
3565
Louis Dionne16fe2952018-07-11 23:14:33 +00003566 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00003567 explicit messages(size_t __refs = 0)
3568 : locale::facet(__refs) {}
3569
Louis Dionne16fe2952018-07-11 23:14:33 +00003570 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00003571 catalog open(const basic_string<char>& __nm, const locale& __loc) const
3572 {
3573 return do_open(__nm, __loc);
3574 }
3575
Louis Dionne16fe2952018-07-11 23:14:33 +00003576 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00003577 string_type get(catalog __c, int __set, int __msgid,
3578 const string_type& __dflt) const
3579 {
3580 return do_get(__c, __set, __msgid, __dflt);
3581 }
3582
Louis Dionne16fe2952018-07-11 23:14:33 +00003583 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00003584 void close(catalog __c) const
3585 {
3586 do_close(__c);
3587 }
3588
3589 static locale::id id;
3590
3591protected:
Louis Dionne16fe2952018-07-11 23:14:33 +00003592 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00003593 ~messages() {}
3594
3595 virtual catalog do_open(const basic_string<char>&, const locale&) const;
3596 virtual string_type do_get(catalog, int __set, int __msgid,
3597 const string_type& __dflt) const;
3598 virtual void do_close(catalog) const;
3599};
3600
3601template <class _CharT>
3602locale::id
3603messages<_CharT>::id;
3604
3605template <class _CharT>
3606typename messages<_CharT>::catalog
3607messages<_CharT>::do_open(const basic_string<char>& __nm, const locale&) const
3608{
Ed Schouten118b6032015-03-11 16:39:36 +00003609#ifdef _LIBCPP_HAS_CATOPEN
Howard Hinnant8c2bf6b2011-10-11 16:00:46 +00003610 catalog __cat = (catalog)catopen(__nm.c_str(), NL_CAT_LOCALE);
Howard Hinnant2862aeb2011-02-25 00:51:08 +00003611 if (__cat != -1)
3612 __cat = static_cast<catalog>((static_cast<size_t>(__cat) >> 1));
3613 return __cat;
Ed Schouten118b6032015-03-11 16:39:36 +00003614#else // !_LIBCPP_HAS_CATOPEN
Arthur O'Dwyer61b40752021-04-18 22:17:44 -04003615 (void)__nm;
Ed Schouten118b6032015-03-11 16:39:36 +00003616 return -1;
3617#endif // _LIBCPP_HAS_CATOPEN
Howard Hinnantc51e1022010-05-11 19:42:16 +00003618}
3619
3620template <class _CharT>
3621typename messages<_CharT>::string_type
3622messages<_CharT>::do_get(catalog __c, int __set, int __msgid,
3623 const string_type& __dflt) const
3624{
Ed Schouten118b6032015-03-11 16:39:36 +00003625#ifdef _LIBCPP_HAS_CATOPEN
Howard Hinnantc51e1022010-05-11 19:42:16 +00003626 string __ndflt;
3627 __narrow_to_utf8<sizeof(char_type)*__CHAR_BIT__>()(back_inserter(__ndflt),
3628 __dflt.c_str(),
3629 __dflt.c_str() + __dflt.size());
Howard Hinnant2862aeb2011-02-25 00:51:08 +00003630 if (__c != -1)
3631 __c <<= 1;
Howard Hinnant8c2bf6b2011-10-11 16:00:46 +00003632 nl_catd __cat = (nl_catd)__c;
Howard Hinnant2862aeb2011-02-25 00:51:08 +00003633 char* __n = catgets(__cat, __set, __msgid, __ndflt.c_str());
Howard Hinnantc51e1022010-05-11 19:42:16 +00003634 string_type __w;
3635 __widen_from_utf8<sizeof(char_type)*__CHAR_BIT__>()(back_inserter(__w),
Arthur O'Dwyer22236632020-12-07 21:50:15 -05003636 __n, __n + _VSTD::strlen(__n));
Howard Hinnantc51e1022010-05-11 19:42:16 +00003637 return __w;
Ed Schouten118b6032015-03-11 16:39:36 +00003638#else // !_LIBCPP_HAS_CATOPEN
Arthur O'Dwyer61b40752021-04-18 22:17:44 -04003639 (void)__c;
3640 (void)__set;
3641 (void)__msgid;
Ed Schouten118b6032015-03-11 16:39:36 +00003642 return __dflt;
3643#endif // _LIBCPP_HAS_CATOPEN
Howard Hinnantc51e1022010-05-11 19:42:16 +00003644}
3645
3646template <class _CharT>
3647void
3648messages<_CharT>::do_close(catalog __c) const
3649{
Ed Schouten118b6032015-03-11 16:39:36 +00003650#ifdef _LIBCPP_HAS_CATOPEN
Howard Hinnant2862aeb2011-02-25 00:51:08 +00003651 if (__c != -1)
3652 __c <<= 1;
Howard Hinnant8c2bf6b2011-10-11 16:00:46 +00003653 nl_catd __cat = (nl_catd)__c;
Howard Hinnant2862aeb2011-02-25 00:51:08 +00003654 catclose(__cat);
Petr Hosek399c5112019-01-13 22:15:37 +00003655#else // !_LIBCPP_HAS_CATOPEN
Arthur O'Dwyer61b40752021-04-18 22:17:44 -04003656 (void)__c;
Ed Schouten118b6032015-03-11 16:39:36 +00003657#endif // _LIBCPP_HAS_CATOPEN
Howard Hinnantc51e1022010-05-11 19:42:16 +00003658}
3659
Louis Dionne9de5a672021-01-14 16:27:53 -05003660_LIBCPP_EXTERN_TEMPLATE_EVEN_IN_DEBUG_MODE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS messages<char>)
Louis Dionne89258142021-08-23 15:32:36 -04003661#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Louis Dionne9de5a672021-01-14 16:27:53 -05003662_LIBCPP_EXTERN_TEMPLATE_EVEN_IN_DEBUG_MODE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS messages<wchar_t>)
Louis Dionne89258142021-08-23 15:32:36 -04003663#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00003664
3665template <class _CharT>
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +00003666class _LIBCPP_TEMPLATE_VIS messages_byname
Howard Hinnantc51e1022010-05-11 19:42:16 +00003667 : public messages<_CharT>
3668{
3669public:
3670 typedef messages_base::catalog catalog;
3671 typedef basic_string<_CharT> string_type;
3672
Louis Dionne16fe2952018-07-11 23:14:33 +00003673 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00003674 explicit messages_byname(const char*, size_t __refs = 0)
3675 : messages<_CharT>(__refs) {}
3676
Louis Dionne16fe2952018-07-11 23:14:33 +00003677 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00003678 explicit messages_byname(const string&, size_t __refs = 0)
3679 : messages<_CharT>(__refs) {}
3680
3681protected:
Louis Dionne16fe2952018-07-11 23:14:33 +00003682 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00003683 ~messages_byname() {}
3684};
3685
Louis Dionne9de5a672021-01-14 16:27:53 -05003686_LIBCPP_EXTERN_TEMPLATE_EVEN_IN_DEBUG_MODE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS messages_byname<char>)
Louis Dionne89258142021-08-23 15:32:36 -04003687#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Louis Dionne9de5a672021-01-14 16:27:53 -05003688_LIBCPP_EXTERN_TEMPLATE_EVEN_IN_DEBUG_MODE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS messages_byname<wchar_t>)
Louis Dionne89258142021-08-23 15:32:36 -04003689#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00003690
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003691template<class _Codecvt, class _Elem = wchar_t,
3692 class _Wide_alloc = allocator<_Elem>,
3693 class _Byte_alloc = allocator<char> >
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +00003694class _LIBCPP_TEMPLATE_VIS wstring_convert
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003695{
3696public:
3697 typedef basic_string<char, char_traits<char>, _Byte_alloc> byte_string;
3698 typedef basic_string<_Elem, char_traits<_Elem>, _Wide_alloc> wide_string;
3699 typedef typename _Codecvt::state_type state_type;
3700 typedef typename wide_string::traits_type::int_type int_type;
3701
3702private:
3703 byte_string __byte_err_string_;
3704 wide_string __wide_err_string_;
3705 _Codecvt* __cvtptr_;
3706 state_type __cvtstate_;
3707 size_t __cvtcount_;
3708
3709 wstring_convert(const wstring_convert& __wc);
3710 wstring_convert& operator=(const wstring_convert& __wc);
3711public:
Marek Kurdejcd0bd6a2021-01-19 08:21:09 +01003712#ifndef _LIBCPP_CXX03_LANG
Louis Dionne16fe2952018-07-11 23:14:33 +00003713 _LIBCPP_INLINE_VISIBILITY
Marek Kurdejcd0bd6a2021-01-19 08:21:09 +01003714 wstring_convert() : wstring_convert(new _Codecvt) {}
3715 _LIBCPP_INLINE_VISIBILITY
3716 explicit wstring_convert(_Codecvt* __pcvt);
3717#else
3718 _LIBCPP_INLINE_VISIBILITY
3719 _LIBCPP_EXPLICIT_AFTER_CXX11
3720 wstring_convert(_Codecvt* __pcvt = new _Codecvt);
3721#endif
3722
Louis Dionne16fe2952018-07-11 23:14:33 +00003723 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003724 wstring_convert(_Codecvt* __pcvt, state_type __state);
Marshall Clowccaa0fb2013-08-27 20:18:59 +00003725 _LIBCPP_EXPLICIT_AFTER_CXX11 wstring_convert(const byte_string& __byte_err,
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003726 const wide_string& __wide_err = wide_string());
Eric Fiselierf07d88c2017-04-19 01:34:08 +00003727#ifndef _LIBCPP_CXX03_LANG
Louis Dionne16fe2952018-07-11 23:14:33 +00003728 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003729 wstring_convert(wstring_convert&& __wc);
3730#endif
3731 ~wstring_convert();
3732
Louis Dionne16fe2952018-07-11 23:14:33 +00003733 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003734 wide_string from_bytes(char __byte)
3735 {return from_bytes(&__byte, &__byte+1);}
Louis Dionne16fe2952018-07-11 23:14:33 +00003736 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003737 wide_string from_bytes(const char* __ptr)
3738 {return from_bytes(__ptr, __ptr + char_traits<char>::length(__ptr));}
Louis Dionne16fe2952018-07-11 23:14:33 +00003739 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003740 wide_string from_bytes(const byte_string& __str)
3741 {return from_bytes(__str.data(), __str.data() + __str.size());}
3742 wide_string from_bytes(const char* __first, const char* __last);
3743
Louis Dionne16fe2952018-07-11 23:14:33 +00003744 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003745 byte_string to_bytes(_Elem __wchar)
3746 {return to_bytes(&__wchar, &__wchar+1);}
Louis Dionne16fe2952018-07-11 23:14:33 +00003747 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003748 byte_string to_bytes(const _Elem* __wptr)
3749 {return to_bytes(__wptr, __wptr + char_traits<_Elem>::length(__wptr));}
Louis Dionne16fe2952018-07-11 23:14:33 +00003750 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003751 byte_string to_bytes(const wide_string& __wstr)
3752 {return to_bytes(__wstr.data(), __wstr.data() + __wstr.size());}
3753 byte_string to_bytes(const _Elem* __first, const _Elem* __last);
3754
Louis Dionne16fe2952018-07-11 23:14:33 +00003755 _LIBCPP_INLINE_VISIBILITY
Marshall Clowccaa0fb2013-08-27 20:18:59 +00003756 size_t converted() const _NOEXCEPT {return __cvtcount_;}
Louis Dionne16fe2952018-07-11 23:14:33 +00003757 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003758 state_type state() const {return __cvtstate_;}
3759};
3760
3761template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Evgeniy Stepanov2fb1cb62015-11-07 01:22:13 +00003762inline
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003763wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3764 wstring_convert(_Codecvt* __pcvt)
3765 : __cvtptr_(__pcvt), __cvtstate_(), __cvtcount_(0)
3766{
3767}
3768
3769template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Evgeniy Stepanov2fb1cb62015-11-07 01:22:13 +00003770inline
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003771wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3772 wstring_convert(_Codecvt* __pcvt, state_type __state)
3773 : __cvtptr_(__pcvt), __cvtstate_(__state), __cvtcount_(0)
3774{
3775}
3776
3777template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3778wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3779 wstring_convert(const byte_string& __byte_err, const wide_string& __wide_err)
3780 : __byte_err_string_(__byte_err), __wide_err_string_(__wide_err),
3781 __cvtstate_(), __cvtcount_(0)
3782{
3783 __cvtptr_ = new _Codecvt;
3784}
3785
Eric Fiselierf07d88c2017-04-19 01:34:08 +00003786#ifndef _LIBCPP_CXX03_LANG
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003787
3788template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Evgeniy Stepanov2fb1cb62015-11-07 01:22:13 +00003789inline
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003790wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3791 wstring_convert(wstring_convert&& __wc)
Howard Hinnantb1ad5a82011-06-30 21:18:19 +00003792 : __byte_err_string_(_VSTD::move(__wc.__byte_err_string_)),
3793 __wide_err_string_(_VSTD::move(__wc.__wide_err_string_)),
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003794 __cvtptr_(__wc.__cvtptr_),
Eric Fiselier35c67232016-06-26 22:56:26 +00003795 __cvtstate_(__wc.__cvtstate_), __cvtcount_(__wc.__cvtcount_)
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003796{
3797 __wc.__cvtptr_ = nullptr;
3798}
3799
Louis Dionne2b1ceaa2021-04-20 12:03:32 -04003800#endif // _LIBCPP_CXX03_LANG
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003801
3802template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3803wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::~wstring_convert()
3804{
3805 delete __cvtptr_;
3806}
3807
3808template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3809typename wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::wide_string
3810wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3811 from_bytes(const char* __frm, const char* __frm_end)
3812{
3813 __cvtcount_ = 0;
3814 if (__cvtptr_ != nullptr)
3815 {
3816 wide_string __ws(2*(__frm_end - __frm), _Elem());
Howard Hinnant16d54f22012-07-12 18:07:41 +00003817 if (__frm != __frm_end)
3818 __ws.resize(__ws.capacity());
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003819 codecvt_base::result __r = codecvt_base::ok;
3820 state_type __st = __cvtstate_;
3821 if (__frm != __frm_end)
3822 {
3823 _Elem* __to = &__ws[0];
3824 _Elem* __to_end = __to + __ws.size();
3825 const char* __frm_nxt;
3826 do
3827 {
3828 _Elem* __to_nxt;
3829 __r = __cvtptr_->in(__st, __frm, __frm_end, __frm_nxt,
3830 __to, __to_end, __to_nxt);
3831 __cvtcount_ += __frm_nxt - __frm;
3832 if (__frm_nxt == __frm)
3833 {
3834 __r = codecvt_base::error;
3835 }
3836 else if (__r == codecvt_base::noconv)
3837 {
3838 __ws.resize(__to - &__ws[0]);
3839 // This only gets executed if _Elem is char
3840 __ws.append((const _Elem*)__frm, (const _Elem*)__frm_end);
3841 __frm = __frm_nxt;
3842 __r = codecvt_base::ok;
3843 }
3844 else if (__r == codecvt_base::ok)
3845 {
3846 __ws.resize(__to_nxt - &__ws[0]);
3847 __frm = __frm_nxt;
3848 }
3849 else if (__r == codecvt_base::partial)
3850 {
3851 ptrdiff_t __s = __to_nxt - &__ws[0];
3852 __ws.resize(2 * __s);
3853 __to = &__ws[0] + __s;
3854 __to_end = &__ws[0] + __ws.size();
3855 __frm = __frm_nxt;
3856 }
3857 } while (__r == codecvt_base::partial && __frm_nxt < __frm_end);
3858 }
3859 if (__r == codecvt_base::ok)
3860 return __ws;
3861 }
Marshall Clow8fea1612016-08-25 15:09:01 +00003862
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003863 if (__wide_err_string_.empty())
Marshall Clow8fea1612016-08-25 15:09:01 +00003864 __throw_range_error("wstring_convert: from_bytes error");
3865
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003866 return __wide_err_string_;
3867}
3868
3869template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3870typename wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::byte_string
3871wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3872 to_bytes(const _Elem* __frm, const _Elem* __frm_end)
3873{
3874 __cvtcount_ = 0;
3875 if (__cvtptr_ != nullptr)
3876 {
3877 byte_string __bs(2*(__frm_end - __frm), char());
Howard Hinnant16d54f22012-07-12 18:07:41 +00003878 if (__frm != __frm_end)
3879 __bs.resize(__bs.capacity());
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003880 codecvt_base::result __r = codecvt_base::ok;
3881 state_type __st = __cvtstate_;
3882 if (__frm != __frm_end)
3883 {
3884 char* __to = &__bs[0];
3885 char* __to_end = __to + __bs.size();
3886 const _Elem* __frm_nxt;
3887 do
3888 {
3889 char* __to_nxt;
3890 __r = __cvtptr_->out(__st, __frm, __frm_end, __frm_nxt,
3891 __to, __to_end, __to_nxt);
3892 __cvtcount_ += __frm_nxt - __frm;
3893 if (__frm_nxt == __frm)
3894 {
3895 __r = codecvt_base::error;
3896 }
3897 else if (__r == codecvt_base::noconv)
3898 {
3899 __bs.resize(__to - &__bs[0]);
3900 // This only gets executed if _Elem is char
3901 __bs.append((const char*)__frm, (const char*)__frm_end);
3902 __frm = __frm_nxt;
3903 __r = codecvt_base::ok;
3904 }
3905 else if (__r == codecvt_base::ok)
3906 {
3907 __bs.resize(__to_nxt - &__bs[0]);
3908 __frm = __frm_nxt;
3909 }
3910 else if (__r == codecvt_base::partial)
3911 {
3912 ptrdiff_t __s = __to_nxt - &__bs[0];
3913 __bs.resize(2 * __s);
3914 __to = &__bs[0] + __s;
3915 __to_end = &__bs[0] + __bs.size();
3916 __frm = __frm_nxt;
3917 }
3918 } while (__r == codecvt_base::partial && __frm_nxt < __frm_end);
3919 }
3920 if (__r == codecvt_base::ok)
3921 {
3922 size_t __s = __bs.size();
3923 __bs.resize(__bs.capacity());
3924 char* __to = &__bs[0] + __s;
3925 char* __to_end = __to + __bs.size();
3926 do
3927 {
3928 char* __to_nxt;
3929 __r = __cvtptr_->unshift(__st, __to, __to_end, __to_nxt);
3930 if (__r == codecvt_base::noconv)
3931 {
3932 __bs.resize(__to - &__bs[0]);
3933 __r = codecvt_base::ok;
3934 }
3935 else if (__r == codecvt_base::ok)
3936 {
3937 __bs.resize(__to_nxt - &__bs[0]);
3938 }
3939 else if (__r == codecvt_base::partial)
3940 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003941 ptrdiff_t __sp = __to_nxt - &__bs[0];
3942 __bs.resize(2 * __sp);
3943 __to = &__bs[0] + __sp;
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003944 __to_end = &__bs[0] + __bs.size();
3945 }
3946 } while (__r == codecvt_base::partial);
3947 if (__r == codecvt_base::ok)
3948 return __bs;
3949 }
3950 }
Marshall Clow8fea1612016-08-25 15:09:01 +00003951
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003952 if (__byte_err_string_.empty())
Marshall Clow8fea1612016-08-25 15:09:01 +00003953 __throw_range_error("wstring_convert: to_bytes error");
3954
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003955 return __byte_err_string_;
3956}
3957
3958template <class _Codecvt, class _Elem = wchar_t, class _Tr = char_traits<_Elem> >
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +00003959class _LIBCPP_TEMPLATE_VIS wbuffer_convert
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003960 : public basic_streambuf<_Elem, _Tr>
3961{
3962public:
3963 // types:
3964 typedef _Elem char_type;
3965 typedef _Tr traits_type;
3966 typedef typename traits_type::int_type int_type;
3967 typedef typename traits_type::pos_type pos_type;
3968 typedef typename traits_type::off_type off_type;
3969 typedef typename _Codecvt::state_type state_type;
3970
3971private:
Howard Hinnant0ac182a2010-06-01 20:09:18 +00003972 char* __extbuf_;
3973 const char* __extbufnext_;
3974 const char* __extbufend_;
3975 char __extbuf_min_[8];
3976 size_t __ebs_;
3977 char_type* __intbuf_;
3978 size_t __ibs_;
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003979 streambuf* __bufptr_;
Howard Hinnant0ac182a2010-06-01 20:09:18 +00003980 _Codecvt* __cv_;
3981 state_type __st_;
3982 ios_base::openmode __cm_;
3983 bool __owns_eb_;
3984 bool __owns_ib_;
3985 bool __always_noconv_;
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003986
Howard Hinnant0ac182a2010-06-01 20:09:18 +00003987 wbuffer_convert(const wbuffer_convert&);
3988 wbuffer_convert& operator=(const wbuffer_convert&);
Marek Kurdejcd0bd6a2021-01-19 08:21:09 +01003989
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003990public:
Marek Kurdejcd0bd6a2021-01-19 08:21:09 +01003991#ifndef _LIBCPP_CXX03_LANG
3992 wbuffer_convert() : wbuffer_convert(nullptr) {}
3993 explicit wbuffer_convert(streambuf* __bytebuf,
3994 _Codecvt* __pcvt = new _Codecvt,
3995 state_type __state = state_type());
3996#else
3997 _LIBCPP_EXPLICIT_AFTER_CXX11
3998 wbuffer_convert(streambuf* __bytebuf = nullptr,
3999 _Codecvt* __pcvt = new _Codecvt,
4000 state_type __state = state_type());
4001#endif
4002
Howard Hinnant0ac182a2010-06-01 20:09:18 +00004003 ~wbuffer_convert();
Howard Hinnant9dd7e892010-05-31 20:58:54 +00004004
Howard Hinnant756c69b2010-09-22 16:48:34 +00004005 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant9dd7e892010-05-31 20:58:54 +00004006 streambuf* rdbuf() const {return __bufptr_;}
Howard Hinnant756c69b2010-09-22 16:48:34 +00004007 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant9dd7e892010-05-31 20:58:54 +00004008 streambuf* rdbuf(streambuf* __bytebuf)
4009 {
4010 streambuf* __r = __bufptr_;
4011 __bufptr_ = __bytebuf;
4012 return __r;
4013 }
4014
Howard Hinnant756c69b2010-09-22 16:48:34 +00004015 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant0ac182a2010-06-01 20:09:18 +00004016 state_type state() const {return __st_;}
Howard Hinnant9dd7e892010-05-31 20:58:54 +00004017
4018protected:
Howard Hinnant0ac182a2010-06-01 20:09:18 +00004019 virtual int_type underflow();
4020 virtual int_type pbackfail(int_type __c = traits_type::eof());
Howard Hinnant9dd7e892010-05-31 20:58:54 +00004021 virtual int_type overflow (int_type __c = traits_type::eof());
Howard Hinnant0ac182a2010-06-01 20:09:18 +00004022 virtual basic_streambuf<char_type, traits_type>* setbuf(char_type* __s,
4023 streamsize __n);
4024 virtual pos_type seekoff(off_type __off, ios_base::seekdir __way,
4025 ios_base::openmode __wch = ios_base::in | ios_base::out);
4026 virtual pos_type seekpos(pos_type __sp,
4027 ios_base::openmode __wch = ios_base::in | ios_base::out);
4028 virtual int sync();
4029
4030private:
4031 bool __read_mode();
4032 void __write_mode();
4033 wbuffer_convert* __close();
Howard Hinnant9dd7e892010-05-31 20:58:54 +00004034};
4035
4036template <class _Codecvt, class _Elem, class _Tr>
Howard Hinnant0ac182a2010-06-01 20:09:18 +00004037wbuffer_convert<_Codecvt, _Elem, _Tr>::
4038 wbuffer_convert(streambuf* __bytebuf, _Codecvt* __pcvt, state_type __state)
Bruce Mitchener170d8972020-11-24 12:53:53 -05004039 : __extbuf_(nullptr),
4040 __extbufnext_(nullptr),
4041 __extbufend_(nullptr),
Howard Hinnant0ac182a2010-06-01 20:09:18 +00004042 __ebs_(0),
4043 __intbuf_(0),
4044 __ibs_(0),
4045 __bufptr_(__bytebuf),
4046 __cv_(__pcvt),
4047 __st_(__state),
4048 __cm_(0),
4049 __owns_eb_(false),
4050 __owns_ib_(false),
4051 __always_noconv_(__cv_ ? __cv_->always_noconv() : false)
4052{
4053 setbuf(0, 4096);
4054}
4055
4056template <class _Codecvt, class _Elem, class _Tr>
4057wbuffer_convert<_Codecvt, _Elem, _Tr>::~wbuffer_convert()
4058{
4059 __close();
4060 delete __cv_;
4061 if (__owns_eb_)
4062 delete [] __extbuf_;
4063 if (__owns_ib_)
4064 delete [] __intbuf_;
4065}
4066
4067template <class _Codecvt, class _Elem, class _Tr>
4068typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
4069wbuffer_convert<_Codecvt, _Elem, _Tr>::underflow()
4070{
4071 if (__cv_ == 0 || __bufptr_ == 0)
4072 return traits_type::eof();
4073 bool __initial = __read_mode();
4074 char_type __1buf;
4075 if (this->gptr() == 0)
4076 this->setg(&__1buf, &__1buf+1, &__1buf+1);
4077 const size_t __unget_sz = __initial ? 0 : min<size_t>((this->egptr() - this->eback()) / 2, 4);
4078 int_type __c = traits_type::eof();
4079 if (this->gptr() == this->egptr())
4080 {
Arthur O'Dwyer22236632020-12-07 21:50:15 -05004081 _VSTD::memmove(this->eback(), this->egptr() - __unget_sz, __unget_sz * sizeof(char_type));
Howard Hinnant0ac182a2010-06-01 20:09:18 +00004082 if (__always_noconv_)
4083 {
4084 streamsize __nmemb = static_cast<streamsize>(this->egptr() - this->eback() - __unget_sz);
4085 __nmemb = __bufptr_->sgetn((char*)this->eback() + __unget_sz, __nmemb);
4086 if (__nmemb != 0)
4087 {
4088 this->setg(this->eback(),
4089 this->eback() + __unget_sz,
4090 this->eback() + __unget_sz + __nmemb);
4091 __c = *this->gptr();
4092 }
4093 }
4094 else
4095 {
Eric Fiselier98e428d2016-06-19 06:58:22 +00004096 _LIBCPP_ASSERT(!(__extbufnext_ == NULL && (__extbufend_ != __extbufnext_)), "underflow moving from NULL" );
4097 if (__extbufend_ != __extbufnext_)
Arthur O'Dwyer22236632020-12-07 21:50:15 -05004098 _VSTD::memmove(__extbuf_, __extbufnext_, __extbufend_ - __extbufnext_);
Howard Hinnant0ac182a2010-06-01 20:09:18 +00004099 __extbufnext_ = __extbuf_ + (__extbufend_ - __extbufnext_);
4100 __extbufend_ = __extbuf_ + (__extbuf_ == __extbuf_min_ ? sizeof(__extbuf_min_) : __ebs_);
Howard Hinnantb1ad5a82011-06-30 21:18:19 +00004101 streamsize __nmemb = _VSTD::min(static_cast<streamsize>(this->egptr() - this->eback() - __unget_sz),
Howard Hinnant0ac182a2010-06-01 20:09:18 +00004102 static_cast<streamsize>(__extbufend_ - __extbufnext_));
4103 codecvt_base::result __r;
Eric Fiselier6003c772016-12-23 23:37:52 +00004104 // FIXME: Do we ever need to restore the state here?
4105 //state_type __svs = __st_;
Howard Hinnant0ac182a2010-06-01 20:09:18 +00004106 streamsize __nr = __bufptr_->sgetn(const_cast<char*>(__extbufnext_), __nmemb);
4107 if (__nr != 0)
4108 {
4109 __extbufend_ = __extbufnext_ + __nr;
4110 char_type* __inext;
4111 __r = __cv_->in(__st_, __extbuf_, __extbufend_, __extbufnext_,
4112 this->eback() + __unget_sz,
4113 this->egptr(), __inext);
4114 if (__r == codecvt_base::noconv)
4115 {
Louis Dionne173f29e2019-05-29 16:01:36 +00004116 this->setg((char_type*)__extbuf_, (char_type*)__extbuf_,
Marshall Clowbeda7142017-06-14 20:00:36 +00004117 (char_type*) const_cast<char *>(__extbufend_));
Howard Hinnant0ac182a2010-06-01 20:09:18 +00004118 __c = *this->gptr();
4119 }
4120 else if (__inext != this->eback() + __unget_sz)
4121 {
4122 this->setg(this->eback(), this->eback() + __unget_sz, __inext);
4123 __c = *this->gptr();
4124 }
4125 }
4126 }
4127 }
4128 else
4129 __c = *this->gptr();
4130 if (this->eback() == &__1buf)
4131 this->setg(0, 0, 0);
4132 return __c;
4133}
4134
4135template <class _Codecvt, class _Elem, class _Tr>
4136typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
4137wbuffer_convert<_Codecvt, _Elem, _Tr>::pbackfail(int_type __c)
4138{
4139 if (__cv_ != 0 && __bufptr_ != 0 && this->eback() < this->gptr())
4140 {
4141 if (traits_type::eq_int_type(__c, traits_type::eof()))
4142 {
4143 this->gbump(-1);
4144 return traits_type::not_eof(__c);
4145 }
4146 if (traits_type::eq(traits_type::to_char_type(__c), this->gptr()[-1]))
4147 {
4148 this->gbump(-1);
4149 *this->gptr() = traits_type::to_char_type(__c);
4150 return __c;
4151 }
4152 }
4153 return traits_type::eof();
4154}
4155
4156template <class _Codecvt, class _Elem, class _Tr>
Howard Hinnant9dd7e892010-05-31 20:58:54 +00004157typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
4158wbuffer_convert<_Codecvt, _Elem, _Tr>::overflow(int_type __c)
4159{
Howard Hinnant0ac182a2010-06-01 20:09:18 +00004160 if (__cv_ == 0 || __bufptr_ == 0)
4161 return traits_type::eof();
4162 __write_mode();
4163 char_type __1buf;
4164 char_type* __pb_save = this->pbase();
4165 char_type* __epb_save = this->epptr();
4166 if (!traits_type::eq_int_type(__c, traits_type::eof()))
4167 {
4168 if (this->pptr() == 0)
4169 this->setp(&__1buf, &__1buf+1);
4170 *this->pptr() = traits_type::to_char_type(__c);
4171 this->pbump(1);
4172 }
4173 if (this->pptr() != this->pbase())
4174 {
4175 if (__always_noconv_)
4176 {
4177 streamsize __nmemb = static_cast<streamsize>(this->pptr() - this->pbase());
4178 if (__bufptr_->sputn((const char*)this->pbase(), __nmemb) != __nmemb)
4179 return traits_type::eof();
4180 }
4181 else
4182 {
4183 char* __extbe = __extbuf_;
4184 codecvt_base::result __r;
4185 do
4186 {
4187 const char_type* __e;
4188 __r = __cv_->out(__st_, this->pbase(), this->pptr(), __e,
4189 __extbuf_, __extbuf_ + __ebs_, __extbe);
4190 if (__e == this->pbase())
4191 return traits_type::eof();
4192 if (__r == codecvt_base::noconv)
4193 {
4194 streamsize __nmemb = static_cast<size_t>(this->pptr() - this->pbase());
4195 if (__bufptr_->sputn((const char*)this->pbase(), __nmemb) != __nmemb)
4196 return traits_type::eof();
4197 }
4198 else if (__r == codecvt_base::ok || __r == codecvt_base::partial)
4199 {
4200 streamsize __nmemb = static_cast<size_t>(__extbe - __extbuf_);
4201 if (__bufptr_->sputn(__extbuf_, __nmemb) != __nmemb)
4202 return traits_type::eof();
4203 if (__r == codecvt_base::partial)
4204 {
Marshall Clowbeda7142017-06-14 20:00:36 +00004205 this->setp(const_cast<char_type *>(__e), this->pptr());
Marshall Clow33932622017-09-12 15:00:43 +00004206 this->__pbump(this->epptr() - this->pbase());
Howard Hinnant0ac182a2010-06-01 20:09:18 +00004207 }
4208 }
4209 else
4210 return traits_type::eof();
4211 } while (__r == codecvt_base::partial);
4212 }
4213 this->setp(__pb_save, __epb_save);
4214 }
4215 return traits_type::not_eof(__c);
4216}
4217
4218template <class _Codecvt, class _Elem, class _Tr>
4219basic_streambuf<_Elem, _Tr>*
4220wbuffer_convert<_Codecvt, _Elem, _Tr>::setbuf(char_type* __s, streamsize __n)
4221{
4222 this->setg(0, 0, 0);
4223 this->setp(0, 0);
4224 if (__owns_eb_)
4225 delete [] __extbuf_;
4226 if (__owns_ib_)
4227 delete [] __intbuf_;
4228 __ebs_ = __n;
4229 if (__ebs_ > sizeof(__extbuf_min_))
4230 {
4231 if (__always_noconv_ && __s)
4232 {
4233 __extbuf_ = (char*)__s;
4234 __owns_eb_ = false;
4235 }
4236 else
4237 {
4238 __extbuf_ = new char[__ebs_];
4239 __owns_eb_ = true;
4240 }
4241 }
4242 else
4243 {
4244 __extbuf_ = __extbuf_min_;
4245 __ebs_ = sizeof(__extbuf_min_);
4246 __owns_eb_ = false;
4247 }
4248 if (!__always_noconv_)
4249 {
4250 __ibs_ = max<streamsize>(__n, sizeof(__extbuf_min_));
4251 if (__s && __ibs_ >= sizeof(__extbuf_min_))
4252 {
4253 __intbuf_ = __s;
4254 __owns_ib_ = false;
4255 }
4256 else
4257 {
4258 __intbuf_ = new char_type[__ibs_];
4259 __owns_ib_ = true;
4260 }
4261 }
4262 else
4263 {
4264 __ibs_ = 0;
4265 __intbuf_ = 0;
4266 __owns_ib_ = false;
4267 }
4268 return this;
4269}
4270
4271template <class _Codecvt, class _Elem, class _Tr>
4272typename wbuffer_convert<_Codecvt, _Elem, _Tr>::pos_type
4273wbuffer_convert<_Codecvt, _Elem, _Tr>::seekoff(off_type __off, ios_base::seekdir __way,
4274 ios_base::openmode __om)
4275{
4276 int __width = __cv_->encoding();
4277 if (__cv_ == 0 || __bufptr_ == 0 || (__width <= 0 && __off != 0) || sync())
4278 return pos_type(off_type(-1));
Marshall Clowc2a72762015-08-27 14:37:22 +00004279 // __width > 0 || __off == 0, now check __way
4280 if (__way != ios_base::beg && __way != ios_base::cur && __way != ios_base::end)
Howard Hinnant0ac182a2010-06-01 20:09:18 +00004281 return pos_type(off_type(-1));
Howard Hinnant0ac182a2010-06-01 20:09:18 +00004282 pos_type __r = __bufptr_->pubseekoff(__width * __off, __way, __om);
4283 __r.state(__st_);
4284 return __r;
4285}
4286
4287template <class _Codecvt, class _Elem, class _Tr>
4288typename wbuffer_convert<_Codecvt, _Elem, _Tr>::pos_type
4289wbuffer_convert<_Codecvt, _Elem, _Tr>::seekpos(pos_type __sp, ios_base::openmode __wch)
4290{
4291 if (__cv_ == 0 || __bufptr_ == 0 || sync())
4292 return pos_type(off_type(-1));
4293 if (__bufptr_->pubseekpos(__sp, __wch) == pos_type(off_type(-1)))
4294 return pos_type(off_type(-1));
4295 return __sp;
4296}
4297
4298template <class _Codecvt, class _Elem, class _Tr>
4299int
4300wbuffer_convert<_Codecvt, _Elem, _Tr>::sync()
4301{
4302 if (__cv_ == 0 || __bufptr_ == 0)
4303 return 0;
4304 if (__cm_ & ios_base::out)
4305 {
4306 if (this->pptr() != this->pbase())
4307 if (overflow() == traits_type::eof())
4308 return -1;
4309 codecvt_base::result __r;
4310 do
4311 {
4312 char* __extbe;
4313 __r = __cv_->unshift(__st_, __extbuf_, __extbuf_ + __ebs_, __extbe);
4314 streamsize __nmemb = static_cast<streamsize>(__extbe - __extbuf_);
4315 if (__bufptr_->sputn(__extbuf_, __nmemb) != __nmemb)
4316 return -1;
4317 } while (__r == codecvt_base::partial);
4318 if (__r == codecvt_base::error)
4319 return -1;
4320 if (__bufptr_->pubsync())
4321 return -1;
4322 }
4323 else if (__cm_ & ios_base::in)
4324 {
4325 off_type __c;
4326 if (__always_noconv_)
4327 __c = this->egptr() - this->gptr();
4328 else
4329 {
4330 int __width = __cv_->encoding();
4331 __c = __extbufend_ - __extbufnext_;
4332 if (__width > 0)
4333 __c += __width * (this->egptr() - this->gptr());
4334 else
4335 {
4336 if (this->gptr() != this->egptr())
4337 {
4338 reverse(this->gptr(), this->egptr());
4339 codecvt_base::result __r;
4340 const char_type* __e = this->gptr();
4341 char* __extbe;
4342 do
4343 {
4344 __r = __cv_->out(__st_, __e, this->egptr(), __e,
4345 __extbuf_, __extbuf_ + __ebs_, __extbe);
4346 switch (__r)
4347 {
4348 case codecvt_base::noconv:
4349 __c += this->egptr() - this->gptr();
4350 break;
4351 case codecvt_base::ok:
4352 case codecvt_base::partial:
4353 __c += __extbe - __extbuf_;
4354 break;
4355 default:
4356 return -1;
4357 }
4358 } while (__r == codecvt_base::partial);
4359 }
4360 }
4361 }
4362 if (__bufptr_->pubseekoff(-__c, ios_base::cur, __cm_) == pos_type(off_type(-1)))
4363 return -1;
4364 this->setg(0, 0, 0);
4365 __cm_ = 0;
4366 }
4367 return 0;
4368}
4369
4370template <class _Codecvt, class _Elem, class _Tr>
4371bool
4372wbuffer_convert<_Codecvt, _Elem, _Tr>::__read_mode()
4373{
4374 if (!(__cm_ & ios_base::in))
4375 {
4376 this->setp(0, 0);
4377 if (__always_noconv_)
4378 this->setg((char_type*)__extbuf_,
4379 (char_type*)__extbuf_ + __ebs_,
4380 (char_type*)__extbuf_ + __ebs_);
4381 else
4382 this->setg(__intbuf_, __intbuf_ + __ibs_, __intbuf_ + __ibs_);
4383 __cm_ = ios_base::in;
4384 return true;
4385 }
4386 return false;
4387}
4388
4389template <class _Codecvt, class _Elem, class _Tr>
4390void
4391wbuffer_convert<_Codecvt, _Elem, _Tr>::__write_mode()
4392{
4393 if (!(__cm_ & ios_base::out))
4394 {
4395 this->setg(0, 0, 0);
4396 if (__ebs_ > sizeof(__extbuf_min_))
4397 {
4398 if (__always_noconv_)
4399 this->setp((char_type*)__extbuf_,
4400 (char_type*)__extbuf_ + (__ebs_ - 1));
4401 else
4402 this->setp(__intbuf_, __intbuf_ + (__ibs_ - 1));
4403 }
4404 else
4405 this->setp(0, 0);
4406 __cm_ = ios_base::out;
4407 }
4408}
4409
4410template <class _Codecvt, class _Elem, class _Tr>
4411wbuffer_convert<_Codecvt, _Elem, _Tr>*
4412wbuffer_convert<_Codecvt, _Elem, _Tr>::__close()
4413{
Bruce Mitchener170d8972020-11-24 12:53:53 -05004414 wbuffer_convert* __rt = nullptr;
4415 if (__cv_ != nullptr && __bufptr_ != nullptr)
Howard Hinnant0ac182a2010-06-01 20:09:18 +00004416 {
4417 __rt = this;
4418 if ((__cm_ & ios_base::out) && sync())
Bruce Mitchener170d8972020-11-24 12:53:53 -05004419 __rt = nullptr;
Howard Hinnant0ac182a2010-06-01 20:09:18 +00004420 }
4421 return __rt;
Howard Hinnant9dd7e892010-05-31 20:58:54 +00004422}
4423
Howard Hinnantc51e1022010-05-11 19:42:16 +00004424_LIBCPP_END_NAMESPACE_STD
4425
Eric Fiselierf4433a32017-05-31 22:07:49 +00004426_LIBCPP_POP_MACROS
4427
Louis Dionne2b1ceaa2021-04-20 12:03:32 -04004428#endif // _LIBCPP_LOCALE