Commit cc173d11 authored by bitplane's avatar bitplane

API Change! File archive API tidied: CFileList now takes care of removing...

API Change! File archive API tidied: CFileList now takes care of removing paths lowering case, finding files, it can hold directory trees and is populated by the filesystem and archives. Archives now inherit it and return a const IFileList pointer rather than implementing each method and requiring special entry types in the API. createFileList works with the virtual filesystem. Separated the mount point stuff from the zip reader to its own files. Added GZIP archive type, fixed problem when loading files without names in gzips. Fixed a crash in the file dialog when the file list was null.

todo: update projects, test properly on Windows and OSX, add #defines for archive loaders

git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@2590 dfc29bdd-3216-0410-991c-e03cc46cb475
parent e6b350d3
Changes in 1.6 (??.??.2009) Changes in 1.6 (??.??.2009)
- Added const method for array::binary_search, potentially slow as it doesn't sort the list!
- Add support for scaling button images. - Add support for scaling button images.
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#define __I_FILE_ARCHIVE_H_INCLUDED__ #define __I_FILE_ARCHIVE_H_INCLUDED__
#include "IReadFile.h" #include "IReadFile.h"
#include "IFileList.h"
namespace irr namespace irr
{ {
...@@ -23,15 +24,18 @@ enum EFileSystemType ...@@ -23,15 +24,18 @@ enum EFileSystemType
//! Contains the different types of archives //! Contains the different types of archives
enum E_FILE_ARCHIVE_TYPE enum E_FILE_ARCHIVE_TYPE
{ {
//! A PKZIP or gzip archive //! A PKZIP archive
EFAT_ZIP = MAKE_IRR_ID('Z','I','P', 0), EFAT_ZIP = MAKE_IRR_ID('Z','I','P', 0),
//! A gzip archive
EFAT_GZIP = MAKE_IRR_ID('g','z','i','p'),
//! A virtual directory //! A virtual directory
EFAT_FOLDER = MAKE_IRR_ID('f','l','d','r'), EFAT_FOLDER = MAKE_IRR_ID('f','l','d','r'),
//! An ID Software PAK archive //! An ID Software PAK archive
EFAT_PAK = MAKE_IRR_ID('P','A','K', 0), EFAT_PAK = MAKE_IRR_ID('P','A','K', 0),
//! A Tape ARchive //! A Tape ARchive
EFAT_TAR = MAKE_IRR_ID('T','A','R', 0), EFAT_TAR = MAKE_IRR_ID('T','A','R', 0),
...@@ -39,7 +43,7 @@ enum E_FILE_ARCHIVE_TYPE ...@@ -39,7 +43,7 @@ enum E_FILE_ARCHIVE_TYPE
EFAT_UNKNOWN = MAKE_IRR_ID('u','n','k','n') EFAT_UNKNOWN = MAKE_IRR_ID('u','n','k','n')
}; };
/*
//! Base Info which all File archives must support on browsing //! Base Info which all File archives must support on browsing
struct IFileArchiveEntry struct IFileArchiveEntry
{ {
...@@ -50,45 +54,41 @@ struct IFileArchiveEntry ...@@ -50,45 +54,41 @@ struct IFileArchiveEntry
bool operator < (const IFileArchiveEntry& other) const bool operator < (const IFileArchiveEntry& other) const
{ {
return simpleFileName < other.simpleFileName; return path < other.path;
} }
bool operator == (const IFileArchiveEntry& other) const bool operator == (const IFileArchiveEntry& other) const
{ {
return simpleFileName == other.simpleFileName; return path == other.path;
} }
}; };
*/
//! The FileArchive manages archives and provides access to files inside them.
//! The FileArchive manages files and archives and provides access to them.
/** It manages where files are, so that modules which use the the IO do not
need to know where every file is located. A file could be in a .zip-Archive or
as file on disk, using the IFileSystem makes no difference to this. */
class IFileArchive : public virtual IReferenceCounted class IFileArchive : public virtual IReferenceCounted
{ {
public: public:
//! return the id of the file Archive //! Opens a file based on its name
virtual const core::string<c16>& getArchiveName() =0; /** Creates and returns a new IReadFile for a file in the archive.
\param filename The file to open
//! get the archive type \return Returns A pointer to the created file on success,
virtual E_FILE_ARCHIVE_TYPE getType() const { return EFAT_UNKNOWN; } or 0 on failure. */
//! opens a file by file name
virtual IReadFile* createAndOpenFile(const core::string<c16>& filename) =0; virtual IReadFile* createAndOpenFile(const core::string<c16>& filename) =0;
//! opens a file by position //! Opens a file based on its position.
/** Creates and returns
\param index The zero based index of the file.
\return Returns a pointer to the created file on success, or 0 on failure. */
virtual IReadFile* createAndOpenFile(u32 index) =0; virtual IReadFile* createAndOpenFile(u32 index) =0;
//! returns fileindex //! Returns the complete file tree
virtual s32 findFile(const core::string<c16>& filename) =0; /** \return Returns the complete directory tree for the archive,
including all files and folders */
//! Returns the amount of files in the filelist. virtual const IFileList* getFileList() const =0;
/** \return Amount of files and directories in the file list. */
virtual u32 getFileCount() const =0;
//! returns data of known file //! get the archive type
virtual const IFileArchiveEntry* getFileInfo(u32 index) =0; virtual E_FILE_ARCHIVE_TYPE getType() const { return EFAT_UNKNOWN; }
}; };
//! Class which is able to create an archive from a file. //! Class which is able to create an archive from a file.
...@@ -100,31 +100,32 @@ class IArchiveLoader : public virtual IReferenceCounted ...@@ -100,31 +100,32 @@ class IArchiveLoader : public virtual IReferenceCounted
{ {
public: public:
//! Check if the file might be loaded by this class //! Check if the file might be loaded by this class
/** Check is based on the file extension (e.g. ".zip") /** Check based on the file extension (e.g. ".zip")
\param fileName Name of file to check. \param fileName Name of file to check.
\return True if file seems to be loadable. */ \return True if file seems to be loadable. */
virtual bool isALoadableFileFormat(const core::string<c16>& filename) const =0; virtual bool isALoadableFileFormat(const core::string<c16>& filename) const =0;
//! 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 =0;
//! Check if the file might be loaded by this class //! Check if the file might be loaded by this class
/** Check might look into the file. /** This check may look into the file.
\param file File handle to check. \param file File handle to check.
\return True if file seems to be loadable. */ \return True if file seems to be loadable. */
virtual bool isALoadableFileFormat(io::IReadFile* file) const =0; virtual bool isALoadableFileFormat(io::IReadFile* file) const =0;
//! Check to see if the loader can create archives of this type.
/** Check based on the archive type.
\param fileType The archive type to check.
\return True if the archile loader supports this type, false if not */
virtual bool isALoadableFileFormat(E_FILE_ARCHIVE_TYPE fileType) const =0;
//! 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 =0;
//! Creates an archive from the file //! Creates an archive from the file
/** \param file File handle to check. /** \param file File handle to check.
\return Pointer to newly created archive, or 0 upon error. */ \return Pointer to newly created archive, or 0 upon error. */
virtual IFileArchive* createArchive(io::IReadFile* file, bool ignoreCase, bool ignorePaths) const =0; 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;
}; };
......
...@@ -13,7 +13,9 @@ namespace irr ...@@ -13,7 +13,9 @@ namespace irr
namespace io namespace io
{ {
//! The Filelist lists all files in a directory. //! Provides a list of files and folders.
/** File lists usually contain a list of all files in a given folder,
but can also contain a complete directory structure. */
class IFileList : public virtual IReferenceCounted class IFileList : public virtual IReferenceCounted
{ {
public: public:
...@@ -24,21 +26,38 @@ public: ...@@ -24,21 +26,38 @@ public:
//! Gets the name of a file in the list, based on an index. //! Gets the name of a file in the list, based on an index.
/** The path is not included in this name. Use getFullFileName for this. /** The path is not included in this name. Use getFullFileName for this.
\param index is the zero based index of the file which name should \param index is the zero based index of the file which name should
be returned. The index has to be smaller than the amount getFileCount() returns. be returned. The index must be less than the amount getFileCount() returns.
\return File name of the file. Returns 0, if an error occured. */ \return File name of the file. Returns 0, if an error occured. */
virtual const core::string<c16>& getFileName(u32 index) const = 0; virtual const core::string<c16>& getFileName(u32 index) const = 0;
//! Gets the full name of a file in the list, path included, based on an index. //! Gets the full name of a file in the list including the path, based on an index.
/** \param index is the zero based index of the file which name should /** \param index is the zero based index of the file which name should
be returned. The index has to be smaller than the amount getFileCount() returns. be returned. The index must be less than the amount getFileCount() returns.
\return File name of the file. Returns 0, if an error occured. */ \return File name of the file. Returns 0, if an error occured. */
virtual const core::string<c16>& getFullFileName(u32 index) = 0; virtual const core::string<c16>& getFullFileName(u32 index) const = 0;
//! Returns the size of a file in the file list, based on an index.
/** \param index is the zero based index of the file which should be returned.
The index must be less than the amount getFileCount() returns.
\return The size of the file in bytes. */
virtual u32 getFileSize(u32 index) const = 0;
//! Check if the file is a directory //! Check if the file is a directory
/** \param index The zero based index of the file whose name shall /** \param index The zero based index which will be checked. The index
be returned. The index has to be smaller than the amount getFileCount() returns. must be less than the amount getFileCount() returns.
\return True if the file is a directory, else false. */ \return True if the file is a directory, else false. */
virtual bool isDirectory(u32 index) const = 0; virtual bool isDirectory(u32 index) const = 0;
//! Searches for a file or folder in the list
/** Searches for a file by name
\param filename The name of the file to search for.
\param isFolder True if you are searching for a file, false if you want a dir.
\return Returns the index of the file in the file list, or -1 if
no matching name name was found. */
virtual s32 findFile(const core::string<c16>& filename, bool isFolder=false) const = 0;
//! Returns the base path of the file list
virtual const core::string<c16>& getPath() const = 0;
}; };
} // end namespace irr } // end namespace irr
......
...@@ -6,39 +6,22 @@ ...@@ -6,39 +6,22 @@
#include "IrrCompileConfig.h" #include "IrrCompileConfig.h"
#include "irrArray.h" #include "irrArray.h"
#include "coreutil.h" #include "coreutil.h"
#include <stdlib.h>
#if (defined(_IRR_POSIX_API_) || defined(_IRR_OSX_PLATFORM_))
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>
#include <unistd.h>
#endif
#ifdef _IRR_WINDOWS_API_
#if !defined ( _WIN32_WCE )
#include <io.h>
#include <direct.h>
#endif
#endif
namespace irr namespace irr
{ {
namespace io namespace io
{ {
CFileList::CFileList(const c8 * param) static const core::string<c16> emptyFileListEntry;
CFileList::CFileList(const core::string<c16>& path, bool ignoreCase, bool ignorePaths)
: IgnorePaths(ignorePaths), IgnoreCase(ignoreCase), Path(path)
{ {
#ifdef _DEBUG #ifdef _DEBUG
setDebugName("CFileList"); setDebugName("CFileList");
#endif #endif
Path.replace('\\', '/');
if ( 0 == param )
constructNative ();
} }
CFileList::~CFileList() CFileList::~CFileList()
...@@ -46,113 +29,15 @@ CFileList::~CFileList() ...@@ -46,113 +29,15 @@ CFileList::~CFileList()
Files.clear(); Files.clear();
} }
void CFileList::constructNative()
{
// --------------------------------------------
// Windows version
#ifdef _IRR_WINDOWS_API_
#if !defined ( _WIN32_WCE )
char tmp[_MAX_PATH];
_getcwd(tmp, _MAX_PATH);
Path = tmp;
struct _finddata_t c_file;
long hFile;
FileEntry entry;
if( (hFile = _findfirst( "*", &c_file )) != -1L )
{
do
{
entry.Name = c_file.name;
entry.Size = c_file.size;
entry.isDirectory = (_A_SUBDIR & c_file.attrib) != 0;
Files.push_back(entry);
}
while( _findnext( hFile, &c_file ) == 0 );
_findclose( hFile );
}
#endif
//TODO add drives
//entry.Name = "E:\\";
//entry.isDirectory = true;
//Files.push_back(entry);
#endif
// --------------------------------------------
// Linux version
#if (defined(_IRR_POSIX_API_) || defined(_IRR_OSX_PLATFORM_))
FileEntry entry;
// Add default parent - even when at /, this is available
entry.Name = "..";
entry.Size = 0;
entry.isDirectory = true;
Files.push_back(entry);
// getting the CWD is rather complex as we do not know the size
// so try it until the call was successful
// Note that neither the first nor the second parameter may be 0 according to POSIX
u32 pathSize=256;
char *tmpPath = new char[pathSize];
while ((pathSize < (1<<16)) && !(getcwd(tmpPath,pathSize)))
{
delete [] tmpPath;
pathSize *= 2;
tmpPath = new char[pathSize];
}
if (!tmpPath)
return;
// note that Path might be stringw, so use tmpPath for system call
Path = tmpPath;
// We use the POSIX compliant methods instead of scandir
DIR* dirHandle=opendir(tmpPath);
delete [] tmpPath;
if (!dirHandle)
return;
struct dirent *dirEntry;
while ((dirEntry=readdir(dirHandle)))
{
if((strcmp(dirEntry->d_name, ".")==0) ||
(strcmp(dirEntry->d_name, "..")==0))
continue;
entry.Name = dirEntry->d_name;
entry.Size = 0;
entry.isDirectory = false;
struct stat buf;
if (stat(dirEntry->d_name, &buf)==0)
{
entry.Size = buf.st_size;
entry.isDirectory = S_ISDIR(buf.st_mode);
}
#if !defined(_IRR_SOLARIS_PLATFORM_) && !defined(__CYGWIN__)
// only available on some systems
else
{
entry.isDirectory = dirEntry->d_type == DT_DIR;
}
#endif
Files.push_back(entry);
}
closedir(dirHandle);
#endif
// sort the list on all platforms
Files.sort();
}
u32 CFileList::getFileCount() const u32 CFileList::getFileCount() const
{ {
return Files.size(); return Files.size();
} }
void CFileList::sort()
static const core::string<c16> emptyFileListEntry; {
Files.sort();
}
const core::string<c16>& CFileList::getFileName(u32 index) const const core::string<c16>& CFileList::getFileName(u32 index) const
{ {
...@@ -164,36 +49,97 @@ const core::string<c16>& CFileList::getFileName(u32 index) const ...@@ -164,36 +49,97 @@ const core::string<c16>& CFileList::getFileName(u32 index) const
//! Gets the full name of a file in the list, path included, based on an index. //! Gets the full name of a file in the list, path included, based on an index.
const core::string<c16>& CFileList::getFullFileName(u32 index) const core::string<c16>& CFileList::getFullFileName(u32 index) const
{ {
if (index >= Files.size()) if (index >= Files.size())
return emptyFileListEntry; return emptyFileListEntry;
if (Files[index].FullName.size() < Files[index].Name.size()) return Files[index].FullName;
{ }
// create full name
Files[index].FullName = Path;
c16 last = lastChar ( Files[index].FullName );
if ( last != '/' && last != '\\' )
Files[index].FullName.append('/');
Files[index].FullName.append(Files[index].Name); //! adds a file or folder
u32 CFileList::addItem(const core::string<c16>& fullPath, u32 size, bool isDirectory, u32 id)
{
SFileListEntry entry;
entry.Size = size;
entry.ID = id;
entry.Name = fullPath;
entry.Name.replace('\\', '/');
entry.IsDirectory = isDirectory;
// remove trailing slash
if (core::lastChar(entry.Name) == '/')
{
entry.IsDirectory = true;
entry.Name[entry.Name.size()-1] = 0;
entry.Name.validate();
} }
return Files[index].FullName; if (IgnoreCase)
} entry.Name.make_lower();
entry.FullName = entry.Name;
core::deletePathFromFilename(entry.Name);
if (IgnorePaths)
entry.FullName = entry.Name;
Files.push_back(entry);
return Files.size() - 1;
}
bool CFileList::isDirectory(u32 index) const bool CFileList::isDirectory(u32 index) const
{ {
bool ret = false; bool ret = false;
if (index < Files.size()) if (index < Files.size())
ret = Files[index].isDirectory; ret = Files[index].IsDirectory;
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
return ret; return ret;
} }
//! Returns the size of a file
u32 CFileList::getFileSize(u32 index) const
{
return index < Files.size() ? Files[index].IsDirectory : 0;
}
//! Searches for a file or folder within the list, returns the index
s32 CFileList::findFile(const core::string<c16>& filename, bool isDirectory = false) const
{
SFileListEntry entry;
entry.FullName = filename;
entry.IsDirectory = isDirectory;
// swap
entry.FullName.replace('\\', '/');
// remove trailing slash
if (core::lastChar(entry.Name) == '/')
{
entry.IsDirectory = true;
entry.Name[ entry.Name.size()-1] = 0;
entry.Name.validate();
}
if (IgnoreCase)
entry.FullName.make_lower();
if (IgnorePaths)
core::deletePathFromFilename(entry.FullName);
return Files.binary_search(entry);
}
//! Returns the base path of the file list
const core::string<c16>& CFileList::getPath() const
{
return Path;
}
} // end namespace irr } // end namespace irr
} // end namespace io } // end namespace io
...@@ -15,66 +15,110 @@ namespace irr ...@@ -15,66 +15,110 @@ namespace irr
namespace io namespace io
{ {
/*! //! An entry in a list of files, can be a folder or a file.
FileSystem, which manages where files are, so that modules which struct SFileListEntry
use the the io do not need to know where every file is located.
local FileEntry
*/
struct FileEntry
{ {
//! The name of the file
/** If this is a file or folder in the virtual filesystem and the archive
was created with the ignoreCase flag then the file name will be lower case. */
core::string<c16> Name; core::string<c16> Name;
//! The name of the file including the path
/** If this is a file or folder in the virtual filesystem and the archive was
created with the ignoreDirs flag then it will be the same as Name. */
core::string<c16> FullName; core::string<c16> FullName;
long Size;
bool isDirectory;
bool operator <(const struct FileEntry& other) const //! The size of the file in bytes
u32 Size;
//! The ID of the file in an archive
/** This is used to link the FileList entry to extra info held about this
file in an archive, which can hold things like data offset and CRC. */
u32 ID;
//! True if this is a folder, false if not.
bool IsDirectory;
//! The == operator is provided so that CFileList can slowly search the list!
bool operator ==(const struct SFileListEntry& other) const
{ {
if ( isDirectory ^ other.isDirectory ) if (IsDirectory != other.IsDirectory)
return isDirectory; return false;
return Name.lower_ignore_case ( other.Name ); return FullName.equals_ignore_case(other.FullName);
}
//! The < operator is provided so that CFileList can sort and quickly search the list.
bool operator <(const struct SFileListEntry& other) const
{
if (IsDirectory != other.IsDirectory)
return IsDirectory;
return FullName.lower_ignore_case(other.FullName);
} }
}; };
/*! //! Implementation of a file list
FileSystem, which manages where files are, so that modules which
use the the io do not need to know where every file is located.
*/
class CFileList : public IFileList class CFileList : public IFileList
{ {
public: public:
//! constructor // CFileList methods
CFileList( const c8 *param = 0);
//! Constructor
/** \param path The path of this file archive */
CFileList(const core::string<c16>& path, bool ignoreCase, bool ignorePaths);
//! Destructor
virtual ~CFileList(); virtual ~CFileList();
//! Add as a file or folder to the list
/** \param fullPath The file name including path, up to the root of the file list.
\param isDirectory True if this is a directory rather than a file.
\param size The size of the file in bytes.
\param id The ID of the file in the archive which owns it */
virtual u32 addItem(const core::string<c16>& fullPath, u32 size, bool isDirectory, u32 id=0);
//! Sorts the file list
void sort();
// IFileList methods
//! Returns the amount of files in the filelist. //! Returns the amount of files in the filelist.
/** \return Amount of files and directories in the file list. */
virtual u32 getFileCount() const; virtual u32 getFileCount() const;
//! Gets the name of a file in the list, based on an index. //! Gets the name of a file in the list, based on an index.
/** \param index is the zero based index of the file which name should
be returned. The index has to be smaller than the amount getFileCount() returns.
\return The file name of the file. Returns 0, if an error occured. */
virtual const core::string<c16>& getFileName(u32 index) const; virtual const core::string<c16>& getFileName(u32 index) const;
//! Gets the full name of a file in the list, path included, based on an index. //! Gets the full name of a file in the list, path included, based on an index.
virtual const core::string<c16>& getFullFileName(u32 index); virtual const core::string<c16>& getFullFileName(u32 index) const;
//! Returns of the file is a directory //! Returns true if the file is a directory
/** \param index is the zero based index of the file which name should
be returned. The index has to be smaller than the amount getFileCount() returns.
\return True if the file is a directory, else false. */
virtual bool isDirectory(u32 index) const; virtual bool isDirectory(u32 index) const;
//protected: //! Returns the size of a file
virtual u32 getFileSize(u32 index) const;
//! Searches for a file or folder within the list, returns the index
virtual s32 findFile(const core::string<c16>& filename, bool isFolder) const;
//! Returns the base path of the file list
virtual const core::string<c16>& getPath() const;
protected:
//! Ignore paths when adding or searching for files
bool IgnorePaths;
//! Ignore case when adding or searching for files
bool IgnoreCase;
//! Path to the file list
core::string<c16> Path; core::string<c16> Path;
core::array< FileEntry > Files;
void constructNative (); //! List of files
core::array<SFileListEntry> Files;
}; };
......
This diff is collapsed.
...@@ -46,7 +46,7 @@ public: ...@@ -46,7 +46,7 @@ public:
virtual IWriteFile* createAndWriteFile(const core::string<c16>& filename, bool append=false); virtual IWriteFile* createAndWriteFile(const core::string<c16>& filename, bool append=false);
//! Adds an archive to the file system. //! Adds an archive to the file system.
virtual bool addFileArchive(const core::string<c16>& filename, bool ignoreCase = true, virtual bool addFileArchive(const core::string<c16>& filename, bool ignoreCase = true,
bool ignorePaths = true, E_FILE_ARCHIVE_TYPE archiveType = EFAT_UNKNOWN); bool ignorePaths = true, E_FILE_ARCHIVE_TYPE archiveType = EFAT_UNKNOWN);
//! move the hirarchy of the filesystem. moves sourceIndex relative up or down //! move the hirarchy of the filesystem. moves sourceIndex relative up or down
...@@ -92,7 +92,7 @@ public: ...@@ -92,7 +92,7 @@ public:
virtual EFileSystemType setFileListSystem(EFileSystemType listType); virtual EFileSystemType setFileListSystem(EFileSystemType listType);
//! Creates a list of files and directories in the current working directory //! Creates a list of files and directories in the current working directory
//! and returns it. //! and returns it.
virtual IFileList* createFileList(); virtual IFileList* createFileList();
...@@ -122,10 +122,14 @@ public: ...@@ -122,10 +122,14 @@ public:
private: private:
EFileSystemType FileSystemType; // Currently used FileSystemType //! Currently used FileSystemType
core::string<c16> WorkingDirectory [2]; // WorkingDirectory for Native/Virtual EFileSystemType FileSystemType;
core::array<IArchiveLoader*> ArchiveLoader; // currently attached ArchiveLoaders //! WorkingDirectory for Native and Virtual filesystems
core::array<IFileArchive*> FileArchives; // currently attached Archives core::string<c16> WorkingDirectory [2];
//! currently attached ArchiveLoaders
core::array<IArchiveLoader*> ArchiveLoader;
//! currently attached Archives
core::array<IFileArchive*> FileArchives;
}; };
......
...@@ -325,10 +325,13 @@ void CGUIFileOpenDialog::fillListBox() ...@@ -325,10 +325,13 @@ void CGUIFileOpenDialog::fillListBox()
FileList = FileSystem->createFileList(); FileList = FileSystem->createFileList();
core::stringw s; core::stringw s;
for (u32 i=0; i<FileList->getFileCount(); ++i) if (FileList)
{ {
s = FileList->getFileName(i); for (u32 i=0; i < FileList->getFileCount(); ++i)
FileBox->addItem(s.c_str(), skin->getIcon(FileList->isDirectory(i) ? EGDI_DIRECTORY : EGDI_FILE)); {
s = FileList->getFileName(i);
FileBox->addItem(s.c_str(), skin->getIcon(FileList->isDirectory(i) ? EGDI_DIRECTORY : EGDI_FILE));
}
} }
if (FileNameText) if (FileNameText)
......
// Copyright (C) 2002-2009 Nikolaus Gebhardt
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#include "CMountPointReader.h"
#include "CReadFile.h"
#include "os.h"
namespace irr
{
namespace io
{
//! Constructor
CArchiveLoaderMount::CArchiveLoaderMount( io::IFileSystem* fs)
: FileSystem(fs)
{
#ifdef _DEBUG
setDebugName("CArchiveLoaderMount");
#endif
}
//! destructor
CArchiveLoaderMount::~CArchiveLoaderMount()
{
}
//! returns true if the file maybe is able to be loaded by this class
bool CArchiveLoaderMount::isALoadableFileFormat(const core::string<c16>& filename) const
{
bool ret = false;
core::string<c16> fname(filename);
deletePathFromFilename(fname);
if (!fname.size())
{
ret = true;
}
return ret;
}
//! Check to see if the loader can create archives of this type.
bool CArchiveLoaderMount::isALoadableFileFormat(E_FILE_ARCHIVE_TYPE fileType) const
{
return fileType == EFAT_FOLDER;
}
//! Check if the file might be loaded by this class
bool CArchiveLoaderMount::isALoadableFileFormat(io::IReadFile* file) const
{
return false;
}
//! Creates an archive from the filename
IFileArchive* CArchiveLoaderMount::createArchive(const core::string<c16>& filename, bool ignoreCase, bool ignorePaths) const
{
IFileArchive *archive = 0;
EFileSystemType current = FileSystem->setFileListSystem(FILESYSTEM_NATIVE);
core::string<c16> save = FileSystem->getWorkingDirectory();
core::string<c16> fullPath = FileSystem->getAbsolutePath(filename);
FileSystem->flattenFilename(fullPath);
if ( FileSystem->changeWorkingDirectoryTo ( fullPath ) )
{
archive = new CMountPointReader(FileSystem, fullPath, ignoreCase, ignorePaths);
}
FileSystem->changeWorkingDirectoryTo(save);
FileSystem->setFileListSystem(current);
return archive;
}
//! creates/loads an archive from the file.
//! \return Pointer to the created archive. Returns 0 if loading failed.
IFileArchive* CArchiveLoaderMount::createArchive(io::IReadFile* file, bool ignoreCase, bool ignorePaths) const
{
return 0;
}
//! compatible Folder Archticture
//
CMountPointReader::CMountPointReader( IFileSystem * parent, const core::string<c16>& basename, bool ignoreCase, bool ignorePaths)
: CFileList(basename, ignoreCase, ignorePaths), Parent(parent)
{
//! ensure CFileList path ends in a slash
if (core::lastChar(Path) != '/' )
Path.append ('/');
core::string<c16> work = Parent->getWorkingDirectory();
Parent->changeWorkingDirectoryTo(basename);
buildDirectory();
Parent->changeWorkingDirectoryTo(work);
sort();
}
CMountPointReader::~CMountPointReader()
{
}
//! returns the list of files
const IFileList* CMountPointReader::getFileList() const
{
return this;
}
void CMountPointReader::buildDirectory()
{
IFileList * list = Parent->createFileList();
const u32 size = list->getFileCount();
for (u32 i = 0; i!= size; ++i)
{
if (!list->isDirectory(i))
{
addItem(list->getFullFileName(i), list->getFileSize(i), false, RealFileNames.size());
RealFileNames.push_back(list->getFullFileName(i));
}
else
{
const core::string<c16>& full = list->getFullFileName(i);
const core::string<c16> rel = list->getFileName(i);
core::string<c16> pwd = Parent->getWorkingDirectory() + "/";
pwd += rel;
if ( rel != "." && rel != ".." )
{
addItem(full, 0, true, 0);
Parent->changeWorkingDirectoryTo(pwd);
buildDirectory ();
Parent->changeWorkingDirectoryTo("..");
}
}
}
list->drop();
}
//! opens a file by index
IReadFile* CMountPointReader::createAndOpenFile(u32 index)
{
if (index >= Files.size())
return 0;
return createReadFile( RealFileNames[Files[index].ID] );
}
//! opens a file by file name
IReadFile* CMountPointReader::createAndOpenFile(const core::string<c16>& filename)
{
s32 index = findFile(filename, false);
if (index == -1)
return 0;
return createReadFile( RealFileNames[Files[index].ID] );
}
} // io
} // irr
// Copyright (C) 2002-2009 Nikolaus Gebhardt
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#ifndef __C_MOUNT_READER_H_INCLUDED__
#define __C_MOUNT_READER_H_INCLUDED__
#include "IFileSystem.h"
#include "CFileList.h"
namespace irr
{
namespace io
{
//! Archiveloader capable of loading MountPoint Archives
class CArchiveLoaderMount : public IArchiveLoader
{
public:
//! Constructor
CArchiveLoaderMount(io::IFileSystem* fs);
//! destructor
virtual ~CArchiveLoaderMount();
//! returns true if the file maybe is able to be loaded by this class
//! based on the file extension (e.g. ".zip")
virtual bool isALoadableFileFormat(const core::string<c16>& filename) 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;
//! Check to see if the loader can create archives of this type.
/** Check based on the archive type.
\param fileType The archive type to check.
\return True if the archile loader supports this type, false if not */
virtual bool isALoadableFileFormat(E_FILE_ARCHIVE_TYPE fileType) 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;
//! creates/loads an archive from the file.
//! \return Pointer to the created archive. Returns 0 if loading failed.
virtual IFileArchive* createArchive(io::IReadFile* file, bool ignoreCase, bool ignorePaths) const;
private:
io::IFileSystem* FileSystem;
};
//! A File Archive which uses a mountpoint
class CMountPointReader : public virtual IFileArchive, virtual CFileList
{
public:
//! Constructor
CMountPointReader(IFileSystem *parent, const core::string<c16>& basename,
bool ignoreCase, bool ignorePaths);
//! Destructor
virtual ~CMountPointReader();
//! opens a file by index
virtual IReadFile* createAndOpenFile(u32 index);
//! opens a file by file name
virtual IReadFile* createAndOpenFile(const core::string<c16>& filename);
//! returns the list of files
virtual const IFileList* getFileList() const;
//! get the class Type
virtual E_FILE_ARCHIVE_TYPE getType() const { return EFAT_FOLDER; }
private:
core::array<core::string<c16> > RealFileNames;
IFileSystem *Parent;
void buildDirectory();
};
} // io
} // irr
#endif
...@@ -29,6 +29,11 @@ bool CArchiveLoaderPAK::isALoadableFileFormat(const core::string<c16>& filename) ...@@ -29,6 +29,11 @@ bool CArchiveLoaderPAK::isALoadableFileFormat(const core::string<c16>& filename)
return core::hasFileExtension ( filename, "pak" ); return core::hasFileExtension ( filename, "pak" );
} }
//! Check to see if the loader can create archives of this type.
bool CArchiveLoaderPAK::isALoadableFileFormat(E_FILE_ARCHIVE_TYPE fileType) const
{
return fileType == EFAT_PAK;
}
//! Creates an archive from the filename //! Creates an archive from the filename
/** \param file File handle to check. /** \param file File handle to check.
...@@ -43,7 +48,7 @@ IFileArchive* CArchiveLoaderPAK::createArchive(const core::string<c16>& filename ...@@ -43,7 +48,7 @@ IFileArchive* CArchiveLoaderPAK::createArchive(const core::string<c16>& filename
archive = createArchive ( file, ignoreCase, ignorePaths ); archive = createArchive ( file, ignoreCase, ignorePaths );
file->drop (); file->drop ();
} }
return archive; return archive;
} }
...@@ -79,7 +84,7 @@ bool CArchiveLoaderPAK::isALoadableFileFormat(io::IReadFile* file) const ...@@ -79,7 +84,7 @@ bool CArchiveLoaderPAK::isALoadableFileFormat(io::IReadFile* file) const
PAK Reader PAK Reader
*/ */
CPakReader::CPakReader(IReadFile* file, bool ignoreCase, bool ignorePaths) CPakReader::CPakReader(IReadFile* file, bool ignoreCase, bool ignorePaths)
: Type("pak"), File(file), IgnoreCase(ignoreCase), IgnorePaths(ignorePaths) : CFileList(file ? file->getFileName() : "", ignoreCase, ignorePaths), File(file)
{ {
#ifdef _DEBUG #ifdef _DEBUG
setDebugName("CPakReader"); setDebugName("CPakReader");
...@@ -92,8 +97,7 @@ CPakReader::CPakReader(IReadFile* file, bool ignoreCase, bool ignorePaths) ...@@ -92,8 +97,7 @@ CPakReader::CPakReader(IReadFile* file, bool ignoreCase, bool ignorePaths)
// scan local headers // scan local headers
scanLocalHeader(); scanLocalHeader();
// prepare file index for binary search sort();
FileList.sort();
} }
} }
...@@ -105,64 +109,21 @@ CPakReader::~CPakReader() ...@@ -105,64 +109,21 @@ CPakReader::~CPakReader()
} }
//! splits filename into useful filenames and paths const IFileList* CPakReader::getFileList() const
void CPakReader::extractFilename(SPakFileEntry* entry)
{ {
s32 lorfn = 56; // length of real file name return this;
if (!lorfn)
return;
if (IgnoreCase)
entry->pakFileName.make_lower();
const c16* p = entry->pakFileName.c_str() + lorfn;
// suche ein slash oder den anfang.
while (*p!='/' && p!=entry->pakFileName.c_str())
{
--p;
--lorfn;
}
bool thereIsAPath = p != entry->pakFileName.c_str();
if (thereIsAPath)
{
// there is a path
++p;
++lorfn;
}
entry->simpleFileName = p;
entry->path = "";
// pfad auch kopieren
if (thereIsAPath)
{
lorfn = (s32)(p - entry->pakFileName.c_str());
entry->path.append(entry->pakFileName, lorfn);
}
if (!IgnorePaths)
entry->simpleFileName = entry->pakFileName; // thanks to Pr3t3nd3r for this fix
} }
//! scans for a local header, returns false if there is no more local file header. //! scans for a local header, returns false if there is no more local file header.
bool CPakReader::scanLocalHeader() bool CPakReader::scanLocalHeader()
{ {
c8 tmp[1024];
SPakFileEntry entry; c8 tmp[1024];
entry.pos = 0; core::string<c16> PakFileName;
memset(&header, 0, sizeof(SPAKFileHeader)); memset(&header, 0, sizeof(SPAKFileHeader));
File->read(&header, sizeof(SPAKFileHeader)); File->read(&header, sizeof(SPAKFileHeader));
if (header.tag[0] != 'P' && header.tag[1] != 'A') if (header.tag[0] != 'P' && header.tag[1] != 'A')
return false; // local file headers end here. return false; // local file headers end here.
...@@ -173,22 +134,29 @@ bool CPakReader::scanLocalHeader() ...@@ -173,22 +134,29 @@ bool CPakReader::scanLocalHeader()
for(int i = 0; i < count; i++) for(int i = 0; i < count; i++)
{ {
// read filename // read filename
entry.pakFileName.reserve(56+2); PakFileName.reserve(56+2);
File->read(tmp, 56); File->read(tmp, 56);
tmp[56] = 0x0; tmp[56] = 0x0;
entry.pakFileName = tmp; PakFileName = tmp;
#ifdef _DEBUG #ifdef _DEBUG
os::Printer::log(entry.pakFileName.c_str()); os::Printer::log(PakFileName.c_str());
#endif #endif
extractFilename(&entry); s32 offset;
s32 size;
File->read(&entry.pos, sizeof(u32)); File->read(&offset, sizeof(u32));
File->read(&entry.length, sizeof(u32)); File->read(&size, sizeof(u32));
FileList.push_back(entry);
} #ifdef __BIG_ENDIAN__
os::Byteswap::byteswap(offset);
os::Byteswap::byteswap(size);
#endif
addItem(PakFileName, size, false, Offsets.size());
Offsets.push_back(offset);
}
return true; return true;
} }
...@@ -196,7 +164,7 @@ bool CPakReader::scanLocalHeader() ...@@ -196,7 +164,7 @@ bool CPakReader::scanLocalHeader()
//! opens a file by file name //! opens a file by file name
IReadFile* CPakReader::createAndOpenFile(const core::string<c16>& filename) IReadFile* CPakReader::createAndOpenFile(const core::string<c16>& filename)
{ {
s32 index = findFile(filename); s32 index = findFile(filename, false);
if (index != -1) if (index != -1)
return createAndOpenFile(index); return createAndOpenFile(index);
...@@ -208,57 +176,14 @@ IReadFile* CPakReader::createAndOpenFile(const core::string<c16>& filename) ...@@ -208,57 +176,14 @@ IReadFile* CPakReader::createAndOpenFile(const core::string<c16>& filename)
//! opens a file by index //! opens a file by index
IReadFile* CPakReader::createAndOpenFile(u32 index) IReadFile* CPakReader::createAndOpenFile(u32 index)
{ {
if (index < FileList.size()) if (index < Files.size())
return createLimitReadFile(FileList[index].simpleFileName, File, FileList[index].pos, FileList[index].length);
else
return 0;
}
//! returns count of files in archive
u32 CPakReader::getFileCount() const
{
return FileList.size();
}
//! returns data of file
const IFileArchiveEntry* CPakReader::getFileInfo(u32 index)
{
return &FileList[index];
}
//! returns fileindex
s32 CPakReader::findFile(const core::string<c16>& filename)
{
SPakFileEntry entry;
entry.simpleFileName = filename;
if (IgnoreCase)
entry.simpleFileName.make_lower();
if (IgnorePaths)
core::deletePathFromFilename(entry.simpleFileName);
s32 res = FileList.binary_search(entry);
#ifdef _DEBUG
if (res == -1)
{ {
for (u32 i=0; i<FileList.size(); ++i) return createLimitReadFile(Files[index].FullName, File, Offsets[Files[index].ID], Files[index].Size);
if (FileList[i].simpleFileName == entry.simpleFileName)
{
os::Printer::log("File in archive but not found.", entry.simpleFileName.c_str(), ELL_ERROR);
break;
}
} }
#endif else
return 0;
return res;
} }
} // end namespace io } // end namespace io
} // end namespace irr } // end namespace irr
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "irrArray.h" #include "irrArray.h"
#include "irrString.h" #include "irrString.h"
#include "IFileSystem.h" #include "IFileSystem.h"
#include "CFileList.h"
namespace irr namespace irr
{ {
...@@ -22,14 +23,6 @@ namespace io ...@@ -22,14 +23,6 @@ namespace io
u32 length; u32 length;
}; };
struct SPakFileEntry: public IFileArchiveEntry
{
core::string<c16> pakFileName;
u32 pos;
u32 length;
};
//! Archiveloader capable of loading PAK Archives //! Archiveloader capable of loading PAK Archives
class CArchiveLoaderPAK : public IArchiveLoader class CArchiveLoaderPAK : public IArchiveLoader
{ {
...@@ -42,17 +35,23 @@ namespace io ...@@ -42,17 +35,23 @@ namespace io
//! based on the file extension (e.g. ".zip") //! based on the file extension (e.g. ".zip")
virtual bool isALoadableFileFormat(const core::string<c16>& filename) const; 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 if the file might be loaded by this class
/** Check might look into the file. /** Check might look into the file.
\param file File handle to check. \param file File handle to check.
\return True if file seems to be loadable. */ \return True if file seems to be loadable. */
virtual bool isALoadableFileFormat(io::IReadFile* file) const; virtual bool isALoadableFileFormat(io::IReadFile* file) const;
//! Check to see if the loader can create archives of this type.
/** Check based on the archive type.
\param fileType The archive type to check.
\return True if the archile loader supports this type, false if not */
virtual bool isALoadableFileFormat(E_FILE_ARCHIVE_TYPE fileType) 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;
//! creates/loads an archive from the file. //! creates/loads an archive from the file.
//! \return Pointer to the created archive. Returns 0 if loading failed. //! \return Pointer to the created archive. Returns 0 if loading failed.
virtual io::IFileArchive* createArchive(io::IReadFile* file, bool ignoreCase, bool ignorePaths) const; virtual io::IFileArchive* createArchive(io::IReadFile* file, bool ignoreCase, bool ignorePaths) const;
...@@ -66,57 +65,48 @@ namespace io ...@@ -66,57 +65,48 @@ namespace io
//! reads from pak //! reads from pak
class CPakReader : public IFileArchive class CPakReader : public virtual IFileArchive, virtual CFileList
{ {
public: public:
CPakReader(IReadFile* file, bool ignoreCase, bool ignorePaths); CPakReader(IReadFile* file, bool ignoreCase, bool ignorePaths);
virtual ~CPakReader(); virtual ~CPakReader();
// file archive methods
//! return the id of the file Archive
virtual const core::string<c16>& getArchiveName() const
{
return File->getFileName();
}
//! opens a file by file name //! opens a file by file name
virtual IReadFile* createAndOpenFile(const core::string<c16>& filename); virtual IReadFile* createAndOpenFile(const core::string<c16>& filename);
//! opens a file by index //! opens a file by index
virtual IReadFile* createAndOpenFile(u32 index); virtual IReadFile* createAndOpenFile(u32 index);
//! returns count of files in archive //! returns the list of files
virtual u32 getFileCount() const; virtual const IFileList* getFileList() const;
//! returns data of file
virtual const IFileArchiveEntry* getFileInfo(u32 index);
//! returns fileindex
virtual s32 findFile(const core::string<c16>& filename);
//! get the class Type //! get the class Type
virtual E_FILE_ARCHIVE_TYPE getType() const { return EFAT_PAK; } virtual E_FILE_ARCHIVE_TYPE getType() const { return EFAT_PAK; }
//! return the id of the file Archive
virtual const core::string<c16>& getArchiveName ()
{
return File->getFileName();
}
private: private:
core::string<c16> Type;
//! scans for a local header, returns false if there is no more local file header. //! scans for a local header, returns false if there is no more local file header.
bool scanLocalHeader(); bool scanLocalHeader();
//! splits filename from zip file into useful filenames and paths //! splits filename from zip file into useful filenames and paths
void extractFilename(SPakFileEntry* entry); //void extractFilename(SPakFileEntry* entry);
IReadFile* File; IReadFile* File;
SPAKFileHeader header; SPAKFileHeader header;
core::array<SPakFileEntry> FileList; //! Contains offsets of the files from the start of the archive file
core::array<u32> Offsets;
bool IgnoreCase;
bool IgnorePaths;
}; };
} // end namespace io } // end namespace io
......
...@@ -32,6 +32,11 @@ bool CArchiveLoaderTAR::isALoadableFileFormat(const core::string<c16>& filename) ...@@ -32,6 +32,11 @@ bool CArchiveLoaderTAR::isALoadableFileFormat(const core::string<c16>& filename)
return core::hasFileExtension(filename, "tar"); return core::hasFileExtension(filename, "tar");
} }
//! Check to see if the loader can create archives of this type.
bool CArchiveLoaderTAR::isALoadableFileFormat(E_FILE_ARCHIVE_TYPE fileType) const
{
return fileType == EFAT_TAR;
}
//! Creates an archive from the filename //! Creates an archive from the filename
/** \param file File handle to check. /** \param file File handle to check.
...@@ -117,7 +122,7 @@ bool CArchiveLoaderTAR::isALoadableFileFormat(io::IReadFile* file) const ...@@ -117,7 +122,7 @@ bool CArchiveLoaderTAR::isALoadableFileFormat(io::IReadFile* file) const
TAR Archive TAR Archive
*/ */
CTarReader::CTarReader(IReadFile* file, bool ignoreCase, bool ignorePaths) CTarReader::CTarReader(IReadFile* file, bool ignoreCase, bool ignorePaths)
: File(file), IgnoreCase(ignoreCase), IgnorePaths(ignorePaths) : CFileList(file ? file->getFileName() : "", ignoreCase, ignorePaths), File(file)
{ {
#ifdef _DEBUG #ifdef _DEBUG
setDebugName("CTarReader"); setDebugName("CTarReader");
...@@ -127,11 +132,10 @@ CTarReader::CTarReader(IReadFile* file, bool ignoreCase, bool ignorePaths) ...@@ -127,11 +132,10 @@ CTarReader::CTarReader(IReadFile* file, bool ignoreCase, bool ignorePaths)
{ {
File->grab(); File->grab();
Base = File->getFileName();
Base.replace('\\', '/');
// fill the file list // fill the file list
populateFileList(); populateFileList();
sort();
} }
} }
...@@ -140,14 +144,18 @@ CTarReader::~CTarReader() ...@@ -140,14 +144,18 @@ CTarReader::~CTarReader()
{ {
if (File) if (File)
File->drop(); File->drop();
}
const IFileList* CTarReader::getFileList() const
{
return this;
} }
u32 CTarReader::populateFileList() u32 CTarReader::populateFileList()
{ {
STarHeader fHead; STarHeader fHead;
FileList.clear(); Files.clear();
u32 pos = 0; u32 pos = 0;
while ( s32(pos + sizeof(STarHeader)) < File->getSize()) while ( s32(pos + sizeof(STarHeader)) < File->getSize())
...@@ -161,9 +169,7 @@ u32 CTarReader::populateFileList() ...@@ -161,9 +169,7 @@ u32 CTarReader::populateFileList()
// only add standard files for now // only add standard files for now
if (fHead.Link == ETLI_REGULAR_FILE || ETLI_REGULAR_FILE_OLD) if (fHead.Link == ETLI_REGULAR_FILE || ETLI_REGULAR_FILE_OLD)
{ {
STARArchiveEntry entry; core::string<c16> fullPath = "";
core::string<c16> fullPath = L"";
fullPath.reserve(255); fullPath.reserve(255);
// USTAR archives have a filename prefix // USTAR archives have a filename prefix
...@@ -171,7 +177,7 @@ u32 CTarReader::populateFileList() ...@@ -171,7 +177,7 @@ u32 CTarReader::populateFileList()
if (!strcmp(fHead.Magic, "ustar")) if (!strcmp(fHead.Magic, "ustar"))
{ {
c8* np = fHead.FileNamePrefix; c8* np = fHead.FileNamePrefix;
while(*np && (np - fHead.FileNamePrefix) < 155) while(*np && (np - fHead.FileNamePrefix) < 155)
fullPath.append(*np); fullPath.append(*np);
np++; np++;
} }
...@@ -184,26 +190,6 @@ u32 CTarReader::populateFileList() ...@@ -184,26 +190,6 @@ u32 CTarReader::populateFileList()
np++; np++;
} }
fullPath.replace('\\', '/');
const 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 // get size
core::stringc sSize = ""; core::stringc sSize = "";
sSize.reserve(12); sSize.reserve(12);
...@@ -213,38 +199,38 @@ u32 CTarReader::populateFileList() ...@@ -213,38 +199,38 @@ u32 CTarReader::populateFileList()
sSize.append(*np); sSize.append(*np);
np++; np++;
} }
entry.size=strtoul(sSize.c_str(), NULL, 8); u32 size = strtoul(sSize.c_str(), NULL, 8);
if (errno==ERANGE) if (errno == ERANGE)
os::Printer::log("File too large", fullPath, ELL_WARNING); os::Printer::log("File too large", fullPath, ELL_WARNING);
// save start position // save start position
entry.startPos = pos + 512; u32 offset = pos + 512;
// move to next file header block // move to next file header block
pos = entry.startPos + (entry.size / 512) * 512 + pos = offset + (size / 512) * 512 + ((size % 512) ? 512 : 0);
((entry.size % 512) ? 512 : 0);
// add file to list // add file to list
FileList.push_back(entry); addItem(fullPath, size, false, Offsets.size());
Offsets.push_back(offset);
} }
else else
{ {
// todo: ETLI_DIRECTORY, ETLI_LINK_TO_ARCHIVED_FILE
// move to next block // move to next block
pos += 512; pos += 512;
} }
} }
FileList.sort(); return Files.size();
return FileList.size();
} }
//! opens a file by file name //! opens a file by file name
IReadFile* CTarReader::createAndOpenFile(const core::string<c16>& filename) IReadFile* CTarReader::createAndOpenFile(const core::string<c16>& filename)
{ {
const s32 index = findFile(filename); const s32 index = findFile(filename, false);
if (index != -1) if (index != -1)
return createAndOpenFile(index); return createAndOpenFile(index);
...@@ -252,53 +238,15 @@ IReadFile* CTarReader::createAndOpenFile(const core::string<c16>& filename) ...@@ -252,53 +238,15 @@ IReadFile* CTarReader::createAndOpenFile(const core::string<c16>& filename)
return 0; return 0;
} }
//! opens a file by index //! opens a file by index
IReadFile* CTarReader::createAndOpenFile(u32 index) IReadFile* CTarReader::createAndOpenFile(u32 index)
{ {
if (index < FileList.size()) if (index < Files.size())
return createLimitReadFile(FileList[index].simpleFileName, File, FileList[index].startPos, FileList[index].size); return createLimitReadFile(Files[index].FullName, File, Offsets[Files[index].ID], Files[index].Size);
else else
return 0; 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);
return FileList.binary_search(entry);
}
} // end namespace io } // end namespace io
} // end namespace irr } // end namespace irr
...@@ -10,14 +10,14 @@ ...@@ -10,14 +10,14 @@
#include "irrArray.h" #include "irrArray.h"
#include "irrString.h" #include "irrString.h"
#include "IFileSystem.h" #include "IFileSystem.h"
#include "IFileList.h" #include "CFileList.h"
namespace irr namespace irr
{ {
namespace io namespace io
{ {
#if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__) #if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__)
# pragma pack( push, packing ) # pragma pack( push, packing )
# pragma pack( 1 ) # pragma pack( 1 )
# define PACK_STRUCT # define PACK_STRUCT
...@@ -61,7 +61,7 @@ namespace io ...@@ -61,7 +61,7 @@ namespace io
// Default alignment // Default alignment
#if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__) #if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__)
# pragma pack( pop, packing ) # pragma pack( pop, packing )
#endif #endif
...@@ -79,35 +79,39 @@ namespace io ...@@ -79,35 +79,39 @@ namespace io
//! based on the file extension (e.g. ".tar") //! based on the file extension (e.g. ".tar")
virtual bool isALoadableFileFormat(const core::string<c16>& filename) const; 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 if the file might be loaded by this class
/** Check might look into the file. /** Check might look into the file.
\param file File handle to check. \param file File handle to check.
\return True if file seems to be loadable. */ \return True if file seems to be loadable. */
virtual bool isALoadableFileFormat(io::IReadFile* file) const; virtual bool isALoadableFileFormat(io::IReadFile* file) const;
//! Check to see if the loader can create archives of this type.
/** Check based on the archive type.
\param fileType The archive type to check.
\return True if the archile loader supports this type, false if not */
virtual bool isALoadableFileFormat(E_FILE_ARCHIVE_TYPE fileType) 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;
//! creates/loads an archive from the file. //! creates/loads an archive from the file.
//! \return Pointer to the created archive. Returns 0 if loading failed. //! \return Pointer to the created archive. Returns 0 if loading failed.
virtual io::IFileArchive* createArchive(io::IReadFile* file, bool ignoreCase, bool ignorePaths) const; 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: private:
io::IFileSystem* FileSystem; io::IFileSystem* FileSystem;
}; };
class CTarReader : public IFileArchive class CTarReader : public virtual IFileArchive, virtual CFileList
{ {
public: public:
CTarReader(IReadFile* file, bool ignoreCase, bool ignorePaths); CTarReader(IReadFile* file, bool ignoreCase, bool ignorePaths);
virtual ~CTarReader(); virtual ~CTarReader();
//! opens a file by file name //! opens a file by file name
...@@ -116,38 +120,20 @@ namespace io ...@@ -116,38 +120,20 @@ namespace io
//! opens a file by index //! opens a file by index
virtual IReadFile* createAndOpenFile(u32 index); virtual IReadFile* createAndOpenFile(u32 index);
//! returns count of files in archive //! returns the list of files
virtual u32 getFileCount() const; virtual const IFileList* getFileList() 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 //! get the class Type
virtual E_FILE_ARCHIVE_TYPE getType() const { return EFAT_TAR; } virtual E_FILE_ARCHIVE_TYPE getType() const { return EFAT_TAR; }
private: private:
struct STARArchiveEntry : public IFileArchiveEntry
{
u32 size;
u32 startPos;
};
u32 populateFileList(); u32 populateFileList();
IReadFile* File;
bool IgnoreCase; IReadFile* File;
bool IgnorePaths;
core::array<STARArchiveEntry> FileList;
core::string<c16> Base; //! Contains offsets of the files from the start of the archive file
core::array<u32> Offsets;
}; };
} // end namespace io } // end namespace io
......
This diff is collapsed.
...@@ -5,12 +5,11 @@ ...@@ -5,12 +5,11 @@
#ifndef __C_ZIP_READER_H_INCLUDED__ #ifndef __C_ZIP_READER_H_INCLUDED__
#define __C_ZIP_READER_H_INCLUDED__ #define __C_ZIP_READER_H_INCLUDED__
#include "IReferenceCounted.h"
#include "IReadFile.h" #include "IReadFile.h"
#include "irrArray.h" #include "irrArray.h"
#include "irrString.h" #include "irrString.h"
#include "IFileSystem.h" #include "IFileSystem.h"
#include "IFileList.h" #include "CFileList.h"
namespace irr namespace irr
{ {
...@@ -22,7 +21,7 @@ namespace io ...@@ -22,7 +21,7 @@ namespace io
// zero in the local header // zero in the local header
const s16 ZIP_INFO_IN_DATA_DESCRIPTOR = 0x0008; const s16 ZIP_INFO_IN_DATA_DESCRIPTOR = 0x0008;
#if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__) #if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__)
# pragma pack( push, packing ) # pragma pack( push, packing )
# pragma pack( 1 ) # pragma pack( 1 )
# define PACK_STRUCT # define PACK_STRUCT
...@@ -114,23 +113,22 @@ namespace io ...@@ -114,23 +113,22 @@ namespace io
} PACK_STRUCT; } PACK_STRUCT;
// Default alignment // Default alignment
#if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__) #if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__)
# pragma pack( pop, packing ) # pragma pack( pop, packing )
#endif #endif
#undef PACK_STRUCT #undef PACK_STRUCT
//! Contains extended info about zip files in the archive
struct SZipFileEntry : public IFileArchiveEntry struct SZipFileEntry
{ {
SZipFileEntry () {} //! Position of data in the archive file
s32 Offset;
core::string<c16> zipFileName; //! The header for this file containing compression info etc
s32 fileDataPosition; // position of compressed data in file
SZIPFileHeader header; SZIPFileHeader header;
}; };
//! Archiveloader capable of loading ZIP Archives //! Archiveloader capable of loading ZIP Archives
class CArchiveLoaderZIP : public IArchiveLoader class CArchiveLoaderZIP : public IArchiveLoader
{ {
...@@ -143,24 +141,27 @@ namespace io ...@@ -143,24 +141,27 @@ namespace io
//! based on the file extension (e.g. ".zip") //! based on the file extension (e.g. ".zip")
virtual bool isALoadableFileFormat(const core::string<c16>& filename) const; 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 if the file might be loaded by this class
/** Check might look into the file. /** Check might look into the file.
\param file File handle to check. \param file File handle to check.
\return True if file seems to be loadable. */ \return True if file seems to be loadable. */
virtual bool isALoadableFileFormat(io::IReadFile* file) const; virtual bool isALoadableFileFormat(io::IReadFile* file) const;
//! Check to see if the loader can create archives of this type.
/** Check based on the archive type.
\param fileType The archive type to check.
\return True if the archile loader supports this type, false if not */
virtual bool isALoadableFileFormat(E_FILE_ARCHIVE_TYPE fileType) 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;
//! creates/loads an archive from the file. //! creates/loads an archive from the file.
//! \return Pointer to the created archive. Returns 0 if loading failed. //! \return Pointer to the created archive. Returns 0 if loading failed.
virtual io::IFileArchive* createArchive(io::IReadFile* file, bool ignoreCase, bool ignorePaths) const; 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: private:
io::IFileSystem* FileSystem; io::IFileSystem* FileSystem;
}; };
...@@ -168,7 +169,7 @@ namespace io ...@@ -168,7 +169,7 @@ namespace io
/*! /*!
Zip file Reader written April 2002 by N.Gebhardt. Zip file Reader written April 2002 by N.Gebhardt.
*/ */
class CZipReader : public IFileArchive class CZipReader : public virtual IFileArchive, virtual CFileList
{ {
public: public:
...@@ -184,20 +185,11 @@ namespace io ...@@ -184,20 +185,11 @@ namespace io
//! opens a file by index //! opens a file by index
virtual IReadFile* createAndOpenFile(u32 index); virtual IReadFile* createAndOpenFile(u32 index);
//! returns count of files in archive //! returns the list of files
virtual u32 getFileCount() const; virtual const IFileList* getFileList() 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 //! get the archive type
virtual const core::string<c16>& getArchiveName(); virtual E_FILE_ARCHIVE_TYPE getType() const;
//! get the class Type
virtual E_FILE_ARCHIVE_TYPE getType() const { return EFAT_ZIP; }
protected: protected:
...@@ -209,77 +201,12 @@ namespace io ...@@ -209,77 +201,12 @@ namespace io
//! the same but for gzip files //! the same but for gzip files
bool scanGZipHeader(); bool scanGZipHeader();
//! splits filename from zip file into useful filenames and paths
void extractFilename(SZipFileEntry* entry);
bool IgnoreCase;
bool IgnorePaths;
bool IsGZip; bool IsGZip;
core::array<SZipFileEntry> FileList;
core::string<c16> Base; // holds extended info about files
core::array<SZipFileEntry> FileInfo;
}; };
//! Archiveloader capable of loading MountPoint Archives
class CArchiveLoaderMount : public IArchiveLoader
{
public:
//! Constructor
CArchiveLoaderMount(io::IFileSystem* fs);
//! destructor
virtual ~CArchiveLoaderMount();
//! returns true if the file maybe is able to be loaded by this class
//! based on the file extension (e.g. ".zip")
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 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;
};
//! A File Archive whichs uses a a mountpoint
class CMountPointReader : public CZipReader
{
public:
CMountPointReader(IFileSystem *parent, const core::string<c16>& basename,
bool ignoreCase, bool ignorePaths);
//! opens a file by file name
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;
void buildDirectory();
};
} // end namespace io } // end namespace io
} // end namespace irr } // end namespace irr
......
This diff is collapsed.
...@@ -36,7 +36,7 @@ IRRIMAGEOBJ = CColorConverter.o CImage.o CImageLoaderBMP.o CImageLoaderJPG.o CIm ...@@ -36,7 +36,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 CImageWriterBMP.o CImageWriterJPG.o CImageWriterPCX.o CImageWriterPNG.o CImageWriterPPM.o CImageWriterPSD.o CImageWriterTGA.o
IRRVIDEOOBJ = CVideoModeList.o CFPSCounter.o $(IRRDRVROBJ) $(IRRIMAGEOBJ) 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 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 CTarReader.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 CMountPointReader.o irrXML.o CAttributes.o
IRROTHEROBJ = CIrrDeviceSDL.o CIrrDeviceLinux.o CIrrDeviceConsole.o CIrrDeviceStub.o CIrrDeviceWin32.o CLogger.o COSOperator.o Irrlicht.o os.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 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 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