home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / stlpt453.zip / STLport-4.5.3 / src / time_facets.cpp < prev    next >
C/C++ Source or Header  |  2001-05-27  |  13KB  |  442 lines

  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.  
  19.  
  20. #include "stlport_prefix.h"
  21. #include <stl/_time_facets.h>
  22. #include <stl/_istream.h>
  23. #include "c_locale.h"
  24.  
  25. _STLP_BEGIN_NAMESPACE
  26.  
  27. char* _STLP_CALL
  28. __write_integer(char* buf, ios_base::fmtflags flags, long x);
  29.  
  30. // The function copy_cstring is used to initialize a string
  31. // with a C-style string.  Used to initialize the month and weekday
  32. // tables in time_get and time_put.  Called only by _Init_timeinfo
  33. // so its name does not require leading underscores.
  34.  
  35. static inline void copy_cstring(const char * s, string& v) {
  36.   copy(s, s + strlen(s), back_insert_iterator<string >(v));
  37. }
  38.  
  39. // default "C" values for month and day names
  40.  
  41.   const char default_dayname[][14] = {
  42.     "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
  43.     "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
  44.     "Friday", "Saturday"};
  45.  
  46.   const char default_monthname[][24] = {
  47.     "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  48.     "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
  49.     "January", "February", "March", "April", "May", "June",
  50.     "July", "August", "September", "October", "November", "December"};
  51.  
  52. // _Init_time_info: initialize table with
  53. // "C" values (note these are not defined in the C standard, so this
  54. // is somewhat arbitrary).
  55.  
  56. void _STLP_CALL _Init_timeinfo(_Time_Info& table) {
  57.   int i;
  58.   for (i = 0; i < 14; ++i)
  59.     copy_cstring(default_dayname[i], table._M_dayname[i]);
  60.   for (i = 0; i < 24; ++i)
  61.     copy_cstring(default_monthname[i], table._M_monthname[i]);
  62.   copy_cstring("AM", table._M_am_pm[0]);
  63.   copy_cstring("PM", table._M_am_pm[1]);
  64.   copy_cstring("%H:%M:%S", table._M_time_format);
  65.   copy_cstring("%m/%d/%y",  table._M_date_format);
  66.   copy_cstring("%a %b %e %H:%M:%S %Y", table._M_date_time_format);
  67. }
  68.  
  69. void _STLP_CALL _Init_timeinfo(_Time_Info& table, _Locale_time * time) {
  70.   int i;
  71.   for (i = 0; i < 7; ++i)
  72.     copy_cstring(_Locale_abbrev_dayofweek(time)[i],
  73.          table._M_dayname[i]);
  74.   for (i = 0; i < 7; ++i)
  75.     copy_cstring(_Locale_full_dayofweek(time)[i],
  76.          table._M_dayname[i+7]); 
  77.   for (i = 0; i < 12; ++i)
  78.     copy_cstring(_Locale_abbrev_monthname(time)[i],
  79.          table._M_monthname[i]);
  80.   for (i = 0; i < 12; ++i)
  81.     copy_cstring(_Locale_full_monthname(time)[i],
  82.          table._M_monthname[i+12]);
  83.   copy_cstring(_Locale_am_str(time),
  84.          table._M_am_pm[0]);
  85.   copy_cstring(_Locale_pm_str(time),
  86.            table._M_am_pm[1]);
  87.   copy_cstring(_Locale_t_fmt(time), table._M_time_format);
  88.   copy_cstring(_Locale_d_fmt(time), table._M_date_format);
  89.   copy_cstring(_Locale_d_t_fmt(time), table._M_date_time_format);
  90.   copy_cstring(_Locale_long_d_fmt(time), table._M_long_date_format);
  91.   copy_cstring(_Locale_long_d_t_fmt(time), table._M_long_date_time_format);
  92. }
  93.  
  94. inline char* __subformat(string format, char*& buf, 
  95.              const _Time_Info&  table, const tm* t) {
  96.   const char * cp = format.data();
  97.   const char * cp_end = cp + format.size();
  98.   while (cp != cp_end) {
  99.     if (*cp == '%') {
  100.         char mod = 0;
  101.       ++cp;
  102.       if(*cp == '#') {
  103.         mod = *cp; ++cp;
  104.       }
  105.       buf = __write_formatted_time(buf, *cp++, mod, table, t);
  106.     } else
  107.       *buf++ = *cp++;
  108.   }
  109.   return buf;
  110. }
  111.  
  112. /* The number of days from the first day of the first ISO week of this
  113.    year to the year day YDAY with week day WDAY.  ISO weeks start on
  114.    Monday; the first ISO week has the year's first Thursday.  YDAY may
  115.    be as small as YDAY_MINIMUM.  */
  116. #define __ISO_WEEK_START_WDAY 1 /* Monday */
  117. #define __ISO_WEEK1_WDAY 4 /* Thursday */
  118. #define __YDAY_MINIMUM (-366)
  119. #define __TM_YEAR_BASE 1900
  120. static int
  121. __iso_week_days (int yday, int wday)
  122. {
  123.   /* Add enough to the first operand of % to make it nonnegative.  */
  124.   int big_enough_multiple_of_7 = (-__YDAY_MINIMUM / 7 + 2) * 7;
  125.   return (yday
  126.       - (yday - wday + __ISO_WEEK1_WDAY + big_enough_multiple_of_7) % 7
  127.       + __ISO_WEEK1_WDAY - __ISO_WEEK_START_WDAY);
  128. }
  129.  
  130. #define    __is_leap(year)    \
  131.   ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
  132.  
  133. #define __hour12(hour) \
  134.   (((hour) % 12 == 0) ? (12) : (hour) % 12)
  135.  
  136. char * __write_formatted_time(char* buf, char format, char modifier,
  137.                   const _Time_Info& table, const tm* t) {
  138.   switch(format) {
  139.     case 'a':
  140.       return copy(table._M_dayname[t->tm_wday].begin(),
  141.               table._M_dayname[t->tm_wday].end(),
  142.               buf);
  143.  
  144.     case 'A':
  145.       return copy(table._M_dayname[t->tm_wday+7].begin(),
  146.               table._M_dayname[t->tm_wday+7].end(),
  147.               buf);
  148.  
  149.     case 'b':
  150.       return copy(table._M_monthname[t->tm_mon].begin(),
  151.               table._M_monthname[t->tm_mon].end(),
  152.               buf);
  153.  
  154.     case 'B':
  155.       return copy(table._M_monthname[t->tm_mon+12].begin(),
  156.          table._M_monthname[t->tm_mon+12].end(),
  157.          buf);
  158.  
  159.     case 'c': {
  160.       const char * cp = (modifier != '#') ? table._M_date_time_format.data():\
  161.                                              table._M_long_date_time_format.data();
  162.       const char* cp_end = (modifier != '#') ? cp + table._M_date_time_format.size():\
  163.                                                 cp + table._M_long_date_time_format.size();
  164.       char mod = 0;
  165.       while (cp != cp_end) {
  166.     if (*cp == '%') {
  167.       ++cp; if(*cp == '#') mod = *cp++; else mod = 0;
  168.       buf = __write_formatted_time(buf, *cp++, mod, table, t);
  169.     }
  170.     else
  171.       *buf++ = *cp++;
  172.       }
  173.       return buf;
  174.     }
  175.  
  176.     case 'd': 
  177.       sprintf(buf, (modifier != '#')?"%.2ld":"%ld", (long)t->tm_mday);
  178.       return ((long)t->tm_mday < 10L && modifier == '#')?buf+1:buf + 2;
  179.  
  180.     case 'e':
  181.       sprintf(buf, "%2ld", (long)t->tm_mday);
  182.       return buf + 2;
  183.  
  184.     case 'H':
  185.       sprintf(buf, (modifier != '#')?"%.2ld":"%ld", (long)t->tm_hour);
  186.       return ((long)t->tm_hour < 10L && modifier == '#')?buf+1:buf + 2;
  187.  
  188.     case 'I':
  189.       sprintf(buf, (modifier != '#')?"%.2ld":"%ld", (long)__hour12(t->tm_hour));
  190.       return ((long)__hour12(t->tm_hour) < 10L && modifier == '#')?buf+1:buf + 2;
  191.  
  192.     case 'j':
  193.       return __write_integer(buf, 0, (long)((long)t->tm_yday + 1));
  194.  
  195.     case 'm':
  196.       sprintf(buf, (modifier != '#')?"%.2ld":"%ld", (long)t->tm_mon + 1);
  197.       return ((long)(t->tm_mon + 1) < 10L && modifier == '#')?buf+1:buf + 2;
  198.  
  199.     case 'M':
  200.       sprintf(buf, (modifier != '#')?"%.2ld":"%ld", (long)t->tm_min);
  201.       return ((long)t->tm_min < 10L && modifier == '#')?buf+1:buf + 2;
  202.  
  203.     case 'p':
  204.       return copy(table._M_am_pm[t->tm_hour/12].begin(),
  205.               table._M_am_pm[t->tm_hour/12].end(),
  206.              buf);
  207.  
  208.     case 'S': // pad with zeros
  209.        sprintf(buf, (modifier != '#')?"%.2ld":"%ld", (long)t->tm_sec);
  210.        return ((long)t->tm_sec < 10L && modifier == '#')?buf+1:buf + 2;
  211.  
  212.     case 'U':
  213.       return __write_integer(buf, 0, 
  214.                 long((t->tm_yday - t->tm_wday + 7) / 7));
  215.       //      break;
  216.  
  217.     case 'w':
  218.       return __write_integer(buf, 0, (long)t->tm_wday);
  219.       //      break;
  220.  
  221.     case 'W':
  222.       return __write_integer(buf, 0,
  223.                      (long)(t->tm_wday == 0       ?
  224.                   (t->tm_yday + 1) / 7 :
  225.                   (t->tm_yday + 8 - t->tm_wday) / 7));
  226.  
  227.     case'x': {
  228.       const char * cp = (modifier != '#') ? table._M_date_format.data():\
  229.                                              table._M_long_date_format.data();
  230.       const char* cp_end = (modifier != '#') ? cp + table._M_date_format.size():\
  231.                                                 cp + table._M_long_date_format.size();
  232.       char mod = 0;
  233.       while (cp != cp_end) {
  234.     if (*cp == '%') {
  235.       ++cp; if(*cp == '#') mod = *cp++; else mod = 0;
  236.       buf = __write_formatted_time(buf, *cp++, mod, table, t);
  237.     }
  238.     else
  239.       *buf++ = *cp++;
  240.       }
  241.       return buf;
  242.     }
  243.  
  244.     case 'X': {
  245.       const char * cp = table._M_time_format.data();
  246.       const char* cp_end = cp + table._M_time_format.size();
  247.       char mod = 0;
  248.       while (cp != cp_end) {
  249.     if (*cp == '%') {
  250.       ++cp; if(*cp == '#') mod = *cp++; else mod = 0;
  251.       buf = __write_formatted_time(buf, *cp++, mod, table, t);
  252.     }
  253.     else
  254.       *buf++ = *cp++;
  255.       }
  256.       return buf;
  257.     }
  258.     case 'y':
  259.       return __write_integer(buf, 0, (long)((long)(t->tm_year + 1900) % 100));
  260.  
  261.     case 'Y':
  262.       return __write_integer(buf, 0, (long)((long)t->tm_year + 1900));
  263.  
  264.     case '%':
  265.       *buf++ = '%';
  266.       return buf;
  267.  
  268. #ifdef __GNUC__
  269.  
  270.       // fbp : at least on SUN 
  271. # if defined ( _STLP_UNIX ) && ! defined (__linux__)
  272. #  define __USE_BSD 1
  273. # endif
  274.  
  275.    /*********************************************
  276.     *     JGS, handle various extensions        *
  277.     *********************************************/
  278.  
  279.     case 'h': /* POSIX.2 extension */
  280.       // same as 'b', abbrev month name
  281.       return copy(table._M_monthname[t->tm_mon].begin(),
  282.               table._M_monthname[t->tm_mon].end(),
  283.               buf);
  284.  
  285.     case 'C': /* POSIX.2 extension */
  286.       // same as 'd', the day 
  287.       sprintf(buf, "%2ld", (long)t->tm_mday);
  288.       return buf + 2;
  289.  
  290.     case 'D': /* POSIX.2 extension */
  291.       // same as 'x'
  292.       return __subformat(table._M_date_format, buf, table, t);
  293.  
  294.     case 'k': /* GNU extension */
  295.       sprintf(buf, "%2ld", (long)t->tm_hour);
  296.       return buf + 2;
  297.  
  298.     case 'l': /* GNU extension */
  299.       sprintf(buf, "%2ld", (long)t->tm_hour % 12);
  300.       return buf + 2;
  301.  
  302.     case 'n': /* POSIX.2 extension */
  303.       *buf++ = '\n';
  304.       return buf;
  305.  
  306.     case 'R': /* GNU extension */
  307.       return __subformat("%H:%M", buf, table, t);
  308.  
  309.     case 'r': /* POSIX.2 extension */
  310.       return __subformat("%I:%M:%S %p", buf, table, t);
  311.  
  312.     case 'T': /* POSIX.2 extension.  */
  313.       return __subformat("%H:%M:%S", buf, table, t);
  314.  
  315.     case 't': /* POSIX.2 extension.  */
  316.       *buf++ = '\t';
  317.       return buf;
  318.  
  319.     case 'u': /* POSIX.2 extension.  */
  320.       return __write_integer(buf, 0, long((t->tm_wday - 1 + 7)) % 7 + 1);
  321.  
  322.     case 's': {
  323.       time_t __t;
  324.       __t = mktime ((tm*)t);
  325.       return __write_integer(buf, 0, (long)__t );
  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)),
  335.                 t->tm_wday);
  336.       } else {
  337.     int d = __iso_week_days (t->tm_yday - (365 + __is_leap (year)),
  338.                    t->tm_wday);
  339.     if (0 <= d) {
  340.       /* This ISO week belongs to the next year.  */
  341.       year++;
  342.       days = d;
  343.     }
  344.       }
  345.       switch (format) {
  346.       case 'g':
  347.     return __write_integer(buf, 0, (long)(year % 100 + 100) % 100);
  348.       case 'G':
  349.     return __write_integer(buf, 0, (long)year);
  350.       default:
  351.     return __write_integer(buf, 0, (long)days / 7 + 1);
  352.       }
  353.     }
  354.  
  355. # if defined ( _STLP_USE_GLIBC  ) && ! defined (__CYGWIN__)
  356.     case 'z':        /* GNU extension.  */
  357.       if (t->tm_isdst < 0)
  358.     break;
  359.       {
  360.     int diff;
  361. #if defined(__USE_BSD) || defined(__BEOS__)
  362.     diff = t->tm_gmtoff;
  363. #else
  364.     diff = t->__tm_gmtoff;
  365. #endif    
  366.     if (diff < 0) {
  367.       *buf++ = '-';
  368.       diff = -diff;
  369.     } else
  370.       *buf++ = '+';
  371.     
  372.     diff /= 60;
  373.     sprintf(buf, "%.4d", (diff / 60) * 100 + diff % 60);
  374.     return buf + 4;
  375.       }
  376. # endif /* __GLIBC__ */
  377. #endif /* __GNUC__ */
  378.  
  379.     default:
  380.       //      return buf;
  381.       break;
  382.   }
  383.   return buf;
  384. }
  385.  
  386. time_base::dateorder _STLP_CALL
  387. __get_date_order(_Locale_time* time)
  388. {
  389.   const char * fmt = _Locale_d_fmt(time);
  390.   char first, second, third;
  391.  
  392.   while (*fmt != 0 && *fmt != '%') ++fmt;
  393.   if (*fmt == 0)
  394.     return time_base::no_order;
  395.   first = *++fmt;
  396.   while (*fmt != 0 && *fmt != '%') ++fmt;
  397.   if (*fmt == 0)
  398.     return time_base::no_order;
  399.   second = *++fmt;
  400.   while (*fmt != 0 && *fmt != '%') ++fmt;
  401.   if (*fmt == 0)
  402.     return time_base::no_order;
  403.   third = *++fmt;
  404.  
  405.   switch (first) {
  406.     case 'd':
  407.       return (second == 'm' && third == 'y') ? time_base::dmy
  408.                          : time_base::no_order;
  409.     case 'm':
  410.       return (second == 'd' && third == 'y') ? time_base::mdy
  411.                          : time_base::no_order;
  412.     case 'y':
  413.       switch (second) {
  414.     case 'd':
  415.       return third == 'm' ? time_base::ydm : time_base::no_order;
  416.         case 'm':
  417.       return third == 'd' ? time_base::ymd : time_base::no_order;
  418.     default:
  419.       return time_base::no_order;
  420.       }
  421.     default:
  422.       return time_base::no_order;
  423.   }
  424. }
  425.  
  426. #if !defined(_STLP_NO_FORCE_INSTANTIATE)
  427. template class time_get<char, istreambuf_iterator<char, char_traits<char> > >;
  428. // template class time_get<char, const char*>;
  429. template class time_put<char, ostreambuf_iterator<char, char_traits<char> > >;
  430. // template class time_put<char, char*>;
  431.  
  432. #ifndef _STLP_NO_WCHAR_T
  433. template class time_get<wchar_t, istreambuf_iterator<wchar_t, char_traits<wchar_t> > >;
  434. // template class time_get<wchar_t, const wchar_t*>;
  435. template class time_put<wchar_t, ostreambuf_iterator<wchar_t, char_traits<wchar_t> > >;
  436. // template class time_put<wchar_t, wchar_t*>;
  437. #endif /* INSTANTIATE_WIDE_STREAMS */
  438.  
  439. #endif
  440.  
  441. _STLP_END_NAMESPACE
  442.