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