#include #include #include #include #include #include #include #include #include #include "prx/libc/include/General.hpp" namespace { int CompareUnits(char16_t left, char16_t right) { return left < right ? -1 : 1; } bool Contains(const char16_t* set, char16_t character) { for (; *set != 0; ++set) { if (*set == character) return true; } return false; } size_t Length(const char16_t* s) { size_t length = 0; while (s[length] != 0) ++length; return length; } std::string AsciiPrefix(const char16_t* text) { std::string prefix; for (; *text != 0 && *text < 0x80; ++text) prefix.push_back(static_cast(*text)); return prefix; } template auto ParseAsciiPrefix(const char16_t* text, char16_t** end, TParse parse) { const std::string prefix = AsciiPrefix(text); char* parsedEnd = nullptr; const auto value = parse(prefix.c_str(), &parsedEnd); if (end != nullptr) *end = const_cast(text) + (parsedEnd - prefix.c_str()); return value; } } extern "C" { void* APS5_VABI memset_nid_postfix(void* s, int c, size_t n) { // APS5_LOG_OUT("s=%p c=%d n=%zu", s, c, n); return std::memset(s, c, n); } void APS5_VABI bzero_nid_postfix(void* destination, size_t count) { std::memset(destination, 0, count); } void* APS5_VABI memcpy_nid_postfix(void* dest, const void* src, size_t n) { return std::memcpy(dest, src, n); } void* APS5_VABI memmove_nid_postfix(void* dest, const void* src, size_t n) { return std::memmove(dest, src, n); } int APS5_VABI memcmp_nid_postfix(const void* s1, const void* s2, size_t n) { return std::memcmp(s1, s2, n); } const void* APS5_VABI memchr_nid_postfix(const void* s, int c, size_t n) { return std::memchr(s, c, n); } int APS5_VABI strcmp_nid_postfix(const char* s1, const char* s2) { return std::strcmp(s1, s2); } int APS5_VABI strncmp_nid_postfix(const char* s1, const char* s2, size_t n) { return std::strncmp(s1, s2, n); } size_t APS5_VABI strlen_nid_postfix(const char* s) { return std::strlen(s); } char* APS5_VABI strcpy_nid_postfix(char* dest, const char* src) { return std::strcpy(dest, src); } char* APS5_VABI strncpy_nid_postfix(char* dest, const char* src, size_t count) { return std::strncpy(dest, src, count); } char* APS5_VABI strcat_nid_postfix(char* dest, const char* src) { return std::strcat(dest, src); } const char* APS5_VABI strchr_nid_postfix(const char* s, int c) { return std::strchr(s, c); } char* APS5_VABI strrchr_nid_postfix(const char* s, int c) { return std::strrchr(const_cast(s), c); } char* APS5_VABI strstr_nid_postfix(const char* haystack, const char* needle) { return std::strstr(const_cast(haystack), needle); } size_t APS5_VABI strlcpy_nid_postfix(char* dest, const char* src, size_t size) { const size_t srcLen = std::strlen(src); if (size != 0u) { const size_t copyLen = srcLen < size - 1u ? srcLen : size - 1u; std::memcpy(dest, src, copyLen); dest[copyLen] = '\0'; } return srcLen; } std::int64_t APS5_VABI strtol_nid_postfix(const char* str, char** endptr, int base) { return std::strtoll(str, endptr, base); } std::uint64_t APS5_VABI strtoul_nid_postfix(const char* str, char** endptr, int base) { return std::strtoull(str, endptr, base); } long long APS5_VABI strtoll_nid_postfix(const char* str, char** endptr, int base) { return std::strtoll(str, endptr, base); } unsigned long long APS5_VABI strtoull_nid_postfix(const char* str, char** endptr, int base) { return std::strtoull(str, endptr, base); } double APS5_VABI strtod_nid_postfix(const char* str, char** endptr) { return std::strtod(str, endptr); } double APS5_VABI atof_nid_postfix(const char* str) { return std::atof(str); } float APS5_VABI strtof_nid_postfix(const char* str, char** endptr) { return std::strtof(str, endptr); } long double APS5_VABI strtold_nid_postfix(const char* str, char** endptr) { static_assert(sizeof(long double) == 16, "Guest long double requires x87 extended precision storage"); return std::strtold(str, endptr); } int APS5_VABI atoi_nid_postfix(const char* str) { return std::atoi(str); } std::div_t APS5_VABI div_nid_postfix(int numerator, int denominator) { return std::div(numerator, denominator); } const char16_t* APS5_VABI wmemchr_nid_postfix(const char16_t* s, char16_t c, size_t n) { for (; n != 0; ++s, --n) { if (*s == c) return s; } return nullptr; } int APS5_VABI wmemcmp_nid_postfix(const char16_t* s1, const char16_t* s2, size_t n) { for (; n != 0; ++s1, ++s2, --n) { if (*s1 != *s2) return CompareUnits(*s1, *s2); } return 0; } char16_t* APS5_VABI wmemcpy_nid_postfix(char16_t* dest, const char16_t* src, size_t n) { if (n != 0) std::memcpy(dest, src, n * sizeof(char16_t)); return dest; } char16_t* APS5_VABI wmemmove_nid_postfix(char16_t* dest, const char16_t* src, size_t n) { if (n != 0) std::memmove(dest, src, n * sizeof(char16_t)); return dest; } } extern "C" { int APS5_VABI strcasecmp_nid_postfix(const char* s1, const char* s2) { while (*s1 && *s2) { unsigned char a = static_cast(std::tolower(static_cast(*s1))); unsigned char b = static_cast(std::tolower(static_cast(*s2))); if (a != b) return a - b; ++s1; ++s2; } return static_cast(*s1) - static_cast(*s2); } int APS5_VABI strncasecmp_nid_postfix(const char* s1, const char* s2, size_t n) { while (n && *s1 && *s2) { unsigned char a = static_cast(std::tolower(static_cast(*s1))); unsigned char b = static_cast(std::tolower(static_cast(*s2))); if (a != b) return a - b; ++s1; ++s2; --n; } if (!n) return 0; return static_cast(*s1) - static_cast(*s2); } int APS5_VABI bcmp_nid_postfix(const void* s1, const void* s2, size_t n) { return std::memcmp(s1, s2, n); } size_t APS5_VABI strspn_nid_postfix(const char* s, const char* accept) { return std::strspn(s, accept); } int APS5_VABI strcoll_nid_postfix(const char* s1, const char* s2) { return std::strcmp(s1, s2); } int APS5_VABI strncpy_s_nid_postfix(char* dest, size_t destsz, const char* src, size_t count) { constexpr int GuestEinval = 22; constexpr int GuestErange = 34; if (!dest || destsz == 0) return GuestEinval; if (!src) { dest[0] = '\0'; return GuestEinval; } size_t length = 0; while (length < count && src[length] != '\0') ++length; if (length >= destsz) { dest[0] = '\0'; return GuestErange; } std::memcpy(dest, src, length); dest[length] = '\0'; return 0; } int APS5_VABI strcpy_s_nid_postfix(char* dest, size_t destsz, const char* src) { return strncpy_s_nid_postfix(dest, destsz, src, static_cast(-1)); } int APS5_VABI strncat_s_nid_postfix(char* dest, size_t destsz, const char* src, size_t count) { constexpr int GuestEinval = 22; constexpr int GuestErange = 34; if (!dest || destsz == 0) return GuestEinval; size_t used = 0; while (used < destsz && dest[used] != '\0') ++used; if (used == destsz || !src) { dest[0] = '\0'; return used == destsz ? GuestErange : GuestEinval; } size_t length = 0; while (length < count && src[length] != '\0') ++length; if (length >= destsz - used) { dest[0] = '\0'; return GuestErange; } std::memcpy(dest + used, src, length); dest[used + length] = '\0'; return 0; } int APS5_VABI strcat_s_nid_postfix(char* dest, size_t destsz, const char* src) { return strncat_s_nid_postfix(dest, destsz, src, static_cast(-1)); } int APS5_VABI memcpy_s_nid_postfix(void* dest, size_t destsz, const void* src, size_t count) { constexpr int GuestEinval = 22; constexpr int GuestErange = 34; if (!dest) return GuestEinval; if (!src || count > destsz) { std::memset(dest, 0, destsz); return src ? GuestErange : GuestEinval; } const auto destination = reinterpret_cast(dest); const auto source = reinterpret_cast(src); const auto distance = destination < source ? source - destination : destination - source; if (count != 0 && distance < count) { std::memset(dest, 0, destsz); return GuestEinval; } std::memcpy(dest, src, count); return 0; } int APS5_VABI memmove_s_nid_postfix(void* dest, size_t destsz, const void* src, size_t count) { constexpr int GuestEinval = 22; constexpr int GuestErange = 34; if (!dest) return GuestEinval; if (!src || count > destsz) { std::memset(dest, 0, destsz); return src ? GuestErange : GuestEinval; } std::memmove(dest, src, count); return 0; } int APS5_VABI memset_s_nid_postfix(void* dest, size_t destsz, int value, size_t count) { constexpr int GuestEinval = 22; constexpr int GuestErange = 34; if (!dest) return GuestEinval; const auto length = count > destsz ? destsz : count; auto* bytes = static_cast(dest); for (size_t index = 0; index < length; ++index) bytes[index] = static_cast(value); return count > destsz ? GuestErange : 0; } char* APS5_VABI strnstr_nid_postfix(const char* haystack, const char* needle, size_t length) { const size_t needleLength = std::strlen(needle); if (needleLength == 0) return const_cast(haystack); for (size_t index = 0; index < length && haystack[index] != '\0'; ++index) { if (needleLength > length - index) break; if (std::strncmp(haystack + index, needle, needleLength) == 0) return const_cast(haystack + index); } return nullptr; } unsigned long long APS5_VABI _Stoull_nid_postfix(const char* str, char** endptr, int base) { return std::strtoull(str, endptr, base); } size_t APS5_VABI wcslen_nid_postfix(const char16_t* s) { return Length(s); } int APS5_VABI wcscmp_nid_postfix(const char16_t* s1, const char16_t* s2) { for (; *s1 == *s2; ++s1, ++s2) { if (*s1 == 0) return 0; } return CompareUnits(*s1, *s2); } int APS5_VABI wcsncmp_nid_postfix(const char16_t* s1, const char16_t* s2, size_t n) { for (; n != 0; ++s1, ++s2, --n) { if (*s1 != *s2) return CompareUnits(*s1, *s2); if (*s1 == 0) return 0; } return 0; } char16_t* APS5_VABI wcscpy_nid_postfix(char16_t* dest, const char16_t* src) { std::memcpy(dest, src, (Length(src) + 1) * sizeof(char16_t)); return dest; } char16_t* APS5_VABI wcsncpy_nid_postfix(char16_t* dest, const char16_t* src, size_t n) { size_t index = 0; for (; index < n && src[index] != 0; ++index) dest[index] = src[index]; for (; index < n; ++index) dest[index] = 0; return dest; } const char16_t* APS5_VABI wcschr_nid_postfix(const char16_t* s, char16_t c) { for (;; ++s) { if (*s == c) return s; if (*s == 0) return nullptr; } } const char16_t* APS5_VABI wcsrchr_nid_postfix(const char16_t* s, char16_t c) { const char16_t* found = nullptr; for (;; ++s) { if (*s == c) found = s; if (*s == 0) return found; } } const char16_t* APS5_VABI wcsstr_nid_postfix(const char16_t* haystack, const char16_t* needle) { const size_t length = Length(needle); if (length == 0) return haystack; for (; *haystack != 0; ++haystack) { size_t matched = 0; while (matched < length && haystack[matched] == needle[matched]) ++matched; if (matched == length) return haystack; } return nullptr; } const char16_t* APS5_VABI wcspbrk_nid_postfix(const char16_t* s, const char16_t* accept) { for (; *s != 0; ++s) { if (Contains(accept, *s)) return s; } return nullptr; } size_t APS5_VABI wcsspn_nid_postfix(const char16_t* s, const char16_t* accept) { size_t count = 0; while (s[count] != 0 && Contains(accept, s[count])) ++count; return count; } char16_t* APS5_VABI wmemset_nid_postfix(char16_t* s, char16_t c, size_t n) { for (size_t index = 0; index < n; ++index) s[index] = c; return s; } double APS5_VABI wcstod_nid_postfix(const char16_t* str, char16_t** endptr) { return ParseAsciiPrefix(str, endptr, [](const char* text, char** end) { return std::strtod(text, end); }); } float APS5_VABI wcstof_nid_postfix(const char16_t* str, char16_t** endptr) { return ParseAsciiPrefix(str, endptr, [](const char* text, char** end) { return std::strtof(text, end); }); } long double APS5_VABI wcstold_nid_postfix(const char16_t* str, char16_t** endptr) { static_assert(sizeof(long double) == 16); static_assert(std::numeric_limits::digits == 64); return ParseAsciiPrefix(str, endptr, [](const char* text, char** end) { return std::strtold(text, end); }); } long long APS5_VABI wcstol_nid_postfix(const char16_t* str, char16_t** endptr, int base) { return ParseAsciiPrefix(str, endptr, [base](const char* text, char** end) { return std::strtoll(text, end, base); }); } long long APS5_VABI wcstoll_nid_postfix(const char16_t* str, char16_t** endptr, int base) { return ParseAsciiPrefix(str, endptr, [base](const char* text, char** end) { return std::strtoll(text, end, base); }); } unsigned long long APS5_VABI wcstoul_nid_postfix(const char16_t* str, char16_t** endptr, int base) { return ParseAsciiPrefix(str, endptr, [base](const char* text, char** end) { return std::strtoull(text, end, base); }); } unsigned long long APS5_VABI wcstoull_nid_postfix(const char16_t* str, char16_t** endptr, int base) { return ParseAsciiPrefix(str, endptr, [base](const char* text, char** end) { return std::strtoull(text, end, base); }); } int APS5_VABI wcscoll_nid_postfix(const char16_t* first, const char16_t* second) { return wcscmp_nid_postfix(first, second); } size_t APS5_VABI wcsxfrm_nid_postfix(char16_t* destination, const char16_t* source, size_t count) { const size_t length = Length(source); if (length < count) std::memcpy(destination, source, (length + 1) * sizeof(char16_t)); return length; } size_t APS5_VABI strxfrm_nid_postfix(char* destination, const char* source, size_t count) { return std::strxfrm(destination, source, count); } size_t APS5_VABI wcsrtombs_nid_postfix(char* destination, const wchar_t** source, size_t count, mbstate_t* state) { return std::wcsrtombs(destination, source, count, state); } }