home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C!T ROM 2
/
ctrom_ii_b.zip
/
ctrom_ii_b
/
PROGRAM
/
PASCAL
/
MKMSG104
/
MKFFILE.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1994-01-09
|
8KB
|
264 lines
Unit MKFFile; {Buffered File Object Unit}
{
MKFFile - Copyright 1993 by Mark May - MK Software
You are free to use this code in your programs, however
it may not be included in Source/TPU function libraries
without my permission.
Mythical Kingom Tech BBS (513)237-7737 HST/v32
FidoNet: 1:110/290
Rime: ->MYTHKING
You may also reach me at maym@dmapub.dma.org
}
{
MKFFile is a buffered file unit. You set the buffer size when
calling the init method. The MKFFile methods (seekfile, blkread,
blkwrite) take advantage of the buffer to minimize actual DOS calls
to access your data. This can significantly speed up your program.
MKFFile does handle blkread/blkwrites that are larger than the
buffer size, and is intended to be truely transparant to your
application.
}
{$I MKB.Def}
Interface
Type FBufType = Array[0..$fff0] of Byte;
Type FFileObj = Object
BufFile: File; {File to be buffered}
Buf: ^FBufType; {Pointer to the buffer-actual size given by init}
BufStart: LongInt; {File position of buffer start}
BufSize: LongInt; {Size of the buffer}
BufChars: Word; {Number of valid characters in the buffer}
CurrSize: LongInt; {Current file size}
NeedWritten: Boolean; {Buffer dirty/needs written flag}
IsOpen: Boolean; {File is currently open flag}
CurrPos: LongInt; {Current position in file/buffer}
Constructor Init(BSize: Word);
{Initialize object and set buffer size/allocate memory}
Destructor Done; Virtual; {Done}
Function OpenFile(FName: String; FMode: Word): Boolean; Virtual;
{Open a file FNAME in the filemode FMode}
Function CloseFile: Boolean; Virtual; {Close the currently open file}
Function BlkRead(Var V; Num: Word; Var NumRead: Word): Boolean; Virtual;
{Equivalent to BlockRead but makes use of buffer to reduce real reads}
Function BlkWrite(Var V; Num: Word): Boolean; Virtual;
{Equivalent to BlockWrite but uses buffer to reduce real writes}
Function SeekFile(FP: LongInt): Boolean; Virtual;
{Equivalent to seek but uses buffer to reduce real seeks}
Function WriteBuffer: Boolean; Virtual;
{Internal use normally - flushes buffer if needed}
Function RawSize: LongInt; Virtual;
{Pass through to filesize function}
End;
Implementation
Uses MKFile,
{$IFDEF WINDOWS}
WinDos;
{$ELSE}
Dos,
{$IFDEF OPRO}
OpCrt;
{$ELSE}
Crt;
{$ENDIF}
{$ENDIF}
Constructor FFileObj.Init(BSize: Word);
Begin
Buf := Nil;
BufSize := BSize;
BufStart := -10; {Invalidate buffer}
BufChars := 0;
IsOpen := False; {Initialize values}
NeedWritten := False;
CurrPos := 0;
GetMem(Buf, BufSize); {Allocate memory for buffer}
If Buf = Nil Then
Fail;
End;
Destructor FFileObj.Done;
Begin
If IsOpen Then {If file is open then close it}
If CloseFile Then;
If Buf <> Nil Then {Free up memory}
FreeMem(Buf, BufSize);
End;
Function FFileObj.OpenFile(FName: String; FMode: Word): Boolean;
Var
Error: Boolean;
Begin
Error := False;
If IsOpen Then {If file is open then close it first}
Error := CloseFile;
If Not Error Then
Begin
Assign(BufFile, FName);
FileMode := FMode;
If FileExist(FName) Then
Reset(BufFile, 1)
Else
ReWrite(BufFile, 1);
Error := IoResult <> 0;
IsOpen := Not Error;
CurrPos := 0; {Initialize file position}
BufStart := -10; {Invalidate buffer}
BufChars := 0;
NeedWritten := False;
CurrSize := RawSize;
End;
OpenFile := Not Error;
End;
Function FFileObj. CloseFile: Boolean;
Var
Error: Boolean;
Begin
Error := False;
If NeedWritten Then {If buffer needs written then write it first}
Error := Not WriteBuffer;
If Not Error Then
Begin
Close(BufFile); {Close file}
Error := (IoResult <> 0);
End;
If Not Error Then
IsOpen := False;
CloseFile := Not Error;
End;
Function FFileObj. BlkRead(Var V; Num: Word; Var NumRead: Word): Boolean;
Var
Tmp: LongInt; {Number of chars to write}
Error: Boolean;
Begin
Error := False;
NumRead := 0; {Initialize number read to zero}
Error := Not SeekFile(CurrPos); {Make currpos valid}
While ((NumRead < Num) and (Not Error)) Do
Begin
Tmp := Num - NumRead;
If Tmp > (BufChars - (CurrPos - BufStart)) Then
Tmp := (BufChars - (CurrPos - BufStart));
Move(Buf^[CurrPos - BufStart], FBufType(V)[NumRead] , Tmp);
Inc(NumRead, Tmp);
Error := Not SeekFile(CurrPos + Tmp);
If BufChars = 0 Then
Num := NumRead;
End;
BlkRead := Not Error;
End;
Function FFileObj. BlkWrite(Var V; Num: Word): Boolean;
Var
Tmp: LongInt; {Number of chars to write}
NumWritten: LongInt; {Number of chars written}
Error: Boolean;
Begin
NumWritten := 0;
Error := False;
If CurrPos < CurrSize Then
Error := Not SeekFile(CurrPos);
While ((NumWritten < Num) and (Not Error)) Do
Begin
Tmp := Num - NumWritten;
If ((BufChars = 0) or (CurrPos >= CurrSize)) Then
Begin
If Tmp > BufSize Then
BufChars := BufSize
Else
BufChars := Tmp;
End;
If Num > (BufChars - (CurrPos - BufStart)) Then
Tmp := (BufChars - (CurrPos - BufStart));
If ((Tmp > 0) and (Not Error)) Then
Begin
Move(FBufType(V)[NumWritten], Buf^[CurrPos - BufStart] , Tmp);
Inc(NumWritten, Tmp);
NeedWritten := True;
Error := Not SeekFile(CurrPos + Tmp);
End;
End;
BlkWrite := Not Error;
End;
Function FFileObj. SeekFile(FP: LongInt): Boolean;
Var
Error: Boolean;
Begin
Error := Not IsOpen; {Error if file isn't open}
If Not Error Then
Begin
If ((FP < BufStart) or (FP > (BufStart + BufChars - 1))) Then
Begin {If FP isn't in buffer}
If NeedWritten Then {Write old buffer first if needed}
Error := Not WriteBuffer;
If Not Error Then
Begin
Seek(BufFile, FP);
Error := (ioResult <> 0); {Seek to FP}
End;
If Not Error Then
Begin
BufStart := FP;
If FP = RawSize Then
BufChars := 0
Else
Error := Not shRead(BufFile, Buf^, BufSize, BufChars); {Fill buffer}
End;
End;
If Not Error Then
CurrPos := FP; {Set current file position to FP}
End;
SeekFile := Not Error;
End;
Function FFileObj.WriteBuffer: Boolean;
Var
DoneOK: Boolean;
Begin
Seek(BufFile, BufStart);
DoneOk := (ioResult = 0); {Seek to buffer start first}
If DoneOk Then
DoneOk := shWrite(BufFile, Buf^, BufChars); {Write buffer}
If (BufStart + BufChars) > CurrSize Then
CurrSize := BufStart + BufChars;
NeedWritten := Not DoneOk; {Turn off needs-written flag}
WriteBuffer := DoneOk; {Return result}
End;
Function FFileObj.RawSize: LongInt;
Begin
RawSize := FileSize(BufFile);
If IoResult <> 0 Then;
End;
End.