Tue, 01 Nov 2022 16:54:24 +0100
add vfs support to dir_redirect
91 | 1 | /* |
2 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. | |
3 | * | |
254 | 4 | * Copyright 2017 Mike Becker, Olaf Wintermann All rights reserved. |
91 | 5 | * |
6 | * Redistribution and use in source and binary forms, with or without | |
7 | * modification, are permitted provided that the following conditions are met: | |
8 | * | |
9 | * 1. Redistributions of source code must retain the above copyright | |
10 | * notice, this list of conditions and the following disclaimer. | |
11 | * | |
12 | * 2. Redistributions in binary form must reproduce the above copyright | |
13 | * notice, this list of conditions and the following disclaimer in the | |
14 | * documentation and/or other materials provided with the distribution. | |
15 | * | |
16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | |
17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE | |
20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
26 | * POSSIBILITY OF SUCH DAMAGE. | |
27 | */ | |
28 | ||
254 | 29 | #include "ucx/utils.h" |
30 | ||
91 | 31 | #include <math.h> |
32 | #include <stdio.h> | |
33 | #include <limits.h> | |
34 | #include <errno.h> | |
35 | ||
36 | /* COPY FUCNTIONS */ | |
254 | 37 | void* ucx_strcpy(const void* s, void* data) { |
38 | const char *str = (const char*) s; | |
91 | 39 | size_t n = 1+strlen(str); |
40 | char *cpy = (char*) malloc(n); | |
41 | memcpy(cpy, str, n); | |
42 | return cpy; | |
43 | } | |
44 | ||
254 | 45 | void* ucx_memcpy(const void* m, void* n) { |
91 | 46 | size_t k = *((size_t*)n); |
47 | void *cpy = malloc(k); | |
48 | memcpy(cpy, m, k); | |
49 | return cpy; | |
50 | } | |
51 | ||
135 | 52 | size_t ucx_stream_bncopy(void *src, void *dest, read_func readfnc, |
91 | 53 | write_func writefnc, char* buf, size_t bufsize, size_t n) { |
54 | if(n == 0 || bufsize == 0) { | |
55 | return 0; | |
56 | } | |
57 | ||
99 | 58 | char *lbuf; |
91 | 59 | size_t ncp = 0; |
99 | 60 | |
61 | if(buf) { | |
62 | lbuf = buf; | |
63 | } else { | |
64 | lbuf = (char*)malloc(bufsize); | |
65 | if(lbuf == NULL) { | |
91 | 66 | return 0; |
67 | } | |
68 | } | |
69 | ||
70 | size_t r; | |
71 | size_t rn = bufsize > n ? n : bufsize; | |
99 | 72 | while((r = readfnc(lbuf, 1, rn, src)) != 0) { |
73 | r = writefnc(lbuf, 1, r, dest); | |
91 | 74 | ncp += r; |
75 | n -= r; | |
76 | rn = bufsize > n ? n : bufsize; | |
77 | if(r == 0 || n == 0) { | |
78 | break; | |
79 | } | |
80 | } | |
81 | ||
99 | 82 | if (lbuf != buf) { |
83 | free(lbuf); | |
84 | } | |
85 | ||
91 | 86 | return ncp; |
87 | } | |
88 | ||
89 | /* COMPARE FUNCTIONS */ | |
90 | ||
254 | 91 | int ucx_cmp_str(const void *s1, const void *s2, void *data) { |
92 | return strcmp((const char*)s1, (const char*)s2); | |
93 | } | |
94 | ||
95 | int ucx_cmp_strn(const void *s1, const void *s2, void *n) { | |
96 | return strncmp((const char*)s1, (const char*)s2, *((size_t*) n)); | |
97 | } | |
98 | ||
99 | int ucx_cmp_sstr(const void *s1, const void *s2, void *data) { | |
100 | sstr_t a = *(const sstr_t*) s1; | |
101 | sstr_t b = *(const sstr_t*) s2; | |
102 | return sstrcmp(a, b); | |
103 | } | |
104 | ||
105 | int ucx_cmp_int(const void *i1, const void *i2, void *data) { | |
106 | int a = *((const int*) i1); | |
107 | int b = *((const int*) i2); | |
108 | if (a == b) { | |
109 | return 0; | |
110 | } else { | |
111 | return a < b ? -1 : 1; | |
112 | } | |
113 | } | |
114 | ||
115 | int ucx_cmp_longint(const void *i1, const void *i2, void *data) { | |
116 | long int a = *((const long int*) i1); | |
117 | long int b = *((const long int*) i2); | |
118 | if (a == b) { | |
119 | return 0; | |
120 | } else { | |
121 | return a < b ? -1 : 1; | |
122 | } | |
123 | } | |
124 | ||
125 | int ucx_cmp_longlong(const void *i1, const void *i2, void *data) { | |
126 | long long a = *((const long long*) i1); | |
127 | long long b = *((const long long*) i2); | |
128 | if (a == b) { | |
129 | return 0; | |
130 | } else { | |
131 | return a < b ? -1 : 1; | |
132 | } | |
91 | 133 | } |
134 | ||
254 | 135 | int ucx_cmp_int16(const void *i1, const void *i2, void *data) { |
136 | int16_t a = *((const int16_t*) i1); | |
137 | int16_t b = *((const int16_t*) i2); | |
138 | if (a == b) { | |
139 | return 0; | |
140 | } else { | |
141 | return a < b ? -1 : 1; | |
142 | } | |
143 | } | |
144 | ||
145 | int ucx_cmp_int32(const void *i1, const void *i2, void *data) { | |
146 | int32_t a = *((const int32_t*) i1); | |
147 | int32_t b = *((const int32_t*) i2); | |
148 | if (a == b) { | |
149 | return 0; | |
150 | } else { | |
151 | return a < b ? -1 : 1; | |
152 | } | |
91 | 153 | } |
154 | ||
254 | 155 | int ucx_cmp_int64(const void *i1, const void *i2, void *data) { |
156 | int64_t a = *((const int64_t*) i1); | |
157 | int64_t b = *((const int64_t*) i2); | |
158 | if (a == b) { | |
159 | return 0; | |
160 | } else { | |
161 | return a < b ? -1 : 1; | |
162 | } | |
163 | } | |
164 | ||
165 | int ucx_cmp_uint(const void *i1, const void *i2, void *data) { | |
166 | unsigned int a = *((const unsigned int*) i1); | |
167 | unsigned int b = *((const unsigned int*) i2); | |
168 | if (a == b) { | |
169 | return 0; | |
170 | } else { | |
171 | return a < b ? -1 : 1; | |
172 | } | |
173 | } | |
174 | ||
175 | int ucx_cmp_ulongint(const void *i1, const void *i2, void *data) { | |
176 | unsigned long int a = *((const unsigned long int*) i1); | |
177 | unsigned long int b = *((const unsigned long int*) i2); | |
178 | if (a == b) { | |
179 | return 0; | |
180 | } else { | |
181 | return a < b ? -1 : 1; | |
182 | } | |
183 | } | |
184 | ||
185 | int ucx_cmp_ulonglong(const void *i1, const void *i2, void *data) { | |
186 | unsigned long long a = *((const unsigned long long*) i1); | |
187 | unsigned long long b = *((const unsigned long long*) i2); | |
91 | 188 | if (a == b) { |
189 | return 0; | |
190 | } else { | |
191 | return a < b ? -1 : 1; | |
192 | } | |
193 | } | |
194 | ||
254 | 195 | int ucx_cmp_uint16(const void *i1, const void *i2, void *data) { |
196 | uint16_t a = *((const uint16_t*) i1); | |
197 | uint16_t b = *((const uint16_t*) i2); | |
198 | if (a == b) { | |
199 | return 0; | |
200 | } else { | |
201 | return a < b ? -1 : 1; | |
202 | } | |
203 | } | |
204 | ||
205 | int ucx_cmp_uint32(const void *i1, const void *i2, void *data) { | |
206 | uint32_t a = *((const uint32_t*) i1); | |
207 | uint32_t b = *((const uint32_t*) i2); | |
208 | if (a == b) { | |
209 | return 0; | |
210 | } else { | |
211 | return a < b ? -1 : 1; | |
212 | } | |
213 | } | |
214 | ||
215 | int ucx_cmp_uint64(const void *i1, const void *i2, void *data) { | |
216 | uint64_t a = *((const uint64_t*) i1); | |
217 | uint64_t b = *((const uint64_t*) i2); | |
218 | if (a == b) { | |
219 | return 0; | |
220 | } else { | |
221 | return a < b ? -1 : 1; | |
222 | } | |
223 | } | |
224 | ||
225 | intmax_t ucx_dist_int(const void *i1, const void *i2, void *data) { | |
226 | intmax_t a = *((const int*) i1); | |
227 | intmax_t b = *((const int*) i2); | |
228 | return a - b; | |
229 | } | |
230 | ||
231 | intmax_t ucx_dist_longint(const void *i1, const void *i2, void *data) { | |
232 | intmax_t a = *((const long int*) i1); | |
233 | intmax_t b = *((const long int*) i2); | |
234 | return a - b; | |
235 | } | |
236 | ||
237 | intmax_t ucx_dist_longlong(const void *i1, const void *i2, void *data) { | |
238 | intmax_t a = *((const long long*) i1); | |
239 | intmax_t b = *((const long long*) i2); | |
240 | return a - b; | |
241 | } | |
242 | ||
243 | intmax_t ucx_dist_int16(const void *i1, const void *i2, void *data) { | |
244 | intmax_t a = *((const int16_t*) i1); | |
245 | intmax_t b = *((const int16_t*) i2); | |
246 | return a - b; | |
247 | } | |
248 | ||
249 | intmax_t ucx_dist_int32(const void *i1, const void *i2, void *data) { | |
250 | intmax_t a = *((const int32_t*) i1); | |
251 | intmax_t b = *((const int32_t*) i2); | |
252 | return a - b; | |
253 | } | |
254 | ||
255 | intmax_t ucx_dist_int64(const void *i1, const void *i2, void *data) { | |
256 | intmax_t a = *((const int64_t*) i1); | |
257 | intmax_t b = *((const int64_t*) i2); | |
258 | return a - b; | |
259 | } | |
260 | ||
261 | intmax_t ucx_dist_uint(const void *i1, const void *i2, void *data) { | |
262 | uintmax_t a = *((const unsigned int*) i1); | |
263 | uintmax_t b = *((const unsigned int*) i2); | |
264 | return a > b ? (intmax_t)(a - b) : -(intmax_t)(b - a); | |
265 | } | |
266 | ||
267 | intmax_t ucx_dist_ulongint(const void *i1, const void *i2, void *data) { | |
268 | uintmax_t a = *((const unsigned long int*) i1); | |
269 | uintmax_t b = *((const unsigned long int*) i2); | |
270 | return a > b ? (intmax_t)(a - b) : -(intmax_t)(b - a); | |
271 | } | |
272 | ||
273 | intmax_t ucx_dist_ulonglong(const void *i1, const void *i2, void *data) { | |
274 | uintmax_t a = *((const unsigned long long*) i1); | |
275 | uintmax_t b = *((const unsigned long long*) i2); | |
276 | return a > b ? (intmax_t)(a - b) : -(intmax_t)(b - a); | |
277 | } | |
278 | ||
279 | intmax_t ucx_dist_uint16(const void *i1, const void *i2, void *data) { | |
280 | uintmax_t a = *((const uint16_t*) i1); | |
281 | uintmax_t b = *((const uint16_t*) i2); | |
282 | return a > b ? (intmax_t)(a - b) : -(intmax_t)(b - a); | |
283 | } | |
284 | ||
285 | intmax_t ucx_dist_uint32(const void *i1, const void *i2, void *data) { | |
286 | uintmax_t a = *((const uint32_t*) i1); | |
287 | uintmax_t b = *((const uint32_t*) i2); | |
288 | return a > b ? (intmax_t)(a - b) : -(intmax_t)(b - a); | |
289 | } | |
290 | ||
291 | intmax_t ucx_dist_uint64(const void *i1, const void *i2, void *data) { | |
292 | uintmax_t a = *((const uint64_t*) i1); | |
293 | uintmax_t b = *((const uint64_t*) i2); | |
294 | return a > b ? (intmax_t)(a - b) : -(intmax_t)(b - a); | |
295 | } | |
296 | ||
297 | int ucx_cmp_float(const void *f1, const void *f2, void *epsilon) { | |
298 | float a = *((const float*) f1); | |
299 | float b = *((const float*) f2); | |
91 | 300 | float e = !epsilon ? 1e-6f : *((float*)epsilon); |
301 | if (fabsf(a - b) < e) { | |
302 | return 0; | |
303 | } else { | |
304 | return a < b ? -1 : 1; | |
305 | } | |
306 | } | |
307 | ||
254 | 308 | int ucx_cmp_double(const void *d1, const void *d2, void *epsilon) { |
309 | double a = *((const double*) d1); | |
310 | double b = *((const double*) d2); | |
91 | 311 | double e = !epsilon ? 1e-14 : *((double*)epsilon); |
312 | if (fabs(a - b) < e) { | |
313 | return 0; | |
314 | } else { | |
315 | return a < b ? -1 : 1; | |
316 | } | |
317 | } | |
318 | ||
254 | 319 | int ucx_cmp_ptr(const void *ptr1, const void *ptr2, void *data) { |
320 | const intptr_t p1 = (const intptr_t) ptr1; | |
321 | const intptr_t p2 = (const intptr_t) ptr2; | |
99 | 322 | if (p1 == p2) { |
91 | 323 | return 0; |
324 | } else { | |
99 | 325 | return p1 < p2 ? -1 : 1; |
91 | 326 | } |
327 | } | |
328 | ||
254 | 329 | int ucx_cmp_mem(const void *ptr1, const void *ptr2, void *n) { |
91 | 330 | return memcmp(ptr1, ptr2, *((size_t*)n)); |
331 | } | |
332 | ||
333 | /* PRINTF FUNCTIONS */ | |
334 | ||
335 | #ifdef va_copy | |
336 | #define UCX_PRINTF_BUFSIZE 256 | |
337 | #else | |
338 | #pragma message("WARNING: C99 va_copy macro not supported by this platform" \ | |
339 | " - limiting ucx_*printf to 2 KiB") | |
340 | #define UCX_PRINTF_BUFSIZE 0x800 | |
341 | #endif | |
342 | ||
343 | int ucx_fprintf(void *stream, write_func wfc, const char *fmt, ...) { | |
344 | int ret; | |
345 | va_list ap; | |
346 | va_start(ap, fmt); | |
347 | ret = ucx_vfprintf(stream, wfc, fmt, ap); | |
348 | va_end(ap); | |
349 | return ret; | |
350 | } | |
351 | ||
352 | int ucx_vfprintf(void *stream, write_func wfc, const char *fmt, va_list ap) { | |
353 | char buf[UCX_PRINTF_BUFSIZE]; | |
354 | #ifdef va_copy | |
355 | va_list ap2; | |
356 | va_copy(ap2, ap); | |
357 | int ret = vsnprintf(buf, UCX_PRINTF_BUFSIZE, fmt, ap); | |
358 | if (ret < 0) { | |
359 | return ret; | |
360 | } else if (ret < UCX_PRINTF_BUFSIZE) { | |
361 | return (int)wfc(buf, 1, ret, stream); | |
362 | } else { | |
363 | if (ret == INT_MAX) { | |
364 | errno = ENOMEM; | |
365 | return -1; | |
366 | } | |
367 | ||
368 | int len = ret + 1; | |
369 | char *newbuf = (char*)malloc(len); | |
370 | if (!newbuf) { | |
371 | return -1; | |
372 | } | |
373 | ||
374 | ret = vsnprintf(newbuf, len, fmt, ap2); | |
375 | if (ret > 0) { | |
376 | ret = (int)wfc(newbuf, 1, ret, stream); | |
377 | } | |
378 | free(newbuf); | |
379 | } | |
380 | return ret; | |
381 | #else | |
382 | int ret = vsnprintf(buf, UCX_PRINTF_BUFSIZE, fmt, ap); | |
383 | if (ret < 0) { | |
384 | return ret; | |
385 | } else if (ret < UCX_PRINTF_BUFSIZE) { | |
386 | return (int)wfc(buf, 1, ret, stream); | |
387 | } else { | |
388 | errno = ENOMEM; | |
389 | return -1; | |
390 | } | |
391 | #endif | |
392 | } | |
393 | ||
394 | sstr_t ucx_asprintf(UcxAllocator *allocator, const char *fmt, ...) { | |
395 | va_list ap; | |
396 | sstr_t ret; | |
397 | va_start(ap, fmt); | |
398 | ret = ucx_vasprintf(allocator, fmt, ap); | |
399 | va_end(ap); | |
400 | return ret; | |
401 | } | |
402 | ||
403 | sstr_t ucx_vasprintf(UcxAllocator *a, const char *fmt, va_list ap) { | |
404 | sstr_t s; | |
405 | s.ptr = NULL; | |
406 | s.length = 0; | |
407 | char buf[UCX_PRINTF_BUFSIZE]; | |
408 | #ifdef va_copy | |
409 | va_list ap2; | |
410 | va_copy(ap2, ap); | |
411 | int ret = vsnprintf(buf, UCX_PRINTF_BUFSIZE, fmt, ap); | |
412 | if (ret > 0 && ret < UCX_PRINTF_BUFSIZE) { | |
99 | 413 | s.ptr = (char*)almalloc(a, ret + 1); |
414 | if (s.ptr) { | |
415 | s.length = (size_t)ret; | |
416 | memcpy(s.ptr, buf, ret); | |
417 | s.ptr[s.length] = '\0'; | |
418 | } | |
91 | 419 | } else if (ret == INT_MAX) { |
420 | errno = ENOMEM; | |
421 | } else { | |
422 | int len = ret + 1; | |
99 | 423 | s.ptr = (char*)almalloc(a, len); |
424 | if (s.ptr) { | |
425 | ret = vsnprintf(s.ptr, len, fmt, ap2); | |
426 | if (ret < 0) { | |
427 | free(s.ptr); | |
428 | s.ptr = NULL; | |
429 | } else { | |
430 | s.length = (size_t)ret; | |
431 | } | |
91 | 432 | } |
433 | } | |
434 | #else | |
435 | int ret = vsnprintf(buf, UCX_PRINTF_BUFSIZE, fmt, ap); | |
436 | if (ret > 0 && ret < UCX_PRINTF_BUFSIZE) { | |
99 | 437 | s.ptr = (char*)almalloc(a, ret + 1); |
438 | if (s.ptr) { | |
439 | s.length = (size_t)ret; | |
440 | memcpy(s.ptr, buf, ret); | |
441 | s.ptr[s.length] = '\0'; | |
442 | } | |
91 | 443 | } else { |
444 | errno = ENOMEM; | |
445 | } | |
446 | #endif | |
447 | return s; | |
448 | } |