1 /*
2  * Copyright (c) 2012-2014 by Farsight Security, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *    http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <assert.h>
18 
19 #include "my_alloc.h"
20 
21 #define VECTOR_GENERATE(name, type)					\
22 typedef struct name##__vector {						\
23 	type *		_v;						\
24 	type *		_p;						\
25 	size_t		_n, _n_alloced, _hint;				\
26 } name;									\
27 __attribute__((unused))							\
28 static inline name *							\
29 name##_init(unsigned hint)						\
30 {									\
31 	name *vec;							\
32 	vec = my_calloc(1, sizeof(name));				\
33 	if (hint == 0) hint = 1;					\
34 	vec->_hint = vec->_n_alloced = hint;				\
35 	vec->_v = my_malloc(vec->_n_alloced * sizeof(type));		\
36 	vec->_p = &(vec->_v[0]);					\
37 	return (vec);							\
38 }									\
39 __attribute__((unused))							\
40 static inline void							\
41 name##_reinit(unsigned hint, name *vec)					\
42 {									\
43 	if (hint == 0) hint = 1;					\
44 	vec->_hint = vec->_n_alloced = hint;				\
45 	vec->_n = 0;							\
46 	vec->_v = my_malloc(vec->_n_alloced * sizeof(type));		\
47 	vec->_p = &(vec->_v[0]);					\
48 }									\
49 __attribute__((unused))							\
50 static inline void							\
51 name##_detach(name *vec, type **out, size_t *outsz)			\
52 {									\
53 	*(out) = (vec)->_v;						\
54 	*(outsz) = (vec)->_n;						\
55 	(vec)->_n = 0;							\
56 	(vec)->_n_alloced = (vec)->_hint;				\
57 	(vec)->_v = my_malloc((vec)->_n_alloced * sizeof(type));	\
58 	(vec)->_p = &(vec->_v[0]);					\
59 }									\
60 __attribute__((unused))							\
61 static inline void							\
62 name##_destroy(name **vec)						\
63 {									\
64 	if (*vec) {							\
65 		my_free((*vec)->_v);					\
66 		my_free((*vec));					\
67 	}								\
68 }									\
69 __attribute__((unused))							\
70 static inline void							\
71 name##_reserve(name *vec, size_t n_elems)				\
72 {									\
73 	while ((n_elems) > ((vec)->_n_alloced - (vec)->_n)) {		\
74 		(vec)->_n_alloced *= 2;					\
75 		(vec)->_v = my_realloc((vec)->_v, (vec)->_n_alloced	\
76 				   * sizeof(type));			\
77 		(vec)->_p = &((vec)->_v[(vec)->_n]);			\
78 	}								\
79 }									\
80 __attribute__((unused))							\
81 static inline void							\
82 name##_add(name *vec, type elem)					\
83 {									\
84 	while ((vec)->_n + 1 > (vec)->_n_alloced) {			\
85 		(vec)->_n_alloced *= 2;					\
86 		(vec)->_v = my_realloc((vec)->_v, (vec)->_n_alloced	\
87 				   * sizeof(type));			\
88 		(vec)->_p = &((vec)->_v[(vec)->_n]);			\
89 	}								\
90 	(vec)->_v[(vec)->_n] = elem;					\
91 	(vec)->_n += 1;							\
92 	(vec)->_p = &((vec)->_v[(vec)->_n]);				\
93 }									\
94 __attribute__((unused))							\
95 static inline void							\
96 name##_append(name *vec, type const *elems, size_t n_elems)		\
97 {									\
98 	name##_reserve(vec, n_elems);					\
99 	memcpy((vec)->_v + (vec)->_n, elems, (n_elems) * sizeof(type));	\
100 	(vec)->_n += (n_elems);						\
101 	(vec)->_p = &((vec)->_v[(vec)->_n]);				\
102 }									\
103 __attribute__((unused))							\
104 static inline void							\
105 name##_extend(name *vec0, name *vec1)					\
106 {									\
107 	name##_append(vec0, (vec1)->_v, (vec1)->_n);			\
108 }									\
109 __attribute__((unused))							\
110 static inline void							\
111 name##_reset(name *vec)							\
112 {									\
113 	(vec)->_n = 0;							\
114 	if ((vec)->_n_alloced > (vec)->_hint) {				\
115 		(vec)->_n_alloced = (vec)->_hint;			\
116 		(vec)->_v = my_realloc((vec)->_v, (vec)->_n_alloced	\
117 				   * sizeof(type));			\
118 	}								\
119 	(vec)->_p = &(vec->_v[0]);					\
120 }									\
121 __attribute__((unused))							\
122 static inline void							\
123 name##_clip(name *vec, size_t n_elems)					\
124 {									\
125 	if (n_elems < (vec)->_n) {					\
126 		(vec)->_n = n_elems;					\
127 		(vec)->_p = &((vec)->_v[(vec)->_n]);			\
128 	}								\
129 }									\
130 __attribute__((unused))							\
131 static inline size_t							\
132 name##_bytes(name *vec)							\
133 {									\
134 	return ((vec)->_n * sizeof(type));				\
135 }									\
136 __attribute__((unused))							\
137 static inline size_t							\
138 name##_size(name *vec)							\
139 {									\
140 	return ((vec)->_n);						\
141 }									\
142 __attribute__((unused))							\
143 static inline type							\
144 name##_value(name *vec, size_t i)					\
145 {									\
146 	assert(i < (vec)->_n);						\
147 	return ((vec)->_v[i]);						\
148 }									\
149 __attribute__((unused))							\
150 static inline type *							\
151 name##_ptr(name *vec)							\
152 {									\
153 	return ((vec)->_p);						\
154 }									\
155 __attribute__((unused))							\
156 static inline type *							\
157 name##_data(name *vec)							\
158 {									\
159 	return ((vec)->_v);						\
160 }									\
161 __attribute__((unused))							\
162 static inline void							\
163 name##_advance(name *vec, size_t x)					\
164 {									\
165 	assert(x <= ((vec)->_n_alloced - (vec)->_n));			\
166 	(vec)->_n += x;							\
167 	(vec)->_p = &((vec)->_v[(vec)->_n]);				\
168 }
169