Delete all Trailing spaces in code.
[reactos.git] / rosapps / smartpdf / fitz / stream / obj_dict.c
1 #include "fitz-base.h"
2 #include "fitz-stream.h"
3
4 /* keep either names or strings in the dict. don't mix & match. */
5
6 static int keyvalcmp(const void *ap, const void *bp)
7 {
8 const fz_keyval *a = ap;
9 const fz_keyval *b = bp;
10 if (fz_isname(a->k))
11 return strcmp(fz_toname(a->k), fz_toname(b->k));
12 if (fz_isstring(a->k))
13 return strcmp(fz_tostrbuf(a->k), fz_tostrbuf(b->k));
14 return -1;
15 }
16
17 static inline int keystrcmp(fz_obj *key, char *s)
18 {
19 if (fz_isname(key))
20 return strcmp(fz_toname(key), s);
21 if (fz_isstring(key))
22 return strcmp(fz_tostrbuf(key), s);
23 return -1;
24 }
25
26 fz_error *
27 fz_newdict(fz_obj **op, int initialcap)
28 {
29 fz_obj *obj;
30 int i;
31
32 obj = *op = fz_malloc(sizeof (fz_obj));
33 if (!obj) return fz_outofmem;
34
35 obj->refs = 1;
36 obj->kind = FZ_DICT;
37
38 obj->u.d.sorted = 1;
39 obj->u.d.len = 0;
40 obj->u.d.cap = initialcap > 0 ? initialcap : 10;
41
42 obj->u.d.items = fz_malloc(sizeof(fz_keyval) * obj->u.d.cap);
43 if (!obj->u.d.items) { fz_free(obj); return fz_outofmem; }
44
45 for (i = 0; i < obj->u.d.cap; i++) {
46 obj->u.d.items[i].k = nil;
47 obj->u.d.items[i].v = nil;
48 }
49
50 return nil;
51 }
52
53 fz_error *
54 fz_copydict(fz_obj **op, fz_obj *obj)
55 {
56 fz_error *error;
57 fz_obj *new;
58 int i;
59
60 if (!fz_isdict(obj))
61 return fz_throw("typecheck in copydict");
62
63 error = fz_newdict(&new, obj->u.d.cap);
64 if (error) return error;
65 *op = new;
66
67 for (i = 0; i < fz_dictlen(obj); i++) {
68 error = fz_dictput(new, fz_dictgetkey(obj, i), fz_dictgetval(obj, i));
69 if (error) { fz_dropobj(new); return error; }
70 }
71
72 return nil;
73 }
74
75 fz_error *
76 fz_deepcopydict(fz_obj **op, fz_obj *obj)
77 {
78 fz_error *error;
79 fz_obj *new;
80 fz_obj *val;
81 int i;
82
83 if (!fz_isdict(obj))
84 return fz_throw("typecheck in deepcopydict");
85
86 error = fz_newdict(&new, obj->u.d.cap);
87 if (error) return error;
88 *op = new;
89
90 for (i = 0; i < fz_dictlen(obj); i++)
91 {
92 val = fz_dictgetval(obj, i);
93
94 if (fz_isarray(val)) {
95 error = fz_deepcopyarray(&val, val);
96 if (error) { fz_dropobj(new); return error; }
97 error = fz_dictput(new, fz_dictgetkey(obj, i), val);
98 if (error) { fz_dropobj(val); fz_dropobj(new); return error; }
99 fz_dropobj(val);
100 }
101
102 else if (fz_isdict(val)) {
103 error = fz_deepcopydict(&val, val);
104 if (error) { fz_dropobj(new); return error; }
105 error = fz_dictput(new, fz_dictgetkey(obj, i), val);
106 if (error) { fz_dropobj(val); fz_dropobj(new); return error; }
107 fz_dropobj(val);
108 }
109
110 else {
111 error = fz_dictput(new, fz_dictgetkey(obj, i), val);
112 if (error) { fz_dropobj(new); return error; }
113 }
114 }
115
116 return nil;
117 }
118
119 static fz_error *
120 growdict(fz_obj *obj)
121 {
122 fz_keyval *newitems;
123 int newcap;
124 int i;
125
126 newcap = obj->u.d.cap * 2;
127
128 newitems = fz_realloc(obj->u.d.items, sizeof(fz_keyval) * newcap);
129 if (!newitems) return fz_outofmem;
130
131 obj->u.d.items = newitems;
132 for (i = obj->u.d.cap; i < newcap; i++) {
133 obj->u.d.items[i].k = nil;
134 obj->u.d.items[i].v = nil;
135 }
136 obj->u.d.cap = newcap;
137
138 return nil;
139 }
140
141 int
142 fz_dictlen(fz_obj *obj)
143 {
144 if (!fz_isdict(obj))
145 return 0;
146 return obj->u.d.len;
147 }
148
149 fz_obj *
150 fz_dictgetkey(fz_obj *obj, int i)
151 {
152 if (!fz_isdict(obj))
153 return nil;
154
155 if (i < 0 || i >= obj->u.d.len)
156 return nil;
157
158 return obj->u.d.items[i].k;
159 }
160
161 fz_obj *
162 fz_dictgetval(fz_obj *obj, int i)
163 {
164 if (!fz_isdict(obj))
165 return nil;
166
167 if (i < 0 || i >= obj->u.d.len)
168 return nil;
169
170 return obj->u.d.items[i].v;
171 }
172
173 static inline int dictfinds(fz_obj *obj, char *key)
174 {
175 if (obj->u.d.sorted)
176 {
177 int l = 0;
178 int r = obj->u.d.len - 1;
179 while (l <= r)
180 {
181 int m = (l + r) >> 1;
182 int c = -keystrcmp(obj->u.d.items[m].k, key);
183 if (c < 0)
184 r = m - 1;
185 else if (c > 0)
186 l = m + 1;
187 else
188 return m;
189 }
190 }
191
192 else
193 {
194 int i;
195 for (i = 0; i < obj->u.d.len; i++)
196 if (keystrcmp(obj->u.d.items[i].k, key) == 0)
197 return i;
198 }
199
200 return -1;
201 }
202
203 fz_obj *
204 fz_dictgets(fz_obj *obj, char *key)
205 {
206 int i;
207
208 if (!fz_isdict(obj))
209 return nil;
210
211 i = dictfinds(obj, key);
212 if (i >= 0)
213 return obj->u.d.items[i].v;
214
215 return nil;
216 }
217
218 fz_obj *
219 fz_dictget(fz_obj *obj, fz_obj *key)
220 {
221 if (fz_isname(key))
222 return fz_dictgets(obj, fz_toname(key));
223 if (fz_isstring(key))
224 return fz_dictgets(obj, fz_tostrbuf(key));
225 return nil;
226 }
227
228 fz_obj *
229 fz_dictgetsa(fz_obj *obj, char *key, char *abbrev)
230 {
231 fz_obj *v;
232 v = fz_dictgets(obj, key);
233 if (v)
234 return v;
235 return fz_dictgets(obj, abbrev);
236 }
237
238 fz_error *
239 fz_dictput(fz_obj *obj, fz_obj *key, fz_obj *val)
240 {
241 fz_error *error;
242 char *s;
243 int i;
244
245 if (!fz_isdict(obj))
246 return fz_throw("typecheck in dictput");
247
248 if (fz_isname(key))
249 s = fz_toname(key);
250 else if (fz_isstring(key))
251 s = fz_tostrbuf(key);
252 else
253 return fz_throw("typecheck in dictput");
254
255 i = dictfinds(obj, s);
256 if (i >= 0)
257 {
258 fz_dropobj(obj->u.d.items[i].v);
259 obj->u.d.items[i].v = fz_keepobj(val);
260 return nil;
261 }
262
263 if (obj->u.d.len + 1 > obj->u.d.cap)
264 {
265 error = growdict(obj);
266 if (error)
267 return error;
268 }
269
270 /* borked! */
271 if (obj->u.d.len)
272 if (keystrcmp(obj->u.d.items[obj->u.d.len - 1].k, s) > 0)
273 obj->u.d.sorted = 0;
274
275 obj->u.d.items[obj->u.d.len].k = fz_keepobj(key);
276 obj->u.d.items[obj->u.d.len].v = fz_keepobj(val);
277 obj->u.d.len ++;
278
279 return nil;
280 }
281
282 fz_error *
283 fz_dictputs(fz_obj *obj, char *key, fz_obj *val)
284 {
285 fz_error *error;
286 fz_obj *keyobj;
287 error = fz_newname(&keyobj, key);
288 if (error) return error;
289 error = fz_dictput(obj, keyobj, val);
290 fz_dropobj(keyobj);
291 return error;
292 }
293
294 fz_error *
295 fz_dictdels(fz_obj *obj, char *key)
296 {
297 int i;
298
299 if (!fz_isdict(obj))
300 return fz_throw("typecheck in dictdel");
301
302 i = dictfinds(obj, key);
303 if (i >= 0)
304 {
305 fz_dropobj(obj->u.d.items[i].k);
306 fz_dropobj(obj->u.d.items[i].v);
307 obj->u.d.sorted = 0;
308 obj->u.d.items[i] = obj->u.d.items[obj->u.d.len-1];
309 obj->u.d.len --;
310 }
311
312 return nil;
313 }
314
315 fz_error *
316 fz_dictdel(fz_obj *obj, fz_obj *key)
317 {
318 if (fz_isname(key))
319 return fz_dictdels(obj, fz_toname(key));
320 else if (fz_isstring(key))
321 return fz_dictdels(obj, fz_tostrbuf(key));
322 else
323 return fz_throw("typecheck in dictdel");
324 }
325
326 void
327 fz_dropdict(fz_obj *obj)
328 {
329 int i;
330
331 if (!fz_isdict(obj))
332 return;
333
334 for (i = 0; i < obj->u.d.len; i++) {
335 if (obj->u.d.items[i].k)
336 fz_dropobj(obj->u.d.items[i].k);
337 if (obj->u.d.items[i].v)
338 fz_dropobj(obj->u.d.items[i].v);
339 }
340
341 fz_free(obj->u.d.items);
342 fz_free(obj);
343 }
344
345 void
346 fz_sortdict(fz_obj *obj)
347 {
348 if (!fz_isdict(obj))
349 return;
350 if (!obj->u.d.sorted)
351 {
352 qsort(obj->u.d.items, obj->u.d.len, sizeof(fz_keyval), keyvalcmp);
353 obj->u.d.sorted = 1;
354 }
355 }
356