1#include <stdio.h>
2#include <string.h>
3
4//comp()
5void Compress(unsigned char *szOut, const char *szMessage) {
6 unsigned long long nBuffer = 0; //This is enough to store 8 uncompressed characters or 9 compressed. We will only use 8 tho.
7 char nBitsInBuffer = 0;
8 while (*szMessage != 0) {
9 nBuffer |= (unsigned long long)(*szMessage++ & 0x7F) << nBitsInBuffer;
10 nBitsInBuffer += 7;
11 if (nBitsInBuffer == 7 * 8) { //We have 8 chars in the buffer, dump them
12 while (nBitsInBuffer > 0) {
13 *szOut++ = nBuffer & 0xFF;
14 nBuffer >>= 8;
15 nBitsInBuffer -= 8;
16 }
17 //The following should be redundant, but just to be safe
18 nBitsInBuffer = 0;
19 nBuffer = 0;
20 }
21 }
22 //Write out whatever is left in the buffer
23 while (nBitsInBuffer > 0) {
24 *szOut++ = nBuffer & 0xFF;
25 nBuffer >>= 8;
26 nBitsInBuffer -= 8;
27 }
28}
29
30//uncomp()
31//nCompressedLen is the number of bytes in the compressed buffer.
32//NOTE: the compressed buffer does not have a NULL terminating character
33void Uncompress(char *szOut, const unsigned char *szCompressed, unsigned nCompressedLen) {
34 unsigned long long nBuffer = 0; //This is enough to store 8 uncompressed characters or 9 compressed. We will only use 8 tho.
35 char nBitsInBuffer = 0;
36 while (nCompressedLen) {
37 while (nCompressedLen && nBitsInBuffer < 7 * 8) {
38 nBuffer |= (unsigned long long)*szCompressed++ << nBitsInBuffer;
39 nBitsInBuffer += 8;
40 --nCompressedLen;
41 }
42 while (nBitsInBuffer > 0) {
43 *szOut++ = nBuffer & 0x7F;
44 nBuffer >>= 7;
45 nBitsInBuffer -= 7;
46 }
47 //The following should be redundant, but just to be safe
48 nBitsInBuffer = 0;
49 nBuffer = 0;
50 }
51}
52
53int main() {
54 //char szMessage[] = "\x53\x7F\x63\x4B";
55 char szMessage[] = "hello world. this is a compressed long string";
56 static const unsigned nCompressedSize = sizeof(szMessage) * 7 / 8; //This does not include the NULL terminating character from the string
57 unsigned char pCompressedBytes[nCompressedSize];
58 char szUncompressed[sizeof(szMessage)];
59 printf(" Message: %s\n", szMessage);
60 Compress(pCompressedBytes, szMessage);
61 printf(" Compressed: ");
62 for (int nByte = 0; nByte < nCompressedSize; ++nByte) {
63 printf("%02X ", pCompressedBytes[nByte]);
64 }
65 printf("\n");
66 Uncompress(szUncompressed, pCompressedBytes, nCompressedSize);
67 szUncompressed[sizeof(szMessage) - 1] = 0; //We need to terminate the string. The NULL terminator is not stored in the compressed bytes
68 printf("Uncompressed: %s\n", szUncompressed);
69 //Now just verify that we ended up with the same message we started with
70 if (strcmp(szMessage, szUncompressed) == 0) {
71 printf("Compression works\n");
72 } else {
73 printf("Compression failed\n");
74 }
75 return 0;
76}
1#include <stdint.h>
2
3uint32_t lz77_compress (uint8_t *uncompressed_text, uint32_t uncompressed_size, uint8_t *compressed_text)
4{
5 uint8_t pointer_length, temp_pointer_length;
6 uint16_t pointer_pos, temp_pointer_pos, output_pointer;
7 uint32_t compressed_pointer, output_size, coding_pos, output_lookahead_ref, look_behind, look_ahead;
8
9 *((uint32_t *) compressed_text) = uncompressed_size;
10 compressed_pointer = output_size = 4;
11
12 for(coding_pos = 0; coding_pos < uncompressed_size; ++coding_pos)
13 {
14 pointer_pos = 0;
15 pointer_length = 0;
16 for(temp_pointer_pos = 1; (temp_pointer_pos < 4096) && (temp_pointer_pos <= coding_pos); ++temp_pointer_pos)
17 {
18 look_behind = coding_pos - temp_pointer_pos;
19 look_ahead = coding_pos;
20 for(temp_pointer_length = 0; uncompressed_text[look_ahead++] == uncompressed_text[look_behind++]; ++temp_pointer_length)
21 if(temp_pointer_length == 15)
22 break;
23 if(temp_pointer_length > pointer_length)
24 {
25 pointer_pos = temp_pointer_pos;
26 pointer_length = temp_pointer_length;
27 if(pointer_length == 15)
28 break;
29 }
30 }
31 coding_pos += pointer_length;
32 if(pointer_length && (coding_pos == uncompressed_size))
33 {
34 output_pointer = (pointer_pos << 4) | (pointer_length - 1);
35 output_lookahead_ref = coding_pos - 1;
36 }
37 else
38 {
39 output_pointer = (pointer_pos << 4) | pointer_length;
40 output_lookahead_ref = coding_pos;
41 }
42 *((uint32_t *) (compressed_text + compressed_pointer)) = output_pointer;
43 compressed_pointer += 2;
44 *(compressed_text + compressed_pointer++) = *(uncompressed_text + output_lookahead_ref);
45 output_size += 3;
46 }
47
48 return output_size;
49}
50
51uint32_t lz77_decompress (uint8_t *compressed_text, uint8_t *uncompressed_text)
52{
53 uint8_t pointer_length;
54 uint16_t input_pointer, pointer_pos;
55 uint32_t compressed_pointer, coding_pos, pointer_offset, uncompressed_size;
56
57 uncompressed_size = *((uint32_t *) compressed_text);
58 compressed_pointer = 4;
59
60 for(coding_pos = 0; coding_pos < uncompressed_size; ++coding_pos)
61 {
62 input_pointer = *((uint32_t *) (compressed_text + compressed_pointer));
63 compressed_pointer += 2;
64 pointer_pos = input_pointer >> 4;
65 pointer_length = input_pointer & 15;
66 if(pointer_pos)
67 for(pointer_offset = coding_pos - pointer_pos; pointer_length > 0; --pointer_length)
68 uncompressed_text[coding_pos++] = uncompressed_text[pointer_offset++];
69 *(uncompressed_text + coding_pos) = *(compressed_text + compressed_pointer++);
70 }
71
72 return coding_pos;
73}
74