#include "cx/printf.h"
#include <stdio.h>
#include <string.h>
#ifndef CX_PRINTF_SBO_SIZE
#define CX_PRINTF_SBO_SIZE 512
#endif
int cx_fprintf(
void *stream,
cx_write_func wfc,
char const *fmt,
...
) {
int ret;
va_list ap;
va_start(ap, fmt);
ret = cx_vfprintf(stream, wfc, fmt, ap);
va_end(ap);
return ret;
}
int cx_vfprintf(
void *stream,
cx_write_func wfc,
char const *fmt,
va_list ap
) {
char buf[
CX_PRINTF_SBO_SIZE];
va_list ap2;
va_copy(ap2, ap);
int ret = vsnprintf(buf,
CX_PRINTF_SBO_SIZE, fmt, ap);
if (ret <
0) {
return ret;
}
else if (ret <
CX_PRINTF_SBO_SIZE) {
return (
int) wfc(buf,
1, ret, stream);
}
else {
int len = ret +
1;
char *newbuf = 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;
}
cxmutstr cx_asprintf_a(
CxAllocator
const *allocator,
char const *fmt,
...
) {
va_list ap;
cxmutstr ret;
va_start(ap, fmt);
ret = cx_vasprintf_a(allocator, fmt, ap);
va_end(ap);
return ret;
}
cxmutstr cx_vasprintf_a(
CxAllocator
const *a,
char const *fmt,
va_list ap
) {
cxmutstr s;
s.ptr =
NULL;
s.length =
0;
char buf[
CX_PRINTF_SBO_SIZE];
va_list ap2;
va_copy(ap2, ap);
int ret = vsnprintf(buf,
CX_PRINTF_SBO_SIZE, fmt, ap);
if (ret >
0 && ret <
CX_PRINTF_SBO_SIZE) {
s.ptr = cxMalloc(a, ret +
1);
if (s.ptr) {
s.length = (
size_t) ret;
memcpy(s.ptr, buf, ret);
s.ptr[s.length] =
'\0';
}
}
else {
int len = ret +
1;
s.ptr = cxMalloc(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;
}
}
}
return s;
}