Mercurial > ~dholland > hg > ag > index.cgi
diff checksum/dosum.c @ 0:13d2b8934445
Import AnaGram (near-)release tree into Mercurial.
author | David A. Holland |
---|---|
date | Sat, 22 Dec 2007 17:52:45 -0500 |
parents | |
children | 3aa0f5a02342 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/checksum/dosum.c Sat Dec 22 17:52:45 2007 -0500 @@ -0,0 +1,102 @@ +/* + * AnaGram, A System for Syntax Directed Programming + * Copyright 1993 Parsifal Software. All Rights Reserved. + * Copyright 2006 David A. Holland. All Rights Reserved. + * See the file COPYING for license and usage terms. + * + * dosum.c - checksums. + */ + +/* + * Fletcher's check-sum routines for AnaGram + * + * Freely adapted from routines published in Dr. Dobbs Journal + * May 1992, p. 64 + * + * Revised as portable C in June 2006. + */ + +#include <stdint.h> +#include <string.h> +#include <assert.h> + +#include "bits.h" + +struct sumstate { + uint16_t k1, k2; +}; + +static void sumstate_init(struct sumstate *s, size_t length) { + s->k1 = (uint16_t) (length >> 16); + s->k2 = (uint16_t) length; + + if (s->k1 == 0) s->k1++; + if (s->k2 == 0) s->k2++; +} + +static void sumstate_sum(struct sumstate *s, const void *buf, size_t len) { + const uint8_t *cb; + unsigned i, n; + uint16_t x; + + cb = buf; + n = len/sizeof(uint16_t); + for (i=0; i<n; i++) { + + // read one octet at a time so the byte order is deterministic + x = *cb++; + x += ((uint16_t)*cb++) << 8; + + s->k1 += x; + if (s->k1 < x) s->k1++; + s->k2 += s->k1; + if (s->k2 < s->k1) s->k2++; + } +} + +static uint32_t sumstate_finish(struct sumstate *s) { + uint32_t sum; + + s->k1 ^= 0xffff; + s->k2 ^= 0xffff; + sum = 65535UL*s->k2 + s->k1; + + return sum; +} + +uint32_t dosum(const char *buf, size_t len, size_t skipstart, size_t skiplen) { + struct sumstate s; + unsigned fudge; + size_t numwords; + + assert(skiplen%2==0); + assert(skipstart==0 || skipstart+skiplen <= len); + sumstate_init(&s, len); + + /* + * It would be nice if we could count on skipstart being aligned. + * But we can't. Nor is the filesize necessarily even. + * + * The followed mangled logic that rounds some things up matches + * what used to be done in an even uglier way. + */ + + assert(sizeof(uint16_t)==2); + numwords = (len+1)/2; + + if (skipstart > 0) { + size_t p0 = skipstart+skiplen; + size_t l0 = (numwords - p0/2) * 2; + size_t p1 = 0; + size_t l1 = (skipstart/2) * 2; + + fudge = skipstart%2; + sumstate_sum(&s, buf+p0, l0); + sumstate_sum(&s, buf+p1, l1); + } + else { + sumstate_sum(&s, buf, numwords * 2); + } + + return sumstate_finish(&s); +}