#include #include #include #include #include "stdio-util.h" typedef struct ws WS; typedef struct as AS; typedef struct wc WC; struct ws { FILE *inner; WRAP_W *wrapper; void *priv; } ; struct as { char *b; int a; int l; char **sp; int *lp; } ; struct wc { FILE *inner; void (*cb)(void *); void *cbarg; unsigned int flags; } ; static int wrap_w_w(void *sv, const char *buf, int len) { WS *s; int i; s = sv; for (i=0;iwrapper->put)(s->priv,buf[i]); return(len); } static int wrap_w_c(void *sv) { WS *s; s = sv; (*s->wrapper->done)(s->priv); free(s); return(0); } static void wrap_put_inner(unsigned char ch, void *sv) { putc(ch,((WS *)sv)->inner); } FILE *open_wrap_w(FILE *inner, WRAP_W *wrapper) { WS *s; FILE *f; int e; void *p; s = malloc(sizeof(WS)); if (! s) return(0); f = funopen(s,0,&wrap_w_w,0,&wrap_w_c); if (! f) { e = errno; free(s); errno = e; return(0); } p = (*wrapper->init)(&wrap_put_inner,s); if (! p) { e = errno; s->inner = 0; s->wrapper = 0; s->priv = 0; fclose(f); free(s); errno = e; return(0); } s->inner = inner; s->wrapper = wrapper; s->priv = p; return(f); } static int accum_w(void *sv, const char *data, int len) { AS *s; s = sv; if (s->sp) { if (s->l+len > s->a) s->b = realloc(s->b,s->a=s->l+len); bcopy(data,s->b+s->l,len); } s->l += len; return(len); } static int accum_c(void *sv) { AS *s; s = sv; if (s->sp) *s->sp = s->b; if (s->lp) *s->lp = s->l; free(s); return(0); } FILE *open_accum(char **sp, int *lp) { AS *s; FILE *f; int e; s = malloc(sizeof(AS)); if (! s) return(0); f = funopen(s,0,&accum_w,0,&accum_c); if (! f) { e = errno; free(s); errno = e; return(0); } s->b = 0; s->a = 0; s->l = 0; s->sp = sp; s->lp = lp; return(f); } static int wrapclose_r(void *pv, char *buf, int len) { return(fread(buf,1,len,((WC *)pv)->inner)); } static int wrapclose_w(void *pv, const char *buf, int len) { return(fwrite(buf,1,len,((WC *)pv)->inner)); } static int wrapclose_c(void *pv) { WC *p; p = pv; if (p->flags & WCF_CLOSE_BEFORE) fclose(p->inner); (*p->cb)(p->cbarg); if (p->flags & WCF_CLOSE_AFTER) fclose(p->inner); free(p); return(0); } FILE *open_wrapclose(FILE *inner, void (*cb)(void *), void *cbarg, unsigned int flags) { WC *p; FILE *f; int e; switch (flags & WCF__CLOSE) { case WCF_CLOSE_NONE: case WCF_CLOSE_BEFORE: case WCF_CLOSE_AFTER: break; default: return(0); break; } p = malloc(sizeof(WC)); if (! p) return(0); f = funopen(p,&wrapclose_r,&wrapclose_w,0,&wrapclose_c); if (! f) { e = errno; free(p); errno = e; return(0); } p->inner = inner; p->cb = cb; p->cbarg = cbarg; p->flags = flags; return(f); }