blob: 411059befa1d8380817897683a8c93d886ee1016 [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
Marshall Clowccaa0fb2013-08-27 20:18:59 +000095 explicit wstring_convert(Codecvt* pcvt = new Codecvt); // explicit in C++14
Howard Hinnant9dd7e892010-05-31 20:58:54 +000096 wstring_convert(Codecvt* pcvt, state_type state);
Marshall Clowccaa0fb2013-08-27 20:18:59 +000097 explicit wstring_convert(const byte_string& byte_err, // explicit in C++14
Howard Hinnant9dd7e892010-05-31 20:58:54 +000098 const wide_string& wide_err = wide_string());
Marshall Clowccaa0fb2013-08-27 20:18:59 +000099 wstring_convert(const wstring_convert&) = delete; // C++14
100 wstring_convert & operator=(const wstring_convert &) = delete; // C++14
Howard Hinnant9dd7e892010-05-31 20:58:54 +0000101 ~wstring_convert();
102
103 wide_string from_bytes(char byte);
104 wide_string from_bytes(const char* ptr);
105 wide_string from_bytes(const byte_string& str);
106 wide_string from_bytes(const char* first, const char* last);
107
108 byte_string to_bytes(Elem wchar);
109 byte_string to_bytes(const Elem* wptr);
110 byte_string to_bytes(const wide_string& wstr);
111 byte_string to_bytes(const Elem* first, const Elem* last);
112
Marshall Clowccaa0fb2013-08-27 20:18:59 +0000113 size_t converted() const; // noexcept in C++14
Howard Hinnant9dd7e892010-05-31 20:58:54 +0000114 state_type state() const;
115};
116
Howard Hinnantc51e1022010-05-11 19:42:16 +0000117template <class Codecvt, class Elem = wchar_t, class Tr = char_traits<Elem>>
Howard Hinnant9dd7e892010-05-31 20:58:54 +0000118class wbuffer_convert
119 : public basic_streambuf<Elem, Tr>
120{
121public:
122 typedef typename Tr::state_type state_type;
123
Marshall Clowccaa0fb2013-08-27 20:18:59 +0000124 explicit wbuffer_convert(streambuf* bytebuf = 0, Codecvt* pcvt = new Codecvt,
125 state_type state = state_type()); // explicit in C++14
126 wbuffer_convert(const wbuffer_convert&) = delete; // C++14
127 wbuffer_convert & operator=(const wbuffer_convert &) = delete; // C++14
128 ~wbuffer_convert(); // C++14
Louis Dionne173f29e2019-05-29 16:01:36 +0000129
Howard Hinnant9dd7e892010-05-31 20:58:54 +0000130 streambuf* rdbuf() const;
131 streambuf* rdbuf(streambuf* bytebuf);
132
133 state_type state() const;
134};
Howard Hinnantc51e1022010-05-11 19:42:16 +0000135
136// 22.4.1 and 22.4.1.3, ctype:
137class ctype_base;
138template <class charT> class ctype;
139template <> class ctype<char>; // specialization
140template <class charT> class ctype_byname;
141template <> class ctype_byname<char>; // specialization
142
143class codecvt_base;
144template <class internT, class externT, class stateT> class codecvt;
145template <class internT, class externT, class stateT> class codecvt_byname;
146
147// 22.4.2 and 22.4.3, numeric:
148template <class charT, class InputIterator> class num_get;
149template <class charT, class OutputIterator> class num_put;
150template <class charT> class numpunct;
151template <class charT> class numpunct_byname;
152
153// 22.4.4, col lation:
154template <class charT> class collate;
155template <class charT> class collate_byname;
156
157// 22.4.5, date and time:
158class time_base;
159template <class charT, class InputIterator> class time_get;
160template <class charT, class InputIterator> class time_get_byname;
161template <class charT, class OutputIterator> class time_put;
162template <class charT, class OutputIterator> class time_put_byname;
163
164// 22.4.6, money:
165class money_base;
166template <class charT, class InputIterator> class money_get;
167template <class charT, class OutputIterator> class money_put;
168template <class charT, bool Intl> class moneypunct;
169template <class charT, bool Intl> class moneypunct_byname;
170
171// 22.4.7, message retrieval:
172class messages_base;
173template <class charT> class messages;
174template <class charT> class messages_byname;
175
176} // std
177
178*/
179
180#include <__config>
181#include <__locale>
Eric Fiselier98e428d2016-06-19 06:58:22 +0000182#include <__debug>
Howard Hinnantc51e1022010-05-11 19:42:16 +0000183#include <algorithm>
184#include <memory>
185#include <ios>
186#include <streambuf>
187#include <iterator>
188#include <limits>
Marshall Clow8732fed2018-12-11 04:35:44 +0000189#include <version>
Marshall Clowdde4bfe2013-03-18 17:45:34 +0000190#ifndef __APPLE__
Howard Hinnant155c2af2010-05-24 17:49:41 +0000191#include <cstdarg>
192#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000193#include <cstdlib>
194#include <ctime>
Eric Fiselierbb999f92017-05-31 22:14:05 +0000195#include <cstdio>
Ed Schouten118b6032015-03-11 16:39:36 +0000196#ifdef _LIBCPP_HAS_CATOPEN
Howard Hinnantc51e1022010-05-11 19:42:16 +0000197#include <nl_types.h>
Marshall Clow3477ec92014-07-10 15:20:28 +0000198#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000199
Ben Craig3756b922016-03-09 15:39:39 +0000200#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
201#include <__bsd_locale_defaults.h>
202#else
203#include <__bsd_locale_fallbacks.h>
204#endif
205
Eric Fiselierf4433a32017-05-31 22:07:49 +0000206#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
207#pragma GCC system_header
208#endif
209
210_LIBCPP_PUSH_MACROS
211#include <__undef_macros>
212
213
Howard Hinnantc51e1022010-05-11 19:42:16 +0000214_LIBCPP_BEGIN_NAMESPACE_STD
215
Marshall Clow82378c02013-03-18 19:34:07 +0000216#if defined(__APPLE__) || defined(__FreeBSD__)
Howard Hinnant1ab52da2011-09-28 21:05:01 +0000217# define _LIBCPP_GET_C_LOCALE 0
Ed Schoutenaa497c82015-03-10 09:35:22 +0000218#elif defined(__CloudABI__) || defined(__NetBSD__)
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000219# define _LIBCPP_GET_C_LOCALE LC_C_LOCALE
Howard Hinnant1ab52da2011-09-28 21:05:01 +0000220#else
221# define _LIBCPP_GET_C_LOCALE __cloc()
Howard Hinnantf312e3e2011-09-28 23:39:33 +0000222 // Get the C locale object
Howard Hinnanta37d3cf2013-08-12 18:38:34 +0000223 _LIBCPP_FUNC_VIS locale_t __cloc();
Howard Hinnantf312e3e2011-09-28 23:39:33 +0000224#define __cloc_defined
Howard Hinnant1ab52da2011-09-28 21:05:01 +0000225#endif
226
Howard Hinnantc51e1022010-05-11 19:42:16 +0000227// __scan_keyword
228// Scans [__b, __e) until a match is found in the basic_strings range
229// [__kb, __ke) or until it can be shown that there is no match in [__kb, __ke).
230// __b will be incremented (visibly), consuming CharT until a match is found
231// or proved to not exist. A keyword may be "", in which will match anything.
232// If one keyword is a prefix of another, and the next CharT in the input
233// might match another keyword, the algorithm will attempt to find the longest
234// matching keyword. If the longer matching keyword ends up not matching, then
235// no keyword match is found. If no keyword match is found, __ke is returned
236// and failbit is set in __err.
237// Else an iterator pointing to the matching keyword is found. If more than
238// one keyword matches, an iterator to the first matching keyword is returned.
Alp Tokerb8a95f52014-05-15 11:27:39 +0000239// If on exit __b == __e, eofbit is set in __err. If __case_sensitive is false,
Howard Hinnantc51e1022010-05-11 19:42:16 +0000240// __ct is used to force to lower case before comparing characters.
241// Examples:
242// Keywords: "a", "abb"
243// If the input is "a", the first keyword matches and eofbit is set.
244// If the input is "abc", no match is found and "ab" are consumed.
245template <class _InputIterator, class _ForwardIterator, class _Ctype>
246_LIBCPP_HIDDEN
247_ForwardIterator
248__scan_keyword(_InputIterator& __b, _InputIterator __e,
249 _ForwardIterator __kb, _ForwardIterator __ke,
250 const _Ctype& __ct, ios_base::iostate& __err,
251 bool __case_sensitive = true)
252{
253 typedef typename iterator_traits<_InputIterator>::value_type _CharT;
Howard Hinnant28b24882011-12-01 20:21:04 +0000254 size_t __nkw = static_cast<size_t>(_VSTD::distance(__kb, __ke));
Howard Hinnantc51e1022010-05-11 19:42:16 +0000255 const unsigned char __doesnt_match = '\0';
256 const unsigned char __might_match = '\1';
257 const unsigned char __does_match = '\2';
258 unsigned char __statbuf[100];
259 unsigned char* __status = __statbuf;
Bruce Mitchener170d8972020-11-24 12:53:53 -0500260 unique_ptr<unsigned char, void(*)(void*)> __stat_hold(nullptr, free);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000261 if (__nkw > sizeof(__statbuf))
262 {
263 __status = (unsigned char*)malloc(__nkw);
Bruce Mitchener170d8972020-11-24 12:53:53 -0500264 if (__status == nullptr)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000265 __throw_bad_alloc();
266 __stat_hold.reset(__status);
267 }
268 size_t __n_might_match = __nkw; // At this point, any keyword might match
269 size_t __n_does_match = 0; // but none of them definitely do
270 // Initialize all statuses to __might_match, except for "" keywords are __does_match
271 unsigned char* __st = __status;
Eric Fiseliera09a3b42014-10-27 19:28:20 +0000272 for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, (void) ++__st)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000273 {
274 if (!__ky->empty())
275 *__st = __might_match;
276 else
277 {
278 *__st = __does_match;
279 --__n_might_match;
280 ++__n_does_match;
281 }
282 }
283 // While there might be a match, test keywords against the next CharT
284 for (size_t __indx = 0; __b != __e && __n_might_match > 0; ++__indx)
285 {
286 // Peek at the next CharT but don't consume it
287 _CharT __c = *__b;
288 if (!__case_sensitive)
289 __c = __ct.toupper(__c);
290 bool __consume = false;
291 // For each keyword which might match, see if the __indx character is __c
292 // If a match if found, consume __c
293 // If a match is found, and that is the last character in the keyword,
294 // then that keyword matches.
295 // If the keyword doesn't match this character, then change the keyword
296 // to doesn't match
297 __st = __status;
Eric Fiseliera09a3b42014-10-27 19:28:20 +0000298 for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, (void) ++__st)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000299 {
300 if (*__st == __might_match)
301 {
302 _CharT __kc = (*__ky)[__indx];
303 if (!__case_sensitive)
304 __kc = __ct.toupper(__kc);
305 if (__c == __kc)
306 {
307 __consume = true;
308 if (__ky->size() == __indx+1)
309 {
310 *__st = __does_match;
311 --__n_might_match;
312 ++__n_does_match;
313 }
314 }
315 else
316 {
317 *__st = __doesnt_match;
318 --__n_might_match;
319 }
320 }
321 }
322 // consume if we matched a character
323 if (__consume)
324 {
325 ++__b;
326 // If we consumed a character and there might be a matched keyword that
327 // was marked matched on a previous iteration, then such keywords
328 // which are now marked as not matching.
329 if (__n_might_match + __n_does_match > 1)
330 {
331 __st = __status;
Eric Fiseliera09a3b42014-10-27 19:28:20 +0000332 for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, (void) ++__st)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000333 {
334 if (*__st == __does_match && __ky->size() != __indx+1)
335 {
336 *__st = __doesnt_match;
337 --__n_does_match;
338 }
339 }
340 }
341 }
342 }
343 // We've exited the loop because we hit eof and/or we have no more "might matches".
344 if (__b == __e)
345 __err |= ios_base::eofbit;
346 // Return the first matching result
Eric Fiseliera09a3b42014-10-27 19:28:20 +0000347 for (__st = __status; __kb != __ke; ++__kb, (void) ++__st)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000348 if (*__st == __does_match)
349 break;
350 if (__kb == __ke)
351 __err |= ios_base::failbit;
352 return __kb;
353}
354
Howard Hinnanta37d3cf2013-08-12 18:38:34 +0000355struct _LIBCPP_TYPE_VIS __num_get_base
Howard Hinnantc51e1022010-05-11 19:42:16 +0000356{
357 static const int __num_get_buf_sz = 40;
358
359 static int __get_base(ios_base&);
360 static const char __src[33];
361};
362
Howard Hinnanta37d3cf2013-08-12 18:38:34 +0000363_LIBCPP_FUNC_VIS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000364void __check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
365 ios_base::iostate& __err);
366
Howard Hinnantc51e1022010-05-11 19:42:16 +0000367template <class _CharT>
368struct __num_get
369 : protected __num_get_base
370{
Howard Hinnantc51e1022010-05-11 19:42:16 +0000371 static string __stage2_float_prep(ios_base& __iob, _CharT* __atoms, _CharT& __decimal_point,
372 _CharT& __thousands_sep);
Aditya Kumaraa866182017-06-14 23:17:45 +0000373
Howard Hinnantc51e1022010-05-11 19:42:16 +0000374 static int __stage2_float_loop(_CharT __ct, bool& __in_units, char& __exp,
375 char* __a, char*& __a_end,
376 _CharT __decimal_point, _CharT __thousands_sep,
377 const string& __grouping, unsigned* __g,
378 unsigned*& __g_end, unsigned& __dc, _CharT* __atoms);
Aditya Kumaraa866182017-06-14 23:17:45 +0000379#ifndef _LIBCPP_ABI_OPTIMIZED_LOCALE_NUM_GET
380 static string __stage2_int_prep(ios_base& __iob, _CharT* __atoms, _CharT& __thousands_sep);
381 static int __stage2_int_loop(_CharT __ct, int __base, char* __a, char*& __a_end,
382 unsigned& __dc, _CharT __thousands_sep, const string& __grouping,
383 unsigned* __g, unsigned*& __g_end, _CharT* __atoms);
384
385#else
386 static string __stage2_int_prep(ios_base& __iob, _CharT& __thousands_sep)
387 {
388 locale __loc = __iob.getloc();
389 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
390 __thousands_sep = __np.thousands_sep();
391 return __np.grouping();
392 }
393
394 const _CharT* __do_widen(ios_base& __iob, _CharT* __atoms) const
395 {
396 return __do_widen_p(__iob, __atoms);
397 }
398
399
400 static int __stage2_int_loop(_CharT __ct, int __base, char* __a, char*& __a_end,
401 unsigned& __dc, _CharT __thousands_sep, const string& __grouping,
402 unsigned* __g, unsigned*& __g_end, const _CharT* __atoms);
403private:
404 template<typename T>
405 const T* __do_widen_p(ios_base& __iob, T* __atoms) const
406 {
407 locale __loc = __iob.getloc();
408 use_facet<ctype<T> >(__loc).widen(__src, __src + 26, __atoms);
409 return __atoms;
410 }
411
412 const char* __do_widen_p(ios_base& __iob, char* __atoms) const
413 {
414 (void)__iob;
415 (void)__atoms;
416 return __src;
417 }
418#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000419};
420
Aditya Kumaraa866182017-06-14 23:17:45 +0000421#ifndef _LIBCPP_ABI_OPTIMIZED_LOCALE_NUM_GET
Howard Hinnantc51e1022010-05-11 19:42:16 +0000422template <class _CharT>
423string
424__num_get<_CharT>::__stage2_int_prep(ios_base& __iob, _CharT* __atoms, _CharT& __thousands_sep)
425{
426 locale __loc = __iob.getloc();
427 use_facet<ctype<_CharT> >(__loc).widen(__src, __src + 26, __atoms);
428 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
429 __thousands_sep = __np.thousands_sep();
430 return __np.grouping();
431}
Aditya Kumaraa866182017-06-14 23:17:45 +0000432#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000433
434template <class _CharT>
435string
436__num_get<_CharT>::__stage2_float_prep(ios_base& __iob, _CharT* __atoms, _CharT& __decimal_point,
437 _CharT& __thousands_sep)
438{
439 locale __loc = __iob.getloc();
440 use_facet<ctype<_CharT> >(__loc).widen(__src, __src + 32, __atoms);
441 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
442 __decimal_point = __np.decimal_point();
443 __thousands_sep = __np.thousands_sep();
444 return __np.grouping();
445}
446
447template <class _CharT>
448int
Aditya Kumaraa866182017-06-14 23:17:45 +0000449#ifndef _LIBCPP_ABI_OPTIMIZED_LOCALE_NUM_GET
Howard Hinnantc51e1022010-05-11 19:42:16 +0000450__num_get<_CharT>::__stage2_int_loop(_CharT __ct, int __base, char* __a, char*& __a_end,
451 unsigned& __dc, _CharT __thousands_sep, const string& __grouping,
452 unsigned* __g, unsigned*& __g_end, _CharT* __atoms)
Aditya Kumaraa866182017-06-14 23:17:45 +0000453#else
454__num_get<_CharT>::__stage2_int_loop(_CharT __ct, int __base, char* __a, char*& __a_end,
455 unsigned& __dc, _CharT __thousands_sep, const string& __grouping,
456 unsigned* __g, unsigned*& __g_end, const _CharT* __atoms)
457
458#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000459{
Howard Hinnantf57b3fc2011-03-09 01:03:19 +0000460 if (__a_end == __a && (__ct == __atoms[24] || __ct == __atoms[25]))
461 {
462 *__a_end++ = __ct == __atoms[24] ? '+' : '-';
463 __dc = 0;
464 return 0;
465 }
Howard Hinnant28b24882011-12-01 20:21:04 +0000466 if (__grouping.size() != 0 && __ct == __thousands_sep)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000467 {
468 if (__g_end-__g < __num_get_buf_sz)
469 {
470 *__g_end++ = __dc;
471 __dc = 0;
472 }
473 return 0;
474 }
475 ptrdiff_t __f = find(__atoms, __atoms + 26, __ct) - __atoms;
Howard Hinnantf57b3fc2011-03-09 01:03:19 +0000476 if (__f >= 24)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000477 return -1;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000478 switch (__base)
479 {
480 case 8:
481 case 10:
482 if (__f >= __base)
Howard Hinnantf57b3fc2011-03-09 01:03:19 +0000483 return -1;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000484 break;
Howard Hinnantf57b3fc2011-03-09 01:03:19 +0000485 case 16:
486 if (__f < 22)
487 break;
488 if (__a_end != __a && __a_end - __a <= 2 && __a_end[-1] == '0')
489 {
490 __dc = 0;
491 *__a_end++ = __src[__f];
Howard Hinnantc51e1022010-05-11 19:42:16 +0000492 return 0;
Howard Hinnantf57b3fc2011-03-09 01:03:19 +0000493 }
494 return -1;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000495 }
Howard Hinnant5d4013d2013-04-15 20:40:06 +0000496 *__a_end++ = __src[__f];
Howard Hinnantc51e1022010-05-11 19:42:16 +0000497 ++__dc;
498 return 0;
499}
500
501template <class _CharT>
502int
503__num_get<_CharT>::__stage2_float_loop(_CharT __ct, bool& __in_units, char& __exp, char* __a, char*& __a_end,
504 _CharT __decimal_point, _CharT __thousands_sep, const string& __grouping,
505 unsigned* __g, unsigned*& __g_end, unsigned& __dc, _CharT* __atoms)
506{
507 if (__ct == __decimal_point)
508 {
509 if (!__in_units)
510 return -1;
511 __in_units = false;
512 *__a_end++ = '.';
513 if (__grouping.size() != 0 && __g_end-__g < __num_get_buf_sz)
514 *__g_end++ = __dc;
515 return 0;
516 }
517 if (__ct == __thousands_sep && __grouping.size() != 0)
518 {
519 if (!__in_units)
520 return -1;
521 if (__g_end-__g < __num_get_buf_sz)
522 {
523 *__g_end++ = __dc;
524 __dc = 0;
525 }
526 return 0;
527 }
528 ptrdiff_t __f = find(__atoms, __atoms + 32, __ct) - __atoms;
529 if (__f >= 32)
530 return -1;
531 char __x = __src[__f];
Howard Hinnant5132e192012-02-15 19:19:37 +0000532 if (__x == '-' || __x == '+')
533 {
Howard Hinnant21413152013-03-08 19:06:24 +0000534 if (__a_end == __a || (__a_end[-1] & 0x5F) == (__exp & 0x7F))
Howard Hinnant5132e192012-02-15 19:19:37 +0000535 {
536 *__a_end++ = __x;
537 return 0;
538 }
539 return -1;
540 }
Howard Hinnantc51e1022010-05-11 19:42:16 +0000541 if (__x == 'x' || __x == 'X')
542 __exp = 'P';
Howard Hinnant21413152013-03-08 19:06:24 +0000543 else if ((__x & 0x5F) == __exp)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000544 {
Marshall Clow5ca73ad2019-02-01 21:59:27 +0000545 __exp |= (char) 0x80;
Howard Hinnant21413152013-03-08 19:06:24 +0000546 if (__in_units)
547 {
548 __in_units = false;
549 if (__grouping.size() != 0 && __g_end-__g < __num_get_buf_sz)
550 *__g_end++ = __dc;
551 }
Howard Hinnantc51e1022010-05-11 19:42:16 +0000552 }
Howard Hinnant5d4013d2013-04-15 20:40:06 +0000553 *__a_end++ = __x;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000554 if (__f >= 22)
555 return 0;
556 ++__dc;
557 return 0;
558}
559
Louis Dionneb5ae3a72020-10-02 14:29:48 -0400560_LIBCPP_EXTERN_TEMPLATE(struct _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __num_get<char>)
561_LIBCPP_EXTERN_TEMPLATE(struct _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __num_get<wchar_t>)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000562
563template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +0000564class _LIBCPP_TEMPLATE_VIS num_get
Howard Hinnantc51e1022010-05-11 19:42:16 +0000565 : public locale::facet,
566 private __num_get<_CharT>
567{
568public:
569 typedef _CharT char_type;
570 typedef _InputIterator iter_type;
571
Louis Dionne16fe2952018-07-11 23:14:33 +0000572 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +0000573 explicit num_get(size_t __refs = 0)
574 : locale::facet(__refs) {}
575
Louis Dionne16fe2952018-07-11 23:14:33 +0000576 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +0000577 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
578 ios_base::iostate& __err, bool& __v) const
579 {
580 return do_get(__b, __e, __iob, __err, __v);
581 }
582
Louis Dionne16fe2952018-07-11 23:14:33 +0000583 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +0000584 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
585 ios_base::iostate& __err, long& __v) const
586 {
587 return do_get(__b, __e, __iob, __err, __v);
588 }
589
Louis Dionne16fe2952018-07-11 23:14:33 +0000590 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +0000591 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
592 ios_base::iostate& __err, long long& __v) const
593 {
594 return do_get(__b, __e, __iob, __err, __v);
595 }
596
Louis Dionne16fe2952018-07-11 23:14:33 +0000597 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +0000598 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
599 ios_base::iostate& __err, unsigned short& __v) const
600 {
601 return do_get(__b, __e, __iob, __err, __v);
602 }
603
Louis Dionne16fe2952018-07-11 23:14:33 +0000604 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +0000605 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
606 ios_base::iostate& __err, unsigned int& __v) const
607 {
608 return do_get(__b, __e, __iob, __err, __v);
609 }
610
Louis Dionne16fe2952018-07-11 23:14:33 +0000611 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +0000612 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
613 ios_base::iostate& __err, unsigned long& __v) const
614 {
615 return do_get(__b, __e, __iob, __err, __v);
616 }
617
Louis Dionne16fe2952018-07-11 23:14:33 +0000618 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +0000619 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
620 ios_base::iostate& __err, unsigned long long& __v) const
621 {
622 return do_get(__b, __e, __iob, __err, __v);
623 }
624
Louis Dionne16fe2952018-07-11 23:14:33 +0000625 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +0000626 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
627 ios_base::iostate& __err, float& __v) const
628 {
629 return do_get(__b, __e, __iob, __err, __v);
630 }
631
Louis Dionne16fe2952018-07-11 23:14:33 +0000632 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +0000633 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
634 ios_base::iostate& __err, double& __v) const
635 {
636 return do_get(__b, __e, __iob, __err, __v);
637 }
638
Louis Dionne16fe2952018-07-11 23:14:33 +0000639 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +0000640 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
641 ios_base::iostate& __err, long double& __v) const
642 {
643 return do_get(__b, __e, __iob, __err, __v);
644 }
645
Louis Dionne16fe2952018-07-11 23:14:33 +0000646 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +0000647 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
648 ios_base::iostate& __err, void*& __v) const
649 {
650 return do_get(__b, __e, __iob, __err, __v);
651 }
652
653 static locale::id id;
654
655protected:
Louis Dionne16fe2952018-07-11 23:14:33 +0000656 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +0000657 ~num_get() {}
658
Marshall Clowae385382013-11-05 14:28:52 +0000659 template <class _Fp>
Shoaib Meenai69c57412017-03-02 03:02:50 +0000660 _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
661 iter_type __do_get_floating_point
Marshall Clowae385382013-11-05 14:28:52 +0000662 (iter_type __b, iter_type __e, ios_base& __iob,
663 ios_base::iostate& __err, _Fp& __v) const;
Marshall Clow96d86d82013-11-07 01:00:50 +0000664
665 template <class _Signed>
Shoaib Meenai69c57412017-03-02 03:02:50 +0000666 _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
667 iter_type __do_get_signed
Marshall Clow96d86d82013-11-07 01:00:50 +0000668 (iter_type __b, iter_type __e, ios_base& __iob,
669 ios_base::iostate& __err, _Signed& __v) const;
670
671 template <class _Unsigned>
Shoaib Meenai69c57412017-03-02 03:02:50 +0000672 _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
673 iter_type __do_get_unsigned
Marshall Clow96d86d82013-11-07 01:00:50 +0000674 (iter_type __b, iter_type __e, ios_base& __iob,
675 ios_base::iostate& __err, _Unsigned& __v) const;
676
677
678 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
679 ios_base::iostate& __err, bool& __v) const;
680
681 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
682 ios_base::iostate& __err, long& __v) const
683 { return this->__do_get_signed ( __b, __e, __iob, __err, __v ); }
684
685 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
686 ios_base::iostate& __err, long long& __v) const
687 { return this->__do_get_signed ( __b, __e, __iob, __err, __v ); }
688
689 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
690 ios_base::iostate& __err, unsigned short& __v) const
691 { return this->__do_get_unsigned ( __b, __e, __iob, __err, __v ); }
692
693 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
694 ios_base::iostate& __err, unsigned int& __v) const
695 { return this->__do_get_unsigned ( __b, __e, __iob, __err, __v ); }
696
697 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
698 ios_base::iostate& __err, unsigned long& __v) const
699 { return this->__do_get_unsigned ( __b, __e, __iob, __err, __v ); }
700
701 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
702 ios_base::iostate& __err, unsigned long long& __v) const
703 { return this->__do_get_unsigned ( __b, __e, __iob, __err, __v ); }
704
705 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
706 ios_base::iostate& __err, float& __v) const
707 { return this->__do_get_floating_point ( __b, __e, __iob, __err, __v ); }
708
709 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
710 ios_base::iostate& __err, double& __v) const
711 { return this->__do_get_floating_point ( __b, __e, __iob, __err, __v ); }
712
713 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
714 ios_base::iostate& __err, long double& __v) const
715 { return this->__do_get_floating_point ( __b, __e, __iob, __err, __v ); }
716
717 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
718 ios_base::iostate& __err, void*& __v) const;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000719};
720
721template <class _CharT, class _InputIterator>
722locale::id
723num_get<_CharT, _InputIterator>::id;
724
725template <class _Tp>
Louis Dionne9e70e362018-11-21 16:24:46 +0000726_LIBCPP_HIDDEN _Tp
Howard Hinnantc51e1022010-05-11 19:42:16 +0000727__num_get_signed_integral(const char* __a, const char* __a_end,
728 ios_base::iostate& __err, int __base)
729{
730 if (__a != __a_end)
731 {
Howard Hinnantca8923c2013-01-22 17:26:08 +0000732 typename remove_reference<decltype(errno)>::type __save_errno = errno;
Howard Hinnant05c71342011-02-25 19:52:41 +0000733 errno = 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000734 char *__p2;
Howard Hinnant1ab52da2011-09-28 21:05:01 +0000735 long long __ll = strtoll_l(__a, &__p2, __base, _LIBCPP_GET_C_LOCALE);
Howard Hinnantca8923c2013-01-22 17:26:08 +0000736 typename remove_reference<decltype(errno)>::type __current_errno = errno;
Howard Hinnant05c71342011-02-25 19:52:41 +0000737 if (__current_errno == 0)
738 errno = __save_errno;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000739 if (__p2 != __a_end)
740 {
741 __err = ios_base::failbit;
742 return 0;
743 }
Howard Hinnant05c71342011-02-25 19:52:41 +0000744 else if (__current_errno == ERANGE ||
745 __ll < numeric_limits<_Tp>::min() ||
746 numeric_limits<_Tp>::max() < __ll)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000747 {
748 __err = ios_base::failbit;
Howard Hinnant05c71342011-02-25 19:52:41 +0000749 if (__ll > 0)
750 return numeric_limits<_Tp>::max();
751 else
752 return numeric_limits<_Tp>::min();
Howard Hinnantc51e1022010-05-11 19:42:16 +0000753 }
754 return static_cast<_Tp>(__ll);
755 }
756 __err = ios_base::failbit;
757 return 0;
758}
759
760template <class _Tp>
Louis Dionne9e70e362018-11-21 16:24:46 +0000761_LIBCPP_HIDDEN _Tp
Howard Hinnantc51e1022010-05-11 19:42:16 +0000762__num_get_unsigned_integral(const char* __a, const char* __a_end,
763 ios_base::iostate& __err, int __base)
764{
765 if (__a != __a_end)
766 {
Eric Fiselierc03318c2018-03-29 01:18:53 +0000767 const bool __negate = *__a == '-';
768 if (__negate && ++__a == __a_end) {
769 __err = ios_base::failbit;
770 return 0;
Howard Hinnant05c71342011-02-25 19:52:41 +0000771 }
Howard Hinnantca8923c2013-01-22 17:26:08 +0000772 typename remove_reference<decltype(errno)>::type __save_errno = errno;
Howard Hinnant05c71342011-02-25 19:52:41 +0000773 errno = 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000774 char *__p2;
Howard Hinnant1ab52da2011-09-28 21:05:01 +0000775 unsigned long long __ll = strtoull_l(__a, &__p2, __base, _LIBCPP_GET_C_LOCALE);
Howard Hinnantca8923c2013-01-22 17:26:08 +0000776 typename remove_reference<decltype(errno)>::type __current_errno = errno;
Howard Hinnant05c71342011-02-25 19:52:41 +0000777 if (__current_errno == 0)
778 errno = __save_errno;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000779 if (__p2 != __a_end)
780 {
781 __err = ios_base::failbit;
782 return 0;
783 }
Eric Fiselierc03318c2018-03-29 01:18:53 +0000784 else if (__current_errno == ERANGE || numeric_limits<_Tp>::max() < __ll)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000785 {
786 __err = ios_base::failbit;
787 return numeric_limits<_Tp>::max();
788 }
Eric Fiselierc03318c2018-03-29 01:18:53 +0000789 _Tp __res = static_cast<_Tp>(__ll);
790 if (__negate) __res = -__res;
791 return __res;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000792 }
793 __err = ios_base::failbit;
794 return 0;
795}
796
797template <class _Tp>
Eric Fiselier98e428d2016-06-19 06:58:22 +0000798_LIBCPP_INLINE_VISIBILITY
799_Tp __do_strtod(const char* __a, char** __p2);
800
801template <>
802inline _LIBCPP_INLINE_VISIBILITY
803float __do_strtod<float>(const char* __a, char** __p2) {
804 return strtof_l(__a, __p2, _LIBCPP_GET_C_LOCALE);
805}
806
807template <>
808inline _LIBCPP_INLINE_VISIBILITY
809double __do_strtod<double>(const char* __a, char** __p2) {
810 return strtod_l(__a, __p2, _LIBCPP_GET_C_LOCALE);
811}
812
813template <>
814inline _LIBCPP_INLINE_VISIBILITY
815long double __do_strtod<long double>(const char* __a, char** __p2) {
816 return strtold_l(__a, __p2, _LIBCPP_GET_C_LOCALE);
817}
818
819template <class _Tp>
Shoaib Meenai54c6fd62016-12-24 18:05:32 +0000820_LIBCPP_HIDDEN
Howard Hinnantc51e1022010-05-11 19:42:16 +0000821_Tp
822__num_get_float(const char* __a, const char* __a_end, ios_base::iostate& __err)
823{
824 if (__a != __a_end)
825 {
Howard Hinnantc9567812013-04-13 18:19:25 +0000826 typename remove_reference<decltype(errno)>::type __save_errno = errno;
827 errno = 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000828 char *__p2;
Eric Fiselier98e428d2016-06-19 06:58:22 +0000829 _Tp __ld = __do_strtod<_Tp>(__a, &__p2);
Howard Hinnantc9567812013-04-13 18:19:25 +0000830 typename remove_reference<decltype(errno)>::type __current_errno = errno;
831 if (__current_errno == 0)
832 errno = __save_errno;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000833 if (__p2 != __a_end)
834 {
835 __err = ios_base::failbit;
836 return 0;
837 }
Howard Hinnantc9567812013-04-13 18:19:25 +0000838 else if (__current_errno == ERANGE)
839 __err = ios_base::failbit;
Eric Fiselier98e428d2016-06-19 06:58:22 +0000840 return __ld;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000841 }
842 __err = ios_base::failbit;
843 return 0;
844}
845
846template <class _CharT, class _InputIterator>
847_InputIterator
848num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
849 ios_base& __iob,
850 ios_base::iostate& __err,
851 bool& __v) const
852{
853 if ((__iob.flags() & ios_base::boolalpha) == 0)
854 {
855 long __lv = -1;
856 __b = do_get(__b, __e, __iob, __err, __lv);
857 switch (__lv)
858 {
859 case 0:
860 __v = false;
861 break;
862 case 1:
863 __v = true;
864 break;
865 default:
866 __v = true;
867 __err = ios_base::failbit;
868 break;
869 }
870 return __b;
871 }
872 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__iob.getloc());
873 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__iob.getloc());
874 typedef typename numpunct<_CharT>::string_type string_type;
875 const string_type __names[2] = {__np.truename(), __np.falsename()};
Arthur O'Dwyere75dcfa2020-11-22 13:21:11 -0500876 const string_type* __i = _VSTD::__scan_keyword(__b, __e, __names, __names+2,
877 __ct, __err);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000878 __v = __i == __names;
879 return __b;
880}
881
Marshall Clow96d86d82013-11-07 01:00:50 +0000882// signed
883
Howard Hinnantc51e1022010-05-11 19:42:16 +0000884template <class _CharT, class _InputIterator>
Marshall Clow96d86d82013-11-07 01:00:50 +0000885template <class _Signed>
Howard Hinnantc51e1022010-05-11 19:42:16 +0000886_InputIterator
Marshall Clow96d86d82013-11-07 01:00:50 +0000887num_get<_CharT, _InputIterator>::__do_get_signed(iter_type __b, iter_type __e,
Howard Hinnantc51e1022010-05-11 19:42:16 +0000888 ios_base& __iob,
889 ios_base::iostate& __err,
Marshall Clow96d86d82013-11-07 01:00:50 +0000890 _Signed& __v) const
Howard Hinnantc51e1022010-05-11 19:42:16 +0000891{
892 // Stage 1
893 int __base = this->__get_base(__iob);
894 // Stage 2
Howard Hinnantc51e1022010-05-11 19:42:16 +0000895 char_type __thousands_sep;
Aditya Kumaraa866182017-06-14 23:17:45 +0000896 const int __atoms_size = 26;
897#ifdef _LIBCPP_ABI_OPTIMIZED_LOCALE_NUM_GET
898 char_type __atoms1[__atoms_size];
899 const char_type *__atoms = this->__do_widen(__iob, __atoms1);
900 string __grouping = this->__stage2_int_prep(__iob, __thousands_sep);
901#else
902 char_type __atoms[__atoms_size];
Howard Hinnantc51e1022010-05-11 19:42:16 +0000903 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
Aditya Kumaraa866182017-06-14 23:17:45 +0000904#endif
Howard Hinnant5d4013d2013-04-15 20:40:06 +0000905 string __buf;
906 __buf.resize(__buf.capacity());
907 char* __a = &__buf[0];
Howard Hinnantc51e1022010-05-11 19:42:16 +0000908 char* __a_end = __a;
909 unsigned __g[__num_get_base::__num_get_buf_sz];
910 unsigned* __g_end = __g;
911 unsigned __dc = 0;
912 for (; __b != __e; ++__b)
Howard Hinnant5d4013d2013-04-15 20:40:06 +0000913 {
Joerg Sonnenberger7a804f62014-02-07 21:14:29 +0000914 if (__a_end == __a + __buf.size())
Howard Hinnant5d4013d2013-04-15 20:40:06 +0000915 {
916 size_t __tmp = __buf.size();
917 __buf.resize(2*__buf.size());
918 __buf.resize(__buf.capacity());
919 __a = &__buf[0];
920 __a_end = __a + __tmp;
921 }
Howard Hinnant3b6579a2010-08-22 00:02:43 +0000922 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantc51e1022010-05-11 19:42:16 +0000923 __thousands_sep, __grouping, __g, __g_end,
924 __atoms))
925 break;
Howard Hinnant5d4013d2013-04-15 20:40:06 +0000926 }
Howard Hinnantc51e1022010-05-11 19:42:16 +0000927 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
928 *__g_end++ = __dc;
929 // Stage 3
Marshall Clow96d86d82013-11-07 01:00:50 +0000930 __v = __num_get_signed_integral<_Signed>(__a, __a_end, __err, __base);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000931 // Digit grouping checked
932 __check_grouping(__grouping, __g, __g_end, __err);
933 // EOF checked
934 if (__b == __e)
935 __err |= ios_base::eofbit;
936 return __b;
937}
938
Marshall Clow96d86d82013-11-07 01:00:50 +0000939// unsigned
Howard Hinnantc51e1022010-05-11 19:42:16 +0000940
941template <class _CharT, class _InputIterator>
Marshall Clow96d86d82013-11-07 01:00:50 +0000942template <class _Unsigned>
Howard Hinnantc51e1022010-05-11 19:42:16 +0000943_InputIterator
Marshall Clow96d86d82013-11-07 01:00:50 +0000944num_get<_CharT, _InputIterator>::__do_get_unsigned(iter_type __b, iter_type __e,
Howard Hinnantc51e1022010-05-11 19:42:16 +0000945 ios_base& __iob,
946 ios_base::iostate& __err,
Marshall Clow96d86d82013-11-07 01:00:50 +0000947 _Unsigned& __v) const
Howard Hinnantc51e1022010-05-11 19:42:16 +0000948{
949 // Stage 1
950 int __base = this->__get_base(__iob);
951 // Stage 2
Howard Hinnantc51e1022010-05-11 19:42:16 +0000952 char_type __thousands_sep;
Aditya Kumaraa866182017-06-14 23:17:45 +0000953 const int __atoms_size = 26;
954#ifdef _LIBCPP_ABI_OPTIMIZED_LOCALE_NUM_GET
955 char_type __atoms1[__atoms_size];
956 const char_type *__atoms = this->__do_widen(__iob, __atoms1);
957 string __grouping = this->__stage2_int_prep(__iob, __thousands_sep);
958#else
959 char_type __atoms[__atoms_size];
Howard Hinnantc51e1022010-05-11 19:42:16 +0000960 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
Aditya Kumaraa866182017-06-14 23:17:45 +0000961#endif
Howard Hinnant5d4013d2013-04-15 20:40:06 +0000962 string __buf;
963 __buf.resize(__buf.capacity());
964 char* __a = &__buf[0];
Howard Hinnantc51e1022010-05-11 19:42:16 +0000965 char* __a_end = __a;
966 unsigned __g[__num_get_base::__num_get_buf_sz];
967 unsigned* __g_end = __g;
968 unsigned __dc = 0;
969 for (; __b != __e; ++__b)
Howard Hinnant5d4013d2013-04-15 20:40:06 +0000970 {
Joerg Sonnenberger7a804f62014-02-07 21:14:29 +0000971 if (__a_end == __a + __buf.size())
Howard Hinnant5d4013d2013-04-15 20:40:06 +0000972 {
973 size_t __tmp = __buf.size();
974 __buf.resize(2*__buf.size());
975 __buf.resize(__buf.capacity());
976 __a = &__buf[0];
977 __a_end = __a + __tmp;
978 }
Howard Hinnant3b6579a2010-08-22 00:02:43 +0000979 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantc51e1022010-05-11 19:42:16 +0000980 __thousands_sep, __grouping, __g, __g_end,
981 __atoms))
982 break;
Howard Hinnant5d4013d2013-04-15 20:40:06 +0000983 }
Howard Hinnantc51e1022010-05-11 19:42:16 +0000984 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
985 *__g_end++ = __dc;
986 // Stage 3
Marshall Clow96d86d82013-11-07 01:00:50 +0000987 __v = __num_get_unsigned_integral<_Unsigned>(__a, __a_end, __err, __base);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000988 // Digit grouping checked
989 __check_grouping(__grouping, __g, __g_end, __err);
990 // EOF checked
991 if (__b == __e)
992 __err |= ios_base::eofbit;
993 return __b;
994}
995
Marshall Clowae385382013-11-05 14:28:52 +0000996// floating point
997
Howard Hinnantc51e1022010-05-11 19:42:16 +0000998template <class _CharT, class _InputIterator>
Marshall Clowae385382013-11-05 14:28:52 +0000999template <class _Fp>
Howard Hinnantc51e1022010-05-11 19:42:16 +00001000_InputIterator
Marshall Clowae385382013-11-05 14:28:52 +00001001num_get<_CharT, _InputIterator>::__do_get_floating_point(iter_type __b, iter_type __e,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001002 ios_base& __iob,
1003 ios_base::iostate& __err,
Marshall Clowae385382013-11-05 14:28:52 +00001004 _Fp& __v) const
Howard Hinnantc51e1022010-05-11 19:42:16 +00001005{
1006 // Stage 1, nothing to do
1007 // Stage 2
1008 char_type __atoms[32];
1009 char_type __decimal_point;
1010 char_type __thousands_sep;
Howard Hinnant3b6579a2010-08-22 00:02:43 +00001011 string __grouping = this->__stage2_float_prep(__iob, __atoms,
1012 __decimal_point,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001013 __thousands_sep);
Howard Hinnant5d4013d2013-04-15 20:40:06 +00001014 string __buf;
1015 __buf.resize(__buf.capacity());
1016 char* __a = &__buf[0];
Howard Hinnantc51e1022010-05-11 19:42:16 +00001017 char* __a_end = __a;
1018 unsigned __g[__num_get_base::__num_get_buf_sz];
1019 unsigned* __g_end = __g;
1020 unsigned __dc = 0;
1021 bool __in_units = true;
1022 char __exp = 'E';
1023 for (; __b != __e; ++__b)
Howard Hinnant5d4013d2013-04-15 20:40:06 +00001024 {
Joerg Sonnenberger7a804f62014-02-07 21:14:29 +00001025 if (__a_end == __a + __buf.size())
Howard Hinnant5d4013d2013-04-15 20:40:06 +00001026 {
1027 size_t __tmp = __buf.size();
1028 __buf.resize(2*__buf.size());
1029 __buf.resize(__buf.capacity());
1030 __a = &__buf[0];
1031 __a_end = __a + __tmp;
1032 }
Howard Hinnant3b6579a2010-08-22 00:02:43 +00001033 if (this->__stage2_float_loop(*__b, __in_units, __exp, __a, __a_end,
1034 __decimal_point, __thousands_sep,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001035 __grouping, __g, __g_end,
1036 __dc, __atoms))
1037 break;
Howard Hinnant5d4013d2013-04-15 20:40:06 +00001038 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00001039 if (__grouping.size() != 0 && __in_units && __g_end-__g < __num_get_base::__num_get_buf_sz)
1040 *__g_end++ = __dc;
1041 // Stage 3
Marshall Clowae385382013-11-05 14:28:52 +00001042 __v = __num_get_float<_Fp>(__a, __a_end, __err);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001043 // Digit grouping checked
1044 __check_grouping(__grouping, __g, __g_end, __err);
1045 // EOF checked
1046 if (__b == __e)
1047 __err |= ios_base::eofbit;
1048 return __b;
1049}
1050
1051template <class _CharT, class _InputIterator>
1052_InputIterator
1053num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
1054 ios_base& __iob,
1055 ios_base::iostate& __err,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001056 void*& __v) const
1057{
1058 // Stage 1
1059 int __base = 16;
1060 // Stage 2
1061 char_type __atoms[26];
Howard Hinnant28b24882011-12-01 20:21:04 +00001062 char_type __thousands_sep = 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001063 string __grouping;
1064 use_facet<ctype<_CharT> >(__iob.getloc()).widen(__num_get_base::__src,
1065 __num_get_base::__src + 26, __atoms);
Howard Hinnant5d4013d2013-04-15 20:40:06 +00001066 string __buf;
1067 __buf.resize(__buf.capacity());
1068 char* __a = &__buf[0];
Howard Hinnantc51e1022010-05-11 19:42:16 +00001069 char* __a_end = __a;
1070 unsigned __g[__num_get_base::__num_get_buf_sz];
1071 unsigned* __g_end = __g;
1072 unsigned __dc = 0;
1073 for (; __b != __e; ++__b)
Howard Hinnant5d4013d2013-04-15 20:40:06 +00001074 {
Joerg Sonnenberger7a804f62014-02-07 21:14:29 +00001075 if (__a_end == __a + __buf.size())
Howard Hinnant5d4013d2013-04-15 20:40:06 +00001076 {
1077 size_t __tmp = __buf.size();
1078 __buf.resize(2*__buf.size());
1079 __buf.resize(__buf.capacity());
1080 __a = &__buf[0];
1081 __a_end = __a + __tmp;
1082 }
Howard Hinnant3b6579a2010-08-22 00:02:43 +00001083 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
1084 __thousands_sep, __grouping,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001085 __g, __g_end, __atoms))
1086 break;
Howard Hinnant5d4013d2013-04-15 20:40:06 +00001087 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00001088 // Stage 3
Marshall Clow0db963d2014-05-21 16:02:20 +00001089 __buf.resize(__a_end - __a);
Ben Craig3756b922016-03-09 15:39:39 +00001090 if (__libcpp_sscanf_l(__buf.c_str(), _LIBCPP_GET_C_LOCALE, "%p", &__v) != 1)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001091 __err = ios_base::failbit;
1092 // EOF checked
1093 if (__b == __e)
1094 __err |= ios_base::eofbit;
1095 return __b;
1096}
1097
Louis Dionneb5ae3a72020-10-02 14:29:48 -04001098_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS num_get<char>)
1099_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS num_get<wchar_t>)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001100
Howard Hinnanta37d3cf2013-08-12 18:38:34 +00001101struct _LIBCPP_TYPE_VIS __num_put_base
Howard Hinnantc51e1022010-05-11 19:42:16 +00001102{
1103protected:
1104 static void __format_int(char* __fmt, const char* __len, bool __signd,
1105 ios_base::fmtflags __flags);
1106 static bool __format_float(char* __fmt, const char* __len,
1107 ios_base::fmtflags __flags);
1108 static char* __identify_padding(char* __nb, char* __ne,
1109 const ios_base& __iob);
1110};
1111
1112template <class _CharT>
1113struct __num_put
1114 : protected __num_put_base
1115{
1116 static void __widen_and_group_int(char* __nb, char* __np, char* __ne,
1117 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1118 const locale& __loc);
1119 static void __widen_and_group_float(char* __nb, char* __np, char* __ne,
1120 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1121 const locale& __loc);
1122};
1123
1124template <class _CharT>
1125void
1126__num_put<_CharT>::__widen_and_group_int(char* __nb, char* __np, char* __ne,
1127 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1128 const locale& __loc)
1129{
1130 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> > (__loc);
1131 const numpunct<_CharT>& __npt = use_facet<numpunct<_CharT> >(__loc);
1132 string __grouping = __npt.grouping();
1133 if (__grouping.empty())
1134 {
1135 __ct.widen(__nb, __ne, __ob);
1136 __oe = __ob + (__ne - __nb);
1137 }
1138 else
1139 {
1140 __oe = __ob;
1141 char* __nf = __nb;
1142 if (*__nf == '-' || *__nf == '+')
1143 *__oe++ = __ct.widen(*__nf++);
1144 if (__ne - __nf >= 2 && __nf[0] == '0' && (__nf[1] == 'x' ||
1145 __nf[1] == 'X'))
1146 {
1147 *__oe++ = __ct.widen(*__nf++);
1148 *__oe++ = __ct.widen(*__nf++);
1149 }
1150 reverse(__nf, __ne);
1151 _CharT __thousands_sep = __npt.thousands_sep();
1152 unsigned __dc = 0;
1153 unsigned __dg = 0;
1154 for (char* __p = __nf; __p < __ne; ++__p)
1155 {
1156 if (static_cast<unsigned>(__grouping[__dg]) > 0 &&
1157 __dc == static_cast<unsigned>(__grouping[__dg]))
1158 {
1159 *__oe++ = __thousands_sep;
1160 __dc = 0;
1161 if (__dg < __grouping.size()-1)
1162 ++__dg;
1163 }
1164 *__oe++ = __ct.widen(*__p);
1165 ++__dc;
1166 }
1167 reverse(__ob + (__nf - __nb), __oe);
1168 }
1169 if (__np == __ne)
1170 __op = __oe;
1171 else
1172 __op = __ob + (__np - __nb);
1173}
1174
1175template <class _CharT>
1176void
1177__num_put<_CharT>::__widen_and_group_float(char* __nb, char* __np, char* __ne,
1178 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1179 const locale& __loc)
1180{
1181 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> > (__loc);
1182 const numpunct<_CharT>& __npt = use_facet<numpunct<_CharT> >(__loc);
1183 string __grouping = __npt.grouping();
1184 __oe = __ob;
1185 char* __nf = __nb;
1186 if (*__nf == '-' || *__nf == '+')
1187 *__oe++ = __ct.widen(*__nf++);
1188 char* __ns;
1189 if (__ne - __nf >= 2 && __nf[0] == '0' && (__nf[1] == 'x' ||
1190 __nf[1] == 'X'))
1191 {
1192 *__oe++ = __ct.widen(*__nf++);
1193 *__oe++ = __ct.widen(*__nf++);
1194 for (__ns = __nf; __ns < __ne; ++__ns)
Howard Hinnant1ab52da2011-09-28 21:05:01 +00001195 if (!isxdigit_l(*__ns, _LIBCPP_GET_C_LOCALE))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001196 break;
1197 }
1198 else
1199 {
1200 for (__ns = __nf; __ns < __ne; ++__ns)
Howard Hinnant1ab52da2011-09-28 21:05:01 +00001201 if (!isdigit_l(*__ns, _LIBCPP_GET_C_LOCALE))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001202 break;
1203 }
1204 if (__grouping.empty())
1205 {
1206 __ct.widen(__nf, __ns, __oe);
1207 __oe += __ns - __nf;
1208 }
1209 else
1210 {
1211 reverse(__nf, __ns);
1212 _CharT __thousands_sep = __npt.thousands_sep();
1213 unsigned __dc = 0;
1214 unsigned __dg = 0;
1215 for (char* __p = __nf; __p < __ns; ++__p)
1216 {
1217 if (__grouping[__dg] > 0 && __dc == static_cast<unsigned>(__grouping[__dg]))
1218 {
1219 *__oe++ = __thousands_sep;
1220 __dc = 0;
1221 if (__dg < __grouping.size()-1)
1222 ++__dg;
1223 }
1224 *__oe++ = __ct.widen(*__p);
1225 ++__dc;
1226 }
1227 reverse(__ob + (__nf - __nb), __oe);
1228 }
1229 for (__nf = __ns; __nf < __ne; ++__nf)
1230 {
1231 if (*__nf == '.')
1232 {
1233 *__oe++ = __npt.decimal_point();
1234 ++__nf;
1235 break;
1236 }
1237 else
1238 *__oe++ = __ct.widen(*__nf);
1239 }
1240 __ct.widen(__nf, __ne, __oe);
1241 __oe += __ne - __nf;
1242 if (__np == __ne)
1243 __op = __oe;
1244 else
1245 __op = __ob + (__np - __nb);
1246}
1247
Louis Dionneb5ae3a72020-10-02 14:29:48 -04001248_LIBCPP_EXTERN_TEMPLATE(struct _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __num_put<char>)
1249_LIBCPP_EXTERN_TEMPLATE(struct _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __num_put<wchar_t>)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001250
1251template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +00001252class _LIBCPP_TEMPLATE_VIS num_put
Howard Hinnantc51e1022010-05-11 19:42:16 +00001253 : public locale::facet,
1254 private __num_put<_CharT>
1255{
1256public:
1257 typedef _CharT char_type;
1258 typedef _OutputIterator iter_type;
1259
Louis Dionne16fe2952018-07-11 23:14:33 +00001260 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00001261 explicit num_put(size_t __refs = 0)
1262 : locale::facet(__refs) {}
1263
Louis Dionne16fe2952018-07-11 23:14:33 +00001264 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00001265 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1266 bool __v) const
1267 {
1268 return do_put(__s, __iob, __fl, __v);
1269 }
1270
Louis Dionne16fe2952018-07-11 23:14:33 +00001271 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00001272 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1273 long __v) const
1274 {
1275 return do_put(__s, __iob, __fl, __v);
1276 }
1277
Louis Dionne16fe2952018-07-11 23:14:33 +00001278 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00001279 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1280 long long __v) const
1281 {
1282 return do_put(__s, __iob, __fl, __v);
1283 }
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 unsigned long __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 unsigned long 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 double __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 long double __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 const void* __v) const
1316 {
1317 return do_put(__s, __iob, __fl, __v);
1318 }
1319
1320 static locale::id id;
1321
1322protected:
Louis Dionne16fe2952018-07-11 23:14:33 +00001323 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00001324 ~num_put() {}
1325
1326 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1327 bool __v) const;
1328 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1329 long __v) const;
1330 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1331 long long __v) const;
1332 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1333 unsigned long) const;
1334 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1335 unsigned long long) const;
1336 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1337 double __v) const;
1338 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1339 long double __v) const;
1340 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1341 const void* __v) const;
1342};
1343
1344template <class _CharT, class _OutputIterator>
1345locale::id
1346num_put<_CharT, _OutputIterator>::id;
1347
1348template <class _CharT, class _OutputIterator>
1349_LIBCPP_HIDDEN
1350_OutputIterator
1351__pad_and_output(_OutputIterator __s,
1352 const _CharT* __ob, const _CharT* __op, const _CharT* __oe,
1353 ios_base& __iob, _CharT __fl)
1354{
1355 streamsize __sz = __oe - __ob;
1356 streamsize __ns = __iob.width();
1357 if (__ns > __sz)
1358 __ns -= __sz;
1359 else
1360 __ns = 0;
1361 for (;__ob < __op; ++__ob, ++__s)
1362 *__s = *__ob;
1363 for (; __ns; --__ns, ++__s)
1364 *__s = __fl;
1365 for (; __ob < __oe; ++__ob, ++__s)
1366 *__s = *__ob;
1367 __iob.width(0);
1368 return __s;
1369}
1370
Howard Hinnant97955172012-09-19 19:14:15 +00001371template <class _CharT, class _Traits>
1372_LIBCPP_HIDDEN
1373ostreambuf_iterator<_CharT, _Traits>
1374__pad_and_output(ostreambuf_iterator<_CharT, _Traits> __s,
1375 const _CharT* __ob, const _CharT* __op, const _CharT* __oe,
1376 ios_base& __iob, _CharT __fl)
1377{
1378 if (__s.__sbuf_ == nullptr)
1379 return __s;
1380 streamsize __sz = __oe - __ob;
1381 streamsize __ns = __iob.width();
1382 if (__ns > __sz)
1383 __ns -= __sz;
1384 else
1385 __ns = 0;
1386 streamsize __np = __op - __ob;
1387 if (__np > 0)
1388 {
1389 if (__s.__sbuf_->sputn(__ob, __np) != __np)
1390 {
1391 __s.__sbuf_ = nullptr;
1392 return __s;
1393 }
1394 }
1395 if (__ns > 0)
1396 {
1397 basic_string<_CharT, _Traits> __sp(__ns, __fl);
1398 if (__s.__sbuf_->sputn(__sp.data(), __ns) != __ns)
1399 {
1400 __s.__sbuf_ = nullptr;
1401 return __s;
1402 }
1403 }
1404 __np = __oe - __op;
1405 if (__np > 0)
1406 {
1407 if (__s.__sbuf_->sputn(__op, __np) != __np)
1408 {
1409 __s.__sbuf_ = nullptr;
1410 return __s;
1411 }
1412 }
1413 __iob.width(0);
1414 return __s;
1415}
1416
Howard Hinnantc51e1022010-05-11 19:42:16 +00001417template <class _CharT, class _OutputIterator>
1418_OutputIterator
1419num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1420 char_type __fl, bool __v) const
1421{
1422 if ((__iob.flags() & ios_base::boolalpha) == 0)
1423 return do_put(__s, __iob, __fl, (unsigned long)__v);
1424 const numpunct<char_type>& __np = use_facet<numpunct<char_type> >(__iob.getloc());
1425 typedef typename numpunct<char_type>::string_type string_type;
Louis Dionneba400782020-10-02 15:02:52 -04001426#if _LIBCPP_DEBUG_LEVEL == 2
Howard Hinnant8ea98242013-08-23 17:37:05 +00001427 string_type __tmp(__v ? __np.truename() : __np.falsename());
1428 string_type __nm = _VSTD::move(__tmp);
1429#else
Howard Hinnantc51e1022010-05-11 19:42:16 +00001430 string_type __nm = __v ? __np.truename() : __np.falsename();
Howard Hinnant8ea98242013-08-23 17:37:05 +00001431#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001432 for (typename string_type::iterator __i = __nm.begin(); __i != __nm.end(); ++__i, ++__s)
1433 *__s = *__i;
1434 return __s;
1435}
1436
1437template <class _CharT, class _OutputIterator>
1438_OutputIterator
1439num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1440 char_type __fl, long __v) const
1441{
1442 // Stage 1 - Get number in narrow char
1443 char __fmt[6] = {'%', 0};
1444 const char* __len = "l";
1445 this->__format_int(__fmt+1, __len, true, __iob.flags());
1446 const unsigned __nbuf = (numeric_limits<long>::digits / 3)
1447 + ((numeric_limits<long>::digits % 3) != 0)
Dimitry Andriccfb7b5d2017-05-06 20:58:50 +00001448 + ((__iob.flags() & ios_base::showbase) != 0)
Eric Fiselier4cc37352016-04-29 07:23:20 +00001449 + 2;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001450 char __nar[__nbuf];
Ben Craig3756b922016-03-09 15:39:39 +00001451 int __nc = __libcpp_snprintf_l(__nar, sizeof(__nar), _LIBCPP_GET_C_LOCALE, __fmt, __v);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001452 char* __ne = __nar + __nc;
1453 char* __np = this->__identify_padding(__nar, __ne, __iob);
1454 // Stage 2 - Widen __nar while adding thousands separators
1455 char_type __o[2*(__nbuf-1) - 1];
1456 char_type* __op; // pad here
1457 char_type* __oe; // end of output
1458 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1459 // [__o, __oe) contains thousands_sep'd wide number
1460 // Stage 3 & 4
1461 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1462}
1463
1464template <class _CharT, class _OutputIterator>
1465_OutputIterator
1466num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1467 char_type __fl, long long __v) const
1468{
1469 // Stage 1 - Get number in narrow char
1470 char __fmt[8] = {'%', 0};
1471 const char* __len = "ll";
1472 this->__format_int(__fmt+1, __len, true, __iob.flags());
1473 const unsigned __nbuf = (numeric_limits<long long>::digits / 3)
1474 + ((numeric_limits<long long>::digits % 3) != 0)
Dimitry Andriccfb7b5d2017-05-06 20:58:50 +00001475 + ((__iob.flags() & ios_base::showbase) != 0)
Marshall Clow7ac088f2015-01-26 17:24:52 +00001476 + 2;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001477 char __nar[__nbuf];
Ben Craig3756b922016-03-09 15:39:39 +00001478 int __nc = __libcpp_snprintf_l(__nar, sizeof(__nar), _LIBCPP_GET_C_LOCALE, __fmt, __v);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001479 char* __ne = __nar + __nc;
1480 char* __np = this->__identify_padding(__nar, __ne, __iob);
1481 // Stage 2 - Widen __nar while adding thousands separators
1482 char_type __o[2*(__nbuf-1) - 1];
1483 char_type* __op; // pad here
1484 char_type* __oe; // end of output
1485 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1486 // [__o, __oe) contains thousands_sep'd wide number
1487 // Stage 3 & 4
1488 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1489}
1490
1491template <class _CharT, class _OutputIterator>
1492_OutputIterator
1493num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1494 char_type __fl, unsigned long __v) const
1495{
1496 // Stage 1 - Get number in narrow char
1497 char __fmt[6] = {'%', 0};
1498 const char* __len = "l";
1499 this->__format_int(__fmt+1, __len, false, __iob.flags());
1500 const unsigned __nbuf = (numeric_limits<unsigned long>::digits / 3)
1501 + ((numeric_limits<unsigned long>::digits % 3) != 0)
Dimitry Andriccfb7b5d2017-05-06 20:58:50 +00001502 + ((__iob.flags() & ios_base::showbase) != 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001503 + 1;
1504 char __nar[__nbuf];
Ben Craig3756b922016-03-09 15:39:39 +00001505 int __nc = __libcpp_snprintf_l(__nar, sizeof(__nar), _LIBCPP_GET_C_LOCALE, __fmt, __v);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001506 char* __ne = __nar + __nc;
1507 char* __np = this->__identify_padding(__nar, __ne, __iob);
1508 // Stage 2 - Widen __nar while adding thousands separators
1509 char_type __o[2*(__nbuf-1) - 1];
1510 char_type* __op; // pad here
1511 char_type* __oe; // end of output
1512 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1513 // [__o, __oe) contains thousands_sep'd wide number
1514 // Stage 3 & 4
1515 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1516}
1517
1518template <class _CharT, class _OutputIterator>
1519_OutputIterator
1520num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1521 char_type __fl, unsigned long long __v) const
1522{
1523 // Stage 1 - Get number in narrow char
1524 char __fmt[8] = {'%', 0};
1525 const char* __len = "ll";
1526 this->__format_int(__fmt+1, __len, false, __iob.flags());
1527 const unsigned __nbuf = (numeric_limits<unsigned long long>::digits / 3)
1528 + ((numeric_limits<unsigned long long>::digits % 3) != 0)
Dimitry Andriccfb7b5d2017-05-06 20:58:50 +00001529 + ((__iob.flags() & ios_base::showbase) != 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001530 + 1;
1531 char __nar[__nbuf];
Ben Craig3756b922016-03-09 15:39:39 +00001532 int __nc = __libcpp_snprintf_l(__nar, sizeof(__nar), _LIBCPP_GET_C_LOCALE, __fmt, __v);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001533 char* __ne = __nar + __nc;
1534 char* __np = this->__identify_padding(__nar, __ne, __iob);
1535 // Stage 2 - Widen __nar while adding thousands separators
1536 char_type __o[2*(__nbuf-1) - 1];
1537 char_type* __op; // pad here
1538 char_type* __oe; // end of output
1539 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1540 // [__o, __oe) contains thousands_sep'd wide number
1541 // Stage 3 & 4
1542 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1543}
1544
1545template <class _CharT, class _OutputIterator>
1546_OutputIterator
1547num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1548 char_type __fl, double __v) const
1549{
1550 // Stage 1 - Get number in narrow char
1551 char __fmt[8] = {'%', 0};
1552 const char* __len = "";
1553 bool __specify_precision = this->__format_float(__fmt+1, __len, __iob.flags());
1554 const unsigned __nbuf = 30;
1555 char __nar[__nbuf];
1556 char* __nb = __nar;
1557 int __nc;
1558 if (__specify_precision)
Ben Craig3756b922016-03-09 15:39:39 +00001559 __nc = __libcpp_snprintf_l(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt,
Howard Hinnant155c2af2010-05-24 17:49:41 +00001560 (int)__iob.precision(), __v);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001561 else
Ben Craig3756b922016-03-09 15:39:39 +00001562 __nc = __libcpp_snprintf_l(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Bruce Mitchener170d8972020-11-24 12:53:53 -05001563 unique_ptr<char, void(*)(void*)> __nbh(nullptr, free);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001564 if (__nc > static_cast<int>(__nbuf-1))
1565 {
1566 if (__specify_precision)
Ben Craig3756b922016-03-09 15:39:39 +00001567 __nc = __libcpp_asprintf_l(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, (int)__iob.precision(), __v);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001568 else
Ben Craig3756b922016-03-09 15:39:39 +00001569 __nc = __libcpp_asprintf_l(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Bruce Mitchener170d8972020-11-24 12:53:53 -05001570 if (__nb == nullptr)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001571 __throw_bad_alloc();
1572 __nbh.reset(__nb);
1573 }
1574 char* __ne = __nb + __nc;
1575 char* __np = this->__identify_padding(__nb, __ne, __iob);
1576 // Stage 2 - Widen __nar while adding thousands separators
1577 char_type __o[2*(__nbuf-1) - 1];
1578 char_type* __ob = __o;
1579 unique_ptr<char_type, void(*)(void*)> __obh(0, free);
1580 if (__nb != __nar)
1581 {
Howard Hinnant28b24882011-12-01 20:21:04 +00001582 __ob = (char_type*)malloc(2*static_cast<size_t>(__nc)*sizeof(char_type));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001583 if (__ob == 0)
1584 __throw_bad_alloc();
1585 __obh.reset(__ob);
1586 }
1587 char_type* __op; // pad here
1588 char_type* __oe; // end of output
1589 this->__widen_and_group_float(__nb, __np, __ne, __ob, __op, __oe, __iob.getloc());
1590 // [__o, __oe) contains thousands_sep'd wide number
1591 // Stage 3 & 4
1592 __s = __pad_and_output(__s, __ob, __op, __oe, __iob, __fl);
1593 return __s;
1594}
1595
1596template <class _CharT, class _OutputIterator>
1597_OutputIterator
1598num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1599 char_type __fl, long double __v) const
1600{
1601 // Stage 1 - Get number in narrow char
1602 char __fmt[8] = {'%', 0};
1603 const char* __len = "L";
1604 bool __specify_precision = this->__format_float(__fmt+1, __len, __iob.flags());
1605 const unsigned __nbuf = 30;
1606 char __nar[__nbuf];
1607 char* __nb = __nar;
1608 int __nc;
1609 if (__specify_precision)
Ben Craig3756b922016-03-09 15:39:39 +00001610 __nc = __libcpp_snprintf_l(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt,
Howard Hinnant155c2af2010-05-24 17:49:41 +00001611 (int)__iob.precision(), __v);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001612 else
Ben Craig3756b922016-03-09 15:39:39 +00001613 __nc = __libcpp_snprintf_l(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Bruce Mitchener170d8972020-11-24 12:53:53 -05001614 unique_ptr<char, void(*)(void*)> __nbh(nullptr, free);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001615 if (__nc > static_cast<int>(__nbuf-1))
1616 {
1617 if (__specify_precision)
Ben Craig3756b922016-03-09 15:39:39 +00001618 __nc = __libcpp_asprintf_l(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, (int)__iob.precision(), __v);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001619 else
Ben Craig3756b922016-03-09 15:39:39 +00001620 __nc = __libcpp_asprintf_l(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Bruce Mitchener170d8972020-11-24 12:53:53 -05001621 if (__nb == nullptr)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001622 __throw_bad_alloc();
1623 __nbh.reset(__nb);
1624 }
1625 char* __ne = __nb + __nc;
1626 char* __np = this->__identify_padding(__nb, __ne, __iob);
1627 // Stage 2 - Widen __nar while adding thousands separators
1628 char_type __o[2*(__nbuf-1) - 1];
1629 char_type* __ob = __o;
1630 unique_ptr<char_type, void(*)(void*)> __obh(0, free);
1631 if (__nb != __nar)
1632 {
Howard Hinnant28b24882011-12-01 20:21:04 +00001633 __ob = (char_type*)malloc(2*static_cast<size_t>(__nc)*sizeof(char_type));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001634 if (__ob == 0)
1635 __throw_bad_alloc();
1636 __obh.reset(__ob);
1637 }
1638 char_type* __op; // pad here
1639 char_type* __oe; // end of output
1640 this->__widen_and_group_float(__nb, __np, __ne, __ob, __op, __oe, __iob.getloc());
1641 // [__o, __oe) contains thousands_sep'd wide number
1642 // Stage 3 & 4
1643 __s = __pad_and_output(__s, __ob, __op, __oe, __iob, __fl);
1644 return __s;
1645}
1646
1647template <class _CharT, class _OutputIterator>
1648_OutputIterator
1649num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1650 char_type __fl, const void* __v) const
1651{
1652 // Stage 1 - Get pointer in narrow char
1653 char __fmt[6] = "%p";
1654 const unsigned __nbuf = 20;
1655 char __nar[__nbuf];
Ben Craig3756b922016-03-09 15:39:39 +00001656 int __nc = __libcpp_snprintf_l(__nar, sizeof(__nar), _LIBCPP_GET_C_LOCALE, __fmt, __v);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001657 char* __ne = __nar + __nc;
1658 char* __np = this->__identify_padding(__nar, __ne, __iob);
1659 // Stage 2 - Widen __nar
1660 char_type __o[2*(__nbuf-1) - 1];
1661 char_type* __op; // pad here
1662 char_type* __oe; // end of output
1663 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
1664 __ct.widen(__nar, __ne, __o);
1665 __oe = __o + (__ne - __nar);
1666 if (__np == __ne)
1667 __op = __oe;
1668 else
1669 __op = __o + (__np - __nar);
1670 // [__o, __oe) contains wide number
1671 // Stage 3 & 4
1672 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1673}
1674
Louis Dionneb5ae3a72020-10-02 14:29:48 -04001675_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS num_put<char>)
1676_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS num_put<wchar_t>)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001677
1678template <class _CharT, class _InputIterator>
1679_LIBCPP_HIDDEN
1680int
1681__get_up_to_n_digits(_InputIterator& __b, _InputIterator __e,
1682 ios_base::iostate& __err, const ctype<_CharT>& __ct, int __n)
1683{
1684 // Precondition: __n >= 1
1685 if (__b == __e)
1686 {
1687 __err |= ios_base::eofbit | ios_base::failbit;
1688 return 0;
1689 }
1690 // get first digit
1691 _CharT __c = *__b;
1692 if (!__ct.is(ctype_base::digit, __c))
1693 {
1694 __err |= ios_base::failbit;
1695 return 0;
1696 }
1697 int __r = __ct.narrow(__c, 0) - '0';
Eric Fiseliera09a3b42014-10-27 19:28:20 +00001698 for (++__b, (void) --__n; __b != __e && __n > 0; ++__b, (void) --__n)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001699 {
1700 // get next digit
1701 __c = *__b;
1702 if (!__ct.is(ctype_base::digit, __c))
1703 return __r;
1704 __r = __r * 10 + __ct.narrow(__c, 0) - '0';
1705 }
1706 if (__b == __e)
1707 __err |= ios_base::eofbit;
1708 return __r;
1709}
1710
Howard Hinnant8331b762013-03-06 23:30:19 +00001711class _LIBCPP_TYPE_VIS time_base
Howard Hinnantc51e1022010-05-11 19:42:16 +00001712{
1713public:
1714 enum dateorder {no_order, dmy, mdy, ymd, ydm};
1715};
1716
1717template <class _CharT>
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +00001718class _LIBCPP_TEMPLATE_VIS __time_get_c_storage
Howard Hinnantc51e1022010-05-11 19:42:16 +00001719{
1720protected:
1721 typedef basic_string<_CharT> string_type;
1722
1723 virtual const string_type* __weeks() const;
1724 virtual const string_type* __months() const;
1725 virtual const string_type* __am_pm() const;
1726 virtual const string_type& __c() const;
1727 virtual const string_type& __r() const;
1728 virtual const string_type& __x() const;
1729 virtual const string_type& __X() const;
Eric Fiselier5eb6efc2015-08-18 19:39:35 +00001730
Louis Dionne16fe2952018-07-11 23:14:33 +00001731 _LIBCPP_INLINE_VISIBILITY
Eric Fiselier5eb6efc2015-08-18 19:39:35 +00001732 ~__time_get_c_storage() {}
Howard Hinnantc51e1022010-05-11 19:42:16 +00001733};
1734
Eric Fiselierf30c0af2017-05-08 00:29:32 +00001735template <> _LIBCPP_FUNC_VIS const string* __time_get_c_storage<char>::__weeks() const;
1736template <> _LIBCPP_FUNC_VIS const string* __time_get_c_storage<char>::__months() const;
1737template <> _LIBCPP_FUNC_VIS const string* __time_get_c_storage<char>::__am_pm() const;
1738template <> _LIBCPP_FUNC_VIS const string& __time_get_c_storage<char>::__c() const;
1739template <> _LIBCPP_FUNC_VIS const string& __time_get_c_storage<char>::__r() const;
1740template <> _LIBCPP_FUNC_VIS const string& __time_get_c_storage<char>::__x() const;
1741template <> _LIBCPP_FUNC_VIS const string& __time_get_c_storage<char>::__X() const;
1742
1743template <> _LIBCPP_FUNC_VIS const wstring* __time_get_c_storage<wchar_t>::__weeks() const;
1744template <> _LIBCPP_FUNC_VIS const wstring* __time_get_c_storage<wchar_t>::__months() const;
1745template <> _LIBCPP_FUNC_VIS const wstring* __time_get_c_storage<wchar_t>::__am_pm() const;
1746template <> _LIBCPP_FUNC_VIS const wstring& __time_get_c_storage<wchar_t>::__c() const;
1747template <> _LIBCPP_FUNC_VIS const wstring& __time_get_c_storage<wchar_t>::__r() const;
1748template <> _LIBCPP_FUNC_VIS const wstring& __time_get_c_storage<wchar_t>::__x() const;
1749template <> _LIBCPP_FUNC_VIS const wstring& __time_get_c_storage<wchar_t>::__X() const;
1750
Howard Hinnantc51e1022010-05-11 19:42:16 +00001751template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +00001752class _LIBCPP_TEMPLATE_VIS time_get
Howard Hinnantc51e1022010-05-11 19:42:16 +00001753 : public locale::facet,
1754 public time_base,
1755 private __time_get_c_storage<_CharT>
1756{
1757public:
1758 typedef _CharT char_type;
1759 typedef _InputIterator iter_type;
1760 typedef time_base::dateorder dateorder;
1761 typedef basic_string<char_type> string_type;
1762
Louis Dionne16fe2952018-07-11 23:14:33 +00001763 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00001764 explicit time_get(size_t __refs = 0)
1765 : locale::facet(__refs) {}
1766
Louis Dionne16fe2952018-07-11 23:14:33 +00001767 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00001768 dateorder date_order() const
1769 {
1770 return this->do_date_order();
1771 }
1772
Louis Dionne16fe2952018-07-11 23:14:33 +00001773 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00001774 iter_type get_time(iter_type __b, iter_type __e, ios_base& __iob,
1775 ios_base::iostate& __err, tm* __tm) const
1776 {
1777 return do_get_time(__b, __e, __iob, __err, __tm);
1778 }
1779
Louis Dionne16fe2952018-07-11 23:14:33 +00001780 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00001781 iter_type get_date(iter_type __b, iter_type __e, ios_base& __iob,
1782 ios_base::iostate& __err, tm* __tm) const
1783 {
1784 return do_get_date(__b, __e, __iob, __err, __tm);
1785 }
1786
Louis Dionne16fe2952018-07-11 23:14:33 +00001787 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00001788 iter_type get_weekday(iter_type __b, iter_type __e, ios_base& __iob,
1789 ios_base::iostate& __err, tm* __tm) const
1790 {
1791 return do_get_weekday(__b, __e, __iob, __err, __tm);
1792 }
1793
Louis Dionne16fe2952018-07-11 23:14:33 +00001794 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00001795 iter_type get_monthname(iter_type __b, iter_type __e, ios_base& __iob,
1796 ios_base::iostate& __err, tm* __tm) const
1797 {
1798 return do_get_monthname(__b, __e, __iob, __err, __tm);
1799 }
1800
Louis Dionne16fe2952018-07-11 23:14:33 +00001801 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00001802 iter_type get_year(iter_type __b, iter_type __e, ios_base& __iob,
1803 ios_base::iostate& __err, tm* __tm) const
1804 {
1805 return do_get_year(__b, __e, __iob, __err, __tm);
1806 }
1807
Louis Dionne16fe2952018-07-11 23:14:33 +00001808 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00001809 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
1810 ios_base::iostate& __err, tm *__tm,
1811 char __fmt, char __mod = 0) const
1812 {
1813 return do_get(__b, __e, __iob, __err, __tm, __fmt, __mod);
1814 }
1815
1816 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
1817 ios_base::iostate& __err, tm* __tm,
1818 const char_type* __fmtb, const char_type* __fmte) const;
1819
1820 static locale::id id;
1821
1822protected:
Louis Dionne16fe2952018-07-11 23:14:33 +00001823 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00001824 ~time_get() {}
1825
1826 virtual dateorder do_date_order() const;
1827 virtual iter_type do_get_time(iter_type __b, iter_type __e, ios_base& __iob,
1828 ios_base::iostate& __err, tm* __tm) const;
1829 virtual iter_type do_get_date(iter_type __b, iter_type __e, ios_base& __iob,
1830 ios_base::iostate& __err, tm* __tm) const;
1831 virtual iter_type do_get_weekday(iter_type __b, iter_type __e, ios_base& __iob,
1832 ios_base::iostate& __err, tm* __tm) const;
1833 virtual iter_type do_get_monthname(iter_type __b, iter_type __e, ios_base& __iob,
1834 ios_base::iostate& __err, tm* __tm) const;
1835 virtual iter_type do_get_year(iter_type __b, iter_type __e, ios_base& __iob,
1836 ios_base::iostate& __err, tm* __tm) const;
1837 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
1838 ios_base::iostate& __err, tm* __tm,
1839 char __fmt, char __mod) const;
1840private:
1841 void __get_white_space(iter_type& __b, iter_type __e,
1842 ios_base::iostate& __err, const ctype<char_type>& __ct) const;
1843 void __get_percent(iter_type& __b, iter_type __e, ios_base::iostate& __err,
1844 const ctype<char_type>& __ct) const;
1845
1846 void __get_weekdayname(int& __m,
1847 iter_type& __b, iter_type __e,
1848 ios_base::iostate& __err,
1849 const ctype<char_type>& __ct) const;
1850 void __get_monthname(int& __m,
1851 iter_type& __b, iter_type __e,
1852 ios_base::iostate& __err,
1853 const ctype<char_type>& __ct) const;
1854 void __get_day(int& __d,
1855 iter_type& __b, iter_type __e,
1856 ios_base::iostate& __err,
1857 const ctype<char_type>& __ct) const;
1858 void __get_month(int& __m,
1859 iter_type& __b, iter_type __e,
1860 ios_base::iostate& __err,
1861 const ctype<char_type>& __ct) const;
1862 void __get_year(int& __y,
1863 iter_type& __b, iter_type __e,
1864 ios_base::iostate& __err,
1865 const ctype<char_type>& __ct) const;
1866 void __get_year4(int& __y,
1867 iter_type& __b, iter_type __e,
1868 ios_base::iostate& __err,
1869 const ctype<char_type>& __ct) const;
1870 void __get_hour(int& __d,
1871 iter_type& __b, iter_type __e,
1872 ios_base::iostate& __err,
1873 const ctype<char_type>& __ct) const;
1874 void __get_12_hour(int& __h,
1875 iter_type& __b, iter_type __e,
1876 ios_base::iostate& __err,
1877 const ctype<char_type>& __ct) const;
1878 void __get_am_pm(int& __h,
1879 iter_type& __b, iter_type __e,
1880 ios_base::iostate& __err,
1881 const ctype<char_type>& __ct) const;
1882 void __get_minute(int& __m,
1883 iter_type& __b, iter_type __e,
1884 ios_base::iostate& __err,
1885 const ctype<char_type>& __ct) const;
1886 void __get_second(int& __s,
1887 iter_type& __b, iter_type __e,
1888 ios_base::iostate& __err,
1889 const ctype<char_type>& __ct) const;
1890 void __get_weekday(int& __w,
1891 iter_type& __b, iter_type __e,
1892 ios_base::iostate& __err,
1893 const ctype<char_type>& __ct) const;
1894 void __get_day_year_num(int& __w,
1895 iter_type& __b, iter_type __e,
1896 ios_base::iostate& __err,
1897 const ctype<char_type>& __ct) const;
1898};
1899
1900template <class _CharT, class _InputIterator>
1901locale::id
1902time_get<_CharT, _InputIterator>::id;
1903
Alp Tokerb8a95f52014-05-15 11:27:39 +00001904// time_get primitives
Howard Hinnantc51e1022010-05-11 19:42:16 +00001905
1906template <class _CharT, class _InputIterator>
1907void
1908time_get<_CharT, _InputIterator>::__get_weekdayname(int& __w,
1909 iter_type& __b, iter_type __e,
1910 ios_base::iostate& __err,
1911 const ctype<char_type>& __ct) const
1912{
1913 // Note: ignoring case comes from the POSIX strptime spec
1914 const string_type* __wk = this->__weeks();
Arthur O'Dwyere75dcfa2020-11-22 13:21:11 -05001915 ptrdiff_t __i = _VSTD::__scan_keyword(__b, __e, __wk, __wk+14, __ct, __err, false) - __wk;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001916 if (__i < 14)
1917 __w = __i % 7;
1918}
1919
1920template <class _CharT, class _InputIterator>
1921void
1922time_get<_CharT, _InputIterator>::__get_monthname(int& __m,
1923 iter_type& __b, iter_type __e,
1924 ios_base::iostate& __err,
1925 const ctype<char_type>& __ct) const
1926{
1927 // Note: ignoring case comes from the POSIX strptime spec
1928 const string_type* __month = this->__months();
Arthur O'Dwyere75dcfa2020-11-22 13:21:11 -05001929 ptrdiff_t __i = _VSTD::__scan_keyword(__b, __e, __month, __month+24, __ct, __err, false) - __month;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001930 if (__i < 24)
1931 __m = __i % 12;
1932}
1933
1934template <class _CharT, class _InputIterator>
1935void
1936time_get<_CharT, _InputIterator>::__get_day(int& __d,
1937 iter_type& __b, iter_type __e,
1938 ios_base::iostate& __err,
1939 const ctype<char_type>& __ct) const
1940{
Arthur O'Dwyere75dcfa2020-11-22 13:21:11 -05001941 int __t = _VSTD::__get_up_to_n_digits(__b, __e, __err, __ct, 2);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001942 if (!(__err & ios_base::failbit) && 1 <= __t && __t <= 31)
1943 __d = __t;
1944 else
1945 __err |= ios_base::failbit;
1946}
1947
1948template <class _CharT, class _InputIterator>
1949void
1950time_get<_CharT, _InputIterator>::__get_month(int& __m,
1951 iter_type& __b, iter_type __e,
1952 ios_base::iostate& __err,
1953 const ctype<char_type>& __ct) const
1954{
1955 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2) - 1;
1956 if (!(__err & ios_base::failbit) && __t <= 11)
1957 __m = __t;
1958 else
1959 __err |= ios_base::failbit;
1960}
1961
1962template <class _CharT, class _InputIterator>
1963void
1964time_get<_CharT, _InputIterator>::__get_year(int& __y,
1965 iter_type& __b, iter_type __e,
1966 ios_base::iostate& __err,
1967 const ctype<char_type>& __ct) const
1968{
1969 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 4);
1970 if (!(__err & ios_base::failbit))
1971 {
1972 if (__t < 69)
1973 __t += 2000;
1974 else if (69 <= __t && __t <= 99)
1975 __t += 1900;
1976 __y = __t - 1900;
1977 }
1978}
1979
1980template <class _CharT, class _InputIterator>
1981void
1982time_get<_CharT, _InputIterator>::__get_year4(int& __y,
1983 iter_type& __b, iter_type __e,
1984 ios_base::iostate& __err,
1985 const ctype<char_type>& __ct) const
1986{
1987 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 4);
1988 if (!(__err & ios_base::failbit))
1989 __y = __t - 1900;
1990}
1991
1992template <class _CharT, class _InputIterator>
1993void
1994time_get<_CharT, _InputIterator>::__get_hour(int& __h,
1995 iter_type& __b, iter_type __e,
1996 ios_base::iostate& __err,
1997 const ctype<char_type>& __ct) const
1998{
1999 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2000 if (!(__err & ios_base::failbit) && __t <= 23)
2001 __h = __t;
2002 else
2003 __err |= ios_base::failbit;
2004}
2005
2006template <class _CharT, class _InputIterator>
2007void
2008time_get<_CharT, _InputIterator>::__get_12_hour(int& __h,
2009 iter_type& __b, iter_type __e,
2010 ios_base::iostate& __err,
2011 const ctype<char_type>& __ct) const
2012{
2013 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2014 if (!(__err & ios_base::failbit) && 1 <= __t && __t <= 12)
2015 __h = __t;
2016 else
2017 __err |= ios_base::failbit;
2018}
2019
2020template <class _CharT, class _InputIterator>
2021void
2022time_get<_CharT, _InputIterator>::__get_minute(int& __m,
2023 iter_type& __b, iter_type __e,
2024 ios_base::iostate& __err,
2025 const ctype<char_type>& __ct) const
2026{
2027 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2028 if (!(__err & ios_base::failbit) && __t <= 59)
2029 __m = __t;
2030 else
2031 __err |= ios_base::failbit;
2032}
2033
2034template <class _CharT, class _InputIterator>
2035void
2036time_get<_CharT, _InputIterator>::__get_second(int& __s,
2037 iter_type& __b, iter_type __e,
2038 ios_base::iostate& __err,
2039 const ctype<char_type>& __ct) const
2040{
2041 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
2042 if (!(__err & ios_base::failbit) && __t <= 60)
2043 __s = __t;
2044 else
2045 __err |= ios_base::failbit;
2046}
2047
2048template <class _CharT, class _InputIterator>
2049void
2050time_get<_CharT, _InputIterator>::__get_weekday(int& __w,
2051 iter_type& __b, iter_type __e,
2052 ios_base::iostate& __err,
2053 const ctype<char_type>& __ct) const
2054{
2055 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 1);
2056 if (!(__err & ios_base::failbit) && __t <= 6)
2057 __w = __t;
2058 else
2059 __err |= ios_base::failbit;
2060}
2061
2062template <class _CharT, class _InputIterator>
2063void
2064time_get<_CharT, _InputIterator>::__get_day_year_num(int& __d,
2065 iter_type& __b, iter_type __e,
2066 ios_base::iostate& __err,
2067 const ctype<char_type>& __ct) const
2068{
2069 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 3);
2070 if (!(__err & ios_base::failbit) && __t <= 365)
2071 __d = __t;
2072 else
2073 __err |= ios_base::failbit;
2074}
2075
2076template <class _CharT, class _InputIterator>
2077void
2078time_get<_CharT, _InputIterator>::__get_white_space(iter_type& __b, iter_type __e,
2079 ios_base::iostate& __err,
2080 const ctype<char_type>& __ct) const
2081{
2082 for (; __b != __e && __ct.is(ctype_base::space, *__b); ++__b)
2083 ;
2084 if (__b == __e)
2085 __err |= ios_base::eofbit;
2086}
2087
2088template <class _CharT, class _InputIterator>
2089void
2090time_get<_CharT, _InputIterator>::__get_am_pm(int& __h,
2091 iter_type& __b, iter_type __e,
2092 ios_base::iostate& __err,
2093 const ctype<char_type>& __ct) const
2094{
2095 const string_type* __ap = this->__am_pm();
2096 if (__ap[0].size() + __ap[1].size() == 0)
2097 {
2098 __err |= ios_base::failbit;
2099 return;
2100 }
Arthur O'Dwyere75dcfa2020-11-22 13:21:11 -05002101 ptrdiff_t __i = _VSTD::__scan_keyword(__b, __e, __ap, __ap+2, __ct, __err, false) - __ap;
Howard Hinnantc51e1022010-05-11 19:42:16 +00002102 if (__i == 0 && __h == 12)
2103 __h = 0;
2104 else if (__i == 1 && __h < 12)
2105 __h += 12;
2106}
2107
2108template <class _CharT, class _InputIterator>
2109void
2110time_get<_CharT, _InputIterator>::__get_percent(iter_type& __b, iter_type __e,
2111 ios_base::iostate& __err,
2112 const ctype<char_type>& __ct) const
2113{
2114 if (__b == __e)
2115 {
2116 __err |= ios_base::eofbit | ios_base::failbit;
2117 return;
2118 }
2119 if (__ct.narrow(*__b, 0) != '%')
2120 __err |= ios_base::failbit;
2121 else if(++__b == __e)
2122 __err |= ios_base::eofbit;
2123}
2124
Alp Tokerb8a95f52014-05-15 11:27:39 +00002125// time_get end primitives
Howard Hinnantc51e1022010-05-11 19:42:16 +00002126
2127template <class _CharT, class _InputIterator>
2128_InputIterator
2129time_get<_CharT, _InputIterator>::get(iter_type __b, iter_type __e,
2130 ios_base& __iob,
2131 ios_base::iostate& __err, tm* __tm,
2132 const char_type* __fmtb, const char_type* __fmte) const
2133{
2134 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2135 __err = ios_base::goodbit;
2136 while (__fmtb != __fmte && __err == ios_base::goodbit)
2137 {
2138 if (__b == __e)
2139 {
2140 __err = ios_base::failbit;
2141 break;
2142 }
2143 if (__ct.narrow(*__fmtb, 0) == '%')
2144 {
2145 if (++__fmtb == __fmte)
2146 {
2147 __err = ios_base::failbit;
2148 break;
2149 }
2150 char __cmd = __ct.narrow(*__fmtb, 0);
2151 char __opt = '\0';
2152 if (__cmd == 'E' || __cmd == '0')
2153 {
2154 if (++__fmtb == __fmte)
2155 {
2156 __err = ios_base::failbit;
2157 break;
2158 }
2159 __opt = __cmd;
2160 __cmd = __ct.narrow(*__fmtb, 0);
2161 }
2162 __b = do_get(__b, __e, __iob, __err, __tm, __cmd, __opt);
2163 ++__fmtb;
2164 }
2165 else if (__ct.is(ctype_base::space, *__fmtb))
2166 {
2167 for (++__fmtb; __fmtb != __fmte && __ct.is(ctype_base::space, *__fmtb); ++__fmtb)
2168 ;
2169 for ( ; __b != __e && __ct.is(ctype_base::space, *__b); ++__b)
2170 ;
2171 }
2172 else if (__ct.toupper(*__b) == __ct.toupper(*__fmtb))
2173 {
2174 ++__b;
2175 ++__fmtb;
2176 }
2177 else
2178 __err = ios_base::failbit;
2179 }
2180 if (__b == __e)
2181 __err |= ios_base::eofbit;
2182 return __b;
2183}
2184
2185template <class _CharT, class _InputIterator>
2186typename time_get<_CharT, _InputIterator>::dateorder
2187time_get<_CharT, _InputIterator>::do_date_order() const
2188{
2189 return mdy;
2190}
2191
2192template <class _CharT, class _InputIterator>
2193_InputIterator
2194time_get<_CharT, _InputIterator>::do_get_time(iter_type __b, iter_type __e,
2195 ios_base& __iob,
2196 ios_base::iostate& __err,
2197 tm* __tm) const
2198{
2199 const char_type __fmt[] = {'%', 'H', ':', '%', 'M', ':', '%', 'S'};
2200 return get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2201}
2202
2203template <class _CharT, class _InputIterator>
2204_InputIterator
2205time_get<_CharT, _InputIterator>::do_get_date(iter_type __b, iter_type __e,
2206 ios_base& __iob,
2207 ios_base::iostate& __err,
2208 tm* __tm) const
2209{
Howard Hinnantc51e1022010-05-11 19:42:16 +00002210 const string_type& __fmt = this->__x();
2211 return get(__b, __e, __iob, __err, __tm, __fmt.data(), __fmt.data() + __fmt.size());
2212}
2213
2214template <class _CharT, class _InputIterator>
2215_InputIterator
2216time_get<_CharT, _InputIterator>::do_get_weekday(iter_type __b, iter_type __e,
2217 ios_base& __iob,
2218 ios_base::iostate& __err,
2219 tm* __tm) const
2220{
2221 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2222 __get_weekdayname(__tm->tm_wday, __b, __e, __err, __ct);
2223 return __b;
2224}
2225
2226template <class _CharT, class _InputIterator>
2227_InputIterator
2228time_get<_CharT, _InputIterator>::do_get_monthname(iter_type __b, iter_type __e,
2229 ios_base& __iob,
2230 ios_base::iostate& __err,
2231 tm* __tm) const
2232{
2233 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2234 __get_monthname(__tm->tm_mon, __b, __e, __err, __ct);
2235 return __b;
2236}
2237
2238template <class _CharT, class _InputIterator>
2239_InputIterator
2240time_get<_CharT, _InputIterator>::do_get_year(iter_type __b, iter_type __e,
2241 ios_base& __iob,
2242 ios_base::iostate& __err,
2243 tm* __tm) const
2244{
2245 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2246 __get_year(__tm->tm_year, __b, __e, __err, __ct);
2247 return __b;
2248}
2249
2250template <class _CharT, class _InputIterator>
2251_InputIterator
2252time_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
2253 ios_base& __iob,
2254 ios_base::iostate& __err, tm* __tm,
2255 char __fmt, char) const
2256{
2257 __err = ios_base::goodbit;
2258 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2259 switch (__fmt)
2260 {
2261 case 'a':
2262 case 'A':
2263 __get_weekdayname(__tm->tm_wday, __b, __e, __err, __ct);
2264 break;
2265 case 'b':
2266 case 'B':
2267 case 'h':
2268 __get_monthname(__tm->tm_mon, __b, __e, __err, __ct);
2269 break;
2270 case 'c':
2271 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002272 const string_type& __fm = this->__c();
2273 __b = get(__b, __e, __iob, __err, __tm, __fm.data(), __fm.data() + __fm.size());
Howard Hinnantc51e1022010-05-11 19:42:16 +00002274 }
2275 break;
2276 case 'd':
2277 case 'e':
2278 __get_day(__tm->tm_mday, __b, __e, __err, __ct);
2279 break;
2280 case 'D':
2281 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002282 const char_type __fm[] = {'%', 'm', '/', '%', 'd', '/', '%', 'y'};
2283 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm)/sizeof(__fm[0]));
Howard Hinnantc51e1022010-05-11 19:42:16 +00002284 }
2285 break;
Howard Hinnantf60ff4e2011-04-10 17:54:14 +00002286 case 'F':
2287 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002288 const char_type __fm[] = {'%', 'Y', '-', '%', 'm', '-', '%', 'd'};
2289 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm)/sizeof(__fm[0]));
Howard Hinnantf60ff4e2011-04-10 17:54:14 +00002290 }
2291 break;
Howard Hinnantc51e1022010-05-11 19:42:16 +00002292 case 'H':
2293 __get_hour(__tm->tm_hour, __b, __e, __err, __ct);
2294 break;
2295 case 'I':
2296 __get_12_hour(__tm->tm_hour, __b, __e, __err, __ct);
2297 break;
2298 case 'j':
2299 __get_day_year_num(__tm->tm_yday, __b, __e, __err, __ct);
2300 break;
2301 case 'm':
2302 __get_month(__tm->tm_mon, __b, __e, __err, __ct);
2303 break;
2304 case 'M':
2305 __get_minute(__tm->tm_min, __b, __e, __err, __ct);
2306 break;
2307 case 'n':
2308 case 't':
2309 __get_white_space(__b, __e, __err, __ct);
2310 break;
2311 case 'p':
2312 __get_am_pm(__tm->tm_hour, __b, __e, __err, __ct);
2313 break;
2314 case 'r':
2315 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002316 const char_type __fm[] = {'%', 'I', ':', '%', 'M', ':', '%', 'S', ' ', '%', 'p'};
2317 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm)/sizeof(__fm[0]));
Howard Hinnantc51e1022010-05-11 19:42:16 +00002318 }
2319 break;
2320 case 'R':
2321 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002322 const char_type __fm[] = {'%', 'H', ':', '%', 'M'};
2323 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm)/sizeof(__fm[0]));
Howard Hinnantc51e1022010-05-11 19:42:16 +00002324 }
2325 break;
2326 case 'S':
2327 __get_second(__tm->tm_sec, __b, __e, __err, __ct);
2328 break;
2329 case 'T':
2330 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002331 const char_type __fm[] = {'%', 'H', ':', '%', 'M', ':', '%', 'S'};
2332 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm)/sizeof(__fm[0]));
Howard Hinnantc51e1022010-05-11 19:42:16 +00002333 }
2334 break;
2335 case 'w':
2336 __get_weekday(__tm->tm_wday, __b, __e, __err, __ct);
2337 break;
2338 case 'x':
2339 return do_get_date(__b, __e, __iob, __err, __tm);
2340 case 'X':
2341 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002342 const string_type& __fm = this->__X();
2343 __b = get(__b, __e, __iob, __err, __tm, __fm.data(), __fm.data() + __fm.size());
Howard Hinnantc51e1022010-05-11 19:42:16 +00002344 }
2345 break;
2346 case 'y':
2347 __get_year(__tm->tm_year, __b, __e, __err, __ct);
2348 break;
2349 case 'Y':
2350 __get_year4(__tm->tm_year, __b, __e, __err, __ct);
2351 break;
2352 case '%':
2353 __get_percent(__b, __e, __err, __ct);
2354 break;
2355 default:
2356 __err |= ios_base::failbit;
2357 }
2358 return __b;
2359}
2360
Louis Dionneb5ae3a72020-10-02 14:29:48 -04002361_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_get<char>)
2362_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_get<wchar_t>)
Howard Hinnantc51e1022010-05-11 19:42:16 +00002363
Howard Hinnanta37d3cf2013-08-12 18:38:34 +00002364class _LIBCPP_TYPE_VIS __time_get
Howard Hinnantc51e1022010-05-11 19:42:16 +00002365{
2366protected:
2367 locale_t __loc_;
2368
2369 __time_get(const char* __nm);
2370 __time_get(const string& __nm);
2371 ~__time_get();
2372};
2373
2374template <class _CharT>
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +00002375class _LIBCPP_TEMPLATE_VIS __time_get_storage
Howard Hinnantc51e1022010-05-11 19:42:16 +00002376 : public __time_get
2377{
2378protected:
2379 typedef basic_string<_CharT> string_type;
2380
2381 string_type __weeks_[14];
2382 string_type __months_[24];
2383 string_type __am_pm_[2];
2384 string_type __c_;
2385 string_type __r_;
2386 string_type __x_;
2387 string_type __X_;
2388
2389 explicit __time_get_storage(const char* __nm);
2390 explicit __time_get_storage(const string& __nm);
2391
Louis Dionne16fe2952018-07-11 23:14:33 +00002392 _LIBCPP_INLINE_VISIBILITY ~__time_get_storage() {}
Howard Hinnantc51e1022010-05-11 19:42:16 +00002393
2394 time_base::dateorder __do_date_order() const;
2395
2396private:
2397 void init(const ctype<_CharT>&);
2398 string_type __analyze(char __fmt, const ctype<_CharT>&);
2399};
2400
Louis Dionne5254b372018-10-25 12:13:43 +00002401#define _LIBCPP_TIME_GET_STORAGE_EXPLICIT_INSTANTIATION(_CharT) \
2402template <> _LIBCPP_FUNC_VIS time_base::dateorder __time_get_storage<_CharT>::__do_date_order() const; \
2403template <> _LIBCPP_FUNC_VIS __time_get_storage<_CharT>::__time_get_storage(const char*); \
2404template <> _LIBCPP_FUNC_VIS __time_get_storage<_CharT>::__time_get_storage(const string&); \
2405template <> _LIBCPP_FUNC_VIS void __time_get_storage<_CharT>::init(const ctype<_CharT>&); \
2406template <> _LIBCPP_FUNC_VIS __time_get_storage<_CharT>::string_type __time_get_storage<_CharT>::__analyze(char, const ctype<_CharT>&); \
2407extern template _LIBCPP_FUNC_VIS time_base::dateorder __time_get_storage<_CharT>::__do_date_order() const; \
2408extern template _LIBCPP_FUNC_VIS __time_get_storage<_CharT>::__time_get_storage(const char*); \
2409extern template _LIBCPP_FUNC_VIS __time_get_storage<_CharT>::__time_get_storage(const string&); \
2410extern template _LIBCPP_FUNC_VIS void __time_get_storage<_CharT>::init(const ctype<_CharT>&); \
2411extern template _LIBCPP_FUNC_VIS __time_get_storage<_CharT>::string_type __time_get_storage<_CharT>::__analyze(char, const ctype<_CharT>&); \
2412/**/
2413
2414_LIBCPP_TIME_GET_STORAGE_EXPLICIT_INSTANTIATION(char)
2415_LIBCPP_TIME_GET_STORAGE_EXPLICIT_INSTANTIATION(wchar_t)
2416#undef _LIBCPP_TIME_GET_STORAGE_EXPLICIT_INSTANTIATION
2417
Howard Hinnantc51e1022010-05-11 19:42:16 +00002418template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +00002419class _LIBCPP_TEMPLATE_VIS time_get_byname
Howard Hinnantc51e1022010-05-11 19:42:16 +00002420 : public time_get<_CharT, _InputIterator>,
2421 private __time_get_storage<_CharT>
2422{
2423public:
2424 typedef time_base::dateorder dateorder;
2425 typedef _InputIterator iter_type;
2426 typedef _CharT char_type;
2427 typedef basic_string<char_type> string_type;
2428
Howard Hinnant756c69b2010-09-22 16:48:34 +00002429 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002430 explicit time_get_byname(const char* __nm, size_t __refs = 0)
2431 : time_get<_CharT, _InputIterator>(__refs),
2432 __time_get_storage<_CharT>(__nm) {}
Howard Hinnant756c69b2010-09-22 16:48:34 +00002433 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002434 explicit time_get_byname(const string& __nm, size_t __refs = 0)
2435 : time_get<_CharT, _InputIterator>(__refs),
2436 __time_get_storage<_CharT>(__nm) {}
2437
2438protected:
Howard Hinnant756c69b2010-09-22 16:48:34 +00002439 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002440 ~time_get_byname() {}
2441
Howard Hinnant756c69b2010-09-22 16:48:34 +00002442 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002443 virtual dateorder do_date_order() const {return this->__do_date_order();}
2444private:
Howard Hinnant756c69b2010-09-22 16:48:34 +00002445 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002446 virtual const string_type* __weeks() const {return this->__weeks_;}
Howard Hinnant756c69b2010-09-22 16:48:34 +00002447 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002448 virtual const string_type* __months() const {return this->__months_;}
Howard Hinnant756c69b2010-09-22 16:48:34 +00002449 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002450 virtual const string_type* __am_pm() const {return this->__am_pm_;}
Howard Hinnant756c69b2010-09-22 16:48:34 +00002451 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002452 virtual const string_type& __c() const {return this->__c_;}
Howard Hinnant756c69b2010-09-22 16:48:34 +00002453 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002454 virtual const string_type& __r() const {return this->__r_;}
Howard Hinnant756c69b2010-09-22 16:48:34 +00002455 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002456 virtual const string_type& __x() const {return this->__x_;}
Howard Hinnant756c69b2010-09-22 16:48:34 +00002457 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002458 virtual const string_type& __X() const {return this->__X_;}
2459};
2460
Louis Dionneb5ae3a72020-10-02 14:29:48 -04002461_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_get_byname<char>)
2462_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_get_byname<wchar_t>)
Howard Hinnantc51e1022010-05-11 19:42:16 +00002463
Howard Hinnanta37d3cf2013-08-12 18:38:34 +00002464class _LIBCPP_TYPE_VIS __time_put
Howard Hinnantc51e1022010-05-11 19:42:16 +00002465{
2466 locale_t __loc_;
2467protected:
Louis Dionne16fe2952018-07-11 23:14:33 +00002468 _LIBCPP_INLINE_VISIBILITY __time_put() : __loc_(_LIBCPP_GET_C_LOCALE) {}
Howard Hinnantc51e1022010-05-11 19:42:16 +00002469 __time_put(const char* __nm);
2470 __time_put(const string& __nm);
2471 ~__time_put();
2472 void __do_put(char* __nb, char*& __ne, const tm* __tm,
2473 char __fmt, char __mod) const;
2474 void __do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
2475 char __fmt, char __mod) const;
2476};
2477
2478template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +00002479class _LIBCPP_TEMPLATE_VIS time_put
Howard Hinnantc51e1022010-05-11 19:42:16 +00002480 : public locale::facet,
2481 private __time_put
2482{
2483public:
2484 typedef _CharT char_type;
2485 typedef _OutputIterator iter_type;
2486
Louis Dionne16fe2952018-07-11 23:14:33 +00002487 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002488 explicit time_put(size_t __refs = 0)
2489 : locale::facet(__refs) {}
2490
2491 iter_type put(iter_type __s, ios_base& __iob, char_type __fl, const tm* __tm,
2492 const char_type* __pb, const char_type* __pe) const;
2493
Louis Dionne16fe2952018-07-11 23:14:33 +00002494 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002495 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
2496 const tm* __tm, char __fmt, char __mod = 0) const
2497 {
2498 return do_put(__s, __iob, __fl, __tm, __fmt, __mod);
2499 }
2500
2501 static locale::id id;
2502
2503protected:
Louis Dionne16fe2952018-07-11 23:14:33 +00002504 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002505 ~time_put() {}
2506 virtual iter_type do_put(iter_type __s, ios_base&, char_type, const tm* __tm,
2507 char __fmt, char __mod) const;
2508
Louis Dionne16fe2952018-07-11 23:14:33 +00002509 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002510 explicit time_put(const char* __nm, size_t __refs)
2511 : locale::facet(__refs),
2512 __time_put(__nm) {}
Louis Dionne16fe2952018-07-11 23:14:33 +00002513 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002514 explicit time_put(const string& __nm, size_t __refs)
2515 : locale::facet(__refs),
2516 __time_put(__nm) {}
2517};
2518
2519template <class _CharT, class _OutputIterator>
2520locale::id
2521time_put<_CharT, _OutputIterator>::id;
2522
2523template <class _CharT, class _OutputIterator>
2524_OutputIterator
2525time_put<_CharT, _OutputIterator>::put(iter_type __s, ios_base& __iob,
2526 char_type __fl, const tm* __tm,
2527 const char_type* __pb,
2528 const char_type* __pe) const
2529{
2530 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2531 for (; __pb != __pe; ++__pb)
2532 {
2533 if (__ct.narrow(*__pb, 0) == '%')
2534 {
2535 if (++__pb == __pe)
2536 {
2537 *__s++ = __pb[-1];
2538 break;
2539 }
2540 char __mod = 0;
2541 char __fmt = __ct.narrow(*__pb, 0);
2542 if (__fmt == 'E' || __fmt == 'O')
2543 {
2544 if (++__pb == __pe)
2545 {
2546 *__s++ = __pb[-2];
2547 *__s++ = __pb[-1];
2548 break;
2549 }
2550 __mod = __fmt;
2551 __fmt = __ct.narrow(*__pb, 0);
2552 }
2553 __s = do_put(__s, __iob, __fl, __tm, __fmt, __mod);
2554 }
2555 else
2556 *__s++ = *__pb;
2557 }
2558 return __s;
2559}
2560
2561template <class _CharT, class _OutputIterator>
2562_OutputIterator
Howard Hinnant28b24882011-12-01 20:21:04 +00002563time_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00002564 char_type, const tm* __tm,
2565 char __fmt, char __mod) const
2566{
2567 char_type __nar[100];
2568 char_type* __nb = __nar;
2569 char_type* __ne = __nb + 100;
2570 __do_put(__nb, __ne, __tm, __fmt, __mod);
Howard Hinnantb1ad5a82011-06-30 21:18:19 +00002571 return _VSTD::copy(__nb, __ne, __s);
Howard Hinnantc51e1022010-05-11 19:42:16 +00002572}
2573
Louis Dionneb5ae3a72020-10-02 14:29:48 -04002574_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_put<char>)
2575_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_put<wchar_t>)
Howard Hinnantc51e1022010-05-11 19:42:16 +00002576
2577template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +00002578class _LIBCPP_TEMPLATE_VIS time_put_byname
Howard Hinnantc51e1022010-05-11 19:42:16 +00002579 : public time_put<_CharT, _OutputIterator>
2580{
2581public:
Louis Dionne16fe2952018-07-11 23:14:33 +00002582 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002583 explicit time_put_byname(const char* __nm, size_t __refs = 0)
2584 : time_put<_CharT, _OutputIterator>(__nm, __refs) {}
2585
Louis Dionne16fe2952018-07-11 23:14:33 +00002586 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002587 explicit time_put_byname(const string& __nm, size_t __refs = 0)
2588 : time_put<_CharT, _OutputIterator>(__nm, __refs) {}
2589
2590protected:
Louis Dionne16fe2952018-07-11 23:14:33 +00002591 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002592 ~time_put_byname() {}
2593};
2594
Louis Dionneb5ae3a72020-10-02 14:29:48 -04002595_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_put_byname<char>)
2596_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_put_byname<wchar_t>)
Howard Hinnantc51e1022010-05-11 19:42:16 +00002597
2598// money_base
2599
Howard Hinnant8331b762013-03-06 23:30:19 +00002600class _LIBCPP_TYPE_VIS money_base
Howard Hinnantc51e1022010-05-11 19:42:16 +00002601{
2602public:
2603 enum part {none, space, symbol, sign, value};
2604 struct pattern {char field[4];};
2605
Louis Dionne16fe2952018-07-11 23:14:33 +00002606 _LIBCPP_INLINE_VISIBILITY money_base() {}
Howard Hinnantc51e1022010-05-11 19:42:16 +00002607};
2608
2609// moneypunct
2610
2611template <class _CharT, bool _International = false>
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +00002612class _LIBCPP_TEMPLATE_VIS moneypunct
Howard Hinnantc51e1022010-05-11 19:42:16 +00002613 : public locale::facet,
2614 public money_base
2615{
2616public:
2617 typedef _CharT char_type;
2618 typedef basic_string<char_type> string_type;
2619
Louis Dionne16fe2952018-07-11 23:14:33 +00002620 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002621 explicit moneypunct(size_t __refs = 0)
2622 : locale::facet(__refs) {}
2623
Louis Dionne16fe2952018-07-11 23:14:33 +00002624 _LIBCPP_INLINE_VISIBILITY char_type decimal_point() const {return do_decimal_point();}
2625 _LIBCPP_INLINE_VISIBILITY char_type thousands_sep() const {return do_thousands_sep();}
2626 _LIBCPP_INLINE_VISIBILITY string grouping() const {return do_grouping();}
2627 _LIBCPP_INLINE_VISIBILITY string_type curr_symbol() const {return do_curr_symbol();}
2628 _LIBCPP_INLINE_VISIBILITY string_type positive_sign() const {return do_positive_sign();}
2629 _LIBCPP_INLINE_VISIBILITY string_type negative_sign() const {return do_negative_sign();}
2630 _LIBCPP_INLINE_VISIBILITY int frac_digits() const {return do_frac_digits();}
2631 _LIBCPP_INLINE_VISIBILITY pattern pos_format() const {return do_pos_format();}
2632 _LIBCPP_INLINE_VISIBILITY pattern neg_format() const {return do_neg_format();}
Howard Hinnantc51e1022010-05-11 19:42:16 +00002633
2634 static locale::id id;
2635 static const bool intl = _International;
2636
2637protected:
Louis Dionne16fe2952018-07-11 23:14:33 +00002638 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002639 ~moneypunct() {}
2640
2641 virtual char_type do_decimal_point() const {return numeric_limits<char_type>::max();}
2642 virtual char_type do_thousands_sep() const {return numeric_limits<char_type>::max();}
2643 virtual string do_grouping() const {return string();}
2644 virtual string_type do_curr_symbol() const {return string_type();}
2645 virtual string_type do_positive_sign() const {return string_type();}
2646 virtual string_type do_negative_sign() const {return string_type(1, '-');}
2647 virtual int do_frac_digits() const {return 0;}
2648 virtual pattern do_pos_format() const
Howard Hinnantb10e6cf2012-11-06 21:48:33 +00002649 {pattern __p = {{symbol, sign, none, value}}; return __p;}
Howard Hinnantc51e1022010-05-11 19:42:16 +00002650 virtual pattern do_neg_format() const
Howard Hinnantb10e6cf2012-11-06 21:48:33 +00002651 {pattern __p = {{symbol, sign, none, value}}; return __p;}
Howard Hinnantc51e1022010-05-11 19:42:16 +00002652};
2653
2654template <class _CharT, bool _International>
2655locale::id
2656moneypunct<_CharT, _International>::id;
2657
Howard Hinnant2c45cb42012-12-12 21:14:28 +00002658template <class _CharT, bool _International>
2659const bool
2660moneypunct<_CharT, _International>::intl;
2661
Louis Dionneb5ae3a72020-10-02 14:29:48 -04002662_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct<char, false>)
2663_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct<char, true>)
2664_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct<wchar_t, false>)
2665_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct<wchar_t, true>)
Howard Hinnantc51e1022010-05-11 19:42:16 +00002666
2667// moneypunct_byname
2668
2669template <class _CharT, bool _International = false>
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +00002670class _LIBCPP_TEMPLATE_VIS moneypunct_byname
Howard Hinnant756c69b2010-09-22 16:48:34 +00002671 : public moneypunct<_CharT, _International>
Howard Hinnantc51e1022010-05-11 19:42:16 +00002672{
2673public:
2674 typedef money_base::pattern pattern;
2675 typedef _CharT char_type;
2676 typedef basic_string<char_type> string_type;
2677
Louis Dionne16fe2952018-07-11 23:14:33 +00002678 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002679 explicit moneypunct_byname(const char* __nm, size_t __refs = 0)
2680 : moneypunct<_CharT, _International>(__refs) {init(__nm);}
2681
Louis Dionne16fe2952018-07-11 23:14:33 +00002682 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002683 explicit moneypunct_byname(const string& __nm, size_t __refs = 0)
2684 : moneypunct<_CharT, _International>(__refs) {init(__nm.c_str());}
2685
2686protected:
Louis Dionne16fe2952018-07-11 23:14:33 +00002687 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002688 ~moneypunct_byname() {}
2689
2690 virtual char_type do_decimal_point() const {return __decimal_point_;}
2691 virtual char_type do_thousands_sep() const {return __thousands_sep_;}
2692 virtual string do_grouping() const {return __grouping_;}
2693 virtual string_type do_curr_symbol() const {return __curr_symbol_;}
2694 virtual string_type do_positive_sign() const {return __positive_sign_;}
2695 virtual string_type do_negative_sign() const {return __negative_sign_;}
2696 virtual int do_frac_digits() const {return __frac_digits_;}
2697 virtual pattern do_pos_format() const {return __pos_format_;}
2698 virtual pattern do_neg_format() const {return __neg_format_;}
2699
2700private:
2701 char_type __decimal_point_;
2702 char_type __thousands_sep_;
2703 string __grouping_;
2704 string_type __curr_symbol_;
2705 string_type __positive_sign_;
2706 string_type __negative_sign_;
2707 int __frac_digits_;
2708 pattern __pos_format_;
2709 pattern __neg_format_;
2710
2711 void init(const char*);
2712};
2713
Shoaib Meenai094c3d22017-04-03 04:04:24 +00002714template<> _LIBCPP_FUNC_VIS void moneypunct_byname<char, false>::init(const char*);
2715template<> _LIBCPP_FUNC_VIS void moneypunct_byname<char, true>::init(const char*);
2716template<> _LIBCPP_FUNC_VIS void moneypunct_byname<wchar_t, false>::init(const char*);
2717template<> _LIBCPP_FUNC_VIS void moneypunct_byname<wchar_t, true>::init(const char*);
Howard Hinnantc51e1022010-05-11 19:42:16 +00002718
Louis Dionneb5ae3a72020-10-02 14:29:48 -04002719_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct_byname<char, false>)
2720_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct_byname<char, true>)
2721_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct_byname<wchar_t, false>)
2722_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct_byname<wchar_t, true>)
Howard Hinnantc51e1022010-05-11 19:42:16 +00002723
2724// money_get
2725
2726template <class _CharT>
2727class __money_get
2728{
2729protected:
2730 typedef _CharT char_type;
2731 typedef basic_string<char_type> string_type;
2732
Louis Dionne16fe2952018-07-11 23:14:33 +00002733 _LIBCPP_INLINE_VISIBILITY __money_get() {}
Howard Hinnantc51e1022010-05-11 19:42:16 +00002734
2735 static void __gather_info(bool __intl, const locale& __loc,
2736 money_base::pattern& __pat, char_type& __dp,
2737 char_type& __ts, string& __grp,
2738 string_type& __sym, string_type& __psn,
2739 string_type& __nsn, int& __fd);
2740};
2741
2742template <class _CharT>
2743void
2744__money_get<_CharT>::__gather_info(bool __intl, const locale& __loc,
2745 money_base::pattern& __pat, char_type& __dp,
2746 char_type& __ts, string& __grp,
2747 string_type& __sym, string_type& __psn,
2748 string_type& __nsn, int& __fd)
2749{
2750 if (__intl)
2751 {
2752 const moneypunct<char_type, true>& __mp =
2753 use_facet<moneypunct<char_type, true> >(__loc);
2754 __pat = __mp.neg_format();
2755 __nsn = __mp.negative_sign();
2756 __psn = __mp.positive_sign();
2757 __dp = __mp.decimal_point();
2758 __ts = __mp.thousands_sep();
2759 __grp = __mp.grouping();
2760 __sym = __mp.curr_symbol();
2761 __fd = __mp.frac_digits();
2762 }
2763 else
2764 {
2765 const moneypunct<char_type, false>& __mp =
2766 use_facet<moneypunct<char_type, false> >(__loc);
2767 __pat = __mp.neg_format();
2768 __nsn = __mp.negative_sign();
2769 __psn = __mp.positive_sign();
2770 __dp = __mp.decimal_point();
2771 __ts = __mp.thousands_sep();
2772 __grp = __mp.grouping();
2773 __sym = __mp.curr_symbol();
2774 __fd = __mp.frac_digits();
2775 }
2776}
2777
Louis Dionneb5ae3a72020-10-02 14:29:48 -04002778_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __money_get<char>)
2779_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __money_get<wchar_t>)
Howard Hinnantc51e1022010-05-11 19:42:16 +00002780
2781template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +00002782class _LIBCPP_TEMPLATE_VIS money_get
Howard Hinnantc51e1022010-05-11 19:42:16 +00002783 : public locale::facet,
2784 private __money_get<_CharT>
2785{
2786public:
2787 typedef _CharT char_type;
2788 typedef _InputIterator iter_type;
2789 typedef basic_string<char_type> string_type;
2790
Louis Dionne16fe2952018-07-11 23:14:33 +00002791 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002792 explicit money_get(size_t __refs = 0)
2793 : locale::facet(__refs) {}
2794
Louis Dionne16fe2952018-07-11 23:14:33 +00002795 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002796 iter_type get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob,
2797 ios_base::iostate& __err, long double& __v) const
2798 {
2799 return do_get(__b, __e, __intl, __iob, __err, __v);
2800 }
2801
Louis Dionne16fe2952018-07-11 23:14:33 +00002802 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002803 iter_type get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob,
2804 ios_base::iostate& __err, string_type& __v) const
2805 {
2806 return do_get(__b, __e, __intl, __iob, __err, __v);
2807 }
2808
2809 static locale::id id;
2810
2811protected:
2812
Louis Dionne16fe2952018-07-11 23:14:33 +00002813 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002814 ~money_get() {}
Howard Hinnant3b6579a2010-08-22 00:02:43 +00002815
Howard Hinnantc51e1022010-05-11 19:42:16 +00002816 virtual iter_type do_get(iter_type __b, iter_type __e, bool __intl,
2817 ios_base& __iob, ios_base::iostate& __err,
2818 long double& __v) const;
2819 virtual iter_type do_get(iter_type __b, iter_type __e, bool __intl,
2820 ios_base& __iob, ios_base::iostate& __err,
2821 string_type& __v) const;
2822
2823private:
2824 static bool __do_get(iter_type& __b, iter_type __e,
2825 bool __intl, const locale& __loc,
2826 ios_base::fmtflags __flags, ios_base::iostate& __err,
2827 bool& __neg, const ctype<char_type>& __ct,
2828 unique_ptr<char_type, void(*)(void*)>& __wb,
2829 char_type*& __wn, char_type* __we);
2830};
2831
2832template <class _CharT, class _InputIterator>
2833locale::id
2834money_get<_CharT, _InputIterator>::id;
2835
Howard Hinnanta37d3cf2013-08-12 18:38:34 +00002836_LIBCPP_FUNC_VIS void __do_nothing(void*);
Howard Hinnantc51e1022010-05-11 19:42:16 +00002837
2838template <class _Tp>
2839_LIBCPP_HIDDEN
2840void
2841__double_or_nothing(unique_ptr<_Tp, void(*)(void*)>& __b, _Tp*& __n, _Tp*& __e)
2842{
2843 bool __owns = __b.get_deleter() != __do_nothing;
Howard Hinnant28b24882011-12-01 20:21:04 +00002844 size_t __cur_cap = static_cast<size_t>(__e-__b.get()) * sizeof(_Tp);
Howard Hinnantc51e1022010-05-11 19:42:16 +00002845 size_t __new_cap = __cur_cap < numeric_limits<size_t>::max() / 2 ?
2846 2 * __cur_cap : numeric_limits<size_t>::max();
Marshall Clow6c9ddc22014-10-27 19:08:10 +00002847 if (__new_cap == 0)
2848 __new_cap = sizeof(_Tp);
Howard Hinnant28b24882011-12-01 20:21:04 +00002849 size_t __n_off = static_cast<size_t>(__n - __b.get());
Howard Hinnantc51e1022010-05-11 19:42:16 +00002850 _Tp* __t = (_Tp*)realloc(__owns ? __b.get() : 0, __new_cap);
2851 if (__t == 0)
2852 __throw_bad_alloc();
2853 if (__owns)
2854 __b.release();
2855 __b = unique_ptr<_Tp, void(*)(void*)>(__t, free);
2856 __new_cap /= sizeof(_Tp);
2857 __n = __b.get() + __n_off;
2858 __e = __b.get() + __new_cap;
2859}
2860
2861// true == success
2862template <class _CharT, class _InputIterator>
2863bool
2864money_get<_CharT, _InputIterator>::__do_get(iter_type& __b, iter_type __e,
2865 bool __intl, const locale& __loc,
2866 ios_base::fmtflags __flags,
2867 ios_base::iostate& __err,
2868 bool& __neg,
2869 const ctype<char_type>& __ct,
2870 unique_ptr<char_type, void(*)(void*)>& __wb,
2871 char_type*& __wn, char_type* __we)
2872{
2873 const unsigned __bz = 100;
2874 unsigned __gbuf[__bz];
2875 unique_ptr<unsigned, void(*)(void*)> __gb(__gbuf, __do_nothing);
2876 unsigned* __gn = __gb.get();
2877 unsigned* __ge = __gn + __bz;
2878 money_base::pattern __pat;
2879 char_type __dp;
2880 char_type __ts;
2881 string __grp;
2882 string_type __sym;
2883 string_type __psn;
2884 string_type __nsn;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00002885 // Capture the spaces read into money_base::{space,none} so they
2886 // can be compared to initial spaces in __sym.
2887 string_type __spaces;
Howard Hinnantc51e1022010-05-11 19:42:16 +00002888 int __fd;
2889 __money_get<_CharT>::__gather_info(__intl, __loc, __pat, __dp, __ts, __grp,
2890 __sym, __psn, __nsn, __fd);
2891 const string_type* __trailing_sign = 0;
2892 __wn = __wb.get();
2893 for (unsigned __p = 0; __p < 4 && __b != __e; ++__p)
2894 {
2895 switch (__pat.field[__p])
2896 {
2897 case money_base::space:
2898 if (__p != 3)
2899 {
2900 if (__ct.is(ctype_base::space, *__b))
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00002901 __spaces.push_back(*__b++);
Howard Hinnantc51e1022010-05-11 19:42:16 +00002902 else
2903 {
2904 __err |= ios_base::failbit;
2905 return false;
2906 }
2907 }
Eric Fiselier4db80032017-05-05 20:32:26 +00002908 _LIBCPP_FALLTHROUGH();
Howard Hinnantc51e1022010-05-11 19:42:16 +00002909 case money_base::none:
2910 if (__p != 3)
2911 {
2912 while (__b != __e && __ct.is(ctype_base::space, *__b))
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00002913 __spaces.push_back(*__b++);
Howard Hinnantc51e1022010-05-11 19:42:16 +00002914 }
2915 break;
2916 case money_base::sign:
2917 if (__psn.size() + __nsn.size() > 0)
2918 {
2919 if (__psn.size() == 0 || __nsn.size() == 0)
2920 { // sign is optional
2921 if (__psn.size() > 0)
2922 { // __nsn.size() == 0
2923 if (*__b == __psn[0])
2924 {
2925 ++__b;
2926 if (__psn.size() > 1)
2927 __trailing_sign = &__psn;
2928 }
2929 else
2930 __neg = true;
2931 }
2932 else if (*__b == __nsn[0]) // __nsn.size() > 0 && __psn.size() == 0
2933 {
2934 ++__b;
2935 __neg = true;
2936 if (__nsn.size() > 1)
2937 __trailing_sign = &__nsn;
2938 }
2939 }
2940 else // sign is required
2941 {
2942 if (*__b == __psn[0])
2943 {
2944 ++__b;
2945 if (__psn.size() > 1)
2946 __trailing_sign = &__psn;
2947 }
2948 else if (*__b == __nsn[0])
2949 {
2950 ++__b;
2951 __neg = true;
2952 if (__nsn.size() > 1)
2953 __trailing_sign = &__nsn;
2954 }
2955 else
2956 {
2957 __err |= ios_base::failbit;
2958 return false;
2959 }
2960 }
2961 }
2962 break;
2963 case money_base::symbol:
2964 {
2965 bool __more_needed = __trailing_sign ||
2966 (__p < 2) ||
2967 (__p == 2 && __pat.field[3] != static_cast<char>(money_base::none));
Marshall Clowdfcbb432013-10-13 01:02:45 +00002968 bool __sb = (__flags & ios_base::showbase) != 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +00002969 if (__sb || __more_needed)
2970 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00002971 typename string_type::const_iterator __sym_space_end = __sym.begin();
2972 if (__p > 0 && (__pat.field[__p - 1] == money_base::none ||
2973 __pat.field[__p - 1] == money_base::space)) {
2974 // Match spaces we've already read against spaces at
2975 // the beginning of __sym.
2976 while (__sym_space_end != __sym.end() &&
2977 __ct.is(ctype_base::space, *__sym_space_end))
2978 ++__sym_space_end;
2979 const size_t __num_spaces = __sym_space_end - __sym.begin();
2980 if (__num_spaces > __spaces.size() ||
2981 !equal(__spaces.end() - __num_spaces, __spaces.end(),
2982 __sym.begin())) {
2983 // No match. Put __sym_space_end back at the
2984 // beginning of __sym, which will prevent a
2985 // match in the next loop.
2986 __sym_space_end = __sym.begin();
2987 }
2988 }
2989 typename string_type::const_iterator __sym_curr_char = __sym_space_end;
2990 while (__sym_curr_char != __sym.end() && __b != __e &&
2991 *__b == *__sym_curr_char) {
2992 ++__b;
2993 ++__sym_curr_char;
2994 }
2995 if (__sb && __sym_curr_char != __sym.end())
Howard Hinnantc51e1022010-05-11 19:42:16 +00002996 {
2997 __err |= ios_base::failbit;
2998 return false;
2999 }
3000 }
3001 }
3002 break;
3003 case money_base::value:
3004 {
3005 unsigned __ng = 0;
3006 for (; __b != __e; ++__b)
3007 {
3008 char_type __c = *__b;
3009 if (__ct.is(ctype_base::digit, __c))
3010 {
3011 if (__wn == __we)
3012 __double_or_nothing(__wb, __wn, __we);
3013 *__wn++ = __c;
3014 ++__ng;
3015 }
3016 else if (__grp.size() > 0 && __ng > 0 && __c == __ts)
3017 {
3018 if (__gn == __ge)
3019 __double_or_nothing(__gb, __gn, __ge);
3020 *__gn++ = __ng;
3021 __ng = 0;
3022 }
3023 else
3024 break;
3025 }
3026 if (__gb.get() != __gn && __ng > 0)
3027 {
3028 if (__gn == __ge)
3029 __double_or_nothing(__gb, __gn, __ge);
3030 *__gn++ = __ng;
3031 }
3032 if (__fd > 0)
3033 {
3034 if (__b == __e || *__b != __dp)
3035 {
3036 __err |= ios_base::failbit;
3037 return false;
3038 }
3039 for (++__b; __fd > 0; --__fd, ++__b)
3040 {
3041 if (__b == __e || !__ct.is(ctype_base::digit, *__b))
3042 {
3043 __err |= ios_base::failbit;
3044 return false;
3045 }
3046 if (__wn == __we)
3047 __double_or_nothing(__wb, __wn, __we);
3048 *__wn++ = *__b;
3049 }
3050 }
3051 if (__wn == __wb.get())
3052 {
3053 __err |= ios_base::failbit;
3054 return false;
3055 }
3056 }
3057 break;
3058 }
3059 }
3060 if (__trailing_sign)
3061 {
3062 for (unsigned __i = 1; __i < __trailing_sign->size(); ++__i, ++__b)
3063 {
3064 if (__b == __e || *__b != (*__trailing_sign)[__i])
3065 {
3066 __err |= ios_base::failbit;
3067 return false;
3068 }
3069 }
3070 }
3071 if (__gb.get() != __gn)
3072 {
3073 ios_base::iostate __et = ios_base::goodbit;
3074 __check_grouping(__grp, __gb.get(), __gn, __et);
3075 if (__et)
3076 {
3077 __err |= ios_base::failbit;
3078 return false;
3079 }
3080 }
3081 return true;
3082}
3083
3084template <class _CharT, class _InputIterator>
3085_InputIterator
3086money_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
3087 bool __intl, ios_base& __iob,
3088 ios_base::iostate& __err,
3089 long double& __v) const
3090{
Howard Hinnant28b24882011-12-01 20:21:04 +00003091 const int __bz = 100;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003092 char_type __wbuf[__bz];
3093 unique_ptr<char_type, void(*)(void*)> __wb(__wbuf, __do_nothing);
3094 char_type* __wn;
3095 char_type* __we = __wbuf + __bz;
3096 locale __loc = __iob.getloc();
3097 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3098 bool __neg = false;
3099 if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct,
3100 __wb, __wn, __we))
3101 {
3102 const char __src[] = "0123456789";
3103 char_type __atoms[sizeof(__src)-1];
3104 __ct.widen(__src, __src + (sizeof(__src)-1), __atoms);
3105 char __nbuf[__bz];
3106 char* __nc = __nbuf;
Bruce Mitchener170d8972020-11-24 12:53:53 -05003107 unique_ptr<char, void(*)(void*)> __h(nullptr, free);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003108 if (__wn - __wb.get() > __bz-2)
3109 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003110 __h.reset((char*)malloc(static_cast<size_t>(__wn - __wb.get() + 2)));
Bruce Mitchener170d8972020-11-24 12:53:53 -05003111 if (__h.get() == nullptr)
Howard Hinnantc51e1022010-05-11 19:42:16 +00003112 __throw_bad_alloc();
3113 __nc = __h.get();
3114 }
3115 if (__neg)
3116 *__nc++ = '-';
3117 for (const char_type* __w = __wb.get(); __w < __wn; ++__w, ++__nc)
Marshall Clow1e68fd42013-03-22 02:14:40 +00003118 *__nc = __src[find(__atoms, _VSTD::end(__atoms), *__w) - __atoms];
Howard Hinnantc51e1022010-05-11 19:42:16 +00003119 *__nc = char();
3120 if (sscanf(__nbuf, "%Lf", &__v) != 1)
3121 __throw_runtime_error("money_get error");
3122 }
3123 if (__b == __e)
3124 __err |= ios_base::eofbit;
3125 return __b;
3126}
3127
3128template <class _CharT, class _InputIterator>
3129_InputIterator
3130money_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
3131 bool __intl, ios_base& __iob,
3132 ios_base::iostate& __err,
3133 string_type& __v) const
3134{
Howard Hinnant28b24882011-12-01 20:21:04 +00003135 const int __bz = 100;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003136 char_type __wbuf[__bz];
3137 unique_ptr<char_type, void(*)(void*)> __wb(__wbuf, __do_nothing);
3138 char_type* __wn;
3139 char_type* __we = __wbuf + __bz;
3140 locale __loc = __iob.getloc();
3141 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3142 bool __neg = false;
3143 if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct,
3144 __wb, __wn, __we))
3145 {
3146 __v.clear();
3147 if (__neg)
3148 __v.push_back(__ct.widen('-'));
3149 char_type __z = __ct.widen('0');
3150 char_type* __w;
3151 for (__w = __wb.get(); __w < __wn-1; ++__w)
3152 if (*__w != __z)
3153 break;
3154 __v.append(__w, __wn);
3155 }
3156 if (__b == __e)
3157 __err |= ios_base::eofbit;
3158 return __b;
3159}
3160
Louis Dionneb5ae3a72020-10-02 14:29:48 -04003161_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS money_get<char>)
3162_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS money_get<wchar_t>)
Howard Hinnantc51e1022010-05-11 19:42:16 +00003163
3164// money_put
3165
3166template <class _CharT>
3167class __money_put
3168{
3169protected:
3170 typedef _CharT char_type;
3171 typedef basic_string<char_type> string_type;
3172
Louis Dionne16fe2952018-07-11 23:14:33 +00003173 _LIBCPP_INLINE_VISIBILITY __money_put() {}
Howard Hinnantc51e1022010-05-11 19:42:16 +00003174
3175 static void __gather_info(bool __intl, bool __neg, const locale& __loc,
3176 money_base::pattern& __pat, char_type& __dp,
3177 char_type& __ts, string& __grp,
3178 string_type& __sym, string_type& __sn,
3179 int& __fd);
3180 static void __format(char_type* __mb, char_type*& __mi, char_type*& __me,
3181 ios_base::fmtflags __flags,
3182 const char_type* __db, const char_type* __de,
3183 const ctype<char_type>& __ct, bool __neg,
3184 const money_base::pattern& __pat, char_type __dp,
3185 char_type __ts, const string& __grp,
3186 const string_type& __sym, const string_type& __sn,
3187 int __fd);
3188};
3189
3190template <class _CharT>
3191void
3192__money_put<_CharT>::__gather_info(bool __intl, bool __neg, const locale& __loc,
3193 money_base::pattern& __pat, char_type& __dp,
3194 char_type& __ts, string& __grp,
3195 string_type& __sym, string_type& __sn,
3196 int& __fd)
3197{
3198 if (__intl)
3199 {
3200 const moneypunct<char_type, true>& __mp =
3201 use_facet<moneypunct<char_type, true> >(__loc);
3202 if (__neg)
3203 {
3204 __pat = __mp.neg_format();
3205 __sn = __mp.negative_sign();
3206 }
3207 else
3208 {
3209 __pat = __mp.pos_format();
3210 __sn = __mp.positive_sign();
3211 }
3212 __dp = __mp.decimal_point();
3213 __ts = __mp.thousands_sep();
3214 __grp = __mp.grouping();
3215 __sym = __mp.curr_symbol();
3216 __fd = __mp.frac_digits();
3217 }
3218 else
3219 {
3220 const moneypunct<char_type, false>& __mp =
3221 use_facet<moneypunct<char_type, false> >(__loc);
3222 if (__neg)
3223 {
3224 __pat = __mp.neg_format();
3225 __sn = __mp.negative_sign();
3226 }
3227 else
3228 {
3229 __pat = __mp.pos_format();
3230 __sn = __mp.positive_sign();
3231 }
3232 __dp = __mp.decimal_point();
3233 __ts = __mp.thousands_sep();
3234 __grp = __mp.grouping();
3235 __sym = __mp.curr_symbol();
3236 __fd = __mp.frac_digits();
3237 }
3238}
3239
3240template <class _CharT>
3241void
3242__money_put<_CharT>::__format(char_type* __mb, char_type*& __mi, char_type*& __me,
3243 ios_base::fmtflags __flags,
3244 const char_type* __db, const char_type* __de,
3245 const ctype<char_type>& __ct, bool __neg,
3246 const money_base::pattern& __pat, char_type __dp,
3247 char_type __ts, const string& __grp,
3248 const string_type& __sym, const string_type& __sn,
3249 int __fd)
3250{
3251 __me = __mb;
3252 for (unsigned __p = 0; __p < 4; ++__p)
3253 {
3254 switch (__pat.field[__p])
3255 {
3256 case money_base::none:
3257 __mi = __me;
3258 break;
3259 case money_base::space:
3260 __mi = __me;
3261 *__me++ = __ct.widen(' ');
3262 break;
3263 case money_base::sign:
3264 if (!__sn.empty())
3265 *__me++ = __sn[0];
3266 break;
3267 case money_base::symbol:
3268 if (!__sym.empty() && (__flags & ios_base::showbase))
Howard Hinnantb1ad5a82011-06-30 21:18:19 +00003269 __me = _VSTD::copy(__sym.begin(), __sym.end(), __me);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003270 break;
3271 case money_base::value:
3272 {
3273 // remember start of value so we can reverse it
3274 char_type* __t = __me;
3275 // find beginning of digits
3276 if (__neg)
3277 ++__db;
3278 // find end of digits
3279 const char_type* __d;
3280 for (__d = __db; __d < __de; ++__d)
3281 if (!__ct.is(ctype_base::digit, *__d))
3282 break;
3283 // print fractional part
3284 if (__fd > 0)
3285 {
3286 int __f;
3287 for (__f = __fd; __d > __db && __f > 0; --__f)
3288 *__me++ = *--__d;
3289 char_type __z = __f > 0 ? __ct.widen('0') : char_type();
3290 for (; __f > 0; --__f)
3291 *__me++ = __z;
3292 *__me++ = __dp;
3293 }
3294 // print units part
3295 if (__d == __db)
3296 {
3297 *__me++ = __ct.widen('0');
3298 }
3299 else
3300 {
3301 unsigned __ng = 0;
3302 unsigned __ig = 0;
3303 unsigned __gl = __grp.empty() ? numeric_limits<unsigned>::max()
3304 : static_cast<unsigned>(__grp[__ig]);
3305 while (__d != __db)
3306 {
3307 if (__ng == __gl)
3308 {
3309 *__me++ = __ts;
3310 __ng = 0;
3311 if (++__ig < __grp.size())
3312 __gl = __grp[__ig] == numeric_limits<char>::max() ?
3313 numeric_limits<unsigned>::max() :
3314 static_cast<unsigned>(__grp[__ig]);
3315 }
3316 *__me++ = *--__d;
3317 ++__ng;
3318 }
3319 }
3320 // reverse it
3321 reverse(__t, __me);
3322 }
3323 break;
3324 }
3325 }
3326 // print rest of sign, if any
3327 if (__sn.size() > 1)
Howard Hinnantb1ad5a82011-06-30 21:18:19 +00003328 __me = _VSTD::copy(__sn.begin()+1, __sn.end(), __me);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003329 // set alignment
3330 if ((__flags & ios_base::adjustfield) == ios_base::left)
3331 __mi = __me;
3332 else if ((__flags & ios_base::adjustfield) != ios_base::internal)
3333 __mi = __mb;
3334}
3335
Louis Dionneb5ae3a72020-10-02 14:29:48 -04003336_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __money_put<char>)
3337_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __money_put<wchar_t>)
Howard Hinnantc51e1022010-05-11 19:42:16 +00003338
3339template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +00003340class _LIBCPP_TEMPLATE_VIS money_put
Howard Hinnantc51e1022010-05-11 19:42:16 +00003341 : public locale::facet,
3342 private __money_put<_CharT>
3343{
3344public:
3345 typedef _CharT char_type;
3346 typedef _OutputIterator iter_type;
3347 typedef basic_string<char_type> string_type;
3348
Louis Dionne16fe2952018-07-11 23:14:33 +00003349 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00003350 explicit money_put(size_t __refs = 0)
3351 : locale::facet(__refs) {}
3352
Louis Dionne16fe2952018-07-11 23:14:33 +00003353 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00003354 iter_type put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl,
3355 long double __units) const
3356 {
3357 return do_put(__s, __intl, __iob, __fl, __units);
3358 }
3359
Louis Dionne16fe2952018-07-11 23:14:33 +00003360 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00003361 iter_type put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl,
3362 const string_type& __digits) const
3363 {
3364 return do_put(__s, __intl, __iob, __fl, __digits);
3365 }
3366
3367 static locale::id id;
3368
3369protected:
Louis Dionne16fe2952018-07-11 23:14:33 +00003370 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00003371 ~money_put() {}
3372
3373 virtual iter_type do_put(iter_type __s, bool __intl, ios_base& __iob,
3374 char_type __fl, long double __units) const;
3375 virtual iter_type do_put(iter_type __s, bool __intl, ios_base& __iob,
3376 char_type __fl, const string_type& __digits) const;
3377};
3378
3379template <class _CharT, class _OutputIterator>
3380locale::id
3381money_put<_CharT, _OutputIterator>::id;
3382
3383template <class _CharT, class _OutputIterator>
3384_OutputIterator
3385money_put<_CharT, _OutputIterator>::do_put(iter_type __s, bool __intl,
3386 ios_base& __iob, char_type __fl,
3387 long double __units) const
3388{
3389 // convert to char
3390 const size_t __bs = 100;
3391 char __buf[__bs];
3392 char* __bb = __buf;
3393 char_type __digits[__bs];
3394 char_type* __db = __digits;
Howard Hinnant28b24882011-12-01 20:21:04 +00003395 size_t __n = static_cast<size_t>(snprintf(__bb, __bs, "%.0Lf", __units));
Bruce Mitchener170d8972020-11-24 12:53:53 -05003396 unique_ptr<char, void(*)(void*)> __hn(nullptr, free);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003397 unique_ptr<char_type, void(*)(void*)> __hd(0, free);
3398 // secure memory for digit storage
3399 if (__n > __bs-1)
3400 {
Ben Craig3756b922016-03-09 15:39:39 +00003401 __n = static_cast<size_t>(__libcpp_asprintf_l(&__bb, _LIBCPP_GET_C_LOCALE, "%.0Lf", __units));
Bruce Mitchener170d8972020-11-24 12:53:53 -05003402 if (__bb == nullptr)
Howard Hinnantc51e1022010-05-11 19:42:16 +00003403 __throw_bad_alloc();
3404 __hn.reset(__bb);
3405 __hd.reset((char_type*)malloc(__n * sizeof(char_type)));
Howard Hinnant03de6f92012-03-07 20:37:43 +00003406 if (__hd == nullptr)
Howard Hinnantc51e1022010-05-11 19:42:16 +00003407 __throw_bad_alloc();
3408 __db = __hd.get();
3409 }
3410 // gather info
3411 locale __loc = __iob.getloc();
3412 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3413 __ct.widen(__bb, __bb + __n, __db);
3414 bool __neg = __n > 0 && __bb[0] == '-';
3415 money_base::pattern __pat;
3416 char_type __dp;
3417 char_type __ts;
3418 string __grp;
3419 string_type __sym;
3420 string_type __sn;
3421 int __fd;
3422 this->__gather_info(__intl, __neg, __loc, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3423 // secure memory for formatting
3424 char_type __mbuf[__bs];
3425 char_type* __mb = __mbuf;
3426 unique_ptr<char_type, void(*)(void*)> __hw(0, free);
3427 size_t __exn = static_cast<int>(__n) > __fd ?
Howard Hinnant28b24882011-12-01 20:21:04 +00003428 (__n - static_cast<size_t>(__fd)) * 2 + __sn.size() +
3429 __sym.size() + static_cast<size_t>(__fd) + 1
3430 : __sn.size() + __sym.size() + static_cast<size_t>(__fd) + 2;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003431 if (__exn > __bs)
3432 {
3433 __hw.reset((char_type*)malloc(__exn * sizeof(char_type)));
3434 __mb = __hw.get();
3435 if (__mb == 0)
3436 __throw_bad_alloc();
3437 }
3438 // format
3439 char_type* __mi;
3440 char_type* __me;
3441 this->__format(__mb, __mi, __me, __iob.flags(),
3442 __db, __db + __n, __ct,
3443 __neg, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3444 return __pad_and_output(__s, __mb, __mi, __me, __iob, __fl);
3445}
3446
3447template <class _CharT, class _OutputIterator>
3448_OutputIterator
3449money_put<_CharT, _OutputIterator>::do_put(iter_type __s, bool __intl,
3450 ios_base& __iob, char_type __fl,
3451 const string_type& __digits) const
3452{
3453 // gather info
3454 locale __loc = __iob.getloc();
3455 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3456 bool __neg = __digits.size() > 0 && __digits[0] == __ct.widen('-');
3457 money_base::pattern __pat;
3458 char_type __dp;
3459 char_type __ts;
3460 string __grp;
3461 string_type __sym;
3462 string_type __sn;
3463 int __fd;
3464 this->__gather_info(__intl, __neg, __loc, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3465 // secure memory for formatting
3466 char_type __mbuf[100];
3467 char_type* __mb = __mbuf;
3468 unique_ptr<char_type, void(*)(void*)> __h(0, free);
Howard Hinnant28b24882011-12-01 20:21:04 +00003469 size_t __exn = static_cast<int>(__digits.size()) > __fd ?
3470 (__digits.size() - static_cast<size_t>(__fd)) * 2 +
3471 __sn.size() + __sym.size() + static_cast<size_t>(__fd) + 1
3472 : __sn.size() + __sym.size() + static_cast<size_t>(__fd) + 2;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003473 if (__exn > 100)
3474 {
3475 __h.reset((char_type*)malloc(__exn * sizeof(char_type)));
3476 __mb = __h.get();
3477 if (__mb == 0)
3478 __throw_bad_alloc();
3479 }
3480 // format
3481 char_type* __mi;
3482 char_type* __me;
3483 this->__format(__mb, __mi, __me, __iob.flags(),
3484 __digits.data(), __digits.data() + __digits.size(), __ct,
3485 __neg, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3486 return __pad_and_output(__s, __mb, __mi, __me, __iob, __fl);
3487}
3488
Louis Dionneb5ae3a72020-10-02 14:29:48 -04003489_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS money_put<char>)
3490_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS money_put<wchar_t>)
Howard Hinnantc51e1022010-05-11 19:42:16 +00003491
3492// messages
3493
Howard Hinnant8331b762013-03-06 23:30:19 +00003494class _LIBCPP_TYPE_VIS messages_base
Howard Hinnantc51e1022010-05-11 19:42:16 +00003495{
3496public:
Howard Hinnant2862aeb2011-02-25 00:51:08 +00003497 typedef ptrdiff_t catalog;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003498
Louis Dionne16fe2952018-07-11 23:14:33 +00003499 _LIBCPP_INLINE_VISIBILITY messages_base() {}
Howard Hinnantc51e1022010-05-11 19:42:16 +00003500};
3501
3502template <class _CharT>
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +00003503class _LIBCPP_TEMPLATE_VIS messages
Howard Hinnantc51e1022010-05-11 19:42:16 +00003504 : public locale::facet,
3505 public messages_base
3506{
3507public:
3508 typedef _CharT char_type;
3509 typedef basic_string<_CharT> string_type;
3510
Louis Dionne16fe2952018-07-11 23:14:33 +00003511 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00003512 explicit messages(size_t __refs = 0)
3513 : locale::facet(__refs) {}
3514
Louis Dionne16fe2952018-07-11 23:14:33 +00003515 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00003516 catalog open(const basic_string<char>& __nm, const locale& __loc) const
3517 {
3518 return do_open(__nm, __loc);
3519 }
3520
Louis Dionne16fe2952018-07-11 23:14:33 +00003521 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00003522 string_type get(catalog __c, int __set, int __msgid,
3523 const string_type& __dflt) const
3524 {
3525 return do_get(__c, __set, __msgid, __dflt);
3526 }
3527
Louis Dionne16fe2952018-07-11 23:14:33 +00003528 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00003529 void close(catalog __c) const
3530 {
3531 do_close(__c);
3532 }
3533
3534 static locale::id id;
3535
3536protected:
Louis Dionne16fe2952018-07-11 23:14:33 +00003537 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00003538 ~messages() {}
3539
3540 virtual catalog do_open(const basic_string<char>&, const locale&) const;
3541 virtual string_type do_get(catalog, int __set, int __msgid,
3542 const string_type& __dflt) const;
3543 virtual void do_close(catalog) const;
3544};
3545
3546template <class _CharT>
3547locale::id
3548messages<_CharT>::id;
3549
3550template <class _CharT>
3551typename messages<_CharT>::catalog
3552messages<_CharT>::do_open(const basic_string<char>& __nm, const locale&) const
3553{
Ed Schouten118b6032015-03-11 16:39:36 +00003554#ifdef _LIBCPP_HAS_CATOPEN
Howard Hinnant8c2bf6b2011-10-11 16:00:46 +00003555 catalog __cat = (catalog)catopen(__nm.c_str(), NL_CAT_LOCALE);
Howard Hinnant2862aeb2011-02-25 00:51:08 +00003556 if (__cat != -1)
3557 __cat = static_cast<catalog>((static_cast<size_t>(__cat) >> 1));
3558 return __cat;
Ed Schouten118b6032015-03-11 16:39:36 +00003559#else // !_LIBCPP_HAS_CATOPEN
Petr Hosek399c5112019-01-13 22:15:37 +00003560 _LIBCPP_UNUSED_VAR(__nm);
Ed Schouten118b6032015-03-11 16:39:36 +00003561 return -1;
3562#endif // _LIBCPP_HAS_CATOPEN
Howard Hinnantc51e1022010-05-11 19:42:16 +00003563}
3564
3565template <class _CharT>
3566typename messages<_CharT>::string_type
3567messages<_CharT>::do_get(catalog __c, int __set, int __msgid,
3568 const string_type& __dflt) const
3569{
Ed Schouten118b6032015-03-11 16:39:36 +00003570#ifdef _LIBCPP_HAS_CATOPEN
Howard Hinnantc51e1022010-05-11 19:42:16 +00003571 string __ndflt;
3572 __narrow_to_utf8<sizeof(char_type)*__CHAR_BIT__>()(back_inserter(__ndflt),
3573 __dflt.c_str(),
3574 __dflt.c_str() + __dflt.size());
Howard Hinnant2862aeb2011-02-25 00:51:08 +00003575 if (__c != -1)
3576 __c <<= 1;
Howard Hinnant8c2bf6b2011-10-11 16:00:46 +00003577 nl_catd __cat = (nl_catd)__c;
Howard Hinnant2862aeb2011-02-25 00:51:08 +00003578 char* __n = catgets(__cat, __set, __msgid, __ndflt.c_str());
Howard Hinnantc51e1022010-05-11 19:42:16 +00003579 string_type __w;
3580 __widen_from_utf8<sizeof(char_type)*__CHAR_BIT__>()(back_inserter(__w),
Arthur O'Dwyer22236632020-12-07 21:50:15 -05003581 __n, __n + _VSTD::strlen(__n));
Howard Hinnantc51e1022010-05-11 19:42:16 +00003582 return __w;
Ed Schouten118b6032015-03-11 16:39:36 +00003583#else // !_LIBCPP_HAS_CATOPEN
Petr Hosek399c5112019-01-13 22:15:37 +00003584 _LIBCPP_UNUSED_VAR(__c);
3585 _LIBCPP_UNUSED_VAR(__set);
3586 _LIBCPP_UNUSED_VAR(__msgid);
Ed Schouten118b6032015-03-11 16:39:36 +00003587 return __dflt;
3588#endif // _LIBCPP_HAS_CATOPEN
Howard Hinnantc51e1022010-05-11 19:42:16 +00003589}
3590
3591template <class _CharT>
3592void
3593messages<_CharT>::do_close(catalog __c) const
3594{
Ed Schouten118b6032015-03-11 16:39:36 +00003595#ifdef _LIBCPP_HAS_CATOPEN
Howard Hinnant2862aeb2011-02-25 00:51:08 +00003596 if (__c != -1)
3597 __c <<= 1;
Howard Hinnant8c2bf6b2011-10-11 16:00:46 +00003598 nl_catd __cat = (nl_catd)__c;
Howard Hinnant2862aeb2011-02-25 00:51:08 +00003599 catclose(__cat);
Petr Hosek399c5112019-01-13 22:15:37 +00003600#else // !_LIBCPP_HAS_CATOPEN
3601 _LIBCPP_UNUSED_VAR(__c);
Ed Schouten118b6032015-03-11 16:39:36 +00003602#endif // _LIBCPP_HAS_CATOPEN
Howard Hinnantc51e1022010-05-11 19:42:16 +00003603}
3604
Louis Dionneb5ae3a72020-10-02 14:29:48 -04003605_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS messages<char>)
3606_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS messages<wchar_t>)
Howard Hinnantc51e1022010-05-11 19:42:16 +00003607
3608template <class _CharT>
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +00003609class _LIBCPP_TEMPLATE_VIS messages_byname
Howard Hinnantc51e1022010-05-11 19:42:16 +00003610 : public messages<_CharT>
3611{
3612public:
3613 typedef messages_base::catalog catalog;
3614 typedef basic_string<_CharT> string_type;
3615
Louis Dionne16fe2952018-07-11 23:14:33 +00003616 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00003617 explicit messages_byname(const char*, size_t __refs = 0)
3618 : messages<_CharT>(__refs) {}
3619
Louis Dionne16fe2952018-07-11 23:14:33 +00003620 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00003621 explicit messages_byname(const string&, size_t __refs = 0)
3622 : messages<_CharT>(__refs) {}
3623
3624protected:
Louis Dionne16fe2952018-07-11 23:14:33 +00003625 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00003626 ~messages_byname() {}
3627};
3628
Louis Dionneb5ae3a72020-10-02 14:29:48 -04003629_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS messages_byname<char>)
3630_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS messages_byname<wchar_t>)
Howard Hinnantc51e1022010-05-11 19:42:16 +00003631
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003632template<class _Codecvt, class _Elem = wchar_t,
3633 class _Wide_alloc = allocator<_Elem>,
3634 class _Byte_alloc = allocator<char> >
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +00003635class _LIBCPP_TEMPLATE_VIS wstring_convert
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003636{
3637public:
3638 typedef basic_string<char, char_traits<char>, _Byte_alloc> byte_string;
3639 typedef basic_string<_Elem, char_traits<_Elem>, _Wide_alloc> wide_string;
3640 typedef typename _Codecvt::state_type state_type;
3641 typedef typename wide_string::traits_type::int_type int_type;
3642
3643private:
3644 byte_string __byte_err_string_;
3645 wide_string __wide_err_string_;
3646 _Codecvt* __cvtptr_;
3647 state_type __cvtstate_;
3648 size_t __cvtcount_;
3649
3650 wstring_convert(const wstring_convert& __wc);
3651 wstring_convert& operator=(const wstring_convert& __wc);
3652public:
Louis Dionne16fe2952018-07-11 23:14:33 +00003653 _LIBCPP_INLINE_VISIBILITY
Marshall Clowccaa0fb2013-08-27 20:18:59 +00003654 _LIBCPP_EXPLICIT_AFTER_CXX11 wstring_convert(_Codecvt* __pcvt = new _Codecvt);
Louis Dionne16fe2952018-07-11 23:14:33 +00003655 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003656 wstring_convert(_Codecvt* __pcvt, state_type __state);
Marshall Clowccaa0fb2013-08-27 20:18:59 +00003657 _LIBCPP_EXPLICIT_AFTER_CXX11 wstring_convert(const byte_string& __byte_err,
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003658 const wide_string& __wide_err = wide_string());
Eric Fiselierf07d88c2017-04-19 01:34:08 +00003659#ifndef _LIBCPP_CXX03_LANG
Louis Dionne16fe2952018-07-11 23:14:33 +00003660 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003661 wstring_convert(wstring_convert&& __wc);
3662#endif
3663 ~wstring_convert();
3664
Louis Dionne16fe2952018-07-11 23:14:33 +00003665 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003666 wide_string from_bytes(char __byte)
3667 {return from_bytes(&__byte, &__byte+1);}
Louis Dionne16fe2952018-07-11 23:14:33 +00003668 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003669 wide_string from_bytes(const char* __ptr)
3670 {return from_bytes(__ptr, __ptr + char_traits<char>::length(__ptr));}
Louis Dionne16fe2952018-07-11 23:14:33 +00003671 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003672 wide_string from_bytes(const byte_string& __str)
3673 {return from_bytes(__str.data(), __str.data() + __str.size());}
3674 wide_string from_bytes(const char* __first, const char* __last);
3675
Louis Dionne16fe2952018-07-11 23:14:33 +00003676 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003677 byte_string to_bytes(_Elem __wchar)
3678 {return to_bytes(&__wchar, &__wchar+1);}
Louis Dionne16fe2952018-07-11 23:14:33 +00003679 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003680 byte_string to_bytes(const _Elem* __wptr)
3681 {return to_bytes(__wptr, __wptr + char_traits<_Elem>::length(__wptr));}
Louis Dionne16fe2952018-07-11 23:14:33 +00003682 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003683 byte_string to_bytes(const wide_string& __wstr)
3684 {return to_bytes(__wstr.data(), __wstr.data() + __wstr.size());}
3685 byte_string to_bytes(const _Elem* __first, const _Elem* __last);
3686
Louis Dionne16fe2952018-07-11 23:14:33 +00003687 _LIBCPP_INLINE_VISIBILITY
Marshall Clowccaa0fb2013-08-27 20:18:59 +00003688 size_t converted() const _NOEXCEPT {return __cvtcount_;}
Louis Dionne16fe2952018-07-11 23:14:33 +00003689 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003690 state_type state() const {return __cvtstate_;}
3691};
3692
3693template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Evgeniy Stepanov2fb1cb62015-11-07 01:22:13 +00003694inline
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003695wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3696 wstring_convert(_Codecvt* __pcvt)
3697 : __cvtptr_(__pcvt), __cvtstate_(), __cvtcount_(0)
3698{
3699}
3700
3701template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Evgeniy Stepanov2fb1cb62015-11-07 01:22:13 +00003702inline
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003703wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3704 wstring_convert(_Codecvt* __pcvt, state_type __state)
3705 : __cvtptr_(__pcvt), __cvtstate_(__state), __cvtcount_(0)
3706{
3707}
3708
3709template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3710wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3711 wstring_convert(const byte_string& __byte_err, const wide_string& __wide_err)
3712 : __byte_err_string_(__byte_err), __wide_err_string_(__wide_err),
3713 __cvtstate_(), __cvtcount_(0)
3714{
3715 __cvtptr_ = new _Codecvt;
3716}
3717
Eric Fiselierf07d88c2017-04-19 01:34:08 +00003718#ifndef _LIBCPP_CXX03_LANG
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003719
3720template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Evgeniy Stepanov2fb1cb62015-11-07 01:22:13 +00003721inline
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003722wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3723 wstring_convert(wstring_convert&& __wc)
Howard Hinnantb1ad5a82011-06-30 21:18:19 +00003724 : __byte_err_string_(_VSTD::move(__wc.__byte_err_string_)),
3725 __wide_err_string_(_VSTD::move(__wc.__wide_err_string_)),
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003726 __cvtptr_(__wc.__cvtptr_),
Eric Fiselier35c67232016-06-26 22:56:26 +00003727 __cvtstate_(__wc.__cvtstate_), __cvtcount_(__wc.__cvtcount_)
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003728{
3729 __wc.__cvtptr_ = nullptr;
3730}
3731
Eric Fiselierf07d88c2017-04-19 01:34:08 +00003732#endif // _LIBCPP_CXX03_LANG
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003733
3734template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3735wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::~wstring_convert()
3736{
3737 delete __cvtptr_;
3738}
3739
3740template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3741typename wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::wide_string
3742wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3743 from_bytes(const char* __frm, const char* __frm_end)
3744{
3745 __cvtcount_ = 0;
3746 if (__cvtptr_ != nullptr)
3747 {
3748 wide_string __ws(2*(__frm_end - __frm), _Elem());
Howard Hinnant16d54f22012-07-12 18:07:41 +00003749 if (__frm != __frm_end)
3750 __ws.resize(__ws.capacity());
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003751 codecvt_base::result __r = codecvt_base::ok;
3752 state_type __st = __cvtstate_;
3753 if (__frm != __frm_end)
3754 {
3755 _Elem* __to = &__ws[0];
3756 _Elem* __to_end = __to + __ws.size();
3757 const char* __frm_nxt;
3758 do
3759 {
3760 _Elem* __to_nxt;
3761 __r = __cvtptr_->in(__st, __frm, __frm_end, __frm_nxt,
3762 __to, __to_end, __to_nxt);
3763 __cvtcount_ += __frm_nxt - __frm;
3764 if (__frm_nxt == __frm)
3765 {
3766 __r = codecvt_base::error;
3767 }
3768 else if (__r == codecvt_base::noconv)
3769 {
3770 __ws.resize(__to - &__ws[0]);
3771 // This only gets executed if _Elem is char
3772 __ws.append((const _Elem*)__frm, (const _Elem*)__frm_end);
3773 __frm = __frm_nxt;
3774 __r = codecvt_base::ok;
3775 }
3776 else if (__r == codecvt_base::ok)
3777 {
3778 __ws.resize(__to_nxt - &__ws[0]);
3779 __frm = __frm_nxt;
3780 }
3781 else if (__r == codecvt_base::partial)
3782 {
3783 ptrdiff_t __s = __to_nxt - &__ws[0];
3784 __ws.resize(2 * __s);
3785 __to = &__ws[0] + __s;
3786 __to_end = &__ws[0] + __ws.size();
3787 __frm = __frm_nxt;
3788 }
3789 } while (__r == codecvt_base::partial && __frm_nxt < __frm_end);
3790 }
3791 if (__r == codecvt_base::ok)
3792 return __ws;
3793 }
Marshall Clow8fea1612016-08-25 15:09:01 +00003794
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003795 if (__wide_err_string_.empty())
Marshall Clow8fea1612016-08-25 15:09:01 +00003796 __throw_range_error("wstring_convert: from_bytes error");
3797
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003798 return __wide_err_string_;
3799}
3800
3801template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3802typename wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::byte_string
3803wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3804 to_bytes(const _Elem* __frm, const _Elem* __frm_end)
3805{
3806 __cvtcount_ = 0;
3807 if (__cvtptr_ != nullptr)
3808 {
3809 byte_string __bs(2*(__frm_end - __frm), char());
Howard Hinnant16d54f22012-07-12 18:07:41 +00003810 if (__frm != __frm_end)
3811 __bs.resize(__bs.capacity());
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003812 codecvt_base::result __r = codecvt_base::ok;
3813 state_type __st = __cvtstate_;
3814 if (__frm != __frm_end)
3815 {
3816 char* __to = &__bs[0];
3817 char* __to_end = __to + __bs.size();
3818 const _Elem* __frm_nxt;
3819 do
3820 {
3821 char* __to_nxt;
3822 __r = __cvtptr_->out(__st, __frm, __frm_end, __frm_nxt,
3823 __to, __to_end, __to_nxt);
3824 __cvtcount_ += __frm_nxt - __frm;
3825 if (__frm_nxt == __frm)
3826 {
3827 __r = codecvt_base::error;
3828 }
3829 else if (__r == codecvt_base::noconv)
3830 {
3831 __bs.resize(__to - &__bs[0]);
3832 // This only gets executed if _Elem is char
3833 __bs.append((const char*)__frm, (const char*)__frm_end);
3834 __frm = __frm_nxt;
3835 __r = codecvt_base::ok;
3836 }
3837 else if (__r == codecvt_base::ok)
3838 {
3839 __bs.resize(__to_nxt - &__bs[0]);
3840 __frm = __frm_nxt;
3841 }
3842 else if (__r == codecvt_base::partial)
3843 {
3844 ptrdiff_t __s = __to_nxt - &__bs[0];
3845 __bs.resize(2 * __s);
3846 __to = &__bs[0] + __s;
3847 __to_end = &__bs[0] + __bs.size();
3848 __frm = __frm_nxt;
3849 }
3850 } while (__r == codecvt_base::partial && __frm_nxt < __frm_end);
3851 }
3852 if (__r == codecvt_base::ok)
3853 {
3854 size_t __s = __bs.size();
3855 __bs.resize(__bs.capacity());
3856 char* __to = &__bs[0] + __s;
3857 char* __to_end = __to + __bs.size();
3858 do
3859 {
3860 char* __to_nxt;
3861 __r = __cvtptr_->unshift(__st, __to, __to_end, __to_nxt);
3862 if (__r == codecvt_base::noconv)
3863 {
3864 __bs.resize(__to - &__bs[0]);
3865 __r = codecvt_base::ok;
3866 }
3867 else if (__r == codecvt_base::ok)
3868 {
3869 __bs.resize(__to_nxt - &__bs[0]);
3870 }
3871 else if (__r == codecvt_base::partial)
3872 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003873 ptrdiff_t __sp = __to_nxt - &__bs[0];
3874 __bs.resize(2 * __sp);
3875 __to = &__bs[0] + __sp;
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003876 __to_end = &__bs[0] + __bs.size();
3877 }
3878 } while (__r == codecvt_base::partial);
3879 if (__r == codecvt_base::ok)
3880 return __bs;
3881 }
3882 }
Marshall Clow8fea1612016-08-25 15:09:01 +00003883
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003884 if (__byte_err_string_.empty())
Marshall Clow8fea1612016-08-25 15:09:01 +00003885 __throw_range_error("wstring_convert: to_bytes error");
3886
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003887 return __byte_err_string_;
3888}
3889
3890template <class _Codecvt, class _Elem = wchar_t, class _Tr = char_traits<_Elem> >
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +00003891class _LIBCPP_TEMPLATE_VIS wbuffer_convert
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003892 : public basic_streambuf<_Elem, _Tr>
3893{
3894public:
3895 // types:
3896 typedef _Elem char_type;
3897 typedef _Tr traits_type;
3898 typedef typename traits_type::int_type int_type;
3899 typedef typename traits_type::pos_type pos_type;
3900 typedef typename traits_type::off_type off_type;
3901 typedef typename _Codecvt::state_type state_type;
3902
3903private:
Howard Hinnant0ac182a2010-06-01 20:09:18 +00003904 char* __extbuf_;
3905 const char* __extbufnext_;
3906 const char* __extbufend_;
3907 char __extbuf_min_[8];
3908 size_t __ebs_;
3909 char_type* __intbuf_;
3910 size_t __ibs_;
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003911 streambuf* __bufptr_;
Howard Hinnant0ac182a2010-06-01 20:09:18 +00003912 _Codecvt* __cv_;
3913 state_type __st_;
3914 ios_base::openmode __cm_;
3915 bool __owns_eb_;
3916 bool __owns_ib_;
3917 bool __always_noconv_;
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003918
Howard Hinnant0ac182a2010-06-01 20:09:18 +00003919 wbuffer_convert(const wbuffer_convert&);
3920 wbuffer_convert& operator=(const wbuffer_convert&);
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003921public:
Bruce Mitchener170d8972020-11-24 12:53:53 -05003922 _LIBCPP_EXPLICIT_AFTER_CXX11 wbuffer_convert(streambuf* __bytebuf = nullptr,
Marshall Clowccaa0fb2013-08-27 20:18:59 +00003923 _Codecvt* __pcvt = new _Codecvt, state_type __state = state_type());
Howard Hinnant0ac182a2010-06-01 20:09:18 +00003924 ~wbuffer_convert();
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003925
Howard Hinnant756c69b2010-09-22 16:48:34 +00003926 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003927 streambuf* rdbuf() const {return __bufptr_;}
Howard Hinnant756c69b2010-09-22 16:48:34 +00003928 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003929 streambuf* rdbuf(streambuf* __bytebuf)
3930 {
3931 streambuf* __r = __bufptr_;
3932 __bufptr_ = __bytebuf;
3933 return __r;
3934 }
3935
Howard Hinnant756c69b2010-09-22 16:48:34 +00003936 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant0ac182a2010-06-01 20:09:18 +00003937 state_type state() const {return __st_;}
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003938
3939protected:
Howard Hinnant0ac182a2010-06-01 20:09:18 +00003940 virtual int_type underflow();
3941 virtual int_type pbackfail(int_type __c = traits_type::eof());
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003942 virtual int_type overflow (int_type __c = traits_type::eof());
Howard Hinnant0ac182a2010-06-01 20:09:18 +00003943 virtual basic_streambuf<char_type, traits_type>* setbuf(char_type* __s,
3944 streamsize __n);
3945 virtual pos_type seekoff(off_type __off, ios_base::seekdir __way,
3946 ios_base::openmode __wch = ios_base::in | ios_base::out);
3947 virtual pos_type seekpos(pos_type __sp,
3948 ios_base::openmode __wch = ios_base::in | ios_base::out);
3949 virtual int sync();
3950
3951private:
3952 bool __read_mode();
3953 void __write_mode();
3954 wbuffer_convert* __close();
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003955};
3956
3957template <class _Codecvt, class _Elem, class _Tr>
Howard Hinnant0ac182a2010-06-01 20:09:18 +00003958wbuffer_convert<_Codecvt, _Elem, _Tr>::
3959 wbuffer_convert(streambuf* __bytebuf, _Codecvt* __pcvt, state_type __state)
Bruce Mitchener170d8972020-11-24 12:53:53 -05003960 : __extbuf_(nullptr),
3961 __extbufnext_(nullptr),
3962 __extbufend_(nullptr),
Howard Hinnant0ac182a2010-06-01 20:09:18 +00003963 __ebs_(0),
3964 __intbuf_(0),
3965 __ibs_(0),
3966 __bufptr_(__bytebuf),
3967 __cv_(__pcvt),
3968 __st_(__state),
3969 __cm_(0),
3970 __owns_eb_(false),
3971 __owns_ib_(false),
3972 __always_noconv_(__cv_ ? __cv_->always_noconv() : false)
3973{
3974 setbuf(0, 4096);
3975}
3976
3977template <class _Codecvt, class _Elem, class _Tr>
3978wbuffer_convert<_Codecvt, _Elem, _Tr>::~wbuffer_convert()
3979{
3980 __close();
3981 delete __cv_;
3982 if (__owns_eb_)
3983 delete [] __extbuf_;
3984 if (__owns_ib_)
3985 delete [] __intbuf_;
3986}
3987
3988template <class _Codecvt, class _Elem, class _Tr>
3989typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
3990wbuffer_convert<_Codecvt, _Elem, _Tr>::underflow()
3991{
3992 if (__cv_ == 0 || __bufptr_ == 0)
3993 return traits_type::eof();
3994 bool __initial = __read_mode();
3995 char_type __1buf;
3996 if (this->gptr() == 0)
3997 this->setg(&__1buf, &__1buf+1, &__1buf+1);
3998 const size_t __unget_sz = __initial ? 0 : min<size_t>((this->egptr() - this->eback()) / 2, 4);
3999 int_type __c = traits_type::eof();
4000 if (this->gptr() == this->egptr())
4001 {
Arthur O'Dwyer22236632020-12-07 21:50:15 -05004002 _VSTD::memmove(this->eback(), this->egptr() - __unget_sz, __unget_sz * sizeof(char_type));
Howard Hinnant0ac182a2010-06-01 20:09:18 +00004003 if (__always_noconv_)
4004 {
4005 streamsize __nmemb = static_cast<streamsize>(this->egptr() - this->eback() - __unget_sz);
4006 __nmemb = __bufptr_->sgetn((char*)this->eback() + __unget_sz, __nmemb);
4007 if (__nmemb != 0)
4008 {
4009 this->setg(this->eback(),
4010 this->eback() + __unget_sz,
4011 this->eback() + __unget_sz + __nmemb);
4012 __c = *this->gptr();
4013 }
4014 }
4015 else
4016 {
Eric Fiselier98e428d2016-06-19 06:58:22 +00004017 _LIBCPP_ASSERT(!(__extbufnext_ == NULL && (__extbufend_ != __extbufnext_)), "underflow moving from NULL" );
4018 if (__extbufend_ != __extbufnext_)
Arthur O'Dwyer22236632020-12-07 21:50:15 -05004019 _VSTD::memmove(__extbuf_, __extbufnext_, __extbufend_ - __extbufnext_);
Howard Hinnant0ac182a2010-06-01 20:09:18 +00004020 __extbufnext_ = __extbuf_ + (__extbufend_ - __extbufnext_);
4021 __extbufend_ = __extbuf_ + (__extbuf_ == __extbuf_min_ ? sizeof(__extbuf_min_) : __ebs_);
Howard Hinnantb1ad5a82011-06-30 21:18:19 +00004022 streamsize __nmemb = _VSTD::min(static_cast<streamsize>(this->egptr() - this->eback() - __unget_sz),
Howard Hinnant0ac182a2010-06-01 20:09:18 +00004023 static_cast<streamsize>(__extbufend_ - __extbufnext_));
4024 codecvt_base::result __r;
Eric Fiselier6003c772016-12-23 23:37:52 +00004025 // FIXME: Do we ever need to restore the state here?
4026 //state_type __svs = __st_;
Howard Hinnant0ac182a2010-06-01 20:09:18 +00004027 streamsize __nr = __bufptr_->sgetn(const_cast<char*>(__extbufnext_), __nmemb);
4028 if (__nr != 0)
4029 {
4030 __extbufend_ = __extbufnext_ + __nr;
4031 char_type* __inext;
4032 __r = __cv_->in(__st_, __extbuf_, __extbufend_, __extbufnext_,
4033 this->eback() + __unget_sz,
4034 this->egptr(), __inext);
4035 if (__r == codecvt_base::noconv)
4036 {
Louis Dionne173f29e2019-05-29 16:01:36 +00004037 this->setg((char_type*)__extbuf_, (char_type*)__extbuf_,
Marshall Clowbeda7142017-06-14 20:00:36 +00004038 (char_type*) const_cast<char *>(__extbufend_));
Howard Hinnant0ac182a2010-06-01 20:09:18 +00004039 __c = *this->gptr();
4040 }
4041 else if (__inext != this->eback() + __unget_sz)
4042 {
4043 this->setg(this->eback(), this->eback() + __unget_sz, __inext);
4044 __c = *this->gptr();
4045 }
4046 }
4047 }
4048 }
4049 else
4050 __c = *this->gptr();
4051 if (this->eback() == &__1buf)
4052 this->setg(0, 0, 0);
4053 return __c;
4054}
4055
4056template <class _Codecvt, class _Elem, class _Tr>
4057typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
4058wbuffer_convert<_Codecvt, _Elem, _Tr>::pbackfail(int_type __c)
4059{
4060 if (__cv_ != 0 && __bufptr_ != 0 && this->eback() < this->gptr())
4061 {
4062 if (traits_type::eq_int_type(__c, traits_type::eof()))
4063 {
4064 this->gbump(-1);
4065 return traits_type::not_eof(__c);
4066 }
4067 if (traits_type::eq(traits_type::to_char_type(__c), this->gptr()[-1]))
4068 {
4069 this->gbump(-1);
4070 *this->gptr() = traits_type::to_char_type(__c);
4071 return __c;
4072 }
4073 }
4074 return traits_type::eof();
4075}
4076
4077template <class _Codecvt, class _Elem, class _Tr>
Howard Hinnant9dd7e892010-05-31 20:58:54 +00004078typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
4079wbuffer_convert<_Codecvt, _Elem, _Tr>::overflow(int_type __c)
4080{
Howard Hinnant0ac182a2010-06-01 20:09:18 +00004081 if (__cv_ == 0 || __bufptr_ == 0)
4082 return traits_type::eof();
4083 __write_mode();
4084 char_type __1buf;
4085 char_type* __pb_save = this->pbase();
4086 char_type* __epb_save = this->epptr();
4087 if (!traits_type::eq_int_type(__c, traits_type::eof()))
4088 {
4089 if (this->pptr() == 0)
4090 this->setp(&__1buf, &__1buf+1);
4091 *this->pptr() = traits_type::to_char_type(__c);
4092 this->pbump(1);
4093 }
4094 if (this->pptr() != this->pbase())
4095 {
4096 if (__always_noconv_)
4097 {
4098 streamsize __nmemb = static_cast<streamsize>(this->pptr() - this->pbase());
4099 if (__bufptr_->sputn((const char*)this->pbase(), __nmemb) != __nmemb)
4100 return traits_type::eof();
4101 }
4102 else
4103 {
4104 char* __extbe = __extbuf_;
4105 codecvt_base::result __r;
4106 do
4107 {
4108 const char_type* __e;
4109 __r = __cv_->out(__st_, this->pbase(), this->pptr(), __e,
4110 __extbuf_, __extbuf_ + __ebs_, __extbe);
4111 if (__e == this->pbase())
4112 return traits_type::eof();
4113 if (__r == codecvt_base::noconv)
4114 {
4115 streamsize __nmemb = static_cast<size_t>(this->pptr() - this->pbase());
4116 if (__bufptr_->sputn((const char*)this->pbase(), __nmemb) != __nmemb)
4117 return traits_type::eof();
4118 }
4119 else if (__r == codecvt_base::ok || __r == codecvt_base::partial)
4120 {
4121 streamsize __nmemb = static_cast<size_t>(__extbe - __extbuf_);
4122 if (__bufptr_->sputn(__extbuf_, __nmemb) != __nmemb)
4123 return traits_type::eof();
4124 if (__r == codecvt_base::partial)
4125 {
Marshall Clowbeda7142017-06-14 20:00:36 +00004126 this->setp(const_cast<char_type *>(__e), this->pptr());
Marshall Clow33932622017-09-12 15:00:43 +00004127 this->__pbump(this->epptr() - this->pbase());
Howard Hinnant0ac182a2010-06-01 20:09:18 +00004128 }
4129 }
4130 else
4131 return traits_type::eof();
4132 } while (__r == codecvt_base::partial);
4133 }
4134 this->setp(__pb_save, __epb_save);
4135 }
4136 return traits_type::not_eof(__c);
4137}
4138
4139template <class _Codecvt, class _Elem, class _Tr>
4140basic_streambuf<_Elem, _Tr>*
4141wbuffer_convert<_Codecvt, _Elem, _Tr>::setbuf(char_type* __s, streamsize __n)
4142{
4143 this->setg(0, 0, 0);
4144 this->setp(0, 0);
4145 if (__owns_eb_)
4146 delete [] __extbuf_;
4147 if (__owns_ib_)
4148 delete [] __intbuf_;
4149 __ebs_ = __n;
4150 if (__ebs_ > sizeof(__extbuf_min_))
4151 {
4152 if (__always_noconv_ && __s)
4153 {
4154 __extbuf_ = (char*)__s;
4155 __owns_eb_ = false;
4156 }
4157 else
4158 {
4159 __extbuf_ = new char[__ebs_];
4160 __owns_eb_ = true;
4161 }
4162 }
4163 else
4164 {
4165 __extbuf_ = __extbuf_min_;
4166 __ebs_ = sizeof(__extbuf_min_);
4167 __owns_eb_ = false;
4168 }
4169 if (!__always_noconv_)
4170 {
4171 __ibs_ = max<streamsize>(__n, sizeof(__extbuf_min_));
4172 if (__s && __ibs_ >= sizeof(__extbuf_min_))
4173 {
4174 __intbuf_ = __s;
4175 __owns_ib_ = false;
4176 }
4177 else
4178 {
4179 __intbuf_ = new char_type[__ibs_];
4180 __owns_ib_ = true;
4181 }
4182 }
4183 else
4184 {
4185 __ibs_ = 0;
4186 __intbuf_ = 0;
4187 __owns_ib_ = false;
4188 }
4189 return this;
4190}
4191
4192template <class _Codecvt, class _Elem, class _Tr>
4193typename wbuffer_convert<_Codecvt, _Elem, _Tr>::pos_type
4194wbuffer_convert<_Codecvt, _Elem, _Tr>::seekoff(off_type __off, ios_base::seekdir __way,
4195 ios_base::openmode __om)
4196{
4197 int __width = __cv_->encoding();
4198 if (__cv_ == 0 || __bufptr_ == 0 || (__width <= 0 && __off != 0) || sync())
4199 return pos_type(off_type(-1));
Marshall Clowc2a72762015-08-27 14:37:22 +00004200 // __width > 0 || __off == 0, now check __way
4201 if (__way != ios_base::beg && __way != ios_base::cur && __way != ios_base::end)
Howard Hinnant0ac182a2010-06-01 20:09:18 +00004202 return pos_type(off_type(-1));
Howard Hinnant0ac182a2010-06-01 20:09:18 +00004203 pos_type __r = __bufptr_->pubseekoff(__width * __off, __way, __om);
4204 __r.state(__st_);
4205 return __r;
4206}
4207
4208template <class _Codecvt, class _Elem, class _Tr>
4209typename wbuffer_convert<_Codecvt, _Elem, _Tr>::pos_type
4210wbuffer_convert<_Codecvt, _Elem, _Tr>::seekpos(pos_type __sp, ios_base::openmode __wch)
4211{
4212 if (__cv_ == 0 || __bufptr_ == 0 || sync())
4213 return pos_type(off_type(-1));
4214 if (__bufptr_->pubseekpos(__sp, __wch) == pos_type(off_type(-1)))
4215 return pos_type(off_type(-1));
4216 return __sp;
4217}
4218
4219template <class _Codecvt, class _Elem, class _Tr>
4220int
4221wbuffer_convert<_Codecvt, _Elem, _Tr>::sync()
4222{
4223 if (__cv_ == 0 || __bufptr_ == 0)
4224 return 0;
4225 if (__cm_ & ios_base::out)
4226 {
4227 if (this->pptr() != this->pbase())
4228 if (overflow() == traits_type::eof())
4229 return -1;
4230 codecvt_base::result __r;
4231 do
4232 {
4233 char* __extbe;
4234 __r = __cv_->unshift(__st_, __extbuf_, __extbuf_ + __ebs_, __extbe);
4235 streamsize __nmemb = static_cast<streamsize>(__extbe - __extbuf_);
4236 if (__bufptr_->sputn(__extbuf_, __nmemb) != __nmemb)
4237 return -1;
4238 } while (__r == codecvt_base::partial);
4239 if (__r == codecvt_base::error)
4240 return -1;
4241 if (__bufptr_->pubsync())
4242 return -1;
4243 }
4244 else if (__cm_ & ios_base::in)
4245 {
4246 off_type __c;
4247 if (__always_noconv_)
4248 __c = this->egptr() - this->gptr();
4249 else
4250 {
4251 int __width = __cv_->encoding();
4252 __c = __extbufend_ - __extbufnext_;
4253 if (__width > 0)
4254 __c += __width * (this->egptr() - this->gptr());
4255 else
4256 {
4257 if (this->gptr() != this->egptr())
4258 {
4259 reverse(this->gptr(), this->egptr());
4260 codecvt_base::result __r;
4261 const char_type* __e = this->gptr();
4262 char* __extbe;
4263 do
4264 {
4265 __r = __cv_->out(__st_, __e, this->egptr(), __e,
4266 __extbuf_, __extbuf_ + __ebs_, __extbe);
4267 switch (__r)
4268 {
4269 case codecvt_base::noconv:
4270 __c += this->egptr() - this->gptr();
4271 break;
4272 case codecvt_base::ok:
4273 case codecvt_base::partial:
4274 __c += __extbe - __extbuf_;
4275 break;
4276 default:
4277 return -1;
4278 }
4279 } while (__r == codecvt_base::partial);
4280 }
4281 }
4282 }
4283 if (__bufptr_->pubseekoff(-__c, ios_base::cur, __cm_) == pos_type(off_type(-1)))
4284 return -1;
4285 this->setg(0, 0, 0);
4286 __cm_ = 0;
4287 }
4288 return 0;
4289}
4290
4291template <class _Codecvt, class _Elem, class _Tr>
4292bool
4293wbuffer_convert<_Codecvt, _Elem, _Tr>::__read_mode()
4294{
4295 if (!(__cm_ & ios_base::in))
4296 {
4297 this->setp(0, 0);
4298 if (__always_noconv_)
4299 this->setg((char_type*)__extbuf_,
4300 (char_type*)__extbuf_ + __ebs_,
4301 (char_type*)__extbuf_ + __ebs_);
4302 else
4303 this->setg(__intbuf_, __intbuf_ + __ibs_, __intbuf_ + __ibs_);
4304 __cm_ = ios_base::in;
4305 return true;
4306 }
4307 return false;
4308}
4309
4310template <class _Codecvt, class _Elem, class _Tr>
4311void
4312wbuffer_convert<_Codecvt, _Elem, _Tr>::__write_mode()
4313{
4314 if (!(__cm_ & ios_base::out))
4315 {
4316 this->setg(0, 0, 0);
4317 if (__ebs_ > sizeof(__extbuf_min_))
4318 {
4319 if (__always_noconv_)
4320 this->setp((char_type*)__extbuf_,
4321 (char_type*)__extbuf_ + (__ebs_ - 1));
4322 else
4323 this->setp(__intbuf_, __intbuf_ + (__ibs_ - 1));
4324 }
4325 else
4326 this->setp(0, 0);
4327 __cm_ = ios_base::out;
4328 }
4329}
4330
4331template <class _Codecvt, class _Elem, class _Tr>
4332wbuffer_convert<_Codecvt, _Elem, _Tr>*
4333wbuffer_convert<_Codecvt, _Elem, _Tr>::__close()
4334{
Bruce Mitchener170d8972020-11-24 12:53:53 -05004335 wbuffer_convert* __rt = nullptr;
4336 if (__cv_ != nullptr && __bufptr_ != nullptr)
Howard Hinnant0ac182a2010-06-01 20:09:18 +00004337 {
4338 __rt = this;
4339 if ((__cm_ & ios_base::out) && sync())
Bruce Mitchener170d8972020-11-24 12:53:53 -05004340 __rt = nullptr;
Howard Hinnant0ac182a2010-06-01 20:09:18 +00004341 }
4342 return __rt;
Howard Hinnant9dd7e892010-05-31 20:58:54 +00004343}
4344
Howard Hinnantc51e1022010-05-11 19:42:16 +00004345_LIBCPP_END_NAMESPACE_STD
4346
Eric Fiselierf4433a32017-05-31 22:07:49 +00004347_LIBCPP_POP_MACROS
4348
Howard Hinnantc51e1022010-05-11 19:42:16 +00004349#endif // _LIBCPP_LOCALE