/src/ghostpdl/psi/iparam.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Copyright (C) 2001-2022 Artifex Software, Inc. |
2 | | All Rights Reserved. |
3 | | |
4 | | This software is provided AS-IS with no warranty, either express or |
5 | | implied. |
6 | | |
7 | | This software is distributed under license and may not be copied, |
8 | | modified or distributed except as expressly authorized under the terms |
9 | | of the license contained in the file LICENSE in this distribution. |
10 | | |
11 | | Refer to licensing information at http://www.artifex.com or contact |
12 | | Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato, |
13 | | CA 94945, U.S.A., +1(415)492-9861, for further information. |
14 | | */ |
15 | | |
16 | | |
17 | | /* Interpreter implementations of parameter dictionaries */ |
18 | | #include "memory_.h" |
19 | | #include "string_.h" |
20 | | #include "ghost.h" |
21 | | #include "ierrors.h" |
22 | | #include "oper.h" /* for check_type */ |
23 | | #include "opcheck.h" |
24 | | #include "ialloc.h" |
25 | | #include "idict.h" |
26 | | #include "imemory.h" /* for iutil.h */ |
27 | | #include "iname.h" |
28 | | #include "istack.h" |
29 | | #include "iparam.h" |
30 | | #include "iutil.h" /* for num_params */ |
31 | | #include "ivmspace.h" |
32 | | #include "store.h" |
33 | | #include "gsstruct.h" /* for st_bytes */ |
34 | | |
35 | | /* ================ Utilities ================ */ |
36 | | |
37 | | /* Convert a key to a ref. */ |
38 | | static int |
39 | | ref_param_key(const iparam_list * plist, gs_param_name pkey, ref * pkref) |
40 | 4.04M | { |
41 | 4.04M | if (plist->int_keys) { |
42 | 0 | long key; |
43 | |
|
44 | 0 | if (sscanf(pkey, "%ld", &key) != 1) |
45 | 0 | return_error(gs_error_rangecheck); |
46 | 0 | make_int(pkref, key); |
47 | 0 | return 0; |
48 | 0 | } else |
49 | 4.04M | return name_ref(plist->memory, (const byte *)pkey, strlen(pkey), pkref, 0); |
50 | 4.04M | } |
51 | | |
52 | | /* Fill in a gs_param_key_t from a name or int ref. */ |
53 | | static int |
54 | | ref_to_key(const ref * pref, gs_param_key_t * key, iparam_list *plist) |
55 | 0 | { |
56 | 0 | if (r_has_type(pref, t_name)) { |
57 | 0 | ref nref; |
58 | |
|
59 | 0 | name_string_ref(plist->memory, pref, &nref); |
60 | 0 | key->data = nref.value.const_bytes; |
61 | 0 | key->size = r_size(&nref); |
62 | 0 | key->persistent = false; /* names may be freed */ |
63 | 0 | } else if (r_has_type(pref, t_integer)) { |
64 | 0 | char istr[sizeof(long) * 8 / 3 + 2]; |
65 | 0 | int len; |
66 | 0 | byte *buf; |
67 | |
|
68 | 0 | gs_snprintf(istr, sizeof(istr), "%"PRIpsint, pref->value.intval); |
69 | 0 | len = strlen(istr); |
70 | | /* GC will take care of freeing this: */ |
71 | 0 | buf = gs_alloc_string(plist->memory, len, "ref_to_key"); |
72 | 0 | if (!buf) |
73 | 0 | return_error(gs_error_VMerror); |
74 | 0 | key->data = buf; |
75 | 0 | key->size = len; |
76 | 0 | key->persistent = true; |
77 | 0 | } else |
78 | 0 | return_error(gs_error_typecheck); |
79 | 0 | return 0; |
80 | 0 | } |
81 | | |
82 | | /* ================ Writing parameters to refs ================ */ |
83 | | |
84 | | /* Forward references */ |
85 | | static int array_new_indexed_plist_write(dict_param_list *plist, |
86 | | ref *parray, const ref *pwanted, |
87 | | gs_ref_memory_t *imem); |
88 | | |
89 | | /* ---------------- Generic writing procedures ---------------- */ |
90 | | |
91 | | static param_proc_begin_xmit_collection(ref_param_begin_write_collection); |
92 | | static param_proc_end_xmit_collection(ref_param_end_write_collection); |
93 | | static param_proc_xmit_typed(ref_param_write_typed); |
94 | | static param_proc_next_key(ref_param_get_next_key); |
95 | | static param_proc_requested(ref_param_requested); |
96 | | static const gs_param_list_procs ref_write_procs = |
97 | | { |
98 | | ref_param_write_typed, |
99 | | ref_param_begin_write_collection, |
100 | | ref_param_end_write_collection, |
101 | | ref_param_get_next_key, |
102 | | NULL, /* request */ |
103 | | ref_param_requested |
104 | | }; |
105 | | static int ref_array_param_requested(const iparam_list *, gs_param_name, |
106 | | ref *, uint, client_name_t); |
107 | | static int ref_param_write(iparam_list *, gs_param_name, const ref *); |
108 | | static int ref_param_write_string_value(ref *, const gs_param_string *, |
109 | | gs_ref_memory_t *); |
110 | | static int ref_param_write_name_value(const gs_memory_t *mem, ref *, const gs_param_string *); |
111 | | static int |
112 | | ref_param_make_int(ref *pe, const void *pvalue, uint i, gs_ref_memory_t *imem) |
113 | 4.09k | { |
114 | 4.09k | make_tav(pe, t_integer, imemory_new_mask(imem), intval, |
115 | 4.09k | ((const gs_param_int_array *)pvalue)->data[i]); |
116 | 4.09k | return 0; |
117 | 4.09k | } |
118 | | static int |
119 | | ref_param_make_float(ref *pe, const void *pvalue, uint i, gs_ref_memory_t *imem) |
120 | 30.3k | { |
121 | 30.3k | make_tav(pe, t_real, imemory_new_mask(imem), realval, |
122 | 30.3k | ((const gs_param_float_array *)pvalue)->data[i]); |
123 | 30.3k | return 0; |
124 | 30.3k | } |
125 | | static int |
126 | | ref_param_make_string(ref *pe, const void *pvalue, uint i, gs_ref_memory_t *imem) |
127 | 0 | { |
128 | 0 | return ref_param_write_string_value(pe, |
129 | 0 | &((const gs_param_string_array *)pvalue)->data[i], |
130 | 0 | imem); |
131 | 0 | } |
132 | | static int |
133 | | ref_param_make_name(ref * pe, const void *pvalue, uint i, gs_ref_memory_t *imem) |
134 | 0 | { |
135 | 0 | return ref_param_write_name_value((const gs_memory_t *)imem, pe, |
136 | 0 | &((const gs_param_string_array *)pvalue)->data[i]); |
137 | 0 | } |
138 | | static int |
139 | | ref_param_write_typed_array(gs_param_list * plist, gs_param_name pkey, |
140 | | void *pvalue, uint count, |
141 | | int (*make)(ref *, const void *, uint, |
142 | | gs_ref_memory_t *)) |
143 | 97.3k | { |
144 | 97.3k | iparam_list *const iplist = (iparam_list *) plist; |
145 | 97.3k | ref value; |
146 | 97.3k | uint i; |
147 | 97.3k | ref *pe; |
148 | 97.3k | int code; |
149 | | |
150 | 97.3k | if ((code = ref_array_param_requested(iplist, pkey, &value, count, |
151 | 97.3k | "ref_param_write_typed_array")) <= 0) |
152 | 80.0k | return code; |
153 | 51.6k | for (i = 0, pe = value.value.refs; i < count; ++i, ++pe) |
154 | 34.4k | if ((code = (*make) (pe, pvalue, i, iplist->ref_memory)) < 0) |
155 | 0 | return code; |
156 | 17.2k | return ref_param_write(iplist, pkey, &value); |
157 | 17.2k | } |
158 | | static int |
159 | | ref_param_begin_write_collection(gs_param_list * plist, gs_param_name pkey, |
160 | | gs_param_dict * pvalue, |
161 | | gs_param_collection_type_t coll_type) |
162 | 0 | { |
163 | 0 | iparam_list *const iplist = (iparam_list *) plist; |
164 | 0 | gs_ref_memory_t *imem = iplist->ref_memory; |
165 | 0 | dict_param_list *dlist = (dict_param_list *) |
166 | 0 | gs_alloc_bytes(plist->memory, size_of(dict_param_list), |
167 | 0 | "ref_param_begin_write_collection"); |
168 | 0 | int code; |
169 | |
|
170 | 0 | if (dlist == 0) |
171 | 0 | return_error(gs_error_VMerror); |
172 | 0 | if (coll_type != gs_param_collection_array) { |
173 | 0 | ref dref; |
174 | |
|
175 | 0 | code = dict_alloc(imem, pvalue->size, &dref); |
176 | 0 | if (code >= 0) { |
177 | 0 | code = dict_param_list_write(dlist, &dref, NULL, imem); |
178 | 0 | dlist->int_keys = coll_type == gs_param_collection_dict_int_keys; |
179 | 0 | } |
180 | 0 | } else { |
181 | 0 | ref aref; |
182 | |
|
183 | 0 | code = gs_alloc_ref_array(imem, &aref, a_all, pvalue->size, |
184 | 0 | "ref_param_begin_write_collection"); |
185 | 0 | if (code >= 0) |
186 | 0 | code = array_new_indexed_plist_write(dlist, &aref, NULL, imem); |
187 | 0 | } |
188 | 0 | if (code < 0) |
189 | 0 | gs_free_object(plist->memory, dlist, "ref_param_begin_write_collection"); |
190 | 0 | else |
191 | 0 | pvalue->list = (gs_param_list *) dlist; |
192 | 0 | return code; |
193 | 0 | } |
194 | | static int |
195 | | ref_param_end_write_collection(gs_param_list * plist, gs_param_name pkey, |
196 | | gs_param_dict * pvalue) |
197 | 0 | { |
198 | 0 | iparam_list *const iplist = (iparam_list *) plist; |
199 | 0 | int code = ref_param_write(iplist, pkey, |
200 | 0 | &((dict_param_list *) pvalue->list)->dict); |
201 | |
|
202 | 0 | gs_free_object(plist->memory, pvalue->list, "ref_param_end_write_collection"); |
203 | 0 | pvalue->list = 0; |
204 | 0 | return code; |
205 | 0 | } |
206 | | static int |
207 | | ref_param_write_typed(gs_param_list * plist, gs_param_name pkey, |
208 | | gs_param_typed_value * pvalue) |
209 | 2.34M | { |
210 | 2.34M | iparam_list *const iplist = (iparam_list *) plist; |
211 | 2.34M | ref value; |
212 | 2.34M | int code = 0; |
213 | | |
214 | 2.34M | switch (pvalue->type) { |
215 | 41.4k | case gs_param_type_null: |
216 | 41.4k | make_null(&value); |
217 | 41.4k | break; |
218 | 442k | case gs_param_type_bool: |
219 | 442k | make_bool(&value, pvalue->value.b); |
220 | 442k | break; |
221 | 796k | case gs_param_type_int: |
222 | 796k | make_int(&value, pvalue->value.i); |
223 | 796k | break; |
224 | 75.4k | case gs_param_type_long: |
225 | | /* FIXME: Rangecheck? */ |
226 | 75.4k | make_int(&value, pvalue->value.l); |
227 | 75.4k | break; |
228 | 61.3k | case gs_param_type_size_t: |
229 | | /* FIXME: Rangecheck? */ |
230 | 61.3k | make_int(&value, pvalue->value.z); |
231 | 61.3k | break; |
232 | 3.41k | case gs_param_type_i64: |
233 | | /* FIXME: Rangecheck? */ |
234 | 3.41k | make_int(&value, pvalue->value.i64); |
235 | 3.41k | break; |
236 | 234k | case gs_param_type_float: |
237 | 234k | make_real(&value, pvalue->value.f); |
238 | 234k | break; |
239 | 552k | case gs_param_type_string: |
240 | 552k | if (!ref_param_requested(plist, pkey)) |
241 | 467k | return 0; |
242 | 84.8k | code = ref_param_write_string_value(&value, &pvalue->value.s, |
243 | 84.8k | iplist->ref_memory); |
244 | 84.8k | break; |
245 | 41.4k | case gs_param_type_name: |
246 | 41.4k | if (!ref_param_requested(plist, pkey)) |
247 | 37.3k | return 0; |
248 | 4.09k | code = ref_param_write_name_value(iplist->memory, &value, &pvalue->value.n); |
249 | 4.09k | break; |
250 | 13.8k | case gs_param_type_int_array: |
251 | 13.8k | return ref_param_write_typed_array(plist, pkey, &pvalue->value.ia, |
252 | 13.8k | pvalue->value.ia.size, |
253 | 13.8k | ref_param_make_int); |
254 | 69.7k | case gs_param_type_float_array: |
255 | 69.7k | return ref_param_write_typed_array(plist, pkey, &pvalue->value.fa, |
256 | 69.7k | pvalue->value.fa.size, |
257 | 69.7k | ref_param_make_float); |
258 | 0 | case gs_param_type_string_array: |
259 | 0 | return ref_param_write_typed_array(plist, pkey, &pvalue->value.sa, |
260 | 0 | pvalue->value.sa.size, |
261 | 0 | ref_param_make_string); |
262 | 13.8k | case gs_param_type_name_array: |
263 | 13.8k | return ref_param_write_typed_array(plist, pkey, &pvalue->value.na, |
264 | 13.8k | pvalue->value.na.size, |
265 | 13.8k | ref_param_make_name); |
266 | 0 | case gs_param_type_dict: |
267 | 0 | case gs_param_type_dict_int_keys: |
268 | 0 | case gs_param_type_array: |
269 | 0 | return ref_param_begin_write_collection(plist, pkey, |
270 | 0 | &pvalue->value.d, |
271 | 0 | (gs_param_collection_type_t)(pvalue->type - gs_param_type_dict)); |
272 | 0 | default: |
273 | 0 | return_error(gs_error_typecheck); |
274 | 2.34M | } |
275 | 1.74M | if (code < 0) |
276 | 0 | return code; |
277 | 1.74M | return ref_param_write(iplist, pkey, &value); |
278 | 1.74M | } |
279 | | |
280 | | /* Check whether a given parameter was requested. */ |
281 | | static int |
282 | | ref_param_requested(const gs_param_list * plist, gs_param_name pkey) |
283 | 2.46M | { |
284 | 2.46M | const iparam_list *const ciplist = (const iparam_list *)plist; |
285 | 2.46M | ref kref; |
286 | 2.46M | ref *ignore_value; |
287 | | |
288 | 2.46M | if (!r_has_type(&ciplist->u.w.wanted, t_dictionary)) |
289 | 417k | return -1; |
290 | 2.04M | if (ref_param_key(ciplist, pkey, &kref) < 0) |
291 | 0 | return -1; /* catch it later */ |
292 | 2.04M | return (dict_find(&ciplist->u.w.wanted, &kref, &ignore_value) > 0); |
293 | 2.04M | } |
294 | | |
295 | | /* Check whether an array parameter is wanted, and allocate it if so. */ |
296 | | /* Return <0 on error, 0 if not wanted, 1 if wanted. */ |
297 | | static int |
298 | | ref_array_param_requested(const iparam_list *iplist, gs_param_name pkey, |
299 | | ref *pvalue, uint size, client_name_t cname) |
300 | 97.3k | { |
301 | 97.3k | int code; |
302 | | |
303 | 97.3k | if (!ref_param_requested((const gs_param_list *)iplist, pkey)) |
304 | 80.0k | return 0; |
305 | 17.2k | code = gs_alloc_ref_array(iplist->ref_memory, pvalue, a_all, size, cname); |
306 | 17.2k | return (code < 0 ? code : 1); |
307 | 97.3k | } |
308 | | |
309 | | /* ---------------- Internal routines ---------------- */ |
310 | | |
311 | | /* Prepare to write a string value. */ |
312 | | static int |
313 | | ref_param_write_string_value(ref * pref, const gs_param_string * pvalue, |
314 | | gs_ref_memory_t *imem) |
315 | 84.8k | { |
316 | 84.8k | const byte *pdata = pvalue->data; |
317 | 84.8k | uint n = pvalue->size; |
318 | | |
319 | 84.8k | if (pvalue->persistent) |
320 | 84.8k | make_const_string(pref, a_readonly | avm_foreign, n, pdata); |
321 | 50.0k | else { |
322 | 50.0k | byte *pstr = gs_alloc_string((gs_memory_t *)imem, n, |
323 | 50.0k | "ref_param_write_string"); |
324 | | |
325 | 50.0k | if (pstr == 0) |
326 | 0 | return_error(gs_error_VMerror); |
327 | 50.0k | memcpy(pstr, pdata, n); |
328 | 50.0k | make_string(pref, a_readonly | imemory_space(imem), n, pstr); |
329 | 50.0k | } |
330 | 84.8k | return 0; |
331 | 84.8k | } |
332 | | |
333 | | /* Prepare to write a name value. */ |
334 | | static int |
335 | | ref_param_write_name_value(const gs_memory_t *mem, ref * pref, const gs_param_string * pvalue) |
336 | 4.09k | { |
337 | 4.09k | return name_ref(mem, pvalue->data, pvalue->size, pref, |
338 | 4.09k | (pvalue->persistent ? 0 : 1)); |
339 | 4.09k | } |
340 | | |
341 | | /* Generic routine for writing a ref parameter. */ |
342 | | static int |
343 | | ref_param_write(iparam_list * plist, gs_param_name pkey, const ref * pvalue) |
344 | 1.76M | { |
345 | 1.76M | ref kref; |
346 | 1.76M | int code; |
347 | | |
348 | 1.76M | if (!ref_param_requested((gs_param_list *) plist, pkey)) |
349 | 1.37M | return 0; |
350 | 387k | code = ref_param_key(plist, pkey, &kref); |
351 | 387k | if (code < 0) |
352 | 0 | return code; |
353 | 387k | return (*plist->u.w.write) (plist, &kref, pvalue); |
354 | 387k | } |
355 | | |
356 | | /* ---------------- Implementations ---------------- */ |
357 | | |
358 | | /* Initialize for writing parameters. */ |
359 | | static void |
360 | | ref_param_write_init(iparam_list * plist, const ref * pwanted, |
361 | | gs_ref_memory_t *imem) |
362 | 34.7k | { |
363 | 34.7k | gs_param_list_init((gs_param_list *)plist, &ref_write_procs, |
364 | 34.7k | (gs_memory_t *)imem); |
365 | 34.7k | plist->ref_memory = imem; |
366 | 34.7k | if (pwanted == 0) |
367 | 34.7k | make_null(&plist->u.w.wanted); |
368 | 23.7k | else |
369 | 23.7k | plist->u.w.wanted = *pwanted; |
370 | 34.7k | plist->results = 0; |
371 | 34.7k | plist->int_keys = false; |
372 | 34.7k | } |
373 | | |
374 | | /* Implementation for getting parameters to a stack. */ |
375 | | static int |
376 | | stack_param_write(iparam_list * plist, const ref * pkey, const ref * pvalue) |
377 | 387k | { |
378 | 387k | stack_param_list *const splist = (stack_param_list *) plist; |
379 | 387k | ref_stack_t *pstack = splist->pstack; |
380 | 387k | s_ptr p = pstack->p; |
381 | | |
382 | 387k | if (pstack->top - p < 2) { |
383 | 0 | int code = ref_stack_push(pstack, 2); |
384 | |
|
385 | 0 | if (code < 0) |
386 | 0 | return code; |
387 | 0 | *ref_stack_index(pstack, 1) = *pkey; |
388 | 0 | p = pstack->p; |
389 | 387k | } else { |
390 | 387k | pstack->p = p += 2; |
391 | 387k | p[-1] = *pkey; |
392 | 387k | } |
393 | 387k | *p = *pvalue; |
394 | 387k | splist->count++; |
395 | 387k | return 0; |
396 | 387k | } |
397 | | |
398 | | /* Implementation for enumerating parameters on a stack */ |
399 | | static int /* ret 0 ok, 1 if EOF, or -ve err */ |
400 | | stack_param_enumerate(iparam_list * plist, gs_param_enumerator_t * penum, |
401 | | gs_param_key_t * key, ref_type * type) |
402 | 0 | { |
403 | 0 | int code; |
404 | 0 | stack_param_list *const splist = (stack_param_list *) plist; |
405 | 0 | int index = penum->intval; |
406 | 0 | ref *stack_element; |
407 | |
|
408 | 0 | do { |
409 | 0 | if (index >= splist->count*2) |
410 | 0 | return 1; |
411 | 0 | stack_element = |
412 | 0 | ref_stack_index(splist->pstack, index + 1 + splist->skip); |
413 | 0 | if (!stack_element) |
414 | 0 | return 1; |
415 | 0 | index += 2; |
416 | 0 | } while (!r_has_type(stack_element, t_name)); |
417 | 0 | *type = r_type(stack_element); |
418 | 0 | code = ref_to_key(stack_element, key, plist); |
419 | 0 | penum->intval = index; |
420 | 0 | return code; |
421 | 0 | } |
422 | | |
423 | | int |
424 | | stack_param_list_write(stack_param_list * plist, ref_stack_t * pstack, |
425 | | const ref * pwanted, gs_ref_memory_t *imem) |
426 | 34.7k | { |
427 | 34.7k | plist->u.w.write = stack_param_write; |
428 | 34.7k | ref_param_write_init((iparam_list *) plist, pwanted, imem); |
429 | 34.7k | plist->enumerate = stack_param_enumerate; |
430 | 34.7k | plist->pstack = pstack; |
431 | 34.7k | plist->skip = 0; |
432 | 34.7k | plist->count = 0; |
433 | 34.7k | return 0; |
434 | 34.7k | } |
435 | | |
436 | | /* Implementation for getting parameters to a dictionary. */ |
437 | | static int |
438 | | dict_param_write(iparam_list * plist, const ref * pkey, const ref * pvalue) |
439 | 0 | { |
440 | 0 | int code = |
441 | 0 | dict_put(&((dict_param_list *) plist)->dict, pkey, pvalue, NULL); |
442 | |
|
443 | 0 | return min(code, 0); |
444 | 0 | } |
445 | | |
446 | | /* Implementation for enumerating parameters in a dictionary */ |
447 | | static int /* ret 0 ok, 1 if EOF, or -ve err */ |
448 | | dict_param_enumerate(iparam_list * plist, gs_param_enumerator_t * penum, |
449 | | gs_param_key_t * key, ref_type * type) |
450 | 0 | { |
451 | 0 | ref elt[2]; |
452 | 0 | int code; |
453 | 0 | dict_param_list *const pdlist = (dict_param_list *) plist; |
454 | 0 | int index = |
455 | 0 | (penum->intval != 0 ? penum->intval : dict_first(&pdlist->dict)); |
456 | |
|
457 | 0 | index = dict_next(&pdlist->dict, index, elt); |
458 | 0 | if (index < 0) |
459 | 0 | return 1; |
460 | 0 | *type = r_type(&elt[0]); |
461 | 0 | code = ref_to_key(&elt[0], key, plist); |
462 | 0 | penum->intval = index; |
463 | 0 | return code; |
464 | 0 | } |
465 | | |
466 | | int |
467 | | dict_param_list_write(dict_param_list *plist, ref *pdict, const ref *pwanted, |
468 | | gs_ref_memory_t *imem) |
469 | 0 | { |
470 | 0 | check_dict_write(*pdict); |
471 | 0 | plist->u.w.write = dict_param_write; |
472 | 0 | plist->enumerate = dict_param_enumerate; |
473 | 0 | ref_param_write_init((iparam_list *) plist, pwanted, imem); |
474 | 0 | plist->dict = *pdict; |
475 | 0 | return 0; |
476 | 0 | } |
477 | | |
478 | | /* Implementation for getting parameters to an indexed array. */ |
479 | | /* Note that this is now internal, since it only handles "new" arrays. */ |
480 | | static int |
481 | | array_new_indexed_param_write(iparam_list * iplist, const ref * pkey, |
482 | | const ref * pvalue) |
483 | 0 | { |
484 | 0 | const ref *const arr = &((dict_param_list *)iplist)->dict; |
485 | 0 | ref *eltp; |
486 | |
|
487 | 0 | if (!r_has_type(pkey, t_integer)) |
488 | 0 | return_error(gs_error_typecheck); |
489 | 0 | check_int_ltu(*pkey, r_size(arr)); |
490 | 0 | store_check_dest(arr, pvalue); |
491 | 0 | eltp = arr->value.refs + pkey->value.intval; |
492 | | /* ref_assign_new(eltp, pvalue); */ |
493 | 0 | ref_assign(eltp, pvalue); |
494 | 0 | r_set_attrs(eltp, imemory_new_mask(iplist->ref_memory)); |
495 | 0 | return 0; |
496 | 0 | } |
497 | | static int |
498 | | array_new_indexed_plist_write(dict_param_list * plist, ref * parray, |
499 | | const ref * pwanted, gs_ref_memory_t *imem) |
500 | 0 | { |
501 | 0 | check_array(*parray); |
502 | 0 | check_write(*parray); |
503 | 0 | plist->u.w.write = array_new_indexed_param_write; |
504 | 0 | ref_param_write_init((iparam_list *) plist, pwanted, imem); |
505 | 0 | plist->dict = *parray; |
506 | 0 | plist->int_keys = true; |
507 | 0 | return 0; |
508 | 0 | } |
509 | | |
510 | | /* ================ Reading refs to parameters ================ */ |
511 | | |
512 | | /* ---------------- Generic reading procedures ---------------- */ |
513 | | |
514 | | static param_proc_begin_xmit_collection(ref_param_begin_read_collection); |
515 | | static param_proc_end_xmit_collection(ref_param_end_read_collection); |
516 | | static param_proc_xmit_typed(ref_param_read_typed); |
517 | | |
518 | | /*static param_proc_next_key(ref_param_get_next_key); already dec'ld above */ |
519 | | static param_proc_get_policy(ref_param_read_get_policy); |
520 | | static param_proc_signal_error(ref_param_read_signal_error); |
521 | | static param_proc_commit(ref_param_read_commit); |
522 | | static const gs_param_list_procs ref_read_procs = |
523 | | { |
524 | | ref_param_read_typed, |
525 | | ref_param_begin_read_collection, |
526 | | ref_param_end_read_collection, |
527 | | ref_param_get_next_key, |
528 | | NULL, /* request */ |
529 | | NULL, /* requested */ |
530 | | ref_param_read_get_policy, |
531 | | ref_param_read_signal_error, |
532 | | ref_param_read_commit, |
533 | | NULL |
534 | | }; |
535 | | static int ref_param_read(iparam_list *, gs_param_name, |
536 | | iparam_loc *, int); |
537 | | static int ref_param_read_string_value(gs_memory_t *mem, |
538 | | const iparam_loc *, |
539 | | gs_param_string *); |
540 | | static int ref_param_read_array(iparam_list *, gs_param_name, |
541 | | iparam_loc *); |
542 | | |
543 | | #define iparam_note_error(loc, code)\ |
544 | 0 | gs_note_error(*(loc).presult = code) |
545 | | #define iparam_check_type(loc, typ)\ |
546 | 0 | if ( !r_has_type((loc).pvalue, typ) )\ |
547 | 0 | return iparam_note_error(loc, gs_error_typecheck) |
548 | | #define iparam_check_read(loc)\ |
549 | 102k | if ( !r_has_attr((loc).pvalue, a_read) )\ |
550 | 102k | return iparam_note_error(loc, gs_error_invalidaccess) |
551 | | |
552 | | static int |
553 | | ref_param_read_int_array(gs_param_list * plist, gs_param_name pkey, |
554 | | gs_param_int_array * pvalue) |
555 | 1.22k | { |
556 | 1.22k | iparam_list *const iplist = (iparam_list *) plist; |
557 | 1.22k | iparam_loc loc; |
558 | 1.22k | int code = ref_param_read_array(iplist, pkey, &loc); |
559 | 1.22k | int *piv; |
560 | 1.22k | uint size; |
561 | 1.22k | long i; |
562 | | |
563 | 1.22k | if (code != 0) |
564 | 0 | return code; |
565 | 1.22k | size = r_size(loc.pvalue); |
566 | 1.22k | piv = (int *)gs_alloc_byte_array(plist->memory, size, sizeof(int), |
567 | 1.22k | "ref_param_read_int_array"); |
568 | | |
569 | 1.22k | if (piv == 0) |
570 | 0 | return_error(gs_error_VMerror); |
571 | 3.68k | for (i = 0; i < size; i++) { |
572 | 2.45k | ref elt; |
573 | | |
574 | 2.45k | array_get(plist->memory, loc.pvalue, i, &elt); |
575 | 2.45k | if (!r_has_type(&elt, t_integer)) { |
576 | 0 | code = gs_note_error(gs_error_typecheck); |
577 | 0 | break; |
578 | 0 | } |
579 | 2.45k | piv[i] = (int)elt.value.intval; |
580 | 2.45k | } |
581 | 1.22k | if (code < 0) { |
582 | 0 | gs_free_object(plist->memory, piv, "ref_param_read_int_array"); |
583 | 0 | return (*loc.presult = code); |
584 | 0 | } |
585 | 1.22k | pvalue->data = piv; |
586 | 1.22k | pvalue->size = size; |
587 | 1.22k | pvalue->persistent = true; |
588 | 1.22k | return 0; |
589 | 1.22k | } |
590 | | static int |
591 | | ref_param_read_float_array(gs_param_list * plist, gs_param_name pkey, |
592 | | gs_param_float_array * pvalue) |
593 | 16.6k | { |
594 | 16.6k | iparam_list *const iplist = (iparam_list *) plist; |
595 | 16.6k | iparam_loc loc; |
596 | 16.6k | ref aref, elt; |
597 | 16.6k | int code = ref_param_read_array(iplist, pkey, &loc); |
598 | 16.6k | float *pfv; |
599 | 16.6k | uint size; |
600 | 16.6k | long i; |
601 | | |
602 | 16.6k | if (code != 0) |
603 | 0 | return code; |
604 | 16.6k | size = r_size(loc.pvalue); |
605 | 16.6k | pfv = (float *)gs_alloc_byte_array(plist->memory, size, sizeof(float), |
606 | 16.6k | "ref_param_read_float_array"); |
607 | | |
608 | 16.6k | if (pfv == 0) |
609 | 0 | return_error(gs_error_VMerror); |
610 | 16.6k | aref = *loc.pvalue; |
611 | 16.6k | loc.pvalue = &elt; |
612 | 52.4k | for (i = 0; code >= 0 && i < size; i++) { |
613 | 35.7k | array_get(plist->memory, &aref, i, &elt); |
614 | 35.7k | code = float_param(&elt, pfv + i); |
615 | 35.7k | } |
616 | 16.6k | if (code < 0) { |
617 | 0 | gs_free_object(plist->memory, pfv, "ref_read_float_array_param"); |
618 | 0 | return (*loc.presult = code); |
619 | 0 | } |
620 | 16.6k | pvalue->data = pfv; |
621 | 16.6k | pvalue->size = size; |
622 | 16.6k | pvalue->persistent = true; |
623 | 16.6k | return 0; |
624 | 16.6k | } |
625 | | static int |
626 | | ref_param_read_string_array(gs_param_list * plist, gs_param_name pkey, |
627 | | gs_param_string_array * pvalue) |
628 | 0 | { |
629 | 0 | iparam_list *const iplist = (iparam_list *) plist; |
630 | 0 | iparam_loc loc; |
631 | 0 | ref aref; |
632 | 0 | int code = ref_param_read_array(iplist, pkey, &loc); |
633 | 0 | gs_param_string *psv; |
634 | 0 | uint size; |
635 | 0 | long i; |
636 | |
|
637 | 0 | if (code != 0) |
638 | 0 | return code; |
639 | 0 | size = r_size(loc.pvalue); |
640 | 0 | psv = (gs_param_string *) |
641 | 0 | gs_alloc_byte_array(plist->memory, size, sizeof(gs_param_string), |
642 | 0 | "ref_param_read_string_array"); |
643 | 0 | if (psv == 0) |
644 | 0 | return_error(gs_error_VMerror); |
645 | 0 | aref = *loc.pvalue; |
646 | 0 | if (r_has_type(&aref, t_array)) { |
647 | 0 | for (i = 0; code >= 0 && i < size; i++) { |
648 | 0 | loc.pvalue = aref.value.refs + i; |
649 | 0 | code = ref_param_read_string_value(plist->memory, &loc, psv + i); |
650 | 0 | } |
651 | 0 | } else { |
652 | 0 | ref elt; |
653 | |
|
654 | 0 | loc.pvalue = &elt; |
655 | 0 | for (i = 0; code >= 0 && i < size; i++) { |
656 | 0 | array_get(plist->memory, &aref, i, &elt); |
657 | 0 | code = ref_param_read_string_value(plist->memory, &loc, psv + i); |
658 | 0 | } |
659 | 0 | } |
660 | 0 | if (code < 0) { |
661 | 0 | gs_free_object(plist->memory, psv, "ref_param_read_string_array"); |
662 | 0 | return (*loc.presult = code); |
663 | 0 | } |
664 | 0 | pvalue->data = psv; |
665 | 0 | pvalue->size = size; |
666 | 0 | pvalue->persistent = true; |
667 | 0 | return 0; |
668 | 0 | } |
669 | | static int |
670 | | ref_param_begin_read_collection(gs_param_list * plist, gs_param_name pkey, |
671 | | gs_param_dict * pvalue, |
672 | | gs_param_collection_type_t coll_type) |
673 | 12.5k | { |
674 | 12.5k | iparam_list *const iplist = (iparam_list *) plist; |
675 | 12.5k | iparam_loc loc; |
676 | 12.5k | bool int_keys = coll_type != 0; |
677 | 12.5k | int code = ref_param_read(iplist, pkey, &loc, -1); |
678 | 12.5k | dict_param_list *dlist; |
679 | | |
680 | 12.5k | if (code != 0) |
681 | 12.5k | return code; |
682 | 0 | dlist = (dict_param_list *) |
683 | 0 | gs_alloc_bytes(plist->memory, size_of(dict_param_list), |
684 | 0 | "ref_param_begin_read_collection"); |
685 | 0 | if (dlist == 0) |
686 | 0 | return_error(gs_error_VMerror); |
687 | 0 | if (r_has_type(loc.pvalue, t_dictionary)) { |
688 | 0 | code = dict_param_list_read(dlist, loc.pvalue, NULL, false, |
689 | 0 | iplist->ref_memory); |
690 | 0 | dlist->int_keys = int_keys; |
691 | 0 | if (code >= 0) |
692 | 0 | pvalue->size = dict_length(loc.pvalue); |
693 | 0 | } else if (int_keys && r_is_array(loc.pvalue)) { |
694 | 0 | code = array_indexed_param_list_read(dlist, loc.pvalue, NULL, false, |
695 | 0 | iplist->ref_memory); |
696 | 0 | if (code >= 0) |
697 | 0 | pvalue->size = r_size(loc.pvalue); |
698 | 0 | } else |
699 | 0 | code = gs_note_error(gs_error_typecheck); |
700 | 0 | if (code < 0) { |
701 | 0 | gs_free_object(plist->memory, dlist, "ref_param_begin_write_collection"); |
702 | 0 | return iparam_note_error(loc, code); |
703 | 0 | } |
704 | 0 | pvalue->list = (gs_param_list *) dlist; |
705 | 0 | return 0; |
706 | 0 | } |
707 | | static int |
708 | | ref_param_end_read_collection(gs_param_list * plist, gs_param_name pkey, |
709 | | gs_param_dict * pvalue) |
710 | 0 | { |
711 | 0 | iparam_list_release((dict_param_list *) pvalue->list); |
712 | 0 | gs_free_object(plist->memory, pvalue->list, |
713 | 0 | "ref_param_end_read_collection"); |
714 | 0 | return 0; |
715 | 0 | } |
716 | | static int |
717 | | ref_param_read_typed(gs_param_list * plist, gs_param_name pkey, |
718 | | gs_param_typed_value * pvalue) |
719 | 1.57M | { |
720 | 1.57M | iparam_list *const iplist = (iparam_list *) plist; |
721 | 1.57M | iparam_loc loc; |
722 | 1.57M | ref elt; |
723 | 1.57M | int code = ref_param_read(iplist, pkey, &loc, -1); |
724 | | |
725 | 1.57M | if (code != 0) |
726 | 1.29M | return code; |
727 | 280k | switch (r_type(loc.pvalue)) { |
728 | 19.1k | case t_array: |
729 | 19.1k | case t_mixedarray: |
730 | 19.1k | case t_shortarray: |
731 | 19.1k | iparam_check_read(loc); |
732 | 19.1k | if (r_size(loc.pvalue) <= 0) { |
733 | | /* 0-length array; can't get type info */ |
734 | 1.22k | pvalue->type = gs_param_type_array; |
735 | 1.22k | pvalue->value.d.list = 0; |
736 | 1.22k | pvalue->value.d.size = 0; |
737 | 1.22k | return 0; |
738 | 1.22k | } |
739 | | /* |
740 | | * We have to guess at the array type. First we guess based |
741 | | * on the type of the first element of the array. If that |
742 | | * fails, we try again with more general types. |
743 | | */ |
744 | 17.8k | array_get(plist->memory, loc.pvalue, 0, &elt); |
745 | 17.8k | switch (r_type(&elt)) { |
746 | 1.22k | case t_integer: |
747 | 1.22k | pvalue->type = gs_param_type_int_array; |
748 | 1.22k | code = ref_param_read_int_array(plist, pkey, |
749 | 1.22k | &pvalue->value.ia); |
750 | 1.22k | if (code != gs_error_typecheck) |
751 | 1.22k | return code; |
752 | | /* This might be a float array. Fall through. */ |
753 | 0 | *loc.presult = 0; /* reset error */ |
754 | 16.6k | case t_real: |
755 | 16.6k | pvalue->type = gs_param_type_float_array; |
756 | 16.6k | return ref_param_read_float_array(plist, pkey, |
757 | 16.6k | &pvalue->value.fa); |
758 | 0 | case t_string: |
759 | 0 | pvalue->type = gs_param_type_string_array; |
760 | 0 | return ref_param_read_string_array(plist, pkey, |
761 | 0 | &pvalue->value.sa); |
762 | 0 | case t_name: |
763 | 0 | pvalue->type = gs_param_type_name_array; |
764 | 0 | return ref_param_read_string_array(plist, pkey, |
765 | 0 | &pvalue->value.na); |
766 | 0 | default: |
767 | 0 | break; |
768 | 17.8k | } |
769 | 0 | return gs_note_error(gs_error_typecheck); |
770 | 48.8k | case t_boolean: |
771 | 48.8k | pvalue->type = gs_param_type_bool; |
772 | 48.8k | pvalue->value.b = loc.pvalue->value.boolval; |
773 | 48.8k | return 0; |
774 | 0 | case t_dictionary: |
775 | 0 | code = ref_param_begin_read_collection(plist, pkey, |
776 | 0 | &pvalue->value.d, gs_param_collection_dict_any); |
777 | 0 | if (code < 0) |
778 | 0 | return code; |
779 | 0 | pvalue->type = gs_param_type_dict; |
780 | | |
781 | | /* fixup new dict's type & int_keys field if contents have int keys */ |
782 | 0 | { |
783 | 0 | gs_param_enumerator_t enumr; |
784 | 0 | gs_param_key_t key; |
785 | 0 | ref_type keytype; |
786 | 0 | dict_param_list *dlist = (dict_param_list *) pvalue->value.d.list; |
787 | |
|
788 | 0 | param_init_enumerator(&enumr); |
789 | 0 | if (!(*(dlist->enumerate)) |
790 | 0 | ((iparam_list *) dlist, &enumr, &key, &keytype) |
791 | 0 | && keytype == t_integer) { |
792 | 0 | dlist->int_keys = 1; |
793 | 0 | pvalue->type = gs_param_type_dict_int_keys; |
794 | 0 | } |
795 | 0 | } |
796 | 0 | return 0; |
797 | 118k | case t_integer: |
798 | 118k | pvalue->type = gs_param_type_i64; |
799 | 118k | pvalue->value.i64 = loc.pvalue->value.intval; |
800 | 118k | return 0; |
801 | 2.45k | case t_name: |
802 | 2.45k | pvalue->type = gs_param_type_name; |
803 | 2.45k | return ref_param_read_string_value(plist->memory, &loc, &pvalue->value.n); |
804 | 4.91k | case t_null: |
805 | 4.91k | pvalue->type = gs_param_type_null; |
806 | 4.91k | return 0; |
807 | 20.8k | case t_real: |
808 | 20.8k | pvalue->value.f = loc.pvalue->value.realval; |
809 | 20.8k | pvalue->type = gs_param_type_float; |
810 | 20.8k | return 0; |
811 | 65.4k | case t_string: |
812 | 65.4k | case t_astruct: |
813 | 65.4k | pvalue->type = gs_param_type_string; |
814 | 65.4k | return ref_param_read_string_value(plist->memory, &loc, &pvalue->value.s); |
815 | 0 | default: |
816 | 0 | break; |
817 | 280k | } |
818 | 0 | return gs_note_error(gs_error_typecheck); |
819 | 280k | } |
820 | | |
821 | | static int |
822 | | ref_param_read_get_policy(gs_param_list * plist, gs_param_name pkey) |
823 | 0 | { |
824 | 0 | iparam_list *const iplist = (iparam_list *) plist; |
825 | 0 | ref *pvalue; |
826 | |
|
827 | 0 | if (!(r_has_type(&iplist->u.r.policies, t_dictionary) && |
828 | 0 | dict_find_string(&iplist->u.r.policies, pkey, &pvalue) > 0 && |
829 | 0 | r_has_type(pvalue, t_integer)) |
830 | 0 | ) |
831 | 0 | return gs_param_policy_ignore; |
832 | 0 | return (int)pvalue->value.intval; |
833 | 0 | } |
834 | | static int |
835 | | ref_param_read_signal_error(gs_param_list * plist, gs_param_name pkey, int code) |
836 | 0 | { |
837 | 0 | iparam_list *const iplist = (iparam_list *) plist; |
838 | 0 | iparam_loc loc = {0}; |
839 | |
|
840 | 0 | ref_param_read(iplist, pkey, &loc, -1); |
841 | 0 | if (loc.presult) |
842 | 0 | *loc.presult = code; |
843 | 0 | switch (ref_param_read_get_policy(plist, pkey)) { |
844 | 0 | case gs_param_policy_ignore: |
845 | 0 | return 0; |
846 | 0 | case gs_param_policy_consult_user: |
847 | 0 | return_error(gs_error_configurationerror); |
848 | 0 | default: |
849 | 0 | return code; |
850 | 0 | } |
851 | 0 | } |
852 | | static int |
853 | | ref_param_read_commit(gs_param_list * plist) |
854 | 6.28k | { |
855 | 6.28k | iparam_list *const iplist = (iparam_list *) plist; |
856 | 6.28k | int i; |
857 | 6.28k | int ecode = 0; |
858 | | |
859 | 6.28k | if (!iplist->u.r.require_all) |
860 | 0 | return 0; |
861 | | /* Check to make sure that all parameters were actually read. */ |
862 | 213k | for (i = 0; i < iplist->count; ++i) |
863 | 207k | if (iplist->results[i] == 0) |
864 | 6.28k | iplist->results[i] = ecode = gs_note_error(gs_error_undefined); |
865 | 6.28k | return ecode; |
866 | 6.28k | } |
867 | | static int |
868 | | ref_param_get_next_key(gs_param_list * plist, gs_param_enumerator_t * penum, |
869 | | gs_param_key_t * key) |
870 | 0 | { |
871 | 0 | ref_type keytype; /* result not needed here */ |
872 | 0 | iparam_list *const pilist = (iparam_list *) plist; |
873 | |
|
874 | 0 | return (*pilist->enumerate) (pilist, penum, key, &keytype); |
875 | 0 | } |
876 | | |
877 | | /* ---------------- Internal routines ---------------- */ |
878 | | |
879 | | /* Read a string value. */ |
880 | | static int |
881 | | ref_param_read_string_value(gs_memory_t *mem, const iparam_loc * ploc, gs_param_string * pvalue) |
882 | 67.8k | { |
883 | 67.8k | const ref *pref = ploc->pvalue; |
884 | | |
885 | 67.8k | switch (r_type(pref)) { |
886 | 2.45k | case t_name: { |
887 | 2.45k | ref nref; |
888 | | |
889 | 2.45k | name_string_ref(mem, pref, &nref); |
890 | 2.45k | pvalue->data = nref.value.const_bytes; |
891 | 2.45k | pvalue->size = r_size(&nref); |
892 | 2.45k | pvalue->persistent = true; |
893 | 2.45k | } |
894 | 2.45k | break; |
895 | 65.4k | case t_string: |
896 | 65.4k | iparam_check_read(*ploc); |
897 | 65.4k | pvalue->data = pref->value.const_bytes; |
898 | 65.4k | pvalue->size = r_size(pref); |
899 | 65.4k | pvalue->persistent = false; |
900 | 65.4k | break; |
901 | 0 | case t_astruct: |
902 | | /* Note: technically, instead of the "mem" argument, we |
903 | | should be using the plists's ref_memory. However, in a |
904 | | simple call to .putdeviceparams, they are identical. */ |
905 | 0 | iparam_check_read(*ploc); |
906 | 0 | if (gs_object_type(mem, pref->value.pstruct) != &st_bytes) |
907 | 0 | return iparam_note_error(*ploc, gs_error_typecheck); |
908 | 0 | pvalue->data = r_ptr(pref, byte); |
909 | 0 | pvalue->size = gs_object_size(mem, pref->value.pstruct); |
910 | 0 | pvalue->persistent = false; |
911 | 0 | break; |
912 | 0 | default: |
913 | 0 | return iparam_note_error(*ploc, gs_error_typecheck); |
914 | 67.8k | } |
915 | 67.8k | return 0; |
916 | 67.8k | } |
917 | | |
918 | | /* Read an array (or packed array) parameter. */ |
919 | | static int |
920 | | ref_param_read_array(iparam_list * plist, gs_param_name pkey, iparam_loc * ploc) |
921 | 17.8k | { |
922 | 17.8k | int code = ref_param_read(plist, pkey, ploc, -1); |
923 | | |
924 | 17.8k | if (code != 0) |
925 | 0 | return code; |
926 | 17.8k | if (!r_is_array(ploc->pvalue)) |
927 | 0 | return iparam_note_error(*ploc, gs_error_typecheck); |
928 | 17.8k | iparam_check_read(*ploc); |
929 | 17.8k | return 0; |
930 | 17.8k | } |
931 | | |
932 | | /* Generic routine for reading a ref parameter. */ |
933 | | static int |
934 | | ref_param_read(iparam_list * plist, gs_param_name pkey, iparam_loc * ploc, |
935 | | int type) |
936 | 1.60M | { |
937 | 1.60M | iparam_list *const iplist = (iparam_list *) plist; |
938 | 1.60M | ref kref; |
939 | 1.60M | int code = ref_param_key(plist, pkey, &kref); |
940 | | |
941 | 1.60M | if (code < 0) |
942 | 0 | return code; |
943 | 1.60M | code = (*plist->u.r.read) (iplist, &kref, ploc); |
944 | 1.60M | if (code != 0) |
945 | 1.30M | return code; |
946 | 297k | if (type >= 0) |
947 | 0 | iparam_check_type(*ploc, type); |
948 | 297k | return 0; |
949 | 297k | } |
950 | | |
951 | | /* ---------------- Implementations ---------------- */ |
952 | | |
953 | | /* Implementation for putting parameters from an empty collection. */ |
954 | | static int |
955 | | empty_param_read(iparam_list * plist, const ref * pkey, iparam_loc * ploc) |
956 | 0 | { |
957 | 0 | return 1; |
958 | 0 | } |
959 | | |
960 | | /* Initialize for reading parameters. */ |
961 | | static int |
962 | | ref_param_read_init(iparam_list * plist, uint count, const ref * ppolicies, |
963 | | bool require_all, gs_ref_memory_t *imem) |
964 | 24.7k | { |
965 | 24.7k | gs_param_list_init((gs_param_list *)plist, &ref_read_procs, |
966 | 24.7k | (gs_memory_t *)imem); |
967 | 24.7k | plist->ref_memory = imem; |
968 | 24.7k | if (ppolicies == 0) |
969 | 24.7k | make_null(&plist->u.r.policies); |
970 | 6.28k | else |
971 | 6.28k | plist->u.r.policies = *ppolicies; |
972 | 24.7k | plist->u.r.require_all = require_all; |
973 | 24.7k | plist->count = count; |
974 | 24.7k | plist->results = (int *) |
975 | 24.7k | gs_alloc_byte_array(plist->memory, count, sizeof(int), |
976 | 24.7k | "ref_param_read_init"); |
977 | | |
978 | 24.7k | if (plist->results == 0) |
979 | 0 | return_error(gs_error_VMerror); |
980 | 24.7k | memset(plist->results, 0, count * sizeof(int)); |
981 | | |
982 | 24.7k | plist->int_keys = false; |
983 | 24.7k | return 0; |
984 | 24.7k | } |
985 | | |
986 | | /* Implementation for putting parameters from an indexed array. */ |
987 | | static int |
988 | | array_indexed_param_read(iparam_list * plist, const ref * pkey, iparam_loc * ploc) |
989 | 0 | { |
990 | 0 | ref *const arr = &((dict_param_list *) plist)->dict; |
991 | |
|
992 | 0 | check_type(*pkey, t_integer); |
993 | 0 | if (pkey->value.intval < 0 || pkey->value.intval >= r_size(arr)) |
994 | 0 | return 1; |
995 | 0 | ploc->pvalue = arr->value.refs + pkey->value.intval; |
996 | 0 | ploc->presult = &plist->results[pkey->value.intval]; |
997 | 0 | *ploc->presult = 1; |
998 | 0 | return 0; |
999 | 0 | } |
1000 | | int |
1001 | | array_indexed_param_list_read(dict_param_list * plist, const ref * parray, |
1002 | | const ref * ppolicies, bool require_all, |
1003 | | gs_ref_memory_t *ref_memory) |
1004 | 0 | { |
1005 | 0 | iparam_list *const iplist = (iparam_list *) plist; |
1006 | 0 | int code; |
1007 | |
|
1008 | 0 | check_read_type(*parray, t_array); |
1009 | 0 | plist->u.r.read = array_indexed_param_read; |
1010 | 0 | plist->dict = *parray; |
1011 | 0 | code = ref_param_read_init(iplist, r_size(parray), ppolicies, |
1012 | 0 | require_all, ref_memory); |
1013 | 0 | plist->int_keys = true; |
1014 | 0 | return code; |
1015 | 0 | } |
1016 | | |
1017 | | /* Implementation for putting parameters from an array. */ |
1018 | | static int |
1019 | | array_param_read(iparam_list * plist, const ref * pkey, iparam_loc * ploc) |
1020 | 0 | { |
1021 | 0 | ref *bot = ((array_param_list *) plist)->bot; |
1022 | 0 | ref *ptr = bot; |
1023 | 0 | ref *top = ((array_param_list *) plist)->top; |
1024 | |
|
1025 | 0 | for (; ptr < top; ptr += 2) { |
1026 | 0 | if (r_has_type(ptr, t_name) && name_eq(ptr, pkey)) { |
1027 | 0 | ploc->pvalue = ptr + 1; |
1028 | 0 | ploc->presult = &plist->results[ptr - bot]; |
1029 | 0 | *ploc->presult = 1; |
1030 | 0 | return 0; |
1031 | 0 | } |
1032 | 0 | } |
1033 | 0 | return 1; |
1034 | 0 | } |
1035 | | |
1036 | | /* Implementation for enumerating parameters in an array */ |
1037 | | static int /* ret 0 ok, 1 if EOF, or -ve err */ |
1038 | | array_param_enumerate(iparam_list * plist, gs_param_enumerator_t * penum, |
1039 | | gs_param_key_t * key, ref_type * type) |
1040 | 0 | { |
1041 | 0 | int index = penum->intval; |
1042 | 0 | ref *bot = ((array_param_list *) plist)->bot; |
1043 | 0 | ref *ptr = bot + index; |
1044 | 0 | ref *top = ((array_param_list *) plist)->top; |
1045 | |
|
1046 | 0 | for (; ptr < top; ptr += 2) { |
1047 | 0 | index += 2; |
1048 | |
|
1049 | 0 | if (r_has_type(ptr, t_name)) { |
1050 | 0 | int code = ref_to_key(ptr, key, plist); |
1051 | |
|
1052 | 0 | *type = r_type(ptr); |
1053 | 0 | penum->intval = index; |
1054 | 0 | return code; |
1055 | 0 | } |
1056 | 0 | } |
1057 | 0 | return 1; |
1058 | 0 | } |
1059 | | |
1060 | | int |
1061 | | array_param_list_read(array_param_list * plist, ref * bot, uint count, |
1062 | | const ref * ppolicies, bool require_all, |
1063 | | gs_ref_memory_t *imem) |
1064 | 0 | { |
1065 | 0 | iparam_list *const iplist = (iparam_list *) plist; |
1066 | |
|
1067 | 0 | if (count & 1) |
1068 | 0 | return_error(gs_error_rangecheck); |
1069 | 0 | plist->u.r.read = array_param_read; |
1070 | 0 | plist->enumerate = array_param_enumerate; |
1071 | 0 | plist->bot = bot; |
1072 | 0 | plist->top = bot + count; |
1073 | 0 | return ref_param_read_init(iplist, count, ppolicies, require_all, imem); |
1074 | 0 | } |
1075 | | |
1076 | | /* Implementation for putting parameters from a stack. */ |
1077 | | static int |
1078 | | stack_param_read(iparam_list * plist, const ref * pkey, iparam_loc * ploc) |
1079 | 1.14M | { |
1080 | 1.14M | stack_param_list *const splist = (stack_param_list *) plist; |
1081 | 1.14M | ref_stack_t *pstack = splist->pstack; |
1082 | | |
1083 | | /* This implementation is slow, but it probably doesn't matter. */ |
1084 | 1.14M | uint index = splist->skip + 1; |
1085 | 1.14M | uint count = splist->count; |
1086 | | |
1087 | 23.4M | for (; count; count--, index += 2) { |
1088 | 22.5M | const ref *p = ref_stack_index(pstack, index); |
1089 | | |
1090 | 22.5M | if (r_has_type(p, t_name) && name_eq(p, pkey)) { |
1091 | 237k | ploc->pvalue = ref_stack_index(pstack, index - 1); |
1092 | 237k | ploc->presult = &plist->results[count - 1]; |
1093 | 237k | *ploc->presult = 1; |
1094 | 237k | return 0; |
1095 | 237k | } |
1096 | 22.5M | } |
1097 | 904k | return 1; |
1098 | 1.14M | } |
1099 | | int |
1100 | | stack_param_list_read(stack_param_list * plist, ref_stack_t * pstack, |
1101 | | uint skip, const ref * ppolicies, bool require_all, |
1102 | | gs_ref_memory_t *imem) |
1103 | 6.28k | { |
1104 | 6.28k | iparam_list *const iplist = (iparam_list *) plist; |
1105 | 6.28k | uint count = ref_stack_counttomark(pstack); |
1106 | | |
1107 | 6.28k | if (count == 0) |
1108 | 0 | return_error(gs_error_unmatchedmark); |
1109 | 6.28k | count -= skip + 1; |
1110 | 6.28k | if (count & 1) |
1111 | 0 | return_error(gs_error_rangecheck); |
1112 | 6.28k | plist->u.r.read = stack_param_read; |
1113 | 6.28k | plist->enumerate = stack_param_enumerate; |
1114 | 6.28k | plist->pstack = pstack; |
1115 | 6.28k | plist->skip = skip; |
1116 | 6.28k | return ref_param_read_init(iplist, count >> 1, ppolicies, require_all, imem); |
1117 | 6.28k | } |
1118 | | |
1119 | | /* Implementation for putting parameters from a dictionary. */ |
1120 | | static int |
1121 | | dict_param_read(iparam_list * plist, const ref * pkey, iparam_loc * ploc) |
1122 | 461k | { |
1123 | 461k | ref const *spdict = &((dict_param_list *) plist)->dict; |
1124 | 461k | int code = dict_find(spdict, pkey, &ploc->pvalue); |
1125 | | |
1126 | 461k | if (code != 1) |
1127 | 400k | return 1; |
1128 | 60.6k | ploc->presult = |
1129 | 60.6k | &plist->results[dict_value_index(spdict, ploc->pvalue)]; |
1130 | 60.6k | *ploc->presult = 1; |
1131 | 60.6k | return 0; |
1132 | 461k | } |
1133 | | int |
1134 | | dict_param_list_read(dict_param_list * plist, const ref * pdict, |
1135 | | const ref * ppolicies, bool require_all, |
1136 | | gs_ref_memory_t *imem) |
1137 | 18.4k | { |
1138 | 18.4k | iparam_list *const iplist = (iparam_list *) plist; |
1139 | 18.4k | uint count; |
1140 | | |
1141 | 18.4k | if (pdict == 0) { |
1142 | 0 | plist->u.r.read = empty_param_read; |
1143 | 0 | count = 0; |
1144 | 18.4k | } else { |
1145 | 18.4k | check_dict_read(*pdict); |
1146 | 18.4k | plist->u.r.read = dict_param_read; |
1147 | 18.4k | plist->dict = *pdict; |
1148 | 18.4k | count = dict_max_index(pdict) + 1; |
1149 | 18.4k | } |
1150 | 18.4k | plist->enumerate = dict_param_enumerate; |
1151 | 18.4k | return ref_param_read_init(iplist, count, ppolicies, require_all, imem); |
1152 | 18.4k | } |