UNIXworkcode

1 /* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 * 4 * Copyright 2016 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 "utils.h" 30 #include <math.h> 31 #include <stdio.h> 32 #include <limits.h> 33 #include <errno.h> 34 35 /* COPY FUCNTIONS */ 36 void* ucx_strcpy(void* s, void* data) { 37 char *str = (char*) s; 38 size_t n = 1+strlen(str); 39 char *cpy = (char*) malloc(n); 40 memcpy(cpy, str, n); 41 return cpy; 42 } 43 44 void* ucx_memcpy(void* m, void* n) { 45 size_t k = *((size_t*)n); 46 void *cpy = malloc(k); 47 memcpy(cpy, m, k); 48 return cpy; 49 } 50 51 size_t ucx_stream_bncopy(void *src, void *dest, read_func readfnc, 52 write_func writefnc, char* buf, size_t bufsize, size_t n) { 53 if(n == 0 || bufsize == 0) { 54 return 0; 55 } 56 57 char *lbuf; 58 size_t ncp = 0; 59 60 if(buf) { 61 lbuf = buf; 62 } else { 63 lbuf = (char*)malloc(bufsize); 64 if(lbuf == NULL) { 65 return 0; 66 } 67 } 68 69 size_t r; 70 size_t rn = bufsize > n ? n : bufsize; 71 while((r = readfnc(lbuf, 1, rn, src)) != 0) { 72 r = writefnc(lbuf, 1, r, dest); 73 ncp += r; 74 n -= r; 75 rn = bufsize > n ? n : bufsize; 76 if(r == 0 || n == 0) { 77 break; 78 } 79 } 80 81 if (lbuf != buf) { 82 free(lbuf); 83 } 84 85 return ncp; 86 } 87 88 /* COMPARE FUNCTIONS */ 89 90 int ucx_strcmp(void *s1, void *s2, void *data) { 91 return strcmp((char*)s1, (char*)s2); 92 } 93 94 int ucx_strncmp(void *s1, void *s2, void *n) { 95 return strncmp((char*)s1, (char*)s2, *((size_t*) n)); 96 } 97 98 int ucx_intcmp(void *i1, void *i2, void *data) { 99 int a = *((int*) i1); 100 int b = *((int*) i2); 101 if (a == b) { 102 return 0; 103 } else { 104 return a < b ? -1 : 1; 105 } 106 } 107 108 int ucx_floatcmp(void *f1, void *f2, void *epsilon) { 109 float a = *((float*) f1); 110 float b = *((float*) f2); 111 float e = !epsilon ? 1e-6f : *((float*)epsilon); 112 if (fabsf(a - b) < e) { 113 return 0; 114 } else { 115 return a < b ? -1 : 1; 116 } 117 } 118 119 int ucx_doublecmp(void *d1, void *d2, void *epsilon) { 120 double a = *((float*) d1); 121 double b = *((float*) d2); 122 double e = !epsilon ? 1e-14 : *((double*)epsilon); 123 if (fabs(a - b) < e) { 124 return 0; 125 } else { 126 return a < b ? -1 : 1; 127 } 128 } 129 130 int ucx_ptrcmp(void *ptr1, void *ptr2, void *data) { 131 intptr_t p1 = (intptr_t) ptr1; 132 intptr_t p2 = (intptr_t) ptr2; 133 if (p1 == p2) { 134 return 0; 135 } else { 136 return p1 < p2 ? -1 : 1; 137 } 138 } 139 140 int ucx_memcmp(void *ptr1, void *ptr2, void *n) { 141 return memcmp(ptr1, ptr2, *((size_t*)n)); 142 } 143 144 /* PRINTF FUNCTIONS */ 145 146 #ifdef va_copy 147 #define UCX_PRINTF_BUFSIZE 256 148 #else 149 #pragma message("WARNING: C99 va_copy macro not supported by this platform" \ 150 " - limiting ucx_*printf to 2 KiB") 151 #define UCX_PRINTF_BUFSIZE 0x800 152 #endif 153 154 int ucx_fprintf(void *stream, write_func wfc, const char *fmt, ...) { 155 int ret; 156 va_list ap; 157 va_start(ap, fmt); 158 ret = ucx_vfprintf(stream, wfc, fmt, ap); 159 va_end(ap); 160 return ret; 161 } 162 163 int ucx_vfprintf(void *stream, write_func wfc, const char *fmt, va_list ap) { 164 char buf[UCX_PRINTF_BUFSIZE]; 165 #ifdef va_copy 166 va_list ap2; 167 va_copy(ap2, ap); 168 int ret = vsnprintf(buf, UCX_PRINTF_BUFSIZE, fmt, ap); 169 if (ret < 0) { 170 return ret; 171 } else if (ret < UCX_PRINTF_BUFSIZE) { 172 return (int)wfc(buf, 1, ret, stream); 173 } else { 174 if (ret == INT_MAX) { 175 errno = ENOMEM; 176 return -1; 177 } 178 179 int len = ret + 1; 180 char *newbuf = (char*)malloc(len); 181 if (!newbuf) { 182 return -1; 183 } 184 185 ret = vsnprintf(newbuf, len, fmt, ap2); 186 if (ret > 0) { 187 ret = (int)wfc(newbuf, 1, ret, stream); 188 } 189 free(newbuf); 190 } 191 return ret; 192 #else 193 int ret = vsnprintf(buf, UCX_PRINTF_BUFSIZE, fmt, ap); 194 if (ret < 0) { 195 return ret; 196 } else if (ret < UCX_PRINTF_BUFSIZE) { 197 return (int)wfc(buf, 1, ret, stream); 198 } else { 199 errno = ENOMEM; 200 return -1; 201 } 202 #endif 203 } 204 205 sstr_t ucx_asprintf(UcxAllocator *allocator, const char *fmt, ...) { 206 va_list ap; 207 sstr_t ret; 208 va_start(ap, fmt); 209 ret = ucx_vasprintf(allocator, fmt, ap); 210 va_end(ap); 211 return ret; 212 } 213 214 sstr_t ucx_vasprintf(UcxAllocator *a, const char *fmt, va_list ap) { 215 sstr_t s; 216 s.ptr = NULL; 217 s.length = 0; 218 char buf[UCX_PRINTF_BUFSIZE]; 219 #ifdef va_copy 220 va_list ap2; 221 va_copy(ap2, ap); 222 int ret = vsnprintf(buf, UCX_PRINTF_BUFSIZE, fmt, ap); 223 if (ret > 0 && ret < UCX_PRINTF_BUFSIZE) { 224 s.ptr = (char*)almalloc(a, ret + 1); 225 if (s.ptr) { 226 s.length = (size_t)ret; 227 memcpy(s.ptr, buf, ret); 228 s.ptr[s.length] = '\0'; 229 } 230 } else if (ret == INT_MAX) { 231 errno = ENOMEM; 232 } else { 233 int len = ret + 1; 234 s.ptr = (char*)almalloc(a, len); 235 if (s.ptr) { 236 ret = vsnprintf(s.ptr, len, fmt, ap2); 237 if (ret < 0) { 238 free(s.ptr); 239 s.ptr = NULL; 240 } else { 241 s.length = (size_t)ret; 242 } 243 } 244 } 245 #else 246 int ret = vsnprintf(buf, UCX_PRINTF_BUFSIZE, fmt, ap); 247 if (ret > 0 && ret < UCX_PRINTF_BUFSIZE) { 248 s.ptr = (char*)almalloc(a, ret + 1); 249 if (s.ptr) { 250 s.length = (size_t)ret; 251 memcpy(s.ptr, buf, ret); 252 s.ptr[s.length] = '\0'; 253 } 254 } else { 255 errno = ENOMEM; 256 } 257 #endif 258 return s; 259 } 260