⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tddatabase.cpp

📁 This is the main project file for VC++ projects generated using an Application Wizard. It cont
💻 CPP
字号:
#include "tddatabase.h"

const char* TDDB_ErrorCodeToString( int iErrorCode )
{
	switch( iErrorCode ){
		case TDDB_OK:
			return "TDDB_OK";

		case TDDBERR_READ_ERROR:
			return "TDDBERR_READ_ERROR";

		case TDDBERR_COULD_NOT_OPEN:
			return "TDDBERR_COULD_NOT_OPEN";

		case TDDBERR_NO_COLUMNS	:
			return "TDDBERR_NO_COLUMNS";

		case TDDBERR_FILE_NOT_FOUND:
			return "TDDBERR_FILE_NOT_FOUND";

		case TDDBERR_WRITE_ERROR	:
			return "TDDBERR_WRITE_ERROR";

		case TDDBERR_PREPARE_ERROR:
			return "TDDBERR_PREPARE_ERROR";

		case TDDBERR_SEEK_ERROR:
			return "TDDBERR_SEEK_ERROR";

		case TDDBERR_DATABASE_NOT_OPEN:
			return "TDDBERR_DATABASE_NOT_OPEN";

		case TDDBERR_INVALID_RECORD:
			return "TDDBERR_INVALID_RECORD";

		default:
			return "Unrecognised error code";
	}
}

CTDDatabase::CTDDatabase(void)
: _lpFile(0)
, _lFirstRecord(-1)
{
	_tableDef.Columns = 0;
	_tableDef.iColumnCount = 0;
}

CTDDatabase::~CTDDatabase(void)
{
	ResetEverything();
}

int CTDDatabase::Open( const char* szFileName )
{
	ResetEverything();

	//check if file exists
	_lpFile = fopen( szFileName, "r");
	if( _lpFile == 0 ){
		return TDDBERR_FILE_NOT_FOUND;
	}

	
	//attemp to open the file
	_lpFile = fopen( szFileName, "r+" );
	if( _lpFile == 0 )
		return TDDBERR_COULD_NOT_OPEN;
	

	//read in the table definition
	//read in the number of columns
	if( fread( &(_tableDef.iColumnCount) , sizeof(_tableDef.iColumnCount), 1, _lpFile) != 1){
		ResetEverything();
		return TDDBERR_READ_ERROR;
	}
	//allocate enough space for columns
	_tableDef.Columns = new TDDBColumn[_tableDef.iColumnCount];
	//read in all the columns
	for( unsigned int i = 0; i < _tableDef.iColumnCount; i++ ){
		//read in the column name
		if( fread(&(_tableDef.Columns[i].szName), TDDB_MAX_COLUMN_NAME, 1, _lpFile) != 1 ){
			ResetEverything();
			return TDDBERR_READ_ERROR;
		}
		//read in the column size in bytes
		if( fread(&(_tableDef.Columns[i].iBytes), sizeof( _tableDef.Columns[i].iBytes ), 1, _lpFile) != 1){
			ResetEverything();
			return TDDBERR_READ_ERROR;
		}
	}

	//save where the first record is
	_lFirstRecord = ftell( _lpFile );

	return TDDB_OK;

}

int CTDDatabase::Close( void )
{
	ResetEverything();
	return TDDB_OK;
}

int CTDDatabase::CreateNew( const char* szFileName, TDDBTable* tableDef )
{
	//attempt to open new file
	FILE* lpNewDBFile = fopen( szFileName, "w" );
	if( lpNewDBFile == 0 )
		return TDDBERR_COULD_NOT_OPEN;

	//write the table def header
	if( fwrite( &(tableDef->iColumnCount), sizeof(tableDef->iColumnCount), 1, lpNewDBFile ) != 1)
		return TDDBERR_WRITE_ERROR;
	for( unsigned int i = 0; i < tableDef->iColumnCount; i++ ){
		//write column name
		if( fwrite(&(tableDef->Columns[i].szName), TDDB_MAX_COLUMN_NAME, 1, lpNewDBFile) != 1 )
			return TDDBERR_WRITE_ERROR;
		//write column size
		if( fwrite(&(tableDef->Columns[i].iBytes), sizeof(tableDef->Columns[i].iBytes), 1, lpNewDBFile) != 1 )
			return TDDBERR_WRITE_ERROR;
	}

	fclose( lpNewDBFile );
	return TDDB_OK;
	
}

unsigned int CTDDatabase::GetRecordSizeInBytes()
{
	if( !IsOpen() )
		return 0;

	if (!(_tableDef.iColumnCount > 0))
		return 0;

	unsigned int iByteCount = sizeof(TDR_RECORD_HEADER);
	for( unsigned int i = 0; i < _tableDef.iColumnCount; i++ ){
		iByteCount += _tableDef.Columns[i].iBytes;
	}

	return iByteCount;
}

int CTDDatabase::ResetEverything( void )
{
	//if anything needs to be cleaned up
	int iRet = (( _lpFile != 0 ) || ( _tableDef.Columns != 0))? 1 : 0 ;

	if( _lpFile != 0 ){
		fclose( _lpFile );
		_lpFile = 0;
	}

	_lFirstRecord = -1;

	if( _tableDef.Columns != 0 ){
		delete[] _tableDef.Columns;
		_tableDef.Columns = 0;
	}

	_tableDef.iColumnCount = 0;

	return iRet;

}

CTDRecord CTDDatabase::CreateRecord( void )
{
	if( !IsOpen() )
		return CTDRecord ( 0, 0 );

	return CTDRecord( &_tableDef, GetRecordSizeInBytes() );
}

int CTDDatabase::GetRecord( CTDRecord* recordOut, unsigned int iIndex )
{
	if( !IsOpen() )
		return TDDBERR_DATABASE_NOT_OPEN;

	if( !recordOut->IsValid() )
		return TDDBERR_INVALID_RECORD;

	//find the record's byte offset in the database file
	long lOffset = GetRecordOffset( iIndex );
	//read up to the offset
	if( fseek( _lpFile, lOffset, SEEK_SET ) != 0 )
		return TDDBERR_SEEK_ERROR;
	//read the record from the file into the record object
	if( fread( (void*)recordOut->_lpBuffer, recordOut->_iBytes, 1, _lpFile ) != 1 )
		return TDDBERR_READ_ERROR;

	return TDDB_OK;
}

int CTDDatabase::SetRecord( CTDRecord* recordIn, unsigned int iIndex )
{
	if( !IsOpen() )
		return TDDBERR_DATABASE_NOT_OPEN;

    if( !recordIn->IsValid() )
		return TDDBERR_INVALID_RECORD;

	//find the record's byte offset in the database file
	long lOffset = GetRecordOffset( iIndex );
	//read up to the offset
	if( fseek( _lpFile, lOffset, SEEK_SET ) != 0 )
		return TDDBERR_SEEK_ERROR;
	//overwrite the previous record
	if( fwrite( (const void*)recordIn->_lpBuffer, recordIn->_iBytes, 1, _lpFile ) != 1 )
		return TDDBERR_WRITE_ERROR;

	return TDDB_OK;
}

int CTDDatabase::AddRecord( CTDRecord* recordIn )
{
	if( !IsOpen() )
		return TDDBERR_DATABASE_NOT_OPEN;

	if( !recordIn->IsValid() )
		return TDDBERR_INVALID_RECORD;

	//find the first deleted record
	unsigned int iRecordCount;
	unsigned int iRet = GetRecordCount( &iRecordCount );
	if( iRet != TDDB_OK )
		return iRet;
	unsigned int iRecordSize = GetRecordSizeInBytes();
	void* vpRecordBuffer = (void*) new char[iRecordSize];

	//cycle through all the records
	if( fseek( _lpFile, _lFirstRecord, SEEK_SET ) != 0 ){
		delete vpRecordBuffer;
		return TDDBERR_SEEK_ERROR;
	}

	for( unsigned int i = 0; i < iRecordCount; i++ ){
		long lRecordPosition = ftell( _lpFile );

		//read in the record
		if( fread( vpRecordBuffer, iRecordSize, 1, _lpFile ) != 1 ){
			delete[] vpRecordBuffer;
			return TDDBERR_READ_ERROR;
		}

		//if the record just read is marked as deleted
		if( *((TDR_RECORD_HEADER*)vpRecordBuffer) & TDRH_MASK_DELETED ){
			//rewind and overwrite it
			fseek( _lpFile, lRecordPosition, SEEK_SET );
			if( fwrite( recordIn->_lpBuffer, recordIn->_iBytes, 1, _lpFile ) != 1 ){
				delete[] vpRecordBuffer;
				return TDDBERR_WRITE_ERROR;
			} else {
				return TDDB_OK;
			}
		}
	}

	//if we reached EOF and didn't find a deleted record, write the record at the end
	if( fseek( _lpFile, 0, SEEK_CUR ) != 0 ){
		delete[] vpRecordBuffer;
		return TDDBERR_WRITE_ERROR;
	}

	if( fwrite( recordIn->_lpBuffer, recordIn->_iBytes, 1, _lpFile ) != 1 ){
		delete[] vpRecordBuffer;
		return TDDBERR_WRITE_ERROR;
	}

	delete[] vpRecordBuffer;
	return TDDB_OK;
}

int CTDDatabase::DeleteRecord( unsigned int iIndex )
{
	long lOffset = GetRecordOffset( iIndex );
	TDR_RECORD_HEADER rh;

	//read in the header
	if( fread( (void*) &rh, sizeof(rh), 1, _lpFile ) != 1 )
		return TDDBERR_READ_ERROR;

	//set the deleted flag
	rh |= TDRH_MASK_DELETED;

	//put the header back
	if( fseek( _lpFile, lOffset, SEEK_SET ) != 0 )
		return TDDBERR_SEEK_ERROR;
	if( fwrite( (void*) &rh, sizeof(rh), 1, _lpFile ) != 1 )
		return TDDBERR_WRITE_ERROR;

	return TDDB_OK;
}

int CTDDatabase::GetRecordCount( unsigned int* lpiCount )
{
	if( !IsOpen() )
		return TDDBERR_DATABASE_NOT_OPEN;

	if( fseek( _lpFile, 0, SEEK_END ) != 0 )
		return TDDBERR_SEEK_ERROR;

	long lBytesInFile = ftell( _lpFile );
	unsigned int iRecordSize = GetRecordSizeInBytes();

	*lpiCount = (unsigned int)((lBytesInFile - _lFirstRecord) / iRecordSize);
	return TDDB_OK;
}

int CTDDatabase::GetValidRecordCount( unsigned int* lpiCount )
{
	if( !IsOpen() )
		return TDDBERR_DATABASE_NOT_OPEN;

	if( fseek( _lpFile, _lFirstRecord, SEEK_SET ) != 0 )
		return TDDBERR_SEEK_ERROR;

	unsigned int iCount = 0;
	unsigned int iRecordSize = GetRecordSizeInBytes();
	void* vpRecordBuffer = (void*) new char[iRecordSize];
	//cycle through every record
	while( fread( vpRecordBuffer, iRecordSize, 1, _lpFile ) == 1 ){
		// if the record isn't deleted, increment
		if( !(*((TDR_RECORD_HEADER*)vpRecordBuffer) & TDRH_MASK_DELETED) )
			iCount++;
	}

	*lpiCount = iCount;
	delete[] vpRecordBuffer;
	return TDDB_OK;
}

long CTDDatabase::GetRecordOffset( unsigned int iIndex )
{
	return ( _lFirstRecord + ((long)iIndex * (long)GetRecordSizeInBytes()) );
}

int CTDDatabase::IsOpen( void )
{
	return ( _lpFile != 0 );
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -