?? tdbf.cpp
字號:
#include <stdio.h>
#include <io.h>
#include <dos.h>
#include <share.h>
#include <fcntl.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#include <sys\stat.h>
#include <sys\types.h>
#include "tdbf.h"
#define min(a, b) ((a) < (b)) ? (a) : (b)
#define max(a, b) ((a) > (b)) ? (a) : (b)
static const long XBASE_LOCK_OFFSET = 0x40000000L;
static const long CLIPPER_LOCK_OFFSET = 1000000000L;
static const long LOCK_FILE_LEN = 0x3FFFFFFFL;
static const int HEAD_LEN = 32;
static const int FIELD_LEN = 32;
TDBFField::TDBFField()
{
memset(Name, 0, sizeof(Name));
Type = 'C';
Width = 10;
Dec = 0;
Offset = 0;
}
TDBFField::TDBFField(const char * aName, unsigned char aType,
unsigned int aWidth, unsigned int aDec
)
{
if(aName)
{
strncpy(Name, aName, sizeof(Name));
strupr(Name);
}
Type = aType;
Width = aWidth;
Dec = aDec;
Offset = 0;
}
void TDBFField::SetField(const char * aName, unsigned char aType,
unsigned int aWidth, unsigned int aDec
)
{
if(aName)
{
strncpy(Name, aName, sizeof(Name));
strupr(Name);
}
Type = aType;
Width = aWidth;
Dec = aDec;
}
TDBF::TDBF()
{
m_lockWaitTime = 5;
m_fieldNumber = 0;
m_fieldInfo = 0;
m_databaseName = 0;
m_recordBuffer = 0;
m_openMode = 0;
m_errorCode = DBF_SUCCESS;
m_fp = -1;
m_lockType = ltNoLock;
memset((void *)&m_head, 0, sizeof(TDBFHead));
}
TDBF::~TDBF()
{
Close();
}
void TDBF::Open(const char * aFileName, int aMode)
{
int accessType = 0, shareType = 0, ownerType = 0;
unsigned int i;
m_databaseName = new char[strlen(aFileName) + 1];
strcpy(m_databaseName, aFileName);
m_openMode = aMode;
m_errorCode = DBF_SUCCESS;
TDBFFieldStruct fieldStruct;
if(aMode & ShareOpen)
{
shareType |= SH_DENYNONE;
m_openMode |= XbaseLock;
}
else // 獨占打開忽略所有加鎖選項
{
m_openMode &= ~(XbaseLock | ClipperLock | AutoReadLock | AutoWriteLock);
}
if(aMode & ReadOnly)
accessType |= O_RDONLY;
if(aMode & ReadWrite) {
accessType |= O_RDWR;
ownerType |= S_IREAD | S_IWRITE;
}
accessType |= O_BINARY;
if(aMode & ShareOpen)
m_fp = ::sopen(aFileName, accessType, shareType, ownerType);
else
m_fp = ::sopen(aFileName, accessType, SH_DENYRW, ownerType);
if(m_fp == -1)
{
m_errorCode = DBF_OPEN_FILE_ERROR;
return;
}
memset((void *)&m_head, 0, sizeof(TDBFHead));
ReadHead();
if(m_errorCode != DBF_SUCCESS)
{
Close();
return;
}
m_fieldNumber = m_head.RecordOffset / sizeof(TDBFFieldStruct);
if(m_fieldNumber <= 1)
{
m_errorCode = DBF_NOT_XBASE_FILE;
Close();
return;
}
m_fieldNumber --;
m_fieldInfo = new TDBFField[m_fieldNumber];
memset(m_fieldInfo, 0, sizeof(TDBFField) * m_fieldNumber);
::lseek(m_fp, HEAD_LEN, SEEK_SET);
for(i = 0; i < m_fieldNumber; i ++)
{
if(::read(m_fp, &fieldStruct, sizeof(TDBFFieldStruct)) != sizeof(TDBFFieldStruct))
{
m_errorCode = DBF_READ_FILE_ERROR;
Close();
return;
}
strncpy(m_fieldInfo[i].Name, fieldStruct.Name, sizeof(m_fieldInfo[i].Name));
m_fieldInfo[i].Type = fieldStruct.Type;
m_fieldInfo[i].Width = fieldStruct.Width;
m_fieldInfo[i].Dec = fieldStruct.Dec;
if(i == 0)
m_fieldInfo[i].Offset = 1;
else
m_fieldInfo[i].Offset = m_fieldInfo[i - 1].Offset + m_fieldInfo[i - 1].Width;
}
m_recordBuffer = new char[m_head.RecordWidth + 1];
memset(m_recordBuffer, 0, m_head.RecordWidth + 1);
}
void TDBF::Close()
{
if(m_fp != -1)
{
close(m_fp);
m_fp = -1;
}
if(m_databaseName != NULL)
{
delete (void *) m_databaseName;
m_databaseName = NULL;
}
if(m_recordBuffer != NULL)
{
delete m_recordBuffer;
m_recordBuffer = NULL;
}
if(m_fieldInfo != NULL)
{
delete m_fieldInfo;
m_fieldInfo = NULL;
}
m_fieldNumber = 0;
m_errorCode = DBF_SUCCESS;
}
void TDBF::ReadHead()
{
TDBFHead tempHead;
m_errorCode = DBF_SUCCESS;
if(::lseek(m_fp, 0L, SEEK_SET) == -1)
{
m_errorCode = DBF_READ_FILE_ERROR;
return;
}
if(::read(m_fp, &tempHead, sizeof(tempHead)) != sizeof(tempHead))
{
m_errorCode = DBF_READ_FILE_ERROR;
return;
}
if(tempHead.RecordOffset <= 0 || tempHead.RecordWidth <= 0)
{
m_errorCode = DBF_READ_FILE_ERROR;
return;
}
memcpy(&m_head, &tempHead, sizeof(m_head));
}
void TDBF::WriteHead()
{
time_t t;
struct tm tmlocal;
m_errorCode = DBF_SUCCESS;
t = ::time(&t);
tmlocal = *(::localtime(&t));
/*
if(m_head.RecordNumber < 0 || m_head.RecordNumber > 200000)
{
char buffer[200];
sprintf(buffer, "%d", m_head.RecordNumber);
m_errorCode = DBF_READ_FILE_ERROR;
return;
}
*/
m_head.Year = (unsigned char)(tmlocal.tm_year % 100);
m_head.Month = (unsigned char)(tmlocal.tm_mon + 1);
m_head.Day = (unsigned char)tmlocal.tm_mday;
if(::lseek(m_fp, 0L, SEEK_SET) == -1)
{
m_errorCode = DBF_READ_FILE_ERROR;
return;
}
if(::write(m_fp, &m_head, sizeof(m_head)) != sizeof(m_head))
m_errorCode = DBF_READ_FILE_ERROR;
}
void TDBF::ReadRecord(long rec)
{
m_errorCode = DBF_SUCCESS;
if(rec < 1L || rec > m_head.RecordNumber)
{
m_errorCode = DBF_RECORD_NUMBER_ERROR;
return;
}
if(m_openMode & AutoReadLock)
{
LockRecord(rec);
if(m_errorCode != DBF_SUCCESS)
return;
}
::lseek(m_fp, RecordOffset(rec), SEEK_SET);
if(::read(m_fp, m_recordBuffer, m_head.RecordWidth) != m_head.RecordWidth)
m_errorCode = DBF_READ_FILE_ERROR;
if(m_openMode & AutoReadLock)
UnlockRecord(rec);
}
void TDBF::WriteRecord(long rec)
{
m_errorCode = DBF_SUCCESS;
if(rec < 1L || rec > m_head.RecordNumber)
{
m_errorCode = DBF_RECORD_NUMBER_ERROR;
return;
}
if(m_lockType == ltNoLock && m_openMode & AutoWriteLock)
{
LockRecord(rec);
if(m_errorCode != DBF_SUCCESS)
return;
}
::lseek(m_fp, RecordOffset(rec), SEEK_SET);
if(::write(m_fp, m_recordBuffer, m_head.RecordWidth) != m_head.RecordWidth)
{
if(m_lockType == ltNoLock && m_openMode & AutoWriteLock)
UnlockRecord(rec);
m_errorCode = DBF_WRITE_FILE_ERROR;
return;
}
if(m_lockType == ltNoLock && m_openMode & AutoWriteLock)
UnlockRecord(rec);
}
void TDBF::AppendRecord()
{
m_errorCode = DBF_SUCCESS;
if(m_lockType == ltNoLock && m_openMode & AutoWriteLock)
{
LockFile();
if(m_errorCode != DBF_SUCCESS)
return;
}
ReadHead();
if(m_errorCode != DBF_SUCCESS)
goto __end;
if(::lseek(m_fp, RecordOffset(m_head.RecordNumber+1L), SEEK_SET) == -1)
{
m_errorCode = DBF_WRITE_FILE_ERROR;
goto __end;
}
if(::write(m_fp, m_recordBuffer, m_head.RecordWidth) != m_head.RecordWidth)
{
m_errorCode = DBF_WRITE_FILE_ERROR;
goto __end;
}
if(::write(m_fp, "\x1A", 1) != 1)
{
m_errorCode = DBF_WRITE_FILE_ERROR;
goto __end;
}
if(m_errorCode == DBF_SUCCESS)
{
m_head.RecordNumber ++;
WriteHead();
}
__end:
if(m_lockType == ltNoLock && m_openMode & AutoWriteLock)
UnlockFile();
}
void TDBF::DeleteRecord(long rec)
{
m_errorCode = DBF_SUCCESS;
ReadRecord(rec);
if(m_errorCode != DBF_SUCCESS)
return;
if(m_recordBuffer[0] == ' ')
{
m_recordBuffer[0] = '*';
WriteRecord(rec);
}
}
void TDBF::UndeleteRecord(long rec)
{
m_errorCode = DBF_SUCCESS;
if(rec < 1L || rec > m_head.RecordNumber) {
m_errorCode = DBF_RECORD_NUMBER_ERROR;
return;
}
ReadRecord(rec);
if(m_errorCode != DBF_SUCCESS)
return;
if(m_recordBuffer[0] == '*')
{
m_recordBuffer[0] = ' ';
WriteRecord(rec);
}
}
int TDBF::IsDelete()
{
m_errorCode = DBF_SUCCESS;
if(m_recordBuffer[0] == '*')
return 1;
return 0;
}
void TDBF::LockRecord(long rec)
{
long offset;
time_t t1, t2;
int result;
m_errorCode = DBF_SUCCESS;
if(rec < 1L || rec > m_head.RecordNumber)
{
m_errorCode = DBF_RECORD_NUMBER_ERROR;
return;
}
if(m_openMode & XbaseLock)
offset = XBASE_LOCK_OFFSET + RecordOffset(rec);
else
offset = CLIPPER_LOCK_OFFSET + rec;
time(&t1);
do
{
if(m_openMode & XbaseLock)
result = lock(m_fp, offset, (long) m_head.RecordWidth);
else
result = lock(m_fp, offset, 1L);
time(&t2);
} while(difftime(t2, t1) <= m_lockWaitTime && result != 0);
if(result != 0)
m_errorCode = DBF_LOCK_RECORD_ERROR;
}
void TDBF::UnlockRecord(long rec)
{
long offset;
int result;
m_errorCode = DBF_SUCCESS;
if(rec < 1L || rec > m_head.RecordNumber)
{
m_errorCode = DBF_RECORD_NUMBER_ERROR;
return;
}
if(m_openMode & XbaseLock)
offset = XBASE_LOCK_OFFSET + RecordOffset(rec);
else
offset = CLIPPER_LOCK_OFFSET + rec;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -