/*
========================
idLZWCompressor::Start
========================
*/
void idLZWCompressor::Start( uint8 * data_, int maxSize_, bool append ) {
	// Clear hash
	ClearHash();
	
	if ( append ) {
		assert( lzwData->nextCode > LZW_FIRST_CODE );
		
		int originalNextCode = lzwData->nextCode;

		lzwData->nextCode = LZW_FIRST_CODE;
		
		// If we are appending, then fill up the hash
		for ( int i = LZW_FIRST_CODE; i < originalNextCode; i++ ) {
			AddToDict( lzwData->dictionaryW[i], lzwData->dictionaryK[i] );
		}
	
		assert( originalNextCode == lzwData->nextCode );
	} else {
		for ( int i = 0; i < LZW_FIRST_CODE; i++ ) {
			lzwData->dictionaryK[i] = (uint8)i;
			lzwData->dictionaryW[i] = 0xFFFF;
		}

		lzwData->nextCode		= LZW_FIRST_CODE;
		lzwData->codeBits		= LZW_START_BITS;
		lzwData->codeWord		= -1;
		lzwData->tempValue		= 0;
		lzwData->tempBits		= 0;
		lzwData->bytesWritten	= 0;
	}
		
	oldCode		= -1;		// Used by DecompressBlock
	data		= data_;

	blockSize	= 0;
	blockIndex	= 0;
	
	bytesRead	= 0;
	
	maxSize		= maxSize_;
	overflowed	= false;

	savedBytesWritten	= 0;
	savedCodeWord		= 0;
	saveCodeBits		= 0;
	savedTempValue		= 0;
	savedTempBits		= 0;
}
/*
========================
idLZWCompressor::DecompressBlock
========================
*/
void idLZWCompressor::DecompressBlock()
{
	assert( blockIndex == blockSize );		// Make sure we've read all we can
	
	blockIndex = 0;
	blockSize = 0;
	
	int firstChar = -1;
	while( blockSize < LZW_BLOCK_SIZE - lzwCompressionData_t::LZW_DICT_SIZE )
	{
		assert( lzwData->codeBits <= lzwCompressionData_t::LZW_DICT_BITS );
		
		int code = ReadBits( lzwData->codeBits );
		if( code == -1 )
		{
			break;
		}
		
		if( oldCode == -1 )
		{
			assert( code < 256 );
			block[blockSize++] = ( uint8 )code;
			oldCode = code;
			firstChar = code;
			continue;
		}
		
		if( code >= lzwData->nextCode )
		{
			assert( code == lzwData->nextCode );
			firstChar = WriteChain( oldCode );
			block[blockSize++] = ( uint8 )firstChar;
		}
		else
		{
			firstChar = WriteChain( code );
		}
		AddToDict( oldCode, firstChar );
		if( BumpBits() )
		{
			oldCode = -1;
		}
		else
		{
			oldCode = code;
		}
	}
}
/*
========================
idLZWCompressor::WriteByte
========================
*/
void idLZWCompressor::WriteByte( uint8 value ) {
	int code = Lookup( lzwData->codeWord, value );
	if ( code >= 0 ) {
		lzwData->codeWord = code;
	} else {
		WriteBits( lzwData->codeWord, lzwData->codeBits );
		if ( !BumpBits() ) {
			AddToDict( lzwData->codeWord, value );
		}
		lzwData->codeWord = value;
	}

	if ( lzwData->bytesWritten >= maxSize - ( lzwData->codeBits + lzwData->tempBits + 7 ) / 8 ) {
		overflowed = true;	// At any point, if we can't perform an End call, then trigger an overflow
		return;
	}
}