File Coverage

/usr/local/lib/perl5/site_perl/5.42.0/x86_64-linux/Horus/include/horus_time.h
Criterion Covered Total %
statement 3 3 100.0
branch n/a
condition n/a
subroutine n/a
pod n/a
total 3 3 100.0


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