Add generic dynamic array type

This commit is contained in:
Luka Jankovic 2025-06-17 01:05:40 +02:00
parent 89e548eca8
commit 7769f5fd58
6 changed files with 94 additions and 79 deletions

View file

@ -2,49 +2,29 @@
struct kubo_context *kubo_context_init() {
struct kubo_context *context = malloc(sizeof(struct kubo_context));
if (!context) {
return NULL;
}
context->num_walls_alloc = KUBO_CONTEXT_NUM_WALLS_ALLOC;
context->walls =
malloc(sizeof(struct kubo_wall) * context->num_walls_alloc);
kubo_wall_arr_init(&context->walls);
return context;
}
void kubo_context_cleanup(struct kubo_context *context) {
free(context->walls);
kubo_wall_arr_free(&context->walls);
free(context);
}
bool kubo_context_add_wall(struct kubo_context *context,
struct kubo_wall *wall) {
struct kubo_wall **new_walls;
if (context->num_walls == context->num_walls_alloc - 1) {
context->num_walls_alloc *= 2;
new_walls = realloc(context->walls, sizeof(struct kubo_wall *) *
context->num_walls_alloc);
if (!new_walls)
return false;
context->walls = new_walls;
}
context->walls[context->num_walls++] = wall;
return true;
}
struct kubo_wall *kubo_context_get_pending_wall(struct kubo_context *context) {
if (context->num_walls > 0) {
switch (context->walls[context->num_walls - 1]->state) {
if (context->walls.count > 0) {
struct kubo_wall *last_wall =
kubo_wall_arr_get(&context->walls, context->walls.count - 1);
switch (last_wall->state) {
case KUBO_WALL_INIT:
case KUBO_WALL_DRAWING:
return context->walls[context->num_walls - 1];
return last_wall;
break;
default:
break;
@ -52,7 +32,7 @@ struct kubo_wall *kubo_context_get_pending_wall(struct kubo_context *context) {
}
struct kubo_wall *wall = kubo_wall_init();
kubo_context_add_wall(context, wall);
kubo_wall_arr_add(&context->walls, wall);
return wall;
}

View file

@ -5,24 +5,19 @@
#include <stdio.h>
#include <stdlib.h>
#include "kubo_dynarray.h"
#include "kubo_wall.h"
#define KUBO_CONTEXT_NUM_WALLS_ALLOC 4
KUBO_DYNARRAY_REGISTER(kubo_wall_arr, struct kubo_wall *);
struct kubo_context {
bool exit_pending;
struct kubo_wall **walls;
unsigned int num_walls;
unsigned int num_walls_alloc;
struct kubo_wall_arr walls;
};
struct kubo_context *kubo_context_init();
void kubo_context_cleanup(struct kubo_context *context);
bool kubo_context_add_wall(struct kubo_context *context,
struct kubo_wall *wall);
struct kubo_wall *kubo_context_get_pending_wall(struct kubo_context *context);
#endif

50
kubo_dynarray.h Normal file
View file

@ -0,0 +1,50 @@
#ifndef KUBO_DYNARRAY_H
#define KUBO_DYNARRAY_H
#include <assert.h>
#include <stdlib.h>
#define KUBO_DRYNARRAY_DEFAULT_CAP 4
#define KUBO_DYNARRAY_REGISTER(name, type) \
struct name { \
type *data; \
size_t count; \
size_t capacity; \
}; \
\
static inline void name##_init(struct name *arr) { \
arr->count = 0; \
arr->capacity = KUBO_DRYNARRAY_DEFAULT_CAP; \
arr->data = malloc(sizeof(type) * arr->capacity); \
} \
\
static inline void name##_free(struct name *arr) { free(arr->data); } \
\
static inline bool name##_reserve(struct name *arr, size_t new_cap) { \
if (arr->capacity >= new_cap) \
return true; \
type *new_data = realloc(arr->data, sizeof(type) * new_cap); \
if (!new_data) \
return false; \
arr->data = new_data; \
arr->capacity = new_cap; \
return true; \
} \
\
static inline bool name##_add(struct name *arr, type new_val) { \
if (arr->count == arr->capacity - 1) { \
if (!name##_reserve(arr, arr->capacity * 2)) { \
return false; \
} \
} \
arr->data[arr->count++] = new_val; \
return true; \
} \
\
static inline type name##_get(struct name *arr, size_t index) { \
assert(index < arr->count); \
return arr->data[index]; \
}
#endif

View file

@ -6,37 +6,22 @@ struct kubo_wall *kubo_wall_init() {
if (!wall)
return NULL;
wall->num_vertices_alloc = KUBO_WALL_INIT_VERTICES;
wall->vertices = malloc(sizeof(Vector2) * wall->num_vertices_alloc);
wall->num_vertices = 0;
wall->state = KUBO_WALL_INIT;
kubo_vector2_arr_init(&wall->vertices);
return wall;
}
void kubo_wall_cleanup(struct kubo_wall *wall) {
free(wall->vertices);
kubo_vector2_arr_free(&wall->vertices);
free(wall);
}
bool kubo_wall_append(struct kubo_wall *wall, Vector2 vertex) {
Vector2 *new_vertices;
if (wall->num_vertices == wall->num_vertices_alloc - 1) {
wall->num_vertices_alloc *= 2;
new_vertices =
realloc(wall->vertices, sizeof(Vector2) * wall->num_vertices_alloc);
if (!new_vertices)
return false;
wall->vertices = new_vertices;
}
wall->vertices[wall->num_vertices++] = vertex;
return true;
bool kubo_wall_add_vertex(struct kubo_wall *wall, Vector2 vec) {
return kubo_vector2_arr_add(&wall->vertices, vec);
}
Vector2 kubo_wall_get_vertex(struct kubo_wall *wall, size_t index) {
return kubo_vector2_arr_get(&wall->vertices, index);
}

View file

@ -4,6 +4,8 @@
#include <stdlib.h>
#include <raylib.h>
#include "kubo_dynarray.h"
#define KUBO_WALL_INIT_VERTICES 4
enum kubo_wall_state {
@ -12,17 +14,18 @@ enum kubo_wall_state {
KUBO_WALL_DONE
};
struct kubo_wall {
Vector2 *vertices;
unsigned int num_vertices;
unsigned int num_vertices_alloc;
KUBO_DYNARRAY_REGISTER(kubo_vector2_arr, Vector2)
struct kubo_wall {
struct kubo_vector2_arr vertices;
enum kubo_wall_state state;
};
struct kubo_wall *kubo_wall_init();
void kubo_wall_cleanup(struct kubo_wall *wall);
bool kubo_wall_append(struct kubo_wall *wall, Vector2 vertex);
bool kubo_wall_add_vertex(struct kubo_wall *wall, Vector2 vec);
Vector2 kubo_wall_get_vertex(struct kubo_wall *wall, size_t index);
#endif

View file

@ -34,15 +34,17 @@ void kubo_window_render(struct kubo_context *context) {
DrawSplineLinear(points, 2, 10.f, BLACK);
}
for (int i = 0; i < context->num_walls; i++) {
DrawSplineLinear(context->walls[i]->vertices,
context->walls[i]->num_vertices, 10.f, BLACK);
if (context->walls[i]->state == KUBO_WALL_STARTED) {
Vector2 mouse_pos = GetMousePosition();
Vector2 points[] = {
context->walls[i]
->vertices[context->walls[i]->num_vertices - 1],
mouse_pos};
for (int i = 0; i < context->walls.count; i++) {
struct kubo_wall *wall = kubo_wall_arr_get(&context->walls, i);
assert(wall != NULL);
DrawSplineLinear(wall->vertices.data, wall->vertices.count, 10.f,
BLACK);
if (wall->state == KUBO_WALL_DRAWING) {
Vector2 mouse = GetMousePosition();
Vector2 points[] = {wall->vertices.data[wall->vertices.count - 1],
mouse};
DrawSplineLinear(points, 2, 10.f, BLACK);
}
}
@ -59,8 +61,8 @@ void kubo_window_input(struct kubo_context *context) {
if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) {
Vector2 new_pos = GetMousePosition();
kubo_wall_append(current_wall, new_pos);
current_wall->state = KUBO_WALL_STARTED;
kubo_wall_add_vertex(current_wall, new_pos);
current_wall->state = KUBO_WALL_DRAWING;
} else if (IsMouseButtonPressed(MOUSE_BUTTON_RIGHT)) {
current_wall->state = KUBO_WALL_DONE;
}