UNIXworkcode

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 } 449