Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/* Copyright (C) 1995, 1998, 1999 Aladdin Enterprises.  All rights reserved.
2
 
3
  This software is provided AS-IS with no warranty, either express or
4
  implied.
5
 
6
  This software is distributed under license and may not be copied,
7
  modified or distributed except as expressly authorized under the terms
8
  of the license contained in the file LICENSE in this distribution.
9
 
10
  For more information about licensing, please refer to
11
  http://www.ghostscript.com/licensing/. For information on
12
  commercial licensing, go to http://www.artifex.com/licensing/ or
13
  contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14
  San Rafael, CA  94903, U.S.A., +1(415)492-9861.
15
*/
16
 
17
/* $Id: gsparam.c,v 1.7 2002/10/07 08:28:56 ghostgum Exp $ */
18
/* Support for parameter lists */
19
#include "memory_.h"
20
#include "string_.h"
21
#include "gx.h"
22
#include "gserrors.h"
23
#include "gsparam.h"
24
#include "gsstruct.h"
25
 
26
/* GC procedures */
27
ENUM_PTRS_WITH(gs_param_typed_value_enum_ptrs, gs_param_typed_value *pvalue) return 0;
28
    case 0:
29
    switch (pvalue->type) {
30
    case gs_param_type_string:
31
	return ENUM_STRING(&pvalue->value.s);
32
    case gs_param_type_name:
33
	return ENUM_STRING(&pvalue->value.n);
34
    case gs_param_type_int_array:
35
	return ENUM_OBJ(pvalue->value.ia.data);
36
    case gs_param_type_float_array:
37
	return ENUM_OBJ(pvalue->value.fa.data);
38
    case gs_param_type_string_array:
39
	return ENUM_OBJ(pvalue->value.sa.data);
40
    case gs_param_type_name_array:
41
	return ENUM_OBJ(pvalue->value.na.data);
42
    default:
43
	return ENUM_OBJ(0);	/* don't stop early */
44
    }
45
ENUM_PTRS_END
46
RELOC_PTRS_WITH(gs_param_typed_value_reloc_ptrs, gs_param_typed_value *pvalue) {
47
    switch (pvalue->type) {
48
    case gs_param_type_string:
49
    case gs_param_type_name: {
50
	gs_const_string str;
51
 
52
	str.data = pvalue->value.s.data; /* n == s */
53
	str.size = pvalue->value.s.size;
54
	RELOC_CONST_STRING_VAR(str);
55
	pvalue->value.s.data = str.data;
56
	break;
57
    }
58
    case gs_param_type_int_array:
59
	RELOC_VAR(pvalue->value.ia.data);
60
	break;
61
    case gs_param_type_float_array:
62
	RELOC_VAR(pvalue->value.fa.data);
63
	break;
64
    case gs_param_type_string_array:
65
	RELOC_VAR(pvalue->value.sa.data);
66
	break;
67
    case gs_param_type_name_array:
68
	RELOC_VAR(pvalue->value.na.data);
69
	break;
70
    default:
71
	break;
72
    }
73
}
74
RELOC_PTRS_END
75
 
76
/* Internal procedure to initialize the common part of a parameter list. */
77
void
78
gs_param_list_init(gs_param_list *plist, const gs_param_list_procs *procs,
79
		   gs_memory_t *mem)
80
{
81
    plist->procs = procs;
82
    plist->memory = mem;
83
    plist->persistent_keys = true;
84
}
85
 
86
/* Set whether the keys for param_write_XXX are persistent. */
87
void
88
gs_param_list_set_persistent_keys(gs_param_list *plist, bool persistent)
89
{
90
    plist->persistent_keys = persistent;
91
}
92
 
93
/* Reset a gs_param_key_t enumerator to its initial state */
94
void
95
param_init_enumerator(gs_param_enumerator_t * enumerator)
96
{
97
    memset(enumerator, 0, sizeof(*enumerator));
98
}
99
 
100
/* Transfer a collection of parameters. */
101
private const byte xfer_item_sizes[] = {
102
    GS_PARAM_TYPE_SIZES(0)
103
};
104
int
105
gs_param_read_items(gs_param_list * plist, void *obj,
106
		    const gs_param_item_t * items)
107
{
108
    const gs_param_item_t *pi;
109
    int ecode = 0;
110
 
111
    for (pi = items; pi->key != 0; ++pi) {
112
	const char *key = pi->key;
113
	void *pvalue = (void *)((char *)obj + pi->offset);
114
	gs_param_typed_value typed;
115
	int code;
116
 
117
	typed.type = pi->type;
118
	code = param_read_requested_typed(plist, key, &typed);
119
	switch (code) {
120
	    default:		/* < 0 */
121
		ecode = code;
122
	    case 1:
123
		break;
124
	    case 0:
125
		if (typed.type != pi->type)	/* shouldn't happen! */
126
		    ecode = gs_note_error(gs_error_typecheck);
127
		else
128
		    memcpy(pvalue, &typed.value, xfer_item_sizes[pi->type]);
129
	}
130
    }
131
    return ecode;
132
}
133
int
134
gs_param_write_items(gs_param_list * plist, const void *obj,
135
		     const void *default_obj, const gs_param_item_t * items)
136
{
137
    const gs_param_item_t *pi;
138
    int ecode = 0;
139
 
140
    for (pi = items; pi->key != 0; ++pi) {
141
	const char *key = pi->key;
142
	const void *pvalue = (const void *)((const char *)obj + pi->offset);
143
	int size = xfer_item_sizes[pi->type];
144
	gs_param_typed_value typed;
145
	int code;
146
 
147
	if (default_obj != 0 &&
148
	    !memcmp((const void *)((const char *)default_obj + pi->offset),
149
		    pvalue, size)
150
	    )
151
	    continue;
152
	memcpy(&typed.value, pvalue, size);
153
	typed.type = pi->type;
154
	code = (*plist->procs->xmit_typed) (plist, key, &typed);
155
	if (code < 0)
156
	    ecode = code;
157
    }
158
    return ecode;
159
}
160
 
161
/* Read a value, with coercion if requested, needed, and possible. */
162
/* If mem != 0, we can coerce int arrays to float arrays. */
163
int
164
param_coerce_typed(gs_param_typed_value * pvalue, gs_param_type req_type,
165
		   gs_memory_t * mem)
166
{
167
    if (req_type == gs_param_type_any || pvalue->type == req_type)
168
	return 0;
169
    /*
170
     * Look for coercion opportunities.  It would be wonderful if we
171
     * could convert int/float arrays and name/string arrays, but
172
     * right now we can't.  However, a 0-length heterogenous array
173
     * will satisfy a request for any specific type.
174
     */
175
    switch (pvalue->type /* actual type */ ) {
176
	case gs_param_type_int:
177
	    switch (req_type) {
178
		case gs_param_type_long:
179
		    pvalue->value.l = pvalue->value.i;
180
		    goto ok;
181
		case gs_param_type_float:
182
		    pvalue->value.f = (float)pvalue->value.l;
183
		    goto ok;
184
		default:
185
		    break;
186
	    }
187
	    break;
188
	case gs_param_type_long:
189
	    switch (req_type) {
190
		case gs_param_type_int:
191
#if arch_sizeof_int < arch_sizeof_long
192
		    if (pvalue->value.l != (int)pvalue->value.l)
193
			return_error(gs_error_rangecheck);
194
#endif
195
		    pvalue->value.i = (int)pvalue->value.l;
196
		    goto ok;
197
		case gs_param_type_float:
198
		    pvalue->value.f = (float)pvalue->value.l;
199
		    goto ok;
200
		default:
201
		    break;
202
	    }
203
	    break;
204
	case gs_param_type_string:
205
	    if (req_type == gs_param_type_name)
206
		goto ok;
207
	    break;
208
	case gs_param_type_name:
209
	    if (req_type == gs_param_type_string)
210
		goto ok;
211
	    break;
212
	case gs_param_type_int_array:
213
	    switch (req_type) {
214
		case gs_param_type_float_array:{
215
			uint size = pvalue->value.ia.size;
216
			float *fv;
217
			uint i;
218
 
219
			if (mem == 0)
220
			    break;
221
			fv = (float *)gs_alloc_byte_array(mem, size, sizeof(float),
222
						"int array => float array");
223
 
224
			if (fv == 0)
225
			    return_error(gs_error_VMerror);
226
			for (i = 0; i < size; ++i)
227
			    fv[i] = (float)pvalue->value.ia.data[i];
228
			pvalue->value.fa.data = fv;
229
			pvalue->value.fa.persistent = false;
230
			goto ok;
231
		    }
232
		default:
233
		    break;
234
	    }
235
	    break;
236
	case gs_param_type_string_array:
237
	    if (req_type == gs_param_type_name_array)
238
		goto ok;
239
	    break;
240
	case gs_param_type_name_array:
241
	    if (req_type == gs_param_type_string_array)
242
		goto ok;
243
	    break;
244
	case gs_param_type_array:
245
	    if (pvalue->value.d.size == 0 &&
246
		(req_type == gs_param_type_int_array ||
247
		 req_type == gs_param_type_float_array ||
248
		 req_type == gs_param_type_string_array ||
249
		 req_type == gs_param_type_name_array)
250
		)
251
		goto ok;
252
	    break;
253
	default:
254
	    break;
255
    }
256
    return_error(gs_error_typecheck);
257
  ok:pvalue->type = req_type;
258
    return 0;
259
}
260
int
261
param_read_requested_typed(gs_param_list * plist, gs_param_name pkey,
262
			   gs_param_typed_value * pvalue)
263
{
264
    gs_param_type req_type = pvalue->type;
265
    int code = (*plist->procs->xmit_typed) (plist, pkey, pvalue);
266
 
267
    if (code != 0)
268
	return code;
269
    return param_coerce_typed(pvalue, req_type, plist->memory);
270
}
271
 
272
 
273
/* ---------------- Fixed-type reading procedures ---------------- */
274
 
275
#define RETURN_READ_TYPED(alt, ptype)\
276
  gs_param_typed_value typed;\
277
  int code;\
278
\
279
  typed.type = ptype;\
280
  code = param_read_requested_typed(plist, pkey, &typed);\
281
  if ( code == 0 )\
282
    *pvalue = typed.value.alt;\
283
  return code
284
 
285
int
286
param_read_null(gs_param_list * plist, gs_param_name pkey)
287
{
288
    gs_param_typed_value typed;
289
 
290
    typed.type = gs_param_type_null;
291
    return param_read_requested_typed(plist, pkey, &typed);
292
}
293
int
294
param_read_bool(gs_param_list * plist, gs_param_name pkey, bool * pvalue)
295
{
296
    RETURN_READ_TYPED(b, gs_param_type_bool);
297
}
298
int
299
param_read_int(gs_param_list * plist, gs_param_name pkey, int *pvalue)
300
{
301
    RETURN_READ_TYPED(i, gs_param_type_int);
302
}
303
int
304
param_read_long(gs_param_list * plist, gs_param_name pkey, long *pvalue)
305
{
306
    RETURN_READ_TYPED(l, gs_param_type_long);
307
}
308
int
309
param_read_float(gs_param_list * plist, gs_param_name pkey, float *pvalue)
310
{
311
    RETURN_READ_TYPED(f, gs_param_type_float);
312
}
313
int
314
param_read_string(gs_param_list * plist, gs_param_name pkey,
315
		  gs_param_string * pvalue)
316
{
317
    RETURN_READ_TYPED(s, gs_param_type_string);
318
}
319
int
320
param_read_name(gs_param_list * plist, gs_param_name pkey,
321
		gs_param_string * pvalue)
322
{
323
    RETURN_READ_TYPED(n, gs_param_type_string);
324
}
325
int
326
param_read_int_array(gs_param_list * plist, gs_param_name pkey,
327
		     gs_param_int_array * pvalue)
328
{
329
    RETURN_READ_TYPED(ia, gs_param_type_int_array);
330
}
331
int
332
param_read_float_array(gs_param_list * plist, gs_param_name pkey,
333
		       gs_param_float_array * pvalue)
334
{
335
    RETURN_READ_TYPED(fa, gs_param_type_float_array);
336
}
337
int
338
param_read_string_array(gs_param_list * plist, gs_param_name pkey,
339
			gs_param_string_array * pvalue)
340
{
341
    RETURN_READ_TYPED(sa, gs_param_type_string_array);
342
}
343
int
344
param_read_name_array(gs_param_list * plist, gs_param_name pkey,
345
		      gs_param_string_array * pvalue)
346
{
347
    RETURN_READ_TYPED(na, gs_param_type_name_array);
348
}
349
 
350
#undef RETURN_READ_TYPED
351
 
352
/* ---------------- Default writing procedures ---------------- */
353
 
354
#define RETURN_WRITE_TYPED(alt, ptype)\
355
  gs_param_typed_value typed;\
356
\
357
  typed.value.alt = *pvalue;\
358
  typed.type = ptype;\
359
  return param_write_typed(plist, pkey, &typed)
360
 
361
int
362
param_write_null(gs_param_list * plist, gs_param_name pkey)
363
{
364
    gs_param_typed_value typed;
365
 
366
    typed.type = gs_param_type_null;
367
    return param_write_typed(plist, pkey, &typed);
368
}
369
int
370
param_write_bool(gs_param_list * plist, gs_param_name pkey, const bool * pvalue)
371
{
372
    RETURN_WRITE_TYPED(b, gs_param_type_bool);
373
}
374
int
375
param_write_int(gs_param_list * plist, gs_param_name pkey, const int *pvalue)
376
{
377
    RETURN_WRITE_TYPED(i, gs_param_type_int);
378
}
379
int
380
param_write_long(gs_param_list * plist, gs_param_name pkey, const long *pvalue)
381
{
382
    RETURN_WRITE_TYPED(l, gs_param_type_long);
383
}
384
int
385
param_write_float(gs_param_list * plist, gs_param_name pkey,
386
		  const float *pvalue)
387
{
388
    RETURN_WRITE_TYPED(f, gs_param_type_float);
389
}
390
int
391
param_write_string(gs_param_list * plist, gs_param_name pkey,
392
		   const gs_param_string * pvalue)
393
{
394
    RETURN_WRITE_TYPED(s, gs_param_type_string);
395
}
396
int
397
param_write_name(gs_param_list * plist, gs_param_name pkey,
398
		 const gs_param_string * pvalue)
399
{
400
    RETURN_WRITE_TYPED(n, gs_param_type_name);
401
}
402
int
403
param_write_int_array(gs_param_list * plist, gs_param_name pkey,
404
		      const gs_param_int_array * pvalue)
405
{
406
    RETURN_WRITE_TYPED(ia, gs_param_type_int_array);
407
}
408
int
409
param_write_int_values(gs_param_list * plist, gs_param_name pkey,
410
		       const int *values, uint size, bool persistent)
411
{
412
    gs_param_int_array ia;
413
 
414
    ia.data = values, ia.size = size, ia.persistent = persistent;
415
    return param_write_int_array(plist, pkey, &ia);
416
}
417
int
418
param_write_float_array(gs_param_list * plist, gs_param_name pkey,
419
			const gs_param_float_array * pvalue)
420
{
421
    RETURN_WRITE_TYPED(fa, gs_param_type_float_array);
422
}
423
int
424
param_write_float_values(gs_param_list * plist, gs_param_name pkey,
425
			 const float *values, uint size, bool persistent)
426
{
427
    gs_param_float_array fa;
428
 
429
    fa.data = values, fa.size = size, fa.persistent = persistent;
430
    return param_write_float_array(plist, pkey, &fa);
431
}
432
int
433
param_write_string_array(gs_param_list * plist, gs_param_name pkey,
434
			 const gs_param_string_array * pvalue)
435
{
436
    RETURN_WRITE_TYPED(sa, gs_param_type_string_array);
437
}
438
int
439
param_write_name_array(gs_param_list * plist, gs_param_name pkey,
440
		       const gs_param_string_array * pvalue)
441
{
442
    RETURN_WRITE_TYPED(na, gs_param_type_name_array);
443
}
444
 
445
#undef RETURN_WRITE_TYPED
446
 
447
/* ---------------- Default request implementation ---------------- */
448
 
449
int
450
gs_param_request_default(gs_param_list * plist, gs_param_name pkey)
451
{
452
    return 0;
453
}
454
 
455
int
456
gs_param_requested_default(const gs_param_list * plist, gs_param_name pkey)
457
{
458
    return -1;			/* requested by default */
459
}