gsparam.c 12 KB

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