shithub: pdffs

Download patch

ref: df075d407417a84a3dacf44044fd0907b295f39e
parent: 1d93500ddcda77cd265d492c6c9094c0f5c7488f
author: Sigrid Haflínudóttir <ftrvxmtrx@gmail.com>
date: Sat Aug 29 19:15:19 EDT 2020

make pdfeval update the pointer; add a dumb ref counter to objects

--- a/dict.c
+++ b/dict.c
@@ -70,12 +70,12 @@
 {
 	int i;
 
-	o = pdfeval(o);
+	pdfeval(&o);
 	if((o->type != Ostream && o->type != Odict) || name == nil)
 		return &null;
 	for(i = 0; i < o->dict.nkv && strcmp(name, o->dict.kv[i].key) != 0; i++);
 
-	return pdfeval(i < o->dict.nkv ? o->dict.kv[i].value : &null);
+	return pdfeval(i < o->dict.nkv ? &o->dict.kv[i].value : nil);
 }
 
 vlong
--- a/eval.c
+++ b/eval.c
@@ -4,14 +4,15 @@
 #include "pdf.h"
 
 Object *
-pdfeval(Object *o)
+pdfeval(Object **oo)
 {
-	Object *d;
+	Object *d, *o;
 	Xref *x;
 	int i;
 
-	if(o == nil)
+	if(oo == nil || *oo == nil)
 		return &null;
+	o = *oo;
 	if(o->type != Oindir)
 		return o;
 
@@ -28,7 +29,7 @@
 	}
 	if((d = pdfobj(o->pdf, o->pdf->bio)) == nil)
 		return &null;
-
+	*oo = d;
 	pdfobjfree(o);
 
 	return d;
--- a/name.c
+++ b/name.c
@@ -55,11 +55,10 @@
 		s[sz++] = c;
 	}
 
-	if((o = malloc(sizeof(*o) + sz + 1)) != nil){
-		memmove(o->name, s, sz);
-		o->name[sz] = 0;
+	if((o = malloc(sizeof(*o))) != nil){
+		o->name = s;
+		s[sz] = 0;
 		o->type = Oname;
-		free(s);
 		return o;
 	}
 
--- a/object.c
+++ b/object.c
@@ -194,7 +194,7 @@
 {
 	int i;
 
-	if(o == nil)
+	if(o == nil || --o->ref >= 0)
 		return;
 
 	switch(o->type){
@@ -201,12 +201,15 @@
 	case Onull:
 		return;
 
-	case Obool:
-	case Onum:
 	case Ostr:
 	case Oname:
+		free(o->str);
 		break;
 
+	case Obool:
+	case Onum:
+		break;
+
 	case Oarray:
 		for(i = 0; i < o->array.ne; i++)
 			pdfobjfree(o->array.e[i]);
@@ -227,4 +230,11 @@
 	}
 
 	free(o);
+}
+
+Object *
+pdfref(Object *o)
+{
+	o->ref++;
+	return o;
 }
--- a/pdf.c
+++ b/pdf.c
@@ -85,17 +85,10 @@
 		goto err;
 	}
 
-	pdf->root = dictget(o, "Root");
-	pdf->info = dictget(o, "Info");
+	pdf->root = pdfref(dictget(o, "Root"));
+	pdf->info = pdfref(dictget(o, "Info"));
 	pdfobjfree(o);
-	o = nil;
 
-	/* root is required, info is optional */
-	if(pdf->root == nil){
-		werrstr("no root");
-		goto err;
-	}
-
 	return 0;
 err:
 	pdfobjfree(o);
@@ -203,8 +196,12 @@
 		pdf->root = dictget(o, "Root");
 		pdf->info = dictget(o, "Info");
 	}
-	fprint(2, "root %T\n", pdf->root);
-	fprint(2, "info %T\n", pdf->info);
+
+	/* root is required, info is optional */
+	if(pdf->root == nil){
+		werrstr("no root");
+		goto err;
+	}
 
 	return pdf;
 err:
--- a/pdf.h
+++ b/pdf.h
@@ -30,15 +30,16 @@
 
 struct Object {
 	int type;
+	int ref;
 	Pdf *pdf;
 	union {
 		int bool;
 		double num;
 		struct {
+			char *str;
 			int len;
-			char str[1];
 		};
-		char name[1];
+		char *name;
 
 		struct {
 			u32int id;
@@ -102,7 +103,9 @@
  * not recursive, ie values of a dictionary won't be resolved
  * automatically.
  */
-Object *pdfeval(Object *o);
+Object *pdfeval(Object **o);
+
+Object *pdfref(Object *o);
 
 int isws(int c);
 int isdelim(int c);
--- a/stream.c
+++ b/stream.c
@@ -23,7 +23,7 @@
 	int i, nflts;
 
 	s = nil;
-	if(pdfeval(o)->type != Ostream) /* FIXME open a string object as a stream as well? */
+	if(pdfeval(&o)->type != Ostream) /* FIXME open a string object as a stream as well? */
 		return nil;
 
 	bufinit(&b, nil, 0);
@@ -35,7 +35,7 @@
 
 	/* see if there are any filters */
 	if((of = dictget(o, "Filter")) != nil){
-		if(pdfeval(of)->type == Oname){ /* one filter */
+		if(pdfeval(&of)->type == Oname){ /* one filter */
 			flts = &of;
 			nflts = 1;
 		}else if(of->type == Oarray){ /* array of filters */
--- a/string.c
+++ b/string.c
@@ -37,11 +37,12 @@
 	o = nil;
 	if(dec16((uchar*)s, n, s+1, len) != n){
 		werrstr("invalid hex");
-	}else if((o = malloc(sizeof(*o) + n + 1)) != nil){
-		memmove(o->str, s, n);
-		o->str[n] = 0;
+	}else if((o = malloc(sizeof(*o))) != nil){
+		o->str = s;
+		s[n] = 0;
 		o->len = n;
 		o->type = Ostr;
+		return o;
 	}
 
 	free(s);
@@ -133,12 +134,11 @@
 		goto err;
 	}
 
-	if(c >= 0 && (o = malloc(sizeof(*o) + sz + 1)) != nil){
-		memmove(o->str, s, sz);
-		o->str[sz] = 0;
+	if(c >= 0 && (o = malloc(sizeof(*o))) != nil){
+		s[sz] = 0;
+		o->str = s;
 		o->len = sz;
 		o->type = Ostr;
-		free(s);
 		return o;
 	}