1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-23 17:34:34 +03:00
samba-mirror/lib/util/stable_sort.h
Douglas Bagnall 4e18e92399 util: add stable sort functions
Sometimes (e.g. in lzxpress Huffman encoding, and in some of our
tests: c.f. https://lists.samba.org/archive/samba-technical/2018-March/126010.html)
we want a stable sort algorithm (meaning one that retains the previous
order of items that compare equal).

The GNU libc qsort() is *usually* stable, in that it first tries to
use a mergesort but reverts to quicksort if the necessary allocations
fail. That has led Samba developers to unthinkingly assume qsort() is
stable which is not the case on many platforms, and might not always
be on GNU/Linuxes either.

This adds four functions. stable_sort() sorts an array, and requires
an auxiliary working array of the same size. stable_sort_talloc()
takes a talloc context so it ca create a working array and call
stable_sort(). stable_sort_r() takes an opaque context blob that gets
passed to the compare function, like qsort_r() and ldb_qsort(). And
stable_sort_talloc_r() rounds out the quadrant.

These are LGPL so that the can be used in ldb, which has problems with
unstable sort.

The tests are borrowed and extended from test_ldb_qsort.c.

When sorting non-trivial structs this is roughly as fast as GNU qsort,
but GNU qsort has optimisations for small items, using direct
assignments of rather than memcpy where the size allows the item to be
cast as some kind of int.

Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Joseph Sutton <josephsutton@catalyst.net.nz>
2022-12-01 22:56:39 +00:00

47 lines
965 B
C

#ifndef HAVE_STABLE_SORT_H
#define HAVE_STABLE_SORT_H 1
#ifdef __COMPAR_FN_T
typedef __compar_fn_t samba_compare_fn_t;
#ifdef __USE_GNU
/* glibc defines __compar_d_fn_t for qsort_r */
typedef __compar_d_fn_t samba_compare_with_context_fn_t;
#endif
#else
typedef int (*samba_compare_fn_t) (const void *, const void *);
typedef int (*samba_compare_with_context_fn_t) (const void *, const void *, void *);
#endif
bool stable_sort_r(void *array, void *aux,
size_t n,
size_t s,
samba_compare_with_context_fn_t cmpfn,
void *opaque);
bool stable_sort(void *array, void *aux,
size_t n,
size_t s,
samba_compare_fn_t cmpfn);
bool stable_sort_talloc_r(TALLOC_CTX *mem_ctx,
void *array,
size_t n,
size_t s,
samba_compare_with_context_fn_t cmpfn,
void *opaque);
bool stable_sort_talloc(TALLOC_CTX *mem_ctx,
void *array,
size_t n,
size_t s,
samba_compare_fn_t cmpfn);
#endif /* HAVE_STABLE_SORT_H */