1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/utils.c Tue Oct 17 16:15:41 2017 +0200 1.3 @@ -0,0 +1,260 @@ 1.4 +/* 1.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 1.6 + * 1.7 + * Copyright 2017 Olaf Wintermann. All rights reserved. 1.8 + * 1.9 + * Redistribution and use in source and binary forms, with or without 1.10 + * modification, are permitted provided that the following conditions are met: 1.11 + * 1.12 + * 1. Redistributions of source code must retain the above copyright 1.13 + * notice, this list of conditions and the following disclaimer. 1.14 + * 1.15 + * 2. Redistributions in binary form must reproduce the above copyright 1.16 + * notice, this list of conditions and the following disclaimer in the 1.17 + * documentation and/or other materials provided with the distribution. 1.18 + * 1.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 1.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 1.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 1.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 1.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 1.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 1.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 1.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 1.29 + * POSSIBILITY OF SUCH DAMAGE. 1.30 + */ 1.31 + 1.32 +#include "ucx/utils.h" 1.33 + 1.34 +#include <math.h> 1.35 +#include <stdio.h> 1.36 +#include <limits.h> 1.37 +#include <errno.h> 1.38 + 1.39 +/* COPY FUCNTIONS */ 1.40 +void* ucx_strcpy(const void* s, void* data) { 1.41 + const char *str = (const char*) s; 1.42 + size_t n = 1+strlen(str); 1.43 + char *cpy = (char*) malloc(n); 1.44 + memcpy(cpy, str, n); 1.45 + return cpy; 1.46 +} 1.47 + 1.48 +void* ucx_memcpy(const void* m, void* n) { 1.49 + size_t k = *((size_t*)n); 1.50 + void *cpy = malloc(k); 1.51 + memcpy(cpy, m, k); 1.52 + return cpy; 1.53 +} 1.54 + 1.55 +size_t ucx_stream_bncopy(void *src, void *dest, read_func readfnc, 1.56 + write_func writefnc, char* buf, size_t bufsize, size_t n) { 1.57 + if(n == 0 || bufsize == 0) { 1.58 + return 0; 1.59 + } 1.60 + 1.61 + char *lbuf; 1.62 + size_t ncp = 0; 1.63 + 1.64 + if(buf) { 1.65 + lbuf = buf; 1.66 + } else { 1.67 + lbuf = (char*)malloc(bufsize); 1.68 + if(lbuf == NULL) { 1.69 + return 0; 1.70 + } 1.71 + } 1.72 + 1.73 + size_t r; 1.74 + size_t rn = bufsize > n ? n : bufsize; 1.75 + while((r = readfnc(lbuf, 1, rn, src)) != 0) { 1.76 + r = writefnc(lbuf, 1, r, dest); 1.77 + ncp += r; 1.78 + n -= r; 1.79 + rn = bufsize > n ? n : bufsize; 1.80 + if(r == 0 || n == 0) { 1.81 + break; 1.82 + } 1.83 + } 1.84 + 1.85 + if (lbuf != buf) { 1.86 + free(lbuf); 1.87 + } 1.88 + 1.89 + return ncp; 1.90 +} 1.91 + 1.92 +/* COMPARE FUNCTIONS */ 1.93 + 1.94 +int ucx_strcmp(const void *s1, const void *s2, void *data) { 1.95 + return strcmp((const char*)s1, (const char*)s2); 1.96 +} 1.97 + 1.98 +int ucx_strncmp(const void *s1, const void *s2, void *n) { 1.99 + return strncmp((const char*)s1, (const char*)s2, *((size_t*) n)); 1.100 +} 1.101 + 1.102 +int ucx_intcmp(const void *i1, const void *i2, void *data) { 1.103 + int a = *((const int*) i1); 1.104 + int b = *((const int*) i2); 1.105 + if (a == b) { 1.106 + return 0; 1.107 + } else { 1.108 + return a < b ? -1 : 1; 1.109 + } 1.110 +} 1.111 + 1.112 +int ucx_floatcmp(const void *f1, const void *f2, void *epsilon) { 1.113 + float a = *((const float*) f1); 1.114 + float b = *((const float*) f2); 1.115 + float e = !epsilon ? 1e-6f : *((float*)epsilon); 1.116 + if (fabsf(a - b) < e) { 1.117 + return 0; 1.118 + } else { 1.119 + return a < b ? -1 : 1; 1.120 + } 1.121 +} 1.122 + 1.123 +int ucx_doublecmp(const void *d1, const void *d2, void *epsilon) { 1.124 + double a = *((const double*) d1); 1.125 + double b = *((const double*) d2); 1.126 + double e = !epsilon ? 1e-14 : *((double*)epsilon); 1.127 + if (fabs(a - b) < e) { 1.128 + return 0; 1.129 + } else { 1.130 + return a < b ? -1 : 1; 1.131 + } 1.132 +} 1.133 + 1.134 +int ucx_ptrcmp(const void *ptr1, const void *ptr2, void *data) { 1.135 + const intptr_t p1 = (const intptr_t) ptr1; 1.136 + const intptr_t p2 = (const intptr_t) ptr2; 1.137 + if (p1 == p2) { 1.138 + return 0; 1.139 + } else { 1.140 + return p1 < p2 ? -1 : 1; 1.141 + } 1.142 +} 1.143 + 1.144 +int ucx_memcmp(const void *ptr1, const void *ptr2, void *n) { 1.145 + return memcmp(ptr1, ptr2, *((size_t*)n)); 1.146 +} 1.147 + 1.148 +/* PRINTF FUNCTIONS */ 1.149 + 1.150 +#ifdef va_copy 1.151 +#define UCX_PRINTF_BUFSIZE 256 1.152 +#else 1.153 +#pragma message("WARNING: C99 va_copy macro not supported by this platform" \ 1.154 + " - limiting ucx_*printf to 2 KiB") 1.155 +#define UCX_PRINTF_BUFSIZE 0x800 1.156 +#endif 1.157 + 1.158 +int ucx_fprintf(void *stream, write_func wfc, const char *fmt, ...) { 1.159 + int ret; 1.160 + va_list ap; 1.161 + va_start(ap, fmt); 1.162 + ret = ucx_vfprintf(stream, wfc, fmt, ap); 1.163 + va_end(ap); 1.164 + return ret; 1.165 +} 1.166 + 1.167 +int ucx_vfprintf(void *stream, write_func wfc, const char *fmt, va_list ap) { 1.168 + char buf[UCX_PRINTF_BUFSIZE]; 1.169 +#ifdef va_copy 1.170 + va_list ap2; 1.171 + va_copy(ap2, ap); 1.172 + int ret = vsnprintf(buf, UCX_PRINTF_BUFSIZE, fmt, ap); 1.173 + if (ret < 0) { 1.174 + return ret; 1.175 + } else if (ret < UCX_PRINTF_BUFSIZE) { 1.176 + return (int)wfc(buf, 1, ret, stream); 1.177 + } else { 1.178 + if (ret == INT_MAX) { 1.179 + errno = ENOMEM; 1.180 + return -1; 1.181 + } 1.182 + 1.183 + int len = ret + 1; 1.184 + char *newbuf = (char*)malloc(len); 1.185 + if (!newbuf) { 1.186 + return -1; 1.187 + } 1.188 + 1.189 + ret = vsnprintf(newbuf, len, fmt, ap2); 1.190 + if (ret > 0) { 1.191 + ret = (int)wfc(newbuf, 1, ret, stream); 1.192 + } 1.193 + free(newbuf); 1.194 + } 1.195 + return ret; 1.196 +#else 1.197 + int ret = vsnprintf(buf, UCX_PRINTF_BUFSIZE, fmt, ap); 1.198 + if (ret < 0) { 1.199 + return ret; 1.200 + } else if (ret < UCX_PRINTF_BUFSIZE) { 1.201 + return (int)wfc(buf, 1, ret, stream); 1.202 + } else { 1.203 + errno = ENOMEM; 1.204 + return -1; 1.205 + } 1.206 +#endif 1.207 +} 1.208 + 1.209 +sstr_t ucx_asprintf(UcxAllocator *allocator, const char *fmt, ...) { 1.210 + va_list ap; 1.211 + sstr_t ret; 1.212 + va_start(ap, fmt); 1.213 + ret = ucx_vasprintf(allocator, fmt, ap); 1.214 + va_end(ap); 1.215 + return ret; 1.216 +} 1.217 + 1.218 +sstr_t ucx_vasprintf(UcxAllocator *a, const char *fmt, va_list ap) { 1.219 + sstr_t s; 1.220 + s.ptr = NULL; 1.221 + s.length = 0; 1.222 + char buf[UCX_PRINTF_BUFSIZE]; 1.223 +#ifdef va_copy 1.224 + va_list ap2; 1.225 + va_copy(ap2, ap); 1.226 + int ret = vsnprintf(buf, UCX_PRINTF_BUFSIZE, fmt, ap); 1.227 + if (ret > 0 && ret < UCX_PRINTF_BUFSIZE) { 1.228 + s.ptr = (char*)almalloc(a, ret + 1); 1.229 + if (s.ptr) { 1.230 + s.length = (size_t)ret; 1.231 + memcpy(s.ptr, buf, ret); 1.232 + s.ptr[s.length] = '\0'; 1.233 + } 1.234 + } else if (ret == INT_MAX) { 1.235 + errno = ENOMEM; 1.236 + } else { 1.237 + int len = ret + 1; 1.238 + s.ptr = (char*)almalloc(a, len); 1.239 + if (s.ptr) { 1.240 + ret = vsnprintf(s.ptr, len, fmt, ap2); 1.241 + if (ret < 0) { 1.242 + free(s.ptr); 1.243 + s.ptr = NULL; 1.244 + } else { 1.245 + s.length = (size_t)ret; 1.246 + } 1.247 + } 1.248 + } 1.249 +#else 1.250 + int ret = vsnprintf(buf, UCX_PRINTF_BUFSIZE, fmt, ap); 1.251 + if (ret > 0 && ret < UCX_PRINTF_BUFSIZE) { 1.252 + s.ptr = (char*)almalloc(a, ret + 1); 1.253 + if (s.ptr) { 1.254 + s.length = (size_t)ret; 1.255 + memcpy(s.ptr, buf, ret); 1.256 + s.ptr[s.length] = '\0'; 1.257 + } 1.258 + } else { 1.259 + errno = ENOMEM; 1.260 + } 1.261 +#endif 1.262 + return s; 1.263 +}