306 size_t cx_list_default_insert_sorted( |
306 size_t cx_list_default_insert_sorted( |
307 struct cx_list_s *list, |
307 struct cx_list_s *list, |
308 void const *sorted_data, |
308 void const *sorted_data, |
309 size_t n |
309 size_t n |
310 ) { |
310 ) { |
|
311 // corner case |
|
312 if (n == 0) return 0; |
|
313 |
311 size_t elem_size = list->collection.elem_size; |
314 size_t elem_size = list->collection.elem_size; |
312 cx_compare_func cmp = list->collection.cmpfunc; |
315 cx_compare_func cmp = list->collection.cmpfunc; |
313 char const *src = sorted_data; |
316 char const *src = sorted_data; |
314 |
317 |
315 size_t r = cx_list_default_insert_array(list, 0, src, n); |
318 // track indices and number of inserted items |
316 cx_list_default_sort(list); |
319 size_t di = 0, si = 0, inserted = 0; |
317 |
320 |
318 return r; |
321 // search the list for insertion points |
|
322 for (; di < list->collection.size; di++) { |
|
323 void const *list_elm = invoke_list_func(at, list, di); |
|
324 |
|
325 // compare current list element with first source element |
|
326 // if less or equal, skip |
|
327 if (cmp(list_elm, src) <= 0) { |
|
328 continue; |
|
329 } |
|
330 |
|
331 // determine number of consecutive elements that can be inserted |
|
332 size_t ins = 1; |
|
333 char const *next = src; |
|
334 while (++si < n) { |
|
335 next += elem_size; |
|
336 // once we become larger than the list elem, break |
|
337 if (cmp(list_elm, next) <= 0) { |
|
338 break; |
|
339 } |
|
340 // otherwise, we can insert one more |
|
341 ins++; |
|
342 } |
|
343 |
|
344 // insert the elements at location si |
|
345 if (ins == 1) { |
|
346 if (0 != invoke_list_func(insert_element, |
|
347 list, di, src)) |
|
348 return inserted; |
|
349 } else { |
|
350 size_t r = invoke_list_func(insert_array, list, di, src, ins); |
|
351 if (r < ins) return inserted + r; |
|
352 } |
|
353 inserted += ins; |
|
354 di += ins; |
|
355 |
|
356 // everything inserted? |
|
357 if (inserted == n) return inserted; |
|
358 src = next; |
|
359 } |
|
360 |
|
361 // insert remaining items |
|
362 if (si < n) { |
|
363 inserted += invoke_list_func(insert_array, list, di, src, n - si); |
|
364 } |
|
365 |
|
366 return inserted; |
319 } |
367 } |
320 |
368 |
321 void cx_list_default_sort(struct cx_list_s *list) { |
369 void cx_list_default_sort(struct cx_list_s *list) { |
322 size_t elem_size = list->collection.elem_size; |
370 size_t elem_size = list->collection.elem_size; |
323 size_t list_size = list->collection.size; |
371 size_t list_size = list->collection.size; |