diff --git a/libmaxsi/c/hsrc/stdio.h b/libmaxsi/c/hsrc/stdio.h index 5b95fc34..e6179e60 100644 --- a/libmaxsi/c/hsrc/stdio.h +++ b/libmaxsi/c/hsrc/stdio.h @@ -100,8 +100,12 @@ extern int putc(int c, FILE* stream); extern int putchar(int c); extern int remove(const char* path); extern void rewind(FILE* stream); +extern int snprintf(char* restrict s, size_t n, const char* restrict format, ...); +extern int sprintf(char* restrict s, const char* restrict format, ...); extern int vfprintf(FILE* restrict stream, const char* restrict format, va_list ap); extern int vprintf(const char* restrict format, va_list ap); +extern int vsnprintf(char* restrict, size_t, const char* restrict, va_list); +extern int vsprintf(char* restrict s, const char* restrict format, va_list ap); /* TODO: These are not implemented in libmaxsi/sortix yet. */ #ifndef SORTIX_UNIMPLEMENTED @@ -128,15 +132,11 @@ extern int rename(const char* oldname, const char* newname); extern int renameat(int oldfd, const char* oldname, int newfd, const char* newname); extern int scanf(const char* restrict format, ...); extern int setvbuf(FILE* restrict stream, char* restrict buf, int type, size_t size); -extern int snprintf(char* restrict s, size_t n, const char* restrict format, ...); -extern int sprintf(char* restrict s, const char* restrict format, ...); extern int sscanf(const char* restrict s, const char* restrict format, ...); extern int ungetc(int c, FILE* stream); extern int vdprintf(int fildes, const char* restrict format, va_list ap); extern int vfscanf(FILE* restrict stream, const char* restrict format, va_list arg); extern int vscanf(const char* restrict format, va_list arg); -extern int vsnprintf(char* restrict, size_t, const char* restrict, va_list); -extern int vsprintf(char* restrict s, const char* restrict format, va_list ap); extern int vsscanf(const char* restrict s, const char* restrict format, va_list arg); extern ssize_t getdelim(char** restrict lineptr, size_t* restrict n, int delimiter, FILE* restrict stream); extern ssize_t getline(char** restrict lineptr, size_t* restrict n, FILE* restrict stream); diff --git a/libmaxsi/io.cpp b/libmaxsi/io.cpp index 0dec9a8a..4963edef 100644 --- a/libmaxsi/io.cpp +++ b/libmaxsi/io.cpp @@ -27,6 +27,7 @@ #include "io.h" #include "format.h" #include "string.h" +#include "memory.h" #include #include #include @@ -110,6 +111,63 @@ namespace Maxsi return (int) result; } + typedef struct vsnprintf_struct + { + char* str; + size_t size; + size_t produced; + size_t written; + } vsnprintf_t; + + size_t StringPrintCallback(void* user, const char* string, size_t stringlen) + { + vsnprintf_t* info = (vsnprintf_t*) user; + if ( info->produced < info->size ) + { + size_t available = info->size - info->produced; + size_t possible = (stringlen < available) ? stringlen : available; + Memory::Copy(info->str + info->produced, string, possible); + info->written += possible; + } + info->produced += stringlen; + return stringlen; + } + + extern "C" int vsnprintf(char* restrict str, size_t size, const char* restrict format, va_list list) + { + vsnprintf_t info; + info.str = str; + info.size = (size) ? size-1 : 0; + info.produced = 0; + info.written = 0; + Maxsi::Format::Virtual(StringPrintCallback, &info, format, list); + if ( size ) { info.str[info.written] = '\0'; } + return (int) info.produced; + } + + extern "C" int snprintf(char* restrict str, size_t size, const char* restrict format, ...) + { + va_list list; + va_start(list, format); + int result = vsnprintf(str, size, format, list); + va_end(list); + return result; + } + + extern "C" int vsprintf(char* restrict str, const char* restrict format, va_list list) + { + return vsnprintf(str, SIZE_MAX, format, list); + } + + extern "C" int sprintf(char* restrict str, const char* restrict format, ...) + { + va_list list; + va_start(list, format); + int result = vsprintf(str, format, list); + va_end(list); + return result; + } + extern "C" void error(int status, int errnum, const char *format, ...) { fprintf(stderr, "%s: ", program_invocation_name);