// xlocmon internal header (from ) #pragma once #ifndef _XLOCMON_ #define _XLOCMON_ #include #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 _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 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 const bool moneypunct<_Elem, _Intl>::intl = _Intl; // STATIC moneypunct::id OBJECT template locale::id moneypunct<_Elem, _Intl>::id; // TEMPLATE CLASS moneypunct_byname template 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 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 locale::id money_get<_Elem, _InIt>::id; // TEMPLATE CLASS money_put template > > 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 locale::id money_put<_Elem, _OutIt>::id; #ifdef _DLL_CPPLIB template class _CRTIMP2 moneypunct; template class _CRTIMP2 moneypunct; template class _CRTIMP2 moneypunct; template class _CRTIMP2 moneypunct; template class _CRTIMP2 money_get > >; template class _CRTIMP2 money_get > >; template class _CRTIMP2 money_put > >; template class _CRTIMP2 money_put > >; #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 */