#include #include #include #include "blocker.h" struct deblocker { void (*string)(const void *, int, void *); void (*error)(void *, const char *, ...); void *cookie; int incount; int blkleft; unsigned char *dbuf; int dlen; int dalloc; } ; DEBLOCKER *deblocker_open(void (*string)(const void *, int, void *), void (*error)(void *, const char *, ...), void *cookie) { DEBLOCKER *d; d = malloc(sizeof(DEBLOCKER)); d->string = string; d->error = error; d->cookie = cookie; d->incount = 1; d->blkleft = 0; d->dbuf = 0; d->dlen = 0; d->dalloc = 0; return(d); } void deblocker_set_string(DEBLOCKER *d, void (*string)(const void *, int, void *)) { d->string = string; } static int deblocker_push_(DEBLOCKER *d, const void *data, int len, int justone) { const unsigned char *dp; int l; dp = data; while <"loop"> (len > 0) { if (d->incount) { int c; c = *dp++; len --; switch (c) { case ':': if (d->blkleft == 0) { (*d->string)(d->dbuf,d->dlen,d->cookie); d->dlen = 0; if (justone) break <"loop">; } else { d->incount = 0; l = d->dlen + d->blkleft; if (l > d->dalloc) d->dbuf = realloc(d->dbuf,d->dalloc=l); } break; case '0': c = 0; if (0) { case '1': c = 1; } if (0) { case '2': c = 2; } if (0) { case '3': c = 3; } if (0) { case '4': c = 4; } if (0) { case '5': c = 5; } if (0) { case '6': c = 6; } if (0) { case '7': c = 7; } if (0) { case '8': c = 8; } if (0) { case '9': c = 9; } d->blkleft = (10 * d->blkleft) + c; break; default: (*d->error)(d->cookie,"invalid character %02x in length",c); return(-1); break; } } else { if (len >= d->blkleft) { bcopy(dp,d->dbuf+d->dlen,d->blkleft); d->dlen += d->blkleft; dp += d->blkleft; len -= d->blkleft; d->blkleft = 0; d->incount = 1; if (justone) break <"loop">; } else { bcopy(dp,d->dbuf+d->dlen,len); d->dlen += len; d->blkleft -= len; len = 0; } } } return(dp-(const unsigned char *)data); } void deblocker_push(DEBLOCKER *d, const void *data, int len) { deblocker_push_(d,data,len,0); } int deblocker_push1(DEBLOCKER *d, const void *data, int len) { return(deblocker_push_(d,data,len,1)); } void deblocker_done(DEBLOCKER *d) { free(d->dbuf); free(d); } typedef struct rblkpriv RBLKPRIV; struct rblkpriv { FILE *sub; int ateof; int incount; int blkleft; } ; static int blocked_r(void *pv, char *buf, int n) { RBLKPRIV *p; int r; p = pv; r = 0; while (n > 0) { if (p->ateof) break; if (p->incount) { int c; c = getc(p->sub); switch (c) { case ':': if (p->blkleft == 0) { default: p->ateof = 1; continue; } p->incount = 0; break; case '0': c = 0; if (0) { case '1': c = 1; } if (0) { case '2': c = 2; } if (0) { case '3': c = 3; } if (0) { case '4': c = 4; } if (0) { case '5': c = 5; } if (0) { case '6': c = 6; } if (0) { case '7': c = 7; } if (0) { case '8': c = 8; } if (0) { case '9': c = 9; } p->blkleft = (10 * p->blkleft) + c; break; } } else { int want; int did; want = p->blkleft; if (want > n) want = n; did = fread(buf,1,want,p->sub); if (did < 0) { p->ateof = 1; return(-1); } if (did == 0) { p->ateof = 1; } else { n -= did; if (n < 0) abort(); buf += did; r += did; p->blkleft -= did; if (p->blkleft < 0) abort(); if (p->blkleft == 0) p->incount = 1; } } } return(r); } static int blocked_r_c(void *pv) { free(pv); return(0); } FILE *fwrap_r_blocked(FILE *sub) { RBLKPRIV *p; p = malloc(sizeof(RBLKPRIV)); p->sub = sub; p->ateof = 0; p->incount = 1; p->blkleft = 0; return(funopen(p,&blocked_r,0,0,&blocked_r_c)); } typedef struct wblkpriv WBLKPRIV; #define WBLK_MAX 255 struct wblkpriv { FILE *sub; } ; static int blocked_w(void *pv, const char *buf, int n) { WBLKPRIV *p; int rv; p = pv; rv = n; while (n >= WBLK_MAX) { fprintf(p->sub,"%d:",WBLK_MAX); fwrite(buf,1,WBLK_MAX,p->sub); n -= WBLK_MAX; buf += WBLK_MAX; } if (n) { fprintf(p->sub,"%d:",n); fwrite(buf,1,n,p->sub); } return(rv); } static int blocked_w_c(void *pv) { WBLKPRIV *p; p = pv; fprintf(p->sub,"0:"); free(pv); return(0); } FILE *fwrap_w_blocked(FILE *sub) { WBLKPRIV *p; p = malloc(sizeof(WBLKPRIV)); p->sub = sub; return(funopen(p,0,&blocked_w,0,&blocked_w_c)); }