src/linked_list.c

changeset 630
ac5e7f789048
parent 629
6c81ee4f11ad
child 638
eafb45eefc51
--- a/src/linked_list.c	Wed Nov 23 22:40:55 2022 +0100
+++ b/src/linked_list.c	Sat Nov 26 16:58:41 2022 +0100
@@ -643,13 +643,16 @@
                                   left->follow_ptr, right->follow_ptr, list->cmpfunc);
 }
 
-static bool cx_ll_iter_valid(CxIterator const *iter) {
+static bool cx_ll_iter_valid(void const *it) {
+    struct cx_iterator_s const *iter = it;
     return iter->elem_handle != NULL;
 }
 
-static void cx_ll_iter_next(CxIterator *iter) {
-    if (iter->remove) {
-        iter->remove = false;
+static void cx_ll_iter_next(void *it) {
+    struct cx_iterator_base_s *itbase = it;
+    if (itbase->remove) {
+        itbase->remove = false;
+        struct cx_mut_iterator_s *iter = it;
         cx_linked_list *ll = iter->src_handle;
         cx_linked_list_node *node = iter->elem_handle;
         iter->elem_handle = node->next;
@@ -658,48 +661,85 @@
         ll->base.size--;
         cxFree(ll->base.allocator, node);
     } else {
+        struct cx_iterator_s *iter = it;
         iter->index++;
         cx_linked_list_node *node = iter->elem_handle;
         iter->elem_handle = node->next;
     }
 }
 
-static void *cx_ll_iter_current(CxIterator const *iter) {
+static void *cx_ll_iter_current(void const *it) {
+    struct cx_iterator_s const *iter = it;
     cx_linked_list_node *node = iter->elem_handle;
     return node->payload;
 }
 
-static void *cx_pll_iter_current(CxIterator const *iter) {
+static void *cx_pll_iter_current(void const *it) {
+    struct cx_iterator_s const *iter = it;
     cx_linked_list_node *node = iter->elem_handle;
     return *(void **) node->payload;
 }
 
+static bool cx_ll_iter_flag_rm(void *it) {
+    struct cx_iterator_base_s *iter = it;
+    if (iter->mutating) {
+        iter->remove = true;
+        return true;
+    } else {
+        return false;
+    }
+}
+
 static CxIterator cx_ll_iterator(
-        struct cx_list_s *list,
+        struct cx_list_s const *list,
         size_t index
 ) {
     CxIterator iter;
     iter.index = index;
     iter.src_handle = list;
     iter.elem_handle = cx_ll_node_at((cx_linked_list const *) list, index);
-    iter.valid = cx_ll_iter_valid;
-    iter.current = cx_ll_iter_current;
-    iter.next = cx_ll_iter_next;
-    iter.remove = false;
+    iter.base.valid = cx_ll_iter_valid;
+    iter.base.current = cx_ll_iter_current;
+    iter.base.next = cx_ll_iter_next;
+    iter.base.flag_removal = cx_ll_iter_flag_rm;
+    iter.base.mutating = false;
+    iter.base.remove = false;
     return iter;
 }
 
 static CxIterator cx_pll_iterator(
+        struct cx_list_s const *list,
+        size_t index
+) {
+    CxIterator iter = cx_ll_iterator(list, index);
+    iter.base.current = cx_pll_iter_current;
+    return iter;
+}
+
+static CxMutIterator cx_ll_mut_iterator(
         struct cx_list_s *list,
         size_t index
 ) {
-    CxIterator iter = cx_ll_iterator(list, index);
-    iter.current = cx_pll_iter_current;
+    CxIterator it = cx_ll_iterator(list, index);
+    it.base.mutating = true;
+
+    // we know the iterators share the same memory layout
+    CxMutIterator iter;
+    memcpy(&iter, &it, sizeof(CxMutIterator));
+    return iter;
+}
+
+static CxMutIterator cx_pll_mut_iterator(
+        struct cx_list_s *list,
+        size_t index
+) {
+    CxMutIterator iter = cx_ll_mut_iterator(list, index);
+    iter.base.current = cx_pll_iter_current;
     return iter;
 }
 
 static int cx_ll_insert_iter(
-        CxIterator *iter,
+        CxMutIterator *iter,
         void const *elem,
         int prepend
 ) {
@@ -719,7 +759,7 @@
 }
 
 static int cx_pll_insert_iter(
-        CxIterator *iter,
+        CxMutIterator *iter,
         void const *elem,
         int prepend
 ) {
@@ -750,7 +790,8 @@
         cx_ll_sort,
         cx_ll_compare,
         cx_ll_reverse,
-        cx_ll_iterator
+        cx_ll_iterator,
+        cx_ll_mut_iterator,
 };
 
 static cx_list_class cx_pointer_linked_list_class = {
@@ -766,6 +807,7 @@
         cx_ll_compare,
         cx_ll_reverse,
         cx_pll_iterator,
+        cx_pll_mut_iterator,
 };
 
 CxList *cxLinkedListCreate(

mercurial