318 lines
7.6 KiB
C++
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;
|
|
}
|
|
}
|
|
}
|
|
}
|