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 }