#include "CPakReader.h"
#ifdef __IRR_COMPILE_WITH_PAK_ARCHIVE_LOADER_
#include "os.h"
#include "coreutil.h"
namespace irr
{
namespace io
{
namespace
{
inline bool isHeaderValid(const SPAKFileHeader& header)
{
const c8* tag = header.tag;
return tag[0] == 'P' &&
tag[1] == 'A' &&
tag[2] == 'C' &&
tag[3] == 'K';
}
}
CArchiveLoaderPAK::CArchiveLoaderPAK( io::IFileSystem* fs)
: FileSystem(fs)
{
#ifdef _DEBUG
setDebugName("CArchiveLoaderPAK");
#endif
}
bool CArchiveLoaderPAK::isALoadableFileFormat(const io::path& filename) const
{
return core::hasFileExtension(filename, "pak");
}
bool CArchiveLoaderPAK::isALoadableFileFormat(E_FILE_ARCHIVE_TYPE fileType) const
{
return fileType == EFAT_PAK;
}
IFileArchive* CArchiveLoaderPAK::createArchive(const io::path& filename, bool ignoreCase, bool ignorePaths) const
{
IFileArchive *archive = 0;
io::IReadFile* file = FileSystem->createAndOpenFile(filename);
if (file)
{
archive = createArchive(file, ignoreCase, ignorePaths);
file->drop ();
}
return archive;
}
IFileArchive* CArchiveLoaderPAK::createArchive(io::IReadFile* file, bool ignoreCase, bool ignorePaths) const
{
IFileArchive *archive = 0;
if ( file )
{
file->seek ( 0 );
archive = new CPakReader(file, ignoreCase, ignorePaths);
}
return archive;
}
bool CArchiveLoaderPAK::isALoadableFileFormat(io::IReadFile* file) const
{
SPAKFileHeader header;
file->read(&header, sizeof(header));
return isHeaderValid(header);
}
CPakReader::CPakReader(IReadFile* file, bool ignoreCase, bool ignorePaths)
: CFileList((file ? file->getFileName() : io::path("")), ignoreCase, ignorePaths), File(file)
{
#ifdef _DEBUG
setDebugName("CPakReader");
#endif
if (File)
{
File->grab();
scanLocalHeader();
sort();
}
}
CPakReader::~CPakReader()
{
if (File)
File->drop();
}
const IFileList* CPakReader::getFileList() const
{
return this;
}
bool CPakReader::scanLocalHeader()
{
SPAKFileHeader header;
File->read(&header, sizeof(header));
if (!isHeaderValid(header))
return false;
#ifdef __BIG_ENDIAN__
header.offset = os::Byteswap::byteswap(header.offset);
header.length = os::Byteswap::byteswap(header.length);
#endif
File->seek(header.offset);
const int numberOfFiles = header.length / sizeof(SPAKFileEntry);
for(int i = 0; i < numberOfFiles; i++)
{
SPAKFileEntry entry;
File->read(&entry, sizeof(entry));
#ifdef _DEBUG
os::Printer::log(entry.name);
#endif
#ifdef __BIG_ENDIAN__
entry.offset = os::Byteswap::byteswap(entry.offset);
entry.length = os::Byteswap::byteswap(entry.length);
#endif
addItem(io::path(entry.name), entry.offset, entry.length, false );
}
return true;
}
IReadFile* CPakReader::createAndOpenFile(const io::path& filename)
{
s32 index = findFile(filename, false);
if (index != -1)
return createAndOpenFile(index);
return 0;
}
IReadFile* CPakReader::createAndOpenFile(u32 index)
{
if (index >= Files.size() )
return 0;
const SFileListEntry &entry = Files[index];
return createLimitReadFile( entry.FullName, File, entry.Offset, entry.Size );
}
}
}
#endif