shithub: pdffs

ref: d9638664119a09f7fbab558635c2bdf16f5fd1c1
dir: pdffs/object.c

View raw version
#include <u.h>
#include <libc.h>
#include <ctype.h>
#include "pdf.h"

Object *
pdfobject(char *p, char **e, int len)
{
	Object *o;
	char *s, *p0;
	int sz;

	o = nil;
	for(; len > 0 && isws(*p); p++, len--);
	if(len < 1){
		werrstr("too short");
		goto err;
	}

	if(*p < 1){
		werrstr("unexpected non-ascii char");
		goto err;
	}

	switch(*p){
	case '<': /* dictionary or a string */
		if(len < 2){
			werrstr("too short");
			goto err;
		}
		if(p[1] == '<'){ /* dictionary */
			o = pdfdict(p, e, len);
			break;
		}
		/* fall through */

	case '(': /* string */
		if((sz = pdfstring(p, e, len)) < 0)
			goto err;
		if((o = malloc(sizeof(*o)+sz+1)) != nil){
			o->type = Ostr;
			o->str = (char*)(o+1);
			strcpy(o->str, p);
		}
		break;

	case '/':
		if((sz = pdfname(p, e, len)) < 0)
			goto err;
		if((o = malloc(sizeof(*o)+sz+1)) != nil){
			o->type = Oname;
			o->str = (char*)(o+1);
			strcpy(o->str, p);
		}
		break;

	case '[':
		o = pdfarray(p, e, len);
		break;

	default:
		if(isdigit(*p)){
			if((o = malloc(sizeof(*o)+sz+1)) != nil){
				o->type = Onum;
				o->num = strtod(p, e);
				sz = len - (*e - p);
				p0 = *e;
				s = p0;
				for(; sz > 0 && isws(*s); s++, sz--);
				if(sz > 0 && isdigit(*s)){
					strtod(s, &p);
					sz -= (p - s);
					s = p;
					for(; sz > 0 && isws(*s); s++, sz--);
					if(sz > 0 && *s == 'R'){ /* indirect object */
						sz--;
						s++;
						o->type = Oindir;
						p0 = s;
						len = sz;
					}
				}
				*e = p0;
			}
			break;
		}
		werrstr("unexpected char %c", *p);
		goto err;
	}

	if(o != nil)
		return o;
err:
	werrstr("object: %r");
	freeobject(o);
	return nil;
}

void
freeobject(Object *o)
{
	if(o == nil)
		return;
	free(o);
}