From 195e148cc1e6df79f21638d9c35e083c15fb3464 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Mon, 29 Jun 2026 16:11:29 +0800 Subject: [PATCH] Common: inlines more functions --- src/common/FFlist.h | 11 +++- src/common/FFstrbuf.h | 119 ++++++++++++++++++++++++++++------- src/common/impl/FFlist.c | 9 --- src/common/impl/FFstrbuf.c | 75 +--------------------- src/common/impl/io_windows.c | 2 +- 5 files changed, 110 insertions(+), 106 deletions(-) diff --git a/src/common/FFlist.h b/src/common/FFlist.h index 80cef0b54..b409c6d4b 100644 --- a/src/common/FFlist.h +++ b/src/common/FFlist.h @@ -15,8 +15,6 @@ typedef struct FFlist { uint32_t capacity; } FFlist; -void* ffListAdd(FFlist* list, uint32_t elementSize); - // Removes the first element, and copy its value to `*result` bool ffListShift(FFlist* list, uint32_t elementSize, void* __restrict result); // Removes the last element, and copy its value to `*result` @@ -105,6 +103,15 @@ static inline void ffListReserve(FFlist* list, uint32_t elementSize, uint32_t ne list->capacity = newCapacity; } +static inline void* ffListAdd(FFlist* list, uint32_t elementSize) { + if (__builtin_expect(list->length == list->capacity, false)) { + ffListReserve(list, elementSize, list->capacity == 0 ? FF_LIST_DEFAULT_ALLOC : list->capacity * 2); + } + + ++list->length; + return ffListGet(list, elementSize, list->length - 1); +} + #define FF_LIST_FOR_EACH(itemType, itemVarName, listVar) \ for (itemType* itemVarName = (itemType*) (listVar).data; \ itemVarName - (itemType*) (listVar).data < (intptr_t) (listVar).length; \ diff --git a/src/common/FFstrbuf.h b/src/common/FFstrbuf.h index 2279152db..0c43858cc 100644 --- a/src/common/FFstrbuf.h +++ b/src/common/FFstrbuf.h @@ -38,15 +38,10 @@ void ffStrbufInitA(FFstrbuf* strbuf, uint32_t allocate); void ffStrbufInitVF(FFstrbuf* strbuf, const char* format, va_list arguments); void ffStrbufInitMoveNS(FFstrbuf* strbuf, uint32_t length, char* heapStr); -void ffStrbufEnsureFree(FFstrbuf* strbuf, uint32_t free); void ffStrbufEnsureFixedLengthFree(FFstrbuf* strbuf, uint32_t free); - -void ffStrbufClear(FFstrbuf* strbuf); +void ffStrbufEnsureFreeNoCheck(FFstrbuf* strbuf, uint32_t free); static inline void ffStrbufAppend(FFstrbuf* __restrict strbuf, const FFstrbuf* __restrict value); -void ffStrbufAppendC(FFstrbuf* strbuf, char c); -void ffStrbufAppendNC(FFstrbuf* strbuf, uint32_t num, char c); -void ffStrbufAppendNS(FFstrbuf* strbuf, uint32_t length, const char* value); void ffStrbufAppendTransformS(FFstrbuf* strbuf, const char* value, int (*transformFunc)(int)); FF_A_PRINTF(2, 3) void ffStrbufAppendF(FFstrbuf* strbuf, const char* format, ...); void ffStrbufAppendVF(FFstrbuf* strbuf, const char* format, va_list arguments); @@ -88,13 +83,6 @@ bool ffStrbufRemoveIgnCaseEndS(FFstrbuf* strbuf, const char* end); bool ffStrbufEnsureEndsWithC(FFstrbuf* strbuf, char c); -void ffStrbufWriteTo(const FFstrbuf* strbuf, FILE* file); -void ffStrbufPutTo(const FFstrbuf* strbuf, FILE* file); - -FF_A_NODISCARD double ffStrbufToDouble(const FFstrbuf* strbuf, double defaultValue); -FF_A_NODISCARD int64_t ffStrbufToSInt(const FFstrbuf* strbuf, int64_t defaultValue); -FF_A_NODISCARD uint64_t ffStrbufToUInt(const FFstrbuf* strbuf, uint64_t defaultValue); - void ffStrbufUpperCase(FFstrbuf* strbuf); void ffStrbufLowerCase(FFstrbuf* strbuf); @@ -229,6 +217,76 @@ FF_A_NODISCARD static inline uint32_t ffStrbufGetFree(const FFstrbuf* strbuf) { return strbuf->allocated - strbuf->length - 1; // - 1 for the null byte } +static inline void ffStrbufEnsureFree(FFstrbuf* strbuf, uint32_t free) { + if (__builtin_expect(free == 0, false)) { + if (__builtin_expect(!(strbuf->allocated == 0 && strbuf->length > 0), true)) { + return; + } + } else { + if (__builtin_expect(ffStrbufGetFree(strbuf) >= free, true)) { + return; + } + } + + ffStrbufEnsureFreeNoCheck(strbuf, free); +} + + +static inline void ffStrbufClear(FFstrbuf* strbuf) { + assert(strbuf != NULL); + extern char* CHAR_NULL_PTR; + + if (strbuf->allocated == 0) { + strbuf->chars = CHAR_NULL_PTR; + } else { + strbuf->chars[0] = '\0'; + } + + strbuf->length = 0; +} + +static inline void ffStrbufAppendC(FFstrbuf* strbuf, char c) { + if (__builtin_expect(ffStrbufGetFree(strbuf) == 0, false)) { + ffStrbufEnsureFreeNoCheck(strbuf, 1); + } + strbuf->chars[strbuf->length++] = c; + strbuf->chars[strbuf->length] = '\0'; +} + +static inline void ffStrbufAppendNC(FFstrbuf* strbuf, uint32_t num, char c) { + if (__builtin_expect(num == 0, false)) { + return; + } + if (__builtin_expect(ffStrbufGetFree(strbuf) < num, false)) { + ffStrbufEnsureFreeNoCheck(strbuf, num); + } + + memset(&strbuf->chars[strbuf->length], c, num); + strbuf->length += num; + strbuf->chars[strbuf->length] = '\0'; +} + +static inline void ffStrbufAppendNS(FFstrbuf* strbuf, uint32_t length, const char* value) { + if (__builtin_expect(value == NULL || length == 0, false)) { + return; + } + if (__builtin_expect(ffStrbufGetFree(strbuf) < length, false)) { + ffStrbufEnsureFreeNoCheck(strbuf, length); + } + + memcpy(&strbuf->chars[strbuf->length], value, length); + strbuf->length += length; + strbuf->chars[strbuf->length] = '\0'; +} + +static inline void ffStrbufAppend(FFstrbuf* __restrict strbuf, const FFstrbuf* __restrict value) { + assert(value != strbuf); + if (value == NULL) { + return; + } + ffStrbufAppendNS(strbuf, value->length, value->chars); +} + static inline void ffStrbufRecalculateLength(FFstrbuf* strbuf) { strbuf->length = (uint32_t) strlen(strbuf->chars); } @@ -338,14 +396,6 @@ FF_A_NODISCARD static inline FFstrbuf ffStrbufCreateS(const char* str) { return strbuf; } -static inline void ffStrbufAppend(FFstrbuf* __restrict strbuf, const FFstrbuf* __restrict value) { - assert(value != strbuf); - if (value == NULL) { - return; - } - ffStrbufAppendNS(strbuf, value->length, value->chars); -} - static inline void ffStrbufPrepend(FFstrbuf* strbuf, FFstrbuf* value) { if (value == NULL) { return; @@ -578,6 +628,33 @@ static inline bool ffStrbufSeparatedContainIgnCase(const FFstrbuf* strbuf, const return ffStrbufSeparatedContainIgnCaseNS(strbuf, comp->length, comp->chars, separator); } +static inline void ffStrbufWriteTo(const FFstrbuf* strbuf, FILE* file) { + fwrite(strbuf->chars, sizeof(*strbuf->chars), strbuf->length, file); +} + +static inline void ffStrbufPutTo(const FFstrbuf* strbuf, FILE* file) { + ffStrbufWriteTo(strbuf, file); + fputc('\n', file); +} + +FF_A_NODISCARD static inline double ffStrbufToDouble(const FFstrbuf* strbuf, double defaultValue) { + char* str_end; + double result = strtod(strbuf->chars, &str_end); + return str_end == strbuf->chars ? defaultValue : result; +} + +FF_A_NODISCARD static inline uint64_t ffStrbufToUInt(const FFstrbuf* strbuf, uint64_t defaultValue) { + char* str_end; + unsigned long long result = strtoull(strbuf->chars, &str_end, 10); + return str_end == strbuf->chars ? defaultValue : (uint64_t) result; +} + +FF_A_NODISCARD static inline int64_t ffStrbufToSInt(const FFstrbuf* strbuf, int64_t defaultValue) { + char* str_end; + long long result = strtoll(strbuf->chars, &str_end, 10); + return str_end == strbuf->chars ? defaultValue : (int64_t) result; +} + // Returns true if the strbuf is modified bool ffStrbufDecodeHexEscapeSequences(FFstrbuf* strbuf); diff --git a/src/common/impl/FFlist.c b/src/common/impl/FFlist.c index eddd0fa46..b6fa2cd28 100644 --- a/src/common/impl/FFlist.c +++ b/src/common/impl/FFlist.c @@ -3,15 +3,6 @@ #include #include -void* ffListAdd(FFlist* list, uint32_t elementSize) { - if (list->length == list->capacity) { - ffListReserve(list, elementSize, list->capacity == 0 ? FF_LIST_DEFAULT_ALLOC : list->capacity * 2); - } - - ++list->length; - return ffListGet(list, elementSize, list->length - 1); -} - bool ffListShift(FFlist* list, uint32_t elementSize, void* __restrict result) { if (list->length == 0) { return false; diff --git a/src/common/impl/FFstrbuf.c b/src/common/impl/FFstrbuf.c index 1f6477ba7..84c38c551 100644 --- a/src/common/impl/FFstrbuf.c +++ b/src/common/impl/FFstrbuf.c @@ -45,11 +45,7 @@ void ffStrbufInitMoveNS(FFstrbuf* strbuf, uint32_t length, char* heapStr) { strbuf->chars = heapStr; } -void ffStrbufEnsureFree(FFstrbuf* strbuf, uint32_t free) { - if (ffStrbufGetFree(strbuf) >= free && !(strbuf->allocated == 0 && strbuf->length > 0)) { - return; - } - +void ffStrbufEnsureFreeNoCheck(FFstrbuf* strbuf, uint32_t free) { uint32_t allocate = strbuf->allocated; if (allocate < FASTFETCH_STRBUF_DEFAULT_ALLOC) { allocate = FASTFETCH_STRBUF_DEFAULT_ALLOC; @@ -100,46 +96,6 @@ void ffStrbufEnsureFixedLengthFree(FFstrbuf* strbuf, uint32_t free) { strbuf->allocated = newCap; } -void ffStrbufClear(FFstrbuf* strbuf) { - assert(strbuf != NULL); - - if (strbuf->allocated == 0) { - strbuf->chars = CHAR_NULL_PTR; - } else { - strbuf->chars[0] = '\0'; - } - - strbuf->length = 0; -} - -void ffStrbufAppendC(FFstrbuf* strbuf, char c) { - ffStrbufEnsureFree(strbuf, 1); - strbuf->chars[strbuf->length++] = c; - strbuf->chars[strbuf->length] = '\0'; -} - -void ffStrbufAppendNC(FFstrbuf* strbuf, uint32_t num, char c) { - if (num == 0) { - return; - } - - ffStrbufEnsureFree(strbuf, num); - memset(&strbuf->chars[strbuf->length], c, num); - strbuf->length += num; - strbuf->chars[strbuf->length] = '\0'; -} - -void ffStrbufAppendNS(FFstrbuf* strbuf, uint32_t length, const char* value) { - if (value == NULL || length == 0) { - return; - } - - ffStrbufEnsureFree(strbuf, length); - memcpy(&strbuf->chars[strbuf->length], value, length); - strbuf->length += length; - strbuf->chars[strbuf->length] = '\0'; -} - void ffStrbufAppendTransformS(FFstrbuf* strbuf, const char* value, int (*transformFunc)(int)) { if (value == NULL) { return; @@ -168,7 +124,7 @@ void ffStrbufAppendVF(FFstrbuf* strbuf, const char* format, va_list arguments) { int written = vsnprintf(strbuf->chars + strbuf->length, strbuf->allocated > 0 ? free + 1 : 0, format, arguments); if (written > 0 && (uint32_t) written > free) { - ffStrbufEnsureFree(strbuf, (uint32_t) written); + ffStrbufEnsureFreeNoCheck(strbuf, (uint32_t) written); written = vsnprintf(strbuf->chars + strbuf->length, (uint32_t) written + 1, format, copy); } @@ -550,33 +506,6 @@ bool ffStrbufEnsureEndsWithC(FFstrbuf* strbuf, char c) { return true; } -void ffStrbufWriteTo(const FFstrbuf* strbuf, FILE* file) { - fwrite(strbuf->chars, sizeof(*strbuf->chars), strbuf->length, file); -} - -void ffStrbufPutTo(const FFstrbuf* strbuf, FILE* file) { - ffStrbufWriteTo(strbuf, file); - fputc('\n', file); -} - -double ffStrbufToDouble(const FFstrbuf* strbuf, double defaultValue) { - char* str_end; - double result = strtod(strbuf->chars, &str_end); - return str_end == strbuf->chars ? defaultValue : result; -} - -uint64_t ffStrbufToUInt(const FFstrbuf* strbuf, uint64_t defaultValue) { - char* str_end; - unsigned long long result = strtoull(strbuf->chars, &str_end, 10); - return str_end == strbuf->chars ? defaultValue : (uint64_t) result; -} - -int64_t ffStrbufToSInt(const FFstrbuf* strbuf, int64_t defaultValue) { - char* str_end; - long long result = strtoll(strbuf->chars, &str_end, 10); - return str_end == strbuf->chars ? defaultValue : (int64_t) result; -} - void ffStrbufAppendSInt(FFstrbuf* strbuf, int64_t value) { ffStrbufEnsureFree(strbuf, 21); // Required by yyjson_write_number char* start = strbuf->chars + strbuf->length; diff --git a/src/common/impl/io_windows.c b/src/common/impl/io_windows.c index 24b8d05d1..e085bf2ca 100644 --- a/src/common/impl/io_windows.c +++ b/src/common/impl/io_windows.c @@ -177,7 +177,7 @@ bool ffWriteFileData(const char* fileName, size_t dataSize, const void* data) { } static inline void readWithLength(HANDLE handle, FFstrbuf* buffer, uint32_t length) { - ffStrbufEnsureFree(buffer, length); + ffStrbufEnsureFixedLengthFree(buffer, length); DWORD bytesRead = 0; while ( length > 0 &&