56
56
/* GC descriptor and procedures */
57
57
gs_private_st_composite(st_c_param, gs_c_param, "gs_c_param",
58
c_param_enum_ptrs, c_param_reloc_ptrs);
58
c_param_enum_ptrs, c_param_reloc_ptrs);
59
59
ENUM_PTRS_WITH(c_param_enum_ptrs, gs_c_param *param) {
61
61
switch (param->type) {
62
/* Only the aggregate types are handled specially. */
62
/* Only the aggregate types are handled specially. */
63
63
case gs_param_type_dict:
64
64
case gs_param_type_dict_int_keys:
65
65
case gs_param_type_array:
66
return ENUM_USING(st_c_param_list, ¶m->value.d,
67
sizeof(param->value.d), index);
66
return ENUM_USING(st_c_param_list, ¶m->value.d,
67
sizeof(param->value.d), index);
69
gs_param_typed_value value;
69
gs_param_typed_value value;
71
value.value = *(const gs_param_value *)¶m->value;
72
value.type = param->type;
73
return gs_param_typed_value_enum_ptrs(mem, &value, sizeof(value), index,
71
value.value = *(const gs_param_value *)¶m->value;
72
value.type = param->type;
73
return gs_param_typed_value_enum_ptrs(mem, &value, sizeof(value), index,
79
79
case 1: return ENUM_OBJ(param->alternate_typed_data);
81
81
if (!param->key.persistent) {
84
key.data = param->key.data;
85
key.size = param->key.size;
86
return ENUM_STRING(&key);
84
key.data = param->key.data;
85
key.size = param->key.size;
86
return ENUM_STRING(&key);
88
return ENUM_OBJ(0); /* keep going */
88
return ENUM_OBJ(0); /* keep going */
90
90
RELOC_PTRS_WITH(c_param_reloc_ptrs, gs_c_param *param) {
91
91
RELOC_VAR(param->next);
92
92
RELOC_VAR(param->alternate_typed_data);
93
93
if (!param->key.persistent) {
96
key.data = param->key.data;
97
key.size = param->key.size;
98
RELOC_CONST_STRING_VAR(key);
99
param->key.data = key.data;
96
key.data = param->key.data;
97
key.size = param->key.size;
98
RELOC_CONST_STRING_VAR(key);
99
param->key.data = key.data;
101
101
switch (param->type) {
102
/* Only the aggregate types are handled specially. */
102
/* Only the aggregate types are handled specially. */
103
103
case gs_param_type_dict:
104
104
case gs_param_type_dict_int_keys:
105
105
case gs_param_type_array:
106
RELOC_USING(st_c_param_list, ¶m->value.d, sizeof(param->value.d));
106
RELOC_USING(st_c_param_list, ¶m->value.d, sizeof(param->value.d));
109
gs_param_typed_value value;
109
gs_param_typed_value value;
111
value.value = *(gs_param_value *)¶m->value;
112
value.type = param->type;
113
gs_param_typed_value_reloc_ptrs(&value, sizeof(value), NULL, gcst);
114
*(gs_param_value *)¶m->value = value.value;
111
value.value = *(gs_param_value *)¶m->value;
112
value.type = param->type;
113
gs_param_typed_value_reloc_ptrs(&value, sizeof(value), NULL, gcst);
114
*(gs_param_value *)¶m->value = value.value;
191
191
gs_c_param *pparam;
193
193
while ((pparam = plist->head) != 0) {
194
gs_c_param *next = pparam->next;
194
gs_c_param *next = pparam->next;
196
switch (pparam->type) {
197
case gs_param_type_dict:
198
case gs_param_type_dict_int_keys:
199
case gs_param_type_array:
200
gs_c_param_list_release(&pparam->value.d);
202
case gs_param_type_string:
203
case gs_param_type_name:
204
case gs_param_type_int_array:
205
case gs_param_type_float_array:
206
case gs_param_type_string_array:
207
case gs_param_type_name_array:
208
if (!pparam->value.s.persistent)
209
gs_free_const_object(mem, pparam->value.s.data,
210
"gs_c_param_list_release data");
215
if (pparam->free_key) {
216
/* We allocated this, so we must free it. */
217
gs_free_const_string(mem, pparam->key.data, pparam->key.size,
218
"gs_c_param_list_release key");
220
gs_free_object(mem, pparam->alternate_typed_data,
221
"gs_c_param_list_release alternate data");
222
gs_free_object(mem, pparam,
223
"gs_c_param_list_release entry");
196
switch (pparam->type) {
197
case gs_param_type_dict:
198
case gs_param_type_dict_int_keys:
199
case gs_param_type_array:
200
gs_c_param_list_release(&pparam->value.d);
202
case gs_param_type_string:
203
case gs_param_type_name:
204
case gs_param_type_int_array:
205
case gs_param_type_float_array:
206
case gs_param_type_string_array:
207
case gs_param_type_name_array:
208
if (!pparam->value.s.persistent)
209
gs_free_const_object(mem, pparam->value.s.data,
210
"gs_c_param_list_release data");
215
if (pparam->free_key) {
216
/* We allocated this, so we must free it. */
217
gs_free_const_string(mem, pparam->key.data, pparam->key.size,
218
"gs_c_param_list_release key");
220
gs_free_object(mem, pparam->alternate_typed_data,
221
"gs_c_param_list_release alternate data");
222
gs_free_object(mem, pparam,
223
"gs_c_param_list_release entry");
231
231
c_param_add(gs_c_param_list * plist, gs_param_name pkey)
233
233
gs_c_param *pparam =
234
gs_alloc_struct(plist->memory, gs_c_param, &st_c_param,
235
"c_param_add entry");
234
gs_alloc_struct(plist->memory, gs_c_param, &st_c_param,
235
"c_param_add entry");
236
236
uint len = strlen(pkey);
240
240
pparam->next = plist->head;
241
241
if (!plist->persistent_keys) {
242
/* We must copy the key. */
243
byte *str = gs_alloc_string(plist->memory, len, "c_param_add key");
242
/* We must copy the key. */
243
byte *str = gs_alloc_string(plist->memory, len, "c_param_add key");
246
gs_free_object(plist->memory, pparam, "c_param_add entry");
249
memcpy(str, pkey, len);
250
pparam->key.data = str;
251
pparam->key.persistent = false; /* we will free it */
252
pparam->free_key = true;
246
gs_free_object(plist->memory, pparam, "c_param_add entry");
249
memcpy(str, pkey, len);
250
pparam->key.data = str;
251
pparam->key.persistent = false; /* we will free it */
252
pparam->free_key = true;
254
pparam->key.data = (const byte *)pkey;
255
pparam->key.persistent = true;
256
pparam->free_key = false;
254
pparam->key.data = (const byte *)pkey;
255
pparam->key.persistent = true;
256
pparam->free_key = false;
258
258
pparam->key.size = len;
259
259
pparam->alternate_typed_data = 0;
263
263
/* Write a dynamically typed parameter to a list. */
265
265
c_param_write(gs_c_param_list * plist, gs_param_name pkey, void *pvalue,
268
268
unsigned top_level_sizeof = 0;
269
269
unsigned second_level_sizeof = 0;
270
270
gs_c_param *pparam = c_param_add(plist, pkey);
273
return_error(gs_error_VMerror);
273
return_error(gs_error_VMerror);
274
274
memcpy(&pparam->value, pvalue, gs_param_type_sizes[(int)type]);
275
275
pparam->type = type;
277
277
/* Need deeper copies of data if it's not persistent */
279
gs_param_string const *curr_string;
280
gs_param_string const *end_string;
282
case gs_param_type_string_array:
283
case gs_param_type_name_array:
284
/* Determine how much mem needed to hold actual string data */
285
curr_string = pparam->value.sa.data;
286
end_string = curr_string + pparam->value.sa.size;
287
for (; curr_string < end_string; ++curr_string)
288
if (!curr_string->persistent)
289
second_level_sizeof += curr_string->size;
292
case gs_param_type_string:
293
case gs_param_type_name:
294
case gs_param_type_int_array:
295
case gs_param_type_float_array:
296
if (!pparam->value.s.persistent) { /* Allocate & copy object pointed to by array or string */
297
byte *top_level_memory = NULL;
300
pparam->value.s.size * gs_param_type_base_sizes[type];
301
if (top_level_sizeof + second_level_sizeof > 0) {
303
gs_alloc_bytes_immovable(plist->memory,
304
top_level_sizeof + second_level_sizeof,
305
"c_param_write data");
306
if (top_level_memory == 0) {
307
gs_free_object(plist->memory, pparam, "c_param_write entry");
308
return_error(gs_error_VMerror);
310
memcpy(top_level_memory, pparam->value.s.data, top_level_sizeof);
312
pparam->value.s.data = top_level_memory;
314
/* String/name arrays need to copy actual str data */
316
if (second_level_sizeof > 0) {
317
byte *second_level_memory =
318
top_level_memory + top_level_sizeof;
320
curr_string = pparam->value.sa.data;
321
end_string = curr_string + pparam->value.sa.size;
322
for (; curr_string < end_string; ++curr_string)
323
if (!curr_string->persistent) {
324
memcpy(second_level_memory,
325
curr_string->data, curr_string->size);
326
((gs_param_string *) curr_string)->data
327
= second_level_memory;
328
second_level_memory += curr_string->size;
279
gs_param_string const *curr_string;
280
gs_param_string const *end_string;
282
case gs_param_type_string_array:
283
case gs_param_type_name_array:
284
/* Determine how much mem needed to hold actual string data */
285
curr_string = pparam->value.sa.data;
286
end_string = curr_string + pparam->value.sa.size;
287
for (; curr_string < end_string; ++curr_string)
288
if (!curr_string->persistent)
289
second_level_sizeof += curr_string->size;
292
case gs_param_type_string:
293
case gs_param_type_name:
294
case gs_param_type_int_array:
295
case gs_param_type_float_array:
296
if (!pparam->value.s.persistent) { /* Allocate & copy object pointed to by array or string */
297
byte *top_level_memory = NULL;
300
pparam->value.s.size * gs_param_type_base_sizes[type];
301
if (top_level_sizeof + second_level_sizeof > 0) {
303
gs_alloc_bytes_immovable(plist->memory,
304
top_level_sizeof + second_level_sizeof,
305
"c_param_write data");
306
if (top_level_memory == 0) {
307
gs_free_object(plist->memory, pparam, "c_param_write entry");
308
return_error(gs_error_VMerror);
310
memcpy(top_level_memory, pparam->value.s.data, top_level_sizeof);
312
pparam->value.s.data = top_level_memory;
314
/* String/name arrays need to copy actual str data */
316
if (second_level_sizeof > 0) {
317
byte *second_level_memory =
318
top_level_memory + top_level_sizeof;
320
curr_string = pparam->value.sa.data;
321
end_string = curr_string + pparam->value.sa.size;
322
for (; curr_string < end_string; ++curr_string)
323
if (!curr_string->persistent) {
324
memcpy(second_level_memory,
325
curr_string->data, curr_string->size);
326
((gs_param_string *) curr_string)->data
327
= second_level_memory;
328
second_level_memory += curr_string->size;
337
337
plist->head = pparam;
342
342
/* Individual writing routines. */
344
344
c_param_begin_write_collection(gs_param_list * plist, gs_param_name pkey,
345
gs_param_dict * pvalue, gs_param_collection_type_t coll_type)
345
gs_param_dict * pvalue, gs_param_collection_type_t coll_type)
347
347
gs_c_param_list *const cplist = (gs_c_param_list *)plist;
348
348
gs_c_param_list *dlist =
349
gs_c_param_list_alloc(cplist->memory,
350
"c_param_begin_write_collection");
349
gs_c_param_list_alloc(cplist->memory,
350
"c_param_begin_write_collection");
353
return_error(gs_error_VMerror);
353
return_error(gs_error_VMerror);
354
354
gs_c_param_list_write(dlist, cplist->memory);
355
355
dlist->coll_type = coll_type;
356
356
pvalue->list = (gs_param_list *) dlist;
360
360
c_param_end_write_collection(gs_param_list * plist, gs_param_name pkey,
361
gs_param_dict * pvalue)
361
gs_param_dict * pvalue)
363
363
gs_c_param_list *const cplist = (gs_c_param_list *)plist;
364
364
gs_c_param_list *dlist = (gs_c_param_list *) pvalue->list;
366
366
return c_param_write(cplist, pkey, pvalue->list,
367
(dlist->coll_type == gs_param_collection_dict_int_keys ?
368
gs_param_type_dict_int_keys :
369
dlist->coll_type == gs_param_collection_array ?
370
gs_param_type_array : gs_param_type_dict));
367
(dlist->coll_type == gs_param_collection_dict_int_keys ?
368
gs_param_type_dict_int_keys :
369
dlist->coll_type == gs_param_collection_array ?
370
gs_param_type_array : gs_param_type_dict));
373
373
c_param_write_typed(gs_param_list * plist, gs_param_name pkey,
374
gs_param_typed_value * pvalue)
374
gs_param_typed_value * pvalue)
376
376
gs_c_param_list *const cplist = (gs_c_param_list *)plist;
377
377
gs_param_collection_type_t coll_type;
379
379
switch (pvalue->type) {
380
case gs_param_type_dict:
381
coll_type = gs_param_collection_dict_any;
383
case gs_param_type_dict_int_keys:
384
coll_type = gs_param_collection_dict_int_keys;
386
case gs_param_type_array:
387
coll_type = gs_param_collection_array;
390
return c_param_write(cplist, pkey, &pvalue->value, pvalue->type);
380
case gs_param_type_dict:
381
coll_type = gs_param_collection_dict_any;
383
case gs_param_type_dict_int_keys:
384
coll_type = gs_param_collection_dict_int_keys;
386
case gs_param_type_array:
387
coll_type = gs_param_collection_array;
390
return c_param_write(cplist, pkey, &pvalue->value, pvalue->type);
392
392
return c_param_begin_write_collection
393
(plist, pkey, &pvalue->value.d, coll_type);
393
(plist, pkey, &pvalue->value.d, coll_type);
396
396
/* Other procedures */
473
return (cplist->target ?
474
param_read_typed(cplist->target, pkey, pvalue) : 1);
473
return (cplist->target ?
474
param_read_typed(cplist->target, pkey, pvalue) : 1);
475
475
pvalue->type = pparam->type;
476
476
switch (pvalue->type) {
477
case gs_param_type_dict:
478
case gs_param_type_dict_int_keys:
479
case gs_param_type_array:
480
gs_c_param_list_read(&pparam->value.d);
481
pvalue->value.d.list = (gs_param_list *) & pparam->value.d;
482
pvalue->value.d.size = pparam->value.d.count;
477
case gs_param_type_dict:
478
case gs_param_type_dict_int_keys:
479
case gs_param_type_array:
480
gs_c_param_list_read(&pparam->value.d);
481
pvalue->value.d.list = (gs_param_list *) & pparam->value.d;
482
pvalue->value.d.size = pparam->value.d.count;
487
487
memcpy(&pvalue->value, &pparam->value,
488
gs_param_type_sizes[(int)pparam->type]);
488
gs_param_type_sizes[(int)pparam->type]);
489
489
code = param_coerce_typed(pvalue, req_type, NULL);
490
490
/****** SHOULD LET param_coerce_typed DO THIS ******/
491
491
if (code == gs_error_typecheck &&
492
req_type == gs_param_type_float_array &&
493
pvalue->type == gs_param_type_int_array
495
/* Convert int array to float dest */
496
gs_param_float_array fa;
499
fa.size = pparam->value.ia.size;
500
fa.persistent = false;
502
if (pparam->alternate_typed_data == 0) {
503
if ((pparam->alternate_typed_data
504
= (void *)gs_alloc_bytes_immovable(cplist->memory,
505
fa.size * sizeof(float),
506
"gs_c_param_read alternate float array")) == 0)
507
return_error(gs_error_VMerror);
509
for (element = 0; element < fa.size; ++element)
510
((float *)(pparam->alternate_typed_data))[element]
511
= (float)pparam->value.ia.data[element];
513
fa.data = (float *)pparam->alternate_typed_data;
515
pvalue->value.fa = fa;
492
req_type == gs_param_type_float_array &&
493
pvalue->type == gs_param_type_int_array
495
/* Convert int array to float dest */
496
gs_param_float_array fa;
499
fa.size = pparam->value.ia.size;
500
fa.persistent = false;
502
if (pparam->alternate_typed_data == 0) {
503
if ((pparam->alternate_typed_data
504
= (void *)gs_alloc_bytes_immovable(cplist->memory,
505
fa.size * sizeof(float),
506
"gs_c_param_read alternate float array")) == 0)
507
return_error(gs_error_VMerror);
509
for (element = 0; element < fa.size; ++element)
510
((float *)(pparam->alternate_typed_data))[element]
511
= (float)pparam->value.ia.data[element];
513
fa.data = (float *)pparam->alternate_typed_data;
515
pvalue->value.fa = fa;
521
521
/* Individual reading routines. */
523
523
c_param_begin_read_collection(gs_param_list * plist, gs_param_name pkey,
524
gs_param_dict * pvalue, gs_param_collection_type_t coll_type)
524
gs_param_dict * pvalue, gs_param_collection_type_t coll_type)
526
526
gs_c_param_list *const cplist = (gs_c_param_list *)plist;
527
527
gs_c_param *pparam = c_param_find(cplist, pkey, false);
532
param_begin_read_collection(cplist->target,
533
pkey, pvalue, coll_type) :
532
param_begin_read_collection(cplist->target,
533
pkey, pvalue, coll_type) :
535
535
switch (pparam->type) {
536
case gs_param_type_dict:
537
if (coll_type != gs_param_collection_dict_any)
538
return_error(gs_error_typecheck);
540
case gs_param_type_dict_int_keys:
541
if (coll_type == gs_param_collection_array)
542
return_error(gs_error_typecheck);
544
case gs_param_type_array:
547
return_error(gs_error_typecheck);
536
case gs_param_type_dict:
537
if (coll_type != gs_param_collection_dict_any)
538
return_error(gs_error_typecheck);
540
case gs_param_type_dict_int_keys:
541
if (coll_type == gs_param_collection_array)
542
return_error(gs_error_typecheck);
544
case gs_param_type_array:
547
return_error(gs_error_typecheck);
549
549
gs_c_param_list_read(&pparam->value.d);
550
550
pvalue->list = (gs_param_list *) & pparam->value.d;