blob: 846ee4c76fbd59dc6905a93bbd18cbe6b716905e [file]
#include <string>
#include <map>
#ifdef WIN32
#include "shlobj.h"
#else
#include <dirent.h>
#include <sys/stat.h>
#endif
#include "SDL.h"
#include "File.hpp"
static std::string basePath;
static std::map<uint32_t, SDL_RWops *> open_files;
static uint32_t current_file_handle = 0;
void setup_base_path()
{
auto basePathPtr = SDL_GetBasePath();
basePath = std::string(basePathPtr);
SDL_free(basePathPtr);
}
int32_t open_file(std::string name) {
auto file = SDL_RWFromFile((basePath + name).c_str(), "rb");
if(file) {
current_file_handle++;
open_files[current_file_handle] = file;
return current_file_handle;
}
return -1;
}
int32_t read_file(uint32_t fh, uint32_t offset, uint32_t length, char *buffer) {
auto file = open_files[fh];
if(file && SDL_RWseek(file, offset, RW_SEEK_SET) != -1) {
size_t bytes_read = SDL_RWread(file, buffer, 1, length);
if(bytes_read > 0)
return bytes_read;
}
return -1;
}
int32_t close_file(uint32_t fh) {
return SDL_RWclose(open_files[fh]) == 0 ? 0 : -1;
}
uint32_t get_file_length(uint32_t fh)
{
auto file = open_files[fh];
SDL_RWseek(file, 0, RW_SEEK_END);
return SDL_RWtell(file);
}
std::vector<blit::FileInfo> list_files(std::string path) {
std::vector<blit::FileInfo> ret;
#ifdef WIN32
HANDLE file;
WIN32_FIND_DATAA findData;
file = FindFirstFileA((basePath + path + "\\*").c_str(), &findData);
if(file == INVALID_HANDLE_VALUE)
return ret;
do
{
blit::FileInfo info;
info.name = findData.cFileName;
if(info.name == "." || info.name == "..")
continue;
info.flags = 0;
if(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
info.flags |= blit::FileFlags::directory;
ret.push_back(info);
}
while(FindNextFileA(file, &findData) != 0);
FindClose(file);
#else
auto dir = opendir((basePath + path).c_str());
if(!dir)
return ret;
struct dirent *ent;
while((ent = readdir(dir))) {
blit::FileInfo info;
info.name = ent->d_name;
if(info.name == "." || info.name == "..")
continue;
info.flags = 0;
if(ent->d_type == DT_LNK) {
// lookup link target
struct stat stat_buf;
if(stat((basePath + path + "/" + info.name).c_str(), &stat_buf) >= 0 && S_ISDIR(stat_buf.st_mode))
info.flags |= blit::FileFlags::directory;
} else if(ent->d_type == DT_DIR)
info.flags |= blit::FileFlags::directory;
ret.push_back(info);
}
closedir(dir);
#endif
return ret;
}