Merge with git+ssh://pasky.or.cz/srv/git/elinks.git
[elinks.git] / src / util / time.c
blobd7691a14d51abaf5188b24b47214ae1c5a8f216b
1 /* Time operations */
3 #ifdef HAVE_CONFIG_H
4 #include "config.h"
5 #endif
7 #ifdef HAVE_SYS_TIME_H
8 #include <sys/time.h>
9 #endif
10 #ifdef HAVE_TIME_H
11 #include <time.h>
12 #endif
14 #include "elinks.h"
16 #include "osdep/osdep.h" /* For win32 gettimeofday() stub */
17 #include "util/error.h"
18 #include "util/time.h"
20 /* Get the current time.
21 * It attempts to use available functions, granularity
22 * may be as worse as 1 second if time() is used. */
23 timeval_T *
24 timeval_now(timeval_T *t)
26 #ifdef HAVE_GETTIMEOFDAY
27 struct timeval tv;
29 gettimeofday(&tv, NULL);
30 t->sec = (long) tv.tv_sec;
31 t->usec = (long) tv.tv_usec;
32 #else
33 #ifdef HAVE_CLOCK_GETTIME
34 struct timespec ts;
36 clock_gettime(CLOCK_REALTIME, &ts);
37 t->sec = (long) ts.tv_sec;
38 t->usec = (long) ts.tv_nsec / 1000;
39 #else
40 t->sec = (long) time(NULL);
41 t->usec = (long) 0;
42 #endif
43 #endif
45 return t;
48 /* Subtract an interval to a timeval, it ensures that
49 * result is never negative. */
50 timeval_T *
51 timeval_sub_interval(timeval_T *t, timeval_T *interval)
53 t->sec -= interval->sec;
54 if (t->sec < 0) {
55 t->sec = 0;
56 t->usec = 0;
57 return t;
60 t->usec -= interval->usec;
62 while (t->usec < 0) {
63 t->usec += 1000000;
64 t->sec--;
67 if (t->sec < 0) {
68 t->sec = 0;
69 t->usec = 0;
72 return t;
75 timeval_T *
76 timeval_sub(timeval_T *res, timeval_T *older, timeval_T *newer)
78 res->sec = newer->sec - older->sec;
79 res->usec = newer->usec - older->usec;
81 while (res->usec < 0) {
82 res->usec += 1000000;
83 res->sec--;
86 return res;
89 timeval_T *
90 timeval_add(timeval_T *res, timeval_T *base, timeval_T *t)
92 res->sec = base->sec + t->sec;
93 res->usec = base->usec + t->usec;
95 while (res->usec >= 1000000) {
96 res->usec -= 1000000;
97 res->sec++;
100 return res;
103 timeval_T *
104 timeval_add_interval(timeval_T *t, timeval_T *interval)
106 t->sec += interval->sec;
107 t->usec += interval->usec;
109 while (t->usec >= 1000000) {
110 t->usec -= 1000000;
111 t->sec++;
114 return t;
117 timeval_T *
118 timeval_from_double(timeval_T *t, double x)
120 t->sec = (long) x;
121 t->usec = (long) ((x - (double) t->sec) * 1000000);
123 return t;
126 timeval_T *
127 timeval_from_milliseconds(timeval_T *t, milliseconds_T milliseconds)
129 long ms = (long) milliseconds;
131 t->sec = ms / 1000;
132 t->usec = (ms % 1000) * 1000;
134 return t;
137 /* Bug 923: Assumes time_t values fit in long. (This function is used
138 * for both timestamps and durations.) */
139 timeval_T *
140 timeval_from_seconds(timeval_T *t, long seconds)
142 t->sec = seconds;
143 t->usec = 0;
145 return t;
148 milliseconds_T
149 sec_to_ms(long sec)
151 assert(sec >= 0 && sec < LONG_MAX / 1000L);
152 if_assert_failed return (milliseconds_T) (LONG_MAX / 1000L);
154 return (milliseconds_T) (sec * 1000L);
157 milliseconds_T
158 add_ms_to_ms(milliseconds_T a, milliseconds_T b)
160 long la = (long) a;
161 long lb = (long) b;
163 assert(la >= 0 && lb >= 0 && lb < LONG_MAX - la);
164 if_assert_failed return (milliseconds_T) (LONG_MAX / 1000L);
166 return (milliseconds_T) (la + lb);
169 milliseconds_T
170 mult_ms(milliseconds_T a, long lb)
172 long la = (long) a;
174 assert(la >= 0 && lb >= 0 && la < LONG_MAX / lb);
175 if_assert_failed return (milliseconds_T) (LONG_MAX / 1000L);
177 return (milliseconds_T) (la * lb);
180 milliseconds_T
181 timeval_to_milliseconds(timeval_T *t)
183 milliseconds_T a = sec_to_ms(t->sec);
184 milliseconds_T b = (milliseconds_T) (t->usec / 1000L);
186 return add_ms_to_ms(a, b);
189 /* Bug 923: Assumes time_t values fit in long. (This function is used
190 * for both timestamps and durations.) */
191 long
192 timeval_to_seconds(timeval_T *t)
194 return t->sec + t->usec / 1000000L;
198 timeval_is_positive(timeval_T *t)
200 return (t->sec > 0 || (t->sec == 0 && t->usec > 0));
203 /* Be sure timeval is not negative. */
204 void
205 timeval_limit_to_zero_or_one(timeval_T *t)
207 if (t->sec < 0) t->sec = 0;
208 if (t->usec < 0) t->usec = 0;
209 #ifdef CONFIG_OS_WIN32
210 /* Under Windows I got 300 seconds timeout, so 1 second should not hurt --witekfl */
211 if (t->sec > 1) t->sec = 1;
212 #endif
215 /* Returns 1 if t1 > t2
216 * -1 if t1 < t2
217 * 0 if t1 == t2 */
219 timeval_cmp(timeval_T *t1, timeval_T *t2)
221 if (t1->sec > t2->sec) return 1;
222 if (t1->sec < t2->sec) return -1;
224 return t1->usec - t2->usec;
228 timeval_div_off_t(off_t n, timeval_T *t)
230 longlong ln = 1000 * (longlong) n; /* FIXME: off_t -> longlong ??? Find a better way. --Zas */
231 longlong lsec = 1000 * (longlong) t->sec;
232 int lusec = t->usec / 1000;
234 if (lsec + lusec)
235 return (ln / (lsec + lusec));
236 else
237 return INT_MAX;