blind-compress.c (1552B)
1 /* See LICENSE file for copyright and license details. */ 2 #include "common.h" 3 4 USAGE("") 5 6 static size_t 7 compare(const char *restrict new, const char *restrict old, size_t n, size_t **cmp, size_t *cmpsize) 8 { 9 size_t i, start1, start2, ptr, same, diff; 10 for (ptr = i = 0; i < n;) { 11 for (start1 = i; i < n && old[i] == new[i]; i++); 12 for (start2 = i; i < n && old[i] != new[i]; i++); 13 same = start2 - start1; 14 diff = i - start2; 15 if (ptr && same < 2 * sizeof(size_t) && same + diff <= SIZE_MAX - (*cmp)[ptr - 1]) { 16 (*cmp)[ptr - 1] += same + diff; 17 } else { 18 if (ptr + 2 > *cmpsize) 19 *cmp = erealloc2(*cmp, *cmpsize += 128, sizeof(size_t)); 20 (*cmp)[ptr++] = same; 21 (*cmp)[ptr++] = diff; 22 } 23 } 24 return ptr; 25 } 26 27 int 28 main(int argc, char *argv[]) 29 { 30 struct stream stream; 31 char *buf[2]; 32 size_t parts, part, off; 33 int i; 34 size_t *cmp = NULL; 35 size_t cmpsize = 0; 36 37 UNOFLAGS(argc); 38 39 eopen_stream(&stream, NULL); 40 echeck_dimensions(&stream, WIDTH | HEIGHT, NULL); 41 fprint_stream_head(stdout, &stream); 42 efflush(stdout, "<stdout>"); 43 44 buf[0] = emalloc(stream.frame_size); 45 buf[1] = ecalloc(1, stream.frame_size); 46 47 for (i = 0; eread_frame(&stream, buf[i]); i ^= 1) { 48 parts = compare(buf[i], buf[i ^ 1], stream.frame_size, &cmp, &cmpsize); 49 for (off = part = 0; part < parts; part += 2) { 50 off += cmp[part]; 51 ewriteall(STDOUT_FILENO, cmp + part, 2 * sizeof(size_t), "<stdout>"); 52 ewriteall(STDOUT_FILENO, buf[i] + off, cmp[part + 1], "<stdout>"); 53 off += cmp[part + 1]; 54 } 55 } 56 57 free(cmp); 58 free(buf[0]); 59 free(buf[1]); 60 return 0; 61 }