├── .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 | --------------------------------------------------------------------------------