Files
fs2open.github.com/code/cfile/cfilearchive.cpp
T

340 lines
7.7 KiB
C++

/*
* Copyright (C) Volition, Inc. 1999. All rights reserved.
*
* All source code herein is the property of Volition, Inc. You may not sell
* or otherwise commercially exploit the source or things you created based on the
* source.
*
*/
/*
* $Logfile: /Freespace2/code/CFile/CfileArchive.cpp $
* $Revision: 2.8 $
* $Date: 2006-12-28 00:59:19 $
* $Author: wmcoolmon $
*
* Low-level code for reading data out of large archive files or normal files. All
* reads/seeks come through here.
*
* $Log: not supported by cvs2svn $
* Revision 2.7 2005/07/24 18:31:17 taylor
* little 64-bit strangeness (longs are 64-bit here rather than 32)
*
* Revision 2.6 2004/07/26 20:47:25 Kazan
* remove MCD complete
*
* Revision 2.5 2004/07/12 16:32:42 Kazan
* MCD - define _MCD_CHECK to use memory tracking
*
* Revision 2.4 2004/03/05 09:01:54 Goober5000
* Uber pass at reducing #includes
* --Goober5000
*
* Revision 2.3 2003/03/19 09:05:25 Goober5000
* more housecleaning, this time for debug warnings
* --Goober5000
*
* Revision 2.2 2002/08/01 01:41:04 penguin
* The big include file move
*
* Revision 2.1 2002/07/29 19:17:21 penguin
* added #ifdef _WIN32 around windows-specific system headers
*
* Revision 2.0 2002/06/03 04:02:21 penguin
* Warpcore CVS sync
*
* Revision 1.1 2002/05/02 18:03:04 mharris
* Initial checkin - converted filenames and includes to lower case
*
*
* 4 2/22/99 10:31p Andsager
* Get rid of unneeded includes.
*
* 3 1/06/99 2:24p Dave
* Stubs and release build fixes.
*
* 2 10/07/98 10:52a Dave
* Initial checkin.
*
* 1 10/07/98 10:48a Dave
*
* 12 5/14/98 8:10p Lawrance
* Fix bug with trying to read past the end of a file (when from a
* packfile).
*
* 11 5/11/98 11:48a John
* fixed bug with memory mapped files
*
* 10 5/11/98 10:59a John
* added in debug code
*
* 9 5/11/98 10:59a John
* Moved the low-level file reading code into cfilearchive.cpp.
*
* 8 4/30/98 4:53p John
* Restructured and cleaned up cfile code. Added capability to read off
* of CD-ROM drive and out of multiple pack files.
*
* 7 4/20/98 11:49a Hoffoss
* Fixed bug with directory name getting.
*
* 6 4/10/98 12:18a Hoffoss
* Make pilot image search in pack file possible.
*
* 5 1/19/98 9:37p Allender
* Great Compiler Warning Purge of Jan, 1998. Used pragma's in a couple
* of places since I was unsure of what to do with code.
*
* 4 12/30/97 5:31p Lawrance
* fixed problem for people that didn't have a VP file
*
* 3 12/30/97 4:31p Sandeep
* Changed pakfile format
*
* 2 12/28/97 12:42p John
* Put in support for reading archive files; Made missionload use the
* cf_get_file_list function. Moved demos directory out of data tree.
*
* 1 12/28/97 11:48a John
*
* $NoKeywords: $
*/
#define _CFILE_INTERNAL
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#ifdef _WIN32
#include <io.h>
#include <direct.h>
#include <windows.h>
#include <winbase.h> /* needed for memory mapping of file functions */
#endif
#include "cfile/cfile.h"
#include "cfile/cfilearchive.h"
#include "luaconf.h"
#define CHECK_POSITION
// Called once to setup the low-level reading code.
void cf_init_lowlevel_read_code( CFILE * cfile, int offset, int size )
{
Assert(cfile != NULL);
Cfile_block *cb;
Assert(cfile->id >= 0 && cfile->id < MAX_CFILE_BLOCKS);
cb = &Cfile_block_list[cfile->id];
cb->lib_offset = offset;
cb->raw_position = 0;
cb->size = size;
if ( cb->fp ) {
if ( cb->lib_offset ) {
fseek( cb->fp, cb->lib_offset, SEEK_SET );
}
#if defined(CHECK_POSITION) && !defined(NDEBUG)
int raw_position;
raw_position = ftell(cb->fp) - cb->lib_offset;
Assert(raw_position == cb->raw_position);
#endif
}
}
// cfeof() Tests for end-of-file on a stream
//
// returns a nonzero value after the first read operation that attempts to read
// past the end of the file. It returns 0 if the current position is not end of file.
// There is no error return.
int cfeof(CFILE *cfile)
{
Assert(cfile != NULL);
Cfile_block *cb;
Assert(cfile->id >= 0 && cfile->id < MAX_CFILE_BLOCKS);
cb = &Cfile_block_list[cfile->id];
int result;
result = 0;
// cfeof() not supported for memory-mapped files
Assert( !cb->data );
Assert(cb->fp != NULL);
#if defined(CHECK_POSITION) && !defined(NDEBUG)
int raw_position;
raw_position = ftell(cb->fp) - cb->lib_offset;
Assert(raw_position == cb->raw_position);
#endif
if (cb->raw_position >= cb->size ) {
result = 1;
} else {
result = 0;
}
return result;
}
// cftell() returns offset into file
//
// returns: success ==> offset into the file
// error ==> -1
//
int cftell( CFILE * cfile )
{
Assert(cfile != NULL);
Cfile_block *cb;
Assert(cfile->id >= 0 && cfile->id < MAX_CFILE_BLOCKS);
cb = &Cfile_block_list[cfile->id];
// Doesn't work for memory mapped files
Assert( !cb->data );
Assert(cb->fp != NULL);
#if defined(CHECK_POSITION) && !defined(NDEBUG)
int raw_position;
raw_position = ftell(cb->fp) - cb->lib_offset;
Assert(raw_position == cb->raw_position);
#endif
return cb->raw_position;
}
// cfseek() moves the file pointer
//
// returns: success ==> 0
// error ==> non-zero
//
int cfseek( CFILE *cfile, int offset, int where )
{
Assert(cfile != NULL);
Cfile_block *cb;
Assert(cfile->id >= 0 && cfile->id < MAX_CFILE_BLOCKS);
cb = &Cfile_block_list[cfile->id];
// TODO: seek to offset in memory mapped file
Assert( !cb->data );
Assert( cb->fp != NULL );
int goal_position;
switch( where ) {
case CF_SEEK_SET:
goal_position = offset+cb->lib_offset;
break;
case CF_SEEK_CUR:
{
goal_position = cb->raw_position+offset+cb->lib_offset;
}
break;
case CF_SEEK_END:
goal_position = cb->size+offset+cb->lib_offset;
break;
default:
Int3();
return 1;
}
int result = fseek(cb->fp, goal_position, SEEK_SET );
cb->raw_position = goal_position - cb->lib_offset;
#if defined(CHECK_POSITION) && !defined(NDEBUG)
int tmp_offset;
tmp_offset = (int)ftell(cb->fp) - cb->lib_offset;
Assert(tmp_offset==cb->raw_position);
#endif
return result;
}
// cfread() reads from a file
//
// returns: returns the number of full elements read
//
//
int cfread(void *buf, int elsize, int nelem, CFILE *cfile)
{
Assert(cfile != NULL);
Assert(buf != NULL);
Assert(cfile->id >= 0 && cfile->id < MAX_CFILE_BLOCKS);
Cfile_block *cb;
cb = &Cfile_block_list[cfile->id];
// cfread() not supported for memory-mapped files
Assert( !cb->data );
Assert(cb->fp != NULL);
int size = elsize*nelem;
Assert(nelem > 0);
Assert(elsize > 0);
Assert(size > 0);
if ( (cb->raw_position+size) > cb->size ) {
size = cb->size - cb->raw_position;
if ( size < 1 ) {
return 0;
}
//mprintf(( "CFILE: EOF encountered in file\n" ));
}
int bytes_read = fread( buf, 1, size, cb->fp );
if ( bytes_read > 0 ) {
cb->raw_position += bytes_read;
}
#if defined(CHECK_POSITION) && !defined(NDEBUG)
int tmp_offset;
tmp_offset = ftell(cb->fp) - cb->lib_offset;
Assert(tmp_offset==cb->raw_position);
#endif
return bytes_read / elsize;
}
int cfread_lua_number(double *buf, CFILE *cfile)
{
Assert(cfile != NULL);
Assert(buf != NULL);
Assert(cfile->id >= 0 && cfile->id < MAX_CFILE_BLOCKS);
Cfile_block *cb;
cb = &Cfile_block_list[cfile->id];
// cfread() not supported for memory-mapped files
Assert( !cb->data );
Assert(cb->fp != NULL);
long orig_pos = ftell(cb->fp);
int items_read = fscanf(cb->fp, LUA_NUMBER_SCAN, buf);
cb->raw_position += ftell(cb->fp)-orig_pos;
#if defined(CHECK_POSITION) && !defined(NDEBUG)
int tmp_offset;
tmp_offset = ftell(cb->fp) - cb->lib_offset;
Assert(tmp_offset==cb->raw_position);
#endif
return items_read;
}