cache.cpp
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C++ 代码 · 共 422 行
CPP
422 行
/****************************************************************************
*
* Open Watcom Project
*
* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
* ========================================================================
*
* This file contains Original Code and/or Modifications of Original
* Code as defined in and that are subject to the Sybase Open Watcom
* Public License version 1.0 (the 'License'). You may not use this file
* except in compliance with the License. BY USING THIS FILE YOU AGREE TO
* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
* provided with the Original Code and Modifications, and is also
* available at www.sybase.com/developer/opensource.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
* NON-INFRINGEMENT. Please see the License for the specific language
* governing rights and limitations under the License.
*
* ========================================================================
*
* Description: WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
* DESCRIBE IT HERE!
*
****************************************************************************/
#include "wpch.hpp"
#include "cache.hpp"
#include "hashtbl.hpp"
#define HEADER_MAGIC 0x4D524257 // "WBRM"
#define COMPONENT_MAGIC 0x454C4946 // "FILE"
struct CacheHeader {
uint_32 magic;
uint_32 fileLen;
uint_32 dirStart;
uint_32 numComponents;
};
struct DirEntry {
char *name;
uint_32 start;
};
CacheOutFile::CacheOutFile()
/**********************/
{
_header = NULL;
_file = NULL;
_directory = new LList<DirEntry>;
}
CacheOutFile::~CacheOutFile()
/***********************/
{
if( _header != NULL ){
Close();
}
delete _directory;
}
WBool CacheOutFile::Open( char const *filename )
/******************************************/
{
WBool result;
result = FALSE;
_file = fopen( filename, "wb" );
if( _file != NULL ){
_header = new CacheHeader;
fwrite( &_header, sizeof( CacheHeader ), 1, _file );
_filePos = sizeof( CacheHeader );
_curEntry = NULL;
_numComponents = 0;
result = TRUE;
}
return result;
}
void CacheOutFile::Close()
/**********************/
{
DirEntry *current;
uint_32 magic = COMPONENT_MAGIC;
uint_32 dirLen;
int strLength;
// Write out the directory.
dirLen = 2*sizeof(uint_32);
fwrite( &magic, sizeof(uint_32), 1, _file );
fwrite( &dirLen, sizeof(uint_32), 1, _file );
current = _directory->First();
while( current != NULL ){
strLength = strlen( current->name ) + 1;
dirLen += strLength + 2*sizeof( uint_32 );
fwrite( &strLength, sizeof( uint_32 ), 1, _file );
fwrite( current->name, 1, strLength, _file );
fwrite( ¤t->start, sizeof( uint_32 ), 1, _file );
delete[] current->name;
delete current;
current = _directory->Next();
}
fseek( _file, _filePos + sizeof( uint_32 ), SEEK_SET );
fwrite( &dirLen, sizeof( uint_32 ), 1, _file );
_header->dirStart = _filePos;
_header->numComponents = _numComponents;
_header->magic = HEADER_MAGIC;
_header->fileLen = _filePos + dirLen;
fseek( _file, 0, SEEK_SET );
fwrite( _header, sizeof( CacheHeader ), 1, _file );
fclose( _file );
_file = NULL;
delete _header;
_header = NULL;
_directory->Clear();
}
void CacheOutFile::StartComponent( char const *name )
/*************************************************/
{
DirEntry *newEntry;
int nameLen;
uint_32 fileHeader[2] = { COMPONENT_MAGIC, 0x00000000 };
nameLen = strlen( name ) + 1;
newEntry = new DirEntry;
newEntry->name = new char[nameLen];
memcpy( newEntry->name, name, nameLen );
newEntry->start = _filePos;
_directory->Append( newEntry );
_curEntry = newEntry;
fwrite( fileHeader, sizeof( uint_32 ), 2, _file );
_filePos += 2*sizeof( uint_32 );
}
void CacheOutFile::EndComponent()
/*****************************/
{
uint_32 curPos;
uint_32 start;
uint_32 length;
if( _curEntry == NULL ){
return;
}
curPos = _filePos;
start = _curEntry->start;
length = curPos - start;
fseek( _file, start + sizeof( uint_32 ), SEEK_SET );
fwrite( &length, sizeof( uint_32 ), 1, _file );
fseek( _file, curPos, SEEK_SET );
_curEntry = NULL;
_numComponents += 1;
return;
}
void CacheOutFile::AddData( void *data, int length )
/**************************************************/
{
fwrite( data, 1, length, _file );
_filePos += length;
}
void CacheOutFile::AddDword( uint_32 dword, int compress )
/********************************************************/
{
if( compress ){
dword <<= 1;
if( dword <= 0xFFFF ){
fwrite( &dword, sizeof( uint_16 ), 1, _file );
_filePos += sizeof( uint_16 );
} else {
dword |= 1;
fwrite( &dword, sizeof( uint_32 ), 1, _file );
_filePos += sizeof( uint_32 );
}
} else {
fwrite( &dword, sizeof( uint_32 ), 1, _file );
_filePos += sizeof( uint_32 );
}
}
void CacheOutFile::AddByte( uint_8 byte )
/***************************************/
{
fputc( byte, _file );
_filePos++;
}
CacheInFile::CacheInFile()
/**************************/
{
_file = NULL;
_directory = new LList<DirEntry>;
}
CacheInFile::~CacheInFile()
/***************************/
{
if( _file != NULL ){
Close();
}
delete _directory;
}
WBool CacheInFile::Open( char const *filename )
/********************************************/
{
CacheHeader header;
uint_32 fileHeader[2];
uint_32 curOffset;
uint_32 dirLen;
FILE *file;
uint_32 strLength;
DirEntry *newEntry;
int i;
file = fopen( filename, "rb" );
if( file == NULL ){
goto error;
}
fread( &header, sizeof( CacheHeader ), 1, file );
if( header.magic != HEADER_MAGIC ){
goto error;
}
fseek( file, 0, SEEK_END );
_fileLen = ftell( file );
if( _fileLen != header.fileLen ){
goto error;
}
_numComponents = header.numComponents;
// Read in the directory file.
fseek( file, header.dirStart, SEEK_SET );
fread( fileHeader, sizeof( uint_32 ), 2, file );
if( fileHeader[0] != COMPONENT_MAGIC ){
goto error;
}
curOffset = 2*sizeof( uint_32 );
dirLen = fileHeader[1];
for( i=0; i<_numComponents; i++ ){
fread( &strLength, sizeof( uint_32 ), 1, file );
curOffset += strLength + 2*sizeof( uint_32 );
if( curOffset > dirLen ){
goto error;
}
newEntry = new DirEntry;
newEntry->name = new char[ strLength ];
fread( newEntry->name, 1, strLength, file );
fread( &newEntry->start, sizeof( uint_32 ), 1, file );
_directory->Append( newEntry );
}
_curEntry = NULL;
_file = file;
return TRUE;
error:
fclose( file );
return FALSE;
}
void CacheInFile::Close()
/************************/
{
DirEntry *current;
current = _directory->First();
while( current != NULL ){
delete[] current->name;
delete current;
current = _directory->Next();
}
_directory->Clear();
fclose( _file );
_file = NULL;
}
WBool CacheInFile::OpenComponent( char const *name )
/*************************************************/
{
DirEntry *current;
uint_32 fileHeader[2];
uint_32 filePos;
current = _directory->First();
while( current != NULL ){
if( strcmp( name, current->name ) == 0 ){
break;
}
current = _directory->Next();
}
if( current == NULL ){
goto error;
}
filePos = current->start;
fseek( _file, filePos, SEEK_SET );
fread( fileHeader, sizeof( uint_32 ), 2, _file );
if( fileHeader[0] != COMPONENT_MAGIC ){
goto error;
}
_curEnd = filePos + fileHeader[1];
_filePos = filePos + 2*sizeof( uint_32 );
_curEntry = current;
return TRUE;
error:
return FALSE;
}
void CacheInFile::CloseComponent()
/*********************************/
{
_curEntry = NULL;
}
int CacheInFile::ReadData( void *data, int length )
/****************************************************/
{
if( _curEntry == NULL ){
return 0;
}
if( _filePos + length > _curEnd ){
length = _curEnd-_filePos;
}
if( length > 0 ){
fread( data, 1, length, _file );
_filePos += length;
}
return length;
}
int CacheInFile::ReadDword( void *dword, int compress )
/*****************************************************/
{
if( _curEntry == NULL ){
return 0;
}
if( compress ){
uint_8 bytes[4];
uint_32 limit;
limit = _curEnd - _filePos;
if( limit < sizeof( uint_16 ) ){
return 0;
}
*((uint_32 *) bytes) = 0;
fread( &bytes[0], sizeof( uint_16 ), 1, _file );
if( bytes[0] % 2 ){
if( limit < sizeof( uint_32 ) ){
return 0;
}
fread( &bytes[2], sizeof( uint_16 ), 1, _file );
_filePos += sizeof( uint_32 );
} else {
_filePos += sizeof( uint_16 );
}
*((uint_32 *) dword) = *((uint_32 *) bytes) >> 1;
} else {
if( _filePos + sizeof( uint_32 ) > _curEnd ){
return 0;
}
fread( dword, sizeof( uint_32 ), 1, _file );
_filePos += sizeof( uint_32 );
}
return sizeof( uint_32 );
}
int CacheInFile::ReadByte( uint_8 &byte )
/***************************************/
{
if( _curEntry == NULL ){
return 0;
}
if( _filePos >= _curEnd ){
return 0;
}
byte = (uint_8) fgetc( _file );
_filePos++;
return 1;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?