raze/source/common/filesystem/resourcefile.h
2019-10-31 18:06:05 +01:00

199 lines
5 KiB
C++

#ifndef __RESFILE_H
#define __RESFILE_H
#include <stdint.h>
#include "files.h"
#include "zstring.h"
#include "name.h"
class FResourceFile;
class FTexture;
enum ELumpFlags
{
LUMPF_ZIPFILE=1, // contains a full path
LUMPF_BLOODCRYPT = 2, // encrypted
LUMPF_COMPRESSED = 4, // compressed
LUMPF_SEQUENTIAL = 8, // compressed but a sequential reader can be retrieved.
};
class FResourceFile;
// 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;
bool Decompress(char *destbuffer);
void Clean()
{
mSize = mCompressedSize = 0;
if (mBuffer != nullptr)
{
delete[] mBuffer;
mBuffer = nullptr;
}
}
};
struct FResourceLump
{
enum ENameType
{
FullNameType,
FullNameNoExtType,
BaseNameType,
BaseNameNoExtType,
ExtensionType,
NUMNAMETYPES
};
friend class FResourceFile;
friend struct FClonedLump;
unsigned LumpSize = 0;
int RefCount = 0;
int Flags = 0;
int ResourceId = -1;
FName LumpName[NUMNAMETYPES] = {};
FResourceFile * Owner = nullptr;
TArray<uint8_t> Cache;
FResourceLump() = default;
virtual ~FResourceLump();
virtual FileReader *GetReader();
virtual FileReader NewReader();
virtual int GetFileOffset() { return -1; }
void LumpNameSetup(FString iname);
virtual FCompressedBuffer GetRawData();
virtual void *Lock(); // validates the cache and increases the refcount.
virtual void Unlock(bool freeunrefd = false); // recreases the refcount and optionally frees the buffer
virtual void *Get(); // validates the cache and returns a pointer without locking
// Wrappers for emulating Blood's resource system
unsigned Size() const{ return LumpSize; }
int LockCount() const { return RefCount; }
const char *ResName() const { return LumpName[BaseNameNoExtType]; }
const char *ResType() { return LumpName[ExtensionType]; }
const char *FullName() const { return LumpName[FullNameType]; }
protected:
virtual int ValidateCache() { return -1; }
};
// Map NBlood's resource system to our own.
using DICTNODE = FResourceLump;
class FResourceFile
{
public:
FileReader Reader;
FString FileName;
protected:
uint32_t NumLumps;
FResourceFile(const char *filename);
FResourceFile(const char *filename, FileReader &r);
// for archives that can contain directories
void PostProcessArchive(void *lumps, size_t lumpsize);
private:
uint32_t FirstLump;
int FilterLumps(FString filtername, void *lumps, size_t lumpsize, uint32_t max);
bool FindPrefixRange(FString 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 quiet, bool containeronly);
public:
static FResourceFile *OpenResourceFile(const char *filename, FileReader &file, bool quiet = false, bool containeronly = false);
static FResourceFile *OpenResourceFile(const char *filename, bool quiet = false, bool containeronly = false);
static FResourceFile *OpenDirectory(const char *filename, bool quiet = false);
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; }
uint32_t GetFirstLump() const { return FirstLump; }
void SetFirstLump(uint32_t f) { FirstLump = f; }
virtual bool Open(bool quiet) = 0;
virtual FResourceLump *GetLump(int no) = 0;
FResourceLump *FindLump(const char *name);
};
struct FUncompressedLump : public FResourceLump
{
int Position;
virtual FileReader *GetReader();
int ValidateCache() override;
virtual int GetFileOffset() { return Position; }
};
// Base class for uncompressed resource files (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
{
FString Filename;
FExternalLump(const char *_filename, int filesize = -1);
virtual int ValidateCache() override;
};
struct FMemoryLump : public FResourceLump
{
FMemoryLump(const void* data, int length)
{
Cache.Resize(length);
memcpy(Cache.Data(), data, length);
}
virtual int ValidateCache() 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;
}
};
struct FClonedLump : public FResourceLump
{
FResourceLump* parent;
FClonedLump(FResourceLump* lump)
{
parent = lump;
}
void* Lock() { return parent->Lock(); }
void Unlock(bool mayfree) override { parent->Unlock(mayfree); }
void* Get() { return parent->Get(); }
int ValidateCache() override { return parent->ValidateCache(); }
};
#endif