From 9bc2a8587bbb9121e05cce1ef0e1822b24e03fc7 Mon Sep 17 00:00:00 2001 From: Timerix22 Date: Sat, 23 Mar 2024 01:17:46 +0500 Subject: [PATCH] ksprintf --- src/DtsodParser/DtsodV24_deserialize.c | 24 +-- src/Filesystem/dir.c | 4 +- src/Filesystem/path.c | 4 +- src/Network/network_types.c | 3 +- src/String/StringBuilder.c | 5 +- src/base/cptr.c | 9 +- src/base/cptr.h | 2 - src/base/errors.c | 17 +- src/base/std.h | 1 + src/base/type_system/base_toString.c | 5 +- src/kprint/kprintf.c | 206 ++++++++++++++++++------- src/kprint/kprintf.h | 13 +- tests/test_hashtable.c | 5 +- 13 files changed, 183 insertions(+), 115 deletions(-) diff --git a/src/DtsodParser/DtsodV24_deserialize.c b/src/DtsodParser/DtsodV24_deserialize.c index 57ac4d0..b793476 100644 --- a/src/DtsodParser/DtsodV24_deserialize.c +++ b/src/DtsodParser/DtsodV24_deserialize.c @@ -44,16 +44,10 @@ Maybe ERROR_WRONGCHAR(const char c, char* _text, char* text_first, const char* s if(!_c) break; } char errmsg[1024]; - IFMSC( - sprintf_s(errmsg,1024, "unexpected <%c> at:\n" - " \"%s\"\n" - "\\___[%s:%d] %s()", - c,errBuf, srcfile,line,funcname), - sprintf(errmsg, "unexpected <%c> at:\n" - " \"%s\"\n" - " \\___[%s:%d] %s()", - c,errBuf, srcfile,line,funcname) - ); + ksprintf(errmsg,1024, "unexpected <%c> at:\n" + " \"%s\"\n" + "\\___[%s:%d] %s()", + c,errBuf, srcfile,line,funcname); safethrow(errmsg,;); } #define safethrow_wrongchar(C, freeMem) { freeMem; return ERROR_WRONGCHAR(C, text, shared->sh_text_first, __FILE__,__LINE__,__func__); } @@ -192,10 +186,7 @@ Maybe __ParseValue(DeserializeSharedData* shared, string str){ char* _c=string_extract(str); if(sscanf(_c, IFWIN("%llu", "%lu"), &lu)!=1){ char err[64]; - IFMSC( - sprintf_s(err,64,"can't parse to int: <%s>",_c), - sprintf(err,"can't parse to int: <%s>",_c) - ); + ksprintf(err,64,"can't parse to int: <%s>",_c); safethrow(err,free(_c)); } free(_c); @@ -208,10 +199,7 @@ Maybe __ParseValue(DeserializeSharedData* shared, string str){ char* _c=string_extract(str); if(sscanf(_c, IFWIN("%lli", "%li"), &li)!=1){ char err[64]; - IFMSC( - sprintf_s(err,64,"can't parse to int: <%s>",_c), - sprintf(err,"can't parse to int: <%s>",_c) - ); + ksprintf(err,64,"can't parse to int: <%s>",_c); safethrow(err,free(_c)); } free(_c); diff --git a/src/Filesystem/dir.c b/src/Filesystem/dir.c index 812c755..63d1520 100644 --- a/src/Filesystem/dir.c +++ b/src/Filesystem/dir.c @@ -36,9 +36,7 @@ Maybe dir_create(const char* path){ #endif { char err[512]; - IFWIN( - sprintf_s(err, 512, "can't create dicectory <%s>", path), - sprintf(err, "can't create dicectory <%s>", path)); + ksprintf(err, 512, "can't create dicectory <%s>", path); safethrow(err,;); } diff --git a/src/Filesystem/path.c b/src/Filesystem/path.c index 66b15fd..afecbb9 100644 --- a/src/Filesystem/path.c +++ b/src/Filesystem/path.c @@ -25,12 +25,12 @@ char* __path_concat(u32 n, ...){ // copying content of all strings to result u16 k=0; for(; k #include #include +#include typedef int8_t i8; typedef uint8_t u8; diff --git a/src/base/type_system/base_toString.c b/src/base/type_system/base_toString.c index b63d82d..50aaa64 100644 --- a/src/base/type_system/base_toString.c +++ b/src/base/type_system/base_toString.c @@ -70,10 +70,7 @@ char* toString_u64(u64 n, bool withPostfix, bool uppercase){ throw("too big precision"); \ if(precision==0) \ precision=toString_float_default_precision; \ - i32 cn=IFMSC( \ - sprintf_s(str, bufsize, "%.*f", precision, n), \ - sprintf(str, "%.*f", precision, n) \ - ); \ + i32 cn = sprintf_s(str, bufsize, "%.*f", precision, n); \ /* remove trailing zeroes except .0*/ \ while(str[cn-1]=='0' && str[cn-2]!='.') \ cn--; \ diff --git a/src/kprint/kprintf.c b/src/kprint/kprintf.c index 0f9e0a6..e0a193a 100644 --- a/src/kprint/kprintf.c +++ b/src/kprint/kprintf.c @@ -45,111 +45,211 @@ WORD unixColorToWin(u8 c){ } #endif -void kprintf(const char* format, ...){ +i32 kprintf(const char* format, ...){ va_list vl; va_start(vl, format); - u32 i=0; - for(char c=format[i++]; c!=0; c=format[i++]){ + i32 i = 0; + for(char c = format[i++]; c != 0; c = format[i++]){ // value format specifiers - if(c=='%'){ - char* argstr=NULL; - bool l=false; - c=format[i++]; + if(c == '%'){ + char* argstr = NULL; + bool l = false; + c = format[i++]; format_escape_seq: switch (c) { case 'u': - argstr=toString_u64( + argstr = toString_u64( l ? va_arg(vl, u64) : va_arg(vl, u32) ,0,0); break; case 'i': case 'd': - argstr=toString_i64( + argstr = toString_i64( l ? va_arg(vl, i64) : va_arg(vl, i32) ); break; case 'f': // f32 is promoted to f64 when passed through '...' - argstr=toString_f64(va_arg(vl, f64), toString_float_default_precision,0,0); + argstr = toString_f64(va_arg(vl, f64), toString_float_default_precision,0,0); break; case 'l': - l=true; - if((c=format[i++])) + l = true; + if((c = format[i++])) goto format_escape_seq; break; case 'p': ; - void* phex=va_arg(vl, void*); - argstr=toString_hex(&phex,getEndian()==LittleEndian,sizeof(phex),1,0); + void* phex = va_arg(vl, void*); + argstr = toString_hex(&phex,getEndian() == LittleEndian,sizeof(phex),1,0); break; case 'x': ; if(l){ - u64 xhex=va_arg(vl, u64); - argstr=toString_hex(&xhex,getEndian()==LittleEndian,sizeof(xhex),0,1); + u64 xhex = va_arg(vl, u64); + argstr = toString_hex(&xhex,getEndian() == LittleEndian,sizeof(xhex),0,1); } else { - u32 xhex=va_arg(vl, u32); - argstr=toString_hex(&xhex,getEndian()==LittleEndian,sizeof(xhex),0,1); + u32 xhex = va_arg(vl, u32); + argstr = toString_hex(&xhex,getEndian() == LittleEndian,sizeof(xhex),0,1); } break; case 's': ; - char* cptr=va_arg(vl,char*); + char* cptr = va_arg(vl,char*); if(!cptr) - cptr=""; + cptr = ""; if(*cptr) fputs(cptr, stdout); break; case 'c': - argstr=malloc(2); - argstr[0]=(char)va_arg(vl,int); - argstr[1]=0; + putc((char)va_arg(vl,int), stdout); break; default: - putc('\n',stdout); - putc('<',stdout); - putc(c,stdout); - putc('>',stdout); - throw(ERR_FORMAT); + fputs("", stdout); + return kprintf_INVALID_FORMAT; } if(argstr){ fputs(argstr, stdout); free(argstr); } } + // escape sequences - else if(c=='\e'){ - IFWIN( - /* WINDOWS */ - ({ - if((c=format[i++])=='['){ - u8 colorUnix=0; - for(i8 n=0; n<6 && c!=0; n++){ - c=format[i++]; - switch (c){ - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - colorUnix=colorUnix*10+c-'0'; - break; - case 'm': ; - WORD colorWin=unixColorToWin(colorUnix); - HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); - SetConsoleTextAttribute(hConsole, colorWin); - goto end_iteration; - default: - goto end_iteration; - } + else if(c == '\e'){ + //////////////////// WINDOWS //////////////////// + #if defined(_WIN64) || defined(_WIN32) + if((c = format[i++]) == '['){ + u8 colorUnix = 0; + for(i8 n = 0; n<6 && c != 0; n++){ + c = format[i++]; + switch (c){ + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + colorUnix = colorUnix*10+c-'0'; + break; + case 'm': ; + WORD colorWin = unixColorToWin(colorUnix); + HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); + SetConsoleTextAttribute(hConsole, colorWin); + goto end_iteration; + default: + goto end_iteration; } } - }), - /* UNIX */ + } + ////////////////////// UNIX ////////////////////// + #else putc(c,stdout); - ); + #endif } + // common characters else { putc(c,stdout); } #if defined(_WIN64) || defined(_WIN32) - end_iteration:; + end_iteration:; #endif } va_end(vl); + return i; +} + + +i32 ksprintf(char* buffer, i32 buffer_size, const char* format, ...){ + if(buffer == NULL) + return kprintf_BUFFER_IS_NULL; + + va_list vl; + va_start(vl, format); + i32 i = 0; + i32 written = 0; + for(char c = format[i++]; c != 0; c = format[i++]){ + // value format specifiers + if(c == '%'){ + char* argstr = NULL; + bool l = false; + c = format[i++]; + format_escape_seq: + switch (c) { + case 'u': + argstr = toString_u64( + l ? va_arg(vl, u64) : va_arg(vl, u32) + ,0,0); + break; + case 'i': case 'd': + argstr = toString_i64( + l ? va_arg(vl, i64) : va_arg(vl, i32) + ); + break; + case 'f': + // f32 is promoted to f64 when passed through '...' + argstr = toString_f64(va_arg(vl, f64), toString_float_default_precision,0,0); + break; + case 'l': + l = true; + if((c = format[i++])) + goto format_escape_seq; + break; + case 'p': ; + void* phex = va_arg(vl, void*); + argstr = toString_hex(&phex,getEndian() == LittleEndian,sizeof(phex),1,0); + break; + case 'x': ; + if(l){ + u64 xhex = va_arg(vl, u64); + argstr = toString_hex(&xhex,getEndian() == LittleEndian,sizeof(xhex),0,1); + } + else { + u32 xhex = va_arg(vl, u32); + argstr = toString_hex(&xhex,getEndian() == LittleEndian,sizeof(xhex),0,1); + } + break; + case 's': ; + char* cptr = va_arg(vl,char*); + if(!cptr) + cptr = ""; + if(*cptr){ + i32 str_length = cptr_length(cptr); + if(written + str_length > buffer_size) + return kprintf_BUFFER_IS_TOO_SMALL; + + memcpy(buffer + written, cptr, str_length); + written += str_length; + } + break; + case 'c': ; + char ch = (char)va_arg(vl,int); + if(written > buffer_size) + return kprintf_BUFFER_IS_TOO_SMALL; + + buffer[written++] = ch; + break; + default: + const char errformat_str[] = ""; + if(written + (i32)sizeof(errformat_str) <= buffer_size) + memcpy(buffer + written, errformat_str, sizeof(errformat_str)); + return kprintf_INVALID_FORMAT; + } + if(argstr){ + i32 str_length = cptr_length(argstr); + if(written + str_length > buffer_size) + return kprintf_BUFFER_IS_TOO_SMALL; + + memcpy(buffer + written, argstr, str_length); + written += str_length; + free(argstr); + } + } + + // common characters + else { + if(written > buffer_size) + return kprintf_BUFFER_IS_TOO_SMALL; + + buffer[written++] = c; + } + } + + va_end(vl); + if(written > buffer_size) + return kprintf_BUFFER_IS_TOO_SMALL; + buffer[written] = '\0'; + return i; } diff --git a/src/kprint/kprintf.h b/src/kprint/kprintf.h index 56eef30..6d503de 100644 --- a/src/kprint/kprintf.h +++ b/src/kprint/kprintf.h @@ -6,8 +6,17 @@ extern "C" { #include "../base/type_system/base_toString.h" -// cross-platform printf analog -void kprintf(const char* format, ...); +#define kprintf_INVALID_FORMAT -1 +#define kprintf_BUFFER_IS_NULL -2 +#define kprintf_BUFFER_IS_TOO_SMALL -3 + +/// cross-platform printf analog +///@return number of processed format string characters or error code +i32 kprintf(const char* format, ...); + +/// @return number of processed format string characters or error code +i32 ksprintf(char* buffer, i32 buffer_size, const char* format, ...); + // printf format terminal color sequence #define _PRINTF_COLOR(N) "\e["#N"m" diff --git a/tests/test_hashtable.c b/tests/test_hashtable.c index 24e5dab..c242483 100644 --- a/tests/test_hashtable.c +++ b/tests/test_hashtable.c @@ -38,10 +38,7 @@ void printrowgraph(Hashtable* ht){ char* genkey(u32 i){ char* key=malloc(12); - IFMSC( - sprintf_s(key,12,"key_%u",i), - sprintf(key,"key_%u",i) - ); + ksprintf(key,12,"key_%u",i); return key; }