android: Parse the APK directory tree, replace AAssetManager enum/getpathinfo.#15441
android: Parse the APK directory tree, replace AAssetManager enum/getpathinfo.#15441icculus wants to merge 2 commits intolibsdl-org:mainfrom
Conversation
|
maybe the part that initiates the call to CreateAPKNodes() could be moved (and executed the first time) in JNI_GetAssetPathInfo() so that apps scan the APK only if they need it. |
|
SDL_GetPathInfo("assets")
That was because I had a file |
I think it only does it the first time it's needed already, but I'll double-check. |
That sounds like a bug, I'll check it. |
1334a10 to
b1c89f6
Compare
Something like this could fix it: diff --git a/src/core/android/SDL_android.c b/src/core/android/SDL_android.c
index d63572e..9e8c101 100644
--- a/src/core/android/SDL_android.c
+++ b/src/core/android/SDL_android.c
@@ -1883,10 +1883,12 @@ static const APKNode *FindAPKNode(const char *path)
break;
}
const char *ptr = SDL_strchr(path, '/');
- const size_t slen = ptr ? ((size_t) (ptr - path)) : ((size_t) SDL_strlen(path) - 1);
+ const size_t slen = ptr ? ((size_t) (ptr - path)) : SDL_strlen(path);
const APKNode *node;
for (node = parent->children; node; node = node->next_sibling) {
- if (SDL_strncmp(path, node->name, slen) == 0) {
+ size_t nlen = SDL_strlen(node->name);
+ size_t max_len = SDL_max(slen, nlen);
+ if (SDL_strncmp(path, node->name, max_len) == 0) {
break;
}
}
@@ -1896,7 +1898,7 @@ static const APKNode *FindAPKNode(const char *path)
}
parent = node;
- path += slen + 1;
+ path += slen;
}
return parent;
Edit: |
If there's a call to SDL_GetPathInfo or SDL_EnumerateDirectory that needs the assets directory, it'll pull the APK info in on the first request, but it doesn't until then, including if you use those APIs and don't need the assets dir. Specifically, we do it in Internal_Android_Create_AssetManager, which Android_JNI_GetAssetPathInfo, etc, call if needed. |
…pathinfo. The AAssetManager won't supply this information to us, but it's just a zip file, so we can read its central directory ourselves. We can still use AAssetManager for file i/o to the APK's assets, so we don't have to deal with compression and other zipfile features. Fixes libsdl-org#15220. Reference Issue libsdl-org#15347.
b1c89f6 to
0d5c870
Compare
Just pushed a fix that was a little like this, thanks! |
|
A minor issue: An existing file with a trailing slash: |
It's called only once, yes, that's ok. But I mean't: |
|
Oh, if that's happening, that's a good point. (But the better question is why we are creating the assetmanager when we don't need it...I'll take a look at that.) |
String handling in C, still awesome. :) |
The AAssetManager won't supply this information to us, but it's just a zip file, so we can read its central directory ourselves. We can still use AAssetManager for file i/o to the APK's assets, so we don't have to deal with compression and other zipfile features, but now we can get a correct view of the filesystem for SDL_EnumerateDirectory() and SDL_GetPathInfo().
This was tested on an Android phone by stuffing enum_callback from testfilesystem.c into testsprite.c and seeing what it spits out when I added a bunch of files to the app's asset tree when building. As SDL currently operates, it can correctly enumerate subdirectories of the "assets" folder, but not the root of it and not if something matching is in the internal storage (see #15347 for discussion on that. We can build on top of this to solve that issue, but I left SDL behaving as before, for now).
The ZipDosTimeToSDLTime() function was lifted from PhysicsFS's zip_dos_time_to_physfs_time(), but that was entirely written by me and released under the same license as SDL. All the rest is from scratch.
Fixes #15220.
Reference Issue #15347.