Sun, 01 Sep 2024 16:14:34 +0200
optimize default insert_sorted implementation
resolves #418
src/list.c | file | annotate | diff | comparison | revisions |
--- a/src/list.c Sun Sep 01 14:48:43 2024 +0200 +++ b/src/list.c Sun Sep 01 16:14:34 2024 +0200 @@ -308,14 +308,62 @@ void const *sorted_data, size_t n ) { + // corner case + if (n == 0) return 0; + size_t elem_size = list->collection.elem_size; cx_compare_func cmp = list->collection.cmpfunc; char const *src = sorted_data; - size_t r = cx_list_default_insert_array(list, 0, src, n); - cx_list_default_sort(list); + // track indices and number of inserted items + size_t di = 0, si = 0, inserted = 0; + + // search the list for insertion points + for (; di < list->collection.size; di++) { + void const *list_elm = invoke_list_func(at, list, di); + + // compare current list element with first source element + // if less or equal, skip + if (cmp(list_elm, src) <= 0) { + continue; + } - return r; + // determine number of consecutive elements that can be inserted + size_t ins = 1; + char const *next = src; + while (++si < n) { + next += elem_size; + // once we become larger than the list elem, break + if (cmp(list_elm, next) <= 0) { + break; + } + // otherwise, we can insert one more + ins++; + } + + // insert the elements at location si + if (ins == 1) { + if (0 != invoke_list_func(insert_element, + list, di, src)) + return inserted; + } else { + size_t r = invoke_list_func(insert_array, list, di, src, ins); + if (r < ins) return inserted + r; + } + inserted += ins; + di += ins; + + // everything inserted? + if (inserted == n) return inserted; + src = next; + } + + // insert remaining items + if (si < n) { + inserted += invoke_list_func(insert_array, list, di, src, n - si); + } + + return inserted; } void cx_list_default_sort(struct cx_list_s *list) {