Source code of Windows XP (NT5)
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

  1. // xloctime internal header (from <locale>)
  2. #pragma once
  3. #ifndef _XLOCTIME_
  4. #define _XLOCTIME_
  5. #include <ctime>
  6. #include <xiosbase>
  7. #pragma pack(push,8)
  8. #pragma warning(push,3)
  9. _STD_BEGIN
  10. // STRUCT time_base
  11. struct _CRTIMP2 time_base
  12. : public locale::facet
  13. { // base class for time_get
  14. enum dateorder
  15. { // constants for different orders of date components
  16. no_order, dmy, mdy, ymd, ydm};
  17. time_base(size_t _Refs = 0)
  18. : locale::facet(_Refs)
  19. { // default constructor
  20. }
  21. };
  22. // TEMPLATE CLASS time_get
  23. template<class _Elem,
  24. class _InIt = istreambuf_iterator<_Elem, char_traits<_Elem> > >
  25. class time_get
  26. : public time_base
  27. { // facet for converting text to encoded times
  28. public:
  29. typedef _Elem char_type;
  30. typedef _InIt iter_type;
  31. static locale::id id; // unique facet id
  32. dateorder date_order() const
  33. { // return date order code
  34. return (do_date_order());
  35. }
  36. _InIt get_time(_InIt _First, _InIt _Last, ios_base& _Iosbase,
  37. ios_base::iostate& _State, tm *_Pt) const
  38. { // get time of day from [_First, _Last) into _Pt
  39. return (do_get_time(_First, _Last, _Iosbase, _State, _Pt));
  40. }
  41. _InIt get_date(_InIt _First, _InIt _Last, ios_base& _Iosbase,
  42. ios_base::iostate& _State, tm *_Pt) const
  43. { // get date from [_First, _Last) into _Pt
  44. return (do_get_date(_First, _Last, _Iosbase, _State, _Pt));
  45. }
  46. _InIt get_weekday(_InIt _First, _InIt _Last, ios_base& _Iosbase,
  47. ios_base::iostate& _State, tm *_Pt) const
  48. { // get weekday from [_First, _Last) into _Pt
  49. return (do_get_weekday(_First, _Last, _Iosbase, _State, _Pt));
  50. }
  51. _InIt get_monthname(_InIt _First, _InIt _Last, ios_base& _Iosbase,
  52. ios_base::iostate& _State, tm *_Pt) const
  53. { // get month from [_First, _Last) into _Pt
  54. return (do_get_monthname(_First, _Last, _Iosbase, _State, _Pt));
  55. }
  56. _InIt get_year(_InIt _First, _InIt _Last, ios_base& _Iosbase,
  57. ios_base::iostate& _State, tm *_Pt) const
  58. { // get year from [_First, _Last) into _Pt
  59. return (do_get_year(_First, _Last, _Iosbase, _State, _Pt));
  60. }
  61. explicit time_get(size_t _Refs = 0)
  62. : time_base(_Refs)
  63. { // construct from current locale
  64. _Init(_Locinfo());
  65. }
  66. time_get(const _Locinfo& _Lobj, size_t _Refs = 0)
  67. : time_base(_Refs)
  68. { // construct from specified locale
  69. _Init(_Lobj);
  70. }
  71. static size_t __cdecl _Getcat(const locale::facet **_Ppf = 0)
  72. { // return locale category mask and construct standard facet
  73. if (_Ppf != 0 && *_Ppf == 0)
  74. *_Ppf = _NEW_CRT time_get<_Elem, _InIt>;
  75. return (_X_TIME);
  76. }
  77. _PROTECTED:
  78. virtual ~time_get()
  79. { // destroy the object
  80. _Tidy();
  81. }
  82. protected:
  83. void _Init(const _Locinfo& _Lobj)
  84. { // initialize from _Lobj
  85. _Days = 0;
  86. _Months = 0;
  87. _TRY_BEGIN
  88. _Days = _MAKLOCSTR(_Elem, _Lobj._Getdays(), _Lobj._Getcvt());
  89. _Months = _MAKLOCSTR(_Elem, _Lobj._Getmonths(), _Lobj._Getcvt());
  90. _Dateorder = (dateorder)_Lobj._Getdateorder();
  91. _CATCH_ALL
  92. _Tidy();
  93. _RERAISE;
  94. _CATCH_END
  95. }
  96. virtual dateorder do_date_order() const
  97. { // return date order code
  98. return (_Dateorder);
  99. }
  100. virtual _InIt do_get_time(_InIt _First, _InIt _Last, ios_base&,
  101. ios_base::iostate& _State, tm *_Pt) const
  102. { // get time of day from [_First, _Last) into _Pt
  103. const _Elem _Colon = _WIDEN(_Elem, ':');
  104. _State |= _Getint(_First, _Last, 0, 23, _Pt->tm_hour);
  105. if (_State != ios_base::goodbit || *_First != _Colon)
  106. _State |= ios_base::failbit; // hour field is bad
  107. else
  108. _State |= _Getint(++_First, _Last, 0, 59, _Pt->tm_min);
  109. if (_State != ios_base::goodbit || *_First != _Colon)
  110. _State |= ios_base::failbit; // min field is bad
  111. else
  112. _State |= _Getint(++_First, _Last, 0, 59, _Pt->tm_sec);
  113. return (_First);
  114. }
  115. virtual _InIt do_get_date(_InIt _First, _InIt _Last, ios_base& _Iosbase,
  116. ios_base::iostate& _State, tm *_Pt) const
  117. { // get date from [_First, _Last) into _Pt
  118. const _Elem _E0 = _WIDEN(_Elem, '0');
  119. const _Elem _E9 = _WIDEN(_Elem, '9');
  120. const _Elem _Colon = _WIDEN(_Elem, ':');
  121. const _Elem _Comma = _WIDEN(_Elem, ',');
  122. const _Elem _Slash = _WIDEN(_Elem, '/');
  123. const _Elem _Space = _WIDEN(_Elem, ' ');
  124. dateorder _Dorder = date_order();
  125. if (_Dorder == no_order)
  126. _Dorder = mdy;
  127. if (*_First < _E0 || _E9 < *_First)
  128. { // begins with month name, assume mdy
  129. _First = get_monthname(_First, _Last, _Iosbase, _State, _Pt);
  130. _Dorder = mdy;
  131. }
  132. else if (_Dorder == mdy)
  133. { // get month number
  134. _State |= _Getint(_First, _Last, 1, 12, _Pt->tm_mon);
  135. --_Pt->tm_mon;
  136. }
  137. else if (_Dorder == dmy)
  138. _State |= _Getint(_First, _Last, 1, 31, _Pt->tm_mday);
  139. else // ymd or ydm
  140. _First = get_year(_First, _Last, _Iosbase, _State, _Pt);
  141. if (_State == ios_base::goodbit)
  142. { // skip spaces [:,/] spaces
  143. while (*_First == _Space)
  144. ++_First;
  145. if (*_First == _Colon || *_First == _Comma || *_First == _Slash)
  146. ++_First;
  147. while (*_First == _Space)
  148. ++_First;
  149. }
  150. if (_State != ios_base::goodbit)
  151. ;
  152. else if (*_First < _E0 || _E9 < *_First)
  153. if (_Dorder == mdy)
  154. _State |= ios_base::failbit; // error, month already seen
  155. else
  156. { // month name is second, like it or not
  157. _First = get_monthname(_First, _Last, _Iosbase, _State, _Pt);
  158. if (_Dorder == ydm)
  159. _Dorder = ymd;
  160. }
  161. else if (_Dorder == dmy || _Dorder == ymd)
  162. { // get month number
  163. _State |= _Getint(_First, _Last, 1, 12, _Pt->tm_mon);
  164. --_Pt->tm_mon;
  165. }
  166. else
  167. _State |= _Getint(_First, _Last, 1, 31, _Pt->tm_mday);
  168. if (_State == ios_base::goodbit)
  169. { // skip spaces [:,/] spaces
  170. while (*_First == _Space)
  171. ++_First;
  172. if (*_First == _Colon || *_First == _Comma || *_First == _Slash)
  173. ++_First;
  174. while (*_First == _Space)
  175. ++_First;
  176. }
  177. if (_State != ios_base::goodbit)
  178. ;
  179. else if (*_First < _E0 || _E9 < *_First)
  180. if (_Dorder != ydm)
  181. _State |= ios_base::failbit; // error, month out of place
  182. else
  183. _First = get_monthname(_First, _Last, _Iosbase, _State, _Pt);
  184. else if (_Dorder == ydm)
  185. { // get month number
  186. _State |= _Getint(_First, _Last, 1, 12, _Pt->tm_mon);
  187. --_Pt->tm_mon;
  188. }
  189. else if (_Dorder == ymd)
  190. _State |= _Getint(_First, _Last, 1, 31, _Pt->tm_mday);
  191. else // mdy or dmy
  192. _First = get_year(_First, _Last, _Iosbase, _State, _Pt);
  193. if (_First == _Last)
  194. _State |= ios_base::eofbit;
  195. return (_First);
  196. }
  197. virtual _InIt do_get_weekday(_InIt _First, _InIt _Last, ios_base&,
  198. ios_base::iostate& _State, tm *_Pt) const
  199. { // get weekday from [_First, _Last) into _Pt
  200. int _Num = _Getloctxt(_First, _Last, (size_t)0, _Days);
  201. if (_Num < 0)
  202. _State |= ios_base::failbit;
  203. else
  204. _Pt->tm_wday = _Num >> 1; // set wday
  205. return (_First);
  206. }
  207. virtual _InIt do_get_monthname(_InIt _First, _InIt _Last, ios_base&,
  208. ios_base::iostate& _State, tm *_Pt) const
  209. { // get month from [_First, _Last) into _Pt
  210. int _Num = _Getloctxt(_First, _Last, (size_t)0, _Months);
  211. if (_Num < 0)
  212. _State |= ios_base::failbit;
  213. else
  214. _Pt->tm_mon = _Num >> 1; // set mon
  215. return (_First);
  216. }
  217. virtual _InIt do_get_year(_InIt _First, _InIt _Last, ios_base&,
  218. ios_base::iostate& _State, tm *_Pt) const
  219. { // get year from [_First, _Last) into _Pt
  220. int _Ans = 0;
  221. _State |= _Getint(_First, _Last, 0, 2035, _Ans);
  222. if (_State & ios_base::failbit)
  223. ;
  224. else if (1900 <= _Ans)
  225. _Ans -= 1900; // [1900, ...) as is
  226. else if (2035 - 1900 < _Ans)
  227. _State |= ios_base::failbit;
  228. if (!(_State & ios_base::failbit))
  229. _Pt->tm_year = _Ans; // set year
  230. return (_First);
  231. }
  232. private:
  233. static ios_base::iostate __cdecl _Getint(_InIt& _First, _InIt& _Last,
  234. int _Lo, int _Hi, int& _Val)
  235. { // get integer in range [_Lo, _Hi] from [_First, _Last)
  236. char _Ac[_MAX_INT_DIG], *_Ep;
  237. char *_Ptr = _Ac;
  238. if (_First == _Last)
  239. ;
  240. else if (*_First == _WIDEN(_Elem, '+'))
  241. *_Ptr++ = '+', ++_First; // copy plus sign
  242. else if (*_First == _WIDEN(_Elem, '-'))
  243. *_Ptr++ = '-', ++_First; // copy minus sign
  244. bool _Seendigit = false;
  245. while (_First != _Last && *_First == _WIDEN(_Elem, '0'))
  246. _Seendigit = true, ++_First; // strip leading zeros
  247. if (_Seendigit)
  248. *_Ptr++ = '0'; // replace one or more with single zero
  249. for (char *const _Pe = &_Ac[_MAX_INT_DIG - 1]; _First != _Last
  250. && '0' <= (*_Ptr = _NARROW(_Elem, *_First)) && *_Ptr <= '9';
  251. _Seendigit = true, ++_First) // copy digits
  252. if (_Ptr < _Pe)
  253. ++_Ptr; // drop trailing digits if already too large
  254. if (!_Seendigit)
  255. _Ptr = _Ac;
  256. *_Ptr = '\0';
  257. errno = 0;
  258. const long _Ans = strtol(_Ac, &_Ep, 10);
  259. ios_base::iostate _State = ios_base::goodbit;
  260. if (_First == _Last)
  261. _State |= ios_base::eofbit;
  262. if (_Ep == _Ac || errno != 0 || _Ans < _Lo || _Hi < _Ans)
  263. _State |= ios_base::failbit; // bad conversion
  264. else
  265. _Val = _Ans; // store valid result
  266. return (_State);
  267. }
  268. void _Tidy()
  269. { // free all storage
  270. _DELETE_CRT_VEC((void *)_Days);
  271. _DELETE_CRT_VEC((void *)_Months);
  272. }
  273. const _Elem *_Days; // ":Sun:Sunday:Mon:Monday..." for example
  274. const _Elem *_Months; // "Jan:January:Feb:February..." for example
  275. dateorder _Dateorder;
  276. };
  277. // STATIC time_get::id OBJECT
  278. template<class _Elem,
  279. class _InIt>
  280. locale::id time_get<_Elem, _InIt>::id;
  281. // TEMPLATE CLASS time_get_byname
  282. template<class _Elem,
  283. class _InIt = istreambuf_iterator<_Elem, char_traits<_Elem> > >
  284. class time_get_byname
  285. : public time_get<_Elem, _InIt>
  286. { // time_get for named locale
  287. public:
  288. explicit time_get_byname(const char *_Locname, size_t _Refs = 0)
  289. : time_get<_Elem, _InIt>(_Locinfo(_Locname), _Refs)
  290. { // construct for named locale
  291. }
  292. _PROTECTED:
  293. virtual ~time_get_byname()
  294. { // destroy the object
  295. }
  296. };
  297. // TEMPLATE CLASS time_put
  298. template<class _Elem,
  299. class _OutIt = ostreambuf_iterator<_Elem, char_traits<_Elem> > >
  300. class time_put
  301. : public locale::facet
  302. { // facet for converting encoded times to text
  303. public:
  304. typedef _Elem char_type;
  305. typedef _OutIt iter_type;
  306. _OutIt put(_OutIt _Dest, ios_base& _Iosbase, _Elem _Fill, const tm *_Pt,
  307. const _Elem *_Fmtfirst, const _Elem *_Fmtlast) const
  308. { // put formatted time from _Pt to _Dest for [_Fmtfirst, _Fmtlast)
  309. const _Elem _Percent = _WIDEN(_Elem, '%');
  310. for (; _Fmtfirst != _Fmtlast; ++_Fmtfirst)
  311. if (*_Fmtfirst != _Percent)
  312. *_Dest++ = *_Fmtfirst; // copy literal element
  313. else if (++_Fmtfirst == _Fmtlast)
  314. { // treat trailing % as %%
  315. *_Dest++ = _Percent;
  316. break;
  317. }
  318. else
  319. { // get specifier after %
  320. char _Specifier = _NARROW(_Elem, *_Fmtfirst);
  321. char _Qualifier = '\0';
  322. if (_Specifier != 'E' && _Specifier != 'O'
  323. && _Specifier != 'Q' && _Specifier != '#')
  324. ; // not [E0Q#] qualifier, treat as specifier
  325. else if (++_Fmtfirst == _Fmtlast)
  326. { // no specifier, copy %[E0Q#] as literal elements
  327. *_Dest++ = _Percent, *_Dest++ = _Specifier;
  328. break;
  329. }
  330. else
  331. { // save both qualifier and specifier
  332. _Qualifier = _Specifier;
  333. _Specifier = _NARROW(_Elem, *_Fmtfirst);
  334. }
  335. _Dest = do_put(_Dest, _Iosbase, _Fill, _Pt,
  336. _Specifier, _Qualifier); // convert a single field
  337. }
  338. return (_Dest);
  339. }
  340. _OutIt put(_OutIt _Dest, ios_base& _Iosbase, _Elem _Fill, const tm *_Pt,
  341. char _Specifier, char _Modifier = 0) const
  342. { // put formatted time from _Pt to _Dest for _Specifier/_Modifier
  343. return (do_put(_Dest, _Iosbase, _Fill, _Pt, _Specifier, _Modifier));
  344. }
  345. static locale::id id; // unique facet id
  346. explicit time_put(size_t _Refs = 0)
  347. : locale::facet(_Refs)
  348. { // construct from current locale
  349. _Init(_Locinfo());
  350. }
  351. time_put(const _Locinfo& _Lobj, size_t _Refs = 0)
  352. : locale::facet(_Refs)
  353. { // construct from specified locale
  354. _Init(_Lobj);
  355. }
  356. static size_t __cdecl _Getcat(const locale::facet **_Ppf = 0)
  357. { // return locale category mask and construct standard facet
  358. if (_Ppf != 0 && *_Ppf == 0)
  359. *_Ppf = _NEW_CRT time_put<_Elem, _OutIt>;
  360. return (_X_TIME);
  361. }
  362. _PROTECTED:
  363. virtual ~time_put()
  364. { // destroy the object
  365. }
  366. protected:
  367. void _Init(const _Locinfo& _Lobj)
  368. { // initialize from _Lobj
  369. _Tnames = _Lobj._Gettnames();
  370. }
  371. virtual _OutIt do_put(_OutIt _Dest, ios_base&, _Elem, const tm *_Pt,
  372. char _Specifier, char _Modifier = 0) const
  373. { // put formatted time from _Pt to _Dest for [_Fmtfirst, _Fmtlast)
  374. char _Fmt[5] = "!%x\0"; // '!' for nonzero count, null for modifier
  375. size_t _Count, _Num;
  376. string _Str;
  377. if (_Modifier == (_Elem)0)
  378. _Fmt[2] = _Specifier;
  379. else
  380. _Fmt[2] = _Modifier, _Fmt[3] = _Specifier;
  381. for (_Num = 16; ; _Num *= 2)
  382. { // convert into ever larger string buffer until success
  383. _Str.append(_Num, '\0');
  384. if (0 < (_Count = _Strftime(&*_Str.begin(), _Str.size(),
  385. _Fmt, _Pt, _Tnames._Getptr())))
  386. break;
  387. }
  388. for (string::const_iterator _Snext = _Str.begin();
  389. 0 < --_Count; ++_Dest)
  390. *_Dest = _WIDEN(_Elem, *++_Snext); // skip literal '!'
  391. return (_Dest);
  392. }
  393. private:
  394. _Locinfo::_Timevec _Tnames; // locale-specific stuff for _Strftime
  395. };
  396. // STATIC time_put::id OBJECT
  397. template<class _Elem,
  398. class _OutIt>
  399. locale::id time_put<_Elem, _OutIt>::id;
  400. // CLASS time_put<wchar_t>
  401. template<> class _CRTIMP2 time_put<wchar_t,
  402. ostreambuf_iterator<wchar_t, char_traits<wchar_t> > >
  403. : public locale::facet
  404. { // facet for converting encoded times to wchar_t text
  405. typedef wchar_t _Elem;
  406. typedef ostreambuf_iterator<wchar_t, char_traits<wchar_t> > _OutIt;
  407. public:
  408. typedef _Elem char_type;
  409. typedef _OutIt iter_type;
  410. _OutIt put(_OutIt _Dest, ios_base& _Iosbase, _Elem _Fill, const tm *_Pt,
  411. const _Elem *_Fmtfirst, const _Elem *_Fmtlast) const
  412. { // put formatted time from _Pt to _Dest for [_Fmtfirst, _Fmtlast)
  413. const _Elem _Percent = _WIDEN(_Elem, '%');
  414. for (; _Fmtfirst != _Fmtlast; ++_Fmtfirst)
  415. if (*_Fmtfirst != _Percent)
  416. *_Dest++ = *_Fmtfirst; // copy literal element
  417. else if (++_Fmtfirst == _Fmtlast)
  418. { // treat trailing % as %%
  419. *_Dest++ = _Percent;
  420. break;
  421. }
  422. else
  423. { // get specifier after %
  424. char _Specifier = _NARROW(_Elem, *_Fmtfirst);
  425. char _Qualifier = '\0';
  426. if (_Specifier != 'E' && _Specifier != 'O'
  427. && _Specifier != 'Q' && _Specifier != '#')
  428. ; // not [E0Q#] qualifier, treat as specifier
  429. else if (++_Fmtfirst == _Fmtlast)
  430. { // no specifier, copy %[E0Q#] as literal elements
  431. *_Dest++ = _Percent, *_Dest++ = _Specifier;
  432. break;
  433. }
  434. else
  435. { // save both qualifier and specifier
  436. _Qualifier = _Specifier;
  437. _Specifier = _NARROW(_Elem, *_Fmtfirst);
  438. }
  439. _Dest = do_put(_Dest, _Iosbase, _Fill, _Pt,
  440. _Specifier, _Qualifier); // convert a single field
  441. }
  442. return (_Dest);
  443. }
  444. _OutIt put(_OutIt _Dest, ios_base& _Iosbase, _Elem _Fill, const tm *_Pt,
  445. char _Specifier, char _Modifier = 0) const
  446. { // put formatted time from _Pt to _Dest for _Specifier/_Modifier
  447. return (do_put(_Dest, _Iosbase, _Fill, _Pt, _Specifier, _Modifier));
  448. }
  449. static locale::id id; // unique facet id
  450. explicit time_put(size_t _Refs = 0)
  451. : locale::facet(_Refs)
  452. { // construct from current locale
  453. _Init(_Locinfo());
  454. }
  455. time_put(const _Locinfo& _Lobj, size_t _Refs = 0)
  456. : locale::facet(_Refs)
  457. { // construct from specified locale
  458. _Init(_Lobj);
  459. }
  460. static size_t __cdecl _Getcat(const locale::facet **_Ppf = 0)
  461. { // return locale category mask and construct standard facet
  462. if (_Ppf != 0 && *_Ppf == 0)
  463. *_Ppf = _NEW_CRT time_put<_Elem, _OutIt>;
  464. return (_X_TIME);
  465. }
  466. _PROTECTED:
  467. virtual ~time_put()
  468. { // destroy the object
  469. }
  470. protected:
  471. void _Init(const _Locinfo& _Lobj)
  472. { // initialize from _Lobj
  473. _Tnames = _Lobj._Gettnames();
  474. _Cvt = _Lobj._Getcvt();
  475. }
  476. virtual _OutIt do_put(_OutIt _Dest, ios_base&, _Elem, const tm *_Pt,
  477. char _Specifier, char _Modifier = 0) const
  478. { // put formatted time from _Pt to _Dest for [_Fmtfirst, _Fmtlast)
  479. char _Fmt[5] = "!%x\0"; // '!' for nonzero count, null for modifier
  480. size_t _Count, _Num;
  481. string _Str;
  482. if (_Modifier == (_Elem)0)
  483. _Fmt[2] = _Specifier;
  484. else
  485. _Fmt[2] = _Modifier, _Fmt[3] = _Specifier;
  486. for (_Num = 16; ; _Num *= 2)
  487. { // convert into ever larger string buffer until success
  488. _Str.append(_Num, '\0');
  489. if (0 < (_Count = _Strftime(&*_Str.begin(), _Str.size(),
  490. _Fmt, _Pt, _Tnames._Getptr())))
  491. break;
  492. }
  493. _Mbstinit(_Mbst);
  494. --_Count;
  495. for (string::const_iterator _Snext = _Str.begin() + 1;
  496. 0 < _Count; ++_Dest)
  497. { // convert to wchar_t, skip literal '!'
  498. wchar_t _Wc;
  499. int _Bytes;
  500. switch (_Bytes = _Mbrtowc(&_Wc, &*_Snext, _Count, &_Mbst, &_Cvt))
  501. {
  502. case -2: // partial conversion
  503. case -1: // failed conversion
  504. return (_Dest);
  505. case 0: // converted null character
  506. _Bytes = (int)::strlen(&*_Snext) + 1;
  507. // fall through
  508. default: // converted _Bytes bytes to a wchar_t
  509. *_Dest = _Wc;
  510. _Snext += _Bytes, _Count -= _Bytes;
  511. }
  512. }
  513. return (_Dest);
  514. }
  515. private:
  516. _Locinfo::_Timevec _Tnames; // locale-specific stuff for _Strftime
  517. _Locinfo::_Cvtvec _Cvt; // conversion information
  518. };
  519. #ifdef _CRTBLD_NATIVE_WCHAR_T
  520. // CLASS time_put<unsigned short>
  521. template<> class _CRTIMP2 time_put<unsigned short,
  522. ostreambuf_iterator<unsigned short, char_traits<unsigned short> > >
  523. : public locale::facet
  524. { // facet for converting encoded times to unsigned short text
  525. typedef unsigned short _Elem;
  526. typedef ostreambuf_iterator<unsigned short, char_traits<unsigned short> > _OutIt;
  527. public:
  528. typedef _Elem char_type;
  529. typedef _OutIt iter_type;
  530. _OutIt put(_OutIt _Dest, ios_base& _Iosbase, _Elem _Fill, const tm *_Pt,
  531. const _Elem *_Fmtfirst, const _Elem *_Fmtlast) const
  532. { // put formatted time from _Pt to _Dest for [_Fmtfirst, _Fmtlast)
  533. const _Elem _Percent = _WIDEN(_Elem, '%');
  534. for (; _Fmtfirst != _Fmtlast; ++_Fmtfirst)
  535. if (*_Fmtfirst != _Percent)
  536. *_Dest++ = *_Fmtfirst; // copy literal element
  537. else if (++_Fmtfirst == _Fmtlast)
  538. { // treat trailing % as %%
  539. *_Dest++ = _Percent;
  540. break;
  541. }
  542. else
  543. { // get specifier after %
  544. char _Specifier = _NARROW(_Elem, *_Fmtfirst);
  545. char _Qualifier = '\0';
  546. if (_Specifier != 'E' && _Specifier != 'O'
  547. && _Specifier != 'Q' && _Specifier != '#')
  548. ; // not [E0Q#] qualifier, treat as specifier
  549. else if (++_Fmtfirst == _Fmtlast)
  550. { // no specifier, copy %[E0Q#] as literal elements
  551. *_Dest++ = _Percent, *_Dest++ = _Specifier;
  552. break;
  553. }
  554. else
  555. { // save both qualifier and specifier
  556. _Qualifier = _Specifier;
  557. _Specifier = _NARROW(_Elem, *_Fmtfirst);
  558. }
  559. _Dest = do_put(_Dest, _Iosbase, _Fill, _Pt,
  560. _Specifier, _Qualifier); // convert a single field
  561. }
  562. return (_Dest);
  563. }
  564. _OutIt put(_OutIt _Dest, ios_base& _Iosbase, _Elem _Fill, const tm *_Pt,
  565. char _Specifier, char _Modifier = 0) const
  566. { // put formatted time from _Pt to _Dest for _Specifier/_Modifier
  567. return (do_put(_Dest, _Iosbase, _Fill, _Pt, _Specifier, _Modifier));
  568. }
  569. static locale::id id; // unique facet id
  570. explicit time_put(size_t _Refs = 0)
  571. : locale::facet(_Refs)
  572. { // construct from current locale
  573. _Init(_Locinfo());
  574. }
  575. time_put(const _Locinfo& _Lobj, size_t _Refs = 0)
  576. : locale::facet(_Refs)
  577. { // construct from specified locale
  578. _Init(_Lobj);
  579. }
  580. static size_t __cdecl _Getcat(const locale::facet **_Ppf = 0)
  581. { // return locale category mask and construct standard facet
  582. if (_Ppf != 0 && *_Ppf == 0)
  583. *_Ppf = _NEW_CRT time_put<_Elem, _OutIt>;
  584. return (_X_TIME);
  585. }
  586. _PROTECTED:
  587. virtual ~time_put()
  588. { // destroy the object
  589. }
  590. protected:
  591. void _Init(const _Locinfo& _Lobj)
  592. { // initialize from _Lobj
  593. _Tnames = _Lobj._Gettnames();
  594. _Cvt = _Lobj._Getcvt();
  595. }
  596. virtual _OutIt do_put(_OutIt _Dest, ios_base&, _Elem, const tm *_Pt,
  597. char _Specifier, char _Modifier = 0) const
  598. { // put formatted time from _Pt to _Dest for [_Fmtfirst, _Fmtlast)
  599. char _Fmt[5] = "!%x\0"; // '!' for nonzero count, null for modifier
  600. size_t _Count, _Num;
  601. string _Str;
  602. if (_Modifier == (_Elem)0)
  603. _Fmt[2] = _Specifier;
  604. else
  605. _Fmt[2] = _Modifier, _Fmt[3] = _Specifier;
  606. for (_Num = 16; ; _Num *= 2)
  607. { // convert into ever larger string buffer until success
  608. _Str.append(_Num, '\0');
  609. if (0 < (_Count = _Strftime(&*_Str.begin(), _Str.size(),
  610. _Fmt, _Pt, _Tnames._Getptr())))
  611. break;
  612. }
  613. _Mbstinit(_Mbst);
  614. --_Count;
  615. for (string::const_iterator _Snext = _Str.begin() + 1;
  616. 0 < _Count; ++_Dest)
  617. { // convert to wchar_t, skip literal '!'
  618. wchar_t _Wc;
  619. int _Bytes;
  620. switch (_Bytes = _Mbrtowc(&_Wc, &*_Snext, _Count, &_Mbst, &_Cvt))
  621. {
  622. case -2: // partial conversion
  623. case -1: // failed conversion
  624. return (_Dest);
  625. case 0: // converted null character
  626. _Bytes = (int)::strlen(&*_Snext) + 1;
  627. // fall through
  628. default: // converted _Bytes bytes to a wchar_t
  629. *_Dest = _Wc;
  630. _Snext += _Bytes, _Count -= _Bytes;
  631. }
  632. }
  633. return (_Dest);
  634. }
  635. private:
  636. _Locinfo::_Timevec _Tnames; // locale-specific stuff for _Strftime
  637. _Locinfo::_Cvtvec _Cvt; // conversion information
  638. };
  639. #endif
  640. // TEMPLATE CLASS time_put_byname
  641. template<class _Elem,
  642. class _OutIt = ostreambuf_iterator<_Elem, char_traits<_Elem> > >
  643. class time_put_byname
  644. : public time_put<_Elem, _OutIt>
  645. { // time_put for named locale
  646. public:
  647. explicit time_put_byname(const char *_Locname, size_t _Refs = 0)
  648. : time_put<_Elem, _OutIt>(_Locinfo(_Locname), _Refs)
  649. { // construct for named locale
  650. }
  651. _PROTECTED:
  652. virtual ~time_put_byname()
  653. { // destroy the object
  654. }
  655. };
  656. #ifdef _DLL_CPPLIB
  657. #ifdef __FORCE_INSTANCE
  658. template class _CRTIMP2 time_get<char,
  659. istreambuf_iterator<char, char_traits<char> > >;
  660. template class _CRTIMP2 time_get<wchar_t,
  661. istreambuf_iterator<wchar_t, char_traits<wchar_t> > >;
  662. #ifdef _CRTBLD_NATIVE_WCHAR_T
  663. template class _CRTIMP2 time_get<unsigned short,
  664. istreambuf_iterator<unsigned short, char_traits<unsigned short> > >;
  665. #endif
  666. template class _CRTIMP2 time_put<char,
  667. ostreambuf_iterator<char, char_traits<char> > >;
  668. template class _CRTIMP2 time_put<wchar_t,
  669. ostreambuf_iterator<wchar_t, char_traits<wchar_t> > >;
  670. #ifdef _CRTBLD_NATIVE_WCHAR_T
  671. template class _CRTIMP2 time_put<unsigned short,
  672. ostreambuf_iterator<unsigned short, char_traits<unsigned short> > >;
  673. #endif
  674. #endif // __FORCE_INSTANCE
  675. #endif // _DLL_CPPLIB
  676. _STD_END
  677. #pragma warning(pop)
  678. #pragma pack(pop)
  679. #endif /* _XLOCTIME_ */
  680. /*
  681. * Copyright (c) 1992-2001 by P.J. Plauger. ALL RIGHTS RESERVED.
  682. * Consult your license regarding permissions and restrictions.
  683. V3.10:0009 */