1/* precomp2.c -- example program: how to generate pre-compressed data
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 generate pre-compressed data.
43//
44// Please study precomp.c first.
45//
46// We will be trying LZO1X-999 and LZO1Y-999, and we will be trying
47// various parameters using the internal interface to squeeze out
48// a little bit of extra compression.
49//
50// NOTE: this program can be quite slow for highly redundant files
51**************************************************************************/
52
53#include "lzo/lzoconf.h"
54#include "lzo/lzo1x.h"
55#include "lzo/lzo1y.h"
56
57LZO_EXTERN(int)
58lzo1x_999_compress_internal ( const lzo_bytep in , lzo_uint  in_len,
59                                    lzo_bytep out, lzo_uintp out_len,
60                                    lzo_voidp wrkmem,
61                              const lzo_bytep dict, lzo_uint dict_len,
62                                    lzo_callback_p cb,
63                                    int try_lazy,
64                                    lzo_uint good_length,
65                                    lzo_uint max_lazy,
66                                    lzo_uint nice_length,
67                                    lzo_uint max_chain,
68                                    lzo_uint32 flags );
69
70LZO_EXTERN(int)
71lzo1y_999_compress_internal ( const lzo_bytep in , lzo_uint  in_len,
72                                    lzo_bytep out, lzo_uintp out_len,
73                                    lzo_voidp wrkmem,
74                              const lzo_bytep dict, lzo_uint dict_len,
75                                    lzo_callback_p cb,
76                                    int try_lazy,
77                                    lzo_uint good_length,
78                                    lzo_uint max_lazy,
79                                    lzo_uint nice_length,
80                                    lzo_uint max_chain,
81                                    lzo_uint32 flags );
82
83#define USE_LZO1X 1
84#define USE_LZO1Y 1
85
86#define PARANOID 1
87
88
89/* portability layer */
90#define WANT_LZO_MALLOC 1
91#define WANT_LZO_FREAD 1
92#define WANT_LZO_WILDARGV 1
93#include "examples/portab.h"
94
95
96/*************************************************************************
97//
98**************************************************************************/
99
100int __lzo_cdecl_main main(int argc, char *argv[])
101{
102    int r;
103    int lazy;
104    const int max_try_lazy = 5;
105    const lzo_uint big = 65536L;    /* can result in very slow compression */
106    const lzo_uint32 flags = 0x1;
107
108    lzo_bytep in;
109    lzo_uint in_len;
110
111    lzo_bytep out;
112    lzo_uint out_bufsize;
113    lzo_uint out_len = 0;
114
115    lzo_bytep wrkmem;
116    lzo_uint wrk_len;
117
118    lzo_uint best_len;
119    int best_compress = -1;
120    int best_lazy = -1;
121
122    lzo_uint orig_len;
123    lzo_uint32 uncompressed_checksum;
124    lzo_uint32 compressed_checksum;
125
126    FILE *f;
127    const char *progname = NULL;
128    const char *in_name = NULL;
129    const char *out_name = NULL;
130    long l;
131
132
133    lzo_wildargv(&argc, &argv);
134
135    printf("\nLZO real-time data compression library (v%s, %s).\n",
136           lzo_version_string(), lzo_version_date());
137    printf("Copyright (C) 1996-2008 Markus Franz Xaver Johannes Oberhumer\nAll Rights Reserved.\n\n");
138
139    progname = argv[0];
140    if (argc < 2 || argc > 3)
141    {
142        printf("usage: %s file [output-file]\n", progname);
143        exit(1);
144    }
145    in_name = argv[1];
146    if (argc > 2) out_name = argv[2];
147
148/*
149 * Step 1: initialize the LZO library
150 */
151    if (lzo_init() != LZO_E_OK)
152    {
153        printf("internal error - lzo_init() failed !!!\n");
154        printf("(this usually indicates a compiler bug - try recompiling\nwithout optimizations, and enable `-DLZO_DEBUG' for diagnostics)\n");
155        exit(1);
156    }
157
158/*
159 * Step 2: allocate the work-memory
160 */
161    wrk_len = 1;
162#ifdef USE_LZO1X
163    if (wrk_len < LZO1X_999_MEM_COMPRESS)
164        wrk_len = LZO1X_999_MEM_COMPRESS;
165#endif
166#ifdef USE_LZO1Y
167    if (wrk_len < LZO1Y_999_MEM_COMPRESS)
168        wrk_len = LZO1Y_999_MEM_COMPRESS;
169#endif
170    wrkmem = (lzo_bytep) lzo_malloc(wrk_len);
171    if (wrkmem == NULL)
172    {
173        printf("%s: out of memory\n", progname);
174        exit(1);
175    }
176
177/*
178 * Step 3: open the input file
179 */
180    f = fopen(in_name,"rb");
181    if (f == NULL)
182    {
183        printf("%s: cannot open file %s\n", progname, in_name);
184        exit(1);
185    }
186    fseek(f,0,SEEK_END);
187    l = ftell(f);
188    fseek(f,0,SEEK_SET);
189    if (l <= 0)
190    {
191        printf("%s: %s: empty file\n", progname, in_name);
192        fclose(f);
193        exit(1);
194    }
195    in_len = (lzo_uint) l;
196    out_bufsize = in_len + in_len / 16 + 64 + 3;
197    best_len = in_len;
198
199/*
200 * Step 4: allocate compression buffers and read the file
201 */
202    in = (lzo_bytep) lzo_malloc(in_len);
203    out = (lzo_bytep) lzo_malloc(out_bufsize);
204    if (in == NULL || out == NULL)
205    {
206        printf("%s: out of memory\n", progname);
207        exit(1);
208    }
209    in_len = (lzo_uint) lzo_fread(f,in,in_len);
210    printf("%s: loaded file %s: %ld bytes\n", progname, in_name, (long) in_len);
211    fclose(f);
212
213/*
214 * Step 5: compute a checksum of the uncompressed data
215 */
216    uncompressed_checksum = lzo_adler32(0,NULL,0);
217    uncompressed_checksum = lzo_adler32(uncompressed_checksum,in,in_len);
218
219/*
220 * Step 6a: compress from `in' to `out' with LZO1X-999
221 */
222#ifdef USE_LZO1X
223    for (lazy = 0; lazy <= max_try_lazy; lazy++)
224    {
225        out_len = out_bufsize;
226        r = lzo1x_999_compress_internal(in,in_len,out,&out_len,wrkmem,
227                                        NULL, 0, 0,
228                                        lazy, big, big, big, big, flags);
229        if (r != LZO_E_OK)
230        {
231            /* this should NEVER happen */
232            printf("internal error - compression failed: %d\n", r);
233            exit(1);
234        }
235        printf("LZO1X-999: lazy =%2d: %8lu -> %8lu\n",
236                lazy, (unsigned long) in_len, (unsigned long) out_len);
237        if (out_len < best_len)
238        {
239            best_len = out_len;
240            best_lazy = lazy;
241            best_compress = 1;      /* LZO1X-999 */
242        }
243    }
244#endif /* USE_LZO1X */
245
246/*
247 * Step 6b: compress from `in' to `out' with LZO1Y-999
248 */
249#ifdef USE_LZO1Y
250    for (lazy = 0; lazy <= max_try_lazy; lazy++)
251    {
252        out_len = out_bufsize;
253        r = lzo1y_999_compress_internal(in,in_len,out,&out_len,wrkmem,
254                                        NULL, 0, 0,
255                                        lazy, big, big, big, big, flags);
256        if (r != LZO_E_OK)
257        {
258            /* this should NEVER happen */
259            printf("internal error - compression failed: %d\n", r);
260            exit(1);
261        }
262        printf("LZO1Y-999: lazy =%2d: %8lu -> %8lu\n",
263                lazy, (unsigned long) in_len, (unsigned long) out_len);
264        if (out_len < best_len)
265        {
266            best_len = out_len;
267            best_lazy = lazy;
268            best_compress = 2;      /* LZO1Y-999 */
269        }
270    }
271#endif /* USE_LZO1Y */
272
273/*
274 * Step 7: check if compressible
275 */
276    if (best_len >= in_len)
277    {
278        printf("This file contains incompressible data.\n");
279        return 0;
280    }
281
282/*
283 * Step 8: compress data again using the best compressor found
284 */
285    out_len = out_bufsize;
286    if (best_compress == 1)
287        r = lzo1x_999_compress_internal(in,in_len,out,&out_len,wrkmem,
288                                        NULL, 0, 0,
289                                        best_lazy, big, big, big, big, flags);
290    else if (best_compress == 2)
291        r = lzo1y_999_compress_internal(in,in_len,out,&out_len,wrkmem,
292                                        NULL, 0, 0,
293                                        best_lazy, big, big, big, big, flags);
294    else
295        r = -100;
296    assert(r == LZO_E_OK);
297    assert(out_len == best_len);
298
299/*
300 * Step 9: optimize compressed data (compressed data is in `out' buffer)
301 */
302#if 1
303    /* Optimization does not require any data in the buffer that will
304     * hold the uncompressed data. To prove this, we clear the buffer.
305     */
306    lzo_memset(in,0,in_len);
307#endif
308
309    orig_len = in_len;
310    r = -100;
311#ifdef USE_LZO1X
312    if (best_compress == 1)
313        r = lzo1x_optimize(out,out_len,in,&orig_len,NULL);
314#endif
315#ifdef USE_LZO1Y
316    if (best_compress == 2)
317        r = lzo1y_optimize(out,out_len,in,&orig_len,NULL);
318#endif
319    if (r != LZO_E_OK || orig_len != in_len)
320    {
321        /* this should NEVER happen */
322        printf("internal error - optimization failed: %d\n", r);
323        exit(1);
324    }
325
326/*
327 * Step 10: compute a checksum of the compressed data
328 */
329    compressed_checksum = lzo_adler32(0,NULL,0);
330    compressed_checksum = lzo_adler32(compressed_checksum,out,out_len);
331
332/*
333 * Step 11: write compressed data to a file
334 */
335    printf("%s: %s: %ld -> %ld, checksum 0x%08lx 0x%08lx\n",
336            progname, in_name, (long) in_len, (long) out_len,
337            (long) uncompressed_checksum, (long) compressed_checksum);
338
339    if (out_name && out_name[0])
340    {
341        printf("%s: writing to file %s\n", progname, out_name);
342        f = fopen(out_name,"wb");
343        if (f == NULL)
344        {
345            printf("%s: cannot open output file %s\n", progname, out_name);
346            exit(1);
347        }
348        if (lzo_fwrite(f,out,out_len) != out_len || fclose(f) != 0)
349        {
350            printf("%s: write error !!\n", progname);
351            exit(1);
352        }
353    }
354
355/*
356 * Step 12: verify decompression
357 */
358#ifdef PARANOID
359    lzo_memset(in,0,in_len);    /* paranoia - clear output buffer */
360    orig_len = in_len;
361    r = -100;
362#ifdef USE_LZO1X
363    if (best_compress == 1)
364        r = lzo1x_decompress_safe(out,out_len,in,&orig_len,NULL);
365#endif
366#ifdef USE_LZO1Y
367    if (best_compress == 2)
368        r = lzo1y_decompress_safe(out,out_len,in,&orig_len,NULL);
369#endif
370    if (r != LZO_E_OK || orig_len != in_len)
371    {
372        /* this should NEVER happen */
373        printf("internal error - decompression failed: %d\n", r);
374        exit(1);
375    }
376    if (uncompressed_checksum != lzo_adler32(lzo_adler32(0,NULL,0),in,in_len))
377    {
378        /* this should NEVER happen */
379        printf("internal error - decompression data error\n");
380        exit(1);
381    }
382    /* Now you could also verify decompression under similar conditions as in
383     * your application, e.g. overlapping assembler decompression etc.
384     */
385#endif
386
387    lzo_free(in);
388    lzo_free(out);
389    lzo_free(wrkmem);
390
391    return 0;
392}
393
394/*
395vi:ts=4:et
396*/
397
398