aboutsummaryrefslogtreecommitdiffstats
path: root/sumtimespec.c
diff options
context:
space:
mode:
Diffstat (limited to 'sumtimespec.c')
-rw-r--r--sumtimespec.c60
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;
}