1/* overlap.c -- example program: overlapping (de)compression 2 3 This file is part of the LZO real-time data compression library. 4 5 Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer 6 Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer 7 Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer 8 Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer 9 Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer 10 Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer 11 Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer 12 Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer 13 Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer 14 Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer 15 Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer 16 Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer 17 Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer 18 All Rights Reserved. 19 20 The LZO library is free software; you can redistribute it and/or 21 modify it under the terms of the GNU General Public License as 22 published by the Free Software Foundation; either version 2 of 23 the License, or (at your option) any later version. 24 25 The LZO library is distributed in the hope that it will be useful, 26 but WITHOUT ANY WARRANTY; without even the implied warranty of 27 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 GNU General Public License for more details. 29 30 You should have received a copy of the GNU General Public License 31 along with the LZO library; see the file COPYING. 32 If not, write to the Free Software Foundation, Inc., 33 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 34 35 Markus F.X.J. Oberhumer 36 <markus@oberhumer.com> 37 http://www.oberhumer.com/opensource/lzo/ 38 */ 39 40 41/************************************************************************* 42// This program shows how to do overlapping compression and 43// in-place decompression. 44// 45// Please study LZO.FAQ and simple.c first. 46**************************************************************************/ 47 48#include "lzo/lzoconf.h" 49#include "lzo/lzo1x.h" 50 51/* portability layer */ 52#define WANT_LZO_MALLOC 1 53#define WANT_LZO_FREAD 1 54#define WANT_LZO_WILDARGV 1 55#include "examples/portab.h" 56 57 58/* Overhead (in bytes) for the in-place decompression buffer. 59 * Most files need only 16 ! 60 * (try `overlap -16 file' or even `overlap -8 file') 61 * 62 * Worst case (for files that are compressible by only a few bytes) 63 * is 'in_len / 16 + 64 + 3'. See step 5a) below. 64 * 65 * For overlapping compression '0xbfff + in_len / 16 + 64 + 3' bytes 66 * will be needed. See step 4a) below. 67 */ 68 69static lzo_uint opt_overhead = 0; /* assume worst case */ 70 71 72#if 0 && defined(LZO_USE_ASM) 73 /* just for testing */ 74# include <lzo_asm.h> 75# define lzo1x_decompress lzo1x_decompress_asm_fast 76#endif 77 78 79/************************************************************************* 80// 81**************************************************************************/ 82 83static const char *progname = NULL; 84 85static unsigned long total_files = 0; 86static unsigned long total_in = 0; 87 88 89static lzo_bytep xmalloc(lzo_uint len) 90{ 91 lzo_bytep p; 92 93 p = (lzo_bytep) lzo_malloc(len > 0 ? len : 1); 94 if (p == NULL) 95 { 96 printf("%s: out of memory\n", progname); 97 exit(1); 98 } 99 return p; 100} 101 102 103/************************************************************************* 104// 105**************************************************************************/ 106 107int do_file ( const char *in_name ) 108{ 109 int r; 110 FILE *f = NULL; 111 long l; 112 113 lzo_bytep wrkmem = NULL; 114 115 lzo_bytep in = NULL; 116 lzo_uint in_len; /* uncompressed length */ 117 118 lzo_bytep out = NULL; 119 lzo_uint out_len; /* compressed length */ 120 121 lzo_bytep overlap = NULL; 122 lzo_uint overhead; 123 lzo_uint offset; 124 125 lzo_uint new_len = 0; 126 127/* 128 * Step 1: open the input file 129 */ 130 f = fopen(in_name,"rb"); 131 if (f == NULL) 132 { 133 printf("%s: %s: cannot open file\n", progname, in_name); 134 goto next_file; 135 } 136 fseek(f,0,SEEK_END); 137 l = ftell(f); 138 fseek(f,0,SEEK_SET); 139 if (l <= 0) 140 { 141 printf("%s: %s: empty file -- skipping\n", progname, in_name); 142 goto next_file; 143 } 144 in_len = (lzo_uint) l; 145 146/* 147 * Step 2: allocate compression buffers and read the file 148 */ 149 in = xmalloc(in_len); 150 out = xmalloc(in_len + in_len / 16 + 64 + 3); 151 wrkmem = xmalloc(LZO1X_1_MEM_COMPRESS); 152 in_len = (lzo_uint) lzo_fread(f,in,in_len); 153 fclose(f); f = NULL; 154 printf("%s: %s: read %ld bytes\n", progname, in_name, (long) in_len); 155 156 total_files++; 157 total_in += (unsigned long) in_len; 158 159/* 160 * Step 3: compress from `in' to `out' with LZO1X-1 161 */ 162 r = lzo1x_1_compress(in,in_len,out,&out_len,wrkmem); 163 if (r != LZO_E_OK || out_len > in_len + in_len / 16 + 64 + 3) 164 { 165 /* this should NEVER happen */ 166 printf("internal error - compression failed: %d\n", r); 167 exit(1); 168 } 169 printf("%-26s %8lu -> %8lu\n", "LZO1X-1:", (long) in_len, (long) out_len); 170 171 172/***** Step 4: overlapping compression *****/ 173 174/* 175 * Step 4a: allocate the `overlap' buffer for overlapping compression 176 */ 177 overhead = in_len > 0xbfff ? 0xbfff : in_len; 178 overhead += in_len / 16 + 64 + 3; 179 overlap = xmalloc(in_len + overhead); 180 181/* 182 * Step 4b: prepare data in `overlap' buffer. 183 * copy uncompressed data at the top of the overlap buffer 184 */ 185 /*** offset = in_len + overhead - in_len; ***/ 186 offset = overhead; 187 lzo_memcpy(overlap + offset, in, in_len); 188 189/* 190 * Step 4c: do an in-place compression within the `overlap' buffer 191 */ 192 r = lzo1x_1_compress(overlap+offset,in_len,overlap,&new_len,wrkmem); 193 if (r != LZO_E_OK) 194 { 195 /* this should NEVER happen */ 196 printf("overlapping compression failed: %d\n", r); 197 exit(1); 198 } 199 200/* 201 * Step 4d: verify overlapping compression 202 */ 203 if (new_len != out_len || lzo_memcmp(out,overlap,out_len) != 0) 204 { 205 /* As compression is non-deterministic there can be a difference 206 * in the representation of the compressed data (but this usually 207 * happens very seldom). So we have to verify the overlapping 208 * compression by doing a temporary decompression. 209 */ 210 lzo_uint l = in_len; 211 lzo_bytep tmp = xmalloc(l); 212 r = lzo1x_decompress_safe(overlap,new_len,tmp,&l,NULL); 213 if (r != LZO_E_OK || l != in_len || lzo_memcmp(in,tmp,l) != 0) 214 { 215 /* this should NEVER happen */ 216 printf("overlapping compression data error\n"); 217 exit(1); 218 } 219 lzo_free(tmp); 220 } 221 222 printf("overlapping compression: %8lu -> %8lu overhead: %7ld\n", 223 (long) in_len, (long) new_len, (long) overhead); 224 lzo_free(overlap); overlap = NULL; 225 226 227/***** Step 5: overlapping decompression *****/ 228 229/* 230 * Step 5a: allocate the `overlap' buffer for in-place decompression 231 */ 232 if (opt_overhead == 0 || out_len >= in_len) 233 overhead = in_len / 16 + 64 + 3; 234 else 235 overhead = opt_overhead; 236 overlap = xmalloc(in_len + overhead); 237 238/* 239 * Step 5b: prepare data in `overlap' buffer. 240 * copy compressed data at the top of the overlap buffer 241 */ 242 offset = in_len + overhead - out_len; 243 lzo_memcpy(overlap + offset, out, out_len); 244 245/* 246 * Step 5c: do an in-place decompression within the `overlap' buffer 247 */ 248 new_len = in_len; 249 r = lzo1x_decompress(overlap+offset,out_len,overlap,&new_len,NULL); 250 if (r != LZO_E_OK) 251 { 252 /* this may happen if overhead is too small */ 253 printf("overlapping decompression failed: %d - increase `opt_overhead'\n", r); 254 exit(1); 255 } 256 257/* 258 * Step 5d: verify decompression 259 */ 260 if (new_len != in_len || lzo_memcmp(in,overlap,in_len) != 0) 261 { 262 /* this may happen if overhead is too small */ 263 printf("overlapping decompression data error - increase `opt_overhead'\n"); 264 exit(1); 265 } 266 printf("overlapping decompression: %8lu -> %8lu overhead: %7ld\n", 267 (long) out_len, (long) new_len, (long) overhead); 268 lzo_free(overlap); overlap = NULL; 269 270 271next_file: 272 lzo_free(overlap); 273 lzo_free(wrkmem); 274 lzo_free(out); 275 lzo_free(in); 276 if (f) fclose(f); 277 278 return 0; 279} 280 281 282/************************************************************************* 283// 284**************************************************************************/ 285 286int __lzo_cdecl_main main(int argc, char *argv[]) 287{ 288 int r; 289 int i = 1; 290 291 lzo_wildargv(&argc, &argv); 292 293 printf("\nLZO real-time data compression library (v%s, %s).\n", 294 lzo_version_string(), lzo_version_date()); 295 printf("Copyright (C) 1996-2008 Markus Franz Xaver Johannes Oberhumer\nAll Rights Reserved.\n\n"); 296 297 progname = argv[0]; 298 if (i < argc && argv[i][0] == '-') 299 opt_overhead = atoi(&argv[i++][1]); 300#if 1 301 if (opt_overhead != 0 && opt_overhead < 8) 302 { 303 printf("%s: invalid overhead value %ld\n", progname, (long)opt_overhead); 304 exit(1); 305 } 306#endif 307 if (i >= argc) 308 { 309 printf("usage: %s [-overhead_in_bytes] file..\n", progname); 310 exit(1); 311 } 312 313/* 314 * Step 1: initialize the LZO library 315 */ 316 if (lzo_init() != LZO_E_OK) 317 { 318 printf("internal error - lzo_init() failed !!!\n"); 319 printf("(this usually indicates a compiler bug - try recompiling\nwithout optimizations, and enable `-DLZO_DEBUG' for diagnostics)\n"); 320 exit(1); 321 } 322 323/* 324 * Step 2: process files 325 */ 326 for (r = 0; r == 0 && i < argc; i++) 327 r = do_file(argv[i]); 328 329 printf("\nDone. Successfully processed %lu bytes in %lu files.\n", 330 total_in, total_files); 331 return r; 332} 333 334/* 335vi:ts=4:et 336*/ 337 338