Run Nindent on lzo/prepcore.c
[profile/ivi/syslinux.git] / lzo / prepcore.c
1 /* ----------------------------------------------------------------------- *
2  *   
3  *   Copyright 2009 Intel Corporation; author: H. Peter Anvin
4  *
5  *   This program is free software; you can redistribute it and/or modify
6  *   it under the terms of the GNU General Public License as published by
7  *   the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
8  *   Boston MA 02110-1301, USA; either version 2 of the License, or
9  *   (at your option) any later version; incorporated herein by reference.
10  *
11  * ----------------------------------------------------------------------- */
12
13 /* 
14    This file is based in part on:
15
16    precomp2.c -- example program: how to generate pre-compressed data
17
18    This file is part of the LZO real-time data compression library.
19
20    Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
21    Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
22    Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
23    Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
24    Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
25    Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
26    Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
27    Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
28    Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
29    Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
30    Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
31    Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
32    Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
33    All Rights Reserved.
34
35    The LZO library is free software; you can redistribute it and/or
36    modify it under the terms of the GNU General Public License as
37    published by the Free Software Foundation; either version 2 of
38    the License, or (at your option) any later version.
39
40    The LZO library is distributed in the hope that it will be useful,
41    but WITHOUT ANY WARRANTY; without even the implied warranty of
42    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
43    GNU General Public License for more details.
44
45    You should have received a copy of the GNU General Public License
46    along with the LZO library; see the file COPYING.
47    If not, write to the Free Software Foundation, Inc.,
48    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
49
50    Markus F.X.J. Oberhumer
51    <markus@oberhumer.com>
52    http://www.oberhumer.com/opensource/lzo/
53  */
54
55 #include "lzo/lzoconf.h"
56 #include "lzo/lzo1x.h"
57
58 LZO_EXTERN(int)
59 lzo1x_999_compress_internal(const lzo_bytep in, lzo_uint in_len,
60                             lzo_bytep out, lzo_uintp out_len,
61                             lzo_voidp wrkmem,
62                             const lzo_bytep dict, lzo_uint dict_len,
63                             lzo_callback_p cb,
64                             int try_lazy,
65                             lzo_uint good_length,
66                             lzo_uint max_lazy,
67                             lzo_uint nice_length,
68                             lzo_uint max_chain, lzo_uint32 flags);
69
70 LZO_EXTERN(int)
71 lzo1y_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, lzo_uint32 flags);
81
82 #define PARANOID 1
83
84 #include <assert.h>
85 #include <inttypes.h>
86 #include <stddef.h>
87 #include <stdlib.h>
88 #include <stdio.h>
89 #include <string.h>
90 #include <ctype.h>
91 #include <time.h>
92
93 struct prefix {
94     uint32_t pfx_start;
95     uint32_t pfx_compressed;
96     uint32_t pfx_cdatalen;
97     uint32_t pfx_checksum;
98 };
99
100 static inline uint32_t get_32(const uint32_t * p)
101 {
102 #if defined(__i386__) || defined(__x86_64__)
103     /* Littleendian and unaligned-capable */
104     return *p;
105 #else
106     const uint8_t *pp = (const uint8_t *)p;
107     return (uint32_t) pp[0] + ((uint32_t) pp[1] << 8) +
108         ((uint32_t) pp[2] << 16) + ((uint32_t) pp[3] << 24);
109 #endif
110 }
111
112 static inline void set_32(uint32_t * p, uint32_t v)
113 {
114 #if defined(__i386__) || defined(__x86_64__)
115     /* Littleendian and unaligned-capable */
116     *p = v;
117 #else
118     uint8_t *pp = (uint8_t *) p;
119     pp[0] = (v & 0xff);
120     pp[1] = ((v >> 8) & 0xff);
121     pp[2] = ((v >> 16) & 0xff);
122     pp[3] = ((v >> 24) & 0xff);
123 #endif
124 }
125
126 /*************************************************************************
127 //
128 **************************************************************************/
129
130 int __lzo_cdecl_main main(int argc, char *argv[])
131 {
132     int r;
133     int lazy;
134     const int max_try_lazy = 5;
135     const lzo_uint big = 65536L;        /* can result in very slow compression */
136     const lzo_uint32 flags = 0x1;
137
138     lzo_bytep in;
139     lzo_bytep infile;
140     lzo_uint in_len, infile_len, start, offset, soff;
141
142     lzo_bytep out;
143     lzo_uint out_bufsize;
144     lzo_uint out_len = 0;
145     lzo_uint outfile_len;
146
147     lzo_byte wrkmem[LZO1X_999_MEM_COMPRESS];
148
149     lzo_uint best_len;
150     int best_lazy = -1;
151
152     lzo_uint orig_len;
153     lzo_uint32 uncompressed_checksum;
154     lzo_uint32 compressed_checksum;
155
156     FILE *f;
157     const char *progname = NULL;
158     const char *in_name = NULL;
159     const char *out_name = NULL;
160     long l;
161
162     struct prefix *prefix;
163
164     progname = argv[0];
165     if (argc != 3) {
166         printf("usage: %s file output-file\n", progname);
167         exit(1);
168     }
169     in_name = argv[1];
170     if (argc > 2)
171         out_name = argv[2];
172
173 /*
174  * Step 1: initialize the LZO library
175  */
176     if (lzo_init() != LZO_E_OK) {
177         printf("internal error - lzo_init() failed !!!\n");
178         printf
179             ("(this usually indicates a compiler bug - try recompiling\nwithout optimizations, and enable `-DLZO_DEBUG' for diagnostics)\n");
180         exit(1);
181     }
182
183 /*
184  * Step 3: open the input file
185  */
186     f = fopen(in_name, "rb");
187     if (f == NULL) {
188         printf("%s: cannot open file %s\n", progname, in_name);
189         exit(1);
190     }
191     fseek(f, 0, SEEK_END);
192     l = ftell(f);
193     fseek(f, 0, SEEK_SET);
194     if (l <= 0) {
195         printf("%s: %s: empty file\n", progname, in_name);
196         fclose(f);
197         exit(1);
198     }
199     infile_len = (lzo_uint) l;
200     out_bufsize = infile_len + infile_len / 16 + 64 + 3 + 2048;
201
202 /*
203  * Step 4: allocate compression buffers and read the file
204  */
205     infile = (lzo_bytep) malloc(infile_len);
206     out = (lzo_bytep) malloc(out_bufsize);
207     if (infile == NULL || out == NULL) {
208         printf("%s: out of memory\n", progname);
209         exit(1);
210     }
211     infile_len = (lzo_uint) fread(infile, 1, infile_len, f);
212     fclose(f);
213
214 /*
215  * Select the portion which is for compression...
216  */
217     prefix = (struct prefix *)infile;
218     start = get_32(&prefix->pfx_start);
219     offset = get_32(&prefix->pfx_compressed);
220     in = infile + offset;
221     in_len = infile_len - offset;
222     best_len = in_len;
223
224 /*
225  * Step 5: compute a checksum of the uncompressed data
226  */
227     uncompressed_checksum = lzo_adler32(0, NULL, 0);
228     uncompressed_checksum = lzo_adler32(uncompressed_checksum, in, in_len);
229
230 /*
231  * Step 6a: compress from `in' to `out' with LZO1X-999
232  */
233     for (lazy = 0; lazy <= max_try_lazy; lazy++) {
234         out_len = out_bufsize;
235         r = lzo1x_999_compress_internal(in, in_len, out, &out_len, wrkmem,
236                                         NULL, 0, 0,
237                                         lazy, big, big, big, big, flags);
238         if (r != LZO_E_OK) {
239             /* this should NEVER happen */
240             printf("internal error - compression failed: %d\n", r);
241             exit(1);
242         }
243         if (out_len < best_len) {
244             best_len = out_len;
245             best_lazy = lazy;
246         }
247     }
248
249 /*
250  * Step 7: check if compressible
251  */
252     if (best_len >= in_len) {
253         printf("This file contains incompressible data.\n");
254         /* return 0;  -- Sucks to be us -hpa ... */
255     }
256
257 /*
258  * Step 8: compress data again using the best compressor found
259  */
260     out_len = out_bufsize;
261     r = lzo1x_999_compress_internal(in, in_len, out, &out_len, wrkmem,
262                                     NULL, 0, 0,
263                                     best_lazy, big, big, big, big, flags);
264     assert(r == LZO_E_OK);
265     assert(out_len == best_len);
266
267 /*
268  * Step 9: optimize compressed data (compressed data is in `out' buffer)
269  */
270 #if 1
271     /* Optimization does not require any data in the buffer that will
272      * hold the uncompressed data. To prove this, we clear the buffer.
273      */
274     memset(in, 0, in_len);
275 #endif
276
277     orig_len = in_len;
278     r = lzo1x_optimize(out, out_len, in, &orig_len, NULL);
279     if (r != LZO_E_OK || orig_len != in_len) {
280         /* this should NEVER happen */
281         printf("internal error - optimization failed: %d\n", r);
282         exit(1);
283     }
284
285 /*
286  * Step 10: compute a checksum of the compressed data
287  */
288     compressed_checksum = lzo_adler32(0, NULL, 0);
289     compressed_checksum = lzo_adler32(compressed_checksum, out, out_len);
290
291 /*
292  * Step 11: write compressed data to a file
293  */
294     /* Make sure we have up to 2048 bytes of zero after the output */
295     memset(out + out_len, 0, 2048);
296
297     outfile_len = out_len;
298
299     soff = get_32(&prefix->pfx_cdatalen);
300     set_32((uint32_t *) (infile + soff), out_len);
301
302     soff = get_32(&prefix->pfx_checksum);
303     if (soff) {
304         /* ISOLINUX padding and checksumming */
305         uint32_t csum = 0;
306         unsigned int ptr;
307         outfile_len =
308             ((offset - start + out_len + 2047) & ~2047) - (offset - start);
309         for (ptr = 64; ptr < offset; ptr += 4)
310             csum += get_32((uint32_t *) (infile + ptr));
311         for (ptr = 0; ptr < outfile_len; ptr += 4)
312             csum += get_32((uint32_t *) (out + ptr));
313
314         set_32((uint32_t *) (infile + soff), offset - start + outfile_len);
315         set_32((uint32_t *) (infile + soff + 4), csum);
316     }
317
318     f = fopen(out_name, "wb");
319     if (f == NULL) {
320         printf("%s: cannot open output file %s\n", progname, out_name);
321         exit(1);
322     }
323     if (fwrite(infile + start, 1, offset - start, f) != offset - start ||
324         fwrite(out, 1, outfile_len, f) != outfile_len || fclose(f)) {
325         printf("%s: write error !!\n", progname);
326         exit(1);
327     }
328
329 /*
330  * Step 12: verify decompression
331  */
332 #ifdef PARANOID
333     memset(in, 0, in_len);      /* paranoia - clear output buffer */
334     orig_len = in_len;
335     r = lzo1x_decompress_safe(out, out_len, in, &orig_len, NULL);
336     if (r != LZO_E_OK || orig_len != in_len) {
337         /* this should NEVER happen */
338         printf("internal error - decompression failed: %d\n", r);
339         exit(1);
340     }
341     if (uncompressed_checksum !=
342         lzo_adler32(lzo_adler32(0, NULL, 0), in, in_len)) {
343         /* this should NEVER happen */
344         printf("internal error - decompression data error\n");
345         exit(1);
346     }
347     /* Now you could also verify decompression under similar conditions as in
348      * your application, e.g. overlapping assembler decompression etc.
349      */
350 #endif
351
352     free(infile);
353     free(out);
354
355     return 0;
356 }