summaryrefslogtreecommitdiff
path: root/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'util.c')
-rw-r--r--util.c25
1 files changed, 21 insertions, 4 deletions
diff --git a/util.c b/util.c
index 2c1ae86..a713086 100644
--- a/util.c
+++ b/util.c
@@ -195,14 +195,32 @@ ruby_strtoul(const char *str, char **endptr, int base)
# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
#endif
-#if !defined HAVE_BSD_QSORT_R && defined HAVE_QSORT_S
+typedef int (cmpfunc_t)(const void*, const void*, void*);
+
+#if defined HAVE_QSORT_S
+# if defined __MSVCRT__
# define qsort_r(base, nel, size, arg, cmp) qsort_s(base, nel, size, cmp, arg)
# define cmp_bsd_qsort cmp_ms_qsort
# define HAVE_BSD_QSORT_R 1
+# elif defined __STDC_VERSION__ && __STDC_VERSION__ >= 201112L
+/* C11 qsort_s has the same arguments as ours */
+void
+ruby_qsort(void* base, const size_t nel, const size_t size, cmpfunc_t *cmp, void *d)
+{
+ if (!nel || !size) return; /* nothing to sort */
+
+ /* get rid of runtime-constraints handler for MT-safeness */
+ if (!base || !cmp) return;
+ if (nel > RSIZE_MAX || size > RSIZE_MAX) return;
+
+ qsort_s(base, nel, size, cmp, d);
+}
+# else
+# error Unknown version qsort_s
+# endif
#endif
-#if defined HAVE_BSD_QSORT_R
-typedef int (cmpfunc_t)(const void*, const void*, void*);
+#if defined HAVE_BSD_QSORT_R
struct bsd_qsort_r_args {
cmpfunc_t *cmp;
void *arg;
@@ -339,7 +357,6 @@ typedef struct { char *LL, *RR; } stack_node; /* Stack structure for L,l,R,r */
((*cmp)((b),(c),d)<0 ? (b) : ((*cmp)((a),(c),d)<0 ? (c) : (a))) : \
((*cmp)((b),(c),d)>0 ? (b) : ((*cmp)((a),(c),d)<0 ? (a) : (c))))
-typedef int (cmpfunc_t)(const void*, const void*, void*);
void
ruby_qsort(void* base, const size_t nel, const size_t size, cmpfunc_t *cmp, void *d)
{