0ad/source/ps/FileUnpacker.cpp
janwas 06412a7751 allocators: bugfix (wasn't setting freelist to 0)
archive: afile_read bugfix (wasn't returning byte count)
byte_order: add to_leXX, implement read_leXX in terms of that, add
write_leXX (and also big-endian versions)
compression: support 0 length buffers + minor fixes
file: no longer support passing fn_len (that didn't work anyway due to
DynHashTbl find(const char*) interface); add FILE_DONT_SET_FN
optimization that prevents cluttering name cache.
file_cache: add logic to verify load/free/load/free sequence; add
FILE_LONG_LIVED flag to specify exceptions (e.g. XMB files that don't
free their buffer immediately)
vfs_mount/vfs_tree: bugfix (was mixing up portable and VFS paths)
vfs_optimizer: small fixes; creating Zip files now works
vfs_tree: add PathName that stores pointer to path and name component
for efficiency + convenience
zip: bugfixes (wasn't endian safe; incorrect handling of cmethod; forgot
to initialize ZipArchive members)

config: add -buildarchive flag
Xeromyces.cpp, FileUnpacker.cpp: add FILE_LONG_LIVED
mapreader: bump time estimate for ReadXML

This was SVN commit r3446.
2006-01-31 03:47:52 +00:00

123 lines
3.4 KiB
C++
Executable File

///////////////////////////////////////////////////////////////////////////////
//
// Name: FileUnpacker.cpp
// Author: Rich Cross
// Contact: rich@wildfiregames.com
//
///////////////////////////////////////////////////////////////////////////////
#include "precompiled.h"
#include "FileUnpacker.h"
#include "lib/res/res.h"
////////////////////////////////////////////////////////////////////////////////////////
// CFileUnpacker constructor
CFileUnpacker::CFileUnpacker()
{
m_Buf = 0;
m_Size = 0;
m_UnpackPos = 0;
m_Version = 0;
}
CFileUnpacker::~CFileUnpacker()
{
file_buf_free(m_Buf);
}
////////////////////////////////////////////////////////////////////////////////////////
// Read: open and read in given file, check magic bits against those given; throw
// variety of exceptions for missing files etc
void CFileUnpacker::Read(const char* filename,const char magicstr[4])
{
// avoid vfs_load complaining about missing data files (which happens
// too often). better to check here than squelch internal VFS error
// reporting. we disable this in release mode to avoid a speed hit.
// UPDATE: We don't disable this in release mode, because vfs_load now
// complains about missing files when running in release
//#ifndef NDEBUG
if(!vfs_exists(filename))
throw CFileOpenError();
//#endif
// somewhat of a hack: if loading a map (.PMP), tell the file manager
// that the buffer will be kept in memory longer (avoids warning).
uint flags = 0;
const char* ext = strrchr(filename, '.');
if(ext && !stricmp(ext, ".pmp"))
flags |= FILE_LONG_LIVED;
// load the whole thing into memory
if(vfs_load(filename, m_Buf, m_Size, flags) < 0)
throw CFileOpenError();
// make sure we read enough for the header
if(m_Size < 12)
{
(void)file_buf_free(m_Buf);
m_Buf = 0;
m_Size = 0;
throw CFileReadError();
}
// extract data from header
u8* header = (u8*)m_Buf;
char* magic = (char*)(header+0);
// FIXME m_Version and datasize: Byte order? -- Simon
m_Version = *(u32*)(header+4);
u32 datasize = *(u32*)(header+8);
// check we've got the right kind of file
// .. and that we read exactly headersize+datasize
if(strncmp(magic, magicstr, 4) != 0 ||
m_Size != 12+datasize)
{
(void)file_buf_free(m_Buf);
m_Buf = 0;
m_Size = 0;
throw CFileTypeError();
}
m_UnpackPos = 12;
}
////////////////////////////////////////////////////////////////////////////////////////
// UnpackRaw: unpack given number of bytes from the input stream into the given array
// - throws CFileEOFError if the end of the data stream is reached before the given
// number of bytes have been read
void CFileUnpacker::UnpackRaw(void* rawdata,u32 rawdatalen)
{
// got enough data to unpack?
if (m_UnpackPos+rawdatalen<=m_Size)
{
// yes .. copy over
void* src = (char*)m_Buf + m_UnpackPos;
memcpy2(rawdata, src, rawdatalen);
m_UnpackPos += rawdatalen;
}
else
// nope - throw exception
throw CFileEOFError();
}
////////////////////////////////////////////////////////////////////////////////////////
// UnpackString: unpack a string from the raw data stream
// - throws CFileEOFError if eof is reached before the string length has been
// satisfied
void CFileUnpacker::UnpackString(CStr& result)
{
// get string length
u32 length;
UnpackRaw(&length,sizeof(length)); // FIXME Byte order? -- Simon
if (m_UnpackPos + length <= m_Size)
{
result=std::string((char *)m_Buf+m_UnpackPos, length);
m_UnpackPos += length;
}
else
throw CFileEOFError();
}