diff options
author | Robin Watts <robin.watts@artifex.com> | 2015-03-04 19:29:22 +0000 |
---|---|---|
committer | Robin Watts <robin.watts@artifex.com> | 2015-03-24 19:49:59 +0000 |
commit | 563c482145d65c4006f5842c8860ab1b09f5a229 (patch) | |
tree | c2b32f42ee3fd9b112f541db3c1d10a6dd21d30d | |
parent | f533104d6e66b3fc6d3b63b98ec7fe4fb175b366 (diff) | |
download | mupdf-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.c | 653 |
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) |