From 5ffb9dfe0e2256adb910571a4857bff931c7a80f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Denis-Courmont?= Date: Tue, 20 Nov 2018 17:56:05 +0200 Subject: [PATCH] compat: replace qsort_r() where missing This should sort properly on Windows and any other platform without qsort_r(). It does _not_ fix any potential issues on any platforms with an incompatible qsort_r() prototype (such as FreeBSD < 13). --- compat/qsort_r.c | 56 ++++++++++++++++++++++++++++++++++++++++++++ configure.ac | 2 +- include/vlc_fixups.h | 6 +++++ 3 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 compat/qsort_r.c diff --git a/compat/qsort_r.c b/compat/qsort_r.c new file mode 100644 index 0000000000..1f68b68ba0 --- /dev/null +++ b/compat/qsort_r.c @@ -0,0 +1,56 @@ +/***************************************************************************** + * qsort_r.c: future POSIX qsort_r() replacement + ***************************************************************************** + * Copyright © 2018 Rémi Denis-Courmont + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. + *****************************************************************************/ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +static _Thread_local struct +{ + int (*compar)(const void *, const void *, void *); + void *arg; +} state; + +static int compar_wrapper(const void *a, const void *b) +{ + return state.compar(a, b, state.arg); +} + +/* Follow the upcoming POSIX prototype, coming from GNU/libc. + * Note that this differs from the BSD prototype. */ + +void qsort_r(void *base, size_t nmemb, size_t size, + int (*compar)(const void *, const void *, void *), + void *arg) +{ + int (*saved_compar)(const void *, const void *, void *) = state.compar; + void *saved_arg = state.arg; + + state.compar = compar; + state.arg = arg; + + qsort(base, nmemb, size, compar_wrapper); + + /* Restore state for nested reentrant calls */ + state.compar = saved_compar; + state.arg = saved_arg; +} diff --git a/configure.ac b/configure.ac index 8cf88a4ec6..1f33f5dc88 100644 --- a/configure.ac +++ b/configure.ac @@ -581,7 +581,7 @@ need_libc=false dnl Check for usual libc functions AC_CHECK_FUNCS([accept4 daemon fcntl flock fstatvfs fork getenv getpwuid_r isatty memalign mkostemp mmap open_memstream newlocale openat pipe2 pread posix_fadvise posix_madvise posix_memalign setlocale stricmp strnicmp strptime uselocale]) -AC_REPLACE_FUNCS([aligned_alloc atof atoll dirfd fdopendir flockfile fsync getdelim getpid lfind lldiv memrchr nrand48 poll recvmsg rewind sendmsg setenv strcasecmp strcasestr strdup strlcpy strndup strnlen strnstr strsep strtof strtok_r strtoll swab tdestroy tfind timegm timespec_get strverscmp pathconf]) +AC_REPLACE_FUNCS([aligned_alloc atof atoll dirfd fdopendir flockfile fsync getdelim getpid lfind lldiv memrchr nrand48 poll qsort_r recvmsg rewind sendmsg setenv strcasecmp strcasestr strdup strlcpy strndup strnlen strnstr strsep strtof strtok_r strtoll swab tdestroy tfind timegm timespec_get strverscmp pathconf]) AC_REPLACE_FUNCS([gettimeofday]) AC_CHECK_FUNC(fdatasync,, [AC_DEFINE(fdatasync, fsync, [Alias fdatasync() to fsync() if missing.]) diff --git a/include/vlc_fixups.h b/include/vlc_fixups.h index a68dc1e820..0263286efc 100644 --- a/include/vlc_fixups.h +++ b/include/vlc_fixups.h @@ -90,6 +90,7 @@ typedef struct #if !defined (HAVE_ALIGNED_ALLOC) || \ !defined (HAVE_MEMRCHR) || \ + !defined (HAVE_QSORT_R) || \ !defined (HAVE_STRLCPY) || \ !defined (HAVE_STRNDUP) || \ !defined (HAVE_STRNLEN) || \ @@ -223,6 +224,11 @@ long long atoll (const char *); lldiv_t lldiv (long long, long long); #endif +#ifndef HAVE_QSORT_R +void (qsort_r)(void *, size_t, size_t, + int (*)(const void *, const void *, void *), void *); +#endif + #ifndef HAVE_STRTOF #ifndef __ANDROID__ float strtof (const char *, char **);