summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrei Karas <akaras@inbox.ru>2017-04-24 19:27:07 +0300
committerAndrei Karas <akaras@inbox.ru>2017-04-24 19:27:07 +0300
commit6f58d1ee37041da28562d09757a9f653109f5677 (patch)
tree494b990338727f2adfdc7d7c6e46558be696aa29
parentd1b635ebf238fac5911fde8982d067ee4ffffe3a (diff)
downloadmv-6f58d1ee37041da28562d09757a9f653109f5677.tar.gz
mv-6f58d1ee37041da28562d09757a9f653109f5677.tar.bz2
mv-6f58d1ee37041da28562d09757a9f653109f5677.tar.xz
mv-6f58d1ee37041da28562d09757a9f653109f5677.zip
Improve VirtFs::getFilesWithDir.
-rw-r--r--src/fs/virtfs/virtfs.cpp23
-rw-r--r--src/fs/virtfs/virtfs.h2
-rw-r--r--src/fs/virtfs/virtfs1_unittest.cc96
-rw-r--r--src/fs/virtfs/virtfsdir.cpp50
-rw-r--r--src/fs/virtfs/virtfsdir.h3
-rw-r--r--src/fs/virtfs/virtfsfuncs.h3
-rw-r--r--src/fs/virtfs/virtfstools.cpp12
-rw-r--r--src/fs/virtfs/virtfstools.h2
-rw-r--r--src/fs/virtfs/virtfszip.cpp93
-rw-r--r--src/fs/virtfs/virtfszip.h3
10 files changed, 273 insertions, 14 deletions
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<VirtFsEntry*>::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 <SDL_rwops.h>
@@ -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<VirtZipEntry*>(entry);
+ if (dirName == dirSeparator)
+ {
+ FOR_EACH (std::vector<ZipLocalHeader*>::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<std::string>::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<ZipLocalHeader*>::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<std::string>::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);