/src/ghostpdl/psi/iparam.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Copyright (C) 2001-2025 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., 39 Mesa Street, Suite 108A, San Francisco, |
13 | | CA 94129, USA, 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 | 1.08G | { |
41 | 1.08G | 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 | 1.08G | return name_ref(plist->memory, (const byte *)pkey, strlen(pkey), pkref, 0); |
50 | 1.08G | } |
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 | 3.20M | { |
56 | 3.20M | if (r_has_type(pref, t_name)) { |
57 | 3.20M | ref nref; |
58 | | |
59 | 3.20M | name_string_ref(plist->memory, pref, &nref); |
60 | 3.20M | key->data = nref.value.const_bytes; |
61 | 3.20M | key->size = r_size(&nref); |
62 | 3.20M | key->persistent = false; /* names may be freed */ |
63 | 3.20M | } 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 | 3.20M | return 0; |
80 | 3.20M | } |
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 | 31.4M | { |
114 | 31.4M | make_tav(pe, t_integer, imemory_new_mask(imem), intval, |
115 | 31.4M | ((const gs_param_int_array *)pvalue)->data[i]); |
116 | 31.4M | return 0; |
117 | 31.4M | } |
118 | | static int |
119 | | ref_param_make_float(ref *pe, const void *pvalue, uint i, gs_ref_memory_t *imem) |
120 | 14.0M | { |
121 | 14.0M | make_tav(pe, t_real, imemory_new_mask(imem), realval, |
122 | 14.0M | ((const gs_param_float_array *)pvalue)->data[i]); |
123 | 14.0M | return 0; |
124 | 14.0M | } |
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 | 1.68M | { |
135 | 1.68M | return ref_param_write_name_value((const gs_memory_t *)imem, pe, |
136 | 1.68M | &((const gs_param_string_array *)pvalue)->data[i]); |
137 | 1.68M | } |
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 | 47.2M | { |
144 | 47.2M | iparam_list *const iplist = (iparam_list *) plist; |
145 | 47.2M | ref value; |
146 | 47.2M | uint i; |
147 | 47.2M | ref *pe; |
148 | 47.2M | int code; |
149 | | |
150 | 47.2M | if ((code = ref_array_param_requested(iplist, pkey, &value, count, |
151 | 47.2M | "ref_param_write_typed_array")) <= 0) |
152 | 30.7M | return code; |
153 | 63.7M | for (i = 0, pe = value.value.refs; i < count; ++i, ++pe) |
154 | 47.1M | if ((code = (*make) (pe, pvalue, i, iplist->ref_memory)) < 0) |
155 | 0 | return code; |
156 | 16.5M | return ref_param_write(iplist, pkey, &value); |
157 | 16.5M | } |
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 | 4.80M | { |
163 | 4.80M | iparam_list *const iplist = (iparam_list *) plist; |
164 | 4.80M | gs_ref_memory_t *imem = iplist->ref_memory; |
165 | 4.80M | dict_param_list *dlist = (dict_param_list *) |
166 | 4.80M | gs_alloc_bytes(plist->memory, size_of(dict_param_list), |
167 | 4.80M | "ref_param_begin_write_collection"); |
168 | 4.80M | int code; |
169 | | |
170 | 4.80M | if (dlist == 0) |
171 | 0 | return_error(gs_error_VMerror); |
172 | 4.80M | if (coll_type != gs_param_collection_array) { |
173 | 4.80M | ref dref; |
174 | | |
175 | 4.80M | code = dict_alloc(imem, pvalue->size, &dref); |
176 | 4.80M | if (code >= 0) { |
177 | 4.80M | code = dict_param_list_write(dlist, &dref, NULL, imem); |
178 | 4.80M | dlist->int_keys = coll_type == gs_param_collection_dict_int_keys; |
179 | 4.80M | } |
180 | 4.80M | } 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 | 4.80M | if (code < 0) |
189 | 0 | gs_free_object(plist->memory, dlist, "ref_param_begin_write_collection"); |
190 | 4.80M | else |
191 | 4.80M | pvalue->list = (gs_param_list *) dlist; |
192 | 4.80M | return code; |
193 | 4.80M | } |
194 | | static int |
195 | | ref_param_end_write_collection(gs_param_list * plist, gs_param_name pkey, |
196 | | gs_param_dict * pvalue) |
197 | 4.80M | { |
198 | 4.80M | iparam_list *const iplist = (iparam_list *) plist; |
199 | 4.80M | int code = ref_param_write(iplist, pkey, |
200 | 4.80M | &((dict_param_list *) pvalue->list)->dict); |
201 | | |
202 | 4.80M | gs_free_object(plist->memory, pvalue->list, "ref_param_end_write_collection"); |
203 | 4.80M | pvalue->list = 0; |
204 | 4.80M | return code; |
205 | 4.80M | } |
206 | | static int |
207 | | ref_param_write_typed(gs_param_list * plist, gs_param_name pkey, |
208 | | gs_param_typed_value * pvalue) |
209 | 621M | { |
210 | 621M | iparam_list *const iplist = (iparam_list *) plist; |
211 | 621M | ref value; |
212 | 621M | int code = 0; |
213 | | |
214 | 621M | switch (pvalue->type) { |
215 | 12.1M | case gs_param_type_null: |
216 | 12.1M | make_null(&value); |
217 | 12.1M | break; |
218 | 182M | case gs_param_type_bool: |
219 | 182M | make_bool(&value, pvalue->value.b); |
220 | 182M | break; |
221 | 170M | case gs_param_type_int: |
222 | 170M | make_int(&value, pvalue->value.i); |
223 | 170M | break; |
224 | 20.9M | case gs_param_type_long: |
225 | | /* FIXME: Rangecheck? */ |
226 | 20.9M | make_int(&value, pvalue->value.l); |
227 | 20.9M | break; |
228 | 18.6M | case gs_param_type_size_t: |
229 | | /* FIXME: Rangecheck? */ |
230 | 18.6M | make_int(&value, pvalue->value.z); |
231 | 18.6M | break; |
232 | 6.15M | case gs_param_type_i64: |
233 | | /* FIXME: Rangecheck? */ |
234 | 6.15M | make_int(&value, pvalue->value.i64); |
235 | 6.15M | break; |
236 | 36.4M | case gs_param_type_float: |
237 | 36.4M | make_real(&value, pvalue->value.f); |
238 | 36.4M | break; |
239 | 102M | case gs_param_type_string: |
240 | 102M | if (!ref_param_requested(plist, pkey)) |
241 | 81.5M | return 0; |
242 | 20.5M | code = ref_param_write_string_value(&value, &pvalue->value.s, |
243 | 20.5M | iplist->ref_memory); |
244 | 20.5M | break; |
245 | 25.2M | case gs_param_type_name: |
246 | 25.2M | if (!ref_param_requested(plist, pkey)) |
247 | 17.2M | return 0; |
248 | 7.98M | code = ref_param_write_name_value(iplist->memory, &value, &pvalue->value.n); |
249 | 7.98M | break; |
250 | 11.1M | case gs_param_type_int_array: |
251 | 11.1M | return ref_param_write_typed_array(plist, pkey, &pvalue->value.ia, |
252 | 11.1M | pvalue->value.ia.size, |
253 | 11.1M | ref_param_make_int); |
254 | 22.5M | case gs_param_type_float_array: |
255 | 22.5M | return ref_param_write_typed_array(plist, pkey, &pvalue->value.fa, |
256 | 22.5M | pvalue->value.fa.size, |
257 | 22.5M | ref_param_make_float); |
258 | 961k | case gs_param_type_string_array: |
259 | 961k | return ref_param_write_typed_array(plist, pkey, &pvalue->value.sa, |
260 | 961k | pvalue->value.sa.size, |
261 | 961k | ref_param_make_string); |
262 | 12.6M | case gs_param_type_name_array: |
263 | 12.6M | return ref_param_write_typed_array(plist, pkey, &pvalue->value.na, |
264 | 12.6M | pvalue->value.na.size, |
265 | 12.6M | 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 | 621M | } |
275 | 475M | if (code < 0) |
276 | 0 | return code; |
277 | 475M | return ref_param_write(iplist, pkey, &value); |
278 | 475M | } |
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 | 678M | { |
284 | 678M | const iparam_list *const ciplist = (const iparam_list *)plist; |
285 | 678M | ref kref; |
286 | 678M | ref *ignore_value; |
287 | | |
288 | 678M | if (!r_has_type(&ciplist->u.w.wanted, t_dictionary)) |
289 | 140M | return -1; |
290 | 538M | if (ref_param_key(ciplist, pkey, &kref) < 0) |
291 | 0 | return -1; /* catch it later */ |
292 | 538M | return (dict_find(&ciplist->u.w.wanted, &kref, &ignore_value) > 0); |
293 | 538M | } |
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 | 47.2M | { |
301 | 47.2M | int code; |
302 | | |
303 | 47.2M | if (!ref_param_requested((const gs_param_list *)iplist, pkey)) |
304 | 30.7M | return 0; |
305 | 16.5M | code = gs_alloc_ref_array(iplist->ref_memory, pvalue, a_all, size, cname); |
306 | 16.5M | return (code < 0 ? code : 1); |
307 | 47.2M | } |
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 | 20.5M | { |
316 | 20.5M | const byte *pdata = pvalue->data; |
317 | 20.5M | uint n = pvalue->size; |
318 | | |
319 | 20.5M | if (pvalue->persistent) |
320 | 20.5M | make_const_string(pref, a_readonly | avm_foreign, n, pdata); |
321 | 10.3M | else { |
322 | 10.3M | byte *pstr = gs_alloc_string((gs_memory_t *)imem, n, |
323 | 10.3M | "ref_param_write_string"); |
324 | | |
325 | 10.3M | if (pstr == 0) |
326 | 0 | return_error(gs_error_VMerror); |
327 | 10.3M | if (n > 0) |
328 | 6.38M | memcpy(pstr, pdata, n); |
329 | 10.3M | make_string(pref, a_readonly | imemory_space(imem), n, pstr); |
330 | 10.3M | } |
331 | 20.5M | return 0; |
332 | 20.5M | } |
333 | | |
334 | | /* Prepare to write a name value. */ |
335 | | static int |
336 | | ref_param_write_name_value(const gs_memory_t *mem, ref * pref, const gs_param_string * pvalue) |
337 | 9.66M | { |
338 | 9.66M | return name_ref(mem, pvalue->data, pvalue->size, pref, |
339 | 9.66M | (pvalue->persistent ? 0 : 1)); |
340 | 9.66M | } |
341 | | |
342 | | /* Generic routine for writing a ref parameter. */ |
343 | | static int |
344 | | ref_param_write(iparam_list * plist, gs_param_name pkey, const ref * pvalue) |
345 | 496M | { |
346 | 496M | ref kref; |
347 | 496M | int code; |
348 | | |
349 | 496M | if (!ref_param_requested((gs_param_list *) plist, pkey)) |
350 | 338M | return 0; |
351 | 158M | code = ref_param_key(plist, pkey, &kref); |
352 | 158M | if (code < 0) |
353 | 0 | return code; |
354 | 158M | return (*plist->u.w.write) (plist, &kref, pvalue); |
355 | 158M | } |
356 | | |
357 | | /* ---------------- Implementations ---------------- */ |
358 | | |
359 | | /* Initialize for writing parameters. */ |
360 | | static void |
361 | | ref_param_write_init(iparam_list * plist, const ref * pwanted, |
362 | | gs_ref_memory_t *imem) |
363 | 17.7M | { |
364 | 17.7M | gs_param_list_init((gs_param_list *)plist, &ref_write_procs, |
365 | 17.7M | (gs_memory_t *)imem); |
366 | 17.7M | plist->ref_memory = imem; |
367 | 17.7M | if (pwanted == 0) |
368 | 17.7M | make_null(&plist->u.w.wanted); |
369 | 10.4M | else |
370 | 10.4M | plist->u.w.wanted = *pwanted; |
371 | 17.7M | plist->results = 0; |
372 | 17.7M | plist->int_keys = false; |
373 | 17.7M | } |
374 | | |
375 | | /* Implementation for getting parameters to a stack. */ |
376 | | static int |
377 | | stack_param_write(iparam_list * plist, const ref * pkey, const ref * pvalue) |
378 | 142M | { |
379 | 142M | stack_param_list *const splist = (stack_param_list *) plist; |
380 | 142M | ref_stack_t *pstack = splist->pstack; |
381 | 142M | s_ptr p = pstack->p; |
382 | | |
383 | 142M | if (pstack->top - p < 2) { |
384 | 426 | int code = ref_stack_push(pstack, 2); |
385 | 426 | ref *o; |
386 | | |
387 | 426 | if (code < 0) |
388 | 0 | return code; |
389 | 426 | o = ref_stack_index(pstack, 1); |
390 | 426 | if (o == NULL) |
391 | 0 | return_error(gs_error_stackunderflow); |
392 | 426 | else |
393 | 426 | *o = *pkey; |
394 | 426 | p = pstack->p; |
395 | 142M | } else { |
396 | 142M | pstack->p = p += 2; |
397 | 142M | p[-1] = *pkey; |
398 | 142M | } |
399 | 142M | *p = *pvalue; |
400 | 142M | splist->count++; |
401 | 142M | return 0; |
402 | 142M | } |
403 | | |
404 | | /* Implementation for enumerating parameters on a stack */ |
405 | | static int /* ret 0 ok, 1 if EOF, or -ve err */ |
406 | | stack_param_enumerate(iparam_list * plist, gs_param_enumerator_t * penum, |
407 | | gs_param_key_t * key, ref_type * type) |
408 | 0 | { |
409 | 0 | int code; |
410 | 0 | stack_param_list *const splist = (stack_param_list *) plist; |
411 | 0 | int index = penum->intval; |
412 | 0 | ref *stack_element; |
413 | |
|
414 | 0 | do { |
415 | 0 | if (index >= splist->count*2) |
416 | 0 | return 1; |
417 | 0 | stack_element = |
418 | 0 | ref_stack_index(splist->pstack, index + 1 + splist->skip); |
419 | 0 | if (!stack_element) |
420 | 0 | return 1; |
421 | 0 | index += 2; |
422 | 0 | } while (!r_has_type(stack_element, t_name)); |
423 | 0 | *type = r_type(stack_element); |
424 | 0 | code = ref_to_key(stack_element, key, plist); |
425 | 0 | penum->intval = index; |
426 | 0 | return code; |
427 | 0 | } |
428 | | |
429 | | int |
430 | | stack_param_list_write(stack_param_list * plist, ref_stack_t * pstack, |
431 | | const ref * pwanted, gs_ref_memory_t *imem) |
432 | 12.8M | { |
433 | 12.8M | plist->u.w.write = stack_param_write; |
434 | 12.8M | ref_param_write_init((iparam_list *) plist, pwanted, imem); |
435 | 12.8M | plist->enumerate = stack_param_enumerate; |
436 | 12.8M | plist->pstack = pstack; |
437 | 12.8M | plist->skip = 0; |
438 | 12.8M | plist->count = 0; |
439 | 12.8M | return 0; |
440 | 12.8M | } |
441 | | |
442 | | /* Implementation for getting parameters to a dictionary. */ |
443 | | static int |
444 | | dict_param_write(iparam_list * plist, const ref * pkey, const ref * pvalue) |
445 | 15.3M | { |
446 | 15.3M | int code = |
447 | 15.3M | dict_put(&((dict_param_list *) plist)->dict, pkey, pvalue, NULL); |
448 | | |
449 | 15.3M | return min(code, 0); |
450 | 15.3M | } |
451 | | |
452 | | /* Implementation for enumerating parameters in a dictionary */ |
453 | | static int /* ret 0 ok, 1 if EOF, or -ve err */ |
454 | | dict_param_enumerate(iparam_list * plist, gs_param_enumerator_t * penum, |
455 | | gs_param_key_t * key, ref_type * type) |
456 | 4.12M | { |
457 | 4.12M | ref elt[2]; |
458 | 4.12M | int code; |
459 | 4.12M | dict_param_list *const pdlist = (dict_param_list *) plist; |
460 | 4.12M | int index = |
461 | 4.12M | (penum->intval != 0 ? penum->intval : dict_first(&pdlist->dict)); |
462 | | |
463 | 4.12M | index = dict_next(&pdlist->dict, index, elt); |
464 | 4.12M | if (index < 0) |
465 | 920k | return 1; |
466 | 3.20M | *type = r_type(&elt[0]); |
467 | 3.20M | code = ref_to_key(&elt[0], key, plist); |
468 | 3.20M | penum->intval = index; |
469 | 3.20M | return code; |
470 | 4.12M | } |
471 | | |
472 | | int |
473 | | dict_param_list_write(dict_param_list *plist, ref *pdict, const ref *pwanted, |
474 | | gs_ref_memory_t *imem) |
475 | 4.87M | { |
476 | 4.87M | check_dict_write(*pdict); |
477 | 4.87M | plist->u.w.write = dict_param_write; |
478 | 4.87M | plist->enumerate = dict_param_enumerate; |
479 | 4.87M | ref_param_write_init((iparam_list *) plist, pwanted, imem); |
480 | 4.87M | plist->dict = *pdict; |
481 | 4.87M | return 0; |
482 | 4.87M | } |
483 | | |
484 | | /* Implementation for getting parameters to an indexed array. */ |
485 | | /* Note that this is now internal, since it only handles "new" arrays. */ |
486 | | static int |
487 | | array_new_indexed_param_write(iparam_list * iplist, const ref * pkey, |
488 | | const ref * pvalue) |
489 | 0 | { |
490 | 0 | const ref *const arr = &((dict_param_list *)iplist)->dict; |
491 | 0 | ref *eltp; |
492 | |
|
493 | 0 | if (!r_has_type(pkey, t_integer)) |
494 | 0 | return_error(gs_error_typecheck); |
495 | 0 | check_int_ltu(*pkey, r_size(arr)); |
496 | 0 | store_check_dest(arr, pvalue); |
497 | 0 | eltp = arr->value.refs + pkey->value.intval; |
498 | | /* ref_assign_new(eltp, pvalue); */ |
499 | 0 | ref_assign(eltp, pvalue); |
500 | 0 | r_set_attrs(eltp, imemory_new_mask(iplist->ref_memory)); |
501 | 0 | return 0; |
502 | 0 | } |
503 | | static int |
504 | | array_new_indexed_plist_write(dict_param_list * plist, ref * parray, |
505 | | const ref * pwanted, gs_ref_memory_t *imem) |
506 | 0 | { |
507 | 0 | check_array(*parray); |
508 | 0 | check_write(*parray); |
509 | 0 | plist->u.w.write = array_new_indexed_param_write; |
510 | 0 | ref_param_write_init((iparam_list *) plist, pwanted, imem); |
511 | 0 | plist->dict = *parray; |
512 | 0 | plist->int_keys = true; |
513 | 0 | return 0; |
514 | 0 | } |
515 | | |
516 | | /* ================ Reading refs to parameters ================ */ |
517 | | |
518 | | /* ---------------- Generic reading procedures ---------------- */ |
519 | | |
520 | | static param_proc_begin_xmit_collection(ref_param_begin_read_collection); |
521 | | static param_proc_end_xmit_collection(ref_param_end_read_collection); |
522 | | static param_proc_xmit_typed(ref_param_read_typed); |
523 | | |
524 | | /*static param_proc_next_key(ref_param_get_next_key); already dec'ld above */ |
525 | | static param_proc_get_policy(ref_param_read_get_policy); |
526 | | static param_proc_signal_error(ref_param_read_signal_error); |
527 | | static param_proc_commit(ref_param_read_commit); |
528 | | static const gs_param_list_procs ref_read_procs = |
529 | | { |
530 | | ref_param_read_typed, |
531 | | ref_param_begin_read_collection, |
532 | | ref_param_end_read_collection, |
533 | | ref_param_get_next_key, |
534 | | NULL, /* request */ |
535 | | NULL, /* requested */ |
536 | | ref_param_read_get_policy, |
537 | | ref_param_read_signal_error, |
538 | | ref_param_read_commit, |
539 | | NULL |
540 | | }; |
541 | | static int ref_param_read(iparam_list *, gs_param_name, |
542 | | iparam_loc *, int); |
543 | | static int ref_param_read_string_value(gs_memory_t *mem, |
544 | | const iparam_loc *, |
545 | | gs_param_string *); |
546 | | static int ref_param_read_array(iparam_list *, gs_param_name, |
547 | | iparam_loc *); |
548 | | |
549 | | #define iparam_note_error(loc, code)\ |
550 | 0 | gs_note_error(*(loc).presult = code) |
551 | | #define iparam_check_type(loc, typ)\ |
552 | 0 | if ( !r_has_type((loc).pvalue, typ) )\ |
553 | 0 | return iparam_note_error(loc, gs_error_typecheck) |
554 | | #define iparam_check_read(loc)\ |
555 | 16.0M | if ( !r_has_attr((loc).pvalue, a_read) )\ |
556 | 16.0M | return iparam_note_error(loc, gs_error_invalidaccess) |
557 | | |
558 | | static int |
559 | | ref_param_read_int_array(gs_param_list * plist, gs_param_name pkey, |
560 | | gs_param_int_array * pvalue) |
561 | 1.90M | { |
562 | 1.90M | iparam_list *const iplist = (iparam_list *) plist; |
563 | 1.90M | iparam_loc loc; |
564 | 1.90M | int code = ref_param_read_array(iplist, pkey, &loc); |
565 | 1.90M | int *piv; |
566 | 1.90M | uint size; |
567 | 1.90M | long i; |
568 | | |
569 | 1.90M | if (code != 0) |
570 | 0 | return code; |
571 | 1.90M | size = r_size(loc.pvalue); |
572 | 1.90M | piv = (int *)gs_alloc_byte_array(plist->memory, size, sizeof(int), |
573 | 1.90M | "ref_param_read_int_array"); |
574 | | |
575 | 1.90M | if (piv == 0) |
576 | 0 | return_error(gs_error_VMerror); |
577 | 9.83M | for (i = 0; i < size; i++) { |
578 | 7.93M | ref elt; |
579 | | |
580 | 7.93M | array_get(plist->memory, loc.pvalue, i, &elt); |
581 | 7.93M | if (!r_has_type(&elt, t_integer)) { |
582 | 0 | code = gs_note_error(gs_error_typecheck); |
583 | 0 | break; |
584 | 0 | } |
585 | 7.93M | piv[i] = (int)elt.value.intval; |
586 | 7.93M | } |
587 | 1.90M | if (code < 0) { |
588 | 0 | gs_free_object(plist->memory, piv, "ref_param_read_int_array"); |
589 | 0 | return (*loc.presult = code); |
590 | 0 | } |
591 | 1.90M | pvalue->data = piv; |
592 | 1.90M | pvalue->size = size; |
593 | 1.90M | pvalue->persistent = true; |
594 | 1.90M | return 0; |
595 | 1.90M | } |
596 | | static int |
597 | | ref_param_read_float_array(gs_param_list * plist, gs_param_name pkey, |
598 | | gs_param_float_array * pvalue) |
599 | 1.66M | { |
600 | 1.66M | iparam_list *const iplist = (iparam_list *) plist; |
601 | 1.66M | iparam_loc loc; |
602 | 1.66M | ref aref, elt; |
603 | 1.66M | int code = ref_param_read_array(iplist, pkey, &loc); |
604 | 1.66M | float *pfv; |
605 | 1.66M | uint size; |
606 | 1.66M | long i; |
607 | | |
608 | 1.66M | if (code != 0) |
609 | 0 | return code; |
610 | 1.66M | size = r_size(loc.pvalue); |
611 | 1.66M | pfv = (float *)gs_alloc_byte_array(plist->memory, size, sizeof(float), |
612 | 1.66M | "ref_param_read_float_array"); |
613 | | |
614 | 1.66M | if (pfv == 0) |
615 | 0 | return_error(gs_error_VMerror); |
616 | 1.66M | aref = *loc.pvalue; |
617 | 1.66M | loc.pvalue = &elt; |
618 | 5.26M | for (i = 0; code >= 0 && i < size; i++) { |
619 | 3.60M | array_get(plist->memory, &aref, i, &elt); |
620 | 3.60M | code = float_param(&elt, pfv + i); |
621 | 3.60M | } |
622 | 1.66M | if (code < 0) { |
623 | 0 | gs_free_object(plist->memory, pfv, "ref_read_float_array_param"); |
624 | 0 | return (*loc.presult = code); |
625 | 0 | } |
626 | 1.66M | pvalue->data = pfv; |
627 | 1.66M | pvalue->size = size; |
628 | 1.66M | pvalue->persistent = true; |
629 | 1.66M | return 0; |
630 | 1.66M | } |
631 | | static int |
632 | | ref_param_read_string_array(gs_param_list * plist, gs_param_name pkey, |
633 | | gs_param_string_array * pvalue) |
634 | 170k | { |
635 | 170k | iparam_list *const iplist = (iparam_list *) plist; |
636 | 170k | iparam_loc loc; |
637 | 170k | ref aref; |
638 | 170k | int code = ref_param_read_array(iplist, pkey, &loc); |
639 | 170k | gs_param_string *psv; |
640 | 170k | uint size; |
641 | 170k | long i; |
642 | | |
643 | 170k | if (code != 0) |
644 | 0 | return code; |
645 | 170k | size = r_size(loc.pvalue); |
646 | 170k | psv = (gs_param_string *) |
647 | 170k | gs_alloc_byte_array(plist->memory, size, sizeof(gs_param_string), |
648 | 170k | "ref_param_read_string_array"); |
649 | 170k | if (psv == 0) |
650 | 0 | return_error(gs_error_VMerror); |
651 | 170k | aref = *loc.pvalue; |
652 | 170k | if (r_has_type(&aref, t_array)) { |
653 | 2.33M | for (i = 0; code >= 0 && i < size; i++) { |
654 | 2.16M | loc.pvalue = aref.value.refs + i; |
655 | 2.16M | code = ref_param_read_string_value(plist->memory, &loc, psv + i); |
656 | 2.16M | } |
657 | 170k | } else { |
658 | 0 | ref elt; |
659 | |
|
660 | 0 | loc.pvalue = &elt; |
661 | 0 | for (i = 0; code >= 0 && i < size; i++) { |
662 | 0 | array_get(plist->memory, &aref, i, &elt); |
663 | 0 | code = ref_param_read_string_value(plist->memory, &loc, psv + i); |
664 | 0 | } |
665 | 0 | } |
666 | 170k | if (code < 0) { |
667 | 0 | gs_free_object(plist->memory, psv, "ref_param_read_string_array"); |
668 | 0 | return (*loc.presult = code); |
669 | 0 | } |
670 | 170k | pvalue->data = psv; |
671 | 170k | pvalue->size = size; |
672 | 170k | pvalue->persistent = true; |
673 | 170k | return 0; |
674 | 170k | } |
675 | | static int |
676 | | ref_param_begin_read_collection(gs_param_list * plist, gs_param_name pkey, |
677 | | gs_param_dict * pvalue, |
678 | | gs_param_collection_type_t coll_type) |
679 | 4.44M | { |
680 | 4.44M | iparam_list *const iplist = (iparam_list *) plist; |
681 | 4.44M | iparam_loc loc; |
682 | 4.44M | bool int_keys = coll_type != 0; |
683 | 4.44M | int code = ref_param_read(iplist, pkey, &loc, -1); |
684 | 4.44M | dict_param_list *dlist; |
685 | | |
686 | 4.44M | if (code != 0) |
687 | 3.52M | return code; |
688 | 920k | dlist = (dict_param_list *) |
689 | 920k | gs_alloc_bytes(plist->memory, size_of(dict_param_list), |
690 | 920k | "ref_param_begin_read_collection"); |
691 | 920k | if (dlist == 0) |
692 | 0 | return_error(gs_error_VMerror); |
693 | 920k | if (r_has_type(loc.pvalue, t_dictionary)) { |
694 | 920k | code = dict_param_list_read(dlist, loc.pvalue, NULL, false, |
695 | 920k | iplist->ref_memory); |
696 | 920k | dlist->int_keys = int_keys; |
697 | 920k | if (code >= 0) |
698 | 920k | pvalue->size = dict_length(loc.pvalue); |
699 | 920k | } else if (int_keys && r_is_array(loc.pvalue)) { |
700 | 0 | code = array_indexed_param_list_read(dlist, loc.pvalue, NULL, false, |
701 | 0 | iplist->ref_memory); |
702 | 0 | if (code >= 0) |
703 | 0 | pvalue->size = r_size(loc.pvalue); |
704 | 0 | } else |
705 | 0 | code = gs_note_error(gs_error_typecheck); |
706 | 920k | if (code < 0) { |
707 | 0 | gs_free_object(plist->memory, dlist, "ref_param_begin_write_collection"); |
708 | 0 | return iparam_note_error(loc, code); |
709 | 0 | } |
710 | 920k | pvalue->list = (gs_param_list *) dlist; |
711 | 920k | return 0; |
712 | 920k | } |
713 | | static int |
714 | | ref_param_end_read_collection(gs_param_list * plist, gs_param_name pkey, |
715 | | gs_param_dict * pvalue) |
716 | 920k | { |
717 | 920k | iparam_list_release((dict_param_list *) pvalue->list); |
718 | 920k | gs_free_object(plist->memory, pvalue->list, |
719 | 920k | "ref_param_end_read_collection"); |
720 | 920k | return 0; |
721 | 920k | } |
722 | | static int |
723 | | ref_param_read_typed(gs_param_list * plist, gs_param_name pkey, |
724 | | gs_param_typed_value * pvalue) |
725 | 382M | { |
726 | 382M | iparam_list *const iplist = (iparam_list *) plist; |
727 | 382M | iparam_loc loc; |
728 | 382M | ref elt; |
729 | 382M | int code = ref_param_read(iplist, pkey, &loc, -1); |
730 | | |
731 | 382M | if (code != 0) |
732 | 336M | return code; |
733 | 46.5M | switch (r_type(loc.pvalue)) { |
734 | 5.08M | case t_array: |
735 | 5.08M | case t_mixedarray: |
736 | 5.08M | case t_shortarray: |
737 | 5.08M | iparam_check_read(loc); |
738 | 5.08M | if (r_size(loc.pvalue) <= 0) { |
739 | | /* 0-length array; can't get type info */ |
740 | 1.35M | pvalue->type = gs_param_type_array; |
741 | 1.35M | pvalue->value.d.list = 0; |
742 | 1.35M | pvalue->value.d.size = 0; |
743 | 1.35M | return 0; |
744 | 1.35M | } |
745 | | /* |
746 | | * We have to guess at the array type. First we guess based |
747 | | * on the type of the first element of the array. If that |
748 | | * fails, we try again with more general types. |
749 | | */ |
750 | 3.73M | array_get(plist->memory, loc.pvalue, 0, &elt); |
751 | 3.73M | switch (r_type(&elt)) { |
752 | 1.90M | case t_integer: |
753 | 1.90M | pvalue->type = gs_param_type_int_array; |
754 | 1.90M | code = ref_param_read_int_array(plist, pkey, |
755 | 1.90M | &pvalue->value.ia); |
756 | 1.90M | if (code != gs_error_typecheck) |
757 | 1.90M | return code; |
758 | | /* This might be a float array. Fall through. */ |
759 | 0 | *loc.presult = 0; /* reset error */ |
760 | 1.66M | case t_real: |
761 | 1.66M | pvalue->type = gs_param_type_float_array; |
762 | 1.66M | return ref_param_read_float_array(plist, pkey, |
763 | 1.66M | &pvalue->value.fa); |
764 | 36 | case t_string: |
765 | 36 | pvalue->type = gs_param_type_string_array; |
766 | 36 | return ref_param_read_string_array(plist, pkey, |
767 | 36 | &pvalue->value.sa); |
768 | 170k | case t_name: |
769 | 170k | pvalue->type = gs_param_type_name_array; |
770 | 170k | return ref_param_read_string_array(plist, pkey, |
771 | 170k | &pvalue->value.na); |
772 | 0 | default: |
773 | 0 | break; |
774 | 3.73M | } |
775 | 0 | return gs_note_error(gs_error_typecheck); |
776 | 12.4M | case t_boolean: |
777 | 12.4M | pvalue->type = gs_param_type_bool; |
778 | 12.4M | pvalue->value.b = loc.pvalue->value.boolval; |
779 | 12.4M | return 0; |
780 | 2 | case t_dictionary: |
781 | 2 | code = ref_param_begin_read_collection(plist, pkey, |
782 | 2 | &pvalue->value.d, gs_param_collection_dict_any); |
783 | 2 | if (code < 0) |
784 | 0 | return code; |
785 | 2 | pvalue->type = gs_param_type_dict; |
786 | | |
787 | | /* fixup new dict's type & int_keys field if contents have int keys */ |
788 | 2 | { |
789 | 2 | gs_param_enumerator_t enumr; |
790 | 2 | gs_param_key_t key; |
791 | 2 | ref_type keytype; |
792 | 2 | dict_param_list *dlist = (dict_param_list *) pvalue->value.d.list; |
793 | | |
794 | 2 | param_init_enumerator(&enumr); |
795 | 2 | if (!(*(dlist->enumerate)) |
796 | 2 | ((iparam_list *) dlist, &enumr, &key, &keytype) |
797 | 2 | && keytype == t_integer) { |
798 | 0 | dlist->int_keys = 1; |
799 | 0 | pvalue->type = gs_param_type_dict_int_keys; |
800 | 0 | } |
801 | 2 | } |
802 | 2 | return 0; |
803 | 17.2M | case t_integer: |
804 | 17.2M | pvalue->type = gs_param_type_i64; |
805 | 17.2M | pvalue->value.i64 = loc.pvalue->value.intval; |
806 | 17.2M | return 0; |
807 | 2.20M | case t_name: |
808 | 2.20M | pvalue->type = gs_param_type_name; |
809 | 2.20M | return ref_param_read_string_value(plist->memory, &loc, &pvalue->value.n); |
810 | 376k | case t_null: |
811 | 376k | pvalue->type = gs_param_type_null; |
812 | 376k | return 0; |
813 | 1.92M | case t_real: |
814 | 1.92M | pvalue->value.f = loc.pvalue->value.realval; |
815 | 1.92M | pvalue->type = gs_param_type_float; |
816 | 1.92M | return 0; |
817 | 7.23M | case t_string: |
818 | 7.23M | case t_astruct: |
819 | 7.23M | pvalue->type = gs_param_type_string; |
820 | 7.23M | return ref_param_read_string_value(plist->memory, &loc, &pvalue->value.s); |
821 | 0 | default: |
822 | 0 | break; |
823 | 46.5M | } |
824 | 0 | return gs_note_error(gs_error_typecheck); |
825 | 46.5M | } |
826 | | |
827 | | static int |
828 | | ref_param_read_get_policy(gs_param_list * plist, gs_param_name pkey) |
829 | 746 | { |
830 | 746 | iparam_list *const iplist = (iparam_list *) plist; |
831 | 746 | ref *pvalue; |
832 | | |
833 | 746 | if (!(r_has_type(&iplist->u.r.policies, t_dictionary) && |
834 | 746 | dict_find_string(&iplist->u.r.policies, pkey, &pvalue) > 0 && |
835 | 746 | r_has_type(pvalue, t_integer)) |
836 | 746 | ) |
837 | 746 | return gs_param_policy_ignore; |
838 | 0 | return (int)pvalue->value.intval; |
839 | 746 | } |
840 | | static int |
841 | | ref_param_read_signal_error(gs_param_list * plist, gs_param_name pkey, int code) |
842 | 746 | { |
843 | 746 | iparam_list *const iplist = (iparam_list *) plist; |
844 | 746 | iparam_loc loc = {0}; |
845 | | |
846 | 746 | ref_param_read(iplist, pkey, &loc, -1); |
847 | 746 | if (loc.presult) |
848 | 374 | *loc.presult = code; |
849 | 746 | switch (ref_param_read_get_policy(plist, pkey)) { |
850 | 746 | case gs_param_policy_ignore: |
851 | 746 | return 0; |
852 | 0 | case gs_param_policy_consult_user: |
853 | 0 | return_error(gs_error_configurationerror); |
854 | 0 | default: |
855 | 0 | return code; |
856 | 746 | } |
857 | 746 | } |
858 | | static int |
859 | | ref_param_read_commit(gs_param_list * plist) |
860 | 1.58M | { |
861 | 1.58M | iparam_list *const iplist = (iparam_list *) plist; |
862 | 1.58M | int i; |
863 | 1.58M | int ecode = 0; |
864 | | |
865 | 1.58M | if (!iplist->u.r.require_all) |
866 | 376k | return 0; |
867 | | /* Check to make sure that all parameters were actually read. */ |
868 | 17.5M | for (i = 0; i < iplist->count; ++i) |
869 | 16.3M | if (iplist->results[i] == 0) |
870 | 1.20M | iplist->results[i] = ecode = gs_note_error(gs_error_undefined); |
871 | 1.20M | return ecode; |
872 | 1.58M | } |
873 | | static int |
874 | | ref_param_get_next_key(gs_param_list * plist, gs_param_enumerator_t * penum, |
875 | | gs_param_key_t * key) |
876 | 4.12M | { |
877 | 4.12M | ref_type keytype; /* result not needed here */ |
878 | 4.12M | iparam_list *const pilist = (iparam_list *) plist; |
879 | | |
880 | 4.12M | return (*pilist->enumerate) (pilist, penum, key, &keytype); |
881 | 4.12M | } |
882 | | |
883 | | /* ---------------- Internal routines ---------------- */ |
884 | | |
885 | | /* Read a string value. */ |
886 | | static int |
887 | | ref_param_read_string_value(gs_memory_t *mem, const iparam_loc * ploc, gs_param_string * pvalue) |
888 | 11.6M | { |
889 | 11.6M | const ref *pref = ploc->pvalue; |
890 | | |
891 | 11.6M | switch (r_type(pref)) { |
892 | 4.35M | case t_name: { |
893 | 4.35M | ref nref; |
894 | | |
895 | 4.35M | name_string_ref(mem, pref, &nref); |
896 | 4.35M | pvalue->data = nref.value.const_bytes; |
897 | 4.35M | pvalue->size = r_size(&nref); |
898 | 4.35M | pvalue->persistent = true; |
899 | 4.35M | } |
900 | 4.35M | break; |
901 | 7.25M | case t_string: |
902 | 7.25M | iparam_check_read(*ploc); |
903 | 7.25M | pvalue->data = pref->value.const_bytes; |
904 | 7.25M | pvalue->size = r_size(pref); |
905 | 7.25M | pvalue->persistent = false; |
906 | 7.25M | break; |
907 | 0 | case t_astruct: |
908 | | /* Note: technically, instead of the "mem" argument, we |
909 | | should be using the plists's ref_memory. However, in a |
910 | | simple call to .putdeviceparams, they are identical. */ |
911 | 0 | iparam_check_read(*ploc); |
912 | 0 | if (gs_object_type(mem, pref->value.pstruct) != &st_bytes) |
913 | 0 | return iparam_note_error(*ploc, gs_error_typecheck); |
914 | 0 | pvalue->data = r_ptr(pref, byte); |
915 | 0 | pvalue->size = gs_object_size(mem, pref->value.pstruct); |
916 | 0 | pvalue->persistent = false; |
917 | 0 | break; |
918 | 0 | default: |
919 | 0 | return iparam_note_error(*ploc, gs_error_typecheck); |
920 | 11.6M | } |
921 | 11.6M | return 0; |
922 | 11.6M | } |
923 | | |
924 | | /* Read an array (or packed array) parameter. */ |
925 | | static int |
926 | | ref_param_read_array(iparam_list * plist, gs_param_name pkey, iparam_loc * ploc) |
927 | 3.73M | { |
928 | 3.73M | int code = ref_param_read(plist, pkey, ploc, -1); |
929 | | |
930 | 3.73M | if (code != 0) |
931 | 0 | return code; |
932 | 3.73M | if (!r_is_array(ploc->pvalue)) |
933 | 0 | return iparam_note_error(*ploc, gs_error_typecheck); |
934 | 3.73M | iparam_check_read(*ploc); |
935 | 3.73M | return 0; |
936 | 3.73M | } |
937 | | |
938 | | /* Generic routine for reading a ref parameter. */ |
939 | | static int |
940 | | ref_param_read(iparam_list * plist, gs_param_name pkey, iparam_loc * ploc, |
941 | | int type) |
942 | 390M | { |
943 | 390M | iparam_list *const iplist = (iparam_list *) plist; |
944 | 390M | ref kref; |
945 | 390M | int code = ref_param_key(plist, pkey, &kref); |
946 | | |
947 | 390M | if (code < 0) |
948 | 0 | return code; |
949 | 390M | code = (*plist->u.r.read) (iplist, &kref, ploc); |
950 | 390M | if (code != 0) |
951 | 339M | return code; |
952 | 51.1M | if (type >= 0) |
953 | 0 | iparam_check_type(*ploc, type); |
954 | 51.1M | return 0; |
955 | 51.1M | } |
956 | | |
957 | | /* ---------------- Implementations ---------------- */ |
958 | | |
959 | | /* Implementation for putting parameters from an empty collection. */ |
960 | | static int |
961 | | empty_param_read(iparam_list * plist, const ref * pkey, iparam_loc * ploc) |
962 | 0 | { |
963 | 0 | return 1; |
964 | 0 | } |
965 | | |
966 | | /* Initialize for reading parameters. */ |
967 | | static int |
968 | | ref_param_read_init(iparam_list * plist, uint count, const ref * ppolicies, |
969 | | bool require_all, gs_ref_memory_t *imem) |
970 | 6.96M | { |
971 | 6.96M | gs_param_list_init((gs_param_list *)plist, &ref_read_procs, |
972 | 6.96M | (gs_memory_t *)imem); |
973 | 6.96M | plist->ref_memory = imem; |
974 | 6.96M | if (ppolicies == 0) |
975 | 6.96M | make_null(&plist->u.r.policies); |
976 | 1.60M | else |
977 | 1.60M | plist->u.r.policies = *ppolicies; |
978 | 6.96M | plist->u.r.require_all = require_all; |
979 | 6.96M | plist->count = count; |
980 | 6.96M | plist->results = (int *) |
981 | 6.96M | gs_alloc_byte_array(plist->memory, count, sizeof(int), |
982 | 6.96M | "ref_param_read_init"); |
983 | | |
984 | 6.96M | if (plist->results == 0) |
985 | 1 | return_error(gs_error_VMerror); |
986 | 6.96M | memset(plist->results, 0, count * sizeof(int)); |
987 | | |
988 | 6.96M | plist->int_keys = false; |
989 | 6.96M | return 0; |
990 | 6.96M | } |
991 | | |
992 | | /* Implementation for putting parameters from an indexed array. */ |
993 | | static int |
994 | | array_indexed_param_read(iparam_list * plist, const ref * pkey, iparam_loc * ploc) |
995 | 0 | { |
996 | 0 | ref *const arr = &((dict_param_list *) plist)->dict; |
997 | |
|
998 | 0 | check_type(*pkey, t_integer); |
999 | 0 | if (pkey->value.intval < 0 || pkey->value.intval >= r_size(arr)) |
1000 | 0 | return 1; |
1001 | 0 | ploc->pvalue = arr->value.refs + pkey->value.intval; |
1002 | 0 | ploc->presult = &plist->results[pkey->value.intval]; |
1003 | 0 | *ploc->presult = 1; |
1004 | 0 | return 0; |
1005 | 0 | } |
1006 | | int |
1007 | | array_indexed_param_list_read(dict_param_list * plist, const ref * parray, |
1008 | | const ref * ppolicies, bool require_all, |
1009 | | gs_ref_memory_t *ref_memory) |
1010 | 0 | { |
1011 | 0 | iparam_list *const iplist = (iparam_list *) plist; |
1012 | 0 | int code; |
1013 | |
|
1014 | 0 | check_read_type(*parray, t_array); |
1015 | 0 | plist->u.r.read = array_indexed_param_read; |
1016 | 0 | plist->dict = *parray; |
1017 | 0 | code = ref_param_read_init(iplist, r_size(parray), ppolicies, |
1018 | 0 | require_all, ref_memory); |
1019 | 0 | plist->int_keys = true; |
1020 | 0 | return code; |
1021 | 0 | } |
1022 | | |
1023 | | /* Implementation for putting parameters from an array. */ |
1024 | | static int |
1025 | | array_param_read(iparam_list * plist, const ref * pkey, iparam_loc * ploc) |
1026 | 0 | { |
1027 | 0 | ref *bot = ((array_param_list *) plist)->bot; |
1028 | 0 | ref *ptr = bot; |
1029 | 0 | ref *top = ((array_param_list *) plist)->top; |
1030 | |
|
1031 | 0 | for (; ptr < top; ptr += 2) { |
1032 | 0 | if (r_has_type(ptr, t_name) && name_eq(ptr, pkey)) { |
1033 | 0 | ploc->pvalue = ptr + 1; |
1034 | 0 | ploc->presult = &plist->results[ptr - bot]; |
1035 | 0 | *ploc->presult = 1; |
1036 | 0 | return 0; |
1037 | 0 | } |
1038 | 0 | } |
1039 | 0 | return 1; |
1040 | 0 | } |
1041 | | |
1042 | | /* Implementation for enumerating parameters in an array */ |
1043 | | static int /* ret 0 ok, 1 if EOF, or -ve err */ |
1044 | | array_param_enumerate(iparam_list * plist, gs_param_enumerator_t * penum, |
1045 | | gs_param_key_t * key, ref_type * type) |
1046 | 0 | { |
1047 | 0 | int index = penum->intval; |
1048 | 0 | ref *bot = ((array_param_list *) plist)->bot; |
1049 | 0 | ref *ptr = bot + index; |
1050 | 0 | ref *top = ((array_param_list *) plist)->top; |
1051 | |
|
1052 | 0 | for (; ptr < top; ptr += 2) { |
1053 | 0 | index += 2; |
1054 | |
|
1055 | 0 | if (r_has_type(ptr, t_name)) { |
1056 | 0 | int code = ref_to_key(ptr, key, plist); |
1057 | |
|
1058 | 0 | *type = r_type(ptr); |
1059 | 0 | penum->intval = index; |
1060 | 0 | return code; |
1061 | 0 | } |
1062 | 0 | } |
1063 | 0 | return 1; |
1064 | 0 | } |
1065 | | |
1066 | | int |
1067 | | array_param_list_read(array_param_list * plist, ref * bot, uint count, |
1068 | | const ref * ppolicies, bool require_all, |
1069 | | gs_ref_memory_t *imem) |
1070 | 0 | { |
1071 | 0 | iparam_list *const iplist = (iparam_list *) plist; |
1072 | |
|
1073 | 0 | if (count & 1) |
1074 | 0 | return_error(gs_error_rangecheck); |
1075 | 0 | plist->u.r.read = array_param_read; |
1076 | 0 | plist->enumerate = array_param_enumerate; |
1077 | 0 | plist->bot = bot; |
1078 | 0 | plist->top = bot + count; |
1079 | 0 | return ref_param_read_init(iplist, count, ppolicies, require_all, imem); |
1080 | 0 | } |
1081 | | |
1082 | | /* Implementation for putting parameters from a stack. */ |
1083 | | static int |
1084 | | stack_param_read(iparam_list * plist, const ref * pkey, iparam_loc * ploc) |
1085 | 275M | { |
1086 | 275M | stack_param_list *const splist = (stack_param_list *) plist; |
1087 | 275M | ref_stack_t *pstack = splist->pstack; |
1088 | | |
1089 | | /* This implementation is slow, but it probably doesn't matter. */ |
1090 | 275M | uint index = splist->skip + 1; |
1091 | 275M | uint count = splist->count; |
1092 | | |
1093 | 4.64G | for (; count; count--, index += 2) { |
1094 | 4.40G | const ref *p = ref_stack_index(pstack, index); |
1095 | | |
1096 | 4.40G | if (p == NULL) |
1097 | 0 | continue; |
1098 | | |
1099 | 4.40G | if (r_has_type(p, t_name) && name_eq(p, pkey)) { |
1100 | 31.1M | ploc->pvalue = ref_stack_index(pstack, index - 1); |
1101 | 31.1M | ploc->presult = &plist->results[count - 1]; |
1102 | 31.1M | *ploc->presult = 1; |
1103 | 31.1M | return 0; |
1104 | 31.1M | } |
1105 | 4.40G | } |
1106 | 244M | return 1; |
1107 | 275M | } |
1108 | | int |
1109 | | stack_param_list_read(stack_param_list * plist, ref_stack_t * pstack, |
1110 | | uint skip, const ref * ppolicies, bool require_all, |
1111 | | gs_ref_memory_t *imem) |
1112 | 1.60M | { |
1113 | 1.60M | iparam_list *const iplist = (iparam_list *) plist; |
1114 | 1.60M | uint count = ref_stack_counttomark(pstack); |
1115 | | |
1116 | 1.60M | if (count == 0) |
1117 | 0 | return_error(gs_error_unmatchedmark); |
1118 | 1.60M | count -= skip + 1; |
1119 | 1.60M | if (count & 1) |
1120 | 0 | return_error(gs_error_rangecheck); |
1121 | 1.60M | plist->u.r.read = stack_param_read; |
1122 | 1.60M | plist->enumerate = stack_param_enumerate; |
1123 | 1.60M | plist->pstack = pstack; |
1124 | 1.60M | plist->skip = skip; |
1125 | 1.60M | return ref_param_read_init(iplist, count >> 1, ppolicies, require_all, imem); |
1126 | 1.60M | } |
1127 | | |
1128 | | /* Implementation for putting parameters from a dictionary. */ |
1129 | | static int |
1130 | | dict_param_read(iparam_list * plist, const ref * pkey, iparam_loc * ploc) |
1131 | 115M | { |
1132 | 115M | ref const *spdict = &((dict_param_list *) plist)->dict; |
1133 | 115M | int code = dict_find(spdict, pkey, &ploc->pvalue); |
1134 | | |
1135 | 115M | if (code != 1) |
1136 | 95.7M | return 1; |
1137 | 20.0M | ploc->presult = |
1138 | 20.0M | &plist->results[dict_value_index(spdict, ploc->pvalue)]; |
1139 | 20.0M | *ploc->presult = 1; |
1140 | 20.0M | return 0; |
1141 | 115M | } |
1142 | | int |
1143 | | dict_param_list_read(dict_param_list * plist, const ref * pdict, |
1144 | | const ref * ppolicies, bool require_all, |
1145 | | gs_ref_memory_t *imem) |
1146 | 5.36M | { |
1147 | 5.36M | iparam_list *const iplist = (iparam_list *) plist; |
1148 | 5.36M | uint count; |
1149 | | |
1150 | 5.36M | if (pdict == 0) { |
1151 | 0 | plist->u.r.read = empty_param_read; |
1152 | 0 | count = 0; |
1153 | 5.36M | } else { |
1154 | 5.36M | check_dict_read(*pdict); |
1155 | 5.36M | plist->u.r.read = dict_param_read; |
1156 | 5.36M | plist->dict = *pdict; |
1157 | 5.36M | count = dict_max_index(pdict) + 1; |
1158 | 5.36M | } |
1159 | 5.36M | plist->enumerate = dict_param_enumerate; |
1160 | 5.36M | return ref_param_read_init(iplist, count, ppolicies, require_all, imem); |
1161 | 5.36M | } |