MinGW: truncate exit()'s argument to lowest 8 bits
[git] / diff-delta.c
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 "git-compat-util.h"
15 #include "delta.h"
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 {
126         unsigned long memsize;
127         const void *src_buf;
128         unsigned long src_size;
129         unsigned int hash_mask;
130         struct index_entry *hash[FLEX_ARRAY];
131 };
132
133 struct delta_index * create_delta_index(const void *buf, unsigned long bufsize)
134 {
135         unsigned int i, hsize, hmask, entries, prev_val, *hash_count;
136         const unsigned char *data, *buffer = buf;
137         struct delta_index *index;
138         struct unpacked_index_entry *entry, **hash;
139         struct index_entry *packed_entry, **packed_hash;
140         void *mem;
141         unsigned long memsize;
142
143         if (!buf || !bufsize)
144                 return NULL;
145
146         /* Determine index hash size.  Note that indexing skips the
147            first byte to allow for optimizing the Rabin's polynomial
148            initialization in create_delta(). */
149         entries = (bufsize - 1)  / RABIN_WINDOW;
150         hsize = entries / 4;
151         for (i = 4; (1u << i) < hsize && i < 31; i++);
152         hsize = 1 << i;
153         hmask = hsize - 1;
154
155         /* allocate lookup index */
156         memsize = sizeof(*hash) * hsize +
157                   sizeof(*entry) * entries;
158         mem = malloc(memsize);
159         if (!mem)
160                 return NULL;
161         hash = mem;
162         mem = hash + hsize;
163         entry = mem;
164
165         memset(hash, 0, hsize * sizeof(*hash));
166
167         /* allocate an array to count hash entries */
168         hash_count = calloc(hsize, sizeof(*hash_count));
169         if (!hash_count) {
170                 free(hash);
171                 return NULL;
172         }
173
174         /* then populate the index */
175         prev_val = ~0;
176         for (data = buffer + entries * RABIN_WINDOW - RABIN_WINDOW;
177              data >= buffer;
178              data -= RABIN_WINDOW) {
179                 unsigned int val = 0;
180                 for (i = 1; i <= RABIN_WINDOW; i++)
181                         val = ((val << 8) | data[i]) ^ T[val >> RABIN_SHIFT];
182                 if (val == prev_val) {
183                         /* keep the lowest of consecutive identical blocks */
184                         entry[-1].entry.ptr = data + RABIN_WINDOW;
185                         --entries;
186                 } else {
187                         prev_val = val;
188                         i = val & hmask;
189                         entry->entry.ptr = data + RABIN_WINDOW;
190                         entry->entry.val = val;
191                         entry->next = hash[i];
192                         hash[i] = entry++;
193                         hash_count[i]++;
194                 }
195         }
196
197         /*
198          * Determine a limit on the number of entries in the same hash
199          * bucket.  This guards us against pathological data sets causing
200          * really bad hash distribution with most entries in the same hash
201          * bucket that would bring us to O(m*n) computing costs (m and n
202          * corresponding to reference and target buffer sizes).
203          *
204          * Make sure none of the hash buckets has more entries than
205          * we're willing to test.  Otherwise we cull the entry list
206          * uniformly to still preserve a good repartition across
207          * the reference buffer.
208          */
209         for (i = 0; i < hsize; i++) {
210                 int acc;
211
212                 if (hash_count[i] <= HASH_LIMIT)
213                         continue;
214
215                 /* We leave exactly HASH_LIMIT entries in the bucket */
216                 entries -= hash_count[i] - HASH_LIMIT;
217
218                 entry = hash[i];
219                 acc = 0;
220
221                 /*
222                  * Assume that this loop is gone through exactly
223                  * HASH_LIMIT times and is entered and left with
224                  * acc==0.  So the first statement in the loop
225                  * contributes (hash_count[i]-HASH_LIMIT)*HASH_LIMIT
226                  * to the accumulator, and the inner loop consequently
227                  * is run (hash_count[i]-HASH_LIMIT) times, removing
228                  * one element from the list each time.  Since acc
229                  * balances out to 0 at the final run, the inner loop
230                  * body can't be left with entry==NULL.  So we indeed
231                  * encounter entry==NULL in the outer loop only.
232                  */
233                 do {
234                         acc += hash_count[i] - HASH_LIMIT;
235                         if (acc > 0) {
236                                 struct unpacked_index_entry *keep = entry;
237                                 do {
238                                         entry = entry->next;
239                                         acc -= HASH_LIMIT;
240                                 } while (acc > 0);
241                                 keep->next = entry->next;
242                         }
243                         entry = entry->next;
244                 } while (entry);
245         }
246         free(hash_count);
247
248         /*
249          * Now create the packed index in array form
250          * rather than linked lists.
251          */
252         memsize = sizeof(*index)
253                 + sizeof(*packed_hash) * (hsize+1)
254                 + sizeof(*packed_entry) * entries;
255         mem = malloc(memsize);
256         if (!mem) {
257                 free(hash);
258                 return NULL;
259         }
260
261         index = mem;
262         index->memsize = memsize;
263         index->src_buf = buf;
264         index->src_size = bufsize;
265         index->hash_mask = hmask;
266
267         mem = index->hash;
268         packed_hash = mem;
269         mem = packed_hash + (hsize+1);
270         packed_entry = mem;
271
272         for (i = 0; i < hsize; i++) {
273                 /*
274                  * Coalesce all entries belonging to one linked list
275                  * into consecutive array entries.
276                  */
277                 packed_hash[i] = packed_entry;
278                 for (entry = hash[i]; entry; entry = entry->next)
279                         *packed_entry++ = entry->entry;
280         }
281
282         /* Sentinel value to indicate the length of the last hash bucket */
283         packed_hash[hsize] = packed_entry;
284
285         assert(packed_entry - (struct index_entry *)mem == entries);
286         free(hash);
287
288         return index;
289 }
290
291 void free_delta_index(struct delta_index *index)
292 {
293         free(index);
294 }
295
296 unsigned long sizeof_delta_index(struct delta_index *index)
297 {
298         if (index)
299                 return index->memsize;
300         else
301                 return 0;
302 }
303
304 /*
305  * The maximum size for any opcode sequence, including the initial header
306  * plus Rabin window plus biggest copy.
307  */
308 #define MAX_OP_SIZE     (5 + 5 + 1 + RABIN_WINDOW + 7)
309
310 void *
311 create_delta(const struct delta_index *index,
312              const void *trg_buf, unsigned long trg_size,
313              unsigned long *delta_size, unsigned long max_size)
314 {
315         unsigned int i, outpos, outsize, moff, msize, val;
316         int inscnt;
317         const unsigned char *ref_data, *ref_top, *data, *top;
318         unsigned char *out;
319
320         if (!trg_buf || !trg_size)
321                 return NULL;
322
323         outpos = 0;
324         outsize = 8192;
325         if (max_size && outsize >= max_size)
326                 outsize = max_size + MAX_OP_SIZE + 1;
327         out = malloc(outsize);
328         if (!out)
329                 return NULL;
330
331         /* store reference buffer size */
332         i = index->src_size;
333         while (i >= 0x80) {
334                 out[outpos++] = i | 0x80;
335                 i >>= 7;
336         }
337         out[outpos++] = i;
338
339         /* store target buffer size */
340         i = trg_size;
341         while (i >= 0x80) {
342                 out[outpos++] = i | 0x80;
343                 i >>= 7;
344         }
345         out[outpos++] = i;
346
347         ref_data = index->src_buf;
348         ref_top = ref_data + index->src_size;
349         data = trg_buf;
350         top = (const unsigned char *) trg_buf + trg_size;
351
352         outpos++;
353         val = 0;
354         for (i = 0; i < RABIN_WINDOW && data < top; i++, data++) {
355                 out[outpos++] = *data;
356                 val = ((val << 8) | *data) ^ T[val >> RABIN_SHIFT];
357         }
358         inscnt = i;
359
360         moff = 0;
361         msize = 0;
362         while (data < top) {
363                 if (msize < 4096) {
364                         struct index_entry *entry;
365                         val ^= U[data[-RABIN_WINDOW]];
366                         val = ((val << 8) | *data) ^ T[val >> RABIN_SHIFT];
367                         i = val & index->hash_mask;
368                         for (entry = index->hash[i]; entry < index->hash[i+1]; entry++) {
369                                 const unsigned char *ref = entry->ptr;
370                                 const unsigned char *src = data;
371                                 unsigned int ref_size = ref_top - ref;
372                                 if (entry->val != val)
373                                         continue;
374                                 if (ref_size > top - src)
375                                         ref_size = top - src;
376                                 if (ref_size <= msize)
377                                         break;
378                                 while (ref_size-- && *src++ == *ref)
379                                         ref++;
380                                 if (msize < ref - entry->ptr) {
381                                         /* this is our best match so far */
382                                         msize = ref - entry->ptr;
383                                         moff = entry->ptr - ref_data;
384                                         if (msize >= 4096) /* good enough */
385                                                 break;
386                                 }
387                         }
388                 }
389
390                 if (msize < 4) {
391                         if (!inscnt)
392                                 outpos++;
393                         out[outpos++] = *data++;
394                         inscnt++;
395                         if (inscnt == 0x7f) {
396                                 out[outpos - inscnt - 1] = inscnt;
397                                 inscnt = 0;
398                         }
399                         msize = 0;
400                 } else {
401                         unsigned int left;
402                         unsigned char *op;
403
404                         if (inscnt) {
405                                 while (moff && ref_data[moff-1] == data[-1]) {
406                                         /* we can match one byte back */
407                                         msize++;
408                                         moff--;
409                                         data--;
410                                         outpos--;
411                                         if (--inscnt)
412                                                 continue;
413                                         outpos--;  /* remove count slot */
414                                         inscnt--;  /* make it -1 */
415                                         break;
416                                 }
417                                 out[outpos - inscnt - 1] = inscnt;
418                                 inscnt = 0;
419                         }
420
421                         /* A copy op is currently limited to 64KB (pack v2) */
422                         left = (msize < 0x10000) ? 0 : (msize - 0x10000);
423                         msize -= left;
424
425                         op = out + outpos++;
426                         i = 0x80;
427
428                         if (moff & 0x000000ff)
429                                 out[outpos++] = moff >> 0,  i |= 0x01;
430                         if (moff & 0x0000ff00)
431                                 out[outpos++] = moff >> 8,  i |= 0x02;
432                         if (moff & 0x00ff0000)
433                                 out[outpos++] = moff >> 16, i |= 0x04;
434                         if (moff & 0xff000000)
435                                 out[outpos++] = moff >> 24, i |= 0x08;
436
437                         if (msize & 0x00ff)
438                                 out[outpos++] = msize >> 0, i |= 0x10;
439                         if (msize & 0xff00)
440                                 out[outpos++] = msize >> 8, i |= 0x20;
441
442                         *op = i;
443
444                         data += msize;
445                         moff += msize;
446                         msize = left;
447
448                         if (msize < 4096) {
449                                 int j;
450                                 val = 0;
451                                 for (j = -RABIN_WINDOW; j < 0; j++)
452                                         val = ((val << 8) | data[j])
453                                               ^ T[val >> RABIN_SHIFT];
454                         }
455                 }
456
457                 if (outpos >= outsize - MAX_OP_SIZE) {
458                         void *tmp = out;
459                         outsize = outsize * 3 / 2;
460                         if (max_size && outsize >= max_size)
461                                 outsize = max_size + MAX_OP_SIZE + 1;
462                         if (max_size && outpos > max_size)
463                                 break;
464                         out = realloc(out, outsize);
465                         if (!out) {
466                                 free(tmp);
467                                 return NULL;
468                         }
469                 }
470         }
471
472         if (inscnt)
473                 out[outpos - inscnt - 1] = inscnt;
474
475         if (max_size && outpos > max_size) {
476                 free(out);
477                 return NULL;
478         }
479
480         *delta_size = outpos;
481         return out;
482 }