summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Beckett <dave@dajobe.org>2014-06-29 15:18:31 -0700
committerDave Beckett <dave@dajobe.org>2014-06-29 15:18:31 -0700
commit755bc7c5879cba3cd9dc8ed3b93c4b1fa1123a69 (patch)
tree297957241bac8cb8ad57a15a0fca2088b129d2b9
parent5a7b95d55c347eba2a8f5a56bb2afbcdcc5d43c5 (diff)
downloadraptor-755bc7c5879cba3cd9dc8ed3b93c4b1fa1123a69.tar.gz
sort_r.c Public Domain sort_r() by Isaac Turner
Imported GIT commit 7c60ef94753624291055af0b1eec291f8c4bd5a7 from https://github.com/noporpoise/sort_r
-rw-r--r--src/sort_r.h122
1 files changed, 122 insertions, 0 deletions
diff --git a/src/sort_r.h b/src/sort_r.h
new file mode 100644
index 00000000..5ea05383
--- /dev/null
+++ b/src/sort_r.h
@@ -0,0 +1,122 @@
+/* Isaac Turner 29 April 2014 Public Domain */
+#ifndef SORT_R_H_
+#define SORT_R_H_
+
+#include <stdlib.h>
+
+/*
+sort_r function to be exported.
+
+Parameters:
+ base is the array to be sorted
+ nel is the number of elements in the array
+ width is the size in bytes of each element of the array
+ compar is the comparison function
+ arg is a pointer to be passed to the comparison function
+
+void sort_r(void *base, size_t nel, size_t width,
+ int (*compar)(const void *_a, const void *_b, void *_arg),
+ void *arg);
+*/
+
+#if (defined __APPLE__ || defined __MACH__ || defined __DARWIN__ || \
+ defined __FREEBSD__ || defined __BSD__ || \
+ defined OpenBSD3_1 || defined OpenBSD3_9 || defined __OpenBSD__ || \
+ defined AMIGA)
+# 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
+#else
+# error Cannot detect operating system
+#endif
+
+#if (defined NESTED_QSORT && NESTED_QSORT == 0)
+# undef NESTED_QSORT
+#elif (!defined NESTED_QSORT && \
+ defined __GLIBC__ && __GLIBC__ == 2 && __GLIBC_MINOR__ < 8)
+/* no qsort_r in glibc before 2.8 */
+# define NESTED_QSORT
+#endif
+
+
+#if defined NESTED_QSORT
+
+ static inline void 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
+
+ /* BSD requires argument swap */
+ extern void qsort_r(void *base, size_t nel, size_t width, void *thunk,
+ int (*compar)(void *_thunk, const void *_a, const void *_b));
+
+ struct sort_r_data
+ {
+ void *arg;
+ int (*compar)(const void *_a, const void *_b, void *_arg);
+ };
+
+ static 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);
+ }
+
+ #elif defined _SORT_R_LINUX
+
+ 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
+
+ /* implementation */
+
+ static inline void 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
+
+ qsort_r(base, nel, width, compar, arg);
+
+ #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);
+
+ #else /* 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);
+
+ #endif
+ }
+
+#endif /* !NESTED_QSORT */
+
+#undef _SORT_R_WINDOWS
+#undef _SORT_R_LINUX
+#undef _SORT_R_BSD
+
+#endif /* SORT_R_H_ */