#include #include typedef struct pdf_item_s pdf_item; struct pdf_item_s { pdf_itemkind kind; fz_obj *key; void *val; pdf_item *next; }; struct refkey { pdf_itemkind kind; int oid; int gen; }; struct pdf_store_s { fz_hashtable *hash; /* hash for oid/gen keys */ pdf_item *root; /* linked list for everything else */ }; fz_error * pdf_newstore(pdf_store **storep) { fz_error *error; pdf_store *store; store = fz_malloc(sizeof(pdf_store)); if (!store) return fz_outofmem; error = fz_newhash(&store->hash, 4096, sizeof(struct refkey)); if (error) { fz_free(store); return error; } store->root = nil; *storep = store; return nil; } static void dropitem(pdf_itemkind kind, void *val) { switch (kind) { case PDF_KCOLORSPACE: fz_dropcolorspace(val); break; case PDF_KFUNCTION: pdf_dropfunction(val); break; case PDF_KXOBJECT: pdf_dropxobject(val); break; case PDF_KIMAGE: fz_dropimage(val); break; case PDF_KPATTERN: pdf_droppattern(val); break; case PDF_KSHADE: fz_dropshade(val); break; case PDF_KCMAP: pdf_dropcmap(val); break; case PDF_KFONT: fz_dropfont(val); break; } } void pdf_emptystore(pdf_store *store) { pdf_item *item; pdf_item *next; struct refkey *key; void *val; int i; for (i = 0; i < fz_hashlen(store->hash); i++) { key = fz_hashgetkey(store->hash, i); val = fz_hashgetval(store->hash, i); if (val) dropitem(key->kind, val); } fz_emptyhash(store->hash); for (item = store->root; item; item = next) { next = item->next; fz_dropobj(item->key); dropitem(item->kind, item->val); fz_free(item); } store->root = nil; } void pdf_dropstore(pdf_store *store) { pdf_emptystore(store); fz_drophash(store->hash); fz_free(store); } fz_error * pdf_storeitem(pdf_store *store, pdf_itemkind kind, fz_obj *key, void *val) { fz_error *error; switch (kind) { case PDF_KCOLORSPACE: fz_keepcolorspace(val); break; case PDF_KFUNCTION: pdf_keepfunction(val); break; case PDF_KXOBJECT: pdf_keepxobject(val); break; case PDF_KIMAGE: fz_keepimage(val); break; case PDF_KPATTERN: pdf_keeppattern(val); break; case PDF_KSHADE: fz_keepshade(val); break; case PDF_KCMAP: pdf_keepcmap(val); break; case PDF_KFONT: fz_keepfont(val); break; } if (fz_isindirect(key)) { struct refkey item; pdf_logrsrc("store item %d: %d %d R = %p\n", kind, fz_tonum(key), fz_togen(key), val); item.kind = kind; item.oid = fz_tonum(key); item.gen = fz_togen(key); error = fz_hashinsert(store->hash, &item, val); if (error) return error; } else { pdf_item *item; item = fz_malloc(sizeof(pdf_item)); if (!item) return fz_outofmem; pdf_logrsrc("store item %d: ... = %p\n", kind, val); item->kind = kind; item->key = fz_keepobj(key); item->val = val; item->next = store->root; store->root = item; } return nil; } void * pdf_finditem(pdf_store *store, pdf_itemkind kind, fz_obj *key) { pdf_item *item; struct refkey refkey; if (key == nil) return nil; if (fz_isindirect(key)) { refkey.kind = kind; refkey.oid = fz_tonum(key); refkey.gen = fz_togen(key); return fz_hashfind(store->hash, &refkey); } else { for (item = store->root; item; item = item->next) if (item->kind == kind && !fz_objcmp(item->key, key)) return item->val; } return nil; }