diff --git a/stio/lib/stio-tim.c b/stio/lib/stio-tim.c new file mode 100644 index 0000000..0c0ec11 --- /dev/null +++ b/stio/lib/stio-tim.c @@ -0,0 +1,192 @@ +/* + * $Id$ + * + Copyright (c) 2015-2016 Chung, Hyung-Hwan. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "stio-tim.h" +#include "stio-prv.h" + +#if defined(_WIN32) +# include +# include +#elif defined(__OS2__) +# define INCL_DOSDATETIME +# define INCL_DOSERRORS +# include +# include +#elif defined(__DOS__) +# include +# include +#else +# if defined(HAVE_SYS_TIME_H) +# include +# endif +# if defined(HAVE_TIME_H) +# include +# endif +# include +#endif + +#if defined(_WIN32) + #define EPOCH_DIFF_YEARS (STIO_EPOCH_YEAR-STIO_EPOCH_YEAR_WIN) + #define EPOCH_DIFF_DAYS ((stio_intptr_t)EPOCH_DIFF_YEARS*365+EPOCH_DIFF_YEARS/4-3) + #define EPOCH_DIFF_SECS ((stio_intptr_t)EPOCH_DIFF_DAYS*24*60*60) +#endif + +int stio_gettime (stio_ntime_t* t) +{ +#if defined(_WIN32) + SYSTEMTIME st; + FILETIME ft; + ULARGE_INTEGER li; + + /* + * MSDN: The FILETIME structure is a 64-bit value representing the + * number of 100-nanosecond intervals since January 1, 1601 (UTC). + */ + + GetSystemTime (&st); + if (SystemTimeToFileTime (&st, &ft) == FALSE) return -1; + + li.LowPart = ft.dwLowDateTime; + li.HighPart = ft.dwHighDateTime; + + /* li.QuadPart is in the 100-nanosecond intervals */ + t->sec = (li.QuadPart / (STIO_NSECS_PER_SEC / 100)) - EPOCH_DIFF_SECS; + t->nsec = (li.QuadPart % (STIO_NSECS_PER_SEC / 100)) * 100; + + return 0; + +#elif defined(__OS2__) + + APIRET rc; + DATETIME dt; + stio_btime_t bt; + + /* Can I use DosQuerySysInfo(QSV_TIME_LOW) and + * DosQuerySysInfo(QSV_TIME_HIGH) for this instead? + * Maybe, resolution too low as it returns values + * in seconds. */ + + rc = DosGetDateTime (&dt); + if (rc != NO_ERROR) return -1; + + bt.year = dt.year - STIO_BTIME_YEAR_BASE; + bt.mon = dt.month - 1; + bt.mday = dt.day; + bt.hour = dt.hours; + bt.min = dt.minutes; + bt.sec = dt.seconds; + /*bt.msec = dt.hundredths * 10;*/ + bt.isdst = -1; /* determine dst for me */ + + if (stio_timelocal (&bt, t) <= -1) return -1; + t->nsec = STIO_MSEC_TO_NSEC(dt.hundredths * 10); + return 0; + +#elif defined(__DOS__) + + struct dostime_t dt; + struct dosdate_t dd; + stio_btime_t bt; + + _dos_gettime (&dt); + _dos_getdate (&dd); + + bt.year = dd.year - STIO_BTIME_YEAR_BASE; + bt.mon = dd.month - 1; + bt.mday = dd.day; + bt.hour = dt.hour; + bt.min = dt.minute; + bt.sec = dt.second; + /*bt.msec = dt.hsecond * 10; */ + bt.isdst = -1; /* determine dst for me */ + + if (stio_timelocal (&bt, t) <= -1) return -1; + t->nsec = STIO_MSEC_TO_NSEC(dt.hsecond * 10); + return 0; + +#elif defined(macintosh) + unsigned long tv; + + GetDateTime (&tv); + + t->sec = tv; + tv->nsec = 0; + + return 0; + +#elif defined(HAVE_GETTIMEOFDAY) + struct timeval tv; + int n; + + /* TODO: consider using clock_gettime() if it's avaialble.. -lrt may be needed */ + n = gettimeofday (&tv, STIO_NULL); + if (n == -1) + { +/* TODO: set stio->errnum using errno... */ + return -1; + } + + t->sec = tv.tv_sec; + t->nsec = STIO_USEC_TO_NSEC(tv.tv_usec); + return 0; + +#else + t->sec = STIO_TIME (STIO_NULL); + t->nsec = 0; + + return 0; +#endif +} + +void stio_addtime (const stio_ntime_t* x, const stio_ntime_t* y, stio_ntime_t* z) +{ + STIO_ASSERT (x->nsec >= 0 && x->nsec < STIO_NSECS_PER_SEC); + STIO_ASSERT (y->nsec >= 0 && y->nsec < STIO_NSECS_PER_SEC); + + z->sec = x->sec + y->sec; + z->nsec = x->nsec + y->nsec; + + if (z->nsec >= STIO_NSECS_PER_SEC) + { + z->sec = z->sec + 1; + z->nsec = z->nsec - STIO_NSECS_PER_SEC; + } +} + +void stio_subtime (const stio_ntime_t* x, const stio_ntime_t* y, stio_ntime_t* z) +{ + STIO_ASSERT (x->nsec >= 0 && x->nsec < STIO_NSECS_PER_SEC); + STIO_ASSERT (y->nsec >= 0 && y->nsec < STIO_NSECS_PER_SEC); + + z->sec = x->sec - y->sec; + z->nsec = x->nsec - y->nsec; + + if (z->nsec < 0) + { + z->sec = z->sec - 1; + z->nsec = z->nsec + STIO_NSECS_PER_SEC; + } +} diff --git a/stio/lib/stio-tim.h b/stio/lib/stio-tim.h new file mode 100644 index 0000000..66ad7eb --- /dev/null +++ b/stio/lib/stio-tim.h @@ -0,0 +1,135 @@ +/* + * $Id$ + * + Copyright (c) 2015-2016 Chung, Hyung-Hwan. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _STIO_TIME_H_ +#define _STIO_TIME_H_ + +#include + +#define STIO_EPOCH_YEAR (1970) +#define STIO_EPOCH_MON (1) +#define STIO_EPOCH_DAY (1) +#define STIO_EPOCH_WDAY (4) + +/* windows specific epoch time */ +#define STIO_EPOCH_YEAR_WIN (1601) +#define STIO_EPOCH_MON_WIN (1) +#define STIO_EPOCH_DAY_WIN (1) + +#define STIO_DAYS_PER_WEEK (7) +#define STIO_MONS_PER_YEAR (12) +#define STIO_HOURS_PER_DAY (24) +#define STIO_MINS_PER_HOUR (60) +#define STIO_MINS_PER_DAY (STIO_MINS_PER_HOUR*STIO_HOURS_PER_DAY) +#define STIO_SECS_PER_MIN (60) +#define STIO_SECS_PER_HOUR (STIO_SECS_PER_MIN*STIO_MINS_PER_HOUR) +#define STIO_SECS_PER_DAY (STIO_SECS_PER_MIN*STIO_MINS_PER_DAY) +#define STIO_MSECS_PER_SEC (1000) +#define STIO_MSECS_PER_MIN (STIO_MSECS_PER_SEC*STIO_SECS_PER_MIN) +#define STIO_MSECS_PER_HOUR (STIO_MSECS_PER_SEC*STIO_SECS_PER_HOUR) +#define STIO_MSECS_PER_DAY (STIO_MSECS_PER_SEC*STIO_SECS_PER_DAY) + +#define STIO_USECS_PER_MSEC (1000) +#define STIO_NSECS_PER_USEC (1000) +#define STIO_NSECS_PER_MSEC (STIO_NSECS_PER_USEC*STIO_USECS_PER_MSEC) +#define STIO_USECS_PER_SEC (STIO_USECS_PER_MSEC*STIO_MSECS_PER_SEC) +#define STIO_NSECS_PER_SEC (STIO_NSECS_PER_USEC*STIO_USECS_PER_MSEC*STIO_MSECS_PER_SEC) + +#define STIO_SECNSEC_TO_MSEC(sec,nsec) \ + (((stio_intptr_t)(sec) * STIO_MSECS_PER_SEC) + ((stio_intptr_t)(nsec) / STIO_NSECS_PER_MSEC)) + +#define STIO_SECNSEC_TO_USEC(sec,nsec) \ + (((stio_intptr_t)(sec) * STIO_USECS_PER_SEC) + ((stio_intptr_t)(nsec) / STIO_NSECS_PER_USEC)) + +#define STIO_SEC_TO_MSEC(sec) ((sec) * STIO_MSECS_PER_SEC) +#define STIO_MSEC_TO_SEC(sec) ((sec) / STIO_MSECS_PER_SEC) + +#define STIO_USEC_TO_NSEC(usec) ((usec) * STIO_NSECS_PER_USEC) +#define STIO_NSEC_TO_USEC(nsec) ((nsec) / STIO_NSECS_PER_USEC) + +#define STIO_MSEC_TO_NSEC(msec) ((msec) * STIO_NSECS_PER_MSEC) +#define STIO_NSEC_TO_MSEC(nsec) ((nsec) / STIO_NSECS_PER_MSEC) + +#define STIO_SEC_TO_NSEC(sec) ((sec) * STIO_NSECS_PER_SEC) +#define STIO_NSEC_TO_SEC(nsec) ((nsec) / STIO_NSECS_PER_SEC) + +#define STIO_SEC_TO_USEC(sec) ((sec) * STIO_USECS_PER_SEC) +#define STIO_USEC_TO_SEC(usec) ((usec) / STIO_USECS_PER_SEC) + +/** + * The stio_ntime_t type defines a numeric time type expressed in the + * number of milliseconds since the Epoch (00:00:00 UTC, Jan 1, 1970). + */ +typedef struct stio_ntime_t stio_ntime_t; +struct stio_ntime_t +{ + stio_intptr_t sec; + stio_int32_t nsec; /* nanoseconds */ +}; + +#define stio_inittime(x,s,ns) (((x)->sec = (s)), ((x)->nsec = (ns))) +#define stio_cleartime(x) stio_inittime(x,0,0) +/*#define stio_cleartime(x) ((x)->sec = (x)->nsec = 0)*/ +#define stio_cmptime(x,y) \ + (((x)->sec == (y)->sec)? ((x)->nsec - (y)->nsec): \ + ((x)->sec - (y)->sec)) + +#define stio_iszerotime(x) ((x)->sec == 0 && (x)->nsec == 0) + +#if defined(__cplusplus) +extern "C" { +#endif + +/** + * The stio_gettime() function gets the current time. + */ +STIO_EXPORT int stio_gettime ( + stio_ntime_t* nt +); + +/** + * The stio_addtime() function adds x and y and stores the result in z + */ +STIO_EXPORT void stio_addtime ( + const stio_ntime_t* x, + const stio_ntime_t* y, + stio_ntime_t* z +); + +/** + * The stio_subtime() function subtract y from x and stores the result in z. + */ +STIO_EXPORT void stio_subtime ( + const stio_ntime_t* x, + const stio_ntime_t* y, + stio_ntime_t* z +); + +#if defined(__cplusplus) +} +#endif + +#endif