325 size_t elem_size = list->collection.elem_size; |
325 size_t elem_size = list->collection.elem_size; |
326 cx_compare_func cmp = list->collection.cmpfunc; |
326 cx_compare_func cmp = list->collection.cmpfunc; |
327 const char *src = sorted_data; |
327 const char *src = sorted_data; |
328 |
328 |
329 // track indices and number of inserted items |
329 // track indices and number of inserted items |
330 size_t di = 0, si = 0, inserted = 0; |
330 size_t di = 0, si = 0, processed = 0; |
331 |
331 |
332 // search the list for insertion points |
332 // search the list for insertion points |
333 for (; di < list->collection.size; di++) { |
333 while (di < list->collection.size) { |
334 const void *list_elm = invoke_list_func(at, list, di); |
334 const void *list_elm = invoke_list_func(at, list, di); |
335 |
335 |
336 // compare current list element with first source element |
336 // compare the current list element with the first source element |
337 // if less or equal, skip |
337 // if less, skip the list elements |
|
338 // if equal, skip the list elements and optionally the source elements |
338 { |
339 { |
339 int d = cmp(list_elm, src); |
340 int d = cmp(list_elm, src); |
340 if (d <= 0) { |
341 if (d <= 0) { |
341 if (!allow_duplicates && d == 0) { |
342 if (!allow_duplicates && d == 0) { |
342 src += elem_size; |
343 src += elem_size; |
343 si++; |
344 si++; |
344 inserted++; // we also count duplicates for the return value |
345 processed++; // we also count duplicates for the return value |
345 while (si < n && cmp(list_elm, src) == 0) { |
346 while (si < n && cmp(list_elm, src) == 0) { |
346 src += elem_size; |
347 src += elem_size; |
347 si++; |
348 si++; |
348 inserted++; |
349 processed++; |
349 } |
350 } |
350 if (inserted == n) { |
351 if (processed == n) { |
351 return inserted; |
352 return processed; |
352 } |
353 } |
353 } |
354 } |
|
355 di++; |
354 continue; |
356 continue; |
355 } |
357 } |
356 } |
358 } |
357 |
359 |
358 // determine number of consecutive elements that can be inserted |
360 // determine the number of consecutive elements that can be inserted |
359 size_t ins = 1; |
361 size_t ins = 1, skip = 0; |
360 const char *next = src; |
362 const char *next = src; |
361 while (++si < n) { |
363 while (++si < n) { |
|
364 if (!allow_duplicates) { |
|
365 // skip duplicates within the source |
|
366 if (cmp(next, next + elem_size) == 0) { |
|
367 next += elem_size; |
|
368 skip++; |
|
369 continue; |
|
370 } else { |
|
371 if (skip > 0) { |
|
372 // if we had to skip something, we must wait for the next run |
|
373 next += elem_size; |
|
374 break; |
|
375 } |
|
376 } |
|
377 } |
362 next += elem_size; |
378 next += elem_size; |
363 // once we become larger than the list elem, break |
379 // once we become larger than the list elem, break |
364 if (cmp(list_elm, next) <= 0) { |
380 if (cmp(list_elm, next) <= 0) { |
365 break; |
381 break; |
366 } |
382 } |
369 } |
385 } |
370 |
386 |
371 // insert the elements at location si |
387 // insert the elements at location si |
372 if (ins == 1) { |
388 if (ins == 1) { |
373 if (NULL == invoke_list_func(insert_element, list, di, src)) { |
389 if (NULL == invoke_list_func(insert_element, list, di, src)) { |
374 return inserted; // LCOV_EXCL_LINE |
390 return processed; // LCOV_EXCL_LINE |
375 } |
391 } |
376 } else { |
392 } else { |
377 size_t r = invoke_list_func(insert_array, list, di, src, ins); |
393 size_t r = invoke_list_func(insert_array, list, di, src, ins); |
378 if (r < ins) { |
394 if (r < ins) { |
379 return inserted + r; // LCOV_EXCL_LINE |
395 return processed + r; // LCOV_EXCL_LINE |
380 } |
396 } |
381 } |
397 } |
382 inserted += ins; |
398 processed += ins + skip; |
383 di += ins; |
399 di += ins; |
384 |
400 |
385 // everything inserted? |
401 // everything inserted? |
386 if (inserted == n) { |
402 if (processed == n) { |
387 return inserted; |
403 return processed; |
388 } |
404 } |
389 src = next; |
405 src = next; |
390 } |
406 } |
391 |
407 |
392 // insert remaining items |
408 // insert remaining items |
393 if (si < n) { |
409 if (si < n) { |
394 inserted += invoke_list_func(insert_array, list, di, src, n - si); |
410 if (allow_duplicates) { |
395 } |
411 processed += invoke_list_func(insert_array, list, di, src, n - si); |
396 |
412 } else { |
397 return inserted; |
413 const void *last = di == 0 ? NULL : invoke_list_func(at, list, di - 1); |
|
414 for (; si < n; si++) { |
|
415 // skip duplicates within the source |
|
416 if (last == NULL || cmp(last, src) != 0) { |
|
417 if (NULL == invoke_list_func(insert_element, list, di, src)) { |
|
418 return processed; // LCOV_EXCL_LINE |
|
419 } |
|
420 last = src; |
|
421 di++; |
|
422 } |
|
423 processed++; |
|
424 src += elem_size; |
|
425 } |
|
426 } |
|
427 } |
|
428 |
|
429 return processed; |
398 } |
430 } |
399 |
431 |
400 size_t cx_list_default_insert_sorted( |
432 size_t cx_list_default_insert_sorted( |
401 struct cx_list_s *list, |
433 struct cx_list_s *list, |
402 const void *sorted_data, |
434 const void *sorted_data, |