AnyPS5/core/libs/prx/libc/src/StringExtensions.cpp

203 lines
6.6 KiB
C++

#include "prx/libc/include/general/VabiMacros.hpp"
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <cerrno>
#include <string_view>
extern "C" {
char* APS5_VABI basename_nid_postfix(const char* path) {
thread_local char buffer[1024];
std::string_view name = path && *path ? path : ".";
while (name.size() > 1 && name.back() == '/') name.remove_suffix(1);
if (name != "/") {
const auto separator = name.find_last_of('/');
if (separator != std::string_view::npos) name.remove_prefix(separator + 1);
}
if (name.size() >= sizeof(buffer)) { errno = 63; return nullptr; }
std::memcpy(buffer, name.data(), name.size());
buffer[name.size()] = '\0';
return buffer;
}
char* APS5_VABI __inet_ntoa_nid_postfix(unsigned int address) {
thread_local char buffer[sizeof("255.255.255.255")];
unsigned char bytes[sizeof(address)];
std::memcpy(bytes, &address, sizeof(bytes));
char* end = buffer;
for (std::size_t index = 0; index < sizeof(bytes); ++index) {
if (index != 0) *end++ = '.';
const unsigned value = bytes[index];
if (value >= 100) *end++ = static_cast<char>('0' + value / 100);
if (value >= 10) *end++ = static_cast<char>('0' + value / 10 % 10);
*end++ = static_cast<char>('0' + value % 10);
}
*end = 0;
return buffer;
}
char* APS5_VABI dirname_nid_postfix(const char* path) {
thread_local char buffer[1024];
if (path == nullptr || *path == '\0') {
buffer[0] = '.';
buffer[1] = '\0';
return buffer;
}
auto length = std::strlen(path);
if (length >= sizeof(buffer)) {
errno = 63;
return nullptr;
}
std::memcpy(buffer, path, length + 1);
while (length > 0 && buffer[length - 1] == '/') --length;
if (length == 0) {
buffer[0] = '/';
buffer[1] = '\0';
return buffer;
}
buffer[length] = '\0';
auto separator = length;
while (separator > 0 && buffer[separator - 1] != '/') --separator;
if (separator == 0) {
buffer[0] = '.';
buffer[1] = '\0';
return buffer;
}
while (separator > 1 && buffer[separator - 1] == '/') --separator;
buffer[separator] = '\0';
return buffer;
}
std::size_t APS5_VABI strnlen_nid_postfix(const char* text, std::size_t limit) {
std::size_t length = 0;
while (length < limit && text[length] != '\0') ++length;
return length;
}
std::size_t APS5_VABI strnlen_s_nid_postfix(const char* text, std::size_t limit) {
return text ? strnlen_nid_postfix(text, limit) : 0;
}
char* APS5_VABI strsep_nid_postfix(char** text, const char* delimiters) {
char* token = *text;
if (token == nullptr) return nullptr;
char* end = token + std::strcspn(token, delimiters);
if (*end == '\0') {
*text = nullptr;
} else {
*end = '\0';
*text = end + 1;
}
return token;
}
char* APS5_VABI strncat_nid_postfix(char* destination, const char* source, std::size_t limit) {
return std::strncat(destination, source, limit);
}
char* APS5_VABI strpbrk_nid_postfix(const char* text, const char* accept) {
return const_cast<char*>(std::strpbrk(text, accept));
}
std::size_t APS5_VABI strcspn_nid_postfix(const char* text, const char* reject) {
return std::strcspn(text, reject);
}
std::size_t APS5_VABI strlcat_nid_postfix(char* destination, const char* source, std::size_t capacity) {
const auto destinationLength = strnlen_nid_postfix(destination, capacity);
const auto sourceLength = std::strlen(source);
if (destinationLength < capacity) {
const auto remaining = capacity - destinationLength - 1;
const auto count = sourceLength < remaining ? sourceLength : remaining;
std::memcpy(destination + destinationLength, source, count);
destination[destinationLength + count] = '\0';
}
return destinationLength + sourceLength;
}
char* APS5_VABI stpcpy_nid_postfix(char* destination, const char* source) {
const auto length = std::strlen(source);
std::memcpy(destination, source, length + 1);
return destination + length;
}
char* APS5_VABI strtok_r_nid_postfix(char* text, const char* delimiters, char** state) {
if (text == nullptr) text = *state;
if (text == nullptr) return nullptr;
text += std::strspn(text, delimiters);
if (*text == '\0') {
*state = text;
return nullptr;
}
char* end = text + std::strcspn(text, delimiters);
if (*end != '\0') *end++ = '\0';
*state = end;
return text;
}
char* APS5_VABI strtok_nid_postfix(char* text, const char* delimiters) {
thread_local char* state = nullptr;
return strtok_r_nid_postfix(text, delimiters, &state);
}
int APS5_VABI __inet_aton_nid_postfix(const char* text, void* address) {
std::uint8_t parts[3];
std::size_t count = 0;
std::uint64_t value = 0;
bool digit = false;
char c = *text;
for (;;) {
if (c < '0' || c > '9') return 0;
value = 0;
unsigned base = 10;
digit = false;
if (c == '0') {
c = *++text;
if (c == 'x' || c == 'X') {
base = 16;
c = *++text;
} else {
base = 8;
digit = true;
}
}
for (;; c = *++text, digit = true) {
const char lower = static_cast<char>(c | 0x20);
if (c >= '0' && c <= '9') {
if (base == 8 && c >= '8') return 0;
value = value * base + static_cast<unsigned>(c - '0');
} else if (base == 16 && lower >= 'a' && lower <= 'f') {
value = (value << 4) | static_cast<unsigned>(lower - 'a' + 10);
} else {
break;
}
}
if (c != '.') break;
if (count == 3 || value > 0xff) return 0;
parts[count++] = static_cast<std::uint8_t>(value);
c = *++text;
}
if (c != '\0' && c != ' ' && (c < '\t' || c > '\r')) return 0;
if (!digit) return 0;
constexpr std::uint64_t limits[] = {UINT64_MAX, 0xffffff, 0xffff, 0xff};
if (value > limits[count]) return 0;
for (std::size_t index = 0; index < count; ++index) value |= std::uint64_t{parts[index]} << (24 - 8 * index);
if (address) {
const std::uint8_t bytes[4] = {static_cast<std::uint8_t>(value >> 24), static_cast<std::uint8_t>(value >> 16),
static_cast<std::uint8_t>(value >> 8), static_cast<std::uint8_t>(value)};
std::memcpy(address, bytes, sizeof(bytes));
}
return 1;
}
std::uint32_t APS5_VABI __inet_addr_nid_postfix(const char* text) {
std::uint32_t address;
return __inet_aton_nid_postfix(text, &address) ? address : 0xffffffff;
}
}