]>
diplodocus.org Git - nmh/blob - sbr/vector.c
1 /* vector.c -- dynamically sized vectors
3 * This code is Copyright (c) 2013, by the authors of nmh. See the
4 * COPYRIGHT file in the root directory of the nmh distribution for
5 * complete copyright information.
9 * This file defines several kinds of vectors:
11 * svector: vector of char arrays
12 * ivector: vector of ints
14 * The interfaces provide only the capabilities needed by nmh. The
15 * implementations rely on dynamic allocation, so that a vector
16 * can be as large as needed, as long as it fits in (virtual) memory.
22 /* The default size of a struct bvector's bits, measured in bits.
23 * The struct's tiny member is used for storage. */
24 #define BVEC_INIT_SIZE (sizeof *(((bvector_t)NULL)->tiny) * CHAR_BIT)
26 /* The default number of char pointers in a struct svector. */
27 #define SVEC_INIT_SIZE 256
29 /* The default number of ints in a struct ivector. */
30 #define IVEC_INIT_SIZE 256
33 * These try to hide the type of the "bits" member of bvector. But if
34 * that is changed to a type that's wider than unsigned long, the 1ul
35 * constants in the code below must also be changed to a 1 that's at
36 * least as wide as the new type.
39 /* The *sizeof* struct bvector's bits member. Not its size in bits. */
40 #define BVEC_SIZEOF_BITS (sizeof *(((bvector_t)NULL)->bits))
41 /* The number of bits held in one element of the bits member. */
42 #define BVEC_BITS_BITS (BVEC_SIZEOF_BITS * CHAR_BIT)
43 /* The index of bit n in struct bvector's bits member. */
44 #define BVEC_WORD(n) ((n) / BVEC_BITS_BITS)
45 /* The index of bit n within a single struct bvector's bits member. */
46 #define BVEC_OFFSET(n) ((n) % BVEC_BITS_BITS)
47 /* The number of elements bits needs to cover bit n, measured in bytes. */
48 #define BVEC_BYTES(n) (((n) / BVEC_BITS_BITS + 1) * BVEC_SIZEOF_BITS)
50 /* bvector_resize ensures the storage used for bits can cover bit
51 * newsize. It always increases the size of the storage used for bits,
52 * even if newsize would have been covered by the existing storage.
53 * Thus it's normally only called when it's known the storage must grow. */
54 static void bvector_resize (bvector_t vec
, size_t newsize
);
57 bvector_create (void) {
60 /* See "wider than unsigned long" comment above. */
61 assert (sizeof *vec
->bits
<= sizeof 1ul);
69 void bvector_init(struct bvector
*bv
)
72 bv
->maxsize
= BVEC_INIT_SIZE
;
73 memset(bv
->tiny
, 0, sizeof bv
->tiny
);
77 bvector_copy (bvector_t dest
, bvector_t src
) {
78 size_t bytes
= BVEC_BYTES(src
->maxsize
);
80 if (dest
->bits
!= dest
->tiny
)
82 if (bytes
<= sizeof dest
->tiny
)
83 dest
->bits
= dest
->tiny
;
85 dest
->bits
= mh_xmalloc (bytes
);
86 memcpy (dest
->bits
, src
->bits
, bytes
);
87 dest
->maxsize
= src
->maxsize
;
91 bvector_free (bvector_t vec
) {
96 void bvector_fini(struct bvector
*bv
)
98 if (bv
->bits
!= bv
->tiny
)
103 bvector_clear (bvector_t vec
, size_t n
) {
104 if (n
< vec
->maxsize
)
105 vec
->bits
[BVEC_WORD(n
)] &= ~(1ul << BVEC_OFFSET(n
));
110 bvector_clear_all (bvector_t vec
) {
111 memset (vec
->bits
, 0, BVEC_BYTES(vec
->maxsize
));
116 bvector_set (bvector_t vec
, size_t n
) {
117 size_t word
= BVEC_WORD(n
);
118 size_t offset
= BVEC_OFFSET(n
);
120 if (n
>= vec
->maxsize
)
121 bvector_resize (vec
, n
);
122 vec
->bits
[word
] |= 1ul << offset
;
126 bvector_at (bvector_t vec
, size_t i
) {
127 if (i
< vec
->maxsize
)
128 return !!(vec
->bits
[BVEC_WORD(i
)] & (1ul << BVEC_OFFSET(i
)));
134 bvector_resize (bvector_t vec
, size_t newsize
) {
135 size_t oldsize
= vec
->maxsize
;
138 while ((vec
->maxsize
*= 2) < newsize
)
140 bytes
= BVEC_BYTES(vec
->maxsize
);
141 if (vec
->bits
== vec
->tiny
) {
142 vec
->bits
= mh_xmalloc(bytes
);
143 memcpy(vec
->bits
, vec
->tiny
, sizeof vec
->tiny
);
145 vec
->bits
= mh_xrealloc(vec
->bits
, bytes
);
147 memset(vec
->bits
+ (oldsize
/ BVEC_BITS_BITS
), 0,
148 (vec
->maxsize
- oldsize
) / CHAR_BIT
);
152 bvector_first_bits (bvector_t vec
) {
163 static void svector_resize (svector_t
, size_t);
166 svector_create (size_t init_size
) {
171 vec
->maxsize
= init_size
? init_size
: SVEC_INIT_SIZE
;
172 bytes
= vec
->maxsize
* sizeof (char *);
173 vec
->strs
= mh_xcalloc (1, bytes
);
180 svector_free (svector_t vec
) {
186 svector_push_back (svector_t vec
, char *s
) {
187 if (++vec
->size
>= vec
->maxsize
)
188 svector_resize (vec
, vec
->size
);
189 return vec
->strs
[vec
->size
-1] = s
;
193 svector_at (svector_t vec
, size_t i
) {
194 if (i
>= vec
->maxsize
)
195 svector_resize (vec
, i
);
200 * Return address of first element that stringwise matches s.
201 * The caller can replace the contents of the return address.
204 svector_find (svector_t vec
, const char *s
) {
206 char **str
= vec
->strs
;
208 for (i
= 0; i
< vec
->size
; ++i
, ++str
) {
209 if (*str
&& ! strcmp(*str
, s
)) {
218 svector_strs (svector_t vec
) {
223 svector_size (svector_t vec
) {
228 svector_resize (svector_t vec
, size_t maxsize
) {
229 size_t old_maxsize
= vec
->maxsize
;
231 while ((vec
->maxsize
*= 2) < maxsize
)
233 vec
->strs
= mh_xrealloc (vec
->strs
, vec
->maxsize
* sizeof (char *));
234 memset(vec
->strs
+ old_maxsize
, 0,
235 (vec
->maxsize
- old_maxsize
) * sizeof *vec
->strs
);
245 static void ivector_resize (ivector_t
, size_t);
248 ivector_create (size_t init_size
) {
253 vec
->maxsize
= init_size
? init_size
: IVEC_INIT_SIZE
;
254 bytes
= vec
->maxsize
* sizeof (int);
255 vec
->ints
= mh_xcalloc (1, bytes
);
262 ivector_free (ivector_t vec
) {
268 ivector_push_back (ivector_t vec
, int n
) {
269 if (++vec
->size
>= vec
->maxsize
)
270 ivector_resize (vec
, vec
->size
);
271 return vec
->ints
[vec
->size
-1] = n
;
275 ivector_at (ivector_t vec
, size_t i
) {
276 if (i
>= vec
->maxsize
)
277 ivector_resize (vec
, i
);
282 ivector_atp (ivector_t vec
, size_t i
) {
283 if (i
>= vec
->maxsize
)
284 ivector_resize (vec
, i
);
285 return &vec
->ints
[i
];
289 ivector_resize (ivector_t vec
, size_t maxsize
) {
290 size_t old_maxsize
= vec
->maxsize
;
292 while ((vec
->maxsize
*= 2) < maxsize
)
294 vec
->ints
= mh_xrealloc (vec
->ints
, vec
->maxsize
* sizeof (int));
295 memset(vec
->ints
+ old_maxsize
, 0,
296 (vec
->maxsize
- old_maxsize
) * sizeof *vec
->ints
);