xref: /freebsd/contrib/llvm-project/libcxx/include/__locale_dir/num.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
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 
__stage2_int_prep__num_get86   _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 
__do_widen__num_get93   _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>
__do_widen_p__num_get99   _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 
__do_widen_p__num_get105   _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>
__stage2_float_prep(ios_base & __iob,_CharT * __atoms,_CharT & __decimal_point,_CharT & __thousands_sep)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>
__stage2_int_loop(_CharT __ct,int __base,char * __a,char * & __a_end,unsigned & __dc,_CharT __thousands_sep,const string & __grouping,unsigned * __g,unsigned * & __g_end,_CharT * __atoms)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>
__stage2_float_loop(_CharT __ct,bool & __in_units,char & __exp,char * __a,char * & __a_end,_CharT __decimal_point,_CharT __thousands_sep,const string & __grouping,unsigned * __g,unsigned * & __g_end,unsigned & __dc,_CharT * __atoms)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