1/*
2 * diff-delta.c: generate a delta between two buffers
3 *
4 * Many parts of this file have been lifted from LibXDiff version 0.10.
5 * http://www.xmailserver.org/xdiff-lib.html
6 *
7 * LibXDiff was written by Davide Libenzi <davidel@xmailserver.org>
8 * Copyright (C) 2003 Davide Libenzi
9 *
10 * Many mods for GIT usage by Nicolas Pitre <nico@cam.org>, (C) 2005.
11 *
12 * This file is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public
14 * License as published by the Free Software Foundation; either
15 * version 2.1 of the License, or (at your option) any later version.
16 *
17 * Use of this within git automatically means that the LGPL
18 * licensing gets turned into GPLv2 within this project.
19 */
20
21#include <stdlib.h>
22#include <string.h>
23#include "delta.h"
24
25
26/* maximum hash entry list for the same hash bucket */
27#define HASH_LIMIT 64
28
29#define RABIN_SHIFT 23
30#define RABIN_WINDOW 16
31
32static const unsigned int T[256] = {
33 0x00000000, 0xab59b4d1, 0x56b369a2, 0xfdeadd73, 0x063f6795, 0xad66d344,
34 0x508c0e37, 0xfbd5bae6, 0x0c7ecf2a, 0xa7277bfb, 0x5acda688, 0xf1941259,
35 0x0a41a8bf, 0xa1181c6e, 0x5cf2c11d, 0xf7ab75cc, 0x18fd9e54, 0xb3a42a85,
36 0x4e4ef7f6, 0xe5174327, 0x1ec2f9c1, 0xb59b4d10, 0x48719063, 0xe32824b2,
37 0x1483517e, 0xbfdae5af, 0x423038dc, 0xe9698c0d, 0x12bc36eb, 0xb9e5823a,
38 0x440f5f49, 0xef56eb98, 0x31fb3ca8, 0x9aa28879, 0x6748550a, 0xcc11e1db,
39 0x37c45b3d, 0x9c9defec, 0x6177329f, 0xca2e864e, 0x3d85f382, 0x96dc4753,
40 0x6b369a20, 0xc06f2ef1, 0x3bba9417, 0x90e320c6, 0x6d09fdb5, 0xc6504964,
41 0x2906a2fc, 0x825f162d, 0x7fb5cb5e, 0xd4ec7f8f, 0x2f39c569, 0x846071b8,
42 0x798aaccb, 0xd2d3181a, 0x25786dd6, 0x8e21d907, 0x73cb0474, 0xd892b0a5,
43 0x23470a43, 0x881ebe92, 0x75f463e1, 0xdeadd730, 0x63f67950, 0xc8afcd81,
44 0x354510f2, 0x9e1ca423, 0x65c91ec5, 0xce90aa14, 0x337a7767, 0x9823c3b6,
45 0x6f88b67a, 0xc4d102ab, 0x393bdfd8, 0x92626b09, 0x69b7d1ef, 0xc2ee653e,
46 0x3f04b84d, 0x945d0c9c, 0x7b0be704, 0xd05253d5, 0x2db88ea6, 0x86e13a77,
47 0x7d348091, 0xd66d3440, 0x2b87e933, 0x80de5de2, 0x7775282e, 0xdc2c9cff,
48 0x21c6418c, 0x8a9ff55d, 0x714a4fbb, 0xda13fb6a, 0x27f92619, 0x8ca092c8,
49 0x520d45f8, 0xf954f129, 0x04be2c5a, 0xafe7988b, 0x5432226d, 0xff6b96bc,
50 0x02814bcf, 0xa9d8ff1e, 0x5e738ad2, 0xf52a3e03, 0x08c0e370, 0xa39957a1,
51 0x584ced47, 0xf3155996, 0x0eff84e5, 0xa5a63034, 0x4af0dbac, 0xe1a96f7d,
52 0x1c43b20e, 0xb71a06df, 0x4ccfbc39, 0xe79608e8, 0x1a7cd59b, 0xb125614a,
53 0x468e1486, 0xedd7a057, 0x103d7d24, 0xbb64c9f5, 0x40b17313, 0xebe8c7c2,
54 0x16021ab1, 0xbd5bae60, 0x6cb54671, 0xc7ecf2a0, 0x3a062fd3, 0x915f9b02,
55 0x6a8a21e4, 0xc1d39535, 0x3c394846, 0x9760fc97, 0x60cb895b, 0xcb923d8a,
56 0x3678e0f9, 0x9d215428, 0x66f4eece, 0xcdad5a1f, 0x3047876c, 0x9b1e33bd,
57 0x7448d825, 0xdf116cf4, 0x22fbb187, 0x89a20556, 0x7277bfb0, 0xd92e0b61,
58 0x24c4d612, 0x8f9d62c3, 0x7836170f, 0xd36fa3de, 0x2e857ead, 0x85dcca7c,
59 0x7e09709a, 0xd550c44b, 0x28ba1938, 0x83e3ade9, 0x5d4e7ad9, 0xf617ce08,
60 0x0bfd137b, 0xa0a4a7aa, 0x5b711d4c, 0xf028a99d, 0x0dc274ee, 0xa69bc03f,
61 0x5130b5f3, 0xfa690122, 0x0783dc51, 0xacda6880, 0x570fd266, 0xfc5666b7,
62 0x01bcbbc4, 0xaae50f15, 0x45b3e48d, 0xeeea505c, 0x13008d2f, 0xb85939fe,
63 0x438c8318, 0xe8d537c9, 0x153feaba, 0xbe665e6b, 0x49cd2ba7, 0xe2949f76,
64 0x1f7e4205, 0xb427f6d4, 0x4ff24c32, 0xe4abf8e3, 0x19412590, 0xb2189141,
65 0x0f433f21, 0xa41a8bf0, 0x59f05683, 0xf2a9e252, 0x097c58b4, 0xa225ec65,
66 0x5fcf3116, 0xf49685c7, 0x033df00b, 0xa86444da, 0x558e99a9, 0xfed72d78,
67 0x0502979e, 0xae5b234f, 0x53b1fe3c, 0xf8e84aed, 0x17bea175, 0xbce715a4,
68 0x410dc8d7, 0xea547c06, 0x1181c6e0, 0xbad87231, 0x4732af42, 0xec6b1b93,
69 0x1bc06e5f, 0xb099da8e, 0x4d7307fd, 0xe62ab32c, 0x1dff09ca, 0xb6a6bd1b,
70 0x4b4c6068, 0xe015d4b9, 0x3eb80389, 0x95e1b758, 0x680b6a2b, 0xc352defa,
71 0x3887641c, 0x93ded0cd, 0x6e340dbe, 0xc56db96f, 0x32c6cca3, 0x999f7872,
72 0x6475a501, 0xcf2c11d0, 0x34f9ab36, 0x9fa01fe7, 0x624ac294, 0xc9137645,
73 0x26459ddd, 0x8d1c290c, 0x70f6f47f, 0xdbaf40ae, 0x207afa48, 0x8b234e99,
74 0x76c993ea, 0xdd90273b, 0x2a3b52f7, 0x8162e626, 0x7c883b55, 0xd7d18f84,
75 0x2c043562, 0x875d81b3, 0x7ab75cc0, 0xd1eee811
76};
77
78static const unsigned int U[256] = {
79 0x00000000, 0x7eb5200d, 0x5633f4cb, 0x2886d4c6, 0x073e5d47, 0x798b7d4a,
80 0x510da98c, 0x2fb88981, 0x0e7cba8e, 0x70c99a83, 0x584f4e45, 0x26fa6e48,
81 0x0942e7c9, 0x77f7c7c4, 0x5f711302, 0x21c4330f, 0x1cf9751c, 0x624c5511,
82 0x4aca81d7, 0x347fa1da, 0x1bc7285b, 0x65720856, 0x4df4dc90, 0x3341fc9d,
83 0x1285cf92, 0x6c30ef9f, 0x44b63b59, 0x3a031b54, 0x15bb92d5, 0x6b0eb2d8,
84 0x4388661e, 0x3d3d4613, 0x39f2ea38, 0x4747ca35, 0x6fc11ef3, 0x11743efe,
85 0x3eccb77f, 0x40799772, 0x68ff43b4, 0x164a63b9, 0x378e50b6, 0x493b70bb,
86 0x61bda47d, 0x1f088470, 0x30b00df1, 0x4e052dfc, 0x6683f93a, 0x1836d937,
87 0x250b9f24, 0x5bbebf29, 0x73386bef, 0x0d8d4be2, 0x2235c263, 0x5c80e26e,
88 0x740636a8, 0x0ab316a5, 0x2b7725aa, 0x55c205a7, 0x7d44d161, 0x03f1f16c,
89 0x2c4978ed, 0x52fc58e0, 0x7a7a8c26, 0x04cfac2b, 0x73e5d470, 0x0d50f47d,
90 0x25d620bb, 0x5b6300b6, 0x74db8937, 0x0a6ea93a, 0x22e87dfc, 0x5c5d5df1,
91 0x7d996efe, 0x032c4ef3, 0x2baa9a35, 0x551fba38, 0x7aa733b9, 0x041213b4,
92 0x2c94c772, 0x5221e77f, 0x6f1ca16c, 0x11a98161, 0x392f55a7, 0x479a75aa,
93 0x6822fc2b, 0x1697dc26, 0x3e1108e0, 0x40a428ed, 0x61601be2, 0x1fd53bef,
94 0x3753ef29, 0x49e6cf24, 0x665e46a5, 0x18eb66a8, 0x306db26e, 0x4ed89263,
95 0x4a173e48, 0x34a21e45, 0x1c24ca83, 0x6291ea8e, 0x4d29630f, 0x339c4302,
96 0x1b1a97c4, 0x65afb7c9, 0x446b84c6, 0x3adea4cb, 0x1258700d, 0x6ced5000,
97 0x4355d981, 0x3de0f98c, 0x15662d4a, 0x6bd30d47, 0x56ee4b54, 0x285b6b59,
98 0x00ddbf9f, 0x7e689f92, 0x51d01613, 0x2f65361e, 0x07e3e2d8, 0x7956c2d5,
99 0x5892f1da, 0x2627d1d7, 0x0ea10511, 0x7014251c, 0x5facac9d, 0x21198c90,
100 0x099f5856, 0x772a785b, 0x4c921c31, 0x32273c3c, 0x1aa1e8fa, 0x6414c8f7,
101 0x4bac4176, 0x3519617b, 0x1d9fb5bd, 0x632a95b0, 0x42eea6bf, 0x3c5b86b2,
102 0x14dd5274, 0x6a687279, 0x45d0fbf8, 0x3b65dbf5, 0x13e30f33, 0x6d562f3e,
103 0x506b692d, 0x2ede4920, 0x06589de6, 0x78edbdeb, 0x5755346a, 0x29e01467,
104 0x0166c0a1, 0x7fd3e0ac, 0x5e17d3a3, 0x20a2f3ae, 0x08242768, 0x76910765,
105 0x59298ee4, 0x279caee9, 0x0f1a7a2f, 0x71af5a22, 0x7560f609, 0x0bd5d604,
106 0x235302c2, 0x5de622cf, 0x725eab4e, 0x0ceb8b43, 0x246d5f85, 0x5ad87f88,
107 0x7b1c4c87, 0x05a96c8a, 0x2d2fb84c, 0x539a9841, 0x7c2211c0, 0x029731cd,
108 0x2a11e50b, 0x54a4c506, 0x69998315, 0x172ca318, 0x3faa77de, 0x411f57d3,
109 0x6ea7de52, 0x1012fe5f, 0x38942a99, 0x46210a94, 0x67e5399b, 0x19501996,
110 0x31d6cd50, 0x4f63ed5d, 0x60db64dc, 0x1e6e44d1, 0x36e89017, 0x485db01a,
111 0x3f77c841, 0x41c2e84c, 0x69443c8a, 0x17f11c87, 0x38499506, 0x46fcb50b,
112 0x6e7a61cd, 0x10cf41c0, 0x310b72cf, 0x4fbe52c2, 0x67388604, 0x198da609,
113 0x36352f88, 0x48800f85, 0x6006db43, 0x1eb3fb4e, 0x238ebd5d, 0x5d3b9d50,
114 0x75bd4996, 0x0b08699b, 0x24b0e01a, 0x5a05c017, 0x728314d1, 0x0c3634dc,
115 0x2df207d3, 0x534727de, 0x7bc1f318, 0x0574d315, 0x2acc5a94, 0x54797a99,
116 0x7cffae5f, 0x024a8e52, 0x06852279, 0x78300274, 0x50b6d6b2, 0x2e03f6bf,
117 0x01bb7f3e, 0x7f0e5f33, 0x57888bf5, 0x293dabf8, 0x08f998f7, 0x764cb8fa,
118 0x5eca6c3c, 0x207f4c31, 0x0fc7c5b0, 0x7172e5bd, 0x59f4317b, 0x27411176,
119 0x1a7c5765, 0x64c97768, 0x4c4fa3ae, 0x32fa83a3, 0x1d420a22, 0x63f72a2f,
120 0x4b71fee9, 0x35c4dee4, 0x1400edeb, 0x6ab5cde6, 0x42331920, 0x3c86392d,
121 0x133eb0ac, 0x6d8b90a1, 0x450d4467, 0x3bb8646a
122};
123
124struct index_entry {
125 const unsigned char *ptr;
126 unsigned int val;
127 struct index_entry *next;
128};
129
130struct delta_index {
131 const void *src_buf;
132 unsigned long src_size;
133 unsigned int hash_mask;
134 struct index_entry *hash[0];
135};
136
137struct delta_index * create_delta_index(const void *buf, unsigned long bufsize)
138{
139 unsigned int i, hsize, hmask, entries, prev_val, *hash_count;
140 const unsigned char *data, *buffer = buf;
141 struct delta_index *index;
142 struct index_entry *entry, **hash;
143 void *mem;
144 unsigned long memsize;
145
146 if (!buf || !bufsize)
147 return NULL;
148
149 /* Determine index hash size. Note that indexing skips the
150 first byte to allow for optimizing the rabin polynomial
151 initialization in create_delta(). */
152 entries = (bufsize - 1) / RABIN_WINDOW;
153 hsize = entries / 4;
154 for (i = 4; (1 << i) < hsize && i < 31; i++);
155 hsize = 1 << i;
156 hmask = hsize - 1;
157
158 /* allocate lookup index */
159 memsize = sizeof(*index) +
160 sizeof(*hash) * hsize +
161 sizeof(*entry) * entries;
162 mem = malloc(memsize);
163 if (!mem)
164 return NULL;
165 index = mem;
166 mem = index + 1;
167 hash = mem;
168 mem = hash + hsize;
169 entry = mem;
170
171 index->src_buf = buf;
172 index->src_size = bufsize;
173 index->hash_mask = hmask;
174 memset(hash, 0, hsize * sizeof(*hash));
175
176 /* allocate an array to count hash entries */
177 hash_count = calloc(hsize, sizeof(*hash_count));
178 if (!hash_count) {
179 free(index);
180 return NULL;
181 }
182
183 /* then populate the index */
184 prev_val = ~0;
185 for (data = buffer + entries * RABIN_WINDOW - RABIN_WINDOW;
186 data >= buffer;
187 data -= RABIN_WINDOW) {
188 unsigned int val = 0;
189 for (i = 1; i <= RABIN_WINDOW; i++)
190 val = ((val << 8) | data[i]) ^ T[val >> RABIN_SHIFT];
191 if (val == prev_val) {
192 /* keep the lowest of consecutive identical blocks */
193 entry[-1].ptr = data + RABIN_WINDOW;
194 } else {
195 prev_val = val;
196 i = val & hmask;
197 entry->ptr = data + RABIN_WINDOW;
198 entry->val = val;
199 entry->next = hash[i];
200 hash[i] = entry++;
201 hash_count[i]++;
202 entries--;
203 }
204 }
205
206 /*
207 * Determine a limit on the number of entries in the same hash
208 * bucket. This guard us against patological data sets causing
209 * really bad hash distribution with most entries in the same hash
210 * bucket that would bring us to O(m*n) computing costs (m and n
211 * corresponding to reference and target buffer sizes).
212 *
213 * Make sure none of the hash buckets has more entries than
214 * we're willing to test. Otherwise we cull the entry list
215 * uniformly to still preserve a good repartition across
216 * the reference buffer.
217 */
218 for (i = 0; i < hsize; i++) {
219 if (hash_count[i] < HASH_LIMIT)
220 continue;
221 entry = hash[i];
222 do {
223 struct index_entry *keep = entry;
224 int skip = hash_count[i] / HASH_LIMIT / 2;
225 do {
226 entry = entry->next;
227 } while(--skip && entry);
228 keep->next = entry;
229 } while(entry);
230 }
231 free(hash_count);
232
233 /* If we didn't use all hash entries, free the unused memory. */
234 if (entries)
235 index = realloc(index, memsize - entries * sizeof(*entry));
236
237 return index;
238}
239
240void free_delta_index(struct delta_index *index)
241{
242 free(index);
243}
244
245/*
246 * The maximum size for any opcode sequence, including the initial header
247 * plus rabin window plus biggest copy.
248 */
249#define MAX_OP_SIZE (5 + 5 + 1 + RABIN_WINDOW + 7)
250
251void *
252create_delta(const struct delta_index *index,
253 const void *trg_buf, unsigned long trg_size,
254 unsigned long *delta_size, unsigned long max_size)
255{
256 unsigned int i, outpos, outsize, val;
257 int inscnt;
258 const unsigned char *ref_data, *ref_top, *data, *top;
259 unsigned char *out;
260
261 if (!trg_buf || !trg_size)
262 return NULL;
263
264 outpos = 0;
265 outsize = 8192;
266 if (max_size && outsize >= max_size)
267 outsize = max_size + MAX_OP_SIZE + 1;
268 out = malloc(outsize);
269 if (!out)
270 return NULL;
271
272 /* store reference buffer size */
273 i = index->src_size;
274 while (i >= 0x80) {
275 out[outpos++] = i | 0x80;
276 i >>= 7;
277 }
278 out[outpos++] = i;
279
280 /* store target buffer size */
281 i = trg_size;
282 while (i >= 0x80) {
283 out[outpos++] = i | 0x80;
284 i >>= 7;
285 }
286 out[outpos++] = i;
287
288 ref_data = index->src_buf;
289 ref_top = ref_data + index->src_size;
290 data = trg_buf;
291 top = trg_buf + trg_size;
292
293 outpos++;
294 val = 0;
295 for (i = 0; i < RABIN_WINDOW && data < top; i++, data++) {
296 out[outpos++] = *data;
297 val = ((val << 8) | *data) ^ T[val >> RABIN_SHIFT];
298 }
299 inscnt = i;
300
301 while (data < top) {
302 unsigned int moff = 0, msize = 0;
303 struct index_entry *entry;
304 val ^= U[data[-RABIN_WINDOW]];
305 val = ((val << 8) | *data) ^ T[val >> RABIN_SHIFT];
306 i = val & index->hash_mask;
307 for (entry = index->hash[i]; entry; entry = entry->next) {
308 const unsigned char *ref = entry->ptr;
309 const unsigned char *src = data;
310 unsigned int ref_size = ref_top - ref;
311 if (entry->val != val)
312 continue;
313 if (ref_size > top - src)
314 ref_size = top - src;
315 if (ref_size > 0x10000)
316 ref_size = 0x10000;
317 if (ref_size <= msize)
318 break;
319 while (ref_size-- && *src++ == *ref)
320 ref++;
321 if (msize < ref - entry->ptr) {
322 /* this is our best match so far */
323 msize = ref - entry->ptr;
324 moff = entry->ptr - ref_data;
325 }
326 }
327
328 if (msize < 4) {
329 if (!inscnt)
330 outpos++;
331 out[outpos++] = *data++;
332 inscnt++;
333 if (inscnt == 0x7f) {
334 out[outpos - inscnt - 1] = inscnt;
335 inscnt = 0;
336 }
337 } else {
338 unsigned char *op;
339
340 if (msize >= RABIN_WINDOW) {
341 const unsigned char *sk;
342 sk = data + msize - RABIN_WINDOW;
343 val = 0;
344 for (i = 0; i < RABIN_WINDOW; i++)
345 val = ((val << 8) | *sk++) ^ T[val >> RABIN_SHIFT];
346 } else {
347 const unsigned char *sk = data + 1;
348 for (i = 1; i < msize; i++) {
349 val ^= U[sk[-RABIN_WINDOW]];
350 val = ((val << 8) | *sk++) ^ T[val >> RABIN_SHIFT];
351 }
352 }
353
354 if (inscnt) {
355 while (moff && ref_data[moff-1] == data[-1]) {
356 if (msize == 0x10000)
357 break;
358 /* we can match one byte back */
359 msize++;
360 moff--;
361 data--;
362 outpos--;
363 if (--inscnt)
364 continue;
365 outpos--; /* remove count slot */
366 inscnt--; /* make it -1 */
367 break;
368 }
369 out[outpos - inscnt - 1] = inscnt;
370 inscnt = 0;
371 }
372
373 data += msize;
374 op = out + outpos++;
375 i = 0x80;
376
377 if (moff & 0xff) { out[outpos++] = moff; i |= 0x01; }
378 moff >>= 8;
379 if (moff & 0xff) { out[outpos++] = moff; i |= 0x02; }
380 moff >>= 8;
381 if (moff & 0xff) { out[outpos++] = moff; i |= 0x04; }
382 moff >>= 8;
383 if (moff & 0xff) { out[outpos++] = moff; i |= 0x08; }
384
385 if (msize & 0xff) { out[outpos++] = msize; i |= 0x10; }
386 msize >>= 8;
387 if (msize & 0xff) { out[outpos++] = msize; i |= 0x20; }
388
389 *op = i;
390 }
391
392 if (outpos >= outsize - MAX_OP_SIZE) {
393 void *tmp = out;
394 outsize = outsize * 3 / 2;
395 if (max_size && outsize >= max_size)
396 outsize = max_size + MAX_OP_SIZE + 1;
397 if (max_size && outpos > max_size)
398 break;
399 out = realloc(out, outsize);
400 if (!out) {
401 free(tmp);
402 return NULL;
403 }
404 }
405 }
406
407 if (inscnt)
408 out[outpos - inscnt - 1] = inscnt;
409
410 if (max_size && outpos > max_size) {
411 free(out);
412 return NULL;
413 }
414
415 *delta_size = outpos;
416 return out;
417}