// xlocnum internal header (from ) #pragma once #ifndef _XLOCNUM_ #define _XLOCNUM_ #include #include #include #include #include #pragma pack(push,8) #pragma warning(push,3) _STD_BEGIN // TEMPLATE CLASS numpunct template class numpunct : public locale::facet { // facet for defining numeric punctuation text public: typedef basic_string<_Elem, char_traits<_Elem>, allocator<_Elem> > string_type; typedef _Elem char_type; static locale::id id; // unique facet id _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 falsename() const { // return name for false return (do_falsename()); } string_type truename() const { // return name for true return (do_truename()); } explicit numpunct(size_t _Refs = 0) : locale::facet(_Refs) { // construct from current locale _Init(_Locinfo()); } numpunct(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 numpunct<_Elem>; return (_X_NUMERIC); } _PROTECTED: virtual ~numpunct() { // destroy the object _Tidy(); } protected: void _Init(const _Locinfo& _Lobj) { // initialize from _Lobj const lconv *_Ptr = _Lobj._Getlconv(); _Grouping = 0; _Falsename = 0; _Truename = 0; _TRY_BEGIN _Grouping = _MAKLOCSTR(char, _Ptr->grouping, _Lobj._Getcvt()); _Falsename = _MAKLOCSTR(_Elem, _Lobj._Getfalse(), _Lobj._Getcvt()); _Truename = _MAKLOCSTR(_Elem, _Lobj._Gettrue(), _Lobj._Getcvt()); _CATCH_ALL _Tidy(); _RERAISE; _CATCH_END _Dp = _WIDEN(_Elem, _Ptr->decimal_point[0]); _Kseparator = _WIDEN(_Elem, _Ptr->thousands_sep[0]); } virtual _Elem do_decimal_point() const { // return decimal point return (_Dp); } 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_falsename() const { // return name for false return (string_type(_Falsename)); } virtual string_type do_truename() const { // return name for true return (string_type(_Truename)); } private: void _Tidy() { // free all storage _DELETE_CRT_VEC((void *)_Grouping); _DELETE_CRT_VEC((void *)_Falsename); _DELETE_CRT_VEC((void *)_Truename); } const char *_Grouping; // grouping string, "" for "C" locale _Elem _Dp; // decimal point, '.' for "C" locale _Elem _Kseparator; // thousands separator, '\0' for "C" locale const _Elem *_Falsename; // name for false, "false" for "C" locale const _Elem *_Truename; // name for true, "true" for "C" locale }; typedef numpunct _Npc; typedef numpunct _Npwc; // TEMPLATE CLASS numpunct_byname template class numpunct_byname : public numpunct<_Elem> { // numpunct for named locale public: explicit numpunct_byname(const char *_Locname, size_t _Refs = 0) : numpunct<_Elem>(_Locinfo(_Locname), _Refs) { // construct for named locale } _PROTECTED: virtual ~numpunct_byname() { // destroy the object } }; // STATIC numpunct::id OBJECT template locale::id numpunct<_Elem>::id; #define _VIRTUAL virtual // TEMPLATE CLASS num_get template > > class num_get : public locale::facet { // facet for converting text to encoded numbers public: typedef numpunct<_Elem> _Mypunct; typedef basic_string<_Elem, char_traits<_Elem>, allocator<_Elem> > _Mystr; 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 num_get<_Elem, _InIt>; return (_X_NUMERIC); } static locale::id id; // unique facet id _PROTECTED: virtual ~num_get() { // destroy the object } protected: void _Init(const _Locinfo&) { // initialize from _Locinfo object (do nothing) } public: explicit num_get(size_t _Refs = 0) : locale::facet(_Refs) { // construct from current locale _Init(_Locinfo()); } num_get(const _Locinfo& _Lobj, size_t _Refs = 0) : locale::facet(_Refs) { // construct from specified locale _Init(_Lobj); } typedef _Elem char_type; typedef _InIt iter_type; _InIt get(_InIt _First, _InIt _Last, ios_base& _Iosbase, ios_base::iostate& _State, _Bool& _Val) const { // get bool from [_First, _Last) into _Val return (do_get(_First, _Last, _Iosbase, _State, _Val)); } _InIt get(_InIt _First, _InIt _Last, ios_base& _Iosbase, ios_base::iostate& _State, unsigned short& _Val) const { // get unsigned short from [_First, _Last) into _Val return (do_get(_First, _Last, _Iosbase, _State, _Val)); } _InIt get(_InIt _First, _InIt _Last, ios_base& _Iosbase, ios_base::iostate& _State, unsigned int& _Val) const { // get unsigned int from [_First, _Last) into _Val return (do_get(_First, _Last, _Iosbase, _State, _Val)); } _InIt get(_InIt _First, _InIt _Last, ios_base& _Iosbase, ios_base::iostate& _State, long& _Val) const { // get long from [_First, _Last) into _Val return (do_get(_First, _Last, _Iosbase, _State, _Val)); } _InIt get(_InIt _First, _InIt _Last, ios_base& _Iosbase, ios_base::iostate& _State, unsigned long& _Val) const { // get unsigned long from [_First, _Last) into _Val return (do_get(_First, _Last, _Iosbase, _State, _Val)); } #ifdef _LONGLONG _InIt get(_InIt _First, _InIt _Last, ios_base& _Iosbase, ios_base::iostate& _State, _LONGLONG& _Val) const { // get long long from [_First, _Last) into _Val return (do_get(_First, _Last, _Iosbase, _State, _Val)); } _InIt get(_InIt _First, _InIt _Last, ios_base& _Iosbase, ios_base::iostate& _State, _ULONGLONG& _Val) const { // get unsigned long long from [_First, _Last) into _Val return (do_get(_First, _Last, _Iosbase, _State, _Val)); } #endif /* _LONGLONG */ _InIt get(_InIt _First, _InIt _Last, ios_base& _Iosbase, ios_base::iostate& _State, float& _Val) const { // get float from [_First, _Last) into _Val return (do_get(_First, _Last, _Iosbase, _State, _Val)); } _InIt get(_InIt _First, _InIt _Last, ios_base& _Iosbase, ios_base::iostate& _State, double& _Val) const { // get double from [_First, _Last) into _Val return (do_get(_First, _Last, _Iosbase, _State, _Val)); } _InIt get(_InIt _First, _InIt _Last, ios_base& _Iosbase, ios_base::iostate& _State, long double& _Val) const { // get long double from [_First, _Last) into _Val return (do_get(_First, _Last, _Iosbase, _State, _Val)); } _InIt get(_InIt _First, _InIt _Last, ios_base& _Iosbase, ios_base::iostate& _State, void *& _Val) const { // get void pointer from [_First, _Last) into _Val return (do_get(_First, _Last, _Iosbase, _State, _Val)); } protected: _VIRTUAL _InIt do_get(_InIt _First, _InIt _Last, ios_base& _Iosbase, ios_base::iostate& _State, _Bool& _Val) const { // get bool from [_First, _Last) into _Val int _Ans = -1; // negative answer indicates failure if (_Iosbase.flags() & ios_base::boolalpha) { // get false name or true name const _Mypunct& _Fac = _USE(_Iosbase.getloc(), _Mypunct); _Mystr _Str((typename _Mystr::size_type)1, (char_type)0); _Str += _Fac.falsename(); _Str += (char_type)0; _Str += _Fac.truename(); // construct "\0false\0true" _Ans = _Getloctxt(_First, _Last, (size_t)2, _Str.c_str()); } else { // get zero or nonzero integer char _Ac[_MAX_INT_DIG], *_Ep; errno = 0; const unsigned long _Ulo = ::strtoul(_Ac, &_Ep, _Getifld(_Ac, _First, _Last, _Iosbase.flags(), _Iosbase.getloc())); if (_Ep != _Ac && errno == 0 && _Ulo <= 1) _Ans = _Ulo; } if (_First == _Last) _State |= ios_base::eofbit; if (_Ans < 0) _State |= ios_base::failbit; else _Val = _Ans != 0; // deliver value return (_First); } _VIRTUAL _InIt do_get(_InIt _First, _InIt _Last, ios_base& _Iosbase, ios_base::iostate& _State, unsigned short& _Val) const { // get unsigned short from [_First, _Last) into _Val char _Ac[_MAX_INT_DIG], *_Ep; errno = 0; int _Base = _Getifld(_Ac, _First, _Last, _Iosbase.flags(), _Iosbase.getloc()); // gather field into _Ac char *_Ptr = _Ac[0] == '-' ? _Ac + 1 : _Ac; // point past any sign const unsigned long _Ans = ::strtoul(_Ptr, &_Ep, _Base); // convert if (_First == _Last) _State |= ios_base::eofbit; if (_Ep == _Ptr || errno != 0 || USHRT_MAX < _Ans) _State |= ios_base::failbit; else _Val = (unsigned short)(_Ac[0] == '-' ? 0 -_Ans : _Ans); // deliver value return (_First); } _VIRTUAL _InIt do_get(_InIt _First, _InIt _Last, ios_base& _Iosbase, ios_base::iostate& _State, unsigned int& _Val) const { // get unsigned int from [_First, _Last) into _Val char _Ac[_MAX_INT_DIG], *_Ep; errno = 0; int _Base = _Getifld(_Ac, _First, _Last, _Iosbase.flags(), _Iosbase.getloc()); // gather field into _Ac char *_Ptr = _Ac[0] == '-' ? _Ac + 1 : _Ac; // point past any sign const unsigned long _Ans = ::strtoul(_Ptr, &_Ep, _Base); // convert if (_First == _Last) _State |= ios_base::eofbit; if (_Ep == _Ptr || errno != 0 || UINT_MAX < _Ans) _State |= ios_base::failbit; else _Val = _Ac[0] == '-' ? 0 -_Ans : _Ans; // deliver value return (_First); } _VIRTUAL _InIt do_get(_InIt _First, _InIt _Last, ios_base& _Iosbase, ios_base::iostate& _State, long& _Val) const { // get long from [_First, _Last) into _Val char _Ac[_MAX_INT_DIG], *_Ep; errno = 0; const long _Ans = ::strtol(_Ac, &_Ep, _Getifld(_Ac, _First, _Last, _Iosbase.flags(), _Iosbase.getloc())); // gather field, convert if (_First == _Last) _State |= ios_base::eofbit; if (_Ep == _Ac || errno != 0) _State |= ios_base::failbit; else _Val = _Ans; // deliver value return (_First); } _VIRTUAL _InIt do_get(_InIt _First, _InIt _Last, ios_base& _Iosbase, ios_base::iostate& _State, unsigned long& _Val) const { // get unsigned long from [_First, _Last) into _Val char _Ac[_MAX_INT_DIG], *_Ep; errno = 0; const unsigned long _Ans = ::strtoul(_Ac, &_Ep, _Getifld(_Ac, _First, _Last, _Iosbase.flags(), _Iosbase.getloc())); // gather field, convert if (_First == _Last) _State |= ios_base::eofbit; if (_Ep == _Ac || errno != 0) _State |= ios_base::failbit; else _Val = _Ans; // deliver value return (_First); } #ifdef _LONGLONG _VIRTUAL _InIt do_get(_InIt _First, _InIt _Last, ios_base& _Iosbase, ios_base::iostate& _State, _LONGLONG& _Val) const { // get long long from [_First, _Last) into _Val char _Ac[_MAX_INT_DIG], *_Ep; errno = 0; const _LONGLONG _Ans = ::_strtoi64(_Ac, &_Ep, _Getifld(_Ac, _First, _Last, _Iosbase.flags(), _Iosbase.getloc())); // gather field, convert if (_First == _Last) _State |= ios_base::eofbit; if (_Ep == _Ac || errno != 0) _State |= ios_base::failbit; else _Val = _Ans; // deliver value return (_First); } _VIRTUAL _InIt do_get(_InIt _First, _InIt _Last, ios_base& _Iosbase, ios_base::iostate& _State, _ULONGLONG& _Val) const { // get unsigned long long from [_First, _Last) into _Val char _Ac[_MAX_INT_DIG], *_Ep; errno = 0; const _ULONGLONG _Ans = ::_strtoui64(_Ac, &_Ep, _Getifld(_Ac, _First, _Last, _Iosbase.flags(), _Iosbase.getloc())); // gather field, convert if (_First == _Last) _State |= ios_base::eofbit; if (_Ep == _Ac || errno != 0) _State |= ios_base::failbit; else _Val = _Ans; // deliver value return (_First); } #endif /* _LONGLONG */ _VIRTUAL _InIt do_get(_InIt _First, _InIt _Last, ios_base& _Iosbase, ios_base::iostate& _State, float& _Val) const { // get float from [_First, _Last) into _Val char _Ac[_MAX_EXP_DIG + _MAX_SIG_DIG + 16], *_Ep; errno = 0; const float _Ans = ::_Stof(_Ac, &_Ep, _Getffld(_Ac, _First, _Last, _Iosbase.getloc())); // gather field, convert if (_First == _Last) _State |= ios_base::eofbit; if (_Ep == _Ac || errno != 0) _State |= ios_base::failbit; else _Val = _Ans; // deliver value return (_First); } _VIRTUAL _InIt do_get(_InIt _First, _InIt _Last, ios_base& _Iosbase, ios_base::iostate& _State, double& _Val) const { // get double from [_First, _Last) into _Val char _Ac[_MAX_EXP_DIG + _MAX_SIG_DIG + 16], *_Ep; errno = 0; const double _Ans = ::_Stod(_Ac, &_Ep, _Getffld(_Ac, _First, _Last, _Iosbase.getloc())); // gather field, convert if (_First == _Last) _State |= ios_base::eofbit; if (_Ep == _Ac || errno != 0) _State |= ios_base::failbit; else _Val = _Ans; // deliver value return (_First); } _VIRTUAL _InIt do_get(_InIt _First, _InIt _Last, ios_base& _Iosbase, ios_base::iostate& _State, long double& _Val) const { // get long double from [_First, _Last) into _Val char _Ac[_MAX_EXP_DIG + _MAX_SIG_DIG + 16], *_Ep; errno = 0; const long double _Ans = ::_Stold(_Ac, &_Ep, _Getffld(_Ac, _First, _Last, _Iosbase.getloc())); // gather field, convert if (_First == _Last) _State |= ios_base::eofbit; if (_Ep == _Ac || errno != 0) _State |= ios_base::failbit; else _Val = _Ans; // deliver value return (_First); } _VIRTUAL _InIt do_get(_InIt _First, _InIt _Last, ios_base& _Iosbase, ios_base::iostate& _State, void *& _Val) const { // get void pointer from [_First, _Last) into _Val char _Ac[_MAX_INT_DIG], *_Ep; errno = 0; #ifdef _LONGLONG int _Base = _Getifld(_Ac, _First, _Last, ios_base::hex, _Iosbase.getloc()); // gather field const _ULONGLONG _Ans = (sizeof (void *) == sizeof (unsigned long)) ? (_ULONGLONG)::strtoul(_Ac, &_Ep, _Base) : ::_strtoui64(_Ac, &_Ep, _Base); #else /* _LONGLONG */ const unsigned long _Ans = ::strtoul(_Ac, &_Ep, _Getifld(_Ac, _First, _Last, ios_base::hex, _Iosbase.getloc())); // gather field, convert #endif /* _LONGLONG */ if (_First == _Last) _State |= ios_base::eofbit; if (_Ep == _Ac || errno != 0) _State |= ios_base::failbit; else _Val = (void *)((char *)0 + _Ans); // deliver value return (_First); } private: static int __cdecl _Getifld(char *_Ac, _InIt& _First, _InIt& _Last, ios_base::fmtflags _Basefield, const locale& _Loc) { // get integer field from [_First, _Last) into _Ac const _Elem _E0 = _WIDEN(_Elem, '0'); const _Mypunct& _Fac = _USE(_Loc, _Mypunct); const string _Grouping = _Fac.grouping(); const _Elem _Kseparator = _Fac.thousands_sep(); char *_Ptr = _Ac; if (_First == _Last) ; // empty field else if (*_First == _WIDEN(_Elem, '+')) *_Ptr++ = '+', ++_First; // gather plus sign else if (*_First == _WIDEN(_Elem, '-')) *_Ptr++ = '-', ++_First; // gather minus sign _Basefield &= ios_base::basefield; int _Base = _Basefield == ios_base::oct ? 8 : _Basefield == ios_base::hex ? 16 : _Basefield == ios_base::_Fmtzero ? 0 : 10; bool _Seendigit = false; // seen a digit in input bool _Nonzero = false; // seen a nonzero digit in input if (_First != _Last && *_First == _E0) { // leading zero, look for 0x, 0X _Seendigit = true, ++_First; if (_First != _Last && (*_First == _WIDEN(_Elem, 'x') || *_First == _WIDEN(_Elem, 'X')) && (_Base == 0 || _Base == 16)) _Base = 16, _Seendigit = false, ++_First; else if (_Base == 0) _Base = 8; } int _Dlen = _Base == 0 || _Base == 10 ? 10 : _Base == 8 ? 8 : 16 + 6; string _Groups((size_t)1, (char)_Seendigit); size_t _Group = 0; for (char *const _Pe = &_Ac[_MAX_INT_DIG - 1]; _First != _Last; ++_First) if (::memchr("0123456789abcdefABCDEF", *_Ptr = _NARROW(_Elem, *_First), _Dlen) != 0) { // got a digit, characterize it and add to group size if ((_Nonzero || *_Ptr != '0') && _Ptr < _Pe) ++_Ptr, _Nonzero = true; _Seendigit = true; 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((string::size_type)1, '\0'); ++_Group; } if (_Group == 0) ; // no thousands separators seen else if ('\0' < _Groups[_Group]) ++_Group; // add trailing group to group count else _Seendigit = false; // trailing separator, fail for (const char *_Pg = _Grouping.c_str(); _Seendigit && 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]) _Seendigit = false; // bad group size, fail else if ('\0' < _Pg[1]) ++_Pg; // group size okay, advance to next test if (_Seendigit && !_Nonzero) *_Ptr++ = '0'; // zero field, replace stripped zero(s) else if (!_Seendigit) _Ptr = _Ac; // roll back pointer to indicate failure *_Ptr = '\0'; return (_Base); } static int __cdecl _Getffld(char *_Ac, _InIt& _First, _InIt &_Last, const locale& _Loc) { // get floating-point field from [_First, _Last) into _Ac const _Elem _E0 = _WIDEN(_Elem, '0'); const _Mypunct& _Fac = _USE(_Loc, _Mypunct); char *_Ptr = _Ac; if (_First == _Last) ; // empty field else if (*_First == _WIDEN(_Elem, '+')) *_Ptr++ = '+', ++_First; // gather plus sign else if (*_First == _WIDEN(_Elem, '-')) *_Ptr++ = '-', ++_First; // gather minus sign bool _Seendigit = false; // seen a digit in input for (; _First != _Last && *_First == _E0; _Seendigit = true, ++_First) ; // strip leading zeros if (_Seendigit) *_Ptr++ = '0'; // put one back int _Significant = 0; // number of significant digits int _Pten = 0; // power of 10 multiplier for (; _First != _Last && (::isdigit)(*_Ptr = _NARROW(_Elem, *_First)); _Seendigit = true, ++_First) if (_Significant < _MAX_SIG_DIG) ++_Ptr, ++_Significant; // save a significant digit else ++_Pten; // or just scale by 10 if (_First != _Last && *_First == _Fac.decimal_point()) *_Ptr++ = localeconv()->decimal_point[0], ++_First; // add . if (_Significant == 0) { // 0000. so far for (; _First != _Last && *_First == _E0; _Seendigit = true, ++_First) --_Pten; // just count leading fraction zeros if (_Pten < 0) *_Ptr++ = '0', ++_Pten; // put one back } for (; _First != _Last && (::isdigit)(*_Ptr = _NARROW(_Elem, *_First)); _Seendigit = true, ++_First) if (_Significant < _MAX_SIG_DIG) ++_Ptr, ++_Significant; // save a significant fraction digit if (_Seendigit && _First != _Last && (*_First == _WIDEN(_Elem, 'e') || *_First == _WIDEN(_Elem, 'E'))) { // 'e' or 'E', collect exponent *_Ptr++ = 'e', ++_First; _Seendigit = false, _Significant = 0; if (_First == _Last) ; // 'e' or 'E' is last element else if (*_First == _WIDEN(_Elem, '+')) *_Ptr++ = '+', ++_First; // gather plus sign else if (*_First == _WIDEN(_Elem, '-')) *_Ptr++ = '-', ++_First; // gather minus sign for (; _First != _Last && *_First == _E0; ) _Seendigit = true, ++_First; // strip leading zeros if (_Seendigit) *_Ptr++ = '0'; // put one back for (; _First != _Last && (::isdigit)(*_Ptr = _NARROW(_Elem, *_First)); _Seendigit = true, ++_First) if (_Significant < _MAX_EXP_DIG) ++_Ptr, ++_Significant; // save a significant digit } if (!_Seendigit) _Ptr = _Ac; // roll back pointer to indicate failure *_Ptr = '\0'; return (_Pten); }; }; // STATIC num_get::id OBJECT template locale::id num_get<_Elem, _InIt>::id; // TEMPLATE CLASS num_put template > > class num_put : public locale::facet { // facet for converting encoded numbers to text public: typedef numpunct<_Elem> _Mypunct; typedef basic_string<_Elem, char_traits<_Elem>, allocator<_Elem> > _Mystr; 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 num_put<_Elem, _OutIt>; return (_X_NUMERIC); } static locale::id id; // unique facet id _PROTECTED: virtual ~num_put() { // destroy the object } protected: void _Init(const _Locinfo&) { // initialize from _Locinfo object (do nothing) } public: explicit num_put(size_t _Refs = 0) : locale::facet(_Refs) { // construct from current locale _Init(_Locinfo()); } num_put(const _Locinfo& _Lobj, size_t _Refs = 0) : locale::facet(_Refs) { // construct from specified locale _Init(_Lobj); } typedef _Elem char_type; typedef _OutIt iter_type; _OutIt put(_OutIt _Dest, ios_base& _Iosbase, _Elem _Fill, _Bool _Val) const { // put formatted bool to _Dest return (do_put(_Dest, _Iosbase, _Fill, _Val)); } _OutIt put(_OutIt _Dest, ios_base& _Iosbase, _Elem _Fill, long _Val) const { // put formatted long to _Dest return (do_put(_Dest, _Iosbase, _Fill, _Val)); } _OutIt put(_OutIt _Dest, ios_base& _Iosbase, _Elem _Fill, unsigned long _Val) const { // put formatted unsigned long to _Dest return (do_put(_Dest, _Iosbase, _Fill, _Val)); } #ifdef _LONGLONG _OutIt put(_OutIt _Dest, ios_base& _Iosbase, _Elem _Fill, _LONGLONG _Val) const { // put formatted long long to _Dest return (do_put(_Dest, _Iosbase, _Fill, _Val)); } _OutIt put(_OutIt _Dest, ios_base& _Iosbase, _Elem _Fill, _ULONGLONG _Val) const { // put formatted unsigned long long to _Dest return (do_put(_Dest, _Iosbase, _Fill, _Val)); } #endif /* _LONGLONG */ _OutIt put(_OutIt _Dest, ios_base& _Iosbase, _Elem _Fill, double _Val) const { // put formatted double to _Dest return (do_put(_Dest, _Iosbase, _Fill, _Val)); } _OutIt put(_OutIt _Dest, ios_base& _Iosbase, _Elem _Fill, long double _Val) const { // put formatted long double to _Dest return (do_put(_Dest, _Iosbase, _Fill, _Val)); } _OutIt put(_OutIt _Dest, ios_base& _Iosbase, _Elem _Fill, const void *_Val) const { // put formatted void pointer to _Dest return (do_put(_Dest, _Iosbase, _Fill, _Val)); } protected: virtual _OutIt do_put(_OutIt _Dest, ios_base& _Iosbase, _Elem _Fill, _Bool _Val) const { // put formatted bool to _Dest if (!(_Iosbase.flags() & ios_base::boolalpha)) return (do_put(_Dest, _Iosbase, _Fill, (long)_Val)); else { // put "false" or "true" const _Mypunct& _Fac = _USE(_Iosbase.getloc(), _Mypunct); const _Mystr _Str(_Val ? _Fac.truename() : _Fac.falsename()); size_t _Fillcount = _Iosbase.width() <= 0 || (size_t)_Iosbase.width() <= _Str.size() ? 0 : (size_t)_Iosbase.width() - _Str.size(); if ((_Iosbase.flags() & ios_base::adjustfield) != ios_base::left) { // put leading fill _Dest = _Rep(_Dest, _Fill, _Fillcount); _Fillcount = 0; } _Dest = _Put(_Dest, _Str.c_str(), _Str.size()); // put field _Iosbase.width(0); return (_Rep(_Dest, _Fill, _Fillcount)); // put trailing fill } } virtual _OutIt do_put(_OutIt _Dest, ios_base& _Iosbase, _Elem _Fill, long _Val) const { // put formatted long to _Dest char _Buf[2 * _MAX_INT_DIG], _Fmt[6]; return (_Iput(_Dest, _Iosbase, _Fill, _Buf, ::sprintf(_Buf, _Ifmt(_Fmt, "ld", _Iosbase.flags()), _Val))); } virtual _OutIt do_put(_OutIt _Dest, ios_base& _Iosbase, _Elem _Fill, unsigned long _Val) const { // put formatted unsigned long to _Dest char _Buf[2 * _MAX_INT_DIG], _Fmt[6]; return (_Iput(_Dest, _Iosbase, _Fill, _Buf, ::sprintf(_Buf, _Ifmt(_Fmt, "lu", _Iosbase.flags()), _Val))); } #ifdef _LONGLONG virtual _OutIt do_put(_OutIt _Dest, ios_base& _Iosbase, _Elem _Fill, _LONGLONG _Val) const { // put formatted long long to _Dest char _Buf[2 * _MAX_INT_DIG], _Fmt[8]; return (_Iput(_Dest, _Iosbase, _Fill, _Buf, ::sprintf(_Buf, _Ifmt(_Fmt, "Ld", _Iosbase.flags()), _Val))); } virtual _OutIt do_put(_OutIt _Dest, ios_base& _Iosbase, _Elem _Fill, _ULONGLONG _Val) const { // put formatted unsigned long long to _Dest char _Buf[2 * _MAX_INT_DIG], _Fmt[8]; return (_Iput(_Dest, _Iosbase, _Fill, _Buf, ::sprintf(_Buf, _Ifmt(_Fmt, "Lu", _Iosbase.flags()), _Val))); } #endif /* _LONGLONG */ virtual _OutIt do_put(_OutIt _Dest, ios_base& _Iosbase, _Elem _Fill, double _Val) const { // put formatted double to _Dest char _Buf[_MAX_EXP_DIG + _MAX_SIG_DIG + 64], _Fmt[8]; streamsize _Precision = _Iosbase.precision() <= 0 && !(_Iosbase.flags() & ios_base::fixed) ? 6 : _Iosbase.precision(); // desired precision int _Significance = _MAX_SIG_DIG < _Precision ? _MAX_SIG_DIG : (int)_Precision; // actual precision for sprintf _Precision -= _Significance; size_t _Beforepoint = 0; // zeros to add before decimal point size_t _Afterpoint = 0; // zeros to add after decimal point if ((_Iosbase.flags() & ios_base::floatfield) == ios_base::fixed) { // scale silly fixed-point value bool _Signed = _Val < 0; if (_Signed) _Val = -_Val; for (; 1e35 <= _Val && _Beforepoint < 5000; _Beforepoint += 10) _Val /= 1e10; // drop 10 zeros before decimal point if (0 < _Val) for (; 10 <= _Precision && _Val <= 1e-35 && _Afterpoint < 5000; _Afterpoint += 10) { // drop 10 zeros after decimal point _Val *= 1e10; _Precision -= 10; } if (_Signed) _Val = -_Val; } return (_Fput(_Dest, _Iosbase, _Fill, _Buf, _Beforepoint, _Afterpoint, _Precision, ::sprintf(_Buf, _Ffmt(_Fmt, 0, _Iosbase.flags()), _Significance, _Val))); // convert and put } virtual _OutIt do_put(_OutIt _Dest, ios_base& _Iosbase, _Elem _Fill, long double _Val) const { // put formatted long double to _Dest char _Buf[_MAX_EXP_DIG + _MAX_SIG_DIG + 64], _Fmt[8]; streamsize _Precision = _Iosbase.precision() <= 0 && !(_Iosbase.flags() & ios_base::fixed) ? 6 : _Iosbase.precision(); // desired precision int _Significance = _MAX_SIG_DIG < _Precision ? _MAX_SIG_DIG : (int)_Precision; // actual precision for sprintf _Precision -= _Significance; size_t _Beforepoint = 0; // zeros to add before decimal point size_t _Afterpoint = 0; // zeros to add after decimal point if ((_Iosbase.flags() & ios_base::floatfield) == ios_base::fixed) { // scale silly fixed-point value bool _Signed = _Val < 0; if (_Signed) _Val = -_Val; for (; 1e35 <= _Val && _Beforepoint < 5000; _Beforepoint += 10) _Val /= 1e10; // drop 10 zeros before decimal point if (0 < _Val) for (; 10 <= _Precision && _Val <= 1e-35 && _Afterpoint < 5000; _Afterpoint += 10) { // drop 10 zeros after decimal point _Val *= 1e10; _Precision -= 10; } if (_Signed) _Val = -_Val; } return (_Fput(_Dest, _Iosbase, _Fill, _Buf, _Beforepoint, _Afterpoint, _Precision, ::sprintf(_Buf, _Ffmt(_Fmt, 'L', _Iosbase.flags()), _Significance, _Val))); // convert and put } virtual _OutIt do_put(_OutIt _Dest, ios_base& _Iosbase, _Elem _Fill, const void *_Val) const { // put formatted void pointer to _Dest char _Buf[2 * _MAX_INT_DIG]; return (_Iput(_Dest, _Iosbase, _Fill, _Buf, ::sprintf(_Buf, "%p", _Val))); } static char *__cdecl _Ffmt(char *_Fmt, char _Spec, ios_base::fmtflags _Flags) { // generate sprintf format for floating-point char *_Ptr = _Fmt; *_Ptr++ = '%'; if (_Flags & ios_base::showpos) *_Ptr++ = '+'; if (_Flags & ios_base::showpoint) *_Ptr++ = '#'; *_Ptr++ = '.'; *_Ptr++ = '*'; // for precision argument if (_Spec != '\0') *_Ptr++ = _Spec; // 'L' qualifier for long double only ios_base::fmtflags _Ffl = _Flags & ios_base::floatfield; *_Ptr++ = _Ffl == ios_base::fixed ? 'f' : _Ffl == ios_base::scientific ? 'e' : 'g'; // specifier *_Ptr = '\0'; return (_Fmt); } static _OutIt __cdecl _Fput(_OutIt _Dest, ios_base& _Iosbase, _Elem _Fill, const char *_Buf, size_t _Beforepoint, size_t _Afterpoint, size_t _Trailing, size_t _Count) { // put formatted floating-point to _Dest _Elem _E0 = _WIDEN(_Elem, '0'); size_t _Fillcount = _Beforepoint + _Afterpoint + _Trailing + _Count; _Fillcount = _Iosbase.width() <= 0 || (size_t)_Iosbase.width() <= _Fillcount ? 0 : (size_t)_Iosbase.width() - _Fillcount; ios_base::fmtflags _Adjustfield = _Iosbase.flags() & ios_base::adjustfield; if (_Adjustfield != ios_base::left && _Adjustfield != ios_base::internal) { // put leading fill _Dest = _Rep(_Dest, _Fill, _Fillcount); _Fillcount = 0; } else if (_Adjustfield == ios_base::internal) { // put internal fill if (0 < _Count && (*_Buf == '+' || *_Buf == '-')) { // but first put sign _Dest = _Putc(_Dest, _Buf, 1); ++_Buf, --_Count; } _Dest = _Rep(_Dest, _Fill, _Fillcount); _Fillcount = 0; } const char *_Ptr = (const char *)::memchr(_Buf, localeconv()->decimal_point[0], _Count); // find decimal point if (_Ptr != 0) { // has decimal point, put pieces and zero fills const _Mypunct& _Fac = _USE(_Iosbase.getloc(), _Mypunct); size_t _Fracoffset = _Ptr - _Buf + 1; _Dest = _Putc(_Dest, _Buf, _Fracoffset - 1); _Dest = _Rep(_Dest, _E0, _Beforepoint); _Dest = _Rep(_Dest, _Fac.decimal_point(), 1); _Dest = _Rep(_Dest, _E0, _Afterpoint); _Buf += _Fracoffset, _Count -= _Fracoffset; } if ((_Ptr = (const char *)::memchr(_Buf, 'e', _Count)) != 0) { // has exponent field, put it out size_t _Expoffset = _Ptr - _Buf + 1; _Dest = _Putc(_Dest, _Buf, _Expoffset - 1); _Dest = _Rep(_Dest, _E0, _Trailing), _Trailing = 0; _Dest = _Putc(_Dest, _Iosbase.flags() & ios_base::uppercase ? "E" : "e", 1); _Buf += _Expoffset, _Count -= _Expoffset; } _Dest = _Putc(_Dest, _Buf, _Count); // put leftover field _Dest = _Rep(_Dest, _E0, _Trailing); // put trailing zeros _Iosbase.width(0); return (_Rep(_Dest, _Fill, _Fillcount)); // put trailing fill } static char *__cdecl _Ifmt(char *_Fmt, const char *_Spec, ios_base::fmtflags _Flags) { // generate sprintf format for integer char *_Ptr = _Fmt; *_Ptr++ = '%'; if (_Flags & ios_base::showpos) *_Ptr++ = '+'; if (_Flags & ios_base::showbase) *_Ptr++ = '#'; if (_Spec[0] != 'L') *_Ptr++ = _Spec[0]; // qualifier else { /* change L to I64 */ *_Ptr++ = 'I'; *_Ptr++ = '6'; *_Ptr++ = '4'; } ios_base::fmtflags _Basefield = _Flags & ios_base::basefield; *_Ptr++ = _Basefield == ios_base::oct ? 'o' : _Basefield != ios_base::hex ? _Spec[1] // 'd' or 'u' : _Flags & ios_base::uppercase ? 'X' : 'x'; *_Ptr = '\0'; return (_Fmt); } static _OutIt __cdecl _Iput(_OutIt _Dest, ios_base& _Iosbase, _Elem _Fill, char *_Buf, size_t _Count) { // put formatted integer to _Dest const size_t _Prefix = *_Buf == '+' || *_Buf == '-' ? 1 : *_Buf == '0' && (_Buf[1] == 'x' || _Buf[1] == 'X') ? 2 : 0; const _Mypunct& _Fac = _USE(_Iosbase.getloc(), _Mypunct); const string _Grouping = _Fac.grouping(); const _Elem _Kseparator = _Fac.thousands_sep(); bool _Grouped = '\0' < *_Grouping.c_str(); if (_Grouped) { // grouping specified, add thousands separators const char *_Pg = _Grouping.c_str(); size_t _Off = _Count; for (_Grouped = false; *_Pg != CHAR_MAX && '\0' < *_Pg && (size_t)*_Pg < _Off - _Prefix; _Grouped = true) { // add a comma to mark thousands separator _Off -= *_Pg; ::memmove(&_Buf[_Off + 1], &_Buf[_Off], _Count + 1 - _Off); _Buf[_Off] = ',', ++_Count; if ('\0' < _Pg[1]) ++_Pg; // not last group, advance } } size_t _Fillcount = _Iosbase.width() <= 0 || (size_t)_Iosbase.width() <= _Count ? 0 : (size_t)_Iosbase.width() - _Count; ios_base::fmtflags _Adjustfield = _Iosbase.flags() & ios_base::adjustfield; if (_Adjustfield != ios_base::left && _Adjustfield != ios_base::internal) { // put leading fill _Dest = _Rep(_Dest, _Fill, _Fillcount); _Fillcount = 0; } else if (_Adjustfield == ios_base::internal) { // put internal fill _Dest = _Putc(_Dest, _Buf, _Prefix); // but first put prefix _Buf += _Prefix, _Count -= _Prefix; _Dest = _Rep(_Dest, _Fill, _Fillcount), _Fillcount = 0; } if (!_Grouped) _Dest = _Putc(_Dest, _Buf, _Count); // put field else for (; ; ++_Buf, --_Count) { // put field with thousands separators for commas size_t _Groupsize = strcspn(_Buf, ","); _Dest = _Putc(_Dest, _Buf, _Groupsize); _Buf += _Groupsize, _Count -= _Groupsize; if (_Count == 0) break; if (_Kseparator != (_Elem)0) _Dest = _Rep(_Dest, _Kseparator, 1); } _Iosbase.width(0); return (_Rep(_Dest, _Fill, _Fillcount)); // put trailing fill } static _OutIt __cdecl _Put(_OutIt _Dest, const _Elem *_Ptr, size_t _Count) { // put [_Ptr, _Ptr + _Count) to _Dest for (; 0 < _Count; --_Count, ++_Dest, ++_Ptr) *_Dest = *_Ptr; return (_Dest); } static _OutIt __cdecl _Putc(_OutIt _Dest, const char *_Ptr, size_t _Count) { // put char sequence [_Ptr, _Ptr + _Count) to _Dest for (; 0 < _Count; --_Count, ++_Dest, ++_Ptr) *_Dest = _WIDEN(_Elem, *_Ptr); 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 num_put::id OBJECT template locale::id num_put<_Elem, _OutIt>::id; #ifdef _DLL_CPPLIB template class _CRTIMP2 numpunct; template class _CRTIMP2 numpunct; template class _CRTIMP2 num_get > >; template class _CRTIMP2 num_get > >; template class _CRTIMP2 num_put > >; template class _CRTIMP2 num_put > >; #endif // _DLL_CPPLIB _STD_END #pragma warning(pop) #pragma pack(pop) #endif /* _XLOCNUM_ */ /* * Copyright (c) 1992-2001 by P.J. Plauger. ALL RIGHTS RESERVED. * Consult your license regarding permissions and restrictions. V3.10:0009 */