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