mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-07 14:24:43 +00:00
873 lines
29 KiB
C++
Vendored
873 lines
29 KiB
C++
Vendored
//===----------------------------------------------------------------------===//
|
|
//
|
|
// 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
|