#include <stdio.h>
#include <string.h>
//comp()
void Compress(unsigned char *szOut, const char *szMessage) {
unsigned long long nBuffer = 0; //This is enough to store 8 uncompressed characters or 9 compressed. We will only use 8 tho.
char nBitsInBuffer = 0;
while (*szMessage != 0) {
nBuffer |= (unsigned long long)(*szMessage++ & 0x7F) << nBitsInBuffer;
nBitsInBuffer += 7;
if (nBitsInBuffer == 7 * 8) { //We have 8 chars in the buffer, dump them
while (nBitsInBuffer > 0) {
*szOut++ = nBuffer & 0xFF;
nBuffer >>= 8;
nBitsInBuffer -= 8;
}
//The following should be redundant, but just to be safe
nBitsInBuffer = 0;
nBuffer = 0;
}
}
//Write out whatever is left in the buffer
while (nBitsInBuffer > 0) {
*szOut++ = nBuffer & 0xFF;
nBuffer >>= 8;
nBitsInBuffer -= 8;
}
}
//uncomp()
//nCompressedLen is the number of bytes in the compressed buffer.
//NOTE: the compressed buffer does not have a NULL terminating character
void Uncompress(char *szOut, const unsigned char *szCompressed, unsigned nCompressedLen) {
unsigned long long nBuffer = 0; //This is enough to store 8 uncompressed characters or 9 compressed. We will only use 8 tho.
char nBitsInBuffer = 0;
while (nCompressedLen) {
while (nCompressedLen && nBitsInBuffer < 7 * 8) {
nBuffer |= (unsigned long long)*szCompressed++ << nBitsInBuffer;
nBitsInBuffer += 8;
--nCompressedLen;
}
while (nBitsInBuffer > 0) {
*szOut++ = nBuffer & 0x7F;
nBuffer >>= 7;
nBitsInBuffer -= 7;
}
//The following should be redundant, but just to be safe
nBitsInBuffer = 0;
nBuffer = 0;
}
}
int main() {
//char szMessage[] = "x53x7Fx63x4B";
char szMessage[] = "hello world. this is a compressed long string";
static const unsigned nCompressedSize = sizeof(szMessage) * 7 / 8; //This does not include the NULL terminating character from the string
unsigned char pCompressedBytes[nCompressedSize];
char szUncompressed[sizeof(szMessage)];
printf(" Message: %s
", szMessage);
Compress(pCompressedBytes, szMessage);
printf(" Compressed: ");
for (int nByte = 0; nByte < nCompressedSize; ++nByte) {
printf("%02X ", pCompressedBytes[nByte]);
}
printf("
");
Uncompress(szUncompressed, pCompressedBytes, nCompressedSize);
szUncompressed[sizeof(szMessage) - 1] = 0; //We need to terminate the string. The NULL terminator is not stored in the compressed bytes
printf("Uncompressed: %s
", szUncompressed);
//Now just verify that we ended up with the same message we started with
if (strcmp(szMessage, szUncompressed) == 0) {
printf("Compression works
");
} else {
printf("Compression failed
");
}
return 0;
}
#include <stdint.h>
uint32_t lz77_compress (uint8_t *uncompressed_text, uint32_t uncompressed_size, uint8_t *compressed_text)
{
uint8_t pointer_length, temp_pointer_length;
uint16_t pointer_pos, temp_pointer_pos, output_pointer;
uint32_t compressed_pointer, output_size, coding_pos, output_lookahead_ref, look_behind, look_ahead;
*((uint32_t *) compressed_text) = uncompressed_size;
compressed_pointer = output_size = 4;
for(coding_pos = 0; coding_pos < uncompressed_size; ++coding_pos)
{
pointer_pos = 0;
pointer_length = 0;
for(temp_pointer_pos = 1; (temp_pointer_pos < 4096) && (temp_pointer_pos <= coding_pos); ++temp_pointer_pos)
{
look_behind = coding_pos - temp_pointer_pos;
look_ahead = coding_pos;
for(temp_pointer_length = 0; uncompressed_text[look_ahead++] == uncompressed_text[look_behind++]; ++temp_pointer_length)
if(temp_pointer_length == 15)
break;
if(temp_pointer_length > pointer_length)
{
pointer_pos = temp_pointer_pos;
pointer_length = temp_pointer_length;
if(pointer_length == 15)
break;
}
}
coding_pos += pointer_length;
if(pointer_length && (coding_pos == uncompressed_size))
{
output_pointer = (pointer_pos << 4) | (pointer_length - 1);
output_lookahead_ref = coding_pos - 1;
}
else
{
output_pointer = (pointer_pos << 4) | pointer_length;
output_lookahead_ref = coding_pos;
}
*((uint32_t *) (compressed_text + compressed_pointer)) = output_pointer;
compressed_pointer += 2;
*(compressed_text + compressed_pointer++) = *(uncompressed_text + output_lookahead_ref);
output_size += 3;
}
return output_size;
}
uint32_t lz77_decompress (uint8_t *compressed_text, uint8_t *uncompressed_text)
{
uint8_t pointer_length;
uint16_t input_pointer, pointer_pos;
uint32_t compressed_pointer, coding_pos, pointer_offset, uncompressed_size;
uncompressed_size = *((uint32_t *) compressed_text);
compressed_pointer = 4;
for(coding_pos = 0; coding_pos < uncompressed_size; ++coding_pos)
{
input_pointer = *((uint32_t *) (compressed_text + compressed_pointer));
compressed_pointer += 2;
pointer_pos = input_pointer >> 4;
pointer_length = input_pointer & 15;
if(pointer_pos)
for(pointer_offset = coding_pos - pointer_pos; pointer_length > 0; --pointer_length)
uncompressed_text[coding_pos++] = uncompressed_text[pointer_offset++];
*(uncompressed_text + coding_pos) = *(compressed_text + compressed_pointer++);
}
return coding_pos;
}