Line | Branch | Exec | Source |
---|---|---|---|
1 | #ifndef UTIL_TIME_UTIL_H | ||
2 | #define UTIL_TIME_UTIL_H | ||
3 | |||
4 | #include <stdbool.h> | ||
5 | #include <stddef.h> | ||
6 | #include <sys/stat.h> | ||
7 | #include <time.h> | ||
8 | #include "debug.h" | ||
9 | #include "log.h" | ||
10 | #include "macros.h" | ||
11 | |||
12 | #define TIME_STR_BUFSIZE (64) // sizeof("292271025015-12-01 23:59:00.999999999 +0400") | ||
13 | #define NS_PER_SECOND (1000000000L) | ||
14 | #define MS_PER_SECOND (1000L) | ||
15 | #define NS_PER_MS (1000000L) | ||
16 | #define US_PER_MS (1000L) | ||
17 | |||
18 | 48 | static inline const struct timespec *get_stat_mtime(const struct stat *st) | |
19 | { | ||
20 | #if !defined(__APPLE__) | ||
21 | // https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_stat.h.html#tag_13_61_03:~:text=struct%20timespec%20st_mtim | ||
22 | 48 | return &st->st_mtim; | |
23 | #else | ||
24 | // macOS doesn't conform to POSIX 2008 and uses its own, platform-specific | ||
25 | // naming for the `struct stat` timespec member | ||
26 | return &st->st_mtimespec; | ||
27 | #endif | ||
28 | } | ||
29 | |||
30 | 211 | static inline struct timespec timespec_subtract ( | |
31 | const struct timespec *lhs, | ||
32 | const struct timespec *rhs | ||
33 | ) { | ||
34 | 211 | BUG_ON(lhs->tv_nsec >= NS_PER_SECOND); | |
35 | 211 | BUG_ON(rhs->tv_nsec >= NS_PER_SECOND); | |
36 | 211 | time_t sec = lhs->tv_sec - rhs->tv_sec; | |
37 | 211 | long nsec = lhs->tv_nsec - rhs->tv_nsec; | |
38 | 422 | return (struct timespec) { | |
39 | 211 | .tv_sec = sec - (nsec < 0), | |
40 |
2/2✓ Branch 0 (6→7) taken 208 times.
✓ Branch 1 (6→8) taken 3 times.
|
211 | .tv_nsec = nsec + (nsec < 0 ? NS_PER_SECOND : 0), |
41 | }; | ||
42 | } | ||
43 | |||
44 | 209 | static inline double timespec_to_fp_milliseconds(struct timespec ts) | |
45 | { | ||
46 | 209 | const double ms_per_s = MS_PER_SECOND; | |
47 | 209 | const double ns_per_ms = NS_PER_MS; | |
48 | 209 | return ((double)ts.tv_sec * ms_per_s) + ((double)ts.tv_nsec / ns_per_ms); | |
49 | } | ||
50 | |||
51 | 1 | static inline bool timespecs_equal(const struct timespec *a, const struct timespec *b) | |
52 | { | ||
53 |
2/4✓ Branch 0 (2→3) taken 1 times.
✗ Branch 1 (2→4) not taken.
✗ Branch 2 (3→4) not taken.
✓ Branch 3 (3→5) taken 1 times.
|
1 | return a->tv_sec == b->tv_sec && a->tv_nsec == b->tv_nsec; |
54 | } | ||
55 | |||
56 | // Convenience wrapper for clock_gettime(), with bool return and error logging | ||
57 | ✗ | static inline bool xgettime(struct timespec *ts) | |
58 | { | ||
59 | ✗ | bool r = (clock_gettime(CLOCK_MONOTONIC, ts) == 0); | |
60 | ✗ | if (unlikely(!r)) { | |
61 | ✗ | LOG_ERRNO("clock_gettime"); | |
62 | } | ||
63 | ✗ | return r; | |
64 | } | ||
65 | |||
66 | char *timespec_to_str(const struct timespec *ts, char buf[TIME_STR_BUFSIZE]) NONNULL_ARGS WARN_UNUSED_RESULT; | ||
67 | |||
68 | #endif | ||
69 |