1
1
#include < stdio.h>
2
+ #include < stdlib.h>
3
+ #include < string.h>
2
4
#include < time.h>
3
5
4
6
// includes for file enumeration
5
7
#if _WIN32
6
8
# include < io.h> // for findfirst() set
9
+ # ifndef _WIN64
10
+ # define PLATFORM " win32"
11
+ # else
12
+ # define PLATFORM " win64"
13
+ # endif
7
14
#else
8
15
# include < dirent.h> // for opendir() etc
9
16
# include < sys/stat.h> // for stat()
17
+ # define stricmp strcasecmp
18
+ # define strnicmp strncasecmp
19
+ # define PLATFORM " unix"
10
20
#endif
11
21
12
22
#include < vector>
21
31
#define MAX_ITERATIONS 1 // number of passes to fully fill buffer, i.e. total processed data size will be up to (BUFFER_SIZE * MAX_ITERATIONS)
22
32
#define COMPRESS_LEVEL 9
23
33
34
+ #if _WIN32
35
+
36
+ #include < windows.h>
37
+
38
+ static HMODULE zlibDll = NULL ;
39
+
40
+ static gzFile gzopen_imp (const char * filename, const char * params)
41
+ {
42
+ if (zlibDll)
43
+ {
44
+ typedef gzFile (WINAPI *gzopen_f)(const char * filename, const char * params);
45
+ static gzopen_f gzopen_ptr = NULL ;
46
+ if (gzopen_ptr == NULL )
47
+ {
48
+ gzopen_ptr = (gzopen_f)GetProcAddress (zlibDll, " gzopen" );
49
+ // assert(gzopen_ptr);
50
+ }
51
+ return gzopen_ptr (filename, params);
52
+ }
53
+ else
54
+ {
55
+ return gzopen (filename, params);
56
+ }
57
+ }
58
+
59
+ static int gzwrite_imp (gzFile file, voidpc buf, unsigned len)
60
+ {
61
+ if (zlibDll)
62
+ {
63
+ typedef int (WINAPI *gzwrite_f)(gzFile file, voidpc buf, unsigned len);
64
+ static gzwrite_f gzwrite_ptr = NULL ;
65
+ if (gzwrite_ptr == NULL )
66
+ {
67
+ gzwrite_ptr = (gzwrite_f)GetProcAddress (zlibDll, " gzwrite" );
68
+ // assert(gzwrite_ptr);
69
+ }
70
+ return gzwrite_ptr (file, buf, len);
71
+ }
72
+ else
73
+ {
74
+ return gzwrite (file, buf, len);
75
+ }
76
+ }
77
+
78
+ static int gzclose_imp (gzFile file)
79
+ {
80
+ if (zlibDll)
81
+ {
82
+ typedef int (WINAPI *gzclose_f)(gzFile file);
83
+ static gzclose_f gzclose_ptr = NULL ;
84
+ if (gzclose_ptr == NULL )
85
+ {
86
+ gzclose_ptr = (gzclose_f)GetProcAddress (zlibDll, " gzclose" );
87
+ // assert(gzclose_ptr);
88
+ }
89
+ return gzclose_ptr (file);
90
+ }
91
+ else
92
+ {
93
+ return gzclose (file);
94
+ }
95
+ }
96
+
97
+ // Hook gzip functions
98
+ #define gzopen gzopen_imp
99
+ #define gzwrite gzwrite_imp
100
+ #define gzclose gzclose_imp
101
+
102
+ #endif // _WIN32
103
+
24
104
std::vector<std::string> fileList;
105
+ std::vector<std::string> fileExclude;
106
+
107
+ static bool IsFileExcluded (const char * filename)
108
+ {
109
+ for (int i = 0 ; i < fileExclude.size (); i++)
110
+ {
111
+ if (!stricmp (filename, fileExclude[i].c_str ()))
112
+ return true ;
113
+ }
114
+ return false ;
115
+ }
25
116
26
117
static bool ScanDirectory (const char *dir, bool recurse = true )
27
118
{
@@ -37,6 +128,7 @@ static bool ScanDirectory(const char *dir, bool recurse = true)
37
128
{
38
129
if (found.name [0 ] == ' .' ) continue ; // "." or ".."
39
130
sprintf (Path, " %s/%s" , dir, found.name );
131
+ if (IsFileExcluded (Path)) continue ;
40
132
// directory -> recurse
41
133
if (found.attrib & _A_SUBDIR)
42
134
{
@@ -60,6 +152,7 @@ static bool ScanDirectory(const char *dir, bool recurse = true)
60
152
{
61
153
if (ent->d_name [0 ] == ' .' ) continue ; // "." or ".."
62
154
sprintf (Path, " %s/%s" , dir, ent->d_name );
155
+ if (IsFileExcluded (Path)) continue ;
63
156
// directory -> recurse
64
157
// note: using 'stat64' here because 'stat' ignores large files
65
158
struct stat64 buf;
@@ -113,19 +206,100 @@ int main(int argc, const char **argv)
113
206
{
114
207
if (argc <= 1 )
115
208
{
116
- printf (" Usage: test <directory>\n " );
209
+ usage:
210
+ printf (
211
+ " Usage: test [options] <directory>\n "
212
+ " Options:\n "
213
+ " --level=[0-9] set compression level, default 9\n "
214
+ " --exclude=<dir> exclude specified directory from tests\n "
215
+ #if _WIN32
216
+ " --dll=<file> use external WINAPI zlib dll\n "
217
+ #endif
218
+ " --compact use compact output\n "
219
+ " --delete erase compressed file after completion\n "
220
+ );
117
221
return 1 ;
118
222
}
119
223
120
- ScanDirectory (argv[1 ]);
224
+ // parse command line
225
+ const char * dirName = NULL ;
226
+ char level = ' 9' ;
227
+ bool compactOutput = false ;
228
+ bool eraseCompressedFile = false ;
229
+
230
+ for (int i = 1 ; i < argc; i++)
231
+ {
232
+ const char * arg = argv[i];
233
+ if (arg[0 ] == ' -' && arg[1 ] == ' -' )
234
+ {
235
+ // option
236
+ arg += 2 ; // skip "--"
237
+ if (!strnicmp (arg, " level=" , 6 ))
238
+ {
239
+ if (!(level >= ' 0' && level <= ' 9' )) goto usage;
240
+ level = arg[6 ];
241
+ }
242
+ else if (!strnicmp (arg, " exclude=" , 8 ))
243
+ {
244
+ fileExclude.push_back (arg+8 );
245
+ }
246
+ else if (!stricmp (arg, " compact" ))
247
+ {
248
+ compactOutput = true ;
249
+ }
250
+ else if (!stricmp (arg, " delete" ))
251
+ {
252
+ eraseCompressedFile = true ;
253
+ }
254
+ #if _WIN32
255
+ else if (!strnicmp (arg, " dll=" , 4 ))
256
+ {
257
+ if (zlibDll != NULL ) goto usage;
258
+ zlibDll = LoadLibrary (arg+4 );
259
+ if (zlibDll == NULL )
260
+ {
261
+ printf (" Error: unable to load zlib.dll %s\n " , arg+4 );
262
+ exit (1 );
263
+ }
264
+ }
265
+ #endif // _WIN32
266
+ else
267
+ {
268
+ goto usage;
269
+ }
270
+ }
271
+ else
272
+ {
273
+ if (dirName) goto usage;
274
+ dirName = arg;
275
+ }
276
+ }
277
+
278
+ if (!dirName)
279
+ {
280
+ printf (" Error: directory name was not specified\n " );
281
+ exit (1 );
282
+ }
283
+
284
+ // prepare data for compression
285
+ ScanDirectory (dirName);
286
+ if (fileList.size () == 0 )
287
+ {
288
+ printf (" Error: the specified location has no files\n " );
289
+ exit (1 );
290
+ }
121
291
// printf("%d files\n", fileList.size());
122
292
123
293
clock_t clocks = 0 ;
124
294
125
- const char * compressedFile = " compressed-" STR (VERSION) " .gz" ;
126
- gzFile gz = gzopen (compressedFile, " wb" STR (COMPRESS_LEVEL));
295
+ // open compressed stream
296
+ char initString[4 ] = " wb" ;
297
+ const char * compressedFile = " compressed-" STR (VERSION) " -" PLATFORM " .gz" ;
298
+ initString[2 ] = level;
299
+ gzFile gz = gzopen (compressedFile, initString);
127
300
int iteration = 0 ;
128
301
int totalDataSize = 0 ;
302
+ // perform compression
129
303
while (FillBuffer () && iteration < MAX_ITERATIONS)
130
304
{
131
305
clock_t clock_a = clock ();
@@ -134,16 +308,38 @@ int main(int argc, const char **argv)
134
308
iteration++;
135
309
totalDataSize += bytesInBuffer;
136
310
}
311
+ // close compressed stream
137
312
gzclose (gz);
138
313
314
+ // determine size of compressed data
139
315
FILE* f = fopen (compressedFile, " rb" );
140
316
fseek (f, 0 , SEEK_END);
141
317
int compressedSize = ftell (f);
142
318
fclose (f);
143
319
144
- printf (" Compressed %.1f Mb of data by method %s with level %d (%s)\n " , (float )totalDataSize / (1024 *1024 ), STR (VERSION), COMPRESS_LEVEL, argv[1 ]);
145
- printf (" Time: %.1f s\n " , clocks / (float )CLOCKS_PER_SEC);
146
- printf (" Size: %d\n " , compressedSize);
320
+ // erase compressed file
321
+ if (eraseCompressedFile)
322
+ {
323
+ remove (compressedFile);
324
+ }
325
+
326
+ // print results
327
+ const char * method = STR (VERSION);
328
+ #if _WIN32
329
+ if (zlibDll) method = " DLL" ;
330
+ #endif
331
+ float time = clocks / (float )CLOCKS_PER_SEC;
332
+ float originalSizeMb = totalDataSize / double (1 <<20 );
333
+ if (!compactOutput)
334
+ {
335
+ printf (" Compressed %.1f Mb of data by method %s with level %c (%s)\n " , originalSizeMb, method, level, dirName);
336
+ }
337
+ else
338
+ {
339
+ printf (" %6s:%c Data: %.1f Mb " , method, level, originalSizeMb);
340
+ }
341
+ printf (" Time: %-5.1f s Size: %d bytes Speed: %5.2f Mb/s Ratio: %.2f\n " ,
342
+ time , compressedSize, totalDataSize / double (1 <<20 ) / time , (double )totalDataSize / compressedSize);
147
343
148
344
return 0 ;
149
345
}
0 commit comments