time_facets.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565
  1. /*
  2. * Copyright (c) 1999
  3. * Silicon Graphics Computer Systems, Inc.
  4. *
  5. * Copyright (c) 1999
  6. * Boris Fomitchev
  7. *
  8. * This material is provided "as is", with absolutely no warranty expressed
  9. * or implied. Any use is at your own risk.
  10. *
  11. * Permission to use or copy this software for any purpose is hereby granted
  12. * without fee, provided the above notices are retained on all copies.
  13. * Permission to modify the code and to distribute modified code is granted,
  14. * provided the above notices are retained, and a notice that the code was
  15. * modified is included with the above copyright notice.
  16. *
  17. */
  18. #include "stlport_prefix.h"
  19. #include <cstdio>
  20. #include <locale>
  21. #include <istream>
  22. #include "c_locale.h"
  23. #include "acquire_release.h"
  24. _STLP_BEGIN_NAMESPACE
  25. _STLP_MOVE_TO_PRIV_NAMESPACE
  26. // default "C" values for month and day names
  27. const char default_dayname[][14] = {
  28. "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
  29. "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
  30. "Friday", "Saturday"};
  31. const char default_monthname[][24] = {
  32. "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  33. "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
  34. "January", "February", "March", "April", "May", "June",
  35. "July", "August", "September", "October", "November", "December"};
  36. #ifndef _STLP_NO_WCHAR_T
  37. const wchar_t default_wdayname[][14] = {
  38. L"Sun", L"Mon", L"Tue", L"Wed", L"Thu", L"Fri", L"Sat",
  39. L"Sunday", L"Monday", L"Tuesday", L"Wednesday", L"Thursday",
  40. L"Friday", L"Saturday"};
  41. const wchar_t default_wmonthname[][24] = {
  42. L"Jan", L"Feb", L"Mar", L"Apr", L"May", L"Jun",
  43. L"Jul", L"Aug", L"Sep", L"Oct", L"Nov", L"Dec",
  44. L"January", L"February", L"March", L"April", L"May", L"June",
  45. L"July", L"August", L"September", L"October", L"November", L"December"};
  46. #endif
  47. #if defined (__BORLANDC__)
  48. _Time_Info time_init<char>::_M_timeinfo;
  49. # ifndef _STLP_NO_WCHAR_T
  50. _WTime_Info time_init<wchar_t>::_M_timeinfo;
  51. # endif
  52. #endif
  53. // _Init_time_info: initialize table with
  54. // "C" values (note these are not defined in the C standard, so this
  55. // is somewhat arbitrary).
  56. static void _Init_timeinfo_base(_Time_Info_Base& table) {
  57. table._M_time_format = "%H:%M:%S";
  58. table._M_date_format = "%m/%d/%y";
  59. table._M_date_time_format = "%m/%d/%y";
  60. }
  61. static void _Init_timeinfo(_Time_Info& table) {
  62. int i;
  63. for (i = 0; i < 14; ++i)
  64. table._M_dayname[i] = default_dayname[i];
  65. for (i = 0; i < 24; ++i)
  66. table._M_monthname[i] = default_monthname[i];
  67. table._M_am_pm[0] = "AM";
  68. table._M_am_pm[1] = "PM";
  69. _Init_timeinfo_base(table);
  70. }
  71. #ifndef _STLP_NO_WCHAR_T
  72. static void _Init_timeinfo(_WTime_Info& table) {
  73. int i;
  74. for (i = 0; i < 14; ++i)
  75. table._M_dayname[i] = default_wdayname[i];
  76. for (i = 0; i < 24; ++i)
  77. table._M_monthname[i] = default_wmonthname[i];
  78. table._M_am_pm[0] = L"AM";
  79. table._M_am_pm[1] = L"PM";
  80. _Init_timeinfo_base(table);
  81. }
  82. #endif
  83. static void _Init_timeinfo_base(_Time_Info_Base& table, _Locale_time * time) {
  84. table._M_time_format = _Locale_t_fmt(time);
  85. if ( table._M_time_format == "%T" ) {
  86. table._M_time_format = "%H:%M:%S";
  87. } else if ( table._M_time_format == "%r" ) {
  88. table._M_time_format = "%I:%M:%S %p";
  89. } else if ( table._M_time_format == "%R" ) {
  90. table._M_time_format = "%H:%M";
  91. }
  92. table._M_date_format = _Locale_d_fmt(time);
  93. table._M_date_time_format = _Locale_d_t_fmt(time);
  94. table._M_long_date_format = _Locale_long_d_fmt(time);
  95. table._M_long_date_time_format = _Locale_long_d_t_fmt(time);
  96. }
  97. static void _Init_timeinfo(_Time_Info& table, _Locale_time * time) {
  98. int i;
  99. for (i = 0; i < 7; ++i)
  100. table._M_dayname[i] = _Locale_abbrev_dayofweek(time, i);
  101. for (i = 0; i < 7; ++i)
  102. table._M_dayname[i+7] = _Locale_full_dayofweek(time, i);
  103. for (i = 0; i < 12; ++i)
  104. table._M_monthname[i] = _Locale_abbrev_monthname(time, i);
  105. for (i = 0; i < 12; ++i)
  106. table._M_monthname[i+12] = _Locale_full_monthname(time, i);
  107. table._M_am_pm[0] = _Locale_am_str(time);
  108. table._M_am_pm[1] = _Locale_pm_str(time);
  109. _Init_timeinfo_base(table, time);
  110. }
  111. #ifndef _STLP_NO_WCHAR_T
  112. static void _Init_timeinfo(_WTime_Info& table, _Locale_time * time) {
  113. wchar_t buf[128];
  114. int i;
  115. for (i = 0; i < 7; ++i)
  116. table._M_dayname[i] = _WLocale_abbrev_dayofweek(time, i, _STLP_ARRAY_AND_SIZE(buf));
  117. for (i = 0; i < 7; ++i)
  118. table._M_dayname[i+7] = _WLocale_full_dayofweek(time, i, _STLP_ARRAY_AND_SIZE(buf));
  119. for (i = 0; i < 12; ++i)
  120. table._M_monthname[i] = _WLocale_abbrev_monthname(time, i, _STLP_ARRAY_AND_SIZE(buf));
  121. for (i = 0; i < 12; ++i)
  122. table._M_monthname[i+12] = _WLocale_full_monthname(time, i, _STLP_ARRAY_AND_SIZE(buf));
  123. table._M_am_pm[0] = _WLocale_am_str(time, _STLP_ARRAY_AND_SIZE(buf));
  124. table._M_am_pm[1] = _WLocale_pm_str(time, _STLP_ARRAY_AND_SIZE(buf));
  125. _Init_timeinfo_base(table, time);
  126. }
  127. #endif
  128. template <class _Ch, class _TimeInfo>
  129. void __subformat(_STLP_BASIC_IOSTRING(_Ch) &buf, const ctype<_Ch>& ct,
  130. const string& format, const _TimeInfo& table, const tm* t) {
  131. const char * cp = format.data();
  132. const char * cp_end = cp + format.size();
  133. while (cp != cp_end) {
  134. if (*cp == '%') {
  135. char mod = 0;
  136. ++cp;
  137. if (*cp == '#') {
  138. mod = *cp; ++cp;
  139. }
  140. __write_formatted_timeT(buf, ct, *cp++, mod, table, t);
  141. } else
  142. buf.append(1, *cp++);
  143. }
  144. }
  145. static void __append(__iostring &buf, const string& name)
  146. { buf.append(name.data(), name.data() + name.size()); }
  147. static void __append(__iowstring &buf, const wstring& name)
  148. { buf.append(name.data(), name.data() + name.size()); }
  149. static void __append(__iostring &buf, char *first, char *last, const ctype<char>& /* ct */)
  150. { buf.append(first, last); }
  151. static void __append(__iowstring &buf, char *first, char *last, const ctype<wchar_t>& ct) {
  152. wchar_t _wbuf[64];
  153. ct.widen(first, last, _wbuf);
  154. buf.append(_wbuf, _wbuf + (last - first));
  155. }
  156. #if defined (__GNUC__)
  157. /* The number of days from the first day of the first ISO week of this
  158. year to the year day YDAY with week day WDAY. ISO weeks start on
  159. Monday; the first ISO week has the year's first Thursday. YDAY may
  160. be as small as YDAY_MINIMUM. */
  161. # define __ISO_WEEK_START_WDAY 1 /* Monday */
  162. # define __ISO_WEEK1_WDAY 4 /* Thursday */
  163. # define __YDAY_MINIMUM (-366)
  164. # define __TM_YEAR_BASE 1900
  165. static int
  166. __iso_week_days(int yday, int wday) {
  167. /* Add enough to the first operand of % to make it nonnegative. */
  168. int big_enough_multiple_of_7 = (-__YDAY_MINIMUM / 7 + 2) * 7;
  169. return (yday
  170. - (yday - wday + __ISO_WEEK1_WDAY + big_enough_multiple_of_7) % 7
  171. + __ISO_WEEK1_WDAY - __ISO_WEEK_START_WDAY);
  172. }
  173. # define __is_leap(year)\
  174. ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
  175. #endif
  176. #define __hour12(hour) \
  177. (((hour) % 12 == 0) ? (12) : (hour) % 12)
  178. #if !defined (_STLP_USE_SAFE_STRING_FUNCTIONS)
  179. # define _STLP_SPRINTF sprintf
  180. #else
  181. # define _STLP_SPRINTF sprintf_s
  182. #endif
  183. template <class _Ch, class _TimeInfo>
  184. void _STLP_CALL __write_formatted_timeT(_STLP_BASIC_IOSTRING(_Ch) &buf,
  185. const ctype<_Ch>& ct,
  186. char format, char modifier,
  187. const _TimeInfo& table, const tm* t) {
  188. char _buf[64];
  189. char *_bend;
  190. switch (format) {
  191. case 'a':
  192. __append(buf, table._M_dayname[t->tm_wday]);
  193. break;
  194. case 'A':
  195. __append(buf, table._M_dayname[t->tm_wday + 7]);
  196. break;
  197. case 'b':
  198. __append(buf, table._M_monthname[t->tm_mon]);
  199. break;
  200. case 'B':
  201. __append(buf, table._M_monthname[t->tm_mon + 12]);
  202. break;
  203. case 'c':
  204. __subformat(buf, ct, (modifier != '#') ? table._M_date_time_format
  205. : table._M_long_date_time_format, table, t);
  206. break;
  207. case 'd':
  208. _STLP_SPRINTF(_buf, (modifier != '#') ? "%.2ld" : "%ld", (long)t->tm_mday);
  209. __append(buf, _buf, ((long)t->tm_mday < 10L && modifier == '#') ? _buf + 1 : _buf + 2, ct);
  210. break;
  211. case 'e':
  212. _STLP_SPRINTF(_buf, "%2ld", (long)t->tm_mday);
  213. __append(buf, _buf, _buf + 2, ct);
  214. break;
  215. case 'H':
  216. _STLP_SPRINTF(_buf, (modifier != '#') ? "%.2ld" : "%ld", (long)t->tm_hour);
  217. __append(buf, _buf, ((long)t->tm_hour < 10L && modifier == '#') ? _buf + 1 : _buf + 2, ct);
  218. break;
  219. case 'I':
  220. _STLP_SPRINTF(_buf, (modifier != '#') ? "%.2ld" : "%ld", (long)__hour12(t->tm_hour));
  221. __append(buf, _buf, ((long)__hour12(t->tm_hour) < 10L && modifier == '#') ? _buf + 1 : _buf + 2, ct);
  222. break;
  223. case 'j':
  224. _bend = __write_integer(_buf, 0, (long)((long)t->tm_yday + 1));
  225. __append(buf, _buf, _bend, ct);
  226. break;
  227. case 'm':
  228. _STLP_SPRINTF(_buf, (modifier != '#') ? "%.2ld" : "%ld", (long)t->tm_mon + 1);
  229. __append(buf, _buf, ((long)(t->tm_mon + 1) < 10L && modifier == '#') ? _buf + 1 : _buf + 2, ct);
  230. break;
  231. case 'M':
  232. _STLP_SPRINTF(_buf, (modifier != '#') ? "%.2ld" : "%ld", (long)t->tm_min);
  233. __append(buf, _buf, ((long)t->tm_min < 10L && modifier == '#') ? _buf + 1 : _buf + 2, ct);
  234. break;
  235. case 'p':
  236. __append(buf, table._M_am_pm[t->tm_hour / 12]);
  237. break;
  238. case 'S': // pad with zeros
  239. _STLP_SPRINTF(_buf, (modifier != '#') ? "%.2ld" : "%ld", (long)t->tm_sec);
  240. __append(buf, _buf, ((long)t->tm_sec < 10L && modifier == '#') ? _buf + 1 : _buf + 2, ct);
  241. break;
  242. case 'U':
  243. _bend = __write_integer(_buf, 0, long((t->tm_yday - t->tm_wday + 7) / 7));
  244. __append(buf, _buf, _bend, ct);
  245. break;
  246. case 'w':
  247. _bend = __write_integer(_buf, 0, (long)t->tm_wday);
  248. __append(buf, _buf, _bend, ct);
  249. break;
  250. case 'W':
  251. _bend = __write_integer(_buf, 0,
  252. (long)(t->tm_wday == 0 ? (t->tm_yday + 1) / 7 :
  253. (t->tm_yday + 8 - t->tm_wday) / 7));
  254. __append(buf, _buf, _bend, ct);
  255. break;
  256. case'x':
  257. __subformat(buf, ct, (modifier != '#') ? table._M_date_format
  258. : table._M_long_date_format, table, t);
  259. break;
  260. case 'X':
  261. __subformat(buf, ct, table._M_time_format, table, t);
  262. break;
  263. case 'y':
  264. _bend = __write_integer(_buf, 0, (long)((long)(t->tm_year + 1900) % 100));
  265. __append(buf, _buf, _bend, ct);
  266. break;
  267. case 'Y':
  268. _bend = __write_integer(_buf, 0, (long)((long)t->tm_year + 1900));
  269. __append(buf, _buf, _bend, ct);
  270. break;
  271. case '%':
  272. buf.append(1, ct.widen('%'));
  273. break;
  274. #if defined (__GNUC__)
  275. // fbp : at least on SUN
  276. # if defined (_STLP_UNIX) && !defined (__linux__)
  277. # define __USE_BSD 1
  278. # endif
  279. /*********************************************
  280. * JGS, handle various extensions *
  281. *********************************************/
  282. case 'h': /* POSIX.2 extension */
  283. // same as 'b', abbrev month name
  284. __append(buf, table._M_monthname[t->tm_mon]);
  285. break;
  286. case 'C': /* POSIX.2 extension */
  287. // same as 'd', the day
  288. _STLP_SPRINTF(_buf, "%2ld", (long)t->tm_mday);
  289. __append(buf, _buf, _buf + 2, ct);
  290. break;
  291. case 'D': /* POSIX.2 extension */
  292. // same as 'x'
  293. __subformat(buf, ct, table._M_date_format, table, t);
  294. break;
  295. case 'k': /* GNU extension */
  296. _STLP_SPRINTF(_buf, "%2ld", (long)t->tm_hour);
  297. __append(buf, _buf, _buf + 2, ct);
  298. break;
  299. case 'l': /* GNU extension */
  300. _STLP_SPRINTF(_buf, "%2ld", (long)t->tm_hour % 12);
  301. __append(buf, _buf, _buf + 2, ct);
  302. break;
  303. case 'n': /* POSIX.2 extension */
  304. buf.append(1, ct.widen('\n'));
  305. break;
  306. case 'R': /* GNU extension */
  307. __subformat(buf, ct, "%H:%M", table, t);
  308. break;
  309. case 'r': /* POSIX.2 extension */
  310. __subformat(buf, ct, "%I:%M:%S %p", table, t);
  311. break;
  312. case 'T': /* POSIX.2 extension. */
  313. __subformat(buf, ct, "%H:%M:%S", table, t);
  314. break;
  315. case 't': /* POSIX.2 extension. */
  316. buf.append(1, ct.widen('\t'));
  317. case 'u': /* POSIX.2 extension. */
  318. _bend = __write_integer(_buf, 0, long((t->tm_wday - 1 + 7)) % 7 + 1);
  319. __append(buf, _buf, _bend, ct);
  320. break;
  321. case 's': {
  322. time_t __t = mktime(__CONST_CAST(tm*, t));
  323. _bend = __write_integer(_buf, 0, (long)__t );
  324. __append(buf, _buf, _bend, ct);
  325. break;
  326. }
  327. case 'g': /* GNU extension */
  328. case 'G': {
  329. int year = t->tm_year + __TM_YEAR_BASE;
  330. int days = __iso_week_days (t->tm_yday, t->tm_wday);
  331. if (days < 0) {
  332. /* This ISO week belongs to the previous year. */
  333. year--;
  334. days = __iso_week_days (t->tm_yday + (365 + __is_leap (year)), t->tm_wday);
  335. }
  336. else {
  337. int d = __iso_week_days (t->tm_yday - (365 + __is_leap (year)), t->tm_wday);
  338. if (0 <= d) {
  339. /* This ISO week belongs to the next year. */
  340. ++year;
  341. days = d;
  342. }
  343. }
  344. long val;
  345. switch (format) {
  346. case 'g':
  347. val = (long)(year % 100 + 100) % 100;
  348. break;
  349. case 'G':
  350. val = (long)year;
  351. break;
  352. default:
  353. val = (long)days / 7 + 1;
  354. break;
  355. }
  356. _bend = __write_integer(_buf, 0, val);
  357. __append(buf, _buf, _bend, ct);
  358. break;
  359. }
  360. # if defined (_STLP_USE_GLIBC)
  361. case 'z': /* GNU extension. */
  362. if (t->tm_isdst < 0)
  363. break;
  364. {
  365. int diff;
  366. # if defined (__USE_BSD) || defined (__BEOS__)
  367. diff = t->tm_gmtoff;
  368. # else
  369. diff = t->__tm_gmtoff;
  370. # endif
  371. if (diff < 0) {
  372. buf.append(1, ct.widen('-'));
  373. diff = -diff;
  374. } else
  375. buf.append(1, ct.widen('+'));
  376. diff /= 60;
  377. _STLP_SPRINTF(_buf, "%.4d", (diff / 60) * 100 + diff % 60);
  378. __append(buf, _buf, _buf + 4, ct);
  379. break;
  380. }
  381. # endif /* __GLIBC__ */
  382. #endif /* __GNUC__ */
  383. default:
  384. break;
  385. }
  386. }
  387. void _STLP_CALL __write_formatted_time(__iostring &buf, const ctype<char>& ct,
  388. char format, char modifier,
  389. const _Time_Info& table, const tm* t)
  390. { __write_formatted_timeT(buf, ct, format, modifier, table, t); }
  391. void _STLP_CALL __write_formatted_time(__iowstring &buf, const ctype<wchar_t>& ct,
  392. char format, char modifier,
  393. const _WTime_Info& table, const tm* t)
  394. { __write_formatted_timeT(buf, ct, format, modifier, table, t); }
  395. static time_base::dateorder __get_date_order(_Locale_time* time) {
  396. const char * fmt = _Locale_d_fmt(time);
  397. char first, second, third;
  398. while (*fmt != 0 && *fmt != '%') ++fmt;
  399. if (*fmt == 0)
  400. return time_base::no_order;
  401. first = *++fmt;
  402. while (*fmt != 0 && *fmt != '%') ++fmt;
  403. if (*fmt == 0)
  404. return time_base::no_order;
  405. second = *++fmt;
  406. while (*fmt != 0 && *fmt != '%') ++fmt;
  407. if (*fmt == 0)
  408. return time_base::no_order;
  409. third = *++fmt;
  410. switch (first) {
  411. case 'd':
  412. return (second == 'm' && third == 'y') ? time_base::dmy
  413. : time_base::no_order;
  414. case 'm':
  415. return (second == 'd' && third == 'y') ? time_base::mdy
  416. : time_base::no_order;
  417. case 'y':
  418. switch (second) {
  419. case 'd':
  420. return third == 'm' ? time_base::ydm : time_base::no_order;
  421. case 'm':
  422. return third == 'd' ? time_base::ymd : time_base::no_order;
  423. default:
  424. return time_base::no_order;
  425. }
  426. default:
  427. return time_base::no_order;
  428. }
  429. }
  430. time_init<char>::time_init()
  431. : _M_dateorder(time_base::no_order)
  432. { _Init_timeinfo(_M_timeinfo); }
  433. time_init<char>::time_init(const char* __name) {
  434. if (!__name)
  435. locale::_M_throw_on_null_name();
  436. int __err_code;
  437. char buf[_Locale_MAX_SIMPLE_NAME];
  438. _Locale_time *__time = __acquire_time(__name, buf, 0, &__err_code);
  439. if (!__time)
  440. locale::_M_throw_on_creation_failure(__err_code, __name, "time");
  441. _Init_timeinfo(this->_M_timeinfo, __time);
  442. _M_dateorder = __get_date_order(__time);
  443. __release_time(__time);
  444. }
  445. time_init<char>::time_init(_Locale_time *__time) {
  446. _Init_timeinfo(this->_M_timeinfo, __time);
  447. _M_dateorder = __get_date_order(__time);
  448. }
  449. #ifndef _STLP_NO_WCHAR_T
  450. time_init<wchar_t>::time_init()
  451. : _M_dateorder(time_base::no_order)
  452. { _Init_timeinfo(_M_timeinfo); }
  453. time_init<wchar_t>::time_init(const char* __name) {
  454. if (!__name)
  455. locale::_M_throw_on_null_name();
  456. int __err_code;
  457. char buf[_Locale_MAX_SIMPLE_NAME];
  458. _Locale_time *__time = __acquire_time(__name, buf, 0, &__err_code);
  459. if (!__time)
  460. locale::_M_throw_on_creation_failure(__err_code, __name, "time");
  461. _Init_timeinfo(this->_M_timeinfo, __time);
  462. _M_dateorder = __get_date_order(__time);
  463. __release_time(__time);
  464. }
  465. time_init<wchar_t>::time_init(_Locale_time *__time) {
  466. _Init_timeinfo(this->_M_timeinfo, __time);
  467. _M_dateorder = __get_date_order(__time);
  468. }
  469. #endif
  470. _STLP_MOVE_TO_STD_NAMESPACE
  471. #if !defined (_STLP_NO_FORCE_INSTANTIATE)
  472. template class time_get<char, istreambuf_iterator<char, char_traits<char> > >;
  473. template class time_put<char, ostreambuf_iterator<char, char_traits<char> > >;
  474. # ifndef _STLP_NO_WCHAR_T
  475. template class time_get<wchar_t, istreambuf_iterator<wchar_t, char_traits<wchar_t> > >;
  476. template class time_put<wchar_t, ostreambuf_iterator<wchar_t, char_traits<wchar_t> > >;
  477. # endif
  478. #endif
  479. _STLP_END_NAMESPACE