home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
World of Shareware - Software Farm 2
/
wosw_2.zip
/
wosw_2
/
PASCAL
/
TBTREE16.ZIP
/
FILEBUFF.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1989-07-13
|
38KB
|
870 lines
(* TBTree16 Copyright (c) 1988,1989 Dean H. Farwell II *)
unit FileBuff;
{$I-} (* turn off I/O error checking *)
(*****************************************************************************)
(* *)
(* O P E N F I L E B U F F E R H A N D L I N G R O U T I N E S *)
(* *)
(*****************************************************************************)
(* This unit handles the opening and closing of files. It allows a user to
set a parameter on how many files can be open at a given time and then
keeps a buffer of open files. The number of files which are in the
buffer, and are therefore open, will not exceed this limit. The limit can
be changed at any time. Each time a file is accessed, the list is checked
to see if the desired file is in the list. If the file is in the list the
file id is returned. If it is not open, it will be opened and the id will
be returned. If the number of files currently open is equal to the
maximum the least recently accessed file will be closed prior to opening
the desired file.
The primary advantage to using this unit is that the user does not have to
worry about opening too many files and causing a runtime error. If all
routines which open and close files use this unit instead of explicitly
opening and closing files then the user can not accidently open too many
files. Unfortunately, this unit presently only handles Untyped and Text
files. It will not handle Typed files. This is mainly due to the strong
type checking of Turbo Pascal. There are ways around it but for now they
seem a little unwieldy. This unit can be used for all files of
type File (ie untyped) and Text. These routines have been thoroughly
tested for untyped files and are used extensively by other TBTREE units.
I have only done limited testing with text files.
The main advantage of this unit is that many files can now be open at the
same time, thus the need to arbitrarily close files is alleviated. This
should reduce overhead caused by the constant opening and closing of
files.
All file accesses within TBTREE use this unit. Whether you use this unit
or not, you still need to initially allocate a number of files to this
unit (in other words the user sets the maximum number of files which can
be in the file open buffer). Obviously, you must not allocate more files
to this unit than DOS can handle. This DOS parameter is set in the
CONFIG.SYS file at bootup time. The absolute maximum allowed by DOS is
20. Since Turbo Pascal needs 5 you have 15 to play with. You can
allocate any number from 1 to 15 to this unit. If you allocate less than
15 (actually the number in the CONFIG.SYS file minus 5) the leftover are
yours to use with Typed files, etc. For example, if you set FILES = 20 in
the CONFIG.SYS file you can allocate 10 files to this unit and you will
have (20 - 5) - 10 = 5 left for yourself to use with typed files. One
added note: you can change this setting at any time during execution. You
can even set it to a number less than the number of files presently open
and files will be closed until the number is reached.
You can use the buffer and these routines for within your application,
thus sharing it with TBTREE. The scenario for use of these routines is as
follows:
1. Call SetMaxOpenFiles(n) where n is the maximum number of files
which can be open at one time. n must be less than or equal to
the value for 'files' in the CONFIG.SYS file minus 5. See the DOS
manual for details. If SetMaxOpenFiles is not called, the max
number of open files will default to one (1). This will not cause
any errors but it will probably cause a large performance
degradation.
2. When you want to create a file use
RewriteTextFile(xxxxxxxx.xxx,fId) or
RewriteUntypedFile(xxxxxxxx.xxx,fId) where xxxxxxxx.xxx is the
file name (including an optional drive and path) for the file to
create and fId is a file id (file variable) you have declared.
For untyped files use OpenUntypedFile routine to open your file
(if it is not open) and return the appropriate file id in fId.
For text files use OpenTextFile for reading and AppendTextFile for
writing. You can now use fId as a file variable. For example:
var myFile : Text;
str : String;
begin
RewriteTextFile('autoexec.bat',myfile);
Writeln(myFile,'verify on');
CloseFile('autoexec.bat');
.
. { to access the file see below }
.
OpenTextFile('autoexec.bat',myFile);
Readln(myFile,str);
.
.
.
CloseAllFiles; { see note 4 below }
end;
3. As noted above, to access the file use
OpenUntypedFile(xxxxxxxx.xxx,fId) or
OpenTextFile(xxxxxxxx.xxx,fId) or AppendTextFile(xxxxxxxx.xxx,fId)
depending on file type, etc. This will ensure that the file will
be open and the routine will open it if it is not. It is only
necessary to call OpenUntypedFile if there is a possibility that
the file may not be open or that fId is not current. For example,
in the above example, AppendTextFile did not have to be called to
access autoexec.bat immediately after executing the RewriteFile
routine. To be safe, always call one of the open file routines
prior to accessing the file. If the file happens to be open there
in not much overhead associated with the call. For all the
routines except for RewriteUntypedFile and RewriteTextFile, the
file must exist.
4. Do not use CLOSE to close a file. Use CloseFile(xxxxxxxx.xxx) or
CloseAllFiles instead. This applies to both Text and Untyped
files. See notes 5 and 6 below.
5. To ensure that a particular file is closed use
CloseFile(xxxxxxxx.xxx). When you call this the file will be
closed if it is not already closed. If it is closed then nothing
happens.
6. To ensure all files are closed use CloseAllFiles.
In previous versions, there was a danger of running out of heap
space and being unable to allocate enough space on the heap to put a file
on the list. This is now handled properly by initially reserving enough
space on the heap for one entry. In this way, you will always be able to
have at least one file open and in the list. It reserves the space as
part of the initialization sequence when the code in the initialization
section is called. If there is not enough heap space available, a runtime
error occurs. If an error does not occur during the initialization, a
problem will never occur later. However, if there is a very limited
amount of heap space available, the unit will not allow very many files to
reside on the list at one time. This will be transparent to you except
that performance will suffer somewhat.
One warning when using these routines and using a file variable local to a
procedure or function: BE SURE TO CLOSE THE FILE (CloseFile or
CloseAllFiles) before leaving the routine. This restriction in not really
any different than using file variables with the Turbo Pascal supplied
routines *)
(*\*)
(* Version Information
Version 1.1 - No Changes
Version 1.2 - No Changes
Version 1.3 - No Changes
Version 1.4 - Internal changes to use the newly redesigned TIME unit
- Changed SetMaxOpenFiles routine. Now this routine handles
the case where you set the number of open files to a value
less than the number presently open. It will close files
automatically until the number open is equal to the number
being set.
Version 1.5 - I redid parts of the documentation for the unit to better
explain its use.
- Unit is now compile with {$I-} which means that I/O checking
off. I now use the IOResult routine supplied with Turbo
Pascal to get the rusult of an I/O operation. If the I/O
operation was not successful then I use the ERROR unit to
handle it. You must become familiar with the error unit!
- Changed code internally to use Inc and Dec where practical
- Changed code internally to use newly added FastMove unit
- Reworked routines for Text Files to alleviate pesky Flush
problem. Routines now work properly without needing to flush
after every Write or Writeln. Chris Cardozo was a great help
in conquering this problem and his efforts are appreciated.
- In previous versions, there was a danger of running out of
heap space and being unable to allocate enough space on the
heap to put a file on the list. This is now handled properly
by initially reserving enough space on the heap for one
entry. In this way, you will always be able to have at least
one file open and in the list. It reserves the space as part
of the initialization sequence when the code in the
initialization section is called. If there is not enough
heap space available, a runtime error occurs. If an error
does not occur during the initialization, a problem will
never occur later. However, if there is a very limited amount
of heap space available, the unit will not allow very many
files to reside on the list at one time. This will be
transparent to you except that performance will suffer
somewhat.
Version 1.6 - No Changes *)
(*\*)
(*////////////////////////// I N T E R F A C E //////////////////////////////*)
interface
uses
Compare,
Dos,
Error,
FastMove,
FileDecs,
Numbers,
Time;
type
OpenFileRange = Byte;
(* This routine will close the given file and delete its entry from the
open files buffer. *)
procedure CloseFile(fName : FnString);
(* This routine will return the file id (fId) for a file after rewriting it.
It's operation is equivalent to the REWRITE routine of TURBO. It will
create a new file or rewrie an existing file. It then adds this file
to the files open buffer in the same manner as OpenFiles would.
note - This routine is for use with Untyped files only. Unlike with the
Turbo Pascal routine Rewrite, the user must supply recSize. It will
not default to 128. *)
procedure RewriteUntypedFile(fName : FnString;
var fId: File;
recSize : Word);
(*\*)
(* This routine will return the file id (fId) for the given file. It will
also open the file if it is not open. If the file is not open the routine
will open it and place the file name in the file open buffer. If the
buffer is full showing that the maximum number of files is open, the
routine will close the least recently used file prior to opening this one.
The maximum number of files which can be open is set by calling the
procedure SetMaxOpenFiles which is part of this unit.
Note : This routine uses the TURBO routine RESET. Therefore the
restrictions that apply to RESET apply to OpenFile. For Example,
an error will result if OpenFile is used on a file that does not
exist. Use RewriteUntypedFile first!
note - This routine is for use with Untyped files only. Unlike with the
Turbo Pascal routine Rewrite, the user must supply recSize. It will
not default to 128. *)
procedure OpenUntypedFile(fName : FnString;
var fId : File;
recSize : Word);
(* This routine will return the file id (fId) for a file after rewriting it.
It's operation is equivalent to the REWRITE routine of TURBO. It will
create a new file or rewrite an existing file. It then adds this file
to the files open buffer in the same manner as OpenFiles would.
note - This routine is for use with Text files only. *)
procedure RewriteTextFile(fName : FnString;
var fId : Text);
(* This routine will return the file id (fId) for the given file. It will
also open the file if it is not open. If the file is not open the routine
will open it and place the file name in the file open buffer. If the
buffer is full showing that the maximum number of files is open, the
routine will close the least recently used file prior to opening this one.
The maximum number of files which can be open is set by calling the
procedure SetMaxOpenFiles which is part of this unit.
Note : This routine uses the TURBO routine RESET. Therefore the
restrictions that apply to RESET apply to OpenFile. For Example,
an error will result if OpenFile is used on a file that does not
exist. Use RewriteTextFile first!
note - This routine is for use with Text files only. *)
procedure OpenTextFile(fName : FnString;
var fId : Text);
(*\*)
(* This routine will return the file id (fId) for the given file. It will
also open the file if it is not open. If the file is not open the routine
will open it and place the file name in the file open buffer. If the
buffer is full showing that the maximum number of files is open, the
routine will close the least recently used file prior to opening this one.
The maximum number of files which can be open is set by calling the
procedure SetMaxOpenFiles which is part of this unit.
Note : This routine uses the TURBO routine APPEND. Therefore the
restrictions that apply to APEND apply to OpenFile. For Example,
an error will result if OpenFile is used on a file that does not
exist. Use RewriteTextFile first!
note - This routine is for use with Text files only. *)
procedure AppendTextFile(fName : FnString;
var fId : Text);
(* This routine will Close all files that are open and empty the open file
buffer. *)
procedure CloseAllFiles;
(* This routine will set the maximum files that can be open at a time. It is
important that this not exceed the number of files DOS will allow to be
open. The number DOS will allow is set in the CONFIG.SYS file. Also
remember that Turbo Pascal needs 5 files so you really can only set this to
the value set in the CONFIG.SYS file minus 5. See the appropriate DOS
manual for details on the FILES command. The value is initially set to one
(1). This routine should be called BEFORE using the buffer. You can call
this routine ANY time with no negative effects. In version 1.4 the routine
was changed to take care of the situation where the number of files open is
greater than n. The routine will first check to ensure that n is valid
(greater than 0). Once this is established, n will be checked against the
number of open files. If the number of open files exceeds n, the least
recently used files will be closed until the number of open files equals n.
Finally, the internal variable will be set and only n number of files will
ever be open at once, until this routine is called again with a new value
for n. *)
procedure SetMaxOpenFiles(n : OpenFileRange);
(* This routine will return the number of files which are presently open. *)
function GetNumberOpenFiles : OpenFileRange;
(*!*)
(*\*)
(*///////////////////// I M P L E M E N T A T I O N /////////////////////////*)
implementation
type
FilesType = (TEXTFILE,UNTYPEDFILE); (* only file types handled
by FILEBUFF *)
FileOpenRecPtr = ^FileOpenRec;
FileOpenRec = record
fName : FnString;
timeUsed : TimeArr;
userPtr : Pointer; (* used to point to users file var *)
prev : FileOpenRecPtr;
next : FileOpenRecPtr;
case fType : FilesType of
TEXTFILE : (fIdText : Text);
UNTYPEDFILE : (fIdUntyped : File);
end;
FileOpenList = record
head : FileOpenRecPtr;
count : OpenFileRange;
end;
var
maxOpenFiles : OpenFileRange;
fileList : FileOpenList;
reservedFPtr : FileOpenRecPtr;
(*\*)
(* This routine deletes a file from the list of open files *)
procedure RemoveFileFromList(var fPtr : FileOpenRecPtr);
begin
Dec(fileList.count);
fPtr^.prev^.next := fPtr^.next;
if fPtr^.next <> NIL then
begin
fPtr^.next^.prev := fPtr^.prev;
end;
if fPtr <> reservedFPtr then
begin (* dispose of it only is it is not the reserved space *)
Dispose(fPtr);
end;
end; (* end of RemoveFileFromList routine *)
(* This routine find the file that was least recently accessed last and returns
the appropriate pointer. The calling routine must then close this file
before opening another. *)
function LRUFile : FileOpenRecPtr;
var
oldPtr, (* points to least recently used file *)
fPtr : FileOpenRecPtr;
minTime : TimeArr; (* time least recently used file was last used *)
begin
fPtr := fileList.head^.next; (* point to first 'real' cell *)
oldPtr := fPtr;
SetMaxTime(minTime);
while fPtr <> NIL do (* go through all open files *)
begin
if CompareTime(fPtr^.timeUsed,minTime) = LESSTHAN then
begin
minTime := fPtr^.timeUsed;
oldPtr := fPtr;
end;
fPtr := fPtr^.next;
end;
LRUFile := oldPtr;
end; (* end of LRUFile routine *)
(*\*)
(* This routine will close the given file and delete its entry from the
open files buffer. *)
procedure CloseFile(fName : FnString);
var
fPtr : FileOpenRecPtr;
found : Boolean;
ioRes : Word;
ioErrRec : IOErrorRec;
begin
fPtr := fileList.head^.next;
found := FALSE;
while (fPtr <> NIL) and (not found) do
begin
if fPtr^.fName = fName then
begin
repeat (* I/O loop with error checking *)
begin
case fPtr^.fType of (* close it *)
TEXTFILE :
begin
FastMover(fPtr^.userPtr^,
fPtr^.fIdText,
128); (* don't want the buffer .. *)
Close(fPtr^.fIdText);
end;
UNTYPEDFILE :
begin
Close(fPtr^.fIdUntyped);
end;
end; (* end of case statement *)
ioRes := IOResult;
if ioRes <> 0 then
begin
ioErrRec.routineName := 'CloseFile';
ioErrRec.tBTreeIOResult := ioRes;
UserIOError(ioErrRec);
end;
end;
until ioRes = 0;
RemoveFileFromList(fPtr);
found := TRUE;
end
else
begin
fPtr := fPtr^.next;
end;
end;
end; (* end of CloseFile routine *)
(*\*)
(* This routine will allocate enough heap space for one FileOpenRec record.
It will first check to see if there is room on the list. If there is not,
a file will be closed to make room. Then the routine will allocate the
heap space required. If there is not enough room on the heap for an entry
a file will be closed to make room. If there are no files open the
reserved heap space is used. *)
procedure AllocateHeapSpaceForList(var fPtr : FileOpenRecPtr);
begin
if fileList.count = maxOpenFiles then
begin (* no more files fit on list ... close one first *)
fPtr := LRUFile;
CloseFile(fPtr^.fName);
end;
if MaxAvail < SizeOf(FileOpenRec) then
begin
if fileList.count > 0 then
begin (* close a file and use its space *)
fPtr := LRUFile;
CloseFile(fPtr^.fName);
New(fPtr);
end
else
begin (* no files to close so use the reserved heap space *)
fPtr := reservedFPtr;
end;
end
else
begin (* room on the heap .. use it *)
New(fPtr);
end;
end; (* end of AllocateHeapSpaceForList routine *)
(* This routine will put the record pointed to by fPtr in the list and
also increments the counter *)
procedure PutFileInList(var fPtr : FileOpenRecPtr);
begin
fPtr^.prev := fileList.head;
fPtr^.next := fileList.head^.next; (* put at head of list *)
fileList.head^.next := fPtr;
if fPtr^.next <> NIL then
begin
fPtr^.next^.prev := fPtr;
end;
Inc(fileList.count);
end; (* end of PutFileInList routine *)
(*\*)
(* This routine will return the file id (fId) for a file after rewriting it.
It's operation is equivalent to the REWRITE routine of TURBO. It will
create a new file or rewrie an existing file. It then adds this file
to the files open buffer in the same manner as OpenFiles would.
note - This routine is for use with Untyped files only. Unlike with the
Turbo Pascal routine Rewrite, the user must supply recSize. It will
not default to 128. *)
procedure RewriteUntypedFile(fName : FnString;
var fId: File;
recSize : Word);
var
fPtr : FileOpenRecPtr;
ioRes : Word;
ioErrRec : IOErrorRec;
begin
CloseFile(fName); (* make sure its closed *)
AllocateHeapSpaceForList(fPtr);
repeat (* I/O loop with error checking *)
Assign(fPtr^.fIdUntyped,fName);
Rewrite(fPtr^.fIdUntyped,recSize); (* open the file *)
ioRes := IOResult;
if ioRes <> 0 then
begin
ioErrRec.routineName := 'RewriteUntypedFile';
ioErrRec.tBTreeIOResult := ioRes;
UserIOError(ioErrRec);
end;
until ioRes = 0;
fPtr^.fName := fName;
fPtr^.fType := UNTYPEDFILE;
PutFileInList(fPtr);
GetTime(fPtr^.timeUsed); (* set the time used *)
FastMover(fPtr^.fIdUntyped,fId,SizeOf(fId));
(* pass back file id to caller *)
end; (* end of RewriteUntypedFile routine *)
(*\*)
(* This routine will return the file id (fId) for the given file. It will
also open the file if it is not open. If the file is not open the routine
will open it and place the file name in the file open buffer. If the
buffer is full showing that the maximum number of files is open, the
routine will close the least recently used file prior to opening this one.
The maximum number of files which can be open is set by calling the
procedure SetMaxOpenFiles which is part of this unit.
Note : This routine uses the TURBO routine RESET. Therefore the
restrictions that apply to RESET apply to OpenFile. For Example,
an error will result if OpenFile is used on a file that does not
exist. Use RewriteUntypedFile first!
note - This routine is for use with Untyped files only. Unlike with the
Turbo Pascal routine Rewrite, the user must supply recSize. It will
not default to 128. *)
procedure OpenUntypedFile(fName : FnString;
var fId : File;
recSize : Word);
var
found : Boolean;
fPtr : FileOpenRecPtr;
ioRes : Word;
ioErrRec : IOErrorRec;
begin
fPtr := fileList.head^.next; (* points to first 'real' cell *)
found := FALSE;
while (not found) and (fPtr <> NIL) do
begin
if fPtr^.fName = fName then
begin
found := TRUE;
end
else
begin
fPtr := fptr^.next;
end;
end;
if not found then
begin
AllocateHeapSpaceForList(fPtr);
repeat (* I/O loop with error checking *)
Assign(fPtr^.fIdUntyped,fName);
Reset(fPtr^.fIdUntyped,recSize); (* open the file *)
ioRes := IOResult;
if ioRes <> 0 then
begin
ioErrRec.routineName := 'OpenUntypedFile';
ioErrRec.tBTreeIOResult := ioRes;
UserIOError(ioErrRec);
end;
until ioRes = 0;
fPtr^.fName := fName;
fPtr^.fType := UNTYPEDFILE;
PutFileInList(fPtr);
end;
GetTime(fPtr^.timeUsed); (* set the time used *)
FastMover(fPtr^.fIdUntyped,fId,SizeOf(fId));
(* pass back file id to caller *)
end; (* end of OpenUntypedFile routine *)
(*\*)
(* This routine will return the file id (fId) for a file after rewriting it.
It's operation is equivalent to the REWRITE routine of TURBO. It will
create a new file or rewrite an existing file. It then adds this file
to the files open buffer in the same manner as OpenFiles would.
note - This routine is for use with Text files only. *)
procedure RewriteTextFile(fName : FnString;
var fId : Text);
var
fPtr : FileOpenRecPtr;
ioRes : Word;
ioErrRec : IOErrorRec;
begin
CloseFile(fName); (* make sure its closed *)
AllocateHeapSpaceForList(fPtr);
repeat (* I/O loop with error checking *)
Assign(fPtr^.fIdText,fName);
Rewrite(fPtr^.fIdText); (* rewrite the file *)
ioRes := IOResult;
if ioRes <> 0 then
begin
ioErrRec.routineName := 'RewriteTextFile';
ioErrRec.tBTreeIOResult := ioRes;
UserIOError(ioErrRec);
end;
until ioRes = 0;
fPtr^.fName := fName;
fPtr^.fType := TEXTFILE;
fPtr^.userPtr := Addr(fId); (* get address of user file variable *)
PutFileInList(fPtr);
GetTime(fPtr^.timeUsed); (* set the time used *)
FastMover(fPtr^.fIdText,fId,SizeOf(fId)); (* pass back file id to caller *)
end; (* end of RewriteTextFile routine *)
(*\*)
(* This routine will return the file id (fId) for the given file. It will
also open the file if it is not open. If the file is not open the routine
will open it and place the file name in the file open buffer. If the
buffer is full showing that the maximum number of files is open, the
routine will close the least recently used file prior to opening this one.
The maximum number of files which can be open is set by calling the
procedure SetMaxOpenFiles which is part of this unit.
Note : This routine uses the TURBO routine RESET. Therefore the
restrictions that apply to RESET apply to OpenFile. For Example,
an error will result if OpenFile is used on a file that does not
exist. Use RewriteTextFile first!
note - This routine is for use with Text files only. *)
procedure OpenTextFile(fName : FnString;
var fId : Text);
var
found : Boolean;
fPtr : FileOpenRecPtr;
ioRes : Word;
ioErrRec : IOErrorRec;
begin
fPtr := fileList.head^.next; (* points to first 'real' cell *)
found := FALSE;
while (not found) and (fPtr <> NIL) do
begin
if fPtr^.fName = fName then
begin
found := TRUE;
end
else
begin
fPtr := fptr^.next;
end;
end;
if not found then
begin
AllocateHeapSpaceForList(fPtr);
repeat (* I/O loop with error checking *)
Assign(fPtr^.fIdText,fName);
Reset(fPtr^.fIdText); (* open the file *)
ioRes := IOResult;
if ioRes <> 0 then
begin
ioErrRec.routineName := 'OpenTextFile';
ioErrRec.tBTreeIOResult := ioRes;
UserIOError(ioErrRec);
end;
until ioRes = 0;
fPtr^.fName := fName;
fPtr^.fType := TEXTFILE;
fPtr^.userPtr := Addr(fId); (* get address of user file variable *)
PutFileInList(fPtr);
FastMover(fPtr^.fIdText,fId,SizeOf(fId)); (* pass back file id to
caller *)
(* notice that you do not do
this if the file is open
already *)
end;
GetTime(fPtr^.timeUsed); (* set the time used *)
end; (* end of OpenTextFile routine *)
(*\*)
(* This routine will return the file id (fId) for the given file. It will
also open the file if it is not open. If the file is not open the routine
will open it and place the file name in the file open buffer. If the
buffer is full showing that the maximum number of files is open, the
routine will close the least recently used file prior to opening this one.
The maximum number of files which can be open is set by calling the
procedure SetMaxOpenFiles which is part of this unit.
Note : This routine uses the TURBO routine APPEND. Therefore the
restrictions that apply to APEND apply to OpenFile. For Example,
an error will result if OpenFile is used on a file that does not
exist. Use RewriteTextFile first!
note - This routine is for use with Text files only. *)
procedure AppendTextFile(fName : FnString;
var fId : Text);
var
found : Boolean;
fPtr : FileOpenRecPtr;
ioRes : Word;
ioErrRec : IOErrorRec;
begin
fPtr := fileList.head^.next; (* points to first 'real' cell *)
found := FALSE;
while (not found) and (fPtr <> NIL) do
begin
if fPtr^.fName = fName then
begin
found := TRUE;
end
else
begin
fPtr := fptr^.next;
end;
end;
if not found then
begin
AllocateHeapSpaceForList(fPtr);
repeat (* I/O loop with error checking *)
Assign(fPtr^.fIdText,fName);
Append(fPtr^.fIdText); (* open the file *)
ioRes := IOResult;
if ioRes <> 0 then
begin
ioErrRec.routineName := 'AppendTextFile';
ioErrRec.tBTreeIOResult := ioRes;
UserIOError(ioErrRec);
end;
until ioRes = 0;
fPtr^.fName := fName;
fPtr^.fType := TEXTFILE;
fPtr^.userPtr := Addr(fId); (* get address of user file variable *)
PutFileInList(fPtr);
FastMover(fPtr^.fIdText,fId,SizeOf(fId)); (* pass back file id to
caller *)
end;
GetTime(fPtr^.timeUsed); (* set the time used *)
end; (* end of AppendTextFile routine *)
(*\*)
(* This routine will Close all files that are open and empty the open file
buffer. *)
procedure CloseAllFiles;
begin
while fileList.count <> 0 do
begin
CloseFile(fileList.head^.next^.fName);
end;
end; (* end of CloseAllFiles routine *)
(* This routine will set the maximum files that can be open at a time. It is
important that this not exceed the number of files DOS will allow to be
open. The number DOS will allow is set in the CONFIG.SYS file. Also
remember that Turbo Pascal needs 5 files so you really can only set this to
the value set in the CONFIG.SYS file minus 5. See the appropriate DOS
manual for details on the FILES command. The value is initially set to one
(1). This routine should be called BEFORE using the buffer. You can call
this routine ANY time with no negative effects. In version 1.4 the routine
was changed to take care of the situation where the number of files open is
greater than n. The routine will first check to ensure that n is valid
(greater than 0). Once this is established, n will be checked against the
number of open files. If the number of open files exceeds n, the least
recently used files will be closed until the number of open files equals n.
Finally, the internal variable will be set and only n number of files will
ever be open at once, until this routine is called again with a new value
for n. *)
procedure SetMaxOpenFiles(n : OpenFileRange);
var
fPtr : FileOpenRecPtr;
begin
if n > 0 then
begin
if fileList.count <= n then
begin
maxOpenFiles := n;
end
else
begin
while fileList.count > n do
begin
fPtr := LRUFile;
CloseFile(fPtr^.fName);
end;
end;
end;
end; (* end of SetMaxOpenFiles routine *)
(*\*)
(* This routine will return the number of files which are presently open. *)
function GetNumberOpenFiles : OpenFileRange;
begin
GetNumberOpenFiles := fileList.count;
end; (* end of GetNumberOpenFiles routine *)
begin
New(fileList.head); (* create an empty cell .. easier to use *)
fileList.count := 0; (* set in-use count *)
fileList.head^.fName := ''; (* this line not really required *)
fileList.head^.prev := NIL; (* neither is this one *)
fileList.head^.next := NIL;
SetMaxOpenFiles(1); (* initially, only one open file at a time *)
New(reservedFPtr); (* reserve heap space for at least one entry in list *)
end. (* end of FileBuff unit *)