| 43 static void *cx_iter_current_ptr(const void *it) { |
44 static void *cx_iter_current_ptr(const void *it) { |
| 44 const struct cx_iterator_s *iter = it; |
45 const struct cx_iterator_s *iter = it; |
| 45 return *(void**)iter->elem_handle; |
46 return *(void**)iter->elem_handle; |
| 46 } |
47 } |
| 47 |
48 |
| 48 static void cx_iter_next_fast(void *it) { |
49 static void cx_iter_next(void *it) { |
| 49 struct cx_iterator_s *iter = it; |
50 struct cx_iterator_s *iter = it; |
| 50 if (iter->base.remove) { |
51 assert(!iter->base.remove); |
| 51 iter->base.remove = false; |
52 iter->index++; |
| 52 iter->elem_count--; |
53 iter->elem_handle = ((char *) iter->elem_handle) + iter->elem_size; |
| 53 // only move the last element when we are not currently aiming |
|
| 54 // at the last element already |
|
| 55 if (iter->index < iter->elem_count) { |
|
| 56 void *last = ((char *) iter->src_handle) |
|
| 57 + iter->elem_count * iter->elem_size; |
|
| 58 memcpy(iter->elem_handle, last, iter->elem_size); |
|
| 59 } |
|
| 60 } else { |
|
| 61 iter->index++; |
|
| 62 iter->elem_handle = ((char *) iter->elem_handle) + iter->elem_size; |
|
| 63 } |
|
| 64 } |
54 } |
| 65 |
55 |
| 66 static void cx_iter_next_slow(void *it) { |
56 CxIterator cxIterator(const void *array, size_t elem_size, size_t elem_count) { |
| 67 struct cx_iterator_s *iter = it; |
|
| 68 if (iter->base.remove) { |
|
| 69 iter->base.remove = false; |
|
| 70 iter->elem_count--; |
|
| 71 |
|
| 72 // number of elements to move |
|
| 73 size_t remaining = iter->elem_count - iter->index; |
|
| 74 if (remaining > 0) { |
|
| 75 memmove( |
|
| 76 iter->elem_handle, |
|
| 77 ((char *) iter->elem_handle) + iter->elem_size, |
|
| 78 remaining * iter->elem_size |
|
| 79 ); |
|
| 80 } |
|
| 81 } else { |
|
| 82 iter->index++; |
|
| 83 iter->elem_handle = ((char *) iter->elem_handle) + iter->elem_size; |
|
| 84 } |
|
| 85 } |
|
| 86 |
|
| 87 CxIterator cxIterator( |
|
| 88 const void *array, |
|
| 89 size_t elem_size, |
|
| 90 size_t elem_count, |
|
| 91 bool remove_keeps_order |
|
| 92 ) { |
|
| 93 CxIterator iter; |
57 CxIterator iter; |
| 94 |
58 |
| 95 iter.index = 0; |
59 iter.index = 0; |
| 96 iter.src_handle = (void*) array; |
60 iter.src_handle = (void*) array; |
| 97 iter.elem_handle = (void*) array; |
61 iter.elem_handle = (void*) array; |
| 98 iter.elem_size = elem_size; |
62 iter.elem_size = elem_size; |
| 99 iter.elem_count = array == NULL ? 0 : elem_count; |
63 iter.elem_count = array == NULL ? 0 : elem_count; |
| 100 iter.base.valid = cx_iter_valid; |
64 iter.base.valid = cx_iter_valid; |
| 101 iter.base.current = cx_iter_current; |
65 iter.base.current = cx_iter_current; |
| 102 iter.base.next = remove_keeps_order ? cx_iter_next_slow : cx_iter_next_fast; |
66 iter.base.next = cx_iter_next; |
| |
67 iter.base.valid_impl = NULL; |
| |
68 iter.base.current_impl = NULL; |
| |
69 iter.base.next_impl = NULL; |
| 103 iter.base.remove = false; |
70 iter.base.remove = false; |
| 104 iter.base.allow_remove = true; |
71 iter.base.allow_remove = true; |
| 105 |
72 |
| 106 return iter; |
73 return iter; |
| 107 } |
74 } |
| 108 |
75 |
| 109 CxIterator cxIteratorPtr( |
76 CxIterator cxIteratorPtr(const void *array, size_t elem_count) { |
| 110 const void *array, |
77 CxIterator iter = cxIterator(array, sizeof(void*), elem_count); |
| 111 size_t elem_count, |
|
| 112 bool remove_keeps_order |
|
| 113 ) { |
|
| 114 CxIterator iter = cxIterator(array, sizeof(void*), elem_count, remove_keeps_order); |
|
| 115 iter.base.current = cx_iter_current_ptr; |
78 iter.base.current = cx_iter_current_ptr; |
| 116 return iter; |
79 return iter; |
| 117 } |
80 } |