feat(set): add set

This commit is contained in:
2026-03-16 23:06:29 +01:00
parent e7f2d6cdeb
commit a6740769b9
4 changed files with 178 additions and 13 deletions
+8 -3
View File
@@ -15,6 +15,7 @@ lib_src = files(
'hashmap/myhashmap.c',
'queue/myqueue.c',
'socket/mysocket.c',
'set/myset.c',
'stack/mystack.c',
'string/mystring.c',
'vector/myvector.c',
@@ -25,6 +26,7 @@ test_src = files(
'test/hashmap/hm1.c',
'test/queue/queue1.c',
'test/socket/socket1.c',
'test/set/set1.c',
'test/stack/stack1.c',
'test/string/str1.c',
'test/string/str2.c',
@@ -37,7 +39,7 @@ test_src = files(
winsock_dep = cc.find_library('ws2_32', required: false)
# Include directories
inc_dir = include_directories('string', 'queue', 'hashmap', 'vector', 'stack', 'socket')
inc_dir = include_directories('string', 'queue', 'hashmap', 'vector', 'stack', 'socket', 'set')
if host_machine.system() == 'windows'
win_inc_dir = include_directories('c:/include/')
else
@@ -60,6 +62,7 @@ install_headers(
'queue/myqueue.h',
'string/mystring.h',
'vector/myvector.h',
'set/myset.h',
'stack/mystack.h',
'socket/mysocket.h',
],
@@ -67,10 +70,12 @@ install_headers(
)
# Test executable
executable(
testlib_exe = executable(
'testlib',
lib_src + test_src,
test_src,
include_directories: [inc_dir, win_inc_dir],
dependencies: winsock_dep,
link_with: myclib_lib,
)
test('testlib', testlib_exe)
+129 -6
View File
@@ -1,6 +1,30 @@
#include "myset.h"
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
static int set_find_index_locked(set_s *set, void *elem, size_t *index_out) {
size_t size = vec_size(set->data);
for (size_t i = 0; i < size; ++i) {
void *current = vec_get(set->data, i);
if (current == NULL) {
return -1;
}
int equal = (memcmp(current, elem, set->elem_size) == 0);
free(current);
if (equal) {
*index_out = i;
return 0;
}
}
*index_out = SIZE_MAX;
return 0;
}
set_s *set_new(size_t element_size) {
if (element_size == 0) {
@@ -12,17 +36,116 @@ set_s *set_new(size_t element_size) {
return NULL;
}
// TODO: think about how to deal the free_value for each element
if (mtx_init(&set->lock, mtx_plain) != thrd_success) {
free(set);
return NULL;
}
set->data = vec_new(8, element_size);
if (set->data == NULL) {
mtx_destroy(&set->lock);
free(set);
return NULL;
}
set->elem_size = element_size;
return set;
}
int set_add(set_s *set, void *elem);
int set_add(set_s *set, void *elem) {
if (set == NULL || elem == NULL) {
return -1;
}
int set_remove(set_s *set, void *elem);
if (mtx_lock(&set->lock) != thrd_success) {
return -1;
}
int set_clear(set_s *set);
size_t index;
if (set_find_index_locked(set, elem, &index) != 0) {
mtx_unlock(&set->lock);
return -1;
}
int set_contains(set_s *set, void *elem);
if (index != SIZE_MAX) {
mtx_unlock(&set->lock);
return 0;
}
void set_free(set_s *set);
int ret = vec_push(set->data, elem);
mtx_unlock(&set->lock);
return ret;
}
int set_remove(set_s *set, void *elem) {
if (set == NULL || elem == NULL) {
return -1;
}
if (mtx_lock(&set->lock) != thrd_success) {
return -1;
}
size_t index;
if (set_find_index_locked(set, elem, &index) != 0) {
mtx_unlock(&set->lock);
return -1;
}
if (index == SIZE_MAX) {
mtx_unlock(&set->lock);
return -1;
}
int ret = vec_remove(set->data, index);
mtx_unlock(&set->lock);
return ret;
}
int set_clear(set_s *set) {
if (set == NULL) {
return -1;
}
if (mtx_lock(&set->lock) != thrd_success) {
return -1;
}
int ret = vec_clear(set->data);
mtx_unlock(&set->lock);
return ret;
}
int set_contains(set_s *set, void *elem) {
if (set == NULL || elem == NULL) {
return -1;
}
if (mtx_lock(&set->lock) != thrd_success) {
return -1;
}
size_t index;
if (set_find_index_locked(set, elem, &index) != 0) {
mtx_unlock(&set->lock);
return -1;
}
mtx_unlock(&set->lock);
return (index == SIZE_MAX) ? 0 : 1;
}
void set_free(set_s *set) {
if (set == NULL) {
return;
}
vec_free(set->data);
mtx_destroy(&set->lock);
free(set);
}
+10 -4
View File
@@ -1,27 +1,33 @@
#ifndef MYCLIB_SET_H
#define MYCLIB_SET_H
// TODO: WIP
#include <stddef.h>
#include <threads.h>
#include "../hashmap/myhashmap.h"
#include "../vector/myvector.h"
typedef struct set {
hashmap_s *map;
vec_s *data;
size_t elem_size;
mtx_t lock;
} set_s;
/* Create a new set for fixed-size elements. */
set_s *set_new(size_t element_size);
/* Add a new element to the set (no-op if already present). */
int set_add(set_s *set, void *elem);
/* Remove an element from the set. */
int set_remove(set_s *set, void *elem);
/* Remove all elements from the set. */
int set_clear(set_s *set);
/* Returns 1 if present, 0 if absent, -1 on error. */
int set_contains(set_s *set, void *elem);
/* Free the set and all related resources. */
void set_free(set_s *set);
#endif
+31
View File
@@ -0,0 +1,31 @@
#include "../set/myset.h"
#include <assert.h>
void test_set1(void) {
set_s *set = set_new(sizeof(int));
assert(set != NULL);
int a = 10;
int b = 20;
int another_a = 10;
int missing = 99;
assert(set_add(set, &a) == 0);
assert(set_add(set, &b) == 0);
/* Duplicate values are ignored and treated as success. */
assert(set_add(set, &another_a) == 0);
assert(set_contains(set, &a) == 1);
assert(set_contains(set, &another_a) == 1);
assert(set_contains(set, &missing) == 0);
assert(set_remove(set, &a) == 0);
assert(set_contains(set, &a) == 0);
assert(set_remove(set, &a) == -1);
assert(set_clear(set) == 0);
assert(set_contains(set, &b) == 0);
set_free(set);
}