Serious-Engine/Sources/Engine/Base/CRCTable.cpp

197 lines
4.8 KiB
C++

/* Copyright (c) 2002-2012 Croteam Ltd.
This program is free software; you can redistribute it and/or modify
it under the terms of version 2 of the GNU General Public License as published by
the Free Software Foundation
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
#include "Engine/StdH.h"
#include <Engine/Base/CRCTable.h>
#include <Engine/Base/FileName.h>
#include <Engine/Base/Stream.h>
#include <Engine/Base/Console.h>
#include <Engine/Base/CRC.h>
#include <Engine/Templates/DynamicStackArray.cpp>
extern INDEX net_bReportCRC;
class CCRCEntry {
public:
CTFileName ce_fnmFile; // the file that CRC is for
ULONG ce_ulCRC; // CRC of the file
BOOL ce_bActive; // set if the file is now active for CRC checking
// filename is its name (used for storing in nametable)
inline const CTFileName &GetName(void) { return ce_fnmFile; };
void Clear(void)
{
ce_fnmFile.Clear();
ce_ulCRC = 0;
ce_bActive = FALSE;
}
};
extern CDynamicStackArray<CTFileName> _afnmNoCRC;
extern BOOL FileMatchesList(CDynamicStackArray<CTFileName> &afnm, const CTFileName &fnm);
#define TYPE CCRCEntry
#define CNameTable_TYPE CNameTable_CCRCEntry
#define CNameTableSlot_TYPE CNameTableSlot_CCRCEntry
#include <Engine/Templates/NameTable.h>
#include <Engine/Templates/NameTable.cpp>
#undef CNameTableSlot_TYPE
#undef CNameTable_TYPE
#undef TYPE
static CDynamicStackArray<CCRCEntry> _aceEntries;
static CNameTable_CCRCEntry _ntEntries;
BOOL CRCT_bGatherCRCs = FALSE; // set while gathering CRCs of all loaded files
// init CRC table
void CRCT_Init(void)
{
_ntEntries.SetAllocationParameters(50, 10, 10);
}
// check if a file is added
BOOL CRCT_IsFileAdded(const CTFileName &fnm)
{
return _ntEntries.Find(fnm)!=NULL;
}
// add one file to active list and get its crc
void CRCT_AddFile_t(const CTFileName &fnm, ULONG ulCRC/*=0*/) // throw char *
{
// if not gathering CRCs now
if (!CRCT_bGatherCRCs) {
// do nothing
return;
}
// try to find it in table
CCRCEntry *pce = _ntEntries.Find(fnm);
BOOL bNew = FALSE;
// if found
if (pce!=NULL) {
// just activate it
bNew = !pce->ce_bActive;
pce->ce_bActive = TRUE;
// if crc is given
if (ulCRC!=0) {
// force it
pce->ce_ulCRC = ulCRC;
}
// if not found
} else {
// calculate checksum
if (ulCRC==0) {
if (FileMatchesList(_afnmNoCRC, fnm)) {
ulCRC = 0x12345678;
} else {
ulCRC = GetFileCRC32_t(fnm);
}
}
// add to the table
pce = &_aceEntries.Push();
pce->ce_fnmFile = fnm;
pce->ce_ulCRC = ulCRC;
pce->ce_bActive = TRUE;
_ntEntries.Add(pce);
bNew = TRUE;
}
if (bNew && net_bReportCRC) {
CPrintF("CRC %08x: '%s'\n", pce->ce_ulCRC, (const char*)pce->ce_fnmFile);
}
}
// free all memory used by the crc cache
void CRCT_Clear(void)
{
_ntEntries.Clear();
_aceEntries.Clear();
}
// reset all files to not active
void CRCT_ResetActiveList(void)
{
for(INDEX ice=0; ice<_aceEntries.Count(); ice++) {
_aceEntries[ice].ce_bActive = FALSE;
}
}
static INDEX GetNumberOfActiveEntries(void)
{
INDEX ctActive = 0;
for(INDEX ice=0; ice<_aceEntries.Count(); ice++) {
if (_aceEntries[ice].ce_bActive) {
ctActive++;
}
}
return ctActive;
}
// dump list of all active files to the stream
void CRCT_MakeFileList_t(CTStream &strmFiles) // throw char *
{
// save number of active entries
INDEX ctActive = GetNumberOfActiveEntries();
strmFiles<<ctActive;
// for each active entry
for(INDEX ice=0; ice<_aceEntries.Count(); ice++) {
CCRCEntry &ce = _aceEntries[ice];
if (!ce.ce_bActive) {
continue;
}
// save name to stream
strmFiles<<(CTString&)ce.ce_fnmFile;
}
}
// dump checksums for all files from the list
ULONG CRCT_MakeCRCForFiles_t(CTStream &strmFiles) // throw char *
{
BOOL bOld = CRCT_bGatherCRCs;
CRCT_bGatherCRCs = TRUE;
ULONG ulCRC;
CRC_Start(ulCRC);
// read number of active files
INDEX ctFiles;
strmFiles>>ctFiles;
// for each one
for(INDEX i=0; i<ctFiles; i++) {
// read the name
CTString strName;
strmFiles>>strName;
CTFileName fname = strName;
// try to find it in table
CCRCEntry *pce = _ntEntries.Find(fname);
// if not there
if (pce==NULL) {
CRCT_AddFile_t(fname);
// add it now
pce = _ntEntries.Find(fname);
}
// add the crc
CRC_AddLONG(ulCRC, pce->ce_ulCRC);
}
CRCT_bGatherCRCs = bOld;
CRC_Finish(ulCRC);
return ulCRC;
}