/* inflate.c * expands a Deflate (RFC 1951) stream */ #include #include #include #include #include "ot.h" #define PUSHBYTE(val) do { \ is->bitbuf|=(val)<bitbuf_len; \ is->bitbuf_len+=8; /* we can only take 8-bit chars */ \ } while(0) #define READBITS(dest, n) do { \ if(is->bitbuf_len < n) { \ OT_WAIT_WHILE(&is->state, buflen<1); \ PUSHBYTE(*p); \ p++; buflen--; \ } \ (dest)=is->bitbuf&~((~0)<bitbuf>>=n; \ is->bitbuf_len-=n; \ } while(0) struct inflate_state { char *name; unsigned bitbuf; /* big enough to hold a 15 bit value */ int bitbuf_len; struct ot_state state; unsigned lit, dist, len; /* used in the dynamic huffman code section */ }; int inflate_init(struct inflate_state *is, const char *name) { is->name=strdup(name); is->bitbuf_len=0; OT_INITIALIZE(&is->state); return 1; } int inflate_update(struct inflate_state *is, void *buf, size_t buflen) { unsigned char *p=buf; unsigned x; OT_BEGIN(&is->state); READBITS(x, 1); fprintf(stderr, "Last block: %d\n", x); READBITS(x, 2); fprintf(stderr, "Type: %d\n", x); if(x==2) { /* dynamic huffman codes */ READBITS(x, 5); is->lit=x+257; /* literal codes */ printf("LiteralCodes: %u\n", is->lit); READBITS(x, 5); is->dist=x+1; /* dist codes */ printf("DistCodes: %u\n", is->dist); READBITS(x, 4); is->len=4+x; /* len codes */ printf("LenCodes: %u\n", is->len); } else { fprintf(stderr, "unknown type %d\n", x); } /* flush bitbuf */ fprintf(stderr, "remaining: 0x%02x\n", is->bitbuf&~((~0)<bitbuf_len)); is->bitbuf_len=0; while(1) { OT_WAIT_WHILE(&is->state, buflen<=0); p++; buflen--; } OT_END(&is->state); return 1; } int inflate_final(struct inflate_state *is) { free(is->name); return 1; } #ifdef STAND_ALONE int main(int argc, char **argv) { struct inflate_state is; char buf[64]; int len; int total_len; total_len=0; inflate_init(&is, "stdin"); while((len=fread(buf, 1, sizeof buf, stdin))>0) { total_len+=len; inflate_update(&is, buf, len); } if(len<0) perror("stdin"); inflate_final(&is); fprintf(stderr, "%d bytes\n", total_len); return 0; } #endif /* CRAP */ #if 0 /* CMF */ OT_WAIT_WHILE(&is->state, buflen<1); printf("CMF: %02x\n", *p); printf("\tCM: %u\n", *p&15); if((*p&15) == 8) { /* CINFO */ printf("\tCINFO: %u\n", *p>>4); } p++; buflen--; /* FLG */ OT_WAIT_WHILE(&is->state, buflen<1); printf("FLG: %02x\n", *p); p++; buflen--; while(1) { OT_WAIT_WHILE(&is->state, buflen<=0); p++; buflen--; } #endif