Skip to content

Commit

Permalink
rewrite archive handling:
Browse files Browse the repository at this point in the history
- less code, less dependencies etc.
- easier to use
- better threadsafety
  • Loading branch information
Karl-Robert Ernst committed Feb 8, 2010
1 parent 2b14a0f commit 899129d
Show file tree
Hide file tree
Showing 37 changed files with 421 additions and 2,071 deletions.
2 changes: 1 addition & 1 deletion rts/CMakeLists.txt
Expand Up @@ -73,7 +73,7 @@ LIST(APPEND spring_libraries ${SDL_LIBRARY} ${Boost_REGEX_LIBRARY} ${Boost_THREA

### build all libraries in lib (has its own CMakeLists.txt)
ADD_SUBDIRECTORY(lib)
LIST(APPEND spring_libraries lua 7zip hpiutil2 oscpack minizip streflop lobby)
LIST(APPEND spring_libraries lua 7zip oscpack minizip streflop lobby)
if (USE_GML)
list (APPEND spring_libraries gml)
endif (USE_GML)
Expand Down
4 changes: 2 additions & 2 deletions rts/Map/MapParser.cpp
Expand Up @@ -8,7 +8,6 @@

#include "Lua/LuaSyncedRead.h"
#include "FileSystem/FileSystem.h"
#include "FileSystem/ArchiveScanner.h"

using namespace std;

Expand Down Expand Up @@ -49,7 +48,8 @@ MapParser::MapParser(const string& mapName) : parser(NULL)
parser->AddFunc("GetMapOptions", LuaSyncedRead::GetMapOptions);
parser->EndTable();
#endif // !defined UNITSYNC && !defined DEDICATED && !defined BUILDING_AI
if (!parser->Execute()) {
if (!parser->Execute())
{
// do nothing
}
}
Expand Down
35 changes: 26 additions & 9 deletions rts/Sim/Path/PathEstimator.cpp
Expand Up @@ -737,23 +737,37 @@ bool CPathEstimator::ReadFile(std::string name, const std::string& map)
std::auto_ptr<CArchiveZip> auto_pfile(pfile);
CArchiveZip& file(*pfile);

int fh = file.OpenFile("pathinfo");
const unsigned fid = file.FindFile("pathinfo");
if (fid < file.NumFiles())
{
pathChecksum = file.GetCrc32(fid);

if (fh) {
pathChecksum = file.GetCrc32("pathinfo");
std::vector<uint8_t> buffer;
file.GetFile(fid, buffer);

unsigned int filehash = 0;
// Check hash.
file.ReadFile(fh, &filehash, 4);
if (buffer.size() < 4)
return false;

unsigned filehash = *((unsigned*)&buffer[0]);
if (filehash != hash)
return false;

unsigned pos = sizeof(unsigned);

// Read block-center-offset data.
const unsigned blockSize = moveinfo->moveData.size() * sizeof(int2);
if (buffer.size() < pos + blockSize*nbrOfBlocks)
return false;
for (int blocknr = 0; blocknr < nbrOfBlocks; blocknr++)
file.ReadFile(fh, blockState[blocknr].sqrCenter, moveinfo->moveData.size() * sizeof(int2));
{
std::memcpy(blockState[blocknr].sqrCenter, &buffer[pos], blockSize);
pos += blockSize;
}

// Read vertices data.
file.ReadFile(fh, vertex, nbrOfVertices * sizeof(float));
if (buffer.size() < pos + nbrOfVertices * sizeof(float))
return false;
std::memcpy(vertex, &buffer[pos], nbrOfVertices * sizeof(float));

// File read successful.
return true;
Expand Down Expand Up @@ -809,7 +823,10 @@ void CPathEstimator::WriteFile(std::string name, const std::string& map)

std::auto_ptr<CArchiveZip> auto_pfile(pfile);
CArchiveZip& file(*pfile);
pathChecksum = file.GetCrc32("pathinfo");

const unsigned fid = file.FindFile("pathinfo");
assert(fid < file.NumFiles());
pathChecksum = file.GetCrc32(fid);
}
}

Expand Down
98 changes: 39 additions & 59 deletions rts/System/FileSystem/Archive7Zip.cpp
Expand Up @@ -3,7 +3,6 @@
#include <algorithm>
#include <boost/system/error_code.hpp>
#include <stdexcept>
#include <string.h>

extern "C" {
#include "lib/7z/Types.h"
Expand All @@ -17,8 +16,7 @@ extern "C" {
#include "LogOutput.h"

CArchive7Zip::CArchive7Zip(const std::string& name) :
CArchiveBuffered(name),
curSearchHandle(1),
CArchiveBase(name),
isOpen(false)
{
blockIndex = 0xFFFFFFFF;
Expand Down Expand Up @@ -49,10 +47,12 @@ CArchive7Zip::CArchive7Zip(const std::string& name) :
CrcGenerateTable();

SRes res = SzArEx_Open(&db, &lookStream.s, &allocImp, &allocTempImp);
if (res == SZ_OK) {
if (res == SZ_OK)
{
isOpen = true;
}
else {
else
{
isOpen = false;
std::string error;
switch (res) {
Expand Down Expand Up @@ -83,7 +83,8 @@ CArchive7Zip::CArchive7Zip(const std::string& name) :
}

// Get contents of archive and store name->int mapping
for (unsigned i = 0; i < db.db.NumFiles; ++i) {
for (unsigned i = 0; i < db.db.NumFiles; ++i)
{
CSzFileItem *f = db.db.Files + i;
if ((f->Size >= 0) && !f->IsDir) {
std::string name = f->Name;
Expand All @@ -95,87 +96,66 @@ CArchive7Zip::CArchive7Zip(const std::string& name) :
fd.crc = (f->Size > 0) ? f->FileCRC : 0;

StringToLowerInPlace(name);
fileData[name] = fd;
fileData.push_back(fd);
lcNameIndex[name] = fileData.size()-1;
}
}
}

CArchive7Zip::~CArchive7Zip(void)
{
if (outBuffer) {
if (outBuffer)
{
IAlloc_Free(&allocImp, outBuffer);
}
if (isOpen) {
if (isOpen)
{
File_Close(&archiveStream.file);
}
SzArEx_Free(&db, &allocImp);
}

unsigned int CArchive7Zip::GetCrc32 (const std::string& fileName)
bool CArchive7Zip::IsOpen()
{
std::string lower = StringToLower(fileName);
FileData fd = fileData[lower];
return fd.crc;
return isOpen;
}

FileBuffer* CArchive7Zip::GetEntireFileImpl(const std::string& fName)
unsigned CArchive7Zip::NumFiles() const
{
if (!isOpen)
return NULL;

// Figure out the file index
std::string fileName = StringToLower(fName);

if (fileData.find(fileName) == fileData.end())
return NULL;

FileData fd = fileData[fileName];
return fileData.size();
}

bool CArchive7Zip::GetFile(unsigned fid, std::vector<uint8_t>& buffer)
{
boost::mutex::scoped_lock lck(archiveLock);
assert(fid >= 0 && fid < NumFiles());

// Get 7zip to decompress it
size_t offset;
size_t outSizeProcessed;

SRes res;

res = SzAr_Extract(&db, &lookStream.s, fd.fp, &blockIndex, &outBuffer, &outBufferSize, &offset, &outSizeProcessed, &allocImp, &allocTempImp);

FileBuffer* of = NULL;
if (res == SZ_OK) {
of = new FileBuffer;
of->size = outSizeProcessed;
of->data = (char*)outBuffer + offset;
res = SzAr_Extract(&db, &lookStream.s, fileData[fid].fp, &blockIndex, &outBuffer, &outBufferSize, &offset, &outSizeProcessed, &allocImp, &allocTempImp);
if (res == SZ_OK)
{
std::copy((char*)outBuffer+offset, (char*)outBuffer+offset+outSizeProcessed, std::back_inserter(buffer));
return true;
}
else
{
return false;
}

if (res != SZ_OK)
return NULL;

return of;
}

int CArchive7Zip::FindFiles(int cur, std::string* name, int* size)
void CArchive7Zip::FileInfo(unsigned fid, std::string& name, int& size) const
{
if (cur == 0) {
curSearchHandle++;
cur = curSearchHandle;
searchHandles[cur] = fileData.begin();
}

if (searchHandles.find(cur) == searchHandles.end())
throw std::runtime_error("Unregistered handle. Pass a handle returned by CArchive7Zip::FindFiles.");

if (searchHandles[cur] == fileData.end()) {
searchHandles.erase(cur);
return 0;
}

*name = searchHandles[cur]->second.origName;
*size = searchHandles[cur]->second.size;

searchHandles[cur]++;
return cur;
assert(fid >= 0 && fid < NumFiles());
name = fileData[fid].origName;
size = fileData[fid].size;
}

bool CArchive7Zip::IsOpen()
unsigned CArchive7Zip::GetCrc32(unsigned fid)
{
return isOpen;
assert(fid >= 0 && fid < NumFiles());
return fileData[fid].crc;
}
25 changes: 14 additions & 11 deletions rts/System/FileSystem/Archive7Zip.h
@@ -1,37 +1,41 @@
#ifndef __ARCHIVE_7ZIP_H
#define __ARCHIVE_7ZIP_H

#include "ArchiveBuffered.h"

#include <boost/thread/mutex.hpp>
extern "C" {
#include "lib/7z/7zFile.h"
#include "lib/7z/Archive/7z/7zIn.h"
};

class CArchive7Zip : public CArchiveBuffered
#include "ArchiveBase.h"

class CArchive7Zip : public CArchiveBase
{
public:
CArchive7Zip(const std::string& name);
virtual ~CArchive7Zip(void);

virtual bool IsOpen();
virtual int FindFiles(int cur, std::string* name, int* size);
virtual unsigned int GetCrc32 (const std::string& fileName);

virtual unsigned NumFiles() const;
virtual bool GetFile(unsigned fid, std::vector<uint8_t>& buffer);
virtual void FileInfo(unsigned fid, std::string& name, int& size) const;
virtual unsigned GetCrc32(unsigned fid);

private:
boost::mutex archiveLock;
UInt32 blockIndex;
Byte *outBuffer;
size_t outBufferSize;

struct FileData {
struct FileData
{
int fp;
int size;
std::string origName;
unsigned int crc;
};
std::map<std::string, FileData> fileData;

int curSearchHandle;
std::map<int, std::map<std::string, FileData>::iterator> searchHandles;
std::vector<FileData> fileData;

CFileInStream archiveStream;
CSzArEx db;
Expand All @@ -40,7 +44,6 @@ class CArchive7Zip : public CArchiveBuffered
ISzAlloc allocTempImp;

bool isOpen;
virtual FileBuffer* GetEntireFileImpl(const std::string& fName);
};

#endif
47 changes: 30 additions & 17 deletions rts/System/FileSystem/ArchiveBase.cpp
@@ -1,5 +1,7 @@
#include "ArchiveBase.h"

#include "CRC.h"
#include "Util.h"

CArchiveBase::CArchiveBase(const std::string& archiveName) : archiveFile(archiveName)
{
Expand All @@ -9,28 +11,39 @@ CArchiveBase::~CArchiveBase()
{
}

unsigned int CArchiveBase::GetCrc32(const std::string& fileName)
std::string CArchiveBase::GetArchiveName()
{
CRC crc;
unsigned char buffer [65536];
int handle;
int maxRead;
int total = 0;
return archiveFile;
}

handle = this->OpenFile(fileName);
if (handle == 0) return crc.GetDigest();
unsigned CArchiveBase::FindFile(const std::string& name) const
{
const std::string fileName = StringToLower(name);
std::map<std::string, unsigned>::const_iterator it = lcNameIndex.find(fileName);
if (it != lcNameIndex.end())
return it->second;
else
return NumFiles();
}

do {
maxRead = this->ReadFile(handle, &buffer, sizeof(buffer));
crc.Update(buffer, maxRead);
total += maxRead;
} while (maxRead == sizeof(buffer));
unsigned CArchiveBase::GetCrc32(unsigned fid)
{
CRC crc;
std::vector<uint8_t> buffer;
if (GetFile(fid, buffer))
crc.Update(&buffer[0], buffer.size());

this->CloseFile(handle);
return crc.GetDigest();
};
}

std::string CArchiveBase::GetArchiveName()
bool CArchiveBase::GetFile(const std::string& name, std::vector<uint8_t>& buffer)
{
return archiveFile;
unsigned fid = FindFile(name);
if (fid < NumFiles())
{
GetFile(fid, buffer);
return true;
}
else
return false;
}

0 comments on commit 899129d

Please sign in to comment.