Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
3001203
feat(libSceIcu): implement u_strFromUTF32 and u_strFromUTF32WithSub
MarcZX10 Oct 28, 2026
bb5f7d7
test(libSceIcu): cover u_strFromUTF32 and u_strFromUTF32WithSub
MarcZX10 Oct 28, 2026
a001db6
docs(libSceIcu): record the UTF-32 to UTF-16 conversion sources
MarcZX10 Oct 28, 2026
4d6a2c7
feat(libSceIcu): implement u_strToUTF32 and u_strToUTF32WithSub
MarcZX10 Oct 28, 2026
3dda4b0
test(libSceIcu): cover u_strToUTF32 and u_strToUTF32WithSub
MarcZX10 Oct 28, 2026
1d26c50
docs(libSceIcu): record the UTF-16 to UTF-32 conversion sources
MarcZX10 Oct 28, 2026
262d0f6
feat(libSceIcu): implement u_strFromJavaModifiedUTF8WithSub
MarcZX10 Oct 28, 2026
12356a3
test(libSceIcu): cover u_strFromJavaModifiedUTF8WithSub
MarcZX10 Oct 28, 2026
4df8183
docs(libSceIcu): record the Java modified UTF-8 to UTF-16 sources
MarcZX10 Oct 28, 2026
60c952b
feat(libSceIcu): implement u_strToJavaModifiedUTF8
MarcZX10 Oct 28, 2026
1ef99b7
test(libSceIcu): cover u_strToJavaModifiedUTF8
MarcZX10 Oct 28, 2026
ff0a981
docs(libSceIcu): record the UTF-16 to Java modified UTF-8 sources
MarcZX10 Oct 28, 2026
0e6c066
feat(libSceIcu): implement u_strCompare
MarcZX10 Oct 28, 2026
2836918
test(libSceIcu): cover u_strCompare
MarcZX10 Oct 28, 2026
5e1dd06
docs(libSceIcu): record the u_strCompare sources
MarcZX10 Oct 28, 2026
7917691
feat(libSceIcu): implement u_strstr and u_strrstr
MarcZX10 Oct 28, 2026
65c9a2b
test(libSceIcu): cover u_strstr and u_strrstr
MarcZX10 Oct 28, 2026
6c2a4a8
docs(libSceIcu): record the substring search sources
MarcZX10 Oct 28, 2026
644d2b9
feat(libSceIcu): implement u_isISOControl and u_forDigit
MarcZX10 Oct 28, 2026
0638886
test(libSceIcu): cover u_isISOControl and u_forDigit
MarcZX10 Oct 28, 2026
50611b6
docs(libSceIcu): record the u_isISOControl and u_forDigit sources
MarcZX10 Oct 28, 2026
0c1748e
feat(libSceIcu): implement u_setMutexFunctions and u_setAtomicIncDecF…
MarcZX10 Oct 28, 2026
ee6fa7b
test(libSceIcu): cover u_setMutexFunctions and u_setAtomicIncDecFunct…
MarcZX10 Oct 28, 2026
5430d39
docs(libSceIcu): record the locking configuration sources
MarcZX10 Oct 28, 2026
ef224c1
feat(libSceIcu): implement u_setMemoryFunctions
MarcZX10 Oct 28, 2026
4c23e3a
test(libSceIcu): cover u_setMemoryFunctions
MarcZX10 Oct 28, 2026
cc02a3e
docs(libSceIcu): record the memory function configuration sources
MarcZX10 Oct 28, 2026
e0ed638
feat(libSceIcu): implement u_getISOComment
MarcZX10 Oct 28, 2026
43ca601
test(libSceIcu): cover u_getISOComment
MarcZX10 Oct 28, 2026
025183c
docs(libSceIcu): record the u_getISOComment sources
MarcZX10 Oct 28, 2026
28d313f
feat(libSceIcu): implement u_setDataDirectory and u_getDataDirectory
MarcZX10 Oct 28, 2026
8ec62ab
test(libSceIcu): cover u_setDataDirectory and u_getDataDirectory
MarcZX10 Oct 28, 2026
f851d50
docs(libSceIcu): record the data directory sources
MarcZX10 Oct 28, 2026
8bec87e
feat(libSceIcu): implement u_setTimeZoneFilesDirectory and u_getTimeZ…
MarcZX10 Oct 28, 2026
69951b7
test(libSceIcu): cover u_setTimeZoneFilesDirectory and u_getTimeZoneF…
MarcZX10 Oct 28, 2026
fba314b
docs(libSceIcu): record the time zone files directory sources
MarcZX10 Oct 28, 2026
ea20d2a
feat(libSceIcu): implement u_cleanup
MarcZX10 Oct 28, 2026
b71259e
test(libSceIcu): cover u_cleanup
MarcZX10 Oct 28, 2026
8df67d6
docs(libSceIcu): record the u_cleanup sources
MarcZX10 Oct 28, 2026
b394b9b
docs(debt): drop the blank line left at the end of the debt file
MarcZX10 Oct 28, 2026
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
80 changes: 79 additions & 1 deletion core/libs/prx/libSceIcu/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
add_library(libSceIcu SHARED EXCLUDE_FROM_ALL Export.cpp Invariant.cpp Version.cpp Unescape.cpp)
add_library(libSceIcu SHARED EXCLUDE_FROM_ALL Export.cpp Invariant.cpp Version.cpp Unescape.cpp Utf32.cpp JavaUtf8.cpp Compare.cpp Search.cpp Character.cpp Configuration.cpp)
target_include_directories(libSceIcu PRIVATE ${LIBS_INCLUDE_DIR})
configure_windows_unwind(libSceIcu)
target_sources(libSceIcu PRIVATE CString.cpp)
Expand Down Expand Up @@ -41,3 +41,81 @@ if(BUILD_TESTING)
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libSceIcu>")
endif()
endif()

if(BUILD_TESTING)
add_test_executable(guest_icu_utf32_tests ${CMAKE_CURRENT_SOURCE_DIR}/tests/Utf32.cpp)
target_include_directories(guest_icu_utf32_tests PRIVATE ${LIBS_INCLUDE_DIR})
target_link_libraries(guest_icu_utf32_tests PRIVATE libSceIcu)
configure_windows_unwind(guest_icu_utf32_tests)
add_test(NAME guest_icu_utf32 COMMAND guest_icu_utf32_tests)
set_tests_properties(guest_icu_utf32 PROPERTIES TIMEOUT 30)
if(WIN32)
set_tests_properties(guest_icu_utf32 PROPERTIES ENVIRONMENT_MODIFICATION
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libSceIcu>")
endif()
endif()

if(BUILD_TESTING)
add_test_executable(guest_icu_java_utf8_tests ${CMAKE_CURRENT_SOURCE_DIR}/tests/JavaUtf8.cpp)
target_include_directories(guest_icu_java_utf8_tests PRIVATE ${LIBS_INCLUDE_DIR})
target_link_libraries(guest_icu_java_utf8_tests PRIVATE libSceIcu)
configure_windows_unwind(guest_icu_java_utf8_tests)
add_test(NAME guest_icu_java_utf8 COMMAND guest_icu_java_utf8_tests)
set_tests_properties(guest_icu_java_utf8 PROPERTIES TIMEOUT 30)
if(WIN32)
set_tests_properties(guest_icu_java_utf8 PROPERTIES ENVIRONMENT_MODIFICATION
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libSceIcu>")
endif()
endif()

if(BUILD_TESTING)
add_test_executable(guest_icu_compare_tests ${CMAKE_CURRENT_SOURCE_DIR}/tests/Compare.cpp)
target_include_directories(guest_icu_compare_tests PRIVATE ${LIBS_INCLUDE_DIR})
target_link_libraries(guest_icu_compare_tests PRIVATE libSceIcu)
configure_windows_unwind(guest_icu_compare_tests)
add_test(NAME guest_icu_compare COMMAND guest_icu_compare_tests)
set_tests_properties(guest_icu_compare PROPERTIES TIMEOUT 30)
if(WIN32)
set_tests_properties(guest_icu_compare PROPERTIES ENVIRONMENT_MODIFICATION
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libSceIcu>")
endif()
endif()

if(BUILD_TESTING)
add_test_executable(guest_icu_search_tests ${CMAKE_CURRENT_SOURCE_DIR}/tests/Search.cpp)
target_include_directories(guest_icu_search_tests PRIVATE ${LIBS_INCLUDE_DIR})
target_link_libraries(guest_icu_search_tests PRIVATE libSceIcu)
configure_windows_unwind(guest_icu_search_tests)
add_test(NAME guest_icu_search COMMAND guest_icu_search_tests)
set_tests_properties(guest_icu_search PROPERTIES TIMEOUT 30)
if(WIN32)
set_tests_properties(guest_icu_search PROPERTIES ENVIRONMENT_MODIFICATION
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libSceIcu>")
endif()
endif()

if(BUILD_TESTING)
add_test_executable(guest_icu_character_tests ${CMAKE_CURRENT_SOURCE_DIR}/tests/Character.cpp)
target_include_directories(guest_icu_character_tests PRIVATE ${LIBS_INCLUDE_DIR})
target_link_libraries(guest_icu_character_tests PRIVATE libSceIcu)
configure_windows_unwind(guest_icu_character_tests)
add_test(NAME guest_icu_character COMMAND guest_icu_character_tests)
set_tests_properties(guest_icu_character PROPERTIES TIMEOUT 30)
if(WIN32)
set_tests_properties(guest_icu_character PROPERTIES ENVIRONMENT_MODIFICATION
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libSceIcu>")
endif()
endif()

if(BUILD_TESTING)
add_test_executable(guest_icu_configuration_tests ${CMAKE_CURRENT_SOURCE_DIR}/tests/Configuration.cpp)
target_include_directories(guest_icu_configuration_tests PRIVATE ${LIBS_INCLUDE_DIR})
target_link_libraries(guest_icu_configuration_tests PRIVATE libSceIcu)
configure_windows_unwind(guest_icu_configuration_tests)
add_test(NAME guest_icu_configuration COMMAND guest_icu_configuration_tests)
set_tests_properties(guest_icu_configuration PROPERTIES TIMEOUT 30)
if(WIN32)
set_tests_properties(guest_icu_configuration PROPERTIES ENVIRONMENT_MODIFICATION
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libSceIcu>")
endif()
endif()
27 changes: 27 additions & 0 deletions core/libs/prx/libSceIcu/Character.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#include "prx/libSceIcu/libSceIcu.hpp"
#include "prx/libSceIcu/Status.hpp"
#include <cstdint>

extern "C" {

std::int8_t APS5_VABI u_isISOControl_nid_postfix(std::int32_t character) {
return static_cast<std::uint32_t>(character) <= 0x9f && (character <= 0x1f || character >= 0x7f);
}

std::int32_t APS5_VABI u_forDigit_nid_postfix(std::int32_t digit, std::int8_t radix) {
if (radix < 2 || radix > 36 || digit < 0 || digit >= radix) return 0;
return digit < 10 ? '0' + digit : 'a' - 10 + digit;
}


std::int32_t APS5_VABI u_getISOComment_nid_postfix(std::int32_t, char* destination, std::int32_t capacity, std::int32_t* status) {
if (!status || *status > 0) return 0;
if (capacity < 0 || (capacity > 0 && !destination)) {
*status = Icu::IllegalArgument;
return 0;
}
Icu::Terminate(destination, capacity, 0, status);
return 0;
}

}
9 changes: 9 additions & 0 deletions core/libs/prx/libSceIcu/Character.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#pragma once
#include "prx/libc/include/general/VabiMacros.hpp"
#include <cstdint>

extern "C" {
std::int8_t APS5_VABI u_isISOControl_nid_postfix(std::int32_t);
std::int32_t APS5_VABI u_forDigit_nid_postfix(std::int32_t, std::int8_t);
std::int32_t APS5_VABI u_getISOComment_nid_postfix(std::int32_t, char*, std::int32_t, std::int32_t*);
}
58 changes: 58 additions & 0 deletions core/libs/prx/libSceIcu/Compare.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#include "prx/libSceIcu/libSceIcu.hpp"
#include "prx/libSceIcu/Status.hpp"
#include <cstdint>

namespace {

bool Lead(std::int32_t unit) { return unit >= 0xd800 && unit <= 0xdbff; }
bool Trail(std::int32_t unit) { return unit >= 0xdc00 && unit <= 0xdfff; }

std::int64_t Measure(const char16_t* text) {
std::int64_t length = 0;
while (text[length] != 0) ++length;
return length;
}

std::int32_t CodePointOrder(const char16_t* text, std::int64_t index, std::int64_t length) {
std::int32_t unit = text[index];
const bool pair = (Lead(unit) && (length < 0 || index + 1 < length) && Trail(text[index + 1])) ||
(Trail(unit) && index > 0 && Lead(text[index - 1]));
return pair ? unit : unit - 0x2800;
}

}

extern "C" {

std::int32_t APS5_VABI u_strCompare_nid_postfix(const char16_t* first, std::int32_t firstLength, const char16_t* second,
std::int32_t secondLength, std::int8_t codePointOrder) {
if (!first || firstLength < -1 || !second || secondLength < -1) return 0;
const bool terminated = firstLength < 0 && secondLength < 0;
std::int64_t limit1 = firstLength;
std::int64_t limit2 = secondLength;
std::int32_t equalResult = 0;
std::int64_t index = 0;
if (terminated) {
if (first == second) return 0;
for (; first[index] == second[index]; ++index) {
if (first[index] == 0) return 0;
}
} else {
if (limit1 < 0) limit1 = Measure(first);
if (limit2 < 0) limit2 = Measure(second);
const auto common = limit1 < limit2 ? limit1 : limit2;
equalResult = limit1 < limit2 ? -1 : limit1 > limit2 ? 1 : 0;
if (first == second) return equalResult;
for (; index < common && first[index] == second[index]; ++index) {}
if (index == common) return equalResult;
}
std::int32_t unit1 = first[index];
std::int32_t unit2 = second[index];
if (unit1 >= 0xd800 && unit2 >= 0xd800 && codePointOrder) {
unit1 = CodePointOrder(first, index, terminated ? -1 : limit1);
unit2 = CodePointOrder(second, index, terminated ? -1 : limit2);
}
return unit1 - unit2;
}

}
7 changes: 7 additions & 0 deletions core/libs/prx/libSceIcu/Compare.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#pragma once
#include "prx/libc/include/general/VabiMacros.hpp"
#include <cstdint>

extern "C" {
std::int32_t APS5_VABI u_strCompare_nid_postfix(const char16_t*, std::int32_t, const char16_t*, std::int32_t, std::int8_t);
}
88 changes: 88 additions & 0 deletions core/libs/prx/libSceIcu/Configuration.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
#include "prx/libSceIcu/libSceIcu.hpp"
#include "prx/libSceIcu/Status.hpp"
#include <cstdint>
#include <mutex>
#include <string>
#include <utility>

namespace {

struct MemoryFunctions {
const void* context = nullptr;
Icu::MemoryAllocate allocate = nullptr;
Icu::MemoryReallocate reallocate = nullptr;
Icu::MemoryFree release = nullptr;
};

std::mutex MemoryLock;
MemoryFunctions Memory;
std::mutex DirectoryLock;
std::string DataDirectory;
std::string TimeZoneDirectory;

}

extern "C" {

void APS5_VABI u_setMutexFunctions_nid_postfix(const void*, const void*, const void*, const void*, const void*, std::int32_t* status) {
if (!Icu::Failure(status)) *status = Icu::UnsupportedError;
}

void APS5_VABI u_setAtomicIncDecFunctions_nid_postfix(const void*, const void*, const void*, std::int32_t* status) {
if (!Icu::Failure(status)) *status = Icu::UnsupportedError;
}


void APS5_VABI u_setMemoryFunctions_nid_postfix(const void* context, Icu::MemoryAllocate allocate, Icu::MemoryReallocate reallocate,
Icu::MemoryFree release, std::int32_t* status) {
if (Icu::Failure(status)) return;
if (!allocate || !reallocate || !release) {
*status = Icu::IllegalArgument;
return;
}
const std::lock_guard lock(MemoryLock);
Memory = {context, allocate, reallocate, release};
}


const char* APS5_VABI u_getDataDirectory_nid_postfix() {
const std::lock_guard lock(DirectoryLock);
return DataDirectory.c_str();
}

void APS5_VABI u_setDataDirectory_nid_postfix(const char* directory) {
std::string copy = directory ? directory : "";
const std::lock_guard lock(DirectoryLock);
DataDirectory = std::move(copy);
}


const char* APS5_VABI u_getTimeZoneFilesDirectory_nid_postfix(std::int32_t* status) {
if (Icu::Failure(status)) return "";
const std::lock_guard lock(DirectoryLock);
return TimeZoneDirectory.c_str();
}

void APS5_VABI u_setTimeZoneFilesDirectory_nid_postfix(const char* path, std::int32_t* status) {
if (Icu::Failure(status)) return;
const std::lock_guard lock(DirectoryLock);
TimeZoneDirectory.clear();
if (!path) {
*status = Icu::IllegalArgument;
return;
}
TimeZoneDirectory = path;
}


void APS5_VABI u_cleanup_nid_postfix() {
{
const std::lock_guard lock(MemoryLock);
Memory = {};
}
const std::lock_guard lock(DirectoryLock);
DataDirectory.clear();
TimeZoneDirectory.clear();
}

}
21 changes: 21 additions & 0 deletions core/libs/prx/libSceIcu/Configuration.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#pragma once
#include "prx/libc/include/general/VabiMacros.hpp"
#include <cstddef>
#include <cstdint>

namespace Icu {
using MemoryAllocate = void* (APS5_VABI*)(const void*, std::size_t);
using MemoryReallocate = void* (APS5_VABI*)(const void*, void*, std::size_t);
using MemoryFree = void (APS5_VABI*)(const void*, void*);
} // namespace Icu

extern "C" {
void APS5_VABI u_setMutexFunctions_nid_postfix(const void*, const void*, const void*, const void*, const void*, std::int32_t*);
void APS5_VABI u_setAtomicIncDecFunctions_nid_postfix(const void*, const void*, const void*, std::int32_t*);
void APS5_VABI u_setMemoryFunctions_nid_postfix(const void*, Icu::MemoryAllocate, Icu::MemoryReallocate, Icu::MemoryFree, std::int32_t*);
const char* APS5_VABI u_getDataDirectory_nid_postfix();
void APS5_VABI u_setDataDirectory_nid_postfix(const char*);
const char* APS5_VABI u_getTimeZoneFilesDirectory_nid_postfix(std::int32_t*);
void APS5_VABI u_setTimeZoneFilesDirectory_nid_postfix(const char*, std::int32_t*);
void APS5_VABI u_cleanup_nid_postfix();
}
Loading
Loading