From 460ae064c9b460a37e21bb0c028265444e18cb2e Mon Sep 17 00:00:00 2001 From: Pedro Date: Thu, 8 Oct 2026 22:31:45 -0500 Subject: [PATCH] feat(libc): implement strsep and memccpy --- core/libs/prx/libc/src/StringExtensions.cpp | 24 +++++++++++++++++++++ core/libs/tests/GuestStrings.cpp | 17 +++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/core/libs/prx/libc/src/StringExtensions.cpp b/core/libs/prx/libc/src/StringExtensions.cpp index a9a7597632b..18e9f00f45b 100644 --- a/core/libs/prx/libc/src/StringExtensions.cpp +++ b/core/libs/prx/libc/src/StringExtensions.cpp @@ -73,4 +73,28 @@ char* APS5_VABI strtok_nid_postfix(char* text, const char* delimiters) { return strtok_r_nid_postfix(text, delimiters, &state); } +char* APS5_VABI strsep_nid_postfix(char** stringp, const char* delimiters) { + char* token = *stringp; + if (token == nullptr) return nullptr; + char* end = token + std::strcspn(token, delimiters); + if (*end != '\0') { + *end = '\0'; + *stringp = end + 1; + } else { + *stringp = nullptr; + } + return token; +} + +void* APS5_VABI memccpy_nid_postfix(void* destination, const void* source, int stop, std::size_t count) { + const auto found = static_cast(std::memchr(source, static_cast(stop), count)); + if (found == nullptr) { + std::memcpy(destination, source, count); + return nullptr; + } + const auto copied = static_cast(found - static_cast(source)) + 1; + std::memcpy(destination, source, copied); + return static_cast(destination) + copied; +} + } diff --git a/core/libs/tests/GuestStrings.cpp b/core/libs/tests/GuestStrings.cpp index 019e4425c96..cc7cd53bd9e 100644 --- a/core/libs/tests/GuestStrings.cpp +++ b/core/libs/tests/GuestStrings.cpp @@ -15,6 +15,8 @@ std::size_t APS5_VABI strcspn_nid_postfix(const char*, const char*); std::size_t APS5_VABI strlcat_nid_postfix(char*, const char*, std::size_t); char* APS5_VABI strtok_r_nid_postfix(char*, const char*, char**); char* APS5_VABI strtok_nid_postfix(char*, const char*); +char* APS5_VABI strsep_nid_postfix(char**, const char*); +void* APS5_VABI memccpy_nid_postfix(void*, const void*, int, std::size_t); char* APS5_VABI strcasestr_nid_postfix(const char*, const char*); int APS5_VABI strcpy_s_nid_postfix(char*, std::size_t, const char*); int APS5_VABI strcat_s_nid_postfix(char*, std::size_t, const char*); @@ -163,5 +165,20 @@ int main() { Require(strcasestr_nid_postfix("", "a") == nullptr); const char highBytes[] = {static_cast(0xff), 'A', 0}; Require(strcasestr_nid_postfix(highBytes, "a") == highBytes + 1); + char separated[] = "a,,b:c"; + char* cursor = separated; + Require(std::strcmp(strsep_nid_postfix(&cursor, ",:"), "a") == 0); + Require(std::strcmp(strsep_nid_postfix(&cursor, ",:"), "") == 0); + Require(std::strcmp(strsep_nid_postfix(&cursor, ",:"), "b") == 0); + Require(std::strcmp(strsep_nid_postfix(&cursor, ",:"), "c") == 0); + Require(cursor == nullptr && strsep_nid_postfix(&cursor, ",") == nullptr); + char* nothing = nullptr; + Require(strsep_nid_postfix(¬hing, ",") == nullptr); + char copy[8] = {}; + Require(memccpy_nid_postfix(copy, "abcdef", 'c', 6) == copy + 3 && std::memcmp(copy, "abc", 3) == 0); + char partial[4] = {}; + Require(memccpy_nid_postfix(partial, "abcd", 'z', 4) == nullptr && std::memcmp(partial, "abcd", 4) == 0); + Require(memccpy_nid_postfix(copy, "xyz", 'x' + 256, 3) == copy + 1); + Require(memccpy_nid_postfix(copy, "xyz", 'x', 0) == nullptr); return CheckMemcpyOverlap() ? 0 : 1; }