200 lines
4.8 KiB
C++
200 lines
4.8 KiB
C++
//===== Copyright © 1996-2008, Valve Corporation, All rights reserved. ======//
|
|
//
|
|
// Purpose:
|
|
//
|
|
//===========================================================================//
|
|
|
|
#ifndef PACKEDSTORE_H
|
|
#define PACKEDSTORE_H
|
|
#ifdef _WIN32
|
|
#pragma once
|
|
#endif
|
|
|
|
|
|
#include <tier0/platform.h>
|
|
#include <tier0/threadtools.h>
|
|
#include <tier2/tier2.h>
|
|
|
|
#include "filesystem.h"
|
|
#include "tier1/utlintrusivelist.h"
|
|
#include "tier1/utlvector.h"
|
|
|
|
class CPackedStore;
|
|
|
|
|
|
|
|
|
|
struct CPackedStoreFileHandle
|
|
{
|
|
public:
|
|
int m_nFileNumber;
|
|
int m_nFileOffset;
|
|
int m_nFileSize;
|
|
int m_nCurrentFileOffset;
|
|
void const *m_pMetaData;
|
|
uint16 m_nMetaDataSize;
|
|
CPackedStore *m_pOwner;
|
|
struct CFileHeaderFixedData *m_pHeaderData;
|
|
uint8 *m_pDirFileNamePtr; // pointer to basename in dir block
|
|
|
|
FORCEINLINE operator bool( void ) const
|
|
{
|
|
return ( m_nFileNumber != -1 );
|
|
}
|
|
|
|
FORCEINLINE int Read( void *pOutData, int nNumBytes );
|
|
|
|
CPackedStoreFileHandle( void )
|
|
{
|
|
m_nFileNumber = -1;
|
|
}
|
|
|
|
int Seek( int nOffset, int nWhence )
|
|
{
|
|
switch( nWhence )
|
|
{
|
|
case SEEK_CUR:
|
|
nOffset = m_nFileOffset + nOffset ;
|
|
break;
|
|
|
|
case SEEK_END:
|
|
nOffset = m_nFileSize - 1 + nOffset;
|
|
break;
|
|
}
|
|
m_nCurrentFileOffset = MAX( 0, MIN( m_nFileSize - 1, nOffset ) );
|
|
return m_nCurrentFileOffset;
|
|
}
|
|
|
|
int Tell( void ) const
|
|
{
|
|
return m_nCurrentFileOffset;
|
|
}
|
|
};
|
|
|
|
#define MAX_ARCHIVE_FILES_TO_KEEP_OPEN_AT_ONCE 128
|
|
|
|
#define PACKEDFILE_EXT_HASH_SIZE 15
|
|
|
|
|
|
#ifdef _WIN32
|
|
typedef HANDLE PackDataFileHandle_t;
|
|
#else
|
|
typedef FileHandle_t PackDataFileHandle_t;
|
|
#endif
|
|
|
|
struct FileHandleTracker_t
|
|
{
|
|
int m_nFileNumber;
|
|
PackDataFileHandle_t m_hFileHandle;
|
|
int m_nCurOfs;
|
|
CThreadFastMutex m_Mutex;
|
|
|
|
FileHandleTracker_t( void )
|
|
{
|
|
m_nFileNumber = -1;
|
|
}
|
|
};
|
|
|
|
enum ePackedStoreAddResultCode
|
|
{
|
|
EPADD_NEWFILE, // the file was added and is new
|
|
EPADD_ADDSAMEFILE, // the file was already present, and the contents are the same as what you passed.
|
|
EPADD_UPDATEFILE, // the file was alreayd present and its contents have been updated
|
|
EPADD_ERROR, // some error has resulted
|
|
};
|
|
|
|
|
|
class CPackedStore
|
|
{
|
|
public:
|
|
CPackedStore( char const *pFileBasename, IBaseFileSystem *pFS, bool bOpenForWrite = false );
|
|
|
|
CPackedStoreFileHandle OpenFile( char const *pFile );
|
|
|
|
ePackedStoreAddResultCode AddFile( char const *pFile, int nNumDataParts, uint16 nMetaDataSize, void *pFileData, uint32 nFullFileSize, bool bMultiChunk, uint32 const *pCrcToUse = NULL );
|
|
|
|
// write out the file directory
|
|
void Write( void );
|
|
|
|
int ReadData( CPackedStoreFileHandle &handle, void *pOutData, int nNumBytes );
|
|
|
|
~CPackedStore( void );
|
|
|
|
FORCEINLINE void *DirectoryData( void )
|
|
{
|
|
return m_DirectoryData.Base();
|
|
}
|
|
|
|
// Get a list of all the files in the zip You are responsible for freeing the contents of
|
|
// outFilenames (call outFilenames.PurgeAndDeleteElements).
|
|
int GetFileList( CUtlStringList &outFilenames, bool bFormattedOutput = false );
|
|
|
|
// Get a list of all files that match the given wildcard string
|
|
int GetFileList( const char *pWildCard, CUtlStringList &outFilenames, bool bFormattedOutput = false );
|
|
|
|
// Get a list of all directories of the given wildcard
|
|
int GetDirList( const char *pWildCard, CUtlStringList &outDirnames );
|
|
int GetDirList( CUtlStringList &outDirnames );
|
|
|
|
bool IsEmpty( void ) const;
|
|
|
|
|
|
char const *FullPathName( void )
|
|
{
|
|
return m_pszFullPathName;
|
|
}
|
|
|
|
void SetWriteChunkSize( int nWriteChunkSize )
|
|
{
|
|
m_nWriteChunkSize = nWriteChunkSize;
|
|
}
|
|
|
|
private:
|
|
char m_pszFileBaseName[MAX_PATH];
|
|
char m_pszFullPathName[MAX_PATH];
|
|
int m_nWriteOffset;
|
|
int m_nChunkWriteIndex;
|
|
int m_nWriteChunkFileIndex;
|
|
int m_nDirectoryDataSize;
|
|
int m_nWriteChunkSize;
|
|
|
|
FileHandle_t m_ChunkWriteHandle;
|
|
IBaseFileSystem *m_pFileSystem;
|
|
CThreadFastMutex m_Mutex;
|
|
|
|
|
|
CUtlIntrusiveList<class CFileExtensionData> m_pExtensionData[PACKEDFILE_EXT_HASH_SIZE];
|
|
|
|
CUtlVector<uint8> m_DirectoryData;
|
|
CUtlBlockVector<uint8> m_EmbeddedChunkData;
|
|
|
|
int m_nHighestChunkFileIndex;
|
|
|
|
FileHandleTracker_t m_FileHandles[MAX_ARCHIVE_FILES_TO_KEEP_OPEN_AT_ONCE];
|
|
|
|
void Init( void );
|
|
|
|
struct CFileHeaderFixedData *FindFileEntry(
|
|
char const *pDirname, char const *pBaseName, char const *pExtension,
|
|
uint8 **pExtBaseOut = NULL, uint8 **pNameBaseOut = NULL );
|
|
|
|
void BuildHashTables( void );
|
|
void GetDataFileName( char *pszOutName, int nFileNumber );
|
|
|
|
FileHandleTracker_t &GetFileHandle( int nFileNumber );
|
|
|
|
FileHandle_t GetWriteHandle( int nChunkIdx );
|
|
void CloseWriteHandle( void );
|
|
|
|
|
|
|
|
};
|
|
|
|
FORCEINLINE int CPackedStoreFileHandle::Read( void *pOutData, int nNumBytes )
|
|
{
|
|
return m_pOwner->ReadData( *this, pOutData, nNumBytes );
|
|
}
|
|
|
|
|
|
#endif // packedtsore_h
|