// xloctime internal header (from ) #pragma once #ifndef _XLOCTIME_ #define _XLOCTIME_ #include #include #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 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 locale::id time_get<_Elem, _InIt>::id; // TEMPLATE CLASS time_get_byname template > > 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 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 locale::id time_put<_Elem, _OutIt>::id; // CLASS time_put template<> class _CRTIMP2 time_put > > : public locale::facet { // facet for converting encoded times to wchar_t text typedef wchar_t _Elem; typedef ostreambuf_iterator > _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 }; // TEMPLATE CLASS time_put_byname template > > 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 template class _CRTIMP2 time_get > >; template class _CRTIMP2 time_get > >; template class _CRTIMP2 time_put > >; template class _CRTIMP2 time_put > >; #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 */