weak-vector.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. /* Copyright 1995-1996,1998,2000-2001,2003,2006,2008-2014,2018
  2. Free Software Foundation, Inc.
  3. This file is part of Guile.
  4. Guile is free software: you can redistribute it and/or modify it
  5. under the terms of the GNU Lesser General Public License as published
  6. by the Free Software Foundation, either version 3 of the License, or
  7. (at your option) any later version.
  8. Guile is distributed in the hope that it will be useful, but WITHOUT
  9. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  10. FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
  11. License for more details.
  12. You should have received a copy of the GNU Lesser General Public
  13. License along with Guile. If not, see
  14. <https://www.gnu.org/licenses/>. */
  15. #ifdef HAVE_CONFIG_H
  16. # include <config.h>
  17. #endif
  18. #include <stdio.h>
  19. #include <string.h>
  20. #include "boolean.h"
  21. #include "extensions.h"
  22. #include "gsubr.h"
  23. #include "list.h"
  24. #include "pairs.h"
  25. #include "vectors.h"
  26. #include "weak-vector.h"
  27. /* {Weak Vectors}
  28. */
  29. #define VECTOR_MAX_LENGTH (SCM_T_BITS_MAX >> 8)
  30. SCM
  31. scm_c_make_weak_vector (size_t len, SCM fill)
  32. #define FUNC_NAME "make-weak-vector"
  33. {
  34. SCM wv;
  35. size_t j;
  36. SCM_ASSERT_RANGE (1, scm_from_size_t (len), len <= VECTOR_MAX_LENGTH);
  37. if (SCM_UNBNDP (fill))
  38. fill = SCM_UNSPECIFIED;
  39. wv = SCM_PACK_POINTER (scm_gc_malloc_pointerless ((len + 1) * sizeof (SCM),
  40. "weak vector"));
  41. SCM_SET_CELL_WORD_0 (wv, (len << 8) | scm_tc7_wvect);
  42. if (SCM_HEAP_OBJECT_P (fill))
  43. {
  44. memset (SCM_I_VECTOR_WELTS (wv), 0, len * sizeof (SCM));
  45. for (j = 0; j < len; j++)
  46. scm_c_weak_vector_set_x (wv, j, fill);
  47. }
  48. else
  49. for (j = 0; j < len; j++)
  50. SCM_SIMPLE_VECTOR_SET (wv, j, fill);
  51. return wv;
  52. }
  53. #undef FUNC_NAME
  54. SCM_DEFINE (scm_make_weak_vector, "make-weak-vector", 1, 1, 0,
  55. (SCM size, SCM fill),
  56. "Return a weak vector with @var{size} elements. If the optional\n"
  57. "argument @var{fill} is given, all entries in the vector will be\n"
  58. "set to @var{fill}. The default value for @var{fill} is the\n"
  59. "empty list.")
  60. #define FUNC_NAME s_scm_make_weak_vector
  61. {
  62. return scm_c_make_weak_vector (scm_to_size_t (size), fill);
  63. }
  64. #undef FUNC_NAME
  65. SCM_REGISTER_PROC(s_list_to_weak_vector, "list->weak-vector", 1, 0, 0, scm_weak_vector);
  66. SCM_DEFINE (scm_weak_vector, "weak-vector", 0, 0, 1,
  67. (SCM lst),
  68. "@deffnx {Scheme Procedure} list->weak-vector lst\n"
  69. "Construct a weak vector from a list: @code{weak-vector} uses\n"
  70. "the list of its arguments while @code{list->weak-vector} uses\n"
  71. "its only argument @var{l} (a list) to construct a weak vector\n"
  72. "the same way @code{list->vector} would.")
  73. #define FUNC_NAME s_scm_weak_vector
  74. {
  75. SCM wv;
  76. size_t i;
  77. long c_size;
  78. SCM_VALIDATE_LIST_COPYLEN (SCM_ARG1, lst, c_size);
  79. wv = scm_c_make_weak_vector ((size_t) c_size, SCM_BOOL_F);
  80. for (i = 0; scm_is_pair (lst); lst = SCM_CDR (lst), i++)
  81. scm_c_weak_vector_set_x (wv, i, SCM_CAR (lst));
  82. return wv;
  83. }
  84. #undef FUNC_NAME
  85. SCM_DEFINE (scm_weak_vector_p, "weak-vector?", 1, 0, 0,
  86. (SCM obj),
  87. "Return @code{#t} if @var{obj} is a weak vector. Note that all\n"
  88. "weak hashes are also weak vectors.")
  89. #define FUNC_NAME s_scm_weak_vector_p
  90. {
  91. return scm_from_bool (scm_is_weak_vector (obj));
  92. }
  93. #undef FUNC_NAME
  94. int
  95. scm_is_weak_vector (SCM obj)
  96. #define FUNC_NAME s_scm_weak_vector_p
  97. {
  98. return SCM_I_WVECTP (obj);
  99. }
  100. #undef FUNC_NAME
  101. #define SCM_VALIDATE_WEAK_VECTOR(pos, var) \
  102. SCM_I_MAKE_VALIDATE_MSG2 (pos, var, SCM_I_WVECTP, "weak vector")
  103. SCM_DEFINE (scm_weak_vector_length, "weak-vector-length", 1, 0, 0,
  104. (SCM wvect),
  105. "Like @code{vector-length}, but for weak vectors.")
  106. #define FUNC_NAME s_scm_weak_vector_length
  107. {
  108. return scm_from_size_t (scm_c_weak_vector_length (wvect));
  109. }
  110. #undef FUNC_NAME
  111. size_t
  112. scm_c_weak_vector_length (SCM wvect)
  113. #define FUNC_NAME s_scm_weak_vector_length
  114. {
  115. SCM_VALIDATE_WEAK_VECTOR (1, wvect);
  116. return SCM_I_VECTOR_LENGTH (wvect);
  117. }
  118. #undef FUNC_NAME
  119. SCM_DEFINE (scm_weak_vector_ref, "weak-vector-ref", 2, 0, 0,
  120. (SCM wvect, SCM k),
  121. "Like @code{vector-ref}, but for weak vectors.")
  122. #define FUNC_NAME s_scm_weak_vector_ref
  123. {
  124. return scm_c_weak_vector_ref (wvect, scm_to_size_t (k));
  125. }
  126. #undef FUNC_NAME
  127. struct weak_vector_ref_data
  128. {
  129. SCM wv;
  130. size_t k;
  131. };
  132. static void*
  133. weak_vector_ref (void *data)
  134. {
  135. struct weak_vector_ref_data *d = data;
  136. return (void *) SCM_UNPACK (SCM_SIMPLE_VECTOR_REF (d->wv, d->k));
  137. }
  138. SCM
  139. scm_c_weak_vector_ref (SCM wv, size_t k)
  140. #define FUNC_NAME s_scm_weak_vector_ref
  141. {
  142. struct weak_vector_ref_data d;
  143. void *ret;
  144. SCM_VALIDATE_WEAK_VECTOR (1, wv);
  145. d.wv = wv;
  146. d.k = k;
  147. if (k >= SCM_I_VECTOR_LENGTH (wv))
  148. scm_out_of_range ("weak-vector-ref", scm_from_size_t (k));
  149. ret = GC_call_with_alloc_lock (weak_vector_ref, &d);
  150. if (ret)
  151. return SCM_PACK_POINTER (ret);
  152. else
  153. return SCM_BOOL_F;
  154. }
  155. #undef FUNC_NAME
  156. SCM_DEFINE (scm_weak_vector_set_x, "weak-vector-set!", 3, 0, 0,
  157. (SCM wvect, SCM k, SCM obj),
  158. "Like @code{vector-set!}, but for weak vectors.")
  159. #define FUNC_NAME s_scm_weak_vector_set_x
  160. {
  161. scm_c_weak_vector_set_x (wvect, scm_to_size_t (k), obj);
  162. return SCM_UNSPECIFIED;
  163. }
  164. #undef FUNC_NAME
  165. void
  166. scm_c_weak_vector_set_x (SCM wv, size_t k, SCM x)
  167. #define FUNC_NAME s_scm_weak_vector_set_x
  168. {
  169. SCM *elts;
  170. struct weak_vector_ref_data d;
  171. void *prev;
  172. SCM_VALIDATE_WEAK_VECTOR (1, wv);
  173. d.wv = wv;
  174. d.k = k;
  175. if (k >= SCM_I_VECTOR_LENGTH (wv))
  176. scm_out_of_range ("weak-vector-set!", scm_from_size_t (k));
  177. prev = GC_call_with_alloc_lock (weak_vector_ref, &d);
  178. elts = SCM_I_VECTOR_WELTS (wv);
  179. if (prev && SCM_HEAP_OBJECT_P (SCM_PACK_POINTER (prev)))
  180. GC_unregister_disappearing_link ((void **) &elts[k]);
  181. elts[k] = x;
  182. if (SCM_HEAP_OBJECT_P (x))
  183. SCM_I_REGISTER_DISAPPEARING_LINK ((void **) &elts[k],
  184. SCM2PTR (x));
  185. }
  186. #undef FUNC_NAME
  187. static void
  188. scm_init_weak_vector_builtins (void)
  189. {
  190. #ifndef SCM_MAGIC_SNARFER
  191. #include "weak-vector.x"
  192. #endif
  193. }
  194. void
  195. scm_init_weak_vectors ()
  196. {
  197. scm_c_register_extension ("libguile-" SCM_EFFECTIVE_VERSION,
  198. "scm_init_weak_vector_builtins",
  199. (scm_t_extension_init_func)scm_init_weak_vector_builtins,
  200. NULL);
  201. }