/src/xpdf-4.04/xpdf/Dict.cc
Line | Count | Source (jump to first uncovered line) |
1 | | //======================================================================== |
2 | | // |
3 | | // Dict.cc |
4 | | // |
5 | | // Copyright 1996-2003 Glyph & Cog, LLC |
6 | | // |
7 | | //======================================================================== |
8 | | |
9 | | #include <aconf.h> |
10 | | |
11 | | #ifdef USE_GCC_PRAGMAS |
12 | | #pragma implementation |
13 | | #endif |
14 | | |
15 | | #include <stddef.h> |
16 | | #include <string.h> |
17 | | #include "gmem.h" |
18 | | #include "gmempp.h" |
19 | | #include "Object.h" |
20 | | #include "XRef.h" |
21 | | #include "Dict.h" |
22 | | |
23 | | //------------------------------------------------------------------------ |
24 | | |
25 | | struct DictEntry { |
26 | | char *key; |
27 | | Object val; |
28 | | DictEntry *next; |
29 | | }; |
30 | | |
31 | | //------------------------------------------------------------------------ |
32 | | // Dict |
33 | | //------------------------------------------------------------------------ |
34 | | |
35 | 325k | Dict::Dict(XRef *xrefA) { |
36 | 325k | xref = xrefA; |
37 | 325k | size = 8; |
38 | 325k | length = 0; |
39 | 325k | entries = (DictEntry *)gmallocn(size, sizeof(DictEntry)); |
40 | 325k | hashTab = (DictEntry **)gmallocn(2 * size - 1, sizeof(DictEntry *)); |
41 | 325k | memset(hashTab, 0, (2 * size - 1) * sizeof(DictEntry *)); |
42 | 325k | ref = 1; |
43 | 325k | } |
44 | | |
45 | 293k | Dict::~Dict() { |
46 | 293k | int i; |
47 | | |
48 | 1.04M | for (i = 0; i < length; ++i) { |
49 | 748k | gfree(entries[i].key); |
50 | 748k | entries[i].val.free(); |
51 | 748k | } |
52 | 293k | gfree(entries); |
53 | 293k | gfree(hashTab); |
54 | 293k | } |
55 | | |
56 | 1.28M | void Dict::add(char *key, Object *val) { |
57 | 1.28M | DictEntry *e; |
58 | 1.28M | int h; |
59 | | |
60 | 1.28M | if ((e = find(key))) { |
61 | 406k | e->val.free(); |
62 | 406k | e->val = *val; |
63 | 406k | gfree(key); |
64 | 873k | } else { |
65 | 873k | if (length == size) { |
66 | 17.4k | expand(); |
67 | 17.4k | } |
68 | 873k | h = hash(key); |
69 | 873k | entries[length].key = key; |
70 | 873k | entries[length].val = *val; |
71 | 873k | entries[length].next = hashTab[h]; |
72 | 873k | hashTab[h] = &entries[length]; |
73 | 873k | ++length; |
74 | 873k | } |
75 | 1.28M | } |
76 | | |
77 | 17.4k | void Dict::expand() { |
78 | 17.4k | int h, i; |
79 | | |
80 | 17.4k | size *= 2; |
81 | 17.4k | entries = (DictEntry *)greallocn(entries, size, sizeof(DictEntry)); |
82 | 17.4k | hashTab = (DictEntry **)greallocn(hashTab, 2 * size - 1, |
83 | 17.4k | sizeof(DictEntry *)); |
84 | 17.4k | memset(hashTab, 0, (2 * size - 1) * sizeof(DictEntry *)); |
85 | 188k | for (i = 0; i < length; ++i) { |
86 | 171k | h = hash(entries[i].key); |
87 | 171k | entries[i].next = hashTab[h]; |
88 | 171k | hashTab[h] = &entries[i]; |
89 | 171k | } |
90 | 17.4k | } |
91 | | |
92 | 1.64M | inline DictEntry *Dict::find(const char *key) { |
93 | 1.64M | DictEntry *e; |
94 | 1.64M | int h; |
95 | | |
96 | 1.64M | h = hash(key); |
97 | 1.99M | for (e = hashTab[h]; e; e = e->next) { |
98 | 983k | if (!strcmp(key, e->key)) { |
99 | 626k | return e; |
100 | 626k | } |
101 | 983k | } |
102 | 1.01M | return NULL; |
103 | 1.64M | } |
104 | | |
105 | 2.68M | int Dict::hash(const char *key) { |
106 | 2.68M | const char *p; |
107 | 2.68M | unsigned int h; |
108 | | |
109 | 2.68M | h = 0; |
110 | 15.2M | for (p = key; *p; ++p) { |
111 | 12.6M | h = 17 * h + (int)(*p & 0xff); |
112 | 12.6M | } |
113 | 2.68M | return (int)(h % (2 * size - 1)); |
114 | 2.68M | } |
115 | | |
116 | 0 | GBool Dict::is(const char *type) { |
117 | 0 | DictEntry *e; |
118 | |
|
119 | 0 | return (e = find("Type")) && e->val.isName(type); |
120 | 0 | } |
121 | | |
122 | 336k | Object *Dict::lookup(const char *key, Object *obj, int recursion) { |
123 | 336k | DictEntry *e; |
124 | | |
125 | 336k | return (e = find(key)) ? e->val.fetch(xref, obj, recursion) |
126 | 336k | : obj->initNull(); |
127 | 336k | } |
128 | | |
129 | 22.5k | Object *Dict::lookupNF(const char *key, Object *obj) { |
130 | 22.5k | DictEntry *e; |
131 | | |
132 | 22.5k | return (e = find(key)) ? e->val.copy(obj) : obj->initNull(); |
133 | 22.5k | } |
134 | | |
135 | 461 | char *Dict::getKey(int i) { |
136 | 461 | return entries[i].key; |
137 | 461 | } |
138 | | |
139 | 335 | Object *Dict::getVal(int i, Object *obj) { |
140 | 335 | return entries[i].val.fetch(xref, obj); |
141 | 335 | } |
142 | | |
143 | 126 | Object *Dict::getValNF(int i, Object *obj) { |
144 | 126 | return entries[i].val.copy(obj); |
145 | 126 | } |