--- a/ucx/printf.c Mon Jan 22 17:27:47 2024 +0100 +++ b/ucx/printf.c Sat Jan 27 17:50:19 2024 +0100 @@ -34,6 +34,7 @@ #ifndef CX_PRINTF_SBO_SIZE #define CX_PRINTF_SBO_SIZE 512 #endif +unsigned const cx_printf_sbo_size = CX_PRINTF_SBO_SIZE; int cx_fprintf( void *stream, @@ -60,17 +61,21 @@ va_copy(ap2, ap); int ret = vsnprintf(buf, CX_PRINTF_SBO_SIZE, fmt, ap); if (ret < 0) { + va_end(ap2); return ret; } else if (ret < CX_PRINTF_SBO_SIZE) { + va_end(ap2); return (int) wfc(buf, 1, ret, stream); } else { int len = ret + 1; char *newbuf = malloc(len); if (!newbuf) { + va_end(ap2); return -1; } ret = vsnprintf(newbuf, len, fmt, ap2); + va_end(ap2); if (ret > 0) { ret = (int) wfc(newbuf, 1, ret, stream); } @@ -85,9 +90,8 @@ ... ) { va_list ap; - cxmutstr ret; va_start(ap, fmt); - ret = cx_vasprintf_a(allocator, fmt, ap); + cxmutstr ret = cx_vasprintf_a(allocator, fmt, ap); va_end(ap); return ret; } @@ -104,7 +108,7 @@ 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) { + if (ret >= 0 && ret < CX_PRINTF_SBO_SIZE) { s.ptr = cxMalloc(a, ret + 1); if (s.ptr) { s.length = (size_t) ret; @@ -124,6 +128,65 @@ } } } + va_end(ap2); return s; } +int cx_sprintf_a(CxAllocator *alloc, char **str, size_t len, const char *fmt, ... ) { + va_list ap; + va_start(ap, fmt); + int ret = cx_vsprintf_a(alloc, str, len, fmt, ap); + va_end(ap); + return ret; +} + +int cx_vsprintf_a(CxAllocator *alloc, char **str, size_t len, const char *fmt, va_list ap) { + va_list ap2; + va_copy(ap2, ap); + int ret = vsnprintf(*str, len, fmt, ap); + if ((unsigned) ret >= len) { + unsigned newlen = ret + 1; + char *ptr = cxRealloc(alloc, *str, newlen); + if (ptr) { + int newret = vsnprintf(ptr, newlen, fmt, ap2); + if (newret < 0) { + cxFree(alloc, ptr); + } else { + *str = ptr; + ret = newret; + } + } + } + va_end(ap2); + return ret; +} + +int cx_sprintf_sa(CxAllocator *alloc, char *buf, size_t len, char **str, const char *fmt, ... ) { + va_list ap; + va_start(ap, fmt); + int ret = cx_vsprintf_sa(alloc, buf, len, str, fmt, ap); + va_end(ap); + return ret; +} + +int cx_vsprintf_sa(CxAllocator *alloc, char *buf, size_t len, char **str, const char *fmt, va_list ap) { + va_list ap2; + va_copy(ap2, ap); + int ret = vsnprintf(buf, len, fmt, ap); + *str = buf; + if ((unsigned) ret >= len) { + unsigned newlen = ret + 1; + char *ptr = cxMalloc(alloc, newlen); + if (ptr) { + int newret = vsnprintf(ptr, newlen, fmt, ap2); + if (newret < 0) { + cxFree(alloc, ptr); + } else { + *str = ptr; + ret = newret; + } + } + } + va_end(ap2); + return ret; +}