File: VirtualArchive.cpp

package info (click to toggle)
spring 105.0.1%2Bdfsg-2
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 108,860 kB
  • sloc: cpp: 467,785; ansic: 302,607; python: 12,925; java: 12,201; awk: 5,889; sh: 2,371; xml: 655; perl: 405; php: 276; objc: 194; makefile: 75; sed: 2
file content (126 lines) | stat: -rw-r--r-- 3,126 bytes parent folder | download | duplicates (3)
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);
}