Files
FC1/Editor/Util/NamedData.cpp
romkazvo 34d6c5d489 123
2023-08-07 19:29:24 +08:00

318 lines
7.6 KiB
C++

////////////////////////////////////////////////////////////////////////////
//
// Crytek Engine Source File.
// Copyright (C), Crytek Studios, 2001.
// -------------------------------------------------------------------------
// File name: NamedData.cpp
// Version: v1.00
// Created: 30/10/2001 by Timur.
// Compilers: Visual C++ 6.0
// Description: Collection of Named data blocks.
// -------------------------------------------------------------------------
// History:
//
////////////////////////////////////////////////////////////////////////////
#include "StdAfx.h"
#include "NamedData.h"
#include "..\zlib\zlib.h"
#include "PakFile.h"
IMPLEMENT_SERIAL(CNamedData, CObject, 1)
//////////////////////////////////////////////////////////////////////////
CNamedData::CNamedData()
{
}
//////////////////////////////////////////////////////////////////////////
CNamedData::~CNamedData()
{
Clear();
}
//////////////////////////////////////////////////////////////////////////
void CNamedData::AddDataBlock( const CString &blockName,void* pData,int nSize,bool bCompress )
{
assert( pData );
assert( nSize > 0 );
bCompress = false;
DataBlock *pBlock = stl::find_in_map( m_blocks,blockName,(DataBlock*)0 );
if (pBlock)
{
delete pBlock;
}
pBlock = new DataBlock;
if (bCompress)
{
pBlock->bCompressed = true;
CMemoryBlock temp;
temp.Attach( pData,nSize );
temp.Compress( pBlock->compressedData );
}
else
{
pBlock->bCompressed = false;
pBlock->data.Allocate( nSize );
pBlock->data.Copy( pData,nSize );
}
m_blocks[blockName] = pBlock;
}
void CNamedData::AddDataBlock( const CString &blockName,CMemoryBlock &mem )
{
DataBlock *pBlock = stl::find_in_map( m_blocks,blockName,(DataBlock*)0 );
if (pBlock)
{
delete pBlock;
}
pBlock = new DataBlock;
if (mem.GetUncompressedSize() != 0)
{
// This is compressed block.
pBlock->bCompressed = true;
pBlock->compressedData = mem;
}
else
{
pBlock->bCompressed = false;
pBlock->data = mem;
}
m_blocks[blockName] = pBlock;
}
//////////////////////////////////////////////////////////////////////////
void CNamedData::Clear()
{
for (Blocks::iterator it = m_blocks.begin(); it != m_blocks.end(); ++it)
{
delete it->second;
}
m_blocks.clear();
}
//////////////////////////////////////////////////////////////////////////
bool CNamedData::GetDataBlock( const CString &blockName,void* &pData, int &nSize )
{
pData = 0;
nSize = 0;
bool bUncompressed = false;
CMemoryBlock *mem = GetDataBlock( blockName,bUncompressed );
if (mem)
{
pData = mem->GetBuffer();
nSize = mem->GetSize();
return true;
}
return false;
}
//////////////////////////////////////////////////////////////////////////
CMemoryBlock* CNamedData::GetDataBlock( const CString &blockName,bool &bCompressed )
{
DataBlock *pBlock = stl::find_in_map( m_blocks,blockName,(DataBlock*)0 );
if (!pBlock)
return 0;
if (bCompressed)
{
// Return compressed data.
if (!pBlock->compressedData.IsEmpty())
return &pBlock->compressedData;
}
else
{
// Return normal data.
if (!pBlock->data.IsEmpty())
{
return &pBlock->data;
}
else
{
// Uncompress compressed block.
if (!pBlock->compressedData.IsEmpty())
{
pBlock->compressedData.Uncompress( pBlock->data );
return &pBlock->data;
}
}
}
return 0;
}
//////////////////////////////////////////////////////////////////////////
void CNamedData::Serialize(CArchive& ar)
{
CObject::Serialize(ar);
if (ar.IsStoring())
{
int iSize = m_blocks.size();
ar << iSize;
for (Blocks::iterator it = m_blocks.begin(); it != m_blocks.end(); it++)
{
CString key = it->first;
DataBlock* pBlock = it->second;
unsigned int nOriginalSize;
unsigned int nSizeFlags;
unsigned int flags = 0;
if (pBlock->bCompressed)
{
nOriginalSize = pBlock->compressedData.GetUncompressedSize();
// Compressed data.
unsigned long destSize = pBlock->compressedData.GetSize();
void *dest = pBlock->compressedData.GetBuffer();
nSizeFlags = destSize | (1<<31);
ar << key;
ar << nSizeFlags; // Current size of data + 1 bit for compressed flag.
ar << nOriginalSize; // Size of uncompressed data.
ar << flags; // Some additional flags.
ar.Write( dest,destSize );
}
else
{
nOriginalSize = pBlock->data.GetSize();
void *dest = pBlock->data.GetBuffer();
nSizeFlags = nOriginalSize;
ar << key;
ar << nSizeFlags;
ar << nOriginalSize; // Size of uncompressed data.
ar << flags; // Some additional flags.
ar.Write( dest,nOriginalSize );
}
}
}
else
{
Clear();
int iSize;
ar >> iSize;
for(int i = 0; i < iSize; i++)
{
CString key;
unsigned int nSizeFlags = 0;
unsigned int nSize = 0;
unsigned int nOriginalSize = 0;
unsigned int flags = 0;
bool bCompressed = false;
DataBlock *pBlock = new DataBlock;
ar >> key;
ar >> nSizeFlags;
ar >> nOriginalSize;
ar >> flags;
nSize = nSizeFlags & (~(1<<31));
bCompressed = (nSizeFlags & (1<<31)) != 0;
if (bCompressed)
{
pBlock->compressedData.Allocate( nSize,nOriginalSize );
void *pSrcData = pBlock->compressedData.GetBuffer();
// Read compressed data.
ar.Read( pSrcData,nSize );
}
else
{
pBlock->data.Allocate( nSize );
void *pSrcData = pBlock->data.GetBuffer();
// Read uncompressed data.
ar.Read( pSrcData,nSize );
}
m_blocks[key] = pBlock;
}
}
}
//////////////////////////////////////////////////////////////////////////
void CNamedData::Save( CPakFile &pakFile )
{
for (Blocks::iterator it = m_blocks.begin(); it != m_blocks.end(); it++)
{
CString key = it->first;
DataBlock* pBlock = it->second;
if (!pBlock->bCompressed)
{
CString filename = key + ".editor_data";
pakFile.UpdateFile( filename,pBlock->data );
}
else
{
int nOriginalSize = pBlock->compressedData.GetUncompressedSize();
CMemFile memFile;
// Write uncompressed data size.
memFile.Write( &nOriginalSize,sizeof(nOriginalSize) );
// Write compressed data.
memFile.Write( pBlock->compressedData.GetBuffer(),pBlock->compressedData.GetSize() );
pakFile.UpdateFile( key+".editor_datac",memFile,false );
}
}
}
//////////////////////////////////////////////////////////////////////////
void CNamedData::Load( const CString &levelPath,CPakFile &pakFile )
{
int i;
CFileUtil::FileArray files;
CFileUtil::ScanDirectory( levelPath,"*.editor_data",files,false );
for (i = 0; i < files.size(); i++)
{
CString filename = files[i].filename;
CCryFile cfile;
if (cfile.Open( Path::Make(levelPath,filename),"rb"))
{
int fileSize = cfile.GetLength();
if (fileSize > 0)
{
CString key = Path::GetFileName(filename);
// Read data block.
DataBlock *pBlock = new DataBlock;
pBlock->data.Allocate( fileSize );
cfile.Read( pBlock->data.GetBuffer(),fileSize );
m_blocks[key] = pBlock;
}
}
}
files.clear();
// Scan compressed data.
CFileUtil::ScanDirectory( levelPath,"*.editor_datac",files,false );
for (i = 0; i < files.size(); i++)
{
CString filename = files[i].filename;
CCryFile cfile;
if (cfile.Open( Path::Make(levelPath,filename),"rb"))
{
int fileSize = cfile.GetLength();
if (fileSize > 0)
{
// Read uncompressed data size.
int nOriginalSize = 0;
cfile.Read( &nOriginalSize,sizeof(nOriginalSize) );
// Read uncompressed data.
int nDataSize = fileSize - sizeof(nOriginalSize);
CString key = Path::GetFileName(filename);
// Read data block.
DataBlock *pBlock = new DataBlock;
pBlock->compressedData.Allocate( nDataSize,nOriginalSize );
cfile.Read( pBlock->compressedData.GetBuffer(),nDataSize );
m_blocks[key] = pBlock;
}
}
}
}