155 lines
4.4 KiB
C
155 lines
4.4 KiB
C
#define panicf(...) base_panicf(__FILE__, __LINE__, __VA_ARGS__)
|
|
#define len(x) (sizeof((x))/sizeof((x)[0]))
|
|
#define ilen(x) ((int)len(x))
|
|
|
|
|
|
_Noreturn
|
|
void base_panicf(char *file, int line, const char *fmt, ...) {
|
|
fprintf(stderr, "%s:%d: ", file, line);
|
|
va_list args;
|
|
va_start(args, fmt);
|
|
vfprintf(stderr, fmt, args);
|
|
va_end(args);
|
|
fprintf(stderr, "\n");
|
|
fflush(stderr);
|
|
fflush(stdout);
|
|
exit(1);
|
|
}
|
|
|
|
#define Vec(T) struct { T *data; int len; int cap; }
|
|
typedef Vec(void) VecVoid;
|
|
|
|
#define vec_push(arr, elem) \
|
|
(vec_grow((VecVoid *)(arr), sizeof((arr)->data[0]), 1), (arr)->data[(arr)->len++] = (elem))
|
|
|
|
#define vec_insert(arr, idx, elem) do { \
|
|
assert((idx) >= 0 && (idx) <= (arr)->len); \
|
|
vec_grow((VecVoid *)(arr), sizeof((arr)->data[0]), 1); \
|
|
memmove(&(arr)->data[(idx) + 1], &(arr)->data[(idx)], sizeof((arr)->data[0]) * ((arr)->len - (idx))); \
|
|
(arr)->data[(idx)] = (elem); \
|
|
(arr)->len += 1; \
|
|
} while (0)
|
|
|
|
#define vec_pop(arr) \
|
|
(assert((arr)->len > 0), (arr)->data[--(arr)->len])
|
|
|
|
#define vec_del(arr, idx) do { \
|
|
assert((idx) >= 0 && (idx) < (arr)->len); \
|
|
memmove(&(arr)->data[(idx)], &(arr)->data[(idx) + 1], sizeof((arr)->data[0]) * ((arr)->len - (idx) - 1)); \
|
|
(arr)->len -= 1; \
|
|
} while (0)
|
|
|
|
#define vec_swap_del(arr, idx) do { \
|
|
assert((idx) >= 0 && (idx) < (arr)->len); \
|
|
(arr)->data[(idx)] = (arr)->data[(arr)->len - 1]; \
|
|
(arr)->len -= 1; \
|
|
} while (0)
|
|
|
|
#define vec_free(arr) do { \
|
|
free((arr)->data); \
|
|
(arr)->data = NULL; \
|
|
(arr)->len = 0; \
|
|
(arr)->cap = 0; \
|
|
} while (0)
|
|
|
|
void vec_grow(VecVoid *array, int elem_size, int add_len) {
|
|
if (array->len + add_len > array->cap) {
|
|
int cap = array->cap ? array->cap : 15;
|
|
int new_cap = (cap + add_len) * 2;
|
|
assert(new_cap > array->len + add_len);
|
|
array->data = realloc(array->data, elem_size * new_cap);
|
|
assert(array->data);
|
|
array->cap = new_cap;
|
|
}
|
|
}
|
|
|
|
void vec_test(void) {
|
|
Vec(int) int_vec = {0};
|
|
assert(int_vec.data == NULL);
|
|
assert(int_vec.len == 0);
|
|
assert(int_vec.cap == 0);
|
|
|
|
for (int i = 0; i < 32; i += 1) {
|
|
vec_push(&int_vec, i * 3);
|
|
assert(int_vec.len == i + 1);
|
|
assert(int_vec.cap >= int_vec.len);
|
|
assert(int_vec.data[int_vec.len - 1] == i * 3);
|
|
}
|
|
|
|
for (int i = 0; i < 32; i += 1) {
|
|
assert(int_vec.data[i] == i * 3);
|
|
}
|
|
|
|
int cap_after_ints = int_vec.cap;
|
|
vec_push(&int_vec, 12345);
|
|
assert(int_vec.len == 33);
|
|
assert(int_vec.data[32] == 12345);
|
|
assert(int_vec.cap >= cap_after_ints);
|
|
|
|
vec_insert(&int_vec, 0, 111);
|
|
assert(int_vec.len == 34);
|
|
assert(int_vec.data[0] == 111);
|
|
assert(int_vec.data[1] == 0);
|
|
|
|
vec_insert(&int_vec, 5, 222);
|
|
assert(int_vec.len == 35);
|
|
assert(int_vec.data[5] == 222);
|
|
assert(int_vec.data[6] == 12);
|
|
|
|
vec_insert(&int_vec, int_vec.len, 333);
|
|
assert(int_vec.len == 36);
|
|
assert(int_vec.data[int_vec.len - 1] == 333);
|
|
|
|
int popped = vec_pop(&int_vec);
|
|
assert(popped == 333);
|
|
assert(int_vec.len == 35);
|
|
|
|
vec_del(&int_vec, 5);
|
|
assert(int_vec.len == 34);
|
|
assert(int_vec.data[5] == 12);
|
|
|
|
int before_swap_del = int_vec.data[int_vec.len - 1];
|
|
vec_swap_del(&int_vec, 1);
|
|
assert(int_vec.len == 33);
|
|
assert(int_vec.data[1] == before_swap_del);
|
|
|
|
vec_free(&int_vec);
|
|
assert(int_vec.data == NULL);
|
|
assert(int_vec.len == 0);
|
|
assert(int_vec.cap == 0);
|
|
|
|
Vec(char *) str_vec = {0};
|
|
vec_push(&str_vec, "a");
|
|
vec_push(&str_vec, "bb");
|
|
vec_push(&str_vec, "ccc");
|
|
|
|
assert(str_vec.len == 3);
|
|
assert(strcmp(str_vec.data[0], "a") == 0);
|
|
assert(strcmp(str_vec.data[1], "bb") == 0);
|
|
assert(strcmp(str_vec.data[2], "ccc") == 0);
|
|
|
|
vec_insert(&str_vec, 1, "inserted");
|
|
assert(str_vec.len == 4);
|
|
assert(strcmp(str_vec.data[1], "inserted") == 0);
|
|
assert(strcmp(str_vec.data[2], "bb") == 0);
|
|
|
|
assert(strcmp(vec_pop(&str_vec), "ccc") == 0);
|
|
assert(str_vec.len == 3);
|
|
|
|
vec_del(&str_vec, 1);
|
|
assert(str_vec.len == 2);
|
|
assert(strcmp(str_vec.data[0], "a") == 0);
|
|
assert(strcmp(str_vec.data[1], "bb") == 0);
|
|
|
|
vec_swap_del(&str_vec, 0);
|
|
assert(str_vec.len == 1);
|
|
assert(strcmp(str_vec.data[0], "bb") == 0);
|
|
|
|
vec_free(&str_vec);
|
|
assert(str_vec.data == NULL);
|
|
assert(str_vec.len == 0);
|
|
assert(str_vec.cap == 0);
|
|
|
|
printf("vector tests passed\n");
|
|
}
|