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