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.