[w3m-dev 02960] inflate without memmove()

* inflate.c: rewrite without memmove()
From: Hironori Sakamoto <hsaka@mth.biglobe.ne.jp>
This commit is contained in:
Fumitoshi UKAI
2002-01-31 15:26:19 +00:00
parent 825c620c69
commit 97f3d67793
2 changed files with 64 additions and 150 deletions

View File

@@ -6,6 +6,11 @@
* doc-jp/README: ditto
* NEWS: update
2002-01-31 Hironori Sakamoto <hsaka@mth.biglobe.ne.jp>
* [w3m-dev 02960] inflate without memmove()
* inflate.c: rewrite without memmove()
2002-01-31 Kiyokazu SUTO <suto@ks-and-ks.ne.jp>
* inflate.c: support raw deflate without zlib header
@@ -2480,4 +2485,4 @@
* release-0-2-1
* import w3m-0.2.1
$Id: ChangeLog,v 1.284 2002/01/31 15:00:58 ukai Exp $
$Id: ChangeLog,v 1.285 2002/01/31 15:26:19 ukai Exp $

207
inflate.c
View File

@@ -1,174 +1,83 @@
#include <errno.h>
/* $Id: inflate.c,v 1.6 2002/01/31 15:26:19 ukai Exp $ */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <zlib.h>
#define MYBUFSIZ (BUFSIZ * 0x10)
#undef BUFSIZE
#define BUFSIZE 4096
/* cf. rfc1950.txt */
static char dummy_head[1 + 1] = {
0x8 + 0x7 * 0x10,
(((0x8 + 0x7 * 0x10) * 0x100 + 30) / 31 * 31) & 0xFF,
};
int
main(int argc, char *argv[])
main(int argc, char **argv)
{
int err, nfiles, i, nin, inrest, eoin, nout, outrest, eoout, ninflates,
raw;
z_stream d_stream;
char *me = argv[0];
char *inbuf, *outbuf, **filev;
if (!(inbuf = malloc(MYBUFSIZ))) {
fprintf(stderr, "%s: inbuf = malloc(%lu): %s\n", me,
(unsigned long)MYBUFSIZ, strerror(errno));
exit(1);
}
if (!(outbuf = malloc(MYBUFSIZ))) {
fprintf(stderr, "%s: outbuf = malloc(%lu): %s\n", me,
(unsigned long)MYBUFSIZ, strerror(errno));
exit(1);
}
d_stream.zalloc = NULL;
d_stream.zfree = NULL;
d_stream.opaque = NULL;
z_stream s;
FILE *f;
char inbuf[BUFSIZE], outbuf[BUFSIZE];
int status, flush, retry = 0, len = 0;
if (argc > 1) {
nfiles = argc - 1;
filev = &argv[1];
f = fopen(argv[1], "rb");
if (!f) {
fprintf(stderr, "%s: cannot open %s\n", argv[0], argv[1]);
exit(1);
}
}
else {
static char *myargv[] = { "-", NULL };
else
f = stdin;
nfiles = 1;
filev = myargv;
}
if ((err = inflateInit(&d_stream)) != Z_OK) {
fprintf(stderr, "%s: inflateInit(&d_stream): %d\n", me, err);
s.zalloc = Z_NULL;
s.zfree = Z_NULL;
s.opaque = Z_NULL;
status = inflateInit(&s);
if (status != Z_OK) {
fprintf(stderr, "%s: inflateInit() %s\n", argv[0], zError(status));
exit(1);
}
for (raw = ninflates = i = inrest = outrest = 0, eoout = 1; i < nfiles;
++i) {
FILE *in;
if (strcmp(filev[i], "-")) {
if (!(in = fopen(filev[i], "rb"))) {
fprintf(stderr, "%s: fopen(\"%s\", \"rb\"): %s\n", me,
filev[i], strerror(errno));
s.avail_in = 0;
s.next_out = (Bytef *) outbuf;
s.avail_out = sizeof(outbuf);
flush = Z_NO_FLUSH;
while (1) {
if (s.avail_in == 0) {
s.next_in = (Bytef *) inbuf;
len = s.avail_in = fread(inbuf, 1, sizeof(inbuf), f);
}
status = inflate(&s, flush);
if (status == Z_STREAM_END || status == Z_BUF_ERROR) {
if (sizeof(outbuf) - s.avail_out)
fwrite(outbuf, 1, sizeof(outbuf) - s.avail_out, stdout);
break;
}
if (status == Z_DATA_ERROR && ! retry++) {
status = inflateReset(&s);
if (status != Z_OK) {
fprintf(stderr, "%s: inflateReset() %s\n", argv[0],
zError(status));
exit(1);
}
s.next_in = (Bytef *) dummy_head;
s.avail_in = sizeof(dummy_head);
status = inflate(&s, flush);
s.next_in = (Bytef *) inbuf;
s.avail_in = len;
continue;
}
else
in = stdin;
for (eoin = 0;;) {
if ((nin =
fread(&inbuf[inrest], 1, MYBUFSIZ - inrest,
in)) < MYBUFSIZ - inrest) {
if (ferror(in)) {
fprintf(stderr, "%s: fread(&inbuf[%d], 1, %d, in): %s\n",
me, inrest, MYBUFSIZ - inrest, strerror(errno));
exit(1);
}
eoin = 1;
}
if (nin > 0) {
retry:
d_stream.next_in = inbuf;
d_stream.avail_in = inrest + nin;
for (eoout = 0;;) {
d_stream.next_out = &outbuf[outrest];
d_stream.avail_out = MYBUFSIZ - outrest;
switch (err = inflate(&d_stream, Z_NO_FLUSH)) {
case Z_OK:
if (!
((nout =
fwrite(outbuf, 1, MYBUFSIZ - d_stream.avail_out,
stdout)) > 0)) {
fprintf(stderr,
"%s: fwrite(outbuf, 1, %d, stdout): %s\n",
me, MYBUFSIZ - d_stream.avail_out,
strerror(errno));
exit(1);
}
memmove(outbuf, &outbuf[nout],
MYBUFSIZ - d_stream.avail_out - nout);
outrest = MYBUFSIZ - d_stream.avail_out - nout;
++ninflates;
break;
case Z_STREAM_END:
case Z_BUF_ERROR:
ninflates = 0;
outrest = MYBUFSIZ - d_stream.avail_out;
eoout = 1;
goto next_fread;
case Z_DATA_ERROR:
if (!ninflates) {
if ((err = inflateReset(&d_stream)) != Z_OK) {
fprintf(stderr,
"%s: inflateReset(&d_stream): %d\n",
me, err);
exit(1);
}
d_stream.next_in = dummy_head;
d_stream.avail_in = sizeof(dummy_head);
if ((err = inflate(&d_stream, Z_NO_FLUSH)) == Z_OK) {
raw = ninflates = 1;
goto retry;
}
}
default:
fprintf(stderr,
"%s: inflate(&d_stream, Z_NO_FLUSH): %d\n", me,
err);
exit(1);
}
}
}
next_fread:
if (d_stream.avail_in) {
memmove(inbuf, &inbuf[inrest + nin - d_stream.avail_in],
d_stream.avail_in);
inrest = d_stream.avail_in;
}
else
inrest = 0;
if (eoin)
break;
if (status != Z_OK) {
fprintf(stderr, "%s: inflate() %s\n", argv[0], zError(status));
exit(1);
}
if (in != stdin)
fclose(in);
if (s.avail_out == 0) {
fwrite(outbuf, 1, sizeof(outbuf), stdout);
s.next_out = (Bytef *) outbuf;
s.avail_out = sizeof(outbuf);
}
retry = 1;
}
if (!eoout && !raw) {
fprintf(stderr, "%s: short input\n", me);
exit(1);
}
if (inrest)
fprintf(stderr, "%s: trailing garbages are ignored\n", me);
if (outrest && fwrite(outbuf, 1, outrest, stdout) < outrest) {
fprintf(stderr, "%s: fwrite(outbuf, 1, %d, stdout): %s\n", me, outrest,
strerror(errno));
exit(1);
}
inflateEnd(&s);
fclose(f);
return 0;
}