blob: 6363b8c637c041b184a6134a6e628b77232d762a [file] [log] [blame]
Howard Hinnantc51e1022010-05-11 19:42:16 +00001// -*- C++ -*-
2//===-------------------------- locale ------------------------------------===//
3//
Howard Hinnantc566dc32010-05-11 21:36:01 +00004// The LLVM Compiler Infrastructure
Howard Hinnantc51e1022010-05-11 19:42:16 +00005//
Howard Hinnantee11c312010-11-16 22:09:02 +00006// This file is dual licensed under the MIT and the University of Illinois Open
7// Source Licenses. See LICENSE.TXT for details.
Howard Hinnantc51e1022010-05-11 19:42:16 +00008//
9//===----------------------------------------------------------------------===//
10
11#ifndef _LIBCPP_LOCALE
12#define _LIBCPP_LOCALE
13
14/*
15 locale synopsis
16
17namespace std
18{
19
20class locale
21{
22public:
23 // types:
24 class facet;
25 class id;
26
27 typedef int category;
28 static const category // values assigned here are for exposition only
29 none = 0x000,
30 collate = 0x010,
31 ctype = 0x020,
32 monetary = 0x040,
33 numeric = 0x080,
34 time = 0x100,
35 messages = 0x200,
36 all = collate | ctype | monetary | numeric | time | messages;
37
38 // construct/copy/destroy:
Howard Hinnant7c9e5732011-05-31 15:34:58 +000039 locale() noexcept;
40 locale(const locale& other) noexcept;
Howard Hinnantc51e1022010-05-11 19:42:16 +000041 explicit locale(const char* std_name);
42 explicit locale(const string& std_name);
43 locale(const locale& other, const char* std_name, category);
44 locale(const locale& other, const string& std_name, category);
45 template <class Facet> locale(const locale& other, Facet* f);
46 locale(const locale& other, const locale& one, category);
47
Howard Hinnant7c9e5732011-05-31 15:34:58 +000048 ~locale(); // not virtual
Howard Hinnantc51e1022010-05-11 19:42:16 +000049
Howard Hinnant7c9e5732011-05-31 15:34:58 +000050 const locale& operator=(const locale& other) noexcept;
Howard Hinnantc51e1022010-05-11 19:42:16 +000051
52 template <class Facet> locale combine(const locale& other) const;
53
54 // locale operations:
55 basic_string<char> name() const;
56 bool operator==(const locale& other) const;
57 bool operator!=(const locale& other) const;
58 template <class charT, class Traits, class Allocator>
59 bool operator()(const basic_string<charT,Traits,Allocator>& s1,
60 const basic_string<charT,Traits,Allocator>& s2) const;
61
62 // global locale objects:
63 static locale global(const locale&);
64 static const locale& classic();
65};
66
67template <class Facet> const Facet& use_facet(const locale&);
Howard Hinnant7c9e5732011-05-31 15:34:58 +000068template <class Facet> bool has_facet(const locale&) noexcept;
Howard Hinnantc51e1022010-05-11 19:42:16 +000069
70// 22.3.3, convenience interfaces:
71template <class charT> bool isspace (charT c, const locale& loc);
72template <class charT> bool isprint (charT c, const locale& loc);
73template <class charT> bool iscntrl (charT c, const locale& loc);
74template <class charT> bool isupper (charT c, const locale& loc);
75template <class charT> bool islower (charT c, const locale& loc);
76template <class charT> bool isalpha (charT c, const locale& loc);
77template <class charT> bool isdigit (charT c, const locale& loc);
78template <class charT> bool ispunct (charT c, const locale& loc);
79template <class charT> bool isxdigit(charT c, const locale& loc);
80template <class charT> bool isalnum (charT c, const locale& loc);
81template <class charT> bool isgraph (charT c, const locale& loc);
82template <class charT> charT toupper(charT c, const locale& loc);
83template <class charT> charT tolower(charT c, const locale& loc);
Howard Hinnant9dd7e892010-05-31 20:58:54 +000084
85template<class Codecvt, class Elem = wchar_t,
86 class Wide_alloc = allocator<Elem>,
87 class Byte_alloc = allocator<char>>
88class wstring_convert
89{
90public:
91 typedef basic_string<char, char_traits<char>, Byte_alloc> byte_string;
92 typedef basic_string<Elem, char_traits<Elem>, Wide_alloc> wide_string;
93 typedef typename Codecvt::state_type state_type;
94 typedef typename wide_string::traits_type::int_type int_type;
95
Marshall Clowccaa0fb2013-08-27 20:18:59 +000096 explicit wstring_convert(Codecvt* pcvt = new Codecvt); // explicit in C++14
Howard Hinnant9dd7e892010-05-31 20:58:54 +000097 wstring_convert(Codecvt* pcvt, state_type state);
Marshall Clowccaa0fb2013-08-27 20:18:59 +000098 explicit wstring_convert(const byte_string& byte_err, // explicit in C++14
Howard Hinnant9dd7e892010-05-31 20:58:54 +000099 const wide_string& wide_err = wide_string());
Marshall Clowccaa0fb2013-08-27 20:18:59 +0000100 wstring_convert(const wstring_convert&) = delete; // C++14
101 wstring_convert & operator=(const wstring_convert &) = delete; // C++14
Howard Hinnant9dd7e892010-05-31 20:58:54 +0000102 ~wstring_convert();
103
104 wide_string from_bytes(char byte);
105 wide_string from_bytes(const char* ptr);
106 wide_string from_bytes(const byte_string& str);
107 wide_string from_bytes(const char* first, const char* last);
108
109 byte_string to_bytes(Elem wchar);
110 byte_string to_bytes(const Elem* wptr);
111 byte_string to_bytes(const wide_string& wstr);
112 byte_string to_bytes(const Elem* first, const Elem* last);
113
Marshall Clowccaa0fb2013-08-27 20:18:59 +0000114 size_t converted() const; // noexcept in C++14
Howard Hinnant9dd7e892010-05-31 20:58:54 +0000115 state_type state() const;
116};
117
Howard Hinnantc51e1022010-05-11 19:42:16 +0000118template <class Codecvt, class Elem = wchar_t, class Tr = char_traits<Elem>>
Howard Hinnant9dd7e892010-05-31 20:58:54 +0000119class wbuffer_convert
120 : public basic_streambuf<Elem, Tr>
121{
122public:
123 typedef typename Tr::state_type state_type;
124
Marshall Clowccaa0fb2013-08-27 20:18:59 +0000125 explicit wbuffer_convert(streambuf* bytebuf = 0, Codecvt* pcvt = new Codecvt,
126 state_type state = state_type()); // explicit in C++14
127 wbuffer_convert(const wbuffer_convert&) = delete; // C++14
128 wbuffer_convert & operator=(const wbuffer_convert &) = delete; // C++14
129 ~wbuffer_convert(); // C++14
130
Howard Hinnant9dd7e892010-05-31 20:58:54 +0000131 streambuf* rdbuf() const;
132 streambuf* rdbuf(streambuf* bytebuf);
133
134 state_type state() const;
135};
Howard Hinnantc51e1022010-05-11 19:42:16 +0000136
137// 22.4.1 and 22.4.1.3, ctype:
138class ctype_base;
139template <class charT> class ctype;
140template <> class ctype<char>; // specialization
141template <class charT> class ctype_byname;
142template <> class ctype_byname<char>; // specialization
143
144class codecvt_base;
145template <class internT, class externT, class stateT> class codecvt;
146template <class internT, class externT, class stateT> class codecvt_byname;
147
148// 22.4.2 and 22.4.3, numeric:
149template <class charT, class InputIterator> class num_get;
150template <class charT, class OutputIterator> class num_put;
151template <class charT> class numpunct;
152template <class charT> class numpunct_byname;
153
154// 22.4.4, col lation:
155template <class charT> class collate;
156template <class charT> class collate_byname;
157
158// 22.4.5, date and time:
159class time_base;
160template <class charT, class InputIterator> class time_get;
161template <class charT, class InputIterator> class time_get_byname;
162template <class charT, class OutputIterator> class time_put;
163template <class charT, class OutputIterator> class time_put_byname;
164
165// 22.4.6, money:
166class money_base;
167template <class charT, class InputIterator> class money_get;
168template <class charT, class OutputIterator> class money_put;
169template <class charT, bool Intl> class moneypunct;
170template <class charT, bool Intl> class moneypunct_byname;
171
172// 22.4.7, message retrieval:
173class messages_base;
174template <class charT> class messages;
175template <class charT> class messages_byname;
176
177} // std
178
179*/
180
181#include <__config>
182#include <__locale>
Eric Fiselier98e428d2016-06-19 06:58:22 +0000183#include <__debug>
Howard Hinnantc51e1022010-05-11 19:42:16 +0000184#include <algorithm>
185#include <memory>
186#include <ios>
187#include <streambuf>
188#include <iterator>
189#include <limits>
Marshall Clowdde4bfe2013-03-18 17:45:34 +0000190#ifndef __APPLE__
Howard Hinnant155c2af2010-05-24 17:49:41 +0000191#include <cstdarg>
192#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +0000193#include <cstdlib>
194#include <ctime>
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
Marshall Clowdde4bfe2013-03-18 17:45:34 +0000200#ifdef __APPLE__
Howard Hinnant48fd5d52012-11-14 21:17:15 +0000201#include <Availability.h>
202#endif
203
Ben Craig3756b922016-03-09 15:39:39 +0000204#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
205#include <__bsd_locale_defaults.h>
206#else
207#include <__bsd_locale_fallbacks.h>
208#endif
209
Eric Fiselierf4433a32017-05-31 22:07:49 +0000210#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
211#pragma GCC system_header
212#endif
213
214_LIBCPP_PUSH_MACROS
215#include <__undef_macros>
216
217
Howard Hinnantc51e1022010-05-11 19:42:16 +0000218_LIBCPP_BEGIN_NAMESPACE_STD
219
Marshall Clow82378c02013-03-18 19:34:07 +0000220#if defined(__APPLE__) || defined(__FreeBSD__)
Howard Hinnant1ab52da2011-09-28 21:05:01 +0000221# define _LIBCPP_GET_C_LOCALE 0
Ed Schoutenaa497c82015-03-10 09:35:22 +0000222#elif defined(__CloudABI__) || defined(__NetBSD__)
Joerg Sonnenberger153e4162013-05-17 21:17:34 +0000223# define _LIBCPP_GET_C_LOCALE LC_C_LOCALE
Howard Hinnant1ab52da2011-09-28 21:05:01 +0000224#else
225# define _LIBCPP_GET_C_LOCALE __cloc()
Howard Hinnantf312e3e2011-09-28 23:39:33 +0000226 // Get the C locale object
Howard Hinnanta37d3cf2013-08-12 18:38:34 +0000227 _LIBCPP_FUNC_VIS locale_t __cloc();
Howard Hinnantf312e3e2011-09-28 23:39:33 +0000228#define __cloc_defined
Howard Hinnant1ab52da2011-09-28 21:05:01 +0000229#endif
230
Howard Hinnantc51e1022010-05-11 19:42:16 +0000231// __scan_keyword
232// Scans [__b, __e) until a match is found in the basic_strings range
233// [__kb, __ke) or until it can be shown that there is no match in [__kb, __ke).
234// __b will be incremented (visibly), consuming CharT until a match is found
235// or proved to not exist. A keyword may be "", in which will match anything.
236// If one keyword is a prefix of another, and the next CharT in the input
237// might match another keyword, the algorithm will attempt to find the longest
238// matching keyword. If the longer matching keyword ends up not matching, then
239// no keyword match is found. If no keyword match is found, __ke is returned
240// and failbit is set in __err.
241// Else an iterator pointing to the matching keyword is found. If more than
242// one keyword matches, an iterator to the first matching keyword is returned.
Alp Tokerb8a95f52014-05-15 11:27:39 +0000243// If on exit __b == __e, eofbit is set in __err. If __case_sensitive is false,
Howard Hinnantc51e1022010-05-11 19:42:16 +0000244// __ct is used to force to lower case before comparing characters.
245// Examples:
246// Keywords: "a", "abb"
247// If the input is "a", the first keyword matches and eofbit is set.
248// If the input is "abc", no match is found and "ab" are consumed.
249template <class _InputIterator, class _ForwardIterator, class _Ctype>
250_LIBCPP_HIDDEN
251_ForwardIterator
252__scan_keyword(_InputIterator& __b, _InputIterator __e,
253 _ForwardIterator __kb, _ForwardIterator __ke,
254 const _Ctype& __ct, ios_base::iostate& __err,
255 bool __case_sensitive = true)
256{
257 typedef typename iterator_traits<_InputIterator>::value_type _CharT;
Howard Hinnant28b24882011-12-01 20:21:04 +0000258 size_t __nkw = static_cast<size_t>(_VSTD::distance(__kb, __ke));
Howard Hinnantc51e1022010-05-11 19:42:16 +0000259 const unsigned char __doesnt_match = '\0';
260 const unsigned char __might_match = '\1';
261 const unsigned char __does_match = '\2';
262 unsigned char __statbuf[100];
263 unsigned char* __status = __statbuf;
264 unique_ptr<unsigned char, void(*)(void*)> __stat_hold(0, free);
265 if (__nkw > sizeof(__statbuf))
266 {
267 __status = (unsigned char*)malloc(__nkw);
268 if (__status == 0)
269 __throw_bad_alloc();
270 __stat_hold.reset(__status);
271 }
272 size_t __n_might_match = __nkw; // At this point, any keyword might match
273 size_t __n_does_match = 0; // but none of them definitely do
274 // Initialize all statuses to __might_match, except for "" keywords are __does_match
275 unsigned char* __st = __status;
Eric Fiseliera09a3b42014-10-27 19:28:20 +0000276 for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, (void) ++__st)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000277 {
278 if (!__ky->empty())
279 *__st = __might_match;
280 else
281 {
282 *__st = __does_match;
283 --__n_might_match;
284 ++__n_does_match;
285 }
286 }
287 // While there might be a match, test keywords against the next CharT
288 for (size_t __indx = 0; __b != __e && __n_might_match > 0; ++__indx)
289 {
290 // Peek at the next CharT but don't consume it
291 _CharT __c = *__b;
292 if (!__case_sensitive)
293 __c = __ct.toupper(__c);
294 bool __consume = false;
295 // For each keyword which might match, see if the __indx character is __c
296 // If a match if found, consume __c
297 // If a match is found, and that is the last character in the keyword,
298 // then that keyword matches.
299 // If the keyword doesn't match this character, then change the keyword
300 // to doesn't match
301 __st = __status;
Eric Fiseliera09a3b42014-10-27 19:28:20 +0000302 for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, (void) ++__st)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000303 {
304 if (*__st == __might_match)
305 {
306 _CharT __kc = (*__ky)[__indx];
307 if (!__case_sensitive)
308 __kc = __ct.toupper(__kc);
309 if (__c == __kc)
310 {
311 __consume = true;
312 if (__ky->size() == __indx+1)
313 {
314 *__st = __does_match;
315 --__n_might_match;
316 ++__n_does_match;
317 }
318 }
319 else
320 {
321 *__st = __doesnt_match;
322 --__n_might_match;
323 }
324 }
325 }
326 // consume if we matched a character
327 if (__consume)
328 {
329 ++__b;
330 // If we consumed a character and there might be a matched keyword that
331 // was marked matched on a previous iteration, then such keywords
332 // which are now marked as not matching.
333 if (__n_might_match + __n_does_match > 1)
334 {
335 __st = __status;
Eric Fiseliera09a3b42014-10-27 19:28:20 +0000336 for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, (void) ++__st)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000337 {
338 if (*__st == __does_match && __ky->size() != __indx+1)
339 {
340 *__st = __doesnt_match;
341 --__n_does_match;
342 }
343 }
344 }
345 }
346 }
347 // We've exited the loop because we hit eof and/or we have no more "might matches".
348 if (__b == __e)
349 __err |= ios_base::eofbit;
350 // Return the first matching result
Eric Fiseliera09a3b42014-10-27 19:28:20 +0000351 for (__st = __status; __kb != __ke; ++__kb, (void) ++__st)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000352 if (*__st == __does_match)
353 break;
354 if (__kb == __ke)
355 __err |= ios_base::failbit;
356 return __kb;
357}
358
Howard Hinnanta37d3cf2013-08-12 18:38:34 +0000359struct _LIBCPP_TYPE_VIS __num_get_base
Howard Hinnantc51e1022010-05-11 19:42:16 +0000360{
361 static const int __num_get_buf_sz = 40;
362
363 static int __get_base(ios_base&);
364 static const char __src[33];
365};
366
Howard Hinnanta37d3cf2013-08-12 18:38:34 +0000367_LIBCPP_FUNC_VIS
Howard Hinnantc51e1022010-05-11 19:42:16 +0000368void __check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
369 ios_base::iostate& __err);
370
Howard Hinnantc51e1022010-05-11 19:42:16 +0000371template <class _CharT>
372struct __num_get
373 : protected __num_get_base
374{
375 static string __stage2_int_prep(ios_base& __iob, _CharT* __atoms, _CharT& __thousands_sep);
376 static string __stage2_float_prep(ios_base& __iob, _CharT* __atoms, _CharT& __decimal_point,
377 _CharT& __thousands_sep);
378 static int __stage2_int_loop(_CharT __ct, int __base, char* __a, char*& __a_end,
379 unsigned& __dc, _CharT __thousands_sep, const string& __grouping,
380 unsigned* __g, unsigned*& __g_end, _CharT* __atoms);
381 static int __stage2_float_loop(_CharT __ct, bool& __in_units, char& __exp,
382 char* __a, char*& __a_end,
383 _CharT __decimal_point, _CharT __thousands_sep,
384 const string& __grouping, unsigned* __g,
385 unsigned*& __g_end, unsigned& __dc, _CharT* __atoms);
386};
387
388template <class _CharT>
389string
390__num_get<_CharT>::__stage2_int_prep(ios_base& __iob, _CharT* __atoms, _CharT& __thousands_sep)
391{
392 locale __loc = __iob.getloc();
393 use_facet<ctype<_CharT> >(__loc).widen(__src, __src + 26, __atoms);
394 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
395 __thousands_sep = __np.thousands_sep();
396 return __np.grouping();
397}
398
399template <class _CharT>
400string
401__num_get<_CharT>::__stage2_float_prep(ios_base& __iob, _CharT* __atoms, _CharT& __decimal_point,
402 _CharT& __thousands_sep)
403{
404 locale __loc = __iob.getloc();
405 use_facet<ctype<_CharT> >(__loc).widen(__src, __src + 32, __atoms);
406 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
407 __decimal_point = __np.decimal_point();
408 __thousands_sep = __np.thousands_sep();
409 return __np.grouping();
410}
411
412template <class _CharT>
413int
414__num_get<_CharT>::__stage2_int_loop(_CharT __ct, int __base, char* __a, char*& __a_end,
415 unsigned& __dc, _CharT __thousands_sep, const string& __grouping,
416 unsigned* __g, unsigned*& __g_end, _CharT* __atoms)
417{
Howard Hinnantf57b3fc2011-03-09 01:03:19 +0000418 if (__a_end == __a && (__ct == __atoms[24] || __ct == __atoms[25]))
419 {
420 *__a_end++ = __ct == __atoms[24] ? '+' : '-';
421 __dc = 0;
422 return 0;
423 }
Howard Hinnant28b24882011-12-01 20:21:04 +0000424 if (__grouping.size() != 0 && __ct == __thousands_sep)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000425 {
426 if (__g_end-__g < __num_get_buf_sz)
427 {
428 *__g_end++ = __dc;
429 __dc = 0;
430 }
431 return 0;
432 }
433 ptrdiff_t __f = find(__atoms, __atoms + 26, __ct) - __atoms;
Howard Hinnantf57b3fc2011-03-09 01:03:19 +0000434 if (__f >= 24)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000435 return -1;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000436 switch (__base)
437 {
438 case 8:
439 case 10:
440 if (__f >= __base)
Howard Hinnantf57b3fc2011-03-09 01:03:19 +0000441 return -1;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000442 break;
Howard Hinnantf57b3fc2011-03-09 01:03:19 +0000443 case 16:
444 if (__f < 22)
445 break;
446 if (__a_end != __a && __a_end - __a <= 2 && __a_end[-1] == '0')
447 {
448 __dc = 0;
449 *__a_end++ = __src[__f];
Howard Hinnantc51e1022010-05-11 19:42:16 +0000450 return 0;
Howard Hinnantf57b3fc2011-03-09 01:03:19 +0000451 }
452 return -1;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000453 }
Howard Hinnant5d4013d2013-04-15 20:40:06 +0000454 *__a_end++ = __src[__f];
Howard Hinnantc51e1022010-05-11 19:42:16 +0000455 ++__dc;
456 return 0;
457}
458
459template <class _CharT>
460int
461__num_get<_CharT>::__stage2_float_loop(_CharT __ct, bool& __in_units, char& __exp, char* __a, char*& __a_end,
462 _CharT __decimal_point, _CharT __thousands_sep, const string& __grouping,
463 unsigned* __g, unsigned*& __g_end, unsigned& __dc, _CharT* __atoms)
464{
465 if (__ct == __decimal_point)
466 {
467 if (!__in_units)
468 return -1;
469 __in_units = false;
470 *__a_end++ = '.';
471 if (__grouping.size() != 0 && __g_end-__g < __num_get_buf_sz)
472 *__g_end++ = __dc;
473 return 0;
474 }
475 if (__ct == __thousands_sep && __grouping.size() != 0)
476 {
477 if (!__in_units)
478 return -1;
479 if (__g_end-__g < __num_get_buf_sz)
480 {
481 *__g_end++ = __dc;
482 __dc = 0;
483 }
484 return 0;
485 }
486 ptrdiff_t __f = find(__atoms, __atoms + 32, __ct) - __atoms;
487 if (__f >= 32)
488 return -1;
489 char __x = __src[__f];
Howard Hinnant5132e192012-02-15 19:19:37 +0000490 if (__x == '-' || __x == '+')
491 {
Howard Hinnant21413152013-03-08 19:06:24 +0000492 if (__a_end == __a || (__a_end[-1] & 0x5F) == (__exp & 0x7F))
Howard Hinnant5132e192012-02-15 19:19:37 +0000493 {
494 *__a_end++ = __x;
495 return 0;
496 }
497 return -1;
498 }
Howard Hinnantc51e1022010-05-11 19:42:16 +0000499 if (__x == 'x' || __x == 'X')
500 __exp = 'P';
Howard Hinnant21413152013-03-08 19:06:24 +0000501 else if ((__x & 0x5F) == __exp)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000502 {
Howard Hinnant21413152013-03-08 19:06:24 +0000503 __exp |= 0x80;
504 if (__in_units)
505 {
506 __in_units = false;
507 if (__grouping.size() != 0 && __g_end-__g < __num_get_buf_sz)
508 *__g_end++ = __dc;
509 }
Howard Hinnantc51e1022010-05-11 19:42:16 +0000510 }
Howard Hinnant5d4013d2013-04-15 20:40:06 +0000511 *__a_end++ = __x;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000512 if (__f >= 22)
513 return 0;
514 ++__dc;
515 return 0;
516}
517
Eric Fiselier1b57fa82016-09-15 22:27:07 +0000518_LIBCPP_EXTERN_TEMPLATE2(struct _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __num_get<char>)
519_LIBCPP_EXTERN_TEMPLATE2(struct _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __num_get<wchar_t>)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000520
521template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +0000522class _LIBCPP_TEMPLATE_VIS num_get
Howard Hinnantc51e1022010-05-11 19:42:16 +0000523 : public locale::facet,
524 private __num_get<_CharT>
525{
526public:
527 typedef _CharT char_type;
528 typedef _InputIterator iter_type;
529
530 _LIBCPP_ALWAYS_INLINE
531 explicit num_get(size_t __refs = 0)
532 : locale::facet(__refs) {}
533
534 _LIBCPP_ALWAYS_INLINE
535 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
536 ios_base::iostate& __err, bool& __v) const
537 {
538 return do_get(__b, __e, __iob, __err, __v);
539 }
540
541 _LIBCPP_ALWAYS_INLINE
542 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
543 ios_base::iostate& __err, long& __v) const
544 {
545 return do_get(__b, __e, __iob, __err, __v);
546 }
547
548 _LIBCPP_ALWAYS_INLINE
549 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
550 ios_base::iostate& __err, long long& __v) const
551 {
552 return do_get(__b, __e, __iob, __err, __v);
553 }
554
555 _LIBCPP_ALWAYS_INLINE
556 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
557 ios_base::iostate& __err, unsigned short& __v) const
558 {
559 return do_get(__b, __e, __iob, __err, __v);
560 }
561
562 _LIBCPP_ALWAYS_INLINE
563 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
564 ios_base::iostate& __err, unsigned int& __v) const
565 {
566 return do_get(__b, __e, __iob, __err, __v);
567 }
568
569 _LIBCPP_ALWAYS_INLINE
570 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
571 ios_base::iostate& __err, unsigned long& __v) const
572 {
573 return do_get(__b, __e, __iob, __err, __v);
574 }
575
576 _LIBCPP_ALWAYS_INLINE
577 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
578 ios_base::iostate& __err, unsigned long long& __v) const
579 {
580 return do_get(__b, __e, __iob, __err, __v);
581 }
582
583 _LIBCPP_ALWAYS_INLINE
584 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
585 ios_base::iostate& __err, float& __v) const
586 {
587 return do_get(__b, __e, __iob, __err, __v);
588 }
589
590 _LIBCPP_ALWAYS_INLINE
591 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
592 ios_base::iostate& __err, double& __v) const
593 {
594 return do_get(__b, __e, __iob, __err, __v);
595 }
596
597 _LIBCPP_ALWAYS_INLINE
598 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
599 ios_base::iostate& __err, long double& __v) const
600 {
601 return do_get(__b, __e, __iob, __err, __v);
602 }
603
604 _LIBCPP_ALWAYS_INLINE
605 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
606 ios_base::iostate& __err, void*& __v) const
607 {
608 return do_get(__b, __e, __iob, __err, __v);
609 }
610
611 static locale::id id;
612
613protected:
Howard Hinnant756c69b2010-09-22 16:48:34 +0000614 _LIBCPP_ALWAYS_INLINE
Howard Hinnantc51e1022010-05-11 19:42:16 +0000615 ~num_get() {}
616
Marshall Clowae385382013-11-05 14:28:52 +0000617 template <class _Fp>
Shoaib Meenai69c57412017-03-02 03:02:50 +0000618 _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
619 iter_type __do_get_floating_point
Marshall Clowae385382013-11-05 14:28:52 +0000620 (iter_type __b, iter_type __e, ios_base& __iob,
621 ios_base::iostate& __err, _Fp& __v) const;
Marshall Clow96d86d82013-11-07 01:00:50 +0000622
623 template <class _Signed>
Shoaib Meenai69c57412017-03-02 03:02:50 +0000624 _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
625 iter_type __do_get_signed
Marshall Clow96d86d82013-11-07 01:00:50 +0000626 (iter_type __b, iter_type __e, ios_base& __iob,
627 ios_base::iostate& __err, _Signed& __v) const;
628
629 template <class _Unsigned>
Shoaib Meenai69c57412017-03-02 03:02:50 +0000630 _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
631 iter_type __do_get_unsigned
Marshall Clow96d86d82013-11-07 01:00:50 +0000632 (iter_type __b, iter_type __e, ios_base& __iob,
633 ios_base::iostate& __err, _Unsigned& __v) const;
634
635
636 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
637 ios_base::iostate& __err, bool& __v) const;
638
639 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
640 ios_base::iostate& __err, long& __v) const
641 { return this->__do_get_signed ( __b, __e, __iob, __err, __v ); }
642
643 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
644 ios_base::iostate& __err, long long& __v) const
645 { return this->__do_get_signed ( __b, __e, __iob, __err, __v ); }
646
647 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
648 ios_base::iostate& __err, unsigned short& __v) const
649 { return this->__do_get_unsigned ( __b, __e, __iob, __err, __v ); }
650
651 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
652 ios_base::iostate& __err, unsigned int& __v) const
653 { return this->__do_get_unsigned ( __b, __e, __iob, __err, __v ); }
654
655 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
656 ios_base::iostate& __err, unsigned long& __v) const
657 { return this->__do_get_unsigned ( __b, __e, __iob, __err, __v ); }
658
659 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
660 ios_base::iostate& __err, unsigned long long& __v) const
661 { return this->__do_get_unsigned ( __b, __e, __iob, __err, __v ); }
662
663 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
664 ios_base::iostate& __err, float& __v) const
665 { return this->__do_get_floating_point ( __b, __e, __iob, __err, __v ); }
666
667 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
668 ios_base::iostate& __err, double& __v) const
669 { return this->__do_get_floating_point ( __b, __e, __iob, __err, __v ); }
670
671 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
672 ios_base::iostate& __err, long double& __v) const
673 { return this->__do_get_floating_point ( __b, __e, __iob, __err, __v ); }
674
675 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
676 ios_base::iostate& __err, void*& __v) const;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000677};
678
679template <class _CharT, class _InputIterator>
680locale::id
681num_get<_CharT, _InputIterator>::id;
682
683template <class _Tp>
684_Tp
685__num_get_signed_integral(const char* __a, const char* __a_end,
686 ios_base::iostate& __err, int __base)
687{
688 if (__a != __a_end)
689 {
Howard Hinnantca8923c2013-01-22 17:26:08 +0000690 typename remove_reference<decltype(errno)>::type __save_errno = errno;
Howard Hinnant05c71342011-02-25 19:52:41 +0000691 errno = 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000692 char *__p2;
Howard Hinnant1ab52da2011-09-28 21:05:01 +0000693 long long __ll = strtoll_l(__a, &__p2, __base, _LIBCPP_GET_C_LOCALE);
Howard Hinnantca8923c2013-01-22 17:26:08 +0000694 typename remove_reference<decltype(errno)>::type __current_errno = errno;
Howard Hinnant05c71342011-02-25 19:52:41 +0000695 if (__current_errno == 0)
696 errno = __save_errno;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000697 if (__p2 != __a_end)
698 {
699 __err = ios_base::failbit;
700 return 0;
701 }
Howard Hinnant05c71342011-02-25 19:52:41 +0000702 else if (__current_errno == ERANGE ||
703 __ll < numeric_limits<_Tp>::min() ||
704 numeric_limits<_Tp>::max() < __ll)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000705 {
706 __err = ios_base::failbit;
Howard Hinnant05c71342011-02-25 19:52:41 +0000707 if (__ll > 0)
708 return numeric_limits<_Tp>::max();
709 else
710 return numeric_limits<_Tp>::min();
Howard Hinnantc51e1022010-05-11 19:42:16 +0000711 }
712 return static_cast<_Tp>(__ll);
713 }
714 __err = ios_base::failbit;
715 return 0;
716}
717
718template <class _Tp>
719_Tp
720__num_get_unsigned_integral(const char* __a, const char* __a_end,
721 ios_base::iostate& __err, int __base)
722{
723 if (__a != __a_end)
724 {
Howard Hinnant05c71342011-02-25 19:52:41 +0000725 if (*__a == '-')
726 {
727 __err = ios_base::failbit;
728 return 0;
729 }
Howard Hinnantca8923c2013-01-22 17:26:08 +0000730 typename remove_reference<decltype(errno)>::type __save_errno = errno;
Howard Hinnant05c71342011-02-25 19:52:41 +0000731 errno = 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000732 char *__p2;
Howard Hinnant1ab52da2011-09-28 21:05:01 +0000733 unsigned long long __ll = strtoull_l(__a, &__p2, __base, _LIBCPP_GET_C_LOCALE);
Howard Hinnantca8923c2013-01-22 17:26:08 +0000734 typename remove_reference<decltype(errno)>::type __current_errno = errno;
Howard Hinnant05c71342011-02-25 19:52:41 +0000735 if (__current_errno == 0)
736 errno = __save_errno;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000737 if (__p2 != __a_end)
738 {
739 __err = ios_base::failbit;
740 return 0;
741 }
Howard Hinnant05c71342011-02-25 19:52:41 +0000742 else if (__current_errno == ERANGE ||
743 numeric_limits<_Tp>::max() < __ll)
Howard Hinnantc51e1022010-05-11 19:42:16 +0000744 {
745 __err = ios_base::failbit;
746 return numeric_limits<_Tp>::max();
747 }
748 return static_cast<_Tp>(__ll);
749 }
750 __err = ios_base::failbit;
751 return 0;
752}
753
754template <class _Tp>
Eric Fiselier98e428d2016-06-19 06:58:22 +0000755_LIBCPP_INLINE_VISIBILITY
756_Tp __do_strtod(const char* __a, char** __p2);
757
758template <>
759inline _LIBCPP_INLINE_VISIBILITY
760float __do_strtod<float>(const char* __a, char** __p2) {
761 return strtof_l(__a, __p2, _LIBCPP_GET_C_LOCALE);
762}
763
764template <>
765inline _LIBCPP_INLINE_VISIBILITY
766double __do_strtod<double>(const char* __a, char** __p2) {
767 return strtod_l(__a, __p2, _LIBCPP_GET_C_LOCALE);
768}
769
770template <>
771inline _LIBCPP_INLINE_VISIBILITY
772long double __do_strtod<long double>(const char* __a, char** __p2) {
773 return strtold_l(__a, __p2, _LIBCPP_GET_C_LOCALE);
774}
775
776template <class _Tp>
Shoaib Meenai54c6fd62016-12-24 18:05:32 +0000777_LIBCPP_HIDDEN
Howard Hinnantc51e1022010-05-11 19:42:16 +0000778_Tp
779__num_get_float(const char* __a, const char* __a_end, ios_base::iostate& __err)
780{
781 if (__a != __a_end)
782 {
Howard Hinnantc9567812013-04-13 18:19:25 +0000783 typename remove_reference<decltype(errno)>::type __save_errno = errno;
784 errno = 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000785 char *__p2;
Eric Fiselier98e428d2016-06-19 06:58:22 +0000786 _Tp __ld = __do_strtod<_Tp>(__a, &__p2);
Howard Hinnantc9567812013-04-13 18:19:25 +0000787 typename remove_reference<decltype(errno)>::type __current_errno = errno;
788 if (__current_errno == 0)
789 errno = __save_errno;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000790 if (__p2 != __a_end)
791 {
792 __err = ios_base::failbit;
793 return 0;
794 }
Howard Hinnantc9567812013-04-13 18:19:25 +0000795 else if (__current_errno == ERANGE)
796 __err = ios_base::failbit;
Eric Fiselier98e428d2016-06-19 06:58:22 +0000797 return __ld;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000798 }
799 __err = ios_base::failbit;
800 return 0;
801}
802
803template <class _CharT, class _InputIterator>
804_InputIterator
805num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
806 ios_base& __iob,
807 ios_base::iostate& __err,
808 bool& __v) const
809{
810 if ((__iob.flags() & ios_base::boolalpha) == 0)
811 {
812 long __lv = -1;
813 __b = do_get(__b, __e, __iob, __err, __lv);
814 switch (__lv)
815 {
816 case 0:
817 __v = false;
818 break;
819 case 1:
820 __v = true;
821 break;
822 default:
823 __v = true;
824 __err = ios_base::failbit;
825 break;
826 }
827 return __b;
828 }
829 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__iob.getloc());
830 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__iob.getloc());
831 typedef typename numpunct<_CharT>::string_type string_type;
832 const string_type __names[2] = {__np.truename(), __np.falsename()};
833 const string_type* __i = __scan_keyword(__b, __e, __names, __names+2,
834 __ct, __err);
835 __v = __i == __names;
836 return __b;
837}
838
Marshall Clow96d86d82013-11-07 01:00:50 +0000839// signed
840
Howard Hinnantc51e1022010-05-11 19:42:16 +0000841template <class _CharT, class _InputIterator>
Marshall Clow96d86d82013-11-07 01:00:50 +0000842template <class _Signed>
Howard Hinnantc51e1022010-05-11 19:42:16 +0000843_InputIterator
Marshall Clow96d86d82013-11-07 01:00:50 +0000844num_get<_CharT, _InputIterator>::__do_get_signed(iter_type __b, iter_type __e,
Howard Hinnantc51e1022010-05-11 19:42:16 +0000845 ios_base& __iob,
846 ios_base::iostate& __err,
Marshall Clow96d86d82013-11-07 01:00:50 +0000847 _Signed& __v) const
Howard Hinnantc51e1022010-05-11 19:42:16 +0000848{
849 // Stage 1
850 int __base = this->__get_base(__iob);
851 // Stage 2
852 char_type __atoms[26];
853 char_type __thousands_sep;
854 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
Howard Hinnant5d4013d2013-04-15 20:40:06 +0000855 string __buf;
856 __buf.resize(__buf.capacity());
857 char* __a = &__buf[0];
Howard Hinnantc51e1022010-05-11 19:42:16 +0000858 char* __a_end = __a;
859 unsigned __g[__num_get_base::__num_get_buf_sz];
860 unsigned* __g_end = __g;
861 unsigned __dc = 0;
862 for (; __b != __e; ++__b)
Howard Hinnant5d4013d2013-04-15 20:40:06 +0000863 {
Joerg Sonnenberger7a804f62014-02-07 21:14:29 +0000864 if (__a_end == __a + __buf.size())
Howard Hinnant5d4013d2013-04-15 20:40:06 +0000865 {
866 size_t __tmp = __buf.size();
867 __buf.resize(2*__buf.size());
868 __buf.resize(__buf.capacity());
869 __a = &__buf[0];
870 __a_end = __a + __tmp;
871 }
Howard Hinnant3b6579a2010-08-22 00:02:43 +0000872 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
Howard Hinnantc51e1022010-05-11 19:42:16 +0000873 __thousands_sep, __grouping, __g, __g_end,
874 __atoms))
875 break;
Howard Hinnant5d4013d2013-04-15 20:40:06 +0000876 }
Howard Hinnantc51e1022010-05-11 19:42:16 +0000877 if (__grouping.size() != 0 && __g_end-__g < __num_get_base::__num_get_buf_sz)
878 *__g_end++ = __dc;
879 // Stage 3
Marshall Clow96d86d82013-11-07 01:00:50 +0000880 __v = __num_get_signed_integral<_Signed>(__a, __a_end, __err, __base);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000881 // Digit grouping checked
882 __check_grouping(__grouping, __g, __g_end, __err);
883 // EOF checked
884 if (__b == __e)
885 __err |= ios_base::eofbit;
886 return __b;
887}
888
Marshall Clow96d86d82013-11-07 01:00:50 +0000889// unsigned
Howard Hinnantc51e1022010-05-11 19:42:16 +0000890
891template <class _CharT, class _InputIterator>
Marshall Clow96d86d82013-11-07 01:00:50 +0000892template <class _Unsigned>
Howard Hinnantc51e1022010-05-11 19:42:16 +0000893_InputIterator
Marshall Clow96d86d82013-11-07 01:00:50 +0000894num_get<_CharT, _InputIterator>::__do_get_unsigned(iter_type __b, iter_type __e,
Howard Hinnantc51e1022010-05-11 19:42:16 +0000895 ios_base& __iob,
896 ios_base::iostate& __err,
Marshall Clow96d86d82013-11-07 01:00:50 +0000897 _Unsigned& __v) const
Howard Hinnantc51e1022010-05-11 19:42:16 +0000898{
899 // Stage 1
900 int __base = this->__get_base(__iob);
901 // Stage 2
902 char_type __atoms[26];
903 char_type __thousands_sep;
904 string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
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_unsigned_integral<_Unsigned>(__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 Clowae385382013-11-05 14:28:52 +0000939// floating point
940
Howard Hinnantc51e1022010-05-11 19:42:16 +0000941template <class _CharT, class _InputIterator>
Marshall Clowae385382013-11-05 14:28:52 +0000942template <class _Fp>
Howard Hinnantc51e1022010-05-11 19:42:16 +0000943_InputIterator
Marshall Clowae385382013-11-05 14:28:52 +0000944num_get<_CharT, _InputIterator>::__do_get_floating_point(iter_type __b, iter_type __e,
Howard Hinnantc51e1022010-05-11 19:42:16 +0000945 ios_base& __iob,
946 ios_base::iostate& __err,
Marshall Clowae385382013-11-05 14:28:52 +0000947 _Fp& __v) const
Howard Hinnantc51e1022010-05-11 19:42:16 +0000948{
949 // Stage 1, nothing to do
950 // Stage 2
951 char_type __atoms[32];
952 char_type __decimal_point;
953 char_type __thousands_sep;
Howard Hinnant3b6579a2010-08-22 00:02:43 +0000954 string __grouping = this->__stage2_float_prep(__iob, __atoms,
955 __decimal_point,
Howard Hinnantc51e1022010-05-11 19:42:16 +0000956 __thousands_sep);
Howard Hinnant5d4013d2013-04-15 20:40:06 +0000957 string __buf;
958 __buf.resize(__buf.capacity());
959 char* __a = &__buf[0];
Howard Hinnantc51e1022010-05-11 19:42:16 +0000960 char* __a_end = __a;
961 unsigned __g[__num_get_base::__num_get_buf_sz];
962 unsigned* __g_end = __g;
963 unsigned __dc = 0;
964 bool __in_units = true;
965 char __exp = 'E';
966 for (; __b != __e; ++__b)
Howard Hinnant5d4013d2013-04-15 20:40:06 +0000967 {
Joerg Sonnenberger7a804f62014-02-07 21:14:29 +0000968 if (__a_end == __a + __buf.size())
Howard Hinnant5d4013d2013-04-15 20:40:06 +0000969 {
970 size_t __tmp = __buf.size();
971 __buf.resize(2*__buf.size());
972 __buf.resize(__buf.capacity());
973 __a = &__buf[0];
974 __a_end = __a + __tmp;
975 }
Howard Hinnant3b6579a2010-08-22 00:02:43 +0000976 if (this->__stage2_float_loop(*__b, __in_units, __exp, __a, __a_end,
977 __decimal_point, __thousands_sep,
Howard Hinnantc51e1022010-05-11 19:42:16 +0000978 __grouping, __g, __g_end,
979 __dc, __atoms))
980 break;
Howard Hinnant5d4013d2013-04-15 20:40:06 +0000981 }
Howard Hinnantc51e1022010-05-11 19:42:16 +0000982 if (__grouping.size() != 0 && __in_units && __g_end-__g < __num_get_base::__num_get_buf_sz)
983 *__g_end++ = __dc;
984 // Stage 3
Marshall Clowae385382013-11-05 14:28:52 +0000985 __v = __num_get_float<_Fp>(__a, __a_end, __err);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000986 // Digit grouping checked
987 __check_grouping(__grouping, __g, __g_end, __err);
988 // EOF checked
989 if (__b == __e)
990 __err |= ios_base::eofbit;
991 return __b;
992}
993
994template <class _CharT, class _InputIterator>
995_InputIterator
996num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
997 ios_base& __iob,
998 ios_base::iostate& __err,
Howard Hinnantc51e1022010-05-11 19:42:16 +0000999 void*& __v) const
1000{
1001 // Stage 1
1002 int __base = 16;
1003 // Stage 2
1004 char_type __atoms[26];
Howard Hinnant28b24882011-12-01 20:21:04 +00001005 char_type __thousands_sep = 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001006 string __grouping;
1007 use_facet<ctype<_CharT> >(__iob.getloc()).widen(__num_get_base::__src,
1008 __num_get_base::__src + 26, __atoms);
Howard Hinnant5d4013d2013-04-15 20:40:06 +00001009 string __buf;
1010 __buf.resize(__buf.capacity());
1011 char* __a = &__buf[0];
Howard Hinnantc51e1022010-05-11 19:42:16 +00001012 char* __a_end = __a;
1013 unsigned __g[__num_get_base::__num_get_buf_sz];
1014 unsigned* __g_end = __g;
1015 unsigned __dc = 0;
1016 for (; __b != __e; ++__b)
Howard Hinnant5d4013d2013-04-15 20:40:06 +00001017 {
Joerg Sonnenberger7a804f62014-02-07 21:14:29 +00001018 if (__a_end == __a + __buf.size())
Howard Hinnant5d4013d2013-04-15 20:40:06 +00001019 {
1020 size_t __tmp = __buf.size();
1021 __buf.resize(2*__buf.size());
1022 __buf.resize(__buf.capacity());
1023 __a = &__buf[0];
1024 __a_end = __a + __tmp;
1025 }
Howard Hinnant3b6579a2010-08-22 00:02:43 +00001026 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc,
1027 __thousands_sep, __grouping,
Howard Hinnantc51e1022010-05-11 19:42:16 +00001028 __g, __g_end, __atoms))
1029 break;
Howard Hinnant5d4013d2013-04-15 20:40:06 +00001030 }
Howard Hinnantc51e1022010-05-11 19:42:16 +00001031 // Stage 3
Marshall Clow0db963d2014-05-21 16:02:20 +00001032 __buf.resize(__a_end - __a);
Ben Craig3756b922016-03-09 15:39:39 +00001033 if (__libcpp_sscanf_l(__buf.c_str(), _LIBCPP_GET_C_LOCALE, "%p", &__v) != 1)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001034 __err = ios_base::failbit;
1035 // EOF checked
1036 if (__b == __e)
1037 __err |= ios_base::eofbit;
1038 return __b;
1039}
1040
Eric Fiselier1b57fa82016-09-15 22:27:07 +00001041_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS num_get<char>)
1042_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS num_get<wchar_t>)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001043
Howard Hinnanta37d3cf2013-08-12 18:38:34 +00001044struct _LIBCPP_TYPE_VIS __num_put_base
Howard Hinnantc51e1022010-05-11 19:42:16 +00001045{
1046protected:
1047 static void __format_int(char* __fmt, const char* __len, bool __signd,
1048 ios_base::fmtflags __flags);
1049 static bool __format_float(char* __fmt, const char* __len,
1050 ios_base::fmtflags __flags);
1051 static char* __identify_padding(char* __nb, char* __ne,
1052 const ios_base& __iob);
1053};
1054
1055template <class _CharT>
1056struct __num_put
1057 : protected __num_put_base
1058{
1059 static void __widen_and_group_int(char* __nb, char* __np, char* __ne,
1060 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1061 const locale& __loc);
1062 static void __widen_and_group_float(char* __nb, char* __np, char* __ne,
1063 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1064 const locale& __loc);
1065};
1066
1067template <class _CharT>
1068void
1069__num_put<_CharT>::__widen_and_group_int(char* __nb, char* __np, char* __ne,
1070 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1071 const locale& __loc)
1072{
1073 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> > (__loc);
1074 const numpunct<_CharT>& __npt = use_facet<numpunct<_CharT> >(__loc);
1075 string __grouping = __npt.grouping();
1076 if (__grouping.empty())
1077 {
1078 __ct.widen(__nb, __ne, __ob);
1079 __oe = __ob + (__ne - __nb);
1080 }
1081 else
1082 {
1083 __oe = __ob;
1084 char* __nf = __nb;
1085 if (*__nf == '-' || *__nf == '+')
1086 *__oe++ = __ct.widen(*__nf++);
1087 if (__ne - __nf >= 2 && __nf[0] == '0' && (__nf[1] == 'x' ||
1088 __nf[1] == 'X'))
1089 {
1090 *__oe++ = __ct.widen(*__nf++);
1091 *__oe++ = __ct.widen(*__nf++);
1092 }
1093 reverse(__nf, __ne);
1094 _CharT __thousands_sep = __npt.thousands_sep();
1095 unsigned __dc = 0;
1096 unsigned __dg = 0;
1097 for (char* __p = __nf; __p < __ne; ++__p)
1098 {
1099 if (static_cast<unsigned>(__grouping[__dg]) > 0 &&
1100 __dc == static_cast<unsigned>(__grouping[__dg]))
1101 {
1102 *__oe++ = __thousands_sep;
1103 __dc = 0;
1104 if (__dg < __grouping.size()-1)
1105 ++__dg;
1106 }
1107 *__oe++ = __ct.widen(*__p);
1108 ++__dc;
1109 }
1110 reverse(__ob + (__nf - __nb), __oe);
1111 }
1112 if (__np == __ne)
1113 __op = __oe;
1114 else
1115 __op = __ob + (__np - __nb);
1116}
1117
1118template <class _CharT>
1119void
1120__num_put<_CharT>::__widen_and_group_float(char* __nb, char* __np, char* __ne,
1121 _CharT* __ob, _CharT*& __op, _CharT*& __oe,
1122 const locale& __loc)
1123{
1124 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> > (__loc);
1125 const numpunct<_CharT>& __npt = use_facet<numpunct<_CharT> >(__loc);
1126 string __grouping = __npt.grouping();
1127 __oe = __ob;
1128 char* __nf = __nb;
1129 if (*__nf == '-' || *__nf == '+')
1130 *__oe++ = __ct.widen(*__nf++);
1131 char* __ns;
1132 if (__ne - __nf >= 2 && __nf[0] == '0' && (__nf[1] == 'x' ||
1133 __nf[1] == 'X'))
1134 {
1135 *__oe++ = __ct.widen(*__nf++);
1136 *__oe++ = __ct.widen(*__nf++);
1137 for (__ns = __nf; __ns < __ne; ++__ns)
Howard Hinnant1ab52da2011-09-28 21:05:01 +00001138 if (!isxdigit_l(*__ns, _LIBCPP_GET_C_LOCALE))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001139 break;
1140 }
1141 else
1142 {
1143 for (__ns = __nf; __ns < __ne; ++__ns)
Howard Hinnant1ab52da2011-09-28 21:05:01 +00001144 if (!isdigit_l(*__ns, _LIBCPP_GET_C_LOCALE))
Howard Hinnantc51e1022010-05-11 19:42:16 +00001145 break;
1146 }
1147 if (__grouping.empty())
1148 {
1149 __ct.widen(__nf, __ns, __oe);
1150 __oe += __ns - __nf;
1151 }
1152 else
1153 {
1154 reverse(__nf, __ns);
1155 _CharT __thousands_sep = __npt.thousands_sep();
1156 unsigned __dc = 0;
1157 unsigned __dg = 0;
1158 for (char* __p = __nf; __p < __ns; ++__p)
1159 {
1160 if (__grouping[__dg] > 0 && __dc == static_cast<unsigned>(__grouping[__dg]))
1161 {
1162 *__oe++ = __thousands_sep;
1163 __dc = 0;
1164 if (__dg < __grouping.size()-1)
1165 ++__dg;
1166 }
1167 *__oe++ = __ct.widen(*__p);
1168 ++__dc;
1169 }
1170 reverse(__ob + (__nf - __nb), __oe);
1171 }
1172 for (__nf = __ns; __nf < __ne; ++__nf)
1173 {
1174 if (*__nf == '.')
1175 {
1176 *__oe++ = __npt.decimal_point();
1177 ++__nf;
1178 break;
1179 }
1180 else
1181 *__oe++ = __ct.widen(*__nf);
1182 }
1183 __ct.widen(__nf, __ne, __oe);
1184 __oe += __ne - __nf;
1185 if (__np == __ne)
1186 __op = __oe;
1187 else
1188 __op = __ob + (__np - __nb);
1189}
1190
Eric Fiselier1b57fa82016-09-15 22:27:07 +00001191_LIBCPP_EXTERN_TEMPLATE2(struct _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __num_put<char>)
1192_LIBCPP_EXTERN_TEMPLATE2(struct _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __num_put<wchar_t>)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001193
1194template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +00001195class _LIBCPP_TEMPLATE_VIS num_put
Howard Hinnantc51e1022010-05-11 19:42:16 +00001196 : public locale::facet,
1197 private __num_put<_CharT>
1198{
1199public:
1200 typedef _CharT char_type;
1201 typedef _OutputIterator iter_type;
1202
1203 _LIBCPP_ALWAYS_INLINE
1204 explicit num_put(size_t __refs = 0)
1205 : locale::facet(__refs) {}
1206
1207 _LIBCPP_ALWAYS_INLINE
1208 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1209 bool __v) const
1210 {
1211 return do_put(__s, __iob, __fl, __v);
1212 }
1213
1214 _LIBCPP_ALWAYS_INLINE
1215 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1216 long __v) const
1217 {
1218 return do_put(__s, __iob, __fl, __v);
1219 }
1220
1221 _LIBCPP_ALWAYS_INLINE
1222 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1223 long long __v) const
1224 {
1225 return do_put(__s, __iob, __fl, __v);
1226 }
1227
1228 _LIBCPP_ALWAYS_INLINE
1229 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1230 unsigned long __v) const
1231 {
1232 return do_put(__s, __iob, __fl, __v);
1233 }
1234
1235 _LIBCPP_ALWAYS_INLINE
1236 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1237 unsigned long long __v) const
1238 {
1239 return do_put(__s, __iob, __fl, __v);
1240 }
1241
1242 _LIBCPP_ALWAYS_INLINE
1243 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1244 double __v) const
1245 {
1246 return do_put(__s, __iob, __fl, __v);
1247 }
1248
1249 _LIBCPP_ALWAYS_INLINE
1250 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1251 long double __v) const
1252 {
1253 return do_put(__s, __iob, __fl, __v);
1254 }
1255
1256 _LIBCPP_ALWAYS_INLINE
1257 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
1258 const void* __v) const
1259 {
1260 return do_put(__s, __iob, __fl, __v);
1261 }
1262
1263 static locale::id id;
1264
1265protected:
Howard Hinnant756c69b2010-09-22 16:48:34 +00001266 _LIBCPP_ALWAYS_INLINE
Howard Hinnantc51e1022010-05-11 19:42:16 +00001267 ~num_put() {}
1268
1269 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1270 bool __v) const;
1271 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1272 long __v) const;
1273 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1274 long long __v) const;
1275 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1276 unsigned long) const;
1277 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1278 unsigned long long) const;
1279 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1280 double __v) const;
1281 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1282 long double __v) const;
1283 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl,
1284 const void* __v) const;
1285};
1286
1287template <class _CharT, class _OutputIterator>
1288locale::id
1289num_put<_CharT, _OutputIterator>::id;
1290
1291template <class _CharT, class _OutputIterator>
1292_LIBCPP_HIDDEN
1293_OutputIterator
1294__pad_and_output(_OutputIterator __s,
1295 const _CharT* __ob, const _CharT* __op, const _CharT* __oe,
1296 ios_base& __iob, _CharT __fl)
1297{
1298 streamsize __sz = __oe - __ob;
1299 streamsize __ns = __iob.width();
1300 if (__ns > __sz)
1301 __ns -= __sz;
1302 else
1303 __ns = 0;
1304 for (;__ob < __op; ++__ob, ++__s)
1305 *__s = *__ob;
1306 for (; __ns; --__ns, ++__s)
1307 *__s = __fl;
1308 for (; __ob < __oe; ++__ob, ++__s)
1309 *__s = *__ob;
1310 __iob.width(0);
1311 return __s;
1312}
1313
Howard Hinnant48fd5d52012-11-14 21:17:15 +00001314#if !defined(__APPLE__) || \
1315 (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED > __MAC_10_8) || \
1316 (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED > __IPHONE_6_0)
1317
Howard Hinnant97955172012-09-19 19:14:15 +00001318template <class _CharT, class _Traits>
1319_LIBCPP_HIDDEN
1320ostreambuf_iterator<_CharT, _Traits>
1321__pad_and_output(ostreambuf_iterator<_CharT, _Traits> __s,
1322 const _CharT* __ob, const _CharT* __op, const _CharT* __oe,
1323 ios_base& __iob, _CharT __fl)
1324{
1325 if (__s.__sbuf_ == nullptr)
1326 return __s;
1327 streamsize __sz = __oe - __ob;
1328 streamsize __ns = __iob.width();
1329 if (__ns > __sz)
1330 __ns -= __sz;
1331 else
1332 __ns = 0;
1333 streamsize __np = __op - __ob;
1334 if (__np > 0)
1335 {
1336 if (__s.__sbuf_->sputn(__ob, __np) != __np)
1337 {
1338 __s.__sbuf_ = nullptr;
1339 return __s;
1340 }
1341 }
1342 if (__ns > 0)
1343 {
1344 basic_string<_CharT, _Traits> __sp(__ns, __fl);
1345 if (__s.__sbuf_->sputn(__sp.data(), __ns) != __ns)
1346 {
1347 __s.__sbuf_ = nullptr;
1348 return __s;
1349 }
1350 }
1351 __np = __oe - __op;
1352 if (__np > 0)
1353 {
1354 if (__s.__sbuf_->sputn(__op, __np) != __np)
1355 {
1356 __s.__sbuf_ = nullptr;
1357 return __s;
1358 }
1359 }
1360 __iob.width(0);
1361 return __s;
1362}
1363
Howard Hinnant48fd5d52012-11-14 21:17:15 +00001364#endif
1365
Howard Hinnantc51e1022010-05-11 19:42:16 +00001366template <class _CharT, class _OutputIterator>
1367_OutputIterator
1368num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1369 char_type __fl, bool __v) const
1370{
1371 if ((__iob.flags() & ios_base::boolalpha) == 0)
1372 return do_put(__s, __iob, __fl, (unsigned long)__v);
1373 const numpunct<char_type>& __np = use_facet<numpunct<char_type> >(__iob.getloc());
1374 typedef typename numpunct<char_type>::string_type string_type;
Howard Hinnant8ea98242013-08-23 17:37:05 +00001375#if _LIBCPP_DEBUG_LEVEL >= 2
1376 string_type __tmp(__v ? __np.truename() : __np.falsename());
1377 string_type __nm = _VSTD::move(__tmp);
1378#else
Howard Hinnantc51e1022010-05-11 19:42:16 +00001379 string_type __nm = __v ? __np.truename() : __np.falsename();
Howard Hinnant8ea98242013-08-23 17:37:05 +00001380#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +00001381 for (typename string_type::iterator __i = __nm.begin(); __i != __nm.end(); ++__i, ++__s)
1382 *__s = *__i;
1383 return __s;
1384}
1385
1386template <class _CharT, class _OutputIterator>
1387_OutputIterator
1388num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1389 char_type __fl, long __v) const
1390{
1391 // Stage 1 - Get number in narrow char
1392 char __fmt[6] = {'%', 0};
1393 const char* __len = "l";
1394 this->__format_int(__fmt+1, __len, true, __iob.flags());
1395 const unsigned __nbuf = (numeric_limits<long>::digits / 3)
1396 + ((numeric_limits<long>::digits % 3) != 0)
Dimitry Andriccfb7b5d2017-05-06 20:58:50 +00001397 + ((__iob.flags() & ios_base::showbase) != 0)
Eric Fiselier4cc37352016-04-29 07:23:20 +00001398 + 2;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001399 char __nar[__nbuf];
Ben Craig3756b922016-03-09 15:39:39 +00001400 int __nc = __libcpp_snprintf_l(__nar, sizeof(__nar), _LIBCPP_GET_C_LOCALE, __fmt, __v);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001401 char* __ne = __nar + __nc;
1402 char* __np = this->__identify_padding(__nar, __ne, __iob);
1403 // Stage 2 - Widen __nar while adding thousands separators
1404 char_type __o[2*(__nbuf-1) - 1];
1405 char_type* __op; // pad here
1406 char_type* __oe; // end of output
1407 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1408 // [__o, __oe) contains thousands_sep'd wide number
1409 // Stage 3 & 4
1410 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1411}
1412
1413template <class _CharT, class _OutputIterator>
1414_OutputIterator
1415num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1416 char_type __fl, long long __v) const
1417{
1418 // Stage 1 - Get number in narrow char
1419 char __fmt[8] = {'%', 0};
1420 const char* __len = "ll";
1421 this->__format_int(__fmt+1, __len, true, __iob.flags());
1422 const unsigned __nbuf = (numeric_limits<long long>::digits / 3)
1423 + ((numeric_limits<long long>::digits % 3) != 0)
Dimitry Andriccfb7b5d2017-05-06 20:58:50 +00001424 + ((__iob.flags() & ios_base::showbase) != 0)
Marshall Clow7ac088f2015-01-26 17:24:52 +00001425 + 2;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001426 char __nar[__nbuf];
Ben Craig3756b922016-03-09 15:39:39 +00001427 int __nc = __libcpp_snprintf_l(__nar, sizeof(__nar), _LIBCPP_GET_C_LOCALE, __fmt, __v);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001428 char* __ne = __nar + __nc;
1429 char* __np = this->__identify_padding(__nar, __ne, __iob);
1430 // Stage 2 - Widen __nar while adding thousands separators
1431 char_type __o[2*(__nbuf-1) - 1];
1432 char_type* __op; // pad here
1433 char_type* __oe; // end of output
1434 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1435 // [__o, __oe) contains thousands_sep'd wide number
1436 // Stage 3 & 4
1437 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1438}
1439
1440template <class _CharT, class _OutputIterator>
1441_OutputIterator
1442num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1443 char_type __fl, unsigned long __v) const
1444{
1445 // Stage 1 - Get number in narrow char
1446 char __fmt[6] = {'%', 0};
1447 const char* __len = "l";
1448 this->__format_int(__fmt+1, __len, false, __iob.flags());
1449 const unsigned __nbuf = (numeric_limits<unsigned long>::digits / 3)
1450 + ((numeric_limits<unsigned long>::digits % 3) != 0)
Dimitry Andriccfb7b5d2017-05-06 20:58:50 +00001451 + ((__iob.flags() & ios_base::showbase) != 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001452 + 1;
1453 char __nar[__nbuf];
Ben Craig3756b922016-03-09 15:39:39 +00001454 int __nc = __libcpp_snprintf_l(__nar, sizeof(__nar), _LIBCPP_GET_C_LOCALE, __fmt, __v);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001455 char* __ne = __nar + __nc;
1456 char* __np = this->__identify_padding(__nar, __ne, __iob);
1457 // Stage 2 - Widen __nar while adding thousands separators
1458 char_type __o[2*(__nbuf-1) - 1];
1459 char_type* __op; // pad here
1460 char_type* __oe; // end of output
1461 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1462 // [__o, __oe) contains thousands_sep'd wide number
1463 // Stage 3 & 4
1464 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1465}
1466
1467template <class _CharT, class _OutputIterator>
1468_OutputIterator
1469num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1470 char_type __fl, unsigned long long __v) const
1471{
1472 // Stage 1 - Get number in narrow char
1473 char __fmt[8] = {'%', 0};
1474 const char* __len = "ll";
1475 this->__format_int(__fmt+1, __len, false, __iob.flags());
1476 const unsigned __nbuf = (numeric_limits<unsigned long long>::digits / 3)
1477 + ((numeric_limits<unsigned long long>::digits % 3) != 0)
Dimitry Andriccfb7b5d2017-05-06 20:58:50 +00001478 + ((__iob.flags() & ios_base::showbase) != 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001479 + 1;
1480 char __nar[__nbuf];
Ben Craig3756b922016-03-09 15:39:39 +00001481 int __nc = __libcpp_snprintf_l(__nar, sizeof(__nar), _LIBCPP_GET_C_LOCALE, __fmt, __v);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001482 char* __ne = __nar + __nc;
1483 char* __np = this->__identify_padding(__nar, __ne, __iob);
1484 // Stage 2 - Widen __nar while adding thousands separators
1485 char_type __o[2*(__nbuf-1) - 1];
1486 char_type* __op; // pad here
1487 char_type* __oe; // end of output
1488 this->__widen_and_group_int(__nar, __np, __ne, __o, __op, __oe, __iob.getloc());
1489 // [__o, __oe) contains thousands_sep'd wide number
1490 // Stage 3 & 4
1491 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1492}
1493
1494template <class _CharT, class _OutputIterator>
1495_OutputIterator
1496num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob,
1497 char_type __fl, double __v) const
1498{
1499 // Stage 1 - Get number in narrow char
1500 char __fmt[8] = {'%', 0};
1501 const char* __len = "";
1502 bool __specify_precision = this->__format_float(__fmt+1, __len, __iob.flags());
1503 const unsigned __nbuf = 30;
1504 char __nar[__nbuf];
1505 char* __nb = __nar;
1506 int __nc;
1507 if (__specify_precision)
Ben Craig3756b922016-03-09 15:39:39 +00001508 __nc = __libcpp_snprintf_l(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt,
Howard Hinnant155c2af2010-05-24 17:49:41 +00001509 (int)__iob.precision(), __v);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001510 else
Ben Craig3756b922016-03-09 15:39:39 +00001511 __nc = __libcpp_snprintf_l(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001512 unique_ptr<char, void(*)(void*)> __nbh(0, free);
1513 if (__nc > static_cast<int>(__nbuf-1))
1514 {
1515 if (__specify_precision)
Ben Craig3756b922016-03-09 15:39:39 +00001516 __nc = __libcpp_asprintf_l(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, (int)__iob.precision(), __v);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001517 else
Ben Craig3756b922016-03-09 15:39:39 +00001518 __nc = __libcpp_asprintf_l(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, __v);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001519 if (__nb == 0)
1520 __throw_bad_alloc();
1521 __nbh.reset(__nb);
1522 }
1523 char* __ne = __nb + __nc;
1524 char* __np = this->__identify_padding(__nb, __ne, __iob);
1525 // Stage 2 - Widen __nar while adding thousands separators
1526 char_type __o[2*(__nbuf-1) - 1];
1527 char_type* __ob = __o;
1528 unique_ptr<char_type, void(*)(void*)> __obh(0, free);
1529 if (__nb != __nar)
1530 {
Howard Hinnant28b24882011-12-01 20:21:04 +00001531 __ob = (char_type*)malloc(2*static_cast<size_t>(__nc)*sizeof(char_type));
Howard Hinnantc51e1022010-05-11 19:42:16 +00001532 if (__ob == 0)
1533 __throw_bad_alloc();
1534 __obh.reset(__ob);
1535 }
1536 char_type* __op; // pad here
1537 char_type* __oe; // end of output
1538 this->__widen_and_group_float(__nb, __np, __ne, __ob, __op, __oe, __iob.getloc());
1539 // [__o, __oe) contains thousands_sep'd wide number
1540 // Stage 3 & 4
1541 __s = __pad_and_output(__s, __ob, __op, __oe, __iob, __fl);
1542 return __s;
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, long double __v) const
1549{
1550 // Stage 1 - Get number in narrow char
1551 char __fmt[8] = {'%', 0};
1552 const char* __len = "L";
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);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001563 unique_ptr<char, void(*)(void*)> __nbh(0, free);
1564 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);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001570 if (__nb == 0)
1571 __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, const void* __v) const
1600{
1601 // Stage 1 - Get pointer in narrow char
1602 char __fmt[6] = "%p";
1603 const unsigned __nbuf = 20;
1604 char __nar[__nbuf];
Ben Craig3756b922016-03-09 15:39:39 +00001605 int __nc = __libcpp_snprintf_l(__nar, sizeof(__nar), _LIBCPP_GET_C_LOCALE, __fmt, __v);
Howard Hinnantc51e1022010-05-11 19:42:16 +00001606 char* __ne = __nar + __nc;
1607 char* __np = this->__identify_padding(__nar, __ne, __iob);
1608 // Stage 2 - Widen __nar
1609 char_type __o[2*(__nbuf-1) - 1];
1610 char_type* __op; // pad here
1611 char_type* __oe; // end of output
1612 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
1613 __ct.widen(__nar, __ne, __o);
1614 __oe = __o + (__ne - __nar);
1615 if (__np == __ne)
1616 __op = __oe;
1617 else
1618 __op = __o + (__np - __nar);
1619 // [__o, __oe) contains wide number
1620 // Stage 3 & 4
1621 return __pad_and_output(__s, __o, __op, __oe, __iob, __fl);
1622}
1623
Eric Fiselier1b57fa82016-09-15 22:27:07 +00001624_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS num_put<char>)
1625_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS num_put<wchar_t>)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001626
1627template <class _CharT, class _InputIterator>
1628_LIBCPP_HIDDEN
1629int
1630__get_up_to_n_digits(_InputIterator& __b, _InputIterator __e,
1631 ios_base::iostate& __err, const ctype<_CharT>& __ct, int __n)
1632{
1633 // Precondition: __n >= 1
1634 if (__b == __e)
1635 {
1636 __err |= ios_base::eofbit | ios_base::failbit;
1637 return 0;
1638 }
1639 // get first digit
1640 _CharT __c = *__b;
1641 if (!__ct.is(ctype_base::digit, __c))
1642 {
1643 __err |= ios_base::failbit;
1644 return 0;
1645 }
1646 int __r = __ct.narrow(__c, 0) - '0';
Eric Fiseliera09a3b42014-10-27 19:28:20 +00001647 for (++__b, (void) --__n; __b != __e && __n > 0; ++__b, (void) --__n)
Howard Hinnantc51e1022010-05-11 19:42:16 +00001648 {
1649 // get next digit
1650 __c = *__b;
1651 if (!__ct.is(ctype_base::digit, __c))
1652 return __r;
1653 __r = __r * 10 + __ct.narrow(__c, 0) - '0';
1654 }
1655 if (__b == __e)
1656 __err |= ios_base::eofbit;
1657 return __r;
1658}
1659
Howard Hinnant8331b762013-03-06 23:30:19 +00001660class _LIBCPP_TYPE_VIS time_base
Howard Hinnantc51e1022010-05-11 19:42:16 +00001661{
1662public:
1663 enum dateorder {no_order, dmy, mdy, ymd, ydm};
1664};
1665
1666template <class _CharT>
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +00001667class _LIBCPP_TEMPLATE_VIS __time_get_c_storage
Howard Hinnantc51e1022010-05-11 19:42:16 +00001668{
1669protected:
1670 typedef basic_string<_CharT> string_type;
1671
1672 virtual const string_type* __weeks() const;
1673 virtual const string_type* __months() const;
1674 virtual const string_type* __am_pm() const;
1675 virtual const string_type& __c() const;
1676 virtual const string_type& __r() const;
1677 virtual const string_type& __x() const;
1678 virtual const string_type& __X() const;
Eric Fiselier5eb6efc2015-08-18 19:39:35 +00001679
1680 _LIBCPP_ALWAYS_INLINE
1681 ~__time_get_c_storage() {}
Howard Hinnantc51e1022010-05-11 19:42:16 +00001682};
1683
Eric Fiselierf30c0af2017-05-08 00:29:32 +00001684template <> _LIBCPP_FUNC_VIS const string* __time_get_c_storage<char>::__weeks() const;
1685template <> _LIBCPP_FUNC_VIS const string* __time_get_c_storage<char>::__months() const;
1686template <> _LIBCPP_FUNC_VIS const string* __time_get_c_storage<char>::__am_pm() const;
1687template <> _LIBCPP_FUNC_VIS const string& __time_get_c_storage<char>::__c() const;
1688template <> _LIBCPP_FUNC_VIS const string& __time_get_c_storage<char>::__r() const;
1689template <> _LIBCPP_FUNC_VIS const string& __time_get_c_storage<char>::__x() const;
1690template <> _LIBCPP_FUNC_VIS const string& __time_get_c_storage<char>::__X() const;
1691
1692template <> _LIBCPP_FUNC_VIS const wstring* __time_get_c_storage<wchar_t>::__weeks() const;
1693template <> _LIBCPP_FUNC_VIS const wstring* __time_get_c_storage<wchar_t>::__months() const;
1694template <> _LIBCPP_FUNC_VIS const wstring* __time_get_c_storage<wchar_t>::__am_pm() const;
1695template <> _LIBCPP_FUNC_VIS const wstring& __time_get_c_storage<wchar_t>::__c() const;
1696template <> _LIBCPP_FUNC_VIS const wstring& __time_get_c_storage<wchar_t>::__r() const;
1697template <> _LIBCPP_FUNC_VIS const wstring& __time_get_c_storage<wchar_t>::__x() const;
1698template <> _LIBCPP_FUNC_VIS const wstring& __time_get_c_storage<wchar_t>::__X() const;
1699
Howard Hinnantc51e1022010-05-11 19:42:16 +00001700template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +00001701class _LIBCPP_TEMPLATE_VIS time_get
Howard Hinnantc51e1022010-05-11 19:42:16 +00001702 : public locale::facet,
1703 public time_base,
1704 private __time_get_c_storage<_CharT>
1705{
1706public:
1707 typedef _CharT char_type;
1708 typedef _InputIterator iter_type;
1709 typedef time_base::dateorder dateorder;
1710 typedef basic_string<char_type> string_type;
1711
1712 _LIBCPP_ALWAYS_INLINE
1713 explicit time_get(size_t __refs = 0)
1714 : locale::facet(__refs) {}
1715
1716 _LIBCPP_ALWAYS_INLINE
1717 dateorder date_order() const
1718 {
1719 return this->do_date_order();
1720 }
1721
1722 _LIBCPP_ALWAYS_INLINE
1723 iter_type get_time(iter_type __b, iter_type __e, ios_base& __iob,
1724 ios_base::iostate& __err, tm* __tm) const
1725 {
1726 return do_get_time(__b, __e, __iob, __err, __tm);
1727 }
1728
1729 _LIBCPP_ALWAYS_INLINE
1730 iter_type get_date(iter_type __b, iter_type __e, ios_base& __iob,
1731 ios_base::iostate& __err, tm* __tm) const
1732 {
1733 return do_get_date(__b, __e, __iob, __err, __tm);
1734 }
1735
1736 _LIBCPP_ALWAYS_INLINE
1737 iter_type get_weekday(iter_type __b, iter_type __e, ios_base& __iob,
1738 ios_base::iostate& __err, tm* __tm) const
1739 {
1740 return do_get_weekday(__b, __e, __iob, __err, __tm);
1741 }
1742
1743 _LIBCPP_ALWAYS_INLINE
1744 iter_type get_monthname(iter_type __b, iter_type __e, ios_base& __iob,
1745 ios_base::iostate& __err, tm* __tm) const
1746 {
1747 return do_get_monthname(__b, __e, __iob, __err, __tm);
1748 }
1749
1750 _LIBCPP_ALWAYS_INLINE
1751 iter_type get_year(iter_type __b, iter_type __e, ios_base& __iob,
1752 ios_base::iostate& __err, tm* __tm) const
1753 {
1754 return do_get_year(__b, __e, __iob, __err, __tm);
1755 }
1756
1757 _LIBCPP_ALWAYS_INLINE
1758 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
1759 ios_base::iostate& __err, tm *__tm,
1760 char __fmt, char __mod = 0) const
1761 {
1762 return do_get(__b, __e, __iob, __err, __tm, __fmt, __mod);
1763 }
1764
1765 iter_type get(iter_type __b, iter_type __e, ios_base& __iob,
1766 ios_base::iostate& __err, tm* __tm,
1767 const char_type* __fmtb, const char_type* __fmte) const;
1768
1769 static locale::id id;
1770
1771protected:
Howard Hinnant756c69b2010-09-22 16:48:34 +00001772 _LIBCPP_ALWAYS_INLINE
Howard Hinnantc51e1022010-05-11 19:42:16 +00001773 ~time_get() {}
1774
1775 virtual dateorder do_date_order() const;
1776 virtual iter_type do_get_time(iter_type __b, iter_type __e, ios_base& __iob,
1777 ios_base::iostate& __err, tm* __tm) const;
1778 virtual iter_type do_get_date(iter_type __b, iter_type __e, ios_base& __iob,
1779 ios_base::iostate& __err, tm* __tm) const;
1780 virtual iter_type do_get_weekday(iter_type __b, iter_type __e, ios_base& __iob,
1781 ios_base::iostate& __err, tm* __tm) const;
1782 virtual iter_type do_get_monthname(iter_type __b, iter_type __e, ios_base& __iob,
1783 ios_base::iostate& __err, tm* __tm) const;
1784 virtual iter_type do_get_year(iter_type __b, iter_type __e, ios_base& __iob,
1785 ios_base::iostate& __err, tm* __tm) const;
1786 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob,
1787 ios_base::iostate& __err, tm* __tm,
1788 char __fmt, char __mod) const;
1789private:
1790 void __get_white_space(iter_type& __b, iter_type __e,
1791 ios_base::iostate& __err, const ctype<char_type>& __ct) const;
1792 void __get_percent(iter_type& __b, iter_type __e, ios_base::iostate& __err,
1793 const ctype<char_type>& __ct) const;
1794
1795 void __get_weekdayname(int& __m,
1796 iter_type& __b, iter_type __e,
1797 ios_base::iostate& __err,
1798 const ctype<char_type>& __ct) const;
1799 void __get_monthname(int& __m,
1800 iter_type& __b, iter_type __e,
1801 ios_base::iostate& __err,
1802 const ctype<char_type>& __ct) const;
1803 void __get_day(int& __d,
1804 iter_type& __b, iter_type __e,
1805 ios_base::iostate& __err,
1806 const ctype<char_type>& __ct) const;
1807 void __get_month(int& __m,
1808 iter_type& __b, iter_type __e,
1809 ios_base::iostate& __err,
1810 const ctype<char_type>& __ct) const;
1811 void __get_year(int& __y,
1812 iter_type& __b, iter_type __e,
1813 ios_base::iostate& __err,
1814 const ctype<char_type>& __ct) const;
1815 void __get_year4(int& __y,
1816 iter_type& __b, iter_type __e,
1817 ios_base::iostate& __err,
1818 const ctype<char_type>& __ct) const;
1819 void __get_hour(int& __d,
1820 iter_type& __b, iter_type __e,
1821 ios_base::iostate& __err,
1822 const ctype<char_type>& __ct) const;
1823 void __get_12_hour(int& __h,
1824 iter_type& __b, iter_type __e,
1825 ios_base::iostate& __err,
1826 const ctype<char_type>& __ct) const;
1827 void __get_am_pm(int& __h,
1828 iter_type& __b, iter_type __e,
1829 ios_base::iostate& __err,
1830 const ctype<char_type>& __ct) const;
1831 void __get_minute(int& __m,
1832 iter_type& __b, iter_type __e,
1833 ios_base::iostate& __err,
1834 const ctype<char_type>& __ct) const;
1835 void __get_second(int& __s,
1836 iter_type& __b, iter_type __e,
1837 ios_base::iostate& __err,
1838 const ctype<char_type>& __ct) const;
1839 void __get_weekday(int& __w,
1840 iter_type& __b, iter_type __e,
1841 ios_base::iostate& __err,
1842 const ctype<char_type>& __ct) const;
1843 void __get_day_year_num(int& __w,
1844 iter_type& __b, iter_type __e,
1845 ios_base::iostate& __err,
1846 const ctype<char_type>& __ct) const;
1847};
1848
1849template <class _CharT, class _InputIterator>
1850locale::id
1851time_get<_CharT, _InputIterator>::id;
1852
Alp Tokerb8a95f52014-05-15 11:27:39 +00001853// time_get primitives
Howard Hinnantc51e1022010-05-11 19:42:16 +00001854
1855template <class _CharT, class _InputIterator>
1856void
1857time_get<_CharT, _InputIterator>::__get_weekdayname(int& __w,
1858 iter_type& __b, iter_type __e,
1859 ios_base::iostate& __err,
1860 const ctype<char_type>& __ct) const
1861{
1862 // Note: ignoring case comes from the POSIX strptime spec
1863 const string_type* __wk = this->__weeks();
Howard Hinnant28b24882011-12-01 20:21:04 +00001864 ptrdiff_t __i = __scan_keyword(__b, __e, __wk, __wk+14, __ct, __err, false) - __wk;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001865 if (__i < 14)
1866 __w = __i % 7;
1867}
1868
1869template <class _CharT, class _InputIterator>
1870void
1871time_get<_CharT, _InputIterator>::__get_monthname(int& __m,
1872 iter_type& __b, iter_type __e,
1873 ios_base::iostate& __err,
1874 const ctype<char_type>& __ct) const
1875{
1876 // Note: ignoring case comes from the POSIX strptime spec
1877 const string_type* __month = this->__months();
Howard Hinnant28b24882011-12-01 20:21:04 +00001878 ptrdiff_t __i = __scan_keyword(__b, __e, __month, __month+24, __ct, __err, false) - __month;
Howard Hinnantc51e1022010-05-11 19:42:16 +00001879 if (__i < 24)
1880 __m = __i % 12;
1881}
1882
1883template <class _CharT, class _InputIterator>
1884void
1885time_get<_CharT, _InputIterator>::__get_day(int& __d,
1886 iter_type& __b, iter_type __e,
1887 ios_base::iostate& __err,
1888 const ctype<char_type>& __ct) const
1889{
1890 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
1891 if (!(__err & ios_base::failbit) && 1 <= __t && __t <= 31)
1892 __d = __t;
1893 else
1894 __err |= ios_base::failbit;
1895}
1896
1897template <class _CharT, class _InputIterator>
1898void
1899time_get<_CharT, _InputIterator>::__get_month(int& __m,
1900 iter_type& __b, iter_type __e,
1901 ios_base::iostate& __err,
1902 const ctype<char_type>& __ct) const
1903{
1904 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2) - 1;
1905 if (!(__err & ios_base::failbit) && __t <= 11)
1906 __m = __t;
1907 else
1908 __err |= ios_base::failbit;
1909}
1910
1911template <class _CharT, class _InputIterator>
1912void
1913time_get<_CharT, _InputIterator>::__get_year(int& __y,
1914 iter_type& __b, iter_type __e,
1915 ios_base::iostate& __err,
1916 const ctype<char_type>& __ct) const
1917{
1918 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 4);
1919 if (!(__err & ios_base::failbit))
1920 {
1921 if (__t < 69)
1922 __t += 2000;
1923 else if (69 <= __t && __t <= 99)
1924 __t += 1900;
1925 __y = __t - 1900;
1926 }
1927}
1928
1929template <class _CharT, class _InputIterator>
1930void
1931time_get<_CharT, _InputIterator>::__get_year4(int& __y,
1932 iter_type& __b, iter_type __e,
1933 ios_base::iostate& __err,
1934 const ctype<char_type>& __ct) const
1935{
1936 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 4);
1937 if (!(__err & ios_base::failbit))
1938 __y = __t - 1900;
1939}
1940
1941template <class _CharT, class _InputIterator>
1942void
1943time_get<_CharT, _InputIterator>::__get_hour(int& __h,
1944 iter_type& __b, iter_type __e,
1945 ios_base::iostate& __err,
1946 const ctype<char_type>& __ct) const
1947{
1948 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
1949 if (!(__err & ios_base::failbit) && __t <= 23)
1950 __h = __t;
1951 else
1952 __err |= ios_base::failbit;
1953}
1954
1955template <class _CharT, class _InputIterator>
1956void
1957time_get<_CharT, _InputIterator>::__get_12_hour(int& __h,
1958 iter_type& __b, iter_type __e,
1959 ios_base::iostate& __err,
1960 const ctype<char_type>& __ct) const
1961{
1962 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
1963 if (!(__err & ios_base::failbit) && 1 <= __t && __t <= 12)
1964 __h = __t;
1965 else
1966 __err |= ios_base::failbit;
1967}
1968
1969template <class _CharT, class _InputIterator>
1970void
1971time_get<_CharT, _InputIterator>::__get_minute(int& __m,
1972 iter_type& __b, iter_type __e,
1973 ios_base::iostate& __err,
1974 const ctype<char_type>& __ct) const
1975{
1976 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
1977 if (!(__err & ios_base::failbit) && __t <= 59)
1978 __m = __t;
1979 else
1980 __err |= ios_base::failbit;
1981}
1982
1983template <class _CharT, class _InputIterator>
1984void
1985time_get<_CharT, _InputIterator>::__get_second(int& __s,
1986 iter_type& __b, iter_type __e,
1987 ios_base::iostate& __err,
1988 const ctype<char_type>& __ct) const
1989{
1990 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 2);
1991 if (!(__err & ios_base::failbit) && __t <= 60)
1992 __s = __t;
1993 else
1994 __err |= ios_base::failbit;
1995}
1996
1997template <class _CharT, class _InputIterator>
1998void
1999time_get<_CharT, _InputIterator>::__get_weekday(int& __w,
2000 iter_type& __b, iter_type __e,
2001 ios_base::iostate& __err,
2002 const ctype<char_type>& __ct) const
2003{
2004 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 1);
2005 if (!(__err & ios_base::failbit) && __t <= 6)
2006 __w = __t;
2007 else
2008 __err |= ios_base::failbit;
2009}
2010
2011template <class _CharT, class _InputIterator>
2012void
2013time_get<_CharT, _InputIterator>::__get_day_year_num(int& __d,
2014 iter_type& __b, iter_type __e,
2015 ios_base::iostate& __err,
2016 const ctype<char_type>& __ct) const
2017{
2018 int __t = __get_up_to_n_digits(__b, __e, __err, __ct, 3);
2019 if (!(__err & ios_base::failbit) && __t <= 365)
2020 __d = __t;
2021 else
2022 __err |= ios_base::failbit;
2023}
2024
2025template <class _CharT, class _InputIterator>
2026void
2027time_get<_CharT, _InputIterator>::__get_white_space(iter_type& __b, iter_type __e,
2028 ios_base::iostate& __err,
2029 const ctype<char_type>& __ct) const
2030{
2031 for (; __b != __e && __ct.is(ctype_base::space, *__b); ++__b)
2032 ;
2033 if (__b == __e)
2034 __err |= ios_base::eofbit;
2035}
2036
2037template <class _CharT, class _InputIterator>
2038void
2039time_get<_CharT, _InputIterator>::__get_am_pm(int& __h,
2040 iter_type& __b, iter_type __e,
2041 ios_base::iostate& __err,
2042 const ctype<char_type>& __ct) const
2043{
2044 const string_type* __ap = this->__am_pm();
2045 if (__ap[0].size() + __ap[1].size() == 0)
2046 {
2047 __err |= ios_base::failbit;
2048 return;
2049 }
Howard Hinnant28b24882011-12-01 20:21:04 +00002050 ptrdiff_t __i = __scan_keyword(__b, __e, __ap, __ap+2, __ct, __err, false) - __ap;
Howard Hinnantc51e1022010-05-11 19:42:16 +00002051 if (__i == 0 && __h == 12)
2052 __h = 0;
2053 else if (__i == 1 && __h < 12)
2054 __h += 12;
2055}
2056
2057template <class _CharT, class _InputIterator>
2058void
2059time_get<_CharT, _InputIterator>::__get_percent(iter_type& __b, iter_type __e,
2060 ios_base::iostate& __err,
2061 const ctype<char_type>& __ct) const
2062{
2063 if (__b == __e)
2064 {
2065 __err |= ios_base::eofbit | ios_base::failbit;
2066 return;
2067 }
2068 if (__ct.narrow(*__b, 0) != '%')
2069 __err |= ios_base::failbit;
2070 else if(++__b == __e)
2071 __err |= ios_base::eofbit;
2072}
2073
Alp Tokerb8a95f52014-05-15 11:27:39 +00002074// time_get end primitives
Howard Hinnantc51e1022010-05-11 19:42:16 +00002075
2076template <class _CharT, class _InputIterator>
2077_InputIterator
2078time_get<_CharT, _InputIterator>::get(iter_type __b, iter_type __e,
2079 ios_base& __iob,
2080 ios_base::iostate& __err, tm* __tm,
2081 const char_type* __fmtb, const char_type* __fmte) const
2082{
2083 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2084 __err = ios_base::goodbit;
2085 while (__fmtb != __fmte && __err == ios_base::goodbit)
2086 {
2087 if (__b == __e)
2088 {
2089 __err = ios_base::failbit;
2090 break;
2091 }
2092 if (__ct.narrow(*__fmtb, 0) == '%')
2093 {
2094 if (++__fmtb == __fmte)
2095 {
2096 __err = ios_base::failbit;
2097 break;
2098 }
2099 char __cmd = __ct.narrow(*__fmtb, 0);
2100 char __opt = '\0';
2101 if (__cmd == 'E' || __cmd == '0')
2102 {
2103 if (++__fmtb == __fmte)
2104 {
2105 __err = ios_base::failbit;
2106 break;
2107 }
2108 __opt = __cmd;
2109 __cmd = __ct.narrow(*__fmtb, 0);
2110 }
2111 __b = do_get(__b, __e, __iob, __err, __tm, __cmd, __opt);
2112 ++__fmtb;
2113 }
2114 else if (__ct.is(ctype_base::space, *__fmtb))
2115 {
2116 for (++__fmtb; __fmtb != __fmte && __ct.is(ctype_base::space, *__fmtb); ++__fmtb)
2117 ;
2118 for ( ; __b != __e && __ct.is(ctype_base::space, *__b); ++__b)
2119 ;
2120 }
2121 else if (__ct.toupper(*__b) == __ct.toupper(*__fmtb))
2122 {
2123 ++__b;
2124 ++__fmtb;
2125 }
2126 else
2127 __err = ios_base::failbit;
2128 }
2129 if (__b == __e)
2130 __err |= ios_base::eofbit;
2131 return __b;
2132}
2133
2134template <class _CharT, class _InputIterator>
2135typename time_get<_CharT, _InputIterator>::dateorder
2136time_get<_CharT, _InputIterator>::do_date_order() const
2137{
2138 return mdy;
2139}
2140
2141template <class _CharT, class _InputIterator>
2142_InputIterator
2143time_get<_CharT, _InputIterator>::do_get_time(iter_type __b, iter_type __e,
2144 ios_base& __iob,
2145 ios_base::iostate& __err,
2146 tm* __tm) const
2147{
2148 const char_type __fmt[] = {'%', 'H', ':', '%', 'M', ':', '%', 'S'};
2149 return get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt)/sizeof(__fmt[0]));
2150}
2151
2152template <class _CharT, class _InputIterator>
2153_InputIterator
2154time_get<_CharT, _InputIterator>::do_get_date(iter_type __b, iter_type __e,
2155 ios_base& __iob,
2156 ios_base::iostate& __err,
2157 tm* __tm) const
2158{
Howard Hinnantc51e1022010-05-11 19:42:16 +00002159 const string_type& __fmt = this->__x();
2160 return get(__b, __e, __iob, __err, __tm, __fmt.data(), __fmt.data() + __fmt.size());
2161}
2162
2163template <class _CharT, class _InputIterator>
2164_InputIterator
2165time_get<_CharT, _InputIterator>::do_get_weekday(iter_type __b, iter_type __e,
2166 ios_base& __iob,
2167 ios_base::iostate& __err,
2168 tm* __tm) const
2169{
2170 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2171 __get_weekdayname(__tm->tm_wday, __b, __e, __err, __ct);
2172 return __b;
2173}
2174
2175template <class _CharT, class _InputIterator>
2176_InputIterator
2177time_get<_CharT, _InputIterator>::do_get_monthname(iter_type __b, iter_type __e,
2178 ios_base& __iob,
2179 ios_base::iostate& __err,
2180 tm* __tm) const
2181{
2182 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2183 __get_monthname(__tm->tm_mon, __b, __e, __err, __ct);
2184 return __b;
2185}
2186
2187template <class _CharT, class _InputIterator>
2188_InputIterator
2189time_get<_CharT, _InputIterator>::do_get_year(iter_type __b, iter_type __e,
2190 ios_base& __iob,
2191 ios_base::iostate& __err,
2192 tm* __tm) const
2193{
2194 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2195 __get_year(__tm->tm_year, __b, __e, __err, __ct);
2196 return __b;
2197}
2198
2199template <class _CharT, class _InputIterator>
2200_InputIterator
2201time_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
2202 ios_base& __iob,
2203 ios_base::iostate& __err, tm* __tm,
2204 char __fmt, char) const
2205{
2206 __err = ios_base::goodbit;
2207 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2208 switch (__fmt)
2209 {
2210 case 'a':
2211 case 'A':
2212 __get_weekdayname(__tm->tm_wday, __b, __e, __err, __ct);
2213 break;
2214 case 'b':
2215 case 'B':
2216 case 'h':
2217 __get_monthname(__tm->tm_mon, __b, __e, __err, __ct);
2218 break;
2219 case 'c':
2220 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002221 const string_type& __fm = this->__c();
2222 __b = get(__b, __e, __iob, __err, __tm, __fm.data(), __fm.data() + __fm.size());
Howard Hinnantc51e1022010-05-11 19:42:16 +00002223 }
2224 break;
2225 case 'd':
2226 case 'e':
2227 __get_day(__tm->tm_mday, __b, __e, __err, __ct);
2228 break;
2229 case 'D':
2230 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002231 const char_type __fm[] = {'%', 'm', '/', '%', 'd', '/', '%', 'y'};
2232 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm)/sizeof(__fm[0]));
Howard Hinnantc51e1022010-05-11 19:42:16 +00002233 }
2234 break;
Howard Hinnantf60ff4e2011-04-10 17:54:14 +00002235 case 'F':
2236 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002237 const char_type __fm[] = {'%', 'Y', '-', '%', 'm', '-', '%', 'd'};
2238 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm)/sizeof(__fm[0]));
Howard Hinnantf60ff4e2011-04-10 17:54:14 +00002239 }
2240 break;
Howard Hinnantc51e1022010-05-11 19:42:16 +00002241 case 'H':
2242 __get_hour(__tm->tm_hour, __b, __e, __err, __ct);
2243 break;
2244 case 'I':
2245 __get_12_hour(__tm->tm_hour, __b, __e, __err, __ct);
2246 break;
2247 case 'j':
2248 __get_day_year_num(__tm->tm_yday, __b, __e, __err, __ct);
2249 break;
2250 case 'm':
2251 __get_month(__tm->tm_mon, __b, __e, __err, __ct);
2252 break;
2253 case 'M':
2254 __get_minute(__tm->tm_min, __b, __e, __err, __ct);
2255 break;
2256 case 'n':
2257 case 't':
2258 __get_white_space(__b, __e, __err, __ct);
2259 break;
2260 case 'p':
2261 __get_am_pm(__tm->tm_hour, __b, __e, __err, __ct);
2262 break;
2263 case 'r':
2264 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002265 const char_type __fm[] = {'%', 'I', ':', '%', 'M', ':', '%', 'S', ' ', '%', 'p'};
2266 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm)/sizeof(__fm[0]));
Howard Hinnantc51e1022010-05-11 19:42:16 +00002267 }
2268 break;
2269 case 'R':
2270 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002271 const char_type __fm[] = {'%', 'H', ':', '%', 'M'};
2272 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm)/sizeof(__fm[0]));
Howard Hinnantc51e1022010-05-11 19:42:16 +00002273 }
2274 break;
2275 case 'S':
2276 __get_second(__tm->tm_sec, __b, __e, __err, __ct);
2277 break;
2278 case 'T':
2279 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002280 const char_type __fm[] = {'%', 'H', ':', '%', 'M', ':', '%', 'S'};
2281 __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm)/sizeof(__fm[0]));
Howard Hinnantc51e1022010-05-11 19:42:16 +00002282 }
2283 break;
2284 case 'w':
2285 __get_weekday(__tm->tm_wday, __b, __e, __err, __ct);
2286 break;
2287 case 'x':
2288 return do_get_date(__b, __e, __iob, __err, __tm);
2289 case 'X':
2290 {
Howard Hinnant28b24882011-12-01 20:21:04 +00002291 const string_type& __fm = this->__X();
2292 __b = get(__b, __e, __iob, __err, __tm, __fm.data(), __fm.data() + __fm.size());
Howard Hinnantc51e1022010-05-11 19:42:16 +00002293 }
2294 break;
2295 case 'y':
2296 __get_year(__tm->tm_year, __b, __e, __err, __ct);
2297 break;
2298 case 'Y':
2299 __get_year4(__tm->tm_year, __b, __e, __err, __ct);
2300 break;
2301 case '%':
2302 __get_percent(__b, __e, __err, __ct);
2303 break;
2304 default:
2305 __err |= ios_base::failbit;
2306 }
2307 return __b;
2308}
2309
Eric Fiselier1b57fa82016-09-15 22:27:07 +00002310_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_get<char>)
2311_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_get<wchar_t>)
Howard Hinnantc51e1022010-05-11 19:42:16 +00002312
Howard Hinnanta37d3cf2013-08-12 18:38:34 +00002313class _LIBCPP_TYPE_VIS __time_get
Howard Hinnantc51e1022010-05-11 19:42:16 +00002314{
2315protected:
2316 locale_t __loc_;
2317
2318 __time_get(const char* __nm);
2319 __time_get(const string& __nm);
2320 ~__time_get();
2321};
2322
2323template <class _CharT>
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +00002324class _LIBCPP_TEMPLATE_VIS __time_get_storage
Howard Hinnantc51e1022010-05-11 19:42:16 +00002325 : public __time_get
2326{
2327protected:
2328 typedef basic_string<_CharT> string_type;
2329
2330 string_type __weeks_[14];
2331 string_type __months_[24];
2332 string_type __am_pm_[2];
2333 string_type __c_;
2334 string_type __r_;
2335 string_type __x_;
2336 string_type __X_;
2337
2338 explicit __time_get_storage(const char* __nm);
2339 explicit __time_get_storage(const string& __nm);
2340
2341 _LIBCPP_ALWAYS_INLINE ~__time_get_storage() {}
2342
2343 time_base::dateorder __do_date_order() const;
2344
2345private:
2346 void init(const ctype<_CharT>&);
2347 string_type __analyze(char __fmt, const ctype<_CharT>&);
2348};
2349
2350template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +00002351class _LIBCPP_TEMPLATE_VIS time_get_byname
Howard Hinnantc51e1022010-05-11 19:42:16 +00002352 : public time_get<_CharT, _InputIterator>,
2353 private __time_get_storage<_CharT>
2354{
2355public:
2356 typedef time_base::dateorder dateorder;
2357 typedef _InputIterator iter_type;
2358 typedef _CharT char_type;
2359 typedef basic_string<char_type> string_type;
2360
Howard Hinnant756c69b2010-09-22 16:48:34 +00002361 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002362 explicit time_get_byname(const char* __nm, size_t __refs = 0)
2363 : time_get<_CharT, _InputIterator>(__refs),
2364 __time_get_storage<_CharT>(__nm) {}
Howard Hinnant756c69b2010-09-22 16:48:34 +00002365 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002366 explicit time_get_byname(const string& __nm, size_t __refs = 0)
2367 : time_get<_CharT, _InputIterator>(__refs),
2368 __time_get_storage<_CharT>(__nm) {}
2369
2370protected:
Howard Hinnant756c69b2010-09-22 16:48:34 +00002371 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002372 ~time_get_byname() {}
2373
Howard Hinnant756c69b2010-09-22 16:48:34 +00002374 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002375 virtual dateorder do_date_order() const {return this->__do_date_order();}
2376private:
Howard Hinnant756c69b2010-09-22 16:48:34 +00002377 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002378 virtual const string_type* __weeks() const {return this->__weeks_;}
Howard Hinnant756c69b2010-09-22 16:48:34 +00002379 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002380 virtual const string_type* __months() const {return this->__months_;}
Howard Hinnant756c69b2010-09-22 16:48:34 +00002381 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002382 virtual const string_type* __am_pm() const {return this->__am_pm_;}
Howard Hinnant756c69b2010-09-22 16:48:34 +00002383 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002384 virtual const string_type& __c() const {return this->__c_;}
Howard Hinnant756c69b2010-09-22 16:48:34 +00002385 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002386 virtual const string_type& __r() const {return this->__r_;}
Howard Hinnant756c69b2010-09-22 16:48:34 +00002387 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002388 virtual const string_type& __x() const {return this->__x_;}
Howard Hinnant756c69b2010-09-22 16:48:34 +00002389 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc51e1022010-05-11 19:42:16 +00002390 virtual const string_type& __X() const {return this->__X_;}
2391};
2392
Eric Fiselier1b57fa82016-09-15 22:27:07 +00002393_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_get_byname<char>)
2394_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_get_byname<wchar_t>)
Howard Hinnantc51e1022010-05-11 19:42:16 +00002395
Howard Hinnanta37d3cf2013-08-12 18:38:34 +00002396class _LIBCPP_TYPE_VIS __time_put
Howard Hinnantc51e1022010-05-11 19:42:16 +00002397{
2398 locale_t __loc_;
2399protected:
Howard Hinnant1ab52da2011-09-28 21:05:01 +00002400 _LIBCPP_ALWAYS_INLINE __time_put() : __loc_(_LIBCPP_GET_C_LOCALE) {}
Howard Hinnantc51e1022010-05-11 19:42:16 +00002401 __time_put(const char* __nm);
2402 __time_put(const string& __nm);
2403 ~__time_put();
2404 void __do_put(char* __nb, char*& __ne, const tm* __tm,
2405 char __fmt, char __mod) const;
2406 void __do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
2407 char __fmt, char __mod) const;
2408};
2409
2410template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +00002411class _LIBCPP_TEMPLATE_VIS time_put
Howard Hinnantc51e1022010-05-11 19:42:16 +00002412 : public locale::facet,
2413 private __time_put
2414{
2415public:
2416 typedef _CharT char_type;
2417 typedef _OutputIterator iter_type;
2418
2419 _LIBCPP_ALWAYS_INLINE
2420 explicit time_put(size_t __refs = 0)
2421 : locale::facet(__refs) {}
2422
2423 iter_type put(iter_type __s, ios_base& __iob, char_type __fl, const tm* __tm,
2424 const char_type* __pb, const char_type* __pe) const;
2425
2426 _LIBCPP_ALWAYS_INLINE
2427 iter_type put(iter_type __s, ios_base& __iob, char_type __fl,
2428 const tm* __tm, char __fmt, char __mod = 0) const
2429 {
2430 return do_put(__s, __iob, __fl, __tm, __fmt, __mod);
2431 }
2432
2433 static locale::id id;
2434
2435protected:
Howard Hinnant756c69b2010-09-22 16:48:34 +00002436 _LIBCPP_ALWAYS_INLINE
Howard Hinnantc51e1022010-05-11 19:42:16 +00002437 ~time_put() {}
2438 virtual iter_type do_put(iter_type __s, ios_base&, char_type, const tm* __tm,
2439 char __fmt, char __mod) const;
2440
Howard Hinnant756c69b2010-09-22 16:48:34 +00002441 _LIBCPP_ALWAYS_INLINE
Howard Hinnantc51e1022010-05-11 19:42:16 +00002442 explicit time_put(const char* __nm, size_t __refs)
2443 : locale::facet(__refs),
2444 __time_put(__nm) {}
Howard Hinnant756c69b2010-09-22 16:48:34 +00002445 _LIBCPP_ALWAYS_INLINE
Howard Hinnantc51e1022010-05-11 19:42:16 +00002446 explicit time_put(const string& __nm, size_t __refs)
2447 : locale::facet(__refs),
2448 __time_put(__nm) {}
2449};
2450
2451template <class _CharT, class _OutputIterator>
2452locale::id
2453time_put<_CharT, _OutputIterator>::id;
2454
2455template <class _CharT, class _OutputIterator>
2456_OutputIterator
2457time_put<_CharT, _OutputIterator>::put(iter_type __s, ios_base& __iob,
2458 char_type __fl, const tm* __tm,
2459 const char_type* __pb,
2460 const char_type* __pe) const
2461{
2462 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__iob.getloc());
2463 for (; __pb != __pe; ++__pb)
2464 {
2465 if (__ct.narrow(*__pb, 0) == '%')
2466 {
2467 if (++__pb == __pe)
2468 {
2469 *__s++ = __pb[-1];
2470 break;
2471 }
2472 char __mod = 0;
2473 char __fmt = __ct.narrow(*__pb, 0);
2474 if (__fmt == 'E' || __fmt == 'O')
2475 {
2476 if (++__pb == __pe)
2477 {
2478 *__s++ = __pb[-2];
2479 *__s++ = __pb[-1];
2480 break;
2481 }
2482 __mod = __fmt;
2483 __fmt = __ct.narrow(*__pb, 0);
2484 }
2485 __s = do_put(__s, __iob, __fl, __tm, __fmt, __mod);
2486 }
2487 else
2488 *__s++ = *__pb;
2489 }
2490 return __s;
2491}
2492
2493template <class _CharT, class _OutputIterator>
2494_OutputIterator
Howard Hinnant28b24882011-12-01 20:21:04 +00002495time_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base&,
Howard Hinnantc51e1022010-05-11 19:42:16 +00002496 char_type, const tm* __tm,
2497 char __fmt, char __mod) const
2498{
2499 char_type __nar[100];
2500 char_type* __nb = __nar;
2501 char_type* __ne = __nb + 100;
2502 __do_put(__nb, __ne, __tm, __fmt, __mod);
Howard Hinnantb1ad5a82011-06-30 21:18:19 +00002503 return _VSTD::copy(__nb, __ne, __s);
Howard Hinnantc51e1022010-05-11 19:42:16 +00002504}
2505
Eric Fiselier1b57fa82016-09-15 22:27:07 +00002506_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_put<char>)
2507_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_put<wchar_t>)
Howard Hinnantc51e1022010-05-11 19:42:16 +00002508
2509template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +00002510class _LIBCPP_TEMPLATE_VIS time_put_byname
Howard Hinnantc51e1022010-05-11 19:42:16 +00002511 : public time_put<_CharT, _OutputIterator>
2512{
2513public:
2514 _LIBCPP_ALWAYS_INLINE
2515 explicit time_put_byname(const char* __nm, size_t __refs = 0)
2516 : time_put<_CharT, _OutputIterator>(__nm, __refs) {}
2517
2518 _LIBCPP_ALWAYS_INLINE
2519 explicit time_put_byname(const string& __nm, size_t __refs = 0)
2520 : time_put<_CharT, _OutputIterator>(__nm, __refs) {}
2521
2522protected:
Howard Hinnant756c69b2010-09-22 16:48:34 +00002523 _LIBCPP_ALWAYS_INLINE
Howard Hinnantc51e1022010-05-11 19:42:16 +00002524 ~time_put_byname() {}
2525};
2526
Eric Fiselier1b57fa82016-09-15 22:27:07 +00002527_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_put_byname<char>)
2528_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_put_byname<wchar_t>)
Howard Hinnantc51e1022010-05-11 19:42:16 +00002529
2530// money_base
2531
Howard Hinnant8331b762013-03-06 23:30:19 +00002532class _LIBCPP_TYPE_VIS money_base
Howard Hinnantc51e1022010-05-11 19:42:16 +00002533{
2534public:
2535 enum part {none, space, symbol, sign, value};
2536 struct pattern {char field[4];};
2537
2538 _LIBCPP_ALWAYS_INLINE money_base() {}
2539};
2540
2541// moneypunct
2542
2543template <class _CharT, bool _International = false>
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +00002544class _LIBCPP_TEMPLATE_VIS moneypunct
Howard Hinnantc51e1022010-05-11 19:42:16 +00002545 : public locale::facet,
2546 public money_base
2547{
2548public:
2549 typedef _CharT char_type;
2550 typedef basic_string<char_type> string_type;
2551
Howard Hinnant756c69b2010-09-22 16:48:34 +00002552 _LIBCPP_ALWAYS_INLINE
Howard Hinnantc51e1022010-05-11 19:42:16 +00002553 explicit moneypunct(size_t __refs = 0)
2554 : locale::facet(__refs) {}
2555
2556 _LIBCPP_ALWAYS_INLINE char_type decimal_point() const {return do_decimal_point();}
2557 _LIBCPP_ALWAYS_INLINE char_type thousands_sep() const {return do_thousands_sep();}
2558 _LIBCPP_ALWAYS_INLINE string grouping() const {return do_grouping();}
2559 _LIBCPP_ALWAYS_INLINE string_type curr_symbol() const {return do_curr_symbol();}
2560 _LIBCPP_ALWAYS_INLINE string_type positive_sign() const {return do_positive_sign();}
2561 _LIBCPP_ALWAYS_INLINE string_type negative_sign() const {return do_negative_sign();}
2562 _LIBCPP_ALWAYS_INLINE int frac_digits() const {return do_frac_digits();}
2563 _LIBCPP_ALWAYS_INLINE pattern pos_format() const {return do_pos_format();}
2564 _LIBCPP_ALWAYS_INLINE pattern neg_format() const {return do_neg_format();}
2565
2566 static locale::id id;
2567 static const bool intl = _International;
2568
2569protected:
Howard Hinnant756c69b2010-09-22 16:48:34 +00002570 _LIBCPP_ALWAYS_INLINE
Howard Hinnantc51e1022010-05-11 19:42:16 +00002571 ~moneypunct() {}
2572
2573 virtual char_type do_decimal_point() const {return numeric_limits<char_type>::max();}
2574 virtual char_type do_thousands_sep() const {return numeric_limits<char_type>::max();}
2575 virtual string do_grouping() const {return string();}
2576 virtual string_type do_curr_symbol() const {return string_type();}
2577 virtual string_type do_positive_sign() const {return string_type();}
2578 virtual string_type do_negative_sign() const {return string_type(1, '-');}
2579 virtual int do_frac_digits() const {return 0;}
2580 virtual pattern do_pos_format() const
Howard Hinnantb10e6cf2012-11-06 21:48:33 +00002581 {pattern __p = {{symbol, sign, none, value}}; return __p;}
Howard Hinnantc51e1022010-05-11 19:42:16 +00002582 virtual pattern do_neg_format() const
Howard Hinnantb10e6cf2012-11-06 21:48:33 +00002583 {pattern __p = {{symbol, sign, none, value}}; return __p;}
Howard Hinnantc51e1022010-05-11 19:42:16 +00002584};
2585
2586template <class _CharT, bool _International>
2587locale::id
2588moneypunct<_CharT, _International>::id;
2589
Howard Hinnant2c45cb42012-12-12 21:14:28 +00002590template <class _CharT, bool _International>
2591const bool
2592moneypunct<_CharT, _International>::intl;
2593
Eric Fiselier1b57fa82016-09-15 22:27:07 +00002594_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct<char, false>)
2595_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct<char, true>)
2596_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct<wchar_t, false>)
2597_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct<wchar_t, true>)
Howard Hinnantc51e1022010-05-11 19:42:16 +00002598
2599// moneypunct_byname
2600
2601template <class _CharT, bool _International = false>
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +00002602class _LIBCPP_TEMPLATE_VIS moneypunct_byname
Howard Hinnant756c69b2010-09-22 16:48:34 +00002603 : public moneypunct<_CharT, _International>
Howard Hinnantc51e1022010-05-11 19:42:16 +00002604{
2605public:
2606 typedef money_base::pattern pattern;
2607 typedef _CharT char_type;
2608 typedef basic_string<char_type> string_type;
2609
2610 _LIBCPP_ALWAYS_INLINE
2611 explicit moneypunct_byname(const char* __nm, size_t __refs = 0)
2612 : moneypunct<_CharT, _International>(__refs) {init(__nm);}
2613
2614 _LIBCPP_ALWAYS_INLINE
2615 explicit moneypunct_byname(const string& __nm, size_t __refs = 0)
2616 : moneypunct<_CharT, _International>(__refs) {init(__nm.c_str());}
2617
2618protected:
Howard Hinnant756c69b2010-09-22 16:48:34 +00002619 _LIBCPP_ALWAYS_INLINE
Howard Hinnantc51e1022010-05-11 19:42:16 +00002620 ~moneypunct_byname() {}
2621
2622 virtual char_type do_decimal_point() const {return __decimal_point_;}
2623 virtual char_type do_thousands_sep() const {return __thousands_sep_;}
2624 virtual string do_grouping() const {return __grouping_;}
2625 virtual string_type do_curr_symbol() const {return __curr_symbol_;}
2626 virtual string_type do_positive_sign() const {return __positive_sign_;}
2627 virtual string_type do_negative_sign() const {return __negative_sign_;}
2628 virtual int do_frac_digits() const {return __frac_digits_;}
2629 virtual pattern do_pos_format() const {return __pos_format_;}
2630 virtual pattern do_neg_format() const {return __neg_format_;}
2631
2632private:
2633 char_type __decimal_point_;
2634 char_type __thousands_sep_;
2635 string __grouping_;
2636 string_type __curr_symbol_;
2637 string_type __positive_sign_;
2638 string_type __negative_sign_;
2639 int __frac_digits_;
2640 pattern __pos_format_;
2641 pattern __neg_format_;
2642
2643 void init(const char*);
2644};
2645
Shoaib Meenai094c3d22017-04-03 04:04:24 +00002646template<> _LIBCPP_FUNC_VIS void moneypunct_byname<char, false>::init(const char*);
2647template<> _LIBCPP_FUNC_VIS void moneypunct_byname<char, true>::init(const char*);
2648template<> _LIBCPP_FUNC_VIS void moneypunct_byname<wchar_t, false>::init(const char*);
2649template<> _LIBCPP_FUNC_VIS void moneypunct_byname<wchar_t, true>::init(const char*);
Howard Hinnantc51e1022010-05-11 19:42:16 +00002650
Eric Fiselier1b57fa82016-09-15 22:27:07 +00002651_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct_byname<char, false>)
2652_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct_byname<char, true>)
2653_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct_byname<wchar_t, false>)
2654_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct_byname<wchar_t, true>)
Howard Hinnantc51e1022010-05-11 19:42:16 +00002655
2656// money_get
2657
2658template <class _CharT>
2659class __money_get
2660{
2661protected:
2662 typedef _CharT char_type;
2663 typedef basic_string<char_type> string_type;
2664
2665 _LIBCPP_ALWAYS_INLINE __money_get() {}
2666
2667 static void __gather_info(bool __intl, const locale& __loc,
2668 money_base::pattern& __pat, char_type& __dp,
2669 char_type& __ts, string& __grp,
2670 string_type& __sym, string_type& __psn,
2671 string_type& __nsn, int& __fd);
2672};
2673
2674template <class _CharT>
2675void
2676__money_get<_CharT>::__gather_info(bool __intl, const locale& __loc,
2677 money_base::pattern& __pat, char_type& __dp,
2678 char_type& __ts, string& __grp,
2679 string_type& __sym, string_type& __psn,
2680 string_type& __nsn, int& __fd)
2681{
2682 if (__intl)
2683 {
2684 const moneypunct<char_type, true>& __mp =
2685 use_facet<moneypunct<char_type, true> >(__loc);
2686 __pat = __mp.neg_format();
2687 __nsn = __mp.negative_sign();
2688 __psn = __mp.positive_sign();
2689 __dp = __mp.decimal_point();
2690 __ts = __mp.thousands_sep();
2691 __grp = __mp.grouping();
2692 __sym = __mp.curr_symbol();
2693 __fd = __mp.frac_digits();
2694 }
2695 else
2696 {
2697 const moneypunct<char_type, false>& __mp =
2698 use_facet<moneypunct<char_type, false> >(__loc);
2699 __pat = __mp.neg_format();
2700 __nsn = __mp.negative_sign();
2701 __psn = __mp.positive_sign();
2702 __dp = __mp.decimal_point();
2703 __ts = __mp.thousands_sep();
2704 __grp = __mp.grouping();
2705 __sym = __mp.curr_symbol();
2706 __fd = __mp.frac_digits();
2707 }
2708}
2709
Eric Fiselier1b57fa82016-09-15 22:27:07 +00002710_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __money_get<char>)
2711_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __money_get<wchar_t>)
Howard Hinnantc51e1022010-05-11 19:42:16 +00002712
2713template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +00002714class _LIBCPP_TEMPLATE_VIS money_get
Howard Hinnantc51e1022010-05-11 19:42:16 +00002715 : public locale::facet,
2716 private __money_get<_CharT>
2717{
2718public:
2719 typedef _CharT char_type;
2720 typedef _InputIterator iter_type;
2721 typedef basic_string<char_type> string_type;
2722
2723 _LIBCPP_ALWAYS_INLINE
2724 explicit money_get(size_t __refs = 0)
2725 : locale::facet(__refs) {}
2726
2727 _LIBCPP_ALWAYS_INLINE
2728 iter_type get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob,
2729 ios_base::iostate& __err, long double& __v) const
2730 {
2731 return do_get(__b, __e, __intl, __iob, __err, __v);
2732 }
2733
2734 _LIBCPP_ALWAYS_INLINE
2735 iter_type get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob,
2736 ios_base::iostate& __err, string_type& __v) const
2737 {
2738 return do_get(__b, __e, __intl, __iob, __err, __v);
2739 }
2740
2741 static locale::id id;
2742
2743protected:
2744
Howard Hinnant756c69b2010-09-22 16:48:34 +00002745 _LIBCPP_ALWAYS_INLINE
Howard Hinnantc51e1022010-05-11 19:42:16 +00002746 ~money_get() {}
Howard Hinnant3b6579a2010-08-22 00:02:43 +00002747
Howard Hinnantc51e1022010-05-11 19:42:16 +00002748 virtual iter_type do_get(iter_type __b, iter_type __e, bool __intl,
2749 ios_base& __iob, ios_base::iostate& __err,
2750 long double& __v) const;
2751 virtual iter_type do_get(iter_type __b, iter_type __e, bool __intl,
2752 ios_base& __iob, ios_base::iostate& __err,
2753 string_type& __v) const;
2754
2755private:
2756 static bool __do_get(iter_type& __b, iter_type __e,
2757 bool __intl, const locale& __loc,
2758 ios_base::fmtflags __flags, ios_base::iostate& __err,
2759 bool& __neg, const ctype<char_type>& __ct,
2760 unique_ptr<char_type, void(*)(void*)>& __wb,
2761 char_type*& __wn, char_type* __we);
2762};
2763
2764template <class _CharT, class _InputIterator>
2765locale::id
2766money_get<_CharT, _InputIterator>::id;
2767
Howard Hinnanta37d3cf2013-08-12 18:38:34 +00002768_LIBCPP_FUNC_VIS void __do_nothing(void*);
Howard Hinnantc51e1022010-05-11 19:42:16 +00002769
2770template <class _Tp>
2771_LIBCPP_HIDDEN
2772void
2773__double_or_nothing(unique_ptr<_Tp, void(*)(void*)>& __b, _Tp*& __n, _Tp*& __e)
2774{
2775 bool __owns = __b.get_deleter() != __do_nothing;
Howard Hinnant28b24882011-12-01 20:21:04 +00002776 size_t __cur_cap = static_cast<size_t>(__e-__b.get()) * sizeof(_Tp);
Howard Hinnantc51e1022010-05-11 19:42:16 +00002777 size_t __new_cap = __cur_cap < numeric_limits<size_t>::max() / 2 ?
2778 2 * __cur_cap : numeric_limits<size_t>::max();
Marshall Clow6c9ddc22014-10-27 19:08:10 +00002779 if (__new_cap == 0)
2780 __new_cap = sizeof(_Tp);
Howard Hinnant28b24882011-12-01 20:21:04 +00002781 size_t __n_off = static_cast<size_t>(__n - __b.get());
Howard Hinnantc51e1022010-05-11 19:42:16 +00002782 _Tp* __t = (_Tp*)realloc(__owns ? __b.get() : 0, __new_cap);
2783 if (__t == 0)
2784 __throw_bad_alloc();
2785 if (__owns)
2786 __b.release();
2787 __b = unique_ptr<_Tp, void(*)(void*)>(__t, free);
2788 __new_cap /= sizeof(_Tp);
2789 __n = __b.get() + __n_off;
2790 __e = __b.get() + __new_cap;
2791}
2792
2793// true == success
2794template <class _CharT, class _InputIterator>
2795bool
2796money_get<_CharT, _InputIterator>::__do_get(iter_type& __b, iter_type __e,
2797 bool __intl, const locale& __loc,
2798 ios_base::fmtflags __flags,
2799 ios_base::iostate& __err,
2800 bool& __neg,
2801 const ctype<char_type>& __ct,
2802 unique_ptr<char_type, void(*)(void*)>& __wb,
2803 char_type*& __wn, char_type* __we)
2804{
2805 const unsigned __bz = 100;
2806 unsigned __gbuf[__bz];
2807 unique_ptr<unsigned, void(*)(void*)> __gb(__gbuf, __do_nothing);
2808 unsigned* __gn = __gb.get();
2809 unsigned* __ge = __gn + __bz;
2810 money_base::pattern __pat;
2811 char_type __dp;
2812 char_type __ts;
2813 string __grp;
2814 string_type __sym;
2815 string_type __psn;
2816 string_type __nsn;
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00002817 // Capture the spaces read into money_base::{space,none} so they
2818 // can be compared to initial spaces in __sym.
2819 string_type __spaces;
Howard Hinnantc51e1022010-05-11 19:42:16 +00002820 int __fd;
2821 __money_get<_CharT>::__gather_info(__intl, __loc, __pat, __dp, __ts, __grp,
2822 __sym, __psn, __nsn, __fd);
2823 const string_type* __trailing_sign = 0;
2824 __wn = __wb.get();
2825 for (unsigned __p = 0; __p < 4 && __b != __e; ++__p)
2826 {
2827 switch (__pat.field[__p])
2828 {
2829 case money_base::space:
2830 if (__p != 3)
2831 {
2832 if (__ct.is(ctype_base::space, *__b))
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00002833 __spaces.push_back(*__b++);
Howard Hinnantc51e1022010-05-11 19:42:16 +00002834 else
2835 {
2836 __err |= ios_base::failbit;
2837 return false;
2838 }
2839 }
Eric Fiselier4db80032017-05-05 20:32:26 +00002840 _LIBCPP_FALLTHROUGH();
Howard Hinnantc51e1022010-05-11 19:42:16 +00002841 case money_base::none:
2842 if (__p != 3)
2843 {
2844 while (__b != __e && __ct.is(ctype_base::space, *__b))
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00002845 __spaces.push_back(*__b++);
Howard Hinnantc51e1022010-05-11 19:42:16 +00002846 }
2847 break;
2848 case money_base::sign:
2849 if (__psn.size() + __nsn.size() > 0)
2850 {
2851 if (__psn.size() == 0 || __nsn.size() == 0)
2852 { // sign is optional
2853 if (__psn.size() > 0)
2854 { // __nsn.size() == 0
2855 if (*__b == __psn[0])
2856 {
2857 ++__b;
2858 if (__psn.size() > 1)
2859 __trailing_sign = &__psn;
2860 }
2861 else
2862 __neg = true;
2863 }
2864 else if (*__b == __nsn[0]) // __nsn.size() > 0 && __psn.size() == 0
2865 {
2866 ++__b;
2867 __neg = true;
2868 if (__nsn.size() > 1)
2869 __trailing_sign = &__nsn;
2870 }
2871 }
2872 else // sign is required
2873 {
2874 if (*__b == __psn[0])
2875 {
2876 ++__b;
2877 if (__psn.size() > 1)
2878 __trailing_sign = &__psn;
2879 }
2880 else if (*__b == __nsn[0])
2881 {
2882 ++__b;
2883 __neg = true;
2884 if (__nsn.size() > 1)
2885 __trailing_sign = &__nsn;
2886 }
2887 else
2888 {
2889 __err |= ios_base::failbit;
2890 return false;
2891 }
2892 }
2893 }
2894 break;
2895 case money_base::symbol:
2896 {
2897 bool __more_needed = __trailing_sign ||
2898 (__p < 2) ||
2899 (__p == 2 && __pat.field[3] != static_cast<char>(money_base::none));
Marshall Clowdfcbb432013-10-13 01:02:45 +00002900 bool __sb = (__flags & ios_base::showbase) != 0;
Howard Hinnantc51e1022010-05-11 19:42:16 +00002901 if (__sb || __more_needed)
2902 {
Jeffrey Yasskin6b045fb2012-03-10 18:31:43 +00002903 typename string_type::const_iterator __sym_space_end = __sym.begin();
2904 if (__p > 0 && (__pat.field[__p - 1] == money_base::none ||
2905 __pat.field[__p - 1] == money_base::space)) {
2906 // Match spaces we've already read against spaces at
2907 // the beginning of __sym.
2908 while (__sym_space_end != __sym.end() &&
2909 __ct.is(ctype_base::space, *__sym_space_end))
2910 ++__sym_space_end;
2911 const size_t __num_spaces = __sym_space_end - __sym.begin();
2912 if (__num_spaces > __spaces.size() ||
2913 !equal(__spaces.end() - __num_spaces, __spaces.end(),
2914 __sym.begin())) {
2915 // No match. Put __sym_space_end back at the
2916 // beginning of __sym, which will prevent a
2917 // match in the next loop.
2918 __sym_space_end = __sym.begin();
2919 }
2920 }
2921 typename string_type::const_iterator __sym_curr_char = __sym_space_end;
2922 while (__sym_curr_char != __sym.end() && __b != __e &&
2923 *__b == *__sym_curr_char) {
2924 ++__b;
2925 ++__sym_curr_char;
2926 }
2927 if (__sb && __sym_curr_char != __sym.end())
Howard Hinnantc51e1022010-05-11 19:42:16 +00002928 {
2929 __err |= ios_base::failbit;
2930 return false;
2931 }
2932 }
2933 }
2934 break;
2935 case money_base::value:
2936 {
2937 unsigned __ng = 0;
2938 for (; __b != __e; ++__b)
2939 {
2940 char_type __c = *__b;
2941 if (__ct.is(ctype_base::digit, __c))
2942 {
2943 if (__wn == __we)
2944 __double_or_nothing(__wb, __wn, __we);
2945 *__wn++ = __c;
2946 ++__ng;
2947 }
2948 else if (__grp.size() > 0 && __ng > 0 && __c == __ts)
2949 {
2950 if (__gn == __ge)
2951 __double_or_nothing(__gb, __gn, __ge);
2952 *__gn++ = __ng;
2953 __ng = 0;
2954 }
2955 else
2956 break;
2957 }
2958 if (__gb.get() != __gn && __ng > 0)
2959 {
2960 if (__gn == __ge)
2961 __double_or_nothing(__gb, __gn, __ge);
2962 *__gn++ = __ng;
2963 }
2964 if (__fd > 0)
2965 {
2966 if (__b == __e || *__b != __dp)
2967 {
2968 __err |= ios_base::failbit;
2969 return false;
2970 }
2971 for (++__b; __fd > 0; --__fd, ++__b)
2972 {
2973 if (__b == __e || !__ct.is(ctype_base::digit, *__b))
2974 {
2975 __err |= ios_base::failbit;
2976 return false;
2977 }
2978 if (__wn == __we)
2979 __double_or_nothing(__wb, __wn, __we);
2980 *__wn++ = *__b;
2981 }
2982 }
2983 if (__wn == __wb.get())
2984 {
2985 __err |= ios_base::failbit;
2986 return false;
2987 }
2988 }
2989 break;
2990 }
2991 }
2992 if (__trailing_sign)
2993 {
2994 for (unsigned __i = 1; __i < __trailing_sign->size(); ++__i, ++__b)
2995 {
2996 if (__b == __e || *__b != (*__trailing_sign)[__i])
2997 {
2998 __err |= ios_base::failbit;
2999 return false;
3000 }
3001 }
3002 }
3003 if (__gb.get() != __gn)
3004 {
3005 ios_base::iostate __et = ios_base::goodbit;
3006 __check_grouping(__grp, __gb.get(), __gn, __et);
3007 if (__et)
3008 {
3009 __err |= ios_base::failbit;
3010 return false;
3011 }
3012 }
3013 return true;
3014}
3015
3016template <class _CharT, class _InputIterator>
3017_InputIterator
3018money_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
3019 bool __intl, ios_base& __iob,
3020 ios_base::iostate& __err,
3021 long double& __v) const
3022{
Howard Hinnant28b24882011-12-01 20:21:04 +00003023 const int __bz = 100;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003024 char_type __wbuf[__bz];
3025 unique_ptr<char_type, void(*)(void*)> __wb(__wbuf, __do_nothing);
3026 char_type* __wn;
3027 char_type* __we = __wbuf + __bz;
3028 locale __loc = __iob.getloc();
3029 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3030 bool __neg = false;
3031 if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct,
3032 __wb, __wn, __we))
3033 {
3034 const char __src[] = "0123456789";
3035 char_type __atoms[sizeof(__src)-1];
3036 __ct.widen(__src, __src + (sizeof(__src)-1), __atoms);
3037 char __nbuf[__bz];
3038 char* __nc = __nbuf;
3039 unique_ptr<char, void(*)(void*)> __h(0, free);
3040 if (__wn - __wb.get() > __bz-2)
3041 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003042 __h.reset((char*)malloc(static_cast<size_t>(__wn - __wb.get() + 2)));
Howard Hinnantc51e1022010-05-11 19:42:16 +00003043 if (__h.get() == 0)
3044 __throw_bad_alloc();
3045 __nc = __h.get();
3046 }
3047 if (__neg)
3048 *__nc++ = '-';
3049 for (const char_type* __w = __wb.get(); __w < __wn; ++__w, ++__nc)
Marshall Clow1e68fd42013-03-22 02:14:40 +00003050 *__nc = __src[find(__atoms, _VSTD::end(__atoms), *__w) - __atoms];
Howard Hinnantc51e1022010-05-11 19:42:16 +00003051 *__nc = char();
3052 if (sscanf(__nbuf, "%Lf", &__v) != 1)
3053 __throw_runtime_error("money_get error");
3054 }
3055 if (__b == __e)
3056 __err |= ios_base::eofbit;
3057 return __b;
3058}
3059
3060template <class _CharT, class _InputIterator>
3061_InputIterator
3062money_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e,
3063 bool __intl, ios_base& __iob,
3064 ios_base::iostate& __err,
3065 string_type& __v) const
3066{
Howard Hinnant28b24882011-12-01 20:21:04 +00003067 const int __bz = 100;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003068 char_type __wbuf[__bz];
3069 unique_ptr<char_type, void(*)(void*)> __wb(__wbuf, __do_nothing);
3070 char_type* __wn;
3071 char_type* __we = __wbuf + __bz;
3072 locale __loc = __iob.getloc();
3073 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3074 bool __neg = false;
3075 if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct,
3076 __wb, __wn, __we))
3077 {
3078 __v.clear();
3079 if (__neg)
3080 __v.push_back(__ct.widen('-'));
3081 char_type __z = __ct.widen('0');
3082 char_type* __w;
3083 for (__w = __wb.get(); __w < __wn-1; ++__w)
3084 if (*__w != __z)
3085 break;
3086 __v.append(__w, __wn);
3087 }
3088 if (__b == __e)
3089 __err |= ios_base::eofbit;
3090 return __b;
3091}
3092
Eric Fiselier1b57fa82016-09-15 22:27:07 +00003093_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS money_get<char>)
3094_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS money_get<wchar_t>)
Howard Hinnantc51e1022010-05-11 19:42:16 +00003095
3096// money_put
3097
3098template <class _CharT>
3099class __money_put
3100{
3101protected:
3102 typedef _CharT char_type;
3103 typedef basic_string<char_type> string_type;
3104
3105 _LIBCPP_ALWAYS_INLINE __money_put() {}
3106
3107 static void __gather_info(bool __intl, bool __neg, const locale& __loc,
3108 money_base::pattern& __pat, char_type& __dp,
3109 char_type& __ts, string& __grp,
3110 string_type& __sym, string_type& __sn,
3111 int& __fd);
3112 static void __format(char_type* __mb, char_type*& __mi, char_type*& __me,
3113 ios_base::fmtflags __flags,
3114 const char_type* __db, const char_type* __de,
3115 const ctype<char_type>& __ct, bool __neg,
3116 const money_base::pattern& __pat, char_type __dp,
3117 char_type __ts, const string& __grp,
3118 const string_type& __sym, const string_type& __sn,
3119 int __fd);
3120};
3121
3122template <class _CharT>
3123void
3124__money_put<_CharT>::__gather_info(bool __intl, bool __neg, const locale& __loc,
3125 money_base::pattern& __pat, char_type& __dp,
3126 char_type& __ts, string& __grp,
3127 string_type& __sym, string_type& __sn,
3128 int& __fd)
3129{
3130 if (__intl)
3131 {
3132 const moneypunct<char_type, true>& __mp =
3133 use_facet<moneypunct<char_type, true> >(__loc);
3134 if (__neg)
3135 {
3136 __pat = __mp.neg_format();
3137 __sn = __mp.negative_sign();
3138 }
3139 else
3140 {
3141 __pat = __mp.pos_format();
3142 __sn = __mp.positive_sign();
3143 }
3144 __dp = __mp.decimal_point();
3145 __ts = __mp.thousands_sep();
3146 __grp = __mp.grouping();
3147 __sym = __mp.curr_symbol();
3148 __fd = __mp.frac_digits();
3149 }
3150 else
3151 {
3152 const moneypunct<char_type, false>& __mp =
3153 use_facet<moneypunct<char_type, false> >(__loc);
3154 if (__neg)
3155 {
3156 __pat = __mp.neg_format();
3157 __sn = __mp.negative_sign();
3158 }
3159 else
3160 {
3161 __pat = __mp.pos_format();
3162 __sn = __mp.positive_sign();
3163 }
3164 __dp = __mp.decimal_point();
3165 __ts = __mp.thousands_sep();
3166 __grp = __mp.grouping();
3167 __sym = __mp.curr_symbol();
3168 __fd = __mp.frac_digits();
3169 }
3170}
3171
3172template <class _CharT>
3173void
3174__money_put<_CharT>::__format(char_type* __mb, char_type*& __mi, char_type*& __me,
3175 ios_base::fmtflags __flags,
3176 const char_type* __db, const char_type* __de,
3177 const ctype<char_type>& __ct, bool __neg,
3178 const money_base::pattern& __pat, char_type __dp,
3179 char_type __ts, const string& __grp,
3180 const string_type& __sym, const string_type& __sn,
3181 int __fd)
3182{
3183 __me = __mb;
3184 for (unsigned __p = 0; __p < 4; ++__p)
3185 {
3186 switch (__pat.field[__p])
3187 {
3188 case money_base::none:
3189 __mi = __me;
3190 break;
3191 case money_base::space:
3192 __mi = __me;
3193 *__me++ = __ct.widen(' ');
3194 break;
3195 case money_base::sign:
3196 if (!__sn.empty())
3197 *__me++ = __sn[0];
3198 break;
3199 case money_base::symbol:
3200 if (!__sym.empty() && (__flags & ios_base::showbase))
Howard Hinnantb1ad5a82011-06-30 21:18:19 +00003201 __me = _VSTD::copy(__sym.begin(), __sym.end(), __me);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003202 break;
3203 case money_base::value:
3204 {
3205 // remember start of value so we can reverse it
3206 char_type* __t = __me;
3207 // find beginning of digits
3208 if (__neg)
3209 ++__db;
3210 // find end of digits
3211 const char_type* __d;
3212 for (__d = __db; __d < __de; ++__d)
3213 if (!__ct.is(ctype_base::digit, *__d))
3214 break;
3215 // print fractional part
3216 if (__fd > 0)
3217 {
3218 int __f;
3219 for (__f = __fd; __d > __db && __f > 0; --__f)
3220 *__me++ = *--__d;
3221 char_type __z = __f > 0 ? __ct.widen('0') : char_type();
3222 for (; __f > 0; --__f)
3223 *__me++ = __z;
3224 *__me++ = __dp;
3225 }
3226 // print units part
3227 if (__d == __db)
3228 {
3229 *__me++ = __ct.widen('0');
3230 }
3231 else
3232 {
3233 unsigned __ng = 0;
3234 unsigned __ig = 0;
3235 unsigned __gl = __grp.empty() ? numeric_limits<unsigned>::max()
3236 : static_cast<unsigned>(__grp[__ig]);
3237 while (__d != __db)
3238 {
3239 if (__ng == __gl)
3240 {
3241 *__me++ = __ts;
3242 __ng = 0;
3243 if (++__ig < __grp.size())
3244 __gl = __grp[__ig] == numeric_limits<char>::max() ?
3245 numeric_limits<unsigned>::max() :
3246 static_cast<unsigned>(__grp[__ig]);
3247 }
3248 *__me++ = *--__d;
3249 ++__ng;
3250 }
3251 }
3252 // reverse it
3253 reverse(__t, __me);
3254 }
3255 break;
3256 }
3257 }
3258 // print rest of sign, if any
3259 if (__sn.size() > 1)
Howard Hinnantb1ad5a82011-06-30 21:18:19 +00003260 __me = _VSTD::copy(__sn.begin()+1, __sn.end(), __me);
Howard Hinnantc51e1022010-05-11 19:42:16 +00003261 // set alignment
3262 if ((__flags & ios_base::adjustfield) == ios_base::left)
3263 __mi = __me;
3264 else if ((__flags & ios_base::adjustfield) != ios_base::internal)
3265 __mi = __mb;
3266}
3267
Eric Fiselier1b57fa82016-09-15 22:27:07 +00003268_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __money_put<char>)
3269_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __money_put<wchar_t>)
Howard Hinnantc51e1022010-05-11 19:42:16 +00003270
3271template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +00003272class _LIBCPP_TEMPLATE_VIS money_put
Howard Hinnantc51e1022010-05-11 19:42:16 +00003273 : public locale::facet,
3274 private __money_put<_CharT>
3275{
3276public:
3277 typedef _CharT char_type;
3278 typedef _OutputIterator iter_type;
3279 typedef basic_string<char_type> string_type;
3280
3281 _LIBCPP_ALWAYS_INLINE
3282 explicit money_put(size_t __refs = 0)
3283 : locale::facet(__refs) {}
3284
3285 _LIBCPP_ALWAYS_INLINE
3286 iter_type put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl,
3287 long double __units) const
3288 {
3289 return do_put(__s, __intl, __iob, __fl, __units);
3290 }
3291
3292 _LIBCPP_ALWAYS_INLINE
3293 iter_type put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl,
3294 const string_type& __digits) const
3295 {
3296 return do_put(__s, __intl, __iob, __fl, __digits);
3297 }
3298
3299 static locale::id id;
3300
3301protected:
Howard Hinnant756c69b2010-09-22 16:48:34 +00003302 _LIBCPP_ALWAYS_INLINE
Howard Hinnantc51e1022010-05-11 19:42:16 +00003303 ~money_put() {}
3304
3305 virtual iter_type do_put(iter_type __s, bool __intl, ios_base& __iob,
3306 char_type __fl, long double __units) const;
3307 virtual iter_type do_put(iter_type __s, bool __intl, ios_base& __iob,
3308 char_type __fl, const string_type& __digits) const;
3309};
3310
3311template <class _CharT, class _OutputIterator>
3312locale::id
3313money_put<_CharT, _OutputIterator>::id;
3314
3315template <class _CharT, class _OutputIterator>
3316_OutputIterator
3317money_put<_CharT, _OutputIterator>::do_put(iter_type __s, bool __intl,
3318 ios_base& __iob, char_type __fl,
3319 long double __units) const
3320{
3321 // convert to char
3322 const size_t __bs = 100;
3323 char __buf[__bs];
3324 char* __bb = __buf;
3325 char_type __digits[__bs];
3326 char_type* __db = __digits;
Howard Hinnant28b24882011-12-01 20:21:04 +00003327 size_t __n = static_cast<size_t>(snprintf(__bb, __bs, "%.0Lf", __units));
Howard Hinnantc51e1022010-05-11 19:42:16 +00003328 unique_ptr<char, void(*)(void*)> __hn(0, free);
3329 unique_ptr<char_type, void(*)(void*)> __hd(0, free);
3330 // secure memory for digit storage
3331 if (__n > __bs-1)
3332 {
Ben Craig3756b922016-03-09 15:39:39 +00003333 __n = static_cast<size_t>(__libcpp_asprintf_l(&__bb, _LIBCPP_GET_C_LOCALE, "%.0Lf", __units));
Howard Hinnantc51e1022010-05-11 19:42:16 +00003334 if (__bb == 0)
3335 __throw_bad_alloc();
3336 __hn.reset(__bb);
3337 __hd.reset((char_type*)malloc(__n * sizeof(char_type)));
Howard Hinnant03de6f92012-03-07 20:37:43 +00003338 if (__hd == nullptr)
Howard Hinnantc51e1022010-05-11 19:42:16 +00003339 __throw_bad_alloc();
3340 __db = __hd.get();
3341 }
3342 // gather info
3343 locale __loc = __iob.getloc();
3344 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3345 __ct.widen(__bb, __bb + __n, __db);
3346 bool __neg = __n > 0 && __bb[0] == '-';
3347 money_base::pattern __pat;
3348 char_type __dp;
3349 char_type __ts;
3350 string __grp;
3351 string_type __sym;
3352 string_type __sn;
3353 int __fd;
3354 this->__gather_info(__intl, __neg, __loc, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3355 // secure memory for formatting
3356 char_type __mbuf[__bs];
3357 char_type* __mb = __mbuf;
3358 unique_ptr<char_type, void(*)(void*)> __hw(0, free);
3359 size_t __exn = static_cast<int>(__n) > __fd ?
Howard Hinnant28b24882011-12-01 20:21:04 +00003360 (__n - static_cast<size_t>(__fd)) * 2 + __sn.size() +
3361 __sym.size() + static_cast<size_t>(__fd) + 1
3362 : __sn.size() + __sym.size() + static_cast<size_t>(__fd) + 2;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003363 if (__exn > __bs)
3364 {
3365 __hw.reset((char_type*)malloc(__exn * sizeof(char_type)));
3366 __mb = __hw.get();
3367 if (__mb == 0)
3368 __throw_bad_alloc();
3369 }
3370 // format
3371 char_type* __mi;
3372 char_type* __me;
3373 this->__format(__mb, __mi, __me, __iob.flags(),
3374 __db, __db + __n, __ct,
3375 __neg, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3376 return __pad_and_output(__s, __mb, __mi, __me, __iob, __fl);
3377}
3378
3379template <class _CharT, class _OutputIterator>
3380_OutputIterator
3381money_put<_CharT, _OutputIterator>::do_put(iter_type __s, bool __intl,
3382 ios_base& __iob, char_type __fl,
3383 const string_type& __digits) const
3384{
3385 // gather info
3386 locale __loc = __iob.getloc();
3387 const ctype<char_type>& __ct = use_facet<ctype<char_type> >(__loc);
3388 bool __neg = __digits.size() > 0 && __digits[0] == __ct.widen('-');
3389 money_base::pattern __pat;
3390 char_type __dp;
3391 char_type __ts;
3392 string __grp;
3393 string_type __sym;
3394 string_type __sn;
3395 int __fd;
3396 this->__gather_info(__intl, __neg, __loc, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3397 // secure memory for formatting
3398 char_type __mbuf[100];
3399 char_type* __mb = __mbuf;
3400 unique_ptr<char_type, void(*)(void*)> __h(0, free);
Howard Hinnant28b24882011-12-01 20:21:04 +00003401 size_t __exn = static_cast<int>(__digits.size()) > __fd ?
3402 (__digits.size() - static_cast<size_t>(__fd)) * 2 +
3403 __sn.size() + __sym.size() + static_cast<size_t>(__fd) + 1
3404 : __sn.size() + __sym.size() + static_cast<size_t>(__fd) + 2;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003405 if (__exn > 100)
3406 {
3407 __h.reset((char_type*)malloc(__exn * sizeof(char_type)));
3408 __mb = __h.get();
3409 if (__mb == 0)
3410 __throw_bad_alloc();
3411 }
3412 // format
3413 char_type* __mi;
3414 char_type* __me;
3415 this->__format(__mb, __mi, __me, __iob.flags(),
3416 __digits.data(), __digits.data() + __digits.size(), __ct,
3417 __neg, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
3418 return __pad_and_output(__s, __mb, __mi, __me, __iob, __fl);
3419}
3420
Eric Fiselier1b57fa82016-09-15 22:27:07 +00003421_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS money_put<char>)
3422_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS money_put<wchar_t>)
Howard Hinnantc51e1022010-05-11 19:42:16 +00003423
3424// messages
3425
Howard Hinnant8331b762013-03-06 23:30:19 +00003426class _LIBCPP_TYPE_VIS messages_base
Howard Hinnantc51e1022010-05-11 19:42:16 +00003427{
3428public:
Howard Hinnant2862aeb2011-02-25 00:51:08 +00003429 typedef ptrdiff_t catalog;
Howard Hinnantc51e1022010-05-11 19:42:16 +00003430
3431 _LIBCPP_ALWAYS_INLINE messages_base() {}
3432};
3433
3434template <class _CharT>
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +00003435class _LIBCPP_TEMPLATE_VIS messages
Howard Hinnantc51e1022010-05-11 19:42:16 +00003436 : public locale::facet,
3437 public messages_base
3438{
3439public:
3440 typedef _CharT char_type;
3441 typedef basic_string<_CharT> string_type;
3442
3443 _LIBCPP_ALWAYS_INLINE
3444 explicit messages(size_t __refs = 0)
3445 : locale::facet(__refs) {}
3446
3447 _LIBCPP_ALWAYS_INLINE
3448 catalog open(const basic_string<char>& __nm, const locale& __loc) const
3449 {
3450 return do_open(__nm, __loc);
3451 }
3452
3453 _LIBCPP_ALWAYS_INLINE
3454 string_type get(catalog __c, int __set, int __msgid,
3455 const string_type& __dflt) const
3456 {
3457 return do_get(__c, __set, __msgid, __dflt);
3458 }
3459
3460 _LIBCPP_ALWAYS_INLINE
3461 void close(catalog __c) const
3462 {
3463 do_close(__c);
3464 }
3465
3466 static locale::id id;
3467
3468protected:
Howard Hinnant756c69b2010-09-22 16:48:34 +00003469 _LIBCPP_ALWAYS_INLINE
Howard Hinnantc51e1022010-05-11 19:42:16 +00003470 ~messages() {}
3471
3472 virtual catalog do_open(const basic_string<char>&, const locale&) const;
3473 virtual string_type do_get(catalog, int __set, int __msgid,
3474 const string_type& __dflt) const;
3475 virtual void do_close(catalog) const;
3476};
3477
3478template <class _CharT>
3479locale::id
3480messages<_CharT>::id;
3481
3482template <class _CharT>
3483typename messages<_CharT>::catalog
3484messages<_CharT>::do_open(const basic_string<char>& __nm, const locale&) const
3485{
Ed Schouten118b6032015-03-11 16:39:36 +00003486#ifdef _LIBCPP_HAS_CATOPEN
Howard Hinnant8c2bf6b2011-10-11 16:00:46 +00003487 catalog __cat = (catalog)catopen(__nm.c_str(), NL_CAT_LOCALE);
Howard Hinnant2862aeb2011-02-25 00:51:08 +00003488 if (__cat != -1)
3489 __cat = static_cast<catalog>((static_cast<size_t>(__cat) >> 1));
3490 return __cat;
Ed Schouten118b6032015-03-11 16:39:36 +00003491#else // !_LIBCPP_HAS_CATOPEN
3492 return -1;
3493#endif // _LIBCPP_HAS_CATOPEN
Howard Hinnantc51e1022010-05-11 19:42:16 +00003494}
3495
3496template <class _CharT>
3497typename messages<_CharT>::string_type
3498messages<_CharT>::do_get(catalog __c, int __set, int __msgid,
3499 const string_type& __dflt) const
3500{
Ed Schouten118b6032015-03-11 16:39:36 +00003501#ifdef _LIBCPP_HAS_CATOPEN
Howard Hinnantc51e1022010-05-11 19:42:16 +00003502 string __ndflt;
3503 __narrow_to_utf8<sizeof(char_type)*__CHAR_BIT__>()(back_inserter(__ndflt),
3504 __dflt.c_str(),
3505 __dflt.c_str() + __dflt.size());
Howard Hinnant2862aeb2011-02-25 00:51:08 +00003506 if (__c != -1)
3507 __c <<= 1;
Howard Hinnant8c2bf6b2011-10-11 16:00:46 +00003508 nl_catd __cat = (nl_catd)__c;
Howard Hinnant2862aeb2011-02-25 00:51:08 +00003509 char* __n = catgets(__cat, __set, __msgid, __ndflt.c_str());
Howard Hinnantc51e1022010-05-11 19:42:16 +00003510 string_type __w;
3511 __widen_from_utf8<sizeof(char_type)*__CHAR_BIT__>()(back_inserter(__w),
3512 __n, __n + strlen(__n));
3513 return __w;
Ed Schouten118b6032015-03-11 16:39:36 +00003514#else // !_LIBCPP_HAS_CATOPEN
3515 return __dflt;
3516#endif // _LIBCPP_HAS_CATOPEN
Howard Hinnantc51e1022010-05-11 19:42:16 +00003517}
3518
3519template <class _CharT>
3520void
3521messages<_CharT>::do_close(catalog __c) const
3522{
Ed Schouten118b6032015-03-11 16:39:36 +00003523#ifdef _LIBCPP_HAS_CATOPEN
Howard Hinnant2862aeb2011-02-25 00:51:08 +00003524 if (__c != -1)
3525 __c <<= 1;
Howard Hinnant8c2bf6b2011-10-11 16:00:46 +00003526 nl_catd __cat = (nl_catd)__c;
Howard Hinnant2862aeb2011-02-25 00:51:08 +00003527 catclose(__cat);
Ed Schouten118b6032015-03-11 16:39:36 +00003528#endif // _LIBCPP_HAS_CATOPEN
Howard Hinnantc51e1022010-05-11 19:42:16 +00003529}
3530
Eric Fiselier1b57fa82016-09-15 22:27:07 +00003531_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS messages<char>)
3532_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS messages<wchar_t>)
Howard Hinnantc51e1022010-05-11 19:42:16 +00003533
3534template <class _CharT>
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +00003535class _LIBCPP_TEMPLATE_VIS messages_byname
Howard Hinnantc51e1022010-05-11 19:42:16 +00003536 : public messages<_CharT>
3537{
3538public:
3539 typedef messages_base::catalog catalog;
3540 typedef basic_string<_CharT> string_type;
3541
3542 _LIBCPP_ALWAYS_INLINE
3543 explicit messages_byname(const char*, size_t __refs = 0)
3544 : messages<_CharT>(__refs) {}
3545
3546 _LIBCPP_ALWAYS_INLINE
3547 explicit messages_byname(const string&, size_t __refs = 0)
3548 : messages<_CharT>(__refs) {}
3549
3550protected:
Howard Hinnant756c69b2010-09-22 16:48:34 +00003551 _LIBCPP_ALWAYS_INLINE
Howard Hinnantc51e1022010-05-11 19:42:16 +00003552 ~messages_byname() {}
3553};
3554
Eric Fiselier1b57fa82016-09-15 22:27:07 +00003555_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS messages_byname<char>)
3556_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS messages_byname<wchar_t>)
Howard Hinnantc51e1022010-05-11 19:42:16 +00003557
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003558template<class _Codecvt, class _Elem = wchar_t,
3559 class _Wide_alloc = allocator<_Elem>,
3560 class _Byte_alloc = allocator<char> >
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +00003561class _LIBCPP_TEMPLATE_VIS wstring_convert
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003562{
3563public:
3564 typedef basic_string<char, char_traits<char>, _Byte_alloc> byte_string;
3565 typedef basic_string<_Elem, char_traits<_Elem>, _Wide_alloc> wide_string;
3566 typedef typename _Codecvt::state_type state_type;
3567 typedef typename wide_string::traits_type::int_type int_type;
3568
3569private:
3570 byte_string __byte_err_string_;
3571 wide_string __wide_err_string_;
3572 _Codecvt* __cvtptr_;
3573 state_type __cvtstate_;
3574 size_t __cvtcount_;
3575
3576 wstring_convert(const wstring_convert& __wc);
3577 wstring_convert& operator=(const wstring_convert& __wc);
3578public:
Evgeniy Stepanov2fb1cb62015-11-07 01:22:13 +00003579 _LIBCPP_ALWAYS_INLINE
Marshall Clowccaa0fb2013-08-27 20:18:59 +00003580 _LIBCPP_EXPLICIT_AFTER_CXX11 wstring_convert(_Codecvt* __pcvt = new _Codecvt);
Evgeniy Stepanov2fb1cb62015-11-07 01:22:13 +00003581 _LIBCPP_ALWAYS_INLINE
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003582 wstring_convert(_Codecvt* __pcvt, state_type __state);
Marshall Clowccaa0fb2013-08-27 20:18:59 +00003583 _LIBCPP_EXPLICIT_AFTER_CXX11 wstring_convert(const byte_string& __byte_err,
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003584 const wide_string& __wide_err = wide_string());
Eric Fiselierf07d88c2017-04-19 01:34:08 +00003585#ifndef _LIBCPP_CXX03_LANG
Evgeniy Stepanov2fb1cb62015-11-07 01:22:13 +00003586 _LIBCPP_ALWAYS_INLINE
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003587 wstring_convert(wstring_convert&& __wc);
3588#endif
3589 ~wstring_convert();
3590
Howard Hinnant756c69b2010-09-22 16:48:34 +00003591 _LIBCPP_ALWAYS_INLINE
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003592 wide_string from_bytes(char __byte)
3593 {return from_bytes(&__byte, &__byte+1);}
Howard Hinnant756c69b2010-09-22 16:48:34 +00003594 _LIBCPP_ALWAYS_INLINE
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003595 wide_string from_bytes(const char* __ptr)
3596 {return from_bytes(__ptr, __ptr + char_traits<char>::length(__ptr));}
Howard Hinnant756c69b2010-09-22 16:48:34 +00003597 _LIBCPP_ALWAYS_INLINE
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003598 wide_string from_bytes(const byte_string& __str)
3599 {return from_bytes(__str.data(), __str.data() + __str.size());}
3600 wide_string from_bytes(const char* __first, const char* __last);
3601
Howard Hinnant756c69b2010-09-22 16:48:34 +00003602 _LIBCPP_ALWAYS_INLINE
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003603 byte_string to_bytes(_Elem __wchar)
3604 {return to_bytes(&__wchar, &__wchar+1);}
Howard Hinnant756c69b2010-09-22 16:48:34 +00003605 _LIBCPP_ALWAYS_INLINE
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003606 byte_string to_bytes(const _Elem* __wptr)
3607 {return to_bytes(__wptr, __wptr + char_traits<_Elem>::length(__wptr));}
Howard Hinnant756c69b2010-09-22 16:48:34 +00003608 _LIBCPP_ALWAYS_INLINE
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003609 byte_string to_bytes(const wide_string& __wstr)
3610 {return to_bytes(__wstr.data(), __wstr.data() + __wstr.size());}
3611 byte_string to_bytes(const _Elem* __first, const _Elem* __last);
3612
Howard Hinnant756c69b2010-09-22 16:48:34 +00003613 _LIBCPP_ALWAYS_INLINE
Marshall Clowccaa0fb2013-08-27 20:18:59 +00003614 size_t converted() const _NOEXCEPT {return __cvtcount_;}
Howard Hinnant756c69b2010-09-22 16:48:34 +00003615 _LIBCPP_ALWAYS_INLINE
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003616 state_type state() const {return __cvtstate_;}
3617};
3618
3619template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Evgeniy Stepanov2fb1cb62015-11-07 01:22:13 +00003620inline
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003621wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3622 wstring_convert(_Codecvt* __pcvt)
3623 : __cvtptr_(__pcvt), __cvtstate_(), __cvtcount_(0)
3624{
3625}
3626
3627template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Evgeniy Stepanov2fb1cb62015-11-07 01:22:13 +00003628inline
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003629wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3630 wstring_convert(_Codecvt* __pcvt, state_type __state)
3631 : __cvtptr_(__pcvt), __cvtstate_(__state), __cvtcount_(0)
3632{
3633}
3634
3635template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3636wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3637 wstring_convert(const byte_string& __byte_err, const wide_string& __wide_err)
3638 : __byte_err_string_(__byte_err), __wide_err_string_(__wide_err),
3639 __cvtstate_(), __cvtcount_(0)
3640{
3641 __cvtptr_ = new _Codecvt;
3642}
3643
Eric Fiselierf07d88c2017-04-19 01:34:08 +00003644#ifndef _LIBCPP_CXX03_LANG
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003645
3646template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
Evgeniy Stepanov2fb1cb62015-11-07 01:22:13 +00003647inline
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003648wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3649 wstring_convert(wstring_convert&& __wc)
Howard Hinnantb1ad5a82011-06-30 21:18:19 +00003650 : __byte_err_string_(_VSTD::move(__wc.__byte_err_string_)),
3651 __wide_err_string_(_VSTD::move(__wc.__wide_err_string_)),
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003652 __cvtptr_(__wc.__cvtptr_),
Eric Fiselier35c67232016-06-26 22:56:26 +00003653 __cvtstate_(__wc.__cvtstate_), __cvtcount_(__wc.__cvtcount_)
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003654{
3655 __wc.__cvtptr_ = nullptr;
3656}
3657
Eric Fiselierf07d88c2017-04-19 01:34:08 +00003658#endif // _LIBCPP_CXX03_LANG
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003659
3660template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3661wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::~wstring_convert()
3662{
3663 delete __cvtptr_;
3664}
3665
3666template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3667typename wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::wide_string
3668wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3669 from_bytes(const char* __frm, const char* __frm_end)
3670{
3671 __cvtcount_ = 0;
3672 if (__cvtptr_ != nullptr)
3673 {
3674 wide_string __ws(2*(__frm_end - __frm), _Elem());
Howard Hinnant16d54f22012-07-12 18:07:41 +00003675 if (__frm != __frm_end)
3676 __ws.resize(__ws.capacity());
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003677 codecvt_base::result __r = codecvt_base::ok;
3678 state_type __st = __cvtstate_;
3679 if (__frm != __frm_end)
3680 {
3681 _Elem* __to = &__ws[0];
3682 _Elem* __to_end = __to + __ws.size();
3683 const char* __frm_nxt;
3684 do
3685 {
3686 _Elem* __to_nxt;
3687 __r = __cvtptr_->in(__st, __frm, __frm_end, __frm_nxt,
3688 __to, __to_end, __to_nxt);
3689 __cvtcount_ += __frm_nxt - __frm;
3690 if (__frm_nxt == __frm)
3691 {
3692 __r = codecvt_base::error;
3693 }
3694 else if (__r == codecvt_base::noconv)
3695 {
3696 __ws.resize(__to - &__ws[0]);
3697 // This only gets executed if _Elem is char
3698 __ws.append((const _Elem*)__frm, (const _Elem*)__frm_end);
3699 __frm = __frm_nxt;
3700 __r = codecvt_base::ok;
3701 }
3702 else if (__r == codecvt_base::ok)
3703 {
3704 __ws.resize(__to_nxt - &__ws[0]);
3705 __frm = __frm_nxt;
3706 }
3707 else if (__r == codecvt_base::partial)
3708 {
3709 ptrdiff_t __s = __to_nxt - &__ws[0];
3710 __ws.resize(2 * __s);
3711 __to = &__ws[0] + __s;
3712 __to_end = &__ws[0] + __ws.size();
3713 __frm = __frm_nxt;
3714 }
3715 } while (__r == codecvt_base::partial && __frm_nxt < __frm_end);
3716 }
3717 if (__r == codecvt_base::ok)
3718 return __ws;
3719 }
Marshall Clow8fea1612016-08-25 15:09:01 +00003720
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003721 if (__wide_err_string_.empty())
Marshall Clow8fea1612016-08-25 15:09:01 +00003722 __throw_range_error("wstring_convert: from_bytes error");
3723
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003724 return __wide_err_string_;
3725}
3726
3727template<class _Codecvt, class _Elem, class _Wide_alloc, class _Byte_alloc>
3728typename wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::byte_string
3729wstring_convert<_Codecvt, _Elem, _Wide_alloc, _Byte_alloc>::
3730 to_bytes(const _Elem* __frm, const _Elem* __frm_end)
3731{
3732 __cvtcount_ = 0;
3733 if (__cvtptr_ != nullptr)
3734 {
3735 byte_string __bs(2*(__frm_end - __frm), char());
Howard Hinnant16d54f22012-07-12 18:07:41 +00003736 if (__frm != __frm_end)
3737 __bs.resize(__bs.capacity());
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003738 codecvt_base::result __r = codecvt_base::ok;
3739 state_type __st = __cvtstate_;
3740 if (__frm != __frm_end)
3741 {
3742 char* __to = &__bs[0];
3743 char* __to_end = __to + __bs.size();
3744 const _Elem* __frm_nxt;
3745 do
3746 {
3747 char* __to_nxt;
3748 __r = __cvtptr_->out(__st, __frm, __frm_end, __frm_nxt,
3749 __to, __to_end, __to_nxt);
3750 __cvtcount_ += __frm_nxt - __frm;
3751 if (__frm_nxt == __frm)
3752 {
3753 __r = codecvt_base::error;
3754 }
3755 else if (__r == codecvt_base::noconv)
3756 {
3757 __bs.resize(__to - &__bs[0]);
3758 // This only gets executed if _Elem is char
3759 __bs.append((const char*)__frm, (const char*)__frm_end);
3760 __frm = __frm_nxt;
3761 __r = codecvt_base::ok;
3762 }
3763 else if (__r == codecvt_base::ok)
3764 {
3765 __bs.resize(__to_nxt - &__bs[0]);
3766 __frm = __frm_nxt;
3767 }
3768 else if (__r == codecvt_base::partial)
3769 {
3770 ptrdiff_t __s = __to_nxt - &__bs[0];
3771 __bs.resize(2 * __s);
3772 __to = &__bs[0] + __s;
3773 __to_end = &__bs[0] + __bs.size();
3774 __frm = __frm_nxt;
3775 }
3776 } while (__r == codecvt_base::partial && __frm_nxt < __frm_end);
3777 }
3778 if (__r == codecvt_base::ok)
3779 {
3780 size_t __s = __bs.size();
3781 __bs.resize(__bs.capacity());
3782 char* __to = &__bs[0] + __s;
3783 char* __to_end = __to + __bs.size();
3784 do
3785 {
3786 char* __to_nxt;
3787 __r = __cvtptr_->unshift(__st, __to, __to_end, __to_nxt);
3788 if (__r == codecvt_base::noconv)
3789 {
3790 __bs.resize(__to - &__bs[0]);
3791 __r = codecvt_base::ok;
3792 }
3793 else if (__r == codecvt_base::ok)
3794 {
3795 __bs.resize(__to_nxt - &__bs[0]);
3796 }
3797 else if (__r == codecvt_base::partial)
3798 {
Howard Hinnant28b24882011-12-01 20:21:04 +00003799 ptrdiff_t __sp = __to_nxt - &__bs[0];
3800 __bs.resize(2 * __sp);
3801 __to = &__bs[0] + __sp;
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003802 __to_end = &__bs[0] + __bs.size();
3803 }
3804 } while (__r == codecvt_base::partial);
3805 if (__r == codecvt_base::ok)
3806 return __bs;
3807 }
3808 }
Marshall Clow8fea1612016-08-25 15:09:01 +00003809
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003810 if (__byte_err_string_.empty())
Marshall Clow8fea1612016-08-25 15:09:01 +00003811 __throw_range_error("wstring_convert: to_bytes error");
3812
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003813 return __byte_err_string_;
3814}
3815
3816template <class _Codecvt, class _Elem = wchar_t, class _Tr = char_traits<_Elem> >
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +00003817class _LIBCPP_TEMPLATE_VIS wbuffer_convert
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003818 : public basic_streambuf<_Elem, _Tr>
3819{
3820public:
3821 // types:
3822 typedef _Elem char_type;
3823 typedef _Tr traits_type;
3824 typedef typename traits_type::int_type int_type;
3825 typedef typename traits_type::pos_type pos_type;
3826 typedef typename traits_type::off_type off_type;
3827 typedef typename _Codecvt::state_type state_type;
3828
3829private:
Howard Hinnant0ac182a2010-06-01 20:09:18 +00003830 char* __extbuf_;
3831 const char* __extbufnext_;
3832 const char* __extbufend_;
3833 char __extbuf_min_[8];
3834 size_t __ebs_;
3835 char_type* __intbuf_;
3836 size_t __ibs_;
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003837 streambuf* __bufptr_;
Howard Hinnant0ac182a2010-06-01 20:09:18 +00003838 _Codecvt* __cv_;
3839 state_type __st_;
3840 ios_base::openmode __cm_;
3841 bool __owns_eb_;
3842 bool __owns_ib_;
3843 bool __always_noconv_;
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003844
Howard Hinnant0ac182a2010-06-01 20:09:18 +00003845 wbuffer_convert(const wbuffer_convert&);
3846 wbuffer_convert& operator=(const wbuffer_convert&);
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003847public:
Marshall Clowccaa0fb2013-08-27 20:18:59 +00003848 _LIBCPP_EXPLICIT_AFTER_CXX11 wbuffer_convert(streambuf* __bytebuf = 0,
3849 _Codecvt* __pcvt = new _Codecvt, state_type __state = state_type());
Howard Hinnant0ac182a2010-06-01 20:09:18 +00003850 ~wbuffer_convert();
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003851
Howard Hinnant756c69b2010-09-22 16:48:34 +00003852 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003853 streambuf* rdbuf() const {return __bufptr_;}
Howard Hinnant756c69b2010-09-22 16:48:34 +00003854 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003855 streambuf* rdbuf(streambuf* __bytebuf)
3856 {
3857 streambuf* __r = __bufptr_;
3858 __bufptr_ = __bytebuf;
3859 return __r;
3860 }
3861
Howard Hinnant756c69b2010-09-22 16:48:34 +00003862 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant0ac182a2010-06-01 20:09:18 +00003863 state_type state() const {return __st_;}
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003864
3865protected:
Howard Hinnant0ac182a2010-06-01 20:09:18 +00003866 virtual int_type underflow();
3867 virtual int_type pbackfail(int_type __c = traits_type::eof());
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003868 virtual int_type overflow (int_type __c = traits_type::eof());
Howard Hinnant0ac182a2010-06-01 20:09:18 +00003869 virtual basic_streambuf<char_type, traits_type>* setbuf(char_type* __s,
3870 streamsize __n);
3871 virtual pos_type seekoff(off_type __off, ios_base::seekdir __way,
3872 ios_base::openmode __wch = ios_base::in | ios_base::out);
3873 virtual pos_type seekpos(pos_type __sp,
3874 ios_base::openmode __wch = ios_base::in | ios_base::out);
3875 virtual int sync();
3876
3877private:
3878 bool __read_mode();
3879 void __write_mode();
3880 wbuffer_convert* __close();
Howard Hinnant9dd7e892010-05-31 20:58:54 +00003881};
3882
3883template <class _Codecvt, class _Elem, class _Tr>
Howard Hinnant0ac182a2010-06-01 20:09:18 +00003884wbuffer_convert<_Codecvt, _Elem, _Tr>::
3885 wbuffer_convert(streambuf* __bytebuf, _Codecvt* __pcvt, state_type __state)
3886 : __extbuf_(0),
3887 __extbufnext_(0),
3888 __extbufend_(0),
3889 __ebs_(0),
3890 __intbuf_(0),
3891 __ibs_(0),
3892 __bufptr_(__bytebuf),
3893 __cv_(__pcvt),
3894 __st_(__state),
3895 __cm_(0),
3896 __owns_eb_(false),
3897 __owns_ib_(false),
3898 __always_noconv_(__cv_ ? __cv_->always_noconv() : false)
3899{
3900 setbuf(0, 4096);
3901}
3902
3903template <class _Codecvt, class _Elem, class _Tr>
3904wbuffer_convert<_Codecvt, _Elem, _Tr>::~wbuffer_convert()
3905{
3906 __close();
3907 delete __cv_;
3908 if (__owns_eb_)
3909 delete [] __extbuf_;
3910 if (__owns_ib_)
3911 delete [] __intbuf_;
3912}
3913
3914template <class _Codecvt, class _Elem, class _Tr>
3915typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
3916wbuffer_convert<_Codecvt, _Elem, _Tr>::underflow()
3917{
3918 if (__cv_ == 0 || __bufptr_ == 0)
3919 return traits_type::eof();
3920 bool __initial = __read_mode();
3921 char_type __1buf;
3922 if (this->gptr() == 0)
3923 this->setg(&__1buf, &__1buf+1, &__1buf+1);
3924 const size_t __unget_sz = __initial ? 0 : min<size_t>((this->egptr() - this->eback()) / 2, 4);
3925 int_type __c = traits_type::eof();
3926 if (this->gptr() == this->egptr())
3927 {
3928 memmove(this->eback(), this->egptr() - __unget_sz, __unget_sz * sizeof(char_type));
3929 if (__always_noconv_)
3930 {
3931 streamsize __nmemb = static_cast<streamsize>(this->egptr() - this->eback() - __unget_sz);
3932 __nmemb = __bufptr_->sgetn((char*)this->eback() + __unget_sz, __nmemb);
3933 if (__nmemb != 0)
3934 {
3935 this->setg(this->eback(),
3936 this->eback() + __unget_sz,
3937 this->eback() + __unget_sz + __nmemb);
3938 __c = *this->gptr();
3939 }
3940 }
3941 else
3942 {
Eric Fiselier98e428d2016-06-19 06:58:22 +00003943 _LIBCPP_ASSERT(!(__extbufnext_ == NULL && (__extbufend_ != __extbufnext_)), "underflow moving from NULL" );
3944 if (__extbufend_ != __extbufnext_)
3945 memmove(__extbuf_, __extbufnext_, __extbufend_ - __extbufnext_);
Howard Hinnant0ac182a2010-06-01 20:09:18 +00003946 __extbufnext_ = __extbuf_ + (__extbufend_ - __extbufnext_);
3947 __extbufend_ = __extbuf_ + (__extbuf_ == __extbuf_min_ ? sizeof(__extbuf_min_) : __ebs_);
Howard Hinnantb1ad5a82011-06-30 21:18:19 +00003948 streamsize __nmemb = _VSTD::min(static_cast<streamsize>(this->egptr() - this->eback() - __unget_sz),
Howard Hinnant0ac182a2010-06-01 20:09:18 +00003949 static_cast<streamsize>(__extbufend_ - __extbufnext_));
3950 codecvt_base::result __r;
Eric Fiselier6003c772016-12-23 23:37:52 +00003951 // FIXME: Do we ever need to restore the state here?
3952 //state_type __svs = __st_;
Howard Hinnant0ac182a2010-06-01 20:09:18 +00003953 streamsize __nr = __bufptr_->sgetn(const_cast<char*>(__extbufnext_), __nmemb);
3954 if (__nr != 0)
3955 {
3956 __extbufend_ = __extbufnext_ + __nr;
3957 char_type* __inext;
3958 __r = __cv_->in(__st_, __extbuf_, __extbufend_, __extbufnext_,
3959 this->eback() + __unget_sz,
3960 this->egptr(), __inext);
3961 if (__r == codecvt_base::noconv)
3962 {
Marshall Clowbeda7142017-06-14 20:00:36 +00003963 this->setg((char_type*)__extbuf_, (char_type*)__extbuf_,
3964 (char_type*) const_cast<char *>(__extbufend_));
Howard Hinnant0ac182a2010-06-01 20:09:18 +00003965 __c = *this->gptr();
3966 }
3967 else if (__inext != this->eback() + __unget_sz)
3968 {
3969 this->setg(this->eback(), this->eback() + __unget_sz, __inext);
3970 __c = *this->gptr();
3971 }
3972 }
3973 }
3974 }
3975 else
3976 __c = *this->gptr();
3977 if (this->eback() == &__1buf)
3978 this->setg(0, 0, 0);
3979 return __c;
3980}
3981
3982template <class _Codecvt, class _Elem, class _Tr>
3983typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
3984wbuffer_convert<_Codecvt, _Elem, _Tr>::pbackfail(int_type __c)
3985{
3986 if (__cv_ != 0 && __bufptr_ != 0 && this->eback() < this->gptr())
3987 {
3988 if (traits_type::eq_int_type(__c, traits_type::eof()))
3989 {
3990 this->gbump(-1);
3991 return traits_type::not_eof(__c);
3992 }
3993 if (traits_type::eq(traits_type::to_char_type(__c), this->gptr()[-1]))
3994 {
3995 this->gbump(-1);
3996 *this->gptr() = traits_type::to_char_type(__c);
3997 return __c;
3998 }
3999 }
4000 return traits_type::eof();
4001}
4002
4003template <class _Codecvt, class _Elem, class _Tr>
Howard Hinnant9dd7e892010-05-31 20:58:54 +00004004typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type
4005wbuffer_convert<_Codecvt, _Elem, _Tr>::overflow(int_type __c)
4006{
Howard Hinnant0ac182a2010-06-01 20:09:18 +00004007 if (__cv_ == 0 || __bufptr_ == 0)
4008 return traits_type::eof();
4009 __write_mode();
4010 char_type __1buf;
4011 char_type* __pb_save = this->pbase();
4012 char_type* __epb_save = this->epptr();
4013 if (!traits_type::eq_int_type(__c, traits_type::eof()))
4014 {
4015 if (this->pptr() == 0)
4016 this->setp(&__1buf, &__1buf+1);
4017 *this->pptr() = traits_type::to_char_type(__c);
4018 this->pbump(1);
4019 }
4020 if (this->pptr() != this->pbase())
4021 {
4022 if (__always_noconv_)
4023 {
4024 streamsize __nmemb = static_cast<streamsize>(this->pptr() - this->pbase());
4025 if (__bufptr_->sputn((const char*)this->pbase(), __nmemb) != __nmemb)
4026 return traits_type::eof();
4027 }
4028 else
4029 {
4030 char* __extbe = __extbuf_;
4031 codecvt_base::result __r;
4032 do
4033 {
4034 const char_type* __e;
4035 __r = __cv_->out(__st_, this->pbase(), this->pptr(), __e,
4036 __extbuf_, __extbuf_ + __ebs_, __extbe);
4037 if (__e == this->pbase())
4038 return traits_type::eof();
4039 if (__r == codecvt_base::noconv)
4040 {
4041 streamsize __nmemb = static_cast<size_t>(this->pptr() - this->pbase());
4042 if (__bufptr_->sputn((const char*)this->pbase(), __nmemb) != __nmemb)
4043 return traits_type::eof();
4044 }
4045 else if (__r == codecvt_base::ok || __r == codecvt_base::partial)
4046 {
4047 streamsize __nmemb = static_cast<size_t>(__extbe - __extbuf_);
4048 if (__bufptr_->sputn(__extbuf_, __nmemb) != __nmemb)
4049 return traits_type::eof();
4050 if (__r == codecvt_base::partial)
4051 {
Marshall Clowbeda7142017-06-14 20:00:36 +00004052 this->setp(const_cast<char_type *>(__e), this->pptr());
Howard Hinnant0ac182a2010-06-01 20:09:18 +00004053 this->pbump(this->epptr() - this->pbase());
4054 }
4055 }
4056 else
4057 return traits_type::eof();
4058 } while (__r == codecvt_base::partial);
4059 }
4060 this->setp(__pb_save, __epb_save);
4061 }
4062 return traits_type::not_eof(__c);
4063}
4064
4065template <class _Codecvt, class _Elem, class _Tr>
4066basic_streambuf<_Elem, _Tr>*
4067wbuffer_convert<_Codecvt, _Elem, _Tr>::setbuf(char_type* __s, streamsize __n)
4068{
4069 this->setg(0, 0, 0);
4070 this->setp(0, 0);
4071 if (__owns_eb_)
4072 delete [] __extbuf_;
4073 if (__owns_ib_)
4074 delete [] __intbuf_;
4075 __ebs_ = __n;
4076 if (__ebs_ > sizeof(__extbuf_min_))
4077 {
4078 if (__always_noconv_ && __s)
4079 {
4080 __extbuf_ = (char*)__s;
4081 __owns_eb_ = false;
4082 }
4083 else
4084 {
4085 __extbuf_ = new char[__ebs_];
4086 __owns_eb_ = true;
4087 }
4088 }
4089 else
4090 {
4091 __extbuf_ = __extbuf_min_;
4092 __ebs_ = sizeof(__extbuf_min_);
4093 __owns_eb_ = false;
4094 }
4095 if (!__always_noconv_)
4096 {
4097 __ibs_ = max<streamsize>(__n, sizeof(__extbuf_min_));
4098 if (__s && __ibs_ >= sizeof(__extbuf_min_))
4099 {
4100 __intbuf_ = __s;
4101 __owns_ib_ = false;
4102 }
4103 else
4104 {
4105 __intbuf_ = new char_type[__ibs_];
4106 __owns_ib_ = true;
4107 }
4108 }
4109 else
4110 {
4111 __ibs_ = 0;
4112 __intbuf_ = 0;
4113 __owns_ib_ = false;
4114 }
4115 return this;
4116}
4117
4118template <class _Codecvt, class _Elem, class _Tr>
4119typename wbuffer_convert<_Codecvt, _Elem, _Tr>::pos_type
4120wbuffer_convert<_Codecvt, _Elem, _Tr>::seekoff(off_type __off, ios_base::seekdir __way,
4121 ios_base::openmode __om)
4122{
4123 int __width = __cv_->encoding();
4124 if (__cv_ == 0 || __bufptr_ == 0 || (__width <= 0 && __off != 0) || sync())
4125 return pos_type(off_type(-1));
Marshall Clowc2a72762015-08-27 14:37:22 +00004126 // __width > 0 || __off == 0, now check __way
4127 if (__way != ios_base::beg && __way != ios_base::cur && __way != ios_base::end)
Howard Hinnant0ac182a2010-06-01 20:09:18 +00004128 return pos_type(off_type(-1));
Howard Hinnant0ac182a2010-06-01 20:09:18 +00004129 pos_type __r = __bufptr_->pubseekoff(__width * __off, __way, __om);
4130 __r.state(__st_);
4131 return __r;
4132}
4133
4134template <class _Codecvt, class _Elem, class _Tr>
4135typename wbuffer_convert<_Codecvt, _Elem, _Tr>::pos_type
4136wbuffer_convert<_Codecvt, _Elem, _Tr>::seekpos(pos_type __sp, ios_base::openmode __wch)
4137{
4138 if (__cv_ == 0 || __bufptr_ == 0 || sync())
4139 return pos_type(off_type(-1));
4140 if (__bufptr_->pubseekpos(__sp, __wch) == pos_type(off_type(-1)))
4141 return pos_type(off_type(-1));
4142 return __sp;
4143}
4144
4145template <class _Codecvt, class _Elem, class _Tr>
4146int
4147wbuffer_convert<_Codecvt, _Elem, _Tr>::sync()
4148{
4149 if (__cv_ == 0 || __bufptr_ == 0)
4150 return 0;
4151 if (__cm_ & ios_base::out)
4152 {
4153 if (this->pptr() != this->pbase())
4154 if (overflow() == traits_type::eof())
4155 return -1;
4156 codecvt_base::result __r;
4157 do
4158 {
4159 char* __extbe;
4160 __r = __cv_->unshift(__st_, __extbuf_, __extbuf_ + __ebs_, __extbe);
4161 streamsize __nmemb = static_cast<streamsize>(__extbe - __extbuf_);
4162 if (__bufptr_->sputn(__extbuf_, __nmemb) != __nmemb)
4163 return -1;
4164 } while (__r == codecvt_base::partial);
4165 if (__r == codecvt_base::error)
4166 return -1;
4167 if (__bufptr_->pubsync())
4168 return -1;
4169 }
4170 else if (__cm_ & ios_base::in)
4171 {
4172 off_type __c;
4173 if (__always_noconv_)
4174 __c = this->egptr() - this->gptr();
4175 else
4176 {
4177 int __width = __cv_->encoding();
4178 __c = __extbufend_ - __extbufnext_;
4179 if (__width > 0)
4180 __c += __width * (this->egptr() - this->gptr());
4181 else
4182 {
4183 if (this->gptr() != this->egptr())
4184 {
4185 reverse(this->gptr(), this->egptr());
4186 codecvt_base::result __r;
4187 const char_type* __e = this->gptr();
4188 char* __extbe;
4189 do
4190 {
4191 __r = __cv_->out(__st_, __e, this->egptr(), __e,
4192 __extbuf_, __extbuf_ + __ebs_, __extbe);
4193 switch (__r)
4194 {
4195 case codecvt_base::noconv:
4196 __c += this->egptr() - this->gptr();
4197 break;
4198 case codecvt_base::ok:
4199 case codecvt_base::partial:
4200 __c += __extbe - __extbuf_;
4201 break;
4202 default:
4203 return -1;
4204 }
4205 } while (__r == codecvt_base::partial);
4206 }
4207 }
4208 }
4209 if (__bufptr_->pubseekoff(-__c, ios_base::cur, __cm_) == pos_type(off_type(-1)))
4210 return -1;
4211 this->setg(0, 0, 0);
4212 __cm_ = 0;
4213 }
4214 return 0;
4215}
4216
4217template <class _Codecvt, class _Elem, class _Tr>
4218bool
4219wbuffer_convert<_Codecvt, _Elem, _Tr>::__read_mode()
4220{
4221 if (!(__cm_ & ios_base::in))
4222 {
4223 this->setp(0, 0);
4224 if (__always_noconv_)
4225 this->setg((char_type*)__extbuf_,
4226 (char_type*)__extbuf_ + __ebs_,
4227 (char_type*)__extbuf_ + __ebs_);
4228 else
4229 this->setg(__intbuf_, __intbuf_ + __ibs_, __intbuf_ + __ibs_);
4230 __cm_ = ios_base::in;
4231 return true;
4232 }
4233 return false;
4234}
4235
4236template <class _Codecvt, class _Elem, class _Tr>
4237void
4238wbuffer_convert<_Codecvt, _Elem, _Tr>::__write_mode()
4239{
4240 if (!(__cm_ & ios_base::out))
4241 {
4242 this->setg(0, 0, 0);
4243 if (__ebs_ > sizeof(__extbuf_min_))
4244 {
4245 if (__always_noconv_)
4246 this->setp((char_type*)__extbuf_,
4247 (char_type*)__extbuf_ + (__ebs_ - 1));
4248 else
4249 this->setp(__intbuf_, __intbuf_ + (__ibs_ - 1));
4250 }
4251 else
4252 this->setp(0, 0);
4253 __cm_ = ios_base::out;
4254 }
4255}
4256
4257template <class _Codecvt, class _Elem, class _Tr>
4258wbuffer_convert<_Codecvt, _Elem, _Tr>*
4259wbuffer_convert<_Codecvt, _Elem, _Tr>::__close()
4260{
4261 wbuffer_convert* __rt = 0;
4262 if (__cv_ != 0 && __bufptr_ != 0)
4263 {
4264 __rt = this;
4265 if ((__cm_ & ios_base::out) && sync())
4266 __rt = 0;
4267 }
4268 return __rt;
Howard Hinnant9dd7e892010-05-31 20:58:54 +00004269}
4270
Howard Hinnantc51e1022010-05-11 19:42:16 +00004271_LIBCPP_END_NAMESPACE_STD
4272
Eric Fiselierf4433a32017-05-31 22:07:49 +00004273_LIBCPP_POP_MACROS
4274
Howard Hinnantc51e1022010-05-11 19:42:16 +00004275#endif // _LIBCPP_LOCALE