88 lines
3.2 KiB
C++
88 lines
3.2 KiB
C++
/* ================================================================
|
|
FIO functionality
|
|
----------------
|
|
fio.cpp/fio.hpp provide functionality for accessing files within RtB. File access is generally assumed to be C-style *FILE.
|
|
|
|
If any file is attempted to be read or written to, fio.hpp should be included first.
|
|
================================================================ */
|
|
#include "fio.hpp"
|
|
#include "Log.hpp"
|
|
#include <string.h> // malloc
|
|
/* ======== Asset data access ======== */
|
|
// Assets are files that may exist in an external storage directory (iOS/Android), a user data directory(all), or in the application itself (iOS/Android/OSX).
|
|
/* asset_fileToMem
|
|
This function attempts to load in the given filename into a memory buffer. This memory buffer is allocated by the function and _MUST_ be free()d by the user. If the file does not exist, an error is reported and NULL is returned.
|
|
*/
|
|
size_t asset_fileToMem(const char *filename, char **buffer) {
|
|
char chunk[1024];
|
|
FILE *file = asset_fopen(filename, "r");
|
|
if (file == NULL) {
|
|
LOG(LOG_ERROR) << FUNC_NAME << ": could not open " << filename;
|
|
return 0;
|
|
}
|
|
fseek(file, 0, SEEK_END);
|
|
size_t size = ftell(file)+1;
|
|
fseek(file, 0, SEEK_SET);
|
|
|
|
*buffer = (char*)malloc(size*sizeof(char));
|
|
int n = 0;
|
|
size_t offset = 0;
|
|
while ((n = fread(chunk, 1, 1024, file))) {
|
|
memcpy((*buffer)+offset, chunk, n);
|
|
offset += n;
|
|
}
|
|
fclose(file);
|
|
return offset;
|
|
}
|
|
FILE *asset_fopen(const char *filename, const char *mode) {
|
|
// TODO: this function should first check the user assets directory for the given filename then fallback to the built-in assets directory
|
|
// OS X: Library/RtB/ OR RtB.app/Contents/Resources
|
|
// iOS: <Application_Home>/Library/ OR RtB.app/Contents/Resources
|
|
// Android: /data/data/com.polymathic.RtB/files/ OR Assets (jar)
|
|
// Linux: <current dir> OR ~/.RtB
|
|
// Windows: <current dir> OR <User Dir>/AppData/Local/RtB
|
|
#ifdef __ANDROID__
|
|
return apk_fopen(filename, mode);
|
|
#elif _WIN32
|
|
FILE *file;
|
|
fopen_s(&file, filename, mode);
|
|
return file;
|
|
#else
|
|
return fopen(filename, mode);
|
|
#endif
|
|
}
|
|
/* ======== Android apk access ======== */
|
|
#ifdef __ANDROID__
|
|
#include <errno.h>
|
|
#include <jni.h>
|
|
#include <android/asset_manager.h>
|
|
#include <android/asset_manager_jni.h>
|
|
static int apk_read(void *asset, char *buf, int size) {
|
|
return AAsset_read((AAsset*)asset, buf, size);
|
|
}
|
|
static int apk_write(void *asset, const char *buf, int size) {
|
|
return EACCES;
|
|
}
|
|
static fpos_t apk_seek(void *asset, fpos_t offset, int whence) {
|
|
return AAsset_seek((AAsset*)asset, offset, whence);
|
|
}
|
|
static int apk_close(void *asset) {
|
|
AAsset_close((AAsset*)asset);
|
|
return 0;
|
|
}
|
|
AAssetManager* asset_manager;
|
|
void apk_set_asset_manager(AAssetManager* manager) {
|
|
asset_manager = manager;
|
|
}
|
|
JNIEXPORT void JNICALL Java_com_polymathic_RtB_RtB_setAssetManager(JNIEnv* env, jobject obj, jobject assetManager) {
|
|
AAssetManager *mgr = AAssetManager_fromJava(env, assetManager);
|
|
apk_set_asset_manager(mgr);
|
|
}
|
|
FILE* apk_fopen(const char *filename, const char *mode) {
|
|
if (mode[0] == 'w') return NULL;
|
|
AAsset *asset = AAssetManager_open(asset_manager, filename, 0);
|
|
if (!asset) return NULL;
|
|
return funopen(asset, apk_read, apk_write, apk_seek, apk_close);
|
|
}
|
|
#endif
|