Skip to content

Commit b6012fa

Browse files
committed
Add vector type to collections.
Signed-off-by: Timothy Rule (VM/EMT3) <[email protected]>
1 parent 9a55054 commit b6012fa

File tree

5 files changed

+512
-2
lines changed

5 files changed

+512
-2
lines changed

dse/clib/collections/vector.h

Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
// Copyright 2025 Robert Bosch GmbH
2+
//
3+
// SPDX-License-Identifier: Apache-2.0
4+
5+
#ifndef DSE_CLIB_COLLECTIONS_VECTOR_H_
6+
#define DSE_CLIB_COLLECTIONS_VECTOR_H_
7+
8+
#include <stdlib.h>
9+
#include <string.h>
10+
#include <errno.h>
11+
12+
13+
#define VECTOR_DEFAULT_CAPACITY 64
14+
15+
16+
typedef struct Vector Vector;
17+
typedef int (*VectorCompar)(const void*, const void*);
18+
typedef int (*VectorRangeCallback)(void* item, void* data);
19+
20+
21+
typedef struct Vector {
22+
struct {
23+
VectorCompar compar;
24+
} vtable;
25+
size_t capacity;
26+
size_t length;
27+
size_t item_size;
28+
void* items;
29+
} Vector;
30+
31+
static __inline__ int __vector_resize(Vector* v, size_t hint)
32+
{
33+
if (v == NULL) return -EINVAL;
34+
if (hint == 0) {
35+
free(v->items);
36+
v->items = NULL;
37+
v->capacity = 0;
38+
} else if (hint > v->length) {
39+
if (v->items == NULL) {
40+
v->items = calloc(hint, v->item_size);
41+
} else {
42+
size_t offset = v->length * v->item_size;
43+
size_t new_size = hint * v->item_size;
44+
v->items = realloc(v->items, new_size);
45+
memset(v->items + offset, 0, new_size - offset);
46+
}
47+
v->capacity = hint;
48+
} else {
49+
/* Hint smaller than length, can't resize. */
50+
return -EINVAL;
51+
}
52+
return 0;
53+
}
54+
55+
static __inline__ Vector vector_make(
56+
size_t item_size, size_t capacity, VectorCompar compar_func)
57+
{
58+
Vector v = {
59+
.item_size = item_size,
60+
.capacity = capacity ? capacity : VECTOR_DEFAULT_CAPACITY,
61+
.vtable.compar = compar_func,
62+
};
63+
__vector_resize(&v, v.capacity);
64+
return v;
65+
}
66+
67+
static __inline__ size_t vector_len(Vector* v)
68+
{
69+
return v ? v->length : 0;
70+
}
71+
72+
static __inline__ int vector_push(Vector* v, void* item)
73+
{
74+
if (v == NULL) return -EINVAL;
75+
if (v->length == v->capacity) __vector_resize(v, v->capacity * 2);
76+
v->length += 1;
77+
if (item) {
78+
size_t offset = (v->length - 1) * v->item_size;
79+
memcpy(v->items + offset, item, v->item_size);
80+
}
81+
return 0;
82+
}
83+
84+
static __inline__ int vector_pop(Vector* v, void* item)
85+
{
86+
if (v == NULL) return -EINVAL;
87+
if (v->length == 0) return -ENODATA;
88+
if (item) {
89+
size_t offset = (v->length - 1) * v->item_size;
90+
memcpy(item, v->items + offset, v->item_size);
91+
}
92+
v->length -= 1;
93+
return 0;
94+
}
95+
96+
static __inline__ void* vector_at(Vector* v, size_t index, void* item)
97+
{
98+
if (v == NULL || v->items == NULL) return NULL;
99+
if (index >= v->length) return NULL;
100+
size_t offset = index * v->item_size;
101+
if (item) {
102+
memcpy(item, v->items + offset, v->item_size);
103+
}
104+
return v->items + offset;
105+
}
106+
107+
static __inline__ int vector_delete_at(Vector* v, size_t index)
108+
{
109+
if (v == NULL) return -EINVAL;
110+
if (v->length == 0 || v->items == NULL) return -ENODATA;
111+
if (index >= v->length) return -EINVAL;
112+
size_t offset = index * v->item_size;
113+
size_t move_size = (v->length - (index + 1)) * v->item_size;
114+
memmove(v->items + offset, v->items + offset + v->item_size, move_size);
115+
v->length -= 1;
116+
return 0;
117+
}
118+
119+
static __inline__ int vector_sort(Vector* v)
120+
{
121+
if (v == NULL) return -EINVAL;
122+
if (v->length == 0 || v->items == NULL) return -ENODATA;
123+
if (v->vtable.compar == NULL) return -EINVAL;
124+
qsort(v->items, v->length, v->item_size, v->vtable.compar);
125+
return 0;
126+
}
127+
128+
static __inline__ int vector_find(
129+
Vector* v, void* key, size_t start, void* item)
130+
{
131+
if (v == NULL) return -EINVAL;
132+
if (key == NULL) return -EINVAL;
133+
if (v->length == 0 || v->items == NULL) return -ENODATA;
134+
if (v->vtable.compar == NULL) return -EINVAL;
135+
if (start >= v->length) return -EINVAL;
136+
size_t offset = start * v->item_size;
137+
void* result = bsearch(key, v->items + offset, v->length - start,
138+
v->item_size, v->vtable.compar);
139+
if (result) {
140+
if (item) {
141+
memcpy(item, result, v->item_size);
142+
}
143+
return 0;
144+
} else {
145+
return 1;
146+
}
147+
}
148+
149+
static __inline__ int vector_range(Vector* v, void* from_key, void* to_key,
150+
VectorRangeCallback func, void* data)
151+
{
152+
if (v == NULL) return -EINVAL;
153+
if (from_key == NULL || to_key == NULL) return -EINVAL;
154+
if (func == NULL) return -EINVAL;
155+
if (v->items != NULL) {
156+
for (size_t i = 0; i < v->length; i++) {
157+
void* item = v->items + (i * v->item_size);
158+
if ((v->vtable.compar(item, from_key) < 0) ||
159+
(v->vtable.compar(item, to_key) > 0)) {
160+
continue;
161+
}
162+
int rc = func(item, data);
163+
if (rc != 0) {
164+
return rc;
165+
}
166+
}
167+
}
168+
return 0;
169+
}
170+
171+
static __inline__ void vector_clear(Vector* v, size_t capacity)
172+
{
173+
if (v == NULL) return;
174+
__vector_resize(v, capacity);
175+
}
176+
177+
178+
#endif // DSE_CLIB_COLLECTIONS_VECTOR_H_

tests/collections/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ add_executable(test_collections
1616
test_set.c
1717
test_hashlist.c
1818
test_sortedlist.c
19+
test_vector.c
1920

2021
${DSE_CLIB_SOURCE_DIR}/collections/hashmap.c
2122
${DSE_CLIB_SOURCE_DIR}/collections/set.c

tests/collections/__test__.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ extern int run_hashmap_tests(void);
1313
extern int run_hashlist_tests(void);
1414
extern int run_set_tests(void);
1515
extern int run_sortedlist_tests(void);
16+
extern int run_vector_tests(void);
1617

1718

1819
int main()
@@ -24,5 +25,6 @@ int main()
2425
rc |= run_hashlist_tests();
2526
rc |= run_set_tests();
2627
rc |= run_sortedlist_tests();
28+
rc |= run_vector_tests();
2729
return rc;
2830
}

tests/collections/test_sortedlist.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,14 @@
1111
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
1212

1313

14-
int test_setup(void** state)
14+
static int test_setup(void** state)
1515
{
1616
UNUSED(state);
1717
return 0;
1818
}
1919

2020

21-
int test_teardown(void** state)
21+
static int test_teardown(void** state)
2222
{
2323
UNUSED(state);
2424
return 0;

0 commit comments

Comments
 (0)