mirror of
https://github.com/Rockbox/rockbox.git
synced 2025-12-08 20:55:17 -05:00
Add libmspack to rbutil
Change-Id: I520c14131ec1e12013f106c13cba00aac058ad83 Reviewed-on: http://gerrit.rockbox.org/391 Reviewed-by: Dominik Riebeling <Dominik.Riebeling@gmail.com>
This commit is contained in:
parent
27111d83be
commit
739a7ae0e9
37 changed files with 10082 additions and 0 deletions
555
rbutil/rbutilqt/mspack/kwajd.c
Normal file
555
rbutil/rbutilqt/mspack/kwajd.c
Normal file
|
|
@ -0,0 +1,555 @@
|
|||
/* This file is part of libmspack.
|
||||
* (C) 2003-2010 Stuart Caie.
|
||||
*
|
||||
* KWAJ is a format very similar to SZDD. KWAJ method 3 (LZH) was
|
||||
* written by Jeff Johnson.
|
||||
*
|
||||
* libmspack is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Lesser General Public License (LGPL) version 2.1
|
||||
*
|
||||
* For further details, see the file COPYING.LIB distributed with libmspack
|
||||
*/
|
||||
|
||||
/* KWAJ decompression implementation */
|
||||
|
||||
#include <system.h>
|
||||
#include <kwaj.h>
|
||||
|
||||
/* prototypes */
|
||||
static struct mskwajd_header *kwajd_open(
|
||||
struct mskwaj_decompressor *base, const char *filename);
|
||||
static void kwajd_close(
|
||||
struct mskwaj_decompressor *base, struct mskwajd_header *hdr);
|
||||
static int kwajd_read_headers(
|
||||
struct mspack_system *sys, struct mspack_file *fh,
|
||||
struct mskwajd_header *hdr);
|
||||
static int kwajd_extract(
|
||||
struct mskwaj_decompressor *base, struct mskwajd_header *hdr,
|
||||
const char *filename);
|
||||
static int kwajd_decompress(
|
||||
struct mskwaj_decompressor *base, const char *input, const char *output);
|
||||
static int kwajd_error(
|
||||
struct mskwaj_decompressor *base);
|
||||
|
||||
static struct kwajd_stream *lzh_init(
|
||||
struct mspack_system *sys, struct mspack_file *in, struct mspack_file *out);
|
||||
static int lzh_decompress(
|
||||
struct kwajd_stream *kwaj);
|
||||
static void lzh_free(
|
||||
struct kwajd_stream *kwaj);
|
||||
static int lzh_read_lens(
|
||||
struct kwajd_stream *kwaj,
|
||||
unsigned int type, unsigned int numsyms,
|
||||
unsigned char *lens, unsigned short *table);
|
||||
static int lzh_read_input(
|
||||
struct kwajd_stream *kwaj);
|
||||
|
||||
|
||||
/***************************************
|
||||
* MSPACK_CREATE_KWAJ_DECOMPRESSOR
|
||||
***************************************
|
||||
* constructor
|
||||
*/
|
||||
struct mskwaj_decompressor *
|
||||
mspack_create_kwaj_decompressor(struct mspack_system *sys)
|
||||
{
|
||||
struct mskwaj_decompressor_p *self = NULL;
|
||||
|
||||
if (!sys) sys = mspack_default_system;
|
||||
if (!mspack_valid_system(sys)) return NULL;
|
||||
|
||||
if ((self = (struct mskwaj_decompressor_p *) sys->alloc(sys, sizeof(struct mskwaj_decompressor_p)))) {
|
||||
self->base.open = &kwajd_open;
|
||||
self->base.close = &kwajd_close;
|
||||
self->base.extract = &kwajd_extract;
|
||||
self->base.decompress = &kwajd_decompress;
|
||||
self->base.last_error = &kwajd_error;
|
||||
self->system = sys;
|
||||
self->error = MSPACK_ERR_OK;
|
||||
}
|
||||
return (struct mskwaj_decompressor *) self;
|
||||
}
|
||||
|
||||
/***************************************
|
||||
* MSPACK_DESTROY_KWAJ_DECOMPRESSOR
|
||||
***************************************
|
||||
* destructor
|
||||
*/
|
||||
void mspack_destroy_kwaj_decompressor(struct mskwaj_decompressor *base)
|
||||
{
|
||||
struct mskwaj_decompressor_p *self = (struct mskwaj_decompressor_p *) base;
|
||||
if (self) {
|
||||
struct mspack_system *sys = self->system;
|
||||
sys->free(self);
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************
|
||||
* KWAJD_OPEN
|
||||
***************************************
|
||||
* opens a KWAJ file without decompressing, reads header
|
||||
*/
|
||||
static struct mskwajd_header *kwajd_open(struct mskwaj_decompressor *base,
|
||||
const char *filename)
|
||||
{
|
||||
struct mskwaj_decompressor_p *self = (struct mskwaj_decompressor_p *) base;
|
||||
struct mskwajd_header *hdr;
|
||||
struct mspack_system *sys;
|
||||
struct mspack_file *fh;
|
||||
|
||||
if (!self) return NULL;
|
||||
sys = self->system;
|
||||
|
||||
fh = sys->open(sys, filename, MSPACK_SYS_OPEN_READ);
|
||||
hdr = (struct mskwajd_header *) sys->alloc(sys, sizeof(struct mskwajd_header_p));
|
||||
if (fh && hdr) {
|
||||
((struct mskwajd_header_p *) hdr)->fh = fh;
|
||||
self->error = kwajd_read_headers(sys, fh, hdr);
|
||||
}
|
||||
else {
|
||||
if (!fh) self->error = MSPACK_ERR_OPEN;
|
||||
if (!hdr) self->error = MSPACK_ERR_NOMEMORY;
|
||||
}
|
||||
|
||||
if (self->error) {
|
||||
if (fh) sys->close(fh);
|
||||
if (hdr) sys->free(hdr);
|
||||
hdr = NULL;
|
||||
}
|
||||
|
||||
return hdr;
|
||||
}
|
||||
|
||||
/***************************************
|
||||
* KWAJD_CLOSE
|
||||
***************************************
|
||||
* closes a KWAJ file
|
||||
*/
|
||||
static void kwajd_close(struct mskwaj_decompressor *base,
|
||||
struct mskwajd_header *hdr)
|
||||
{
|
||||
struct mskwaj_decompressor_p *self = (struct mskwaj_decompressor_p *) base;
|
||||
struct mskwajd_header_p *hdr_p = (struct mskwajd_header_p *) hdr;
|
||||
|
||||
if (!self || !self->system) return;
|
||||
|
||||
/* close the file handle associated */
|
||||
self->system->close(hdr_p->fh);
|
||||
|
||||
/* free the memory associated */
|
||||
self->system->free(hdr);
|
||||
|
||||
self->error = MSPACK_ERR_OK;
|
||||
}
|
||||
|
||||
/***************************************
|
||||
* KWAJD_READ_HEADERS
|
||||
***************************************
|
||||
* reads the headers of a KWAJ format file
|
||||
*/
|
||||
static int kwajd_read_headers(struct mspack_system *sys,
|
||||
struct mspack_file *fh,
|
||||
struct mskwajd_header *hdr)
|
||||
{
|
||||
unsigned char buf[16];
|
||||
int i;
|
||||
|
||||
/* read in the header */
|
||||
if (sys->read(fh, &buf[0], kwajh_SIZEOF) != kwajh_SIZEOF) {
|
||||
return MSPACK_ERR_READ;
|
||||
}
|
||||
|
||||
/* check for "KWAJ" signature */
|
||||
if (((unsigned int) EndGetI32(&buf[kwajh_Signature1]) != 0x4A41574B) ||
|
||||
((unsigned int) EndGetI32(&buf[kwajh_Signature2]) != 0xD127F088))
|
||||
{
|
||||
return MSPACK_ERR_SIGNATURE;
|
||||
}
|
||||
|
||||
/* basic header fields */
|
||||
hdr->comp_type = EndGetI16(&buf[kwajh_CompMethod]);
|
||||
hdr->data_offset = EndGetI16(&buf[kwajh_DataOffset]);
|
||||
hdr->headers = EndGetI16(&buf[kwajh_Flags]);
|
||||
hdr->length = 0;
|
||||
hdr->filename = NULL;
|
||||
hdr->extra = NULL;
|
||||
hdr->extra_length = 0;
|
||||
|
||||
/* optional headers */
|
||||
|
||||
/* 4 bytes: length of unpacked file */
|
||||
if (hdr->headers & MSKWAJ_HDR_HASLENGTH) {
|
||||
if (sys->read(fh, &buf[0], 4) != 4) return MSPACK_ERR_READ;
|
||||
hdr->length = EndGetI32(&buf[0]);
|
||||
}
|
||||
|
||||
/* 2 bytes: unknown purpose */
|
||||
if (hdr->headers & MSKWAJ_HDR_HASUNKNOWN1) {
|
||||
if (sys->read(fh, &buf[0], 2) != 2) return MSPACK_ERR_READ;
|
||||
}
|
||||
|
||||
/* 2 bytes: length of section, then [length] bytes: unknown purpose */
|
||||
if (hdr->headers & MSKWAJ_HDR_HASUNKNOWN2) {
|
||||
if (sys->read(fh, &buf[0], 2) != 2) return MSPACK_ERR_READ;
|
||||
i = EndGetI16(&buf[0]);
|
||||
if (sys->seek(fh, (off_t)i, MSPACK_SYS_SEEK_CUR)) return MSPACK_ERR_SEEK;
|
||||
}
|
||||
|
||||
/* filename and extension */
|
||||
if (hdr->headers & (MSKWAJ_HDR_HASFILENAME | MSKWAJ_HDR_HASFILEEXT)) {
|
||||
off_t pos = sys->tell(fh);
|
||||
char *fn = (char *) sys->alloc(sys, (size_t) 13);
|
||||
|
||||
/* allocate memory for maximum length filename */
|
||||
if (! fn) return MSPACK_ERR_NOMEMORY;
|
||||
hdr->filename = fn;
|
||||
|
||||
/* copy filename if present */
|
||||
if (hdr->headers & MSKWAJ_HDR_HASFILENAME) {
|
||||
if (sys->read(fh, &buf[0], 9) != 9) return MSPACK_ERR_READ;
|
||||
for (i = 0; i < 9; i++, fn++) if (!(*fn = buf[i])) break;
|
||||
pos += (i < 9) ? i+1 : 9;
|
||||
if (sys->seek(fh, pos, MSPACK_SYS_SEEK_START))
|
||||
return MSPACK_ERR_SEEK;
|
||||
}
|
||||
|
||||
/* copy extension if present */
|
||||
if (hdr->headers & MSKWAJ_HDR_HASFILEEXT) {
|
||||
*fn++ = '.';
|
||||
if (sys->read(fh, &buf[0], 4) != 4) return MSPACK_ERR_READ;
|
||||
for (i = 0; i < 4; i++, fn++) if (!(*fn = buf[i])) break;
|
||||
pos += (i < 4) ? i+1 : 4;
|
||||
if (sys->seek(fh, pos, MSPACK_SYS_SEEK_START))
|
||||
return MSPACK_ERR_SEEK;
|
||||
}
|
||||
*fn = '\0';
|
||||
}
|
||||
|
||||
/* 2 bytes: extra text length then [length] bytes of extra text data */
|
||||
if (hdr->headers & MSKWAJ_HDR_HASEXTRATEXT) {
|
||||
if (sys->read(fh, &buf[0], 2) != 2) return MSPACK_ERR_READ;
|
||||
i = EndGetI16(&buf[0]);
|
||||
hdr->extra = (char *) sys->alloc(sys, (size_t)i+1);
|
||||
if (! hdr->extra) return MSPACK_ERR_NOMEMORY;
|
||||
if (sys->read(fh, hdr->extra, i) != i) return MSPACK_ERR_READ;
|
||||
hdr->extra[i] = '\0';
|
||||
hdr->extra_length = i;
|
||||
}
|
||||
return MSPACK_ERR_OK;
|
||||
}
|
||||
|
||||
/***************************************
|
||||
* KWAJD_EXTRACT
|
||||
***************************************
|
||||
* decompresses a KWAJ file
|
||||
*/
|
||||
static int kwajd_extract(struct mskwaj_decompressor *base,
|
||||
struct mskwajd_header *hdr, const char *filename)
|
||||
{
|
||||
struct mskwaj_decompressor_p *self = (struct mskwaj_decompressor_p *) base;
|
||||
struct mspack_system *sys;
|
||||
struct mspack_file *fh, *outfh;
|
||||
|
||||
if (!self) return MSPACK_ERR_ARGS;
|
||||
if (!hdr) return self->error = MSPACK_ERR_ARGS;
|
||||
|
||||
sys = self->system;
|
||||
fh = ((struct mskwajd_header_p *) hdr)->fh;
|
||||
|
||||
/* seek to the compressed data */
|
||||
if (sys->seek(fh, hdr->data_offset, MSPACK_SYS_SEEK_START)) {
|
||||
return self->error = MSPACK_ERR_SEEK;
|
||||
}
|
||||
|
||||
/* open file for output */
|
||||
if (!(outfh = sys->open(sys, filename, MSPACK_SYS_OPEN_WRITE))) {
|
||||
return self->error = MSPACK_ERR_OPEN;
|
||||
}
|
||||
|
||||
self->error = MSPACK_ERR_OK;
|
||||
|
||||
/* decompress based on format */
|
||||
if (hdr->comp_type == MSKWAJ_COMP_NONE ||
|
||||
hdr->comp_type == MSKWAJ_COMP_XOR)
|
||||
{
|
||||
/* NONE is a straight copy. XOR is a copy xored with 0xFF */
|
||||
unsigned char *buf = (unsigned char *) sys->alloc(sys, (size_t) KWAJ_INPUT_SIZE);
|
||||
if (buf) {
|
||||
int read, i;
|
||||
while ((read = sys->read(fh, buf, KWAJ_INPUT_SIZE)) > 0) {
|
||||
if (hdr->comp_type == MSKWAJ_COMP_XOR) {
|
||||
for (i = 0; i < read; i++) buf[i] ^= 0xFF;
|
||||
}
|
||||
if (sys->write(outfh, buf, read) != read) {
|
||||
self->error = MSPACK_ERR_WRITE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (read < 0) self->error = MSPACK_ERR_READ;
|
||||
sys->free(buf);
|
||||
}
|
||||
else {
|
||||
self->error = MSPACK_ERR_NOMEMORY;
|
||||
}
|
||||
}
|
||||
else if (hdr->comp_type == MSKWAJ_COMP_SZDD) {
|
||||
self->error = lzss_decompress(sys, fh, outfh, KWAJ_INPUT_SIZE,
|
||||
LZSS_MODE_EXPAND);
|
||||
}
|
||||
else if (hdr->comp_type == MSKWAJ_COMP_LZH) {
|
||||
struct kwajd_stream *lzh = lzh_init(sys, fh, outfh);
|
||||
self->error = (lzh) ? lzh_decompress(lzh) : MSPACK_ERR_NOMEMORY;
|
||||
lzh_free(lzh);
|
||||
}
|
||||
else {
|
||||
self->error = MSPACK_ERR_DATAFORMAT;
|
||||
}
|
||||
|
||||
/* close output file */
|
||||
sys->close(outfh);
|
||||
|
||||
return self->error;
|
||||
}
|
||||
|
||||
/***************************************
|
||||
* KWAJD_DECOMPRESS
|
||||
***************************************
|
||||
* unpacks directly from input to output
|
||||
*/
|
||||
static int kwajd_decompress(struct mskwaj_decompressor *base,
|
||||
const char *input, const char *output)
|
||||
{
|
||||
struct mskwaj_decompressor_p *self = (struct mskwaj_decompressor_p *) base;
|
||||
struct mskwajd_header *hdr;
|
||||
int error;
|
||||
|
||||
if (!self) return MSPACK_ERR_ARGS;
|
||||
|
||||
if (!(hdr = kwajd_open(base, input))) return self->error;
|
||||
error = kwajd_extract(base, hdr, output);
|
||||
kwajd_close(base, hdr);
|
||||
return self->error = error;
|
||||
}
|
||||
|
||||
/***************************************
|
||||
* KWAJD_ERROR
|
||||
***************************************
|
||||
* returns the last error that occurred
|
||||
*/
|
||||
static int kwajd_error(struct mskwaj_decompressor *base)
|
||||
{
|
||||
struct mskwaj_decompressor_p *self = (struct mskwaj_decompressor_p *) base;
|
||||
return (self) ? self->error : MSPACK_ERR_ARGS;
|
||||
}
|
||||
|
||||
/***************************************
|
||||
* LZH_INIT, LZH_DECOMPRESS, LZH_FREE
|
||||
***************************************
|
||||
* unpacks KWAJ method 3 files
|
||||
*/
|
||||
|
||||
/* import bit-reading macros and code */
|
||||
#define BITS_TYPE struct kwajd_stream
|
||||
#define BITS_VAR lzh
|
||||
#define BITS_ORDER_MSB
|
||||
#define BITS_NO_READ_INPUT
|
||||
#define READ_BYTES do { \
|
||||
if (i_ptr >= i_end) { \
|
||||
if ((err = lzh_read_input(lzh))) return err; \
|
||||
i_ptr = lzh->i_ptr; \
|
||||
i_end = lzh->i_end; \
|
||||
} \
|
||||
INJECT_BITS(*i_ptr++, 8); \
|
||||
} while (0)
|
||||
#include <readbits.h>
|
||||
|
||||
/* import huffman-reading macros and code */
|
||||
#define TABLEBITS(tbl) KWAJ_TABLEBITS
|
||||
#define MAXSYMBOLS(tbl) KWAJ_##tbl##_SYMS
|
||||
#define HUFF_TABLE(tbl,idx) lzh->tbl##_table[idx]
|
||||
#define HUFF_LEN(tbl,idx) lzh->tbl##_len[idx]
|
||||
#define HUFF_ERROR return MSPACK_ERR_DATAFORMAT
|
||||
#include <readhuff.h>
|
||||
|
||||
/* In the KWAJ LZH format, there is no special 'eof' marker, it just
|
||||
* ends. Depending on how many bits are left in the final byte when
|
||||
* the stream ends, that might be enough to start another literal or
|
||||
* match. The only easy way to detect that we've come to an end is to
|
||||
* guard all bit-reading. We allow fake bits to be read once we reach
|
||||
* the end of the stream, but we check if we then consumed any of
|
||||
* those fake bits, after doing the READ_BITS / READ_HUFFSYM. This
|
||||
* isn't how the default readbits.h read_input() works (it simply lets
|
||||
* 2 fake bytes in then stops), so we implement our own.
|
||||
*/
|
||||
#define READ_BITS_SAFE(val, n) do { \
|
||||
READ_BITS(val, n); \
|
||||
if (lzh->input_end && bits_left < lzh->input_end) \
|
||||
return MSPACK_ERR_OK; \
|
||||
} while (0)
|
||||
|
||||
#define READ_HUFFSYM_SAFE(tbl, val) do { \
|
||||
READ_HUFFSYM(tbl, val); \
|
||||
if (lzh->input_end && bits_left < lzh->input_end) \
|
||||
return MSPACK_ERR_OK; \
|
||||
} while (0)
|
||||
|
||||
#define BUILD_TREE(tbl, type) \
|
||||
STORE_BITS; \
|
||||
err = lzh_read_lens(lzh, type, MAXSYMBOLS(tbl), \
|
||||
&HUFF_LEN(tbl,0), &HUFF_TABLE(tbl,0)); \
|
||||
if (err) return err; \
|
||||
RESTORE_BITS; \
|
||||
if (make_decode_table(MAXSYMBOLS(tbl), TABLEBITS(tbl), \
|
||||
&HUFF_LEN(tbl,0), &HUFF_TABLE(tbl,0))) \
|
||||
return MSPACK_ERR_DATAFORMAT;
|
||||
|
||||
#define WRITE_BYTE do { \
|
||||
if (lzh->sys->write(lzh->output, &lzh->window[pos], 1) != 1) \
|
||||
return MSPACK_ERR_WRITE; \
|
||||
} while (0)
|
||||
|
||||
static struct kwajd_stream *lzh_init(struct mspack_system *sys,
|
||||
struct mspack_file *in, struct mspack_file *out)
|
||||
{
|
||||
struct kwajd_stream *lzh;
|
||||
|
||||
if (!sys || !in || !out) return NULL;
|
||||
if (!(lzh = (struct kwajd_stream *) sys->alloc(sys, sizeof(struct kwajd_stream)))) return NULL;
|
||||
|
||||
lzh->sys = sys;
|
||||
lzh->input = in;
|
||||
lzh->output = out;
|
||||
return lzh;
|
||||
}
|
||||
|
||||
static int lzh_decompress(struct kwajd_stream *lzh)
|
||||
{
|
||||
register unsigned int bit_buffer;
|
||||
register int bits_left, i;
|
||||
register unsigned short sym;
|
||||
unsigned char *i_ptr, *i_end, lit_run = 0;
|
||||
int j, pos = 0, len, offset, err;
|
||||
unsigned int types[6];
|
||||
|
||||
/* reset global state */
|
||||
INIT_BITS;
|
||||
RESTORE_BITS;
|
||||
memset(&lzh->window[0], LZSS_WINDOW_FILL, (size_t) LZSS_WINDOW_SIZE);
|
||||
|
||||
/* read 6 encoding types (for byte alignment) but only 5 are needed */
|
||||
for (i = 0; i < 6; i++) READ_BITS_SAFE(types[i], 4);
|
||||
|
||||
/* read huffman table symbol lengths and build huffman trees */
|
||||
BUILD_TREE(MATCHLEN1, types[0]);
|
||||
BUILD_TREE(MATCHLEN2, types[1]);
|
||||
BUILD_TREE(LITLEN, types[2]);
|
||||
BUILD_TREE(OFFSET, types[3]);
|
||||
BUILD_TREE(LITERAL, types[4]);
|
||||
|
||||
while (!lzh->input_end) {
|
||||
if (lit_run) READ_HUFFSYM_SAFE(MATCHLEN2, len);
|
||||
else READ_HUFFSYM_SAFE(MATCHLEN1, len);
|
||||
|
||||
if (len > 0) {
|
||||
len += 2;
|
||||
lit_run = 0; /* not the end of a literal run */
|
||||
READ_HUFFSYM_SAFE(OFFSET, j); offset = j << 6;
|
||||
READ_BITS_SAFE(j, 6); offset |= j;
|
||||
|
||||
/* copy match as output and into the ring buffer */
|
||||
while (len-- > 0) {
|
||||
lzh->window[pos] = lzh->window[(pos+4096-offset) & 4095];
|
||||
WRITE_BYTE;
|
||||
pos++; pos &= 4095;
|
||||
}
|
||||
}
|
||||
else {
|
||||
READ_HUFFSYM_SAFE(LITLEN, len); len++;
|
||||
lit_run = (len == 32) ? 0 : 1; /* end of a literal run? */
|
||||
while (len-- > 0) {
|
||||
READ_HUFFSYM_SAFE(LITERAL, j);
|
||||
/* copy as output and into the ring buffer */
|
||||
lzh->window[pos] = j;
|
||||
WRITE_BYTE;
|
||||
pos++; pos &= 4095;
|
||||
}
|
||||
}
|
||||
}
|
||||
return MSPACK_ERR_OK;
|
||||
}
|
||||
|
||||
static void lzh_free(struct kwajd_stream *lzh)
|
||||
{
|
||||
struct mspack_system *sys;
|
||||
if (!lzh || !lzh->sys) return;
|
||||
sys = lzh->sys;
|
||||
sys->free(lzh);
|
||||
}
|
||||
|
||||
static int lzh_read_lens(struct kwajd_stream *lzh,
|
||||
unsigned int type, unsigned int numsyms,
|
||||
unsigned char *lens, unsigned short *table)
|
||||
{
|
||||
register unsigned int bit_buffer;
|
||||
register int bits_left;
|
||||
unsigned char *i_ptr, *i_end;
|
||||
unsigned int i, c, sel;
|
||||
int err;
|
||||
|
||||
RESTORE_BITS;
|
||||
switch (type) {
|
||||
case 0:
|
||||
i = numsyms; c = (i==16)?4: (i==32)?5: (i==64)?6: (i==256)?8 :0;
|
||||
for (i = 0; i < numsyms; i++) lens[i] = c;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
READ_BITS_SAFE(c, 4); lens[0] = c;
|
||||
for (i = 1; i < numsyms; i++) {
|
||||
READ_BITS_SAFE(sel, 1); if (sel == 0) lens[i] = c;
|
||||
else { READ_BITS_SAFE(sel, 1); if (sel == 0) lens[i] = ++c;
|
||||
else { READ_BITS_SAFE(c, 4); lens[i] = c; }}
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
READ_BITS_SAFE(c, 4); lens[0] = c;
|
||||
for (i = 1; i < numsyms; i++) {
|
||||
READ_BITS_SAFE(sel, 2);
|
||||
if (sel == 3) READ_BITS_SAFE(c, 4); else c += (char) sel-1;
|
||||
lens[i] = c;
|
||||
}
|
||||
break;
|
||||
|
||||
case 3:
|
||||
for (i = 0; i < numsyms; i++) {
|
||||
READ_BITS_SAFE(c, 4); lens[i] = c;
|
||||
}
|
||||
break;
|
||||
}
|
||||
STORE_BITS;
|
||||
return MSPACK_ERR_OK;
|
||||
}
|
||||
|
||||
static int lzh_read_input(struct kwajd_stream *lzh) {
|
||||
int read;
|
||||
if (lzh->input_end) {
|
||||
lzh->input_end += 8;
|
||||
lzh->inbuf[0] = 0;
|
||||
read = 1;
|
||||
}
|
||||
else {
|
||||
read = lzh->sys->read(lzh->input, &lzh->inbuf[0], KWAJ_INPUT_SIZE);
|
||||
if (read < 0) return MSPACK_ERR_READ;
|
||||
if (read == 0) {
|
||||
lzh->input_end = 8;
|
||||
lzh->inbuf[0] = 0;
|
||||
read = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* update i_ptr and i_end */
|
||||
lzh->i_ptr = &lzh->inbuf[0];
|
||||
lzh->i_end = &lzh->inbuf[read];
|
||||
return MSPACK_ERR_OK;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue