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