_time_facets.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441
  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. #ifndef _STLP_TIME_FACETS_C
  19. #define _STLP_TIME_FACETS_C
  20. #ifndef _STLP_INTERNAL_TIME_FACETS_H
  21. # include <stl/_time_facets.h>
  22. #endif
  23. #ifndef _STLP_INTERNAL_NUM_PUT_H
  24. # include <stl/_num_put.h>
  25. #endif
  26. #ifndef _STLP_INTERNAL_NUM_GET_H
  27. # include <stl/_num_get.h>
  28. #endif
  29. _STLP_BEGIN_NAMESPACE
  30. //----------------------------------------------------------------------
  31. // Declarations of static template members.
  32. template <class _CharT, class _InputIterator>
  33. locale::id time_get<_CharT, _InputIterator>::id;
  34. template <class _CharT, class _OutputIterator>
  35. locale::id time_put<_CharT, _OutputIterator>::id;
  36. _STLP_MOVE_TO_PRIV_NAMESPACE
  37. /* Matching input against a list of names
  38. * Alphabetic input of the names of months and the names
  39. * of weekdays requires matching input against a list of names.
  40. * We use a simple generic algorithm to accomplish this. This
  41. * algorithm is not very efficient, especially for longer lists
  42. * of names, but it probably does not matter for the initial
  43. * implementation and it may never matter, since we do not expect
  44. * this kind of input to be used very often. The algorithm
  45. * could be improved fairly simply by creating a new list of
  46. * names still in the running at each iteration. A more sophisticated
  47. * approach would be to build a tree to do the matching.
  48. *
  49. * We compare each character of the input to the corresponding
  50. * character of each name on the list that has not been eliminated,
  51. * either because every character in the name has already been
  52. * matched, or because some character has not been matched. We
  53. * continue only as long as there are some names that have not been
  54. * eliminated.
  55. * We do not really need a random access iterator (a forward iterator
  56. * would do), but the extra generality makes the notation clumsier,
  57. * and we don't really need it.
  58. * We can recognize a failed match by the fact that the return value
  59. * will be __name_end.
  60. */
  61. #define _MAXNAMES 24
  62. template <class _InIt, class _NameIt>
  63. size_t _STLP_CALL
  64. __match(_InIt& __first, _InIt& __last, _NameIt __name, _NameIt __name_end) {
  65. typedef ptrdiff_t difference_type;
  66. difference_type __n = __name_end - __name;
  67. difference_type __i, __start = 0;
  68. size_t __pos = 0;
  69. difference_type __check_count = __n;
  70. bool __do_not_check[_MAXNAMES];
  71. size_t __matching_name_index = __n;
  72. memset(__do_not_check, 0, sizeof(__do_not_check));
  73. while (__first != __last) {
  74. difference_type __new_n = __n;
  75. for (__i = __start; __i < __n; ++__i) {
  76. if (!__do_not_check[__i]) {
  77. if (*__first == __name[__i][__pos]) {
  78. if (__pos == (__name[__i].size() - 1)) {
  79. __matching_name_index = __i;
  80. __do_not_check[__i] = true;
  81. if (__i == __start) ++__start;
  82. --__check_count;
  83. if (__check_count == 0) {
  84. ++__first;
  85. return __matching_name_index;
  86. }
  87. }
  88. __new_n = __i + 1;
  89. }
  90. else {
  91. __do_not_check[__i] = true;
  92. if (__i == __start) ++__start;
  93. --__check_count;
  94. if (__check_count == 0)
  95. return __matching_name_index;
  96. }
  97. }
  98. else {
  99. if (__i == __start) ++ __start;
  100. }
  101. }
  102. __n = __new_n;
  103. ++__first; ++__pos;
  104. }
  105. return __matching_name_index;
  106. }
  107. // __get_formatted_time reads input that is assumed to be formatted
  108. // according to the rules for the C strftime function (C standard,
  109. // 7.12.3.5). This function is used to implement the do_get_time
  110. // and do_get_date virtual functions, which depend on the locale
  111. // specifications for the time and day formats respectively.
  112. // Note the catchall default case, intended mainly for the '%Z'
  113. // format designator, which does not make sense here since the
  114. // representation of timezones is not part of the locale.
  115. //
  116. // The case branches are implemented either by doing a match using
  117. // the appopriate name table or by doing a __get_integer_nogroup.
  118. //
  119. // 'y' format is assumed to mean that the input represents years
  120. // since 1900. That is, 2002 should be represented as 102. There
  121. // is no century-guessing.
  122. //
  123. // The match is successful if and only if the second component of the
  124. // return value is format_end.
  125. // Note that the antepenultimate parameter is being used only to determine
  126. // the correct overloading for the calls to __get_integer_nogroup.
  127. template <class _InIt1, class _Ch, class _TimeInfo>
  128. string::const_iterator _STLP_CALL
  129. __get_formatted_time _STLP_WEAK (_InIt1 __first, _InIt1 __last,
  130. string::const_iterator __format, string::const_iterator __format_end,
  131. _Ch*, const _TimeInfo& __table,
  132. const ios_base& __s, ios_base::iostate& __err, tm* __t) {
  133. const ctype<_Ch>& __ct = use_facet<ctype<_Ch> >(__s.getloc());
  134. typedef basic_string<_Ch, char_traits<_Ch>, allocator<_Ch> > string_type;
  135. size_t offset;
  136. while (__first != __last && __format != __format_end) {
  137. offset = 0;
  138. if (*__format == '%') {
  139. ++__format;
  140. char __c = *__format;
  141. if (__c == '#') { //MS extension
  142. ++__format;
  143. __c = *__format;
  144. }
  145. switch (__c) {
  146. case 'A':
  147. offset = 7;
  148. case 'a': {
  149. size_t __index = __match(__first, __last,
  150. __table._M_dayname + offset, __table._M_dayname + offset + 7);
  151. if (__index == 7)
  152. return __format;
  153. __t->tm_wday = __STATIC_CAST(int, __index);
  154. break;
  155. }
  156. case 'B':
  157. offset = 12;
  158. case 'b': {
  159. size_t __index = __match(__first, __last,
  160. __table._M_monthname + offset, __table._M_monthname + offset + 12);
  161. if (__index == 12)
  162. return __format;
  163. __t->tm_mon = __STATIC_CAST(int, __index);
  164. break;
  165. }
  166. case 'd': {
  167. bool __pr = __get_decimal_integer(__first, __last, __t->tm_mday, __STATIC_CAST(_Ch*, 0));
  168. if (!__pr || __t->tm_mday < 1 || __t->tm_mday > 31) {
  169. __err |= ios_base::failbit;
  170. return __format;
  171. }
  172. break;
  173. }
  174. case 'H': case 'I': {
  175. bool __pr = __get_decimal_integer(__first, __last, __t->tm_hour, __STATIC_CAST(_Ch*, 0));
  176. if (!__pr)
  177. return __format;
  178. break;
  179. }
  180. case 'j': {
  181. bool __pr = __get_decimal_integer(__first, __last, __t->tm_yday, __STATIC_CAST(_Ch*, 0));
  182. if (!__pr)
  183. return __format;
  184. break;
  185. }
  186. case 'm': {
  187. bool __pr = __get_decimal_integer(__first, __last, __t->tm_mon, __STATIC_CAST(_Ch*, 0));
  188. --__t->tm_mon;
  189. if (!__pr || __t->tm_mon < 0 || __t->tm_mon > 11) {
  190. __err |= ios_base::failbit;
  191. return __format;
  192. }
  193. break;
  194. }
  195. case 'M': {
  196. bool __pr = __get_decimal_integer(__first, __last, __t->tm_min, __STATIC_CAST(_Ch*, 0));
  197. if (!__pr)
  198. return __format;
  199. break;
  200. }
  201. case 'p': {
  202. size_t __index = __match(__first, __last,
  203. __table._M_am_pm + 0, __table._M_am_pm + 2);
  204. if (__index == 2)
  205. return __format;
  206. // 12:00 PM <=> 12:00, 12:00 AM <=> 00:00
  207. if (__index == 1 && __t->tm_hour != 12 )
  208. __t->tm_hour += 12;
  209. if (__index == 0 && __t->tm_hour == 12 )
  210. __t->tm_hour = 0;
  211. break;
  212. }
  213. case 'S': {
  214. bool __pr = __get_decimal_integer(__first, __last, __t->tm_sec, __STATIC_CAST(_Ch*, 0));
  215. if (!__pr)
  216. return __format;
  217. break;
  218. }
  219. case 'y': {
  220. bool __pr = __get_decimal_integer(__first, __last, __t->tm_year, __STATIC_CAST(_Ch*, 0));
  221. if (!__pr)
  222. return __format;
  223. break;
  224. }
  225. case 'Y': {
  226. bool __pr = __get_decimal_integer(__first, __last, __t->tm_year, __STATIC_CAST(_Ch*, 0));
  227. __t->tm_year -= 1900;
  228. if (!__pr)
  229. return __format;
  230. break;
  231. }
  232. default:
  233. break;
  234. }
  235. }
  236. else {
  237. if (*__first++ != __ct.widen(*__format)) break;
  238. }
  239. ++__format;
  240. }
  241. return __format;
  242. }
  243. template <class _InIt, class _TimeInfo>
  244. bool _STLP_CALL
  245. __get_short_or_long_dayname(_InIt& __first, _InIt& __last, const _TimeInfo& __table, tm* __t) {
  246. size_t __index = __match(__first, __last, __table._M_dayname + 0, __table._M_dayname + 14);
  247. if (__index != 14) {
  248. __t->tm_wday = __STATIC_CAST(int, __index % 7);
  249. return true;
  250. }
  251. return false;
  252. }
  253. template <class _InIt, class _TimeInfo>
  254. bool _STLP_CALL
  255. __get_short_or_long_monthname(_InIt& __first, _InIt& __last, const _TimeInfo& __table, tm* __t) {
  256. size_t __index = __match(__first, __last, __table._M_monthname + 0, __table._M_monthname + 24);
  257. if (__index != 24) {
  258. __t->tm_mon = __STATIC_CAST(int, __index % 12);
  259. return true;
  260. }
  261. return false;
  262. }
  263. _STLP_MOVE_TO_STD_NAMESPACE
  264. template <class _Ch, class _InIt>
  265. _InIt
  266. time_get<_Ch, _InIt>::do_get_date(_InIt __s, _InIt __end,
  267. ios_base& __str, ios_base::iostate& __err,
  268. tm* __t) const {
  269. typedef string::const_iterator string_iterator;
  270. string_iterator __format = this->_M_timeinfo._M_date_format.begin();
  271. string_iterator __format_end = this->_M_timeinfo._M_date_format.end();
  272. string_iterator __result
  273. = _STLP_PRIV __get_formatted_time(__s, __end, __format, __format_end,
  274. __STATIC_CAST(_Ch*, 0), this->_M_timeinfo,
  275. __str, __err, __t);
  276. if (__result == __format_end)
  277. __err = ios_base::goodbit;
  278. else {
  279. __err = ios_base::failbit;
  280. if (__s == __end)
  281. __err |= ios_base::eofbit;
  282. }
  283. return __s;
  284. }
  285. template <class _Ch, class _InIt>
  286. _InIt
  287. time_get<_Ch, _InIt>::do_get_time(_InIt __s, _InIt __end,
  288. ios_base& __str, ios_base::iostate& __err,
  289. tm* __t) const {
  290. typedef string::const_iterator string_iterator;
  291. string_iterator __format = this->_M_timeinfo._M_time_format.begin();
  292. string_iterator __format_end = this->_M_timeinfo._M_time_format.end();
  293. string_iterator __result
  294. = _STLP_PRIV __get_formatted_time(__s, __end, __format, __format_end,
  295. __STATIC_CAST(_Ch*, 0), this->_M_timeinfo,
  296. __str, __err, __t);
  297. __err = __result == __format_end ? ios_base::goodbit
  298. : ios_base::failbit;
  299. if (__s == __end)
  300. __err |= ios_base::eofbit;
  301. return __s;
  302. }
  303. template <class _Ch, class _InIt>
  304. _InIt
  305. time_get<_Ch, _InIt>::do_get_year(_InIt __s, _InIt __end,
  306. ios_base&, ios_base::iostate& __err,
  307. tm* __t) const {
  308. if (__s == __end) {
  309. __err = ios_base::failbit | ios_base::eofbit;
  310. return __s;
  311. }
  312. bool __pr = _STLP_PRIV __get_decimal_integer(__s, __end, __t->tm_year, __STATIC_CAST(_Ch*, 0));
  313. __t->tm_year -= 1900;
  314. __err = __pr ? ios_base::goodbit : ios_base::failbit;
  315. if (__s == __end)
  316. __err |= ios_base::eofbit;
  317. return __s;
  318. }
  319. template <class _Ch, class _InIt>
  320. _InIt
  321. time_get<_Ch, _InIt>::do_get_weekday(_InIt __s, _InIt __end,
  322. ios_base &__str, ios_base::iostate &__err,
  323. tm *__t) const {
  324. bool __result =
  325. _STLP_PRIV __get_short_or_long_dayname(__s, __end, this->_M_timeinfo, __t);
  326. if (__result)
  327. __err = ios_base::goodbit;
  328. else {
  329. __err = ios_base::failbit;
  330. if (__s == __end)
  331. __err |= ios_base::eofbit;
  332. }
  333. return __s;
  334. }
  335. template <class _Ch, class _InIt>
  336. _InIt
  337. time_get<_Ch, _InIt>::do_get_monthname(_InIt __s, _InIt __end,
  338. ios_base &__str, ios_base::iostate &__err,
  339. tm *__t) const {
  340. bool __result =
  341. _STLP_PRIV __get_short_or_long_monthname(__s, __end, this->_M_timeinfo, __t);
  342. if (__result)
  343. __err = ios_base::goodbit;
  344. else {
  345. __err = ios_base::failbit;
  346. if (__s == __end)
  347. __err |= ios_base::eofbit;
  348. }
  349. return __s;
  350. }
  351. template<class _Ch, class _OutputIter>
  352. _OutputIter
  353. time_put<_Ch,_OutputIter>::put(_OutputIter __s, ios_base& __f, _Ch __fill,
  354. const tm* __tmb, const _Ch* __pat,
  355. const _Ch* __pat_end) const {
  356. const ctype<_Ch>& _Ct = use_facet<ctype<_Ch> >(__f.getloc());
  357. while (__pat != __pat_end) {
  358. char __c = _Ct.narrow(*__pat, 0);
  359. if (__c == '%') {
  360. char __mod = 0;
  361. ++__pat;
  362. __c = _Ct.narrow(*__pat++, 0);
  363. if (__c == '#') { // MS extension
  364. __mod = __c;
  365. __c = _Ct.narrow(*__pat++, 0);
  366. }
  367. __s = do_put(__s, __f, __fill, __tmb, __c, __mod);
  368. }
  369. else
  370. *__s++ = *__pat++;
  371. }
  372. return __s;
  373. }
  374. template<class _Ch, class _OutputIter>
  375. _OutputIter
  376. time_put<_Ch,_OutputIter>::do_put(_OutputIter __s, ios_base& __f, _Ch /* __fill */,
  377. const tm* __tmb, char __format,
  378. char __modifier ) const {
  379. const ctype<_Ch>& __ct = use_facet<ctype<_Ch> >(__f.getloc());
  380. _STLP_BASIC_IOSTRING(_Ch) __buf;
  381. _STLP_PRIV __write_formatted_time(__buf, __ct, __format, __modifier, this->_M_timeinfo, __tmb);
  382. return copy(__buf.begin(), __buf.end(), __s);
  383. }
  384. _STLP_END_NAMESPACE
  385. #endif /* _STLP_TIME_FACETS_C */
  386. // Local Variables:
  387. // mode:C++
  388. // End: