/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
0.23.2 by Nicolas Pitre
Add the diff-delta.c and patch-delta.c files.
1
/*
2
 * diff-delta.c: generate a delta between two buffers
3
 *
4
 * This code was greatly inspired by parts of LibXDiff from Davide Libenzi
5
 * http://www.xmailserver.org/xdiff-lib.html
6
 *
7
 * Rewritten for GIT by Nicolas Pitre <nico@cam.org>, (C) 2005-2007
8
 *
9
 * This code is free software; you can redistribute it and/or modify
10
 * it under the terms of the GNU General Public License version 2 as
11
 * published by the Free Software Foundation.
12
 */
13
14
#include "delta.h"
0.23.5 by John Arbash Meinel
Minor changes to get diff-delta.c and patch-delta.c to compile.
15
#include <assert.h>
0.23.2 by Nicolas Pitre
Add the diff-delta.c and patch-delta.c files.
16
17
/* maximum hash entry list for the same hash bucket */
18
#define HASH_LIMIT 64
19
20
#define RABIN_SHIFT 23
21
#define RABIN_WINDOW 16
22
23
static const unsigned int T[256] = {
24
	0x00000000, 0xab59b4d1, 0x56b369a2, 0xfdeadd73, 0x063f6795, 0xad66d344,
25
	0x508c0e37, 0xfbd5bae6, 0x0c7ecf2a, 0xa7277bfb, 0x5acda688, 0xf1941259,
26
	0x0a41a8bf, 0xa1181c6e, 0x5cf2c11d, 0xf7ab75cc, 0x18fd9e54, 0xb3a42a85,
27
	0x4e4ef7f6, 0xe5174327, 0x1ec2f9c1, 0xb59b4d10, 0x48719063, 0xe32824b2,
28
	0x1483517e, 0xbfdae5af, 0x423038dc, 0xe9698c0d, 0x12bc36eb, 0xb9e5823a,
29
	0x440f5f49, 0xef56eb98, 0x31fb3ca8, 0x9aa28879, 0x6748550a, 0xcc11e1db,
30
	0x37c45b3d, 0x9c9defec, 0x6177329f, 0xca2e864e, 0x3d85f382, 0x96dc4753,
31
	0x6b369a20, 0xc06f2ef1, 0x3bba9417, 0x90e320c6, 0x6d09fdb5, 0xc6504964,
32
	0x2906a2fc, 0x825f162d, 0x7fb5cb5e, 0xd4ec7f8f, 0x2f39c569, 0x846071b8,
33
	0x798aaccb, 0xd2d3181a, 0x25786dd6, 0x8e21d907, 0x73cb0474, 0xd892b0a5,
34
	0x23470a43, 0x881ebe92, 0x75f463e1, 0xdeadd730, 0x63f67950, 0xc8afcd81,
35
	0x354510f2, 0x9e1ca423, 0x65c91ec5, 0xce90aa14, 0x337a7767, 0x9823c3b6,
36
	0x6f88b67a, 0xc4d102ab, 0x393bdfd8, 0x92626b09, 0x69b7d1ef, 0xc2ee653e,
37
	0x3f04b84d, 0x945d0c9c, 0x7b0be704, 0xd05253d5, 0x2db88ea6, 0x86e13a77,
38
	0x7d348091, 0xd66d3440, 0x2b87e933, 0x80de5de2, 0x7775282e, 0xdc2c9cff,
39
	0x21c6418c, 0x8a9ff55d, 0x714a4fbb, 0xda13fb6a, 0x27f92619, 0x8ca092c8,
40
	0x520d45f8, 0xf954f129, 0x04be2c5a, 0xafe7988b, 0x5432226d, 0xff6b96bc,
41
	0x02814bcf, 0xa9d8ff1e, 0x5e738ad2, 0xf52a3e03, 0x08c0e370, 0xa39957a1,
42
	0x584ced47, 0xf3155996, 0x0eff84e5, 0xa5a63034, 0x4af0dbac, 0xe1a96f7d,
43
	0x1c43b20e, 0xb71a06df, 0x4ccfbc39, 0xe79608e8, 0x1a7cd59b, 0xb125614a,
44
	0x468e1486, 0xedd7a057, 0x103d7d24, 0xbb64c9f5, 0x40b17313, 0xebe8c7c2,
45
	0x16021ab1, 0xbd5bae60, 0x6cb54671, 0xc7ecf2a0, 0x3a062fd3, 0x915f9b02,
46
	0x6a8a21e4, 0xc1d39535, 0x3c394846, 0x9760fc97, 0x60cb895b, 0xcb923d8a,
47
	0x3678e0f9, 0x9d215428, 0x66f4eece, 0xcdad5a1f, 0x3047876c, 0x9b1e33bd,
48
	0x7448d825, 0xdf116cf4, 0x22fbb187, 0x89a20556, 0x7277bfb0, 0xd92e0b61,
49
	0x24c4d612, 0x8f9d62c3, 0x7836170f, 0xd36fa3de, 0x2e857ead, 0x85dcca7c,
50
	0x7e09709a, 0xd550c44b, 0x28ba1938, 0x83e3ade9, 0x5d4e7ad9, 0xf617ce08,
51
	0x0bfd137b, 0xa0a4a7aa, 0x5b711d4c, 0xf028a99d, 0x0dc274ee, 0xa69bc03f,
52
	0x5130b5f3, 0xfa690122, 0x0783dc51, 0xacda6880, 0x570fd266, 0xfc5666b7,
53
	0x01bcbbc4, 0xaae50f15, 0x45b3e48d, 0xeeea505c, 0x13008d2f, 0xb85939fe,
54
	0x438c8318, 0xe8d537c9, 0x153feaba, 0xbe665e6b, 0x49cd2ba7, 0xe2949f76,
55
	0x1f7e4205, 0xb427f6d4, 0x4ff24c32, 0xe4abf8e3, 0x19412590, 0xb2189141,
56
	0x0f433f21, 0xa41a8bf0, 0x59f05683, 0xf2a9e252, 0x097c58b4, 0xa225ec65,
57
	0x5fcf3116, 0xf49685c7, 0x033df00b, 0xa86444da, 0x558e99a9, 0xfed72d78,
58
	0x0502979e, 0xae5b234f, 0x53b1fe3c, 0xf8e84aed, 0x17bea175, 0xbce715a4,
59
	0x410dc8d7, 0xea547c06, 0x1181c6e0, 0xbad87231, 0x4732af42, 0xec6b1b93,
60
	0x1bc06e5f, 0xb099da8e, 0x4d7307fd, 0xe62ab32c, 0x1dff09ca, 0xb6a6bd1b,
61
	0x4b4c6068, 0xe015d4b9, 0x3eb80389, 0x95e1b758, 0x680b6a2b, 0xc352defa,
62
	0x3887641c, 0x93ded0cd, 0x6e340dbe, 0xc56db96f, 0x32c6cca3, 0x999f7872,
63
	0x6475a501, 0xcf2c11d0, 0x34f9ab36, 0x9fa01fe7, 0x624ac294, 0xc9137645,
64
	0x26459ddd, 0x8d1c290c, 0x70f6f47f, 0xdbaf40ae, 0x207afa48, 0x8b234e99,
65
	0x76c993ea, 0xdd90273b, 0x2a3b52f7, 0x8162e626, 0x7c883b55, 0xd7d18f84,
66
	0x2c043562, 0x875d81b3, 0x7ab75cc0, 0xd1eee811
67
};
68
69
static const unsigned int U[256] = {
70
	0x00000000, 0x7eb5200d, 0x5633f4cb, 0x2886d4c6, 0x073e5d47, 0x798b7d4a,
71
	0x510da98c, 0x2fb88981, 0x0e7cba8e, 0x70c99a83, 0x584f4e45, 0x26fa6e48,
72
	0x0942e7c9, 0x77f7c7c4, 0x5f711302, 0x21c4330f, 0x1cf9751c, 0x624c5511,
73
	0x4aca81d7, 0x347fa1da, 0x1bc7285b, 0x65720856, 0x4df4dc90, 0x3341fc9d,
74
	0x1285cf92, 0x6c30ef9f, 0x44b63b59, 0x3a031b54, 0x15bb92d5, 0x6b0eb2d8,
75
	0x4388661e, 0x3d3d4613, 0x39f2ea38, 0x4747ca35, 0x6fc11ef3, 0x11743efe,
76
	0x3eccb77f, 0x40799772, 0x68ff43b4, 0x164a63b9, 0x378e50b6, 0x493b70bb,
77
	0x61bda47d, 0x1f088470, 0x30b00df1, 0x4e052dfc, 0x6683f93a, 0x1836d937,
78
	0x250b9f24, 0x5bbebf29, 0x73386bef, 0x0d8d4be2, 0x2235c263, 0x5c80e26e,
79
	0x740636a8, 0x0ab316a5, 0x2b7725aa, 0x55c205a7, 0x7d44d161, 0x03f1f16c,
80
	0x2c4978ed, 0x52fc58e0, 0x7a7a8c26, 0x04cfac2b, 0x73e5d470, 0x0d50f47d,
81
	0x25d620bb, 0x5b6300b6, 0x74db8937, 0x0a6ea93a, 0x22e87dfc, 0x5c5d5df1,
82
	0x7d996efe, 0x032c4ef3, 0x2baa9a35, 0x551fba38, 0x7aa733b9, 0x041213b4,
83
	0x2c94c772, 0x5221e77f, 0x6f1ca16c, 0x11a98161, 0x392f55a7, 0x479a75aa,
84
	0x6822fc2b, 0x1697dc26, 0x3e1108e0, 0x40a428ed, 0x61601be2, 0x1fd53bef,
85
	0x3753ef29, 0x49e6cf24, 0x665e46a5, 0x18eb66a8, 0x306db26e, 0x4ed89263,
86
	0x4a173e48, 0x34a21e45, 0x1c24ca83, 0x6291ea8e, 0x4d29630f, 0x339c4302,
87
	0x1b1a97c4, 0x65afb7c9, 0x446b84c6, 0x3adea4cb, 0x1258700d, 0x6ced5000,
88
	0x4355d981, 0x3de0f98c, 0x15662d4a, 0x6bd30d47, 0x56ee4b54, 0x285b6b59,
89
	0x00ddbf9f, 0x7e689f92, 0x51d01613, 0x2f65361e, 0x07e3e2d8, 0x7956c2d5,
90
	0x5892f1da, 0x2627d1d7, 0x0ea10511, 0x7014251c, 0x5facac9d, 0x21198c90,
91
	0x099f5856, 0x772a785b, 0x4c921c31, 0x32273c3c, 0x1aa1e8fa, 0x6414c8f7,
92
	0x4bac4176, 0x3519617b, 0x1d9fb5bd, 0x632a95b0, 0x42eea6bf, 0x3c5b86b2,
93
	0x14dd5274, 0x6a687279, 0x45d0fbf8, 0x3b65dbf5, 0x13e30f33, 0x6d562f3e,
94
	0x506b692d, 0x2ede4920, 0x06589de6, 0x78edbdeb, 0x5755346a, 0x29e01467,
95
	0x0166c0a1, 0x7fd3e0ac, 0x5e17d3a3, 0x20a2f3ae, 0x08242768, 0x76910765,
96
	0x59298ee4, 0x279caee9, 0x0f1a7a2f, 0x71af5a22, 0x7560f609, 0x0bd5d604,
97
	0x235302c2, 0x5de622cf, 0x725eab4e, 0x0ceb8b43, 0x246d5f85, 0x5ad87f88,
98
	0x7b1c4c87, 0x05a96c8a, 0x2d2fb84c, 0x539a9841, 0x7c2211c0, 0x029731cd,
99
	0x2a11e50b, 0x54a4c506, 0x69998315, 0x172ca318, 0x3faa77de, 0x411f57d3,
100
	0x6ea7de52, 0x1012fe5f, 0x38942a99, 0x46210a94, 0x67e5399b, 0x19501996,
101
	0x31d6cd50, 0x4f63ed5d, 0x60db64dc, 0x1e6e44d1, 0x36e89017, 0x485db01a,
102
	0x3f77c841, 0x41c2e84c, 0x69443c8a, 0x17f11c87, 0x38499506, 0x46fcb50b,
103
	0x6e7a61cd, 0x10cf41c0, 0x310b72cf, 0x4fbe52c2, 0x67388604, 0x198da609,
104
	0x36352f88, 0x48800f85, 0x6006db43, 0x1eb3fb4e, 0x238ebd5d, 0x5d3b9d50,
105
	0x75bd4996, 0x0b08699b, 0x24b0e01a, 0x5a05c017, 0x728314d1, 0x0c3634dc,
106
	0x2df207d3, 0x534727de, 0x7bc1f318, 0x0574d315, 0x2acc5a94, 0x54797a99,
107
	0x7cffae5f, 0x024a8e52, 0x06852279, 0x78300274, 0x50b6d6b2, 0x2e03f6bf,
108
	0x01bb7f3e, 0x7f0e5f33, 0x57888bf5, 0x293dabf8, 0x08f998f7, 0x764cb8fa,
109
	0x5eca6c3c, 0x207f4c31, 0x0fc7c5b0, 0x7172e5bd, 0x59f4317b, 0x27411176,
110
	0x1a7c5765, 0x64c97768, 0x4c4fa3ae, 0x32fa83a3, 0x1d420a22, 0x63f72a2f,
111
	0x4b71fee9, 0x35c4dee4, 0x1400edeb, 0x6ab5cde6, 0x42331920, 0x3c86392d,
112
	0x133eb0ac, 0x6d8b90a1, 0x450d4467, 0x3bb8646a
113
};
114
115
struct index_entry {
116
	const unsigned char *ptr;
117
	unsigned int val;
118
};
119
120
struct unpacked_index_entry {
121
	struct index_entry entry;
122
	struct unpacked_index_entry *next;
123
};
124
125
struct delta_index {
0.23.24 by John Arbash Meinel
Change the code so that we can pass in multiple sources to match against.
126
	unsigned long memsize; /* Total bytes pointed to by this index */
127
	const void *src_buf; /* Pointer to the beginning of source data */
128
	unsigned long src_size; /* Total length of source data */
129
	unsigned long agg_src_offset; /* Start of source data as part of the
130
									 aggregate source */
131
	unsigned int hash_mask; /* val & hash_mask gives the hash index for a given
132
							   entry */
0.23.5 by John Arbash Meinel
Minor changes to get diff-delta.c and patch-delta.c to compile.
133
	struct index_entry *hash[];
0.23.2 by Nicolas Pitre
Add the diff-delta.c and patch-delta.c files.
134
};
135
0.23.24 by John Arbash Meinel
Change the code so that we can pass in multiple sources to match against.
136
struct delta_index * create_delta_index(const void *buf, unsigned long bufsize,
137
										unsigned long agg_src_offset)
0.23.2 by Nicolas Pitre
Add the diff-delta.c and patch-delta.c files.
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 unpacked_index_entry *entry, **hash;
143
	struct index_entry *packed_entry, **packed_hash;
144
	void *mem;
145
	unsigned long memsize;
146
147
	if (!buf || !bufsize)
148
		return NULL;
149
150
	/* Determine index hash size.  Note that indexing skips the
151
	   first byte to allow for optimizing the Rabin's polynomial
152
	   initialization in create_delta(). */
153
	entries = (bufsize - 1)  / RABIN_WINDOW;
154
	hsize = entries / 4;
155
	for (i = 4; (1u << i) < hsize && i < 31; i++);
156
	hsize = 1 << i;
157
	hmask = hsize - 1;
158
159
	/* allocate lookup index */
160
	memsize = sizeof(*hash) * hsize +
161
		  sizeof(*entry) * entries;
162
	mem = malloc(memsize);
163
	if (!mem)
164
		return NULL;
165
	hash = mem;
166
	mem = hash + hsize;
167
	entry = mem;
168
169
	memset(hash, 0, hsize * sizeof(*hash));
170
171
	/* allocate an array to count hash entries */
172
	hash_count = calloc(hsize, sizeof(*hash_count));
173
	if (!hash_count) {
174
		free(hash);
175
		return NULL;
176
	}
177
178
	/* then populate the index */
179
	prev_val = ~0;
180
	for (data = buffer + entries * RABIN_WINDOW - RABIN_WINDOW;
0.23.24 by John Arbash Meinel
Change the code so that we can pass in multiple sources to match against.
181
		 data >= buffer;
182
		 data -= RABIN_WINDOW) {
0.23.2 by Nicolas Pitre
Add the diff-delta.c and patch-delta.c files.
183
		unsigned int val = 0;
184
		for (i = 1; i <= RABIN_WINDOW; i++)
185
			val = ((val << 8) | data[i]) ^ T[val >> RABIN_SHIFT];
186
		if (val == prev_val) {
187
			/* keep the lowest of consecutive identical blocks */
188
			entry[-1].entry.ptr = data + RABIN_WINDOW;
189
			--entries;
190
		} else {
191
			prev_val = val;
192
			i = val & hmask;
193
			entry->entry.ptr = data + RABIN_WINDOW;
194
			entry->entry.val = val;
195
			entry->next = hash[i];
196
			hash[i] = entry++;
197
			hash_count[i]++;
198
		}
199
	}
200
201
	/*
202
	 * Determine a limit on the number of entries in the same hash
0.23.24 by John Arbash Meinel
Change the code so that we can pass in multiple sources to match against.
203
	 * bucket.	This guards us against pathological data sets causing
0.23.2 by Nicolas Pitre
Add the diff-delta.c and patch-delta.c files.
204
	 * really bad hash distribution with most entries in the same hash
205
	 * bucket that would bring us to O(m*n) computing costs (m and n
206
	 * corresponding to reference and target buffer sizes).
207
	 *
208
	 * Make sure none of the hash buckets has more entries than
209
	 * we're willing to test.  Otherwise we cull the entry list
210
	 * uniformly to still preserve a good repartition across
211
	 * the reference buffer.
212
	 */
213
	for (i = 0; i < hsize; i++) {
214
		int acc;
215
216
		if (hash_count[i] <= HASH_LIMIT)
217
			continue;
218
219
		/* We leave exactly HASH_LIMIT entries in the bucket */
220
		entries -= hash_count[i] - HASH_LIMIT;
221
222
		entry = hash[i];
223
		acc = 0;
224
225
		/*
226
		 * Assume that this loop is gone through exactly
227
		 * HASH_LIMIT times and is entered and left with
0.23.24 by John Arbash Meinel
Change the code so that we can pass in multiple sources to match against.
228
		 * acc==0.	So the first statement in the loop
0.23.2 by Nicolas Pitre
Add the diff-delta.c and patch-delta.c files.
229
		 * contributes (hash_count[i]-HASH_LIMIT)*HASH_LIMIT
230
		 * to the accumulator, and the inner loop consequently
231
		 * is run (hash_count[i]-HASH_LIMIT) times, removing
232
		 * one element from the list each time.  Since acc
233
		 * balances out to 0 at the final run, the inner loop
234
		 * body can't be left with entry==NULL.  So we indeed
235
		 * encounter entry==NULL in the outer loop only.
236
		 */
237
		do {
238
			acc += hash_count[i] - HASH_LIMIT;
239
			if (acc > 0) {
240
				struct unpacked_index_entry *keep = entry;
241
				do {
242
					entry = entry->next;
243
					acc -= HASH_LIMIT;
244
				} while (acc > 0);
245
				keep->next = entry->next;
246
			}
247
			entry = entry->next;
248
		} while (entry);
249
	}
250
	free(hash_count);
251
252
	/*
253
	 * Now create the packed index in array form
254
	 * rather than linked lists.
255
	 */
256
	memsize = sizeof(*index)
257
		+ sizeof(*packed_hash) * (hsize+1)
258
		+ sizeof(*packed_entry) * entries;
259
	mem = malloc(memsize);
260
	if (!mem) {
261
		free(hash);
262
		return NULL;
263
	}
264
265
	index = mem;
266
	index->memsize = memsize;
267
	index->src_buf = buf;
268
	index->src_size = bufsize;
0.23.24 by John Arbash Meinel
Change the code so that we can pass in multiple sources to match against.
269
	index->agg_src_offset = agg_src_offset;
0.23.2 by Nicolas Pitre
Add the diff-delta.c and patch-delta.c files.
270
	index->hash_mask = hmask;
271
272
	mem = index->hash;
273
	packed_hash = mem;
274
	mem = packed_hash + (hsize+1);
275
	packed_entry = mem;
276
277
	for (i = 0; i < hsize; i++) {
278
		/*
279
		 * Coalesce all entries belonging to one linked list
280
		 * into consecutive array entries.
281
		 */
282
		packed_hash[i] = packed_entry;
283
		for (entry = hash[i]; entry; entry = entry->next)
284
			*packed_entry++ = entry->entry;
285
	}
286
287
	/* Sentinel value to indicate the length of the last hash bucket */
288
	packed_hash[hsize] = packed_entry;
289
290
	assert(packed_entry - (struct index_entry *)mem == entries);
291
	free(hash);
292
293
	return index;
294
}
295
296
void free_delta_index(struct delta_index *index)
297
{
298
	free(index);
299
}
300
301
unsigned long sizeof_delta_index(struct delta_index *index)
302
{
303
	if (index)
304
		return index->memsize;
305
	else
306
		return 0;
307
}
308
309
/*
310
 * The maximum size for any opcode sequence, including the initial header
311
 * plus Rabin window plus biggest copy.
312
 */
313
#define MAX_OP_SIZE	(5 + 5 + 1 + RABIN_WINDOW + 7)
314
315
void *
0.23.24 by John Arbash Meinel
Change the code so that we can pass in multiple sources to match against.
316
create_delta(struct delta_index **indexes,
317
			 unsigned int num_indexes,
318
			 const void *trg_buf, unsigned long trg_size,
319
			 unsigned long *delta_size, unsigned long max_size)
0.23.2 by Nicolas Pitre
Add the diff-delta.c and patch-delta.c files.
320
{
0.23.24 by John Arbash Meinel
Change the code so that we can pass in multiple sources to match against.
321
	unsigned int i, j, outpos, outsize, moff, msize, val;
322
	const struct delta_index *index, *mindex;
0.23.2 by Nicolas Pitre
Add the diff-delta.c and patch-delta.c files.
323
	int inscnt;
324
	const unsigned char *ref_data, *ref_top, *data, *top;
325
	unsigned char *out;
326
327
	if (!trg_buf || !trg_size)
328
		return NULL;
329
330
	outpos = 0;
331
	outsize = 8192;
332
	if (max_size && outsize >= max_size)
333
		outsize = max_size + MAX_OP_SIZE + 1;
334
	out = malloc(outsize);
335
	if (!out)
336
		return NULL;
337
338
	/* store reference buffer size */
0.23.24 by John Arbash Meinel
Change the code so that we can pass in multiple sources to match against.
339
	i = 0;
340
	for (j = 0; j < num_indexes; ++j) {
341
		index = indexes[j];
342
		i += index->src_size;
343
	}
0.23.26 by John Arbash Meinel
We now start to make use of the ability to extend the delta index
344
	assert(i <= index->src_size + index->agg_src_offset);
345
	i = index->src_size + index->agg_src_offset;
0.23.2 by Nicolas Pitre
Add the diff-delta.c and patch-delta.c files.
346
	while (i >= 0x80) {
347
		out[outpos++] = i | 0x80;
348
		i >>= 7;
349
	}
350
	out[outpos++] = i;
351
352
	/* store target buffer size */
353
	i = trg_size;
354
	while (i >= 0x80) {
355
		out[outpos++] = i | 0x80;
356
		i >>= 7;
357
	}
358
	out[outpos++] = i;
359
360
	data = trg_buf;
361
	top = (const unsigned char *) trg_buf + trg_size;
362
0.23.24 by John Arbash Meinel
Change the code so that we can pass in multiple sources to match against.
363
	/* Start the matching by filling out with a simple 'insert' instruction, of
364
	 * the first RABIN_WINDOW bytes of the input.
365
	 */
366
	outpos++; /* leave a byte for the insert command */
0.23.2 by Nicolas Pitre
Add the diff-delta.c and patch-delta.c files.
367
	val = 0;
368
	for (i = 0; i < RABIN_WINDOW && data < top; i++, data++) {
369
		out[outpos++] = *data;
370
		val = ((val << 8) | *data) ^ T[val >> RABIN_SHIFT];
371
	}
0.23.24 by John Arbash Meinel
Change the code so that we can pass in multiple sources to match against.
372
	/* we are now setup with an insert of 'i' bytes and val contains the RABIN
373
	 * hash for those bytes, and data points to the RABIN_WINDOW+1 byte of
374
	 * input.
375
	 */
0.23.2 by Nicolas Pitre
Add the diff-delta.c and patch-delta.c files.
376
	inscnt = i;
377
378
	moff = 0;
379
	msize = 0;
0.23.24 by John Arbash Meinel
Change the code so that we can pass in multiple sources to match against.
380
	mindex = NULL;
0.23.2 by Nicolas Pitre
Add the diff-delta.c and patch-delta.c files.
381
	while (data < top) {
382
		if (msize < 4096) {
0.23.24 by John Arbash Meinel
Change the code so that we can pass in multiple sources to match against.
383
			/* we don't have a 'worthy enough' match yet, so let's look for
384
			 * one.
385
			 */
0.23.2 by Nicolas Pitre
Add the diff-delta.c and patch-delta.c files.
386
			struct index_entry *entry;
0.23.24 by John Arbash Meinel
Change the code so that we can pass in multiple sources to match against.
387
			/* Shift the window by one byte. */
0.23.2 by Nicolas Pitre
Add the diff-delta.c and patch-delta.c files.
388
			val ^= U[data[-RABIN_WINDOW]];
389
			val = ((val << 8) | *data) ^ T[val >> RABIN_SHIFT];
0.23.24 by John Arbash Meinel
Change the code so that we can pass in multiple sources to match against.
390
			for (j = 0; j < num_indexes; ++j) {
391
				index = indexes[j];
392
				i = val & index->hash_mask;
393
				ref_top = index->src_buf + index->src_size;
394
				ref_data = index->src_buf;
395
				for (entry = index->hash[i]; entry < index->hash[i+1];
396
					 entry++) {
397
					const unsigned char *ref = entry->ptr;
398
					const unsigned char *src = data;
399
					unsigned int ref_size = ref_top - ref;
400
					if (entry->val != val)
401
						continue;
402
					/* ref_size is the longest possible match that we could make
403
					 * here. If ref_size <= msize, then we know that we cannot
404
					 * match more bytes with this location that we have already
405
					 * matched.
406
					 */
407
					if (ref_size > top - src)
408
						ref_size = top - src;
409
					if (ref_size <= msize)
0.23.2 by Nicolas Pitre
Add the diff-delta.c and patch-delta.c files.
410
						break;
0.23.24 by John Arbash Meinel
Change the code so that we can pass in multiple sources to match against.
411
					/* See how many bytes actually match at this location. */
412
					while (ref_size-- && *src++ == *ref)
413
						ref++;
414
					if (msize < ref - entry->ptr) {
415
						/* this is our best match so far */
416
						msize = ref - entry->ptr;
417
						moff = entry->ptr - ref_data;
418
						mindex = index;
419
						if (msize >= 4096) /* good enough */
420
							break;
421
					}
0.23.2 by Nicolas Pitre
Add the diff-delta.c and patch-delta.c files.
422
				}
423
			}
424
		}
425
426
		if (msize < 4) {
0.23.24 by John Arbash Meinel
Change the code so that we can pass in multiple sources to match against.
427
			/* The best match right now is less than 4 bytes long. So just add
428
			 * the current byte to the insert instruction. Increment the insert
429
			 * counter, and copy the byte of data into the output buffer.
430
			 */
0.23.2 by Nicolas Pitre
Add the diff-delta.c and patch-delta.c files.
431
			if (!inscnt)
432
				outpos++;
433
			out[outpos++] = *data++;
434
			inscnt++;
435
			if (inscnt == 0x7f) {
0.23.24 by John Arbash Meinel
Change the code so that we can pass in multiple sources to match against.
436
				/* We have a max length insert instruction, finalize it in the
437
				 * output.
438
				 */
0.23.2 by Nicolas Pitre
Add the diff-delta.c and patch-delta.c files.
439
				out[outpos - inscnt - 1] = inscnt;
440
				inscnt = 0;
441
			}
442
			msize = 0;
443
		} else {
444
			unsigned int left;
445
			unsigned char *op;
446
447
			if (inscnt) {
0.23.24 by John Arbash Meinel
Change the code so that we can pass in multiple sources to match against.
448
				ref_data = mindex->src_buf;
0.23.2 by Nicolas Pitre
Add the diff-delta.c and patch-delta.c files.
449
				while (moff && ref_data[moff-1] == data[-1]) {
450
					/* we can match one byte back */
451
					msize++;
452
					moff--;
453
					data--;
454
					outpos--;
455
					if (--inscnt)
456
						continue;
457
					outpos--;  /* remove count slot */
458
					inscnt--;  /* make it -1 */
459
					break;
460
				}
461
				out[outpos - inscnt - 1] = inscnt;
462
				inscnt = 0;
463
			}
464
465
			/* A copy op is currently limited to 64KB (pack v2) */
466
			left = (msize < 0x10000) ? 0 : (msize - 0x10000);
467
			msize -= left;
468
469
			op = out + outpos++;
470
			i = 0x80;
471
0.23.24 by John Arbash Meinel
Change the code so that we can pass in multiple sources to match against.
472
			/* so far, moff has been the offset in a single source, however,
473
			 * now we encode it as the offset in the aggregate source
474
			 */
475
			moff = moff + mindex->agg_src_offset;
0.23.2 by Nicolas Pitre
Add the diff-delta.c and patch-delta.c files.
476
			if (moff & 0x000000ff)
477
				out[outpos++] = moff >> 0,  i |= 0x01;
478
			if (moff & 0x0000ff00)
479
				out[outpos++] = moff >> 8,  i |= 0x02;
480
			if (moff & 0x00ff0000)
481
				out[outpos++] = moff >> 16, i |= 0x04;
482
			if (moff & 0xff000000)
483
				out[outpos++] = moff >> 24, i |= 0x08;
484
485
			if (msize & 0x00ff)
486
				out[outpos++] = msize >> 0, i |= 0x10;
487
			if (msize & 0xff00)
488
				out[outpos++] = msize >> 8, i |= 0x20;
489
490
			*op = i;
491
492
			data += msize;
493
			moff += msize;
494
			msize = left;
495
496
			if (msize < 4096) {
497
				int j;
498
				val = 0;
499
				for (j = -RABIN_WINDOW; j < 0; j++)
500
					val = ((val << 8) | data[j])
0.23.24 by John Arbash Meinel
Change the code so that we can pass in multiple sources to match against.
501
						  ^ T[val >> RABIN_SHIFT];
0.23.2 by Nicolas Pitre
Add the diff-delta.c and patch-delta.c files.
502
			}
503
		}
504
505
		if (outpos >= outsize - MAX_OP_SIZE) {
506
			void *tmp = out;
507
			outsize = outsize * 3 / 2;
508
			if (max_size && outsize >= max_size)
509
				outsize = max_size + MAX_OP_SIZE + 1;
510
			if (max_size && outpos > max_size)
511
				break;
512
			out = realloc(out, outsize);
513
			if (!out) {
514
				free(tmp);
515
				return NULL;
516
			}
517
		}
518
	}
519
520
	if (inscnt)
521
		out[outpos - inscnt - 1] = inscnt;
522
523
	if (max_size && outpos > max_size) {
524
		free(out);
525
		return NULL;
526
	}
527
528
	*delta_size = outpos;
529
	return out;
530
}
0.23.24 by John Arbash Meinel
Change the code so that we can pass in multiple sources to match against.
531
532
/* vim: noet ts=4 sw=4 sts=4 */