809 } |
809 } |
810 ll->begin = ll->end = NULL; |
810 ll->begin = ll->end = NULL; |
811 list->collection.size = 0; |
811 list->collection.size = 0; |
812 } |
812 } |
813 |
813 |
814 #ifndef CX_LINKED_LIST_SWAP_SBO_SIZE |
|
815 #define CX_LINKED_LIST_SWAP_SBO_SIZE 128 |
|
816 #endif |
|
817 const unsigned cx_linked_list_swap_sbo_size = CX_LINKED_LIST_SWAP_SBO_SIZE; |
|
818 |
|
819 static int cx_ll_swap( |
814 static int cx_ll_swap( |
820 struct cx_list_s *list, |
815 struct cx_list_s *list, |
821 size_t i, |
816 size_t i, |
822 size_t j |
817 size_t j |
823 ) { |
818 ) { |
892 nleft = cx_ll_node_at(ll, other); |
887 nleft = cx_ll_node_at(ll, other); |
893 } |
888 } |
894 } |
889 } |
895 } |
890 } |
896 |
891 |
897 if (list->collection.elem_size > CX_LINKED_LIST_SWAP_SBO_SIZE) { |
892 cx_linked_list_node *prev = nleft->prev; |
898 cx_linked_list_node *prev = nleft->prev; |
893 cx_linked_list_node *next = nright->next; |
899 cx_linked_list_node *next = nright->next; |
894 cx_linked_list_node *midstart = nleft->next; |
900 cx_linked_list_node *midstart = nleft->next; |
895 cx_linked_list_node *midend = nright->prev; |
901 cx_linked_list_node *midend = nright->prev; |
896 |
902 |
897 if (prev == NULL) { |
903 if (prev == NULL) { |
898 ll->begin = nright; |
904 ll->begin = nright; |
899 } else { |
905 } else { |
900 prev->next = nright; |
906 prev->next = nright; |
901 } |
907 } |
902 nright->prev = prev; |
908 nright->prev = prev; |
903 if (midstart == nright) { |
909 if (midstart == nright) { |
904 // special case: both nodes are adjacent |
910 // special case: both nodes are adjacent |
905 nright->next = nleft; |
911 nright->next = nleft; |
906 nleft->prev = nright; |
912 nleft->prev = nright; |
907 } else { |
913 } else { |
908 // likely case: a chain is between the two nodes |
914 // likely case: a chain is between the two nodes |
909 nright->next = midstart; |
915 nright->next = midstart; |
910 midstart->prev = nright; |
916 midstart->prev = nright; |
911 midend->next = nleft; |
917 midend->next = nleft; |
912 nleft->prev = midend; |
918 nleft->prev = midend; |
913 } |
919 } |
914 nleft->next = next; |
920 nleft->next = next; |
915 if (next == NULL) { |
921 if (next == NULL) { |
916 ll->end = nleft; |
922 ll->end = nleft; |
917 } else { |
923 } else { |
918 next->prev = nleft; |
924 next->prev = nleft; |
|
925 } |
|
926 } else { |
|
927 // swap payloads to avoid relinking |
|
928 char buf[CX_LINKED_LIST_SWAP_SBO_SIZE]; |
|
929 memcpy(buf, nleft->payload, list->collection.elem_size); |
|
930 memcpy(nleft->payload, nright->payload, list->collection.elem_size); |
|
931 memcpy(nright->payload, buf, list->collection.elem_size); |
|
932 } |
919 } |
933 |
920 |
934 return 0; |
921 return 0; |
935 } |
922 } |
936 |
923 |