1 // This file is part of Deark.
2 // Copyright (C) 2021 Jason Summers
3 // See the file COPYING for terms of use.
5 // LZH with adaptive Huffman coding
7 #define DE_NOT_IN_MODULE
8 #include "deark-private.h"
9 #include "deark-fmtutil.h"
11 #include "../foreign/lzhuf.h"
13 void fmtutil_get_lzhuf_d_code_and_len(UI n
, UI
*pd_code
, UI
*pd_len
)
15 if(n
<32 || n
>=256) { *pd_code
= 0; *pd_len
= 3; }
16 else if(n
<80) { *pd_code
= (n
-16)>>4; *pd_len
= 4; }
17 else if(n
<144) { *pd_code
= (n
-48)>>3; *pd_len
= 5; }
18 else if(n
<192) { *pd_code
= (n
-96)>>2; *pd_len
= 6; }
19 else if(n
<240) { *pd_code
= (n
-144)>>1; *pd_len
= 7; }
20 else { *pd_code
= n
-192; *pd_len
= 8; };
23 static void my_lh1_codec_addbuf(struct de_dfilter_ctx
*dfctx
,
24 const u8
*buf
, i64 buf_len
)
26 struct lzahuf_ctx
*cctx
= (struct lzahuf_ctx
*)dfctx
->codec_private
;
28 if(dfctx
->finished_flag
|| cctx
->errflag
) {
32 lzhuf_Decode_continue(cctx
, buf
, buf_len
, 0);
36 dfctx
->finished_flag
= 1;
40 static void my_lh1_codec_finish(struct de_dfilter_ctx
*dfctx
)
42 struct lzahuf_ctx
*cctx
= (struct lzahuf_ctx
*)dfctx
->codec_private
;
44 lzhuf_Decode_continue(cctx
, NULL
, 0, 1);
46 cctx
->total_nbytes_processed
-= (i64
)(cctx
->bbll
.nbits_in_bitbuf
/8);
47 de_bitbuf_lowlevel_empty(&cctx
->bbll
);
48 dfctx
->dres
->bytes_consumed
= cctx
->total_nbytes_processed
;
49 dfctx
->dres
->bytes_consumed_valid
= 1;
52 de_dfilter_set_generic_error(cctx
->c
, dfctx
->dres
, cctx
->modname
);
56 static void my_lh1_codec_command(struct de_dfilter_ctx
*dfctx
, int cmd
, UI flags
)
58 struct lzahuf_ctx
*cctx
= (struct lzahuf_ctx
*)dfctx
->codec_private
;
60 if(cmd
==DE_DFILTER_COMMAND_FINISH_BLOCK
) {
61 lzhuf_Decode_continue(cctx
, NULL
, 0, 1);
62 cctx
->total_nbytes_processed
-= (i64
)(cctx
->bbll
.nbits_in_bitbuf
/8);
63 de_bitbuf_lowlevel_empty(&cctx
->bbll
);
64 if(cctx
->lh1p
.is_dms_deep
) {
65 de_lz77buffer_set_curpos(cctx
->ringbuf
, cctx
->ringbuf
->curpos
+ 60);
68 else if(cmd
==DE_DFILTER_COMMAND_RESET_COUNTERS
) {
69 cctx
->nbytes_written
= 0;
70 cctx
->total_nbytes_processed
= 0;
72 dfctx
->finished_flag
= 0;
76 static void my_lh1_codec_destroy(struct de_dfilter_ctx
*dfctx
)
78 struct lzahuf_ctx
*cctx
= (struct lzahuf_ctx
*)dfctx
->codec_private
;
81 de_lz77buffer_destroy(cctx
->c
, cctx
->ringbuf
);
83 de_free(dfctx
->c
, cctx
);
85 dfctx
->codec_private
= NULL
;
88 // codec_private_params: 'struct de_lh1_params'. Can be NULL.
89 void dfilter_lh1_codec(struct de_dfilter_ctx
*dfctx
, void *codec_private_params
)
91 struct lzahuf_ctx
*cctx
= NULL
;
93 cctx
= de_malloc(dfctx
->c
, sizeof(struct lzahuf_ctx
));
95 cctx
->modname
= "lzhuf";
97 cctx
->dcmpro
= dfctx
->dcmpro
;
98 cctx
->dres
= dfctx
->dres
;
100 dfctx
->codec_private
= (void*)cctx
;
101 dfctx
->codec_addbuf_fn
= my_lh1_codec_addbuf
;
102 dfctx
->codec_finish_fn
= my_lh1_codec_finish
;
103 dfctx
->codec_command_fn
= my_lh1_codec_command
;
104 dfctx
->codec_destroy_fn
= my_lh1_codec_destroy
;
106 if(codec_private_params
) {
107 // Use params from caller, if present.
108 de_memcpy(&cctx
->lh1p
, codec_private_params
, sizeof(struct de_lh1_params
));
111 // Set default params.
112 cctx
->lh1p
.history_fill_val
= 0x20;
115 lzhuf_Decode_init(cctx
);
118 // codec_private_params: 'struct de_lh1_params'. Can be NULL.
119 void fmtutil_lh1_codectype1(deark
*c
, struct de_dfilter_in_params
*dcmpri
,
120 struct de_dfilter_out_params
*dcmpro
, struct de_dfilter_results
*dres
,
121 void *codec_private_params
)
123 de_dfilter_decompress_oneshot(c
, dfilter_lh1_codec
, codec_private_params
,
124 dcmpri
, dcmpro
, dres
);