/* SPDX-License-Identifier: MIT * Copyright (c) 2026 Leah Rowe * * Non-randomisation-related numerical functions. * For rand functions, see: rand.c */ #ifdef __OpenBSD__ #include #endif #include #include #if !((defined(__OpenBSD__) && (OpenBSD) >= 201) || \ defined(__FreeBSD__) || \ defined(__NetBSD__) || defined(__APPLE__)) #include /* if not arc4random: /dev/urandom */ #endif #include #include #include #include #include #include #include "../include/common.h" unsigned short hextonum(char ch_s) { int saved_errno = errno; unsigned char ch; size_t rval; ch = (unsigned char)ch_s; if ((unsigned int)(ch - '0') <= 9) return ch - '0'; ch |= 0x20; if ((unsigned int)(ch - 'a') <= 5) return ch - 'a' + 10; if (ch == '?' || ch == 'x') return rsize(16); /* <-- with rejection sampling! */ return 16; } /* basically hexdump -C */ /* TODO: optimise this write a full util for hexdump how to optimise: don't call print tens of thousands of times! convert the numbers manually, and cache everything in a BUFSIZ sized buffer, with everything properly aligned. i worked out that i could fit 79 rows in a 8KB buffer (1264 bytes of numbers represented as strings in hex) this depends on the OS, and would be calculated at runtime. then: don't use printf. just write it to stdout (basically a simple cat implementation) */ void spew_hex(const void *data, size_t len) { const unsigned char *buf = (const unsigned char *)data; unsigned char c; size_t i; size_t j; if (buf == NULL || len == 0) return; for (i = 0; i < len; i += 16) { printf("%0*zx ", sizeof(size_t) * 2, i); for (j = 0; j < 16; j++) { if (i + j < len) printf("%02x ", buf[i + j]); else printf(" "); if (j == 7) printf(" "); } printf(" |"); for (j = 0; j < 16 && i + j < len; j++) { c = buf[i + j]; printf("%c", isprint(c) ? c : '.'); } printf("|\n"); } printf("%08zx\n", len); } void check_bin(size_t a, const char *a_name) { if (a > 1) err_exit(EINVAL, "%s must be 0 or 1, but is %lu", a_name, (size_t)a); }