Counter Strike : Global Offensive Source Code
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.
 
 
 
 
 
 

310 lines
7.5 KiB

//====== Copyright c 1996-2007, Valve Corporation, All rights reserved. =======//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
#include "platform.h"
#include "utlvector.h"
#include "utlbuffer.h"
#include "chunkfile.h"
#include "utlencode.h"
#include "fgdlib/wckeyvalues.h"
#include "vmfmeshdatasupport.h"
CVmfMeshDataSupport_SaveLoadHandler::CVmfMeshDataSupport_SaveLoadHandler()
{
}
CVmfMeshDataSupport_SaveLoadHandler::~CVmfMeshDataSupport_SaveLoadHandler()
{
NULL;
}
ChunkFileResult_t CVmfMeshDataSupport_SaveLoadHandler::WriteDataChunk( CChunkFile *pFile, char const *szHash )
{
ChunkFileResult_t eResult;
eResult = pFile->BeginChunk( GetCustomSectionName() );
if ( eResult != ChunkFile_Ok )
return eResult;
// Write out our data version
char szModelDataVer[ 16 ] = {0};
sprintf( szModelDataVer, "%d", GetCustomSectionVer() );
eResult = pFile->WriteKeyValue( "version", szModelDataVer );
if ( eResult != ChunkFile_Ok )
return eResult;
// Write our hash
eResult = pFile->WriteKeyValue( "hash", szHash );
if ( eResult != ChunkFile_Ok )
return eResult;
// Write out additional data
eResult = OnFileDataWriting( pFile, szHash );
if ( eResult != ChunkFile_Ok )
return eResult;
return pFile->EndChunk();
}
ChunkFileResult_t CVmfMeshDataSupport_SaveLoadHandler::OnFileDataWriting( CChunkFile *pFile, char const *szHash )
{
return ChunkFile_Ok;
}
ChunkFileResult_t CVmfMeshDataSupport_SaveLoadHandler::WriteBufferData( CChunkFile *pFile, CUtlBuffer &bufData, char const *szPrefix )
{
int numEncBytes = KvEncoder::GuessEncodedLength( bufData.TellPut() );
CUtlBuffer bufEncoded;
bufEncoded.EnsureCapacity( numEncBytes );
if ( !KvEncoder::Encode( bufData, bufEncoded ) )
return ChunkFile_Fail;
numEncBytes = bufEncoded.TellPut();
// Now we have the encoded data, split it into blocks
int numBytesPerLine = KEYVALUE_MAX_VALUE_LENGTH - 2;
int numLines = (numEncBytes + numBytesPerLine - 1 ) / numBytesPerLine;
int numLastLineBytes = numEncBytes % numBytesPerLine;
if ( !numLastLineBytes )
numLastLineBytes = numBytesPerLine;
// Key buffer
char chKeyBuf[ KEYVALUE_MAX_KEY_LENGTH ] = {0};
char chKeyValue[ KEYVALUE_MAX_VALUE_LENGTH ] = {0};
// Write the data
ChunkFileResult_t eResult;
sprintf( chKeyBuf, "%s_ebytes", szPrefix );
eResult = pFile->WriteKeyValueInt( chKeyBuf, numEncBytes );
if ( eResult != ChunkFile_Ok )
return eResult;
sprintf( chKeyBuf, "%s_rbytes", szPrefix );
eResult = pFile->WriteKeyValueInt( chKeyBuf, bufData.TellPut() );
if ( eResult != ChunkFile_Ok )
return eResult;
sprintf( chKeyBuf, "%s_lines", szPrefix );
eResult = pFile->WriteKeyValueInt( chKeyBuf, numLines );
if ( eResult != ChunkFile_Ok )
return eResult;
for ( int ln = 0; ln < numLines; ++ ln )
{
int lnLen = ( ln < (numLines - 1) ) ? numBytesPerLine : numLastLineBytes;
sprintf( chKeyBuf, "%s_ln_%d", szPrefix, ln );
sprintf( chKeyValue, "%.*s", lnLen, ( char * ) bufEncoded.Base() + ln * numBytesPerLine );
eResult = pFile->WriteKeyValue( chKeyBuf, chKeyValue );
if ( eResult != ChunkFile_Ok )
return eResult;
}
return ChunkFile_Ok;
}
ChunkFileResult_t CVmfMeshDataSupport_SaveLoadHandler::LoadKeyValueBegin( CChunkFile *pFile )
{
m_eLoadState = LOAD_VERSION;
m_iLoadVer = 0;
m_hLoadHeader.sHash[0] = 0;
LoadInitHeader();
return ChunkFile_Ok;
}
ChunkFileResult_t CVmfMeshDataSupport_SaveLoadHandler::LoadKeyValue( const char *szKey, const char *szValue )
{
switch ( m_eLoadState )
{
case LOAD_VERSION:
return LoadKeyValue_Hdr( szKey, szValue );
default:
switch ( m_iLoadVer )
{
case 1:
return LoadKeyValue_Ver1( szKey, szValue );
default:
return ChunkFile_Fail;
}
}
}
ChunkFileResult_t CVmfMeshDataSupport_SaveLoadHandler::LoadKeyValue_Hdr( const char *szKey, const char *szValue )
{
switch ( m_eLoadState )
{
case LOAD_VERSION:
if ( stricmp( szKey, "version" ) )
return ChunkFile_Fail;
m_iLoadVer = atoi( szValue );
switch ( m_iLoadVer )
{
case 1:
m_eLoadState = LOAD_HASH;
return ChunkFile_Ok;
default:
return ChunkFile_Fail;
}
default:
return ChunkFile_Fail;
}
}
ChunkFileResult_t CVmfMeshDataSupport_SaveLoadHandler::LoadKeyValue_Ver1( const char *szKey, const char *szValue )
{
const char *szKeyName = szKey;
const int nPrefixLen = 3;
switch ( m_eLoadState )
{
case LOAD_HASH:
if ( stricmp( szKey, "hash" ) )
return ChunkFile_Fail;
strncpy( m_hLoadHeader.sHash, szValue, sizeof( m_hLoadHeader.sHash ) );
m_eLoadState = LOAD_PREFIX;
break;
case LOAD_PREFIX:
sprintf( m_hLoadHeader.sPrefix, "%.*s", nPrefixLen, szKey );
if ( strlen( szKey ) < 4 )
return ChunkFile_Fail;
if ( szKey[3] != '_' )
return ChunkFile_Fail;
m_eLoadState = LOAD_HEADER;
// fall-through
case LOAD_HEADER:
if ( strnicmp( m_hLoadHeader.sPrefix, szKey, nPrefixLen ) )
return ChunkFile_Fail;
if ( szKey[3] != '_' )
return ChunkFile_Fail;
szKeyName = szKey + 4;
if ( !stricmp( szKeyName, "ebytes" ) )
m_hLoadHeader.numEncBytes = atoi( szValue );
else if ( !stricmp( szKeyName, "rbytes" ) )
m_hLoadHeader.numBytes = atoi( szValue );
else if ( !stricmp( szKeyName, "lines" ) )
m_hLoadHeader.numLines = atoi( szValue );
else
return ChunkFile_Fail;
if ( !LoadHaveHeader() )
break;
m_eLoadState = LOAD_DATA;
return LoadHaveLines( 0 );
case LOAD_DATA:
if ( strnicmp( m_hLoadHeader.sPrefix, szKey, nPrefixLen ) )
return ChunkFile_Fail;
if ( szKey[3] != '_' )
return ChunkFile_Fail;
szKeyName = szKey + 4;
if ( strnicmp( szKeyName, "ln", 2 ) || szKeyName[2] != '_' )
return ChunkFile_Fail;
szKeyName += 3;
{
int iLineNum = atoi( szKeyName );
if ( iLineNum != m_hLoadHeader.numHaveLines )
return ChunkFile_Fail;
m_bufLoadData.Put( szValue, strlen( szValue ) );
return LoadHaveLines( iLineNum + 1 );
}
default:
return ChunkFile_Fail;
}
return ChunkFile_Ok;
}
ChunkFileResult_t CVmfMeshDataSupport_SaveLoadHandler::LoadKeyValueEnd( CChunkFile *pFile, ChunkFileResult_t eLoadResult )
{
if ( eLoadResult != ChunkFile_Ok )
return eLoadResult;
if ( m_eLoadState == LOAD_VERSION )
return ChunkFile_Ok;
switch ( m_iLoadVer )
{
case 1:
switch ( m_eLoadState )
{
case LOAD_HASH:
case LOAD_PREFIX:
return ChunkFile_Ok;
default:
return ChunkFile_Fail;
}
default:
return ChunkFile_Fail;
}
}
void CVmfMeshDataSupport_SaveLoadHandler::LoadInitHeader()
{
m_hLoadHeader.sPrefix[0] = 0;
m_hLoadHeader.numLines = -1;
m_hLoadHeader.numBytes = -1;
m_hLoadHeader.numEncBytes = -1;
m_hLoadHeader.numHaveLines = 0;
}
bool CVmfMeshDataSupport_SaveLoadHandler::LoadHaveHeader()
{
return m_hLoadHeader.numLines >= 0 && m_hLoadHeader.numBytes >= 0 && m_hLoadHeader.numEncBytes >= 0;
}
ChunkFileResult_t CVmfMeshDataSupport_SaveLoadHandler::LoadHaveLines( int numHaveLines )
{
if ( !numHaveLines )
{
m_bufLoadData.EnsureCapacity( m_hLoadHeader.numEncBytes );
m_bufLoadData.SeekPut( CUtlBuffer::SEEK_HEAD, 0 );
}
m_hLoadHeader.numHaveLines = numHaveLines;
if ( m_hLoadHeader.numHaveLines < m_hLoadHeader.numLines )
return ChunkFile_Ok;
if ( m_hLoadHeader.numHaveLines > m_hLoadHeader.numLines )
return ChunkFile_Fail;
ChunkFileResult_t eRes = LoadSaveFullData();
if ( eRes != ChunkFile_Ok )
return eRes;
LoadInitHeader();
m_eLoadState = LOAD_PREFIX;
return ChunkFile_Ok;
}
ChunkFileResult_t CVmfMeshDataSupport_SaveLoadHandler::LoadSaveFullData()
{
// The filename
CUtlBuffer bufBytes;
bufBytes.EnsureCapacity( m_hLoadHeader.numBytes + 0x10 );
if ( !KvEncoder::Decode( m_bufLoadData, bufBytes ) )
return ChunkFile_Fail;
return OnFileDataLoaded( bufBytes );
}