benchmark silo added
[c11concurrency-benchmarks.git] / silo / third-party / lz4 / fullbench.c
1 /*\r
2     bench.c - Demo program to benchmark open-source compression algorithm\r
3     Copyright (C) Yann Collet 2012-2013\r
4     GPL v2 License\r
5 \r
6     This program is free software; you can redistribute it and/or modify\r
7     it under the terms of the GNU General Public License as published by\r
8     the Free Software Foundation; either version 2 of the License, or\r
9     (at your option) any later version.\r
10 \r
11     This program is distributed in the hope that it will be useful,\r
12     but WITHOUT ANY WARRANTY; without even the implied warranty of\r
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
14     GNU General Public License for more details.\r
15 \r
16     You should have received a copy of the GNU General Public License along\r
17     with this program; if not, write to the Free Software Foundation, Inc.,\r
18     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
19 \r
20     You can contact the author at :\r
21     - LZ4 homepage : http://fastcompression.blogspot.com/p/lz4.html\r
22     - LZ4 source repository : http://code.google.com/p/lz4/\r
23 */\r
24 \r
25 //**************************************\r
26 // Compiler Options\r
27 //**************************************\r
28 // Disable some Visual warning messages\r
29 #define _CRT_SECURE_NO_WARNINGS\r
30 #define _CRT_SECURE_NO_DEPRECATE     // VS2005\r
31 \r
32 // Unix Large Files support (>4GB)\r
33 #if (defined(__sun__) && (!defined(__LP64__)))   // Sun Solaris 32-bits requires specific definitions\r
34 #  define _LARGEFILE_SOURCE \r
35 #  define _FILE_OFFSET_BITS 64\r
36 #elif ! defined(__LP64__)                        // No point defining Large file for 64 bit\r
37 #  define _LARGEFILE64_SOURCE\r
38 #endif\r
39 \r
40 // S_ISREG & gettimeofday() are not supported by MSVC\r
41 #if defined(_MSC_VER)\r
42 #  define S_ISREG(x) (((x) & S_IFMT) == S_IFREG)\r
43 #  define BMK_LEGACY_TIMER 1\r
44 #endif\r
45 \r
46 // GCC does not support _rotl outside of Windows\r
47 #if !defined(_WIN32)\r
48 #  define _rotl(x,r) ((x << r) | (x >> (32 - r)))\r
49 #endif\r
50 \r
51 \r
52 //**************************************\r
53 // Includes\r
54 //**************************************\r
55 #include <stdlib.h>      // malloc\r
56 #include <stdio.h>       // fprintf, fopen, ftello64\r
57 #include <sys/types.h>   // stat64\r
58 #include <sys/stat.h>    // stat64\r
59 \r
60 // Use ftime() if gettimeofday() is not available on your target\r
61 #if defined(BMK_LEGACY_TIMER)\r
62 #  include <sys/timeb.h>   // timeb, ftime\r
63 #else\r
64 #  include <sys/time.h>    // gettimeofday\r
65 #endif\r
66 \r
67 #include "lz4.h"\r
68 #define COMPRESSOR0 LZ4_compress\r
69 #include "lz4hc.h"\r
70 #define COMPRESSOR1 LZ4_compressHC\r
71 #define DEFAULTCOMPRESSOR COMPRESSOR0\r
72 \r
73 #include "xxhash.h"\r
74 \r
75 \r
76 //**************************************\r
77 // Basic Types\r
78 //**************************************\r
79 #if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L   // C99\r
80 # include <stdint.h>\r
81   typedef uint8_t  BYTE;\r
82   typedef uint16_t U16;\r
83   typedef uint32_t U32;\r
84   typedef  int32_t S32;\r
85   typedef uint64_t U64;\r
86 #else\r
87   typedef unsigned char       BYTE;\r
88   typedef unsigned short      U16;\r
89   typedef unsigned int        U32;\r
90   typedef   signed int        S32;\r
91   typedef unsigned long long  U64;\r
92 #endif\r
93 \r
94 \r
95 //****************************\r
96 // Constants\r
97 //****************************\r
98 #define COMPRESSOR_NAME "Full LZ4 speed analyzer"\r
99 #define COMPRESSOR_VERSION ""\r
100 #define COMPILED __DATE__\r
101 #define AUTHOR "Yann Collet"\r
102 #define WELCOME_MESSAGE "*** %s %s, by %s (%s) ***\n", COMPRESSOR_NAME, COMPRESSOR_VERSION, AUTHOR, COMPILED\r
103 \r
104 #define NBLOOPS    6\r
105 #define TIMELOOP   2500\r
106 \r
107 #define KNUTH      2654435761U\r
108 #define MAX_MEM    (1984<<20)\r
109 #define DEFAULT_CHUNKSIZE   (4<<20)\r
110 \r
111 \r
112 //**************************************\r
113 // Local structures\r
114 //**************************************\r
115 struct chunkParameters\r
116 {\r
117     U32   id;\r
118     char* origBuffer;\r
119     char* compressedBuffer;\r
120     int   origSize;\r
121     int   compressedSize;\r
122 };\r
123 \r
124 \r
125 //**************************************\r
126 // MACRO\r
127 //**************************************\r
128 #define DISPLAY(...) fprintf(stderr, __VA_ARGS__)\r
129 \r
130 \r
131 \r
132 //**************************************\r
133 // Benchmark Parameters\r
134 //**************************************\r
135 static int chunkSize = DEFAULT_CHUNKSIZE;\r
136 static int nbIterations = NBLOOPS;\r
137 static int BMK_pause = 0;\r
138 static int compressionTest = 1;\r
139 static int decompressionTest = 1;\r
140 \r
141 void BMK_SetBlocksize(int bsize)\r
142 {\r
143     chunkSize = bsize;\r
144     DISPLAY("-Using Block Size of %i KB-\n", chunkSize>>10);\r
145 }\r
146 \r
147 void BMK_SetNbIterations(int nbLoops)\r
148 {\r
149     nbIterations = nbLoops;\r
150     DISPLAY("- %i iterations -\n", nbIterations);\r
151 }\r
152 \r
153 void BMK_SetPause()\r
154 {\r
155     BMK_pause = 1;\r
156 }\r
157 \r
158 //*********************************************************\r
159 //  Private functions\r
160 //*********************************************************\r
161 \r
162 #if defined(BMK_LEGACY_TIMER)\r
163 \r
164 static int BMK_GetMilliStart()\r
165 {\r
166   // Based on Legacy ftime()\r
167   // Rolls over every ~ 12.1 days (0x100000/24/60/60)\r
168   // Use GetMilliSpan to correct for rollover\r
169   struct timeb tb;\r
170   int nCount;\r
171   ftime( &tb );\r
172   nCount = (int) (tb.millitm + (tb.time & 0xfffff) * 1000);\r
173   return nCount;\r
174 }\r
175 \r
176 #else\r
177 \r
178 static int BMK_GetMilliStart()\r
179 {\r
180   // Based on newer gettimeofday()\r
181   // Use GetMilliSpan to correct for rollover\r
182   struct timeval tv;\r
183   int nCount;\r
184   gettimeofday(&tv, NULL);\r
185   nCount = (int) (tv.tv_usec/1000 + (tv.tv_sec & 0xfffff) * 1000);\r
186   return nCount;\r
187 }\r
188 \r
189 #endif\r
190 \r
191 \r
192 static int BMK_GetMilliSpan( int nTimeStart )\r
193 {\r
194   int nSpan = BMK_GetMilliStart() - nTimeStart;\r
195   if ( nSpan < 0 )\r
196     nSpan += 0x100000 * 1000;\r
197   return nSpan;\r
198 }\r
199 \r
200 \r
201 static size_t BMK_findMaxMem(U64 requiredMem)\r
202 {\r
203     size_t step = (64U<<20);   // 64 MB\r
204     BYTE* testmem=NULL;\r
205 \r
206     requiredMem = (((requiredMem >> 25) + 1) << 26);\r
207     if (requiredMem > MAX_MEM) requiredMem = MAX_MEM;\r
208 \r
209     requiredMem += 2*step;\r
210     while (!testmem)\r
211     {\r
212         requiredMem -= step;\r
213         testmem = (BYTE*) malloc ((size_t)requiredMem);\r
214     }\r
215 \r
216     free (testmem);\r
217     return (size_t) (requiredMem - step);\r
218 }\r
219 \r
220 \r
221 static U64 BMK_GetFileSize(char* infilename)\r
222 {\r
223     int r;\r
224 #if defined(_MSC_VER)\r
225     struct _stat64 statbuf;\r
226     r = _stat64(infilename, &statbuf);\r
227 #else\r
228     struct stat statbuf;\r
229     r = stat(infilename, &statbuf);\r
230 #endif\r
231     if (r || !S_ISREG(statbuf.st_mode)) return 0;   // No good...\r
232     return (U64)statbuf.st_size;\r
233 }\r
234 \r
235 \r
236 //*********************************************************\r
237 //  Public function\r
238 //*********************************************************\r
239 \r
240 static inline int local_LZ4_compress_limitedOutput(const char* in, char* out, int inSize)\r
241 {\r
242     return LZ4_compress_limitedOutput(in, out, inSize, LZ4_compressBound(inSize));\r
243 }\r
244 \r
245 static inline int local_LZ4_compressHC_limitedOutput(const char* in, char* out, int inSize)\r
246 {\r
247     return LZ4_compressHC_limitedOutput(in, out, inSize, LZ4_compressBound(inSize));\r
248 }\r
249 \r
250 static inline int local_LZ4_decompress_fast(const char* in, char* out, int inSize, int outSize)\r
251 {\r
252     (void)inSize;\r
253     LZ4_decompress_fast(in, out, outSize);\r
254     return outSize;\r
255 }\r
256 \r
257 static inline int local_LZ4_decompress_fast_withPrefix64k(const char* in, char* out, int inSize, int outSize)\r
258 {\r
259     (void)inSize;\r
260     LZ4_decompress_fast_withPrefix64k(in, out, outSize);\r
261     return outSize;\r
262 }\r
263 \r
264 static inline int local_LZ4_decompress_safe_partial(const char* in, char* out, int inSize, int outSize)\r
265 {\r
266     return LZ4_decompress_safe_partial(in, out, inSize, outSize - 5, outSize);\r
267 }\r
268 \r
269 int fullSpeedBench(char** fileNamesTable, int nbFiles)\r
270 {\r
271   int fileIdx=0;\r
272   FILE* fileIn;\r
273   char* infilename;\r
274   U64 largefilesize;\r
275   size_t benchedSize;\r
276   int nbChunks;\r
277   int maxCChunkSize;\r
278   size_t readSize;\r
279   char* orig_buff;\r
280   char* compressed_buff; int compressed_buff_size;\r
281   struct chunkParameters* chunkP;\r
282   U32 crcc, crcd=0;\r
283 # define NB_COMPRESSION_ALGORITHMS 4\r
284   static char* compressionNames[] = { "LZ4_compress", "LZ4_compress_limitedOutput", "LZ4_compressHC", "LZ4_compressHC_limitedOutput" };\r
285   double totalCTime[NB_COMPRESSION_ALGORITHMS] = {0};\r
286   double totalCSize[NB_COMPRESSION_ALGORITHMS] = {0};\r
287 # define NB_DECOMPRESSION_ALGORITHMS 5\r
288   static char* decompressionNames[] = { "LZ4_decompress_fast", "LZ4_decompress_fast_withPrefix64k", "LZ4_decompress_safe", "LZ4_decompress_safe_withPrefix64k", "LZ4_decompress_safe_partial" };\r
289   double totalDTime[NB_DECOMPRESSION_ALGORITHMS] = {0};\r
290 \r
291   U64 totals = 0;\r
292 \r
293 \r
294   // Loop for each file\r
295   while (fileIdx<nbFiles)\r
296   {\r
297       // Check file existence\r
298       infilename = fileNamesTable[fileIdx++];\r
299       fileIn = fopen( infilename, "rb" );\r
300       if (fileIn==NULL)\r
301       {\r
302         DISPLAY( "Pb opening %s\n", infilename);\r
303         return 11;\r
304       }\r
305 \r
306       // Memory allocation & restrictions\r
307       largefilesize = BMK_GetFileSize(infilename);\r
308       benchedSize = (size_t) BMK_findMaxMem(largefilesize) / 2;\r
309       if ((U64)benchedSize > largefilesize) benchedSize = (size_t)largefilesize;\r
310       if (benchedSize < largefilesize)\r
311       {\r
312           DISPLAY("Not enough memory for '%s' full size; testing %i MB only...\n", infilename, (int)(benchedSize>>20));\r
313       }\r
314 \r
315       // Alloc\r
316       chunkP = (struct chunkParameters*) malloc(((benchedSize / chunkSize)+1) * sizeof(struct chunkParameters));\r
317       orig_buff = (char*) malloc((size_t)benchedSize);\r
318       nbChunks = (int) (benchedSize / chunkSize) + 1;\r
319       maxCChunkSize = LZ4_compressBound(chunkSize);\r
320       compressed_buff_size = nbChunks * maxCChunkSize;\r
321       compressed_buff = (char*)malloc((size_t)compressed_buff_size);\r
322 \r
323 \r
324       if(!orig_buff || !compressed_buff)\r
325       {\r
326         DISPLAY("\nError: not enough memory!\n");\r
327         free(orig_buff);\r
328         free(compressed_buff);\r
329         fclose(fileIn);\r
330         return 12;\r
331       }\r
332 \r
333       // Init chunks data\r
334       {\r
335           int i;\r
336           size_t remaining = benchedSize;\r
337           char* in = orig_buff;\r
338           char* out = compressed_buff;\r
339           for (i=0; i<nbChunks; i++)\r
340           {\r
341               chunkP[i].id = i;\r
342               chunkP[i].origBuffer = in; in += chunkSize;\r
343               if ((int)remaining > chunkSize) { chunkP[i].origSize = chunkSize; remaining -= chunkSize; } else { chunkP[i].origSize = (int)remaining; remaining = 0; }\r
344               chunkP[i].compressedBuffer = out; out += maxCChunkSize;\r
345               chunkP[i].compressedSize = 0;\r
346           }\r
347       }\r
348 \r
349       // Fill input buffer\r
350       DISPLAY("Loading %s...       \r", infilename);\r
351       readSize = fread(orig_buff, 1, benchedSize, fileIn);\r
352       fclose(fileIn);\r
353 \r
354       if(readSize != benchedSize)\r
355       {\r
356         DISPLAY("\nError: problem reading file '%s' !!    \n", infilename);\r
357         free(orig_buff);\r
358         free(compressed_buff);\r
359         return 13;\r
360       }\r
361 \r
362       // Calculating input Checksum\r
363       crcc = XXH32(orig_buff, (unsigned int)benchedSize,0);\r
364 \r
365 \r
366       // Bench\r
367       {\r
368         int loopNb, nb_loops, chunkNb, cAlgNb, dAlgNb;\r
369         size_t cSize=0;\r
370         double ratio=0.;\r
371 \r
372         DISPLAY("\r%79s\r", "");\r
373         DISPLAY(" %s : \n", infilename);\r
374 \r
375         // Compression Algorithms\r
376         for (cAlgNb=0; (cAlgNb < NB_COMPRESSION_ALGORITHMS) && (compressionTest); cAlgNb++)\r
377         {\r
378             char* cName = compressionNames[cAlgNb];\r
379             int (*compressionFunction)(const char*, char*, int);\r
380             double bestTime = 100000000.;\r
381 \r
382             switch(cAlgNb)\r
383             {\r
384             case 0: compressionFunction = LZ4_compress; break;\r
385             case 1: compressionFunction = local_LZ4_compress_limitedOutput; break;\r
386             case 2: compressionFunction = LZ4_compressHC; break;\r
387             case 3: compressionFunction = local_LZ4_compressHC_limitedOutput; break;\r
388             default : DISPLAY("ERROR ! Bad algorithm Id !! \n"); return 1;\r
389             }\r
390 \r
391             for (loopNb = 1; loopNb <= nbIterations; loopNb++)\r
392             {\r
393                 double averageTime;\r
394                 int milliTime;\r
395 \r
396                 DISPLAY("%1i-%-19.19s : %9i ->\r", loopNb, cName, (int)benchedSize);\r
397                 { size_t i; for (i=0; i<benchedSize; i++) compressed_buff[i]=(char)i; }     // warmimg up memory\r
398 \r
399                 nb_loops = 0;\r
400                 milliTime = BMK_GetMilliStart();\r
401                 while(BMK_GetMilliStart() == milliTime);\r
402                 milliTime = BMK_GetMilliStart();\r
403                 while(BMK_GetMilliSpan(milliTime) < TIMELOOP)\r
404                 {\r
405                     for (chunkNb=0; chunkNb<nbChunks; chunkNb++)\r
406                     {\r
407                         chunkP[chunkNb].compressedSize = compressionFunction(chunkP[chunkNb].origBuffer, chunkP[chunkNb].compressedBuffer, chunkP[chunkNb].origSize);\r
408                         if (chunkP[chunkNb].compressedSize==0) DISPLAY("ERROR ! %s() = 0 !! \n", cName), exit(1);\r
409                     }\r
410                     nb_loops++;\r
411                 }\r
412                 milliTime = BMK_GetMilliSpan(milliTime);\r
413 \r
414                 averageTime = (double)milliTime / nb_loops;\r
415                 if (averageTime < bestTime) bestTime = averageTime;\r
416                 cSize=0; for (chunkNb=0; chunkNb<nbChunks; chunkNb++) cSize += chunkP[chunkNb].compressedSize;\r
417                 ratio = (double)cSize/(double)benchedSize*100.;\r
418                 DISPLAY("%1i-%-19.19s : %9i -> %9i (%5.2f%%),%7.1f MB/s\r", loopNb, cName, (int)benchedSize, (int)cSize, ratio, (double)benchedSize / bestTime / 1000.);\r
419             }\r
420 \r
421             if (ratio<100.)\r
422                 DISPLAY("%-21.21s : %9i -> %9i (%5.2f%%),%7.1f MB/s\n", cName, (int)benchedSize, (int)cSize, ratio, (double)benchedSize / bestTime / 1000.);\r
423             else\r
424                 DISPLAY("%-21.21s : %9i -> %9i (%5.1f%%),%7.1f MB/s\n", cName, (int)benchedSize, (int)cSize, ratio, (double)benchedSize / bestTime / 1000.);\r
425 \r
426             totalCTime[cAlgNb] += bestTime;\r
427             totalCSize[cAlgNb] += cSize;\r
428         }\r
429 \r
430         // Prepare layout for decompression\r
431         for (chunkNb=0; chunkNb<nbChunks; chunkNb++)\r
432         {\r
433             chunkP[chunkNb].compressedSize = LZ4_compress(chunkP[chunkNb].origBuffer, chunkP[chunkNb].compressedBuffer, chunkP[chunkNb].origSize);\r
434             if (chunkP[chunkNb].compressedSize==0) DISPLAY("ERROR ! %s() = 0 !! \n", compressionNames[0]), exit(1);\r
435         }\r
436         { size_t i; for (i=0; i<benchedSize; i++) orig_buff[i]=0; }     // zeroing source area, for CRC checking\r
437 \r
438         // Decompression Algorithms\r
439         for (dAlgNb=0; (dAlgNb < NB_DECOMPRESSION_ALGORITHMS) && (decompressionTest); dAlgNb++)\r
440         {\r
441             char* dName = decompressionNames[dAlgNb];\r
442             int (*decompressionFunction)(const char*, char*, int, int);\r
443             double bestTime = 100000000.;\r
444 \r
445             switch(dAlgNb)\r
446             {\r
447             case 0: decompressionFunction = local_LZ4_decompress_fast; break;\r
448             case 1: decompressionFunction = local_LZ4_decompress_fast_withPrefix64k; break;\r
449             case 2: decompressionFunction = LZ4_decompress_safe; break;\r
450             case 3: decompressionFunction = LZ4_decompress_safe_withPrefix64k; break;\r
451             case 4: decompressionFunction = local_LZ4_decompress_safe_partial; break;\r
452             default : DISPLAY("ERROR ! Bad algorithm Id !! \n"); return 1;\r
453             }\r
454 \r
455             for (loopNb = 1; loopNb <= nbIterations; loopNb++)\r
456             {\r
457                 double averageTime;\r
458                 int milliTime;\r
459 \r
460                 DISPLAY("%1i-%-19.19s : %9i ->\r", loopNb, dName, (int)benchedSize);\r
461 \r
462                 nb_loops = 0;\r
463                 milliTime = BMK_GetMilliStart();\r
464                 while(BMK_GetMilliStart() == milliTime);\r
465                 milliTime = BMK_GetMilliStart();\r
466                 while(BMK_GetMilliSpan(milliTime) < TIMELOOP)\r
467                 {\r
468                     for (chunkNb=0; chunkNb<nbChunks; chunkNb++)\r
469                     {\r
470                         int decodedSize = decompressionFunction(chunkP[chunkNb].compressedBuffer, chunkP[chunkNb].origBuffer, chunkP[chunkNb].compressedSize, chunkP[chunkNb].origSize);\r
471                         if (chunkP[chunkNb].origSize != decodedSize) DISPLAY("ERROR ! %s() == %i != %i !! \n", dName, decodedSize, chunkP[chunkNb].origSize), exit(1);\r
472                     }\r
473                     nb_loops++;\r
474                 }\r
475                 milliTime = BMK_GetMilliSpan(milliTime);\r
476 \r
477                 averageTime = (double)milliTime / nb_loops;\r
478                 if (averageTime < bestTime) bestTime = averageTime;\r
479 \r
480                 DISPLAY("%1i-%-19.19s : %9i -> %7.1f MB/s\r", loopNb, dName, (int)benchedSize, (double)benchedSize / bestTime / 1000.);\r
481             }\r
482 \r
483             // CRC Checking\r
484             crcd = XXH32(orig_buff, (int)benchedSize, 0);\r
485             if (crcc!=crcd) { DISPLAY("\n!!! WARNING !!! %14s : Invalid Checksum : %x != %x\n", infilename, (unsigned)crcc, (unsigned)crcd); exit(1); }\r
486             DISPLAY("%-21.21s : %9i -> %7.1f MB/s\n", dName, (int)benchedSize, (double)benchedSize / bestTime / 1000.);\r
487 \r
488             totalDTime[dAlgNb] += bestTime;\r
489         }\r
490 \r
491         totals += benchedSize;\r
492       }\r
493 \r
494       free(orig_buff);\r
495       free(compressed_buff);\r
496       free(chunkP);\r
497   }\r
498 \r
499   if (nbFiles > 1)\r
500   {\r
501       int AlgNb;\r
502 \r
503       DISPLAY(" ** TOTAL ** : \n");\r
504       for (AlgNb = 0; (AlgNb < NB_COMPRESSION_ALGORITHMS) && (compressionTest); AlgNb ++)\r
505       {\r
506           char* cName = compressionNames[AlgNb];\r
507           DISPLAY("%-21.21s :%10llu ->%10llu (%5.2f%%), %6.1f MB/s\n", cName, (long long unsigned int)totals, (long long unsigned int)totalCSize[AlgNb], (double)totalCSize[AlgNb]/(double)totals*100., (double)totals/totalCTime[AlgNb]/1000.);\r
508       }\r
509       for (AlgNb = 0; (AlgNb < NB_DECOMPRESSION_ALGORITHMS) && (decompressionTest); AlgNb ++)\r
510       {\r
511           char* dName = decompressionNames[AlgNb];\r
512           DISPLAY("%-21.21s :%10llu -> %6.1f MB/s\n", dName, (long long unsigned int)totals, (double)totals/totalDTime[AlgNb]/1000.);\r
513       }\r
514   }\r
515 \r
516   if (BMK_pause) { printf("press enter...\n"); getchar(); }\r
517 \r
518   return 0;\r
519 }\r
520 \r
521 \r
522 int usage(char* exename)\r
523 {\r
524     DISPLAY( "Usage :\n");\r
525     DISPLAY( "      %s [arg] file1 file2 ... fileX\n", exename);\r
526     DISPLAY( "Arguments :\n");\r
527     DISPLAY( " -c     : compression tests only\n");\r
528     DISPLAY( " -d     : decompression tests only\n");\r
529     DISPLAY( " -H     : Help (this text + advanced options)\n");\r
530     return 0;\r
531 }\r
532 \r
533 int usage_advanced()\r
534 {\r
535     DISPLAY( "\nAdvanced options :\n");\r
536     DISPLAY( " -B#    : Block size [4-7](default : 7)\n");\r
537     //DISPLAY( " -BD    : Block dependency (improve compression ratio)\n");\r
538     DISPLAY( " -i#    : iteration loops [1-9](default : 6)\n");\r
539     return 0;\r
540 }\r
541 \r
542 int badusage(char* exename)\r
543 {\r
544     DISPLAY("Wrong parameters\n");\r
545     usage(exename);\r
546     return 0;\r
547 }\r
548 \r
549 int main(int argc, char** argv)\r
550 {\r
551     int i,\r
552         filenamesStart=2;\r
553     char* exename=argv[0];\r
554     char* input_filename=0;\r
555 \r
556     // Welcome message\r
557     DISPLAY( WELCOME_MESSAGE);\r
558 \r
559     if (argc<2) { badusage(exename); return 1; }\r
560 \r
561     for(i=1; i<argc; i++)\r
562     {\r
563         char* argument = argv[i];\r
564 \r
565         if(!argument) continue;   // Protection if argument empty\r
566 \r
567         // Decode command (note : aggregated commands are allowed)\r
568         if (argument[0]=='-')\r
569         {\r
570             while (argument[1]!=0)\r
571             {\r
572                 argument ++;\r
573 \r
574                 switch(argument[0])\r
575                 {\r
576                     // Select compression algorithm only\r
577                 case 'c': decompressionTest = 0; break;\r
578 \r
579                     // Select decompression algorithm only\r
580                 case 'd': compressionTest = 0; break;\r
581 \r
582                     // Display help on usage\r
583                 case 'H': usage(exename); usage_advanced(); return 0;\r
584 \r
585                     // Modify Block Properties\r
586                 case 'B':\r
587                     while (argument[1]!=0)\r
588                     switch(argument[1])\r
589                     {\r
590                     case '4':\r
591                     case '5':\r
592                     case '6':\r
593                     case '7':\r
594                     { \r
595                         int B = argument[1] - '0'; \r
596                         int S = 1 << (8 + 2*B); \r
597                         BMK_SetBlocksize(S); \r
598                         argument++;\r
599                         break;\r
600                     }\r
601                     case 'D': argument++; break;\r
602                     default : goto _exit_blockProperties;\r
603                     }\r
604 _exit_blockProperties:\r
605                     break;\r
606 \r
607                     // Modify Nb Iterations\r
608                 case 'i': \r
609                     if ((argument[1] >='1') && (argument[1] <='9'))\r
610                     {\r
611                         int iters = argument[1] - '0'; \r
612                         BMK_SetNbIterations(iters); \r
613                         argument++;\r
614                     }\r
615                     break;\r
616 \r
617                     // Pause at the end (hidden option)\r
618                 case 'p': BMK_SetPause(); break;\r
619 \r
620                     // Unrecognised command\r
621                 default : badusage(exename); return 1;\r
622                 }\r
623             }\r
624             continue;\r
625         }\r
626 \r
627         // first provided filename is input\r
628         if (!input_filename) { input_filename=argument; filenamesStart=i; continue; }\r
629 \r
630     }\r
631 \r
632     // No input filename ==> Error\r
633     if(!input_filename) { badusage(exename); return 1; }\r
634 \r
635     return fullSpeedBench(argv+filenamesStart, argc-filenamesStart);\r
636 \r
637 }\r
638 \r