summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin Watts <robin.watts@artifex.com>2015-03-04 19:29:22 +0000
committerRobin Watts <robin.watts@artifex.com>2015-03-24 19:49:59 +0000
commit563c482145d65c4006f5842c8860ab1b09f5a229 (patch)
treec2b32f42ee3fd9b112f541db3c1d10a6dd21d30d
parentf533104d6e66b3fc6d3b63b98ec7fe4fb175b366 (diff)
downloadmupdf-563c482145d65c4006f5842c8860ab1b09f5a229.tar.xz
Reduce pdf_obj memory usage.
Historically pdf_obj was a structure with a header and a union in it. As time has gone by more stuff has been put into the header, and the different arms of the union have changed in size. We've even adopted the idea of different 'kinds' of pdf_obj's being different sizes (names and strings for examples). Here we rework the system slightly; we minimise the header, and split out everything into different structures. Every different 'kind' of pdf_obj is now it's own structure, just as big as it needs to be. Key changes: * refs is now a short rather than an int. We are never going to need more than 32767 refs (indeed, if we ever need more than about 3 (10 at the outside), something has gone very wrong!). This aids structure packing. * Only arrays, dicts and refs actually need the pdf_document pointer. * Only arrays and dicts need the parent_num pointer.
-rw-r--r--source/pdf/pdf-object.c653
1 files changed, 361 insertions, 292 deletions
diff --git a/source/pdf/pdf-object.c b/source/pdf/pdf-object.c
index ecdb1ebb..5711cbaa 100644
--- a/source/pdf/pdf-object.c
+++ b/source/pdf/pdf-object.c
@@ -32,36 +32,69 @@ enum
struct pdf_obj_s
{
- int refs;
+ short refs;
unsigned char kind;
unsigned char flags;
- pdf_document *doc; /* KEEP */
- int parent_num;
+};
+
+typedef struct pdf_obj_num_s
+{
+ pdf_obj super;
union
{
int i;
float f;
- struct {
- unsigned short len;
- char buf[1];
- } s;
- char n[1];
- struct {
- int len;
- int cap;
- pdf_obj **items;
- } a;
- struct {
- int len;
- int cap;
- struct keyval *items;
- } d;
- struct {
- int num;
- int gen;
- } r;
} u;
-};
+} pdf_obj_num;
+
+typedef struct pdf_obj_string_s
+{
+ pdf_obj super;
+ unsigned short len;
+ char buf[1];
+} pdf_obj_string;
+
+typedef struct pdf_obj_name_s
+{
+ pdf_obj super;
+ char n[1];
+} pdf_obj_name;
+
+typedef struct pdf_obj_array_s
+{
+ pdf_obj super;
+ pdf_document *doc;
+ int parent_num;
+ int len;
+ int cap;
+ pdf_obj **items;
+} pdf_obj_array;
+
+typedef struct pdf_obj_dict_s
+{
+ pdf_obj super;
+ pdf_document *doc;
+ int parent_num;
+ int len;
+ int cap;
+ struct keyval *items;
+} pdf_obj_dict;
+
+typedef struct pdf_obj_ref_s
+{
+ pdf_obj super;
+ pdf_document *doc; /* Only needed for arrays, dicts and indirects */
+ int num;
+ int gen;
+} pdf_obj_ref;
+
+#define NAME(obj) ((pdf_obj_name *)(obj))
+#define NUM(obj) ((pdf_obj_num *)(obj))
+#define STRING(obj) ((pdf_obj_string *)(obj))
+#define DICT(obj) ((pdf_obj_dict *)(obj))
+#define ARRAY(obj) ((pdf_obj_array *)(obj))
+#define REF(obj) ((pdf_obj_ref *)(obj))
+
pdf_obj *
pdf_new_null(fz_context *ctx, pdf_document *doc)
@@ -78,45 +111,39 @@ pdf_new_bool(fz_context *ctx, pdf_document *doc, int b)
pdf_obj *
pdf_new_int(fz_context *ctx, pdf_document *doc, int i)
{
- pdf_obj *obj;
- obj = Memento_label(fz_malloc(ctx, sizeof(pdf_obj)), "pdf_obj(int)");
- obj->doc = doc;
- obj->refs = 1;
- obj->kind = PDF_INT;
- obj->flags = 0;
- obj->parent_num = 0;
+ pdf_obj_num *obj;
+ obj = Memento_label(fz_malloc(ctx, sizeof(pdf_obj_num)), "pdf_obj(int)");
+ obj->super.refs = 1;
+ obj->super.kind = PDF_INT;
+ obj->super.flags = 0;
obj->u.i = i;
- return obj;
+ return &obj->super;
}
pdf_obj *
pdf_new_real(fz_context *ctx, pdf_document *doc, float f)
{
- pdf_obj *obj;
- obj = Memento_label(fz_malloc(ctx, sizeof(pdf_obj)), "pdf_obj(real)");
- obj->doc = doc;
- obj->refs = 1;
- obj->kind = PDF_REAL;
- obj->flags = 0;
- obj->parent_num = 0;
+ pdf_obj_num *obj;
+ obj = Memento_label(fz_malloc(ctx, sizeof(pdf_obj_num)), "pdf_obj(real)");
+ obj->super.refs = 1;
+ obj->super.kind = PDF_REAL;
+ obj->super.flags = 0;
obj->u.f = f;
- return obj;
+ return &obj->super;
}
pdf_obj *
pdf_new_string(fz_context *ctx, pdf_document *doc, const char *str, int len)
{
- pdf_obj *obj;
- obj = Memento_label(fz_malloc(ctx, offsetof(pdf_obj, u.s.buf) + len + 1), "pdf_obj(string)");
- obj->doc = doc;
- obj->refs = 1;
- obj->kind = PDF_STRING;
- obj->flags = 0;
- obj->parent_num = 0;
- obj->u.s.len = len;
- memcpy(obj->u.s.buf, str, len);
- obj->u.s.buf[len] = '\0';
- return obj;
+ pdf_obj_string *obj;
+ obj = Memento_label(fz_malloc(ctx, offsetof(pdf_obj_string, buf) + len + 1), "pdf_obj(string)");
+ obj->super.refs = 1;
+ obj->super.kind = PDF_STRING;
+ obj->super.flags = 0;
+ obj->len = len;
+ memcpy(obj->buf, str, len);
+ obj->buf[len] = '\0';
+ return &obj->super;
}
static int
@@ -128,36 +155,33 @@ namecmp(const void *key, const void *name)
pdf_obj *
pdf_new_name(fz_context *ctx, pdf_document *doc, const char *str)
{
- pdf_obj *obj;
+ pdf_obj_name *obj;
char **stdname;
stdname = bsearch(str, &PDF_NAMES[1], PDF_OBJ_ENUM_NAME__LIMIT-1, sizeof(char *), namecmp);
if (stdname != NULL)
return (pdf_obj *)(intptr_t)(stdname - &PDF_NAMES[0]);
- obj = Memento_label(fz_malloc(ctx, offsetof(pdf_obj, u.n) + strlen(str) + 1), "pdf_obj(name)");
- obj->doc = doc;
- obj->refs = 1;
- obj->kind = PDF_NAME;
- obj->flags = 0;
- obj->parent_num = 0;
- strcpy(obj->u.n, str);
- return obj;
+ obj = Memento_label(fz_malloc(ctx, offsetof(pdf_obj_name, n) + strlen(str) + 1), "pdf_obj(name)");
+ obj->super.refs = 1;
+ obj->super.kind = PDF_NAME;
+ obj->super.flags = 0;
+ strcpy(obj->n, str);
+ return &obj->super;
}
pdf_obj *
pdf_new_indirect(fz_context *ctx, pdf_document *doc, int num, int gen)
{
- pdf_obj *obj;
- obj = Memento_label(fz_malloc(ctx, sizeof(pdf_obj)), "pdf_obj(indirect)");
+ pdf_obj_ref *obj;
+ obj = Memento_label(fz_malloc(ctx, sizeof(pdf_obj_ref)), "pdf_obj(indirect)");
+ obj->super.refs = 1;
+ obj->super.kind = PDF_INDIRECT;
+ obj->super.flags = 0;
obj->doc = doc;
- obj->refs = 1;
- obj->kind = PDF_INDIRECT;
- obj->flags = 0;
- obj->parent_num = 0;
- obj->u.r.num = num;
- obj->u.r.gen = gen;
- return obj;
+ obj->num = num;
+ obj->gen = gen;
+ return &obj->super;
}
pdf_obj *
@@ -245,9 +269,9 @@ int pdf_to_int(fz_context *ctx, pdf_obj *obj)
if (obj < PDF_OBJ__LIMIT)
return 0;
if (obj->kind == PDF_INT)
- return obj->u.i;
+ return NUM(obj)->u.i;
if (obj->kind == PDF_REAL)
- return (int)(obj->u.f + 0.5f); /* No roundf in MSVC */
+ return (int)(NUM(obj)->u.f + 0.5f); /* No roundf in MSVC */
return 0;
}
@@ -257,9 +281,9 @@ float pdf_to_real(fz_context *ctx, pdf_obj *obj)
if (obj < PDF_OBJ__LIMIT)
return 0;
if (obj->kind == PDF_REAL)
- return obj->u.f;
+ return NUM(obj)->u.f;
if (obj->kind == PDF_INT)
- return obj->u.i;
+ return NUM(obj)->u.i;
return 0;
}
@@ -272,7 +296,7 @@ char *pdf_to_name(fz_context *ctx, pdf_obj *obj)
return PDF_NAMES[(intptr_t)obj];
if (obj < PDF_OBJ__LIMIT || obj->kind != PDF_NAME)
return "";
- return obj->u.n;
+ return NAME(obj)->n;
}
char *pdf_to_str_buf(fz_context *ctx, pdf_obj *obj)
@@ -280,7 +304,7 @@ char *pdf_to_str_buf(fz_context *ctx, pdf_obj *obj)
RESOLVE(obj);
if (obj < PDF_OBJ__LIMIT || obj->kind != PDF_STRING)
return "";
- return obj->u.s.buf;
+ return STRING(obj)->buf;
}
int pdf_to_str_len(fz_context *ctx, pdf_obj *obj)
@@ -288,14 +312,14 @@ int pdf_to_str_len(fz_context *ctx, pdf_obj *obj)
RESOLVE(obj);
if (obj < PDF_OBJ__LIMIT || obj->kind != PDF_STRING)
return 0;
- return obj->u.s.len;
+ return STRING(obj)->len;
}
void pdf_set_int(fz_context *ctx, pdf_obj *obj, int i)
{
if (obj < PDF_OBJ__LIMIT || obj->kind != PDF_INT)
return;
- obj->u.i = i;
+ NUM(obj)->u.i = i;
}
/* for use by pdf_crypt_obj_imp to decrypt AES string in place */
@@ -304,9 +328,9 @@ void pdf_set_str_len(fz_context *ctx, pdf_obj *obj, int newlen)
RESOLVE(obj);
if (obj < PDF_OBJ__LIMIT || obj->kind != PDF_STRING)
return; /* This should never happen */
- if (newlen > obj->u.s.len)
+ if (newlen > STRING(obj)->len)
return; /* This should never happen */
- obj->u.s.len = newlen;
+ STRING(obj)->len = newlen;
}
pdf_obj *pdf_to_dict(fz_context *ctx, pdf_obj *obj)
@@ -319,21 +343,21 @@ int pdf_to_num(fz_context *ctx, pdf_obj *obj)
{
if (obj < PDF_OBJ__LIMIT || obj->kind != PDF_INDIRECT)
return 0;
- return obj->u.r.num;
+ return REF(obj)->num;
}
int pdf_to_gen(fz_context *ctx, pdf_obj *obj)
{
if (obj < PDF_OBJ__LIMIT || obj->kind != PDF_INDIRECT)
return 0;
- return obj->u.r.gen;
+ return REF(obj)->gen;
}
pdf_document *pdf_get_indirect_document(fz_context *ctx, pdf_obj *obj)
{
if (obj < PDF_OBJ__LIMIT || obj->kind != PDF_INDIRECT)
return NULL;
- return obj->doc;
+ return REF(obj)->doc;
}
int pdf_objcmp_resolve(fz_context *ctx, pdf_obj *a, pdf_obj *b)
@@ -361,14 +385,14 @@ pdf_objcmp(fz_context *ctx, pdf_obj *a, pdf_obj *b)
if (b->kind != PDF_NAME)
return 1;
- return strcmp(b->u.n, PDF_NAMES[(intptr_t)a]);
+ return strcmp(NAME(b)->n, PDF_NAMES[(intptr_t)a]);
}
if (b < PDF_OBJ_NAME__LIMIT)
{
if (a->kind != PDF_NAME)
return 1;
- return strcmp(a->u.n, PDF_NAMES[(intptr_t)b]);
+ return strcmp(NAME(a)->n, PDF_NAMES[(intptr_t)b]);
}
if (a < PDF_OBJ__LIMIT || b < PDF_OBJ__LIMIT)
@@ -380,54 +404,54 @@ pdf_objcmp(fz_context *ctx, pdf_obj *a, pdf_obj *b)
switch (a->kind)
{
case PDF_INT:
- return a->u.i - b->u.i;
+ return NUM(a)->u.i - NUM(b)->u.i;
case PDF_REAL:
- if (a->u.f < b->u.f)
+ if (NUM(a)->u.f < NUM(b)->u.f)
return -1;
- if (a->u.f > b->u.f)
+ if (NUM(a)->u.f > NUM(b)->u.f)
return 1;
return 0;
case PDF_STRING:
- if (a->u.s.len < b->u.s.len)
+ if (STRING(a)->len < STRING(b)->len)
{
- if (memcmp(a->u.s.buf, b->u.s.buf, a->u.s.len) <= 0)
+ if (memcmp(STRING(a)->buf, STRING(b)->buf, STRING(a)->len) <= 0)
return -1;
return 1;
}
- if (a->u.s.len > b->u.s.len)
+ if (STRING(a)->len > STRING(b)->len)
{
- if (memcmp(a->u.s.buf, b->u.s.buf, b->u.s.len) >= 0)
+ if (memcmp(STRING(a)->buf, STRING(b)->buf, STRING(b)->len) >= 0)
return 1;
return -1;
}
- return memcmp(a->u.s.buf, b->u.s.buf, a->u.s.len);
+ return memcmp(STRING(a)->buf, STRING(b)->buf, STRING(a)->len);
case PDF_NAME:
- return strcmp(a->u.n, b->u.n);
+ return strcmp(NAME(a)->n, NAME(b)->n);
case PDF_INDIRECT:
- if (a->u.r.num == b->u.r.num)
- return a->u.r.gen - b->u.r.gen;
- return a->u.r.num - b->u.r.num;
+ if (REF(a)->num == REF(b)->num)
+ return REF(a)->gen - REF(b)->gen;
+ return REF(a)->num - REF(b)->num;
case PDF_ARRAY:
- if (a->u.a.len != b->u.a.len)
- return a->u.a.len - b->u.a.len;
- for (i = 0; i < a->u.a.len; i++)
- if (pdf_objcmp(ctx, a->u.a.items[i], b->u.a.items[i]))
+ if (ARRAY(a)->len != ARRAY(b)->len)
+ return ARRAY(a)->len - ARRAY(b)->len;
+ for (i = 0; i < ARRAY(a)->len; i++)
+ if (pdf_objcmp(ctx, ARRAY(a)->items[i], ARRAY(b)->items[i]))
return 1;
return 0;
case PDF_DICT:
- if (a->u.d.len != b->u.d.len)
- return a->u.d.len - b->u.d.len;
- for (i = 0; i < a->u.d.len; i++)
+ if (DICT(a)->len != DICT(b)->len)
+ return DICT(a)->len - DICT(b)->len;
+ for (i = 0; i < DICT(a)->len; i++)
{
- if (pdf_objcmp(ctx, a->u.d.items[i].k, b->u.d.items[i].k))
+ if (pdf_objcmp(ctx, DICT(a)->items[i].k, DICT(b)->items[i].k))
return 1;
- if (pdf_objcmp(ctx, a->u.d.items[i].v, b->u.d.items[i].v))
+ if (pdf_objcmp(ctx, DICT(a)->items[i].v, DICT(b)->items[i].v))
return 1;
}
return 0;
@@ -464,70 +488,67 @@ pdf_objkindstr(pdf_obj *obj)
pdf_obj *
pdf_new_array(fz_context *ctx, pdf_document *doc, int initialcap)
{
- pdf_obj *obj;
+ pdf_obj_array *obj;
int i;
- obj = Memento_label(fz_malloc(ctx, sizeof(pdf_obj)), "pdf_obj(array)");
+ obj = Memento_label(fz_malloc(ctx, sizeof(pdf_obj_array)), "pdf_obj(array)");
+ obj->super.refs = 1;
+ obj->super.kind = PDF_ARRAY;
+ obj->super.flags = 0;
obj->doc = doc;
- obj->refs = 1;
- obj->kind = PDF_ARRAY;
- obj->flags = 0;
obj->parent_num = 0;
- obj->u.a.len = 0;
- obj->u.a.cap = initialcap > 1 ? initialcap : 6;
+ obj->len = 0;
+ obj->cap = initialcap > 1 ? initialcap : 6;
fz_try(ctx)
{
- obj->u.a.items = Memento_label(fz_malloc_array(ctx, obj->u.a.cap, sizeof(pdf_obj*)), "pdf_obj(array items)");
+ obj->items = Memento_label(fz_malloc_array(ctx, obj->cap, sizeof(pdf_obj*)), "pdf_obj(array items)");
}
fz_catch(ctx)
{
fz_free(ctx, obj);
fz_rethrow(ctx);
}
- for (i = 0; i < obj->u.a.cap; i++)
- obj->u.a.items[i] = NULL;
+ for (i = 0; i < obj->cap; i++)
+ obj->items[i] = NULL;
- return obj;
+ return &obj->super;
}
static void
-pdf_array_grow(fz_context *ctx, pdf_obj *obj)
+pdf_array_grow(fz_context *ctx, pdf_obj_array *obj)
{
int i;
- int new_cap = (obj->u.a.cap * 3) / 2;
+ int new_cap = (obj->cap * 3) / 2;
- obj->u.a.items = fz_resize_array(ctx, obj->u.a.items, new_cap, sizeof(pdf_obj*));
- obj->u.a.cap = new_cap;
+ obj->items = fz_resize_array(ctx, obj->items, new_cap, sizeof(pdf_obj*));
+ obj->cap = new_cap;
- for (i = obj->u.a.len ; i < obj->u.a.cap; i++)
- obj->u.a.items[i] = NULL;
+ for (i = obj->len ; i < obj->cap; i++)
+ obj->items[i] = NULL;
}
pdf_obj *
pdf_copy_array(fz_context *ctx, pdf_obj *obj)
{
- RESOLVE(obj);
- if (obj)
- {
- pdf_document *doc = obj->doc;
+ pdf_document *doc;
+ pdf_obj *arr;
+ int i;
+ int n;
- pdf_obj *arr;
- int i;
- int n;
+ RESOLVE(obj);
+ if (obj < PDF_OBJ__LIMIT || obj->kind != PDF_ARRAY)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "assert: not an array (%s)", pdf_objkindstr(obj));
- if (obj->kind != PDF_ARRAY)
- fz_warn(ctx, "assert: not an array (%s)", pdf_objkindstr(obj));
+ doc = ARRAY(obj)->doc;
- arr = pdf_new_array(ctx, doc, pdf_array_len(ctx, obj));
- n = pdf_array_len(ctx, obj);
- for (i = 0; i < n; i++)
- pdf_array_push(ctx, arr, pdf_array_get(ctx, obj, i));
+ n = pdf_array_len(ctx, obj);
+ arr = pdf_new_array(ctx, doc, n);
+ for (i = 0; i < n; i++)
+ pdf_array_push(ctx, arr, pdf_array_get(ctx, obj, i));
- return arr;
- }
- return NULL; /* Can't warn :( */
+ return arr;
}
int
@@ -536,7 +557,7 @@ pdf_array_len(fz_context *ctx, pdf_obj *obj)
RESOLVE(obj);
if (obj < PDF_OBJ__LIMIT || obj->kind != PDF_ARRAY)
return 0;
- return obj->u.a.len;
+ return ARRAY(obj)->len;
}
pdf_obj *
@@ -545,20 +566,41 @@ pdf_array_get(fz_context *ctx, pdf_obj *obj, int i)
RESOLVE(obj);
if (obj < PDF_OBJ__LIMIT || obj->kind != PDF_ARRAY)
return NULL;
- if (i < 0 || i >= obj->u.a.len)
+ if (i < 0 || i >= ARRAY(obj)->len)
return NULL;
- return obj->u.a.items[i];
+ return ARRAY(obj)->items[i];
}
static void object_altered(fz_context *ctx, pdf_obj *obj, pdf_obj *val)
{
- pdf_document *doc = obj->doc;
+ pdf_document *doc;
+ int parent;
/*
+ obj should be a dict or an array. We don't care about
+ any other types, as they aren't 'containers'.
+ */
+ if (obj < PDF_OBJ__LIMIT)
+ return;
+
+ switch (obj->kind)
+ {
+ case PDF_DICT:
+ doc = DICT(obj)->doc;
+ parent = DICT(obj)->parent_num;
+ break;
+ case PDF_ARRAY:
+ doc = ARRAY(obj)->doc;
+ parent = ARRAY(obj)->parent_num;
+ break;
+ default:
+ return;
+ }
+ /*
parent_num = 0 while an object is being parsed from the file.
No further action is necessary.
*/
- if (obj->parent_num == 0 || doc->freeze_updates)
+ if (parent == 0 || doc->freeze_updates)
return;
/*
@@ -566,8 +608,8 @@ static void object_altered(fz_context *ctx, pdf_obj *obj, pdf_obj *val)
has been moved to the incremental xref section and the newly linked
object needs to record the parent_num
*/
- pdf_xref_ensure_incremental_object(ctx, doc, obj->parent_num);
- pdf_set_obj_parent(ctx, val, obj->parent_num);
+ pdf_xref_ensure_incremental_object(ctx, doc, parent);
+ pdf_set_obj_parent(ctx, val, parent);
}
void
@@ -580,12 +622,12 @@ pdf_array_put(fz_context *ctx, pdf_obj *obj, int i, pdf_obj *item)
fz_warn(ctx, "assert: not an array (%s)", pdf_objkindstr(obj));
else if (i < 0)
fz_warn(ctx, "assert: index %d < 0", i);
- else if (i >= obj->u.a.len)
- fz_warn(ctx, "assert: index %d > length %d", i, obj->u.a.len);
+ else if (i >= ARRAY(obj)->len)
+ fz_warn(ctx, "assert: index %d > length %d", i, ARRAY(obj)->len);
else
{
- pdf_drop_obj(ctx, obj->u.a.items[i]);
- obj->u.a.items[i] = pdf_keep_obj(ctx, item);
+ pdf_drop_obj(ctx, ARRAY(obj)->items[i]);
+ ARRAY(obj)->items[i] = pdf_keep_obj(ctx, item);
}
object_altered(ctx, obj, item);
@@ -610,10 +652,10 @@ pdf_array_push(fz_context *ctx, pdf_obj *obj, pdf_obj *item)
fz_warn(ctx, "assert: not an array (%s)", pdf_objkindstr(obj));
else
{
- if (obj->u.a.len + 1 > obj->u.a.cap)
- pdf_array_grow(ctx, obj);
- obj->u.a.items[obj->u.a.len] = pdf_keep_obj(ctx, item);
- obj->u.a.len++;
+ if (ARRAY(obj)->len + 1 > ARRAY(obj)->cap)
+ pdf_array_grow(ctx, ARRAY(obj));
+ ARRAY(obj)->items[ARRAY(obj)->len] = pdf_keep_obj(ctx, item);
+ ARRAY(obj)->len++;
}
object_altered(ctx, obj, item);
@@ -646,13 +688,13 @@ pdf_array_insert(fz_context *ctx, pdf_obj *obj, pdf_obj *item, int i)
fz_warn(ctx, "assert: not an array (%s)", pdf_objkindstr(obj));
else
{
- if (i < 0 || i > obj->u.a.len)
- fz_throw(ctx, FZ_ERROR_GENERIC, "attempt to insert object %d in array of length %d", i, obj->u.a.len);
- if (obj->u.a.len + 1 > obj->u.a.cap)
- pdf_array_grow(ctx, obj);
- memmove(obj->u.a.items + i + 1, obj->u.a.items + i, (obj->u.a.len - i) * sizeof(pdf_obj*));
- obj->u.a.items[i] = pdf_keep_obj(ctx, item);
- obj->u.a.len++;
+ if (i < 0 || i > ARRAY(obj)->len)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "attempt to insert object %d in array of length %d", i, ARRAY(obj)->len);
+ if (ARRAY(obj)->len + 1 > ARRAY(obj)->cap)
+ pdf_array_grow(ctx, ARRAY(obj));
+ memmove(ARRAY(obj)->items + i + 1, ARRAY(obj)->items + i, (ARRAY(obj)->len - i) * sizeof(pdf_obj*));
+ ARRAY(obj)->items[i] = pdf_keep_obj(ctx, item);
+ ARRAY(obj)->len++;
}
object_altered(ctx, obj, item);
@@ -685,10 +727,10 @@ pdf_array_delete(fz_context *ctx, pdf_obj *obj, int i)
fz_warn(ctx, "assert: not an array (%s)", pdf_objkindstr(obj));
else
{
- pdf_drop_obj(ctx, obj->u.a.items[i]);
- obj->u.a.items[i] = 0;
- obj->u.a.len--;
- memmove(obj->u.a.items + i, obj->u.a.items + i + 1, (obj->u.a.len - i) * sizeof(pdf_obj*));
+ pdf_drop_obj(ctx, ARRAY(obj)->items[i]);
+ ARRAY(obj)->items[i] = 0;
+ ARRAY(obj)->len--;
+ memmove(ARRAY(obj)->items + i, ARRAY(obj)->items + i + 1, (ARRAY(obj)->len - i) * sizeof(pdf_obj*));
}
}
return; /* Can't warn :( */
@@ -813,14 +855,14 @@ static int keyvalcmp(const void *ap, const void *bp)
if (a->k < PDF_OBJ_NAME__LIMIT)
an = PDF_NAMES[(intptr_t)a->k];
else if (a->k >= PDF_OBJ__LIMIT && a->k->kind == PDF_NAME)
- an = a->k->u.n;
+ an = NAME(a->k)->n;
else
return 0;
if (b->k < PDF_OBJ_NAME__LIMIT)
bn = PDF_NAMES[(intptr_t)b->k];
else if (b->k >= PDF_OBJ__LIMIT && b->k->kind == PDF_NAME)
- bn = b->k->u.n;
+ bn = NAME(b->k)->n;
else
return 0;
@@ -830,50 +872,50 @@ static int keyvalcmp(const void *ap, const void *bp)
pdf_obj *
pdf_new_dict(fz_context *ctx, pdf_document *doc, int initialcap)
{
- pdf_obj *obj;
+ pdf_obj_dict *obj;
int i;
- obj = Memento_label(fz_malloc(ctx, sizeof(pdf_obj)), "pdf_obj(dict)");
+ obj = Memento_label(fz_malloc(ctx, sizeof(pdf_obj_dict)), "pdf_obj(dict)");
+ obj->super.refs = 1;
+ obj->super.kind = PDF_DICT;
+ obj->super.flags = 0;
obj->doc = doc;
- obj->refs = 1;
- obj->kind = PDF_DICT;
- obj->flags = 0;
obj->parent_num = 0;
- obj->u.d.len = 0;
- obj->u.d.cap = initialcap > 1 ? initialcap : 10;
+ obj->len = 0;
+ obj->cap = initialcap > 1 ? initialcap : 10;
fz_try(ctx)
{
- obj->u.d.items = Memento_label(fz_malloc_array(ctx, obj->u.d.cap, sizeof(struct keyval)), "pdf_obj(dict items)");
+ DICT(obj)->items = Memento_label(fz_malloc_array(ctx, DICT(obj)->cap, sizeof(struct keyval)), "pdf_obj(dict items)");
}
fz_catch(ctx)
{
fz_free(ctx, obj);
fz_rethrow(ctx);
}
- for (i = 0; i < obj->u.d.cap; i++)
+ for (i = 0; i < DICT(obj)->cap; i++)
{
- obj->u.d.items[i].k = NULL;
- obj->u.d.items[i].v = NULL;
+ DICT(obj)->items[i].k = NULL;
+ DICT(obj)->items[i].v = NULL;
}
- return obj;
+ return &obj->super;
}
static void
pdf_dict_grow(fz_context *ctx, pdf_obj *obj)
{
int i;
- int new_cap = (obj->u.d.cap * 3) / 2;
+ int new_cap = (DICT(obj)->cap * 3) / 2;
- obj->u.d.items = fz_resize_array(ctx, obj->u.d.items, new_cap, sizeof(struct keyval));
- obj->u.d.cap = new_cap;
+ DICT(obj)->items = fz_resize_array(ctx, DICT(obj)->items, new_cap, sizeof(struct keyval));
+ DICT(obj)->cap = new_cap;
- for (i = obj->u.d.len; i < obj->u.d.cap; i++)
+ for (i = DICT(obj)->len; i < DICT(obj)->cap; i++)
{
- obj->u.d.items[i].k = NULL;
- obj->u.d.items[i].v = NULL;
+ DICT(obj)->items[i].k = NULL;
+ DICT(obj)->items[i].v = NULL;
}
}
@@ -886,7 +928,7 @@ pdf_copy_dict(fz_context *ctx, pdf_obj *obj)
RESOLVE(obj);
if (obj >= PDF_OBJ__LIMIT)
{
- pdf_document *doc = obj->doc;
+ pdf_document *doc = DICT(obj)->doc;
if (obj->kind != PDF_DICT)
fz_warn(ctx, "assert: not a dict (%s)", pdf_objkindstr(obj));
@@ -907,7 +949,7 @@ pdf_dict_len(fz_context *ctx, pdf_obj *obj)
RESOLVE(obj);
if (obj < PDF_OBJ__LIMIT || obj->kind != PDF_DICT)
return 0;
- return obj->u.d.len;
+ return DICT(obj)->len;
}
pdf_obj *
@@ -916,9 +958,9 @@ pdf_dict_get_key(fz_context *ctx, pdf_obj *obj, int i)
RESOLVE(obj);
if (obj < PDF_OBJ__LIMIT || obj->kind != PDF_DICT)
return NULL;
- if (i < 0 || i >= obj->u.d.len)
+ if (i < 0 || i >= DICT(obj)->len)
return NULL;
- return obj->u.d.items[i].k;
+ return DICT(obj)->items[i].k;
}
pdf_obj *
@@ -927,9 +969,9 @@ pdf_dict_get_val(fz_context *ctx, pdf_obj *obj, int i)
RESOLVE(obj);
if (obj < PDF_OBJ__LIMIT || obj->kind != PDF_DICT)
return NULL;
- if (i < 0 || i >= obj->u.d.len)
+ if (i < 0 || i >= DICT(obj)->len)
return NULL;
- return obj->u.d.items[i].v;
+ return DICT(obj)->items[i].v;
}
void
@@ -941,25 +983,25 @@ pdf_dict_put_val_drop(fz_context *ctx, pdf_obj *obj, int i, pdf_obj *new_obj)
pdf_drop_obj(ctx, new_obj);
return;
}
- if (i < 0 || i >= obj->u.d.len)
+ if (i < 0 || i >= DICT(obj)->len)
{
/* FIXME: Should probably extend the dict here */
pdf_drop_obj(ctx, new_obj);
return;
}
- pdf_drop_obj(ctx, obj->u.d.items[i].v);
- obj->u.d.items[i].v = new_obj;
+ pdf_drop_obj(ctx, DICT(obj)->items[i].v);
+ DICT(obj)->items[i].v = new_obj;
}
static int
pdf_dict_finds(fz_context *ctx, pdf_obj *obj, const char *key, int *location)
{
- if ((obj->flags & PDF_FLAGS_SORTED) && obj->u.d.len > 0)
+ if ((obj->flags & PDF_FLAGS_SORTED) && DICT(obj)->len > 0)
{
int l = 0;
- int r = obj->u.d.len - 1;
+ int r = DICT(obj)->len - 1;
- if (strcmp(pdf_to_name(ctx, obj->u.d.items[r].k), key) < 0)
+ if (strcmp(pdf_to_name(ctx, DICT(obj)->items[r].k), key) < 0)
{
if (location)
*location = r + 1;
@@ -969,7 +1011,7 @@ pdf_dict_finds(fz_context *ctx, pdf_obj *obj, const char *key, int *location)
while (l <= r)
{
int m = (l + r) >> 1;
- int c = -strcmp(pdf_to_name(ctx, obj->u.d.items[m].k), key);
+ int c = -strcmp(pdf_to_name(ctx, DICT(obj)->items[m].k), key);
if (c < 0)
r = m - 1;
else if (c > 0)
@@ -985,13 +1027,13 @@ pdf_dict_finds(fz_context *ctx, pdf_obj *obj, const char *key, int *location)
else
{
int i;
- for (i = 0; i < obj->u.d.len; i++)
- if (strcmp(pdf_to_name(ctx, obj->u.d.items[i].k), key) == 0)
+ for (i = 0; i < DICT(obj)->len; i++)
+ if (strcmp(pdf_to_name(ctx, DICT(obj)->items[i].k), key) == 0)
return i;
if (location)
- *location = obj->u.d.len;
+ *location = DICT(obj)->len;
}
return -1;
@@ -1000,13 +1042,13 @@ pdf_dict_finds(fz_context *ctx, pdf_obj *obj, const char *key, int *location)
static int
pdf_dict_find(fz_context *ctx, pdf_obj *obj, pdf_obj *key, int *location)
{
- if ((obj->flags & PDF_FLAGS_SORTED) && obj->u.d.len > 0)
+ if ((obj->flags & PDF_FLAGS_SORTED) && DICT(obj)->len > 0)
{
int l = 0;
- int r = obj->u.d.len - 1;
- pdf_obj *k = obj->u.d.items[r].k;
+ int r = DICT(obj)->len - 1;
+ pdf_obj *k = DICT(obj)->items[r].k;
- if (k == key || (k >= PDF_OBJ__LIMIT && strcmp(k->u.n, PDF_NAMES[(intptr_t)key]) < 0))
+ if (k == key || (k >= PDF_OBJ__LIMIT && strcmp(NAME(k)->n, PDF_NAMES[(intptr_t)key]) < 0))
{
if (location)
*location = r + 1;
@@ -1018,8 +1060,8 @@ pdf_dict_find(fz_context *ctx, pdf_obj *obj, pdf_obj *key, int *location)
int m = (l + r) >> 1;
int c;
- k = obj->u.d.items[m].k;
- c = (k < PDF_OBJ__LIMIT ? key-k : -strcmp(k->u.n, PDF_NAMES[(intptr_t)key]));
+ k = DICT(obj)->items[m].k;
+ c = (k < PDF_OBJ__LIMIT ? key-k : -strcmp(NAME(k)->n, PDF_NAMES[(intptr_t)key]));
if (c < 0)
r = m - 1;
else if (c > 0)
@@ -1034,9 +1076,9 @@ pdf_dict_find(fz_context *ctx, pdf_obj *obj, pdf_obj *key, int *location)
else
{
int i;
- for (i = 0; i < obj->u.d.len; i++)
+ for (i = 0; i < DICT(obj)->len; i++)
{
- pdf_obj *k = obj->u.d.items[i].k;
+ pdf_obj *k = DICT(obj)->items[i].k;
if (k < PDF_OBJ__LIMIT)
{
if (k == key)
@@ -1044,13 +1086,13 @@ pdf_dict_find(fz_context *ctx, pdf_obj *obj, pdf_obj *key, int *location)
}
else
{
- if (!strcmp(PDF_NAMES[(intptr_t)key], k->u.n))
+ if (!strcmp(PDF_NAMES[(intptr_t)key], NAME(k)->n))
return i;
}
}
if (location)
- *location = obj->u.d.len;
+ *location = DICT(obj)->len;
}
return -1;
@@ -1067,7 +1109,7 @@ pdf_dict_gets(fz_context *ctx, pdf_obj *obj, const char *key)
i = pdf_dict_finds(ctx, obj, key, NULL);
if (i >= 0)
- return obj->u.d.items[i].v;
+ return DICT(obj)->items[i].v;
return NULL;
}
@@ -1144,7 +1186,7 @@ pdf_dict_get(fz_context *ctx, pdf_obj *obj, pdf_obj *key)
i = pdf_dict_find(ctx, obj, key, NULL);
if (i >= 0)
- return obj->u.d.items[i].v;
+ return DICT(obj)->items[i].v;
return NULL;
}
@@ -1199,33 +1241,33 @@ pdf_dict_put(fz_context *ctx, pdf_obj *obj, pdf_obj *key, pdf_obj *val)
return;
}
- if (obj->u.d.len > 100 && !(obj->flags & PDF_FLAGS_SORTED))
+ if (DICT(obj)->len > 100 && !(obj->flags & PDF_FLAGS_SORTED))
pdf_sort_dict(ctx, obj);
i = pdf_dict_finds(ctx, obj, s, &location);
- if (i >= 0 && i < obj->u.d.len)
+ if (i >= 0 && i < DICT(obj)->len)
{
- if (obj->u.d.items[i].v != val)
+ if (DICT(obj)->items[i].v != val)
{
- pdf_obj *d = obj->u.d.items[i].v;
- obj->u.d.items[i].v = pdf_keep_obj(ctx, val);
+ pdf_obj *d = DICT(obj)->items[i].v;
+ DICT(obj)->items[i].v = pdf_keep_obj(ctx, val);
pdf_drop_obj(ctx, d);
}
}
else
{
- if (obj->u.d.len + 1 > obj->u.d.cap)
+ if (DICT(obj)->len + 1 > DICT(obj)->cap)
pdf_dict_grow(ctx, obj);
i = location;
- if ((obj->flags & PDF_FLAGS_SORTED) && obj->u.d.len > 0)
- memmove(&obj->u.d.items[i + 1],
- &obj->u.d.items[i],
- (obj->u.d.len - i) * sizeof(struct keyval));
-
- obj->u.d.items[i].k = pdf_keep_obj(ctx, key);
- obj->u.d.items[i].v = pdf_keep_obj(ctx, val);
- obj->u.d.len ++;
+ if ((obj->flags & PDF_FLAGS_SORTED) && DICT(obj)->len > 0)
+ memmove(&DICT(obj)->items[i + 1],
+ &DICT(obj)->items[i],
+ (DICT(obj)->len - i) * sizeof(struct keyval));
+
+ DICT(obj)->items[i].k = pdf_keep_obj(ctx, key);
+ DICT(obj)->items[i].v = pdf_keep_obj(ctx, val);
+ DICT(obj)->len ++;
}
object_altered(ctx, obj, val);
@@ -1247,8 +1289,15 @@ pdf_dict_put_drop(fz_context *ctx, pdf_obj *obj, pdf_obj *key, pdf_obj *val)
void
pdf_dict_puts(fz_context *ctx, pdf_obj *obj, const char *key, pdf_obj *val)
{
- pdf_document *doc = obj->doc;
- pdf_obj *keyobj = pdf_new_name(ctx, doc, key);
+ pdf_document *doc;
+ pdf_obj *keyobj;
+
+ RESOLVE(obj);
+ if (obj < PDF_OBJ__LIMIT || obj->kind != PDF_DICT)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "not a dictionary (%s)", pdf_objkindstr(obj));
+
+ doc = DICT(obj)->doc;
+ keyobj = pdf_new_name(ctx, doc, key);
fz_try(ctx)
pdf_dict_put(ctx, obj, keyobj, val);
@@ -1261,16 +1310,20 @@ pdf_dict_puts(fz_context *ctx, pdf_obj *obj, const char *key, pdf_obj *val)
void
pdf_dict_puts_drop(fz_context *ctx, pdf_obj *obj, const char *key, pdf_obj *val)
{
- pdf_document *doc = obj->doc;
- pdf_obj *keyobj = NULL;
+ pdf_document *doc;
+ pdf_obj *keyobj;
+
+ RESOLVE(obj);
+ if (obj < PDF_OBJ__LIMIT || obj->kind != PDF_DICT)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "not a dictionary (%s)", pdf_objkindstr(obj));
+
+ doc = DICT(obj)->doc;
+ keyobj = pdf_new_name(ctx, doc, key);
fz_var(keyobj);
fz_try(ctx)
- {
- keyobj = pdf_new_name(ctx, doc, key);
pdf_dict_put(ctx, obj, keyobj, val);
- }
fz_always(ctx)
{
pdf_drop_obj(ctx, keyobj);
@@ -1285,59 +1338,60 @@ pdf_dict_puts_drop(fz_context *ctx, pdf_obj *obj, const char *key, pdf_obj *val)
void
pdf_dict_putp(fz_context *ctx, pdf_obj *obj, const char *keys, pdf_obj *val)
{
+ pdf_document *doc;
+ char buf[256];
+ char *k, *e;
+ pdf_obj *cobj = NULL;
+
RESOLVE(obj);
- if (obj >= PDF_OBJ__LIMIT)
- {
- pdf_document *doc = obj->doc;
+ if (obj < PDF_OBJ__LIMIT || obj->kind != PDF_DICT)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "not a dictionary (%s)", pdf_objkindstr(obj));
- char buf[256];
- char *k, *e;
- pdf_obj *cobj = NULL;
+ doc = DICT(obj)->doc;
- if (strlen(keys)+1 > 256)
- fz_throw(ctx, FZ_ERROR_GENERIC, "buffer overflow in pdf_dict_putp");
+ if (strlen(keys)+1 > 256)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "buffer overflow in pdf_dict_putp");
- strcpy(buf, keys);
+ strcpy(buf, keys);
- e = buf;
- while (*e)
- {
- k = e;
- while (*e != '/' && *e != '\0')
- e++;
+ e = buf;
+ while (*e)
+ {
+ k = e;
+ while (*e != '/' && *e != '\0')
+ e++;
- if (*e == '/')
- {
- *e = '\0';
- e++;
- }
+ if (*e == '/')
+ {
+ *e = '\0';
+ e++;
+ }
- if (*e)
+ if (*e)
+ {
+ /* Not the last key in the key path. Create subdict if not already there. */
+ cobj = pdf_dict_gets(ctx, obj, k);
+ if (cobj == NULL)
{
- /* Not the last key in the key path. Create subdict if not already there. */
- cobj = pdf_dict_gets(ctx, obj, k);
- if (cobj == NULL)
- {
- cobj = pdf_new_dict(ctx, doc, 1);
- fz_try(ctx)
- pdf_dict_puts(ctx, obj, k, cobj);
- fz_always(ctx)
- pdf_drop_obj(ctx, cobj);
- fz_catch(ctx)
- fz_rethrow(ctx);
- }
- /* Move to subdict */
- obj = cobj;
+ cobj = pdf_new_dict(ctx, doc, 1);
+ fz_try(ctx)
+ pdf_dict_puts(ctx, obj, k, cobj);
+ fz_always(ctx)
+ pdf_drop_obj(ctx, cobj);
+ fz_catch(ctx)
+ fz_rethrow(ctx);
}
+ /* Move to subdict */
+ obj = cobj;
+ }
+ else
+ {
+ /* Last key. Use it to store the value */
+ /* Use val = NULL to request delete */
+ if (val)
+ pdf_dict_puts(ctx, obj, k, val);
else
- {
- /* Last key. Use it to store the value */
- /* Use val = NULL to request delete */
- if (val)
- pdf_dict_puts(ctx, obj, k, val);
- else
- pdf_dict_dels(ctx, obj, k);
- }
+ pdf_dict_dels(ctx, obj, k);
}
}
}
@@ -1359,6 +1413,13 @@ pdf_dict_vputl(fz_context *ctx, pdf_obj *obj, pdf_obj *val, va_list keys)
pdf_obj *key;
pdf_obj *next_key;
pdf_obj *next_obj;
+ pdf_document *doc;
+
+ RESOLVE(obj);
+ if (obj < PDF_OBJ__LIMIT || obj->kind != PDF_DICT)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "not a dictionary (%s)", pdf_objkindstr(obj));
+
+ doc = DICT(obj)->doc;
key = va_arg(keys, pdf_obj *);
if (key == NULL)
@@ -1380,7 +1441,7 @@ new_obj:
/* We have to create entries */
do
{
- next_obj = pdf_new_dict(ctx, obj->doc, 1);
+ next_obj = pdf_new_dict(ctx, doc, 1);
pdf_dict_put_drop(ctx, obj, key, next_obj);
obj = next_obj;
key = next_key;
@@ -1435,11 +1496,11 @@ pdf_dict_dels(fz_context *ctx, pdf_obj *obj, const char *key)
int i = pdf_dict_finds(ctx, obj, key, NULL);
if (i >= 0)
{
- pdf_drop_obj(ctx, obj->u.d.items[i].k);
- pdf_drop_obj(ctx, obj->u.d.items[i].v);
+ pdf_drop_obj(ctx, DICT(obj)->items[i].k);
+ pdf_drop_obj(ctx, DICT(obj)->items[i].v);
obj->flags &= ~PDF_FLAGS_SORTED;
- obj->u.d.items[i] = obj->u.d.items[obj->u.d.len-1];
- obj->u.d.len --;
+ DICT(obj)->items[i] = DICT(obj)->items[DICT(obj)->len-1];
+ DICT(obj)->len --;
}
}
@@ -1458,7 +1519,7 @@ pdf_dict_del(fz_context *ctx, pdf_obj *obj, pdf_obj *key)
if (key < PDF_OBJ__LIMIT)
pdf_dict_dels(ctx, obj, PDF_NAMES[(intptr_t)key]);
else if (key->kind == PDF_NAME)
- pdf_dict_dels(ctx, obj, key->u.n);
+ pdf_dict_dels(ctx, obj, NAME(obj)->n);
/* else Can't warn */
}
@@ -1470,7 +1531,7 @@ pdf_sort_dict(fz_context *ctx, pdf_obj *obj)
return;
if (!(obj->flags & PDF_FLAGS_SORTED))
{
- qsort(obj->u.d.items, obj->u.d.len, sizeof(struct keyval), keyvalcmp);
+ qsort(DICT(obj)->items, DICT(obj)->len, sizeof(struct keyval), keyvalcmp);
obj->flags |= PDF_FLAGS_SORTED;
}
}
@@ -1557,10 +1618,10 @@ pdf_drop_array(fz_context *ctx, pdf_obj *obj)
{
int i;
- for (i = 0; i < obj->u.a.len; i++)
- pdf_drop_obj(ctx, obj->u.a.items[i]);
+ for (i = 0; i < DICT(obj)->len; i++)
+ pdf_drop_obj(ctx, ARRAY(obj)->items[i]);
- fz_free(ctx, obj->u.a.items);
+ fz_free(ctx, DICT(obj)->items);
fz_free(ctx, obj);
}
@@ -1569,12 +1630,12 @@ pdf_drop_dict(fz_context *ctx, pdf_obj *obj)
{
int i;
- for (i = 0; i < obj->u.d.len; i++) {
- pdf_drop_obj(ctx, obj->u.d.items[i].k);
- pdf_drop_obj(ctx, obj->u.d.items[i].v);
+ for (i = 0; i < DICT(obj)->len; i++) {
+ pdf_drop_obj(ctx, DICT(obj)->items[i].k);
+ pdf_drop_obj(ctx, DICT(obj)->items[i].v);
}
- fz_free(ctx, obj->u.d.items);
+ fz_free(ctx, DICT(obj)->items);
fz_free(ctx, obj);
}
@@ -1602,16 +1663,16 @@ pdf_set_obj_parent(fz_context *ctx, pdf_obj *obj, int num)
if (obj < PDF_OBJ__LIMIT)
return;
- obj->parent_num = num;
-
switch(obj->kind)
{
case PDF_ARRAY:
+ ARRAY(obj)->parent_num = num;
n = pdf_array_len(ctx, obj);
for (i = 0; i < n; i++)
pdf_set_obj_parent(ctx, pdf_array_get(ctx, obj, i), num);
break;
case PDF_DICT:
+ DICT(obj)->parent_num = num;
n = pdf_dict_len(ctx, obj);
for (i = 0; i < n; i++)
pdf_set_obj_parent(ctx, pdf_dict_get_val(ctx, obj, i), num);
@@ -1624,7 +1685,15 @@ int pdf_obj_parent_num(fz_context *ctx, pdf_obj *obj)
if (obj < PDF_OBJ__LIMIT)
return 0;
- return obj->parent_num;
+ switch(obj->kind)
+ {
+ case PDF_ARRAY:
+ return ARRAY(obj)->parent_num;
+ case PDF_DICT:
+ return DICT(obj)->parent_num;
+ default:
+ return 0;
+ }
}
pdf_obj *pdf_new_obj_from_str(fz_context *ctx, pdf_document *doc, const char *src)