1 // See the file readme-lzhuf.txt for more information about this file.
2 // Modifications for Deark are Copyright (C) 2021 Jason Summers, and have the
3 // same terms of use as the main part of Deark.
4 // Alternatively, at your option, the modifications for Deark may be treated
7 // Intro from the original software:
9 /**************************************************************
11 written by Haruyasu Yoshizaki 11/20/1988
12 some minor changes 4/6/1989
13 comments translated by Haruhiko Okumura 4/7/1989
14 **************************************************************/
17 #define LZHUF_N 4096 /* buffer size */
18 #define LZHUF_F 60 /* lookahead buffer size */
19 #define LZHUF_THRESHOLD 2
20 #define LZHUF_N_CHAR (256 - LZHUF_THRESHOLD + LZHUF_F)
21 /* kinds of characters (character code = 0..N_CHAR-1) */
22 #define LZHUF_T (LZHUF_N_CHAR * 2 - 1) /* size of table */
23 #define LZHUF_R (LZHUF_T - 1) /* position of root */
24 #define LZHUF_MAX_FREQ 0x8000 /* updates tree when the */
25 /* root frequency comes to this value. */
30 struct de_dfilter_in_params
*dcmpri
;
31 struct de_dfilter_out_params
*dcmpro
;
32 struct de_dfilter_results
*dres
;
36 struct de_lz77buffer
*ringbuf
;
37 struct de_bitreader bitrd
;
39 u16 freq
[LZHUF_T
+ 1]; /* frequency table */
41 i16 prnt
[LZHUF_T
+ LZHUF_N_CHAR
]; /* pointers to parent nodes, except for the */
42 /* elements [T..T + N_CHAR - 1] which are used to get */
43 /* the positions of leaves corresponding to the codes. */
45 i16 son
[LZHUF_T
]; /* pointers to child nodes (son[], son[] + 1) */
49 /* initialization of tree */
51 static void lzhuf_StartHuff(struct lzahuf_ctx
*cctx
)
55 for (i
= 0; i
< LZHUF_N_CHAR
; i
++) {
57 cctx
->son
[i
] = i
+ LZHUF_T
;
58 cctx
->prnt
[i
+ LZHUF_T
] = i
;
60 i
= 0; j
= LZHUF_N_CHAR
;
61 while (j
<= LZHUF_R
) {
62 cctx
->freq
[j
] = cctx
->freq
[i
] + cctx
->freq
[i
+ 1];
64 cctx
->prnt
[i
] = cctx
->prnt
[i
+ 1] = j
;
67 cctx
->freq
[LZHUF_T
] = 0xffff;
68 cctx
->prnt
[LZHUF_R
] = 0;
72 /* reconstruction of tree */
74 static void lzhuf_reconst(struct lzahuf_ctx
*cctx
)
79 /* collect leaf nodes in the first half of the table */
80 /* and replace the freq by (freq + 1) / 2. */
82 for (i
= 0; i
< LZHUF_T
; i
++) {
83 if (cctx
->son
[i
] >= LZHUF_T
) {
84 cctx
->freq
[j
] = (cctx
->freq
[i
] + 1) / 2;
85 cctx
->son
[j
] = cctx
->son
[i
];
89 /* begin constructing tree by connecting sons */
90 for (i
= 0, j
= LZHUF_N_CHAR
; j
< LZHUF_T
; i
+= 2, j
++) {
92 f
= cctx
->freq
[j
] = cctx
->freq
[i
] + cctx
->freq
[k
];
93 for (k
= j
- 1; f
< cctx
->freq
[k
]; k
--);
96 de_memmove(&cctx
->freq
[k
+ 1], &cctx
->freq
[k
], l
*sizeof(cctx
->freq
[0]));
98 de_memmove(&cctx
->son
[k
+ 1], &cctx
->son
[k
], l
*sizeof(cctx
->son
[0]));
102 for (i
= 0; i
< LZHUF_T
; i
++) {
103 if ((k
= cctx
->son
[i
]) >= LZHUF_T
) {
106 cctx
->prnt
[k
] = cctx
->prnt
[k
+ 1] = i
;
112 /* increment frequency of given code by one, and update tree */
114 static void lzhuf_update(struct lzahuf_ctx
*cctx
, int c
)
119 if (cctx
->freq
[LZHUF_R
] == LZHUF_MAX_FREQ
) {
122 c
= cctx
->prnt
[c
+ LZHUF_T
];
126 /* if the order is disturbed, exchange nodes */
127 if (k
> cctx
->freq
[l
= c
+ 1]) {
128 while (k
> cctx
->freq
[++l
]);
130 cctx
->freq
[c
] = cctx
->freq
[l
];
135 if (i
< LZHUF_T
) cctx
->prnt
[i
+ 1] = l
;
141 if (j
< LZHUF_T
) cctx
->prnt
[j
+ 1] = c
;
146 } while ((c
= cctx
->prnt
[c
]) != 0); /* repeat up to root */
149 static int lzhuf_DecodeChar(struct lzahuf_ctx
*cctx
)
153 c
= cctx
->son
[LZHUF_R
];
155 /* travel from root to leaf, */
156 /* choosing the smaller child node (son[]) if the read bit is 0, */
157 /* the bigger (son[]+1} if 1 */
158 while (c
< LZHUF_T
) {
159 c
+= (UI
)de_bitreader_getbits(&cctx
->bitrd
, 1);
163 lzhuf_update(cctx
, c
);
167 static int lzhuf_DecodePosition(struct lzahuf_ctx
*cctx
)
171 /* recover upper 6 bits from table */
172 i
= (UI
)de_bitreader_getbits(&cctx
->bitrd
, 8);
173 c
= (UI
)fmtutil_get_lzhuf_d_code(i
) << 6;
174 j
= fmtutil_get_lzhuf_d_len(i
);
176 /* read lower 6 bits verbatim */
178 i
= (i
<<j
) | (UI
)de_bitreader_getbits(&cctx
->bitrd
, j
);
179 return c
| (i
& 0x3f);
182 static void lzah_lz77buf_writebytecb(struct de_lz77buffer
*rb
, u8 n
)
184 struct lzahuf_ctx
*cctx
= (struct lzahuf_ctx
*)rb
->userdata
;
186 if(cctx
->nbytes_written
>= cctx
->textsize
) {
189 dbuf_writebyte(cctx
->dcmpro
->f
, n
);
190 cctx
->nbytes_written
++;
193 static void lzhuf_Decode(struct lzahuf_ctx
*cctx
) /* recover */
197 if(cctx
->dcmpro
->len_known
) {
198 cctx
->textsize
= cctx
->dcmpro
->expected_len
;
201 de_dfilter_set_generic_error(cctx
->c
, cctx
->dres
, cctx
->modname
);
205 lzhuf_StartHuff(cctx
);
207 cctx
->ringbuf
= de_lz77buffer_create(cctx
->c
, LZHUF_N
);
208 cctx
->ringbuf
->userdata
= (void*)cctx
;
209 cctx
->ringbuf
->writebyte_cb
= lzah_lz77buf_writebytecb
;
210 de_lz77buffer_clear(cctx
->ringbuf
, 0x20);
211 de_lz77buffer_set_curpos(cctx
->ringbuf
, LZHUF_N
- LZHUF_F
);
214 if(cctx
->nbytes_written
>= cctx
->textsize
) {
217 if(cctx
->bitrd
.eof_flag
) {
221 c
= lzhuf_DecodeChar(cctx
);
223 de_lz77buffer_add_literal_byte(cctx
->ringbuf
, (u8
)c
);
226 // i is the distance back
227 i
= lzhuf_DecodePosition(cctx
);
228 // j is the match length
229 j
= c
- 255 + LZHUF_THRESHOLD
;
231 de_lz77buffer_copy_from_hist(cctx
->ringbuf
,
232 (UI
)(cctx
->ringbuf
->curpos
- (UI
)i
- 1), j
);
237 de_lz77buffer_destroy(cctx
->c
, cctx
->ringbuf
);
238 cctx
->ringbuf
= NULL
;