Properly format and fix a mem leak.

This commit is contained in:
MAJigsaw77
2025-10-09 18:29:16 +08:00
committed by Hundrec
parent fb8fd8b7d4
commit e139ae252f
3 changed files with 108 additions and 52 deletions
+11 -2
View File
@@ -1,12 +1,21 @@
package funkin.external.apple;
#if ios
#if ((ios || macos) && cpp)
/**
* A utility class for FNFC loading on apple devices.
*/
@:build(funkin.util.macro.LinkerMacro.xml('project/Build.xml'))
@:include('FNFCUtil.hpp')
@:unreflective
extern class FNFCUtil
{
@:native('copyFNFCIntoCache')
/**
* Copies the FNFC resource from the specified URL into the cache.
*
* @param url The URL of the FNFC resource to copy into the cache.
* @param callback A function to be called when the copy operation completes.
*/
@:native('Apple_FNFCUtil_CopyFNFCIntoCache')
static function copyFNFCIntoCache(url:cpp.ConstCharStar, callback:cpp.Callable<(event:cpp.ConstCharStar, value:cpp.ConstCharStar) -> Void>):Void;
}
#end
+13 -1
View File
@@ -1,5 +1,17 @@
#pragma once
/**
* Function pointer type for handling events with associated string values.
*
* @param event The name of the event as a null-terminated string.
* @param value The value associated with the event as a null-terminated string.
*/
typedef void (*FNFCCallback)(const char* event, const char* value);
void copyFNFCIntoCache(const char *url, FNFCCallback callback);
/**
* Copies the FNFC resource from the specified URL into the cache.
*
* @param url The URL of the FNFC resource to copy into the cache.
* @param callback A function to be called when the copy operation completes.
*/
void Apple_FNFCUtil_CopyFNFCIntoCache(const char *url, FNFCCallback callback);
+84 -49
View File
@@ -3,95 +3,130 @@
static FNFCCallback fnfcCallback = nullptr;
void copyFNFCIntoCache(const char *url, FNFCCallback callback)
void Apple_FNFCUtil_CopyFNFCIntoCache(const char *url, FNFCCallback callback)
{
if (!fnfcCallback) {
fnfcCallback = callback;
#if TARGET_OS_IOS
if (!fnfcCallback)
{
fnfcCallback = callback;
}
if (!url) {
if (fnfcCallback) {
dispatch_async(dispatch_get_main_queue(), ^{
fnfcCallback("FNFC_URL_NIL", "The URL passed to the conversion was null.");
});
}
if (!url)
{
if (fnfcCallback)
{
dispatch_async(dispatch_get_main_queue(), ^{
fnfcCallback("FNFC_URL_NIL", "The URL passed to the conversion was null.");
});
}
return;
}
NSString *urlString = [NSString stringWithUTF8String:url];
NSURL *fileURL = [NSURL URLWithString:urlString];
if (!fileURL || !fileURL.isFileURL) {
if (!fileURL || !fileURL.isFileURL)
{
fileURL = [NSURL fileURLWithPath:urlString];
}
if (!fileURL || !fileURL.isFileURL) {
if (fnfcCallback) {
dispatch_async(dispatch_get_main_queue(), ^{
NSString *msg = [NSString stringWithFormat:@"The passed URL '%@' doesn't point at a FNFC file.", urlString];
fnfcCallback("FNFC_FILE_MISMATC", [msg UTF8String]);
});
}
if (!fileURL || !fileURL.isFileURL)
{
if (fnfcCallback)
{
dispatch_async(dispatch_get_main_queue(), ^{
char *msg = strdup([[NSString stringWithFormat:@"The passed URL '%@' doesn't point at a FNFC file.", urlString] UTF8String]);
fnfcCallback("FNFC_FILE_MISMATC", msg);
free(msg);
});
}
return;
}
BOOL accessed = [fileURL startAccessingSecurityScopedResource];
if (!accessed) {
if (fnfcCallback) {
dispatch_async(dispatch_get_main_queue(), ^{
NSString *msg = [NSString stringWithFormat:@"Failed to get access to URL '%@'.", urlString];
fnfcCallback("FNFC_FILE_ACCESS_ERR", [msg UTF8String]);
});
}
if (!accessed)
{
if (fnfcCallback)
{
dispatch_async(dispatch_get_main_queue(), ^{
char *msg = strdup([[NSString stringWithFormat:@"Failed to get access to URL '%@'.", urlString] UTF8String]);
fnfcCallback("FNFC_FILE_ACCESS_ERR", msg);
free(msg);
});
}
}
NSString *sourcePath = [fileURL path];
NSString *filename = [sourcePath lastPathComponent];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *cacheDir = [[paths firstObject] stringByAppendingPathComponent:@"fnfc"];
NSFileManager *fm = [NSFileManager defaultManager];
NSError *dirError = nil;
if (![fm fileExistsAtPath:cacheDir]) {
if(![fm createDirectoryAtPath:cacheDir withIntermediateDirectories:YES attributes:nil error:&dirError]) {
if (fnfcCallback) {
dispatch_async(dispatch_get_main_queue(), ^{
NSString *msg = [NSString stringWithFormat:@"Failed to create directory %@: %@", cacheDir, dirError];
fnfcCallback("FNFC_DIR_CREATE_ERR", [msg UTF8String]);
});
}
if (![fm fileExistsAtPath:cacheDir])
{
if (![fm createDirectoryAtPath:cacheDir withIntermediateDirectories:YES attributes:nil error:&dirError])
{
if (fnfcCallback)
{
dispatch_async(dispatch_get_main_queue(), ^{
char *msg = strdup([[NSString stringWithFormat:@"Failed to create directory %@: %@", cacheDir, dirError] UTF8String]);
fnfcCallback("FNFC_DIR_CREATE_ERR", msg);
free(msg);
});
}
}
}
NSString *destPath = [cacheDir stringByAppendingPathComponent:filename];
NSError *error = nil;
if ([fm fileExistsAtPath:destPath]) {
if ([fm fileExistsAtPath:destPath])
{
[fm removeItemAtPath:destPath error:nil];
}
if (![fm copyItemAtPath:sourcePath toPath:destPath error:&error]) {
if (fnfcCallback) {
dispatch_async(dispatch_get_main_queue(), ^{
NSString *msg = [NSString stringWithFormat:@"Failed to copy FNFC from URL %@ to directory %@: %@", sourcePath, destPath, error];
fnfcCallback("FNFC_COPY_ERR", [msg UTF8String]);
});
}
if (accessed) {
if (![fm copyItemAtPath:sourcePath toPath:destPath error:&error])
{
if (fnfcCallback)
{
dispatch_async(dispatch_get_main_queue(), ^{
char *msg = strdup([[NSString stringWithFormat:@"Failed to copy FNFC from URL %@ to directory %@: %@", sourcePath, destPath, error] UTF8String]);
fnfcCallback("FNFC_COPY_ERR", msg);
free(msg);
});
}
if (accessed)
{
[fileURL stopAccessingSecurityScopedResource];
}
return;
}
if (accessed) {
if (accessed)
{
[fileURL stopAccessingSecurityScopedResource];
}
if (fnfcCallback) {
const char *val = strdup([destPath UTF8String]);
dispatch_async(dispatch_get_main_queue(), ^{
fnfcCallback("FNFC_RESULTS", val);
free((void *)val);
});
}
if (fnfcCallback)
{
dispatch_async(dispatch_get_main_queue(), ^{
char *val = strdup([destPath UTF8String]);
fnfcCallback("FNFC_RESULTS", val);
free(val);
});
}
#endif
}