📄 dbfop.cpp
字号:
/************************************************************************
DBFOP for C++ V1.00 ,1995.1.10
Develop by John,Liao
Modified by Zhanghao. 1998.05.18
This Module include the C++ headfile dbfop.hpp,
and C++ resource file dbfop.cpp.
This module is develop for use DBF(DBASEIII,DBASEII,MFOXBASE,FOXPRO 2.x)
and IDX(MFOXBASE).but use IDX only allow read or change the field that
isn't key word.
Support netware share .flielock,fileunlock,recordlock,recordunlock.
*************************************************************************/
/* -----------------------------------------------------------------------
The class DBF is interface to custom,all function that given
can be invoked by use the class DBF.
------------------------------------------------------------------------
1995.7.29 Change file option fxxx to xxx like _fsopen replace with sopen
1995.7.31 Change dowith option when type='N'
1995.7.31 Add option DBF::append(),DBF::clear();
1998.5.18 Add Foxpro 2.x DBF process.
-------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <share.h>
#include <string.h>
#include <io.h>
#include <dos.h>
#include <fcntl.h>
#include <sys\stat.h>
#include <share.h>
#include <ctype.h>
#include "dbfop.hpp"
static INT2 ccc(CHAR *,INT2,INT2);
INT2 ccc(CHAR * ptsr,INT2 len,INT2 bit)
{
CHAR temp1[30],temp11[30],i1;
CHAR temp2[30],temp22[30],i2;
INT2 tempi,i;
CHAR * ps,*ps1;
for(ps1=ptsr;(*ps1==' ')&&(*ps1!='\x0');ps1++);
ps=strchr(ps1,'.');
if(ps==NULL){ // NOT HAVE '.'
strcpy(temp1,ps1);
temp2[0]='\x0';
}else{
*ps='\x0';
strcpy(temp1,ps1);
ps++;
strcpy(temp2,ps);
}
i1=(short)(len-(bit?(bit+1):0));
if((short)strlen(temp1) > i1){
strncpy(temp11,temp1,i1);
temp11[i1]='\x0';
}else{
tempi=(INT2)(i1-strlen(temp1));
for(i=0;i<tempi;i++) temp11[i]=' ';
strcpy(temp11+tempi,temp1);
}
// ------------------------------------------
if(bit>0){
if((short)strlen(temp2) > bit){
strncpy(temp22,temp2,bit);
temp22[bit]='\x0';
}else{
i2=(short)strlen(temp2);
tempi=(INT2)(bit-strlen(temp2));
strcpy(temp22,temp2);
for(i=0;i<tempi;i++) (temp22+i2)[i]='0';
temp22[bit]='\x0';
}
}
strcpy(ptsr,temp11);
if(bit!=0){
strcat(ptsr,".");
strcat(ptsr,temp22);
}
return 0;
}
INT2 IDX_BLOCK::skip()
{
if(curp>=(INT2)items-1){
return -2;
}
curp++;
return 0;
}
INT2 IDX_BLOCK::find(CHAR * key)
{
INT2 compi=keylen;
CHAR *p;
INT2 RetCode,i;
if((short)strlen(key)<keylen)
compi=(INT2)strlen(key);
for(i=0,p=buff+12;i<items;i++,p+=keylen+4){
RetCode=(INT2)strncmp(key,p,compi);
if(RetCode==0) // Founded this key
if(flag>=2){ // .and. this is a leaf or leaf&root node
curp=i;
return 0; // Founded ,OK return to master
}else{ // .and. this is a frame or root node
curp=i;
return -10; // This is a ROOT,Maybe in gaven BLOCK
}
if(RetCode<0){ //if the key < curent key in idx file
if(flag<2){ //and this is FRAME or ROOT node
curp=i; //in FRAME or ROOT node key is MAXKEY in given node
return -10;//This is a ROOT,Maybe in gaven BLOCK
}
}
}
return -3; // Maybe in NextBlock
}
IDX::IDX()
{
Installed=0;
//fp=NULL;
handle=-1;
rootpos=blocks=0l;
key_len=0;
return ;
}
IDX::~IDX()
{
if(this->handle!=-1){
close(handle);
handle=-1;
}
}
// open function open the idx file
INT2 IDX::open(CHAR * filename)
{
CHAR buff[30];
// fp=_fsopen(filename,"rb",SH_DENYNONE);
// change by liaoj int 1999.3.22
handle=(INT2)sopen(filename,O_RDONLY|O_BINARY|O_DENYNONE,SH_DENYNONE,S_IREAD);
/*
handle=sopen(filename,O_RDWR|O_BINARY|O_DENYNONE,
SH_DENYNONE,S_IREAD|S_IWRITE);
*/
// if(fp==NULL) return -1;
if(handle==-1) return -1;
if(lseek(handle,0,SEEK_SET)!=0) return -1;
if(read(handle,buff,30)!=30) return -1;
rootpos=*(UINT4 *)buff;
blocks=*(UINT4 *)(buff+8);
key_len=*(INT2 *)(buff+12);
block.SetKeyLen(key_len);
block.ReadBlock(this->handle,rootpos);
while(block.GetFlag()<2){
block.ReadBlock(this->handle,block.GetResult());
}
GoHome();
return 0;
}
INT2 IDX::Prev()
{
UINT4 PrevBlock;
if(block.Prev()!=0){
PrevBlock=block.GetPrev();
if(PrevBlock==0xffffffffl){
return -1;
}
block.ReadBlock(this->handle,(INT4)PrevBlock);
block.End();
}
return 0;
}
INT2 IDX::Next()
{
UINT4 NextBlock;
if(block.Next()!=0){ // Is already in the last node in this block
NextBlock=block.GetNext();
if(NextBlock==0xffffffffl){
return -2;
}
block.ReadBlock(this->handle,(INT4)NextBlock);
block.Home();
}
return 0;
}
INT2 IDX::Find(CHAR * key)
{
INT2 RetCode;
block.ReadBlock(this->handle,rootpos);
for(;;){
RetCode=block.find(key);
switch(RetCode){
case 0:
return 0;
case -1:
return -1;
case -2:
if(block.GetPrev()==(UINT4)0xffffffffl){
return -1;
}else{
block.ReadBlock(this->handle,block.GetPrev());
}
break;
case -3:
if(block.GetNext()==(UINT4)0xffffffffl){
return -1;
}else {
block.ReadBlock(this->handle,block.GetNext());
}
break;
case -10:
block.ReadBlock(this->handle,block.GetResult());
break;
default:
// -------------------------------------------------
// Fatal Error :: return code is not allow
// in class IDX_BLOCK::find(CHAR * );
// -------------------------------------------------
break;
}
}
}
INT2 IDX::Skip()
{
return Next();
}
INT2 IDX::GoHome()
{
while(block.GetPrev()!=(UINT4)0xffffffffl){
block.ReadBlock(this->handle,block.GetPrev());
};
block.Home();
return 0;
}
INT2 IDX::GoEnd()
{
while(block.GetNext()!=(UINT4)0xffffffffl){
block.ReadBlock(this->handle,block.GetNext());
};
block.End();
return 0;
}
UINT4 IDX_BLOCK::GetResult()
{
CHAR tf[5];
CHAR * p=buff+12+curp*(keylen+4);
p+=keylen;
tf[3]=p[0];tf[2]=p[1];tf[1]=p[2];tf[0]=p[3];
return *(UINT4 * )tf;
}
//INT2 IDX_BLOCK::ReadBlock(FILE * fp,UINT4 pos)
INT2 IDX_BLOCK::ReadBlock(INT2 handle,UINT4 pos)
{
// fseek(fp,pos,SEEK_SET);
lseek(handle,pos,SEEK_SET);
// fread(buff,512l,1,fp);
read(handle,buff,512);
flag=buff[0];
count=buff[1];
items=buff[2];
prev=*(UINT4 *)(buff+4);
next=*(UINT4 *)(buff+8);
curp=0;
return 0;
}
//------------------Next is DBF ----------------------
DBF::DBF()
{
Installed=0;
First=NULL;
pIDX=NULL;
handle=-1;
buff=NULL;
// ---------------------------------
SwapBuffer=NULL;
MaxRecNum=0;
CurRecNum=0;
// --------------------------------
current_recno=record_no=0l;
record_len=0;
Name[0]='\x0';
changeflag=0;
m_errno=0;
fieldvalue=NULL;
pFIELD = NULL;
}
DBF::~DBF()
{
if(First!=NULL){
delete First;
First=NULL;
}
if(SwapBuffer!=NULL) delete SwapBuffer;
SwapBuffer=NULL;
MaxRecNum=0;
CurRecNum=0;
if(pIDX!=NULL){
delete First;
pIDX=NULL;
}
if(handle!=-1){ // this
::close(handle);
handle=-1;
}
if(buff!=NULL){
delete buff;
buff=NULL;
}
if(fieldvalue!=NULL){
delete fieldvalue;
fieldvalue=NULL;
}
return;
}
INT2 DBF::Clear()
{
memset(buff,' ',record_len);
return 0;
}
INT2 DBF::AppendBlank()
{
CHAR tempbuf[100];
UINT4 temp_recno;
INT2 i;
INT4 offset;
if(!Installed){ // Not open this file
m_errno=ClassNotInit;
return ClassNotInit;
}
if(lseek(handle,0l,SEEK_SET)!=0){
m_errno=SeekFileError;
return SeekFileError;
}
if(read(handle,tempbuf,8)!=8){
m_errno=ReadFileError;
return ReadFileError;
}
temp_recno=++(*(UINT4*)(tempbuf+4));// recordnum+1;
if(lseek(handle,0l,SEEK_SET)!=0){
m_errno=SeekFileError;
return m_errno;
}
if(write(handle,tempbuf,8)!=8){
m_errno=WriteFileError;
return m_errno;
}
offset=(INT4)head_len+(temp_recno-1l)*record_len;
lseek(handle,offset,SEEK_SET);
for(i=0;i<(short)record_len;i++) // fputc(0x20,fp); // FILL BLANK
write(handle," ",1);
write(handle,"\x1a",1);
this->ReOpen();
this->GoTo(temp_recno);
return 0;
}
INT2 DBF::Append()
{
CHAR tempbuf[100];
UINT4 temp_recno;
INT4 offset;
if(!Installed){ // Not open this file
errno=ClassNotInit;
return ClassNotInit;
}
if(lseek(handle,0l,SEEK_SET)!=0){
errno=SeekFileError;
return SeekFileError;
}
if(read(handle,tempbuf,8)!=8){
errno=ReadFileError;
return m_errno;
}
temp_recno=++(*(UINT4*)(tempbuf+4));// recordnum+1;
if(lseek(handle,0l,SEEK_SET)!=0){
errno=SeekFileError;
return m_errno;
}
if(write(handle,tempbuf,8)!=8){
errno=WriteFileError;
return m_errno;
}
offset=(INT4)head_len+(temp_recno-1l)*record_len;
if(lseek(handle,offset,SEEK_SET)!=offset){
errno=SeekFileError;
return m_errno;
}
write(handle,buff,(UINT2)record_len);
write(handle,"\x1a",1);
this->ReOpen();
this->GoTo(temp_recno);
return 0;
}
INT2 DBF::dbf_wbuff()
{
//CHAR tempbuf[100];
INT4 offset;
offset=(INT4)head_len+(current_recno-1l)*record_len;
if(current_recno<=0){
errno=RecordOutOfRange;
return m_errno;
}
if(changeflag==0){
errno=DBFOK;
return DBFOK;
}
if(lseek(handle,offset,SEEK_SET)!=offset){
errno=SeekFileError;
return m_errno;
}
if((UINT2)write(handle,buff,(UINT2)record_len)!=(UINT2)record_len){
errno=WriteFileError;
return m_errno;
}
errno=DBFOK;
return DBFOK;
}
INT2 DBF::dbf_buff()
{
INT4 offset=(INT4)head_len+(current_recno-1l)*record_len;
if(current_recno<=0){
errno=RecordOutOfRange;
return m_errno;
}
if(lseek(handle,offset,SEEK_SET)!=offset){
errno=SeekFileError;
return m_errno;
}
if(::eof(handle)){
errno=SeekFileError;
return m_errno;
}
if((UINT2)read(handle,buff,(UINT2)record_len)!=(UINT2)record_len){
errno=ReadFileError;
return m_errno;
}
changeflag=0;
errno=0;
return 0;
}
INT2 DBF::Zap()
{
CHAR tempbuf[100];
if(!Installed){ // Not open this file
errno=ClassNotInit;
return m_errno;
}
lseek(handle,0l,SEEK_SET);
//if(fread(tempbuf,32l,1l,fp)!=1){
if(read(handle,tempbuf,32)!=32){
this->Close();
errno=NotDBFFile;
return m_errno;
}
*(UINT4 *)(tempbuf+4)=0l; // record_no
if(chsize(handle,head_len)!=0){
// ------------------------
errno=ChsizeFileError;
return m_errno;
}
lseek(handle,0l,SEEK_SET);
if(write(handle,tempbuf,32)!=32){
//this->close();
errno=WriteFileError;
return WriteFileError;
}
lseek(handle,0l,SEEK_END);
write(handle,"\x1a\x0",2);
MaxRecNum=0;
CurRecNum=0;
lock_flag=0;
ReOpen();
m_errno=DBFOK;
return m_errno;
}
INT2 DBF::Open(CHAR * filename,INT2 OpenMode_Par,INT2 DBFType_Par)
{
CHAR tempbuf[100];
INT2 i,j,FieldOffset;
struct FIELD * tpf;
if(Installed){
this->Close();
}
strcpy(Name,filename);
OpenMode=OpenMode_Par;
DBFType=DBFType_Par;
if(OpenMode==ReadWrite){
handle=(INT2)sopen(Name,O_RDWR|O_BINARY|O_DENYNONE,SH_DENYNONE,S_IREAD|S_IWRITE);
}else{
handle=(INT2)sopen(Name,O_RDONLY|O_BINARY|O_DENYNONE,SH_DENYNONE,S_IREAD);
}
if(handle==-1){
errno=FileOpenFailure;
return m_errno;
}
lseek(handle,0l,SEEK_SET);
if(read(handle,tempbuf,32)!=32){
this->Close();
errno=ReadFileError;
return m_errno;
}
record_no=*(UINT4 *)(tempbuf+4);
head_len=*(UINT2 *)(tempbuf+8);
//head_len=tempbuf[8];
//head_len+=tempbuf[9]<<8;
record_len=*(UINT2*)(tempbuf+10);
fieldnum=(INT2)((head_len)/32-1);
// need automatic detect the dbf file type is foxbase or clipper
if(DBFType==AutoDetect){
if((head_len-1)%32==0)
DBFType=Foxbase;
else
DBFType=Clipper;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -