Created
March 23, 2014 06:19
-
-
Save rlofc/9719452 to your computer and use it in GitHub Desktop.
Use physfs file system in GamePlay3D
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "Base.h" | |
#include "FileSystem.h" | |
#include "Properties.h" | |
#include "Stream.h" | |
#include "Platform.h" | |
#include <sys/types.h> | |
#include <sys/stat.h> | |
#ifdef WIN32 | |
#include <windows.h> | |
#include <tchar.h> | |
#include <stdio.h> | |
#include <direct.h> | |
#define gp_stat _stat | |
#define gp_stat_struct struct stat | |
#else | |
#define __EXT_POSIX2 | |
#include <libgen.h> | |
#include <dirent.h> | |
#define gp_stat stat | |
#define gp_stat_struct struct stat | |
#endif | |
#ifdef __ANDROID__ | |
#include <android/asset_manager.h> | |
extern AAssetManager* __assetManager; | |
#endif | |
namespace gameplay | |
{ | |
#ifdef __ANDROID__ | |
#include <unistd.h> | |
static void makepath(std::string path, int mode) | |
{ | |
std::vector<std::string> dirs; | |
while (path.length() > 0) | |
{ | |
int index = path.find('/'); | |
std::string dir = (index == -1 ) ? path : path.substr(0, index); | |
if (dir.length() > 0) | |
dirs.push_back(dir); | |
if (index + 1 >= path.length() || index == -1) | |
break; | |
path = path.substr(index + 1); | |
} | |
struct stat s; | |
std::string dirPath; | |
for (unsigned int i = 0; i < dirs.size(); i++) | |
{ | |
dirPath += "/"; | |
dirPath += dirs[i]; | |
if (stat(dirPath.c_str(), &s) != 0) | |
{ | |
// Directory does not exist. | |
if (mkdir(dirPath.c_str(), 0777) != 0) | |
{ | |
GP_ERROR("Failed to create directory: '%s'", dirPath.c_str()); | |
return; | |
} | |
} | |
} | |
return; | |
} | |
/** | |
* Returns true if the file exists in the android read-only asset directory. | |
*/ | |
static bool androidFileExists(const char* filePath) | |
{ | |
AAsset* asset = AAssetManager_open(__assetManager, filePath, AASSET_MODE_RANDOM); | |
if (asset) | |
{ | |
int lenght = AAsset_getLength(asset); | |
AAsset_close(asset); | |
return length > 0; | |
} | |
return false; | |
} | |
#endif | |
/** @script{ignore} */ | |
static std::string __resourcePath(""); | |
static std::map<std::string, std::string> __aliases; | |
/** | |
* Gets the fully resolved path. | |
* If the path is relative then it will be prefixed with the resource path. | |
* Aliases will be converted to a relative path. | |
* | |
* @param path The path to resolve. | |
* @param fullPath The full resolved path. (out param) | |
*/ | |
static void getFullPath(const char* path, std::string& fullPath) | |
{ | |
if (FileSystem::isAbsolutePath(path)) | |
{ | |
fullPath.assign(path); | |
} | |
else | |
{ | |
fullPath.assign(__resourcePath); | |
fullPath += FileSystem::resolvePath(path); | |
} | |
} | |
/** | |
* | |
* @script{ignore} | |
*/ | |
class FileStream : public Stream | |
{ | |
public: | |
friend class FileSystem; | |
~FileStream(); | |
virtual bool canRead(); | |
virtual bool canWrite(); | |
virtual bool canSeek(); | |
virtual void close(); | |
virtual size_t read(void* ptr, size_t size, size_t count); | |
virtual char* readLine(char* str, int num); | |
virtual size_t write(const void* ptr, size_t size, size_t count); | |
virtual bool eof(); | |
virtual size_t length(); | |
virtual long int position(); | |
virtual bool seek(long int offset, int origin); | |
virtual bool rewind(); | |
static FileStream* create(const char* filePath, const char* mode); | |
private: | |
FileStream(PHYSFS_file* file); | |
private: | |
PHYSFS_file* _file; | |
bool _canRead; | |
bool _canWrite; | |
}; | |
#ifdef __ANDROID__ | |
/** | |
* | |
* @script{ignore} | |
*/ | |
class FileStreamAndroid : public Stream | |
{ | |
public: | |
friend class FileSystem; | |
~FileStreamAndroid(); | |
virtual bool canRead(); | |
virtual bool canWrite(); | |
virtual bool canSeek(); | |
virtual void close(); | |
virtual size_t read(void* ptr, size_t size, size_t count); | |
virtual char* readLine(char* str, int num); | |
virtual size_t write(const void* ptr, size_t size, size_t count); | |
virtual bool eof(); | |
virtual size_t length(); | |
virtual long int position(); | |
virtual bool seek(long int offset, int origin); | |
virtual bool rewind(); | |
static FileStreamAndroid* create(const char* filePath, const char* mode); | |
private: | |
FileStreamAndroid(AAsset* asset); | |
private: | |
AAsset* _asset; | |
}; | |
#endif | |
///////////////////////////// | |
FileSystem::FileSystem() | |
{ | |
} | |
FileSystem::~FileSystem() | |
{ | |
} | |
void FileSystem::setResourcePath(const char* path) | |
{ | |
/* __resourcePath = path == NULL ? "" : path; */ | |
} | |
const char* FileSystem::getResourcePath() | |
{ | |
return __resourcePath.c_str(); | |
} | |
void FileSystem::loadResourceAliases(const char* aliasFilePath) | |
{ | |
Properties* properties = Properties::create(aliasFilePath); | |
if (properties) | |
{ | |
Properties* aliases; | |
while ((aliases = properties->getNextNamespace()) != NULL) | |
{ | |
loadResourceAliases(aliases); | |
} | |
} | |
SAFE_DELETE(properties); | |
} | |
void FileSystem::loadResourceAliases(Properties* properties) | |
{ | |
assert(properties); | |
const char* name; | |
while ((name = properties->getNextProperty()) != NULL) | |
{ | |
__aliases[name] = properties->getString(); | |
} | |
} | |
std::string FileSystem::displayFileDialog(size_t dialogMode, const char* title, const char* filterDescription, const char* filterExtensions, const char* initialDirectory) | |
{ | |
return Platform::displayFileDialog(dialogMode, title, filterDescription, filterExtensions, initialDirectory); | |
} | |
const char* FileSystem::resolvePath(const char* path) | |
{ | |
GP_ASSERT(path); | |
size_t len = strlen(path); | |
if (len > 1 && path[0] == '@') | |
{ | |
std::string alias(path + 1); | |
std::map<std::string, std::string>::const_iterator itr = __aliases.find(alias); | |
if (itr == __aliases.end()) | |
return path; // no matching alias found | |
return itr->second.c_str(); | |
} | |
return path; | |
} | |
bool FileSystem::listFiles(const char* dirPath, std::vector<std::string>& files) | |
{ | |
#ifdef WIN32 | |
std::string path(FileSystem::getResourcePath()); | |
if (dirPath && strlen(dirPath) > 0) | |
{ | |
path.append(dirPath); | |
} | |
path.append("/*"); | |
// Convert char to wchar | |
std::basic_string<TCHAR> wPath; | |
wPath.assign(path.begin(), path.end()); | |
WIN32_FIND_DATA FindFileData; | |
HANDLE hFind = FindFirstFile(wPath.c_str(), &FindFileData); | |
if (hFind == INVALID_HANDLE_VALUE) | |
{ | |
return false; | |
} | |
do | |
{ | |
// Add to the list if this is not a directory | |
if ((FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) | |
{ | |
// Convert wchar to char | |
std::basic_string<TCHAR> wfilename(FindFileData.cFileName); | |
std::string filename; | |
filename.assign(wfilename.begin(), wfilename.end()); | |
files.push_back(filename); | |
} | |
} while (FindNextFile(hFind, &FindFileData) != 0); | |
FindClose(hFind); | |
return true; | |
#else | |
std::string path(FileSystem::getResourcePath()); | |
if (dirPath && strlen(dirPath) > 0) | |
{ | |
path.append(dirPath); | |
} | |
path.append("/."); | |
bool result = false; | |
struct dirent* dp; | |
DIR* dir = opendir(path.c_str()); | |
if (dir != NULL) | |
{ | |
while ((dp = readdir(dir)) != NULL) | |
{ | |
std::string filepath(path); | |
filepath.append("/"); | |
filepath.append(dp->d_name); | |
struct stat buf; | |
if (!stat(filepath.c_str(), &buf)) | |
{ | |
// Add to the list if this is not a directory | |
if (!S_ISDIR(buf.st_mode)) | |
{ | |
files.push_back(dp->d_name); | |
} | |
} | |
} | |
closedir(dir); | |
result = true; | |
} | |
#ifdef __ANDROID__ | |
// List the files that are in the android APK at this path | |
AAssetDir* assetDir = AAssetManager_openDir(__assetManager, dirPath); | |
if (assetDir != NULL) | |
{ | |
AAssetDir_rewind(assetDir); | |
const char* file = NULL; | |
while ((file = AAssetDir_getNextFileName(assetDir)) != NULL) | |
{ | |
std::string filename(file); | |
// Check if this file was already added to the list because it was copied to the SD card. | |
if (find(files.begin(), files.end(), filename) == files.end()) | |
{ | |
files.push_back(filename); | |
} | |
} | |
AAssetDir_close(assetDir); | |
result = true; | |
} | |
#endif | |
return result; | |
#endif | |
} | |
bool FileSystem::fileExists(const char* filePath) | |
{ | |
GP_ASSERT(filePath); | |
#ifdef __ANDROID__ | |
if (androidFileExists(resolvePath(filePath))) | |
{ | |
return true; | |
} | |
#endif | |
std::string fullPath; | |
getFullPath(filePath, fullPath); | |
return PHYSFS_exists(fullPath.c_str()); | |
} | |
Stream* FileSystem::open(const char* path, size_t streamMode) | |
{ | |
char modeStr[] = "rb"; | |
if ((streamMode & WRITE) != 0) | |
modeStr[0] = 'w'; | |
#ifdef __ANDROID__ | |
if ((streamMode & WRITE) != 0) | |
{ | |
// Open a file on the SD card | |
std::string fullPath(__resourcePath); | |
fullPath += resolvePath(path); | |
size_t index = fullPath.rfind('/'); | |
if (index != std::string::npos) | |
{ | |
std::string directoryPath = fullPath.substr(0, index); | |
struct stat s; | |
if (stat(directoryPath.c_str(), &s) != 0) | |
makepath(directoryPath, 0777); | |
} | |
return FileStream::create(fullPath.c_str(), modeStr); | |
} | |
else | |
{ | |
// Open a file in the read-only asset directory | |
return FileStreamAndroid::create(resolvePath(path), modeStr); | |
} | |
#else | |
std::string fullPath; | |
getFullPath(path, fullPath); | |
FileStream* stream = FileStream::create(fullPath.c_str(), modeStr); | |
return stream; | |
#endif | |
} | |
PHYSFS_file* FileSystem::openFile(const char* filePath, const char* mode) | |
{ | |
GP_ASSERT(filePath); | |
GP_ASSERT(mode); | |
std::string fullPath; | |
getFullPath(filePath, fullPath); | |
createFileFromAsset(filePath); | |
PHYSFS_file* file = NULL; | |
switch (mode[0]) { | |
case 'r': file = PHYSFS_openRead(fullPath.c_str()); break; | |
case 'w': file = PHYSFS_openWrite(fullPath.c_str()); break; | |
case 'a': file = PHYSFS_openAppend(fullPath.c_str()); break; | |
} | |
return file; | |
} | |
char* FileSystem::readAll(const char* filePath, int* fileSize) | |
{ | |
GP_ASSERT(filePath); | |
// Open file for reading. | |
std::auto_ptr<Stream> stream(open(filePath)); | |
if (stream.get() == NULL) | |
{ | |
GP_ERROR("Failed to load file: %s", filePath); | |
return NULL; | |
} | |
size_t size = stream->length(); | |
// Read entire file contents. | |
char* buffer = new char[size + 1]; | |
size_t read = stream->read(buffer, 1, size); | |
if (read != size) | |
{ | |
GP_ERROR("Failed to read complete contents of file '%s' (amount read vs. file size: %u < %u).", filePath, read, size); | |
SAFE_DELETE_ARRAY(buffer); | |
return NULL; | |
} | |
// Force the character buffer to be NULL-terminated. | |
buffer[size] = '\0'; | |
if (fileSize) | |
{ | |
*fileSize = (int)size; | |
} | |
return buffer; | |
} | |
bool FileSystem::isAbsolutePath(const char* filePath) | |
{ | |
if (filePath == 0 || filePath[0] == '\0') | |
return false; | |
#ifdef WIN32 | |
if (filePath[1] != '\0') | |
{ | |
char first = filePath[0]; | |
return (filePath[1] == ':' && ((first >= 'a' && first <= 'z') || (first >= 'A' && first <= 'Z'))); | |
} | |
return false; | |
#else | |
return filePath[0] == '/'; | |
#endif | |
} | |
void FileSystem::createFileFromAsset(const char* path) | |
{ | |
#ifdef __ANDROID__ | |
static std::set<std::string> upToDateAssets; | |
GP_ASSERT(path); | |
std::string fullPath(__resourcePath); | |
std::string resolvedPath = FileSystem::resolvePath(path); | |
fullPath += resolvedPath; | |
std::string directoryPath = fullPath.substr(0, fullPath.rfind('/')); | |
struct stat s; | |
if (stat(directoryPath.c_str(), &s) != 0) | |
makepath(directoryPath, 0777); | |
// To ensure that the files on the file system corresponding to the assets in the APK bundle | |
// are always up to date (and in sync), we copy them from the APK to the file system once | |
// for each time the process (game) runs. | |
if (upToDateAssets.find(fullPath) == upToDateAssets.end()) | |
{ | |
AAsset* asset = AAssetManager_open(__assetManager, resolvedPath.c_str(), AASSET_MODE_RANDOM); | |
if (asset) | |
{ | |
const void* data = AAsset_getBuffer(asset); | |
int length = AAsset_getLength(asset); | |
PHYSFS_file* file = PHYSFS_openWrite(fullPath.c_str()); | |
if (file != NULL) | |
{ | |
int ret = PHYSFS_write(file, data, sizeof(unsigned char), length); | |
if (PHYSFS_close(file) != 0) | |
{ | |
GP_ERROR("Failed to close file on file system created from APK asset '%s'.", path); | |
return; | |
} | |
if (ret != length) | |
{ | |
GP_ERROR("Failed to write all data from APK asset '%s' to file on file system.", path); | |
return; | |
} | |
} | |
else | |
{ | |
GP_ERROR("Failed to create file on file system from APK asset '%s'.", path); | |
return; | |
} | |
upToDateAssets.insert(fullPath); | |
} | |
} | |
#endif | |
} | |
std::string FileSystem::getDirectoryName(const char* path) | |
{ | |
if (path == NULL || strlen(path) == 0) | |
{ | |
return ""; | |
} | |
#ifdef WIN32 | |
char drive[_MAX_DRIVE]; | |
char dir[_MAX_DIR]; | |
_splitpath(path, drive, dir, NULL, NULL); | |
std::string dirname; | |
size_t driveLength = strlen(drive); | |
if (driveLength > 0) | |
{ | |
dirname.reserve(driveLength + strlen(dir)); | |
dirname.append(drive); | |
dirname.append(dir); | |
} | |
else | |
{ | |
dirname.assign(dir); | |
} | |
std::replace(dirname.begin(), dirname.end(), '\\', '/'); | |
return dirname; | |
#else | |
// dirname() modifies the input string so create a temp string | |
std::string dirname; | |
char* tempPath = new char[strlen(path) + 1]; | |
strcpy(tempPath, path); | |
char* dir = ::dirname(tempPath); | |
if (dir && strlen(dir) > 0) | |
{ | |
dirname.assign(dir); | |
// dirname() strips off the trailing '/' so add it back to be consistent with Windows | |
dirname.append("/"); | |
} | |
SAFE_DELETE_ARRAY(tempPath); | |
return dirname; | |
#endif | |
} | |
std::string FileSystem::getExtension(const char* path) | |
{ | |
const char* str = strrchr(path, '.'); | |
if (str == NULL) | |
return ""; | |
std::string ext; | |
size_t len = strlen(str); | |
for (size_t i = 0; i < len; ++i) | |
ext += std::toupper(str[i]); | |
return ext; | |
} | |
////////////////// | |
FileStream::FileStream(PHYSFS_file* file) | |
: _file(file), _canRead(false), _canWrite(false) | |
{ | |
} | |
FileStream::~FileStream() | |
{ | |
if (_file) | |
{ | |
close(); | |
} | |
} | |
FileStream* FileStream::create(const char* filePath, const char* mode) | |
{ | |
PHYSFS_file* file = NULL; | |
switch (mode[0]) { | |
case 'r': file = PHYSFS_openRead(filePath); break; | |
case 'w': file = PHYSFS_openWrite(filePath); break; | |
case 'a': file = PHYSFS_openAppend(filePath); break; | |
} | |
if (file) | |
{ | |
FileStream* stream = new FileStream(file); | |
const char* s = mode; | |
while (s != NULL && *s != '\0') | |
{ | |
if (*s == 'r') | |
stream->_canRead = true; | |
else if (*s == 'w') | |
stream->_canWrite = true; | |
++s; | |
} | |
return stream; | |
} | |
return NULL; | |
} | |
bool FileStream::canRead() | |
{ | |
return _file && _canRead; | |
} | |
bool FileStream::canWrite() | |
{ | |
return _file && _canWrite; | |
} | |
bool FileStream::canSeek() | |
{ | |
return _file != NULL; | |
} | |
void FileStream::close() | |
{ | |
if (_file) | |
PHYSFS_close(_file); | |
_file = NULL; | |
} | |
size_t FileStream::read(void* ptr, size_t size, size_t count) | |
{ | |
if (!_file) | |
return 0; | |
return PHYSFS_read(_file, ptr, size, count); | |
} | |
char* FileStream::readLine(char* str, int num) | |
{ | |
if (!_file) | |
return 0; | |
return PHYSFS_fgets(str, num, _file); | |
} | |
size_t FileStream::write(const void* ptr, size_t size, size_t count) | |
{ | |
if (!_file) | |
return 0; | |
return PHYSFS_write(_file, ptr, size, count); | |
} | |
bool FileStream::eof() | |
{ | |
if (!_file || PHYSFS_eof(_file)) | |
return true; | |
return ((size_t)position()) >= length(); | |
} | |
size_t FileStream::length() | |
{ | |
return PHYSFS_fileLength(_file); | |
} | |
long int FileStream::position() | |
{ | |
if (!_file) | |
return -1; | |
return PHYSFS_tell(_file); | |
} | |
bool FileStream::seek(long int offset, int origin) | |
{ | |
if (!_file) | |
return false; | |
switch (origin) { | |
case SEEK_CUR: | |
offset = position() + offset; | |
break; | |
case SEEK_END: | |
offset = length() - offset; | |
break; | |
case SEEK_SET: | |
break; | |
default: | |
return false; | |
} | |
return PHYSFS_seek(_file, offset) != 0; | |
} | |
bool FileStream::rewind() | |
{ | |
if (canSeek()) | |
{ | |
seek(0,SEEK_SET); | |
return true; | |
} | |
return false; | |
} | |
//////////////////////////////// | |
#ifdef __ANDROID__ | |
FileStreamAndroid::FileStreamAndroid(AAsset* asset) | |
: _asset(asset) | |
{ | |
} | |
FileStreamAndroid::~FileStreamAndroid() | |
{ | |
if (_asset) | |
close(); | |
} | |
FileStreamAndroid* FileStreamAndroid::create(const char* filePath, const char* mode) | |
{ | |
AAsset* asset = AAssetManager_open(__assetManager, filePath, AASSET_MODE_RANDOM); | |
if (asset) | |
{ | |
FileStreamAndroid* stream = new FileStreamAndroid(asset); | |
return stream; | |
} | |
return NULL; | |
} | |
bool FileStreamAndroid::canRead() | |
{ | |
return true; | |
} | |
bool FileStreamAndroid::canWrite() | |
{ | |
return false; | |
} | |
bool FileStreamAndroid::canSeek() | |
{ | |
return true; | |
} | |
void FileStreamAndroid::close() | |
{ | |
if (_asset) | |
AAsset_close(_asset); | |
_asset = NULL; | |
} | |
size_t FileStreamAndroid::read(void* ptr, size_t size, size_t count) | |
{ | |
int result = AAsset_read(_asset, ptr, size * count); | |
return result > 0 ? ((size_t)result) / size : 0; | |
} | |
char* FileStreamAndroid::readLine(char* str, int num) | |
{ | |
if (num <= 0) | |
return NULL; | |
char c = 0; | |
size_t maxCharsToRead = num - 1; | |
for (size_t i = 0; i < maxCharsToRead; ++i) | |
{ | |
size_t result = read(&c, 1, 1); | |
if (result != 1) | |
{ | |
str[i] = '\0'; | |
break; | |
} | |
if (c == '\n') | |
{ | |
str[i] = c; | |
str[i + 1] = '\0'; | |
break; | |
} | |
else if(c == '\r') | |
{ | |
str[i] = c; | |
// next may be '\n' | |
size_t pos = position(); | |
char nextChar = 0; | |
if (read(&nextChar, 1, 1) != 1) | |
{ | |
// no more characters | |
str[i + 1] = '\0'; | |
break; | |
} | |
if (nextChar == '\n') | |
{ | |
if (i == maxCharsToRead - 1) | |
{ | |
str[i + 1] = '\0'; | |
break; | |
} | |
else | |
{ | |
str[i + 1] = nextChar; | |
str[i + 2] = '\0'; | |
break; | |
} | |
} | |
else | |
{ | |
seek(pos, SEEK_SET); | |
str[i + 1] = '\0'; | |
break; | |
} | |
} | |
str[i] = c; | |
} | |
return str; // what if first read failed? | |
} | |
size_t FileStreamAndroid::write(const void* ptr, size_t size, size_t count) | |
{ | |
return 0; | |
} | |
bool FileStreamAndroid::eof() | |
{ | |
return position() >= length(); | |
} | |
size_t FileStreamAndroid::length() | |
{ | |
return (size_t)AAsset_getLength(_asset); | |
} | |
long int FileStreamAndroid::position() | |
{ | |
return AAsset_getLength(_asset) - AAsset_getRemainingLength(_asset); | |
} | |
bool FileStreamAndroid::seek(long int offset, int origin) | |
{ | |
return AAsset_seek(_asset, offset, origin) != -1; | |
} | |
bool FileStreamAndroid::rewind() | |
{ | |
if (canSeek()) | |
{ | |
return AAsset_seek(_asset, 0, SEEK_SET) != -1; | |
} | |
return false; | |
} | |
#endif | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef FILESYSTEM_H_ | |
#define FILESYSTEM_H_ | |
#include "Stream.h" | |
#include <string> | |
#include "physfs.h" | |
namespace gameplay | |
{ | |
class Properties; | |
/** | |
* Defines a set of functions for interacting with the device file system. | |
*/ | |
class FileSystem | |
{ | |
public: | |
/** | |
* Mode flags for opening a stream. | |
* | |
* @script{ignore} | |
*/ | |
enum StreamMode | |
{ | |
READ = 1, | |
WRITE = 2 | |
}; | |
/** | |
* Mode flags for displaying a dialog. | |
* | |
* @script{ignore} | |
*/ | |
enum DialogMode | |
{ | |
OPEN, | |
SAVE | |
}; | |
/** | |
* Destructor. | |
*/ | |
~FileSystem(); | |
/** | |
* Sets the path to the root of the resources folder for the game. | |
* | |
* Once set, all resource/file loading will load from the given path. | |
* The default resource path is "./". | |
* | |
* @param path The path to the root of the resources folder. | |
*/ | |
static void setResourcePath(const char* path); | |
/** | |
* Returns the currently set resource path. | |
* | |
* @return The currently set resource path. | |
*/ | |
static const char* getResourcePath(); | |
/** | |
* Loads a properties file containing a list of filesystem aliases. | |
* | |
* The specified aliases file is a valid properties file that contains one | |
* or more namespaces with a list of filesystem aliases that will be used | |
* to establish soft links to files when reading files through this class. | |
* | |
* This can be helpful for managing loading of resources that may change | |
* from one platform to another (such as texture formats). An aliases | |
* file per-platform can be maintained and asset loading code can refer | |
* to the alias name instead of the actual hard file name. | |
* | |
* @param aliasFilePath Path to a properties file containing filesystem aliases. | |
* | |
* @see Properties | |
*/ | |
static void loadResourceAliases(const char* aliasFilePath); | |
/** | |
* Loads a set of filesystem aliases from the given Properties object. | |
* | |
* The specified properties object contains a single namespace with a list | |
* of filesystem aliases that will be used to establish soft links to files | |
* when reading files through this class. | |
* | |
* This can be helpful for managing loading of resources that may change | |
* from one platform to another (such as texture formats). An aliases | |
* file per-platform can be maintained and asset loading code can refer | |
* to the alias name instead of the actual hard file name. | |
* | |
* @param properties Properties object containing filesystem aliases. | |
* | |
* @see Properties | |
*/ | |
static void loadResourceAliases(Properties* properties); | |
/** | |
* Displays an open or save dialog using the native platform dialog system. | |
* | |
* @param dialogMode The mode of the dialog. (Ex. OPEN or SAVE) | |
* @param title The title of the dialog. (Ex. Select File or Save File) | |
* @param filterDescription The file filter description. (Ex. All Files or Image Files) | |
* @param filterExtensions The extensions to filter on. (Ex. png;bmp) | |
* @param initialDirectory The initial directory to start. NULL runs from the executable directory. | |
* @return The file that is opened or saved, or an empty string if canceled. | |
* | |
* @script{ignore} | |
*/ | |
static std::string displayFileDialog(size_t dialogMode, const char* title, const char* filterDescription, const char* filterExtensions, const char* initialDirectory); | |
/** | |
* Resolves a filesystem path. | |
* | |
* If the specified path is a filesystem alias, the alias will be | |
* resolved and the physical file will be returned. | |
* | |
* Note that this method does not convert a relative path to an | |
* absolute filesystem path. | |
* | |
* @param path Path to resolve. | |
* | |
* @return The resolved file path. | |
*/ | |
static const char* resolvePath(const char* path); | |
/** | |
* Lists the files in the specified directory and adds the files to the vector. Excludes directories. | |
* | |
* @param dirPath Directory path relative to the path set in <code>setResourcePath(const char*)</code>. | |
* @param files The vector to append the files to. | |
* | |
* @return True if successful, false if error. | |
* | |
* @script{ignore} | |
*/ | |
static bool listFiles(const char* dirPath, std::vector<std::string>& files); | |
/** | |
* Checks if the file at the given path exists. | |
* | |
* @param filePath The path to the file. | |
* | |
* @return <code>true</code> if the file exists; <code>false</code> otherwise. | |
*/ | |
static bool fileExists(const char* filePath); | |
/** | |
* Opens a byte stream for the given resource path. | |
* | |
* If <code>path</code> is a file path, the file at the specified location is opened relative to the currently set | |
* resource path. | |
* | |
* @param path The path to the resource to be opened, relative to the currently set resource path. | |
* @param streamMode The stream mode used to open the file. | |
* | |
* @return A stream that can be used to read or write to the file depending on the mode. | |
* Returns NULL if there was an error. (Request mode not supported). | |
* | |
* @script{ignore} | |
*/ | |
static Stream* open(const char* path, size_t streamMode = READ); | |
/** | |
* Opens the specified file. | |
* | |
* The file at the specified location is opened, relative to the currently set | |
* resource path. | |
* | |
* @param filePath The path to the file to be opened, relative to the currently set resource path. | |
* @param mode The mode used to open the file, passed directly to fopen. | |
* | |
* @return A pointer to a FILE object that can be used to identify the stream or NULL on error. | |
* | |
* @see setResourcePath(const char*) | |
* @script{ignore} | |
*/ | |
static PHYSFS_file* openFile(const char* filePath, const char* mode); | |
/** | |
* Reads the entire contents of the specified file and returns its contents. | |
* | |
* The returned character array is allocated with new[] and must therefore | |
* deleted by the caller using delete[]. | |
* | |
* @param filePath The path to the file to be read. | |
* @param fileSize The size of the file in bytes (optional). | |
* | |
* @return A newly allocated (NULL-terminated) character array containing the | |
* contents of the file, or NULL if the file could not be read. | |
*/ | |
static char* readAll(const char* filePath, int* fileSize = NULL); | |
/** | |
* Determines if the file path is an absolute path for the current platform. | |
* | |
* @param filePath The file path to test. | |
* | |
* @return True if the path is an absolute path or false otherwise. | |
*/ | |
static bool isAbsolutePath(const char* filePath); | |
/** | |
* Creates a file on the file system from the specified asset (Android-specific). | |
* | |
* @param path The path to the file. | |
*/ | |
static void createFileFromAsset(const char* path); | |
/** | |
* Returns the directory name up to and including the trailing '/'. | |
* | |
* This is a lexical method so it does not verify that the directory exists. | |
* Back slashes will be converted to forward slashes. | |
* | |
* - "res/image.png" will return "res/" | |
* - "image.png" will return "" | |
* - "c:\foo\bar\image.png" will return "c:/foo/bar/" | |
* | |
* @param path The file path. May be relative or absolute, forward or back slashes. May be NULL. | |
* | |
* @return The directory name with the trailing '/'. Returns "" if path is NULL or the path does not contain a directory. | |
*/ | |
static std::string getDirectoryName(const char* path); | |
/** | |
* Returns the extension of the given file path. | |
* | |
* The extension returned includes all character after and including the last '.' | |
* in the file path. The extension is returned as all uppercase. | |
* | |
* If the path does not contain an extension, an empty string is returned. | |
* | |
* @param path File path. | |
* | |
* @return The file extension, all uppercase, including the '.'. | |
*/ | |
static std::string getExtension(const char* path); | |
private: | |
/** | |
* Constructor. | |
*/ | |
FileSystem(); | |
}; | |
} | |
#endif |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifdef __linux__ | |
#include "gameplay.h" | |
using namespace gameplay; | |
extern int __argc; | |
extern char** __argv; | |
#include "physfs.h" | |
/** | |
* Main entry point. | |
*/ | |
int main(int argc, char** argv) | |
{ | |
__argc = argc; | |
__argv = argv; | |
PHYSFS_init(argv[0]); | |
PHYSFS_addToSearchPath("./", 0); | |
PHYSFS_addToSearchPath("./res", 0); | |
Game* game = Game::getInstance(); | |
Platform* platform = Platform::create(game); | |
GP_ASSERT(platform); | |
int result = platform->enterMessagePump(); | |
delete platform; | |
return result; | |
} | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment