Files
panopainter/src/asset.cpp
2019-09-23 18:06:20 +02:00

252 lines
5.8 KiB
C++

#include "pch.h"
#include "log.h"
#include "asset.h"
#ifdef __APPLE__
#include <Foundation/Foundation.h>
#include "objc_utils.h"
#endif
#ifdef __ANDROID__
#include <dirent.h>
AAssetManager* Asset::m_am;
bool android_create_dir(const std::string& path);
#endif
bool Asset::delete_file(const std::string& path)
{
LOG("delete file: %s", path.c_str());
std::remove(path.c_str());
return true;
}
bool Asset::exist(std::string path)
{
if (Asset::is_asset(path))
{
Asset asset;
if (asset.open(path.c_str()))
{
asset.close();
return true;
}
}
else
{
FILE* fp = fopen(path.c_str(), "rb");
if (!fp)
return false;
fclose(fp);
return true;
}
return false; // useless return for the stupid xcode
}
std::vector<std::string> Asset::list_files(std::string folder, const std::string& filter_regex)
{
bool is_asset = Asset::is_asset(folder);
std::vector<std::string> names;
#ifdef _WIN32
WIN32_FIND_DATAA fd;
HANDLE hFind = ::FindFirstFileA((folder + "\\*").c_str(), &fd);
if (hFind != INVALID_HANDLE_VALUE)
{
do
{
// read all (real) files in current folder
// , delete '!' read other 2 default folder . and ..
if (!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
{
names.push_back(fd.cFileName);
}
} while (::FindNextFileA(hFind, &fd));
::FindClose(hFind);
}
#elif __ANDROID__
if (is_asset)
{
AAssetDir* dir = AAssetManager_openDir(Asset::m_am, folder.c_str());
while (const char* name = AAssetDir_getNextFileName(dir))
{
//LOG("asset: %s", name);
names.push_back(name);
}
AAssetDir_close(dir);
}
else
{
DIR *dp;
struct dirent *ep;
dp = opendir(folder.c_str());
if (dp != NULL)
{
while ((ep = readdir(dp)))
if (ep->d_type != DT_DIR)
names.push_back(ep->d_name);
closedir(dp);
}
else
LOG("Couldn't open the directory: %s", folder.c_str());
}
#else
std::string abs_path = folder;
if (is_asset)
{
NSString* bundle_path = [[NSBundle mainBundle] resourcePath];
std::string base = [bundle_path cStringUsingEncoding : 1];
abs_path = base + "/" + folder;
}
DIR *dp;
struct dirent *ep;
dp = opendir(abs_path.c_str());
if (dp != NULL)
{
while ((ep = readdir(dp)))
if (ep->d_type != DT_DIR)
names.push_back(ep->d_name);
closedir(dp);
}
else
LOG("Couldn't open the directory: %s", folder.c_str());
#endif
if (!filter_regex.empty())
{
std::regex r(filter_regex);
names.erase(std::remove_if(names.begin(), names.end(),
[&r](const std::string& s) { return !std::regex_match(s, r); }), names.end());
}
return names;
}
std::string Asset::absolute(const std::string& path)
{
#ifdef __APPLE__
NSString* bundle_path = [[NSBundle mainBundle] resourcePath];
std::string base = [bundle_path cStringUsingEncoding:1];
return base + "/" + path;
#else
return path;
#endif
}
bool Asset::is_asset(const std::string & path)
{
return path.substr(0, 5) == "data/";
}
bool Asset::create_dir(const std::string& path)
{
#if __WIN__
return PathFileExistsA(path.c_str()) ? true : CreateDirectoryA(path.c_str(), NULL);
#elif __ANDROID__
return android_create_dir(path);
#elif __IOS__ || __OSX__
return apple_create_dir(path);
#endif
}
bool Asset::open(const char* path)
{
//LOG("Asset::open %s", path);
m_current_path = path;
std::string file_path = path;
#ifdef __ANDROID__
if (is_asset(path))
{
if (!(m_asset = AAssetManager_open(m_am, path, AASSET_MODE_RANDOM)))
{
LOG("AAssetManager_open failed %s", path);
return false;
}
}
else
{
if (!(m_fp = fopen(file_path.c_str(), "rb")))
{
LOG("asset open errno = %d, %s", errno, path);
return false;
}
fseek(m_fp, 0, SEEK_END);
m_len = (int)ftell(m_fp);
fseek(m_fp, 0, SEEK_SET);
}
#else
#ifdef __APPLE__
if (is_asset(path))
{
NSString* bundle_path = [[NSBundle mainBundle] resourcePath];
std::string base = [bundle_path cStringUsingEncoding:1];
file_path = base + "/" + path;
}
#endif
//LOG("asset file: %s", file_path.c_str());
if (!(m_fp = fopen(file_path.c_str(), "rb")))
{
LOG("asset open errno = %d, %s", errno, path);
return false;
}
fseek(m_fp, 0, SEEK_END);
m_len = (int)ftell(m_fp);
fseek(m_fp, 0, SEEK_SET);
#endif
return true;
}
glm::uint8_t* Asset::read_all()
{
#ifdef __ANDROID__
if (!m_data)
{
if (is_asset(m_current_path))
{
m_len = (int)AAsset_getLength(m_asset);
m_data = (uint8_t*)AAsset_getBuffer(m_asset);
}
else
{
m_data = new uint8_t[m_len];
if (m_len != fread(m_data, 1, m_len, m_fp))
{
LOG("ASSET READ FAILED for %s", m_current_path.c_str());
delete[] m_data;
m_data = nullptr;
}
}
}
return m_data;
#else
if (!m_data)
{
m_data = new uint8_t[m_len];
if (m_len != fread(m_data, 1, m_len, m_fp))
{
LOG("ASSET READ FAILED for %s", m_current_path.c_str());
delete[] m_data;
m_data = nullptr;
}
}
return m_data;
#endif
}
void Asset::close()
{
#ifdef __ANDROID__
if (m_asset)
AAsset_close(m_asset);
m_asset = nullptr;
#else
if (m_fp)
fclose(m_fp);
if (m_data)
delete m_data;
m_data = nullptr;
m_fp = nullptr;
#endif
}