1 /* lzotest.c -- very comprehensive test driver for the LZO library
3 This file is part of the LZO real-time data compression library.
5 Copyright (C) 1996-2017 Markus Franz Xaver Johannes Oberhumer
8 The LZO library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 2 of
11 the License, or (at your option) any later version.
13 The LZO library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with the LZO library; see the file COPYING.
20 If not, write to the Free Software Foundation, Inc.,
21 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23 Markus F.X.J. Oberhumer
24 <markus@oberhumer.com>
25 http://www.oberhumer.com/opensource/lzo/
29 #include <lzo/lzoconf.h>
32 /*************************************************************************
34 **************************************************************************/
36 /* portability layer */
37 #define WANT_LZO_MALLOC 1
38 #define WANT_LZO_FREAD 1
39 #define WANT_LZO_WILDARGV 1
40 #define WANT_LZO_PCLOCK 1
41 #define LZO_WANT_ACCLIB_GETOPT 1
42 #include "examples/portab.h"
44 #if defined(HAVE_STRNICMP) && !defined(HAVE_STRNCASECMP)
45 # define strncasecmp(a,b,c) strnicmp(a,b,c)
46 # define HAVE_STRNCASECMP 1
50 # define is_digit(x) (isdigit((unsigned char)(x)))
51 # define is_space(x) (isspace((unsigned char)(x)))
53 # define is_digit(x) ((unsigned)(x) - '0' <= 9)
54 # define is_space(x) ((x)==' ' || (x)=='\t' || (x)=='\r' || (x)=='\n')
58 /*************************************************************************
59 // compression include section
60 **************************************************************************/
63 #define HAVE_LZO1A_H 1
64 #define HAVE_LZO1B_H 1
65 #define HAVE_LZO1C_H 1
66 #define HAVE_LZO1F_H 1
67 #define HAVE_LZO1X_H 1
68 #define HAVE_LZO1Y_H 1
69 #define HAVE_LZO1Z_H 1
70 #define HAVE_LZO2A_H 1
72 #if defined(NO_ZLIB_H) || (SIZEOF_INT < 4)
75 #if defined(NO_BZLIB_H) || (SIZEOF_INT != 4)
79 #if 0 && defined(LZO_OS_DOS16)
80 /* don't make this test program too big */
92 #if defined(HAVE_LZO1_H)
93 # include <lzo/lzo1.h>
95 #if defined(HAVE_LZO1A_H)
96 # include <lzo/lzo1a.h>
98 #if defined(HAVE_LZO1B_H)
99 # include <lzo/lzo1b.h>
101 #if defined(HAVE_LZO1C_H)
102 # include <lzo/lzo1c.h>
104 #if defined(HAVE_LZO1F_H)
105 # include <lzo/lzo1f.h>
107 #if defined(HAVE_LZO1X_H)
108 # include <lzo/lzo1x.h>
110 #if defined(HAVE_LZO1Y_H)
111 # include <lzo/lzo1y.h>
113 #if defined(HAVE_LZO1Z_H)
114 # include <lzo/lzo1z.h>
116 #if defined(HAVE_LZO2A_H)
117 # include <lzo/lzo2a.h>
119 #if defined(HAVE_LZO2B_H)
120 # include <lzo/lzo2b.h>
122 /* other compressors */
123 #if defined(HAVE_ZLIB_H)
127 #if defined(HAVE_BZLIB_H)
133 /*************************************************************************
134 // enumerate all methods
135 **************************************************************************/
138 /* compression algorithms */
140 M_LZO1B_2, M_LZO1B_3, M_LZO1B_4, M_LZO1B_5,
141 M_LZO1B_6, M_LZO1B_7, M_LZO1B_8, M_LZO1B_9,
144 M_LZO1C_2, M_LZO1C_3, M_LZO1C_4, M_LZO1C_5,
145 M_LZO1C_6, M_LZO1C_7, M_LZO1C_8, M_LZO1C_9,
171 M_LAST_LZO_COMPRESSOR = 998,
173 /* other compressors */
174 #if defined(ALG_ZLIB)
176 M_ZLIB_8_2, M_ZLIB_8_3, M_ZLIB_8_4, M_ZLIB_8_5,
177 M_ZLIB_8_6, M_ZLIB_8_7, M_ZLIB_8_8, M_ZLIB_8_9,
179 #if defined(ALG_BZIP2)
181 M_BZIP2_2, M_BZIP2_3, M_BZIP2_4, M_BZIP2_5,
182 M_BZIP2_6, M_BZIP2_7, M_BZIP2_8, M_BZIP2_9,
185 /* dummy compressor - for benchmarking */
188 M_LAST_COMPRESSOR = 4999,
190 /* dummy algorithms - for benchmarking */
193 /* checksum algorithms - for benchmarking */
196 #if defined(ALG_ZLIB)
205 /*************************************************************************
206 // command line options
207 **************************************************************************/
211 long opt_c_loops = 0;
212 long opt_d_loops = 0;
213 const char *opt_corpus_path = NULL;
214 const char *opt_dump_compressed_data = NULL;
216 lzo_bool opt_use_safe_decompressor = 0;
217 lzo_bool opt_use_asm_decompressor = 0;
218 lzo_bool opt_use_asm_fast_decompressor = 0;
219 lzo_bool opt_optimize_compressed_data = 0;
222 lzo_uint opt_max_dict_len = LZO_UINT_MAX;
223 const char *opt_dictionary_file = NULL;
225 lzo_bool opt_read_from_stdin = 0;
227 /* set these to 1 to measure the speed impact of a checksum */
228 lzo_bool opt_compute_adler32 = 0;
229 lzo_bool opt_compute_crc32 = 0;
230 static lzo_uint32_t adler_in, adler_out;
231 static lzo_uint32_t crc_in, crc_out;
233 lzo_bool opt_execution_time = 0;
235 lzo_bool opt_clear_wrkmem = 0;
237 static const lzo_bool opt_try_to_compress_0_bytes = 1;
240 /*************************************************************************
242 **************************************************************************/
244 static const char *progname = "";
245 static lzo_pclock_handle_t pch;
247 /* for statistics and benchmark */
249 static unsigned long total_n = 0;
250 static unsigned long total_c_len = 0;
251 static unsigned long total_d_len = 0;
252 static unsigned long total_blocks = 0;
253 static double total_perc = 0.0;
254 static const char *total_method_name = NULL;
255 static unsigned total_method_names = 0;
256 /* Note: the average value of a rate (e.g. compression speed) is defined
257 * by the Harmonic Mean (and _not_ by the Arithmethic Mean ) */
258 static unsigned long total_c_mbs_n = 0;
259 static unsigned long total_d_mbs_n = 0;
260 static double total_c_mbs_harmonic = 0.0;
261 static double total_d_mbs_harmonic = 0.0;
262 static double total_c_mbs_sum = 0.0;
263 static double total_d_mbs_sum = 0.0;
266 #if defined(HAVE_LZO1X_H)
267 int default_method = M_LZO1X_1;
268 #elif defined(HAVE_LZO1B_H)
269 int default_method = M_LZO1B_1;
270 #elif defined(HAVE_LZO1C_H)
271 int default_method = M_LZO1C_1;
272 #elif defined(HAVE_LZO1F_H)
273 int default_method = M_LZO1F_1;
274 #elif defined(HAVE_LZO1Y_H)
275 int default_method = M_LZO1Y_1;
277 int default_method = M_MEMCPY;
281 static const int benchmark_methods[] = {
282 M_LZO1B_1, M_LZO1B_9,
283 M_LZO1C_1, M_LZO1C_9,
289 static const int x1_methods[] = {
290 M_LZO1, M_LZO1A, M_LZO1B_1, M_LZO1C_1, M_LZO1F_1, M_LZO1X_1, M_LZO1Y_1,
294 static const int x99_methods[] = {
295 M_LZO1_99, M_LZO1A_99, M_LZO1B_99, M_LZO1C_99,
299 static const int x999_methods[] = {
300 M_LZO1B_999, M_LZO1C_999, M_LZO1F_999, M_LZO1X_999, M_LZO1Y_999,
307 /* exit codes of this test program */
313 #define EXIT_LZO_ERROR 5
314 #define EXIT_LZO_INIT 6
315 #define EXIT_INTERNAL 7
318 /*************************************************************************
320 **************************************************************************/
322 static lzo_uint opt_block_size;
323 static lzo_uint opt_max_data_len;
335 static mblock_t file_data; /* original uncompressed data */
336 static mblock_t block_c; /* compressed data */
337 static mblock_t block_d; /* decompressed data */
338 static mblock_t block_w; /* wrkmem */
339 static mblock_t dict;
342 static void mb_alloc_extra(mblock_t *mb, lzo_uint len, lzo_uint extra_bottom, lzo_uint extra_top)
344 lzo_uint align = (lzo_uint) sizeof(lzo_align_t);
346 mb->alloc_ptr = mb->ptr = NULL;
347 mb->alloc_len = mb->len = 0;
349 mb->alloc_len = extra_bottom + len + extra_top;
350 if (mb->alloc_len == 0) mb->alloc_len = 1;
351 mb->alloc_ptr = (lzo_bytep) lzo_malloc(mb->alloc_len);
353 if (mb->alloc_ptr == NULL) {
354 fprintf(stderr, "%s: out of memory (wanted %lu bytes)\n", progname, (unsigned long)mb->alloc_len);
357 if (mb->alloc_len >= align && __lzo_align_gap(mb->alloc_ptr, align) != 0) {
358 fprintf(stderr, "%s: C library problem: malloc() returned misaligned pointer!\n", progname);
362 mb->ptr = mb->alloc_ptr + extra_bottom;
363 mb->len = mb->saved_len = len;
369 static void mb_alloc(mblock_t *mb, lzo_uint len)
371 mb_alloc_extra(mb, len, 0, 0);
375 static void mb_free(mblock_t *mb)
378 if (mb->alloc_ptr) lzo_free(mb->alloc_ptr);
379 mb->alloc_ptr = mb->ptr = NULL;
380 mb->alloc_len = mb->len = 0;
384 static lzo_uint get_max_compression_expansion(int m, lzo_uint bl)
386 if (m == M_MEMCPY || m >= M_LAST_COMPRESSOR)
388 if (m == M_LZO2A_999 || m == M_LZO2B_999)
390 if (m > 0 && m < M_LAST_LZO_COMPRESSOR)
391 return bl / 16 + 64 + 3;
395 static lzo_uint get_max_decompression_overrun(int m, lzo_uint bl)
399 /* may overwrite 3 bytes past the end of the decompressed block */
400 if (opt_use_asm_fast_decompressor)
401 return (lzo_uint) sizeof(lzo_voidp) - 1;
406 /*************************************************************************
407 // dictionary support
408 **************************************************************************/
410 static void dict_alloc(lzo_uint max_dict_len)
412 lzo_uint l = 0xbfff; /* MAX_DICT_LEN */
413 if (max_dict_len > 0 && l > max_dict_len)
419 /* this default dictionary does not provide good contexts... */
420 static void dict_set_default(void)
426 if (dict.len > dict.alloc_len)
427 dict.len = dict.alloc_len;
429 lzo_memset(dict.ptr, 0, dict.len);
431 for (i = 0; i < 256; i++)
432 for (j = 0; j < 16; j++) {
435 dict.ptr[d++] = (unsigned char) i;
439 dict.adler = lzo_adler32(1, dict.ptr, dict.len);
443 static void dict_load(const char *file_name)
448 fp = fopen(file_name, "rb");
451 dict.len = (lzo_uint) lzo_fread(fp, dict.ptr, dict.alloc_len);
453 dict.adler = lzo_adler32(1, dict.ptr, dict.len);
458 /*************************************************************************
459 // compression database
460 **************************************************************************/
466 lzo_uint32_t mem_compress;
467 lzo_uint32_t mem_decompress;
468 lzo_compress_t compress;
469 lzo_optimize_t optimize;
470 lzo_decompress_t decompress;
471 lzo_decompress_t decompress_safe;
472 lzo_decompress_t decompress_asm;
473 lzo_decompress_t decompress_asm_safe;
474 lzo_decompress_t decompress_asm_fast;
475 lzo_decompress_t decompress_asm_fast_safe;
476 lzo_compress_dict_t compress_dict;
477 lzo_decompress_dict_t decompress_dict_safe;
487 #define M_PRIVATE LZO_PRIVATE
488 #define m_uint lzo_uint
489 #define m_uint32_t lzo_uint32_t
490 #define m_voidp lzo_voidp
491 #define m_bytep lzo_bytep
492 #define m_uintp lzo_uintp
493 #include "wrapmisc.h"
498 static const compress_t compress_database[] = {
500 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
504 /*************************************************************************
506 **************************************************************************/
509 lzo_decompress_t get_decomp_info ( const compress_t *c, const char **nn )
511 lzo_decompress_t d = 0;
512 const char *n = NULL;
514 /* safe has priority over asm/fast */
515 if (!d && opt_use_safe_decompressor && opt_use_asm_fast_decompressor)
517 d = c->decompress_asm_fast_safe;
520 if (!d && opt_use_safe_decompressor && opt_use_asm_decompressor)
522 d = c->decompress_asm_safe;
525 if (!d && opt_use_safe_decompressor)
527 d = c->decompress_safe;
530 if (!d && opt_use_asm_fast_decompressor)
532 d = c->decompress_asm_fast;
535 if (!d && opt_use_asm_decompressor)
537 d = c->decompress_asm;
548 if (opt_dict && c->decompress_dict_safe)
558 const compress_t *find_method_by_id ( int method )
560 const compress_t *db;
561 size_t size = sizeof(compress_database) / sizeof(*(compress_database));
564 db = compress_database;
565 for (i = 0; i < size && db->name != NULL; i++, db++)
567 if (method == db->id)
575 const compress_t *find_method_by_name ( const char *name )
577 const compress_t *db;
578 size_t size = sizeof(compress_database) / sizeof(*(compress_database));
581 db = compress_database;
582 for (i = 0; i < size && db->name != NULL; i++, db++)
584 size_t n = strlen(db->name);
586 #if defined(HAVE_STRNCASECMP)
587 if (strncasecmp(name,db->name,n) == 0 && (!name[n] || name[n] == ','))
590 if (strncmp(name,db->name,n) == 0 && (!name[n] || name[n] == ','))
599 lzo_bool is_compressor ( const compress_t *c )
601 return (c->id <= M_LAST_COMPRESSOR || c->id >= 9721);
605 /*************************************************************************
606 // check that memory gets accessed within bounds
607 **************************************************************************/
609 static void memchecker_init ( mblock_t *mb, lzo_uint l, unsigned char random_byte )
612 lzo_uint len = (lzo_uint) l;
615 assert(len <= mb->len);
619 for (i = 0; i < 16 && p > mb->alloc_ptr; i++)
620 *--p = random_byte++;
623 for (i = 0; i < 16 && p < mb->alloc_ptr + mb->alloc_len; i++)
624 *p++ = random_byte++;
625 #if 0 || defined(LZO_DEBUG)
626 /* fill in garbage */
629 for (i = 0; i < len; i++, random_byte += 2)
635 static int memchecker_check ( mblock_t *mb, lzo_uint l, unsigned char random_byte )
638 lzo_uint len = (lzo_uint) l;
641 assert(len <= mb->len);
645 for (i = 0; i < 16 && p > mb->alloc_ptr; i++)
646 if (*--p != random_byte++)
650 for (i = 0; i < 16 && p < mb->alloc_ptr + mb->alloc_len; i++)
651 if (*p++ != random_byte++)
657 /*************************************************************************
659 **************************************************************************/
662 int call_compressor ( const compress_t *c,
663 const lzo_bytep src, lzo_uint src_len,
664 lzo_bytep dst, lzo_uintp dst_len )
668 if (c && c->compress && block_w.len >= c->mem_compress)
670 unsigned char random_byte = (unsigned char) src_len;
671 memchecker_init(&block_w, c->mem_compress, random_byte);
672 if (opt_clear_wrkmem)
673 lzo_memset(block_w.ptr, 0, c->mem_compress);
675 if (opt_dict && c->compress_dict)
676 r = c->compress_dict(src,src_len,dst,dst_len,block_w.ptr,dict.ptr,dict.len);
678 r = c->compress(src,src_len,dst,dst_len,block_w.ptr);
680 if (memchecker_check(&block_w, c->mem_compress, random_byte) != 0)
681 printf("WARNING: wrkmem overwrite error (compress) !!!\n");
684 if (r == 0 && opt_compute_adler32)
687 adler = lzo_adler32(0, NULL, 0);
688 adler = lzo_adler32(adler, src, src_len);
691 if (r == 0 && opt_compute_crc32)
694 crc = lzo_crc32(0, NULL, 0);
695 crc = lzo_crc32(crc, src, src_len);
703 /*************************************************************************
704 // decompress a block
705 **************************************************************************/
708 int call_decompressor ( const compress_t *c, lzo_decompress_t d,
709 const lzo_bytep src, lzo_uint src_len,
710 lzo_bytep dst, lzo_uintp dst_len )
714 if (c && d && block_w.len >= c->mem_decompress)
716 unsigned char random_byte = (unsigned char) src_len;
717 memchecker_init(&block_w, c->mem_decompress, random_byte);
718 if (opt_clear_wrkmem)
719 lzo_memset(block_w.ptr, 0, c->mem_decompress);
721 if (opt_dict && c->decompress_dict_safe)
722 r = c->decompress_dict_safe(src,src_len,dst,dst_len,block_w.ptr,dict.ptr,dict.len);
724 r = d(src,src_len,dst,dst_len,block_w.ptr);
726 if (memchecker_check(&block_w, c->mem_decompress, random_byte) != 0)
727 printf("WARNING: wrkmem overwrite error (decompress) !!!\n");
730 if (r == 0 && opt_compute_adler32)
731 adler_out = lzo_adler32(1, dst, *dst_len);
732 if (r == 0 && opt_compute_crc32)
733 crc_out = lzo_crc32(0, dst, *dst_len);
739 /*************************************************************************
741 **************************************************************************/
744 int call_optimizer ( const compress_t *c,
745 lzo_bytep src, lzo_uint src_len,
746 lzo_bytep dst, lzo_uintp dst_len )
748 if (c && c->optimize && block_w.len >= c->mem_decompress)
749 return c->optimize(src,src_len,dst,dst_len,block_w.ptr);
754 /***********************************************************************
756 ************************************************************************/
758 static int load_file(const char *file_name, lzo_uint max_data_len)
768 mblock_t *mb = &file_data;
772 fp = fopen(file_name, "rb");
775 fflush(stdout); fflush(stderr);
776 fprintf(stderr, "%s: ", file_name);
779 fflush(stdout); fflush(stderr);
782 r = fseek(fp, 0, SEEK_END);
790 r = fseek(fp, 0, SEEK_SET);
792 if (r != 0 || ll < 0)
794 fflush(stdout); fflush(stderr);
795 fprintf(stderr, "%s: ", file_name);
798 fflush(stdout); fflush(stderr);
804 if (l > max_data_len) l = max_data_len;
806 if ((off_t) l != ll) l = max_data_len;
808 if ((long) l != ll) l = max_data_len;
812 mb->len = (lzo_uint) lzo_fread(fp, mb->ptr, mb->len);
815 if (fclose(fp) != 0 || r != 0)
818 fflush(stdout); fflush(stderr);
819 fprintf(stderr, "%s: ", file_name);
822 fflush(stdout); fflush(stderr);
830 /***********************************************************************
831 // print some compression statistics
832 ************************************************************************/
834 static double t_div(double a, double b)
836 return b > 0.00001 ? a / b : 0;
839 static double set_perc_d(double perc, char *s)
845 if (perc <= 100 - 1.0 / 16) {
846 sprintf(s, "%4.1f", perc);
849 long p = (long) (perc + 0.5);
855 sprintf(s, "%ld", p);
860 static double set_perc(unsigned long c_len, unsigned long d_len, char *s)
864 perc = c_len * 100.0 / d_len;
865 return set_perc_d(perc, s);
870 void print_stats ( const char *method_name, const char *file_name,
871 long t_loops, long c_loops, long d_loops,
872 double t_secs, double c_secs, double d_secs,
873 unsigned long c_len, unsigned long d_len,
874 unsigned long blocks )
876 unsigned long x_len = d_len;
877 unsigned long t_bytes, c_bytes, d_bytes;
878 double c_mbs, d_mbs, t_mbs;
882 perc = set_perc(c_len, d_len, perc_str);
884 c_bytes = x_len * c_loops * t_loops;
885 d_bytes = x_len * d_loops * t_loops;
886 t_bytes = c_bytes + d_bytes;
889 c_secs = d_secs = t_secs = 0.0;
891 /* speed in uncompressed megabytes per second (1 megabyte = 1.000.000 bytes) */
892 c_mbs = (c_secs > 0.001) ? (c_bytes / c_secs) / 1000000.0 : 0;
893 d_mbs = (d_secs > 0.001) ? (d_bytes / d_secs) / 1000000.0 : 0;
894 t_mbs = (t_secs > 0.001) ? (t_bytes / t_secs) / 1000000.0 : 0;
897 total_c_len += c_len;
898 total_d_len += d_len;
899 total_blocks += blocks;
903 total_c_mbs_harmonic += 1.0 / c_mbs;
904 total_c_mbs_sum += c_mbs;
908 total_d_mbs_harmonic += 1.0 / d_mbs;
909 total_d_mbs_sum += d_mbs;
912 if (opt_verbose >= 2)
914 printf(" compressed into %lu bytes, %s%% (%s%.3f bits/byte)\n",
915 c_len, perc_str, "", perc * 0.08);
918 printf("%-15s %5ld: ","overall", t_loops);
919 printf("%10lu bytes, %8.2f secs, %8.3f MB/sec\n",
920 t_bytes, t_secs, t_mbs);
924 printf("%-15s %5ld: ","compress", c_loops);
925 printf("%10lu bytes, %8.2f secs, %8.3f MB/sec\n",
926 c_bytes, c_secs, c_mbs);
927 printf("%-15s %5ld: ","decompress", d_loops);
928 printf("%10lu bytes, %8.2f secs, %8.3f MB/sec\n",
929 d_bytes, d_secs, d_mbs);
933 /* create a line for util/table.pl */
934 if (opt_verbose >= 1)
937 const char *n, *nn, *b;
938 for (nn = n = b = file_name; *nn; nn++)
939 if (*nn == '/' || *nn == '\\' || *nn == ':')
944 printf("%-13s| %-14s %8lu %4lu %9lu %4s %s%8.3f %8.3f |\n",
945 method_name, n, d_len, blocks, c_len, perc_str, "", c_mbs, d_mbs);
948 if (opt_verbose >= 2)
954 void print_totals ( void )
958 if ((opt_verbose >= 1 && total_n > 1) || (opt_totals >= 2))
960 unsigned long n = total_n > 0 ? total_n : 1;
961 const char *t1 = "-------";
962 const char *t2 = total_method_names == 1 ? total_method_name : "";
963 #if 1 && defined(__LZOLIB_PCLOCK_CH_INCLUDED)
964 char pclock_mode[32+1];
965 sprintf(pclock_mode, "[clock=%d]", pch.mode);
967 if (opt_pclock == 0) t1 = t2;
971 set_perc_d(total_perc / n, perc_str);
972 printf("%-13s %-12s %10lu %4.1f %9lu %4s %8.3f %8.3f\n",
974 total_d_len / n, total_blocks * 1.0 / n, total_c_len / n, perc_str,
975 t_div((double)total_c_mbs_n, total_c_mbs_harmonic),
976 t_div((double)total_d_mbs_n, total_d_mbs_harmonic));
978 set_perc(total_c_len, total_d_len, perc_str);
979 printf("%-13s %-12s %10lu %4lu %9lu %4s %s%8.3f %8.3f\n",
981 total_d_len, total_blocks, total_c_len, perc_str, "",
982 t_div((double)total_c_mbs_n, total_c_mbs_harmonic),
983 t_div((double)total_d_mbs_n, total_d_mbs_harmonic));
988 /*************************************************************************
989 // compress and decompress a file
990 **************************************************************************/
992 static __lzo_noinline
993 int process_file ( const compress_t *c, lzo_decompress_t decompress,
994 const char *method_name,
995 const char *file_name,
996 long t_loops, long c_loops, long d_loops )
999 unsigned long blocks = 0;
1000 unsigned long compressed_len = 0;
1001 double t_time = 0, c_time = 0, d_time = 0;
1002 lzo_pclock_t t_start, t_stop, x_start, x_stop;
1003 FILE *fp_dump = NULL;
1005 if (opt_dump_compressed_data)
1006 fp_dump = fopen(opt_dump_compressed_data,"wb");
1008 /* process the file */
1010 lzo_pclock_flush_cpu_cache(&pch, 0);
1011 lzo_pclock_read(&pch, &t_start);
1012 for (t_i = 0; t_i < t_loops; t_i++)
1014 lzo_uint len, c_len, c_len_max, d_len = 0;
1015 const lzo_bytep d = file_data.ptr;
1017 len = file_data.len;
1021 /* process blocks */
1022 if (len > 0 || opt_try_to_compress_0_bytes) do
1027 unsigned char random_byte = (unsigned char) file_data.len;
1028 #if 1 && defined(CLOCKS_PER_SEC)
1029 random_byte = (unsigned char) (random_byte ^ clock());
1033 bl = len > opt_block_size ? opt_block_size : len;
1034 /* update lengths for memchecker_xxx() */
1035 block_c.len = bl + get_max_compression_expansion(c->id, bl);
1036 block_d.len = bl + get_max_decompression_overrun(c->id, bl);
1037 #if defined(__LZO_CHECKER)
1038 /* malloc a block of the exact size to detect any overrun */
1039 assert(block_c.alloc_ptr == NULL);
1040 assert(block_d.alloc_ptr == NULL);
1041 mb_alloc(&block_c, block_c.len);
1042 mb_alloc(&block_d, block_d.len);
1044 assert(block_c.len <= block_c.saved_len);
1045 assert(block_d.len <= block_d.saved_len);
1047 memchecker_init(&block_c, block_c.len, random_byte);
1048 memchecker_init(&block_d, block_d.len, random_byte);
1050 /* compress the block */
1051 c_len = c_len_max = 0;
1052 lzo_pclock_flush_cpu_cache(&pch, 0);
1053 lzo_pclock_read(&pch, &x_start);
1054 for (r = 0, c_i = 0; c_i < c_loops; c_i++)
1056 c_len = block_c.len;
1057 r = call_compressor(c, d, bl, block_c.ptr, &c_len);
1060 if (c_len > c_len_max)
1062 if (c_len > block_c.len)
1063 goto compress_overrun;
1065 lzo_pclock_read(&pch, &x_stop);
1066 c_time += lzo_pclock_get_elapsed(&pch, &x_start, &x_stop);
1069 printf(" compression failed in block %lu (%d) (%lu %lu)\n",
1070 blocks, r, (unsigned long)c_len, (unsigned long)bl);
1071 return EXIT_LZO_ERROR;
1073 if (memchecker_check(&block_c, block_c.len, random_byte) != 0)
1076 printf(" compression overwrite error in block %lu "
1077 "(%lu %lu %lu %lu)\n",
1078 blocks, (unsigned long)c_len, (unsigned long)d_len, (unsigned long)bl, (unsigned long)block_c.len);
1079 return EXIT_LZO_ERROR;
1082 /* optimize the compressed block */
1083 if (c_len < bl && opt_optimize_compressed_data)
1086 r = call_optimizer(c, block_c.ptr, c_len, block_d.ptr, &d_len);
1087 if (r != 0 || d_len != bl)
1089 printf(" optimization failed in block %lu (%d) "
1090 "(%lu %lu %lu)\n", blocks, r,
1091 (unsigned long)c_len, (unsigned long)d_len, (unsigned long)bl);
1092 return EXIT_LZO_ERROR;
1094 if (memchecker_check(&block_c, block_c.len, random_byte) != 0 ||
1095 memchecker_check(&block_d, block_d.len, random_byte) != 0)
1097 printf(" optimize overwrite error in block %lu "
1098 "(%lu %lu %lu %lu)\n",
1099 blocks, (unsigned long)c_len, (unsigned long)d_len, (unsigned long)bl, (unsigned long)block_c.len);
1100 return EXIT_LZO_ERROR;
1104 /* dump compressed data to disk */
1107 lzo_uint l = (lzo_uint) lzo_fwrite(fp_dump, block_c.ptr, c_len);
1108 if (l != c_len || fflush(fp_dump) != 0) {
1110 (void) fclose(fp_dump); fp_dump = NULL;
1114 /* decompress the block and verify */
1115 lzo_pclock_flush_cpu_cache(&pch, 0);
1116 lzo_pclock_read(&pch, &x_start);
1117 for (r = 0, c_i = 0; c_i < d_loops; c_i++)
1120 r = call_decompressor(c, decompress, block_c.ptr, c_len, block_d.ptr, &d_len);
1121 if (r != 0 || d_len != bl)
1124 lzo_pclock_read(&pch, &x_stop);
1125 d_time += lzo_pclock_get_elapsed(&pch, &x_start, &x_stop);
1128 printf(" decompression failed in block %lu (%d) "
1129 "(%lu %lu %lu)\n", blocks, r,
1130 (unsigned long)c_len, (unsigned long)d_len, (unsigned long)bl);
1131 return EXIT_LZO_ERROR;
1135 printf(" decompression size error in block %lu (%lu %lu %lu)\n",
1136 blocks, (unsigned long)c_len, (unsigned long)d_len, (unsigned long)bl);
1137 return EXIT_LZO_ERROR;
1139 if (is_compressor(c))
1141 if (lzo_memcmp(d, block_d.ptr, bl) != 0)
1144 while (x < bl && block_d.ptr[x] == d[x])
1146 printf(" decompression data error in block %lu at offset "
1147 "%lu (%lu %lu)\n", blocks, (unsigned long)x,
1148 (unsigned long)c_len, (unsigned long)d_len);
1149 if (opt_compute_adler32)
1150 printf(" checksum: 0x%08lx 0x%08lx\n",
1151 (unsigned long)adler_in, (unsigned long)adler_out);
1154 r = (x >= 10) ? -10 : 0 - (int) x;
1155 for (j = r; j <= 10 && x + j < bl; j++)
1156 printf(" %02x", (int)d[x+j]);
1157 printf("\nDecomp:");
1158 for (j = r; j <= 10 && x + j < bl; j++)
1159 printf(" %02x", (int)block_d.ptr[x+j]);
1162 return EXIT_LZO_ERROR;
1164 if ((opt_compute_adler32 && adler_in != adler_out) ||
1165 (opt_compute_crc32 && crc_in != crc_out))
1167 printf(" checksum error in block %lu (%lu %lu)\n",
1168 blocks, (unsigned long)c_len, (unsigned long)d_len);
1169 printf(" adler32: 0x%08lx 0x%08lx\n",
1170 (unsigned long)adler_in, (unsigned long)adler_out);
1171 printf(" crc32: 0x%08lx 0x%08lx\n",
1172 (unsigned long)crc_in, (unsigned long)crc_out);
1173 return EXIT_LZO_ERROR;
1177 if (memchecker_check(&block_d, block_d.len, random_byte) != 0)
1179 printf(" decompression overwrite error in block %lu "
1180 "(%lu %lu %lu %lu)\n",
1181 blocks, (unsigned long)c_len, (unsigned long)d_len,
1182 (unsigned long)bl, (unsigned long)block_d.len);
1183 return EXIT_LZO_ERROR;
1186 #if defined(__LZO_CHECKER)
1187 /* free in reverse order of allocations */
1194 compressed_len += (unsigned long) c_len_max;
1198 lzo_pclock_read(&pch, &t_stop);
1199 t_time += lzo_pclock_get_elapsed(&pch, &t_start, &t_stop);
1202 (void) fclose(fp_dump); fp_dump = NULL;
1204 opt_dump_compressed_data = NULL; /* only dump the first file */
1206 print_stats(method_name, file_name,
1207 t_loops, c_loops, d_loops,
1208 t_time, c_time, d_time,
1209 compressed_len, (unsigned long) file_data.len, blocks);
1210 if (total_method_name != c->name) {
1211 total_method_name = c->name;
1212 total_method_names += 1;
1221 int do_file ( int method, const char *file_name,
1222 long c_loops, long d_loops,
1223 lzo_uint32_tp p_adler, lzo_uint32_tp p_crc )
1226 const compress_t *c;
1227 lzo_decompress_t decompress;
1228 lzo_uint32_t adler, crc;
1229 char method_name[256+1];
1231 const long t_loops = 1;
1233 adler_in = adler_out = 0;
1234 crc_in = crc_out = 0;
1240 c = find_method_by_id(method);
1241 if (c == NULL || c->name == NULL || c->compress == NULL)
1242 return EXIT_INTERNAL;
1243 decompress = get_decomp_info(c,&n);
1244 if (!decompress || n == NULL || block_w.len < c->mem_decompress)
1245 return EXIT_INTERNAL;
1246 strcpy(method_name,c->name);
1247 strcat(method_name,n);
1249 if (c_loops < 1) c_loops = 1;
1250 if (d_loops < 1) d_loops = 1;
1252 fflush(stdout); fflush(stderr);
1254 /* read the whole file */
1255 r = load_file(file_name, opt_max_data_len);
1259 /* compute some checksums */
1260 adler = lzo_adler32(0, NULL, 0);
1261 adler = lzo_adler32(adler, file_data.ptr, file_data.len);
1264 crc = lzo_crc32(0, NULL, 0);
1265 crc = lzo_crc32(crc, file_data.ptr, file_data.len);
1269 if (opt_verbose >= 2)
1271 printf("File %s: %lu bytes (0x%08lx, 0x%08lx)\n",
1272 file_name, (unsigned long) file_data.len, (unsigned long) adler, (unsigned long) crc);
1273 printf(" compressing %lu bytes (%ld/%ld/%ld loops, %lu block-size)\n",
1274 (unsigned long) file_data.len, t_loops, c_loops, d_loops, (unsigned long) opt_block_size);
1275 printf(" %s\n", method_name);
1278 r = process_file(c, decompress, method_name, file_name,
1279 t_loops, c_loops, d_loops);
1285 /*************************************************************************
1286 // Calgary Corpus and Silesia Corpus test suite driver
1287 **************************************************************************/
1289 struct corpus_entry_t
1297 const struct corpus_entry_t *opt_corpus = NULL;
1299 static const struct corpus_entry_t calgary_corpus[] =
1301 { "bib", 8, 0x4bd09e98L, 0xb856ebe8L },
1302 { "book1", 1, 0xd4d3613eL, 0x24e19972L },
1303 { "book2", 1, 0x6fe14cc3L, 0xba0f3f26L },
1304 { "geo", 6, 0xf3cc5be0L, 0x4d3a6ed0L },
1305 { "news", 2, 0x2ed405b8L, 0xcafac853L },
1306 { "obj1", 35, 0x3887dd2cL, 0xc7b0cd26L },
1307 { "obj2", 4, 0xf89407c4L, 0x3ae33007L },
1308 { "paper1", 17, 0xfe65ce62L, 0x2b6baca0L },
1309 { "paper2", 11, 0x1238b7c2L, 0xf76cba72L },
1310 { "pic", 4, 0xf61a5702L, 0x4b17e59cL },
1311 { "progc", 25, 0x4c00ba45L, 0x6fb16094L },
1312 { "progl", 20, 0x4cba738eL, 0xddbf6baaL },
1313 { "progp", 28, 0x7495b92bL, 0x493a1809L },
1314 { "trans", 15, 0x52a2cec8L, 0xcdec06a6L },
1315 { NULL, 0, 0x00000000L, 0x00000000L }
1318 static const struct corpus_entry_t silesia_corpus[] =
1320 { "dickens", 1, 0x170f606fL, 0xaf3a6b76L },
1321 { "mozilla", 1, 0x1188dd4eL, 0x7fb0ab7dL },
1322 { "mr", 1, 0xaea14b97L, 0xa341883fL },
1323 { "nci", 1, 0x0af16f1fL, 0x60ff63d3L },
1324 { "ooffice", 1, 0x83c8f689L, 0xa023e1faL },
1325 { "osdb", 1, 0xb825b790L, 0xa0ca388cL },
1326 { "reymont", 1, 0xce5c82caL, 0x50d35f03L },
1327 { "samba", 1, 0x19dbb9f5L, 0x2beac5f3L },
1328 { "sao", 1, 0x7edfc4a9L, 0xfda125bfL },
1329 { "webster", 1, 0xf2962fc6L, 0x01f5a2e9L },
1330 { "xml", 1, 0xeccd03d6L, 0xff8f3051L },
1331 { "x-ray", 1, 0xc95435a0L, 0xc86a35c6L },
1332 { NULL, 0, 0x00000000L, 0x00000000L }
1337 int do_corpus ( const struct corpus_entry_t *corpus, int method, const char *path,
1338 long c_loops, long d_loops )
1343 if (path == NULL || strlen(path) >= sizeof(name) - 12)
1348 if (n > 0 && name[n-1] != '/' && name[n-1] != '\\' && name[n-1] != ':')
1354 for (i = 0; corpus[i].name != NULL; i++)
1356 lzo_uint32_t adler, crc;
1357 long c = c_loops * corpus[i].loops;
1358 long d = d_loops * corpus[i].loops;
1361 strcpy(name+n,corpus[i].name);
1362 r = do_file(method, name, c, d, &adler, &crc);
1365 if (adler != corpus[i].adler)
1367 printf(" invalid test suite\n");
1370 if (corpus[i].crc && crc != corpus[i].crc)
1372 printf(" internal checksum error !! (0x%08lx 0x%08lx)\n",
1373 (unsigned long) crc, (unsigned long) corpus[i].crc);
1374 return EXIT_INTERNAL;
1381 /*************************************************************************
1383 **************************************************************************/
1386 void usage ( const char *name, int exit_code, lzo_bool show_methods )
1393 fflush(stdout); fflush(stderr);
1395 fprintf(fp,"Usage: %s [option..] file...\n", name);
1397 fprintf(fp,"Options:\n");
1398 fprintf(fp," -m# compression method\n");
1399 fprintf(fp," -b# set input block size (default %lu, max %lu)\n",
1400 (unsigned long) opt_block_size, (unsigned long) opt_max_data_len);
1401 fprintf(fp," -n# number of compression/decompression runs\n");
1402 fprintf(fp," -c# number of compression runs\n");
1403 fprintf(fp," -d# number of decompression runs\n");
1404 fprintf(fp," -S use safe decompressor (if available)\n");
1405 fprintf(fp," -A use assembler decompressor (if available)\n");
1406 fprintf(fp," -F use fast assembler decompressor (if available)\n");
1407 fprintf(fp," -O optimize compressed data (if available)\n");
1408 fprintf(fp," -s DIR process Calgary Corpus test suite in directory `DIR'\n");
1409 fprintf(fp," -@ read list of files to compress from stdin\n");
1410 fprintf(fp," -q be quiet\n");
1411 fprintf(fp," -Q be very quiet\n");
1412 fprintf(fp," -v be verbose\n");
1413 fprintf(fp," -L display software license\n");
1417 #if defined(__LZOLIB_PCLOCK_CH_INCLUDED)
1418 lzo_pclock_t t_dummy;
1419 lzo_pclock_read(&pch, &t_dummy);
1420 (void) lzo_pclock_get_elapsed(&pch, &t_dummy, &t_dummy);
1421 fprintf(fp,"\nAll timings are recorded using pclock mode %d %s.\n", pch.mode, pch.name);
1424 fprintf(fp,"The following compression methods are available:\n");
1426 fprintf(fp," usage name memory available extras\n");
1427 fprintf(fp," ----- ---- ------ ----------------\n");
1429 for (i = 0; i <= M_LAST_COMPRESSOR; i++)
1431 const compress_t *c;
1432 c = find_method_by_id(i);
1436 const char *sep = " ";
1437 unsigned long m = c->mem_compress;
1439 sprintf(n,"-m%d",i);
1440 fprintf(fp," %-6s %-13s",n,c->name);
1442 fprintf(fp,"%9lu", m);
1444 m = (m + 1023) / 1024;
1445 fprintf(fp,"%6lu KiB", m);
1448 if (c->decompress_safe)
1449 { fprintf(fp, "%s%s", sep, "safe"); sep = ", "; }
1450 if (c->decompress_asm)
1451 { fprintf(fp, "%s%s", sep, "asm"); sep = ", "; }
1452 if (c->decompress_asm_safe)
1453 { fprintf(fp, "%s%s", sep, "asm+safe"); sep = ", "; }
1454 if (c->decompress_asm_fast)
1455 { fprintf(fp, "%s%s", sep, "fastasm"); sep = ", "; }
1456 if (c->decompress_asm_fast_safe)
1457 { fprintf(fp, "%s%s", sep, "fastasm+safe"); sep = ", "; }
1459 { fprintf(fp, "%s%s", sep, "optimize"); /*sep = ", ";*/ }
1467 fprintf(fp,"Type '%s -m' to list all available methods.\n", name);
1472 exit_code = EXIT_USAGE;
1483 fflush(stdout); fflush(stderr);
1486 " The LZO library is free software; you can redistribute it and/or\n"
1487 " modify it under the terms of the GNU General Public License as\n"
1488 " published by the Free Software Foundation; either version 2 of\n"
1489 " the License, or (at your option) any later version.\n"
1491 " The LZO library is distributed in the hope that it will be useful,\n"
1492 " but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
1493 " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
1494 " GNU General Public License for more details.\n"
1498 " You should have received a copy of the GNU General Public License\n"
1499 " along with the LZO library; see the file COPYING.\n"
1500 " If not, write to the Free Software Foundation, Inc.,\n"
1501 " 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n"
1503 " Markus F.X.J. Oberhumer\n"
1504 " <markus@oberhumer.com>\n"
1505 " http://www.oberhumer.com/opensource/lzo/\n"
1514 /*************************************************************************
1515 // parse method option '-m'
1516 **************************************************************************/
1518 static int methods[256+1];
1519 static int methods_n = 0;
1521 static void add_method(int m)
1527 if (!find_method_by_id(m)) {
1528 fprintf(stdout,"%s: invalid method %d\n",progname,m);
1532 for (i = 0; i < methods_n; i++)
1533 if (methods[i] == m)
1536 if (methods_n >= 256)
1538 fprintf(stderr,"%s: too many methods\n",progname);
1542 methods[methods_n++] = m;
1543 methods[methods_n] = 0;
1548 static void add_methods(const int *ml)
1555 static void add_all_methods(int first, int last)
1559 for (m = first; m <= last; m++)
1560 if (find_method_by_id(m) != NULL)
1565 static int m_strcmp(const char *a, const char *b)
1569 if (a[0] == 0 || b[0] == 0)
1572 if (strncmp(a,b,n) == 0 && (a[n] == 0 || a[n] == ','))
1578 static lzo_bool m_strisdigit(const char *s)
1585 if (*s == 0 || *s == ',')
1592 static void parse_methods(const char *p)
1594 const compress_t *c;
1598 if (p == NULL || p[0] == 0)
1599 usage(progname,-1,1);
1600 else if ((c = find_method_by_name(p)) != NULL)
1602 else if (m_strcmp(p,"all") == 0 || m_strcmp(p,"avail") == 0)
1603 add_all_methods(1,M_LAST_COMPRESSOR);
1604 else if (m_strcmp(p,"ALL") == 0)
1606 add_all_methods(1,M_LAST_COMPRESSOR);
1607 add_all_methods(9721,9729);
1608 add_all_methods(9781,9789);
1610 else if (m_strcmp(p,"lzo") == 0)
1611 add_all_methods(1,M_MEMCPY);
1612 else if (m_strcmp(p,"bench") == 0)
1613 add_methods(benchmark_methods);
1614 else if (m_strcmp(p,"m1") == 0)
1615 add_methods(x1_methods);
1616 else if (m_strcmp(p,"m99") == 0)
1617 add_methods(x99_methods);
1618 else if (m_strcmp(p,"m999") == 0)
1619 add_methods(x999_methods);
1620 else if (m_strcmp(p,"1x999") == 0)
1621 add_all_methods(9721,9729);
1622 else if (m_strcmp(p,"1y999") == 0)
1623 add_all_methods(9821,9829);
1624 #if defined(ALG_ZLIB)
1625 else if (m_strcmp(p,"zlib") == 0)
1626 add_all_methods(M_ZLIB_8_1,M_ZLIB_8_9);
1628 #if defined(ALG_BZIP2)
1629 else if (m_strcmp(p,"bzip2") == 0)
1630 add_all_methods(M_BZIP2_1,M_BZIP2_9);
1632 else if (m_strisdigit(p))
1633 add_method(atoi(p));
1636 printf("%s: invalid method '%s'\n\n",progname,p);
1640 while (*p && *p != ',')
1650 /*************************************************************************
1652 **************************************************************************/
1655 OPT_LONGOPT_ONLY = 512,
1670 static const struct lzo_getopt_longopt_t longopts[] =
1672 /* { name has_arg *flag val } */
1673 {"help", 0, 0, 'h'+256}, /* give help */
1674 {"license", 0, 0, 'L'}, /* display software license */
1675 {"quiet", 0, 0, 'q'}, /* quiet mode */
1676 {"verbose", 0, 0, 'v'}, /* verbose mode */
1677 {"version", 0, 0, 'V'+256}, /* display version number */
1679 {"adler32", 0, 0, OPT_ADLER32},
1680 {"calgary-corpus", 1, 0, OPT_CALGARY_CORPUS},
1681 {"clear-wrkmem", 0, 0, OPT_CLEAR_WRKMEM},
1682 {"clock", 1, 0, OPT_PCLOCK},
1683 {"corpus", 1, 0, OPT_CALGARY_CORPUS},
1684 {"crc32", 0, 0, OPT_CRC32},
1685 {"dict", 1, 0, OPT_DICT},
1686 {"dump-compressed", 1, 0, OPT_DUMP},
1687 {"execution-time", 0, 0, OPT_EXECUTION_TIME},
1688 {"max-data-length", 1, 0, OPT_MAX_DATA_LEN},
1689 {"max-dict-length", 1, 0, OPT_MAX_DICT_LEN},
1690 {"silesia-corpus", 1, 0, OPT_SILESIA_CORPUS},
1691 {"uclock", 1, 0, OPT_PCLOCK},
1692 {"methods", 1, 0, 'm'},
1693 {"totals", 0, 0, 'T'},
1699 static int do_option(lzo_getopt_p g, int optc)
1701 #define mfx_optarg g->optarg
1705 opt_use_asm_decompressor = 1;
1708 opt_block_size = 0; /* set to opt_max_data_len later */
1711 if (!mfx_optarg || !is_digit(mfx_optarg[0]))
1713 opt_block_size = atol(mfx_optarg);
1718 if (!mfx_optarg || !is_digit(mfx_optarg[0]))
1720 opt_c_loops = atol(mfx_optarg);
1724 if (!mfx_optarg || !is_digit(mfx_optarg[0]))
1726 opt_d_loops = atol(mfx_optarg);
1729 opt_use_asm_fast_decompressor = 1;
1735 usage(progname,EXIT_OK,0);
1741 parse_methods(mfx_optarg);
1744 if (!mfx_optarg || !is_digit(mfx_optarg[0]))
1746 opt_c_loops = opt_d_loops = atol(mfx_optarg);
1749 opt_optimize_compressed_data = 1;
1758 case OPT_CALGARY_CORPUS:
1759 if (!mfx_optarg || !mfx_optarg[0])
1761 opt_corpus_path = mfx_optarg;
1762 opt_corpus = calgary_corpus;
1764 case OPT_SILESIA_CORPUS:
1765 if (!mfx_optarg || !mfx_optarg[0])
1767 opt_corpus_path = mfx_optarg;
1768 opt_corpus = silesia_corpus;
1771 opt_use_safe_decompressor = 1;
1784 opt_read_from_stdin = 1;
1787 case '1': case '2': case '3': case '4': case '5':
1788 case '6': case '7': case '8': case '9':
1789 /* this is a dirty hack... */
1790 if (g->shortpos == 0) {
1791 char m[2]; m[0] = (char) optc; m[1] = 0;
1794 const char *m = &g->argv[g->optind][g->shortpos-1];
1796 ++g->optind; g->shortpos = 0;
1801 opt_compute_adler32 = 1;
1803 case OPT_CLEAR_WRKMEM:
1804 opt_clear_wrkmem = 1;
1807 opt_compute_crc32 = 1;
1811 opt_dictionary_file = mfx_optarg;
1813 case OPT_EXECUTION_TIME:
1814 opt_execution_time = 1;
1817 opt_dump_compressed_data = mfx_optarg;
1819 case OPT_MAX_DATA_LEN:
1820 if (!mfx_optarg || !is_digit(mfx_optarg[0]))
1822 opt_max_data_len = atol(mfx_optarg);
1824 case OPT_MAX_DICT_LEN:
1825 if (!mfx_optarg || !is_digit(mfx_optarg[0]))
1827 opt_max_dict_len = atol(mfx_optarg);
1830 if (!mfx_optarg || !is_digit(mfx_optarg[0]))
1832 opt_pclock = atoi(mfx_optarg);
1833 #if defined(__LZOLIB_PCLOCK_CH_INCLUDED)
1835 pch.mode = opt_pclock;
1844 fprintf(stderr,"%s: internal error in getopt (%d)\n",progname,optc);
1852 static void handle_opterr(lzo_getopt_p g, const char *f, void *v)
1854 struct A { va_list ap; };
1855 struct A *a = (struct A *) v;
1856 fprintf( stderr, "%s: ", g->progname);
1858 vfprintf(stderr, f, a->ap);
1860 fprintf( stderr, "UNKNOWN GETOPT ERROR");
1861 fprintf( stderr, "\n");
1865 static int get_options(int argc, char **argv)
1867 lzo_getopt_t mfx_getopt;
1869 static const char shortopts[] =
1870 "Ab::c:C:d:D:FhHLm::n:OqQs:STvV@123456789";
1872 lzo_getopt_init(&mfx_getopt, 1, argc, argv);
1873 mfx_getopt.progname = progname;
1874 mfx_getopt.opterr = handle_opterr;
1875 while ((optc = lzo_getopt(&mfx_getopt, shortopts, longopts, NULL)) >= 0)
1877 if (do_option(&mfx_getopt, optc) != 0)
1881 return mfx_getopt.optind;
1885 /*************************************************************************
1887 **************************************************************************/
1889 int __lzo_cdecl_main main(int argc, char *argv[])
1897 lzo_wildargv(&argc, &argv);
1898 lzo_pclock_open_default(&pch);
1901 for (s = progname; *s; s++)
1902 if ((*s == '/' || *s == '\\') && s[1])
1905 printf("\nLZO real-time data compression library (v%s, %s).\n",
1906 lzo_version_string(), lzo_version_date());
1907 printf("Copyright (C) 1996-2017 Markus Franz Xaver Johannes Oberhumer\nAll Rights Reserved.\n\n");
1911 * Step 1: initialize the LZO library
1914 if (lzo_init() != LZO_E_OK)
1916 printf("internal error - lzo_init() failed !!!\n");
1917 printf("(this usually indicates a compiler bug - try recompiling\nwithout optimizations, and enable `-DLZO_DEBUG' for diagnostics)\n");
1923 * Step 2: setup default options
1926 opt_max_data_len = 64 * 1024L * 1024L;
1927 opt_block_size = 256 * 1024L;
1929 #if (LZO_ARCH_M68K && LZO_OS_TOS)
1930 /* reduce memory requirements for 14 MB machines */
1931 opt_max_data_len = 8 * 1024L * 1024L;
1937 * Step 3: parse options
1941 usage(progname,-1,0);
1942 i = get_options(argc,argv);
1945 add_method(default_method);
1946 if (methods_n > 1 && opt_read_from_stdin)
1948 printf("%s: cannot use multiple methods and '-@'\n", progname);
1952 if (opt_block_size == 0)
1953 opt_block_size = opt_max_data_len;
1954 if (opt_block_size > opt_max_data_len)
1955 opt_block_size = opt_max_data_len;
1957 if (opt_c_loops < 1)
1959 if (opt_d_loops < 1)
1964 * Step 4: start work
1968 for (ii = 0; ii < methods_n; ii++) {
1969 const compress_t *c = find_method_by_id(methods[ii]);
1971 if (c->mem_compress > block_w.len)
1972 block_w.len = c->mem_compress;
1973 if (c->mem_decompress > block_w.len)
1974 block_w.len = c->mem_decompress;
1977 mb_alloc(&block_w, block_w.len);
1978 lzo_memset(block_w.ptr, 0, block_w.len);
1980 #if !defined(__LZO_CHECKER)
1981 mb_alloc_extra(&block_c, opt_block_size + get_max_compression_expansion(-1, opt_block_size), 16, 16);
1982 mb_alloc_extra(&block_d, opt_block_size + get_max_decompression_overrun(-1, opt_block_size), 16, 16);
1987 opt_optimize_compressed_data = 0;
1988 dict_alloc(opt_max_dict_len);
1989 if (opt_dictionary_file)
1991 dict_load(opt_dictionary_file);
1993 printf("Using dictionary '%s', %lu bytes, ID 0x%08lx.\n",
1994 opt_dictionary_file,
1995 (unsigned long) dict.len, (unsigned long) dict.adler);
2000 printf("Using default dictionary, %lu bytes, ID 0x%08lx.\n",
2001 (unsigned long) dict.len, (unsigned long) dict.adler);
2005 t_total = time(NULL);
2007 for (m = 0; m < methods_n && r == EXIT_OK; m++)
2009 int method = methods[m];
2012 if (i >= argc && opt_corpus_path == NULL && !opt_read_from_stdin)
2013 usage(progname,-1,0);
2014 if (m == 0 && opt_verbose >= 1)
2015 printf("%lu block-size\n\n", (unsigned long) opt_block_size);
2017 assert(find_method_by_id(method) != NULL);
2019 if (opt_corpus_path != NULL)
2020 r = do_corpus(opt_corpus, method, opt_corpus_path,
2021 opt_c_loops, opt_d_loops);
2024 for ( ; i < argc && r == EXIT_OK; i++)
2026 r = do_file(method,argv[i],opt_c_loops,opt_d_loops,NULL,NULL);
2027 if (r == EXIT_FILE) /* ignore file errors */
2030 if (opt_read_from_stdin)
2034 while (r == EXIT_OK && fgets(buf,sizeof(buf)-1,stdin) != NULL)
2036 buf[sizeof(buf)-1] = 0;
2037 p = buf + strlen(buf);
2038 while (p > buf && is_space(p[-1]))
2041 while (*p && is_space(*p))
2044 r = do_file(method,p,opt_c_loops,opt_d_loops,NULL,NULL);
2045 if (r == EXIT_FILE) /* ignore file errors */
2048 opt_read_from_stdin = 0;
2052 t_total = time(NULL) - t_total;
2056 if (opt_execution_time || (methods_n > 1 && opt_verbose >= 1))
2057 printf("\n%s: execution time: %lu seconds\n", progname, (unsigned long) t_total);
2059 printf("\n%s: exit code: %d\n", progname, r);
2061 lzo_pclock_close(&pch);
2066 /* vim:set ts=4 sw=4 et: */