feat(set): add set
This commit is contained in:
+8
-3
@@ -15,6 +15,7 @@ lib_src = files(
|
|||||||
'hashmap/myhashmap.c',
|
'hashmap/myhashmap.c',
|
||||||
'queue/myqueue.c',
|
'queue/myqueue.c',
|
||||||
'socket/mysocket.c',
|
'socket/mysocket.c',
|
||||||
|
'set/myset.c',
|
||||||
'stack/mystack.c',
|
'stack/mystack.c',
|
||||||
'string/mystring.c',
|
'string/mystring.c',
|
||||||
'vector/myvector.c',
|
'vector/myvector.c',
|
||||||
@@ -25,6 +26,7 @@ test_src = files(
|
|||||||
'test/hashmap/hm1.c',
|
'test/hashmap/hm1.c',
|
||||||
'test/queue/queue1.c',
|
'test/queue/queue1.c',
|
||||||
'test/socket/socket1.c',
|
'test/socket/socket1.c',
|
||||||
|
'test/set/set1.c',
|
||||||
'test/stack/stack1.c',
|
'test/stack/stack1.c',
|
||||||
'test/string/str1.c',
|
'test/string/str1.c',
|
||||||
'test/string/str2.c',
|
'test/string/str2.c',
|
||||||
@@ -37,7 +39,7 @@ test_src = files(
|
|||||||
winsock_dep = cc.find_library('ws2_32', required: false)
|
winsock_dep = cc.find_library('ws2_32', required: false)
|
||||||
|
|
||||||
# Include directories
|
# 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'
|
if host_machine.system() == 'windows'
|
||||||
win_inc_dir = include_directories('c:/include/')
|
win_inc_dir = include_directories('c:/include/')
|
||||||
else
|
else
|
||||||
@@ -60,6 +62,7 @@ install_headers(
|
|||||||
'queue/myqueue.h',
|
'queue/myqueue.h',
|
||||||
'string/mystring.h',
|
'string/mystring.h',
|
||||||
'vector/myvector.h',
|
'vector/myvector.h',
|
||||||
|
'set/myset.h',
|
||||||
'stack/mystack.h',
|
'stack/mystack.h',
|
||||||
'socket/mysocket.h',
|
'socket/mysocket.h',
|
||||||
],
|
],
|
||||||
@@ -67,10 +70,12 @@ install_headers(
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Test executable
|
# Test executable
|
||||||
executable(
|
testlib_exe = executable(
|
||||||
'testlib',
|
'testlib',
|
||||||
lib_src + test_src,
|
test_src,
|
||||||
include_directories: [inc_dir, win_inc_dir],
|
include_directories: [inc_dir, win_inc_dir],
|
||||||
dependencies: winsock_dep,
|
dependencies: winsock_dep,
|
||||||
link_with: myclib_lib,
|
link_with: myclib_lib,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
test('testlib', testlib_exe)
|
||||||
|
|||||||
+129
-6
@@ -1,6 +1,30 @@
|
|||||||
#include "myset.h"
|
#include "myset.h"
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
#include <stdlib.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) {
|
set_s *set_new(size_t element_size) {
|
||||||
if (element_size == 0) {
|
if (element_size == 0) {
|
||||||
@@ -12,17 +36,116 @@ set_s *set_new(size_t element_size) {
|
|||||||
return NULL;
|
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;
|
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
@@ -1,27 +1,33 @@
|
|||||||
#ifndef MYCLIB_SET_H
|
#ifndef MYCLIB_SET_H
|
||||||
#define MYCLIB_SET_H
|
#define MYCLIB_SET_H
|
||||||
|
|
||||||
// TODO: WIP
|
#include <stddef.h>
|
||||||
|
|
||||||
#include <threads.h>
|
#include <threads.h>
|
||||||
|
|
||||||
#include "../hashmap/myhashmap.h"
|
#include "../vector/myvector.h"
|
||||||
|
|
||||||
typedef struct set {
|
typedef struct set {
|
||||||
hashmap_s *map;
|
vec_s *data;
|
||||||
|
size_t elem_size;
|
||||||
mtx_t lock;
|
mtx_t lock;
|
||||||
} set_s;
|
} set_s;
|
||||||
|
|
||||||
|
/* Create a new set for fixed-size elements. */
|
||||||
set_s *set_new(size_t element_size);
|
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);
|
int set_add(set_s *set, void *elem);
|
||||||
|
|
||||||
|
/* Remove an element from the set. */
|
||||||
int set_remove(set_s *set, void *elem);
|
int set_remove(set_s *set, void *elem);
|
||||||
|
|
||||||
|
/* Remove all elements from the set. */
|
||||||
int set_clear(set_s *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);
|
int set_contains(set_s *set, void *elem);
|
||||||
|
|
||||||
|
/* Free the set and all related resources. */
|
||||||
void set_free(set_s *set);
|
void set_free(set_s *set);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user