/*
This product contains certain software code or other information
("AT&T Software") proprietary to AT&T Corp. ("AT&T").  The AT&T
Software is provided to you "AS IS".  YOU ASSUME TOTAL RESPONSIBILITY
AND RISK FOR USE OF THE AT&T SOFTWARE.  AT&T DOES NOT MAKE, AND
EXPRESSLY DISCLAIMS, ANY EXPRESS OR IMPLIED WARRANTIES OF ANY KIND
WHATSOEVER, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, WARRANTIES OF
TITLE OR NON-INFRINGEMENT OF ANY INTELLECTUAL PROPERTY RIGHTS, ANY
WARRANTIES ARISING BY USAGE OF TRADE, COURSE OF DEALING OR COURSE OF
PERFORMANCE, OR ANY WARRANTY THAT THE AT&T SOFTWARE IS "ERROR FREE" OR
WILL MEET YOUR REQUIREMENTS.

Unless you accept a license to use the AT&T Software, you shall not
reverse compile, disassemble or otherwise reverse engineer this
product to ascertain the source code for any AT&T Software.

(c) AT&T Corp. All rights reserved.  AT&T is a registered trademark of AT&T Corp.

***********************************************************************

History:

      24/11/99  - initial release by Hartmut Liefke, liefke@seas.upenn.edu
                                     Dan Suciu,      suciu@research.att.com
*/

//**************************************************************************
//**************************************************************************

// This module implements 'Compressor' and 'Uncompressor' -
// the interfaces to the ZLIB (either gzip or bzip) libary

#include "stdafx.h"

#ifdef _DEBUG
int totaldecomp = 0;
int complen = 0;
int numheaders = 0;
//char buffer[200*1024];
#endif

/* find a string in piece of binary memory, like strstr() */
static char *memstr(char *mem, int len, char *str)
{
	int i = 0, slen = strlen(str);

	while (i <= len-slen) {
		if (!memcmp(&mem[i], str, slen))
			return &mem[i];
		i++;
	}

	return NULL;
}

NoZip::NoZip(int idx, bool iscomp): Zipper(idx, iscomp) 
{
	availout = 65536;
	resetTotals();
	initialized = false;
}

NoZip::~NoZip()
{}

void NoZip::initCompress()
{
	initialized = false;
}

void NoZip::setCompPtrs(char *nextout, char* nextin, int availin)
{
	this->nextout = nextout;
	this->nextin = nextin;
	this->availin = availin;
}

int NoZip::doCompress(int flag)
{
	int offset = 0;
	int len = min(availin, availout);

	if (availin == 0) {
		/* store end-of-stream marker */
		offset = sizeof(XMILL_HEADER_NOZIP)-1;
		memcpy(nextout, XMILL_HEADER_NOZIP, offset);
		totalout += offset;
		availout -= offset;
#ifdef _DEBUGPRINT
		printf("stored footer %ld at %ld\n", numheaders, complen);
#endif
		return BZ_STREAM_END;
	}

	if (!initialized) {
		/* store begin-of-stream marker */
		offset = sizeof(XMILL_HEADER_NOZIP)-1;
		availout -= offset;
		totalout += offset;
		memcpy(nextout, XMILL_HEADER_NOZIP, offset);
		initialized = true;
#ifdef _DEBUGPRINT
		printf("stored header %ld at %ld\n", ++numheaders, complen);
#endif
	}
	totalin += len;
	totalout += len;
	memcpy(nextout+offset, nextin, len);
	if (availin > availout)
		nextin += len;

#if 0
	char *headerptr = NULL;
	if ((headerptr = memstr(nextin, len, "Cheer"))) {
		int a = 1;
	}
#endif

#ifdef _DEBUG
	//memcpy(&buffer[complen], nextin, len);
	complen += len;
#endif
	availin -= len;
	availout -= len;
	if (flag == -1)
		return BZ_OK;
	else
		return BZ_RUN_OK;
}

void NoZip::endCompress()
{
	initialized = false;
}

void NoZip::initUncompress()
{
	initialized = false;
}

void NoZip::setUncompPtrs(char *nextout, int availout, int availin)
{
	this->nextout = nextout;
	this->availout = availout;
	this->availin = availin;
}

int NoZip::doUncompress()
{
	int offset = 0, off = 0;
	char *headerptr = NULL;

	if (availin == 0)
		return BZ_STREAM_END;

	if (!initialized) {
		/* check for begin-of-stream header */
		off = sizeof(XMILL_HEADER_NOZIP)-1;
		if (!strncmp(nextin, XMILL_HEADER_NOZIP, off)) {
			initialized = true;
			availin -= off;
#ifdef _DEBUGPRINT
			printf("found a header at %ld\n", totaldecomp);
#endif
		} else {
			off = 0;
		}
	}
	int len = min(availin, availout);

	/* check for end-of-stream header */
	offset = sizeof(XMILL_HEADER_NOZIP)-1;
	if ((headerptr = memstr(nextin+off, len, XMILL_HEADER_NOZIP))) {
		/* yep, found header somewhere, don't read any further */
		len = headerptr-(nextin+off);
	} else {
		offset = 0;
	}

	totalin += len;
	totalout += len;
	memcpy(nextout, nextin+off, len);

#if 0
	char *header = NULL;
	if ((header = memstr(nextin+off, len, "Cheer"))) {
		int a = 1;
	}
#endif

	nextout += len;
	availin -= len;
	availout -= len;

#ifdef _DEBUGPRINT
	/*if (memcmp(&buffer[totaldecomp], nextin+off, len)) {
		int i = 1;
	}*/
	totaldecomp += len;
	printf("total decompressed: %ld Bytes (header: %ld, current: %ld)\n", 
		totaldecomp, offset + off, len);
#endif

	/* check for end-of-stream header */
	offset = sizeof(XMILL_HEADER_NOZIP)-1;
	if (!memcmp(nextin+off+len, XMILL_HEADER_NOZIP, offset)) {
		/* yep, found header at the end */
		availin -= offset;
		totalin += offset;
		initialized = false;
#ifdef _DEBUGPRINT
		if (!strncmp(nextin+off+len+offset, XMILL_HEADER_NOZIP, offset)) {
			printf("found footer/header combo %ld at %ld\n", 
				++numheaders, totaldecomp);
		} else {
			printf("found final footer %ld at %ld\n", 
				++numheaders, totaldecomp);
		}
#endif
	}
	if (headerptr) {
		return BZ_STREAM_END;
	} else {
		return BZ_OK;
	}
}

void NoZip::endUncompress()
{
	initialized = false;
}

void NoZip::setNextOut(char* nextout)
{
	this->nextout = nextout;
}

void NoZip::setNextIn(char* nextin)
{
	this->nextin = nextin;
}

char **NoZip::getNextInPtr()
{
	return &nextin;
}

void NoZip::setAvailIn(int availin)
{
	this->availin = availin;
}

int NoZip::getAvailIn()
{
	return availin;
}

int* NoZip::getAvailInPtr()
{
	return &availin;
}

int NoZip::getAvailOut()
{
	return availout;
}

int* NoZip::getAvailOutPtr()
{
	return &availout;
}

int NoZip::getTotalOut()
{
	return totalout;
}

int NoZip::getTotalIn()
{
	return totalin;
}

void NoZip::resetTotals()
{
	totalin = 0;
	totalout = 0;
}

