feat(libcurl): implement curl_strequal and curl_strnequal

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
Daniel HornandClaude Opus 5.5 committed 2026-11-01 09:55:52 +00:00
1 parent 26fa1212b8
commit 453ee145b4
5 files changed
+116 -9

No files matched your search

+16
View File
@@ -0,0 +1,16 @@
add_library(libcurl SHARED EXCLUDE_FROM_ALL Export.cpp)
target_include_directories(libcurl PRIVATE ${LIBS_INCLUDE_DIR})
configure_windows_unwind(libcurl)
if(BUILD_TESTING)
add_test_executable(guest_curl_strings_tests ${LIBS_INCLUDE_DIR}/tests/GuestCurlStrings.cpp)
target_include_directories(guest_curl_strings_tests PRIVATE ${LIBS_INCLUDE_DIR})
target_link_libraries(guest_curl_strings_tests PRIVATE libcurl libc)
configure_windows_unwind(guest_curl_strings_tests)
add_test(NAME guest_curl_strings COMMAND guest_curl_strings_tests)
set_tests_properties(guest_curl_strings PROPERTIES TIMEOUT 20)
if(WIN32)
set_tests_properties(guest_curl_strings PROPERTIES ENVIRONMENT_MODIFICATION
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libcurl>")
endif()
endif()
+21 -4
View File
@@ -1,6 +1,11 @@
#include "prx/libcurl/include/InventoryExports.hpp"
#include "prx/libc/include/General.hpp"
#include "prx/libc/include/general/ExportMacros.hpp"
#include <cstddef>
static char RawUpper(char value) {
return value >= 'a' && value <= 'z' ? static_cast<char>('A' + value - 'a') : value;
}
extern "C" {
@@ -76,8 +81,13 @@ int APS5_VABI curl_multi_socket_all() {
NotImplemented_nid_no_patch(__func__);
}
int APS5_VABI curl_strequal() {
NotImplemented_nid_no_patch(__func__);
int APS5_VABI curl_strequal(const char* first, const char* second) {
if (!first || !second) NotImplemented_nid_no_patch(__func__);
while (*first && *second && RawUpper(*first) == RawUpper(*second)) {
++first;
++second;
}
return RawUpper(*first) == RawUpper(*second);
}
int APS5_VABI curl_url_get() {
@@ -160,8 +170,15 @@ int APS5_VABI curl_easy_init() {
NotImplemented_nid_no_patch(__func__);
}
int APS5_VABI curl_strnequal() {
NotImplemented_nid_no_patch(__func__);
int APS5_VABI curl_strnequal(const char* first, const char* second, size_t max) {
if (!first || !second) NotImplemented_nid_no_patch(__func__);
while (*first && *second && max && RawUpper(*first) == RawUpper(*second)) {
--max;
++first;
++second;
}
if (max == 0) return 1;
return RawUpper(*first) == RawUpper(*second);
}
int APS5_VABI curl_mime_data_cb() {
@@ -1,6 +1,7 @@
#pragma once
#include "SceTypes.hpp"
#include <cstddef>
extern "C" {
@@ -22,7 +23,7 @@ int APS5_VABI curl_version();
int APS5_VABI curl_free();
int APS5_VABI curl_mvsnprintf();
int APS5_VABI curl_multi_socket_all();
int APS5_VABI curl_strequal();
int APS5_VABI curl_strequal(const char* first, const char* second);
int APS5_VABI curl_url_get();
int APS5_VABI curl_multi_strerror();
int APS5_VABI curl_easy_setopt();
@@ -43,7 +44,7 @@ int APS5_VABI curl_easy_send();
int APS5_VABI curl_easy_reset();
int APS5_VABI curl_easy_strerror();
int APS5_VABI curl_easy_init();
int APS5_VABI curl_strnequal();
int APS5_VABI curl_strnequal(const char* first, const char* second, size_t max);
int APS5_VABI curl_mime_data_cb();
int APS5_VABI curl_mvaprintf();
int APS5_VABI curl_url();
+71
View File
@@ -0,0 +1,71 @@
#include "prx/libc/include/general/VabiMacros.hpp"
#include "prx/libcurl/libcurl.hpp"
#include <cstdio>
#include <cstdlib>
#include <stdexcept>
#include <string>
static void Require(bool condition, int line) {
if (!condition) {
std::fprintf(stderr, "curl string check failed at line %d\n", line);
std::abort();
}
}
#define Check(value) Require((value), __LINE__)
template <typename TCall>
static bool ReportsNotImplemented(const char* name, TCall call) {
try {
call();
} catch (const std::runtime_error& error) {
return std::string(error.what()) == std::string(name) + " not implemented";
}
return false;
}
static void CheckEqual() {
Check(curl_strequal("", "") == 1);
Check(curl_strequal("Content-Type", "content-TYPE") == 1);
Check(curl_strequal("azAZ", "AZaz") == 1);
Check(curl_strequal("a1-_", "A1-_") == 1);
Check(curl_strequal("abc", "abd") == 0);
Check(curl_strequal("abc", "ab") == 0);
Check(curl_strequal("ab", "abc") == 0);
Check(curl_strequal("", "a") == 0);
Check(curl_strequal("a", "") == 0);
Check(curl_strequal("@", "`") == 0);
Check(curl_strequal("[", "{") == 0);
Check(curl_strequal("\xE9", "\xC9") == 0);
Check(curl_strequal("\xE9", "\xE9") == 1);
}
static void CheckBounded() {
Check(curl_strnequal("abc", "xyz", 0) == 1);
Check(curl_strnequal("", "a", 0) == 1);
Check(curl_strnequal("abcX", "ABCy", 3) == 1);
Check(curl_strnequal("abcX", "ABCy", 4) == 0);
Check(curl_strnequal("abc", "ab", 2) == 1);
Check(curl_strnequal("abc", "ab", 3) == 0);
Check(curl_strnequal("ab", "abc", 3) == 0);
Check(curl_strnequal("ab", "AB", 2) == 1);
Check(curl_strnequal("ab", "AB", 100) == 1);
Check(curl_strnequal("ab\0x", "ab\0y", 4) == 1);
Check(curl_strnequal("", "", 5) == 1);
Check(curl_strnequal("\xE9", "\xC9", 1) == 0);
}
static void CheckNullPointers() {
Check(ReportsNotImplemented("curl_strequal", [] { curl_strequal(nullptr, "a"); }));
Check(ReportsNotImplemented("curl_strequal", [] { curl_strequal("a", nullptr); }));
Check(ReportsNotImplemented("curl_strequal", [] { curl_strequal(nullptr, nullptr); }));
Check(ReportsNotImplemented("curl_strnequal", [] { curl_strnequal(nullptr, "a", 1); }));
Check(ReportsNotImplemented("curl_strnequal", [] { curl_strnequal("a", nullptr, 1); }));
Check(ReportsNotImplemented("curl_strnequal", [] { curl_strnequal(nullptr, nullptr, 0); }));
}
int main() {
CheckEqual();
CheckBounded();
CheckNullPointers();
return 0;
}
+5 -3
View File
@@ -1,8 +1,12 @@
# libcurl technical debt
### Unknown function info
- [curl_strequal, curl_strnequal](../../../core/libs/prx/libcurl/Export.cpp) (libcurl) - signatures and ASCII-only matching follow curl's public [curl_strequal documentation](https://curl.se/libcurl/c/curl_strequal.html) and [strcase.c](https://github.com/curl/curl/blob/curl-7_73_0/lib/strcase.c). No console or title caller was read. A null argument throws, because the module's curl version is unknown and curl differs: 7.73 dereferences it, while 8.10 treats two nulls as equal.
### Callable exports
- [Callable exports](../../../core/libs/prx/libcurl/Export.cpp) - 85 callable NIDs match the [public 3.20 catalogue](https://github.com/DNNDHH/PS5-3.20_Libs/blob/b2a77c09cd71c01f34c790cfbe98c751a13262ad/libcurl.c) and the [selected export metadata](https://gist.github.com/kyon-eth/996975adc28d0d270d032fb47eb297a7/52f3b6179ff69fbc0725e02ba146279ecd451f49) from two version-labelled images (SHA-256 `69baa557f91eba487275aa1b8e0aecd8dde1caa261eb2dd04106f8fa00e65361`). The labels are not authenticated. Prototypes and behavior are unverified; these declarations throw through `NotImplemented_nid_no_patch` and implement no runtime functionality.
- [Callable exports](../../../core/libs/prx/libcurl/Export.cpp) - 83 callable NIDs match the [public 3.20 catalogue](https://github.com/DNNDHH/PS5-3.20_Libs/blob/b2a77c09cd71c01f34c790cfbe98c751a13262ad/libcurl.c) and the [selected export metadata](https://gist.github.com/kyon-eth/996975adc28d0d270d032fb47eb297a7/52f3b6179ff69fbc0725e02ba146279ecd451f49) from two version-labelled images (SHA-256 `69baa557f91eba487275aa1b8e0aecd8dde1caa261eb2dd04106f8fa00e65361`). The labels are not authenticated. Prototypes and behavior are unverified; these declarations throw through `NotImplemented_nid_no_patch` and implement no runtime functionality.
| Name | NID |
| --- | --- |
@@ -24,7 +28,6 @@
| `curl_free` | `AAHmHrXOtv4` |
| `curl_mvsnprintf` | `BAz8Ji7lJls` |
| `curl_multi_socket_all` | `BhNAR5P2VEg` |
| `curl_strequal` | `CDG6wR08Ntw` |
| `curl_url_get` | `Cc+Qhdd4ons` |
| `curl_multi_strerror` | `Dfdbc8trvZg` |
| `curl_easy_setopt` | `DiBmbfiH8J4` |
@@ -45,7 +48,6 @@
| `curl_easy_reset` | `N5yPp5dHBQE` |
| `curl_easy_strerror` | `NGTkAHTkViY` |
| `curl_easy_init` | `NUbq2aNGojo` |
| `curl_strnequal` | `OJiHNjSOguc` |
| `curl_mime_data_cb` | `PoT9ByTU4ws` |
| `curl_mvaprintf` | `Pyz55DYmOrI` |
| `curl_url` | `QwbCXdumE84` |