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); item = fz_hashfind(store->hash, &refkey); if (item) { item->age = 0; return item->val; } } else { for (item = store->root; item; item = item->next) if (item->kind == kind && !fz_objcmp(item->key, key)) { item->age = 0; return item->val; } } return nil; }
int fz_array_contains(fz_obj *arr, fz_obj *obj) { int i; for (i = 0; i < fz_array_len(arr); i++) if (!fz_objcmp(fz_array_get(arr, i), obj)) return 1; return 0; }
static void removeduplicateobjs(void) { int num, other; for (num = 1; num < xref->len; num++) { /* Only compare an object to objects preceding it */ for (other = 1; other < num; other++) { fz_obj *a, *b; if (num == other || !uselist[num] || !uselist[other]) continue; /* * Comparing stream objects data contents would take too long. * * pdf_is_stream calls pdf_cache_object and ensures * that the xref table has the objects loaded. */ fz_try(ctx) { if (pdf_is_stream(xref, num, 0) || pdf_is_stream(xref, other, 0)) continue; } fz_catch(ctx) { /* Assume different */ } a = xref->table[num].obj; b = xref->table[other].obj; a = fz_resolve_indirect(a); b = fz_resolve_indirect(b); if (fz_objcmp(a, b)) continue; /* Keep the lowest numbered object */ renumbermap[num] = MIN(num, other); renumbermap[other] = MIN(num, other); uselist[MAX(num, other)] = 0; /* One duplicate was found, do not look for another */ break; } } }
void pdf_removeitem(pdf_store *store, pdf_itemkind kind, fz_obj *key) { pdf_item *item, *prev; struct refkey refkey; if (key == nil) return; if (fz_isindirect(key)) { refkey.kind = kind; refkey.oid = fz_tonum(key); refkey.gen = fz_togen(key); item = fz_hashfind(store->hash, &refkey); if (!item) return; fz_hashremove(store->hash, &refkey); pdf_logrsrc("remove item %s (%d %d R) ptr=%p\n", kindstr(kind), fz_tonum(key), fz_togen(key), item->val); dropitem(kind, item->val); fz_dropobj(item->key); fz_free(item); } else { prev = nil; for (item = store->root; item; item = item->next) { if (item->kind == kind && !fz_objcmp(item->key, key)) { if (!prev) store->root = item->next; else prev->next = item->next; dropitem(kind, item->val); fz_dropobj(item->key); fz_free(item); break; } prev = item; } } }
int fz_objcmp(fz_obj *a, fz_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 FZ_NULL: return 0; case FZ_BOOL: return a->u.b - b->u.b; case FZ_INT: return a->u.i - b->u.i; case FZ_REAL: if (a->u.f < b->u.f) return -1; if (a->u.f > b->u.f) return 1; return 0; case FZ_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 FZ_NAME: return strcmp(a->u.n, b->u.n); case FZ_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 FZ_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 (fz_objcmp(a->u.a.items[i], b->u.a.items[i])) return 1; return 0; case FZ_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 (fz_objcmp(a->u.d.items[i].k, b->u.d.items[i].k)) return 1; if (fz_objcmp(a->u.d.items[i].v, b->u.d.items[i].v)) return 1; } return 0; } return 1; }