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