Skip to content

Commit 5f0a1d2

Browse files
committed
uuid: cross-platform timespec_get
1 parent c411229 commit 5f0a1d2

File tree

1 file changed

+35
-14
lines changed

1 file changed

+35
-14
lines changed

src/uuid/extension.c

Lines changed: 35 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -67,13 +67,35 @@
6767
#include <string.h>
6868
#include <time.h>
6969

70+
// Some older systems do not support timespec_get() from time.h
71+
#if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 201112L || \
72+
(!defined(TIME_UTC) && (!defined(_POSIX_TIMERS) || _POSIX_TIMERS <= 0))
73+
#include <sys/time.h>
74+
#endif
75+
7076
#include "sqlite3ext.h"
7177
SQLITE_EXTENSION_INIT3
7278

7379
#if !defined(SQLITE_ASCII) && !defined(SQLITE_EBCDIC)
7480
#define SQLITE_ASCII 1
7581
#endif
7682

83+
// timespec_now returns the current time with nanosecond precision.
84+
static struct timespec timespec_now(void) {
85+
struct timespec ts;
86+
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && defined(TIME_UTC)
87+
timespec_get(&ts, TIME_UTC);
88+
#elif defined(_POSIX_TIMERS) && (_POSIX_TIMERS > 0)
89+
clock_gettime(CLOCK_REALTIME, &ts);
90+
#else
91+
struct timeval tv;
92+
gettimeofday(&tv, NULL);
93+
ts.tv_sec = tv.tv_sec;
94+
ts.tv_nsec = tv.tv_usec * 1000;
95+
#endif
96+
return ts;
97+
}
98+
7799
/*
78100
* Translate a single byte of Hex into an integer.
79101
* This routine only works if h really is a valid hexadecimal
@@ -191,23 +213,22 @@ static void uuid_v7_generate(sqlite3_context* context, int argc, sqlite3_value**
191213
(void)argc;
192214
(void)argv;
193215

194-
struct timespec ts;
216+
unsigned long long timestamp_ms;
195217
if (argc == 1 && sqlite3_value_type(argv[0]) == SQLITE_INTEGER) {
196218
sqlite3_int64 seconds = sqlite3_value_int64(argv[0]);
197-
ts.tv_sec = seconds;
198-
ts.tv_nsec = 0;
219+
timestamp_ms = seconds * 1000ULL;
199220
} else {
200-
timespec_get(&ts, TIME_UTC);
221+
struct timespec ts = timespec_now();
222+
timestamp_ms = ts.tv_sec * 1000ULL + ts.tv_nsec / 1000000;
201223
}
202-
unsigned long long timestampMs = ts.tv_sec * 1000ULL + ts.tv_nsec / 1000000;
203224

204225
sqlite3_randomness(16, aBlob);
205-
aBlob[0] = timestampMs >> 40;
206-
aBlob[1] = timestampMs >> 32;
207-
aBlob[2] = timestampMs >> 24;
208-
aBlob[3] = timestampMs >> 16;
209-
aBlob[4] = timestampMs >> 8;
210-
aBlob[5] = timestampMs;
226+
aBlob[0] = timestamp_ms >> 40;
227+
aBlob[1] = timestamp_ms >> 32;
228+
aBlob[2] = timestamp_ms >> 24;
229+
aBlob[3] = timestamp_ms >> 16;
230+
aBlob[4] = timestamp_ms >> 8;
231+
aBlob[5] = timestamp_ms;
211232
aBlob[6] = (aBlob[6] & 0x0f) + 0x70;
212233
aBlob[8] = (aBlob[8] & 0x3f) + 0x80;
213234
sqlite3_uuid_blob_to_str(aBlob, zStr);
@@ -228,12 +249,12 @@ static void uuid_v7_extract_timestamp_ms(sqlite3_context* context, int argc, sql
228249
if (pBlob == 0 || (pBlob[6] >> 4) != 7)
229250
return;
230251

231-
unsigned long long timestampMs = 0;
252+
unsigned long long timestamp_ms = 0;
232253
for (size_t i = 0; i < 6; ++i) {
233-
timestampMs = (timestampMs << 8) + pBlob[i];
254+
timestamp_ms = (timestamp_ms << 8) + pBlob[i];
234255
}
235256

236-
sqlite3_result_int64(context, timestampMs);
257+
sqlite3_result_int64(context, timestamp_ms);
237258
}
238259

239260
#endif

0 commit comments

Comments
 (0)