~vdupras/duskos

7a619571ed1a12ec43fa28372a67b561febada36 — Virgil Dupras 2 months ago 6e6395f
ar/puff: stream to StdOut
1 files changed, 32 insertions(+), 32 deletions(-)

M fs/ar/puff.c
M fs/ar/puff.c => fs/ar/puff.c +32 -32
@@ 41,13 41,19 @@
#define FIXLCODES 288
#define OUTBUFLEN $10000

/* Output and buffering
 * The puff algorithm needs to access its previously outputted contents up to
 * 32K back. For this reason, we can't spit directly to StdOut. Instead, what we
 * do is we have a buffer of twice the required size (64K) and spit there. This
 * buffer is split in 2 pages. Whenever we hit the limit of one of the pages, we
 * check if the other page is full. If yes, we spit it to StdOut and go on.
*/

/* input and output state */
struct state {
	/* output state */
	unsigned char out[OUTBUFLEN];	/* output buffer */
	unsigned int outcnt;		/* bytes written to out so far */

	/* input state */
	unsigned int outptr;        /* current position in output buffer */
	unsigned int outcnt;		/* total bytes written to out so far */
	unsigned char *in;			/* input buffer */
	unsigned int inlen;			/* available input at in */
	unsigned int incnt;			/* bytes read so far */


@@ 57,6 63,17 @@ struct state {

static state s;

static void spit(unsigned char c) {
	unsigned int pageptr;
	s.out[s.outptr++] = c;
	s.outcnt++;
	if ((s.outcnt>=OUTBUFLEN) && (!(s.outptr % (OUTBUFLEN/2)))) {
		// we finished a page and need to flush the "other"
		pageptr = s.outptr ^ (OUTBUFLEN/2); // ptr to "other"
		fwrite(&s.out[pageptr], OUTBUFLEN/2, StdOut());
	}
}

/*
 * Return need bits from the input stream.	This always leaves less than
 * eight bits in the buffer.  bits() works properly for need == 0.


@@ 128,16 145,8 @@ static int stored()
	/* copy len bytes from in to out */
	if (s.incnt + len > s.inlen)
		return 2;								/* not enough input */
	if (s.out != NULL) {
		if (s.outcnt + len > OUTBUFLEN)
			return 1;							/* not enough output space */
		while (len--)
			s.out[s.outcnt++] = s.in[s.incnt++];
	}
	else {										/* just scanning */
		s.outcnt += len;
		s.incnt += len;
	}
	while (len--)
		spit(s.in[s.incnt++]);

	/* done with a valid stored block */
	return 0;


@@ 355,12 364,7 @@ static int codes(huffman *lencode, huffman *distcode)
			return symbol;				/* invalid symbol */
		if (symbol < 256) {				/* literal: symbol is the byte */
			/* write out the literal */
			if (s.out != NULL) {
				if (s.outcnt == OUTBUFLEN)
					return 1;
				s.out[s.outcnt] = symbol;
			}
			s.outcnt++;
			spit(symbol);
		}
		else if (symbol > 256) {		/* length */
			/* get and compute length */


@@ 378,17 382,9 @@ static int codes(huffman *lencode, huffman *distcode)
				return -11;		/* distance too far back */

			/* copy length bytes from distance bytes back */
			if (s.out != NULL) {
				if (s.outcnt + len > OUTBUFLEN)
					return 1;
				while (len--) {
					s.out[s.outcnt] = dist > s.outcnt ?
						0 : s.out[s.outcnt - dist];
					s.outcnt++;
				}
			while (len--) {
				spit(dist > s.outcnt ? 0 : s.out[(s.outcnt - dist) % OUTBUFLEN]);
			}
			else
				s.outcnt += len;
		}
	} while (symbol != 256);			/* end of block symbol */



@@ 681,7 677,9 @@ int puff(unsigned char *source, unsigned int sourcelen)
{
	int last, type;				/* block information */
	int err;					/* return value */
	unsigned int pageptr;

	s.outptr = 0;
	s.outcnt = 0;
	s.in = source;
	s.inlen = sourcelen;


@@ 701,9 699,11 @@ int puff(unsigned char *source, unsigned int sourcelen)
			break;					/* return with error */
	} while (!last);

	/* update the lengths and return */
	if (err <= 0) {
		fwrite(s.out, s.outcnt, StdOut());
		pageptr = s.outptr & (OUTBUFLEN/2);
		if (s.outptr-pageptr) {
			fwrite(&s.out[pageptr], s.outptr-pageptr, StdOut());
		}
	}
	return err;
}