/src/ghostpdl/base/gscparam.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Copyright (C) 2001-2023 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 | | /* Default implementation of parameter lists */ |
18 | | #include "memory_.h" |
19 | | #include "string_.h" |
20 | | #include "gx.h" |
21 | | #include "gserrors.h" |
22 | | #include "gsparam.h" |
23 | | #include "gsstruct.h" |
24 | | |
25 | | /* Forward references */ |
26 | | typedef union c_param_value_s { |
27 | | GS_PARAM_VALUE_UNION(gs_c_param_list); |
28 | | } gs_c_param_value; |
29 | | /*typedef struct gs_c_param_s gs_c_param; *//* in gsparam.h */ |
30 | | |
31 | | /* Define the GC type for a parameter list. */ |
32 | | private_st_c_param_list(); |
33 | | |
34 | | /* Lengths corresponding to various gs_param_type_xxx types */ |
35 | | const byte gs_param_type_sizes[] = { |
36 | | GS_PARAM_TYPE_SIZES(sizeof(gs_c_param_list)) |
37 | | }; |
38 | | |
39 | | /* Lengths of *actual* data-containing type pointed to or contained by gs_param_type_xxx's */ |
40 | | const byte gs_param_type_base_sizes[] = { |
41 | | GS_PARAM_TYPE_BASE_SIZES(0) |
42 | | }; |
43 | | |
44 | | /* |
45 | | * Define a parameter list element. We use gs_param_type_any to identify |
46 | | * elements that have been requested but not yet written. The reading |
47 | | * procedures must recognize such elements as undefined, and ignore them. |
48 | | */ |
49 | | struct gs_c_param_s { |
50 | | gs_c_param *next; |
51 | | gs_param_key_t key; |
52 | | bool free_key; |
53 | | gs_c_param_value value; |
54 | | gs_param_type type; |
55 | | void *alternate_typed_data; |
56 | | int error; |
57 | | }; |
58 | | |
59 | | /* GC descriptor and procedures */ |
60 | | gs_private_st_composite(st_c_param, gs_c_param, "gs_c_param", |
61 | | c_param_enum_ptrs, c_param_reloc_ptrs); |
62 | 29.3M | ENUM_PTRS_WITH(c_param_enum_ptrs, gs_c_param *param) { |
63 | 11.7M | index -= 3; |
64 | 11.7M | switch (param->type) { |
65 | | /* Only the aggregate types are handled specially. */ |
66 | 0 | case gs_param_type_dict: |
67 | 0 | case gs_param_type_dict_int_keys: |
68 | 0 | case gs_param_type_array: |
69 | 0 | return ENUM_USING(st_c_param_list, ¶m->value.d, |
70 | 0 | sizeof(param->value.d), index); |
71 | 11.7M | default: { |
72 | 11.7M | gs_param_typed_value value; |
73 | | |
74 | 11.7M | value.value = *(const gs_param_value *)¶m->value; |
75 | 11.7M | value.type = param->type; |
76 | 11.7M | return gs_param_typed_value_enum_ptrs(mem, &value, sizeof(value), index, |
77 | 11.7M | pep, NULL, gcst); |
78 | 0 | } |
79 | 11.7M | } |
80 | 11.7M | } |
81 | 5.87M | case 0: return ENUM_OBJ(param->next); |
82 | 5.87M | case 1: return ENUM_OBJ(param->alternate_typed_data); |
83 | 5.87M | case 2: |
84 | 5.87M | if (!param->key.persistent) { |
85 | 5.87M | gs_const_string key; |
86 | | |
87 | 5.87M | key.data = param->key.data; |
88 | 5.87M | key.size = param->key.size; |
89 | 5.87M | return ENUM_STRING(&key); |
90 | 5.87M | } else |
91 | 0 | return ENUM_OBJ(0); /* keep going */ |
92 | 29.3M | ENUM_PTRS_END |
93 | 5.87M | RELOC_PTRS_WITH(c_param_reloc_ptrs, gs_c_param *param) { |
94 | 5.87M | RELOC_VAR(param->next); |
95 | 5.87M | RELOC_VAR(param->alternate_typed_data); |
96 | 5.87M | if (!param->key.persistent) { |
97 | 5.87M | gs_const_string key; |
98 | | |
99 | 5.87M | key.data = param->key.data; |
100 | 5.87M | key.size = param->key.size; |
101 | 5.87M | RELOC_CONST_STRING_VAR(key); |
102 | 5.87M | param->key.data = key.data; |
103 | 5.87M | } |
104 | 5.87M | switch (param->type) { |
105 | | /* Only the aggregate types are handled specially. */ |
106 | 0 | case gs_param_type_dict: |
107 | 0 | case gs_param_type_dict_int_keys: |
108 | 0 | case gs_param_type_array: |
109 | 0 | RELOC_USING(st_c_param_list, ¶m->value.d, sizeof(param->value.d)); |
110 | 0 | break; |
111 | 5.87M | default: { |
112 | 5.87M | gs_param_typed_value value; |
113 | | |
114 | 5.87M | value.value = *(gs_param_value *)¶m->value; |
115 | 5.87M | value.type = param->type; |
116 | 5.87M | gs_param_typed_value_reloc_ptrs(&value, sizeof(value), NULL, gcst); |
117 | 5.87M | *(gs_param_value *)¶m->value = value.value; |
118 | 5.87M | } |
119 | 5.87M | } |
120 | 5.87M | } |
121 | 5.87M | RELOC_PTRS_END |
122 | | |
123 | | /* ---------------- Utilities ---------------- */ |
124 | | |
125 | | gs_c_param_list * |
126 | | gs_c_param_list_alloc(gs_memory_t *mem, client_name_t cname) |
127 | 920k | { |
128 | 920k | return gs_alloc_struct(mem, gs_c_param_list, &st_c_param_list, cname); |
129 | 920k | } |
130 | | |
131 | | void gs_c_param_list_free(gs_memory_t *mem, gs_c_param_list *plist, client_name_t cname) |
132 | 0 | { |
133 | 0 | if (plist == NULL) |
134 | 0 | return; |
135 | 0 | gs_c_param_list_release(plist); |
136 | 0 | gs_free_object(mem, plist, cname); |
137 | 0 | } |
138 | | |
139 | | static gs_c_param * |
140 | | c_param_find(const gs_c_param_list *plist, gs_param_name pkey, bool any) |
141 | 15.7M | { |
142 | 15.7M | gs_c_param *pparam = plist->head; |
143 | 15.7M | uint len = strlen(pkey); |
144 | | |
145 | 41.0M | for (; pparam != 0; pparam = pparam->next) |
146 | 40.9M | if (pparam->key.size == len && !memcmp(pparam->key.data, pkey, len)) |
147 | 15.5M | return (pparam->type != gs_param_type_any || any ? pparam : 0); |
148 | 165k | return 0; |
149 | 15.7M | } |
150 | | |
151 | | /* ---------------- Writing parameters to a list ---------------- */ |
152 | | |
153 | | static param_proc_begin_xmit_collection(c_param_begin_write_collection); |
154 | | static param_proc_end_xmit_collection(c_param_end_write_collection); |
155 | | static param_proc_xmit_typed(c_param_write_typed); |
156 | | static param_proc_request(c_param_request); |
157 | | static param_proc_requested(c_param_requested); |
158 | | static const gs_param_list_procs c_write_procs = |
159 | | { |
160 | | c_param_write_typed, |
161 | | c_param_begin_write_collection, |
162 | | c_param_end_write_collection, |
163 | | NULL, /* get_next_key */ |
164 | | c_param_request, |
165 | | c_param_requested |
166 | | }; |
167 | | |
168 | | /* Initialize a list for writing. */ |
169 | | void |
170 | | gs_c_param_list_write(gs_c_param_list * plist, gs_memory_t * mem) |
171 | 2.01M | { |
172 | 2.01M | plist->memory = mem; |
173 | 2.01M | plist->head = 0; |
174 | 2.01M | plist->target = 0; /* not used for writing */ |
175 | 2.01M | plist->count = 0; |
176 | 2.01M | plist->any_requested = false; |
177 | 2.01M | plist->persistent_keys = true; |
178 | 2.01M | gs_c_param_list_write_more(plist); |
179 | 2.01M | } |
180 | | |
181 | | /* Set the target of a list. Only relevant for reading. */ |
182 | | void |
183 | | gs_c_param_list_set_target(gs_c_param_list *plist, gs_param_list *target) |
184 | 6.15k | { |
185 | 6.15k | plist->target = target; |
186 | 6.15k | } |
187 | | |
188 | | /* Re-enable a list for writing, without clearing it. */ |
189 | | /* gs_c_param_list_write must have been called previously. */ |
190 | | void |
191 | | gs_c_param_list_write_more(gs_c_param_list * plist) |
192 | 2.04M | { |
193 | 2.04M | plist->procs = &c_write_procs; |
194 | 2.04M | plist->coll_type = gs_param_collection_dict_any; |
195 | 2.04M | } |
196 | | |
197 | | /* Release a list. */ |
198 | | void |
199 | | gs_c_param_list_release(gs_c_param_list * plist) |
200 | 1.36M | { |
201 | 1.36M | gs_memory_t *mem = plist->memory; |
202 | 1.36M | gs_c_param *pparam; |
203 | | |
204 | 2.07M | while ((pparam = plist->head) != 0) { |
205 | 704k | gs_c_param *next = pparam->next; |
206 | | |
207 | 704k | switch (pparam->type) { |
208 | 0 | case gs_param_type_dict: |
209 | 0 | case gs_param_type_dict_int_keys: |
210 | 0 | case gs_param_type_array: |
211 | 0 | gs_c_param_list_release(&pparam->value.d); |
212 | 0 | break; |
213 | 209 | case gs_param_type_string: |
214 | 209 | case gs_param_type_name: |
215 | 179k | case gs_param_type_int_array: |
216 | 179k | case gs_param_type_float_array: |
217 | 208k | case gs_param_type_string_array: |
218 | 208k | case gs_param_type_name_array: |
219 | 208k | if (!pparam->value.s.persistent) |
220 | 208k | gs_free_const_object(mem, pparam->value.s.data, |
221 | 208k | "gs_c_param_list_release data"); |
222 | 208k | break; |
223 | 496k | default: |
224 | 496k | break; |
225 | 704k | } |
226 | 704k | if (pparam->free_key) { |
227 | | /* We allocated this, so we must free it. */ |
228 | 442k | gs_free_const_string(mem, pparam->key.data, pparam->key.size, |
229 | 442k | "gs_c_param_list_release key"); |
230 | 442k | } |
231 | 704k | gs_free_object(mem, pparam->alternate_typed_data, |
232 | 704k | "gs_c_param_list_release alternate data"); |
233 | 704k | gs_free_object(mem, pparam, |
234 | 704k | "gs_c_param_list_release entry"); |
235 | 704k | plist->head = next; |
236 | 704k | plist->count--; |
237 | 704k | } |
238 | 1.36M | } |
239 | | |
240 | | /* Add an entry to a list. Doesn't set: value, type, plist->head. */ |
241 | | static gs_c_param * |
242 | | c_param_add(gs_c_param_list * plist, gs_param_name pkey) |
243 | 3.51M | { |
244 | 3.51M | gs_c_param *pparam = |
245 | 3.51M | gs_alloc_struct(plist->memory, gs_c_param, &st_c_param, |
246 | 3.51M | "c_param_add entry"); |
247 | 3.51M | uint len; |
248 | | |
249 | 3.51M | if ((pparam == NULL) || (pkey == NULL)) |
250 | 0 | return NULL; |
251 | | |
252 | 3.51M | len = strlen(pkey); |
253 | 3.51M | pparam->next = plist->head; |
254 | 3.51M | if (!plist->persistent_keys) { |
255 | | /* We must copy the key. */ |
256 | 3.25M | byte *str = gs_alloc_string(plist->memory, len, "c_param_add key"); |
257 | | |
258 | 3.25M | if (str == 0) { |
259 | 0 | gs_free_object(plist->memory, pparam, "c_param_add entry"); |
260 | 0 | return 0; |
261 | 0 | } |
262 | 3.25M | memcpy(str, pkey, len); |
263 | 3.25M | pparam->key.data = str; |
264 | 3.25M | pparam->key.persistent = false; /* we will free it */ |
265 | 3.25M | pparam->free_key = true; |
266 | 3.25M | } else { |
267 | 261k | pparam->key.data = (const byte *)pkey; |
268 | 261k | pparam->key.persistent = true; |
269 | 261k | pparam->free_key = false; |
270 | 261k | } |
271 | 3.51M | pparam->key.size = len; |
272 | 3.51M | pparam->alternate_typed_data = 0; |
273 | 3.51M | pparam->error = 0; |
274 | 3.51M | return pparam; |
275 | 3.51M | } |
276 | | |
277 | | /* Write a dynamically typed parameter to a list. */ |
278 | | static int |
279 | | c_param_write(gs_c_param_list * plist, gs_param_name pkey, void *pvalue, |
280 | | gs_param_type type) |
281 | 3.51M | { |
282 | 3.51M | unsigned top_level_sizeof = 0; |
283 | 3.51M | unsigned second_level_sizeof = 0; |
284 | 3.51M | gs_c_param *pparam = c_param_add(plist, pkey); |
285 | | |
286 | 3.51M | if (pparam == 0) |
287 | 0 | return_error(gs_error_VMerror); |
288 | 3.51M | memcpy(&pparam->value, pvalue, gs_param_type_sizes[(int)type]); |
289 | 3.51M | pparam->type = type; |
290 | | |
291 | | /* Need deeper copies of data if it's not persistent */ |
292 | 3.51M | switch (type) { |
293 | 0 | gs_param_string const *curr_string; |
294 | 0 | gs_param_string const *end_string; |
295 | | |
296 | 28.9k | case gs_param_type_string_array: |
297 | 28.9k | case gs_param_type_name_array: |
298 | | /* Determine how much mem needed to hold actual string data */ |
299 | 28.9k | curr_string = pparam->value.sa.data; |
300 | 28.9k | end_string = curr_string + pparam->value.sa.size; |
301 | 134k | for (; curr_string < end_string; ++curr_string) |
302 | 105k | if (!curr_string->persistent) |
303 | 105k | second_level_sizeof += curr_string->size; |
304 | | /* fall thru */ |
305 | | |
306 | 29.1k | case gs_param_type_string: |
307 | 29.1k | case gs_param_type_name: |
308 | 1.50M | case gs_param_type_int_array: |
309 | 1.50M | case gs_param_type_float_array: |
310 | 1.50M | if (!pparam->value.s.persistent) { /* Allocate & copy object pointed to by array or string */ |
311 | 1.50M | byte *top_level_memory = NULL; |
312 | | |
313 | 1.50M | top_level_sizeof = |
314 | 1.50M | pparam->value.s.size * gs_param_type_base_sizes[type]; |
315 | 1.50M | if (top_level_sizeof + second_level_sizeof > 0) { |
316 | 1.50M | top_level_memory = |
317 | 1.50M | gs_alloc_bytes_immovable(plist->memory, |
318 | 1.50M | top_level_sizeof + second_level_sizeof, |
319 | 1.50M | "c_param_write data"); |
320 | 1.50M | if (top_level_memory == 0) { |
321 | 0 | if (pparam->key.persistent == false) { |
322 | 0 | gs_free_string(plist->memory, (byte *)(pparam->key.data), |
323 | 0 | strlen((const char *)(pparam->key.data)), "c_param_add key"); |
324 | 0 | } |
325 | 0 | gs_free_object(plist->memory, pparam, "c_param_write entry"); |
326 | 0 | return_error(gs_error_VMerror); |
327 | 0 | } |
328 | 1.50M | memcpy(top_level_memory, pparam->value.s.data, top_level_sizeof); |
329 | 1.50M | } |
330 | 1.50M | pparam->value.s.data = top_level_memory; |
331 | | |
332 | | /* String/name arrays need to copy actual str data */ |
333 | | |
334 | 1.50M | if (second_level_sizeof > 0) { |
335 | 28.9k | byte *second_level_memory = |
336 | 28.9k | top_level_memory + top_level_sizeof; |
337 | | |
338 | 28.9k | curr_string = pparam->value.sa.data; |
339 | 28.9k | end_string = curr_string + pparam->value.sa.size; |
340 | 134k | for (; curr_string < end_string; ++curr_string) |
341 | 105k | if (!curr_string->persistent) { |
342 | 105k | memcpy(second_level_memory, |
343 | 105k | curr_string->data, curr_string->size); |
344 | 105k | ((gs_param_string *) curr_string)->data |
345 | 105k | = second_level_memory; |
346 | 105k | second_level_memory += curr_string->size; |
347 | 105k | } |
348 | 28.9k | } |
349 | 1.50M | } |
350 | 1.50M | break; |
351 | 2.00M | default: |
352 | 2.00M | break; |
353 | 3.51M | } |
354 | | |
355 | 3.51M | plist->head = pparam; |
356 | 3.51M | plist->count++; |
357 | 3.51M | return 0; |
358 | 3.51M | } |
359 | | |
360 | | /* Individual writing routines. */ |
361 | | static int |
362 | | c_param_begin_write_collection(gs_param_list * plist, gs_param_name pkey, |
363 | | gs_param_dict * pvalue, gs_param_collection_type_t coll_type) |
364 | 0 | { |
365 | 0 | gs_c_param_list *const cplist = (gs_c_param_list *)plist; |
366 | 0 | gs_c_param_list *dlist = |
367 | 0 | gs_c_param_list_alloc(cplist->memory, |
368 | 0 | "c_param_begin_write_collection"); |
369 | |
|
370 | 0 | if (dlist == 0) |
371 | 0 | return_error(gs_error_VMerror); |
372 | 0 | gs_c_param_list_write(dlist, cplist->memory); |
373 | 0 | dlist->coll_type = coll_type; |
374 | 0 | pvalue->list = (gs_param_list *) dlist; |
375 | 0 | return 0; |
376 | 0 | } |
377 | | static int |
378 | | c_param_end_write_collection(gs_param_list * plist, gs_param_name pkey, |
379 | | gs_param_dict * pvalue) |
380 | 0 | { |
381 | 0 | gs_c_param_list *const cplist = (gs_c_param_list *)plist; |
382 | 0 | gs_c_param_list *dlist = (gs_c_param_list *) pvalue->list; |
383 | 0 | int code; |
384 | |
|
385 | 0 | code = c_param_write(cplist, pkey, pvalue->list, |
386 | 0 | (dlist->coll_type == gs_param_collection_dict_int_keys ? |
387 | 0 | gs_param_type_dict_int_keys : |
388 | 0 | dlist->coll_type == gs_param_collection_array ? |
389 | 0 | gs_param_type_array : gs_param_type_dict)); |
390 | |
|
391 | 0 | gs_free_object(plist->memory, pvalue->list, "c_param_end_write_collection"); |
392 | 0 | pvalue->list = 0; |
393 | 0 | return code; |
394 | 0 | } |
395 | | static int |
396 | | c_param_write_typed(gs_param_list * plist, gs_param_name pkey, |
397 | | gs_param_typed_value * pvalue) |
398 | 3.51M | { |
399 | 3.51M | gs_c_param_list *const cplist = (gs_c_param_list *)plist; |
400 | 3.51M | gs_param_collection_type_t coll_type; |
401 | | |
402 | 3.51M | switch (pvalue->type) { |
403 | 0 | case gs_param_type_dict: |
404 | 0 | coll_type = gs_param_collection_dict_any; |
405 | 0 | break; |
406 | 0 | case gs_param_type_dict_int_keys: |
407 | 0 | coll_type = gs_param_collection_dict_int_keys; |
408 | 0 | break; |
409 | 0 | case gs_param_type_array: |
410 | 0 | coll_type = gs_param_collection_array; |
411 | 0 | break; |
412 | 3.51M | default: |
413 | 3.51M | return c_param_write(cplist, pkey, &pvalue->value, pvalue->type); |
414 | 3.51M | } |
415 | 0 | return c_param_begin_write_collection |
416 | 0 | (plist, pkey, &pvalue->value.d, coll_type); |
417 | 3.51M | } |
418 | | |
419 | | /* Other procedures */ |
420 | | |
421 | | static int |
422 | | c_param_request(gs_param_list * plist, gs_param_name pkey) |
423 | 0 | { |
424 | 0 | gs_c_param_list *const cplist = (gs_c_param_list *)plist; |
425 | 0 | gs_c_param *pparam; |
426 | |
|
427 | 0 | cplist->any_requested = true; |
428 | 0 | if (c_param_find(cplist, pkey, true)) |
429 | 0 | return 0; |
430 | 0 | pparam = c_param_add(cplist, pkey); |
431 | 0 | if (pparam == 0) |
432 | 0 | return_error(gs_error_VMerror); |
433 | 0 | pparam->type = gs_param_type_any; /* mark as undefined */ |
434 | 0 | cplist->head = pparam; |
435 | 0 | return 0; |
436 | 0 | } |
437 | | |
438 | | static int |
439 | | c_param_requested(const gs_param_list * plist, gs_param_name pkey) |
440 | 0 | { |
441 | 0 | const gs_c_param_list *const cplist = (const gs_c_param_list *)plist; |
442 | 0 | gs_param_list *target = cplist->target; |
443 | 0 | int code; |
444 | |
|
445 | 0 | if (!cplist->any_requested) |
446 | 0 | return (target ? param_requested(target, pkey) : -1); |
447 | 0 | if (c_param_find(cplist, pkey, true) != 0) |
448 | 0 | return 1; |
449 | 0 | if (!target) |
450 | 0 | return 0; |
451 | 0 | code = param_requested(target, pkey); |
452 | 0 | return (code < 0 ? 0 : 1); |
453 | 0 | } |
454 | | |
455 | | /* ---------------- Reading from a list to parameters ---------------- */ |
456 | | |
457 | | static param_proc_begin_xmit_collection(c_param_begin_read_collection); |
458 | | static param_proc_end_xmit_collection(c_param_end_read_collection); |
459 | | static param_proc_xmit_typed(c_param_read_typed); |
460 | | static param_proc_next_key(c_param_get_next_key); |
461 | | static param_proc_get_policy(c_param_read_get_policy); |
462 | | static param_proc_signal_error(c_param_read_signal_error); |
463 | | static param_proc_read_signalled_error(c_param_read_signalled_error); |
464 | | static param_proc_commit(c_param_read_commit); |
465 | | static const gs_param_list_procs c_read_procs = |
466 | | { |
467 | | c_param_read_typed, |
468 | | c_param_begin_read_collection, |
469 | | c_param_end_read_collection, |
470 | | c_param_get_next_key, |
471 | | NULL, /* request, N/A */ |
472 | | NULL, /* requested, N/A */ |
473 | | c_param_read_get_policy, |
474 | | c_param_read_signal_error, |
475 | | c_param_read_commit, |
476 | | c_param_read_signalled_error |
477 | | }; |
478 | | |
479 | | /* Switch a list from writing to reading. */ |
480 | | void |
481 | | gs_c_param_list_read(gs_c_param_list * plist) |
482 | 4.43M | { |
483 | 4.43M | plist->procs = &c_read_procs; |
484 | 4.43M | } |
485 | | |
486 | | /* Generic routine for reading a parameter from a list. */ |
487 | | |
488 | | static int |
489 | | c_param_read_typed(gs_param_list * plist, gs_param_name pkey, |
490 | | gs_param_typed_value * pvalue) |
491 | 15.7M | { |
492 | 15.7M | gs_c_param_list *const cplist = (gs_c_param_list *)plist; |
493 | 15.7M | gs_param_type req_type = pvalue->type; |
494 | 15.7M | gs_c_param *pparam = c_param_find(cplist, pkey, false); |
495 | 15.7M | int code; |
496 | | |
497 | 15.7M | if (pparam == 0) |
498 | 140k | return (cplist->target ? |
499 | 79.9k | param_read_typed(cplist->target, pkey, pvalue) : 1); |
500 | 15.5M | pvalue->type = pparam->type; |
501 | 15.5M | switch (pvalue->type) { |
502 | 0 | case gs_param_type_dict: |
503 | 0 | case gs_param_type_dict_int_keys: |
504 | 0 | case gs_param_type_array: |
505 | 0 | gs_c_param_list_read(&pparam->value.d); |
506 | 0 | pvalue->value.d.list = (gs_param_list *) & pparam->value.d; |
507 | 0 | pvalue->value.d.size = pparam->value.d.count; |
508 | 0 | return 0; |
509 | 15.5M | default: |
510 | 15.5M | break; |
511 | 15.5M | } |
512 | 15.5M | memcpy(&pvalue->value, &pparam->value, |
513 | 15.5M | gs_param_type_sizes[(int)pparam->type]); |
514 | 15.5M | code = param_coerce_typed(pvalue, req_type, NULL); |
515 | | /****** SHOULD LET param_coerce_typed DO THIS ******/ |
516 | 15.5M | if (code == gs_error_typecheck && |
517 | 15.5M | req_type == gs_param_type_float_array && |
518 | 15.5M | pvalue->type == gs_param_type_int_array |
519 | 15.5M | ) { |
520 | | /* Convert int array to float dest */ |
521 | 0 | gs_param_float_array fa; |
522 | 0 | int element; |
523 | |
|
524 | 0 | fa.size = pparam->value.ia.size; |
525 | 0 | fa.persistent = false; |
526 | |
|
527 | 0 | if (pparam->alternate_typed_data == 0) { |
528 | 0 | if ((pparam->alternate_typed_data |
529 | 0 | = (void *)gs_alloc_bytes_immovable(cplist->memory, |
530 | 0 | fa.size * sizeof(float), |
531 | 0 | "gs_c_param_read alternate float array")) == 0) |
532 | 0 | return_error(gs_error_VMerror); |
533 | | |
534 | 0 | for (element = 0; element < fa.size; ++element) |
535 | 0 | ((float *)(pparam->alternate_typed_data))[element] |
536 | 0 | = (float)pparam->value.ia.data[element]; |
537 | 0 | } |
538 | 0 | fa.data = (float *)pparam->alternate_typed_data; |
539 | |
|
540 | 0 | pvalue->value.fa = fa; |
541 | 0 | pvalue->type = req_type; |
542 | 0 | return 0; |
543 | 0 | } |
544 | 15.5M | return code; |
545 | 15.5M | } |
546 | | |
547 | | /* Individual reading routines. */ |
548 | | static int |
549 | | c_param_begin_read_collection(gs_param_list * plist, gs_param_name pkey, |
550 | | gs_param_dict * pvalue, gs_param_collection_type_t coll_type) |
551 | 24.6k | { |
552 | 24.6k | gs_c_param_list *const cplist = (gs_c_param_list *)plist; |
553 | 24.6k | gs_c_param *pparam = c_param_find(cplist, pkey, false); |
554 | | |
555 | 24.6k | if (pparam == 0) |
556 | 24.6k | return |
557 | 24.6k | (cplist->target ? |
558 | 12.3k | param_begin_read_collection(cplist->target, |
559 | 24.6k | pkey, pvalue, coll_type) : |
560 | 24.6k | 1); |
561 | 0 | switch (pparam->type) { |
562 | 0 | case gs_param_type_dict: |
563 | 0 | if (coll_type != gs_param_collection_dict_any) |
564 | 0 | return_error(gs_error_typecheck); |
565 | 0 | break; |
566 | 0 | case gs_param_type_dict_int_keys: |
567 | 0 | if (coll_type == gs_param_collection_array) |
568 | 0 | return_error(gs_error_typecheck); |
569 | 0 | break; |
570 | 0 | case gs_param_type_array: |
571 | 0 | break; |
572 | 0 | default: |
573 | 0 | return_error(gs_error_typecheck); |
574 | 0 | } |
575 | 0 | gs_c_param_list_read(&pparam->value.d); |
576 | 0 | pvalue->list = (gs_param_list *) & pparam->value.d; |
577 | 0 | pvalue->size = pparam->value.d.count; |
578 | 0 | return 0; |
579 | 0 | } |
580 | | static int |
581 | | c_param_end_read_collection(gs_param_list * plist, gs_param_name pkey, |
582 | | gs_param_dict * pvalue) |
583 | 0 | { |
584 | 0 | return 0; |
585 | 0 | } |
586 | | |
587 | | /* Other procedures */ |
588 | | static int /* ret 0 ok, 1 if EOF, or -ve err */ |
589 | | c_param_get_next_key(gs_param_list * plist, gs_param_enumerator_t * penum, |
590 | | gs_param_key_t * key) |
591 | 19.3M | { |
592 | 19.3M | gs_c_param_list *const cplist = (gs_c_param_list *)plist; |
593 | 19.3M | gs_c_param *pparam = |
594 | 19.3M | (penum->pvoid ? ((gs_c_param *) (penum->pvoid))->next : |
595 | 19.3M | cplist->head); |
596 | | |
597 | 19.3M | if (pparam == 0) |
598 | 4.12M | return 1; |
599 | 15.2M | penum->pvoid = pparam; |
600 | 15.2M | *key = pparam->key; |
601 | 15.2M | return 0; |
602 | 19.3M | } |
603 | | static int |
604 | | c_param_read_get_policy(gs_param_list * plist, gs_param_name pkey) |
605 | 0 | { |
606 | 0 | return gs_param_policy_ignore; |
607 | 0 | } |
608 | | static int |
609 | | c_param_read_signal_error(gs_param_list * plist, gs_param_name pkey, int code) |
610 | 5 | { |
611 | 5 | gs_c_param_list *const cplist = (gs_c_param_list *)plist; |
612 | 5 | gs_c_param *pparam = c_param_find(cplist, pkey, false); |
613 | | |
614 | 5 | if (pparam) |
615 | 5 | pparam->error = code; |
616 | | |
617 | 5 | return 0; |
618 | 5 | } |
619 | | static int |
620 | | c_param_read_commit(gs_param_list * plist) |
621 | 0 | { |
622 | 0 | return 0; |
623 | 0 | } |
624 | | static int |
625 | | c_param_read_signalled_error(gs_param_list * plist, gs_param_name pkey) |
626 | 0 | { |
627 | 0 | gs_c_param_list *const cplist = (gs_c_param_list *)plist; |
628 | 0 | gs_c_param *pparam = c_param_find(cplist, pkey, false); |
629 | |
|
630 | 0 | return (pparam ? pparam->error : 0); |
631 | 0 | } |