summaryrefslogtreecommitdiff
path: root/source/3rd-party/uuid4/uuid4.c
diff options
context:
space:
mode:
authorchai <chaifix@163.com>2019-03-29 00:43:25 +0800
committerchai <chaifix@163.com>2019-03-29 00:43:25 +0800
commitf4c338c63f3456a8eccd56c35e233843687d55be (patch)
tree7278fe4723320c9ef310c5a04d92bf0be1bc778c /source/3rd-party/uuid4/uuid4.c
parent3bced067a4144381e59ce4bd0eb749eeff5ad1f4 (diff)
*thread
Diffstat (limited to 'source/3rd-party/uuid4/uuid4.c')
-rw-r--r--source/3rd-party/uuid4/uuid4.c90
1 files changed, 90 insertions, 0 deletions
diff --git a/source/3rd-party/uuid4/uuid4.c b/source/3rd-party/uuid4/uuid4.c
new file mode 100644
index 0000000..1b60188
--- /dev/null
+++ b/source/3rd-party/uuid4/uuid4.c
@@ -0,0 +1,90 @@
+/**
+ * Copyright (c) 2018 rxi
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the MIT license. See LICENSE for details.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+
+#if defined(_WIN32)
+#include <windows.h>
+#include <wincrypt.h>
+#endif
+
+#include "uuid4.h"
+
+
+static uint64_t seed[2];
+
+
+static uint64_t xorshift128plus(uint64_t *s) {
+ /* http://xorshift.di.unimi.it/xorshift128plus.c */
+ uint64_t s1 = s[0];
+ const uint64_t s0 = s[1];
+ s[0] = s0;
+ s1 ^= s1 << 23;
+ s[1] = s1 ^ s0 ^ (s1 >> 18) ^ (s0 >> 5);
+ return s[1] + s0;
+}
+
+
+int uuid4_init(void) {
+#if defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__)
+ int res;
+ FILE *fp = fopen("/dev/urandom", "rb");
+ if (!fp) {
+ return UUID4_EFAILURE;
+ }
+ res = fread(seed, 1, sizeof(seed), fp);
+ fclose(fp);
+ if ( res != sizeof(seed) ) {
+ return UUID4_EFAILURE;
+ }
+
+#elif defined(_WIN32)
+ int res;
+ HCRYPTPROV hCryptProv;
+ res = CryptAcquireContext(
+ &hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
+ if (!res) {
+ return UUID4_EFAILURE;
+ }
+ res = CryptGenRandom(hCryptProv, (DWORD) sizeof(seed), (PBYTE) seed);
+ CryptReleaseContext(hCryptProv, 0);
+ if (!res) {
+ return UUID4_EFAILURE;
+ }
+
+#else
+ #error "unsupported platform"
+#endif
+ return UUID4_ESUCCESS;
+}
+
+
+void uuid4_generate(char *dst) {
+ static const char *template = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx";
+ static const char *chars = "0123456789abcdef";
+ union { unsigned char b[16]; uint64_t word[2]; } s;
+ const char *p;
+ int i, n;
+ /* get random */
+ s.word[0] = xorshift128plus(seed);
+ s.word[1] = xorshift128plus(seed);
+ /* build string */
+ p = template;
+ i = 0;
+ while (*p) {
+ n = s.b[i >> 1];
+ n = (i & 1) ? (n >> 4) : (n & 0xf);
+ switch (*p) {
+ case 'x' : *dst = chars[n]; i++; break;
+ case 'y' : *dst = chars[(n & 0x3) + 8]; i++; break;
+ default : *dst = *p;
+ }
+ dst++, p++;
+ }
+ *dst = '\0';
+}