RtB/src/fio.cpp

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