Files
AnyPS5/core/libs/tests/GuestWcsrtombs.cpp
T

68 lines
3.5 KiB
C++

#include "prx/libc/include/Api.hpp"
#include "prx/libc/include/general/VabiMacros.hpp"
#include <cstddef>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
static void Require(bool value, const char* message) {
if (!value) {
std::fprintf(stderr, "%s\n", message);
std::exit(1);
}
}
int main() {
const std::uint16_t text[] = {'a', 'b', 'c', 0};
const std::uint16_t empty[] = {0};
const std::uint16_t twoBytes[] = {'a', 0x100, 'b', 0};
const std::uint16_t bytes[] = {0x7f, 0x80, 0xe9, 0xff, 0};
std::uint64_t state[2]{};
char out[8];
const auto* source = text;
std::memset(out, 'x', sizeof(out));
*__error_nid_postfix() = 7;
Require(wcsrtombs_nid_postfix(out, &source, sizeof(out), state) == 3, "full conversion length");
Require(source == nullptr && std::memcmp(out, "abc\0xxxx", 8) == 0, "full conversion and terminator");
Require(*__error_nid_postfix() == 7, "successful conversion preserves errno");
source = text;
std::memset(out, 'x', sizeof(out));
Require(wcsrtombs_nid_postfix(out, &source, 0, nullptr) == 0, "zero capacity length");
Require(source == text && out[0] == 'x', "zero capacity leaves input and output alone");
Require(wcsrtombs_nid_postfix(out, &source, 2, nullptr) == 2, "partial conversion length");
Require(source == text + 2 && std::memcmp(out, "abxxxxxx", 8) == 0, "partial conversion has no terminator");
Require(wcsrtombs_nid_postfix(out + 2, &source, 1, nullptr) == 1, "exact capacity length");
Require(source == text + 3 && std::memcmp(out, "abcxxxxx", 8) == 0, "exact capacity leaves terminator pending");
Require(wcsrtombs_nid_postfix(out + 3, &source, 1, nullptr) == 0, "resume at terminator");
Require(source == nullptr && std::memcmp(out, "abc\0xxxx", 8) == 0, "resumed conversion terminates");
source = empty;
std::memset(out, 'x', sizeof(out));
Require(wcsrtombs_nid_postfix(out, &source, 1, state) == 0, "empty string length");
Require(source == nullptr && out[0] == 0 && out[1] == 'x', "empty string terminator");
source = bytes;
Require(wcsrtombs_nid_postfix(out, &source, sizeof(out), state) == 7, "UTF-8 conversion length");
Require(source == nullptr && std::memcmp(out, "\x7f\xc2\x80\xc3\xa9\xc3\xbf\0", 8) == 0, "high characters become two UTF-8 bytes");
source = text;
Require(wcsrtombs_nid_postfix(nullptr, &source, 0, state) == 3 && source == text, "length query ignores capacity and preserves source");
Require(wcsrtombs_nid_postfix(nullptr, &source, 1, nullptr) == 3 && source == text, "length query with implicit state");
source = empty;
Require(wcsrtombs_nid_postfix(nullptr, &source, 0, state) == 0 && source == empty, "empty length query");
source = twoBytes;
std::memset(out, 'x', sizeof(out));
*__error_nid_postfix() = 7;
Require(wcsrtombs_nid_postfix(out, &source, sizeof(out), state) == 4, "a character above 0xff converts");
Require(source == nullptr && std::memcmp(out, "a\xc4\x80" "b\0", 5) == 0, "U+0100 becomes C4 80");
Require(*__error_nid_postfix() == 7, "conversion preserves errno");
source = twoBytes;
Require(wcsrtombs_nid_postfix(nullptr, &source, 0, state) == 4 && source == twoBytes, "length query counts UTF-8 bytes");
source = twoBytes;
std::memset(out, 'x', sizeof(out));
Require(wcsrtombs_nid_postfix(out, &source, 2, state) == 1 && source == twoBytes + 1, "a character that does not fit stops the conversion");
Require(std::memcmp(out, "axxxxxxx", 8) == 0, "no partial character is written");
}