Pastebin

Paste #622: quick.c

< previous paste - next paste>

Pasted by Anonymous Coward

Download View as text

/*
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


Do not write anything in this field if you're a human.

Go to most recent paste.