Path: blob/main/contrib/llvm-project/libcxx/include/__locale_dir/money.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_MONEY_H9#define _LIBCPP___LOCALE_DIR_MONEY_H1011#include <__algorithm/copy.h>12#include <__algorithm/equal.h>13#include <__algorithm/find.h>14#include <__algorithm/reverse.h>15#include <__config>16#include <__locale>17#include <__locale_dir/check_grouping.h>18#include <__locale_dir/get_c_locale.h>19#include <__locale_dir/pad_and_output.h>20#include <__memory/unique_ptr.h>21#include <ios>22#include <string>2324#if _LIBCPP_HAS_LOCALIZATION2526# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)27# pragma GCC system_header28# endif2930_LIBCPP_PUSH_MACROS31# include <__undef_macros>3233_LIBCPP_BEGIN_NAMESPACE_STD3435// money_base3637class _LIBCPP_EXPORTED_FROM_ABI money_base {38public:39enum part { none, space, symbol, sign, value };40struct pattern {41char field[4];42};4344_LIBCPP_HIDE_FROM_ABI money_base() {}45};4647// moneypunct4849template <class _CharT, bool _International = false>50class moneypunct : public locale::facet, public money_base {51public:52typedef _CharT char_type;53typedef basic_string<char_type> string_type;5455_LIBCPP_HIDE_FROM_ABI explicit moneypunct(size_t __refs = 0) : locale::facet(__refs) {}5657_LIBCPP_HIDE_FROM_ABI char_type decimal_point() const { return do_decimal_point(); }58_LIBCPP_HIDE_FROM_ABI char_type thousands_sep() const { return do_thousands_sep(); }59_LIBCPP_HIDE_FROM_ABI string grouping() const { return do_grouping(); }60_LIBCPP_HIDE_FROM_ABI string_type curr_symbol() const { return do_curr_symbol(); }61_LIBCPP_HIDE_FROM_ABI string_type positive_sign() const { return do_positive_sign(); }62_LIBCPP_HIDE_FROM_ABI string_type negative_sign() const { return do_negative_sign(); }63_LIBCPP_HIDE_FROM_ABI int frac_digits() const { return do_frac_digits(); }64_LIBCPP_HIDE_FROM_ABI pattern pos_format() const { return do_pos_format(); }65_LIBCPP_HIDE_FROM_ABI pattern neg_format() const { return do_neg_format(); }6667static locale::id id;68static const bool intl = _International;6970protected:71_LIBCPP_HIDE_FROM_ABI_VIRTUAL ~moneypunct() override {}7273virtual char_type do_decimal_point() const { return numeric_limits<char_type>::max(); }74virtual char_type do_thousands_sep() const { return numeric_limits<char_type>::max(); }75virtual string do_grouping() const { return string(); }76virtual string_type do_curr_symbol() const { return string_type(); }77virtual string_type do_positive_sign() const { return string_type(); }78virtual string_type do_negative_sign() const { return string_type(1, '-'); }79virtual int do_frac_digits() const { return 0; }80virtual pattern do_pos_format() const {81pattern __p = {{symbol, sign, none, value}};82return __p;83}84virtual pattern do_neg_format() const {85pattern __p = {{symbol, sign, none, value}};86return __p;87}88};8990template <class _CharT, bool _International>91locale::id moneypunct<_CharT, _International>::id;9293template <class _CharT, bool _International>94const bool moneypunct<_CharT, _International>::intl;9596extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct<char, false>;97extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct<char, true>;98# if _LIBCPP_HAS_WIDE_CHARACTERS99extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct<wchar_t, false>;100extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct<wchar_t, true>;101# endif102103// moneypunct_byname104105template <class _CharT, bool _International = false>106class moneypunct_byname : public moneypunct<_CharT, _International> {107public:108typedef money_base::pattern pattern;109typedef _CharT char_type;110typedef basic_string<char_type> string_type;111112_LIBCPP_HIDE_FROM_ABI explicit moneypunct_byname(const char* __nm, size_t __refs = 0)113: moneypunct<_CharT, _International>(__refs) {114init(__nm);115}116117_LIBCPP_HIDE_FROM_ABI explicit moneypunct_byname(const string& __nm, size_t __refs = 0)118: moneypunct<_CharT, _International>(__refs) {119init(__nm.c_str());120}121122protected:123_LIBCPP_HIDE_FROM_ABI_VIRTUAL ~moneypunct_byname() override {}124125char_type do_decimal_point() const override { return __decimal_point_; }126char_type do_thousands_sep() const override { return __thousands_sep_; }127string do_grouping() const override { return __grouping_; }128string_type do_curr_symbol() const override { return __curr_symbol_; }129string_type do_positive_sign() const override { return __positive_sign_; }130string_type do_negative_sign() const override { return __negative_sign_; }131int do_frac_digits() const override { return __frac_digits_; }132pattern do_pos_format() const override { return __pos_format_; }133pattern do_neg_format() const override { return __neg_format_; }134135private:136char_type __decimal_point_;137char_type __thousands_sep_;138string __grouping_;139string_type __curr_symbol_;140string_type __positive_sign_;141string_type __negative_sign_;142int __frac_digits_;143pattern __pos_format_;144pattern __neg_format_;145146void init(const char*);147};148149template <>150_LIBCPP_EXPORTED_FROM_ABI void moneypunct_byname<char, false>::init(const char*);151template <>152_LIBCPP_EXPORTED_FROM_ABI void moneypunct_byname<char, true>::init(const char*);153extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct_byname<char, false>;154extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct_byname<char, true>;155156# if _LIBCPP_HAS_WIDE_CHARACTERS157template <>158_LIBCPP_EXPORTED_FROM_ABI void moneypunct_byname<wchar_t, false>::init(const char*);159template <>160_LIBCPP_EXPORTED_FROM_ABI void moneypunct_byname<wchar_t, true>::init(const char*);161extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct_byname<wchar_t, false>;162extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct_byname<wchar_t, true>;163# endif164165// money_get166167template <class _CharT>168class __money_get {169protected:170typedef _CharT char_type;171typedef basic_string<char_type> string_type;172173_LIBCPP_HIDE_FROM_ABI __money_get() {}174175static void __gather_info(176bool __intl,177const locale& __loc,178money_base::pattern& __pat,179char_type& __dp,180char_type& __ts,181string& __grp,182string_type& __sym,183string_type& __psn,184string_type& __nsn,185int& __fd);186};187188template <class _CharT>189void __money_get<_CharT>::__gather_info(190bool __intl,191const locale& __loc,192money_base::pattern& __pat,193char_type& __dp,194char_type& __ts,195string& __grp,196string_type& __sym,197string_type& __psn,198string_type& __nsn,199int& __fd) {200if (__intl) {201const moneypunct<char_type, true>& __mp = std::use_facet<moneypunct<char_type, true> >(__loc);202__pat = __mp.neg_format();203__nsn = __mp.negative_sign();204__psn = __mp.positive_sign();205__dp = __mp.decimal_point();206__ts = __mp.thousands_sep();207__grp = __mp.grouping();208__sym = __mp.curr_symbol();209__fd = __mp.frac_digits();210} else {211const moneypunct<char_type, false>& __mp = std::use_facet<moneypunct<char_type, false> >(__loc);212__pat = __mp.neg_format();213__nsn = __mp.negative_sign();214__psn = __mp.positive_sign();215__dp = __mp.decimal_point();216__ts = __mp.thousands_sep();217__grp = __mp.grouping();218__sym = __mp.curr_symbol();219__fd = __mp.frac_digits();220}221}222223extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __money_get<char>;224# if _LIBCPP_HAS_WIDE_CHARACTERS225extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __money_get<wchar_t>;226# endif227228template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >229class money_get : public locale::facet, private __money_get<_CharT> {230public:231typedef _CharT char_type;232typedef _InputIterator iter_type;233typedef basic_string<char_type> string_type;234235_LIBCPP_HIDE_FROM_ABI explicit money_get(size_t __refs = 0) : locale::facet(__refs) {}236237_LIBCPP_HIDE_FROM_ABI iter_type238get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob, ios_base::iostate& __err, long double& __v) const {239return do_get(__b, __e, __intl, __iob, __err, __v);240}241242_LIBCPP_HIDE_FROM_ABI iter_type243get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob, ios_base::iostate& __err, string_type& __v) const {244return do_get(__b, __e, __intl, __iob, __err, __v);245}246247static locale::id id;248249protected:250_LIBCPP_HIDE_FROM_ABI_VIRTUAL ~money_get() override {}251252virtual iter_type253do_get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob, ios_base::iostate& __err, long double& __v) const;254virtual iter_type255do_get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob, ios_base::iostate& __err, string_type& __v) const;256257private:258static bool __do_get(259iter_type& __b,260iter_type __e,261bool __intl,262const locale& __loc,263ios_base::fmtflags __flags,264ios_base::iostate& __err,265bool& __neg,266const ctype<char_type>& __ct,267unique_ptr<char_type, void (*)(void*)>& __wb,268char_type*& __wn,269char_type* __we);270};271272template <class _CharT, class _InputIterator>273locale::id money_get<_CharT, _InputIterator>::id;274275_LIBCPP_EXPORTED_FROM_ABI void __do_nothing(void*);276277template <class _Tp>278_LIBCPP_HIDE_FROM_ABI void __double_or_nothing(unique_ptr<_Tp, void (*)(void*)>& __b, _Tp*& __n, _Tp*& __e) {279bool __owns = __b.get_deleter() != __do_nothing;280size_t __cur_cap = static_cast<size_t>(__e - __b.get()) * sizeof(_Tp);281size_t __new_cap = __cur_cap < numeric_limits<size_t>::max() / 2 ? 2 * __cur_cap : numeric_limits<size_t>::max();282if (__new_cap == 0)283__new_cap = sizeof(_Tp);284size_t __n_off = static_cast<size_t>(__n - __b.get());285_Tp* __t = (_Tp*)std::realloc(__owns ? __b.get() : 0, __new_cap);286if (__t == 0)287std::__throw_bad_alloc();288if (__owns)289__b.release();290else291std::memcpy(__t, __b.get(), __cur_cap);292__b = unique_ptr<_Tp, void (*)(void*)>(__t, free);293__new_cap /= sizeof(_Tp);294__n = __b.get() + __n_off;295__e = __b.get() + __new_cap;296}297298// true == success299template <class _CharT, class _InputIterator>300bool money_get<_CharT, _InputIterator>::__do_get(301iter_type& __b,302iter_type __e,303bool __intl,304const locale& __loc,305ios_base::fmtflags __flags,306ios_base::iostate& __err,307bool& __neg,308const ctype<char_type>& __ct,309unique_ptr<char_type, void (*)(void*)>& __wb,310char_type*& __wn,311char_type* __we) {312if (__b == __e) {313__err |= ios_base::failbit;314return false;315}316const unsigned __bz = 100;317unsigned __gbuf[__bz];318unique_ptr<unsigned, void (*)(void*)> __gb(__gbuf, __do_nothing);319unsigned* __gn = __gb.get();320unsigned* __ge = __gn + __bz;321money_base::pattern __pat;322char_type __dp;323char_type __ts;324string __grp;325string_type __sym;326string_type __psn;327string_type __nsn;328// Capture the spaces read into money_base::{space,none} so they329// can be compared to initial spaces in __sym.330string_type __spaces;331int __fd;332__money_get<_CharT>::__gather_info(__intl, __loc, __pat, __dp, __ts, __grp, __sym, __psn, __nsn, __fd);333const string_type* __trailing_sign = 0;334__wn = __wb.get();335for (unsigned __p = 0; __p < 4 && __b != __e; ++__p) {336switch (__pat.field[__p]) {337case money_base::space:338if (__p != 3) {339if (__ct.is(ctype_base::space, *__b))340__spaces.push_back(*__b++);341else {342__err |= ios_base::failbit;343return false;344}345}346[[__fallthrough__]];347case money_base::none:348if (__p != 3) {349while (__b != __e && __ct.is(ctype_base::space, *__b))350__spaces.push_back(*__b++);351}352break;353case money_base::sign:354if (__psn.size() > 0 && *__b == __psn[0]) {355++__b;356__neg = false;357if (__psn.size() > 1)358__trailing_sign = std::addressof(__psn);359break;360}361if (__nsn.size() > 0 && *__b == __nsn[0]) {362++__b;363__neg = true;364if (__nsn.size() > 1)365__trailing_sign = std::addressof(__nsn);366break;367}368if (__psn.size() > 0 && __nsn.size() > 0) { // sign is required369__err |= ios_base::failbit;370return false;371}372if (__psn.size() == 0 && __nsn.size() == 0)373// locale has no way of specifying a sign. Use the initial value of __neg as a default374break;375__neg = (__nsn.size() == 0);376break;377case money_base::symbol: {378bool __more_needed =379__trailing_sign || (__p < 2) || (__p == 2 && __pat.field[3] != static_cast<char>(money_base::none));380bool __sb = (__flags & ios_base::showbase) != 0;381if (__sb || __more_needed) {382typename string_type::const_iterator __sym_space_end = __sym.begin();383if (__p > 0 && (__pat.field[__p - 1] == money_base::none || __pat.field[__p - 1] == money_base::space)) {384// Match spaces we've already read against spaces at385// the beginning of __sym.386while (__sym_space_end != __sym.end() && __ct.is(ctype_base::space, *__sym_space_end))387++__sym_space_end;388const size_t __num_spaces = __sym_space_end - __sym.begin();389if (__num_spaces > __spaces.size() ||390!std::equal(__spaces.end() - __num_spaces, __spaces.end(), __sym.begin())) {391// No match. Put __sym_space_end back at the392// beginning of __sym, which will prevent a393// match in the next loop.394__sym_space_end = __sym.begin();395}396}397typename string_type::const_iterator __sym_curr_char = __sym_space_end;398while (__sym_curr_char != __sym.end() && __b != __e && *__b == *__sym_curr_char) {399++__b;400++__sym_curr_char;401}402if (__sb && __sym_curr_char != __sym.end()) {403__err |= ios_base::failbit;404return false;405}406}407} break;408case money_base::value: {409unsigned __ng = 0;410for (; __b != __e; ++__b) {411char_type __c = *__b;412if (__ct.is(ctype_base::digit, __c)) {413if (__wn == __we)414std::__double_or_nothing(__wb, __wn, __we);415*__wn++ = __c;416++__ng;417} else if (__grp.size() > 0 && __ng > 0 && __c == __ts) {418if (__gn == __ge)419std::__double_or_nothing(__gb, __gn, __ge);420*__gn++ = __ng;421__ng = 0;422} else423break;424}425if (__gb.get() != __gn && __ng > 0) {426if (__gn == __ge)427std::__double_or_nothing(__gb, __gn, __ge);428*__gn++ = __ng;429}430if (__fd > 0) {431if (__b == __e || *__b != __dp) {432__err |= ios_base::failbit;433return false;434}435for (++__b; __fd > 0; --__fd, ++__b) {436if (__b == __e || !__ct.is(ctype_base::digit, *__b)) {437__err |= ios_base::failbit;438return false;439}440if (__wn == __we)441std::__double_or_nothing(__wb, __wn, __we);442*__wn++ = *__b;443}444}445if (__wn == __wb.get()) {446__err |= ios_base::failbit;447return false;448}449} break;450}451}452if (__trailing_sign) {453for (unsigned __i = 1; __i < __trailing_sign->size(); ++__i, ++__b) {454if (__b == __e || *__b != (*__trailing_sign)[__i]) {455__err |= ios_base::failbit;456return false;457}458}459}460if (__gb.get() != __gn) {461ios_base::iostate __et = ios_base::goodbit;462__check_grouping(__grp, __gb.get(), __gn, __et);463if (__et) {464__err |= ios_base::failbit;465return false;466}467}468return true;469}470471template <class _CharT, class _InputIterator>472_InputIterator money_get<_CharT, _InputIterator>::do_get(473iter_type __b, iter_type __e, bool __intl, ios_base& __iob, ios_base::iostate& __err, long double& __v) const {474const int __bz = 100;475char_type __wbuf[__bz];476unique_ptr<char_type, void (*)(void*)> __wb(__wbuf, __do_nothing);477char_type* __wn;478char_type* __we = __wbuf + __bz;479locale __loc = __iob.getloc();480const ctype<char_type>& __ct = std::use_facet<ctype<char_type> >(__loc);481bool __neg = false;482if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct, __wb, __wn, __we)) {483const char __src[] = "0123456789";484char_type __atoms[sizeof(__src) - 1];485__ct.widen(__src, __src + (sizeof(__src) - 1), __atoms);486char __nbuf[__bz];487char* __nc = __nbuf;488const char* __nc_in = __nc;489unique_ptr<char, void (*)(void*)> __h(nullptr, free);490if (__wn - __wb.get() > __bz - 2) {491__h.reset((char*)malloc(static_cast<size_t>(__wn - __wb.get() + 2)));492if (__h.get() == nullptr)493std::__throw_bad_alloc();494__nc = __h.get();495__nc_in = __nc;496}497if (__neg)498*__nc++ = '-';499for (const char_type* __w = __wb.get(); __w < __wn; ++__w, ++__nc)500*__nc = __src[std::find(__atoms, std::end(__atoms), *__w) - __atoms];501*__nc = char();502if (sscanf(__nc_in, "%Lf", &__v) != 1)503std::__throw_runtime_error("money_get error");504}505if (__b == __e)506__err |= ios_base::eofbit;507return __b;508}509510template <class _CharT, class _InputIterator>511_InputIterator money_get<_CharT, _InputIterator>::do_get(512iter_type __b, iter_type __e, bool __intl, ios_base& __iob, ios_base::iostate& __err, string_type& __v) const {513const int __bz = 100;514char_type __wbuf[__bz];515unique_ptr<char_type, void (*)(void*)> __wb(__wbuf, __do_nothing);516char_type* __wn;517char_type* __we = __wbuf + __bz;518locale __loc = __iob.getloc();519const ctype<char_type>& __ct = std::use_facet<ctype<char_type> >(__loc);520bool __neg = false;521if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct, __wb, __wn, __we)) {522__v.clear();523if (__neg)524__v.push_back(__ct.widen('-'));525char_type __z = __ct.widen('0');526char_type* __w;527for (__w = __wb.get(); __w < __wn - 1; ++__w)528if (*__w != __z)529break;530__v.append(__w, __wn);531}532if (__b == __e)533__err |= ios_base::eofbit;534return __b;535}536537extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS money_get<char>;538# if _LIBCPP_HAS_WIDE_CHARACTERS539extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS money_get<wchar_t>;540# endif541542// money_put543544template <class _CharT>545class __money_put {546protected:547typedef _CharT char_type;548typedef basic_string<char_type> string_type;549550_LIBCPP_HIDE_FROM_ABI __money_put() {}551552static void __gather_info(553bool __intl,554bool __neg,555const locale& __loc,556money_base::pattern& __pat,557char_type& __dp,558char_type& __ts,559string& __grp,560string_type& __sym,561string_type& __sn,562int& __fd);563static void __format(564char_type* __mb,565char_type*& __mi,566char_type*& __me,567ios_base::fmtflags __flags,568const char_type* __db,569const char_type* __de,570const ctype<char_type>& __ct,571bool __neg,572const money_base::pattern& __pat,573char_type __dp,574char_type __ts,575const string& __grp,576const string_type& __sym,577const string_type& __sn,578int __fd);579};580581template <class _CharT>582void __money_put<_CharT>::__gather_info(583bool __intl,584bool __neg,585const locale& __loc,586money_base::pattern& __pat,587char_type& __dp,588char_type& __ts,589string& __grp,590string_type& __sym,591string_type& __sn,592int& __fd) {593if (__intl) {594const moneypunct<char_type, true>& __mp = std::use_facet<moneypunct<char_type, true> >(__loc);595if (__neg) {596__pat = __mp.neg_format();597__sn = __mp.negative_sign();598} else {599__pat = __mp.pos_format();600__sn = __mp.positive_sign();601}602__dp = __mp.decimal_point();603__ts = __mp.thousands_sep();604__grp = __mp.grouping();605__sym = __mp.curr_symbol();606__fd = __mp.frac_digits();607} else {608const moneypunct<char_type, false>& __mp = std::use_facet<moneypunct<char_type, false> >(__loc);609if (__neg) {610__pat = __mp.neg_format();611__sn = __mp.negative_sign();612} else {613__pat = __mp.pos_format();614__sn = __mp.positive_sign();615}616__dp = __mp.decimal_point();617__ts = __mp.thousands_sep();618__grp = __mp.grouping();619__sym = __mp.curr_symbol();620__fd = __mp.frac_digits();621}622}623624template <class _CharT>625void __money_put<_CharT>::__format(626char_type* __mb,627char_type*& __mi,628char_type*& __me,629ios_base::fmtflags __flags,630const char_type* __db,631const char_type* __de,632const ctype<char_type>& __ct,633bool __neg,634const money_base::pattern& __pat,635char_type __dp,636char_type __ts,637const string& __grp,638const string_type& __sym,639const string_type& __sn,640int __fd) {641__me = __mb;642for (char __p : __pat.field) {643switch (__p) {644case money_base::none:645__mi = __me;646break;647case money_base::space:648__mi = __me;649*__me++ = __ct.widen(' ');650break;651case money_base::sign:652if (!__sn.empty())653*__me++ = __sn[0];654break;655case money_base::symbol:656if (!__sym.empty() && (__flags & ios_base::showbase))657__me = std::copy(__sym.begin(), __sym.end(), __me);658break;659case money_base::value: {660// remember start of value so we can reverse it661char_type* __t = __me;662// find beginning of digits663if (__neg)664++__db;665// find end of digits666const char_type* __d;667for (__d = __db; __d < __de; ++__d)668if (!__ct.is(ctype_base::digit, *__d))669break;670// print fractional part671if (__fd > 0) {672int __f;673for (__f = __fd; __d > __db && __f > 0; --__f)674*__me++ = *--__d;675char_type __z = __f > 0 ? __ct.widen('0') : char_type();676for (; __f > 0; --__f)677*__me++ = __z;678*__me++ = __dp;679}680// print units part681if (__d == __db) {682*__me++ = __ct.widen('0');683} else {684unsigned __ng = 0;685unsigned __ig = 0;686unsigned __gl = __grp.empty() ? numeric_limits<unsigned>::max() : static_cast<unsigned>(__grp[__ig]);687while (__d != __db) {688if (__ng == __gl) {689*__me++ = __ts;690__ng = 0;691if (++__ig < __grp.size())692__gl = __grp[__ig] == numeric_limits<char>::max()693? numeric_limits<unsigned>::max()694: static_cast<unsigned>(__grp[__ig]);695}696*__me++ = *--__d;697++__ng;698}699}700// reverse it701std::reverse(__t, __me);702} break;703}704}705// print rest of sign, if any706if (__sn.size() > 1)707__me = std::copy(__sn.begin() + 1, __sn.end(), __me);708// set alignment709if ((__flags & ios_base::adjustfield) == ios_base::left)710__mi = __me;711else if ((__flags & ios_base::adjustfield) != ios_base::internal)712__mi = __mb;713}714715extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __money_put<char>;716# if _LIBCPP_HAS_WIDE_CHARACTERS717extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __money_put<wchar_t>;718# endif719720template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >721class money_put : public locale::facet, private __money_put<_CharT> {722public:723typedef _CharT char_type;724typedef _OutputIterator iter_type;725typedef basic_string<char_type> string_type;726727_LIBCPP_HIDE_FROM_ABI explicit money_put(size_t __refs = 0) : locale::facet(__refs) {}728729_LIBCPP_HIDE_FROM_ABI iter_type730put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl, long double __units) const {731return do_put(__s, __intl, __iob, __fl, __units);732}733734_LIBCPP_HIDE_FROM_ABI iter_type735put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl, const string_type& __digits) const {736return do_put(__s, __intl, __iob, __fl, __digits);737}738739static locale::id id;740741protected:742_LIBCPP_HIDE_FROM_ABI_VIRTUAL ~money_put() override {}743744virtual iter_type do_put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl, long double __units) const;745virtual iter_type746do_put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl, const string_type& __digits) const;747};748749template <class _CharT, class _OutputIterator>750locale::id money_put<_CharT, _OutputIterator>::id;751752template <class _CharT, class _OutputIterator>753_OutputIterator money_put<_CharT, _OutputIterator>::do_put(754iter_type __s, bool __intl, ios_base& __iob, char_type __fl, long double __units) const {755// convert to char756const size_t __bs = 100;757char __buf[__bs];758char* __bb = __buf;759char_type __digits[__bs];760char_type* __db = __digits;761int __n = snprintf(__bb, __bs, "%.0Lf", __units);762unique_ptr<char, void (*)(void*)> __hn(nullptr, free);763unique_ptr<char_type, void (*)(void*)> __hd(0, free);764// secure memory for digit storage765if (static_cast<size_t>(__n) > __bs - 1) {766__n = __locale::__asprintf(&__bb, _LIBCPP_GET_C_LOCALE, "%.0Lf", __units);767if (__n == -1)768std::__throw_bad_alloc();769__hn.reset(__bb);770__hd.reset((char_type*)malloc(static_cast<size_t>(__n) * sizeof(char_type)));771if (__hd == nullptr)772std::__throw_bad_alloc();773__db = __hd.get();774}775// gather info776locale __loc = __iob.getloc();777const ctype<char_type>& __ct = std::use_facet<ctype<char_type> >(__loc);778__ct.widen(__bb, __bb + __n, __db);779bool __neg = __n > 0 && __bb[0] == '-';780money_base::pattern __pat;781char_type __dp;782char_type __ts;783string __grp;784string_type __sym;785string_type __sn;786int __fd;787this->__gather_info(__intl, __neg, __loc, __pat, __dp, __ts, __grp, __sym, __sn, __fd);788// secure memory for formatting789char_type __mbuf[__bs];790char_type* __mb = __mbuf;791unique_ptr<char_type, void (*)(void*)> __hw(0, free);792size_t __exn = __n > __fd ? (static_cast<size_t>(__n) - static_cast<size_t>(__fd)) * 2 + __sn.size() + __sym.size() +793static_cast<size_t>(__fd) + 1794: __sn.size() + __sym.size() + static_cast<size_t>(__fd) + 2;795if (__exn > __bs) {796__hw.reset((char_type*)malloc(__exn * sizeof(char_type)));797__mb = __hw.get();798if (__mb == 0)799std::__throw_bad_alloc();800}801// format802char_type* __mi;803char_type* __me;804this->__format(805__mb, __mi, __me, __iob.flags(), __db, __db + __n, __ct, __neg, __pat, __dp, __ts, __grp, __sym, __sn, __fd);806return std::__pad_and_output(__s, __mb, __mi, __me, __iob, __fl);807}808809template <class _CharT, class _OutputIterator>810_OutputIterator money_put<_CharT, _OutputIterator>::do_put(811iter_type __s, bool __intl, ios_base& __iob, char_type __fl, const string_type& __digits) const {812// gather info813locale __loc = __iob.getloc();814const ctype<char_type>& __ct = std::use_facet<ctype<char_type> >(__loc);815bool __neg = __digits.size() > 0 && __digits[0] == __ct.widen('-');816money_base::pattern __pat;817char_type __dp;818char_type __ts;819string __grp;820string_type __sym;821string_type __sn;822int __fd;823this->__gather_info(__intl, __neg, __loc, __pat, __dp, __ts, __grp, __sym, __sn, __fd);824// secure memory for formatting825char_type __mbuf[100];826char_type* __mb = __mbuf;827unique_ptr<char_type, void (*)(void*)> __h(0, free);828size_t __exn =829static_cast<int>(__digits.size()) > __fd830? (__digits.size() - static_cast<size_t>(__fd)) * 2 + __sn.size() + __sym.size() + static_cast<size_t>(__fd) +8311832: __sn.size() + __sym.size() + static_cast<size_t>(__fd) + 2;833if (__exn > 100) {834__h.reset((char_type*)malloc(__exn * sizeof(char_type)));835__mb = __h.get();836if (__mb == 0)837std::__throw_bad_alloc();838}839// format840char_type* __mi;841char_type* __me;842this->__format(843__mb,844__mi,845__me,846__iob.flags(),847__digits.data(),848__digits.data() + __digits.size(),849__ct,850__neg,851__pat,852__dp,853__ts,854__grp,855__sym,856__sn,857__fd);858return std::__pad_and_output(__s, __mb, __mi, __me, __iob, __fl);859}860861extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS money_put<char>;862# if _LIBCPP_HAS_WIDE_CHARACTERS863extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS money_put<wchar_t>;864# endif865866_LIBCPP_END_NAMESPACE_STD867868_LIBCPP_POP_MACROS869870#endif // _LIBCPP_HAS_LOCALIZATION871872#endif // _LIBCPP___LOCALE_DIR_MONEY_H873874875