home *** CD-ROM | disk | FTP | other *** search
- #include <ctype.h>
- #include <WStr.h>
- #include <WFile.h>
- #ifdef MAJORBBS
- extern "C"
- {
- #include <gcomm.h>
- }
- #endif
- #pragma hdrstop
-
- // copyright (c) 1992, 1993 by Paul Wheaton
-
- //.parse
-
- void LowLevelFile::InternalInit(int BufSize)
- {
- if (FilePointer==NULL) FatalError("LLFileCtor2:"+String120(GivenFileName));
- Open=True;
- if ((BufSize==BUFSIZ)||(BufSize==0)) Buf=NULL;
- else
- {
- #ifdef MAJORBBS
- Buf=(char*)malloc(BufSize);
- if (Buf!=NULL) setvbuf(FilePointer,Buf,_IOFBF,size_t(BufSize));
- #else
- Buf=new char[BufSize];
- if (Buf==NULL) Beep();
- else setvbuf(FilePointer,Buf,_IOFBF,size_t(BufSize));
- #endif
- }
- }
-
- //.parse
-
- LowLevelFile::LowLevelFile(const char* FileName, const char* Mode,int BufSize)
- {
- GivenFileName=(char*)FileName;
- if (!FileExists(FileName))
- {
- FILE* P=fopen(FileName,"wb");
- if (P==NULL) FatalError("LLFileCtor1:"+String120(FileName));
- fclose(P);
- }
- FilePointer=fopen(FileName,Mode);
- InternalInit(BufSize);
- }
-
- /*
-
- LowLevelFile::LowLevelFile(const char* FileName,FileShareType FS,
- const char* Mode,int BufSize)
- {
- GivenFileName=(char*)FileName;
- if (!FileExists(FileName))
- {
- FILE* P=fsopen(FileName,"wb");
- if (P==NULL) FatalError("LLFileCtor1:"+String120(FileName));
- fclose(P);
- }
- FilePointer=fsopen(FileName,Mode);
- InternalInit(BufSize);
- }
- */
-
- //.parse
-
- void LowLevelFile::Close()
- {
- if (Open)
- {
- Open=False;
- fclose(FilePointer);
- #ifdef MAJORBBS
- if (Buf) free(Buf);
- #else
- if (Buf) delete Buf;
- #endif
- }
- }
-
- //.parse
-
- long LowLevelFile::Size()
- {
- long P=CurPos();
- Flush();
- long S=filelength(fileno(FilePointer));
- Seek(P);
- return(S);
- }
-
- //.parse
-
- File::File(const char* FileName,Bool Mode,int BufSize):
- LowLevelFile(FileName,((Mode==ReadOnly)?("rb"):("r+b")),BufSize)
- {}
-
- //.parse
-
- Bool File::Read(void *Buffer,int Size)
- {
- char* P=(char*)Buffer;
- Bool ReturnVal=True;
- while((ReturnVal==True)&&(Size>0))
- {
- int X=Min(Size,512);
- ReturnVal=(fread(P,X,1,FilePointer)==1);
- Size-=X;
- P+=X;
- }
- return ReturnVal;
- }
-
- //.parse
-
- void File::Write(const void *Buffer,int Size)
- {
- const char* P=(const char*)Buffer;
- while(Size>0)
- {
- int X=Min(Size,512);
- fwrite(P,X,1,FilePointer);
- Size-=X;
- P+=X;
- }
- }
-
- //.parse
-
- Bool File::Read(ByteVector& BV,int Size)
- {
- if (BV.Capacity()<Size) BV.ReAlloc(Size);
- BV.Len=Size;
- return Read((void*)BV.P,Size);
- }
-
- //.parse
-
- void TextFile::Write(const char* S)
- {
- if (!Started)
- {
- Started=True;
- SeekEOF();
- }
- #ifdef MAJORBBS
- /*
- while (*S)
- {
- if (fputc(*S,FilePointer)==EOF) FatalError("tfwrite");
- S++;
- }
- */
- if (fprintf(FilePointer,S)<0) FatalError("tfwrite");
- #else
- if (fputs(S,FilePointer)<0) FatalError("tfwrite");
- #endif
- }
-
- void TextFile::WriteLine(const char* S)
- {
- Write(S);
- Write("\n");
- }
-
- //.parse
-
- Bool TextFile::Read(char* S)
- {
- if (!Started)
- {
- Started=True;
- SeekBOF();
- }
- if (fgets(S,MaxInt,FilePointer)!=NULL)
- {
- int L=strlen(S);
- if (L>0)
- {
- if (S[L-1]=='\n') S[L-1]='\0';
- }
- else S[0]='\0';
- return(True);
- }
- else
- {
- S[0]='\0';
- return(False);
- }
- }
-
- //.parse
-
- void DeleteFile(const char* FileName)
- {
- if (FileExists(FileName)) unlink(FileName);
- }
-
- //.parse
-
- void FileCopying(File& DFile, File& SFile, long Size)
- {
- const BufSize=512;
- Byte Buf[BufSize];
- while (Size>0)
- {
- long Chunk=Min(Size,long(BufSize));
- SFile.Read(&Buf[0],int(Chunk));
- DFile.Write(&Buf[0],int(Chunk));
- Size-=Chunk;
- }
- }
-
- //.parse
-
- Word CRC(File& F)
- {
- F.Seek(0);
- return CRC(F,F.Size());
- }
-
- const Word CRCMask=0x1021; // crc-ccitt mask
-
- Word CRC(File& F,long FSize)
- {
- Word X=0;
- long I;
- For(I,FSize)
- {
- char Ch;
- F.ReadThing(Ch);
- int Z=Ch;
- Z<<=8;
- int J;
- For(J,8)
- {
- if((X ^ Z) & 0x8000) X=(X<<1)^CRCMask;
- else X<<=1;
- Z<<=1;
- }
- }
- return X;
- }
-
- //.parse
-
- #ifdef MAJORBBS
-
- Bool FileExists(const char* Name)
- {
- fndblk FF;
- Bool Found=(fnd1st(&FF,(char*)Name,0)==1);
- return Found;
- }
-
- long DiskSpace(const char Drive)
- {
- int D;
- if (Drive=='.') D=0;
- else D=((int(Drive)+1)-int('A')); // BC byte math not trustworthy
- long X=getdfre(D)/1024;
- return X;
- }
-
- #else
-
- char CurDiskDrive()
- {
- unsigned D;
- _dos_getdrive(&D);
- char C=char(D+'A'-1);
- return C;
- }
-
- long DiskSpace(const char Drive)
- {
- char D;
- if (Drive=='.') D='\0';
- else D=char((int(toupper(Drive))+1)-int('A')); // BC byte math not trustworthy
- struct diskfree_t F;
- long X=0;
- if (_dos_getdiskfree(D,&F)==0)
- {
- X=long(F.avail_clusters)*long(F.bytes_per_sector)*long(F.sectors_per_cluster);
- X/=1024;
- }
- return X;
- }
-
- #endif
-
- //.parse
-
- long FileSize(const char* FileName)
- {
- long X=0;
- if (FileExists(FileName))
- {
- File F(FileName,ReadOnly);
- X=F.Size();
- }
- return X;
- }
-
- //.parse
-
- void CopyFile(const char* DestFile, const char* SourceFile)
- {
- DeleteFile(DestFile);
- File DF(DestFile);
- File SF(SourceFile,ReadOnly);
- FileCopying(DF,SF,SF.Size());
- }
-
- //.parse
-
- RecFile::RecFile(const char* FileName,int RecordSize,Bool Mode,int BufSize):
- LowLevelFile(FileName,((Mode==ReadOnly)?("rb"):("r+b")),BufSize)
- {
- RecSize=RecordSize;
- }
-
- //.parse
-
- Bool RecFile::Read(void *Buffer)
- {
- return (fread(Buffer,RecSize,1,FilePointer)==1);
- }
-
- //.parse
-
- void RecFile::Write(const void *Buffer)
- {
- fwrite(Buffer,RecSize,1,FilePointer);
- }
-
- //.parse
-
- Bool RecFile::Read(void *Buffer,int S)
- {
- return (fread(Buffer,RecSize*S,1,FilePointer)==1);
- }
-
- //.parse
-
- void RecFile::Write(const void *Buffer,int S)
- {
- fwrite(Buffer,RecSize*S,1,FilePointer);
- }
-
- //.parse
-
- void RecFile::Seek(long RecNum)
- {
- LowLevelFile::Seek(RecNum*RecSize);
- }
-
- //.parse
-
- long RecFile::Size()
- {
- return LowLevelFile::Size()/RecSize;
- }
-
- //.parse
-
- long RecFile::CurRec()
- {
- return LowLevelFile::CurPos()/RecSize;
- }
-
- //.parse
-
- Bool TokenFile::TokenExists(Word Token)
- {
- if (!InRange(Token,Word(1),MaxTokens)) return False;
- SeekIndexSlot(Token);
- long Pos;
- ReadThing(Pos);
- return(Pos!=0);
- }
-
- //.parse
-
- void TokenFile::GetFreeInfo(long Pos, long& Size, long& NextBlock)
- {
- File::Seek(Pos);
- ReadThing(Size);
- ReadThing(NextBlock);
- }
-
- //.parse
-
- long TokenFile::New(long FSize)
- {
- long CurBlock=FirstFreeBlock;
- long LastBlock=0;
- while (CurBlock)
- {
- long CurSize;
- long NextBlock;
- GetFreeInfo(CurBlock,CurSize,NextBlock);
- if (CurSize<FSize)
- {
- LastBlock=CurBlock;
- CurBlock=NextBlock;
- }
- else // a fit!
- {
- // take off of free list
- if (LastBlock) // make free list skip this block
- {
- Flush();
- File::Seek(LastBlock+4);
- File::WriteThing(NextBlock);
- Flush();
- }
- else // make start of free list point to next element of list
- {
- FirstFreeBlock=NextBlock;
- Flush();
- File::Seek(0);
- File::WriteThing(FirstFreeBlock);
- Flush();
- }
- if (CurSize>FSize) // add leftovers to free list
- Delete(CurBlock+FSize,CurSize-FSize);
- File::Seek(CurBlock);
- return(CurBlock);
- }
- }
- // return the block num for appending to EOF
- File::Seek(Size());
- return (Size());
- }
-
- //.parse
-
- void TokenFile::Delete(long Pos, long Size)
- {
- if (Size<8) return; // too small to mess with
- Flush();
- File::Seek(0);
- File::WriteThing(Pos);
- File::Seek(Pos);
- File::WriteThing(Size);
- File::WriteThing(FirstFreeBlock);
- Flush();
- FirstFreeBlock=Pos;
- }
-
- //.parse
-
- void TokenFile::Delete(Word Token)
- {
- if (!InRange(Token,Word(1),MaxTokens)) return;
- SeekIndexSlot(Token);
- long Pos,Size;
- ReadCurIndexSlot(Pos,Size);
- if (Pos)
- {
- Delete(Pos,Size);
- Pos=0;
- Size=0;
- Flush();
- SeekIndexSlot(Token);
- WriteThing(Pos);
- WriteThing(Size);
- Flush();
- }
- }
-
- //.parse
-
- void TokenFile::WritePrep(Word Token,long DataSize)
- {
- if (!InRange(Token,Word(1),MaxTokens)) return;
- SeekIndexSlot(Token);
- long Pos,CurSize;
- ReadCurIndexSlot(Pos,CurSize);
- if (Pos==0) Pos=New(DataSize);
- else if (CurSize<DataSize) // can't use this space
- {
- Delete(Pos,CurSize);
- Pos=New(DataSize);
- }
- else if (CurSize>DataSize) // can use this space but need to return excess
- Delete(Pos+DataSize,CurSize-DataSize);
- // the last case is that the currently selected block is the perfect size
- // in case Pos or Size ain't what it used to be...
- Flush();
- SeekIndexSlot(Token);
- File::WriteThing(Pos);
- File::WriteThing(DataSize);
- Flush();
- File::Seek(Pos);
- }
-
- //.parse
-
- TokenFile::TokenFile(const char* FileName,int BufSize):
- File(FileName,ReadAndWrite,BufSize)
- {
- if (Size()==0)
- {
- FirstFreeBlock=0;
- File::WriteThing(FirstFreeBlock);
- const Word MTInit=1000; // MaxTokens Init
- MaxTokens=MTInit;
- File::WriteThing(MaxTokens);
- Word NotUsed=0;
- File::WriteThing(NotUsed);
- long A[MTInit*2]; // 2 longs per token
- const Word ASize=MTInit*2*4;
- memset(&A[0],0,ASize);
- File::Write(&A[0],ASize);
- Flush();
- }
- else
- {
- File::Seek(0);
- ReadThing(FirstFreeBlock);
- ReadThing(MaxTokens);
- }
- }
-
- //.parse
-
- void TokenFile::ReadCurIndexSlot(long& Pos, long& Size)
- {
- ReadThing(Pos);
- ReadThing(Size);
- }
-
- //.parse
-
- long TokenFile::Seek(Word Token)
- {
- if (!InRange(Token,Word(1),MaxTokens)) return 0;
- SeekIndexSlot(Token);
- long Pos,Size;
- ReadCurIndexSlot(Pos,Size);
- if (Pos>0)
- {
- File::Seek(Pos);
- return(Size);
- }
- return (0);
- }
-
- //.parse
-
- void TokenFile::Extract(Word Token,char* FileName)
- {
- DeleteFile(FileName);
- if (TokenExists(Token))
- {
- long Size=Seek(Token);
- File F(FileName);
- FileCopying(F,*this,Size);
- }
- }
-
- //.parse
-
- Bool TokenExists(const char *FileName,Word Token)
- {
- if (!FileExists(FileName)) return False;
- TokenFile F(FileName);
- Bool B=F.TokenExists(Token);
- return B;
- }
-
-