sort.inl 1.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748
  1. /* Sort function. */
  2. /* from https://github.com/bel2125/sort_r */
  3. static void
  4. mg_sort(void *data,
  5. size_t elemcount,
  6. size_t elemsize,
  7. int (*compfunc)(const void *data1, const void *data2, void *userarg),
  8. void *userarg)
  9. {
  10. /* We cannot use qsort_r here. For a detailed reason, see
  11. * https://github.com/civetweb/civetweb/issues/1048#issuecomment-1047093014
  12. * https://stackoverflow.com/questions/39560773/different-declarations-of-qsort-r-on-mac-and-linux
  13. */
  14. /* We use ShellSort here with this gap sequence: https://oeis.org/A102549 */
  15. int A102549[9] = {1, 4, 10, 23, 57, 132, 301, 701, 1750};
  16. int Aidx, gap, i, j, k;
  17. void *tmp = alloca(elemsize);
  18. for (Aidx = 8; Aidx >= 0; Aidx--) {
  19. gap = A102549[Aidx];
  20. if (gap > ((int)elemcount / 2)) {
  21. continue;
  22. }
  23. for (i = 0; i < gap; i++) {
  24. for (j = i; j < (int)elemcount; j += gap) {
  25. memcpy(tmp, (void *)((ptrdiff_t)data + elemsize * j), elemsize);
  26. for (k = j; k >= gap; k -= gap) {
  27. void *cmp =
  28. (void *)((ptrdiff_t)data + elemsize * (k - gap));
  29. int cmpres = compfunc(cmp, tmp, userarg);
  30. if (cmpres > 0) {
  31. memcpy((void *)((ptrdiff_t)data + elemsize * k),
  32. cmp,
  33. elemsize);
  34. } else {
  35. break;
  36. }
  37. }
  38. memcpy((void *)((ptrdiff_t)data + elemsize * k), tmp, elemsize);
  39. }
  40. }
  41. }
  42. }
  43. /* end if sort.inl */