1349 lines
38 KiB
C
1349 lines
38 KiB
C
|
|
/*****************************************************************************/
|
||
|
|
/* SISCO SOFTWARE MODULE HEADER **********************************************/
|
||
|
|
/*****************************************************************************/
|
||
|
|
/* (c) Copyright Systems Integration Specialists Company, Inc., */
|
||
|
|
/* 2005 All Rights Reserved */
|
||
|
|
/* */
|
||
|
|
/* MODULE NAME : StdTimeW32.h */
|
||
|
|
/* PRODUCT(S) : Standard Time Management Library */
|
||
|
|
/* */
|
||
|
|
/* MODULE DESCRIPTION: */
|
||
|
|
/* Implementation of Standard Time Management Library Win32 Compatibility */
|
||
|
|
/* Layer. This module is compiled with STDTIMEW32_ENABLED on Windows to */
|
||
|
|
/* generate debugging code or to run emulation on Unix. To run on */
|
||
|
|
/* Windows, compile with STDTIMEW32_DISABLED. STDTIMEW32_ENABLED is */
|
||
|
|
/* required on Unix/Linux (that is, non-Windows) platforms. */
|
||
|
|
/* */
|
||
|
|
/* MODIFICATION LOG: */
|
||
|
|
/* Date Who Rev Comments */
|
||
|
|
/* -------- --- --- ----------------------------------------------------- */
|
||
|
|
/* 05/16/08 JRB 07 Fix DST adjustment in StdTimeW32LocalFileTimeToFileTime*/
|
||
|
|
/* 04/08/08 JRB 06 Chg FILETIME to portable STDTIME_WIN_FILETIME. */
|
||
|
|
/* 02/20/08 JRB 05 Use new simpler "TimeTypeEx", "StructTmEx" functions. */
|
||
|
|
/* 03/18/07 RLH 04 Enable GMT vs. LOC conversions to work on QNX; */
|
||
|
|
/* fix bug in Bool_StdTimeGmTimeR. */
|
||
|
|
/* 11/21/06 RLH 03 StdTimeRet no longer static, now in stdtime.c */
|
||
|
|
/* 06/07/06 RLH 02 Numerous features added, see stdtime.doc */
|
||
|
|
/* 01/18/06 RLH 01 Created */
|
||
|
|
/*****************************************************************************/
|
||
|
|
|
||
|
|
#include "stdtime.h"
|
||
|
|
|
||
|
|
#define STDTIMEW32_FT_TIMET_SCALE 10000000
|
||
|
|
#define STDTIMEW32_FT_TIMET_BASE_HI 0x019DB1DE
|
||
|
|
#define STDTIMEW32_FT_TIMET_BASE_LO 0xD53E8000
|
||
|
|
|
||
|
|
|
||
|
|
/*-***************************************************************************/
|
||
|
|
/* Bool_StdTimeGmTimeR - PRIVATE FUNCTION */
|
||
|
|
/* provide interface for gmtime_r where possible, otherwise gmtime. */
|
||
|
|
/* we provide thread safety for this function, if the operating system and */
|
||
|
|
/* runtime library allows for it. */
|
||
|
|
/*****************************************************************************/
|
||
|
|
|
||
|
|
STDTIME_BOOL Bool_StdTimeGmTimeR (
|
||
|
|
time_t * pTimeT,
|
||
|
|
struct tm * pStructTm)
|
||
|
|
{
|
||
|
|
|
||
|
|
if ((pTimeT == NULL) || (pStructTm == NULL))
|
||
|
|
{
|
||
|
|
return STDTIME_FALSE;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
#ifdef STDTIME_REENTRANT_GMTIME_LOCALTIME
|
||
|
|
|
||
|
|
if (gmtime_r (pTimeT, pStructTm) != 0)
|
||
|
|
{
|
||
|
|
return STDTIME_TRUE;
|
||
|
|
}
|
||
|
|
|
||
|
|
return STDTIME_FALSE;
|
||
|
|
|
||
|
|
|
||
|
|
#elif defined(STDTIME_MSVC8)
|
||
|
|
|
||
|
|
|
||
|
|
#ifdef _USE_64BIT_TIME_T
|
||
|
|
if (_gmtime64_s (pStructTm, (__time64_t *) pTimeT) == 0)
|
||
|
|
{
|
||
|
|
return STDTIME_TRUE;
|
||
|
|
}
|
||
|
|
|
||
|
|
return STDTIME_FALSE;
|
||
|
|
|
||
|
|
|
||
|
|
#else /* not _USE_64BIT_TIME_T */
|
||
|
|
|
||
|
|
if (_gmtime32_s (pStructTm, (__time32_t *) pTimeT) == 0)
|
||
|
|
{
|
||
|
|
return STDTIME_TRUE;
|
||
|
|
}
|
||
|
|
|
||
|
|
return STDTIME_FALSE;
|
||
|
|
|
||
|
|
#endif /* _USE_64BIT_TIME_T */
|
||
|
|
|
||
|
|
|
||
|
|
#else /* no reentrant gmtime available */
|
||
|
|
|
||
|
|
{
|
||
|
|
struct tm * pTempTm = NULL;
|
||
|
|
|
||
|
|
pTempTm = gmtime (pTimeT);
|
||
|
|
|
||
|
|
if (pTempTm == NULL)
|
||
|
|
{
|
||
|
|
return STDTIME_FALSE;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* copy back to caller */
|
||
|
|
*pStructTm = *pTempTm;
|
||
|
|
|
||
|
|
return STDTIME_TRUE;
|
||
|
|
}
|
||
|
|
|
||
|
|
#endif
|
||
|
|
|
||
|
|
} /* Bool_StdTimeGmTimeR */
|
||
|
|
|
||
|
|
|
||
|
|
/*-***************************************************************************/
|
||
|
|
/* Bool_StdTimeLocalTimeR - PRIVATE FUNCTION */
|
||
|
|
/* provide interface for localtime_r where possible, otherwise localtime. */
|
||
|
|
/* we provide thread safety for this function, if the operating system and */
|
||
|
|
/* runtime library allows for it. */
|
||
|
|
/*****************************************************************************/
|
||
|
|
|
||
|
|
STDTIME_BOOL Bool_StdTimeLocalTimeR (
|
||
|
|
time_t * pTimeT,
|
||
|
|
struct tm * pStructTm)
|
||
|
|
{
|
||
|
|
|
||
|
|
if ((pTimeT == NULL) || (pStructTm == NULL))
|
||
|
|
{
|
||
|
|
return STDTIME_FALSE;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
#ifdef STDTIME_REENTRANT_GMTIME_LOCALTIME
|
||
|
|
|
||
|
|
if (localtime_r (pTimeT, pStructTm) != 0)
|
||
|
|
{
|
||
|
|
return STDTIME_TRUE;
|
||
|
|
}
|
||
|
|
|
||
|
|
return STDTIME_FALSE;
|
||
|
|
|
||
|
|
|
||
|
|
#elif defined(STDTIME_MSVC8)
|
||
|
|
|
||
|
|
|
||
|
|
#ifdef _USE_64BIT_TIME_T
|
||
|
|
if (_localtime64_s (pStructTm, (__time64_t *) pTimeT) == 0)
|
||
|
|
{
|
||
|
|
return STDTIME_TRUE;
|
||
|
|
}
|
||
|
|
|
||
|
|
return STDTIME_FALSE;
|
||
|
|
|
||
|
|
|
||
|
|
#else /* not _USE_64BIT_TIME_T */
|
||
|
|
|
||
|
|
if (_localtime32_s (pStructTm, (__time32_t *) pTimeT) == 0)
|
||
|
|
{
|
||
|
|
return STDTIME_TRUE;
|
||
|
|
}
|
||
|
|
|
||
|
|
return STDTIME_FALSE;
|
||
|
|
|
||
|
|
#endif /* _USE_64BIT_TIME_T */
|
||
|
|
|
||
|
|
|
||
|
|
#else /* no reentrant localtime available */
|
||
|
|
|
||
|
|
{
|
||
|
|
struct tm * pTempTm = NULL;
|
||
|
|
|
||
|
|
pTempTm = localtime (pTimeT);
|
||
|
|
|
||
|
|
if (pTempTm == NULL)
|
||
|
|
{
|
||
|
|
return STDTIME_FALSE;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* copy back to caller */
|
||
|
|
*pStructTm = *pTempTm;
|
||
|
|
|
||
|
|
return STDTIME_TRUE;
|
||
|
|
}
|
||
|
|
|
||
|
|
#endif
|
||
|
|
|
||
|
|
} /* Bool_StdTimeLocalTimeR */
|
||
|
|
|
||
|
|
|
||
|
|
#if 0 /* Int_StdTimeLocalDiff is obsolete */
|
||
|
|
|
||
|
|
/* function is obsolete as of 2007-03-18, will be removed in future release. */
|
||
|
|
|
||
|
|
/*-***************************************************************************/
|
||
|
|
/* Int_StdTimeLocalDiff - PRIVATE FUNCTION */
|
||
|
|
/* get difference in minutes of (GMT time) - (local time) */
|
||
|
|
/* in case gmtime() or localtime() fails, return 0 */
|
||
|
|
/*****************************************************************************/
|
||
|
|
|
||
|
|
static int32_t Int_StdTimeLocalDiff ()
|
||
|
|
{
|
||
|
|
time_t gmt_time_t;
|
||
|
|
struct tm locTm;
|
||
|
|
struct tm gmtTm;
|
||
|
|
|
||
|
|
int32_t locDay;
|
||
|
|
int32_t gmtDay;
|
||
|
|
int32_t locMin;
|
||
|
|
int32_t gmtMin;
|
||
|
|
int32_t diff;
|
||
|
|
|
||
|
|
/* problem with this logic is that 'time(NULL)' returns current time */
|
||
|
|
/* so calculation of LOC vs. GMT is based on current time instead of */
|
||
|
|
/* the time value being converted. */
|
||
|
|
|
||
|
|
gmt_time_t = time(NULL);
|
||
|
|
|
||
|
|
if (! Bool_StdTimeLocalTimeR (&gmt_time_t, &locTm))
|
||
|
|
{
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
locDay = ((locTm.tm_year) * 10000) + ((locTm.tm_mon) * 100)
|
||
|
|
+(locTm.tm_mday);
|
||
|
|
|
||
|
|
locMin = ((locTm.tm_hour) * 60) + locTm.tm_min;
|
||
|
|
|
||
|
|
if (! Bool_StdTimeGmTimeR (&gmt_time_t, &gmtTm))
|
||
|
|
{
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
gmtDay = ((gmtTm.tm_year) * 10000) + ((gmtTm.tm_mon) * 100)
|
||
|
|
+(gmtTm.tm_mday);
|
||
|
|
|
||
|
|
gmtMin = ((gmtTm.tm_hour) * 60) + gmtTm.tm_min;
|
||
|
|
|
||
|
|
if (locDay == gmtDay)
|
||
|
|
{
|
||
|
|
/* loc and gmt are in same day */
|
||
|
|
diff = gmtMin - locMin;
|
||
|
|
}
|
||
|
|
|
||
|
|
else if (gmtDay > locDay)
|
||
|
|
{
|
||
|
|
/* gmtDay > locDay, so gmtMin < locMin */
|
||
|
|
|
||
|
|
/* example: 2006-01-01 23:00 EST = 2006-01-02 04:00 GMT */
|
||
|
|
/* 04:00 GMT - 23:00 EST = difference of -19:00 but that is wrong. */
|
||
|
|
/* it should be a difference of +05:00 */
|
||
|
|
|
||
|
|
/* to correct, calculate (04:00+24:00) GMT - 23:00 EST = +05:00 */
|
||
|
|
/* note that adjustment is made in minutes */
|
||
|
|
|
||
|
|
diff = (gmtMin + 1440) - locMin;
|
||
|
|
}
|
||
|
|
|
||
|
|
else
|
||
|
|
{
|
||
|
|
/* gmtDay < locDay, so gmtMin > locMin */
|
||
|
|
|
||
|
|
/* example: 2006-01-02 01:00 MSK = 2006-01-01 22:00 GMT */
|
||
|
|
/* 22:00 GMT - 01:00 MSK = difference of +21:00 but that is wrong. */
|
||
|
|
/* it should be a difference of -03:00 */
|
||
|
|
|
||
|
|
/* to correct, calculate 22:00 GMT - (01:00+24:00) MSK = -03:00 */
|
||
|
|
/* note that adjustment is made in minutes */
|
||
|
|
|
||
|
|
diff = gmtMin - (locMin + 1440);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* calculated difference value is in minutes */
|
||
|
|
/* for EST, diff = GMT-EST = 300 [ 5 hours ] */
|
||
|
|
/* for EDT, diff = GMT-EDT = 240 [ 4 hours ] */
|
||
|
|
|
||
|
|
return diff;
|
||
|
|
|
||
|
|
} /* Int_StdTimeLocalDiff */
|
||
|
|
|
||
|
|
#endif /* Int_StdTimeLocalDiff is obsolete */
|
||
|
|
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/* StdTimeW32FileTimeToLocalFileTime */
|
||
|
|
/* portable implementation of WIN32 API FileTimeToLocalFileTime */
|
||
|
|
/*****************************************************************************/
|
||
|
|
|
||
|
|
|
||
|
|
STDTIMEW32_STATIC STDTIME_WIN_BOOL StdTimeW32FileTimeToLocalFileTime (
|
||
|
|
const STDTIME_WIN_FILETIME * /*I*/ pGmtFileTime,
|
||
|
|
STDTIME_WIN_FILETIME * /*O*/ pLocFileTime)
|
||
|
|
{
|
||
|
|
STDTIME gmtStdTime;
|
||
|
|
STDTIME locStdTime;
|
||
|
|
STDTIME_RC rc;
|
||
|
|
time_t gmtTimeT;
|
||
|
|
|
||
|
|
struct tm * pStructTm;
|
||
|
|
struct tm locStructTm;
|
||
|
|
int32_t nsec;
|
||
|
|
|
||
|
|
if ((pGmtFileTime == NULL) || (pLocFileTime == NULL))
|
||
|
|
{
|
||
|
|
return STDTIME_WIN_FALSE;
|
||
|
|
}
|
||
|
|
|
||
|
|
rc = FileTimeToStdTime (pGmtFileTime, &gmtStdTime);
|
||
|
|
|
||
|
|
if (rc != STDTIME_OK)
|
||
|
|
return STDTIME_WIN_FALSE;
|
||
|
|
|
||
|
|
rc = StdTimeToTimeTypeEx (&gmtStdTime, &gmtTimeT, &nsec);
|
||
|
|
|
||
|
|
if (rc != STDTIME_OK)
|
||
|
|
return STDTIME_WIN_FALSE;
|
||
|
|
|
||
|
|
pStructTm = localtime (&gmtTimeT);
|
||
|
|
|
||
|
|
if (pStructTm == NULL)
|
||
|
|
return STDTIME_WIN_FALSE;
|
||
|
|
|
||
|
|
locStructTm = *pStructTm;
|
||
|
|
|
||
|
|
rc = StructTmExToStdTime (&locStructTm, nsec, &locStdTime);
|
||
|
|
|
||
|
|
if (rc != STDTIME_OK)
|
||
|
|
return STDTIME_WIN_FALSE;
|
||
|
|
|
||
|
|
rc = StdTimeToFileTime (&locStdTime, pLocFileTime);
|
||
|
|
|
||
|
|
if (rc != STDTIME_OK)
|
||
|
|
return STDTIME_WIN_FALSE;
|
||
|
|
|
||
|
|
return STDTIME_WIN_TRUE;
|
||
|
|
|
||
|
|
} /* StdTimeW32FileTimeToLocalFileTime */
|
||
|
|
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/* StdTimeW32LocalFileTimeToFileTime */
|
||
|
|
/* portable implementation of WIN32 API LocalFileTimeToFileTime */
|
||
|
|
/*****************************************************************************/
|
||
|
|
|
||
|
|
|
||
|
|
STDTIMEW32_STATIC STDTIME_WIN_BOOL StdTimeW32LocalFileTimeToFileTime (
|
||
|
|
const STDTIME_WIN_FILETIME * /*I*/ pLocFileTime,
|
||
|
|
STDTIME_WIN_FILETIME * /*O*/ pGmtFileTime)
|
||
|
|
{
|
||
|
|
STDTIME gmtStdTime;
|
||
|
|
STDTIME locStdTime;
|
||
|
|
STDTIME_RC rc;
|
||
|
|
time_t gmtTimeT;
|
||
|
|
|
||
|
|
struct tm locStructTm;
|
||
|
|
int32_t nsec;
|
||
|
|
|
||
|
|
|
||
|
|
if ((pGmtFileTime == NULL) || (pLocFileTime == NULL))
|
||
|
|
{
|
||
|
|
return STDTIME_WIN_FALSE;
|
||
|
|
}
|
||
|
|
|
||
|
|
rc = FileTimeToStdTime (pLocFileTime, &locStdTime);
|
||
|
|
|
||
|
|
if (rc != STDTIME_OK)
|
||
|
|
return STDTIME_WIN_FALSE;
|
||
|
|
|
||
|
|
rc = StdTimeToStructTmEx (&locStdTime, &locStructTm, &nsec);
|
||
|
|
|
||
|
|
if (rc != STDTIME_OK)
|
||
|
|
return STDTIME_WIN_FALSE;
|
||
|
|
|
||
|
|
locStructTm.tm_isdst = -1; /* CRITICAL: make OS figure out if DST */
|
||
|
|
gmtTimeT = mktime (&locStructTm);
|
||
|
|
|
||
|
|
if (gmtTimeT == (time_t) (-1))
|
||
|
|
return STDTIME_WIN_FALSE;
|
||
|
|
|
||
|
|
rc = TimeTypeExToStdTime (gmtTimeT, nsec, &gmtStdTime);
|
||
|
|
|
||
|
|
if (rc != STDTIME_OK)
|
||
|
|
return STDTIME_WIN_FALSE;
|
||
|
|
|
||
|
|
rc = StdTimeToFileTime (&gmtStdTime, pGmtFileTime);
|
||
|
|
|
||
|
|
if (rc != STDTIME_OK)
|
||
|
|
return STDTIME_WIN_FALSE;
|
||
|
|
|
||
|
|
return STDTIME_WIN_TRUE;
|
||
|
|
|
||
|
|
} /* StdTimeW32LocalFileTimeToFileTime */
|
||
|
|
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/* StdTimeW32_IsLeap - return 1 if leap year, else 0 */
|
||
|
|
/*****************************************************************************/
|
||
|
|
|
||
|
|
|
||
|
|
STDTIMEW32_STATIC int StdTimeW32_IsLeap (int year)
|
||
|
|
{
|
||
|
|
if ((year < 0 ) || (year > 32767))
|
||
|
|
{
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
if ((year % 4000) == 0)
|
||
|
|
{
|
||
|
|
return 0; /* multiples of 4000 are not leap years */
|
||
|
|
}
|
||
|
|
|
||
|
|
if ((year % 400) == 0)
|
||
|
|
{
|
||
|
|
return 1; /* multiples of 400 are leap years */
|
||
|
|
}
|
||
|
|
|
||
|
|
if ((year % 100) == 0)
|
||
|
|
{
|
||
|
|
return 0; /* multiples of 100 are not leap years */
|
||
|
|
}
|
||
|
|
|
||
|
|
if ((year % 4) == 0)
|
||
|
|
{
|
||
|
|
return 1; /* multiples of 4 are leap years */
|
||
|
|
}
|
||
|
|
|
||
|
|
return 0; /* all others are not leap years */
|
||
|
|
|
||
|
|
} /* StdTimeW32_IsLeap */
|
||
|
|
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/* StdTimeW32_LeapYearDays - number leap-year days based on year y */
|
||
|
|
/*****************************************************************************/
|
||
|
|
|
||
|
|
|
||
|
|
STDTIMEW32_STATIC int StdTimeW32_LeapYearDays (int y)
|
||
|
|
{
|
||
|
|
/* number of 4000-year multiples */
|
||
|
|
int n4000 = (y / 4000);
|
||
|
|
|
||
|
|
/* number of 400-year multiples in excess of 4000 */
|
||
|
|
int n400 = (y % 4000) / 400;
|
||
|
|
|
||
|
|
/* number of 100-year multiples in excess of 400 */
|
||
|
|
int n100 = (y % 400) / 100;
|
||
|
|
|
||
|
|
/* number of 4-year multiples in excess of 100 */
|
||
|
|
int n4 = (y % 100) / 4;
|
||
|
|
|
||
|
|
return
|
||
|
|
( 969 * n4000 )
|
||
|
|
+ ( 97 * n400 )
|
||
|
|
+ ( 24 * n100 )
|
||
|
|
+ ( 1 * n4 );
|
||
|
|
|
||
|
|
} /* StdTimeW32_LeapYearDays */
|
||
|
|
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/* days-per-month table */
|
||
|
|
/*****************************************************************************/
|
||
|
|
|
||
|
|
|
||
|
|
static int StdTimeW32_DaysPerMon [13] =
|
||
|
|
{ 00,
|
||
|
|
31, /* JAN */
|
||
|
|
28, /* FEB */
|
||
|
|
31, /* MAR */
|
||
|
|
30, /* APR */
|
||
|
|
31, /* MAY */
|
||
|
|
30, /* JUN */
|
||
|
|
31, /* JUL */
|
||
|
|
31, /* AUG */
|
||
|
|
30, /* SEP */
|
||
|
|
31, /* OCT */
|
||
|
|
30, /* NOV */
|
||
|
|
31 /* DEC */
|
||
|
|
};
|
||
|
|
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/* StdTimeW32SystemTimeToFileTimeEx */
|
||
|
|
/* portable implementation of WIN32 API SystemTimeToFileTime */
|
||
|
|
/*****************************************************************************/
|
||
|
|
|
||
|
|
|
||
|
|
STDTIMEW32_STATIC STDTIME_WIN_BOOL StdTimeW32SystemTimeToFileTimeEx (
|
||
|
|
const STDTIME_WIN_SYSTEMTIME * /*I*/ pSystemTime,
|
||
|
|
STDTIME_WIN_FILETIME * /*O*/ pFileTime,
|
||
|
|
int /*I*/ nsec,
|
||
|
|
int /*I*/ usec)
|
||
|
|
{
|
||
|
|
QUADLIB_U64 uVal;
|
||
|
|
QUADLIB_U64 uNum;
|
||
|
|
|
||
|
|
STDTIME_WIN_SYSTEMTIME st;
|
||
|
|
STDTIME_WIN_FILETIME ft;
|
||
|
|
|
||
|
|
|
||
|
|
int i;
|
||
|
|
int d;
|
||
|
|
int basedays;
|
||
|
|
|
||
|
|
if ((pSystemTime == NULL) || (pFileTime == NULL))
|
||
|
|
{
|
||
|
|
return STDTIME_WIN_FALSE;
|
||
|
|
}
|
||
|
|
|
||
|
|
st = *pSystemTime;
|
||
|
|
|
||
|
|
/* form # of days for year - will not overflow uVal.lo */
|
||
|
|
|
||
|
|
QUADLIB_U64_HI(uVal) = 0;
|
||
|
|
QUADLIB_I64_LO(uVal) = (365 * st.wYear) + StdTimeW32_LeapYearDays (st.wYear);
|
||
|
|
|
||
|
|
/* convert year/mon to days */
|
||
|
|
|
||
|
|
d = st.wDay;
|
||
|
|
|
||
|
|
for (i=1; i < st.wMonth; i++)
|
||
|
|
{
|
||
|
|
d += StdTimeW32_DaysPerMon [i];
|
||
|
|
}
|
||
|
|
|
||
|
|
if (st.wMonth > 2)
|
||
|
|
{
|
||
|
|
d += StdTimeW32_IsLeap (st.wYear);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* calculate: uVal += (d - basedays - 1) */
|
||
|
|
/* == uVal = uVal + d - basedays - 1 == uVal + d - (basedays + 1); */
|
||
|
|
|
||
|
|
/* use the equivalence above to avoid one QUADLIB operation, since */
|
||
|
|
/* there is an overhead to using them under simulation. */
|
||
|
|
|
||
|
|
QUADLIB_U64_HI(uNum) = 0;
|
||
|
|
|
||
|
|
QUADLIB_I64_LO(uNum) = d;
|
||
|
|
QUADLIB_U64_ADD_EQ (uVal, uNum);
|
||
|
|
|
||
|
|
basedays = (STDTIME_WIN_EPOCH_YEAR * 365)
|
||
|
|
+ StdTimeW32_LeapYearDays(STDTIME_WIN_EPOCH_YEAR);
|
||
|
|
|
||
|
|
QUADLIB_I64_LO(uNum) = basedays + 1;
|
||
|
|
QUADLIB_U64_SUB_EQ (uVal, uNum);
|
||
|
|
|
||
|
|
/* calculate: uVal = (uVal * 24) + st.wHour; */
|
||
|
|
|
||
|
|
QUADLIB_U64_LO(uNum) = 24;
|
||
|
|
QUADLIB_U64_MUL_EQ (uVal, uNum);
|
||
|
|
|
||
|
|
QUADLIB_U64_LO(uNum) = st.wHour;
|
||
|
|
QUADLIB_U64_ADD_EQ (uVal, uNum);
|
||
|
|
|
||
|
|
/* calculate: uVal = (uVal * 60) + st.wMinute; */
|
||
|
|
|
||
|
|
QUADLIB_U64_LO(uNum) = 60;
|
||
|
|
QUADLIB_U64_MUL_EQ (uVal, uNum);
|
||
|
|
|
||
|
|
QUADLIB_U64_LO(uNum) = st.wMinute;
|
||
|
|
QUADLIB_U64_ADD_EQ (uVal, uNum);
|
||
|
|
|
||
|
|
/* calculate: uVal = (uVal * 60) + st.wSecond; */
|
||
|
|
|
||
|
|
QUADLIB_U64_LO(uNum) = 60;
|
||
|
|
QUADLIB_U64_MUL_EQ (uVal, uNum);
|
||
|
|
|
||
|
|
QUADLIB_U64_LO(uNum) = st.wSecond;
|
||
|
|
QUADLIB_U64_ADD_EQ (uVal, uNum);
|
||
|
|
|
||
|
|
/* calculate: uVal = (uVal * 1000) + st.wMilliseconds; */
|
||
|
|
|
||
|
|
QUADLIB_U64_LO(uNum) = 1000;
|
||
|
|
QUADLIB_U64_MUL_EQ (uVal, uNum);
|
||
|
|
|
||
|
|
QUADLIB_U64_LO(uNum) = st.wMilliseconds;
|
||
|
|
QUADLIB_U64_ADD_EQ (uVal, uNum);
|
||
|
|
|
||
|
|
/* calculate: uVal = (uVal * 1000) + usec; */
|
||
|
|
|
||
|
|
QUADLIB_U64_LO(uNum) = 1000;
|
||
|
|
QUADLIB_U64_MUL_EQ (uVal, uNum);
|
||
|
|
|
||
|
|
QUADLIB_U64_LO(uNum) = usec;
|
||
|
|
QUADLIB_U64_ADD_EQ (uVal, uNum);
|
||
|
|
|
||
|
|
/* calculate: uVal = (uVal * 10) + (nsec/100); */
|
||
|
|
|
||
|
|
QUADLIB_U64_LO(uNum) = 10;
|
||
|
|
QUADLIB_U64_MUL_EQ (uVal, uNum);
|
||
|
|
|
||
|
|
QUADLIB_U64_LO(uNum) = (nsec/100);
|
||
|
|
QUADLIB_U64_ADD_EQ (uVal, uNum);
|
||
|
|
|
||
|
|
ft.dwLowDateTime = QUADLIB_U64_LO(uVal);
|
||
|
|
ft.dwHighDateTime = QUADLIB_U64_HI(uVal);
|
||
|
|
|
||
|
|
*pFileTime = ft;
|
||
|
|
return STDTIME_WIN_TRUE;
|
||
|
|
|
||
|
|
} /* StdTimeW32SystemTimeToFileTimeEx */
|
||
|
|
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/* StdTimeW32SystemTimeToFileTime */
|
||
|
|
/* portable implementation of WIN32 API SystemTimeToFileTime */
|
||
|
|
/* convert SYSTEMTIME to FILETIME; usec and nsec values default to zero */
|
||
|
|
/*****************************************************************************/
|
||
|
|
|
||
|
|
|
||
|
|
STDTIMEW32_STATIC STDTIME_WIN_BOOL StdTimeW32SystemTimeToFileTime (
|
||
|
|
const STDTIME_WIN_SYSTEMTIME * /*I*/ pSystemTime,
|
||
|
|
STDTIME_WIN_FILETIME * /*O*/ pFileTime)
|
||
|
|
{
|
||
|
|
return StdTimeW32SystemTimeToFileTimeEx (pSystemTime, pFileTime, 0, 0);
|
||
|
|
|
||
|
|
} /* StdTimeW32SystemTimeToFileTime */
|
||
|
|
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/* StdTimeW32FileTimeToSystemTime */
|
||
|
|
/* portable implementation of WIN32 API FileTimeToSystemTime */
|
||
|
|
/*****************************************************************************/
|
||
|
|
|
||
|
|
|
||
|
|
STDTIMEW32_STATIC STDTIME_WIN_BOOL StdTimeW32FileTimeToSystemTime (
|
||
|
|
const STDTIME_WIN_FILETIME * /*I*/ pFileTime,
|
||
|
|
STDTIME_WIN_SYSTEMTIME * /*O*/ pSystemTime)
|
||
|
|
{
|
||
|
|
QUADLIB_U64 uVal;
|
||
|
|
QUADLIB_U64 uMod;
|
||
|
|
QUADLIB_U64 uDiv;
|
||
|
|
|
||
|
|
STDTIME_WIN_SYSTEMTIME st;
|
||
|
|
STDTIME_WIN_FILETIME ft;
|
||
|
|
|
||
|
|
int yday;
|
||
|
|
int max_yday;
|
||
|
|
int day;
|
||
|
|
int mon;
|
||
|
|
int nsec;
|
||
|
|
int usec;
|
||
|
|
int days;
|
||
|
|
int year;
|
||
|
|
int year_hi;
|
||
|
|
int year_lo;
|
||
|
|
int leap;
|
||
|
|
int dpm;
|
||
|
|
int basedays;
|
||
|
|
int workdays;
|
||
|
|
|
||
|
|
|
||
|
|
#ifdef _MSC_VER
|
||
|
|
#pragma warning(push)
|
||
|
|
#pragma warning(disable:4244)
|
||
|
|
/* silence the VC compiler warning message: */
|
||
|
|
/* "conversion from 'int' to 'WORD', possible loss of data" */
|
||
|
|
#endif
|
||
|
|
|
||
|
|
|
||
|
|
if ((pSystemTime == NULL) || (pFileTime == NULL))
|
||
|
|
{
|
||
|
|
return STDTIME_WIN_FALSE;
|
||
|
|
}
|
||
|
|
|
||
|
|
ft = *pFileTime;
|
||
|
|
|
||
|
|
QUADLIB_U64_HI(uVal) = ft.dwHighDateTime;
|
||
|
|
QUADLIB_U64_LO(uVal) = ft.dwLowDateTime;
|
||
|
|
|
||
|
|
/* uVal has count of 100 nsecs intervals */
|
||
|
|
/* calculate: nsec = (uVal % 10) * 100; */
|
||
|
|
|
||
|
|
QUADLIB_U64_HI(uDiv) = 0;
|
||
|
|
QUADLIB_U64_LO(uDiv) = 10;
|
||
|
|
uVal = QuadLibU64DivMod (uVal, uDiv, &uMod);
|
||
|
|
nsec = QUADLIB_I64_LO(uMod) * 100;
|
||
|
|
|
||
|
|
/* uVal has usecs */
|
||
|
|
/* calculate: usec = uVal % 1000; */
|
||
|
|
|
||
|
|
QUADLIB_U64_LO(uDiv) = 1000;
|
||
|
|
uVal = QuadLibU64DivMod (uVal, uDiv, &uMod);
|
||
|
|
usec = QUADLIB_I64_LO(uMod);
|
||
|
|
|
||
|
|
/* uVal has msecs */
|
||
|
|
/* calculate: wMilliseconds = uVal % 1000; */
|
||
|
|
/* QUADLIB_U64_LO(uDiv) = 1000; ==> still in effect */
|
||
|
|
|
||
|
|
uVal = QuadLibU64DivMod (uVal, uDiv, &uMod);
|
||
|
|
st.wMilliseconds = QUADLIB_U64_LO(uMod);
|
||
|
|
|
||
|
|
/* uVal has secs */
|
||
|
|
/* calculate: wSecond = uVal % 60; */
|
||
|
|
|
||
|
|
QUADLIB_U64_LO(uDiv) = 60;
|
||
|
|
uVal = QuadLibU64DivMod (uVal, uDiv, &uMod);
|
||
|
|
st.wSecond = QUADLIB_U64_LO(uMod);
|
||
|
|
|
||
|
|
/* uVal has mins */
|
||
|
|
/* calculate: wMinute = uVal % 60; */
|
||
|
|
/* QUADLIB_U64_LO(uDiv) = 60; ==> still in effect */
|
||
|
|
|
||
|
|
uVal = QuadLibU64DivMod (uVal, uDiv, &uMod);
|
||
|
|
st.wMinute = QUADLIB_U64_LO(uMod);
|
||
|
|
|
||
|
|
/* uVal has hours */
|
||
|
|
/* calculate: wHour = uVal % 24; */
|
||
|
|
|
||
|
|
QUADLIB_U64_LO(uDiv) = 24;
|
||
|
|
uVal = QuadLibU64DivMod (uVal, uDiv, &uMod);
|
||
|
|
|
||
|
|
st.wHour = QUADLIB_U64_LO(uMod);
|
||
|
|
|
||
|
|
/* uVal has days */
|
||
|
|
|
||
|
|
days = QUADLIB_I64_LO(uVal);
|
||
|
|
|
||
|
|
/* Jan 1 1601 was a Monday (day number 1) */
|
||
|
|
/* determine day of week by adding base day number to relative 0 day */
|
||
|
|
/* modulus 7 is the day number */
|
||
|
|
|
||
|
|
st.wDayOfWeek = (days + 1) % 7;
|
||
|
|
|
||
|
|
/* FT Epoch starts on Jan 1, 1601 */
|
||
|
|
/* calculate the number of days prior to FT Epoch */
|
||
|
|
/* treating year 0 as a year = start of year 0 to end of year 1600 */
|
||
|
|
/* which is 1601 years = 584753 */
|
||
|
|
|
||
|
|
basedays = (STDTIME_WIN_EPOCH_YEAR * 365)
|
||
|
|
+ StdTimeW32_LeapYearDays(STDTIME_WIN_EPOCH_YEAR);
|
||
|
|
|
||
|
|
workdays = days + basedays;
|
||
|
|
|
||
|
|
/* if we assumed every year were 365 days long, */
|
||
|
|
/* then workdays / 365 would calculate too high a year, whereas */
|
||
|
|
/* workdays / 366 would calculate too low a year */
|
||
|
|
/* determine year by forming an estimated year, then */
|
||
|
|
/* calculating its total days until we get the right number */
|
||
|
|
|
||
|
|
year_hi = (workdays / 365) + 1;
|
||
|
|
year_lo = (workdays / 366) - 1;
|
||
|
|
|
||
|
|
for (year = year_hi; year > year_lo; year--)
|
||
|
|
{
|
||
|
|
days = (year * 365) + StdTimeW32_LeapYearDays (year);
|
||
|
|
|
||
|
|
if (days <= workdays) break;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (year == year_lo)
|
||
|
|
{
|
||
|
|
/* failed to determine year */
|
||
|
|
return STDTIME_WIN_FALSE;
|
||
|
|
}
|
||
|
|
|
||
|
|
st.wYear = year;
|
||
|
|
|
||
|
|
/* if 'days' == 6 (for example), then 6 complete days have */
|
||
|
|
/* elapsed, plus the number of fractional days (sec, msec, etc.) */
|
||
|
|
/* once fractional days exist, we are into the next day */
|
||
|
|
/* from a calendar point of view, the day is 'days+1' even if a */
|
||
|
|
/* day isn't over yet. */
|
||
|
|
|
||
|
|
/* however, at midnight (fractional days are exactly zero) */
|
||
|
|
/* it is assumed to be the start of the next day. */
|
||
|
|
/* so regardless, the day of year is days+1 always. */
|
||
|
|
|
||
|
|
yday = workdays - days + 1;
|
||
|
|
leap = StdTimeW32_IsLeap (year);
|
||
|
|
max_yday = 365 + leap;
|
||
|
|
|
||
|
|
if ((yday < 1) || (yday > max_yday))
|
||
|
|
{
|
||
|
|
/* yday is invalid for the given year */
|
||
|
|
return STDTIME_WIN_FALSE;
|
||
|
|
}
|
||
|
|
|
||
|
|
day = yday;
|
||
|
|
|
||
|
|
for (mon=1; mon <= 12; mon++)
|
||
|
|
{
|
||
|
|
dpm = StdTimeW32_DaysPerMon [mon];
|
||
|
|
|
||
|
|
if (leap && (mon == 2)) dpm++;
|
||
|
|
|
||
|
|
if (day <= dpm) break;
|
||
|
|
day -= dpm;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (mon > 12)
|
||
|
|
{
|
||
|
|
/* failed to determine month */
|
||
|
|
return STDTIME_WIN_FALSE;
|
||
|
|
}
|
||
|
|
|
||
|
|
st.wMonth = mon;
|
||
|
|
st.wDay = day;
|
||
|
|
|
||
|
|
*pSystemTime = st;
|
||
|
|
|
||
|
|
return STDTIME_WIN_TRUE;
|
||
|
|
|
||
|
|
|
||
|
|
#ifdef _MSC_VER
|
||
|
|
#pragma warning(pop)
|
||
|
|
#endif
|
||
|
|
|
||
|
|
|
||
|
|
} /* StdTimeW32FileTimeToSystemTime */
|
||
|
|
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/* StdTimeW32GetDayofWeekAndYear */
|
||
|
|
/* get day of week, day of year from year, mon, day of month */
|
||
|
|
/* the maximum day number in the STDTIME system is about 3,652,500 */
|
||
|
|
/* so, there is no need for 64-bit math in this function, which only */
|
||
|
|
/* deals with days as the finest resolution. */
|
||
|
|
/*****************************************************************************/
|
||
|
|
|
||
|
|
STDTIME_RC StdTimeW32GetDayofWeekAndYear (
|
||
|
|
int32_t /*I*/ nYear,
|
||
|
|
int32_t /*I*/ nMon,
|
||
|
|
int32_t /*I*/ nDayofMon,
|
||
|
|
int32_t * /*O*/ pDayofWeek,
|
||
|
|
int32_t * /*O*/ pDayofYear)
|
||
|
|
{
|
||
|
|
int32_t n;
|
||
|
|
int32_t yeardays;
|
||
|
|
int32_t basedays;
|
||
|
|
int32_t leap;
|
||
|
|
|
||
|
|
int32_t nDayofWeek;
|
||
|
|
int32_t nDayofYear;
|
||
|
|
|
||
|
|
STDTIME_ENUM_FUNC (StdTimeW32GetDayofWeekAndYear)
|
||
|
|
|
||
|
|
/* output fields are optional, but at least one must be present */
|
||
|
|
/* for the function to be considered successful */
|
||
|
|
|
||
|
|
if ((pDayofWeek == NULL) && (pDayofYear == NULL))
|
||
|
|
{
|
||
|
|
STDTIME_RET_EC (null_argument);
|
||
|
|
}
|
||
|
|
|
||
|
|
if ((nYear < STDTIME_YEAR_MIN)
|
||
|
|
|| (nYear > STDTIME_YEAR_MAX))
|
||
|
|
{
|
||
|
|
STDTIME_RET_EC (invalid_year);
|
||
|
|
}
|
||
|
|
|
||
|
|
if ((nMon < 1) || (nMon > 12))
|
||
|
|
{
|
||
|
|
STDTIME_RET_EC (invalid_mon);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (nDayofMon < 1)
|
||
|
|
{
|
||
|
|
STDTIME_RET_EC (invalid_day);
|
||
|
|
}
|
||
|
|
|
||
|
|
leap = StdTimeW32_IsLeap (nYear);
|
||
|
|
n = StdTimeW32_DaysPerMon [nMon];
|
||
|
|
|
||
|
|
if (nMon == 2)
|
||
|
|
{
|
||
|
|
n += leap;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (nDayofMon > n)
|
||
|
|
{
|
||
|
|
STDTIME_RET_EC (invalid_day);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* form # of days for year - will not overflow 32 bits */
|
||
|
|
|
||
|
|
yeardays = (365 * nYear) + StdTimeW32_LeapYearDays (nYear-1);
|
||
|
|
|
||
|
|
/* convert year/mon to days */
|
||
|
|
|
||
|
|
nDayofYear = nDayofMon;
|
||
|
|
|
||
|
|
for (n=1; n < nMon; n++)
|
||
|
|
{
|
||
|
|
nDayofYear += StdTimeW32_DaysPerMon [n];
|
||
|
|
}
|
||
|
|
|
||
|
|
if (nMon > 2)
|
||
|
|
{
|
||
|
|
nDayofYear += leap;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (pDayofYear != NULL)
|
||
|
|
{
|
||
|
|
*pDayofYear = nDayofYear;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (pDayofWeek == NULL)
|
||
|
|
{
|
||
|
|
STDTIME_RET_OK; /* nothing else to do */
|
||
|
|
}
|
||
|
|
|
||
|
|
basedays = (STDTIME_WIN_EPOCH_YEAR * 365)
|
||
|
|
+ StdTimeW32_LeapYearDays(STDTIME_WIN_EPOCH_YEAR);
|
||
|
|
|
||
|
|
yeardays += (nDayofYear - basedays - 1);
|
||
|
|
|
||
|
|
/* uNum now contains a day number relative to January 1, 1601. */
|
||
|
|
/* it is known that this day was a Monday (day number == 1) */
|
||
|
|
/* so, to get day of week, form mod 7 of the day number + 1 */
|
||
|
|
/* and add 1 */
|
||
|
|
|
||
|
|
nDayofWeek = (yeardays + 1) % 7;
|
||
|
|
*pDayofWeek = nDayofWeek;
|
||
|
|
|
||
|
|
STDTIME_RET_OK;
|
||
|
|
|
||
|
|
} /* StdTimeW32GetDayofWeekAndYear */
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/* gettimeofday() simulation on Win32 systems */
|
||
|
|
/*****************************************************************************/
|
||
|
|
|
||
|
|
#define STDTIMEW32_GETTIMEOFDAY_SUCCESS 0
|
||
|
|
#define STDTIMEW32_GETTIMEOFDAY_FAILURE (-1)
|
||
|
|
|
||
|
|
#ifdef STDTIMEW32_USE_GETTIMEOFDAY
|
||
|
|
#ifdef STDTIMEW32_DEBUGGING
|
||
|
|
|
||
|
|
/* on Unix/Linux systems, gettimeofday() is defined in */
|
||
|
|
/* <time.h> or <sys/time.h> */
|
||
|
|
|
||
|
|
#ifndef _WINSOCKAPI_
|
||
|
|
struct timeval
|
||
|
|
{
|
||
|
|
long tv_sec; /* seconds since Jan 1 1970 */
|
||
|
|
long tv_usec; /* microseconds (seconds / 1_000_000) */
|
||
|
|
};
|
||
|
|
#endif
|
||
|
|
|
||
|
|
STDTIMEW32_STATIC int gettimeofday (
|
||
|
|
struct timeval *pTimeVal, void *pObsolete);
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/* */
|
||
|
|
/* pObsolete as an argument is obsolete on most Unix/Linux systems, in */
|
||
|
|
/* which it is an error to specify a non-NULL value. */
|
||
|
|
/* */
|
||
|
|
/* gettimeofday() return codes */
|
||
|
|
/* rc 0: success */
|
||
|
|
/* rc -1: failure, errno set. */
|
||
|
|
/* errno: EFAULT pTimeVal points outside the accessible address space. */
|
||
|
|
/* errno: EINVAL The structure pointed to by 'pTimeVal' specifies an */
|
||
|
|
/* invalid time (not supported here) */
|
||
|
|
/* errno: EINVAL pObsolete argument is not NULL */
|
||
|
|
/* errno: EOVERFLOW: The system time is greater than 2038, cannot be stored.*/
|
||
|
|
/* Windows does not have EOVERFLOW in errno.h; ERANGE could be used, */
|
||
|
|
/* but for simulation purposes, this condition is not supported. */
|
||
|
|
/* */
|
||
|
|
/*****************************************************************************/
|
||
|
|
|
||
|
|
|
||
|
|
#endif /* STDTIMEW32_DEBUGGING */
|
||
|
|
#endif /* STDTIMEW32_USE_GETTIMEOFDAY */
|
||
|
|
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/* gettimeofday - simulate Unix/Linux function gettimeofday() */
|
||
|
|
/* function is used for debugging purposes only */
|
||
|
|
/*****************************************************************************/
|
||
|
|
|
||
|
|
|
||
|
|
#ifdef STDTIMEW32_USE_GETTIMEOFDAY
|
||
|
|
#ifdef STDTIMEW32_DEBUGGING
|
||
|
|
|
||
|
|
|
||
|
|
STDTIMEW32_STATIC int gettimeofday (
|
||
|
|
struct timeval *pTimeVal, void *pObsolete)
|
||
|
|
{
|
||
|
|
STDTIME_WIN_FILETIME ft;
|
||
|
|
QUADLIB_U64 qFileTime;
|
||
|
|
QUADLIB_U64 qSec;
|
||
|
|
QUADLIB_U64 qNsec100;
|
||
|
|
QUADLIB_U64 qNum;
|
||
|
|
|
||
|
|
if (pTimeVal == NULL)
|
||
|
|
{
|
||
|
|
errno = EFAULT;
|
||
|
|
return STDTIMEW32_GETTIMEOFDAY_FAILURE;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (pObsolete != NULL)
|
||
|
|
{
|
||
|
|
/* the obsolete argument is not supposed to be used */
|
||
|
|
errno = EINVAL;
|
||
|
|
return STDTIMEW32_GETTIMEOFDAY_FAILURE;
|
||
|
|
}
|
||
|
|
|
||
|
|
GetSystemTimeAsFileTime (&ft);
|
||
|
|
|
||
|
|
QUADLIB_U64_HI(qFileTime) = ft.dwHighDateTime;
|
||
|
|
QUADLIB_U64_LO(qFileTime) = ft.dwLowDateTime;
|
||
|
|
|
||
|
|
/* conversion code adapted from MSDN KB Q167296 */
|
||
|
|
/* subtract epoch factor and divide by 10_000_000 */
|
||
|
|
|
||
|
|
QUADLIB_U64_HI(qNum) = STDTIMEW32_FT_TIMET_BASE_HI;
|
||
|
|
QUADLIB_U64_LO(qNum) = STDTIMEW32_FT_TIMET_BASE_LO;
|
||
|
|
|
||
|
|
QUADLIB_I64_SUB_EQ (qFileTime, qNum);
|
||
|
|
|
||
|
|
QUADLIB_U64_HI(qNum) = 0;
|
||
|
|
QUADLIB_U64_LO(qNum) = STDTIMEW32_FT_TIMET_SCALE;
|
||
|
|
|
||
|
|
qSec = QuadLibU64DivMod (qFileTime, qNum, &qNsec100);
|
||
|
|
|
||
|
|
pTimeVal->tv_sec = (long) QUADLIB_U64_LO(qSec);
|
||
|
|
|
||
|
|
/* qNsec100 has multiples of 100 nanoseconds, or 1/10 microseconds */
|
||
|
|
/* to get whole microseconds, divide by 10 */
|
||
|
|
|
||
|
|
pTimeVal->tv_usec = (long) QUADLIB_U64_LO(qNsec100) / 10;
|
||
|
|
|
||
|
|
return STDTIMEW32_GETTIMEOFDAY_SUCCESS;
|
||
|
|
|
||
|
|
} /* gettimeofday */
|
||
|
|
|
||
|
|
|
||
|
|
#endif /* STDTIMEW32_DEBUGGING */
|
||
|
|
#endif /* STDTIMEW32_USE_GETTIMEOFDAY */
|
||
|
|
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/* StdTimeW32GetTimeOfDayToFileTime - interface Unix to Windows time */
|
||
|
|
/* function is used to replace WIN32 API GetSystemTimeAsFileTime */
|
||
|
|
/*****************************************************************************/
|
||
|
|
|
||
|
|
|
||
|
|
#ifdef STDTIMEW32_USE_GETTIMEOFDAY
|
||
|
|
|
||
|
|
|
||
|
|
STDTIMEW32_STATIC void StdTimeW32GetTimeOfDayToFileTime (STDTIME_WIN_FILETIME *pFileTime)
|
||
|
|
{
|
||
|
|
QUADLIB_U64 qResult;
|
||
|
|
QUADLIB_U64 qNum;
|
||
|
|
struct timeval timeVal;
|
||
|
|
STDTIME_WIN_FILETIME ft = {0};
|
||
|
|
|
||
|
|
/* since there is no return-code mechanism for the Windows API */
|
||
|
|
/* GetSystemTimeAsFileTime, we have none here. if the input */
|
||
|
|
/* parameter is NULL, the caller accepts the consequences. */
|
||
|
|
/* a call to GetSystemTimeAsFileTime(NULL) crashes on Windows */
|
||
|
|
|
||
|
|
if (gettimeofday (&timeVal, NULL) != STDTIMEW32_GETTIMEOFDAY_SUCCESS)
|
||
|
|
{
|
||
|
|
*pFileTime = ft;
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* multiply seconds result by 10_000_000 */
|
||
|
|
QUADLIB_U64_HI(qResult) = 0;
|
||
|
|
QUADLIB_U64_LO(qResult) = timeVal.tv_sec;
|
||
|
|
|
||
|
|
QUADLIB_U64_HI(qNum) = 0;
|
||
|
|
QUADLIB_U64_LO(qNum) = STDTIMEW32_FT_TIMET_SCALE;
|
||
|
|
|
||
|
|
QUADLIB_U64_MUL_EQ (qResult, qNum);
|
||
|
|
|
||
|
|
/* add 100nsec intervals by converting tv_usec to 100nsec */
|
||
|
|
/* note that 100nsec units = 10 * usec units */
|
||
|
|
/* there is no way to know if multiply by 10 will cause overflow */
|
||
|
|
/* in 32-bit mode, so quad lib used for this */
|
||
|
|
|
||
|
|
QUADLIB_U64_LO(qNum) = timeVal.tv_usec;
|
||
|
|
QUADLIB_U64_MUL10_EQ (qNum);
|
||
|
|
QUADLIB_U64_ADD_EQ (qResult, qNum);
|
||
|
|
|
||
|
|
/* add constant difference in epoch values */
|
||
|
|
|
||
|
|
QUADLIB_U64_HI(qNum) = STDTIMEW32_FT_TIMET_BASE_HI;
|
||
|
|
QUADLIB_U64_LO(qNum) = STDTIMEW32_FT_TIMET_BASE_LO;
|
||
|
|
|
||
|
|
QUADLIB_U64_ADD_EQ (qResult, qNum);
|
||
|
|
|
||
|
|
ft.dwHighDateTime = QUADLIB_U64_HI(qResult);
|
||
|
|
ft.dwLowDateTime = QUADLIB_U64_LO(qResult);
|
||
|
|
|
||
|
|
*pFileTime = ft;
|
||
|
|
|
||
|
|
} /* StdTimeW32GetTimeOfDayToFileTime */
|
||
|
|
|
||
|
|
|
||
|
|
#endif /* STDTIMEW32_USE_GETTIMEOFDAY */
|
||
|
|
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/* clock_gettime() simulation on Win32 systems */
|
||
|
|
/* StdTimeW32ClockGetTimeToFileTime - interface Unix to Windows time */
|
||
|
|
/*****************************************************************************/
|
||
|
|
|
||
|
|
#define STDTIMEW32_CLOCKGETTIME_SUCCESS 0
|
||
|
|
#define STDTIMEW32_CLOCKGETTIME_FAILURE (-1)
|
||
|
|
|
||
|
|
#ifdef STDTIMEW32_USE_CLOCKGETTIME
|
||
|
|
#ifdef STDTIMEW32_DEBUGGING
|
||
|
|
|
||
|
|
/* clock_gettime is defined in Unix <time.h> */
|
||
|
|
|
||
|
|
#ifndef _CLOCKID_T
|
||
|
|
#define _CLOCKID_T
|
||
|
|
typedef int clockid_t;
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#ifndef _TIME_T_DEFINED
|
||
|
|
typedef long time_t;
|
||
|
|
#define _TIME_T_DEFINED
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#define CLOCK_REALTIME 0
|
||
|
|
|
||
|
|
/* only CLOCK_REALTIME is supported in this simulation */
|
||
|
|
|
||
|
|
/*efine CLOCK_MONOTONIC 1 */
|
||
|
|
/*efine CLOCK_PROCESS_CPUTIME_ID 2 */
|
||
|
|
/*efine CLOCK_THREAD_CPUTIME_ID 3 */
|
||
|
|
|
||
|
|
struct timespec
|
||
|
|
{
|
||
|
|
time_t tv_sec; /* Seconds */
|
||
|
|
long tv_nsec; /* Nanoseconds */
|
||
|
|
};
|
||
|
|
|
||
|
|
STDTIMEW32_STATIC int clock_gettime (clockid_t clock_id, struct timespec *tp);
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/* rc 0: success */
|
||
|
|
/* rc -1: failure, errno set. */
|
||
|
|
/* errno: EFAULT tp points outside the accessible address space. */
|
||
|
|
/* errno: EINVAL The clk_id specified is not supported on this system. */
|
||
|
|
/*****************************************************************************/
|
||
|
|
|
||
|
|
|
||
|
|
#endif /* STDTIMEW32_DEBUGGING */
|
||
|
|
#endif /* STDTIMEW32_USE_CLOCKGETTIME */
|
||
|
|
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/* clock_gettime - simulate Unix/Linux function clock_gettime() */
|
||
|
|
/*****************************************************************************/
|
||
|
|
|
||
|
|
#ifdef STDTIMEW32_USE_CLOCKGETTIME
|
||
|
|
#ifdef STDTIMEW32_DEBUGGING
|
||
|
|
|
||
|
|
STDTIMEW32_STATIC int clock_gettime (
|
||
|
|
clockid_t clock_id, struct timespec *pTimeSpec)
|
||
|
|
{
|
||
|
|
STDTIME_WIN_FILETIME ft;
|
||
|
|
QUADLIB_U64 qFileTime;
|
||
|
|
QUADLIB_U64 qSec;
|
||
|
|
QUADLIB_U64 qNsec100;
|
||
|
|
QUADLIB_U64 qNum;
|
||
|
|
|
||
|
|
if (pTimeSpec == NULL)
|
||
|
|
{
|
||
|
|
errno = EFAULT;
|
||
|
|
return STDTIMEW32_CLOCKGETTIME_FAILURE;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (clock_id != CLOCK_REALTIME)
|
||
|
|
{
|
||
|
|
errno = EINVAL;
|
||
|
|
return STDTIMEW32_CLOCKGETTIME_FAILURE;
|
||
|
|
}
|
||
|
|
|
||
|
|
GetSystemTimeAsFileTime (&ft);
|
||
|
|
|
||
|
|
QUADLIB_U64_HI(qFileTime) = ft.dwHighDateTime;
|
||
|
|
QUADLIB_U64_LO(qFileTime) = ft.dwLowDateTime;
|
||
|
|
|
||
|
|
/* conversion code adapted from MSDN KB Q167296 */
|
||
|
|
/* subtract epoch factor and divide by 10_000_000 */
|
||
|
|
|
||
|
|
QUADLIB_U64_HI(qNum) = STDTIMEW32_FT_TIMET_BASE_HI;
|
||
|
|
QUADLIB_U64_LO(qNum) = STDTIMEW32_FT_TIMET_BASE_LO;
|
||
|
|
|
||
|
|
QUADLIB_I64_SUB_EQ (qFileTime, qNum);
|
||
|
|
|
||
|
|
QUADLIB_U64_HI(qNum) = 0;
|
||
|
|
QUADLIB_U64_LO(qNum) = STDTIMEW32_FT_TIMET_SCALE;
|
||
|
|
|
||
|
|
qSec = QuadLibU64DivMod (qFileTime, qNum, &qNsec100);
|
||
|
|
|
||
|
|
pTimeSpec->tv_sec = (long) QUADLIB_U64_LO(qSec);
|
||
|
|
|
||
|
|
/* qNsec100 has multiples of 100 nanoseconds, or 1/10 microseconds */
|
||
|
|
/* to get whole nanoseconds, multiply by 100 */
|
||
|
|
/* since this value was calculated as a remainder, it will never */
|
||
|
|
/* exceed 10_000_000, so multiplying by 100 will always work */
|
||
|
|
|
||
|
|
pTimeSpec->tv_nsec = (long) QUADLIB_U64_LO(qNsec100) * 100;
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
|
||
|
|
} /* clock_gettime */
|
||
|
|
|
||
|
|
|
||
|
|
#endif /* STDTIMEW32_DEBUGGING */
|
||
|
|
#endif /* STDTIMEW32_USE_CLOCKGETTIME */
|
||
|
|
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/* StdTimeW32ClockGetTimeToFileTime - interface Unix to Windows time */
|
||
|
|
/* function is used to replace WIN32 API GetSystemTimeAsFileTime */
|
||
|
|
/*****************************************************************************/
|
||
|
|
|
||
|
|
|
||
|
|
#ifdef STDTIMEW32_USE_CLOCKGETTIME
|
||
|
|
|
||
|
|
|
||
|
|
STDTIMEW32_STATIC void StdTimeW32ClockGetTimeToFileTime (
|
||
|
|
STDTIME_WIN_FILETIME *pFileTime)
|
||
|
|
{
|
||
|
|
QUADLIB_U64 qResult;
|
||
|
|
QUADLIB_U64 qNum;
|
||
|
|
struct timespec timeSpec;
|
||
|
|
STDTIME_WIN_FILETIME ft = {0};
|
||
|
|
|
||
|
|
/* since there is no return-code mechanism for the Windows API */
|
||
|
|
/* GetSystemTimeAsFileTime, we have none here. if the input */
|
||
|
|
/* parameter is NULL, the caller accepts the consequences. */
|
||
|
|
/* a call to GetSystemTimeAsFileTime(NULL) crashes on Windows */
|
||
|
|
|
||
|
|
if (clock_gettime (CLOCK_REALTIME, &timeSpec) !=
|
||
|
|
STDTIMEW32_CLOCKGETTIME_SUCCESS)
|
||
|
|
{
|
||
|
|
*pFileTime = ft;
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* multiply seconds result by 10_000_000 */
|
||
|
|
#if STDTIME_TIME_T64_ENABLED
|
||
|
|
QUADLIB_U64_HI(qResult) = QUADLIB_U64_HI(timeSpec.tv_sec);
|
||
|
|
QUADLIB_U64_LO(qResult) = QUADLIB_U64_LO(timeSpec.tv_sec);
|
||
|
|
#else
|
||
|
|
QUADLIB_U64_HI(qResult) = 0;
|
||
|
|
QUADLIB_U64_LO(qResult) = (*(uint32_t *)(&(timeSpec.tv_sec)));
|
||
|
|
#endif
|
||
|
|
|
||
|
|
QUADLIB_U64_HI(qNum) = 0;
|
||
|
|
QUADLIB_U64_LO(qNum) = STDTIMEW32_FT_TIMET_SCALE;
|
||
|
|
|
||
|
|
QUADLIB_U64_MUL_EQ (qResult, qNum);
|
||
|
|
|
||
|
|
/* add 100nsec intervals by converting tv_nsec to 100nsec */
|
||
|
|
|
||
|
|
QUADLIB_U64_LO(qNum) = timeSpec.tv_nsec / 100;
|
||
|
|
QUADLIB_U64_ADD_EQ (qResult, qNum);
|
||
|
|
|
||
|
|
/* add constant difference in epoch values */
|
||
|
|
|
||
|
|
QUADLIB_U64_HI(qNum) = STDTIMEW32_FT_TIMET_BASE_HI;
|
||
|
|
QUADLIB_U64_LO(qNum) = STDTIMEW32_FT_TIMET_BASE_LO;
|
||
|
|
|
||
|
|
QUADLIB_U64_ADD_EQ (qResult, qNum);
|
||
|
|
|
||
|
|
ft.dwHighDateTime = QUADLIB_U64_HI(qResult);
|
||
|
|
ft.dwLowDateTime = QUADLIB_U64_LO(qResult);
|
||
|
|
|
||
|
|
*pFileTime = ft;
|
||
|
|
|
||
|
|
} /* StdTimeW32ClockGetTimeToFileTime */
|
||
|
|
|
||
|
|
|
||
|
|
#endif /* STDTIMEW32_USE_CLOCKGETTIME */
|
||
|
|
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/* StdTimeW32TimeBToFileTime - interface Unix to Windows time */
|
||
|
|
/* function is used to replace WIN32 API GetSystemTimeAsFileTime */
|
||
|
|
/* */
|
||
|
|
/* ftime() and struct timeb exist on Windows and Unix */
|
||
|
|
/* however, a struct timeb has only millisecond precision, so there is */
|
||
|
|
/* no reason to use it on Windows, and would be used on Unix/Linux only */
|
||
|
|
/* if no better alternatives existed. */
|
||
|
|
/*****************************************************************************/
|
||
|
|
|
||
|
|
|
||
|
|
#ifdef STDTIMEW32_USE_TIMEB
|
||
|
|
|
||
|
|
|
||
|
|
STDTIMEW32_STATIC void StdTimeW32TimeBToFileTime (
|
||
|
|
STDTIME_WIN_FILETIME *pFileTime)
|
||
|
|
{
|
||
|
|
QUADLIB_U64 qResult;
|
||
|
|
QUADLIB_U64 qNum;
|
||
|
|
struct timeb timeBuffer;
|
||
|
|
STDTIME_WIN_FILETIME ft = {0};
|
||
|
|
|
||
|
|
/* since there is no return-code mechanism for the Windows API */
|
||
|
|
/* GetSystemTimeAsFileTime, we have none here. if the input */
|
||
|
|
/* parameter is NULL, the caller accepts the consequences. */
|
||
|
|
/* a call to GetSystemTimeAsFileTime(NULL) crashes on Windows */
|
||
|
|
|
||
|
|
ftime (&timeBuffer);
|
||
|
|
|
||
|
|
/* ftime returns a time_t and a millisecond count */
|
||
|
|
/* since there is no further precision, the resulting FILETIME */
|
||
|
|
/* value will have zero for microseconds and nanoseconds */
|
||
|
|
|
||
|
|
/* multiply seconds result by 10_000_000 */
|
||
|
|
|
||
|
|
#if STDTIME_TIME_T64_ENABLED
|
||
|
|
QUADLIB_U64_HI(qResult) = QUADLIB_U64_HI(timeBuffer.time);
|
||
|
|
QUADLIB_U64_LO(qResult) = QUADLIB_U64_LO(timeBuffer.time);
|
||
|
|
#else
|
||
|
|
QUADLIB_U64_HI(qResult) = 0;
|
||
|
|
QUADLIB_U64_LO(qResult) = (*(uint32_t *)(&(timeBuffer.time)));
|
||
|
|
#endif
|
||
|
|
|
||
|
|
QUADLIB_U64_HI(qNum) = 0;
|
||
|
|
QUADLIB_U64_LO(qNum) = STDTIMEW32_FT_TIMET_SCALE;
|
||
|
|
|
||
|
|
QUADLIB_U64_MUL_EQ (qResult, qNum);
|
||
|
|
|
||
|
|
/* add milliseconds after converting to 100-nanosecond intervals */
|
||
|
|
/* this requires multiplying an unsigned short by 10,000 */
|
||
|
|
/* the maximum value will not overflow an unsigned 32-bit value */
|
||
|
|
|
||
|
|
QUADLIB_U64_LO(qNum) = 10000 * (unsigned long) timeBuffer.millitm;
|
||
|
|
QUADLIB_U64_ADD_EQ (qResult, qNum);
|
||
|
|
|
||
|
|
/* add constant difference in epoch values */
|
||
|
|
|
||
|
|
QUADLIB_U64_HI(qNum) = STDTIMEW32_FT_TIMET_BASE_HI;
|
||
|
|
QUADLIB_U64_LO(qNum) = STDTIMEW32_FT_TIMET_BASE_LO;
|
||
|
|
|
||
|
|
QUADLIB_U64_ADD_EQ (qResult, qNum);
|
||
|
|
|
||
|
|
ft.dwHighDateTime = QUADLIB_U64_HI(qResult);
|
||
|
|
ft.dwLowDateTime = QUADLIB_U64_LO(qResult);
|
||
|
|
|
||
|
|
*pFileTime = ft;
|
||
|
|
|
||
|
|
} /* StdTimeW32TimeBToFileTime */
|
||
|
|
|
||
|
|
|
||
|
|
#endif /* STDTIMEW32_USE_TIMEB */
|
||
|
|
|
||
|
|
|