diff --git a/src/util/FFstrbuf.c b/src/util/FFstrbuf.c index 802b79a80..6fe0b151c 100644 --- a/src/util/FFstrbuf.c +++ b/src/util/FFstrbuf.c @@ -682,3 +682,35 @@ bool ffStrbufMatchSeparatedNS(const FFstrbuf* strbuf, uint32_t compLength, const return false; } + +int ffStrbufAppendUtf32CodePoint(FFstrbuf* strbuf, uint32_t codepoint) +{ + if (codepoint <= 0x7F) { + ffStrbufAppendC(strbuf, (char)codepoint); + return 1; + } else if (codepoint <= 0x7FF) { + ffStrbufAppendNS(strbuf, 2, (char[]){ + (char) (0xC0 | (codepoint >> 6)), + (char) (0x80 | (codepoint & 0x3F)) + }); + return 2; + } else if (codepoint <= 0xFFFF) { + ffStrbufAppendNS(strbuf, 3, (char[]){ + (char) (0xE0 | (codepoint >> 12)), + (char) (0x80 | ((codepoint >> 6) & 0x3F)), + (char) (0x80 | (codepoint & 0x3F)) + }); + return 3; + } else if (codepoint <= 0x10FFFF) { + ffStrbufAppendNS(strbuf, 4, (char[]){ + (char) (0xF0 | (codepoint >> 18)), + (char) (0x80 | ((codepoint >> 12) & 0x3F)), + (char) (0x80 | ((codepoint >> 6) & 0x3F)), + (char) (0x80 | (codepoint & 0x3F)) + }); + return 4; + } + + ffStrbufAppendS(strbuf, "�"); // U+FFFD REPLACEMENT CHARACTER + return 1; +} diff --git a/src/util/FFstrbuf.h b/src/util/FFstrbuf.h index 3d551d435..7e9692722 100644 --- a/src/util/FFstrbuf.h +++ b/src/util/FFstrbuf.h @@ -96,6 +96,8 @@ void ffStrbufGetlineRestore(char** lineptr, size_t* n, FFstrbuf* buffer); bool ffStrbufRemoveDupWhitespaces(FFstrbuf* strbuf); bool ffStrbufMatchSeparatedNS(const FFstrbuf* strbuf, uint32_t compLength, const char* comp, char separator); +int ffStrbufAppendUtf32CodePoint(FFstrbuf* strbuf, uint32_t codepoint); + FF_C_NODISCARD static inline FFstrbuf ffStrbufCreateA(uint32_t allocate) { FFstrbuf strbuf; diff --git a/tests/strbuf.c b/tests/strbuf.c index 9781f0d75..94addc466 100644 --- a/tests/strbuf.c +++ b/tests/strbuf.c @@ -711,6 +711,15 @@ int main(void) ffStrbufDestroy(&strbuf); } + { + ffStrbufAppendUtf32CodePoint(&strbuf, 0x6587); + ffStrbufAppendUtf32CodePoint(&strbuf, 0x6cc9); + ffStrbufAppendUtf32CodePoint(&strbuf, 0x9a7f); + VERIFY(ffStrbufEqualS(&strbuf, u8"文泉驿")); + + ffStrbufDestroy(&strbuf); + } + //Success puts("\e[32mAll tests passed!" FASTFETCH_TEXT_MODIFIER_RESET); }