#include "utils.h"
#include <math.h>
#include <stdio.h>
#include <limits.h>
#include <errno.h>
void* ucx_strcpy(
void* s,
void* data) {
char *str = (
char*) s;
size_t n =
1+strlen(str);
char *cpy = (
char*) malloc(n);
memcpy(cpy, str, n);
return cpy;
}
void* ucx_memcpy(
void* m,
void* n) {
size_t k = *((
size_t*)n);
void *cpy = malloc(k);
memcpy(cpy, m, k);
return cpy;
}
size_t ucx_stream_bncopy(
void *src,
void *dest, read_func readfnc,
write_func writefnc,
char* buf,
size_t bufsize,
size_t n) {
if(n ==
0 || bufsize ==
0) {
return 0;
}
char *lbuf;
size_t ncp =
0;
if(buf) {
lbuf = buf;
}
else {
lbuf = (
char*)malloc(bufsize);
if(lbuf ==
NULL) {
return 0;
}
}
size_t r;
size_t rn = bufsize > n ? n : bufsize;
while((r = readfnc(lbuf,
1, rn, src)) !=
0) {
r = writefnc(lbuf,
1, r, dest);
ncp += r;
n -= r;
rn = bufsize > n ? n : bufsize;
if(r ==
0 || n ==
0) {
break;
}
}
if (lbuf != buf) {
free(lbuf);
}
return ncp;
}
int ucx_strcmp(
void *s1,
void *s2,
void *data) {
return strcmp((
char*)s1, (
char*)s2);
}
int ucx_strncmp(
void *s1,
void *s2,
void *n) {
return strncmp((
char*)s1, (
char*)s2, *((
size_t*) n));
}
int ucx_intcmp(
void *i1,
void *i2,
void *data) {
int a = *((
int*) i1);
int b = *((
int*) i2);
if (a == b) {
return 0;
}
else {
return a < b ? -
1 :
1;
}
}
int ucx_floatcmp(
void *f1,
void *f2,
void *epsilon) {
float a = *((
float*) f1);
float b = *((
float*) f2);
float e = !epsilon ? 1e-6f : *((
float*)epsilon);
if (fabsf(a - b) < e) {
return 0;
}
else {
return a < b ? -
1 :
1;
}
}
int ucx_doublecmp(
void *d1,
void *d2,
void *epsilon) {
double a = *((
float*) d1);
double b = *((
float*) d2);
double e = !epsilon ? 1e-
14 : *((
double*)epsilon);
if (fabs(a - b) < e) {
return 0;
}
else {
return a < b ? -
1 :
1;
}
}
int ucx_ptrcmp(
void *ptr1,
void *ptr2,
void *data) {
intptr_t p1 = (
intptr_t) ptr1;
intptr_t p2 = (
intptr_t) ptr2;
if (p1 == p2) {
return 0;
}
else {
return p1 < p2 ? -
1 :
1;
}
}
int ucx_memcmp(
void *ptr1,
void *ptr2,
void *n) {
return memcmp(ptr1, ptr2, *((
size_t*)n));
}
#ifdef va_copy
#define UCX_PRINTF_BUFSIZE 256
#else
#pragma message(
"WARNING: C99 va_copy macro not supported by this platform" \
" - limiting ucx_*printf to 2 KiB")
#define UCX_PRINTF_BUFSIZE 0x800
#endif
int ucx_fprintf(
void *stream, write_func wfc,
const char *fmt, ...) {
int ret;
va_list ap;
va_start(ap, fmt);
ret = ucx_vfprintf(stream, wfc, fmt, ap);
va_end(ap);
return ret;
}
int ucx_vfprintf(
void *stream, write_func wfc,
const char *fmt, va_list ap) {
char buf[
UCX_PRINTF_BUFSIZE];
#ifdef va_copy
va_list ap2;
va_copy(ap2, ap);
int ret = vsnprintf(buf,
UCX_PRINTF_BUFSIZE, fmt, ap);
if (ret <
0) {
return ret;
}
else if (ret <
UCX_PRINTF_BUFSIZE) {
return (
int)wfc(buf,
1, ret, stream);
}
else {
if (ret ==
INT_MAX) {
errno =
ENOMEM;
return -
1;
}
int len = ret +
1;
char *newbuf = (
char*)malloc(len);
if (!newbuf) {
return -
1;
}
ret = vsnprintf(newbuf, len, fmt, ap2);
if (ret >
0) {
ret = (
int)wfc(newbuf,
1, ret, stream);
}
free(newbuf);
}
return ret;
#else
int ret = vsnprintf(buf,
UCX_PRINTF_BUFSIZE, fmt, ap);
if (ret <
0) {
return ret;
}
else if (ret <
UCX_PRINTF_BUFSIZE) {
return (
int)wfc(buf,
1, ret, stream);
}
else {
errno =
ENOMEM;
return -
1;
}
#endif
}
sstr_t ucx_asprintf(UcxAllocator *allocator,
const char *fmt, ...) {
va_list ap;
sstr_t ret;
va_start(ap, fmt);
ret = ucx_vasprintf(allocator, fmt, ap);
va_end(ap);
return ret;
}
sstr_t ucx_vasprintf(UcxAllocator *a,
const char *fmt, va_list ap) {
sstr_t s;
s.ptr =
NULL;
s.length =
0;
char buf[
UCX_PRINTF_BUFSIZE];
#ifdef va_copy
va_list ap2;
va_copy(ap2, ap);
int ret = vsnprintf(buf,
UCX_PRINTF_BUFSIZE, fmt, ap);
if (ret >
0 && ret <
UCX_PRINTF_BUFSIZE) {
s.ptr = (
char*)almalloc(a, ret +
1);
if (s.ptr) {
s.length = (
size_t)ret;
memcpy(s.ptr, buf, ret);
s.ptr[s.length] =
'\0';
}
}
else if (ret ==
INT_MAX) {
errno =
ENOMEM;
}
else {
int len = ret +
1;
s.ptr = (
char*)almalloc(a, len);
if (s.ptr) {
ret = vsnprintf(s.ptr, len, fmt, ap2);
if (ret <
0) {
free(s.ptr);
s.ptr =
NULL;
}
else {
s.length = (
size_t)ret;
}
}
}
#else
int ret = vsnprintf(buf,
UCX_PRINTF_BUFSIZE, fmt, ap);
if (ret >
0 && ret <
UCX_PRINTF_BUFSIZE) {
s.ptr = (
char*)almalloc(a, ret +
1);
if (s.ptr) {
s.length = (
size_t)ret;
memcpy(s.ptr, buf, ret);
s.ptr[s.length] =
'\0';
}
}
else {
errno =
ENOMEM;
}
#endif
return s;
}