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