Merge branch 'master' into core32
[profile/ivi/syslinux.git] / lzo / prepcore.c
1 /* 
2    This file is based in part on:
3
4    precomp2.c -- example program: how to generate pre-compressed data
5
6    This file is part of the LZO real-time data compression library.
7
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 #include "lzo/lzoconf.h"
44 #include "lzo/lzo1x.h"
45
46 LZO_EXTERN(int)
47 lzo1x_999_compress_internal ( const lzo_bytep in , lzo_uint  in_len,
48                                     lzo_bytep out, lzo_uintp out_len,
49                                     lzo_voidp wrkmem,
50                               const lzo_bytep dict, lzo_uint dict_len,
51                                     lzo_callback_p cb,
52                                     int try_lazy,
53                                     lzo_uint good_length,
54                                     lzo_uint max_lazy,
55                                     lzo_uint nice_length,
56                                     lzo_uint max_chain,
57                                     lzo_uint32 flags );
58
59 LZO_EXTERN(int)
60 lzo1y_999_compress_internal ( const lzo_bytep in , lzo_uint  in_len,
61                                     lzo_bytep out, lzo_uintp out_len,
62                                     lzo_voidp wrkmem,
63                               const lzo_bytep dict, lzo_uint dict_len,
64                                     lzo_callback_p cb,
65                                     int try_lazy,
66                                     lzo_uint good_length,
67                                     lzo_uint max_lazy,
68                                     lzo_uint nice_length,
69                                     lzo_uint max_chain,
70                                     lzo_uint32 flags );
71
72 #define USE_LZO1X 1
73 #undef  USE_LZO1Y
74
75 #define PARANOID 1
76
77 #include <assert.h>
78 #include <inttypes.h>
79 #include <stddef.h>
80 #include <stdlib.h>
81 #include <stdio.h>
82 #include <string.h>
83 #include <ctype.h>
84 #include <time.h>
85
86 struct prefix {
87     uint32_t pfx_start;
88     uint32_t pfx_compressed;
89     uint32_t pfx_cdatalen;
90     uint32_t pfx_checksum;
91 };
92
93 static inline uint32_t get_32(const uint32_t *p)
94 {
95 #if defined(__i386__) || defined(__x86_64__)
96   /* Littleendian and unaligned-capable */
97   return *p;
98 #else
99   const uint8_t *pp = (const uint8_t *)p;
100   return (uint32_t)pp[0] + ((uint32_t)pp[1] << 8) +
101     ((uint32_t)pp[2] << 16) + ((uint32_t)pp[3] << 24);
102 #endif
103 }
104
105 static inline void set_32(uint32_t *p, uint32_t v)
106 {
107 #if defined(__i386__) || defined(__x86_64__)
108   /* Littleendian and unaligned-capable */
109   *(uint32_t *)p = v;
110 #else
111   uint8_t *pp = (uint8_t *)p;
112   pp[0] = (v & 0xff);
113   pp[1] = ((v >> 8) & 0xff);
114   pp[2] = ((v >> 16) & 0xff);
115   pp[3] = ((v >> 24) & 0xff);
116 #endif
117 }
118
119 /*************************************************************************
120 //
121 **************************************************************************/
122
123 int __lzo_cdecl_main main(int argc, char *argv[])
124 {
125     int r;
126     int lazy;
127     const int max_try_lazy = 5;
128     const lzo_uint big = 65536L;    /* can result in very slow compression */
129     const lzo_uint32 flags = 0x1;
130
131     lzo_bytep in;
132     lzo_bytep infile;
133     lzo_uint in_len, infile_len, start, offset, soff;
134
135     lzo_bytep out;
136     lzo_uint out_bufsize;
137     lzo_uint out_len = 0;
138     lzo_uint outfile_len;
139
140     lzo_bytep wrkmem;
141     lzo_uint wrk_len;
142
143     lzo_uint best_len;
144     int best_compress = -1;
145     int best_lazy = -1;
146
147     lzo_uint orig_len;
148     lzo_uint32 uncompressed_checksum;
149     lzo_uint32 compressed_checksum;
150
151     FILE *f;
152     const char *progname = NULL;
153     const char *in_name = NULL;
154     const char *out_name = NULL;
155     long l;
156
157     struct prefix *prefix;
158
159     progname = argv[0];
160     if (argc != 3)
161     {
162         printf("usage: %s file output-file\n", progname);
163         exit(1);
164     }
165     in_name = argv[1];
166     if (argc > 2)
167         out_name = argv[2];
168
169 /*
170  * Step 1: initialize the LZO library
171  */
172     if (lzo_init() != LZO_E_OK)
173     {
174         printf("internal error - lzo_init() failed !!!\n");
175         printf("(this usually indicates a compiler bug - try recompiling\nwithout optimizations, and enable `-DLZO_DEBUG' for diagnostics)\n");
176         exit(1);
177     }
178
179 /*
180  * Step 2: allocate the work-memory
181  */
182     wrk_len = 1;
183 #ifdef USE_LZO1X
184     if (wrk_len < LZO1X_999_MEM_COMPRESS)
185         wrk_len = LZO1X_999_MEM_COMPRESS;
186 #endif
187 #ifdef USE_LZO1Y
188     if (wrk_len < LZO1Y_999_MEM_COMPRESS)
189         wrk_len = LZO1Y_999_MEM_COMPRESS;
190 #endif
191     wrkmem = (lzo_bytep) malloc(wrk_len);
192     if (wrkmem == NULL)
193     {
194         printf("%s: out of memory\n", progname);
195         exit(1);
196     }
197
198 /*
199  * Step 3: open the input file
200  */
201     f = fopen(in_name,"rb");
202     if (f == NULL)
203     {
204         printf("%s: cannot open file %s\n", progname, in_name);
205         exit(1);
206     }
207     fseek(f,0,SEEK_END);
208     l = ftell(f);
209     fseek(f,0,SEEK_SET);
210     if (l <= 0)
211     {
212         printf("%s: %s: empty file\n", progname, in_name);
213         fclose(f);
214         exit(1);
215     }
216     infile_len = (lzo_uint) l;
217     out_bufsize = infile_len + infile_len / 16 + 64 + 3 + 2048;
218
219 /*
220  * Step 4: allocate compression buffers and read the file
221  */
222     infile = (lzo_bytep) malloc(infile_len);
223     out = (lzo_bytep) malloc(out_bufsize);
224     if (infile == NULL || out == NULL)
225     {
226         printf("%s: out of memory\n", progname);
227         exit(1);
228     }
229     infile_len = (lzo_uint) fread(infile,1,infile_len,f);
230     fclose(f);
231
232 /*
233  * Select the portion which is for compression...
234  */
235     prefix = (struct prefix *)infile;
236     start  = get_32(&prefix->pfx_start);
237     offset = get_32(&prefix->pfx_compressed);
238     in = infile + offset;
239     in_len = infile_len - offset;
240     best_len = in_len;
241
242 /*
243  * Step 5: compute a checksum of the uncompressed data
244  */
245     uncompressed_checksum = lzo_adler32(0,NULL,0);
246     uncompressed_checksum = lzo_adler32(uncompressed_checksum,in,in_len);
247
248 /*
249  * Step 6a: compress from `in' to `out' with LZO1X-999
250  */
251 #ifdef USE_LZO1X
252     for (lazy = 0; lazy <= max_try_lazy; lazy++)
253     {
254         out_len = out_bufsize;
255         r = lzo1x_999_compress_internal(in,in_len,out,&out_len,wrkmem,
256                                         NULL, 0, 0,
257                                         lazy, big, big, big, big, flags);
258         if (r != LZO_E_OK)
259         {
260             /* this should NEVER happen */
261             printf("internal error - compression failed: %d\n", r);
262             exit(1);
263         }
264         if (out_len < best_len)
265         {
266             best_len = out_len;
267             best_lazy = lazy;
268             best_compress = 1;      /* LZO1X-999 */
269         }
270     }
271 #endif /* USE_LZO1X */
272
273 /*
274  * Step 6b: compress from `in' to `out' with LZO1Y-999
275  */
276 #ifdef USE_LZO1Y
277     for (lazy = 0; lazy <= max_try_lazy; lazy++)
278     {
279         out_len = out_bufsize;
280         r = lzo1y_999_compress_internal(in,in_len,out,&out_len,wrkmem,
281                                         NULL, 0, 0,
282                                         lazy, big, big, big, big, flags);
283         if (r != LZO_E_OK)
284         {
285             /* this should NEVER happen */
286             printf("internal error - compression failed: %d\n", r);
287             exit(1);
288         }
289         if (out_len < best_len)
290         {
291             best_len = out_len;
292             best_lazy = lazy;
293             best_compress = 2;      /* LZO1Y-999 */
294         }
295     }
296 #endif /* USE_LZO1Y */
297
298 /*
299  * Step 7: check if compressible
300  */
301     if (best_len >= in_len)
302     {
303         printf("This file contains incompressible data.\n");
304         /* return 0;  -- Sucks to be us -hpa ... */
305     }
306
307 /*
308  * Step 8: compress data again using the best compressor found
309  */
310     out_len = out_bufsize;
311     if (best_compress == 1)
312         r = lzo1x_999_compress_internal(in,in_len,out,&out_len,wrkmem,
313                                         NULL, 0, 0,
314                                         best_lazy, big, big, big, big, flags);
315     else if (best_compress == 2)
316         r = lzo1y_999_compress_internal(in,in_len,out,&out_len,wrkmem,
317                                         NULL, 0, 0,
318                                         best_lazy, big, big, big, big, flags);
319     else
320         r = -100;
321     assert(r == LZO_E_OK);
322     assert(out_len == best_len);
323
324 /*
325  * Step 9: optimize compressed data (compressed data is in `out' buffer)
326  */
327 #if 1
328     /* Optimization does not require any data in the buffer that will
329      * hold the uncompressed data. To prove this, we clear the buffer.
330      */
331     lzo_memset(in,0,in_len);
332 #endif
333
334     orig_len = in_len;
335     r = -100;
336 #ifdef USE_LZO1X
337     if (best_compress == 1)
338         r = lzo1x_optimize(out,out_len,in,&orig_len,NULL);
339 #endif
340 #ifdef USE_LZO1Y
341     if (best_compress == 2)
342         r = lzo1y_optimize(out,out_len,in,&orig_len,NULL);
343 #endif
344     if (r != LZO_E_OK || orig_len != in_len)
345     {
346         /* this should NEVER happen */
347         printf("internal error - optimization failed: %d\n", r);
348         exit(1);
349     }
350
351 /*
352  * Step 10: compute a checksum of the compressed data
353  */
354     compressed_checksum = lzo_adler32(0,NULL,0);
355     compressed_checksum = lzo_adler32(compressed_checksum,out,out_len);
356
357 /*
358  * Step 11: write compressed data to a file
359  */
360     /* Make sure we have up to 2048 bytes of zero after the output */
361     memset(out+out_len, 0, 2048);
362
363     outfile_len = out_len;
364
365     soff = get_32(&prefix->pfx_cdatalen);
366     set_32((uint32_t *)(infile+soff), out_len);
367
368     soff = get_32(&prefix->pfx_checksum);
369     if (soff) {
370         /* ISOLINUX padding and checksumming */
371         uint32_t csum = 0;
372         unsigned int ptr;
373         outfile_len = ((offset+out_len+2047) & ~2047) - offset;
374         for (ptr = 64; ptr < offset; ptr += 4)
375             csum += get_32((uint32_t *)(infile+ptr));
376         for (ptr = 0; ptr < outfile_len; ptr += 4)
377             csum += get_32((uint32_t *)(out+ptr));
378
379         set_32((uint32_t *)(infile+soff), offset-start+outfile_len);
380         set_32((uint32_t *)(infile+soff+4), csum);
381     }
382
383     f = fopen(out_name,"wb");
384     if (f == NULL)
385     {
386         printf("%s: cannot open output file %s\n", progname, out_name);
387         exit(1);
388     }
389     if (fwrite(infile+start,1,offset-start,f) != offset-start ||
390         fwrite(out,1,outfile_len,f) != outfile_len ||
391         fclose(f))
392     {
393         printf("%s: write error !!\n", progname);
394         exit(1);
395     }
396
397 /*
398  * Step 12: verify decompression
399  */
400 #ifdef PARANOID
401     lzo_memset(in,0,in_len);    /* paranoia - clear output buffer */
402     orig_len = in_len;
403     r = -100;
404 #ifdef USE_LZO1X
405     if (best_compress == 1)
406         r = lzo1x_decompress_safe(out,out_len,in,&orig_len,NULL);
407 #endif
408 #ifdef USE_LZO1Y
409     if (best_compress == 2)
410         r = lzo1y_decompress_safe(out,out_len,in,&orig_len,NULL);
411 #endif
412     if (r != LZO_E_OK || orig_len != in_len)
413     {
414         /* this should NEVER happen */
415         printf("internal error - decompression failed: %d\n", r);
416         exit(1);
417     }
418     if (uncompressed_checksum != lzo_adler32(lzo_adler32(0,NULL,0),in,in_len))
419     {
420         /* this should NEVER happen */
421         printf("internal error - decompression data error\n");
422         exit(1);
423     }
424     /* Now you could also verify decompression under similar conditions as in
425      * your application, e.g. overlapping assembler decompression etc.
426      */
427 #endif
428
429     free(infile);
430     free(out);
431     free(wrkmem);
432
433     return 0;
434 }
435
436 /*
437 vi:ts=4:et
438 */
439