xref: /freebsd-src/contrib/libucl/klib/kvec.h (revision a0409676120c1e558d0ade943019934e0f15118d)
18e3b1ab2SBaptiste Daroussin /* The MIT License
28e3b1ab2SBaptiste Daroussin 
38e3b1ab2SBaptiste Daroussin    Copyright (c) 2008, by Attractive Chaos <attractor@live.co.uk>
48e3b1ab2SBaptiste Daroussin 
58e3b1ab2SBaptiste Daroussin    Permission is hereby granted, free of charge, to any person obtaining
68e3b1ab2SBaptiste Daroussin    a copy of this software and associated documentation files (the
78e3b1ab2SBaptiste Daroussin    "Software"), to deal in the Software without restriction, including
88e3b1ab2SBaptiste Daroussin    without limitation the rights to use, copy, modify, merge, publish,
98e3b1ab2SBaptiste Daroussin    distribute, sublicense, and/or sell copies of the Software, and to
108e3b1ab2SBaptiste Daroussin    permit persons to whom the Software is furnished to do so, subject to
118e3b1ab2SBaptiste Daroussin    the following conditions:
128e3b1ab2SBaptiste Daroussin 
138e3b1ab2SBaptiste Daroussin    The above copyright notice and this permission notice shall be
148e3b1ab2SBaptiste Daroussin    included in all copies or substantial portions of the Software.
158e3b1ab2SBaptiste Daroussin 
168e3b1ab2SBaptiste Daroussin    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
178e3b1ab2SBaptiste Daroussin    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
188e3b1ab2SBaptiste Daroussin    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
198e3b1ab2SBaptiste Daroussin    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
208e3b1ab2SBaptiste Daroussin    BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
218e3b1ab2SBaptiste Daroussin    ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
228e3b1ab2SBaptiste Daroussin    CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
238e3b1ab2SBaptiste Daroussin    SOFTWARE.
248e3b1ab2SBaptiste Daroussin */
258e3b1ab2SBaptiste Daroussin 
268e3b1ab2SBaptiste Daroussin /*
278e3b1ab2SBaptiste Daroussin   An example:
288e3b1ab2SBaptiste Daroussin 
298e3b1ab2SBaptiste Daroussin #include "kvec.h"
308e3b1ab2SBaptiste Daroussin int main() {
318e3b1ab2SBaptiste Daroussin 	kvec_t(int) array;
328e3b1ab2SBaptiste Daroussin 	kv_init(array);
33*a0409676SBaptiste Daroussin 	kv_push_safe(int, array, 10, e0); // append
348e3b1ab2SBaptiste Daroussin 	kv_a(int, array, 20) = 5; // dynamic
358e3b1ab2SBaptiste Daroussin 	kv_A(array, 20) = 4; // static
368e3b1ab2SBaptiste Daroussin 	kv_destroy(array);
378e3b1ab2SBaptiste Daroussin 	return 0;
38*a0409676SBaptiste Daroussin e0:
39*a0409676SBaptiste Daroussin 	return 1;
408e3b1ab2SBaptiste Daroussin }
418e3b1ab2SBaptiste Daroussin */
428e3b1ab2SBaptiste Daroussin 
438e3b1ab2SBaptiste Daroussin /*
448e3b1ab2SBaptiste Daroussin   2008-09-22 (0.1.0):
458e3b1ab2SBaptiste Daroussin 
468e3b1ab2SBaptiste Daroussin 	* The initial version.
478e3b1ab2SBaptiste Daroussin 
488e3b1ab2SBaptiste Daroussin */
498e3b1ab2SBaptiste Daroussin 
508e3b1ab2SBaptiste Daroussin #ifndef AC_KVEC_H
518e3b1ab2SBaptiste Daroussin #define AC_KVEC_H
528e3b1ab2SBaptiste Daroussin 
538e3b1ab2SBaptiste Daroussin #include <stdlib.h>
548e3b1ab2SBaptiste Daroussin 
558e3b1ab2SBaptiste Daroussin #define kv_roundup32(x) (--(x), (x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16, ++(x))
568e3b1ab2SBaptiste Daroussin 
578e3b1ab2SBaptiste Daroussin #define kvec_t(type) struct { size_t n, m; type *a; }
588e3b1ab2SBaptiste Daroussin #define kv_init(v) ((v).n = (v).m = 0, (v).a = 0)
598e3b1ab2SBaptiste Daroussin #define kv_destroy(v) free((v).a)
608e3b1ab2SBaptiste Daroussin #define kv_A(v, i) ((v).a[(i)])
618e3b1ab2SBaptiste Daroussin #define kv_pop(v) ((v).a[--(v).n])
628e3b1ab2SBaptiste Daroussin #define kv_size(v) ((v).n)
638e3b1ab2SBaptiste Daroussin #define kv_max(v) ((v).m)
648e3b1ab2SBaptiste Daroussin 
65*a0409676SBaptiste Daroussin #define kv_resize_safe(type, v, s, el)  do { \
66*a0409676SBaptiste Daroussin 		type *_tp = (type*)realloc((v).a, sizeof(type) * (s)); \
67*a0409676SBaptiste Daroussin 		if (_tp == NULL) { \
68*a0409676SBaptiste Daroussin 			goto el; \
69*a0409676SBaptiste Daroussin 		} else { \
70*a0409676SBaptiste Daroussin 			(v).a = _tp; \
71*a0409676SBaptiste Daroussin 			(v).m = (s); \
72*a0409676SBaptiste Daroussin 		} \
73*a0409676SBaptiste Daroussin 	} while (0)
74*a0409676SBaptiste Daroussin 
758e3b1ab2SBaptiste Daroussin #define kv_grow_factor 1.5
76*a0409676SBaptiste Daroussin #define kv_grow_safe(type, v, el)  do { \
77*a0409676SBaptiste Daroussin 		size_t _ts = ((v).m > 1 ? (v).m * kv_grow_factor : 2); \
78*a0409676SBaptiste Daroussin 		type *_tp = (type*)realloc((v).a, sizeof(type) * _ts); \
79*a0409676SBaptiste Daroussin 		if (_tp == NULL) { \
80*a0409676SBaptiste Daroussin 			goto el; \
81*a0409676SBaptiste Daroussin 		} else { \
82*a0409676SBaptiste Daroussin 			(v).a = _tp; \
83*a0409676SBaptiste Daroussin 			(v).m = _ts; \
84*a0409676SBaptiste Daroussin 		} \
85*a0409676SBaptiste Daroussin 	} while (0)
86*a0409676SBaptiste Daroussin 
87*a0409676SBaptiste Daroussin #define kv_copy_safe(type, v1, v0, el) do { \
88*a0409676SBaptiste Daroussin 		if ((v1).m < (v0).n) kv_resize_safe(type, v1, (v0).n, el); \
89*a0409676SBaptiste Daroussin 		(v1).n = (v0).n; \
90*a0409676SBaptiste Daroussin 		memcpy((v1).a, (v0).a, sizeof(type) * (v0).n); \
91*a0409676SBaptiste Daroussin 	} while (0)
92*a0409676SBaptiste Daroussin 
93*a0409676SBaptiste Daroussin #define kv_push_safe(type, v, x, el) do { \
94*a0409676SBaptiste Daroussin 		if ((v).n == (v).m) { \
95*a0409676SBaptiste Daroussin 			kv_grow_safe(type, v, el); \
96*a0409676SBaptiste Daroussin 		} \
97*a0409676SBaptiste Daroussin 		(v).a[(v).n++] = (x); \
98*a0409676SBaptiste Daroussin 	} while (0)
99*a0409676SBaptiste Daroussin 
100*a0409676SBaptiste Daroussin #define kv_prepend_safe(type, v, x, el) do { \
101*a0409676SBaptiste Daroussin 		if ((v).n == (v).m) { \
102*a0409676SBaptiste Daroussin 			kv_grow_safe(type, v, el); \
103*a0409676SBaptiste Daroussin 		} \
104*a0409676SBaptiste Daroussin 		memmove((v).a + 1, (v).a, sizeof(type) * (v).n); \
105*a0409676SBaptiste Daroussin 		(v).a[0] = (x);	\
106*a0409676SBaptiste Daroussin 		(v).n ++; \
107*a0409676SBaptiste Daroussin 	} while (0)
108*a0409676SBaptiste Daroussin 
109*a0409676SBaptiste Daroussin #define kv_concat_safe(type, v1, v0, el) do { \
110*a0409676SBaptiste Daroussin 		if ((v1).m < (v0).n + (v1).n) \
111*a0409676SBaptiste Daroussin 			kv_resize_safe(type, v1, (v0).n + (v1).n, el); \
112*a0409676SBaptiste Daroussin 		memcpy((v1).a + (v1).n, (v0).a, sizeof(type) * (v0).n);	\
113*a0409676SBaptiste Daroussin 		(v1).n = (v0).n + (v1).n; \
114*a0409676SBaptiste Daroussin 	} while (0)
115*a0409676SBaptiste Daroussin 
116*a0409676SBaptiste Daroussin #define kv_del(type, v, i) do {												\
117*a0409676SBaptiste Daroussin 	if ((i) < (v).n) {														\
118*a0409676SBaptiste Daroussin 		memmove((v).a + (i), (v).a + ((i) + 1), sizeof(type) * ((v).n - (i) - 1)); \
119*a0409676SBaptiste Daroussin 		(v).n --;															\
120*a0409676SBaptiste Daroussin 	}																		\
121*a0409676SBaptiste Daroussin } while (0)
122*a0409676SBaptiste Daroussin 
123*a0409676SBaptiste Daroussin /*
124*a0409676SBaptiste Daroussin  * Old (ENOMEM-unsafe) version of kv_xxx macros. Compat-only, not for use in
125*a0409676SBaptiste Daroussin  * the new library code.
126*a0409676SBaptiste Daroussin  */
127*a0409676SBaptiste Daroussin 
128*a0409676SBaptiste Daroussin #define kv_resize(type, v, s)  ((v).m = (s), (v).a = (type*)realloc((v).a, sizeof(type) * (v).m))
129*a0409676SBaptiste Daroussin 
1308e3b1ab2SBaptiste Daroussin #define kv_grow(type, v)  ((v).m = ((v).m > 1 ? (v).m * kv_grow_factor : 2), \
1318e3b1ab2SBaptiste Daroussin 		(v).a = (type*)realloc((v).a, sizeof(type) * (v).m))
1328e3b1ab2SBaptiste Daroussin 
1338e3b1ab2SBaptiste Daroussin #define kv_copy(type, v1, v0) do {											\
1348e3b1ab2SBaptiste Daroussin 		if ((v1).m < (v0).n) kv_resize(type, v1, (v0).n);					\
1358e3b1ab2SBaptiste Daroussin 		(v1).n = (v0).n;													\
1368e3b1ab2SBaptiste Daroussin 		memcpy((v1).a, (v0).a, sizeof(type) * (v0).n);						\
1378e3b1ab2SBaptiste Daroussin 	} while (0)																\
1388e3b1ab2SBaptiste Daroussin 
1398e3b1ab2SBaptiste Daroussin #define kv_push(type, v, x) do {											\
1408e3b1ab2SBaptiste Daroussin 		if ((v).n == (v).m) {												\
1418e3b1ab2SBaptiste Daroussin 			kv_grow(type, v);												\
1428e3b1ab2SBaptiste Daroussin 		}																	\
1438e3b1ab2SBaptiste Daroussin 		(v).a[(v).n++] = (x);												\
1448e3b1ab2SBaptiste Daroussin 	} while (0)
1458e3b1ab2SBaptiste Daroussin 
1468e3b1ab2SBaptiste Daroussin #define kv_prepend(type, v, x) do {											\
1478e3b1ab2SBaptiste Daroussin 	if ((v).n == (v).m) {													\
1488e3b1ab2SBaptiste Daroussin 		kv_grow(type, v);													\
1498e3b1ab2SBaptiste Daroussin 	}																		\
1508e3b1ab2SBaptiste Daroussin 	memmove((v).a + 1, (v).a, sizeof(type) * (v).n);							\
1518e3b1ab2SBaptiste Daroussin 	(v).a[0] = (x);															\
1528e3b1ab2SBaptiste Daroussin 	(v).n ++;																\
1538e3b1ab2SBaptiste Daroussin } while (0)
1548e3b1ab2SBaptiste Daroussin 
1558e3b1ab2SBaptiste Daroussin #define kv_concat(type, v1, v0) do {										\
1568e3b1ab2SBaptiste Daroussin 	if ((v1).m < (v0).n + (v1).n) kv_resize(type, v1, (v0).n + (v1).n);		\
15739ee7a7aSBaptiste Daroussin 		memcpy((v1).a + (v1).n, (v0).a, sizeof(type) * (v0).n);	\
1588e3b1ab2SBaptiste Daroussin 		(v1).n = (v0).n + (v1).n;											\
1598e3b1ab2SBaptiste Daroussin 	} while (0)
1608e3b1ab2SBaptiste Daroussin 
161*a0409676SBaptiste Daroussin #endif /* AC_KVEC_H */
162