dynamic array contains function
This commit is contained in:
@@ -6,6 +6,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
typedef union any_align { char c; int i; long l; long long ll; float f; double d; void *p; long double ld; } any_align_t;
|
typedef union any_align { char c; int i; long l; long long ll; float f; double d; void *p; long double ld; } any_align_t;
|
||||||
#define MAX_ALIGN ((size_t) sizeof(any_align_t))
|
#define MAX_ALIGN ((size_t) sizeof(any_align_t))
|
||||||
@@ -106,9 +107,13 @@ allocator_t allocator_from_arena(arena_allocator_t *this);
|
|||||||
// dynamic arrays //////////////////////////////////////////////////////////////
|
// dynamic arrays //////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
typedef struct dyn_array_header {
|
typedef struct dyn_array_header {
|
||||||
size_t size, capacity, itemsize;
|
size_t n_items, capacity, itemsize;
|
||||||
allocator_t allocator;
|
allocator_t allocator;
|
||||||
uint8_t bytes[];
|
union {
|
||||||
|
// allocates a little more memory than needed, but who cares?
|
||||||
|
uint8_t bytes[1];
|
||||||
|
any_align_t _[1];
|
||||||
|
};
|
||||||
} dyn_array_header_t;
|
} dyn_array_header_t;
|
||||||
|
|
||||||
typedef struct dyn_array_create_func_args {
|
typedef struct dyn_array_create_func_args {
|
||||||
@@ -142,7 +147,7 @@ void dyn_array_shrink_func(void *this, size_t n_items_to_remove, const char *fil
|
|||||||
#define arr_reset(THIS)\
|
#define arr_reset(THIS)\
|
||||||
do {\
|
do {\
|
||||||
dyn_array_header_t *header = PTR_FROM_FIELD_PTR(dyn_array_header_t, bytes, THIS);\
|
dyn_array_header_t *header = PTR_FROM_FIELD_PTR(dyn_array_header_t, bytes, THIS);\
|
||||||
header->size = 0;\
|
header->n_items = 0;\
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
size_t arr_len(void *this);
|
size_t arr_len(void *this);
|
||||||
@@ -156,6 +161,28 @@ size_t arr_cap(void *this);
|
|||||||
|
|
||||||
#define arr_pop(THIS) (arr_shrink(THIS, 1), THIS[arr_len(THIS)])
|
#define arr_pop(THIS) (arr_shrink(THIS, 1), THIS[arr_len(THIS)])
|
||||||
|
|
||||||
|
|
||||||
|
/* Compile-time assert that works in expression contexts */
|
||||||
|
#define STATIC_ASSERT(expr) ((void)sizeof(char[(expr) ? 1 : -1]))
|
||||||
|
|
||||||
|
|
||||||
|
bool dyn_array_contains_func(void *this, uint8_t *value);
|
||||||
|
|
||||||
|
/*
|
||||||
|
arr_contains(THIS, TYPE, VALUE)
|
||||||
|
|
||||||
|
- SIZE CHECK: compile-time check that sizeof(*THIS) == sizeof(TYPE)
|
||||||
|
- TYPE is the type of the value to search for
|
||||||
|
- VALUE is stored in a compound literal of TYPE
|
||||||
|
- Pure C99, no extensions needed
|
||||||
|
- Callers with typeof support can make wrapper macros
|
||||||
|
*/
|
||||||
|
#define arr_contains(THIS, TYPE, VALUE)\
|
||||||
|
(\
|
||||||
|
STATIC_ASSERT(sizeof(*(THIS)) == sizeof(TYPE)),\
|
||||||
|
dyn_array_contains_func((THIS), (uint8_t*)&(TYPE){(VALUE)})\
|
||||||
|
)
|
||||||
|
|
||||||
// CLI /////////////////////////////////////////////////////////////////////////
|
// CLI /////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#define CLI_UNIQUE1 __macro_internal_34bba35b8b9b20a75f9881e3795630e25d36e620d9c9741e2e9141ba82ec6ef7__
|
#define CLI_UNIQUE1 __macro_internal_34bba35b8b9b20a75f9881e3795630e25d36e620d9c9741e2e9141ba82ec6ef7__
|
||||||
|
|||||||
+23
-6
@@ -39,7 +39,7 @@ static inline void *todo_remove_create_func(dyn_array_create_non_crashing_func_a
|
|||||||
args.file,
|
args.file,
|
||||||
args.line
|
args.line
|
||||||
);
|
);
|
||||||
header->size = 0;
|
header->n_items = 0;
|
||||||
header->capacity = args.initial_capacity;
|
header->capacity = args.initial_capacity;
|
||||||
header->itemsize = args.itemsize;
|
header->itemsize = args.itemsize;
|
||||||
header->allocator = args.allocator;
|
header->allocator = args.allocator;
|
||||||
@@ -48,7 +48,7 @@ static inline void *todo_remove_create_func(dyn_array_create_non_crashing_func_a
|
|||||||
|
|
||||||
static inline void *todo_remove_grow_func(void *this, size_t n_new_items, const char *file, int line) {
|
static inline void *todo_remove_grow_func(void *this, size_t n_new_items, const char *file, int line) {
|
||||||
dyn_array_header_t *header = PTR_FROM_FIELD_PTR(dyn_array_header_t, bytes, this);
|
dyn_array_header_t *header = PTR_FROM_FIELD_PTR(dyn_array_header_t, bytes, this);
|
||||||
size_t new_size = header->size + n_new_items;
|
size_t new_size = header->n_items + n_new_items;
|
||||||
|
|
||||||
if (header->capacity < new_size) {
|
if (header->capacity < new_size) {
|
||||||
size_t cap_times_2 = header->capacity * 2;
|
size_t cap_times_2 = header->capacity * 2;
|
||||||
@@ -65,7 +65,7 @@ static inline void *todo_remove_grow_func(void *this, size_t n_new_items, const
|
|||||||
);
|
);
|
||||||
header->capacity = new_capacity;
|
header->capacity = new_capacity;
|
||||||
}
|
}
|
||||||
header->size = new_size;
|
header->n_items = new_size;
|
||||||
return &header->bytes;
|
return &header->bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,18 +80,35 @@ void dyn_array_shrink_func(void *this, size_t n_items_to_remove, const char *fil
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
dyn_array_header_t *header = PTR_FROM_FIELD_PTR(dyn_array_header_t, bytes, this);
|
dyn_array_header_t *header = PTR_FROM_FIELD_PTR(dyn_array_header_t, bytes, this);
|
||||||
header->size -= n_items_to_remove;
|
header->n_items -= n_items_to_remove;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t arr_len(void *this) {
|
size_t arr_len(void *this) {
|
||||||
if (this == NULL) { return 0; }
|
if (this == NULL) { return 0; }
|
||||||
dyn_array_header_t *header = PTR_FROM_FIELD_PTR(dyn_array_header_t, bytes, this);
|
dyn_array_header_t *header = PTR_FROM_FIELD_PTR(dyn_array_header_t, bytes, this);
|
||||||
return header->size;
|
return header->n_items;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t dyn_array_capacity(void *this) {
|
size_t arr_cap(void *this) {
|
||||||
if (this == NULL) { return 0; }
|
if (this == NULL) { return 0; }
|
||||||
dyn_array_header_t *header = PTR_FROM_FIELD_PTR(dyn_array_header_t, bytes, this);
|
dyn_array_header_t *header = PTR_FROM_FIELD_PTR(dyn_array_header_t, bytes, this);
|
||||||
return header->capacity;
|
return header->capacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool dyn_array_contains_func(void *this, uint8_t *value) {
|
||||||
|
dyn_array_header_t *header = PTR_FROM_FIELD_PTR(dyn_array_header_t, bytes, this);
|
||||||
|
for (size_t i = 0; i < header->n_items; i++) {
|
||||||
|
bool is_equal = true;
|
||||||
|
for (size_t off = 0; off < header->itemsize; off++) {
|
||||||
|
if (header->bytes[i*header->itemsize+off] != value[off]) {
|
||||||
|
is_equal = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (is_equal) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|||||||
@@ -50,3 +50,21 @@ Test(dynamic_arrays, pop) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Test(dynamic_arrays, contains) {
|
||||||
|
with_borrow(alloc) {
|
||||||
|
int *numbers = make_arr(alloc, int);
|
||||||
|
arr_append(numbers, 20);
|
||||||
|
cr_expect(arr_contains(numbers, int, 20));
|
||||||
|
arr_reset(numbers);
|
||||||
|
|
||||||
|
for ( size_t y = 0; y < 1000; y++ ) {
|
||||||
|
for ( size_t i = 0; i < 100; i++ ) {
|
||||||
|
if (!arr_contains(numbers, int, i)) {
|
||||||
|
arr_append(numbers, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cr_assert_eq(arr_len(numbers), 100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user