move control socket handling to separate file
[mizunara.git] / ucx / utils.c
1 /*
2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3  *
4  * Copyright 2017 Mike Becker, Olaf Wintermann All rights reserved.
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
29 #include "ucx/utils.h"
30
31 #include <math.h>
32 #include <stdio.h>
33 #include <limits.h>
34 #include <errno.h>
35
36 /* COPY FUCNTIONS */
37 void* ucx_strcpy(const void* s, void* data) {
38     const char *str = (const char*) s;
39     size_t n = 1+strlen(str);
40     char *cpy = (char*) malloc(n);
41     memcpy(cpy, str, n);
42     return cpy;
43 }
44
45 void* ucx_memcpy(const void* m, void* n) {
46     size_t k = *((size_t*)n);
47     void *cpy = malloc(k);
48     memcpy(cpy, m, k);
49     return cpy;
50 }
51
52 size_t ucx_stream_bncopy(void *src, void *dest, read_func readfnc,
53         write_func writefnc, char* buf, size_t bufsize, size_t n) {
54     if(n == 0 || bufsize == 0) {
55         return 0;
56     }
57     
58     char *lbuf;    
59     size_t ncp = 0;
60     
61     if(buf) {
62         lbuf = buf;
63     } else {
64         lbuf = (char*)malloc(bufsize);
65         if(lbuf == NULL) {
66             return 0;
67         }
68     }
69     
70     size_t r;
71     size_t rn = bufsize > n ? n : bufsize;
72     while((r = readfnc(lbuf, 1, rn, src)) != 0) {
73         r = writefnc(lbuf, 1, r, dest);
74         ncp += r;
75         n -= r;
76         rn = bufsize > n ? n : bufsize;
77         if(r == 0 || n == 0) {
78             break;
79         }
80     }
81     
82     if (lbuf != buf) {
83         free(lbuf);
84     }
85     
86     return ncp;
87 }
88
89 /* COMPARE FUNCTIONS */
90
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    }
133 }
134
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    }
153 }
154
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);
188    if (a == b) {
189        return 0;
190    } else {
191        return a < b ? -1 : 1;
192    }
193 }
194
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);
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
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);
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
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;
322     if (p1 == p2) {
323         return 0;
324     } else {
325         return p1  < p2 ? -1 : 1;
326     }
327 }
328
329 int ucx_cmp_mem(const void *ptr1, const void *ptr2, void *n) {
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) {
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         }
419     } else if (ret == INT_MAX) {
420         errno = ENOMEM;
421     } else  {
422         int len = ret + 1;
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             }
432         }
433     }
434 #else
435     int ret = vsnprintf(buf, UCX_PRINTF_BUFSIZE, fmt, ap);
436     if (ret > 0 && ret < UCX_PRINTF_BUFSIZE) {
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         }
443     } else {
444         errno = ENOMEM;
445     }
446 #endif
447     return s;
448 }