ref: a9516693e7142a658f4e3ea190272f4cd73b24be
dir: /stream.c/
#include <u.h> #include <libc.h> #include <bio.h> #include "pdf.h" static int bufiof(Biobufhdr *b, void *data, long n) { Stream *s; s = (void*)((char*)b - sizeof(*s)); return bufget(&s->buf, data, n); } Stream * streamopen(Pdf *pdf, Object *o) { Stream *s; Buffer b, x; Object *of, **flts; Filter *f; int i, nflts; s = nil; if(pdfeval(pdf, o) != 0 || o == nil || o->type != Ostream) /* FIXME open a string object as a stream as well? */ return nil; bufinit(&b, nil, 0); if(Bseek(pdf->bio, o->stream.off, 0) != o->stream.off) return nil; if(bufreadn(&b, pdf->bio, o->stream.len) < 0) goto err; bufdump(&b); /* see if there are any filters */ if((of = pdfdictget(o, "Filter")) != nil){ if(pdfeval(pdf, of) != 0) goto err; if(of->type == Oname){ /* one filter */ flts = &of; nflts = 1; }else if(of->type == Oarray){ /* array of filters */ flts = of->array.e; nflts = of->array.ne; }else{ werrstr("filters type invalid (%T)", of); goto err; } for(i = nflts-1; i >= 0; i--){ if(flts[i]->type != Oname){ werrstr("filter type invalid (%T)", flts[i]); goto err; } if((f = filteropen(flts[i]->name, o)) == nil) goto err; bufinit(&x, nil, 0); if(filterrun(f, &b, &x) != 0){ buffree(&x); goto err; } buffree(&b); b = x; } } if((s = calloc(1, sizeof(*s)+sizeof(Biobuf))) == nil){ buffree(&b); return nil; } s->bio = (uchar*)(s+1); s->buf = b; Binit(s->bio, Bfildes(pdf->bio), OREAD); Biofn(s->bio, bufiof); bufdump(&s->buf); return s; err: werrstr("stream: %r"); buffree(&b); free(s); return nil; } void streamclose(Stream *s) { buffree(&s->buf); Bterm(s->bio); free(s); }