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