Example #1
0
static int
ref_param_read_typed(gs_param_list * plist, gs_param_name pkey,
		     gs_param_typed_value * pvalue)
{
    iparam_list *const iplist = (iparam_list *) plist;
    iparam_loc loc;
    ref elt;
    int code = ref_param_read(iplist, pkey, &loc, -1);

    if (code != 0)
	return code;
    switch (r_type(loc.pvalue)) {
	case t_array:
	case t_mixedarray:
	case t_shortarray:
	    iparam_check_read(loc);
	    if (r_size(loc.pvalue) <= 0) {
		/* 0-length array; can't get type info */
		pvalue->type = gs_param_type_array;
		pvalue->value.d.list = 0;
		pvalue->value.d.size = 0;
		return 0;
	    }
	    /*
	     * We have to guess at the array type.  First we guess based
	     * on the type of the first element of the array.  If that
	     * fails, we try again with more general types.
	     */
	    array_get(plist->memory, loc.pvalue, 0, &elt);
	    switch (r_type(&elt)) {
		case t_integer:
		    pvalue->type = gs_param_type_int_array;
		    code = ref_param_read_int_array(plist, pkey,
						    &pvalue->value.ia);
		    if (code != e_typecheck)
			return code;
		    /* This might be a float array.  Fall through. */
		    *loc.presult = 0;  /* reset error */
		case t_real:
		    pvalue->type = gs_param_type_float_array;
		    return ref_param_read_float_array(plist, pkey,
						      &pvalue->value.fa);
		case t_string:
		    pvalue->type = gs_param_type_string_array;
		    return ref_param_read_string_array(plist, pkey,
						       &pvalue->value.sa);
		case t_name:
		    pvalue->type = gs_param_type_name_array;
		    return ref_param_read_string_array(plist, pkey,
						       &pvalue->value.na);
		default:
		    break;
	    }
	    return gs_note_error(e_typecheck);
	case t_boolean:
	    pvalue->type = gs_param_type_bool;
	    pvalue->value.b = loc.pvalue->value.boolval;
	    return 0;
	case t_dictionary:
	    code = ref_param_begin_read_collection(plist, pkey,
			    &pvalue->value.d, gs_param_collection_dict_any);
	    if (code < 0)
		return code;
	    pvalue->type = gs_param_type_dict;

	    /* fixup new dict's type & int_keys field if contents have int keys */
	    {
		gs_param_enumerator_t enumr;
		gs_param_key_t key;
		ref_type keytype;

		param_init_enumerator(&enumr);
		if (!(*((iparam_list *) plist)->enumerate)
		    ((iparam_list *) pvalue->value.d.list, &enumr, &key, &keytype)
		    && keytype == t_integer) {
		    ((dict_param_list *) pvalue->value.d.list)->int_keys = 1;
		    pvalue->type = gs_param_type_dict_int_keys;
		}
	    }
	    return 0;
	case t_integer:
	    pvalue->type = gs_param_type_long;
	    pvalue->value.l = loc.pvalue->value.intval;
	    return 0;
	case t_name:
	    pvalue->type = gs_param_type_name;
	    return ref_param_read_string_value(plist->memory, &loc, &pvalue->value.n);
	case t_null:
	    pvalue->type = gs_param_type_null;
	    return 0;
	case t_real:
	    pvalue->value.f = loc.pvalue->value.realval;
	    pvalue->type = gs_param_type_float;
	    return 0;
	case t_string:
        case t_astruct:
	    pvalue->type = gs_param_type_string;
	    return ref_param_read_string_value(plist->memory, &loc, &pvalue->value.s);
	default:
	    break;
    }
    return gs_note_error(e_typecheck);
}
Example #2
0
/* 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,
						     &copy.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,
						   &copy.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;
}
Example #3
0
/* Serialize the contents of a gs_param_list (including sub-dicts) */
int				/* ret -ve err, else # bytes needed to represent param list, whether */

/* or not it actually fit into buffer. List was successully */

/* serialized only if if this # is <= supplied buf size. */
gs_param_list_serialize(
                           gs_param_list * list,	/* root of list to serialize */
                                        /* list MUST BE IN READ MODE */
                           byte * buf,	/* destination buffer (can be 0) */
                           int buf_sizeof	/* # bytes available in buf (can be 0) */
)
{
    int code = 0;
    int temp_code;
    gs_param_enumerator_t key_enum;
    gs_param_key_t key;
    WriteBuffer write_buf;

    write_buf.buf = buf;
    write_buf.buf_end = buf + (buf ? buf_sizeof : 0);
    write_buf.total_sizeof = 0;
    param_init_enumerator(&key_enum);

    /* Each item is serialized as ("word" means compressed word):
     *  word: key sizeof + 1, or 0 if end of list/dict
     *  word: data type(gs_param_type_xxx)
     *  byte[]: key, including trailing \0
     *  (if simple type)
     *   byte[]: unpacked representation of data
     *  (if simple array or string)
     *   byte[]: unpacked mem image of gs_param_xxx_array structure
     *   pad: to array alignment
     *   byte[]: data associated with array contents
     *  (if string/name array)
     *   byte[]: unpacked mem image of gs_param_string_array structure
     *   pad: to void *
     *   { gs_param_string structure mem image;
     *     data associated with string;
     *   } for each string in array
     *  (if dict/dict_int_keys)
     *   word: # of entries in dict,
     *   pad: to void *
     *   dict entries follow immediately until end-of-dict
     *
     * NB that this format is designed to allow using an input buffer
     * as the direct source of data when expanding a gs_c_param_list
     */
    /* Enumerate all the keys; use keys to get their typed values */
    while ((code = param_get_next_key(list, &key_enum, &key)) == 0) {
        int value_top_sizeof;
        int value_base_sizeof;

        /* Get next datum & put its type & key to buffer */
        gs_param_typed_value value;
        char string_key[256];

        if (sizeof(string_key) < key.size + 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(list, string_key, &value)) != 0) {
            code = code > 0 ? gs_note_error(gs_error_unknownerror) : code;
            break;
        }
        wb_put_word((unsigned)key.size + 1, &write_buf);
        wb_put_word((unsigned)value.type, &write_buf);
        wb_put_bytes((byte *) string_key, key.size + 1, &write_buf);

        /* Put value & its size to buffer */
        value_top_sizeof = gs_param_type_sizes[value.type];
        value_base_sizeof = gs_param_type_base_sizes[value.type];
        switch (value.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:
                wb_put_bytes((byte *) & value.value, value_top_sizeof, &write_buf);
                break;

            case gs_param_type_string:
            case gs_param_type_name:
            case gs_param_type_int_array:
            case gs_param_type_float_array:
                wb_put_bytes((byte *) & value.value, value_top_sizeof, &write_buf);
                wb_put_alignment(value_base_sizeof, &write_buf);
                value_base_sizeof *= value.value.s.size;
                wb_put_bytes(value.value.s.data, value_base_sizeof, &write_buf);
                break;

            case gs_param_type_string_array:
            case gs_param_type_name_array:
                value_base_sizeof *= value.value.sa.size;
                wb_put_bytes((const byte *)&value.value, value_top_sizeof, &write_buf);
                wb_put_alignment(sizeof(void *), &write_buf);

                wb_put_bytes((const byte *)value.value.sa.data, value_base_sizeof,
                          &write_buf);
                {
                    int str_count;
                    const gs_param_string *sa;

                    for (str_count = value.value.sa.size,
                         sa = value.value.sa.data; str_count-- > 0; ++sa)
                        wb_put_bytes(sa->data, sa->size, &write_buf);
                }
                break;

            case gs_param_type_dict:
            case gs_param_type_dict_int_keys:
                wb_put_word(value.value.d.size, &write_buf);
                wb_put_alignment(sizeof(void *), &write_buf);

                {
                    int bytes_written =
                    gs_param_list_serialize(value.value.d.list,
                                            write_buf.buf,
                     write_buf.buf ? write_buf.buf_end - write_buf.buf : 0);

                    temp_code = param_end_read_dict(list,
                                                    (const char *)key.data,
                                                    &value.value.d);
                    if (bytes_written < 0)
                        code = bytes_written;
                    else {
                        code = temp_code;
                        if (bytes_written)
                            wb_put_bytes(write_buf.buf, bytes_written, &write_buf);
                    }
                }
                break;

            default:
                code = gs_note_error(gs_error_unknownerror);
                break;
        }
        if (code < 0)
            break;
    }

    /* Write end marker, which is an (illegal) 0 key length */
    if (code >= 0) {
        wb_put_word(0, &write_buf);
        code = write_buf.total_sizeof;
    }
    return code;
}