Category : C++ Source Code
Archive   : WLIB.ZIP
Filename : WFILE.C

 
Output of file : WFILE.C contained in archive : WLIB.ZIP
#include "WLocal.h"
#pragma hdrstop

// copyright (c) 1992, 1993 by Paul Wheaton, Banana Programming
// 1916 Brooks #205, Missoula, MT 59801
//
// phone: (406)543-1928
// CompuServe: 72707,207
// Internet: [email protected]
// BBS: (406)543-8234 (The Montana Banana BBS)

//.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() 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

static VoidFuncPtr CopyGrind=NULL;

void SetCopyGrind(VoidFuncPtr CG)
{
CopyGrind=CG;
}

void FileCopying(File& DFile, File& SFile, long Size)
{
int BufSize=1024*8;
char* Buf=(char*)malloc(BufSize);
if (Buf==NULL)
{
BufSize=512;
Buf=(char*)malloc(BufSize);
if (Buf==NULL) FatalError("out of mem file copy");
}
while (Size>0)
{
if (CopyGrind!=NULL) (*CopyGrind)();
long Chunk=Min(Size,long(BufSize));
SFile.Read(&Buf[0],int(Chunk));
DFile.Write(&Buf[0],int(Chunk));
Size-=Chunk;
}
CopyGrind=NULL;
free(Buf);
}

//.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(long Token)
{
if (!InRange(Token,long(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::FindSpace(long FSize)
{
long CurBlock=FirstFreeBlock;
long LastBlock=0;
while (CurBlock!=0)
{
long CurSize;
long NextBlock;
GetFreeInfo(CurBlock,CurSize,NextBlock);
if (CurSize {
LastBlock=CurBlock;
CurBlock=NextBlock;
}
else // a fit!
{
// take off of free list
if (LastBlock!=0) // 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
long X=Size();
File::Seek(X);
if (FSize>0)
{
File::Seek(X+FSize-1);
char C='\0';
File::WriteThing(C);
Flush();
File::Seek(X);
}
return X;
}

//.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(long Token)
{
if (!InRange(Token,long(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(long Token,long DataSize)
{
if (!InRange(Token,long(1),MaxTokens)) return;
SeekIndexSlot(Token);
long Pos,CurSize;
ReadCurIndexSlot(Pos,CurSize);
if (Pos==0) Pos=FindSpace(DataSize);
else if (CurSize {
Delete(Pos,CurSize);
Pos=FindSpace(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

static void InitTokenFile(File& F,long MaxTokens)
{
long FirstFreeBlock=0;
F.WriteThing(FirstFreeBlock);
F.WriteThing(MaxTokens);
long NextFreeToken=2;
F.WriteThing(NextFreeToken);
long NotUsed=0;
F.WriteThing(NotUsed);
long A[100*2]; // 2 longs per token
ClearArray(A);
while(MaxTokens>100)
{
F.Write(A,100*4*2);
MaxTokens-=100;
}
if (MaxTokens>0) F.Write(A,int(MaxTokens*2*4));
}

void CreateTokenFile(const char* FileName,long MaxTokens)
{
DeleteFile(FileName);
File F(FileName);
InitTokenFile(F,MaxTokens);
}

TokenFile::TokenFile(const char* FileName,int BufSize):
File(FileName,ReadAndWrite,BufSize)
{
if (Size()==0)
{
FirstFreeBlock=0;
MaxTokens=1000;
InitTokenFile(*this,MaxTokens);
NextFreeToken=2;
}
else
{
File::Seek(0);
ReadThing(FirstFreeBlock);
ReadThing(MaxTokens);
ReadThing(NextFreeToken);
}
}

//.parse

void TokenFile::ReadCurIndexSlot(long& Pos, long& Size)
{
ReadThing(Pos);
ReadThing(Size);
}

//.parse

long TokenFile::Seek(long Token)
{
if (!InRange(Token,long(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(long 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,long Token)
{
if (!FileExists(FileName)) return False;
TokenFile F(FileName);
Bool B=F.TokenExists(Token);
return B;
}

//.parse

long TokenFile::NewToken(long DataSize)
{
SeekIndexSlot(NextFreeToken);
long Pos, Size;
ReadCurIndexSlot(Pos,Size);
while (Pos!=0)
{
NextFreeToken++;
if (NextFreeToken>=MaxTokens)
{
NextFreeToken=2;
SeekIndexSlot(NextFreeToken);
}
ReadCurIndexSlot(Pos,Size);
}
long Token=NextFreeToken;
NextFreeToken++;
WritePrep(Token,DataSize);
return Token;
}



  3 Responses to “Category : C++ Source Code
Archive   : WLIB.ZIP
Filename : WFILE.C

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/