Mastering Algorithms With C - Kyle Loudon [173]
while (i < LZ77_WINDOW_SIZE && j < LZ77_BUFFER_SIZE - 1) {
if (window[i] != buffer[j])
break;
match++;
i++;
j++;
}
/**************************************************************************
* *
* Keep track of the offset, length, and next symbol for the best match. *
* *
**************************************************************************/
if (match > longest) {
*offset = k;
longest = match;
*next = buffer[j];
}
}
return longest;
}
/*****************************************************************************
* *
* ----------------------------- lz77_compress ---------------------------- *
* *
*****************************************************************************/
int lz77_compress(const unsigned char *original, unsigned char **compressed,
int size) {
unsigned char window[LZ77_WINDOW_SIZE],
buffer[LZ77_BUFFER_SIZE],
*comp,
*temp,
next;
int offset,
length,
remaining,
hsize,
ipos,
opos,
tpos,
i;
/*****************************************************************************
* *
* Make the pointer to the compressed data not valid until later. *
* *
*****************************************************************************/
*compressed = NULL;
/*****************************************************************************
* *
* Write the header information. *
* *
*****************************************************************************/
hsize = sizeof(int);
if ((comp = (unsigned char *)malloc(hsize)) == NULL)
return -1;
memcpy(comp, &size, sizeof(int));
/*****************************************************************************
* *
* Initialize the sliding window and the look-ahead buffer. *
* *
*****************************************************************************/
memset(window, 0, LZ77_WINDOW_SIZE);
memset(buffer, 0, LZ77_BUFFER_SIZE);
/*****************************************************************************
* *
* Load the look-ahead buffer. *
* *
*****************************************************************************/
ipos = 0;
for (i = 0; i < LZ77_BUFFER_SIZE && ipos < size; i++) {
buffer[i] = original[ipos];
ipos++;
}
/*****************************************************************************
* *
* Compress the data. *
* *
*****************************************************************************/
opos = hsize * 8;
remaining = size;
while (remaining > 0) {
if ((length = compare_win(window, buffer, &offset, &next)) != 0) {
/***********************************************************************
* *
* Encode a phrase token. *
* *
***********************************************************************/
token = 0x00000001 << (LZ77_PHRASE_BITS - 1);
/***********************************************************************
* *
* Set the offset where the match was found in the sliding window. *
* *
***********************************************************************/
token = token | (offset << (LZ77_PHRASE_BITS - LZ77_TYPE_BITS -
LZ77_WINOFF_BITS));
/***********************************************************************
* *
* Set the length of the match. *
* *
***********************************************************************/
token = token | (length << (LZ77_PHRASE_BITS - LZ77_TYPE_BITS -
LZ77_WINOFF_BITS - LZ77_BUFLEN_BITS));
/***********************************************************************
* *
* Set the next symbol in the look-ahead buffer after the match. *
* *
***********************************************************************/
token = token | next;
/***********************************************************************
* *
* Set the number of bits in the token. *
* *
***********************************************************************/
tbits = LZ77_PHRASE_BITS;
}
else {
/***********************************************************************
* *
* Encode a symbol token. *
* *
***********************************************************************/