You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
277 lines
8.8 KiB
277 lines
8.8 KiB
//========= Copyright Valve Corporation, All rights reserved. ============//
|
|
//
|
|
// Purpose:
|
|
//
|
|
// $NoKeywords: $
|
|
//===========================================================================//
|
|
|
|
#ifndef PACKFILE_H
|
|
#define PACKFILE_H
|
|
|
|
#ifdef _WIN32
|
|
#pragma once
|
|
#endif
|
|
|
|
// How many bytes compressed filehandles should hold for seeking backwards. Seeks beyond this limit will require
|
|
// rewinding and restarting the compression, at significant performance penalty. (Warnings emitted when this occurs)
|
|
#define PACKFILE_COMPRESSED_FILEHANDLE_SEEK_BUFFER 4096
|
|
|
|
// How many bytes compressed filehandles should attempt to read (and cache) at a time from the underlying compressed data.
|
|
#define PACKFILE_COMPRESSED_FILEHANDLE_READ_BUFFER 4096
|
|
|
|
// Emit warnings in debug builds if we hold more than this many compressed file handles alive to alert to the poor
|
|
// memory characteristics.
|
|
#define PACKFILE_COMPRESSED_FILE_HANDLES_WARNING 20
|
|
|
|
#include "basefilesystem.h"
|
|
#include "tier1/refcount.h"
|
|
#include "tier1/utlbuffer.h"
|
|
#include "tier1/lzmaDecoder.h"
|
|
|
|
class CPackFile;
|
|
class CZipPackFile;
|
|
|
|
// A pack file handle - essentially represents a file inside the pack file.
|
|
class CPackFileHandle
|
|
{
|
|
public:
|
|
virtual ~CPackFileHandle() {};
|
|
|
|
virtual int Read( void* pBuffer, int nDestSize, int nBytes ) = 0;
|
|
virtual int Seek( int nOffset, int nWhence ) = 0;
|
|
virtual int Tell() = 0;
|
|
virtual int Size() = 0;
|
|
|
|
virtual void SetBufferSize( int nBytes ) = 0;
|
|
virtual int GetSectorSize() = 0;
|
|
virtual int64 AbsoluteBaseOffset() = 0;
|
|
};
|
|
|
|
class CZipPackFileHandle : public CPackFileHandle
|
|
{
|
|
public:
|
|
CZipPackFileHandle( CZipPackFile* pOwner, int64 nBase, unsigned int nLength, unsigned int nIndex = -1, unsigned int nFilePointer = 0 );
|
|
virtual ~CZipPackFileHandle();
|
|
|
|
virtual int Read( void* pBuffer, int nDestSize, int nBytes ) OVERRIDE;
|
|
virtual int Seek( int nOffset, int nWhence ) OVERRIDE;
|
|
|
|
virtual int Tell() OVERRIDE { return m_nFilePointer; };
|
|
virtual int Size() OVERRIDE { return m_nLength; };
|
|
|
|
virtual void SetBufferSize( int nBytes ) OVERRIDE;
|
|
virtual int GetSectorSize() OVERRIDE;
|
|
virtual int64 AbsoluteBaseOffset() OVERRIDE;
|
|
|
|
protected:
|
|
int64 m_nBase; // Base offset of the file inside the pack file.
|
|
unsigned int m_nFilePointer; // Current seek pointer (0 based from the beginning of the file).
|
|
CZipPackFile* m_pOwner; // Pack file that owns this handle
|
|
unsigned int m_nLength; // Length of this file.
|
|
unsigned int m_nIndex; // Index into the pack's directory table
|
|
};
|
|
|
|
class CLZMAZipPackFileHandle : public CZipPackFileHandle
|
|
{
|
|
public:
|
|
CLZMAZipPackFileHandle( CZipPackFile* pOwner, int64 nBase, unsigned int nOriginalSize, unsigned int nCompressedSize,
|
|
unsigned int nIndex = -1, unsigned int nFilePointer = 0 );
|
|
~CLZMAZipPackFileHandle();
|
|
|
|
virtual int Read( void* pBuffer, int nDestSize, int nBytes ) OVERRIDE;
|
|
virtual int Seek( int nOffset, int nWhence ) OVERRIDE;
|
|
|
|
virtual int Tell() OVERRIDE;
|
|
virtual int Size() OVERRIDE;
|
|
|
|
private:
|
|
// Ensure there are bytes in the read buffer, assuming we're not at the end of the underlying data
|
|
int FillReadBuffer();
|
|
|
|
// Reset buffers and underlying seek position to 0
|
|
void Reset();
|
|
|
|
// Contains the last PACKFILE_COMPRESSED_FILEHANDLE_SEEK_BUFFER decompressed bytes. The Put and Get locations mimic our
|
|
// filehandle -- TellPut() == TelGet() when we are not back seeking.
|
|
CUtlBuffer m_BackSeekBuffer;
|
|
|
|
// The read buffer from the underlying compressed stream. We read PACKFILE_COMPRESSED_FILEHANDLE_READ_BUFFER bytes
|
|
// into this buffer, then consume it via the buffer get position.
|
|
CUtlBuffer m_ReadBuffer;
|
|
|
|
// The decompress stream we feed our base filehandle into
|
|
CLZMAStream *m_pLZMAStream;
|
|
|
|
// Current seek position in uncompressed data
|
|
int m_nSeekPosition;
|
|
|
|
// Size of the decompressed data
|
|
unsigned int m_nOriginalSize;
|
|
};
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// An abstract pack file
|
|
class CPackFile : public CRefCounted<CRefCountServiceMT>
|
|
{
|
|
public:
|
|
CPackFile();
|
|
virtual ~CPackFile();
|
|
|
|
// The means by which you open files:
|
|
virtual CFileHandle *OpenFile( const char *pFileName, const char *pOptions = "rb" ) = 0;
|
|
|
|
// Check for existance in pack
|
|
virtual bool ContainsFile( const char *pFileName ) = 0;
|
|
|
|
// The two functions a pack file must provide
|
|
virtual bool Prepare( int64 fileLen = -1, int64 nFileOfs = 0 ) = 0;
|
|
|
|
// Returns the filename for a given file in the pack. Returns true if a filename is found, otherwise buffer is filled with "unknown"
|
|
virtual bool IndexToFilename( int nIndex, char* buffer, int nBufferSize ) = 0;
|
|
|
|
inline int GetSectorSize();
|
|
|
|
virtual void SetupPreloadData() {}
|
|
virtual void DiscardPreloadData() {}
|
|
virtual int64 GetPackFileBaseOffset() = 0;
|
|
|
|
CBaseFileSystem *FileSystem() { return m_fs; }
|
|
|
|
// Helper for the filesystem's FindFirst/FindNext() API which mimics the old windows equivalent. pWildcard is the
|
|
// same pattern that you would pass to FindFirst, not a true wildcard.
|
|
// Mirrors the VPK code's similar call.
|
|
virtual void GetFileAndDirLists( const char *pFindWildCard, CUtlStringList &outDirnames, CUtlStringList &outFilenames, bool bSortedOutput ) = 0;
|
|
|
|
// Note: threading model for pack files assumes that data
|
|
// is segmented into pack files that aggregate files
|
|
// meant to be read in one thread. Performance characteristics
|
|
// tuned for that case
|
|
CThreadFastMutex m_mutex;
|
|
|
|
// Path management:
|
|
void SetPath( const CUtlSymbol &path ) { m_Path = path; }
|
|
const CUtlSymbol& GetPath() const { Assert( m_Path != UTL_INVAL_SYMBOL ); return m_Path; }
|
|
CUtlSymbol m_Path;
|
|
|
|
// possibly embedded pack
|
|
int64 m_nBaseOffset;
|
|
|
|
CUtlString m_ZipName;
|
|
|
|
bool m_bIsMapPath;
|
|
long m_lPackFileTime;
|
|
|
|
int m_refCount;
|
|
int m_nOpenFiles;
|
|
|
|
FILE *m_hPackFileHandleFS;
|
|
#if defined( SUPPORT_PACKED_STORE )
|
|
CPackedStoreFileHandle m_hPackFileHandleVPK;
|
|
#endif
|
|
bool m_bIsExcluded;
|
|
|
|
int m_PackFileID;
|
|
protected:
|
|
// This is the core IO routine for reading anything from a pack file, everything should go through here at some point
|
|
virtual int ReadFromPack( int nIndex, void* buffer, int nDestBytes, int nBytes, int64 nOffset ) = 0;
|
|
|
|
int64 m_FileLength;
|
|
CBaseFileSystem *m_fs;
|
|
|
|
friend class CPackFileHandle;
|
|
};
|
|
|
|
class CZipPackFile : public CPackFile
|
|
{
|
|
friend class CZipPackFileHandle;
|
|
public:
|
|
CZipPackFile( CBaseFileSystem* fs, void *pSection = NULL );
|
|
virtual ~CZipPackFile();
|
|
|
|
// Loads the pack file
|
|
virtual bool Prepare( int64 fileLen = -1, int64 nFileOfs = 0 ) OVERRIDE;
|
|
virtual bool ContainsFile( const char *pFileName ) OVERRIDE;
|
|
virtual CFileHandle *OpenFile( const char *pFileName, const char *pOptions = "rb" ) OVERRIDE;
|
|
|
|
virtual void GetFileAndDirLists( const char *pFindWildCard, CUtlStringList &outDirnames, CUtlStringList &outFilenames, bool bSortedOutput ) OVERRIDE;
|
|
|
|
virtual int64 GetPackFileBaseOffset() OVERRIDE { return m_nBaseOffset; }
|
|
|
|
virtual bool IndexToFilename( int nIndex, char *pBuffer, int nBufferSize ) OVERRIDE;
|
|
|
|
protected:
|
|
virtual int ReadFromPack( int nIndex, void* buffer, int nDestBytes, int nBytes, int64 nOffset ) OVERRIDE;
|
|
|
|
#pragma pack(1)
|
|
|
|
typedef struct
|
|
{
|
|
char name[ 112 ];
|
|
int64 filepos;
|
|
int64 filelen;
|
|
} packfile64_t;
|
|
|
|
typedef struct
|
|
{
|
|
char id[ 4 ];
|
|
int64 dirofs;
|
|
int64 dirlen;
|
|
} packheader64_t;
|
|
|
|
typedef struct
|
|
{
|
|
char id[ 8 ];
|
|
int64 packheaderpos;
|
|
int64 originalfilesize;
|
|
} packappenededheader_t;
|
|
|
|
#pragma pack()
|
|
|
|
// A Pack file directory entry:
|
|
class CPackFileEntry
|
|
{
|
|
public:
|
|
unsigned int m_nPosition;
|
|
unsigned int m_nOriginalSize;
|
|
unsigned int m_nCompressedSize;
|
|
unsigned int m_HashName;
|
|
unsigned short m_nPreloadIdx;
|
|
unsigned short pad;
|
|
unsigned short m_nCompressionMethod;
|
|
FileNameHandle_t m_hFileName;
|
|
};
|
|
|
|
class CPackFileLessFunc
|
|
{
|
|
public:
|
|
bool Less( CPackFileEntry const& src1, CPackFileEntry const& src2, void *pCtx );
|
|
};
|
|
|
|
// Find a file inside a pack file:
|
|
const CPackFileEntry* FindFile( const char* pFileName );
|
|
|
|
// Entries to the individual files stored inside the pack file.
|
|
CUtlSortVector< CPackFileEntry, CPackFileLessFunc > m_PackFiles;
|
|
|
|
bool GetFileInfo( const char *pFileName, int &nBaseIndex, int64 &nFileOffset, int &nOriginalSize, int &nCompressedSize, unsigned short &nCompressionMethod );
|
|
|
|
// Preload Support
|
|
void SetupPreloadData() OVERRIDE;
|
|
void DiscardPreloadData() OVERRIDE;
|
|
ZIP_PreloadDirectoryEntry* GetPreloadEntry( int nEntryIndex );
|
|
|
|
int64 m_nPreloadSectionOffset;
|
|
unsigned int m_nPreloadSectionSize;
|
|
ZIP_PreloadHeader *m_pPreloadHeader;
|
|
unsigned short* m_pPreloadRemapTable;
|
|
ZIP_PreloadDirectoryEntry *m_pPreloadDirectory;
|
|
void* m_pPreloadData;
|
|
CByteswap m_swap;
|
|
|
|
#if defined ( _X360 )
|
|
void *m_pSection;
|
|
#endif
|
|
};
|
|
|
|
#endif // PACKFILE_H
|