raze/source/common/filesystem/resourcefile.h

248 lines
6.9 KiB
C
Raw Normal View History

#ifndef __RESFILE_H
#define __RESFILE_H
#include <limits.h>
#include <vector>
#include <string>
#include "files.h"
2020-04-11 21:54:33 +00:00
std::string ExtractBaseName(const char* path, bool include_extension = false);
void strReplace(std::string& str, const char* from, const char* to);
// user context in which the file system gets opened. This also contains a few callbacks to avoid direct dependencies on the engine.
2020-04-11 21:54:33 +00:00
struct LumpFilterInfo
{
std::vector<std::string> gameTypeFilter; // this can contain multiple entries
std::string dotFilter;
2020-04-11 21:54:33 +00:00
// The following are for checking if the root directory of a zip can be removed.
std::vector<std::string> reservedFolders;
std::vector<std::string> requiredPrefixes;
std::vector<std::string> embeddings;
std::vector<std::string> blockednames; // File names that will never be accepted (e.g. dehacked.exe for Doom)
std::function<bool(const char*, const char*)> filenamecheck; // for scanning directories, this allows to eliminate unwanted content.
2020-04-11 21:54:33 +00:00
std::function<void()> postprocessFunc;
};
enum class FSMessageLevel
{
Error = 1,
Warning = 2,
Attention = 3,
Message = 4,
DebugWarn = 5,
DebugNotify = 6,
};
// pass the text output function as parameter to avoid a hard dependency on higher level code.
using FileSystemMessageFunc = int(*)(FSMessageLevel msglevel, const char* format, ...);
class FResourceFile;
2020-04-11 21:54:33 +00:00
// [RH] Namespaces from BOOM.
// These are needed here in the low level part so that WAD files can be properly set up.
2020-04-11 21:52:02 +00:00
typedef enum {
ns_hidden = -1,
ns_global = 0,
ns_sprites,
ns_flats,
ns_colormaps,
ns_acslibrary,
ns_newtextures,
2020-04-11 21:54:33 +00:00
ns_bloodraw, // no longer used - kept for ZScript.
ns_bloodsfx, // no longer used - kept for ZScript.
ns_bloodmisc, // no longer used - kept for ZScript.
2020-04-11 21:52:02 +00:00
ns_strifevoices,
ns_hires,
ns_voxels,
// These namespaces are only used to mark lumps in special subdirectories
// so that their contents doesn't interfere with the global namespace.
// searching for data in these namespaces works differently for lumps coming
// from Zips or other files.
ns_specialzipdirectory,
ns_sounds,
ns_patches,
ns_graphics,
ns_music,
ns_firstskin,
} namespace_t;
enum ELumpFlags
{
2020-04-11 21:54:33 +00:00
LUMPF_MAYBEFLAT = 1, // might be a flat outside F_START/END
LUMPF_FULLPATH = 2, // contains a full path. This will trigger extended namespace checks when looking up short names.
LUMPF_EMBEDDED = 4, // marks an embedded resource file for later processing.
LUMPF_SHORTNAME = 8, // the stored name is a short extension-less name
LUMPF_COMPRESSED = 16, // compressed or encrypted, i.e. cannot be read with the container file's reader.
2020-04-11 21:52:02 +00:00
};
2020-04-11 21:54:33 +00:00
// This holds a compresed Zip entry with all needed info to decompress it.
struct FCompressedBuffer
{
unsigned mSize;
unsigned mCompressedSize;
int mMethod;
int mZipFlags;
unsigned mCRC32;
char *mBuffer;
const char* filename;
bool Decompress(char *destbuffer);
void Clean()
{
mSize = mCompressedSize = 0;
if (mBuffer != nullptr)
{
delete[] mBuffer;
mBuffer = nullptr;
}
}
};
struct FResourceLump
{
friend class FResourceFile;
2020-04-11 21:54:33 +00:00
friend class FWadFile; // this still needs direct access.
2020-04-11 21:54:33 +00:00
int LumpSize;
int RefCount;
protected:
std::string FullName;
2020-04-11 21:54:33 +00:00
public:
uint8_t Flags;
char * Cache;
FResourceFile * Owner;
2020-04-11 21:54:33 +00:00
FResourceLump()
{
Cache = NULL;
Owner = NULL;
Flags = 0;
RefCount = 0;
}
virtual ~FResourceLump();
virtual FileReader *GetReader();
virtual FileReader NewReader();
virtual int GetFileOffset() { return -1; }
2020-04-11 21:54:33 +00:00
virtual int GetIndexNum() const { return -1; }
virtual int GetNamespace() const { return 0; }
void LumpNameSetup(const char* iname);
void CheckEmbedded(LumpFilterInfo* lfi);
virtual FCompressedBuffer GetRawData();
2020-04-11 21:54:33 +00:00
void *Lock(); // validates the cache and increases the refcount.
int Unlock(); // decreases the refcount and frees the buffer
unsigned Size() const{ return LumpSize; }
int LockCount() const { return RefCount; }
const char* getName() { return FullName.c_str(); }
protected:
2020-04-11 21:54:33 +00:00
virtual int FillCache() { return -1; }
};
class FResourceFile
{
public:
FileReader Reader;
std::string FileName;
protected:
uint32_t NumLumps;
char Hash[48];
FResourceFile(const char *filename);
FResourceFile(const char *filename, FileReader &r);
// for archives that can contain directories
2020-04-11 21:54:33 +00:00
void GenerateHash();
void PostProcessArchive(void *lumps, size_t lumpsize, LumpFilterInfo *filter);
private:
uint32_t FirstLump;
int FilterLumps(const std::string& filtername, void *lumps, size_t lumpsize, uint32_t max);
2020-04-11 21:54:33 +00:00
int FilterLumpsByGameType(LumpFilterInfo *filter, void *lumps, size_t lumpsize, uint32_t max);
bool FindPrefixRange(const char* filter, void *lumps, size_t lumpsize, uint32_t max, uint32_t &start, uint32_t &end);
void JunkLeftoverFilters(void *lumps, size_t lumpsize, uint32_t max);
static FResourceFile *DoOpenResourceFile(const char *filename, FileReader &file, bool containeronly, LumpFilterInfo* filter, FileSystemMessageFunc Printf);
public:
static FResourceFile *OpenResourceFile(const char *filename, FileReader &file, bool containeronly = false, LumpFilterInfo* filter = nullptr, FileSystemMessageFunc Printf = nullptr);
static FResourceFile *OpenResourceFile(const char *filename, bool containeronly = false, LumpFilterInfo* filter = nullptr, FileSystemMessageFunc Printf = nullptr);
static FResourceFile *OpenDirectory(const char *filename, LumpFilterInfo* filter = nullptr, FileSystemMessageFunc Printf = nullptr);
virtual ~FResourceFile();
// If this FResourceFile represents a directory, the Reader object is not usable so don't return it.
FileReader *GetReader() { return Reader.isOpen()? &Reader : nullptr; }
uint32_t LumpCount() const { return NumLumps; }
2020-04-11 21:54:33 +00:00
uint32_t GetFirstEntry() const { return FirstLump; }
void SetFirstLump(uint32_t f) { FirstLump = f; }
const char* GetHash() const { return Hash; }
virtual FResourceLump *GetLump(int no) = 0;
FResourceLump *FindLump(const char *name);
};
struct FUncompressedLump : public FResourceLump
{
int Position;
2020-04-11 21:54:33 +00:00
virtual FileReader *GetReader();
virtual int FillCache() override;
2020-04-11 21:54:33 +00:00
virtual int GetFileOffset() { return Position; }
};
2020-04-11 21:54:33 +00:00
// Base class for uncompressed resource files (WAD, GRP, PAK and single lumps)
class FUncompressedFile : public FResourceFile
{
protected:
TArray<FUncompressedLump> Lumps;
FUncompressedFile(const char *filename);
FUncompressedFile(const char *filename, FileReader &r);
virtual FResourceLump *GetLump(int no) { return ((unsigned)no < NumLumps)? &Lumps[no] : NULL; }
};
struct FExternalLump : public FResourceLump
{
std::string Filename;
FExternalLump(const char *_filename, int filesize = -1);
virtual int FillCache() override;
};
struct FMemoryLump : public FResourceLump
{
FMemoryLump(const void* data, int length)
{
2020-04-11 21:54:33 +00:00
RefCount = INT_MAX / 2;
LumpSize = length;
2020-04-11 21:54:33 +00:00
Cache = new char[length];
memcpy(Cache, data, length);
}
2020-04-11 21:54:33 +00:00
virtual int FillCache() override
{
RefCount = INT_MAX / 2; // Make sure it never counts down to 0 by resetting it to something high each time it is used.
return 1;
}
};
2020-04-11 21:54:33 +00:00
#endif