#include <u.h>#include <libc.h>#include <bio.h>#include "pdf.h" Stream *Sbio(void *bio){ Stream *s; if((s = calloc(1, sizeof(*s))) == nil) return nil; s->bio = bio; return s;} Stream *Sopen(Object *o){ Stream *s; Buffer b, x; Object *of, **flts; Filter *f; int i, nflts, r; s = nil; o = pdfeval(o); if(o->type != Ostream){ /* FIXME open a string object as a stream as well? */ werrstr("not a stream"); return nil; } bufinit(&b, nil, 0); if(Sseek(o->pdf->s, o->stream.off, 0) != o->stream.off) return nil; if(bufreadn(&b, o->pdf->s, o->stream.len) < 0) goto err; /* see if there are any filters */ if((of = dictget(o, "Filter")) != &null){ of = pdfeval(of); 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 = 0; i < nflts; 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); r = filterrun(f, &b, &x); filterclose(f); if(r != 0){ buffree(&x); goto err; } if(!bufeof(&b)) fprint(2, "buffer has %d bytes left\n", bufleft(&b)); buffree(&b); b = x; } } if((s = calloc(1, sizeof(*s))) == nil){ buffree(&b); return nil; } s->buf = b; s->objoff = o->stream.off; return s;err: werrstr("stream: %r"); buffree(&b); free(s); return nil;} intSread(Stream *s, void *b, int sz){ return s->bio != nil ? Bread(s->bio, b, sz) : bufget(&s->buf, b, sz);} intSgetc(Stream *s){ int n; uchar c; n = 1; if(s->bio != nil) c = Bgetc(s->bio); else if((n = bufget(&s->buf, &c, 1)) < 0) return -2; return n == 0 ? -1 : (int)c;} intSungetc(Stream *s){ return s->bio != nil ? Bungetc(s->bio) : Sseek(s, -1, 1);} intSoffset(Stream *s){ return s->bio != nil ? Boffset(s->bio) : s->buf.off;} intSobjoffset(Stream *s){ return s->objoff;} intSsize(Stream *s){ if(s->bio != nil) return -1; return bufleft(&s->buf);} struct sgetd{ Stream *s; int eof;}; static intSgetdf(void *vp){ int c; struct sgetd *sg = vp; c = Sgetc(sg->s); if(c < 0) sg->eof = 1; return c;} intSgetd(Stream *s, double *dp){ double d; struct sgetd b; b.s = s; b.eof = 0; d = charstod(Sgetdf, &b); if(b.eof) return -1; Sungetc(s); *dp = d; return 1;} intSgeti(Stream *s, int *i){ double d; int res, c; while((c = isws(Sgetc(s)))); if(c < 0) return c; Sungetc(s); res = Sgetd(s, &d); *i = d; return res;} void *Sgetmemimage(Stream *s){ return s->buf.memimage != nil ? s->buf.memimage(&s->buf) : nil;} intSseek(Stream *s, int off, int whence){ if(s->bio != nil) return Bseek(s->bio, off, whence); if(whence == 1) off += s->buf.off; else if(whence == 2) off += s->buf.sz; if(off < 0){ werrstr("seek: %d < 0", off); off = 0; }else if(off > s->buf.sz){ werrstr("seek: %d > %d", off, s->buf.sz); off = s->buf.sz; } s->buf.off = off; return off;} char *Srdstr(Stream *s, int delim, int zero){ int i, len; char *line; if(s->bio != nil){ line = Brdstr(s->bio, delim, zero); s->linelen = Blinelen(s->bio); return line; } for(i = s->buf.off; i < s->buf.sz;){ i++; if(s->buf.b[i-1] == delim) break; } if(i >= s->buf.sz) return nil; len = i - s->buf.off; if((line = malloc(len+1)) == nil) return nil; memmove(line, s->buf.b+s->buf.off, len); s->buf.off += len; if(line[len-1] == delim && zero) len--; line[len] = 0; s->linelen = len; return line;} intSlinelen(Stream *s){ return s->linelen;} voidSclose(Stream *s){ if(s == nil) return; buffree(&s->buf); if(s->bio != nil) Bterm(s->bio); free(s);}
#include <u.h>
#include <libc.h>
#include <bio.h>
#include "pdf.h"
Stream *
Sbio(void *bio)
{
Stream *s;
if((s = calloc(1, sizeof(*s))) == nil)
return nil;
s->bio = bio;
return s;
}
Stream *
Sopen(Object *o)
{
Stream *s;
Buffer b, x;
Object *of, **flts;
Filter *f;
int i, nflts, r;
s = nil;
o = pdfeval(o);
if(o->type != Ostream){ /* FIXME open a string object as a stream as well? */
werrstr("not a stream");
return nil;
}
bufinit(&b, nil, 0);
if(Sseek(o->pdf->s, o->stream.off, 0) != o->stream.off)
return nil;
if(bufreadn(&b, o->pdf->s, o->stream.len) < 0)
goto err;
/* see if there are any filters */
if((of = dictget(o, "Filter")) != &null){
of = pdfeval(of);
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 = 0; i < nflts; 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);
r = filterrun(f, &b, &x);
filterclose(f);
if(r != 0){
buffree(&x);
goto err;
}
if(!bufeof(&b))
fprint(2, "buffer has %d bytes left\n", bufleft(&b));
buffree(&b);
b = x;
}
}
if((s = calloc(1, sizeof(*s))) == nil){
buffree(&b);
return nil;
}
s->buf = b;
s->objoff = o->stream.off;
return s;
err:
werrstr("stream: %r");
buffree(&b);
free(s);
return nil;
}
int
Sread(Stream *s, void *b, int sz)
{
return s->bio != nil ? Bread(s->bio, b, sz) : bufget(&s->buf, b, sz);
}
int
Sgetc(Stream *s)
{
int n;
uchar c;
n = 1;
if(s->bio != nil)
c = Bgetc(s->bio);
else if((n = bufget(&s->buf, &c, 1)) < 0)
return -2;
return n == 0 ? -1 : (int)c;
}
int
Sungetc(Stream *s)
{
return s->bio != nil ? Bungetc(s->bio) : Sseek(s, -1, 1);
}
int
Soffset(Stream *s)
{
return s->bio != nil ? Boffset(s->bio) : s->buf.off;
}
int
Sobjoffset(Stream *s)
{
return s->objoff;
}
int
Ssize(Stream *s)
{
if(s->bio != nil)
return -1;
return bufleft(&s->buf);
}
struct sgetd
{
Stream *s;
int eof;
};
static int
Sgetdf(void *vp)
{
int c;
struct sgetd *sg = vp;
c = Sgetc(sg->s);
if(c < 0)
sg->eof = 1;
return c;
}
int
Sgetd(Stream *s, double *dp)
{
double d;
struct sgetd b;
b.s = s;
b.eof = 0;
d = charstod(Sgetdf, &b);
if(b.eof)
return -1;
Sungetc(s);
*dp = d;
return 1;
}
int
Sgeti(Stream *s, int *i)
{
double d;
int res, c;
while((c = isws(Sgetc(s))));
if(c < 0)
return c;
Sungetc(s);
res = Sgetd(s, &d);
*i = d;
return res;
}
void *
Sgetmemimage(Stream *s)
{
return s->buf.memimage != nil ? s->buf.memimage(&s->buf) : nil;
}
int
Sseek(Stream *s, int off, int whence)
{
if(s->bio != nil)
return Bseek(s->bio, off, whence);
if(whence == 1)
off += s->buf.off;
else if(whence == 2)
off += s->buf.sz;
if(off < 0){
werrstr("seek: %d < 0", off);
off = 0;
}else if(off > s->buf.sz){
werrstr("seek: %d > %d", off, s->buf.sz);
off = s->buf.sz;
}
s->buf.off = off;
return off;
}
char *
Srdstr(Stream *s, int delim, int zero)
{
int i, len;
char *line;
if(s->bio != nil){
line = Brdstr(s->bio, delim, zero);
s->linelen = Blinelen(s->bio);
return line;
}
for(i = s->buf.off; i < s->buf.sz;){
i++;
if(s->buf.b[i-1] == delim)
break;
}
if(i >= s->buf.sz)
return nil;
len = i - s->buf.off;
if((line = malloc(len+1)) == nil)
return nil;
memmove(line, s->buf.b+s->buf.off, len);
s->buf.off += len;
if(line[len-1] == delim && zero)
len--;
line[len] = 0;
s->linelen = len;
return line;
}
int
Slinelen(Stream *s)
{
return s->linelen;
}
void
Sclose(Stream *s)
{
if(s == nil)
return;
buffree(&s->buf);
if(s->bio != nil)
Bterm(s->bio);
free(s);
}