Skip to content

Commit

Permalink
Refactor: Reimplemented DFile as a C++ class
Browse files Browse the repository at this point in the history
Todo: Cleanup
Todo: Reimplement the used DFile pool.
  • Loading branch information
danij-deng committed Oct 1, 2012
1 parent fb7256b commit 0f59ae6
Show file tree
Hide file tree
Showing 16 changed files with 560 additions and 378 deletions.
155 changes: 112 additions & 43 deletions doomsday/engine/api/dfile.h
@@ -1,10 +1,11 @@
/**
* @file dfile.h
* Unique file reference in the engine's virtual file system.
* Reference/handle to a unique file in the engine's virtual file system.
*
* @ingroup fs
*
* @author Copyright &copy; 2012 Daniel Swanson <danij@dengine.net>
* @author Copyright &copy; 2003-2012 Jaakko Keränen <jaakko.keranen@iki.fi>
* @author Copyright &copy; 2005-2012 Daniel Swanson <danij@dengine.net>
*
* @par License
* GPL: http://www.gnu.org/licenses/gpl.html
Expand All @@ -30,69 +31,137 @@
extern "C" {
#endif

/// @addtogroup fs
///@{
/// Seek methods
typedef enum {
SeekSet = 0,
SeekCur = 1,
SeekEnd = 2
} SeekMethod;

struct dfile_s; // The file handle instance (opaque).
#ifdef __cplusplus
} // extern "C"
#endif

/**
* DFile instance.
*/
typedef struct dfile_s DFile;
#ifdef __cplusplus

struct filelist_s;

namespace de {

class AbstractFile;
class DFileBuilder;

/**
* Close the file if open. Note that this clears any previously buffered data.
* Reference/handle to a unique file in the engine's virtual file system.
*/
void DFile_Close(DFile* file);
class DFile
{
public:
~DFile();

/// @return @c true iff this handle's internal state is valid.
boolean DFile_IsValid(DFile const* file);
/**
* Close the file if open. Note that this clears any previously buffered data.
*/
DFile& close();

/// @return The length of the file, in bytes.
size_t DFile_Length(DFile* file);
struct filelist_s* list();

/// @return Offset in bytes from the start of the file to begin read.
size_t DFile_BaseOffset(DFile const* file);
DFile& setList(struct filelist_s* list);

/**
* @return Number of bytes read (at most @a count bytes will be read).
*/
size_t DFile_Read(DFile* file, uint8_t* buffer, size_t count);
AbstractFile* file();
AbstractFile* file() const;

/**
* Read a character from the stream, advancing the read position in the process.
*/
unsigned char DFile_GetC(DFile* file);
/// @return @c true iff this handle's internal state is valid.
bool isValid() const;

/**
* @return @c true iff the stream has reached the end of the file.
*/
boolean DFile_AtEnd(DFile* file);
/// @return The length of the file, in bytes.
size_t length();

/**
* @return Current position in the stream as an offset from the beginning of the file.
*/
size_t DFile_Tell(DFile* file);
/// @return Offset in bytes from the start of the file to begin read.
size_t baseOffset() const;

/**
* @return The current position in the file, before the move, as an
* offset from the beginning of the file.
*/
size_t DFile_Seek(DFile* file, size_t offset, int whence);
/**
* @return Number of bytes read (at most @a count bytes will be read).
*/
size_t read(uint8_t* buffer, size_t count);

/**
* Read a character from the stream, advancing the read position in the process.
*/
unsigned char getC();

/**
* @return @c true iff the stream has reached the end of the file.
*/
bool atEnd();

/**
* @return Current position in the stream as an offset from the beginning of the file.
*/
size_t tell();

/**
* @return The current position in the file, before the move, as an
* offset from the beginning of the file.
*/
size_t seek(size_t offset, SeekMethod whence);

/**
* Rewind the stream to the start of the file.
*/
DFile& rewind();

#if _DEBUG
static void debugPrint(DFile const& hndl);
#endif

friend class DFileBuilder;

private:
DFile();

struct Instance;
Instance* d;
};

} // namespace de

extern "C" {
#endif // __cplusplus

/**
* Rewind the stream to the start of the file.
* C wrapper API:
*/
void DFile_Rewind(DFile* file);

struct dfile_s; // The texture instance (opaque).
typedef struct dfile_s DFile;

void DFile_Close(DFile* hndl);

boolean DFile_IsValid(DFile const* hndl);

size_t DFile_Length(DFile* hndl);

size_t DFile_BaseOffset(DFile const* hndl);

size_t DFile_Read(DFile* hndl, uint8_t* buffer, size_t count);

unsigned char DFile_GetC(DFile* hndl);

boolean DFile_AtEnd(DFile* hndl);

size_t DFile_Tell(DFile* hndl);

size_t DFile_Seek(DFile* hndl, size_t offset, SeekMethod whence);

void DFile_Rewind(DFile* hndl);

#if _DEBUG
void DFile_Print(DFile const* file);
void DFile_DebugPrint(DFile const* file);
#endif

#ifdef __cplusplus
} // extern "C"
#endif

///@}

#endif /* LIBDENG_FILESYS_FILEHANDLE_H */
34 changes: 17 additions & 17 deletions doomsday/engine/portable/include/dfilebuilder.h
Expand Up @@ -27,67 +27,67 @@

#ifdef __cplusplus

namespace de {

class DFileBuilder
{
public:
static void init();
static void shutdown();

/**
* Create a new handle on the AbstractFile @a af.
* Create a new handle on the AbstractFile @a file.
*
* @param af VFS object representing the file being opened.
*/
static DFile* fromAbstractFile(AbstractFile& af);
static DFile* fromAbstractFile(AbstractFile& file);

/**
* Create a new handle on a lump of AbstractFile @a af.
* Create a new handle on a lump of AbstractFile @a file.
*
* @param af VFS object representing the container of the lump to be opened.
* @param lumpIdx Logical index of the lump within @a af to be opened.
* @param lumpIdx Logical index of the lump within @a file to be opened.
* @param dontBuffer @c true= do not buffer a copy of the lump.
*/
static DFile* fromAbstractFileLump(AbstractFile& af, int lumpIdx, bool dontBuffer);
static DFile* fromAbstractFileLump(AbstractFile& file, int lumpIdx, bool dontBuffer);

/**
* Open a new handle on the specified system file.
* Open a new handle on the specified native file.
*
* @param file File system handle to the file being opened.
* @param nativeFile Native file system handle to the file being opened.
* @param baseOffset Offset from the start of the file in bytes to begin.
*/
static DFile* fromFile(FILE& file, size_t baseOffset);
static DFile* fromFile(FILE& nativeFile, size_t baseOffset);

/**
* Create a duplicate of handle @a hndl. Note that the duplicate is in
* fact a "reference" to the original, so all changes to the file which they
* represent are implicitly shared.
*
* @param hndl DFile handle to be duplicated.
* @param hndl Handle to be duplicated.
*/
static DFile* dup(DFile const& hndl);
};

} // namespace de

extern "C" {
#endif

/**
* Non-public methods of DFile. Placed here temporarily.
*/

DFile* DFile_New(void);

void DFile_Delete(DFile* file, boolean recycle);

/// @return File object represented by this handle.
AbstractFile* DFile_File(DFile* file);
AbstractFile* DFile_File(DFile* hndl);

/// @return FileList object which owns this handle.
FileList* DFile_List(DFile* file);
struct filelist_s* DFile_List(DFile* hndl);

DFile* DFile_SetList(DFile* file, FileList* list);
DFile* DFile_SetList(DFile* hndl, struct filelist_s* list);

/// @return File object represented by this handle.
AbstractFile* DFile_File_const(DFile const* file);
AbstractFile* DFile_File_const(DFile const* hndl);

#ifdef __cplusplus
} // extern "C"
Expand Down
2 changes: 1 addition & 1 deletion doomsday/engine/portable/include/fs_main.h
Expand Up @@ -52,7 +52,7 @@

#ifdef __cplusplus
#include <QList>
typedef QList<DFile*> FileList;
typedef QList<de::DFile*> FileList;
#else // __cplusplus
struct filelist_s;
typedef struct filelist_s FileList;
Expand Down
2 changes: 1 addition & 1 deletion doomsday/engine/portable/include/zipfile.h
Expand Up @@ -52,7 +52,7 @@ class PathDirectoryNode;
/**
* ZipFile. Runtime representation of an opened ZIP file.
*/
class ZipFile : AbstractFile
class ZipFile : public AbstractFile
{
public:
ZipFile(DFile& file, char const* path, LumpInfo const& info);
Expand Down
10 changes: 5 additions & 5 deletions doomsday/engine/portable/src/abstractfile.cpp
Expand Up @@ -46,7 +46,7 @@ de::AbstractFile::~AbstractFile()
{
Str_Free(&path_);
F_DestroyLumpInfo(&info_);
if(file) DFile_Delete(file, true);
if(file) delete file;
}

filetype_t de::AbstractFile::type() const
Expand All @@ -66,10 +66,10 @@ de::AbstractFile* de::AbstractFile::container() const

size_t de::AbstractFile::baseOffset() const
{
return (file? DFile_BaseOffset(file) : 0);
return (file? file->baseOffset() : 0);
}

DFile* de::AbstractFile::handle()
de::DFile* de::AbstractFile::handle()
{
return file;
}
Expand Down Expand Up @@ -154,7 +154,7 @@ size_t AbstractFile_BaseOffset(AbstractFile const* af)
DFile* AbstractFile_Handle(AbstractFile* af)
{
SELF(af);
return self->handle();
return reinterpret_cast<DFile*>(self->handle());
}

ddstring_t const* AbstractFile_Path(AbstractFile const* af)
Expand Down Expand Up @@ -202,7 +202,7 @@ void AbstractFile_SetCustom(AbstractFile* af, boolean yes)
AbstractFile* UnknownFile_New(DFile* file, char const* path, LumpInfo const* info)
{
DENG2_ASSERT(file && info);
de::AbstractFile* af = new de::AbstractFile(FT_UNKNOWNFILE, path, *file, *info);
de::AbstractFile* af = new de::AbstractFile(FT_UNKNOWNFILE, path, *reinterpret_cast<de::DFile*>(file), *info);
if(!af) LegacyCore_FatalError("UnknownFile_New: Failed to instantiate new AbstractFile.");
return reinterpret_cast<AbstractFile*>(af);
}
Expand Down
2 changes: 1 addition & 1 deletion doomsday/engine/portable/src/def_read.c
Expand Up @@ -2710,7 +2710,7 @@ int DED_Read(ded_t* ded, const char* path)
}

// We will buffer a local copy of the file. How large a buffer do we need?
DFile_Seek(file, 0, SEEK_END);
DFile_Seek(file, 0, SeekEnd);
bufferedDefSize = DFile_Tell(file);
DFile_Rewind(file);
bufferedDef = (char*) calloc(1, bufferedDefSize + 1);
Expand Down

0 comments on commit 0f59ae6

Please sign in to comment.