From 737b36e799eddcacff2737567852957fe2ee0d9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 24 Sep 2022 19:22:33 +0800 Subject: [PATCH] FFstrbuf / FFlist: add some improvements 1. make some short fns inlinable 2. simplify implementation 3. fix possible crashes with non-allocated strbuf 4. make the default init fn allocates no memory 5. add more tests --- src/util/FFlist.c | 10 --- src/util/FFlist.h | 15 +++- src/util/FFstrbuf.c | 203 ++++++++++++++------------------------------ src/util/FFstrbuf.h | 113 +++++++++++++++++++----- tests/list.c | 68 +++++++-------- tests/strbuf.c | 153 ++++++++++++++++++++------------- 6 files changed, 290 insertions(+), 272 deletions(-) diff --git a/src/util/FFlist.c b/src/util/FFlist.c index eccf96e32..d01353ffb 100644 --- a/src/util/FFlist.c +++ b/src/util/FFlist.c @@ -2,11 +2,6 @@ #include -void ffListInit(FFlist* list, uint32_t elementSize) -{ - ffListInitA(list, elementSize, FF_LIST_DEFAULT_ALLOC); -} - void ffListInitA(FFlist* list, uint32_t elementSize, uint32_t capacity) { list->elementSize = elementSize; @@ -15,11 +10,6 @@ void ffListInitA(FFlist* list, uint32_t elementSize, uint32_t capacity) list->data = capacity == 0 ? NULL : malloc((size_t)list->capacity * list->elementSize); } -void* ffListGet(const FFlist* list, uint32_t index) -{ - return list->data + (index * list->elementSize); -} - void* ffListAdd(FFlist* list) { if(list->length == list->capacity) diff --git a/src/util/FFlist.h b/src/util/FFlist.h index 8f477dd54..0ec1f2899 100644 --- a/src/util/FFlist.h +++ b/src/util/FFlist.h @@ -7,6 +7,7 @@ #include #include +#include #define FF_LIST_DEFAULT_ALLOC 16 @@ -18,15 +19,23 @@ typedef struct FFlist uint32_t capacity; } FFlist; -void ffListInit(FFlist* list, uint32_t elementSize); void ffListInitA(FFlist* list, uint32_t elementSize, uint32_t capacity); -FF_C_NODISCARD void* ffListGet(const FFlist* list, uint32_t index); - void* ffListAdd(FFlist* list); FF_C_NODISCARD uint32_t ffListFirstIndexComp(const FFlist* list, void* compElement, bool(*compFunc)(const void*, const void*)); void ffListDestroy(FFlist* list); +static inline void ffListInit(FFlist* list, uint32_t elementSize) +{ + ffListInitA(list, elementSize, 0); +} + +static inline void* ffListGet(const FFlist* list, uint32_t index) +{ + assert(list->capacity > 0); + return list->data + (index * list->elementSize); +} + #endif diff --git a/src/util/FFstrbuf.c b/src/util/FFstrbuf.c index e6f705f52..1b152ae44 100644 --- a/src/util/FFstrbuf.c +++ b/src/util/FFstrbuf.c @@ -1,16 +1,10 @@ #include "FFstrbuf.h" -#include #include #include static char* CHAR_NULL_PTR = ""; -void ffStrbufInit(FFstrbuf* strbuf) -{ - ffStrbufInitA(strbuf, FASTFETCH_STRBUF_DEFAULT_ALLOC); -} - void ffStrbufInitA(FFstrbuf* strbuf, uint32_t allocate) { strbuf->allocated = allocate; @@ -28,8 +22,21 @@ void ffStrbufInitCopy(FFstrbuf* strbuf, const FFstrbuf* src) ffStrbufAppend(strbuf, src); } +void ffStrbufInitF(FFstrbuf* strbuf, const char* format, ...) +{ + assert(format != NULL); + + ffStrbufInit(strbuf); + + va_list arguments; + va_start(arguments, format); + ffStrbufAppendVF(strbuf, format, arguments); + va_end(arguments); +} + uint32_t ffStrbufGetFree(const FFstrbuf* strbuf) { + assert(strbuf != NULL); if(strbuf->allocated == 0) return 0; @@ -61,6 +68,8 @@ void ffStrbufEnsureFree(FFstrbuf* strbuf, uint32_t free) void ffStrbufClear(FFstrbuf* strbuf) { + assert(strbuf != NULL); + if(strbuf->allocated == 0) strbuf->chars = CHAR_NULL_PTR; else @@ -69,18 +78,6 @@ void ffStrbufClear(FFstrbuf* strbuf) strbuf->length = 0; } -void ffStrbufRecalculateLength(FFstrbuf* strbuf) -{ - for(strbuf->length = 0; strbuf->chars[strbuf->length] != '\0'; ++strbuf->length); -} - -void ffStrbufAppend(FFstrbuf* strbuf, const FFstrbuf* value) -{ - if(value == NULL) - return; - ffStrbufAppendNS(strbuf, value->length, value->chars); -} - void ffStrbufAppendC(FFstrbuf* strbuf, char c) { ffStrbufEnsureFree(strbuf, 1); @@ -90,7 +87,7 @@ void ffStrbufAppendC(FFstrbuf* strbuf, char c) void ffStrbufAppendNS(FFstrbuf* strbuf, uint32_t length, const char* value) { - if(value == NULL) + if(value == NULL || length == 0) return; ffStrbufEnsureFree(strbuf, length); @@ -101,7 +98,7 @@ void ffStrbufAppendNS(FFstrbuf* strbuf, uint32_t length, const char* value) void ffStrbufAppendNSExludingC(FFstrbuf* strbuf, uint32_t length, const char* value, char exclude) { - if(value == NULL) + if(value == NULL || length == 0) return; ffStrbufEnsureFree(strbuf, length); @@ -120,10 +117,14 @@ void ffStrbufAppendTransformS(FFstrbuf* strbuf, const char* value, int(*transfor if(value == NULL) return; + //Ensure capacity > 0 or the modification below will fail + uint32_t length = (uint32_t) strlen(value); + if(length == 0) + return; + + ffStrbufEnsureFree(strbuf, length); for(uint32_t i = 0; value[i] != '\0'; i++) { - if(i % 16 == 0) - ffStrbufEnsureFree(strbuf, 16); strbuf->chars[strbuf->length++] = (char) transformFunc(value[i]); } strbuf->chars[strbuf->length] = '\0'; @@ -131,8 +132,7 @@ void ffStrbufAppendTransformS(FFstrbuf* strbuf, const char* value, int(*transfor void ffStrbufAppendVF(FFstrbuf* strbuf, const char* format, va_list arguments) { - if(format == NULL) - return; + assert(format != NULL); va_list copy; va_copy(copy, arguments); @@ -155,10 +155,11 @@ void ffStrbufAppendVF(FFstrbuf* strbuf, const char* format, va_list arguments) strbuf->chars[strbuf->length] = '\0'; } -void ffStrbufAppendF(FFstrbuf* strbuf, const char* format, ...) +void ffStrbufSetF(FFstrbuf* strbuf, const char* format, ...) { - if(format == NULL) - return; + assert(format != NULL); + + ffStrbufClear(strbuf); va_list arguments; va_start(arguments, format); @@ -166,13 +167,21 @@ void ffStrbufAppendF(FFstrbuf* strbuf, const char* format, ...) va_end(arguments); } -void ffStrbufPrependS(FFstrbuf* strbuf, const char* value) +void ffStrbufAppendF(FFstrbuf* strbuf, const char* format, ...) { - ffStrbufPrependNS(strbuf, (uint32_t) strlen(value), value); + assert(format != NULL); + + va_list arguments; + va_start(arguments, format); + ffStrbufAppendVF(strbuf, format, arguments); + va_end(arguments); } void ffStrbufPrependNS(FFstrbuf* strbuf, uint32_t length, const char* value) { + if(value == NULL || length == 0) + return; + ffStrbufEnsureFree(strbuf, length); memmove(strbuf->chars + length, strbuf->chars, strbuf->length + 1); // + 1 for the null byte memcpy(strbuf->chars, value, length); @@ -191,35 +200,9 @@ void ffStrbufSet(FFstrbuf* strbuf, const FFstrbuf* value) ffStrbufAppendNS(strbuf, value->length, value->chars); } -int ffStrbufComp(const FFstrbuf* strbuf, const FFstrbuf* comp) -{ - if(strbuf->length != comp->length) - return (int) strbuf->length - (int) comp->length; - - return ffStrbufCompS(strbuf, comp->chars); -} - -int ffStrbufCompS(const FFstrbuf* strbuf, const char* comp) -{ - return strcmp(strbuf->chars, comp); -} - -int ffStrbufIgnCaseComp(const FFstrbuf* strbuf, const FFstrbuf* comp) -{ - if(strbuf->length != comp->length) - return (int) strbuf->length - (int) comp->length; - - return ffStrbufIgnCaseCompS(strbuf, comp->chars); -} - -int ffStrbufIgnCaseCompS(const FFstrbuf* strbuf, const char* comp) -{ - return strcasecmp(strbuf->chars, comp); -} - void ffStrbufTrimLeft(FFstrbuf* strbuf, char c) { - if(strbuf->allocated == 0) + if(strbuf->length == 0) //`allocated == 0` implies `length == 0` return; uint32_t index = 0; @@ -236,7 +219,7 @@ void ffStrbufTrimLeft(FFstrbuf* strbuf, char c) void ffStrbufTrimRight(FFstrbuf* strbuf, char c) { - if(strbuf->allocated == 0) + if(strbuf->length == 0) return; while(ffStrbufEndsWithC(strbuf, c)) @@ -297,58 +280,23 @@ void ffStrbufRemoveStrings(FFstrbuf* strbuf, uint32_t numStrings, ...) uint32_t ffStrbufNextIndexC(const FFstrbuf* strbuf, uint32_t start, char c) { - for(uint32_t i = start; i < strbuf->length; i++) - { - if(strbuf->chars[i] == c) - return i; - } - return strbuf->length; + assert(start <= strbuf->length); + + const char* ptr = (const char*)memchr(strbuf->chars + start, c, strbuf->length - start); + return ptr ? (uint32_t)(ptr - strbuf->chars) : strbuf->length; } uint32_t ffStrbufNextIndexS(const FFstrbuf* strbuf, uint32_t start, const char* str) { - for(uint32_t i = start; i < strbuf->length; i++) - { - bool found = true; + assert(start <= strbuf->length); - for(uint32_t k = 0; str[k] != '\0'; k++) - { - if(i + k == strbuf->length) - return strbuf->length; - - if(strbuf->chars[i + k] != str[k]) - { - found = false; - break; - } - } - - if(found) - return i; - } - - return strbuf->length; -} - -uint32_t ffStrbufFirstIndexC(const FFstrbuf* strbuf, char c) -{ - return ffStrbufNextIndexC(strbuf, 0, c); -} - -uint32_t ffStrbufFirstIndex(const FFstrbuf* strbuf, const FFstrbuf* searched) -{ - return ffStrbufNextIndexS(strbuf, 0, searched->chars); -} - -uint32_t ffStrbufFirstIndexS(const FFstrbuf* strbuf, const char* str) -{ - return ffStrbufNextIndexS(strbuf, 0, str); + const char* ptr = strstr(strbuf->chars + start, str); + return ptr ? (uint32_t)(ptr - strbuf->chars) : strbuf->length; } uint32_t ffStrbufPreviousIndexC(const FFstrbuf* strbuf, uint32_t start, char c) { - if(start >= strbuf->length) - return strbuf->length; + assert(start <= strbuf->length); //We need to loop one higher than the actual index, because uint32_t is guranteed to be >= 0, so this statement would always be true for(uint32_t i = start + 1; i > 0; i--) @@ -359,11 +307,6 @@ uint32_t ffStrbufPreviousIndexC(const FFstrbuf* strbuf, uint32_t start, char c) return strbuf->length; } -uint32_t ffStrbufLastIndexC(const FFstrbuf* strbuf, char c) -{ - return ffStrbufPreviousIndexC(strbuf, strbuf->length - 1, c); -} - void ffStrbufSubstrBefore(FFstrbuf* strbuf, uint32_t index) { if(strbuf->length <= index) @@ -420,24 +363,6 @@ void ffStrbufSubstrAfterLastC(FFstrbuf* strbuf, char c) ffStrbufSubstrAfter(strbuf, index); } -bool ffStrbufStartsWithS(const FFstrbuf* strbuf, const char* start) -{ - for(uint32_t i = 0; start[i] != '\0'; i++) - { - if(i >= strbuf->length) - return false; - - if(strbuf->chars[i] != start[i]) - return false; - } - return true; -} - -bool ffStrbufStartsWithIgnCase(const FFstrbuf* strbuf, const FFstrbuf* start) -{ - return ffStrbufStartsWithS(strbuf, start->chars); -} - bool ffStrbufStartsWithIgnCaseS(const FFstrbuf* strbuf, const char* start) { for(uint32_t i = 0; start[i] != '\0'; i++) @@ -451,6 +376,13 @@ bool ffStrbufStartsWithIgnCaseS(const FFstrbuf* strbuf, const char* start) return true; } +bool ffStrbufStartsWithIgnCase(const FFstrbuf* strbuf, const FFstrbuf* start) +{ + if (start->length > strbuf->length) + return false; + return ffStrbufStartsWithIgnCaseS(strbuf, start->chars); +} + bool ffStrbufEndsWithC(const FFstrbuf* strbuf, char c) { return strbuf->length == 0 ? false : @@ -464,13 +396,7 @@ bool ffStrbufEndsWithS(const FFstrbuf* strbuf, const char* end) if(endLength > strbuf->length) return false; - for(uint32_t i = endLength; i > 0; i--) - { - if(strbuf->chars[strbuf->length - endLength + i - 1] != end[i - 1]) - return false; - } - - return true; + return memcmp(strbuf->chars + strbuf->length - endLength, end, endLength) == 0; } uint32_t ffStrbufCountC(const FFstrbuf* strbuf, char c) @@ -481,6 +407,7 @@ uint32_t ffStrbufCountC(const FFstrbuf* strbuf, char c) if(strbuf->chars[i] == c) result++; } + return result; } @@ -531,20 +458,16 @@ void ffStrbufPutTo(const FFstrbuf* strbuf, FILE* file) double ffStrbufToDouble(const FFstrbuf* strbuf) { - double value; - if(sscanf(strbuf->chars, "%lf", &value) != 1) - return 0.0 / 0.0; //NaN - - return value; + char* str_end; + double result = strtod(strbuf->chars, &str_end); + return str_end == strbuf->chars ? 0.0/0.0 : result; } uint16_t ffStrbufToUInt16(const FFstrbuf* strbuf, uint16_t defaultValue) { - uint16_t value; - if(sscanf(strbuf->chars, "%"SCNu16, &value) != 1) - return defaultValue; - - return value; + char* str_end; + unsigned long result = strtoul(strbuf->chars, &str_end, 10); + return str_end == strbuf->chars || result > UINT16_MAX ? defaultValue : (uint16_t)result; } void ffStrbufDestroy(FFstrbuf* strbuf) diff --git a/src/util/FFstrbuf.h b/src/util/FFstrbuf.h index be1849623..84db2f060 100644 --- a/src/util/FFstrbuf.h +++ b/src/util/FFstrbuf.h @@ -10,6 +10,8 @@ #include #include #include +#include +#include #define FASTFETCH_STRBUF_DEFAULT_ALLOC 32 @@ -22,9 +24,9 @@ typedef struct FFstrbuf #define FF_STRBUF_CREATE(name) FFstrbuf name; ffStrbufInit(&name); -void ffStrbufInit(FFstrbuf* strbuf); void ffStrbufInitA(FFstrbuf* strbuf, uint32_t allocate); void ffStrbufInitCopy(FFstrbuf* strbuf, const FFstrbuf* src); +void ffStrbufInitF(FFstrbuf* strbuf, const char* format, ...); void ffStrbufEnsureFree(FFstrbuf* strbuf, uint32_t free); @@ -32,29 +34,18 @@ FF_C_NODISCARD uint32_t ffStrbufGetFree(const FFstrbuf* strbuf); void ffStrbufClear(FFstrbuf* strbuf); -void ffStrbufRecalculateLength(FFstrbuf* strbuf); - -void ffStrbufAppend(FFstrbuf* strbuf, const FFstrbuf* value); void ffStrbufAppendC(FFstrbuf* strbuf, char c); - void ffStrbufAppendNS(FFstrbuf* strbuf, uint32_t length, const char* value); - void ffStrbufAppendNSExludingC(FFstrbuf* strbuf, uint32_t length, const char* value, char exclude); void ffStrbufAppendTransformS(FFstrbuf* strbuf, const char* value, int(*transformFunc)(int)); FF_C_PRINTF(2, 3) 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 ffStrbufSetNS(FFstrbuf* strbuf, uint32_t length, const char* value); void ffStrbufSet(FFstrbuf* strbuf, const FFstrbuf* value); - -FF_C_NODISCARD int ffStrbufComp(const FFstrbuf* strbuf, const FFstrbuf* comp); -FF_C_NODISCARD int ffStrbufCompS(const FFstrbuf* strbuf, const char* comp); - -FF_C_NODISCARD int ffStrbufIgnCaseComp(const FFstrbuf* strbuf, const FFstrbuf* comp); -FF_C_NODISCARD int ffStrbufIgnCaseCompS(const FFstrbuf* strbuf, const char* comp); +void ffStrbufSetF(FFstrbuf* strbuf, const char* format, ...); void ffStrbufTrimLeft(FFstrbuf* strbuf, char c); void ffStrbufTrimRight(FFstrbuf* strbuf, char c); @@ -69,14 +60,8 @@ void ffStrbufRemoveStrings(FFstrbuf* strbuf, uint32_t numStrings, ...); FF_C_NODISCARD uint32_t ffStrbufNextIndexC(const FFstrbuf* strbuf, uint32_t start, char c); FF_C_NODISCARD uint32_t ffStrbufNextIndexS(const FFstrbuf* strbuf, uint32_t start, const char* str); -FF_C_NODISCARD uint32_t ffStrbufFirstIndexC(const FFstrbuf* strbuf, char c); -FF_C_NODISCARD uint32_t ffStrbufFirstIndex(const FFstrbuf* strbuf, const FFstrbuf* searched); -FF_C_NODISCARD uint32_t ffStrbufFirstIndexS(const FFstrbuf* strbuf, const char* str); - FF_C_NODISCARD uint32_t ffStrbufPreviousIndexC(const FFstrbuf* strbuf, uint32_t start, char c); -FF_C_NODISCARD uint32_t ffStrbufLastIndexC(const FFstrbuf* strbuf, char c); - void ffStrbufSubstrBefore(FFstrbuf* strbuf, uint32_t index); void ffStrbufSubstrBeforeFirstC(FFstrbuf* strbuf, char c); void ffStrbufSubstrBeforeLastC(FFstrbuf* strbuf, char c); @@ -85,8 +70,6 @@ void ffStrbufSubstrAfterFirstC(FFstrbuf* strbuf, char c); void ffStrbufSubstrAfterFirstS(FFstrbuf* strbuf, const char* str); void ffStrbufSubstrAfterLastC(FFstrbuf* strbuf, char c); -bool ffStrbufStartsWithS(const FFstrbuf* strbuf, const char* start); - bool ffStrbufStartsWithIgnCase(const FFstrbuf* strbuf, const FFstrbuf* start); bool ffStrbufStartsWithIgnCaseS(const FFstrbuf* strbuf, const char* start); @@ -107,6 +90,11 @@ FF_C_NODISCARD uint16_t ffStrbufToUInt16(const FFstrbuf* strbuf, uint16_t defaul void ffStrbufDestroy(FFstrbuf* strbuf); +static inline void ffStrbufRecalculateLength(FFstrbuf* strbuf) +{ + strbuf->length = (uint32_t) strlen(strbuf->chars); +} + static inline void ffStrbufAppendS(FFstrbuf* strbuf, const char* value) { if(value == NULL) @@ -128,4 +116,87 @@ static inline void ffStrbufInitS(FFstrbuf* strbuf, const char* str) ffStrbufAppendS(strbuf, str); } +static inline void ffStrbufAppend(FFstrbuf* strbuf, const FFstrbuf* value) +{ + assert(value != strbuf); + if(value == NULL) + return; + ffStrbufAppendNS(strbuf, value->length, value->chars); +} + +static inline void ffStrbufInit(FFstrbuf* strbuf) +{ + ffStrbufInitA(strbuf, 0); +} + +static inline void ffStrbufPrependS(FFstrbuf* strbuf, const char* value) +{ + if(value == NULL) + return; + ffStrbufPrependNS(strbuf, (uint32_t) strlen(value), value); +} + +static inline int ffStrbufComp(const FFstrbuf* strbuf, const FFstrbuf* comp) +{ + uint32_t length = strbuf->length > comp->length ? comp->length : strbuf->length; + return memcmp(strbuf->chars, comp->chars, length + 1); +} + +static inline FF_C_NODISCARD int ffStrbufCompS(const FFstrbuf* strbuf, const char* comp) +{ + return strcmp(strbuf->chars, comp); +} + +static inline FF_C_NODISCARD int ffStrbufIgnCaseCompS(const FFstrbuf* strbuf, const char* comp) +{ + return strcasecmp(strbuf->chars, comp); +} + +static inline FF_C_NODISCARD int ffStrbufIgnCaseComp(const FFstrbuf* strbuf, const FFstrbuf* comp) +{ + return ffStrbufIgnCaseCompS(strbuf, comp->chars); +} + +static inline FF_C_NODISCARD uint32_t ffStrbufFirstIndexC(const FFstrbuf* strbuf, char c) +{ + return ffStrbufNextIndexC(strbuf, 0, c); +} + +static inline FF_C_NODISCARD uint32_t ffStrbufFirstIndex(const FFstrbuf* strbuf, const FFstrbuf* searched) +{ + return ffStrbufNextIndexS(strbuf, 0, searched->chars); +} + +static inline FF_C_NODISCARD uint32_t ffStrbufFirstIndexS(const FFstrbuf* strbuf, const char* str) +{ + return ffStrbufNextIndexS(strbuf, 0, str); +} + +static inline FF_C_NODISCARD uint32_t ffStrbufLastIndexC(const FFstrbuf* strbuf, char c) +{ + return ffStrbufPreviousIndexC(strbuf, strbuf->length - 1, c); +} + +static inline FF_C_NODISCARD bool ffStrbufStartsWithC(const FFstrbuf* strbuf, char c) +{ + return strbuf->chars[0] == c; +} + +static inline FF_C_NODISCARD bool ffStrbufStartsWithSN(const FFstrbuf* strbuf, const char* start, uint32_t length) +{ + if (length > strbuf->length) + return false; + + return memcmp(strbuf->chars, start, length) == 0; +} + +static inline FF_C_NODISCARD bool ffStrbufStartsWithS(const FFstrbuf* strbuf, const char* start) +{ + return ffStrbufStartsWithSN(strbuf, start, (uint32_t) strlen(start)); +} + +static inline FF_C_NODISCARD bool ffStrbufStartsWith(const FFstrbuf* strbuf, const FFstrbuf* start) +{ + return ffStrbufStartsWithSN(strbuf, start->chars, start->length); +} #endif diff --git a/tests/list.c b/tests/list.c index ebae7c8d7..38be491e5 100644 --- a/tests/list.c +++ b/tests/list.c @@ -4,12 +4,11 @@ #include #include -static void testFailed(const FFlist* list, const char* message, ...) +__attribute__((__noreturn__)) +static void testFailed(const FFlist* list, const char* expression, int lineNo) { - va_list args; - va_start(args, message); fputs(FASTFETCH_TEXT_MODIFIER_ERROR, stderr); - vfprintf(stderr, message, args); + fprintf(stderr, "[%d] %s, list:", lineNo, expression); for (uint32_t i = 0; i < list->length; ++i) { fprintf(stderr, "%u ", *(uint32_t*)ffListGet(list, i)); @@ -17,10 +16,16 @@ static void testFailed(const FFlist* list, const char* message, ...) fputc('\n', stderr); fputs(FASTFETCH_TEXT_MODIFIER_RESET, stderr); fputc('\n', stderr); - va_end(args); exit(1); } +static bool numEqualsAdapter(const void* first, const void* second) +{ + return *(uint32_t*)first == *(uint32_t*)second; +} + +#define VERIFY(expression) if(!(expression)) testFailed(&list, #expression, __LINE__) + int main(int argc, char** argv) { FF_UNUSED(argc, argv) @@ -29,60 +34,45 @@ int main(int argc, char** argv) //initA - ffListInitA(&list, sizeof(uint32_t), 0); + ffListInit(&list, sizeof(uint32_t)); - if(ffListGet(&list, 0) != NULL) - testFailed(&list, "ffListGet(&list, 0) != NULL"); - - if(list.elementSize != sizeof(int)) - testFailed(&list, "list.elementSize != sizeof(int)"); - - if(list.capacity != 0) - testFailed(&list, "list.capacity != 0"); - - if(list.length != 0) - testFailed(&list, "list.length != 0"); + VERIFY(list.elementSize == sizeof(uint32_t)); + VERIFY(list.capacity == 0); + VERIFY(list.length == 0); //add for (uint32_t i = 1; i <= FF_LIST_DEFAULT_ALLOC + 1; ++i) { *(uint32_t*)ffListAdd(&list) = i; - if(list.elementSize != sizeof(uint32_t)) - testFailed(&list, "list.elementSize != sizeof(uint32_t)"); - - if(list.length != i) - testFailed(&list, "list.length != i"); + VERIFY(list.elementSize == sizeof(uint32_t)); + VERIFY(list.length == i); if(i <= FF_LIST_DEFAULT_ALLOC) { - if(list.capacity != FF_LIST_DEFAULT_ALLOC) - testFailed(&list, "list.length != FF_LIST_DEFAULT_ALLOC"); + VERIFY(list.capacity == FF_LIST_DEFAULT_ALLOC); } else { - if(list.capacity != FF_LIST_DEFAULT_ALLOC * 2) - testFailed(&list, "list.length != FF_LIST_DEFAULT_ALLOC * 2"); + VERIFY(list.capacity == FF_LIST_DEFAULT_ALLOC * 2); } - if(*(uint32_t*)ffListGet(&list, 0) != 1) - testFailed(&list, "*(int*)ffListGet(&list, 0) != 1"); - - if(*(uint32_t*)ffListGet(&list, i - 1) != i) - testFailed(&list, "*(int*)ffListGet(&list, i - 1) != i"); + VERIFY(*(uint32_t*)ffListGet(&list, 0) == 1); + VERIFY(*(uint32_t*)ffListGet(&list, i - 1) == i); } + // ffListFirstIndexComp + uint32_t n = 10; + VERIFY(ffListFirstIndexComp(&list, &n, numEqualsAdapter) == 9); + n = 999; + VERIFY(ffListFirstIndexComp(&list, &n, numEqualsAdapter) == list.length); + //Destroy ffListDestroy(&list); - if(list.elementSize != sizeof(uint32_t)) - testFailed(&list, "list.elementSize != sizeof(uint32_t)"); - - if(list.capacity != 0) - testFailed(&list, "list.capacity != 0"); - - if(list.length != 0) - testFailed(&list, "list.length != 0"); + VERIFY(list.elementSize == sizeof(uint32_t)); + VERIFY(list.capacity == 0); + VERIFY(list.length == 0); //Success puts("\033[32mAll tests passed!"FASTFETCH_TEXT_MODIFIER_RESET); diff --git a/tests/strbuf.c b/tests/strbuf.c index a82180d60..da26e50e7 100644 --- a/tests/strbuf.c +++ b/tests/strbuf.c @@ -1,20 +1,23 @@ #include "fastfetch.h" #include -#include #include -static void testFailed(const FFstrbuf* strbuf, const char* message, ...) +__attribute__((__noreturn__)) +static void testFailed(const FFstrbuf* strbuf, const char* expression, int lineNo) { - va_list args; - va_start(args, message); fputs(FASTFETCH_TEXT_MODIFIER_ERROR, stderr); - vfprintf(stderr, message, args); - fputs(", strbuf: ", stderr); + fprintf(stderr, "[%d] %s, strbuf:", lineNo, expression); ffStrbufWriteTo(strbuf, stderr); fputs(FASTFETCH_TEXT_MODIFIER_RESET, stderr); fputc('\n', stderr); - va_end(args); + exit(1); +} + +#define VERIFY(expression) if(!(expression)) testFailed(&strbuf, #expression, __LINE__) + +int shouldNotBeCalled(int c) { + FF_UNUSED(c); exit(1); } @@ -32,102 +35,134 @@ int main(int argc, char** argv) ffStrbufInitA(&strbuf, 0); - if(strbuf.chars[0] != 0) //make sure chars[0] is accessable - testFailed(&strbuf, "strbuf.chars[0] != 0"); + VERIFY(strbuf.chars[0] == 0); + VERIFY(strbuf.allocated == 0); + VERIFY(strbuf.length == 0); - if(strbuf.allocated != 0) - testFailed(&strbuf, "strbuf.allocated != 0"); + VERIFY(!ffStrbufStartsWithC(&strbuf, '0')); + VERIFY(!ffStrbufEndsWithC(&strbuf, '0')); + VERIFY(!ffStrbufStartsWithS(&strbuf, "0")); + VERIFY(!ffStrbufEndsWithS(&strbuf, "0")); + VERIFY(ffStrbufCountC(&strbuf, '0') == 0); - if(strbuf.length != 0) - testFailed(&strbuf, "strbuf.length != 0"); + //Ensure following functions work with non-allocated string + ffStrbufAppendS(&strbuf, ""); + ffStrbufAppendF(&strbuf, "%s", ""); + ffStrbufAppendTransformS(&strbuf, "", shouldNotBeCalled); + ffStrbufPrependS(&strbuf, ""); + ffStrbufTrim(&strbuf, ' '); + + VERIFY(strbuf.chars[0] == 0); + VERIFY(strbuf.allocated == 0); + VERIFY(strbuf.length == 0); //appendS ffStrbufAppendS(&strbuf, "12345"); + ffStrbufAppendS(&strbuf, NULL); - if(strbuf.length != 5) - testFailed(&strbuf, "strbuf.length != 5"); - - if(strbuf.allocated < 6) - testFailed(&strbuf, "strbuf.allocated < 6"); - - if(ffStrbufCompS(&strbuf, "12345") != 0) - testFailed(&strbuf, "strbuf.data != \"12345\""); + VERIFY(strbuf.length == 5); + VERIFY(strbuf.allocated >= 6); + VERIFY(ffStrbufCompS(&strbuf, "12345") == 0); //appendNS ffStrbufAppendNS(&strbuf, 4, "67890"); + ffStrbufAppendNS(&strbuf, 0, NULL); - if(strbuf.length != 9) - testFailed(&strbuf, "strbuf.length != 9"); - - if(strbuf.allocated < 10) - testFailed(&strbuf, "strbuf.allocated < 10"); - - if(ffStrbufCompS(&strbuf, "123456789") != 0) - testFailed(&strbuf, "strbuf.data != \"123456789\""); + VERIFY(strbuf.length == 9); + VERIFY(strbuf.allocated >= 10); + VERIFY(ffStrbufCompS(&strbuf, "123456789") == 0); //appendS long ffStrbufAppendS(&strbuf, "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"); + VERIFY(strbuf.length == 109); + VERIFY(strbuf.allocated >= 110); + VERIFY(strbuf.chars[strbuf.length] == 0); - if(strbuf.length != 109) - testFailed(&strbuf, "strbuf.length != 109"); + //substr - if(strbuf.allocated < 110) - testFailed(&strbuf, "strbuf.allocated < 110"); + ffStrbufSubstrBefore(&strbuf, 9); + VERIFY(strbuf.length == 9); + VERIFY(strbuf.allocated >= 110); + VERIFY(strbuf.chars[strbuf.length] == 0); + VERIFY(ffStrbufCompS(&strbuf, "123456789") == 0); - if(strbuf.chars[strbuf.length] != 0) - testFailed(&strbuf, "strbuf.chars[strbuf.length] != 0"); + //startsWithC - strbuf.length = 9; + VERIFY(ffStrbufStartsWithC(&strbuf, '1')); + VERIFY(!ffStrbufStartsWithC(&strbuf, '2')); //startsWithS - if(!ffStrbufStartsWithS(&strbuf, "123")) - testFailed(&strbuf, "!ffStrbufStartsWithS(&strbuf, \"123\")"); + VERIFY(ffStrbufStartsWithS(&strbuf, "123")); + VERIFY(ffStrbufStartsWithS(&strbuf, "123456789")); + VERIFY(!ffStrbufStartsWithS(&strbuf, "1234567890123")); + + //endsWithC + VERIFY(ffStrbufEndsWithC(&strbuf, '9')); + VERIFY(!ffStrbufEndsWithC(&strbuf, '1')); + + //endsWithS + + VERIFY(ffStrbufEndsWithS(&strbuf, "789")); + VERIFY(ffStrbufEndsWithS(&strbuf, "123456789")); + VERIFY(!ffStrbufEndsWithS(&strbuf, "1234567890123")); + + //toNumber + + VERIFY(ffStrbufToDouble(&strbuf) == 123456789.0); + VERIFY(ffStrbufToUInt16(&strbuf, 999) == 999); //overflow + + //countC + + VERIFY(ffStrbufCountC(&strbuf, '1') == 1); + VERIFY(ffStrbufCountC(&strbuf, '0') == 0); //removeS ffStrbufRemoveS(&strbuf, "78"); - if(strbuf.length != 7) - testFailed(&strbuf, "strbuf.length != 7"); - - if(strcmp(strbuf.chars, "1234569") != 0) - testFailed(&strbuf, "strcmp(strbuf.chars, \"123469\") != 0"); + VERIFY(strbuf.length == 7); + VERIFY(strcmp(strbuf.chars, "1234569") == 0); //removeStrings ffStrbufRemoveStrings(&strbuf, 3, "23", "45", "9"); - if(strbuf.length != 2) - testFailed(&strbuf, "strbuf.length != 2"); - - if(strcmp(strbuf.chars, "16") != 0) - testFailed(&strbuf, "strbuf.chars != \"126\""); + VERIFY(strbuf.length == 2); + VERIFY(strcmp(strbuf.chars, "16") == 0); //PrependS ffStrbufPrependS(&strbuf, "123"); + ffStrbufPrependS(&strbuf, NULL); - if(strbuf.length != 5) - testFailed(&strbuf, "strbuf.length != 5"); + VERIFY(strbuf.length == 5); + VERIFY(strcmp(strbuf.chars, "12316") == 0); - if(strcmp(strbuf.chars, "12316") != 0) - testFailed(&strbuf, "strbuf.chars != \"12316\""); + //indexC + VERIFY(ffStrbufFirstIndexC(&strbuf, '1') == 0); + VERIFY(ffStrbufNextIndexC(&strbuf, 1, '1') == 3); + VERIFY(ffStrbufNextIndexC(&strbuf, 4, '1') == 5); + VERIFY(ffStrbufLastIndexC(&strbuf, '1') == 3); + VERIFY(ffStrbufPreviousIndexC(&strbuf, 2, '1') == 0); + VERIFY(ffStrbufPreviousIndexC(&strbuf, 0, '1') == 0); + VERIFY(ffStrbufPreviousIndexC(&strbuf, 0, '2') == 5); + + //indexS + VERIFY(ffStrbufFirstIndexS(&strbuf, "12316") == 0); + VERIFY(ffStrbufNextIndexS(&strbuf, 1, "1") == 3); + VERIFY(ffStrbufNextIndexS(&strbuf, 4, "1") == 5); //Destroy ffStrbufDestroy(&strbuf); - if(strbuf.allocated != 0) - testFailed(&strbuf, "strbuf.allocated != 0"); - if(strbuf.length != 0) - testFailed(&strbuf, "strbuf.length != 0"); - - if(strbuf.chars != NULL) - testFailed(&strbuf, "strbuf.chars != NULL"); + VERIFY(strbuf.allocated == 0); + VERIFY(strbuf.length == 0); + VERIFY(strbuf.chars == NULL); //Success puts("\033[32mAll tests passed!"FASTFETCH_TEXT_MODIFIER_RESET);