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