OS_NS_time.cpp

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

Generated on Thu Nov 9 09:41:58 2006 for ACE by doxygen 1.3.6