#include <cgraph/alloc.h>
#include <stdbool.h>
#include <stdlib.h>
+#include <string.h>
#ifdef __GNUC__
#define LIST_UNUSED __attribute__((unused))
list->data[index] = item; \
} \
\
+ /** remove an element from a list \
+ * \
+ * \param list List to operate on \
+ * \param item Value of element to remove \
+ */ \
+ static inline LIST_UNUSED void name##_remove(name##_t *list, type item) { \
+ assert(list != NULL); \
+ \
+ for (size_t i = 0; i < list->size; ++i) { \
+ /* is this the element we are looking for? */ \
+ if (memcmp(&list->data[i], &item, sizeof(type)) == 0) { \
+ \
+ /* destroy the element we are about to remove */ \
+ void (*dtor_)(type) = (void (*)(type))(dtor); \
+ if (dtor_ != NULL) { \
+ dtor_(list->data[i]); \
+ } \
+ \
+ /* shrink the list */ \
+ size_t remainder = (list->size - i - 1) * sizeof(type); \
+ memmove(&list->data[i], &list->data[i + 1], remainder); \
+ --list->size; \
+ return; \
+ } \
+ } \
+ } \
+ \
/** access an element in a list for the purpose of modification \
* \
* Because this acquires an internal pointer into the list structure, `get` \
ints_free(&xs);
}
+/// removing from an empty list should be a no-op
+static void test_remove_empty(void) {
+ ints_t xs = {0};
+ ints_remove(&xs, 10);
+ assert(ints_size(&xs) == 0);
+ ints_free(&xs);
+}
+
+/// some basic removal tests
+static void test_remove(void) {
+ ints_t xs = {0};
+
+ for (size_t i = 0; i < 10; ++i) {
+ ints_append(&xs, (int)i);
+ }
+
+ // remove something that does not exist
+ ints_remove(&xs, 42);
+ for (size_t i = 0; i < 10; ++i) {
+ assert(ints_get(&xs, i) == (int)i);
+ }
+
+ // remove in the middle
+ ints_remove(&xs, 4);
+ assert(ints_size(&xs) == 9);
+ for (size_t i = 0; i < 9; ++i) {
+ if (i < 4) {
+ assert(ints_get(&xs, i) == (int)i);
+ } else {
+ assert(ints_get(&xs, i) == (int)i + 1);
+ }
+ }
+
+ // remove the first
+ ints_remove(&xs, 0);
+ assert(ints_size(&xs) == 8);
+ for (size_t i = 0; i < 8; ++i) {
+ if (i < 3) {
+ assert(ints_get(&xs, i) == (int)i + 1);
+ } else {
+ assert(ints_get(&xs, i) == (int)i + 2);
+ }
+ }
+
+ // remove the last
+ ints_remove(&xs, 9);
+ assert(ints_size(&xs) == 7);
+ for (size_t i = 0; i < 7; ++i) {
+ if (i < 3) {
+ assert(ints_get(&xs, i) == (int)i + 1);
+ } else {
+ assert(ints_get(&xs, i) == (int)i + 2);
+ }
+ }
+
+ // remove all the rest
+ for (size_t i = 0; i < 7; ++i) {
+ ints_remove(&xs, ints_get(&xs, 0));
+ }
+ assert(ints_size(&xs) == 0);
+
+ ints_free(&xs);
+}
+
static void test_at(void) {
ints_t xs = {0};
for (size_t i = 0; i < 10; ++i) {
strs_free(&xs);
}
+/// test removal does not leak memory
+static void test_remove_with_dtor(void) {
+ strs_t xs = {0};
+
+ char *hello = strdup("hello");
+ assert(hello != NULL);
+
+ strs_append(&xs, hello);
+ strs_remove(&xs, hello);
+ assert(strs_size(&xs) == 0);
+
+ strs_free(&xs);
+}
+
int main(void) {
#define RUN(t) \
RUN(append);
RUN(get);
RUN(set);
+ RUN(remove_empty);
+ RUN(remove);
RUN(at);
RUN(clear_empty);
RUN(clear);
RUN(large);
RUN(attach_detach);
RUN(dtor);
+ RUN(remove_with_dtor);
#undef RUN