master
1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef _LIBCPP___LOCALE_DIR_NUM_H
10#define _LIBCPP___LOCALE_DIR_NUM_H
11
12#include <__algorithm/find.h>
13#include <__algorithm/reverse.h>
14#include <__charconv/to_chars_integral.h>
15#include <__charconv/traits.h>
16#include <__config>
17#include <__iterator/istreambuf_iterator.h>
18#include <__iterator/ostreambuf_iterator.h>
19#include <__locale_dir/check_grouping.h>
20#include <__locale_dir/get_c_locale.h>
21#include <__locale_dir/pad_and_output.h>
22#include <__locale_dir/scan_keyword.h>
23#include <__memory/unique_ptr.h>
24#include <__system_error/errc.h>
25#include <cerrno>
26#include <ios>
27#include <streambuf>
28
29#if _LIBCPP_HAS_LOCALIZATION
30
31# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
32# pragma GCC system_header
33# endif
34
35// TODO: Properly qualify calls now that the locale base API defines functions instead of macros
36// NOLINTBEGIN(libcpp-robust-against-adl)
37
38_LIBCPP_PUSH_MACROS
39# include <__undef_macros>
40
41_LIBCPP_BEGIN_NAMESPACE_STD
42
43struct _LIBCPP_EXPORTED_FROM_ABI __num_get_base {
44 static const int __num_get_buf_sz = 40;
45
46 static int __get_base(ios_base&);
47 static const char __src[33]; // "0123456789abcdefABCDEFxX+-pPiInN"
48 // count of leading characters in __src used for parsing integers ("012..X+-")
49 static const size_t __int_chr_cnt = 26;
50 // count of leading characters in __src used for parsing floating-point values ("012..-pP")
51 static const size_t __fp_chr_cnt = 28;
52};
53
54template <class _CharT>
55struct __num_get : protected __num_get_base {
56 static string __stage2_float_prep(ios_base& __iob, _CharT* __atoms, _CharT& __decimal_point, _CharT& __thousands_sep);
57
58 static int __stage2_float_loop(
59 _CharT __ct,
60 bool& __in_units,
61 char& __exp,
62 char* __a,
63 char*& __a_end,
64 _CharT __decimal_point,
65 _CharT __thousands_sep,
66 const string& __grouping,
67 unsigned* __g,
68 unsigned*& __g_end,
69 unsigned& __dc,
70 _CharT* __atoms);
71
72 [[__deprecated__("This exists only for ABI compatibility")]] static string
73 __stage2_int_prep(ios_base& __iob, _CharT* __atoms, _CharT& __thousands_sep);
74 static int __stage2_int_loop(
75 _CharT __ct,
76 int __base,
77 char* __a,
78 char*& __a_end,
79 unsigned& __dc,
80 _CharT __thousands_sep,
81 const string& __grouping,
82 unsigned* __g,
83 unsigned*& __g_end,
84 _CharT* __atoms);
85
86 _LIBCPP_HIDE_FROM_ABI static string __stage2_int_prep(ios_base& __iob, _CharT& __thousands_sep) {
87 locale __loc = __iob.getloc();
88 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
89 __thousands_sep = __np.thousands_sep();
90 return __np.grouping();
91 }
92
93 _LIBCPP_HIDE_FROM_ABI const _CharT* __do_widen(ios_base& __iob, _CharT* __atoms) const {
94 return __do_widen_p(__iob, __atoms);
95 }
96
97private:
98 template <typename _Tp>
99 _LIBCPP_HIDE_FROM_ABI const _Tp* __do_widen_p(ios_base& __iob, _Tp* __atoms) const {
100 locale __loc = __iob.getloc();
101 use_facet<ctype<_Tp> >(__loc).widen(__src, __src + __int_chr_cnt, __atoms);
102 return __atoms;
103 }
104
105 _LIBCPP_HIDE_FROM_ABI const char* __do_widen_p(ios_base& __iob, char* __atoms) const {
106 (void)__iob;
107 (void)__atoms;
108 return __src;
109 }
110};
111
112template <class _CharT>
113string __num_get<_CharT>::__stage2_float_prep(
114 ios_base& __iob, _CharT* __atoms, _CharT& __decimal_point, _CharT& __thousands_sep) {
115 locale __loc = __iob.getloc();
116 std::use_facet<ctype<_CharT> >(__loc).widen(__src, __src + __fp_chr_cnt, __atoms);
117 const numpunct<_CharT>& __np = std::use_facet<numpunct<_CharT> >(__loc);
118 __decimal_point = __np.decimal_point();
119 __thousands_sep = __np.thousands_sep();
120 return __np.grouping();
121}
122
123template <class _CharT>
124int __num_get<_CharT>::__stage2_int_loop(
125 _CharT __ct,
126 int __base,
127 char* __a,
128 char*& __a_end,
129 unsigned& __dc,
130 _CharT __thousands_sep,
131 const string& __grouping,
132 unsigned* __g,
133 unsigned*& __g_end,
134 _CharT* __atoms) {
135 if (__a_end == __a && (__ct == __atoms[24] || __ct == __atoms[25])) {
136 *__a_end++ = __ct == __atoms[24] ? '+' : '-';
137 __dc = 0;
138 return 0;
139 }
140 if (__grouping.size() != 0 && __ct == __thousands_sep) {
141 if (__g_end - __g < __num_get_buf_sz) {
142 *__g_end++ = __dc;
143 __dc = 0;
144 }
145 return 0;
146 }
147 ptrdiff_t __f = std::find(__atoms, __atoms + __int_chr_cnt, __ct) - __atoms;
148 if (__f >= 24)
149 return -1;
150 switch (__base) {
151 case 8:
152 case 10:
153 if (__f >= __base)
154 return -1;
155 break;
156 case 16:
157 if (__f < 22)
158 break;
159 if (__a_end != __a && __a_end - __a <= 2 && __a_end[-1] == '0') {
160 __dc = 0;
161 *__a_end++ = __src[__f];
162 return 0;
163 }
164 return -1;
165 }
166 *__a_end++ = __src[__f];
167 ++__dc;
168 return 0;
169}
170
171template <class _CharT>
172int __num_get<_CharT>::__stage2_float_loop(
173 _CharT __ct,
174 bool& __in_units,
175 char& __exp,
176 char* __a,
177 char*& __a_end,
178 _CharT __decimal_point,
179 _CharT __thousands_sep,
180 const string& __grouping,
181 unsigned* __g,
182 unsigned*& __g_end,
183 unsigned& __dc,
184 _CharT* __atoms) {
185 if (__ct == __decimal_point) {
186 if (!__in_units)
187 return -1;
188 __in_units = false;
189 *__a_end++ = '.';
190 if (__grouping.size() != 0 && __g_end - __g < __num_get_buf_sz)
191 *__g_end++ = __dc;
192 return 0;
193 }
194 if (__ct == __thousands_sep && __grouping.size() != 0) {
195 if (!__in_units)
196 return -1;
197 if (__g_end - __g < __num_get_buf_sz) {
198 *__g_end++ = __dc;
199 __dc = 0;
200 }
201 return 0;
202 }
203 ptrdiff_t __f = std::find(__atoms, __atoms + __num_get_base::__fp_chr_cnt, __ct) - __atoms;
204 if (__f >= static_cast<ptrdiff_t>(__num_get_base::__fp_chr_cnt))
205 return -1;
206 char __x = __src[__f];
207 if (__x == '-' || __x == '+') {
208 if (__a_end == __a || (std::toupper(__a_end[-1]) == std::toupper(__exp))) {
209 *__a_end++ = __x;
210 return 0;
211 }
212 return -1;
213 }
214 if (__x == 'x' || __x == 'X')
215 __exp = 'P';
216 else if (std::toupper(__x) == __exp) {
217 __exp = std::tolower(__exp);
218 if (__in_units) {
219 __in_units = false;
220 if (__grouping.size() != 0 && __g_end - __g < __num_get_buf_sz)
221 *__g_end++ = __dc;
222 }
223 }
224 *__a_end++ = __x;
225 if (__f >= 22)
226 return 0;
227 ++__dc;
228 return 0;
229}
230
231extern template struct _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __num_get<char>;
232# if _LIBCPP_HAS_WIDE_CHARACTERS
233extern template struct _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __num_get<wchar_t>;
234# endif
235
236template <class _Tp>
237_LIBCPP_HIDE_FROM_ABI _Tp __do_strtod(const char* __a, char** __p2);
238
239template <>
240inline _LIBCPP_HIDE_FROM_ABI float __do_strtod<float>(const char* __a, char** __p2) {
241 return __locale::__strtof(__a, __p2, _LIBCPP_GET_C_LOCALE);
242}
243
244template <>
245inline _LIBCPP_HIDE_FROM_ABI double __do_strtod<double>(const char* __a, char** __p2) {
246 return __locale::__strtod(__a, __p2, _LIBCPP_GET_C_LOCALE);
247}
248
249template <>
250inline _LIBCPP_HIDE_FROM_ABI long double __do_strtod<long double>(const char* __a, char** __p2) {
251 return __locale::__strtold(__a, __p2, _LIBCPP_GET_C_LOCALE);
252}
253
254template <class _Tp>
255_LIBCPP_HIDE_FROM_ABI _Tp __num_get_float(const char* __a, const char* __a_end, ios_base::iostate& __err) {
256 if (__a != __a_end) {
257 __libcpp_remove_reference_t<decltype(errno)> __save_errno = errno;
258 errno = 0;
259 char* __p2;
260 _Tp __ld = std::__do_strtod<_Tp>(__a, &__p2);
261 __libcpp_remove_reference_t<decltype(errno)> __current_errno = errno;
262 if (__current_errno == 0)
263 errno = __save_errno;
264 if (__p2 != __a_end) {
265 __err = ios_base::failbit;
266 return 0;
267 } else if (__current_errno == ERANGE)
268 __err = ios_base::failbit;
269 return __ld;
270 }
271 __err = ios_base::failbit;
272 return 0;
273}
274
275template <class _Tp>
276_LIBCPP_HIDE_FROM_ABI _Tp
277__num_get_signed_integral(const char* __a, const char* __a_end, ios_base::iostate& __err, int __base) {
278 if (__a != __a_end) {
279 __libcpp_remove_reference_t<decltype(errno)> __save_errno = errno;
280 errno = 0;
281 char* __p2;
282 long long __ll = __locale::__strtoll(__a, &__p2, __base, _LIBCPP_GET_C_LOCALE);
283 __libcpp_remove_reference_t<decltype(errno)> __current_errno = errno;
284 if (__current_errno == 0)
285 errno = __save_errno;
286 if (__p2 != __a_end) {
287 __err = ios_base::failbit;
288 return 0;
289 } else if (__current_errno == ERANGE || __ll < numeric_limits<_Tp>::min() || numeric_limits<_Tp>::max() < __ll) {
290 __err = ios_base::failbit;
291 if (__ll > 0)
292 return numeric_limits<_Tp>::max();
293 else
294 return numeric_limits<_Tp>::min();
295 }
296 return static_cast<_Tp>(__ll);
297 }
298 __err = ios_base::failbit;
299 return 0;
300}
301
302template <class _Tp>
303_LIBCPP_HIDE_FROM_ABI _Tp
304__num_get_unsigned_integral(const char* __a, const char* __a_end, ios_base::iostate& __err, int __base) {
305 if (__a != __a_end) {
306 const bool __negate = *__a == '-';
307 if (__negate && ++__a == __a_end) {
308 __err = ios_base::failbit;
309 return 0;
310 }
311 __libcpp_remove_reference_t<decltype(errno)> __save_errno = errno;
312 errno = 0;
313 char* __p2;
314 unsigned long long __ll = __locale::__strtoull(__a, &__p2, __base, _LIBCPP_GET_C_LOCALE);
315 __libcpp_remove_reference_t<decltype(errno)> __current_errno = errno;
316 if (__current_errno == 0)
317 errno = __save_errno;
318 if (__p2 != __a_end) {
319 __err = ios_base::failbit;
320 return 0;
321 } else if (__current_errno == ERANGE || numeric_limits<_Tp>::max() < __ll) {
322 __err = ios_base::failbit;
323 return numeric_limits<_Tp>::max();
324 }
325 _Tp __res = static_cast<_Tp>(__ll);
326 if (__negate)
327 __res = -__res;
328 return __res;
329 }
330 __err = ios_base::failbit;
331 return 0;
332}
333
334template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
335class num_get : public locale::facet, private __num_get<_CharT> {
336public:
337 typedef _CharT char_type;
338 typedef _InputIterator iter_type;
339
340 _LIBCPP_HIDE_FROM_ABI explicit num_get(size_t __refs = 0) : locale::facet(__refs) {}
341
342 _LIBCPP_HIDE_FROM_ABI iter_type
343 get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, bool& __v) const {
344 return do_get(__b, __e, __iob, __err, __v);
345 }
346
347 _LIBCPP_HIDE_FROM_ABI iter_type
348 get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, long& __v) const {
349 return do_get(__b, __e, __iob, __err, __v);
350 }
351
352 _LIBCPP_HIDE_FROM_ABI iter_type
353 get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, long long& __v) const {
354 return do_get(__b, __e, __iob, __err, __v);
355 }
356
357 _LIBCPP_HIDE_FROM_ABI iter_type
358 get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, unsigned short& __v) const {
359 return do_get(__b, __e, __iob, __err, __v);
360 }
361
362 _LIBCPP_HIDE_FROM_ABI iter_type
363 get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, unsigned int& __v) const {
364 return do_get(__b, __e, __iob, __err, __v);
365 }
366
367 _LIBCPP_HIDE_FROM_ABI iter_type
368 get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, unsigned long& __v) const {
369 return do_get(__b, __e, __iob, __err, __v);
370 }
371
372 _LIBCPP_HIDE_FROM_ABI iter_type
373 get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, unsigned long long& __v) const {
374 return do_get(__b, __e, __iob, __err, __v);
375 }
376
377 _LIBCPP_HIDE_FROM_ABI iter_type
378 get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, float& __v) const {
379 return do_get(__b, __e, __iob, __err, __v);
380 }
381
382 _LIBCPP_HIDE_FROM_ABI iter_type
383 get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, double& __v) const {
384 return do_get(__b, __e, __iob, __err, __v);
385 }
386
387 _LIBCPP_HIDE_FROM_ABI iter_type
388 get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, long double& __v) const {
389 return do_get(__b, __e, __iob, __err, __v);
390 }
391
392 _LIBCPP_HIDE_FROM_ABI iter_type
393 get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, void*& __v) const {
394 return do_get(__b, __e, __iob, __err, __v);
395 }
396
397 static locale::id id;
398
399protected:
400 _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~num_get() override {}
401
402 template <class _Fp>
403 _LIBCPP_HIDE_FROM_ABI iter_type
404 __do_get_floating_point(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, _Fp& __v) const {
405 // Stage 1, nothing to do
406 // Stage 2
407 char_type __atoms[__num_get_base::__fp_chr_cnt];
408 char_type __decimal_point;
409 char_type __thousands_sep;
410 string __grouping = this->__stage2_float_prep(__iob, __atoms, __decimal_point, __thousands_sep);
411 string __buf;
412 __buf.resize(__buf.capacity());
413 char* __a = &__buf[0];
414 char* __a_end = __a;
415 unsigned __g[__num_get_base::__num_get_buf_sz];
416 unsigned* __g_end = __g;
417 unsigned __dc = 0;
418 bool __in_units = true;
419 char __exp = 'E';
420 bool __is_leading_parsed = false;
421 for (; __b != __e; ++__b) {
422 if (__a_end == __a + __buf.size()) {
423 size_t __tmp = __buf.size();
424 __buf.resize(2 * __buf.size());
425 __buf.resize(__buf.capacity());
426 __a = &__buf[0];
427 __a_end = __a + __tmp;
428 }
429 if (this->__stage2_float_loop(
430 *__b,
431 __in_units,
432 __exp,
433 __a,
434 __a_end,
435 __decimal_point,
436 __thousands_sep,
437 __grouping,
438 __g,
439 __g_end,
440 __dc,
441 __atoms))
442 break;
443
444 // the leading character excluding the sign must be a decimal digit
445 if (!__is_leading_parsed) {
446 if (__a_end - __a >= 1 && __a[0] != '-' && __a[0] != '+') {
447 if (('0' <= __a[0] && __a[0] <= '9') || __a[0] == '.')
448 __is_leading_parsed = true;
449 else
450 break;
451 } else if (__a_end - __a >= 2 && (__a[0] == '-' || __a[0] == '+')) {
452 if (('0' <= __a[1] && __a[1] <= '9') || __a[1] == '.')
453 __is_leading_parsed = true;
454 else
455 break;
456 }
457 }
458 }
459 if (__grouping.size() != 0 && __in_units && __g_end - __g < __num_get_base::__num_get_buf_sz)
460 *__g_end++ = __dc;
461 // Stage 3
462 __v = std::__num_get_float<_Fp>(__a, __a_end, __err);
463 // Digit grouping checked
464 __check_grouping(__grouping, __g, __g_end, __err);
465 // EOF checked
466 if (__b == __e)
467 __err |= ios_base::eofbit;
468 return __b;
469 }
470
471 template <class _Signed>
472 _LIBCPP_HIDE_FROM_ABI iter_type
473 __do_get_signed(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, _Signed& __v) const {
474 // Stage 1
475 int __base = this->__get_base(__iob);
476 // Stage 2
477 char_type __thousands_sep;
478 const int __atoms_size = __num_get_base::__int_chr_cnt;
479 char_type __atoms1[__atoms_size];
480 const char_type* __atoms = this->__do_widen(__iob, __atoms1);
481 string __grouping = this->__stage2_int_prep(__iob, __thousands_sep);
482 string __buf;
483 __buf.resize(__buf.capacity());
484 char* __a = &__buf[0];
485 char* __a_end = __a;
486 unsigned __g[__num_get_base::__num_get_buf_sz];
487 unsigned* __g_end = __g;
488 unsigned __dc = 0;
489 for (; __b != __e; ++__b) {
490 if (__a_end == __a + __buf.size()) {
491 size_t __tmp = __buf.size();
492 __buf.resize(2 * __buf.size());
493 __buf.resize(__buf.capacity());
494 __a = &__buf[0];
495 __a_end = __a + __tmp;
496 }
497 if (this->__stage2_int_loop(
498 *__b,
499 __base,
500 __a,
501 __a_end,
502 __dc,
503 __thousands_sep,
504 __grouping,
505 __g,
506 __g_end,
507 const_cast<char_type*>(__atoms)))
508 break;
509 }
510 if (__grouping.size() != 0 && __g_end - __g < __num_get_base::__num_get_buf_sz)
511 *__g_end++ = __dc;
512 // Stage 3
513 __v = std::__num_get_signed_integral<_Signed>(__a, __a_end, __err, __base);
514 // Digit grouping checked
515 __check_grouping(__grouping, __g, __g_end, __err);
516 // EOF checked
517 if (__b == __e)
518 __err |= ios_base::eofbit;
519 return __b;
520 }
521
522 template <class _Unsigned>
523 _LIBCPP_HIDE_FROM_ABI iter_type
524 __do_get_unsigned(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, _Unsigned& __v) const {
525 // Stage 1
526 int __base = this->__get_base(__iob);
527 // Stage 2
528 char_type __thousands_sep;
529 const int __atoms_size = __num_get_base::__int_chr_cnt;
530 char_type __atoms1[__atoms_size];
531 const char_type* __atoms = this->__do_widen(__iob, __atoms1);
532 string __grouping = this->__stage2_int_prep(__iob, __thousands_sep);
533 string __buf;
534 __buf.resize(__buf.capacity());
535 char* __a = &__buf[0];
536 char* __a_end = __a;
537 unsigned __g[__num_get_base::__num_get_buf_sz];
538 unsigned* __g_end = __g;
539 unsigned __dc = 0;
540 for (; __b != __e; ++__b) {
541 if (__a_end == __a + __buf.size()) {
542 size_t __tmp = __buf.size();
543 __buf.resize(2 * __buf.size());
544 __buf.resize(__buf.capacity());
545 __a = &__buf[0];
546 __a_end = __a + __tmp;
547 }
548 if (this->__stage2_int_loop(
549 *__b,
550 __base,
551 __a,
552 __a_end,
553 __dc,
554 __thousands_sep,
555 __grouping,
556 __g,
557 __g_end,
558 const_cast<char_type*>(__atoms)))
559 break;
560 }
561 if (__grouping.size() != 0 && __g_end - __g < __num_get_base::__num_get_buf_sz)
562 *__g_end++ = __dc;
563 // Stage 3
564 __v = std::__num_get_unsigned_integral<_Unsigned>(__a, __a_end, __err, __base);
565 // Digit grouping checked
566 __check_grouping(__grouping, __g, __g_end, __err);
567 // EOF checked
568 if (__b == __e)
569 __err |= ios_base::eofbit;
570 return __b;
571 }
572
573 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, bool& __v) const;
574
575 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, long& __v) const {
576 return this->__do_get_signed(__b, __e, __iob, __err, __v);
577 }
578
579 virtual iter_type
580 do_get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, long long& __v) const {
581 return this->__do_get_signed(__b, __e, __iob, __err, __v);
582 }
583
584 virtual iter_type
585 do_get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, unsigned short& __v) const {
586 return this->__do_get_unsigned(__b, __e, __iob, __err, __v);
587 }
588
589 virtual iter_type
590 do_get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, unsigned int& __v) const {
591 return this->__do_get_unsigned(__b, __e, __iob, __err, __v);
592 }
593
594 virtual iter_type
595 do_get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, unsigned long& __v) const {
596 return this->__do_get_unsigned(__b, __e, __iob, __err, __v);
597 }
598
599 virtual iter_type
600 do_get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, unsigned long long& __v) const {
601 return this->__do_get_unsigned(__b, __e, __iob, __err, __v);
602 }
603
604 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, float& __v) const {
605 return this->__do_get_floating_point(__b, __e, __iob, __err, __v);
606 }
607
608 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, double& __v) const {
609 return this->__do_get_floating_point(__b, __e, __iob, __err, __v);
610 }
611
612 virtual iter_type
613 do_get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, long double& __v) const {
614 return this->__do_get_floating_point(__b, __e, __iob, __err, __v);
615 }
616
617 virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, void*& __v) const;
618};
619
620template <class _CharT, class _InputIterator>
621locale::id num_get<_CharT, _InputIterator>::id;
622
623template <class _CharT, class _InputIterator>
624_InputIterator num_get<_CharT, _InputIterator>::do_get(
625 iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, bool& __v) const {
626 if ((__iob.flags() & ios_base::boolalpha) == 0) {
627 long __lv = -1;
628 __b = do_get(__b, __e, __iob, __err, __lv);
629 switch (__lv) {
630 case 0:
631 __v = false;
632 break;
633 case 1:
634 __v = true;
635 break;
636 default:
637 __v = true;
638 __err = ios_base::failbit;
639 break;
640 }
641 return __b;
642 }
643 const ctype<_CharT>& __ct = std::use_facet<ctype<_CharT> >(__iob.getloc());
644 const numpunct<_CharT>& __np = std::use_facet<numpunct<_CharT> >(__iob.getloc());
645 typedef typename numpunct<_CharT>::string_type string_type;
646 const string_type __names[2] = {__np.truename(), __np.falsename()};
647 const string_type* __i = std::__scan_keyword(__b, __e, __names, __names + 2, __ct, __err);
648 __v = __i == __names;
649 return __b;
650}
651
652template <class _CharT, class _InputIterator>
653_InputIterator num_get<_CharT, _InputIterator>::do_get(
654 iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, void*& __v) const {
655 // Stage 1
656 int __base = 16;
657 // Stage 2
658 char_type __atoms[__num_get_base::__int_chr_cnt];
659 char_type __thousands_sep = char_type();
660 string __grouping;
661 std::use_facet<ctype<_CharT> >(__iob.getloc())
662 .widen(__num_get_base::__src, __num_get_base::__src + __num_get_base::__int_chr_cnt, __atoms);
663 string __buf;
664 __buf.resize(__buf.capacity());
665 char* __a = &__buf[0];
666 char* __a_end = __a;
667 unsigned __g[__num_get_base::__num_get_buf_sz];
668 unsigned* __g_end = __g;
669 unsigned __dc = 0;
670 for (; __b != __e; ++__b) {
671 if (__a_end == __a + __buf.size()) {
672 size_t __tmp = __buf.size();
673 __buf.resize(2 * __buf.size());
674 __buf.resize(__buf.capacity());
675 __a = &__buf[0];
676 __a_end = __a + __tmp;
677 }
678 if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc, __thousands_sep, __grouping, __g, __g_end, __atoms))
679 break;
680 }
681 // Stage 3
682 __buf.resize(__a_end - __a);
683 if (__locale::__sscanf(__buf.c_str(), _LIBCPP_GET_C_LOCALE, "%p", &__v) != 1)
684 __err = ios_base::failbit;
685 // EOF checked
686 if (__b == __e)
687 __err |= ios_base::eofbit;
688 return __b;
689}
690
691extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS num_get<char>;
692# if _LIBCPP_HAS_WIDE_CHARACTERS
693extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS num_get<wchar_t>;
694# endif
695
696struct _LIBCPP_EXPORTED_FROM_ABI __num_put_base {
697protected:
698 static void __format_int(char* __fmt, const char* __len, bool __signd, ios_base::fmtflags __flags);
699 static bool __format_float(char* __fmt, const char* __len, ios_base::fmtflags __flags);
700 static char* __identify_padding(char* __nb, char* __ne, const ios_base& __iob);
701};
702
703template <class _CharT>
704struct __num_put : protected __num_put_base {
705 static void __widen_and_group_int(
706 char* __nb, char* __np, char* __ne, _CharT* __ob, _CharT*& __op, _CharT*& __oe, const locale& __loc);
707 static void __widen_and_group_float(
708 char* __nb, char* __np, char* __ne, _CharT* __ob, _CharT*& __op, _CharT*& __oe, const locale& __loc);
709};
710
711template <class _CharT>
712void __num_put<_CharT>::__widen_and_group_int(
713 char* __nb, char* __np, char* __ne, _CharT* __ob, _CharT*& __op, _CharT*& __oe, const locale& __loc) {
714 const ctype<_CharT>& __ct = std::use_facet<ctype<_CharT> >(__loc);
715 const numpunct<_CharT>& __npt = std::use_facet<numpunct<_CharT> >(__loc);
716 string __grouping = __npt.grouping();
717 if (__grouping.empty()) {
718 __ct.widen(__nb, __ne, __ob);
719 __oe = __ob + (__ne - __nb);
720 } else {
721 __oe = __ob;
722 char* __nf = __nb;
723 if (*__nf == '-' || *__nf == '+')
724 *__oe++ = __ct.widen(*__nf++);
725 if (__ne - __nf >= 2 && __nf[0] == '0' && (__nf[1] == 'x' || __nf[1] == 'X')) {
726 *__oe++ = __ct.widen(*__nf++);
727 *__oe++ = __ct.widen(*__nf++);
728 }
729 std::reverse(__nf, __ne);
730 _CharT __thousands_sep = __npt.thousands_sep();
731 unsigned __dc = 0;
732 unsigned __dg = 0;
733 for (char* __p = __nf; __p < __ne; ++__p) {
734 if (static_cast<unsigned>(__grouping[__dg]) > 0 && __dc == static_cast<unsigned>(__grouping[__dg])) {
735 *__oe++ = __thousands_sep;
736 __dc = 0;
737 if (__dg < __grouping.size() - 1)
738 ++__dg;
739 }
740 *__oe++ = __ct.widen(*__p);
741 ++__dc;
742 }
743 std::reverse(__ob + (__nf - __nb), __oe);
744 }
745 if (__np == __ne)
746 __op = __oe;
747 else
748 __op = __ob + (__np - __nb);
749}
750
751template <class _CharT>
752void __num_put<_CharT>::__widen_and_group_float(
753 char* __nb, char* __np, char* __ne, _CharT* __ob, _CharT*& __op, _CharT*& __oe, const locale& __loc) {
754 const ctype<_CharT>& __ct = std::use_facet<ctype<_CharT> >(__loc);
755 const numpunct<_CharT>& __npt = std::use_facet<numpunct<_CharT> >(__loc);
756 string __grouping = __npt.grouping();
757 __oe = __ob;
758 char* __nf = __nb;
759 if (*__nf == '-' || *__nf == '+')
760 *__oe++ = __ct.widen(*__nf++);
761 char* __ns;
762 if (__ne - __nf >= 2 && __nf[0] == '0' && (__nf[1] == 'x' || __nf[1] == 'X')) {
763 *__oe++ = __ct.widen(*__nf++);
764 *__oe++ = __ct.widen(*__nf++);
765 for (__ns = __nf; __ns < __ne; ++__ns)
766 if (!__locale::__isxdigit(*__ns, _LIBCPP_GET_C_LOCALE))
767 break;
768 } else {
769 for (__ns = __nf; __ns < __ne; ++__ns)
770 if (!__locale::__isdigit(*__ns, _LIBCPP_GET_C_LOCALE))
771 break;
772 }
773 if (__grouping.empty()) {
774 __ct.widen(__nf, __ns, __oe);
775 __oe += __ns - __nf;
776 } else {
777 std::reverse(__nf, __ns);
778 _CharT __thousands_sep = __npt.thousands_sep();
779 unsigned __dc = 0;
780 unsigned __dg = 0;
781 for (char* __p = __nf; __p < __ns; ++__p) {
782 if (__grouping[__dg] > 0 && __dc == static_cast<unsigned>(__grouping[__dg])) {
783 *__oe++ = __thousands_sep;
784 __dc = 0;
785 if (__dg < __grouping.size() - 1)
786 ++__dg;
787 }
788 *__oe++ = __ct.widen(*__p);
789 ++__dc;
790 }
791 std::reverse(__ob + (__nf - __nb), __oe);
792 }
793 for (__nf = __ns; __nf < __ne; ++__nf) {
794 if (*__nf == '.') {
795 *__oe++ = __npt.decimal_point();
796 ++__nf;
797 break;
798 } else
799 *__oe++ = __ct.widen(*__nf);
800 }
801 __ct.widen(__nf, __ne, __oe);
802 __oe += __ne - __nf;
803 if (__np == __ne)
804 __op = __oe;
805 else
806 __op = __ob + (__np - __nb);
807}
808
809extern template struct _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __num_put<char>;
810# if _LIBCPP_HAS_WIDE_CHARACTERS
811extern template struct _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __num_put<wchar_t>;
812# endif
813
814template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
815class num_put : public locale::facet, private __num_put<_CharT> {
816public:
817 typedef _CharT char_type;
818 typedef _OutputIterator iter_type;
819
820 _LIBCPP_HIDE_FROM_ABI explicit num_put(size_t __refs = 0) : locale::facet(__refs) {}
821
822 _LIBCPP_HIDE_FROM_ABI iter_type put(iter_type __s, ios_base& __iob, char_type __fl, bool __v) const {
823 return do_put(__s, __iob, __fl, __v);
824 }
825
826 _LIBCPP_HIDE_FROM_ABI iter_type put(iter_type __s, ios_base& __iob, char_type __fl, long __v) const {
827 return do_put(__s, __iob, __fl, __v);
828 }
829
830 _LIBCPP_HIDE_FROM_ABI iter_type put(iter_type __s, ios_base& __iob, char_type __fl, long long __v) const {
831 return do_put(__s, __iob, __fl, __v);
832 }
833
834 _LIBCPP_HIDE_FROM_ABI iter_type put(iter_type __s, ios_base& __iob, char_type __fl, unsigned long __v) const {
835 return do_put(__s, __iob, __fl, __v);
836 }
837
838 _LIBCPP_HIDE_FROM_ABI iter_type put(iter_type __s, ios_base& __iob, char_type __fl, unsigned long long __v) const {
839 return do_put(__s, __iob, __fl, __v);
840 }
841
842 _LIBCPP_HIDE_FROM_ABI iter_type put(iter_type __s, ios_base& __iob, char_type __fl, double __v) const {
843 return do_put(__s, __iob, __fl, __v);
844 }
845
846 _LIBCPP_HIDE_FROM_ABI iter_type put(iter_type __s, ios_base& __iob, char_type __fl, long double __v) const {
847 return do_put(__s, __iob, __fl, __v);
848 }
849
850 _LIBCPP_HIDE_FROM_ABI iter_type put(iter_type __s, ios_base& __iob, char_type __fl, const void* __v) const {
851 return do_put(__s, __iob, __fl, __v);
852 }
853
854 static locale::id id;
855
856protected:
857 _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~num_put() override {}
858
859 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl, bool __v) const;
860 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl, long __v) const;
861 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl, long long __v) const;
862 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl, unsigned long) const;
863 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl, unsigned long long) const;
864 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl, double __v) const;
865 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl, long double __v) const;
866 virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl, const void* __v) const;
867
868 template <class _Integral>
869 _LIBCPP_HIDE_FROM_ABI inline _OutputIterator
870 __do_put_integral(iter_type __s, ios_base& __iob, char_type __fl, _Integral __v) const;
871
872 template <class _Float>
873 _LIBCPP_HIDE_FROM_ABI inline _OutputIterator
874 __do_put_floating_point(iter_type __s, ios_base& __iob, char_type __fl, _Float __v, char const* __len) const;
875};
876
877template <class _CharT, class _OutputIterator>
878locale::id num_put<_CharT, _OutputIterator>::id;
879
880template <class _CharT, class _OutputIterator>
881_OutputIterator
882num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob, char_type __fl, bool __v) const {
883 if ((__iob.flags() & ios_base::boolalpha) == 0)
884 return do_put(__s, __iob, __fl, (unsigned long)__v);
885 const numpunct<char_type>& __np = std::use_facet<numpunct<char_type> >(__iob.getloc());
886 typedef typename numpunct<char_type>::string_type string_type;
887 string_type __nm = __v ? __np.truename() : __np.falsename();
888 for (typename string_type::iterator __i = __nm.begin(); __i != __nm.end(); ++__i, ++__s)
889 *__s = *__i;
890 return __s;
891}
892
893template <class _CharT, class _OutputIterator>
894template <class _Integral>
895_LIBCPP_HIDE_FROM_ABI inline _OutputIterator num_put<_CharT, _OutputIterator>::__do_put_integral(
896 iter_type __s, ios_base& __iob, char_type __fl, _Integral __v) const {
897 // Stage 1 - Get number in narrow char
898
899 // Worst case is octal, with showbase enabled. Note that octal is always
900 // printed as an unsigned value.
901 using _Unsigned = typename make_unsigned<_Integral>::type;
902 _LIBCPP_CONSTEXPR const unsigned __buffer_size =
903 (numeric_limits<_Unsigned>::digits / 3) // 1 char per 3 bits
904 + ((numeric_limits<_Unsigned>::digits % 3) != 0) // round up
905 + 2; // base prefix + terminating null character
906
907 char __char_buffer[__buffer_size];
908 char* __buffer_ptr = __char_buffer;
909
910 auto __flags = __iob.flags();
911
912 auto __basefield = (__flags & ios_base::basefield);
913
914 // Extract base
915 int __base = 10;
916 if (__basefield == ios_base::oct)
917 __base = 8;
918 else if (__basefield == ios_base::hex)
919 __base = 16;
920
921 // Print '-' and make the argument unsigned
922 auto __uval = std::__to_unsigned_like(__v);
923 if (__basefield != ios_base::oct && __basefield != ios_base::hex && __v < 0) {
924 *__buffer_ptr++ = '-';
925 __uval = std::__complement(__uval);
926 }
927
928 // Maybe add '+' prefix
929 if (std::is_signed<_Integral>::value && (__flags & ios_base::showpos) && __basefield != ios_base::oct &&
930 __basefield != ios_base::hex && __v >= 0)
931 *__buffer_ptr++ = '+';
932
933 // Add base prefix
934 if (__v != 0 && __flags & ios_base::showbase) {
935 if (__basefield == ios_base::oct) {
936 *__buffer_ptr++ = '0';
937 } else if (__basefield == ios_base::hex) {
938 *__buffer_ptr++ = '0';
939 *__buffer_ptr++ = (__flags & ios_base::uppercase ? 'X' : 'x');
940 }
941 }
942
943 auto __res = std::__to_chars_integral(__buffer_ptr, __char_buffer + __buffer_size, __uval, __base);
944 _LIBCPP_ASSERT_INTERNAL(__res.__ec == std::errc(0), "to_chars: invalid maximum buffer size computed?");
945
946 // Make letters uppercase
947 if (__flags & ios_base::hex && __flags & ios_base::uppercase) {
948 for (; __buffer_ptr != __res.__ptr; ++__buffer_ptr)
949 *__buffer_ptr = std::__hex_to_upper(*__buffer_ptr);
950 }
951
952 char* __np = this->__identify_padding(__char_buffer, __res.__ptr, __iob);
953 // Stage 2 - Widen __nar while adding thousands separators
954 char_type __o[2 * (__buffer_size - 1) - 1];
955 char_type* __op; // pad here
956 char_type* __oe; // end of output
957 this->__widen_and_group_int(__char_buffer, __np, __res.__ptr, __o, __op, __oe, __iob.getloc());
958 // [__o, __oe) contains thousands_sep'd wide number
959 // Stage 3 & 4
960 return std::__pad_and_output(__s, __o, __op, __oe, __iob, __fl);
961}
962
963template <class _CharT, class _OutputIterator>
964_OutputIterator
965num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob, char_type __fl, long __v) const {
966 return this->__do_put_integral(__s, __iob, __fl, __v);
967}
968
969template <class _CharT, class _OutputIterator>
970_OutputIterator
971num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob, char_type __fl, long long __v) const {
972 return this->__do_put_integral(__s, __iob, __fl, __v);
973}
974
975template <class _CharT, class _OutputIterator>
976_OutputIterator
977num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob, char_type __fl, unsigned long __v) const {
978 return this->__do_put_integral(__s, __iob, __fl, __v);
979}
980
981template <class _CharT, class _OutputIterator>
982_OutputIterator
983num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob, char_type __fl, unsigned long long __v) const {
984 return this->__do_put_integral(__s, __iob, __fl, __v);
985}
986
987template <class _CharT, class _OutputIterator>
988template <class _Float>
989_LIBCPP_HIDE_FROM_ABI inline _OutputIterator num_put<_CharT, _OutputIterator>::__do_put_floating_point(
990 iter_type __s, ios_base& __iob, char_type __fl, _Float __v, char const* __len) const {
991 // Stage 1 - Get number in narrow char
992 char __fmt[8] = {'%', 0};
993 bool __specify_precision = this->__format_float(__fmt + 1, __len, __iob.flags());
994 const unsigned __nbuf = 30;
995 char __nar[__nbuf];
996 char* __nb = __nar;
997 int __nc;
998 _LIBCPP_DIAGNOSTIC_PUSH
999 _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wformat-nonliteral")
1000 _LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wformat-nonliteral")
1001 if (__specify_precision)
1002 __nc = __locale::__snprintf(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt, (int)__iob.precision(), __v);
1003 else
1004 __nc = __locale::__snprintf(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt, __v);
1005 unique_ptr<char, void (*)(void*)> __nbh(nullptr, free);
1006 if (__nc > static_cast<int>(__nbuf - 1)) {
1007 if (__specify_precision)
1008 __nc = __locale::__asprintf(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, (int)__iob.precision(), __v);
1009 else
1010 __nc = __locale::__asprintf(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, __v);
1011 if (__nc == -1)
1012 std::__throw_bad_alloc();
1013 __nbh.reset(__nb);
1014 }
1015 _LIBCPP_DIAGNOSTIC_POP
1016 char* __ne = __nb + __nc;
1017 char* __np = this->__identify_padding(__nb, __ne, __iob);
1018 // Stage 2 - Widen __nar while adding thousands separators
1019 char_type __o[2 * (__nbuf - 1) - 1];
1020 char_type* __ob = __o;
1021 unique_ptr<char_type, void (*)(void*)> __obh(0, free);
1022 if (__nb != __nar) {
1023 __ob = (char_type*)malloc(2 * static_cast<size_t>(__nc) * sizeof(char_type));
1024 if (__ob == 0)
1025 std::__throw_bad_alloc();
1026 __obh.reset(__ob);
1027 }
1028 char_type* __op; // pad here
1029 char_type* __oe; // end of output
1030 this->__widen_and_group_float(__nb, __np, __ne, __ob, __op, __oe, __iob.getloc());
1031 // [__o, __oe) contains thousands_sep'd wide number
1032 // Stage 3 & 4
1033 __s = std::__pad_and_output(__s, __ob, __op, __oe, __iob, __fl);
1034 return __s;
1035}
1036
1037template <class _CharT, class _OutputIterator>
1038_OutputIterator
1039num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob, char_type __fl, double __v) const {
1040 return this->__do_put_floating_point(__s, __iob, __fl, __v, "");
1041}
1042
1043template <class _CharT, class _OutputIterator>
1044_OutputIterator
1045num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob, char_type __fl, long double __v) const {
1046 return this->__do_put_floating_point(__s, __iob, __fl, __v, "L");
1047}
1048
1049template <class _CharT, class _OutputIterator>
1050_OutputIterator
1051num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob, char_type __fl, const void* __v) const {
1052 auto __flags = __iob.flags();
1053 __iob.flags((__flags & ~ios_base::basefield & ~ios_base::uppercase) | ios_base::hex | ios_base::showbase);
1054 auto __res = __do_put_integral(__s, __iob, __fl, reinterpret_cast<uintptr_t>(__v));
1055 __iob.flags(__flags);
1056 return __res;
1057}
1058
1059extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS num_put<char>;
1060# if _LIBCPP_HAS_WIDE_CHARACTERS
1061extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS num_put<wchar_t>;
1062# endif
1063
1064_LIBCPP_END_NAMESPACE_STD
1065
1066_LIBCPP_POP_MACROS
1067
1068// NOLINTEND(libcpp-robust-against-adl)
1069
1070#endif // _LIBCPP_HAS_LOCALIZATION
1071
1072#endif // _LIBCPP___LOCALE_DIR_NUM_H