1 /* Copyright (C) 1993, 2000 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.h,v 1.13 2005/09/05 13:58:55 leonardo Exp $ */ 18 /* Client interface to parameter dictionaries */ 19 20 #ifndef gsparam_INCLUDED 21 # define gsparam_INCLUDED 22 23 #include "gsstype.h" 24 25 /* 26 * Several interfaces use parameter dictionaries to communicate sets of 27 * (key, value) pairs between a client and an object with complex state. 28 * (Several of these correspond directly to similar interfaces in the 29 * PostScript language.) This file defines the API for parameter dictionaries. 30 */ 31 32 /* ---------------- Generic interfaces ---------------- */ 33 34 /* Define the abstract type for a parameter list. */ 35 #ifndef gs_param_list_DEFINED 36 # define gs_param_list_DEFINED 37 typedef struct gs_param_list_s gs_param_list; 38 #endif 39 40 /* Define the type for a parameter key name. */ 41 typedef const char *gs_param_name; 42 43 /* 44 * Parameter values fall into three categories: 45 * - Scalar (null, Boolean, int, long, float); 46 * - Homogenous collection (string/name, int array, float array, 47 * string/name array); 48 * - Heterogenous collection (dictionary, int-keyed dictionary, array). 49 * Each category has its own representation and memory management issues. 50 */ 51 typedef enum { 52 /* Scalar */ 53 gs_param_type_null, gs_param_type_bool, gs_param_type_int, 54 gs_param_type_long, gs_param_type_float, 55 /* Homogenous collection */ 56 gs_param_type_string, gs_param_type_name, 57 gs_param_type_int_array, gs_param_type_float_array, 58 gs_param_type_string_array, gs_param_type_name_array, 59 /* Heterogenous collection */ 60 gs_param_type_dict, gs_param_type_dict_int_keys, gs_param_type_array 61 } gs_param_type; 62 63 /* Define a "don't care" type for reading typed values. */ 64 #define gs_param_type_any ((gs_param_type)-1) 65 66 /* 67 * Define the structures for homogenous collection values 68 * (string/name, integer array, or floating point array). 69 * The size is the number of elements, not the size in bytes. 70 * A value is persistent if it is defined as static const, 71 * or if it is allocated in garbage-collectable space and never freed. 72 */ 73 74 #define _param_array_struct(sname,etype)\ 75 struct sname { const etype *data; uint size; bool persistent; } 76 typedef _param_array_struct(gs_param_int_array_s, int) gs_param_int_array; 77 typedef _param_array_struct(gs_param_float_array_s, float) gs_param_float_array; 78 typedef _param_array_struct(gs_param_string_array_s, gs_param_string) gs_param_string_array; 79 80 #define param_string_from_string(ps, str)\ 81 ((ps).data = (const byte *)(str),\ 82 (ps).size = strlen((const char *)(ps).data),\ 83 (ps).persistent = true) 84 85 #define param_string_from_transient_string(ps, str)\ 86 ((ps).data = (const byte *)(str),\ 87 (ps).size = strlen((const char *)(ps).data),\ 88 (ps).persistent = false) 89 90 /* 91 * Define the structure for heterogenous collection values (dictionaries 92 * and heterogenous arrays). 93 */ 94 typedef struct gs_param_collection_s { 95 gs_param_list *list; 96 uint size; 97 } gs_param_collection; 98 typedef gs_param_collection gs_param_dict; 99 typedef gs_param_collection gs_param_array; 100 101 /* 102 * Define the sizes of the various parameter value types, indexed by type. 103 */ 104 #define GS_PARAM_TYPE_SIZES(dict_size)\ 105 0, sizeof(bool), sizeof(int), sizeof(long), sizeof(float),\ 106 sizeof(gs_param_string), sizeof(gs_param_string),\ 107 sizeof(gs_param_int_array), sizeof(gs_param_float_array),\ 108 sizeof(gs_param_string_array), sizeof(gs_param_string_array),\ 109 (dict_size), (dict_size), (dict_size) 110 /* 111 * Define the sizes of the underlying data types contained in or pointed 112 * to by the various value types. 113 */ 114 #define GS_PARAM_TYPE_BASE_SIZES(dict_elt_size)\ 115 0, sizeof(bool), sizeof(int), sizeof(long), sizeof(float),\ 116 1, 1, sizeof(int), sizeof(float),\ 117 sizeof(gs_param_string), sizeof(gs_param_string),\ 118 (dict_elt_size), (dict_elt_size), (dict_elt_size) 119 120 /* Define tables with 0 for the sizes of the heterogenous collections. */ 121 extern const byte gs_param_type_sizes[]; 122 extern const byte gs_param_type_base_sizes[]; 123 124 /* Define a union capable of holding any parameter value. */ 125 #define GS_PARAM_VALUE_UNION(dict_type)\ 126 bool b;\ 127 int i;\ 128 long l;\ 129 float f;\ 130 gs_param_string s;\ 131 gs_param_string n;\ 132 gs_param_int_array ia;\ 133 gs_param_float_array fa;\ 134 gs_param_string_array sa;\ 135 gs_param_string_array na;\ 136 dict_type d 137 typedef union gs_param_value_s { 138 GS_PARAM_VALUE_UNION(gs_param_collection); 139 } gs_param_value; 140 141 /* 142 * Define a structure containing a dynamically typed value (a value along 143 * with its type). 144 */ 145 typedef struct gs_param_typed_value_s { 146 gs_param_value value; 147 gs_param_type type; 148 } gs_param_typed_value; 149 /* 150 * Garbage collection of gs_param_values depends on the value type and on 151 * the 'd' member of the union. We provide enum_ptrs and reloc_ptrs 152 * procedures that handle all the other cases -- i.e., cases other than 153 * heterogenous collections. 154 */ 155 struct_proc_enum_ptrs(gs_param_typed_value_enum_ptrs); 156 struct_proc_reloc_ptrs(gs_param_typed_value_reloc_ptrs); 157 #define gs_param_typed_value_max_ptrs 1 158 159 /* 160 * Define the representation alternatives for heterogenous collections. 161 * _any must be 0, for Boolean testing. 162 */ 163 typedef enum { 164 165 /* Create or accept a general dictionary. */ 166 167 gs_param_collection_dict_any = 0, 168 169 /* Create a dictionary with integer string keys ("0", "1", ...); */ 170 /* accept a dictionary with integer string keys, or a heterogenous */ 171 /* array. */ 172 173 gs_param_collection_dict_int_keys = 1, 174 175 /* Create an array if possible, otherwise a dictionary with integer */ 176 /* string keys; accept the same types as dict_int_keys. */ 177 178 gs_param_collection_array = 2 179 180 } gs_param_collection_type_t; 181 182 /* 183 * Define the 'policies' for handling out-of-range parameter values. 184 * This is not an enum, because some parameters may recognize other values. 185 */ 186 #define gs_param_policy_signal_error 0 187 #define gs_param_policy_ignore 1 188 #define gs_param_policy_consult_user 2 189 190 /* 191 * Define an enumerator used to iterate through the keys in a list. 192 * 193 * All the members of the union must be used such that memset(0) entire 194 * union means 'beginning of enumeration'. 195 */ 196 typedef union gs_param_enumerator_s { 197 int intval; 198 long longval; 199 void *pvoid; 200 char *pchar; 201 } gs_param_enumerator_t; 202 typedef gs_param_string gs_param_key_t; 203 204 /* 205 * Define the object procedures. Note that the same interface is used 206 * both for getting and for setting parameter values. (This is a bit 207 * of a hack, and we might change it someday.) The procedures return 208 * as follows: 209 * - 'reading' procedures ('put' operations from the client's viewpoint) 210 * return 1 for a missing parameter, 0 for a valid parameter, <0 on error. 211 * - 'writing' procedures ('get' operations from the client's viewpoint) 212 * return 0 or 1 if successful, <0 on error. 213 * 214 * A lazy implementation can use the default procedures for scalar and 215 * homogenous collection types: these just called xmit_typed. 216 */ 217 218 /* 219 * Transmitting variable-size objects requires some extra care. 220 * - When writing an array, string, name, or dictionary, the 221 * implementation (not the client) sets all the fields of the value. 222 * - When reading an array, string, or name, the client must set 223 * all the fields of the value. 224 * - When reading a dictionary, the client must set the size field 225 * before calling begin_write_dict; the implementation of begin_write_dict 226 * allocates the list. 227 */ 228 229 /* 230 * Setting parameters must use a "two-phase commit" policy. Specifically, 231 * any put_params procedure must observe the following discipline: 232 233 1. For each parameter known to the device, ask the parameter list if 234 there is a new value, and if so, make all necessary validity checks. If any 235 check fails, call param_signal_error for that parameter, but continue to 236 check further parameters. Normally, this step should not alter the state of 237 the device; however, if the device allows changing any parameters that are 238 read-only by default (for example, BitsPerPixel or ProcessColorModel), or if 239 it replaces the default put_params behavior for any parameter (for example, 240 if it handles MediaSize or Resolution itself to forestall the normal closing 241 of the device when these are set), step 1 of put_params must change the 242 parameters in the device state, and step 2 must undo the changes if 243 returning an error. 244 245 2. Call the "superclass" put_params routine. For printer devices, 246 this is gdev_prn_put_params; for other devices, it is gx_default_put_params. 247 Note that this must be done even if errors were detected in step 1. If this 248 routine returns an error code, or if step 1 detected an error, undo any 249 changes that step 1 made in the device state, and return the error code. 250 251 3. Install the new parameter values in the device. If necessary, 252 close the device first; a higher-level routine (gs_putdeviceparams) will 253 reopen the device if necessary. 254 255 */ 256 257 typedef struct gs_param_list_procs_s { 258 259 /* Transmit a typed value. */ 260 /* 261 * Note that read/write_typed do a begin_read/write_collection 262 * if the type is one of the heterogenous collection types. 263 * Note also that even for reading, the caller must set pvalue->type 264 * to the desired type or to gs_param_type_any. 265 */ 266 267 #define param_proc_xmit_typed(proc)\ 268 int proc(gs_param_list *, gs_param_name, gs_param_typed_value *) 269 param_proc_xmit_typed((*xmit_typed)); 270 /* See below for param_read_[requested_]typed */ 271 #define param_write_typed(plist, pkey, pvalue)\ 272 (*(plist)->procs->xmit_typed)(plist, pkey, pvalue) 273 274 /* Start transmitting a dictionary or heterogenous value. */ 275 276 #define param_proc_begin_xmit_collection(proc)\ 277 int proc(gs_param_list *, gs_param_name, gs_param_dict *,\ 278 gs_param_collection_type_t) 279 param_proc_begin_xmit_collection((*begin_xmit_collection)); 280 #define param_begin_read_collection(plist, pkey, pvalue, coll_type)\ 281 (*(plist)->procs->begin_xmit_collection)(plist, pkey, pvalue, coll_type) 282 #define param_begin_read_dict(l, k, v, int_keys)\ 283 param_begin_read_collection(l, k, v,\ 284 (int_keys ? gs_param_collection_dict_int_keys :\ 285 gs_param_collection_dict_any)) 286 #define param_begin_write_collection(plist, pkey, pvalue, coll_type)\ 287 (*(plist)->procs->begin_xmit_collection)(plist, pkey, pvalue, coll_type) 288 #define param_begin_write_dict(l, k, v, int_keys)\ 289 param_begin_write_collection(l, k, v,\ 290 (int_keys ? gs_param_collection_dict_int_keys :\ 291 gs_param_collection_dict_any)) 292 293 /* Finish transmitting a collection value. */ 294 295 #define param_proc_end_xmit_collection(proc)\ 296 int proc(gs_param_list *, gs_param_name, gs_param_dict *) 297 param_proc_end_xmit_collection((*end_xmit_collection)); 298 #define param_end_read_collection(plist, pkey, pvalue)\ 299 (*(plist)->procs->end_xmit_collection)(plist, pkey, pvalue) 300 #define param_end_read_dict(l, k, v) param_end_read_collection(l, k, v) 301 #define param_end_write_collection(plist, pkey, pvalue)\ 302 (*(plist)->procs->end_xmit_collection)(plist, pkey, pvalue) 303 #define param_end_write_dict(l, k, v) param_end_write_collection(l, k, v) 304 305 /* 306 * Get the next key in sequence. 307 * (Only used when reading.) 308 * Use param_init_enumerator(...) to reset to first key. 309 */ 310 311 #define param_proc_next_key(proc)\ 312 int proc(gs_param_list *, gs_param_enumerator_t *, gs_param_key_t *) 313 param_proc_next_key((*next_key)); 314 #define param_get_next_key(plist, penum, pkey)\ 315 (*(plist)->procs->next_key)(plist, penum, pkey) 316 317 /* 318 * Request a specific parameter. (Only used when writing, before 319 * writing any values.) If no specific parameters are requested, 320 * param_requested always returns -1; if specific parameters 321 * are requested, param_requested will return 1 for those, 322 * and may return either 0 or 1 for others. 323 */ 324 325 #define param_proc_request(proc)\ 326 int proc(gs_param_list *, gs_param_name) 327 param_proc_request((*request)); 328 329 #define param_request(plist, pkey)\ 330 ((plist)->procs->request(plist, pkey)) 331 332 /* 333 * Determine whether a given key has been requested. (Only used 334 * when writing.) A return value of -1 means that no specific 335 * parameters have been requested; 0 means specific parameters have 336 * been requested, but not this one; 1 means this parameter has 337 * been requested specifically. 338 */ 339 340 #define param_proc_requested(proc)\ 341 int proc(const gs_param_list *, gs_param_name) 342 param_proc_requested((*requested)); 343 #define param_requested(plist, pkey)\ 344 (*(plist)->procs->requested)(plist, pkey) 345 346 /* Get the 'policy' associated with an out-of-range parameter value. */ 347 /* (Only used when reading.) */ 348 349 #define param_proc_get_policy(proc)\ 350 int proc(gs_param_list *, gs_param_name) 351 param_proc_get_policy((*get_policy)); 352 #define param_get_policy(plist, pkey)\ 353 (*(plist)->procs->get_policy)(plist, pkey) 354 355 /* 356 * Signal an error. (Only used when reading.) 357 * The procedure may return a different error code, 358 * or may return 0 indicating that the error is to be ignored. 359 */ 360 361 #define param_proc_signal_error(proc)\ 362 int proc(gs_param_list *, gs_param_name, int) 363 param_proc_signal_error((*signal_error)); 364 #define param_signal_error(plist, pkey, code)\ 365 (*(plist)->procs->signal_error)(plist, pkey, code) 366 #define param_return_error(plist, pkey, code)\ 367 return_error(param_signal_error(plist, pkey, code)) 368 369 /* 370 * "Commit" a set of changes. (Only used when reading.) 371 * This is called at the end of the first phase. 372 */ 373 374 #define param_proc_commit(proc)\ 375 int proc(gs_param_list *) 376 param_proc_commit((*commit)); 377 #define param_commit(plist)\ 378 (*(plist)->procs->commit)(plist) 379 380 } gs_param_list_procs; 381 382 /* Transmit typed parameters. */ 383 int param_read_requested_typed(gs_param_list *, gs_param_name, 384 gs_param_typed_value *); 385 386 #define param_read_typed(plist, pkey, pvalue)\ 387 ((pvalue)->type = gs_param_type_any,\ 388 param_read_requested_typed(plist, pkey, pvalue)) 389 390 /* Transmit parameters of specific types. */ 391 int param_read_null(gs_param_list *, gs_param_name); 392 int param_write_null(gs_param_list *, gs_param_name); 393 int param_read_bool(gs_param_list *, gs_param_name, bool *); 394 int param_write_bool(gs_param_list *, gs_param_name, const bool *); 395 int param_read_int(gs_param_list *, gs_param_name, int *); 396 int param_write_int(gs_param_list *, gs_param_name, const int *); 397 int param_read_long(gs_param_list *, gs_param_name, long *); 398 int param_write_long(gs_param_list *, gs_param_name, const long *); 399 int param_read_float(gs_param_list *, gs_param_name, float *); 400 int param_write_float(gs_param_list *, gs_param_name, const float *); 401 int param_read_string(gs_param_list *, gs_param_name, gs_param_string *); 402 int param_write_string(gs_param_list *, gs_param_name, 403 const gs_param_string *); 404 int param_read_name(gs_param_list *, gs_param_name, gs_param_string *); 405 int param_write_name(gs_param_list *, gs_param_name, 406 const gs_param_string *); 407 int param_read_int_array(gs_param_list *, gs_param_name, 408 gs_param_int_array *); 409 int param_write_int_array(gs_param_list *, gs_param_name, 410 const gs_param_int_array *); 411 int param_write_int_values(gs_param_list *, gs_param_name, 412 const int *, uint, bool); 413 int param_read_float_array(gs_param_list *, gs_param_name, 414 gs_param_float_array *); 415 int param_write_float_array(gs_param_list *, gs_param_name, 416 const gs_param_float_array *); 417 int param_write_float_values(gs_param_list *, gs_param_name, 418 const float *, uint, bool); 419 int param_read_string_array(gs_param_list *, gs_param_name, 420 gs_param_string_array *); 421 int param_write_string_array(gs_param_list *, gs_param_name, 422 const gs_param_string_array *); 423 int param_read_name_array(gs_param_list *, gs_param_name, 424 gs_param_string_array *); 425 int param_write_name_array(gs_param_list *, gs_param_name, 426 const gs_param_string_array *); 427 428 /* 429 * Define an abstract parameter list. Implementations are concrete 430 * subclasses. 431 * 432 * The persisent_keys flag allows for both statically and dynamically 433 * allocated keys. The default is static (the keys are normally C string 434 * literals). 435 */ 436 #define gs_param_list_common\ 437 const gs_param_list_procs *procs;\ 438 gs_memory_t *memory; /* for allocating coerced arrays */\ 439 bool persistent_keys 440 struct gs_param_list_s { 441 gs_param_list_common; 442 }; 443 444 /* Set whether the keys for param_write_XXX are persistent. */ 445 /* VMS limits procedure names to 31 characters. */ 446 #define gs_param_list_set_persistent_keys gs_param_list_set_persist_keys 447 void gs_param_list_set_persistent_keys(gs_param_list *, bool); 448 449 /* Initialize a parameter list key enumerator. */ 450 void param_init_enumerator(gs_param_enumerator_t * penum); 451 452 /* 453 * The following interface provides a convenient way to read and set 454 * collections of parameters of any type other than dictionaries. 455 */ 456 457 typedef struct gs_param_item_s { 458 const char *key; 459 byte /*gs_param_type */ type; 460 short offset; /* offset of value in structure */ 461 } gs_param_item_t; 462 #define gs_param_item_end { 0 } /* list terminator */ 463 /* 464 * Transfer a collection of parameters. 465 * For param_write_items, if a parameter value is equal to the value in 466 * the optional default_obj, the item isn't transferred. 467 */ 468 int gs_param_read_items(gs_param_list * plist, void *obj, 469 const gs_param_item_t * items); 470 int gs_param_write_items(gs_param_list * plist, const void *obj, 471 const void *default_obj, 472 const gs_param_item_t * items); 473 474 /* Internal procedure to initialize the common part of a parameter list. */ 475 void gs_param_list_init(gs_param_list *, const gs_param_list_procs *, 476 gs_memory_t *); 477 478 /* 479 * Internal procedure to read a value, with coercion if requested, needed, 480 * and possible. If mem != 0, we can coerce int arrays to float arrays, and 481 * possibly do other coercions later. 482 */ 483 int param_coerce_typed(gs_param_typed_value * pvalue, 484 gs_param_type req_type, gs_memory_t * mem); 485 486 /* ---------------- Default implementation ---------------- */ 487 488 /* 489 * Provide default generic implementations of param_request and 490 * param_requested. 491 */ 492 param_proc_request(gs_param_request_default); /* does nothing */ 493 param_proc_requested(gs_param_requested_default); /* always returns true */ 494 495 /* 496 * Define a default implementation, intended to be usable easily 497 * from C code. The intended usage pattern is: 498 gs_c_param_list list; 499 [... other code here ...] 500 gs_c_param_list_write(&list, mem); 501 [As many as needed:] 502 code = param_write_XXX(&list, "ParamName", ¶m_value); 503 [Check code for <0] 504 gs_c_param_list_read(&list); 505 code = gs_putdeviceparams(dev, &list); 506 gs_c_param_list_release(&list); 507 [Check code for <0] 508 if ( code == 1 ) 509 { 510 code = (*dev_proc(dev, open_device))(dev); 511 [Check code for <0] 512 } 513 * 514 * This implementation also has the special property that it can forward 515 * unrecognized param_read_ calls to another parameter list, called the 516 * target. This allows constructing incrementally modified parameter lists. 517 * Note that this is only relevant for put_params (reading from the 518 * parameter list). 519 */ 520 521 typedef struct gs_c_param_s gs_c_param; /* opaque here */ 522 typedef struct gs_c_param_list_s { 523 gs_param_list_common; 524 gs_c_param *head; 525 gs_param_list *target; 526 uint count; 527 bool any_requested; 528 gs_param_collection_type_t coll_type; 529 } gs_c_param_list; 530 #define private_st_c_param_list() /* in gsparam.c */\ 531 gs_private_st_ptrs2(st_c_param_list, gs_c_param_list, "c_param_list",\ 532 c_param_list_enum_ptrs, c_param_list_reloc_ptrs, head, target) 533 534 /* Define a GC descriptor for gs_param_string. */ 535 /* This structure descriptor is only for non persistent gs_param_strings. */ 536 #define private_st_gs_param_string() /* in gdevdevn.c */\ 537 gs_private_st_composite(st_gs_param_string, gs_param_string, "gs_param_string",\ 538 param_string_enum_ptrs, param_string_reloc_ptrs) 539 540 /* Set the target of a C parameter list. */ 541 void gs_c_param_list_set_target(gs_c_param_list *, gs_param_list *); 542 543 /* 544 * Clients normally allocate the gs_c_param_list on the stack, but we 545 * provide a procedure for allocating one in memory. 546 */ 547 gs_c_param_list *gs_c_param_list_alloc(gs_memory_t *, client_name_t); 548 void gs_c_param_list_write(gs_c_param_list *, gs_memory_t *); 549 void gs_c_param_list_write_more(gs_c_param_list *); /* switch back to writing, no init */ 550 void gs_c_param_list_read(gs_c_param_list *); /* switch to reading */ 551 void gs_c_param_list_release(gs_c_param_list *); 552 553 #endif /* gsparam_INCLUDED */ 554