Skip to content
Open
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
4 changes: 4 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,7 @@
[submodule "3rdparty/quickjs"]
path = 3rdparty/quickjs
url = https://github.com/quickjs-ng/quickjs.git
[submodule "3rdparty/icu"]
path = 3rdparty/icu
url = https://github.com/unicode-org/icu.git
shallow = true
1 change: 1 addition & 0 deletions 3rdparty/icu
Submodule icu added at 049e0d
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -663,6 +663,7 @@ set_target_properties(usb-1.0 PROPERTIES POSITION_INDEPENDENT_CODE ON)

include(cmake/ZArchive.cmake)
include(cmake/Opus.cmake)
include(cmake/Icu.cmake)
if(WIN32 OR APPLE)
set(MI_BUILD_SHARED ON CACHE BOOL "" FORCE)
set(MI_BUILD_STATIC OFF CACHE BOOL "" FORCE)
Expand Down
86 changes: 86 additions & 0 deletions cmake/Icu.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
set(ICU_SOURCE_DIR ${CMAKE_SOURCE_DIR}/3rdparty/icu/icu4c/source)

add_library(icu_common STATIC EXCLUDE_FROM_ALL
${ICU_SOURCE_DIR}/common/appendable.cpp
${ICU_SOURCE_DIR}/common/bmpset.cpp
${ICU_SOURCE_DIR}/common/bytesinkutil.cpp
${ICU_SOURCE_DIR}/common/bytestream.cpp
${ICU_SOURCE_DIR}/common/bytestrie.cpp
${ICU_SOURCE_DIR}/common/charstr.cpp
${ICU_SOURCE_DIR}/common/cmemory.cpp
${ICU_SOURCE_DIR}/common/cstring.cpp
${ICU_SOURCE_DIR}/common/edits.cpp
${ICU_SOURCE_DIR}/common/emojiprops.cpp
${ICU_SOURCE_DIR}/common/loadednormalizer2impl.cpp
${ICU_SOURCE_DIR}/common/normalizer2.cpp
${ICU_SOURCE_DIR}/common/normalizer2impl.cpp
${ICU_SOURCE_DIR}/common/patternprops.cpp
${ICU_SOURCE_DIR}/common/propname.cpp
${ICU_SOURCE_DIR}/common/putil.cpp
${ICU_SOURCE_DIR}/common/stringpiece.cpp
${ICU_SOURCE_DIR}/common/uarrsort.cpp
${ICU_SOURCE_DIR}/common/ubidi_props.cpp
${ICU_SOURCE_DIR}/common/ucase.cpp
${ICU_SOURCE_DIR}/common/uchar.cpp
${ICU_SOURCE_DIR}/common/ucharstrie.cpp
${ICU_SOURCE_DIR}/common/ucharstrieiterator.cpp
${ICU_SOURCE_DIR}/common/ucln_cmn.cpp
${ICU_SOURCE_DIR}/common/ucmndata.cpp
${ICU_SOURCE_DIR}/common/ucptrie.cpp
${ICU_SOURCE_DIR}/common/udata.cpp
${ICU_SOURCE_DIR}/common/udatamem.cpp
${ICU_SOURCE_DIR}/common/udataswp.cpp
${ICU_SOURCE_DIR}/common/uhash.cpp
${ICU_SOURCE_DIR}/common/uinvchar.cpp
${ICU_SOURCE_DIR}/common/umapfile.cpp
${ICU_SOURCE_DIR}/common/umath.cpp
${ICU_SOURCE_DIR}/common/umutablecptrie.cpp
${ICU_SOURCE_DIR}/common/umutex.cpp
${ICU_SOURCE_DIR}/common/unifilt.cpp
${ICU_SOURCE_DIR}/common/unifunct.cpp
${ICU_SOURCE_DIR}/common/uniset.cpp
${ICU_SOURCE_DIR}/common/unisetspan.cpp
${ICU_SOURCE_DIR}/common/unistr.cpp
${ICU_SOURCE_DIR}/common/unistr_case.cpp
${ICU_SOURCE_DIR}/common/uobject.cpp
${ICU_SOURCE_DIR}/common/uprops.cpp
${ICU_SOURCE_DIR}/common/ustrcase.cpp
${ICU_SOURCE_DIR}/common/ustring.cpp
${ICU_SOURCE_DIR}/common/ustrtrns.cpp
${ICU_SOURCE_DIR}/common/utf_impl.cpp
${ICU_SOURCE_DIR}/common/util.cpp
${ICU_SOURCE_DIR}/common/utrace.cpp
${ICU_SOURCE_DIR}/common/utrie2.cpp
${ICU_SOURCE_DIR}/common/utrie_swap.cpp
${ICU_SOURCE_DIR}/common/uvector.cpp
${ICU_SOURCE_DIR}/common/uvectr32.cpp
${ICU_SOURCE_DIR}/stubdata/stubdata.cpp)
if(WIN32)
target_sources(icu_common PRIVATE
${ICU_SOURCE_DIR}/common/fixedstring.cpp
${ICU_SOURCE_DIR}/common/localebuilder.cpp
${ICU_SOURCE_DIR}/common/locid.cpp
${ICU_SOURCE_DIR}/common/loclikely.cpp
${ICU_SOURCE_DIR}/common/loclikelysubtags.cpp
${ICU_SOURCE_DIR}/common/locmap.cpp
${ICU_SOURCE_DIR}/common/lsr.cpp
${ICU_SOURCE_DIR}/common/resource.cpp
${ICU_SOURCE_DIR}/common/ucol_swp.cpp
${ICU_SOURCE_DIR}/common/uenum.cpp
${ICU_SOURCE_DIR}/common/uloc.cpp
${ICU_SOURCE_DIR}/common/uloc_keytype.cpp
${ICU_SOURCE_DIR}/common/uloc_tag.cpp
${ICU_SOURCE_DIR}/common/uresbund.cpp
${ICU_SOURCE_DIR}/common/uresdata.cpp
${ICU_SOURCE_DIR}/common/uscript_props.cpp
${ICU_SOURCE_DIR}/common/ustrenum.cpp
${ICU_SOURCE_DIR}/common/utypes.cpp
${ICU_SOURCE_DIR}/common/wintz.cpp)
endif()
target_include_directories(icu_common SYSTEM PUBLIC ${ICU_SOURCE_DIR}/common)
target_compile_definitions(icu_common PUBLIC U_STATIC_IMPLEMENTATION PRIVATE U_COMMON_IMPLEMENTATION UCONFIG_NO_FILE_IO=1)
target_compile_features(icu_common PUBLIC cxx_std_17)
set_target_properties(icu_common PROPERTIES POSITION_INDEPENDENT_CODE ON CXX_VISIBILITY_PRESET hidden VISIBILITY_INLINES_HIDDEN ON)
if(MINGW OR CMAKE_SYSTEM_NAME STREQUAL "Linux")
target_link_options(icu_common INTERFACE LINKER:--exclude-libs,libicu_common.a)
endif()
42 changes: 42 additions & 0 deletions core/libs/prx/libSceIcu/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ target_sources(libSceIcu PRIVATE CompareIter.cpp)
target_sources(libSceIcu PRIVATE Space.cpp)
target_sources(libSceIcu PRIVATE Utf8.cpp)
target_sources(libSceIcu PRIVATE Resource.cpp)
target_sources(libSceIcu PRIVATE Properties.cpp CaseMapping.cpp)
target_link_libraries(libSceIcu PRIVATE icu_common)

if(BUILD_TESTING)
add_test_executable(guest_icu_utf8_tests ${LIBS_INCLUDE_DIR}/tests/GuestIcuUtf8.cpp)
Expand Down Expand Up @@ -162,3 +164,43 @@ if(BUILD_TESTING)
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libSceIcu>;PATH=path_list_prepend:$<TARGET_FILE_DIR:libkernel>")
endif()
endif()

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

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

if(BUILD_TESTING)
add_test_executable(guest_icu_unicode_data_tests ${CMAKE_CURRENT_SOURCE_DIR}/tests/UnicodeData.cpp)
target_include_directories(guest_icu_unicode_data_tests PRIVATE ${LIBS_INCLUDE_DIR})
target_compile_definitions(guest_icu_unicode_data_tests PRIVATE ANYPS5_ICU_UNICODE_DATA="${ICU_SOURCE_DIR}/data/unidata/UnicodeData.txt")
target_link_libraries(guest_icu_unicode_data_tests PRIVATE libSceIcu libc)
configure_windows_unwind(guest_icu_unicode_data_tests)
add_test(NAME guest_icu_unicode_data COMMAND guest_icu_unicode_data_tests)
set_tests_properties(guest_icu_unicode_data PROPERTIES TIMEOUT 60)
if(WIN32)
set_tests_properties(guest_icu_unicode_data PROPERTIES ENVIRONMENT_MODIFICATION
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libSceIcu>")
endif()
endif()
94 changes: 94 additions & 0 deletions core/libs/prx/libSceIcu/CaseMapping.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
#include "prx/libSceIcu/CaseMapping.hpp"
#include "prx/libc/include/General.hpp"
#include "ucase.h"
#include "ucasemap_imp.h"
#include "unicode/ustring.h"
#include <cstdint>

namespace {

void CheckString(const char16_t* text, std::int32_t length) {
if (length < -1 || (!text && length != 0)) APS5_INVALID_ARG_EX;
}

UErrorCode& Status(std::int32_t* error) {
if (!error) APS5_INVALID_ARG_EX;
return *reinterpret_cast<UErrorCode*>(error);
}

bool InvalidMapping(const char16_t* destination, std::int32_t capacity, const char16_t* source, std::int32_t length) {
return capacity < 0 || (!destination && capacity > 0) || !source || length < -1;
}

std::int32_t MapInLocale(const char* name, const char* locale, char16_t* destination, std::int32_t capacity,
const char16_t* source, std::int32_t length, UStringCaseMapper* mapper, std::int32_t* error) {
auto& status = Status(error);
std::int32_t caseLocale = UCASE_LOC_ROOT;
if (locale) {
if (*locale) caseLocale = ucase_getCaseLocale(locale);
} else if (U_SUCCESS(status) && !InvalidMapping(destination, capacity, source, length)) {
NotImplemented_nid_no_patch(name);
}
return ustrcase_mapWithOverlap(caseLocale, 0, UCASEMAP_BREAK_ITERATOR_NULL destination, capacity, source, length, mapper,
status);
}

}

extern "C" {

std::int32_t APS5_VABI u_strFoldCase_nid_postfix(char16_t* destination, std::int32_t capacity, const char16_t* source,
std::int32_t length, std::uint32_t options, std::int32_t* error) {
return u_strFoldCase(destination, capacity, source, length, options, &Status(error));
}

std::int32_t APS5_VABI u_strToLower_nid_postfix(char16_t* destination, std::int32_t capacity, const char16_t* source,
std::int32_t length, const char* locale, std::int32_t* error) {
return MapInLocale("u_strToLower: default locale", locale, destination, capacity, source, length,
ustrcase_internalToLower, error);
}

std::int32_t APS5_VABI u_strToUpper_nid_postfix(char16_t* destination, std::int32_t capacity, const char16_t* source,
std::int32_t length, const char* locale, std::int32_t* error) {
return MapInLocale("u_strToUpper: default locale", locale, destination, capacity, source, length,
ustrcase_internalToUpper, error);
}

std::int32_t APS5_VABI u_strCaseCompare_nid_postfix(const char16_t* first, std::int32_t firstLength, const char16_t* second,
std::int32_t secondLength, std::uint32_t options, std::int32_t* error) {
return u_strCaseCompare(first, firstLength, second, secondLength, options, reinterpret_cast<UErrorCode*>(error));
}

std::int32_t APS5_VABI u_strcasecmp_nid_postfix(const char16_t* first, const char16_t* second, std::uint32_t options) {
CheckString(first, -1);
CheckString(second, -1);
return u_strcasecmp(first, second, options);
}

std::int32_t APS5_VABI u_strncasecmp_nid_postfix(const char16_t* first, const char16_t* second, std::int32_t count,
std::uint32_t options) {
CheckString(first, count);
CheckString(second, count);
return u_strncasecmp(first, second, count, options);
}

std::int32_t APS5_VABI u_memcasecmp_nid_postfix(const char16_t* first, const char16_t* second, std::int32_t length,
std::uint32_t options) {
CheckString(first, length);
CheckString(second, length);
return u_memcasecmp(first, second, length, options);
}

void APS5_VABI u_caseInsensitivePrefixMatch_nid_postfix(const char16_t* first, std::int32_t firstLength, const char16_t* second,
std::int32_t secondLength, std::uint32_t options,
std::int32_t* firstMatch, std::int32_t* secondMatch,
std::int32_t* error) {
if (U_FAILURE(Status(error))) return;
if (firstMatch && !secondMatch) APS5_INVALID_ARG_EX;
CheckString(first, firstLength);
CheckString(second, secondLength);
u_caseInsensitivePrefixMatch(first, firstLength, second, secondLength, options, firstMatch, secondMatch,
reinterpret_cast<UErrorCode*>(error));
}

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

extern "C" {
std::int32_t APS5_VABI u_strFoldCase_nid_postfix(char16_t*, std::int32_t, const char16_t*, std::int32_t, std::uint32_t, std::int32_t*);
std::int32_t APS5_VABI u_strToLower_nid_postfix(char16_t*, std::int32_t, const char16_t*, std::int32_t, const char*, std::int32_t*);
std::int32_t APS5_VABI u_strToUpper_nid_postfix(char16_t*, std::int32_t, const char16_t*, std::int32_t, const char*, std::int32_t*);
std::int32_t APS5_VABI u_strCaseCompare_nid_postfix(const char16_t*, std::int32_t, const char16_t*, std::int32_t, std::uint32_t, std::int32_t*);
std::int32_t APS5_VABI u_strcasecmp_nid_postfix(const char16_t*, const char16_t*, std::uint32_t);
std::int32_t APS5_VABI u_strncasecmp_nid_postfix(const char16_t*, const char16_t*, std::int32_t, std::uint32_t);
std::int32_t APS5_VABI u_memcasecmp_nid_postfix(const char16_t*, const char16_t*, std::int32_t, std::uint32_t);
void APS5_VABI u_caseInsensitivePrefixMatch_nid_postfix(const char16_t*, std::int32_t, const char16_t*, std::int32_t, std::uint32_t, std::int32_t*, std::int32_t*, std::int32_t*);
}
Loading
Loading