mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
794 lines
22 KiB
794 lines
22 KiB
// xloctime internal header (from <locale>)
|
|
#pragma once
|
|
#ifndef _XLOCTIME_
|
|
#define _XLOCTIME_
|
|
#include <ctime>
|
|
#include <xiosbase>
|
|
|
|
#pragma pack(push,8)
|
|
#pragma warning(push,3)
|
|
_STD_BEGIN
|
|
|
|
// STRUCT time_base
|
|
struct _CRTIMP2 time_base
|
|
: public locale::facet
|
|
{ // base class for time_get
|
|
enum dateorder
|
|
{ // constants for different orders of date components
|
|
no_order, dmy, mdy, ymd, ydm};
|
|
|
|
time_base(size_t _Refs = 0)
|
|
: locale::facet(_Refs)
|
|
{ // default constructor
|
|
}
|
|
};
|
|
|
|
// TEMPLATE CLASS time_get
|
|
template<class _Elem,
|
|
class _InIt = istreambuf_iterator<_Elem, char_traits<_Elem> > >
|
|
class time_get
|
|
: public time_base
|
|
{ // facet for converting text to encoded times
|
|
public:
|
|
typedef _Elem char_type;
|
|
typedef _InIt iter_type;
|
|
|
|
static locale::id id; // unique facet id
|
|
|
|
dateorder date_order() const
|
|
{ // return date order code
|
|
return (do_date_order());
|
|
}
|
|
|
|
_InIt get_time(_InIt _First, _InIt _Last, ios_base& _Iosbase,
|
|
ios_base::iostate& _State, tm *_Pt) const
|
|
{ // get time of day from [_First, _Last) into _Pt
|
|
return (do_get_time(_First, _Last, _Iosbase, _State, _Pt));
|
|
}
|
|
|
|
_InIt get_date(_InIt _First, _InIt _Last, ios_base& _Iosbase,
|
|
ios_base::iostate& _State, tm *_Pt) const
|
|
{ // get date from [_First, _Last) into _Pt
|
|
return (do_get_date(_First, _Last, _Iosbase, _State, _Pt));
|
|
}
|
|
|
|
_InIt get_weekday(_InIt _First, _InIt _Last, ios_base& _Iosbase,
|
|
ios_base::iostate& _State, tm *_Pt) const
|
|
{ // get weekday from [_First, _Last) into _Pt
|
|
return (do_get_weekday(_First, _Last, _Iosbase, _State, _Pt));
|
|
}
|
|
|
|
_InIt get_monthname(_InIt _First, _InIt _Last, ios_base& _Iosbase,
|
|
ios_base::iostate& _State, tm *_Pt) const
|
|
{ // get month from [_First, _Last) into _Pt
|
|
return (do_get_monthname(_First, _Last, _Iosbase, _State, _Pt));
|
|
}
|
|
|
|
_InIt get_year(_InIt _First, _InIt _Last, ios_base& _Iosbase,
|
|
ios_base::iostate& _State, tm *_Pt) const
|
|
{ // get year from [_First, _Last) into _Pt
|
|
return (do_get_year(_First, _Last, _Iosbase, _State, _Pt));
|
|
}
|
|
|
|
explicit time_get(size_t _Refs = 0)
|
|
: time_base(_Refs)
|
|
{ // construct from current locale
|
|
_Init(_Locinfo());
|
|
}
|
|
|
|
time_get(const _Locinfo& _Lobj, size_t _Refs = 0)
|
|
: time_base(_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 time_get<_Elem, _InIt>;
|
|
return (_X_TIME);
|
|
}
|
|
|
|
_PROTECTED:
|
|
virtual ~time_get()
|
|
{ // destroy the object
|
|
_Tidy();
|
|
}
|
|
|
|
protected:
|
|
void _Init(const _Locinfo& _Lobj)
|
|
{ // initialize from _Lobj
|
|
_Days = 0;
|
|
_Months = 0;
|
|
|
|
_TRY_BEGIN
|
|
_Days = _MAKLOCSTR(_Elem, _Lobj._Getdays(), _Lobj._Getcvt());
|
|
_Months = _MAKLOCSTR(_Elem, _Lobj._Getmonths(), _Lobj._Getcvt());
|
|
_Dateorder = (dateorder)_Lobj._Getdateorder();
|
|
_CATCH_ALL
|
|
_Tidy();
|
|
_RERAISE;
|
|
_CATCH_END
|
|
}
|
|
|
|
virtual dateorder do_date_order() const
|
|
{ // return date order code
|
|
return (_Dateorder);
|
|
}
|
|
|
|
virtual _InIt do_get_time(_InIt _First, _InIt _Last, ios_base&,
|
|
ios_base::iostate& _State, tm *_Pt) const
|
|
{ // get time of day from [_First, _Last) into _Pt
|
|
const _Elem _Colon = _WIDEN(_Elem, ':');
|
|
_State |= _Getint(_First, _Last, 0, 23, _Pt->tm_hour);
|
|
|
|
if (_State != ios_base::goodbit || *_First != _Colon)
|
|
_State |= ios_base::failbit; // hour field is bad
|
|
else
|
|
_State |= _Getint(++_First, _Last, 0, 59, _Pt->tm_min);
|
|
|
|
if (_State != ios_base::goodbit || *_First != _Colon)
|
|
_State |= ios_base::failbit; // min field is bad
|
|
else
|
|
_State |= _Getint(++_First, _Last, 0, 59, _Pt->tm_sec);
|
|
return (_First);
|
|
}
|
|
|
|
virtual _InIt do_get_date(_InIt _First, _InIt _Last, ios_base& _Iosbase,
|
|
ios_base::iostate& _State, tm *_Pt) const
|
|
{ // get date from [_First, _Last) into _Pt
|
|
const _Elem _E0 = _WIDEN(_Elem, '0');
|
|
const _Elem _E9 = _WIDEN(_Elem, '9');
|
|
const _Elem _Colon = _WIDEN(_Elem, ':');
|
|
const _Elem _Comma = _WIDEN(_Elem, ',');
|
|
const _Elem _Slash = _WIDEN(_Elem, '/');
|
|
const _Elem _Space = _WIDEN(_Elem, ' ');
|
|
|
|
dateorder _Dorder = date_order();
|
|
if (_Dorder == no_order)
|
|
_Dorder = mdy;
|
|
|
|
if (*_First < _E0 || _E9 < *_First)
|
|
{ // begins with month name, assume mdy
|
|
_First = get_monthname(_First, _Last, _Iosbase, _State, _Pt);
|
|
_Dorder = mdy;
|
|
}
|
|
else if (_Dorder == mdy)
|
|
{ // get month number
|
|
_State |= _Getint(_First, _Last, 1, 12, _Pt->tm_mon);
|
|
--_Pt->tm_mon;
|
|
}
|
|
else if (_Dorder == dmy)
|
|
_State |= _Getint(_First, _Last, 1, 31, _Pt->tm_mday);
|
|
else // ymd or ydm
|
|
_First = get_year(_First, _Last, _Iosbase, _State, _Pt);
|
|
|
|
if (_State == ios_base::goodbit)
|
|
{ // skip spaces [:,/] spaces
|
|
while (*_First == _Space)
|
|
++_First;
|
|
if (*_First == _Colon || *_First == _Comma || *_First == _Slash)
|
|
++_First;
|
|
while (*_First == _Space)
|
|
++_First;
|
|
}
|
|
|
|
if (_State != ios_base::goodbit)
|
|
;
|
|
else if (*_First < _E0 || _E9 < *_First)
|
|
if (_Dorder == mdy)
|
|
_State |= ios_base::failbit; // error, month already seen
|
|
else
|
|
{ // month name is second, like it or not
|
|
_First = get_monthname(_First, _Last, _Iosbase, _State, _Pt);
|
|
if (_Dorder == ydm)
|
|
_Dorder = ymd;
|
|
}
|
|
else if (_Dorder == dmy || _Dorder == ymd)
|
|
{ // get month number
|
|
_State |= _Getint(_First, _Last, 1, 12, _Pt->tm_mon);
|
|
--_Pt->tm_mon;
|
|
}
|
|
else
|
|
_State |= _Getint(_First, _Last, 1, 31, _Pt->tm_mday);
|
|
|
|
if (_State == ios_base::goodbit)
|
|
{ // skip spaces [:,/] spaces
|
|
while (*_First == _Space)
|
|
++_First;
|
|
if (*_First == _Colon || *_First == _Comma || *_First == _Slash)
|
|
++_First;
|
|
while (*_First == _Space)
|
|
++_First;
|
|
}
|
|
|
|
if (_State != ios_base::goodbit)
|
|
;
|
|
else if (*_First < _E0 || _E9 < *_First)
|
|
if (_Dorder != ydm)
|
|
_State |= ios_base::failbit; // error, month out of place
|
|
else
|
|
_First = get_monthname(_First, _Last, _Iosbase, _State, _Pt);
|
|
else if (_Dorder == ydm)
|
|
{ // get month number
|
|
_State |= _Getint(_First, _Last, 1, 12, _Pt->tm_mon);
|
|
--_Pt->tm_mon;
|
|
}
|
|
else if (_Dorder == ymd)
|
|
_State |= _Getint(_First, _Last, 1, 31, _Pt->tm_mday);
|
|
else // mdy or dmy
|
|
_First = get_year(_First, _Last, _Iosbase, _State, _Pt);
|
|
|
|
if (_First == _Last)
|
|
_State |= ios_base::eofbit;
|
|
return (_First);
|
|
}
|
|
|
|
virtual _InIt do_get_weekday(_InIt _First, _InIt _Last, ios_base&,
|
|
ios_base::iostate& _State, tm *_Pt) const
|
|
{ // get weekday from [_First, _Last) into _Pt
|
|
int _Num = _Getloctxt(_First, _Last, (size_t)0, _Days);
|
|
|
|
if (_Num < 0)
|
|
_State |= ios_base::failbit;
|
|
else
|
|
_Pt->tm_wday = _Num >> 1; // set wday
|
|
return (_First);
|
|
}
|
|
|
|
virtual _InIt do_get_monthname(_InIt _First, _InIt _Last, ios_base&,
|
|
ios_base::iostate& _State, tm *_Pt) const
|
|
{ // get month from [_First, _Last) into _Pt
|
|
int _Num = _Getloctxt(_First, _Last, (size_t)0, _Months);
|
|
|
|
if (_Num < 0)
|
|
_State |= ios_base::failbit;
|
|
else
|
|
_Pt->tm_mon = _Num >> 1; // set mon
|
|
return (_First);
|
|
}
|
|
|
|
virtual _InIt do_get_year(_InIt _First, _InIt _Last, ios_base&,
|
|
ios_base::iostate& _State, tm *_Pt) const
|
|
{ // get year from [_First, _Last) into _Pt
|
|
int _Ans = 0;
|
|
_State |= _Getint(_First, _Last, 0, 2035, _Ans);
|
|
|
|
if (_State & ios_base::failbit)
|
|
;
|
|
else if (1900 <= _Ans)
|
|
_Ans -= 1900; // [1900, ...) as is
|
|
else if (2035 - 1900 < _Ans)
|
|
_State |= ios_base::failbit;
|
|
|
|
if (!(_State & ios_base::failbit))
|
|
_Pt->tm_year = _Ans; // set year
|
|
return (_First);
|
|
}
|
|
|
|
private:
|
|
static ios_base::iostate __cdecl _Getint(_InIt& _First, _InIt& _Last,
|
|
int _Lo, int _Hi, int& _Val)
|
|
{ // get integer in range [_Lo, _Hi] from [_First, _Last)
|
|
char _Ac[_MAX_INT_DIG], *_Ep;
|
|
char *_Ptr = _Ac;
|
|
|
|
if (_First == _Last)
|
|
;
|
|
else if (*_First == _WIDEN(_Elem, '+'))
|
|
*_Ptr++ = '+', ++_First; // copy plus sign
|
|
else if (*_First == _WIDEN(_Elem, '-'))
|
|
*_Ptr++ = '-', ++_First; // copy minus sign
|
|
|
|
bool _Seendigit = false;
|
|
while (_First != _Last && *_First == _WIDEN(_Elem, '0'))
|
|
_Seendigit = true, ++_First; // strip leading zeros
|
|
if (_Seendigit)
|
|
*_Ptr++ = '0'; // replace one or more with single zero
|
|
|
|
for (char *const _Pe = &_Ac[_MAX_INT_DIG - 1]; _First != _Last
|
|
&& '0' <= (*_Ptr = _NARROW(_Elem, *_First)) && *_Ptr <= '9';
|
|
_Seendigit = true, ++_First) // copy digits
|
|
if (_Ptr < _Pe)
|
|
++_Ptr; // drop trailing digits if already too large
|
|
|
|
if (!_Seendigit)
|
|
_Ptr = _Ac;
|
|
*_Ptr = '\0';
|
|
errno = 0;
|
|
const long _Ans = strtol(_Ac, &_Ep, 10);
|
|
ios_base::iostate _State = ios_base::goodbit;
|
|
|
|
if (_First == _Last)
|
|
_State |= ios_base::eofbit;
|
|
if (_Ep == _Ac || errno != 0 || _Ans < _Lo || _Hi < _Ans)
|
|
_State |= ios_base::failbit; // bad conversion
|
|
else
|
|
_Val = _Ans; // store valid result
|
|
return (_State);
|
|
}
|
|
|
|
void _Tidy()
|
|
{ // free all storage
|
|
_DELETE_CRT_VEC((void *)_Days);
|
|
_DELETE_CRT_VEC((void *)_Months);
|
|
}
|
|
|
|
const _Elem *_Days; // ":Sun:Sunday:Mon:Monday..." for example
|
|
const _Elem *_Months; // "Jan:January:Feb:February..." for example
|
|
dateorder _Dateorder;
|
|
};
|
|
|
|
// STATIC time_get::id OBJECT
|
|
template<class _Elem,
|
|
class _InIt>
|
|
locale::id time_get<_Elem, _InIt>::id;
|
|
|
|
// TEMPLATE CLASS time_get_byname
|
|
template<class _Elem,
|
|
class _InIt = istreambuf_iterator<_Elem, char_traits<_Elem> > >
|
|
class time_get_byname
|
|
: public time_get<_Elem, _InIt>
|
|
{ // time_get for named locale
|
|
public:
|
|
explicit time_get_byname(const char *_Locname, size_t _Refs = 0)
|
|
: time_get<_Elem, _InIt>(_Locinfo(_Locname), _Refs)
|
|
{ // construct for named locale
|
|
}
|
|
|
|
_PROTECTED:
|
|
virtual ~time_get_byname()
|
|
{ // destroy the object
|
|
}
|
|
};
|
|
|
|
// TEMPLATE CLASS time_put
|
|
template<class _Elem,
|
|
class _OutIt = ostreambuf_iterator<_Elem, char_traits<_Elem> > >
|
|
class time_put
|
|
: public locale::facet
|
|
{ // facet for converting encoded times to text
|
|
public:
|
|
typedef _Elem char_type;
|
|
typedef _OutIt iter_type;
|
|
|
|
_OutIt put(_OutIt _Dest, ios_base& _Iosbase, _Elem _Fill, const tm *_Pt,
|
|
const _Elem *_Fmtfirst, const _Elem *_Fmtlast) const
|
|
{ // put formatted time from _Pt to _Dest for [_Fmtfirst, _Fmtlast)
|
|
const _Elem _Percent = _WIDEN(_Elem, '%');
|
|
|
|
for (; _Fmtfirst != _Fmtlast; ++_Fmtfirst)
|
|
if (*_Fmtfirst != _Percent)
|
|
*_Dest++ = *_Fmtfirst; // copy literal element
|
|
else if (++_Fmtfirst == _Fmtlast)
|
|
{ // treat trailing % as %%
|
|
*_Dest++ = _Percent;
|
|
break;
|
|
}
|
|
else
|
|
{ // get specifier after %
|
|
char _Specifier = _NARROW(_Elem, *_Fmtfirst);
|
|
char _Qualifier = '\0';
|
|
|
|
if (_Specifier != 'E' && _Specifier != 'O'
|
|
&& _Specifier != 'Q' && _Specifier != '#')
|
|
; // not [E0Q#] qualifier, treat as specifier
|
|
else if (++_Fmtfirst == _Fmtlast)
|
|
{ // no specifier, copy %[E0Q#] as literal elements
|
|
*_Dest++ = _Percent, *_Dest++ = _Specifier;
|
|
break;
|
|
}
|
|
else
|
|
{ // save both qualifier and specifier
|
|
_Qualifier = _Specifier;
|
|
_Specifier = _NARROW(_Elem, *_Fmtfirst);
|
|
}
|
|
|
|
_Dest = do_put(_Dest, _Iosbase, _Fill, _Pt,
|
|
_Specifier, _Qualifier); // convert a single field
|
|
}
|
|
return (_Dest);
|
|
}
|
|
|
|
_OutIt put(_OutIt _Dest, ios_base& _Iosbase, _Elem _Fill, const tm *_Pt,
|
|
char _Specifier, char _Modifier = 0) const
|
|
{ // put formatted time from _Pt to _Dest for _Specifier/_Modifier
|
|
return (do_put(_Dest, _Iosbase, _Fill, _Pt, _Specifier, _Modifier));
|
|
}
|
|
|
|
static locale::id id; // unique facet id
|
|
|
|
explicit time_put(size_t _Refs = 0)
|
|
: locale::facet(_Refs)
|
|
{ // construct from current locale
|
|
_Init(_Locinfo());
|
|
}
|
|
|
|
time_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 time_put<_Elem, _OutIt>;
|
|
return (_X_TIME);
|
|
}
|
|
|
|
_PROTECTED:
|
|
virtual ~time_put()
|
|
{ // destroy the object
|
|
}
|
|
|
|
protected:
|
|
void _Init(const _Locinfo& _Lobj)
|
|
{ // initialize from _Lobj
|
|
_Tnames = _Lobj._Gettnames();
|
|
}
|
|
|
|
virtual _OutIt do_put(_OutIt _Dest, ios_base&, _Elem, const tm *_Pt,
|
|
char _Specifier, char _Modifier = 0) const
|
|
{ // put formatted time from _Pt to _Dest for [_Fmtfirst, _Fmtlast)
|
|
char _Fmt[5] = "!%x\0"; // '!' for nonzero count, null for modifier
|
|
size_t _Count, _Num;
|
|
string _Str;
|
|
|
|
if (_Modifier == (_Elem)0)
|
|
_Fmt[2] = _Specifier;
|
|
else
|
|
_Fmt[2] = _Modifier, _Fmt[3] = _Specifier;
|
|
|
|
for (_Num = 16; ; _Num *= 2)
|
|
{ // convert into ever larger string buffer until success
|
|
_Str.append(_Num, '\0');
|
|
if (0 < (_Count = _Strftime(&*_Str.begin(), _Str.size(),
|
|
_Fmt, _Pt, _Tnames._Getptr())))
|
|
break;
|
|
}
|
|
|
|
for (string::const_iterator _Snext = _Str.begin();
|
|
0 < --_Count; ++_Dest)
|
|
*_Dest = _WIDEN(_Elem, *++_Snext); // skip literal '!'
|
|
return (_Dest);
|
|
}
|
|
|
|
private:
|
|
_Locinfo::_Timevec _Tnames; // locale-specific stuff for _Strftime
|
|
};
|
|
|
|
// STATIC time_put::id OBJECT
|
|
template<class _Elem,
|
|
class _OutIt>
|
|
locale::id time_put<_Elem, _OutIt>::id;
|
|
|
|
// CLASS time_put<wchar_t>
|
|
template<> class _CRTIMP2 time_put<wchar_t,
|
|
ostreambuf_iterator<wchar_t, char_traits<wchar_t> > >
|
|
: public locale::facet
|
|
{ // facet for converting encoded times to wchar_t text
|
|
typedef wchar_t _Elem;
|
|
typedef ostreambuf_iterator<wchar_t, char_traits<wchar_t> > _OutIt;
|
|
|
|
public:
|
|
typedef _Elem char_type;
|
|
typedef _OutIt iter_type;
|
|
|
|
_OutIt put(_OutIt _Dest, ios_base& _Iosbase, _Elem _Fill, const tm *_Pt,
|
|
const _Elem *_Fmtfirst, const _Elem *_Fmtlast) const
|
|
{ // put formatted time from _Pt to _Dest for [_Fmtfirst, _Fmtlast)
|
|
const _Elem _Percent = _WIDEN(_Elem, '%');
|
|
|
|
for (; _Fmtfirst != _Fmtlast; ++_Fmtfirst)
|
|
if (*_Fmtfirst != _Percent)
|
|
*_Dest++ = *_Fmtfirst; // copy literal element
|
|
else if (++_Fmtfirst == _Fmtlast)
|
|
{ // treat trailing % as %%
|
|
*_Dest++ = _Percent;
|
|
break;
|
|
}
|
|
else
|
|
{ // get specifier after %
|
|
char _Specifier = _NARROW(_Elem, *_Fmtfirst);
|
|
char _Qualifier = '\0';
|
|
|
|
if (_Specifier != 'E' && _Specifier != 'O'
|
|
&& _Specifier != 'Q' && _Specifier != '#')
|
|
; // not [E0Q#] qualifier, treat as specifier
|
|
else if (++_Fmtfirst == _Fmtlast)
|
|
{ // no specifier, copy %[E0Q#] as literal elements
|
|
*_Dest++ = _Percent, *_Dest++ = _Specifier;
|
|
break;
|
|
}
|
|
else
|
|
{ // save both qualifier and specifier
|
|
_Qualifier = _Specifier;
|
|
_Specifier = _NARROW(_Elem, *_Fmtfirst);
|
|
}
|
|
|
|
_Dest = do_put(_Dest, _Iosbase, _Fill, _Pt,
|
|
_Specifier, _Qualifier); // convert a single field
|
|
}
|
|
return (_Dest);
|
|
}
|
|
|
|
_OutIt put(_OutIt _Dest, ios_base& _Iosbase, _Elem _Fill, const tm *_Pt,
|
|
char _Specifier, char _Modifier = 0) const
|
|
{ // put formatted time from _Pt to _Dest for _Specifier/_Modifier
|
|
return (do_put(_Dest, _Iosbase, _Fill, _Pt, _Specifier, _Modifier));
|
|
}
|
|
|
|
static locale::id id; // unique facet id
|
|
|
|
explicit time_put(size_t _Refs = 0)
|
|
: locale::facet(_Refs)
|
|
{ // construct from current locale
|
|
_Init(_Locinfo());
|
|
}
|
|
|
|
time_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 time_put<_Elem, _OutIt>;
|
|
return (_X_TIME);
|
|
}
|
|
|
|
_PROTECTED:
|
|
virtual ~time_put()
|
|
{ // destroy the object
|
|
}
|
|
|
|
protected:
|
|
void _Init(const _Locinfo& _Lobj)
|
|
{ // initialize from _Lobj
|
|
_Tnames = _Lobj._Gettnames();
|
|
_Cvt = _Lobj._Getcvt();
|
|
}
|
|
|
|
virtual _OutIt do_put(_OutIt _Dest, ios_base&, _Elem, const tm *_Pt,
|
|
char _Specifier, char _Modifier = 0) const
|
|
{ // put formatted time from _Pt to _Dest for [_Fmtfirst, _Fmtlast)
|
|
char _Fmt[5] = "!%x\0"; // '!' for nonzero count, null for modifier
|
|
size_t _Count, _Num;
|
|
string _Str;
|
|
|
|
if (_Modifier == (_Elem)0)
|
|
_Fmt[2] = _Specifier;
|
|
else
|
|
_Fmt[2] = _Modifier, _Fmt[3] = _Specifier;
|
|
|
|
for (_Num = 16; ; _Num *= 2)
|
|
{ // convert into ever larger string buffer until success
|
|
_Str.append(_Num, '\0');
|
|
if (0 < (_Count = _Strftime(&*_Str.begin(), _Str.size(),
|
|
_Fmt, _Pt, _Tnames._Getptr())))
|
|
break;
|
|
}
|
|
|
|
_Mbstinit(_Mbst);
|
|
--_Count;
|
|
for (string::const_iterator _Snext = _Str.begin() + 1;
|
|
0 < _Count; ++_Dest)
|
|
{ // convert to wchar_t, skip literal '!'
|
|
wchar_t _Wc;
|
|
int _Bytes;
|
|
|
|
switch (_Bytes = _Mbrtowc(&_Wc, &*_Snext, _Count, &_Mbst, &_Cvt))
|
|
{
|
|
case -2: // partial conversion
|
|
case -1: // failed conversion
|
|
return (_Dest);
|
|
|
|
case 0: // converted null character
|
|
_Bytes = (int)::strlen(&*_Snext) + 1;
|
|
// fall through
|
|
|
|
default: // converted _Bytes bytes to a wchar_t
|
|
*_Dest = _Wc;
|
|
_Snext += _Bytes, _Count -= _Bytes;
|
|
}
|
|
}
|
|
return (_Dest);
|
|
}
|
|
|
|
private:
|
|
_Locinfo::_Timevec _Tnames; // locale-specific stuff for _Strftime
|
|
_Locinfo::_Cvtvec _Cvt; // conversion information
|
|
};
|
|
#ifdef _CRTBLD_NATIVE_WCHAR_T
|
|
// CLASS time_put<unsigned short>
|
|
template<> class _CRTIMP2 time_put<unsigned short,
|
|
ostreambuf_iterator<unsigned short, char_traits<unsigned short> > >
|
|
: public locale::facet
|
|
{ // facet for converting encoded times to unsigned short text
|
|
typedef unsigned short _Elem;
|
|
typedef ostreambuf_iterator<unsigned short, char_traits<unsigned short> > _OutIt;
|
|
|
|
public:
|
|
typedef _Elem char_type;
|
|
typedef _OutIt iter_type;
|
|
|
|
_OutIt put(_OutIt _Dest, ios_base& _Iosbase, _Elem _Fill, const tm *_Pt,
|
|
const _Elem *_Fmtfirst, const _Elem *_Fmtlast) const
|
|
{ // put formatted time from _Pt to _Dest for [_Fmtfirst, _Fmtlast)
|
|
const _Elem _Percent = _WIDEN(_Elem, '%');
|
|
|
|
for (; _Fmtfirst != _Fmtlast; ++_Fmtfirst)
|
|
if (*_Fmtfirst != _Percent)
|
|
*_Dest++ = *_Fmtfirst; // copy literal element
|
|
else if (++_Fmtfirst == _Fmtlast)
|
|
{ // treat trailing % as %%
|
|
*_Dest++ = _Percent;
|
|
break;
|
|
}
|
|
else
|
|
{ // get specifier after %
|
|
char _Specifier = _NARROW(_Elem, *_Fmtfirst);
|
|
char _Qualifier = '\0';
|
|
|
|
if (_Specifier != 'E' && _Specifier != 'O'
|
|
&& _Specifier != 'Q' && _Specifier != '#')
|
|
; // not [E0Q#] qualifier, treat as specifier
|
|
else if (++_Fmtfirst == _Fmtlast)
|
|
{ // no specifier, copy %[E0Q#] as literal elements
|
|
*_Dest++ = _Percent, *_Dest++ = _Specifier;
|
|
break;
|
|
}
|
|
else
|
|
{ // save both qualifier and specifier
|
|
_Qualifier = _Specifier;
|
|
_Specifier = _NARROW(_Elem, *_Fmtfirst);
|
|
}
|
|
|
|
_Dest = do_put(_Dest, _Iosbase, _Fill, _Pt,
|
|
_Specifier, _Qualifier); // convert a single field
|
|
}
|
|
return (_Dest);
|
|
}
|
|
|
|
_OutIt put(_OutIt _Dest, ios_base& _Iosbase, _Elem _Fill, const tm *_Pt,
|
|
char _Specifier, char _Modifier = 0) const
|
|
{ // put formatted time from _Pt to _Dest for _Specifier/_Modifier
|
|
return (do_put(_Dest, _Iosbase, _Fill, _Pt, _Specifier, _Modifier));
|
|
}
|
|
|
|
static locale::id id; // unique facet id
|
|
|
|
explicit time_put(size_t _Refs = 0)
|
|
: locale::facet(_Refs)
|
|
{ // construct from current locale
|
|
_Init(_Locinfo());
|
|
}
|
|
|
|
time_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 time_put<_Elem, _OutIt>;
|
|
return (_X_TIME);
|
|
}
|
|
|
|
_PROTECTED:
|
|
virtual ~time_put()
|
|
{ // destroy the object
|
|
}
|
|
|
|
protected:
|
|
void _Init(const _Locinfo& _Lobj)
|
|
{ // initialize from _Lobj
|
|
_Tnames = _Lobj._Gettnames();
|
|
_Cvt = _Lobj._Getcvt();
|
|
}
|
|
|
|
virtual _OutIt do_put(_OutIt _Dest, ios_base&, _Elem, const tm *_Pt,
|
|
char _Specifier, char _Modifier = 0) const
|
|
{ // put formatted time from _Pt to _Dest for [_Fmtfirst, _Fmtlast)
|
|
char _Fmt[5] = "!%x\0"; // '!' for nonzero count, null for modifier
|
|
size_t _Count, _Num;
|
|
string _Str;
|
|
|
|
if (_Modifier == (_Elem)0)
|
|
_Fmt[2] = _Specifier;
|
|
else
|
|
_Fmt[2] = _Modifier, _Fmt[3] = _Specifier;
|
|
|
|
for (_Num = 16; ; _Num *= 2)
|
|
{ // convert into ever larger string buffer until success
|
|
_Str.append(_Num, '\0');
|
|
if (0 < (_Count = _Strftime(&*_Str.begin(), _Str.size(),
|
|
_Fmt, _Pt, _Tnames._Getptr())))
|
|
break;
|
|
}
|
|
|
|
_Mbstinit(_Mbst);
|
|
--_Count;
|
|
for (string::const_iterator _Snext = _Str.begin() + 1;
|
|
0 < _Count; ++_Dest)
|
|
{ // convert to wchar_t, skip literal '!'
|
|
wchar_t _Wc;
|
|
int _Bytes;
|
|
|
|
switch (_Bytes = _Mbrtowc(&_Wc, &*_Snext, _Count, &_Mbst, &_Cvt))
|
|
{
|
|
case -2: // partial conversion
|
|
case -1: // failed conversion
|
|
return (_Dest);
|
|
|
|
case 0: // converted null character
|
|
_Bytes = (int)::strlen(&*_Snext) + 1;
|
|
// fall through
|
|
|
|
default: // converted _Bytes bytes to a wchar_t
|
|
*_Dest = _Wc;
|
|
_Snext += _Bytes, _Count -= _Bytes;
|
|
}
|
|
}
|
|
return (_Dest);
|
|
}
|
|
|
|
private:
|
|
_Locinfo::_Timevec _Tnames; // locale-specific stuff for _Strftime
|
|
_Locinfo::_Cvtvec _Cvt; // conversion information
|
|
};
|
|
#endif
|
|
|
|
// TEMPLATE CLASS time_put_byname
|
|
template<class _Elem,
|
|
class _OutIt = ostreambuf_iterator<_Elem, char_traits<_Elem> > >
|
|
class time_put_byname
|
|
: public time_put<_Elem, _OutIt>
|
|
{ // time_put for named locale
|
|
public:
|
|
explicit time_put_byname(const char *_Locname, size_t _Refs = 0)
|
|
: time_put<_Elem, _OutIt>(_Locinfo(_Locname), _Refs)
|
|
{ // construct for named locale
|
|
}
|
|
|
|
_PROTECTED:
|
|
virtual ~time_put_byname()
|
|
{ // destroy the object
|
|
}
|
|
};
|
|
|
|
#ifdef _DLL_CPPLIB
|
|
#ifdef __FORCE_INSTANCE
|
|
template class _CRTIMP2 time_get<char,
|
|
istreambuf_iterator<char, char_traits<char> > >;
|
|
template class _CRTIMP2 time_get<wchar_t,
|
|
istreambuf_iterator<wchar_t, char_traits<wchar_t> > >;
|
|
#ifdef _CRTBLD_NATIVE_WCHAR_T
|
|
template class _CRTIMP2 time_get<unsigned short,
|
|
istreambuf_iterator<unsigned short, char_traits<unsigned short> > >;
|
|
#endif
|
|
template class _CRTIMP2 time_put<char,
|
|
ostreambuf_iterator<char, char_traits<char> > >;
|
|
template class _CRTIMP2 time_put<wchar_t,
|
|
ostreambuf_iterator<wchar_t, char_traits<wchar_t> > >;
|
|
#ifdef _CRTBLD_NATIVE_WCHAR_T
|
|
template class _CRTIMP2 time_put<unsigned short,
|
|
ostreambuf_iterator<unsigned short, char_traits<unsigned short> > >;
|
|
#endif
|
|
#endif // __FORCE_INSTANCE
|
|
#endif // _DLL_CPPLIB
|
|
_STD_END
|
|
#pragma warning(pop)
|
|
#pragma pack(pop)
|
|
|
|
#endif /* _XLOCTIME_ */
|
|
|
|
/*
|
|
* Copyright (c) 1992-2001 by P.J. Plauger. ALL RIGHTS RESERVED.
|
|
* Consult your license regarding permissions and restrictions.
|
|
V3.10:0009 */
|