- Added missing projects "VFS" & "export" to SVN

git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@4447 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
Wanne
2011-05-26 11:25:04 +00:00
parent 6e2bdd557c
commit be95a2a7b1
203 changed files with 44525 additions and 0 deletions
+269
View File
@@ -0,0 +1,269 @@
/*
* bfVFS : vfs/Ext/7z/vfs_7z_library.cpp
* - implements Library interface, creates library object from uncompressed 7-zip archive files
*
* Copyright (C) 2008 - 2010 (BF) john.bf.smith@googlemail.com
*
* This file is part of the bfVFS library
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifdef VFS_WITH_7ZIP
#include <vfs/Ext/7z/vfs_7z_library.h>
#include <vfs/Core/Location/vfs_lib_dir.h>
#include <vfs/Core/File/vfs_lib_file.h>
#include <vfs/Core/vfs_file_raii.h>
namespace sz
{
extern "C"
{
#include <7z.h>
#include <7zCrc.h>
#include <7zAlloc.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(std::exception &ex)
{
VFS_LOG_ERROR(ex.what());
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(std::exception& ex)
{
VFS_LOG_ERROR(ex.what());
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,
vfs::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)) )
{
VFS_THROW(_BS(L"Could not open 7z archive [") << m_libraryFile->getPath() << L"]" << _BS::wget);
}
vfs::TDirectory<ILibrary::tWriteType>* pLD = NULL;
vfs::Path oDir, oFile;
vfs::Path oDirPath;
const size_t FBUFFER_SIZE = 1024;
std::vector<vfs::UInt16> fname_buffer;
fname_buffer.resize(FBUFFER_SIZE);
for(vfs::UInt32 i = 0; i < db.db.NumFiles; i++)
{
sz::CSzFileItem *f = db.db.Files + i;
if (f->IsDir)
{
continue;
}
size_t fsize = SzArEx_GetFileNameUtf16(&db, i, NULL);
if(fsize >= fname_buffer.size())
{
fname_buffer.resize(fsize + 32);
}
fsize = SzArEx_GetFileNameUtf16(&db, i, &fname_buffer[0]);
fname_buffer[fsize] = 0;
vfs::Path sPath((wchar_t*)&fname_buffer[0]);
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
VFS_THROW_IFF( 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(std::exception& ex)
{
VFS_LOG_ERROR(ex.what());
return false;
}
}
#endif // VFS_WITH_7ZIP
@@ -0,0 +1,428 @@
/*
* bfVFS : vfs/Ext/7z/vfs_create_7z_library.cpp
* - writes uncompressed 7z archive file
*
* Copyright (C) 2008 - 2010 (BF) john.bf.smith@googlemail.com
*
* This file is part of the bfVFS library
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifdef VFS_WITH_7ZIP
#include <cstring>
#include <vfs/Core/vfs_types.h>
#include <vfs/Ext/7z/vfs_create_7z_library.h>
#include <vfs/Core/vfs_file_raii.h>
#include <vfs/Core/vfs_debug.h>
namespace sz
{
extern "C"
{
#include <7zCrc.h>
#include <7z.h>
//#include "Archive/7z/7zIn.h"
}
};
#include <vector>
#include <sstream>
/******************************************************************************************/
/******************************************************************************************/
/******************************************************************************************/
namespace szExt
{
inline ::size_t WRITEBYTE(std::ostream& out, sz::Byte const& value)
{
out.write((char*)&value,sizeof(sz::Byte));
return 1;
}
template<typename T>
inline ::size_t WRITEALL(std::ostream& out, T const& value)
{
out.write((char*)&value,sizeof(T));
return sizeof(T);
}
template<typename T>
inline ::size_t WRITEBUFFER(std::ostream& out, T* value, ::size_t num_elements)
{
out.write((char*)value, num_elements*sizeof(T));
return num_elements*sizeof(T);
}
/**
* "compress" numbers by removing heading zero-bytes
* - add additional byte that represents a bit-vector of bytes within a 64-bit/8-byte number
* - if the number is smaller than 128, use the extra byte to store the value
*/
template<typename T>
inline ::size_t WRITE(std::ostream& out, T const& value)
{
::size_t count = 0;
sz::Byte data[8];
sz::Byte firstByte = 0;
sz::Byte* b = (sz::Byte*)&value;
::size_t SIZE = sizeof(T);
b+= SIZE-1;
vfs::Int32 i;
for(i = (vfs::Int32)(SIZE-1); i>=0; --i)
{
if( (*b & 0xFF) != 0)
{
break;
}
b--;
}
if(i < 0)
{
count += WRITEBYTE(out,0);
return count;
}
if(i == 0)
{
if(*b >= 0x80)
{
count += WRITEBYTE(out,0x80);
}
count += WRITEBYTE(out,*b);
return count;
}
vfs::Int32 num = 0;
for(;i >= 0; --i)
{
firstByte |= 1 << (8 - i - 1);
data[i] = *b--;
num++;
}
count += WRITEBYTE(out,firstByte);
count += WRITEBUFFER(out,data,num);
return count;
}
}
/******************************************************************************************/
/******************************************************************************************/
/******************************************************************************************/
vfs::CCreateUncompressed7zLibrary::CCreateUncompressed7zLibrary()
: m_pLibFile(NULL)
{
sz::CrcGenerateTable();
}
vfs::CCreateUncompressed7zLibrary::~CCreateUncompressed7zLibrary()
{
m_pLibFile = NULL;
m_lFileInfo.clear();
m_mapDirInfo.clear();
}
bool vfs::CCreateUncompressed7zLibrary::addFile(vfs::tReadableFile* pFile)
{
if(!pFile)
{
// at least nothing bad happened
return true;
}
try
{
vfs::COpenReadFile infile(pFile);
}
catch(std::exception &ex)
{
std::wstringstream wss;
wss << L"Could not open File \"" << pFile->getPath()() << L"\"";
VFS_RETHROW(wss.str().c_str(), ex);
}
SFileInfo fi;
vfs::Path filename = pFile->getPath();
fi.name = filename.c_wcs();
fi.size = pFile->getSize();
if(m_lFileInfo.empty())
{
fi.offset = 0;
}
else
{
SFileInfo const& fic = m_lFileInfo.back();
fi.offset = fic.offset + fic.size;
}
typedef std::vector<vfs::Byte> tByteVector;
tByteVector data( (tByteVector::size_type)fi.size );
VFS_THROW_IFF(fi.size == pFile->read(&data[0], (vfs::size_t)fi.size), L"");
fi.CRC = sz::CrcCalc(&data[0],(::size_t)fi.size);
m_ssFileStream.write(&data[0],(std::streamsize)fi.size);
m_lFileInfo.push_back(fi);
vfs::Path path,dummy;
filename.splitLast(path,dummy);
if(!path.empty())
{
tDirInfo::iterator it_find = m_mapDirInfo.find(path.c_wcs());
if(it_find == m_mapDirInfo.end())
{
SFileInfo dir;
dir.name = path.c_wcs();
dir.offset = 0;
dir.size = 0;
dir.time_creation = 0;
dir.time_last_access = 0;
dir.time_write = 0;
m_mapDirInfo.insert(std::make_pair(dir.name,dir));
}
}
return true;
}
bool vfs::CCreateUncompressed7zLibrary::writeLibrary(vfs::Path const& sLibName)
{
vfs::COpenWriteFile outfile(sLibName,true);
return writeLibrary(&outfile.file());
}
bool vfs::CCreateUncompressed7zLibrary::writeLibrary(vfs::tWritableFile* pFile)
{
if(!pFile)
{
return false;
}
if(m_lFileInfo.empty())
{
return false;
}
m_pLibFile = pFile;
if(!m_pLibFile->isOpenWrite() && !m_pLibFile->openWrite(true,true))
{
return false;
}
//
writeNextHeader(m_ssInfoStream);
//
std::stringstream ssSigHeader;
writeSignatureHeader(ssSigHeader);
//
m_pLibFile->write(ssSigHeader.str().c_str() , (vfs::size_t)ssSigHeader.str().length());
//
m_pLibFile->write(m_ssFileStream.str().c_str() , (vfs::size_t)m_ssFileStream.str().length());
//
m_pLibFile->write(m_ssInfoStream.str().c_str() , (vfs::size_t)m_ssInfoStream.str().length());
return true;
}
/**************************************************************************************/
bool vfs::CCreateUncompressed7zLibrary::writeSignatureHeader(std::ostream& out)
{
::size_t count=0;
// #define k7zSignatureSize -> not in namespace sz
count += szExt::WRITEBUFFER(out, sz::k7zSignature, k7zSignatureSize);
sz::Byte Major = 0, Minor = 2;
count += szExt::WRITEALL(out, (sz::Byte)Major );
count += szExt::WRITEALL(out, (sz::Byte)Minor );
sz::UInt32 StartHeaderCRC, NextHeaderCRC;
SFileInfo const& fi = m_lFileInfo.back();
sz::UInt64 NextHeaderOffset = fi.offset + fi.size;
sz::UInt64 NextHeaderSize = m_ssInfoStream.str().length()*sizeof(char);
NextHeaderCRC = sz::CrcCalc(m_ssInfoStream.str().c_str(),(::size_t)NextHeaderSize);
std::stringstream sstemp;
count += szExt::WRITEALL(sstemp, (sz::UInt64)NextHeaderOffset );
count += szExt::WRITEALL(sstemp, (sz::UInt64)NextHeaderSize );
count += szExt::WRITEALL(sstemp, (sz::UInt32)NextHeaderCRC );
StartHeaderCRC = sz::CrcCalc(sstemp.str().c_str(), sstemp.str().length()*sizeof(char));
count += szExt::WRITEALL(out, (sz::UInt32)StartHeaderCRC );
out << sstemp.str();
return true;
}
bool vfs::CCreateUncompressed7zLibrary::writeNextHeader(std::ostream& out)
{
szExt::WRITE(out, (sz::Byte)sz::k7zIdHeader);
// this->WriteArchiveProperties(out);
// this->WriteAdditionalStreamsInfo(out)
//
this->writeMainStreamsInfo(out);
//
this->writeFilesInfo(out);
szExt::WRITE(out, (sz::Byte)sz::k7zIdEnd );
return true;
}
bool vfs::CCreateUncompressed7zLibrary::writeMainStreamsInfo(std::ostream& out)
{
szExt::WRITE(out, (sz::Byte)sz::k7zIdMainStreamsInfo );
this->writePackInfo(out);
this->writeUnPackInfo(out);
this->writeSubStreamsInfo(out);
szExt::WRITE(out, (sz::Byte)sz::k7zIdEnd );
return true;
}
bool vfs::CCreateUncompressed7zLibrary::writePackInfo(std::ostream& out)
{
szExt::WRITE(out, (sz::Byte)sz::k7zIdPackInfo );
szExt::WRITE(out, (sz::UInt64)0 ); // data offset
szExt::WRITE(out, (sz::UInt32)m_lFileInfo.size() );
szExt::WRITE(out, (sz::Byte)sz::k7zIdSize );
std::list<SFileInfo>::iterator it = m_lFileInfo.begin();
for(;it != m_lFileInfo.end(); ++it)
{
szExt::WRITE(out, (sz::UInt64)it->size );
}
szExt::WRITE(out, (sz::Byte)sz::k7zIdEnd );
return true;
}
bool vfs::CCreateUncompressed7zLibrary::writeUnPackInfo(std::ostream& out)
{
szExt::WRITE(out, (sz::Byte)sz::k7zIdUnpackInfo );
szExt::WRITE(out, (sz::Byte)sz::k7zIdFolder );
szExt::WRITE(out, (sz::UInt64)m_lFileInfo.size() );
szExt::WRITE(out, (sz::Byte)0 ); // External
std::list<SFileInfo>::iterator fit = m_lFileInfo.begin();
for(;fit != m_lFileInfo.end(); ++fit)
{
this->writeFolder(out);
}
szExt::WRITE(out, (sz::Byte)sz::k7zIdCodersUnpackSize );
fit = m_lFileInfo.begin();
for(;fit != m_lFileInfo.end(); ++fit)
{
szExt::WRITE(out, (sz::UInt64)fit->size );
}
szExt::WRITE(out, (sz::Byte)sz::k7zIdEnd );
return true;
}
bool vfs::CCreateUncompressed7zLibrary::writeSubStreamsInfo(std::ostream& out)
{
szExt::WRITE(out, (sz::Byte)sz::k7zIdSubStreamsInfo );
szExt::WRITE(out, (sz::Byte)sz::k7zIdCRC );
szExt::WRITE(out, (sz::Byte)1 ); // early out - all CRCs defined
std::list<SFileInfo>::iterator fit = m_lFileInfo.begin();
for(;fit != m_lFileInfo.end(); ++fit )
{
szExt::WRITEALL(out, (sz::UInt32)fit->CRC);
}
szExt::WRITE(out, (sz::Byte)sz::k7zIdEnd );
return true;
}
bool vfs::CCreateUncompressed7zLibrary::writeFolder(std::ostream& out)
{
szExt::WRITE(out, (sz::UInt32)1 ); // NumCoders
szExt::WRITE(out, (sz::Byte)1 ); // MainByte
szExt::WRITE(out, (sz::Byte)0 ); // Methods
return true;
}
bool vfs::CCreateUncompressed7zLibrary::writeFilesInfo(std::ostream& out)
{
szExt::WRITE(out, (sz::Byte)sz::k7zIdFilesInfo );
vfs::UInt64 num_files = (m_lFileInfo.size()+m_mapDirInfo.size());
szExt::WRITE(out, (sz::UInt64)num_files );
// empty stream -> pack info in bit-vector
szExt::WRITE(out, (sz::Byte)sz::k7zIdEmptyStream );
sz::UInt64 num_empty64 = num_files/8 + (num_files%8 == 0 ? 0 : 1);
::size_t num_empty = (::size_t)num_empty64;
VFS_THROW_IFF(num_empty == num_empty64, L"WTF");
sz::Byte *empty_vector = new sz::Byte[num_empty];
memset(empty_vector,0,(::size_t)num_empty);
for(::size_t e=m_lFileInfo.size(); e < num_files; ++e)
{
::size_t index = e / 8;
empty_vector[index] |= 1 << (7 - e%8);
}
szExt::WRITE(out, (sz::UInt64)num_empty ); // size
szExt::WRITEBUFFER(out, empty_vector, (::size_t)num_empty);
delete[] empty_vector;
// names
szExt::WRITE(out, (sz::Byte)sz::k7zIdName );
::size_t count = 0;
std::stringstream name_stream;
count += szExt::WRITE(name_stream, (sz::Byte)0 ); // switch
std::list<SFileInfo>::iterator fit = m_lFileInfo.begin();
for(;fit != m_lFileInfo.end(); ++fit)
{
count += (::size_t)this->writeFileName(name_stream, fit->name);
}
std::map<vfs::String::str_t,SFileInfo>::iterator dit = m_mapDirInfo.begin();
for(;dit != m_mapDirInfo.end(); ++dit)
{
count += (::size_t)this->writeFileName(name_stream, dit->second.name);
}
szExt::WRITE(out, (sz::UInt64)count ); // size
szExt::WRITEBUFFER(out, name_stream.str().c_str(), name_stream.str().length() );
//szExt::WRITE(out, (sz::Byte)sz::k7zIdEmptyFile );
//szExt::WRITE(out, (sz::Byte)sz::k7zIdCTime ); // create
//szExt::WRITE(out, (sz::Byte)sz::k7zIdATime ); // last access
//szExt::WRITE(out, (sz::Byte)sz::k7zIdMTime ); // write
//szExt::WRITE(out, (sz::Byte)sz::k7zIdWinAttributes );
szExt::WRITE(out, (sz::Byte)sz::k7zIdEnd );
return true;
}
vfs::size_t vfs::CCreateUncompressed7zLibrary::writeFileName(std::ostream& out, vfs::String const& filename)
{
::size_t count = 0;
VFS_THROW_IFF(filename.length(), L"zero length name");
count += szExt::WRITEBUFFER(out, filename.c_str(), filename.length());
count += szExt::WRITE(out, (sz::Byte)0);
count += szExt::WRITE(out, (sz::Byte)0);
return (vfs::size_t)count;
}
#endif // VFS_WITH_7ZIP
+30
View File
@@ -0,0 +1,30 @@
## Ext
if(BFVFS_WITH_7ZIP)
set(INCLUDE_Ext_7zip
${MOD_INCLUDE}/7z/vfs_7z_library.h
${MOD_INCLUDE}/7z/vfs_create_7z_library.h
)
set(SOURCE_Ext_7zip
${MOD_SOURCE}/7z/vfs_7z_library.cpp
${MOD_SOURCE}/7z/vfs_create_7z_library.cpp
)
source_group("Ext" FILES ${INCLUDE_Ext_7zip} ${SOURCE_Ext_7zip})
endif()
if(BFVFS_WITH_SLF)
set(INCLUDE_Ext_slf
${MOD_INCLUDE}/slf/vfs_slf_library.h
)
set(SOURCE_Ext_slf
${MOD_SOURCE}/slf/vfs_slf_library.cpp
)
source_group("Ext" FILES ${INCLUDE_Ext_slf} ${SOURCE_Ext_slf})
endif()
set(${mod}_files
${INCLUDE_Ext_7zip} ${SOURCE_Ext_7zip}
${INCLUDE_Ext_slf} ${SOURCE_Ext_slf}
CACHE INTERNAL ""
)
+179
View File
@@ -0,0 +1,179 @@
/*
* bfVFS : vfs/Ext/slf/vfs_slf_library.cpp
* - implements Library interface, creates library object from SLF archive files
*
* Copyright (C) 2008 - 2010 (BF) john.bf.smith@googlemail.com
*
* This file is part of the bfVFS library
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifdef VFS_WITH_SLF
#include <vfs/Ext/slf/vfs_slf_library.h>
#include <vfs/Core/Location/vfs_lib_dir.h>
#include <vfs/vfs_config.h>
#include <vfs/Core/Interface/vfs_directory_interface.h>
#include <vfs/Core/File/vfs_lib_file.h>
#include <vfs/Core/vfs_file_raii.h>
#include <cstring>
namespace slf
{
typedef vfs::UInt32 DWORD;
// copy from WinDef.h
typedef struct _FILETIME {
DWORD dwLowDateTime;
DWORD dwHighDateTime;
} FILETIME, *PFILETIME, *LPFILETIME;
typedef void* HANDLE;
const vfs::UInt32 FILENAME_SIZE = 256;
const vfs::UInt32 PATH_SIZE = 80;
const vfs::UInt32 FILE_OK = 0;
const vfs::UInt32 FILE_DELETED = 0xff;
const vfs::UInt32 FILE_OLD = 1;
const vfs::UInt32 FILE_DOESNT_EXIST = 0xfe;
struct LIBHEADER
{
vfs::Byte sLibName[ FILENAME_SIZE ];
vfs::Byte sPathToLibrary[ FILENAME_SIZE ];
vfs::Int32 iEntries;
vfs::Int32 iUsed;
vfs::UInt16 iSort;
vfs::UInt16 iVersion;
vfs::UByte fContainsSubDirectories;
vfs::Int32 iReserved;
};
struct DIRENTRY
{
vfs::Byte sFileName[ FILENAME_SIZE ];
vfs::UInt32 uiOffset;
vfs::UInt32 uiLength;
vfs::UInt8 ubState;
vfs::UInt8 ubReserved;
FILETIME sFileTime;
vfs::UInt16 usReserved2;
};
}; // end namespace slf
/********************************************************************************************/
/********************************************************************************************/
/********************************************************************************************/
vfs::CSLFLibrary::CSLFLibrary(tReadableFile *pLibraryFile, vfs::Path const& sMountPoint, bool bOwnFile)
: vfs::CUncompressedLibraryBase(pLibraryFile,sMountPoint,bOwnFile)
{};
vfs::CSLFLibrary::~CSLFLibrary()
{
}
bool vfs::CSLFLibrary::init()
{
if(!m_libraryFile)
{
return false;
}
try
{
vfs::COpenReadFile rfile(m_libraryFile);
slf::LIBHEADER LibFileHeader;
vfs::size_t bytesRead = m_libraryFile->read((vfs::Byte*)&LibFileHeader, sizeof( slf::LIBHEADER ));
VFS_THROW_IFF(bytesRead == sizeof( slf::LIBHEADER ), L"");
vfs::Path oLibPath;
//if the library has a path
if( strlen( (char*)LibFileHeader.sPathToLibrary ) != 0 )
{
oLibPath = vfs::Path( LibFileHeader.sPathToLibrary );
}
else
{
//else the library name does not contain a path ( most likely either an error or it is the default path )
oLibPath = vfs::Path( vfs::Const::EMPTY() );
}
if(m_mountPoint.empty())
{
m_mountPoint = oLibPath;
}
else
{
m_mountPoint += oLibPath;
}
//place the file pointer at the begining of the file headers ( they are at the end of the file )
m_libraryFile->setReadPosition(-( LibFileHeader.iEntries * (vfs::Int32)sizeof(slf::DIRENTRY) ), vfs::IBaseFile::SD_END);
//loop through the library and determine the number of files that are FILE_OK
//ie. so we dont load the old or deleted files
slf::DIRENTRY DirEntry;
vfs::Path oDir, oFile;
vfs::Path oDirPath;
for(vfs::UInt32 uiLoop=0; uiLoop < (vfs::UInt32)LibFileHeader.iEntries; uiLoop++ )
{
//read in the file header
//memset(&DirEntry,0,sizeof(DirEntry));
bytesRead = m_libraryFile->read((Byte*)&DirEntry, sizeof( slf::DIRENTRY ));
VFS_THROW_IFF(bytesRead == sizeof( slf::DIRENTRY ), L"");
if( DirEntry.ubState == slf::FILE_OK )
{
vfs::Path sPath(vfs::String::as_utf16(DirEntry.sFileName));
sPath.splitLast(oDir,oFile);
oDirPath = m_mountPoint;
if(!oDir.empty())
{
oDirPath += oDir;
}
// get or create according directory object
vfs::TDirectory<ILibrary::tWriteType>* pLD = NULL;
tDirCatalogue::iterator it = m_dirs.find(oDirPath);
if(it != m_dirs.end())
{
pLD = it->second;
}
else
{
pLD = new vfs::CLibDirectory(oDirPath,oDirPath);
m_dirs.insert(std::make_pair(oDirPath,pLD));
}
// create file
vfs::CLibFile *pFile = vfs::CLibFile::create(oFile,pLD,this);
// add file to directory
VFS_THROW_IFF(pLD->addFile(pFile), L"");
// link file data struct to file object
m_fileData.insert(std::make_pair(pFile, SFileData(DirEntry.uiLength, DirEntry.uiOffset)));
} // end if
} // end for
return true;
}
catch(std::exception& ex)
{
VFS_LOG_ERROR(ex.what());
return false;
}
}
#endif // VFS_WITH_SLF