shithub: pdffs

ref: 745debcdfb49837a82d112c2623b7a763fdf2cd0
dir: pdffs/stream.c

View raw version
#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(Object *o)
{
	Stream *s;
	Buffer b, x;
	Object *of, **flts;
	Filter *f;
	int i, nflts;

	s = nil;
	if(pdfeval(&o)->type != Ostream) /* FIXME open a string object as a stream as well? */
		return nil;

	bufinit(&b, nil, 0);
	if(Bseek(o->pdf->bio, o->stream.off, 0) != o->stream.off)
		return nil;
	if(bufreadn(&b, o->pdf->bio, o->stream.len) < 0)
		goto err;

	/* see if there are any filters */
	if((of = dictget(o, "Filter")) != nil){
		if(pdfeval(&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(o->pdf->bio), OREAD);
	Biofn(s->bio, bufiof);

	return s;
err:
	werrstr("stream: %r");
	buffree(&b);
	free(s);
	return nil;
}

void
streamclose(Stream *s)
{
	buffree(&s->buf);
	Bterm(s->bio);
	free(s);
}