From 6f58d1ee37041da28562d09757a9f653109f5677 Mon Sep 17 00:00:00 2001 From: Andrei Karas Date: Mon, 24 Apr 2017 19:27:07 +0300 Subject: Improve VirtFs::getFilesWithDir. --- src/fs/virtfs/virtfs.cpp | 23 ++++++++++ src/fs/virtfs/virtfs.h | 2 + src/fs/virtfs/virtfs1_unittest.cc | 96 +++++++++++++++++++++++++++++++++++++++ src/fs/virtfs/virtfsdir.cpp | 50 ++++++++++++++++++++ src/fs/virtfs/virtfsdir.h | 3 ++ src/fs/virtfs/virtfsfuncs.h | 3 ++ src/fs/virtfs/virtfstools.cpp | 12 ----- src/fs/virtfs/virtfstools.h | 2 - src/fs/virtfs/virtfszip.cpp | 93 +++++++++++++++++++++++++++++++++++++ src/fs/virtfs/virtfszip.h | 3 ++ 10 files changed, 273 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/fs/virtfs/virtfs.cpp b/src/fs/virtfs/virtfs.cpp index b4807afe7..1f7bde683 100644 --- a/src/fs/virtfs/virtfs.cpp +++ b/src/fs/virtfs/virtfs.cpp @@ -183,6 +183,29 @@ namespace VirtFs } } + void getFilesWithDir(std::string dirName, + StringVect &list) + { + prepareFsPath(dirName); + if (checkPath(dirName) == false) + { + reportAlways("VirtFs::enumerateFiles invalid path: %s", + dirName.c_str()); + return; + } + + std::string rootDir = dirName; + if (findLast(rootDir, std::string(dirSeparator)) == false) + rootDir += dirSeparator; + + FOR_EACH (std::vector::const_iterator, it, mEntries) + { + VirtFsEntry *const entry = *it; + entry->funcs->getFilesWithDir(entry, rootDir, list); + } + } + + void getDirs(std::string dirName, StringVect &list) { diff --git a/src/fs/virtfs/virtfs.h b/src/fs/virtfs/virtfs.h index 5046f4675..2d95b55c9 100644 --- a/src/fs/virtfs/virtfs.h +++ b/src/fs/virtfs/virtfs.h @@ -96,6 +96,8 @@ namespace VirtFs int &restrict fileSize); void getFiles(std::string dirName, StringVect &list); + void getFilesWithDir(std::string dirName, + StringVect &list); void getDirs(std::string dirName, StringVect &list); } // namespace VirtFs diff --git a/src/fs/virtfs/virtfs1_unittest.cc b/src/fs/virtfs/virtfs1_unittest.cc index 23255e0c5..b6a928bb6 100644 --- a/src/fs/virtfs/virtfs1_unittest.cc +++ b/src/fs/virtfs/virtfs1_unittest.cc @@ -30,6 +30,7 @@ #include "utils/checkutils.h" #include "utils/delete2.h" +#include "utils/stringutils.h" #include @@ -695,6 +696,19 @@ static bool inList(StringVect list, return false; } +static bool inList(StringVect list, + const std::string &dir, + const std::string &name) +{ + const std::string path = pathJoin(dir, name); + FOR_EACH (StringVectCIter, it, list) + { + if (*it == path) + return true; + } + return false; +} + TEST_CASE("VirtFs1 enumerateFiles1") { VirtFs::init("."); @@ -2020,3 +2034,85 @@ TEST_CASE("VirtFs1 getDirs2") VirtFs::deinit(); delete2(logger); } + +TEST_CASE("VirtFs1 getFilesWithDir1") +{ + VirtFs::init("."); + logger = new Logger(); + std::string name("data/test/test.zip"); + std::string prefix; + if (Files::existsLocal(name) == false) + prefix = "../" + prefix; + + VirtFs::mountZip(prefix + "data/test/test2.zip", + Append_false); + + StringVect list; + VirtFs::getFilesWithDir("dir", list); + REQUIRE(list.size() == 2); + REQUIRE(inList(list, "dir", "dye.png")); + REQUIRE(inList(list, "dir", "hide.png")); + list.clear(); + + VirtFs::getFilesWithDir("dir2", list); + REQUIRE(list.size() == 4); + REQUIRE(inList(list, "dir2", "hide.png")); + REQUIRE(inList(list, "dir2", "paths.xml")); + REQUIRE(inList(list, "dir2", "test.txt")); + REQUIRE(inList(list, "dir2", "units.xml")); + list.clear(); + + VirtFs::getFilesWithDir("/", list); + REQUIRE(list.size() > 2); + REQUIRE(inList(list, "/", "test.txt")); + REQUIRE(inList(list, "/", "units.xml")); + list.clear(); + + VirtFs::unmountZip(prefix + "data/test/test2.zip"); + VirtFs::deinit(); + delete2(logger); +} + +TEST_CASE("VirtFs1 getFilesWithDir2") +{ + VirtFs::init("."); + logger = new Logger(); + std::string name("data/test/test.zip"); + std::string prefix; + if (Files::existsLocal(name) == false) + prefix = "../" + prefix; + StringVect list; + + SECTION("dir1") + { + VirtFs::mountDir(prefix + "data/graphics", + Append_false); + + VirtFs::getFilesWithDir("/", list); + REQUIRE(list.size() <= 5); + VirtFs::unmountDir(prefix + "data/graphics"); + } + + SECTION("dir2") + { + VirtFs::mountDir(prefix + "data", + Append_false); + + VirtFs::getFilesWithDir("music", list); + REQUIRE(list.size() <= 5); + REQUIRE(list.size() >= 1); + REQUIRE(inList(list, "music", "keprohm.ogg")); + list.clear(); + + VirtFs::getFilesWithDir(pathJoin("evol", "icons"), list); + REQUIRE(list.size() == 3); + REQUIRE(inList(list, pathJoin("evol" , "icons"), "evol-client.ico")); + REQUIRE(inList(list, pathJoin("evol" , "icons"), "evol-client.png")); + REQUIRE(inList(list, pathJoin("evol" , "icons"), "evol-client.xpm")); + + VirtFs::unmountDir(prefix + "data"); + } + + VirtFs::deinit(); + delete2(logger); +} diff --git a/src/fs/virtfs/virtfsdir.cpp b/src/fs/virtfs/virtfsdir.cpp index 967c80610..223b45e1d 100644 --- a/src/fs/virtfs/virtfsdir.cpp +++ b/src/fs/virtfs/virtfsdir.cpp @@ -138,6 +138,7 @@ namespace VirtFsDir ptr->openAppend = &VirtFsDir::openAppend; ptr->loadFile = &VirtFsDir::loadFile; ptr->getFiles = &VirtFsDir::getFiles; + ptr->getFilesWithDir = &VirtFsDir::getFilesWithDir; ptr->getDirs = &VirtFsDir::getDirs; ptr->rwops_seek = &VirtFsDir::rwops_seek; ptr->rwops_read = &VirtFsDir::rwops_read; @@ -563,6 +564,55 @@ namespace VirtFsDir } } + void getFilesWithDir(VirtFsEntry *restrict const entry, + const std::string &dirName, + StringVect &names) + { + const std::string path = entry->root + dirName; + const struct dirent *next_file = nullptr; + DIR *const dir = opendir(path.c_str()); + if (dir) + { + while ((next_file = readdir(dir))) + { + struct stat statbuf; + const std::string file = next_file->d_name; + if (file == "." || file == "..") + continue; +#ifndef WIN32 + if (mPermitLinks == false) + { + if (lstat(path.c_str(), &statbuf) == 0 && + S_ISLNK(statbuf.st_mode) != 0) + { + continue; + } + } +#endif // WIN32 + + const std::string filePath = pathJoin(path, file); + if (stat(filePath.c_str(), &statbuf) == 0) + { + if (S_ISDIR(statbuf.st_mode) != 0) + continue; + } + + bool found(false); + FOR_EACH (StringVectCIter, itn, names) + { + if (*itn == file) + { + found = true; + break; + } + } + if (found == false) + names.push_back(pathJoin(dirName, file)); + } + closedir(dir); + } + } + void getDirs(VirtFsEntry *restrict const entry, const std::string &dirName, StringVect &names) diff --git a/src/fs/virtfs/virtfsdir.h b/src/fs/virtfs/virtfsdir.h index 74bf569bf..12a4ee831 100644 --- a/src/fs/virtfs/virtfsdir.h +++ b/src/fs/virtfs/virtfsdir.h @@ -58,6 +58,9 @@ namespace VirtFsDir void getFiles(VirtFsEntry *restrict const entry, const std::string &dirName, StringVect &names); + void getFilesWithDir(VirtFsEntry *restrict const entry, + const std::string &dirName, + StringVect &names); void getDirs(VirtFsEntry *restrict const entry, const std::string &dirName, StringVect &names); diff --git a/src/fs/virtfs/virtfsfuncs.h b/src/fs/virtfs/virtfsfuncs.h index f8c69e125..9f164c865 100644 --- a/src/fs/virtfs/virtfsfuncs.h +++ b/src/fs/virtfs/virtfsfuncs.h @@ -88,6 +88,9 @@ struct VirtFsFuncs final void (*getFiles) (VirtFsEntry *restrict const entry, const std::string &dirName, StringVect &names); + void (*getFilesWithDir) (VirtFsEntry *restrict const entry, + const std::string &dirName, + StringVect &names); void (*getDirs) (VirtFsEntry *restrict const entry, const std::string &dirName, StringVect &names); diff --git a/src/fs/virtfs/virtfstools.cpp b/src/fs/virtfs/virtfstools.cpp index be634b89c..892b02db3 100644 --- a/src/fs/virtfs/virtfstools.cpp +++ b/src/fs/virtfs/virtfstools.cpp @@ -76,18 +76,6 @@ namespace VirtFs VirtFs::freeList(list); } - void getFilesWithDir(const std::string &path, - StringVect &list) - { - VirtList *const fonts = VirtFs::enumerateFiles(path); - FOR_EACH (StringVectCIter, i, fonts->names) - { - if (!VirtFs::isDirectory(path + *i)) - list.push_back(path + *i); - } - VirtFs::freeList(fonts); - } - void getFilesInDir(const std::string &dir, StringVect &list, const std::string &ext) diff --git a/src/fs/virtfs/virtfstools.h b/src/fs/virtfs/virtfstools.h index 8385920cc..f00a976bb 100644 --- a/src/fs/virtfs/virtfstools.h +++ b/src/fs/virtfs/virtfstools.h @@ -37,8 +37,6 @@ namespace VirtFs void getFilesInDir(const std::string &dir, StringVect &list, const std::string &ext); - void getFilesWithDir(const std::string &restrict path, - StringVect &restrict list); std::string getPath(const std::string &file); bool loadTextFile(const std::string &fileName, StringVect &lines); diff --git a/src/fs/virtfs/virtfszip.cpp b/src/fs/virtfs/virtfszip.cpp index bf7e8fba2..9b53e86aa 100644 --- a/src/fs/virtfs/virtfszip.cpp +++ b/src/fs/virtfs/virtfszip.cpp @@ -75,6 +75,7 @@ namespace VirtFsZip ptr->openAppend = &VirtFsZip::openAppend; ptr->loadFile = &VirtFsZip::loadFile; ptr->getFiles = &VirtFsZip::getFiles; + ptr->getFilesWithDir = &VirtFsZip::getFilesWithDir; ptr->getDirs = &VirtFsZip::getDirs; ptr->rwops_seek = &VirtFsZip::rwops_seek; ptr->rwops_read = &VirtFsZip::rwops_read; @@ -288,6 +289,98 @@ namespace VirtFsZip } } + void getFilesWithDir(VirtFsEntry *restrict const entry, + const std::string &dirName, + StringVect &names) + { + VirtZipEntry *const zipEntry = static_cast(entry); + if (dirName == dirSeparator) + { + FOR_EACH (std::vector::const_iterator, + it2, + zipEntry->mHeaders) + { + ZipLocalHeader *const header = *it2; + std::string fileName = header->fileName; + // skip subdirs from enumeration + const size_t idx = fileName.find(dirSeparator); + if (idx != std::string::npos) + fileName.erase(idx); + bool found(false); + FOR_EACH (StringVectCIter, itn, names) + { + if (*itn == fileName) + { + found = true; + break; + } + } + if (found == false) + { + std::string dirName2 = pathJoin(dirName, fileName); + if (findLast(dirName2, std::string(dirSeparator)) == false) + dirName2 += dirSeparator; + FOR_EACH (std::vector::const_iterator, + it, + zipEntry->mDirs) + { + if (*it == dirName2) + { + found = true; + break; + } + } + if (found == false) + names.push_back(pathJoin(dirName, fileName)); + } + } + } + else + { + FOR_EACH (std::vector::const_iterator, + it2, + zipEntry->mHeaders) + { + ZipLocalHeader *const header = *it2; + std::string fileName = header->fileName; + if (findCutFirst(fileName, dirName) == true) + { + // skip subdirs from enumeration + const size_t idx = fileName.find(dirSeparator); + if (idx != std::string::npos) + fileName.erase(idx); + bool found(false); + FOR_EACH (StringVectCIter, itn, names) + { + if (*itn == fileName) + { + found = true; + break; + } + } + if (found == false) + { + std::string dirName2 = pathJoin(dirName, fileName); + if (findLast(dirName2, std::string(dirSeparator)) == false) + dirName2 += dirSeparator; + FOR_EACH (std::vector::const_iterator, + it, + zipEntry->mDirs) + { + if (*it == dirName2) + { + found = true; + break; + } + } + if (found == false) + names.push_back(pathJoin(dirName, fileName)); + } + } + } + } + } + void getDirs(VirtFsEntry *restrict const entry, const std::string &dirName, StringVect &names) diff --git a/src/fs/virtfs/virtfszip.h b/src/fs/virtfs/virtfszip.h index 3ae74cc95..5ffd545f8 100644 --- a/src/fs/virtfs/virtfszip.h +++ b/src/fs/virtfs/virtfszip.h @@ -45,6 +45,9 @@ namespace VirtFsZip void getFiles(VirtFsEntry *restrict const entry, const std::string &dirName, StringVect &names); + void getFilesWithDir(VirtFsEntry *restrict const entry, + const std::string &dirName, + StringVect &names); void getDirs(VirtFsEntry *restrict const entry, const std::string &dirName, StringVect &names); -- cgit v1.2.3-70-g09d2