diff options
author | Tor Andersson <tor.andersson@artifex.com> | 2013-06-19 15:29:44 +0200 |
---|---|---|
committer | Tor Andersson <tor.andersson@artifex.com> | 2013-06-20 16:45:35 +0200 |
commit | 0a927854a10e1e6b9770a81e2e1d9f3093631757 (patch) | |
tree | 3d65d820d9fdba2d0d394d99c36290c851b78ca0 /pdf/pdf_object.c | |
parent | 1ae8f19179c5f0f8c6352b3c7855465325d5449a (diff) | |
download | mupdf-0a927854a10e1e6b9770a81e2e1d9f3093631757.tar.xz |
Rearrange source files.
Diffstat (limited to 'pdf/pdf_object.c')
-rw-r--r-- | pdf/pdf_object.c | 1576 |
1 files changed, 0 insertions, 1576 deletions
diff --git a/pdf/pdf_object.c b/pdf/pdf_object.c deleted file mode 100644 index 8e5cf419..00000000 --- a/pdf/pdf_object.c +++ /dev/null @@ -1,1576 +0,0 @@ -#include "mupdf/pdf.h" - -typedef enum pdf_objkind_e -{ - PDF_NULL = 0, - PDF_BOOL = 'b', - PDF_INT = 'i', - PDF_REAL = 'f', - PDF_STRING = 's', - PDF_NAME = 'n', - PDF_ARRAY = 'a', - PDF_DICT = 'd', - PDF_INDIRECT = 'r' -} pdf_objkind; - -struct keyval -{ - pdf_obj *k; - pdf_obj *v; -}; - -struct pdf_obj_s -{ - int refs; - char kind; - char marked; - fz_context *ctx; - union - { - int b; - 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 { - char sorted; - int len; - int cap; - struct keyval *items; - } d; - struct { - int num; - int gen; - pdf_document *xref; - } r; - } u; -}; - -pdf_obj * -pdf_new_null(fz_context *ctx) -{ - pdf_obj *obj; - obj = Memento_label(fz_malloc(ctx, sizeof(pdf_obj)), "pdf_obj(null)"); - obj->ctx = ctx; - obj->refs = 1; - obj->kind = PDF_NULL; - obj->marked = 0; - return obj; -} - -pdf_obj * -pdf_new_bool(fz_context *ctx, int b) -{ - pdf_obj *obj; - obj = Memento_label(fz_malloc(ctx, sizeof(pdf_obj)), "pdf_obj(bool)"); - obj->ctx = ctx; - obj->refs = 1; - obj->kind = PDF_BOOL; - obj->marked = 0; - obj->u.b = b; - return obj; -} - -pdf_obj * -pdf_new_int(fz_context *ctx, int i) -{ - pdf_obj *obj; - obj = Memento_label(fz_malloc(ctx, sizeof(pdf_obj)), "pdf_obj(int)"); - obj->ctx = ctx; - obj->refs = 1; - obj->kind = PDF_INT; - obj->marked = 0; - obj->u.i = i; - return obj; -} - -pdf_obj * -pdf_new_real(fz_context *ctx, float f) -{ - pdf_obj *obj; - obj = Memento_label(fz_malloc(ctx, sizeof(pdf_obj)), "pdf_obj(real)"); - obj->ctx = ctx; - obj->refs = 1; - obj->kind = PDF_REAL; - obj->marked = 0; - obj->u.f = f; - return obj; -} - -pdf_obj * -pdf_new_string(fz_context *ctx, 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->ctx = ctx; - obj->refs = 1; - obj->kind = PDF_STRING; - obj->marked = 0; - obj->u.s.len = len; - memcpy(obj->u.s.buf, str, len); - obj->u.s.buf[len] = '\0'; - return obj; -} - -pdf_obj * -pdf_new_name(fz_context *ctx, const char *str) -{ - pdf_obj *obj; - obj = Memento_label(fz_malloc(ctx, offsetof(pdf_obj, u.n) + strlen(str) + 1), "pdf_obj(name)"); - obj->ctx = ctx; - obj->refs = 1; - obj->kind = PDF_NAME; - obj->marked = 0; - strcpy(obj->u.n, str); - return obj; -} - -pdf_obj * -pdf_new_indirect(fz_context *ctx, int num, int gen, void *xref) -{ - pdf_obj *obj; - obj = Memento_label(fz_malloc(ctx, sizeof(pdf_obj)), "pdf_obj(indirect)"); - obj->ctx = ctx; - obj->refs = 1; - obj->kind = PDF_INDIRECT; - obj->marked = 0; - obj->u.r.num = num; - obj->u.r.gen = gen; - obj->u.r.xref = xref; - return obj; -} - -pdf_obj * -pdf_keep_obj(pdf_obj *obj) -{ - if (obj) - obj->refs ++; - return obj; -} - -int pdf_is_indirect(pdf_obj *obj) -{ - return obj ? obj->kind == PDF_INDIRECT : 0; -} - -#define RESOLVE(obj) \ - do { \ - if (obj && obj->kind == PDF_INDIRECT) \ - {\ - obj = pdf_resolve_indirect(obj); \ - } \ - } while (0) - -int pdf_is_null(pdf_obj *obj) -{ - RESOLVE(obj); - return obj ? obj->kind == PDF_NULL : 0; -} - -int pdf_is_bool(pdf_obj *obj) -{ - RESOLVE(obj); - return obj ? obj->kind == PDF_BOOL : 0; -} - -int pdf_is_int(pdf_obj *obj) -{ - RESOLVE(obj); - return obj ? obj->kind == PDF_INT : 0; -} - -int pdf_is_real(pdf_obj *obj) -{ - RESOLVE(obj); - return obj ? obj->kind == PDF_REAL : 0; -} - -int pdf_is_string(pdf_obj *obj) -{ - RESOLVE(obj); - return obj ? obj->kind == PDF_STRING : 0; -} - -int pdf_is_name(pdf_obj *obj) -{ - RESOLVE(obj); - return obj ? obj->kind == PDF_NAME : 0; -} - -int pdf_is_array(pdf_obj *obj) -{ - RESOLVE(obj); - return obj ? obj->kind == PDF_ARRAY : 0; -} - -int pdf_is_dict(pdf_obj *obj) -{ - RESOLVE(obj); - return obj ? obj->kind == PDF_DICT : 0; -} - -int pdf_to_bool(pdf_obj *obj) -{ - RESOLVE(obj); - if (!obj) - return 0; - return obj->kind == PDF_BOOL ? obj->u.b : 0; -} - -int pdf_to_int(pdf_obj *obj) -{ - RESOLVE(obj); - if (!obj) - return 0; - if (obj->kind == PDF_INT) - return obj->u.i; - if (obj->kind == PDF_REAL) - return (int)(obj->u.f + 0.5f); /* No roundf in MSVC */ - return 0; -} - -float pdf_to_real(pdf_obj *obj) -{ - RESOLVE(obj); - if (!obj) - return 0; - if (obj->kind == PDF_REAL) - return obj->u.f; - if (obj->kind == PDF_INT) - return obj->u.i; - return 0; -} - -char *pdf_to_name(pdf_obj *obj) -{ - RESOLVE(obj); - if (!obj || obj->kind != PDF_NAME) - return ""; - return obj->u.n; -} - -char *pdf_to_str_buf(pdf_obj *obj) -{ - RESOLVE(obj); - if (!obj || obj->kind != PDF_STRING) - return ""; - return obj->u.s.buf; -} - -int pdf_to_str_len(pdf_obj *obj) -{ - RESOLVE(obj); - if (!obj || obj->kind != PDF_STRING) - return 0; - return obj->u.s.len; -} - -void pdf_set_int(pdf_obj *obj, int i) -{ - if (!obj || obj->kind != PDF_INT) - return; - obj->u.i = i; -} - -/* for use by pdf_crypt_obj_imp to decrypt AES string in place */ -void pdf_set_str_len(pdf_obj *obj, int newlen) -{ - RESOLVE(obj); - if (!obj || obj->kind != PDF_STRING) - return; /* This should never happen */ - if (newlen > obj->u.s.len) - return; /* This should never happen */ - obj->u.s.len = newlen; -} - -pdf_obj *pdf_to_dict(pdf_obj *obj) -{ - RESOLVE(obj); - return (obj && obj->kind == PDF_DICT ? obj : NULL); -} - -int pdf_to_num(pdf_obj *obj) -{ - if (!obj || obj->kind != PDF_INDIRECT) - return 0; - return obj->u.r.num; -} - -int pdf_to_gen(pdf_obj *obj) -{ - if (!obj || obj->kind != PDF_INDIRECT) - return 0; - return obj->u.r.gen; -} - -pdf_document *pdf_get_indirect_document(pdf_obj *obj) -{ - if (!obj || obj->kind != PDF_INDIRECT) - return NULL; - return obj->u.r.xref; -} - -int -pdf_objcmp(pdf_obj *a, pdf_obj *b) -{ - int i; - - if (a == b) - return 0; - - if (!a || !b) - return 1; - - if (a->kind != b->kind) - return 1; - - switch (a->kind) - { - case PDF_NULL: - return 0; - - case PDF_BOOL: - return a->u.b - b->u.b; - - case PDF_INT: - return a->u.i - b->u.i; - - case PDF_REAL: - if (a->u.f < b->u.f) - return -1; - if (a->u.f > b->u.f) - return 1; - return 0; - - case PDF_STRING: - if (a->u.s.len < b->u.s.len) - { - if (memcmp(a->u.s.buf, b->u.s.buf, a->u.s.len) <= 0) - return -1; - return 1; - } - if (a->u.s.len > b->u.s.len) - { - if (memcmp(a->u.s.buf, b->u.s.buf, b->u.s.len) >= 0) - return 1; - return -1; - } - return memcmp(a->u.s.buf, b->u.s.buf, a->u.s.len); - - case PDF_NAME: - return strcmp(a->u.n, b->u.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; - - 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(a->u.a.items[i], b->u.a.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 (pdf_objcmp(a->u.d.items[i].k, b->u.d.items[i].k)) - return 1; - if (pdf_objcmp(a->u.d.items[i].v, b->u.d.items[i].v)) - return 1; - } - return 0; - - } - return 1; -} - -static char * -pdf_objkindstr(pdf_obj *obj) -{ - if (!obj) - return "<NULL>"; - switch (obj->kind) - { - case PDF_NULL: return "null"; - case PDF_BOOL: return "boolean"; - case PDF_INT: return "integer"; - case PDF_REAL: return "real"; - case PDF_STRING: return "string"; - case PDF_NAME: return "name"; - case PDF_ARRAY: return "array"; - case PDF_DICT: return "dictionary"; - case PDF_INDIRECT: return "reference"; - } - return "<unknown>"; -} - -pdf_obj * -pdf_new_array(fz_context *ctx, int initialcap) -{ - pdf_obj *obj; - int i; - - obj = Memento_label(fz_malloc(ctx, sizeof(pdf_obj)), "pdf_obj(array)"); - obj->ctx = ctx; - obj->refs = 1; - obj->kind = PDF_ARRAY; - obj->marked = 0; - - obj->u.a.len = 0; - obj->u.a.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)"); - } - 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; - - return obj; -} - -static void -pdf_array_grow(pdf_obj *obj) -{ - int i; - int new_cap = (obj->u.a.cap * 3) / 2; - - obj->u.a.items = fz_resize_array(obj->ctx, obj->u.a.items, new_cap, sizeof(pdf_obj*)); - obj->u.a.cap = new_cap; - - for (i = obj->u.a.len ; i < obj->u.a.cap; i++) - obj->u.a.items[i] = NULL; -} - -pdf_obj * -pdf_copy_array(fz_context *ctx, pdf_obj *obj) -{ - pdf_obj *arr; - int i; - int n; - - RESOLVE(obj); - if (!obj) - return NULL; /* Can't warn :( */ - if (obj->kind != PDF_ARRAY) - fz_warn(ctx, "assert: not an array (%s)", pdf_objkindstr(obj)); - - arr = pdf_new_array(ctx, pdf_array_len(obj)); - n = pdf_array_len(obj); - for (i = 0; i < n; i++) - pdf_array_push(arr, pdf_array_get(obj, i)); - - return arr; -} - -int -pdf_array_len(pdf_obj *obj) -{ - RESOLVE(obj); - if (!obj || obj->kind != PDF_ARRAY) - return 0; - return obj->u.a.len; -} - -pdf_obj * -pdf_array_get(pdf_obj *obj, int i) -{ - RESOLVE(obj); - - if (!obj || obj->kind != PDF_ARRAY) - return NULL; - - if (i < 0 || i >= obj->u.a.len) - return NULL; - - return obj->u.a.items[i]; -} - -void -pdf_array_put(pdf_obj *obj, int i, pdf_obj *item) -{ - RESOLVE(obj); - - if (!obj) - return; /* Can't warn :( */ - if (obj->kind != PDF_ARRAY) - fz_warn(obj->ctx, "assert: not an array (%s)", pdf_objkindstr(obj)); - else if (i < 0) - fz_warn(obj->ctx, "assert: index %d < 0", i); - else if (i >= obj->u.a.len) - fz_warn(obj->ctx, "assert: index %d > length %d", i, obj->u.a.len); - else - { - pdf_drop_obj(obj->u.a.items[i]); - obj->u.a.items[i] = pdf_keep_obj(item); - } -} - -void -pdf_array_push(pdf_obj *obj, pdf_obj *item) -{ - RESOLVE(obj); - - if (!obj) - return; /* Can't warn :( */ - if (obj->kind != PDF_ARRAY) - fz_warn(obj->ctx, "assert: not an array (%s)", pdf_objkindstr(obj)); - else - { - if (obj->u.a.len + 1 > obj->u.a.cap) - pdf_array_grow(obj); - obj->u.a.items[obj->u.a.len] = pdf_keep_obj(item); - obj->u.a.len++; - } -} - -void -pdf_array_push_drop(pdf_obj *obj, pdf_obj *item) -{ - fz_context *ctx = obj->ctx; - - fz_try(ctx) - { - pdf_array_push(obj, item); - } - fz_always(ctx) - { - pdf_drop_obj(item); - } - fz_catch(ctx) - { - fz_rethrow(ctx); - } -} - -void -pdf_array_insert(pdf_obj *obj, pdf_obj *item) -{ - RESOLVE(obj); - - if (!obj) - return; /* Can't warn :( */ - if (obj->kind != PDF_ARRAY) - fz_warn(obj->ctx, "assert: not an array (%s)", pdf_objkindstr(obj)); - else - { - if (obj->u.a.len + 1 > obj->u.a.cap) - pdf_array_grow(obj); - memmove(obj->u.a.items + 1, obj->u.a.items, obj->u.a.len * sizeof(pdf_obj*)); - obj->u.a.items[0] = pdf_keep_obj(item); - obj->u.a.len++; - } -} - -int -pdf_array_contains(pdf_obj *arr, pdf_obj *obj) -{ - int i, len; - - len = pdf_array_len(arr); - for (i = 0; i < len; i++) - if (!pdf_objcmp(pdf_array_get(arr, i), obj)) - return 1; - - return 0; -} - -pdf_obj *pdf_new_rect(fz_context *ctx, const fz_rect *rect) -{ - pdf_obj *arr = NULL; - pdf_obj *item = NULL; - - fz_var(arr); - fz_var(item); - fz_try(ctx) - { - arr = pdf_new_array(ctx, 4); - - item = pdf_new_real(ctx, rect->x0); - pdf_array_push(arr, item); - pdf_drop_obj(item); - item = NULL; - - item = pdf_new_real(ctx, rect->y0); - pdf_array_push(arr, item); - pdf_drop_obj(item); - item = NULL; - - item = pdf_new_real(ctx, rect->x1); - pdf_array_push(arr, item); - pdf_drop_obj(item); - item = NULL; - - item = pdf_new_real(ctx, rect->y1); - pdf_array_push(arr, item); - pdf_drop_obj(item); - item = NULL; - } - fz_catch(ctx) - { - pdf_drop_obj(item); - pdf_drop_obj(arr); - fz_rethrow(ctx); - } - - return arr; -} - -pdf_obj *pdf_new_matrix(fz_context *ctx, const fz_matrix *mtx) -{ - pdf_obj *arr = NULL; - pdf_obj *item = NULL; - - fz_var(arr); - fz_var(item); - fz_try(ctx) - { - arr = pdf_new_array(ctx, 6); - - item = pdf_new_real(ctx, mtx->a); - pdf_array_push(arr, item); - pdf_drop_obj(item); - item = NULL; - - item = pdf_new_real(ctx, mtx->b); - pdf_array_push(arr, item); - pdf_drop_obj(item); - item = NULL; - - item = pdf_new_real(ctx, mtx->c); - pdf_array_push(arr, item); - pdf_drop_obj(item); - item = NULL; - - item = pdf_new_real(ctx, mtx->d); - pdf_array_push(arr, item); - pdf_drop_obj(item); - item = NULL; - - item = pdf_new_real(ctx, mtx->e); - pdf_array_push(arr, item); - pdf_drop_obj(item); - item = NULL; - - item = pdf_new_real(ctx, mtx->f); - pdf_array_push(arr, item); - pdf_drop_obj(item); - item = NULL; - } - fz_catch(ctx) - { - pdf_drop_obj(item); - pdf_drop_obj(arr); - fz_rethrow(ctx); - } - - return arr; -} - -/* dicts may only have names as keys! */ - -static int keyvalcmp(const void *ap, const void *bp) -{ - const struct keyval *a = ap; - const struct keyval *b = bp; - return strcmp(pdf_to_name(a->k), pdf_to_name(b->k)); -} - -pdf_obj * -pdf_new_dict(fz_context *ctx, int initialcap) -{ - pdf_obj *obj; - int i; - - obj = Memento_label(fz_malloc(ctx, sizeof(pdf_obj)), "pdf_obj(dict)"); - obj->ctx = ctx; - obj->refs = 1; - obj->kind = PDF_DICT; - obj->marked = 0; - - obj->u.d.sorted = 0; - obj->u.d.len = 0; - obj->u.d.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)"); - } - fz_catch(ctx) - { - fz_free(ctx, obj); - fz_rethrow(ctx); - } - for (i = 0; i < obj->u.d.cap; i++) - { - obj->u.d.items[i].k = NULL; - obj->u.d.items[i].v = NULL; - } - - return obj; -} - -static void -pdf_dict_grow(pdf_obj *obj) -{ - int i; - int new_cap = (obj->u.d.cap * 3) / 2; - - obj->u.d.items = fz_resize_array(obj->ctx, obj->u.d.items, new_cap, sizeof(struct keyval)); - obj->u.d.cap = new_cap; - - for (i = obj->u.d.len; i < obj->u.d.cap; i++) - { - obj->u.d.items[i].k = NULL; - obj->u.d.items[i].v = NULL; - } -} - -pdf_obj * -pdf_copy_dict(fz_context *ctx, pdf_obj *obj) -{ - pdf_obj *dict; - int i, n; - - RESOLVE(obj); - if (!obj) - return NULL; /* Can't warn :( */ - if (obj->kind != PDF_DICT) - fz_warn(ctx, "assert: not a dict (%s)", pdf_objkindstr(obj)); - - n = pdf_dict_len(obj); - dict = pdf_new_dict(ctx, n); - for (i = 0; i < n; i++) - pdf_dict_put(dict, pdf_dict_get_key(obj, i), pdf_dict_get_val(obj, i)); - - return dict; -} - -int -pdf_dict_len(pdf_obj *obj) -{ - RESOLVE(obj); - if (!obj || obj->kind != PDF_DICT) - return 0; - return obj->u.d.len; -} - -pdf_obj * -pdf_dict_get_key(pdf_obj *obj, int i) -{ - RESOLVE(obj); - if (!obj || obj->kind != PDF_DICT) - return NULL; - - if (i < 0 || i >= obj->u.d.len) - return NULL; - - return obj->u.d.items[i].k; -} - -pdf_obj * -pdf_dict_get_val(pdf_obj *obj, int i) -{ - RESOLVE(obj); - if (!obj || obj->kind != PDF_DICT) - return NULL; - - if (i < 0 || i >= obj->u.d.len) - return NULL; - - return obj->u.d.items[i].v; -} - -static int -pdf_dict_finds(pdf_obj *obj, const char *key, int *location) -{ - if (obj->u.d.sorted && obj->u.d.len > 0) - { - int l = 0; - int r = obj->u.d.len - 1; - - if (strcmp(pdf_to_name(obj->u.d.items[r].k), key) < 0) - { - if (location) - *location = r + 1; - return -1; - } - - while (l <= r) - { - int m = (l + r) >> 1; - int c = -strcmp(pdf_to_name(obj->u.d.items[m].k), key); - if (c < 0) - r = m - 1; - else if (c > 0) - l = m + 1; - else - return m; - - if (location) - *location = l; - } - } - - else - { - int i; - for (i = 0; i < obj->u.d.len; i++) - if (strcmp(pdf_to_name(obj->u.d.items[i].k), key) == 0) - return i; - - if (location) - *location = obj->u.d.len; - } - - return -1; -} - -pdf_obj * -pdf_dict_gets(pdf_obj *obj, const char *key) -{ - int i; - - RESOLVE(obj); - if (!obj || obj->kind != PDF_DICT) - return NULL; - - i = pdf_dict_finds(obj, key, NULL); - if (i >= 0) - return obj->u.d.items[i].v; - - return NULL; -} - -pdf_obj * -pdf_dict_getp(pdf_obj *obj, const char *keys) -{ - char buf[256]; - char *k, *e; - - if (strlen(keys)+1 > 256) - fz_throw(obj->ctx, FZ_ERROR_GENERIC, "buffer overflow in pdf_dict_getp"); - - strcpy(buf, keys); - - e = buf; - while (*e && obj) - { - k = e; - while (*e != '/' && *e != '\0') - e++; - - if (*e == '/') - { - *e = '\0'; - e++; - } - - obj = pdf_dict_gets(obj, k); - } - - return obj; -} - -pdf_obj * -pdf_dict_get(pdf_obj *obj, pdf_obj *key) -{ - if (!key || key->kind != PDF_NAME) - return NULL; - return pdf_dict_gets(obj, pdf_to_name(key)); -} - -pdf_obj * -pdf_dict_getsa(pdf_obj *obj, const char *key, const char *abbrev) -{ - pdf_obj *v; - v = pdf_dict_gets(obj, key); - if (v) - return v; - return pdf_dict_gets(obj, abbrev); -} - -void -pdf_dict_put(pdf_obj *obj, pdf_obj *key, pdf_obj *val) -{ - int location; - char *s; - int i; - - RESOLVE(obj); - if (!obj) - return; /* Can't warn :( */ - if (obj->kind != PDF_DICT) - { - fz_warn(obj->ctx, "assert: not a dict (%s)", pdf_objkindstr(obj)); - return; - } - - RESOLVE(key); - if (!key || key->kind != PDF_NAME) - { - fz_warn(obj->ctx, "assert: key is not a name (%s)", pdf_objkindstr(obj)); - return; - } - else - s = pdf_to_name(key); - - if (!val) - { - fz_warn(obj->ctx, "assert: val does not exist for key (%s)", s); - return; - } - - if (obj->u.d.len > 100 && !obj->u.d.sorted) - pdf_sort_dict(obj); - - i = pdf_dict_finds(obj, s, &location); - if (i >= 0 && i < obj->u.d.len) - { - if (obj->u.d.items[i].v != val) - { - pdf_drop_obj(obj->u.d.items[i].v); - obj->u.d.items[i].v = pdf_keep_obj(val); - } - } - else - { - if (obj->u.d.len + 1 > obj->u.d.cap) - pdf_dict_grow(obj); - - i = location; - if (obj->u.d.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(key); - obj->u.d.items[i].v = pdf_keep_obj(val); - obj->u.d.len ++; - } -} - -void -pdf_dict_puts(pdf_obj *obj, const char *key, pdf_obj *val) -{ - fz_context *ctx = obj->ctx; - pdf_obj *keyobj = pdf_new_name(ctx, key); - - fz_try(ctx) - { - pdf_dict_put(obj, keyobj, val); - } - fz_always(ctx) - { - pdf_drop_obj(keyobj); - } - fz_catch(ctx) - { - fz_rethrow(ctx); - } -} - -void -pdf_dict_puts_drop(pdf_obj *obj, const char *key, pdf_obj *val) -{ - fz_context *ctx = obj->ctx; - pdf_obj *keyobj = NULL; - - fz_var(keyobj); - - fz_try(ctx) - { - keyobj = pdf_new_name(ctx, key); - pdf_dict_put(obj, keyobj, val); - } - fz_always(ctx) - { - pdf_drop_obj(keyobj); - pdf_drop_obj(val); - } - fz_catch(ctx) - { - fz_rethrow(ctx); - } -} - -void -pdf_dict_putp(pdf_obj *obj, const char *keys, pdf_obj *val) -{ - fz_context *ctx = obj->ctx; - char buf[256]; - char *k, *e; - pdf_obj *cobj = NULL; - - if (strlen(keys)+1 > 256) - fz_throw(obj->ctx, FZ_ERROR_GENERIC, "buffer overflow in pdf_dict_getp"); - - strcpy(buf, keys); - - e = buf; - while (*e) - { - k = e; - while (*e != '/' && *e != '\0') - e++; - - if (*e == '/') - { - *e = '\0'; - e++; - } - - if (*e) - { - /* Not the last key in the key path. Create subdict if not already there. */ - cobj = pdf_dict_gets(obj, k); - if (cobj == NULL) - { - cobj = pdf_new_dict(ctx, 1); - fz_try(ctx) - { - pdf_dict_puts(obj, k, cobj); - } - fz_always(ctx) - { - pdf_drop_obj(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(obj, k, val); - else - pdf_dict_dels(obj, k); - } - } -} - -void -pdf_dict_putp_drop(pdf_obj *obj, const char *keys, pdf_obj *val) -{ - fz_context *ctx = obj->ctx; - - fz_try(ctx) - { - pdf_dict_putp(obj, keys, val); - } - fz_always(ctx) - { - pdf_drop_obj(val); - } - fz_catch(ctx) - { - fz_rethrow(ctx); - } -} - -void -pdf_dict_dels(pdf_obj *obj, const char *key) -{ - RESOLVE(obj); - - if (!obj) - return; /* Can't warn :( */ - if (obj->kind != PDF_DICT) - fz_warn(obj->ctx, "assert: not a dict (%s)", pdf_objkindstr(obj)); - else - { - int i = pdf_dict_finds(obj, key, NULL); - if (i >= 0) - { - pdf_drop_obj(obj->u.d.items[i].k); - pdf_drop_obj(obj->u.d.items[i].v); - obj->u.d.sorted = 0; - obj->u.d.items[i] = obj->u.d.items[obj->u.d.len-1]; - obj->u.d.len --; - } - } -} - -void -pdf_dict_del(pdf_obj *obj, pdf_obj *key) -{ - RESOLVE(key); - if (!key || key->kind != PDF_NAME) - fz_warn(obj->ctx, "assert: key is not a name (%s)", pdf_objkindstr(obj)); - else - pdf_dict_dels(obj, key->u.n); -} - -void -pdf_sort_dict(pdf_obj *obj) -{ - RESOLVE(obj); - if (!obj || obj->kind != PDF_DICT) - return; - if (!obj->u.d.sorted) - { - qsort(obj->u.d.items, obj->u.d.len, sizeof(struct keyval), keyvalcmp); - obj->u.d.sorted = 1; - } -} - -int -pdf_obj_marked(pdf_obj *obj) -{ - RESOLVE(obj); - if (!obj) - return 0; - return obj->marked; -} - -int -pdf_obj_mark(pdf_obj *obj) -{ - int marked; - RESOLVE(obj); - if (!obj) - return 0; - marked = obj->marked; - obj->marked = 1; - return marked; -} - -void -pdf_obj_unmark(pdf_obj *obj) -{ - RESOLVE(obj); - if (!obj) - return; - obj->marked = 0; -} - -static void -pdf_free_array(pdf_obj *obj) -{ - int i; - - for (i = 0; i < obj->u.a.len; i++) - pdf_drop_obj(obj->u.a.items[i]); - - fz_free(obj->ctx, obj->u.a.items); - fz_free(obj->ctx, obj); -} - -static void -pdf_free_dict(pdf_obj *obj) -{ - int i; - - for (i = 0; i < obj->u.d.len; i++) { - pdf_drop_obj(obj->u.d.items[i].k); - pdf_drop_obj(obj->u.d.items[i].v); - } - - fz_free(obj->ctx, obj->u.d.items); - fz_free(obj->ctx, obj); -} - -void -pdf_drop_obj(pdf_obj *obj) -{ - if (!obj) - return; - if (--obj->refs) - return; - if (obj->kind == PDF_ARRAY) - pdf_free_array(obj); - else if (obj->kind == PDF_DICT) - pdf_free_dict(obj); - else - fz_free(obj->ctx, obj); -} - -pdf_obj *pdf_new_obj_from_str(fz_context *ctx, const char *src) -{ - pdf_obj *result; - pdf_lexbuf lexbuf; - fz_stream *stream = fz_open_memory(ctx, (unsigned char *)src, strlen(src)); - - pdf_lexbuf_init(ctx, &lexbuf, PDF_LEXBUF_SMALL); - fz_try(ctx) - { - result = pdf_parse_stm_obj(NULL, stream, &lexbuf); - } - fz_always(ctx) - { - pdf_lexbuf_fin(&lexbuf); - fz_close(stream); - } - fz_catch(ctx) - { - /* FIXME: TryLater */ - return NULL; - } - - return result; -} - -/* Pretty printing objects */ - -struct fmt -{ - char *buf; - int cap; - int len; - int indent; - int tight; - int col; - int sep; - int last; -}; - -static void fmt_obj(struct fmt *fmt, pdf_obj *obj); - -static inline int iswhite(int ch) -{ - return - ch == '\000' || - ch == '\011' || - ch == '\012' || - ch == '\014' || - ch == '\015' || - ch == '\040'; -} - -static inline int isdelim(int ch) -{ - return - ch == '(' || ch == ')' || - ch == '<' || ch == '>' || - ch == '[' || ch == ']' || - ch == '{' || ch == '}' || - ch == '/' || - ch == '%'; -} - -static inline void fmt_putc(struct fmt *fmt, int c) -{ - if (fmt->sep && !isdelim(fmt->last) && !isdelim(c)) { - fmt->sep = 0; - fmt_putc(fmt, ' '); - } - fmt->sep = 0; - - if (fmt->buf && fmt->len < fmt->cap) - fmt->buf[fmt->len] = c; - - if (c == '\n') - fmt->col = 0; - else - fmt->col ++; - - fmt->len ++; - - fmt->last = c; -} - -static inline void fmt_indent(struct fmt *fmt) -{ - int i = fmt->indent; - while (i--) { - fmt_putc(fmt, ' '); - fmt_putc(fmt, ' '); - } -} - -static inline void fmt_puts(struct fmt *fmt, char *s) -{ - while (*s) - fmt_putc(fmt, *s++); -} - -static inline void fmt_sep(struct fmt *fmt) -{ - fmt->sep = 1; -} - -static void fmt_str(struct fmt *fmt, pdf_obj *obj) -{ - char *s = pdf_to_str_buf(obj); - int n = pdf_to_str_len(obj); - int i, c; - - fmt_putc(fmt, '('); - for (i = 0; i < n; i++) - { - c = (unsigned char)s[i]; - if (c == '\n') - fmt_puts(fmt, "\\n"); - else if (c == '\r') - fmt_puts(fmt, "\\r"); - else if (c == '\t') - fmt_puts(fmt, "\\t"); - else if (c == '\b') - fmt_puts(fmt, "\\b"); - else if (c == '\f') - fmt_puts(fmt, "\\f"); - else if (c == '(') - fmt_puts(fmt, "\\("); - else if (c == ')') - fmt_puts(fmt, "\\)"); - else if (c == '\\') - fmt_puts(fmt, "\\\\"); - else if (c < 32 || c >= 127) { - char buf[16]; - fmt_putc(fmt, '\\'); - sprintf(buf, "%03o", c); - fmt_puts(fmt, buf); - } - else - fmt_putc(fmt, c); - } - fmt_putc(fmt, ')'); -} - -static void fmt_hex(struct fmt *fmt, pdf_obj *obj) -{ - char *s = pdf_to_str_buf(obj); - int n = pdf_to_str_len(obj); - int i, b, c; - - fmt_putc(fmt, '<'); - for (i = 0; i < n; i++) { - b = (unsigned char) s[i]; - c = (b >> 4) & 0x0f; - fmt_putc(fmt, c < 0xA ? c + '0' : c + 'A' - 0xA); - c = (b) & 0x0f; - fmt_putc(fmt, c < 0xA ? c + '0' : c + 'A' - 0xA); - } - fmt_putc(fmt, '>'); -} - -static void fmt_name(struct fmt *fmt, pdf_obj *obj) -{ - unsigned char *s = (unsigned char *) pdf_to_name(obj); - int i, c; - - fmt_putc(fmt, '/'); - - for (i = 0; s[i]; i++) - { - if (isdelim(s[i]) || iswhite(s[i]) || - s[i] == '#' || s[i] < 32 || s[i] >= 127) - { - fmt_putc(fmt, '#'); - c = (s[i] >> 4) & 0xf; - fmt_putc(fmt, c < 0xA ? c + '0' : c + 'A' - 0xA); - c = s[i] & 0xf; - fmt_putc(fmt, c < 0xA ? c + '0' : c + 'A' - 0xA); - } - else - { - fmt_putc(fmt, s[i]); - } - } -} - -static void fmt_array(struct fmt *fmt, pdf_obj *obj) -{ - int i, n; - - n = pdf_array_len(obj); - if (fmt->tight) { - fmt_putc(fmt, '['); - for (i = 0; i < n; i++) { - fmt_obj(fmt, pdf_array_get(obj, i)); - fmt_sep(fmt); - } - fmt_putc(fmt, ']'); - } - else { - fmt_puts(fmt, "[ "); - for (i = 0; i < n; i++) { - if (fmt->col > 60) { - fmt_putc(fmt, '\n'); - fmt_indent(fmt); - } - fmt_obj(fmt, pdf_array_get(obj, i)); - fmt_putc(fmt, ' '); - } - fmt_putc(fmt, ']'); - fmt_sep(fmt); - } -} - -static void fmt_dict(struct fmt *fmt, pdf_obj *obj) -{ - int i, n; - pdf_obj *key, *val; - - n = pdf_dict_len(obj); - if (fmt->tight) { - fmt_puts(fmt, "<<"); - for (i = 0; i < n; i++) { - fmt_obj(fmt, pdf_dict_get_key(obj, i)); - fmt_sep(fmt); - fmt_obj(fmt, pdf_dict_get_val(obj, i)); - fmt_sep(fmt); - } - fmt_puts(fmt, ">>"); - } - else { - fmt_puts(fmt, "<<\n"); - fmt->indent ++; - for (i = 0; i < n; i++) { - key = pdf_dict_get_key(obj, i); - val = pdf_dict_get_val(obj, i); - fmt_indent(fmt); - fmt_obj(fmt, key); - fmt_putc(fmt, ' '); - if (!pdf_is_indirect(val) && pdf_is_array(val)) - fmt->indent ++; - fmt_obj(fmt, val); - fmt_putc(fmt, '\n'); - if (!pdf_is_indirect(val) && pdf_is_array(val)) - fmt->indent --; - } - fmt->indent --; - fmt_indent(fmt); - fmt_puts(fmt, ">>"); - } -} - -static void fmt_obj(struct fmt *fmt, pdf_obj *obj) -{ - char buf[256]; - - if (!obj) - fmt_puts(fmt, "<NULL>"); - else if (pdf_is_indirect(obj)) - { - sprintf(buf, "%d %d R", pdf_to_num(obj), pdf_to_gen(obj)); - fmt_puts(fmt, buf); - } - else if (pdf_is_null(obj)) - fmt_puts(fmt, "null"); - else if (pdf_is_bool(obj)) - fmt_puts(fmt, pdf_to_bool(obj) ? "true" : "false"); - else if (pdf_is_int(obj)) - { - sprintf(buf, "%d", pdf_to_int(obj)); - fmt_puts(fmt, buf); - } - else if (pdf_is_real(obj)) - { - sprintf(buf, "%1.9g", pdf_to_real(obj)); - if (strchr(buf, 'e')) /* bad news! */ - sprintf(buf, fabsf(pdf_to_real(obj)) > 1 ? "%1.1f" : "%1.8f", pdf_to_real(obj)); - fmt_puts(fmt, buf); - } - else if (pdf_is_string(obj)) - { - char *str = pdf_to_str_buf(obj); - int len = pdf_to_str_len(obj); - int added = 0; - int i, c; - for (i = 0; i < len; i++) { - c = (unsigned char)str[i]; - if (strchr("()\\\n\r\t\b\f", c)) - added ++; - else if (c < 32 || c >= 127) - added += 3; - } - if (added < len) - fmt_str(fmt, obj); - else - fmt_hex(fmt, obj); - } - else if (pdf_is_name(obj)) - fmt_name(fmt, obj); - else if (pdf_is_array(obj)) - fmt_array(fmt, obj); - else if (pdf_is_dict(obj)) - fmt_dict(fmt, obj); - else - fmt_puts(fmt, "<unknown object>"); -} - -static int -pdf_sprint_obj(char *s, int n, pdf_obj *obj, int tight) -{ - struct fmt fmt; - - fmt.indent = 0; - fmt.col = 0; - fmt.sep = 0; - fmt.last = 0; - - fmt.tight = tight; - fmt.buf = s; - fmt.cap = n; - fmt.len = 0; - fmt_obj(&fmt, obj); - - if (fmt.buf && fmt.len < fmt.cap) - fmt.buf[fmt.len] = '\0'; - - return fmt.len; -} - -int -pdf_fprint_obj(FILE *fp, pdf_obj *obj, int tight) -{ - char buf[1024]; - char *ptr; - int n; - - n = pdf_sprint_obj(NULL, 0, obj, tight); - if ((n + 1) < sizeof buf) - { - pdf_sprint_obj(buf, sizeof buf, obj, tight); - fputs(buf, fp); - fputc('\n', fp); - } - else - { - ptr = fz_malloc(obj->ctx, n + 1); - pdf_sprint_obj(ptr, n + 1, obj, tight); - fputs(ptr, fp); - fputc('\n', fp); - fz_free(obj->ctx, ptr); - } - return n; -} - -#ifndef NDEBUG -void -pdf_print_obj(pdf_obj *obj) -{ - pdf_fprint_obj(stdout, obj, 0); -} - -void -pdf_print_ref(pdf_obj *ref) -{ - pdf_print_obj(pdf_resolve_indirect(ref)); -} -#endif |