aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/moslib/ds/hashmap.h31
-rw-r--r--include/moslib/tester.h21
-rw-r--r--src/ds/hashmap.c82
-rw-r--r--tests/ds/array_tests.c12
-rw-r--r--tests/ds/hashmap_tests.c46
-rw-r--r--tests/safe_tests.c26
-rw-r--r--tests/string_tests.c20
7 files changed, 167 insertions, 71 deletions
diff --git a/include/moslib/ds/hashmap.h b/include/moslib/ds/hashmap.h
index 3c50287..4136ac2 100644
--- a/include/moslib/ds/hashmap.h
+++ b/include/moslib/ds/hashmap.h
@@ -83,6 +83,14 @@
//
// ----------------------------------------------------------------------------------------------------
//
+// To delete an an entry from a hashmap use:
+//
+// int deleted = hm_del(hm, key);
+//
+// It will return 1 if entry of such key existed and was deleted, 0 otherwise.
+//
+// ----------------------------------------------------------------------------------------------------
+//
// You can loop over the hashmap using these functions:
//
// struct Entry *first = hm_first(hm);
@@ -130,6 +138,7 @@
#define hm_put_e mos_hm_put_e
#define hm_get mos_hm_get
#define hm_get_e mos_hm_get_e
+#define hm_del mos_hm_del
#define hm_first mos_hm_first
#define hm_next mos_hm_next
#define hm_size mos_hm_size
@@ -221,6 +230,19 @@ typedef struct {
// pointer to the entry or NULL if no entry with such key exists
#define mos_hm_get_e(hm, k) (mos_hm_ini, (hm)->key = k, mos_hm_get_e_fn(hm, mos_hm_fn_args))
+// Delete an entry with specific key from the hashmap
+//
+// Arguments:
+// hm
+// hashmap to delete from
+//
+// k
+// key of the entry to delete
+//
+// Returns:
+// 1 if an entry of given key was deleted, 0 otherwise
+#define mos_hm_del(hm, k) (mos_hm_ini, (hm)->key = k, mos_hm_del_fn(hm, mos_hm_fn_args))
+
// Get a pointer to the first entry in the hashmap
//
// Arguments:
@@ -250,7 +272,7 @@ typedef struct {
// Arguments:
// hm
// hashmap to get the count of entries from
-extern size_t mos_hm_size(void *hm);
+extern size_t mos_hm_size(const void *hm);
// Free the hashmap
//
@@ -268,8 +290,9 @@ extern void mos_hm_init(void *p_hm, size_t entry_size);
extern void *mos_hm_new_fn(MosHmInitArgs args);
extern void mos_hm_put_fn(void *p_hm, void *key, size_t entry_size, size_t key_size, uint8_t load_factor);
extern size_t mos_hm_get_fn(void *hm, void *key, size_t entry_size, size_t key_size);
-extern void *mos_hm_get_e_fn(void *hm, void *key, size_t entry_size, size_t key_size);
-extern void *mos_hm_first_fn(void *hm, size_t entry_size);
-extern void *mos_hm_next_fn(void *hm, void *curr, size_t entry_size);
+extern void *mos_hm_get_e_fn(const void *hm, const void *key, size_t entry_size, size_t key_size);
+extern int mos_hm_del_fn(const void *hm, const void *key, size_t entry_size, size_t key_size);
+extern void *mos_hm_first_fn(const void *hm, size_t entry_size);
+extern void *mos_hm_next_fn(const void *hm, const void *curr, size_t entry_size);
#endif // MOSLIB_DS_HASHMAP_H
diff --git a/include/moslib/tester.h b/include/moslib/tester.h
index a522b9d..f8cc8b1 100644
--- a/include/moslib/tester.h
+++ b/include/moslib/tester.h
@@ -23,10 +23,9 @@
// ----------------------------------------------------------------------------------------------------
//
// Create tests.
-// Tests are of type TestFn (Test (*)()).
// They should use test_assert functions to check correctness.
// Example:
-// Test test_fn() {
+// TEST(test_fn) {
// int result1 = 1 + 2;
// int result2 = 3 + 5;
//
@@ -38,11 +37,11 @@
// You need to create a helper test and pass it into test_assert_exit in main test.
// Pass the helper test and expected exit code to it.
// Example:
-// Test helper_test() {
+// TEST_HELPER(helper_test) {
// int param1, param2;
// int result = exit_failure_function(&param1, &param2);
// }
-// Test main_test() {
+// TEST(main_test) {
// test_assert_exit(helper_test, EXIT_FAILURE);
// }
//
@@ -50,17 +49,17 @@
// You need to create a helper test and pass it into test_assert_out in main test.
// Pass the helper test, output stream, and expected output to it.
// Example:
-// Test helper_test() {
+// TEST_HELPER(helper_test) {
// printf("output");
// }
-// Test main_test() {
+// TEST(main_test) {
// test_assert_out(helper_test, stdout, "output");
// }
//
// If your functions have output and you want to suppress them for the sake of tests,
// you can do so using suppress_output and unsupress_outputs.
// Example:
-// Test error_test() {
+// TEST(error_test) {
// suppress_output(stdout);
// suppress_output(stderr);
// int code = fun_that_fails_with_output();
@@ -96,7 +95,8 @@
#ifndef MOS_FORCE_PREFIXES
-#define Test MosTest
+#define TEST MOS_TEST
+#define TEST_HELPER MOS_TEST_HELPER
#define Tester MosTester
#define TestGroup MosTestGroup
#define TestFn MosTestFn
@@ -113,10 +113,11 @@
#endif // MOS_FORCE_PREFIXES
-typedef void MosTest; // this is just for nice indication that a function is a test
+#define MOS_TEST(name) static void name(void)
+#define MOS_TEST_HELPER MOS_TEST
typedef struct MosTester MosTester;
typedef struct MosTestGroup MosTestGroup;
-typedef MosTest (*MosTestFn)(void);
+typedef void (*MosTestFn)(void);
// Initalize new tester
// You can skip this and just define it as NULL - it will initalize automatically
diff --git a/src/ds/hashmap.c b/src/ds/hashmap.c
index 9b92302..60c85af 100644
--- a/src/ds/hashmap.c
+++ b/src/ds/hashmap.c
@@ -11,6 +11,7 @@
typedef struct {
uint8_t *filled;
+ uint8_t *dead;
size_t size;
size_t cap;
uint32_t (*hash)(const void *key);
@@ -25,14 +26,26 @@ static void *hdr2hm(Header *hdr) {
return hdr + 1;
}
-static int filled(void *hm, size_t index) {
+static int filled(const void *hm, size_t index) {
return hm2hdr(hm)->filled[index / 8] & (1 << index % 8);
}
-static void fill(void *hm, size_t index) {
+static void fill(const void *hm, size_t index) {
hm2hdr(hm)->filled[index / 8] |= (1 << index % 8);
}
+static int dead(const void *hm, size_t index) {
+ return hm2hdr(hm)->dead[index / 8] & (1 << index % 8);
+}
+
+static void kill(const void *hm, size_t index) {
+ hm2hdr(hm)->dead[index / 8] |= (1 << index % 8);
+}
+
+static void unkill(const void *hm, size_t index) {
+ hm2hdr(hm)->dead[index / 8] &= (0xFF ^ (1 << index % 8));
+}
+
// FNV-1a
static uint32_t default_hash(const void *key, size_t key_size) {
const uint8_t *p = key;
@@ -71,6 +84,7 @@ void mos_hm_init(void *p_hm, size_t entry_size) {
Header *hdr = mos_safe_malloc(sizeof(Header) + (INIT_CAP + 1) * entry_size);
*hdr = (Header){
.filled = mos_safe_calloc((INIT_CAP - 1) / 8 + 1, 1),
+ .dead = mos_safe_calloc((INIT_CAP - 1) / 8 + 1, 1),
.size = 0,
.cap = INIT_CAP,
.hash = NULL,
@@ -84,6 +98,7 @@ void mos_hm_init(void *p_hm, size_t entry_size) {
if (hdr->cap == 0) {
hdr = mos_safe_realloc(hdr, sizeof(Header) + (INIT_CAP + 1) * entry_size);
hdr->filled = mos_safe_calloc((INIT_CAP - 1) / 8 + 1, 1);
+ hdr->dead = mos_safe_calloc((INIT_CAP - 1) / 8 + 1, 1);
hdr->cap = INIT_CAP;
*(void **)p_hm = hdr2hm(hdr);
}
@@ -92,6 +107,7 @@ void mos_hm_init(void *p_hm, size_t entry_size) {
void *mos_hm_new_fn(MosHmInitArgs args) {
Header *hdr = mos_safe_malloc(sizeof(Header));
hdr->filled = NULL;
+ hdr->dead = NULL;
hdr->cap = 0;
hdr->size = 0;
@@ -118,16 +134,20 @@ void *mos_hm_new_fn(MosHmInitArgs args) {
return hdr2hm(hdr);
}
-static size_t probe(void *hm, void *key, size_t entry_size, size_t key_size, size_t key_off) {
+static size_t probe(const void *hm, const void *key, size_t entry_size, size_t key_size, size_t key_off, int put) {
Header *hdr = hm2hdr(hm);
uint32_t hash = hdr->hash ? hdr->hash(key) : default_hash(key, key_size);
size_t i = hash % hdr->cap;
+ size_t tomb = 0;
for (size_t it = 0; it < hdr->cap; it++) {
void *key2 = (char *)hm + (i + 1) * entry_size + key_off;
- if (!filled(hm, i) || (hdr->eq ? hdr->eq(key, key2) : default_eq(key, key2, key_size))) {
+ if (!filled(hm, i))
+ return tomb ? tomb : i;
+ if (hdr->eq ? hdr->eq(key, key2) : default_eq(key, key2, key_size))
return i;
- }
+ if (put && tomb == 0 && dead(hm, i))
+ tomb = i;
i = (i + 1) % hdr->cap;
}
return 0;
@@ -140,7 +160,8 @@ static void expand(void *p_hm, size_t entry_size, size_t key_size, size_t key_of
Header *new_hdr = mos_safe_malloc(sizeof(Header) + (2 * hdr->cap + 1) * entry_size);
*new_hdr = (Header){
.filled = mos_safe_calloc((2 * hdr->cap - 1) / 8 + 1, 1),
- .size = hdr->size,
+ .dead = mos_safe_calloc((2 * hdr->cap - 1) / 8 + 1, 1),
+ .size = mos_hm_size(hm),
.cap = 2 * hdr->cap,
.hash = hdr->hash,
.eq = hdr->eq,
@@ -148,7 +169,7 @@ static void expand(void *p_hm, size_t entry_size, size_t key_size, size_t key_of
void *new_hm = hdr2hm(new_hdr);
for (size_t i = 0; i < hdr->cap; i++) {
- if (!filled(hm, i))
+ if (!filled(hm, i) || dead(hm, i))
continue;
void *entry = (char *)hm + (i + 1) * entry_size;
@@ -167,6 +188,7 @@ static void expand(void *p_hm, size_t entry_size, size_t key_size, size_t key_of
}
free(hdr->filled);
+ free(hdr->dead);
free(hdr);
*(void **)p_hm = new_hm;
}
@@ -176,12 +198,13 @@ void mos_hm_put_fn(void *p_hm, void *key, size_t entry_size, size_t key_size, ui
Header *hdr = hm2hdr(*(void **)p_hm);
void *hm = *(void **)p_hm;
- size_t i = probe(hm, key, entry_size, key_size, key_off);
+ size_t i = probe(hm, key, entry_size, key_size, key_off, 1);
memcpy((char *)hm + (i + 1) * entry_size, hm, entry_size);
if (!filled(hm, i)) {
hdr->size++;
fill(hm, i);
}
+ unkill(hm, i);
if (hdr->size * 100 >= hdr->cap * load_factor)
expand(p_hm, entry_size, key_size, key_off);
@@ -189,23 +212,32 @@ void mos_hm_put_fn(void *p_hm, void *key, size_t entry_size, size_t key_size, ui
size_t mos_hm_get_fn(void *hm, void *key, size_t entry_size, size_t key_size) {
size_t key_off = (char *)key - (char *)hm;
- size_t i = probe(hm, key, entry_size, key_size, key_off);
- if (!filled(hm, i)) {
+ size_t i = probe(hm, key, entry_size, key_size, key_off, 0);
+ if (!filled(hm, i) || dead(hm, i)) {
memset(hm, 0, entry_size);
return 0;
}
return i + 1;
}
-void *mos_hm_get_e_fn(void *hm, void *key, size_t entry_size, size_t key_size) {
+void *mos_hm_get_e_fn(const void *hm, const void *key, size_t entry_size, size_t key_size) {
size_t key_off = (char *)key - (char *)hm;
- size_t i = probe(hm, key, entry_size, key_size, key_off);
- if (!filled(hm, i))
+ size_t i = probe(hm, key, entry_size, key_size, key_off, 0);
+ if (!filled(hm, i) || dead(hm, i))
return NULL;
return (char *)hm + (i + 1) * entry_size;
}
-void *mos_hm_first_fn(void *hm, size_t entry_size) {
+int mos_hm_del_fn(const void *hm, const void *key, size_t entry_size, size_t key_size) {
+ size_t key_off = (char *)key - (char *)hm;
+ size_t i = probe(hm, key, entry_size, key_size, key_off, 0);
+ if (!filled(hm, i) || dead(hm, i))
+ return 0;
+ kill(hm, i);
+ return 1;
+}
+
+void *mos_hm_first_fn(const void *hm, size_t entry_size) {
if (!hm)
return NULL;
@@ -214,13 +246,13 @@ void *mos_hm_first_fn(void *hm, size_t entry_size) {
return NULL;
for (size_t i = 0; i < hdr->cap; i++) {
- if (filled(hm, i))
+ if (filled(hm, i) && !dead(hm, i))
return (char *)hm + (i + 1) * entry_size;
}
return NULL;
}
-void *mos_hm_next_fn(void *hm, void *curr, size_t entry_size) {
+void *mos_hm_next_fn(const void *hm, const void *curr, size_t entry_size) {
if (!hm)
return NULL;
@@ -236,16 +268,27 @@ void *mos_hm_next_fn(void *hm, void *curr, size_t entry_size) {
return NULL;
for (size_t i = index; i < hdr->cap; i++) {
- if (filled(hm, i))
+ if (filled(hm, i) && !dead(hm, i))
return (char *)hm + (i + 1) * entry_size;
}
return NULL;
}
-size_t mos_hm_size(void *hm) {
+static size_t bit_count(const uint8_t *bitmap, size_t size) {
+ size_t count = 0;
+ for (size_t i = 0; i < size; i++) {
+ uint8_t c = (bitmap[i] & 0x55) + ((bitmap[i] >> 1) & 0x55);
+ c = (c & 0x33) + ((c >> 2) & 0x33);
+ count += (c & 0x0F) + ((c >> 4) & 0x0F);
+ }
+ return count;
+}
+
+size_t mos_hm_size(const void *hm) {
if (!hm)
return 0;
- return hm2hdr(hm)->size;
+ Header *hdr = hm2hdr(hm);
+ return hdr->size - bit_count(hdr->dead, (hdr->cap - 1) / 8 + 1);
}
void mos_hm_free(void *hm) {
@@ -254,5 +297,6 @@ void mos_hm_free(void *hm) {
Header *hdr = hm2hdr(hm);
free(hdr->filled);
+ free(hdr->dead);
free(hdr);
}
diff --git a/tests/ds/array_tests.c b/tests/ds/array_tests.c
index b292407..c5d7c4d 100644
--- a/tests/ds/array_tests.c
+++ b/tests/ds/array_tests.c
@@ -4,7 +4,7 @@
#include <string.h>
-Test cap_test() {
+TEST(cap_test) {
float *arr = NULL;
test_assert(arr_cap(arr) == 0, "uninitialized array has capacity different than 0");
@@ -24,7 +24,7 @@ Test cap_test() {
arr_free(arr);
}
-Test len_test() {
+TEST(len_test) {
char *arr = NULL;
test_assert(arr_len(arr) == 0, "uninitialized array has length different than 0");
@@ -39,7 +39,7 @@ Test len_test() {
arr_free(arr);
}
-Test adding_items() {
+TEST(adding_items) {
int *arr = NULL;
// {3}
@@ -84,7 +84,7 @@ Test adding_items() {
arr_free(arr);
}
-Test getting_items() {
+TEST(getting_items) {
struct test {
int f1;
char f2;
@@ -121,7 +121,7 @@ Test getting_items() {
arr_free(arr);
}
-Test deleting_items() {
+TEST(deleting_items) {
int *arr = NULL;
int items[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
arr_append_n(arr, items, 9);
@@ -152,7 +152,7 @@ Test deleting_items() {
arr_free(arr);
}
-Test arr_concat_test() {
+TEST(arr_concat_test) {
unsigned long *arr1 = NULL;
unsigned long *arr2 = NULL;
diff --git a/tests/ds/hashmap_tests.c b/tests/ds/hashmap_tests.c
index 288bb4e..844ffb2 100644
--- a/tests/ds/hashmap_tests.c
+++ b/tests/ds/hashmap_tests.c
@@ -8,7 +8,9 @@
#include "moslib/ds/array.h"
#include "moslib/string.h"
-Test put_get() {
+#define INIT_CAP 16
+
+TEST(put_get) {
HM_DEF(E, float, int);
E *hm = NULL;
@@ -21,22 +23,21 @@ Test put_get() {
test_assert(hm_get(hm, 0.0f) == 2137, "hm_put didn't update value properly");
test_assert(hm_size(hm) == 2, "hm_size returned wrong entry count");
- // a lot of puts and gets to test expansion of hashmap
- for (int i = 2; i < 100; i++) {
+ for (int i = 2; i < 2 * INIT_CAP + 2; i++) {
hm_put(hm, (float)i, i);
}
int flag = 1;
- for (int i = 2; i < 100; i++) {
+ for (int i = 2; i < 2 * INIT_CAP + 2; i++) {
if (hm_get(hm, (float)i) != i)
flag = 0;
}
test_assert(flag, "hm_put / hm_get failed when expansion was needed");
- test_assert(hm_size(hm) == 100, "hm_size returned wrong entry count");
+ test_assert(hm_size(hm) == 2 * INIT_CAP + 2, "hm_size returned wrong entry count");
hm_free(hm);
}
-Test put_e_get_e() {
+TEST(put_e_get_e) {
HM_DEF(E, float, int);
E *hm = NULL;
@@ -54,7 +55,33 @@ Test put_e_get_e() {
hm_free(hm);
}
-Test str_key() {
+TEST(deleting) {
+ HM_DEF(E, long double, float);
+ E *hm = NULL;
+
+ hm_put(hm, 1.0, 1.0);
+ hm_put(hm, 2.0, 2.0);
+
+ int del = hm_del(hm, 1.0);
+ test_assert(hm_get_e(hm, 1.0) == NULL, "hm_del didn't delete entry it supposed to");
+ test_assert(del == 1, "hm_del didn't return 1 when it deleted");
+ test_assert(hm_size(hm) == 1, "hm_size after successful hm_del is incorrect");
+
+ del = hm_del(hm, 1.0);
+ test_assert(del == 0, "hm_del didn't return 0 when it didn't delete");
+ test_assert(hm_get(hm, 2.0) == 2.0, "hm_del deleted wrong entry");
+ test_assert(hm_size(hm) == 1, "hm_size after failed hm_del is incorrect");
+
+ for (int i = 3; i < 2 * INIT_CAP + 3; i++) {
+ hm_put(hm, (long double)i, (float)i);
+ }
+ test_assert(hm_get_e(hm, 1.0) == NULL, "expansion revived entry");
+ test_assert(hm_size(hm) == 2 * INIT_CAP + 1, "hm_size after expansion is incorrect");
+
+ hm_free(hm);
+}
+
+TEST(str_key) {
HM_DEF(E, char *, int);
E *hm = hm_new(.key = STR);
@@ -72,7 +99,7 @@ Test str_key() {
hm_free(hm);
}
-Test ss_key() {
+TEST(ss_key) {
HM_DEF(E, StringSlice, int);
E *hm = hm_new(.key = SS);
@@ -92,7 +119,7 @@ Test ss_key() {
hm_free(hm);
}
-Test looping() {
+TEST(looping) {
HM_DEF(E, int, int);
E *hm = NULL;
@@ -127,6 +154,7 @@ void ds_hashmap_tests(Tester *tester) {
TestGroup *group = add_test_group(tester, "moslib/ds/hashmap.h");
add_test(group, put_get);
add_test(group, put_e_get_e);
+ add_test(group, deleting);
add_test(group, str_key);
add_test(group, ss_key);
add_test(group, looping);
diff --git a/tests/safe_tests.c b/tests/safe_tests.c
index 3d46a37..b50b073 100644
--- a/tests/safe_tests.c
+++ b/tests/safe_tests.c
@@ -5,11 +5,11 @@
#include <stdlib.h>
#include <unistd.h>
-Test malloc_exit() {
+TEST_HELPER(malloc_exit) {
safe_malloc(ULLONG_MAX);
}
-Test test_safe_malloc() {
+TEST(test_safe_malloc) {
void *p = safe_malloc(1024);
test_assert(p != NULL, "Failed to malloc 1KiB");
@@ -18,11 +18,11 @@ Test test_safe_malloc() {
unsuppress_outputs();
}
-Test calloc_exit() {
+TEST_HELPER(calloc_exit) {
safe_calloc(ULLONG_MAX, ULLONG_MAX);
}
-Test test_safe_calloc() {
+TEST(test_safe_calloc) {
void *p = safe_calloc(16, 16);
test_assert(p != NULL, "Failed to calloc 16 items of 16 bytes");
@@ -31,12 +31,12 @@ Test test_safe_calloc() {
unsuppress_outputs();
}
-Test realloc_exit() {
+TEST_HELPER(realloc_exit) {
void *p = NULL;
safe_realloc(p, ULLONG_MAX);
}
-Test test_safe_realloc() {
+TEST(test_safe_realloc) {
void *p = NULL;
p = safe_realloc(p, 1024);
test_assert(p != NULL, "Failed to realloc NULL to 1KiB");
@@ -49,11 +49,11 @@ Test test_safe_realloc() {
unsuppress_outputs();
}
-Test fopen_exit() {
+TEST_HELPER(fopen_exit) {
safe_fopen("/non-existing-file-name", "r");
}
-Test test_safe_fopen() {
+TEST(test_safe_fopen) {
FILE *fp = safe_fopen(__FILE__, "r");
test_assert(fp != NULL, "Failed to fopen current file");
@@ -62,16 +62,16 @@ Test test_safe_fopen() {
unsuppress_outputs();
}
-Test test_safe_tmpfile() {
+TEST(test_safe_tmpfile) {
FILE *fp = safe_tmpfile();
test_assert(fp != NULL, "Failed to create a tmpfile");
}
-Test dup_exit() {
+TEST_HELPER(dup_exit) {
safe_dup(-1);
}
-Test test_safe_dup() {
+TEST(test_safe_dup) {
int fd = safe_dup(STDOUT_FILENO);
test_assert(fd != -1, "Failed to dup STDOUT_FILENO");
close(fd);
@@ -81,11 +81,11 @@ Test test_safe_dup() {
unsuppress_outputs();
}
-Test dup2_exit() {
+TEST_HELPER(dup2_exit) {
safe_dup2(-1, STDOUT_FILENO);
}
-Test test_safe_dup2() {
+TEST(test_safe_dup2) {
int res = dup2(STDOUT_FILENO, STDOUT_FILENO);
test_assert(res != -1, "Failed to dup STDOUT_FILENO 2 itself");
diff --git a/tests/string_tests.c b/tests/string_tests.c
index 4cb6372..0d0d7e2 100644
--- a/tests/string_tests.c
+++ b/tests/string_tests.c
@@ -9,7 +9,7 @@
#define HELLO_WORLD_LIT "Hello, World!"
-Test creating() {
+TEST(creating) {
char *str = HELLO_WORLD_LIT;
size_t str_len = strlen(str);
@@ -32,12 +32,12 @@ Test creating() {
test_assert(ss5.data == ss1.data && ss5.len == ss1.len, "ss_from_arr created wrong slice");
}
-Test ss_print_helper() {
+TEST(ss_print_helper) {
StringSlice ss = ss_from_str("test");
ss_print(ss);
}
-Test printing() {
+TEST(printing) {
test_assert_out(ss_print_helper, stdout, "test");
StringSlice ss = ss_from_str("slice");
@@ -46,7 +46,7 @@ Test printing() {
test_assert(strcmp(buf, "out: slice :)") == 0, "SS_FMT + SS_ARGS printed wrong output");
}
-Test comparing() {
+TEST(comparing) {
StringSlice ss = ss_from_str("hello world");
test_assert(ss_eq(ss, ss), "slice is not equal to itself");
test_assert(ss_eq_str(ss, ss.data), "slice is not equal to its C string");
@@ -66,7 +66,7 @@ Test comparing() {
test_assert(ss_eq_str(ss4, "world") == 0, "slice is equal to different string");
}
-Test trimming() {
+TEST(trimming) {
StringSlice ss = ss_from_str(" Hi :) ");
StringSlice t = ss_trim(ss);
test_assert(ss_eq_str(t, "Hi :)"), "trim didn't trim properly");
@@ -83,7 +83,7 @@ Test trimming() {
test_assert(ss_eq_str(t, ""), "trimming breaks for all whitespace slice");
}
-Test prefix_suffix() {
+TEST(prefix_suffix) {
StringSlice ss = ss_from_str("pre mid suf");
test_assert(ss_starts_with(ss, ss_from_str("pre")), "slice doesn't start with its slice prefix");
@@ -103,7 +103,7 @@ Test prefix_suffix() {
test_assert(ss_ends_with(ss2, ss_from_str("")), "ends_with breaks for empty slice and suffix");
}
-Test deleting() {
+TEST(deleting) {
StringSlice ss = ss_from_str("1234567890");
size_t deleted = ss_del_left(&ss, 2);
@@ -147,7 +147,7 @@ Test deleting() {
test_assert(!flag && ss.len == 7, "del_suffix_str didn't work properly for not found suffix");
}
-Test splitting() {
+TEST(splitting) {
StringSlice ss1 = ss_from_str("Hello, World!");
StringSlice ss2 = ss_split(&ss1, ',');
@@ -191,7 +191,7 @@ Test splitting() {
test_assert(ss_eq_str(ss_right, "") && ss_eq_str(ss_middle, ""), "ss_split_right didn't split properly (n > len)");
}
-Test finding() {
+TEST(finding) {
char *txt = "a slice of FINDME text";
StringSlice ss = ss_from_str(txt);
@@ -205,7 +205,7 @@ Test finding() {
test_assert(ss_eq_str(ss_find_str(ss, "abcd"), ""), "find_str didn't return empty slice for not found target");
}
-Test utf8_len_test() {
+TEST(utf8_len_test) {
StringSlice ss = ss_from_str("1 byte chars");
test_assert(ss_utf8_len(ss) == ss.len, "utf8_len differs from len for all 1 byte characters");