diff options
Diffstat (limited to '')
-rw-r--r-- | sumtimespec.c | 60 |
1 files changed, 24 insertions, 36 deletions
diff --git a/sumtimespec.c b/sumtimespec.c index a359971..2b2e935 100644 --- a/sumtimespec.c +++ b/sumtimespec.c @@ -6,48 +6,36 @@ int libsimple_sumtimespec(struct timespec *sum, const struct timespec *augend, const struct timespec *addend) { - long int ns = augend->tv_nsec + addend->tv_nsec; time_t s; - int ret = 0; - - s = augend->tv_sec + addend->tv_sec; - if ((augend->tv_sec < 0) == (addend->tv_sec < 0)) { - if (augend->tv_sec >= 0 && augend->tv_sec > TIME_MAX - addend->tv_sec) { - s = TIME_MAX; - ns = 999999999L; - errno = ERANGE; - ret = -1; - } else if (augend->tv_sec < 0 && augend->tv_sec < TIME_MIN - addend->tv_sec) { - s = TIME_MIN; - ns = 0; - errno = ERANGE; - ret = -1; - } + + if (LIBSIMPLE_SADD_OVERFLOW(augend->tv_sec, addend->tv_sec, &s, TIME_MIN, TIME_MAX)) { + if (addend->tv_sec > 0) + goto too_large; + else + goto too_small; } - if (ns < 0) { - if (s == TIME_MIN) { - ns = 0L; - errno = ERANGE; - ret = -1; - } else { - s -= 1; - ns += 1000000000L; - } - } else if (ns >= 1000000000L) { - if (s == TIME_MAX) { - ns = 999999999L; - errno = ERANGE; - ret = -1; - } else { - s += 1; - ns -= 1000000000L; - } + sum->tv_nsec = augend->tv_nsec + addend->tv_nsec; + if (sum->tv_nsec >= 1000000000L) { + if (LIBSIMPLE_SINCR_OVERFLOW(&s, TIME_MAX)) + goto too_large; + sum->tv_nsec -= 1000000000L; } sum->tv_sec = s; - sum->tv_nsec = ns; - return ret; + return 0; + +too_large: + sum->tv_sec = TIME_MAX; + sum->tv_nsec = 999999999L; + errno = ERANGE; + return -1; + +too_small: + sum->tv_sec = TIME_MIN; + sum->tv_nsec = 0; + errno = ERANGE; + return -1; } |