brintos

brintos / llvm-project-archived public Read only

0
0
Text · 28.7 KiB · 12ba384 Raw
874 lines · c
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef _LIBCPP___LOCALE_DIR_MONEY_H10#define _LIBCPP___LOCALE_DIR_MONEY_H11 12#include <__algorithm/copy.h>13#include <__algorithm/equal.h>14#include <__algorithm/find.h>15#include <__algorithm/reverse.h>16#include <__config>17#include <__locale>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 <__memory/unique_ptr.h>22#include <ios>23#include <string>24 25#if _LIBCPP_HAS_LOCALIZATION26 27#  if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)28#    pragma GCC system_header29#  endif30 31_LIBCPP_PUSH_MACROS32#  include <__undef_macros>33 34_LIBCPP_BEGIN_NAMESPACE_STD35 36// money_base37 38class _LIBCPP_EXPORTED_FROM_ABI money_base {39public:40  enum part { none, space, symbol, sign, value };41  struct pattern {42    char field[4];43  };44 45  _LIBCPP_HIDE_FROM_ABI money_base() {}46};47 48// moneypunct49 50template <class _CharT, bool _International = false>51class moneypunct : public locale::facet, public money_base {52public:53  typedef _CharT char_type;54  typedef basic_string<char_type> string_type;55 56  _LIBCPP_HIDE_FROM_ABI explicit moneypunct(size_t __refs = 0) : locale::facet(__refs) {}57 58  _LIBCPP_HIDE_FROM_ABI char_type decimal_point() const { return do_decimal_point(); }59  _LIBCPP_HIDE_FROM_ABI char_type thousands_sep() const { return do_thousands_sep(); }60  _LIBCPP_HIDE_FROM_ABI string grouping() const { return do_grouping(); }61  _LIBCPP_HIDE_FROM_ABI string_type curr_symbol() const { return do_curr_symbol(); }62  _LIBCPP_HIDE_FROM_ABI string_type positive_sign() const { return do_positive_sign(); }63  _LIBCPP_HIDE_FROM_ABI string_type negative_sign() const { return do_negative_sign(); }64  _LIBCPP_HIDE_FROM_ABI int frac_digits() const { return do_frac_digits(); }65  _LIBCPP_HIDE_FROM_ABI pattern pos_format() const { return do_pos_format(); }66  _LIBCPP_HIDE_FROM_ABI pattern neg_format() const { return do_neg_format(); }67 68  static locale::id id;69  static const bool intl = _International;70 71protected:72  _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~moneypunct() override {}73 74  virtual char_type do_decimal_point() const { return numeric_limits<char_type>::max(); }75  virtual char_type do_thousands_sep() const { return numeric_limits<char_type>::max(); }76  virtual string do_grouping() const { return string(); }77  virtual string_type do_curr_symbol() const { return string_type(); }78  virtual string_type do_positive_sign() const { return string_type(); }79  virtual string_type do_negative_sign() const { return string_type(1, '-'); }80  virtual int do_frac_digits() const { return 0; }81  virtual pattern do_pos_format() const {82    pattern __p = {{symbol, sign, none, value}};83    return __p;84  }85  virtual pattern do_neg_format() const {86    pattern __p = {{symbol, sign, none, value}};87    return __p;88  }89};90 91template <class _CharT, bool _International>92locale::id moneypunct<_CharT, _International>::id;93 94template <class _CharT, bool _International>95const bool moneypunct<_CharT, _International>::intl;96 97extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct<char, false>;98extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct<char, true>;99#  if _LIBCPP_HAS_WIDE_CHARACTERS100extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct<wchar_t, false>;101extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct<wchar_t, true>;102#  endif103 104// moneypunct_byname105 106template <class _CharT, bool _International = false>107class moneypunct_byname : public moneypunct<_CharT, _International> {108public:109  typedef money_base::pattern pattern;110  typedef _CharT char_type;111  typedef basic_string<char_type> string_type;112 113  _LIBCPP_HIDE_FROM_ABI explicit moneypunct_byname(const char* __nm, size_t __refs = 0)114      : moneypunct<_CharT, _International>(__refs) {115    init(__nm);116  }117 118  _LIBCPP_HIDE_FROM_ABI explicit moneypunct_byname(const string& __nm, size_t __refs = 0)119      : moneypunct<_CharT, _International>(__refs) {120    init(__nm.c_str());121  }122 123protected:124  _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~moneypunct_byname() override {}125 126  char_type do_decimal_point() const override { return __decimal_point_; }127  char_type do_thousands_sep() const override { return __thousands_sep_; }128  string do_grouping() const override { return __grouping_; }129  string_type do_curr_symbol() const override { return __curr_symbol_; }130  string_type do_positive_sign() const override { return __positive_sign_; }131  string_type do_negative_sign() const override { return __negative_sign_; }132  int do_frac_digits() const override { return __frac_digits_; }133  pattern do_pos_format() const override { return __pos_format_; }134  pattern do_neg_format() const override { return __neg_format_; }135 136private:137  char_type __decimal_point_;138  char_type __thousands_sep_;139  string __grouping_;140  string_type __curr_symbol_;141  string_type __positive_sign_;142  string_type __negative_sign_;143  int __frac_digits_;144  pattern __pos_format_;145  pattern __neg_format_;146 147  void init(const char*);148};149 150template <>151_LIBCPP_EXPORTED_FROM_ABI void moneypunct_byname<char, false>::init(const char*);152template <>153_LIBCPP_EXPORTED_FROM_ABI void moneypunct_byname<char, true>::init(const char*);154extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct_byname<char, false>;155extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct_byname<char, true>;156 157#  if _LIBCPP_HAS_WIDE_CHARACTERS158template <>159_LIBCPP_EXPORTED_FROM_ABI void moneypunct_byname<wchar_t, false>::init(const char*);160template <>161_LIBCPP_EXPORTED_FROM_ABI void moneypunct_byname<wchar_t, true>::init(const char*);162extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct_byname<wchar_t, false>;163extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct_byname<wchar_t, true>;164#  endif165 166// money_get167 168template <class _CharT>169class __money_get {170protected:171  typedef _CharT char_type;172  typedef basic_string<char_type> string_type;173 174  _LIBCPP_HIDE_FROM_ABI __money_get() {}175 176  static void __gather_info(177      bool __intl,178      const locale& __loc,179      money_base::pattern& __pat,180      char_type& __dp,181      char_type& __ts,182      string& __grp,183      string_type& __sym,184      string_type& __psn,185      string_type& __nsn,186      int& __fd);187};188 189template <class _CharT>190void __money_get<_CharT>::__gather_info(191    bool __intl,192    const locale& __loc,193    money_base::pattern& __pat,194    char_type& __dp,195    char_type& __ts,196    string& __grp,197    string_type& __sym,198    string_type& __psn,199    string_type& __nsn,200    int& __fd) {201  if (__intl) {202    const moneypunct<char_type, true>& __mp = std::use_facet<moneypunct<char_type, true> >(__loc);203    __pat                                   = __mp.neg_format();204    __nsn                                   = __mp.negative_sign();205    __psn                                   = __mp.positive_sign();206    __dp                                    = __mp.decimal_point();207    __ts                                    = __mp.thousands_sep();208    __grp                                   = __mp.grouping();209    __sym                                   = __mp.curr_symbol();210    __fd                                    = __mp.frac_digits();211  } else {212    const moneypunct<char_type, false>& __mp = std::use_facet<moneypunct<char_type, false> >(__loc);213    __pat                                    = __mp.neg_format();214    __nsn                                    = __mp.negative_sign();215    __psn                                    = __mp.positive_sign();216    __dp                                     = __mp.decimal_point();217    __ts                                     = __mp.thousands_sep();218    __grp                                    = __mp.grouping();219    __sym                                    = __mp.curr_symbol();220    __fd                                     = __mp.frac_digits();221  }222}223 224extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __money_get<char>;225#  if _LIBCPP_HAS_WIDE_CHARACTERS226extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __money_get<wchar_t>;227#  endif228 229template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >230class money_get : public locale::facet, private __money_get<_CharT> {231public:232  typedef _CharT char_type;233  typedef _InputIterator iter_type;234  typedef basic_string<char_type> string_type;235 236  _LIBCPP_HIDE_FROM_ABI explicit money_get(size_t __refs = 0) : locale::facet(__refs) {}237 238  _LIBCPP_HIDE_FROM_ABI iter_type239  get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob, ios_base::iostate& __err, long double& __v) const {240    return do_get(__b, __e, __intl, __iob, __err, __v);241  }242 243  _LIBCPP_HIDE_FROM_ABI iter_type244  get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob, ios_base::iostate& __err, string_type& __v) const {245    return do_get(__b, __e, __intl, __iob, __err, __v);246  }247 248  static locale::id id;249 250protected:251  _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~money_get() override {}252 253  virtual iter_type254  do_get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob, ios_base::iostate& __err, long double& __v) const;255  virtual iter_type256  do_get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob, ios_base::iostate& __err, string_type& __v) const;257 258private:259  static bool __do_get(260      iter_type& __b,261      iter_type __e,262      bool __intl,263      const locale& __loc,264      ios_base::fmtflags __flags,265      ios_base::iostate& __err,266      bool& __neg,267      const ctype<char_type>& __ct,268      unique_ptr<char_type, void (*)(void*)>& __wb,269      char_type*& __wn,270      char_type* __we);271};272 273template <class _CharT, class _InputIterator>274locale::id money_get<_CharT, _InputIterator>::id;275 276_LIBCPP_EXPORTED_FROM_ABI void __do_nothing(void*);277 278template <class _Tp>279_LIBCPP_HIDE_FROM_ABI void __double_or_nothing(unique_ptr<_Tp, void (*)(void*)>& __b, _Tp*& __n, _Tp*& __e) {280  bool __owns      = __b.get_deleter() != __do_nothing;281  size_t __cur_cap = static_cast<size_t>(__e - __b.get()) * sizeof(_Tp);282  size_t __new_cap = __cur_cap < numeric_limits<size_t>::max() / 2 ? 2 * __cur_cap : numeric_limits<size_t>::max();283  if (__new_cap == 0)284    __new_cap = sizeof(_Tp);285  size_t __n_off = static_cast<size_t>(__n - __b.get());286  _Tp* __t       = (_Tp*)std::realloc(__owns ? __b.get() : 0, __new_cap);287  if (__t == 0)288    std::__throw_bad_alloc();289  if (__owns)290    __b.release();291  else292    std::memcpy(__t, __b.get(), __cur_cap);293  __b = unique_ptr<_Tp, void (*)(void*)>(__t, free);294  __new_cap /= sizeof(_Tp);295  __n = __b.get() + __n_off;296  __e = __b.get() + __new_cap;297}298 299// true == success300template <class _CharT, class _InputIterator>301bool money_get<_CharT, _InputIterator>::__do_get(302    iter_type& __b,303    iter_type __e,304    bool __intl,305    const locale& __loc,306    ios_base::fmtflags __flags,307    ios_base::iostate& __err,308    bool& __neg,309    const ctype<char_type>& __ct,310    unique_ptr<char_type, void (*)(void*)>& __wb,311    char_type*& __wn,312    char_type* __we) {313  if (__b == __e) {314    __err |= ios_base::failbit;315    return false;316  }317  const unsigned __bz = 100;318  unsigned __gbuf[__bz];319  unique_ptr<unsigned, void (*)(void*)> __gb(__gbuf, __do_nothing);320  unsigned* __gn = __gb.get();321  unsigned* __ge = __gn + __bz;322  money_base::pattern __pat;323  char_type __dp;324  char_type __ts;325  string __grp;326  string_type __sym;327  string_type __psn;328  string_type __nsn;329  // Capture the spaces read into money_base::{space,none} so they330  // can be compared to initial spaces in __sym.331  string_type __spaces;332  int __fd;333  __money_get<_CharT>::__gather_info(__intl, __loc, __pat, __dp, __ts, __grp, __sym, __psn, __nsn, __fd);334  const string_type* __trailing_sign = 0;335  __wn                               = __wb.get();336  for (unsigned __p = 0; __p < 4 && __b != __e; ++__p) {337    switch (__pat.field[__p]) {338    case money_base::space:339      if (__p != 3) {340        if (__ct.is(ctype_base::space, *__b))341          __spaces.push_back(*__b++);342        else {343          __err |= ios_base::failbit;344          return false;345        }346      }347      [[__fallthrough__]];348    case money_base::none:349      if (__p != 3) {350        while (__b != __e && __ct.is(ctype_base::space, *__b))351          __spaces.push_back(*__b++);352      }353      break;354    case money_base::sign:355      if (__psn.size() > 0 && *__b == __psn[0]) {356        ++__b;357        __neg = false;358        if (__psn.size() > 1)359          __trailing_sign = std::addressof(__psn);360        break;361      }362      if (__nsn.size() > 0 && *__b == __nsn[0]) {363        ++__b;364        __neg = true;365        if (__nsn.size() > 1)366          __trailing_sign = std::addressof(__nsn);367        break;368      }369      if (__psn.size() > 0 && __nsn.size() > 0) { // sign is required370        __err |= ios_base::failbit;371        return false;372      }373      if (__psn.size() == 0 && __nsn.size() == 0)374        // locale has no way of specifying a sign. Use the initial value of __neg as a default375        break;376      __neg = (__nsn.size() == 0);377      break;378    case money_base::symbol: {379      bool __more_needed =380          __trailing_sign || (__p < 2) || (__p == 2 && __pat.field[3] != static_cast<char>(money_base::none));381      bool __sb = (__flags & ios_base::showbase) != 0;382      if (__sb || __more_needed) {383        typename string_type::const_iterator __sym_space_end = __sym.begin();384        if (__p > 0 && (__pat.field[__p - 1] == money_base::none || __pat.field[__p - 1] == money_base::space)) {385          // Match spaces we've already read against spaces at386          // the beginning of __sym.387          while (__sym_space_end != __sym.end() && __ct.is(ctype_base::space, *__sym_space_end))388            ++__sym_space_end;389          const size_t __num_spaces = __sym_space_end - __sym.begin();390          if (__num_spaces > __spaces.size() ||391              !std::equal(__spaces.end() - __num_spaces, __spaces.end(), __sym.begin())) {392            // No match. Put __sym_space_end back at the393            // beginning of __sym, which will prevent a394            // match in the next loop.395            __sym_space_end = __sym.begin();396          }397        }398        typename string_type::const_iterator __sym_curr_char = __sym_space_end;399        while (__sym_curr_char != __sym.end() && __b != __e && *__b == *__sym_curr_char) {400          ++__b;401          ++__sym_curr_char;402        }403        if (__sb && __sym_curr_char != __sym.end()) {404          __err |= ios_base::failbit;405          return false;406        }407      }408    } break;409    case money_base::value: {410      unsigned __ng = 0;411      for (; __b != __e; ++__b) {412        char_type __c = *__b;413        if (__ct.is(ctype_base::digit, __c)) {414          if (__wn == __we)415            std::__double_or_nothing(__wb, __wn, __we);416          *__wn++ = __c;417          ++__ng;418        } else if (__grp.size() > 0 && __ng > 0 && __c == __ts) {419          if (__gn == __ge)420            std::__double_or_nothing(__gb, __gn, __ge);421          *__gn++ = __ng;422          __ng    = 0;423        } else424          break;425      }426      if (__gb.get() != __gn && __ng > 0) {427        if (__gn == __ge)428          std::__double_or_nothing(__gb, __gn, __ge);429        *__gn++ = __ng;430      }431      if (__fd > 0) {432        if (__b == __e || *__b != __dp) {433          __err |= ios_base::failbit;434          return false;435        }436        for (++__b; __fd > 0; --__fd, (void)++__b) {437          if (__b == __e || !__ct.is(ctype_base::digit, *__b)) {438            __err |= ios_base::failbit;439            return false;440          }441          if (__wn == __we)442            std::__double_or_nothing(__wb, __wn, __we);443          *__wn++ = *__b;444        }445      }446      if (__wn == __wb.get()) {447        __err |= ios_base::failbit;448        return false;449      }450    } break;451    }452  }453  if (__trailing_sign) {454    for (unsigned __i = 1; __i < __trailing_sign->size(); ++__i, (void)++__b) {455      if (__b == __e || *__b != (*__trailing_sign)[__i]) {456        __err |= ios_base::failbit;457        return false;458      }459    }460  }461  if (__gb.get() != __gn) {462    ios_base::iostate __et = ios_base::goodbit;463    __check_grouping(__grp, __gb.get(), __gn, __et);464    if (__et) {465      __err |= ios_base::failbit;466      return false;467    }468  }469  return true;470}471 472template <class _CharT, class _InputIterator>473_InputIterator money_get<_CharT, _InputIterator>::do_get(474    iter_type __b, iter_type __e, bool __intl, ios_base& __iob, ios_base::iostate& __err, long double& __v) const {475  const int __bz = 100;476  char_type __wbuf[__bz];477  unique_ptr<char_type, void (*)(void*)> __wb(__wbuf, __do_nothing);478  char_type* __wn;479  char_type* __we              = __wbuf + __bz;480  locale __loc                 = __iob.getloc();481  const ctype<char_type>& __ct = std::use_facet<ctype<char_type> >(__loc);482  bool __neg                   = false;483  if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct, __wb, __wn, __we)) {484    const char __src[] = "0123456789";485    char_type __atoms[sizeof(__src) - 1];486    __ct.widen(__src, __src + (sizeof(__src) - 1), __atoms);487    char __nbuf[__bz];488    char* __nc          = __nbuf;489    const char* __nc_in = __nc;490    unique_ptr<char, void (*)(void*)> __h(nullptr, free);491    if (__wn - __wb.get() > __bz - 2) {492      __h.reset((char*)malloc(static_cast<size_t>(__wn - __wb.get() + 2)));493      if (__h.get() == nullptr)494        std::__throw_bad_alloc();495      __nc    = __h.get();496      __nc_in = __nc;497    }498    if (__neg)499      *__nc++ = '-';500    for (const char_type* __w = __wb.get(); __w < __wn; ++__w, ++__nc)501      *__nc = __src[std::find(__atoms, std::end(__atoms), *__w) - __atoms];502    *__nc = char();503    if (sscanf(__nc_in, "%Lf", &__v) != 1)504      std::__throw_runtime_error("money_get error");505  }506  if (__b == __e)507    __err |= ios_base::eofbit;508  return __b;509}510 511template <class _CharT, class _InputIterator>512_InputIterator money_get<_CharT, _InputIterator>::do_get(513    iter_type __b, iter_type __e, bool __intl, ios_base& __iob, ios_base::iostate& __err, string_type& __v) const {514  const int __bz = 100;515  char_type __wbuf[__bz];516  unique_ptr<char_type, void (*)(void*)> __wb(__wbuf, __do_nothing);517  char_type* __wn;518  char_type* __we              = __wbuf + __bz;519  locale __loc                 = __iob.getloc();520  const ctype<char_type>& __ct = std::use_facet<ctype<char_type> >(__loc);521  bool __neg                   = false;522  if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct, __wb, __wn, __we)) {523    __v.clear();524    if (__neg)525      __v.push_back(__ct.widen('-'));526    char_type __z = __ct.widen('0');527    char_type* __w;528    for (__w = __wb.get(); __w < __wn - 1; ++__w)529      if (*__w != __z)530        break;531    __v.append(__w, __wn);532  }533  if (__b == __e)534    __err |= ios_base::eofbit;535  return __b;536}537 538extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS money_get<char>;539#  if _LIBCPP_HAS_WIDE_CHARACTERS540extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS money_get<wchar_t>;541#  endif542 543// money_put544 545template <class _CharT>546class __money_put {547protected:548  typedef _CharT char_type;549  typedef basic_string<char_type> string_type;550 551  _LIBCPP_HIDE_FROM_ABI __money_put() {}552 553  static void __gather_info(554      bool __intl,555      bool __neg,556      const locale& __loc,557      money_base::pattern& __pat,558      char_type& __dp,559      char_type& __ts,560      string& __grp,561      string_type& __sym,562      string_type& __sn,563      int& __fd);564  static void __format(565      char_type* __mb,566      char_type*& __mi,567      char_type*& __me,568      ios_base::fmtflags __flags,569      const char_type* __db,570      const char_type* __de,571      const ctype<char_type>& __ct,572      bool __neg,573      const money_base::pattern& __pat,574      char_type __dp,575      char_type __ts,576      const string& __grp,577      const string_type& __sym,578      const string_type& __sn,579      int __fd);580};581 582template <class _CharT>583void __money_put<_CharT>::__gather_info(584    bool __intl,585    bool __neg,586    const locale& __loc,587    money_base::pattern& __pat,588    char_type& __dp,589    char_type& __ts,590    string& __grp,591    string_type& __sym,592    string_type& __sn,593    int& __fd) {594  if (__intl) {595    const moneypunct<char_type, true>& __mp = std::use_facet<moneypunct<char_type, true> >(__loc);596    if (__neg) {597      __pat = __mp.neg_format();598      __sn  = __mp.negative_sign();599    } else {600      __pat = __mp.pos_format();601      __sn  = __mp.positive_sign();602    }603    __dp  = __mp.decimal_point();604    __ts  = __mp.thousands_sep();605    __grp = __mp.grouping();606    __sym = __mp.curr_symbol();607    __fd  = __mp.frac_digits();608  } else {609    const moneypunct<char_type, false>& __mp = std::use_facet<moneypunct<char_type, false> >(__loc);610    if (__neg) {611      __pat = __mp.neg_format();612      __sn  = __mp.negative_sign();613    } else {614      __pat = __mp.pos_format();615      __sn  = __mp.positive_sign();616    }617    __dp  = __mp.decimal_point();618    __ts  = __mp.thousands_sep();619    __grp = __mp.grouping();620    __sym = __mp.curr_symbol();621    __fd  = __mp.frac_digits();622  }623}624 625template <class _CharT>626void __money_put<_CharT>::__format(627    char_type* __mb,628    char_type*& __mi,629    char_type*& __me,630    ios_base::fmtflags __flags,631    const char_type* __db,632    const char_type* __de,633    const ctype<char_type>& __ct,634    bool __neg,635    const money_base::pattern& __pat,636    char_type __dp,637    char_type __ts,638    const string& __grp,639    const string_type& __sym,640    const string_type& __sn,641    int __fd) {642  __me = __mb;643  for (char __p : __pat.field) {644    switch (__p) {645    case money_base::none:646      __mi = __me;647      break;648    case money_base::space:649      __mi    = __me;650      *__me++ = __ct.widen(' ');651      break;652    case money_base::sign:653      if (!__sn.empty())654        *__me++ = __sn[0];655      break;656    case money_base::symbol:657      if (!__sym.empty() && (__flags & ios_base::showbase))658        __me = std::copy(__sym.begin(), __sym.end(), __me);659      break;660    case money_base::value: {661      // remember start of value so we can reverse it662      char_type* __t = __me;663      // find beginning of digits664      if (__neg)665        ++__db;666      // find end of digits667      const char_type* __d;668      for (__d = __db; __d < __de; ++__d)669        if (!__ct.is(ctype_base::digit, *__d))670          break;671      // print fractional part672      if (__fd > 0) {673        int __f;674        for (__f = __fd; __d > __db && __f > 0; --__f)675          *__me++ = *--__d;676        char_type __z = __f > 0 ? __ct.widen('0') : char_type();677        for (; __f > 0; --__f)678          *__me++ = __z;679        *__me++ = __dp;680      }681      // print units part682      if (__d == __db) {683        *__me++ = __ct.widen('0');684      } else {685        unsigned __ng = 0;686        unsigned __ig = 0;687        unsigned __gl = __grp.empty() ? numeric_limits<unsigned>::max() : static_cast<unsigned>(__grp[__ig]);688        while (__d != __db) {689          if (__ng == __gl) {690            *__me++ = __ts;691            __ng    = 0;692            if (++__ig < __grp.size())693              __gl = __grp[__ig] == numeric_limits<char>::max()694                       ? numeric_limits<unsigned>::max()695                       : static_cast<unsigned>(__grp[__ig]);696          }697          *__me++ = *--__d;698          ++__ng;699        }700      }701      // reverse it702      std::reverse(__t, __me);703    } break;704    }705  }706  // print rest of sign, if any707  if (__sn.size() > 1)708    __me = std::copy(__sn.begin() + 1, __sn.end(), __me);709  // set alignment710  if ((__flags & ios_base::adjustfield) == ios_base::left)711    __mi = __me;712  else if ((__flags & ios_base::adjustfield) != ios_base::internal)713    __mi = __mb;714}715 716extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __money_put<char>;717#  if _LIBCPP_HAS_WIDE_CHARACTERS718extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __money_put<wchar_t>;719#  endif720 721template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >722class money_put : public locale::facet, private __money_put<_CharT> {723public:724  typedef _CharT char_type;725  typedef _OutputIterator iter_type;726  typedef basic_string<char_type> string_type;727 728  _LIBCPP_HIDE_FROM_ABI explicit money_put(size_t __refs = 0) : locale::facet(__refs) {}729 730  _LIBCPP_HIDE_FROM_ABI iter_type731  put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl, long double __units) const {732    return do_put(__s, __intl, __iob, __fl, __units);733  }734 735  _LIBCPP_HIDE_FROM_ABI iter_type736  put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl, const string_type& __digits) const {737    return do_put(__s, __intl, __iob, __fl, __digits);738  }739 740  static locale::id id;741 742protected:743  _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~money_put() override {}744 745  virtual iter_type do_put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl, long double __units) const;746  virtual iter_type747  do_put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl, const string_type& __digits) const;748};749 750template <class _CharT, class _OutputIterator>751locale::id money_put<_CharT, _OutputIterator>::id;752 753template <class _CharT, class _OutputIterator>754_OutputIterator money_put<_CharT, _OutputIterator>::do_put(755    iter_type __s, bool __intl, ios_base& __iob, char_type __fl, long double __units) const {756  // convert to char757  const size_t __bs = 100;758  char __buf[__bs];759  char* __bb = __buf;760  char_type __digits[__bs];761  char_type* __db = __digits;762  int __n         = snprintf(__bb, __bs, "%.0Lf", __units);763  unique_ptr<char, void (*)(void*)> __hn(nullptr, free);764  unique_ptr<char_type, void (*)(void*)> __hd(0, free);765  // secure memory for digit storage766  if (static_cast<size_t>(__n) > __bs - 1) {767    __n = __locale::__asprintf(&__bb, _LIBCPP_GET_C_LOCALE, "%.0Lf", __units);768    if (__n == -1)769      std::__throw_bad_alloc();770    __hn.reset(__bb);771    __hd.reset((char_type*)malloc(static_cast<size_t>(__n) * sizeof(char_type)));772    if (__hd == nullptr)773      std::__throw_bad_alloc();774    __db = __hd.get();775  }776  // gather info777  locale __loc                 = __iob.getloc();778  const ctype<char_type>& __ct = std::use_facet<ctype<char_type> >(__loc);779  __ct.widen(__bb, __bb + __n, __db);780  bool __neg = __n > 0 && __bb[0] == '-';781  money_base::pattern __pat;782  char_type __dp;783  char_type __ts;784  string __grp;785  string_type __sym;786  string_type __sn;787  int __fd;788  this->__gather_info(__intl, __neg, __loc, __pat, __dp, __ts, __grp, __sym, __sn, __fd);789  // secure memory for formatting790  char_type __mbuf[__bs];791  char_type* __mb = __mbuf;792  unique_ptr<char_type, void (*)(void*)> __hw(0, free);793  size_t __exn = __n > __fd ? (static_cast<size_t>(__n) - static_cast<size_t>(__fd)) * 2 + __sn.size() + __sym.size() +794                                  static_cast<size_t>(__fd) + 1795                            : __sn.size() + __sym.size() + static_cast<size_t>(__fd) + 2;796  if (__exn > __bs) {797    __hw.reset((char_type*)malloc(__exn * sizeof(char_type)));798    __mb = __hw.get();799    if (__mb == 0)800      std::__throw_bad_alloc();801  }802  // format803  char_type* __mi;804  char_type* __me;805  this->__format(806      __mb, __mi, __me, __iob.flags(), __db, __db + __n, __ct, __neg, __pat, __dp, __ts, __grp, __sym, __sn, __fd);807  return std::__pad_and_output(__s, __mb, __mi, __me, __iob, __fl);808}809 810template <class _CharT, class _OutputIterator>811_OutputIterator money_put<_CharT, _OutputIterator>::do_put(812    iter_type __s, bool __intl, ios_base& __iob, char_type __fl, const string_type& __digits) const {813  // gather info814  locale __loc                 = __iob.getloc();815  const ctype<char_type>& __ct = std::use_facet<ctype<char_type> >(__loc);816  bool __neg                   = __digits.size() > 0 && __digits[0] == __ct.widen('-');817  money_base::pattern __pat;818  char_type __dp;819  char_type __ts;820  string __grp;821  string_type __sym;822  string_type __sn;823  int __fd;824  this->__gather_info(__intl, __neg, __loc, __pat, __dp, __ts, __grp, __sym, __sn, __fd);825  // secure memory for formatting826  char_type __mbuf[100];827  char_type* __mb = __mbuf;828  unique_ptr<char_type, void (*)(void*)> __h(0, free);829  size_t __exn =830      static_cast<int>(__digits.size()) > __fd831          ? (__digits.size() - static_cast<size_t>(__fd)) * 2 + __sn.size() + __sym.size() + static_cast<size_t>(__fd) +832                1833          : __sn.size() + __sym.size() + static_cast<size_t>(__fd) + 2;834  if (__exn > 100) {835    __h.reset((char_type*)malloc(__exn * sizeof(char_type)));836    __mb = __h.get();837    if (__mb == 0)838      std::__throw_bad_alloc();839  }840  // format841  char_type* __mi;842  char_type* __me;843  this->__format(844      __mb,845      __mi,846      __me,847      __iob.flags(),848      __digits.data(),849      __digits.data() + __digits.size(),850      __ct,851      __neg,852      __pat,853      __dp,854      __ts,855      __grp,856      __sym,857      __sn,858      __fd);859  return std::__pad_and_output(__s, __mb, __mi, __me, __iob, __fl);860}861 862extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS money_put<char>;863#  if _LIBCPP_HAS_WIDE_CHARACTERS864extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS money_put<wchar_t>;865#  endif866 867_LIBCPP_END_NAMESPACE_STD868 869_LIBCPP_POP_MACROS870 871#endif // _LIBCPP_HAS_LOCALIZATION872 873#endif // _LIBCPP___LOCALE_DIR_MONEY_H874