| /* Copyright (c) 2015 Google Inc |
| * Davide Libenzi <dlibenzi@google.com> |
| * See LICENSE for details. |
| */ |
| |
| #include <stdio.h> |
| |
| static void mem_swap(void *a, void *b, size_t size) |
| { |
| for (; size > 0; size--, a++, b++) { |
| char tmp = *(char*) a; |
| |
| *(char *) a = *(char *) b; |
| *(char *) b = tmp; |
| } |
| } |
| |
| void sort(void *base, size_t count, size_t size, |
| int (*cmp)(const void *, const void *)) |
| { |
| ssize_t n = count * size, c; |
| |
| /* Standard heapsort algorithm. First loop creates a heap, and the |
| * second one progressively pop the top of the heap, and does re-heap |
| * operations so that we maintain the heap properties. |
| */ |
| for (ssize_t i = (count / 2 - 1) * size; i >= 0; i -= size) { |
| for (ssize_t r = i; r * 2 + size < n; r = c) { |
| c = r * 2 + size; |
| if (c < n - size && cmp(base + c, base + c + size) < 0) |
| c += size; |
| if (cmp(base + r, base + c) >= 0) |
| break; |
| mem_swap(base + r, base + c, size); |
| } |
| } |
| |
| for (ssize_t i = n - size; i > 0; i -= size) { |
| mem_swap(base, base + i, size); |
| for (ssize_t r = 0; r * 2 + size < i; r = c) { |
| c = r * 2 + size; |
| if (c < i - size && cmp(base + c, base + c + size) < 0) |
| c += size; |
| if (cmp(base + r, base + c) >= 0) |
| break; |
| mem_swap(base + r, base + c, size); |
| } |
| } |
| } |