File Coverage

include/horus_time.h
Criterion Covered Total %
statement 29 29 100.0
branch 1 2 50.0
condition n/a
subroutine n/a
pod n/a
total 30 31 96.7


line stmt bran cond sub pod time code
1             #ifndef HORUS_TIME_H
2             #define HORUS_TIME_H
3              
4             /*
5             * horus_time.h - Timestamp helpers for UUID generation
6             *
7             * Gregorian: 60-bit count of 100-nanosecond intervals since Oct 15, 1582
8             * Unix epoch: 48-bit milliseconds since Jan 1, 1970
9             */
10              
11             #include
12              
13             #if defined(_WIN32) || defined(_WIN64)
14             # ifndef WIN32_LEAN_AND_MEAN
15             # define WIN32_LEAN_AND_MEAN
16             # endif
17             # include
18             /* Windows FILETIME epoch (1601-01-01) to Unix epoch (1970-01-01)
19             offset in 100-nanosecond intervals */
20             # define HORUS_WIN_TO_UNIX_OFFSET UINT64_C(116444736000000000)
21             #else
22             # include
23             #endif
24              
25             /* Offset between UUID epoch (1582-10-15) and Unix epoch (1970-01-01)
26             * in 100-nanosecond intervals */
27             #define HORUS_UUID_EPOCH_OFFSET UINT64_C(0x01B21DD213814000)
28              
29             /* ── Gregorian timestamp (for v1, v6) ───────────────────────────── */
30              
31 237           static inline uint64_t horus_gregorian_100ns(void) {
32             #if defined(_WIN32) || defined(_WIN64)
33             /* Windows FILETIME gives 100ns intervals since 1601-01-01.
34             Convert to UUID epoch (1582-10-15) by subtracting the offset. */
35             FILETIME ft;
36             ULARGE_INTEGER ui;
37             GetSystemTimeAsFileTime(&ft);
38             ui.LowPart = ft.dwLowDateTime;
39             ui.HighPart = ft.dwHighDateTime;
40             /* Convert: 100ns since 1601 -> 100ns since 1970 -> 100ns since 1582 */
41             return ui.QuadPart - HORUS_WIN_TO_UNIX_OFFSET + HORUS_UUID_EPOCH_OFFSET;
42             #elif defined(CLOCK_REALTIME) && !defined(__APPLE__)
43             /* Use clock_gettime for nanosecond resolution where available */
44             struct timespec ts;
45 237           clock_gettime(CLOCK_REALTIME, &ts);
46 237           return ((uint64_t)ts.tv_sec * 10000000ULL)
47 237           + ((uint64_t)ts.tv_nsec / 100ULL)
48 237           + HORUS_UUID_EPOCH_OFFSET;
49             #else
50             /* Fallback: gettimeofday gives microsecond resolution */
51             struct timeval tv;
52             gettimeofday(&tv, NULL);
53             return ((uint64_t)tv.tv_sec * 10000000ULL)
54             + ((uint64_t)tv.tv_usec * 10ULL)
55             + HORUS_UUID_EPOCH_OFFSET;
56             #endif
57             }
58              
59             /* ── Unix epoch milliseconds (for v7) ──────────────────────────── */
60              
61 2163           static inline uint64_t horus_unix_epoch_ms(void) {
62             #if defined(_WIN32) || defined(_WIN64)
63             FILETIME ft;
64             ULARGE_INTEGER ui;
65             GetSystemTimeAsFileTime(&ft);
66             ui.LowPart = ft.dwLowDateTime;
67             ui.HighPart = ft.dwHighDateTime;
68             /* Convert from Windows FILETIME (1601) to Unix epoch (1970) ms */
69             return (ui.QuadPart - HORUS_WIN_TO_UNIX_OFFSET) / 10000ULL;
70             #else
71             struct timeval tv;
72 2163           gettimeofday(&tv, NULL);
73 2163           return ((uint64_t)tv.tv_sec * 1000ULL) + ((uint64_t)tv.tv_usec / 1000ULL);
74             #endif
75             }
76              
77             /* ── Extract Gregorian timestamp from v1 UUID bytes ─────────────── */
78              
79 2           static inline uint64_t horus_extract_time_v1(const unsigned char *bytes) {
80             /* v1 layout: time_low (bytes 0-3), time_mid (bytes 4-5),
81             * time_hi_and_version (bytes 6-7, version in high nibble) */
82 2           uint64_t time_low = ((uint64_t)bytes[0] << 24) | ((uint64_t)bytes[1] << 16)
83 2           | ((uint64_t)bytes[2] << 8) | (uint64_t)bytes[3];
84 2           uint64_t time_mid = ((uint64_t)bytes[4] << 8) | (uint64_t)bytes[5];
85 2           uint64_t time_hi = ((uint64_t)(bytes[6] & 0x0F) << 8) | (uint64_t)bytes[7];
86              
87 2           return (time_hi << 48) | (time_mid << 32) | time_low;
88             }
89              
90             /* ── Extract Gregorian timestamp from v6 UUID bytes ─────────────── */
91              
92 1           static inline uint64_t horus_extract_time_v6(const unsigned char *bytes) {
93             /* v6 layout: time_high (bytes 0-3), time_mid (bytes 4-5),
94             * time_low_and_version (bytes 6-7, version in high nibble of byte 6) */
95 1           uint64_t time_high = ((uint64_t)bytes[0] << 24) | ((uint64_t)bytes[1] << 16)
96 1           | ((uint64_t)bytes[2] << 8) | (uint64_t)bytes[3];
97 1           uint64_t time_mid = ((uint64_t)bytes[4] << 8) | (uint64_t)bytes[5];
98 1           uint64_t time_low = ((uint64_t)(bytes[6] & 0x0F) << 8) | (uint64_t)bytes[7];
99              
100 1           return (time_high << 28) | (time_mid << 12) | time_low;
101             }
102              
103             /* ── Extract Unix epoch ms from v7 UUID bytes ───────────────────── */
104              
105 2           static inline uint64_t horus_extract_time_v7(const unsigned char *bytes) {
106             /* v7 layout: 48-bit Unix ms timestamp in bytes 0-5 */
107 2           return ((uint64_t)bytes[0] << 40) | ((uint64_t)bytes[1] << 32)
108 2           | ((uint64_t)bytes[2] << 24) | ((uint64_t)bytes[3] << 16)
109 2           | ((uint64_t)bytes[4] << 8) | (uint64_t)bytes[5];
110             }
111              
112             /* ── Convert Gregorian 100ns ticks to Unix epoch seconds (NV) ──── */
113              
114 3           static inline double horus_gregorian_to_unix(uint64_t ticks) {
115 3 50         if (ticks < HORUS_UUID_EPOCH_OFFSET) return 0.0;
116 3           return (double)(ticks - HORUS_UUID_EPOCH_OFFSET) / 10000000.0;
117             }
118              
119             /* ── Convert Unix epoch ms to Unix epoch seconds (NV) ──────────── */
120              
121 2           static inline double horus_ms_to_unix(uint64_t ms) {
122 2           return (double)ms / 1000.0;
123             }
124              
125             #endif /* HORUS_TIME_H */