/src/ghostpdl/base/gsparam.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 | | /* Support for 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 | | /* GC procedures */ |
26 | 11.7M | ENUM_PTRS_WITH(gs_param_typed_value_enum_ptrs, gs_param_typed_value *pvalue) return 0; |
27 | 5.87M | case 0: |
28 | 5.87M | switch (pvalue->type) { |
29 | 0 | case gs_param_type_string: |
30 | 0 | return ENUM_STRING(&pvalue->value.s); |
31 | 0 | case gs_param_type_name: |
32 | 0 | return ENUM_STRING(&pvalue->value.n); |
33 | 2.71M | case gs_param_type_int_array: |
34 | 2.71M | return ENUM_OBJ(pvalue->value.ia.data); |
35 | 0 | case gs_param_type_float_array: |
36 | 0 | return ENUM_OBJ(pvalue->value.fa.data); |
37 | 0 | case gs_param_type_string_array: |
38 | 0 | return ENUM_OBJ(pvalue->value.sa.data); |
39 | 0 | case gs_param_type_name_array: |
40 | 0 | return ENUM_OBJ(pvalue->value.na.data); |
41 | 3.16M | default: |
42 | 3.16M | return ENUM_OBJ(0); /* don't stop early */ |
43 | 5.87M | } |
44 | 11.7M | ENUM_PTRS_END |
45 | 5.87M | RELOC_PTRS_WITH(gs_param_typed_value_reloc_ptrs, gs_param_typed_value *pvalue) { |
46 | 5.87M | switch (pvalue->type) { |
47 | 0 | case gs_param_type_string: |
48 | 0 | case gs_param_type_name: { |
49 | 0 | gs_const_string str; |
50 | |
|
51 | 0 | str.data = pvalue->value.s.data; /* n == s */ |
52 | 0 | str.size = pvalue->value.s.size; |
53 | 0 | RELOC_CONST_STRING_VAR(str); |
54 | 0 | pvalue->value.s.data = str.data; |
55 | 0 | break; |
56 | 0 | } |
57 | 2.71M | case gs_param_type_int_array: |
58 | 2.71M | RELOC_VAR(pvalue->value.ia.data); |
59 | 2.71M | break; |
60 | 0 | case gs_param_type_float_array: |
61 | 0 | RELOC_VAR(pvalue->value.fa.data); |
62 | 0 | break; |
63 | 0 | case gs_param_type_string_array: |
64 | 0 | RELOC_VAR(pvalue->value.sa.data); |
65 | 0 | break; |
66 | 0 | case gs_param_type_name_array: |
67 | 0 | RELOC_VAR(pvalue->value.na.data); |
68 | 0 | break; |
69 | 3.16M | default: |
70 | 3.16M | break; |
71 | 5.87M | } |
72 | 5.87M | } |
73 | 5.87M | RELOC_PTRS_END |
74 | | |
75 | | /* Internal procedure to initialize the common part of a parameter list. */ |
76 | | void |
77 | | gs_param_list_init(gs_param_list *plist, const gs_param_list_procs *procs, |
78 | | gs_memory_t *mem) |
79 | 25.3M | { |
80 | 25.3M | plist->procs = procs; |
81 | 25.3M | plist->memory = mem; |
82 | 25.3M | plist->persistent_keys = true; |
83 | 25.3M | } |
84 | | |
85 | | /* Set whether the keys for param_write_XXX are persistent. */ |
86 | | void |
87 | | gs_param_list_set_persistent_keys(gs_param_list *plist, bool persistent) |
88 | 18.4M | { |
89 | 18.4M | plist->persistent_keys = persistent; |
90 | 18.4M | } |
91 | | |
92 | | /* Reset a gs_param_key_t enumerator to its initial state */ |
93 | | void |
94 | | param_init_enumerator(gs_param_enumerator_t * enumerator) |
95 | 5.04M | { |
96 | 5.04M | memset(enumerator, 0, sizeof(*enumerator)); |
97 | 5.04M | } |
98 | | |
99 | | /* Transfer a collection of parameters. */ |
100 | | static const byte xfer_item_sizes[] = { |
101 | | GS_PARAM_TYPE_SIZES(0) |
102 | | }; |
103 | | int |
104 | | gs_param_read_items(gs_param_list * plist, void *obj, |
105 | | const gs_param_item_t * items, |
106 | | gs_memory_t *mem) |
107 | 2.94M | { |
108 | 2.94M | const gs_param_item_t *pi; |
109 | 2.94M | int ecode = 0; |
110 | | |
111 | 69.1M | for (pi = items; pi->key != 0; ++pi) { |
112 | 66.2M | const char *key = pi->key; |
113 | 66.2M | void *pvalue = (void *)((char *)obj + pi->offset); |
114 | 66.2M | gs_param_typed_value typed; |
115 | 66.2M | int code; |
116 | | |
117 | 66.2M | typed.type = pi->type; |
118 | 66.2M | code = param_read_requested_typed(plist, key, &typed); |
119 | 66.2M | switch (code) { |
120 | 0 | default: /* < 0 */ |
121 | 0 | ecode = code; |
122 | 56.0M | case 1: |
123 | 56.0M | break; |
124 | 10.1M | case 0: |
125 | 10.1M | if (typed.type != pi->type) /* shouldn't happen! */ |
126 | 0 | ecode = gs_note_error(gs_error_typecheck); |
127 | 10.1M | else { |
128 | 10.1M | switch(typed.type) |
129 | 10.1M | { |
130 | 0 | case gs_param_type_dict: |
131 | 0 | case gs_param_type_dict_int_keys: |
132 | 0 | case gs_param_type_array: |
133 | 0 | return_error(gs_error_rangecheck); |
134 | 108k | case gs_param_type_string: |
135 | 108k | case gs_param_type_name: |
136 | 108k | { |
137 | 108k | void *copy; |
138 | 108k | gs_string *s; |
139 | 108k | if (mem == NULL) { |
140 | | /* Return pointers to the data in the param list. This |
141 | | * means that if the caller wants to keep it around it |
142 | | * needs to copy it itself, or run the risk of the |
143 | | * param list going away. */ |
144 | 0 | goto copy_pointer; |
145 | 0 | } |
146 | | /* Free any existing data before copying into it. */ |
147 | 108k | s = ((gs_string *)pvalue); |
148 | 108k | if (typed.value.s.size != s->size) { |
149 | 0 | gs_free_string(mem, s->data, s->size, "gs_param_read_items"); |
150 | 0 | s->data = NULL; |
151 | 0 | s->size = 0; |
152 | 0 | copy = gs_alloc_string(mem, typed.value.s.size, "gs_param_read_items"); |
153 | 0 | if (copy == NULL) |
154 | 0 | return_error(gs_error_VMerror); |
155 | 0 | s->size = typed.value.s.size; |
156 | 108k | } else { |
157 | 108k | copy = s->data; |
158 | 108k | } |
159 | 108k | if (typed.value.s.size > 0) |
160 | 0 | memcpy(copy, typed.value.s.data, typed.value.s.size); |
161 | 108k | s->data = copy; |
162 | 108k | ((gs_param_string *)pvalue)->persistent = 0; /* 0 => We own this copy */ |
163 | 108k | break; |
164 | 108k | } |
165 | 0 | case gs_param_type_int_array: |
166 | 368k | case gs_param_type_float_array: |
167 | 368k | case gs_param_type_string_array: |
168 | 368k | case gs_param_type_name_array: |
169 | 368k | { |
170 | 368k | int eltsize; |
171 | 368k | gs_param_string_array *sa; |
172 | 368k | if (mem == NULL) { |
173 | | /* Return pointers to the data in the param list. This |
174 | | * means that if the caller wants to keep it around it |
175 | | * needs to copy it itself, or run the risk of the |
176 | | * param list going away. */ |
177 | 0 | goto copy_pointer; |
178 | 0 | } |
179 | | /* Free any existing data before copying into it. */ |
180 | 368k | eltsize = gs_param_type_base_sizes[typed.type]; |
181 | 368k | sa = ((gs_param_string_array *)pvalue); |
182 | 368k | if (typed.value.ia.size != sa->size) { |
183 | 324k | void *copy; |
184 | 324k | if (typed.type == gs_param_type_name_array || |
185 | 324k | typed.type == gs_param_type_string_array) { |
186 | | /* Free the strings. */ |
187 | 0 | int i; |
188 | 0 | gs_param_string *arr; |
189 | 0 | union { const gs_param_string *cs; gs_param_string *s; } u; |
190 | 0 | u.cs = sa->data; |
191 | 0 | arr = u.s; /* Hideous dodge to avoid the const. */ |
192 | 0 | for (i = 0; i < typed.value.sa.size; i++) { |
193 | | /* Hideous hackery to get around the const nature of gs_param_strings. */ |
194 | 0 | gs_string *arr_non_const = (gs_string *)(void *)(&arr[i]); |
195 | 0 | if (arr[i].persistent == 0) |
196 | 0 | gs_free_string(mem, arr_non_const->data, arr_non_const->size, "gs_param_read_items"); |
197 | 0 | arr_non_const->data = NULL; |
198 | 0 | arr_non_const->size = 0; |
199 | 0 | } |
200 | 0 | } |
201 | 324k | gs_free_const_object(mem, sa->data, "gs_param_read_items"); |
202 | 324k | sa->data = NULL; |
203 | 324k | sa->size = 0; |
204 | 324k | copy = gs_alloc_bytes(mem, eltsize * typed.value.s.size, "gs_param_read_items"); |
205 | 324k | if (copy == NULL) |
206 | 0 | return_error(gs_error_VMerror); |
207 | 324k | memset(copy, 0, eltsize * typed.value.s.size); |
208 | 324k | sa->size = typed.value.s.size; |
209 | 324k | sa->data = copy; |
210 | 324k | } |
211 | | /* Now copy the elements of the arrays. */ |
212 | 368k | if (typed.type == gs_param_type_name_array || |
213 | 368k | typed.type == gs_param_type_string_array) { |
214 | | /* Free the strings. */ |
215 | 0 | int i; |
216 | 0 | const gs_param_string *src = typed.value.sa.data; |
217 | 0 | gs_param_string *dst; |
218 | 0 | union { const gs_param_string *cs; gs_param_string *s; } u; |
219 | 0 | u.cs = sa->data; |
220 | 0 | dst = u.s; /* Hideous dodge to avoid the const. */ |
221 | 0 | for (i = 0; i < typed.value.sa.size; i++) { |
222 | | /* Hideous hackery to get around the const nature of gs_param_strings. */ |
223 | 0 | gs_string *dst_non_const = (gs_string *)(void *)(&dst[i]); |
224 | 0 | if (dst[i].persistent == 0) |
225 | 0 | gs_free_string(mem, dst_non_const->data, dst_non_const->size, "gs_param_read_items"); |
226 | 0 | dst_non_const->data = NULL; |
227 | 0 | dst_non_const->size = 0; |
228 | 0 | } |
229 | | /* Copy values */ |
230 | 0 | for (i = 0; i < sa->size; i++) { |
231 | 0 | dst[i].data = gs_alloc_string(mem, src[i].size, "gs_param_read_items"); |
232 | 0 | if (dst[i].data == NULL) |
233 | 0 | return_error(gs_error_VMerror); |
234 | 0 | dst[i].size = src[i].size; |
235 | 0 | dst[i].persistent = 0; /* 0 => We own this copy */ |
236 | 0 | } |
237 | 368k | } else { |
238 | | /* Hideous hackery to get around the const nature of gs_param_strings. */ |
239 | 368k | gs_string *s = (gs_string *)(void *)sa; |
240 | 368k | if (typed.value.s.size > 0) |
241 | 368k | memcpy(s->data, typed.value.s.data, eltsize * typed.value.s.size); |
242 | 368k | } |
243 | 368k | ((gs_param_string *)pvalue)->persistent = 0; /* 0 => We own this copy */ |
244 | 368k | break; |
245 | 368k | } |
246 | 9.68M | default: |
247 | 9.68M | copy_pointer: |
248 | 9.68M | memcpy(pvalue, &typed.value, xfer_item_sizes[pi->type]); |
249 | 10.1M | } |
250 | 10.1M | } |
251 | 66.2M | } |
252 | 66.2M | } |
253 | 2.94M | return ecode; |
254 | 2.94M | } |
255 | | int |
256 | | gs_param_write_items(gs_param_list * plist, const void *obj, |
257 | | const void *default_obj, const gs_param_item_t * items) |
258 | 5.00M | { |
259 | 5.00M | const gs_param_item_t *pi; |
260 | 5.00M | int ecode = 0; |
261 | | |
262 | 115M | for (pi = items; pi->key != 0; ++pi) { |
263 | 110M | const char *key = pi->key; |
264 | 110M | const void *pvalue = (const void *)((const char *)obj + pi->offset); |
265 | 110M | int size = xfer_item_sizes[pi->type]; |
266 | 110M | gs_param_typed_value typed; |
267 | 110M | int code; |
268 | | |
269 | 110M | if (default_obj != 0 && |
270 | 110M | !memcmp((const void *)((const char *)default_obj + pi->offset), |
271 | 1.83M | pvalue, size) |
272 | 110M | ) |
273 | 1.37M | continue; |
274 | 109M | if (size > 0) |
275 | 109M | memcpy(&typed.value, pvalue, size); |
276 | 109M | typed.type = pi->type; |
277 | | /* Ensure the list doesn't end up keeping a pointer to our values. */ |
278 | 109M | typed.value.s.persistent = 0; |
279 | 109M | code = (*plist->procs->xmit_typed) (plist, key, &typed); |
280 | 109M | if (code < 0) |
281 | 0 | ecode = code; |
282 | 109M | } |
283 | 5.00M | return ecode; |
284 | 5.00M | } |
285 | | |
286 | | /* Read a value, with coercion if requested, needed, and possible. */ |
287 | | /* If mem != 0, we can coerce int arrays to float arrays. */ |
288 | | int |
289 | | param_coerce_typed(gs_param_typed_value * pvalue, gs_param_type req_type, |
290 | | gs_memory_t * mem) |
291 | 77.7M | { |
292 | 77.7M | if (req_type == gs_param_type_any || pvalue->type == req_type) |
293 | 58.2M | return 0; |
294 | | /* |
295 | | * Look for coercion opportunities. It would be wonderful if we |
296 | | * could convert int/float arrays and name/string arrays, but |
297 | | * right now we can't. However, a 0-length heterogenous array |
298 | | * will satisfy a request for any specific type. |
299 | | */ |
300 | | /* Strictly speaking assigning one element of union |
301 | | * to another, overlapping element of a different size is |
302 | | * undefined behavior, hence assign to intermediate variables |
303 | | */ |
304 | 19.4M | switch (pvalue->type /* actual type */ ) { |
305 | 0 | case gs_param_type_int: |
306 | 0 | switch (req_type) { |
307 | 0 | case gs_param_type_i64: |
308 | 0 | { |
309 | 0 | int64_t i64 = (int64_t)pvalue->value.i; |
310 | 0 | pvalue->value.i64 = i64; |
311 | 0 | goto ok; |
312 | 0 | } |
313 | 0 | case gs_param_type_size_t: |
314 | 0 | { |
315 | 0 | size_t z = (size_t)pvalue->value.i; |
316 | 0 | if (pvalue->value.i < 0) |
317 | 0 | return gs_error_rangecheck; |
318 | 0 | pvalue->value.z = z; |
319 | 0 | goto ok; |
320 | 0 | } |
321 | 0 | case gs_param_type_long: |
322 | 0 | { |
323 | 0 | long l = (long)pvalue->value.i; |
324 | 0 | pvalue->value.l = l; |
325 | 0 | goto ok; |
326 | 0 | } |
327 | 0 | case gs_param_type_float: |
328 | 0 | { |
329 | 0 | float fl = (float)pvalue->value.i; |
330 | 0 | pvalue->value.f = fl; |
331 | 0 | goto ok; |
332 | 0 | } |
333 | 0 | default: |
334 | 0 | break; |
335 | 0 | } |
336 | 0 | break; |
337 | 0 | case gs_param_type_long: |
338 | 0 | switch (req_type) { |
339 | 0 | case gs_param_type_i64: |
340 | 0 | { |
341 | 0 | int64_t i64 = (int64_t)pvalue->value.l; |
342 | 0 | pvalue->value.i64 = i64; |
343 | 0 | goto ok; |
344 | 0 | } |
345 | 0 | case gs_param_type_size_t: |
346 | 0 | { |
347 | 0 | size_t z = (size_t)pvalue->value.l; |
348 | 0 | if (pvalue->value.l < 0 |
349 | | #if ARCH_SIZEOF_SIZE_T < ARCH_SIZEOF_LONG |
350 | | || pvalue->value.l != (long)z |
351 | | #endif |
352 | 0 | ) |
353 | 0 | return_error(gs_error_rangecheck); |
354 | 0 | pvalue->value.z = z; |
355 | 0 | goto ok; |
356 | 0 | } |
357 | 0 | case gs_param_type_int: |
358 | 0 | { |
359 | 0 | int int1 = (int)pvalue->value.l; |
360 | 0 | #if ARCH_SIZEOF_INT < ARCH_SIZEOF_LONG |
361 | 0 | if (pvalue->value.l != (long)int1) |
362 | 0 | return_error(gs_error_rangecheck); |
363 | 0 | #endif |
364 | 0 | pvalue->value.i = int1; |
365 | 0 | goto ok; |
366 | 0 | } |
367 | 0 | case gs_param_type_float: |
368 | 0 | { |
369 | 0 | float fl = (float)pvalue->value.l; |
370 | 0 | pvalue->value.f = fl; |
371 | 0 | goto ok; |
372 | 0 | } |
373 | 0 | default: |
374 | 0 | break; |
375 | 0 | } |
376 | 0 | break; |
377 | 15.3M | case gs_param_type_i64: |
378 | 15.3M | switch (req_type) { |
379 | 1.42M | case gs_param_type_size_t: |
380 | 1.42M | { |
381 | 1.42M | size_t z = (size_t)pvalue->value.i64; |
382 | 1.42M | if (pvalue->value.i64 < 0 |
383 | | #if ARCH_SIZEOF_SIZE_T < 8 /* sizeof(int64_t) */ |
384 | | || pvalue->value.i64 != (int64_t)z |
385 | | #endif |
386 | 1.42M | ) |
387 | 0 | return_error(gs_error_rangecheck); |
388 | 1.42M | pvalue->value.z = z; |
389 | 1.42M | goto ok; |
390 | 1.42M | } |
391 | 7.53M | case gs_param_type_long: |
392 | 7.53M | { |
393 | 7.53M | long l = (long)pvalue->value.i64; |
394 | | #if ARCH_SIZEOF_LONG < 8 /* sizeof(int64_t) */ |
395 | | if (pvalue->value.i64 != (int64_t)l) |
396 | | return_error(gs_error_rangecheck); |
397 | | #endif |
398 | 7.53M | pvalue->value.l = l; |
399 | 7.53M | goto ok; |
400 | 1.42M | } |
401 | 6.39M | case gs_param_type_int: |
402 | 6.39M | { |
403 | 6.39M | int int1 = (int)pvalue->value.i64; |
404 | 6.39M | #if ARCH_SIZEOF_INT < 8 /* sizeof(int64_t) */ |
405 | 6.39M | if (pvalue->value.i64 != (int64_t)int1) |
406 | 0 | return_error(gs_error_rangecheck); |
407 | 6.39M | #endif |
408 | 6.39M | pvalue->value.i = int1; |
409 | 6.39M | goto ok; |
410 | 6.39M | } |
411 | 8.72k | case gs_param_type_float: |
412 | 8.72k | { |
413 | 8.72k | float fl = (float)pvalue->value.i64; |
414 | 8.72k | pvalue->value.f = fl; |
415 | 8.72k | goto ok; |
416 | 6.39M | } |
417 | 0 | default: |
418 | 0 | break; |
419 | 15.3M | } |
420 | 0 | break; |
421 | 0 | case gs_param_type_size_t: |
422 | 0 | switch (req_type) { |
423 | 0 | case gs_param_type_i64: |
424 | 0 | { |
425 | 0 | int64_t i64 = (int64_t)pvalue->value.z; |
426 | 0 | if (i64 < 0 |
427 | | #if 8 /* sizeof(int64_t) */ < ARCH_SIZEOF_SIZE_T |
428 | | /* Unlikely, but let's plan for the day when we need 128bit addressing :) */ |
429 | | || pvalue->value.z != (size_t)i64 |
430 | | #endif |
431 | 0 | ) |
432 | 0 | return_error(gs_error_rangecheck); |
433 | 0 | pvalue->value.i64 = i64; |
434 | 0 | goto ok; |
435 | 0 | } |
436 | 0 | case gs_param_type_long: |
437 | 0 | { |
438 | 0 | long l = (long)pvalue->value.z; |
439 | | #if ARCH_SIZEOF_LONG < 8 /* sizeof(int64_t) */ |
440 | | if (pvalue->value.z != (size_t)l) |
441 | | return_error(gs_error_rangecheck); |
442 | | #endif |
443 | 0 | pvalue->value.l = l; |
444 | 0 | goto ok; |
445 | 0 | } |
446 | 0 | case gs_param_type_int: |
447 | 0 | { |
448 | 0 | int int1 = (int)pvalue->value.z; |
449 | 0 | #if ARCH_SIZEOF_INT < 8 /* sizeof(int64_t) */ |
450 | 0 | if (pvalue->value.z != (size_t)int1) |
451 | 0 | return_error(gs_error_rangecheck); |
452 | 0 | #endif |
453 | 0 | pvalue->value.i = int1; |
454 | 0 | goto ok; |
455 | 0 | } |
456 | 0 | case gs_param_type_float: |
457 | 0 | { |
458 | 0 | float fl = (float)pvalue->value.z; |
459 | 0 | pvalue->value.f = fl; |
460 | 0 | goto ok; |
461 | 0 | } |
462 | 0 | default: |
463 | 0 | break; |
464 | 0 | } |
465 | 0 | break; |
466 | 1 | case gs_param_type_string: |
467 | 1 | if (req_type == gs_param_type_name) |
468 | 0 | goto ok; |
469 | 1 | break; |
470 | 2.20M | case gs_param_type_name: |
471 | 2.20M | if (req_type == gs_param_type_string) |
472 | 2.20M | goto ok; |
473 | 3 | break; |
474 | 337k | case gs_param_type_int_array: |
475 | 337k | switch (req_type) { |
476 | 324k | case gs_param_type_float_array:{ |
477 | 324k | uint size = pvalue->value.ia.size; |
478 | 324k | float *fv; |
479 | 324k | uint i; |
480 | | |
481 | 324k | if (mem == 0) |
482 | 0 | break; |
483 | 324k | fv = (float *)gs_alloc_byte_array(mem, size, sizeof(float), |
484 | 324k | "int array => float array"); |
485 | | |
486 | 324k | if (fv == 0) |
487 | 0 | return_error(gs_error_VMerror); |
488 | 1.62M | for (i = 0; i < size; ++i) |
489 | 1.29M | fv[i] = (float)pvalue->value.ia.data[i]; |
490 | 324k | pvalue->value.fa.data = fv; |
491 | 324k | pvalue->value.fa.persistent = false; |
492 | 324k | goto ok; |
493 | 324k | } |
494 | 12.3k | default: |
495 | 12.3k | break; |
496 | 337k | } |
497 | 12.3k | break; |
498 | 12.3k | case gs_param_type_string_array: |
499 | 0 | if (req_type == gs_param_type_name_array) |
500 | 0 | goto ok; |
501 | 0 | break; |
502 | 20.4k | case gs_param_type_name_array: |
503 | 20.4k | if (req_type == gs_param_type_string_array) |
504 | 20.4k | goto ok; |
505 | 0 | break; |
506 | 1.35M | case gs_param_type_array: |
507 | 1.35M | if (pvalue->value.d.size == 0 && |
508 | 1.35M | (req_type == gs_param_type_int_array || |
509 | 1.35M | req_type == gs_param_type_float_array || |
510 | 1.35M | req_type == gs_param_type_string_array || |
511 | 1.35M | req_type == gs_param_type_name_array) |
512 | 1.35M | ) |
513 | 1.35M | goto ok; |
514 | 0 | break; |
515 | 188k | default: |
516 | 188k | break; |
517 | 19.4M | } |
518 | 19.4M | return_error(gs_error_typecheck); |
519 | 19.2M | ok:pvalue->type = req_type; |
520 | 19.2M | return 0; |
521 | 19.4M | } |
522 | | int |
523 | | param_read_requested_typed(gs_param_list * plist, gs_param_name pkey, |
524 | | gs_param_typed_value * pvalue) |
525 | 398M | { |
526 | 398M | gs_param_type req_type = pvalue->type; |
527 | 398M | int code = (*plist->procs->xmit_typed) (plist, pkey, pvalue); |
528 | | |
529 | 398M | if (code != 0) |
530 | 336M | return code; |
531 | 62.1M | return param_coerce_typed(pvalue, req_type, plist->memory); |
532 | 398M | } |
533 | | |
534 | | /* ---------------- Fixed-type reading procedures ---------------- */ |
535 | | |
536 | | #define RETURN_READ_TYPED(alt, ptype)\ |
537 | 313M | gs_param_typed_value typed;\ |
538 | 313M | int code;\ |
539 | 313M | \ |
540 | 313M | typed.type = ptype;\ |
541 | 313M | code = param_read_requested_typed(plist, pkey, &typed);\ |
542 | 313M | if ( code == 0 )\ |
543 | 313M | *pvalue = typed.value.alt;\ |
544 | 313M | return code |
545 | | |
546 | | int |
547 | | param_read_null(gs_param_list * plist, gs_param_name pkey) |
548 | 188k | { |
549 | 188k | gs_param_typed_value typed; |
550 | | |
551 | 188k | typed.type = gs_param_type_null; |
552 | 188k | return param_read_requested_typed(plist, pkey, &typed); |
553 | 188k | } |
554 | | int |
555 | | param_read_bool(gs_param_list * plist, gs_param_name pkey, bool * pvalue) |
556 | 59.7M | { |
557 | 59.7M | RETURN_READ_TYPED(b, gs_param_type_bool); |
558 | 59.7M | } |
559 | | int |
560 | | param_read_int(gs_param_list * plist, gs_param_name pkey, int *pvalue) |
561 | 58.0M | { |
562 | 58.0M | RETURN_READ_TYPED(i, gs_param_type_int); |
563 | 58.0M | } |
564 | | int |
565 | | param_read_long(gs_param_list * plist, gs_param_name pkey, long *pvalue) |
566 | 60.3M | { |
567 | 60.3M | RETURN_READ_TYPED(l, gs_param_type_long); |
568 | 60.3M | } |
569 | | int |
570 | | param_read_i64(gs_param_list * plist, gs_param_name pkey, int64_t *pvalue) |
571 | 4.44M | { |
572 | 4.44M | RETURN_READ_TYPED(i64, gs_param_type_i64); |
573 | 4.44M | } |
574 | | int |
575 | | param_read_size_t(gs_param_list * plist, gs_param_name pkey, size_t *pvalue) |
576 | 10.7M | { |
577 | 10.7M | RETURN_READ_TYPED(z, gs_param_type_size_t); |
578 | 10.7M | } |
579 | | int |
580 | | param_read_float(gs_param_list * plist, gs_param_name pkey, float *pvalue) |
581 | 10.2M | { |
582 | 10.2M | RETURN_READ_TYPED(f, gs_param_type_float); |
583 | 10.2M | } |
584 | | int |
585 | | param_read_string(gs_param_list * plist, gs_param_name pkey, |
586 | | gs_param_string * pvalue) |
587 | 78.1M | { |
588 | 78.1M | RETURN_READ_TYPED(s, gs_param_type_string); |
589 | 78.1M | } |
590 | | int |
591 | | param_read_name(gs_param_list * plist, gs_param_name pkey, |
592 | | gs_param_string * pvalue) |
593 | 8.02M | { |
594 | 8.02M | RETURN_READ_TYPED(n, gs_param_type_string); |
595 | 8.02M | } |
596 | | int |
597 | | param_read_int_array(gs_param_list * plist, gs_param_name pkey, |
598 | | gs_param_int_array * pvalue) |
599 | 1.87M | { |
600 | 1.87M | RETURN_READ_TYPED(ia, gs_param_type_int_array); |
601 | 1.87M | } |
602 | | int |
603 | | param_read_float_array(gs_param_list * plist, gs_param_name pkey, |
604 | | gs_param_float_array * pvalue) |
605 | 11.0M | { |
606 | 11.0M | RETURN_READ_TYPED(fa, gs_param_type_float_array); |
607 | 11.0M | } |
608 | | int |
609 | | param_read_string_array(gs_param_list * plist, gs_param_name pkey, |
610 | | gs_param_string_array * pvalue) |
611 | 1.31M | { |
612 | 1.31M | RETURN_READ_TYPED(sa, gs_param_type_string_array); |
613 | 1.31M | } |
614 | | int |
615 | | param_read_name_array(gs_param_list * plist, gs_param_name pkey, |
616 | | gs_param_string_array * pvalue) |
617 | 9.47M | { |
618 | 9.47M | RETURN_READ_TYPED(na, gs_param_type_name_array); |
619 | 9.47M | } |
620 | | |
621 | | #undef RETURN_READ_TYPED |
622 | | |
623 | | /* ---------------- Default writing procedures ---------------- */ |
624 | | |
625 | | #define RETURN_WRITE_TYPED(alt, ptype)\ |
626 | 484M | gs_param_typed_value typed;\ |
627 | 484M | \ |
628 | 484M | typed.value.alt = *pvalue;\ |
629 | 484M | typed.type = ptype;\ |
630 | 484M | return param_write_typed(plist, pkey, &typed) |
631 | | |
632 | | int |
633 | | param_write_null(gs_param_list * plist, gs_param_name pkey) |
634 | 12.1M | { |
635 | 12.1M | gs_param_typed_value typed; |
636 | | |
637 | 12.1M | typed.type = gs_param_type_null; |
638 | 12.1M | return param_write_typed(plist, pkey, &typed); |
639 | 12.1M | } |
640 | | int |
641 | | param_write_bool(gs_param_list * plist, gs_param_name pkey, const bool * pvalue) |
642 | 104M | { |
643 | 104M | RETURN_WRITE_TYPED(b, gs_param_type_bool); |
644 | 104M | } |
645 | | int |
646 | | param_write_int(gs_param_list * plist, gs_param_name pkey, const int *pvalue) |
647 | 150M | { |
648 | 150M | RETURN_WRITE_TYPED(i, gs_param_type_int); |
649 | 150M | } |
650 | | int |
651 | | param_write_long(gs_param_list * plist, gs_param_name pkey, const long *pvalue) |
652 | 18.9M | { |
653 | 18.9M | RETURN_WRITE_TYPED(l, gs_param_type_long); |
654 | 18.9M | } |
655 | | int |
656 | | param_write_i64(gs_param_list * plist, gs_param_name pkey, const int64_t *pvalue) |
657 | 812k | { |
658 | 812k | RETURN_WRITE_TYPED(i64, gs_param_type_i64); |
659 | 812k | } |
660 | | int |
661 | | param_write_size_t(gs_param_list * plist, gs_param_name pkey, const size_t *pvalue) |
662 | 17.6M | { |
663 | 17.6M | RETURN_WRITE_TYPED(z, gs_param_type_size_t); |
664 | 17.6M | } |
665 | | int |
666 | | param_write_float(gs_param_list * plist, gs_param_name pkey, |
667 | | const float *pvalue) |
668 | 29.3M | { |
669 | 29.3M | RETURN_WRITE_TYPED(f, gs_param_type_float); |
670 | 29.3M | } |
671 | | int |
672 | | param_write_string(gs_param_list * plist, gs_param_name pkey, |
673 | | const gs_param_string * pvalue) |
674 | 97.2M | { |
675 | 97.2M | RETURN_WRITE_TYPED(s, gs_param_type_string); |
676 | 97.2M | } |
677 | | int |
678 | | param_write_name(gs_param_list * plist, gs_param_name pkey, |
679 | | const gs_param_string * pvalue) |
680 | 25.2M | { |
681 | 25.2M | RETURN_WRITE_TYPED(n, gs_param_type_name); |
682 | 25.2M | } |
683 | | int |
684 | | param_write_int_array(gs_param_list * plist, gs_param_name pkey, |
685 | | const gs_param_int_array * pvalue) |
686 | 4.54M | { |
687 | 4.54M | RETURN_WRITE_TYPED(ia, gs_param_type_int_array); |
688 | 4.54M | } |
689 | | int |
690 | | param_write_int_values(gs_param_list * plist, gs_param_name pkey, |
691 | | const int *values, uint size, bool persistent) |
692 | 17.4k | { |
693 | 17.4k | gs_param_int_array ia; |
694 | | |
695 | 17.4k | ia.data = values, ia.size = size, ia.persistent = persistent; |
696 | 17.4k | return param_write_int_array(plist, pkey, &ia); |
697 | 17.4k | } |
698 | | int |
699 | | param_write_float_array(gs_param_list * plist, gs_param_name pkey, |
700 | | const gs_param_float_array * pvalue) |
701 | 20.7M | { |
702 | 20.7M | RETURN_WRITE_TYPED(fa, gs_param_type_float_array); |
703 | 20.7M | } |
704 | | int |
705 | | param_write_float_values(gs_param_list * plist, gs_param_name pkey, |
706 | | const float *values, uint size, bool persistent) |
707 | 42.3k | { |
708 | 42.3k | gs_param_float_array fa; |
709 | | |
710 | 42.3k | fa.data = values, fa.size = size, fa.persistent = persistent; |
711 | 42.3k | return param_write_float_array(plist, pkey, &fa); |
712 | 42.3k | } |
713 | | int |
714 | | param_write_string_array(gs_param_list * plist, gs_param_name pkey, |
715 | | const gs_param_string_array * pvalue) |
716 | 990k | { |
717 | 990k | RETURN_WRITE_TYPED(sa, gs_param_type_string_array); |
718 | 990k | } |
719 | | int |
720 | | param_write_name_array(gs_param_list * plist, gs_param_name pkey, |
721 | | const gs_param_string_array * pvalue) |
722 | 12.6M | { |
723 | 12.6M | RETURN_WRITE_TYPED(na, gs_param_type_name_array); |
724 | 12.6M | } |
725 | | |
726 | | #undef RETURN_WRITE_TYPED |
727 | | |
728 | | /* ---------------- Default request implementation ---------------- */ |
729 | | |
730 | | int |
731 | | gs_param_request_default(gs_param_list * plist, gs_param_name pkey) |
732 | 0 | { |
733 | 0 | return 0; |
734 | 0 | } |
735 | | |
736 | | int |
737 | | gs_param_requested_default(const gs_param_list * plist, gs_param_name pkey) |
738 | 0 | { |
739 | 0 | return -1; /* requested by default */ |
740 | 0 | } |