289acf3333
The build system used by rbutil is not very robust: all the files are eventually compiled to the same directory so we cannot have two files with the same name (system.c would conflicts with system.cpp) so rename one file to avoid this. Also change all include directives to local ones because we don't have to expose the entire mspack source to inclusion. Change-Id: I3fe0638d69fdc30566eb9425abfe33c807678b28 Reviewed-on: http://gerrit.rockbox.org/417 Reviewed-by: Dominik Riebeling <Dominik.Riebeling@gmail.com>
555 lines
16 KiB
C
555 lines
16 KiB
C
/* 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-mspack.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;
|
|
}
|