windows-nt/Source/XPSP1/NT/base/crts/libw32/include/xlocnum

1153 lines
34 KiB
Plaintext
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
// xlocnum internal header (from <locale>)
#pragma once
#ifndef _XLOCNUM_
#define _XLOCNUM_
#include <cerrno>
#include <climits>
#include <cstdio>
#include <cstdlib>
#include <streambuf>
#pragma pack(push,8)
#pragma warning(push,3)
_STD_BEGIN
// TEMPLATE CLASS numpunct
template<class _Elem>
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<char> _Npc;
typedef numpunct<wchar_t> _Npwc;
// TEMPLATE CLASS numpunct_byname
template<class _Elem>
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<class _Elem>
locale::id numpunct<_Elem>::id;
#define _VIRTUAL virtual
// TEMPLATE CLASS num_get
template<class _Elem,
class _InIt = istreambuf_iterator<_Elem, char_traits<_Elem> > >
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<class _Elem,
class _InIt>
locale::id num_get<_Elem, _InIt>::id;
// TEMPLATE CLASS num_put
template<class _Elem,
class _OutIt = ostreambuf_iterator<_Elem, char_traits<_Elem> > >
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<class _Elem,
class _OutIt>
locale::id num_put<_Elem, _OutIt>::id;
#ifdef _DLL_CPPLIB
template class _CRTIMP2 numpunct<char>;
template class _CRTIMP2 numpunct<wchar_t>;
template class _CRTIMP2 num_get<char,
istreambuf_iterator<char, char_traits<char> > >;
template class _CRTIMP2 num_get<wchar_t,
istreambuf_iterator<wchar_t, char_traits<wchar_t> > >;
template class _CRTIMP2 num_put<char,
ostreambuf_iterator<char, char_traits<char> > >;
template class _CRTIMP2 num_put<wchar_t,
ostreambuf_iterator<wchar_t, char_traits<wchar_t> > >;
#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 */