-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlzp.c
128 lines (115 loc) · 1.93 KB
/
lzp.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define putchar putchar_unlocked
#define getchar getchar_unlocked
#define fwrite fwrite_unlocked
#define fread fread_unlocked
#define HASH_ORDER 16
#define HASH_SIZE (1 << HASH_ORDER)
#define HASH(h, x) (h = (h << 4) ^ x)
unsigned char table[HASH_SIZE];
void
encode(void)
{
unsigned char buf[9];
unsigned short hash;
int mask, i, j, c;
buf[0] = 'L';
buf[1] = 'Z';
buf[2] = 'P';
buf[3] = '1';
i = fwrite(buf, 1, 4, stdout);
if (i != 4) {
fprintf(stderr, "fwrite failed\n");
exit(1);
}
hash = 0;
for (;;) {
j = 1;
mask = 0;
for (i = 0; i < 8; i++) {
c = getchar();
if (c == EOF)
break;
if (c == table[hash]) {
mask |= 1 << i;
} else {
table[hash] = c;
buf[j++] = c;
}
HASH(hash, c);
}
if (i > 0) {
buf[0] = mask;
i = fwrite(buf, 1, j, stdout);
if (i != j) {
fprintf(stderr, "fwrite failed\n");
exit(1);
}
}
if (c == EOF)
break;
}
}
void
decode(void)
{
unsigned char buf[8];
unsigned short hash;
int mask, i, j, c;
i = fread(buf, 1, 4, stdin);
if (i != 4) {
fprintf(stderr, "fread failed\n");
exit(1);
}
if (buf[0] != 'L' || buf[1] != 'Z' ||
buf[2] != 'P' || buf[3] != '1') {
fprintf(stderr, "not compressed stream\n");
exit(1);
}
hash = 0;
for (;;) {
j = 0;
mask = getchar();
if (mask == EOF)
return;
for (i = 0; i < 8; i++) {
if ((mask & (1 << i)) != 0) {
c = table[hash];
} else {
c = getchar();
if (c == EOF)
break;
table[hash] = c;
}
buf[j++] = c;
HASH(hash, c);
}
if (j > 0) {
i = fwrite(buf, 1, j, stdout);
if (i != j) {
fprintf(stderr, "fwrite failed\n");
exit(1);
}
}
}
}
void
usage(void)
{
fprintf(stderr, "lzp <-c|-d>\n");
exit(1);
}
int
main(int argc, char **argv)
{
if (argc != 2)
usage();
if (strcmp(argv[1], "-c") == 0)
encode();
else if (strcmp(argv[1], "-d") == 0)
decode();
else
usage();
}