//===== Copyright © 1996-2008, Valve Corporation, All rights reserved. ======// // // Purpose: // //===========================================================================// #ifndef PACKEDSTORE_H #define PACKEDSTORE_H #ifdef _WIN32 #pragma once #endif #include #include #include #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 m_pExtensionData[PACKEDFILE_EXT_HASH_SIZE]; CUtlVector m_DirectoryData; CUtlBlockVector 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