Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/cmd/codexlib/lzd/lzd.c
1810 views
1
#pragma prototyped
2
3
/*
4
* lzd decoder snarfed from the public domain booz -- Rahul Dhesi 1991/07/07
5
*/
6
7
#include <codex.h>
8
9
#define MEM_BLOCK_SIZE 8192
10
#define OUT_BUF_SIZE (MEM_BLOCK_SIZE/2)
11
#define IN_BUF_SIZE (MEM_BLOCK_SIZE/2)
12
13
#define STACKSIZE 2000
14
#define INBUFSIZ (IN_BUF_SIZE - SPARE)
15
#define OUTBUFSIZ (OUT_BUF_SIZE - SPARE)
16
#define MEMERR 2
17
#define IOERR 1
18
#define MAXBITS 13
19
#define CLEAR 256 /* clear code */
20
#define Z_EOF 257 /* end of file marker */
21
#define FIRST_FREE 258 /* first free code */
22
#define MAXMAX 8192 /* max code + 1 */
23
#define SPARE 4
24
25
typedef struct Table_s
26
{
27
unsigned int next;
28
char z_ch;
29
} Table_t;
30
31
typedef struct State_s
32
{
33
Codex_t* codex;
34
35
unsigned char buf[SF_BUFSIZE];
36
unsigned char* ip;
37
unsigned char* ie;
38
39
unsigned long bitbuf;
40
unsigned short bitcount;
41
unsigned short bitmask;
42
43
unsigned int old_code;
44
unsigned int suf_code;
45
unsigned int max_code;
46
unsigned int free_code;
47
unsigned int in_code;
48
unsigned int fin_char;
49
unsigned int nbits;
50
unsigned int cpy;
51
unsigned int bad;
52
unsigned int eof;
53
unsigned int sp;
54
unsigned int stack[STACKSIZE + SPARE];
55
56
Table_t table[MAXMAX];
57
58
char spare[SPARE];
59
} State_t;
60
61
#define GETCHAR(p) ((p)->ip < (p)->ie ? (int)*(p)->ip++ : fill(p))
62
63
static int
64
fill(State_t* state)
65
{
66
ssize_t r;
67
68
if (state->eof)
69
return 0;
70
if ((r = sfrd(state->codex->sp, state->buf, sizeof(state->buf), &state->codex->sfdisc)) <= 0)
71
{
72
state->eof = 1;
73
return 0;
74
}
75
state->ie = (state->ip = state->buf) + r;
76
return *state->ip++;
77
}
78
79
static int
80
getcode(State_t* state)
81
{
82
unsigned short x;
83
84
while (state->nbits > state->bitcount)
85
{
86
state->bitbuf |= GETCHAR(state) << state->bitcount;
87
state->bitcount += 8;
88
}
89
x = state->bitbuf & state->bitmask;
90
state->bitbuf >>= state->nbits;
91
state->bitcount -= state->nbits;
92
return state->eof ? Z_EOF : x;
93
}
94
95
static void
96
push(State_t* state, int c)
97
{
98
state->stack[state->sp++] = c;
99
if (state->sp >= STACKSIZE)
100
state->sp--;
101
}
102
103
#define pop(p) ((p)->stack[--(p)->sp])
104
105
static void
106
clrcode(State_t* state)
107
{
108
state->bitmask = (1 << (state->nbits = 9)) - 1;
109
state->max_code = 512;
110
state->free_code = FIRST_FREE;
111
}
112
113
static void
114
addcode(register State_t* state, int suf_code, int old_code)
115
{
116
state->table[state->free_code].z_ch = suf_code;
117
state->table[state->free_code].next = old_code;
118
if (++state->free_code >= state->max_code && state->nbits < MAXBITS)
119
{
120
state->nbits++;
121
state->bitmask <<= 1;
122
state->bitmask |= 1;
123
state->max_code = state->max_code << 1;
124
}
125
}
126
127
static int
128
lzd_open(Codex_t* p, char* const args[], Codexnum_t flags)
129
{
130
register State_t* state;
131
132
if (!(state = newof(0, State_t, 1, 0)))
133
{
134
if (p->disc->errorf)
135
(*p->disc->errorf)(NiL, p->disc, 2, "out of space");
136
return -1;
137
}
138
state->codex = p;
139
p->data = state;
140
return 0;
141
}
142
143
static int
144
lzd_init(Codex_t* p)
145
{
146
register State_t* state = (State_t*)p->data;
147
148
state->bitcount = 0;
149
state->bad = state->cpy = state->eof = 0;
150
state->ip = state->ie = 0;
151
state->sp = 0;
152
clrcode(state);
153
return 0;
154
}
155
156
static ssize_t
157
lzd_read(Sfio_t* sp, void* buf, size_t n, Sfdisc_t* disc)
158
{
159
register State_t* state = (State_t*)CODEX(disc)->data;
160
register char* s = (char*)buf;
161
register char* e = s + n;
162
register int c;
163
164
if (state->eof)
165
return state->bad;
166
if (state->cpy)
167
{
168
state->cpy = 0;
169
while (state->sp != 0)
170
{
171
*s++ = pop(state);
172
if (s >= e)
173
{
174
state->cpy = 1;
175
return s - (char*)buf;
176
}
177
}
178
}
179
while ((c = getcode(state)) != Z_EOF)
180
{
181
if (c == CLEAR)
182
{
183
clrcode(state);
184
*s++ = state->fin_char = state->suf_code = state->old_code = c = getcode(state);
185
if (s >= e)
186
return s - (char*)buf;
187
}
188
else
189
{
190
state->in_code = c;
191
if (c >= state->free_code)
192
{
193
c = state->old_code;
194
push(state, state->fin_char);
195
}
196
while (c > 255)
197
{
198
push(state, state->table[c].z_ch);
199
c = state->table[c].next;
200
}
201
state->suf_code = state->fin_char = c;
202
addcode(state, state->suf_code, state->old_code);
203
state->old_code = state->in_code;
204
push(state, state->suf_code);
205
while (state->sp != 0)
206
{
207
*s++ = pop(state);
208
if (s >= e)
209
{
210
state->cpy = 1;
211
return s - (char*)buf;
212
}
213
}
214
}
215
}
216
state->eof = 1;
217
return s - (char*)buf;
218
}
219
220
Codexmeth_t codex_lzd =
221
{
222
"lzd",
223
"\bzoo\b(1) archive lzd compression.",
224
"[+(version)?codex-lzd 1991-07-07]"
225
"[+(author)?Rahul Dhesi]",
226
CODEX_DECODE|CODEX_COMPRESS,
227
0,
228
0,
229
lzd_open,
230
0,
231
lzd_init,
232
0,
233
lzd_read,
234
0,
235
0,
236
0,
237
0,
238
0,
239
0,
240
CODEXNEXT(lzd)
241
};
242
243
CODEXLIB(lzd)
244
245