Browse code

added implementation of cli_qsort_r (qsort with cb arg)

Kevin Lin authored on 2015/05/22 04:03:46
Showing 2 changed files
... ...
@@ -661,6 +661,7 @@ int cli_updatelimits(cli_ctx *, unsigned long);
661 661
 unsigned long cli_getsizelimit(cli_ctx *, unsigned long);
662 662
 int cli_matchregex(const char *str, const char *regex);
663 663
 void cli_qsort(void *a, size_t n, size_t es, int (*cmp)(const void *, const void *));
664
+void cli_qsort_r(void *a, size_t n, size_t es, int (*cmp)(const void*, const void *, const void *), void *arg);
664 665
 int cli_checktimelimit(cli_ctx *ctx);
665 666
 
666 667
 /* symlink behaviour */
... ...
@@ -38,6 +38,7 @@
38 38
 #include "others.h"
39 39
 
40 40
 static inline char	*med3(char *, char *, char *, int (*)(const void *, const void *));
41
+static inline char	*med3_r(void *, char *, char *, char *, int (*)(const void *, const void *, const void *));
41 42
 static inline void	 swapfunc(char *, char *, int, int);
42 43
 
43 44
 /*
... ...
@@ -80,7 +81,9 @@ swapfunc(a, b, n, swaptype)
80 80
 
81 81
 #define CMP1(a, b) ((int)(*((uint32_t *)(a)) - *((uint32_t *)(b))))
82 82
 #define CMP(a, b)   (cmp ? (cmp(a, b)) : CMP1(a, b))
83
+#define CMP_R(arg, a, b)   (cmp ? (cmp(arg, a, b)) : CMP1(a, b))
83 84
 #define MED3(a, b, c, d)   (d ? (med3(a, b, c, d)) : (CMP1(a, b) < 0 ? (CMP1(b, c) < 0 ? (b) : (CMP1(a, c) < 0 ? (c) : (a))) : (CMP1(b, c) > 0 ? (b) : (CMP1(a, c) < 0 ? (a) : (c)))))
85
+#define MED3_R(arg, a, b, c, d)   (d ? (med3_r(arg, a, b, c, d)) : (CMP1(a, b) < 0 ? (CMP1(b, c) < 0 ? (b) : (CMP1(a, c) < 0 ? (c) : (a))) : (CMP1(b, c) > 0 ? (b) : (CMP1(a, c) < 0 ? (a) : (c)))))
84 86
 
85 87
 static inline char *
86 88
 med3(a, b, c, cmp)
... ...
@@ -92,6 +95,17 @@ med3(a, b, c, cmp)
92 92
               :(CMP(b, c) > 0 ? b : (CMP(a, c) < 0 ? a : c ));
93 93
 }
94 94
 
95
+static inline char *
96
+med3_r(arg, a, b, c, cmp)
97
+	void *arg;
98
+	char *a, *b, *c;
99
+	int (*cmp)(const void *, const void *, const void *);
100
+{
101
+	return CMP_R(arg, a, b) < 0 ?
102
+	       (CMP_R(arg, b, c) < 0 ? b : (CMP_R(arg, a, c) < 0 ? c : a ))
103
+              :(CMP_R(arg, b, c) > 0 ? b : (CMP_R(arg, a, c) < 0 ? a : c ));
104
+}
105
+
95 106
 void cli_qsort(void *a, size_t n, size_t es, int (*cmp)(const void *, const void *))
96 107
 {
97 108
 	char *pa, *pb, *pc, *pd, *pl, *pm, *pn;
... ...
@@ -169,3 +183,81 @@ loop:	SWAPINIT(a, es);
169 169
 	}
170 170
 /*		cli_qsort(pn - r, r / es, es, cmp);*/
171 171
 }
172
+
173
+void cli_qsort_r(void *a, size_t n, size_t es, int (*cmp)(const void*, const void *, const void *), void *arg)
174
+{
175
+	char *pa, *pb, *pc, *pd, *pl, *pm, *pn;
176
+	int d, r, swaptype, swap_cnt;
177
+
178
+loop:	SWAPINIT(a, es);
179
+	swap_cnt = 0;
180
+	if (n < 7) {
181
+		for (pm = (char *) a + es; pm < (char *) a + n * es; pm += es)
182
+			for (pl = pm; pl > (char *) a && CMP_R(arg, pl - es, pl) > 0;
183
+			     pl -= es)
184
+				swap(pl, pl - es);
185
+		return;
186
+	}
187
+	pm = (char *) a + (n / 2) * es;
188
+	if (n > 7) {
189
+		pl = a;
190
+		pn = (char *) a + (n - 1) * es;
191
+		if (n > 40) {
192
+			d = (n / 8) * es;
193
+			pl = MED3_R(arg, pl, pl + d, pl + 2 * d, cmp);
194
+			pm = MED3_R(arg, pm - d, pm, pm + d, cmp);
195
+			pn = MED3_R(arg, pn - 2 * d, pn - d, pn, cmp);
196
+		}
197
+		pm = MED3_R(arg, pl, pm, pn, cmp);
198
+	}
199
+	swap(a, pm);
200
+	pa = pb = (char *) a + es;
201
+
202
+	pc = pd = (char *) a + (n - 1) * es;
203
+	for (;;) {
204
+		while (pb <= pc && (r = CMP_R(arg, pb, a)) <= 0) {
205
+			if (r == 0) {
206
+				swap_cnt = 1;
207
+				swap(pa, pb);
208
+				pa += es;
209
+			}
210
+			pb += es;
211
+		}
212
+		while (pb <= pc && (r = CMP_R(arg, pc, a)) >= 0) {
213
+			if (r == 0) {
214
+				swap_cnt = 1;
215
+				swap(pc, pd);
216
+				pd -= es;
217
+			}
218
+			pc -= es;
219
+		}
220
+		if (pb > pc)
221
+			break;
222
+		swap(pb, pc);
223
+		swap_cnt = 1;
224
+		pb += es;
225
+		pc -= es;
226
+	}
227
+	if (swap_cnt == 0) {  /* Switch to insertion sort */
228
+		for (pm = (char *) a + es; pm < (char *) a + n * es; pm += es)
229
+			for (pl = pm; pl > (char *) a && CMP_R(arg, pl - es, pl) > 0; 
230
+			     pl -= es)
231
+				swap(pl, pl - es);
232
+		return;
233
+	}
234
+
235
+	pn = (char *) a + n * es;
236
+	r = MIN(pa - (char *)a, pb - pa);
237
+	vecswap(a, pb - r, r);
238
+	r = MIN((size_t) (pd - pc), (size_t) (pn - pd - es));
239
+	vecswap(pb, pn - r, r);
240
+	if ((size_t) (r = pb - pa) > es)
241
+		cli_qsort_r(a, r / es, es, cmp, arg);
242
+	if ((size_t) (r = pd - pc) > es) { 
243
+		/* Iterate rather than recurse to save stack space */
244
+		a = pn - r;
245
+		n = r / es;
246
+		goto loop;
247
+	}
248
+/*		cli_qsort_r(pn - r, r / es, es, cmp);*/
249
+}