]>
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
);
61 /* See "wider than unsigned long" comment above. */
62 assert (sizeof *vec
->bits
<= sizeof 1ul);
71 bvector_init(struct bvector
*bv
)
74 bv
->maxsize
= BVEC_INIT_SIZE
;
75 memset(bv
->tiny
, 0, sizeof bv
->tiny
);
79 bvector_copy (bvector_t dest
, bvector_t src
)
81 size_t bytes
= BVEC_BYTES(src
->maxsize
);
83 if (dest
->bits
!= dest
->tiny
)
85 if (bytes
<= sizeof dest
->tiny
)
86 dest
->bits
= dest
->tiny
;
88 dest
->bits
= mh_xmalloc (bytes
);
89 memcpy (dest
->bits
, src
->bits
, bytes
);
90 dest
->maxsize
= src
->maxsize
;
94 bvector_free (bvector_t vec
)
101 bvector_fini(struct bvector
*bv
)
103 if (bv
->bits
!= bv
->tiny
)
108 bvector_clear (bvector_t vec
, size_t n
)
110 if (n
< vec
->maxsize
)
111 vec
->bits
[BVEC_WORD(n
)] &= ~(1ul << BVEC_OFFSET(n
));
116 bvector_clear_all (bvector_t vec
)
118 memset (vec
->bits
, 0, BVEC_BYTES(vec
->maxsize
));
123 bvector_set (bvector_t vec
, size_t n
)
125 size_t word
= BVEC_WORD(n
);
126 size_t offset
= BVEC_OFFSET(n
);
128 if (n
>= vec
->maxsize
)
129 bvector_resize (vec
, n
);
130 vec
->bits
[word
] |= 1ul << offset
;
134 bvector_at (bvector_t vec
, size_t i
)
136 if (i
< vec
->maxsize
)
137 return !!(vec
->bits
[BVEC_WORD(i
)] & (1ul << BVEC_OFFSET(i
)));
143 bvector_resize (bvector_t vec
, size_t newsize
)
145 size_t oldsize
= vec
->maxsize
;
148 while ((vec
->maxsize
*= 2) < newsize
)
150 bytes
= BVEC_BYTES(vec
->maxsize
);
151 if (vec
->bits
== vec
->tiny
) {
152 vec
->bits
= mh_xmalloc(bytes
);
153 memcpy(vec
->bits
, vec
->tiny
, sizeof vec
->tiny
);
155 vec
->bits
= mh_xrealloc(vec
->bits
, bytes
);
157 memset(vec
->bits
+ (oldsize
/ BVEC_BITS_BITS
), 0,
158 (vec
->maxsize
- oldsize
) / CHAR_BIT
);
162 bvector_first_bits (bvector_t vec
)
174 static void svector_resize (svector_t
, size_t);
177 svector_create (size_t init_size
)
183 vec
->maxsize
= init_size
? init_size
: SVEC_INIT_SIZE
;
184 bytes
= vec
->maxsize
* sizeof (char *);
185 vec
->strs
= mh_xcalloc (1, bytes
);
192 svector_free (svector_t vec
)
199 svector_push_back (svector_t vec
, char *s
)
201 if (++vec
->size
>= vec
->maxsize
)
202 svector_resize (vec
, vec
->size
);
203 return vec
->strs
[vec
->size
-1] = s
;
207 svector_at (svector_t vec
, size_t i
)
209 if (i
>= vec
->maxsize
)
210 svector_resize (vec
, i
);
215 * Return address of first element that stringwise matches s.
216 * The caller can replace the contents of the return address.
219 svector_find (svector_t vec
, const char *s
)
222 char **str
= vec
->strs
;
224 for (i
= 0; i
< vec
->size
; ++i
, ++str
) {
225 if (*str
&& ! strcmp(*str
, s
)) {
234 svector_strs (svector_t vec
)
240 svector_size (svector_t vec
)
246 svector_resize (svector_t vec
, size_t maxsize
)
248 size_t old_maxsize
= vec
->maxsize
;
250 while ((vec
->maxsize
*= 2) < maxsize
)
252 vec
->strs
= mh_xrealloc (vec
->strs
, vec
->maxsize
* sizeof (char *));
253 memset(vec
->strs
+ old_maxsize
, 0,
254 (vec
->maxsize
- old_maxsize
) * sizeof *vec
->strs
);
264 static void ivector_resize (ivector_t
, size_t);
267 ivector_create (size_t init_size
)
273 vec
->maxsize
= init_size
? init_size
: IVEC_INIT_SIZE
;
274 bytes
= vec
->maxsize
* sizeof (int);
275 vec
->ints
= mh_xcalloc (1, bytes
);
282 ivector_free (ivector_t vec
)
289 ivector_push_back (ivector_t vec
, int n
)
291 if (++vec
->size
>= vec
->maxsize
)
292 ivector_resize (vec
, vec
->size
);
293 return vec
->ints
[vec
->size
-1] = n
;
297 ivector_at (ivector_t vec
, size_t i
)
299 if (i
>= vec
->maxsize
)
300 ivector_resize (vec
, i
);
305 ivector_atp (ivector_t vec
, size_t i
)
307 if (i
>= vec
->maxsize
)
308 ivector_resize (vec
, i
);
309 return &vec
->ints
[i
];
313 ivector_resize (ivector_t vec
, size_t maxsize
)
315 size_t old_maxsize
= vec
->maxsize
;
317 while ((vec
->maxsize
*= 2) < maxsize
)
319 vec
->ints
= mh_xrealloc (vec
->ints
, vec
->maxsize
* sizeof (int));
320 memset(vec
->ints
+ old_maxsize
, 0,
321 (vec
->maxsize
- old_maxsize
) * sizeof *vec
->ints
);