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
|
/* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */
#include "DirArchive.h"
#include <assert.h>
#include <fstream>
#include "System/FileSystem/DataDirsAccess.h"
#include "System/FileSystem/FileSystem.h"
#include "System/FileSystem/FileQueryFlags.h"
#include "System/StringUtil.h"
CDirArchiveFactory::CDirArchiveFactory()
: IArchiveFactory("sdd")
{
}
IArchive* CDirArchiveFactory::DoCreateArchive(const std::string& filePath) const
{
return new CDirArchive(filePath);
}
CDirArchive::CDirArchive(const std::string& archiveName)
: IArchive(archiveName)
, dirName(archiveName + '/')
{
const std::vector<std::string>& found = dataDirsAccess.FindFiles(dirName, "*", FileQueryFlags::RECURSE);
// because spring expects the contents of archives to be case independent,
// we convert filenames to lowercase in every function, and keep a std::map
// lcNameToOrigName to convert back from lowercase to original case.
std::vector<std::string>::const_iterator fi;
for (fi = found.begin(); fi != found.end(); ++fi) {
// strip our own name off.. & convert to forward slashes
std::string origName(*fi, dirName.length());
FileSystem::ForwardSlashes(origName);
// convert to lowercase and store
searchFiles.push_back(origName);
lcNameIndex[StringToLower(origName)] = searchFiles.size() - 1;
}
}
CDirArchive::~CDirArchive()
{
}
bool CDirArchive::IsOpen()
{
return true;
}
unsigned int CDirArchive::NumFiles() const
{
return searchFiles.size();
}
bool CDirArchive::GetFile(unsigned int fid, std::vector<std::uint8_t>& buffer)
{
assert(IsFileId(fid));
const std::string rawpath = dataDirsAccess.LocateFile(dirName + searchFiles[fid]);
std::ifstream ifs(rawpath.c_str(), std::ios::in | std::ios::binary);
if (!ifs.bad() && ifs.is_open()) {
ifs.seekg(0, std::ios_base::end);
buffer.resize(ifs.tellg());
ifs.seekg(0, std::ios_base::beg);
ifs.clear();
if (!buffer.empty()) {
ifs.read((char*)&buffer[0], buffer.size());
}
return true;
} else {
return false;
}
}
void CDirArchive::FileInfo(unsigned int fid, std::string& name, int& size) const
{
assert(IsFileId(fid));
name = searchFiles[fid];
const std::string rawPath = dataDirsAccess.LocateFile(dirName + name);
std::ifstream ifs(rawPath.c_str(), std::ios::in | std::ios::binary);
if (!ifs.bad() && ifs.is_open()) {
ifs.seekg(0, std::ios_base::end);
size = ifs.tellg();
} else {
size = 0;
}
}
|