Pastebin
Paste #622: quick.c
< previous paste - next paste>
Pasted by Anonymous Coward
/*
Demo project for the QuickLZ 1.30 data compression library
Originally with copyright by Lasse Reinhold, but now public domain! No copyright
pending. Do whatever you wish with this source - commercially, non-commercially,
open or closed source.
Be aware that only this particular file is public domain, not the quicklz.c
compression library itself.
The file is written for Visual C++ and is using Windows API.
*/
#include <stdio.h>
#include "../../quicklz.c"
#include <time.h>
#include <windows.h>
// read and compress files in 65536/2 byte chunks
unsigned int chunksize = 65536/2;
// we allocate ~4 MB so that we can also decompress files that were compressed with other
// chunk sizes (may give some disk I/O speed gain)
#define MAX_CHUNKSIZE 4000000
char src[MAX_CHUNKSIZE];
// quicklz needs "uncompressed size" + 400 byte dst buffer when using streaming compression
char dst[MAX_CHUNKSIZE + 400];
char src_cmd[1000];
char dst_cmd[1000];
// SCRATCH is defined in quicklz.c
char scratch[SCRATCH];
HANDLE ofile;
// benchmarking variables
long long total = 0;
unsigned int last_tick = 0;
long long last_total = 0;
unsigned int Bs = 0;
long long files = 0;
void inmem(char *source_file)
{
char *src, *dst;
unsigned int j, y;
FILE *ifile;
size_t i, u;
double mbs, fastest;
ifile = fopen(source_file, "rb");
if (ifile == 0)
{
printf("Error reading source file.\n");
exit(-1);
}
src = (char*)malloc(80000001);
dst = (char*)malloc(80000001 + 400); // destination buffer must be size + 36000 bytes
if(src == 0 || dst == 0)
{
printf("Error allocating memory.\n");
exit(-1);
}
printf("Reading source file...\n");
i = fread(src, 1, 80000001, ifile);
if (i == 80000001)
{
printf("File too large.\n");
exit(-1);
}
printf("Setting HIGH_PRIORITY_CLASS...\n");
SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);
printf("Benchmarking, please wait...\n");
fastest = 0.0;
for (j = 0; j < 1; j++)
{
y = 0;
mbs = GetTickCount();
while(GetTickCount() == mbs);
mbs = GetTickCount();
while(GetTickCount() - mbs < 3000) // 1% accuracy with 18.2 timer
{
u = qlz_compress(src, dst, i, scratch);
y++;
}
mbs = ((double)i*(double)y)/((double)(GetTickCount() - mbs)/1000.)/1000000.;
if (fastest < mbs)
fastest = mbs;
}
printf("\nCompressed %d bytes into %d bytes (%.1f%%) at %.1f Mbyte/s.\n", (unsigned int)i, (unsigned int)u, (double)u/(double)i*100., fastest);
fastest = 0.0;
for (j = 0; j < 1; j++)
{
y = 0;
mbs = GetTickCount();
while(GetTickCount() == mbs);
mbs = GetTickCount();
while(GetTickCount() - mbs < 3000)
{
u = qlz_decompress(dst, src, scratch);
y++;
}
mbs = ((double)i*(double)y)/((double)(GetTickCount() - mbs)/1000.)/1000000.;
if (fastest < mbs)
fastest = mbs;
}
printf("\nDecompressed at %.1f Mbyte/s.\n\n(1 MB = 1000000 byte)\n", fastest);
}
print_delimiter(long long l)
{
char s[20];
char d[20];
int i, j = 0;
memset(s, 0, 20);
memset(d, 0, 20);
sprintf(s, "%lld", l);
for(i = 0; i < strlen(s); i++)
{
if((strlen(s) - i) % 3 == 0 && i != 0)
{
d[j] = '.';
j++;
}
d[j] = s[i];
j++;
}
printf("%s", d);
}
void update_statusbar(int y)
{
if (total - last_total > 1000000)
{
if (GetTickCount() - last_tick > 3000)
{
Bs = (unsigned int)((total - last_total) / (GetTickCount() - last_tick));
last_tick = GetTickCount();
last_total = total;
}
if(y == 1)
printf(" Read %lld MB, %d MB/s \r", total >> 20, Bs >> 10);
else
printf(" Written %lld MB, %d MB/s \r", total >> 20, Bs >> 10);
}
}
void decompress(char *destination_file, HANDLE ifile)
{
DWORD i, s;
HANDLE oofile = CreateFile(destination_file, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
if (oofile == INVALID_HANDLE_VALUE)
{
printf("Error opening destination file '%s'.\n", destination_file);
exit(-1);
}
files++;
for(;;)
{
update_statusbar(2);
ReadFile(ifile, src, 1, &i, 0);
if (*src != 'B')
break;
ReadFile(ifile, src, 9, &i, 0);
ReadFile(ifile, src + 9, (DWORD)qlz_size_compressed(src) - 9, &i, 0);
i = (DWORD)qlz_decompress(src, dst, scratch);
total += i;
if (i == 0)
{
printf("Source file is corrupted, does not contain QuickLZ data or is version incompatible.\n");
exit(-1);
}
WriteFile(oofile, dst, i, &s, 0);
if (s != i)
{
printf("Disk full while writing destination file '%s'.\n", destination_file);
exit(-1);
}
}
CloseHandle(oofile);
}
void compress(char *source_file, FILE *ofile)
{
unsigned int u;
DWORD dummy, w, i;
HANDLE ifile;
ifile = CreateFile(source_file, GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0);
if (ifile == INVALID_HANDLE_VALUE)
{
printf("Error opening source file '%s'.\n", source_file);
exit(-1);
}
files++;
do
{
update_statusbar(1);
ReadFile(ifile, src, chunksize, &i, 0);
if (i == 0)
{
WriteFile(ofile, "E", 1, &dummy, NULL);
CloseHandle(ifile);
return;
}
total += i;
u = (unsigned int)qlz_compress(src, dst, (size_t)i, scratch);
WriteFile(ofile, "B", 1, &dummy, NULL);
WriteFile(ofile, dst, u, &w, NULL);
if (w != u)
{
printf("Disk full while writing destination file.\n");
exit(-1);
}
} while ((unsigned int)i == chunksize);
WriteFile(ofile, "E", 1, &dummy, NULL);
CloseHandle(ifile);
}
void listdir(char *basedir, char *pattern, int recursive)
{
char path[2000];
char t[2000];
WIN32_FIND_DATA dir;
HANDLE dp;
unsigned int blocklen;
DWORD dummy;
strcpy(t, basedir);
strcat(t, "\\");
strcat(t, pattern);
dp = FindFirstFile(t, &dir);
if ((dp != INVALID_HANDLE_VALUE))
{
do
{
if (!(dir.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
{
strcpy(path, basedir);
strcat(path, "\\");
strcat(path, dir.cFileName);
if (strcmp(path, dst_cmd) != 0)
{
printf(" %s \n", dir.cFileName);
WriteFile(ofile, "F", 1, &dummy, NULL);
blocklen = (unsigned int)strlen(dir.cFileName);
WriteFile(ofile, &blocklen, 4, &dummy, NULL); // dummy needed on Me, 98, 95
WriteFile(ofile, dir.cFileName, (unsigned int)strlen(dir.cFileName) + 1, &dummy, NULL); // dummy needed on Me, 98, 95
compress(path, ofile);
}
}
} while (FindNextFile(dp, &dir) != 0);
}
if(recursive == 1)
{
strcpy(t, basedir);
strcat(t, "\\");
strcat(t, "*");
dp = FindFirstFile(t, &dir);
if (dp != INVALID_HANDLE_VALUE)
{
do
{
if(dir.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY && strcmp(dir.cFileName, ".") != 0 && strcmp(dir.cFileName, "..") != 0)
{
printf("%s \n", basedir);
WriteFile(ofile, "D", 1, &dummy, NULL);
blocklen = (unsigned int)strlen(dir.cFileName);
WriteFile(ofile, &blocklen, 4, &dummy, NULL); // dummy needed on Me, 98, 95
WriteFile(ofile, dir.cFileName, (unsigned int)strlen(dir.cFileName) + 1, &dummy, NULL); // dummy needed on Me, 98, 95
strcpy(path, basedir);
strcat(path, "\\");
strcat(path, dir.cFileName);
listdir(path, pattern, recursive);
}
} while (FindNextFile(dp, &dir) != 0);
}
}
WriteFile(ofile, "U", 1, &dummy, NULL);
return;
}
void dirtree(FILE *ifile, char *extractdir)
{
char c;
char curdir[2000];
char buf[2000];
char buf2[2000];
DWORD r = 0, i = 0;
unsigned int blocklen;
strcpy(curdir, extractdir);
for(;;)
{
ReadFile(ifile, &c, 1, &r, 0);
if (r == 0)
return;
if(c == 'D')
{
ReadFile(ifile, &blocklen, 4, &i, 0);
ReadFile(ifile, buf, blocklen + 1, &i, 0);
strcat(curdir, "\\");
strcat(curdir, buf);
printf("%s \n", curdir);
CreateDirectory(curdir, 0);
}
else if(c == 'U')
{
char *s = strrchr(curdir, '\\');
if (s != 0)
*s = 0;
}
else if(c == 'F')
{
ReadFile(ifile, &blocklen, 4, &i, 0);
ReadFile(ifile, buf, blocklen + 1, &i, 0);
strcpy(buf2, curdir);
strcat(buf2, "\\");
strcat(buf2, buf);
printf(" %s \n", buf);
decompress(buf2, ifile);
}
else
{
printf ("\nInternal error.\n");
exit(-1);
}
}
}
void prepend_curdir(char *src, char *dst)
{
char *s = strrchr(src, '\\');
if (s == 0)
{
GetCurrentDirectory(1000, dst);
if (strrchr(dst, '\\') != src + strlen(src))
strcat(dst, "\\");
strcat(dst, src);
}
else
strcpy(dst, src);
}
int main(int argc, char* argv[])
{
char tmp[15];
DWORD dummy;
memset(scratch, 0, SCRATCH);
if (argc == 3 && strcmp(argv[1], "-mem") == 0)
inmem(argv[2]);
else if (argc == 4 && strcmp(argv[1], "-d") == 0)
{
// decompress
HANDLE ifile;
char *s = (strrchr(argv[3], '\\'));
if (s == argv[3] + strlen(argv[3]) - 1)
*s = 0;
ifile = CreateFile(argv[2], GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if (ifile == INVALID_HANDLE_VALUE)
{
printf("Error opening source file '%s'.\n", argv[2]);
exit(-1);
}
ReadFile(ifile, tmp, 15, &dummy, 0);
if (strcmp(tmp, "qlzdemo120_000\0") != 0)
{
printf("Source file is corrupted, does not contain QuickLZ data or is version incompatible.\n");
exit(-1);
}
dirtree(ifile, argv[3]);
CloseHandle(ifile);
printf(" \nWrote ");
print_delimiter(total);
printf(" bytes in %lld file(s).\n", files);
}
else if ((argc == 3 || (argc == 4 && strcmp(argv[3], "-r") == 0)) && strcmp(argv[1], "-d") != 0)
{
// compress
char *s;
prepend_curdir(argv[1], src_cmd);
prepend_curdir(argv[2], dst_cmd);
s = strrchr(src_cmd, '\\');
*s = 0;
ofile = CreateFile(dst_cmd, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
if (ofile == INVALID_HANDLE_VALUE)
{
printf("Error creating destination file '%s'.\n", dst_cmd);
exit(-1);
}
WriteFile(ofile, "qlzdemo120_000\0", 15, &dummy, 0);
if(argc == 3)
listdir(src_cmd, s + 1, 0);
else
listdir(src_cmd, s + 1, 1);
CloseHandle(ofile);
printf(" \nCompressed ");
print_delimiter(total);
printf(" bytes in %lld file(s).\n", files);
}
else
printf("QuickLZ 1.30 BETA 1. Copyright 2006-2007 Lasse Reinhold.\n\nCompiled with COMPRESSION_LEVEL = %d\n\nTo compress: quick <source file search pattern> <destination file> [-r] \nTo decompress: quick -d <source file> <destination directory>\nTo perform an in-memory benchmark: quick -mem <source file> (max. 80 Mbyte)\n\nThe -r flag will search for files recursively in sub directories, preserving\nthe directory structure, also preserving sub directories with no matching files.\n\nAt decompression, existing files are overwritten with no warning.\n\nExamples of compression:\n quick database.xml c:\\backup.qlz\n quick c:\\database\\\?\?-Sep-2007.dat c:\\backup.qlz -r\n quick * backup.qlz -r\n quick \"c:\\space in names\\data.txt\" \"c:\\my backup.qlz\"\n", COMPRESSION_LEVEL);
}
New Paste
Go to most recent paste.