1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
|
/* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */
#include "VirtualArchive.h"
#include "System/FileSystem/FileSystem.h"
#include "System/FileSystem/DataDirsAccess.h"
#include "System/FileSystem/FileQueryFlags.h"
#include "System/Log/ILog.h"
#include "minizip/zip.h"
#include <cassert>
CVirtualArchiveFactory* virtualArchiveFactory;
CVirtualArchiveFactory::CVirtualArchiveFactory() : IArchiveFactory("sva")
{
virtualArchiveFactory = this;
}
CVirtualArchiveFactory::~CVirtualArchiveFactory()
{
virtualArchiveFactory = nullptr;
}
CVirtualArchive* CVirtualArchiveFactory::AddArchive(const std::string& fileName)
{
CVirtualArchive* archive = new CVirtualArchive(fileName);
archives.push_back(archive);
return archive;
}
IArchive* CVirtualArchiveFactory::DoCreateArchive(const std::string& fileName) const
{
const std::string baseName = FileSystem::GetBasename(fileName);
for (CVirtualArchive* archive: archives) {
if (archive->GetFileName() == baseName)
return archive->Open();
}
return nullptr;
}
CVirtualArchiveOpen::CVirtualArchiveOpen(CVirtualArchive* archive, const std::string& fileName) : IArchive(fileName), archive(archive)
{
// set subclass name index to archive's index (doesn't update while archive is open)
lcNameIndex = archive->GetNameIndex();
}
unsigned int CVirtualArchiveOpen::NumFiles() const
{
return archive->NumFiles();
}
bool CVirtualArchiveOpen::GetFile( unsigned int fid, std::vector<std::uint8_t>& buffer )
{
return archive->GetFile(fid, buffer);
}
void CVirtualArchiveOpen::FileInfo( unsigned int fid, std::string& name, int& size ) const
{
return archive->FileInfo(fid, name, size);
}
CVirtualArchiveOpen* CVirtualArchive::Open()
{
return new CVirtualArchiveOpen(this, fileName);
}
bool CVirtualArchive::GetFile(unsigned int fid, std::vector<std::uint8_t>& buffer)
{
if (fid >= files.size())
return false;
buffer = files[fid].buffer;
return true;
}
void CVirtualArchive::FileInfo(unsigned int fid, std::string& name, int& size) const
{
assert(fid < files.size());
name = files[fid].name;
size = files[fid].buffer.size();
}
unsigned int CVirtualArchive::AddFile(const std::string& name)
{
lcNameIndex[name] = files.size();
files.emplace_back(files.size(), name);
return (files.size() - 1);
}
void CVirtualArchive::WriteToFile()
{
const std::string zipFilePath = dataDirsAccess.LocateFile(fileName, FileQueryFlags::WRITE) + ".sdz";
LOG("Writing zip file for virtual archive %s to %s", fileName.c_str(), zipFilePath.c_str());
zipFile zip = zipOpen(zipFilePath.c_str(), APPEND_STATUS_CREATE);
if (zip == nullptr) {
LOG("[VirtualArchive::%s] could not open zip file %s for writing", __func__, zipFilePath.c_str());
return;
}
for (const CVirtualFile& file: files) {
file.WriteZip(zip);
}
zipClose(zip, nullptr);
}
void CVirtualFile::WriteZip(void* zf) const
{
zipFile zip = static_cast<zipFile>(zf);
zipOpenNewFileInZip(zip, name.c_str(), nullptr, nullptr, 0, nullptr, 0, nullptr, Z_DEFLATED, Z_BEST_COMPRESSION);
zipWriteInFileInZip(zip, buffer.data(), buffer.size());
zipCloseFileInZip(zip);
}
|