gsparam.c 12 KB

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