1/* dict.c -- example program: how to use preset dictionaries
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 use preset dictionaries.
43//
44// Please study LZO.FAQ and simple.c first.
45**************************************************************************/
46
47#include "lzo/lzoconf.h"
48#include "lzo/lzo1x.h"
49
50/* portability layer */
51#define WANT_LZO_MALLOC 1
52#define WANT_LZO_FREAD 1
53#define WANT_LZO_WILDARGV 1
54#include "examples/portab.h"
55
56
57static const char *progname = NULL;
58
59#define DICT_LEN    0xbfff
60static lzo_bytep    dict;
61static lzo_uint     dict_len = 0;
62static lzo_uint32   dict_adler32;
63
64
65/*************************************************************************
66//
67**************************************************************************/
68
69static lzo_uint total_n = 0;
70static lzo_uint total_c_len = 0;
71static lzo_uint total_d_len = 0;
72
73static void print_file ( const char *name, lzo_uint d_len, lzo_uint c_len )
74{
75    double perc;
76
77    perc = (d_len > 0) ? c_len * 100.0 / d_len : 0;
78    printf("  |  %-30s   %9ld -> %9ld   %7.2f%%  |\n",
79            name, (long) d_len, (long) c_len, perc);
80
81    total_n++;
82    total_c_len += c_len;
83    total_d_len += d_len;
84}
85
86
87/*************************************************************************
88//
89**************************************************************************/
90
91int do_file ( const char *in_name, int level )
92{
93    int r;
94    lzo_bytep in;
95    lzo_bytep out;
96    lzo_bytep newb;
97    lzo_bytep wrkmem;
98    lzo_uint in_len;
99    lzo_uint out_len;
100    lzo_uint new_len;
101    long l;
102    FILE *f;
103
104/*
105 * Step 1: open the input file
106 */
107    f = fopen(in_name,"rb");
108    if (f == 0)
109    {
110        printf("%s: cannot open file %s\n", progname, in_name);
111        return 0;   /* no error */
112    }
113    fseek(f,0,SEEK_END);
114    l = ftell(f);
115    fseek(f,0,SEEK_SET);
116    if (l <= 0)
117    {
118        printf("%s: %s: empty file -- skipping\n", progname, in_name);
119        fclose(f);
120        return 0;
121    }
122    in_len = (lzo_uint) l;
123
124/*
125 * Step 2: allocate compression buffers and read the file
126 */
127    in = (lzo_bytep) lzo_malloc(in_len);
128    out = (lzo_bytep) lzo_malloc(in_len + in_len / 16 + 64 + 3);
129    newb = (lzo_bytep) lzo_malloc(in_len);
130    wrkmem = (lzo_bytep) lzo_malloc(LZO1X_999_MEM_COMPRESS);
131    if (in == NULL || out == NULL || newb == NULL || wrkmem == NULL)
132    {
133        printf("%s: out of memory\n", progname);
134        exit(1);
135    }
136    in_len = (lzo_uint) lzo_fread(f,in,in_len);
137    fclose(f);
138
139/*
140 * Step 3: compress from `in' to `out' with LZO1X-999
141 */
142    r = lzo1x_999_compress_level(in,in_len,out,&out_len,wrkmem,
143                                 dict, dict_len, 0, level);
144    if (r != LZO_E_OK)
145    {
146        /* this should NEVER happen */
147        printf("internal error - compression failed: %d\n", r);
148        return 1;
149    }
150
151    print_file(in_name,in_len,out_len);
152
153/*
154 * Step 4: decompress again, now going from `out' to `newb'
155 */
156    new_len = in_len;
157    r = lzo1x_decompress_dict_safe(out,out_len,newb,&new_len,NULL,dict,dict_len);
158    if (r != LZO_E_OK)
159    {
160        /* this should NEVER happen */
161        printf("internal error - decompression failed: %d\n", r);
162        return 1;
163    }
164
165/*
166 * Step 5: verify decompression
167 */
168    if (new_len != in_len || lzo_memcmp(in,newb,in_len) != 0)
169    {
170        /* this should NEVER happen */
171        printf("internal error - decompression data error\n");
172        return 1;
173    }
174
175    /* free buffers in reverse order to help malloc() */
176    lzo_free(wrkmem);
177    lzo_free(newb);
178    lzo_free(out);
179    lzo_free(in);
180    return 0;
181}
182
183
184/*************************************************************************
185//
186**************************************************************************/
187
188int __lzo_cdecl_main main(int argc, char *argv[])
189{
190    int i = 1;
191    int r;
192    const char *dict_name;
193    FILE *f;
194    time_t t_total;
195    int level = 7;
196
197    lzo_wildargv(&argc, &argv);
198
199    printf("\nLZO real-time data compression library (v%s, %s).\n",
200           lzo_version_string(), lzo_version_date());
201    printf("Copyright (C) 1996-2008 Markus Franz Xaver Johannes Oberhumer\nAll Rights Reserved.\n\n");
202
203    progname = argv[0];
204
205    if (i < argc && argv[i][0] == '-' && isdigit(argv[i][1]))
206        level = atoi(&argv[i++][1]);
207
208    if (i + 1 >= argc || level < 1 || level > 9)
209    {
210        printf("usage: %s [-level] [ dictionary-file | -n ]  file...\n", progname);
211        exit(1);
212    }
213    printf("Compression level is LZO1X-999/%d\n", level);
214
215/*
216 * Step 1: initialize the LZO library
217 */
218    if (lzo_init() != LZO_E_OK)
219    {
220        printf("internal error - lzo_init() failed !!!\n");
221        printf("(this usually indicates a compiler bug - try recompiling\nwithout optimizations, and enable `-DLZO_DEBUG' for diagnostics)\n");
222        exit(1);
223    }
224
225/*
226 * Step 2: prepare the dictionary
227 */
228    dict = (lzo_bytep) lzo_malloc(DICT_LEN);
229    if (dict == NULL)
230    {
231        printf("%s: out of memory\n", progname);
232        exit(1);
233    }
234    dict_name = argv[i++];
235    if (strcmp(dict_name,"-n") == 0)
236    {
237        dict_name = "empty";
238        dict_len = 0;
239    }
240    else
241    {
242        f = fopen(dict_name,"rb");
243        if (!f)
244        {
245            printf("%s: cannot open dictionary file %s\n", progname, dict_name);
246            exit(1);
247        }
248        dict_len = (lzo_uint) lzo_fread(f,dict,DICT_LEN);
249        fclose(f);
250    }
251
252    dict_adler32 = lzo_adler32(0,NULL,0);
253    dict_adler32 = lzo_adler32(dict_adler32,dict,dict_len);
254    printf("Using dictionary '%s', %ld bytes, ID 0x%08lx.\n",
255            dict_name, (long) dict_len, (long) dict_adler32);
256
257/*
258 * Step 3: process files
259 */
260    t_total = time(NULL);
261    for (r = 0; r == 0 && i < argc; i++)
262        r = do_file(argv[i], level);
263    t_total = time(NULL) - t_total;
264
265    lzo_free(dict);
266
267    if (total_n > 1)
268        print_file("***TOTALS***",total_d_len,total_c_len);
269
270    printf("Dictionary compression test %s, execution time %lu seconds.\n",
271            r == 0 ? "passed" : "FAILED", (unsigned long) t_total);
272    return r;
273}
274
275/*
276vi:ts=4:et
277*/
278
279