summaryrefslogtreecommitdiffstats
path: root/src/vector.h
blob: 02ea804ec22c1836af5f2b7cf3332a7fec94eaf4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
/**
   \file

   Typesafe dynamically sized arrays
*/


#pragma once

#include <stdbool.h>
#include <stdlib.h>

/** A vector descriptor */
typedef struct _vector_desc {
	size_t allocated;		/**< The number of elements currently allocated */
	size_t length;			/**< The actual number of elements in the vector */
} vector_desc_t;

/**
   A type for a vector of \e type elements

   \hideinitializer
*/
#define VECTOR(type) struct {	\
	vector_desc_t desc;	\
	type *data;		\
}

bool _vector_resize(vector_desc_t *desc, void **data, size_t n, size_t elemsize);
bool _vector_insert(vector_desc_t *desc, void **data, void *element, size_t pos, size_t elemsize);
void _vector_delete(vector_desc_t *desc, void **data, size_t pos, size_t elemsize);

/**
   Resizes the vector \e a to \e n elements

   \hideinitializer
*/
#define VECTOR_RESIZE(v, n)  ({				\
	__typeof__(v) *_v = &(v);			\
	_vector_resize(&_v->desc, (void **)&_v->data, (n), sizeof(*_v->data)); \
})

/**
   Frees all resources used by the vector \e v

   \hideinitializer
*/
#define VECTOR_FREE(v) free((v).data)

/**
   Returns the number of elements in the vector \e v

   \hideinitializer
*/
#define VECTOR_LEN(v) ((v).desc.length)

/**
   Returns the element with index \e i in the vector \e v

   \hideinitializer
*/
#define VECTOR_INDEX(v, i) ((v).data[i])

/**
   Returns a pointer to the vector elements of \e v

   \hideinitializer
*/
#define VECTOR_DATA(v) ((v).data)

/**
   Inserts the element \e elem at index \e pos of vector \e v

   \hideinitializer
*/
#define VECTOR_INSERT(v, elem, pos) ({			\
	__typeof__(v) *_v = &(v);			\
	__typeof__(*_v->data) _e = (elem);		\
	_vector_insert(&_v->desc, (void **)&_v->data, &_e, (pos), sizeof(_e)); \
})

/**
   Adds the element \e elem at the end of vector \e v

   \hideinitializer
*/
#define VECTOR_ADD(v, elem) ({				\
	__typeof__(v) *_v = &(v);			\
	__typeof__(*_v->data) _e = (elem);		\
	_vector_insert(&_v->desc, (void **)&_v->data, &_e, _v->desc.length, sizeof(_e)); \
})

/**
   Deletes the element at index \e pos of vector \e v

   \hideinitializer
*/
#define VECTOR_DELETE(v, pos) ({			\
	__typeof__(v) *_v = &(v);			\
	_vector_delete(&_v->desc, (void **)&_v->data, (pos), sizeof(*_v->data)); \
})

/**
   Performs a binary search on the vector \e v, returning a pointer to a matching vector element

   \hideinitializer
*/
#define VECTOR_BSEARCH(key, v, cmp) ({			\
	__typeof__(v) *_v = &(v);			\
	const __typeof__(*_v->data) *_key = (key);	\
	int (*_cmp)(__typeof__(_key), __typeof__(_key)) = (cmp); \
	(__typeof__(_v->data))bsearch(_key, _v->data, _v->desc.length, sizeof(*_v->data), (int (*)(const void *, const void *))_cmp); \
})