| 39 #define ll_next(node) CX_LL_PTR(node, loc_next) |
38 #define ll_next(node) CX_LL_PTR(node, loc_next) |
| 40 #define ll_advance(node) CX_LL_PTR(node, loc_advance) |
39 #define ll_advance(node) CX_LL_PTR(node, loc_advance) |
| 41 #define ll_data(node) (((char*)(node))+loc_data) |
40 #define ll_data(node) (((char*)(node))+loc_data) |
| 42 |
41 |
| 43 void *cx_linked_list_at( |
42 void *cx_linked_list_at( |
| 44 void const *start, |
43 const void *start, |
| 45 size_t start_index, |
44 size_t start_index, |
| 46 ptrdiff_t loc_advance, |
45 ptrdiff_t loc_advance, |
| 47 size_t index |
46 size_t index |
| 48 ) { |
47 ) { |
| 49 assert(start != NULL); |
48 assert(start != NULL); |
| 50 assert(loc_advance >= 0); |
49 assert(loc_advance >= 0); |
| 51 size_t i = start_index; |
50 size_t i = start_index; |
| 52 void const *cur = start; |
51 const void *cur = start; |
| 53 while (i != index && cur != NULL) { |
52 while (i != index && cur != NULL) { |
| 54 cur = ll_advance(cur); |
53 cur = ll_advance(cur); |
| 55 i < index ? i++ : i--; |
54 i < index ? i++ : i--; |
| 56 } |
55 } |
| 57 return (void *) cur; |
56 return (void *) cur; |
| 58 } |
57 } |
| 59 |
58 |
| 60 ssize_t cx_linked_list_find( |
59 ssize_t cx_linked_list_find( |
| 61 void const *start, |
60 const void *start, |
| 62 ptrdiff_t loc_advance, |
61 ptrdiff_t loc_advance, |
| 63 ptrdiff_t loc_data, |
62 ptrdiff_t loc_data, |
| 64 cx_compare_func cmp_func, |
63 cx_compare_func cmp_func, |
| 65 void const *elem |
64 const void *elem |
| 66 ) { |
65 ) { |
| 67 void *dummy; |
66 void *dummy; |
| 68 return cx_linked_list_find_node( |
67 return cx_linked_list_find_node( |
| 69 &dummy, start, |
68 &dummy, start, |
| 70 loc_advance, loc_data, |
69 loc_advance, loc_data, |
| 72 ); |
71 ); |
| 73 } |
72 } |
| 74 |
73 |
| 75 ssize_t cx_linked_list_find_node( |
74 ssize_t cx_linked_list_find_node( |
| 76 void **result, |
75 void **result, |
| 77 void const *start, |
76 const void *start, |
| 78 ptrdiff_t loc_advance, |
77 ptrdiff_t loc_advance, |
| 79 ptrdiff_t loc_data, |
78 ptrdiff_t loc_data, |
| 80 cx_compare_func cmp_func, |
79 cx_compare_func cmp_func, |
| 81 void const *elem |
80 const void *elem |
| 82 ) { |
81 ) { |
| 83 assert(result != NULL); |
82 assert(result != NULL); |
| 84 assert(start != NULL); |
83 assert(start != NULL); |
| 85 assert(loc_advance >= 0); |
84 assert(loc_advance >= 0); |
| 86 assert(loc_data >= 0); |
85 assert(loc_data >= 0); |
| 87 assert(cmp_func); |
86 assert(cmp_func); |
| 88 |
87 |
| 89 void const *node = start; |
88 const void *node = start; |
| 90 ssize_t index = 0; |
89 ssize_t index = 0; |
| 91 do { |
90 do { |
| 92 void *current = ll_data(node); |
91 void *current = ll_data(node); |
| 93 if (cmp_func(current, elem) == 0) { |
92 if (cmp_func(current, elem) == 0) { |
| 94 *result = (void*) node; |
93 *result = (void *) node; |
| 95 return index; |
94 return index; |
| 96 } |
95 } |
| 97 node = ll_advance(node); |
96 node = ll_advance(node); |
| 98 index++; |
97 index++; |
| 99 } while (node != NULL); |
98 } while (node != NULL); |
| 100 *result = NULL; |
99 *result = NULL; |
| 101 return -1; |
100 return -1; |
| 102 } |
101 } |
| 103 |
102 |
| 104 void *cx_linked_list_first( |
103 void *cx_linked_list_first( |
| 105 void const *node, |
104 const void *node, |
| 106 ptrdiff_t loc_prev |
105 ptrdiff_t loc_prev |
| 107 ) { |
106 ) { |
| 108 return cx_linked_list_last(node, loc_prev); |
107 return cx_linked_list_last(node, loc_prev); |
| 109 } |
108 } |
| 110 |
109 |
| 111 void *cx_linked_list_last( |
110 void *cx_linked_list_last( |
| 112 void const *node, |
111 const void *node, |
| 113 ptrdiff_t loc_next |
112 ptrdiff_t loc_next |
| 114 ) { |
113 ) { |
| 115 assert(node != NULL); |
114 assert(node != NULL); |
| 116 assert(loc_next >= 0); |
115 assert(loc_next >= 0); |
| 117 |
116 |
| 118 void const *cur = node; |
117 const void *cur = node; |
| 119 void const *last; |
118 const void *last; |
| 120 do { |
119 do { |
| 121 last = cur; |
120 last = cur; |
| 122 } while ((cur = ll_next(cur)) != NULL); |
121 } while ((cur = ll_next(cur)) != NULL); |
| 123 |
122 |
| 124 return (void *) last; |
123 return (void *) last; |
| 125 } |
124 } |
| 126 |
125 |
| 127 void *cx_linked_list_prev( |
126 void *cx_linked_list_prev( |
| 128 void const *begin, |
127 const void *begin, |
| 129 ptrdiff_t loc_next, |
128 ptrdiff_t loc_next, |
| 130 void const *node |
129 const void *node |
| 131 ) { |
130 ) { |
| 132 assert(begin != NULL); |
131 assert(begin != NULL); |
| 133 assert(node != NULL); |
132 assert(node != NULL); |
| 134 assert(loc_next >= 0); |
133 assert(loc_next >= 0); |
| 135 if (begin == node) return NULL; |
134 if (begin == node) return NULL; |
| 136 void const *cur = begin; |
135 const void *cur = begin; |
| 137 void const *next; |
136 const void *next; |
| 138 while (1) { |
137 while (1) { |
| 139 next = ll_next(cur); |
138 next = ll_next(cur); |
| 140 if (next == node) return (void *) cur; |
139 if (next == node) return (void *) cur; |
| 141 cur = next; |
140 cur = next; |
| 142 } |
141 } |
| 245 } else { |
244 } else { |
| 246 cx_linked_list_link(insert_end, successor, loc_prev, loc_next); |
245 cx_linked_list_link(insert_end, successor, loc_prev, loc_next); |
| 247 } |
246 } |
| 248 } |
247 } |
| 249 |
248 |
| 250 void cx_linked_list_remove( |
249 void cx_linked_list_insert_sorted( |
| 251 void **begin, |
250 void **begin, |
| 252 void **end, |
251 void **end, |
| 253 ptrdiff_t loc_prev, |
252 ptrdiff_t loc_prev, |
| 254 ptrdiff_t loc_next, |
253 ptrdiff_t loc_next, |
| 255 void *node |
254 void *new_node, |
| |
255 cx_compare_func cmp_func |
| |
256 ) { |
| |
257 assert(ll_next(new_node) == NULL); |
| |
258 cx_linked_list_insert_sorted_chain( |
| |
259 begin, end, loc_prev, loc_next, new_node, cmp_func); |
| |
260 } |
| |
261 |
| |
262 void cx_linked_list_insert_sorted_chain( |
| |
263 void **begin, |
| |
264 void **end, |
| |
265 ptrdiff_t loc_prev, |
| |
266 ptrdiff_t loc_next, |
| |
267 void *insert_begin, |
| |
268 cx_compare_func cmp_func |
| |
269 ) { |
| |
270 assert(begin != NULL); |
| |
271 assert(loc_next >= 0); |
| |
272 assert(insert_begin != NULL); |
| |
273 |
| |
274 // track currently observed nodes |
| |
275 void *dest_prev = NULL; |
| |
276 void *dest = *begin; |
| |
277 void *src = insert_begin; |
| |
278 |
| |
279 // special case: list is empty |
| |
280 if (dest == NULL) { |
| |
281 *begin = src; |
| |
282 if (end != NULL) { |
| |
283 *end = cx_linked_list_last(src, loc_next); |
| |
284 } |
| |
285 return; |
| |
286 } |
| |
287 |
| |
288 // search the list for insertion points |
| |
289 while (dest != NULL && src != NULL) { |
| |
290 // compare current list node with source node |
| |
291 // if less or equal, skip |
| |
292 if (cmp_func(dest, src) <= 0) { |
| |
293 dest_prev = dest; |
| |
294 dest = ll_next(dest); |
| |
295 continue; |
| |
296 } |
| |
297 |
| |
298 // determine chain of elements that can be inserted |
| |
299 void *end_of_chain = src; |
| |
300 void *next_in_chain = ll_next(src); |
| |
301 while (next_in_chain != NULL) { |
| |
302 // once we become larger than the list elem, break |
| |
303 if (cmp_func(dest, next_in_chain) <= 0) { |
| |
304 break; |
| |
305 } |
| |
306 // otherwise, we can insert one more |
| |
307 end_of_chain = next_in_chain; |
| |
308 next_in_chain = ll_next(next_in_chain); |
| |
309 } |
| |
310 |
| |
311 // insert the elements |
| |
312 if (dest_prev == NULL) { |
| |
313 // new begin |
| |
314 *begin = src; |
| |
315 } else { |
| |
316 cx_linked_list_link(dest_prev, src, loc_prev, loc_next); |
| |
317 } |
| |
318 cx_linked_list_link(end_of_chain, dest, loc_prev, loc_next); |
| |
319 |
| |
320 // continue with next |
| |
321 src = next_in_chain; |
| |
322 dest_prev = dest; |
| |
323 dest = ll_next(dest); |
| |
324 } |
| |
325 |
| |
326 // insert remaining items |
| |
327 if (src != NULL) { |
| |
328 cx_linked_list_link(dest_prev, src, loc_prev, loc_next); |
| |
329 } |
| |
330 |
| |
331 // determine new end of list, if requested |
| |
332 if (end != NULL) { |
| |
333 *end = cx_linked_list_last( |
| |
334 dest != NULL ? dest : dest_prev, loc_next); |
| |
335 } |
| |
336 } |
| |
337 |
| |
338 size_t cx_linked_list_remove_chain( |
| |
339 void **begin, |
| |
340 void **end, |
| |
341 ptrdiff_t loc_prev, |
| |
342 ptrdiff_t loc_next, |
| |
343 void *node, |
| |
344 size_t num |
| 256 ) { |
345 ) { |
| 257 assert(node != NULL); |
346 assert(node != NULL); |
| 258 assert(loc_next >= 0); |
347 assert(loc_next >= 0); |
| 259 assert(loc_prev >= 0 || begin != NULL); |
348 assert(loc_prev >= 0 || begin != NULL); |
| 260 |
349 |
| |
350 // easy exit |
| |
351 if (num == 0) return 0; |
| |
352 |
| 261 // find adjacent nodes |
353 // find adjacent nodes |
| 262 void *next = ll_next(node); |
|
| 263 void *prev; |
354 void *prev; |
| 264 if (loc_prev >= 0) { |
355 if (loc_prev >= 0) { |
| 265 prev = ll_prev(node); |
356 prev = ll_prev(node); |
| 266 } else { |
357 } else { |
| 267 prev = cx_linked_list_prev(*begin, loc_next, node); |
358 prev = cx_linked_list_prev(*begin, loc_next, node); |
| |
359 } |
| |
360 |
| |
361 void *next = ll_next(node); |
| |
362 size_t removed = 1; |
| |
363 for (; removed < num && next != NULL ; removed++) { |
| |
364 next = ll_next(next); |
| 268 } |
365 } |
| 269 |
366 |
| 270 // update next pointer of prev node, or set begin |
367 // update next pointer of prev node, or set begin |
| 271 if (prev == NULL) { |
368 if (prev == NULL) { |
| 272 if (begin != NULL) { |
369 if (begin != NULL) { |
| 423 if (end) *end = sorted_end; |
522 if (end) *end = sorted_end; |
| 424 } |
523 } |
| 425 } |
524 } |
| 426 |
525 |
| 427 int cx_linked_list_compare( |
526 int cx_linked_list_compare( |
| 428 void const *begin_left, |
527 const void *begin_left, |
| 429 void const *begin_right, |
528 const void *begin_right, |
| 430 ptrdiff_t loc_advance, |
529 ptrdiff_t loc_advance, |
| 431 ptrdiff_t loc_data, |
530 ptrdiff_t loc_data, |
| 432 cx_compare_func cmp_func |
531 cx_compare_func cmp_func |
| 433 ) { |
532 ) { |
| 434 void const *left = begin_left, *right = begin_right; |
533 const void *left = begin_left, *right = begin_right; |
| 435 |
534 |
| 436 while (left != NULL && right != NULL) { |
535 while (left != NULL && right != NULL) { |
| 437 void const *left_data = ll_data(left); |
536 const void *left_data = ll_data(left); |
| 438 void const *right_data = ll_data(right); |
537 const void *right_data = ll_data(right); |
| 439 int result = cmp_func(left_data, right_data); |
538 int result = cmp_func(left_data, right_data); |
| 440 if (result != 0) return result; |
539 if (result != 0) return result; |
| 441 left = ll_advance(left); |
540 left = ll_advance(left); |
| 442 right = ll_advance(right); |
541 right = ll_advance(right); |
| 443 } |
542 } |
| 541 } |
644 } |
| 542 |
645 |
| 543 static size_t cx_ll_insert_array( |
646 static size_t cx_ll_insert_array( |
| 544 struct cx_list_s *list, |
647 struct cx_list_s *list, |
| 545 size_t index, |
648 size_t index, |
| 546 void const *array, |
649 const void *array, |
| 547 size_t n |
650 size_t n |
| 548 ) { |
651 ) { |
| 549 // out-of bounds and corner case check |
652 // out-of bounds and corner case check |
| 550 if (index > list->collection.size || n == 0) return 0; |
653 if (index > list->collection.size || n == 0) return 0; |
| 551 |
654 |
| 552 // find position efficiently |
655 // find position efficiently |
| 553 cx_linked_list_node *node = index == 0 ? NULL : cx_ll_node_at((cx_linked_list *) list, index - 1); |
656 cx_linked_list_node *node = index == 0 ? NULL : cx_ll_node_at((cx_linked_list *) list, index - 1); |
| 554 |
657 |
| 555 // perform first insert |
658 // perform first insert |
| 556 if (0 != cx_ll_insert_at(list, node, array)) { |
659 if (0 != cx_ll_insert_at(list, node, array)) return 1; |
| 557 return 1; |
|
| 558 } |
|
| 559 |
660 |
| 560 // is there more? |
661 // is there more? |
| 561 if (n == 1) return 1; |
662 if (n == 1) return 1; |
| 562 |
663 |
| 563 // we now know exactly where we are |
664 // we now know exactly where we are |
| 564 node = node == NULL ? ((cx_linked_list *) list)->begin : node->next; |
665 node = node == NULL ? ((cx_linked_list *) list)->begin : node->next; |
| 565 |
666 |
| 566 // we can add the remaining nodes and immedately advance to the inserted node |
667 // we can add the remaining nodes and immediately advance to the inserted node |
| 567 char const *source = array; |
668 const char *source = array; |
| 568 for (size_t i = 1; i < n; i++) { |
669 for (size_t i = 1; i < n; i++) { |
| 569 source += list->collection.elem_size; |
670 source += list->collection.elem_size; |
| 570 if (0 != cx_ll_insert_at(list, node, source)) { |
671 if (0 != cx_ll_insert_at(list, node, source)) return i; |
| 571 return i; |
|
| 572 } |
|
| 573 node = node->next; |
672 node = node->next; |
| 574 } |
673 } |
| 575 return n; |
674 return n; |
| 576 } |
675 } |
| 577 |
676 |
| 578 static int cx_ll_insert_element( |
677 static int cx_ll_insert_element( |
| 579 struct cx_list_s *list, |
678 struct cx_list_s *list, |
| 580 size_t index, |
679 size_t index, |
| 581 void const *element |
680 const void *element |
| 582 ) { |
681 ) { |
| 583 return 1 != cx_ll_insert_array(list, index, element, 1); |
682 return 1 != cx_ll_insert_array(list, index, element, 1); |
| 584 } |
683 } |
| 585 |
684 |
| 586 static int cx_ll_remove( |
685 static _Thread_local cx_compare_func cx_ll_insert_sorted_cmp_func; |
| |
686 |
| |
687 static int cx_ll_insert_sorted_cmp_helper(const void *l, const void *r) { |
| |
688 const cx_linked_list_node *left = l; |
| |
689 const cx_linked_list_node *right = r; |
| |
690 return cx_ll_insert_sorted_cmp_func(left->payload, right->payload); |
| |
691 } |
| |
692 |
| |
693 static size_t cx_ll_insert_sorted( |
| 587 struct cx_list_s *list, |
694 struct cx_list_s *list, |
| 588 size_t index |
695 const void *array, |
| |
696 size_t n |
| |
697 ) { |
| |
698 // special case |
| |
699 if (n == 0) return 0; |
| |
700 |
| |
701 // create a new chain of nodes |
| |
702 cx_linked_list_node *chain = cx_ll_malloc_node(list); |
| |
703 if (chain == NULL) return 0; |
| |
704 |
| |
705 memcpy(chain->payload, array, list->collection.elem_size); |
| |
706 chain->prev = NULL; |
| |
707 chain->next = NULL; |
| |
708 |
| |
709 // add all elements from the array to that chain |
| |
710 cx_linked_list_node *prev = chain; |
| |
711 const char *src = array; |
| |
712 size_t inserted = 1; |
| |
713 for (; inserted < n; inserted++) { |
| |
714 cx_linked_list_node *next = cx_ll_malloc_node(list); |
| |
715 if (next == NULL) break; |
| |
716 src += list->collection.elem_size; |
| |
717 memcpy(next->payload, src, list->collection.elem_size); |
| |
718 prev->next = next; |
| |
719 next->prev = prev; |
| |
720 prev = next; |
| |
721 } |
| |
722 prev->next = NULL; |
| |
723 |
| |
724 // invoke the low level function |
| |
725 cx_linked_list *ll = (cx_linked_list *) list; |
| |
726 cx_ll_insert_sorted_cmp_func = list->collection.cmpfunc; |
| |
727 cx_linked_list_insert_sorted_chain( |
| |
728 (void **) &ll->begin, |
| |
729 (void **) &ll->end, |
| |
730 CX_LL_LOC_PREV, |
| |
731 CX_LL_LOC_NEXT, |
| |
732 chain, |
| |
733 cx_ll_insert_sorted_cmp_helper |
| |
734 ); |
| |
735 |
| |
736 // adjust the list metadata |
| |
737 list->collection.size += inserted; |
| |
738 |
| |
739 return inserted; |
| |
740 } |
| |
741 |
| |
742 static size_t cx_ll_remove( |
| |
743 struct cx_list_s *list, |
| |
744 size_t index, |
| |
745 size_t num, |
| |
746 void *targetbuf |
| 589 ) { |
747 ) { |
| 590 cx_linked_list *ll = (cx_linked_list *) list; |
748 cx_linked_list *ll = (cx_linked_list *) list; |
| 591 cx_linked_list_node *node = cx_ll_node_at(ll, index); |
749 cx_linked_list_node *node = cx_ll_node_at(ll, index); |
| 592 |
750 |
| 593 // out-of-bounds check |
751 // out-of-bounds check |
| 594 if (node == NULL) return 1; |
752 if (node == NULL) return 0; |
| 595 |
|
| 596 // element destruction |
|
| 597 cx_invoke_destructor(list, node->payload); |
|
| 598 |
753 |
| 599 // remove |
754 // remove |
| 600 cx_linked_list_remove((void **) &ll->begin, (void **) &ll->end, |
755 size_t removed = cx_linked_list_remove_chain( |
| 601 CX_LL_LOC_PREV, CX_LL_LOC_NEXT, node); |
756 (void **) &ll->begin, |
| |
757 (void **) &ll->end, |
| |
758 CX_LL_LOC_PREV, |
| |
759 CX_LL_LOC_NEXT, |
| |
760 node, |
| |
761 num |
| |
762 ); |
| 602 |
763 |
| 603 // adjust size |
764 // adjust size |
| 604 list->collection.size--; |
765 list->collection.size -= removed; |
| 605 |
766 |
| 606 // free and return |
767 // copy or destroy the removed chain |
| 607 cxFree(list->collection.allocator, node); |
768 if (targetbuf == NULL) { |
| 608 |
769 cx_linked_list_node *n = node; |
| 609 return 0; |
770 for (size_t i = 0; i < removed; i++) { |
| |
771 // element destruction |
| |
772 cx_invoke_destructor(list, n->payload); |
| |
773 |
| |
774 // free the node and advance |
| |
775 void *next = n->next; |
| |
776 cxFree(list->collection.allocator, n); |
| |
777 n = next; |
| |
778 } |
| |
779 } else { |
| |
780 char *dest = targetbuf; |
| |
781 cx_linked_list_node *n = node; |
| |
782 for (size_t i = 0; i < removed; i++) { |
| |
783 // copy payload |
| |
784 memcpy(dest, n->payload, list->collection.elem_size); |
| |
785 |
| |
786 // advance target buffer |
| |
787 dest += list->collection.elem_size; |
| |
788 |
| |
789 // free the node and advance |
| |
790 void *next = n->next; |
| |
791 cxFree(list->collection.allocator, n); |
| |
792 n = next; |
| |
793 } |
| |
794 } |
| |
795 |
| |
796 return removed; |
| 610 } |
797 } |
| 611 |
798 |
| 612 static void cx_ll_clear(struct cx_list_s *list) { |
799 static void cx_ll_clear(struct cx_list_s *list) { |
| 613 if (list->collection.size == 0) return; |
800 if (list->collection.size == 0) return; |
| 614 |
801 |
| 798 cx_linked_list *ll = (cx_linked_list *) list; |
985 cx_linked_list *ll = (cx_linked_list *) list; |
| 799 cx_linked_list_reverse((void **) &ll->begin, (void **) &ll->end, CX_LL_LOC_PREV, CX_LL_LOC_NEXT); |
986 cx_linked_list_reverse((void **) &ll->begin, (void **) &ll->end, CX_LL_LOC_PREV, CX_LL_LOC_NEXT); |
| 800 } |
987 } |
| 801 |
988 |
| 802 static int cx_ll_compare( |
989 static int cx_ll_compare( |
| 803 struct cx_list_s const *list, |
990 const struct cx_list_s *list, |
| 804 struct cx_list_s const *other |
991 const struct cx_list_s *other |
| 805 ) { |
992 ) { |
| 806 cx_linked_list *left = (cx_linked_list *) list; |
993 cx_linked_list *left = (cx_linked_list *) list; |
| 807 cx_linked_list *right = (cx_linked_list *) other; |
994 cx_linked_list *right = (cx_linked_list *) other; |
| 808 return cx_linked_list_compare(left->begin, right->begin, |
995 return cx_linked_list_compare(left->begin, right->begin, |
| 809 CX_LL_LOC_NEXT, CX_LL_LOC_DATA, |
996 CX_LL_LOC_NEXT, CX_LL_LOC_DATA, |
| 810 list->collection.cmpfunc); |
997 list->collection.cmpfunc); |
| 811 } |
998 } |
| 812 |
999 |
| 813 static bool cx_ll_iter_valid(void const *it) { |
1000 static bool cx_ll_iter_valid(const void *it) { |
| 814 struct cx_iterator_s const *iter = it; |
1001 const struct cx_iterator_s *iter = it; |
| 815 return iter->elem_handle != NULL; |
1002 return iter->elem_handle != NULL; |
| 816 } |
1003 } |
| 817 |
1004 |
| 818 static void cx_ll_iter_next(void *it) { |
1005 static void cx_ll_iter_next(void *it) { |
| 819 struct cx_iterator_s *iter = it; |
1006 struct cx_iterator_s *iter = it; |
| 854 cx_linked_list_node *node = iter->elem_handle; |
1041 cx_linked_list_node *node = iter->elem_handle; |
| 855 iter->elem_handle = node->prev; |
1042 iter->elem_handle = node->prev; |
| 856 } |
1043 } |
| 857 } |
1044 } |
| 858 |
1045 |
| 859 static void *cx_ll_iter_current(void const *it) { |
1046 static void *cx_ll_iter_current(const void *it) { |
| 860 struct cx_iterator_s const *iter = it; |
1047 const struct cx_iterator_s *iter = it; |
| 861 cx_linked_list_node *node = iter->elem_handle; |
1048 cx_linked_list_node *node = iter->elem_handle; |
| 862 return node->payload; |
1049 return node->payload; |
| 863 } |
1050 } |
| 864 |
1051 |
| 865 static CxIterator cx_ll_iterator( |
1052 static CxIterator cx_ll_iterator( |
| 866 struct cx_list_s const *list, |
1053 const struct cx_list_s *list, |
| 867 size_t index, |
1054 size_t index, |
| 868 bool backwards |
1055 bool backwards |
| 869 ) { |
1056 ) { |
| 870 CxIterator iter; |
1057 CxIterator iter; |
| 871 iter.index = index; |
1058 iter.index = index; |
| 872 iter.src_handle.c = list; |
1059 iter.src_handle.c = list; |
| 873 iter.elem_handle = cx_ll_node_at((cx_linked_list const *) list, index); |
1060 iter.elem_handle = cx_ll_node_at((const cx_linked_list *) list, index); |
| 874 iter.elem_size = list->collection.elem_size; |
1061 iter.elem_size = list->collection.elem_size; |
| 875 iter.elem_count = list->collection.size; |
1062 iter.elem_count = list->collection.size; |
| 876 iter.base.valid = cx_ll_iter_valid; |
1063 iter.base.valid = cx_ll_iter_valid; |
| 877 iter.base.current = cx_ll_iter_current; |
1064 iter.base.current = cx_ll_iter_current; |
| 878 iter.base.next = backwards ? cx_ll_iter_prev : cx_ll_iter_next; |
1065 iter.base.next = backwards ? cx_ll_iter_prev : cx_ll_iter_next; |