Separate host detection and printing logic

This commit is contained in:
Linus Dierheimer
2022-09-04 12:43:30 +02:00
parent 542ad5eab6
commit d387800bda
13 changed files with 312 additions and 181 deletions
+21 -1
View File
@@ -133,7 +133,7 @@ configure_file(src/fastfetch_config.h.in fastfetch_config.h)
# libfastfetch target #
#######################
add_library(libfastfetch OBJECT
set(LIBFASTFETCH_SRC
src/util/FFstrbuf.c
src/util/FFlist.c
src/util/FFvaluestore.c
@@ -163,6 +163,7 @@ add_library(libfastfetch OBJECT
src/detection/datetime.c
src/detection/temps.c
src/detection/title.c
src/detection/host/host.c
src/detection/displayserver/displayServer.c
src/detection/displayserver/wayland.c
src/detection/displayserver/xcb.c
@@ -209,6 +210,25 @@ add_library(libfastfetch OBJECT
src/modules/opencl.c
)
if(APPLE)
list(APPEND LIBFASTFETCH_SRC
)
elseif(ANDROID)
list(APPEND LIBFASTFETCH_SRC
"src/detection/host/host_android.c"
)
elseif(UNIX)
list(APPEND LIBFASTFETCH_SRC
"src/detection/host/host_linux.c"
)
else()
message(FATAL_ERROR "Unsupported platform")
endif()
add_library(libfastfetch OBJECT
${LIBFASTFETCH_SRC}
)
if(ENABLE_LIBPCI)
pkg_check_modules(LIBPCI libpci)
if(LIBPCI_FOUND)
+2 -3
View File
@@ -352,10 +352,9 @@ int ffSettingsGetSQLite3Int(const FFinstance* instance, const char* dbPath, cons
#ifdef __ANDROID__
#include <sys/system_properties.h>
bool ffSettingsGetAndroidProperty(const char* propName, FFstrbuf* result) {
uint32_t originalLength = result->length;
void ffSettingsGetAndroidProperty(const char* propName, FFstrbuf* result) {
ffStrbufEnsureFree(result, PROP_VALUE_MAX);
result->length += (uint32_t) __system_property_get(propName, result->chars + result->length);
return result->length > originalLength;
result->chars[result->length] = '\0';
}
#endif
+1 -1
View File
@@ -33,7 +33,7 @@ FFvariant ffSettingsGetXFConf(FFinstance* instance, const char* channelName, con
int ffSettingsGetSQLite3Int(const FFinstance* instance, const char* dbPath, const char* query);
#ifdef __ANDROID__
bool ffSettingsGetAndroidProperty(const char* propName, FFstrbuf* result);
void ffSettingsGetAndroidProperty(const char* propName, FFstrbuf* result);
#endif
#endif
+25
View File
@@ -0,0 +1,25 @@
#include "host.h"
#include "pthread.h"
void ffDetectHostImpl(FFHostResult* host);
const FFHostResult* ffDetectHost()
{
static FFHostResult host;
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
static bool init = false;
pthread_mutex_lock(&mutex);
if(init)
{
pthread_mutex_unlock(&mutex);
return &host;
}
init = true;
ffDetectHostImpl(&host);
pthread_mutex_unlock(&mutex);
return &host;
}
+31
View File
@@ -0,0 +1,31 @@
#pragma once
#ifndef FF_INCLUDED_DETECTION_HOST_host
#define FF_INCLUDED_DETECTION_HOST_host
#include "fastfetch.h"
#define FF_HOST_PRODUCT_NAME_WSL "Windows Subsystem for Linux"
typedef struct FFHostResult
{
FFstrbuf productFamily;
FFstrbuf productName;
FFstrbuf productVersion;
FFstrbuf productSku;
FFstrbuf biosDate;
FFstrbuf biosRelease;
FFstrbuf biosVendor;
FFstrbuf biosVersion;
FFstrbuf boardName;
FFstrbuf boardVendor;
FFstrbuf boardVersion;
FFstrbuf chassisType;
FFstrbuf chassisVendor;
FFstrbuf chassisVersion;
FFstrbuf sysVendor;
} FFHostResult;
const FFHostResult* ffDetectHost();
#endif
+45
View File
@@ -0,0 +1,45 @@
#include "host.h"
#include <ctype.h>
void ffDetectHostImpl(FFHostResult* host)
{
//Family
ffStrbufInit(&host->productFamily);
ffSettingsGetAndroidProperty("ro.product.device", &host->productFamily);
//Name
ffStrbufInit(&host->productName);
ffSettingsGetAndroidProperty("ro.product.brand", &host->productName);
if(host->productName.length > 0){
host->productName.chars[0] = (char) toupper(host->productName.chars[0]);
ffStrbufAppendC(&host->productName, ' ');
}
ffSettingsGetAndroidProperty("ro.product.model", &host->productName);
ffStrbufTrimRight(&host->productName, ' ');
//Sys vendor
ffStrbufInit(&host->sysVendor);
ffSettingsGetAndroidProperty("ro.product.manufacturer", &host->sysVendor);
//Not implemented
ffStrbufInitA(&host->productVersion, 0);
ffStrbufInitA(&host->productSku, 0);
ffStrbufInitA(&host->biosDate, 0);
ffStrbufInitA(&host->biosRelease, 0);
ffStrbufInitA(&host->biosVendor, 0);
ffStrbufInitA(&host->biosVersion, 0);
ffStrbufInitA(&host->boardName, 0);
ffStrbufInitA(&host->boardVendor, 0);
ffStrbufInitA(&host->boardVersion, 0);
ffStrbufInitA(&host->chassisType, 0);
ffStrbufInitA(&host->chassisVendor, 0);
ffStrbufInitA(&host->chassisVersion, 0);
}
+118
View File
@@ -0,0 +1,118 @@
#include "host.h"
#include "common/io.h"
#include <stdlib.h>
static bool hostValueSet(FFstrbuf* value)
{
return
value->length > 0 &&
ffStrbufStartsWithIgnCaseS(value, "To be filled") != true &&
ffStrbufStartsWithIgnCaseS(value, "To be set") != true &&
ffStrbufStartsWithIgnCaseS(value, "OEM") != true &&
ffStrbufStartsWithIgnCaseS(value, "O.E.M.") != true &&
ffStrbufIgnCaseCompS(value, "None") != 0 &&
ffStrbufIgnCaseCompS(value, "System Product") != 0 &&
ffStrbufIgnCaseCompS(value, "System Product Name") != 0 &&
ffStrbufIgnCaseCompS(value, "System Product Version") != 0 &&
ffStrbufIgnCaseCompS(value, "System Name") != 0 &&
ffStrbufIgnCaseCompS(value, "System Version") != 0 &&
ffStrbufIgnCaseCompS(value, "Default string") != 0 &&
ffStrbufIgnCaseCompS(value, "Undefined") != 0 &&
ffStrbufIgnCaseCompS(value, "Not Specified") != 0 &&
ffStrbufIgnCaseCompS(value, "Not Applicable") != 0 &&
ffStrbufIgnCaseCompS(value, "INVALID") != 0 &&
ffStrbufIgnCaseCompS(value, "Type1ProductConfigId") != 0 &&
ffStrbufIgnCaseCompS(value, "All Series") != 0
;
}
static void getHostValue(const char* devicesPath, const char* classPath, FFstrbuf* buffer)
{
ffReadFileBuffer(devicesPath, buffer);
if(hostValueSet(buffer))
return;
ffReadFileBuffer(classPath, buffer);
if(hostValueSet(buffer))
return;
ffStrbufClear(buffer);
}
static void getHostProductName(FFstrbuf* name)
{
getHostValue("/sys/devices/virtual/dmi/id/product_name", "/sys/class/dmi/id/product_name", name);
if(name->length > 0)
return;
ffReadFileBuffer("/sys/firmware/devicetree/base/model", name);
if(hostValueSet(name))
return;
//does a clear before the read
ffReadFileBuffer("/tmp/sysinfo/model", name);
if(hostValueSet(name))
return;
ffStrbufClear(name);
}
void ffDetectHostImpl(FFHostResult* host)
{
ffStrbufInit(&host->productFamily);
getHostValue("/sys/devices/virtual/dmi/id/product_family", "/sys/class/dmi/id/product_family", &host->productFamily);
ffStrbufInit(&host->productName);
getHostProductName(&host->productName);
ffStrbufInit(&host->productVersion);
getHostValue("/sys/devices/virtual/dmi/id/product_version", "/sys/class/dmi/id/product_version", &host->productVersion);
ffStrbufInit(&host->productSku);
getHostValue("/sys/devices/virtual/dmi/id/product_sku", "/sys/class/dmi/id/product_sku", &host->productSku);
ffStrbufInit(&host->biosDate);
getHostValue("/sys/devices/virtual/dmi/id/bios_date", "/sys/class/dmi/id/bios_date", &host->biosDate);
ffStrbufInit(&host->biosRelease);
getHostValue("/sys/devices/virtual/dmi/id/bios_release", "/sys/class/dmi/id/bios_release", &host->biosRelease);
ffStrbufInit(&host->biosVendor);
getHostValue("/sys/devices/virtual/dmi/id/bios_vendor", "/sys/class/dmi/id/bios_vendor", &host->biosVendor);
ffStrbufInit(&host->biosVersion);
getHostValue("/sys/devices/virtual/dmi/id/bios_version", "/sys/class/dmi/id/bios_version", &host->biosVersion);
ffStrbufInit(&host->boardName);
getHostValue("/sys/devices/virtual/dmi/id/board_name", "/sys/class/dmi/id/board_name", &host->boardName);
ffStrbufInit(&host->boardVendor);
getHostValue("/sys/devices/virtual/dmi/id/board_vendor", "/sys/class/dmi/id/board_vendor", &host->boardVendor);
ffStrbufInit(&host->boardVersion);
getHostValue("/sys/devices/virtual/dmi/id/board_version", "/sys/class/dmi/id/board_version", &host->boardVersion);
ffStrbufInit(&host->chassisType);
getHostValue("/sys/devices/virtual/dmi/id/chassis_type", "/sys/class/dmi/id/chassis_type", &host->chassisType);
ffStrbufInit(&host->chassisVendor);
getHostValue("/sys/devices/virtual/dmi/id/chassis_vendor", "/sys/class/dmi/id/chassis_vendor", &host->chassisVendor);
ffStrbufInit(&host->chassisVersion);
getHostValue("/sys/devices/virtual/dmi/id/chassis_version", "/sys/class/dmi/id/chassis_version", &host->chassisVersion);
ffStrbufInit(&host->sysVendor);
getHostValue("/sys/devices/virtual/dmi/id/sys_vendor", "/sys/class/dmi/id/sys_vendor", &host->sysVendor);
//KVM/Qemu virtual machine
if(ffStrbufStartsWithS(&host->productName, "Standard PC"))
ffStrbufPrependS(&host->productName, "KVM/QEMU ");
//On WSL, the real host can't be detected. Instead use WSL as host.
if(host->productFamily.length == 0 && host->productName.length == 0 && (
getenv("WSLENV") != NULL ||
getenv("WSL_DISTRO") != NULL ||
getenv("WSL_INTEROP") != NULL
)) ffStrbufAppendS(&host->productName, FF_HOST_PRODUCT_NAME_WSL);
}
+1 -1
View File
@@ -37,7 +37,7 @@ const FFlogo* ffLogoBuiltinGetUnknown()
static const FFlogo* getLogoNone()
{
FF_LOGO_INIT
FF_LOGO_NAMES("none", "empty", "")
FF_LOGO_NAMES("none", "empty")
FF_LOGO_LINES("")
FF_LOGO_COLORS("")
FF_LOGO_RETURN
+3 -5
View File
@@ -5,6 +5,7 @@
#include "common/properties.h"
#include "detection/temps.h"
#include "detection/vulkan.h"
#include "detection/host/host.h"
#include <stdlib.h>
@@ -266,11 +267,8 @@ void ffPrintGPU(FFinstance* instance)
if(ffPrintFromCache(instance, FF_GPU_MODULE_NAME, &instance->config.gpu, FF_GPU_NUM_FORMAT_ARGS))
return;
if(
getenv("WSLENV") != NULL ||
getenv("WSL_DISTRO") != NULL ||
getenv("WSL_INTEROP") != NULL
) {
if(ffStrbufCompS(&ffDetectHost()->productName, FF_HOST_PRODUCT_NAME_WSL) == 0)
{
ffPrintError(instance, FF_GPU_MODULE_NAME, 0, &instance->config.gpu, "WSL doesn't expose senseful GPU names");
return;
}
+27 -170
View File
@@ -1,196 +1,53 @@
#include "fastfetch.h"
#include "common/printing.h"
#include "common/caching.h"
#include <stdlib.h>
#include "detection/host/host.h"
#define FF_HOST_MODULE_NAME "Host"
#define FF_HOST_NUM_FORMAT_ARGS 15
#ifndef __ANDROID__
#include "common/io.h"
#else
#include <ctype.h>
#endif
#ifndef __ANDROID__
static bool hostValueSet(FFstrbuf* value)
{
ffStrbufTrimRight(value, '\n');
ffStrbufTrim(value, ' ');
return
value->length > 0 &&
ffStrbufStartsWithIgnCaseS(value, "To be filled") != true &&
ffStrbufStartsWithIgnCaseS(value, "To be set") != true &&
ffStrbufStartsWithIgnCaseS(value, "OEM") != true &&
ffStrbufStartsWithIgnCaseS(value, "O.E.M.") != true &&
ffStrbufIgnCaseCompS(value, "None") != 0 &&
ffStrbufIgnCaseCompS(value, "System Product") != 0 &&
ffStrbufIgnCaseCompS(value, "System Product Name") != 0 &&
ffStrbufIgnCaseCompS(value, "System Product Version") != 0 &&
ffStrbufIgnCaseCompS(value, "System Name") != 0 &&
ffStrbufIgnCaseCompS(value, "System Version") != 0 &&
ffStrbufIgnCaseCompS(value, "Default string") != 0 &&
ffStrbufIgnCaseCompS(value, "Undefined") != 0 &&
ffStrbufIgnCaseCompS(value, "Not Specified") != 0 &&
ffStrbufIgnCaseCompS(value, "Not Applicable") != 0 &&
ffStrbufIgnCaseCompS(value, "INVALID") != 0 &&
ffStrbufIgnCaseCompS(value, "Type1ProductConfigId") != 0 &&
ffStrbufIgnCaseCompS(value, "All Series") != 0
;
}
static void getHostValue(const char* devicesPath, const char* classPath, FFstrbuf* buffer)
{
ffReadFileBuffer(devicesPath, buffer);
if(buffer->length == 0)
ffReadFileBuffer(classPath, buffer);
}
#endif
void ffPrintHost(FFinstance* instance)
{
if(ffPrintFromCache(instance, FF_HOST_MODULE_NAME, &instance->config.host, FF_HOST_NUM_FORMAT_ARGS))
return;
FFstrbuf product_family;
ffStrbufInit(&product_family);
#ifndef __ANDROID__
getHostValue("/sys/devices/virtual/dmi/id/product_family", "/sys/class/dmi/id/product_family", &product_family);
if(!hostValueSet(&product_family))
ffStrbufClear(&product_family);
#else
ffSettingsGetAndroidProperty("ro.product.device", &product_family);
#endif
const FFHostResult* host = ffDetectHost();
FFstrbuf product_name;
ffStrbufInit(&product_name);
#ifndef __ANDROID__
getHostValue("/sys/devices/virtual/dmi/id/product_name", "/sys/class/dmi/id/product_name", &product_name);
if(product_name.length == 0)
ffReadFileBuffer("/sys/firmware/devicetree/base/model", &product_name);
if(product_name.length == 0)
ffReadFileBuffer("/tmp/sysinfo/model", &product_name);
if(ffStrbufStartsWithS(&product_name, "Standard PC"))
{
FFstrbuf copy;
ffStrbufInitCopy(&copy, &product_name);
ffStrbufSetS(&product_name, "KVM/QEMU ");
ffStrbufAppend(&product_name, &copy);
ffStrbufDestroy(&copy);
}
if(!hostValueSet(&product_name))
ffStrbufClear(&product_name);
//On WSL, the real host can't be detected. Instead use WSL as host.
if(product_name.length == 0 && product_family.length == 0 && (
getenv("WSLENV") != NULL ||
getenv("WSL_DISTRO") != NULL ||
getenv("WSL_INTEROP") != NULL
)) ffStrbufAppendS(&product_name, "Windows Subsystem for Linux");
#else
ffSettingsGetAndroidProperty("ro.product.brand", &product_name);
if(product_name.length > 0){
product_name.chars[0] = (char) toupper(product_name.chars[0]);
ffStrbufAppendC(&product_name, ' ');
}
if(!ffSettingsGetAndroidProperty("ro.product.model", &product_name))
ffSettingsGetAndroidProperty("ro.product.name", &product_name);
ffStrbufTrimRight(&product_name, ' ');
#endif
if(product_family.length == 0 && product_name.length == 0)
if(host->productFamily.length == 0 && host->productName.length == 0)
{
ffStrbufDestroy(&product_family);
ffStrbufDestroy(&product_name);
ffPrintError(instance, FF_HOST_MODULE_NAME, 0, &instance->config.host, "neither product_family nor product_name is set by O.E.M.");
return;
}
#ifdef __ANDROID__
#define FF_HOST_DATA(name) \
FFstrbuf name; \
ffStrbufInitA(&name, 0);
#else
#define FF_HOST_DATA(name) \
FFstrbuf name; \
ffStrbufInit(&name); \
getHostValue("/sys/devices/virtual/dmi/id/"#name, "/sys/class/dmi/id/"#name, &name); \
if(!hostValueSet(&name)) \
ffStrbufClear(&name);
#endif
FFstrbuf output;
ffStrbufInit(&output);
FF_HOST_DATA(product_version)
FF_HOST_DATA(product_sku)
FF_HOST_DATA(bios_date)
FF_HOST_DATA(bios_release)
FF_HOST_DATA(bios_vendor)
FF_HOST_DATA(bios_version)
FF_HOST_DATA(board_name)
FF_HOST_DATA(board_vendor)
FF_HOST_DATA(board_version)
FF_HOST_DATA(chassis_type)
FF_HOST_DATA(chassis_vendor)
FF_HOST_DATA(chassis_version)
FF_HOST_DATA(sys_vendor)
FFstrbuf host;
ffStrbufInit(&host);
if(product_name.length > 0)
ffStrbufAppend(&host, &product_name);
if(host->productName.length > 0)
ffStrbufAppend(&output, &host->productName);
else
ffStrbufAppend(&host, &product_family);
ffStrbufAppend(&output, &host->productFamily);
if(product_version.length > 0)
if(host->productVersion.length > 0)
{
ffStrbufAppendC(&host, ' ');
ffStrbufAppend(&host, &product_version);
ffStrbufAppendC(&output, ' ');
ffStrbufAppend(&output, &host->productVersion);
}
ffPrintAndWriteToCache(instance, FF_HOST_MODULE_NAME, &instance->config.host, &host, FF_HOST_NUM_FORMAT_ARGS, (FFformatarg[]) {
{FF_FORMAT_ARG_TYPE_STRBUF, &product_family},
{FF_FORMAT_ARG_TYPE_STRBUF, &product_name},
{FF_FORMAT_ARG_TYPE_STRBUF, &product_version},
{FF_FORMAT_ARG_TYPE_STRBUF, &product_sku},
{FF_FORMAT_ARG_TYPE_STRBUF, &bios_date},
{FF_FORMAT_ARG_TYPE_STRBUF, &bios_release},
{FF_FORMAT_ARG_TYPE_STRBUF, &bios_vendor},
{FF_FORMAT_ARG_TYPE_STRBUF, &bios_version},
{FF_FORMAT_ARG_TYPE_STRBUF, &board_name},
{FF_FORMAT_ARG_TYPE_STRBUF, &board_vendor},
{FF_FORMAT_ARG_TYPE_STRBUF, &board_version},
{FF_FORMAT_ARG_TYPE_STRBUF, &chassis_type},
{FF_FORMAT_ARG_TYPE_STRBUF, &chassis_vendor},
{FF_FORMAT_ARG_TYPE_STRBUF, &chassis_version},
{FF_FORMAT_ARG_TYPE_STRBUF, &sys_vendor}
ffPrintAndWriteToCache(instance, FF_HOST_MODULE_NAME, &instance->config.host, &output, FF_HOST_NUM_FORMAT_ARGS, (FFformatarg[]) {
{FF_FORMAT_ARG_TYPE_STRBUF, &host->productFamily},
{FF_FORMAT_ARG_TYPE_STRBUF, &host->productName},
{FF_FORMAT_ARG_TYPE_STRBUF, &host->productVersion},
{FF_FORMAT_ARG_TYPE_STRBUF, &host->productSku},
{FF_FORMAT_ARG_TYPE_STRBUF, &host->biosDate},
{FF_FORMAT_ARG_TYPE_STRBUF, &host->biosRelease},
{FF_FORMAT_ARG_TYPE_STRBUF, &host->biosVendor},
{FF_FORMAT_ARG_TYPE_STRBUF, &host->biosVersion},
{FF_FORMAT_ARG_TYPE_STRBUF, &host->boardName},
{FF_FORMAT_ARG_TYPE_STRBUF, &host->boardVendor},
{FF_FORMAT_ARG_TYPE_STRBUF, &host->boardVersion},
{FF_FORMAT_ARG_TYPE_STRBUF, &host->chassisType},
{FF_FORMAT_ARG_TYPE_STRBUF, &host->chassisVendor},
{FF_FORMAT_ARG_TYPE_STRBUF, &host->chassisVersion},
{FF_FORMAT_ARG_TYPE_STRBUF, &host->sysVendor}
});
ffStrbufDestroy(&product_family);
ffStrbufDestroy(&product_name);
//On Android, all of them get initialized without heap, so no need to destroy them.
#ifndef __ANDROID__
ffStrbufDestroy(&product_version);
ffStrbufDestroy(&product_sku);
ffStrbufDestroy(&bios_date);
ffStrbufDestroy(&bios_release);
ffStrbufDestroy(&bios_vendor);
ffStrbufDestroy(&bios_version);
ffStrbufDestroy(&board_name);
ffStrbufDestroy(&board_vendor);
ffStrbufDestroy(&board_version);
ffStrbufDestroy(&chassis_type);
ffStrbufDestroy(&chassis_vendor);
ffStrbufDestroy(&chassis_version);
ffStrbufDestroy(&sys_vendor);
#endif
}
+13
View File
@@ -188,6 +188,19 @@ void ffStrbufAppendF(FFstrbuf* strbuf, const char* format, ...)
va_end(arguments);
}
void ffStrbufPrependS(FFstrbuf* strbuf, const char* value)
{
ffStrbufPrependNS(strbuf, (uint32_t) strlen(value), value);
}
void ffStrbufPrependNS(FFstrbuf* strbuf, uint32_t length, const char* value)
{
ffStrbufEnsureFree(strbuf, length);
memmove(strbuf->chars + length, strbuf->chars, strbuf->length + 1); // + 1 for the null byte
memcpy(strbuf->chars, value, length);
strbuf->length += length;
}
void ffStrbufSet(FFstrbuf* strbuf, const FFstrbuf* value)
{
ffStrbufClear(strbuf);
+3
View File
@@ -40,6 +40,9 @@ void ffStrbufAppendTransformS(FFstrbuf* strbuf, const char* value, int(*transfor
void ffStrbufAppendF(FFstrbuf* strbuf, const char* format, ...);
void ffStrbufAppendVF(FFstrbuf* strbuf, const char* format, va_list arguments);
void ffStrbufPrependS(FFstrbuf* strbuf, const char* value);
void ffStrbufPrependNS(FFstrbuf* strbuf, uint32_t length, const char* value);
void ffStrbufSet(FFstrbuf* strbuf, const FFstrbuf* value);
void ffStrbufSetS(FFstrbuf* strbuf, const char* value);
+22
View File
@@ -23,6 +23,9 @@ int main(int argc, char** argv)
FF_UNUSED(argc, argv)
FFstrbuf strbuf;
//initA
ffStrbufInitA(&strbuf, 64);
if(strbuf.allocated != 64)
@@ -31,6 +34,8 @@ int main(int argc, char** argv)
if(strbuf.length != 0)
testFailed(&strbuf, "testSrbuf.length != 0");
//appendS
ffStrbufAppendS(&strbuf, "123456789");
if(strbuf.length != 9)
@@ -39,9 +44,13 @@ int main(int argc, char** argv)
if(strcmp(strbuf.chars, "123456789") != 0)
testFailed(&strbuf, "strbuf.data != \"123456789\"");
//startsWithS
if(!ffStrbufStartsWithS(&strbuf, "123"))
testFailed(&strbuf, "!ffStrbufStartsWithS(&strbuf, \"123\")");
//removeS
ffStrbufRemoveS(&strbuf, "78");
if(strbuf.length != 7)
@@ -50,6 +59,8 @@ int main(int argc, char** argv)
if(strcmp(strbuf.chars, "1234569") != 0)
testFailed(&strbuf, "strcmp(strbuf.chars, \"123469\") != 0");
//removeStrings
ffStrbufRemoveStrings(&strbuf, 3, "23", "45", "9");
if(strbuf.length != 2)
@@ -58,5 +69,16 @@ int main(int argc, char** argv)
if(strcmp(strbuf.chars, "16") != 0)
testFailed(&strbuf, "strbuf.chars != \"126\"");
//PrependS
ffStrbufPrependS(&strbuf, "123");
if(strbuf.length != 5)
testFailed(&strbuf, "strbuf.length != 5");
if(strcmp(strbuf.chars, "12316") != 0)
testFailed(&strbuf, "strbuf.chars != \"12316\"");
//Success
puts("\033[32mAll tests passed!"FASTFETCH_TEXT_MODIFIER_RESET);
}