Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/libcxx/include/__locale_dir/num.h
213766 views
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
43
struct _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
54
template <class _CharT>
55
struct __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
97
private:
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
112
template <class _CharT>
113
string __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
123
template <class _CharT>
124
int __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
171
template <class _CharT>
172
int __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
231
extern template struct _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __num_get<char>;
232
# if _LIBCPP_HAS_WIDE_CHARACTERS
233
extern template struct _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __num_get<wchar_t>;
234
# endif
235
236
template <class _Tp>
237
_LIBCPP_HIDE_FROM_ABI _Tp __do_strtod(const char* __a, char** __p2);
238
239
template <>
240
inline _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
244
template <>
245
inline _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
249
template <>
250
inline _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
254
template <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
275
template <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
302
template <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
334
template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
335
class num_get : public locale::facet, private __num_get<_CharT> {
336
public:
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
399
protected:
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
620
template <class _CharT, class _InputIterator>
621
locale::id num_get<_CharT, _InputIterator>::id;
622
623
template <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
652
template <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
691
extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS num_get<char>;
692
# if _LIBCPP_HAS_WIDE_CHARACTERS
693
extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS num_get<wchar_t>;
694
# endif
695
696
struct _LIBCPP_EXPORTED_FROM_ABI __num_put_base {
697
protected:
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
703
template <class _CharT>
704
struct __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
711
template <class _CharT>
712
void __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
751
template <class _CharT>
752
void __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
809
extern template struct _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __num_put<char>;
810
# if _LIBCPP_HAS_WIDE_CHARACTERS
811
extern template struct _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __num_put<wchar_t>;
812
# endif
813
814
template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
815
class num_put : public locale::facet, private __num_put<_CharT> {
816
public:
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
856
protected:
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
877
template <class _CharT, class _OutputIterator>
878
locale::id num_put<_CharT, _OutputIterator>::id;
879
880
template <class _CharT, class _OutputIterator>
881
_OutputIterator
882
num_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
893
template <class _CharT, class _OutputIterator>
894
template <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
963
template <class _CharT, class _OutputIterator>
964
_OutputIterator
965
num_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
969
template <class _CharT, class _OutputIterator>
970
_OutputIterator
971
num_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
975
template <class _CharT, class _OutputIterator>
976
_OutputIterator
977
num_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
981
template <class _CharT, class _OutputIterator>
982
_OutputIterator
983
num_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
987
template <class _CharT, class _OutputIterator>
988
template <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
1037
template <class _CharT, class _OutputIterator>
1038
_OutputIterator
1039
num_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
1043
template <class _CharT, class _OutputIterator>
1044
_OutputIterator
1045
num_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
1049
template <class _CharT, class _OutputIterator>
1050
_OutputIterator
1051
num_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
1059
extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS num_put<char>;
1060
# if _LIBCPP_HAS_WIDE_CHARACTERS
1061
extern 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
1073
1074