135 assert(loc_prev < 0 || CX_LL_PTR(new_node, loc_prev) == NULL); |
135 assert(loc_prev < 0 || CX_LL_PTR(new_node, loc_prev) == NULL); |
136 *begin = new_node; |
136 *begin = new_node; |
137 } |
137 } |
138 } |
138 } |
139 |
139 |
140 void *cx_linked_list_remove(void **begin, void **end, ptrdiff_t loc_prev, ptrdiff_t loc_next, void *node) { |
140 void cx_linked_list_remove(void **begin, void **end, ptrdiff_t loc_prev, ptrdiff_t loc_next, void *node) { |
141 assert(loc_next >= 0); |
141 assert(loc_next >= 0); |
142 assert(loc_prev >= 0 || begin != NULL); |
142 assert(loc_prev >= 0 || begin != NULL); |
143 |
143 |
144 // find adjacent nodes |
144 // find adjacent nodes |
145 void *next = CX_LL_PTR(node, loc_next); |
145 void *next = CX_LL_PTR(node, loc_next); |
148 prev = CX_LL_PTR(node, loc_prev); |
148 prev = CX_LL_PTR(node, loc_prev); |
149 } else { |
149 } else { |
150 prev = cx_linked_list_prev(*begin, loc_next, node); |
150 prev = cx_linked_list_prev(*begin, loc_next, node); |
151 } |
151 } |
152 |
152 |
153 // update links of adjacent nodes |
153 // update next pointer of prev node, or set begin |
154 if (prev != NULL) { |
154 if (prev == NULL) { |
|
155 if (begin != NULL) { |
|
156 *begin = next; |
|
157 } |
|
158 } else { |
155 CX_LL_PTR(prev, loc_next) = next; |
159 CX_LL_PTR(prev, loc_next) = next; |
156 } |
160 } |
157 if (next != NULL && loc_prev >= 0) { |
161 |
|
162 // update prev pointer of next node, or set end |
|
163 if (next == NULL) { |
|
164 if (end != NULL) { |
|
165 *end = prev; |
|
166 } |
|
167 } else if (loc_prev >= 0) { |
158 CX_LL_PTR(next, loc_prev) = prev; |
168 CX_LL_PTR(next, loc_prev) = prev; |
159 } |
169 } |
160 |
|
161 // erase links of the target node |
|
162 CX_LL_PTR(node, loc_next) = NULL; |
|
163 if (loc_prev >= 0) { |
|
164 CX_LL_PTR(node, loc_prev) = NULL; |
|
165 } |
|
166 |
|
167 // update begin, if required |
|
168 if (*begin == node) { |
|
169 *begin = next; |
|
170 } |
|
171 |
|
172 // update end, if required |
|
173 if (end != NULL && *end == node) { |
|
174 *end = prev; |
|
175 } |
|
176 |
|
177 return prev == NULL ? next : prev; |
|
178 } |
170 } |
179 |
171 |
180 size_t cx_linked_list_size(void *node, ptrdiff_t loc_next) { |
172 size_t cx_linked_list_size(void *node, ptrdiff_t loc_next) { |
181 assert(loc_next >= 0); |
173 assert(loc_next >= 0); |
182 size_t size = 0; |
174 size_t size = 0; |
237 free(sorted); |
229 free(sorted); |
238 } |
230 } |
239 return ret; |
231 return ret; |
240 } |
232 } |
241 |
233 |
242 void cx_linked_list_sort(void **begin, void **end, ptrdiff_t loc_prev, ptrdiff_t loc_next, |
234 void cx_linked_list_sort( /* NOLINT(misc-no-recursion) - purposely recursive function */ |
243 ptrdiff_t loc_data, int follow_ptr, CxListComparator cmp_func) { |
235 void **begin, void **end, ptrdiff_t loc_prev, ptrdiff_t loc_next, |
|
236 ptrdiff_t loc_data, int follow_ptr, CxListComparator cmp_func) { |
244 assert(begin != NULL); |
237 assert(begin != NULL); |
245 assert(loc_next >= 0); |
238 assert(loc_next >= 0); |
246 assert(loc_data >= 0); |
239 assert(loc_data >= 0); |
247 assert(cmp_func); |
240 assert(cmp_func); |
248 |
241 |
422 cx_linked_list_node *node = cx_ll_node_at(ll, index); |
415 cx_linked_list_node *node = cx_ll_node_at(ll, index); |
423 |
416 |
424 // out-of-bounds check |
417 // out-of-bounds check |
425 if (node == NULL) return 1; |
418 if (node == NULL) return 1; |
426 |
419 |
427 // change left side connection |
420 // remove |
428 if (node->prev == NULL) { |
421 cx_linked_list_remove((void **) &ll->begin, (void **) &ll->end, |
429 ll->begin = node->next; |
422 CX_LL_LOC_PREV, CX_LL_LOC_NEXT, node); |
430 } else { |
|
431 node->prev->next = node->next; |
|
432 } |
|
433 |
|
434 // change right side connection |
|
435 if (node->next == NULL) { |
|
436 ll->end = node->prev; |
|
437 } else { |
|
438 node->next->prev = node->prev; |
|
439 } |
|
440 |
423 |
441 // adjust size |
424 // adjust size |
442 list->size--; |
425 list->size--; |
443 |
426 |
444 // free and return |
427 // free and return |