Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions core/libs/prx/libc/src/LocaleSupport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,23 @@ void APS5_VABI _ZNSt8ios_baseD2Ev_nid_postfix(GuestLocale::IosBase* self) {
self->locale = nullptr;
}

GuestLocale::IosBase* APS5_VABI SetStreamWidth(GuestLocale::IosBase* stream, std::int32_t width) {
if (stream == nullptr) throw std::invalid_argument("setw: null stream");
stream->width = width;
return stream;
}

struct StreamManipulator {
GuestLocale::IosBase* (APS5_VABI* function)(GuestLocale::IosBase*, std::int32_t);
std::int32_t argument;
};

static_assert(sizeof(StreamManipulator) == 0x10);

StreamManipulator APS5_VABI _ZSt4setwi_nid_postfix(std::int32_t width) {
return {&SetStreamWidth, width};
}

// Dinkumware's static locale::_Init(bool) returns the global _Locimp, which the caller copies.
GuestLocale::Implementation* APS5_VABI _ZNSt6locale5_InitEv_nid_postfix() {
std::lock_guard<std::mutex> lock(g_localeInitMutex);
Expand Down
25 changes: 25 additions & 0 deletions core/libs/tests/GuestLocale.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ void APS5_VABI _ZNSt6locale5facet9_RegisterEv_nid_postfix(GuestLocale::Facet* se
void APS5_VABI _ZNSt8_LocinfoC1EPKc_nid_postfix(GuestLocale::LocinfoStorage* self, const char* localeName);
void APS5_VABI _ZNSt8_LocinfoD1Ev_nid_postfix(GuestLocale::LocinfoStorage* self);
void APS5_VABI _ZNSt8ios_baseD2Ev_nid_postfix(GuestLocale::IosBase* self);
struct StreamManipulator {
GuestLocale::IosBase* (APS5_VABI* function)(GuestLocale::IosBase*, std::int32_t);
std::int32_t argument;
};
StreamManipulator APS5_VABI _ZSt4setwi_nid_postfix(std::int32_t width);
const short* APS5_VABI _Getpctype_nid_postfix();
const short* APS5_VABI _Getptolower_nid_postfix();
const short* APS5_VABI _Getptoupper_nid_postfix();
Expand Down Expand Up @@ -147,6 +152,25 @@ static void CheckStreamDestruction() {
Require(object.stream.locale == &_ZSt21_sceLibcClassicLocale_nid_postfix);
}

static void CheckStreamWidth() {
struct GuardedStream {
std::uint64_t before = 0x12345678;
GuestLocale::IosBase stream{};
std::uint64_t after = 0x87654321;
} object;
object.stream.flags = 0x4000;
object.stream.precision = 6;
const auto manipulator = _ZSt4setwi_nid_postfix(12);
Require(manipulator.argument == 12 && manipulator.function != nullptr);
Require(manipulator.function(&object.stream, manipulator.argument) == &object.stream);
Require(object.stream.width == 12 && object.stream.flags == 0x4000 && object.stream.precision == 6);
Require(object.before == 0x12345678 && object.after == 0x87654321);
const auto reset = _ZSt4setwi_nid_postfix(0);
reset.function(&object.stream, reset.argument);
Require(object.stream.width == 0);
RequireException([&] { manipulator.function(nullptr, manipulator.argument); });
}

static void CheckWideCaseTranslation() {
const auto* lower = _Getptolower_nid_postfix();
const auto* upper = _Getptoupper_nid_postfix();
Expand Down Expand Up @@ -175,6 +199,7 @@ int main() {
CheckCharacterTables();
CheckCharacterConversions();
CheckStreamDestruction();
CheckStreamWidth();
CheckWideCaseTranslation();
_Locksyslock_nid_postfix();
_Locksyslock_nid_postfix();
Expand Down
Loading