aboutsummaryrefslogtreecommitdiffstats
path: root/sumtimeval.c
diff options
context:
space:
mode:
Diffstat (limited to 'sumtimeval.c')
-rw-r--r--sumtimeval.c40
1 files changed, 30 insertions, 10 deletions
diff --git a/sumtimeval.c b/sumtimeval.c
index 47ef705..e52d58f 100644
--- a/sumtimeval.c
+++ b/sumtimeval.c
@@ -6,16 +6,36 @@
int
libsimple_sumtimeval(struct timeval *sum, const struct timeval *augend, const struct timeval *addend)
{
- struct timespec a, b, s;
- int r;
- libsimple_timeval2timespec(&a, augend);
- libsimple_timeval2timespec(&b, addend);
- r = libsimple_sumtimespec(&s, &a, &b);
- if (r && errno != ERANGE)
- return r;
- if (libsimple_timespec2timeval(sum, &s) && r)
- errno = ERANGE;
- return r;
+ time_t s;
+
+ 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;
+ }
+
+ sum->tv_usec = augend->tv_usec + addend->tv_usec;
+ if (sum->tv_usec >= 1000000L) {
+ if (LIBSIMPLE_SINCR_OVERFLOW(&s, TIME_MAX))
+ goto too_large;
+ sum->tv_usec -= 1000000L;
+ }
+
+ sum->tv_sec = s;
+ return 0;
+
+too_large:
+ sum->tv_sec = TIME_MAX;
+ sum->tv_usec = 999999L;
+ errno = ERANGE;
+ return -1;
+
+too_small:
+ sum->tv_sec = TIME_MIN;
+ sum->tv_usec = 0;
+ errno = ERANGE;
+ return -1;
}