#ifndef engine_h
#define engine_h

#define MAX_LZW_BITS    13      /* maximum LZW code size (8192 symbols) */
#define LZW_TABLE_SIZE  ((int) 1 << MAX_LZW_BITS)
#define HSIZE           10009    /* hash table size for 80% occupancy THIS MUST BE PRIME*/
#define MAXCODE(n_bits) (((int) 1 << (n_bits)) - 1)

/* Macros for extracting header data --- note we assume chars may be signed */

#define UINT8 unsigned char
typedef unsigned char byte;
#define UINT16 unsigned short
#define READ_MAX 8192



class ComDecEngine
{
	private:
/* vars used by both comrpession and decression */
		BOOL bEncrypt;

/* FOR DECOMPRESSION */
		HFILE hInFile;
		BYTE *SrcPtr;
		int SrcLeft;
		int InputType;
		unsigned char Buffer[READ_MAX+2];
		unsigned char *DestPtr;

		int last_byte;           /* # of bytes in code_buf */
		int last_bit;            /* # of bits in code_buf */
		int cur_bit;             /* next bit index to read */
		int out_of_blocks;   /* TRUE if hit terminator data block */

		int input_code_size; 	 /* codesize given in GIF file */
		int clear_code,end_code; /* values for Clear and End codes */

		int code_size;           /* current actual code size */
		int limit_code;          /* 2^code_size */
		int max_code;            /* first unused code value */
		int first_time;      /* flags first call to LZWReadByte */
		int oldcode;           /* previous LZW symbol */
		int firstcode;         /* first byte of oldcode's expansion */

		UINT16 *symbol_head; /* => table of prefix symbols */
		UINT8  *symbol_tail; /* => table of suffix bytes */
		UINT8  symbol_stack[8192]; /* stack for symbol expansions */
		UINT8  *sp;          /* stack pointer */


/* FOR COMPRESSION */
		HFILE hOutFile;
		short n_bits;              /* current number of bits/code */
		short maxcode;        /* maximum code, given n_bits */
		short init_bits;           /* initial n_bits ... restored after clear */
		short ClearCode;      /* clear code (doesn't change) */
		short EOFCode;        /* EOF code (ditto) */
		short free_code;      /* first not-yet-used symbol code */

		short hash_code[HSIZE]; /* => hash table of symbol codes */
		short hash_prefix[HSIZE]; /* => hash table of prefix symbols */
		UINT8 hash_suffix[HSIZE];  /* => hash table of suffix bytes */
		short bytesinpkt;          /* # of bytes in current packet */
		char packetbuf[256];     /* workspace for accumulating packet */
		int cur_accum;         /* holds bits not yet output */
		short cur_bits;            /* # of bits in cur_accum */
		short waiting_code;   /* symbol not yet output; may be extendable */
		int first_byte;      /* if TRUE, waiting_code is not valid */


/* internal methods for decompression */
		void ReInitLZW(void);
		void InitLZWCode(void);
		int GetDataBlock(void);
		int GetCode(void);
		int LZWReadByte(void);

/* internal methods for compression */
		void flush_packet(void);
		void output(short code);
		void clear_hash(void);
		void clear_block(void);
	  void compress_init(short i_bits);
		void compress_byte(short c);
		void compress_term(void);

	public:
		
		ComDecEngine();
		DecompressLZW(HFILE hSrcFile,DWORD dwCompressedSize,BYTE *OutputBuffer);
		BOOL CompressFile(BYTE *pData,DWORD dwSize, HFILE hOut);
		void SetEncrypt(BOOL bEncrypt) {this->bEncrypt = bEncrypt;}


};

/* LZW decompression tables:
 *   symbol_head[K] = prefix symbol of any LZW symbol K (0..LZW_TABLE_SIZE-1)
 *   symbol_tail[K] = suffix byte   of any LZW symbol K (0..LZW_TABLE_SIZE-1)
 * Note that entries 0..end_code of the above tables are not used,
 * since those symbols represent raw bytes or special codes.
 *
 * The stack represents the not-yet-used expansion of the last LZW symbol.
 * In the worst case, a symbol could expand to as many bytes as there are
 * LZW symbols, so we allocate LZW_TABLE_SIZE bytes for the stack.
 * (This is conservative since that number includes the raw-byte symbols.)
 */

/* COMPRESSION info
 * The LZW hash table consists of three parallel arrays:
 *   hash_code[i]       code of symbol in slot i, or 0 if empty slot
 *   hash_prefix[i]     symbol's prefix code; undefined if empty slot
 *   hash_suffix[i]     symbol's suffix character; undefined if empty slot
 * where slot values (i) range from 0 to HSIZE-1.
 *
 * Algorithm:  use open addressing double hashing (no chaining) on the
 * prefix code / suffix character combination.  We do a variant of Knuth's
 * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
 * secondary probe.
 *
 * The hash tables are allocated from heap space since they would use up
 * rather a lot of the near data space in a PC.
 */



 

#endif