|
|
//
// General Data Compression
//
#ifndef _H_GDC
#define _H_GDC
//
//
// CONSTANTS
//
//
//
// Scratch buffer mutex
//
#define GDC_MUTEX_NAME "GDCMutex"
//
// Compression Types (bit flags)
//
#define GCT_NOCOMPRESSION 0x0000
#define GCT_PKZIP 0x0001
#define GCT_PERSIST_PKZIP 0x0002
#define GCT_DEFAULT (GCT_PKZIP | GCT_PERSIST_PKZIP)
//
// Compression Options for GCT_PKZIP
//
#define GDCCO_MAXSPEED 0
#define GDCCO_MAXCOMPRESSION 1
//
// Data sizes used to determine the saved dictionary space in our work
// buffer.
//
#define GDC_DATA_SMALL 1024
#define GDC_DATA_MEDIUM 2048
#define GDC_DATA_MAX 4096
//
// Persistent Dictionaries used for compression/decompression
//
enum { GDC_DICT_UPDATES = 0, GDC_DICT_MISC, GDC_DICT_INPUT, GDC_DICT_COUNT };
typedef struct tagGDC_DICTIONARY { UINT cbUsed; // Amount of saved data
BYTE pData[GDC_DATA_MAX]; // Saved uncompressed data
} GDC_DICTIONARY; typedef GDC_DICTIONARY * PGDC_DICTIONARY;
//
// Byte runs that can be replaced with smaller bit sequences
//
#define GDC_MINREP 2
#define GDC_MAXREP (GDC_MINREP+(8*1)+2+4+8+16+32+64+128+256-4)
// GDC_MAXREP is 516, 129*4
//
// Holds uncompressed data for both compression/decompression
//
#define GDC_UNCOMPRESSED (GDC_MAXREP + 2*GDC_DATA_MAX)
//
// We don't need to double-buffer compressed data--we just read it out
// of the caller's source or write it into the caller's dest directly.
//
// NOTE: With real PKZIP, which mostly reads from/writes to files,
// they don't have memory pointers containing raw data already. That's
// whe original code we got used Read/Write routine callbacks. This is
// no longer necessary.
//
//
// Random, little understood PKZIP table values, codes
//
#define KMP_THRESHOLD 10
#define GDC_LIT_SIZE (256 + GDC_MAXREP + 2)
// GDC_LIT_SIZE is 774
// EOF is last index of Lit array
#define EOF_CODE (GDC_LIT_SIZE-1)
#define ABORT_CODE (EOF_CODE+1)
//
// EXT_DIST_BITS is the # of bits needed to store an index into a GDC_DIST_SIZE
// array. That's defined to be 64, which is 2^6, hence 6 bits. Smaller
// dictionary compressions use fewer bits and hence not all of the DIST
// items. The mask
// is used to pull the 6-bit sized index out of a byte.
//
#define GDC_DIST_SIZE 64
#define EXT_DIST_BITS_MIN 4
#define EXT_DIST_BITS_MEDIUM 5
#define EXT_DIST_BITS_MAC 6
#define GDC_LEN_SIZE 16
#define GDC_DECODED_SIZE 256
//
// The hash function has 4*256+5*256 different values, which means
// we need that many entries in our hash array.
//
#define GDC_HASHFN(x) (4*(x)[0] + 5*(x)[1])
#define GDC_HASH_SIZE (4*256 + 5*256)
//
// Structure: GDC_IMPLODE
//
// Workspace for compressing our data. We have simplified and shrunk this
// structure a fair amount, by having constant code/bit tables and not
// double-buffering the compressed result. PKZIP's implode calculates the
// LitBits & LitCodes every time through (rather than storing 2 774 byte
// arrays in data--which would be a pain to declare anyway!), and makes a
// private copy of the DistBits & DistCodes.
//
typedef struct tagGDC_IMPLODE { //
// NO SOURCE INFO--we copy source chunks and maybe dictionary into
// RawData. Then at the end we copy RawData back into the dictionary
// if there is one.
//
//
// Destination info
//
LPBYTE pDst; // Current Dest ptr (advances as we write)
UINT cbDst; // Amount of Dest left (shrinks as we write)
UINT iDstBit; // Current bit pos in Current Dest ptr byte
//
// Compression info
//
UINT cbDictSize; UINT cbDictUsed; UINT ExtDistBits; UINT ExtDistMask;
//
// Working info
//
UINT Distance; UINT ibRawData;
// NOTE: GDC_UNCOMPRESSED is a multiple of 4
BYTE RawData[GDC_UNCOMPRESSED];
// NOTE: This is DWORD aligned (GDC_MAXREP is a multiple of 4
// and the extra 2 WORDS == 1 DWORD
short Next[2 + GDC_MAXREP];
// NOTE: GDC_UNCOMPRESED is a multiple of 4
WORD SortArray[GDC_UNCOMPRESSED];
// NOTE: This is DWORD aligned since GDC_HASH_SIZE is a multiple of 4
WORD HashArray[GDC_HASH_SIZE]; } GDC_IMPLODE, * PGDC_IMPLODE;
//
// GDC_EXPLODE
// Workspace for uncompressing our data. We have vastly simplified and
// shrunk this structure as per the comments for GDC_IMPLODE.
//
typedef struct tagGDC_EXPLODE { //
// Source info
//
LPBYTE pSrc; // Current Src ptr (advances as we read)
UINT cbSrc; // Amount of Src left (shrinks as we read)
UINT SrcByte; // Look ahead byte in source
UINT SrcBits; // Remainded src bits
//
// NO DEST INFO--we copy maybe dictionary into RawData at the beginning.
// Then at the end we maybe copy RawData back into the dictionary.
//
//
// Compression info
//
UINT ExtDistBits; UINT ExtDistMask; UINT cbDictUsed;
UINT Distance; UINT iRawData; // Current index into RawData
BYTE RawData[GDC_UNCOMPRESSED]; } GDC_EXPLODE, *PGDC_EXPLODE;
#define GDC_WORKBUF_SIZE max(sizeof(GDC_IMPLODE), sizeof(GDC_EXPLODE))
//
// EXTERNAL FUNCTIONS
//
//
// API FUNCTION: GDC_Init()
//
// DESCRIPTION:
//
// Initialises the General Data Compressor.
// Must be called before any other GDC functions.
//
// PARAMETERS:
//
//
//
void GDC_Init(void);
//
// FUNCTION: GDC_Compress(..)
//
// DESCRIPTION:
//
// Compresses source data into a destination buffer.
//
//
// PARAMETERS:
//
// pDictionary - NULL if old PKZIP, valid ptr if persistent
//
// Options - specifies whether speed of compression or
// size of the compressed data is the most important factor. This
// basically affects the amount of previous data saved for looking
// backwards. MAXSPEED means smaller dictionary. MAXCOMPRESSION
// means a bigger one. The dictionary size is basically the amount
// of overlap in the source data used when calculating the hash
// index.
//
// GDCCO_MAXSPEED - compress the data as quickly as possible, at
// the expense of increased compressed data size
//
// GDCCO_MAXCOMPRESSION - compress the data as much as possible, at the
// expense of increased compression time.
// With a persistent dictionary, only GDCCO_MAXCOMPRESSION is meaningful.
//
// pSrc - pointer to the source (uncompressed) data.
//
// cbSrcSize - the number of bytes of source.
//
// pDst - pointer to the destination, where the
// compressed result will go.
//
// pcbDstSize - pointer to the maximum amount the destina-
// tion can hold. If the compressed result ends
// up being bigger than this amount, we bail
// out and don't compress the source at all.
// Otherwise the resulting size is written back.
//
// RETURNS:
//
// TRUE if success, FALSE if failure.
//
//
BOOL GDC_Compress ( PGDC_DICTIONARY pDictionary, UINT Options, LPBYTE pWorkBuf, LPBYTE pSrc, UINT cbSrcSize, LPBYTE pDst, UINT * pcbDstSize );
//
// API FUNCTION: GDC_Decompress(..)
//
// DESCRIPTION:
//
// Decompresses source data into a destination buffer.
//
//
// PARAMETERS:
//
// pDictionary - NULL if old PKZIP, ptr to saved data if
// persistent.
//
// pSrc - pointer to the source (compressed) data.
//
// cbSrcSize - the number of bytes of source.
//
// pDst - pointer to the destination, where the
// uncompressed result will go.
//
// pcbDstSize - pointer to the maximum amount the desina-
// tion can hold. If the uncompressed result
// ends up being bigger than this amount, we
// bail out since we can't decompress it.
// Otherwise the resulting size is written back.
//
// RETURNS:
//
// TRUE if success, FALSE if failure.
//
BOOL GDC_Decompress ( PGDC_DICTIONARY pDictionary, LPBYTE pWorkBuf, LPBYTE pSrc, UINT cbSrcSize, LPBYTE pDst, UINT * pcbDstSize );
//
// INTERNAL FUNCTIONS
//
void GDCCalcDecode(const BYTE * pBits, const BYTE * pCodes, UINT size, LPBYTE pDecode);
LPBYTE GDCGetWorkBuf(void); void GDCReleaseWorkBuf(LPBYTE);
UINT GDCFindRep(PGDC_IMPLODE pgdcImp, LPBYTE Start);
void GDCSortBuffer(PGDC_IMPLODE pgdcImp, LPBYTE low, LPBYTE hi);
BOOL GDCOutputBits(PGDC_IMPLODE pgdcImp, WORD Cnt, WORD Code);
UINT GDCDecodeLit(PGDC_EXPLODE);
UINT GDCDecodeDist(PGDC_EXPLODE pgdcExp, UINT Len);
BOOL GDCWasteBits(PGDC_EXPLODE pgdcExp, UINT Bits);
#endif // _H_GDC
|