diff options
author | Calvin Morrison <calvin@pobox.com> | 2023-04-05 14:13:39 -0400 |
---|---|---|
committer | Calvin Morrison <calvin@pobox.com> | 2023-04-05 14:13:39 -0400 |
commit | 835e373b3eeaabcd0621ed6798ab500f37982fae (patch) | |
tree | dfa16b0e2e1b4956b38f693220eac4e607802133 /xpdf/Dict.cc |
Diffstat (limited to 'xpdf/Dict.cc')
-rw-r--r-- | xpdf/Dict.cc | 145 |
1 files changed, 145 insertions, 0 deletions
diff --git a/xpdf/Dict.cc b/xpdf/Dict.cc new file mode 100644 index 0000000..c8c2973 --- /dev/null +++ b/xpdf/Dict.cc @@ -0,0 +1,145 @@ +//======================================================================== +// +// Dict.cc +// +// Copyright 1996-2003 Glyph & Cog, LLC +// +//======================================================================== + +#include <aconf.h> + +#ifdef USE_GCC_PRAGMAS +#pragma implementation +#endif + +#include <stddef.h> +#include <string.h> +#include "gmem.h" +#include "gmempp.h" +#include "Object.h" +#include "XRef.h" +#include "Dict.h" + +//------------------------------------------------------------------------ + +struct DictEntry { + char *key; + Object val; + DictEntry *next; +}; + +//------------------------------------------------------------------------ +// Dict +//------------------------------------------------------------------------ + +Dict::Dict(XRef *xrefA) { + xref = xrefA; + size = 8; + length = 0; + entries = (DictEntry *)gmallocn(size, sizeof(DictEntry)); + hashTab = (DictEntry **)gmallocn(2 * size - 1, sizeof(DictEntry *)); + memset(hashTab, 0, (2 * size - 1) * sizeof(DictEntry *)); + ref = 1; +} + +Dict::~Dict() { + int i; + + for (i = 0; i < length; ++i) { + gfree(entries[i].key); + entries[i].val.free(); + } + gfree(entries); + gfree(hashTab); +} + +void Dict::add(char *key, Object *val) { + DictEntry *e; + int h; + + if ((e = find(key))) { + e->val.free(); + e->val = *val; + gfree(key); + } else { + if (length == size) { + expand(); + } + h = hash(key); + entries[length].key = key; + entries[length].val = *val; + entries[length].next = hashTab[h]; + hashTab[h] = &entries[length]; + ++length; + } +} + +void Dict::expand() { + int h, i; + + size *= 2; + entries = (DictEntry *)greallocn(entries, size, sizeof(DictEntry)); + hashTab = (DictEntry **)greallocn(hashTab, 2 * size - 1, + sizeof(DictEntry *)); + memset(hashTab, 0, (2 * size - 1) * sizeof(DictEntry *)); + for (i = 0; i < length; ++i) { + h = hash(entries[i].key); + entries[i].next = hashTab[h]; + hashTab[h] = &entries[i]; + } +} + +inline DictEntry *Dict::find(const char *key) { + DictEntry *e; + int h; + + h = hash(key); + for (e = hashTab[h]; e; e = e->next) { + if (!strcmp(key, e->key)) { + return e; + } + } + return NULL; +} + +int Dict::hash(const char *key) { + const char *p; + unsigned int h; + + h = 0; + for (p = key; *p; ++p) { + h = 17 * h + (int)(*p & 0xff); + } + return (int)(h % (2 * size - 1)); +} + +GBool Dict::is(const char *type) { + DictEntry *e; + + return (e = find("Type")) && e->val.isName(type); +} + +Object *Dict::lookup(const char *key, Object *obj, int recursion) { + DictEntry *e; + + return (e = find(key)) ? e->val.fetch(xref, obj, recursion) + : obj->initNull(); +} + +Object *Dict::lookupNF(const char *key, Object *obj) { + DictEntry *e; + + return (e = find(key)) ? e->val.copy(obj) : obj->initNull(); +} + +char *Dict::getKey(int i) { + return entries[i].key; +} + +Object *Dict::getVal(int i, Object *obj) { + return entries[i].val.fetch(xref, obj); +} + +Object *Dict::getValNF(int i, Object *obj) { + return entries[i].val.copy(obj); +} |