Commit f0e49594 authored by bitplane's avatar bitplane

- IFileSystem changes:

   - Added TAR archive loader.
   - Renamed the following functions-
      IFileArchive::getArchiveType to getType
      IFileSystem::registerFileArchive to addFileArchive
      IFileSystem::unregisterFileArchive to removeFileArchive
      IFileArchive::openFile to createAndOpenFile
   - New enum, E_FILE_ARCHIVE_TYPE. getType on IArchiveLoader and IFileArchive now both return this.
   - IFileSystem::addFileArchive takes a parameter to specify the archive type rather always using the file extension. IFileSystem::addZipFileArchive, addFolderFileArchive and addPakFileArchive now use this but these functions are now marked as deprecated. Users should now use addFileArchive instead.


git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@2447 dfc29bdd-3216-0410-991c-e03cc46cb475
parent 802af445
Changes in 1.6
- IFileSystem changes:
- Added TAR archive loader.
- Renamed the following functions-
IFileArchive::getArchiveType to getType
IFileSystem::registerFileArchive to addFileArchive
IFileSystem::unregisterFileArchive to removeFileArchive
IFileArchive::openFile to createAndOpenFile
- New enum, E_FILE_ARCHIVE_TYPE. getType on IArchiveLoader and IFileArchive now both return this.
- IFileSystem::addFileArchive takes a parameter to specify the archive type rather always using the file extension. IFileSystem::addZipFileArchive, addFolderFileArchive and addPakFileArchive now use this but these functions are now marked as deprecated. Users should now use addFileArchive instead.
- Fix highlighting in IGUIEditBox where kerning pairs are used in the font. For example in future italic, OS or other custom fonts.
- IOSOperator::getTextFromClipboard returns now const c8* instead of c8*
......
......@@ -848,9 +848,9 @@ void CQuake3EventHandler::AddArchive ( const core::string<c16>& archiveName )
}
}
if ( !exists )
if (!exists)
{
fs->registerFileArchive ( archiveName, true, false );
fs->addFileArchive(archiveName, true, false);
}
}
......@@ -866,7 +866,26 @@ void CQuake3EventHandler::AddArchive ( const core::string<c16>& archiveName )
u32 index = gui.ArchiveList->addRow(i);
gui.ArchiveList->setCellText ( index, 0, archive->getArchiveType () );
core::stringw typeName;
switch(archive->getType())
{
case io::EFAT_ZIP:
typeName = "ZIP";
break;
case io::EFAT_FOLDER:
typeName = "Mount";
break;
case io::EFAT_PAK:
typeName = "PAK";
break;
case io::EFAT_TAR:
typeName = "TAR";
break;
default:
typeName = "archive";
}
gui.ArchiveList->setCellText ( index, 0, typeName );
gui.ArchiveList->setCellText ( index, 1, archive->getArchiveName () );
}
}
......@@ -1327,7 +1346,7 @@ bool CQuake3EventHandler::OnEvent(const SEvent& eve)
else
if ( eve.GUIEvent.Caller == gui.ArchiveRemove && eve.GUIEvent.EventType == gui::EGET_BUTTON_CLICKED )
{
Game->Device->getFileSystem()->unregisterFileArchive ( gui.ArchiveList->getSelected () );
Game->Device->getFileSystem()->removeFileArchive( gui.ArchiveList->getSelected() );
Game->CurrentMapName = "";
AddArchive ( "" );
}
......
......@@ -20,6 +20,25 @@ enum EFileSystemType
FILESYSTEM_VIRTUAL, // Virtual FileSystem
};
//! Contains the different types of archives
enum E_FILE_ARCHIVE_TYPE
{
//! A ZIP archive
EFAT_ZIP = MAKE_IRR_ID('Z','I','P', 0),
//! A virtual directory
EFAT_FOLDER = MAKE_IRR_ID('f','l','d','r'),
//! A Windows PAK file
EFAT_PAK = MAKE_IRR_ID('P','A','K', 0),
//! A Tape ARchive file
EFAT_TAR = MAKE_IRR_ID('T','A','R', 0),
//! The type of this archive is unknown
EFAT_UNKNOWN = MAKE_IRR_ID('u','n','k','n')
};
//! Base Info which all File archives must support on browsing
struct IFileArchiveEntry
......@@ -50,14 +69,14 @@ struct IFileArchive : public virtual IReferenceCounted
//! return the id of the file Archive
virtual const core::string<c16>& getArchiveName() =0;
//! get the class Type
virtual const core::string<c16>& getArchiveType() =0;
//! get the archive type
virtual E_FILE_ARCHIVE_TYPE getType() const { return EFAT_UNKNOWN; }
//! opens a file by file name
virtual IReadFile* openFile(const core::string<c16>& filename) =0;
virtual IReadFile* createAndOpenFile(const core::string<c16>& filename) =0;
//! opens a file by position
virtual IReadFile* openFile(s32 index) =0;
virtual IReadFile* createAndOpenFile(u32 index) =0;
//! returns fileindex
virtual s32 findFile(const core::string<c16>& filename) =0;
......@@ -98,6 +117,11 @@ struct IArchiveLoader : public virtual IReferenceCounted
/** \param file File handle to check.
\return Pointer to newly created archive, or 0 upon error. */
virtual IFileArchive* createArchive(io::IReadFile* file, bool ignoreCase, bool ignorePaths) const =0;
//! Returns the type of archive created by this loader
/** When creating your own archive loaders you must specifiy a new unique type identifier.
You can use the MAKE_IRR_ID macro to generate an identifier based on a four character code */
virtual E_FILE_ARCHIVE_TYPE getType() const =0;
};
......
......@@ -92,52 +92,75 @@ public:
virtual IWriteFile* createAndWriteFile(const core::string<c16>& filename, bool append=false) =0;
//! Adds an archive to the file system.
/** After calling this, the Irrlicht Engine will search and open files directly from this archive too.
/** After calling this, the Irrlicht Engine will also search and open files directly from this archive.
This is useful for hiding data from the end user, speeding up file access and making it possible to
access for example Quake3 .pk3 files, which are nothing different than .zip files.
\param filename: Filename of the zip archive to add to the file system.
access for example Quake3 .pk3 files, which are no different than .zip files.
By default Irrlicht supports ZIP, PAK, TAR and directories as archives. You can provide your own archive
types by implementing IArchiveLoader and passing an instance to addArchiveLoader.
\param filename: Filename of the archive to add to the file system.
\param ignoreCase: If set to true, files in the archive can be accessed without
writing all letters in the right case.
\param ignorePaths: If set to true, files in the added archive can be accessed
without its complete path.
\return Returns true if the archive was added successful, false if not. */
virtual bool registerFileArchive(const core::string<c16>& filename, bool ignoreCase=true, bool ignorePaths=true) =0;
\param archiveType: If no specific E_FILE_ARCHIVE_TYPE is selected then the type of archive will depend on
the extension of the file name. If you use a different extension then you can use this parameter to force
a specific type of archive.
\return Returns true if the archive was added successfully, false if not. */
virtual bool addFileArchive(const core::string<c16>& filename, bool ignoreCase=true, bool ignorePaths=true,
E_FILE_ARCHIVE_TYPE archiveType=EFAT_UNKNOWN) =0;
//! Adds an external archive loader to the engine.
/** Use this function to add support for new archive types to the engine, for example propiatrary or
encyrpted file storage. */
virtual void addArchiveLoader(IArchiveLoader* loader) =0;
//! return the amount of currently attached Archives
//! Returns the number of archives currently attached to the file system
virtual u32 getFileArchiveCount() const =0;
//! removes an archive from the file system.
virtual bool unregisterFileArchive(u32 index) =0;
//! removes an archive from the file system.
virtual bool unregisterFileArchive(const core::string<c16>& filename) =0;
//! move the hirarchy of the filesystem. moves sourceIndex relative up or down
//! Removes an archive from the file system.
/** This will close the archive and free any file handles, but will not close resources which have already
been loaded and are now cached, for example textures and meshes.
\param index: The index of the archive to remove
\return Returns true on success, false on failure */
virtual bool removeFileArchive(u32 index) =0;
//! Removes an archive from the file system.
/** This will close the archive and free any file handles, but will not close resources which have already
been loaded and are now cached, for example textures and meshes.
\param index: The index of the archive to remove
\return Returns true on success, false on failure */
virtual bool removeFileArchive(const core::string<c16>& filename) =0;
//! Changes the search order of attached archives.
/**
\param sourceIndex: The index of the archive to change
\param relative: The relative change in position, archives with a lower index are searched first */
virtual bool moveFileArchive(u32 sourceIndex, s32 relative) =0;
//! get the Archive number index
//! Returns the archive at a given index.
virtual IFileArchive* getFileArchive(u32 index) =0;
//! Adds an zip archive to the file system.
/** After calling this, the Irrlicht Engine will search and open files directly from this archive too.
//! Adds a zip archive to the file system. Deprecated! This function is provided for compatibility
/** with older versions of Irrlicht and may be removed in future versions, you should use
addFileArchive instead.
After calling this, the Irrlicht Engine will search and open files directly from this archive too.
This is useful for hiding data from the end user, speeding up file access and making it possible to
access for example Quake3 .pk3 files, which are nothing different than .zip files.
access for example Quake3 .pk3 files, which are no different than .zip files.
\param filename: Filename of the zip archive to add to the file system.
\param ignoreCase: If set to true, files in the archive can be accessed without
writing all letters in the right case.
\param ignorePaths: If set to true, files in the added archive can be accessed
without its complete path.
\return Returns true if the archive was added successful, false if not. */
\return Returns true if the archive was added successfully, false if not. */
virtual bool addZipFileArchive(const c8* filename, bool ignoreCase=true, bool ignorePaths=true)
{
return registerFileArchive(filename, ignoreCase, ignorePaths);
return addFileArchive(filename, ignoreCase, ignorePaths, EFAT_ZIP);
}
//! Adds an unzipped archive (or basedirectory with subdirectories..) to the file system.
/** Useful for handling data which will be in a zip file
/** Deprecated! This function is provided for compatibility with older versions of Irrlicht
and may be removed in future versions, you should use addFileArchive instead.
Useful for handling data which will be in a zip file
\param filename: Filename of the unzipped zip archive base directory to add to the file system.
\param ignoreCase: If set to true, files in the archive can be accessed without
writing all letters in the right case.
......@@ -146,11 +169,13 @@ public:
\return Returns true if the archive was added successful, false if not. */
virtual bool addFolderFileArchive(const c8* filename, bool ignoreCase=true, bool ignorePaths=true)
{
return registerFileArchive(filename, ignoreCase, ignorePaths);
return addFileArchive(filename, ignoreCase, ignorePaths, EFAT_FOLDER);
}
//! Adds an pak archive to the file system.
/** After calling this, the Irrlicht Engine will search and open files directly from this archive too.
//! Adds a pak archive to the file system.
/** Deprecated! This function is provided for compatibility with older versions of Irrlicht
and may be removed in future versions, you should use addFileArchive instead.
After calling this, the Irrlicht Engine will search and open files directly from this archive too.
This is useful for hiding data from the end user, speeding up file access and making it possible to
access for example Quake2/KingPin/Hexen2 .pak files
\param filename: Filename of the pak archive to add to the file system.
......@@ -161,7 +186,7 @@ public:
\return Returns true if the archive was added successful, false if not. */
virtual bool addPakFileArchive(const c8* filename, bool ignoreCase=true, bool ignorePaths=true)
{
return registerFileArchive(filename, ignoreCase, ignorePaths);
return addFileArchive(filename, ignoreCase, ignorePaths, EFAT_PAK);
}
//! Get the current working directory.
......@@ -176,7 +201,7 @@ public:
virtual bool changeWorkingDirectoryTo(const core::string<c16>& newDirectory) =0;
//! Converts a relative path to an absolute (unique) path, resolving symbolic links if required
/** \param filename Possibly relative filename begin queried.
/** \param filename Possibly relative file or directory name to query.
\result Absolute filename which points to the same file. */
virtual core::string<c16> getAbsolutePath(const core::string<c16>& filename) const =0;
......
......@@ -30,7 +30,7 @@ namespace irr
namespace io
{
CFileList::CFileList( const c8 * param)
CFileList::CFileList(const c8 * param)
{
#ifdef _DEBUG
setDebugName("CFileList");
......@@ -43,11 +43,11 @@ CFileList::CFileList( const c8 * param)
CFileList::~CFileList()
{
Files.clear ();
Files.clear();
}
void CFileList::constructNative ()
void CFileList::constructNative()
{
// --------------------------------------------
// Windows version
......
......@@ -9,6 +9,7 @@
#include "IWriteFile.h"
#include "CZipReader.h"
#include "CPakReader.h"
#include "CTarReader.h"
#include "CFileList.h"
#include "CXMLReader.h"
#include "CXMLWriter.h"
......@@ -42,9 +43,10 @@ CFileSystem::CFileSystem()
setFileListSystem(FILESYSTEM_NATIVE);
addArchiveLoader(new CArchiveLoaderZIP(this));
addArchiveLoader(new CArchiveLoaderMount(this));
addArchiveLoader(new CArchiveLoaderPAK(this));
ArchiveLoader.push_back(new CArchiveLoaderZIP(this));
ArchiveLoader.push_back(new CArchiveLoaderMount(this));
ArchiveLoader.push_back(new CArchiveLoaderPAK(this));
ArchiveLoader.push_back(new CArchiveLoaderTAR(this));
}
......@@ -73,7 +75,7 @@ IReadFile* CFileSystem::createAndOpenFile(const core::string<c16>& filename)
for (i=0; i< FileArchives.size(); ++i)
{
file = FileArchives[i]->openFile(filename);
file = FileArchives[i]->createAndOpenFile(filename);
if (file)
return file;
}
......@@ -130,7 +132,7 @@ void CFileSystem::addArchiveLoader(IArchiveLoader* loader)
if (!loader)
return;
//loader->grab();
loader->grab();
ArchiveLoader.push_back(loader);
}
......@@ -159,7 +161,8 @@ bool CFileSystem::moveFileArchive(u32 sourceIndex, s32 relative)
//! Adds an archive to the file system.
bool CFileSystem::registerFileArchive(const core::string<c16>& filename, bool ignoreCase, bool ignorePaths)
bool CFileSystem::addFileArchive(const core::string<c16>& filename, bool ignoreCase,
bool ignorePaths, E_FILE_ARCHIVE_TYPE archiveType)
{
IFileArchive* archive = 0;
bool ret = false;
......@@ -172,6 +175,9 @@ bool CFileSystem::registerFileArchive(const core::string<c16>& filename, bool ig
return true;
}
// do we know what type it should be?
if (archiveType == EFAT_UNKNOWN)
{
// try to load archive based on file name
for (i = 0; i < ArchiveLoader.size(); ++i)
{
......@@ -184,7 +190,7 @@ bool CFileSystem::registerFileArchive(const core::string<c16>& filename, bool ig
}
// try to load archive based on content
if (0 == archive)
if (!archive)
{
io::IReadFile* file = createAndOpenFile(filename);
if (file)
......@@ -200,9 +206,49 @@ bool CFileSystem::registerFileArchive(const core::string<c16>& filename, bool ig
break;
}
}
file->drop ();
file->drop();
}
}
}
else
{
// try to open archive based on archive loader type
io::IReadFile* file = 0;
for (i = 0; i < ArchiveLoader.size(); ++i)
{
if (ArchiveLoader[i]->getType() == archiveType)
{
// attempt to open file
if (!file)
file = createAndOpenFile(filename);
// is the file open?
if (file)
{
// attempt to open archive
file->seek(0);
if (ArchiveLoader[i]->isALoadableFileFormat(file))
{
file->seek(0);
archive = ArchiveLoader[i]->createArchive(file, ignoreCase, ignorePaths);
if (archive)
break;
}
}
else
{
// couldn't open file
break;
}
}
}
// if open, close the file
if (file)
file->drop();
}
if (archive)
{
......@@ -220,7 +266,7 @@ bool CFileSystem::registerFileArchive(const core::string<c16>& filename, bool ig
//! removes an archive from the file system.
bool CFileSystem::unregisterFileArchive(u32 index)
bool CFileSystem::removeFileArchive(u32 index)
{
bool ret = false;
if (index < FileArchives.size())
......@@ -235,12 +281,12 @@ bool CFileSystem::unregisterFileArchive(u32 index)
//! removes an archive from the file system.
bool CFileSystem::unregisterFileArchive(const core::string<c16>& filename)
bool CFileSystem::removeFileArchive(const core::string<c16>& filename)
{
for (u32 i=0; i < FileArchives.size(); ++i)
{
if (filename == FileArchives[i]->getArchiveName())
return unregisterFileArchive(i);
return removeFileArchive(i);
}
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
return false;
......@@ -484,7 +530,7 @@ IFileList* CFileSystem::createFileList()
CFileList* flist[2] = { 0, 0 };
//! merge relative folder file archives
if ( FileArchives[i]->getArchiveType() == "mount" )
if ( FileArchives[i]->getType() == EFAT_FOLDER)
{
EFileSystemType currentType = setFileListSystem ( FILESYSTEM_NATIVE );
......@@ -504,7 +550,7 @@ IFileList* CFileSystem::createFileList()
setFileListSystem ( currentType );
}
else
if ( FileArchives[i]->getArchiveType() == "zip" )
if ( FileArchives[i]->getType() == EFAT_ZIP )
{
flist[0] = new CFileList( "zip" );
flist[1] = new CFileList( "zip directory" );
......
......@@ -46,7 +46,8 @@ public:
virtual IWriteFile* createAndWriteFile(const core::string<c16>& filename, bool append=false);
//! Adds an archive to the file system.
virtual bool registerFileArchive( const core::string<c16>& filename, bool ignoreCase = true, bool ignorePaths = true);
virtual bool addFileArchive(const core::string<c16>& filename, bool ignoreCase = true,
bool ignorePaths = true, E_FILE_ARCHIVE_TYPE archiveType = EFAT_UNKNOWN);
//! move the hirarchy of the filesystem. moves sourceIndex relative up or down
virtual bool moveFileArchive( u32 sourceIndex, s32 relative );
......@@ -61,10 +62,10 @@ public:
virtual IFileArchive* getFileArchive(u32 index);
//! removes an archive from the file system.
virtual bool unregisterFileArchive(u32 index);
virtual bool removeFileArchive(u32 index);
//! removes an archive from the file system.
virtual bool unregisterFileArchive(const core::string<c16>& filename);
virtual bool removeFileArchive(const core::string<c16>& filename);
//! Returns the string of the current working directory
virtual const core::string<c16>& getWorkingDirectory();
......
......@@ -19,7 +19,7 @@ namespace io
so that it may only start from a certain file position
and may only read until a certain file position.
This can be useful, for example for reading uncompressed files
in an archive (zip).
in an archive (zip, tar).
!*/
class CLimitReadFile : public IReadFile
{
......
......@@ -194,21 +194,24 @@ bool CPakReader::scanLocalHeader()
//! opens a file by file name
IReadFile* CPakReader::openFile(const core::string<c16>& filename)
IReadFile* CPakReader::createAndOpenFile(const core::string<c16>& filename)
{
s32 index = findFile(filename);
if (index != -1)
return openFile(index);
return createAndOpenFile(index);
return 0;
}
//! opens a file by index
IReadFile* CPakReader::openFile(s32 index)
IReadFile* CPakReader::createAndOpenFile(u32 index)
{
if (index < FileList.size())
return createLimitReadFile(FileList[index].simpleFileName, File, FileList[index].pos, FileList[index].length);
else
return 0;
}
......
......@@ -57,6 +57,9 @@ namespace io
//! \return Pointer to the created archive. Returns 0 if loading failed.
virtual io::IFileArchive* createArchive(io::IReadFile* file, bool ignoreCase, bool ignorePaths) const;
//! Returns the type of archive created by this loader
virtual E_FILE_ARCHIVE_TYPE getType() const { return EFAT_PAK; }
private:
io::IFileSystem* FileSystem;
};
......@@ -71,10 +74,10 @@ namespace io
virtual ~CPakReader();
//! opens a file by file name
virtual IReadFile* openFile(const core::string<c16>& filename);
virtual IReadFile* createAndOpenFile(const core::string<c16>& filename);
//! opens a file by index
virtual IReadFile* openFile(s32 index);
virtual IReadFile* createAndOpenFile(u32 index);
//! returns count of files in archive
virtual u32 getFileCount() const;
......@@ -86,7 +89,7 @@ namespace io
virtual s32 findFile(const core::string<c16>& filename);
//! get the class Type
virtual const core::string<c16>& getArchiveType() { return Type; }
virtual E_FILE_ARCHIVE_TYPE getType() const { return EFAT_PAK; }
//! return the id of the file Archive
virtual const core::string<c16>& getArchiveName ()
......
// Copyright (C) 2009 Gaz Davidson
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#include "CTarReader.h"
#include "CFileList.h"
#include "CLimitReadFile.h"
#include "os.h"
#include "coreutil.h"
#include "IrrCompileConfig.h"
namespace irr
{
namespace io
{
//! Constructor
CArchiveLoaderTAR::CArchiveLoaderTAR(io::IFileSystem* fs)
: FileSystem(fs)
{
#ifdef _DEBUG
setDebugName("CArchiveLoaderTAR");
#endif
}
//! destructor
CArchiveLoaderTAR::~CArchiveLoaderTAR()
{
}
//! returns true if the file maybe is able to be loaded by this class
bool CArchiveLoaderTAR::isALoadableFileFormat(const core::string<c16>& filename) const
{
return core::hasFileExtension(filename, "tar");
}
//! Creates an archive from the filename
/** \param file File handle to check.
\return Pointer to newly created archive, or 0 upon error. */
IFileArchive* CArchiveLoaderTAR::createArchive(const core::string<c16>& 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;
}
//! creates/loads an archive from the file.
//! \return Pointer to the created archive. Returns 0 if loading failed.
IFileArchive* CArchiveLoaderTAR::createArchive(io::IReadFile* file, bool ignoreCase, bool ignorePaths) const
{
IFileArchive *archive = 0;
if (file)
{
file->seek(0);
archive = new CTarReader(file, ignoreCase, ignorePaths);
}
return archive;
}
//! Check if the file might be loaded by this class
/** Check might look into the file.
\param file File handle to check.
\return True if file seems to be loadable. */
bool CArchiveLoaderTAR::isALoadableFileFormat(io::IReadFile* file) const
{
// TAR files consist of blocks of 512 bytes
// if it isn't a multiple of 512 then it's not a TAR file.
if (file->getSize() % 512)
return false;
file->seek(0);
// read header of first file
STarHeader fHead;
file->read(&fHead, sizeof(STarHeader));
#ifdef __BIG_ENDIAN__
for (u32* p = (u32*)&fHead; p < &fHead + sizeof(fHead); ++p)
os::Byteswap::byteswap(*p);
#endif
u32 checksum = 0;
sscanf(fHead.Checksum, "%lo", &checksum);
// verify checksum
// some old TAR writers assume that chars are signed, others assume unsigned
// USTAR archives have a longer header, old TAR archives end after linkname
u32 checksum1=0;
s32 checksum2=0;
// remember to blank the checksum field!
for (u32 i=0; i<8;++i)
fHead.Checksum[i] = ' ';
// old header
for (u8* p = (u8*)(&fHead); p < (u8*)(&fHead.Magic[0]); ++p)
{
checksum1 += *p;
checksum2 += c8(*p);
}
if (!strcmp(fHead.Magic, "star"))
{
for (u8* p = (u8*)(&fHead.Magic[0]); p < (u8*)(&fHead) + sizeof(fHead); ++p)
{
checksum1 += *p;
checksum2 += c8(*p);
}
}
return checksum1 == checksum || checksum2 == (s32)checksum;
}
/*
TAR Archive
*/
CTarReader::CTarReader(IReadFile* file, bool ignoreCase, bool ignorePaths)
: File(file), IgnoreCase(ignoreCase), IgnorePaths(ignorePaths)
{
#ifdef _DEBUG
setDebugName("CTarReader");
#endif
if (File)
{
File->grab();
Base = File->getFileName();
Base.replace('\\', '/');
// fill the file list
populateFileList();
}
}
CTarReader::~CTarReader()
{
if (File)
File->drop();
}
u32 CTarReader::populateFileList()
{
STarHeader fHead;
FileList.clear();
u32 pos = 0;
while ( s32(pos + sizeof(STarHeader)) < File->getSize())
{
// seek to next file header
File->seek(pos);
// read the header
File->read(&fHead, sizeof(fHead));
#ifdef __BIG_ENDIAN__
for (u32* p = (u32*)&fHead; p < &fHead + sizeof(fHead); ++p)
os::Byteswap::byteswap(*p);
#endif
// only add standard files for now
if (fHead.Link == ETLI_REGULAR_FILE || ETLI_REGULAR_FILE_OLD)
{
STARArchiveEntry entry;
core::string<c16> fullPath = L"";
fullPath.reserve(255);
// USTAR archives have a filename prefix
// may not be null terminated, copy carefully!
if (!strcmp(fHead.Magic, "ustar"))
{
c8* np = fHead.FileNamePrefix;
while(*np && (np - fHead.FileNamePrefix) < 155)
fullPath.append(*np);
np++;
}
// append the file name
c8* np = fHead.FileName;
while(*np && (np - fHead.FileName) < 100)
{
fullPath.append(*np);
np++;
}
fullPath.replace('\\', '/');
s32 lastSlash = fullPath.findLast('/');
if (IgnoreCase)
fullPath.make_lower();
if (lastSlash == -1)
{
entry.path = "";
entry.simpleFileName = fullPath;
}
else
{
entry.path = fullPath.subString(0, lastSlash);
if (IgnorePaths)
entry.simpleFileName = &fullPath[lastSlash+1];
else
entry.simpleFileName = fullPath;
}
// get size
core::stringc sSize = "";
sSize.reserve(12);
np = fHead.Size;
while(*np && (np - fHead.Size) < 12)
{
sSize.append(*np);
np++;
}
sscanf(sSize.c_str(), "%lo", &entry.size);
// save start position
entry.startPos = pos + 512;
// move to next file header block
pos = entry.startPos + (entry.size / 512) * 512 +
((entry.size % 512) ? 512 : 0);
// add file to list
FileList.push_back(entry);
}
else
{
// move to next block
pos += 512;
}
}
FileList.sort();
return FileList.size();
}
//! opens a file by file name
IReadFile* CTarReader::createAndOpenFile(const core::string<c16>& filename)
{
s32 index = findFile(filename);
if (index != -1)
return createAndOpenFile(index);
return 0;
}
//! opens a file by index
IReadFile* CTarReader::createAndOpenFile(u32 index)
{
if (index < FileList.size())
return createLimitReadFile(FileList[index].simpleFileName, File, FileList[index].startPos, FileList[index].size);
else
return 0;
}
//! returns count of files in archive
u32 CTarReader::getFileCount() const
{
return FileList.size();
}
//! returns data of file
const IFileArchiveEntry* CTarReader::getFileInfo(u32 index)
{
return &FileList[index];
}
//! return the id of the file Archive
const core::string<c16>& CTarReader::getArchiveName()
{
return Base;
}
//! returns fileindex
s32 CTarReader::findFile(const core::string<c16>& simpleFilename)
{
STARArchiveEntry entry;
entry.simpleFileName = simpleFilename;
if (IgnoreCase)
entry.simpleFileName.make_lower();
if (IgnorePaths)
core::deletePathFromFilename(entry.simpleFileName);
s32 res = FileList.binary_search(entry);
return res;
}
} // end namespace io
} // end namespace irr
// Copyright (C) 2009 Gaz Davidson
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#ifndef __C_TAR_READER_H_INCLUDED__
#define __C_TAR_READER_H_INCLUDED__
#include "IReferenceCounted.h"
#include "IReadFile.h"
#include "irrArray.h"
#include "irrString.h"
#include "IFileSystem.h"
#include "IFileList.h"
namespace irr
{
namespace io
{
#if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__)
# pragma pack( push, packing )
# pragma pack( 1 )
# define PACK_STRUCT
#elif defined( __GNUC__ )
# define PACK_STRUCT __attribute__((packed))
#else
# error compiler not supported
#endif
enum E_TAR_LINK_INDICATOR
{
ETLI_REGULAR_FILE_OLD = 0 ,
ETLI_REGULAR_FILE = '0',
ETLI_LINK_TO_ARCHIVED_FILE = '1',
ETLI_SYMBOLIC_LINK = '2',
ETLI_CHAR_SPECIAL_DEVICE = '3',
ETLI_BLOCK_SPECIAL_DEVICE = '4',
ETLI_DIRECTORY = '5',
ETLI_FIFO_SPECIAL_FILE = '6'
};
struct STarHeader
{
c8 FileName[100];
c8 FileMode[8];
c8 UserID[8];
c8 GroupID[8];
c8 Size[12];
c8 ModifiedTime[12];
c8 Checksum[8];
c8 Link;
c8 LinkName[100];
c8 Magic[6];
c8 USTARVersion[2];
c8 UserName[32];
c8 GroupName[32];
c8 DeviceMajor[8];
c8 DeviceMinor[8];
c8 FileNamePrefix[155];
} PACK_STRUCT;
// Default alignment
#if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__)
# pragma pack( pop, packing )
#endif
#undef PACK_STRUCT
//! Archiveloader capable of loading ZIP Archives
class CArchiveLoaderTAR : public IArchiveLoader
{
public:
//! Constructor
CArchiveLoaderTAR(io::IFileSystem* fs);
//! destructor
virtual ~CArchiveLoaderTAR();
//! returns true if the file maybe is able to be loaded by this class
//! based on the file extension (e.g. ".tar")
virtual bool isALoadableFileFormat(const core::string<c16>& filename) const;
//! Creates an archive from the filename
/** \param file File handle to check.
\return Pointer to newly created archive, or 0 upon error. */
virtual IFileArchive* createArchive(const core::string<c16>& filename, bool ignoreCase, bool ignorePaths) const;
//! Check if the file might be loaded by this class
/** Check might look into the file.
\param file File handle to check.
\return True if file seems to be loadable. */
virtual bool isALoadableFileFormat(io::IReadFile* file) const;
//! creates/loads an archive from the file.
//! \return Pointer to the created archive. Returns 0 if loading failed.
virtual io::IFileArchive* createArchive(io::IReadFile* file, bool ignoreCase, bool ignorePaths) const;
//! Returns the type of archive created by this loader
virtual E_FILE_ARCHIVE_TYPE getType() const { return EFAT_TAR; }
private:
io::IFileSystem* FileSystem;
};
class CTarReader : public IFileArchive
{
public:
CTarReader(IReadFile* file, bool ignoreCase, bool ignorePaths);
virtual ~CTarReader();
//! opens a file by file name
virtual IReadFile* createAndOpenFile(const core::string<c16>& filename);
//! opens a file by index
virtual IReadFile* createAndOpenFile(u32 index);
//! returns count of files in archive
virtual u32 getFileCount() const;
//! returns data of file
virtual const IFileArchiveEntry* getFileInfo(u32 index);
//! returns fileindex
virtual s32 findFile(const core::string<c16>& filename);
//! return the id of the file Archive
virtual const core::string<c16>& getArchiveName();
//! get the class Type
virtual E_FILE_ARCHIVE_TYPE getType() const { return EFAT_TAR; }
private:
struct STARArchiveEntry : public IFileArchiveEntry
{
u32 size;
u32 startPos;
};
u32 populateFileList();
IReadFile* File;
bool IgnoreCase;
bool IgnorePaths;
core::array<STARArchiveEntry> FileList;
core::string<c16> Base;
};
} // end namespace io
} // end namespace irr
#endif
......@@ -94,7 +94,7 @@ bool CArchiveLoaderZIP::isALoadableFileFormat(io::IReadFile* file) const
ZIP Archive
*/
CZipReader::CZipReader(IReadFile* file, bool ignoreCase, bool ignorePaths)
: File(file), IgnoreCase(ignoreCase), IgnorePaths(ignorePaths), Type ( "zip" )
: File(file), IgnoreCase(ignoreCase), IgnorePaths(ignorePaths)
{
#ifdef _DEBUG
setDebugName("CZipReader");
......@@ -329,19 +329,19 @@ bool CZipReader::scanLocalHeader()
//! opens a file by file name
IReadFile* CZipReader::openFile(const core::string<c16>& filename)
IReadFile* CZipReader::createAndOpenFile(const core::string<c16>& filename)
{
s32 index = findFile(filename);
if (index != -1)
return openFile(index);
return createAndOpenFile(index);
return 0;
}
//! opens a file by index
IReadFile* CZipReader::openFile(s32 index)
IReadFile* CZipReader::createAndOpenFile(u32 index)
{
//0 - The file is stored (no compression)
//1 - The file is Shrunk
......@@ -593,7 +593,6 @@ CMountPointReader::CMountPointReader( IFileSystem * parent, const core::string<c
Base.replace ( '\\', '/' );
if ( core::lastChar ( Base ) != '/' )
Base.append ( '/' );
Type = "mount";
}
void CMountPointReader::buildDirectory ( )
......@@ -601,31 +600,29 @@ void CMountPointReader::buildDirectory ( )
}
//! opens a file by file name
IReadFile* CMountPointReader::openFile(const core::string<c16>& filename)
IReadFile* CMountPointReader::createAndOpenFile(const core::string<c16>& filename)
{
if ( !filename.size() )
if (!filename.size())
return 0;
core::string<c16> fname ( Base );
core::string<c16> fname(Base);
fname += filename;
CMountPointReadFile* file = new CMountPointReadFile( fname, filename);
CMountPointReadFile* file = new CMountPointReadFile(fname, filename);
if (file->isOpen())
return file;
file->drop();
return 0;
}
//! returns fileindex
s32 CMountPointReader::findFile(const core::string<c16>& filename)
{
IReadFile *file = openFile ( filename );
if ( 0 == file )
IReadFile *file = createAndOpenFile(filename);
if (!file)
return -1;
file->drop ();
file->drop();
return 1;
}
......@@ -636,7 +633,7 @@ s32 CMountPointReader::findFile(const core::string<c16>& filename)
CMountPointReader::CMountPointReader( IFileSystem * parent, const core::string<c16>& basename, bool ignoreCase, bool ignorePaths)
: CZipReader( 0, ignoreCase, ignorePaths ), Parent ( parent )
{
Type = "mount";
//Type = "mount";
core::string<c16> work = Parent->getWorkingDirectory ();
Parent->changeWorkingDirectoryTo ( basename );
......@@ -685,7 +682,7 @@ s32 CMountPointReader::findFile(const core::string<c16>& simpleFilename)
}
//! opens a file by file name
IReadFile* CMountPointReader::openFile(const core::string<c16>& filename)
IReadFile* CMountPointReader::createAndOpenFile(const core::string<c16>& filename)
{
s32 index = -1;
......
......@@ -142,6 +142,9 @@ namespace io
//! \return Pointer to the created archive. Returns 0 if loading failed.
virtual io::IFileArchive* createArchive(io::IReadFile* file, bool ignoreCase, bool ignorePaths) const;
//! Returns the type of archive created by this loader
virtual E_FILE_ARCHIVE_TYPE getType() const { return EFAT_ZIP; }
private:
io::IFileSystem* FileSystem;
};
......@@ -159,10 +162,10 @@ namespace io
virtual ~CZipReader();
//! opens a file by file name
virtual IReadFile* openFile(const core::string<c16>& filename);
virtual IReadFile* createAndOpenFile(const core::string<c16>& filename);
//! opens a file by index
virtual IReadFile* openFile(s32 index);
virtual IReadFile* createAndOpenFile(u32 index);
//! returns count of files in archive
virtual u32 getFileCount() const;
......@@ -177,7 +180,7 @@ namespace io
virtual const core::string<c16>& getArchiveName ();
//! get the class Type
virtual const core::string<c16>& getArchiveType() { return Type; }
virtual E_FILE_ARCHIVE_TYPE getType() const { return EFAT_ZIP; }
private:
......@@ -197,7 +200,6 @@ namespace io
bool IgnorePaths;
core::array<SZipFileEntry> FileList;
core::string<c16> Type;
core::string<c16> Base;
};
......@@ -232,6 +234,9 @@ namespace io
//! \return Pointer to the created archive. Returns 0 if loading failed.
virtual IFileArchive* createArchive(io::IReadFile* file, bool ignoreCase, bool ignorePaths) const;
//! Returns the type of archive created by this loader
virtual E_FILE_ARCHIVE_TYPE getType() const { return EFAT_FOLDER; }
private:
io::IFileSystem* FileSystem;
};
......@@ -245,11 +250,14 @@ namespace io
bool ignoreCase, bool ignorePaths);
//! opens a file by file name
virtual IReadFile* openFile(const core::string<c16>& filename);
virtual IReadFile* createAndOpenFile(const core::string<c16>& filename);
//! returns fileindex
virtual s32 findFile(const core::string<c16>& filename);
//! get the class Type
virtual E_FILE_ARCHIVE_TYPE getType() const { return EFAT_FOLDER; }
private:
IFileSystem *Parent;
......
......@@ -1978,6 +1978,12 @@
<File
RelativePath=".\CPakReader.h">
</File>
<File
RelativePath=".\CTarReader.cpp">
</File>
<File
RelativePath=".\CTarReader.h">
</File>
<File
RelativePath=".\CReadFile.cpp">
</File>
......
......@@ -2746,6 +2746,14 @@
RelativePath="CPakReader.h"
>
</File>
<File
RelativePath="CTarReader.cpp"
>
</File>
<File
RelativePath="CTarReader.h"
>
</File>
<File
RelativePath="CReadFile.cpp"
>
......
......@@ -3107,6 +3107,14 @@
RelativePath="CReadFile.h"
>
</File>
<File
RelativePath=".\CTarReader.cpp"
>
</File>
<File
RelativePath=".\CTarReader.h"
>
</File>
<File
RelativePath="CWriteFile.cpp"
>
......
......@@ -2385,6 +2385,14 @@
RelativePath="CPakReader.h"
>
</File>
<File
RelativePath="CTarReader.cpp"
>
</File>
<File
RelativePath="CTarReader.h"
>
</File>
<File
RelativePath="CReadFile.cpp"
>
......
......@@ -1132,6 +1132,12 @@
<File
RelativePath=".\CPakReader.h">
</File>
<File
RelativePath=".\CTarReader.cpp">
</File>
<File
RelativePath=".\CTarReader.h">
</File>
<File
RelativePath=".\CParticleAnimatedMeshSceneNodeEmitter.cpp">
</File>
......
......@@ -33,7 +33,7 @@ IRRIMAGEOBJ = CColorConverter.o CImage.o CImageLoaderBMP.o CImageLoaderJPG.o CIm
CImageWriterBMP.o CImageWriterJPG.o CImageWriterPCX.o CImageWriterPNG.o CImageWriterPPM.o CImageWriterPSD.o CImageWriterTGA.o
IRRVIDEOOBJ = CVideoModeList.o CFPSCounter.o $(IRRDRVROBJ) $(IRRIMAGEOBJ)
IRRSWRENDEROBJ = CSoftwareDriver.o CSoftwareTexture.o CTRFlat.o CTRFlatWire.o CTRGouraud.o CTRGouraudWire.o CTRTextureFlat.o CTRTextureFlatWire.o CTRTextureGouraud.o CTRTextureGouraudAdd.o CTRTextureGouraudNoZ.o CTRTextureGouraudWire.o CZBuffer.o CTRTextureGouraudVertexAlpha2.o CTRTextureGouraudNoZ2.o CTRTextureLightMap2_M2.o CTRTextureLightMap2_M4.o CTRTextureLightMap2_M1.o CSoftwareDriver2.o CSoftwareTexture2.o CTRTextureGouraud2.o CTRGouraud2.o CTRGouraudAlpha2.o CTRGouraudAlphaNoZ2.o CTRTextureDetailMap2.o CTRTextureGouraudAdd2.o CTRTextureGouraudAddNoZ2.o CTRTextureWire2.o CTRTextureLightMap2_Add.o CTRTextureLightMapGouraud2_M4.o IBurningShader.o CTRTextureBlend.o CTRTextureGouraudAlpha.o CTRTextureGouraudAlphaNoZ.o CDepthBuffer.o CBurningShader_Raster_Reference.o
IRRIOOBJ = CFileList.o CFileSystem.o CLimitReadFile.o CMemoryFile.o CReadFile.o CWriteFile.o CXMLReader.o CXMLWriter.o CZipReader.o CPakReader.o irrXML.o CAttributes.o
IRRIOOBJ = CFileList.o CFileSystem.o CLimitReadFile.o CMemoryFile.o CReadFile.o CWriteFile.o CXMLReader.o CXMLWriter.o CZipReader.o CPakReader.o CTarReader.o irrXML.o CAttributes.o
IRROTHEROBJ = CIrrDeviceSDL.o CIrrDeviceLinux.o CIrrDeviceConsole.o CIrrDeviceStub.o CIrrDeviceWin32.o CLogger.o COSOperator.o Irrlicht.o os.o
IRRGUIOBJ = CGUIButton.o CGUICheckBox.o CGUIComboBox.o CGUIContextMenu.o CGUIEditBox.o CGUIEnvironment.o CGUIFileOpenDialog.o CGUIFont.o CGUIImage.o CGUIInOutFader.o CGUIListBox.o CGUIMenu.o CGUIMeshViewer.o CGUIMessageBox.o CGUIModalScreen.o CGUIScrollBar.o CGUISpinBox.o CGUISkin.o CGUIStaticText.o CGUITabControl.o CGUITable.o CGUIToolBar.o CGUIWindow.o CGUIColorSelectDialog.o CDefaultGUIElementFactory.o CGUISpriteBank.o CGUIImageList.o CGUITreeView.o
ZLIBOBJ = zlib/adler32.o zlib/compress.o zlib/crc32.o zlib/deflate.o zlib/inffast.o zlib/inflate.o zlib/inftrees.o zlib/trees.o zlib/uncompr.o zlib/zutil.o
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment