blob: c1296665505e164851368427381bcddf36127916 [file] [log] [blame] [edit]
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef _LIBCPP___LOCALE_DIR_MONEY_H
#define _LIBCPP___LOCALE_DIR_MONEY_H
#include <__algorithm/copy.h>
#include <__algorithm/equal.h>
#include <__algorithm/find.h>
#include <__algorithm/reverse.h>
#include <__config>
#include <__locale>
#include <__locale_dir/check_grouping.h>
#include <__locale_dir/get_c_locale.h>
#include <__locale_dir/pad_and_output.h>
#include <__memory/unique_ptr.h>
#include <ios>
#include <string>
#if _LIBCPP_HAS_LOCALIZATION
# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
# endif
_LIBCPP_PUSH_MACROS
# include <__undef_macros>
_LIBCPP_BEGIN_NAMESPACE_STD
// money_base
class _LIBCPP_EXPORTED_FROM_ABI money_base {
public:
enum part { none, space, symbol, sign, value };
struct pattern {
char field[4];
};
_LIBCPP_HIDE_FROM_ABI money_base() {}
};
// moneypunct
template <class _CharT, bool _International = false>
class moneypunct : public locale::facet, public money_base {
public:
typedef _CharT char_type;
typedef basic_string<char_type> string_type;
_LIBCPP_HIDE_FROM_ABI explicit moneypunct(size_t __refs = 0) : locale::facet(__refs) {}
_LIBCPP_HIDE_FROM_ABI char_type decimal_point() const { return do_decimal_point(); }
_LIBCPP_HIDE_FROM_ABI char_type thousands_sep() const { return do_thousands_sep(); }
_LIBCPP_HIDE_FROM_ABI string grouping() const { return do_grouping(); }
_LIBCPP_HIDE_FROM_ABI string_type curr_symbol() const { return do_curr_symbol(); }
_LIBCPP_HIDE_FROM_ABI string_type positive_sign() const { return do_positive_sign(); }
_LIBCPP_HIDE_FROM_ABI string_type negative_sign() const { return do_negative_sign(); }
_LIBCPP_HIDE_FROM_ABI int frac_digits() const { return do_frac_digits(); }
_LIBCPP_HIDE_FROM_ABI pattern pos_format() const { return do_pos_format(); }
_LIBCPP_HIDE_FROM_ABI pattern neg_format() const { return do_neg_format(); }
static locale::id id;
static const bool intl = _International;
protected:
_LIBCPP_HIDE_FROM_ABI_VIRTUAL ~moneypunct() override {}
virtual char_type do_decimal_point() const { return numeric_limits<char_type>::max(); }
virtual char_type do_thousands_sep() const { return numeric_limits<char_type>::max(); }
virtual string do_grouping() const { return string(); }
virtual string_type do_curr_symbol() const { return string_type(); }
virtual string_type do_positive_sign() const { return string_type(); }
virtual string_type do_negative_sign() const { return string_type(1, '-'); }
virtual int do_frac_digits() const { return 0; }
virtual pattern do_pos_format() const {
pattern __p = {{symbol, sign, none, value}};
return __p;
}
virtual pattern do_neg_format() const {
pattern __p = {{symbol, sign, none, value}};
return __p;
}
};
template <class _CharT, bool _International>
locale::id moneypunct<_CharT, _International>::id;
template <class _CharT, bool _International>
const bool moneypunct<_CharT, _International>::intl;
extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct<char, false>;
extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct<char, true>;
# if _LIBCPP_HAS_WIDE_CHARACTERS
extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct<wchar_t, false>;
extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct<wchar_t, true>;
# endif
// moneypunct_byname
template <class _CharT, bool _International = false>
class moneypunct_byname : public moneypunct<_CharT, _International> {
public:
typedef money_base::pattern pattern;
typedef _CharT char_type;
typedef basic_string<char_type> string_type;
_LIBCPP_HIDE_FROM_ABI explicit moneypunct_byname(const char* __nm, size_t __refs = 0)
: moneypunct<_CharT, _International>(__refs) {
init(__nm);
}
_LIBCPP_HIDE_FROM_ABI explicit moneypunct_byname(const string& __nm, size_t __refs = 0)
: moneypunct<_CharT, _International>(__refs) {
init(__nm.c_str());
}
protected:
_LIBCPP_HIDE_FROM_ABI_VIRTUAL ~moneypunct_byname() override {}
char_type do_decimal_point() const override { return __decimal_point_; }
char_type do_thousands_sep() const override { return __thousands_sep_; }
string do_grouping() const override { return __grouping_; }
string_type do_curr_symbol() const override { return __curr_symbol_; }
string_type do_positive_sign() const override { return __positive_sign_; }
string_type do_negative_sign() const override { return __negative_sign_; }
int do_frac_digits() const override { return __frac_digits_; }
pattern do_pos_format() const override { return __pos_format_; }
pattern do_neg_format() const override { return __neg_format_; }
private:
char_type __decimal_point_;
char_type __thousands_sep_;
string __grouping_;
string_type __curr_symbol_;
string_type __positive_sign_;
string_type __negative_sign_;
int __frac_digits_;
pattern __pos_format_;
pattern __neg_format_;
void init(const char*);
};
template <>
_LIBCPP_EXPORTED_FROM_ABI void moneypunct_byname<char, false>::init(const char*);
template <>
_LIBCPP_EXPORTED_FROM_ABI void moneypunct_byname<char, true>::init(const char*);
extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct_byname<char, false>;
extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct_byname<char, true>;
# if _LIBCPP_HAS_WIDE_CHARACTERS
template <>
_LIBCPP_EXPORTED_FROM_ABI void moneypunct_byname<wchar_t, false>::init(const char*);
template <>
_LIBCPP_EXPORTED_FROM_ABI void moneypunct_byname<wchar_t, true>::init(const char*);
extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct_byname<wchar_t, false>;
extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct_byname<wchar_t, true>;
# endif
// money_get
template <class _CharT>
class __money_get {
protected:
typedef _CharT char_type;
typedef basic_string<char_type> string_type;
_LIBCPP_HIDE_FROM_ABI __money_get() {}
static void __gather_info(
bool __intl,
const locale& __loc,
money_base::pattern& __pat,
char_type& __dp,
char_type& __ts,
string& __grp,
string_type& __sym,
string_type& __psn,
string_type& __nsn,
int& __fd);
};
template <class _CharT>
void __money_get<_CharT>::__gather_info(
bool __intl,
const locale& __loc,
money_base::pattern& __pat,
char_type& __dp,
char_type& __ts,
string& __grp,
string_type& __sym,
string_type& __psn,
string_type& __nsn,
int& __fd) {
if (__intl) {
const moneypunct<char_type, true>& __mp = std::use_facet<moneypunct<char_type, true> >(__loc);
__pat = __mp.neg_format();
__nsn = __mp.negative_sign();
__psn = __mp.positive_sign();
__dp = __mp.decimal_point();
__ts = __mp.thousands_sep();
__grp = __mp.grouping();
__sym = __mp.curr_symbol();
__fd = __mp.frac_digits();
} else {
const moneypunct<char_type, false>& __mp = std::use_facet<moneypunct<char_type, false> >(__loc);
__pat = __mp.neg_format();
__nsn = __mp.negative_sign();
__psn = __mp.positive_sign();
__dp = __mp.decimal_point();
__ts = __mp.thousands_sep();
__grp = __mp.grouping();
__sym = __mp.curr_symbol();
__fd = __mp.frac_digits();
}
}
extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __money_get<char>;
# if _LIBCPP_HAS_WIDE_CHARACTERS
extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __money_get<wchar_t>;
# endif
template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
class money_get : public locale::facet, private __money_get<_CharT> {
public:
typedef _CharT char_type;
typedef _InputIterator iter_type;
typedef basic_string<char_type> string_type;
_LIBCPP_HIDE_FROM_ABI explicit money_get(size_t __refs = 0) : locale::facet(__refs) {}
_LIBCPP_HIDE_FROM_ABI iter_type
get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob, ios_base::iostate& __err, long double& __v) const {
return do_get(__b, __e, __intl, __iob, __err, __v);
}
_LIBCPP_HIDE_FROM_ABI iter_type
get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob, ios_base::iostate& __err, string_type& __v) const {
return do_get(__b, __e, __intl, __iob, __err, __v);
}
static locale::id id;
protected:
_LIBCPP_HIDE_FROM_ABI_VIRTUAL ~money_get() override {}
virtual iter_type
do_get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob, ios_base::iostate& __err, long double& __v) const;
virtual iter_type
do_get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob, ios_base::iostate& __err, string_type& __v) const;
private:
static bool __do_get(
iter_type& __b,
iter_type __e,
bool __intl,
const locale& __loc,
ios_base::fmtflags __flags,
ios_base::iostate& __err,
bool& __neg,
const ctype<char_type>& __ct,
unique_ptr<char_type, void (*)(void*)>& __wb,
char_type*& __wn,
char_type* __we);
};
template <class _CharT, class _InputIterator>
locale::id money_get<_CharT, _InputIterator>::id;
_LIBCPP_EXPORTED_FROM_ABI void __do_nothing(void*);
template <class _Tp>
_LIBCPP_HIDE_FROM_ABI void __double_or_nothing(unique_ptr<_Tp, void (*)(void*)>& __b, _Tp*& __n, _Tp*& __e) {
bool __owns = __b.get_deleter() != __do_nothing;
size_t __cur_cap = static_cast<size_t>(__e - __b.get()) * sizeof(_Tp);
size_t __new_cap = __cur_cap < numeric_limits<size_t>::max() / 2 ? 2 * __cur_cap : numeric_limits<size_t>::max();
if (__new_cap == 0)
__new_cap = sizeof(_Tp);
size_t __n_off = static_cast<size_t>(__n - __b.get());
_Tp* __t = (_Tp*)std::realloc(__owns ? __b.get() : 0, __new_cap);
if (__t == 0)
std::__throw_bad_alloc();
if (__owns)
__b.release();
else
std::memcpy(__t, __b.get(), __cur_cap);
__b = unique_ptr<_Tp, void (*)(void*)>(__t, free);
__new_cap /= sizeof(_Tp);
__n = __b.get() + __n_off;
__e = __b.get() + __new_cap;
}
// true == success
template <class _CharT, class _InputIterator>
bool money_get<_CharT, _InputIterator>::__do_get(
iter_type& __b,
iter_type __e,
bool __intl,
const locale& __loc,
ios_base::fmtflags __flags,
ios_base::iostate& __err,
bool& __neg,
const ctype<char_type>& __ct,
unique_ptr<char_type, void (*)(void*)>& __wb,
char_type*& __wn,
char_type* __we) {
if (__b == __e) {
__err |= ios_base::failbit;
return false;
}
const unsigned __bz = 100;
unsigned __gbuf[__bz];
unique_ptr<unsigned, void (*)(void*)> __gb(__gbuf, __do_nothing);
unsigned* __gn = __gb.get();
unsigned* __ge = __gn + __bz;
money_base::pattern __pat;
char_type __dp;
char_type __ts;
string __grp;
string_type __sym;
string_type __psn;
string_type __nsn;
// Capture the spaces read into money_base::{space,none} so they
// can be compared to initial spaces in __sym.
string_type __spaces;
int __fd;
__money_get<_CharT>::__gather_info(__intl, __loc, __pat, __dp, __ts, __grp, __sym, __psn, __nsn, __fd);
const string_type* __trailing_sign = 0;
__wn = __wb.get();
for (unsigned __p = 0; __p < 4 && __b != __e; ++__p) {
switch (__pat.field[__p]) {
case money_base::space:
if (__p != 3) {
if (__ct.is(ctype_base::space, *__b))
__spaces.push_back(*__b++);
else {
__err |= ios_base::failbit;
return false;
}
}
[[__fallthrough__]];
case money_base::none:
if (__p != 3) {
while (__b != __e && __ct.is(ctype_base::space, *__b))
__spaces.push_back(*__b++);
}
break;
case money_base::sign:
if (__psn.size() > 0 && *__b == __psn[0]) {
++__b;
__neg = false;
if (__psn.size() > 1)
__trailing_sign = std::addressof(__psn);
break;
}
if (__nsn.size() > 0 && *__b == __nsn[0]) {
++__b;
__neg = true;
if (__nsn.size() > 1)
__trailing_sign = std::addressof(__nsn);
break;
}
if (__psn.size() > 0 && __nsn.size() > 0) { // sign is required
__err |= ios_base::failbit;
return false;
}
if (__psn.size() == 0 && __nsn.size() == 0)
// locale has no way of specifying a sign. Use the initial value of __neg as a default
break;
__neg = (__nsn.size() == 0);
break;
case money_base::symbol: {
bool __more_needed =
__trailing_sign || (__p < 2) || (__p == 2 && __pat.field[3] != static_cast<char>(money_base::none));
bool __sb = (__flags & ios_base::showbase) != 0;
if (__sb || __more_needed) {
typename string_type::const_iterator __sym_space_end = __sym.begin();
if (__p > 0 && (__pat.field[__p - 1] == money_base::none || __pat.field[__p - 1] == money_base::space)) {
// Match spaces we've already read against spaces at
// the beginning of __sym.
while (__sym_space_end != __sym.end() && __ct.is(ctype_base::space, *__sym_space_end))
++__sym_space_end;
const size_t __num_spaces = __sym_space_end - __sym.begin();
if (__num_spaces > __spaces.size() ||
!std::equal(__spaces.end() - __num_spaces, __spaces.end(), __sym.begin())) {
// No match. Put __sym_space_end back at the
// beginning of __sym, which will prevent a
// match in the next loop.
__sym_space_end = __sym.begin();
}
}
typename string_type::const_iterator __sym_curr_char = __sym_space_end;
while (__sym_curr_char != __sym.end() && __b != __e && *__b == *__sym_curr_char) {
++__b;
++__sym_curr_char;
}
if (__sb && __sym_curr_char != __sym.end()) {
__err |= ios_base::failbit;
return false;
}
}
} break;
case money_base::value: {
unsigned __ng = 0;
for (; __b != __e; ++__b) {
char_type __c = *__b;
if (__ct.is(ctype_base::digit, __c)) {
if (__wn == __we)
std::__double_or_nothing(__wb, __wn, __we);
*__wn++ = __c;
++__ng;
} else if (__grp.size() > 0 && __ng > 0 && __c == __ts) {
if (__gn == __ge)
std::__double_or_nothing(__gb, __gn, __ge);
*__gn++ = __ng;
__ng = 0;
} else
break;
}
if (__gb.get() != __gn && __ng > 0) {
if (__gn == __ge)
std::__double_or_nothing(__gb, __gn, __ge);
*__gn++ = __ng;
}
if (__fd > 0) {
if (__b == __e || *__b != __dp) {
__err |= ios_base::failbit;
return false;
}
for (++__b; __fd > 0; --__fd, ++__b) {
if (__b == __e || !__ct.is(ctype_base::digit, *__b)) {
__err |= ios_base::failbit;
return false;
}
if (__wn == __we)
std::__double_or_nothing(__wb, __wn, __we);
*__wn++ = *__b;
}
}
if (__wn == __wb.get()) {
__err |= ios_base::failbit;
return false;
}
} break;
}
}
if (__trailing_sign) {
for (unsigned __i = 1; __i < __trailing_sign->size(); ++__i, ++__b) {
if (__b == __e || *__b != (*__trailing_sign)[__i]) {
__err |= ios_base::failbit;
return false;
}
}
}
if (__gb.get() != __gn) {
ios_base::iostate __et = ios_base::goodbit;
__check_grouping(__grp, __gb.get(), __gn, __et);
if (__et) {
__err |= ios_base::failbit;
return false;
}
}
return true;
}
template <class _CharT, class _InputIterator>
_InputIterator money_get<_CharT, _InputIterator>::do_get(
iter_type __b, iter_type __e, bool __intl, ios_base& __iob, ios_base::iostate& __err, long double& __v) const {
const int __bz = 100;
char_type __wbuf[__bz];
unique_ptr<char_type, void (*)(void*)> __wb(__wbuf, __do_nothing);
char_type* __wn;
char_type* __we = __wbuf + __bz;
locale __loc = __iob.getloc();
const ctype<char_type>& __ct = std::use_facet<ctype<char_type> >(__loc);
bool __neg = false;
if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct, __wb, __wn, __we)) {
const char __src[] = "0123456789";
char_type __atoms[sizeof(__src) - 1];
__ct.widen(__src, __src + (sizeof(__src) - 1), __atoms);
char __nbuf[__bz];
char* __nc = __nbuf;
const char* __nc_in = __nc;
unique_ptr<char, void (*)(void*)> __h(nullptr, free);
if (__wn - __wb.get() > __bz - 2) {
__h.reset((char*)malloc(static_cast<size_t>(__wn - __wb.get() + 2)));
if (__h.get() == nullptr)
std::__throw_bad_alloc();
__nc = __h.get();
__nc_in = __nc;
}
if (__neg)
*__nc++ = '-';
for (const char_type* __w = __wb.get(); __w < __wn; ++__w, ++__nc)
*__nc = __src[std::find(__atoms, std::end(__atoms), *__w) - __atoms];
*__nc = char();
if (sscanf(__nc_in, "%Lf", &__v) != 1)
std::__throw_runtime_error("money_get error");
}
if (__b == __e)
__err |= ios_base::eofbit;
return __b;
}
template <class _CharT, class _InputIterator>
_InputIterator money_get<_CharT, _InputIterator>::do_get(
iter_type __b, iter_type __e, bool __intl, ios_base& __iob, ios_base::iostate& __err, string_type& __v) const {
const int __bz = 100;
char_type __wbuf[__bz];
unique_ptr<char_type, void (*)(void*)> __wb(__wbuf, __do_nothing);
char_type* __wn;
char_type* __we = __wbuf + __bz;
locale __loc = __iob.getloc();
const ctype<char_type>& __ct = std::use_facet<ctype<char_type> >(__loc);
bool __neg = false;
if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct, __wb, __wn, __we)) {
__v.clear();
if (__neg)
__v.push_back(__ct.widen('-'));
char_type __z = __ct.widen('0');
char_type* __w;
for (__w = __wb.get(); __w < __wn - 1; ++__w)
if (*__w != __z)
break;
__v.append(__w, __wn);
}
if (__b == __e)
__err |= ios_base::eofbit;
return __b;
}
extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS money_get<char>;
# if _LIBCPP_HAS_WIDE_CHARACTERS
extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS money_get<wchar_t>;
# endif
// money_put
template <class _CharT>
class __money_put {
protected:
typedef _CharT char_type;
typedef basic_string<char_type> string_type;
_LIBCPP_HIDE_FROM_ABI __money_put() {}
static void __gather_info(
bool __intl,
bool __neg,
const locale& __loc,
money_base::pattern& __pat,
char_type& __dp,
char_type& __ts,
string& __grp,
string_type& __sym,
string_type& __sn,
int& __fd);
static void __format(
char_type* __mb,
char_type*& __mi,
char_type*& __me,
ios_base::fmtflags __flags,
const char_type* __db,
const char_type* __de,
const ctype<char_type>& __ct,
bool __neg,
const money_base::pattern& __pat,
char_type __dp,
char_type __ts,
const string& __grp,
const string_type& __sym,
const string_type& __sn,
int __fd);
};
template <class _CharT>
void __money_put<_CharT>::__gather_info(
bool __intl,
bool __neg,
const locale& __loc,
money_base::pattern& __pat,
char_type& __dp,
char_type& __ts,
string& __grp,
string_type& __sym,
string_type& __sn,
int& __fd) {
if (__intl) {
const moneypunct<char_type, true>& __mp = std::use_facet<moneypunct<char_type, true> >(__loc);
if (__neg) {
__pat = __mp.neg_format();
__sn = __mp.negative_sign();
} else {
__pat = __mp.pos_format();
__sn = __mp.positive_sign();
}
__dp = __mp.decimal_point();
__ts = __mp.thousands_sep();
__grp = __mp.grouping();
__sym = __mp.curr_symbol();
__fd = __mp.frac_digits();
} else {
const moneypunct<char_type, false>& __mp = std::use_facet<moneypunct<char_type, false> >(__loc);
if (__neg) {
__pat = __mp.neg_format();
__sn = __mp.negative_sign();
} else {
__pat = __mp.pos_format();
__sn = __mp.positive_sign();
}
__dp = __mp.decimal_point();
__ts = __mp.thousands_sep();
__grp = __mp.grouping();
__sym = __mp.curr_symbol();
__fd = __mp.frac_digits();
}
}
template <class _CharT>
void __money_put<_CharT>::__format(
char_type* __mb,
char_type*& __mi,
char_type*& __me,
ios_base::fmtflags __flags,
const char_type* __db,
const char_type* __de,
const ctype<char_type>& __ct,
bool __neg,
const money_base::pattern& __pat,
char_type __dp,
char_type __ts,
const string& __grp,
const string_type& __sym,
const string_type& __sn,
int __fd) {
__me = __mb;
for (char __p : __pat.field) {
switch (__p) {
case money_base::none:
__mi = __me;
break;
case money_base::space:
__mi = __me;
*__me++ = __ct.widen(' ');
break;
case money_base::sign:
if (!__sn.empty())
*__me++ = __sn[0];
break;
case money_base::symbol:
if (!__sym.empty() && (__flags & ios_base::showbase))
__me = std::copy(__sym.begin(), __sym.end(), __me);
break;
case money_base::value: {
// remember start of value so we can reverse it
char_type* __t = __me;
// find beginning of digits
if (__neg)
++__db;
// find end of digits
const char_type* __d;
for (__d = __db; __d < __de; ++__d)
if (!__ct.is(ctype_base::digit, *__d))
break;
// print fractional part
if (__fd > 0) {
int __f;
for (__f = __fd; __d > __db && __f > 0; --__f)
*__me++ = *--__d;
char_type __z = __f > 0 ? __ct.widen('0') : char_type();
for (; __f > 0; --__f)
*__me++ = __z;
*__me++ = __dp;
}
// print units part
if (__d == __db) {
*__me++ = __ct.widen('0');
} else {
unsigned __ng = 0;
unsigned __ig = 0;
unsigned __gl = __grp.empty() ? numeric_limits<unsigned>::max() : static_cast<unsigned>(__grp[__ig]);
while (__d != __db) {
if (__ng == __gl) {
*__me++ = __ts;
__ng = 0;
if (++__ig < __grp.size())
__gl = __grp[__ig] == numeric_limits<char>::max()
? numeric_limits<unsigned>::max()
: static_cast<unsigned>(__grp[__ig]);
}
*__me++ = *--__d;
++__ng;
}
}
// reverse it
std::reverse(__t, __me);
} break;
}
}
// print rest of sign, if any
if (__sn.size() > 1)
__me = std::copy(__sn.begin() + 1, __sn.end(), __me);
// set alignment
if ((__flags & ios_base::adjustfield) == ios_base::left)
__mi = __me;
else if ((__flags & ios_base::adjustfield) != ios_base::internal)
__mi = __mb;
}
extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __money_put<char>;
# if _LIBCPP_HAS_WIDE_CHARACTERS
extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __money_put<wchar_t>;
# endif
template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
class money_put : public locale::facet, private __money_put<_CharT> {
public:
typedef _CharT char_type;
typedef _OutputIterator iter_type;
typedef basic_string<char_type> string_type;
_LIBCPP_HIDE_FROM_ABI explicit money_put(size_t __refs = 0) : locale::facet(__refs) {}
_LIBCPP_HIDE_FROM_ABI iter_type
put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl, long double __units) const {
return do_put(__s, __intl, __iob, __fl, __units);
}
_LIBCPP_HIDE_FROM_ABI iter_type
put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl, const string_type& __digits) const {
return do_put(__s, __intl, __iob, __fl, __digits);
}
static locale::id id;
protected:
_LIBCPP_HIDE_FROM_ABI_VIRTUAL ~money_put() override {}
virtual iter_type do_put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl, long double __units) const;
virtual iter_type
do_put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl, const string_type& __digits) const;
};
template <class _CharT, class _OutputIterator>
locale::id money_put<_CharT, _OutputIterator>::id;
template <class _CharT, class _OutputIterator>
_OutputIterator money_put<_CharT, _OutputIterator>::do_put(
iter_type __s, bool __intl, ios_base& __iob, char_type __fl, long double __units) const {
// convert to char
const size_t __bs = 100;
char __buf[__bs];
char* __bb = __buf;
char_type __digits[__bs];
char_type* __db = __digits;
int __n = snprintf(__bb, __bs, "%.0Lf", __units);
unique_ptr<char, void (*)(void*)> __hn(nullptr, free);
unique_ptr<char_type, void (*)(void*)> __hd(0, free);
// secure memory for digit storage
if (static_cast<size_t>(__n) > __bs - 1) {
__n = __locale::__asprintf(&__bb, _LIBCPP_GET_C_LOCALE, "%.0Lf", __units);
if (__n == -1)
std::__throw_bad_alloc();
__hn.reset(__bb);
__hd.reset((char_type*)malloc(static_cast<size_t>(__n) * sizeof(char_type)));
if (__hd == nullptr)
std::__throw_bad_alloc();
__db = __hd.get();
}
// gather info
locale __loc = __iob.getloc();
const ctype<char_type>& __ct = std::use_facet<ctype<char_type> >(__loc);
__ct.widen(__bb, __bb + __n, __db);
bool __neg = __n > 0 && __bb[0] == '-';
money_base::pattern __pat;
char_type __dp;
char_type __ts;
string __grp;
string_type __sym;
string_type __sn;
int __fd;
this->__gather_info(__intl, __neg, __loc, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
// secure memory for formatting
char_type __mbuf[__bs];
char_type* __mb = __mbuf;
unique_ptr<char_type, void (*)(void*)> __hw(0, free);
size_t __exn = __n > __fd ? (static_cast<size_t>(__n) - static_cast<size_t>(__fd)) * 2 + __sn.size() + __sym.size() +
static_cast<size_t>(__fd) + 1
: __sn.size() + __sym.size() + static_cast<size_t>(__fd) + 2;
if (__exn > __bs) {
__hw.reset((char_type*)malloc(__exn * sizeof(char_type)));
__mb = __hw.get();
if (__mb == 0)
std::__throw_bad_alloc();
}
// format
char_type* __mi;
char_type* __me;
this->__format(
__mb, __mi, __me, __iob.flags(), __db, __db + __n, __ct, __neg, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
return std::__pad_and_output(__s, __mb, __mi, __me, __iob, __fl);
}
template <class _CharT, class _OutputIterator>
_OutputIterator money_put<_CharT, _OutputIterator>::do_put(
iter_type __s, bool __intl, ios_base& __iob, char_type __fl, const string_type& __digits) const {
// gather info
locale __loc = __iob.getloc();
const ctype<char_type>& __ct = std::use_facet<ctype<char_type> >(__loc);
bool __neg = __digits.size() > 0 && __digits[0] == __ct.widen('-');
money_base::pattern __pat;
char_type __dp;
char_type __ts;
string __grp;
string_type __sym;
string_type __sn;
int __fd;
this->__gather_info(__intl, __neg, __loc, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
// secure memory for formatting
char_type __mbuf[100];
char_type* __mb = __mbuf;
unique_ptr<char_type, void (*)(void*)> __h(0, free);
size_t __exn =
static_cast<int>(__digits.size()) > __fd
? (__digits.size() - static_cast<size_t>(__fd)) * 2 + __sn.size() + __sym.size() + static_cast<size_t>(__fd) +
1
: __sn.size() + __sym.size() + static_cast<size_t>(__fd) + 2;
if (__exn > 100) {
__h.reset((char_type*)malloc(__exn * sizeof(char_type)));
__mb = __h.get();
if (__mb == 0)
std::__throw_bad_alloc();
}
// format
char_type* __mi;
char_type* __me;
this->__format(
__mb,
__mi,
__me,
__iob.flags(),
__digits.data(),
__digits.data() + __digits.size(),
__ct,
__neg,
__pat,
__dp,
__ts,
__grp,
__sym,
__sn,
__fd);
return std::__pad_and_output(__s, __mb, __mi, __me, __iob, __fl);
}
extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS money_put<char>;
# if _LIBCPP_HAS_WIDE_CHARACTERS
extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS money_put<wchar_t>;
# endif
_LIBCPP_END_NAMESPACE_STD
_LIBCPP_POP_MACROS
#endif // _LIBCPP_HAS_LOCALIZATION
#endif // _LIBCPP___LOCALE_DIR_MONEY_H