os/ossrv/genericopenlibs/cppstdlib/stl/src/time_facets.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     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