/* Copy one parameter list to another, recursively if necessary. */ int param_list_copy(gs_param_list *plto, gs_param_list *plfrom) { gs_param_enumerator_t key_enum; gs_param_key_t key; /* * If plfrom and plto use different allocators, we must copy * aggregate values even if they are "persistent". */ bool copy_persists = plto->memory == plfrom->memory; int code; param_init_enumerator(&key_enum); while ((code = param_get_next_key(plfrom, &key_enum, &key)) == 0) { char string_key[256]; /* big enough for any reasonable key */ gs_param_typed_value value; gs_param_collection_type_t coll_type; gs_param_typed_value copy; if (key.size > sizeof(string_key) - 1) { code = gs_note_error(gs_error_rangecheck); break; } memcpy(string_key, key.data, key.size); string_key[key.size] = 0; if ((code = param_read_typed(plfrom, string_key, &value)) != 0) { code = (code > 0 ? gs_note_error(gs_error_unknownerror) : code); break; } gs_param_list_set_persistent_keys(plto, key.persistent); switch (value.type) { case gs_param_type_dict: coll_type = gs_param_collection_dict_any; goto cc; case gs_param_type_dict_int_keys: coll_type = gs_param_collection_dict_int_keys; goto cc; case gs_param_type_array: coll_type = gs_param_collection_array; cc: copy.value.d.size = value.value.d.size; if ((code = param_begin_write_collection(plto, string_key, ©.value.d, coll_type)) < 0 || (code = param_list_copy(copy.value.d.list, value.value.d.list)) < 0 || (code = param_end_write_collection(plto, string_key, ©.value.d)) < 0) break; code = param_end_read_collection(plfrom, string_key, &value.value.d); break; case gs_param_type_string: value.value.s.persistent &= copy_persists; goto ca; case gs_param_type_name: value.value.n.persistent &= copy_persists; goto ca; case gs_param_type_int_array: value.value.ia.persistent &= copy_persists; goto ca; case gs_param_type_float_array: value.value.fa.persistent &= copy_persists; goto ca; case gs_param_type_string_array: value.value.sa.persistent &= copy_persists; ca: default: code = param_write_typed(plto, string_key, &value); } if (code < 0) break; } return code; }
/* Expand a buffer into a gs_param_list (including sub-dicts) */ int /* ret -ve err, +ve # of chars read from buffer */ gs_param_list_unserialize( gs_param_list * list, /* root of list to expand to */ /* list MUST BE IN WRITE MODE */ const byte * buf /* source buffer */ ) { int code = 0; const byte *orig_buf = buf; do { gs_param_typed_value typed; gs_param_name key; unsigned key_sizeof; int value_top_sizeof; int value_base_sizeof; int temp_code; gs_param_type type; /* key length, 0 indicates end of data */ key_sizeof = buf_get_word(&buf); if (key_sizeof == 0) /* end of data */ break; /* data type */ type = (gs_param_type) buf_get_word(&buf); /* key */ key = (gs_param_name) buf; buf += key_sizeof; /* Data values */ value_top_sizeof = gs_param_type_sizes[type]; value_base_sizeof = gs_param_type_base_sizes[type]; typed.type = type; if (type != gs_param_type_dict && type != gs_param_type_dict_int_keys) { memcpy(&typed.value, buf, value_top_sizeof); buf += value_top_sizeof; } switch (type) { case gs_param_type_null: case gs_param_type_bool: case gs_param_type_int: case gs_param_type_long: case gs_param_type_float: break; case gs_param_type_string: case gs_param_type_name: case gs_param_type_int_array: case gs_param_type_float_array: ptr_align_to(&buf, value_base_sizeof); typed.value.s.data = buf; typed.value.s.persistent = false; buf += typed.value.s.size * value_base_sizeof; break; case gs_param_type_string_array: case gs_param_type_name_array: ptr_align_to(&buf, sizeof(void *)); typed.value.sa.data = (const gs_param_string *)buf; typed.value.sa.persistent = false; buf += typed.value.s.size * value_base_sizeof; { int str_count; gs_param_string *sa; for (str_count = typed.value.sa.size, sa = (gs_param_string *) typed.value.sa.data; str_count-- > 0; ++sa) { sa->data = buf; sa->persistent = false; buf += sa->size; } } break; case gs_param_type_dict: case gs_param_type_dict_int_keys: typed.value.d.size = buf_get_word(&buf); code = param_begin_write_dict (list, key, &typed.value.d, type == gs_param_type_dict_int_keys); if (code < 0) break; ptr_align_to(&buf, sizeof(void *)); code = gs_param_list_unserialize(typed.value.d.list, buf); temp_code = param_end_write_dict(list, key, &typed.value.d); if (code >= 0) { buf += code; code = temp_code; } break; default: code = gs_note_error(gs_error_unknownerror); break; } if (code < 0) break; if (typed.type != gs_param_type_dict && typed.type != gs_param_type_dict_int_keys) code = param_write_typed(list, key, &typed); } while (code >= 0); return code >= 0 ? buf - orig_buf : code; }