Path: blob/main/contrib/llvm-project/libcxx/include/__locale_dir/num.h
213766 views
//===----------------------------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#ifndef _LIBCPP___LOCALE_DIR_NUM_H9#define _LIBCPP___LOCALE_DIR_NUM_H1011#include <__algorithm/find.h>12#include <__algorithm/reverse.h>13#include <__charconv/to_chars_integral.h>14#include <__charconv/traits.h>15#include <__config>16#include <__iterator/istreambuf_iterator.h>17#include <__iterator/ostreambuf_iterator.h>18#include <__locale_dir/check_grouping.h>19#include <__locale_dir/get_c_locale.h>20#include <__locale_dir/pad_and_output.h>21#include <__locale_dir/scan_keyword.h>22#include <__memory/unique_ptr.h>23#include <__system_error/errc.h>24#include <cerrno>25#include <ios>26#include <streambuf>2728#if _LIBCPP_HAS_LOCALIZATION2930# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)31# pragma GCC system_header32# endif3334// TODO: Properly qualify calls now that the locale base API defines functions instead of macros35// NOLINTBEGIN(libcpp-robust-against-adl)3637_LIBCPP_PUSH_MACROS38# include <__undef_macros>3940_LIBCPP_BEGIN_NAMESPACE_STD4142struct _LIBCPP_EXPORTED_FROM_ABI __num_get_base {43static const int __num_get_buf_sz = 40;4445static int __get_base(ios_base&);46static const char __src[33]; // "0123456789abcdefABCDEFxX+-pPiInN"47// count of leading characters in __src used for parsing integers ("012..X+-")48static const size_t __int_chr_cnt = 26;49// count of leading characters in __src used for parsing floating-point values ("012..-pP")50static const size_t __fp_chr_cnt = 28;51};5253template <class _CharT>54struct __num_get : protected __num_get_base {55static string __stage2_float_prep(ios_base& __iob, _CharT* __atoms, _CharT& __decimal_point, _CharT& __thousands_sep);5657static int __stage2_float_loop(58_CharT __ct,59bool& __in_units,60char& __exp,61char* __a,62char*& __a_end,63_CharT __decimal_point,64_CharT __thousands_sep,65const string& __grouping,66unsigned* __g,67unsigned*& __g_end,68unsigned& __dc,69_CharT* __atoms);7071[[__deprecated__("This exists only for ABI compatibility")]] static string72__stage2_int_prep(ios_base& __iob, _CharT* __atoms, _CharT& __thousands_sep);73static int __stage2_int_loop(74_CharT __ct,75int __base,76char* __a,77char*& __a_end,78unsigned& __dc,79_CharT __thousands_sep,80const string& __grouping,81unsigned* __g,82unsigned*& __g_end,83_CharT* __atoms);8485_LIBCPP_HIDE_FROM_ABI static string __stage2_int_prep(ios_base& __iob, _CharT& __thousands_sep) {86locale __loc = __iob.getloc();87const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);88__thousands_sep = __np.thousands_sep();89return __np.grouping();90}9192_LIBCPP_HIDE_FROM_ABI const _CharT* __do_widen(ios_base& __iob, _CharT* __atoms) const {93return __do_widen_p(__iob, __atoms);94}9596private:97template <typename _Tp>98_LIBCPP_HIDE_FROM_ABI const _Tp* __do_widen_p(ios_base& __iob, _Tp* __atoms) const {99locale __loc = __iob.getloc();100use_facet<ctype<_Tp> >(__loc).widen(__src, __src + __int_chr_cnt, __atoms);101return __atoms;102}103104_LIBCPP_HIDE_FROM_ABI const char* __do_widen_p(ios_base& __iob, char* __atoms) const {105(void)__iob;106(void)__atoms;107return __src;108}109};110111template <class _CharT>112string __num_get<_CharT>::__stage2_float_prep(113ios_base& __iob, _CharT* __atoms, _CharT& __decimal_point, _CharT& __thousands_sep) {114locale __loc = __iob.getloc();115std::use_facet<ctype<_CharT> >(__loc).widen(__src, __src + __fp_chr_cnt, __atoms);116const numpunct<_CharT>& __np = std::use_facet<numpunct<_CharT> >(__loc);117__decimal_point = __np.decimal_point();118__thousands_sep = __np.thousands_sep();119return __np.grouping();120}121122template <class _CharT>123int __num_get<_CharT>::__stage2_int_loop(124_CharT __ct,125int __base,126char* __a,127char*& __a_end,128unsigned& __dc,129_CharT __thousands_sep,130const string& __grouping,131unsigned* __g,132unsigned*& __g_end,133_CharT* __atoms) {134if (__a_end == __a && (__ct == __atoms[24] || __ct == __atoms[25])) {135*__a_end++ = __ct == __atoms[24] ? '+' : '-';136__dc = 0;137return 0;138}139if (__grouping.size() != 0 && __ct == __thousands_sep) {140if (__g_end - __g < __num_get_buf_sz) {141*__g_end++ = __dc;142__dc = 0;143}144return 0;145}146ptrdiff_t __f = std::find(__atoms, __atoms + __int_chr_cnt, __ct) - __atoms;147if (__f >= 24)148return -1;149switch (__base) {150case 8:151case 10:152if (__f >= __base)153return -1;154break;155case 16:156if (__f < 22)157break;158if (__a_end != __a && __a_end - __a <= 2 && __a_end[-1] == '0') {159__dc = 0;160*__a_end++ = __src[__f];161return 0;162}163return -1;164}165*__a_end++ = __src[__f];166++__dc;167return 0;168}169170template <class _CharT>171int __num_get<_CharT>::__stage2_float_loop(172_CharT __ct,173bool& __in_units,174char& __exp,175char* __a,176char*& __a_end,177_CharT __decimal_point,178_CharT __thousands_sep,179const string& __grouping,180unsigned* __g,181unsigned*& __g_end,182unsigned& __dc,183_CharT* __atoms) {184if (__ct == __decimal_point) {185if (!__in_units)186return -1;187__in_units = false;188*__a_end++ = '.';189if (__grouping.size() != 0 && __g_end - __g < __num_get_buf_sz)190*__g_end++ = __dc;191return 0;192}193if (__ct == __thousands_sep && __grouping.size() != 0) {194if (!__in_units)195return -1;196if (__g_end - __g < __num_get_buf_sz) {197*__g_end++ = __dc;198__dc = 0;199}200return 0;201}202ptrdiff_t __f = std::find(__atoms, __atoms + __num_get_base::__fp_chr_cnt, __ct) - __atoms;203if (__f >= static_cast<ptrdiff_t>(__num_get_base::__fp_chr_cnt))204return -1;205char __x = __src[__f];206if (__x == '-' || __x == '+') {207if (__a_end == __a || (std::toupper(__a_end[-1]) == std::toupper(__exp))) {208*__a_end++ = __x;209return 0;210}211return -1;212}213if (__x == 'x' || __x == 'X')214__exp = 'P';215else if (std::toupper(__x) == __exp) {216__exp = std::tolower(__exp);217if (__in_units) {218__in_units = false;219if (__grouping.size() != 0 && __g_end - __g < __num_get_buf_sz)220*__g_end++ = __dc;221}222}223*__a_end++ = __x;224if (__f >= 22)225return 0;226++__dc;227return 0;228}229230extern template struct _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __num_get<char>;231# if _LIBCPP_HAS_WIDE_CHARACTERS232extern template struct _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __num_get<wchar_t>;233# endif234235template <class _Tp>236_LIBCPP_HIDE_FROM_ABI _Tp __do_strtod(const char* __a, char** __p2);237238template <>239inline _LIBCPP_HIDE_FROM_ABI float __do_strtod<float>(const char* __a, char** __p2) {240return __locale::__strtof(__a, __p2, _LIBCPP_GET_C_LOCALE);241}242243template <>244inline _LIBCPP_HIDE_FROM_ABI double __do_strtod<double>(const char* __a, char** __p2) {245return __locale::__strtod(__a, __p2, _LIBCPP_GET_C_LOCALE);246}247248template <>249inline _LIBCPP_HIDE_FROM_ABI long double __do_strtod<long double>(const char* __a, char** __p2) {250return __locale::__strtold(__a, __p2, _LIBCPP_GET_C_LOCALE);251}252253template <class _Tp>254_LIBCPP_HIDE_FROM_ABI _Tp __num_get_float(const char* __a, const char* __a_end, ios_base::iostate& __err) {255if (__a != __a_end) {256__libcpp_remove_reference_t<decltype(errno)> __save_errno = errno;257errno = 0;258char* __p2;259_Tp __ld = std::__do_strtod<_Tp>(__a, &__p2);260__libcpp_remove_reference_t<decltype(errno)> __current_errno = errno;261if (__current_errno == 0)262errno = __save_errno;263if (__p2 != __a_end) {264__err = ios_base::failbit;265return 0;266} else if (__current_errno == ERANGE)267__err = ios_base::failbit;268return __ld;269}270__err = ios_base::failbit;271return 0;272}273274template <class _Tp>275_LIBCPP_HIDE_FROM_ABI _Tp276__num_get_signed_integral(const char* __a, const char* __a_end, ios_base::iostate& __err, int __base) {277if (__a != __a_end) {278__libcpp_remove_reference_t<decltype(errno)> __save_errno = errno;279errno = 0;280char* __p2;281long long __ll = __locale::__strtoll(__a, &__p2, __base, _LIBCPP_GET_C_LOCALE);282__libcpp_remove_reference_t<decltype(errno)> __current_errno = errno;283if (__current_errno == 0)284errno = __save_errno;285if (__p2 != __a_end) {286__err = ios_base::failbit;287return 0;288} else if (__current_errno == ERANGE || __ll < numeric_limits<_Tp>::min() || numeric_limits<_Tp>::max() < __ll) {289__err = ios_base::failbit;290if (__ll > 0)291return numeric_limits<_Tp>::max();292else293return numeric_limits<_Tp>::min();294}295return static_cast<_Tp>(__ll);296}297__err = ios_base::failbit;298return 0;299}300301template <class _Tp>302_LIBCPP_HIDE_FROM_ABI _Tp303__num_get_unsigned_integral(const char* __a, const char* __a_end, ios_base::iostate& __err, int __base) {304if (__a != __a_end) {305const bool __negate = *__a == '-';306if (__negate && ++__a == __a_end) {307__err = ios_base::failbit;308return 0;309}310__libcpp_remove_reference_t<decltype(errno)> __save_errno = errno;311errno = 0;312char* __p2;313unsigned long long __ll = __locale::__strtoull(__a, &__p2, __base, _LIBCPP_GET_C_LOCALE);314__libcpp_remove_reference_t<decltype(errno)> __current_errno = errno;315if (__current_errno == 0)316errno = __save_errno;317if (__p2 != __a_end) {318__err = ios_base::failbit;319return 0;320} else if (__current_errno == ERANGE || numeric_limits<_Tp>::max() < __ll) {321__err = ios_base::failbit;322return numeric_limits<_Tp>::max();323}324_Tp __res = static_cast<_Tp>(__ll);325if (__negate)326__res = -__res;327return __res;328}329__err = ios_base::failbit;330return 0;331}332333template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >334class num_get : public locale::facet, private __num_get<_CharT> {335public:336typedef _CharT char_type;337typedef _InputIterator iter_type;338339_LIBCPP_HIDE_FROM_ABI explicit num_get(size_t __refs = 0) : locale::facet(__refs) {}340341_LIBCPP_HIDE_FROM_ABI iter_type342get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, bool& __v) const {343return do_get(__b, __e, __iob, __err, __v);344}345346_LIBCPP_HIDE_FROM_ABI iter_type347get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, long& __v) const {348return do_get(__b, __e, __iob, __err, __v);349}350351_LIBCPP_HIDE_FROM_ABI iter_type352get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, long long& __v) const {353return do_get(__b, __e, __iob, __err, __v);354}355356_LIBCPP_HIDE_FROM_ABI iter_type357get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, unsigned short& __v) const {358return do_get(__b, __e, __iob, __err, __v);359}360361_LIBCPP_HIDE_FROM_ABI iter_type362get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, unsigned int& __v) const {363return do_get(__b, __e, __iob, __err, __v);364}365366_LIBCPP_HIDE_FROM_ABI iter_type367get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, unsigned long& __v) const {368return do_get(__b, __e, __iob, __err, __v);369}370371_LIBCPP_HIDE_FROM_ABI iter_type372get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, unsigned long long& __v) const {373return do_get(__b, __e, __iob, __err, __v);374}375376_LIBCPP_HIDE_FROM_ABI iter_type377get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, float& __v) const {378return do_get(__b, __e, __iob, __err, __v);379}380381_LIBCPP_HIDE_FROM_ABI iter_type382get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, double& __v) const {383return do_get(__b, __e, __iob, __err, __v);384}385386_LIBCPP_HIDE_FROM_ABI iter_type387get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, long double& __v) const {388return do_get(__b, __e, __iob, __err, __v);389}390391_LIBCPP_HIDE_FROM_ABI iter_type392get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, void*& __v) const {393return do_get(__b, __e, __iob, __err, __v);394}395396static locale::id id;397398protected:399_LIBCPP_HIDE_FROM_ABI_VIRTUAL ~num_get() override {}400401template <class _Fp>402_LIBCPP_HIDE_FROM_ABI iter_type403__do_get_floating_point(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, _Fp& __v) const {404// Stage 1, nothing to do405// Stage 2406char_type __atoms[__num_get_base::__fp_chr_cnt];407char_type __decimal_point;408char_type __thousands_sep;409string __grouping = this->__stage2_float_prep(__iob, __atoms, __decimal_point, __thousands_sep);410string __buf;411__buf.resize(__buf.capacity());412char* __a = &__buf[0];413char* __a_end = __a;414unsigned __g[__num_get_base::__num_get_buf_sz];415unsigned* __g_end = __g;416unsigned __dc = 0;417bool __in_units = true;418char __exp = 'E';419bool __is_leading_parsed = false;420for (; __b != __e; ++__b) {421if (__a_end == __a + __buf.size()) {422size_t __tmp = __buf.size();423__buf.resize(2 * __buf.size());424__buf.resize(__buf.capacity());425__a = &__buf[0];426__a_end = __a + __tmp;427}428if (this->__stage2_float_loop(429*__b,430__in_units,431__exp,432__a,433__a_end,434__decimal_point,435__thousands_sep,436__grouping,437__g,438__g_end,439__dc,440__atoms))441break;442443// the leading character excluding the sign must be a decimal digit444if (!__is_leading_parsed) {445if (__a_end - __a >= 1 && __a[0] != '-' && __a[0] != '+') {446if (('0' <= __a[0] && __a[0] <= '9') || __a[0] == '.')447__is_leading_parsed = true;448else449break;450} else if (__a_end - __a >= 2 && (__a[0] == '-' || __a[0] == '+')) {451if (('0' <= __a[1] && __a[1] <= '9') || __a[1] == '.')452__is_leading_parsed = true;453else454break;455}456}457}458if (__grouping.size() != 0 && __in_units && __g_end - __g < __num_get_base::__num_get_buf_sz)459*__g_end++ = __dc;460// Stage 3461__v = std::__num_get_float<_Fp>(__a, __a_end, __err);462// Digit grouping checked463__check_grouping(__grouping, __g, __g_end, __err);464// EOF checked465if (__b == __e)466__err |= ios_base::eofbit;467return __b;468}469470template <class _Signed>471_LIBCPP_HIDE_FROM_ABI iter_type472__do_get_signed(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, _Signed& __v) const {473// Stage 1474int __base = this->__get_base(__iob);475// Stage 2476char_type __thousands_sep;477const int __atoms_size = __num_get_base::__int_chr_cnt;478char_type __atoms1[__atoms_size];479const char_type* __atoms = this->__do_widen(__iob, __atoms1);480string __grouping = this->__stage2_int_prep(__iob, __thousands_sep);481string __buf;482__buf.resize(__buf.capacity());483char* __a = &__buf[0];484char* __a_end = __a;485unsigned __g[__num_get_base::__num_get_buf_sz];486unsigned* __g_end = __g;487unsigned __dc = 0;488for (; __b != __e; ++__b) {489if (__a_end == __a + __buf.size()) {490size_t __tmp = __buf.size();491__buf.resize(2 * __buf.size());492__buf.resize(__buf.capacity());493__a = &__buf[0];494__a_end = __a + __tmp;495}496if (this->__stage2_int_loop(497*__b,498__base,499__a,500__a_end,501__dc,502__thousands_sep,503__grouping,504__g,505__g_end,506const_cast<char_type*>(__atoms)))507break;508}509if (__grouping.size() != 0 && __g_end - __g < __num_get_base::__num_get_buf_sz)510*__g_end++ = __dc;511// Stage 3512__v = std::__num_get_signed_integral<_Signed>(__a, __a_end, __err, __base);513// Digit grouping checked514__check_grouping(__grouping, __g, __g_end, __err);515// EOF checked516if (__b == __e)517__err |= ios_base::eofbit;518return __b;519}520521template <class _Unsigned>522_LIBCPP_HIDE_FROM_ABI iter_type523__do_get_unsigned(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, _Unsigned& __v) const {524// Stage 1525int __base = this->__get_base(__iob);526// Stage 2527char_type __thousands_sep;528const int __atoms_size = __num_get_base::__int_chr_cnt;529char_type __atoms1[__atoms_size];530const char_type* __atoms = this->__do_widen(__iob, __atoms1);531string __grouping = this->__stage2_int_prep(__iob, __thousands_sep);532string __buf;533__buf.resize(__buf.capacity());534char* __a = &__buf[0];535char* __a_end = __a;536unsigned __g[__num_get_base::__num_get_buf_sz];537unsigned* __g_end = __g;538unsigned __dc = 0;539for (; __b != __e; ++__b) {540if (__a_end == __a + __buf.size()) {541size_t __tmp = __buf.size();542__buf.resize(2 * __buf.size());543__buf.resize(__buf.capacity());544__a = &__buf[0];545__a_end = __a + __tmp;546}547if (this->__stage2_int_loop(548*__b,549__base,550__a,551__a_end,552__dc,553__thousands_sep,554__grouping,555__g,556__g_end,557const_cast<char_type*>(__atoms)))558break;559}560if (__grouping.size() != 0 && __g_end - __g < __num_get_base::__num_get_buf_sz)561*__g_end++ = __dc;562// Stage 3563__v = std::__num_get_unsigned_integral<_Unsigned>(__a, __a_end, __err, __base);564// Digit grouping checked565__check_grouping(__grouping, __g, __g_end, __err);566// EOF checked567if (__b == __e)568__err |= ios_base::eofbit;569return __b;570}571572virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, bool& __v) const;573574virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, long& __v) const {575return this->__do_get_signed(__b, __e, __iob, __err, __v);576}577578virtual iter_type579do_get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, long long& __v) const {580return this->__do_get_signed(__b, __e, __iob, __err, __v);581}582583virtual iter_type584do_get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, unsigned short& __v) const {585return this->__do_get_unsigned(__b, __e, __iob, __err, __v);586}587588virtual iter_type589do_get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, unsigned int& __v) const {590return this->__do_get_unsigned(__b, __e, __iob, __err, __v);591}592593virtual iter_type594do_get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, unsigned long& __v) const {595return this->__do_get_unsigned(__b, __e, __iob, __err, __v);596}597598virtual iter_type599do_get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, unsigned long long& __v) const {600return this->__do_get_unsigned(__b, __e, __iob, __err, __v);601}602603virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, float& __v) const {604return this->__do_get_floating_point(__b, __e, __iob, __err, __v);605}606607virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, double& __v) const {608return this->__do_get_floating_point(__b, __e, __iob, __err, __v);609}610611virtual iter_type612do_get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, long double& __v) const {613return this->__do_get_floating_point(__b, __e, __iob, __err, __v);614}615616virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, void*& __v) const;617};618619template <class _CharT, class _InputIterator>620locale::id num_get<_CharT, _InputIterator>::id;621622template <class _CharT, class _InputIterator>623_InputIterator num_get<_CharT, _InputIterator>::do_get(624iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, bool& __v) const {625if ((__iob.flags() & ios_base::boolalpha) == 0) {626long __lv = -1;627__b = do_get(__b, __e, __iob, __err, __lv);628switch (__lv) {629case 0:630__v = false;631break;632case 1:633__v = true;634break;635default:636__v = true;637__err = ios_base::failbit;638break;639}640return __b;641}642const ctype<_CharT>& __ct = std::use_facet<ctype<_CharT> >(__iob.getloc());643const numpunct<_CharT>& __np = std::use_facet<numpunct<_CharT> >(__iob.getloc());644typedef typename numpunct<_CharT>::string_type string_type;645const string_type __names[2] = {__np.truename(), __np.falsename()};646const string_type* __i = std::__scan_keyword(__b, __e, __names, __names + 2, __ct, __err);647__v = __i == __names;648return __b;649}650651template <class _CharT, class _InputIterator>652_InputIterator num_get<_CharT, _InputIterator>::do_get(653iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, void*& __v) const {654// Stage 1655int __base = 16;656// Stage 2657char_type __atoms[__num_get_base::__int_chr_cnt];658char_type __thousands_sep = char_type();659string __grouping;660std::use_facet<ctype<_CharT> >(__iob.getloc())661.widen(__num_get_base::__src, __num_get_base::__src + __num_get_base::__int_chr_cnt, __atoms);662string __buf;663__buf.resize(__buf.capacity());664char* __a = &__buf[0];665char* __a_end = __a;666unsigned __g[__num_get_base::__num_get_buf_sz];667unsigned* __g_end = __g;668unsigned __dc = 0;669for (; __b != __e; ++__b) {670if (__a_end == __a + __buf.size()) {671size_t __tmp = __buf.size();672__buf.resize(2 * __buf.size());673__buf.resize(__buf.capacity());674__a = &__buf[0];675__a_end = __a + __tmp;676}677if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc, __thousands_sep, __grouping, __g, __g_end, __atoms))678break;679}680// Stage 3681__buf.resize(__a_end - __a);682if (__locale::__sscanf(__buf.c_str(), _LIBCPP_GET_C_LOCALE, "%p", &__v) != 1)683__err = ios_base::failbit;684// EOF checked685if (__b == __e)686__err |= ios_base::eofbit;687return __b;688}689690extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS num_get<char>;691# if _LIBCPP_HAS_WIDE_CHARACTERS692extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS num_get<wchar_t>;693# endif694695struct _LIBCPP_EXPORTED_FROM_ABI __num_put_base {696protected:697static void __format_int(char* __fmt, const char* __len, bool __signd, ios_base::fmtflags __flags);698static bool __format_float(char* __fmt, const char* __len, ios_base::fmtflags __flags);699static char* __identify_padding(char* __nb, char* __ne, const ios_base& __iob);700};701702template <class _CharT>703struct __num_put : protected __num_put_base {704static void __widen_and_group_int(705char* __nb, char* __np, char* __ne, _CharT* __ob, _CharT*& __op, _CharT*& __oe, const locale& __loc);706static void __widen_and_group_float(707char* __nb, char* __np, char* __ne, _CharT* __ob, _CharT*& __op, _CharT*& __oe, const locale& __loc);708};709710template <class _CharT>711void __num_put<_CharT>::__widen_and_group_int(712char* __nb, char* __np, char* __ne, _CharT* __ob, _CharT*& __op, _CharT*& __oe, const locale& __loc) {713const ctype<_CharT>& __ct = std::use_facet<ctype<_CharT> >(__loc);714const numpunct<_CharT>& __npt = std::use_facet<numpunct<_CharT> >(__loc);715string __grouping = __npt.grouping();716if (__grouping.empty()) {717__ct.widen(__nb, __ne, __ob);718__oe = __ob + (__ne - __nb);719} else {720__oe = __ob;721char* __nf = __nb;722if (*__nf == '-' || *__nf == '+')723*__oe++ = __ct.widen(*__nf++);724if (__ne - __nf >= 2 && __nf[0] == '0' && (__nf[1] == 'x' || __nf[1] == 'X')) {725*__oe++ = __ct.widen(*__nf++);726*__oe++ = __ct.widen(*__nf++);727}728std::reverse(__nf, __ne);729_CharT __thousands_sep = __npt.thousands_sep();730unsigned __dc = 0;731unsigned __dg = 0;732for (char* __p = __nf; __p < __ne; ++__p) {733if (static_cast<unsigned>(__grouping[__dg]) > 0 && __dc == static_cast<unsigned>(__grouping[__dg])) {734*__oe++ = __thousands_sep;735__dc = 0;736if (__dg < __grouping.size() - 1)737++__dg;738}739*__oe++ = __ct.widen(*__p);740++__dc;741}742std::reverse(__ob + (__nf - __nb), __oe);743}744if (__np == __ne)745__op = __oe;746else747__op = __ob + (__np - __nb);748}749750template <class _CharT>751void __num_put<_CharT>::__widen_and_group_float(752char* __nb, char* __np, char* __ne, _CharT* __ob, _CharT*& __op, _CharT*& __oe, const locale& __loc) {753const ctype<_CharT>& __ct = std::use_facet<ctype<_CharT> >(__loc);754const numpunct<_CharT>& __npt = std::use_facet<numpunct<_CharT> >(__loc);755string __grouping = __npt.grouping();756__oe = __ob;757char* __nf = __nb;758if (*__nf == '-' || *__nf == '+')759*__oe++ = __ct.widen(*__nf++);760char* __ns;761if (__ne - __nf >= 2 && __nf[0] == '0' && (__nf[1] == 'x' || __nf[1] == 'X')) {762*__oe++ = __ct.widen(*__nf++);763*__oe++ = __ct.widen(*__nf++);764for (__ns = __nf; __ns < __ne; ++__ns)765if (!__locale::__isxdigit(*__ns, _LIBCPP_GET_C_LOCALE))766break;767} else {768for (__ns = __nf; __ns < __ne; ++__ns)769if (!__locale::__isdigit(*__ns, _LIBCPP_GET_C_LOCALE))770break;771}772if (__grouping.empty()) {773__ct.widen(__nf, __ns, __oe);774__oe += __ns - __nf;775} else {776std::reverse(__nf, __ns);777_CharT __thousands_sep = __npt.thousands_sep();778unsigned __dc = 0;779unsigned __dg = 0;780for (char* __p = __nf; __p < __ns; ++__p) {781if (__grouping[__dg] > 0 && __dc == static_cast<unsigned>(__grouping[__dg])) {782*__oe++ = __thousands_sep;783__dc = 0;784if (__dg < __grouping.size() - 1)785++__dg;786}787*__oe++ = __ct.widen(*__p);788++__dc;789}790std::reverse(__ob + (__nf - __nb), __oe);791}792for (__nf = __ns; __nf < __ne; ++__nf) {793if (*__nf == '.') {794*__oe++ = __npt.decimal_point();795++__nf;796break;797} else798*__oe++ = __ct.widen(*__nf);799}800__ct.widen(__nf, __ne, __oe);801__oe += __ne - __nf;802if (__np == __ne)803__op = __oe;804else805__op = __ob + (__np - __nb);806}807808extern template struct _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __num_put<char>;809# if _LIBCPP_HAS_WIDE_CHARACTERS810extern template struct _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __num_put<wchar_t>;811# endif812813template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >814class num_put : public locale::facet, private __num_put<_CharT> {815public:816typedef _CharT char_type;817typedef _OutputIterator iter_type;818819_LIBCPP_HIDE_FROM_ABI explicit num_put(size_t __refs = 0) : locale::facet(__refs) {}820821_LIBCPP_HIDE_FROM_ABI iter_type put(iter_type __s, ios_base& __iob, char_type __fl, bool __v) const {822return do_put(__s, __iob, __fl, __v);823}824825_LIBCPP_HIDE_FROM_ABI iter_type put(iter_type __s, ios_base& __iob, char_type __fl, long __v) const {826return do_put(__s, __iob, __fl, __v);827}828829_LIBCPP_HIDE_FROM_ABI iter_type put(iter_type __s, ios_base& __iob, char_type __fl, long long __v) const {830return do_put(__s, __iob, __fl, __v);831}832833_LIBCPP_HIDE_FROM_ABI iter_type put(iter_type __s, ios_base& __iob, char_type __fl, unsigned long __v) const {834return do_put(__s, __iob, __fl, __v);835}836837_LIBCPP_HIDE_FROM_ABI iter_type put(iter_type __s, ios_base& __iob, char_type __fl, unsigned long long __v) const {838return do_put(__s, __iob, __fl, __v);839}840841_LIBCPP_HIDE_FROM_ABI iter_type put(iter_type __s, ios_base& __iob, char_type __fl, double __v) const {842return do_put(__s, __iob, __fl, __v);843}844845_LIBCPP_HIDE_FROM_ABI iter_type put(iter_type __s, ios_base& __iob, char_type __fl, long double __v) const {846return do_put(__s, __iob, __fl, __v);847}848849_LIBCPP_HIDE_FROM_ABI iter_type put(iter_type __s, ios_base& __iob, char_type __fl, const void* __v) const {850return do_put(__s, __iob, __fl, __v);851}852853static locale::id id;854855protected:856_LIBCPP_HIDE_FROM_ABI_VIRTUAL ~num_put() override {}857858virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl, bool __v) const;859virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl, long __v) const;860virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl, long long __v) const;861virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl, unsigned long) const;862virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl, unsigned long long) const;863virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl, double __v) const;864virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl, long double __v) const;865virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl, const void* __v) const;866867template <class _Integral>868_LIBCPP_HIDE_FROM_ABI inline _OutputIterator869__do_put_integral(iter_type __s, ios_base& __iob, char_type __fl, _Integral __v) const;870871template <class _Float>872_LIBCPP_HIDE_FROM_ABI inline _OutputIterator873__do_put_floating_point(iter_type __s, ios_base& __iob, char_type __fl, _Float __v, char const* __len) const;874};875876template <class _CharT, class _OutputIterator>877locale::id num_put<_CharT, _OutputIterator>::id;878879template <class _CharT, class _OutputIterator>880_OutputIterator881num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob, char_type __fl, bool __v) const {882if ((__iob.flags() & ios_base::boolalpha) == 0)883return do_put(__s, __iob, __fl, (unsigned long)__v);884const numpunct<char_type>& __np = std::use_facet<numpunct<char_type> >(__iob.getloc());885typedef typename numpunct<char_type>::string_type string_type;886string_type __nm = __v ? __np.truename() : __np.falsename();887for (typename string_type::iterator __i = __nm.begin(); __i != __nm.end(); ++__i, ++__s)888*__s = *__i;889return __s;890}891892template <class _CharT, class _OutputIterator>893template <class _Integral>894_LIBCPP_HIDE_FROM_ABI inline _OutputIterator num_put<_CharT, _OutputIterator>::__do_put_integral(895iter_type __s, ios_base& __iob, char_type __fl, _Integral __v) const {896// Stage 1 - Get number in narrow char897898// Worst case is octal, with showbase enabled. Note that octal is always899// printed as an unsigned value.900using _Unsigned = typename make_unsigned<_Integral>::type;901_LIBCPP_CONSTEXPR const unsigned __buffer_size =902(numeric_limits<_Unsigned>::digits / 3) // 1 char per 3 bits903+ ((numeric_limits<_Unsigned>::digits % 3) != 0) // round up904+ 2; // base prefix + terminating null character905906char __char_buffer[__buffer_size];907char* __buffer_ptr = __char_buffer;908909auto __flags = __iob.flags();910911auto __basefield = (__flags & ios_base::basefield);912913// Extract base914int __base = 10;915if (__basefield == ios_base::oct)916__base = 8;917else if (__basefield == ios_base::hex)918__base = 16;919920// Print '-' and make the argument unsigned921auto __uval = std::__to_unsigned_like(__v);922if (__basefield != ios_base::oct && __basefield != ios_base::hex && __v < 0) {923*__buffer_ptr++ = '-';924__uval = std::__complement(__uval);925}926927// Maybe add '+' prefix928if (std::is_signed<_Integral>::value && (__flags & ios_base::showpos) && __basefield != ios_base::oct &&929__basefield != ios_base::hex && __v >= 0)930*__buffer_ptr++ = '+';931932// Add base prefix933if (__v != 0 && __flags & ios_base::showbase) {934if (__basefield == ios_base::oct) {935*__buffer_ptr++ = '0';936} else if (__basefield == ios_base::hex) {937*__buffer_ptr++ = '0';938*__buffer_ptr++ = (__flags & ios_base::uppercase ? 'X' : 'x');939}940}941942auto __res = std::__to_chars_integral(__buffer_ptr, __char_buffer + __buffer_size, __uval, __base);943_LIBCPP_ASSERT_INTERNAL(__res.__ec == std::errc(0), "to_chars: invalid maximum buffer size computed?");944945// Make letters uppercase946if (__flags & ios_base::hex && __flags & ios_base::uppercase) {947for (; __buffer_ptr != __res.__ptr; ++__buffer_ptr)948*__buffer_ptr = std::__hex_to_upper(*__buffer_ptr);949}950951char* __np = this->__identify_padding(__char_buffer, __res.__ptr, __iob);952// Stage 2 - Widen __nar while adding thousands separators953char_type __o[2 * (__buffer_size - 1) - 1];954char_type* __op; // pad here955char_type* __oe; // end of output956this->__widen_and_group_int(__char_buffer, __np, __res.__ptr, __o, __op, __oe, __iob.getloc());957// [__o, __oe) contains thousands_sep'd wide number958// Stage 3 & 4959return std::__pad_and_output(__s, __o, __op, __oe, __iob, __fl);960}961962template <class _CharT, class _OutputIterator>963_OutputIterator964num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob, char_type __fl, long __v) const {965return this->__do_put_integral(__s, __iob, __fl, __v);966}967968template <class _CharT, class _OutputIterator>969_OutputIterator970num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob, char_type __fl, long long __v) const {971return this->__do_put_integral(__s, __iob, __fl, __v);972}973974template <class _CharT, class _OutputIterator>975_OutputIterator976num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob, char_type __fl, unsigned long __v) const {977return this->__do_put_integral(__s, __iob, __fl, __v);978}979980template <class _CharT, class _OutputIterator>981_OutputIterator982num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob, char_type __fl, unsigned long long __v) const {983return this->__do_put_integral(__s, __iob, __fl, __v);984}985986template <class _CharT, class _OutputIterator>987template <class _Float>988_LIBCPP_HIDE_FROM_ABI inline _OutputIterator num_put<_CharT, _OutputIterator>::__do_put_floating_point(989iter_type __s, ios_base& __iob, char_type __fl, _Float __v, char const* __len) const {990// Stage 1 - Get number in narrow char991char __fmt[8] = {'%', 0};992bool __specify_precision = this->__format_float(__fmt + 1, __len, __iob.flags());993const unsigned __nbuf = 30;994char __nar[__nbuf];995char* __nb = __nar;996int __nc;997_LIBCPP_DIAGNOSTIC_PUSH998_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wformat-nonliteral")999_LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wformat-nonliteral")1000if (__specify_precision)1001__nc = __locale::__snprintf(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt, (int)__iob.precision(), __v);1002else1003__nc = __locale::__snprintf(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt, __v);1004unique_ptr<char, void (*)(void*)> __nbh(nullptr, free);1005if (__nc > static_cast<int>(__nbuf - 1)) {1006if (__specify_precision)1007__nc = __locale::__asprintf(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, (int)__iob.precision(), __v);1008else1009__nc = __locale::__asprintf(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, __v);1010if (__nc == -1)1011std::__throw_bad_alloc();1012__nbh.reset(__nb);1013}1014_LIBCPP_DIAGNOSTIC_POP1015char* __ne = __nb + __nc;1016char* __np = this->__identify_padding(__nb, __ne, __iob);1017// Stage 2 - Widen __nar while adding thousands separators1018char_type __o[2 * (__nbuf - 1) - 1];1019char_type* __ob = __o;1020unique_ptr<char_type, void (*)(void*)> __obh(0, free);1021if (__nb != __nar) {1022__ob = (char_type*)malloc(2 * static_cast<size_t>(__nc) * sizeof(char_type));1023if (__ob == 0)1024std::__throw_bad_alloc();1025__obh.reset(__ob);1026}1027char_type* __op; // pad here1028char_type* __oe; // end of output1029this->__widen_and_group_float(__nb, __np, __ne, __ob, __op, __oe, __iob.getloc());1030// [__o, __oe) contains thousands_sep'd wide number1031// Stage 3 & 41032__s = std::__pad_and_output(__s, __ob, __op, __oe, __iob, __fl);1033return __s;1034}10351036template <class _CharT, class _OutputIterator>1037_OutputIterator1038num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob, char_type __fl, double __v) const {1039return this->__do_put_floating_point(__s, __iob, __fl, __v, "");1040}10411042template <class _CharT, class _OutputIterator>1043_OutputIterator1044num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob, char_type __fl, long double __v) const {1045return this->__do_put_floating_point(__s, __iob, __fl, __v, "L");1046}10471048template <class _CharT, class _OutputIterator>1049_OutputIterator1050num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob, char_type __fl, const void* __v) const {1051auto __flags = __iob.flags();1052__iob.flags((__flags & ~ios_base::basefield & ~ios_base::uppercase) | ios_base::hex | ios_base::showbase);1053auto __res = __do_put_integral(__s, __iob, __fl, reinterpret_cast<uintptr_t>(__v));1054__iob.flags(__flags);1055return __res;1056}10571058extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS num_put<char>;1059# if _LIBCPP_HAS_WIDE_CHARACTERS1060extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS num_put<wchar_t>;1061# endif10621063_LIBCPP_END_NAMESPACE_STD10641065_LIBCPP_POP_MACROS10661067// NOLINTEND(libcpp-robust-against-adl)10681069#endif // _LIBCPP_HAS_LOCALIZATION10701071#endif // _LIBCPP___LOCALE_DIR_NUM_H107210731074