Mercurial > ~dholland > hg > ag > index.cgi
comparison 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 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:13d2b8934445 |
---|---|
1 /* | |
2 * AnaGram, A System for Syntax Directed Programming | |
3 * Copyright 1993 Parsifal Software. All Rights Reserved. | |
4 * Copyright 2006 David A. Holland. All Rights Reserved. | |
5 * See the file COPYING for license and usage terms. | |
6 * | |
7 * dosum.c - checksums. | |
8 */ | |
9 | |
10 /* | |
11 * Fletcher's check-sum routines for AnaGram | |
12 * | |
13 * Freely adapted from routines published in Dr. Dobbs Journal | |
14 * May 1992, p. 64 | |
15 * | |
16 * Revised as portable C in June 2006. | |
17 */ | |
18 | |
19 #include <stdint.h> | |
20 #include <string.h> | |
21 #include <assert.h> | |
22 | |
23 #include "bits.h" | |
24 | |
25 struct sumstate { | |
26 uint16_t k1, k2; | |
27 }; | |
28 | |
29 static void sumstate_init(struct sumstate *s, size_t length) { | |
30 s->k1 = (uint16_t) (length >> 16); | |
31 s->k2 = (uint16_t) length; | |
32 | |
33 if (s->k1 == 0) s->k1++; | |
34 if (s->k2 == 0) s->k2++; | |
35 } | |
36 | |
37 static void sumstate_sum(struct sumstate *s, const void *buf, size_t len) { | |
38 const uint8_t *cb; | |
39 unsigned i, n; | |
40 uint16_t x; | |
41 | |
42 cb = buf; | |
43 n = len/sizeof(uint16_t); | |
44 for (i=0; i<n; i++) { | |
45 | |
46 // read one octet at a time so the byte order is deterministic | |
47 x = *cb++; | |
48 x += ((uint16_t)*cb++) << 8; | |
49 | |
50 s->k1 += x; | |
51 if (s->k1 < x) s->k1++; | |
52 s->k2 += s->k1; | |
53 if (s->k2 < s->k1) s->k2++; | |
54 } | |
55 } | |
56 | |
57 static uint32_t sumstate_finish(struct sumstate *s) { | |
58 uint32_t sum; | |
59 | |
60 s->k1 ^= 0xffff; | |
61 s->k2 ^= 0xffff; | |
62 sum = 65535UL*s->k2 + s->k1; | |
63 | |
64 return sum; | |
65 } | |
66 | |
67 uint32_t dosum(const char *buf, size_t len, size_t skipstart, size_t skiplen) { | |
68 struct sumstate s; | |
69 unsigned fudge; | |
70 size_t numwords; | |
71 | |
72 assert(skiplen%2==0); | |
73 assert(skipstart==0 || skipstart+skiplen <= len); | |
74 sumstate_init(&s, len); | |
75 | |
76 /* | |
77 * It would be nice if we could count on skipstart being aligned. | |
78 * But we can't. Nor is the filesize necessarily even. | |
79 * | |
80 * The followed mangled logic that rounds some things up matches | |
81 * what used to be done in an even uglier way. | |
82 */ | |
83 | |
84 assert(sizeof(uint16_t)==2); | |
85 numwords = (len+1)/2; | |
86 | |
87 if (skipstart > 0) { | |
88 size_t p0 = skipstart+skiplen; | |
89 size_t l0 = (numwords - p0/2) * 2; | |
90 size_t p1 = 0; | |
91 size_t l1 = (skipstart/2) * 2; | |
92 | |
93 fudge = skipstart%2; | |
94 sumstate_sum(&s, buf+p0, l0); | |
95 sumstate_sum(&s, buf+p1, l1); | |
96 } | |
97 else { | |
98 sumstate_sum(&s, buf, numwords * 2); | |
99 } | |
100 | |
101 return sumstate_finish(&s); | |
102 } |