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