vessel/core/include/array.h
Arija A. 4f0bf80e5f
refact: Remove mem.h
Signed-off-by: Arija A. <ari@ari.lt>
2025-06-21 23:43:31 +03:00

142 lines
9.6 KiB
C

#ifndef VESSEL_ARRAY_H_
#define VESSEL_ARRAY_H_
#include "conf.h"
#include "def.h"
#include "thread.h"
#include <string.h>
#define VS_ARRAY_INITAL_CAP 32
#define VS_ARRAY_GROWTH_FACTOR 2
/* Generic array */
#define VS_G_ARRAY_APPEND(arr, item) \
do { \
if ((arr)->size >= (arr)->cap) { \
(arr)->cap = \
(arr)->cap == 0 ? VS_ARRAY_INITAL_CAP : ((arr)->cap * VS_ARRAY_GROWTH_FACTOR); \
(arr)->items = VS_REALLOC((arr)->items, (arr)->cap * sizeof(*(arr)->items)); \
} \
(arr)->items[(arr)->size++] = (item); \
} while (0)
#define VS_G_ARRAY_DESTROY(arr) VS_FREE((arr)->items)
/* Typed array */
#define VS_ARRAY_DECLARE_STRUCT(name, type) \
struct name { \
size_t cap, size; \
Lock lock; \
(type) * items; \
}; \
bool name##_init((name) * a); \
bool name##_grow((name) * a); \
bool name##_append((name) * a, const type item); \
bool name##_clear((name) * a); \
bool name##_copy((name) * a, (name) * b); \
bool name##_pop((name) * a, (type) * out); \
bool name##_destroy((name) * a)
#define VS_ARRAY_DECLARE(name, type) \
ARRAY_DECLARE_STRUCT(name, type); \
typedef struct name name
#define VS_ARRAY_DEFINE(name, type) \
bool name##_init(struct name *a) { \
if (!a) \
return false; \
if (!Lock_init(&a->lock)) \
return false; \
if (!Lock_lock(&a->lock)) { \
Lock_destroy(&a->lock); \
return false; \
} \
a->cap = VS_ARRAY_INITAL_CAP; \
a->size = 0; \
a->items = VS_MALLOC(sizeof(*a->items) * a->cap); \
if (!a->items) { \
Lock_unlock(&a->lock); \
Lock_destroy(&a->lock); \
return false; \
} \
return Lock_unlock(&a->lock); \
} \
bool name##_grow(struct name *a) { \
(type) * new_items; \
const size_t new_cap = sizeof(*a->items) * a->cap * VS_ARRAY_GROWTH_FACTOR; \
if (!a || !Lock_lock(&a->lock)) \
return false; \
new_items = VS_REALLOC(a->items, new_cap); \
if (!new_items) { \
Lock_unlock(&a->lock); \
return false; \
} \
a->items = new_items; \
a->cap = new_cap; \
return Lock_unlock(&a->lock); \
} \
bool name##_append(struct name *a, const type item) { \
if (!a || !Lock_lock(&a->lock)) \
return false; \
if (!Lock_unlock(&a->lock)) \
return false; \
if ((a->size + 1) >= a->cap && !name##_grow(a)) \
return false; \
if (!Lock_lock(&a->lock)) \
return false; \
a->items[a->size++] = item; \
return Lock_unlock(&a->lock); \
} \
bool name##_clear(struct name *a) { \
if (!a || !Lock_lock(&a->lock)) \
return false; \
a->size = 0; \
return Lock_unlock(&a->lock); \
} \
bool name##_copy(struct name *a, struct name *b) { \
if (!a || !b) \
return false; \
if (!Lock_lock(&a->lock)) \
return false; \
if (!Lock_lock(&b->lock)) { \
Lock_unlock(&a->lock); \
return false; \
} \
b->cap = a->cap; \
b->size = a->size; \
b->items = VS_MALLOC(sizeof(*b->items) * b->cap); \
if (!b->items) { \
Lock_unlock(&a->lock); \
Lock_unlock(&b->lock); \
return false; \
} \
memmove(b->items, a->items, sizeof(*b->items) * b->cap); \
const bool al = Lock_unlock(&a->lock); \
const bool bl = Lock_unlock(&b->lock); \
return al && bl; \
} \
bool name##_pop(struct name *a, struct type *out) { \
if (!a || !out || !Lock_lock(&a->lock)) \
return false; \
if (a->size == 0) { \
Lock_unlock(&a->lock); \
return false; \
} \
*out = a->items[--a->size]; \
return Lock_unlock(&a->lock); \
} \
bool name##_destroy(struct name *a) { \
if (!Lock_lock(&a->lock)) \
return false; \
VS_FREE(a->items); \
const bool al = Lock_unlock(&a->lock); \
const bool bl = Lock_destroy(&a->lock); \
return al && bl; \
} \
const bool __##name##_defined__ = true
#endif /* VESSEL_ARRAY_H_ */