|
20 | 20 |
|
21 | 21 | #include <stdlib.h> |
22 | 22 | #include <string.h> |
| 23 | +#include <zlib.h> |
23 | 24 | #include "delta.h" |
24 | 25 |
|
25 | 26 |
|
| 27 | +/* block size: min = 16, max = 64k, power of 2 */ |
| 28 | +#define BLK_SIZE 16 |
| 29 | + |
| 30 | +#define MIN(a, b) ((a) < (b) ? (a) : (b)) |
| 31 | + |
| 32 | +#define GR_PRIME 0x9e370001 |
| 33 | +#define HASH(v, shift) (((unsigned int)(v) * GR_PRIME) >> (shift)) |
| 34 | + |
26 | 35 | struct index { |
27 | 36 | const unsigned char *ptr; |
| 37 | + unsigned int val; |
28 | 38 | struct index *next; |
29 | 39 | }; |
30 | 40 |
|
31 | 41 | static struct index ** delta_index(const unsigned char *buf, |
32 | 42 | unsigned long bufsize, |
33 | 43 | unsigned int *hash_shift) |
34 | 44 | { |
35 | | - unsigned long hsize; |
36 | | - unsigned int hshift, i; |
| 45 | + unsigned int hsize, hshift, entries, blksize, i; |
37 | 46 | const unsigned char *data; |
38 | 47 | struct index *entry, **hash; |
39 | 48 | void *mem; |
40 | 49 |
|
41 | 50 | /* determine index hash size */ |
42 | | - hsize = bufsize / 4; |
43 | | - for (i = 8; (1 << i) < hsize && i < 16; i++); |
| 51 | + entries = (bufsize + BLK_SIZE - 1) / BLK_SIZE; |
| 52 | + hsize = entries / 4; |
| 53 | + for (i = 4; (1 << i) < hsize && i < 16; i++); |
44 | 54 | hsize = 1 << i; |
45 | | - hshift = i - 8; |
| 55 | + hshift = 32 - i; |
46 | 56 | *hash_shift = hshift; |
47 | 57 |
|
48 | 58 | /* allocate lookup index */ |
49 | | - mem = malloc(hsize * sizeof(*hash) + bufsize * sizeof(*entry)); |
| 59 | + mem = malloc(hsize * sizeof(*hash) + entries * sizeof(*entry)); |
50 | 60 | if (!mem) |
51 | 61 | return NULL; |
52 | 62 | hash = mem; |
53 | 63 | entry = mem + hsize * sizeof(*hash); |
54 | 64 | memset(hash, 0, hsize * sizeof(*hash)); |
55 | 65 |
|
56 | 66 | /* then populate it */ |
57 | | - data = buf + bufsize - 2; |
58 | | - while (data > buf) { |
59 | | - entry->ptr = --data; |
60 | | - i = data[0] ^ data[1] ^ (data[2] << hshift); |
| 67 | + data = buf + entries * BLK_SIZE - BLK_SIZE; |
| 68 | + blksize = bufsize - (data - buf); |
| 69 | + while (data >= buf) { |
| 70 | + unsigned int val = adler32(0, data, blksize); |
| 71 | + i = HASH(val, hshift); |
| 72 | + entry->ptr = data; |
| 73 | + entry->val = val; |
61 | 74 | entry->next = hash[i]; |
62 | 75 | hash[i] = entry++; |
| 76 | + blksize = BLK_SIZE; |
| 77 | + data -= BLK_SIZE; |
63 | 78 | } |
64 | 79 |
|
65 | 80 | return hash; |
@@ -126,27 +141,29 @@ void *diff_delta(void *from_buf, unsigned long from_size, |
126 | 141 |
|
127 | 142 | while (data < top) { |
128 | 143 | unsigned int moff = 0, msize = 0; |
129 | | - if (data + 2 < top) { |
130 | | - i = data[0] ^ data[1] ^ (data[2] << hash_shift); |
131 | | - for (entry = hash[i]; entry; entry = entry->next) { |
132 | | - const unsigned char *ref = entry->ptr; |
133 | | - const unsigned char *src = data; |
134 | | - unsigned int ref_size = ref_top - ref; |
135 | | - if (ref_size > top - src) |
136 | | - ref_size = top - src; |
137 | | - if (ref_size > 0x10000) |
138 | | - ref_size = 0x10000; |
139 | | - if (ref_size <= msize) |
| 144 | + unsigned int blksize = MIN(top - data, BLK_SIZE); |
| 145 | + unsigned int val = adler32(0, data, blksize); |
| 146 | + i = HASH(val, hash_shift); |
| 147 | + for (entry = hash[i]; entry; entry = entry->next) { |
| 148 | + const unsigned char *ref = entry->ptr; |
| 149 | + const unsigned char *src = data; |
| 150 | + unsigned int ref_size = ref_top - ref; |
| 151 | + if (entry->val != val) |
| 152 | + continue; |
| 153 | + if (ref_size > top - src) |
| 154 | + ref_size = top - src; |
| 155 | + while (ref_size && *src++ == *ref) { |
| 156 | + ref++; |
| 157 | + ref_size--; |
| 158 | + } |
| 159 | + ref_size = ref - entry->ptr; |
| 160 | + if (ref_size > msize) { |
| 161 | + /* this is our best match so far */ |
| 162 | + moff = entry->ptr - ref_data; |
| 163 | + msize = ref_size; |
| 164 | + if (msize >= 0x10000) { |
| 165 | + msize = 0x10000; |
140 | 166 | break; |
141 | | - while (ref_size && *src++ == *ref) { |
142 | | - ref++; |
143 | | - ref_size--; |
144 | | - } |
145 | | - ref_size = ref - entry->ptr; |
146 | | - if (msize < ref - entry->ptr) { |
147 | | - /* this is our best match so far */ |
148 | | - msize = ref - entry->ptr; |
149 | | - moff = entry->ptr - ref_data; |
150 | 167 | } |
151 | 168 | } |
152 | 169 | } |
|
0 commit comments