xs_random.h (1816B)
1 /* copyright (c) 2022 - 2025 grunfink et al. / MIT license */ 2 3 #ifndef _XS_RANDOM_H 4 5 #define _XS_RANDOM_H 6 7 unsigned int xs_rnd_int32_d(unsigned int *seed); 8 void *xs_rnd_buf(void *buf, int size); 9 10 #ifdef XS_IMPLEMENTATION 11 12 #include <stdio.h> 13 #include <sys/time.h> 14 #include <unistd.h> 15 #include <stdlib.h> 16 17 unsigned int xs_rnd_int32_d(unsigned int *seed) 18 /* returns a deterministic random integer. If seed is NULL, uses a static one */ 19 { 20 static unsigned int s = 0; 21 22 if (seed == NULL) 23 seed = &s; 24 25 if (*seed == 0) { 26 struct timeval tv; 27 28 gettimeofday(&tv, NULL); 29 *seed = tv.tv_sec ^ tv.tv_usec ^ getpid(); 30 } 31 32 /* Linear congruential generator by Numerical Recipes */ 33 *seed = (*seed * 1664525) + 1013904223; 34 35 return *seed; 36 } 37 38 39 void *xs_rnd_buf(void *buf, int size) 40 /* fills buf with random data */ 41 { 42 #ifdef __OpenBSD__ 43 44 /* available since OpenBSD 2.2 */ 45 arc4random_buf(buf, size); 46 47 #else 48 49 FILE *f; 50 int done = 0; 51 52 if ((f = fopen("/dev/urandom", "r")) != NULL) { 53 /* fill with great random data from the system */ 54 if (fread(buf, size, 1, f) == 1) 55 done = 1; 56 57 fclose(f); 58 } 59 60 if (!done) { 61 /* fill the buffer with poor quality, deterministic data */ 62 unsigned int s = 0; 63 unsigned char *p = (unsigned char *)buf; 64 int n = size / sizeof(s); 65 66 /* fill with full integers */ 67 while (n--) { 68 xs_rnd_int32_d(&s); 69 memcpy(p, &s, sizeof(s)); 70 p += sizeof(s); 71 } 72 73 if ((n = size % sizeof(s))) { 74 /* fill the remaining */ 75 xs_rnd_int32_d(&s); 76 memcpy(p, &s, n); 77 } 78 } 79 80 #endif /* __OpenBSD__ */ 81 82 return buf; 83 } 84 85 86 #endif /* XS_IMPLEMENTATION */ 87 88 #endif /* XS_RANDOM_H */