#include "ucx/utils.h"
#include <math.h>
#include <stdio.h>
#include <limits.h>
#include <errno.h>
void* ucx_strcpy(
const void* s,
void* data) {
const char *str = (
const char*) s;
size_t n =
1+strlen(str);
char *cpy = (
char*) malloc(n);
memcpy(cpy, str, n);
return cpy;
}
void* ucx_memcpy(
const 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_cmp_str(
const void *s1,
const void *s2,
void *data) {
return strcmp((
const char*)s1, (
const char*)s2);
}
int ucx_cmp_strn(
const void *s1,
const void *s2,
void *n) {
return strncmp((
const char*)s1, (
const char*)s2, *((
size_t*) n));
}
int ucx_cmp_sstr(
const void *s1,
const void *s2,
void *data) {
sstr_t a = *(
const sstr_t*) s1;
sstr_t b = *(
const sstr_t*) s2;
return sstrcmp(a, b);
}
int ucx_cmp_int(
const void *i1,
const void *i2,
void *data) {
int a = *((
const int*) i1);
int b = *((
const int*) i2);
if (a == b) {
return 0;
}
else {
return a < b ? -
1 :
1;
}
}
int ucx_cmp_longint(
const void *i1,
const void *i2,
void *data) {
long int a = *((
const long int*) i1);
long int b = *((
const long int*) i2);
if (a == b) {
return 0;
}
else {
return a < b ? -
1 :
1;
}
}
int ucx_cmp_longlong(
const void *i1,
const void *i2,
void *data) {
long long a = *((
const long long*) i1);
long long b = *((
const long long*) i2);
if (a == b) {
return 0;
}
else {
return a < b ? -
1 :
1;
}
}
int ucx_cmp_int16(
const void *i1,
const void *i2,
void *data) {
int16_t a = *((
const int16_t*) i1);
int16_t b = *((
const int16_t*) i2);
if (a == b) {
return 0;
}
else {
return a < b ? -
1 :
1;
}
}
int ucx_cmp_int32(
const void *i1,
const void *i2,
void *data) {
int32_t a = *((
const int32_t*) i1);
int32_t b = *((
const int32_t*) i2);
if (a == b) {
return 0;
}
else {
return a < b ? -
1 :
1;
}
}
int ucx_cmp_int64(
const void *i1,
const void *i2,
void *data) {
int64_t a = *((
const int64_t*) i1);
int64_t b = *((
const int64_t*) i2);
if (a == b) {
return 0;
}
else {
return a < b ? -
1 :
1;
}
}
int ucx_cmp_uint(
const void *i1,
const void *i2,
void *data) {
unsigned int a = *((
const unsigned int*) i1);
unsigned int b = *((
const unsigned int*) i2);
if (a == b) {
return 0;
}
else {
return a < b ? -
1 :
1;
}
}
int ucx_cmp_ulongint(
const void *i1,
const void *i2,
void *data) {
unsigned long int a = *((
const unsigned long int*) i1);
unsigned long int b = *((
const unsigned long int*) i2);
if (a == b) {
return 0;
}
else {
return a < b ? -
1 :
1;
}
}
int ucx_cmp_ulonglong(
const void *i1,
const void *i2,
void *data) {
unsigned long long a = *((
const unsigned long long*) i1);
unsigned long long b = *((
const unsigned long long*) i2);
if (a == b) {
return 0;
}
else {
return a < b ? -
1 :
1;
}
}
int ucx_cmp_uint16(
const void *i1,
const void *i2,
void *data) {
uint16_t a = *((
const uint16_t*) i1);
uint16_t b = *((
const uint16_t*) i2);
if (a == b) {
return 0;
}
else {
return a < b ? -
1 :
1;
}
}
int ucx_cmp_uint32(
const void *i1,
const void *i2,
void *data) {
uint32_t a = *((
const uint32_t*) i1);
uint32_t b = *((
const uint32_t*) i2);
if (a == b) {
return 0;
}
else {
return a < b ? -
1 :
1;
}
}
int ucx_cmp_uint64(
const void *i1,
const void *i2,
void *data) {
uint64_t a = *((
const uint64_t*) i1);
uint64_t b = *((
const uint64_t*) i2);
if (a == b) {
return 0;
}
else {
return a < b ? -
1 :
1;
}
}
intmax_t ucx_dist_int(
const void *i1,
const void *i2,
void *data) {
intmax_t a = *((
const int*) i1);
intmax_t b = *((
const int*) i2);
return a - b;
}
intmax_t ucx_dist_longint(
const void *i1,
const void *i2,
void *data) {
intmax_t a = *((
const long int*) i1);
intmax_t b = *((
const long int*) i2);
return a - b;
}
intmax_t ucx_dist_longlong(
const void *i1,
const void *i2,
void *data) {
intmax_t a = *((
const long long*) i1);
intmax_t b = *((
const long long*) i2);
return a - b;
}
intmax_t ucx_dist_int16(
const void *i1,
const void *i2,
void *data) {
intmax_t a = *((
const int16_t*) i1);
intmax_t b = *((
const int16_t*) i2);
return a - b;
}
intmax_t ucx_dist_int32(
const void *i1,
const void *i2,
void *data) {
intmax_t a = *((
const int32_t*) i1);
intmax_t b = *((
const int32_t*) i2);
return a - b;
}
intmax_t ucx_dist_int64(
const void *i1,
const void *i2,
void *data) {
intmax_t a = *((
const int64_t*) i1);
intmax_t b = *((
const int64_t*) i2);
return a - b;
}
intmax_t ucx_dist_uint(
const void *i1,
const void *i2,
void *data) {
uintmax_t a = *((
const unsigned int*) i1);
uintmax_t b = *((
const unsigned int*) i2);
return a > b ? (
intmax_t)(a - b) : -(
intmax_t)(b - a);
}
intmax_t ucx_dist_ulongint(
const void *i1,
const void *i2,
void *data) {
uintmax_t a = *((
const unsigned long int*) i1);
uintmax_t b = *((
const unsigned long int*) i2);
return a > b ? (
intmax_t)(a - b) : -(
intmax_t)(b - a);
}
intmax_t ucx_dist_ulonglong(
const void *i1,
const void *i2,
void *data) {
uintmax_t a = *((
const unsigned long long*) i1);
uintmax_t b = *((
const unsigned long long*) i2);
return a > b ? (
intmax_t)(a - b) : -(
intmax_t)(b - a);
}
intmax_t ucx_dist_uint16(
const void *i1,
const void *i2,
void *data) {
uintmax_t a = *((
const uint16_t*) i1);
uintmax_t b = *((
const uint16_t*) i2);
return a > b ? (
intmax_t)(a - b) : -(
intmax_t)(b - a);
}
intmax_t ucx_dist_uint32(
const void *i1,
const void *i2,
void *data) {
uintmax_t a = *((
const uint32_t*) i1);
uintmax_t b = *((
const uint32_t*) i2);
return a > b ? (
intmax_t)(a - b) : -(
intmax_t)(b - a);
}
intmax_t ucx_dist_uint64(
const void *i1,
const void *i2,
void *data) {
uintmax_t a = *((
const uint64_t*) i1);
uintmax_t b = *((
const uint64_t*) i2);
return a > b ? (
intmax_t)(a - b) : -(
intmax_t)(b - a);
}
int ucx_cmp_float(
const void *f1,
const void *f2,
void *epsilon) {
float a = *((
const float*) f1);
float b = *((
const float*) f2);
float e = !epsilon ? 1e-6f : *((
float*)epsilon);
if (fabsf(a - b) < e) {
return 0;
}
else {
return a < b ? -
1 :
1;
}
}
int ucx_cmp_double(
const void *d1,
const void *d2,
void *epsilon) {
double a = *((
const double*) d1);
double b = *((
const double*) d2);
double e = !epsilon ? 1e-
14 : *((
double*)epsilon);
if (fabs(a - b) < e) {
return 0;
}
else {
return a < b ? -
1 :
1;
}
}
int ucx_cmp_ptr(
const void *ptr1,
const void *ptr2,
void *data) {
const intptr_t p1 = (
const intptr_t) ptr1;
const intptr_t p2 = (
const intptr_t) ptr2;
if (p1 == p2) {
return 0;
}
else {
return p1 < p2 ? -
1 :
1;
}
}
int ucx_cmp_mem(
const void *ptr1,
const 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;
}