... | ... |
@@ -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 |
+} |