Sat, 22 Jan 2022 18:49:06 +0100
add the feature to remove items during iteration
src/cx/iterator.h | file | annotate | diff | comparison | revisions | |
src/cx/list.h | file | annotate | diff | comparison | revisions | |
src/linked_list.c | file | annotate | diff | comparison | revisions | |
test/test_list.c | file | annotate | diff | comparison | revisions |
1.1 --- a/src/cx/iterator.h Sat Jan 22 17:15:14 2022 +0100 1.2 +++ b/src/cx/iterator.h Sat Jan 22 18:49:06 2022 +0100 1.3 @@ -57,16 +57,6 @@ 1.4 */ 1.5 struct cx_iterator_s { 1.6 /** 1.7 - * If the iterator is position-aware, contains the index of the element in the underlying collection. 1.8 - * Otherwise, this field is usually uninitialized. 1.9 - */ 1.10 - size_t index; 1.11 - /** 1.12 - * Internal data. 1.13 - */ 1.14 - void *data; 1.15 - 1.16 - /** 1.17 * True iff the iterator points to valid data. 1.18 */ 1.19 bool (*valid)(CxIterator const *) __attribute__ ((__nonnull__)); 1.20 @@ -80,6 +70,29 @@ 1.21 * Advances the iterator. 1.22 */ 1.23 void (*next)(CxIterator *) __attribute__ ((__nonnull__)); 1.24 + 1.25 + /** 1.26 + * Handle for the current element, if required. 1.27 + */ 1.28 + void *elem_handle; 1.29 + 1.30 + /** 1.31 + * Handle for the source collection, if any. 1.32 + */ 1.33 + void *src_handle; 1.34 + 1.35 + /** 1.36 + * If the iterator is position-aware, contains the index of the element in the underlying collection. 1.37 + * Otherwise, this field is usually uninitialized. 1.38 + */ 1.39 + size_t index; 1.40 + 1.41 + /** 1.42 + * Users may set this to true, if the current element shall be removed from the underlying collection 1.43 + * when the iterator advances. 1.44 + * Has no effect on iterators that are not based on a collection. 1.45 + */ 1.46 + bool remove; 1.47 }; 1.48 1.49 /**
2.1 --- a/src/cx/list.h Sat Jan 22 17:15:14 2022 +0100 2.2 +++ b/src/cx/list.h Sat Jan 22 18:49:06 2022 +0100 2.3 @@ -125,7 +125,7 @@ 2.4 * Returns an iterator pointing to the specified index. 2.5 */ 2.6 CxIterator (*iterator)( 2.7 - cx_list_s const *list, 2.8 + cx_list_s *list, 2.9 size_t index 2.10 ); 2.11 } cx_list_class;
3.1 --- a/src/linked_list.c Sat Jan 22 17:15:14 2022 +0100 3.2 +++ b/src/linked_list.c Sat Jan 22 18:49:06 2022 +0100 3.3 @@ -641,40 +641,53 @@ 3.4 } 3.5 3.6 static bool cx_ll_iter_valid(CxIterator const *iter) { 3.7 - return iter->data != NULL; 3.8 + return iter->elem_handle != NULL; 3.9 } 3.10 3.11 static void cx_ll_iter_next(CxIterator *iter) { 3.12 - iter->index++; 3.13 - cx_linked_list_node *node = iter->data; 3.14 - iter->data = node->next; 3.15 + if (iter->remove) { 3.16 + iter->remove = false; 3.17 + cx_linked_list *ll = iter->src_handle; 3.18 + cx_linked_list_node *node = iter->elem_handle; 3.19 + iter->elem_handle = node->next; 3.20 + cx_linked_list_remove((void **) &ll->begin, (void **) &ll->end, 3.21 + CX_LL_LOC_PREV, CX_LL_LOC_NEXT, node); 3.22 + ll->base.size--; 3.23 + cxFree(ll->base.allocator, node); 3.24 + } else { 3.25 + iter->index++; 3.26 + cx_linked_list_node *node = iter->elem_handle; 3.27 + iter->elem_handle = node->next; 3.28 + } 3.29 } 3.30 3.31 static void *cx_ll_iter_current(CxIterator const *iter) { 3.32 - cx_linked_list_node *node = iter->data; 3.33 + cx_linked_list_node *node = iter->elem_handle; 3.34 return node->payload; 3.35 } 3.36 3.37 static void *cx_pll_iter_current(CxIterator const *iter) { 3.38 - cx_linked_list_node *node = iter->data; 3.39 + cx_linked_list_node *node = iter->elem_handle; 3.40 return *(void **) node->payload; 3.41 } 3.42 3.43 static CxIterator cx_ll_iterator( 3.44 - cx_list_s const *list, 3.45 + cx_list_s *list, 3.46 size_t index 3.47 ) { 3.48 CxIterator iter; 3.49 iter.index = index; 3.50 - iter.data = cx_ll_node_at((cx_linked_list const *) list, index); 3.51 + iter.src_handle = list; 3.52 + iter.elem_handle = cx_ll_node_at((cx_linked_list const *) list, index); 3.53 iter.valid = cx_ll_iter_valid; 3.54 iter.current = cx_ll_iter_current; 3.55 iter.next = cx_ll_iter_next; 3.56 + iter.remove = false; 3.57 return iter; 3.58 } 3.59 3.60 static CxIterator cx_pll_iterator( 3.61 - cx_list_s const *list, 3.62 + cx_list_s *list, 3.63 size_t index 3.64 ) { 3.65 CxIterator iter = cx_ll_iterator(list, index);
4.1 --- a/test/test_list.c Sat Jan 22 17:15:14 2022 +0100 4.2 +++ b/test/test_list.c Sat Jan 22 18:49:06 2022 +0100 4.3 @@ -762,12 +762,19 @@ 4.4 void test_hl_linked_list_iterator_impl(CxList list) { 4.5 int i = 0; 4.6 for (CxIterator iter = cxListBegin(list); cxIteratorValid(&iter); cxIteratorNext(&iter)) { 4.7 - CU_ASSERT_EQUAL(iter.index, (size_t) i) 4.8 + CU_ASSERT_EQUAL(iter.index, (size_t) (i + 1) / 2) 4.9 int *x = cxIteratorCurrent(&iter); 4.10 CU_ASSERT_EQUAL(*x, i) 4.11 + if (i % 2 == 1) iter.remove = true; 4.12 i++; 4.13 } 4.14 CU_ASSERT_EQUAL(i, 10) 4.15 + CU_ASSERT_EQUAL_FATAL(list->size, 5) 4.16 + CU_ASSERT_EQUAL(*(int *) cxListAt(list, 0), 0) 4.17 + CU_ASSERT_EQUAL(*(int *) cxListAt(list, 1), 2) 4.18 + CU_ASSERT_EQUAL(*(int *) cxListAt(list, 2), 4) 4.19 + CU_ASSERT_EQUAL(*(int *) cxListAt(list, 3), 6) 4.20 + CU_ASSERT_EQUAL(*(int *) cxListAt(list, 4), 8) 4.21 cxLinkedListDestroy(list); 4.22 CU_ASSERT_TRUE(cxTestingAllocatorVerify()) 4.23 }