Merge commit '0feff4ba7b16501341c575e06b4c98a6e1bd2809'

pull/594/head
Behdad Esfahbod 7 years ago
commit 0f78d78aae
  1. 147
      src/hb-sort-r.hh

@ -72,35 +72,15 @@ Parameters:
void hb_sort_r(void *base, size_t nel, size_t width,
int (*compar)(const void *_a, const void *_b, void *_arg),
void *arg);
*/
#define _SORT_R_INLINE inline
#if (defined __APPLE__ || defined __MACH__ || defined __DARWIN__ || \
defined __FreeBSD__ || defined __DragonFly__)
# define _SORT_R_BSD
#elif (defined _GNU_SOURCE || defined __gnu_hurd__ || defined __GNU__ || \
defined __linux__ || defined __MINGW32__ || defined __GLIBC__)
# define _SORT_R_LINUX
#elif (defined _WIN32 || defined _WIN64 || defined __WINDOWS__)
# define _SORT_R_WINDOWS
# undef _SORT_R_INLINE
# define _SORT_R_INLINE __inline
#else
/* Using our own recursive quicksort sort_r_simple() */
#endif
#if (defined NESTED_QSORT && NESTED_QSORT == 0)
# undef NESTED_QSORT
#endif
/* swap a, b iff a>b */
/* __restrict is same as restrict but better support on old machines */
static _SORT_R_INLINE int sort_r_cmpswap(char *__restrict a, char *__restrict b, size_t w,
int (*compar)(const void *_a, const void *_b,
void *_arg),
void *arg)
static int sort_r_cmpswap(char *__restrict a, char *__restrict b, size_t w,
int (*compar)(const void *_a, const void *_b,
void *_arg),
void *arg)
{
char tmp, *end = a+w;
if(compar(a, b, arg) > 0) {
@ -110,12 +90,11 @@ static _SORT_R_INLINE int sort_r_cmpswap(char *__restrict a, char *__restrict b,
return 0;
}
/* Implement recursive quicksort ourselves */
/* Note: quicksort is not stable, equivalent values may be swapped */
static _SORT_R_INLINE void sort_r_simple(void *base, size_t nel, size_t w,
int (*compar)(const void *_a, const void *_b,
void *_arg),
void *arg)
static inline void sort_r_simple(void *base, size_t nel, size_t w,
int (*compar)(const void *_a, const void *_b,
void *_arg),
void *arg)
{
char *b = (char *)base, *end = b + nel*w;
if(nel < 7) {
@ -172,109 +151,11 @@ static _SORT_R_INLINE void sort_r_simple(void *base, size_t nel, size_t w,
}
}
#if defined NESTED_QSORT
static _SORT_R_INLINE void hb_sort_r(void *base, size_t nel, size_t width,
int (*compar)(const void *_a, const void *_b,
void *aarg),
void *arg)
{
int nested_cmp(const void *a, const void *b)
{
return compar(a, b, arg);
}
qsort(base, nel, width, nested_cmp);
}
#else /* !NESTED_QSORT */
/* Declare structs and functions */
#if defined _SORT_R_BSD
/* Ensure qsort_r is defined */
extern void qsort_r(void *base, size_t nel, size_t width, void *thunk,
int (*compar)(void *_thunk, const void *_a, const void *_b));
#endif
#if defined _SORT_R_BSD || defined _SORT_R_WINDOWS
/* BSD (qsort_r), Windows (qsort_s) require argument swap */
struct sort_r_data
{
void *arg;
int (*compar)(const void *_a, const void *_b, void *_arg);
};
static _SORT_R_INLINE int sort_r_arg_swap(void *s, const void *a, const void *b)
{
struct sort_r_data *ss = (struct sort_r_data*)s;
return (ss->compar)(a, b, ss->arg);
}
#endif
#if defined _SORT_R_LINUX
#if 0 /* BE: To avoid redeclaration warning. */
typedef int(* __compar_d_fn_t)(const void *, const void *, void *);
extern void qsort_r(void *base, size_t nel, size_t width,
__compar_d_fn_t __compar, void *arg)
__attribute__((nonnull (1, 4)));
#endif
#endif
/* implementation */
static _SORT_R_INLINE void hb_sort_r(void *base, size_t nel, size_t width,
int (*compar)(const void *_a, const void *_b, void *_arg),
void *arg)
{
#if defined _SORT_R_LINUX
#if defined __GLIBC__ && ((__GLIBC__ < 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 8))
/* no qsort_r in glibc before 2.8, need to use nested qsort */
sort_r_simple(base, nel, width, compar, arg);
#else
qsort_r(base, nel, width, compar, arg);
#endif
#elif defined _SORT_R_BSD
struct sort_r_data tmp;
tmp.arg = arg;
tmp.compar = compar;
qsort_r(base, nel, width, &tmp, sort_r_arg_swap);
#elif defined _SORT_R_WINDOWS
struct sort_r_data tmp;
tmp.arg = arg;
tmp.compar = compar;
qsort_s(base, nel, width, sort_r_arg_swap, &tmp);
#else
/* Fall back to our own quicksort implementation */
sort_r_simple(base, nel, width, compar, arg);
#endif
}
#endif /* !NESTED_QSORT */
#undef _SORT_R_INLINE
#undef _SORT_R_WINDOWS
#undef _SORT_R_LINUX
#undef _SORT_R_BSD
static inline void hb_sort_r(void *base, size_t nel, size_t width,
int (*compar)(const void *_a, const void *_b, void *_arg),
void *arg)
{
sort_r_simple(base, nel, width, compar, arg);
}
#endif /* HB_SORT_R_HH */

Loading…
Cancel
Save