2019-10-28 23:15:36 +00:00
# pragma once
//-----------------------------------------------------------------------------
//
// DESCRIPTION:
// File system I/O functions.
//
//-----------------------------------------------------------------------------
# include <stdexcept>
# include "files.h"
# include "tarray.h"
2019-11-02 00:30:21 +00:00
# include "name.h"
2019-10-28 23:15:36 +00:00
# include "zstring.h"
2019-10-31 17:06:05 +00:00
# ifdef FindResource
# undef FindResource
# endif
2019-10-28 23:15:36 +00:00
// We do not want to expose the resource file interface here.
class FResourceFile ;
struct FResourceLump ;
class FileSystemError : std : : runtime_error
{
public :
FileSystemError ( const char * err ) : std : : runtime_error ( err ) { }
} ;
// A file in memory.
class FileData
{
public :
FileData ( ) ;
FileData ( const FileData & copy ) ;
FileData & operator = ( const FileData & copy ) ;
~ FileData ( ) ;
void * GetMem ( ) { return Block . Len ( ) = = 0 ? NULL : ( void * ) Block . GetChars ( ) ; }
size_t GetSize ( ) { return Block . Len ( ) ; }
FString GetString ( ) { return Block ; }
private :
FileData ( const FString & source ) ;
FString Block ;
friend class FileSystem ;
} ;
struct FolderEntry
{
const char * name ;
unsigned lumpnum ;
} ;
2019-10-31 16:13:48 +00:00
enum DICTFLAGS {
DICT_LOAD = 4 ,
DICT_LOCK = 8 ,
} ;
2019-10-31 00:48:10 +00:00
enum class ELookupMode // Todo: Merge with FResourceLump::ENameType
2019-10-28 23:15:36 +00:00
{
2019-10-31 00:48:10 +00:00
FullName ,
NoExtension ,
BaseName ,
BaseWithExtension ,
IdWithType ,
NumLookupModes
2019-10-28 23:15:36 +00:00
} ;
2019-10-31 00:48:10 +00:00
enum
{
NumLookupModes = ( int ) ELookupMode : : NumLookupModes + 1
} ;
2019-10-28 23:15:36 +00:00
class FileSystem
{
public :
FileSystem ( ) = default ;
~ FileSystem ( ) ;
int InitMultipleFiles ( TArray < FString > & filenames , const TArray < FString > & todelete ) ;
2019-11-02 18:12:01 +00:00
void AddFile ( const char * filename , FileReader * wadinfo = NULL , bool nosubdirflag = false ) ;
2019-11-01 08:30:28 +00:00
void AddAdditionalFile ( const char * filename , FileReader * wadinfo = NULL ) { }
2019-10-28 23:15:36 +00:00
int CheckIfResourceFileLoaded ( const char * name ) noexcept ;
const char * GetResourceFileName ( int filenum ) const noexcept ;
const char * GetResourceFileFullName ( int filenum ) const noexcept ;
int GetFirstEntry ( int filenum ) const noexcept ;
int GetLastEntry ( int filenum ) const noexcept ;
int GetEntryCount ( int filenum ) const noexcept ;
int FindFile ( const char * name , ELookupMode lookupmode = ELookupMode : : FullName , int filenum = - 1 ) const noexcept ;
int GetFile ( const char * name , ELookupMode lookupmode = ELookupMode : : FullName , int filenum = - 1 ) const ; // Like FindFile, but throws an exception when it cannot find what it looks for.
2019-12-07 09:31:27 +00:00
bool FileExists ( const char * name )
{
return FindFile ( name ) > = 0 ;
}
2019-10-28 23:15:36 +00:00
int FindFile ( const FString & name , ELookupMode lookupmode = ELookupMode : : FullName , int filenum = - 1 ) const noexcept { return FindFile ( name . GetChars ( ) , lookupmode , filenum ) ; }
int GetFile ( const FString & name , ELookupMode lookupmode = ELookupMode : : FullName , int filenum = - 1 ) const { return GetFile ( name . GetChars ( ) , lookupmode , filenum ) ; }
2019-12-07 09:31:27 +00:00
bool FileExists ( const FString & name )
{
return FindFile ( name ) > = 0 ;
}
2019-10-28 23:15:36 +00:00
int FindFile ( const std : : string & name , ELookupMode lookupmode = ELookupMode : : FullName , int filenum = - 1 ) const noexcept { return FindFile ( name . c_str ( ) , lookupmode , filenum ) ; }
int GetFile ( const std : : string & name , ELookupMode lookupmode = ELookupMode : : FullName , int filenum = - 1 ) const { return GetFile ( name . c_str ( ) , lookupmode , filenum ) ; }
2019-12-07 09:31:27 +00:00
bool FileExists ( const std : : string & name )
{
return FindFile ( name ) > = 0 ;
}
2019-10-28 23:15:36 +00:00
2019-10-31 00:48:10 +00:00
int FindResource ( int resid , const char * type , int filenum = - 1 ) const noexcept ;
int GetResource ( int resid , const char * type , int filenum = - 1 ) const ; // Like FindFile, but throws an exception when it cannot find what it looks for.
2019-10-31 16:13:48 +00:00
void AddFromBuffer ( const char * name , const char * type , char * data , int size , int id , int flags ) ;
2019-10-31 00:48:10 +00:00
2019-11-02 00:30:21 +00:00
TArray < FString > GetAllFilesOfType ( FName type , bool withsubdirs = false ) ;
2019-10-28 23:15:36 +00:00
TArray < uint8_t > GetFileData ( int file , int pad = 0 ) ; // reads file into a writable buffer and optionally adds some padding at the end. (FileData isn't writable!)
FileData ReadFile ( int file ) ;
FileData ReadFile ( const char * name ) { return ReadFile ( GetFile ( name ) ) ; }
2019-12-07 09:31:27 +00:00
inline TArray < uint8_t > LoadFile ( const char * name , int padding )
{
auto lump = FindFile ( name ) ;
if ( lump < 0 ) return TArray < uint8_t > ( ) ;
return GetFileData ( lump , padding ) ;
}
2019-10-31 00:48:10 +00:00
const void * Lock ( int lump ) ;
2019-10-31 17:06:05 +00:00
void Unlock ( int lump , bool mayfree = false ) ;
const void * Get ( int lump ) ;
2019-10-31 16:13:48 +00:00
// These are designed to be stand-ins for Blood's resource class.
2019-10-31 17:06:05 +00:00
static const void * Lock ( FResourceLump * lump ) ;
2019-10-31 16:13:48 +00:00
static void Unlock ( FResourceLump * lump ) ;
2019-10-31 17:06:05 +00:00
static const void * Load ( FResourceLump * lump ) ;
2019-10-31 16:13:48 +00:00
FResourceLump * Lookup ( const char * name , const char * type ) ;
FResourceLump * Lookup ( unsigned int id , const char * type ) ;
2019-11-02 09:20:32 +00:00
bool CreatePathlessCopy ( const char * name , int id , int flags ) ;
2019-10-28 23:15:36 +00:00
FileReader OpenFileReader ( int file ) ; // opens a reader that redirects to the containing file's one.
FileReader ReopenFileReader ( int file , bool alwayscache = false ) ; // opens an independent reader.
2019-12-07 09:14:51 +00:00
FileReader OpenFileReader ( const char * name , int where ) ;
2019-10-28 23:15:36 +00:00
int Iterate ( const char * name , int * lastfile , ELookupMode lookupmode = ELookupMode : : FullName ) ; // [RH] Find files with duplication
int FileLength ( int file ) const ;
int GetFileOffset ( int file ) ; // [RH] Returns offset of file in the wadfile
int GetFileFlags ( int file ) ; // Return the flags for this file
const char * GetFileName ( int file ) const ;
FString GetFileFullPath ( int file ) const ; // [RH] Returns wad's name + file's full name
int GetFileContainer ( int file ) const ; // [RH] Returns filenum for a specified file
int GetRFFIndexNum ( int file ) const ; // Returns the RFF index number for this file
unsigned GetFilesInFolder ( const char * path , TArray < FolderEntry > & result , bool atomic ) const ;
bool IsEncryptedFile ( int file ) const noexcept ;
2019-10-31 00:48:10 +00:00
int GetResourceId ( int file ) const ;
2019-10-28 23:15:36 +00:00
int GetNumResourceFiles ( ) const { return NumFiles ; }
int GetNumEntries ( ) const { return NumEntries ; }
2019-10-31 19:17:49 +00:00
FResourceLump * GetFileAt ( int lump ) const
{
return FileInfo [ lump ] . lump ;
}
2019-12-07 08:44:43 +00:00
void PrintDirectory ( ) ;
2019-10-28 23:15:36 +00:00
protected :
2019-10-31 19:17:49 +00:00
struct FileRecord
{
int rfnum ;
FResourceLump * lump ;
} ;
2019-10-28 23:15:36 +00:00
TArray < FResourceFile * > Files ;
TArray < FileRecord > FileInfo ;
TArray < uint32_t > Hashes ; // one allocation for all hash lists.
2019-10-31 00:48:10 +00:00
uint32_t * FirstFileIndex [ NumLookupModes ] ; // Hash information for the base name (no path and no extension)
uint32_t * NextFileIndex [ NumLookupModes ] ;
2019-10-28 23:15:36 +00:00
uint32_t NumFiles = 0 ; // Not necessarily the same as FileInfo.Size()
2019-10-31 16:13:48 +00:00
uint32_t NumEntries ; // Hash modulus. Can be smaller than NumFiles if things get added at run time.
2019-10-28 23:15:36 +00:00
void InitHashChains ( ) ; // [RH] Set up the lumpinfo hashing
2019-10-31 17:06:05 +00:00
void AddLump ( FResourceLump * lump ) ;
2019-10-28 23:15:36 +00:00
private :
void DeleteAll ( ) ;
} ;
2019-10-31 19:17:49 +00:00
extern FileSystem fileSystem ;
2019-10-28 23:15:36 +00:00