├── .travis.yml
├── LICENSE
├── README.md
├── collage.cpp
├── collage.hpp
├── redist
├── README.md
├── collage.cpp
├── collage.hpp
└── deps
│ ├── Amalgamate.exe
│ ├── bsdiff
│ ├── LICENCE
│ ├── README.md
│ ├── SAIS.md
│ ├── bsdiff.c
│ ├── bspatch.c
│ ├── sais.c
│ └── sais.h
│ └── fart.exe
└── sample.cc
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: cpp
2 |
3 | compiler:
4 | - clang
5 | - gcc
6 |
7 | install:
8 | - wget --quiet -O - https://raw.githubusercontent.com/r-lyeh/depot/master/travis.pre.sh | bash -x
9 |
10 | script:
11 | - wget --quiet -O - https://raw.githubusercontent.com/r-lyeh/depot/master/travis.build.sh | bash -x
12 | - wget --quiet -O - https://raw.githubusercontent.com/r-lyeh/depot/master/travis.run.sh | bash -x
13 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2015 r-lyeh (https://github.com/r-lyeh)
2 |
3 | This software is provided 'as-is', without any express or implied
4 | warranty. In no event will the authors be held liable for any damages
5 | arising from the use of this software.
6 |
7 | Permission is granted to anyone to use this software for any purpose,
8 | including commercial applications, and to alter it and redistribute it
9 | freely, subject to the following restrictions:
10 |
11 | 1. The origin of this software must not be misrepresented; you must not
12 | claim that you wrote the original software. If you use this software
13 | in a product, an acknowledgment in the product documentation would be
14 | appreciated but is not required.
15 | 2. Altered source versions must be plainly marked as such, and must not be
16 | misrepresented as being the original software.
17 | 3. This notice may not be removed or altered from any source distribution.
18 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Collage
2 | =======
3 |
4 | - Collage is a lightweight C++ library to diff and patch data.
5 | - Collage provides interface to bsdiff/bspatch libraries (for now).
6 | - Collage is tiny. Single header and source files.
7 | - Collage is stand-alone. All dependencies are embedded.
8 | - Collage is cross-platform.
9 | - Collage is zlib/libpng licensed.
10 |
11 | ## sample
12 | ```c++
13 | #include
14 | #include
15 | #include "collage.hpp"
16 |
17 | int main() {
18 | std::string source = "hello world and thanks";
19 | std::string target = "hello cruel \x1 world. thanks for the fish.";
20 |
21 | std::string patch = collage::diff( source, target );
22 | assert( !patch.empty() );
23 |
24 | std::string patched = collage::patch( source, patch );
25 | assert( !patched.empty() );
26 | assert( target == patched );
27 |
28 | std::cout << "'" << source << "' + " << patch.size() << "-bytes patch == '" << patched << "'" << std::endl;
29 | std::cout << "All ok." << std::endl;
30 | }
31 | ```
32 |
33 | ## possible output
34 | ```
35 | 'hello world and thanks' + 46-bytes patch == 'hello cruel ☺ world. thanks for the fish.'
36 | All ok.
37 | ```
38 |
39 | ## licenses
40 | - [collage](https://github.com/r-lyeh/collage), zlib/libpng licensed.
41 | - [bsdiff](https://github.com/mendsley/bsdiff), by Colin Percival and Matthew Endsley, BSD2 licensed.
42 | - [sais-lite](https://github.com/davehughes/sais), by Yuta Mori, MIT licensed.
43 |
--------------------------------------------------------------------------------
/collage.cpp:
--------------------------------------------------------------------------------
1 | // Collage, lightweight C++ library to diff and patch arbitrary data
2 | // rlyeh, zlib/libpng licensed
3 |
4 | #include
5 | #include
6 | #include
7 |
8 | #define new new_
9 |
10 | //#line 1 "bsdiff.c"
11 | #include
12 | #include
13 |
14 | struct bsdiff_stream
15 | {
16 | void* opaque;
17 |
18 | void* (*malloc)(size_t size);
19 | void (*free)(void* ptr);
20 | int (*write)(struct bsdiff_stream* stream, const void* buffer, int size);
21 | };
22 |
23 | int bsdiff(const uint8_t* old, int64_t oldsize, const uint8_t* new, int64_t newsize, struct bsdiff_stream* stream);
24 |
25 | #if !defined(BSDIFF_HEADER_ONLY)
26 |
27 | #include
28 | #include
29 |
30 | #define MIN(x,y) (((x)<(y)) ? (x) : (y))
31 |
32 | static void split(int64_t *I,int64_t *V,int64_t start,int64_t len,int64_t h)
33 | {
34 | int64_t i,j,k,x,tmp,jj,kk;
35 |
36 | if(len<16) {
37 | for(k=start;kstart) split(I,V,start,jj-start,h);
86 |
87 | for(i=0;ikk) split(I,V,kk,start+len-kk,h);
91 | }
92 |
93 | /* [ref] Code commented because of http://stackoverflow.com/questions/12751775/why-does-bsdiff-exe-have-trouble-with-this-smaller-file */
94 | /* [ref] See Graeme Johnson's answer */
95 | #if 1//def BSDIFF_USE_SAIS
96 |
97 | //#line 1 "sais.h"
98 | #ifndef _SAIS_H
99 | #define _SAIS_H 1
100 |
101 | #include
102 | #define sais_index_type int64_t
103 | #define sais_bool_type int
104 |
105 | #ifdef __cplusplus
106 | extern "C" {
107 | #endif /* __cplusplus */
108 |
109 | /* find the suffix array SA of T[0..n-1]
110 | use a working space (excluding T and SA) of at most 2n+O(lg n) */
111 | int
112 | sais(const unsigned char *T, sais_index_type *SA, int n);
113 |
114 | /* find the suffix array SA of T[0..n-1] in {0..k-1}^n
115 | use a working space (excluding T and SA) of at most MAX(4k,2n) */
116 | int
117 | sais_int(const int *T, sais_index_type *SA, int n, int k);
118 |
119 | /* burrows-wheeler transform */
120 | int
121 | sais_bwt(const unsigned char *T, unsigned char *U, sais_index_type *A, int n);
122 | int
123 | sais_int_bwt(const int *T, sais_index_type *U, sais_index_type *A, int n, int k);
124 |
125 | #ifdef __cplusplus
126 | } /* extern "C" */
127 | #endif /* __cplusplus */
128 |
129 | #endif /* _SAIS_H */
130 |
131 |
132 |
133 | //#line 1 "sais.c"
134 | /*
135 | * sais.c for sais-lite
136 | * Copyright (c) 2008-2010 Yuta Mori All Rights Reserved.
137 | *
138 | * Permission is hereby granted, free of charge, to any person
139 | * obtaining a copy of this software and associated documentation
140 | * files (the "Software"), to deal in the Software without
141 | * restriction, including without limitation the rights to use,
142 | * copy, modify, merge, publish, distribute, sublicense, and/or sell
143 | * copies of the Software, and to permit persons to whom the
144 | * Software is furnished to do so, subject to the following
145 | * conditions:
146 | *
147 | * The above copyright notice and this permission notice shall be
148 | * included in all copies or substantial portions of the Software.
149 | *
150 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
151 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
152 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
153 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
154 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
155 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
156 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
157 | * OTHER DEALINGS IN THE SOFTWARE.
158 | */
159 |
160 | #include
161 | #include
162 |
163 | //#line 1 "sais.h"
164 | #ifndef _SAIS_H
165 | #define _SAIS_H 1
166 |
167 | #include
168 | #define sais_index_type int64_t
169 | #define sais_bool_type int
170 |
171 | #ifdef __cplusplus
172 | extern "C" {
173 | #endif /* __cplusplus */
174 |
175 | /* find the suffix array SA of T[0..n-1]
176 | use a working space (excluding T and SA) of at most 2n+O(lg n) */
177 | int
178 | sais(const unsigned char *T, sais_index_type *SA, int n);
179 |
180 | /* find the suffix array SA of T[0..n-1] in {0..k-1}^n
181 | use a working space (excluding T and SA) of at most MAX(4k,2n) */
182 | int
183 | sais_int(const int *T, sais_index_type *SA, int n, int k);
184 |
185 | /* burrows-wheeler transform */
186 | int
187 | sais_bwt(const unsigned char *T, unsigned char *U, sais_index_type *A, int n);
188 | int
189 | sais_int_bwt(const int *T, sais_index_type *U, sais_index_type *A, int n, int k);
190 |
191 | #ifdef __cplusplus
192 | } /* extern "C" */
193 | #endif /* __cplusplus */
194 |
195 | #endif /* _SAIS_H */
196 |
197 |
198 | #ifndef UCHAR_SIZE
199 | # define UCHAR_SIZE 256
200 | #endif
201 | #ifndef MINBUCKETSIZE
202 | # define MINBUCKETSIZE 256
203 | #endif
204 |
205 | #define SAIS_LMSSORT2_LIMIT 0x3fffffff
206 |
207 | #define SAIS_MYMALLOC(_num, _type) ((_type *)malloc((_num) * sizeof(_type)))
208 | #define SAIS_MYFREE(_ptr, _num, _type) free((_ptr))
209 | #define chr(_a) (cs == sizeof(sais_index_type) ? ((sais_index_type *)T)[(_a)] : ((unsigned char *)T)[(_a)])
210 |
211 | /* find the start or end of each bucket */
212 | static
213 | void
214 | getCounts(const void *T, sais_index_type *C, sais_index_type n, sais_index_type k, int cs) {
215 | sais_index_type i;
216 | for(i = 0; i < k; ++i) { C[i] = 0; }
217 | for(i = 0; i < n; ++i) { ++C[chr(i)]; }
218 | }
219 | static
220 | void
221 | getBuckets(const sais_index_type *C, sais_index_type *B, sais_index_type k, sais_bool_type end) {
222 | sais_index_type i, sum = 0;
223 | if(end) { for(i = 0; i < k; ++i) { sum += C[i]; B[i] = sum; } }
224 | else { for(i = 0; i < k; ++i) { sum += C[i]; B[i] = sum - C[i]; } }
225 | }
226 |
227 | /* sort all type LMS suffixes */
228 | static
229 | void
230 | LMSsort1(const void *T, sais_index_type *SA,
231 | sais_index_type *C, sais_index_type *B,
232 | sais_index_type n, sais_index_type k, int cs) {
233 | sais_index_type *b, i, j;
234 | sais_index_type c0, c1;
235 |
236 | /* compute SAl */
237 | if(C == B) { getCounts(T, C, n, k, cs); }
238 | getBuckets(C, B, k, 0); /* find starts of buckets */
239 | j = n - 1;
240 | b = SA + B[c1 = chr(j)];
241 | --j;
242 | *b++ = (chr(j) < c1) ? ~j : j;
243 | for(i = 0; i < n; ++i) {
244 | if(0 < (j = SA[i])) {
245 | assert(chr(j) >= chr(j + 1));
246 | if((c0 = chr(j)) != c1) { B[c1] = b - SA; b = SA + B[c1 = c0]; }
247 | assert(i < (b - SA));
248 | --j;
249 | *b++ = (chr(j) < c1) ? ~j : j;
250 | SA[i] = 0;
251 | } else if(j < 0) {
252 | SA[i] = ~j;
253 | }
254 | }
255 | /* compute SAs */
256 | if(C == B) { getCounts(T, C, n, k, cs); }
257 | getBuckets(C, B, k, 1); /* find ends of buckets */
258 | for(i = n - 1, b = SA + B[c1 = 0]; 0 <= i; --i) {
259 | if(0 < (j = SA[i])) {
260 | assert(chr(j) <= chr(j + 1));
261 | if((c0 = chr(j)) != c1) { B[c1] = b - SA; b = SA + B[c1 = c0]; }
262 | assert((b - SA) <= i);
263 | --j;
264 | *--b = (chr(j) > c1) ? ~(j + 1) : j;
265 | SA[i] = 0;
266 | }
267 | }
268 | }
269 | static
270 | sais_index_type
271 | LMSpostproc1(const void *T, sais_index_type *SA,
272 | sais_index_type n, sais_index_type m, int cs) {
273 | sais_index_type i, j, p, q, plen, qlen, name;
274 | sais_index_type c0, c1;
275 | sais_bool_type diff;
276 |
277 | /* compact all the sorted substrings into the first m items of SA
278 | 2*m must be not larger than n (proveable) */
279 | assert(0 < n);
280 | for(i = 0; (p = SA[i]) < 0; ++i) { SA[i] = ~p; assert((i + 1) < n); }
281 | if(i < m) {
282 | for(j = i, ++i;; ++i) {
283 | assert(i < n);
284 | if((p = SA[i]) < 0) {
285 | SA[j++] = ~p; SA[i] = 0;
286 | if(j == m) { break; }
287 | }
288 | }
289 | }
290 |
291 | /* store the length of all substrings */
292 | i = n - 1; j = n - 1; c0 = chr(n - 1);
293 | do { c1 = c0; } while((0 <= --i) && ((c0 = chr(i)) >= c1));
294 | for(; 0 <= i;) {
295 | do { c1 = c0; } while((0 <= --i) && ((c0 = chr(i)) <= c1));
296 | if(0 <= i) {
297 | SA[m + ((i + 1) >> 1)] = j - i; j = i + 1;
298 | do { c1 = c0; } while((0 <= --i) && ((c0 = chr(i)) >= c1));
299 | }
300 | }
301 |
302 | /* find the lexicographic names of all substrings */
303 | for(i = 0, name = 0, q = n, qlen = 0; i < m; ++i) {
304 | p = SA[i], plen = SA[m + (p >> 1)], diff = 1;
305 | if((plen == qlen) && ((q + plen) < n)) {
306 | for(j = 0; (j < plen) && (chr(p + j) == chr(q + j)); ++j) { }
307 | if(j == plen) { diff = 0; }
308 | }
309 | if(diff != 0) { ++name, q = p, qlen = plen; }
310 | SA[m + (p >> 1)] = name;
311 | }
312 |
313 | return name;
314 | }
315 | static
316 | void
317 | LMSsort2(const void *T, sais_index_type *SA,
318 | sais_index_type *C, sais_index_type *B, sais_index_type *D,
319 | sais_index_type n, sais_index_type k, int cs) {
320 | sais_index_type *b, i, j, t, d;
321 | sais_index_type c0, c1;
322 | assert(C != B);
323 |
324 | /* compute SAl */
325 | getBuckets(C, B, k, 0); /* find starts of buckets */
326 | j = n - 1;
327 | b = SA + B[c1 = chr(j)];
328 | --j;
329 | t = (chr(j) < c1);
330 | j += n;
331 | *b++ = (t & 1) ? ~j : j;
332 | for(i = 0, d = 0; i < n; ++i) {
333 | if(0 < (j = SA[i])) {
334 | if(n <= j) { d += 1; j -= n; }
335 | assert(chr(j) >= chr(j + 1));
336 | if((c0 = chr(j)) != c1) { B[c1] = b - SA; b = SA + B[c1 = c0]; }
337 | assert(i < (b - SA));
338 | --j;
339 | t = c0; t = (t << 1) | (chr(j) < c1);
340 | if(D[t] != d) { j += n; D[t] = d; }
341 | *b++ = (t & 1) ? ~j : j;
342 | SA[i] = 0;
343 | } else if(j < 0) {
344 | SA[i] = ~j;
345 | }
346 | }
347 | for(i = n - 1; 0 <= i; --i) {
348 | if(0 < SA[i]) {
349 | if(SA[i] < n) {
350 | SA[i] += n;
351 | for(j = i - 1; SA[j] < n; --j) { }
352 | SA[j] -= n;
353 | i = j;
354 | }
355 | }
356 | }
357 |
358 | /* compute SAs */
359 | getBuckets(C, B, k, 1); /* find ends of buckets */
360 | for(i = n - 1, d += 1, b = SA + B[c1 = 0]; 0 <= i; --i) {
361 | if(0 < (j = SA[i])) {
362 | if(n <= j) { d += 1; j -= n; }
363 | assert(chr(j) <= chr(j + 1));
364 | if((c0 = chr(j)) != c1) { B[c1] = b - SA; b = SA + B[c1 = c0]; }
365 | assert((b - SA) <= i);
366 | --j;
367 | t = c0; t = (t << 1) | (chr(j) > c1);
368 | if(D[t] != d) { j += n; D[t] = d; }
369 | *--b = (t & 1) ? ~(j + 1) : j;
370 | SA[i] = 0;
371 | }
372 | }
373 | }
374 | static
375 | sais_index_type
376 | LMSpostproc2(sais_index_type *SA, sais_index_type n, sais_index_type m) {
377 | sais_index_type i, j, d, name;
378 |
379 | /* compact all the sorted LMS substrings into the first m items of SA */
380 | assert(0 < n);
381 | for(i = 0, name = 0; (j = SA[i]) < 0; ++i) {
382 | j = ~j;
383 | if(n <= j) { name += 1; }
384 | SA[i] = j;
385 | assert((i + 1) < n);
386 | }
387 | if(i < m) {
388 | for(d = i, ++i;; ++i) {
389 | assert(i < n);
390 | if((j = SA[i]) < 0) {
391 | j = ~j;
392 | if(n <= j) { name += 1; }
393 | SA[d++] = j; SA[i] = 0;
394 | if(d == m) { break; }
395 | }
396 | }
397 | }
398 | if(name < m) {
399 | /* store the lexicographic names */
400 | for(i = m - 1, d = name + 1; 0 <= i; --i) {
401 | if(n <= (j = SA[i])) { j -= n; --d; }
402 | SA[m + (j >> 1)] = d;
403 | }
404 | } else {
405 | /* unset flags */
406 | for(i = 0; i < m; ++i) {
407 | if(n <= (j = SA[i])) { j -= n; SA[i] = j; }
408 | }
409 | }
410 |
411 | return name;
412 | }
413 |
414 | /* compute SA and BWT */
415 | static
416 | void
417 | induceSA(const void *T, sais_index_type *SA,
418 | sais_index_type *C, sais_index_type *B,
419 | sais_index_type n, sais_index_type k, int cs) {
420 | sais_index_type *b, i, j;
421 | sais_index_type c0, c1;
422 | /* compute SAl */
423 | if(C == B) { getCounts(T, C, n, k, cs); }
424 | getBuckets(C, B, k, 0); /* find starts of buckets */
425 | j = n - 1;
426 | b = SA + B[c1 = chr(j)];
427 | *b++ = ((0 < j) && (chr(j - 1) < c1)) ? ~j : j;
428 | for(i = 0; i < n; ++i) {
429 | j = SA[i], SA[i] = ~j;
430 | if(0 < j) {
431 | --j;
432 | assert(chr(j) >= chr(j + 1));
433 | if((c0 = chr(j)) != c1) { B[c1] = b - SA; b = SA + B[c1 = c0]; }
434 | assert(i < (b - SA));
435 | *b++ = ((0 < j) && (chr(j - 1) < c1)) ? ~j : j;
436 | }
437 | }
438 | /* compute SAs */
439 | if(C == B) { getCounts(T, C, n, k, cs); }
440 | getBuckets(C, B, k, 1); /* find ends of buckets */
441 | for(i = n - 1, b = SA + B[c1 = 0]; 0 <= i; --i) {
442 | if(0 < (j = SA[i])) {
443 | --j;
444 | assert(chr(j) <= chr(j + 1));
445 | if((c0 = chr(j)) != c1) { B[c1] = b - SA; b = SA + B[c1 = c0]; }
446 | assert((b - SA) <= i);
447 | *--b = ((j == 0) || (chr(j - 1) > c1)) ? ~j : j;
448 | } else {
449 | SA[i] = ~j;
450 | }
451 | }
452 | }
453 | static
454 | sais_index_type
455 | computeBWT(const void *T, sais_index_type *SA,
456 | sais_index_type *C, sais_index_type *B,
457 | sais_index_type n, sais_index_type k, int cs) {
458 | sais_index_type *b, i, j, pidx = -1;
459 | sais_index_type c0, c1;
460 | /* compute SAl */
461 | if(C == B) { getCounts(T, C, n, k, cs); }
462 | getBuckets(C, B, k, 0); /* find starts of buckets */
463 | j = n - 1;
464 | b = SA + B[c1 = chr(j)];
465 | *b++ = ((0 < j) && (chr(j - 1) < c1)) ? ~j : j;
466 | for(i = 0; i < n; ++i) {
467 | if(0 < (j = SA[i])) {
468 | --j;
469 | assert(chr(j) >= chr(j + 1));
470 | SA[i] = ~((sais_index_type)(c0 = chr(j)));
471 | if(c0 != c1) { B[c1] = b - SA; b = SA + B[c1 = c0]; }
472 | assert(i < (b - SA));
473 | *b++ = ((0 < j) && (chr(j - 1) < c1)) ? ~j : j;
474 | } else if(j != 0) {
475 | SA[i] = ~j;
476 | }
477 | }
478 | /* compute SAs */
479 | if(C == B) { getCounts(T, C, n, k, cs); }
480 | getBuckets(C, B, k, 1); /* find ends of buckets */
481 | for(i = n - 1, b = SA + B[c1 = 0]; 0 <= i; --i) {
482 | if(0 < (j = SA[i])) {
483 | --j;
484 | assert(chr(j) <= chr(j + 1));
485 | SA[i] = (c0 = chr(j));
486 | if(c0 != c1) { B[c1] = b - SA; b = SA + B[c1 = c0]; }
487 | assert((b - SA) <= i);
488 | *--b = ((0 < j) && (chr(j - 1) > c1)) ? ~((sais_index_type)chr(j - 1)) : j;
489 | } else if(j != 0) {
490 | SA[i] = ~j;
491 | } else {
492 | pidx = i;
493 | }
494 | }
495 | return pidx;
496 | }
497 |
498 | /* find the suffix array SA of T[0..n-1] in {0..255}^n */
499 | static
500 | sais_index_type
501 | sais_main(const void *T, sais_index_type *SA,
502 | sais_index_type fs, sais_index_type n, sais_index_type k, int cs,
503 | sais_bool_type isbwt) {
504 | sais_index_type *C, *B, *D, *RA, *b;
505 | sais_index_type i, j, m, p, q, t, name, pidx = 0, newfs;
506 | sais_index_type c0, c1;
507 | unsigned int flags;
508 |
509 | assert((T != NULL) && (SA != NULL));
510 | assert((0 <= fs) && (0 < n) && (1 <= k));
511 |
512 | if(k <= MINBUCKETSIZE) {
513 | if((C = SAIS_MYMALLOC(k, sais_index_type)) == NULL) { return -2; }
514 | if(k <= fs) {
515 | B = SA + (n + fs - k);
516 | flags = 1;
517 | } else {
518 | if((B = SAIS_MYMALLOC(k, sais_index_type)) == NULL) { SAIS_MYFREE(C, k, sais_index_type); return -2; }
519 | flags = 3;
520 | }
521 | } else if(k <= fs) {
522 | C = SA + (n + fs - k);
523 | if(k <= (fs - k)) {
524 | B = C - k;
525 | flags = 0;
526 | } else if(k <= (MINBUCKETSIZE * 4)) {
527 | if((B = SAIS_MYMALLOC(k, sais_index_type)) == NULL) { return -2; }
528 | flags = 2;
529 | } else {
530 | B = C;
531 | flags = 8;
532 | }
533 | } else {
534 | if((C = B = SAIS_MYMALLOC(k, sais_index_type)) == NULL) { return -2; }
535 | flags = 4 | 8;
536 | }
537 | if((n <= SAIS_LMSSORT2_LIMIT) && (2 <= (n / k))) {
538 | if(flags & 1) { flags |= ((k * 2) <= (fs - k)) ? 32 : 16; }
539 | else if((flags == 0) && ((k * 2) <= (fs - k * 2))) { flags |= 32; }
540 | }
541 |
542 | /* stage 1: reduce the problem by at least 1/2
543 | sort all the LMS-substrings */
544 | getCounts(T, C, n, k, cs); getBuckets(C, B, k, 1); /* find ends of buckets */
545 | for(i = 0; i < n; ++i) { SA[i] = 0; }
546 | b = &t; i = n - 1; j = n; m = 0; c0 = chr(n - 1);
547 | do { c1 = c0; } while((0 <= --i) && ((c0 = chr(i)) >= c1));
548 | for(; 0 <= i;) {
549 | do { c1 = c0; } while((0 <= --i) && ((c0 = chr(i)) <= c1));
550 | if(0 <= i) {
551 | *b = j; b = SA + --B[c1]; j = i; ++m;
552 | do { c1 = c0; } while((0 <= --i) && ((c0 = chr(i)) >= c1));
553 | }
554 | }
555 |
556 | if(1 < m) {
557 | if(flags & (16 | 32)) {
558 | if(flags & 16) {
559 | if((D = SAIS_MYMALLOC(k * 2, sais_index_type)) == NULL) {
560 | if(flags & (1 | 4)) { SAIS_MYFREE(C, k, sais_index_type); }
561 | if(flags & 2) { SAIS_MYFREE(B, k, sais_index_type); }
562 | return -2;
563 | }
564 | } else {
565 | D = B - k * 2;
566 | }
567 | assert((j + 1) < n);
568 | ++B[chr(j + 1)];
569 | for(i = 0, j = 0; i < k; ++i) {
570 | j += C[i];
571 | if(B[i] != j) { assert(SA[B[i]] != 0); SA[B[i]] += n; }
572 | D[i] = D[i + k] = 0;
573 | }
574 | LMSsort2(T, SA, C, B, D, n, k, cs);
575 | name = LMSpostproc2(SA, n, m);
576 | if(flags & 16) { SAIS_MYFREE(D, k * 2, sais_index_type); }
577 | } else {
578 | LMSsort1(T, SA, C, B, n, k, cs);
579 | name = LMSpostproc1(T, SA, n, m, cs);
580 | }
581 | } else if(m == 1) {
582 | *b = j + 1;
583 | name = 1;
584 | } else {
585 | name = 0;
586 | }
587 |
588 | /* stage 2: solve the reduced problem
589 | recurse if names are not yet unique */
590 | if(name < m) {
591 | if(flags & 4) { SAIS_MYFREE(C, k, sais_index_type); }
592 | if(flags & 2) { SAIS_MYFREE(B, k, sais_index_type); }
593 | newfs = (n + fs) - (m * 2);
594 | if((flags & (1 | 4 | 8)) == 0) {
595 | if((k + name) <= newfs) { newfs -= k; }
596 | else { flags |= 8; }
597 | }
598 | assert((n >> 1) <= (newfs + m));
599 | RA = SA + m + newfs;
600 | for(i = m + (n >> 1) - 1, j = m - 1; m <= i; --i) {
601 | if(SA[i] != 0) {
602 | RA[j--] = SA[i] - 1;
603 | }
604 | }
605 | if(sais_main(RA, SA, newfs, m, name, sizeof(sais_index_type), 0) != 0) {
606 | if(flags & 1) { SAIS_MYFREE(C, k, sais_index_type); }
607 | return -2;
608 | }
609 |
610 | i = n - 1; j = m - 1; c0 = chr(n - 1);
611 | do { c1 = c0; } while((0 <= --i) && ((c0 = chr(i)) >= c1));
612 | for(; 0 <= i;) {
613 | do { c1 = c0; } while((0 <= --i) && ((c0 = chr(i)) <= c1));
614 | if(0 <= i) {
615 | RA[j--] = i + 1;
616 | do { c1 = c0; } while((0 <= --i) && ((c0 = chr(i)) >= c1));
617 | }
618 | }
619 | for(i = 0; i < m; ++i) { SA[i] = RA[SA[i]]; }
620 | if(flags & 4) {
621 | if((C = B = SAIS_MYMALLOC(k, sais_index_type)) == NULL) { return -2; }
622 | }
623 | if(flags & 2) {
624 | if((B = SAIS_MYMALLOC(k, sais_index_type)) == NULL) {
625 | if(flags & 1) { SAIS_MYFREE(C, k, sais_index_type); }
626 | return -2;
627 | }
628 | }
629 | }
630 |
631 | /* stage 3: induce the result for the original problem */
632 | if(flags & 8) { getCounts(T, C, n, k, cs); }
633 | /* put all left-most S characters into their buckets */
634 | if(1 < m) {
635 | getBuckets(C, B, k, 1); /* find ends of buckets */
636 | i = m - 1, j = n, p = SA[m - 1], c1 = chr(p);
637 | do {
638 | q = B[c0 = c1];
639 | while(q < j) { SA[--j] = 0; }
640 | do {
641 | SA[--j] = p;
642 | if(--i < 0) { break; }
643 | p = SA[i];
644 | } while((c1 = chr(p)) == c0);
645 | } while(0 <= i);
646 | while(0 < j) { SA[--j] = 0; }
647 | }
648 | if(isbwt == 0) { induceSA(T, SA, C, B, n, k, cs); }
649 | else { pidx = computeBWT(T, SA, C, B, n, k, cs); }
650 | if(flags & (1 | 4)) { SAIS_MYFREE(C, k, sais_index_type); }
651 | if(flags & 2) { SAIS_MYFREE(B, k, sais_index_type); }
652 |
653 | return pidx;
654 | }
655 |
656 | /*---------------------------------------------------------------------------*/
657 |
658 | int
659 | sais(const unsigned char *T, sais_index_type *SA, int n) {
660 | if((T == NULL) || (SA == NULL) || (n < 0)) { return -1; }
661 | if(n <= 1) { if(n == 1) { SA[0] = 0; } return 0; }
662 | return sais_main(T, SA, 0, n, UCHAR_SIZE, sizeof(unsigned char), 0);
663 | }
664 |
665 | int
666 | sais_int(const int *T, sais_index_type *SA, int n, int k) {
667 | if((T == NULL) || (SA == NULL) || (n < 0) || (k <= 0)) { return -1; }
668 | if(n <= 1) { if(n == 1) { SA[0] = 0; } return 0; }
669 | return sais_main(T, SA, 0, n, k, sizeof(int), 0);
670 | }
671 |
672 | int
673 | sais_bwt(const unsigned char *T, unsigned char *U, sais_index_type *A, int n) {
674 | int i, pidx;
675 | if((T == NULL) || (U == NULL) || (A == NULL) || (n < 0)) { return -1; }
676 | if(n <= 1) { if(n == 1) { U[0] = T[0]; } return n; }
677 | pidx = sais_main(T, A, 0, n, UCHAR_SIZE, sizeof(unsigned char), 1);
678 | if(pidx < 0) { return pidx; }
679 | U[0] = T[n - 1];
680 | for(i = 0; i < pidx; ++i) { U[i + 1] = (unsigned char)A[i]; }
681 | for(i += 1; i < n; ++i) { U[i] = (unsigned char)A[i]; }
682 | pidx += 1;
683 | return pidx;
684 | }
685 |
686 | int
687 | sais_int_bwt(const int *T, sais_index_type *U, sais_index_type *A, int n, int k) {
688 | int i, pidx;
689 | if((T == NULL) || (U == NULL) || (A == NULL) || (n < 0) || (k <= 0)) { return -1; }
690 | if(n <= 1) { if(n == 1) { U[0] = T[0]; } return n; }
691 | pidx = sais_main(T, A, 0, n, k, sizeof(int), 1);
692 | if(pidx < 0) { return pidx; }
693 | U[0] = T[n - 1];
694 | for(i = 0; i < pidx; ++i) { U[i + 1] = A[i]; }
695 | for(i += 1; i < n; ++i) { U[i] = A[i]; }
696 | pidx += 1;
697 | return pidx;
698 | }
699 |
700 | #endif
701 |
702 | static void qsufsort(int64_t *I,int64_t *V,const uint8_t *old,int64_t oldsize)
703 | {
704 | int64_t buckets[256];
705 | int64_t i,h,len;
706 |
707 | for(i=0;i<256;i++) buckets[i]=0;
708 | for(i=0;i0;i--) buckets[i]=buckets[i-1];
711 | buckets[0]=0;
712 |
713 | for(i=0;iy) {
765 | *pos=I[st];
766 | return x;
767 | } else {
768 | *pos=I[en];
769 | return y;
770 | }
771 | };
772 |
773 | x=st+(en-st)/2;
774 | if(memcmp(old+I[x],new,MIN(oldsize-I[x],newsize))<0) {
775 | return search(I,old,oldsize,new,newsize,x,en,pos);
776 | } else {
777 | return search(I,old,oldsize,new,newsize,st,x,pos);
778 | };
779 | }
780 |
781 | static int offtout( int64_t ii, uint8_t *buf ) {
782 | /* taken from https://github.com/r-lyeh/vle */
783 | uint64_t i = (uint64_t)ii;
784 | i = i & (1ull << 63) ? ~(i << 1) : (i << 1);
785 | unsigned char *origin = buf;
786 | do {
787 | *buf++ = (unsigned char)( 0x80 | (i & 0x7f));
788 | i >>= 7;
789 | } while( i > 0 );
790 | *(buf-1) ^= 0x80;
791 | return buf - origin;
792 | }
793 |
794 | static int64_t writedata(struct bsdiff_stream* stream, const void* buffer, int64_t length)
795 | {
796 | int64_t result = 0;
797 |
798 | while (length > 0)
799 | {
800 | const int smallsize = (int)MIN(length, INT_MAX);
801 | const int writeresult = stream->write(stream, buffer, smallsize);
802 | if (writeresult == -1)
803 | {
804 | return -1;
805 | }
806 |
807 | result += writeresult;
808 | length -= smallsize;
809 | buffer = (uint8_t*)buffer + smallsize;
810 | }
811 |
812 | return result;
813 | }
814 |
815 | struct bsdiff_request
816 | {
817 | const uint8_t* old;
818 | int64_t oldsize;
819 | const uint8_t* new;
820 | int64_t newsize;
821 | struct bsdiff_stream* stream;
822 | int64_t *I;
823 | uint8_t *buffer;
824 | };
825 |
826 | static int bsdiff_internal(const struct bsdiff_request req)
827 | {
828 | int64_t *I,*V;
829 | int64_t scan,pos,len;
830 | int64_t lastscan,lastpos,lastoffset;
831 | int64_t oldscore,scsc;
832 | int64_t s,Sf,lenf,Sb,lenb;
833 | int64_t overlap,Ss,lens;
834 | int64_t i;
835 | uint8_t *buffer;
836 | uint8_t buf[10 * 3], *ptr;
837 |
838 | if((V=(int64_t*)req.stream->malloc((req.oldsize+1)*sizeof(int64_t)))==NULL) return -1;
839 | I = req.I;
840 |
841 | qsufsort(I,V,req.old,req.oldsize);
842 | req.stream->free(V);
843 |
844 | buffer = req.buffer;
845 |
846 | /* Compute the differences, writing ctrl as we go */
847 | scan=0;len=0;pos=0;
848 | lastscan=0;lastpos=0;lastoffset=0;
849 | while(scanoldscore+8)) break;
863 |
864 | if((scan+lastoffsetSf*2-lenf) { Sf=s; lenf=i; };
875 | };
876 |
877 | lenb=0;
878 | if(scan=lastscan+i)&&(pos>=i);i++) {
881 | if(req.old[pos-i]==req.new[scan-i]) s++;
882 | if(s*2-i>Sb*2-lenb) { Sb=s; lenb=i; };
883 | };
884 | };
885 |
886 | if(lastscan+lenf>scan-lenb) {
887 | overlap=(lastscan+lenf)-(scan-lenb);
888 | s=0;Ss=0;lens=0;
889 | for(i=0;iSs) { Ss=s; lens=i+1; };
895 | };
896 |
897 | lenf+=lens-overlap;
898 | lenb-=lens;
899 | };
900 |
901 | ptr = buf;
902 | ptr += offtout(lenf,buf);
903 | ptr += offtout((scan-lenb)-(lastscan+lenf),ptr);
904 | ptr += offtout((pos-lenb)-(lastpos+lenf),ptr);
905 |
906 | /* Write control data */
907 | if (writedata(req.stream, buf, ptr - buf))
908 | return -1;
909 |
910 | /* Write diff data */
911 | for(i=0;imalloc((oldsize+1)*sizeof(int64_t)))==NULL)
937 | return -1;
938 |
939 | if((req.buffer=(uint8_t*)stream->malloc(newsize+1))==NULL)
940 | {
941 | stream->free(req.I);
942 | return -1;
943 | }
944 |
945 | req.old = old;
946 | req.oldsize = oldsize;
947 | req.new = new;
948 | req.newsize = newsize;
949 | req.stream = stream;
950 |
951 | result = bsdiff_internal(req);
952 |
953 | stream->free(req.buffer);
954 | stream->free(req.I);
955 |
956 | return result;
957 | }
958 |
959 | #if defined(BSDIFF_EXECUTABLE)
960 |
961 | #include
962 |
963 | #include
964 | #include
965 | #include
966 | #include
967 | #include
968 | #include
969 |
970 | static int bz2_write(struct bsdiff_stream* stream, const void* buffer, int size)
971 | {
972 | int bz2err;
973 | BZFILE* bz2;
974 |
975 | bz2 = (BZFILE*)stream->opaque;
976 | BZ2_bzWrite(&bz2err, bz2, (void*)buffer, size);
977 | if (bz2err != BZ_STREAM_END && bz2err != BZ_OK)
978 | return -1;
979 |
980 | return 0;
981 | }
982 |
983 | int main(int argc,char *argv[])
984 | {
985 | int fd;
986 | int bz2err;
987 | uint8_t *old,*new;
988 | off_t oldsize,newsize;
989 | uint8_t buf[8];
990 | FILE * pf;
991 | struct bsdiff_stream stream;
992 | BZFILE* bz2;
993 |
994 | memset(&bz2, 0, sizeof(bz2));
995 | stream.malloc = malloc;
996 | stream.free = free;
997 | stream.write = bz2_write;
998 |
999 | if(argc!=4) errx(1,"usage: %s oldfile newfile patchfile\n",argv[0]);
1000 |
1001 | /* Allocate oldsize+1 bytes instead of oldsize bytes to ensure
1002 | that we never try to malloc(0) and get a NULL pointer */
1003 | if(((fd=open(argv[1],O_RDONLY,0))<0) ||
1004 | ((oldsize=lseek(fd,0,SEEK_END))==-1) ||
1005 | ((old=malloc(oldsize+1))==NULL) ||
1006 | (lseek(fd,0,SEEK_SET)!=0) ||
1007 | (read(fd,old,oldsize)!=oldsize) ||
1008 | (close(fd)==-1)) err(1,"%s",argv[1]);
1009 |
1010 | /* Allocate newsize+1 bytes instead of newsize bytes to ensure
1011 | that we never try to malloc(0) and get a NULL pointer */
1012 | if(((fd=open(argv[2],O_RDONLY,0))<0) ||
1013 | ((newsize=lseek(fd,0,SEEK_END))==-1) ||
1014 | ((new=malloc(newsize+1))==NULL) ||
1015 | (lseek(fd,0,SEEK_SET)!=0) ||
1016 | (read(fd,new,newsize)!=newsize) ||
1017 | (close(fd)==-1)) err(1,"%s",argv[2]);
1018 |
1019 | /* Create the patch file */
1020 | if ((pf = fopen(argv[3], "w")) == NULL)
1021 | err(1, "%s", argv[3]);
1022 |
1023 | /* Write header (signature+newsize)*/
1024 | offtout(newsize, buf);
1025 | if (fwrite("ENDSLEY/BSDIFF43", 16, 1, pf) != 1 ||
1026 | fwrite(buf, sizeof(buf), 1, pf) != 1)
1027 | err(1, "Failed to write header");
1028 |
1029 | if (NULL == (bz2 = BZ2_bzWriteOpen(&bz2err, pf, 9, 0, 0)))
1030 | errx(1, "BZ2_bzWriteOpen, bz2err=%d", bz2err);
1031 |
1032 | stream.opaque = bz2;
1033 | if (bsdiff(old, oldsize, new, newsize, &stream))
1034 | err(1, "bsdiff");
1035 |
1036 | BZ2_bzWriteClose(&bz2err, bz2, 0, NULL, NULL);
1037 | if (bz2err != BZ_OK)
1038 | err(1, "BZ2_bzWriteClose, bz2err=%d", bz2err);
1039 |
1040 | if (fclose(pf))
1041 | err(1, "fclose");
1042 |
1043 | /* Free the memory we used */
1044 | free(old);
1045 | free(new);
1046 |
1047 | return 0;
1048 | }
1049 |
1050 | #endif
1051 |
1052 | #endif
1053 |
1054 |
1055 |
1056 | //#line 1 "bspatch.c"
1057 | #include
1058 |
1059 | struct bspatch_stream
1060 | {
1061 | void* opaque;
1062 | int (*read)(const struct bspatch_stream* stream, void* buffer, int length);
1063 | };
1064 |
1065 | int bspatch(const uint8_t* old, int64_t oldsize, uint8_t* new, int64_t newsize, struct bspatch_stream* stream);
1066 |
1067 | #if !defined(BSPATCH_HEADER_ONLY)
1068 |
1069 | static int64_t offtin( const uint8_t *buf ) {
1070 | /* taken from https://github.com/r-lyeh/vle */
1071 | uint64_t out = 0, j = -7;
1072 | do {
1073 | out |= (( ((uint64_t)(*buf)) & 0x7f) << (j += 7) );
1074 | } while( ((uint64_t)(*buf++)) & 0x80 );
1075 | return (int64_t)( out & (1) ? ~(out >> 1) : (out >> 1) );
1076 | }
1077 |
1078 | int bspatch(const uint8_t* old, int64_t oldsize, uint8_t* new, int64_t newsize, struct bspatch_stream* stream)
1079 | {
1080 | uint8_t buf[10], *ptr;
1081 | int64_t oldpos,newpos;
1082 | int64_t ctrl[3];
1083 | int64_t i;
1084 |
1085 | oldpos=0;newpos=0;
1086 | while(newposread(stream, ptr, 1) ) {
1092 | return -1;
1093 | }
1094 | if( ((*ptr++) & 0x80) == 0x00 ) {
1095 | break;
1096 | }
1097 | }
1098 | ctrl[i]=offtin(buf);
1099 | };
1100 |
1101 | /* Sanity-check */
1102 | if(newpos+ctrl[0]>newsize)
1103 | return -1;
1104 |
1105 | /* Read diff string */
1106 | if (stream->read(stream, new + newpos, ctrl[0]))
1107 | return -1;
1108 |
1109 | /* Add old data to diff string */
1110 | for(i=0;i=0) && (oldpos+inewsize)
1120 | return -1;
1121 |
1122 | /* Read extra string */
1123 | if (stream->read(stream, new + newpos, ctrl[1]))
1124 | return -1;
1125 |
1126 | /* Adjust pointers */
1127 | newpos+=ctrl[1];
1128 | oldpos+=ctrl[2];
1129 | };
1130 |
1131 | return 0;
1132 | }
1133 |
1134 | #if defined(BSPATCH_EXECUTABLE)
1135 |
1136 | #include
1137 | #include
1138 | #include
1139 | #include
1140 | #include
1141 | #include
1142 | #include
1143 | #include
1144 |
1145 | static int bz2_read(const struct bspatch_stream* stream, void* buffer, int length)
1146 | {
1147 | int n;
1148 | int bz2err;
1149 | BZFILE* bz2;
1150 |
1151 | bz2 = (BZFILE*)stream->opaque;
1152 | n = BZ2_bzRead(&bz2err, bz2, buffer, length);
1153 | if (n != length)
1154 | return -1;
1155 |
1156 | return 0;
1157 | }
1158 |
1159 | int main(int argc,char * argv[])
1160 | {
1161 | FILE * f;
1162 | int fd;
1163 | int bz2err;
1164 | uint8_t header[24];
1165 | uint8_t *old, *new;
1166 | int64_t oldsize, newsize;
1167 | BZFILE* bz2;
1168 | struct bspatch_stream stream;
1169 |
1170 | if(argc!=4) errx(1,"usage: %s oldfile newfile patchfile\n",argv[0]);
1171 |
1172 | /* Open patch file */
1173 | if ((f = fopen(argv[3], "r")) == NULL)
1174 | err(1, "fopen(%s)", argv[3]);
1175 |
1176 | /* Read header */
1177 | if (fread(header, 1, 16, f) != 16) {
1178 | if (feof(f))
1179 | errx(1, "Corrupt patch\n");
1180 | err(1, "fread(%s)", argv[3]);
1181 | }
1182 |
1183 | /* Check for appropriate magic */
1184 | if (memcmp(header, "ENDSLEY/BSDIFF43", 16) != 0)
1185 | errx(1, "Corrupt patch\n");
1186 |
1187 | /* Read lengths from header */
1188 | newsize=offtin(header+16);
1189 | if(newsize<0)
1190 | errx(1,"Corrupt patch\n");
1191 |
1192 | /* Close patch file and re-open it via libbzip2 at the right places */
1193 | if(((fd=open(argv[1],O_RDONLY,0))<0) ||
1194 | ((oldsize=lseek(fd,0,SEEK_END))==-1) ||
1195 | ((old=malloc(oldsize+1))==NULL) ||
1196 | (lseek(fd,0,SEEK_SET)!=0) ||
1197 | (read(fd,old,oldsize)!=oldsize) ||
1198 | (close(fd)==-1)) err(1,"%s",argv[1]);
1199 | if((new=malloc(newsize+1))==NULL) err(1,NULL);
1200 |
1201 | if (NULL == (bz2 = BZ2_bzReadOpen(&bz2err, f, 0, 0, NULL, 0)))
1202 | errx(1, "BZ2_bzReadOpen, bz2err=%d", bz2err);
1203 |
1204 | stream.read = bz2_read;
1205 | stream.opaque = bz2;
1206 | if (bspatch(old, oldsize, new, newsize, &stream))
1207 | errx(1, "bspatch");
1208 |
1209 | /* Clean up the bzip2 reads */
1210 | BZ2_bzReadClose(&bz2err, bz2);
1211 | fclose(f);
1212 |
1213 | /* Write the new file */
1214 | if(((fd=open(argv[2],O_CREAT|O_TRUNC|O_WRONLY,0666))<0) ||
1215 | (write(fd,new,newsize)!=newsize) || (close(fd)==-1))
1216 | err(1,"%s",argv[2]);
1217 |
1218 | free(new);
1219 | free(old);
1220 |
1221 | return 0;
1222 | }
1223 |
1224 | #endif
1225 | #endif
1226 |
1227 | #undef new
1228 |
1229 | #include
1230 | #include
1231 |
1232 | #include "collage.hpp"
1233 |
1234 | namespace collage {
1235 |
1236 | namespace {
1237 | /* variable length encoding */
1238 | std::string vlebit( size_t i ) {
1239 | std::string out;
1240 | do {
1241 | out += (unsigned char)( 0x80 | (i & 0x7f));
1242 | i >>= 7;
1243 | } while( i > 0 );
1244 | *out.rbegin() ^= 0x80;
1245 | return out;
1246 | }
1247 | size_t vlebit( const char *&i ) {
1248 | size_t out = 0, j = -7;
1249 | do {
1250 | out |= ((size_t(*i) & 0x7f) << (j += 7) );
1251 | } while( size_t(*i++) & 0x80 );
1252 | return out;
1253 | }
1254 |
1255 | /* wrappers */
1256 | static int bs_write(struct bsdiff_stream* stream, const void* buffer, int size) {
1257 | return *((std::string*)stream->opaque) += std::string((char *)buffer,size), 0;
1258 | }
1259 |
1260 | static int bs_read(const struct bspatch_stream * stream, void* buffer, int size) {
1261 | std::pair &opaque = *( (std::pair *)stream->opaque );
1262 | if( opaque.first + size <= opaque.second ) {
1263 | memcpy( buffer, opaque.first, size );
1264 | opaque.first += size;
1265 | return 0;
1266 | } else {
1267 | return -1;
1268 | }
1269 | }
1270 | }
1271 |
1272 | bool diff( std::string &result, const char *from0, const char *from1, const char *to0, const char *to1, unsigned Q ) {
1273 | result = std::string();
1274 | switch( Q ) {
1275 | default:
1276 | case BSDIFF: {
1277 | struct bsdiff_stream diff_stream;
1278 | diff_stream.opaque = (void *)&result;
1279 | diff_stream.malloc = malloc;
1280 | diff_stream.free = free;
1281 | diff_stream.write = bs_write;
1282 | if( 0 == bsdiff( (const uint8_t *)from0, from1 - from0, (const uint8_t *)to0, to1 - to0, &diff_stream ) ) {
1283 | return true;
1284 | }
1285 | }
1286 | }
1287 | return false;
1288 | }
1289 |
1290 | /* result must be resized in advance */
1291 | bool patch( std::string &result, const char *from0, const char *from1, const char *diff0, const char *diff1, unsigned Q ) {
1292 | switch( Q ) {
1293 | default:
1294 | case BSDIFF: {
1295 | std::pair pair( diff0, diff1 );
1296 | struct bspatch_stream patch_stream;
1297 | patch_stream.opaque = (void *)&pair;
1298 | patch_stream.read = bs_read;
1299 | if( 0 == bspatch( (const uint8_t *)from0, from1 - from0, (uint8_t *)(&result[0]), result.size(), &patch_stream ) ) {
1300 | return true;
1301 | }
1302 | }
1303 | }
1304 | return false;
1305 | }
1306 |
1307 | std::string diff( const std::string &from, const std::string &to, unsigned Q ) {
1308 | std::string result;
1309 | if( diff( result, from.c_str(), from.c_str() + from.size(), to.c_str(), to.c_str() + to.size(), Q ) ) {
1310 | return std::string() + char(Q & 0x7F) + vlebit(to.size()) + result;
1311 | } else {
1312 | return std::string();
1313 | }
1314 | }
1315 |
1316 | std::string patch( const std::string &from, const std::string &diff ) {
1317 | const char *diff8 = diff.c_str();
1318 | unsigned Q = *diff8++;
1319 | std::string result( vlebit(diff8), '\0' );
1320 | if( patch( result, from.c_str(), from.c_str() + from.size(), diff8, diff8 + (diff.size() - (diff8 - diff.c_str()) ), Q ) ) {
1321 | return result;
1322 | } else {
1323 | return std::string();
1324 | }
1325 | }
1326 | }
1327 |
1328 |
--------------------------------------------------------------------------------
/collage.hpp:
--------------------------------------------------------------------------------
1 | // Collage, lightweight C++ library to diff and patch arbitrary data
2 | // rlyeh, zlib/libpng licensed
3 |
4 | #pragma once
5 | #include
6 |
7 | namespace collage {
8 | // available libraries
9 | enum { BSDIFF = 0 };
10 |
11 | // api
12 | std::string diff( const std::string &from, const std::string &to, unsigned library = BSDIFF );
13 | std::string patch( const std::string &from, const std::string &diff );
14 | }
15 |
--------------------------------------------------------------------------------
/redist/README.md:
--------------------------------------------------------------------------------
1 | collage/redist
2 | ==============
3 |
4 | - This optional folder is used to regenerate the amalgamated distribution. Do not include it into your project.
5 | - Regenerate the distribution by typing the following lines:
6 | ```
7 | move /y collage.hpp ..
8 | deps\Amalgamate.exe -w "*.*pp;*.c;*.h" collage.cpp ..\collage.cpp
9 | deps\fart.exe -- ..\collage.cpp "#line" "//#line"
10 | deps\fart.exe -- ..\collage.cpp "#pragma once" "//#pragma once"
11 | copy ..\collage.hpp /y
12 | ```
13 |
--------------------------------------------------------------------------------
/redist/collage.cpp:
--------------------------------------------------------------------------------
1 | // Collage, lightweight C++ library to diff and patch arbitrary data
2 | // rlyeh, zlib/libpng licensed
3 |
4 | #include
5 | #include
6 | #include
7 |
8 | #define new new_
9 | #include "deps/bsdiff/bsdiff.c"
10 | #include "deps/bsdiff/bspatch.c"
11 | #undef new
12 |
13 | #include
14 | #include
15 |
16 | #include "collage.hpp"
17 |
18 | namespace collage {
19 |
20 | namespace {
21 | /* variable length encoding */
22 | std::string vlebit( size_t i ) {
23 | std::string out;
24 | do {
25 | out += (unsigned char)( 0x80 | (i & 0x7f));
26 | i >>= 7;
27 | } while( i > 0 );
28 | *out.rbegin() ^= 0x80;
29 | return out;
30 | }
31 | size_t vlebit( const char *&i ) {
32 | size_t out = 0, j = -7;
33 | do {
34 | out |= ((size_t(*i) & 0x7f) << (j += 7) );
35 | } while( size_t(*i++) & 0x80 );
36 | return out;
37 | }
38 |
39 | /* wrappers */
40 | static int bs_write(struct bsdiff_stream* stream, const void* buffer, int size) {
41 | return *((std::string*)stream->opaque) += std::string((char *)buffer,size), 0;
42 | }
43 |
44 | static int bs_read(const struct bspatch_stream * stream, void* buffer, int size) {
45 | std::pair &opaque = *( (std::pair *)stream->opaque );
46 | if( opaque.first + size <= opaque.second ) {
47 | memcpy( buffer, opaque.first, size );
48 | opaque.first += size;
49 | return 0;
50 | } else {
51 | return -1;
52 | }
53 | }
54 | }
55 |
56 | bool diff( std::string &result, const char *from0, const char *from1, const char *to0, const char *to1, unsigned Q ) {
57 | result = std::string();
58 | switch( Q ) {
59 | default:
60 | case BSDIFF: {
61 | struct bsdiff_stream diff_stream;
62 | diff_stream.opaque = (void *)&result;
63 | diff_stream.malloc = malloc;
64 | diff_stream.free = free;
65 | diff_stream.write = bs_write;
66 | if( 0 == bsdiff( (const uint8_t *)from0, from1 - from0, (const uint8_t *)to0, to1 - to0, &diff_stream ) ) {
67 | return true;
68 | }
69 | }
70 | }
71 | return false;
72 | }
73 |
74 | /* result must be resized in advance */
75 | bool patch( std::string &result, const char *from0, const char *from1, const char *diff0, const char *diff1, unsigned Q ) {
76 | switch( Q ) {
77 | default:
78 | case BSDIFF: {
79 | std::pair pair( diff0, diff1 );
80 | struct bspatch_stream patch_stream;
81 | patch_stream.opaque = (void *)&pair;
82 | patch_stream.read = bs_read;
83 | if( 0 == bspatch( (const uint8_t *)from0, from1 - from0, (uint8_t *)(&result[0]), result.size(), &patch_stream ) ) {
84 | return true;
85 | }
86 | }
87 | }
88 | return false;
89 | }
90 |
91 | std::string diff( const std::string &from, const std::string &to, unsigned Q ) {
92 | std::string result;
93 | if( diff( result, from.c_str(), from.c_str() + from.size(), to.c_str(), to.c_str() + to.size(), Q ) ) {
94 | return std::string() + char(Q & 0x7F) + vlebit(to.size()) + result;
95 | } else {
96 | return std::string();
97 | }
98 | }
99 |
100 | std::string patch( const std::string &from, const std::string &diff ) {
101 | const char *diff8 = diff.c_str();
102 | unsigned Q = *diff8++;
103 | std::string result( vlebit(diff8), '\0' );
104 | if( patch( result, from.c_str(), from.c_str() + from.size(), diff8, diff8 + (diff.size() - (diff8 - diff.c_str()) ), Q ) ) {
105 | return result;
106 | } else {
107 | return std::string();
108 | }
109 | }
110 | }
111 |
--------------------------------------------------------------------------------
/redist/collage.hpp:
--------------------------------------------------------------------------------
1 | // Collage, lightweight C++ library to diff and patch arbitrary data
2 | // rlyeh, zlib/libpng licensed
3 |
4 | #pragma once
5 | #include
6 |
7 | namespace collage {
8 | // available libraries
9 | enum { BSDIFF = 0 };
10 |
11 | // api
12 | std::string diff( const std::string &from, const std::string &to, unsigned library = BSDIFF );
13 | std::string patch( const std::string &from, const std::string &diff );
14 | }
15 |
--------------------------------------------------------------------------------
/redist/deps/Amalgamate.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r-lyeh-archived/collage/29573f36db3795bae6ca8602b744f5fa558d1270/redist/deps/Amalgamate.exe
--------------------------------------------------------------------------------
/redist/deps/bsdiff/LICENCE:
--------------------------------------------------------------------------------
1 | Copyright 2003-2005 Colin Percival
2 | Copyright 2012 Matthew Endsley
3 | All rights reserved
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted providing that the following conditions
7 | are met:
8 | 1. Redistributions of source code must retain the above copyright
9 | notice, this list of conditions and the following disclaimer.
10 | 2. Redistributions in binary form must reproduce the above copyright
11 | notice, this list of conditions and the following disclaimer in the
12 | documentation and/or other materials provided with the distribution.
13 |
14 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 | ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
18 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 | OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
22 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
23 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24 | POSSIBILITY OF SUCH DAMAGE.
25 |
--------------------------------------------------------------------------------
/redist/deps/bsdiff/README.md:
--------------------------------------------------------------------------------
1 | bsdiff/bspatch
2 | ==============
3 | bsdiff and bspatch are libraries for building and applying patches to binary
4 | files.
5 |
6 | The original algorithm and implementation was developed by Colin Percival. The
7 | algorithm is detailed in his doctoral thesis:
8 | . For more information visit his
9 | website at .
10 |
11 | I maintain this project seperately from Colin's work, with the goal of making
12 | the core functionality easily embedable in existing projects.
13 |
14 | Contact
15 | -------
16 | [@MatthewEndsley](https://twitter.com/#!/MatthewEndsley)
17 |
18 |
19 | License
20 | -------
21 | Copyright 2003-2005 Colin Percival
22 | Copyright 2012 Matthew Endsley
23 |
24 | This project is governed by the BSD 2-clause license. For details see the file
25 | titled LICENSE in the project root folder.
26 |
27 | Overview
28 | --------
29 | There are two separate libraries in the project, bsdiff and bspatch. Each are
30 | self contained in bsdiff.c and bspatch.c The easiest way to integrate is to
31 | simply copy the c file to your source folder and build it.
32 |
33 | The overarching goal was to modify the original bsdiff/bspatch code from Colin
34 | and eliminate external dependencies and provide a simple interface to the core
35 | functionality.
36 |
37 | You can define `BSDIFF_HEADER_ONLY` or `BSPATCH_HEADER_ONLY` to only include
38 | the header parts of the file. If including a `.c` file makes you feel really
39 | dirty you can copy paste the header portion at the top of the file into your own
40 | `.h` file.
41 |
42 | I've exposed relevant functions via the `_stream` classes. The only external
43 | dependency not exposed is `memcmp` in `bsdiff`.
44 |
45 | This library generates patches that are not compatible with the original bsdiff
46 | tool. The impompatibilities were motivated by the patching needs for the game
47 | AirMech and the following requirements:
48 |
49 | * Eliminate/minimize any seek operations when applying patches
50 | * Eliminate any required disk I/O and support embedded streams
51 | * Ability to easily embed the routines as a library instead of an external binary
52 | * Compile+run on all platforms we use to build the game (Windows, Linux, NaCl, OSX)
53 |
54 | Compiling
55 | ---------
56 | The libraries should compile warning free in any moderately recent version of
57 | gcc. The project uses `` which is technically a C99 file and not
58 | available in Microsoft Visual Studio. The easiest solution here is to use the
59 | msinttypes version of stdint.h from .
60 | The direct link for the lazy people is:
61 | .
62 |
63 | If your compiler does not provide an implementation of `` you can
64 | remove the header from the bsdiff/bspatch files and provide your own typedefs
65 | for the following symbols: `uint8_t`, `uint64_t` and `int64_t`.
66 |
67 | Examples
68 | --------
69 | Each project has an optional main function that serves as an example for using
70 | the library. Simply defined `BSDIFF_EXECUTABLE` or `BSPATCH_EXECUTABLE` to
71 | enable building the standalone tools.
72 |
73 | Reference
74 | ---------
75 | ### bsdiff
76 |
77 | struct bsdiff_stream
78 | {
79 | void* opaque;
80 | void* (*malloc)(size_t size);
81 | void (*free)(void* ptr);
82 | int (*write)(struct bsdiff_stream* stream,
83 | const void* buffer, int size);
84 | };
85 |
86 | int bsdiff(const uint8_t* old, int64_t oldsize, const uint8_t* new,
87 | int64_t newsize, struct bsdiff_stream* stream);
88 |
89 |
90 | In order to use `bsdiff`, you need to define functions for allocating memory and
91 | writing binary data. This behavior is controlled by the `stream` parameted
92 | passed to to `bsdiff(...)`.
93 |
94 | The `opaque` field is never read or modified from within the `bsdiff` function.
95 | The caller can use this field to store custom state data needed for the callback
96 | functions.
97 |
98 | The `malloc` and `free` members should point to functions that behave like the
99 | standard `malloc` and `free` C functions.
100 |
101 | The `write` function is called by bsdiff to write a block of binary data to the
102 | stream. The return value for `write` should be `0` on success and non-zero if
103 | the callback failed to write all data. In the default example, bzip2 is used to
104 | compress output data.
105 |
106 | `bsdiff` returns `0` on success and `-1` on failure.
107 |
108 | ### bspatch
109 |
110 | struct bspatch_stream
111 | {
112 | void* opaque;
113 | int (*read)(const struct bspatch_stream* stream,
114 | void* buffer, int length);
115 | };
116 |
117 | int bspatch(const uint8_t* old, int64_t oldsize, uint8_t* new,
118 | int64_t newsize, struct bspatch_stream* stream);
119 |
120 | The `bspatch` function transforms the data for a file using data generated from
121 | `bsdiff`. The caller takes care of loading the old file and allocating space for
122 | new file data. The `stream` parameter controls the process for reading binary
123 | patch data.
124 |
125 | The `opaque` field is never read or modified from within the bspatch function.
126 | The caller can use this field to store custom state data needed for the read
127 | function.
128 |
129 | The `read` function is called by `bspatch` to read a block of binary data from
130 | the stream. The return value for `read` should be `0` on success and non-zero
131 | if the callback failed to read the requested amount of data. In the default
132 | example, bzip2 is used to decompress input data.
133 |
134 | `bspatch` returns `0` on success and `-1` on failure. On success, `new` contains
135 | the data for the patched file.
136 |
--------------------------------------------------------------------------------
/redist/deps/bsdiff/SAIS.md:
--------------------------------------------------------------------------------
1 |
2 | sais-lite-2.4.0
3 | ----------------------
4 |
5 | This archive contains the source code of the implementation of
6 | the IS based linear suffix array construction algorithm
7 | described in the paper:
8 |
9 | Ge Nong, Sen Zhang and Wai Hong Chan
10 | Two Efficient Algorithms for Linear Suffix Array Construction
11 | 2008?
12 | http://www.cs.sysu.edu.cn/nong/index.files/Two%20Efficient%20Algorithms%20for%20Linear%20Suffix%20Array%20Construction.pdf
13 |
14 |
15 | Yuta Mori
16 |
--------------------------------------------------------------------------------
/redist/deps/bsdiff/bsdiff.c:
--------------------------------------------------------------------------------
1 | /*-
2 | * Copyright 2003-2005 Colin Percival
3 | * Copyright 2012 Matthew Endsley
4 | * All rights reserved
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted providing that the following conditions
8 | * are met:
9 | * 1. Redistributions of source code must retain the above copyright
10 | * notice, this list of conditions and the following disclaimer.
11 | * 2. Redistributions in binary form must reproduce the above copyright
12 | * notice, this list of conditions and the following disclaimer in the
13 | * documentation and/or other materials provided with the distribution.
14 | *
15 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
19 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
23 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
24 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 | * POSSIBILITY OF SUCH DAMAGE.
26 | */
27 |
28 | #include
29 | #include
30 |
31 | struct bsdiff_stream
32 | {
33 | void* opaque;
34 |
35 | void* (*malloc)(size_t size);
36 | void (*free)(void* ptr);
37 | int (*write)(struct bsdiff_stream* stream, const void* buffer, int size);
38 | };
39 |
40 | int bsdiff(const uint8_t* old, int64_t oldsize, const uint8_t* new, int64_t newsize, struct bsdiff_stream* stream);
41 |
42 | #if !defined(BSDIFF_HEADER_ONLY)
43 |
44 | #include
45 | #include
46 |
47 | #define MIN(x,y) (((x)<(y)) ? (x) : (y))
48 |
49 | static void split(int64_t *I,int64_t *V,int64_t start,int64_t len,int64_t h)
50 | {
51 | int64_t i,j,k,x,tmp,jj,kk;
52 |
53 | if(len<16) {
54 | for(k=start;kstart) split(I,V,start,jj-start,h);
103 |
104 | for(i=0;ikk) split(I,V,kk,start+len-kk,h);
108 | }
109 |
110 | /* [ref] Code commented because of http://stackoverflow.com/questions/12751775/why-does-bsdiff-exe-have-trouble-with-this-smaller-file */
111 | /* [ref] See Graeme Johnson's answer */
112 | #if 1//def BSDIFF_USE_SAIS
113 | #include "sais.h"
114 | #include "sais.c"
115 | #endif
116 |
117 | static void qsufsort(int64_t *I,int64_t *V,const uint8_t *old,int64_t oldsize)
118 | {
119 | int64_t buckets[256];
120 | int64_t i,h,len;
121 |
122 | for(i=0;i<256;i++) buckets[i]=0;
123 | for(i=0;i0;i--) buckets[i]=buckets[i-1];
126 | buckets[0]=0;
127 |
128 | for(i=0;iy) {
180 | *pos=I[st];
181 | return x;
182 | } else {
183 | *pos=I[en];
184 | return y;
185 | }
186 | };
187 |
188 | x=st+(en-st)/2;
189 | if(memcmp(old+I[x],new,MIN(oldsize-I[x],newsize))<0) {
190 | return search(I,old,oldsize,new,newsize,x,en,pos);
191 | } else {
192 | return search(I,old,oldsize,new,newsize,st,x,pos);
193 | };
194 | }
195 |
196 | static int offtout( int64_t ii, uint8_t *buf ) {
197 | /* taken from https://github.com/r-lyeh/vle */
198 | uint64_t i = (uint64_t)ii;
199 | i = i & (1ull << 63) ? ~(i << 1) : (i << 1);
200 | unsigned char *origin = buf;
201 | do {
202 | *buf++ = (unsigned char)( 0x80 | (i & 0x7f));
203 | i >>= 7;
204 | } while( i > 0 );
205 | *(buf-1) ^= 0x80;
206 | return buf - origin;
207 | }
208 |
209 | static int64_t writedata(struct bsdiff_stream* stream, const void* buffer, int64_t length)
210 | {
211 | int64_t result = 0;
212 |
213 | while (length > 0)
214 | {
215 | const int smallsize = (int)MIN(length, INT_MAX);
216 | const int writeresult = stream->write(stream, buffer, smallsize);
217 | if (writeresult == -1)
218 | {
219 | return -1;
220 | }
221 |
222 | result += writeresult;
223 | length -= smallsize;
224 | buffer = (uint8_t*)buffer + smallsize;
225 | }
226 |
227 | return result;
228 | }
229 |
230 | struct bsdiff_request
231 | {
232 | const uint8_t* old;
233 | int64_t oldsize;
234 | const uint8_t* new;
235 | int64_t newsize;
236 | struct bsdiff_stream* stream;
237 | int64_t *I;
238 | uint8_t *buffer;
239 | };
240 |
241 | static int bsdiff_internal(const struct bsdiff_request req)
242 | {
243 | int64_t *I,*V;
244 | int64_t scan,pos,len;
245 | int64_t lastscan,lastpos,lastoffset;
246 | int64_t oldscore,scsc;
247 | int64_t s,Sf,lenf,Sb,lenb;
248 | int64_t overlap,Ss,lens;
249 | int64_t i;
250 | uint8_t *buffer;
251 | uint8_t buf[10 * 3], *ptr;
252 |
253 | if((V=(int64_t*)req.stream->malloc((req.oldsize+1)*sizeof(int64_t)))==NULL) return -1;
254 | I = req.I;
255 |
256 | qsufsort(I,V,req.old,req.oldsize);
257 | req.stream->free(V);
258 |
259 | buffer = req.buffer;
260 |
261 | /* Compute the differences, writing ctrl as we go */
262 | scan=0;len=0;pos=0;
263 | lastscan=0;lastpos=0;lastoffset=0;
264 | while(scanoldscore+8)) break;
278 |
279 | if((scan+lastoffsetSf*2-lenf) { Sf=s; lenf=i; };
290 | };
291 |
292 | lenb=0;
293 | if(scan=lastscan+i)&&(pos>=i);i++) {
296 | if(req.old[pos-i]==req.new[scan-i]) s++;
297 | if(s*2-i>Sb*2-lenb) { Sb=s; lenb=i; };
298 | };
299 | };
300 |
301 | if(lastscan+lenf>scan-lenb) {
302 | overlap=(lastscan+lenf)-(scan-lenb);
303 | s=0;Ss=0;lens=0;
304 | for(i=0;iSs) { Ss=s; lens=i+1; };
310 | };
311 |
312 | lenf+=lens-overlap;
313 | lenb-=lens;
314 | };
315 |
316 | ptr = buf;
317 | ptr += offtout(lenf,buf);
318 | ptr += offtout((scan-lenb)-(lastscan+lenf),ptr);
319 | ptr += offtout((pos-lenb)-(lastpos+lenf),ptr);
320 |
321 | /* Write control data */
322 | if (writedata(req.stream, buf, ptr - buf))
323 | return -1;
324 |
325 | /* Write diff data */
326 | for(i=0;imalloc((oldsize+1)*sizeof(int64_t)))==NULL)
352 | return -1;
353 |
354 | if((req.buffer=(uint8_t*)stream->malloc(newsize+1))==NULL)
355 | {
356 | stream->free(req.I);
357 | return -1;
358 | }
359 |
360 | req.old = old;
361 | req.oldsize = oldsize;
362 | req.new = new;
363 | req.newsize = newsize;
364 | req.stream = stream;
365 |
366 | result = bsdiff_internal(req);
367 |
368 | stream->free(req.buffer);
369 | stream->free(req.I);
370 |
371 | return result;
372 | }
373 |
374 | #if defined(BSDIFF_EXECUTABLE)
375 |
376 | #include
377 |
378 | #include
379 | #include
380 | #include
381 | #include
382 | #include
383 | #include
384 |
385 | static int bz2_write(struct bsdiff_stream* stream, const void* buffer, int size)
386 | {
387 | int bz2err;
388 | BZFILE* bz2;
389 |
390 | bz2 = (BZFILE*)stream->opaque;
391 | BZ2_bzWrite(&bz2err, bz2, (void*)buffer, size);
392 | if (bz2err != BZ_STREAM_END && bz2err != BZ_OK)
393 | return -1;
394 |
395 | return 0;
396 | }
397 |
398 | int main(int argc,char *argv[])
399 | {
400 | int fd;
401 | int bz2err;
402 | uint8_t *old,*new;
403 | off_t oldsize,newsize;
404 | uint8_t buf[8];
405 | FILE * pf;
406 | struct bsdiff_stream stream;
407 | BZFILE* bz2;
408 |
409 | memset(&bz2, 0, sizeof(bz2));
410 | stream.malloc = malloc;
411 | stream.free = free;
412 | stream.write = bz2_write;
413 |
414 | if(argc!=4) errx(1,"usage: %s oldfile newfile patchfile\n",argv[0]);
415 |
416 | /* Allocate oldsize+1 bytes instead of oldsize bytes to ensure
417 | that we never try to malloc(0) and get a NULL pointer */
418 | if(((fd=open(argv[1],O_RDONLY,0))<0) ||
419 | ((oldsize=lseek(fd,0,SEEK_END))==-1) ||
420 | ((old=malloc(oldsize+1))==NULL) ||
421 | (lseek(fd,0,SEEK_SET)!=0) ||
422 | (read(fd,old,oldsize)!=oldsize) ||
423 | (close(fd)==-1)) err(1,"%s",argv[1]);
424 |
425 |
426 | /* Allocate newsize+1 bytes instead of newsize bytes to ensure
427 | that we never try to malloc(0) and get a NULL pointer */
428 | if(((fd=open(argv[2],O_RDONLY,0))<0) ||
429 | ((newsize=lseek(fd,0,SEEK_END))==-1) ||
430 | ((new=malloc(newsize+1))==NULL) ||
431 | (lseek(fd,0,SEEK_SET)!=0) ||
432 | (read(fd,new,newsize)!=newsize) ||
433 | (close(fd)==-1)) err(1,"%s",argv[2]);
434 |
435 | /* Create the patch file */
436 | if ((pf = fopen(argv[3], "w")) == NULL)
437 | err(1, "%s", argv[3]);
438 |
439 | /* Write header (signature+newsize)*/
440 | offtout(newsize, buf);
441 | if (fwrite("ENDSLEY/BSDIFF43", 16, 1, pf) != 1 ||
442 | fwrite(buf, sizeof(buf), 1, pf) != 1)
443 | err(1, "Failed to write header");
444 |
445 |
446 | if (NULL == (bz2 = BZ2_bzWriteOpen(&bz2err, pf, 9, 0, 0)))
447 | errx(1, "BZ2_bzWriteOpen, bz2err=%d", bz2err);
448 |
449 | stream.opaque = bz2;
450 | if (bsdiff(old, oldsize, new, newsize, &stream))
451 | err(1, "bsdiff");
452 |
453 | BZ2_bzWriteClose(&bz2err, bz2, 0, NULL, NULL);
454 | if (bz2err != BZ_OK)
455 | err(1, "BZ2_bzWriteClose, bz2err=%d", bz2err);
456 |
457 | if (fclose(pf))
458 | err(1, "fclose");
459 |
460 | /* Free the memory we used */
461 | free(old);
462 | free(new);
463 |
464 | return 0;
465 | }
466 |
467 | #endif
468 |
469 | #endif
470 |
--------------------------------------------------------------------------------
/redist/deps/bsdiff/bspatch.c:
--------------------------------------------------------------------------------
1 | /*-
2 | * Copyright 2003-2005 Colin Percival
3 | * Copyright 2012 Matthew Endsley
4 | * All rights reserved
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted providing that the following conditions
8 | * are met:
9 | * 1. Redistributions of source code must retain the above copyright
10 | * notice, this list of conditions and the following disclaimer.
11 | * 2. Redistributions in binary form must reproduce the above copyright
12 | * notice, this list of conditions and the following disclaimer in the
13 | * documentation and/or other materials provided with the distribution.
14 | *
15 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
19 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
23 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
24 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 | * POSSIBILITY OF SUCH DAMAGE.
26 | */
27 |
28 | #include
29 |
30 | struct bspatch_stream
31 | {
32 | void* opaque;
33 | int (*read)(const struct bspatch_stream* stream, void* buffer, int length);
34 | };
35 |
36 | int bspatch(const uint8_t* old, int64_t oldsize, uint8_t* new, int64_t newsize, struct bspatch_stream* stream);
37 |
38 | #if !defined(BSPATCH_HEADER_ONLY)
39 |
40 | static int64_t offtin( const uint8_t *buf ) {
41 | /* taken from https://github.com/r-lyeh/vle */
42 | uint64_t out = 0, j = -7;
43 | do {
44 | out |= (( ((uint64_t)(*buf)) & 0x7f) << (j += 7) );
45 | } while( ((uint64_t)(*buf++)) & 0x80 );
46 | return (int64_t)( out & (1) ? ~(out >> 1) : (out >> 1) );
47 | }
48 |
49 | int bspatch(const uint8_t* old, int64_t oldsize, uint8_t* new, int64_t newsize, struct bspatch_stream* stream)
50 | {
51 | uint8_t buf[10], *ptr;
52 | int64_t oldpos,newpos;
53 | int64_t ctrl[3];
54 | int64_t i;
55 |
56 | oldpos=0;newpos=0;
57 | while(newposread(stream, ptr, 1) ) {
63 | return -1;
64 | }
65 | if( ((*ptr++) & 0x80) == 0x00 ) {
66 | break;
67 | }
68 | }
69 | ctrl[i]=offtin(buf);
70 | };
71 |
72 | /* Sanity-check */
73 | if(newpos+ctrl[0]>newsize)
74 | return -1;
75 |
76 | /* Read diff string */
77 | if (stream->read(stream, new + newpos, ctrl[0]))
78 | return -1;
79 |
80 | /* Add old data to diff string */
81 | for(i=0;i=0) && (oldpos+inewsize)
91 | return -1;
92 |
93 | /* Read extra string */
94 | if (stream->read(stream, new + newpos, ctrl[1]))
95 | return -1;
96 |
97 | /* Adjust pointers */
98 | newpos+=ctrl[1];
99 | oldpos+=ctrl[2];
100 | };
101 |
102 | return 0;
103 | }
104 |
105 | #if defined(BSPATCH_EXECUTABLE)
106 |
107 | #include
108 | #include
109 | #include
110 | #include
111 | #include
112 | #include
113 | #include
114 | #include
115 |
116 | static int bz2_read(const struct bspatch_stream* stream, void* buffer, int length)
117 | {
118 | int n;
119 | int bz2err;
120 | BZFILE* bz2;
121 |
122 | bz2 = (BZFILE*)stream->opaque;
123 | n = BZ2_bzRead(&bz2err, bz2, buffer, length);
124 | if (n != length)
125 | return -1;
126 |
127 | return 0;
128 | }
129 |
130 | int main(int argc,char * argv[])
131 | {
132 | FILE * f;
133 | int fd;
134 | int bz2err;
135 | uint8_t header[24];
136 | uint8_t *old, *new;
137 | int64_t oldsize, newsize;
138 | BZFILE* bz2;
139 | struct bspatch_stream stream;
140 |
141 | if(argc!=4) errx(1,"usage: %s oldfile newfile patchfile\n",argv[0]);
142 |
143 | /* Open patch file */
144 | if ((f = fopen(argv[3], "r")) == NULL)
145 | err(1, "fopen(%s)", argv[3]);
146 |
147 | /* Read header */
148 | if (fread(header, 1, 16, f) != 16) {
149 | if (feof(f))
150 | errx(1, "Corrupt patch\n");
151 | err(1, "fread(%s)", argv[3]);
152 | }
153 |
154 | /* Check for appropriate magic */
155 | if (memcmp(header, "ENDSLEY/BSDIFF43", 16) != 0)
156 | errx(1, "Corrupt patch\n");
157 |
158 | /* Read lengths from header */
159 | newsize=offtin(header+16);
160 | if(newsize<0)
161 | errx(1,"Corrupt patch\n");
162 |
163 | /* Close patch file and re-open it via libbzip2 at the right places */
164 | if(((fd=open(argv[1],O_RDONLY,0))<0) ||
165 | ((oldsize=lseek(fd,0,SEEK_END))==-1) ||
166 | ((old=malloc(oldsize+1))==NULL) ||
167 | (lseek(fd,0,SEEK_SET)!=0) ||
168 | (read(fd,old,oldsize)!=oldsize) ||
169 | (close(fd)==-1)) err(1,"%s",argv[1]);
170 | if((new=malloc(newsize+1))==NULL) err(1,NULL);
171 |
172 | if (NULL == (bz2 = BZ2_bzReadOpen(&bz2err, f, 0, 0, NULL, 0)))
173 | errx(1, "BZ2_bzReadOpen, bz2err=%d", bz2err);
174 |
175 | stream.read = bz2_read;
176 | stream.opaque = bz2;
177 | if (bspatch(old, oldsize, new, newsize, &stream))
178 | errx(1, "bspatch");
179 |
180 | /* Clean up the bzip2 reads */
181 | BZ2_bzReadClose(&bz2err, bz2);
182 | fclose(f);
183 |
184 | /* Write the new file */
185 | if(((fd=open(argv[2],O_CREAT|O_TRUNC|O_WRONLY,0666))<0) ||
186 | (write(fd,new,newsize)!=newsize) || (close(fd)==-1))
187 | err(1,"%s",argv[2]);
188 |
189 | free(new);
190 | free(old);
191 |
192 | return 0;
193 | }
194 |
195 | #endif
196 | #endif
197 |
--------------------------------------------------------------------------------
/redist/deps/bsdiff/sais.c:
--------------------------------------------------------------------------------
1 | /*
2 | * sais.c for sais-lite
3 | * Copyright (c) 2008-2010 Yuta Mori All Rights Reserved.
4 | *
5 | * Permission is hereby granted, free of charge, to any person
6 | * obtaining a copy of this software and associated documentation
7 | * files (the "Software"), to deal in the Software without
8 | * restriction, including without limitation the rights to use,
9 | * copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the
11 | * Software is furnished to do so, subject to the following
12 | * conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be
15 | * included in all copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
19 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
21 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24 | * OTHER DEALINGS IN THE SOFTWARE.
25 | */
26 |
27 | #include
28 | #include
29 | #include "sais.h"
30 |
31 | #ifndef UCHAR_SIZE
32 | # define UCHAR_SIZE 256
33 | #endif
34 | #ifndef MINBUCKETSIZE
35 | # define MINBUCKETSIZE 256
36 | #endif
37 |
38 | #define SAIS_LMSSORT2_LIMIT 0x3fffffff
39 |
40 | #define SAIS_MYMALLOC(_num, _type) ((_type *)malloc((_num) * sizeof(_type)))
41 | #define SAIS_MYFREE(_ptr, _num, _type) free((_ptr))
42 | #define chr(_a) (cs == sizeof(sais_index_type) ? ((sais_index_type *)T)[(_a)] : ((unsigned char *)T)[(_a)])
43 |
44 | /* find the start or end of each bucket */
45 | static
46 | void
47 | getCounts(const void *T, sais_index_type *C, sais_index_type n, sais_index_type k, int cs) {
48 | sais_index_type i;
49 | for(i = 0; i < k; ++i) { C[i] = 0; }
50 | for(i = 0; i < n; ++i) { ++C[chr(i)]; }
51 | }
52 | static
53 | void
54 | getBuckets(const sais_index_type *C, sais_index_type *B, sais_index_type k, sais_bool_type end) {
55 | sais_index_type i, sum = 0;
56 | if(end) { for(i = 0; i < k; ++i) { sum += C[i]; B[i] = sum; } }
57 | else { for(i = 0; i < k; ++i) { sum += C[i]; B[i] = sum - C[i]; } }
58 | }
59 |
60 | /* sort all type LMS suffixes */
61 | static
62 | void
63 | LMSsort1(const void *T, sais_index_type *SA,
64 | sais_index_type *C, sais_index_type *B,
65 | sais_index_type n, sais_index_type k, int cs) {
66 | sais_index_type *b, i, j;
67 | sais_index_type c0, c1;
68 |
69 | /* compute SAl */
70 | if(C == B) { getCounts(T, C, n, k, cs); }
71 | getBuckets(C, B, k, 0); /* find starts of buckets */
72 | j = n - 1;
73 | b = SA + B[c1 = chr(j)];
74 | --j;
75 | *b++ = (chr(j) < c1) ? ~j : j;
76 | for(i = 0; i < n; ++i) {
77 | if(0 < (j = SA[i])) {
78 | assert(chr(j) >= chr(j + 1));
79 | if((c0 = chr(j)) != c1) { B[c1] = b - SA; b = SA + B[c1 = c0]; }
80 | assert(i < (b - SA));
81 | --j;
82 | *b++ = (chr(j) < c1) ? ~j : j;
83 | SA[i] = 0;
84 | } else if(j < 0) {
85 | SA[i] = ~j;
86 | }
87 | }
88 | /* compute SAs */
89 | if(C == B) { getCounts(T, C, n, k, cs); }
90 | getBuckets(C, B, k, 1); /* find ends of buckets */
91 | for(i = n - 1, b = SA + B[c1 = 0]; 0 <= i; --i) {
92 | if(0 < (j = SA[i])) {
93 | assert(chr(j) <= chr(j + 1));
94 | if((c0 = chr(j)) != c1) { B[c1] = b - SA; b = SA + B[c1 = c0]; }
95 | assert((b - SA) <= i);
96 | --j;
97 | *--b = (chr(j) > c1) ? ~(j + 1) : j;
98 | SA[i] = 0;
99 | }
100 | }
101 | }
102 | static
103 | sais_index_type
104 | LMSpostproc1(const void *T, sais_index_type *SA,
105 | sais_index_type n, sais_index_type m, int cs) {
106 | sais_index_type i, j, p, q, plen, qlen, name;
107 | sais_index_type c0, c1;
108 | sais_bool_type diff;
109 |
110 | /* compact all the sorted substrings into the first m items of SA
111 | 2*m must be not larger than n (proveable) */
112 | assert(0 < n);
113 | for(i = 0; (p = SA[i]) < 0; ++i) { SA[i] = ~p; assert((i + 1) < n); }
114 | if(i < m) {
115 | for(j = i, ++i;; ++i) {
116 | assert(i < n);
117 | if((p = SA[i]) < 0) {
118 | SA[j++] = ~p; SA[i] = 0;
119 | if(j == m) { break; }
120 | }
121 | }
122 | }
123 |
124 | /* store the length of all substrings */
125 | i = n - 1; j = n - 1; c0 = chr(n - 1);
126 | do { c1 = c0; } while((0 <= --i) && ((c0 = chr(i)) >= c1));
127 | for(; 0 <= i;) {
128 | do { c1 = c0; } while((0 <= --i) && ((c0 = chr(i)) <= c1));
129 | if(0 <= i) {
130 | SA[m + ((i + 1) >> 1)] = j - i; j = i + 1;
131 | do { c1 = c0; } while((0 <= --i) && ((c0 = chr(i)) >= c1));
132 | }
133 | }
134 |
135 | /* find the lexicographic names of all substrings */
136 | for(i = 0, name = 0, q = n, qlen = 0; i < m; ++i) {
137 | p = SA[i], plen = SA[m + (p >> 1)], diff = 1;
138 | if((plen == qlen) && ((q + plen) < n)) {
139 | for(j = 0; (j < plen) && (chr(p + j) == chr(q + j)); ++j) { }
140 | if(j == plen) { diff = 0; }
141 | }
142 | if(diff != 0) { ++name, q = p, qlen = plen; }
143 | SA[m + (p >> 1)] = name;
144 | }
145 |
146 | return name;
147 | }
148 | static
149 | void
150 | LMSsort2(const void *T, sais_index_type *SA,
151 | sais_index_type *C, sais_index_type *B, sais_index_type *D,
152 | sais_index_type n, sais_index_type k, int cs) {
153 | sais_index_type *b, i, j, t, d;
154 | sais_index_type c0, c1;
155 | assert(C != B);
156 |
157 | /* compute SAl */
158 | getBuckets(C, B, k, 0); /* find starts of buckets */
159 | j = n - 1;
160 | b = SA + B[c1 = chr(j)];
161 | --j;
162 | t = (chr(j) < c1);
163 | j += n;
164 | *b++ = (t & 1) ? ~j : j;
165 | for(i = 0, d = 0; i < n; ++i) {
166 | if(0 < (j = SA[i])) {
167 | if(n <= j) { d += 1; j -= n; }
168 | assert(chr(j) >= chr(j + 1));
169 | if((c0 = chr(j)) != c1) { B[c1] = b - SA; b = SA + B[c1 = c0]; }
170 | assert(i < (b - SA));
171 | --j;
172 | t = c0; t = (t << 1) | (chr(j) < c1);
173 | if(D[t] != d) { j += n; D[t] = d; }
174 | *b++ = (t & 1) ? ~j : j;
175 | SA[i] = 0;
176 | } else if(j < 0) {
177 | SA[i] = ~j;
178 | }
179 | }
180 | for(i = n - 1; 0 <= i; --i) {
181 | if(0 < SA[i]) {
182 | if(SA[i] < n) {
183 | SA[i] += n;
184 | for(j = i - 1; SA[j] < n; --j) { }
185 | SA[j] -= n;
186 | i = j;
187 | }
188 | }
189 | }
190 |
191 | /* compute SAs */
192 | getBuckets(C, B, k, 1); /* find ends of buckets */
193 | for(i = n - 1, d += 1, b = SA + B[c1 = 0]; 0 <= i; --i) {
194 | if(0 < (j = SA[i])) {
195 | if(n <= j) { d += 1; j -= n; }
196 | assert(chr(j) <= chr(j + 1));
197 | if((c0 = chr(j)) != c1) { B[c1] = b - SA; b = SA + B[c1 = c0]; }
198 | assert((b - SA) <= i);
199 | --j;
200 | t = c0; t = (t << 1) | (chr(j) > c1);
201 | if(D[t] != d) { j += n; D[t] = d; }
202 | *--b = (t & 1) ? ~(j + 1) : j;
203 | SA[i] = 0;
204 | }
205 | }
206 | }
207 | static
208 | sais_index_type
209 | LMSpostproc2(sais_index_type *SA, sais_index_type n, sais_index_type m) {
210 | sais_index_type i, j, d, name;
211 |
212 | /* compact all the sorted LMS substrings into the first m items of SA */
213 | assert(0 < n);
214 | for(i = 0, name = 0; (j = SA[i]) < 0; ++i) {
215 | j = ~j;
216 | if(n <= j) { name += 1; }
217 | SA[i] = j;
218 | assert((i + 1) < n);
219 | }
220 | if(i < m) {
221 | for(d = i, ++i;; ++i) {
222 | assert(i < n);
223 | if((j = SA[i]) < 0) {
224 | j = ~j;
225 | if(n <= j) { name += 1; }
226 | SA[d++] = j; SA[i] = 0;
227 | if(d == m) { break; }
228 | }
229 | }
230 | }
231 | if(name < m) {
232 | /* store the lexicographic names */
233 | for(i = m - 1, d = name + 1; 0 <= i; --i) {
234 | if(n <= (j = SA[i])) { j -= n; --d; }
235 | SA[m + (j >> 1)] = d;
236 | }
237 | } else {
238 | /* unset flags */
239 | for(i = 0; i < m; ++i) {
240 | if(n <= (j = SA[i])) { j -= n; SA[i] = j; }
241 | }
242 | }
243 |
244 | return name;
245 | }
246 |
247 | /* compute SA and BWT */
248 | static
249 | void
250 | induceSA(const void *T, sais_index_type *SA,
251 | sais_index_type *C, sais_index_type *B,
252 | sais_index_type n, sais_index_type k, int cs) {
253 | sais_index_type *b, i, j;
254 | sais_index_type c0, c1;
255 | /* compute SAl */
256 | if(C == B) { getCounts(T, C, n, k, cs); }
257 | getBuckets(C, B, k, 0); /* find starts of buckets */
258 | j = n - 1;
259 | b = SA + B[c1 = chr(j)];
260 | *b++ = ((0 < j) && (chr(j - 1) < c1)) ? ~j : j;
261 | for(i = 0; i < n; ++i) {
262 | j = SA[i], SA[i] = ~j;
263 | if(0 < j) {
264 | --j;
265 | assert(chr(j) >= chr(j + 1));
266 | if((c0 = chr(j)) != c1) { B[c1] = b - SA; b = SA + B[c1 = c0]; }
267 | assert(i < (b - SA));
268 | *b++ = ((0 < j) && (chr(j - 1) < c1)) ? ~j : j;
269 | }
270 | }
271 | /* compute SAs */
272 | if(C == B) { getCounts(T, C, n, k, cs); }
273 | getBuckets(C, B, k, 1); /* find ends of buckets */
274 | for(i = n - 1, b = SA + B[c1 = 0]; 0 <= i; --i) {
275 | if(0 < (j = SA[i])) {
276 | --j;
277 | assert(chr(j) <= chr(j + 1));
278 | if((c0 = chr(j)) != c1) { B[c1] = b - SA; b = SA + B[c1 = c0]; }
279 | assert((b - SA) <= i);
280 | *--b = ((j == 0) || (chr(j - 1) > c1)) ? ~j : j;
281 | } else {
282 | SA[i] = ~j;
283 | }
284 | }
285 | }
286 | static
287 | sais_index_type
288 | computeBWT(const void *T, sais_index_type *SA,
289 | sais_index_type *C, sais_index_type *B,
290 | sais_index_type n, sais_index_type k, int cs) {
291 | sais_index_type *b, i, j, pidx = -1;
292 | sais_index_type c0, c1;
293 | /* compute SAl */
294 | if(C == B) { getCounts(T, C, n, k, cs); }
295 | getBuckets(C, B, k, 0); /* find starts of buckets */
296 | j = n - 1;
297 | b = SA + B[c1 = chr(j)];
298 | *b++ = ((0 < j) && (chr(j - 1) < c1)) ? ~j : j;
299 | for(i = 0; i < n; ++i) {
300 | if(0 < (j = SA[i])) {
301 | --j;
302 | assert(chr(j) >= chr(j + 1));
303 | SA[i] = ~((sais_index_type)(c0 = chr(j)));
304 | if(c0 != c1) { B[c1] = b - SA; b = SA + B[c1 = c0]; }
305 | assert(i < (b - SA));
306 | *b++ = ((0 < j) && (chr(j - 1) < c1)) ? ~j : j;
307 | } else if(j != 0) {
308 | SA[i] = ~j;
309 | }
310 | }
311 | /* compute SAs */
312 | if(C == B) { getCounts(T, C, n, k, cs); }
313 | getBuckets(C, B, k, 1); /* find ends of buckets */
314 | for(i = n - 1, b = SA + B[c1 = 0]; 0 <= i; --i) {
315 | if(0 < (j = SA[i])) {
316 | --j;
317 | assert(chr(j) <= chr(j + 1));
318 | SA[i] = (c0 = chr(j));
319 | if(c0 != c1) { B[c1] = b - SA; b = SA + B[c1 = c0]; }
320 | assert((b - SA) <= i);
321 | *--b = ((0 < j) && (chr(j - 1) > c1)) ? ~((sais_index_type)chr(j - 1)) : j;
322 | } else if(j != 0) {
323 | SA[i] = ~j;
324 | } else {
325 | pidx = i;
326 | }
327 | }
328 | return pidx;
329 | }
330 |
331 | /* find the suffix array SA of T[0..n-1] in {0..255}^n */
332 | static
333 | sais_index_type
334 | sais_main(const void *T, sais_index_type *SA,
335 | sais_index_type fs, sais_index_type n, sais_index_type k, int cs,
336 | sais_bool_type isbwt) {
337 | sais_index_type *C, *B, *D, *RA, *b;
338 | sais_index_type i, j, m, p, q, t, name, pidx = 0, newfs;
339 | sais_index_type c0, c1;
340 | unsigned int flags;
341 |
342 | assert((T != NULL) && (SA != NULL));
343 | assert((0 <= fs) && (0 < n) && (1 <= k));
344 |
345 | if(k <= MINBUCKETSIZE) {
346 | if((C = SAIS_MYMALLOC(k, sais_index_type)) == NULL) { return -2; }
347 | if(k <= fs) {
348 | B = SA + (n + fs - k);
349 | flags = 1;
350 | } else {
351 | if((B = SAIS_MYMALLOC(k, sais_index_type)) == NULL) { SAIS_MYFREE(C, k, sais_index_type); return -2; }
352 | flags = 3;
353 | }
354 | } else if(k <= fs) {
355 | C = SA + (n + fs - k);
356 | if(k <= (fs - k)) {
357 | B = C - k;
358 | flags = 0;
359 | } else if(k <= (MINBUCKETSIZE * 4)) {
360 | if((B = SAIS_MYMALLOC(k, sais_index_type)) == NULL) { return -2; }
361 | flags = 2;
362 | } else {
363 | B = C;
364 | flags = 8;
365 | }
366 | } else {
367 | if((C = B = SAIS_MYMALLOC(k, sais_index_type)) == NULL) { return -2; }
368 | flags = 4 | 8;
369 | }
370 | if((n <= SAIS_LMSSORT2_LIMIT) && (2 <= (n / k))) {
371 | if(flags & 1) { flags |= ((k * 2) <= (fs - k)) ? 32 : 16; }
372 | else if((flags == 0) && ((k * 2) <= (fs - k * 2))) { flags |= 32; }
373 | }
374 |
375 | /* stage 1: reduce the problem by at least 1/2
376 | sort all the LMS-substrings */
377 | getCounts(T, C, n, k, cs); getBuckets(C, B, k, 1); /* find ends of buckets */
378 | for(i = 0; i < n; ++i) { SA[i] = 0; }
379 | b = &t; i = n - 1; j = n; m = 0; c0 = chr(n - 1);
380 | do { c1 = c0; } while((0 <= --i) && ((c0 = chr(i)) >= c1));
381 | for(; 0 <= i;) {
382 | do { c1 = c0; } while((0 <= --i) && ((c0 = chr(i)) <= c1));
383 | if(0 <= i) {
384 | *b = j; b = SA + --B[c1]; j = i; ++m;
385 | do { c1 = c0; } while((0 <= --i) && ((c0 = chr(i)) >= c1));
386 | }
387 | }
388 |
389 | if(1 < m) {
390 | if(flags & (16 | 32)) {
391 | if(flags & 16) {
392 | if((D = SAIS_MYMALLOC(k * 2, sais_index_type)) == NULL) {
393 | if(flags & (1 | 4)) { SAIS_MYFREE(C, k, sais_index_type); }
394 | if(flags & 2) { SAIS_MYFREE(B, k, sais_index_type); }
395 | return -2;
396 | }
397 | } else {
398 | D = B - k * 2;
399 | }
400 | assert((j + 1) < n);
401 | ++B[chr(j + 1)];
402 | for(i = 0, j = 0; i < k; ++i) {
403 | j += C[i];
404 | if(B[i] != j) { assert(SA[B[i]] != 0); SA[B[i]] += n; }
405 | D[i] = D[i + k] = 0;
406 | }
407 | LMSsort2(T, SA, C, B, D, n, k, cs);
408 | name = LMSpostproc2(SA, n, m);
409 | if(flags & 16) { SAIS_MYFREE(D, k * 2, sais_index_type); }
410 | } else {
411 | LMSsort1(T, SA, C, B, n, k, cs);
412 | name = LMSpostproc1(T, SA, n, m, cs);
413 | }
414 | } else if(m == 1) {
415 | *b = j + 1;
416 | name = 1;
417 | } else {
418 | name = 0;
419 | }
420 |
421 | /* stage 2: solve the reduced problem
422 | recurse if names are not yet unique */
423 | if(name < m) {
424 | if(flags & 4) { SAIS_MYFREE(C, k, sais_index_type); }
425 | if(flags & 2) { SAIS_MYFREE(B, k, sais_index_type); }
426 | newfs = (n + fs) - (m * 2);
427 | if((flags & (1 | 4 | 8)) == 0) {
428 | if((k + name) <= newfs) { newfs -= k; }
429 | else { flags |= 8; }
430 | }
431 | assert((n >> 1) <= (newfs + m));
432 | RA = SA + m + newfs;
433 | for(i = m + (n >> 1) - 1, j = m - 1; m <= i; --i) {
434 | if(SA[i] != 0) {
435 | RA[j--] = SA[i] - 1;
436 | }
437 | }
438 | if(sais_main(RA, SA, newfs, m, name, sizeof(sais_index_type), 0) != 0) {
439 | if(flags & 1) { SAIS_MYFREE(C, k, sais_index_type); }
440 | return -2;
441 | }
442 |
443 | i = n - 1; j = m - 1; c0 = chr(n - 1);
444 | do { c1 = c0; } while((0 <= --i) && ((c0 = chr(i)) >= c1));
445 | for(; 0 <= i;) {
446 | do { c1 = c0; } while((0 <= --i) && ((c0 = chr(i)) <= c1));
447 | if(0 <= i) {
448 | RA[j--] = i + 1;
449 | do { c1 = c0; } while((0 <= --i) && ((c0 = chr(i)) >= c1));
450 | }
451 | }
452 | for(i = 0; i < m; ++i) { SA[i] = RA[SA[i]]; }
453 | if(flags & 4) {
454 | if((C = B = SAIS_MYMALLOC(k, sais_index_type)) == NULL) { return -2; }
455 | }
456 | if(flags & 2) {
457 | if((B = SAIS_MYMALLOC(k, sais_index_type)) == NULL) {
458 | if(flags & 1) { SAIS_MYFREE(C, k, sais_index_type); }
459 | return -2;
460 | }
461 | }
462 | }
463 |
464 | /* stage 3: induce the result for the original problem */
465 | if(flags & 8) { getCounts(T, C, n, k, cs); }
466 | /* put all left-most S characters into their buckets */
467 | if(1 < m) {
468 | getBuckets(C, B, k, 1); /* find ends of buckets */
469 | i = m - 1, j = n, p = SA[m - 1], c1 = chr(p);
470 | do {
471 | q = B[c0 = c1];
472 | while(q < j) { SA[--j] = 0; }
473 | do {
474 | SA[--j] = p;
475 | if(--i < 0) { break; }
476 | p = SA[i];
477 | } while((c1 = chr(p)) == c0);
478 | } while(0 <= i);
479 | while(0 < j) { SA[--j] = 0; }
480 | }
481 | if(isbwt == 0) { induceSA(T, SA, C, B, n, k, cs); }
482 | else { pidx = computeBWT(T, SA, C, B, n, k, cs); }
483 | if(flags & (1 | 4)) { SAIS_MYFREE(C, k, sais_index_type); }
484 | if(flags & 2) { SAIS_MYFREE(B, k, sais_index_type); }
485 |
486 | return pidx;
487 | }
488 |
489 | /*---------------------------------------------------------------------------*/
490 |
491 | int
492 | sais(const unsigned char *T, sais_index_type *SA, int n) {
493 | if((T == NULL) || (SA == NULL) || (n < 0)) { return -1; }
494 | if(n <= 1) { if(n == 1) { SA[0] = 0; } return 0; }
495 | return sais_main(T, SA, 0, n, UCHAR_SIZE, sizeof(unsigned char), 0);
496 | }
497 |
498 | int
499 | sais_int(const int *T, sais_index_type *SA, int n, int k) {
500 | if((T == NULL) || (SA == NULL) || (n < 0) || (k <= 0)) { return -1; }
501 | if(n <= 1) { if(n == 1) { SA[0] = 0; } return 0; }
502 | return sais_main(T, SA, 0, n, k, sizeof(int), 0);
503 | }
504 |
505 | int
506 | sais_bwt(const unsigned char *T, unsigned char *U, sais_index_type *A, int n) {
507 | int i, pidx;
508 | if((T == NULL) || (U == NULL) || (A == NULL) || (n < 0)) { return -1; }
509 | if(n <= 1) { if(n == 1) { U[0] = T[0]; } return n; }
510 | pidx = sais_main(T, A, 0, n, UCHAR_SIZE, sizeof(unsigned char), 1);
511 | if(pidx < 0) { return pidx; }
512 | U[0] = T[n - 1];
513 | for(i = 0; i < pidx; ++i) { U[i + 1] = (unsigned char)A[i]; }
514 | for(i += 1; i < n; ++i) { U[i] = (unsigned char)A[i]; }
515 | pidx += 1;
516 | return pidx;
517 | }
518 |
519 | int
520 | sais_int_bwt(const int *T, sais_index_type *U, sais_index_type *A, int n, int k) {
521 | int i, pidx;
522 | if((T == NULL) || (U == NULL) || (A == NULL) || (n < 0) || (k <= 0)) { return -1; }
523 | if(n <= 1) { if(n == 1) { U[0] = T[0]; } return n; }
524 | pidx = sais_main(T, A, 0, n, k, sizeof(int), 1);
525 | if(pidx < 0) { return pidx; }
526 | U[0] = T[n - 1];
527 | for(i = 0; i < pidx; ++i) { U[i + 1] = A[i]; }
528 | for(i += 1; i < n; ++i) { U[i] = A[i]; }
529 | pidx += 1;
530 | return pidx;
531 | }
532 |
--------------------------------------------------------------------------------
/redist/deps/bsdiff/sais.h:
--------------------------------------------------------------------------------
1 | /*
2 | * sais.h for sais-lite
3 | * Copyright (c) 2008-2010 Yuta Mori All Rights Reserved.
4 | *
5 | * Permission is hereby granted, free of charge, to any person
6 | * obtaining a copy of this software and associated documentation
7 | * files (the "Software"), to deal in the Software without
8 | * restriction, including without limitation the rights to use,
9 | * copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the
11 | * Software is furnished to do so, subject to the following
12 | * conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be
15 | * included in all copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
19 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
21 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24 | * OTHER DEALINGS IN THE SOFTWARE.
25 | */
26 |
27 | #ifndef _SAIS_H
28 | #define _SAIS_H 1
29 |
30 | #include
31 | #define sais_index_type int64_t
32 | #define sais_bool_type int
33 |
34 | #ifdef __cplusplus
35 | extern "C" {
36 | #endif /* __cplusplus */
37 |
38 | /* find the suffix array SA of T[0..n-1]
39 | use a working space (excluding T and SA) of at most 2n+O(lg n) */
40 | int
41 | sais(const unsigned char *T, sais_index_type *SA, int n);
42 |
43 | /* find the suffix array SA of T[0..n-1] in {0..k-1}^n
44 | use a working space (excluding T and SA) of at most MAX(4k,2n) */
45 | int
46 | sais_int(const int *T, sais_index_type *SA, int n, int k);
47 |
48 | /* burrows-wheeler transform */
49 | int
50 | sais_bwt(const unsigned char *T, unsigned char *U, sais_index_type *A, int n);
51 | int
52 | sais_int_bwt(const int *T, sais_index_type *U, sais_index_type *A, int n, int k);
53 |
54 |
55 | #ifdef __cplusplus
56 | } /* extern "C" */
57 | #endif /* __cplusplus */
58 |
59 | #endif /* _SAIS_H */
60 |
--------------------------------------------------------------------------------
/redist/deps/fart.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r-lyeh-archived/collage/29573f36db3795bae6ca8602b744f5fa558d1270/redist/deps/fart.exe
--------------------------------------------------------------------------------
/sample.cc:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include "collage.hpp"
4 |
5 | int main() {
6 | std::string source = "hello world and thanks";
7 | std::string target = "hello cruel \x1 world. thanks for the fish.";
8 |
9 | std::string patch = collage::diff( source, target );
10 | assert( !patch.empty() );
11 |
12 | std::string patched = collage::patch( source, patch );
13 | assert( !patched.empty() );
14 | assert( target == patched );
15 |
16 | std::cout << "'" << source << "' + " << patch.size() << "-bytes patch == '" << patched << "'" << std::endl;
17 | std::cout << "All ok." << std::endl;
18 | }
19 |
--------------------------------------------------------------------------------