Files
source/VFS/Location/vfs_7z_library.cpp
T
Wanne 14750c6903 **********************************************************
** Big Maps Projects code (incl. Multiplayer v1.5 **
**********************************************************
- Merged Big Maps Project code from BMP+MP trunk (Revision: 3340)
o Complete SVN Revision history: https://81.169.133.124/source/ja2/branches/Wanne/JA2%201.13%20MP
- Before THIS merge, I made a branch of the existing 1.13 source
o SVN Branch: https://81.169.133.124/source/ja2/branches/JA2_rev.3336/src
- Removed old VS 6.0 and VS 2003 project and solutions files, because compilation is broken long time ago
- I will add VS 2010 projects and solution file in the next few days

git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@3341 3b4a5df2-a311-0410-b5c6-a8a6f20db521
2010-02-28 18:38:52 +00:00

232 lines
5.6 KiB
C++

#include "vfs_7z_library.h"
#include "vfs_lib_dir.h"
#include "../File/vfs_lib_file.h"
#include "../vfs_file_raii.h"
namespace sz
{
extern "C"
{
#include "7zCrc.h"
#include "Archive/7z/7zAlloc.h"
#include "Archive/7z/7zExtract.h"
#include "Archive/7z/7zIn.h"
}
}
/********************************************************************************************/
/*** my 7z extensions ***/
/********************************************************************************************/
namespace szExt
{
typedef struct CSzVfsFile
{
vfs::tReadableFile* file;
} CSzVfsFile;
typedef struct CVfsFileInStream
{
sz::ISeekInStream s;
CSzVfsFile file;
} CVfsFileInStream;
static sz::SRes VfsFileInStream_Read(void *pp, void *buf, ::size_t *size)
{
CVfsFileInStream *p = (CVfsFileInStream *)pp;
::size_t to_read = *size;
sz::SRes res;
try
{
*size = (::size_t)p->file.file->read((vfs::Byte*)buf,to_read);
res = SZ_OK;
}
catch(CBasicException &ex)
{
logException(ex);
res = SZ_ERROR_READ;
}
return res;
}
static sz::SRes VfsFileInStream_Seek(void *pp, sz::Int64 *pos, sz::ESzSeek origin)
{
CVfsFileInStream *p = (CVfsFileInStream *)pp;
vfs::IBaseFile::ESeekDir eSD;
switch (origin)
{
case sz::SZ_SEEK_SET:
eSD = vfs::IBaseFile::SD_BEGIN;
break;
case sz::SZ_SEEK_CUR:
eSD = vfs::IBaseFile::SD_CURRENT;
break;
case sz::SZ_SEEK_END:
eSD = vfs::IBaseFile::SD_END;
break;
default:
return SZ_ERROR_PARAM;
}
vfs::offset_t _pos = (vfs::offset_t)(*pos);
sz::SRes res;
try
{
p->file.file->setReadPosition(_pos,eSD);
*pos = p->file.file->getReadPosition();
res = SZ_OK;
}
catch(CBasicException& ex)
{
logException(ex);
res = SZ_ERROR_READ;
}
return res;
}
void VfsFileInStream_CreateVTable(CVfsFileInStream *p)
{
p->s.Read = VfsFileInStream_Read;
p->s.Seek = VfsFileInStream_Seek;
}
}; // end namespace szExt
/********************************************************************************************/
/********************************************************************************************/
/********************************************************************************************/
vfs::CUncompressed7zLibrary::CUncompressed7zLibrary(
tReadableFile *libraryFile,
vfs::Path const& mountPoint,
bool ownFile,
ObjBlockAllocator<vfs::CLibFile>* allocator)
: vfs::CUncompressedLibraryBase(libraryFile, mountPoint, ownFile), _allocator(allocator)
{
}
vfs::CUncompressed7zLibrary::~CUncompressed7zLibrary()
{
}
#define k_Copy 0
sz::UInt64 GetSum(const sz::UInt64 *values, sz::UInt32 index)
{
sz::UInt64 sum = 0;
sz::UInt32 i;
for (i = 0; i < index; i++)
{
sum += values[i];
}
return sum;
}
bool vfs::CUncompressed7zLibrary::init()
{
if(!m_libraryFile)
{
return false;
}
try
{
szExt::CVfsFileInStream archiveStream;
sz::CLookToRead lookStream;
sz::CSzArEx db;
sz::SRes res;
sz::ISzAlloc allocImp;
sz::ISzAlloc allocTempImp;
vfs::COpenReadFile rfile(m_libraryFile);
archiveStream.file.file = m_libraryFile;
szExt::VfsFileInStream_CreateVTable(&archiveStream);
sz::LookToRead_CreateVTable(&lookStream, False);
lookStream.realStream = &archiveStream.s;
sz::LookToRead_Init(&lookStream);
allocImp.Alloc = sz::SzAlloc;
allocImp.Free = sz::SzFree;
allocTempImp.Alloc = sz::SzAllocTemp;
allocTempImp.Free = sz::SzFreeTemp;
sz::CrcGenerateTable();
sz::SzArEx_Init(&db);
if( SZ_OK != (res = sz::SzArEx_Open(&db, &lookStream.s, &allocImp, &allocTempImp)) )
{
THROWEXCEPTION(BuildString().add(L"Could not open 7z archive [").add(m_libraryFile->getPath()).add(L"]").get());
}
vfs::TDirectory<ILibrary::tWriteType>* pLD = NULL;
vfs::Path oDir, oFile;
vfs::Path oDirPath;
for(vfs::UInt32 i = 0; i < db.db.NumFiles; i++)
{
sz::CSzFileItem *f = db.db.Files + i;
if (f->IsDir)
{
continue;
}
vfs::Path sPath(f->Name);
sPath.splitLast(oDir,oFile);
oDirPath = m_mountPoint;
if(!oDir.empty())
{
oDirPath += oDir;
}
// determine offset and size
sz::UInt32 folderIndex = db.FileIndexToFolderIndexMap[i];
sz::CSzFolder *folder = db.db.Folders + folderIndex;
sz::UInt64 unpackSizeSpec = sz::SzFolder_GetUnpackSize(folder);
size_t unpackSize = (size_t)unpackSizeSpec;
sz::UInt64 startOffset = sz::SzArEx_GetFolderStreamPos(&db, folderIndex, 0);
//const sz::UInt64 *packSizes = db.db.PackSizes + db.FolderStartPackStreamIndex[folderIndex];
//CSzCoderInfo *coder = &folder->Coders[0];
//if (coder->MethodID == k_Copy)
//{
// UInt32 si = 0;
// UInt64 offset;
// UInt64 inSize;
// offset = GetSum(packSizes, si);
// inSize = packSizes[si];
//}
// get or create according directory object
tDirCatalogue::iterator it = m_dirs.find(oDirPath);
if(it != m_dirs.end())
{
pLD = it->second;
}
else
{
pLD = new vfs::CLibDirectory(oDir,oDirPath);
m_dirs.insert(std::make_pair(oDirPath,pLD));
}
// create file
vfs::CLibFile *pFile = vfs::CLibFile::create(oFile,pLD,this,_allocator);
// add file to directory
THROWIFFALSE( pLD->addFile(pFile), L"" );
// link file data struct to file object
m_fileData.insert(std::make_pair(pFile,SFileData(unpackSize, (vfs::size_t)startOffset)));
}
return true;
}
catch(CBasicException& ex)
{
logException(ex);
return false;
}
}