OS_NS_time.cpp

Go to the documentation of this file.
00001 // $Id: OS_NS_time.cpp 80826 2008-03-04 14:51:23Z wotte $
00002 
00003 #include "ace/OS_NS_time.h"
00004 
00005 ACE_RCSID(ace, OS_NS_time, "$Id: OS_NS_time.cpp 80826 2008-03-04 14:51:23Z wotte $")
00006 
00007 #if !defined (ACE_HAS_INLINED_OSCALLS)
00008 # include "ace/OS_NS_time.inl"
00009 #endif /* ACE_HAS_INLINED_OSCALLS */
00010 
00011 #if defined (ACE_LACKS_STRPTIME)
00012 # include "ace/os_include/os_ctype.h"
00013 #endif /* ACE_LACKS_STRPTIME */
00014 
00015 #include "ace/OS_NS_Thread.h"
00016 #include "ace/Object_Manager_Base.h"
00017 
00018 #if defined (ACE_HAS_WINCE)
00019 #  include "ace/OS_NS_stdio.h"     /* Need ACE_OS::sprintf() */
00020 
00021 namespace
00022 {
00023   ACE_TCHAR const * const ACE_OS_day_of_week_name[] =
00024     {
00025       ACE_TEXT ("Sun"),
00026       ACE_TEXT ("Mon"),
00027       ACE_TEXT ("Tue"),
00028       ACE_TEXT ("Wed"),
00029       ACE_TEXT ("Thu"),
00030       ACE_TEXT ("Fri"),
00031       ACE_TEXT ("Sat")
00032     };
00033 
00034   ACE_TCHAR const * const ACE_OS_month_name[] =
00035     {
00036       ACE_TEXT ("Jan"),
00037       ACE_TEXT ("Feb"),
00038       ACE_TEXT ("Mar"),
00039       ACE_TEXT ("Apr"),
00040       ACE_TEXT ("May"),
00041       ACE_TEXT ("Jun"),
00042       ACE_TEXT ("Jul"),
00043       ACE_TEXT ("Aug"),
00044       ACE_TEXT ("Sep"),
00045       ACE_TEXT ("Oct"),
00046       ACE_TEXT ("Nov"),
00047       ACE_TEXT ("Dec")
00048     };
00049 
00050   static ACE_TCHAR const ACE_OS_CTIME_R_FMTSTR[] = ACE_TEXT ("%3s %3s %02d %02d:%02d:%02d %04d\n");
00051 } /* end blank namespace */
00052 #endif /* ACE_HAS_WINCE */
00053 
00054 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
00055 
00056 # if defined (ACE_HAS_WINCE)
00057 ACE_TCHAR *
00058 ACE_OS::ctime_r (const time_t *clock, ACE_TCHAR *buf, int buflen)
00059 {
00060   // buflen must be at least 26 wchar_t long.
00061   if (buflen < 26)              // Again, 26 is a magic number.
00062     {
00063       errno = ERANGE;
00064       return 0;
00065     }
00066   // This is really stupid, converting FILETIME to timeval back and
00067   // forth.  It assumes FILETIME and DWORDLONG are the same structure
00068   // internally.
00069   ULARGE_INTEGER _100ns;
00070   _100ns.QuadPart = (DWORDLONG) *clock * 10000 * 1000
00071                      + ACE_Time_Value::FILETIME_to_timval_skew;
00072   FILETIME file_time;
00073   file_time.dwLowDateTime = _100ns.LowPart;
00074   file_time.dwHighDateTime = _100ns.HighPart;
00075 
00076   FILETIME localtime;
00077   SYSTEMTIME systime;
00078   FileTimeToLocalFileTime (&file_time, &localtime);
00079   FileTimeToSystemTime (&localtime, &systime);
00080   ACE_OS::sprintf (buf, ACE_OS_CTIME_R_FMTSTR,
00081                    ACE_OS_day_of_week_name[systime.wDayOfWeek],
00082                    ACE_OS_month_name[systime.wMonth - 1],
00083                    systime.wDay,
00084                    systime.wHour,
00085                    systime.wMinute,
00086                    systime.wSecond,
00087                    systime.wYear);
00088   return buf;
00089 }
00090 # endif /* ACE_HAS_WINCE */
00091 
00092 # if defined (ACE_LACKS_DIFFTIME)
00093 double
00094 ACE_OS::difftime (time_t t1, time_t t0)
00095 {
00096   /* return t1 - t0 in seconds */
00097   struct tm tms[2], *ptms[2], temp;
00098   double seconds;
00099   int swap = 0;
00100 
00101   /* extract the tm structure from time_t */
00102   ptms[1] = ::gmtime_r (&t1, &tms[1]);
00103   if (ptms[1] == 0) return 0.0;
00104 
00105   ptms[0] = ::gmtime_r (&t0, &tms[0]);
00106   if (ptms[0] == 0) return 0.0;
00107 
00108     /* make sure t1 is > t0 */
00109   if (tms[1].tm_year < tms[0].tm_year)
00110     swap = 1;
00111   else if (tms[1].tm_year == tms[0].tm_year)
00112     {
00113       if (tms[1].tm_yday < tms[0].tm_yday)
00114         swap = 1;
00115       else if (tms[1].tm_yday == tms[0].tm_yday)
00116         {
00117           if (tms[1].tm_hour < tms[0].tm_hour)
00118             swap = 1;
00119           else if (tms[1].tm_hour == tms[0].tm_hour)
00120             {
00121               if (tms[1].tm_min < tms[0].tm_min)
00122                 swap = 1;
00123               else if (tms[1].tm_min == tms[0].tm_min)
00124                 {
00125                   if (tms[1].tm_sec < tms[0].tm_sec)
00126                     swap = 1;
00127                 }
00128             }
00129         }
00130     }
00131 
00132   if (swap)
00133     temp = tms[0], tms[0] = tms[1], tms[1] = temp;
00134 
00135   seconds = 0.0;
00136   if (tms[1].tm_year > tms[0].tm_year)
00137     {
00138       // Accumulate the time until t[0] catches up to t[1]'s year.
00139       seconds = 60 - tms[0].tm_sec;
00140       tms[0].tm_sec = 0;
00141       tms[0].tm_min += 1;
00142       seconds += 60 * (60 - tms[0].tm_min);
00143       tms[0].tm_min = 0;
00144       tms[0].tm_hour += 1;
00145       seconds += 60*60 * (24 - tms[0].tm_hour);
00146       tms[0].tm_hour = 0;
00147       tms[0].tm_yday += 1;
00148 
00149 #   define ISLEAPYEAR(y) ((y)&3u?0:(y)%25u?1:(y)/25u&12?0:1)
00150 
00151       if (ISLEAPYEAR(tms[0].tm_year))
00152         seconds += 60*60*24 * (366 - tms[0].tm_yday);
00153       else
00154         seconds += 60*60*24 * (365 - tms[0].tm_yday);
00155 
00156       tms[0].tm_yday = 0;
00157       tms[0].tm_year += 1;
00158 
00159       while (tms[1].tm_year > tms[0].tm_year)
00160         {
00161           if (ISLEAPYEAR(tms[0].tm_year))
00162             seconds += 60*60*24 * 366;
00163           else
00164             seconds += 60*60*24 * 365;
00165 
00166           tms[0].tm_year += 1;
00167         }
00168 
00169 #   undef ISLEAPYEAR
00170 
00171     }
00172   else
00173     {
00174       // Normalize
00175       if (tms[1].tm_sec < tms[0].tm_sec)
00176         {
00177           if (tms[1].tm_min == 0)
00178             {
00179               if (tms[1].tm_hour == 0)
00180                 {
00181                   tms[1].tm_yday -= 1;
00182                   tms[1].tm_hour += 24;
00183                 }
00184               tms[1].tm_hour -= 1;
00185               tms[1].tm_min += 60;
00186             }
00187           tms[1].tm_min -= 1;
00188           tms[1].tm_sec += 60;
00189         }
00190       tms[1].tm_sec -= tms[0].tm_sec;
00191 
00192       if (tms[1].tm_min < tms[0].tm_min)
00193         {
00194           if (tms[1].tm_hour == 0)
00195             {
00196               tms[1].tm_yday -= 1;
00197               tms[1].tm_hour += 24;
00198             }
00199           tms[1].tm_hour -= 1;
00200           tms[1].tm_min += 60;
00201         }
00202       tms[1].tm_min -= tms[0].tm_min;
00203 
00204       if (tms[1].tm_hour < tms[0].tm_hour)
00205         {
00206           tms[1].tm_yday -= 1;
00207           tms[1].tm_hour += 24;
00208         }
00209       tms[1].tm_hour -= tms[0].tm_hour;
00210 
00211       tms[1].tm_yday -= tms[0].tm_yday;
00212     }
00213 
00214   // accumulate the seconds
00215   seconds += tms[1].tm_sec;
00216   seconds += 60 * tms[1].tm_min;
00217   seconds += 60*60 * tms[1].tm_hour;
00218   seconds += 60*60*24 * tms[1].tm_yday;
00219 
00220   return seconds;
00221 }
00222 # endif /* ACE_LACKS_DIFFTIME */
00223 
00224 struct tm *
00225 ACE_OS::localtime_r (const time_t *t, struct tm *res)
00226 {
00227   ACE_OS_TRACE ("ACE_OS::localtime_r");
00228 #if defined (ACE_HAS_REENTRANT_FUNCTIONS)
00229 # if defined (DIGITAL_UNIX)
00230   ACE_OSCALL_RETURN (::_Plocaltime_r (t, res), struct tm *, 0);
00231 # else
00232   ACE_OSCALL_RETURN (::localtime_r (t, res), struct tm *, 0);
00233 # endif /* DIGITAL_UNIX */
00234 #elif defined (ACE_HAS_TR24731_2005_CRT)
00235   ACE_SECURECRTCALL (localtime_s (res, t), struct tm *, 0, res);
00236   return res;
00237 #elif !defined (ACE_HAS_WINCE)
00238   ACE_OS_GUARD
00239 
00240   ACE_UNUSED_ARG (res);
00241   struct tm * res_ptr;
00242   ACE_OSCALL (::localtime (t), struct tm *, 0, res_ptr);
00243   if (res_ptr == 0)
00244     return 0;
00245   else
00246     {
00247       *res = *res_ptr;
00248       return res;
00249     }
00250 #elif defined (ACE_HAS_WINCE)
00251   // This is really stupid, converting FILETIME to timeval back and
00252   // forth.  It assumes FILETIME and DWORDLONG are the same structure
00253   // internally.
00254 
00255   TIME_ZONE_INFORMATION pTz;
00256 
00257   const unsigned short int __mon_yday[2][13] =
00258   {
00259     /* Normal years.  */
00260     { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
00261     /* Leap years.  */
00262     { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
00263   };
00264 
00265   ULARGE_INTEGER _100ns;
00266   ::GetTimeZoneInformation (&pTz);
00267 
00268   _100ns.QuadPart = (DWORDLONG) *t * 10000 * 1000 + ACE_Time_Value::FILETIME_to_timval_skew;
00269   FILETIME file_time;
00270   file_time.dwLowDateTime = _100ns.LowPart;
00271   file_time.dwHighDateTime = _100ns.HighPart;
00272 
00273   FILETIME localtime;
00274   SYSTEMTIME systime;
00275   FileTimeToLocalFileTime (&file_time, &localtime);
00276   FileTimeToSystemTime (&localtime, &systime);
00277 
00278   res->tm_hour = systime.wHour;
00279 
00280   if(pTz.DaylightBias!=0)
00281     res->tm_isdst = 1;
00282   else
00283     res->tm_isdst = 1;
00284 
00285    int iLeap;
00286    iLeap = (res->tm_year % 4 == 0 && (res->tm_year% 100 != 0 || res->tm_year % 400 == 0));
00287    // based on leap select which group to use
00288 
00289    res->tm_mday = systime.wDay;
00290    res->tm_min = systime.wMinute;
00291    res->tm_mon = systime.wMonth - 1;
00292    res->tm_sec = systime.wSecond;
00293    res->tm_wday = systime.wDayOfWeek;
00294    res->tm_yday = __mon_yday[iLeap][systime.wMonth] + systime.wDay;
00295    res->tm_year = systime.wYear;// this the correct year but bias the value to start at the 1900
00296    res->tm_year = res->tm_year - 1900;
00297 
00298    return res;
00299 #else
00300   // @@ Same as ACE_OS::localtime (), you need to implement it
00301   //    yourself.
00302   ACE_UNUSED_ARG (t);
00303   ACE_UNUSED_ARG (res);
00304   ACE_NOTSUP_RETURN (0);
00305 #endif /* ACE_HAS_REENTRANT_FUNCTIONS */
00306 }
00307 
00308 time_t
00309 ACE_OS::mktime (struct tm *t)
00310 {
00311   ACE_OS_TRACE ("ACE_OS::mktime");
00312 #   if defined (ACE_HAS_WINCE)
00313   SYSTEMTIME t_sys;
00314   FILETIME t_file;
00315   t_sys.wSecond = t->tm_sec;
00316   t_sys.wMinute = t->tm_min;
00317   t_sys.wHour = t->tm_hour;
00318   t_sys.wDay = t->tm_mday;
00319   t_sys.wMonth = t->tm_mon + 1;  // SYSTEMTIME is 1-indexed, tm is 0-indexed
00320   t_sys.wYear = t->tm_year + 1900; // SYSTEMTIME is real; tm is since 1900
00321   t_sys.wDayOfWeek = t->tm_wday;  // Ignored in below function call.
00322   if (SystemTimeToFileTime (&t_sys, &t_file) == 0)
00323     return -1;
00324   ACE_Time_Value tv (t_file);
00325   return tv.sec ();
00326 #   else
00327 #     if defined (ACE_HAS_THREADS)  &&  !defined (ACE_HAS_MT_SAFE_MKTIME)
00328   ACE_OS_GUARD
00329 #     endif /* ACE_HAS_THREADS  &&  ! ACE_HAS_MT_SAFE_MKTIME */
00330 
00331   ACE_OSCALL_RETURN (ACE_STD_NAMESPACE::mktime (t), time_t, (time_t) -1);
00332 #   endif /* ACE_HAS_WINCE */
00333 }
00334 
00335 #if defined (ACE_HAS_POWERPC_TIMER) && defined (ghs)
00336 void
00337 ACE_OS::readPPCTimeBase (u_long &most, u_long &least)
00338 {
00339   ACE_OS_TRACE ("ACE_OS::readPPCTimeBase");
00340 
00341   // This function can't be inline because it depends on the arguments
00342   // being in particular registers (r3 and r4), in conformance with the
00343   // EABI standard.  It would be nice if we knew how to put the variable
00344   // names directly into the assembler instructions . . .
00345   asm("aclock:");
00346   asm("mftb  r5,TBU");
00347   asm("mftb  r6,TBL");
00348   asm("mftb  r7,TBU");
00349   asm("cmpw  r5,r7");
00350   asm("bne   aclock");
00351 
00352   asm("stw r5, 0(r3)");
00353   asm("stw r6, 0(r4)");
00354 }
00355 #endif /* ACE_HAS_POWERPC_TIMER && ghs */
00356 
00357 #if defined (ACE_LACKS_STRPTIME) && !defined (ACE_REFUSE_STRPTIME_EMULATION)
00358 char *
00359 ACE_OS::strptime_emulation (const char *buf, const char *format, struct tm *tm)
00360 {
00361   int bi = 0;
00362   int fi = 0;
00363   int percent = 0;
00364 
00365   if (!buf || !format)
00366     return 0;
00367 
00368   while (format[fi] != '\0')
00369     {
00370       if (percent)
00371         {
00372           percent = 0;
00373           switch (format[fi])
00374             {
00375             case '%':                        // an escaped %
00376               if (buf[bi] == '%')
00377                 {
00378                   fi++; bi++;
00379                 }
00380               else
00381                 return const_cast<char*> (buf + bi);
00382               break;
00383 
00384               /* not supported yet: weekday via locale long/short names
00385                  case 'a':                        / * weekday via locale * /
00386                  / * FALL THROUGH * /
00387                  case 'A':                        / * long/short names * /
00388                  break;
00389                  */
00390 
00391               /* not supported yet:
00392                  case 'b':                        / * month via locale * /
00393                  / * FALL THROUGH * /
00394                  case 'B':                        / * long/short names * /
00395                  / * FALL THROUGH * /
00396                  case 'h':
00397                  break;
00398                  */
00399 
00400               /* not supported yet:
00401                  case 'c':                        / * %x %X * /
00402                  break;
00403                  */
00404 
00405               /* not supported yet:
00406                  case 'C':                        / * date & time -  * /
00407                  / * locale long format * /
00408                  break;
00409                  */
00410 
00411             case 'd':                        /* day of month (1-31) */
00412               /* FALL THROUGH */
00413             case 'e':
00414               if (!ACE_OS::strptime_getnum
00415                      (buf + bi, &tm->tm_mday, &bi, &fi, 1, 31))
00416                 return const_cast<char*> (buf + bi);
00417 
00418               break;
00419 
00420             case 'D':                        /* %m/%d/%y */
00421               if (!ACE_OS::strptime_getnum
00422                      (buf + bi, &tm->tm_mon, &bi, &fi, 1, 12))
00423                 return const_cast<char*> (buf + bi);
00424 
00425               fi--;
00426               tm->tm_mon--;
00427 
00428               if (buf[bi] != '/')
00429                 return const_cast<char*> (buf + bi);
00430 
00431               bi++;
00432 
00433               if (!ACE_OS::strptime_getnum
00434                      (buf + bi, &tm->tm_mday, &bi, &fi, 1, 31))
00435                 return const_cast<char*> (buf + bi);
00436 
00437               fi--;
00438               if (buf[bi] != '/')
00439                 return const_cast<char*> (buf + bi);
00440               bi++;
00441               if (!ACE_OS::strptime_getnum
00442                      (buf + bi, &tm->tm_year, &bi, &fi, 0, 99))
00443                 return const_cast<char*> (buf + bi);
00444               if (tm->tm_year < 69)
00445                 tm->tm_year += 100;
00446               break;
00447 
00448             case 'H':                        /* hour (0-23) */
00449               /* FALL THROUGH */
00450             case 'k':
00451               if (!ACE_OS::strptime_getnum
00452                      (buf + bi, &tm->tm_hour, &bi, &fi, 0, 23))
00453                 return const_cast<char*> (buf + bi);
00454               break;
00455 
00456               /* not supported yet:
00457                  case 'I':                        / * hour (0-12) * /
00458                  / * FALL THROUGH * /
00459                  case 'l':
00460                  break;
00461                  */
00462 
00463             case 'j':                        /* day of year (0-366) */
00464               if (!ACE_OS::strptime_getnum
00465                      (buf + bi, &tm->tm_yday, &bi, &fi, 1, 366))
00466                 return const_cast<char*> (buf + bi);
00467 
00468               tm->tm_yday--;
00469               break;
00470 
00471             case 'm':                        /* an escaped % */
00472               if (!ACE_OS::strptime_getnum
00473                      (buf + bi, &tm->tm_mon, &bi, &fi, 1, 12))
00474                 return const_cast<char*> (buf + bi);
00475 
00476               tm->tm_mon--;
00477               break;
00478 
00479             case 'M':                        /* minute (0-59) */
00480               if (!ACE_OS::strptime_getnum
00481                      (buf + bi, &tm->tm_min, &bi, &fi, 0, 59))
00482                 return const_cast<char*> (buf + bi);
00483 
00484               break;
00485 
00486               /* not supported yet:
00487                  case 'p':                        / * am or pm for locale * /
00488                  break;
00489                  */
00490 
00491               /* not supported yet:
00492                  case 'r':                        / * %I:%M:%S %p * /
00493                  break;
00494                  */
00495 
00496             case 'R':                        /* %H:%M */
00497               if (!ACE_OS::strptime_getnum
00498                      (buf + bi, &tm->tm_hour, &bi, &fi, 0, 23))
00499                 return const_cast<char*> (buf + bi);
00500 
00501               fi--;
00502               if (buf[bi] != ':')
00503                 return const_cast<char*> (buf + bi);
00504               bi++;
00505               if (!ACE_OS::strptime_getnum
00506                      (buf + bi, &tm->tm_min, &bi, &fi, 0, 59))
00507                 return const_cast<char*> (buf + bi);
00508 
00509               break;
00510 
00511             case 'S':                        /* seconds (0-61) */
00512               if (!ACE_OS::strptime_getnum
00513                      (buf + bi, &tm->tm_sec, &bi, &fi, 0, 61))
00514                 return const_cast<char*> (buf + bi);
00515               break;
00516 
00517             case 'T':                        /* %H:%M:%S */
00518               if (!ACE_OS::strptime_getnum
00519                      (buf + bi, &tm->tm_hour, &bi, &fi, 0, 23))
00520                 return const_cast<char*> (buf + bi);
00521 
00522               fi--;
00523               if (buf[bi] != ':')
00524                 return const_cast<char*> (buf + bi);
00525               bi++;
00526               if (!ACE_OS::strptime_getnum
00527                      (buf + bi, &tm->tm_min, &bi, &fi, 0, 59))
00528                 return const_cast<char*> (buf + bi);
00529 
00530               fi--;
00531               if (buf[bi] != ':')
00532                 return const_cast<char*> (buf + bi);
00533               bi++;
00534               if (!ACE_OS::strptime_getnum
00535                      (buf + bi, &tm->tm_sec, &bi, &fi, 0, 61))
00536                 return const_cast<char*> (buf + bi);
00537 
00538               break;
00539 
00540             case 'w':                        /* day of week (0=Sun-6) */
00541               if (!ACE_OS::strptime_getnum
00542                      (buf + bi, &tm->tm_wday, &bi, &fi, 0, 6))
00543                 return const_cast<char*> (buf + bi);
00544 
00545               break;
00546 
00547               /* not supported yet: date, based on locale
00548                  case 'x':                        / * date, based on locale * /
00549                  break;
00550                  */
00551 
00552               /* not supported yet:
00553                  case 'X':                        / * time, based on locale * /
00554                  break;
00555                  */
00556 
00557             case 'y':                        /* the year - 1900 (0-99) */
00558               if (!ACE_OS::strptime_getnum
00559                      (buf + bi, &tm->tm_year, &bi, &fi, 0, 99))
00560                 return const_cast<char*> (buf + bi);
00561 
00562               if (tm->tm_year < 69)
00563                 tm->tm_year += 100;
00564               break;
00565 
00566             case 'Y':                        /* the full year (1999) */
00567               if (!ACE_OS::strptime_getnum
00568                      (buf + bi, &tm->tm_year, &bi, &fi, 0, 0))
00569                 return const_cast<char*> (buf + bi);
00570 
00571               tm->tm_year -= 1900;
00572               break;
00573 
00574             default:                        /* unrecognised */
00575               return const_cast<char*> (buf + bi);
00576             } /* switch (format[fi]) */
00577 
00578         }
00579       else
00580         { /* if (percent) */
00581           if (format[fi] == '%')
00582             {
00583               percent = 1;
00584               fi++;
00585             }
00586           else
00587             {
00588               if (format[fi] == buf[bi])
00589                 {
00590                   fi++;
00591                   bi++;
00592                 }
00593               else
00594                 return const_cast<char*> (buf + bi);
00595             }
00596         } /* if (percent) */
00597     } /* while (format[fi] */
00598 
00599   return const_cast<char*> (buf + bi);
00600 }
00601 
00602 int
00603 ACE_OS::strptime_getnum (const char *buf,
00604                          int *num,
00605                          int *bi,
00606                          int *fi,
00607                          int min,
00608                          int max)
00609 {
00610   int i = 0, tmp = 0;
00611 
00612   while (isdigit (buf[i]))
00613     {
00614       tmp = (tmp * 10) + (buf[i] - '0');
00615       if (max && (tmp > max))
00616         return 0;
00617       i++;
00618     }
00619 
00620   if (tmp < min)
00621     return 0;
00622   else if (i)
00623     {
00624       *num = tmp;
00625       (*fi)++;
00626       *bi += i;
00627       return 1;
00628     }
00629   else
00630     return 0;
00631 }
00632 #endif /* ACE_LACKS_STRPTIME && !ACE_REFUSE_STRPTIME_EMULATION */
00633 
00634 ACE_END_VERSIONED_NAMESPACE_DECL

Generated on Tue Feb 2 17:18:41 2010 for ACE by  doxygen 1.4.7