813 lines
23 KiB
Plaintext
813 lines
23 KiB
Plaintext
|
// xlocmon internal header (from <locale>)
|
||
|
#pragma once
|
||
|
#ifndef _XLOCMON_
|
||
|
#define _XLOCMON_
|
||
|
#include <xiosbase>
|
||
|
|
||
|
#pragma pack(push,8)
|
||
|
#pragma warning(push,3)
|
||
|
_STD_BEGIN
|
||
|
// STRUCT money_base
|
||
|
struct _CRTIMP2 money_base
|
||
|
: public locale::facet
|
||
|
{ // ultimate base class for moneypunct
|
||
|
enum
|
||
|
{ // constants for different format codes
|
||
|
symbol = '$', sign = '+', space = ' ', value = 'v', none = 'x'};
|
||
|
typedef int part;
|
||
|
|
||
|
struct pattern
|
||
|
{ // four-part formats for monetary text
|
||
|
char field[4];
|
||
|
};
|
||
|
|
||
|
money_base(size_t _Refs = 0)
|
||
|
: locale::facet(_Refs)
|
||
|
{ // default constructor
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// TEMPLATE CLASS _Mpunct
|
||
|
template<class _Elem>
|
||
|
class _Mpunct
|
||
|
: public money_base
|
||
|
{ // common base class for moneypunct<_Elem, false/true>
|
||
|
public:
|
||
|
typedef _Elem char_type;
|
||
|
typedef basic_string<_Elem, char_traits<_Elem>, allocator<_Elem> >
|
||
|
string_type;
|
||
|
|
||
|
_Elem decimal_point() const
|
||
|
{ // return decimal point
|
||
|
return (do_decimal_point());
|
||
|
}
|
||
|
|
||
|
_Elem thousands_sep() const
|
||
|
{ // return thousands separator
|
||
|
return (do_thousands_sep());
|
||
|
}
|
||
|
|
||
|
string grouping() const
|
||
|
{ // return grouping string
|
||
|
return (do_grouping());
|
||
|
}
|
||
|
|
||
|
string_type curr_symbol() const
|
||
|
{ // return currency symbol string
|
||
|
return (do_curr_symbol());
|
||
|
}
|
||
|
|
||
|
string_type positive_sign() const
|
||
|
{ // return plus sign
|
||
|
return (do_positive_sign());
|
||
|
}
|
||
|
|
||
|
string_type negative_sign() const
|
||
|
{ // return minus sign
|
||
|
return (do_negative_sign());
|
||
|
}
|
||
|
|
||
|
int frac_digits() const
|
||
|
{ // return number of fraction digits
|
||
|
return (do_frac_digits());
|
||
|
}
|
||
|
|
||
|
pattern pos_format() const
|
||
|
{ // return format for positive values
|
||
|
return (do_pos_format());
|
||
|
}
|
||
|
|
||
|
pattern neg_format() const
|
||
|
{ // return format for negative values
|
||
|
return (do_neg_format());
|
||
|
}
|
||
|
|
||
|
explicit _Mpunct(size_t _Refs, bool _Intl)
|
||
|
: money_base(_Refs), _International(_Intl)
|
||
|
{ // construct from current locale
|
||
|
_Init(_Locinfo());
|
||
|
}
|
||
|
|
||
|
_Mpunct(const _Locinfo& _Lobj, size_t _Refs, bool _Intl)
|
||
|
: money_base(_Refs), _International(_Intl)
|
||
|
{ // construct from specified locale
|
||
|
_Init(_Lobj);
|
||
|
}
|
||
|
|
||
|
_PROTECTED:
|
||
|
virtual ~_Mpunct()
|
||
|
{ // destroy the object
|
||
|
_Tidy();
|
||
|
}
|
||
|
|
||
|
protected:
|
||
|
void _Init(const _Locinfo& _Lobj)
|
||
|
{ // initialize from _Lobj
|
||
|
const lconv *_Ptr = _Lobj._Getlconv();
|
||
|
|
||
|
_Grouping = 0;
|
||
|
_Currencysign = 0;
|
||
|
_Plussign = 0;
|
||
|
_Minussign = 0;
|
||
|
|
||
|
_TRY_BEGIN
|
||
|
_Grouping = _MAKLOCSTR(char, _Ptr->mon_grouping, _Lobj._Getcvt());
|
||
|
_Currencysign = _MAKLOCSTR(_Elem, _International
|
||
|
? _Ptr->int_curr_symbol : _Ptr->currency_symbol, _Lobj._Getcvt());
|
||
|
_Plussign = _MAKLOCSTR(_Elem, 4 < (unsigned int)_Ptr->p_sign_posn
|
||
|
? "" : _Ptr->positive_sign, _Lobj._Getcvt());
|
||
|
_Minussign = _MAKLOCSTR(_Elem, 4 < (unsigned int)_Ptr->n_sign_posn
|
||
|
? "-" : _Ptr->negative_sign, _Lobj._Getcvt());
|
||
|
_CATCH_ALL
|
||
|
_Tidy();
|
||
|
_RERAISE;
|
||
|
_CATCH_END
|
||
|
|
||
|
_Decimalpoint = _WIDEN(_Elem, _Ptr->mon_decimal_point[0]);
|
||
|
_Kseparator = _WIDEN(_Elem, _Ptr->mon_thousands_sep[0]);
|
||
|
|
||
|
_Fracdigits = _International ? _Ptr->int_frac_digits
|
||
|
: _Ptr->frac_digits;
|
||
|
if (_Fracdigits < 0 || CHAR_MAX <= _Fracdigits)
|
||
|
_Fracdigits = 0;
|
||
|
|
||
|
_Makpat(_Plusformat, _Ptr->p_sep_by_space,
|
||
|
_Ptr->p_cs_precedes, _Ptr->p_sign_posn);
|
||
|
_Makpat(_Minusformat, _Ptr->n_sep_by_space,
|
||
|
_Ptr->n_cs_precedes, _Ptr->n_sign_posn);
|
||
|
}
|
||
|
|
||
|
virtual _Elem do_decimal_point() const
|
||
|
{ // return decimal point
|
||
|
return (_Decimalpoint);
|
||
|
}
|
||
|
|
||
|
virtual _Elem do_thousands_sep() const
|
||
|
{ // return thousands separator
|
||
|
return (_Kseparator);
|
||
|
}
|
||
|
|
||
|
virtual string do_grouping() const
|
||
|
{ // return grouping string
|
||
|
return (string(_Grouping));
|
||
|
}
|
||
|
|
||
|
virtual string_type do_curr_symbol() const
|
||
|
{ // return currency symbol string
|
||
|
return (string_type(_Currencysign));
|
||
|
}
|
||
|
|
||
|
virtual string_type do_positive_sign() const
|
||
|
{ // return plus sign
|
||
|
return (string_type(_Plussign));
|
||
|
}
|
||
|
|
||
|
virtual string_type do_negative_sign() const
|
||
|
{ // return minus sign
|
||
|
return (string_type(_Minussign));
|
||
|
}
|
||
|
|
||
|
virtual int do_frac_digits() const
|
||
|
{ // return number of fraction digits
|
||
|
return (_Fracdigits);
|
||
|
}
|
||
|
|
||
|
virtual pattern do_pos_format() const
|
||
|
{ // return format for positive values
|
||
|
return (_Plusformat);
|
||
|
}
|
||
|
|
||
|
virtual pattern do_neg_format() const
|
||
|
{ // return format for negative values
|
||
|
return (_Minusformat);
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
void _Makpat(pattern& _Pattern, unsigned int _Sepbyspace,
|
||
|
unsigned int _Symbolprecedes, unsigned int _Signposition)
|
||
|
{ // make format pattern from locale information
|
||
|
const char *_Ptr = _International || (_Sepbyspace & ~1) != 0
|
||
|
|| (_Symbolprecedes & ~1) != 0 || 4 < _Signposition
|
||
|
? "$+vx" // international or bad parameters
|
||
|
: "+v$x" "+v$x" "v$+x" "v+$x" "v$+x"
|
||
|
"+$vx" "+$vx" "$v+x" "+$vx" "$+vx"
|
||
|
"+v $" "+v $" "v $+" "v+ $" "v $+"
|
||
|
"+$ v" "+$ v" "$ v+" "+$ v" "$ +v"
|
||
|
+ (_Signposition * 4 // pick even/odd column
|
||
|
+ (_Symbolprecedes == 1 ? 20 : 0) // pick even/odd row
|
||
|
+ (_Sepbyspace == 1 ? 40 : 0)); // pick first/second half
|
||
|
memcpy(_Pattern.field, _Ptr, 4);
|
||
|
}
|
||
|
|
||
|
void _Tidy()
|
||
|
{ // free all storage
|
||
|
_DELETE_CRT_VEC((void *)_Grouping);
|
||
|
_DELETE_CRT_VEC((void *)_Currencysign);
|
||
|
_DELETE_CRT_VEC((void *)_Plussign);
|
||
|
_DELETE_CRT_VEC((void *)_Minussign);
|
||
|
}
|
||
|
|
||
|
const char *_Grouping; // grouping string, "" for "C" locale
|
||
|
_Elem _Decimalpoint; // decimal point, '\0' for "C" locale
|
||
|
_Elem _Kseparator; // thousands separator, '\0' for "C" locale
|
||
|
const _Elem *_Currencysign; // currency symbol, "" for "C" locale
|
||
|
const _Elem *_Plussign; // plus sign, "" for "C" locale
|
||
|
const _Elem *_Minussign; // minus sign, "-" for "C" locale
|
||
|
int _Fracdigits; // number of fraction digits, 0 for "C" locale
|
||
|
pattern _Plusformat; // positive format, "$+vx" for "C" locale
|
||
|
pattern _Minusformat; // negative format, "$+vx" for "C" locale
|
||
|
bool _International; // true if international format
|
||
|
};
|
||
|
|
||
|
// TEMPLATE CLASS moneypunct
|
||
|
template<class _Elem,
|
||
|
bool _Intl = false>
|
||
|
class moneypunct
|
||
|
: public _Mpunct<_Elem>
|
||
|
{ // facet for defining monetary punctuation text
|
||
|
public:
|
||
|
static const bool intl; // true if international
|
||
|
static locale::id id; // unique facet id
|
||
|
|
||
|
explicit moneypunct(size_t _Refs = 0)
|
||
|
: _Mpunct<_Elem>(_Refs, _Intl)
|
||
|
{ // construct from current locale
|
||
|
}
|
||
|
|
||
|
moneypunct(const _Locinfo& _Lobj, size_t _Refs = 0)
|
||
|
: _Mpunct<_Elem>(_Lobj, _Refs, _Intl)
|
||
|
{ // construct from specified locale
|
||
|
}
|
||
|
|
||
|
static size_t __cdecl _Getcat(const locale::facet **_Ppf = 0)
|
||
|
{ // return locale category mask and construct standard facet
|
||
|
if (_Ppf != 0 && *_Ppf == 0)
|
||
|
*_Ppf = _NEW_CRT moneypunct<_Elem, _Intl>;
|
||
|
return (_X_MONETARY);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// STATIC moneypunct::intl OBJECT
|
||
|
template<class _Elem,
|
||
|
bool _Intl>
|
||
|
const bool moneypunct<_Elem, _Intl>::intl = _Intl;
|
||
|
|
||
|
// STATIC moneypunct::id OBJECT
|
||
|
template<class _Elem,
|
||
|
bool _Intl>
|
||
|
locale::id moneypunct<_Elem, _Intl>::id;
|
||
|
|
||
|
// TEMPLATE CLASS moneypunct_byname
|
||
|
template<class _Elem,
|
||
|
bool _Intl = false>
|
||
|
class moneypunct_byname
|
||
|
: public moneypunct<_Elem, _Intl>
|
||
|
{ // moneypunct for named locale
|
||
|
public:
|
||
|
explicit moneypunct_byname(const char *_Locname, size_t _Refs = 0)
|
||
|
: moneypunct<_Elem, _Intl>(_Locinfo(_Locname), _Refs)
|
||
|
{ // construct for named locale
|
||
|
}
|
||
|
|
||
|
_PROTECTED:
|
||
|
virtual ~moneypunct_byname()
|
||
|
{ // destroy the object
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// TEMPLATE CLASS money_get
|
||
|
template<class _Elem,
|
||
|
class _InIt = istreambuf_iterator<_Elem, char_traits<_Elem> > >
|
||
|
class money_get
|
||
|
: public locale::facet
|
||
|
{ // facet for converting text to encoded monetary amounts
|
||
|
typedef moneypunct<_Elem, false> _Mypunct0;
|
||
|
typedef moneypunct<_Elem, true> _Mypunct1;
|
||
|
|
||
|
public:
|
||
|
typedef _Elem char_type;
|
||
|
typedef _InIt iter_type;
|
||
|
typedef basic_string<_Elem, char_traits<_Elem>, allocator<_Elem> >
|
||
|
string_type;
|
||
|
|
||
|
_InIt get(_InIt _First, _InIt _Last, bool _Intl,
|
||
|
ios_base& _Iosbase, ios_base::iostate& _State, long double& _Val) const
|
||
|
{ // get long double from [_First, _Last) into _Val
|
||
|
return (do_get(_First, _Last, _Intl, _Iosbase, _State, _Val));
|
||
|
}
|
||
|
|
||
|
_InIt get(_InIt _First, _InIt _Last, bool _Intl,
|
||
|
ios_base& _Iosbase, ios_base::iostate& _State, string_type& _Val) const
|
||
|
{ // get string_type from [_First, _Last) into _Val
|
||
|
return (do_get(_First, _Last, _Intl, _Iosbase, _State, _Val));
|
||
|
}
|
||
|
|
||
|
static locale::id id; // unique facet id
|
||
|
|
||
|
explicit money_get(size_t _Refs = 0)
|
||
|
: locale::facet(_Refs)
|
||
|
{ // construct from current locale
|
||
|
_Init(_Locinfo());
|
||
|
}
|
||
|
|
||
|
money_get(const _Locinfo& _Lobj, size_t _Refs = 0)
|
||
|
: locale::facet(_Refs)
|
||
|
{ // construct from specified locale
|
||
|
_Init(_Lobj);
|
||
|
}
|
||
|
|
||
|
static size_t __cdecl _Getcat(const locale::facet **_Ppf = 0)
|
||
|
{ // return locale category mask and construct standard facet
|
||
|
if (_Ppf != 0 && *_Ppf == 0)
|
||
|
*_Ppf = _NEW_CRT money_get<_Elem, _InIt>;
|
||
|
return (_X_MONETARY);
|
||
|
}
|
||
|
|
||
|
_PROTECTED:
|
||
|
virtual ~money_get()
|
||
|
{ // destroy the object
|
||
|
}
|
||
|
|
||
|
protected:
|
||
|
void _Init(const _Locinfo&)
|
||
|
{ // initialize from _Locinfo object (do nothing)
|
||
|
}
|
||
|
|
||
|
virtual _InIt do_get(_InIt _First, _InIt _Last, bool _Intl,
|
||
|
ios_base& _Iosbase, ios_base::iostate& _State, long double& _Val) const
|
||
|
{ // get long double from [_First, _Last) into _Val
|
||
|
string_type _Str = _Getmfld(_First, _Last, _Intl, _Iosbase);
|
||
|
|
||
|
if (_First == _Last)
|
||
|
_State |= ios_base::eofbit;
|
||
|
if (_Str.size() == 0)
|
||
|
_State |= ios_base::failbit; // _Getmfld failed
|
||
|
else
|
||
|
{ // convert to char string, then to long double
|
||
|
string _Str2;
|
||
|
_Str2.reserve(_Str.size());
|
||
|
for (size_t _Off = 0; _Off < _Str.size(); ++_Off)
|
||
|
_Str2 += _NARROW(_Elem, _Str[_Off]);
|
||
|
|
||
|
const char *_Eb = _Str2.c_str();
|
||
|
char *_Ep;
|
||
|
errno = 0;
|
||
|
const long double _Ans = _Stold(_Eb, &_Ep, 0); // convert
|
||
|
|
||
|
if (_Ep == _Eb || errno != 0)
|
||
|
_State |= ios_base::failbit;
|
||
|
else
|
||
|
_Val = _Ans; // deliver value
|
||
|
}
|
||
|
return (_First);
|
||
|
}
|
||
|
|
||
|
virtual _InIt do_get(_InIt _First, _InIt _Last, bool _Intl,
|
||
|
ios_base& _Iosbase, ios_base::iostate& _State, string_type& _Val) const
|
||
|
{ // get string_type from [_First, _Last) into _Val
|
||
|
string_type _Str = _Getmfld(_First, _Last, _Intl, _Iosbase);
|
||
|
|
||
|
if (_First == _Last)
|
||
|
_State |= ios_base::eofbit;
|
||
|
if (_Str.size() == 0)
|
||
|
_State |= ios_base::failbit; // _Getmfld failed
|
||
|
else
|
||
|
_Val = _Str; // deliver value
|
||
|
return (_First);
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
string_type _Getmfld(_InIt& _First, _InIt& _Last, bool _Intl,
|
||
|
ios_base& _Iosbase) const
|
||
|
{ // get monetary field from [_First, _Last) into string_type
|
||
|
const _Mpunct<_Elem> *_Pfac;
|
||
|
if (_Intl)
|
||
|
_Pfac = &_USE(_Iosbase.getloc(), _Mypunct1); // international
|
||
|
else
|
||
|
_Pfac = &_USE(_Iosbase.getloc(), _Mypunct0); // local
|
||
|
|
||
|
const ctype<_Elem>& _Fac2 = _USE(_Iosbase.getloc(), ctype<_Elem>);
|
||
|
bool _Bad = false, _Neg = false;
|
||
|
string_type _Sign, _Val;
|
||
|
const money_base::pattern _Pattern = _Pfac->neg_format();
|
||
|
|
||
|
for (size_t _Off = 0; !_Bad && _Off < 4; ++_Off)
|
||
|
switch (_Pattern.field[_Off])
|
||
|
{ // parse a format component
|
||
|
case money_base::symbol:
|
||
|
{ // parse currency symbol
|
||
|
string_type _Symbol = _Pfac->curr_symbol();
|
||
|
typename string_type::const_iterator _Source;
|
||
|
|
||
|
if (_Iosbase.flags() & ios_base::showbase)
|
||
|
; // showbase ==> mandatory currency symbol
|
||
|
else if (_Off == 3 && _Sign.size() <= 1
|
||
|
&& (_First == _Last || *_First != *_Symbol.c_str()))
|
||
|
_Symbol.erase(); // currency symbol optional at end
|
||
|
|
||
|
for (_Source = _Symbol.begin();
|
||
|
_First != _Last && _Source != _Symbol.end()
|
||
|
&& *_First == *_Source; ++_Source, ++_First)
|
||
|
; // still matching currency symbol
|
||
|
|
||
|
if (_Source != _Symbol.end())
|
||
|
_Bad = true; // currency symbol match failed
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case money_base::sign: // parse sign
|
||
|
if (_First == _Last)
|
||
|
; // assume no sign
|
||
|
else if (0 < (_Pfac->positive_sign()).size()
|
||
|
&& _Pfac->positive_sign()[0] == *_First)
|
||
|
{ // match positive sign
|
||
|
++_First;
|
||
|
_Sign = _Pfac->positive_sign();
|
||
|
}
|
||
|
else if (0 < (_Pfac->negative_sign()).size()
|
||
|
&& _Pfac->negative_sign()[0] == *_First)
|
||
|
{ // match negative sign
|
||
|
++_First;
|
||
|
_Sign = _Pfac->negative_sign();
|
||
|
_Neg = true;
|
||
|
}
|
||
|
break; // sign match can't fail
|
||
|
|
||
|
case money_base::value:
|
||
|
{ // parse value field
|
||
|
int _Fracdigseen = 0;
|
||
|
int _Fracdigits = _Pfac->frac_digits();
|
||
|
const string _Grouping = _Pfac->grouping();
|
||
|
|
||
|
if (*_Grouping.c_str() <= '\0')
|
||
|
while (_First != _Last
|
||
|
&& _Fac2.is(ctype_base::digit, *_First))
|
||
|
_Val += *_First++; // no grouping, just gather digits
|
||
|
else
|
||
|
{ // grouping specified, gather digits and group sizes
|
||
|
const _Elem _Kseparator = _Pfac->thousands_sep();
|
||
|
string _Groups((size_t)1, '\0');
|
||
|
size_t _Group = 0;
|
||
|
|
||
|
for (; _First != _Last; ++_First)
|
||
|
if (_Fac2.is(ctype_base::digit, *_First))
|
||
|
{ // got a digit, add to group size
|
||
|
_Val += *_First;
|
||
|
if (_Groups[_Group] != CHAR_MAX)
|
||
|
++_Groups[_Group];
|
||
|
}
|
||
|
else if (_Groups[_Group] == '\0'
|
||
|
|| _Kseparator == (_Elem)0
|
||
|
|| *_First != _Kseparator)
|
||
|
break; // not a group separator, done
|
||
|
else
|
||
|
{ // add a new group to _Groups string
|
||
|
_Groups.append((size_t)1, '\0');
|
||
|
++_Group;
|
||
|
}
|
||
|
|
||
|
if (_Group == 0)
|
||
|
; // no thousands separators seen
|
||
|
else if ('\0' < _Groups[_Group])
|
||
|
++_Group; // add trailing group to group count
|
||
|
else
|
||
|
_Bad = true; // trailing separator, fail
|
||
|
|
||
|
for (const char *_Pg = _Grouping.c_str();
|
||
|
!_Bad && 0 < _Group; )
|
||
|
if (*_Pg == CHAR_MAX)
|
||
|
break; // end of grouping constraints to check
|
||
|
else if (0 < --_Group && *_Pg != _Groups[_Group]
|
||
|
|| 0 == _Group && *_Pg < _Groups[_Group])
|
||
|
_Bad = true; // bad group size, fail
|
||
|
else if ('\0' < _Pg[1])
|
||
|
++_Pg; // group size okay, advance to next test
|
||
|
if (_Bad)
|
||
|
break; // bad grouping, give up
|
||
|
}
|
||
|
|
||
|
if (_First != _Last && *_First == _Pfac->decimal_point())
|
||
|
{ // seen decimal point, gather fraction digits
|
||
|
while (++_First != _Last
|
||
|
&& _Fac2.is(ctype_base::digit, *_First))
|
||
|
if (_Fracdigseen < _Fracdigits)
|
||
|
_Val += *_First, ++_Fracdigseen;
|
||
|
}
|
||
|
|
||
|
if (_Val.size() == 0)
|
||
|
_Bad = true; // fail if no elements parsed
|
||
|
else
|
||
|
for (; _Fracdigseen < _Fracdigits; ++_Fracdigseen)
|
||
|
_Val += _WIDEN(_Elem, '0'); // pad out fraction
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case money_base::space: // parse space
|
||
|
if (_Off == 3)
|
||
|
break; // ignore space format at end
|
||
|
while (_First != _Last
|
||
|
&& _Fac2.is(ctype_base::space, *_First))
|
||
|
++_First; // space match can't fail
|
||
|
}
|
||
|
|
||
|
if (!_Bad && 1 < _Sign.size())
|
||
|
{ // match rest of sign string
|
||
|
typename string_type::const_iterator _Source;
|
||
|
|
||
|
for (_Source = _Sign.begin(); _First != _Last
|
||
|
&& ++_Source != _Sign.end() && *_First == *_Source; ++_First)
|
||
|
;
|
||
|
if (_Source != _Sign.end())
|
||
|
_Bad = true; // rest of sign doesn't match, fail
|
||
|
}
|
||
|
|
||
|
if (_Bad)
|
||
|
_Val.erase(); // bad input, return empty string
|
||
|
else if (_Neg)
|
||
|
_Val.insert((size_t)0, (size_t)1, _WIDEN(_Elem, '-'));
|
||
|
return (_Val);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// STATIC money_get::id OBJECT
|
||
|
template<class _Elem,
|
||
|
class _InIt>
|
||
|
locale::id money_get<_Elem, _InIt>::id;
|
||
|
|
||
|
// TEMPLATE CLASS money_put
|
||
|
template<class _Elem,
|
||
|
class _OutIt = ostreambuf_iterator<_Elem, char_traits<_Elem> > >
|
||
|
class money_put
|
||
|
: public locale::facet
|
||
|
{ // facet for converting encoded monetary amounts to text
|
||
|
typedef moneypunct<_Elem, false> _Mypunct0;
|
||
|
typedef moneypunct<_Elem, true> _Mypunct1;
|
||
|
|
||
|
public:
|
||
|
typedef _Elem char_type;
|
||
|
typedef _OutIt iter_type;
|
||
|
typedef basic_string<_Elem, char_traits<_Elem>, allocator<_Elem> >
|
||
|
string_type;
|
||
|
|
||
|
_OutIt put(_OutIt _Dest, bool _Intl, ios_base& _Iosbase, _Elem _Fill,
|
||
|
long double _Val) const
|
||
|
{ // put long double to _Dest
|
||
|
return (do_put(_Dest, _Intl, _Iosbase, _Fill, _Val));
|
||
|
}
|
||
|
|
||
|
_OutIt put(_OutIt _Dest, bool _Intl, ios_base& _Iosbase, _Elem _Fill,
|
||
|
const string_type& _Val) const
|
||
|
{ // put string_type to _Dest
|
||
|
return (do_put(_Dest, _Intl, _Iosbase, _Fill, _Val));
|
||
|
}
|
||
|
|
||
|
static locale::id id; // unique facet id
|
||
|
|
||
|
explicit money_put(size_t _Refs = 0)
|
||
|
: locale::facet(_Refs)
|
||
|
{ // construct from current locale
|
||
|
_Init(_Locinfo());
|
||
|
}
|
||
|
|
||
|
money_put(const _Locinfo& _Lobj, size_t _Refs = 0)
|
||
|
: locale::facet(_Refs)
|
||
|
{ // construct from specified locale
|
||
|
_Init(_Lobj);
|
||
|
}
|
||
|
|
||
|
static size_t __cdecl _Getcat(const locale::facet **_Ppf = 0)
|
||
|
{ // return locale category mask and construct standard facet
|
||
|
if (_Ppf != 0 && *_Ppf == 0)
|
||
|
*_Ppf = _NEW_CRT money_put<_Elem, _OutIt>;
|
||
|
return (_X_MONETARY);
|
||
|
}
|
||
|
|
||
|
_PROTECTED:
|
||
|
virtual ~money_put()
|
||
|
{ // destroy the object
|
||
|
}
|
||
|
|
||
|
protected:
|
||
|
void _Init(const _Locinfo&)
|
||
|
{ // initialize from _Locinfo object (do nothing)
|
||
|
}
|
||
|
|
||
|
virtual _OutIt do_put(_OutIt _Dest, bool _Intl,
|
||
|
ios_base& _Iosbase, _Elem _Fill, long double _Val) const
|
||
|
{ // put long double to _Dest
|
||
|
bool _Negative = false;
|
||
|
if (_Val < 0)
|
||
|
_Negative = true, _Val = -_Val;
|
||
|
|
||
|
size_t _Exp;
|
||
|
for (_Exp = 0; 1e35 <= _Val && _Exp < 5000; _Exp += 10)
|
||
|
_Val /= 1e10; // drop 10 zeros before decimal point
|
||
|
|
||
|
string_type _Val2;
|
||
|
char _Buf[40];
|
||
|
int _Count = ::sprintf(_Buf, "%.0Lf",
|
||
|
_Val); // convert to chars
|
||
|
for (int _Off = 0; _Off < _Count; ++_Off)
|
||
|
_Val2.append((typename string_type::size_type)1,
|
||
|
_WIDEN(_Elem, _Buf[_Off])); // convert chars to elements
|
||
|
_Val2.append(_Exp, _WIDEN(_Elem, '0'));
|
||
|
|
||
|
return (_Putmfld(_Dest, _Intl, _Iosbase, _Fill, _Negative, _Val2));
|
||
|
}
|
||
|
|
||
|
virtual _OutIt do_put(_OutIt _Dest, bool _Intl,
|
||
|
ios_base& _Iosbase, _Elem _Fill, const string_type& _Val) const
|
||
|
{ // put string_type to _Dest
|
||
|
const ctype<_Elem>& _Fac = _USE(_Iosbase.getloc(), ctype<_Elem>);
|
||
|
const _Elem *_Ptr = _Val.c_str();
|
||
|
bool _Negative = false;
|
||
|
if (*_Ptr == _WIDEN(_Elem, '-'))
|
||
|
_Negative = true, ++_Ptr;
|
||
|
|
||
|
size_t _Count;
|
||
|
for (_Count = 0; _Fac.is(ctype_base::digit, _Ptr[_Count]); ++_Count)
|
||
|
; // count digits
|
||
|
string_type _Val2(_Ptr, _Count);
|
||
|
if (_Count == 0)
|
||
|
_Val2.append((typename string_type::size_type)1,
|
||
|
_WIDEN(_Elem, '0')); // replace empty digit string with '0'
|
||
|
|
||
|
return (_Putmfld(_Dest, _Intl, _Iosbase, _Fill, _Negative, _Val2));
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
_OutIt _Putmfld(_OutIt _Dest, bool _Intl, ios_base& _Iosbase, _Elem _Fill,
|
||
|
bool _Neg, string_type _Val) const
|
||
|
{ // put string_type with just digits to _Dest
|
||
|
const _Mpunct<_Elem> *_Pfac;
|
||
|
if (_Intl)
|
||
|
_Pfac = &_USE(_Iosbase.getloc(), _Mypunct1); // international
|
||
|
else
|
||
|
_Pfac = &_USE(_Iosbase.getloc(), _Mypunct0); // local
|
||
|
|
||
|
size_t _Fracdigits = _Pfac->frac_digits();
|
||
|
const string _Grouping = _Pfac->grouping();
|
||
|
|
||
|
if (_Fracdigits < _Val.size() && '\0' < *_Grouping.c_str())
|
||
|
{ // grouping specified, add thousands separators
|
||
|
const _Elem _Kseparator = _Pfac->thousands_sep();
|
||
|
const char *_Pg = _Grouping.c_str();
|
||
|
size_t _Off = _Val.size() - _Fracdigits; // start of fraction
|
||
|
|
||
|
while (*_Pg != CHAR_MAX && '\0' < *_Pg
|
||
|
&& (size_t)*_Pg < _Off)
|
||
|
{ // add a thousands separator, right to left
|
||
|
_Val.insert(_Off -= *_Pg, (size_t)1, _Kseparator);
|
||
|
if ('\0' < _Pg[1])
|
||
|
++_Pg; // not last group, advance
|
||
|
}
|
||
|
}
|
||
|
|
||
|
money_base::pattern _Pattern;
|
||
|
string_type _Sign;
|
||
|
if (_Neg)
|
||
|
{ // negative value, choose appropriate format and sign
|
||
|
_Pattern = _Pfac->neg_format();
|
||
|
_Sign = _Pfac->negative_sign();
|
||
|
}
|
||
|
else
|
||
|
{ // positive value, choose appropriate format and sign
|
||
|
_Pattern = _Pfac->pos_format();
|
||
|
_Sign = _Pfac->positive_sign();
|
||
|
}
|
||
|
|
||
|
string_type _Symbol;
|
||
|
if (_Iosbase.flags() & ios_base::showbase)
|
||
|
_Symbol = _Pfac->curr_symbol(); // showbase ==> show symbol
|
||
|
|
||
|
bool _Intern = false;
|
||
|
size_t _Fillcount, _Off;
|
||
|
for (_Fillcount = 0, _Off = 0; _Off < 4; ++_Off)
|
||
|
switch (_Pattern.field[_Off])
|
||
|
{ // accumulate total length in _Fillcount
|
||
|
case money_base::symbol: // count currency symbol size
|
||
|
_Fillcount += _Symbol.size();
|
||
|
break;
|
||
|
|
||
|
case money_base::sign: // count sign size
|
||
|
_Fillcount += _Sign.size();
|
||
|
break;
|
||
|
|
||
|
case money_base::value: // count value field size
|
||
|
_Fillcount += _Val.size() + (0 < _Fracdigits ? 1 : 0)
|
||
|
+ (_Val.size() <= _Fracdigits
|
||
|
? _Fracdigits - _Val.size() + 1 : 0);
|
||
|
break;
|
||
|
|
||
|
case money_base::space: // count space size
|
||
|
_Intern = true;
|
||
|
}
|
||
|
|
||
|
_Fillcount = _Iosbase.width() <= 0
|
||
|
|| (size_t)_Iosbase.width() <= _Fillcount
|
||
|
? 0 : (size_t)_Iosbase.width() - _Fillcount;
|
||
|
|
||
|
ios_base::fmtflags _Afl =
|
||
|
_Iosbase.flags() & ios_base::adjustfield;
|
||
|
if (_Afl != ios_base::left
|
||
|
&& (_Afl != ios_base::internal || !_Intern))
|
||
|
{ // put leading fill
|
||
|
_Dest = _Rep(_Dest, _Fill, _Fillcount);
|
||
|
_Fillcount = 0;
|
||
|
}
|
||
|
|
||
|
for (_Off = 0; _Off < 4; ++_Off)
|
||
|
switch (_Pattern.field[_Off])
|
||
|
{ // put components as specified by _Pattern
|
||
|
case money_base::symbol: // put currency symbol
|
||
|
_Dest = _Put(_Dest, _Symbol.begin(), _Symbol.size());
|
||
|
break;
|
||
|
|
||
|
case money_base::sign: // put sign
|
||
|
if (0 < _Sign.size())
|
||
|
_Dest = _Put(_Dest, _Sign.begin(), 1);
|
||
|
break;
|
||
|
|
||
|
case money_base::value: // put value field
|
||
|
if (_Fracdigits == 0)
|
||
|
_Dest = _Put(_Dest, _Val.begin(),
|
||
|
_Val.size()); // no fraction part
|
||
|
else if (_Val.size() <= _Fracdigits)
|
||
|
{ // put leading zero, all fraction digits
|
||
|
*_Dest++ = _WIDEN(_Elem, '0');
|
||
|
*_Dest++ = _Pfac->decimal_point();
|
||
|
_Dest = _Rep(_Dest, _WIDEN(_Elem, '0'),
|
||
|
_Fracdigits - _Val.size()); // insert zeros
|
||
|
_Dest = _Put(_Dest, _Val.begin(), _Val.size());
|
||
|
}
|
||
|
else
|
||
|
{ // put both integer and fraction parts
|
||
|
_Dest = _Put(_Dest, _Val.begin(),
|
||
|
_Val.size() - _Fracdigits); // put integer part
|
||
|
*_Dest++ = _Pfac->decimal_point();
|
||
|
_Dest = _Put(_Dest, _Val.end() - _Fracdigits,
|
||
|
_Fracdigits); // put fraction part
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case money_base::space: // put any internal fill
|
||
|
if (_Afl == ios_base::internal)
|
||
|
{ // put internal fill
|
||
|
_Dest = _Rep(_Dest, _Fill, _Fillcount);
|
||
|
_Fillcount = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (1 < _Sign.size())
|
||
|
_Dest = _Put(_Dest, _Sign.begin() + 1,
|
||
|
_Sign.size() - 1); // put remainder of sign
|
||
|
_Iosbase.width(0);
|
||
|
return (_Rep(_Dest, _Fill, _Fillcount)); // put trailing fill
|
||
|
}
|
||
|
|
||
|
static _OutIt __cdecl _Put(_OutIt _Dest,
|
||
|
typename string_type::const_iterator _Source, size_t _Count)
|
||
|
{ // put [_Source, _Source + _Count) to _Dest
|
||
|
for (; 0 < _Count; --_Count, ++_Dest, ++_Source)
|
||
|
*_Dest = *_Source;
|
||
|
return (_Dest);
|
||
|
}
|
||
|
|
||
|
static _OutIt __cdecl _Rep(_OutIt _Dest, _Elem _Ch, size_t _Count)
|
||
|
{ // put _Count * _Ch to _Dest
|
||
|
for (; 0 < _Count; --_Count, ++_Dest)
|
||
|
*_Dest = _Ch;
|
||
|
return (_Dest);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// STATIC money_put::id OBJECT
|
||
|
template<class _Elem,
|
||
|
class _OutIt>
|
||
|
locale::id money_put<_Elem, _OutIt>::id;
|
||
|
|
||
|
#ifdef _DLL_CPPLIB
|
||
|
template class _CRTIMP2 moneypunct<char, true>;
|
||
|
template class _CRTIMP2 moneypunct<char, false>;
|
||
|
template class _CRTIMP2 moneypunct<wchar_t, true>;
|
||
|
template class _CRTIMP2 moneypunct<wchar_t, false>;
|
||
|
template class _CRTIMP2 money_get<char,
|
||
|
istreambuf_iterator<char, char_traits<char> > >;
|
||
|
template class _CRTIMP2 money_get<wchar_t,
|
||
|
istreambuf_iterator<wchar_t, char_traits<wchar_t> > >;
|
||
|
template class _CRTIMP2 money_put<char,
|
||
|
ostreambuf_iterator<char, char_traits<char> > >;
|
||
|
template class _CRTIMP2 money_put<wchar_t,
|
||
|
ostreambuf_iterator<wchar_t, char_traits<wchar_t> > >;
|
||
|
#endif // _DLL_CPPLIB
|
||
|
_STD_END
|
||
|
#pragma warning(pop)
|
||
|
#pragma pack(pop)
|
||
|
|
||
|
#endif /* _XLOCMON_ */
|
||
|
|
||
|
/*
|
||
|
* Copyright (c) 1992-2001 by P.J. Plauger. ALL RIGHTS RESERVED.
|
||
|
* Consult your license regarding permissions and restrictions.
|
||
|
V3.10:0009 */
|