duskos

dusk os fork
git clone git://git.alexwennerberg.com/duskos
Log | Files | Refs | README | LICENSE

commit 7a619571ed1a12ec43fa28372a67b561febada36
parent 6e6395f0eb761e375826676c1abd74ebae1ea185
Author: Virgil Dupras <hsoft@hardcoded.net>
Date:   Wed, 30 Nov 2022 18:25:39 -0500

ar/puff: stream to StdOut

Diffstat:
Mfs/ar/puff.c | 64++++++++++++++++++++++++++++++++--------------------------------
1 file changed, 32 insertions(+), 32 deletions(-)

diff --git a/fs/ar/puff.c b/fs/ar/puff.c @@ -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; }