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

131 lines
3.6 KiB
C++

#include <atomic>
#include <cstddef>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <new>
#include "prx/libc/include/FileStream.hpp"
#include "prx/libc/include/ApplicationHeap.hpp"
#include "prx/libc/include/General.hpp"
#include "SceTypes.hpp"
#ifdef _WIN32
#include "prx/libc/include/WindowsFormatting.hpp"
#endif
namespace {
using GuestNewHandler = void (APS5_VABI*)();
std::atomic<GuestNewHandler> g_newHandler{nullptr};
void* Allocate(std::size_t size) {
for (;;) {
GuestNewHandler handler = nullptr;
try {
return ApplicationHeapAllocate_nid_no_patch(size == 0 ? 1 : size);
} catch (const std::bad_alloc&) {
handler = g_newHandler.load();
if (handler == nullptr) throw;
}
handler();
}
}
}
extern "C" {
#ifdef _WIN32
int APS5_VABI vsprintf_s_nid_postfix(char* buffer, size_t size, const char* format, VaList* args) {
return LibcDetail::FormatWindows(buffer, size, format, args);
}
int APS5_VABI sprintf_s_nid_postfix(char* buffer, size_t size, const char* format, ...) {
__builtin_sysv_va_list args;
__builtin_sysv_va_start(args, format);
const int result = LibcDetail::FormatWindows(buffer, size, format, args);
__builtin_sysv_va_end(args);
return result;
}
#endif
[[noreturn]] void APS5_VABI _Assert_nid_postfix(const char* message, const char* location) {
std::fprintf(stderr, "[libc] guest assertion failed: %s (%s)\n", message ? message : "?", location ? location : "?");
std::fflush(stderr);
std::abort();
}
// Only the "C" locale exists.
const char* APS5_VABI setlocale_nid_postfix(int category, const char* locale) {
(void)category;
if (locale == nullptr || locale[0] == 0 || std::strcmp(locale, "C") == 0 || std::strcmp(locale, "POSIX") == 0) return "C";
return nullptr;
}
GuestNewHandler APS5_VABI _ZSt15set_new_handlerPFvvE_nid_postfix(GuestNewHandler handler) {
return g_newHandler.exchange(handler);
}
GuestNewHandler APS5_VABI _ZSt15get_new_handlerv_nid_postfix() {
return g_newHandler.load();
}
unsigned char _ZSt7nothrow_nid_postfix = 0;
void* APS5_VABI _Znwm_nid_postfix(std::size_t size) {
return Allocate(size);
}
void* APS5_VABI _Znam_nid_postfix(std::size_t size) {
return Allocate(size);
}
void* APS5_VABI _ZnwmRKSt9nothrow_t_nid_postfix(std::size_t size, const void*) noexcept {
try {
return Allocate(size);
} catch (const std::bad_alloc&) {
return nullptr;
}
}
void* APS5_VABI _ZnamRKSt9nothrow_t_nid_postfix(std::size_t size, const void*) noexcept {
try {
return Allocate(size);
} catch (const std::bad_alloc&) {
return nullptr;
}
}
void APS5_VABI _ZdlPv_nid_postfix(void* pointer) {
if (pointer != nullptr) ApplicationHeapFree_nid_no_patch(pointer);
}
void APS5_VABI _ZdaPv_nid_postfix(void* pointer) {
if (pointer != nullptr) ApplicationHeapFree_nid_no_patch(pointer);
}
void APS5_VABI _ZdlPvm_nid_postfix(void* pointer, std::size_t) {
if (pointer != nullptr) ApplicationHeapFree_nid_no_patch(pointer);
}
void APS5_VABI _ZdaPvm_nid_postfix(void* pointer, std::size_t) {
if (pointer != nullptr) ApplicationHeapFree_nid_no_patch(pointer);
}
void APS5_VABI _ZdlPvSt11align_val_t_nid_postfix(void* pointer, std::size_t alignment) {
(void)alignment;
if (pointer != nullptr) ApplicationHeapFree_nid_no_patch(pointer);
}
void APS5_VABI _ZdlPvmSt11align_val_t_nid_postfix(void* pointer, std::size_t, std::size_t alignment) {
(void)alignment;
if (pointer != nullptr) ApplicationHeapFree_nid_no_patch(pointer);
}
}