Skip to content

Commit d2f7837

Browse files
committed
New filesystem stuff(untested)
1 parent b29bab7 commit d2f7837

File tree

3 files changed

+157
-2
lines changed

3 files changed

+157
-2
lines changed

include/nbl/system/CAPKResourcesArchive.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,9 @@ class CAPKResourcesArchive : public IFileArchive
3838
AAsset_close(asset);
3939
return fileView;
4040
}
41-
std::vector<std::string> listAssets(const char* asset_path)
41+
core::vector<std::string> listAssets(const char* asset_path) override
4242
{
43-
std::vector<std::string> result;
43+
core::vector<std::string> result;
4444

4545
auto context_object = activity->clazz;
4646
auto getAssets_method = env->GetMethodID(env->GetObjectClass(context_object), "getAssets", "()Landroid/content/res/AssetManager;");

include/nbl/system/IFileArchive.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,31 @@ class IFileArchive : public core::IReferenceCounted
8282
_NBL_ALIGNED_FREE(m_filesBuffer);
8383
_NBL_ALIGNED_FREE(m_fileFlags);
8484
}
85+
86+
// List all files and directories in a specific dir of the archive
87+
virtual core::vector<system::path> listAssets(const char* asset_path)
88+
{
89+
constexpr auto isSubDir = [](path p, path root) -> bool
90+
{
91+
while (p != path()) {
92+
if (p == root) {
93+
return true;
94+
}
95+
p = p.parent_path();
96+
}
97+
return false;
98+
};
99+
core::vector<path> res;
100+
for (auto& entry : m_files)
101+
{
102+
if (isSubDir(entry.fullName, asset_path))
103+
{
104+
res.push_back(entry.fullName);
105+
}
106+
}
107+
return res;
108+
}
109+
85110
//! An entry in a list of files, can be a folder or a file.
86111
struct SFileListEntry
87112
{

include/nbl/system/ISystem.h

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,137 @@ class ISystem : public core::IReferenceCounted
344344
}
345345
void unmount(const IFileArchive* archive, const system::path& pathAlias)
346346
{
347+
assert(false); // TODO(dan): i swear i'll get to it at some point
348+
}
349+
350+
/*
351+
Returns true if the path is writable (e.g. if p is a path inside an archive the function will return true).
352+
The path existence is not checked.
353+
*/
354+
bool isPathReadOnly(const system::path& p)
355+
{
356+
auto curPath = p;
357+
while (!curPath.empty() && curPath.parent_path() != curPath)
358+
{
359+
auto archives = m_cachedArchiveFiles.findRange(curPath);
360+
if (!archives.empty()) return true;
361+
362+
curPath = curPath.parent_path().generic_string();
363+
}
364+
return false;
365+
}
366+
367+
bool createDirectory(const system::path& p)
368+
{
369+
return std::filesystem::create_directory(p);
370+
}
371+
372+
bool deleteDirectory(const system::path& p)
373+
{
374+
return std::filesystem::remove(p);
375+
}
376+
377+
378+
/*
379+
Recursively lists all files and directories in the directory.
380+
*/
381+
core::vector<system::path> listFilesInDirectory(const system::path& p)
382+
{
383+
if (isPathReadOnly(p))
384+
{
385+
auto curPath = p;
386+
while (!curPath.empty() && curPath.parent_path() != curPath)
387+
{
388+
auto archives = m_cachedArchiveFiles.findRange(curPath);
389+
for (auto& arch : archives)
390+
{
391+
auto rel = std::filesystem::relative(p, arch.first);
392+
auto res = arch.second->listAssets(rel.generic_string().c_str());
393+
std::for_each(res.begin(), res.end(), [&arch](system::path& p) {p = arch.first / p; });
394+
return res;
395+
}
396+
397+
curPath = curPath.parent_path().generic_string();
398+
}
399+
return {};
400+
}
401+
else
402+
{
403+
uint32_t fileCount = std::distance(std::filesystem::recursive_directory_iterator(p), std::filesystem::recursive_directory_iterator{});
404+
core::vector<system::path> res;
405+
res.reserve(fileCount);
406+
for (auto entry : std::filesystem::recursive_directory_iterator(p))
407+
{
408+
res.push_back(entry.path());
409+
}
410+
return res;
411+
}
412+
}
413+
414+
415+
bool isDirectory(const system::path& p)
416+
{
417+
if (isPathReadOnly(p))
418+
{
419+
return p.extension() == ""; // TODO: this is a temporary decision until i figure out how to check if a file is directory in androi APK
420+
}
421+
else
422+
{
423+
return std::filesystem::is_directory(p);
424+
}
425+
}
426+
427+
/*
428+
Recursively copy a directory or a file from one place to another.
429+
from - a path to the source file or directory. Must exist. Can be both readonly and mutable path.
430+
to - a path to the destination file or directory. Must be mutable path (isPathReadonly(to) must be false).
431+
*/
432+
bool copy(const system::path& from, const system::path& to)
433+
{
434+
constexpr auto copyFile = [this](const system::path& from, const system::path& to)
435+
{
436+
system::future<core::smart_refctd_ptr<IFile>> readFileFut, writeFileFut;
437+
system::future<size_t> readFut, writeFut;
438+
439+
createFile(readFileFut, from, IFile::ECF_READ);
440+
createFile(writeFileFut, from, IFile::ECF_WRITE);
441+
auto readFile = readFileFut.get();
442+
auto writeFile = writeFileFut.get();
347443

444+
char* fileData = (char*)malloc(readFile->getSize());
445+
readFile->read(readFut, fileData, 0, readFile->getSize());
446+
readFut.get();
447+
448+
writeFile->write(writeFut, fileData, 0, readFile->getSize());
449+
writeFut.get();
450+
451+
free(fileData);
452+
};
453+
if (isPathReadOnly(from))
454+
{
455+
if (isPathReadOnly(to)) return false;
456+
if (isDirectory(from))
457+
{
458+
auto allFiles = listFilesInDirectory(from);
459+
for (const auto& file : allFiles)
460+
{
461+
auto relative = std::filesystem::relative(file, from);
462+
auto targetName = to / relative;
463+
copyFile(file, targetName);
464+
}
465+
}
466+
else
467+
{
468+
copyFile(from, to);
469+
}
470+
return true;
471+
}
472+
else
473+
{
474+
std::error_code error;
475+
std::filesystem::copy(from, to, error);
476+
return static_cast<bool>(error);
477+
}
348478
}
349479

350480
struct SystemMemory

0 commit comments

Comments
 (0)