idict.h 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. /* Copyright (C) 1989, 1995, 1997, 1998 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: idict.h,v 1.6 2004/08/04 19:36:12 stefan Exp $ */
  14. /* Interfaces for Ghostscript dictionary package */
  15. #ifndef idict_INCLUDED
  16. # define idict_INCLUDED
  17. #include "iddstack.h"
  18. /*
  19. * Contrary to our usual practice, we expose the (first-level)
  20. * representation of a dictionary in the interface file,
  21. * because it is so important that access checking go fast.
  22. * The access attributes for the dictionary are stored in
  23. * the values ref.
  24. */
  25. struct dict_s {
  26. ref values; /* t_array, values */
  27. ref keys; /* t_shortarray or t_array, keys */
  28. ref count; /* t_integer, count of occupied entries */
  29. /* (length) */
  30. ref maxlength; /* t_integer, maxlength as seen by client. */
  31. ref memory; /* foreign t_struct, the allocator that */
  32. /* created this dictionary */
  33. #define dict_memory(pdict) r_ptr(&(pdict)->memory, gs_ref_memory_t)
  34. #define dict_mem(pdict) r_ptr(&(pdict)->memory, gs_memory_t)
  35. };
  36. /*
  37. * Define the maximum size of a dictionary.
  38. */
  39. extern const uint dict_max_size;
  40. /*
  41. * Define whether dictionaries expand automatically when full. Note that
  42. * if dict_auto_expand is true, dict_put, dict_copy, dict_resize, and
  43. * dict_grow cannot return e_dictfull; however, they can return e_VMerror.
  44. * (dict_find can return e_dictfull even if dict_auto_expand is true.)
  45. */
  46. extern bool dict_auto_expand;
  47. /*
  48. * Create a dictionary.
  49. */
  50. #ifndef gs_ref_memory_DEFINED
  51. # define gs_ref_memory_DEFINED
  52. typedef struct gs_ref_memory_s gs_ref_memory_t;
  53. #endif
  54. int dict_alloc(gs_ref_memory_t *, uint maxlength, ref * pdref);
  55. #define dict_create(maxlen, pdref)\
  56. dict_alloc(iimemory, maxlen, pdref)
  57. /*
  58. * Return a pointer to a ref that holds the access attributes
  59. * for a dictionary.
  60. */
  61. #define dict_access_ref(pdref) (&(pdref)->value.pdict->values)
  62. /*
  63. * Check a dictionary for read or write permission.
  64. * Note: this does NOT check the type of its operand!
  65. */
  66. #define check_dict_read(dref) check_read(*dict_access_ref(&dref))
  67. #define check_dict_write(dref) check_write(*dict_access_ref(&dref))
  68. /*
  69. * Look up a key in a dictionary. Store a pointer to the value slot
  70. * where found, or to the (value) slot for inserting.
  71. * The caller is responsible for checking that the dictionary is readable.
  72. * Return 1 if found, 0 if not and there is room for a new entry,
  73. * Failure returns:
  74. * e_typecheck if the key is null;
  75. * e_invalidaccess if the key is a string lacking read access;
  76. * e_VMerror or e_limitcheck if the key is a string and the corresponding
  77. * error occurs from attempting to convert it to a name;
  78. * e_dictfull if the dictionary is full and the key is missing.
  79. */
  80. int dict_find(const ref * pdref, const ref * key, ref ** ppvalue);
  81. /*
  82. * Look up a (constant) C string in a dictionary.
  83. * Return 1 if found, <= 0 if not.
  84. */
  85. int dict_find_string(const ref * pdref, const char *kstr, ref ** ppvalue);
  86. /*
  87. * Enter a key-value pair in a dictionary.
  88. * The caller is responsible for checking that the dictionary is writable.
  89. * Return 1 if this was a new entry, 0 if this replaced an existing entry.
  90. * Failure returns are as for dict_find, except that e_dictfull doesn't
  91. * occur if the dictionary is full but expandable, plus:
  92. * e_invalidaccess for an attempt to store a younger key or value into
  93. * an older dictionary, or as described just below;
  94. * e_VMerror if a VMerror occurred while trying to expand the
  95. * dictionary.
  96. * Note that this procedure, and all procedures that may change the
  97. * contents of a dictionary, take a pointer to a dictionary stack,
  98. * so they can update the cached 'top' values and also update the cached
  99. * value pointer in names. A NULL pointer for the dictionary stack is
  100. * allowed, but in this case, if the dictionary is present on any dictionary
  101. * stack, an e_invalidaccess error will occur if cached values need updating.
  102. * THIS ERROR CHECK IS NOT IMPLEMENTED YET.
  103. */
  104. int dict_put(ref * pdref, const ref * key, const ref * pvalue,
  105. dict_stack_t *pds);
  106. /*
  107. * Enter a key-value pair where the key is a (constant) C string.
  108. */
  109. int dict_put_string(ref * pdref, const char *kstr, const ref * pvalue,
  110. dict_stack_t *pds);
  111. /*
  112. * Remove a key-value pair from a dictionary.
  113. * Return 0 or e_undefined.
  114. */
  115. int dict_undef(ref * pdref, const ref * key, dict_stack_t *pds);
  116. /*
  117. * Return the number of elements in a dictionary.
  118. */
  119. uint dict_length(const ref * pdref);
  120. /*
  121. * Return the capacity of a dictionary.
  122. */
  123. uint dict_maxlength(const ref * pdref);
  124. /*
  125. * Return the maximum index of a slot within a dictionary.
  126. * Note that this may be greater than maxlength.
  127. */
  128. uint dict_max_index(const ref * pdref);
  129. /*
  130. * Copy one dictionary into another.
  131. * Return 0 or e_dictfull.
  132. * If new_only is true, only copy entries whose keys
  133. * aren't already present in the destination.
  134. */
  135. int dict_copy_entries(const ref * dfrom, ref * dto, bool new_only,
  136. dict_stack_t *pds);
  137. #define dict_copy(dfrom, dto, pds) dict_copy_entries(dfrom, dto, false, pds)
  138. #define dict_copy_new(dfrom, dto, pds) dict_copy_entries(dfrom, dto, true, pds)
  139. /*
  140. * Grow or shrink a dictionary.
  141. * Return 0, e_dictfull, or e_VMerror.
  142. */
  143. int dict_resize(ref * pdref, uint newmaxlength, dict_stack_t *pds);
  144. /*
  145. * Grow a dictionary in the same way as dict_put does.
  146. * We export this for some special-case code in zop_def.
  147. */
  148. int dict_grow(ref * pdref, dict_stack_t *pds);
  149. /*
  150. * Ensure that a dictionary uses the unpacked representation for keys.
  151. * (This is of no interest to ordinary clients.)
  152. */
  153. int dict_unpack(ref * pdref, dict_stack_t *pds);
  154. /*
  155. * Prepare to enumerate a dictionary.
  156. * Return an integer suitable for the first call to dict_next.
  157. */
  158. int dict_first(const ref * pdref);
  159. /*
  160. * Enumerate the next element of a dictionary.
  161. * index is initially the result of a call on dict_first.
  162. * Either store a key and value at eltp[0] and eltp[1]
  163. * and return an updated index, or return -1
  164. * to signal that there are no more elements in the dictionary.
  165. */
  166. int dict_next(const ref * pdref, int index, ref * eltp);
  167. /*
  168. * Given a value pointer return by dict_find, return an index that
  169. * identifies the entry within the dictionary. (This may, but need not,
  170. * be the same as the index returned by dict_next.)
  171. * The index is in the range [0..max_index-1].
  172. */
  173. int dict_value_index(const ref * pdref, const ref * pvalue);
  174. /*
  175. * Given an index in [0..max_index-1], as returned by dict_value_index,
  176. * return the key and value, as returned by dict_next.
  177. * If the index designates an unoccupied entry, return e_undefined.
  178. */
  179. int dict_index_entry(const ref * pdref, int index, ref * eltp);
  180. /*
  181. * The following are some internal details that are used in both the
  182. * implementation and some high-performance clients.
  183. */
  184. /* On machines with reasonable amounts of memory, we round up dictionary
  185. * sizes to the next power of 2 whenever possible, to allow us to use
  186. * masking rather than division for computing the hash index.
  187. * Unfortunately, if we required this, it would cut the maximum size of a
  188. * dictionary in half. Therefore, on such machines, we distinguish
  189. * "huge" dictionaries (dictionaries whose size is larger than the largest
  190. * power of 2 less than dict_max_size) as a special case:
  191. *
  192. * - If the top dictionary on the stack is huge, we set the dtop
  193. * parameters so that the fast inline lookup will always fail.
  194. *
  195. * - For general lookup, we use the slower hash_mod algorithm for
  196. * huge dictionaries.
  197. */
  198. #define dict_max_non_huge ((uint)(max_array_size / 2 + 1))
  199. /* Define the hashing function for names. */
  200. /* We don't have to scramble the index, because */
  201. /* indices are assigned in a scattered order (see name_ref in iname.c). */
  202. #define dict_name_index_hash(nidx) (nidx)
  203. /* Hash an arbitrary non-negative or unsigned integer into a dictionary. */
  204. #define dict_hash_mod_rem(hash, size) ((hash) % (size))
  205. #define dict_hash_mod_mask(hash, size) ((hash) & ((size) - 1))
  206. #define dict_hash_mod_small(hash, size) dict_hash_mod_rem(hash, size)
  207. #define dict_hash_mod_inline_small(hash, size) dict_hash_mod_rem(hash, size)
  208. #define dict_hash_mod_large(hash, size)\
  209. (size > dict_max_non_huge ? dict_hash_mod_rem(hash, size) :\
  210. dict_hash_mod_mask(hash, size))
  211. #define dict_hash_mod_inline_large(hash, size) dict_hash_mod_mask(hash, size)
  212. /* Round up the requested size of a dictionary. Return 0 if too big. */
  213. uint dict_round_size_small(uint rsize);
  214. uint dict_round_size_large(uint rsize);
  215. /* Choose the algorithms depending on the size of memory. */
  216. #if arch_small_memory
  217. # define dict_hash_mod(h, s) dict_hash_mod_small(h, s)
  218. # define dict_hash_mod_inline(h, s) dict_hash_mod_inline_small(h, s)
  219. # define dict_round_size(s) dict_round_size_small(s)
  220. #else
  221. # ifdef DEBUG
  222. # define dict_hash_mod(h, s)\
  223. (gs_debug_c('.') ? dict_hash_mod_small(h, s) :\
  224. dict_hash_mod_large(h, s))
  225. # define dict_hash_mod_inline(h, s)\
  226. (gs_debug_c('.') ? dict_hash_mod_inline_small(h, s) :\
  227. dict_hash_mod_inline_large(h, s))
  228. # define dict_round_size(s)\
  229. (gs_debug_c('.') ? dict_round_size_small(s) :\
  230. dict_round_size_large(s))
  231. # else
  232. # define dict_hash_mod(h, s) dict_hash_mod_large(h, s)
  233. # define dict_hash_mod_inline(h, s) dict_hash_mod_inline_large(h, s)
  234. # define dict_round_size(s) dict_round_size_large(s)
  235. # endif
  236. #endif
  237. #endif /* idict_INCLUDED */