X-Git-Url: https://git.distorted.org.uk/~mdw/sgt/puzzles/blobdiff_plain/48d70ca96bb91f3e9abef9a0b38ed0a5cbb21d7b..HEAD:/random.c diff --git a/random.c b/random.c index 664b11c..6d278a4 100644 --- a/random.c +++ b/random.c @@ -12,18 +12,10 @@ #include #include +#include #include "puzzles.h" -typedef unsigned long uint32; - -typedef struct { - uint32 h[5]; - unsigned char block[64]; - int blkused; - uint32 lenhi, lenlo; -} SHA_State; - /* ---------------------------------------------------------------------- * Core SHA algorithm: processes 16-word blocks into a message digest. */ @@ -108,14 +100,14 @@ static void SHATransform(uint32 * digest, uint32 * block) * the end, and pass those blocks to the core SHA algorithm. */ -static void SHA_Init(SHA_State * s) +void SHA_Init(SHA_State * s) { SHA_Core_Init(s->h); s->blkused = 0; s->lenhi = s->lenlo = 0; } -static void SHA_Bytes(SHA_State * s, void *p, int len) +void SHA_Bytes(SHA_State * s, void *p, int len) { unsigned char *q = (unsigned char *) p; uint32 wordblock[16]; @@ -158,7 +150,7 @@ static void SHA_Bytes(SHA_State * s, void *p, int len) } } -static void SHA_Final(SHA_State * s, unsigned char *output) +void SHA_Final(SHA_State * s, unsigned char *output) { int i; int pad; @@ -196,7 +188,7 @@ static void SHA_Final(SHA_State * s, unsigned char *output) } } -static void SHA_Simple(void *p, int len, unsigned char *output) +void SHA_Simple(void *p, int len, unsigned char *output) { SHA_State s; @@ -215,7 +207,7 @@ struct random_state { int pos; }; -random_state *random_init(char *seed, int len) +random_state *random_new(char *seed, int len) { random_state *state; @@ -229,6 +221,16 @@ random_state *random_init(char *seed, int len) return state; } +random_state *random_copy(random_state *tocopy) +{ + random_state *result; + result = snew(random_state); + memcpy(result->seedbuf, tocopy->seedbuf, sizeof(result->seedbuf)); + memcpy(result->databuf, tocopy->databuf, sizeof(result->databuf)); + result->pos = tocopy->pos; + return result; +} + unsigned long random_bits(random_state *state, int bits) { unsigned long ret = 0; @@ -272,7 +274,7 @@ unsigned long random_upto(random_state *state, unsigned long limit) bits += 3; assert(bits < 32); - max = 1 << bits; + max = 1L << bits; divisor = max / limit; max = limit * divisor; @@ -287,3 +289,63 @@ void random_free(random_state *state) { sfree(state); } + +char *random_state_encode(random_state *state) +{ + char retbuf[256]; + int len = 0, i; + + for (i = 0; i < lenof(state->seedbuf); i++) + len += sprintf(retbuf+len, "%02x", state->seedbuf[i]); + for (i = 0; i < lenof(state->databuf); i++) + len += sprintf(retbuf+len, "%02x", state->databuf[i]); + len += sprintf(retbuf+len, "%02x", state->pos); + + return dupstr(retbuf); +} + +random_state *random_state_decode(char *input) +{ + random_state *state; + int pos, byte, digits; + + state = snew(random_state); + + memset(state->seedbuf, 0, sizeof(state->seedbuf)); + memset(state->databuf, 0, sizeof(state->databuf)); + state->pos = 0; + + byte = digits = 0; + pos = 0; + while (*input) { + int v = *input++; + + if (v >= '0' && v <= '9') + v = v - '0'; + else if (v >= 'A' && v <= 'F') + v = v - 'A' + 10; + else if (v >= 'a' && v <= 'f') + v = v - 'a' + 10; + else + v = 0; + + byte = (byte << 4) | v; + digits++; + + if (digits == 2) { + /* + * We have a byte. Put it somewhere. + */ + if (pos < lenof(state->seedbuf)) + state->seedbuf[pos++] = byte; + else if (pos < lenof(state->seedbuf) + lenof(state->databuf)) + state->databuf[pos++ - lenof(state->seedbuf)] = byte; + else if (pos == lenof(state->seedbuf) + lenof(state->databuf) && + byte <= lenof(state->databuf)) + state->pos = byte; + byte = digits = 0; + } + } + + return state; +}