diff options
author | Jörg Frings-Fürst <debian@jff-webhosting.net> | 2015-02-04 14:09:54 +0100 |
---|---|---|
committer | Jörg Frings-Fürst <debian@jff-webhosting.net> | 2015-02-04 14:09:54 +0100 |
commit | bd82d030011cd8b9655e5ded6b6df9343b42a6bd (patch) | |
tree | de82d886dfea0cb7dbb6e80436218a25cb211bc3 /src/time.c |
Imported Upstream version 3.22upstream/3.22
Diffstat (limited to 'src/time.c')
-rw-r--r-- | src/time.c | 217 |
1 files changed, 217 insertions, 0 deletions
diff --git a/src/time.c b/src/time.c new file mode 100644 index 0000000..3d25042 --- /dev/null +++ b/src/time.c @@ -0,0 +1,217 @@ +/* + * Copyright Jan Engelhardt, 2012 + * + * This file is part of libHX. libHX is free software; you can + * redistribute it and/or modify it under the terms of the GNU Lesser + * General Public License as published by the Free Software Foundation; + * either version 2.1 or (at your option) any later version. + */ +#include <sys/stat.h> +#include <sys/time.h> +#include <stdbool.h> +#include <time.h> +#include <libHX/misc.h> +#include "internal.h" + +#define MICROSECOND 100000 +#define NANOSECOND 1000000000 +#define NANOSECOND_LL 1000000000LL + +#ifdef HAVE_STRUCT_TIMESPEC_TV_NSEC +EXPORT_SYMBOL bool HX_timespec_isneg(const struct timespec *x) +{ + return (x->tv_sec < 0) || (x->tv_nsec < 0); +} + +EXPORT_SYMBOL struct timespec * +HX_timespec_neg(struct timespec *r, const struct timespec *a) +{ + if (a->tv_sec != 0) { + r->tv_sec = -a->tv_sec; + r->tv_nsec = a->tv_nsec; + } else { + r->tv_sec = 0; + r->tv_nsec = -a->tv_nsec; + } + return r; +} + +EXPORT_SYMBOL struct timespec *HX_timespec_add(struct timespec *r, + const struct timespec *a, const struct timespec *b) +{ + /* + * Split the value represented by the struct into two + * independent values that can be added individually. + */ + long nsec[2]; + nsec[0] = (a->tv_sec < 0) ? -a->tv_nsec : a->tv_nsec; + nsec[1] = (b->tv_sec < 0) ? -b->tv_nsec : b->tv_nsec; + + r->tv_sec = a->tv_sec + b->tv_sec; + r->tv_nsec = nsec[0] + nsec[1]; + if (r->tv_nsec >= NANOSECOND) { + ++r->tv_sec; + r->tv_nsec -= NANOSECOND; + } else if (r->tv_nsec <= -NANOSECOND) { + --r->tv_sec; + r->tv_nsec += NANOSECOND; + } + + /* Combine again */ + if (r->tv_sec < 0) { + if (r->tv_nsec < 0) { + r->tv_nsec = -r->tv_nsec; + } else if (r->tv_nsec > 0) { + if (++r->tv_sec == 0) + r->tv_nsec = -NANOSECOND + r->tv_nsec; + else + r->tv_nsec = NANOSECOND - r->tv_nsec; + } + } else if (r->tv_sec > 0 && r->tv_nsec < 0) { + --r->tv_sec; + r->tv_nsec = NANOSECOND + r->tv_nsec; + } + return r; +} + +EXPORT_SYMBOL struct timespec *HX_timespec_sub(struct timespec *r, + const struct timespec *a, const struct timespec *b) +{ + struct timespec b2; + return HX_timespec_add(r, a, HX_timespec_neg(&b2, b)); +} + +EXPORT_SYMBOL void HX_diff_timespec(struct timespec *delta, + const struct timespec *future, const struct timespec *past) +{ + HX_timespec_sub(delta, future, past); +} + +EXPORT_SYMBOL struct timespec * +HX_timespec_mul(struct timespec *r, const struct timespec *a, int f) +{ + long long t; + + t = a->tv_sec * NANOSECOND_LL + + ((a->tv_sec >= 0) ? a->tv_nsec : -a->tv_nsec); + t *= f; + r->tv_sec = t / NANOSECOND; + r->tv_nsec = t % NANOSECOND; + if (r->tv_sec < 0 && r->tv_nsec < 0) + r->tv_nsec = -r->tv_nsec; + return r; +} + +EXPORT_SYMBOL struct timespec * +HX_timespec_mulf(struct timespec *r, const struct timespec *a, double f) +{ + double t; + + t = (a->tv_sec * NANOSECOND_LL + + ((a->tv_sec >= 0) ? a->tv_nsec : -a->tv_nsec)) * f; + r->tv_sec = t / NANOSECOND; + /* + * This is quite the same as r->tv_nsec = fmod(t, NANOSECOND), + * except that without the library call, we are faster. + */ + r->tv_nsec = t - r->tv_sec * NANOSECOND_LL; + if (r->tv_sec < 0 && r->tv_nsec < 0) + r->tv_nsec = -r->tv_nsec; + return r; +} +#endif + +#ifdef HAVE_STRUCT_TIMEVAL_TV_USEC +EXPORT_SYMBOL struct timeval *HX_timeval_sub(struct timeval *delta, + const struct timeval *future, const struct timeval *past) +{ + delta->tv_sec = future->tv_sec - past->tv_sec; + delta->tv_usec = future->tv_usec - past->tv_usec; + if (future->tv_sec < past->tv_sec || (future->tv_sec == past->tv_sec && + future->tv_usec < past->tv_usec)) { + if (future->tv_usec > past->tv_usec) { + delta->tv_usec = -MICROSECOND + delta->tv_usec; + ++delta->tv_sec; + } + if (delta->tv_sec < 0) + delta->tv_usec *= -1; + } else if (delta->tv_usec < 0) { + delta->tv_usec += MICROSECOND; + --delta->tv_sec; + } + return delta; +} + +EXPORT_SYMBOL void HX_diff_timeval(struct timeval *delta, + const struct timeval *future, const struct timeval *past) +{ + HX_timeval_sub(delta, future, past); +} +#endif + +EXPORT_SYMBOL long HX_time_compare(const struct stat *a, + const struct stat *b, char sel) +{ + long r; + +#if defined(HAVE_STRUCT_STAT_ST_MTIMENSEC) + if (sel == 'm') + return ((r = a->st_mtime - b->st_mtime) != 0) ? + r : a->st_mtimensec - b->st_mtimensec; +#ifdef HAVE_STRUCT_STAT_ST_OTIMENSEC + else if (sel == 'o') + return ((r = a->st_otime - b->st_otime) != 0) ? + r : a->st_otimensec - b->st_otimensec; +#endif + else if (sel == 'a') + return ((r = a->st_atime - b->st_atime) != 0) ? + r : a->st_atimensec - b->st_atimensec; + else if (sel == 'c') + return ((r = a->st_ctime - b->st_ctime) != 0) ? + r : a->st_ctimensec - b->st_ctimensec; +#elif defined(HAVE_STRUCT_STAT_ST_MTIM) + if (sel == 'm') + return ((r = a->st_mtim.tv_sec - b->st_mtim.tv_sec) != 0) ? + r : a->st_mtim.tv_nsec - b->st_mtim.tv_nsec; +#ifdef HAVE_STRUCT_STAT_ST_OTIM + else if (sel == 'o') + return ((r = a->st_otim.tv_sec - b->st_otim.tv_sec) != 0) ? + r : a->st_otim.tv_nsec - b->st_otim.tv_nsec; +#endif + else if (sel == 'a') + return ((r = a->st_atim.tv_sec - b->st_atim.tv_sec) != 0) ? + r : a->st_atim.tv_nsec - b->st_atim.tv_nsec; + else if (sel == 'c') + return ((r = a->st_ctim.tv_sec - b->st_ctim.tv_sec) != 0) ? + r : a->st_ctim.tv_nsec - b->st_ctim.tv_nsec; +#elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC) + if (sel == 'm') + return ((r = a->st_mtimespec.tv_sec - b->st_mtimespec.tv_sec) != 0) ? + r : a->st_mtimespec.tv_nsec - b->st_mtimespec.tv_nsec; +#ifdef HAVE_STRUCT_STAT_ST_OTIMESPEC + else if (sel == 'o') + return ((r = a->st_otimespec.tv_sec - b->st_otimespec.tv_sec) != 0) ? + r : a->st_otimespec.tv_nsec - b->st_otimespec.tv_nsec; +#endif + else if (sel == 'a') + return ((r = a->st_atimespec.tv_sec - b->st_atimespec.tv_sec) != 0) ? + r : a->st_atimespec.tv_nsec - b->st_atimespec.tv_nsec; + else if (sel == 'c') + return ((r = a->st_ctimespec.tv_sec - b->st_ctimespec.tv_sec) != 0) ? + r : a->st_ctimespec.tv_nsec - b->st_ctimespec.tv_nsec; +#elif defined(HAVE_STRUCT_STAT_ST_MTIME) + if (sel == 'm') + return a->st_mtime - b->st_mtime; +#ifdef HAVE_STRUCT_STAT_ST_OTIME + else if (sel == 'o') + return a->st_otime - b->st_otime; +#endif + else if (sel == 'a') + return a->st_atime - b->st_atime; + else if (sel == 'c') + return a->st_ctime - b->st_ctime; +#else +# error Tis not ending well. +#endif + return 0; +} |