1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-12-01 23:12:49 +02:00

- ZipArchive namespace for operations with zip archives, located in CZipLoader.h/cpp.

- new fields in mod format, for use with mod manager (check config/shemas/mod.json for details)
- removed some 0.92 compatibility from mods loading
- several compile fixes
This commit is contained in:
Ivan Savenko
2013-08-19 11:50:53 +00:00
parent 38c1542d9d
commit 5654fef901
15 changed files with 209 additions and 53 deletions

View File

@@ -2,6 +2,8 @@
#include "../../Global.h"
#include "CZipLoader.h"
#include "../ScopeGuard.h"
/*
* CZipLoader.cpp, part of VCMI engine
*
@@ -99,4 +101,102 @@ std::unordered_set<ResourceID> CZipLoader::getFilteredFiles(std::function<bool(c
foundID.insert(file.first);
}
return foundID;
}
}
/// extracts currently selected file from zip into stream "where"
static bool extractCurrent(unzFile file, std::ostream & where)
{
std::array<char, 8 * 1024> buffer;
unzOpenCurrentFile(file);
while (1)
{
int readSize = unzReadCurrentFile(file, buffer.data(), buffer.size());
if (readSize < 0) // error
break;
if (readSize == 0) // end-of-file. Also performs CRC check
return unzCloseCurrentFile(file) == UNZ_OK;
if (readSize > 0) // successfull read
{
where.write(buffer.data(), readSize);
if (!where.good())
break;
}
}
// extraction failed. Close file and exit
unzCloseCurrentFile(file);
return false;
}
std::vector<std::string> ZipArchive::listFiles(std::string filename)
{
std::vector<std::string> ret;
unzFile file = unzOpen(filename.c_str());
if (unzGoToFirstFile(file) == UNZ_OK)
{
do
{
unz_file_info info;
std::vector<char> filename;
unzGetCurrentFileInfo (file, &info, nullptr, 0, nullptr, 0, nullptr, 0);
filename.resize(info.size_filename);
// Get name of current file. Contrary to docs "info" parameter can't be null
unzGetCurrentFileInfo (file, &info, filename.data(), filename.size(), nullptr, 0, nullptr, 0);
ret.push_back(std::string(filename.data(), filename.size()));
}
while (unzGoToNextFile(file) == UNZ_OK);
}
unzClose(file);
return ret;
}
bool ZipArchive::extract(std::string from, std::string where)
{
// Note: may not be fast enough for large archives (should NOT happen with mods)
// because locating each file by name may be slow. Unlikely slower than decompression though
return extract(from, where, listFiles(from));
}
bool ZipArchive::extract(std::string from, std::string where, std::vector<std::string> what)
{
unzFile archive = unzOpen(from.c_str());
auto onExit = vstd::makeScopeGuard([&]()
{
unzClose(archive);
});
for (std::string & file : what)
{
if (unzLocateFile(archive, file.c_str(), 1) != UNZ_OK)
return false;
std::string fullName = where + '/' + file;
std::string fullPath = fullName.substr(0, fullName.find_last_of("/"));
boost::filesystem::create_directories(fullPath);
// directory. No file to extract
// TODO: better way to detect directory? Probably check return value of unzOpenCurrentFile?
if (boost::algorithm::ends_with(file, "/"))
continue;
std::ofstream destFile(fullName);
if (!destFile.good())
return false;
if (!extractCurrent(archive, destFile))
return false;
}
return true;
}