diff --git a/CMakeLists.txt b/CMakeLists.txt index 2bd8fbbaa..5359ee9e6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -81,6 +81,7 @@ cmake_dependent_option(ENABLE_LIBZFS "Enable libzfs" ON "LINUX OR FreeBSD OR Sun option(ENABLE_SYSTEM_YYJSON "Use system provided (instead of fastfetch embedded) yyjson library" OFF) option(ENABLE_ASAN "Build fastfetch with ASAN (address sanitizer)" OFF) option(ENABLE_LTO "Enable link-time optimization in release mode if supported" ON) +option(ENABLE_STBPRINTF "Enable stb_printf" OFF) option(BUILD_TESTS "Build tests" OFF) # Also create test executables option(SET_TWEAK "Add tweak to project version" ON) # This is set to off by github actions for release builds option(IS_MUSL "Build with musl libc" OFF) # Used by Github Actions @@ -1052,6 +1053,10 @@ elseif(SunOS) ) endif() +if(ENABLE_STBPRINTF) + list(APPEND LIBFASTFETCH_SRC src/util/stb_printf.c) +endif() + if(ENABLE_DIRECTX_HEADERS) message(STATUS "Enabling DirectX headers for WSL") list(APPEND LIBFASTFETCH_SRC src/detection/gpu/gpu_wsl.cpp) @@ -1092,6 +1097,10 @@ add_library(libfastfetch OBJECT ${LIBFASTFETCH_SRC} ) +if(ENABLE_STBPRINTF) + target_compile_definitions(libfastfetch PUBLIC FF_USE_STBPRINTF) +endif() + if(yyjson_FOUND) target_compile_definitions(libfastfetch PUBLIC FF_USE_SYSTEM_YYJSON) target_link_libraries(libfastfetch PUBLIC yyjson::yyjson) diff --git a/src/3rdparty/stb/stb_sprintf.h b/src/3rdparty/stb/stb_sprintf.h index 70ed4e0e4..7e9d5e78c 100644 --- a/src/3rdparty/stb/stb_sprintf.h +++ b/src/3rdparty/stb/stb_sprintf.h @@ -591,7 +591,7 @@ STBSP__PUBLICDEF int STB_SPRINTF_DECORATE(vsprintfcb)(STBSP_SPRINTFCB *callback, s = (char *)"null"; // get the length, limited to desired precision // always limit to ~0u chars since our counts are 32b - l = stbsp__strlen_limited(s, (pr >= 0) ? pr : ~0u); + l = stbsp__strlen_limited(s, (pr >= 0) ? (unsigned) pr : ~0u); lead[0] = 0; tail[0] = 0; pr = 0; @@ -695,7 +695,7 @@ STBSP__PUBLICDEF int STB_SPRINTF_DECORATE(vsprintfcb)(STBSP_SPRINTFCB *callback, n = (dp >= 1000) ? 6 : ((dp >= 100) ? 5 : ((dp >= 10) ? 4 : 3)); tail[0] = (char)n; for (;;) { - tail[n] = '0' + dp % 10; + tail[n] = (char)('0' + dp % 10); if (n <= 3) break; --n; @@ -793,7 +793,7 @@ STBSP__PUBLICDEF int STB_SPRINTF_DECORATE(vsprintfcb)(STBSP_SPRINTFCB *callback, #endif tail[0] = (char)n; for (;;) { - tail[n] = '0' + dp % 10; + tail[n] = (char)('0' + dp % 10); if (n <= 3) break; --n; @@ -1431,7 +1431,7 @@ STBSP__PUBLICDEF int STB_SPRINTF_DECORATE( vsnprintf )( char * buf, int count, c { stbsp__context c; - if ( (count == 0) && !buf ) + if ( count == 0 ) { c.length = 0; diff --git a/src/common/init.c b/src/common/init.c index 96117c66e..f27052fdb 100644 --- a/src/common/init.c +++ b/src/common/init.c @@ -266,6 +266,9 @@ void ffListFeatures(void) #if FF_HAVE_EMBEDDED_PCIIDS "Embedded pciids\n" #endif + #if FF_USE_STBPRINTF + "stb_printf\n" + #endif "" , stdout); } diff --git a/src/common/time.h b/src/common/time.h index 588ba7847..76bdcc094 100644 --- a/src/common/time.h +++ b/src/common/time.h @@ -9,6 +9,8 @@ #include #endif +#include "util/stb_printf.h" + static inline double ffTimeGetTick(void) //In msec { #ifdef _WIN32 diff --git a/src/util/FFstrbuf.c b/src/util/FFstrbuf.c index 4387a5d7b..21c722fae 100644 --- a/src/util/FFstrbuf.c +++ b/src/util/FFstrbuf.c @@ -20,8 +20,15 @@ void ffStrbufInitVF(FFstrbuf* strbuf, const char* format, va_list arguments) { assert(format != NULL); + #ifndef FF_USE_STBPRINTF int len = vasprintf(&strbuf->chars, format, arguments); assert(len >= 0); + #else + int len = vsnprintf(NULL, 0, format, arguments); + assert(len >= 0); + strbuf->chars = (char*) malloc(sizeof(char) * (len + 1)); + vsnprintf(strbuf->chars, len + 1, format, arguments); + #endif strbuf->allocated = (uint32_t)(len + 1); strbuf->length = (uint32_t)len; diff --git a/src/util/FFstrbuf.h b/src/util/FFstrbuf.h index fa4a9da87..243437e9d 100644 --- a/src/util/FFstrbuf.h +++ b/src/util/FFstrbuf.h @@ -18,6 +18,8 @@ #define FASTFETCH_STRBUF_DEFAULT_ALLOC 32 +#include "stb_printf.h" + typedef struct FFstrbuf { uint32_t allocated; diff --git a/src/util/stb_printf.c b/src/util/stb_printf.c new file mode 100644 index 000000000..0f5212efb --- /dev/null +++ b/src/util/stb_printf.c @@ -0,0 +1,3 @@ +#define STB_SPRINTF_IMPLEMENTATION 1 +#pragma GCC diagnostic ignored "-Wsign-conversion" +#include "3rdparty/stb/stb_sprintf.h" diff --git a/src/util/stb_printf.h b/src/util/stb_printf.h new file mode 100644 index 000000000..62250d171 --- /dev/null +++ b/src/util/stb_printf.h @@ -0,0 +1,50 @@ +#pragma once + +#ifdef FF_USE_STBPRINTF + +#include +#include +#include "3rdparty/stb/stb_sprintf.h" + +static inline char *STB_SPRINTF_DECORATE(printf_callback)(const char* __restrict buf, void* __restrict user, int len) +{ + fwrite(buf, 1, (uint32_t) len, (FILE *)user); + return (char *) buf; +} + +static inline int STB_SPRINTF_DECORATE(vfprintf)(FILE* file, char const* __restrict fmt, va_list va) +{ + char tmp[STB_SPRINTF_MIN]; + return STB_SPRINTF_DECORATE(vsprintfcb)(STB_SPRINTF_DECORATE(printf_callback), file, tmp, fmt, va); +} +#define vfprintf(...) STB_SPRINTF_DECORATE(vfprintf)(__VA_ARGS__) + +static inline int STBSP__ATTRIBUTE_FORMAT(1,2) STB_SPRINTF_DECORATE(printf)(char const* __restrict fmt, ...) +{ + va_list va; + va_start(va, fmt); + int result = STB_SPRINTF_DECORATE(vfprintf)(stdout, fmt, va); + va_end(va); + return result; +} +#define printf(...) STB_SPRINTF_DECORATE(printf)(__VA_ARGS__) + +static inline int STBSP__ATTRIBUTE_FORMAT(2,3) STB_SPRINTF_DECORATE(fprintf)(FILE* __restrict file, char const* __restrict fmt, ...) +{ + va_list va; + va_start(va, fmt); + int result = STB_SPRINTF_DECORATE(vfprintf)(file, fmt, va); + va_end(va); + return result; +} +#define fprintf(...) STB_SPRINTF_DECORATE(fprintf)(__VA_ARGS__) + +#define vsprintf(...) STB_SPRINTF_DECORATE(vsprintf)(__VA_ARGS__) + +#define vsnprintf(...) STB_SPRINTF_DECORATE(vsnprintf)(__VA_ARGS__) + +#define sprintf(...) STB_SPRINTF_DECORATE(sprintf)(__VA_ARGS__) + +#define snprintf(...) STB_SPRINTF_DECORATE(snprintf)(__VA_ARGS__) + +#endif